Skip to content

Commit

Permalink
Merge branch 'feature/9345_indirect_jumpfit_python_algorithm' into de…
Browse files Browse the repository at this point in the history
…velop

Conflicts:
	Code/Mantid/scripts/Inelastic/IndirectJumpFit.py

Refs #9345
  • Loading branch information
DanNixon committed Aug 22, 2014
2 parents acefddc + b0c427a commit 8b2a8d4
Show file tree
Hide file tree
Showing 7 changed files with 230 additions and 143 deletions.
@@ -0,0 +1,153 @@
from mantid.kernel import *
from mantid.api import *
from mantid.simpleapi import *
from mantid import logger, mtd
from IndirectCommon import *
from IndirectImport import import_mantidplot

import os.path


class JumpFit(PythonAlgorithm):


def category(self):
return 'Workflow\\Inelastic;PythonAlgorithms;Inelastic'


def PyInit(self):
self.declareProperty(WorkspaceProperty('InputWorkspace', '', direction=Direction.Input),
doc='Input workspace')

valid_functions = ['ChudleyElliot', 'HallRoss', 'FickDiffusion', 'TeixeiraWater']
self.declareProperty(name='Function', defaultValue=valid_functions[0],
validator=StringListValidator(valid_functions),
doc='The fit function to use')

self.declareProperty(name='Width', defaultValue=0, validator=IntMandatoryValidator(),
doc='Spectrum in the workspace to use for fiting')

self.declareProperty(name='QMin', defaultValue=0.0, validator=FloatMandatoryValidator(),
doc='Lower bound of Q range to use for fitting')
self.declareProperty(name='QMax', defaultValue=0.0, validator=FloatMandatoryValidator(),
doc='Upper bound of Q range to use for fitting')

self.declareProperty(name='Output', defaultValue='', direction=Direction.InOut,
doc='Output name')

self.declareProperty(name='Verbose', defaultValue=False, doc='Output more verbose message to log')
self.declareProperty(name='Plot', defaultValue=False, doc='Plot result workspace')
self.declareProperty(name='Save', defaultValue=False, doc='Save result workspace to nexus file in the default save directory')


def PyExec(self):
in_ws = self.getPropertyValue('InputWorkspace')
out_name = self.getPropertyValue('Output')

jump_function = self.getProperty('Function').value
width = self.getProperty('Width').value
q_min = self.getProperty('QMin').value
q_max = self.getProperty('QMax').value

verbose = self.getProperty('Verbose').value
plot = self.getProperty('Plot').value
save = self.getProperty('Save').value

workdir = getDefaultWorkingDirectory()

StartTime('Jump fit : ' + jump_function + ' ; ')

# Select the width we wish to fit
spectrum_ws = "__" + in_ws
ExtractSingleSpectrum(InputWorkspace=in_ws, OutputWorkspace=spectrum_ws, WorkspaceIndex=width)

# Convert to HWHM
Scale(InputWorkspace=spectrum_ws, Factor=0.5, OutputWorkspace=spectrum_ws)

# Crop the workspace between the given ranges
if verbose:
logger.notice('Cropping from Q= ' + str(q_min) + ' to ' + str(q_max))

# Give the user some extra infromation if required
if verbose:
in_run = mtd[in_ws].getRun()
try:
log = in_run.getLogData('fit_program')
if log:
val = log.value
logger.notice('Fit program was : ' + val)
except RuntimeError:
# If we couldn't find the fit program, just pass
pass

logger.notice('Parameters in ' + in_ws)

x_data = mtd[in_ws].readX(0)
m_max = x_data[-1]

# Select fit function to use
if jump_function == 'ChudleyElliot':
# Chudley-Elliott: HWHM=(1-sin*(Q*L)/(Q*L))/Tau
# for Q->0 W=Q^2*L^2/(6*Tau)

t_val = 1.0 / m_max
l_val = 1.5
function = 'name=ChudleyElliot, Tau=' + str(t_val) + ', L=' + str(l_val)

elif jump_function == 'HallRoss':
# Hall-Ross: HWHM=(1-exp(-L*Q^2))/Tau
# for Q->0 W=A*Q^2*r

