Skip to content

Commit

Permalink
Implement LoadFullprofFile. Refs #6750.
Browse files Browse the repository at this point in the history
  • Loading branch information
wdzhou committed Apr 2, 2013
1 parent 4514b7b commit b236bbe
Show file tree
Hide file tree
Showing 3 changed files with 479 additions and 0 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,315 @@
"""*WIKI*
This algorithm is to import Fullprof .irf file (peak parameters) and .hkl file (reflections) and
record the information to TableWorkspaces, which serve as the inputs for algorithm LeBailFit.
==== Format of Instrument parameter TableWorkspace ====
Instrument parameter TableWorkspace contains all the peak profile parameters imported from Fullprof .irf file.
Presently these are the peak profiles supported
* Thermal neutron back to back exponential convoluted with pseudo-voigt (profile No. 10 in Fullprof)
Each row in TableWorkspace corresponds to one profile parameter.
Columns include Name, Value, FitOrTie, Min, Max and StepSize.
==== Format of reflection TableWorkspace ====
Each row of this workspace corresponds to one diffraction peak.
The information contains the peak's Miller index and (local) peak profile parameters of this peak.
For instance of a back-to-back exponential convoluted with Gaussian peak,
the peak profile parameters include Alpha, Beta, Sigma, centre and height.
== How to use algorithm with other algorithms ==
This algorithm is designed to work with other algorithms to do Le Bail fit. The introduction can be found in the wiki page of [[LeBailFit]].
*WIKI*"""
from mantid.api import PythonAlgorithm, registerAlgorithm, ITableWorkspaceProperty, WorkspaceFactory, FileProperty, FileAction, MatrixWorkspaceProperty, WorkspaceProperty
from mantid.kernel import Direction, StringListValidator

import mantid.simpleapi as api

_OUTPUTLEVEL = "NOOUTPUT"

class LoadFullprofFile(PythonAlgorithm):
""" Create the input TableWorkspaces for LeBail Fitting
"""
def category(self):
"""
"""
return "Diffraction;Utility"

def name(self):
"""
"""
return "LoadFullprofFile"

def PyInit(self):
""" Declare properties
"""
self.setWikiSummary("""Load file generated by Fullprof.""")

self.declareProperty(FileProperty("Filename","", FileAction.Load, ['.hkl', '.prf']),
"Name of [http://www.ill.eu/sites/fullprof/ Fullprof] .hkl or .prf file.")

#self.declareProperty("Bank", 1, "Bank ID for output if there are more than one bank in .irf file.")

self.declareProperty(ITableWorkspaceProperty("PeakParameterWorkspace", "", Direction.Output),
"Name of table workspace containing peak parameters from .hkl file.")

self.declareProperty(MatrixWorkspaceProperty("OutputWorkspace", "", Direction.Output),
"Name of data workspace containing the diffraction pattern in .prf file. ")

return

def PyExec(self):
""" Main Execution Body
"""
# 1. Properties
fpfilename = self.getPropertyValue("Filename")

# 2. Import
if fpfilename.lower().endswith(".hkl") is True:
# (.hkl) file
self._tableWS = self._loadFPHKLFile(fpfilename)
self._dataWS = self._makeEmptyDataWorkspace()
elif fpfilename.lower().endswith(".prf") is True:
# (.prf) file
self._tableWS, self._dataWS= self._loadFullprofPrfFile(fpfilename)
else:
raise NotImplementedError("File %s is neither .hkl nor .prf. It is not supported." % (fpfilename))

# 3. Export
self.setProperty("PeakParameterWorkspace", self._tableWS)
self.setProperty("OutputWorkspace", self._dataWS)

return


def _loadFPHKLFile(self, filename):
""" Load Fullprof .hkl file to a TableWorkspace
"""
# 1. Import to a dictionary
hkldict = self._importFullprofHKLFile(filename)

# 2. Create workspace from dictionary
peakws = self._createReflectionWorkspace(hkldict)

return peakws


def _importFullprofHKLFile(self, hklfilename):
""" Import Fullprof's .hkl file
"""
import math
# 1. Import file
try:
hklfile = open(hklfilename, "r")
lines = hklfile.readlines()
hklfile.close()
except IOError:
print "Error to open/read Fullprof .hkl file %s" % (hklfilename)
raise IOError()

# 2. Parse
hkldict = {}
for line in lines:
# a) Clean & split
line = line.strip()
if len(line) == 0:
continue
terms = line.split()

# b) parse
if not terms[0].isdigit():
# Comment line
continue

h = int(terms[0])
k = int(terms[1])
l = int(terms[2])
if len(terms) >= 9:
dsp = float(terms[3])
tof = float(terms[4])
alpha = float(terms[5])
beta = float(terms[6])
sigma2 = float(terms[7])
gamma2 = float(terms[8])
else:
dsp = 0.0
tof = 0.0
alpha = 0.0
beta = 0.0
sigma2 = 0.0
gamma2 = 0.0
fwhm = 1.0

if len(terms) >= 13:
fwhm = float(terms[12])
elif len(terms) >= 9:
fwhm = math.sqrt(sigma2)*2.0

dkey = (h, k, l)

