-
Elliot Oram authored
Refs #13826
Elliot Oram authoredRefs #13826
Code owners
Assign users and groups as approvers for specific file changes. Learn more.
Quasi.cpp 12.11 KiB
#include "MantidAPI/TextAxis.h"
#include "MantidQtCustomInterfaces/Indirect/Quasi.h"
#include "MantidQtCustomInterfaces/UserInputValidator.h"
using namespace Mantid::API;
namespace MantidQt {
namespace CustomInterfaces {
Quasi::Quasi(QWidget *parent) : IndirectBayesTab(parent), m_previewSpec(0) {
m_uiForm.setupUi(parent);
// Create range selector
auto eRangeSelector = m_uiForm.ppPlot->addRangeSelector("QuasiERange");
connect(eRangeSelector, SIGNAL(minValueChanged(double)), this,
SLOT(minValueChanged(double)));
connect(eRangeSelector, SIGNAL(maxValueChanged(double)), this,
SLOT(maxValueChanged(double)));
// Add the properties browser to the UI form
m_uiForm.treeSpace->addWidget(m_propTree);
m_properties["EMin"] = m_dblManager->addProperty("EMin");
m_properties["EMax"] = m_dblManager->addProperty("EMax");
m_properties["SampleBinning"] = m_dblManager->addProperty("Sample Binning");
m_properties["ResBinning"] = m_dblManager->addProperty("Resolution Binning");
m_dblManager->setDecimals(m_properties["EMin"], NUM_DECIMALS);
m_dblManager->setDecimals(m_properties["EMax"], NUM_DECIMALS);
m_dblManager->setDecimals(m_properties["SampleBinning"], INT_DECIMALS);
m_dblManager->setDecimals(m_properties["ResBinning"], INT_DECIMALS);
m_propTree->addProperty(m_properties["EMin"]);
m_propTree->addProperty(m_properties["EMax"]);
m_propTree->addProperty(m_properties["SampleBinning"]);
m_propTree->addProperty(m_properties["ResBinning"]);
// Set default values
m_dblManager->setValue(m_properties["SampleBinning"], 1);
m_dblManager->setMinimum(m_properties["SampleBinning"], 1);
m_dblManager->setValue(m_properties["ResBinning"], 1);
m_dblManager->setMinimum(m_properties["ResBinning"], 1);
// Connect optional form elements with enabling checkboxes
connect(m_uiForm.chkFixWidth, SIGNAL(toggled(bool)), m_uiForm.mwFixWidthDat,
SLOT(setEnabled(bool)));
connect(m_uiForm.chkUseResNorm, SIGNAL(toggled(bool)), m_uiForm.dsResNorm,
SLOT(setEnabled(bool)));
// Connect the data selector for the sample to the mini plot
connect(m_uiForm.dsSample, SIGNAL(dataReady(const QString &)), this,
SLOT(handleSampleInputReady(const QString &)));
connect(m_uiForm.dsResolution, SIGNAL(dataReady(const QString &)), this,
SLOT(handleResolutionInputReady(const QString &)));
// Connect the progrm selector to its handler
connect(m_uiForm.cbProgram, SIGNAL(currentIndexChanged(int)), this,
SLOT(handleProgramChange(int)));
// Connect preview spectrum spinner to handler
connect(m_uiForm.spPreviewSpectrum, SIGNAL(valueChanged(int)), this,
SLOT(previewSpecChanged(int)));
}
/**
* Set the data selectors to use the default save directory
* when browsing for input files.
*
* @param settings :: The current settings
*/
void Quasi::loadSettings(const QSettings &settings) {
m_uiForm.dsSample->readSettings(settings.group());
m_uiForm.dsResolution->readSettings(settings.group());
m_uiForm.dsResNorm->readSettings(settings.group());
m_uiForm.mwFixWidthDat->readSettings(settings.group());
}
void Quasi::setup() {}
/**
* Validate the form to check the program can be run
*
* @return :: Whether the form was valid
*/
bool Quasi::validate() {
UserInputValidator uiv;
uiv.checkDataSelectorIsValid("Sample", m_uiForm.dsSample);
uiv.checkDataSelectorIsValid("Resolution", m_uiForm.dsResolution);
// check that the ResNorm file is valid if we are using it
if (m_uiForm.chkUseResNorm->isChecked()) {
uiv.checkDataSelectorIsValid("ResNorm", m_uiForm.dsResNorm);
}
// check fixed width file exists
if (m_uiForm.chkFixWidth->isChecked() && !m_uiForm.mwFixWidthDat->isValid()) {
uiv.checkMWRunFilesIsValid("Width", m_uiForm.mwFixWidthDat);
}
QString errors = uiv.generateErrorMessage();
if (!errors.isEmpty()) {
emit showMessageBox(errors);
return false;
}
QString program = m_uiForm.cbProgram->currentText();
if (program == "Stretched Exponential") {
QString resName = m_uiForm.dsResolution->getCurrentDataName();
if (!resName.endsWith("_res")) {
emit showMessageBox("Stretched Exponential program can only be used with "
"a resolution file.");
return false;
}
}
return true;
}
/**
* Collect the settings on the GUI and build a python
* script that runs Quasi
*/
void Quasi::run() {
// Using 1/0 instead of True/False for compatibility with underlying Fortran
// code
// in some places
bool save = false;
bool elasticPeak = false;
bool sequence = false;
bool fixedWidth = false;
std::string fixedWidthFile("");
bool useResNorm = false;
std::string resNormFile("");
std::string sampleName =
m_uiForm.dsSample->getCurrentDataName().toStdString();
std::string resName =
m_uiForm.dsResolution->getCurrentDataName().toStdString();
std::string program = m_uiForm.cbProgram->currentText().toStdString();
if (program == "Lorentzians") {
program = "QL";
} else {
program = "QSe";
}
// Collect input from fit options section
std::string background = m_uiForm.cbBackground->currentText().toStdString();
if (m_uiForm.chkElasticPeak->isChecked()) {
elasticPeak = true;
}
if (m_uiForm.chkSequentialFit->isChecked()) {
sequence = true;
}
if (m_uiForm.chkFixWidth->isChecked()) {
fixedWidth = true;
fixedWidthFile = m_uiForm.mwFixWidthDat->getFirstFilename().toStdString();
}
if (m_uiForm.chkUseResNorm->isChecked()) {
useResNorm = true;
resNormFile = m_uiForm.dsResNorm->getCurrentDataName().toStdString();
}
// Collect input from the properties browser
double eMin = m_properties["EMin"]->valueText().toDouble();
double eMax = m_properties["EMax"]->valueText().toDouble();
long sampleBins = m_properties["SampleBinning"]->valueText().toLong();
long resBins = m_properties["ResBinning"]->valueText().toLong();
// Output options
if (m_uiForm.chkSave->isChecked()) {
save = true;
}
std::string plot = m_uiForm.cbPlot->currentText().toStdString();
IAlgorithm_sptr runAlg = AlgorithmManager::Instance().create("QLRun");
runAlg->initialize();
runAlg->setProperty("Program", program);
runAlg->setProperty("SampleWorkspace", sampleName);
runAlg->setProperty("ResolutionWorkspace", resName);
runAlg->setProperty("ResNormWorkspace", resNormFile);
runAlg->setProperty("OutputWorkspaceFit", "fit");
runAlg->setProperty("OutputWorkspaceProb", "prob");
runAlg->setProperty("OutputWorkspaceResult", "result");
runAlg->setProperty("MinRange", eMin);
runAlg->setProperty("MaxRange", eMax);
runAlg->setProperty("SampleBins", sampleBins);
runAlg->setProperty("ResolutionBins", resBins);
runAlg->setProperty("Elastic", elasticPeak);
runAlg->setProperty("Background", background);
runAlg->setProperty("FixedWidth", fixedWidth);
runAlg->setProperty("UseResNorm", useResNorm);
runAlg->setProperty("WidthFile", fixedWidthFile);
runAlg->setProperty("Loop", sequence);
runAlg->setProperty("Save", save);
runAlg->setProperty("Plot", plot);
m_QuasiAlg = runAlg;
m_batchAlgoRunner->addAlgorithm(runAlg);
connect(m_batchAlgoRunner, SIGNAL(batchComplete(bool)), this,
SLOT(algorithmComplete(bool)));
m_batchAlgoRunner->executeBatchAsync();
}
/**
* Updates the data and fit curves on the mini plot.
*/
void Quasi::algorithmComplete(bool error) {
if (error)
return;
else
updateMiniPlot();
}
void Quasi::updateMiniPlot() {
// Update sample plot
if (!m_uiForm.dsSample->isValid())
return;
m_uiForm.ppPlot->clear();
QString sampleName = m_uiForm.dsSample->getCurrentDataName();
m_uiForm.ppPlot->addSpectrum("Sample", sampleName, m_previewSpec);
// Update fit plot
QString program = m_uiForm.cbProgram->currentText();
if (program == "Lorentzians")
program = "QL";
else
program = "QSe";
QString resName = m_uiForm.dsResolution->getCurrentDataName();
// Should be either "red", "sqw" or "res"
QString resType = resName.right(3);
// Get the correct workspace name based on the type of resolution file
if (program == "QL") {
if (resType == "res")
program += "r";
else
program += "d";
}
QString outWsName = sampleName.left(sampleName.size() - 3) + program +
"_Workspace_" + QString::number(m_previewSpec);
if (!AnalysisDataService::Instance().doesExist(outWsName.toStdString()))
return;
MatrixWorkspace_sptr outputWorkspace =
AnalysisDataService::Instance().retrieveWS<MatrixWorkspace>(
outWsName.toStdString());
TextAxis *axis = dynamic_cast<TextAxis *>(outputWorkspace->getAxis(1));
for (size_t histIndex = 0; histIndex < outputWorkspace->getNumberHistograms();
histIndex++) {
QString specName = QString::fromStdString(axis->label(histIndex));
QColor curveColour;
if (specName.contains("fit.1"))
curveColour = Qt::red;
else if (specName.contains("fit.2"))
curveColour = Qt::magenta;
else if (specName.contains("diff.1"))
curveColour = Qt::green;
else if (specName.contains("diff.2"))
curveColour = Qt::cyan;
else
continue;
m_uiForm.ppPlot->addSpectrum(specName, outputWorkspace, histIndex,
curveColour);
}
}
/**
* Plots the loaded file to the miniplot and sets the guides
* and the range
*
* @param filename :: The name of the workspace to plot
*/
void Quasi::handleSampleInputReady(const QString &filename) {
MatrixWorkspace_sptr inWs =
AnalysisDataService::Instance().retrieveWS<MatrixWorkspace>(
filename.toStdString());
int numHist = static_cast<int>(inWs->getNumberHistograms()) - 1;
m_uiForm.spPreviewSpectrum->setMaximum(numHist);
updateMiniPlot();
QPair<double, double> range = m_uiForm.ppPlot->getCurveRange("Sample");
auto eRangeSelector = m_uiForm.ppPlot->getRangeSelector("QuasiERange");
setRangeSelector(eRangeSelector, m_properties["EMin"], m_properties["EMax"],
range);
setPlotPropertyRange(eRangeSelector, m_properties["EMin"],
m_properties["EMax"], range);
}
/**
* Toggles the use ResNorm option depending on if the resolution file is a
* resolution or vanadoum reduction.
* @param wsName The name of the workspace loaded
*/
void Quasi::handleResolutionInputReady(const QString &wsName) {
bool isResolution(wsName.endsWith("_res"));
m_uiForm.chkUseResNorm->setEnabled(isResolution);
if (!isResolution)
m_uiForm.chkUseResNorm->setChecked(false);
}
/**
* Updates the property manager when the lower guide is moved on the mini plot
*
* @param min :: The new value of the lower guide
*/
void Quasi::minValueChanged(double min) {
m_dblManager->setValue(m_properties["EMin"], min);
}
/**
* Updates the property manager when the upper guide is moved on the mini plot
*
* @param max :: The new value of the upper guide
*/
void Quasi::maxValueChanged(double max) {
m_dblManager->setValue(m_properties["EMax"], max);
}
/**
* Handles when properties in the property manager are updated.
*
* @param prop :: The property being updated
* @param val :: The new value for the property
*/
void Quasi::updateProperties(QtProperty *prop, double val) {
UNUSED_ARG(val);
auto eRangeSelector = m_uiForm.ppPlot->getRangeSelector("QuasiERange");
if (prop == m_properties["EMin"] || prop == m_properties["EMax"]) {
auto bounds = qMakePair(m_dblManager->value(m_properties["EMin"]),
m_dblManager->value(m_properties["EMax"]));
setRangeSelector(eRangeSelector, m_properties["EMin"], m_properties["EMax"],
bounds);
}
}
/**
* Handles when the slected item in the program combobox
* is changed
*
* @param index :: The current index of the combobox
*/
void Quasi::handleProgramChange(int index) {
int numberOptions = m_uiForm.cbPlot->count();
switch (index) {
case 0:
m_uiForm.cbPlot->setItemText(numberOptions - 1, "Prob");
break;
case 1:
m_uiForm.cbPlot->setItemText(numberOptions - 1, "Beta");
break;
}
}
/**
* Handles setting a new preview spectrum on the preview plot.
*
* @param value Spectrum index
*/
void Quasi::previewSpecChanged(int value) {
m_previewSpec = value;
updateMiniPlot();
}
} // namespace CustomInterfaces
} // namespace MantidQt