source: trunk/imports/G2img_1TIF.py @ 3176

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

Add A centered monoclinics to super symmetry ptssdict
Add import of Dexela detector tif images

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