source: trunk/imports/G2img_1TIF.py @ 3017

Last change on this file since 3017 was 3017, checked in by toby, 4 years ago

change reading of "Chess" (Pilatus?) detector to uint32 to avoid overflow error on windows

  • Property svn:eol-style set to native
  • Property svn:keywords set to Date Author Revision URL Id
File size: 16.1 KB
Line 
1# -*- coding: utf-8 -*-
2########### SVN repository information ###################
3# $Date: 2017-08-18 17:51:40 +0000 (Fri, 18 Aug 2017) $
4# $Author: toby $
5# $Revision: 3017 $
6# $URL: trunk/imports/G2img_1TIF.py $
7# $Id: G2img_1TIF.py 3017 2017-08-18 17:51:40Z toby $
8########### SVN repository information ###################
9'''
10*Module G2img_1TIF: Tagged-image File images*
11--------------------------------------------------
12
13Routine to read an image in Tagged-image file (TIF) format as well as a variety
14of slightly incorrect pseudo-TIF formats used at instruments around the world.
15Note that the name ``G2img_1TIF`` is used so that this file will
16sort to the top of the image formats and thus show up first in the menu.
17(It is the most common, alas).
18
19'''
20
21import struct as st
22import GSASIIobj as G2obj
23import GSASIIpath
24import numpy as np
25import time
26DEBUG = False
27GSASIIpath.SetVersionNumber("$Revision: 3017 $")
28class TIF_ReaderClass(G2obj.ImportImage):
29    '''Reads TIF files using a routine (:func:`GetTifData`) that looks
30    for files that can be identified from known instruments and will
31    correct for slightly incorrect TIF usage. If that routine fails,
32    it will be read with a standard TIF reader, which can handle compression
33    and other things less commonly used at beamlines.
34    '''
35    def __init__(self):
36        super(self.__class__,self).__init__( # fancy way to self-reference
37            extensionlist=('.tif','.tiff'),
38            strictExtension=False,
39            formatName = 'TIF image',
40            longFormatName = 'Various .tif and pseudo-TIF formats'
41            )
42        self.scriptable = True
43
44    def ContentsValidator(self, filepointer):
45        '''Does the header match the required TIF header?
46        '''
47        tag = filepointer.read(2)
48        if tag == 'II' and int(st.unpack('<h',filepointer.read(2))[0]) == 42: #little endian
49            pass
50        elif tag == 'MM' and int(st.unpack('>h',filepointer.read(2))[0]) == 42: #big endian
51            pass
52        else:
53            return False # header not found; not valid TIF
54        return True
55   
56    def Reader(self,filename,filepointer, ParentFrame=None, **unused):
57        '''Read the TIF file using :func:`GetTifData`. If that fails,
58        use :func:`scipy.misc.imread` and give the user a chance to
59        edit the likely wrong default image parameters.
60        '''
61        self.Comments,self.Data,self.Npix,self.Image = GetTifData(filename)
62        if self.Npix == 0:
63            print("GetTifData failed to read "+str(filename)+" Trying SciPy")
64            import scipy.misc
65            self.Image = scipy.misc.imread(filename,flatten=True)
66            self.Npix = self.Image.size
67            if ParentFrame:
68                self.SciPy = True
69                self.Comments = ['no metadata']
70                self.Data = {'wavelength': 0.1, 'pixelSize': [200, 200], 'distance': 100.0}
71                self.Data['size'] = list(self.Image.shape)
72                self.Data['center'] = [int(i/2) for i in self.Image.shape]
73        if self.Npix == 0:
74            return False
75        self.LoadImage(ParentFrame,filename)
76        return True
77
78def GetTifData(filename):
79    '''Read an image in a pseudo-tif format,
80    as produced by a wide variety of software, almost always
81    incorrectly in some way.
82    '''
83    import struct as st
84    import array as ar
85    import ReadMarCCDFrame as rmf
86    image = None
87    File = open(filename,'rb')
88    dataType = 5
89    center = [None,None]
90    wavelength = None
91    distance = None
92    polarization = None
93    try:
94        Meta = open(filename+'.metadata','Ur')
95        head = Meta.readlines()
96        for line in head:
97            line = line.strip()
98            try:
99                if '=' not in line: continue
100                keyword = line.split('=')[0].strip()
101                if 'dataType' == keyword:
102                    dataType = int(line.split('=')[1])
103                elif 'wavelength' == keyword.lower():
104                    wavelength = float(line.split('=')[1])
105                elif 'distance' == keyword.lower():
106                    distance = float(line.split('=')[1])
107                elif 'polarization' == keyword.lower():
108                    polarization = float(line.split('=')[1])
109            except:
110                print('error reading metadata: '+line)
111        Meta.close()
112    except IOError:
113        print 'no metadata file found - will try to read file anyway'
114        head = ['no metadata file found',]
115       
116    tag = File.read(2)
117    byteOrd = '<'
118    if tag == 'II' and int(st.unpack('<h',File.read(2))[0]) == 42:     #little endian
119        IFD = int(st.unpack(byteOrd+'i',File.read(4))[0])
120    elif tag == 'MM' and int(st.unpack('>h',File.read(2))[0]) == 42:   #big endian
121        byteOrd = '>'
122        IFD = int(st.unpack(byteOrd+'i',File.read(4))[0])       
123    else:
124        lines = ['not a detector tiff file',]
125        return lines,0,0,0
126    File.seek(IFD)                                                  #get number of directory entries
127    NED = int(st.unpack(byteOrd+'h',File.read(2))[0])
128    IFD = {}
129    nSlice = 1
130    for ied in range(NED):
131        Tag,Type = st.unpack(byteOrd+'Hh',File.read(4))
132        nVal = st.unpack(byteOrd+'i',File.read(4))[0]
133        if DEBUG: print 'Try:',Tag,Type,nVal
134        if Type == 1:
135            Value = st.unpack(byteOrd+nVal*'b',File.read(nVal))
136        elif Type == 2:
137            Value = st.unpack(byteOrd+'i',File.read(4))
138        elif Type == 3:
139            Value = st.unpack(byteOrd+nVal*'h',File.read(nVal*2))
140            st.unpack(byteOrd+nVal*'h',File.read(nVal*2))
141        elif Type == 4:
142            if Tag in [273,279]:
143                nSlice = nVal
144                nVal = 1
145            Value = st.unpack(byteOrd+nVal*'i',File.read(nVal*4))
146        elif Type == 5:
147            Value = st.unpack(byteOrd+nVal*'i',File.read(nVal*4))
148        elif Type == 11:
149            Value = st.unpack(byteOrd+nVal*'f',File.read(nVal*4))
150        IFD[Tag] = [Type,nVal,Value]
151        if DEBUG: print Tag,IFD[Tag]
152    sizexy = [IFD[256][2][0],IFD[257][2][0]]
153    [nx,ny] = sizexy
154    Npix = nx*ny
155    time0 = time.time()
156    if 34710 in IFD:
157        print 'Read MAR CCD tiff file: ',filename
158        marFrame = rmf.marFrame(File,byteOrd,IFD)
159        image = np.flipud(np.array(np.asarray(marFrame.image),dtype=np.int32))
160        tifType = marFrame.filetitle
161        pixy = [marFrame.pixelsizeX/1000.0,marFrame.pixelsizeY/1000.0]
162        head = marFrame.outputHead()
163# extract resonable wavelength from header
164        wavelength = marFrame.sourceWavelength*1e-5
165        wavelength = (marFrame.opticsWavelength > 0) and marFrame.opticsWavelength*1e-5 or wavelength
166        wavelength = (wavelength <= 0) and None or wavelength
167# extract resonable distance from header
168        distance = (marFrame.startXtalToDetector+marFrame.endXtalToDetector)*5e-4
169        distance = (distance <= marFrame.startXtalToDetector*5e-4) and marFrame.xtalToDetector*1e-3 or distance
170        distance = (distance <= 0) and None or distance
171# extract resonable center from header
172        center = [marFrame.beamX*marFrame.pixelsizeX*1e-9,marFrame.beamY*marFrame.pixelsizeY*1e-9]
173        center = (center[0] != 0 and center[1] != 0) and center or [None,None]
174#print head,tifType,pixy
175    elif nSlice > 1:    #CheMin multislice tif file!
176        try:
177            import Image as Im
178        except ImportError:
179            try:
180                from PIL import Image as Im
181            except ImportError:
182                print "PIL/pillow Image module not present. This TIF cannot be read without this"
183                #raise Exception("PIL/pillow Image module not found")
184                lines = ['not a detector tiff file',]
185                return lines,0,0,0
186        tifType = 'CheMin'
187        pixy = [40.,40.]
188        image = np.flipud(np.array(Im.open(filename)))*10.
189        distance = 18.0
190        center = [pixy[0]*sizexy[0]/2000,0]     #the CheMin beam stop is here
191        wavelength = 1.78892
192    elif 272 in IFD:
193        ifd = IFD[272]
194        File.seek(ifd[2][0])
195        S = File.read(ifd[1])
196        if 'PILATUS' in S:
197            tifType = 'Pilatus'
198            dataType = 0
199            pixy = [172.,172.]
200            File.seek(4096)
201            print 'Read Pilatus tiff file: ',filename
202            image = ar.array('I',File.read(4*Npix))
203            image = np.array(np.asarray(image),dtype=np.int32)
204        else:
205            if IFD[258][2][0] == 16:
206                tifType = 'GE'
207                pixy = [200.,200.]
208                File.seek(8)
209                print 'Read GE-detector tiff file: ',filename
210                image = np.array(np.frombuffer(File.read(2*Npix),dtype=np.uint16),dtype=np.int32)
211#                image = np.fromfile(File,dtype=np.int16,count=2*Npix)[:Npix]
212#                image = np.array(ar.array('H',File.read(2*Npix)),dtype=np.int32)
213            elif IFD[258][2][0] == 32:
214                tifType = 'CHESS'
215                pixy = [200.,200.]
216                File.seek(8)
217                print 'Read CHESS-detector tiff file: ',filename
218                image = np.array(ar.array('I',File.read(4*Npix)),dtype=np.uint32)
219    elif 270 in IFD:
220        File.seek(IFD[270][2][0])
221        S = File.read(IFD[273][2][0]-IFD[270][2][0])
222        if 'ImageJ' in S:
223            tifType = 'ImageJ'
224            dataType = 0
225            pixy = [200.,200.]*IFD[277][2][0]
226            File.seek(IFD[273][2][0])
227            print 'Read ImageJ tiff file: ',filename
228#            image = ar.array('H',File.read(2*Npix))
229#            image = File.read(2*Npix,dtype=np.uint16)
230            if IFD[258][2][0] == 32:
231                image = File.read(4*Npix)
232                image = np.array(np.frombuffer(image,dtype=byteOrd+'i4'),dtype=np.int32)
233            elif IFD[258][2][0] == 16:
234                image = File.read(2*Npix)
235                pixy = [109.92,109.92]      #for LCLS ImageJ tif files
236                image = np.array(np.frombuffer(image,dtype=byteOrd+'u2'),dtype=np.int32)
237#            if '>' in byteOrd:
238#                image.byteswap()
239#            image = np.array(np.frombuffer(image),dtype=np.int32)
240#            image = np.array(np.asarray(image,dtype='H'),dtype=np.int32)           
241    elif 262 in IFD and IFD[262][2][0] > 4:
242        tifType = 'DND'
243        pixy = [158.,158.]
244        File.seek(512)
245        print 'Read DND SAX/WAX-detector tiff file: ',filename
246        image = np.array(np.frombuffer(File.read(2*Npix),dtype=np.uint16),dtype=np.int32)
247#        image = np.fromfile(File,dtype=np.int16,count=2*Npix)[:Npix]
248#        image = np.array(ar.array('H',File.read(2*Npix)),dtype=np.int32)
249    elif sizexy == [1536,1536]:
250        tifType = 'APS Gold'
251        pixy = [150.,150.]
252        File.seek(64)
253        print 'Read Gold tiff file:',filename
254        image = np.array(np.frombuffer(File.read(2*Npix),dtype=np.uint16),dtype=np.int32)
255#        image = np.fromfile(File,dtype=np.int16,count=2*Npix)[:Npix]
256#        image = np.array(ar.array('H',File.read(2*Npix)),dtype=np.int32)
257    elif sizexy == [2048,2048] or sizexy == [1024,1024] or sizexy == [3072,3072]:
258        if IFD[273][2][0] == 8:
259            if IFD[258][2][0] == 32:
260                tifType = 'PE'
261                pixy = [200.,200.]
262                File.seek(8)
263                print 'Read APS PE-detector tiff file: ',filename
264                if dataType == 5:
265                    image = np.array(np.frombuffer(File.read(4*Npix),dtype=np.float32),dtype=np.int32)  #fastest
266#                    image = np.fromfile(File,dtype=np.float32,count=4*Npix)[:Npix]
267#                    image = np.array(ar.array('f',File.read(4*Npix)),dtype=np.int32)
268                else:
269                    image = np.array(np.frombuffer(File.read(4*Npix),dtype=np.int),dtype=np.int32)
270#                    image = np.fromfile(File,dtype=np.int,count=4*Npix)[:Npix]
271#                    image = np.array(ar.array('I',File.read(4*Npix)),dtype=np.int32)
272            elif IFD[258][2][0] == 16: 
273                tifType = 'MedOptics D1'
274                pixy = [46.9,46.9]
275                File.seek(8)
276                print 'Read MedOptics D1 tiff file: ',filename
277                image = np.array(np.frombuffer(File.read(2*Npix),dtype=np.uint16),dtype=np.int32)
278#                image = np.array(ar.array('H',File.read(2*Npix)),dtype=np.int32)
279                 
280        elif IFD[273][2][0] == 4096:
281            if sizexy[0] == 3072:
282                pixy =  [73.,73.]
283                tifType = 'MAR225'           
284            else:
285                pixy = [158.,158.]
286                tifType = 'MAR325'           
287            File.seek(4096)
288            print 'Read MAR CCD tiff file: ',filename
289            image = np.array(np.frombuffer(File.read(2*Npix),dtype=np.uint16),dtype=np.int32)
290#            image = np.fromfile(File,dtype=np.int16,count=2*Npix)[:Npix]
291#            image = np.array(ar.array('H',File.read(2*Npix)),dtype=np.int32)
292        elif IFD[273][2][0] == 512:
293            tifType = '11-ID-C'
294            pixy = [200.,200.]
295            File.seek(512)
296            print 'Read 11-ID-C tiff file: ',filename
297            image = np.array(np.frombuffer(File.read(2*Npix),dtype=np.uint16),dtype=np.int32)
298#            image = np.array(ar.array('H',File.read(2*Npix)),dtype=np.int32)
299                   
300    elif sizexy == [4096,4096]:
301        if IFD[273][2][0] == 8:
302            if IFD[258][2][0] == 16:
303                tifType = 'scanCCD'
304                pixy = [9.,9.]
305                File.seek(8)
306                print 'Read APS scanCCD tiff file: ',filename
307                image = np.array(ar.array('H',File.read(2*Npix)),dtype=np.int32)
308            elif IFD[258][2][0] == 32:
309                tifType = 'PE4k'
310                pixy = [100.,100.]
311                File.seek(8)
312                print 'Read PE 4Kx4K tiff file: ',filename
313                image = np.array(np.frombuffer(File.read(4*Npix),dtype=np.float32)/2.**4,dtype=np.int32)
314#                image = np.fromfile(File,dtype=np.uint,count=4*Npix)[:Npix]
315#                if np.max(image) > 2**31:
316#                    image = np.array(image-2**30,dtype=np.int32)
317#                else:
318#                    image = np.array(image,dtype=np.int32)
319#                arry = ar.array('I',File.read(4*Npix))
320#                image = np.array(arry)/2**16           
321        elif IFD[273][2][0] == 4096:
322            tifType = 'Rayonix'
323            pixy = [73.242,73.242]
324            File.seek(4096)
325            print 'Read Rayonix MX300HE tiff file: ',filename
326            image = np.array(np.frombuffer(File.read(2*Npix),dtype=np.uint16),dtype=np.int32)
327#            image = np.fromfile(File,dtype=np.int16,count=2*Npix)[:Npix]
328#            image = np.array(ar.array('H',File.read(2*Npix)),dtype=np.int32)
329    elif sizexy == [391,380]:
330        pixy = [109.92,109.92]
331        File.seek(8)
332        image = np.array(np.frombuffer(File.read(2*Npix),dtype=np.int16),dtype=np.int32)
333    elif sizexy == [380,391]:
334        File.seek(110)
335        pixy = [109.92,109.92]
336        image = np.array(np.frombuffer(File.read(Npix),dtype=np.uint8),dtype=np.int32)
337    elif sizexy ==  [825,830]:
338        pixy = [109.92,109.92]
339        File.seek(8)
340        image = np.array(np.frombuffer(File.read(Npix),dtype=np.uint8),dtype=np.int32)
341    elif sizexy ==  [1800,1800]:
342        pixy = [109.92,109.92]
343        File.seek(110)
344        image = np.array(np.frombuffer(File.read(Npix),dtype=np.uint8),dtype=np.int32)
345#    elif sizexy == [960,960]:
346#        tiftype = 'PE-BE'
347#        pixy = (200,200)
348#        File.seek(8)
349#        if not imageOnly:
350#            print 'Read Gold tiff file:',filename
351#        image = np.array(ar.array('H',File.read(2*Npix)),dtype=np.int32)
352           
353    if image is None:
354        lines = ['not a known detector tiff file',]
355        return lines,0,0,0
356       
357    if sizexy[1]*sizexy[0] != image.size: # test is resize is allowed
358        lines = ['not a known detector tiff file',]
359        return lines,0,0,0
360    print 'image read time: %.3f'%(time.time()-time0)
361    image = np.reshape(image,(sizexy[1],sizexy[0]))
362    center = (not center[0]) and [pixy[0]*sizexy[0]/2000,pixy[1]*sizexy[1]/2000] or center
363    wavelength = (not wavelength) and 0.10 or wavelength
364    distance = (not distance) and 100.0 or distance
365    polarization = (not polarization) and 0.99 or polarization
366    data = {'pixelSize':pixy,'wavelength':wavelength,'distance':distance,'center':center,'size':sizexy,
367            'setdist':distance,'PolaVal':[polarization,False]}
368    File.close()   
369    return head,data,Npix,image
Note: See TracBrowser for help on using the repository browser.