source: trunk/imports/G2img_1TIF.py @ 4763

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

cleanup tif import for PIL use - remove commented lines
move getAtomPtrs from G2phsGUI to G2math & correct all ses; add a few new ones as well
Add new Atoms/Edit? Atoms/Collect? atoms - it moves atoms to equivalents closest to x, y, z axes, origin or cell center

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