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 as N, logging 
 17   
 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):
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 logging.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(N.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 FIXME - this should call edfimage.write if that is wanted? 140 eg: obj = edfimage(data = self.data, header = self.header) 141 obj.write(fname) 142 or maybe something like: edfimage.write(self, fname) 143 """ 144 logging.warning("***warning***: call to unifinished " + \ 145 "brukerimage.write. This will write the file" + \ 146 fname + "as an edf-file") 147 148 149 outfile = self._open(fname, "wb") 150 outfile.write('{\n') 151 i = 4 152 for k in self.header_keys: 153 out = (("%s = %s;\n") % (k, self.header[k])) 154 i = i + len(out) 155 outfile.write(out) 156 out = (4096 - i) * ' ' 157 outfile.write(out) 158 outfile.write('}\n') 159 # Assumes a short-circuiting if / or ... 160 if not self.header.has_key("ByteOrder") or \ 161 self.header["ByteOrder"] == "LowByteFirst": 162 outfile.write(self.data.astype(N.uint16).tostring()) 163 else: 164 outfile.write(self.data.byteswap().astype( 165 N.uint16).tostring()) 166 outfile.close()
167
168 - def write2(self, fname):
169 """ FIXME: what is this? """ 170 pass
171 172 173
174 -def test():
175 """ a testcase """ 176 import sys, time 177 img = brukerimage() 178 start = time.clock() 179 for filename in sys.argv[1:]: 180 img.read(filename) 181 res = img.toPIL16() 182 img.rebin(2, 2) 183 print filename + (": max=%d, min=%d, mean=%.2e, stddev=%.2e") % ( 184 img.getmax(), img.getmin(), img.getmean(), img.getstddev()) 185 print 'integrated intensity (%d %d %d %d) =%.3f' % ( 186 10, 20, 20, 40, img.integrate_area((10, 20, 20, 40))) 187 end = time.clock() 188 print (end - start)
189 190 191 192 if __name__ == '__main__': 193 test() 194