Package fabio :: Module cbfimage
[hide private]
[frames] | no frames]

Source Code for Module fabio.cbfimage

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