source: trunk/imports/G2img_1TIF.py @ 2774

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

implement MC/SA for reflectometry
more image importer speed ups

  • Property svn:eol-style set to native
  • Property svn:keywords set to Date Author Revision URL Id
File size: 15.0 KB
Line 
1# -*- coding: utf-8 -*-
2########### SVN repository information ###################
3# $Date: 2017-04-07 21:05:51 +0000 (Fri, 07 Apr 2017) $
4# $Author: vondreele $
5# $Revision: 2774 $
6# $URL: trunk/imports/G2img_1TIF.py $
7# $Id: G2img_1TIF.py 2774 2017-04-07 21:05:51Z 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
21import struct as st
22import GSASIIIO as G2IO
23import GSASIIpath
24import numpy as np
25import time
26DEBUG = False
27GSASIIpath.SetVersionNumber("$Revision: 2774 $")
28class TIF_ReaderClass(G2IO.ImportImage):
29    '''Reads TIF files using a routine (:func:`GetTifData`) that looks
30    for files that can be identified from known instruments and will
31    correct for slightly incorrect TIF usage. If that routine fails,
32    it will be read with a standard TIF reader, which can handle compression
33    and other things less commonly used at beamlines.
34    '''
35    def __init__(self):
36        super(self.__class__,self).__init__( # fancy way to self-reference
37            extensionlist=('.tif','.tiff'),
38            strictExtension=False,
39            formatName = 'TIF image',
40            longFormatName = 'Various .tif and pseudo-TIF formats'
41            )
42
43    def ContentsValidator(self, filepointer):
44        '''Does the header match the required TIF header?
45        '''
46        tag = filepointer.read(2)
47        if tag == 'II' and int(st.unpack('<h',filepointer.read(2))[0]) == 42: #little endian
48            pass
49        elif tag == 'MM' and int(st.unpack('>h',filepointer.read(2))[0]) == 42: #big endian
50            pass
51        else:
52            return False # header not found; not valid TIF
53        return True
54   
55    def Reader(self,filename,filepointer, ParentFrame=None, **unused):
56        '''Read the TIF file using :func:`GetTifData`. If that fails,
57        use :func:`scipy.misc.imread` and give the user a chance to
58        edit the likely wrong default image parameters.
59        '''
60       
61        self.Comments,self.Data,self.Npix,self.Image = GetTifData(filename)
62        if self.Npix == 0:
63            print("GetTifData failed to read "+str(filename)+" Trying SciPy")
64            import scipy.misc
65            self.Image = scipy.misc.imread(filename,flatten=True)
66            self.Npix = self.Image.size
67            if ParentFrame:
68                self.Comments = ['no metadata']
69                self.Data = {'wavelength': 0.1, 'pixelSize': [200, 200], 'distance': 100.0}
70                self.Data['size'] = list(self.Image.shape)
71                self.Data['center'] = [int(i/2) for i in self.Image.shape]
72                G2IO.EditImageParms(ParentFrame,self.Data,self.Comments,self.Image,filename)
73        if self.Npix == 0:
74            return False
75        self.LoadImage(ParentFrame,filename)
76        return True
77
78def GetTifData(filename):
79    '''Read an image in a pseudo-tif format,
80    as produced by a wide variety of software, almost always
81    incorrectly in some way.
82    '''
83    import struct as st
84    import array as ar
85    import ReadMarCCDFrame as rmf
86    image = None
87    File = open(filename,'rb')
88    dataType = 5
89    center = [None,None]
90    wavelength = None
91    distance = None
92    polarization = None
93    try:
94        Meta = open(filename+'.metadata','Ur')
95        head = Meta.readlines()
96        for line in head:
97            line = line.strip()
98            try:
99                if '=' not in line: continue
100                keyword = line.split('=')[0].strip()
101                if 'dataType' == keyword:
102                    dataType = int(line.split('=')[1])
103                elif 'wavelength' == keyword.lower():
104                    wavelength = float(line.split('=')[1])
105                elif 'distance' == keyword.lower():
106                    distance = float(line.split('=')[1])
107                elif 'polarization' == keyword.lower():
108                    polarization = float(line.split('=')[1])
109            except:
110                print('error reading metadata: '+line)
111        Meta.close()
112    except IOError:
113        print 'no metadata file found - will try to read file anyway'
114        head = ['no metadata file found',]
115       
116    tag = File.read(2)
117    byteOrd = '<'
118    if tag == 'II' and int(st.unpack('<h',File.read(2))[0]) == 42:     #little endian
119        IFD = int(st.unpack(byteOrd+'i',File.read(4))[0])
120    elif tag == 'MM' and int(st.unpack('>h',File.read(2))[0]) == 42:   #big endian
121        byteOrd = '>'
122        IFD = int(st.unpack(byteOrd+'i',File.read(4))[0])       
123    else:
124        lines = ['not a detector tiff file',]
125        return lines,0,0,0
126    File.seek(IFD)                                                  #get number of directory entries
127    NED = int(st.unpack(byteOrd+'h',File.read(2))[0])
128    IFD = {}
129    nSlice = 1
130    for ied in range(NED):
131        Tag,Type = st.unpack(byteOrd+'Hh',File.read(4))
132        nVal = st.unpack(byteOrd+'i',File.read(4))[0]
133        if DEBUG: print 'Try:',Tag,Type,nVal
134        if Type == 1:
135            Value = st.unpack(byteOrd+nVal*'b',File.read(nVal))
136        elif Type == 2:
137            Value = st.unpack(byteOrd+'i',File.read(4))
138        elif Type == 3:
139            Value = st.unpack(byteOrd+nVal*'h',File.read(nVal*2))
140            st.unpack(byteOrd+nVal*'h',File.read(nVal*2))
141        elif Type == 4:
142            if Tag in [273,279]:
143                nSlice = nVal
144                nVal = 1
145            Value = st.unpack(byteOrd+nVal*'i',File.read(nVal*4))
146        elif Type == 5:
147            Value = st.unpack(byteOrd+nVal*'i',File.read(nVal*4))
148        elif Type == 11:
149            Value = st.unpack(byteOrd+nVal*'f',File.read(nVal*4))
150        IFD[Tag] = [Type,nVal,Value]
151        if DEBUG: print Tag,IFD[Tag]
152    sizexy = [IFD[256][2][0],IFD[257][2][0]]
153    [nx,ny] = sizexy
154    Npix = nx*ny
155    time0 = time.time()
156    if 34710 in IFD:
157        print 'Read MAR CCD tiff file: ',filename
158        marFrame = rmf.marFrame(File,byteOrd,IFD)
159        image = np.flipud(np.array(np.asarray(marFrame.image),dtype=np.int32))
160        tifType = marFrame.filetitle
161        pixy = [marFrame.pixelsizeX/1000.0,marFrame.pixelsizeY/1000.0]
162        head = marFrame.outputHead()
163# extract resonable wavelength from header
164        wavelength = marFrame.sourceWavelength*1e-5
165        wavelength = (marFrame.opticsWavelength > 0) and marFrame.opticsWavelength*1e-5 or wavelength
166        wavelength = (wavelength <= 0) and None or wavelength
167# extract resonable distance from header
168        distance = (marFrame.startXtalToDetector+marFrame.endXtalToDetector)*5e-4
169        distance = (distance <= marFrame.startXtalToDetector*5e-4) and marFrame.xtalToDetector*1e-3 or distance
170        distance = (distance <= 0) and None or distance
171# extract resonable center from header
172        center = [marFrame.beamX*marFrame.pixelsizeX*1e-9,marFrame.beamY*marFrame.pixelsizeY*1e-9]
173        center = (center[0] != 0 and center[1] != 0) and center or [None,None]
174#print head,tifType,pixy
175    elif nSlice > 1:    #CheMin multislice tif file!
176        try:
177            import Image as Im
178        except ImportError:
179            try:
180                from PIL import Image as Im
181            except ImportError:
182                print "PIL/pillow Image module not present. This TIF cannot be read without this"
183                #raise Exception("PIL/pillow Image module not found")
184                lines = ['not a detector tiff file',]
185                return lines,0,0,0
186        tifType = 'CheMin'
187        pixy = [40,40]
188        image = np.flipud(np.array(Im.open(filename)))*10.
189        distance = 18.0
190        center = [pixy[0]*sizexy[0]/2000,0]     #the CheMin beam stop is here
191        wavelength = 1.78892
192    elif 272 in IFD:
193        ifd = IFD[272]
194        File.seek(ifd[2][0])
195        S = File.read(ifd[1])
196        if 'PILATUS' in S:
197            tifType = 'Pilatus'
198            dataType = 0
199            pixy = [172,172]
200            File.seek(4096)
201            print 'Read Pilatus tiff file: ',filename
202            image = ar.array('I',File.read(4*Npix))
203            image = np.array(np.asarray(image),dtype=np.int32)
204        else:
205            if IFD[258][2][0] == 16:
206                tifType = 'GE'
207                pixy = [200,200]
208                File.seek(8)
209                print 'Read GE-detector tiff file: ',filename
210                image = np.array(np.frombuffer(File.read(2*Npix),dtype=np.uint16),dtype=np.int32)
211#                image = np.fromfile(File,dtype=np.int16,count=2*Npix)[:Npix]
212#                image = np.array(ar.array('H',File.read(2*Npix)),dtype=np.int32)
213            elif IFD[258][2][0] == 32:
214                tifType = 'CHESS'
215                pixy = [200,200]
216                File.seek(8)
217                print 'Read CHESS-detector tiff file: ',filename
218                image = np.array(ar.array('I',File.read(4*Npix)),dtype=np.int32)
219    elif 270 in IFD:
220        File.seek(IFD[270][2][0])
221        S = File.read(IFD[273][2][0]-IFD[270][2][0])
222        if 'ImageJ' in S:
223            tifType = 'ImageJ'
224            dataType = 0
225            pixy = [200,200]*IFD[277][2][0]
226            File.seek(IFD[273][2][0])
227            print 'Read ImageJ tiff file: ',filename
228#            image = ar.array('H',File.read(2*Npix))
229            image = File.read(2*Npix,dtype=np.uint16)
230            if '>' in byteOrd:
231                image.byteswap()
232            image = np.array(np.frombuffer(image),dtype=np.int32)
233#            image = np.array(np.asarray(image,dtype='H'),dtype=np.int32)           
234    elif 262 in IFD and IFD[262][2][0] > 4:
235        tifType = 'DND'
236        pixy = [158,158]
237        File.seek(512)
238        print 'Read DND SAX/WAX-detector tiff file: ',filename
239        image = np.array(np.frombuffer(File.read(2*Npix),dtype=np.uint16),dtype=np.int32)
240#        image = np.fromfile(File,dtype=np.int16,count=2*Npix)[:Npix]
241#        image = np.array(ar.array('H',File.read(2*Npix)),dtype=np.int32)
242    elif sizexy == [1536,1536]:
243        tifType = 'APS Gold'
244        pixy = [150,150]
245        File.seek(64)
246        print 'Read Gold tiff file:',filename
247        image = np.array(np.frombuffer(File.read(2*Npix),dtype=np.uint16),dtype=np.int32)
248#        image = np.fromfile(File,dtype=np.int16,count=2*Npix)[:Npix]
249#        image = np.array(ar.array('H',File.read(2*Npix)),dtype=np.int32)
250    elif sizexy == [2048,2048] or sizexy == [1024,1024] or sizexy == [3072,3072]:
251        if IFD[273][2][0] == 8:
252            if IFD[258][2][0] == 32:
253                tifType = 'PE'
254                pixy = [200,200]
255                File.seek(8)
256                print 'Read APS PE-detector tiff file: ',filename
257                if dataType == 5:
258                    image = np.array(np.frombuffer(File.read(4*Npix),dtype=np.float32),dtype=np.int32)  #fastest
259#                    image = np.fromfile(File,dtype=np.float32,count=4*Npix)[:Npix]
260#                    image = np.array(ar.array('f',File.read(4*Npix)),dtype=np.int32)
261                else:
262                    image = np.array(np.frombuffer(File.read(4*Npix),dtype=np.int),dtype=np.int32)
263#                    image = np.fromfile(File,dtype=np.int,count=4*Npix)[:Npix]
264#                    image = np.array(ar.array('I',File.read(4*Npix)),dtype=np.int32)
265            elif IFD[258][2][0] == 16: 
266                tifType = 'MedOptics D1'
267                pixy = [46.9,46.9]
268                File.seek(8)
269                print 'Read MedOptics D1 tiff file: ',filename
270                image = np.array(np.frombuffer(File.read(2*Npix),dtype=np.uint16),dtype=np.int32)
271#                image = np.array(ar.array('H',File.read(2*Npix)),dtype=np.int32)
272                 
273        elif IFD[273][2][0] == 4096:
274            if sizexy[0] == 3072:
275                pixy =  [73,73]
276                tifType = 'MAR225'           
277            else:
278                pixy = [158,158]
279                tifType = 'MAR325'           
280            File.seek(4096)
281            print 'Read MAR CCD tiff file: ',filename
282            image = np.array(np.frombuffer(File.read(2*Npix),dtype=np.uint16),dtype=np.int32)
283#            image = np.fromfile(File,dtype=np.int16,count=2*Npix)[:Npix]
284#            image = np.array(ar.array('H',File.read(2*Npix)),dtype=np.int32)
285        elif IFD[273][2][0] == 512:
286            tifType = '11-ID-C'
287            pixy = [200,200]
288            File.seek(512)
289            print 'Read 11-ID-C tiff file: ',filename
290            image = np.array(np.frombuffer(File.read(2*Npix),dtype=np.uint16),dtype=np.int32)
291#            image = np.array(ar.array('H',File.read(2*Npix)),dtype=np.int32)
292                   
293    elif sizexy == [4096,4096]:
294        if IFD[273][2][0] == 8:
295            if IFD[258][2][0] == 16:
296                tifType = 'scanCCD'
297                pixy = [9,9]
298                File.seek(8)
299                print 'Read APS scanCCD tiff file: ',filename
300                image = np.array(ar.array('H',File.read(2*Npix)),dtype=np.int32)
301            elif IFD[258][2][0] == 32:
302                tifType = 'PE4k'
303                pixy = [100,100]
304                File.seek(8)
305                print 'Read PE 4Kx4K tiff file: ',filename
306                image = np.array(np.frombuffer(File.read(4*Npix),dtype=np.float32)/2.**4,dtype=np.int32)
307#                image = np.fromfile(File,dtype=np.uint,count=4*Npix)[:Npix]
308#                if np.max(image) > 2**31:
309#                    image = np.array(image-2**30,dtype=np.int32)
310#                else:
311#                    image = np.array(image,dtype=np.int32)
312#                arry = ar.array('I',File.read(4*Npix))
313#                image = np.array(arry)/2**16           
314        elif IFD[273][2][0] == 4096:
315            tifType = 'Rayonix'
316            pixy = [73.242,73.242]
317            File.seek(4096)
318            print 'Read Rayonix MX300HE tiff file: ',filename
319            image = np.array(np.frombuffer(File.read(2*Npix),dtype=np.uint16),dtype=np.int32)
320#            image = np.fromfile(File,dtype=np.int16,count=2*Npix)[:Npix]
321#            image = np.array(ar.array('H',File.read(2*Npix)),dtype=np.int32)
322#    elif sizexy == [960,960]:
323#        tiftype = 'PE-BE'
324#        pixy = (200,200)
325#        File.seek(8)
326#        if not imageOnly:
327#            print 'Read Gold tiff file:',filename
328#        image = np.array(ar.array('H',File.read(2*Npix)),dtype=np.int32)
329           
330    if image is None:
331        lines = ['not a known detector tiff file',]
332        return lines,0,0,0
333       
334    if sizexy[1]*sizexy[0] != image.size: # test is resize is allowed
335        lines = ['not a known detector tiff file',]
336        return lines,0,0,0
337    print 'image read time: %.3f'%(time.time()-time0)
338    image = np.reshape(image,(sizexy[1],sizexy[0]))
339    center = (not center[0]) and [pixy[0]*sizexy[0]/2000,pixy[1]*sizexy[1]/2000] or center
340    wavelength = (not wavelength) and 0.10 or wavelength
341    distance = (not distance) and 100.0 or distance
342    polarization = (not polarization) and 0.99 or polarization
343    data = {'pixelSize':pixy,'wavelength':wavelength,'distance':distance,'center':center,'size':sizexy,
344            'setdist':distance,'PolaVal':[polarization,False]}
345    File.close()   
346    return head,data,Npix,image
Note: See TracBrowser for help on using the repository browser.