-
Campbell, Stuart authoredCampbell, Stuart authored
Code owners
Assign users and groups as approvers for specific file changes. Learn more.
RefinePowderDiffProfileSeq.py 36.21 KiB
#pylint: disable=no-init,invalid-name
from mantid.api import *
import mantid.simpleapi as api
from mantid.api import *
from mantid.kernel import *
#from Calibration_ImportInformation import *
#--------------------------------------------------------------------------------
#pylint: disable=too-many-instance-attributes
class RefinePowderDiffProfileSeq(PythonAlgorithm):
""" Refine powder diffractometer profile by Le Bail algorithm sequentially
"""
dataws = None
wsindex = None
startx = None
endx = None
_lastStep = None
_projectID = None
functionoption = None
peaktype = None
bkgdtype = None
bkgdparws = None
profilews = None
braggpeakws = None
paramstofit = None
numcycles = None
outprojectfilename = None
inprojectfilename = None
datawsname = None
def category(self):
""" Category
"""
return "Diffraction"
def name(self):
""" Algorithm name
"""
return "RefinePowderDiffProfileSeq"
def summary(self):
return "Refine powder diffractomer profile parameters sequentially."
def PyInit(self):
""" Declare properties
"""
self.declareProperty(MatrixWorkspaceProperty("InputWorkspace", "", Direction.Input, PropertyMode.Optional),\
"Name of data workspace containing the diffraction pattern in .prf file. ")
self.declareProperty("WorkspaceIndex", 0,
"Spectrum (workspace index starting from 0) of the data to refine against in input workspace.")
self.declareProperty(ITableWorkspaceProperty("SeqControlInfoWorkspace", "", Direction.InOut, PropertyMode.Optional),\
"Name of table workspace containing sequential refinement information.")
self.declareProperty(ITableWorkspaceProperty("InputProfileWorkspace", "", Direction.Input, PropertyMode.Optional),\
"Name of table workspace containing starting profile parameters.")
self.declareProperty(ITableWorkspaceProperty("InputBraggPeaksWorkspace", "", Direction.Input, PropertyMode.Optional),\
"Name of table workspace containing a list of reflections. ")
self.declareProperty(ITableWorkspaceProperty("InputBackgroundParameterWorkspace", "", Direction.Input,\
PropertyMode.Optional), "Name of table workspace containing a list of reflections. ")
self.declareProperty("StartX", -0., "Start X (TOF) to refine diffraction pattern.")
self.declareProperty("EndX", -0., "End X (TOF) to refine diffraction pattern.")
funcoptions = ["Setup", "Refine", "Save", "Load"]
self.declareProperty("FunctionOption", "Refine", StringListValidator(funcoptions), "Options of functionality")
#refoptions = ["Levenberg-Marquardt", "Random Walk", "Single Peak Fit"]
refoptions = ["Random Walk"]
self.declareProperty("RefinementOption", "Random Walk", StringListValidator(refoptions),\
"Options of algorithm to refine. ")
self.declareProperty(StringArrayProperty("ParametersToRefine", values=[], direction=Direction.Input),\
"List of parameters to refine.")
self.declareProperty("NumRefineCycles", 1, "Number of refinement cycles.")
peaktypes = ["", "Neutron Back-to-back exponential convoluted with pseudo-voigt",\
"Thermal neutron Back-to-back exponential convoluted with pseudo-voigt"]
self.declareProperty("ProfileType", "", StringListValidator(peaktypes), "Type of peak profile function.")
bkgdtypes = ["", "Polynomial", "Chebyshev", "FullprofPolynomial"]
self.declareProperty("BackgroundType", "", StringListValidator(bkgdtypes), "Type of background function.")
self.declareProperty("FromStep", -1, "If non-negative, the previous code is not set from last step, but the step specified.")
# Property for save project
self.declareProperty(FileProperty("OutputProjectFilename","", FileAction.OptionalSave, ['.nxs']),\
"Name of sequential project file.")
# Property for save project
self.declareProperty(FileProperty("InputProjectFilename","", FileAction.OptionalLoad, ['.nxs']),\
"Name of sequential project file.")
# Project ID
self.declareProperty("ProjectID", "", "Project ID.")
return
def PyExec(self):
""" Main
"""
# Process input
self._processInputProperties()
# Instantiaze sequential refinement
seqrefine = SeqRefineProfile(self._projectID, self.log())
# Execute
if self.functionoption == "Setup":
# Set up
if seqrefine.isSetup() is True:
raise NotImplementedError("Impossible to have it set up already.")
seqrefine.initSetup(self.dataws, self.wsindex, self.peaktype, self.profilews, self.braggpeakws, self.bkgdtype,\
self.bkgdparws, self.startx, self.endx)
elif self.functionoption == "Refine":
# Refine
if seqrefine.isSetup() is False:
raise NotImplementedError("Exception because sequential refinement is not set up.")
seqrefine.refine(self.dataws, self.wsindex, self.paramstofit, self.numcycles, self.startx, self.endx, self._lastStep)
elif self.functionoption == "Save":
# Save the current state to a project file
seqrefine.saveProject(str(self.dataws), self.wsindex, self.outprojectfilename)
elif self.functionoption == "Load":
# Set up from an exiting project file
if seqrefine.isSetup() is True:
raise NotImplementedError("Impossible to have it set up already.")
seqrefine.loadProject(self.inprojectfilename)
else:
# None-support
raise NotImplementedError("Function is not supported.")
return
def _processInputProperties(self):
""" Process input properties
"""
# Input data workspace and related
self.dataws = self.getProperty("InputWorkspace").value
self.wsindex = self.getProperty("WorkspaceIndex").value
self.startx = self.getProperty("StartX").value
self.endx = self.getProperty("EndX").value
self._lastStep = self.getProperty("FromStep").value
self._projectID = self.getProperty("ProjectID").value
if len(self._projectID) == 0:
raise NotImplementedError("User must specify project ID.")
self.functionoption = self.getProperty("FunctionOption").value
if self.functionoption == "Setup":
# Request on 'Setup'
ptype = self.getProperty("ProfileType").value
if ptype == "Neutron Back-to-back exponential convoluted with pseudo-voigt":
self.peaktype = "NeutronBk2BkExpConvPVoigt"
elif ptype == "Thermal neutron Back-to-back exponential convoluted with pseudo-voigt":
self.peaktype = "ThermalNeutronBk2BkExpConvPVoigt"
else:
raise NotImplementedError("Peak profile is not supported.")
self.bkgdtype = self.getProperty("BackgroundType").value
self.bkgdparws = self.getProperty("InputBackgroundParameterWorkspace").value
self.profilews = self.getProperty("InputProfileWorkspace").value
self.braggpeakws = self.getProperty("InputBraggPeaksWorkspace").value
elif self.functionoption == "Refine":
self.paramstofit = self.getProperty("ParametersToRefine").value
self.numcycles = self.getProperty("NumRefineCycles").value
elif self.functionoption == "Save":
self.outprojectfilename = self.getProperty("OutputProjectFilename").value
elif self.functionoption == "Load":
self.inprojectfilename = self.getProperty("InputProjectFilename").value
else:
raise NotImplementedError("Unsupported function mode %s. " % (self.functionoption))
if self.functionoption != "Load":
self.datawsname = str(self.dataws)
if self.wsindex < 0 or self.wsindex >= self.dataws.getNumberHistograms():
raise NotImplementedError("Input workspace index %d is out of range (0, %d)." %\
(self.wsindex, self.dataws.getNumberHistograms()))
return
#--------------------------------------------------------------------
#
#--------------------------------------------------------------------
#pylint: disable=too-many-instance-attributes
class SeqRefineProfile(object):
""" A class to do sequential refinement on peak profile
Use case:
1. Set class object such as : ID/StartDate/Directory
2. Run main to refine some parameters
3. Check result
4. If no further instruction, only need to set up parameters to refine
the input/starting values should be from the last
"""
_datawsname = None
_profileWS = None
_braggpeakws = None
_bkgdtype = None
_bkgdparws = None
_wsgroup = None
datawsname = None
wsindex = None
_recordws = None
_recordwsLastRowValid = None
_lastValidStep = None
_lastValidRowIndex = None
_peakType = None
_bkgdType = None
_currstep = None
def __init__(self, ID, glog):
"""
"""
# Set up log
self.glog = glog
# Set up ID
self._ID = str(ID)
self.glog.information("SeqRefineProfile is initialized with ID = %s" % (str(ID)))
# Standard record table and check its existence
# FIXME - This workspace's name should be passed from Algorithm's property!
self._recordwsname = "Record%sTable" % (str(ID))
self.glog.notice("Using record table %s" % (self._recordwsname))
if AnalysisDataService.doesExist(self._recordwsname):
# Record workspace exists: has been set up
self._isSetup = True
else:
# Record workspace does not exist: first time or need to load from file
self._isSetup = False
self._recordWSLastRowInvalid = False
# Result workspace group
self._wsgroupName = self._ID + "_Group"
if AnalysisDataService.doesExist(self._wsgroupName):
self._wsgroupCreated = True
else:
self._wsgroupCreated = False
return
#pylint: disable=too-many-arguments
def initSetup(self, dataws, wsindex, peaktype, profilews, braggpeakws, bkgdtype, bkgdparws, startx, endx):
""" Set up the properties for LeBailFit as the first time including
do a Le bail calculation based on the input parameters
including profilews, braggpeakws, and etc
"""
# Data and data range
self._datawsname = str(dataws)
if startx <= 0.:
startx = dataws.readX(wsindex)[0]
if endx <= 0.:
endx = dataws.readX(wsindex)[-1]
# Profile
self._peakType = peaktype
self._profileWS = profilews
self._braggpeakws = braggpeakws
self._bkgdtype = bkgdtype
self._bkgdparws = bkgdparws
# Generate record table
self._genRecordTable()
# Check input parameters, i.e., verification/examine input parameters
runner = RefineProfileParameters(self.glog)
outwsname = self._datawsname+"_Init"
runner.setInputs(self._datawsname, self._peakType, self._profileWS, self._braggpeakws, self._bkgdtype, self._bkgdparws)
# FIXME - Need to verify whether input and output background parameter ws name can be same
runner.setOutputs(outwsname, self._profileWS, self._braggpeakws, self._bkgdparws)
self._recordPreRefineInfo(runner, -1)
runner.calculate(startx, endx)
self._recordPostRefineInfo(runner)
# Group the newly generated workspace and do some record
api.GroupWorkspaces(InputWorkspaces="%s, %s, %s, %s" % (outwsname, self._profileWS, self._braggpeakws, self._bkgdparws),\
OutputWorkspace=self._wsgroupName)
self._wsgroupCreated = True
# Repository
# Replace 'Refine' of step 0 to ID (it is always empty)
self._recordws.setCell(0, 5, self._ID)
# Replace 'InputProfileWorkspace' by profile type (it is alwasy same as output)
self._recordws.setCell(0, 9, self._peakType)
self._isSetup = True
return
def loadProject(self, projectfilename):
""" Load the project from a saved project file
"""
# Load workspace group
api.LoadNexusProcessed(Filename=projectfilename, OutputWorkspace=self._wsgroupName)
self._wsgroup = AnalysisDataService.retrieve(self._wsgroupName)
if self._wsgroup.__class__.__name__ != "WorkspaceGroup":
raise NotImplementedError("Input is not a workspace group but a %s" % (self._wsgroup.__class__.__name__))
else:
self._wsgroupCreated = True
# Parse README
wsnames = self._wsgroup.getNames()
readmewsname = None
for wsname in wsnames:
if wsname.startswith("READ"):
readmewsname = wsname
break
if readmewsname is None:
raise NotImplementedError("No README workspace is found in loaded workspace group.")
readmews = AnalysisDataService.retrieve(readmewsname)
infodict = {}
numrows = readmews.rowCount()
self.glog.information("Found %d rows in workspace %s" % (numrows, str(readmews)))
for r in xrange(numrows):
functioncat = str(readmews.cell(r, 0)).strip()
functiontype = str(readmews.cell(r, 1)).strip()
infodict[functioncat] = functiontype.strip()
self.glog.information("README keys: %s" % (infodict.keys()))
self._peakType = infodict["Peak"]
self.datawsname = infodict["Data"]
self.wsindex = infodict["Spectrum"]
if self._ID != infodict["ID"]:
raise NotImplementedError("ID mismatch!")
self._recordwsname = infodict["Record"]
self._isSetup = True
return
#pylint: disable=too-many-arguments
def refine(self, dataws, wsindex, parametersToFit, numcycles, startx, endx, laststepindex):
""" Refine parameters
"""
# Range of fit
if startx <= 0.:
startx = dataws.readX(wsindex)[0]
if endx <= 0.:
endx = dataws.readX(wsindex)[-1]
# Set up RefineProfileParameters object
runner = RefineProfileParameters(self.glog)
# Locate refinement record table
profilewsname, braggpeakwsname, bkgdtype, bkgdparamwsname, laststep = self._parseRecordTable(laststepindex)
# Set up runner and refine
runner.setupMonteCarloRefine(numcycles, parametersToFit)
outwsname, outprofilewsname, outbraggpeakwsname = self._genOutputWorkspace(str(dataws), profilewsname, braggpeakwsname)
# Set up input and output
runner.setInputs(str(dataws), self._peakType, profilewsname, braggpeakwsname, bkgdtype, bkgdparamwsname)
# FIXME - Need to verify whether input and output background parameter ws name can be same
runner.setOutputs(outwsname, outprofilewsname, outbraggpeakwsname, bkgdparamwsname)
# Refine and record pre and post refinement information
self._recordPreRefineInfo(runner, laststep)
runner.refine(numcycles, parametersToFit, startx, endx)
self._recordPostRefineInfo(runner)
# Group newly generated workspaces and add name to reposiotry
if self._wsgroupCreated is True:
api.GroupWorkspaces(InputWorkspaces="%s, %s, %s, %s" % (outwsname, outprofilewsname, outbraggpeakwsname, self._wsgroupName),\
OutputWorkspace=self._wsgroupName)
else:
wsgroup = AnalysisDataService.retrieve(self._wsgroupName)
hasbkgd = list(wsgroup.getNames()).count(bkgdparamwsname)
if hasbkgd == 1:
api.GroupWorkspaces(InputWorkspaces="%s, %s, %s" % (outwsname, outprofilewsname, outbraggpeakwsname),\
OutputWorkspace=self._wsgroupName)
elif hasbkgd == 0:
api.GroupWorkspaces(InputWorkspaces="%s, %s, %s, %s" % (outwsname, outprofilewsname, outbraggpeakwsname, bkgdparamwsname),\
OutputWorkspace=self._wsgroupName)
else:
raise NotImplementedError("Impossible to have 1 workspace appeared twice in a workspace group.")
return
def isSetup(self):
""" Status whether refinement is set up.
"""
return self._isSetup
def saveProject(self, datawsname, wsindex, projectfname):
""" Save current to a project file
Note: MC setup table workspace is not generated in this class. So it won't be saved
"""
import os
# FIXME - Find out a good way to remove existing files/directories
if os.path.exists(projectfname) is True:
import shutil
try:
os.remove(projectfname)
except RuntimeError:
shutil.rmtree(projectfname)
except IOError:
shutil.rmtree(projectfname)
except OSError:
shutil.rmtree(projectfname)
api.SaveNexusProcessed(InputWorkspace=self._wsgroupName, Filename=projectfname, Append=False)
# Add data workspace, tracking record table to workspaces
# api.GroupWorkspaces(InputWorkspaces="%s, %s, %s" % (datawsname, self._recordwsname, self._wsgroupName),
# OutputWorkspace=self._wsgroupName)
self.glog.notice("Append record workspace %s" % (self._recordwsname))
api.SaveNexusProcessed(InputWorkspace=self._recordwsname, Filename=projectfname, Append=True)
self.glog.notice("Append data workspace %s" % (datawsname))
api.SaveNexusProcessed(InputWorkspace=datawsname, Filename=projectfname, Append=True)
# Create a new README table workspace for some other information
readmewsname = "READ_%s" % (self._ID)
readmews = api.CreateEmptyTableWorkspace(OutputWorkspace=readmewsname)
readmews.addColumn("str", "Function")
readmews.addColumn("str", "Type")
readmews.addRow(["Peak", "Not Important"])
readmews.addRow(["Background", "Not Important"])
readmews.addRow(["ID", str(self._ID)])
readmews.addRow(["Record", self._recordwsname])
readmews.addRow(["Data", str(datawsname)])
readmews.addRow(["Spectrum", str(wsindex)])
api.SaveNexusProcessed(InputWorkspace=readmewsname, Filename=projectfname, Append=True)
return
def _genRecordTable(self):
""" Generate record table
"""
tablews = api.CreateEmptyTableWorkspace(OutputWorkspace=self._recordwsname)
tablews.addColumn("int", "Step")
tablews.addColumn("str", "OutProfile")
tablews.addColumn("str", "OutReflection")
tablews.addColumn("str", "OutBackgroud")
tablews.addColumn("str", "OutBckgroundParam")
tablews.addColumn("str", "Refine")
tablews.addColumn("double", "RwpOut")
tablews.addColumn("int", "LastStep")
tablews.addColumn("double", "RwpIn")
tablews.addColumn("str", "InProfile")
tablews.addColumn("str", "InReflection")
tablews.addColumn("str", "InBackgroud")
tablews.addColumn("str", "InBckgroundParam")
self._recordws = tablews
return
def _parseRecordTable(self, laststep):
""" Parse record table and return the last refinement result
Notice that 'last row' in record table might not be a valid row (incomplete).
It might be caused by an exception raised in refinement or its setup.
Class variable _recordWSLastRowInvalid is used to indicate this
"""
# Retrieve record workspace
self._recordws = AnalysisDataService.retrieve(str(self._recordwsname))
numrows = self._recordws.rowCount()
if numrows == 0:
raise NotImplementedError("Empty record table workspace. ")
# Find last valid row
lastvalidrow = -1
lastrow = numrows-1
self._recordwsLastRowValid = False
while self._recordwsLastRowValid is False and lastrow >= 0:
profilewsname = self._recordws.cell(lastrow, 1)
if profilewsname == "":
self.glog.warning("Profile workspace name is emtpy in row %d!" % (lastrow))
lastrow -= 1
else:
self._recordwsLastRowValid = True
lastvalidrow = lastrow
# ENDWHILE
if lastvalidrow < 0:
raise NotImplementedError("XXX")
# Find out last step row
lastrecordedstep = self._recordws.cell(lastvalidrow, 0)
self.glog.notice("Last recorded valid step is %d. " % (lastrecordedstep))
self._lastValidStep = lastrecordedstep
self._lastValidRowIndex = lastvalidrow
if laststep > lastrecordedstep:
self.glog.warning("Last step %d is not recorded. Using step %d instead. " %\
(laststep, lastrecordedstep))
laststep = lastrecordedstep
elif laststep < 0:
self.glog.notice("Using default last valid step %d. " % (self._lastValidStep))
laststep = self._lastValidStep
profilewsname = ""
while lastvalidrow >= 0:
step = self._recordws.cell(lastvalidrow, 0)
if step != laststep:
lastvalidrow -= 1
else:
profilewsname = self._recordws.cell(lastvalidrow, 1).strip()
reflectwsname = self._recordws.cell(lastvalidrow, 2).strip()
bkgdtype = self._recordws.cell(lastrow, 3).strip()
bkgdparamwsname = self._recordws.cell(lastrow, 4).strip()
if profilewsname == "":
raise NotImplementedError("Profile workspace name is emtpy in row %d. It is not supposed to happen." %\
(lastvalidrow))
break
# ENDWHILE
if profilewsname == "":
raise NotImplementedError("Step %d is not found in record table. It is impossible. " %\
(laststep))
# Current step
self._currstep = self._lastValidStep + 1
self.glog.notice("Current step is %d" % (self._currstep))
# Set up for other informatin
# Peak type
self._peakType = self._recordws.cell(0, 9).strip()
# Background type
self._bkgdType = bkgdtype.strip()
return (profilewsname, reflectwsname, bkgdtype, bkgdparamwsname, laststep)
def _recordPreRefineInfo(self, refiner, laststep):
""" Record pre-refinement information
"""
rectablews = mtd[self._recordwsname]
numrows = rectablews.rowCount()
if self._recordWSLastRowInvalid is False:
self._currstep = numrows
rectablews.addRow([self._currstep, "", "", "", "", "", -1.0, laststep, -1.0, "profilews",\
"reflectionws", "Polynomial", "BkgdParm"])
else:
self._currstep = numrows-1
laststep = self._lastValidStep
# print "*** Record workspace has %d rows. current step = %d. " % (rectablews.rowCount(), self._currstep)
if len(refiner.paramToFit) > 0:
rectablews.setCell(self._currstep, 5, str(refiner.paramToFit))
rectablews.setCell(self._currstep, 9, str(refiner.inprofilewsname))
rectablews.setCell(self._currstep, 10, str(refiner.inreflectionwsname))
rectablews.setCell(self._currstep, 11, str(refiner.bkgdtype))
rectablews.setCell(self._currstep, 12, str(refiner.bkgdtablewsname))
return
def _recordPostRefineInfo(self, refiner):
""" Record post-refinement information, i.e., refinement result
"""
# Parse profile table workspace
# print "****** outprofilews type = ", type(refiner.outprofilewsname)
outprofilews = AnalysisDataService.retrieve(str(refiner.outprofilewsname))
# outprofilews = api.mtd[refiner.outprofilewsname]
# FIXME - Use Name[0], Value[1] as default
numpars = outprofilews.rowCount()
rwp = None
for i in xrange(numpars):
parname = outprofilews.cell(i, 0)
if parname.lower() == "rwp":
rwp = outprofilews.cell(i, 1)
break
# Set the record table workspace
rectablews = mtd[self._recordwsname]
#numrows = rectablews.rowCount()
# currstep = numrows-1
rectablews.setCell(self._currstep, 1, str(refiner.outprofilewsname))
rectablews.setCell(self._currstep, 2, str(refiner.outreflectionwsname))
rectablews.setCell(self._currstep, 3, str(refiner.bkgdtype))
rectablews.setCell(self._currstep, 4, str(refiner.bkgdtablewsname))
if rwp is not None:
rectablews.setCell(self._currstep, 6, rwp)
return
def _genOutputWorkspace(self, datawsname, profilewsname, braggpeakwsname):
"""
"""
outwsname = "%s_%s_Step%d" % (datawsname, self._ID, self._currstep)
if profilewsname.count(self._ID) > 0:
outprofilewsname = profilewsname.split(self._ID)[0]
else:
outprofilewsname = profilewsname
outprofilewsname = "%s%s_Step%d" % (outprofilewsname, self._ID, self._currstep)
if braggpeakwsname.count(str(self._ID)) > 0:
outbpwsname = braggpeakwsname.split(self._ID)[0]
else:
outbpwsname = braggpeakwsname
outbpwsname = "%s%s_Step%d"%(outbpwsname, self._ID, self._currstep)
return (outwsname, outprofilewsname, outbpwsname)
#--------------------------------------------------------------------
def generateMCSetupTableProf9(wsname):
""" Generate a Le Bail fit Monte Carlo random walk setup table
"""
tablews = api.CreateEmptyTableWorkspace(OutputWorkspace=str(wsname))
tablews.addColumn("str", "Name")
tablews.addColumn("double", "A0")
tablews.addColumn("double", "A1")
tablews.addColumn("int", "NonNegative")
tablews.addColumn("int", "Group")
group = 0
tablews.addRow(["Dtt1" , 5.0, 0.0, 0, group])
tablews.addRow(["Dtt2" , 1.0, 0.0, 0, group])
tablews.addRow(["Zero" , 5.0, 0.0, 0, group])
group = 1
tablews.addRow(["Beta0" , 0.50, 1.0, 0, group])
tablews.addRow(["Beta1" , 0.05, 1.0, 0, group])
group = 2
tablews.addRow(["Alph0" , 0.05, 1.0, 0, group])
tablews.addRow(["Alph1" , 0.02, 1.0, 0, group])
group = 3
tablews.addRow(["Sig0", 2.0, 1.0, 1, group])
tablews.addRow(["Sig1", 2.0, 1.0, 1, group])
tablews.addRow(["Sig2", 2.0, 1.0, 1, group])
group = 4
tablews.addRow(["Gam0", 2.0, 1.0, 0, group])
tablews.addRow(["Gam1", 2.0, 1.0, 0, group])
tablews.addRow(["Gam2", 2.0, 1.0, 0, group])
return tablews
def generateMCSetupTableProf10(wsname):
""" Generate a Le Bail fit Monte Carlo random walk setup table
"""
tablews = api.CreateEmptyTableWorkspace(OutputWorkspace=str(wsname))
tablews.addColumn("str", "Name")
tablews.addColumn("double", "A0")
tablews.addColumn("double", "A1")
tablews.addColumn("int", "NonNegative")
tablews.addColumn("int", "Group")
group = 0
tablews.addRow(["Dtt1" , 5.0, 0.0, 0, group])
tablews.addRow(["Dtt1t" , 5.0, 0.0, 0, group])
tablews.addRow(["Dtt2t" , 1.0, 0.0, 0, group])
tablews.addRow(["Zero" , 5.0, 0.0, 0, group])
tablews.addRow(["Zerot" , 5.0, 0.0, 0, group])
tablews.addRow(["Width" , 0.0, 0.1, 1, group])
tablews.addRow(["Tcross", 0.0, 1.0, 1, group])
group = 1
tablews.addRow(["Beta0" , 0.50, 1.0, 0, group])
tablews.addRow(["Beta1" , 0.05, 1.0, 0, group])
tablews.addRow(["Beta0t", 0.50, 1.0, 0, group])
tablews.addRow(["Beta1t", 0.05, 1.0, 0, group])
group = 2
tablews.addRow(["Alph0" , 0.05, 1.0, 0, group])
tablews.addRow(["Alph1" , 0.02, 1.0, 0, group])
tablews.addRow(["Alph0t", 0.10, 1.0, 0, group])
tablews.addRow(["Alph1t", 0.05, 1.0, 0, group])
group = 3
tablews.addRow(["Sig0", 2.0, 1.0, 1, group])
tablews.addRow(["Sig1", 2.0, 1.0, 1, group])
tablews.addRow(["Sig2", 2.0, 1.0, 1, group])
group = 4
tablews.addRow(["Gam0", 2.0, 1.0, 0, group])
tablews.addRow(["Gam1", 2.0, 1.0, 0, group])
tablews.addRow(["Gam2", 2.0, 1.0, 0, group])
return tablews
def breakParametersGroups(tablews):
""" Break the parameter groups. Such that each parameter/row has an individual group
"""
numrows = tablews.rowCount()
for ir in xrange(numrows):
tablews.setCell(ir, 4, ir)
return
def resetParametersGroups(tablews):
""" Set the group number to original setup
"""
numrows = tablews.rowCount()
for ir in xrange(numrows):
parname = tablews.cell(ir, 0)
if parname in ["Dtt1", "Dtt1t", "Dtt2t", "Zero", "Zerot", "Width", "Tcross"]:
group = 0
elif parname in ["Beta0", "Beta1", "Beta0t", "Beta1t"]:
group = 1
elif parname in ["Alph0", "Alph1", "Alph0t", "Alph1t"]:
group = 2
elif parname in ["Sig0", "Sig1", "Sig2"]:
group = 3
else:
group = 4
tablews.setCell(ir, 4, group)
return
#pylint: disable=too-many-instance-attributes
class RefineProfileParameters(object):
""" Class to refine profile parameters ONE step
"""
datawsname = None
inprofilewsname = None
inreflectionwsname = None
bkgdtype = None
bkgdtablewsname = None
outprofilewsname = None
outreflectionwsname = None
outbkgdtablewsname = None
def __init__(self, glog):
""" Initialization
"""
self.peaktype = "NOSETUP"
# Output
self.outwsname = None
self.glog = glog
self.numsteps = 0
# Refine
self.paramToFit = []
# Flags
self._inputIsSetup = False
self._outputIsSetup = False
return
#pylint: disable=too-many-arguments
def setInputs(self, datawsname, peaktype, profilewsname, braggpeakwsname, bkgdtype, bkgdparwsname):
"""
"""
self.datawsname = datawsname
self.peaktype = peaktype
self.inprofilewsname = profilewsname
self.inreflectionwsname = braggpeakwsname
self.bkgdtype = bkgdtype
self.bkgdtablewsname = bkgdparwsname
self._inputIsSetup = True
return
def setOutputs(self, outwsname, profilewsname, braggpeakwsname, bkgdparwsname):
""" Set up the variables for output
"""
self.outwsname = outwsname
self.outprofilewsname = profilewsname
self.outreflectionwsname = braggpeakwsname
self.outbkgdtablewsname = bkgdparwsname
self._outputIsSetup = True
return
def setupMonteCarloRefine(self, numcycles, parametersToFit):
""" Set up refinement parameters
"""
if numcycles <= 0:
raise NotImplementedError("It is not allowed to set up a 0 or a negative number to MonteCarloRefine")
else:
self.numsteps = numcycles
self.paramToFit = parametersToFit
return
def calculate(self, startx, endx):
""" Do Le bail calculation
"""
if (self._inputIsSetup and self._outputIsSetup) is False:
raise NotImplementedError("Either input or output is not setup: inputIsStepUp = %s, outputIsSetup = %s" %\
(str(self._inputIsSetup), str(self._outputIsSetup)))
self.glog.information("**** Calculate: DataWorksapce = %s" % (str(self.datawsname)))
self.glog.information("**** Fit range: %f, %f" % (startx, endx))
self.glog.information("**** Profile workspace = %s, Reflection workspace = %s" % (
self.inprofilewsname, self.inreflectionwsname))
api.LeBailFit(\
Function = 'Calculation',\
InputWorkspace = self.datawsname,\
OutputWorkspace = self.outwsname,\
InputParameterWorkspace = self.inprofilewsname,\
OutputParameterWorkspace= self.outprofilewsname,\
InputHKLWorkspace = self.inreflectionwsname,\
OutputPeaksWorkspace = self.outreflectionwsname,\
FitRegion = '%f, %f' % (startx, endx),\
PeakType = self.peaktype,\
BackgroundType = self.bkgdtype,\
UseInputPeakHeights = False,\
PeakRadius = '8',\
BackgroundParametersWorkspace = self.bkgdtablewsname\
)
return
def refine(self, numsteps, parameternames, startx, endx):
""" Main execution body (doStep4)
"""
# Check validity
if (self._inputIsSetup and self._outputIsSetup) is False:
raise NotImplementedError("Either input or output is not setup.")
self.glog.debug("[Refine] Input profile workspace = %s" % (self.inprofilewsname))
# Update parameters' fit table
if numsteps > 0:
# Set up the default parameters to refine
# Set up the parameters to refine
# FIXME - It is found that in the 'load' mode, a ID???_Group_2 might be generated by running
# UpdatePeakParameterTableValue(). It is not a real new table workspace, but a link
# to the 'inprofilewsname'
# There must be something wrong in AnalysisDataService.
api.UpdatePeakParameterTableValue(\
InputWorkspace = self.inprofilewsname,\
Column = "FitOrTie",\
NewStringValue = "tie")
api.UpdatePeakParameterTableValue(\
InputWorkspace = self.inprofilewsname,\
Column = "FitOrTie",\
ParameterNames = parameternames,\
NewStringValue = "fit")
# Limit the range of MC
if parameternames.count("Width") > 0:
#self.cwl = 1.33
UpdatePeakParameterTableValue(\
InputWorkspace = self.inprofilewsname,\
Column = "Min",\
ParameterNames = ["Width"],\
NewFloatValue = 0.50) #cwl*0.25)
UpdatePeakParameterTableValue(\
InputWorkspace = self.inprofilewsname,\
Column = "Max",\
ParameterNames = ["Width"],\
NewFloatValue = 1.25) #cwl*4.0)
# Generate Monte carlo table
wsname = "MCSetupParameterTable"
if self.peaktype == "NeutronBk2BkExpConvPVoigt":
tablews = generateMCSetupTableProf9(wsname)
elif self.peaktype == "ThermalNeutronBk2BkExpConvPVoigt":
tablews = generateMCSetupTableProf10(wsname)
else:
raise NotImplementedError("Peak type %s is not supported to set up MC table." % (self.peaktype))
api.LeBailFit(\
InputWorkspace = self.datawsname,\
OutputWorkspace = self.outwsname,\
InputParameterWorkspace = self.inprofilewsname,\
OutputParameterWorkspace = self.outprofilewsname,\
InputHKLWorkspace = self.inreflectionwsname,\
OutputPeaksWorkspace = self.outreflectionwsname,\
FitRegion = '%f, %f' % (startx, endx),\
Function = 'MonteCarlo',\
NumberMinimizeSteps = numsteps,\
PeakType = self.peaktype,\
BackgroundType = self.bkgdtype,\
BackgroundParametersWorkspace = self.bkgdtablewsname,\
UseInputPeakHeights = False,\
PeakRadius ='8',\
Minimizer = 'Levenberg-Marquardt',\
MCSetupWorkspace = str(wsname),\
Damping = '5.0',\
RandomSeed = 0,\
AnnealingTemperature = 100.0,\
DrunkenWalk = True)
# ENDIF (step)
return
# Register algorithm with Mantid
AlgorithmFactory.subscribe(RefinePowderDiffProfileSeq)