Newer
Older
// DiffRotDiscreteCircle
m_uiForm.ckPlotGuess->setEnabled(index < 3);
m_properties["UseDeltaFunc"]->setEnabled(index < 3);
updatePlotOptions();
}
/**
* Add/Remove sub property 'BGA1' from background based on Background type
* @param index A reference to the Background type
void ConvFit::bgTypeSelection(int index) {
if (index == 2) {
m_properties["LinearBackground"]->addSubProperty(m_properties["BGA1"]);
} else {
m_properties["LinearBackground"]->removeSubProperty(m_properties["BGA1"]);
/**
* Updates the plot in the gui window
void ConvFit::updatePlot() {
using Mantid::Kernel::Exception::NotFoundError;
if (!m_cfInputWS) {
g_log.error("No workspace loaded, cannot create preview plot.");
return;
const bool plotGuess = m_uiForm.ckPlotGuess->isChecked();
m_uiForm.ckPlotGuess->setChecked(false);
int specNo = m_uiForm.spPlotSpectrum->text().toInt();
m_uiForm.ppPlot->clear();
m_uiForm.ppPlot->addSpectrum("Sample", m_cfInputWS, specNo);
try {
const QPair<double, double> curveRange =
m_uiForm.ppPlot->getCurveRange("Sample");
const std::pair<double, double> range(curveRange.first, curveRange.second);
m_uiForm.ppPlot->getRangeSelector("ConvFitRange")
->setRange(range.first, range.second);
m_uiForm.ckPlotGuess->setChecked(plotGuess);
} catch (std::invalid_argument &exc) {
showMessageBox(exc.what());
// Default FWHM to resolution of instrument
double resolution = getInstrumentResolution(m_cfInputWSName.toStdString());
if (resolution > 0) {
m_dblManager->setValue(m_properties["Lorentzian 1.FWHM"], resolution);
m_dblManager->setValue(m_properties["Lorentzian 2.FWHM"], resolution);
// If there is a result plot then plot it
if (AnalysisDataService::Instance().doesExist(m_pythonExportWsName)) {
WorkspaceGroup_sptr outputGroup =
AnalysisDataService::Instance().retrieveWS<WorkspaceGroup>(
m_pythonExportWsName);
if (specNo >= static_cast<int>(outputGroup->size()))
MatrixWorkspace_sptr ws = boost::dynamic_pointer_cast<MatrixWorkspace>(
outputGroup->getItem(specNo));
if (ws)
m_uiForm.ppPlot->addSpectrum("Fit", ws, 1, Qt::red);
}
}
/**
* 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;
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();
if (fitType == "") {
g_log.error("No fit type defined!");
}
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
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");
// Get params.
QMap<QString, double> parameters;
std::vector<std::string> parNames = outputFunc->getParameterNames();
std::vector<double> parVals;
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++;
if (fitTypeIndex == 1 || fitTypeIndex == 2) {
// One Lorentz
QString pref = prefBase;
if (usingCompositeFunc) {
pref += "f" + QString::number(funcIndex) + ".f" +
QString::number(subIndex) + ".";
} else {
pref += "f" + QString::number(subIndex) + ".";
}
m_dblManager->setValue(m_properties["Lorentzian 1.Amplitude"],
parameters[pref + "Amplitude"]);
m_dblManager->setValue(m_properties["Lorentzian 1.PeakCentre"],
parameters[pref + "PeakCentre"]);
m_dblManager->setValue(m_properties["Lorentzian 1.FWHM"],
parameters[pref + "FWHM"]);
funcIndex++;
if (fitTypeIndex == 2) {
// Two Lorentz
QString pref = prefBase;
pref += "f" + QString::number(funcIndex) + ".f" +
QString::number(subIndex) + ".";
m_dblManager->setValue(m_properties["Lorentzian 2.Amplitude"],
parameters[pref + "Amplitude"]);
m_dblManager->setValue(m_properties["Lorentzian 2.PeakCentre"],
parameters[pref + "PeakCentre"]);
m_dblManager->setValue(m_properties["Lorentzian 2.FWHM"],
parameters[pref + "FWHM"]);
if (fitTypeIndex == 3) {
// DiffSphere
QString pref = prefBase;
if (usingCompositeFunc) {
pref += "f" + QString::number(funcIndex) + ".f" +
QString::number(subIndex) + ".";
} else {
pref += "f" + QString::number(subIndex) + ".";
}
m_dblManager->setValue(m_properties["Diffusion Sphere.Intensity"],
parameters[pref + "Intensity"]);
m_dblManager->setValue(m_properties["Diffusion Sphere.Radius"],
parameters[pref + "Radius"]);
m_dblManager->setValue(m_properties["Diffusion Sphere.Diffusion"],
parameters[pref + "Diffusion"]);
m_dblManager->setValue(m_properties["Diffusion Sphere.Shift"],
parameters[pref + "Shift"]);
if (fitTypeIndex == 4) {
// DiffSphere
QString pref = prefBase;
if (usingCompositeFunc) {
pref += "f" + QString::number(funcIndex) + ".f" +
QString::number(subIndex) + ".";
} else {
pref += "f" + QString::number(subIndex) + ".";
m_dblManager->setValue(m_properties["Diffusion Circle.Intensity"],
parameters[pref + "Intensity"]);
m_dblManager->setValue(m_properties["Diffusion Circle.Radius"],
parameters[pref + "Radius"]);
m_dblManager->setValue(m_properties["Diffusion Circle.Decay"],
parameters[pref + "Decay"]);
m_dblManager->setValue(m_properties["Diffusion Circle.Shift"],
parameters[pref + "Shift"]);
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);
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
if (prop == m_properties["UseDeltaFunc"])
updatePlotOptions();
else if (prop == m_properties["UseFABADA"]) {
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");
}
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
void ConvFit::updatePlotOptions() {
m_uiForm.cbPlotType->clear();
bool deltaFunction = m_blnManager->value(m_properties["UseDeltaFunc"]);
QStringList plotOptions;
plotOptions << "None";
if (deltaFunction)
plotOptions << "Height";
switch (m_uiForm.cbFitType->currentIndex()) {
// Lorentzians
case 1:
case 2:
plotOptions << "Amplitude"
<< "FWHM";
if (deltaFunction)
plotOptions << "EISF";
break;
// DiffSphere
case 3:
plotOptions << "Intensity"
<< "Radius"
<< "Diffusion"
<< "Shift";
break;
// DiffRotDiscreteCircle
case 4:
plotOptions << "Intensity"
<< "Radius"
<< "Decay"
<< "Shift";
break;
default:
break;
plotOptions << "All";
m_uiForm.cbPlotType->addItems(plotOptions);
}
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
/**
* Gets a list of parameters for a given fit function.
*
* @return List fo parameters
*/
QStringList ConvFit::getFunctionParameters(const QString &functionName) {
QStringList parameters;
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 current parameter elements
if (functionName.compare("Zero Lorentzians") == 0) {
return;
} else {
for (auto it = m_properties.begin(); it != m_properties.end();) {
if (it.key().startsWith("parameter_")) {
delete it.value();
it = m_properties.erase(it);
} else {
++it;
}
}
// Don't run the algorithm when updating parameter values
/*disconnect(m_dblManager, SIGNAL(valueChanged(QtProperty *, double)), this,
SLOT(runPreviewAlgorithm()));*/
// Add new parameter elements
QStringList parameters = getFunctionParameters(functionName);
for (auto it = parameters.begin(); it != parameters.end(); ++it) {
QString name = "parameter_" + *it;
m_properties[name] = m_dblManager->addProperty(*it);
m_dblManager->setValue(m_properties[name], 1.0);
m_properties["FitFunction"]->addSubProperty(m_properties[name]);
}
/*connect(m_dblManager, SIGNAL(valueChanged(QtProperty *, double)), this,
SLOT(runPreviewAlgorithm()));*/
// runPreviewAlgorithm();
}
}
} // namespace IDA
} // namespace CustomInterfaces