Newer
Older
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
m_singleFitOutputName =
runPythonCode(
QString(
"from IndirectCommon import getWSprefix\nprint getWSprefix('") +
m_cfInputWSName + QString("')\n"))
.trimmed();
m_singleFitOutputName +=
QString("conv_") + fitType + bgType + m_uiForm.spPlotSpectrum->text();
int maxIterations =
static_cast<int>(m_dblManager->value(m_properties["MaxIterations"]));
m_singleFitAlg = AlgorithmManager::Instance().create("Fit");
m_singleFitAlg->initialize();
m_singleFitAlg->setPropertyValue("Function", function->asString());
m_singleFitAlg->setPropertyValue("InputWorkspace",
m_cfInputWSName.toStdString());
m_singleFitAlg->setProperty<int>("WorkspaceIndex",
m_uiForm.spPlotSpectrum->text().toInt());
m_singleFitAlg->setProperty<double>(
"StartX", m_dblManager->value(m_properties["StartX"]));
m_singleFitAlg->setProperty<double>(
"EndX", m_dblManager->value(m_properties["EndX"]));
m_singleFitAlg->setProperty("Output", m_singleFitOutputName.toStdString());
m_singleFitAlg->setProperty("CreateOutput", true);
m_singleFitAlg->setProperty("OutputCompositeMembers", true);
m_singleFitAlg->setProperty("ConvolveMembers", true);
m_singleFitAlg->setProperty("MaxIterations", maxIterations);
m_singleFitAlg->setProperty(
"Minimizer", minimizerString(m_singleFitOutputName).toStdString());
m_batchAlgoRunner->addAlgorithm(m_singleFitAlg);
connect(m_batchAlgoRunner, SIGNAL(batchComplete(bool)), this,
SLOT(singleFitComplete(bool)));
m_batchAlgoRunner->executeBatchAsync();
}
/**
* Handle completion of the fit algorithm for single fit.
*
* @param error If the fit algorithm failed
*/
void ConvFit::singleFitComplete(bool error) {
disconnect(m_batchAlgoRunner, SIGNAL(batchComplete(bool)), this,
SLOT(singleFitComplete(bool)));
if (error) {
showMessageBox("Fit algorithm failed.");
return;
}
// Plot the line on the mini plot
m_uiForm.ppPlot->removeSpectrum("Guess");
m_uiForm.ppPlot->addSpectrum("Fit", m_singleFitOutputName + "_Workspace", 1,
Qt::red);
IFunction_sptr outputFunc = m_singleFitAlg->getProperty("Function");
QString functionName = m_uiForm.cbFitType->currentText();
// Get params.
QMap<QString, double> parameters;
std::vector<std::string> parNames = outputFunc->getParameterNames();
std::vector<double> parVals;
QStringList params = getFunctionParameters(functionName);
for (size_t i = 0; i < parNames.size(); ++i)
parVals.push_back(outputFunc->getParameter(parNames[i]));
for (size_t i = 0; i < parNames.size(); ++i)
parameters[QString(parNames[i].c_str())] = parVals[i];
// Populate Tree widget with values
// Background should always be f0
m_dblManager->setValue(m_properties["BGA0"], parameters["f0.A0"]);
m_dblManager->setValue(m_properties["BGA1"], parameters["f0.A1"]);
int fitTypeIndex = m_uiForm.cbFitType->currentIndex();
int funcIndex = 0;
int subIndex = 0;
// check if we're using a temperature correction
if (m_uiForm.ckTempCorrection->isChecked() &&
!m_uiForm.leTempCorrection->text().isEmpty()) {
subIndex++;
}
bool usingDeltaFunc = m_blnManager->value(m_properties["UseDeltaFunc"]);
// If using a delta function with any fit type or using two Lorentzians
bool usingCompositeFunc =
((usingDeltaFunc && fitTypeIndex > 0) || fitTypeIndex == 2);
QString prefBase = "f1.f1.";
if (usingDeltaFunc) {
QString key = prefBase;
if (usingCompositeFunc) {
key += "f0.";
m_dblManager->setValue(m_properties["DeltaHeight"], parameters[key]);
funcIndex++;
QString pref = prefBase;
if (usingCompositeFunc) {
pref += "f" + QString::number(funcIndex) + ".f" +
QString::number(subIndex) + ".";
} else {
pref += "f" + QString::number(subIndex) + ".";
}
if (fitTypeIndex == 1 || fitTypeIndex == 2) {
functionName = "Lorentzian 1";
for (auto it = params.begin(); it != params.end() - 3; ++it) {
QString functionParam = functionName + "." + *it;
QString paramValue = pref + *it;
m_dblManager->setValue(m_properties[functionParam],
parameters[paramValue]);
}
pref = prefBase;
pref += "f" + QString::number(funcIndex) + ".f" +
QString::number(subIndex) + ".";
functionName = "Lorentzian 2";
for (auto it = params.begin() + 3; it != params.end(); ++it) {
QString functionParam = functionName + "." + *it;
QString paramValue = pref + *it;
m_dblManager->setValue(m_properties[functionParam],
parameters[paramValue]);
}
} else {
for (auto it = params.begin(); it != params.end(); ++it) {
QString functionParam = functionName + "." + *it;
QString paramValue = pref + *it;
m_dblManager->setValue(m_properties[functionParam],
parameters[paramValue]);
}
funcIndex++;
m_pythonExportWsName = "";
}
/**
* Handles the user entering a new minimum spectrum index.
*
* Prevents the user entering an overlapping spectra range.
*
* @param value Minimum spectrum index
*/
void ConvFit::specMinChanged(int value) {
m_uiForm.spSpectraMax->setMinimum(value);
}
/**
* Handles the user entering a new maximum spectrum index.
*
* Prevents the user entering an overlapping spectra range.
*
* @param value Maximum spectrum index
*/
void ConvFit::specMaxChanged(int value) {
m_uiForm.spSpectraMin->setMaximum(value);
}
void ConvFit::minChanged(double val) {
m_dblManager->setValue(m_properties["StartX"], val);
}
void ConvFit::maxChanged(double val) {
m_dblManager->setValue(m_properties["EndX"], val);
}
void ConvFit::hwhmChanged(double val) {
const double peakCentre =
m_dblManager->value(m_properties["Lorentzian 1.PeakCentre"]);
// Always want FWHM to display as positive.
const double hwhm = std::fabs(val - peakCentre);
// Update the property
auto hwhmRangeSelector = m_uiForm.ppPlot->getRangeSelector("ConvFitHWHM");
hwhmRangeSelector->blockSignals(true);
m_dblManager->setValue(m_properties["Lorentzian 1.FWHM"], hwhm * 2);
hwhmRangeSelector->blockSignals(false);
}
void ConvFit::backgLevel(double val) {
m_dblManager->setValue(m_properties["BGA0"], val);
}
void ConvFit::updateRS(QtProperty *prop, double val) {
auto fitRangeSelector = m_uiForm.ppPlot->getRangeSelector("ConvFitRange");
auto backRangeSelector =
m_uiForm.ppPlot->getRangeSelector("ConvFitBackRange");
if (prop == m_properties["StartX"]) {
fitRangeSelector->setMinimum(val);
} else if (prop == m_properties["EndX"]) {
fitRangeSelector->setMaximum(val);
} else if (prop == m_properties["BGA0"]) {
backRangeSelector->setMinimum(val);
} else if (prop == m_properties["Lorentzian 1.FWHM"]) {
hwhmUpdateRS(val);
} else if (prop == m_properties["Lorentzian 1.PeakCentre"]) {
hwhmUpdateRS(m_dblManager->value(m_properties["Lorentzian 1.FWHM"]));
}
}
void ConvFit::hwhmUpdateRS(double val) {
const double peakCentre =
m_dblManager->value(m_properties["Lorentzian 1.PeakCentre"]);
auto hwhmRangeSelector = m_uiForm.ppPlot->getRangeSelector("ConvFitHWHM");
hwhmRangeSelector->setMinimum(peakCentre - val / 2);
hwhmRangeSelector->setMaximum(peakCentre + val / 2);
}
void ConvFit::checkBoxUpdate(QtProperty *prop, bool checked) {
UNUSED_ARG(checked);
if (prop == m_properties["UseFABADA"]) {
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
if (checked) {
// FABADA needs a much higher iteration limit
m_dblManager->setValue(m_properties["MaxIterations"], 20000);
m_properties["FABADA"]->addSubProperty(m_properties["OutputFABADAChain"]);
m_properties["FABADA"]->addSubProperty(m_properties["FABADAChainLength"]);
m_properties["FABADA"]->addSubProperty(
m_properties["FABADAConvergenceCriteria"]);
m_properties["FABADA"]->addSubProperty(
m_properties["FABADAJumpAcceptanceRate"]);
} else {
m_dblManager->setValue(m_properties["MaxIterations"], 500);
m_properties["FABADA"]->removeSubProperty(
m_properties["OutputFABADAChain"]);
m_properties["FABADA"]->removeSubProperty(
m_properties["FABADAChainLength"]);
m_properties["FABADA"]->removeSubProperty(
m_properties["FABADAConvergenceCriteria"]);
m_properties["FABADA"]->removeSubProperty(
m_properties["FABADAJumpAcceptanceRate"]);
void ConvFit::fitContextMenu(const QPoint &) {
QtBrowserItem *item(NULL);
item = m_cfTree->currentItem();
// is it a fit property ?
QtProperty *prop = item->property();
if (prop == m_properties["StartX"] || prop == m_properties["EndX"])
return;
// is it already fixed?
bool fixed = prop->propertyManager() != m_dblManager;
if (fixed && prop->propertyManager() != m_stringManager)
return;
// Create the menu
QMenu *menu = new QMenu("ConvFit", m_cfTree);
QAction *action;
if (!fixed) {
action = new QAction("Fix", m_parentWidget);
connect(action, SIGNAL(triggered()), this, SLOT(fixItem()));
} else {
action = new QAction("Remove Fix", m_parentWidget);
connect(action, SIGNAL(triggered()), this, SLOT(unFixItem()));
// Show the menu
menu->popup(QCursor::pos());
}
void ConvFit::fixItem() {
QtBrowserItem *item = m_cfTree->currentItem();
// Determine what the property is.
QtProperty *prop = item->property();
QtProperty *fixedProp = m_stringManager->addProperty(prop->propertyName());
QtProperty *fprlbl = m_stringManager->addProperty("Fixed");
fixedProp->addSubProperty(fprlbl);
m_stringManager->setValue(fixedProp, prop->valueText());
item->parent()->property()->addSubProperty(fixedProp);
m_fixedProps[fixedProp] = prop;
item->parent()->property()->removeSubProperty(prop);
}
void ConvFit::unFixItem() {
QtBrowserItem *item = m_cfTree->currentItem();
QtProperty *prop = item->property();
if (prop->subProperties().empty()) {
item = item->parent();
prop = item->property();
}
item->parent()->property()->addSubProperty(m_fixedProps[prop]);
item->parent()->property()->removeSubProperty(prop);
m_fixedProps.remove(prop);
QtProperty *proplbl = prop->subProperties()[0];
delete proplbl;
delete prop;
}
void ConvFit::showTieCheckbox(QString fitType) {
m_uiForm.ckTieCentres->setVisible(fitType == "Two Lorentzians");
}
/**
* Gets a list of parameters for a given fit function.
* @return List fo parameters
*/
QStringList ConvFit::getFunctionParameters(QString functionName) {
QStringList parameters;
if (functionName.compare("Two Lorentzians") == 0) {
functionName = "Lorentzian";
IFunction_sptr func =
FunctionFactory::Instance().createFunction(functionName.toStdString());
for (size_t i = 0; i < func->nParams(); i++) {
parameters << QString::fromStdString(func->parameterName(i));
if (functionName.compare("One Lorentzian") == 0) {
functionName = "Lorentzian";
if (functionName.compare("Zero Lorentzians") == 0) {
parameters.append("Zero");
} else {
IFunction_sptr func =
FunctionFactory::Instance().createFunction(functionName.toStdString());
for (size_t i = 0; i < func->nParams(); i++) {
parameters << QString::fromStdString(func->parameterName(i));
}
return parameters;
}
/**
* Handles a new fit function being selected.
* @param functionName Name of new fit function
*/
void ConvFit::fitFunctionSelected(const QString &functionName) {
// remove previous parameters from tree
m_cfTree->removeProperty(m_properties["FitFunction1"]);
m_cfTree->removeProperty(m_properties["FitFunction2"]);
m_uiForm.ckPlotGuess->setChecked(false);
m_uiForm.ckTieCentres->setChecked(false);
// Add new parameter elements
int fitFunctionIndex = m_uiForm.cbFitType->currentIndex();
QStringList parameters = getFunctionParameters(functionName);
// Two Loremtzians Fit
if (fitFunctionIndex == 2) {
m_properties["FitFunction1"] = m_grpManager->addProperty("Lorentzian 1");
m_cfTree->addProperty(m_properties["FitFunction1"]);
m_properties["FitFunction2"] = m_grpManager->addProperty("Lorentzian 2");
m_cfTree->addProperty(m_properties["FitFunction2"]);
} else {
m_properties["FitFunction1"] = m_grpManager->addProperty(functionName);
m_cfTree->addProperty(m_properties["FitFunction1"]);
}
// No fit function parameters required for Zero
if (parameters[0].compare("Zero") != 0) {
// Two Lorentzians Fit
if (fitFunctionIndex == 2) {
for (auto it = parameters.begin(); it != parameters.end(); ++it) {
if (count == 3) {
propName = "Lorentzian 2";
}
QString name = propName + "." + *it;
m_properties[name] = m_dblManager->addProperty(*it);
if (QString(*it).compare("FWHM") == 0) {
m_dblManager->setValue(m_properties[name], 0.0175);
} else {
m_dblManager->setValue(m_properties[name], 0.0);
}
if (QString(*it).compare("Amplitude") == 0 ||
QString(*it).compare("Intensity") == 0) {
m_dblManager->setValue(m_properties[name], 1.0);
}
m_dblManager->setDecimals(m_properties[name], NUM_DECIMALS);
if (count < 3) {
m_properties["FitFunction1"]->addSubProperty(m_properties[name]);
} else {
m_properties["FitFunction2"]->addSubProperty(m_properties[name]);
}
count++;
}
} else {
if (fitFunctionIndex == 1) {
propName = "Lorentzian 1";
} else {
propName = functionName;
}
for (auto it = parameters.begin(); it != parameters.end(); ++it) {
QString name = propName + "." + *it;
m_properties[name] = m_dblManager->addProperty(*it);
if (QString(*it).compare("FWHM") == 0) {
m_dblManager->setValue(m_properties[name], 0.0175);
} else {
m_dblManager->setValue(m_properties[name], 0.0);
}
if (QString(*it).compare("Amplitude") == 0 ||
QString(*it).compare("Intensity") == 0) {
m_dblManager->setValue(m_properties[name], 1.0);
}
m_dblManager->setDecimals(m_properties[name], NUM_DECIMALS);
m_properties["FitFunction1"]->addSubProperty(m_properties[name]);
}
}
}
}
} // namespace IDA
} // namespace CustomInterfaces