Newer
Older
// Mantid Repository : https://github.com/mantidproject/mantid
//
// Copyright © 2021 ISIS Rutherford Appleton Laboratory UKRI,
// NScD Oak Ridge National Laboratory, European Spallation Source,
// Institut Laue - Langevin & CSNS, Institute of High Energy Physics, CAS
// SPDX - License - Identifier: GPL - 3.0 +
#include "MantidQtWidgets/Common/BasicFitOptionsBrowser.h"
#include "MantidAPI/CostFunctionFactory.h"
#include "MantidAPI/FuncMinimizerFactory.h"
#include "MantidAPI/IFuncMinimizer.h"
#include "MantidAPI/IWorkspaceProperty.h"
#include "MantidKernel/PropertyWithValue.h"
#include "MantidQtWidgets/Common/QtPropertyBrowser/qteditorfactory.h"
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
#include "MantidQtWidgets/Common/QtPropertyBrowser/qtpropertymanager.h"
#include "MantidQtWidgets/Common/QtPropertyBrowser/qttreepropertybrowser.h"
#include <QVBoxLayout>
namespace MantidQt {
namespace MantidWidgets {
/**
* Constructor
* @param parent :: The parent widget.
* @param fitType :: The type of the underlying fitting algorithm.
*/
BasicFitOptionsBrowser::BasicFitOptionsBrowser(QWidget *parent,
FittingMode fitType)
: QWidget(parent), m_fittingTypeProp(nullptr), m_minimizer(nullptr),
m_decimals(6), m_fittingType(fitType) {
// create m_browser
createBrowser();
createProperties();
auto *layout = new QVBoxLayout(this);
layout->addWidget(m_browser);
layout->setContentsMargins(0, 0, 0, 0);
}
BasicFitOptionsBrowser::~BasicFitOptionsBrowser() {
m_browser->unsetFactoryForManager(m_intManager);
m_browser->unsetFactoryForManager(m_enumManager);
}
/**
* Create the Qt property browser and set up property managers.
*/
void BasicFitOptionsBrowser::createBrowser() {
/* Create property managers: they create, own properties, get and set values
*/
m_intManager = new QtIntPropertyManager(this);
m_enumManager = new QtEnumPropertyManager(this);
// create editor factories
auto *spinBoxFactory = new QtSpinBoxFactory(this);
auto *comboBoxFactory = new QtEnumEditorFactory(this);
m_browser = new QtTreePropertyBrowser(nullptr, QStringList(), false);
// assign factories to property managers
m_browser->setFactoryForManager(m_intManager, spinBoxFactory);
m_browser->setFactoryForManager(m_enumManager, comboBoxFactory);
connect(m_enumManager, SIGNAL(propertyChanged(QtProperty *)), this,
SLOT(enumChanged(QtProperty *)));
}
/**
* @brief Initialize the fitting type property. Show in the browser
* only if user can switch fit type.
*/
void BasicFitOptionsBrowser::initFittingTypeProp() {
m_fittingTypeProp = m_enumManager->addProperty("Fitting Mode");
QStringList types;
types << "Sequential"
<< "Simultaneous";
m_enumManager->setEnumNames(m_fittingTypeProp, types);
m_browser->addProperty(m_fittingTypeProp);
}
/**
* Create browser's QtProperties
*/
void BasicFitOptionsBrowser::createProperties() {
initFittingTypeProp();
createCommonProperties();
switchFitType();
}
void BasicFitOptionsBrowser::createCommonProperties() {
// Create MaxIterations property
m_maxIterations = m_intManager->addProperty("Max Iterations");
{
m_intManager->setValue(m_maxIterations, 500);
m_intManager->setMinimum(m_maxIterations, 0);
m_browser->addProperty(m_maxIterations);
addProperty("MaxIterations", m_maxIterations,
&BasicFitOptionsBrowser::getIntProperty,
&BasicFitOptionsBrowser::setIntProperty);
}
// Set up the minimizer property.
m_minimizer = m_enumManager->addProperty("Minimizer");
{
// Get names of registered minimizers from the factory
std::vector<std::string> minimizerOptions =
Mantid::API::FuncMinimizerFactory::Instance().getKeys();
QStringList minimizers;
for (auto &minimizerOption : minimizerOptions) {
minimizers << QString::fromStdString(minimizerOption);
}
m_enumManager->setEnumNames(m_minimizer, minimizers);
int i =
m_enumManager->enumNames(m_minimizer).indexOf("Levenberg-Marquardt");
if (i >= 0) {
m_enumManager->setValue(m_minimizer, i);
}
m_browser->addProperty(m_minimizer);
addProperty("Minimizer", m_minimizer,
&BasicFitOptionsBrowser::getStringEnumProperty,
&BasicFitOptionsBrowser::setStringEnumProperty);
}
// Create cost function property
m_costFunction = m_enumManager->addProperty("Cost Function");
{
// Get names of registered cost functions from the factory
std::vector<std::string> costOptions =
Mantid::API::CostFunctionFactory::Instance().getKeys();
QStringList costFunctions;
// Store them in the m_minimizer enum property
for (auto &costOption : costOptions) {
costFunctions << QString::fromStdString(costOption);
}
m_enumManager->setEnumNames(m_costFunction, costFunctions);
m_browser->addProperty(m_costFunction);
addProperty("CostFunction", m_costFunction,
&BasicFitOptionsBrowser::getStringEnumProperty,
&BasicFitOptionsBrowser::setStringEnumProperty);
}
// Create EvaluationType property
m_evaluationType = m_enumManager->addProperty("Evaluation Type");
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
{
QStringList evaluationTypes;
evaluationTypes << "CentrePoint"
<< "Histogram";
m_enumManager->setEnumNames(m_evaluationType, evaluationTypes);
m_browser->addProperty(m_evaluationType);
addProperty("EvaluationType", m_evaluationType,
&BasicFitOptionsBrowser::getStringEnumProperty,
&BasicFitOptionsBrowser::setStringEnumProperty);
}
}
void BasicFitOptionsBrowser::addProperty(
const QString &name, QtProperty *prop,
QString (BasicFitOptionsBrowser::*getter)(QtProperty *) const,
void (BasicFitOptionsBrowser::*setter)(QtProperty *, const QString &)) {
m_propertyNameMap[name] = prop;
m_getters[prop] = getter;
m_setters[prop] = setter;
}
/**
* Set a new value to a Fit's property.
* @param name :: The name of a Fit's property.
* @param value :: The new value as a string.
*/
void BasicFitOptionsBrowser::setProperty(const QString &name,
const QString &value) {
if (!m_propertyNameMap.contains(name)) {
throw std::runtime_error("Property " + name.toStdString() +
" isn't supported by the browser.");
}
auto prop = m_propertyNameMap[name];
auto f = m_setters[prop];
(this->*f)(prop, value);
}
/**
* Update the browser when an enum property changes.
* @param prop :: Property that changed its value.
void BasicFitOptionsBrowser::enumChanged(QtProperty *prop) {
if (prop == m_fittingTypeProp) {
switchFitType();
}
}
/**
* Switch the current fit type according to the value in the FitType property.
void BasicFitOptionsBrowser::switchFitType() {
const auto fittingMode = getCurrentFittingType();
if (fittingMode == FittingMode::SIMULTANEOUS) {
emit changedToSimultaneousFitting();
} else {
emit changedToSequentialFitting();
}
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
}
/**
* Get the value of an integer algorithm property.
* @param prop :: The corresponding QtProperty.
*/
QString BasicFitOptionsBrowser::getIntProperty(QtProperty *prop) const {
return QString::number(m_intManager->value(prop));
}
/**
* Set a new value of an integer algorithm property.
* @param prop :: The corresponding QtProperty.
* @param value :: The new value.
*/
void BasicFitOptionsBrowser::setIntProperty(QtProperty *prop,
const QString &value) {
m_intManager->setValue(prop, value.toInt());
}
/**
* Get the value of a string algorithm property with predefined set of values.
* @param prop :: The corresponding QtProperty.
*/
QString BasicFitOptionsBrowser::getStringEnumProperty(QtProperty *prop) const {
int i = m_enumManager->value(prop);
if (i < 0)
return "";
return m_enumManager->enumNames(prop)[i];
}
/**
* Set a new value of a string algorithm property with predefined set of values.
* @param prop :: The corresponding QtProperty.
* @param value :: The new value.
*/
void BasicFitOptionsBrowser::setStringEnumProperty(QtProperty *prop,
const QString &value) {
int i = m_enumManager->enumNames(prop).indexOf(value);
if (i >= 0)
m_enumManager->setValue(prop, i);
}
/**
* Get the current fitting type, ie which algorithm to use:
* Simultaneous for Fit and Sequential for PlotPeakByLogValue.
*/
FittingMode BasicFitOptionsBrowser::getCurrentFittingType() const {
auto value = m_enumManager->value(m_fittingTypeProp);
return static_cast<FittingMode>(value);
}
/**
* Set the current fitting type, ie which algorithm to use:
* Simultaneous for Fit and Sequential for PlotPeakByLogValue.
*/
void BasicFitOptionsBrowser::setCurrentFittingType(FittingMode fitType) {
if (fitType == FittingMode::SIMULTANEOUS) {
m_enumManager->setValue(m_fittingTypeProp, 1);
} else {
m_enumManager->setValue(m_fittingTypeProp, 0);
}
}
} // namespace MantidWidgets
} // namespace MantidQt