Source code for G2pwd_rigaku

# -*- coding: utf-8 -*-
########### SVN repository information ###################
# $Date: 2023-02-06 15:54:24 -0600 (Mon, 06 Feb 2023) $
# $Author: vondreele $
# $Revision: 5495 $
# $URL: https://subversion.xray.aps.anl.gov/pyGSAS/trunk/imports/G2pwd_rigaku.py $
# $Id: G2pwd_rigaku.py 5495 2023-02-06 21:54:24Z vondreele $
########### SVN repository information ###################

from __future__ import division, print_function
import os
import os.path as ospath
import platform
import numpy as np
import GSASIIobj as G2obj
import GSASIIctrlGUI as G2G
import GSASIIpath
GSASIIpath.SetVersionNumber("$Revision: 5495 $")
[docs] class Rigaku_txtReaderClass(G2obj.ImportPowderData): '''Routines to import powder data from a Rigaku .txt file with an angle and then 1 or 11(!) intensity values on the line. The example file is proceeded with 10 of blank lines, but I have assumed they could be any sort of text. This code should work with an angle and any number of intensity values/line as long as the number is the same on each line. The step size may not change. The number of comment lines can also change, but should not appear to be intensity values (numbers only). ''' def __init__(self): super(self.__class__,self).__init__( # fancy way to self-reference extensionlist=('.txt','.TXT'), strictExtension=True, formatName = 'Rigaku .txt exported', longFormatName = 'Rigaku powder data exported as .txt' ) self.scriptable = True self.vals = None self.stepsize = None self.skip = 0 # Validate the contents -- make sure we only have valid lines and set # values we will need for later read.
[docs] def ContentsValidator(self, filename): self.vals = None self.stepsize = None j = 0 prevAngle = None header = True self.skip = -1 fp = open(filename,'r') for i,line in enumerate(fp): sline = line.split() vals = len(sline) if header: self.skip += 1 if not line.strip(): continue # ignore blank lines err = False for item in sline: try: float(item) except: err = True break if err: continue if vals < 1: continue header = False # found first non-header line if vals < 2: print('Too few values for Rigaku .txt file') fp.close() return False if self.vals is None: self.vals = vals elif self.vals != vals: print('Inconsistent numbers values for Rigaku .txt file on line '+str(i+1)) fp.close() return False else: j += 1 try: angle = float(sline[0]) except: print('Unable to read angle on line '+str(i+1)) fp.close() return False if prevAngle is None: prevAngle = angle continue stepsize = (angle-prevAngle)/(vals-1) prevAngle = angle if self.stepsize is None: self.stepsize = stepsize elif abs(self.stepsize - stepsize) > max(abs(stepsize),abs(self.stepsize))/10000. : print('Inconsistent step size for Rigaku .txt file on line '+ str(i+1) + ' here '+ repr(stepsize) + ' prev '+ repr(self.stepsize)) fp.close() return False if j > 30: fp.close() return True fp.close() return False
[docs] def Reader(self,filename, ParentFrame=None, **kwarg): 'Read a Rigaku .txt file' x = [] y = [] w = [] fp = open(filename,'r') for i,line in enumerate(fp): if i < self.skip: continue sline = line.split() try: angle = float(sline[0]) except: print('Unable to read angle on line '+str(i+1)) self.errors = 'Error reading line: '+str(i+1) return False for j in sline[1:]: x.append(angle) angle += self.stepsize try: y.append(float(j)) except: print('Unable to read intensity on line '+str(i+1)) self.errors = 'Error reading line: '+str(i+1) return False w.append(1.0/max(1.,float(j))) N = len(x) self.powderdata = [ np.array(x), # x-axis values np.array(y), # powder pattern intensities np.array(w), # 1/sig(intensity)^2 values (weights) np.zeros(N), # calc. intensities (zero) np.zeros(N), # calc. background (zero) np.zeros(N), # obs-calc profiles ] self.powderentry[0] = filename #self.powderentry[2] = 1 # xye file only has one bank self.idstring = os.path.basename(filename) return True
[docs] class Rigaku_rasReaderClass(G2obj.ImportPowderData): '''Routines to import powder data from a Rigaku .ras file with multiple scans. All scans will be imported as individual PWDR entries ''' def __init__(self): super(self.__class__,self).__init__( # fancy way to self-reference extensionlist=('.ras','.RAS','rasx',), strictExtension=True, formatName = 'Rigaku .ras/.rasx file', longFormatName = 'Rigaku .ras/.rasx raw multipattern powder data' ) self.scriptable = True self.vals = None self.stepsize = None self.skip = 0 # Validate the contents -- make sure we only have valid lines and set # values we will need for later read.
[docs] def ContentsValidator(self, filename): if '2' in platform.python_version_tuple()[0]: fp = open(filename,'Ur') else: fp = open(filename,'r',encoding='latin-1') self.vals = None self.stepsize = None if '.rasx' in 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 import xmltodict as xml try: import zipfile as ZF with ZF.ZipFile(filename, 'r') as zipObj: zipObj.extract('Data0/Profile0.txt') zipObj.extract('Data0/MesurementConditions0.xml') with open('Data0/Profile0.txt') as fd: fd.seek(3) self.data = fd.readlines() self.formatName = 'Rigaku .rasx file' with open('Data0/MesurementConditions0.xml') as xd: self.comments = xd.read() os.remove('Data0/MesurementConditions0.xml') os.remove('Data0/Profile0.txt') os.rmdir('Data0') self.idstring = ospath.basename(filename) + ' Bank 1' self.powderentry[0] = filename self.comments = [] return True except: return False else: fp.seek(0) if fp.readline()[:-1] != '*RAS_DATA_START': self.errors = 'Bad ras file' fp.close() return False nBanks= 0 for i,line in enumerate(fp): if line[:-1] == '*RAS_HEADER_START': nBanks += 1 self.dnames.append(os.path.basename(filename)+' sample '+(str(nBanks))) if nBanks: if not len(self.selections): self.selections = list(range(nBanks)) self.numbanks = nBanks fp.close() return True
[docs] def Reader(self,filename, ParentFrame=None, **kwarg): 'Read a Rigaku .ras/.rasx file' if '.rasx' in filename: x = [] y = [] w = [] for line in self.data: sline = line.split() x.append(float(sline[0])) y.append(float(sline[1])) w.append(1.0/max(1.,float(y[-1]))) N = len(x) self.powderdata = [ np.array(x), # x-axis values np.array(y), # powder pattern intensities np.array(w), # 1/sig(intensity)^2 values (weights) np.zeros(N), # calc. intensities (zero) np.zeros(N), # calc. background (zero) np.zeros(N), # obs-calc profiles ] self.repeat = False return True else: #.ras file if '2' in platform.python_version_tuple()[0]: fp = open(filename,'Ur') else: fp = open(filename,'r',encoding='latin-1') blockNum = self.selections[0] x = [] y = [] w = [] block = 0 while True: line = fp.readline()[:-1] if line != '*RAS_INT_START': continue if block == blockNum: line = fp.readline()[:-1] while True: if line == '*RAS_INT_END': break sline = line.split() x.append(float(sline[0])) y.append(float(sline[1])) w.append(1.0/max(1.,float(y[-1]))) line = fp.readline()[:-1] break block += 1 N = len(x) self.powderdata = [ np.array(x), # x-axis values np.array(y), # powder pattern intensities np.array(w), # 1/sig(intensity)^2 values (weights) np.zeros(N), # calc. intensities (zero) np.zeros(N), # calc. background (zero) np.zeros(N), # obs-calc profiles ] self.powderentry[0] = self.dnames[blockNum] self.idstring = self.dnames[blockNum] self.selections.remove(blockNum) self.repeat = False if len(self.selections): self.repeat = True return True