source: trunk/imports/G2img_1TIF.py @ 3136

Last change on this file since 3136 was 3136, checked in by vondreele, 6 years ago

make GSAS-II python 3.6 compliant & preserve python 2.7 use;changes:
do from future import division, print_function for all GSAS-II py sources
all menu items revised to be py 2.7/3.6 compliant
all wx.OPEN --> wx.FD_OPEN in file dialogs
all integer divides (typically for image pixel math) made explicit with ; ambiguous ones made floats as appropriate
all print "stuff" --> print (stuff)
all print >> pFile,'stuff' --> pFile.writeCIFtemplate('stuff')
all read file opens made explicit 'r' or 'rb'
all cPickle imports made for py2.7 or 3.6 as cPickle or _pickle; test for '2' platform.version_tuple[0] for py 2.7
define cPickleload to select load(fp) or load(fp,encoding='latin-1') for loading gpx files; provides cross compatibility between py 2.7/3.6 gpx files
make dict.keys() as explicit list(dict.keys()) as needed (NB: possible source of remaining py3.6 bugs)
make zip(a,b) as explicit list(zip(a,b)) as needed (NB: possible source of remaining py3.6 bugs)
select unichr/chr according test for '2' platform.version_tuple[0] for py 2.7 (G2pwdGUI * G2plot) for special characters
select wg.EVT_GRID_CELL_CHANGE (classic) or wg.EVT_GRID_CELL_CHANGED (phoenix) in grid Bind
maxint --> maxsize; used in random number stuff
raise Exception,"stuff" --> raise Exception("stuff")
wx 'classic' sizer.DeleteWindows?() or 'phoenix' sizer.Clear(True)
wx 'classic' SetToolTipString?(text) or 'phoenix' SetToolTip?(wx.ToolTip?(text)); define SetToolTipString?(self,text) to handle the choice in plots
status.SetFields? --> status.SetStatusText?
'classic' AddSimpleTool? or 'phoenix' self.AddTool? for plot toolbar; Bind different as well
define GetItemPydata? as it doesn't exist in wx 'phoenix'
allow python versions 2.7 & 3.6 to run GSAS-II
Bind override commented out - no logging capability (NB: remove all logging code?)
all import ContentsValidator? open filename & test if valid then close; filepointer removed from Reader
binary importers (mostly images) test for 'byte' type & convert as needed to satisfy py 3.6 str/byte rules

  • Property svn:eol-style set to native
  • Property svn:keywords set to Date Author Revision URL Id
File size: 16.4 KB
Line 
1# -*- coding: utf-8 -*-
2########### SVN repository information ###################
3# $Date: 2017-10-23 16:39:16 +0000 (Mon, 23 Oct 2017) $
4# $Author: vondreele $
5# $Revision: 3136 $
6# $URL: trunk/imports/G2img_1TIF.py $
7# $Id: G2img_1TIF.py 3136 2017-10-23 16:39:16Z 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: 3136 $")
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    print (IFD,NED)
138    IFD = {}
139    nSlice = 1
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#            image = ar.array('H',File.read(2*Npix))
240#            image = File.read(2*Npix,dtype=np.uint16)
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#            if '>' in byteOrd:
249#                image.byteswap()
250#            image = np.array(np.frombuffer(image),dtype=np.int32)
251#            image = np.array(np.asarray(image,dtype='H'),dtype=np.int32)           
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.int),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#                image = np.fromfile(File,dtype=np.uint,count=4*Npix)[:Npix]
326#                if np.max(image) > 2**31:
327#                    image = np.array(image-2**30,dtype=np.int32)
328#                else:
329#                    image = np.array(image,dtype=np.int32)
330#                arry = ar.array('I',File.read(4*Npix))
331#                image = np.array(arry)/2**16           
332        elif IFD[273][2][0] == 4096:
333            tifType = 'Rayonix'
334            pixy = [73.242,73.242]
335            File.seek(4096)
336            print ('Read Rayonix MX300HE tiff file: '+filename)
337            image = np.array(np.frombuffer(File.read(2*Npix),dtype=np.uint16),dtype=np.int32)
338#            image = np.fromfile(File,dtype=np.int16,count=2*Npix)[:Npix]
339#            image = np.array(ar.array('H',File.read(2*Npix)),dtype=np.int32)
340    elif sizexy == [391,380]:
341        pixy = [109.92,109.92]
342        File.seek(8)
343        image = np.array(np.frombuffer(File.read(2*Npix),dtype=np.int16),dtype=np.int32)
344    elif sizexy == [380,391]:
345        File.seek(110)
346        pixy = [109.92,109.92]
347        image = np.array(np.frombuffer(File.read(Npix),dtype=np.uint8),dtype=np.int32)
348    elif sizexy ==  [825,830]:
349        pixy = [109.92,109.92]
350        File.seek(8)
351        image = np.array(np.frombuffer(File.read(Npix),dtype=np.uint8),dtype=np.int32)
352    elif sizexy ==  [1800,1800]:
353        pixy = [109.92,109.92]
354        File.seek(110)
355        image = np.array(np.frombuffer(File.read(Npix),dtype=np.uint8),dtype=np.int32)
356#    elif sizexy == [960,960]:
357#        tiftype = 'PE-BE'
358#        pixy = (200,200)
359#        File.seek(8)
360#        if not imageOnly:
361#            print 'Read Gold tiff file:',filename
362#        image = np.array(ar.array('H',File.read(2*Npix)),dtype=np.int32)
363           
364    if image is None:
365        lines = ['not a known detector tiff file',]
366        return lines,0,0,0
367       
368    if sizexy[1]*sizexy[0] != image.size: # test is resize is allowed
369        lines = ['not a known detector tiff file',]
370        return lines,0,0,0
371    print ('image read time: %.3f'%(time.time()-time0))
372    image = np.reshape(image,(sizexy[1],sizexy[0]))
373    center = (not center[0]) and [pixy[0]*sizexy[0]/2000,pixy[1]*sizexy[1]/2000] or center
374    wavelength = (not wavelength) and 0.10 or wavelength
375    distance = (not distance) and 100.0 or distance
376    polarization = (not polarization) and 0.99 or polarization
377    data = {'pixelSize':pixy,'wavelength':wavelength,'distance':distance,'center':center,'size':sizexy,
378            'setdist':distance,'PolaVal':[polarization,False]}
379    File.close()   
380    return head,data,Npix,image
Note: See TracBrowser for help on using the repository browser.