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.
Files changed (67) hide show
  1. Library/Python/2.7/site-packages/fabio/GEimage.py +334 -0
  2. Library/Python/2.7/site-packages/fabio/GEimage.pyc +0 -0
  3. Library/Python/2.7/site-packages/fabio/GEimage_old.py +501 -0
  4. Library/Python/2.7/site-packages/fabio/GEimage_old.pyc +0 -0
  5. Library/Python/2.7/site-packages/fabio/HiPiCimage.py +106 -0
  6. Library/Python/2.7/site-packages/fabio/HiPiCimage.pyc +0 -0
  7. Library/Python/2.7/site-packages/fabio/OXDimage.py +442 -0
  8. Library/Python/2.7/site-packages/fabio/OXDimage.pyc +0 -0
  9. Library/Python/2.7/site-packages/fabio/TiffIO.py +1197 -0
  10. Library/Python/2.7/site-packages/fabio/TiffIO.pyc +0 -0
  11. Library/Python/2.7/site-packages/fabio/__init__.py +10 -0
  12. Library/Python/2.7/site-packages/fabio/__init__.pyc +0 -0
  13. Library/Python/2.7/site-packages/fabio/adscimage.py +137 -0
  14. Library/Python/2.7/site-packages/fabio/adscimage.pyc +0 -0
  15. Library/Python/2.7/site-packages/fabio/binaryimage.py +87 -0
  16. Library/Python/2.7/site-packages/fabio/binaryimage.pyc +0 -0
  17. Library/Python/2.7/site-packages/fabio/bruker100image.py +96 -0
  18. Library/Python/2.7/site-packages/fabio/bruker100image.pyc +0 -0
  19. Library/Python/2.7/site-packages/fabio/brukerimage.py +195 -0
  20. Library/Python/2.7/site-packages/fabio/brukerimage.pyc +0 -0
  21. Library/Python/2.7/site-packages/fabio/byte_offset.so +0 -0
  22. Library/Python/2.7/site-packages/fabio/cbfimage.py +758 -0
  23. Library/Python/2.7/site-packages/fabio/cbfimage.pyc +0 -0
  24. Library/Python/2.7/site-packages/fabio/cf_io.so +0 -0
  25. Library/Python/2.7/site-packages/fabio/compression.py +388 -0
  26. Library/Python/2.7/site-packages/fabio/compression.pyc +0 -0
  27. Library/Python/2.7/site-packages/fabio/converters.py +54 -0
  28. Library/Python/2.7/site-packages/fabio/converters.pyc +0 -0
  29. Library/Python/2.7/site-packages/fabio/datIO.py +60 -0
  30. Library/Python/2.7/site-packages/fabio/datIO.pyc +0 -0
  31. Library/Python/2.7/site-packages/fabio/dm3image.py +219 -0
  32. Library/Python/2.7/site-packages/fabio/dm3image.pyc +0 -0
  33. Library/Python/2.7/site-packages/fabio/edfimage.py +924 -0
  34. Library/Python/2.7/site-packages/fabio/edfimage.pyc +0 -0
  35. Library/Python/2.7/site-packages/fabio/fabioimage.py +556 -0
  36. Library/Python/2.7/site-packages/fabio/fabioimage.pyc +0 -0
  37. Library/Python/2.7/site-packages/fabio/fabioutils.py +491 -0
  38. Library/Python/2.7/site-packages/fabio/fabioutils.pyc +0 -0
  39. Library/Python/2.7/site-packages/fabio/file_series.py +313 -0
  40. Library/Python/2.7/site-packages/fabio/file_series.pyc +0 -0
  41. Library/Python/2.7/site-packages/fabio/fit2dmaskimage.py +94 -0
  42. Library/Python/2.7/site-packages/fabio/fit2dmaskimage.pyc +0 -0
  43. Library/Python/2.7/site-packages/fabio/fit2dspreadsheetimage.py +85 -0
  44. Library/Python/2.7/site-packages/fabio/fit2dspreadsheetimage.pyc +0 -0
  45. Library/Python/2.7/site-packages/fabio/kcdimage.py +131 -0
  46. Library/Python/2.7/site-packages/fabio/kcdimage.pyc +0 -0
  47. Library/Python/2.7/site-packages/fabio/mar345_IO.so +0 -0
  48. Library/Python/2.7/site-packages/fabio/mar345image.py +320 -0
  49. Library/Python/2.7/site-packages/fabio/mar345image.pyc +0 -0
  50. Library/Python/2.7/site-packages/fabio/marccdimage.py +309 -0
  51. Library/Python/2.7/site-packages/fabio/marccdimage.pyc +0 -0
  52. Library/Python/2.7/site-packages/fabio/openimage.py +162 -0
  53. Library/Python/2.7/site-packages/fabio/openimage.pyc +0 -0
  54. Library/Python/2.7/site-packages/fabio/pilatusimage.py +81 -0
  55. Library/Python/2.7/site-packages/fabio/pilatusimage.pyc +0 -0
  56. Library/Python/2.7/site-packages/fabio/pnmimage.py +165 -0
  57. Library/Python/2.7/site-packages/fabio/pnmimage.pyc +0 -0
  58. Library/Python/2.7/site-packages/fabio/readbytestream.py +86 -0
  59. Library/Python/2.7/site-packages/fabio/readbytestream.pyc +0 -0
  60. Library/Python/2.7/site-packages/fabio/tifimage.py +283 -0
  61. Library/Python/2.7/site-packages/fabio/tifimage.pyc +0 -0
  62. Library/Python/2.7/site-packages/fabio/xsdimage.py +134 -0
  63. Library/Python/2.7/site-packages/fabio/xsdimage.pyc +0 -0
  64. Library/Python/2.7/site-packages/fabio-0.1.1-py2.7.egg-info/PKG-INFO +11 -0
  65. Library/Python/2.7/site-packages/fabio-0.1.1-py2.7.egg-info/SOURCES.txt +114 -0
  66. Library/Python/2.7/site-packages/fabio-0.1.1-py2.7.egg-info/dependency_links.txt +1 -0
  67. Library/Python/2.7/site-packages/fabio-0.1.1-py2.7.egg-info/top_level.txt +4 -0
