Skip to content

Commit

Permalink
Add new ResNorm algorithm
Browse files Browse the repository at this point in the history
Refs #11703
  • Loading branch information
DanNixon committed May 7, 2015
1 parent 3c49726 commit fda0956
Show file tree
Hide file tree
Showing 2 changed files with 187 additions and 102 deletions.
@@ -1,94 +1,166 @@
#pylint: disable=no-init
from mantid.api import PythonAlgorithm, AlgorithmFactory
from mantid.kernel import StringListValidator, StringMandatoryValidator
from mantid.api import PythonAlgorithm, AlgorithmFactory, MatrixWorkspaceProperty
from mantid.kernel import Direction
from mantid.simpleapi import *
from mantid import config, logger
import os


class ResNorm(PythonAlgorithm):

_res_ws = None
_van_ws = None
_e_min = None
_e_max = None
_create_output = None
_out_ws = None


def category(self):
return "Workflow\\MIDAS;PythonAlgorithms"


def summary(self):
return "This algorithm creates a group 'normalisation' file by taking a resolution file and fitting it to all the groups in the resolution (vanadium) data file which has the same grouping as the sample data of interest."
return "This algorithm creates a group 'normalisation' file by taking \
a resolution file and fitting it to all the groups in the \
resolution (vanadium) data file which has the same grouping as \
the sample data of interest."


