source: trunk/imports/G2img_1TIF.py @ 3767

Last change on this file since 3767 was 3767, checked in by vondreele, 3 years ago

add sample changer position as an image parameter & have it show up in sequential calibration results

  • Property svn:eol-style set to native
  • Property svn:keywords set to Date Author Revision URL Id
File size: 15.7 KB
Line 
1# -*- coding: utf-8 -*-
2########### SVN repository information ###################
3# $Date: 2018-12-18 21:07:28 +0000 (Tue, 18 Dec 2018) $
4# $Author: vondreele $
5# $Revision: 3767 $
6# $URL: trunk/imports/G2img_1TIF.py $
7# $Id: G2img_1TIF.py 3767 2018-12-18 21:07:28Z 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.
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: 3767 $")
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            # for scipy 1.2 & later  scipy.misc.imread will be removed
73            # with note to use imageio.imread instead
74            # (N.B. scipy.misc.imread uses PIL/pillow perhaps better to just use pillow)
75            self.Npix = self.Image.size
76            if ParentFrame:
77                self.SciPy = True
78                self.Comments = ['no metadata']
79                self.Data = {'wavelength': 0.1, 'pixelSize': [200., 200.], 'distance': 100.0}
80                self.Data['size'] = list(self.Image.shape)
81                self.Data['center'] = [int(i/2) for i in self.Image.shape]
82        if self.Npix == 0:
83            return False
84        self.LoadImage(ParentFrame,filename)
85        return True
86
87def GetTifData(filename):
88    '''Read an image in a pseudo-tif format,
89    as produced by a wide variety of software, almost always
90    incorrectly in some way.
91    '''
92    import struct as st
93    import array as ar
94    import ReadMarCCDFrame as rmf
95    image = None
96    File = open(filename,'rb')
97    dataType = 5
98    center = [None,None]
99    wavelength = None
100    distance = None
101    polarization = None
102    samplechangerpos = None
103    try:
104        Meta = open(filename+'.metadata','Ur')
105        head = Meta.readlines()
106        for line in head:
107            line = line.strip()
108            try:
109                if '=' not in line: continue
110                keyword = line.split('=')[0].strip()
111                if 'dataType' == keyword:
112                    dataType = int(line.split('=')[1])
113                elif 'wavelength' == keyword.lower():
114                    wavelength = float(line.split('=')[1])
115                elif 'distance' == keyword.lower():
116                    distance = float(line.split('=')[1])
117                elif 'polarization' == keyword.lower():
118                    polarization = float(line.split('=')[1])
119                elif 'samplechangercoordinate' == keyword.lower():
120                    samplechangerpos = float(line.split('=')[1])
121            except:
122                print('error reading metadata: '+line)
123        Meta.close()
124    except IOError:
125        print ('no metadata file found - will try to read file anyway')
126        head = ['no metadata file found',]
127       
128    tag = File.read(2)
129    if 'bytes' in str(type(tag)):
130        tag = tag.decode('latin-1')
131    byteOrd = '<'
132    if tag == 'II' and int(st.unpack('<h',File.read(2))[0]) == 42:     #little endian
133        IFD = int(st.unpack(byteOrd+'i',File.read(4))[0])
134    elif tag == 'MM' and int(st.unpack('>h',File.read(2))[0]) == 42:   #big endian
135        byteOrd = '>'
136        IFD = int(st.unpack(byteOrd+'i',File.read(4))[0])       
137    else:
138        print (tag)
139        lines = ['not a detector tiff file',]
140        return lines,0,0,0
141    File.seek(IFD)                                                  #get number of directory entries
142    NED = int(st.unpack(byteOrd+'h',File.read(2))[0])
143    IFD = {}
144    nSlice = 1
145    if DEBUG: print('byteorder:',byteOrd)
146    for ied in range(NED):
147        Tag,Type = st.unpack(byteOrd+'Hh',File.read(4))
148        nVal = st.unpack(byteOrd+'i',File.read(4))[0]
149        if DEBUG: print ('Try:',Tag,Type,nVal)
150        if Type == 1:
151            Value = st.unpack(byteOrd+nVal*'b',File.read(nVal))
152        elif Type == 2:
153            Value = st.unpack(byteOrd+'i',File.read(4))
154        elif Type == 3:
155            Value = st.unpack(byteOrd+nVal*'h',File.read(nVal*2))
156            st.unpack(byteOrd+nVal*'h',File.read(nVal*2))
157        elif Type == 4:
158            if Tag in [273,279]:
159                nSlice = nVal
160                nVal = 1
161            Value = st.unpack(byteOrd+nVal*'i',File.read(nVal*4))
162        elif Type == 5:
163            Value = st.unpack(byteOrd+nVal*'i',File.read(nVal*4))
164        elif Type == 11:
165            Value = st.unpack(byteOrd+nVal*'f',File.read(nVal*4))
166        IFD[Tag] = [Type,nVal,Value]
167        if DEBUG: print (Tag,IFD[Tag])
168    sizexy = [IFD[256][2][0],IFD[257][2][0]]
169    [nx,ny] = sizexy
170    Npix = nx*ny
171    time0 = time.time()
172    if 34710 in IFD:
173        print ('Read MAR CCD tiff file: '+filename)
174        marFrame = rmf.marFrame(File,byteOrd,IFD)
175        image = np.flipud(np.array(np.asarray(marFrame.image),dtype=np.int32))
176        tifType = marFrame.filetitle
177        pixy = [marFrame.pixelsizeX/1000.0,marFrame.pixelsizeY/1000.0]
178        head = marFrame.outputHead()
179# extract resonable wavelength from header
180        wavelength = marFrame.sourceWavelength*1e-5
181        wavelength = (marFrame.opticsWavelength > 0) and marFrame.opticsWavelength*1e-5 or wavelength
182        wavelength = (wavelength <= 0) and None or wavelength
183# extract resonable distance from header
184        distance = (marFrame.startXtalToDetector+marFrame.endXtalToDetector)*5e-4
185        distance = (distance <= marFrame.startXtalToDetector*5e-4) and marFrame.xtalToDetector*1e-3 or distance
186        distance = (distance <= 0) and None or distance
187# extract resonable center from header
188        center = [marFrame.beamX*marFrame.pixelsizeX*1e-9,marFrame.beamY*marFrame.pixelsizeY*1e-9]
189        center = (center[0] != 0 and center[1] != 0) and center or [None,None]
190#print head,tifType,pixy
191    elif nSlice > 1:    #CheMin multislice tif file!
192        try:
193            import Image as Im
194        except ImportError:
195            try:
196                from PIL import Image as Im
197            except ImportError:
198                print ("PIL/pillow Image module not present. This TIF cannot be read without this")
199                #raise Exception("PIL/pillow Image module not found")
200                lines = ['not a detector tiff file',]
201                return lines,0,0,0
202        tifType = 'CheMin'
203        pixy = [40.,40.]
204        image = np.flipud(np.array(Im.open(filename)))*10.
205        distance = 18.0
206        center = [pixy[0]*sizexy[0]/2000,0]     #the CheMin beam stop is here
207        wavelength = 1.78892
208    elif 272 in IFD:
209        ifd = IFD[272]
210        File.seek(ifd[2][0])
211        S = File.read(ifd[1])
212        if b'PILATUS' in S:
213            tifType = 'Pilatus'
214            dataType = 0
215            pixy = [172.,172.]
216            File.seek(4096)
217            print ('Read Pilatus tiff file: '+filename)
218            image = np.array(np.frombuffer(File.read(4*Npix),dtype=np.int32),dtype=np.int32)
219        else:
220            if IFD[258][2][0] == 16:
221                if sizexy == [3888,3072] or sizexy == [3072,3888]:
222                    tifType = 'Dexela'
223                    pixy = [74.8,74.8]
224                    print ('Read Dexela detector tiff file: '+filename)
225                else:
226                    tifType = 'GE'
227                    pixy = [200.,200.]
228                    print ('Read GE-detector tiff file: '+filename)
229                File.seek(8)
230                image = np.array(np.frombuffer(File.read(2*Npix),dtype=np.uint16),dtype=np.int32)
231            elif IFD[258][2][0] == 32:
232                # includes CHESS & Pilatus files from Area Detector
233                tifType = 'CHESS'
234                pixy = [200.,200.]
235                File.seek(8)
236                print ('Read as 32-bit unsigned (CHESS) tiff file: '+filename)
237                image = np.array(ar.array('I',File.read(4*Npix)),dtype=np.uint32)
238    elif 270 in IFD:
239        File.seek(IFD[270][2][0])
240        S = File.read(IFD[273][2][0]-IFD[270][2][0])
241        if b'ImageJ' in S:
242            tifType = 'ImageJ'
243            dataType = 0
244            pixy = [200.,200.]*IFD[277][2][0]
245            File.seek(IFD[273][2][0])
246            print ('Read ImageJ tiff file: '+filename)
247            if IFD[258][2][0] == 32:
248                image = File.read(4*Npix)
249                image = np.array(np.frombuffer(image,dtype=byteOrd+'i4'),dtype=np.int32)
250            elif IFD[258][2][0] == 16:
251                image = File.read(2*Npix)
252                pixy = [109.92,109.92]      #for LCLS ImageJ tif files
253                image = np.array(np.frombuffer(image,dtype=byteOrd+'u2'),dtype=np.int32)
254        else:   #gain map from  11-ID-C?
255            pixy = [200.,200.]
256            tifType = 'Gain map'
257            image = File.read(4*Npix)
258            image = np.array(np.frombuffer(image,dtype=byteOrd+'f4')*1000,dtype=np.int32)
259           
260    elif 262 in IFD and IFD[262][2][0] > 4:
261        tifType = 'DND'
262        pixy = [158.,158.]
263        File.seek(512)
264        print ('Read DND SAX/WAX-detector tiff file: '+filename)
265        image = np.array(np.frombuffer(File.read(2*Npix),dtype=np.uint16),dtype=np.int32)
266    elif sizexy == [1536,1536]:
267        tifType = 'APS Gold'
268        pixy = [150.,150.]
269        File.seek(64)
270        print ('Read Gold tiff file:'+filename)
271        image = np.array(np.frombuffer(File.read(2*Npix),dtype=np.uint16),dtype=np.int32)
272    elif sizexy == [2048,2048] or sizexy == [1024,1024] or sizexy == [3072,3072]:
273        if IFD[273][2][0] == 8:
274            if IFD[258][2][0] == 32:
275                tifType = 'PE'
276                pixy = [200.,200.]
277                File.seek(8)
278                print ('Read APS PE-detector tiff file: '+filename)
279                if dataType == 5:
280                    image = np.array(np.frombuffer(File.read(4*Npix),dtype=np.float32),dtype=np.int32)  #fastest
281                else:
282                    image = np.array(np.frombuffer(File.read(4*Npix),dtype=np.int32),dtype=np.int32)
283            elif IFD[258][2][0] == 16: 
284                tifType = 'MedOptics D1'
285                pixy = [46.9,46.9]
286                File.seek(8)
287                print ('Read MedOptics D1 tiff file: '+filename)
288                image = np.array(np.frombuffer(File.read(2*Npix),dtype=np.uint16),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        elif IFD[273][2][0] == 512:
301            tifType = '11-ID-C'
302            pixy = [200.,200.]
303            File.seek(512)
304            print ('Read 11-ID-C tiff file: '+filename)
305            image = np.array(np.frombuffer(File.read(2*Npix),dtype=np.uint16),dtype=np.int32)
306                   
307    elif sizexy == [4096,4096]:
308        if IFD[273][2][0] == 8:
309            if IFD[258][2][0] == 16:
310                tifType = 'scanCCD'
311                pixy = [9.,9.]
312                File.seek(8)
313                print ('Read APS scanCCD tiff file: '+filename)
314                image = np.array(ar.array('H',File.read(2*Npix)),dtype=np.int32)
315            elif IFD[258][2][0] == 32:
316                tifType = 'PE4k'
317                pixy = [100.,100.]
318                File.seek(8)
319                print ('Read PE 4Kx4K tiff file: '+filename)
320                image = np.array(np.frombuffer(File.read(4*Npix),dtype=np.float32)/2.**4,dtype=np.int32)
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    elif sizexy == [391,380]:
328        pixy = [109.92,109.92]
329        File.seek(8)
330        image = np.array(np.frombuffer(File.read(2*Npix),dtype=np.int16),dtype=np.int32)
331    elif sizexy == [380,391]:
332        File.seek(110)
333        pixy = [109.92,109.92]
334        image = np.array(np.frombuffer(File.read(Npix),dtype=np.uint8),dtype=np.int32)
335    elif sizexy ==  [825,830]:
336        pixy = [109.92,109.92]
337        File.seek(8)
338        image = np.array(np.frombuffer(File.read(Npix),dtype=np.uint8),dtype=np.int32)
339    elif sizexy ==  [1800,1800]:
340        pixy = [109.92,109.92]
341        File.seek(110)
342        image = np.array(np.frombuffer(File.read(Npix),dtype=np.uint8),dtype=np.int32)
343    elif sizexy == [2880,2880]:
344        pixy = [150.,150.]
345        File.seek(8)
346        dt = np.dtype(np.float32)
347        dt = dt.newbyteorder(byteOrd)
348        image = np.array(np.frombuffer(File.read(Npix*4),dtype=dt),dtype=np.int32)
349#    elif sizexy == [960,960]:
350#        tiftype = 'PE-BE'
351#        pixy = (200,200)
352#        File.seek(8)
353#        if not imageOnly:
354#            print 'Read Gold tiff file:',filename
355#        image = np.array(ar.array('H',File.read(2*Npix)),dtype=np.int32)
356           
357    if image is None:
358        lines = ['not a known detector tiff file',]
359        return lines,0,0,0
360       
361    if sizexy[1]*sizexy[0] != image.size: # test is resize is allowed
362        lines = ['not a known detector tiff file',]
363        return lines,0,0,0
364    print ('image read time: %.3f'%(time.time()-time0))
365    image = np.reshape(image,(sizexy[1],sizexy[0]))
366    center = (not center[0]) and [pixy[0]*sizexy[0]/2000,pixy[1]*sizexy[1]/2000] or center
367    wavelength = (not wavelength) and 0.10 or wavelength
368    distance = (not distance) and 100.0 or distance
369    polarization = (not polarization) and 0.99 or polarization
370    samplechangerpos = (not samplechangerpos) and 0.0 or samplechangerpos
371    data = {'pixelSize':pixy,'wavelength':wavelength,'distance':distance,'center':center,'size':sizexy,
372            'setdist':distance,'PolaVal':[polarization,False],'samplechangerpos':samplechangerpos}
373    File.close()   
374    return head,data,Npix,image
Note: See TracBrowser for help on using the repository browser.