Newer
Older
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
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]);
}
funcIndex++;
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]);
}
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["UseDeltaFunc"])
updatePlotOptions();
else if (prop == m_properties["UseFABADA"]) {
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
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]);
}
}
}
}
/**
* Populates the plot combobox
*/
void ConvFit::updatePlotOptions() {
m_uiForm.cbPlotType->clear();
const bool deltaFunction = m_blnManager->value(m_properties["UseDeltaFunc"]);
const int fitFunctionType = m_uiForm.cbFitType->currentIndex();
QStringList plotOptions;
plotOptions << "None";
if (deltaFunction && fitFunctionType < 3) {
plotOptions << "Height";
}
QStringList params = QStringList();
if (fitFunctionType != 2) {
params = getFunctionParameters(m_uiForm.cbFitType->currentText());
} else {
params = getFunctionParameters(QString("One Lorentzian"));
}
if (fitFunctionType != 0) {
plotOptions.append(params);
}
if (fitFunctionType != 0 || deltaFunction) {
plotOptions << "All";
}
m_uiForm.cbPlotType->addItems(plotOptions);
}
} // namespace IDA
} // namespace CustomInterfaces