# -*- coding: utf-8 -*-
'''
*Module G2img_pixirad_1ID_16bit.py: 16-bit Pixirad TIF*
----------------------------------------------------------
Adaptation of G2img_1ID_32bit_TIFsum.py for use with the 1ID SAXS pixirad.
Used at 1-ID with normalized 16bit Pixirad TIF for rapid access measurement
'''
from __future__ import division, print_function
import struct as st
from .. import GSASIIobj as G2obj
from .. import GSASIIfiles as G2fil
import numpy as np
import time
DEBUG = False
[docs]
class TIF_ReaderClass(G2obj.ImportImage):
'''Reads TIF files using a routine (:func:`GetTifData`) that looks
for files that can be identified from known instruments and will
correct for slightly incorrect TIF usage. If that routine fails,
it will be read with a standard TIF reader, which can handle compression
and other things less commonly used at beamlines.
'''
def __init__(self):
super(self.__class__,self).__init__( # fancy way to self-reference
extensionlist=('.tif'),
strictExtension=True,
formatName = '1ID normalized 16bit Pixirad TIF',
longFormatName = '1ID normalized 16bit Pixirad TIF generated by Matlab batch summation script'
)
self.scriptable = True
[docs]
def ContentsValidator(self, filename):
'''Does the header match the required TIF header?
'''
fp = open(filename,'rb')
tag = fp.read(2)
if 'bytes' in str(type(tag)):
tag = tag.decode('latin-1')
if tag == 'II' and int(st.unpack('<h',fp.read(2))[0]) == 42: #little endian
pass
elif tag == 'MM' and int(st.unpack('>h',fp.read(2))[0]) == 42: #big endian
pass
else:
return False # header not found; not valid TIF
fp.close()
fp.close()
return True
[docs]
def Reader(self,filename, ParentFrame=None, **unused):
'''Read the TIF file using :func:`GetTifData`.
'''
self.Comments,self.Data,self.Npix,self.Image = GetTifData(filename)
if self.Npix == 0:
G2fil.G2Print("GetTifData failed to read "+str(filename)+" Trying PIL")
import PIL.Image as PI
self.Image = PI.open(filename,mode='r')
self.Npix = self.Image.size
self.Data = {}
if ParentFrame:
self.SciPy = True
self.Comments = ['no metadata']
self.Data = {'wavelength': 0.172973, 'pixelSize': [62., 62.], 'distance': 6450.0}
try:
self.Data['size'] = list(self.Image.shape)
except:
return False
self.Data['center'] = [int(i/2) for i in self.Image.shape]
if self.Npix == 0:
return False
self.Data.update({'samplechangerpos':None,'det2theta':0.0})
self.LoadImage(ParentFrame,filename)
if DEBUG:
print('self.data =',self.Data)
return True
[docs]
def GetTifData(filename):
'''Confirm that the file is in fact a 16bit tiff image with the correct
parameters. Will nearly always throw an error unless used with the 1ID
GSASII workflow, which assigns the proper tags and converts the Pixirad
tiff images into the 16bit format with a different buffer in order to hold
the larger amount of data in each pixel.
'''
import struct as st
#import ReadMarCCDFrame as rmf
image = None
File = open(filename,'rb')
dataType = 5
center = [None,None]
wavelength = None
distance = None
polarization = None
DEBUG = False
try:
Meta = open(filename+'.metadata','r')
head = Meta.readlines()
for line in head:
line = line.strip()
try:
if '=' not in line: continue
keyword = line.split('=')[0].strip()
if 'dataType' == keyword:
dataType = int(line.split('=')[1])
elif 'wavelength' == keyword.lower():
wavelength = float(line.split('=')[1])
elif 'distance' == keyword.lower():
distance = float(line.split('=')[1])
elif 'polarization' == keyword.lower():
polarization = float(line.split('=')[1])
except:
print('error reading metadata: '+line)
Meta.close()
except IOError:
print ('no metadata file found - will try to read file anyway')
head = ['no metadata file found',]
tag = File.read(2)
if 'bytes' in str(type(tag)):
tag = tag.decode('latin-1')
byteOrd = '<'
if tag == 'II' and int(st.unpack('<h',File.read(2))[0]) == 42: #little endian
IFD = int(st.unpack(byteOrd+'i',File.read(4))[0])
elif tag == 'MM' and int(st.unpack('>h',File.read(2))[0]) == 42: #big endian
byteOrd = '>'
IFD = int(st.unpack(byteOrd+'i',File.read(4))[0])
else:
print (tag)
lines = ['not a detector tiff file',]
return lines,0,0,0
File.seek(IFD) #get number of directory entries
NED = int(st.unpack(byteOrd+'h',File.read(2))[0])
IFD = {}
nSlice = 1
if DEBUG: print('byteorder:',byteOrd)
for ied in range(NED):
Tag,Type = st.unpack(byteOrd+'Hh',File.read(4))
nVal = st.unpack(byteOrd+'i',File.read(4))[0]
if DEBUG: print ('Try:',Tag,Type,nVal)
if Type == 1:
Value = st.unpack(byteOrd+nVal*'b',File.read(nVal))
elif Type == 2:
Value = st.unpack(byteOrd+'i',File.read(4))
elif Type == 3:
Value = st.unpack(byteOrd+nVal*'h',File.read(nVal*2))
st.unpack(byteOrd+nVal*'h',File.read(nVal*2))
elif Type == 4:
if Tag in [273,279]:
nSlice = nVal
nVal = 1
Value = st.unpack(byteOrd+nVal*'i',File.read(nVal*4))
elif Type == 5:
Value = st.unpack(byteOrd+nVal*'i',File.read(nVal*4))
elif Type == 11:
Value = st.unpack(byteOrd+nVal*'f',File.read(nVal*4))
IFD[Tag] = [Type,nVal,Value]
if DEBUG: print (Tag,IFD[Tag])
sizexy = [IFD[256][2][0],IFD[257][2][0]]
[nx,ny] = sizexy
Npix = nx*ny
time0 = time.time()
if DEBUG:
print(IFD) #prints the tiff tags, good for making sure the format is good
'''This is the code that was changed from the original GSASII tiff reading
script, only populates the image variable if certain parameters are met
'''
if IFD[258][2][0] == 16: #summed files are 16 bit to hold the required amount of data
if sizexy == [1024, 402] or sizexy == [402, 1024]: #confirms that it has the proper size
tifType = '1ID summed 16bit Dexela'
pixy = [62.,62.] #sets the pixel size
print ('Read 1ID normalized 16bit Pixirad tiff file: '+filename)
File.seek(0) #goto first pixel
image = np.array(np.frombuffer(File.read(2*Npix),dtype=np.int16),dtype=np.int32) #result must be 32 bt like all the others
if image is None:
print('Image is improperly formatted in some way, confirm that this tiff file is being uses properly with the 1ID workflow')
lines = ['Image is improperly formatted in some way',]
return lines,0,0,0
if sizexy[1]*sizexy[0] != image.size: # test is resize is allowed
print('Image size is not consistent with the expected 1024 by 402')
lines = ['Unexpected image size, not 1024 by 402',]
return lines,0,0,0
print ('image read time: %.3f'%(time.time()-time0))
image = np.reshape(image,(sizexy[1],sizexy[0]))
center = (not center[0]) and [pixy[0]*sizexy[0]/2000,pixy[1]*sizexy[1]/2000] or center
wavelength = (not wavelength) and 0.10 or wavelength
distance = (not distance) and 100.0 or distance
polarization = (not polarization) and 0.99 or polarization
data = {'pixelSize':pixy,'wavelength':wavelength,'distance':distance,'center':center,'size':sizexy,
'setdist':distance,'PolaVal':[polarization,False]}
File.close()
return head,data,Npix,image