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

Source Code for Module fabio.brukerimage

  1  #!/usr/bin/env python 
  2  """ 
  3   
  4  Authors: Henning O. Sorensen & Erik Knudsen 
  5           Center for Fundamental Research: Metal Structures in Four Dimensions 
  6           Risoe National Laboratory 
  7           Frederiksborgvej 399 
  8           DK-4000 Roskilde 
  9           email:erik.knudsen@risoe.dk 
 10   
 11  Based on: openbruker,readbruker, readbrukerheader functions in the opendata 
 12           module of ImageD11 written by Jon Wright, ESRF, Grenoble, France 
 13   
 14  """ 
 15   
 16  import numpy, logging 
 17  logger = logging.getLogger("brukerimage") 
 18  from fabioimage import fabioimage 
 19  from readbytestream import readbytestream 
 20   
 21   
22 -class brukerimage(fabioimage):
23 """ 24 Read and eventually write ID11 bruker (eg smart6500) images 25 """ 26 27 # needed if you feel like writing - see ImageD11/scripts/edf2bruker.py 28 29 __headerstring__ = "" 30 31
32 - def _readheader(self, infile):
33 """ 34 the bruker format uses 80 char lines in key : value format 35 In the fisrt 512*5 bytes of the header there should be a 36 HDRBLKS key, whose value denotes how many 512 byte blocks 37 are in the total header. The header is always n*5*512 bytes, 38 otherwise it wont contain whole key: value pairs 39 """ 40 lump = infile.read(512 * 5) 41 self.__headerstring__ += lump 42 i = 80 43 self.header = {} 44 while i < 512 * 5: 45 if lump[i - 80: i].find(":") > 0: 46 key, val = lump[i - 80: i].split(":", 1) 47 key = key.strip() # remove the whitespace (why?) 48 val = val.strip() 49 if self.header.has_key(key): 50 # append lines if key already there 51 self.header[key] = self.header[key] + '\n' + val 52 else: 53 self.header[key] = val 54 self.header_keys.append(key) 55 i = i + 80 # next 80 characters 56 # we must have read this in the first 512 bytes. 57 nhdrblks = int(self.header['HDRBLKS']) 58 # Now read in the rest of the header blocks, appending 59 rest = infile.read(512 * (nhdrblks - 5)) 60 self.__headerstring__ += rest 61 lump = lump[i - 80: 512] + rest 62 i = 80 63 j = 512 * nhdrblks 64 while i < j : 65 if lump[i - 80: i].find(":") > 0: # as for first 512 bytes of header 66 key, val = lump[i - 80: i].split(":", 1) 67 key = key.strip() 68 val = val.strip() 69 if self.header.has_key(key): 70 self.header[key] = self.header[key] + '\n' + val 71 else: 72 self.header[key] = val 73 self.header_keys.append(key) 74 i = i + 80 75 # make a (new) header item called "datastart" 76 self.header['datastart'] = infile.tell() 77 #set the image dimensions 78 self.dim1 = int(self.header['NROWS']) 79 self.dim2 = int(self.header['NCOLS'])
80
81 - def read(self, fname, frame=None):
82 """ 83 Read in and unpack the pixels (including overflow table 84 """ 85 infile = self._open(fname, "rb") 86 try: 87 self._readheader(infile) 88 except: 89 raise 90 91 rows = self.dim1 92 cols = self.dim2 93 94 try: 95 # you had to read the Bruker docs to know this! 96 npixelb = int(self.header['NPIXELB']) 97 except: 98 errmsg = "length " + str(len(self.header['NPIXELB'])) + "\n" 99 for byt in self.header['NPIXELB']: 100 errmsg += "char: " + str(byt) + " " + str(ord(byt)) + "\n" 101 logger.warning(errmsg) 102 raise 103 104 self.data = readbytestream(infile, infile.tell(), 105 rows, cols, npixelb, 106 datatype="int", 107 signed='n', 108 swap='n') 109 110 #handle overflows 111 nov = int(self.header['NOVERFL']) 112 if nov > 0: # Read in the overflows 113 # need at least int32 sized data I guess - can reach 2^21 114 self.data = self.data.astype(numpy.uint32) 115 # 16 character overflows: 116 # 9 characters of intensity 117 # 7 character position 118 for i in range(nov): 119 ovfl = infile.read(16) 120 intensity = int(ovfl[0: 9]) 121 position = int(ovfl[9: 16]) 122 # relies on python style modulo being always + 123 row = position % rows 124 # relies on truncation down 125 col = position / rows 126 #print "Overflow ", r, c, intensity, position,\ 127 # self.data[r,c],self.data[c,r] 128 self.data[col, row] = intensity 129 infile.close() 130 131 self.resetvals() 132 self.pilimage = None 133 return self
134 135
136 - def write(self, fname):
137 """ 138 Writes the image as EDF 139 140 FIXME: this should call edfimage.write if that is wanted? 141 obj = edfimage(data = self.data, header = self.header) 142 obj.write(fname) 143 or maybe something like: edfimage.write(self, fname) 144 145 """ 146 logger.warning("***warning***: call to unifinished " + \ 147 "brukerimage.write. This will write the file" + \ 148 fname + "as an edf-file") 149 150 151 outfile = self._open(fname, "wb") 152 outfile.write('{\n') 153 i = 4 154 for k in self.header_keys: 155 out = (("%s = %s;\n") % (k, self.header[k])) 156 i = i + len(out) 157 outfile.write(out) 158 out = (4096 - i) * ' ' 159 outfile.write(out) 160 outfile.write('}\n') 161 # Assumes a short-circuiting if / or ... 162 if not self.header.has_key("ByteOrder") or \ 163 self.header["ByteOrder"] == "LowByteFirst": 164 outfile.write(self.data.astype(numpy.uint16).tostring()) 165 else: 166 outfile.write(self.data.byteswap().astype( 167 numpy.uint16).tostring()) 168 outfile.close()
169 170 171 172
173 -def test():
174 """ a testcase """ 175 import sys, time 176 img = brukerimage() 177 start = time.clock() 178 for filename in sys.argv[1:]: 179 img.read(filename) 180 res = img.toPIL16() 181 img.rebin(2, 2) 182 print filename + (": max=%d, min=%d, mean=%.2e, stddev=%.2e") % ( 183 img.getmax(), img.getmin(), img.getmean(), img.getstddev()) 184 print 'integrated intensity (%d %d %d %d) =%.3f' % ( 185 10, 20, 20, 40, img.integrate_area((10, 20, 20, 40))) 186 end = time.clock() 187 print (end - start)
188 189 190 191 if __name__ == '__main__': 192 test() 193