source: trunk/imports/G2img_1TIF.py @ 3194

Last change on this file since 3194 was 3194, checked in by vondreele, 5 years ago

fix to CifFile?
fixes to cbf & tif importers for new Pilatus 2M detector
fixes to mag structure display

  • Property svn:eol-style set to native
  • Property svn:keywords set to Date Author Revision URL Id
File size: 15.2 KB
Line 
1# -*- coding: utf-8 -*-
2########### SVN repository information ###################
3# $Date: 2017-12-15 19:19:06 +0000 (Fri, 15 Dec 2017) $
4# $Author: vondreele $
5# $Revision: 3194 $
6# $URL: trunk/imports/G2img_1TIF.py $
7# $Id: G2img_1TIF.py 3194 2017-12-15 19:19:06Z 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: 3194 $")
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    if DEBUG: print('byteorder:',byteOrd)
140    for ied in range(NED):
141        Tag,Type = st.unpack(byteOrd+'Hh',File.read(4))
142        nVal = st.unpack(byteOrd+'i',File.read(4))[0]
143        if DEBUG: print ('Try:',Tag,Type,nVal)
144        if Type == 1:
145            Value = st.unpack(byteOrd+nVal*'b',File.read(nVal))
146        elif Type == 2:
147            Value = st.unpack(byteOrd+'i',File.read(4))
148        elif Type == 3:
149            Value = st.unpack(byteOrd+nVal*'h',File.read(nVal*2))
150            st.unpack(byteOrd+nVal*'h',File.read(nVal*2))
151        elif Type == 4:
152            if Tag in [273,279]:
153                nSlice = nVal
154                nVal = 1
155            Value = st.unpack(byteOrd+nVal*'i',File.read(nVal*4))
156        elif Type == 5:
157            Value = st.unpack(byteOrd+nVal*'i',File.read(nVal*4))
158        elif Type == 11:
159            Value = st.unpack(byteOrd+nVal*'f',File.read(nVal*4))
160        IFD[Tag] = [Type,nVal,Value]
161        if DEBUG: print (Tag,IFD[Tag])
162    sizexy = [IFD[256][2][0],IFD[257][2][0]]
163    [nx,ny] = sizexy
164    Npix = nx*ny
165    time0 = time.time()
166    if 34710 in IFD:
167        print ('Read MAR CCD tiff file: '+filename)
168        marFrame = rmf.marFrame(File,byteOrd,IFD)
169        image = np.flipud(np.array(np.asarray(marFrame.image),dtype=np.int32))
170        tifType = marFrame.filetitle
171        pixy = [marFrame.pixelsizeX/1000.0,marFrame.pixelsizeY/1000.0]
172        head = marFrame.outputHead()
173# extract resonable wavelength from header
174        wavelength = marFrame.sourceWavelength*1e-5
175        wavelength = (marFrame.opticsWavelength > 0) and marFrame.opticsWavelength*1e-5 or wavelength
176        wavelength = (wavelength <= 0) and None or wavelength
177# extract resonable distance from header
178        distance = (marFrame.startXtalToDetector+marFrame.endXtalToDetector)*5e-4
179        distance = (distance <= marFrame.startXtalToDetector*5e-4) and marFrame.xtalToDetector*1e-3 or distance
180        distance = (distance <= 0) and None or distance
181# extract resonable center from header
182        center = [marFrame.beamX*marFrame.pixelsizeX*1e-9,marFrame.beamY*marFrame.pixelsizeY*1e-9]
183        center = (center[0] != 0 and center[1] != 0) and center or [None,None]
184#print head,tifType,pixy
185    elif nSlice > 1:    #CheMin multislice tif file!
186        try:
187            import Image as Im
188        except ImportError:
189            try:
190                from PIL import Image as Im
191            except ImportError:
192                print ("PIL/pillow Image module not present. This TIF cannot be read without this")
193                #raise Exception("PIL/pillow Image module not found")
194                lines = ['not a detector tiff file',]
195                return lines,0,0,0
196        tifType = 'CheMin'
197        pixy = [40.,40.]
198        image = np.flipud(np.array(Im.open(filename)))*10.
199        distance = 18.0
200        center = [pixy[0]*sizexy[0]/2000,0]     #the CheMin beam stop is here
201        wavelength = 1.78892
202    elif 272 in IFD:
203        ifd = IFD[272]
204        File.seek(ifd[2][0])
205        S = File.read(ifd[1])
206        if b'PILATUS' in S:
207            tifType = 'Pilatus'
208            dataType = 0
209            pixy = [172.,172.]
210            File.seek(4096)
211            print ('Read Pilatus tiff file: '+filename)
212            image = np.array(np.frombuffer(File.read(4*Npix),dtype=np.int32),dtype=np.int32)
213        else:
214            if IFD[258][2][0] == 16:
215                if sizexy == [3888,3072]:
216                    tifType = 'Dexela'
217                    pixy = [74.8,74.8]
218                    print ('Read Dexela detector tiff file: '+filename)
219                else:
220                    tifType = 'GE'
221                    pixy = [200.,200.]
222                    print ('Read GE-detector tiff file: '+filename)
223                File.seek(8)
224                image = np.array(np.frombuffer(File.read(2*Npix),dtype=np.uint16),dtype=np.int32)
225            elif IFD[258][2][0] == 32:
226                # includes CHESS & Pilatus files from Area Detector
227                tifType = 'CHESS'
228                pixy = [200.,200.]
229                File.seek(8)
230                print ('Read as 32-bit unsigned (CHESS) tiff file: '+filename)
231                image = np.array(ar.array('I',File.read(4*Npix)),dtype=np.uint32)
232    elif 270 in IFD:
233        File.seek(IFD[270][2][0])
234        S = File.read(IFD[273][2][0]-IFD[270][2][0])
235        if b'ImageJ' in S:
236            tifType = 'ImageJ'
237            dataType = 0
238            pixy = [200.,200.]*IFD[277][2][0]
239            File.seek(IFD[273][2][0])
240            print ('Read ImageJ tiff file: '+filename)
241            if IFD[258][2][0] == 32:
242                image = File.read(4*Npix)
243                image = np.array(np.frombuffer(image,dtype=byteOrd+'i4'),dtype=np.int32)
244            elif IFD[258][2][0] == 16:
245                image = File.read(2*Npix)
246                pixy = [109.92,109.92]      #for LCLS ImageJ tif files
247                image = np.array(np.frombuffer(image,dtype=byteOrd+'u2'),dtype=np.int32)
248        else:   #gain map from  11-ID-C?
249            pixy = [200.,200.]
250            tifType = 'Gain map'
251            image = File.read(4*Npix)
252            image = np.array(np.frombuffer(image,dtype=byteOrd+'f4')*1000,dtype=np.int32)
253           
254    elif 262 in IFD and IFD[262][2][0] > 4:
255        tifType = 'DND'
256        pixy = [158.,158.]
257        File.seek(512)
258        print ('Read DND SAX/WAX-detector tiff file: '+filename)
259        image = np.array(np.frombuffer(File.read(2*Npix),dtype=np.uint16),dtype=np.int32)
260    elif sizexy == [1536,1536]:
261        tifType = 'APS Gold'
262        pixy = [150.,150.]
263        File.seek(64)
264        print ('Read Gold tiff file:'+filename)
265        image = np.array(np.frombuffer(File.read(2*Npix),dtype=np.uint16),dtype=np.int32)
266    elif sizexy == [2048,2048] or sizexy == [1024,1024] or sizexy == [3072,3072]:
267        if IFD[273][2][0] == 8:
268            if IFD[258][2][0] == 32:
269                tifType = 'PE'
270                pixy = [200.,200.]
271                File.seek(8)
272                print ('Read APS PE-detector tiff file: '+filename)
273                if dataType == 5:
274                    image = np.array(np.frombuffer(File.read(4*Npix),dtype=np.float32),dtype=np.int32)  #fastest
275                else:
276                    image = np.array(np.frombuffer(File.read(4*Npix),dtype=np.int32),dtype=np.int32)
277            elif IFD[258][2][0] == 16: 
278                tifType = 'MedOptics D1'
279                pixy = [46.9,46.9]
280                File.seek(8)
281                print ('Read MedOptics D1 tiff file: '+filename)
282                image = np.array(np.frombuffer(File.read(2*Npix),dtype=np.uint16),dtype=np.int32)
283                 
284        elif IFD[273][2][0] == 4096:
285            if sizexy[0] == 3072:
286                pixy =  [73.,73.]
287                tifType = 'MAR225'           
288            else:
289                pixy = [158.,158.]
290                tifType = 'MAR325'           
291            File.seek(4096)
292            print ('Read MAR CCD tiff file: '+filename)
293            image = np.array(np.frombuffer(File.read(2*Npix),dtype=np.uint16),dtype=np.int32)
294        elif IFD[273][2][0] == 512:
295            tifType = '11-ID-C'
296            pixy = [200.,200.]
297            File.seek(512)
298            print ('Read 11-ID-C tiff file: '+filename)
299            image = np.array(np.frombuffer(File.read(2*Npix),dtype=np.uint16),dtype=np.int32)
300                   
301    elif sizexy == [4096,4096]:
302        if IFD[273][2][0] == 8:
303            if IFD[258][2][0] == 16:
304                tifType = 'scanCCD'
305                pixy = [9.,9.]
306                File.seek(8)
307                print ('Read APS scanCCD tiff file: '+filename)
308                image = np.array(ar.array('H',File.read(2*Npix)),dtype=np.int32)
309            elif IFD[258][2][0] == 32:
310                tifType = 'PE4k'
311                pixy = [100.,100.]
312                File.seek(8)
313                print ('Read PE 4Kx4K tiff file: '+filename)
314                image = np.array(np.frombuffer(File.read(4*Npix),dtype=np.float32)/2.**4,dtype=np.int32)
315        elif IFD[273][2][0] == 4096:
316            tifType = 'Rayonix'
317            pixy = [73.242,73.242]
318            File.seek(4096)
319            print ('Read Rayonix MX300HE tiff file: '+filename)
320            image = np.array(np.frombuffer(File.read(2*Npix),dtype=np.uint16),dtype=np.int32)
321    elif sizexy == [391,380]:
322        pixy = [109.92,109.92]
323        File.seek(8)
324        image = np.array(np.frombuffer(File.read(2*Npix),dtype=np.int16),dtype=np.int32)
325    elif sizexy == [380,391]:
326        File.seek(110)
327        pixy = [109.92,109.92]
328        image = np.array(np.frombuffer(File.read(Npix),dtype=np.uint8),dtype=np.int32)
329    elif sizexy ==  [825,830]:
330        pixy = [109.92,109.92]
331        File.seek(8)
332        image = np.array(np.frombuffer(File.read(Npix),dtype=np.uint8),dtype=np.int32)
333    elif sizexy ==  [1800,1800]:
334        pixy = [109.92,109.92]
335        File.seek(110)
336        image = np.array(np.frombuffer(File.read(Npix),dtype=np.uint8),dtype=np.int32)
337    elif sizexy == [2880,2880]:
338        pixy = [150.,150.]
339        File.seek(8)
340        dt = np.dtype(np.float32)
341        dt = dt.newbyteorder(byteOrd)
342        image = np.array(np.frombuffer(File.read(Npix*4),dtype=dt),dtype=np.int32)
343#    elif sizexy == [960,960]:
344#        tiftype = 'PE-BE'
345#        pixy = (200,200)
346#        File.seek(8)
347#        if not imageOnly:
348#            print 'Read Gold tiff file:',filename
349#        image = np.array(ar.array('H',File.read(2*Npix)),dtype=np.int32)
350           
351    if image is None:
352        lines = ['not a known detector tiff file',]
353        return lines,0,0,0
354       
355    if sizexy[1]*sizexy[0] != image.size: # test is resize is allowed
356        lines = ['not a known detector tiff file',]
357        return lines,0,0,0
358    print ('image read time: %.3f'%(time.time()-time0))
359    image = np.reshape(image,(sizexy[1],sizexy[0]))
360    center = (not center[0]) and [pixy[0]*sizexy[0]/2000,pixy[1]*sizexy[1]/2000] or center
361    wavelength = (not wavelength) and 0.10 or wavelength
362    distance = (not distance) and 100.0 or distance
363    polarization = (not polarization) and 0.99 or polarization
364    data = {'pixelSize':pixy,'wavelength':wavelength,'distance':distance,'center':center,'size':sizexy,
365            'setdist':distance,'PolaVal':[polarization,False]}
366    File.close()   
367    return head,data,Npix,image
Note: See TracBrowser for help on using the repository browser.