if hkldict.has_key(dkey):
if _OUTPUTLEVEL == "INFORMATION":
print "Warning! Duplicate HKL %d, %d, %d" (h, k, l)
continue

if fwhm < 1.0E-5:
# Peak width is too small/annihilated peak
if _OUTPUTLEVEL == "INFORMATION":
print "Peak (%d, %d, %d) has an unreasonable small FWHM. Peak does not exist. " % (h, k, l)
continue

hkldict[dkey] = {}
hkldict[dkey]["dsp"] = dsp
hkldict[dkey]["tof"] = tof
hkldict[dkey]["alpha"] = alpha
hkldict[dkey]["beta"] = beta
hkldict[dkey]["sigma2"] = sigma2
hkldict[dkey]["gamma2"] = gamma2
hkldict[dkey]["FWHM"] = fwhm
# ENDFOR: line

print "Import Fullprof reflection file %s successfully. " % (hklfilename)

return hkldict

def _createReflectionWorkspace(self, hkldict):
""" Create TableWorkspace containing reflections and etc.
"""
# 1. Set up columns
tablews = WorkspaceFactory.createTable()

tablews.addColumn("int", "H");
tablews.addColumn("int", "K");
tablews.addColumn("int", "L");
tablews.addColumn("double", "Alpha");
tablews.addColumn("double", "Beta");
tablews.addColumn("double", "Sigma2");
tablews.addColumn("double", "Gamma");
tablews.addColumn("double", "FWHM");
tablews.addColumn("double", "PeakHeight");

# 2. Add rows
for hkl in sorted(hkldict.keys()):
pardict = hkldict[hkl]
tablews.addRow([hkl[0], hkl[1], hkl[2], pardict["alpha"], pardict["beta"], pardict["sigma2"], pardict["gamma2"], pardict["FWHM"], 1.0])
# ENDFOR

return tablews


def _loadFullprofPrfFile(self, prffilename):
""" Load Fullprof .prf file
"""
# 1. Parse the file to dictionary
infodict, data = self._parseFullprofPrfFile(prffilename)

# 2. Export information to table file
tablews = WorkspaceFactory.createTable()
tablews.addColumn("str", "Name")
tablews.addColumn("double", "Value")
for parname in infodict.keys():
parvalue = infodict[parname]
tablews.addRow([parname, parvalue])

# 3. Export the data workspace
datasize = len(data)
print "Data Size = ", datasize
dataws = WorkspaceFactory.create("Workspace2D", 4, datasize, datasize)
for i in xrange(datasize):
for j in xrange(4):
dataws.dataX(j)[i] = data[i][0]
dataws.dataY(j)[i] = data[i][j+1]
dataws.dataE(j)[i] = 1.0

return (tablews, dataws)


def _parseFullprofPrfFile(self, filename):
""" Parse Fullprof .prf file to a information dictionary and a data set (list of list)
"""
# 1. Import file
try:
pfile = open(filename, "r")
except IOError:
raise NotImplementedError("Unable to open .prf file %s" % (filename))

rawlines = pfile.readlines()
lines = []
for l in rawlines:
line = l.strip()
if len(line) > 0:
lines.append(line)

infodict = {}
dataset = []

# 2. Parse information line
infoline = lines[0]
if infoline.count("CELL:") == 1:
terms = infoline.split("CELL:")[1].split()
a = float(terms[0])
b = float(terms[1])
c = float(terms[2])
alpha = float(terms[3])
beta = float(terms[4])
gamma = float(terms[5])
infodict["A"] = float(a)
infodict["B"] = float(b)
infodict["C"] = float(c)
infodict["Alpha"] = float(alpha)
infodict["Beta"] = float(beta )
infodict["Gamma"] = float(gamma)
#if infoline.count("SPGR:") == 1:
# terms = infoline.split("SPGR:")
# spacegroup = terms[1].strip()
# infodict["SpaceGroup"] = spacegroup

# 3. Parse data
firstline = -1
for i in xrange(1, len(lines)):
if lines[i].startswith("T.O.F"):
firstline = i+1
break

if firstline < 0:
raise NotImplementedError("File format is incorrect. Unable to locate data title line")


count = 0
for i in xrange(firstline, len(lines)):
terms = lines[i].split()
if len(terms) == 5 and lines[i].count(")") == 0:
# it is a data line
x = float(terms[0])
yobs = float(terms[1])
ycal = float(terms[2])
ydif = float(terms[3])
ybak = float(terms[4])

dataset.append([x, yobs, ycal, ydif, ybak])
count += 1

else:
break
# ENDFOR

print "Data set counter = ", count

return (infodict, dataset)


def _makeEmptyDataWorkspace(self):
""" Make an empty data workspace (Workspace2D)
"""
dataws = WorkspaceFactory.create("Workspace2D", 1, 1, 1)

return dataws


# Register algorithm with Mantid
registerAlgorithm(LoadFullprofFile)

Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ set ( TEST_PY_FILES
CreateWorkspaceTest.py
DakotaChiSquaredTest.py
FindReflectometryLinesTest.py
LoadFullprofFileTest.py
MaskWorkspaceToCalFileTest.py
RetrieveRunInfoTest.py
Stitch1DTest.py
Expand Down

0 comments on commit b236bbe

Please sign in to comment.