t_val = 1.0 / m_max
l_val = 1.5
function = 'name=HallRoss, Tau=' + str(t_val) + ', L=' + str(l_val)

elif jump_function == 'FickDiffusion':
# Fick: HWHM=D*Q^2

y_data = mtd[in_ws].readY(0)
diff = (y_data[2] - y_data[0]) / ((x_data[2] - x_data[0]) * (x_data[2] - x_data[0]))
function = 'name=FickDiffusion, D=' + str(diff)

elif jump_function == 'TeixeiraWater':
# Teixeira: HWHM=Q^2*L/((1+Q^2*L)*tau)
# for Q->0 W=

t_val = 1.0 / m_max
l_val = 1.5
function = 'name=TeixeiraWater, Tau=' + str(t_val) + ', L=' + str(l_val)

# Run fit function
if out_name is "":
out_name = in_ws[:-10] + '_' + jump_function + 'fit'

Fit(Function=function, InputWorkspace=spectrum_ws, CreateOutput=True, Output=out_name, StartX=q_min, EndX=q_max)
fit_workspace = out_name + '_Workspace'

# Populate sample logs
CopyLogs(InputWorkspace=in_ws, OutputWorkspace=fit_workspace)
AddSampleLog(Workspace=fit_workspace, LogName="jump_function", LogType="String", LogText=jump_function)
AddSampleLog(Workspace=fit_workspace, LogName="q_min", LogType="Number", LogText=str(q_min))
AddSampleLog(Workspace=fit_workspace, LogName="q_max", LogType="Number", LogText=str(q_max))

# Process output options
if save:
fit_path = os.path.join(workdir, fit_workspace + '.nxs')
SaveNexusProcessed(InputWorkspace=fit_workspace, Filename=fit_path)

if verbose:
logger.notice('Fit file is ' + fit_path)

if plot:
mtd_plot = import_mantidplot()
mtd_plot.plotSpectrum(fit_workspace, [0, 1, 2], True)

self.setProperty('Output', out_name)

DeleteWorkspace(Workspace=spectrum_ws)

EndTime('Jump fit : ' + jump_function + ' ; ')


# Register algorithm with Mantid
AlgorithmFactory.subscribe(JumpFit)
Expand Up @@ -3,6 +3,7 @@

#include "MantidAPI/MatrixWorkspace.h"
#include "MantidQtMantidWidgets/RangeSelector.h"
#include "MantidQtAPI/AlgorithmRunner.h"
#include "MantidQtAPI/QwtWorkspaceSpectrumData.h"

#include <QMap>
Expand Down Expand Up @@ -42,7 +43,7 @@ namespace MantidQt
This class defines a abstract base class for the different tabs of the Indirect Bayes interface.
Any joint functionality shared between each of the tabs should be implemented here as well as defining
shared member functions.
@author Samuel Jackson, STFC
Copyright &copy; 2013 ISIS Rutherford Appleton Laboratory & NScD Oak Ridge National Laboratory
Expand Down Expand Up @@ -112,17 +113,19 @@ namespace MantidQt
/// Function to run a string as python code
void runPythonScript(const QString& pyInput);
/// Function to read an instrument's resolution from the IPF using a string
bool getInstrumentResolution(const QString& filename, std::pair<double,double>& res);
bool getInstrumentResolution(const QString& filename, std::pair<double,double>& res);
/// Function to read an instrument's resolution from the IPF using a workspace pointer
bool getInstrumentResolution(Mantid::API::MatrixWorkspace_const_sptr ws, std::pair<double,double>& res);
/// Function to set the range limits of the plot
void setPlotRange(QtProperty* min, QtProperty* max, const std::pair<double, double>& bounds);
/// Function to set the position of the lower guide on the plot
void updateLowerGuide(QtProperty* lower, QtProperty* upper, double value);
void updateLowerGuide(QtProperty* lower, QtProperty* upper, double value);
/// Function to set the position of the upper guide on the plot
void updateUpperGuide(QtProperty* lower, QtProperty* upper, double value);
void updateUpperGuide(QtProperty* lower, QtProperty* upper, double value);
/// Function to get the range of the curve displayed on the mini plot
std::pair<double,double> getCurveRange();
/// Run an algorithm async
void runAlgorithm(const Mantid::API::IAlgorithm_sptr algorithm);

