Mantid
Loading...
Searching...
No Matches
FitPropertyBrowser.cpp
Go to the documentation of this file.
1// Mantid Repository : https://github.com/mantidproject/mantid
2//
3// Copyright © 2018 ISIS Rutherford Appleton Laboratory UKRI,
4// NScD Oak Ridge National Laboratory, European Spallation Source,
5// Institut Laue - Langevin & CSNS, Institute of High Energy Physics, CAS
6// SPDX - License - Identifier: GPL - 3.0 +
13
25#include "MantidAPI/TableRow.h"
28
30#include "MantidKernel/Logger.h"
31
32#include "MantidQtWidgets/Common/QtPropertyBrowser/FilenameDialogEditor.h"
33#include "MantidQtWidgets/Common/QtPropertyBrowser/FormulaDialogEditor.h"
34#include "MantidQtWidgets/Common/QtPropertyBrowser/StringEditorFactory.h"
35
36#include "MantidQtWidgets/Common/QtPropertyBrowser/DoubleEditorFactory.h"
37#include "MantidQtWidgets/Common/QtPropertyBrowser/ParameterPropertyManager.h"
38#include "MantidQtWidgets/Common/QtPropertyBrowser/qteditorfactory.h"
39#include "MantidQtWidgets/Common/QtPropertyBrowser/qttreepropertybrowser.h"
40
41#include <Poco/ActiveResult.h>
42
43#include <QApplication>
44#include <QClipboard>
45#include <QGridLayout>
46#include <QInputDialog>
47#include <QListWidget>
48#include <QMenu>
49#include <QMessageBox>
50#include <QPushButton>
51#include <QSettings>
52#include <QSignalMapper>
53#include <QTreeWidget>
54#include <QUrl>
55#include <QVBoxLayout>
56
57#include <algorithm>
58#include <utility>
59
60namespace MantidQt {
61using API::MantidDesktopServices;
62
63namespace MantidWidgets {
64
65namespace {
66Mantid::Kernel::Logger g_log("FitPropertyBrowser");
67
68using namespace Mantid::API;
69
70int getNumberOfSpectra(const MatrixWorkspace_sptr &workspace) {
71 return static_cast<int>(workspace->getNumberHistograms());
72}
73} // namespace
74
80FitPropertyBrowser::FitPropertyBrowser(QWidget *parent, QObject *mantidui)
81 : QDockWidget("Fit Function", parent), m_workspaceIndex(nullptr), m_startX(nullptr), m_endX(nullptr),
82 m_output(nullptr), m_minimizer(nullptr), m_ignoreInvalidData(nullptr), m_costFunction(nullptr),
83 m_maxIterations(nullptr), m_peakRadius(nullptr), m_plotDiff(nullptr), m_excludeRange(nullptr),
84 m_plotCompositeMembers(nullptr), m_convolveMembers(nullptr), m_rawData(nullptr), m_xColumn(nullptr),
85 m_yColumn(nullptr), m_errColumn(nullptr), m_showParamErrors(nullptr), m_evaluationType(nullptr),
86 m_compositeFunction(), m_browser(nullptr), m_fitActionUndoFit(nullptr), m_fitActionSeqFit(nullptr),
87 m_fitActionFit(nullptr), m_fitActionEvaluate(nullptr), m_functionsGroup(nullptr), m_settingsGroup(nullptr),
88 m_customSettingsGroup(nullptr), m_changeSlotsEnabled(false), m_guessOutputName(true),
89 m_updateObserver(*this, &FitPropertyBrowser::handleFactoryUpdate), m_fitMapper(nullptr), m_fitMenu(nullptr),
90 m_displayActionPlotGuess(nullptr), m_displayActionQuality(nullptr), m_displayActionClearAll(nullptr),
91 m_setupActionCustomSetup(nullptr), m_setupActionRemove(nullptr), m_tip(nullptr), m_fitSelector(nullptr),
92 m_fitTree(nullptr), m_currentHandler(nullptr), m_defaultFunction("Gaussian"), m_defaultPeak("Gaussian"),
93 m_defaultBackground("LinearBackground"), m_peakToolOn(false), m_hideWsListWidget(false), m_auto_back(false),
94 m_autoBgName(
95 QString::fromStdString(Mantid::Kernel::ConfigService::Instance().getString("curvefitting.autoBackground"))),
96 m_autoBackground(nullptr), m_decimals(-1), m_mantidui(mantidui), m_shouldBeNormalised(false),
97 m_fitAlgParameters(""), m_oldWorkspaceIndex(-1) {
98 Mantid::API::FrameworkManager::Instance().loadPlugins();
99
100 // If Gaussian does not exist then the plugins did not load.
101 if (!Mantid::API::FunctionFactory::Instance().exists("Gaussian")) {
102 throw std::runtime_error("FitPropertyBrowser: Unable to find Gaussian function\n"
103 "Has the CurveFitting plugin loaded?");
104 }
105 if (m_autoBgName.toLower() == "none") {
106 m_autoBgName = "";
107 } else {
109 }
110
111 std::string def = Mantid::Kernel::ConfigService::Instance().getString("curvefitting.defaultPeak");
112 if (!def.empty()) {
113 m_defaultPeak = def;
114 }
115
116 def = Mantid::Kernel::ConfigService::Instance().getString("curvefitting.autoBackground");
117 if (!def.empty()) {
119 }
121
122 setObjectName("FitFunction"); // this is needed for QMainWindow::restoreState()
123 setMinimumHeight(150);
124 setMinimumWidth(200);
125
126 QWidget *w = new QWidget(this);
127
128 /* Create property managers: they create, own properties, get and set values
129 */
130 m_groupManager = new QtGroupPropertyManager(w);
131 m_doubleManager = new QtDoublePropertyManager(w);
132 m_stringManager = new QtStringPropertyManager(w);
133 m_enumManager = new QtEnumPropertyManager(w);
134 m_intManager = new QtIntPropertyManager(w);
135 m_boolManager = new QtBoolPropertyManager(w);
136 m_filenameManager = new QtStringPropertyManager(w);
137 m_formulaManager = new QtStringPropertyManager(w);
138 m_columnManager = new QtEnumPropertyManager(w);
139 m_workspace = m_enumManager->addProperty("Workspace");
140 m_vectorManager = new QtGroupPropertyManager(w);
141 m_vectorSizeManager = new QtIntPropertyManager(w);
142 m_vectorDoubleManager = new QtDoublePropertyManager(w);
143 m_parameterManager = new ParameterPropertyManager(w);
144}
145
150 QWidget *w = new QWidget(this);
151
152 QSettings settings;
153 settings.beginGroup("Mantid/FitBrowser");
154
155 /* Create function group */
156 QtProperty *functionsGroup = m_groupManager->addProperty("Functions");
157
158 if (m_mantidui) {
159 connect(this, SIGNAL(xRangeChanged(double, double)), m_mantidui, SLOT(x_range_from_picker(double, double)));
160 }
161 /* Create input - output properties */
162 QtProperty *settingsGroup = m_groupManager->addProperty("Settings");
163 m_startX = addDoubleProperty("StartX");
164 m_endX = addDoubleProperty("EndX");
165
166 m_workspaceIndex = m_intManager->addProperty("Workspace Index");
167 m_output = m_stringManager->addProperty("Output");
168 m_minimizer = m_enumManager->addProperty("Minimizer");
169 m_minimizers << "Levenberg-Marquardt"
170 << "Levenberg-MarquardtMD"
171 << "Trust Region"
172 << "Simplex"
173 << "FABADA"
174 << "Conjugate gradient (Fletcher-Reeves imp.)"
175 << "Conjugate gradient (Polak-Ribiere imp.)"
176 << "BFGS"
177 << "Damped GaussNewton";
178
179 m_ignoreInvalidData = m_boolManager->addProperty("Ignore invalid data");
180 setIgnoreInvalidData(settings.value("Ignore invalid data", false).toBool());
181
182 m_enumManager->setEnumNames(m_minimizer, m_minimizers);
183 m_costFunction = m_enumManager->addProperty("Cost function");
184 m_costFunctions << "Least squares"
185 << "Rwp"
186 << "Unweighted least squares"
187 << "Poisson";
189 m_maxIterations = m_intManager->addProperty("Max Iterations");
190 m_intManager->setValue(m_maxIterations, settings.value("Max Iterations", 500).toInt());
191
192 m_peakRadius = m_intManager->addProperty("Peak Radius");
193 m_intManager->setValue(m_peakRadius, settings.value("Peak Radius", 0).toInt());
194
195 m_plotDiff = m_boolManager->addProperty("Plot Difference");
196 bool plotDiffSetting = settings.value("Plot Difference", QVariant(true)).toBool();
197 m_boolManager->setValue(m_plotDiff, plotDiffSetting);
198
199 m_excludeRange = m_stringManager->addProperty("Exclude Range");
200 m_excludeRange->setToolTip("A list of pairs of real numbers which define the region to exclude");
201
202 m_plotCompositeMembers = m_boolManager->addProperty("Plot Composite Members");
203 bool plotCompositeItems = settings.value(m_plotCompositeMembers->propertyName(), QVariant(false)).toBool();
204 m_boolManager->setValue(m_plotCompositeMembers, plotCompositeItems);
205
206 m_convolveMembers = m_boolManager->addProperty("Convolve Composite Members");
207 bool convolveCompositeItems = settings.value(m_plotCompositeMembers->propertyName(), QVariant(false)).toBool();
208 m_boolManager->setValue(m_convolveMembers, convolveCompositeItems);
209
210 m_showParamErrors = m_boolManager->addProperty("Show Parameter Errors");
211 bool showParamErrors = settings.value(m_showParamErrors->propertyName(), false).toBool();
212 m_boolManager->setValue(m_showParamErrors, showParamErrors);
213 m_parameterManager->setErrorsEnabled(showParamErrors);
214
215 m_evaluationType = m_enumManager->addProperty("Evaluate Function As");
216 m_evaluationType->setToolTip("Consider using Histogram fit which may produce more accurate results.");
217 m_evaluationTypes << "CentrePoint"
218 << "Histogram";
220 int evaluationType = settings.value(m_evaluationType->propertyName(), 0).toInt();
221 m_enumManager->setValue(m_evaluationType, evaluationType);
222
223 m_xColumn = m_columnManager->addProperty("XColumn");
224 m_yColumn = m_columnManager->addProperty("YColumn");
225 m_errColumn = m_columnManager->addProperty("ErrColumn");
226
227 settingsGroup->addSubProperty(m_workspace);
228 settingsGroup->addSubProperty(m_startX);
229 settingsGroup->addSubProperty(m_endX);
230
231 // Only include the cost function when in the dock widget inside mantid plot,
232 // not on muon analysis widget
233 // Include minimiser and plot difference under a different settings section.
234 settingsGroup->addSubProperty(m_output);
235 settingsGroup->addSubProperty(m_minimizer);
236 settingsGroup->addSubProperty(m_ignoreInvalidData);
237 settingsGroup->addSubProperty(m_costFunction);
238 settingsGroup->addSubProperty(m_maxIterations);
239 settingsGroup->addSubProperty(m_peakRadius);
240 settingsGroup->addSubProperty(m_plotDiff);
241 settingsGroup->addSubProperty(m_excludeRange);
242 settingsGroup->addSubProperty(m_plotCompositeMembers);
243 settingsGroup->addSubProperty(m_convolveMembers);
244 settingsGroup->addSubProperty(m_showParamErrors);
245 settingsGroup->addSubProperty(m_evaluationType);
246
247 /* Create editors and assign them to the managers */
248 createEditors(w);
249
251
252 m_functionsGroup = m_browser->addProperty(functionsGroup);
253 m_settingsGroup = m_browser->addProperty(settingsGroup);
254
255 initLayout(w);
256}
257
268
278 auto *btnFit = new QPushButton("Fit");
279 m_tip = new QLabel("", w);
280
281 m_fitMapper = new QSignalMapper(this);
282 m_fitMenu = new QMenu(this);
284 connect(m_fitMapper, SIGNAL(mappedString(const QString &)), this, SLOT(executeFitMenu(const QString &)));
285 btnFit->setMenu(m_fitMenu);
286 return btnFit;
287}
288
297void FitPropertyBrowser::populateFitMenuButton(QSignalMapper *fitMapper, QMenu *fitMenu) {
298 // assert(fitmapper);
299
300 m_fitActionFit = new QAction("Fit", this);
301 m_fitActionSeqFit = new QAction("Sequential Fit", this);
302 m_fitActionUndoFit = new QAction("Undo Fit", this);
303 m_fitActionEvaluate = new QAction("Evaluate function", this);
304
305 fitMapper->setMapping(m_fitActionFit, "Fit");
306 fitMapper->setMapping(m_fitActionSeqFit, "SeqFit");
307 fitMapper->setMapping(m_fitActionUndoFit, "UndoFit");
308 fitMapper->setMapping(m_fitActionEvaluate, "Evaluate");
309
310 connect(m_fitActionFit, SIGNAL(triggered()), fitMapper, SLOT(map()));
311 connect(m_fitActionSeqFit, SIGNAL(triggered()), fitMapper, SLOT(map()));
312 connect(m_fitActionUndoFit, SIGNAL(triggered()), fitMapper, SLOT(map()));
313 connect(m_fitActionEvaluate, SIGNAL(triggered()), fitMapper, SLOT(map()));
314
315 fitMenu->addAction(m_fitActionFit);
316 fitMenu->addAction(m_fitActionSeqFit);
317 fitMenu->addAction(m_fitActionEvaluate);
318 fitMenu->addSeparator();
319 fitMenu->addAction(m_fitActionUndoFit);
320 fitMenu->addSeparator();
321}
332 QPushButton *btnFit = createFitMenuButton(w);
333 btnFit->setObjectName("button_Fit");
334 // to be able to change windows title from tread
335 connect(this, SIGNAL(changeWindowTitle(const QString &)), this, SLOT(setWindowTitle(const QString &)));
336
337 /* Create the top level group */
338
339 m_groupManager->addProperty("Fit");
340
341 connect(m_enumManager, SIGNAL(propertyChanged(QtProperty *)), this, SLOT(enumChanged(QtProperty *)));
342 connect(m_boolManager, SIGNAL(propertyChanged(QtProperty *)), this, SLOT(boolChanged(QtProperty *)));
343 connect(m_intManager, SIGNAL(propertyChanged(QtProperty *)), this, SLOT(intChanged(QtProperty *)));
344 connect(m_doubleManager, SIGNAL(propertyChanged(QtProperty *)), this, SLOT(doubleChanged(QtProperty *)));
345 connect(m_stringManager, SIGNAL(propertyChanged(QtProperty *)), this, SLOT(stringChanged(QtProperty *)));
346 connect(m_filenameManager, SIGNAL(propertyChanged(QtProperty *)), this, SLOT(stringChanged(QtProperty *)));
347 connect(m_formulaManager, SIGNAL(propertyChanged(QtProperty *)), this, SLOT(stringChanged(QtProperty *)));
348 connect(m_columnManager, SIGNAL(propertyChanged(QtProperty *)), this, SLOT(columnChanged(QtProperty *)));
349 connect(m_vectorDoubleManager, SIGNAL(propertyChanged(QtProperty *)), this, SLOT(vectorDoubleChanged(QtProperty *)));
350 connect(m_parameterManager, SIGNAL(propertyChanged(QtProperty *)), this, SLOT(parameterChanged(QtProperty *)));
351 connect(m_vectorSizeManager, SIGNAL(propertyChanged(QtProperty *)), this, SLOT(vectorSizeChanged(QtProperty *)));
352
353 auto *layout = new QVBoxLayout(w);
354 layout->setObjectName("vlayout");
355 auto *buttonsLayout = new QGridLayout();
356
357 auto *btnDisplay = new QPushButton("Display");
358 btnDisplay->setObjectName("button_Display");
359 QMenu *displayMenu = new QMenu(this);
360 displayMenu->setObjectName("menu_Display");
361 m_displayActionPlotGuess = new QAction("Plot Guess", this);
362 m_displayActionPlotGuess->setEnabled(false);
363 m_displayActionQuality = new QAction("Quality", this);
364 m_displayActionQuality->setObjectName("action_Quality");
365 m_displayActionQuality->setCheckable(true);
366 m_displayActionQuality->setChecked(true);
367 m_displayActionClearAll = new QAction("Clear fit curves", this);
368 QSignalMapper *displayMapper = new QSignalMapper(this);
369 displayMapper->setObjectName("mapper_Display");
370
371 displayMapper->setMapping(m_displayActionPlotGuess, "PlotGuess");
372 displayMapper->setMapping(m_displayActionQuality, "Quality");
373 displayMapper->setMapping(m_displayActionClearAll, "ClearAll");
374 connect(m_displayActionPlotGuess, SIGNAL(triggered()), displayMapper, SLOT(map()));
375 connect(m_displayActionQuality, SIGNAL(triggered()), displayMapper, SLOT(map()));
376 connect(m_displayActionClearAll, SIGNAL(triggered()), displayMapper, SLOT(map()));
377 connect(displayMapper, SIGNAL(mappedString(const QString &)), this, SLOT(executeDisplayMenu(const QString &)));
378 displayMenu->addAction(m_displayActionPlotGuess);
379 displayMenu->addAction(m_displayActionClearAll);
380 displayMenu->addAction(m_displayActionQuality);
381 btnDisplay->setMenu(displayMenu);
382
383 auto *btnSetup = new QPushButton("Setup");
384 btnSetup->setObjectName("button_Setup");
385 QMenu *setupMenu = new QMenu(this);
386 setupMenu->setObjectName("menu_Setup");
387
388 m_setupActionCustomSetup = new QAction("Custom Setup", this);
389 QAction *setupActionManageSetup = new QAction("Manage Setup", this);
390 setupActionManageSetup->setObjectName("action_ManageSetup");
391 QAction *setupActionPeakFindingAlgs = new QAction("Peak Finding Algorithms", this);
392 setupActionPeakFindingAlgs->setObjectName("action_PeakFindingAlgs");
393 QAction *setupActionFindPeaks = new QAction("Find Peaks", this);
394 setupActionFindPeaks->setObjectName("action_FindPeaks");
395 QAction *setupActionFindPeaksConvolve = new QAction("Find Peaks Convolve", this);
396 setupActionFindPeaksConvolve->setObjectName("action_FindPeaksConvolve");
397 QAction *setupActionClearFit = new QAction("Clear Model", this);
398 setupActionClearFit->setObjectName("action_ClearModel");
399
400 QMenu *setupSubMenuCustom = new QMenu(this);
401 m_setupActionCustomSetup->setMenu(setupSubMenuCustom);
402 // empty menu for now, so set it disabled to avoid confusing users
403 m_setupActionCustomSetup->setEnabled(false);
404
405 QMenu *setupSubMenuManage = new QMenu(this);
406 QAction *setupActionSave = new QAction("Save Setup", this);
407 m_setupActionRemove = new QAction("Remove Setup", this);
408 QAction *setupActionClear = new QAction("Clear Setups", this);
409 setupActionClear->setObjectName("action_ClearSetups");
410 QAction *setupActionCopyToClipboard = new QAction("Copy To Clipboard", this);
411 setupActionCopyToClipboard->setObjectName("action_CopyToClipboard");
412 QAction *setupActionLoadFromString = new QAction("Load From String", this);
413 setupActionLoadFromString->setObjectName("action_LoadFromString");
414 QSignalMapper *setupManageMapper = new QSignalMapper(this);
415 setupManageMapper->setMapping(setupActionSave, "SaveSetup");
416 setupManageMapper->setMapping(setupActionCopyToClipboard, "CopyToClipboard");
417 setupManageMapper->setMapping(setupActionLoadFromString, "LoadFromString");
418 setupManageMapper->setMapping(setupActionClear, "ClearSetups");
419 connect(setupActionSave, SIGNAL(triggered()), setupManageMapper, SLOT(map()));
420 connect(setupActionCopyToClipboard, SIGNAL(triggered()), setupManageMapper, SLOT(map()));
421 connect(setupActionLoadFromString, SIGNAL(triggered()), setupManageMapper, SLOT(map()));
422 connect(setupActionClear, SIGNAL(triggered()), setupManageMapper, SLOT(map()));
423 connect(setupManageMapper, SIGNAL(mappedString(const QString &)), this,
424 SLOT(executeSetupManageMenu(const QString &)));
425 setupSubMenuManage->addAction(setupActionSave);
426 setupSubMenuManage->addAction(m_setupActionRemove);
427 setupSubMenuManage->addAction(setupActionClear);
428 setupSubMenuManage->addAction(setupActionCopyToClipboard);
429 setupSubMenuManage->addAction(setupActionLoadFromString);
430 setupActionManageSetup->setMenu(setupSubMenuManage);
431
432 QMenu *setupSubMenuRemove = new QMenu(this);
433 m_setupActionRemove->setMenu(setupSubMenuRemove);
434 // empty menu for now, so set it disabled to avoid confusing users
435 m_setupActionRemove->setEnabled(false);
436
437 QSignalMapper *PeakFindingAlgMapper = new QSignalMapper(this);
438 PeakFindingAlgMapper->setMapping(setupActionFindPeaks, "FindPeaks");
439 PeakFindingAlgMapper->setMapping(setupActionFindPeaksConvolve, "FindPeaksConvolve");
440 connect(setupActionFindPeaks, SIGNAL(triggered()), PeakFindingAlgMapper, SLOT(map()));
441 connect(setupActionFindPeaksConvolve, SIGNAL(triggered()), PeakFindingAlgMapper, SLOT(map()));
442 connect(PeakFindingAlgMapper, SIGNAL(mappedString(const QString &)), this,
443 SLOT(executePeakFindingAlgMenu(const QString &)));
444
445 QSignalMapper *setupMapper = new QSignalMapper(this);
446 setupMapper->setMapping(setupActionClearFit, "ClearFit");
447 connect(setupActionClearFit, SIGNAL(triggered()), setupMapper, SLOT(map()));
448 connect(setupMapper, SIGNAL(mappedString(const QString &)), this, SLOT(executeSetupMenu(const QString &)));
449
450 QMenu *setupSubMenuPeakFindingAgls = new QMenu(this);
451 setupSubMenuPeakFindingAgls->addAction(setupActionFindPeaks);
452 setupSubMenuPeakFindingAgls->addAction(setupActionFindPeaksConvolve);
453 setupActionPeakFindingAlgs->setMenu(setupSubMenuPeakFindingAgls);
454
455 setupMenu->addAction(m_setupActionCustomSetup);
456 setupMenu->addAction(setupActionManageSetup);
457 setupMenu->addSeparator();
458 setupMenu->addAction(setupActionPeakFindingAlgs);
459 setupMenu->addSeparator();
460 setupMenu->addAction(setupActionClearFit);
461 btnSetup->setMenu(setupMenu);
462
464
465 buttonsLayout->addWidget(btnFit, 0, 0);
466 buttonsLayout->addWidget(btnDisplay, 0, 1);
467 buttonsLayout->addWidget(btnSetup, 0, 2);
468
469 m_status = new QLabel("Status:", w);
470 m_status->hide();
471 connect(this, SIGNAL(fitResultsChanged(const QString &)), this, SLOT(showFitResultStatus(const QString &)),
472 Qt::QueuedConnection);
473 layout->addWidget(m_status);
474 layout->addLayout(buttonsLayout);
475 layout->addWidget(m_tip);
476 layout->addWidget(m_browser);
477 m_browser->setObjectName("tree_browser");
478
479 m_workspaceLabel = new QLabel("Workspaces");
480 layout->addWidget(m_workspaceLabel);
481 m_wsListWidget = new QListWidget();
482 layout->addWidget(m_wsListWidget);
483 m_workspaceLabel->hide();
484 m_wsListWidget->hide();
485
486 setWidget(w);
487
488 m_browser->setContextMenuPolicy(Qt::CustomContextMenu);
489 connect(m_browser, SIGNAL(customContextMenuRequested(const QPoint &)), this, SLOT(popupMenu(const QPoint &)));
490 connect(m_browser, SIGNAL(currentItemChanged(const QtBrowserItem *)), this,
491 SLOT(currentItemChanged(const QtBrowserItem *)));
492 connect(this, SIGNAL(multifitFinished()), this, SLOT(processMultiBGResults()));
493
494 connect(m_wsListWidget, SIGNAL(itemDoubleClicked(QListWidgetItem *)), this,
495 SLOT(workspaceDoubleClicked(QListWidgetItem *)));
496
498
499 // Update tooltips when function structure is (or might've been) changed in
500 // any way
501 connect(this, SIGNAL(functionChanged()), SLOT(updateStructureTooltips()));
502 connect(this, SIGNAL(functionChanged()), SLOT(clearFitResultStatus()));
503
504 // Update available functions in this fit property browser, when the function
505 // factory changes.
507 FunctionFactory::Instance().notificationCenter.addObserver(m_updateObserver);
508 connect(this, SIGNAL(functionFactoryUpdateReceived()), this, SLOT(populateFunctionNames()));
509 FunctionFactory::Instance().enableNotifications();
510
511 // Initial call, as function is not changed when it's created for the first
512 // time
514
516
518}
519
520// Adds the fit result workspaces to the qlistwidget in the browser
522 const auto outName = outputName();
523 const std::vector<std::string> workspaceNames{outName + "_NormalisedCovarianceMatrix", outName + "_Parameters",
524 outName + "_Workspace"};
525
526 for (const auto &name : workspaceNames) {
527 // check if already in the list
528 auto foundInList = m_wsListWidget->findItems(QString::fromStdString(name), Qt::MatchExactly);
529 if (foundInList.size() == 0 && AnalysisDataService::Instance().doesExist(name)) {
530 new QListWidgetItem(QString::fromStdString(name), m_wsListWidget);
531 }
532 }
533
534 auto noOfItems = m_wsListWidget->count();
535 if (noOfItems != 0 && !m_hideWsListWidget) {
536 auto widgetHeight = m_wsListWidget->sizeHintForRow(0) * (noOfItems + 1) + 2 * m_wsListWidget->frameWidth();
537 m_wsListWidget->setMaximumHeight(widgetHeight);
538 m_workspaceLabel->show();
539 m_wsListWidget->show();
540 }
541}
542
544 auto wsName = item->text();
545 emit workspaceClicked(wsName);
546}
547
556 QtCheckBoxFactory *checkBoxFactory = new QtCheckBoxFactory(w);
557 QtEnumEditorFactory *comboBoxFactory = new QtEnumEditorFactory(w);
558 QtSpinBoxFactory *spinBoxFactory = new QtSpinBoxFactory(w);
559 DoubleEditorFactory *doubleEditorFactory = new DoubleEditorFactory(w);
560 StringEditorFactory *stringEditFactory = new StringEditorFactory(w);
561 FilenameDialogEditorFactory *filenameDialogEditorFactory = new FilenameDialogEditorFactory(w);
562 FormulaDialogEditorFactory *formulaDialogEditFactory = new FormulaDialogEditorFactory(w);
563
564 m_browser = new QtTreePropertyBrowser();
565 m_browser->setFactoryForManager(m_enumManager, comboBoxFactory);
566 m_browser->setFactoryForManager(m_boolManager, checkBoxFactory);
567 m_browser->setFactoryForManager(m_intManager, spinBoxFactory);
568 m_browser->setFactoryForManager(m_doubleManager, doubleEditorFactory);
569 m_browser->setFactoryForManager(m_stringManager, stringEditFactory);
570 m_browser->setFactoryForManager(m_filenameManager, filenameDialogEditorFactory);
571 m_browser->setFactoryForManager(m_formulaManager, formulaDialogEditFactory);
572 m_browser->setFactoryForManager(m_columnManager, comboBoxFactory);
573 m_browser->setFactoryForManager(m_vectorSizeManager, spinBoxFactory);
574 m_browser->setFactoryForManager(m_vectorDoubleManager, doubleEditorFactory);
575 m_browser->setFactoryForManager(m_parameterManager, new ParameterEditorFactory(w));
576}
577
581 QMenu *menuLoad = m_setupActionCustomSetup->menu();
582 menuLoad->clear();
583 QMenu *menuRemove = m_setupActionRemove->menu();
584 menuRemove->clear();
585
586 QSettings settings;
587 settings.beginGroup("Mantid/FitBrowser/SavedFunctions");
588 QStringList names = settings.childKeys();
589
590 QSignalMapper *mapperLoad = new QSignalMapper(this);
591 QSignalMapper *mapperRemove = new QSignalMapper(this);
592 // enable actions that open the menus only if there will be >=1 entries in
593 // there
594 m_setupActionCustomSetup->setEnabled(names.size() >= 1);
595 m_setupActionRemove->setEnabled(names.size() >= 1);
596 for (int i = 0; i < names.size(); i++) {
597 QAction *itemLoad = new QAction(names.at(i), this);
598 QAction *itemRemove = new QAction(names.at(i), this);
599 mapperLoad->setMapping(itemLoad, names.at(i));
600 mapperRemove->setMapping(itemRemove, names.at(i));
601 connect(itemLoad, SIGNAL(triggered()), mapperLoad, SLOT(map()));
602 connect(itemRemove, SIGNAL(triggered()), mapperRemove, SLOT(map()));
603 menuLoad->addAction(itemLoad);
604 menuRemove->addAction(itemRemove);
605 }
606 connect(mapperLoad, SIGNAL(mappedString(const QString &)), this, SLOT(executeCustomSetupLoad(const QString &)));
607 connect(mapperRemove, SIGNAL(mappedString(const QString &)), this, SLOT(executeCustomSetupRemove(const QString &)));
608}
609
611 QSettings settings;
612 settings.beginGroup("Mantid/FitBrowser/SavedFunctions");
613
614 QString str = settings.value(name).toString();
615 loadFunction(str);
616}
617
619 QSettings settings;
620 settings.beginGroup("Mantid/FitBrowser/SavedFunctions");
621
622 settings.remove(name);
624}
625
627 QSettings settings;
628 settings.beginGroup("Mantid/FitBrowser/SavedFunctions");
629
630 settings.clear();
632}
633
638 // Call tooltip update func on the root handler - it goes down recursively
640}
641
642void FitPropertyBrowser::executeFitMenu(const QString &item) {
643 if (item == "Fit") {
644 fit();
645 } else if (item == "SeqFit") {
647 } else if (item == "UndoFit") {
648 undoFit();
649 } else if (item == "Evaluate") {
650 doFit(0);
651 }
652}
653
654void FitPropertyBrowser::executeDisplayMenu(const QString &item) {
655 if (item == "PlotGuess") {
657 } else if (item == "ClearAll") {
659 }
660}
661
663 if (item == "FindPeaks")
664 findPeaks(std::make_unique<FindPeakDefaultStrategy>());
665 if (item == "FindPeaksConvolve")
666 findPeaks(std::make_unique<FindPeakConvolveStrategy>());
667}
668
669void FitPropertyBrowser::executeSetupMenu(const QString &item) {
670 if (item == "ClearFit")
671 clear();
672}
673
675 if (item == "SaveSetup")
676 saveFunction();
677 if (item == "ClearSetups")
679 if (item == "CopyToClipboard")
680 copy();
681 if (item == "LoadFromString")
683}
684
687 m_compositeFunction.reset();
688
689 // remove the FunctionFactory Observer
691 FunctionFactory::Instance().notificationCenter.removeObserver(m_updateObserver);
692
693 m_browser->unsetFactoryForManager(m_enumManager);
694 m_browser->unsetFactoryForManager(m_boolManager);
695 m_browser->unsetFactoryForManager(m_intManager);
696 m_browser->unsetFactoryForManager(m_doubleManager);
697 m_browser->unsetFactoryForManager(m_stringManager);
698 m_browser->unsetFactoryForManager(m_filenameManager);
699 m_browser->unsetFactoryForManager(m_formulaManager);
700 m_browser->unsetFactoryForManager(m_columnManager);
701 m_browser->unsetFactoryForManager(m_vectorSizeManager);
702 m_browser->unsetFactoryForManager(m_vectorDoubleManager);
703 m_browser->unsetFactoryForManager(m_parameterManager);
704}
705
708 return static_cast<PropertyHandler *>(m_compositeFunction->getHandler());
709}
710
712 PropertyHandler *h = getHandler()->addFunction(fnName);
713 emit functionChanged();
714 return h;
715}
716
718 if (handler) {
719 emit functionRemoved();
720 emit functionChanged();
722 handler->removeFunction();
723 compositeFunction()->checkFunction();
724 }
725}
726
730 QtBrowserItem *ci = m_browser->currentItem();
731 // Find the function which has ci as its top browser item
732 auto cf = getHandler()->findCompositeFunction(ci);
733 if (!cf)
734 return;
735
736 // Declare new widget for picking fit functions
738
739 connect(m_fitSelector, SIGNAL(accepted()), this, SLOT(acceptFit()));
740 connect(m_fitSelector, SIGNAL(rejected()), this, SLOT(closeFit()));
741 m_fitSelector->show();
742}
743
745 QtBrowserItem *ci = m_browser->currentItem();
746 std::shared_ptr<const Mantid::API::CompositeFunction> cf = getHandler()->findCompositeFunction(ci);
747 if (!cf)
748 return;
749 auto function = m_fitSelector->getFunction();
750 if (function.isEmpty()) {
751 return;
752 }
754 h->addFunction(function.toStdString());
755 emit functionChanged();
756
757 closeFit();
758}
759
761
768 emit functionRemoved();
769 m_autoBackground = nullptr;
770 }
771 if (!func) {
773 } else {
774 auto cf = std::dynamic_pointer_cast<Mantid::API::CompositeFunction>(func);
775 if (!cf || (cf->name() != "CompositeFunction" && cf->name() != "MultiBG" && cf->name() != "MultiDomainFunction")) {
777 m_compositeFunction->addFunction(func);
778 } else {
780 }
781 }
783
784 auto h = std::make_unique<PropertyHandler>(m_compositeFunction, Mantid::API::CompositeFunction_sptr(), this);
785 m_compositeFunction->setHandler(std::move(h));
786 setCurrentFunction(static_cast<PropertyHandler *>(m_compositeFunction->getHandler()));
787
788 if (m_auto_back) {
790 }
791
792 disableUndo();
793 setFitEnabled(m_compositeFunction->nFunctions() > 0);
794 emit functionChanged();
795}
796
802 if (str.isEmpty()) {
804 } else {
805 auto f = tryCreateFitFunction(str);
806 if (f) {
808 } else {
810 }
811 }
812}
813
815 try {
816 return Mantid::API::FunctionFactory::Instance().createInitialized(str.toStdString());
817 } catch (const std::exception &ex) {
818 QMessageBox::critical(this, "Mantid - Error", "Unexpected exception caught:\n\n" + QString(ex.what()));
819 return nullptr;
820 }
821}
822
823void FitPropertyBrowser::popupMenu(const QPoint & /*unused*/) {
824 QtBrowserItem *ci = m_browser->currentItem();
825 if (!ci)
826 return;
827 QMenu *menu = new QMenu(this);
828 QAction *action;
829
830 bool isFunctionsGroup = ci == m_functionsGroup;
831 bool isSettingsGroup = ci == m_settingsGroup;
832 bool isASetting = ci->parent() == m_settingsGroup;
833 bool isFunction = getHandler()->findFunction(ci) != nullptr;
834 bool isCompositeFunction = isFunction && getHandler()->findCompositeFunction(ci);
835
836 PropertyHandler *h = getHandler()->findHandler(ci->property());
837
838 if (isFunctionsGroup) {
839 action = new QAction("Add function", this);
840 connect(action, SIGNAL(triggered()), this, SLOT(addFunction()));
841 menu->addAction(action);
842
843 if (m_compositeFunction->name() == "MultiBG" && m_compositeFunction->nFunctions() == 1 &&
844 Mantid::API::AnalysisDataService::Instance().doesExist(workspaceName())) {
845 action = new QAction("Setup multifit", this);
846 connect(action, SIGNAL(triggered()), this, SLOT(setupMultifit()));
847 menu->addAction(action);
848 }
849
850 if (m_peakToolOn) {
851 if (h && h->hasPlot()) {
852 action = new QAction("Remove plot", this);
853 connect(action, SIGNAL(triggered()), this, SLOT(removeGuessAll()));
854 menu->addAction(action);
855 } else {
856 action = new QAction("Plot", this);
857 connect(action, SIGNAL(triggered()), this, SLOT(plotGuessAll()));
858 menu->addAction(action);
859 }
860 }
861
862 menu->addSeparator();
863
864 action = new QAction("Save", this);
865 connect(action, SIGNAL(triggered()), this, SLOT(saveFunction()));
866 menu->addAction(action);
867
868 action = new QAction("Load", this);
869 connect(action, SIGNAL(triggered()), this, SLOT(loadFunction()));
870 menu->addAction(action);
871
872 action = new QAction("Copy To Clipboard", this);
873 connect(action, SIGNAL(triggered()), this, SLOT(copy()));
874 menu->addAction(action);
875
876 menu->addSeparator();
877
878 action = new QAction("Help", this);
879 connect(action, SIGNAL(triggered()), this, SLOT(browserHelp()));
880 menu->addAction(action);
881 } else if (isSettingsGroup || isASetting) {
882 if (isFitEnabled()) {
883 action = new QAction("Fit", this);
884 connect(action, SIGNAL(triggered()), this, SLOT(fit()));
885 menu->addAction(action);
886 }
887
888 if (isUndoEnabled()) {
889 action = new QAction("Undo Fit", this);
890 connect(action, SIGNAL(triggered()), this, SLOT(undoFit()));
891 menu->addAction(action);
892 }
893
894 action = new QAction("Clear all", this);
895 connect(action, SIGNAL(triggered()), this, SLOT(clear()));
896 menu->addAction(action);
897
898 action = new QAction("Help", this);
899 connect(action, SIGNAL(triggered()), this, SLOT(browserHelp()));
900 menu->addAction(action);
901
902 } else if (isFunction) {
903 if (isCompositeFunction) {
904 action = new QAction("Add function", this);
905 connect(action, SIGNAL(triggered()), this, SLOT(addFunction()));
906 menu->addAction(action);
907 }
908
909 action = new QAction("Remove", this);
910 connect(action, SIGNAL(triggered()), this, SLOT(deleteFunction()));
911 menu->addAction(action);
912
913 if (m_peakToolOn) {
914 if (h && h->hasPlot()) {
915 action = new QAction("Remove plot", this);
916 connect(action, SIGNAL(triggered()), this, SLOT(removeGuessCurrent()));
917 menu->addAction(action);
918 } else {
919 action = new QAction("Plot", this);
920 connect(action, SIGNAL(triggered()), this, SLOT(plotGuessCurrent()));
921 menu->addAction(action);
922 }
923 }
924
925 action = new QAction("Help", this);
926 connect(action, SIGNAL(triggered()), this, SLOT(functionHelp()));
927 menu->addAction(action);
928
929 menu->addSeparator();
930 } else if (h) {
931 bool isParameter = h->isParameter(ci->property());
932 bool isTie = !isParameter && ci->property()->propertyName() == "Tie";
933 bool isLowerBound = !isParameter && ci->property()->propertyName() == "Lower Bound";
934 bool isUpperBound = !isParameter && ci->property()->propertyName() == "Upper Bound";
935 bool isType = isParameter && ci->property()->propertyName() == "Type";
936 if (isType) {
937 isParameter = false;
938 }
939 if (isTie) {
940 action = new QAction("Remove", this);
941 connect(action, SIGNAL(triggered()), this, SLOT(deleteTie()));
942 menu->addAction(action);
943 } else if (isLowerBound || isUpperBound) {
944 action = new QAction("Remove", this);
945 connect(action, SIGNAL(triggered()), this, SLOT(removeBounds()));
946 menu->addAction(action);
947 } else if (count() > 0 && isParameter) {
948 bool hasTies;
949 bool hasFixes;
950 bool hasBounds;
951 hasConstraints(ci->property(), hasTies, hasFixes, hasBounds);
952
953 if (!hasTies && !hasFixes) {
954 QMenu *constraintMenu = menu->addMenu("Constraint");
955
956 QMenu *detailMenu = constraintMenu->addMenu("Lower Bound");
957
958 action = new QAction("10%", this);
959 connect(action, SIGNAL(triggered()), this, SLOT(addLowerBound10()));
960 detailMenu->addAction(action);
961
962 action = new QAction("50%", this);
963 connect(action, SIGNAL(triggered()), this, SLOT(addLowerBound50()));
964 detailMenu->addAction(action);
965
966 action = new QAction("Custom", this);
967 connect(action, SIGNAL(triggered()), this, SLOT(addLowerBound()));
968 detailMenu->addAction(action);
969 detailMenu = constraintMenu->addMenu("Upper Bound");
970
971 action = new QAction("10%", this);
972 connect(action, SIGNAL(triggered()), this, SLOT(addUpperBound10()));
973 detailMenu->addAction(action);
974
975 action = new QAction("50%", this);
976 connect(action, SIGNAL(triggered()), this, SLOT(addUpperBound50()));
977 detailMenu->addAction(action);
978
979 action = new QAction("Custom", this);
980 connect(action, SIGNAL(triggered()), this, SLOT(addUpperBound()));
981 detailMenu->addAction(action);
982 detailMenu = constraintMenu->addMenu("Both Bounds");
983
984 action = new QAction("10%", this);
985 connect(action, SIGNAL(triggered()), this, SLOT(addBothBounds10()));
986 detailMenu->addAction(action);
987
988 action = new QAction("50%", this);
989 connect(action, SIGNAL(triggered()), this, SLOT(addBothBounds50()));
990 detailMenu->addAction(action);
991
992 action = new QAction("Custom", this);
993 connect(action, SIGNAL(triggered()), this, SLOT(addBothBounds()));
994 detailMenu->addAction(action);
995 }
996
997 if (hasBounds) {
998 action = new QAction("Remove constraints", this);
999 connect(action, SIGNAL(triggered()), this, SLOT(removeBounds()));
1000 menu->addAction(action);
1001 }
1002
1003 if (!hasTies && !hasFixes && !hasBounds) {
1004 action = new QAction("Fix", this);
1005 connect(action, SIGNAL(triggered()), this, SLOT(addFixTie()));
1006 menu->addAction(action);
1007
1008 if (count() == 1) {
1009 action = new QAction("Tie", this);
1010 connect(action, SIGNAL(triggered()), this, SLOT(addTie()));
1011 menu->addAction(action);
1012 } else {
1013 QMenu *detail = menu->addMenu("Tie");
1014
1015 action = new QAction("To function", this);
1016 connect(action, SIGNAL(triggered()), this, SLOT(addTieToFunction()));
1017 detail->addAction(action);
1018
1019 action = new QAction("Custom Tie", this);
1020 connect(action, SIGNAL(triggered()), this, SLOT(addTie()));
1021 detail->addAction(action);
1022 }
1023 } else if (hasTies) {
1024 action = new QAction("Remove tie", this);
1025 connect(action, SIGNAL(triggered()), this, SLOT(deleteTie()));
1026 menu->addAction(action);
1027 } else if (hasFixes) {
1028 action = new QAction("Remove fix", this);
1029 connect(action, SIGNAL(triggered()), this, SLOT(deleteTie()));
1030 menu->addAction(action);
1031 }
1032 }
1033 }
1034
1035 menu->popup(QCursor::pos());
1036}
1037
1041 const QtBrowserItem *const ci = m_browser->currentItem();
1042 PropertyHandler *h = getHandler()->findHandler(ci->property());
1043 removeFunction(h);
1044}
1045
1046//
1047
1048// Get the default function name
1050
1051// Set the default function name
1052void FitPropertyBrowser::setDefaultFunctionType(const std::string &fnType) { m_defaultFunction = fnType; }
1053
1056 // If the default peak is not in registered peaks, default to Gaussian
1057 if (m_registeredPeaks.indexOf(QString::fromStdString(m_defaultPeak)) == -1) {
1058 g_log.warning("Could not find peak function: '" + m_defaultPeak + "'. Defaulting to Gaussian.");
1059 setDefaultPeakType("Gaussian");
1060 }
1061 return m_defaultPeak;
1062}
1064void FitPropertyBrowser::setDefaultPeakType(const std::string &fnType) {
1065 m_defaultPeak = fnType;
1066 setDefaultFunctionType(fnType);
1067}
1071void FitPropertyBrowser::setDefaultBackgroundType(const std::string &fnType) {
1072 m_defaultBackground = fnType;
1073 setDefaultFunctionType(fnType);
1074}
1075
1076std::shared_ptr<Mantid::API::Workspace> FitPropertyBrowser::getWorkspace() const {
1077 std::string wsName = workspaceName();
1078 if (wsName.empty())
1079 return std::shared_ptr<Mantid::API::Workspace>();
1080 try {
1081 return Mantid::API::AnalysisDataService::Instance().retrieve(wsName);
1082 } catch (...) {
1083 return std::shared_ptr<Mantid::API::Workspace>();
1084 }
1085}
1086
1089 int i = m_enumManager->value(m_workspace);
1090 std::string res = "";
1091 if (i >= 0) {
1092 res = m_workspaceNames[i].toStdString();
1093 }
1094 return res;
1095}
1096
1098void FitPropertyBrowser::setWorkspaceName(const QString &wsName) {
1099 int i = static_cast<int>(m_workspaceNames.indexOf(wsName));
1100 if (i < 0) {
1101 // workspace may not be found because add notification hasn't been
1102 // processed yet
1104 i = static_cast<int>(m_workspaceNames.indexOf(wsName));
1105 }
1106 if (i >= 0) {
1107 m_enumManager->setValue(m_workspace, i);
1109 try {
1110 mws = std::dynamic_pointer_cast<Mantid::API::MatrixWorkspace>(
1111 Mantid::API::AnalysisDataService::Instance().retrieve(wsName.toStdString()));
1113 }
1114 if (mws) {
1115 auto wi = static_cast<size_t>(workspaceIndex());
1116 if (wi < mws->getNumberHistograms() && !mws->x(wi).empty()) {
1117 setStartX(mws->x(wi).front());
1118 setEndX(mws->x(wi).back());
1119 }
1120 }
1121 }
1123}
1124
1127
1130 try {
1131 auto const index = getAllowedIndex(i);
1134 // ignore this error
1135 }
1136}
1137
1139std::string FitPropertyBrowser::outputName() const { return m_stringManager->value(m_output).toStdString(); }
1140
1142void FitPropertyBrowser::setOutputName(const std::string &name) {
1143 m_stringManager->setValue(m_output, QString::fromStdString(name));
1144}
1145
1147std::string FitPropertyBrowser::minimizer(bool withProperties) const {
1148 int i = m_enumManager->value(m_minimizer);
1149 QString minimStr = m_minimizers[i];
1150 // append minimizer properties as name=value pairs
1151 if (withProperties) {
1152 foreach (const QtProperty *const prop, m_minimizerProperties) {
1153 if (prop->propertyManager() == m_stringManager) {
1154 QString value = m_stringManager->value(prop);
1155 if (!value.isEmpty()) {
1156 minimStr += "," + prop->propertyName() + "=" + value;
1157 }
1158 } else {
1159 minimStr += "," + prop->propertyName() + "=";
1160 if (prop->propertyManager() == m_intManager) {
1161 minimStr += QString::number(m_intManager->value(prop));
1162 } else if (prop->propertyManager() == m_doubleManager) {
1163 minimStr += QString::number(m_doubleManager->value(prop));
1164 } else if (prop->propertyManager() == m_boolManager) {
1165 minimStr += QString::number(m_boolManager->value(prop));
1166 } else {
1167 throw std::runtime_error("The fit browser doesn't support the type "
1168 "of minimizer's property " +
1169 prop->propertyName().toStdString());
1170 }
1171 }
1172 }
1173 }
1174 return minimStr.toStdString();
1175}
1176
1179
1182
1185 int i = m_enumManager->value(m_costFunction);
1186 return m_costFunctions[i].toStdString();
1187}
1188
1193
1196 if (!m_evaluationType->isEnabled()) {
1197 return false;
1198 }
1199 int i = m_enumManager->value(m_evaluationType);
1200 return m_evaluationTypes[i].toStdString() == "Histogram";
1201}
1202
1205
1208
1211 return m_stringManager->value(m_excludeRange).QString::toStdString();
1212}
1213
1216 const std::vector<std::string> names = Mantid::API::FunctionFactory::Instance().getFunctionNamesGUI();
1217 m_registeredFunctions.clear();
1218 m_registeredPeaks.clear();
1220 m_registeredOther.clear();
1221
1222 const auto &functionFactory = Mantid::API::FunctionFactory::Instance();
1223 for (const auto &fnName : names) {
1224 if (fnName == "MultiBG")
1225 continue;
1227 try {
1228 function = functionFactory.createFunction(fnName);
1229 } catch (std::exception &exc) {
1230 g_log.warning() << "Unable to create " << fnName << ": " << exc.what() << "\n";
1231 continue;
1232 }
1233 QString qfnName = QString::fromStdString(fnName);
1234 m_registeredFunctions << qfnName;
1235 if (dynamic_cast<Mantid::API::IPeakFunction *>(function.get())) {
1236 m_registeredPeaks << qfnName;
1237 } else if (dynamic_cast<Mantid::API::IBackgroundFunction *>(function.get())) {
1238 m_registeredBackgrounds << qfnName;
1239 } else {
1240 m_registeredOther << qfnName;
1241 }
1242 }
1243}
1244
1248void FitPropertyBrowser::enumChanged(QtProperty *prop) {
1250 return;
1251
1252 bool storeSettings = false;
1253 if (prop == m_workspace) {
1254 workspaceChange(QString::fromStdString(workspaceName()));
1258 } else if (prop->propertyName() == "Type") {
1259 disableUndo();
1261 if (!h)
1262 return;
1263 // if (!h->parentHandler()) return;
1264 auto f = h->changeType(prop);
1265 if (!h->parentHandler()) {
1266 m_compositeFunction = std::dynamic_pointer_cast<Mantid::API::CompositeFunction>(f);
1267 }
1268 if (f)
1270 emit functionChanged();
1271
1272 } else if (prop == m_minimizer) {
1274 } else if (prop == m_evaluationType) {
1275 storeSettings = true;
1276 }
1277
1278 if (storeSettings) {
1279 QSettings settings;
1280 settings.beginGroup("Mantid/FitBrowser");
1281 auto val = m_enumManager->value(prop);
1282 settings.setValue(prop->propertyName(), val);
1283 }
1284}
1285
1289void FitPropertyBrowser::boolChanged(QtProperty *prop) {
1291 return;
1292
1293 if (prop == m_plotDiff || prop == m_plotCompositeMembers || prop == m_ignoreInvalidData ||
1294 prop == m_showParamErrors) {
1295 bool val = m_boolManager->value(prop);
1296
1297 QSettings settings;
1298 settings.beginGroup("Mantid/FitBrowser");
1299 settings.setValue(prop->propertyName(), val);
1300
1301 if (prop == m_showParamErrors) {
1302 m_parameterManager->setErrorsEnabled(val);
1303 emit errorsEnabled(val);
1304 }
1305 } else { // it could be an attribute
1307 if (!h)
1308 return;
1309 enactAttributeChange(prop, h);
1310 }
1311}
1312
1316void FitPropertyBrowser::intChanged(QtProperty *prop) {
1318 return;
1319
1320 if (prop == m_workspaceIndex) {
1321 // Get current value displayed by the workspace index spinbox
1322 auto const currentIndex = workspaceIndex();
1323 auto const allowedIndex = getAllowedIndex(currentIndex);
1324 if (allowedIndex != currentIndex) {
1325 setWorkspaceIndex(allowedIndex);
1326 emit workspaceIndexChanged(allowedIndex);
1327 }
1328 m_oldWorkspaceIndex = allowedIndex;
1329 } else if (prop->propertyName() == "Workspace Index") {
1330 // Property field from Settings. Note the white space.
1332 if (!h)
1333 return;
1335 } else if (prop->propertyName() == "WorkspaceIndex") {
1336 // Property field from functions. In a word.
1338 auto const index = prop->valueText().toInt();
1339 if (h) {
1340 h->setAttribute(prop);
1344 }
1345 } else if (prop == m_maxIterations || prop == m_peakRadius) {
1346 QSettings settings;
1347 settings.beginGroup("Mantid/FitBrowser");
1348 int val = m_intManager->value(prop);
1349 settings.setValue(prop->propertyName(), val);
1350 if (prop == m_peakRadius) {
1352 }
1353 } else { // it could be an attribute
1355 if (!h)
1356 return;
1357 enactAttributeChange(prop, h);
1358 }
1359}
1360
1366 return;
1367
1368 double value = m_doubleManager->value(prop);
1369 if (prop == m_startX) {
1370 // call setWorkspace to change maxX in functions
1372 m_doubleManager->setMinimum(m_endX, value);
1373 getHandler()->setAttribute("StartX", value);
1374 emit startXChanged(startX());
1375 emit xRangeChanged(startX(), endX());
1376 return;
1377 } else if (prop == m_endX) {
1378 // call setWorkspace to change minX in functions
1380 m_doubleManager->setMaximum(m_startX, value);
1381 getHandler()->setAttribute("EndX", value);
1382 emit endXChanged(endX());
1383 emit xRangeChanged(startX(), endX());
1384 return;
1385 } else { // check if it is a constraint
1387 if (!h)
1388 return;
1389
1390 QtProperty *parProp = h->getParameterProperty(prop);
1391 if (parProp) {
1392 if (prop->propertyName() == "LowerBound") {
1393 double loBound = m_doubleManager->value(prop);
1394 h->addConstraint(parProp, true, false, loBound, 0);
1395 } else if (prop->propertyName() == "UpperBound") {
1396 double upBound = m_doubleManager->value(prop);
1397 h->addConstraint(parProp, false, true, 0, upBound);
1398 }
1399 } else { // it could be an attribute
1400 enactAttributeChange(prop, h);
1401 }
1402 }
1403}
1404
1405void FitPropertyBrowser::enactAttributeChange(QtProperty *prop, PropertyHandler *h, const bool vectorAttribute) {
1406 try {
1407 if (vectorAttribute) {
1408 h->setVectorAttribute(prop);
1409 } else {
1410 h->setAttribute(prop);
1411 }
1412 } catch (IFunction::ValidationException &ve) {
1413 std::stringstream err_str;
1414 err_str << prop->propertyName().toStdString() << " - " << ve.what();
1415 g_log.warning(err_str.str());
1416 }
1417}
1418
1427 return;
1428
1429 getHandler()->setParameter(prop);
1430}
1431
1437 return;
1438
1439 if (prop == m_output) {
1440 std::string oName = outputName();
1441 if (oName.find_first_not_of(' ') == std::string::npos) {
1442 setOutputName("");
1443 } else if (workspaceName() == oName || oName.empty()) {
1444 m_guessOutputName = true;
1445 } else {
1446 m_guessOutputName = false;
1447 }
1448 } else if (prop->propertyName() == "Tie") {
1450 if (!h)
1451 return;
1452
1453 const QtProperty *const parProp = h->getParameterProperty(prop);
1454 if (!parProp)
1455 return;
1456
1457 const QString parName = h->functionPrefix() + "." + parProp->propertyName();
1458
1459 const auto oldExp = getOldExpressionAsString(parName);
1460 const auto exp = m_stringManager->value(prop);
1461
1462 if (oldExp == exp)
1463 return;
1464
1465 try {
1466 compositeFunction().get()->tie(parName.toStdString(), exp.toStdString());
1467 h->addTie(parName + "=" + exp);
1468 } catch (...) {
1469 const auto msg =
1470 "Failed to update tie on " + parName.toStdString() + ". Expression " + exp.toStdString() + " is invalid.";
1471 QMessageBox::critical(this, "Mantid - Error", msg.c_str());
1472
1473 m_stringManager->setValue(prop, oldExp);
1474 }
1475 } else if (getHandler()->setAttribute(prop)) { // setting an attribute may
1476 // change function parameters
1477 emit functionChanged();
1478 return;
1479 }
1480}
1481
1485QString FitPropertyBrowser::getOldExpressionAsString(const QString &parameterName) const {
1486 // Note this only finds the oldTie if it was a tie to a function (e.g. f0.Height=f1.Height)
1487 // but not if it was a custom tie (e.g. f0.Height=2.0)
1488 QString oldExp;
1489 size_t parIndex;
1490 try {
1491 parIndex = compositeFunction()->parameterIndex(parameterName.toStdString());
1492 } catch (std::exception &) {
1493 return "";
1494 }
1495 const auto oldTie = compositeFunction()->getTie(parIndex);
1496 if (oldTie) {
1497 const auto oldTieStr = oldTie->asString();
1498 oldExp = QString::fromStdString(oldTieStr.substr(oldTieStr.find("=") + 1));
1499 } else {
1500 oldExp = "";
1501 }
1502 return oldExp;
1503}
1504
1510 return;
1511
1512 if (getHandler()->setAttribute(prop)) {
1513 return;
1514 }
1515}
1516// Centre of the current peak
1519 return m_currentHandler->pfun()->centre();
1520 }
1521 return 0;
1522}
1523
1534
1535// Height of the current peak
1538 return m_currentHandler->pfun()->height();
1539 }
1540 return 0.;
1541}
1542
1553
1554// Width of the current peak
1557 return m_currentHandler->pfun()->fwhm();
1558 }
1559 return 0;
1560}
1561
1572
1574int FitPropertyBrowser::count() const { return static_cast<int>(m_compositeFunction->nFunctions()); }
1575
1578
1583 m_currentHandler = h;
1584 if (m_currentHandler) {
1585 m_browser->setCurrentItem(m_currentHandler->item());
1586 emit currentChanged();
1587 }
1588}
1589
1596
1600void FitPropertyBrowser::doFit(int maxIterations) {
1601 const std::string wsName = workspaceName();
1602
1603 if (wsName.empty()) {
1604 QMessageBox::critical(this, "Mantid - Error", "Workspace name is not set");
1605 return;
1606 }
1607
1608 const auto ws = getWorkspace();
1609 if (!ws) {
1610 return;
1611 }
1612
1613 try {
1614 emit algorithmStarted(QString::fromStdString(wsName));
1615 m_initialParameters.resize(compositeFunction()->nParams());
1616 for (size_t i = 0; i < compositeFunction()->nParams(); i++) {
1617 m_initialParameters[i] = compositeFunction()->getParameter(i);
1618 }
1619 m_fitActionUndoFit->setEnabled(true);
1620
1621 Mantid::API::IAlgorithm_sptr alg = Mantid::API::AlgorithmManager::Instance().create("Fit");
1622 alg->initialize();
1623 if (isHistogramFit()) {
1624 alg->setProperty("EvaluationType", "Histogram");
1625 }
1626 alg->setProperty("Function", std::dynamic_pointer_cast<Mantid::API::IFunction>(compositeFunction())->clone());
1627 alg->setProperty("InputWorkspace", ws);
1628 auto tbl = std::dynamic_pointer_cast<ITableWorkspace>(ws);
1629 if (!tbl) {
1630 alg->setProperty("WorkspaceIndex", workspaceIndex());
1631 } else {
1632 alg->setPropertyValue("XColumn", getXColumnName().toStdString());
1633 alg->setPropertyValue("YColumn", getYColumnName().toStdString());
1634 if (getErrColumnName().toStdString() != "")
1635 alg->setPropertyValue("ErrColumn", getErrColumnName().toStdString());
1636 }
1637 alg->setProperty("StartX", startX());
1638 alg->setProperty("EndX", endX());
1639 alg->setPropertyValue("Output", outputName());
1640 alg->setPropertyValue("Minimizer", minimizer(true));
1641 alg->setProperty("IgnoreInvalidData", ignoreInvalidData());
1642 alg->setPropertyValue("CostFunction", costFunction());
1643 alg->setProperty("MaxIterations", maxIterations);
1644 alg->setProperty("PeakRadius", getPeakRadius());
1645 if (!isHistogramFit()) {
1646 if (!tbl) {
1647 alg->setProperty("Normalise", m_shouldBeNormalised);
1648 }
1649 // Always output each composite function but not necessarily plot it
1650 alg->setProperty("OutputCompositeMembers", true);
1651 if (alg->existsProperty("ConvolveMembers")) {
1652 alg->setProperty("ConvolveMembers", convolveMembers());
1653 }
1654 }
1655 if (!getExcludeRange().empty()) {
1656 if (alg->getPropertyValue("EvaluationType") != "Histogram")
1657 alg->setProperty("Exclude", getExcludeRange());
1658 else {
1659 g_log.warning("Exclude property not avaliable when evaluating as a histogram.");
1660 }
1661 }
1662 observeFinish(alg);
1663 Poco::ActiveResult<bool> result(alg->executeAsync());
1664 while (!result.available()) {
1665 QCoreApplication::processEvents();
1666 }
1667 m_fitAlgParameters = alg->toString();
1668 if (!result.error().empty()) {
1669 emit algorithmFailed();
1670 }
1671 } catch (const std::exception &e) {
1672 QString msg = "Fit algorithm failed.\n\n" + QString(e.what()) + "\n";
1673 QMessageBox::critical(this, "Mantid - Error", msg);
1674 }
1675}
1676
1682 if (m_compositeFunction->nFunctions() > 1) {
1683 function = m_compositeFunction;
1684 } else {
1685 function = getFunctionAtIndex(0);
1686 }
1687 return function;
1688}
1689
1694 return m_compositeFunction->getFunction(index);
1695}
1696
1698 // Emit a signal to show that the fitting has completed. (workspaceNames that
1699 // the fit has been done against is sent as a parameter)
1700 QString name(QString::fromStdString(alg->getProperty("InputWorkspace")));
1701 if (name.contains('_')) // Must be fitting to raw data, need to group under
1702 // name without "_Raw".
1703 emit fittingDone(name.left(name.indexOf('_')));
1704 else // else fitting to current workspace, group under same name.
1705 emit fittingDone(name);
1706
1707 IFunction_sptr function = alg->getProperty("Function");
1709 if (alg->existsProperty("OutputWorkspace")) {
1710 std::string out = alg->getProperty("OutputWorkspace");
1711 emit algorithmFinished(QString::fromStdString(out));
1712 }
1713 // Update Status string in member variable (so can be retrieved)
1714 m_fitAlgOutputStatus = alg->getPropertyValue("OutputStatus");
1715 auto status = QString::fromStdString(m_fitAlgOutputStatus);
1716 emit fitResultsChanged(status);
1717 // update Quality string
1718 if (m_displayActionQuality->isChecked()) {
1719 double quality = alg->getProperty("OutputChi2overDoF");
1720 std::string costFunctionStr = alg->getProperty("CostFunction");
1721 std::shared_ptr<Mantid::API::ICostFunction> costfun =
1722 Mantid::API::CostFunctionFactory::Instance().create(costFunctionStr);
1723 status = (status == "success") ? "success" : "failed";
1724 emit changeWindowTitle(QString("Fit Function (") + costfun->shortName().c_str() + " = " + QString::number(quality) +
1725 ", " + status + ")");
1726 } else
1727 emit changeWindowTitle("Fit Function");
1728 if (m_compositeFunction->name() == "MultiBG") {
1729 emit multifitFinished();
1730 }
1731}
1732
1734 auto function = getFittingFunction();
1735 return function->asString();
1736}
1737
1740void FitPropertyBrowser::showFitResultStatus(const QString &status) {
1741 auto text(status);
1742 text.replace("\n", "<br>");
1743 QString color("green");
1744 if (status != "success") {
1745 color = "red";
1746 }
1747
1748 m_status->setText(QString("Status: <span style='color:%2'>%1</span>").arg(text, color));
1749 m_status->show();
1750}
1751
1754 m_status->setText("Status:");
1755 m_status->hide();
1756}
1757
1760 m_workspaceNames.clear();
1761 if (m_allowedTableWorkspace.isEmpty()) {
1762 bool allAreAllowed = m_allowedSpectra.isEmpty();
1763 QStringList allowedNames;
1764 auto wsList = Mantid::API::AnalysisDataService::Instance().getObjectNames();
1765 for (const auto &wsName : wsList) {
1766 auto const &name = QString::fromStdString(wsName);
1767 if (allAreAllowed || m_allowedSpectra.contains(name)) {
1768 allowedNames << name;
1769 }
1770 }
1771
1772 for (const auto &name : allowedNames) {
1773 Mantid::API::Workspace_sptr ws = Mantid::API::AnalysisDataService::Instance().retrieve(name.toStdString());
1774 if (isWorkspaceValid(ws)) {
1775 m_workspaceNames.append(name);
1776 }
1777 }
1778 } else {
1780 }
1783}
1784
1789 (void)e;
1790 // Observe what workspaces are added and deleted unless it's a custom
1791 // fitting, all workspaces for custom fitting (eg muon analysis) should be
1792 // manually added.
1795}
1796
1801 (void)e;
1802 setADSObserveEnabled(false);
1803}
1804
1806 observeAdd(enabled);
1807 observePostDelete(enabled);
1808 observeRename(enabled);
1809}
1810
1812void FitPropertyBrowser::addHandle(const std::string &wsName, const std::shared_ptr<Mantid::API::Workspace> &ws) {
1813 auto const qName = QString::fromStdString(wsName);
1814 if (!isWorkspaceValid(ws) ||
1815 (!m_allowedSpectra.isEmpty() && !m_allowedSpectra.contains(qName) && m_allowedTableWorkspace.isEmpty()))
1816 return;
1817 QString oldName = QString::fromStdString(workspaceName());
1818 int i = static_cast<int>(m_workspaceNames.indexOf(qName));
1819
1820 bool initialSignalsBlocked = m_enumManager->signalsBlocked();
1821
1822 // if new workspace append this workspace name
1823 if (i < 0) {
1824 if (!m_workspaceNames.isEmpty()) {
1825 m_enumManager->blockSignals(true);
1826 }
1827
1828 m_workspaceNames.append(qName);
1829 m_workspaceNames.sort();
1831 }
1832 // get hold of index of oldName
1833 i = static_cast<int>(m_workspaceNames.indexOf(oldName));
1834 if (i >= 0) {
1835 m_enumManager->setValue(m_workspace, i);
1836 }
1837
1838 m_enumManager->blockSignals(initialSignalsBlocked);
1839}
1840
1842void FitPropertyBrowser::postDeleteHandle(const std::string &wsName) { removeWorkspace(wsName); }
1843
1844void FitPropertyBrowser::removeWorkspace(const std::string &wsName) {
1845 QString oldName = QString::fromStdString(workspaceName());
1846 int iName = static_cast<int>(m_workspaceNames.indexOf(QString(wsName.c_str())));
1847 if (iName >= 0) {
1848 m_workspaceNames.removeAt(iName);
1849 }
1850
1851 bool initialSignalsBlocked = m_enumManager->signalsBlocked();
1852
1853 if (QString::fromStdString(wsName) != oldName) {
1854 m_enumManager->blockSignals(true);
1855 }
1856
1858
1859 iName = static_cast<int>(m_workspaceNames.indexOf(oldName));
1860 if (iName >= 0) {
1861 m_enumManager->setValue(m_workspace, iName);
1862 }
1863
1864 m_enumManager->blockSignals(initialSignalsBlocked);
1865
1866 for (auto i = 0; i < m_wsListWidget->count(); ++i) {
1867 auto item = m_wsListWidget->item(i);
1868 if (item->text().toStdString() == wsName) {
1869 m_wsListWidget->takeItem(m_wsListWidget->row(item));
1870 }
1871 }
1872
1873 if (m_wsListWidget->count() == 0) {
1874 m_wsListWidget->hide();
1875 m_workspaceLabel->hide();
1876 }
1877}
1878
1879void FitPropertyBrowser::renameHandle(const std::string &oldName, const std::string &newName) {
1880 QString oldNameQ = QString::fromStdString(oldName);
1881 QString newNameQ = QString::fromStdString(newName);
1882 auto it = m_allowedSpectra.find(oldNameQ);
1883 if (it != m_allowedSpectra.end()) {
1884 auto indices = m_allowedSpectra.value(oldNameQ);
1885 m_allowedSpectra.remove(oldNameQ);
1886 m_allowedSpectra.insert(newNameQ, indices);
1887 }
1888 int iWorkspace = static_cast<int>(m_workspaceNames.indexOf(oldNameQ));
1889 if (iWorkspace >= 0) {
1890 m_workspaceNames.replace(iWorkspace, newNameQ);
1892 }
1893 workspaceChange(newNameQ);
1894
1895 for (auto i = 0; i < m_wsListWidget->count(); ++i) {
1896 auto item = m_wsListWidget->item(i);
1897 if (item->text().toStdString() == oldName) {
1898 m_wsListWidget->takeItem(m_wsListWidget->row(item));
1899 m_wsListWidget->insertItem(m_wsListWidget->row(item), newNameQ);
1900 }
1901 }
1902}
1903
1909 return (dynamic_cast<Mantid::API::MatrixWorkspace *>(ws.get()) != nullptr ||
1910 dynamic_cast<Mantid::API::ITableWorkspace *>(ws.get()) != nullptr);
1911}
1912
1915 if (count() == 0) {
1916 return false;
1917 }
1919}
1920
1922double FitPropertyBrowser::startX() const { return m_doubleManager->value(m_startX); }
1923
1926
1928double FitPropertyBrowser::endX() const { return m_doubleManager->value(m_endX); }
1929
1932
1933void FitPropertyBrowser::setXRange(double start, double end) {
1934 disconnect(m_doubleManager, SIGNAL(propertyChanged(QtProperty *)), this, SLOT(doubleChanged(QtProperty *)));
1935
1936 m_doubleManager->setValue(m_startX, start);
1937 m_doubleManager->setValue(m_endX, end);
1938
1940 m_doubleManager->setMinimum(m_endX, start);
1941 m_doubleManager->setMaximum(m_startX, end);
1942
1943 getHandler()->setAttribute("StartX", start);
1944 getHandler()->setAttribute("EndX", end);
1945
1946 connect(m_doubleManager, SIGNAL(propertyChanged(QtProperty *)), this, SLOT(doubleChanged(QtProperty *)));
1947}
1948
1950 auto ws = getWorkspace();
1951 auto tbl = std::dynamic_pointer_cast<ITableWorkspace>(ws);
1952 auto mws = std::dynamic_pointer_cast<MatrixWorkspace>(ws);
1953 QVector<double> range;
1954 if (tbl) {
1955 auto xColumnIndex = m_columnManager->value(m_xColumn);
1956 std::vector<double> xColumnData;
1957 auto col = tbl->getColumn(xColumnIndex);
1958 try {
1959 for (size_t i = 0; i < tbl->rowCount(); ++i) {
1960 xColumnData.emplace_back(col->toDouble(i));
1961 }
1962 } catch (std::invalid_argument &err) {
1963 QMessageBox::critical(this, "Mantid - Error", "The X column is not a number");
1964 throw std::invalid_argument(err);
1965 }
1966 std::sort(xColumnData.begin(), xColumnData.end());
1967 range.push_back(xColumnData.front());
1968 range.push_back(xColumnData.back());
1969 } else if (mws) {
1970 auto xData = mws->mutableX(workspaceIndex());
1971 range.push_back(xData.front());
1972 range.push_back(xData.back());
1973 }
1974 return range;
1975}
1976
1978 const auto ws = getWorkspace();
1979 auto tbl = std::dynamic_pointer_cast<ITableWorkspace>(ws);
1980 QString columnName = "";
1981 if (tbl) {
1982 auto columns = tbl->getColumnNames();
1983 auto xIndex = m_columnManager->value(m_xColumn);
1984 if (xIndex >= static_cast<int>(columns.size())) {
1985 QMessageBox::critical(nullptr, "Mantid - Error", "X column was not found.");
1986 }
1987 columnName = QString::fromStdString(columns[xIndex]);
1988 }
1989 return columnName;
1990}
1991
1993 const auto ws = getWorkspace();
1994 auto tbl = std::dynamic_pointer_cast<ITableWorkspace>(ws);
1995 QString columnName = "";
1996 if (tbl) {
1997 auto columns = tbl->getColumnNames();
1998 auto yIndex = m_columnManager->value(m_yColumn);
1999 if (yIndex >= static_cast<int>(columns.size())) {
2000 QMessageBox::critical(nullptr, "Mantid - Error", "Y column was not found.");
2001 }
2002 columnName = QString::fromStdString(columns[yIndex]);
2003 }
2004 return columnName;
2005}
2006
2008 const auto ws = getWorkspace();
2009 auto tbl = std::dynamic_pointer_cast<ITableWorkspace>(ws);
2010 QString columnName = "";
2011 if (tbl) {
2012 auto columns = tbl->getColumnNames();
2013 // The error column has an empty first entry
2014 auto errIndex = m_columnManager->value(m_errColumn) - 1;
2015 if (errIndex >= static_cast<int>(columns.size())) {
2016 QMessageBox::warning(nullptr, "Mantid - Warning", "Error column was not found.");
2017 } else if (errIndex != -1) {
2018 columnName = QString::fromStdString(columns[errIndex]);
2019 }
2020 }
2021 return columnName;
2022}
2023
2025QtBrowserItem *FitPropertyBrowser::findItem(QtBrowserItem *parent, QtProperty *prop) const {
2026 QList<QtBrowserItem *> children = parent->children();
2027 QtBrowserItem *res = nullptr;
2028 for (auto &child : children) {
2029 if (child->property() == prop) {
2030 return child;
2031 }
2032 QList<QtBrowserItem *> grand_children = child->children();
2033 if (grand_children.size() > 0)
2034 res = findItem(child, prop);
2035 if (res)
2036 return res;
2037 }
2038 return nullptr;
2039}
2040
2044void FitPropertyBrowser::currentItemChanged(const QtBrowserItem *current) {
2045 if (current) {
2046 m_currentHandler = getHandler()->findHandler(current->property());
2047 } else {
2048 m_currentHandler = nullptr;
2049 }
2050 emit currentChanged();
2051}
2052
2059 if (!h)
2060 return;
2061 enactAttributeChange(prop, h, true);
2062}
2063
2070 if (!h)
2071 return;
2072 enactAttributeChange(prop, h, true);
2073}
2074
2079
2084
2094
2096 QList<QtProperty *> props = m_functionsGroup->property()->subProperties();
2097 foreach (QtProperty *prop, props) {
2098 m_functionsGroup->property()->removeSubProperty(prop);
2099 }
2100}
2101
2104 for (auto paramIndex = 0u; paramIndex < finalFunction->nParams(); ++paramIndex) {
2105 compositeFunction()->setParameter(paramIndex, finalFunction->getParameter(paramIndex));
2106 compositeFunction()->setError(paramIndex, finalFunction->getError(paramIndex));
2107 }
2110}
2111
2116 if (m_initialParameters.size() == compositeFunction()->nParams()) {
2117 for (size_t i = 0; i < compositeFunction()->nParams(); i++) {
2118 compositeFunction()->setParameter(i, m_initialParameters[i]);
2119 }
2123 emit fitUndone();
2124 }
2125 disableUndo();
2126}
2127
2130 m_initialParameters.clear();
2131 m_fitActionUndoFit->setEnabled(false);
2132}
2133
2136 return m_initialParameters.size() && compositeFunction()->nParams() == m_initialParameters.size();
2137}
2138
2141 m_fitActionFit->setEnabled(enable);
2142 m_fitActionSeqFit->setEnabled(enable);
2143}
2144
2146bool FitPropertyBrowser::isFitEnabled() const { return m_fitActionFit->isEnabled(); }
2147
2152 QtBrowserItem *ci = m_browser->currentItem();
2153 QtProperty *paramProp = ci->property();
2154 PropertyHandler *h = getHandler()->findHandler(paramProp);
2155 if (!h)
2156 return;
2157 if (!h->isParameter(paramProp))
2158 return;
2159
2160 auto f = h->function();
2161 if (!f)
2162 return;
2163
2164 bool ok = false;
2165 QString tieStr = QInputDialog::getText(this, "Mantid - Fit", "Enter tie expression", QLineEdit::Normal, "", &ok);
2166 if (ok) {
2167 tieStr = tieStr.trimmed();
2168 if (!tieStr.contains('=')) {
2169 tieStr = h->functionPrefix() + "." + paramProp->propertyName() + "=" + tieStr;
2170 }
2171 h->addTie(tieStr);
2172 } // if (ok)
2173}
2174
2180 QtBrowserItem *ci = m_browser->currentItem();
2181 QtProperty *paramProp = ci->property();
2182 PropertyHandler *h = getHandler()->findHandler(paramProp);
2183 if (!h)
2184 return;
2185 if (!h->isParameter(paramProp))
2186 return;
2187 std::string parName = paramProp->propertyName().toStdString();
2188 QStringList fnNames;
2189
2190 int iPar = -1;
2191 for (size_t i = 0; i < m_compositeFunction->nParams(); i++) {
2193 const Mantid::API::IFunction *const fun = ref.getLocalFunction();
2194
2195 // Pick out parameters with the same name as the one we're tying from
2196 if (fun->parameterName(static_cast<int>(ref.getLocalIndex())) == parName) {
2197 if (iPar == -1 && fun == h->function().get()) // If this is the 'tied from' parameter, remember it
2198 {
2199 iPar = (int)i;
2200 } else // Otherwise add it to the list of potential 'tyees'
2201 {
2202 fnNames << QString::fromStdString(m_compositeFunction->parameterName(i));
2203 }
2204 }
2205 }
2206 if (fnNames.empty() || iPar < 0) {
2207 QMessageBox::information(this, "Mantid - information", "Cannot tie this parameter to any function");
2208 return;
2209 }
2210
2211 bool ok;
2212 QString tieName = QInputDialog::getItem(this, "Mantid - Fit", "Select function", fnNames, 0, false, &ok);
2213
2214 if (!ok)
2215 return;
2216
2217 QString tieExpr = QString::fromStdString(m_compositeFunction->parameterName(iPar)) + "=" + tieName;
2218
2219 h->addTie(tieExpr);
2220}
2221
2226 QtBrowserItem *ci = m_browser->currentItem();
2227 QtProperty *paramProp = ci->property();
2228 PropertyHandler *h = getHandler()->findHandler(paramProp);
2229 if (!h)
2230 return;
2231 if (!h->isParameter(paramProp))
2232 return;
2233 h->fix(paramProp->propertyName());
2234}
2235
2240 QtBrowserItem *ci = m_browser->currentItem();
2241 QtProperty *paramProp = ci->property();
2242 PropertyHandler *h = getHandler()->findHandler(paramProp);
2243 if (!h)
2244 return;
2245 // get name of parent property (i.e. function)
2246 if (paramProp->propertyName() != "Tie") {
2247 auto parameterMap = h->getTies();
2248 auto match = parameterMap.find(paramProp->propertyName());
2249 if (match != parameterMap.end()) {
2250 paramProp = match.value();
2251 }
2252 }
2253 if (paramProp->propertyName() == "Tie") {
2254 auto ties = h->getTies();
2255 QString qParName = ties.key(paramProp, "");
2256 std::string parName = qParName.toStdString();
2257 QStringList functionNames;
2258 // ithParameter = -1 => not found
2259 int ithParameter = -1;
2260 for (size_t i = 0; i < m_compositeFunction->nParams(); i++) {
2261 const Mantid::API::ParameterReference parameterRef(m_compositeFunction.get(), i);
2262 const Mantid::API::IFunction *const function = parameterRef.getLocalFunction();
2263 // Pick out parameters with the same name as the one we're tying from
2264 if (function->parameterName(static_cast<int>(parameterRef.getLocalIndex())) == parName) {
2265 if (ithParameter == -1 && function == h->function().get()) // If this is the 'tied from'
2266 // parameter, remember it
2267 {
2268 ithParameter = static_cast<int>(i);
2269 } else // Otherwise add it to the list of potential 'tyees'
2270 {
2271 functionNames << QString::fromStdString(m_compositeFunction->parameterName(i));
2272 }
2273 }
2274 }
2275 if (functionNames.empty() && ithParameter < 0) {
2276 QMessageBox::information(this, "Mantid - information", "Cannot find a parameter with this tie");
2277 } else {
2278 QString tieExpr = QString::fromStdString(m_compositeFunction->parameterName(ithParameter));
2279 h->removeTie(paramProp, tieExpr.toStdString());
2280 }
2281 } else {
2282 h->removeTie(ci->property()->propertyName());
2283 }
2284}
2285
2292void FitPropertyBrowser::hasConstraints(QtProperty *parProp, bool &hasTie, bool &hasFix, bool &hasBounds) const {
2293 hasTie = false;
2294 hasFix = false;
2295 hasBounds = false;
2296 QList<QtProperty *> subs = parProp->subProperties();
2297 for (const auto *sub : subs) {
2298 const auto propName = sub->propertyName();
2299 if (propName == "Tie") {
2300 hasTie = true;
2301 } else if (propName == "Fix") {
2302 hasFix = true;
2303 } else if (propName == "LowerBound") {
2304 hasBounds = true;
2305 } else if (propName == "UpperBound") {
2306 hasBounds = true;
2307 }
2308 }
2309}
2310
2314QtProperty *FitPropertyBrowser::getTieProperty(QtProperty *parProp) const {
2315 QList<QtProperty *> subs = parProp->subProperties();
2316 if (auto sub =
2317 std::find_if(std::cbegin(subs), std::cend(subs), [](const auto x) { return (*x).propertyName() == "Tie"; });
2318 sub != std::cend(subs)) {
2319 return *sub;
2320 }
2321 return nullptr;
2322}
2323
2329 Q_UNUSED(notice);
2330 // Don't call populate directly as the updates can come from a different
2331 // thread
2333}
2334
2338void FitPropertyBrowser::setTip(const QString &txt) { m_tip->setText(txt); }
2339
2344void FitPropertyBrowser::addConstraint(int f, bool lo, bool up) {
2345 QtBrowserItem *ci = m_browser->currentItem();
2346 QtProperty *parProp = ci->property();
2347 PropertyHandler *h = getHandler()->findHandler(parProp);
2348 if (!h)
2349 return;
2350
2351 double x = parProp->valueText().toDouble();
2352 double loBound = x * (1 - 0.01 * f);
2353 double upBound = x * (1 + 0.01 * f);
2354
2355 h->addConstraint(ci->property(), lo, up, loBound, upBound);
2356}
2357
2362
2367
2372
2377
2382
2387
2393
2399
2404
2409 QtBrowserItem *ci = m_browser->currentItem();
2410 QtProperty *parProp = ci->property();
2411 PropertyHandler *h = getHandler()->findHandler(parProp);
2412 if (!h)
2413 return;
2414
2415 h->removeConstraint(parProp);
2416}
2417
2422
2427
2433
2438
2440 if (getHandler()->hasPlot()) {
2442 } else {
2443 plotGuessAll();
2444 }
2445}
2446
2448
2454QtProperty *FitPropertyBrowser::addDoubleProperty(const QString &name, QtDoublePropertyManager *manager) const {
2455 if (manager == nullptr)
2456 manager = m_doubleManager;
2457 QtProperty *prop = manager->addProperty(name);
2458 manager->setDecimals(prop, m_decimals);
2459 manager->setRange(prop, -DBL_MAX, DBL_MAX);
2460 return prop;
2461}
2462
2468QtProperty *FitPropertyBrowser::addStringProperty(const QString &name) const {
2469 QtProperty *prop;
2470 QString propName = name.toLower();
2471 if (propName == "filename") {
2472 prop = m_filenameManager->addProperty(name);
2473 } else if (propName == "formula") {
2475 prop = m_formulaManager->addProperty(name);
2476 } else {
2477 prop = m_stringManager->addProperty(name);
2478 }
2479 return prop;
2480}
2481
2490 const std::vector<std::string> &allowed_values) const {
2491 QStringList qAllowedValues;
2492 QtProperty *prop = m_enumManager->addProperty(name);
2493
2494 for (const auto &values : allowed_values) {
2495 qAllowedValues << QString::fromStdString(values);
2496 }
2497 m_enumManager->setEnumNames(prop, qAllowedValues);
2498
2499 return prop;
2500}
2501
2507void FitPropertyBrowser::setStringPropertyValue(QtProperty *prop, const QString &value) const {
2508 auto *manager = dynamic_cast<QtStringPropertyManager *>(prop->propertyManager());
2509 if (manager) {
2510 manager->setValue(prop, value);
2511 }
2512}
2513
2514QString FitPropertyBrowser::getStringPropertyValue(QtProperty *prop) const {
2515 const auto *const manager = dynamic_cast<QtStringPropertyManager *>(prop->propertyManager());
2516 if (manager)
2517 return manager->value(prop);
2518 else
2519 return QString("");
2520}
2521
2523
2525
2530int FitPropertyBrowser::getAllowedIndex(int currentIndex) const {
2531 auto const workspace = std::dynamic_pointer_cast<MatrixWorkspace>(getWorkspace());
2532
2533 if (!workspace) {
2534 return 0;
2535 }
2536
2537 auto const allowedIndices =
2538 m_allowedSpectra.empty() ? QList<int>() : m_allowedSpectra[QString::fromStdString(workspaceName())];
2539 auto const firstIndex = m_allowedSpectra.empty() ? 0 : allowedIndices.front();
2540 auto const lastIndex = m_allowedSpectra.empty() ? getNumberOfSpectra(workspace) - 1 : allowedIndices.back();
2541
2542 auto allowedIndex = currentIndex;
2543 if (currentIndex < firstIndex) {
2544 allowedIndex = firstIndex;
2545 } else if (currentIndex > lastIndex) {
2546 allowedIndex = lastIndex;
2547 } else if (!m_allowedSpectra.empty() && !allowedIndices.contains(currentIndex)) {
2548 allowedIndex = m_oldWorkspaceIndex;
2549 auto i = allowedIndices.indexOf(m_oldWorkspaceIndex);
2550 if (i >= 0) {
2551 i = currentIndex > m_oldWorkspaceIndex ? i + 1 : i - 1;
2552 if (i >= 0 && i < allowedIndices.size()) {
2553 allowedIndex = allowedIndices[i];
2554 }
2555 }
2556 }
2557 return allowedIndex;
2558}
2559
2561 bool ok(false);
2562 QString fnName = QInputDialog::getText(this, tr("Mantid - Input"), tr("Please select a name for the function"),
2563 QLineEdit::Normal, "", &ok);
2564 if (ok && !fnName.isEmpty()) {
2565 saveFunction(fnName);
2566 }
2567}
2568
2569void FitPropertyBrowser::saveFunction(const QString &fnName) {
2570 QSettings settings;
2571 settings.beginGroup("Mantid/FitBrowser/SavedFunctions");
2572 QStringList names = settings.childKeys();
2573 if (names.contains(fnName) && QMessageBox::question(this, "Mantid - Question",
2574 "Function with this name already exists.\n"
2575 "Would you like to replace it?",
2576 QMessageBox::Yes) != QMessageBox::Yes) {
2577 return;
2578 }
2579 settings.setValue(fnName, QString::fromStdString(theFunction()->asString()));
2581}
2582
2584 QSettings settings;
2585 settings.beginGroup("Mantid/FitBrowser/SavedFunctions");
2586 QStringList names = settings.childKeys();
2587 if (names.isEmpty()) {
2588 QMessageBox::information(this, "Mantid - Information", "There are no saved functions");
2589 return;
2590 }
2591 QString name = QInputDialog::getItem(this, "Mantid - Input", "Please select a function to load", names, 0, false);
2592 if (!name.isEmpty()) {
2593 QString str = settings.value(name).toString();
2594
2595 loadFunction(str);
2596 }
2597}
2598
2600 QString str = QInputDialog::getText(this, "Mantid - Input", "Specify fit function string");
2601
2602 if (!str.isEmpty()) {
2603 loadFunction(str);
2604 }
2605}
2606
2607void FitPropertyBrowser::loadFunction(const QString &funcString) {
2608 // when loading a function from a string initially
2609 // do not try to do auto background even if set
2610 bool isAutoBGset = false;
2611 if (m_auto_back) {
2612 isAutoBGset = true;
2613 m_auto_back = false;
2614 }
2615
2617 clearBrowser();
2618 createCompositeFunction(funcString);
2619 emit functionLoaded(funcString);
2620
2621 if (isAutoBGset)
2622 m_auto_back = true;
2623}
2624
2626 QClipboard *clipboard = QApplication::clipboard();
2627 clipboard->setText(QString::fromStdString(theFunction()->asString()));
2628}
2629
2631 QClipboard *clipboard = QApplication::clipboard();
2632 QString str = clipboard->text();
2634}
2635
2637 QString str = QString::fromStdString(theFunction()->asString());
2638 // getHandler()->removeAllPlots();// this crashes mantidplot
2639 clearBrowser();
2641}
2642
2644 std::string wsName = workspaceName();
2645 if (!wsName.empty()) {
2646 try {
2647 auto ws = Mantid::API::AnalysisDataService::Instance().retrieve(wsName);
2648 auto mws = std::dynamic_pointer_cast<Mantid::API::MatrixWorkspace>(ws);
2649 if (mws) {
2650 function->setMatrixWorkspace(mws, workspaceIndex(), startX(), endX());
2651 } else {
2652 function->setWorkspace(ws);
2653 }
2654 } catch (...) {
2655 }
2656 }
2657}
2658
2660 if (m_autoBgName.isEmpty())
2661 return;
2662 bool hasPlot = false;
2664 if (m_autoBackground) { // remove old background
2665 if (ch == m_autoBackground) {
2666 ch = nullptr;
2667 }
2668 hasPlot = m_autoBackground->hasPlot();
2670 m_autoBackground = nullptr;
2671 }
2672 // Create the function
2673 PropertyHandler *h = getHandler()->addFunction(m_autoBgName.toStdString());
2674 if (!h)
2675 return;
2676 if (!m_autoBgAttributes.isEmpty()) { // set attributes
2677 QStringList attList = m_autoBgAttributes.split(' ');
2678 foreach (const QString &att, attList) {
2679 QStringList name_value = att.split('=');
2680 if (name_value.size() == 2) {
2681 QString name = name_value[0].trimmed();
2682 QString value = name_value[1].trimmed();
2683 if (h->function()->hasAttribute(name.toStdString())) {
2684 h->setAttribute(name, value);
2685 }
2686 }
2687 }
2688 }
2689 h->fit();
2690 m_autoBackground = h;
2692 if (hasPlot) {
2694 emit plotCurrentGuess();
2695 if (ch) {
2697 }
2698 }
2699}
2700
2706
2714 try {
2715 QStringList nameList = aName.split(' ');
2716 if (nameList.isEmpty())
2717 return;
2718 QString name = nameList[0];
2719 std::shared_ptr<Mantid::API::IFunction> f = std::shared_ptr<Mantid::API::IFunction>(
2720 Mantid::API::FunctionFactory::Instance().createFunction(name.toStdString()));
2721 m_auto_back = true;
2723 if (nameList.size() > 1) {
2724 nameList.removeFirst();
2725 m_autoBgAttributes = nameList.join(" ");
2726 }
2727 Mantid::Kernel::ConfigService::Instance().setString("curvefitting.autoBackground", aName.toStdString());
2728 } catch (...) {
2729 m_auto_back = false;
2730 }
2731}
2732
2734 auto *dlg = new SequentialFitDialog(this, m_mantidui);
2735 std::string wsName = workspaceName();
2736 if (!wsName.empty() && dlg->addWorkspaces(QStringList(QString::fromStdString(wsName)))) {
2737 dlg->show();
2738 }
2739}
2740
2741void FitPropertyBrowser::findPeaks(const std::unique_ptr<FindPeakStrategyGeneric> findPeakStrategy) {
2742 std::string wsName{workspaceName()};
2743 if (wsName.empty()) {
2744 QMessageBox::critical(this, "Mantid - Error", "Workspace name is not set");
2745 return;
2746 }
2747
2748 std::string peakListName = wsName + "_PeakList_tmp";
2749 QString setting =
2750 QString::fromStdString(Mantid::Kernel::ConfigService::Instance().getString("curvefitting.findPeaksFWHM"));
2751 int FWHM{setting.isEmpty() ? 7 : setting.toInt()};
2752
2754 findPeakStrategy->initialise(wsName, workspaceIndex(), peakListName, FWHM, &obs);
2755
2756 QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
2757
2758 Mantid::API::MatrixWorkspace_sptr inputWS = std::dynamic_pointer_cast<Mantid::API::MatrixWorkspace>(
2759 Mantid::API::AnalysisDataService::Instance().retrieve(workspaceName()));
2760
2761 try {
2762 findPeakStrategy->execute();
2763 clear();
2764 for (size_t i = 0; i < findPeakStrategy->peakNumber(); ++i) {
2765 if (findPeakStrategy->getPeakCentre(i) < startX() || findPeakStrategy->getPeakCentre(i) > endX()) {
2766 continue;
2767 }
2768 if (!createAndAddFunction(inputWS, i, findPeakStrategy)) {
2769 break;
2770 }
2771 }
2772 } catch (...) {
2773 QApplication::restoreOverrideCursor();
2774 throw;
2775 }
2776
2777 QApplication::restoreOverrideCursor();
2778}
2779
2781 m_peakToolOn = on;
2782 m_displayActionPlotGuess->setEnabled(on);
2783}
2784
2789 if (m_decimals < 0) {
2790 QSettings settings;
2791 settings.beginGroup("Mantid/FitBrowser");
2792 m_decimals = settings.value("decimals", 6).toInt();
2793 }
2794 QSet<QtProperty *> props = m_doubleManager->properties();
2795 foreach (QtProperty *prop, props) {
2796 m_doubleManager->setDecimals(prop, m_decimals);
2797 }
2798}
2799
2801 m_decimals = d;
2802 QSettings settings;
2803 settings.beginGroup("Mantid/FitBrowser");
2804 settings.setValue("decimals", d);
2806}
2807
2809
2812
2814
2815void FitPropertyBrowser::setTextPlotGuess(const QString &text) { m_displayActionPlotGuess->setText(text); }
2816
2820void FitPropertyBrowser::workspaceChange(const QString &wsName) {
2821 if (m_guessOutputName) {
2822 m_stringManager->setValue(m_output, QString::fromStdString(workspaceName()));
2823 }
2824
2825 emit workspaceNameChanged(wsName);
2826 emit wsChangePPAssign(wsName);
2827}
2828
2833
2838 auto *dlg = new MultifitSetupDialog(this);
2839 dlg->exec();
2840 QStringList ties = dlg->getParameterTies();
2841
2842 if (!ties.isEmpty()) {
2843 QString wsName = QString::fromStdString(workspaceName());
2844 Mantid::API::MatrixWorkspace_sptr mws = std::dynamic_pointer_cast<Mantid::API::MatrixWorkspace>(
2845 Mantid::API::AnalysisDataService::Instance().retrieve(workspaceName()));
2846 if (mws) {
2847 auto fun = getFunctionAtIndex(0);
2848 QString fun1Ini = QString::fromStdString(fun->asString());
2849 QString funIni = "composite=MultiBG;" + fun1Ini + ",Workspace=" + wsName + ",WSParam=(WorkspaceIndex=0);";
2850 QString tieStr;
2851 for (size_t i = 1; i < mws->getNumberHistograms(); ++i) {
2852 QString comma = i > 1 ? "," : "";
2853 QString fi = comma + "f" + QString::number(i) + ".";
2854 for (int j = 0; j < static_cast<int>(fun->nParams()); ++j) {
2855 if (!ties[j].isEmpty()) {
2856 tieStr += fi + QString::fromStdString(fun->parameterName(j)) + "=" + ties[j];
2857 }
2858 }
2859 QString wsParam = ",WSParam=(WorkspaceIndex=" + QString::number(i);
2860 wsParam += ",StartX=" + QString::number(startX()) + ",EndX=" + QString::number(endX()) + ")";
2861 funIni += fun1Ini + ",Workspace=" + wsName + wsParam + ";";
2862 }
2863 if (!tieStr.isEmpty()) {
2864 funIni += "ties=(" + tieStr + ")";
2865 }
2866 loadFunction(funIni);
2867 }
2868 }
2869}
2870
2873 if (compositeFunction()->name() != "MultiBG")
2874 return;
2875
2876 // if all member functions are of the same type and composition
2877 // create a TableWorkspace with parameter series
2878
2879 // check if member functions are the same
2880 QStringList parNames;
2881 auto fun0 = getFunctionAtIndex(0);
2882 if (!fun0) {
2883 throw std::runtime_error("IFunction expected but func function of another type");
2884 }
2885 for (size_t i = 0; i < fun0->nParams(); ++i) {
2886 parNames << QString::fromStdString(fun0->parameterName(i));
2887 }
2888
2889 for (size_t i = 1; i < compositeFunction()->nFunctions(); ++i) {
2890 auto fun = getFunctionAtIndex(i);
2891 if (!fun) {
2892 throw std::runtime_error("IFunction expected but func function of another type");
2893 }
2894 for (size_t j = 0; j < fun->nParams(); ++j) {
2895 if (parNames.indexOf(QString::fromStdString(fun->parameterName(j))) < 0) {
2896 // Functions are different, stop
2897 return;
2898 }
2899 }
2900 }
2901
2902 QApplication::setOverrideCursor(Qt::WaitCursor);
2903 // create a TableWorkspace: first column - function index
2904 // other colomns - the parameters
2905 Mantid::API::ITableWorkspace_sptr table = Mantid::API::WorkspaceFactory::Instance().createTable("TableWorkspace");
2906 table->addColumn("int", "Index");
2907 foreach (const QString &par, parNames) {
2908 table->addColumn("double", par.toStdString());
2909 }
2910 // Create WorkspaceGroup with the fit results
2911 std::vector<std::string> worspaceNames(compositeFunction()->nFunctions());
2912 for (size_t i = 0; i < compositeFunction()->nFunctions(); ++i) {
2913 // Mantid::API::TableRow row = table->appendRow();
2914 // row << int(i);
2915 // Mantid::API::IFunctionMW* fun =
2916 // dynamic_cast<Mantid::API::IFunctionMW*>(compositeFunction()->getFunction(i));
2917 // for(size_t j = 0; j < fun->nParams(); ++j)
2918 //{
2919 // row << fun->getParameter(j);
2920 //}
2921 // size_t wi = fun->getWorkspaceIndex();
2922 // Mantid::API::MatrixWorkspace_sptr mws =
2923 // fun->createCalculatedWorkspace(fun->getMatrixWorkspace(),wi);
2924 // worspaceNames[i] =
2925 // workspaceNames()+"_"+QString::number(wi).toStdString()+"_Workspace";
2926 // Mantid::API::AnalysisDataService::Instance().addOrReplace(worspaceNames[i],mws);
2927 }
2928
2929 // Save the table
2930 Mantid::API::AnalysisDataService::Instance().addOrReplace(workspaceName() + "_Param_series", table);
2931 try {
2932 Mantid::API::IAlgorithm_sptr group = Mantid::API::AlgorithmManager::Instance().create("GroupWorkspaces");
2933 group->setProperty("InputWorkspaces", worspaceNames);
2934 group->setPropertyValue("OutputWorkspace", workspaceName() + "_Workspace");
2935 group->execute();
2936 } catch (...) {
2937 }
2938 QApplication::restoreOverrideCursor();
2939}
2940
2947 // remove old properties
2948 if (m_browser->isItemVisible(m_settingsGroup)) {
2949 if (m_settingsGroup->property()->subProperties().contains(m_workspaceIndex)) {
2950 m_settingsGroup->property()->removeSubProperty(m_workspaceIndex);
2951 } else if (m_settingsGroup->property()->subProperties().contains(m_xColumn)) {
2952 m_settingsGroup->property()->removeSubProperty(m_xColumn);
2953 m_settingsGroup->property()->removeSubProperty(m_yColumn);
2954 m_settingsGroup->property()->removeSubProperty(m_errColumn);
2955 }
2956 }
2957
2959 try {
2960 ws = Mantid::API::AnalysisDataService::Instance().retrieve(workspaceName());
2961 } catch (...) {
2962 return;
2963 }
2964 if (!ws)
2965 return;
2966
2967 // If this is a MuonFitPropertyBrowser, "evaluation type" goes in the Custom
2968 // Settings group.
2969 // If not, there is no Custom Settings group and it goes in the regular
2970 // Settings group.
2971 const auto *const settings = m_customSettingsGroup ? m_customSettingsGroup : m_settingsGroup;
2972
2973 if (settings->property()->subProperties().contains(m_evaluationType)) {
2974 settings->property()->removeSubProperty(m_evaluationType);
2975 m_evaluationType->setEnabled(false);
2976 // if it is a MatrixWorkspace insert WorkspaceIndex
2977 auto mws = std::dynamic_pointer_cast<Mantid::API::MatrixWorkspace>(ws);
2978 if (mws) {
2980 auto isHistogram = mws->isHistogramData();
2981 m_evaluationType->setEnabled(isHistogram);
2982 if (isHistogram) {
2983 settings->property()->addSubProperty(m_evaluationType);
2984 }
2985 return;
2986 }
2987 }
2988
2989 // if it is a TableWorkspace insert the column properties
2990 auto tws = std::dynamic_pointer_cast<Mantid::API::ITableWorkspace>(ws);
2991 if (tws) {
2993 // insert properties
2994 m_settingsGroup->property()->insertSubProperty(m_xColumn, m_workspace);
2995 m_settingsGroup->property()->insertSubProperty(m_yColumn, m_xColumn);
2996 m_settingsGroup->property()->insertSubProperty(m_errColumn, m_yColumn);
2998 return;
2999 QString xName;
3000 QString yName;
3001 QString errName;
3002 auto names = tws->getColumnNames();
3003 QStringList columns;
3004 for (const auto &name : names) {
3005 columns << QString::fromStdString(name);
3006 auto col = tws->getColumn(name);
3007 if (xName.isEmpty() && col->getPlotType() == 1 /*X*/) {
3008 xName = QString::fromStdString(name);
3009 }
3010 if (yName.isEmpty() && col->getPlotType() == 2 /*Y*/) {
3011 yName = QString::fromStdString(name);
3012 }
3013 if (errName.isEmpty() && col->getPlotType() == 5 /*yErr*/) {
3014 errName = QString::fromStdString(name);
3015 }
3016 }
3017 m_columnManager->setEnumNames(m_xColumn, columns);
3018 m_columnManager->setEnumNames(m_yColumn, columns);
3019 // set the column values
3020 if (!xName.isEmpty()) {
3021 m_columnManager->setValue(m_xColumn, static_cast<int>(columns.indexOf(xName)));
3022 } else {
3023 if (auto name = std::find_if(std::cbegin(columns), std::cend(columns), [&](const auto x) { return x != yName; });
3024 name != std::cend(columns)) {
3025 m_columnManager->setValue(m_xColumn, static_cast<int>(columns.indexOf(*name)));
3026 }
3027 }
3028 if (!yName.isEmpty()) {
3029 m_columnManager->setValue(m_yColumn, static_cast<int>(columns.indexOf(yName)));
3030 } else {
3031 if (auto name = std::find_if(std::cbegin(columns), std::cend(columns), [&](const auto x) { return x != xName; });
3032 name != std::cend(columns)) {
3033 m_columnManager->setValue(m_yColumn, static_cast<int>(columns.indexOf(*name)));
3034 }
3035 }
3036 columns.prepend("");
3037 m_columnManager->setEnumNames(m_errColumn, columns);
3038 if (!errName.isEmpty()) {
3039 m_columnManager->setValue(m_errColumn, static_cast<int>(columns.indexOf(errName)));
3040 } else {
3041 m_columnManager->setValue(m_errColumn, 0);
3042 }
3043 return;
3044 }
3045}
3046
3048 if (m_browser->isItemVisible(m_settingsGroup)) {
3049 if (!m_settingsGroup->property()->subProperties().contains(m_workspaceIndex)) {
3050 m_settingsGroup->property()->insertSubProperty(m_workspaceIndex, m_workspace);
3051 }
3052 }
3053}
3054
3059
3064 if (m_browser->isItemVisible(m_settingsGroup)) {
3065 m_browser->setItemVisible(m_settingsGroup, false);
3066 } else {
3067 m_browser->setItemVisible(m_settingsGroup, true);
3068 }
3069}
3070
3075void FitPropertyBrowser::removePropertiesFromSettingsBrowser(const QStringList &propsToRemove) {
3076 // get settings properties
3077 QList<QtProperty *> props = m_settingsGroup->property()->subProperties();
3078 for (auto &prop : props) {
3079 if (propsToRemove.contains(prop->propertyName())) {
3080 m_settingsGroup->property()->removeSubProperty(prop);
3081 }
3082 }
3083}
3084
3086
3093 if (prop == m_xColumn) { // update startX and endX
3094 try {
3095 auto ws = Mantid::API::AnalysisDataService::Instance().retrieve(workspaceName());
3096 auto tws = std::dynamic_pointer_cast<Mantid::API::ITableWorkspace>(ws);
3097 if (!tws)
3098 return;
3099 int i = m_columnManager->value(m_xColumn);
3100 if (i < 0 || i >= static_cast<int>(tws->rowCount()) || tws->rowCount() == 0)
3101 return;
3102 auto col = tws->getColumn(static_cast<size_t>(i));
3103 const double startXVal = col->toDouble(0);
3104 const double endXVal = col->toDouble(tws->rowCount() - 1);
3105 m_doubleManager->setValue(m_startX, startXVal);
3106 m_doubleManager->setValue(m_endX, endXVal);
3107 } catch (...) {
3108 // do nothing
3109 }
3110 }
3111}
3112
3117 // delete old minimizer properties
3118 foreach (QtProperty *prop, m_minimizerProperties) {
3119 m_settingsGroup->property()->removeSubProperty(prop);
3120 }
3121
3122 // add new minimizer properties
3123 auto minzer = Mantid::API::FuncMinimizerFactory::Instance().createMinimizer(this->minimizer());
3124 const auto &properties = minzer->getProperties();
3125 for (auto property : properties) {
3126 QString propName = QString::fromStdString((*property).name());
3127 QtProperty *prop = nullptr;
3128 if (const auto prp = dynamic_cast<const Mantid::Kernel::PropertyWithValue<bool> *const>(property)) {
3129 prop = m_boolManager->addProperty(propName);
3130 bool val = *prp;
3131 m_boolManager->setValue(prop, val);
3132 } else if (const auto prp = dynamic_cast<const Mantid::Kernel::PropertyWithValue<double> *const>(property)) {
3133 prop = this->addDoubleProperty(propName);
3134 double val = *prp;
3135 m_doubleManager->setValue(prop, val);
3136 } else if (const auto prp = dynamic_cast<const Mantid::Kernel::PropertyWithValue<int> *const>(property)) {
3137 prop = m_intManager->addProperty(propName);
3138 int val = *prp;
3139 m_intManager->setValue(prop, val);
3140 } else if (const auto prp = dynamic_cast<const Mantid::Kernel::PropertyWithValue<size_t> *const>(property)) {
3141 prop = m_intManager->addProperty(propName);
3142 size_t val = *prp;
3143 m_intManager->setValue(prop, static_cast<int>(val));
3144 } else if (const auto prp = dynamic_cast<const Mantid::Kernel::PropertyWithValue<std::string> *const>(property)) {
3145 prop = m_stringManager->addProperty(propName);
3146 QString val = QString::fromStdString(prp->value());
3147 m_stringManager->setValue(prop, val);
3148 } else if (dynamic_cast<Mantid::API::IWorkspaceProperty *>(property)) {
3149 prop = m_stringManager->addProperty(propName);
3150 m_stringManager->setValue(prop, QString::fromStdString((*property).value()));
3151 } else {
3152 QMessageBox::warning(this, "Mantid - Error",
3153 "Type of minimizer's property " + propName + " is not yet supported by the browser.");
3154 continue;
3155 }
3156
3157 if (!prop)
3158 continue;
3159 // set the tooltip from property doc string
3160 QString toolTip = QString::fromStdString((*property).documentation());
3161 if (!toolTip.isEmpty()) {
3162 prop->setToolTip(toolTip);
3163 }
3164 m_settingsGroup->property()->addSubProperty(prop);
3165 m_minimizerProperties.append(prop);
3166 }
3167}
3168
3173 auto fun = theFunction();
3174 size_t np = fun->nParams();
3175 QList<double> out;
3176 for (size_t i = 0; i < np; ++i) {
3177 const double parValue = fun->getParameter(i);
3178 out.append(parValue);
3179 }
3180 return out;
3181}
3182
3187 auto fun = theFunction();
3188 size_t np = fun->nParams();
3189 QStringList out;
3190 for (size_t i = 0; i < np; ++i) {
3191 std::string parName = fun->parameterName(i);
3192 out.append(QString::fromStdString(parName));
3193 }
3194 return out;
3195}
3200
3205
3210 const PropertyHandler *const handler = currentHandler();
3211 if (handler) {
3213 }
3214}
3215
3220 MantidQt::API::HelpWindow::showPage(QStringLiteral("workbench/plotwindow.html"));
3221}
3222
3229 if (m_fitActionSeqFit) {
3230 if (allow) {
3231 m_fitActionSeqFit->setEnabled(m_compositeFunction->nFunctions() > 0);
3232 } else {
3233 m_fitActionSeqFit->setEnabled(false);
3234 }
3235 }
3236}
3237
3238void FitPropertyBrowser::modifyFitMenu(QAction *fitAction, bool enabled) {
3239 if (enabled) {
3240 m_fitMenu->addAction(fitAction);
3241 } else {
3242 m_fitMenu->removeAction(fitAction);
3243 }
3244}
3245
3247 return static_cast<int>(m_functionsGroup->children().size());
3248}
3249
3250void FitPropertyBrowser::addAllowedSpectra(const QString &wsName, const QList<int> &wsSpectra) {
3251 auto const name = wsName.toStdString();
3252 auto ws = AnalysisDataService::Instance().retrieveWS<MatrixWorkspace>(name);
3253 if (ws) {
3254 QList<int> indices;
3255 indices.reserve(wsSpectra.size());
3256 std::transform(wsSpectra.cbegin(), wsSpectra.cend(), std::back_inserter(indices),
3257 [&ws](const auto i) { return static_cast<int>(ws->getIndexFromSpectrumNumber(i)); });
3258
3259 auto wsFound = m_allowedSpectra.find(wsName);
3260 m_allowedSpectra.insert(wsName, indices);
3261 if (wsFound != m_allowedSpectra.end()) {
3262 // we already knew about this workspace
3263 // update workspace index list
3265 } else {
3266 // new workspace, update workspace names
3268 }
3269 } else {
3270 throw std::runtime_error("Workspace " + name + " is not a MatrixWorkspace");
3271 }
3272}
3273
3274void FitPropertyBrowser::removeWorkspaceAndSpectra(const std::string &wsName) {
3275 removeWorkspace(wsName);
3276 // remove spectra
3277 QString qWsName = QString::fromStdString(wsName);
3278 m_allowedSpectra.erase(m_allowedSpectra.find(qWsName));
3279}
3280
3282 auto const name = wsName.toStdString();
3283 auto ws = AnalysisDataService::Instance().retrieveWS<ITableWorkspace>(name);
3284 if (ws) {
3285 m_allowedTableWorkspace = wsName;
3286 } else {
3287 throw std::runtime_error("Workspace " + name + " is not a TableWorkspace");
3288 }
3289}
3290
3299QString FitPropertyBrowser::addFunction(const QString &fnName) {
3300 return addFunction(fnName.toStdString())->functionPrefix();
3301}
3302
3304 const std::unique_ptr<FindPeakStrategyGeneric> &findPeakStrategy) {
3305 bool validFn = false;
3306 auto f = std::dynamic_pointer_cast<Mantid::API::IPeakFunction>(
3307 Mantid::API::FunctionFactory::Instance().createFunction(defaultPeakType()));
3308 if (f) {
3309 validFn = true;
3310 f->setMatrixWorkspace(inputWS, workspaceIndex(), startX(), endX());
3311 f->setCentre(findPeakStrategy->getPeakCentre(peakIndex));
3312 f->setFwhm(findPeakStrategy->getPeakWidth(peakIndex));
3313 f->setHeight(findPeakStrategy->getPeakHeight(peakIndex));
3314 addFunction(f->asString());
3315 }
3316 return validFn;
3317}
3318
3320 if (prefix.isEmpty())
3321 throw std::runtime_error("Peak function prefix cannot be empty");
3322 auto const indexList = prefix.split(".");
3323 auto const n = indexList.size() - 1;
3324 auto const *handler = getHandler();
3325 for (int i = 0; i < n; ++i) {
3326 auto const index = indexList[i].mid(1).toInt();
3327 handler = handler->getHandler(index);
3328 }
3329 return handler->getHandler(indexList[n].mid(1).toInt());
3330}
3331
3332void FitPropertyBrowser::setPeakCentreOf(const QString &prefix, double value) {
3333 auto handler = getPeakHandler(prefix);
3334 handler->setCentre(value);
3335 handler->updateParameters();
3336}
3337
3338double FitPropertyBrowser::getPeakCentreOf(const QString &prefix) {
3339 const auto *handler = getPeakHandler(prefix);
3340 return handler->centre();
3341}
3342
3343void FitPropertyBrowser::setPeakHeightOf(const QString &prefix, double value) {
3344 auto handler = getPeakHandler(prefix);
3345 handler->setHeight(value);
3346 handler->updateParameters();
3347}
3348
3349double FitPropertyBrowser::getPeakHeightOf(const QString &prefix) {
3350 const auto *handler = getPeakHandler(prefix);
3351 return handler->height();
3352}
3353
3354void FitPropertyBrowser::setPeakFwhmOf(const QString &prefix, double value) {
3355 auto handler = getPeakHandler(prefix);
3356 handler->setFwhm(value);
3357 handler->updateParameters();
3358}
3359
3360double FitPropertyBrowser::getPeakFwhmOf(const QString &prefix) {
3361 const auto *handler = getPeakHandler(prefix);
3362 return handler->fwhm();
3363}
3364
3365std::string FitPropertyBrowser::getWidthParameterNameOf(const QString &prefix) {
3366 const auto *handler = getPeakHandler(prefix);
3367 return handler->getWidthParameterName();
3368}
3369
3370std::string FitPropertyBrowser::getCentreParameterNameOf(const QString &prefix) {
3371 const auto *handler = getPeakHandler(prefix);
3372 return handler->getCentreParameterName();
3373}
3374
3375bool FitPropertyBrowser::isParameterExplicitlySetOf(const QString &prefix, const std::string &param) {
3376 const auto *handler = getPeakHandler(prefix);
3377 return handler->isParameterExplicitlySet(param);
3378}
3379
3381 QStringList peaks;
3382 const auto *parentHandler = getHandler();
3383 const auto nFunctions = parentHandler->cfun()->nFunctions();
3384 for (size_t i = 0; i < nFunctions; ++i) {
3385 const auto *handler = parentHandler->getHandler(i);
3386 if (handler->pfun()) {
3387 peaks << handler->functionPrefix();
3388 }
3389 }
3390 return peaks;
3391}
3392
3393} // namespace MantidWidgets
3394} // namespace MantidQt
std::string name
Definition Run.cpp:60
CostFunctions::CostFuncFitting & m_costFunction
The cost function.
double value
The value of the point.
Definition FitMW.cpp:51
IPeaksWorkspace_sptr workspace
std::map< DeltaEMode::Type, std::string > index
static void showPage(const std::string &url=std::string())
static void showFitFunction(const std::string &name=std::string())
void observeAdd(bool on=true)
Observe additions.
void observePostDelete(bool on=true)
Observe workspace deletes.
void observeRename(bool on=true)
Observe renaming.
The factory for the FilenameDialogEditor.
Class FitPropertyBrowser implements QtPropertyBrowser to display and control fitting function paramet...
int m_decimals
Number of decimal places in double properties.
QString getXColumnName() const
Get the name of the X column.
void hideEvent(QHideEvent *e) override
actions to do before the browser is hidden
QtBrowserItem * findItem(QtBrowserItem *parent, QtProperty *prop) const
Find QtBrowserItem for a property prop among the chidren of.
void updateParameters()
Update the function parameters.
void checkFunction()
Check that the properties match the function.
void updateAttributes()
Update the function attributes.
void setAutoBackgroundName(const QString &aName)
Remember a background function name to be used for creating auto-background.
bool rawData() const override
Returns true if the fit should be done against binned (bunched) data.
void setDefaultPeakType(const std::string &fnType)
Set the default peak type.
QString getYColumnName() const
Get the name of the Y column.
void setOutputName(const std::string &)
Set the output name.
void processMultiBGResults()
Process and create some output if it is a MultiBG fit.
bool m_shouldBeNormalised
Should the data be normalised before fitting?
virtual bool isWorkspaceValid(Mantid::API::Workspace_sptr) const
Check if the workspace can be used in the fit.
bool isHistogramFit() const
Get "HistogramFit" option.
virtual void removePropertiesFromSettingsBrowser(const QStringList &propsToRemove)
Function to toggle the visibility of a settings group property exposed to python.
QString getOldExpressionAsString(const QString &parameterName) const
Get the tie expression stored in the function in case the new expression is invalid and the GUI needs...
bool plotCompositeMembers() const
Returns true if a composite's member functions should be plotted also.
void updateDecimals()
impose a number of decimal places on all defined Double properties
void setPeakFwhmOf(const QString &prefix, double value)
QtProperty * addStringListProperty(const QString &name, const std::vector< std::string > &allowed_values) const
Create a string list property.
void initLayout(QWidget *w)
Initialise the layout.
void showEvent(QShowEvent *e) override
actions to do before the browser made visible
void setXRange(double start, double end)
Set both start and end X.
void fittingDone(const QString &)
signal which can optionally be caught for customization after a fit has been done
std::shared_ptr< Mantid::API::CompositeFunction > compositeFunction() const
Get Composite Function.
void addBothBounds10()
Slot.Sets the lower and upper bounds of the selected parameter to 10% of its value.
virtual void populateFunctionNames()
Get the registered function names.
void browserHelp()
Open a web page with description of FitPropertyBrowser.
bool m_hideWsListWidget
bool to display ws list or not
void addBothBounds50()
Slot.Sets the lower and upper bounds of the selected parameter to 50% of its value.
virtual void boolChanged(QtProperty *prop)
Called when a bool property is changed.
int getPeakRadius() const
Get the peak radius for peak functions.
void setTextPlotGuess(const QString &text)
alter text of Plot Guess
virtual void enumChanged(QtProperty *prop)
Called when the function name property changed.
void setWorkspace(const Mantid::API::IFunction_sptr &function) const
Sets the workspace to a function.
std::string workspaceName() const
Get the input workspace name.
void sendParameterChanged(const Mantid::API::IFunction *f)
void setWorkspaceProperties()
Display properties relevant to the selected workspace.
QStringList m_registeredBackgrounds
A list of registered backgrounds.
const std::string & defaultBackgroundType() const
Get the default background type.
QVector< double > getXRange()
Get the X limits of the workspace.
void setStartX(double start) override
Set the start X.
void currentItemChanged(const QtBrowserItem *)
Slot.
void addAutoBackground()
Creates and adds the autobackground.
QStringList m_registeredOther
A list of registered functions that are neither peaks nor backgrounds.
bool isUndoEnabled() const
Tells if undo can be done.
FitPropertyBrowser(QWidget *parent=nullptr, QObject *mantidui=nullptr)
Constructor.
void createEditors(QWidget *w)
Create editors and assign them to the managers.
QtProperty * getTieProperty(QtProperty *parProp) const
Returns the tie property for a parameter property, or NULL.
void removeBounds()
Slot.Removes lower and upper bounds from the selected parameter property.
void addUpperBound()
Slot.Adds upper bound to the selected parameter property.
Mantid::API::IFunction_sptr getFittingFunction() const
Return the fitting function.
std::vector< double > m_initialParameters
To keep a copy of the initial parameters in case for undo fit.
void handleFactoryUpdate(Mantid::API::FunctionFactoryUpdateNotification_ptr)
Callback for FunctionFactory update notifications.
void doFit(int maxIterations)
Do the fitting.
virtual void intChanged(QtProperty *prop)
Called when an int property changed.
bool isPeak() const
Is the current function a peak?
bool isFitEnabled() const
Returns true if the function is ready for a fit.
int maxIterations() const
Get the max number of iterations.
QtGroupPropertyManager * m_groupManager
Property managers:
void paste()
Paste a function string from the clipboard.
int m_oldWorkspaceIndex
Store workspace index to revert to in case validation fails.
QStringList m_registeredPeaks
A list of registered peaks.
QString m_allowedTableWorkspace
If set it contains the table workspace name to be fitted in this browser:
bool m_auto_back
If true background function will be included automatically.
virtual void doubleChanged(QtProperty *prop)
Called when a double property changed.
int getAllowedIndex(int currentIndex) const
Return the nearest allowed workspace index.
PropertyHandler * currentHandler() const
Get the current function.
void addUpperBound10()
Slot.Adds upper bound to the selected parameter property.
QList< double > getParameterValues() const
Get function parameter values.
void setStringPropertyValue(QtProperty *prop, const QString &value) const
Set a value to a string property.
std::string m_defaultFunction
Default function name.
bool ignoreInvalidData() const
Get the ignore invalid data option.
void modifyFitMenu(QAction *fitAction, bool enabled)
void addFitResultWorkspacesToTableWidget()
Adds the fit result workspaces to the QListWidget in the browser.
virtual void removeFunction(PropertyHandler *handler)
Removes the function held by the property handler.
virtual void setWorkspaceName(const QString &wsName) override
Set the input workspace name.
void workspaceClicked(const QString &wsName)
void setWorkspaceIndex(int i) override
Set workspace index.
void removeWorkspaceAndSpectra(const std::string &wsName)
void updateBrowserFromFitResults(const Mantid::API::IFunction_sptr &finalFunction)
Set the parameters to the fit outcome.
std::string defaultPeakType()
Get the default peak type.
void allowSequentialFits(bool allow) override
Allow or disallow sequential fits (depending on whether other conditions are met)
void functionHelp()
Open a web page with description of the current function.
void setupMultifit()
Call MultifitSetupDialog to populate MultiBG function.
void updateStructureTooltips()
Update structure tooltips for all functions.
virtual void setFitEnabled(bool enable)
Enable/disable the Fit buttons;.
std::string getWidthParameterNameOf(const QString &prefix)
const QStringList & getWorkspaceNames()
Returns the list of workspaces that are currently been worked on by the fit property browser.
const std::string & defaultFunctionType() const
Get the default function type.
void enactAttributeChange(QtProperty *prop, PropertyHandler *h, const bool vectorAttribute=false)
void copy()
Copy the function string to the clipboard.
void finishHandle(const Mantid::API::IAlgorithm *alg) override
Called when the Fit is finished.
void addAllowedSpectra(const QString &wsName, const QList< int > &wsIndices)
void addBothBounds()
Slot.Adds lower and upper bounds to the selected parameter property.
void initBasicLayout(QWidget *w)
Initialise the layout, except for the fit button in the menu bar.
QtBrowserItem * m_settingsGroup
Group for input/output settings.
QObject * m_mantidui
holds effectively a MantidUI for connecting
void postDeleteHandle(const std::string &wsName) override
workspace was removed
void removeWorkspace(const std::string &wsName)
void addHandle(const std::string &wsName, const std::shared_ptr< Mantid::API::Workspace > &ws) override
workspace was added
QStringList m_workspaceNames
A list of available workspaces.
QPushButton * createFitMenuButton(QWidget *w)
Initialise the layout for the fit button.
void disableUndo()
disable undo when the function changes
std::string minimizer(bool withProperties=false) const
Get the minimizer.
void removePlotSignal(MantidQt::MantidWidgets::PropertyHandler *)
Mantid::API::IFunction_sptr tryCreateFitFunction(const QString &str)
Catches unexpected not found exceptions.
void stringChanged(QtProperty *prop)
Called when a string property changed.
double height() const
Height of the current peak.
bool m_peakToolOn
Shows if the PeakPickerTool is on.
void setCentre(double value)
Set centre of the current peak.
double fwhm() const
Width of the current peak.
Poco::NObserver< FitPropertyBrowser, Mantid::API::FunctionFactoryUpdateNotification > m_updateObserver
Observes algorithm factory update notifications.
bool createAndAddFunction(const Mantid::API::MatrixWorkspace_sptr inputWS, const size_t peakIndex, const std::unique_ptr< FindPeakStrategyGeneric > &findPeakStrategy)
bool m_changeSlotsEnabled
If false the change-slots (such as enumChanged(), doubleChanged()) are disabled.
virtual void toggleSettingsBrowserVisible()
Function to toggle the visibility of the settings browser.
void renameHandle(const std::string &oldName, const std::string &newName) override
Handler of the Rename notifications.
void parameterChanged(const Mantid::API::IFunction *)
bool convolveMembers() const
Get the "ConvolveMembers" option.
virtual void populateFitMenuButton(QSignalMapper *fitMapper, QMenu *fitMenu)
Populate the fit button.
void findPeaks(const std::unique_ptr< FindPeakStrategyGeneric > findPeakStrategy)
void setHeight(double value)
Set height of the current peak.
QtBrowserItem * m_functionsGroup
Group for functions.
std::string m_defaultBackground
Default background name.
std::string getFunctionString() const
Get the function as a string.
PropertyHandler * getHandler() const
Get handler to the root composite function.
void addConstraint(int f, bool lo, bool up)
Slot.
virtual void addWorkspaceIndexToBrowser()
Adds the workspace index property to the browser.
QSignalMapper * m_fitMapper
Make sure m_groupMember belongs to the group.
void fitResultsChanged(const QString &status)
QString m_autoBgName
Name of the autobackground function.
virtual std::string outputName() const
Get the output name.
QString getStringPropertyValue(QtProperty *prop) const
QStringList m_evaluationTypes
A list of possible function evaluation types.
bool plotDiff() const
Returns true if the difference plot should be drawn.
std::string m_storedWorkspaceName
store current workspace name
std::shared_ptr< Mantid::API::Workspace > getWorkspace() const
Get the workspace.
void columnChanged(QtProperty *prop)
================================================================================================= Slo...
virtual void workspaceChange(const QString &wsName)
Sets the new workspace to the current one.
QMap< QString, QList< int > > m_allowedSpectra
If non-empty it contains references to the spectra allowed to be fitted in this browser: keys are wor...
QStringList getParameterNames() const
Get function parameter names.
void setDefaultBackgroundType(const std::string &fnType)
Set the default background type.
void clearFitResultStatus()
Clear the Fit status display.
bool m_guessOutputName
if true the output name will be guessed every time workspace name is changeed
void hasConstraints(QtProperty *parProp, bool &hasTie, bool &hasFix, bool &hasBounds) const
Does a parameter have a tie.
QStringList m_minimizers
A list of available minimizers.
PropertyHandler * getPeakHandler(const QString &prefix)
void setPeakCentreOf(const QString &prefix, double value)
void reset()
reset the function part, renew function, all handlers are new
QtProperty * addStringProperty(const QString &name) const
Create a string property and set some settings.
std::string getExcludeRange() const
Get the excluded range for the fit.
void setFwhm(double value)
Set width of the current peak.
QString m_autoBgAttributes
List of attributes of the autobackground function as name=value pairs separated by spaces.
QStringList m_registeredFunctions
A list of registered functions.
void setTip(const QString &txt)
Display a tip.
void populateWorkspaceNames()
Get and store available workspace names.
const std::string & getFitAlgorithmOutputStatus() const
================================================================================================= Get...
double centre() const
Centre of the current peak.
void showFitResultStatus(const QString &status)
Display the status string returned from Fit.
QtProperty * addDoubleProperty(const QString &name, QtDoublePropertyManager *manager=nullptr) const
Create a double property and set some settings.
void updateSetupMenus()
Update setup menus according to how these are set in settings.
std::shared_ptr< const Mantid::API::IFunction > theFunction() const
Get the current function.
void setCurrentFunction(PropertyHandler *h) const
Set new current function.
PropertyHandler * m_autoBackground
The autobackground handler.
std::shared_ptr< Mantid::API::CompositeFunction > m_compositeFunction
A copy of the edited function.
Mantid::API::IFunction_sptr getFunctionAtIndex(std::size_t const &index) const
Return a function at a specific index in the composite function.
std::string getCentreParameterNameOf(const QString &prefix)
void setPeakHeightOf(const QString &prefix, double value)
void setDefaultFunctionType(const std::string &fnType)
Set the default function type.
bool isParameterExplicitlySetOf(const QString &prefix, const std::string &param)
void filenameChanged(QtProperty *prop)
Called when a filename property changed.
void setEndX(double end) override
Set the end X.
void createCompositeFunction(const QString &str="")
Create CompositeFunction from string.
void setIgnoreInvalidData(bool on)
Set the ignore invalid data option.
const std::string & getFitAlgorithmParameters() const
================================================================================================= Get...
QStringList m_costFunctions
A list of available cost functions.
QtBrowserItem * m_customSettingsGroup
Group for custom options available on muon analysis widget.
void minimizerChanged()
Called when the minimizer changes. Creates minimizes's properties.
QString getErrColumnName() const
Get the name of the Error column.
std::string costFunction() const
Get the cost function.
void addUpperBound50()
Slot.Adds upper bound to the selected parameter property.
void itemDoubleClicked(QListWidgetItem *item)
This is a dialog for doing setting up the MultiBG function.
Helps display and edit functions in FitPropertyBrowser.
std::shared_ptr< Mantid::API::IPeakFunction > pfun() const
bool setParameter(QtProperty *prop)
Set function parameter value read from a QtProperty.
void removeTie(QtProperty *prop, const std::string &globalName)
Remove the tie.
bool setAttribute(QtProperty *prop, bool resetProperties=true)
Set function attribute value read from a QtProperty.
void addConstraint(QtProperty *parProp, bool lo, bool up, double loBound, double upBound)
Add constraint to parameter property parProp.
PropertyHandler * addFunction(const std::string &fnName)
Add a function to the function handled by this handler.
const QMap< QString, QtProperty * > & getTies()
void updateErrors()
Set all parameter error values in the manager.
PropertyHandler * findHandler(const Mantid::API::IFunction *fun)
void setCentre(const double &c)
Set the centre of the handled peak function.
void setVectorAttribute(QtProperty *prop)
Set function vector attribute value.
void calcBaseAll()
If the handled function is composite calculate the peak baselines for all members.
void setHeight(const double &h)
Set the height of the handled peak function.
void removeAllPlots()
Remove all plots including children's.
std::shared_ptr< Mantid::API::IFunction > ifun() const
std::shared_ptr< const Mantid::API::CompositeFunction > findCompositeFunction(QtBrowserItem *item) const
Returns 'this' if item == m_item and this is a composite function or calls findCompositeFunction recu...
std::shared_ptr< const Mantid::API::IFunction > findFunction(QtBrowserItem *item) const
Returns 'this' if item == m_item or calls findFunction recursively with all its children or zero.
std::shared_ptr< Mantid::API::IFunction > changeType(QtProperty *prop)
Change the type of the function (replace the function)
QString updateStructureTooltip()
Update high-level structure tooltip and return it.
void clearErrors()
Clear all parameter error values in the manager.
void updateParameters()
Sync all parameter values with the manager.
QtProperty * getParameterProperty(const QString &parName) const
void updateAttributes()
Sync all parameter values with the manager.
Select a function type out of a list of available ones.
QString getFunction() const
Return selected function.
void observeFinish(const IAlgorithm_const_sptr &alg)
Connect to algorithm alg and observe its finish notification.
A composite function is a function containing other functions.
IFunction_sptr function() const
Return the handled function.
Definition IFunction.h:766
IAlgorithm is the interface implemented by the Algorithm base class.
Definition IAlgorithm.h:45
An interface to a background function.
This is an interface to a fitting function - a semi-abstarct class.
Definition IFunction.h:166
virtual std::string parameterName(size_t i) const =0
Returns the name of parameter i.
An interface to a peak function, which extend the interface of IFunctionWithLocation by adding method...
ITableWorkspace is an implementation of Workspace in which the data are organised in columns of same ...
An interface that is implemented by WorkspaceProperty.
Base MatrixWorkspace Abstract Class.
A reference to a parameter in a function.
std::size_t getLocalIndex() const
Return parameter index in the local function.
IFunction * getLocalFunction() const
Return pointer to the local function.
Exception for when an item is not found in a collection.
Definition Exception.h:145
virtual bool existsProperty(const std::string &name) const =0
Checks whether the named property is already in the list of managed property.
virtual TypedValue getProperty(const std::string &name) const =0
Get the value of a property.
virtual std::string getPropertyValue(const std::string &name) const =0
Get the value of a property as a string.
The Logger class is in charge of the publishing messages from the framework through various channels.
Definition Logger.h:51
void warning(const std::string &msg)
Logs at warning level.
Definition Logger.cpp:117
The concrete, templated class for properties.
static T & Instance()
Return a reference to the Singleton instance, creating it if it does not already exist Creation is do...
The AlgorithmProgressDialogPresenter keeps track of the running algorithms and displays a progress ba...
std::shared_ptr< IAlgorithm > IAlgorithm_sptr
shared pointer to Mantid::API::IAlgorithm
const Poco::AutoPtr< FunctionFactoryUpdateNotification > & FunctionFactoryUpdateNotification_ptr
Convenient typedef for an UpdateNotification AutoPtr.
std::shared_ptr< ITableWorkspace > ITableWorkspace_sptr
shared pointer to Mantid::API::ITableWorkspace
std::shared_ptr< Workspace > Workspace_sptr
shared pointer to Mantid::API::Workspace
Kernel::Logger g_log("ExperimentInfo")
static logger object
std::shared_ptr< IFunction > IFunction_sptr
shared pointer to the function base class
Definition IFunction.h:743
Mantid::Kernel::SingletonHolder< FunctionFactoryImpl > FunctionFactory
std::shared_ptr< const IFunction > IFunction_const_sptr
shared pointer to the function base class (const version)
Definition IFunction.h:745
std::shared_ptr< MatrixWorkspace > MatrixWorkspace_sptr
shared pointer to the matrix workspace base class
std::shared_ptr< CompositeFunction > CompositeFunction_sptr
shared pointer to the composite function base class
Mantid::Kernel::SingletonHolder< ConfigServiceImpl > ConfigService
Helper class which provides the Collimation Length for SANS instruments.
Simple Exception Struct to differentiate validation error from other exceptions.
Definition IFunction.h:171