source: trunk/imports/G2img_1TIF.py @ 3152

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

Fix bug with PE .raw.tif reads

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