/// Plot of the input
QwtPlot* m_plot;
Expand All @@ -138,9 +141,11 @@ namespace MantidQt
QtDoublePropertyManager* m_dblManager;
/// Double editor facotry for the properties browser
DoubleEditorFactory* m_dblEdFac;
/// Algorithm runner object to execute algorithms on a seperate thread from the gui
MantidQt::API::AlgorithmRunner* m_algRunner;

};
} // namespace CustomInterfaces
} // namespace Mantid

#endif
#endif
Expand Up @@ -37,10 +37,10 @@ namespace MantidQt
void findAllWidths(Mantid::API::MatrixWorkspace_const_sptr ws);

private:
//The ui form
// The UI form
Ui::JumpFit m_uiForm;
// map of axis labels to spectrum number
std::map<std::string,int> spectraList;
// Map of axis labels to spectrum number
std::map<std::string, int> m_spectraList;

};
} // namespace CustomInterfaces
Expand Down
14 changes: 13 additions & 1 deletion Code/Mantid/MantidQt/CustomInterfaces/src/IndirectBayesTab.cpp
Expand Up @@ -15,7 +15,8 @@ namespace MantidQt
IndirectBayesTab::IndirectBayesTab(QWidget * parent) : QWidget(parent),
m_plot(new QwtPlot(parent)), m_curve(new QwtPlotCurve()), m_rangeSelector(new MantidWidgets::RangeSelector(m_plot)),
m_propTree(new QtTreePropertyBrowser()), m_properties(), m_dblManager(new QtDoublePropertyManager()),
m_dblEdFac(new DoubleEditorFactory())
m_dblEdFac(new DoubleEditorFactory()),
m_algRunner(new MantidQt::API::AlgorithmRunner(parent))
{
m_propTree->setFactoryForManager(m_dblManager, m_dblEdFac);
m_rangeSelector->setInfoOnly(false);
Expand Down Expand Up @@ -58,6 +59,17 @@ namespace MantidQt
emit executePythonScript(pyInput, true);
}

/**
* Runs an algorithm async
*
* @param algorithm :: The algorithm to be run
*/
void IndirectBayesTab::runAlgorithm(const Mantid::API::IAlgorithm_sptr algorithm)
{
algorithm->setRethrows(true);
m_algRunner->startAlgorithm(algorithm);
}

