source: trunk/imports/G2img_1TIF.py @ 2068

Last change on this file since 2068 was 2068, checked in by toby, 8 years ago

cleanup image reader documetation

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