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 +
14
26#include "MantidAPI/TableRow.h"
29
31#include "MantidKernel/Logger.h"
32
33#include "MantidQtWidgets/Common/QtPropertyBrowser/FilenameDialogEditor.h"
34#include "MantidQtWidgets/Common/QtPropertyBrowser/FormulaDialogEditor.h"
35#include "MantidQtWidgets/Common/QtPropertyBrowser/StringEditorFactory.h"
36
37#include "MantidQtWidgets/Common/QtPropertyBrowser/DoubleEditorFactory.h"
38#include "MantidQtWidgets/Common/QtPropertyBrowser/ParameterPropertyManager.h"
39#include "MantidQtWidgets/Common/QtPropertyBrowser/qteditorfactory.h"
40#include "MantidQtWidgets/Common/QtPropertyBrowser/qttreepropertybrowser.h"
41
42#include <Poco/ActiveResult.h>
43
44#include <QApplication>
45#include <QClipboard>
46#include <QGridLayout>
47#include <QInputDialog>
48#include <QListWidget>
49#include <QMenu>
50#include <QMessageBox>
51#include <QPushButton>
52#include <QSettings>
53#include <QSignalMapper>
54#include <QTreeWidget>
55#include <QUrl>
56#include <QVBoxLayout>
57
58#include <algorithm>
59#include <utility>
60
61namespace MantidQt {
62using API::MantidDesktopServices;
63
64namespace MantidWidgets {
65
66namespace {
67Mantid::Kernel::Logger g_log("FitPropertyBrowser");
68
69using namespace Mantid::API;
70
71int getNumberOfSpectra(const MatrixWorkspace_sptr &workspace) {
72 return static_cast<int>(workspace->getNumberHistograms());
73}
74} // namespace
75
81FitPropertyBrowser::FitPropertyBrowser(QWidget *parent, QObject *mantidui)
82 : QDockWidget("Fit Function", parent), m_workspaceIndex(nullptr), m_startX(nullptr), m_endX(nullptr),
83 m_output(nullptr), m_minimizer(nullptr), m_ignoreInvalidData(nullptr), m_costFunction(nullptr),
84 m_maxIterations(nullptr), m_peakRadius(nullptr), m_plotDiff(nullptr), m_excludeRange(nullptr),
85 m_plotCompositeMembers(nullptr), m_convolveMembers(nullptr), m_rawData(nullptr), m_xColumn(nullptr),
86 m_yColumn(nullptr), m_errColumn(nullptr), m_showParamErrors(nullptr), m_evaluationType(nullptr),
87 m_compositeFunction(), m_browser(nullptr), m_fitActionUndoFit(nullptr), m_fitActionSeqFit(nullptr),
88 m_fitActionFit(nullptr), m_fitActionEvaluate(nullptr), m_functionsGroup(nullptr), m_settingsGroup(nullptr),
89 m_customSettingsGroup(nullptr), m_changeSlotsEnabled(false), m_guessOutputName(true),
90 m_updateObserver(*this, &FitPropertyBrowser::handleFactoryUpdate), m_fitMapper(nullptr), m_fitMenu(nullptr),
91 m_displayActionPlotGuess(nullptr), m_displayActionQuality(nullptr), m_displayActionClearAll(nullptr),
92 m_setupActionCustomSetup(nullptr), m_setupActionRemove(nullptr), m_tip(nullptr), m_fitSelector(nullptr),
93 m_fitTree(nullptr), m_currentHandler(nullptr), m_defaultFunction("Gaussian"), m_defaultPeak("Gaussian"),
94 m_defaultBackground("LinearBackground"), m_peakToolOn(false), m_hideWsListWidget(false), m_auto_back(false),
95 m_autoBgName(
96 QString::fromStdString(Mantid::Kernel::ConfigService::Instance().getString("curvefitting.autoBackground"))),
97 m_autoBackground(nullptr), m_decimals(-1), m_mantidui(mantidui), m_shouldBeNormalised(false),
98 m_fitAlgParameters(""), m_oldWorkspaceIndex(-1) {
99 Mantid::API::FrameworkManager::Instance().loadPlugins();
100
101 // If Gaussian does not exist then the plugins did not load.
102 if (!Mantid::API::FunctionFactory::Instance().exists("Gaussian")) {
103 throw std::runtime_error("FitPropertyBrowser: Unable to find Gaussian function\n"
104 "Has the CurveFitting plugin loaded?");
105 }
106 if (m_autoBgName.toLower() == "none") {
107 m_autoBgName = "";
108 } else {
110 }
111
112 std::string def = Mantid::Kernel::ConfigService::Instance().getString("curvefitting.defaultPeak");
113 if (!def.empty()) {
114 m_defaultPeak = def;
115 }
116
117 def = Mantid::Kernel::ConfigService::Instance().getString("curvefitting.autoBackground");
118 if (!def.empty()) {
120 }
122
123 setObjectName("FitFunction"); // this is needed for QMainWindow::restoreState()
124 setMinimumHeight(150);
125 setMinimumWidth(200);
126
127 QWidget *w = new QWidget(this);
128
129 /* Create property managers: they create, own properties, get and set values
130 */
131 m_groupManager = new QtGroupPropertyManager(w);
132 m_doubleManager = new QtDoublePropertyManager(w);
133 m_stringManager = new QtStringPropertyManager(w);
134 m_enumManager = new QtEnumPropertyManager(w);
135 m_intManager = new QtIntPropertyManager(w);
136 m_boolManager = new QtBoolPropertyManager(w);
137 m_filenameManager = new QtStringPropertyManager(w);
138 m_formulaManager = new QtStringPropertyManager(w);
139 m_columnManager = new QtEnumPropertyManager(w);
140 m_workspace = m_enumManager->addProperty("Workspace");
141 m_vectorManager = new QtGroupPropertyManager(w);
142 m_vectorSizeManager = new QtIntPropertyManager(w);
143 m_vectorDoubleManager = new QtDoublePropertyManager(w);
144 m_parameterManager = new ParameterPropertyManager(w);
145}
146
151 QWidget *w = new QWidget(this);
152
153 QSettings settings;
154 settings.beginGroup("Mantid/FitBrowser");
155
156 /* Create function group */
157 QtProperty *functionsGroup = m_groupManager->addProperty("Functions");
158
159 if (m_mantidui) {
160 connect(this, SIGNAL(xRangeChanged(double, double)), m_mantidui, SLOT(x_range_from_picker(double, double)));
161 }
162 /* Create input - output properties */
163 QtProperty *settingsGroup = m_groupManager->addProperty("Settings");
164 m_startX = addDoubleProperty("StartX");
165 m_endX = addDoubleProperty("EndX");
166
167 m_workspaceIndex = m_intManager->addProperty("Workspace Index");
168 m_output = m_stringManager->addProperty("Output");
169 m_minimizer = m_enumManager->addProperty("Minimizer");
170 m_minimizers << "Levenberg-Marquardt"
171 << "Levenberg-MarquardtMD"
172 << "Trust Region"
173 << "Simplex"
174 << "FABADA"
175 << "Conjugate gradient (Fletcher-Reeves imp.)"
176 << "Conjugate gradient (Polak-Ribiere imp.)"
177 << "BFGS"
178 << "Damped GaussNewton";
179
180 m_ignoreInvalidData = m_boolManager->addProperty("Ignore invalid data");
181 setIgnoreInvalidData(settings.value("Ignore invalid data", false).toBool());
182
183 m_enumManager->setEnumNames(m_minimizer, m_minimizers);
184 m_costFunction = m_enumManager->addProperty("Cost function");
185 m_costFunctions << "Least squares"
186 << "Rwp"
187 << "Unweighted least squares"
188 << "Poisson";
190 m_maxIterations = m_intManager->addProperty("Max Iterations");
191 m_intManager->setValue(m_maxIterations, settings.value("Max Iterations", 500).toInt());
192
193 m_peakRadius = m_intManager->addProperty("Peak Radius");
194 m_intManager->setValue(m_peakRadius, settings.value("Peak Radius", 0).toInt());
195
196 m_plotDiff = m_boolManager->addProperty("Plot Difference");
197 bool plotDiffSetting = settings.value("Plot Difference", QVariant(true)).toBool();
198 m_boolManager->setValue(m_plotDiff, plotDiffSetting);
199
200 m_excludeRange = m_stringManager->addProperty("Exclude Range");
201 m_excludeRange->setToolTip("A list of pairs of real numbers which define the region to exclude");
202
203 m_plotCompositeMembers = m_boolManager->addProperty("Plot Composite Members");
204 bool plotCompositeItems = settings.value(m_plotCompositeMembers->propertyName(), QVariant(false)).toBool();
205 m_boolManager->setValue(m_plotCompositeMembers, plotCompositeItems);
206
207 m_convolveMembers = m_boolManager->addProperty("Convolve Composite Members");
208 bool convolveCompositeItems = settings.value(m_plotCompositeMembers->propertyName(), QVariant(false)).toBool();
209 m_boolManager->setValue(m_convolveMembers, convolveCompositeItems);
210
211 m_showParamErrors = m_boolManager->addProperty("Show Parameter Errors");
212 bool showParamErrors = settings.value(m_showParamErrors->propertyName(), false).toBool();
213 m_boolManager->setValue(m_showParamErrors, showParamErrors);
214 m_parameterManager->setErrorsEnabled(showParamErrors);
215
216 m_evaluationType = m_enumManager->addProperty("Evaluate Function As");
217 m_evaluationType->setToolTip("Consider using Histogram fit which may produce more accurate results.");
218 m_evaluationTypes << "CentrePoint"
219 << "Histogram";
221 int evaluationType = settings.value(m_evaluationType->propertyName(), 0).toInt();
222 m_enumManager->setValue(m_evaluationType, evaluationType);
223
224 m_xColumn = m_columnManager->addProperty("XColumn");
225 m_yColumn = m_columnManager->addProperty("YColumn");
226 m_errColumn = m_columnManager->addProperty("ErrColumn");
227
228 settingsGroup->addSubProperty(m_workspace);
229 settingsGroup->addSubProperty(m_startX);
230 settingsGroup->addSubProperty(m_endX);
231
232 // Only include the cost function when in the dock widget inside mantid plot,
233 // not on muon analysis widget
234 // Include minimiser and plot difference under a different settings section.
235 settingsGroup->addSubProperty(m_output);
236 settingsGroup->addSubProperty(m_minimizer);
237 settingsGroup->addSubProperty(m_ignoreInvalidData);
238 settingsGroup->addSubProperty(m_costFunction);
239 settingsGroup->addSubProperty(m_maxIterations);
240 settingsGroup->addSubProperty(m_peakRadius);
241 settingsGroup->addSubProperty(m_plotDiff);
242 settingsGroup->addSubProperty(m_excludeRange);
243 settingsGroup->addSubProperty(m_plotCompositeMembers);
244 settingsGroup->addSubProperty(m_convolveMembers);
245 settingsGroup->addSubProperty(m_showParamErrors);
246 settingsGroup->addSubProperty(m_evaluationType);
247
248 /* Create editors and assign them to the managers */
249 createEditors(w);
250
252
253 m_functionsGroup = m_browser->addProperty(functionsGroup);
254 m_settingsGroup = m_browser->addProperty(settingsGroup);
255
256 initLayout(w);
257}
258
269
279 auto *btnFit = new QPushButton("Fit");
280 m_tip = new QLabel("", w);
281
282 m_fitMapper = new QSignalMapper(this);
283 m_fitMenu = new QMenu(this);
285 connect(m_fitMapper, SIGNAL(mappedString(const QString &)), this, SLOT(executeFitMenu(const QString &)));
286 btnFit->setMenu(m_fitMenu);
287 return btnFit;
288}
289
298void FitPropertyBrowser::populateFitMenuButton(QSignalMapper *fitMapper, QMenu *fitMenu) {
299 // assert(fitmapper);
300
301 m_fitActionFit = new QAction("Fit", this);
302 m_fitActionSeqFit = new QAction("Sequential Fit", this);
303 m_fitActionUndoFit = new QAction("Undo Fit", this);
304 m_fitActionEvaluate = new QAction("Evaluate function", this);
305
306 fitMapper->setMapping(m_fitActionFit, "Fit");
307 fitMapper->setMapping(m_fitActionSeqFit, "SeqFit");
308 fitMapper->setMapping(m_fitActionUndoFit, "UndoFit");
309 fitMapper->setMapping(m_fitActionEvaluate, "Evaluate");
310
311 connect(m_fitActionFit, SIGNAL(triggered()), fitMapper, SLOT(map()));
312 connect(m_fitActionSeqFit, SIGNAL(triggered()), fitMapper, SLOT(map()));
313 connect(m_fitActionUndoFit, SIGNAL(triggered()), fitMapper, SLOT(map()));
314 connect(m_fitActionEvaluate, SIGNAL(triggered()), fitMapper, SLOT(map()));
315
316 fitMenu->addAction(m_fitActionFit);
317 fitMenu->addAction(m_fitActionSeqFit);
318 fitMenu->addAction(m_fitActionEvaluate);
319 fitMenu->addSeparator();
320 fitMenu->addAction(m_fitActionUndoFit);
321 fitMenu->addSeparator();
322}
333 QPushButton *btnFit = createFitMenuButton(w);
334 btnFit->setObjectName("button_Fit");
335 // to be able to change windows title from tread
336 connect(this, SIGNAL(changeWindowTitle(const QString &)), this, SLOT(setWindowTitle(const QString &)));
337
338 /* Create the top level group */
339
340 m_groupManager->addProperty("Fit");
341
342 connect(m_enumManager, SIGNAL(propertyChanged(QtProperty *)), this, SLOT(enumChanged(QtProperty *)));
343 connect(m_boolManager, SIGNAL(propertyChanged(QtProperty *)), this, SLOT(boolChanged(QtProperty *)));
344 connect(m_intManager, SIGNAL(propertyChanged(QtProperty *)), this, SLOT(intChanged(QtProperty *)));
345 connect(m_doubleManager, SIGNAL(propertyChanged(QtProperty *)), this, SLOT(doubleChanged(QtProperty *)));
346 connect(m_stringManager, SIGNAL(propertyChanged(QtProperty *)), this, SLOT(stringChanged(QtProperty *)));
347 connect(m_filenameManager, SIGNAL(propertyChanged(QtProperty *)), this, SLOT(stringChanged(QtProperty *)));
348 connect(m_formulaManager, SIGNAL(propertyChanged(QtProperty *)), this, SLOT(stringChanged(QtProperty *)));
349 connect(m_columnManager, SIGNAL(propertyChanged(QtProperty *)), this, SLOT(columnChanged(QtProperty *)));
350 connect(m_vectorDoubleManager, SIGNAL(propertyChanged(QtProperty *)), this, SLOT(vectorDoubleChanged(QtProperty *)));
351 connect(m_parameterManager, SIGNAL(propertyChanged(QtProperty *)), this, SLOT(parameterChanged(QtProperty *)));
352 connect(m_vectorSizeManager, SIGNAL(propertyChanged(QtProperty *)), this, SLOT(vectorSizeChanged(QtProperty *)));
353
354 auto *layout = new QVBoxLayout(w);
355 layout->setObjectName("vlayout");
356 auto *buttonsLayout = new QGridLayout();
357
358 auto *btnDisplay = new QPushButton("Display");
359 btnDisplay->setObjectName("button_Display");
360 QMenu *displayMenu = new QMenu(this);
361 displayMenu->setObjectName("menu_Display");
362 m_displayActionPlotGuess = new QAction("Plot Guess", this);
363 m_displayActionPlotGuess->setEnabled(false);
364 m_displayActionQuality = new QAction("Quality", this);
365 m_displayActionQuality->setObjectName("action_Quality");
366 m_displayActionQuality->setCheckable(true);
367 m_displayActionQuality->setChecked(true);
368 m_displayActionClearAll = new QAction("Clear fit curves", this);
369 QSignalMapper *displayMapper = new QSignalMapper(this);
370 displayMapper->setObjectName("mapper_Display");
371
372 displayMapper->setMapping(m_displayActionPlotGuess, "PlotGuess");
373 displayMapper->setMapping(m_displayActionQuality, "Quality");
374 displayMapper->setMapping(m_displayActionClearAll, "ClearAll");
375 connect(m_displayActionPlotGuess, SIGNAL(triggered()), displayMapper, SLOT(map()));
376 connect(m_displayActionQuality, SIGNAL(triggered()), displayMapper, SLOT(map()));
377 connect(m_displayActionClearAll, SIGNAL(triggered()), displayMapper, SLOT(map()));
378 connect(displayMapper, SIGNAL(mappedString(const QString &)), this, SLOT(executeDisplayMenu(const QString &)));
379 displayMenu->addAction(m_displayActionPlotGuess);
380 displayMenu->addAction(m_displayActionClearAll);
381 displayMenu->addAction(m_displayActionQuality);
382 btnDisplay->setMenu(displayMenu);
383
384 auto *btnSetup = new QPushButton("Setup");
385 btnSetup->setObjectName("button_Setup");
386 QMenu *setupMenu = new QMenu(this);
387 setupMenu->setObjectName("menu_Setup");
388
389 m_setupActionCustomSetup = new QAction("Custom Setup", this);
390 QAction *setupActionManageSetup = new QAction("Manage Setup", this);
391 setupActionManageSetup->setObjectName("action_ManageSetup");
392 QAction *setupActionPeakFindingAlgs = new QAction("Peak Finding Algorithms", this);
393 setupActionPeakFindingAlgs->setObjectName("action_PeakFindingAlgs");
394 QAction *setupActionFindPeaks = new QAction("Find Peaks", this);
395 setupActionFindPeaks->setObjectName("action_FindPeaks");
396 QAction *setupActionFindPeaksConvolve = new QAction("Find Peaks Convolve", this);
397 setupActionFindPeaksConvolve->setObjectName("action_FindPeaksConvolve");
398 QAction *setupActionClearFit = new QAction("Clear Model", this);
399 setupActionClearFit->setObjectName("action_ClearModel");
400
401 QMenu *setupSubMenuCustom = new QMenu(this);
402 m_setupActionCustomSetup->setMenu(setupSubMenuCustom);
403 // empty menu for now, so set it disabled to avoid confusing users
404 m_setupActionCustomSetup->setEnabled(false);
405
406 QMenu *setupSubMenuManage = new QMenu(this);
407 QAction *setupActionSave = new QAction("Save Setup", this);
408 m_setupActionRemove = new QAction("Remove Setup", this);
409 QAction *setupActionClear = new QAction("Clear Setups", this);
410 setupActionClear->setObjectName("action_ClearSetups");
411 QAction *setupActionCopyToClipboard = new QAction("Copy To Clipboard", this);
412 setupActionCopyToClipboard->setObjectName("action_CopyToClipboard");
413 QAction *setupActionLoadFromString = new QAction("Load From String", this);
414 setupActionLoadFromString->setObjectName("action_LoadFromString");
415 QSignalMapper *setupManageMapper = new QSignalMapper(this);
416 setupManageMapper->setMapping(setupActionSave, "SaveSetup");
417 setupManageMapper->setMapping(setupActionCopyToClipboard, "CopyToClipboard");
418 setupManageMapper->setMapping(setupActionLoadFromString, "LoadFromString");
419 setupManageMapper->setMapping(setupActionClear, "ClearSetups");
420 connect(setupActionSave, SIGNAL(triggered()), setupManageMapper, SLOT(map()));
421 connect(setupActionCopyToClipboard, SIGNAL(triggered()), setupManageMapper, SLOT(map()));
422 connect(setupActionLoadFromString, SIGNAL(triggered()), setupManageMapper, SLOT(map()));
423 connect(setupActionClear, SIGNAL(triggered()), setupManageMapper, SLOT(map()));
424 connect(setupManageMapper, SIGNAL(mappedString(const QString &)), this,
425 SLOT(executeSetupManageMenu(const QString &)));
426 setupSubMenuManage->addAction(setupActionSave);
427 setupSubMenuManage->addAction(m_setupActionRemove);
428 setupSubMenuManage->addAction(setupActionClear);
429 setupSubMenuManage->addAction(setupActionCopyToClipboard);
430 setupSubMenuManage->addAction(setupActionLoadFromString);
431 setupActionManageSetup->setMenu(setupSubMenuManage);
432
433 QMenu *setupSubMenuRemove = new QMenu(this);
434 m_setupActionRemove->setMenu(setupSubMenuRemove);
435 // empty menu for now, so set it disabled to avoid confusing users
436 m_setupActionRemove->setEnabled(false);
437
438 QSignalMapper *PeakFindingAlgMapper = new QSignalMapper(this);
439 PeakFindingAlgMapper->setMapping(setupActionFindPeaks, "FindPeaks");
440 PeakFindingAlgMapper->setMapping(setupActionFindPeaksConvolve, "FindPeaksConvolve");
441 connect(setupActionFindPeaks, SIGNAL(triggered()), PeakFindingAlgMapper, SLOT(map()));
442 connect(setupActionFindPeaksConvolve, SIGNAL(triggered()), PeakFindingAlgMapper, SLOT(map()));
443 connect(PeakFindingAlgMapper, SIGNAL(mappedString(const QString &)), this,
444 SLOT(executePeakFindingAlgMenu(const QString &)));
445
446 QSignalMapper *setupMapper = new QSignalMapper(this);
447 setupMapper->setMapping(setupActionClearFit, "ClearFit");
448 connect(setupActionClearFit, SIGNAL(triggered()), setupMapper, SLOT(map()));
449 connect(setupMapper, SIGNAL(mappedString(const QString &)), this, SLOT(executeSetupMenu(const QString &)));
450
451 QMenu *setupSubMenuPeakFindingAgls = new QMenu(this);
452 setupSubMenuPeakFindingAgls->addAction(setupActionFindPeaks);
453 setupSubMenuPeakFindingAgls->addAction(setupActionFindPeaksConvolve);
454 setupActionPeakFindingAlgs->setMenu(setupSubMenuPeakFindingAgls);
455
456 setupMenu->addAction(m_setupActionCustomSetup);
457 setupMenu->addAction(setupActionManageSetup);
458 setupMenu->addSeparator();
459 setupMenu->addAction(setupActionPeakFindingAlgs);
460 setupMenu->addSeparator();
461 setupMenu->addAction(setupActionClearFit);
462 btnSetup->setMenu(setupMenu);
463
465
466 buttonsLayout->addWidget(btnFit, 0, 0);
467 buttonsLayout->addWidget(btnDisplay, 0, 1);
468 buttonsLayout->addWidget(btnSetup, 0, 2);
469
470 m_status = new QLabel("Status:", w);
471 m_status->hide();
472 connect(this, SIGNAL(fitResultsChanged(const QString &)), this, SLOT(showFitResultStatus(const QString &)),
473 Qt::QueuedConnection);
474 layout->addWidget(m_status);
475 layout->addLayout(buttonsLayout);
476 layout->addWidget(m_tip);
477 layout->addWidget(m_browser);
478 m_browser->setObjectName("tree_browser");
479
480 m_workspaceLabel = new QLabel("Workspaces");
481 layout->addWidget(m_workspaceLabel);
482 m_wsListWidget = new QListWidget();
483 layout->addWidget(m_wsListWidget);
484 m_workspaceLabel->hide();
485 m_wsListWidget->hide();
486
487 setWidget(w);
488
489 m_browser->setContextMenuPolicy(Qt::CustomContextMenu);
490 connect(m_browser, SIGNAL(customContextMenuRequested(const QPoint &)), this, SLOT(popupMenu(const QPoint &)));
491 connect(m_browser, SIGNAL(currentItemChanged(const QtBrowserItem *)), this,
492 SLOT(currentItemChanged(const QtBrowserItem *)));
493 connect(this, SIGNAL(multifitFinished()), this, SLOT(processMultiBGResults()));
494
495 connect(m_wsListWidget, SIGNAL(itemDoubleClicked(QListWidgetItem *)), this,
496 SLOT(workspaceDoubleClicked(QListWidgetItem *)));
497
499
500 // Update tooltips when function structure is (or might've been) changed in
501 // any way
502 connect(this, SIGNAL(functionChanged()), SLOT(updateStructureTooltips()));
503 connect(this, SIGNAL(functionChanged()), SLOT(clearFitResultStatus()));
504
505 // Update available functions in this fit property browser, when the function
506 // factory changes.
508 FunctionFactory::Instance().notificationCenter.addObserver(m_updateObserver);
509 connect(this, SIGNAL(functionFactoryUpdateReceived()), this, SLOT(populateFunctionNames()));
510 FunctionFactory::Instance().enableNotifications();
511
512 // Initial call, as function is not changed when it's created for the first
513 // time
515
517
519}
520
521// Adds the fit result workspaces to the qlistwidget in the browser
523 const auto outName = outputName();
524 const std::vector<std::string> workspaceNames{outName + "_NormalisedCovarianceMatrix", outName + "_Parameters",
525 outName + "_Workspace"};
526
527 for (const auto &name : workspaceNames) {
528 // check if already in the list
529 auto foundInList = m_wsListWidget->findItems(QString::fromStdString(name), Qt::MatchExactly);
530 if (foundInList.size() == 0 && AnalysisDataService::Instance().doesExist(name)) {
531 new QListWidgetItem(QString::fromStdString(name), m_wsListWidget);
532 }
533 }
534
535 auto noOfItems = m_wsListWidget->count();
536 if (noOfItems != 0 && !m_hideWsListWidget) {
537 auto widgetHeight = m_wsListWidget->sizeHintForRow(0) * (noOfItems + 1) + 2 * m_wsListWidget->frameWidth();
538 m_wsListWidget->setMaximumHeight(widgetHeight);
539 m_workspaceLabel->show();
540 m_wsListWidget->show();
541 }
542}
543
545 auto wsName = item->text();
546 emit workspaceClicked(wsName);
547}
548
557 QtCheckBoxFactory *checkBoxFactory = new QtCheckBoxFactory(w);
558 QtEnumEditorFactory *comboBoxFactory = new QtEnumEditorFactory(w);
559 QtSpinBoxFactory *spinBoxFactory = new QtSpinBoxFactory(w);
560 DoubleEditorFactory *doubleEditorFactory = new DoubleEditorFactory(w);
561 StringEditorFactory *stringEditFactory = new StringEditorFactory(w);
562 FilenameDialogEditorFactory *filenameDialogEditorFactory = new FilenameDialogEditorFactory(w);
563 FormulaDialogEditorFactory *formulaDialogEditFactory = new FormulaDialogEditorFactory(w);
564
565 m_browser = new QtTreePropertyBrowser();
566 m_browser->setFactoryForManager(m_enumManager, comboBoxFactory);
567 m_browser->setFactoryForManager(m_boolManager, checkBoxFactory);
568 m_browser->setFactoryForManager(m_intManager, spinBoxFactory);
569 m_browser->setFactoryForManager(m_doubleManager, doubleEditorFactory);
570 m_browser->setFactoryForManager(m_stringManager, stringEditFactory);
571 m_browser->setFactoryForManager(m_filenameManager, filenameDialogEditorFactory);
572 m_browser->setFactoryForManager(m_formulaManager, formulaDialogEditFactory);
573 m_browser->setFactoryForManager(m_columnManager, comboBoxFactory);
574 m_browser->setFactoryForManager(m_vectorSizeManager, spinBoxFactory);
575 m_browser->setFactoryForManager(m_vectorDoubleManager, doubleEditorFactory);
576 m_browser->setFactoryForManager(m_parameterManager, new ParameterEditorFactory(w));
577}
578
582 QMenu *menuLoad = m_setupActionCustomSetup->menu();
583 menuLoad->clear();
584 QMenu *menuRemove = m_setupActionRemove->menu();
585 menuRemove->clear();
586
587 QSettings settings;
588 settings.beginGroup("Mantid/FitBrowser/SavedFunctions");
589 QStringList names = settings.childKeys();
590
591 QSignalMapper *mapperLoad = new QSignalMapper(this);
592 QSignalMapper *mapperRemove = new QSignalMapper(this);
593 // enable actions that open the menus only if there will be >=1 entries in
594 // there
595 m_setupActionCustomSetup->setEnabled(names.size() >= 1);
596 m_setupActionRemove->setEnabled(names.size() >= 1);
597 for (int i = 0; i < names.size(); i++) {
598 QAction *itemLoad = new QAction(names.at(i), this);
599 QAction *itemRemove = new QAction(names.at(i), this);
600 mapperLoad->setMapping(itemLoad, names.at(i));
601 mapperRemove->setMapping(itemRemove, names.at(i));
602 connect(itemLoad, SIGNAL(triggered()), mapperLoad, SLOT(map()));
603 connect(itemRemove, SIGNAL(triggered()), mapperRemove, SLOT(map()));
604 menuLoad->addAction(itemLoad);
605 menuRemove->addAction(itemRemove);
606 }
607 connect(mapperLoad, SIGNAL(mappedString(const QString &)), this, SLOT(executeCustomSetupLoad(const QString &)));
608 connect(mapperRemove, SIGNAL(mappedString(const QString &)), this, SLOT(executeCustomSetupRemove(const QString &)));
609}
610
612 QSettings settings;
613 settings.beginGroup("Mantid/FitBrowser/SavedFunctions");
614
615 QString str = settings.value(name).toString();
616 loadFunction(str);
617}
618
620 QSettings settings;
621 settings.beginGroup("Mantid/FitBrowser/SavedFunctions");
622
625}
626
628 QSettings settings;
629 settings.beginGroup("Mantid/FitBrowser/SavedFunctions");
630
631 settings.clear();
633}
634
639 // Call tooltip update func on the root handler - it goes down recursively
641}
642
643void FitPropertyBrowser::executeFitMenu(const QString &item) {
644 if (item == "Fit") {
645 fit();
646 } else if (item == "SeqFit") {
648 } else if (item == "UndoFit") {
649 undoFit();
650 } else if (item == "Evaluate") {
651 doFit(0);
652 }
653}
654
655void FitPropertyBrowser::executeDisplayMenu(const QString &item) {
656 if (item == "PlotGuess") {
658 } else if (item == "ClearAll") {
660 }
661}
662
664 if (item == "FindPeaks")
665 findPeaks(std::make_unique<FindPeakDefaultStrategy>());
666 if (item == "FindPeaksConvolve")
667 findPeaks(std::make_unique<FindPeakConvolveStrategy>());
668}
669
670void FitPropertyBrowser::executeSetupMenu(const QString &item) {
671 if (item == "ClearFit")
672 clear();
673}
674
676 if (item == "SaveSetup")
677 saveFunction();
678 if (item == "ClearSetups")
680 if (item == "CopyToClipboard")
681 copy();
682 if (item == "LoadFromString")
684}
685
688 m_compositeFunction.reset();
689
690 // remove the FunctionFactory Observer
692 FunctionFactory::Instance().notificationCenter.removeObserver(m_updateObserver);
693
694 m_browser->unsetFactoryForManager(m_enumManager);
695 m_browser->unsetFactoryForManager(m_boolManager);
696 m_browser->unsetFactoryForManager(m_intManager);
697 m_browser->unsetFactoryForManager(m_doubleManager);
698 m_browser->unsetFactoryForManager(m_stringManager);
699 m_browser->unsetFactoryForManager(m_filenameManager);
700 m_browser->unsetFactoryForManager(m_formulaManager);
701 m_browser->unsetFactoryForManager(m_columnManager);
702 m_browser->unsetFactoryForManager(m_vectorSizeManager);
703 m_browser->unsetFactoryForManager(m_vectorDoubleManager);
704 m_browser->unsetFactoryForManager(m_parameterManager);
705}
706
709 return static_cast<PropertyHandler *>(m_compositeFunction->getHandler());
710}
711
712PropertyHandler *FitPropertyBrowser::addFunction(const std::string &fnName, bool notify /*= true*/) {
713 PropertyHandler *h = getHandler()->addFunction(fnName);
714 if (notify) {
715 emit functionChanged();
716 }
717 return h;
718}
719
721 if (handler) {
722 emit functionRemoved();
723 emit functionChanged();
725 handler->removeFunction();
726 compositeFunction()->checkFunction();
727 }
728}
729
733 QtBrowserItem *ci = m_browser->currentItem();
734 // Find the function which has ci as its top browser item
735 auto cf = getHandler()->findCompositeFunction(ci);
736 if (!cf)
737 return;
738
739 // Declare new widget for picking fit functions
741
742 connect(m_fitSelector, SIGNAL(accepted()), this, SLOT(acceptFit()));
743 connect(m_fitSelector, SIGNAL(rejected()), this, SLOT(closeFit()));
744 m_fitSelector->show();
745}
746
748 QtBrowserItem *ci = m_browser->currentItem();
749 std::shared_ptr<const Mantid::API::CompositeFunction> cf = getHandler()->findCompositeFunction(ci);
750 if (!cf)
751 return;
752 auto function = m_fitSelector->getFunction();
753 if (function.isEmpty()) {
754 return;
755 }
757 h->addFunction(function.toStdString());
758 emit functionChanged();
759
760 closeFit();
761}
762
764
771 emit functionRemoved();
772 m_autoBackground = nullptr;
773 }
774 if (!func) {
776 } else {
777 auto cf = std::dynamic_pointer_cast<Mantid::API::CompositeFunction>(func);
778 if (!cf || (cf->name() != "CompositeFunction" && cf->name() != "MultiBG" && cf->name() != "MultiDomainFunction")) {
780 m_compositeFunction->addFunction(func);
781 } else {
783 }
784 }
786
787 auto h = std::make_unique<PropertyHandler>(m_compositeFunction, Mantid::API::CompositeFunction_sptr(), this);
788 m_compositeFunction->setHandler(std::move(h));
789 setCurrentFunction(static_cast<PropertyHandler *>(m_compositeFunction->getHandler()));
790
791 if (m_auto_back) {
793 }
794
795 disableUndo();
796 setFitEnabled(m_compositeFunction->nFunctions() > 0);
797 emit functionChanged();
798}
799
805 if (str.isEmpty()) {
807 } else {
808 auto f = tryCreateFitFunction(str);
809 if (f) {
811 } else {
813 }
814 }
815}
816
818 try {
819 return Mantid::API::FunctionFactory::Instance().createInitialized(str.toStdString());
820 } catch (const std::exception &ex) {
821 QMessageBox::critical(this, "Mantid - Error", "Unexpected exception caught:\n\n" + QString(ex.what()));
822 return nullptr;
823 }
824}
825
826void FitPropertyBrowser::popupMenu(const QPoint & /*unused*/) {
827 QtBrowserItem *ci = m_browser->currentItem();
828 if (!ci)
829 return;
830 QMenu *menu = new QMenu(this);
831 QAction *action;
832
833 bool isFunctionsGroup = ci == m_functionsGroup;
834 bool isSettingsGroup = ci == m_settingsGroup;
835 bool isASetting = ci->parent() == m_settingsGroup;
836 bool isFunction = getHandler()->findFunction(ci) != nullptr;
837 bool isCompositeFunction = isFunction && getHandler()->findCompositeFunction(ci);
838
839 PropertyHandler *h = getHandler()->findHandler(ci->property());
840
841 if (isFunctionsGroup) {
842 action = new QAction("Add function", this);
843 connect(action, SIGNAL(triggered()), this, SLOT(addFunction()));
844 menu->addAction(action);
845
846 if (m_compositeFunction->name() == "MultiBG" && m_compositeFunction->nFunctions() == 1 &&
847 Mantid::API::AnalysisDataService::Instance().doesExist(workspaceName())) {
848 action = new QAction("Setup multifit", this);
849 connect(action, SIGNAL(triggered()), this, SLOT(setupMultifit()));
850 menu->addAction(action);
851 }
852
853 if (m_peakToolOn) {
854 if (h && h->hasPlot()) {
855 action = new QAction("Remove plot", this);
856 connect(action, SIGNAL(triggered()), this, SLOT(removeGuessAll()));
857 menu->addAction(action);
858 } else {
859 action = new QAction("Plot", this);
860 connect(action, SIGNAL(triggered()), this, SLOT(plotGuessAll()));
861 menu->addAction(action);
862 }
863 }
864
865 menu->addSeparator();
866
867 action = new QAction("Save", this);
868 connect(action, SIGNAL(triggered()), this, SLOT(saveFunction()));
869 menu->addAction(action);
870
871 action = new QAction("Load", this);
872 connect(action, SIGNAL(triggered()), this, SLOT(loadFunction()));
873 menu->addAction(action);
874
875 action = new QAction("Copy To Clipboard", this);
876 connect(action, SIGNAL(triggered()), this, SLOT(copy()));
877 menu->addAction(action);
878
879 menu->addSeparator();
880
881 action = new QAction("Help", this);
882 connect(action, SIGNAL(triggered()), this, SLOT(browserHelp()));
883 menu->addAction(action);
884 } else if (isSettingsGroup || isASetting) {
885 if (isFitEnabled()) {
886 action = new QAction("Fit", this);
887 connect(action, SIGNAL(triggered()), this, SLOT(fit()));
888 menu->addAction(action);
889 }
890
891 if (isUndoEnabled()) {
892 action = new QAction("Undo Fit", this);
893 connect(action, SIGNAL(triggered()), this, SLOT(undoFit()));
894 menu->addAction(action);
895 }
896
897 action = new QAction("Clear all", this);
898 connect(action, SIGNAL(triggered()), this, SLOT(clear()));
899 menu->addAction(action);
900
901 action = new QAction("Help", this);
902 connect(action, SIGNAL(triggered()), this, SLOT(browserHelp()));
903 menu->addAction(action);
904
905 } else if (isFunction) {
906 if (isCompositeFunction) {
907 action = new QAction("Add function", this);
908 connect(action, SIGNAL(triggered()), this, SLOT(addFunction()));
909 menu->addAction(action);
910 }
911
912 action = new QAction("Remove", this);
913 connect(action, SIGNAL(triggered()), this, SLOT(deleteFunction()));
914 menu->addAction(action);
915
916 if (m_peakToolOn) {
917 if (h && h->hasPlot()) {
918 action = new QAction("Remove plot", this);
919 connect(action, SIGNAL(triggered()), this, SLOT(removeGuessCurrent()));
920 menu->addAction(action);
921 } else {
922 action = new QAction("Plot", this);
923 connect(action, SIGNAL(triggered()), this, SLOT(plotGuessCurrent()));
924 menu->addAction(action);
925 }
926 }
927
928 action = new QAction("Help", this);
929 connect(action, SIGNAL(triggered()), this, SLOT(functionHelp()));
930 menu->addAction(action);
931
932 menu->addSeparator();
933 } else if (h) {
934 bool isParameter = h->isParameter(ci->property());
935 bool isTie = !isParameter && ci->property()->propertyName() == "Tie";
936 bool isLowerBound = !isParameter && ci->property()->propertyName() == "Lower Bound";
937 bool isUpperBound = !isParameter && ci->property()->propertyName() == "Upper Bound";
938 bool isType = isParameter && ci->property()->propertyName() == "Type";
939 if (isType) {
940 isParameter = false;
941 }
942 if (isTie) {
943 action = new QAction("Remove", this);
944 connect(action, SIGNAL(triggered()), this, SLOT(deleteTie()));
945 menu->addAction(action);
946 } else if (isLowerBound || isUpperBound) {
947 action = new QAction("Remove", this);
948 connect(action, SIGNAL(triggered()), this, SLOT(removeBounds()));
949 menu->addAction(action);
950 } else if (count() > 0 && isParameter) {
951 bool hasTies;
952 bool hasFixes;
953 bool hasBounds;
954 hasConstraints(ci->property(), hasTies, hasFixes, hasBounds);
955
956 if (!hasTies && !hasFixes) {
957 QMenu *constraintMenu = menu->addMenu("Constraint");
958
959 QMenu *detailMenu = constraintMenu->addMenu("Lower Bound");
960
961 action = new QAction("10%", this);
962 connect(action, SIGNAL(triggered()), this, SLOT(addLowerBound10()));
963 detailMenu->addAction(action);
964
965 action = new QAction("50%", this);
966 connect(action, SIGNAL(triggered()), this, SLOT(addLowerBound50()));
967 detailMenu->addAction(action);
968
969 action = new QAction("Custom", this);
970 connect(action, SIGNAL(triggered()), this, SLOT(addLowerBound()));
971 detailMenu->addAction(action);
972 detailMenu = constraintMenu->addMenu("Upper Bound");
973
974 action = new QAction("10%", this);
975 connect(action, SIGNAL(triggered()), this, SLOT(addUpperBound10()));
976 detailMenu->addAction(action);
977
978 action = new QAction("50%", this);
979 connect(action, SIGNAL(triggered()), this, SLOT(addUpperBound50()));
980 detailMenu->addAction(action);
981
982 action = new QAction("Custom", this);
983 connect(action, SIGNAL(triggered()), this, SLOT(addUpperBound()));
984 detailMenu->addAction(action);
985 detailMenu = constraintMenu->addMenu("Both Bounds");
986
987 action = new QAction("10%", this);
988 connect(action, SIGNAL(triggered()), this, SLOT(addBothBounds10()));
989 detailMenu->addAction(action);
990
991 action = new QAction("50%", this);
992 connect(action, SIGNAL(triggered()), this, SLOT(addBothBounds50()));
993 detailMenu->addAction(action);
994
995 action = new QAction("Custom", this);
996 connect(action, SIGNAL(triggered()), this, SLOT(addBothBounds()));
997 detailMenu->addAction(action);
998 }
999
1000 if (hasBounds) {
1001 action = new QAction("Remove constraints", this);
1002 connect(action, SIGNAL(triggered()), this, SLOT(removeBounds()));
1003 menu->addAction(action);
1004 }
1005
1006 if (!hasTies && !hasFixes && !hasBounds) {
1007 action = new QAction("Fix", this);
1008 connect(action, SIGNAL(triggered()), this, SLOT(addFixTie()));
1009 menu->addAction(action);
1010
1011 if (count() == 1) {
1012 action = new QAction("Tie", this);
1013 connect(action, SIGNAL(triggered()), this, SLOT(addTie()));
1014 menu->addAction(action);
1015 } else {
1016 QMenu *detail = menu->addMenu("Tie");
1017
1018 action = new QAction("To function", this);
1019 connect(action, SIGNAL(triggered()), this, SLOT(addTieToFunction()));
1020 detail->addAction(action);
1021
1022 action = new QAction("Custom Tie", this);
1023 connect(action, SIGNAL(triggered()), this, SLOT(addTie()));
1024 detail->addAction(action);
1025 }
1026 } else if (hasTies) {
1027 action = new QAction("Remove tie", this);
1028 connect(action, SIGNAL(triggered()), this, SLOT(deleteTie()));
1029 menu->addAction(action);
1030 } else if (hasFixes) {
1031 action = new QAction("Remove fix", this);
1032 connect(action, SIGNAL(triggered()), this, SLOT(deleteTie()));
1033 menu->addAction(action);
1034 }
1035 }
1036 }
1037
1038 menu->popup(QCursor::pos());
1039}
1040
1044 const QtBrowserItem *const ci = m_browser->currentItem();
1045 PropertyHandler *h = getHandler()->findHandler(ci->property());
1046 removeFunction(h);
1047}
1048
1049//
1050
1051// Get the default function name
1053
1054// Set the default function name
1055void FitPropertyBrowser::setDefaultFunctionType(const std::string &fnType) { m_defaultFunction = fnType; }
1056
1059 // If the default peak is not in registered peaks, default to Gaussian
1060 if (m_registeredPeaks.indexOf(QString::fromStdString(m_defaultPeak)) == -1) {
1061 g_log.warning("Could not find peak function: '" + m_defaultPeak + "'. Defaulting to Gaussian.");
1062 setDefaultPeakType("Gaussian");
1063 }
1064 return m_defaultPeak;
1065}
1067void FitPropertyBrowser::setDefaultPeakType(const std::string &fnType) {
1068 m_defaultPeak = fnType;
1069 setDefaultFunctionType(fnType);
1070}
1074void FitPropertyBrowser::setDefaultBackgroundType(const std::string &fnType) {
1075 m_defaultBackground = fnType;
1076 setDefaultFunctionType(fnType);
1077}
1078
1079std::shared_ptr<Mantid::API::Workspace> FitPropertyBrowser::getWorkspace() const {
1080 std::string wsName = workspaceName();
1081 if (wsName.empty())
1082 return std::shared_ptr<Mantid::API::Workspace>();
1083 try {
1084 return Mantid::API::AnalysisDataService::Instance().retrieve(wsName);
1085 } catch (...) {
1086 return std::shared_ptr<Mantid::API::Workspace>();
1087 }
1088}
1089
1092 int i = m_enumManager->value(m_workspace);
1093 std::string res = "";
1094 if (i >= 0) {
1095 res = m_workspaceNames[i].toStdString();
1096 }
1097 return res;
1098}
1099
1101void FitPropertyBrowser::setWorkspaceName(const QString &wsName) {
1102 int i = static_cast<int>(m_workspaceNames.indexOf(wsName));
1103 if (i < 0) {
1104 // workspace may not be found because add notification hasn't been
1105 // processed yet
1107 i = static_cast<int>(m_workspaceNames.indexOf(wsName));
1108 }
1109 if (i >= 0) {
1110 m_enumManager->setValue(m_workspace, i);
1112 try {
1113 mws = std::dynamic_pointer_cast<Mantid::API::MatrixWorkspace>(
1114 Mantid::API::AnalysisDataService::Instance().retrieve(wsName.toStdString()));
1116 }
1117 if (mws) {
1118 auto wi = static_cast<size_t>(workspaceIndex());
1119 if (wi < mws->getNumberHistograms() && !mws->x(wi).empty()) {
1120 setStartX(mws->x(wi).front());
1121 setEndX(mws->x(wi).back());
1122 }
1123 }
1124 }
1126}
1127
1130
1133 try {
1134 auto const index = getAllowedIndex(i);
1137 // ignore this error
1138 }
1139}
1140
1142std::string FitPropertyBrowser::outputName() const { return m_stringManager->value(m_output).toStdString(); }
1143
1145void FitPropertyBrowser::setOutputName(const std::string &name) {
1146 m_stringManager->setValue(m_output, QString::fromStdString(name));
1147}
1148
1150std::string FitPropertyBrowser::minimizer(bool withProperties) const {
1151 int i = m_enumManager->value(m_minimizer);
1152 QString minimStr = m_minimizers[i];
1153 // append minimizer properties as name=value pairs
1154 if (withProperties) {
1155 for (const QtProperty *const prop : m_minimizerProperties) {
1156 if (prop->propertyManager() == m_stringManager) {
1157 QString value = m_stringManager->value(prop);
1158 if (!value.isEmpty()) {
1159 minimStr += "," + prop->propertyName() + "=" + value;
1160 }
1161 } else {
1162 minimStr += "," + prop->propertyName() + "=";
1163 if (prop->propertyManager() == m_intManager) {
1164 minimStr += QString::number(m_intManager->value(prop));
1165 } else if (prop->propertyManager() == m_doubleManager) {
1166 minimStr += QString::number(m_doubleManager->value(prop));
1167 } else if (prop->propertyManager() == m_boolManager) {
1168 minimStr += QString::number(m_boolManager->value(prop));
1169 } else {
1170 throw std::runtime_error("The fit browser doesn't support the type "
1171 "of minimizer's property " +
1172 prop->propertyName().toStdString());
1173 }
1174 }
1175 }
1176 }
1177 return minimStr.toStdString();
1178}
1179
1182
1185
1188 int i = m_enumManager->value(m_costFunction);
1189 return m_costFunctions[i].toStdString();
1190}
1191
1196
1199 if (!m_evaluationType->isEnabled()) {
1200 return false;
1201 }
1202 int i = m_enumManager->value(m_evaluationType);
1203 return m_evaluationTypes[i].toStdString() == "Histogram";
1204}
1205
1208
1211
1214 return m_stringManager->value(m_excludeRange).QString::toStdString();
1215}
1216
1219 const std::vector<std::string> names = Mantid::API::FunctionFactory::Instance().getFunctionNamesGUI();
1220 m_registeredFunctions.clear();
1221 m_registeredPeaks.clear();
1223 m_registeredOther.clear();
1224
1225 const auto &functionFactory = Mantid::API::FunctionFactory::Instance();
1226 for (const auto &fnName : names) {
1227 if (fnName == "MultiBG")
1228 continue;
1230 try {
1231 function = functionFactory.createFunction(fnName);
1232 } catch (std::exception &exc) {
1233 g_log.warning() << "Unable to create " << fnName << ": " << exc.what() << "\n";
1234 continue;
1235 }
1236 QString qfnName = QString::fromStdString(fnName);
1237 m_registeredFunctions << qfnName;
1238 if (dynamic_cast<Mantid::API::IPeakFunction *>(function.get())) {
1239 m_registeredPeaks << qfnName;
1240 } else if (dynamic_cast<Mantid::API::IBackgroundFunction *>(function.get())) {
1241 m_registeredBackgrounds << qfnName;
1242 } else {
1243 m_registeredOther << qfnName;
1244 }
1245 }
1246}
1247
1251void FitPropertyBrowser::enumChanged(QtProperty *prop) {
1253 return;
1254
1255 bool storeSettings = false;
1256 if (prop == m_workspace) {
1257 workspaceChange(QString::fromStdString(workspaceName()));
1261 } else if (prop->propertyName() == "Type") {
1262 disableUndo();
1264 if (!h)
1265 return;
1266 // if (!h->parentHandler()) return;
1267 auto f = h->changeType(prop);
1268 if (!h->parentHandler()) {
1269 m_compositeFunction = std::dynamic_pointer_cast<Mantid::API::CompositeFunction>(f);
1270 }
1271 if (f)
1273 emit functionChanged();
1274
1275 } else if (prop == m_minimizer) {
1277 } else if (prop == m_evaluationType) {
1278 storeSettings = true;
1279 }
1280
1281 if (storeSettings) {
1282 QSettings settings;
1283 settings.beginGroup("Mantid/FitBrowser");
1284 auto val = m_enumManager->value(prop);
1285 QSettingsChangeAware(settings).setValue(prop->propertyName(), val);
1286 }
1287}
1288
1292void FitPropertyBrowser::boolChanged(QtProperty *prop) {
1294 return;
1295
1296 if (prop == m_plotDiff || prop == m_plotCompositeMembers || prop == m_ignoreInvalidData ||
1297 prop == m_showParamErrors) {
1298 bool val = m_boolManager->value(prop);
1299
1300 QSettings settings;
1301 settings.beginGroup("Mantid/FitBrowser");
1302 QSettingsChangeAware(settings).setValue(prop->propertyName(), val);
1303
1304 if (prop == m_showParamErrors) {
1305 m_parameterManager->setErrorsEnabled(val);
1306 emit errorsEnabled(val);
1307 }
1308 } else { // it could be an attribute
1310 if (!h)
1311 return;
1312 enactAttributeChange(prop, h);
1313 }
1314}
1315
1319void FitPropertyBrowser::intChanged(QtProperty *prop) {
1321 return;
1322
1323 if (prop == m_workspaceIndex) {
1324 // Get current value displayed by the workspace index spinbox
1325 auto const currentIndex = workspaceIndex();
1326 auto const allowedIndex = getAllowedIndex(currentIndex);
1327 if (allowedIndex != currentIndex) {
1328 setWorkspaceIndex(allowedIndex);
1329 emit workspaceIndexChanged(allowedIndex);
1330 }
1331 m_oldWorkspaceIndex = allowedIndex;
1332 } else if (prop->propertyName() == "Workspace Index") {
1333 // Property field from Settings. Note the white space.
1335 if (!h)
1336 return;
1338 } else if (prop->propertyName() == "WorkspaceIndex") {
1339 // Property field from functions. In a word.
1341 auto const index = prop->valueText().toInt();
1342 if (h) {
1343 h->setAttribute(prop);
1347 }
1348 } else if (prop == m_maxIterations || prop == m_peakRadius) {
1349 QSettings settings;
1350 settings.beginGroup("Mantid/FitBrowser");
1351 int val = m_intManager->value(prop);
1352 QSettingsChangeAware(settings).setValue(prop->propertyName(), val);
1353 if (prop == m_peakRadius) {
1355 }
1356 } else { // it could be an attribute
1358 if (!h)
1359 return;
1360 enactAttributeChange(prop, h);
1361 }
1362}
1363
1369 return;
1370
1371 double value = m_doubleManager->value(prop);
1372 if (prop == m_startX) {
1373 // call setWorkspace to change maxX in functions
1375 m_doubleManager->setMinimum(m_endX, value);
1376 getHandler()->setAttribute("StartX", value);
1377 emit startXChanged(startX());
1378 emit xRangeChanged(startX(), endX());
1379 return;
1380 } else if (prop == m_endX) {
1381 // call setWorkspace to change minX in functions
1383 m_doubleManager->setMaximum(m_startX, value);
1384 getHandler()->setAttribute("EndX", value);
1385 emit endXChanged(endX());
1386 emit xRangeChanged(startX(), endX());
1387 return;
1388 } else { // check if it is a constraint
1390 if (!h)
1391 return;
1392
1393 QtProperty *parProp = h->getParameterProperty(prop);
1394 if (parProp) {
1395 if (prop->propertyName() == "LowerBound") {
1396 double loBound = m_doubleManager->value(prop);
1397 h->addConstraint(parProp, true, false, loBound, 0);
1398 } else if (prop->propertyName() == "UpperBound") {
1399 double upBound = m_doubleManager->value(prop);
1400 h->addConstraint(parProp, false, true, 0, upBound);
1401 }
1402 } else { // it could be an attribute
1403 enactAttributeChange(prop, h);
1404 }
1405 }
1406}
1407
1408void FitPropertyBrowser::enactAttributeChange(QtProperty *prop, PropertyHandler *h, const bool vectorAttribute) {
1409 try {
1410 if (vectorAttribute) {
1411 h->setVectorAttribute(prop);
1412 } else {
1413 h->setAttribute(prop);
1414 }
1415 } catch (IFunction::ValidationException &ve) {
1416 std::stringstream err_str;
1417 err_str << prop->propertyName().toStdString() << " - " << ve.what();
1418 g_log.warning(err_str.str());
1419 }
1420}
1421
1430 return;
1431
1432 getHandler()->setParameter(prop);
1433}
1434
1440 return;
1441
1442 if (prop == m_output) {
1443 std::string oName = outputName();
1444 if (oName.find_first_not_of(' ') == std::string::npos) {
1445 setOutputName("");
1446 } else if (workspaceName() == oName || oName.empty()) {
1447 m_guessOutputName = true;
1448 } else {
1449 m_guessOutputName = false;
1450 }
1451 } else if (prop->propertyName() == "Tie") {
1453 if (!h)
1454 return;
1455
1456 const QtProperty *const parProp = h->getParameterProperty(prop);
1457 if (!parProp)
1458 return;
1459
1460 const QString parName = h->functionPrefix() + "." + parProp->propertyName();
1461
1462 const auto oldExp = getOldExpressionAsString(parName);
1463 const auto exp = m_stringManager->value(prop);
1464
1465 if (oldExp == exp)
1466 return;
1467
1468 try {
1469 compositeFunction().get()->tie(parName.toStdString(), exp.toStdString());
1470 h->addTie(parName + "=" + exp);
1471 } catch (...) {
1472 const auto msg =
1473 "Failed to update tie on " + parName.toStdString() + ". Expression " + exp.toStdString() + " is invalid.";
1474 QMessageBox::critical(this, "Mantid - Error", msg.c_str());
1475
1476 m_stringManager->setValue(prop, oldExp);
1477 }
1478 } else if (getHandler()->setAttribute(prop)) { // setting an attribute may
1479 // change function parameters
1480 emit functionChanged();
1481 return;
1482 }
1483}
1484
1488QString FitPropertyBrowser::getOldExpressionAsString(const QString &parameterName) const {
1489 // Note this only finds the oldTie if it was a tie to a function (e.g. f0.Height=f1.Height)
1490 // but not if it was a custom tie (e.g. f0.Height=2.0)
1491 QString oldExp;
1492 size_t parIndex;
1493 try {
1494 parIndex = compositeFunction()->parameterIndex(parameterName.toStdString());
1495 } catch (std::exception &) {
1496 return "";
1497 }
1498 const auto oldTie = compositeFunction()->getTie(parIndex);
1499 if (oldTie) {
1500 const auto oldTieStr = oldTie->asString();
1501 oldExp = QString::fromStdString(oldTieStr.substr(oldTieStr.find("=") + 1));
1502 } else {
1503 oldExp = "";
1504 }
1505 return oldExp;
1506}
1507
1513 return;
1514
1515 if (getHandler()->setAttribute(prop)) {
1516 return;
1517 }
1518}
1519// Centre of the current peak
1522 return m_currentHandler->pfun()->centre();
1523 }
1524 return 0;
1525}
1526
1537
1538// Height of the current peak
1541 return m_currentHandler->pfun()->height();
1542 }
1543 return 0.;
1544}
1545
1556
1557// Width of the current peak
1560 return m_currentHandler->pfun()->fwhm();
1561 }
1562 return 0;
1563}
1564
1575
1577int FitPropertyBrowser::count() const { return static_cast<int>(m_compositeFunction->nFunctions()); }
1578
1581
1586 m_currentHandler = h;
1587 if (m_currentHandler) {
1588 m_browser->setCurrentItem(m_currentHandler->item());
1589 emit currentChanged();
1590 }
1591}
1592
1599
1603void FitPropertyBrowser::doFit(int maxIterations) {
1604 const std::string wsName = workspaceName();
1605
1606 if (wsName.empty()) {
1607 QMessageBox::critical(this, "Mantid - Error", "Workspace name is not set");
1608 return;
1609 }
1610
1611 const auto ws = getWorkspace();
1612 if (!ws) {
1613 return;
1614 }
1615
1616 try {
1617 emit algorithmStarted(QString::fromStdString(wsName));
1618 m_initialParameters.resize(compositeFunction()->nParams());
1619 for (size_t i = 0; i < compositeFunction()->nParams(); i++) {
1620 m_initialParameters[i] = compositeFunction()->getParameter(i);
1621 }
1622 m_fitActionUndoFit->setEnabled(true);
1623
1624 Mantid::API::IAlgorithm_sptr alg = Mantid::API::AlgorithmManager::Instance().create("Fit");
1625 alg->initialize();
1626 if (isHistogramFit()) {
1627 alg->setProperty("EvaluationType", "Histogram");
1628 }
1629 alg->setProperty("Function", std::dynamic_pointer_cast<Mantid::API::IFunction>(compositeFunction())->clone());
1630 alg->setProperty("InputWorkspace", ws);
1631 auto tbl = std::dynamic_pointer_cast<ITableWorkspace>(ws);
1632 if (!tbl) {
1633 alg->setProperty("WorkspaceIndex", workspaceIndex());
1634 } else {
1635 alg->setPropertyValue("XColumn", getXColumnName().toStdString());
1636 alg->setPropertyValue("YColumn", getYColumnName().toStdString());
1637 if (getErrColumnName().toStdString() != "")
1638 alg->setPropertyValue("ErrColumn", getErrColumnName().toStdString());
1639 }
1640 alg->setProperty("StartX", startX());
1641 alg->setProperty("EndX", endX());
1642 alg->setPropertyValue("Output", outputName());
1643 alg->setPropertyValue("Minimizer", minimizer(true));
1644 alg->setProperty("IgnoreInvalidData", ignoreInvalidData());
1645 alg->setPropertyValue("CostFunction", costFunction());
1646 alg->setProperty("MaxIterations", maxIterations);
1647 alg->setProperty("PeakRadius", getPeakRadius());
1648 if (!isHistogramFit()) {
1649 if (!tbl) {
1650 alg->setProperty("Normalise", m_shouldBeNormalised);
1651 }
1652 // Always output each composite function but not necessarily plot it
1653 alg->setProperty("OutputCompositeMembers", true);
1654 if (alg->existsProperty("ConvolveMembers")) {
1655 alg->setProperty("ConvolveMembers", convolveMembers());
1656 }
1657 }
1658 if (!getExcludeRange().empty()) {
1659 if (alg->getPropertyValue("EvaluationType") != "Histogram")
1660 alg->setProperty("Exclude", getExcludeRange());
1661 else {
1662 g_log.warning("Exclude property not avaliable when evaluating as a histogram.");
1663 }
1664 }
1665 observeFinish(alg);
1666 Poco::ActiveResult<bool> result(alg->executeAsync());
1667 while (!result.available()) {
1668 QCoreApplication::processEvents();
1669 }
1670 m_fitAlgParameters = alg->toString();
1671 if (!result.error().empty()) {
1672 emit algorithmFailed();
1673 }
1674 } catch (const std::exception &e) {
1675 QString msg = "Fit algorithm failed.\n\n" + QString(e.what()) + "\n";
1676 QMessageBox::critical(this, "Mantid - Error", msg);
1677 }
1678}
1679
1685 if (m_compositeFunction->nFunctions() > 1) {
1686 function = m_compositeFunction;
1687 } else {
1688 function = getFunctionAtIndex(0);
1689 }
1690 return function;
1691}
1692
1697 return m_compositeFunction->getFunction(index);
1698}
1699
1701 // Emit a signal to show that the fitting has completed. (workspaceNames that
1702 // the fit has been done against is sent as a parameter)
1703 QString name(QString::fromStdString(alg->getProperty("InputWorkspace")));
1704 if (name.contains('_')) // Must be fitting to raw data, need to group under
1705 // name without "_Raw".
1706 emit fittingDone(name.left(name.indexOf('_')));
1707 else // else fitting to current workspace, group under same name.
1708 emit fittingDone(name);
1709
1710 IFunction_sptr function = alg->getProperty("Function");
1712 if (alg->existsProperty("OutputWorkspace")) {
1713 std::string out = alg->getProperty("OutputWorkspace");
1714 emit algorithmFinished(QString::fromStdString(out));
1715 }
1716 // Update Status string in member variable (so can be retrieved)
1717 m_fitAlgOutputStatus = alg->getPropertyValue("OutputStatus");
1718 auto status = QString::fromStdString(m_fitAlgOutputStatus);
1719 emit fitResultsChanged(status);
1720 // update Quality string
1721 if (m_displayActionQuality->isChecked()) {
1722 double quality = alg->getProperty("OutputChi2overDoF");
1723 std::string costFunctionStr = alg->getProperty("CostFunction");
1724 std::shared_ptr<Mantid::API::ICostFunction> costfun =
1725 Mantid::API::CostFunctionFactory::Instance().create(costFunctionStr);
1726 status = (status == "success") ? "success" : "failed";
1727 emit changeWindowTitle(QString("Fit Function (") + costfun->shortName().c_str() + " = " + QString::number(quality) +
1728 ", " + status + ")");
1729 } else
1730 emit changeWindowTitle("Fit Function");
1731 if (m_compositeFunction->name() == "MultiBG") {
1732 emit multifitFinished();
1733 }
1734}
1735
1737 auto function = getFittingFunction();
1738 return function->asString();
1739}
1740
1743void FitPropertyBrowser::showFitResultStatus(const QString &status) {
1744 auto text(status);
1745 text.replace("\n", "<br>");
1746 QString color("green");
1747 if (status != "success") {
1748 color = "red";
1749 }
1750
1751 m_status->setText(QString("Status: <span style='color:%2'>%1</span>").arg(text, color));
1752 m_status->show();
1753}
1754
1757 m_status->setText("Status:");
1758 m_status->hide();
1759}
1760
1763 m_workspaceNames.clear();
1764 if (m_allowedTableWorkspace.isEmpty()) {
1765 bool allAreAllowed = m_allowedSpectra.isEmpty();
1766 QStringList allowedNames;
1767 auto wsList = Mantid::API::AnalysisDataService::Instance().getObjectNames();
1768 for (const auto &wsName : wsList) {
1769 auto const &name = QString::fromStdString(wsName);
1770 if (allAreAllowed || m_allowedSpectra.contains(name)) {
1771 allowedNames << name;
1772 }
1773 }
1774
1775 for (const auto &name : allowedNames) {
1776 Mantid::API::Workspace_sptr ws = Mantid::API::AnalysisDataService::Instance().retrieve(name.toStdString());
1777 if (isWorkspaceValid(ws)) {
1778 m_workspaceNames.append(name);
1779 }
1780 }
1781 } else {
1783 }
1786}
1787
1792 (void)e;
1793 // Observe what workspaces are added and deleted unless it's a custom
1794 // fitting, all workspaces for custom fitting (eg muon analysis) should be
1795 // manually added.
1798}
1799
1804 (void)e;
1805 setADSObserveEnabled(false);
1806}
1807
1809 observeAdd(enabled);
1810 observePostDelete(enabled);
1811 observeRename(enabled);
1812}
1813
1815void FitPropertyBrowser::addHandle(const std::string &wsName, const std::shared_ptr<Mantid::API::Workspace> &ws) {
1816 auto const qName = QString::fromStdString(wsName);
1817 if (!isWorkspaceValid(ws) ||
1818 (!m_allowedSpectra.isEmpty() && !m_allowedSpectra.contains(qName) && m_allowedTableWorkspace.isEmpty()))
1819 return;
1820 QString oldName = QString::fromStdString(workspaceName());
1821 int i = static_cast<int>(m_workspaceNames.indexOf(qName));
1822
1823 bool initialSignalsBlocked = m_enumManager->signalsBlocked();
1824
1825 // if new workspace append this workspace name
1826 if (i < 0) {
1827 if (!m_workspaceNames.isEmpty()) {
1828 m_enumManager->blockSignals(true);
1829 }
1830
1831 m_workspaceNames.append(qName);
1832 m_workspaceNames.sort();
1834 }
1835 // get hold of index of oldName
1836 i = static_cast<int>(m_workspaceNames.indexOf(oldName));
1837 if (i >= 0) {
1838 m_enumManager->setValue(m_workspace, i);
1839 }
1840
1841 m_enumManager->blockSignals(initialSignalsBlocked);
1842}
1843
1845void FitPropertyBrowser::postDeleteHandle(const std::string &wsName) { removeWorkspace(wsName); }
1846
1847void FitPropertyBrowser::removeWorkspace(const std::string &wsName) {
1848 QString oldName = QString::fromStdString(workspaceName());
1849 int iName = static_cast<int>(m_workspaceNames.indexOf(QString(wsName.c_str())));
1850 if (iName >= 0) {
1851 m_workspaceNames.removeAt(iName);
1852 }
1853
1854 bool initialSignalsBlocked = m_enumManager->signalsBlocked();
1855
1856 if (QString::fromStdString(wsName) != oldName) {
1857 m_enumManager->blockSignals(true);
1858 }
1859
1861
1862 iName = static_cast<int>(m_workspaceNames.indexOf(oldName));
1863 if (iName >= 0) {
1864 m_enumManager->setValue(m_workspace, iName);
1865 }
1866
1867 m_enumManager->blockSignals(initialSignalsBlocked);
1868
1869 for (auto i = 0; i < m_wsListWidget->count(); ++i) {
1870 auto item = m_wsListWidget->item(i);
1871 if (item->text().toStdString() == wsName) {
1872 m_wsListWidget->takeItem(m_wsListWidget->row(item));
1873 }
1874 }
1875
1876 if (m_wsListWidget->count() == 0) {
1877 m_wsListWidget->hide();
1878 m_workspaceLabel->hide();
1879 }
1880}
1881
1882void FitPropertyBrowser::renameHandle(const std::string &oldName, const std::string &newName) {
1883 QString oldNameQ = QString::fromStdString(oldName);
1884 QString newNameQ = QString::fromStdString(newName);
1885 auto it = m_allowedSpectra.find(oldNameQ);
1886 if (it != m_allowedSpectra.end()) {
1887 auto indices = m_allowedSpectra.value(oldNameQ);
1888 m_allowedSpectra.remove(oldNameQ);
1889 m_allowedSpectra.insert(newNameQ, indices);
1890 }
1891 int iWorkspace = static_cast<int>(m_workspaceNames.indexOf(oldNameQ));
1892 if (iWorkspace >= 0) {
1893 m_workspaceNames.replace(iWorkspace, newNameQ);
1895 }
1896 workspaceChange(newNameQ);
1897
1898 for (auto i = 0; i < m_wsListWidget->count(); ++i) {
1899 auto item = m_wsListWidget->item(i);
1900 if (item->text().toStdString() == oldName) {
1901 m_wsListWidget->takeItem(m_wsListWidget->row(item));
1902 m_wsListWidget->insertItem(m_wsListWidget->row(item), newNameQ);
1903 }
1904 }
1905}
1906
1912 return (dynamic_cast<Mantid::API::MatrixWorkspace *>(ws.get()) != nullptr ||
1913 dynamic_cast<Mantid::API::ITableWorkspace *>(ws.get()) != nullptr);
1914}
1915
1918 if (count() == 0) {
1919 return false;
1920 }
1922}
1923
1925double FitPropertyBrowser::startX() const { return m_doubleManager->value(m_startX); }
1926
1929
1931double FitPropertyBrowser::endX() const { return m_doubleManager->value(m_endX); }
1932
1935
1936void FitPropertyBrowser::setXRange(double start, double end) {
1937 disconnect(m_doubleManager, SIGNAL(propertyChanged(QtProperty *)), this, SLOT(doubleChanged(QtProperty *)));
1938
1939 m_doubleManager->setValue(m_startX, start);
1940 m_doubleManager->setValue(m_endX, end);
1941
1943 m_doubleManager->setMinimum(m_endX, start);
1944 m_doubleManager->setMaximum(m_startX, end);
1945
1946 getHandler()->setAttribute("StartX", start);
1947 getHandler()->setAttribute("EndX", end);
1948
1949 connect(m_doubleManager, SIGNAL(propertyChanged(QtProperty *)), this, SLOT(doubleChanged(QtProperty *)));
1950}
1951
1953 auto ws = getWorkspace();
1954 auto tbl = std::dynamic_pointer_cast<ITableWorkspace>(ws);
1955 auto mws = std::dynamic_pointer_cast<MatrixWorkspace>(ws);
1956 QList<double> range;
1957 if (tbl) {
1958 auto xColumnIndex = m_columnManager->value(m_xColumn);
1959 std::vector<double> xColumnData;
1960 auto col = tbl->getColumn(xColumnIndex);
1961 try {
1962 for (size_t i = 0; i < tbl->rowCount(); ++i) {
1963 xColumnData.emplace_back(col->toDouble(i));
1964 }
1965 } catch (std::invalid_argument &err) {
1966 QMessageBox::critical(this, "Mantid - Error", "The X column is not a number");
1967 throw std::invalid_argument(err);
1968 }
1969 std::sort(xColumnData.begin(), xColumnData.end());
1970 range.push_back(xColumnData.front());
1971 range.push_back(xColumnData.back());
1972 } else if (mws) {
1973 auto xData = mws->mutableX(workspaceIndex());
1974 range.push_back(xData.front());
1975 range.push_back(xData.back());
1976 }
1977 return range;
1978}
1979
1981 const auto ws = getWorkspace();
1982 auto tbl = std::dynamic_pointer_cast<ITableWorkspace>(ws);
1983 QString columnName = "";
1984 if (tbl) {
1985 auto columns = tbl->getColumnNames();
1986 auto xIndex = m_columnManager->value(m_xColumn);
1987 if (xIndex >= static_cast<int>(columns.size())) {
1988 QMessageBox::critical(nullptr, "Mantid - Error", "X column was not found.");
1989 }
1990 columnName = QString::fromStdString(columns[xIndex]);
1991 }
1992 return columnName;
1993}
1994
1996 const auto ws = getWorkspace();
1997 auto tbl = std::dynamic_pointer_cast<ITableWorkspace>(ws);
1998 QString columnName = "";
1999 if (tbl) {
2000 auto columns = tbl->getColumnNames();
2001 auto yIndex = m_columnManager->value(m_yColumn);
2002 if (yIndex >= static_cast<int>(columns.size())) {
2003 QMessageBox::critical(nullptr, "Mantid - Error", "Y column was not found.");
2004 }
2005 columnName = QString::fromStdString(columns[yIndex]);
2006 }
2007 return columnName;
2008}
2009
2011 const auto ws = getWorkspace();
2012 auto tbl = std::dynamic_pointer_cast<ITableWorkspace>(ws);
2013 QString columnName = "";
2014 if (tbl) {
2015 auto columns = tbl->getColumnNames();
2016 // The error column has an empty first entry
2017 auto errIndex = m_columnManager->value(m_errColumn) - 1;
2018 if (errIndex >= static_cast<int>(columns.size())) {
2019 QMessageBox::warning(nullptr, "Mantid - Warning", "Error column was not found.");
2020 } else if (errIndex != -1) {
2021 columnName = QString::fromStdString(columns[errIndex]);
2022 }
2023 }
2024 return columnName;
2025}
2026
2028QtBrowserItem *FitPropertyBrowser::findItem(QtBrowserItem *parent, QtProperty *prop) const {
2029 QList<QtBrowserItem *> children = parent->children();
2030 QtBrowserItem *res = nullptr;
2031 for (auto &child : children) {
2032 if (child->property() == prop) {
2033 return child;
2034 }
2035 QList<QtBrowserItem *> grand_children = child->children();
2036 if (grand_children.size() > 0)
2037 res = findItem(child, prop);
2038 if (res)
2039 return res;
2040 }
2041 return nullptr;
2042}
2043
2047void FitPropertyBrowser::currentItemChanged(const QtBrowserItem *current) {
2048 if (current) {
2049 m_currentHandler = getHandler()->findHandler(current->property());
2050 } else {
2051 m_currentHandler = nullptr;
2052 }
2053 emit currentChanged();
2054}
2055
2062 if (!h)
2063 return;
2064 enactAttributeChange(prop, h, true);
2065}
2066
2073 if (!h)
2074 return;
2075 enactAttributeChange(prop, h, true);
2076}
2077
2082
2087
2097
2099 QList<QtProperty *> props = m_functionsGroup->property()->subProperties();
2100 for (QtProperty *prop : props) {
2101 m_functionsGroup->property()->removeSubProperty(prop);
2102 }
2103}
2104
2107 for (auto paramIndex = 0u; paramIndex < finalFunction->nParams(); ++paramIndex) {
2108 compositeFunction()->setParameter(paramIndex, finalFunction->getParameter(paramIndex));
2109 compositeFunction()->setError(paramIndex, finalFunction->getError(paramIndex));
2110 }
2113}
2114
2119 if (m_initialParameters.size() == compositeFunction()->nParams()) {
2120 for (size_t i = 0; i < compositeFunction()->nParams(); i++) {
2121 compositeFunction()->setParameter(i, m_initialParameters[i]);
2122 }
2126 emit fitUndone();
2127 }
2128 disableUndo();
2129}
2130
2133 m_initialParameters.clear();
2134 m_fitActionUndoFit->setEnabled(false);
2135}
2136
2139 return m_initialParameters.size() && compositeFunction()->nParams() == m_initialParameters.size();
2140}
2141
2144 m_fitActionFit->setEnabled(enable);
2145 m_fitActionSeqFit->setEnabled(enable);
2146}
2147
2149bool FitPropertyBrowser::isFitEnabled() const { return m_fitActionFit->isEnabled(); }
2150
2155 QtBrowserItem *ci = m_browser->currentItem();
2156 QtProperty *paramProp = ci->property();
2157 PropertyHandler *h = getHandler()->findHandler(paramProp);
2158 if (!h)
2159 return;
2160 if (!h->isParameter(paramProp))
2161 return;
2162
2163 auto f = h->function();
2164 if (!f)
2165 return;
2166
2167 bool ok = false;
2168 QString tieStr = QInputDialog::getText(this, "Mantid - Fit", "Enter tie expression", QLineEdit::Normal, "", &ok);
2169 if (ok) {
2170 tieStr = tieStr.trimmed();
2171 if (!tieStr.contains('=')) {
2172 tieStr = h->functionPrefix() + "." + paramProp->propertyName() + "=" + tieStr;
2173 }
2174 h->addTie(tieStr);
2175 } // if (ok)
2176}
2177
2183 QtBrowserItem *ci = m_browser->currentItem();
2184 QtProperty *paramProp = ci->property();
2185 PropertyHandler *h = getHandler()->findHandler(paramProp);
2186 if (!h)
2187 return;
2188 if (!h->isParameter(paramProp))
2189 return;
2190 std::string parName = paramProp->propertyName().toStdString();
2191 QStringList fnNames;
2192
2193 int iPar = -1;
2194 for (size_t i = 0; i < m_compositeFunction->nParams(); i++) {
2196 const Mantid::API::IFunction *const fun = ref.getLocalFunction();
2197
2198 // Pick out parameters with the same name as the one we're tying from
2199 if (fun->parameterName(static_cast<int>(ref.getLocalIndex())) == parName) {
2200 if (iPar == -1 && fun == h->function().get()) // If this is the 'tied from' parameter, remember it
2201 {
2202 iPar = (int)i;
2203 } else // Otherwise add it to the list of potential 'tyees'
2204 {
2205 fnNames << QString::fromStdString(m_compositeFunction->parameterName(i));
2206 }
2207 }
2208 }
2209 if (fnNames.empty() || iPar < 0) {
2210 QMessageBox::information(this, "Mantid - information", "Cannot tie this parameter to any function");
2211 return;
2212 }
2213
2214 bool ok;
2215 QString tieName = QInputDialog::getItem(this, "Mantid - Fit", "Select function", fnNames, 0, false, &ok);
2216
2217 if (!ok)
2218 return;
2219
2220 QString tieExpr = QString::fromStdString(m_compositeFunction->parameterName(iPar)) + "=" + tieName;
2221
2222 h->addTie(tieExpr);
2223}
2224
2229 QtBrowserItem *ci = m_browser->currentItem();
2230 QtProperty *paramProp = ci->property();
2231 PropertyHandler *h = getHandler()->findHandler(paramProp);
2232 if (!h)
2233 return;
2234 if (!h->isParameter(paramProp))
2235 return;
2236 h->fix(paramProp->propertyName());
2237}
2238
2243 QtBrowserItem *ci = m_browser->currentItem();
2244 QtProperty *paramProp = ci->property();
2245 PropertyHandler *h = getHandler()->findHandler(paramProp);
2246 if (!h)
2247 return;
2248 // get name of parent property (i.e. function)
2249 if (paramProp->propertyName() != "Tie") {
2250 auto parameterMap = h->getTies();
2251 auto match = parameterMap.find(paramProp->propertyName());
2252 if (match != parameterMap.end()) {
2253 paramProp = match.value();
2254 }
2255 }
2256 if (paramProp->propertyName() == "Tie") {
2257 auto ties = h->getTies();
2258 QString qParName = ties.key(paramProp, "");
2259 std::string parName = qParName.toStdString();
2260 QStringList functionNames;
2261 // ithParameter = -1 => not found
2262 int ithParameter = -1;
2263 for (size_t i = 0; i < m_compositeFunction->nParams(); i++) {
2264 const Mantid::API::ParameterReference parameterRef(m_compositeFunction.get(), i);
2265 const Mantid::API::IFunction *const function = parameterRef.getLocalFunction();
2266 // Pick out parameters with the same name as the one we're tying from
2267 if (function->parameterName(static_cast<int>(parameterRef.getLocalIndex())) == parName) {
2268 if (ithParameter == -1 && function == h->function().get()) // If this is the 'tied from'
2269 // parameter, remember it
2270 {
2271 ithParameter = static_cast<int>(i);
2272 } else // Otherwise add it to the list of potential 'tyees'
2273 {
2274 functionNames << QString::fromStdString(m_compositeFunction->parameterName(i));
2275 }
2276 }
2277 }
2278 if (functionNames.empty() && ithParameter < 0) {
2279 QMessageBox::information(this, "Mantid - information", "Cannot find a parameter with this tie");
2280 } else {
2281 QString tieExpr = QString::fromStdString(m_compositeFunction->parameterName(ithParameter));
2282 h->removeTie(paramProp, tieExpr.toStdString());
2283 }
2284 } else {
2285 h->removeTie(ci->property()->propertyName());
2286 }
2287}
2288
2295void FitPropertyBrowser::hasConstraints(QtProperty *parProp, bool &hasTie, bool &hasFix, bool &hasBounds) const {
2296 hasTie = false;
2297 hasFix = false;
2298 hasBounds = false;
2299 QList<QtProperty *> subs = parProp->subProperties();
2300 for (const auto *sub : subs) {
2301 const auto propName = sub->propertyName();
2302 if (propName == "Tie") {
2303 hasTie = true;
2304 } else if (propName == "Fix") {
2305 hasFix = true;
2306 } else if (propName == "LowerBound") {
2307 hasBounds = true;
2308 } else if (propName == "UpperBound") {
2309 hasBounds = true;
2310 }
2311 }
2312}
2313
2317QtProperty *FitPropertyBrowser::getTieProperty(QtProperty *parProp) const {
2318 QList<QtProperty *> subs = parProp->subProperties();
2319 if (auto sub =
2320 std::find_if(std::cbegin(subs), std::cend(subs), [](const auto x) { return (*x).propertyName() == "Tie"; });
2321 sub != std::cend(subs)) {
2322 return *sub;
2323 }
2324 return nullptr;
2325}
2326
2332 Q_UNUSED(notice);
2333 // Don't call populate directly as the updates can come from a different
2334 // thread
2336}
2337
2341void FitPropertyBrowser::setTip(const QString &txt) { m_tip->setText(txt); }
2342
2347void FitPropertyBrowser::addConstraint(int f, bool lo, bool up) {
2348 QtBrowserItem *ci = m_browser->currentItem();
2349 QtProperty *parProp = ci->property();
2350 PropertyHandler *h = getHandler()->findHandler(parProp);
2351 if (!h)
2352 return;
2353
2354 double x = parProp->valueText().toDouble();
2355 double loBound = x * (1 - 0.01 * f);
2356 double upBound = x * (1 + 0.01 * f);
2357
2358 h->addConstraint(ci->property(), lo, up, loBound, upBound);
2359}
2360
2365
2370
2375
2380
2385
2390
2396
2402
2407
2412 QtBrowserItem *ci = m_browser->currentItem();
2413 QtProperty *parProp = ci->property();
2414 PropertyHandler *h = getHandler()->findHandler(parProp);
2415 if (!h)
2416 return;
2417
2418 h->removeConstraint(parProp);
2419}
2420
2425
2430
2436
2441
2443 if (getHandler()->hasPlot()) {
2445 } else {
2446 plotGuessAll();
2447 }
2448}
2449
2451
2457QtProperty *FitPropertyBrowser::addDoubleProperty(const QString &name, QtDoublePropertyManager *manager) const {
2458 if (manager == nullptr)
2459 manager = m_doubleManager;
2460 QtProperty *prop = manager->addProperty(name);
2461 manager->setDecimals(prop, m_decimals);
2462 manager->setRange(prop, -DBL_MAX, DBL_MAX);
2463 return prop;
2464}
2465
2471QtProperty *FitPropertyBrowser::addStringProperty(const QString &name) const {
2472 QtProperty *prop;
2473 QString propName = name.toLower();
2474 if (propName == "filename") {
2475 prop = m_filenameManager->addProperty(name);
2476 } else if (propName == "formula") {
2478 prop = m_formulaManager->addProperty(name);
2479 } else {
2480 prop = m_stringManager->addProperty(name);
2481 }
2482 return prop;
2483}
2484
2493 const std::vector<std::string> &allowed_values) const {
2494 QStringList qAllowedValues;
2495 QtProperty *prop = m_enumManager->addProperty(name);
2496
2497 for (const auto &values : allowed_values) {
2498 qAllowedValues << QString::fromStdString(values);
2499 }
2500 m_enumManager->setEnumNames(prop, qAllowedValues);
2501
2502 return prop;
2503}
2504
2510void FitPropertyBrowser::setStringPropertyValue(QtProperty *prop, const QString &value) const {
2511 auto *manager = dynamic_cast<QtStringPropertyManager *>(prop->propertyManager());
2512 if (manager) {
2513 manager->setValue(prop, value);
2514 }
2515}
2516
2517QString FitPropertyBrowser::getStringPropertyValue(QtProperty *prop) const {
2518 const auto *const manager = dynamic_cast<QtStringPropertyManager *>(prop->propertyManager());
2519 if (manager)
2520 return manager->value(prop);
2521 else
2522 return QString("");
2523}
2524
2526
2528
2533int FitPropertyBrowser::getAllowedIndex(int currentIndex) const {
2534 auto const workspace = std::dynamic_pointer_cast<MatrixWorkspace>(getWorkspace());
2535
2536 if (!workspace) {
2537 return 0;
2538 }
2539
2540 auto const allowedIndices =
2541 m_allowedSpectra.empty() ? QList<int>() : m_allowedSpectra[QString::fromStdString(workspaceName())];
2542 auto const firstIndex = m_allowedSpectra.empty() ? 0 : allowedIndices.front();
2543 auto const lastIndex = m_allowedSpectra.empty() ? getNumberOfSpectra(workspace) - 1 : allowedIndices.back();
2544
2545 auto allowedIndex = currentIndex;
2546 if (currentIndex < firstIndex) {
2547 allowedIndex = firstIndex;
2548 } else if (currentIndex > lastIndex) {
2549 allowedIndex = lastIndex;
2550 } else if (!m_allowedSpectra.empty() && !allowedIndices.contains(currentIndex)) {
2551 allowedIndex = m_oldWorkspaceIndex;
2552 auto i = allowedIndices.indexOf(m_oldWorkspaceIndex);
2553 if (i >= 0) {
2554 i = currentIndex > m_oldWorkspaceIndex ? i + 1 : i - 1;
2555 if (i >= 0 && i < allowedIndices.size()) {
2556 allowedIndex = allowedIndices[i];
2557 }
2558 }
2559 }
2560 return allowedIndex;
2561}
2562
2564 bool ok(false);
2565 QString fnName = QInputDialog::getText(this, tr("Mantid - Input"), tr("Please select a name for the function"),
2566 QLineEdit::Normal, "", &ok);
2567 if (ok && !fnName.isEmpty()) {
2568 saveFunction(fnName);
2569 }
2570}
2571
2572void FitPropertyBrowser::saveFunction(const QString &fnName) {
2573 QSettings settings;
2574 settings.beginGroup("Mantid/FitBrowser/SavedFunctions");
2575 QStringList names = settings.childKeys();
2576 if (names.contains(fnName) &&
2577 QMessageBox::question(this, "Mantid - Question",
2578 "Function with this name already exists.\n"
2579 "Would you like to replace it?",
2580 QMessageBox::Yes | QMessageBox::No, QMessageBox::No) != QMessageBox::Yes) {
2581 return;
2582 }
2583 QSettingsChangeAware(settings).setValue(fnName, QString::fromStdString(theFunction()->asString()));
2585}
2586
2588 QSettings settings;
2589 settings.beginGroup("Mantid/FitBrowser/SavedFunctions");
2590 QStringList names = settings.childKeys();
2591 if (names.isEmpty()) {
2592 QMessageBox::information(this, "Mantid - Information", "There are no saved functions");
2593 return;
2594 }
2595 QString name = QInputDialog::getItem(this, "Mantid - Input", "Please select a function to load", names, 0, false);
2596 if (!name.isEmpty()) {
2597 QString str = settings.value(name).toString();
2598
2599 loadFunction(str);
2600 }
2601}
2602
2604 QString str = QInputDialog::getText(this, "Mantid - Input", "Specify fit function string");
2605
2606 if (!str.isEmpty()) {
2607 loadFunction(str);
2608 }
2609}
2610
2611void FitPropertyBrowser::loadFunction(const QString &funcString) {
2612 // when loading a function from a string initially
2613 // do not try to do auto background even if set
2614 bool isAutoBGset = false;
2615 if (m_auto_back) {
2616 isAutoBGset = true;
2617 m_auto_back = false;
2618 }
2619
2621 clearBrowser();
2622 createCompositeFunction(funcString);
2623 emit functionLoaded(funcString);
2624
2625 if (isAutoBGset)
2626 m_auto_back = true;
2627}
2628
2630 QClipboard *clipboard = QApplication::clipboard();
2631 clipboard->setText(QString::fromStdString(theFunction()->asString()));
2632}
2633
2635 QClipboard *clipboard = QApplication::clipboard();
2636 QString str = clipboard->text();
2638}
2639
2641 QString str = QString::fromStdString(theFunction()->asString());
2642 // getHandler()->removeAllPlots();// this crashes mantidplot
2643 clearBrowser();
2645}
2646
2648 std::string wsName = workspaceName();
2649 if (!wsName.empty()) {
2650 try {
2651 auto ws = Mantid::API::AnalysisDataService::Instance().retrieve(wsName);
2652 auto mws = std::dynamic_pointer_cast<Mantid::API::MatrixWorkspace>(ws);
2653 if (mws) {
2654 function->setMatrixWorkspace(mws, workspaceIndex(), startX(), endX());
2655 } else {
2656 function->setWorkspace(ws);
2657 }
2658 } catch (...) {
2659 }
2660 }
2661}
2662
2664 if (m_autoBgName.isEmpty())
2665 return;
2666 bool hasPlot = false;
2668 if (m_autoBackground) { // remove old background
2669 if (ch == m_autoBackground) {
2670 ch = nullptr;
2671 }
2672 hasPlot = m_autoBackground->hasPlot();
2674 m_autoBackground = nullptr;
2675 }
2676 // Create the function
2677 PropertyHandler *h = getHandler()->addFunction(m_autoBgName.toStdString());
2678 if (!h)
2679 return;
2680 if (!m_autoBgAttributes.isEmpty()) { // set attributes
2681 QStringList attList = m_autoBgAttributes.split(' ');
2682 for (const QString &att : attList) {
2683 QStringList name_value = att.split('=');
2684 if (name_value.size() == 2) {
2685 QString name = name_value[0].trimmed();
2686 QString value = name_value[1].trimmed();
2687 if (h->function()->hasAttribute(name.toStdString())) {
2688 h->setAttribute(name, value);
2689 }
2690 }
2691 }
2692 }
2693 h->fit();
2694 m_autoBackground = h;
2696 if (hasPlot) {
2698 emit plotCurrentGuess();
2699 if (ch) {
2701 }
2702 }
2703}
2704
2710
2718 try {
2719 QStringList nameList = aName.split(' ');
2720 if (nameList.isEmpty())
2721 return;
2722 QString name = nameList[0];
2723 std::shared_ptr<Mantid::API::IFunction> f = std::shared_ptr<Mantid::API::IFunction>(
2724 Mantid::API::FunctionFactory::Instance().createFunction(name.toStdString()));
2725 m_auto_back = true;
2727 if (nameList.size() > 1) {
2728 nameList.removeFirst();
2729 m_autoBgAttributes = nameList.join(" ");
2730 }
2731 Mantid::Kernel::ConfigService::Instance().setString("curvefitting.autoBackground", aName.toStdString());
2732 } catch (...) {
2733 m_auto_back = false;
2734 }
2735}
2736
2738 auto *dlg = new SequentialFitDialog(this, m_mantidui);
2739 std::string wsName = workspaceName();
2740 if (!wsName.empty() && dlg->addWorkspaces(QStringList(QString::fromStdString(wsName)))) {
2741 dlg->show();
2742 }
2743}
2744
2745void FitPropertyBrowser::findPeaks(const std::unique_ptr<FindPeakStrategyGeneric> findPeakStrategy) {
2746 std::string wsName{workspaceName()};
2747 if (wsName.empty()) {
2748 QMessageBox::critical(this, "Mantid - Error", "Workspace name is not set");
2749 return;
2750 }
2751
2752 std::string peakListName = wsName + "_PeakList_tmp";
2753 QString setting =
2754 QString::fromStdString(Mantid::Kernel::ConfigService::Instance().getString("curvefitting.findPeaksFWHM"));
2755 int FWHM{setting.isEmpty() ? 7 : setting.toInt()};
2756
2758 findPeakStrategy->initialise(wsName, workspaceIndex(), peakListName, FWHM, &obs);
2759
2760 QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
2761
2762 Mantid::API::MatrixWorkspace_sptr inputWS = std::dynamic_pointer_cast<Mantid::API::MatrixWorkspace>(
2763 Mantid::API::AnalysisDataService::Instance().retrieve(workspaceName()));
2764
2765 try {
2766 findPeakStrategy->execute();
2767 clear();
2768 m_browser->setUpdatesEnabled(false);
2769 for (size_t i = 0; i < findPeakStrategy->peakNumber(); ++i) {
2770 if (findPeakStrategy->getPeakCentre(i) < startX() || findPeakStrategy->getPeakCentre(i) > endX()) {
2771 continue;
2772 }
2773 if (!createAndAddFunction(inputWS, i, findPeakStrategy)) {
2774 break;
2775 }
2776 }
2777 m_browser->setUpdatesEnabled(true);
2778 emit functionChanged();
2779 } catch (...) {
2780 m_browser->setUpdatesEnabled(true);
2781 QApplication::restoreOverrideCursor();
2782 throw;
2783 }
2784
2785 QApplication::restoreOverrideCursor();
2786}
2787
2789 m_peakToolOn = on;
2790 m_displayActionPlotGuess->setEnabled(on);
2791}
2792
2797 if (m_decimals < 0) {
2798 QSettings settings;
2799 settings.beginGroup("Mantid/FitBrowser");
2800 m_decimals = settings.value("decimals", 6).toInt();
2801 }
2802 QSet<QtProperty *> props = m_doubleManager->properties();
2803 for (QtProperty *prop : props) {
2804 m_doubleManager->setDecimals(prop, m_decimals);
2805 }
2806}
2807
2809 m_decimals = d;
2810 QSettings settings;
2811 settings.beginGroup("Mantid/FitBrowser");
2812 QSettingsChangeAware(settings).setValue("decimals", d);
2814}
2815
2817
2820
2822
2823void FitPropertyBrowser::setTextPlotGuess(const QString &text) { m_displayActionPlotGuess->setText(text); }
2824
2828void FitPropertyBrowser::workspaceChange(const QString &wsName) {
2829 if (m_guessOutputName) {
2830 m_stringManager->setValue(m_output, QString::fromStdString(workspaceName()));
2831 }
2832
2833 emit workspaceNameChanged(wsName);
2834 emit wsChangePPAssign(wsName);
2835}
2836
2841
2846 auto *dlg = new MultifitSetupDialog(this);
2847 dlg->exec();
2848 QStringList ties = dlg->getParameterTies();
2849
2850 if (!ties.isEmpty()) {
2851 QString wsName = QString::fromStdString(workspaceName());
2852 Mantid::API::MatrixWorkspace_sptr mws = std::dynamic_pointer_cast<Mantid::API::MatrixWorkspace>(
2853 Mantid::API::AnalysisDataService::Instance().retrieve(workspaceName()));
2854 if (mws) {
2855 auto fun = getFunctionAtIndex(0);
2856 QString fun1Ini = QString::fromStdString(fun->asString());
2857 QString funIni = "composite=MultiBG;" + fun1Ini + ",Workspace=" + wsName + ",WSParam=(WorkspaceIndex=0);";
2858 QString tieStr;
2859 for (size_t i = 1; i < mws->getNumberHistograms(); ++i) {
2860 QString comma = i > 1 ? "," : "";
2861 QString fi = comma + "f" + QString::number(i) + ".";
2862 for (int j = 0; j < static_cast<int>(fun->nParams()); ++j) {
2863 if (!ties[j].isEmpty()) {
2864 tieStr += fi + QString::fromStdString(fun->parameterName(j)) + "=" + ties[j];
2865 }
2866 }
2867 QString wsParam = ",WSParam=(WorkspaceIndex=" + QString::number(i);
2868 wsParam += ",StartX=" + QString::number(startX()) + ",EndX=" + QString::number(endX()) + ")";
2869 funIni += fun1Ini + ",Workspace=" + wsName + wsParam + ";";
2870 }
2871 if (!tieStr.isEmpty()) {
2872 funIni += "ties=(" + tieStr + ")";
2873 }
2874 loadFunction(funIni);
2875 }
2876 }
2877}
2878
2881 if (compositeFunction()->name() != "MultiBG")
2882 return;
2883
2884 // if all member functions are of the same type and composition
2885 // create a TableWorkspace with parameter series
2886
2887 // check if member functions are the same
2888 QStringList parNames;
2889 auto fun0 = getFunctionAtIndex(0);
2890 if (!fun0) {
2891 throw std::runtime_error("IFunction expected but func function of another type");
2892 }
2893 for (size_t i = 0; i < fun0->nParams(); ++i) {
2894 parNames << QString::fromStdString(fun0->parameterName(i));
2895 }
2896
2897 for (size_t i = 1; i < compositeFunction()->nFunctions(); ++i) {
2898 auto fun = getFunctionAtIndex(i);
2899 if (!fun) {
2900 throw std::runtime_error("IFunction expected but func function of another type");
2901 }
2902 for (size_t j = 0; j < fun->nParams(); ++j) {
2903 if (parNames.indexOf(QString::fromStdString(fun->parameterName(j))) < 0) {
2904 // Functions are different, stop
2905 return;
2906 }
2907 }
2908 }
2909
2910 QApplication::setOverrideCursor(Qt::WaitCursor);
2911 // create a TableWorkspace: first column - function index
2912 // other colomns - the parameters
2913 Mantid::API::ITableWorkspace_sptr table = Mantid::API::WorkspaceFactory::Instance().createTable("TableWorkspace");
2914 table->addColumn("int", "Index");
2915 for (const QString &par : parNames) {
2916 table->addColumn("double", par.toStdString());
2917 }
2918 // Create WorkspaceGroup with the fit results
2919 std::vector<std::string> worspaceNames(compositeFunction()->nFunctions());
2920 for (size_t i = 0; i < compositeFunction()->nFunctions(); ++i) {
2921 // Mantid::API::TableRow row = table->appendRow();
2922 // row << int(i);
2923 // Mantid::API::IFunctionMW* fun =
2924 // dynamic_cast<Mantid::API::IFunctionMW*>(compositeFunction()->getFunction(i));
2925 // for(size_t j = 0; j < fun->nParams(); ++j)
2926 //{
2927 // row << fun->getParameter(j);
2928 //}
2929 // size_t wi = fun->getWorkspaceIndex();
2930 // Mantid::API::MatrixWorkspace_sptr mws =
2931 // fun->createCalculatedWorkspace(fun->getMatrixWorkspace(),wi);
2932 // worspaceNames[i] =
2933 // workspaceNames()+"_"+QString::number(wi).toStdString()+"_Workspace";
2934 // Mantid::API::AnalysisDataService::Instance().addOrReplace(worspaceNames[i],mws);
2935 }
2936
2937 // Save the table
2938 Mantid::API::AnalysisDataService::Instance().addOrReplace(workspaceName() + "_Param_series", table);
2939 try {
2940 Mantid::API::IAlgorithm_sptr group = Mantid::API::AlgorithmManager::Instance().create("GroupWorkspaces");
2941 group->setProperty("InputWorkspaces", worspaceNames);
2942 group->setPropertyValue("OutputWorkspace", workspaceName() + "_Workspace");
2943 group->execute();
2944 } catch (...) {
2945 }
2946 QApplication::restoreOverrideCursor();
2947}
2948
2955 // remove old properties
2956 if (m_browser->isItemVisible(m_settingsGroup)) {
2957 if (m_settingsGroup->property()->subProperties().contains(m_workspaceIndex)) {
2958 m_settingsGroup->property()->removeSubProperty(m_workspaceIndex);
2959 } else if (m_settingsGroup->property()->subProperties().contains(m_xColumn)) {
2960 m_settingsGroup->property()->removeSubProperty(m_xColumn);
2961 m_settingsGroup->property()->removeSubProperty(m_yColumn);
2962 m_settingsGroup->property()->removeSubProperty(m_errColumn);
2963 }
2964 }
2965
2967 try {
2968 ws = Mantid::API::AnalysisDataService::Instance().retrieve(workspaceName());
2969 } catch (...) {
2970 return;
2971 }
2972 if (!ws)
2973 return;
2974
2975 // If this is a MuonFitPropertyBrowser, "evaluation type" goes in the Custom
2976 // Settings group.
2977 // If not, there is no Custom Settings group and it goes in the regular
2978 // Settings group.
2979 const auto *const settings = m_customSettingsGroup ? m_customSettingsGroup : m_settingsGroup;
2980
2981 if (settings->property()->subProperties().contains(m_evaluationType)) {
2982 settings->property()->removeSubProperty(m_evaluationType);
2983 m_evaluationType->setEnabled(false);
2984 // if it is a MatrixWorkspace insert WorkspaceIndex
2985 auto mws = std::dynamic_pointer_cast<Mantid::API::MatrixWorkspace>(ws);
2986 if (mws) {
2988 auto isHistogram = mws->isHistogramData();
2989 m_evaluationType->setEnabled(isHistogram);
2990 if (isHistogram) {
2991 settings->property()->addSubProperty(m_evaluationType);
2992 }
2993 return;
2994 }
2995 }
2996
2997 // if it is a TableWorkspace insert the column properties
2998 auto tws = std::dynamic_pointer_cast<Mantid::API::ITableWorkspace>(ws);
2999 if (tws) {
3001 // insert properties
3002 m_settingsGroup->property()->insertSubProperty(m_xColumn, m_workspace);
3003 m_settingsGroup->property()->insertSubProperty(m_yColumn, m_xColumn);
3004 m_settingsGroup->property()->insertSubProperty(m_errColumn, m_yColumn);
3006 return;
3007 QString xName;
3008 QString yName;
3009 QString errName;
3010 auto names = tws->getColumnNames();
3011 QStringList columns;
3012 for (const auto &name : names) {
3013 columns << QString::fromStdString(name);
3014 auto col = tws->getColumn(name);
3015 if (xName.isEmpty() && col->getPlotType() == 1 /*X*/) {
3016 xName = QString::fromStdString(name);
3017 }
3018 if (yName.isEmpty() && col->getPlotType() == 2 /*Y*/) {
3019 yName = QString::fromStdString(name);
3020 }
3021 if (errName.isEmpty() && col->getPlotType() == 5 /*yErr*/) {
3022 errName = QString::fromStdString(name);
3023 }
3024 }
3025 m_columnManager->setEnumNames(m_xColumn, columns);
3026 m_columnManager->setEnumNames(m_yColumn, columns);
3027 // set the column values
3028 if (!xName.isEmpty()) {
3029 m_columnManager->setValue(m_xColumn, static_cast<int>(columns.indexOf(xName)));
3030 } else {
3031 if (auto name = std::find_if(std::cbegin(columns), std::cend(columns), [&](const auto x) { return x != yName; });
3032 name != std::cend(columns)) {
3033 m_columnManager->setValue(m_xColumn, static_cast<int>(columns.indexOf(*name)));
3034 }
3035 }
3036 if (!yName.isEmpty()) {
3037 m_columnManager->setValue(m_yColumn, static_cast<int>(columns.indexOf(yName)));
3038 } else {
3039 if (auto name = std::find_if(std::cbegin(columns), std::cend(columns), [&](const auto x) { return x != xName; });
3040 name != std::cend(columns)) {
3041 m_columnManager->setValue(m_yColumn, static_cast<int>(columns.indexOf(*name)));
3042 }
3043 }
3044 columns.prepend("");
3045 m_columnManager->setEnumNames(m_errColumn, columns);
3046 if (!errName.isEmpty()) {
3047 m_columnManager->setValue(m_errColumn, static_cast<int>(columns.indexOf(errName)));
3048 } else {
3049 m_columnManager->setValue(m_errColumn, 0);
3050 }
3051 return;
3052 }
3053}
3054
3056 if (m_browser->isItemVisible(m_settingsGroup)) {
3057 if (!m_settingsGroup->property()->subProperties().contains(m_workspaceIndex)) {
3058 m_settingsGroup->property()->insertSubProperty(m_workspaceIndex, m_workspace);
3059 }
3060 }
3061}
3062
3067
3072 if (m_browser->isItemVisible(m_settingsGroup)) {
3073 m_browser->setItemVisible(m_settingsGroup, false);
3074 } else {
3075 m_browser->setItemVisible(m_settingsGroup, true);
3076 }
3077}
3078
3083void FitPropertyBrowser::removePropertiesFromSettingsBrowser(const QStringList &propsToRemove) {
3084 // get settings properties
3085 QList<QtProperty *> props = m_settingsGroup->property()->subProperties();
3086 for (auto &prop : props) {
3087 if (propsToRemove.contains(prop->propertyName())) {
3088 m_settingsGroup->property()->removeSubProperty(prop);
3089 }
3090 }
3091}
3092
3094
3101 if (prop == m_xColumn) { // update startX and endX
3102 try {
3103 auto ws = Mantid::API::AnalysisDataService::Instance().retrieve(workspaceName());
3104 auto tws = std::dynamic_pointer_cast<Mantid::API::ITableWorkspace>(ws);
3105 if (!tws)
3106 return;
3107 int i = m_columnManager->value(m_xColumn);
3108 if (i < 0 || i >= static_cast<int>(tws->rowCount()) || tws->rowCount() == 0)
3109 return;
3110 auto col = tws->getColumn(static_cast<size_t>(i));
3111 const double startXVal = col->toDouble(0);
3112 const double endXVal = col->toDouble(tws->rowCount() - 1);
3113 m_doubleManager->setValue(m_startX, startXVal);
3114 m_doubleManager->setValue(m_endX, endXVal);
3115 } catch (...) {
3116 // do nothing
3117 }
3118 }
3119}
3120
3125 // delete old minimizer properties
3126 for (QtProperty *prop : m_minimizerProperties) {
3127 m_settingsGroup->property()->removeSubProperty(prop);
3128 }
3129
3130 // add new minimizer properties
3131 auto minzer = Mantid::API::FuncMinimizerFactory::Instance().createMinimizer(this->minimizer());
3132 const auto &properties = minzer->getProperties();
3133 for (auto property : properties) {
3134 QString propName = QString::fromStdString((*property).name());
3135 QtProperty *prop = nullptr;
3136 if (const auto prp = dynamic_cast<const Mantid::Kernel::PropertyWithValue<bool> *const>(property)) {
3137 prop = m_boolManager->addProperty(propName);
3138 bool val = *prp;
3139 m_boolManager->setValue(prop, val);
3140 } else if (const auto prp = dynamic_cast<const Mantid::Kernel::PropertyWithValue<double> *const>(property)) {
3141 prop = this->addDoubleProperty(propName);
3142 double val = *prp;
3143 m_doubleManager->setValue(prop, val);
3144 } else if (const auto prp = dynamic_cast<const Mantid::Kernel::PropertyWithValue<int> *const>(property)) {
3145 prop = m_intManager->addProperty(propName);
3146 int val = *prp;
3147 m_intManager->setValue(prop, val);
3148 } else if (const auto prp = dynamic_cast<const Mantid::Kernel::PropertyWithValue<size_t> *const>(property)) {
3149 prop = m_intManager->addProperty(propName);
3150 size_t val = *prp;
3151 m_intManager->setValue(prop, static_cast<int>(val));
3152 } else if (const auto prp = dynamic_cast<const Mantid::Kernel::PropertyWithValue<std::string> *const>(property)) {
3153 prop = m_stringManager->addProperty(propName);
3154 QString val = QString::fromStdString(prp->value());
3155 m_stringManager->setValue(prop, val);
3156 } else if (dynamic_cast<Mantid::API::IWorkspaceProperty *>(property)) {
3157 prop = m_stringManager->addProperty(propName);
3158 m_stringManager->setValue(prop, QString::fromStdString((*property).value()));
3159 } else {
3160 QMessageBox::warning(this, "Mantid - Error",
3161 "Type of minimizer's property " + propName + " is not yet supported by the browser.");
3162 continue;
3163 }
3164
3165 if (!prop)
3166 continue;
3167 // set the tooltip from property doc string
3168 QString toolTip = QString::fromStdString((*property).documentation());
3169 if (!toolTip.isEmpty()) {
3170 prop->setToolTip(toolTip);
3171 }
3172 m_settingsGroup->property()->addSubProperty(prop);
3173 m_minimizerProperties.append(prop);
3174 }
3175}
3176
3181 auto fun = theFunction();
3182 size_t np = fun->nParams();
3183 QList<double> out;
3184 for (size_t i = 0; i < np; ++i) {
3185 const double parValue = fun->getParameter(i);
3186 out.append(parValue);
3187 }
3188 return out;
3189}
3190
3195 auto fun = theFunction();
3196 size_t np = fun->nParams();
3197 QStringList out;
3198 for (size_t i = 0; i < np; ++i) {
3199 std::string parName = fun->parameterName(i);
3200 out.append(QString::fromStdString(parName));
3201 }
3202 return out;
3203}
3208
3213
3218 const PropertyHandler *const handler = currentHandler();
3219 if (handler) {
3221 }
3222}
3223
3228 MantidQt::API::HelpWindow::showPage(QStringLiteral("workbench/plotwindow.html"));
3229}
3230
3237 if (m_fitActionSeqFit) {
3238 if (allow) {
3239 m_fitActionSeqFit->setEnabled(m_compositeFunction->nFunctions() > 0);
3240 } else {
3241 m_fitActionSeqFit->setEnabled(false);
3242 }
3243 }
3244}
3245
3246void FitPropertyBrowser::modifyFitMenu(QAction *fitAction, bool enabled) {
3247 if (enabled) {
3248 m_fitMenu->addAction(fitAction);
3249 } else {
3250 m_fitMenu->removeAction(fitAction);
3251 }
3252}
3253
3255 return static_cast<int>(m_functionsGroup->children().size());
3256}
3257
3258void FitPropertyBrowser::addAllowedSpectra(const QString &wsName, const QList<int> &wsSpectra) {
3259 auto const name = wsName.toStdString();
3260 auto ws = AnalysisDataService::Instance().retrieveWS<MatrixWorkspace>(name);
3261 if (ws) {
3262 QList<int> indices;
3263 indices.reserve(wsSpectra.size());
3264 std::transform(wsSpectra.cbegin(), wsSpectra.cend(), std::back_inserter(indices),
3265 [&ws](const auto i) { return static_cast<int>(ws->getIndexFromSpectrumNumber(i)); });
3266
3267 auto wsFound = m_allowedSpectra.find(wsName);
3268 m_allowedSpectra.insert(wsName, indices);
3269 if (wsFound != m_allowedSpectra.end()) {
3270 // we already knew about this workspace
3271 // update workspace index list
3273 } else {
3274 // new workspace, update workspace names
3276 }
3277 } else {
3278 throw std::runtime_error("Workspace " + name + " is not a MatrixWorkspace");
3279 }
3280}
3281
3282void FitPropertyBrowser::removeWorkspaceAndSpectra(const std::string &wsName) {
3283 removeWorkspace(wsName);
3284 // remove spectra. The find must be checked before it is erased: erasing end() is undefined
3285 // behaviour, and a caller removing a workspace this browser was never told about - or removing the
3286 // same one twice - reaches here with no entry to erase.
3287 QString qWsName = QString::fromStdString(wsName);
3288 auto const spectra = m_allowedSpectra.find(qWsName);
3289 if (spectra != m_allowedSpectra.end()) {
3290 m_allowedSpectra.erase(spectra);
3291 }
3292}
3293
3295 auto const name = wsName.toStdString();
3296 auto ws = AnalysisDataService::Instance().retrieveWS<ITableWorkspace>(name);
3297 if (ws) {
3298 m_allowedTableWorkspace = wsName;
3299 } else {
3300 throw std::runtime_error("Workspace " + name + " is not a TableWorkspace");
3301 }
3302}
3303
3312QString FitPropertyBrowser::addFunction(const QString &fnName) {
3313 return addFunction(fnName.toStdString())->functionPrefix();
3314}
3315
3317 const std::unique_ptr<FindPeakStrategyGeneric> &findPeakStrategy) {
3318 bool validFn = false;
3319 auto f = std::dynamic_pointer_cast<Mantid::API::IPeakFunction>(
3320 Mantid::API::FunctionFactory::Instance().createFunction(defaultPeakType()));
3321 if (f) {
3322 validFn = true;
3323 f->setMatrixWorkspace(inputWS, workspaceIndex(), startX(), endX());
3324 f->setCentre(findPeakStrategy->getPeakCentre(peakIndex));
3325 f->setFwhm(findPeakStrategy->getPeakWidth(peakIndex));
3326 f->setHeight(findPeakStrategy->getPeakHeight(peakIndex));
3327 addFunction(f->asString(), false);
3328 }
3329 return validFn;
3330}
3331
3333 if (prefix.isEmpty())
3334 throw std::runtime_error("Peak function prefix cannot be empty");
3335 auto const indexList = prefix.split(".");
3336 auto const n = indexList.size() - 1;
3337 auto const *handler = getHandler();
3338 for (int i = 0; i < n; ++i) {
3339 auto const index = indexList[i].mid(1).toInt();
3340 handler = handler->getHandler(index);
3341 }
3342 return handler->getHandler(indexList[n].mid(1).toInt());
3343}
3344
3345void FitPropertyBrowser::setPeakCentreOf(const QString &prefix, double value) {
3346 auto handler = getPeakHandler(prefix);
3347 handler->setCentre(value);
3348 handler->updateParameters();
3349}
3350
3351double FitPropertyBrowser::getPeakCentreOf(const QString &prefix) {
3352 const auto *handler = getPeakHandler(prefix);
3353 return handler->centre();
3354}
3355
3356void FitPropertyBrowser::setPeakHeightOf(const QString &prefix, double value) {
3357 auto handler = getPeakHandler(prefix);
3358 handler->setHeight(value);
3359 handler->updateParameters();
3360}
3361
3362double FitPropertyBrowser::getPeakHeightOf(const QString &prefix) {
3363 const auto *handler = getPeakHandler(prefix);
3364 return handler->height();
3365}
3366
3367void FitPropertyBrowser::setPeakFwhmOf(const QString &prefix, double value) {
3368 auto handler = getPeakHandler(prefix);
3369 handler->setFwhm(value);
3370 handler->updateParameters();
3371}
3372
3373double FitPropertyBrowser::getPeakFwhmOf(const QString &prefix) {
3374 const auto *handler = getPeakHandler(prefix);
3375 return handler->fwhm();
3376}
3377
3378std::string FitPropertyBrowser::getWidthParameterNameOf(const QString &prefix) {
3379 const auto *handler = getPeakHandler(prefix);
3380 return handler->getWidthParameterName();
3381}
3382
3383std::string FitPropertyBrowser::getCentreParameterNameOf(const QString &prefix) {
3384 const auto *handler = getPeakHandler(prefix);
3385 return handler->getCentreParameterName();
3386}
3387
3388bool FitPropertyBrowser::isParameterExplicitlySetOf(const QString &prefix, const std::string &param) {
3389 const auto *handler = getPeakHandler(prefix);
3390 return handler->isParameterExplicitlySet(param);
3391}
3392
3394 QStringList peaks;
3395 const auto *parentHandler = getHandler();
3396 const auto nFunctions = parentHandler->cfun()->nFunctions();
3397 for (size_t i = 0; i < nFunctions; ++i) {
3398 const auto *handler = parentHandler->getHandler(i);
3399 if (handler->pfun()) {
3400 peaks << handler->functionPrefix();
3401 }
3402 }
3403 return peaks;
3404}
3405
3406} // namespace MantidWidgets
3407} // 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.
void setStartX(double start) override
Set the start X.
void currentItemChanged(const QtBrowserItem *)
Slot.
void addAutoBackground()
Creates and adds the autobackground.
QStringList m_registeredOther
A list of registered functions that are neither peaks nor backgrounds.
bool isUndoEnabled() const
Tells if undo can be done.
FitPropertyBrowser(QWidget *parent=nullptr, QObject *mantidui=nullptr)
Constructor.
void createEditors(QWidget *w)
Create editors and assign them to the managers.
QtProperty * getTieProperty(QtProperty *parProp) const
Returns the tie property for a parameter property, or NULL.
void removeBounds()
Slot.Removes lower and upper bounds from the selected parameter property.
void addUpperBound()
Slot.Adds upper bound to the selected parameter property.
Mantid::API::IFunction_sptr getFittingFunction() const
Return the fitting function.
std::vector< double > m_initialParameters
To keep a copy of the initial parameters in case for undo fit.
void handleFactoryUpdate(Mantid::API::FunctionFactoryUpdateNotification_ptr)
Callback for FunctionFactory update notifications.
void doFit(int maxIterations)
Do the fitting.
virtual void intChanged(QtProperty *prop)
Called when an int property changed.
bool isPeak() const
Is the current function a peak?
bool isFitEnabled() const
Returns true if the function is ready for a fit.
int maxIterations() const
Get the max number of iterations.
QtGroupPropertyManager * m_groupManager
Property managers:
void paste()
Paste a function string from the clipboard.
int m_oldWorkspaceIndex
Store workspace index to revert to in case validation fails.
QStringList m_registeredPeaks
A list of registered peaks.
QString m_allowedTableWorkspace
If set it contains the table workspace name to be fitted in this browser:
bool m_auto_back
If true background function will be included automatically.
virtual void doubleChanged(QtProperty *prop)
Called when a double property changed.
int getAllowedIndex(int currentIndex) const
Return the nearest allowed workspace index.
PropertyHandler * currentHandler() const
Get the current function.
void addUpperBound10()
Slot.Adds upper bound to the selected parameter property.
QList< double > getParameterValues() const
Get function parameter values.
void setStringPropertyValue(QtProperty *prop, const QString &value) const
Set a value to a string property.
std::string m_defaultFunction
Default function name.
bool ignoreInvalidData() const
Get the ignore invalid data option.
void modifyFitMenu(QAction *fitAction, bool enabled)
void addFitResultWorkspacesToTableWidget()
Adds the fit result workspaces to the QListWidget in the browser.
virtual void removeFunction(PropertyHandler *handler)
Removes the function held by the property handler.
virtual void setWorkspaceName(const QString &wsName) override
Set the input workspace name.
void workspaceClicked(const QString &wsName)
void setWorkspaceIndex(int i) override
Set workspace index.
void removeWorkspaceAndSpectra(const std::string &wsName)
void updateBrowserFromFitResults(const Mantid::API::IFunction_sptr &finalFunction)
Set the parameters to the fit outcome.
std::string defaultPeakType()
Get the default peak type.
void allowSequentialFits(bool allow) override
Allow or disallow sequential fits (depending on whether other conditions are met)
void functionHelp()
Open a web page with description of the current function.
void setupMultifit()
Call MultifitSetupDialog to populate MultiBG function.
void updateStructureTooltips()
Update structure tooltips for all functions.
virtual void setFitEnabled(bool enable)
Enable/disable the Fit buttons;.
std::string getWidthParameterNameOf(const QString &prefix)
const QStringList & getWorkspaceNames()
Returns the list of workspaces that are currently been worked on by the fit property browser.
const std::string & defaultFunctionType() const
Get the default function type.
QList< double > getXRange()
Get the X limits of the workspace.
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.
A QSettings facade that applies only effective changes.
bool remove(QString const &key)
Remove a key or group only when it contains a value.
bool setValue(QString const &key, QVariant const &value)
Set a value only when the effective stored value differs.
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:771
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:748
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:750
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