/**
* Plot a workspace to the miniplot given a workspace name and
* a specturm index.
Expand Down
65 changes: 33 additions & 32 deletions Code/Mantid/MantidQt/CustomInterfaces/src/JumpFit.cpp
@@ -1,3 +1,4 @@
#include "MantidAPI/AlgorithmManager.h"
#include "MantidAPI/Run.h"
#include "MantidAPI/TextAxis.h"
#include "MantidQtCustomInterfaces/JumpFit.h"
Expand Down Expand Up @@ -48,7 +49,7 @@ namespace MantidQt
uiv.checkDataSelectorIsValid("Sample", m_uiForm.dsSample);

//this workspace doesn't have any valid widths
if(spectraList.size() == 0)
if(m_spectraList.size() == 0)
{
uiv.addErrorMessage("Input workspace doesn't appear to contain any width data.");
}
Expand All @@ -69,50 +70,51 @@ namespace MantidQt
*/
void JumpFit::run()
{
QString verbose("False");
QString plot("False");
QString save("False");

QString sample = m_uiForm.dsSample->getCurrentDataName();
using namespace Mantid::API;

//fit function to use
QString fitFunction("CE");
// Fit function to use
QString fitFunction("ChudleyElliot");
switch(m_uiForm.cbFunction->currentIndex())
{
case 0:
fitFunction = "CE"; // Use Chudley-Elliott
fitFunction = "ChudleyElliot";
break;
case 1:
fitFunction = "HallRoss";
break;
case 2:
fitFunction = "Fick";
fitFunction = "FickDiffusion";
break;
case 3:
fitFunction = "Teixeira";
fitFunction = "TeixeiraWater";
break;
}

// Loaded workspace name
QString sample = m_uiForm.dsSample->getCurrentDataName();
auto ws = Mantid::API::AnalysisDataService::Instance().retrieve(sample.toStdString());

std::string widthText = m_uiForm.cbWidth->currentText().toStdString();
int width = spectraList[widthText];
QString widthTxt = boost::lexical_cast<std::string>(width).c_str();
long width = m_spectraList[widthText];

// Cropping values
QString QMin = m_properties["QMin"]->valueText();
QString QMax = m_properties["QMax"]->valueText();
IAlgorithm_sptr fitAlg = AlgorithmManager::Instance().create("JumpFit");
fitAlg->initialize();

//output options
if(m_uiForm.chkVerbose->isChecked()) { verbose = "True"; }
if(m_uiForm.chkSave->isChecked()) { save = "True"; }
if(m_uiForm.chkPlot->isChecked()) { plot = "True"; }
fitAlg->setProperty("InputWorkspace", ws);
fitAlg->setProperty("Function", fitFunction.toStdString());

QString pyInput =
"from IndirectJumpFit import JumpRun\n";
fitAlg->setProperty("Width", width);
fitAlg->setProperty("QMin", m_dblManager->value(m_properties["QMin"]));
fitAlg->setProperty("QMax", m_dblManager->value(m_properties["QMax"]));

pyInput += "JumpRun('"+sample+"','"+fitFunction+"',"+widthTxt+","+QMin+","+QMax+","
"Save="+save+", Plot="+plot+", Verbose="+verbose+")\n";
bool verbose = m_uiForm.chkVerbose->isChecked();
bool save = m_uiForm.chkSave->isChecked();
bool plot = m_uiForm.chkPlot->isChecked();
fitAlg->setProperty("Plot", plot);
fitAlg->setProperty("Verbose", verbose);
fitAlg->setProperty("Save", save);

runPythonScript(pyInput);
runAlgorithm(fitAlg);
}

/**
Expand All @@ -134,18 +136,17 @@ namespace MantidQt
*/
void JumpFit::handleSampleInputReady(const QString& filename)
{

auto ws = Mantid::API::AnalysisDataService::Instance().retrieve(filename.toStdString());
auto mws = boost::dynamic_pointer_cast<Mantid::API::MatrixWorkspace>(ws);

findAllWidths(mws);

if(spectraList.size() > 0)
if(m_spectraList.size() > 0)
{
m_uiForm.cbWidth->setEnabled(true);

std::string currentWidth = m_uiForm.cbWidth->currentText().toStdString();
plotMiniPlot(filename, spectraList[currentWidth]);
plotMiniPlot(filename, m_spectraList[currentWidth]);
std::pair<double,double> res;
std::pair<double,double> range = getCurveRange();

Expand Down Expand Up @@ -176,7 +177,7 @@ namespace MantidQt
void JumpFit::findAllWidths(Mantid::API::MatrixWorkspace_const_sptr ws)
{
m_uiForm.cbWidth->clear();
spectraList.clear();
m_spectraList.clear();

for (size_t i = 0; i < ws->getNumberHistograms(); ++i)
{
Expand Down Expand Up @@ -206,7 +207,7 @@ namespace MantidQt
}

cbItemName = title.substr(0, substrIndex);
spectraList[cbItemName] = static_cast<int>(i);
m_spectraList[cbItemName] = static_cast<int>(i);
m_uiForm.cbWidth->addItem(QString(cbItemName.c_str()));

//display widths f1.f1, f2.f1 and f2.f2
Expand All @@ -228,11 +229,11 @@ namespace MantidQt
QString sampleName = m_uiForm.dsSample->getCurrentDataName();
QString samplePath = m_uiForm.dsSample->getFullFilePath();

if(!sampleName.isEmpty() && spectraList.size() > 0)
if(!sampleName.isEmpty() && m_spectraList.size() > 0)
{
if(validate())
{
plotMiniPlot(sampleName, spectraList[text.toStdString()]);
plotMiniPlot(sampleName, m_spectraList[text.toStdString()]);
}
}
}
Expand Down

0 comments on commit 8b2a8d4

Please sign in to comment.