source: trunk/imports/G2img_1TIF.py @ 4021

Last change on this file since 4021 was 4021, checked in by toby, 3 years ago

implement filter for screen messages; start to replace print() with G2Print(); scripting changes for PDF

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