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(mapped(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(mapped(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(mapped(const QString &)), this, SLOT(executeSetupManageMenu(const QString &)));
424 setupSubMenuManage->addAction(setupActionSave);
425 setupSubMenuManage->addAction(m_setupActionRemove);
426 setupSubMenuManage->addAction(setupActionClear);
427 setupSubMenuManage->addAction(setupActionCopyToClipboard);
428 setupSubMenuManage->addAction(setupActionLoadFromString);
429 setupActionManageSetup->setMenu(setupSubMenuManage);
430
431 QMenu *setupSubMenuRemove = new QMenu(this);
432 m_setupActionRemove->setMenu(setupSubMenuRemove);
433 // empty menu for now, so set it disabled to avoid confusing users
434 m_setupActionRemove->setEnabled(false);
435
436 QSignalMapper *PeakFindingAlgMapper = new QSignalMapper(this);
437 PeakFindingAlgMapper->setMapping(setupActionFindPeaks, "FindPeaks");
438 PeakFindingAlgMapper->setMapping(setupActionFindPeaksConvolve, "FindPeaksConvolve");
439 connect(setupActionFindPeaks, SIGNAL(triggered()), PeakFindingAlgMapper, SLOT(map()));
440 connect(setupActionFindPeaksConvolve, SIGNAL(triggered()), PeakFindingAlgMapper, SLOT(map()));
441 connect(PeakFindingAlgMapper, SIGNAL(mapped(const QString &)), this,
442 SLOT(executePeakFindingAlgMenu(const QString &)));
443
444 QSignalMapper *setupMapper = new QSignalMapper(this);
445 setupMapper->setMapping(setupActionClearFit, "ClearFit");
446 connect(setupActionClearFit, SIGNAL(triggered()), setupMapper, SLOT(map()));
447 connect(setupMapper, SIGNAL(mapped(const QString &)), this, SLOT(executeSetupMenu(const QString &)));
448
449 QMenu *setupSubMenuPeakFindingAgls = new QMenu(this);
450 setupSubMenuPeakFindingAgls->addAction(setupActionFindPeaks);
451 setupSubMenuPeakFindingAgls->addAction(setupActionFindPeaksConvolve);
452 setupActionPeakFindingAlgs->setMenu(setupSubMenuPeakFindingAgls);
453
454 setupMenu->addAction(m_setupActionCustomSetup);
455 setupMenu->addAction(setupActionManageSetup);
456 setupMenu->addSeparator();
457 setupMenu->addAction(setupActionPeakFindingAlgs);
458 setupMenu->addSeparator();
459 setupMenu->addAction(setupActionClearFit);
460 btnSetup->setMenu(setupMenu);
461
463
464 buttonsLayout->addWidget(btnFit, 0, 0);
465 buttonsLayout->addWidget(btnDisplay, 0, 1);
466 buttonsLayout->addWidget(btnSetup, 0, 2);
467
468 m_status = new QLabel("Status:", w);
469 m_status->hide();
470 connect(this, SIGNAL(fitResultsChanged(const QString &)), this, SLOT(showFitResultStatus(const QString &)),
471 Qt::QueuedConnection);
472 layout->addWidget(m_status);
473 layout->addLayout(buttonsLayout);
474 layout->addWidget(m_tip);
475 layout->addWidget(m_browser);
476 m_browser->setObjectName("tree_browser");
477
478 m_workspaceLabel = new QLabel("Workspaces");
479 layout->addWidget(m_workspaceLabel);
480 m_wsListWidget = new QListWidget();
481 layout->addWidget(m_wsListWidget);
482 m_workspaceLabel->hide();
483 m_wsListWidget->hide();
484
485 setWidget(w);
486
487 m_browser->setContextMenuPolicy(Qt::CustomContextMenu);
488 connect(m_browser, SIGNAL(customContextMenuRequested(const QPoint &)), this, SLOT(popupMenu(const QPoint &)));
489 connect(m_browser, SIGNAL(currentItemChanged(QtBrowserItem *)), this, SLOT(currentItemChanged(QtBrowserItem *)));
490 connect(this, SIGNAL(multifitFinished()), this, SLOT(processMultiBGResults()));
491
492 connect(m_wsListWidget, SIGNAL(itemDoubleClicked(QListWidgetItem *)), this,
493 SLOT(workspaceDoubleClicked(QListWidgetItem *)));
494
496
497 // Update tooltips when function structure is (or might've been) changed in
498 // any way
499 connect(this, SIGNAL(functionChanged()), SLOT(updateStructureTooltips()));
500 connect(this, SIGNAL(functionChanged()), SLOT(clearFitResultStatus()));
501
502 // Update available functions in this fit property browser, when the function
503 // factory changes.
505 FunctionFactory::Instance().notificationCenter.addObserver(m_updateObserver);
506 connect(this, SIGNAL(functionFactoryUpdateReceived()), this, SLOT(populateFunctionNames()));
507 FunctionFactory::Instance().enableNotifications();
508
509 // Initial call, as function is not changed when it's created for the first
510 // time
512
514
516}
517
518// Adds the fit result workspaces to the qlistwidget in the browser
520 const auto outName = outputName();
521 const std::vector<std::string> workspaceNames{outName + "_NormalisedCovarianceMatrix", outName + "_Parameters",
522 outName + "_Workspace"};
523
524 for (const auto &name : workspaceNames) {
525 // check if already in the list
526 auto foundInList = m_wsListWidget->findItems(QString::fromStdString(name), Qt::MatchExactly);
527 if (foundInList.size() == 0 && AnalysisDataService::Instance().doesExist(name)) {
528 new QListWidgetItem(QString::fromStdString(name), m_wsListWidget);
529 }
530 }
531
532 auto noOfItems = m_wsListWidget->count();
533 if (noOfItems != 0 && !m_hideWsListWidget) {
534 auto widgetHeight = m_wsListWidget->sizeHintForRow(0) * (noOfItems + 1) + 2 * m_wsListWidget->frameWidth();
535 m_wsListWidget->setMaximumHeight(widgetHeight);
536 m_workspaceLabel->show();
537 m_wsListWidget->show();
538 }
539}
540
542 auto wsName = item->text();
543 emit workspaceClicked(wsName);
544}
545
554 QtCheckBoxFactory *checkBoxFactory = new QtCheckBoxFactory(w);
555 QtEnumEditorFactory *comboBoxFactory = new QtEnumEditorFactory(w);
556 QtSpinBoxFactory *spinBoxFactory = new QtSpinBoxFactory(w);
557 DoubleEditorFactory *doubleEditorFactory = new DoubleEditorFactory(w);
558 StringEditorFactory *stringEditFactory = new StringEditorFactory(w);
559 FilenameDialogEditorFactory *filenameDialogEditorFactory = new FilenameDialogEditorFactory(w);
560 FormulaDialogEditorFactory *formulaDialogEditFactory = new FormulaDialogEditorFactory(w);
561
562 m_browser = new QtTreePropertyBrowser();
563 m_browser->setFactoryForManager(m_enumManager, comboBoxFactory);
564 m_browser->setFactoryForManager(m_boolManager, checkBoxFactory);
565 m_browser->setFactoryForManager(m_intManager, spinBoxFactory);
566 m_browser->setFactoryForManager(m_doubleManager, doubleEditorFactory);
567 m_browser->setFactoryForManager(m_stringManager, stringEditFactory);
568 m_browser->setFactoryForManager(m_filenameManager, filenameDialogEditorFactory);
569 m_browser->setFactoryForManager(m_formulaManager, formulaDialogEditFactory);
570 m_browser->setFactoryForManager(m_columnManager, comboBoxFactory);
571 m_browser->setFactoryForManager(m_vectorSizeManager, spinBoxFactory);
572 m_browser->setFactoryForManager(m_vectorDoubleManager, doubleEditorFactory);
573 m_browser->setFactoryForManager(m_parameterManager, new ParameterEditorFactory(w));
574}
575
579 QMenu *menuLoad = m_setupActionCustomSetup->menu();
580 menuLoad->clear();
581 QMenu *menuRemove = m_setupActionRemove->menu();
582 menuRemove->clear();
583
584 QSettings settings;
585 settings.beginGroup("Mantid/FitBrowser/SavedFunctions");
586 QStringList names = settings.childKeys();
587
588 QSignalMapper *mapperLoad = new QSignalMapper(this);
589 QSignalMapper *mapperRemove = new QSignalMapper(this);
590 // enable actions that open the menus only if there will be >=1 entries in
591 // there
592 m_setupActionCustomSetup->setEnabled(names.size() >= 1);
593 m_setupActionRemove->setEnabled(names.size() >= 1);
594 for (int i = 0; i < names.size(); i++) {
595 QAction *itemLoad = new QAction(names.at(i), this);
596 QAction *itemRemove = new QAction(names.at(i), this);
597 mapperLoad->setMapping(itemLoad, names.at(i));
598 mapperRemove->setMapping(itemRemove, names.at(i));
599 connect(itemLoad, SIGNAL(triggered()), mapperLoad, SLOT(map()));
600 connect(itemRemove, SIGNAL(triggered()), mapperRemove, SLOT(map()));
601 menuLoad->addAction(itemLoad);
602 menuRemove->addAction(itemRemove);
603 }
604 connect(mapperLoad, SIGNAL(mapped(const QString &)), this, SLOT(executeCustomSetupLoad(const QString &)));
605 connect(mapperRemove, SIGNAL(mapped(const QString &)), this, SLOT(executeCustomSetupRemove(const QString &)));
606}
607
609 QSettings settings;
610 settings.beginGroup("Mantid/FitBrowser/SavedFunctions");
611
612 QString str = settings.value(name).toString();
613 loadFunction(str);
614}
615
617 QSettings settings;
618 settings.beginGroup("Mantid/FitBrowser/SavedFunctions");
619
620 settings.remove(name);
622}
623
625 QSettings settings;
626 settings.beginGroup("Mantid/FitBrowser/SavedFunctions");
627
628 settings.clear();
630}
631
636 // Call tooltip update func on the root handler - it goes down recursively
638}
639
640void FitPropertyBrowser::executeFitMenu(const QString &item) {
641 if (item == "Fit") {
642 fit();
643 } else if (item == "SeqFit") {
645 } else if (item == "UndoFit") {
646 undoFit();
647 } else if (item == "Evaluate") {
648 doFit(0);
649 }
650}
651
652void FitPropertyBrowser::executeDisplayMenu(const QString &item) {
653 if (item == "PlotGuess") {
655 } else if (item == "ClearAll") {
657 }
658}
659
661 if (item == "FindPeaks")
662 findPeaks(std::make_unique<FindPeakDefaultStrategy>());
663 if (item == "FindPeaksConvolve")
664 findPeaks(std::make_unique<FindPeakConvolveStrategy>());
665}
666
667void FitPropertyBrowser::executeSetupMenu(const QString &item) {
668 if (item == "ClearFit")
669 clear();
670}
671
673 if (item == "SaveSetup")
674 saveFunction();
675 if (item == "ClearSetups")
677 if (item == "CopyToClipboard")
678 copy();
679 if (item == "LoadFromString")
681}
682
685 m_compositeFunction.reset();
686
687 // remove the FunctionFactory Observer
689 FunctionFactory::Instance().notificationCenter.removeObserver(m_updateObserver);
690
691 m_browser->unsetFactoryForManager(m_enumManager);
692 m_browser->unsetFactoryForManager(m_boolManager);
693 m_browser->unsetFactoryForManager(m_intManager);
694 m_browser->unsetFactoryForManager(m_doubleManager);
695 m_browser->unsetFactoryForManager(m_stringManager);
696 m_browser->unsetFactoryForManager(m_filenameManager);
697 m_browser->unsetFactoryForManager(m_formulaManager);
698 m_browser->unsetFactoryForManager(m_columnManager);
699 m_browser->unsetFactoryForManager(m_vectorSizeManager);
700 m_browser->unsetFactoryForManager(m_vectorDoubleManager);
701 m_browser->unsetFactoryForManager(m_parameterManager);
702}
703
706 return static_cast<PropertyHandler *>(m_compositeFunction->getHandler());
707}
708
710 PropertyHandler *h = getHandler()->addFunction(fnName);
711 emit functionChanged();
712 return h;
713}
714
716 if (handler) {
717 emit functionRemoved();
718 emit functionChanged();
720 handler->removeFunction();
721 compositeFunction()->checkFunction();
722 }
723}
724
728 QtBrowserItem *ci = m_browser->currentItem();
729 // Find the function which has ci as its top browser item
730 auto cf = getHandler()->findCompositeFunction(ci);
731 if (!cf)
732 return;
733
734 // Declare new widget for picking fit functions
736
737 connect(m_fitSelector, SIGNAL(accepted()), this, SLOT(acceptFit()));
738 connect(m_fitSelector, SIGNAL(rejected()), this, SLOT(closeFit()));
739 m_fitSelector->show();
740}
741
743 QtBrowserItem *ci = m_browser->currentItem();
744 std::shared_ptr<const Mantid::API::CompositeFunction> cf = getHandler()->findCompositeFunction(ci);
745 if (!cf)
746 return;
747 auto function = m_fitSelector->getFunction();
748 if (function.isEmpty()) {
749 return;
750 }
752 h->addFunction(function.toStdString());
753 emit functionChanged();
754
755 closeFit();
756}
757
759
766 emit functionRemoved();
767 m_autoBackground = nullptr;
768 }
769 if (!func) {
771 } else {
772 auto cf = std::dynamic_pointer_cast<Mantid::API::CompositeFunction>(func);
773 if (!cf || (cf->name() != "CompositeFunction" && cf->name() != "MultiBG" && cf->name() != "MultiDomainFunction")) {
775 m_compositeFunction->addFunction(func);
776 } else {
778 }
779 }
781
782 auto h = std::make_unique<PropertyHandler>(m_compositeFunction, Mantid::API::CompositeFunction_sptr(), this);
783 m_compositeFunction->setHandler(std::move(h));
784 setCurrentFunction(static_cast<PropertyHandler *>(m_compositeFunction->getHandler()));
785
786 if (m_auto_back) {
788 }
789
790 disableUndo();
791 setFitEnabled(m_compositeFunction->nFunctions() > 0);
792 emit functionChanged();
793}
794
800 if (str.isEmpty()) {
802 } else {
803 auto f = tryCreateFitFunction(str);
804 if (f) {
806 } else {
808 }
809 }
810}
811
813 try {
814 return Mantid::API::FunctionFactory::Instance().createInitialized(str.toStdString());
815 } catch (const std::exception &ex) {
816 QMessageBox::critical(this, "Mantid - Error", "Unexpected exception caught:\n\n" + QString(ex.what()));
817 return nullptr;
818 }
819}
820
821void FitPropertyBrowser::popupMenu(const QPoint & /*unused*/) {
822 QtBrowserItem *ci = m_browser->currentItem();
823 if (!ci)
824 return;
825 QMenu *menu = new QMenu(this);
826 QAction *action;
827
828 bool isFunctionsGroup = ci == m_functionsGroup;
829 bool isSettingsGroup = ci == m_settingsGroup;
830 bool isASetting = ci->parent() == m_settingsGroup;
831 bool isFunction = getHandler()->findFunction(ci) != nullptr;
832 bool isCompositeFunction = isFunction && getHandler()->findCompositeFunction(ci);
833
834 PropertyHandler *h = getHandler()->findHandler(ci->property());
835
836 if (isFunctionsGroup) {
837 action = new QAction("Add function", this);
838 connect(action, SIGNAL(triggered()), this, SLOT(addFunction()));
839 menu->addAction(action);
840
841 if (m_compositeFunction->name() == "MultiBG" && m_compositeFunction->nFunctions() == 1 &&
842 Mantid::API::AnalysisDataService::Instance().doesExist(workspaceName())) {
843 action = new QAction("Setup multifit", this);
844 connect(action, SIGNAL(triggered()), this, SLOT(setupMultifit()));
845 menu->addAction(action);
846 }
847
848 if (m_peakToolOn) {
849 if (h && h->hasPlot()) {
850 action = new QAction("Remove plot", this);
851 connect(action, SIGNAL(triggered()), this, SLOT(removeGuessAll()));
852 menu->addAction(action);
853 } else {
854 action = new QAction("Plot", this);
855 connect(action, SIGNAL(triggered()), this, SLOT(plotGuessAll()));
856 menu->addAction(action);
857 }
858 }
859
860 menu->addSeparator();
861
862 action = new QAction("Save", this);
863 connect(action, SIGNAL(triggered()), this, SLOT(saveFunction()));
864 menu->addAction(action);
865
866 action = new QAction("Load", this);
867 connect(action, SIGNAL(triggered()), this, SLOT(loadFunction()));
868 menu->addAction(action);
869
870 action = new QAction("Copy To Clipboard", this);
871 connect(action, SIGNAL(triggered()), this, SLOT(copy()));
872 menu->addAction(action);
873
874 menu->addSeparator();
875
876 action = new QAction("Help", this);
877 connect(action, SIGNAL(triggered()), this, SLOT(browserHelp()));
878 menu->addAction(action);
879 } else if (isSettingsGroup || isASetting) {
880 if (isFitEnabled()) {
881 action = new QAction("Fit", this);
882 connect(action, SIGNAL(triggered()), this, SLOT(fit()));
883 menu->addAction(action);
884 }
885
886 if (isUndoEnabled()) {
887 action = new QAction("Undo Fit", this);
888 connect(action, SIGNAL(triggered()), this, SLOT(undoFit()));
889 menu->addAction(action);
890 }
891
892 action = new QAction("Clear all", this);
893 connect(action, SIGNAL(triggered()), this, SLOT(clear()));
894 menu->addAction(action);
895
896 action = new QAction("Help", this);
897 connect(action, SIGNAL(triggered()), this, SLOT(browserHelp()));
898 menu->addAction(action);
899
900 } else if (isFunction) {
901 if (isCompositeFunction) {
902 action = new QAction("Add function", this);
903 connect(action, SIGNAL(triggered()), this, SLOT(addFunction()));
904 menu->addAction(action);
905 }
906
907 action = new QAction("Remove", this);
908 connect(action, SIGNAL(triggered()), this, SLOT(deleteFunction()));
909 menu->addAction(action);
910
911 if (m_peakToolOn) {
912 if (h && h->hasPlot()) {
913 action = new QAction("Remove plot", this);
914 connect(action, SIGNAL(triggered()), this, SLOT(removeGuessCurrent()));
915 menu->addAction(action);
916 } else {
917 action = new QAction("Plot", this);
918 connect(action, SIGNAL(triggered()), this, SLOT(plotGuessCurrent()));
919 menu->addAction(action);
920 }
921 }
922
923 action = new QAction("Help", this);
924 connect(action, SIGNAL(triggered()), this, SLOT(functionHelp()));
925 menu->addAction(action);
926
927 menu->addSeparator();
928 } else if (h) {
929 bool isParameter = h->isParameter(ci->property());
930 bool isTie = !isParameter && ci->property()->propertyName() == "Tie";
931 bool isLowerBound = !isParameter && ci->property()->propertyName() == "Lower Bound";
932 bool isUpperBound = !isParameter && ci->property()->propertyName() == "Upper Bound";
933 bool isType = isParameter && ci->property()->propertyName() == "Type";
934 if (isType) {
935 isParameter = false;
936 }
937 if (isTie) {
938 action = new QAction("Remove", this);
939 connect(action, SIGNAL(triggered()), this, SLOT(deleteTie()));
940 menu->addAction(action);
941 } else if (isLowerBound || isUpperBound) {
942 action = new QAction("Remove", this);
943 connect(action, SIGNAL(triggered()), this, SLOT(removeBounds()));
944 menu->addAction(action);
945 } else if (count() > 0 && isParameter) {
946 bool hasTies;
947 bool hasFixes;
948 bool hasBounds;
949 hasConstraints(ci->property(), hasTies, hasFixes, hasBounds);
950
951 if (!hasTies && !hasFixes) {
952 QMenu *constraintMenu = menu->addMenu("Constraint");
953
954 QMenu *detailMenu = constraintMenu->addMenu("Lower Bound");
955
956 action = new QAction("10%", this);
957 connect(action, SIGNAL(triggered()), this, SLOT(addLowerBound10()));
958 detailMenu->addAction(action);
959
960 action = new QAction("50%", this);
961 connect(action, SIGNAL(triggered()), this, SLOT(addLowerBound50()));
962 detailMenu->addAction(action);
963
964 action = new QAction("Custom", this);
965 connect(action, SIGNAL(triggered()), this, SLOT(addLowerBound()));
966 detailMenu->addAction(action);
967 detailMenu = constraintMenu->addMenu("Upper Bound");
968
969 action = new QAction("10%", this);
970 connect(action, SIGNAL(triggered()), this, SLOT(addUpperBound10()));
971 detailMenu->addAction(action);
972
973 action = new QAction("50%", this);
974 connect(action, SIGNAL(triggered()), this, SLOT(addUpperBound50()));
975 detailMenu->addAction(action);
976
977 action = new QAction("Custom", this);
978 connect(action, SIGNAL(triggered()), this, SLOT(addUpperBound()));
979 detailMenu->addAction(action);
980 detailMenu = constraintMenu->addMenu("Both Bounds");
981
982 action = new QAction("10%", this);
983 connect(action, SIGNAL(triggered()), this, SLOT(addBothBounds10()));
984 detailMenu->addAction(action);
985
986 action = new QAction("50%", this);
987 connect(action, SIGNAL(triggered()), this, SLOT(addBothBounds50()));
988 detailMenu->addAction(action);
989
990 action = new QAction("Custom", this);
991 connect(action, SIGNAL(triggered()), this, SLOT(addBothBounds()));
992 detailMenu->addAction(action);
993 }
994
995 if (hasBounds) {
996 action = new QAction("Remove constraints", this);
997 connect(action, SIGNAL(triggered()), this, SLOT(removeBounds()));
998 menu->addAction(action);
999 }
1000
1001 if (!hasTies && !hasFixes && !hasBounds) {
1002 action = new QAction("Fix", this);
1003 connect(action, SIGNAL(triggered()), this, SLOT(addFixTie()));
1004 menu->addAction(action);
1005
1006 if (count() == 1) {
1007 action = new QAction("Tie", this);
1008 connect(action, SIGNAL(triggered()), this, SLOT(addTie()));
1009 menu->addAction(action);
1010 } else {
1011 QMenu *detail = menu->addMenu("Tie");
1012
1013 action = new QAction("To function", this);
1014 connect(action, SIGNAL(triggered()), this, SLOT(addTieToFunction()));
1015 detail->addAction(action);
1016
1017 action = new QAction("Custom Tie", this);
1018 connect(action, SIGNAL(triggered()), this, SLOT(addTie()));
1019 detail->addAction(action);
1020 }
1021 } else if (hasTies) {
1022 action = new QAction("Remove tie", this);
1023 connect(action, SIGNAL(triggered()), this, SLOT(deleteTie()));
1024 menu->addAction(action);
1025 } else if (hasFixes) {
1026 action = new QAction("Remove fix", this);
1027 connect(action, SIGNAL(triggered()), this, SLOT(deleteTie()));
1028 menu->addAction(action);
1029 }
1030 }
1031 }
1032
1033 menu->popup(QCursor::pos());
1034}
1035
1039 const QtBrowserItem *const ci = m_browser->currentItem();
1040 PropertyHandler *h = getHandler()->findHandler(ci->property());
1041 removeFunction(h);
1042}
1043
1044//
1045
1046// Get the default function name
1048
1049// Set the default function name
1050void FitPropertyBrowser::setDefaultFunctionType(const std::string &fnType) { m_defaultFunction = fnType; }
1051
1054 // If the default peak is not in registered peaks, default to Gaussian
1055 if (m_registeredPeaks.indexOf(QString::fromStdString(m_defaultPeak)) == -1) {
1056 g_log.warning("Could not find peak function: '" + m_defaultPeak + "'. Defaulting to Gaussian.");
1057 setDefaultPeakType("Gaussian");
1058 }
1059 return m_defaultPeak;
1060}
1062void FitPropertyBrowser::setDefaultPeakType(const std::string &fnType) {
1063 m_defaultPeak = fnType;
1064 setDefaultFunctionType(fnType);
1065}
1069void FitPropertyBrowser::setDefaultBackgroundType(const std::string &fnType) {
1070 m_defaultBackground = fnType;
1071 setDefaultFunctionType(fnType);
1072}
1073
1074std::shared_ptr<Mantid::API::Workspace> FitPropertyBrowser::getWorkspace() const {
1075 std::string wsName = workspaceName();
1076 if (wsName.empty())
1077 return std::shared_ptr<Mantid::API::Workspace>();
1078 try {
1079 return Mantid::API::AnalysisDataService::Instance().retrieve(wsName);
1080 } catch (...) {
1081 return std::shared_ptr<Mantid::API::Workspace>();
1082 }
1083}
1084
1087 int i = m_enumManager->value(m_workspace);
1088 std::string res = "";
1089 if (i >= 0) {
1090 res = m_workspaceNames[i].toStdString();
1091 }
1092 return res;
1093}
1094
1096void FitPropertyBrowser::setWorkspaceName(const QString &wsName) {
1097 int i = m_workspaceNames.indexOf(wsName);
1098 if (i < 0) {
1099 // workspace may not be found because add notification hasn't been
1100 // processed yet
1102 i = m_workspaceNames.indexOf(wsName);
1103 }
1104 if (i >= 0) {
1105 m_enumManager->setValue(m_workspace, i);
1107 try {
1108 mws = std::dynamic_pointer_cast<Mantid::API::MatrixWorkspace>(
1109 Mantid::API::AnalysisDataService::Instance().retrieve(wsName.toStdString()));
1111 }
1112 if (mws) {
1113 auto wi = static_cast<size_t>(workspaceIndex());
1114 if (wi < mws->getNumberHistograms() && !mws->x(wi).empty()) {
1115 setStartX(mws->x(wi).front());
1116 setEndX(mws->x(wi).back());
1117 }
1118 }
1119 }
1121}
1122
1125
1128 try {
1129 auto const index = getAllowedIndex(i);
1132 // ignore this error
1133 }
1134}
1135
1137std::string FitPropertyBrowser::outputName() const { return m_stringManager->value(m_output).toStdString(); }
1138
1140void FitPropertyBrowser::setOutputName(const std::string &name) {
1141 m_stringManager->setValue(m_output, QString::fromStdString(name));
1142}
1143
1145std::string FitPropertyBrowser::minimizer(bool withProperties) const {
1146 int i = m_enumManager->value(m_minimizer);
1147 QString minimStr = m_minimizers[i];
1148 // append minimizer properties as name=value pairs
1149 if (withProperties) {
1150 foreach (const QtProperty *const prop, m_minimizerProperties) {
1151 if (prop->propertyManager() == m_stringManager) {
1152 QString value = m_stringManager->value(prop);
1153 if (!value.isEmpty()) {
1154 minimStr += "," + prop->propertyName() + "=" + value;
1155 }
1156 } else {
1157 minimStr += "," + prop->propertyName() + "=";
1158 if (prop->propertyManager() == m_intManager) {
1159 minimStr += QString::number(m_intManager->value(prop));
1160 } else if (prop->propertyManager() == m_doubleManager) {
1161 minimStr += QString::number(m_doubleManager->value(prop));
1162 } else if (prop->propertyManager() == m_boolManager) {
1163 minimStr += QString::number(m_boolManager->value(prop));
1164 } else {
1165 throw std::runtime_error("The fit browser doesn't support the type "
1166 "of minimizer's property " +
1167 prop->propertyName().toStdString());
1168 }
1169 }
1170 }
1171 }
1172 return minimStr.toStdString();
1173}
1174
1177
1180
1183 int i = m_enumManager->value(m_costFunction);
1184 return m_costFunctions[i].toStdString();
1185}
1186
1191
1194 if (!m_evaluationType->isEnabled()) {
1195 return false;
1196 }
1197 int i = m_enumManager->value(m_evaluationType);
1198 return m_evaluationTypes[i].toStdString() == "Histogram";
1199}
1200
1203
1206
1209 return m_stringManager->value(m_excludeRange).QString::toStdString();
1210}
1211
1214 const std::vector<std::string> names = Mantid::API::FunctionFactory::Instance().getFunctionNamesGUI();
1215 m_registeredFunctions.clear();
1216 m_registeredPeaks.clear();
1218 m_registeredOther.clear();
1219
1220 const auto &functionFactory = Mantid::API::FunctionFactory::Instance();
1221 for (const auto &fnName : names) {
1222 if (fnName == "MultiBG")
1223 continue;
1225 try {
1226 function = functionFactory.createFunction(fnName);
1227 } catch (std::exception &exc) {
1228 g_log.warning() << "Unable to create " << fnName << ": " << exc.what() << "\n";
1229 continue;
1230 }
1231 QString qfnName = QString::fromStdString(fnName);
1232 m_registeredFunctions << qfnName;
1233 if (dynamic_cast<Mantid::API::IPeakFunction *>(function.get())) {
1234 m_registeredPeaks << qfnName;
1235 } else if (dynamic_cast<Mantid::API::IBackgroundFunction *>(function.get())) {
1236 m_registeredBackgrounds << qfnName;
1237 } else {
1238 m_registeredOther << qfnName;
1239 }
1240 }
1241}
1242
1246void FitPropertyBrowser::enumChanged(QtProperty *prop) {
1248 return;
1249
1250 bool storeSettings = false;
1251 if (prop == m_workspace) {
1252 workspaceChange(QString::fromStdString(workspaceName()));
1256 } else if (prop->propertyName() == "Type") {
1257 disableUndo();
1259 if (!h)
1260 return;
1261 // if (!h->parentHandler()) return;
1262 auto f = h->changeType(prop);
1263 if (!h->parentHandler()) {
1264 m_compositeFunction = std::dynamic_pointer_cast<Mantid::API::CompositeFunction>(f);
1265 }
1266 if (f)
1268 emit functionChanged();
1269
1270 } else if (prop == m_minimizer) {
1272 } else if (prop == m_evaluationType) {
1273 storeSettings = true;
1274 }
1275
1276 if (storeSettings) {
1277 QSettings settings;
1278 settings.beginGroup("Mantid/FitBrowser");
1279 auto val = m_enumManager->value(prop);
1280 settings.setValue(prop->propertyName(), val);
1281 }
1282}
1283
1287void FitPropertyBrowser::boolChanged(QtProperty *prop) {
1289 return;
1290
1291 if (prop == m_plotDiff || prop == m_plotCompositeMembers || prop == m_ignoreInvalidData ||
1292 prop == m_showParamErrors) {
1293 bool val = m_boolManager->value(prop);
1294
1295 QSettings settings;
1296 settings.beginGroup("Mantid/FitBrowser");
1297 settings.setValue(prop->propertyName(), val);
1298
1299 if (prop == m_showParamErrors) {
1300 m_parameterManager->setErrorsEnabled(val);
1301 emit errorsEnabled(val);
1302 }
1303 } else { // it could be an attribute
1305 if (!h)
1306 return;
1307 enactAttributeChange(prop, h);
1308 }
1309}
1310
1314void FitPropertyBrowser::intChanged(QtProperty *prop) {
1316 return;
1317
1318 if (prop == m_workspaceIndex) {
1319 // Get current value displayed by the workspace index spinbox
1320 auto const currentIndex = workspaceIndex();
1321 auto const allowedIndex = getAllowedIndex(currentIndex);
1322 if (allowedIndex != currentIndex) {
1323 setWorkspaceIndex(allowedIndex);
1324 emit workspaceIndexChanged(allowedIndex);
1325 }
1326 m_oldWorkspaceIndex = allowedIndex;
1327 } else if (prop->propertyName() == "Workspace Index") {
1328 // Property field from Settings. Note the white space.
1330 if (!h)
1331 return;
1333 } else if (prop->propertyName() == "WorkspaceIndex") {
1334 // Property field from functions. In a word.
1336 auto const index = prop->valueText().toInt();
1337 if (h) {
1338 h->setAttribute(prop);
1342 }
1343 } else if (prop == m_maxIterations || prop == m_peakRadius) {
1344 QSettings settings;
1345 settings.beginGroup("Mantid/FitBrowser");
1346 int val = m_intManager->value(prop);
1347 settings.setValue(prop->propertyName(), val);
1348 if (prop == m_peakRadius) {
1350 }
1351 } else { // it could be an attribute
1353 if (!h)
1354 return;
1355 enactAttributeChange(prop, h);
1356 }
1357}
1358
1364 return;
1365
1366 double value = m_doubleManager->value(prop);
1367 if (prop == m_startX) {
1368 // call setWorkspace to change maxX in functions
1370 m_doubleManager->setMinimum(m_endX, value);
1371 getHandler()->setAttribute("StartX", value);
1372 emit startXChanged(startX());
1373 emit xRangeChanged(startX(), endX());
1374 return;
1375 } else if (prop == m_endX) {
1376 // call setWorkspace to change minX in functions
1378 m_doubleManager->setMaximum(m_startX, value);
1379 getHandler()->setAttribute("EndX", value);
1380 emit endXChanged(endX());
1381 emit xRangeChanged(startX(), endX());
1382 return;
1383 } else { // check if it is a constraint
1385 if (!h)
1386 return;
1387
1388 QtProperty *parProp = h->getParameterProperty(prop);
1389 if (parProp) {
1390 if (prop->propertyName() == "LowerBound") {
1391 double loBound = m_doubleManager->value(prop);
1392 h->addConstraint(parProp, true, false, loBound, 0);
1393 } else if (prop->propertyName() == "UpperBound") {
1394 double upBound = m_doubleManager->value(prop);
1395 h->addConstraint(parProp, false, true, 0, upBound);
1396 }
1397 } else { // it could be an attribute
1398 enactAttributeChange(prop, h);
1399 }
1400 }
1401}
1402
1403void FitPropertyBrowser::enactAttributeChange(QtProperty *prop, PropertyHandler *h, const bool vectorAttribute) {
1404 try {
1405 if (vectorAttribute) {
1406 h->setVectorAttribute(prop);
1407 } else {
1408 h->setAttribute(prop);
1409 }
1410 } catch (IFunction::ValidationException &ve) {
1411 std::stringstream err_str;
1412 err_str << prop->propertyName().toStdString() << " - " << ve.what();
1413 g_log.warning(err_str.str());
1414 }
1415}
1416
1425 return;
1426
1427 getHandler()->setParameter(prop);
1428}
1429
1435 return;
1436
1437 if (prop == m_output) {
1438 std::string oName = outputName();
1439 if (oName.find_first_not_of(' ') == std::string::npos) {
1440 setOutputName("");
1441 } else if (workspaceName() == oName || oName.empty()) {
1442 m_guessOutputName = true;
1443 } else {
1444 m_guessOutputName = false;
1445 }
1446 } else if (prop->propertyName() == "Tie") {
1448 if (!h)
1449 return;
1450
1451 const QtProperty *const parProp = h->getParameterProperty(prop);
1452 if (!parProp)
1453 return;
1454
1455 const QString parName = h->functionPrefix() + "." + parProp->propertyName();
1456
1457 const auto oldExp = getOldExpressionAsString(parName);
1458 const auto exp = m_stringManager->value(prop);
1459
1460 if (oldExp == exp)
1461 return;
1462
1463 try {
1464 compositeFunction().get()->tie(parName.toStdString(), exp.toStdString());
1465 h->addTie(parName + "=" + exp);
1466 } catch (...) {
1467 const auto msg =
1468 "Failed to update tie on " + parName.toStdString() + ". Expression " + exp.toStdString() + " is invalid.";
1469 QMessageBox::critical(this, "Mantid - Error", msg.c_str());
1470
1471 m_stringManager->setValue(prop, oldExp);
1472 }
1473 } else if (getHandler()->setAttribute(prop)) { // setting an attribute may
1474 // change function parameters
1475 emit functionChanged();
1476 return;
1477 }
1478}
1479
1483QString FitPropertyBrowser::getOldExpressionAsString(const QString &parameterName) const {
1484 // Note this only finds the oldTie if it was a tie to a function (e.g. f0.Height=f1.Height)
1485 // but not if it was a custom tie (e.g. f0.Height=2.0)
1486 QString oldExp;
1487 size_t parIndex;
1488 try {
1489 parIndex = compositeFunction()->parameterIndex(parameterName.toStdString());
1490 } catch (std::exception &) {
1491 return "";
1492 }
1493 const auto oldTie = compositeFunction()->getTie(parIndex);
1494 if (oldTie) {
1495 const auto oldTieStr = oldTie->asString();
1496 oldExp = QString::fromStdString(oldTieStr.substr(oldTieStr.find("=") + 1));
1497 } else {
1498 oldExp = "";
1499 }
1500 return oldExp;
1501}
1502
1508 return;
1509
1510 if (getHandler()->setAttribute(prop)) {
1511 return;
1512 }
1513}
1514// Centre of the current peak
1517 return m_currentHandler->pfun()->centre();
1518 }
1519 return 0;
1520}
1521
1532
1533// Height of the current peak
1536 return m_currentHandler->pfun()->height();
1537 }
1538 return 0.;
1539}
1540
1551
1552// Width of the current peak
1555 return m_currentHandler->pfun()->fwhm();
1556 }
1557 return 0;
1558}
1559
1570
1572int FitPropertyBrowser::count() const { return static_cast<int>(m_compositeFunction->nFunctions()); }
1573
1576
1581 m_currentHandler = h;
1582 if (m_currentHandler) {
1583 m_browser->setCurrentItem(m_currentHandler->item());
1584 emit currentChanged();
1585 }
1586}
1587
1594
1598void FitPropertyBrowser::doFit(int maxIterations) {
1599 const std::string wsName = workspaceName();
1600
1601 if (wsName.empty()) {
1602 QMessageBox::critical(this, "Mantid - Error", "Workspace name is not set");
1603 return;
1604 }
1605
1606 const auto ws = getWorkspace();
1607 if (!ws) {
1608 return;
1609 }
1610
1611 try {
1612 emit algorithmStarted(QString::fromStdString(wsName));
1613 m_initialParameters.resize(compositeFunction()->nParams());
1614 for (size_t i = 0; i < compositeFunction()->nParams(); i++) {
1615 m_initialParameters[i] = compositeFunction()->getParameter(i);
1616 }
1617 m_fitActionUndoFit->setEnabled(true);
1618
1619 Mantid::API::IAlgorithm_sptr alg = Mantid::API::AlgorithmManager::Instance().create("Fit");
1620 alg->initialize();
1621 if (isHistogramFit()) {
1622 alg->setProperty("EvaluationType", "Histogram");
1623 }
1624 alg->setProperty("Function", std::dynamic_pointer_cast<Mantid::API::IFunction>(compositeFunction())->clone());
1625 alg->setProperty("InputWorkspace", ws);
1626 auto tbl = std::dynamic_pointer_cast<ITableWorkspace>(ws);
1627 if (!tbl) {
1628 alg->setProperty("WorkspaceIndex", workspaceIndex());
1629 } else {
1630 alg->setPropertyValue("XColumn", getXColumnName().toStdString());
1631 alg->setPropertyValue("YColumn", getYColumnName().toStdString());
1632 if (getErrColumnName().toStdString() != "")
1633 alg->setPropertyValue("ErrColumn", getErrColumnName().toStdString());
1634 }
1635 alg->setProperty("StartX", startX());
1636 alg->setProperty("EndX", endX());
1637 alg->setPropertyValue("Output", outputName());
1638 alg->setPropertyValue("Minimizer", minimizer(true));
1639 alg->setProperty("IgnoreInvalidData", ignoreInvalidData());
1640 alg->setPropertyValue("CostFunction", costFunction());
1641 alg->setProperty("MaxIterations", maxIterations);
1642 alg->setProperty("PeakRadius", getPeakRadius());
1643 if (!isHistogramFit()) {
1644 if (!tbl) {
1645 alg->setProperty("Normalise", m_shouldBeNormalised);
1646 }
1647 // Always output each composite function but not necessarily plot it
1648 alg->setProperty("OutputCompositeMembers", true);
1649 if (alg->existsProperty("ConvolveMembers")) {
1650 alg->setProperty("ConvolveMembers", convolveMembers());
1651 }
1652 }
1653 if (!getExcludeRange().empty()) {
1654 if (alg->getPropertyValue("EvaluationType") != "Histogram")
1655 alg->setProperty("Exclude", getExcludeRange());
1656 else {
1657 g_log.warning("Exclude property not avaliable when evaluating as a histogram.");
1658 }
1659 }
1660 observeFinish(alg);
1661 Poco::ActiveResult<bool> result(alg->executeAsync());
1662 while (!result.available()) {
1663 QCoreApplication::processEvents();
1664 }
1665 m_fitAlgParameters = alg->toString();
1666 if (!result.error().empty()) {
1667 emit algorithmFailed();
1668 }
1669 } catch (const std::exception &e) {
1670 QString msg = "Fit algorithm failed.\n\n" + QString(e.what()) + "\n";
1671 QMessageBox::critical(this, "Mantid - Error", msg);
1672 }
1673}
1674
1680 if (m_compositeFunction->nFunctions() > 1) {
1681 function = m_compositeFunction;
1682 } else {
1683 function = getFunctionAtIndex(0);
1684 }
1685 return function;
1686}
1687
1692 return m_compositeFunction->getFunction(index);
1693}
1694
1696 // Emit a signal to show that the fitting has completed. (workspaceNames that
1697 // the fit has been done against is sent as a parameter)
1698 QString name(QString::fromStdString(alg->getProperty("InputWorkspace")));
1699 if (name.contains('_')) // Must be fitting to raw data, need to group under
1700 // name without "_Raw".
1701 emit fittingDone(name.left(name.indexOf('_')));
1702 else // else fitting to current workspace, group under same name.
1703 emit fittingDone(name);
1704
1705 IFunction_sptr function = alg->getProperty("Function");
1707 if (alg->existsProperty("OutputWorkspace")) {
1708 std::string out = alg->getProperty("OutputWorkspace");
1709 emit algorithmFinished(QString::fromStdString(out));
1710 }
1711 // Update Status string in member variable (so can be retrieved)
1712 m_fitAlgOutputStatus = alg->getPropertyValue("OutputStatus");
1713 auto status = QString::fromStdString(m_fitAlgOutputStatus);
1714 emit fitResultsChanged(status);
1715 // update Quality string
1716 if (m_displayActionQuality->isChecked()) {
1717 double quality = alg->getProperty("OutputChi2overDoF");
1718 std::string costFunctionStr = alg->getProperty("CostFunction");
1719 std::shared_ptr<Mantid::API::ICostFunction> costfun =
1720 Mantid::API::CostFunctionFactory::Instance().create(costFunctionStr);
1721 status = (status == "success") ? "success" : "failed";
1722 emit changeWindowTitle(QString("Fit Function (") + costfun->shortName().c_str() + " = " + QString::number(quality) +
1723 ", " + status + ")");
1724 } else
1725 emit changeWindowTitle("Fit Function");
1726 if (m_compositeFunction->name() == "MultiBG") {
1727 emit multifitFinished();
1728 }
1729}
1730
1732 auto function = getFittingFunction();
1733 return function->asString();
1734}
1735
1738void FitPropertyBrowser::showFitResultStatus(const QString &status) {
1739 auto text(status);
1740 text.replace("\n", "<br>");
1741 QString color("green");
1742 if (status != "success") {
1743 color = "red";
1744 }
1745
1746 m_status->setText(QString("Status: <span style='color:%2'>%1</span>").arg(text, color));
1747 m_status->show();
1748}
1749
1752 m_status->setText("Status:");
1753 m_status->hide();
1754}
1755
1758 m_workspaceNames.clear();
1759 if (m_allowedTableWorkspace.isEmpty()) {
1760 bool allAreAllowed = m_allowedSpectra.isEmpty();
1761 QStringList allowedNames;
1762 auto wsList = Mantid::API::AnalysisDataService::Instance().getObjectNames();
1763 for (const auto &wsName : wsList) {
1764 auto const &name = QString::fromStdString(wsName);
1765 if (allAreAllowed || m_allowedSpectra.contains(name)) {
1766 allowedNames << name;
1767 }
1768 }
1769
1770 for (const auto &name : allowedNames) {
1771 Mantid::API::Workspace_sptr ws = Mantid::API::AnalysisDataService::Instance().retrieve(name.toStdString());
1772 if (isWorkspaceValid(ws)) {
1773 m_workspaceNames.append(name);
1774 }
1775 }
1776 } else {
1778 }
1781}
1782
1787 (void)e;
1788 // Observe what workspaces are added and deleted unless it's a custom
1789 // fitting, all workspaces for custom fitting (eg muon analysis) should be
1790 // manually added.
1793}
1794
1799 (void)e;
1800 setADSObserveEnabled(false);
1801}
1802
1804 observeAdd(enabled);
1805 observePostDelete(enabled);
1806 observeRename(enabled);
1807}
1808
1810void FitPropertyBrowser::addHandle(const std::string &wsName, const std::shared_ptr<Mantid::API::Workspace> &ws) {
1811 auto const qName = QString::fromStdString(wsName);
1812 if (!isWorkspaceValid(ws) ||
1813 (!m_allowedSpectra.isEmpty() && !m_allowedSpectra.contains(qName) && m_allowedTableWorkspace.isEmpty()))
1814 return;
1815 QString oldName = QString::fromStdString(workspaceName());
1816 int i = m_workspaceNames.indexOf(qName);
1817
1818 bool initialSignalsBlocked = m_enumManager->signalsBlocked();
1819
1820 // if new workspace append this workspace name
1821 if (i < 0) {
1822 if (!m_workspaceNames.isEmpty()) {
1823 m_enumManager->blockSignals(true);
1824 }
1825
1826 m_workspaceNames.append(qName);
1827 m_workspaceNames.sort();
1829 }
1830 // get hold of index of oldName
1831 i = m_workspaceNames.indexOf(oldName);
1832 if (i >= 0) {
1833 m_enumManager->setValue(m_workspace, i);
1834 }
1835
1836 m_enumManager->blockSignals(initialSignalsBlocked);
1837}
1838
1840void FitPropertyBrowser::postDeleteHandle(const std::string &wsName) { removeWorkspace(wsName); }
1841
1842void FitPropertyBrowser::removeWorkspace(const std::string &wsName) {
1843 QString oldName = QString::fromStdString(workspaceName());
1844 int iName = m_workspaceNames.indexOf(QString(wsName.c_str()));
1845 if (iName >= 0) {
1846 m_workspaceNames.removeAt(iName);
1847 }
1848
1849 bool initialSignalsBlocked = m_enumManager->signalsBlocked();
1850
1851 if (QString::fromStdString(wsName) != oldName) {
1852 m_enumManager->blockSignals(true);
1853 }
1854
1856
1857 iName = m_workspaceNames.indexOf(oldName);
1858 if (iName >= 0) {
1859 m_enumManager->setValue(m_workspace, iName);
1860 }
1861
1862 m_enumManager->blockSignals(initialSignalsBlocked);
1863
1864 for (auto i = 0; i < m_wsListWidget->count(); ++i) {
1865 auto item = m_wsListWidget->item(i);
1866 if (item->text().toStdString() == wsName) {
1867 m_wsListWidget->takeItem(m_wsListWidget->row(item));
1868 }
1869 }
1870
1871 if (m_wsListWidget->count() == 0) {
1872 m_wsListWidget->hide();
1873 m_workspaceLabel->hide();
1874 }
1875}
1876
1877void FitPropertyBrowser::renameHandle(const std::string &oldName, const std::string &newName) {
1878 QString oldNameQ = QString::fromStdString(oldName);
1879 QString newNameQ = QString::fromStdString(newName);
1880 auto it = m_allowedSpectra.find(oldNameQ);
1881 if (it != m_allowedSpectra.end()) {
1882 auto indices = m_allowedSpectra.value(oldNameQ);
1883 m_allowedSpectra.remove(oldNameQ);
1884 m_allowedSpectra.insert(newNameQ, indices);
1885 }
1886 int iWorkspace = m_workspaceNames.indexOf(oldNameQ);
1887 if (iWorkspace >= 0) {
1888 m_workspaceNames.replace(iWorkspace, newNameQ);
1890 }
1891 workspaceChange(newNameQ);
1892
1893 for (auto i = 0; i < m_wsListWidget->count(); ++i) {
1894 auto item = m_wsListWidget->item(i);
1895 if (item->text().toStdString() == oldName) {
1896 m_wsListWidget->takeItem(m_wsListWidget->row(item));
1897 m_wsListWidget->insertItem(m_wsListWidget->row(item), newNameQ);
1898 }
1899 }
1900}
1901
1907 return (dynamic_cast<Mantid::API::MatrixWorkspace *>(ws.get()) != nullptr ||
1908 dynamic_cast<Mantid::API::ITableWorkspace *>(ws.get()) != nullptr);
1909}
1910
1913 if (count() == 0) {
1914 return false;
1915 }
1917}
1918
1920double FitPropertyBrowser::startX() const { return m_doubleManager->value(m_startX); }
1921
1924
1926double FitPropertyBrowser::endX() const { return m_doubleManager->value(m_endX); }
1927
1930
1931void FitPropertyBrowser::setXRange(double start, double end) {
1932 disconnect(m_doubleManager, SIGNAL(propertyChanged(QtProperty *)), this, SLOT(doubleChanged(QtProperty *)));
1933
1934 m_doubleManager->setValue(m_startX, start);
1935 m_doubleManager->setValue(m_endX, end);
1936
1938 m_doubleManager->setMinimum(m_endX, start);
1939 m_doubleManager->setMaximum(m_startX, end);
1940
1941 getHandler()->setAttribute("StartX", start);
1942 getHandler()->setAttribute("EndX", end);
1943
1944 connect(m_doubleManager, SIGNAL(propertyChanged(QtProperty *)), this, SLOT(doubleChanged(QtProperty *)));
1945}
1946
1948 auto ws = getWorkspace();
1949 auto tbl = std::dynamic_pointer_cast<ITableWorkspace>(ws);
1950 auto mws = std::dynamic_pointer_cast<MatrixWorkspace>(ws);
1951 QVector<double> range;
1952 if (tbl) {
1953 auto xColumnIndex = m_columnManager->value(m_xColumn);
1954 std::vector<double> xColumnData;
1955 auto col = tbl->getColumn(xColumnIndex);
1956 try {
1957 for (size_t i = 0; i < tbl->rowCount(); ++i) {
1958 xColumnData.emplace_back(col->toDouble(i));
1959 }
1960 } catch (std::invalid_argument &err) {
1961 QMessageBox::critical(this, "Mantid - Error", "The X column is not a number");
1962 throw std::invalid_argument(err);
1963 }
1964 std::sort(xColumnData.begin(), xColumnData.end());
1965 range.push_back(xColumnData.front());
1966 range.push_back(xColumnData.back());
1967 } else if (mws) {
1968 auto xData = mws->mutableX(workspaceIndex());
1969 range.push_back(xData.front());
1970 range.push_back(xData.back());
1971 }
1972 return range;
1973}
1974
1976 const auto ws = getWorkspace();
1977 auto tbl = std::dynamic_pointer_cast<ITableWorkspace>(ws);
1978 QString columnName = "";
1979 if (tbl) {
1980 auto columns = tbl->getColumnNames();
1981 auto xIndex = m_columnManager->value(m_xColumn);
1982 if (xIndex >= static_cast<int>(columns.size())) {
1983 QMessageBox::critical(nullptr, "Mantid - Error", "X column was not found.");
1984 }
1985 columnName = QString::fromStdString(columns[xIndex]);
1986 }
1987 return columnName;
1988}
1989
1991 const auto ws = getWorkspace();
1992 auto tbl = std::dynamic_pointer_cast<ITableWorkspace>(ws);
1993 QString columnName = "";
1994 if (tbl) {
1995 auto columns = tbl->getColumnNames();
1996 auto yIndex = m_columnManager->value(m_yColumn);
1997 if (yIndex >= static_cast<int>(columns.size())) {
1998 QMessageBox::critical(nullptr, "Mantid - Error", "Y column was not found.");
1999 }
2000 columnName = QString::fromStdString(columns[yIndex]);
2001 }
2002 return columnName;
2003}
2004
2006 const auto ws = getWorkspace();
2007 auto tbl = std::dynamic_pointer_cast<ITableWorkspace>(ws);
2008 QString columnName = "";
2009 if (tbl) {
2010 auto columns = tbl->getColumnNames();
2011 // The error column has an empty first entry
2012 auto errIndex = m_columnManager->value(m_errColumn) - 1;
2013 if (errIndex >= static_cast<int>(columns.size())) {
2014 QMessageBox::warning(nullptr, "Mantid - Warning", "Error column was not found.");
2015 } else if (errIndex != -1) {
2016 columnName = QString::fromStdString(columns[errIndex]);
2017 }
2018 }
2019 return columnName;
2020}
2021
2023QtBrowserItem *FitPropertyBrowser::findItem(QtBrowserItem *parent, QtProperty *prop) const {
2024 QList<QtBrowserItem *> children = parent->children();
2025 QtBrowserItem *res = nullptr;
2026 for (auto &child : children) {
2027 if (child->property() == prop) {
2028 return child;
2029 }
2030 QList<QtBrowserItem *> grand_children = child->children();
2031 if (grand_children.size() > 0)
2032 res = findItem(child, prop);
2033 if (res)
2034 return res;
2035 }
2036 return nullptr;
2037}
2038
2042void FitPropertyBrowser::currentItemChanged(QtBrowserItem *current) {
2043 if (current) {
2044 m_currentHandler = getHandler()->findHandler(current->property());
2045 } else {
2046 m_currentHandler = nullptr;
2047 }
2048 emit currentChanged();
2049}
2050
2057 if (!h)
2058 return;
2059 enactAttributeChange(prop, h, true);
2060}
2061
2068 if (!h)
2069 return;
2070 enactAttributeChange(prop, h, true);
2071}
2072
2077
2082
2092
2094 QList<QtProperty *> props = m_functionsGroup->property()->subProperties();
2095 foreach (QtProperty *prop, props) {
2096 m_functionsGroup->property()->removeSubProperty(prop);
2097 }
2098}
2099
2102 for (auto paramIndex = 0u; paramIndex < finalFunction->nParams(); ++paramIndex) {
2103 compositeFunction()->setParameter(paramIndex, finalFunction->getParameter(paramIndex));
2104 compositeFunction()->setError(paramIndex, finalFunction->getError(paramIndex));
2105 }
2108}
2109
2114 if (m_initialParameters.size() == compositeFunction()->nParams()) {
2115 for (size_t i = 0; i < compositeFunction()->nParams(); i++) {
2116 compositeFunction()->setParameter(i, m_initialParameters[i]);
2117 }
2121 emit fitUndone();
2122 }
2123 disableUndo();
2124}
2125
2128 m_initialParameters.clear();
2129 m_fitActionUndoFit->setEnabled(false);
2130}
2131
2134 return m_initialParameters.size() && compositeFunction()->nParams() == m_initialParameters.size();
2135}
2136
2139 m_fitActionFit->setEnabled(enable);
2140 m_fitActionSeqFit->setEnabled(enable);
2141}
2142
2144bool FitPropertyBrowser::isFitEnabled() const { return m_fitActionFit->isEnabled(); }
2145
2150 QtBrowserItem *ci = m_browser->currentItem();
2151 QtProperty *paramProp = ci->property();
2152 PropertyHandler *h = getHandler()->findHandler(paramProp);
2153 if (!h)
2154 return;
2155 if (!h->isParameter(paramProp))
2156 return;
2157
2158 auto f = h->function();
2159 if (!f)
2160 return;
2161
2162 bool ok = false;
2163 QString tieStr = QInputDialog::getText(this, "Mantid - Fit", "Enter tie expression", QLineEdit::Normal, "", &ok);
2164 if (ok) {
2165 tieStr = tieStr.trimmed();
2166 if (!tieStr.contains('=')) {
2167 tieStr = h->functionPrefix() + "." + paramProp->propertyName() + "=" + tieStr;
2168 }
2169 h->addTie(tieStr);
2170 } // if (ok)
2171}
2172
2178 QtBrowserItem *ci = m_browser->currentItem();
2179 QtProperty *paramProp = ci->property();
2180 PropertyHandler *h = getHandler()->findHandler(paramProp);
2181 if (!h)
2182 return;
2183 if (!h->isParameter(paramProp))
2184 return;
2185 std::string parName = paramProp->propertyName().toStdString();
2186 QStringList fnNames;
2187
2188 int iPar = -1;
2189 for (size_t i = 0; i < m_compositeFunction->nParams(); i++) {
2191 const Mantid::API::IFunction *const fun = ref.getLocalFunction();
2192
2193 // Pick out parameters with the same name as the one we're tying from
2194 if (fun->parameterName(static_cast<int>(ref.getLocalIndex())) == parName) {
2195 if (iPar == -1 && fun == h->function().get()) // If this is the 'tied from' parameter, remember it
2196 {
2197 iPar = (int)i;
2198 } else // Otherwise add it to the list of potential 'tyees'
2199 {
2200 fnNames << QString::fromStdString(m_compositeFunction->parameterName(i));
2201 }
2202 }
2203 }
2204 if (fnNames.empty() || iPar < 0) {
2205 QMessageBox::information(this, "Mantid - information", "Cannot tie this parameter to any function");
2206 return;
2207 }
2208
2209 bool ok;
2210 QString tieName = QInputDialog::getItem(this, "Mantid - Fit", "Select function", fnNames, 0, false, &ok);
2211
2212 if (!ok)
2213 return;
2214
2215 QString tieExpr = QString::fromStdString(m_compositeFunction->parameterName(iPar)) + "=" + tieName;
2216
2217 h->addTie(tieExpr);
2218}
2219
2224 QtBrowserItem *ci = m_browser->currentItem();
2225 QtProperty *paramProp = ci->property();
2226 PropertyHandler *h = getHandler()->findHandler(paramProp);
2227 if (!h)
2228 return;
2229 if (!h->isParameter(paramProp))
2230 return;
2231 h->fix(paramProp->propertyName());
2232}
2233
2238 QtBrowserItem *ci = m_browser->currentItem();
2239 QtProperty *paramProp = ci->property();
2240 PropertyHandler *h = getHandler()->findHandler(paramProp);
2241 if (!h)
2242 return;
2243 // get name of parent property (i.e. function)
2244 if (paramProp->propertyName() != "Tie") {
2245 auto parameterMap = h->getTies();
2246 auto match = parameterMap.find(paramProp->propertyName());
2247 if (match != parameterMap.end()) {
2248 paramProp = match.value();
2249 }
2250 }
2251 if (paramProp->propertyName() == "Tie") {
2252 auto ties = h->getTies();
2253 QString qParName = ties.key(paramProp, "");
2254 std::string parName = qParName.toStdString();
2255 QStringList functionNames;
2256 // ithParameter = -1 => not found
2257 int ithParameter = -1;
2258 for (size_t i = 0; i < m_compositeFunction->nParams(); i++) {
2259 const Mantid::API::ParameterReference parameterRef(m_compositeFunction.get(), i);
2260 const Mantid::API::IFunction *const function = parameterRef.getLocalFunction();
2261 // Pick out parameters with the same name as the one we're tying from
2262 if (function->parameterName(static_cast<int>(parameterRef.getLocalIndex())) == parName) {
2263 if (ithParameter == -1 && function == h->function().get()) // If this is the 'tied from'
2264 // parameter, remember it
2265 {
2266 ithParameter = static_cast<int>(i);
2267 } else // Otherwise add it to the list of potential 'tyees'
2268 {
2269 functionNames << QString::fromStdString(m_compositeFunction->parameterName(i));
2270 }
2271 }
2272 }
2273 if (functionNames.empty() && ithParameter < 0) {
2274 QMessageBox::information(this, "Mantid - information", "Cannot find a parameter with this tie");
2275 } else {
2276 QString tieExpr = QString::fromStdString(m_compositeFunction->parameterName(ithParameter));
2277 h->removeTie(paramProp, tieExpr.toStdString());
2278 }
2279 } else {
2280 h->removeTie(ci->property()->propertyName());
2281 }
2282}
2283
2290void FitPropertyBrowser::hasConstraints(QtProperty *parProp, bool &hasTie, bool &hasFix, bool &hasBounds) const {
2291 hasTie = false;
2292 hasFix = false;
2293 hasBounds = false;
2294 QList<QtProperty *> subs = parProp->subProperties();
2295 for (const auto *sub : subs) {
2296 const auto propName = sub->propertyName();
2297 if (propName == "Tie") {
2298 hasTie = true;
2299 } else if (propName == "Fix") {
2300 hasFix = true;
2301 } else if (propName == "LowerBound") {
2302 hasBounds = true;
2303 } else if (propName == "UpperBound") {
2304 hasBounds = true;
2305 }
2306 }
2307}
2308
2312QtProperty *FitPropertyBrowser::getTieProperty(QtProperty *parProp) const {
2313 QList<QtProperty *> subs = parProp->subProperties();
2314 if (auto sub =
2315 std::find_if(std::cbegin(subs), std::cend(subs), [](const auto x) { return (*x).propertyName() == "Tie"; });
2316 sub != std::cend(subs)) {
2317 return *sub;
2318 }
2319 return nullptr;
2320}
2321
2327 Q_UNUSED(notice);
2328 // Don't call populate directly as the updates can come from a different
2329 // thread
2331}
2332
2336void FitPropertyBrowser::setTip(const QString &txt) { m_tip->setText(txt); }
2337
2342void FitPropertyBrowser::addConstraint(int f, bool lo, bool up) {
2343 QtBrowserItem *ci = m_browser->currentItem();
2344 QtProperty *parProp = ci->property();
2345 PropertyHandler *h = getHandler()->findHandler(parProp);
2346 if (!h)
2347 return;
2348
2349 double x = parProp->valueText().toDouble();
2350 double loBound = x * (1 - 0.01 * f);
2351 double upBound = x * (1 + 0.01 * f);
2352
2353 h->addConstraint(ci->property(), lo, up, loBound, upBound);
2354}
2355
2360
2365
2370
2375
2380
2385
2391
2397
2402
2407 QtBrowserItem *ci = m_browser->currentItem();
2408 QtProperty *parProp = ci->property();
2409 PropertyHandler *h = getHandler()->findHandler(parProp);
2410 if (!h)
2411 return;
2412
2413 h->removeConstraint(parProp);
2414}
2415
2420
2425
2431
2436
2438 if (getHandler()->hasPlot()) {
2440 } else {
2441 plotGuessAll();
2442 }
2443}
2444
2446
2452QtProperty *FitPropertyBrowser::addDoubleProperty(const QString &name, QtDoublePropertyManager *manager) const {
2453 if (manager == nullptr)
2454 manager = m_doubleManager;
2455 QtProperty *prop = manager->addProperty(name);
2456 manager->setDecimals(prop, m_decimals);
2457 manager->setRange(prop, -DBL_MAX, DBL_MAX);
2458 return prop;
2459}
2460
2466QtProperty *FitPropertyBrowser::addStringProperty(const QString &name) const {
2467 QtProperty *prop;
2468 QString propName = name.toLower();
2469 if (propName == "filename") {
2470 prop = m_filenameManager->addProperty(name);
2471 } else if (propName == "formula") {
2473 prop = m_formulaManager->addProperty(name);
2474 } else {
2475 prop = m_stringManager->addProperty(name);
2476 }
2477 return prop;
2478}
2479
2488 const std::vector<std::string> &allowed_values) const {
2489 QStringList qAllowedValues;
2490 QtProperty *prop = m_enumManager->addProperty(name);
2491
2492 for (const auto &values : allowed_values) {
2493 qAllowedValues << QString::fromStdString(values);
2494 }
2495 m_enumManager->setEnumNames(prop, qAllowedValues);
2496
2497 return prop;
2498}
2499
2505void FitPropertyBrowser::setStringPropertyValue(QtProperty *prop, const QString &value) const {
2506 auto *manager = dynamic_cast<QtStringPropertyManager *>(prop->propertyManager());
2507 if (manager) {
2508 manager->setValue(prop, value);
2509 }
2510}
2511
2512QString FitPropertyBrowser::getStringPropertyValue(QtProperty *prop) const {
2513 const auto *const manager = dynamic_cast<QtStringPropertyManager *>(prop->propertyManager());
2514 if (manager)
2515 return manager->value(prop);
2516 else
2517 return QString("");
2518}
2519
2521
2523
2528int FitPropertyBrowser::getAllowedIndex(int currentIndex) const {
2529 auto const workspace = std::dynamic_pointer_cast<MatrixWorkspace>(getWorkspace());
2530
2531 if (!workspace) {
2532 return 0;
2533 }
2534
2535 auto const allowedIndices =
2536 m_allowedSpectra.empty() ? QList<int>() : m_allowedSpectra[QString::fromStdString(workspaceName())];
2537 auto const firstIndex = m_allowedSpectra.empty() ? 0 : allowedIndices.front();
2538 auto const lastIndex = m_allowedSpectra.empty() ? getNumberOfSpectra(workspace) - 1 : allowedIndices.back();
2539
2540 auto allowedIndex = currentIndex;
2541 if (currentIndex < firstIndex) {
2542 allowedIndex = firstIndex;
2543 } else if (currentIndex > lastIndex) {
2544 allowedIndex = lastIndex;
2545 } else if (!m_allowedSpectra.empty() && !allowedIndices.contains(currentIndex)) {
2546 allowedIndex = m_oldWorkspaceIndex;
2547 auto i = allowedIndices.indexOf(m_oldWorkspaceIndex);
2548 if (i >= 0) {
2549 i = currentIndex > m_oldWorkspaceIndex ? i + 1 : i - 1;
2550 if (i >= 0 && i < allowedIndices.size()) {
2551 allowedIndex = allowedIndices[i];
2552 }
2553 }
2554 }
2555 return allowedIndex;
2556}
2557
2559 bool ok(false);
2560 QString fnName = QInputDialog::getText(this, tr("Mantid - Input"), tr("Please select a name for the function"),
2561 QLineEdit::Normal, "", &ok);
2562 if (ok && !fnName.isEmpty()) {
2563 saveFunction(fnName);
2564 }
2565}
2566
2567void FitPropertyBrowser::saveFunction(const QString &fnName) {
2568 QSettings settings;
2569 settings.beginGroup("Mantid/FitBrowser/SavedFunctions");
2570 QStringList names = settings.childKeys();
2571 if (names.contains(fnName) && QMessageBox::question(this, "Mantid - Question",
2572 "Function with this name already exists.\n"
2573 "Would you like to replace it?",
2574 QMessageBox::Yes) != QMessageBox::Yes) {
2575 return;
2576 }
2577 settings.setValue(fnName, QString::fromStdString(theFunction()->asString()));
2579}
2580
2582 QSettings settings;
2583 settings.beginGroup("Mantid/FitBrowser/SavedFunctions");
2584 QStringList names = settings.childKeys();
2585 if (names.isEmpty()) {
2586 QMessageBox::information(this, "Mantid - Information", "There are no saved functions");
2587 return;
2588 }
2589 QString name = QInputDialog::getItem(this, "Mantid - Input", "Please select a function to load", names, 0, false);
2590 if (!name.isEmpty()) {
2591 QString str = settings.value(name).toString();
2592
2593 loadFunction(str);
2594 }
2595}
2596
2598 QString str = QInputDialog::getText(this, "Mantid - Input", "Specify fit function string");
2599
2600 if (!str.isEmpty()) {
2601 loadFunction(str);
2602 }
2603}
2604
2605void FitPropertyBrowser::loadFunction(const QString &funcString) {
2606 // when loading a function from a string initially
2607 // do not try to do auto background even if set
2608 bool isAutoBGset = false;
2609 if (m_auto_back) {
2610 isAutoBGset = true;
2611 m_auto_back = false;
2612 }
2613
2615 clearBrowser();
2616 createCompositeFunction(funcString);
2617 emit functionLoaded(funcString);
2618
2619 if (isAutoBGset)
2620 m_auto_back = true;
2621}
2622
2624 QClipboard *clipboard = QApplication::clipboard();
2625 clipboard->setText(QString::fromStdString(theFunction()->asString()));
2626}
2627
2629 QClipboard *clipboard = QApplication::clipboard();
2630 QString str = clipboard->text();
2632}
2633
2635 QString str = QString::fromStdString(theFunction()->asString());
2636 // getHandler()->removeAllPlots();// this crashes mantidplot
2637 clearBrowser();
2639}
2640
2642 std::string wsName = workspaceName();
2643 if (!wsName.empty()) {
2644 try {
2645 auto ws = Mantid::API::AnalysisDataService::Instance().retrieve(wsName);
2646 auto mws = std::dynamic_pointer_cast<Mantid::API::MatrixWorkspace>(ws);
2647 if (mws) {
2648 function->setMatrixWorkspace(mws, workspaceIndex(), startX(), endX());
2649 } else {
2650 function->setWorkspace(ws);
2651 }
2652 } catch (...) {
2653 }
2654 }
2655}
2656
2658 if (m_autoBgName.isEmpty())
2659 return;
2660 bool hasPlot = false;
2662 if (m_autoBackground) { // remove old background
2663 if (ch == m_autoBackground) {
2664 ch = nullptr;
2665 }
2666 hasPlot = m_autoBackground->hasPlot();
2668 m_autoBackground = nullptr;
2669 }
2670 // Create the function
2671 PropertyHandler *h = getHandler()->addFunction(m_autoBgName.toStdString());
2672 if (!h)
2673 return;
2674 if (!m_autoBgAttributes.isEmpty()) { // set attributes
2675 QStringList attList = m_autoBgAttributes.split(' ');
2676 foreach (const QString &att, attList) {
2677 QStringList name_value = att.split('=');
2678 if (name_value.size() == 2) {
2679 QString name = name_value[0].trimmed();
2680 QString value = name_value[1].trimmed();
2681 if (h->function()->hasAttribute(name.toStdString())) {
2682 h->setAttribute(name, value);
2683 }
2684 }
2685 }
2686 }
2687 h->fit();
2688 m_autoBackground = h;
2690 if (hasPlot) {
2692 emit plotCurrentGuess();
2693 if (ch) {
2695 }
2696 }
2697}
2698
2704
2712 try {
2713 QStringList nameList = aName.split(' ');
2714 if (nameList.isEmpty())
2715 return;
2716 QString name = nameList[0];
2717 std::shared_ptr<Mantid::API::IFunction> f = std::shared_ptr<Mantid::API::IFunction>(
2718 Mantid::API::FunctionFactory::Instance().createFunction(name.toStdString()));
2719 m_auto_back = true;
2721 if (nameList.size() > 1) {
2722 nameList.removeFirst();
2723 m_autoBgAttributes = nameList.join(" ");
2724 }
2725 Mantid::Kernel::ConfigService::Instance().setString("curvefitting.autoBackground", aName.toStdString());
2726 } catch (...) {
2727 m_auto_back = false;
2728 }
2729}
2730
2732 auto *dlg = new SequentialFitDialog(this, m_mantidui);
2733 std::string wsName = workspaceName();
2734 if (!wsName.empty() && dlg->addWorkspaces(QStringList(QString::fromStdString(wsName)))) {
2735 dlg->show();
2736 }
2737}
2738
2739void FitPropertyBrowser::findPeaks(const std::unique_ptr<FindPeakStrategyGeneric> findPeakStrategy) {
2740 std::string wsName{workspaceName()};
2741 if (wsName.empty()) {
2742 QMessageBox::critical(this, "Mantid - Error", "Workspace name is not set");
2743 return;
2744 }
2745
2746 std::string peakListName = wsName + "_PeakList_tmp";
2747 QString setting =
2748 QString::fromStdString(Mantid::Kernel::ConfigService::Instance().getString("curvefitting.findPeaksFWHM"));
2749 int FWHM{setting.isEmpty() ? 7 : setting.toInt()};
2750
2752 findPeakStrategy->initialise(wsName, workspaceIndex(), peakListName, FWHM, &obs);
2753
2754 QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
2755
2756 Mantid::API::MatrixWorkspace_sptr inputWS = std::dynamic_pointer_cast<Mantid::API::MatrixWorkspace>(
2757 Mantid::API::AnalysisDataService::Instance().retrieve(workspaceName()));
2758
2759 try {
2760 findPeakStrategy->execute();
2761 clear();
2762 for (size_t i = 0; i < findPeakStrategy->peakNumber(); ++i) {
2763 if (findPeakStrategy->getPeakCentre(i) < startX() || findPeakStrategy->getPeakCentre(i) > endX()) {
2764 continue;
2765 }
2766 if (!createAndAddFunction(inputWS, i, findPeakStrategy)) {
2767 break;
2768 }
2769 }
2770 } catch (...) {
2771 QApplication::restoreOverrideCursor();
2772 throw;
2773 }
2774
2775 QApplication::restoreOverrideCursor();
2776}
2777
2779 m_peakToolOn = on;
2780 m_displayActionPlotGuess->setEnabled(on);
2781}
2782
2787 if (m_decimals < 0) {
2788 QSettings settings;
2789 settings.beginGroup("Mantid/FitBrowser");
2790 m_decimals = settings.value("decimals", 6).toInt();
2791 }
2792 QSet<QtProperty *> props = m_doubleManager->properties();
2793 foreach (QtProperty *prop, props) {
2794 m_doubleManager->setDecimals(prop, m_decimals);
2795 }
2796}
2797
2799 m_decimals = d;
2800 QSettings settings;
2801 settings.beginGroup("Mantid/FitBrowser");
2802 settings.setValue("decimals", d);
2804}
2805
2807
2810
2812
2813void FitPropertyBrowser::setTextPlotGuess(const QString &text) { m_displayActionPlotGuess->setText(text); }
2814
2818void FitPropertyBrowser::workspaceChange(const QString &wsName) {
2819 if (m_guessOutputName) {
2820 m_stringManager->setValue(m_output, QString::fromStdString(workspaceName()));
2821 }
2822
2823 emit workspaceNameChanged(wsName);
2824 emit wsChangePPAssign(wsName);
2825}
2826
2831
2836 auto *dlg = new MultifitSetupDialog(this);
2837 dlg->exec();
2838 QStringList ties = dlg->getParameterTies();
2839
2840 if (!ties.isEmpty()) {
2841 QString wsName = QString::fromStdString(workspaceName());
2842 Mantid::API::MatrixWorkspace_sptr mws = std::dynamic_pointer_cast<Mantid::API::MatrixWorkspace>(
2843 Mantid::API::AnalysisDataService::Instance().retrieve(workspaceName()));
2844 if (mws) {
2845 auto fun = getFunctionAtIndex(0);
2846 QString fun1Ini = QString::fromStdString(fun->asString());
2847 QString funIni = "composite=MultiBG;" + fun1Ini + ",Workspace=" + wsName + ",WSParam=(WorkspaceIndex=0);";
2848 QString tieStr;
2849 for (size_t i = 1; i < mws->getNumberHistograms(); ++i) {
2850 QString comma = i > 1 ? "," : "";
2851 QString fi = comma + "f" + QString::number(i) + ".";
2852 for (int j = 0; j < static_cast<int>(fun->nParams()); ++j) {
2853 if (!ties[j].isEmpty()) {
2854 tieStr += fi + QString::fromStdString(fun->parameterName(j)) + "=" + ties[j];
2855 }
2856 }
2857 QString wsParam = ",WSParam=(WorkspaceIndex=" + QString::number(i);
2858 wsParam += ",StartX=" + QString::number(startX()) + ",EndX=" + QString::number(endX()) + ")";
2859 funIni += fun1Ini + ",Workspace=" + wsName + wsParam + ";";
2860 }
2861 if (!tieStr.isEmpty()) {
2862 funIni += "ties=(" + tieStr + ")";
2863 }
2864 loadFunction(funIni);
2865 }
2866 }
2867}
2868
2871 if (compositeFunction()->name() != "MultiBG")
2872 return;
2873
2874 // if all member functions are of the same type and composition
2875 // create a TableWorkspace with parameter series
2876
2877 // check if member functions are the same
2878 QStringList parNames;
2879 auto fun0 = getFunctionAtIndex(0);
2880 if (!fun0) {
2881 throw std::runtime_error("IFunction expected but func function of another type");
2882 }
2883 for (size_t i = 0; i < fun0->nParams(); ++i) {
2884 parNames << QString::fromStdString(fun0->parameterName(i));
2885 }
2886
2887 for (size_t i = 1; i < compositeFunction()->nFunctions(); ++i) {
2888 auto fun = getFunctionAtIndex(i);
2889 if (!fun) {
2890 throw std::runtime_error("IFunction expected but func function of another type");
2891 }
2892 for (size_t j = 0; j < fun->nParams(); ++j) {
2893 if (parNames.indexOf(QString::fromStdString(fun->parameterName(j))) < 0) {
2894 // Functions are different, stop
2895 return;
2896 }
2897 }
2898 }
2899
2900 QApplication::setOverrideCursor(Qt::WaitCursor);
2901 // create a TableWorkspace: first column - function index
2902 // other colomns - the parameters
2903 Mantid::API::ITableWorkspace_sptr table = Mantid::API::WorkspaceFactory::Instance().createTable("TableWorkspace");
2904 table->addColumn("int", "Index");
2905 foreach (const QString &par, parNames) {
2906 table->addColumn("double", par.toStdString());
2907 }
2908 // Create WorkspaceGroup with the fit results
2909 std::vector<std::string> worspaceNames(compositeFunction()->nFunctions());
2910 for (size_t i = 0; i < compositeFunction()->nFunctions(); ++i) {
2911 // Mantid::API::TableRow row = table->appendRow();
2912 // row << int(i);
2913 // Mantid::API::IFunctionMW* fun =
2914 // dynamic_cast<Mantid::API::IFunctionMW*>(compositeFunction()->getFunction(i));
2915 // for(size_t j = 0; j < fun->nParams(); ++j)
2916 //{
2917 // row << fun->getParameter(j);
2918 //}
2919 // size_t wi = fun->getWorkspaceIndex();
2920 // Mantid::API::MatrixWorkspace_sptr mws =
2921 // fun->createCalculatedWorkspace(fun->getMatrixWorkspace(),wi);
2922 // worspaceNames[i] =
2923 // workspaceNames()+"_"+QString::number(wi).toStdString()+"_Workspace";
2924 // Mantid::API::AnalysisDataService::Instance().addOrReplace(worspaceNames[i],mws);
2925 }
2926
2927 // Save the table
2928 Mantid::API::AnalysisDataService::Instance().addOrReplace(workspaceName() + "_Param_series", table);
2929 try {
2930 Mantid::API::IAlgorithm_sptr group = Mantid::API::AlgorithmManager::Instance().create("GroupWorkspaces");
2931 group->setProperty("InputWorkspaces", worspaceNames);
2932 group->setPropertyValue("OutputWorkspace", workspaceName() + "_Workspace");
2933 group->execute();
2934 } catch (...) {
2935 }
2936 QApplication::restoreOverrideCursor();
2937}
2938
2945 // remove old properties
2946 if (m_browser->isItemVisible(m_settingsGroup)) {
2947 if (m_settingsGroup->property()->subProperties().contains(m_workspaceIndex)) {
2948 m_settingsGroup->property()->removeSubProperty(m_workspaceIndex);
2949 } else if (m_settingsGroup->property()->subProperties().contains(m_xColumn)) {
2950 m_settingsGroup->property()->removeSubProperty(m_xColumn);
2951 m_settingsGroup->property()->removeSubProperty(m_yColumn);
2952 m_settingsGroup->property()->removeSubProperty(m_errColumn);
2953 }
2954 }
2955
2957 try {
2958 ws = Mantid::API::AnalysisDataService::Instance().retrieve(workspaceName());
2959 } catch (...) {
2960 return;
2961 }
2962 if (!ws)
2963 return;
2964
2965 // If this is a MuonFitPropertyBrowser, "evaluation type" goes in the Custom
2966 // Settings group.
2967 // If not, there is no Custom Settings group and it goes in the regular
2968 // Settings group.
2969 const auto *const settings = m_customSettingsGroup ? m_customSettingsGroup : m_settingsGroup;
2970
2971 if (settings->property()->subProperties().contains(m_evaluationType)) {
2972 settings->property()->removeSubProperty(m_evaluationType);
2973 m_evaluationType->setEnabled(false);
2974 // if it is a MatrixWorkspace insert WorkspaceIndex
2975 auto mws = std::dynamic_pointer_cast<Mantid::API::MatrixWorkspace>(ws);
2976 if (mws) {
2978 auto isHistogram = mws->isHistogramData();
2979 m_evaluationType->setEnabled(isHistogram);
2980 if (isHistogram) {
2981 settings->property()->addSubProperty(m_evaluationType);
2982 }
2983 return;
2984 }
2985 }
2986
2987 // if it is a TableWorkspace insert the column properties
2988 auto tws = std::dynamic_pointer_cast<Mantid::API::ITableWorkspace>(ws);
2989 if (tws) {
2991 // insert properties
2992 m_settingsGroup->property()->insertSubProperty(m_xColumn, m_workspace);
2993 m_settingsGroup->property()->insertSubProperty(m_yColumn, m_xColumn);
2994 m_settingsGroup->property()->insertSubProperty(m_errColumn, m_yColumn);
2996 return;
2997 QString xName;
2998 QString yName;
2999 QString errName;
3000 auto names = tws->getColumnNames();
3001 QStringList columns;
3002 for (const auto &name : names) {
3003 columns << QString::fromStdString(name);
3004 auto col = tws->getColumn(name);
3005 if (xName.isEmpty() && col->getPlotType() == 1 /*X*/) {
3006 xName = QString::fromStdString(name);
3007 }
3008 if (yName.isEmpty() && col->getPlotType() == 2 /*Y*/) {
3009 yName = QString::fromStdString(name);
3010 }
3011 if (errName.isEmpty() && col->getPlotType() == 5 /*yErr*/) {
3012 errName = QString::fromStdString(name);
3013 }
3014 }
3015 m_columnManager->setEnumNames(m_xColumn, columns);
3016 m_columnManager->setEnumNames(m_yColumn, columns);
3017 // set the column values
3018 if (!xName.isEmpty()) {
3019 m_columnManager->setValue(m_xColumn, columns.indexOf(xName));
3020 } else {
3021 if (auto name = std::find_if(std::cbegin(columns), std::cend(columns), [&](const auto x) { return x != yName; });
3022 name != std::cend(columns)) {
3023 m_columnManager->setValue(m_xColumn, columns.indexOf(*name));
3024 }
3025 }
3026 if (!yName.isEmpty()) {
3027 m_columnManager->setValue(m_yColumn, columns.indexOf(yName));
3028 } else {
3029 if (auto name = std::find_if(std::cbegin(columns), std::cend(columns), [&](const auto x) { return x != xName; });
3030 name != std::cend(columns)) {
3031 m_columnManager->setValue(m_yColumn, columns.indexOf(*name));
3032 }
3033 }
3034 columns.prepend("");
3035 m_columnManager->setEnumNames(m_errColumn, columns);
3036 if (!errName.isEmpty()) {
3037 m_columnManager->setValue(m_errColumn, columns.indexOf(errName));
3038 } else {
3039 m_columnManager->setValue(m_errColumn, 0);
3040 }
3041 return;
3042 }
3043}
3044
3046 if (m_browser->isItemVisible(m_settingsGroup)) {
3047 if (!m_settingsGroup->property()->subProperties().contains(m_workspaceIndex)) {
3048 m_settingsGroup->property()->insertSubProperty(m_workspaceIndex, m_workspace);
3049 }
3050 }
3051}
3052
3057
3062 if (m_browser->isItemVisible(m_settingsGroup)) {
3063 m_browser->setItemVisible(m_settingsGroup, false);
3064 } else {
3065 m_browser->setItemVisible(m_settingsGroup, true);
3066 }
3067}
3068
3073void FitPropertyBrowser::removePropertiesFromSettingsBrowser(const QStringList &propsToRemove) {
3074 // get settings properties
3075 QList<QtProperty *> props = m_settingsGroup->property()->subProperties();
3076 for (auto &prop : props) {
3077 if (propsToRemove.contains(prop->propertyName())) {
3078 m_settingsGroup->property()->removeSubProperty(prop);
3079 }
3080 }
3081}
3082
3084
3091 if (prop == m_xColumn) { // update startX and endX
3092 try {
3093 auto ws = Mantid::API::AnalysisDataService::Instance().retrieve(workspaceName());
3094 auto tws = std::dynamic_pointer_cast<Mantid::API::ITableWorkspace>(ws);
3095 if (!tws)
3096 return;
3097 int i = m_columnManager->value(m_xColumn);
3098 if (i < 0 || i >= static_cast<int>(tws->rowCount()) || tws->rowCount() == 0)
3099 return;
3100 auto col = tws->getColumn(static_cast<size_t>(i));
3101 const double startXVal = col->toDouble(0);
3102 const double endXVal = col->toDouble(tws->rowCount() - 1);
3103 m_doubleManager->setValue(m_startX, startXVal);
3104 m_doubleManager->setValue(m_endX, endXVal);
3105 } catch (...) {
3106 // do nothing
3107 }
3108 }
3109}
3110
3115 // delete old minimizer properties
3116 foreach (QtProperty *prop, m_minimizerProperties) {
3117 m_settingsGroup->property()->removeSubProperty(prop);
3118 }
3119
3120 // add new minimizer properties
3121 auto minzer = Mantid::API::FuncMinimizerFactory::Instance().createMinimizer(this->minimizer());
3122 const auto &properties = minzer->getProperties();
3123 for (auto property : properties) {
3124 QString propName = QString::fromStdString((*property).name());
3125 QtProperty *prop = nullptr;
3126 if (const auto prp = dynamic_cast<const Mantid::Kernel::PropertyWithValue<bool> *const>(property)) {
3127 prop = m_boolManager->addProperty(propName);
3128 bool val = *prp;
3129 m_boolManager->setValue(prop, val);
3130 } else if (const auto prp = dynamic_cast<const Mantid::Kernel::PropertyWithValue<double> *const>(property)) {
3131 prop = this->addDoubleProperty(propName);
3132 double val = *prp;
3133 m_doubleManager->setValue(prop, val);
3134 } else if (const auto prp = dynamic_cast<const Mantid::Kernel::PropertyWithValue<int> *const>(property)) {
3135 prop = m_intManager->addProperty(propName);
3136 int val = *prp;
3137 m_intManager->setValue(prop, val);
3138 } else if (const auto prp = dynamic_cast<const Mantid::Kernel::PropertyWithValue<size_t> *const>(property)) {
3139 prop = m_intManager->addProperty(propName);
3140 size_t val = *prp;
3141 m_intManager->setValue(prop, static_cast<int>(val));
3142 } else if (const auto prp = dynamic_cast<const Mantid::Kernel::PropertyWithValue<std::string> *const>(property)) {
3143 prop = m_stringManager->addProperty(propName);
3144 QString val = QString::fromStdString(prp->value());
3145 m_stringManager->setValue(prop, val);
3146 } else if (dynamic_cast<Mantid::API::IWorkspaceProperty *>(property)) {
3147 prop = m_stringManager->addProperty(propName);
3148 m_stringManager->setValue(prop, QString::fromStdString((*property).value()));
3149 } else {
3150 QMessageBox::warning(this, "Mantid - Error",
3151 "Type of minimizer's property " + propName + " is not yet supported by the browser.");
3152 continue;
3153 }
3154
3155 if (!prop)
3156 continue;
3157 // set the tooltip from property doc string
3158 QString toolTip = QString::fromStdString((*property).documentation());
3159 if (!toolTip.isEmpty()) {
3160 prop->setToolTip(toolTip);
3161 }
3162 m_settingsGroup->property()->addSubProperty(prop);
3163 m_minimizerProperties.append(prop);
3164 }
3165}
3166
3171 auto fun = theFunction();
3172 size_t np = fun->nParams();
3173 QList<double> out;
3174 for (size_t i = 0; i < np; ++i) {
3175 const double parValue = fun->getParameter(i);
3176 out.append(parValue);
3177 }
3178 return out;
3179}
3180
3185 auto fun = theFunction();
3186 size_t np = fun->nParams();
3187 QStringList out;
3188 for (size_t i = 0; i < np; ++i) {
3189 std::string parName = fun->parameterName(i);
3190 out.append(QString::fromStdString(parName));
3191 }
3192 return out;
3193}
3198
3203
3208 const PropertyHandler *const handler = currentHandler();
3209 if (handler) {
3211 }
3212}
3213
3218 MantidQt::API::HelpWindow::showPage(QStringLiteral("workbench/plotwindow.html"));
3219}
3220
3227 if (m_fitActionSeqFit) {
3228 if (allow) {
3229 m_fitActionSeqFit->setEnabled(m_compositeFunction->nFunctions() > 0);
3230 } else {
3231 m_fitActionSeqFit->setEnabled(false);
3232 }
3233 }
3234}
3235
3236void FitPropertyBrowser::modifyFitMenu(QAction *fitAction, bool enabled) {
3237 if (enabled) {
3238 m_fitMenu->addAction(fitAction);
3239 } else {
3240 m_fitMenu->removeAction(fitAction);
3241 }
3242}
3243
3245 return m_functionsGroup->children().size();
3246}
3247
3248void FitPropertyBrowser::addAllowedSpectra(const QString &wsName, const QList<int> &wsSpectra) {
3249 auto const name = wsName.toStdString();
3250 auto ws = AnalysisDataService::Instance().retrieveWS<MatrixWorkspace>(name);
3251 if (ws) {
3252 QList<int> indices;
3253 indices.reserve(wsSpectra.size());
3254 std::transform(wsSpectra.cbegin(), wsSpectra.cend(), std::back_inserter(indices),
3255 [&ws](const auto i) { return static_cast<int>(ws->getIndexFromSpectrumNumber(i)); });
3256
3257 auto wsFound = m_allowedSpectra.find(wsName);
3258 m_allowedSpectra.insert(wsName, indices);
3259 if (wsFound != m_allowedSpectra.end()) {
3260 // we already knew about this workspace
3261 // update workspace index list
3263 } else {
3264 // new workspace, update workspace names
3266 }
3267 } else {
3268 throw std::runtime_error("Workspace " + name + " is not a MatrixWorkspace");
3269 }
3270}
3271
3272void FitPropertyBrowser::removeWorkspaceAndSpectra(const std::string &wsName) {
3273 removeWorkspace(wsName);
3274 // remove spectra
3275 QString qWsName = QString::fromStdString(wsName);
3276 m_allowedSpectra.erase(m_allowedSpectra.find(qWsName));
3277}
3278
3280 auto const name = wsName.toStdString();
3281 auto ws = AnalysisDataService::Instance().retrieveWS<ITableWorkspace>(name);
3282 if (ws) {
3283 m_allowedTableWorkspace = wsName;
3284 } else {
3285 throw std::runtime_error("Workspace " + name + " is not a TableWorkspace");
3286 }
3287}
3288
3297QString FitPropertyBrowser::addFunction(const QString &fnName) {
3298 return addFunction(fnName.toStdString())->functionPrefix();
3299}
3300
3302 const std::unique_ptr<FindPeakStrategyGeneric> &findPeakStrategy) {
3303 bool validFn = false;
3304 auto f = std::dynamic_pointer_cast<Mantid::API::IPeakFunction>(
3305 Mantid::API::FunctionFactory::Instance().createFunction(defaultPeakType()));
3306 if (f) {
3307 validFn = true;
3308 f->setMatrixWorkspace(inputWS, workspaceIndex(), startX(), endX());
3309 f->setCentre(findPeakStrategy->getPeakCentre(peakIndex));
3310 f->setFwhm(findPeakStrategy->getPeakWidth(peakIndex));
3311 f->setHeight(findPeakStrategy->getPeakHeight(peakIndex));
3312 addFunction(f->asString());
3313 }
3314 return validFn;
3315}
3316
3318 if (prefix.isEmpty())
3319 throw std::runtime_error("Peak function prefix cannot be empty");
3320 auto const indexList = prefix.split(".");
3321 auto const n = indexList.size() - 1;
3322 auto const *handler = getHandler();
3323 for (int i = 0; i < n; ++i) {
3324 auto const index = indexList[i].mid(1).toInt();
3325 handler = handler->getHandler(index);
3326 }
3327 return handler->getHandler(indexList[n].mid(1).toInt());
3328}
3329
3330void FitPropertyBrowser::setPeakCentreOf(const QString &prefix, double value) {
3331 auto handler = getPeakHandler(prefix);
3332 handler->setCentre(value);
3333 handler->updateParameters();
3334}
3335
3336double FitPropertyBrowser::getPeakCentreOf(const QString &prefix) {
3337 const auto *handler = getPeakHandler(prefix);
3338 return handler->centre();
3339}
3340
3341void FitPropertyBrowser::setPeakHeightOf(const QString &prefix, double value) {
3342 auto handler = getPeakHandler(prefix);
3343 handler->setHeight(value);
3344 handler->updateParameters();
3345}
3346
3347double FitPropertyBrowser::getPeakHeightOf(const QString &prefix) {
3348 const auto *handler = getPeakHandler(prefix);
3349 return handler->height();
3350}
3351
3352void FitPropertyBrowser::setPeakFwhmOf(const QString &prefix, double value) {
3353 auto handler = getPeakHandler(prefix);
3354 handler->setFwhm(value);
3355 handler->updateParameters();
3356}
3357
3358double FitPropertyBrowser::getPeakFwhmOf(const QString &prefix) {
3359 const auto *handler = getPeakHandler(prefix);
3360 return handler->fwhm();
3361}
3362
3363std::string FitPropertyBrowser::getWidthParameterNameOf(const QString &prefix) {
3364 const auto *handler = getPeakHandler(prefix);
3365 return handler->getWidthParameterName();
3366}
3367
3368std::string FitPropertyBrowser::getCentreParameterNameOf(const QString &prefix) {
3369 const auto *handler = getPeakHandler(prefix);
3370 return handler->getCentreParameterName();
3371}
3372
3373bool FitPropertyBrowser::isParameterExplicitlySetOf(const QString &prefix, const std::string &param) {
3374 const auto *handler = getPeakHandler(prefix);
3375 return handler->isParameterExplicitlySet(param);
3376}
3377
3379 QStringList peaks;
3380 const auto *parentHandler = getHandler();
3381 const auto nFunctions = parentHandler->cfun()->nFunctions();
3382 for (size_t i = 0; i < nFunctions; ++i) {
3383 const auto *handler = parentHandler->getHandler(i);
3384 if (handler->pfun()) {
3385 peaks << handler->functionPrefix();
3386 }
3387 }
3388 return peaks;
3389}
3390
3391} // namespace MantidWidgets
3392} // 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 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