* functions to calculate
[pyion.git] / ion / __init__.py
blob9ae30239373be0129bd4a8bcd42968ed00825d22
1 """ ion toplevel module
3 ion includes general routines for common manipulations I use
5 Most modules are entirely my own work.
7 * maths (randomization, compression)
8 * i/o
9 * data (efficient/easy representations of simple, large scale types,
10 such as taglists)
12 Some modules have an additional related module -- eg ``n`` -> ``xn``.
13 ``x`` modules contain experimental code; API MAY CHANGE AT ANY TIME.
15 """
17 class LengthMismatch (ValueError):
18 pass
20 def seqorsingle (value, datatype):
21 """Return a sequence of 'scalar's from a scalar or sequence of scalars.
23 Parameters
24 ----------
25 v : sequence or scalar
26 The distinction is muddied by things like strings, which are
27 technically sequences, but more often treated as scalars.
29 datatype : if ``type (v)`` matches this type, it is considered a scalar.
30 can be a sequence, eg (int, float)
32 Returns
33 -------
34 seq : sequence (or unmatched scalar)
37 XXX could be apropos to numpy.alen / numpy.asarray
38 """
39 vtype = type (value)
40 try:
41 _ = datatype.__iter__
42 for type in datatype:
43 if vtype == type:
44 return (value,)
45 return value
46 except AttributeError:
47 if datatype == vtype:
48 return (value,)
49 return value
51 def limititer (iter, num = 1):
52 """Iterates through the first of the items in an iterable.
54 Parameters
55 ----------
56 iter : iterable
57 Typically an infinite iterable without slicability
58 num : integer
59 the first ``num`` entries of the iterable are iterated
60 through before iteration stops.
61 """
62 assert num > 0
63 while num:
64 yield iter.next()
65 num -= 1
67 # XXX rename -> squeeze_split
68 def squeezeSplit (src, sep):
69 """Return src splitted by sep and squeezed (removing ''s)"""
70 splitted = src.split(sep)
71 while '' in splitted:
72 splitted.remove ('')
73 return splitted
75 def bin (value):
76 """Return the binary representation of the input number, MSB-first.
78 Parameters
79 ----------
80 value : int or long
81 Positive number to calculate the representation of
83 Returns
84 -------
85 binstr : string
86 A string with one character per bit in ``value``.
87 len (bitstr) == min_nbits (value)
89 Examples
90 --------
91 >>> bin (100)
92 '1100100'
94 >>> bin (0xffffffff)
95 '11111111111111111111111111111111'
97 Notes
98 -------
99 * Uses ``numpy.binary_repr`` if available (~68x speedup).
100 * You should use ``binary_repr`` directly if you need to represent
101 negative numbers.
102 * Deprecated, will be obsolete in Python 3 vs the builtin ``bin()``
104 try:
105 import numpy
106 return numpy.binary_repr (value)
107 except ImportError:
108 t = []
109 i = 1
110 while value > 0:
111 t.append (chr (value & 1 + 48))
112 value >>= 1
113 return ''.join(t)
115 def piz (v, n):
116 """Split a series
117 a, b, c, d, a, b, c, d
119 a, a | b, b | c, c | d, d
121 useful for things such as coordinates:
122 def foo(*coords):
123 xc, yc = piz (coords, 2)
124 # xc, yc are now matching lists of x and y coords
126 Where passing them around as 2-tuples would be woefully inefficient,
127 but working with them needs them individualized.
131 perhaps could be replaced with tuple subclass
132 Still, this is useful for other things
133 Like separating out RGB channels
136 if (len (v) % n > 0):
137 raise IndexError("piz() input sequence length doesn't match\
138 number of fields")
139 l = []
140 i = 0
141 while (i < n):
142 l.append(v[i::n])
143 i += 1
144 return tuple (l)
146 def read_everything (filename, open = open):
147 """Return a string containing the entirety of the file contents."""
148 f = open (filename)
149 rval = f.read()
150 f.close()
151 return rval
153 def read_everyline (filename, open = open):
154 """Return a list containing every line in file."""
155 f = open (filename)
156 rval = f.readlines()
157 f.close()
158 return rval
160 def cycleiter (iter, startoffset, step = 1):
161 """infinite cycling through rotations of a sequence.
163 Parameters
164 ----------
165 iter : sequence or iterable
166 if ``iter`` doesn't have __len__ attribute,
167 it must iterate over the same number of items each time.
168 startoffset : integer
169 step : integer
170 added to ``offset`` each iteration
172 Examples
173 --------
175 >>> list (limititer (cycle ([0,1,2,3], 1, 1), 5))
176 [1, 2, 3, 0], [2, 3, 0, 1], [3, 0, 1, 2], [0, 1, 2, 3]
178 try:
179 nitems = len (iter)
180 except AttributeError:
181 nitems = len (list (iter))
182 iter = iter.__iter__ ()
183 offset = startoffset % nitems
184 output = [None] * nitems
185 while 1:
186 output [:nitems] = foo
187 # XXX complete this
189 # XXX turn this into an iterator with (seq, step, nsteps) parameters.
190 def cycle (v, n):
191 """ cycle v by n steps. 01234 +1 -> 40123; -1 -> 12340"""
192 n = n % len(v)
193 if n == 0:
194 return
195 try:
196 import numpy
197 if issubclass(v.__class__, numpy.ndarray):
198 return numpy.append (v[-n:], v[:-n])
199 else:
200 try:
201 return v[-n:] + v[:-n]
202 except:
203 return cycleiter (v, n)
204 except ImportError:
205 try:
206 return v[-n:] + v[:-n]
207 except:
208 return cycleiter (v, n)
210 def min_nbits (num):
211 """Calculates the number of bits needed to store an integer or long
213 Parameters
214 ----------
215 num : positive integer
217 Examples
218 --------
219 >>> min_nbits ( 255)
222 >>> min_nbits ( 256)
227 return round (notional_nbits (num))
228 # v = 256
229 # b = 8
231 # bytes
232 # while v < n:
233 # v <<= 8
234 # b += 8
236 #bits
237 # v >>= 7
238 # b -= 7
239 # n += 1
241 def notional_nbits (num):
242 """Calculate the notional number of bits needed to store an integer value.
244 Parameters
245 ----------
246 num : positive integer
248 Returns
249 ----------
250 nbits : float
251 A measure of bits per sized variable,
252 suitable for calculating interface efficiency.
254 Examples
255 --------
256 >>> notional_nbits (4)
257 2.3219280948873622
259 >>> notional_nbits (3)
263 from math import log
264 return log (num + 1, 2)
266 def setattrs (object, **kwargs):
267 """Sets attributes on an object from keyword args.
269 Parameters
270 ----------
271 object : instance
272 An object supporting the specified attributes.
273 If an object has a __dict__ attribute
274 (ie. the class is not limited via __slots__ or implemented in C)
275 then any attribute may be set on it.
276 kwargs : attribute=value pairs, optional
277 for each attribute = value pair, set ``object.attribute = value``.
279 Attribute names should be only valid Python symbol names.
280 However, when expanding a dictionary into kwargs like::
282 setattrs (obj, **{'spacy attribute': 1})
284 it is possible to assign attributes that are only accessible with
285 ``obj.__dict__['attr']`` or ``getattr (obj, 'attr')``.
286 This situation can only occur when attributes of ``object`` are freeform
287 (ie. it has a __dict__ attribute.)
289 Examples
290 --------
291 >>> import numpy as np
292 >>> c = np.arange (16)
293 >>> setattrs (c,
294 ... shape = (4,4),
295 ... dtype = 'f4')
296 >>> c.shape, c.dtype
297 ((4, 4), dtype('float32'))
299 for key, value in kwargs.items():
300 setattr (object, key, value)
303 # note - the following line confuses IPython.
304 # it may be inappropriate behaviour for the top level of a package
305 #__all__ = ('tupled', )