@@ -0,0 +1,758 @@
1
+ #!/usr/bin/env python
2
+ # coding: utf8
3
+ """
4
+ Authors: Jérôme Kieffer, ESRF
5
+ email:jerome.kieffer@esrf.fr
6
+
7
+ Cif Binary Files images are 2D images written by the Pilatus detector and others.
8
+ They use a modified (simplified) byte-offset algorithm.
9
+
10
+ CIF is a library for manipulating Crystallographic information files and tries
11
+ to conform to the specification of the IUCR
12
+ """
13
+ __author__ = "Jérôme Kieffer"
14
+ __contact__ = "jerome.kieffer@esrf.eu"
15
+ __license__ = "GPLv3+"
16
+ __copyright__ = "European Synchrotron Radiation Facility, Grenoble, France"
17
+ __version__ = ["Generated by CIF.py: Jan 2005 - April 2012",
18
+ "Written by Jerome Kieffer: Jerome.Kieffer@esrf.eu",
19
+ "On-line data analysis / ISDD ", "ESRF Grenoble (France)"]
20
+
21
+
22
+ import os, logging
23
+ logger = logging.getLogger("cbfimage")
24
+ import numpy
25
+ from fabioimage import fabioimage
26
+ from compression import decByteOffet_numpy, md5sum, compByteOffet_numpy
27
+ #import time
28
+
29
+ DATA_TYPES = { "signed 8-bit integer" : numpy.int8,
30
+ "signed 16-bit integer" : numpy.int16,
31
+ "signed 32-bit integer" : numpy.int32,
32
+ "signed 64-bit integer" : numpy.int64
33
+ }
34
+
35
+ MINIMUM_KEYS = ["X-Binary-Size-Fastest-Dimension",
36
+ 'ByteOrder',
37
+ 'Data type',
38
+ 'X dimension',
39
+ 'Y dimension',
40
+ 'Number of readouts']
41
+
42
+
43
+ STARTER = "\x0c\x1a\x04\xd5"
44
+ PADDING = 512
45
+
46
+ class cbfimage(fabioimage):
47
+ """
48
+ Read the Cif Binary File data format
49
+ """
50
+ def __init__(self, data=None , header=None, fname=None):
51
+ """
52
+ Constructor of the class CIF Binary File reader.
53
+
54
+ @param _strFilename: the name of the file to open
55
+ @type _strFilename: string
56
+ """
57
+ fabioimage.__init__(self, data, header)
58
+ self.cif = CIF()
59
+ if fname is not None: #load the file)
60
+ self.read(fname)
61
+
62
+ @staticmethod
63
+ def checkData(data=None):
64
+ if data is None:
65
+ return None
66
+ elif numpy.issubdtype(data.dtype, int):
67
+ return data
68
+ else:
69
+ return data.astype(int)
70
+
71
+
72
+ def _readheader(self, inStream):
73
+ """
74
+ Read in a header in some CBF format from a string representing binary stuff
75
+
76
+ @param inStream: file containing the Cif Binary part.
77
+ @type inStream: opened file.
78
+ """
79
+ self.cif.loadCIF(inStream, _bKeepComment=True)
80
+
81
+ # backport contents of the CIF data to the headers
82
+ for key in self.cif:
83
+ if key != "_array_data.data":
84
+ self.header_keys.append(key)
85
+ self.header[key] = self.cif[key].strip(" \"\n\r\t")
86
+
87
+ if not "_array_data.data" in self.cif:
88
+ raise Exception("cbfimage: CBF file %s is corrupt, cannot find data block with '_array_data.data' key" % self.fname)
89
+
90
+ inStream2 = self.cif["_array_data.data"]
91
+ sep = "\r\n"
92
+ iSepPos = inStream2.find(sep)
93
+ if iSepPos < 0 or iSepPos > 80:
94
+ sep = "\n" #switch back to unix representation
95
+
96
+ lines = inStream2.split(sep)
97
+ for oneLine in lines[1:]:
98
+ if len(oneLine) < 10:
99
+ break
100
+ try:
101
+ key, val = oneLine.split(':' , 1)
102
+ except ValueError:
103
+ key, val = oneLine.split('=' , 1)
104
+ key = key.strip()
105
+ self.header_keys.append(key)
106
+ self.header[key] = val.strip(" \"\n\r\t")
107
+ missing = []
108
+ for item in MINIMUM_KEYS:
109
+ if item not in self.header_keys:
110
+ missing.append(item)
111
+ if len(missing) > 0:
112
+ logger.debug("CBF file misses the keys " + " ".join(missing))
113
+
114
+
115
+ def read(self, fname, frame=None):
116
+ """
117
+ Read in header into self.header and
118
+ the data into self.data
119
+ """
120
+ self.filename = fname
121
+ self.header = {}
122
+ self.resetvals()
123
+
124
+ infile = self._open(fname, "rb")
125
+ self._readheader(infile)
126
+ # Compute image size
127
+ try:
128
+ self.dim1 = int(self.header['X-Binary-Size-Fastest-Dimension'])
129
+ self.dim2 = int(self.header['X-Binary-Size-Second-Dimension'])
130
+ except:
131
+ raise Exception(IOError, "CBF file %s is corrupt, no dimensions in it" % fname)
132
+ try:
133
+ bytecode = DATA_TYPES[self.header['X-Binary-Element-Type']]
134
+ self.bpp = len(numpy.array(0, bytecode).tostring())
135
+ except KeyError:
136
+ bytecode = numpy.int32
137
+ self.bpp = 32
138
+ logger.warning("Defaulting type to int32")
139
+ if self.header["conversions"] == "x-CBF_BYTE_OFFSET":
140
+ self.data = self._readbinary_byte_offset(self.cif["_array_data.data"]).astype(bytecode).reshape((self.dim2, self.dim1))
141
+ else:
142
+ raise Exception(IOError, "Compression scheme not yet supported, please contact FABIO development team")
143
+
144
+ self.bytecode = self.data.dtype.type
145
+ self.resetvals()
146
+ # # ensure the PIL image is reset
147
+ self.pilimage = None
148
+ return self
149
+
150
+
151
+
152
+ def _readbinary_byte_offset(self, inStream):
153
+ """
154
+ Read in a binary part of an x-CBF_BYTE_OFFSET compressed image
155
+
156
+ @param inStream: the binary image (without any CIF decorators)
157
+ @type inStream: python string.
158
+ @return: a linear numpy array without shape and dtype set
159
+ @rtype: numpy array
160
+ """
161
+ startPos = inStream.find(STARTER) + 4
162
+ data = inStream[ startPos: startPos + int(self.header["X-Binary-Size"])]
163
+ try:
164
+ import byte_offset
165
+ except ImportError:
166
+ logger.warning("Error in byte_offset part: Falling back to Numpy implementation")
167
+ myData = decByteOffet_numpy(data, size=self.dim1 * self.dim2)
168
+ else:
169
+ myData = byte_offset.analyseCython(data, size=self.dim1 * self.dim2)
170
+
171
+ assert len(myData) == self.dim1 * self.dim2
172
+ return myData
173
+
174
+
175
+ def write(self, fname):
176
+ """
177
+ write the file in CBF format
178
+ @param fname: name of the file
179
+ @type: string
180
+ """
181
+ if self.data is not None:
182
+ self.dim2, self.dim1 = self.data.shape
183
+ else:
184
+ raise RuntimeError("CBF image contains no data")
185
+ binary_blob = compByteOffet_numpy(self.data)
186
+ # l = len(binary_blob)
187
+ # if (l % PADDING) != 0:
188
+ # rem = PADDING - (l % PADDING)
189
+ # binary_blob += "\x00" * rem
190
+ dtype = "Unknown"
191
+ for key, value in DATA_TYPES.iteritems():
192
+ if value == self.data.dtype:
193
+ dtype = key
194
+ binary_block = [
195
+ "--CIF-BINARY-FORMAT-SECTION--",
196
+ "Content-Type: application/octet-stream;",
197
+ ' conversions="x-CBF_BYTE_OFFSET"',
198
+ 'Content-Transfer-Encoding: BINARY',
199
+ "X-Binary-Size: %d" % (len(binary_blob)),
200
+ "X-Binary-ID: 1",
201
+ 'X-Binary-Element-Type: "%s"' % (dtype),
202
+ "X-Binary-Element-Byte-Order: LITTLE_ENDIAN" ,
203
+ "Content-MD5: %s" % md5sum(binary_blob),
204
+ "X-Binary-Number-of-Elements: %s" % (self.dim1 * self.dim2),
205
+ "X-Binary-Size-Fastest-Dimension: %d" % self.dim1,
206
+ "X-Binary-Size-Second-Dimension: %d" % self.dim2,
207
+ "X-Binary-Size-Padding: %d" % 1,
208
+ "",
209
+ STARTER + binary_blob,
210
+ "",
211
+ "--CIF-BINARY-FORMAT-SECTION----"
212
+ ]
213
+
214
+ if "_array_data.header_contents" not in self.header:
215
+ nonCifHeaders = []
216
+ else:
217
+ nonCifHeaders = [i.strip()[2:] for i in self.header["_array_data.header_contents"].split("\n") if i.find("# ") >= 0]
218
+
219
+ for key in self.header:
220
+ if (key not in self.header_keys):
221
+ self.header_keys.append(key)
222
+ for key in self.header_keys:
223
+ if key.startswith("_") :
224
+ if key not in self.cif or self.cif[key] != self.header[key]:
225
+ self.cif[key] = self.header[key]
226
+ elif key.startswith("X-Binary-"):
227
+ pass
228
+ elif key.startswith("Content-"):
229
+ pass
230
+ elif key.startswith("conversions"):
231
+ pass
232
+ elif key.startswith("filename"):
233
+ pass
234
+ elif key in self.header:
235
+ nonCifHeaders.append("%s %s" % (key, self.header[key]))
236
+ if len(nonCifHeaders) > 0:
237
+ self.cif["_array_data.header_contents"] = "\r\n".join(["# %s" % i for i in nonCifHeaders])
238
+
239
+ self.cif["_array_data.data"] = "\r\n".join(binary_block)
240
+ self.cif.saveCIF(fname, linesep="\r\n", binary=True)
241
+
242
+ ################################################################################
243
+ # CIF class
244
+ ################################################################################
245
+ class CIF(dict):
246
+ """
247
+ This is the CIF class, it represents the CIF dictionary;
248
+ and as a a python dictionary thus inherits from the dict built in class.
249
+ """
250
+ EOL = ["\r", "\n", "\r\n", "\n\r"]
251
+ BLANK = [" ", "\t"] + EOL
252
+ START_COMMENT = ["\"", "\'"]
253
+ BINARY_MARKER = "--CIF-BINARY-FORMAT-SECTION--"
254
+
255
+ def __init__(self, _strFilename=None):
256
+ """
257
+ Constructor of the class.
258
+
259
+ @param _strFilename: the name of the file to open
260
+ @type _strFilename: filename (str) or file object
261
+ """
262
+ dict.__init__(self)
263
+ self._ordered = []
264
+ if _strFilename is not None: #load the file)
265
+ self.loadCIF(_strFilename)
266
+
267
+ def __setitem__(self, key, value):
268
+ if key not in self._ordered:
269
+ self._ordered.append(key)
270
+ return dict.__setitem__(self, key, value)
271
+
272
+ def pop(self, key):
273
+ if key in self._ordered:
274
+ self._ordered.remove(key)
275
+ return dict.pop(self, key)
276
+
277
+ def popitem(self, key):
278
+ if key in self._ordered:
279
+ self._ordered.remove(key)
280
+ return dict.popitem(self, key)
281
+
282
+
283
+ def loadCIF(self, _strFilename, _bKeepComment=False):
284
+ """Load the CIF file and populates the CIF dictionary into the object
285
+ @param _strFilename: the name of the file to open
286
+ @type _strFilename: string
287
+ @param _strFilename: the name of the file to open
288
+ @type _strFilename: string
289
+ @return: None
290
+ """
291
+
292
+ if isinstance(_strFilename, (str, unicode)):
293
+ if os.path.isfile(_strFilename):
294
+ infile = open(_strFilename, "rb")
295
+ else:
296
+ raise RuntimeError("CIF.loadCIF: No such file to open: %s" % _strFilename)
297
+ #elif isinstance(_strFilename, file, bz2.BZ2File, ):
298
+ elif "read" in dir(_strFilename):
299
+ infile = _strFilename
300
+ else:
301
+ raise RuntimeError("CIF.loadCIF: what is %s type %s" % (_strFilename, type(_strFilename)))
302
+ if _bKeepComment:
303
+ self._parseCIF(infile.read())
304
+ else:
305
+ self._parseCIF(CIF._readCIF(infile))
306
+ readCIF = loadCIF
307
+
308
+ @staticmethod
309
+ def isAscii(_strIn):
310
+ """
311
+ Check if all characters in a string are ascii,
312
+
313
+ @param _strIn: input string
314
+ @type _strIn: python string
315
+ @return: boolean
316
+ @rtype: boolean
317
+ """
318
+ bIsAcii = True
319
+ for i in _strIn:
320
+ if ord(i) > 127:
321
+ bIsAcii = False
322
+ break
323
+ return bIsAcii
324
+
325
+
326
+ @staticmethod
327
+ def _readCIF(_instream):
328
+ """
329
+ - Check if the filename containing the CIF data exists
330
+ - read the cif file
331
+ - removes the comments
332
+
333
+ @param _instream: the file containing the CIF data
334
+ @type _instream: open file in read mode
335
+ @return: a string containing the raw data
336
+ @rtype: string
337
+ """
338
+ if not "readlines" in dir(_instream):
339
+ raise RuntimeError("CIF._readCIF(instream): I expected instream to be an opened file,\
340
+ here I got %s type %s" % (_instream, type(_instream)))
341
+ lLinesRead = _instream.readlines()
342
+ sText = ""
343
+ for sLine in lLinesRead:
344
+ iPos = sLine.find("#")
345
+ if iPos >= 0:
346
+ if CIF.isAscii(sLine):
347
+ sText += sLine[:iPos] + os.linesep
348
+
349
+ if iPos > 80 :
350
+ logger.warning("This line is too long and could cause problems in PreQuest: %s", sLine)
351
+ else :
352
+ sText += sLine
353
+ if len(sLine.strip()) > 80 :
354
+ logger.warning("This line is too long and could cause problems in PreQues: %s", sLine)
355
+ return sText
356
+
357
+
358
+ def _parseCIF(self, sText):
359
+ """
360
+ - Parses the text of a CIF file
361
+ - Cut it in fields
362
+ - Find all the loops and process
363
+ - Find all the keys and values
364
+
365
+ @param sText: the content of the CIF - file
366
+ @type sText: string
367
+ @return: Nothing, the data are incorporated at the CIF object dictionary
368
+ @rtype: None
369
+ """
370
+ loopidx = []
371
+ looplen = []
372
+ loop = []
373
+ #first of all : separate the cif file in fields
374
+ lFields = CIF._splitCIF(sText.strip())
375
+ #Then : look for loops
376
+ for i in range(len(lFields)):
377
+ if lFields[i].lower() == "loop_":
378
+ loopidx.append(i)
379
+ if len(loopidx) > 0:
380
+ for i in loopidx:
381
+ loopone, length, keys = CIF._analyseOneLoop(lFields, i)
382
+ loop.append([keys, loopone])
383
+ looplen.append(length)
384
+
385
+
386
+ for i in range(len(loopidx) - 1, -1, -1):
387
+ f1 = lFields[:loopidx[i]] + lFields[loopidx[i] + looplen[i]:]
388
+ lFields = f1
389
+
390
+ self["loop_"] = loop
391
+
392
+ for i in range(len(lFields) - 1):
393
+ # print lFields[i], lFields[i+1]
394
+ if len(lFields[i + 1]) == 0 : lFields[i + 1] = "?"
395
+ if lFields[i][0] == "_" and lFields[i + 1][0] != "_":
396
+ self[lFields[i]] = lFields[i + 1]
397
+
398
+ @staticmethod
399
+ def _splitCIF(sText):
400
+ """
401
+ Separate the text in fields as defined in the CIF
402
+
403
+ @param sText: the content of the CIF - file
404
+ @type sText: string
405
+ @return: list of all the fields of the CIF
406
+ @rtype: list
407
+ """
408
+ lFields = []
409
+ while True:
410
+ if len(sText) == 0:
411
+ break
412
+ elif sText[0] == "'":
413
+ idx = 0
414
+ bFinished = False
415
+ while not bFinished:
416
+ idx += 1 + sText[idx + 1:].find("'")
417
+ ##########debuging in case we arrive at the end of the text
418
+ if idx >= len(sText) - 1:
419
+ # print sText,idx,len(sText)
420
+ lFields.append(sText[1:-1].strip())
421
+ sText = ""
422
+ bFinished = True
423
+ break
424
+
425
+ if sText[idx + 1] in CIF.BLANK:
426
+ lFields.append(sText[1:idx].strip())
427
+ sText1 = sText[idx + 1:]
428
+ sText = sText1.strip()
429
+ bFinished = True
430
+
431
+ elif sText[0] == '"':
432
+ idx = 0
433
+ bFinished = False
434
+ while not bFinished:
435
+ idx += 1 + sText[idx + 1:].find('"')
436
+ ##########debuging in case we arrive at the end of the text
437
+ if idx >= len(sText) - 1:
438
+ # print sText,idx,len(sText)
439
+ lFields.append(sText[1:-1].strip())
440
+ # print lFields[-1]
441
+ sText = ""
442
+ bFinished = True
443
+ break
444
+
445
+ if sText[idx + 1] in CIF.BLANK:
446
+ lFields.append(sText[1:idx].strip())
447
+ # print lFields[-1]
448
+ sText1 = sText[idx + 1:]
449
+ sText = sText1.strip()
450
+ bFinished = True
451
+ elif sText[0] == ';':
452
+ if sText[1:].strip().find(CIF.BINARY_MARKER) == 0:
453
+ idx = sText[32:].find(CIF.BINARY_MARKER)
454
+ if idx == -1:
455
+ idx = 0
456
+ else:
457
+ idx += 32 + len(CIF.BINARY_MARKER)
458
+ else:
459
+ idx = 0
460
+ bFinished = False
461
+ while not bFinished:
462
+ idx += 1 + sText[idx + 1:].find(';')
463
+ if sText[idx - 1] in CIF.EOL:
464
+ lFields.append(sText[1:idx - 1].strip())
465
+ sText1 = sText[idx + 1:]
466
+ sText = sText1.strip()
467
+ bFinished = True
468
+ else:
469
+ f = sText.split(None, 1)[0]
470
+ lFields.append(f)
471
+ # print lFields[-1]
472
+ sText1 = sText[len(f):].strip()
473
+ sText = sText1
474
+ return lFields
475
+
476
+
477
+ @staticmethod
478
+ def _analyseOneLoop(lFields, iStart):
479
+ """Processes one loop in the data extraction of the CIF file
480
+ @param lFields: list of all the words contained in the cif file
481
+ @type lFields: list
482
+ @param iStart: the starting index corresponding to the "loop_" key
483
+ @type iStart: integer
484
+ @return: the list of loop dictionaries, the length of the data
485
+ extracted from the lFields and the list of all the keys of the loop.
486
+ @rtype: tuple
487
+ """
488
+ # in earch loop we first search the length of the loop
489
+ # print lFields
490
+ # curloop = {}
491
+ loop = []
492
+ keys = []
493
+ i = iStart + 1
494
+ bFinished = False
495
+ while not bFinished:
496
+ if lFields[i][0] == "_":
497
+ keys.append(lFields[i])#.lower())
498
+ i += 1
499
+ else:
500
+ bFinished = True
501
+ data = []
502
+ while True:
503
+ if i >= len(lFields):
504
+ break
505
+ elif len(lFields[i]) == 0:
506
+ break
507
+ elif lFields[i][0] == "_":
508
+ break
509
+ elif lFields[i] in ["loop_", "stop_", "global_", "data_", "save_"]:
510
+ break
511
+ else:
512
+ data.append(lFields[i])
513
+ i += 1
514
+ #print len(keys), len(data)
515
+ k = 0
516
+
517
+ if len(data) < len(keys):
518
+ element = {}
519
+ for j in keys:
520
+ if k < len(data):
521
+ element[j] = data[k]
522
+ else :
523
+ element[j] = "?"
524
+ k += 1
525
+ #print element
526
+ loop.append(element)
527
+
528
+ else:
529
+ #print data
530
+ #print keys
531
+ for i in range(len(data) / len(keys)):
532
+ element = {}
533
+ for j in keys:
534
+ element[j] = data[k]
535
+ k += 1
536
+ # print element
537
+ loop.append(element)
538
+ # print loop
539
+ return loop, 1 + len(keys) + len(data), keys
540
+
541
+
542
+
543
+
544
+
545
+
546
+ #############################################################################################
547
+ ######## everything needed to write a cif file #########################################
548
+ #############################################################################################
549
+
550
+ def saveCIF(self, _strFilename="test.cif", linesep=os.linesep, binary=False):
551
+ """Transforms the CIF object in string then write it into the given file
552
+ @param _strFilename: the of the file to be written
553
+ @param linesep: line separation used (to force compatibility with windows/unix)
554
+ @param binary: Shall we write the data as binary (True only for imageCIF/CBF)
555
+ @type param: string
556
+ """
557
+ if binary:
558
+ mode = "wb"
559
+ else:
560
+ mode = "w"
561
+ try:
562
+ fFile = open(_strFilename, mode)
563
+ except IOError:
564
+ print("Error during the opening of file for write: %s" %
565
+ _strFilename)
566
+ return
567
+ fFile.write(self.tostring(_strFilename, linesep))
568
+ try:
569
+ fFile.close()
570
+ except IOError:
571
+ print("Error during the closing of file for write: %s" %
572
+ _strFilename)
573
+
574
+
575
+ def tostring(self, _strFilename=None, linesep=os.linesep):
576
+ """converts a cif dictionnary to a string according to the CIF syntax
577
+ @param _strFilename: the name of the filename to be appended in the
578
+ header of the CIF file
579
+ @type _strFilename: string
580
+ @return : a sting that corresponds to the content of the CIF - file.
581
+ @rtype: string
582
+ """
583
+ # sCifText = ""
584
+ lstStrCif = ["# " + i for i in __version__]
585
+ if "_chemical_name_common" in self:
586
+ t = self["_chemical_name_common"].split()[0]
587
+ elif _strFilename is not None:
588
+ t = os.path.splitext(os.path.split(str(_strFilename).strip())[1])[0]
589
+ else:
590
+ t = ""
591
+ lstStrCif.append("data_%s" % (t))
592
+ #first of all get all the keys :
593
+ lKeys = self.keys()
594
+ lKeys.sort()
595
+ for key in lKeys[:]:
596
+ if key in self._ordered:
597
+ lKeys.remove(key)
598
+ self._ordered += lKeys
599
+
600
+ for sKey in self._ordered:
601
+ if sKey == "loop_":
602
+ continue
603
+ if sKey not in self:
604
+ self._ordered.remove(sKey)
605
+ logger.debug("Skipping key %s from ordered list as no more present in dict")
606
+ continue
607
+ sValue = str(self[sKey])
608
+ if sValue.find("\n") > -1: #should add value between ;;
609
+ lLine = [sKey, ";", sValue, ";", ""]
610
+ elif len(sValue.split()) > 1: #should add value between ''
611
+ sLine = "%s '%s'" % (sKey, sValue)
612
+ if len(sLine) > 80:
613
+ lLine = [str(sKey), sValue]
614
+ else:
615
+ lLine = [sLine]
616
+ else:
617
+ sLine = "%s %s" % (sKey, sValue)
618
+ if len(sLine) > 80:
619
+ lLine = [str(sKey), sValue]
620
+ else:
621
+ lLine = [sLine]
622
+ lstStrCif += lLine
623
+ if self.has_key("loop_"):
624
+ for loop in self["loop_"]:
625
+ lstStrCif.append("loop_ ")
626
+ lKeys = loop[0]
627
+ llData = loop[1]
628
+ lstStrCif += [" %s" % (sKey) for sKey in lKeys]
629
+ for lData in llData:
630
+ sLine = " "
631
+ for key in lKeys:
632
+ sRawValue = lData[key]
633
+ if sRawValue.find("\n") > -1: #should add value between ;;
634
+ lstStrCif += [sLine, ";", str(sRawValue), ";"]
635
+ sLine = " "
636
+ else:
637
+ if len(sRawValue.split()) > 1: #should add value between ''
638
+ value = "'%s'" % (sRawValue)
639
+ else:
640
+ value = str(sRawValue)
641
+ if len(sLine) + len(value) > 78:
642
+ lstStrCif += [sLine]
643
+ sLine = " " + value
644
+ else:
645
+ sLine += " " + value
646
+ lstStrCif.append(sLine)
647
+ lstStrCif.append("")
648
+ return linesep.join(lstStrCif)
649
+
650
+
651
+ def exists(self, sKey):
652
+ """
653
+ Check if the key exists in the CIF and is non empty.
654
+ @param sKey: CIF key
655
+ @type sKey: string
656
+ @param cif: CIF dictionary
657
+ @return: True if the key exists in the CIF dictionary and is non empty
658
+ @rtype: boolean
659
+ """
660
+ bExists = False
661
+ if self.has_key(sKey):
662
+ if len(self[sKey]) >= 1:
663
+ if self[sKey][0] not in ["?", "."]:
664
+ bExists = True
665
+ return bExists
666
+
667
+
668
+ def existsInLoop(self, sKey):
669
+ """
670
+ Check if the key exists in the CIF dictionary.
671
+ @param sKey: CIF key
672
+ @type sKey: string
673
+ @param cif: CIF dictionary
674
+ @return: True if the key exists in the CIF dictionary and is non empty
675
+ @rtype: boolean
676
+ """
677
+ if not self.exists("loop_"):
678
+ return False
679
+ bExists = False
680
+ if not bExists:
681
+ for i in self["loop_"]:
682
+ for j in i[0]:
683
+ if j == sKey:
684
+ bExists = True
685
+ return bExists
686
+
687
+
688
+ def loadCHIPLOT(self, _strFilename):
689
+ """
690
+ Load the powder diffraction CHIPLOT file and returns the
691
+ pd_CIF dictionary in the object
692
+
693
+ @param _strFilename: the name of the file to open
694
+ @type _strFilename: string
695
+ @return: the CIF object corresponding to the powder diffraction
696
+ @rtype: dictionary
697
+ """
698
+ if not os.path.isfile(_strFilename):
699
+ print "I cannot find the file %s" % _strFilename
700
+ raise
701
+ lInFile = open(_strFilename, "r").readlines()
702
+ self["_audit_creation_method"] = 'From 2-D detector using FIT2D and CIFfile'
703
+ self["_pd_meas_scan_method"] = "fixed"
704
+ self["_pd_spec_description"] = lInFile[0].strip()
705
+ try:
706
+ iLenData = int(lInFile[3])
707
+ except ValueError:
708
+ iLenData = None
709
+ lOneLoop = []
710
+ try:
711
+ f2ThetaMin = float(lInFile[4].split()[0])
712
+ last = ""
713
+ for sLine in lInFile[-20:]:
714
+ if sLine.strip() != "":
715
+ last = sLine.strip()
716
+ f2ThetaMax = float(last.split()[0])
717
+ limitsOK = True
718
+
719
+ except (ValueError, IndexError):
720
+ limitsOK = False
721
+ f2ThetaMin = 180.0
722
+ f2ThetaMax = 0
723
+ # print "limitsOK:", limitsOK
724
+ for sLine in lInFile[4:]:
725
+ sCleaned = sLine.split("#")[0].strip()
726
+ data = sCleaned.split()
727
+ if len(data) == 2 :
728
+ if not limitsOK:
729
+ f2Theta = float(data[0])
730
+ if f2Theta < f2ThetaMin :
731
+ f2ThetaMin = f2Theta
732
+ if f2Theta > f2ThetaMax :
733
+ f2ThetaMax = f2Theta
734
+ lOneLoop.append({ "_pd_meas_intensity_total": data[1] })
735
+ if not iLenData:
736
+ iLenData = len(lOneLoop)
737
+ assert (iLenData == len(lOneLoop))
738
+ self[ "_pd_meas_2theta_range_inc" ] = "%.4f" % ((f2ThetaMax - f2ThetaMin) / (iLenData - 1))
739
+ if self[ "_pd_meas_2theta_range_inc" ] < 0:
740
+ self[ "_pd_meas_2theta_range_inc" ] = abs (self[ "_pd_meas_2theta_range_inc" ])
741
+ tmp = f2ThetaMax
742
+ f2ThetaMax = f2ThetaMin
743
+ f2ThetaMin = tmp
744
+ self[ "_pd_meas_2theta_range_max" ] = "%.4f" % f2ThetaMax
745
+ self[ "_pd_meas_2theta_range_min" ] = "%.4f" % f2ThetaMin
746
+ self[ "_pd_meas_number_of_points" ] = str(iLenData)
747
+ self["loop_"] = [ [ ["_pd_meas_intensity_total" ], lOneLoop ] ]
748
+
749
+
750
+ @staticmethod
751
+ def LoopHasKey(loop, key):
752
+ "Returns True if the key (string) exist in the array called loop"""
753
+ try:
754
+ loop.index(key)
755
+ return True
756
+ except ValueError:
757
+ return False
758
+