Source code for G2pwd_BrukerRAW

# -*- coding: utf-8 -*-
########### SVN repository information ###################
# $Date: 2024-03-06 10:33:02 -0600 (Wed, 06 Mar 2024) $
# $Author: toby $
# $Revision: 5753 $
# $URL: https://subversion.xray.aps.anl.gov/pyGSAS/trunk/imports/G2pwd_BrukerRAW.py $
# $Id: G2pwd_BrukerRAW.py 5753 2024-03-06 16:33:02Z toby $
########### SVN repository information ###################
'''
'''

from __future__ import division, print_function
import os
import os.path as ospath
import struct as st
import numpy as np
import GSASIIobj as G2obj
import GSASIIctrlGUI as G2G
import GSASIIpath
GSASIIpath.SetVersionNumber("$Revision: 5753 $")
[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.formatName = 'Bruker RAW ver. 1' elif head[:4] == 'RAW2': self.formatName = 'Bruker RAW ver. 2' elif head == 'RAW1.01': self.formatName = 'Bruker RAW ver. 3' elif head == 'RAW4.00': self.formatName = 'Bruker RAW ver. 4' self.errors += "Sorry, this is a Version 4 Bruker file. " self.errors += "We need documentation for it so that it can be implemented in GSAS-II. " self.errors += "Use PowDLL (http://users.uoi.gr/nkourkou/powdll/) to convert it to ASCII xy." print(self.errors) fp.close() return False 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.formatName: raise Exception #for now elif 'ver. 2' in self.formatName: 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 = ospath.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.,y,1.) 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.formatName: 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 = ospath.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.formatName: #does not work - format still elusive fp.seek(12) #ok self.comments.append('Date='+self.Read(fp,10)) self.comments.append('Time='+self.Read(fp,10)) fp.seek(144) self.comments.append('Sample='+self.Read(fp,60)) fp.seek(564) # where is it? radius = st.unpack('<f',fp.read(4))[0] self.comments.append('Gonio. radius=%.2f'%(radius)) self.Sample['Gonio. radius'] = radius fp.seek(516) #ok self.comments.append('Anode='+self.Read(fp,4)) fp.seek(472) #ok 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.seek(pos) #deliberate fail here - pos not known from file contents self.idstring = ospath.basename(filename) + ' Scan '+str(1) nSteps = int(st.unpack('<i',fp.read(4))[0]) st.unpack('<d',fp.read(8))[0] start2Th = st.unpack('<d',fp.read(8))[0] 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)]) 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)] fp.close() else: return False return True
[docs] class brml_ReaderClass(G2obj.ImportPowderData): 'Routines to import powder data from a zip Bruker .brml file' def __init__(self): super(self.__class__,self).__init__( # fancy way to self-reference extensionlist=('.brml',), strictExtension=True, formatName = 'Bruker brml', longFormatName = 'Bruker .brml powder data file' ) self.scriptable = True self.data = None
[docs] def ContentsValidator(self, filename): try: import xmltodict as xml except: print('Attempting to conda install xmltodict - please wait') res = GSASIIpath.condaInstall('xmltodict') if res: msg = 'Installation of the xmltodict package failed with error:\n' + str(res) G2G.G2MessageBox(self,msg,'Install xmltodict Error') return False try: import xmltodict as xml except: return False try: import zipfile as ZF with ZF.ZipFile(filename, 'r') as zipObj: zipObj.extract('Experiment0/RawData0.xml') with open('Experiment0/RawData0.xml') as fd: self.data = dict(xml.parse(fd.read())) self.formatName = 'Bruker .brml file' os.remove('Experiment0/RawData0.xml') os.rmdir('Experiment0') self.idstring = ospath.basename(filename) + ' Bank 1' self.powderentry[0] = filename self.comments = [] return True except: return False
[docs] def Reader(self,filename, ParentFrame=None, **kwarg): 'Read a Bruker brml file' print(filename) datano = 1 try: nSteps = int(self.data['RawData']['DataRoutes']['DataRoute'][datano]['ScanInformation']['MeasurementPoints']) except KeyError: datano = 0 nSteps = int(self.data['RawData']['DataRoutes']['DataRoute']['ScanInformation']['MeasurementPoints']) x = np.zeros(nSteps, dtype=float) y = np.zeros(nSteps, dtype=float) w = np.zeros(nSteps, dtype=float) if datano: effTime = float(self.data['RawData']['DataRoutes']['DataRoute'][datano]['ScanInformation']['TimePerStepEffective']) else: effTime = float(self.data['RawData']['DataRoutes']['DataRoute']['ScanInformation']['TimePerStepEffective']) # Extract 2-theta angle and counts from the XML document i=0 while i < nSteps : if datano: entry = self.data['RawData']['DataRoutes']['DataRoute'][datano]['Datum'][i].split(',') else: entry = self.data['RawData']['DataRoutes']['DataRoute']['Datum'][i].split(',') x[i] = float(entry[2]) y[i] = float(entry[4])*float(entry[0])/effTime i = i + 1 w = np.where(y>0,1/y,0.) self.powderdata = [x,y,w,np.zeros(nSteps),np.zeros(nSteps),np.zeros(nSteps)] return True