fabio 0.1.1__zip
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- Library/Python/2.7/site-packages/fabio/GEimage.py +334 -0
- Library/Python/2.7/site-packages/fabio/GEimage.pyc +0 -0
- Library/Python/2.7/site-packages/fabio/GEimage_old.py +501 -0
- Library/Python/2.7/site-packages/fabio/GEimage_old.pyc +0 -0
- Library/Python/2.7/site-packages/fabio/HiPiCimage.py +106 -0
- Library/Python/2.7/site-packages/fabio/HiPiCimage.pyc +0 -0
- Library/Python/2.7/site-packages/fabio/OXDimage.py +442 -0
- Library/Python/2.7/site-packages/fabio/OXDimage.pyc +0 -0
- Library/Python/2.7/site-packages/fabio/TiffIO.py +1197 -0
- Library/Python/2.7/site-packages/fabio/TiffIO.pyc +0 -0
- Library/Python/2.7/site-packages/fabio/__init__.py +10 -0
- Library/Python/2.7/site-packages/fabio/__init__.pyc +0 -0
- Library/Python/2.7/site-packages/fabio/adscimage.py +137 -0
- Library/Python/2.7/site-packages/fabio/adscimage.pyc +0 -0
- Library/Python/2.7/site-packages/fabio/binaryimage.py +87 -0
- Library/Python/2.7/site-packages/fabio/binaryimage.pyc +0 -0
- Library/Python/2.7/site-packages/fabio/bruker100image.py +96 -0
- Library/Python/2.7/site-packages/fabio/bruker100image.pyc +0 -0
- Library/Python/2.7/site-packages/fabio/brukerimage.py +195 -0
- Library/Python/2.7/site-packages/fabio/brukerimage.pyc +0 -0
- Library/Python/2.7/site-packages/fabio/byte_offset.so +0 -0
- Library/Python/2.7/site-packages/fabio/cbfimage.py +758 -0
- Library/Python/2.7/site-packages/fabio/cbfimage.pyc +0 -0
- Library/Python/2.7/site-packages/fabio/cf_io.so +0 -0
- Library/Python/2.7/site-packages/fabio/compression.py +388 -0
- Library/Python/2.7/site-packages/fabio/compression.pyc +0 -0
- Library/Python/2.7/site-packages/fabio/converters.py +54 -0
- Library/Python/2.7/site-packages/fabio/converters.pyc +0 -0
- Library/Python/2.7/site-packages/fabio/datIO.py +60 -0
- Library/Python/2.7/site-packages/fabio/datIO.pyc +0 -0
- Library/Python/2.7/site-packages/fabio/dm3image.py +219 -0
- Library/Python/2.7/site-packages/fabio/dm3image.pyc +0 -0
- Library/Python/2.7/site-packages/fabio/edfimage.py +924 -0
- Library/Python/2.7/site-packages/fabio/edfimage.pyc +0 -0
- Library/Python/2.7/site-packages/fabio/fabioimage.py +556 -0
- Library/Python/2.7/site-packages/fabio/fabioimage.pyc +0 -0
- Library/Python/2.7/site-packages/fabio/fabioutils.py +491 -0
- Library/Python/2.7/site-packages/fabio/fabioutils.pyc +0 -0
- Library/Python/2.7/site-packages/fabio/file_series.py +313 -0
- Library/Python/2.7/site-packages/fabio/file_series.pyc +0 -0
- Library/Python/2.7/site-packages/fabio/fit2dmaskimage.py +94 -0
- Library/Python/2.7/site-packages/fabio/fit2dmaskimage.pyc +0 -0
- Library/Python/2.7/site-packages/fabio/fit2dspreadsheetimage.py +85 -0
- Library/Python/2.7/site-packages/fabio/fit2dspreadsheetimage.pyc +0 -0
- Library/Python/2.7/site-packages/fabio/kcdimage.py +131 -0
- Library/Python/2.7/site-packages/fabio/kcdimage.pyc +0 -0
- Library/Python/2.7/site-packages/fabio/mar345_IO.so +0 -0
- Library/Python/2.7/site-packages/fabio/mar345image.py +320 -0
- Library/Python/2.7/site-packages/fabio/mar345image.pyc +0 -0
- Library/Python/2.7/site-packages/fabio/marccdimage.py +309 -0
- Library/Python/2.7/site-packages/fabio/marccdimage.pyc +0 -0
- Library/Python/2.7/site-packages/fabio/openimage.py +162 -0
- Library/Python/2.7/site-packages/fabio/openimage.pyc +0 -0
- Library/Python/2.7/site-packages/fabio/pilatusimage.py +81 -0
- Library/Python/2.7/site-packages/fabio/pilatusimage.pyc +0 -0
- Library/Python/2.7/site-packages/fabio/pnmimage.py +165 -0
- Library/Python/2.7/site-packages/fabio/pnmimage.pyc +0 -0
- Library/Python/2.7/site-packages/fabio/readbytestream.py +86 -0
- Library/Python/2.7/site-packages/fabio/readbytestream.pyc +0 -0
- Library/Python/2.7/site-packages/fabio/tifimage.py +283 -0
- Library/Python/2.7/site-packages/fabio/tifimage.pyc +0 -0
- Library/Python/2.7/site-packages/fabio/xsdimage.py +134 -0
- Library/Python/2.7/site-packages/fabio/xsdimage.pyc +0 -0
- Library/Python/2.7/site-packages/fabio-0.1.1-py2.7.egg-info/PKG-INFO +11 -0
- Library/Python/2.7/site-packages/fabio-0.1.1-py2.7.egg-info/SOURCES.txt +114 -0
- Library/Python/2.7/site-packages/fabio-0.1.1-py2.7.egg-info/dependency_links.txt +1 -0
- Library/Python/2.7/site-packages/fabio-0.1.1-py2.7.egg-info/top_level.txt +4 -0
|
Binary file
|
|
@@ -0,0 +1,556 @@
|
|
|
1
|
+
#!/usr/bin/env python
|
|
2
|
+
|
|
3
|
+
"""
|
|
4
|
+
|
|
5
|
+
Authors: Henning O. Sorensen & Erik Knudsen
|
|
6
|
+
Center for Fundamental Research: Metal Structures in Four Dimensions
|
|
7
|
+
Risoe National Laboratory
|
|
8
|
+
Frederiksborgvej 399
|
|
9
|
+
DK-4000 Roskilde
|
|
10
|
+
email:erik.knudsen@risoe.dk
|
|
11
|
+
|
|
12
|
+
and Jon Wright, Jerome Kieffer: ESRF
|
|
13
|
+
|
|
14
|
+
"""
|
|
15
|
+
from __future__ import with_statement
|
|
16
|
+
import os, types, logging, sys, tempfile
|
|
17
|
+
logger = logging.getLogger("fabioimage")
|
|
18
|
+
import numpy
|
|
19
|
+
try:
|
|
20
|
+
import Image
|
|
21
|
+
except ImportError:
|
|
22
|
+
logger.warning("PIL is not installed ... trying to do without")
|
|
23
|
+
Image = None
|
|
24
|
+
import fabioutils, converters
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
class fabioimage(object):
|
|
28
|
+
"""
|
|
29
|
+
A common object for images in fable
|
|
30
|
+
Contains a numpy array (.data) and dict of meta data (.header)
|
|
31
|
+
"""
|
|
32
|
+
|
|
33
|
+
_need_a_seek_to_read = False
|
|
34
|
+
_need_a_real_file = False
|
|
35
|
+
|
|
36
|
+
def __init__(self, data=None , header=None):
|
|
37
|
+
"""
|
|
38
|
+
Set up initial values
|
|
39
|
+
"""
|
|
40
|
+
self._classname = None
|
|
41
|
+
if type(data) in types.StringTypes:
|
|
42
|
+
raise Exception("fabioimage.__init__ bad argument - " + \
|
|
43
|
+
"data should be numpy array")
|
|
44
|
+
self.data = self.checkData(data)
|
|
45
|
+
self.pilimage = None
|
|
46
|
+
if header is None:
|
|
47
|
+
self.header = {}
|
|
48
|
+
else:
|
|
49
|
+
self.header = self.checkHeader(header)
|
|
50
|
+
self.header_keys = self.header.keys() # holds key ordering
|
|
51
|
+
if self.data is not None:
|
|
52
|
+
self.dim2, self.dim1 = self.data.shape
|
|
53
|
+
else:
|
|
54
|
+
self.dim1 = self.dim2 = 0
|
|
55
|
+
self.bytecode = None # numpy typecode
|
|
56
|
+
self.bpp = 2 # bytes per pixel
|
|
57
|
+
# cache for image statistics
|
|
58
|
+
self.mean = self.maxval = self.stddev = self.minval = None
|
|
59
|
+
# Cache roi
|
|
60
|
+
self.roi = None
|
|
61
|
+
self.area_sum = None
|
|
62
|
+
self.slice = None
|
|
63
|
+
# New for multiframe files
|
|
64
|
+
self.nframes = 1
|
|
65
|
+
self.currentframe = 0
|
|
66
|
+
self.filename = None
|
|
67
|
+
self.filenumber = None
|
|
68
|
+
|
|
69
|
+
@staticmethod
|
|
70
|
+
def checkHeader(header=None):
|
|
71
|
+
"""
|
|
72
|
+
Empty for fabioimage but may be populated by others classes
|
|
73
|
+
"""
|
|
74
|
+
if header is None:
|
|
75
|
+
return {}
|
|
76
|
+
else:
|
|
77
|
+
return header
|
|
78
|
+
|
|
79
|
+
@staticmethod
|
|
80
|
+
def checkData(data=None):
|
|
81
|
+
"""
|
|
82
|
+
Empty for fabioimage but may be populated by others classes, especially for format accepting only integers
|
|
83
|
+
"""
|
|
84
|
+
return data
|
|
85
|
+
|
|
86
|
+
def getclassname(self):
|
|
87
|
+
"""
|
|
88
|
+
Retrieves the name of the class
|
|
89
|
+
@return: the name of the class
|
|
90
|
+
"""
|
|
91
|
+
if self._classname is None:
|
|
92
|
+
self._classname = str(self.__class__).replace("<class '", "").replace("'>", "").split(".")[-1]
|
|
93
|
+
return self._classname
|
|
94
|
+
classname = property(getclassname)
|
|
95
|
+
|
|
96
|
+
def getframe(self, num):
|
|
97
|
+
""" returns the file numbered 'num' in the series as a fabioimage """
|
|
98
|
+
if self.nframes == 1:
|
|
99
|
+
# single image per file
|
|
100
|
+
import openimage
|
|
101
|
+
return openimage.openimage(
|
|
102
|
+
fabioutils.jump_filename(self.filename, num))
|
|
103
|
+
raise Exception("getframe out of range")
|
|
104
|
+
|
|
105
|
+
def previous(self):
|
|
106
|
+
""" returns the previous file in the series as a fabioimage """
|
|
107
|
+
import openimage
|
|
108
|
+
return openimage.openimage(
|
|
109
|
+
fabioutils.previous_filename(self.filename))
|
|
110
|
+
|
|
111
|
+
def next(self):
|
|
112
|
+
""" returns the next file in the series as a fabioimage """
|
|
113
|
+
import openimage
|
|
114
|
+
return openimage.openimage(
|
|
115
|
+
fabioutils.next_filename(self.filename))
|
|
116
|
+
|
|
117
|
+
def toPIL16(self, filename=None):
|
|
118
|
+
"""
|
|
119
|
+
Convert to Python Imaging Library 16 bit greyscale image
|
|
120
|
+
|
|
121
|
+
FIXME - this should be handled by the libraries now
|
|
122
|
+
"""
|
|
123
|
+
if not Image:
|
|
124
|
+
raise RuntimeError("PIL is not installed !!! ")
|
|
125
|
+
if filename:
|
|
126
|
+
self.read(filename)
|
|
127
|
+
if self.pilimage is not None:
|
|
128
|
+
return self.pilimage
|
|
129
|
+
# mode map
|
|
130
|
+
size = self.data.shape[:2][::-1]
|
|
131
|
+
typmap = {
|
|
132
|
+
'float32' : "F" ,
|
|
133
|
+
'int32' : "F;32S" ,
|
|
134
|
+
'uint32' : "F;32" ,
|
|
135
|
+
'int16' : "F;16S" ,
|
|
136
|
+
'uint16' : "F;16" ,
|
|
137
|
+
'int8' : "F;8S" ,
|
|
138
|
+
'uint8' : "F;8" }
|
|
139
|
+
if typmap.has_key(self.data.dtype.name):
|
|
140
|
+
mode2 = typmap[ self.data.dtype.name ]
|
|
141
|
+
mode1 = mode2[0]
|
|
142
|
+
else:
|
|
143
|
+
raise Exception("Unknown numpy type " + str(self.data.dtype.type))
|
|
144
|
+
#
|
|
145
|
+
# hack for byteswapping for PIL in MacOS
|
|
146
|
+
testval = numpy.array((1, 0), numpy.uint8).view(numpy.uint16)[0]
|
|
147
|
+
if testval == 1:
|
|
148
|
+
dats = self.data.tostring()
|
|
149
|
+
elif testval == 256:
|
|
150
|
+
dats = self.data.byteswap().tostring()
|
|
151
|
+
else:
|
|
152
|
+
raise Exception("Endian unknown in fabioimage.toPIL16")
|
|
153
|
+
|
|
154
|
+
self.pilimage = Image.frombuffer(mode1,
|
|
155
|
+
size,
|
|
156
|
+
dats,
|
|
157
|
+
"raw",
|
|
158
|
+
mode2,
|
|
159
|
+
0,
|
|
160
|
+
1)
|
|
161
|
+
|
|
162
|
+
return self.pilimage
|
|
163
|
+
|
|
164
|
+
def getheader(self):
|
|
165
|
+
""" returns self.header """
|
|
166
|
+
return self.header
|
|
167
|
+
|
|
168
|
+
def getmax(self):
|
|
169
|
+
""" Find max value in self.data, caching for the future """
|
|
170
|
+
if self.maxval is None:
|
|
171
|
+
self.maxval = self.data.max()
|
|
172
|
+
return self.maxval
|
|
173
|
+
|
|
174
|
+
def getmin(self):
|
|
175
|
+
""" Find min value in self.data, caching for the future """
|
|
176
|
+
if self.minval is None:
|
|
177
|
+
self.minval = self.data.min()
|
|
178
|
+
return self.minval
|
|
179
|
+
|
|
180
|
+
def make_slice(self, coords):
|
|
181
|
+
"""
|
|
182
|
+
Convert a len(4) set of coords into a len(2)
|
|
183
|
+
tuple (pair) of slice objects
|
|
184
|
+
the latter are immutable, meaning the roi can be cached
|
|
185
|
+
"""
|
|
186
|
+
assert len(coords) == 4
|
|
187
|
+
if len(coords) == 4:
|
|
188
|
+
# fabian edfimage preference
|
|
189
|
+
if coords[0] > coords[2]:
|
|
190
|
+
coords[0:3:2] = [coords[2], coords[0]]
|
|
191
|
+
if coords[1] > coords[3]:
|
|
192
|
+
coords[1:4:2] = [coords[3], coords[1]]
|
|
193
|
+
#in fabian: normally coordinates are given as (x,y) whereas
|
|
194
|
+
# a matrix is given as row,col
|
|
195
|
+
# also the (for whichever reason) the image is flipped upside
|
|
196
|
+
# down wrt to the matrix hence these tranformations
|
|
197
|
+
fixme = (self.dim2 - coords[3] - 1,
|
|
198
|
+
coords[0] ,
|
|
199
|
+
self.dim2 - coords[1] - 1,
|
|
200
|
+
coords[2])
|
|
201
|
+
return (slice(int(fixme[0]), int(fixme[2]) + 1) ,
|
|
202
|
+
slice(int(fixme[1]), int(fixme[3]) + 1))
|
|
203
|
+
|
|
204
|
+
|
|
205
|
+
def integrate_area(self, coords):
|
|
206
|
+
"""
|
|
207
|
+
Sums up a region of interest
|
|
208
|
+
if len(coords) == 4 -> convert coords to slices
|
|
209
|
+
if len(coords) == 2 -> use as slices
|
|
210
|
+
floor -> ? removed as unused in the function.
|
|
211
|
+
"""
|
|
212
|
+
if self.data == None:
|
|
213
|
+
# This should return NAN, not zero ?
|
|
214
|
+
return 0
|
|
215
|
+
if len(coords) == 4:
|
|
216
|
+
sli = self.make_slice(coords)
|
|
217
|
+
elif len(coords) == 2 and isinstance(coords[0], slice) and \
|
|
218
|
+
isinstance(coords[1], slice):
|
|
219
|
+
sli = coords
|
|
220
|
+
|
|
221
|
+
if sli == self.slice and self.area_sum is not None:
|
|
222
|
+
pass
|
|
223
|
+
elif sli == self.slice and self.roi is not None:
|
|
224
|
+
self.area_sum = self.roi.sum(dtype=numpy.float)
|
|
225
|
+
else:
|
|
226
|
+
self.slice = sli
|
|
227
|
+
self.roi = self.data[ self.slice ]
|
|
228
|
+
self.area_sum = self.roi.sum(dtype=numpy.float)
|
|
229
|
+
return self.area_sum
|
|
230
|
+
|
|
231
|
+
def getmean(self):
|
|
232
|
+
""" return the mean """
|
|
233
|
+
if self.mean is None:
|
|
234
|
+
self.mean = self.data.mean(dtype=numpy.double)
|
|
235
|
+
return self.mean
|
|
236
|
+
|
|
237
|
+
def getstddev(self):
|
|
238
|
+
""" return the standard deviation """
|
|
239
|
+
if self.stddev == None:
|
|
240
|
+
self.stddev = self.data.std(dtype=numpy.double)
|
|
241
|
+
return self.stddev
|
|
242
|
+
|
|
243
|
+
def add(self, other):
|
|
244
|
+
"""
|
|
245
|
+
Add another Image - warning, does not clip to 16 bit images by default
|
|
246
|
+
"""
|
|
247
|
+
if not hasattr(other, 'data'):
|
|
248
|
+
logger.warning('edfimage.add() called with something that ' + \
|
|
249
|
+
'does not have a data field')
|
|
250
|
+
assert self.data.shape == other.data.shape , \
|
|
251
|
+
'incompatible images - Do they have the same size?'
|
|
252
|
+
self.data = self.data + other.data
|
|
253
|
+
self.resetvals()
|
|
254
|
+
|
|
255
|
+
|
|
256
|
+
def resetvals(self):
|
|
257
|
+
""" Reset cache - call on changing data """
|
|
258
|
+
self.mean = self.stddev = self.maxval = self.minval = None
|
|
259
|
+
self.roi = self.slice = self.area_sum = None
|
|
260
|
+
|
|
261
|
+
def rebin(self, x_rebin_fact, y_rebin_fact, keep_I=True):
|
|
262
|
+
"""
|
|
263
|
+
Rebin the data and adjust dims
|
|
264
|
+
@param x_rebin_fact: x binning factor
|
|
265
|
+
@param y_rebin_fact: y binning factor
|
|
266
|
+
@param keep_I: shall the signal increase ?
|
|
267
|
+
@type x_rebin_fact: int
|
|
268
|
+
@type y_rebin_fact: int
|
|
269
|
+
@type keep_I: boolean
|
|
270
|
+
|
|
271
|
+
|
|
272
|
+
"""
|
|
273
|
+
if self.data == None:
|
|
274
|
+
raise Exception('Please read in the file you wish to rebin first')
|
|
275
|
+
|
|
276
|
+
if (self.dim1 % x_rebin_fact != 0) or (self.dim2 % y_rebin_fact != 0):
|
|
277
|
+
raise RuntimeError('image size is not divisible by rebin factor - ' + \
|
|
278
|
+
'skipping rebin')
|
|
279
|
+
else:
|
|
280
|
+
dataIn = self.data.astype("float64")
|
|
281
|
+
shapeIn = self.data.shape
|
|
282
|
+
shapeOut = (shapeIn[0] / y_rebin_fact, shapeIn[1] / x_rebin_fact)
|
|
283
|
+
binsize = y_rebin_fact * x_rebin_fact
|
|
284
|
+
if binsize < 50: #method faster for small binning (4x4)
|
|
285
|
+
out = numpy.zeros(shapeOut, dtype="float64")
|
|
286
|
+
for j in range(x_rebin_fact):
|
|
287
|
+
for i in range(y_rebin_fact):
|
|
288
|
+
out += dataIn[i::y_rebin_fact, j::x_rebin_fact]
|
|
289
|
+
else: #method faster for large binning (8x8)
|
|
290
|
+
temp = self.data.astype("float64")
|
|
291
|
+
temp.shape = (shapeOut[0], y_rebin_fact, shapeOut[1], x_rebin_fact)
|
|
292
|
+
out = temp.sum(axis=3).sum(axis=1)
|
|
293
|
+
self.resetvals()
|
|
294
|
+
if keep_I:
|
|
295
|
+
self.data = (out / (y_rebin_fact * x_rebin_fact)).astype(self.data.dtype)
|
|
296
|
+
else:
|
|
297
|
+
self.data = out.astype(self.data.dtype)
|
|
298
|
+
|
|
299
|
+
self.dim1 = self.dim1 / x_rebin_fact
|
|
300
|
+
self.dim2 = self.dim2 / y_rebin_fact
|
|
301
|
+
|
|
302
|
+
#update header
|
|
303
|
+
self.update_header()
|
|
304
|
+
|
|
305
|
+
def write(self, fname):
|
|
306
|
+
"""
|
|
307
|
+
To be overwritten - write the file
|
|
308
|
+
"""
|
|
309
|
+
raise Exception("Class has not implemented readheader method yet")
|
|
310
|
+
|
|
311
|
+
def save(self, fname):
|
|
312
|
+
'wrapper for write'
|
|
313
|
+
self.write(fname)
|
|
314
|
+
|
|
315
|
+
def readheader(self, filename):
|
|
316
|
+
"""
|
|
317
|
+
Call the _readheader function...
|
|
318
|
+
"""
|
|
319
|
+
# Override the needs asserting that all headers can be read via python modules
|
|
320
|
+
save_state = self._need_a_real_file , self._need_a_seek_to_read
|
|
321
|
+
self._need_a_real_file , self._need_a_seek_to_read = False, False
|
|
322
|
+
fin = self._open(filename)
|
|
323
|
+
self._readheader(fin)
|
|
324
|
+
fin.close()
|
|
325
|
+
self._need_a_real_file , self._need_a_seek_to_read = save_state
|
|
326
|
+
|
|
327
|
+
def _readheader(self, fik_obj):
|
|
328
|
+
"""
|
|
329
|
+
Must be overridden in classes
|
|
330
|
+
"""
|
|
331
|
+
raise Exception("Class has not implemented _readheader method yet")
|
|
332
|
+
|
|
333
|
+
def update_header(self , **kwds):
|
|
334
|
+
"""
|
|
335
|
+
update the header entries
|
|
336
|
+
by default pass in a dict of key, values.
|
|
337
|
+
"""
|
|
338
|
+
self.header.update(kwds)
|
|
339
|
+
|
|
340
|
+
def read(self, filename, frame=None):
|
|
341
|
+
"""
|
|
342
|
+
To be overridden - fill in self.header and self.data
|
|
343
|
+
"""
|
|
344
|
+
raise Exception("Class has not implemented read method yet")
|
|
345
|
+
# return self
|
|
346
|
+
|
|
347
|
+
def load(self, *arg, **kwarg):
|
|
348
|
+
"Wrapper for read"
|
|
349
|
+
return self.read(*arg, **kwarg)
|
|
350
|
+
|
|
351
|
+
def readROI(self, filename, frame=None, coords=None):
|
|
352
|
+
"""
|
|
353
|
+
Method reading Region of Interest.
|
|
354
|
+
This implementation is the trivial one, just doing read and crop
|
|
355
|
+
"""
|
|
356
|
+
self.read(filename, frame)
|
|
357
|
+
if len(coords) == 4:
|
|
358
|
+
self.slice = self.make_slice(coords)
|
|
359
|
+
elif len(coords) == 2 and isinstance(coords[0], slice) and \
|
|
360
|
+
isinstance(coords[1], slice):
|
|
361
|
+
self.slice = coords
|
|
362
|
+
else:
|
|
363
|
+
logger.warning('readROI: Unable to understand Region Of Interest: got %s', coords)
|
|
364
|
+
self.roi = self.data[ self.slice ]
|
|
365
|
+
return self.roi
|
|
366
|
+
|
|
367
|
+
|
|
368
|
+
def _open(self, fname, mode="rb"):
|
|
369
|
+
"""
|
|
370
|
+
Try to handle compressed files, streams, shared memory etc
|
|
371
|
+
Return an object which can be used for "read" and "write"
|
|
372
|
+
... FIXME - what about seek ?
|
|
373
|
+
"""
|
|
374
|
+
fileObject = None
|
|
375
|
+
self.filename = fname
|
|
376
|
+
self.filenumber = fabioutils.extract_filenumber(fname)
|
|
377
|
+
if hasattr(fname, "read") and hasattr(fname, "write"):
|
|
378
|
+
# It is already something we can use
|
|
379
|
+
return fname
|
|
380
|
+
if isinstance(fname, (str, unicode)):
|
|
381
|
+
self.header["filename"] = fname
|
|
382
|
+
if os.path.splitext(fname)[1] == ".gz":
|
|
383
|
+
fileObject = self._compressed_stream(fname,
|
|
384
|
+
fabioutils.COMPRESSORS['.gz'],
|
|
385
|
+
fabioutils.GzipFile,
|
|
386
|
+
mode)
|
|
387
|
+
elif os.path.splitext(fname)[1] == '.bz2':
|
|
388
|
+
fileObject = self._compressed_stream(fname,
|
|
389
|
+
fabioutils.COMPRESSORS['.bz2'],
|
|
390
|
+
fabioutils.BZ2File,
|
|
391
|
+
mode)
|
|
392
|
+
#
|
|
393
|
+
# Here we return the file even though it may be bzipped or gzipped
|
|
394
|
+
# but named incorrectly...
|
|
395
|
+
#
|
|
396
|
+
# FIXME - should we fix that or complain about the daft naming?
|
|
397
|
+
else:
|
|
398
|
+
fileObject = fabioutils.File(fname, mode)
|
|
399
|
+
if "name" not in dir(fileObject):
|
|
400
|
+
fileObject.name = fname
|
|
401
|
+
|
|
402
|
+
return fileObject
|
|
403
|
+
|
|
404
|
+
def _compressed_stream(self,
|
|
405
|
+
fname,
|
|
406
|
+
system_uncompress,
|
|
407
|
+
python_uncompress,
|
|
408
|
+
mode='rb'):
|
|
409
|
+
"""
|
|
410
|
+
Try to transparently handle gzip / bzip without always getting python
|
|
411
|
+
performance
|
|
412
|
+
"""
|
|
413
|
+
# assert that python modules are always OK based on performance benchmark
|
|
414
|
+
# Try to fix the way we are using them?
|
|
415
|
+
fobj = None
|
|
416
|
+
if self._need_a_real_file and mode[0] == "r":
|
|
417
|
+
fo = python_uncompress(fname, mode)
|
|
418
|
+
# fobj = os.tmpfile()
|
|
419
|
+
#problem when not administrator under certain flavors of windows
|
|
420
|
+
tmpfd, tmpfn = tempfile.mkstemp()
|
|
421
|
+
os.close(tmpfd)
|
|
422
|
+
fobj = fabioutils.File(tmpfn, "w+b")
|
|
423
|
+
fobj.write(fo.read())
|
|
424
|
+
fo.close()
|
|
425
|
+
fobj.seek(0)
|
|
426
|
+
elif self._need_a_seek_to_read and mode[0] == "r":
|
|
427
|
+
fo = python_uncompress(fname, mode)
|
|
428
|
+
fobj = fabioutils.StringIO(fo.read(), fname, mode)
|
|
429
|
+
else:
|
|
430
|
+
fobj = python_uncompress(fname, mode)
|
|
431
|
+
return fobj
|
|
432
|
+
|
|
433
|
+
def convert(self, dest):
|
|
434
|
+
"""
|
|
435
|
+
Convert a fabioimage object into another fabioimage object (with possible conversions)
|
|
436
|
+
@param dest: destination type "EDF", "edfimage" or the class itself
|
|
437
|
+
"""
|
|
438
|
+
if type(dest) in types.StringTypes:
|
|
439
|
+
dest = dest.lower()
|
|
440
|
+
modules = []
|
|
441
|
+
for val in fabioutils.FILETYPES.values():
|
|
442
|
+
modules += [i + "image" for i in val if i not in modules]
|
|
443
|
+
klass = None
|
|
444
|
+
module = None
|
|
445
|
+
klass_name = None
|
|
446
|
+
for klass_name in modules:
|
|
447
|
+
if klass_name.startswith(dest):
|
|
448
|
+
try:
|
|
449
|
+
module = sys.modules["fabio." + klass_name]
|
|
450
|
+
except KeyError:
|
|
451
|
+
try:
|
|
452
|
+
module = __import__(klass_name)
|
|
453
|
+
except:
|
|
454
|
+
logger.error("Failed to import %s", klass_name)
|
|
455
|
+
else:
|
|
456
|
+
logger.debug("imported %simage", klass_name)
|
|
457
|
+
if module is not None:
|
|
458
|
+
break
|
|
459
|
+
if module is not None:
|
|
460
|
+
if hasattr(module, klass_name):
|
|
461
|
+
klass = getattr(module, klass_name)
|
|
462
|
+
else:
|
|
463
|
+
logger.error("Module %s has no image class" % module)
|
|
464
|
+
elif isinstance(dest, self.__class__):
|
|
465
|
+
klass = dest.__class__
|
|
466
|
+
elif ("__new__" in dir(dest)) and isinstance(dest(), fabioimage):
|
|
467
|
+
klass = dest
|
|
468
|
+
else:
|
|
469
|
+
logger.warning("Unrecognized destination format: %s " % dest)
|
|
470
|
+
return self
|
|
471
|
+
if klass is None:
|
|
472
|
+
logger.warning("Unrecognized destination format: %s " % dest)
|
|
473
|
+
return self
|
|
474
|
+
other = klass() #temporary instance (to be overwritten)
|
|
475
|
+
other = klass(data=converters.convert_data(self.classname, other.classname, self.data),
|
|
476
|
+
header=converters.convert_header(self.classname, other.classname, self.header))
|
|
477
|
+
return other
|
|
478
|
+
|
|
479
|
+
def test():
|
|
480
|
+
"""
|
|
481
|
+
check some basic fabioimage functionality
|
|
482
|
+
"""
|
|
483
|
+
import time
|
|
484
|
+
start = time.time()
|
|
485
|
+
|
|
486
|
+
dat = numpy.ones((1024, 1024), numpy.uint16)
|
|
487
|
+
dat = (dat * 50000).astype(numpy.uint16)
|
|
488
|
+
assert dat.dtype.char == numpy.ones((1), numpy.uint16).dtype.char
|
|
489
|
+
hed = {"Title":"50000 everywhere"}
|
|
490
|
+
obj = fabioimage(dat, hed)
|
|
491
|
+
|
|
492
|
+
assert obj.getmax() == 50000
|
|
493
|
+
assert obj.getmin() == 50000
|
|
494
|
+
assert obj.getmean() == 50000 , obj.getmean()
|
|
495
|
+
assert obj.getstddev() == 0.
|
|
496
|
+
|
|
497
|
+
dat2 = numpy.zeros((1024, 1024), numpy.uint16, savespace=1)
|
|
498
|
+
cord = [ 256, 256, 790, 768 ]
|
|
499
|
+
slic = obj.make_slice(cord)
|
|
500
|
+
dat2[slic] = dat2[slic] + 100
|
|
501
|
+
|
|
502
|
+
obj = fabioimage(dat2, hed)
|
|
503
|
+
|
|
504
|
+
# New object, so...
|
|
505
|
+
assert obj.maxval is None
|
|
506
|
+
assert obj.minval is None
|
|
507
|
+
|
|
508
|
+
assert obj.getmax() == 100, obj.getmax()
|
|
509
|
+
assert obj.getmin() == 0 , obj.getmin()
|
|
510
|
+
npix = (slic[0].stop - slic[0].start) * (slic[1].stop - slic[1].start)
|
|
511
|
+
obj.resetvals()
|
|
512
|
+
area1 = obj.integrate_area(cord)
|
|
513
|
+
obj.resetvals()
|
|
514
|
+
area2 = obj.integrate_area(slic)
|
|
515
|
+
assert area1 == area2
|
|
516
|
+
assert obj.integrate_area(cord) == obj.integrate_area(slic)
|
|
517
|
+
assert obj.integrate_area(cord) == npix * 100, obj.integrate_area(cord)
|
|
518
|
+
|
|
519
|
+
|
|
520
|
+
def clean():
|
|
521
|
+
""" clean up the created testfiles"""
|
|
522
|
+
for name in ["testfile", "testfile.gz", "testfile.bz2"]:
|
|
523
|
+
try:
|
|
524
|
+
os.remove(name)
|
|
525
|
+
except:
|
|
526
|
+
continue
|
|
527
|
+
|
|
528
|
+
|
|
529
|
+
clean()
|
|
530
|
+
import gzip, bz2
|
|
531
|
+
gzip.open("testfile.gz", "wb").write("{ hello }")
|
|
532
|
+
fout = obj._open("testfile.gz")
|
|
533
|
+
readin = fout.read()
|
|
534
|
+
assert readin == "{ hello }", readin + " gzipped file"
|
|
535
|
+
|
|
536
|
+
|
|
537
|
+
bz2.BZ2File("testfilebz", "wb").write("{ hello }")
|
|
538
|
+
fout = obj._open("testfile.bz2")
|
|
539
|
+
readin = fout.read()
|
|
540
|
+
assert readin == "{ hello }", readin + " bzipped file"
|
|
541
|
+
|
|
542
|
+
ftest = open("testfile", "wb")
|
|
543
|
+
ftest.write("{ hello }")
|
|
544
|
+
assert ftest == obj._open(ftest)
|
|
545
|
+
ftest.close()
|
|
546
|
+
fout = obj._open("testfile")
|
|
547
|
+
readin = fout.read()
|
|
548
|
+
assert readin == "{ hello }", readin + "plain file"
|
|
549
|
+
fout.close()
|
|
550
|
+
ftest.close()
|
|
551
|
+
clean()
|
|
552
|
+
|
|
553
|
+
print "Passed in", time.time() - start, "s"
|
|
554
|
+
|
|
555
|
+
if __name__ == '__main__':
|
|
556
|
+
test()
|
|
Binary file
|