source: trunk/imports/G2img_1TIF.py @ 5009

Last change on this file since 5009 was 5009, checked in by vondreele, 4 years ago

add 'det2thet' to image importers data dict.

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