1
2 import sys
3 import numpy as npy
4 import pylab as P
5 from scipy.weave import inline, converters, blitz
6 from scipy.testing import measure
7
8
9
10
11 def multi_iter_example():
12
13
14
15
16
17
18
19
20
21
22
23
24 a = npy.ones((4,4), npy.float64)
25
26 dtype2ctype = {
27 npy.dtype(npy.float64): 'double',
28 npy.dtype(npy.float32): 'float',
29 npy.dtype(npy.int32): 'int',
30 npy.dtype(npy.int16): 'short',
31 }
32 dt = dtype2ctype.get(a.dtype)
33
34
35 code = \
36 """
37 %s *p1, *p2;
38 PyObject *itr;
39 itr = PyArray_MultiIterNew(2, a_array, b_array);
40 while(PyArray_MultiIter_NOTDONE(itr)) {
41 p1 = (%s *) PyArray_MultiIter_DATA(itr, 0);
42 p2 = (%s *) PyArray_MultiIter_DATA(itr, 1);
43 *p1 = (*p1) * (*p2);
44 PyArray_MultiIter_NEXT(itr);
45 }
46 """ % (dt, dt, dt)
47
48 b = npy.arange(4, dtype=a.dtype)
49 print '\n A B '
50 print a, b
51
52 b.shape = (1,4)
53 inline(code, ['a', 'b'])
54 print "\ninline version of a*b[None,:],"
55 print a
56 a = npy.ones((4,4), npy.float64)
57 b = npy.arange(4, dtype=a.dtype)
58 b.shape = (4,1)
59 inline(code, ['a', 'b'])
60 print "\ninline version of a*b[:,None],"
61 print a
62
63 def data_casting_test():
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84 nsl, nline, npt = (20,64,64)
85 hdr_dt = npy.dtype('>V28')
86
87 blk_dt1 = npy.dtype(('>i2', nline*npt*2))
88 dat_dt = npy.dtype({'names': ['hdr', 'data'], 'formats': [hdr_dt, blk_dt1]})
89
90 vol = npy.empty((nsl,), dat_dt)
91 t = time_casting(vol[:]['data'])
92 P.plot(100*t/t.max(), 'b--', label='vol=20 contiguous blocks')
93 P.plot(100*t/t.max(), 'bo')
94
95 blk_dt2 = npy.dtype(('>i2', nsl*nline*npt*2))
96 dat_dt = npy.dtype({'names': ['hdr', 'data'], 'formats': [hdr_dt, blk_dt2]})
97
98 vol = npy.empty((1,), dat_dt)
99 t = time_casting(vol[0]['data'])
100 P.plot(100*t/t.max(), 'g--', label='vol=1 contiguous block')
101 P.plot(100*t/t.max(), 'go')
102
103
104 blk_dt3 = npy.dtype(('>i4', nsl*npt*2))
105 dat_dt = npy.dtype({'names': ['hdr', 'data'], 'formats': [hdr_dt, blk_dt3]})
106
107 vols = npy.empty((2*nline,), dat_dt)
108
109 t = time_casting(vols[0::2]['data'])
110 P.plot(100*t/t.max(), 'r--', label='vol=64 discontiguous blocks')
111 P.plot(100*t/t.max(), 'ro')
112 P.xticks([0,1,2], ('strings', 'numpy auto', 'inline'))
113 P.gca().set_xlim((-0.25, 2.25))
114 P.gca().set_ylim((0, 110))
115 P.gca().set_ylabel(r"% of slowest time")
116 P.legend(loc=8)
117 P.title('Casting raw file data to an MR volume')
118 P.show()
119
120
121 def time_casting(int_data):
122 nblk = 1 if len(int_data.shape) < 2 else int_data.shape[0]
123 bias = (npy.random.rand(nblk) + \
124 1j*npy.random.rand(nblk)).astype(npy.complex64)
125 dstr = int_data.tostring()
126 dt = npy.int16 if int_data.dtype.itemsize == 2 else npy.int32
127 fshape = list(int_data.shape)
128 fshape[-1] = fshape[-1]/2
129 float_data = npy.empty(fshape, npy.complex64)
130
131 float_data.shape = (npy.product(fshape),)
132 tstr = measure("float_data[:] = complex_fromstring(dstr, dt)", times=25)
133 float_data.shape = fshape
134 print "to-/from- string: ", tstr, "shape=",float_data.shape
135
136
137 sl = [None, slice(None)] if len(fshape)<2 else [slice(None)]*len(fshape)
138
139 tnpy = measure("""
140 for fline, iline, b in zip(float_data[sl], int_data[sl], bias):
141 cast_to_complex_npy(fline, iline, bias=b)""", times=25)
142 print"numpy automagic: ", tnpy
143
144
145 twv = measure("cast_to_complex(float_data, int_data, bias=bias)",
146 times=25)
147 print"inline casting: ", twv
148 return npy.array([tstr, tnpy, twv], npy.float64)
149
150 def complex_fromstring(data, numtype):
151 if sys.byteorder == "little":
152 return npy.fromstring(
153 npy.fromstring(data,numtype).byteswap().astype(npy.float32).tostring(),
154 npy.complex64)
155 else:
156 return npy.fromstring(
157 npy.fromstring(data,numtype).astype(npy.float32).tostring(),
158 npy.complex64)
159
160 def cast_to_complex(cplx_float, cplx_integer, bias=None):
161 if cplx_integer.dtype.itemsize == 4:
162 replacements = tuple(["l", "long", "SWAPLONG", "l"]*2)
163 else:
164 replacements = tuple(["s", "short", "SWAPSHORT", "s"]*2)
165 if sys.byteorder == "big":
166 replacements[-2] = replacements[-6] = "NOP"
167
168 cast_code = """
169 #define SWAPSHORT(x) ((short) ((x >> 8) | (x << 8)) )
170 #define SWAPLONG(x) ((long) ((x >> 24) | (x << 24) | ((x & 0x00ff0000) >> 8) | ((x & 0x0000ff00) << 8)) )
171 #define NOP(x) x
172
173 unsigned short *s;
174 unsigned long *l;
175 float repart, impart;
176 PyObject *itr;
177 itr = PyArray_IterNew(py_cplx_integer);
178 while(PyArray_ITER_NOTDONE(itr)) {
179
180 // get real part
181 %s = (unsigned %s *) PyArray_ITER_DATA(itr);
182 repart = %s(*%s);
183 PyArray_ITER_NEXT(itr);
184 // get imag part
185 %s = (unsigned %s *) PyArray_ITER_DATA(itr);
186 impart = %s(*%s);
187 PyArray_ITER_NEXT(itr);
188 *(cplx_float++) = std::complex<float>(repart, impart);
189
190 }
191 """ % replacements
192
193 inline(cast_code, ['cplx_float', 'cplx_integer'])
194 if bias is not None:
195 if len(cplx_float.shape) > 1:
196 bsl = [slice(None)]*(len(cplx_float.shape)-1) + [None]
197 else:
198 bsl = slice(None)
199 npy.subtract(cplx_float, bias[bsl], cplx_float)
200
201 def cast_to_complex_npy(cplx_float, cplx_integer, bias=None):
202 cplx_float.real[:] = cplx_integer[0::2]
203 cplx_float.imag[:] = cplx_integer[1::2]
204 if bias is not None:
205 npy.subtract(cplx_float, bias, cplx_float)
206
207 if __name__=="__main__":
208 data_casting_test()
209 multi_iter_example()