source: trunk/imports/G2img_1TIF.py @ 3160

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

fix new PE importer; it was a 32bit float image not int.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Date Author Revision URL Id
File size: 16.1 KB
Line 
1# -*- coding: utf-8 -*-
2########### SVN repository information ###################
3# $Date: 2017-11-23 17:46:20 +0000 (Thu, 23 Nov 2017) $
4# $Author: vondreele $
5# $Revision: 3160 $
6# $URL: trunk/imports/G2img_1TIF.py $
7# $Id: G2img_1TIF.py 3160 2017-11-23 17:46:20Z 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: 3160 $")
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 = ar.array('I',File.read(4*Npix))
213            image = np.array(np.asarray(image),dtype=np.int32)
214        else:
215            if IFD[258][2][0] == 16:
216                tifType = 'GE'
217                pixy = [200.,200.]
218                File.seek(8)
219                print ('Read GE-detector tiff file: '+filename)
220                image = np.array(np.frombuffer(File.read(2*Npix),dtype=np.uint16),dtype=np.int32)
221#                image = np.fromfile(File,dtype=np.int16,count=2*Npix)[:Npix]
222#                image = np.array(ar.array('H',File.read(2*Npix)),dtype=np.int32)
223            elif IFD[258][2][0] == 32:
224                # includes CHESS & Pilatus files from Area Detector
225                tifType = 'CHESS'
226                pixy = [200.,200.]
227                File.seek(8)
228                print ('Read as 32-bit unsigned (CHESS) tiff file: '+filename)
229                image = np.array(ar.array('I',File.read(4*Npix)),dtype=np.uint32)
230    elif 270 in IFD:
231        File.seek(IFD[270][2][0])
232        S = File.read(IFD[273][2][0]-IFD[270][2][0])
233        if b'ImageJ' in S:
234            tifType = 'ImageJ'
235            dataType = 0
236            pixy = [200.,200.]*IFD[277][2][0]
237            File.seek(IFD[273][2][0])
238            print ('Read ImageJ tiff file: '+filename)
239            if IFD[258][2][0] == 32:
240                image = File.read(4*Npix)
241                image = np.array(np.frombuffer(image,dtype=byteOrd+'i4'),dtype=np.int32)
242            elif IFD[258][2][0] == 16:
243                image = File.read(2*Npix)
244                pixy = [109.92,109.92]      #for LCLS ImageJ tif files
245                image = np.array(np.frombuffer(image,dtype=byteOrd+'u2'),dtype=np.int32)
246        else:   #gain map from  11-ID-C?
247            pixy = [200.,200.]
248            tifType = 'Gain map'
249            image = File.read(4*Npix)
250            image = np.array(np.frombuffer(image,dtype=byteOrd+'f4')*1000,dtype=np.int32)
251           
252    elif 262 in IFD and IFD[262][2][0] > 4:
253        tifType = 'DND'
254        pixy = [158.,158.]
255        File.seek(512)
256        print ('Read DND SAX/WAX-detector tiff file: '+filename)
257        image = np.array(np.frombuffer(File.read(2*Npix),dtype=np.uint16),dtype=np.int32)
258#        image = np.fromfile(File,dtype=np.int16,count=2*Npix)[:Npix]
259#        image = np.array(ar.array('H',File.read(2*Npix)),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#        image = np.fromfile(File,dtype=np.int16,count=2*Npix)[:Npix]
267#        image = np.array(ar.array('H',File.read(2*Npix)),dtype=np.int32)
268    elif sizexy == [2048,2048] or sizexy == [1024,1024] or sizexy == [3072,3072]:
269        if IFD[273][2][0] == 8:
270            if IFD[258][2][0] == 32:
271                tifType = 'PE'
272                pixy = [200.,200.]
273                File.seek(8)
274                print ('Read APS PE-detector tiff file: '+filename)
275                if dataType == 5:
276                    image = np.array(np.frombuffer(File.read(4*Npix),dtype=np.float32),dtype=np.int32)  #fastest
277#                    image = np.fromfile(File,dtype=np.float32,count=4*Npix)[:Npix]
278#                    image = np.array(ar.array('f',File.read(4*Npix)),dtype=np.int32)
279                else:
280                    image = np.array(np.frombuffer(File.read(4*Npix),dtype=np.int32),dtype=np.int32)
281#                    image = np.fromfile(File,dtype=np.int,count=4*Npix)[:Npix]
282#                    image = np.array(ar.array('I',File.read(4*Npix)),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#                image = np.array(ar.array('H',File.read(2*Npix)),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            print ('Read MAR CCD tiff file: '+filename)
300            image = np.array(np.frombuffer(File.read(2*Npix),dtype=np.uint16),dtype=np.int32)
301#            image = np.fromfile(File,dtype=np.int16,count=2*Npix)[:Npix]
302#            image = np.array(ar.array('H',File.read(2*Npix)),dtype=np.int32)
303        elif IFD[273][2][0] == 512:
304            tifType = '11-ID-C'
305            pixy = [200.,200.]
306            File.seek(512)
307            print ('Read 11-ID-C tiff file: '+filename)
308            image = np.array(np.frombuffer(File.read(2*Npix),dtype=np.uint16),dtype=np.int32)
309#            image = np.array(ar.array('H',File.read(2*Npix)),dtype=np.int32)
310                   
311    elif sizexy == [4096,4096]:
312        if IFD[273][2][0] == 8:
313            if IFD[258][2][0] == 16:
314                tifType = 'scanCCD'
315                pixy = [9.,9.]
316                File.seek(8)
317                print ('Read APS scanCCD tiff file: '+filename)
318                image = np.array(ar.array('H',File.read(2*Npix)),dtype=np.int32)
319            elif IFD[258][2][0] == 32:
320                tifType = 'PE4k'
321                pixy = [100.,100.]
322                File.seek(8)
323                print ('Read PE 4Kx4K tiff file: '+filename)
324                image = np.array(np.frombuffer(File.read(4*Npix),dtype=np.float32)/2.**4,dtype=np.int32)
325        elif IFD[273][2][0] == 4096:
326            tifType = 'Rayonix'
327            pixy = [73.242,73.242]
328            File.seek(4096)
329            print ('Read Rayonix MX300HE tiff file: '+filename)
330            image = np.array(np.frombuffer(File.read(2*Npix),dtype=np.uint16),dtype=np.int32)
331    elif sizexy == [391,380]:
332        pixy = [109.92,109.92]
333        File.seek(8)
334        image = np.array(np.frombuffer(File.read(2*Npix),dtype=np.int16),dtype=np.int32)
335    elif sizexy == [380,391]:
336        File.seek(110)
337        pixy = [109.92,109.92]
338        image = np.array(np.frombuffer(File.read(Npix),dtype=np.uint8),dtype=np.int32)
339    elif sizexy ==  [825,830]:
340        pixy = [109.92,109.92]
341        File.seek(8)
342        image = np.array(np.frombuffer(File.read(Npix),dtype=np.uint8),dtype=np.int32)
343    elif sizexy ==  [1800,1800]:
344        pixy = [109.92,109.92]
345        File.seek(110)
346        image = np.array(np.frombuffer(File.read(Npix),dtype=np.uint8),dtype=np.int32)
347    elif sizexy == [2880,2880]:
348        pixy = [150.,150.]
349        File.seek(8)
350        dt = np.dtype(np.float32)
351        dt = dt.newbyteorder(byteOrd)
352        image = np.array(np.frombuffer(File.read(Npix*4),dtype=dt),dtype=np.int32)
353#    elif sizexy == [960,960]:
354#        tiftype = 'PE-BE'
355#        pixy = (200,200)
356#        File.seek(8)
357#        if not imageOnly:
358#            print 'Read Gold tiff file:',filename
359#        image = np.array(ar.array('H',File.read(2*Npix)),dtype=np.int32)
360           
361    if image is None:
362        lines = ['not a known detector tiff file',]
363        return lines,0,0,0
364       
365    if sizexy[1]*sizexy[0] != image.size: # test is resize is allowed
366        lines = ['not a known detector tiff file',]
367        return lines,0,0,0
368    print ('image read time: %.3f'%(time.time()-time0))
369    image = np.reshape(image,(sizexy[1],sizexy[0]))
370    center = (not center[0]) and [pixy[0]*sizexy[0]/2000,pixy[1]*sizexy[1]/2000] or center
371    wavelength = (not wavelength) and 0.10 or wavelength
372    distance = (not distance) and 100.0 or distance
373    polarization = (not polarization) and 0.99 or polarization
374    data = {'pixelSize':pixy,'wavelength':wavelength,'distance':distance,'center':center,'size':sizexy,
375            'setdist':distance,'PolaVal':[polarization,False]}
376    File.close()   
377    return head,data,Npix,image
Note: See TracBrowser for help on using the repository browser.