Source code for GSASII.imports.G2pwd_BrukerRAW

# -*- coding: utf-8 -*-
'''
'''
import os
import struct as st
import numpy as np
from .. import GSASIIobj as G2obj
[docs] class raw_ReaderClass(G2obj.ImportPowderData): 'Routines to import powder data from a binary Bruker .RAW file' def __init__(self): super(self.__class__,self).__init__( # fancy way to self-reference extensionlist=('.RAW',), strictExtension=False, formatName = 'Bruker RAW', longFormatName = 'Bruker .RAW powder data file' ) self.scriptable = True # Validate the contents -- make sure we only have valid lines def Read(self,fp,nbytes): data = fp.read(nbytes) if 'bytes' in str(type(data)): data = data.decode('latin-1') return data
[docs] def ContentsValidator(self, filename): 'Look through the file for expected types of lines in a valid Bruker RAW file' fp = open(filename,'rb') head = self.Read(fp,7) if 'bytes' in str(type(head)): head = head.decode('latin-1') if head[:4] == 'RAW ': self.fmtVer = 'Bruker RAW ver. 1' elif head[:4] == 'RAW2': self.fmtVer = 'Bruker RAW ver. 2' elif head == 'RAW1.01': self.fmtVer = 'Bruker RAW ver. 3' elif head == 'RAW4.00': self.fmtVer = 'Bruker RAW ver. 4' pwdrscan = fp.read() nBanks = pwdrscan.count(b'2Theta') if not len(self.selections): self.selections = list(range(nBanks)) self.numbanks = nBanks for i in range(nBanks): self.dnames.append(os.path.basename(filename)+' scan '+(str(i))) else: self.errors = 'Unexpected information in header: ' if all([ord(c) < 128 and ord(c) != 0 for c in str(head)]): # show only if ASCII self.errors += ' '+str(head) else: self.errors += ' (binary)' fp.close() return False fp.close() return True
[docs] def Reader(self,filename, ParentFrame=None, **kwarg): 'Read a Bruker RAW file' self.comments = [] self.powderentry[0] = filename fp = open(filename,'rb') if 'ver. 1' in self.fmtVer: raise Exception('Read of Bruker "RAW " (pre-version #) file not supported') #for now elif 'ver. 2' in self.fmtVer: fp.seek(4) nBlock = int(st.unpack('<i',fp.read(4))[0]) fp.seek(168) self.comments.append('Date/Time='+self.Read(fp,20)) self.comments.append('Anode='+self.Read(fp,2)) self.comments.append('Ka1=%.5f'%(st.unpack('<f',fp.read(4))[0])) self.comments.append('Ka2=%.5f'%(st.unpack('<f',fp.read(4))[0])) self.comments.append('Ka2/Ka1=%.5f'%(st.unpack('<f',fp.read(4))[0])) fp.seek(206) self.comments.append('Kb=%.5f'%(st.unpack('<f',fp.read(4))[0])) pos = 256 fp.seek(pos) blockNum = kwarg.get('blocknum',0) self.idstring = os.path.basename(filename) + ' Scan '+str(blockNum) if blockNum <= nBlock: for iBlock in range(blockNum): headLen = int(st.unpack('<H',fp.read(2))[0]) nSteps = int(st.unpack('<H',fp.read(2))[0]) if iBlock+1 == blockNum: fp.seek(pos+12) step = st.unpack('<f',fp.read(4))[0] start2Th = st.unpack('<f',fp.read(4))[0] pos += headLen #position at start of data block fp.seek(pos) x = np.array([start2Th+i*step for i in range(nSteps)]) y = np.array([max(1.,st.unpack('<f',fp.read(4))[0]) for i in range(nSteps)]) y = np.where(y<0.,1.,y) w = 1./y self.powderdata = [x,y,w,np.zeros(nSteps),np.zeros(nSteps),np.zeros(nSteps)] break pos += headLen+4*nSteps fp.seek(pos) if blockNum == nBlock: self.repeat = False else: self.repeat = True fp.close() elif 'ver. 3' in self.fmtVer: fp.seek(12) nBlock = int(st.unpack('<i',fp.read(4))[0]) self.comments.append('Date='+self.Read(fp,10)) self.comments.append('Time='+self.Read(fp,10)) fp.seek(326) self.comments.append('Sample='+self.Read(fp,60)) fp.seek(564) radius = st.unpack('<f',fp.read(4))[0] self.comments.append('Gonio. radius=%.2f'%(radius)) self.Sample['Gonio. radius'] = radius fp.seek(608) self.comments.append('Anode='+self.Read(fp,4)) fp.seek(616) self.comments.append('Ka mean=%.5f'%(st.unpack('<d',fp.read(8))[0])) self.comments.append('Ka1=%.5f'%(st.unpack('<d',fp.read(8))[0])) self.comments.append('Ka2=%.5f'%(st.unpack('<d',fp.read(8))[0])) self.comments.append('Kb=%.5f'%(st.unpack('<d',fp.read(8))[0])) self.comments.append('Ka2/Ka1=%.5f'%(st.unpack('<d',fp.read(8))[0])) pos = 712 fp.seek(pos) #position at 1st block header blockNum = kwarg.get('blocknum',0) self.idstring = os.path.basename(filename) + ' Scan '+str(blockNum) if blockNum <= nBlock: for iBlock in range(blockNum): headLen = int(st.unpack('<i',fp.read(4))[0]) nSteps = int(st.unpack('<i',fp.read(4))[0]) if not nSteps: break if nBlock > 1: fp.seek(pos+256) headLen += st.unpack('<i',fp.read(4))[0] else: headLen += 40 if iBlock+1 == blockNum: fp.seek(pos+8) st.unpack('<d',fp.read(8))[0] start2Th = st.unpack('<d',fp.read(8))[0] fp.seek(pos+212) temp = st.unpack('<f',fp.read(4))[0] if temp > 0.: self.Sample['Temperature'] = temp fp.seek(pos+176) step = st.unpack('<d',fp.read(8))[0] pos += headLen #position at start of data block fp.seek(pos) x = np.array([start2Th+i*step for i in range(nSteps)]) try: y = np.array([max(1.,st.unpack('<f',fp.read(4))[0]) for i in range(nSteps)]) except: #this is absurd fp.seek(pos-40) y = np.array([max(1.,st.unpack('<f',fp.read(4))[0]) for i in range(nSteps)]) w = 1./y self.powderdata = [x,y,w,np.zeros(nSteps),np.zeros(nSteps),np.zeros(nSteps)] break pos += headLen+4*nSteps fp.seek(pos) if blockNum == nBlock: self.repeat = False else: self.repeat = True fp.close() elif 'ver. 4' in self.fmtVer: driveNo = 0 fp.seek(12) #ok self.comments.append('Date='+self.Read(fp,12).strip('\x00')) self.comments.append('Time='+self.Read(fp,10).strip('\x00')) fp.seek(61) #start of header segments nBank = 0 blockNum = kwarg.get('blocknum',0) while nBank < self.numbanks: while True: #read block header segtype = st.unpack('<I',fp.read(4))[0] if not segtype or segtype == 160: break # done with header seglen = max(st.unpack('<I',fp.read(4))[0],8) if segtype == 10: fp.read(4) #skip these self.comments.append('%s=%s'%(self.Read(fp,24).strip('\x00'),self.Read(fp,seglen-36).strip('\x00'))) elif segtype == 30: #x-ray source info fp.read(64) self.comments.append('Ka mean=%.5f'%(st.unpack('<d',fp.read(8))[0])) self.comments.append('Ka1=%.5f'%(st.unpack('<d',fp.read(8))[0])) self.comments.append('Ka2=%.5f'%(st.unpack('<d',fp.read(8))[0])) self.comments.append('Kb=%.5f'%(st.unpack('<d',fp.read(8))[0])) self.comments.append('Ka2/Ka1=%.5f'%(st.unpack('<d',fp.read(8))[0])) fp.read(4) self.comments.append('Anode='+self.Read(fp,4).strip('\x00')) fp.read(seglen-120) elif segtype == 60: alignFlag = st.unpack('<I',fp.read(4))[0] driveName = self.Read(fp,24).strip('\x00') fp.read(32) Delt = st.unpack('<d',fp.read(8))[0] fp.read(seglen-76) self.comments.append('Drive %s: align flag %d'%(driveName,alignFlag)) self.comments.append('Drive %s: delta %f'%(driveName,Delt)) driveNo += 1 else: fp.read(seglen-8) if (segtype == 0 or segtype == 160): #read data block self.idstring = self.dnames[nBank] meta = {} fp.read(28) meta['ScanType'] = self.Read(fp,24).strip('\x00') if meta['ScanType'] not in ['Locked Coupled','Unlocked Coupled','Detector Scan']: return False fp.read(16) startAngle = st.unpack('<d',fp.read(8))[0] meta['startAngle'] = '%.4f'%startAngle stepSize = st.unpack('<d',fp.read(8))[0] meta['stepSize'] = '%.4f'%stepSize Nsteps = st.unpack('<I',fp.read(4))[0] meta['Nsteps'] = '%d'%Nsteps meta['stepTime(ms)'] = st.unpack('<f',fp.read(4))[0] fp.read(4) meta['generatorVoltage(kV)'] = st.unpack('<f',fp.read(4))[0] meta['generatorCurrent(mA)'] = st.unpack('<f',fp.read(4))[0] fp.read(4) meta['usedWave'] = st.unpack('<d',fp.read(8))[0] fp.read(16) datumSize = st.unpack('<I',fp.read(4))[0] hdrSize = st.unpack('<I',fp.read(4))[0] fp.read(16) if meta['ScanType'] in ['Locked Coupled','Unlocked Coupled','Detector Scan']: while hdrSize > 0: segtype = st.unpack('<I',fp.read(4))[0] seglen = max(st.unpack('<I',fp.read(4))[0],8) if segtype == 50: fp.read(4) segName = self.Read(fp,24).strip('\x00') if segName in ['Theta','2Theta','Chi','Phi','BeamTranslation','Z-Drive','Divergence Slit']: fp.read(20) meta['start %s'%segName] = '%.4f'%(st.unpack('<d',fp.read(8))[0]) fp.read(seglen-64) else: fp.read(seglen-36) else: fp.read(seglen-8) hdrSize -= seglen #end of reading scan header pos = fp.tell() fp.seek(pos-16) meta['Temperature'] = st.unpack('<f',fp.read(4))[0] if meta['Temperature'] > 7.: #one raw4 file had int4='9999' in this place & <7K unlikely for lab data self.Sample['Temperature'] = meta['Temperature'] try: self.Sample['Omega'] = float(meta['start Theta']) except: pass fp.read(12) x = np.array([startAngle+i*stepSize for i in range(Nsteps)]) y = np.array([max(1.,st.unpack('<f',fp.read(4))[0]) for i in range(Nsteps)]) w = 1./y if nBank == blockNum-1: self.powderdata = [x,y,w,np.zeros(Nsteps),np.zeros(Nsteps),np.zeros(Nsteps)] for item in meta: self.comments.append('%s = %s'%(item,str(meta[item]))) fp.close() self.repeat = True if nBank == self.numbanks-1: self.repeat = False return True else: meta['Unknown range/scan type'] = True fp.read(hdrSize) fp.read(datumSize*Nsteps) nBank += 1 else: return False self.repeat = False return True