Newer
Older
m_uiForm.ppPlot->addSpectrum("Fit", ws, 1, Qt::red);
m_uiForm.ppPlot->addSpectrum("Diff", ws, 2, Qt::blue);
if (m_uiForm.ckPlotGuess->isChecked()) {
m_uiForm.ppPlot->removeSpectrum("Guess");
m_uiForm.ckPlotGuess->setChecked(false);
}
}
/**
* Updates the guess for the plot
*/
void ConvFit::plotGuess() {
m_uiForm.ppPlot->removeSpectrum("Guess");
// Do nothing if there is not a sample and resolution
if (!(m_uiForm.dsSampleInput->isValid() && m_uiForm.dsResInput->isValid() &&
m_uiForm.ckPlotGuess->isChecked()))
return;
if (m_uiForm.cbFitType->currentIndex() > 2) {
return;
bool tieCentres = (m_uiForm.cbFitType->currentIndex() > 1);
CompositeFunction_sptr function = createFunction(tieCentres);
if (m_cfInputWS == NULL) {
updatePlot();
const size_t binIndexLow =
m_cfInputWS->binIndexOf(m_dblManager->value(m_properties["StartX"]));
const size_t binIndexHigh =
m_cfInputWS->binIndexOf(m_dblManager->value(m_properties["EndX"]));
const size_t nData = binIndexHigh - binIndexLow;
std::vector<double> inputXData(nData);
const Mantid::MantidVec &XValues = m_cfInputWS->readX(0);
const bool isHistogram = m_cfInputWS->isHistogramData();
for (size_t i = 0; i < nData; i++) {
if (isHistogram) {
inputXData[i] =
0.5 * (XValues[binIndexLow + i] + XValues[binIndexLow + i + 1]);
} else {
inputXData[i] = XValues[binIndexLow + i];
FunctionDomain1DVector domain(inputXData);
FunctionValues outputData(domain);
function->function(domain, outputData);
QVector<double> dataX, dataY;
for (size_t i = 0; i < nData; i++) {
dataX.append(inputXData[i]);
dataY.append(outputData.getCalculated(i));
}
IAlgorithm_sptr createWsAlg =
AlgorithmManager::Instance().create("CreateWorkspace");
createWsAlg->initialize();
createWsAlg->setChild(true);
createWsAlg->setLogging(false);
createWsAlg->setProperty("OutputWorkspace", "__GuessAnon");
createWsAlg->setProperty("NSpec", 1);
createWsAlg->setProperty("DataX", dataX.toStdVector());
createWsAlg->setProperty("DataY", dataY.toStdVector());
createWsAlg->execute();
MatrixWorkspace_sptr guessWs = createWsAlg->getProperty("OutputWorkspace");
m_uiForm.ppPlot->addSpectrum("Guess", guessWs, 0, Qt::green);
}
/**
* Fits a single spectrum to the plot
*/
void ConvFit::singleFit() {
if (!validate())
return;
m_uiForm.ckPlotGuess->setChecked(false);
CompositeFunction_sptr function =
createFunction(m_uiForm.ckTieCentres->isChecked());
// get output name
QString fitType = fitTypeString();
QString bgType = backgroundString();
g_log.error("No fit type defined.");
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
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]);
}
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"]) {
if (checked == true) {
m_properties["DeltaFunction"]->addSubProperty(
m_properties["DeltaHeight"]);
m_dblManager->setValue(m_properties["DeltaHeight"], 1.0000);
} else {
m_properties["DeltaFunction"]->removeSubProperty(
m_properties["DeltaHeight"]);
}
} else if (prop == m_properties["UseFABADA"]) {
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
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) {
double oneLValues[3] = {0.0, 0.0, 0.0};
if (m_previousFit.compare("One Lorentzian") == 0 &&
m_uiForm.cbFitType->currentText().compare("Two Lorentzians") == 0) {
previouslyOneL = true;
oneLValues[0] = m_dblManager->value(m_properties["Lorentzian 1.Amplitude"]);
oneLValues[1] =
m_dblManager->value(m_properties["Lorentzian 1.PeakCentre"]);
oneLValues[2] = m_dblManager->value(m_properties["Lorentzian 1.FWHM"]);
// 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);
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) {
if (previouslyOneL && count < 3) {
m_dblManager->setValue(m_properties[name], oneLValues[2]);
} else {
m_dblManager->setValue(m_properties[name], 0.0175);
}
} else if (QString(*it).compare("Amplitude") == 0) {
if (previouslyOneL && count < 3) {
m_dblManager->setValue(m_properties[name], oneLValues[0]);
} else {
m_dblManager->setValue(m_properties[name], 1.0);
}
} else if (QString(*it).compare("PeakCentre") == 0) {
if (previouslyOneL && count < 3) {
m_dblManager->setValue(m_properties[name], oneLValues[1]);
} else {
m_dblManager->setValue(m_properties[name], 0.0);
} else {
m_dblManager->setValue(m_properties[name], 0.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 if (QString(*it).compare("Amplitude") == 0 ||
QString(*it).compare("Intensity") == 0) {
m_dblManager->setValue(m_properties[name], 1.0);
} else {
m_dblManager->setValue(m_properties[name], 0.0);
}
m_dblManager->setDecimals(m_properties[name], NUM_DECIMALS);
m_properties["FitFunction1"]->addSubProperty(m_properties[name]);
}
}
}
m_previousFit = m_uiForm.cbFitType->currentText();
/**
* 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 < 3 && fitFunctionType != 0) {
params.removeAll("PeakCentre");
}
if (fitFunctionType != 0) {
plotOptions.append(params);
}
if (fitFunctionType != 0 || deltaFunction) {
plotOptions << "All";
}
m_uiForm.cbPlotType->addItems(plotOptions);
}
/**
* Converts the user input for function into short hand for use in the workspace
* naming
* @param original - The original user input to the function
* @return The short hand of the users input
*/
QString ConvFit::convertFuncToShort(const QString &original) {
if (m_uiForm.cbFitType->currentIndex() != 0) {
if (original.at(0) == 'E') {
result += "E";
} else if (original.at(0) == 'I') {
result += "I";
} else {
return "SFT";
}
auto pos = original.find("Circle");
if (pos != -1) {
result += "DC";
} else {
result += "DS";
}
}
return result;
}
/**
* Converts the user input for background into short hand for use in the
* workspace naming
* @param original - The original user input to the function
* @return The short hand of the users input
*/
QString ConvFit::convertBackToShort(const std::string &original) {
QString result = QString::fromStdString(original.substr(0, 3));
auto pos = original.find(" ");
if (pos != std::string::npos) {
result += original.at(pos + 1);
}
return result;
}
} // namespace IDA
} // namespace CustomInterfaces