def PyInit(self):
self.declareProperty(name='InputType', defaultValue='File',
validator=StringListValidator(['File','Workspace']),
doc='Origin of data input - File (.nxs) or Workspace')
self.declareProperty(name='Instrument', defaultValue='iris',
validator=StringListValidator(['irs','iris','osi','osiris']),
doc='Instrument')
self.declareProperty(name='Analyser', defaultValue='graphite002',
validator=StringListValidator(['graphite002','graphite004']),
doc='Analyser & reflection')
self.declareProperty(name='VanNumber', defaultValue='',
validator=StringMandatoryValidator(),
doc='Sample run number')
self.declareProperty(name='ResInputType',defaultValue='File',
validator=StringListValidator(['File','Workspace']),
doc='Origin of res input - File (_res.nxs) or Workspace')
self.declareProperty(name='ResNumber', defaultValue='',
validator=StringMandatoryValidator(),
doc='Resolution run number')
self.declareProperty(name='EnergyMin', defaultValue=-0.2,
self.declareProperty(MatrixWorkspaceProperty('ResolutionWorkspace', '',
direction=Direction.Input),
doc='Workspace containing resolution')

self.declareProperty(MatrixWorkspaceProperty('VanadiumWorkspace', '',
direction=Direction.Input),
doc='Workspace containing reduction of vanadium run')

self.declareProperty(name='EnergyMin',
defaultValue=-0.2,
doc='Minimum energy for fit. Default=-0.2')
self.declareProperty(name='EnergyMax', defaultValue=0.2,

self.declareProperty(name='EnergyMax',
defaultValue=0.2,
doc='Maximum energy for fit. Default=0.2')
self.declareProperty(name='VanBinning', defaultValue=1,
doc='Binning value (integer) for sample. Default=1')
self.declareProperty(name='Plot', defaultValue='None',
validator=StringListValidator(['None','Intensity','Stretch','Fit','All']),
doc='Plot options')
self.declareProperty(name='Save', defaultValue=False,
doc='Switch Save result to nxs file Off/On')

self.declareProperty(name='CreateOutput',
defaultValue=False,
doc='Create additional fitting output')

self.declareProperty(MatrixWorkspaceProperty('OutputWorkspace', '',
direction=Direction.Output),
doc='Fitted parameter output')


def validateInputs(self):
self._get_properties()
issues = dict()

# Validate fitting range in energy
if self._e_min > self._e_max:
issues['EnergyMax'] = 'Must be less than EnergyMin'

# Resolution should only have one histogram
if mtd[self._res_ws].getNumberHistograms() != 1:
issues['ResolutionWorkspace'] = 'Must have exactly one histogram'

return issues


def _get_properties(self):
self._res_ws = self.getPropertyValue('ResolutionWorkspace')
self._van_ws = self.getPropertyValue('VanadiumWorkspace')
self._e_min = self.getProperty('EnergyMin').value
self._e_max = self.getProperty('EnergyMax').value
self._create_output = self.getProperty('CreateOutput').value
self._out_ws = self.getPropertyValue('OutputWorkspace')


def PyExec(self):
from IndirectImport import run_f2py_compatibility_test, is_supported_f2py_platform

if is_supported_f2py_platform():
import IndirectBayes as Main

run_f2py_compatibility_test()

self.log().information('ResNorm input')
inType = self.getPropertyValue('InputType')
prefix = self.getPropertyValue('Instrument')
ana = self.getPropertyValue('Analyser')
van = self.getPropertyValue('VanNumber')
rinType = self.getPropertyValue('ResInputType')
res = self.getPropertyValue('ResNumber')
emin = self.getPropertyValue('EnergyMin')
emax = self.getPropertyValue('EnergyMax')
nbin = self.getPropertyValue('VanBinning')

vname = prefix+van+'_'+ana+ '_red'
rname = prefix+res+'_'+ana+ '_res'
erange = [float(emin), float(emax)]
plotOp = self.getPropertyValue('Plot')
saveOp = self.getProperty('Save').value

workdir = config['defaultsave.directory']
if inType == 'File':
vpath = os.path.join(workdir, vname+'.nxs') # path name for van nxs file
LoadNexusProcessed(Filename=vpath, OutputWorkspace=vname)
Vmessage = 'Vanadium from File : '+vpath
else:
Vmessage = 'Vanadium from Workspace : '+vname
if rinType == 'File':
rpath = os.path.join(workdir, rname+'.nxs') # path name for res nxs file
LoadNexusProcessed(Filename=rpath, OutputWorkspace=rname)
Rmessage = 'Resolution from File : '+rpath
else:
Rmessage = 'Resolution from Workspace : '+rname
logger.information(Vmessage)
logger.information(Rmessage)
Main.ResNormRun(vname,rname,erange,nbin,True,plotOp,saveOp)
from IndirectCommon import getWSprefix

van_ws = mtd[self._van_ws]
num_hist = van_ws.getNumberHistograms()

v_values = van_ws.getAxis(1).extractValues()
v_unit = van_ws.getAxis(1).getUnit().unitID()

padded_res_ws = self._pad_res_ws(num_hist)

input_str = ''
for idx in range(num_hist):
input_str += '%s,i%d;' % (padded_res_ws, idx)

out_name = getWSprefix(self._res_ws) + 'ResNorm_Fit'

fit_params = PlotPeakByLogValue(Input=input_str,
OutputWorkspace=out_name,
Function='name=TabulatedFunction,Workspace=irs26173_graphite002_red,Scaling=1.0,Shift=0.0',
FitType='Individual',
PassWSIndexToFunction=True,
CreateOutput=self._create_output,
StartX=self._e_min,
EndX=self._e_max)

self._process_fit_params(fit_params, v_values, v_unit)
self.setProperty('OutputWorkspace', self._out_ws)

DeleteWorkspace(padded_res_ws)
if not self._create_output:
DeleteWorkspace(fit_params)


def _pad_res_ws(self, num_hist):
"""
Generate a resolution workspaes with the same number of histograms
as the vanadium run.
@param num_hist Number of histograms required
@return Padded workspace
"""

ws_name = '__%s_%dspec' % (self._res_ws, num_hist)

for idx in range(num_hist):
input_ws_1 = ws_name
if idx == 0:
input_ws_1 = self._res_ws

AppendSpectra(InputWorkspace1=input_ws_1,
InputWorkspace2=self._res_ws,
OutputWorkspace=ws_name)

return mtd[ws_name]


def _process_fit_params(self, fit_params, x_axis, x_unit):
"""
Generate the output workspace containing fit parameters using the
fit parameter table from PlotPeakByLogValue.
@param fit_params Fit parameters as table workspace
@param x_axis Values for X axis of output workspace
@param x_unit Unit for X axis of output workspace
"""

col_names = fit_params.getColumnNames()

vert_axis_values = ['Scaling', 'Shift']

y_values = []
e_values = []

for name in vert_axis_values:
y_values.extend(fit_params.column(col_names.index(name)))
e_values.extend(fit_params.column(col_names.index(name + '_Err')))

CreateWorkspace(OutputWorkspace=self._out_ws,
DataX=x_axis,
DataY=y_values,
DataE=e_values,
NSpec=len(vert_axis_values),
UnitX=x_unit,
VerticalAxisUnit='Text',
VerticalAxisValues=vert_axis_values)


# Register algorithm with Mantid
Expand Down
73 changes: 43 additions & 30 deletions Code/Mantid/docs/source/algorithms/ResNorm-v1.rst
Expand Up @@ -9,41 +9,54 @@
Description
-----------

The routine varies the width of the resolution file to give a 'stretch
factor' and the area provides an intensity normalisation factor. The
fitted parameters are in the group workspace with suffix \_ResNorm with
additional suffices of Intensity & Stretch. The fitted data are in the
workspace ending in \_ResNorm\_Fit.

This routine was originally part of the MODES package.
TODO

Usage
-----

**Example - a basic example using ResNorm.**

.. code-block:: python
def createSampleWorkspace(name, random=False):
""" Creates a sample workspace with a single lorentzian that looks like IRIS data"""
import os
function = "name=Lorentzian,Amplitude=8,PeakCentre=5,FWHM=0.7"
ws = CreateSampleWorkspace("Histogram", Function="User Defined", UserDefinedFunction=function, XUnit="DeltaE", Random=True, XMin=0, XMax=10, BinWidth=0.01)
ws = CropWorkspace(ws, StartWorkspaceIndex=0, EndWorkspaceIndex=9)
ws = ScaleX(ws, -5, "Add")
ws = ScaleX(ws, 0.1, "Multiply")
#load instrument and instrument parameters
LoadInstrument(ws, InstrumentName='IRIS')
path = os.path.join(config['instrumentDefinition.directory'], 'IRIS_graphite_002_Parameters.xml')
LoadParameterFile(ws, Filename=path)
ws = RenameWorkspace(ws, OutputWorkspace=name)
return ws
ws = createSampleWorkspace("irs26173_graphite002_red", random=True)
res = createSampleWorkspace("irs26173_graphite002_res")
ResNorm(VanNumber='26176', ResNumber='26173', InputType='Workspace', ResInputType='Workspace', Instrument='irs', Analyser='graphite002', Plot='None')
.. testcode:: ExIRISResNorm

def createSampleWorkspace(name, num_spec=10, random=False):
"""
Creates a sample workspace with a single lorentzian that looks like IRIS data
"""
import os

# Create sample data
function = "name=Lorentzian,Amplitude=8,PeakCentre=5,FWHM=0.7"
ws = CreateSampleWorkspace("Histogram",
Function="User Defined",
UserDefinedFunction=function,
XUnit="DeltaE",
Random=random,
XMin=0,
XMax=10,
BinWidth=0.01)

# Reduce number of spectra
ws = CropWorkspace(ws,
StartWorkspaceIndex=0,
EndWorkspaceIndex=num_spec-1)

ws = ScaleX(ws, -5, "Add")
ws = ScaleX(ws, 0.1, "Multiply")

# Load instrument and instrument parameters
LoadInstrument(ws, InstrumentName='IRIS')
path = os.path.join(config['instrumentDefinition.directory'], 'IRIS_graphite_002_Parameters.xml')
LoadParameterFile(ws, Filename=path)
ws = RenameWorkspace(ws, OutputWorkspace=name)

return ws


van = createSampleWorkspace("irs26173_graphite002_red", random=True)
res = createSampleWorkspace("irs26173_graphite002_res", num_spec=1)

res_norm = ResNorm(ResolutionWorkspace=res,
VanadiumWorkspace=van)


.. categories::

0 comments on commit fda0956

Please sign in to comment.