Mantid
Loading...
Searching...
No Matches
FitPropertyBrowser.cpp
Go to the documentation of this file.
1// Mantid Repository : https://github.com/mantidproject/mantid
2//
3// Copyright © 2018 ISIS Rutherford Appleton Laboratory UKRI,
4// NScD Oak Ridge National Laboratory, European Spallation Source,
5// Institut Laue - Langevin & CSNS, Institute of High Energy Physics, CAS
6// SPDX - License - Identifier: GPL - 3.0 +
13
26#include "MantidAPI/TableRow.h"
28
30#include "MantidKernel/Logger.h"
31
32#include "MantidQtWidgets/Common/QtPropertyBrowser/FilenameDialogEditor.h"
33#include "MantidQtWidgets/Common/QtPropertyBrowser/FormulaDialogEditor.h"
34#include "MantidQtWidgets/Common/QtPropertyBrowser/StringEditorFactory.h"
35
36#include "MantidQtWidgets/Common/QtPropertyBrowser/DoubleEditorFactory.h"
37#include "MantidQtWidgets/Common/QtPropertyBrowser/ParameterPropertyManager.h"
38#include "MantidQtWidgets/Common/QtPropertyBrowser/qteditorfactory.h"
39#include "MantidQtWidgets/Common/QtPropertyBrowser/qttreepropertybrowser.h"
40
41#include <Poco/ActiveResult.h>
42
43#include <QApplication>
44#include <QClipboard>
45#include <QGridLayout>
46#include <QInputDialog>
47#include <QListWidget>
48#include <QMenu>
49#include <QMessageBox>
50#include <QPushButton>
51#include <QSettings>
52#include <QSignalMapper>
53#include <QTreeWidget>
54#include <QUrl>
55#include <QVBoxLayout>
56
57#include <algorithm>
58#include <utility>
59
60namespace MantidQt {
61using API::MantidDesktopServices;
62
63namespace MantidWidgets {
64
65namespace {
66Mantid::Kernel::Logger g_log("FitPropertyBrowser");
67
68using namespace Mantid::API;
69
70int getNumberOfSpectra(const MatrixWorkspace_sptr &workspace) {
71 return static_cast<int>(workspace->getNumberHistograms());
72}
73} // namespace
74
80FitPropertyBrowser::FitPropertyBrowser(QWidget *parent, QObject *mantidui)
81 : QDockWidget("Fit Function", parent), m_workspaceIndex(nullptr), m_startX(nullptr), m_endX(nullptr),
82 m_output(nullptr), m_minimizer(nullptr), m_ignoreInvalidData(nullptr), m_costFunction(nullptr),
83 m_maxIterations(nullptr), m_peakRadius(nullptr), m_plotDiff(nullptr), m_excludeRange(nullptr),
84 m_plotCompositeMembers(nullptr), m_convolveMembers(nullptr), m_rawData(nullptr), m_xColumn(nullptr),
85 m_yColumn(nullptr), m_errColumn(nullptr), m_showParamErrors(nullptr), m_evaluationType(nullptr),
86 m_compositeFunction(), m_browser(nullptr), m_fitActionUndoFit(nullptr), m_fitActionSeqFit(nullptr),
87 m_fitActionFit(nullptr), m_fitActionEvaluate(nullptr), m_functionsGroup(nullptr), m_settingsGroup(nullptr),
88 m_customSettingsGroup(nullptr), m_changeSlotsEnabled(false), m_guessOutputName(true),
89 m_updateObserver(*this, &FitPropertyBrowser::handleFactoryUpdate), m_fitMapper(nullptr), m_fitMenu(nullptr),
90 m_displayActionPlotGuess(nullptr), m_displayActionQuality(nullptr), m_displayActionClearAll(nullptr),
91 m_setupActionCustomSetup(nullptr), m_setupActionRemove(nullptr), m_tip(nullptr), m_fitSelector(nullptr),
92 m_fitTree(nullptr), m_currentHandler(nullptr), m_defaultFunction("Gaussian"), m_defaultPeak("Gaussian"),
93 m_defaultBackground("LinearBackground"), m_peakToolOn(false), m_hideWsListWidget(false), m_auto_back(false),
94 m_autoBgName(
95 QString::fromStdString(Mantid::Kernel::ConfigService::Instance().getString("curvefitting.autoBackground"))),
96 m_autoBackground(nullptr), m_decimals(-1), m_mantidui(mantidui), m_shouldBeNormalised(false),
97 m_fitAlgParameters(""), m_oldWorkspaceIndex(-1) {
99
100 // If Gaussian does not exist then the plugins did not load.
101 if (!Mantid::API::FunctionFactory::Instance().exists("Gaussian")) {
102 throw std::runtime_error("FitPropertyBrowser: Unable to find Gaussian function\n"
103 "Has the CurveFitting plugin loaded?");
104 }
105 if (m_autoBgName.toLower() == "none") {
106 m_autoBgName = "";
107 } else {
109 }
110
111 std::string def = Mantid::Kernel::ConfigService::Instance().getString("curvefitting.defaultPeak");
112 if (!def.empty()) {
113 m_defaultPeak = def;
114 }
115
116 def = Mantid::Kernel::ConfigService::Instance().getString("curvefitting.autoBackground");
117 if (!def.empty()) {
119 }
121
122 setObjectName("FitFunction"); // this is needed for QMainWindow::restoreState()
123 setMinimumHeight(150);
124 setMinimumWidth(200);
125
126 QWidget *w = new QWidget(this);
127
128 /* Create property managers: they create, own properties, get and set values
129 */
130 m_groupManager = new QtGroupPropertyManager(w);
131 m_doubleManager = new QtDoublePropertyManager(w);
132 m_stringManager = new QtStringPropertyManager(w);
133 m_enumManager = new QtEnumPropertyManager(w);
134 m_intManager = new QtIntPropertyManager(w);
135 m_boolManager = new QtBoolPropertyManager(w);
136 m_filenameManager = new QtStringPropertyManager(w);
137 m_formulaManager = new QtStringPropertyManager(w);
138 m_columnManager = new QtEnumPropertyManager(w);
139 m_workspace = m_enumManager->addProperty("Workspace");
140 m_vectorManager = new QtGroupPropertyManager(w);
141 m_vectorSizeManager = new QtIntPropertyManager(w);
142 m_vectorDoubleManager = new QtDoublePropertyManager(w);
143 m_parameterManager = new ParameterPropertyManager(w);
144}
145
150 QWidget *w = new QWidget(this);
151
152 QSettings settings;
153 settings.beginGroup("Mantid/FitBrowser");
154
155 /* Create function group */
156 QtProperty *functionsGroup = m_groupManager->addProperty("Functions");
157
158 if (m_mantidui) {
159 connect(this, SIGNAL(xRangeChanged(double, double)), m_mantidui, SLOT(x_range_from_picker(double, double)));
160 }
161 /* Create input - output properties */
162 QtProperty *settingsGroup = m_groupManager->addProperty("Settings");
163 m_startX = addDoubleProperty("StartX");
164 m_endX = addDoubleProperty("EndX");
165
166 m_workspaceIndex = m_intManager->addProperty("Workspace Index");
167 m_output = m_stringManager->addProperty("Output");
168 m_minimizer = m_enumManager->addProperty("Minimizer");
169 m_minimizers << "Levenberg-Marquardt"
170 << "Levenberg-MarquardtMD"
171 << "Trust Region"
172 << "Simplex"
173 << "FABADA"
174 << "Conjugate gradient (Fletcher-Reeves imp.)"
175 << "Conjugate gradient (Polak-Ribiere imp.)"
176 << "BFGS"
177 << "Damped GaussNewton";
178
179 m_ignoreInvalidData = m_boolManager->addProperty("Ignore invalid data");
180 setIgnoreInvalidData(settings.value("Ignore invalid data", false).toBool());
181
182 m_enumManager->setEnumNames(m_minimizer, m_minimizers);
183 m_costFunction = m_enumManager->addProperty("Cost function");
184 m_costFunctions << "Least squares"
185 << "Rwp"
186 << "Unweighted least squares"
187 << "Poisson";
189 m_maxIterations = m_intManager->addProperty("Max Iterations");
190 m_intManager->setValue(m_maxIterations, settings.value("Max Iterations", 500).toInt());
191
192 m_peakRadius = m_intManager->addProperty("Peak Radius");
193 m_intManager->setValue(m_peakRadius, settings.value("Peak Radius", 0).toInt());
194
195 m_plotDiff = m_boolManager->addProperty("Plot Difference");
196 bool plotDiff = settings.value("Plot Difference", QVariant(true)).toBool();
198
199 m_excludeRange = m_stringManager->addProperty("Exclude Range");
200 m_excludeRange->setToolTip("A list of pairs of real numbers which define the region to exclude");
201
202 m_plotCompositeMembers = m_boolManager->addProperty("Plot Composite Members");
203 bool plotCompositeItems = settings.value(m_plotCompositeMembers->propertyName(), QVariant(false)).toBool();
204 m_boolManager->setValue(m_plotCompositeMembers, plotCompositeItems);
205
206 m_convolveMembers = m_boolManager->addProperty("Convolve Composite Members");
207 bool convolveCompositeItems = settings.value(m_plotCompositeMembers->propertyName(), QVariant(false)).toBool();
208 m_boolManager->setValue(m_convolveMembers, convolveCompositeItems);
209
210 m_showParamErrors = m_boolManager->addProperty("Show Parameter Errors");
211 bool showParamErrors = settings.value(m_showParamErrors->propertyName(), false).toBool();
212 m_boolManager->setValue(m_showParamErrors, showParamErrors);
213 m_parameterManager->setErrorsEnabled(showParamErrors);
214
215 m_evaluationType = m_enumManager->addProperty("Evaluate Function As");
216 m_evaluationType->setToolTip("Consider using Histogram fit which may produce more accurate results.");
217 m_evaluationTypes << "CentrePoint"
218 << "Histogram";
220 int evaluationType = settings.value(m_evaluationType->propertyName(), 0).toInt();
221 m_enumManager->setValue(m_evaluationType, evaluationType);
222
223 m_xColumn = m_columnManager->addProperty("XColumn");
224 m_yColumn = m_columnManager->addProperty("YColumn");
225 m_errColumn = m_columnManager->addProperty("ErrColumn");
226
227 settingsGroup->addSubProperty(m_workspace);
228 settingsGroup->addSubProperty(m_startX);
229 settingsGroup->addSubProperty(m_endX);
230
231 // Only include the cost function when in the dock widget inside mantid plot,
232 // not on muon analysis widget
233 // Include minimiser and plot difference under a different settings section.
234 settingsGroup->addSubProperty(m_output);
235 settingsGroup->addSubProperty(m_minimizer);
236 settingsGroup->addSubProperty(m_ignoreInvalidData);
237 settingsGroup->addSubProperty(m_costFunction);
238 settingsGroup->addSubProperty(m_maxIterations);
239 settingsGroup->addSubProperty(m_peakRadius);
240 settingsGroup->addSubProperty(m_plotDiff);
241 settingsGroup->addSubProperty(m_excludeRange);
242 settingsGroup->addSubProperty(m_plotCompositeMembers);
243 settingsGroup->addSubProperty(m_convolveMembers);
244 settingsGroup->addSubProperty(m_showParamErrors);
245 settingsGroup->addSubProperty(m_evaluationType);
246
247 /* Create editors and assign them to the managers */
248 createEditors(w);
249
251
252 m_functionsGroup = m_browser->addProperty(functionsGroup);
253 m_settingsGroup = m_browser->addProperty(settingsGroup);
254
255 initLayout(w);
256}
257
268
278 auto *btnFit = new QPushButton("Fit");
279 m_tip = new QLabel("", w);
280
281 m_fitMapper = new QSignalMapper(this);
282 m_fitMenu = new QMenu(this);
284 connect(m_fitMapper, SIGNAL(mapped(const QString &)), this, SLOT(executeFitMenu(const QString &)));
285 btnFit->setMenu(m_fitMenu);
286 return btnFit;
287}
288
297void FitPropertyBrowser::populateFitMenuButton(QSignalMapper *fitMapper, QMenu *fitMenu) {
298 // assert(fitmapper);
299
300 m_fitActionFit = new QAction("Fit", this);
301 m_fitActionSeqFit = new QAction("Sequential Fit", this);
302 m_fitActionUndoFit = new QAction("Undo Fit", this);
303 m_fitActionEvaluate = new QAction("Evaluate function", this);
304
305 fitMapper->setMapping(m_fitActionFit, "Fit");
306 fitMapper->setMapping(m_fitActionSeqFit, "SeqFit");
307 fitMapper->setMapping(m_fitActionUndoFit, "UndoFit");
308 fitMapper->setMapping(m_fitActionEvaluate, "Evaluate");
309
310 connect(m_fitActionFit, SIGNAL(triggered()), fitMapper, SLOT(map()));
311 connect(m_fitActionSeqFit, SIGNAL(triggered()), fitMapper, SLOT(map()));
312 connect(m_fitActionUndoFit, SIGNAL(triggered()), fitMapper, SLOT(map()));
313 connect(m_fitActionEvaluate, SIGNAL(triggered()), fitMapper, SLOT(map()));
314
315 fitMenu->addAction(m_fitActionFit);
316 fitMenu->addAction(m_fitActionSeqFit);
317 fitMenu->addAction(m_fitActionEvaluate);
318 fitMenu->addSeparator();
319 fitMenu->addAction(m_fitActionUndoFit);
320 fitMenu->addSeparator();
321}
332 QPushButton *btnFit = createFitMenuButton(w);
333 btnFit->setObjectName("button_Fit");
334 // to be able to change windows title from tread
335 connect(this, SIGNAL(changeWindowTitle(const QString &)), this, SLOT(setWindowTitle(const QString &)));
336
337 /* Create the top level group */
338
339 m_groupManager->addProperty("Fit");
340
341 connect(m_enumManager, SIGNAL(propertyChanged(QtProperty *)), this, SLOT(enumChanged(QtProperty *)));
342 connect(m_boolManager, SIGNAL(propertyChanged(QtProperty *)), this, SLOT(boolChanged(QtProperty *)));
343 connect(m_intManager, SIGNAL(propertyChanged(QtProperty *)), this, SLOT(intChanged(QtProperty *)));
344 connect(m_doubleManager, SIGNAL(propertyChanged(QtProperty *)), this, SLOT(doubleChanged(QtProperty *)));
345 connect(m_stringManager, SIGNAL(propertyChanged(QtProperty *)), this, SLOT(stringChanged(QtProperty *)));
346 connect(m_filenameManager, SIGNAL(propertyChanged(QtProperty *)), this, SLOT(stringChanged(QtProperty *)));
347 connect(m_formulaManager, SIGNAL(propertyChanged(QtProperty *)), this, SLOT(stringChanged(QtProperty *)));
348 connect(m_columnManager, SIGNAL(propertyChanged(QtProperty *)), this, SLOT(columnChanged(QtProperty *)));
349 connect(m_vectorDoubleManager, SIGNAL(propertyChanged(QtProperty *)), this, SLOT(vectorDoubleChanged(QtProperty *)));
350 connect(m_parameterManager, SIGNAL(propertyChanged(QtProperty *)), this, SLOT(parameterChanged(QtProperty *)));
351 connect(m_vectorSizeManager, SIGNAL(propertyChanged(QtProperty *)), this, SLOT(vectorSizeChanged(QtProperty *)));
352
353 auto *layout = new QVBoxLayout(w);
354 layout->setObjectName("vlayout");
355 auto *buttonsLayout = new QGridLayout();
356
357 auto *btnDisplay = new QPushButton("Display");
358 btnDisplay->setObjectName("button_Display");
359 QMenu *displayMenu = new QMenu(this);
360 displayMenu->setObjectName("menu_Display");
361 m_displayActionPlotGuess = new QAction("Plot Guess", this);
362 m_displayActionPlotGuess->setEnabled(false);
363 m_displayActionQuality = new QAction("Quality", this);
364 m_displayActionQuality->setObjectName("action_Quality");
365 m_displayActionQuality->setCheckable(true);
366 m_displayActionQuality->setChecked(true);
367 m_displayActionClearAll = new QAction("Clear fit curves", this);
368 QSignalMapper *displayMapper = new QSignalMapper(this);
369 displayMapper->setObjectName("mapper_Display");
370
371 displayMapper->setMapping(m_displayActionPlotGuess, "PlotGuess");
372 displayMapper->setMapping(m_displayActionQuality, "Quality");
373 displayMapper->setMapping(m_displayActionClearAll, "ClearAll");
374 connect(m_displayActionPlotGuess, SIGNAL(triggered()), displayMapper, SLOT(map()));
375 connect(m_displayActionQuality, SIGNAL(triggered()), displayMapper, SLOT(map()));
376 connect(m_displayActionClearAll, SIGNAL(triggered()), displayMapper, SLOT(map()));
377 connect(displayMapper, SIGNAL(mapped(const QString &)), this, SLOT(executeDisplayMenu(const QString &)));
378 displayMenu->addAction(m_displayActionPlotGuess);
379 displayMenu->addAction(m_displayActionClearAll);
380 displayMenu->addAction(m_displayActionQuality);
381 btnDisplay->setMenu(displayMenu);
382
383 auto *btnSetup = new QPushButton("Setup");
384 btnSetup->setObjectName("button_Setup");
385 QMenu *setupMenu = new QMenu(this);
386 setupMenu->setObjectName("menu_Setup");
387
388 m_setupActionCustomSetup = new QAction("Custom Setup", this);
389 QAction *setupActionManageSetup = new QAction("Manage Setup", this);
390 setupActionManageSetup->setObjectName("action_ManageSetup");
391 QAction *setupActionFindPeaks = new QAction("Find Peaks", this);
392 setupActionFindPeaks->setObjectName("action_FindPeaks");
393 QAction *setupActionClearFit = new QAction("Clear Model", this);
394 setupActionClearFit->setObjectName("action_ClearModel");
395
396 QMenu *setupSubMenuCustom = new QMenu(this);
397 m_setupActionCustomSetup->setMenu(setupSubMenuCustom);
398 // empty menu for now, so set it disabled to avoid confusing users
399 m_setupActionCustomSetup->setEnabled(false);
400
401 QMenu *setupSubMenuManage = new QMenu(this);
402 QAction *setupActionSave = new QAction("Save Setup", this);
403 m_setupActionRemove = new QAction("Remove Setup", this);
404 QAction *setupActionClear = new QAction("Clear Setups", this);
405 setupActionClear->setObjectName("action_ClearSetups");
406 QAction *setupActionCopyToClipboard = new QAction("Copy To Clipboard", this);
407 setupActionCopyToClipboard->setObjectName("action_CopyToClipboard");
408 QAction *setupActionLoadFromString = new QAction("Load From String", this);
409 setupActionLoadFromString->setObjectName("action_LoadFromString");
410 QSignalMapper *setupManageMapper = new QSignalMapper(this);
411 setupManageMapper->setMapping(setupActionSave, "SaveSetup");
412 setupManageMapper->setMapping(setupActionCopyToClipboard, "CopyToClipboard");
413 setupManageMapper->setMapping(setupActionLoadFromString, "LoadFromString");
414 setupManageMapper->setMapping(setupActionClear, "ClearSetups");
415 connect(setupActionSave, SIGNAL(triggered()), setupManageMapper, SLOT(map()));
416 connect(setupActionCopyToClipboard, SIGNAL(triggered()), setupManageMapper, SLOT(map()));
417 connect(setupActionLoadFromString, SIGNAL(triggered()), setupManageMapper, SLOT(map()));
418 connect(setupActionClear, SIGNAL(triggered()), setupManageMapper, SLOT(map()));
419 connect(setupManageMapper, SIGNAL(mapped(const QString &)), this, SLOT(executeSetupManageMenu(const QString &)));
420 setupSubMenuManage->addAction(setupActionSave);
421 setupSubMenuManage->addAction(m_setupActionRemove);
422 setupSubMenuManage->addAction(setupActionClear);
423 setupSubMenuManage->addAction(setupActionCopyToClipboard);
424 setupSubMenuManage->addAction(setupActionLoadFromString);
425 setupActionManageSetup->setMenu(setupSubMenuManage);
426
427 QMenu *setupSubMenuRemove = new QMenu(this);
428 m_setupActionRemove->setMenu(setupSubMenuRemove);
429 // empty menu for now, so set it disabled to avoid confusing users
430 m_setupActionRemove->setEnabled(false);
431
432 QSignalMapper *setupMapper = new QSignalMapper(this);
433 setupMapper->setMapping(setupActionClearFit, "ClearFit");
434 setupMapper->setMapping(setupActionFindPeaks, "FindPeaks");
435 connect(setupActionClearFit, SIGNAL(triggered()), setupMapper, SLOT(map()));
436 connect(setupActionFindPeaks, SIGNAL(triggered()), setupMapper, SLOT(map()));
437 connect(setupMapper, SIGNAL(mapped(const QString &)), this, SLOT(executeSetupMenu(const QString &)));
438
439 setupMenu->addAction(m_setupActionCustomSetup);
440 setupMenu->addAction(setupActionManageSetup);
441 setupMenu->addSeparator();
442 setupMenu->addAction(setupActionFindPeaks);
443 setupMenu->addSeparator();
444 setupMenu->addAction(setupActionClearFit);
445 btnSetup->setMenu(setupMenu);
446
448
449 buttonsLayout->addWidget(btnFit, 0, 0);
450 buttonsLayout->addWidget(btnDisplay, 0, 1);
451 buttonsLayout->addWidget(btnSetup, 0, 2);
452
453 m_status = new QLabel("Status:", w);
454 m_status->hide();
455 connect(this, SIGNAL(fitResultsChanged(const QString &)), this, SLOT(showFitResultStatus(const QString &)),
456 Qt::QueuedConnection);
457 layout->addWidget(m_status);
458 layout->addLayout(buttonsLayout);
459 layout->addWidget(m_tip);
460 layout->addWidget(m_browser);
461 m_browser->setObjectName("tree_browser");
462
463 m_workspaceLabel = new QLabel("Workspaces");
464 layout->addWidget(m_workspaceLabel);
465 m_wsListWidget = new QListWidget();
466 layout->addWidget(m_wsListWidget);
467 m_workspaceLabel->hide();
468 m_wsListWidget->hide();
469
470 setWidget(w);
471
472 m_browser->setContextMenuPolicy(Qt::CustomContextMenu);
473 connect(m_browser, SIGNAL(customContextMenuRequested(const QPoint &)), this, SLOT(popupMenu(const QPoint &)));
474 connect(m_browser, SIGNAL(currentItemChanged(QtBrowserItem *)), this, SLOT(currentItemChanged(QtBrowserItem *)));
475 connect(this, SIGNAL(multifitFinished()), this, SLOT(processMultiBGResults()));
476
477 connect(m_wsListWidget, SIGNAL(itemDoubleClicked(QListWidgetItem *)), this,
478 SLOT(workspaceDoubleClicked(QListWidgetItem *)));
479
481
482 // Update tooltips when function structure is (or might've been) changed in
483 // any way
484 connect(this, SIGNAL(functionChanged()), SLOT(updateStructureTooltips()));
485 connect(this, SIGNAL(functionChanged()), SLOT(clearFitResultStatus()));
486
487 // Update available functions in this fit property browser, when the function
488 // factory changes.
490 FunctionFactory::Instance().notificationCenter.addObserver(m_updateObserver);
491 connect(this, SIGNAL(functionFactoryUpdateReceived()), this, SLOT(populateFunctionNames()));
492 FunctionFactory::Instance().enableNotifications();
493
494 // Initial call, as function is not changed when it's created for the first
495 // time
497
499
501}
502
503// Adds the fit result workspaces to the qlistwidget in the browser
505 const auto outName = outputName();
506 const std::vector<std::string> workspaceNames{outName + "_NormalisedCovarianceMatrix", outName + "_Parameters",
507 outName + "_Workspace"};
508
509 for (const auto &name : workspaceNames) {
510 // check if already in the list
511 auto foundInList = m_wsListWidget->findItems(QString::fromStdString(name), Qt::MatchExactly);
512 if (foundInList.size() == 0 && AnalysisDataService::Instance().doesExist(name)) {
513 new QListWidgetItem(QString::fromStdString(name), m_wsListWidget);
514 }
515 }
516
517 auto noOfItems = m_wsListWidget->count();
518 if (noOfItems != 0 && !m_hideWsListWidget) {
519 auto height = m_wsListWidget->sizeHintForRow(0) * (noOfItems + 1) + 2 * m_wsListWidget->frameWidth();
520 m_wsListWidget->setMaximumHeight(height);
521 m_workspaceLabel->show();
522 m_wsListWidget->show();
523 }
524}
525
527 auto wsName = item->text();
528 emit workspaceClicked(wsName);
529}
530
539 QtCheckBoxFactory *checkBoxFactory = new QtCheckBoxFactory(w);
540 QtEnumEditorFactory *comboBoxFactory = new QtEnumEditorFactory(w);
541 QtSpinBoxFactory *spinBoxFactory = new QtSpinBoxFactory(w);
542 DoubleEditorFactory *doubleEditorFactory = new DoubleEditorFactory(w);
543 StringEditorFactory *stringEditFactory = new StringEditorFactory(w);
544 FilenameDialogEditorFactory *filenameDialogEditorFactory = new FilenameDialogEditorFactory(w);
545 FormulaDialogEditorFactory *formulaDialogEditFactory = new FormulaDialogEditorFactory(w);
546
547 m_browser = new QtTreePropertyBrowser();
548 m_browser->setFactoryForManager(m_enumManager, comboBoxFactory);
549 m_browser->setFactoryForManager(m_boolManager, checkBoxFactory);
550 m_browser->setFactoryForManager(m_intManager, spinBoxFactory);
551 m_browser->setFactoryForManager(m_doubleManager, doubleEditorFactory);
552 m_browser->setFactoryForManager(m_stringManager, stringEditFactory);
553 m_browser->setFactoryForManager(m_filenameManager, filenameDialogEditorFactory);
554 m_browser->setFactoryForManager(m_formulaManager, formulaDialogEditFactory);
555 m_browser->setFactoryForManager(m_columnManager, comboBoxFactory);
556 m_browser->setFactoryForManager(m_vectorSizeManager, spinBoxFactory);
557 m_browser->setFactoryForManager(m_vectorDoubleManager, doubleEditorFactory);
558 m_browser->setFactoryForManager(m_parameterManager, new ParameterEditorFactory(w));
559}
560
564 QMenu *menuLoad = m_setupActionCustomSetup->menu();
565 menuLoad->clear();
566 QMenu *menuRemove = m_setupActionRemove->menu();
567 menuRemove->clear();
568
569 QSettings settings;
570 settings.beginGroup("Mantid/FitBrowser/SavedFunctions");
571 QStringList names = settings.childKeys();
572
573 QSignalMapper *mapperLoad = new QSignalMapper(this);
574 QSignalMapper *mapperRemove = new QSignalMapper(this);
575 // enable actions that open the menus only if there will be >=1 entries in
576 // there
577 m_setupActionCustomSetup->setEnabled(names.size() >= 1);
578 m_setupActionRemove->setEnabled(names.size() >= 1);
579 for (int i = 0; i < names.size(); i++) {
580 QAction *itemLoad = new QAction(names.at(i), this);
581 QAction *itemRemove = new QAction(names.at(i), this);
582 mapperLoad->setMapping(itemLoad, names.at(i));
583 mapperRemove->setMapping(itemRemove, names.at(i));
584 connect(itemLoad, SIGNAL(triggered()), mapperLoad, SLOT(map()));
585 connect(itemRemove, SIGNAL(triggered()), mapperRemove, SLOT(map()));
586 menuLoad->addAction(itemLoad);
587 menuRemove->addAction(itemRemove);
588 }
589 connect(mapperLoad, SIGNAL(mapped(const QString &)), this, SLOT(executeCustomSetupLoad(const QString &)));
590 connect(mapperRemove, SIGNAL(mapped(const QString &)), this, SLOT(executeCustomSetupRemove(const QString &)));
591}
592
594 QSettings settings;
595 settings.beginGroup("Mantid/FitBrowser/SavedFunctions");
596
597 QString str = settings.value(name).toString();
598 loadFunction(str);
599}
600
602 QSettings settings;
603 settings.beginGroup("Mantid/FitBrowser/SavedFunctions");
604
605 settings.remove(name);
607}
608
610 QSettings settings;
611 settings.beginGroup("Mantid/FitBrowser/SavedFunctions");
612
613 settings.clear();
615}
616
621 // Call tooltip update func on the root handler - it goes down recursively
623}
624
625void FitPropertyBrowser::executeFitMenu(const QString &item) {
626 if (item == "Fit") {
627 fit();
628 } else if (item == "SeqFit") {
630 } else if (item == "UndoFit") {
631 undoFit();
632 } else if (item == "Evaluate") {
633 doFit(0);
634 }
635}
636
637void FitPropertyBrowser::executeDisplayMenu(const QString &item) {
638 if (item == "PlotGuess") {
640 } else if (item == "ClearAll") {
642 }
643}
644
645void FitPropertyBrowser::executeSetupMenu(const QString &item) {
646 if (item == "ClearFit")
647 clear();
648 if (item == "FindPeaks")
649 findPeaks();
650}
651
653 if (item == "SaveSetup")
654 saveFunction();
655 if (item == "ClearSetups")
657 if (item == "CopyToClipboard")
658 copy();
659 if (item == "LoadFromString")
661}
662
665 m_compositeFunction.reset();
666
667 // remove the FunctionFactory Observer
669 FunctionFactory::Instance().notificationCenter.removeObserver(m_updateObserver);
670
671 m_browser->unsetFactoryForManager(m_enumManager);
672 m_browser->unsetFactoryForManager(m_boolManager);
673 m_browser->unsetFactoryForManager(m_intManager);
674 m_browser->unsetFactoryForManager(m_doubleManager);
675 m_browser->unsetFactoryForManager(m_stringManager);
676 m_browser->unsetFactoryForManager(m_filenameManager);
677 m_browser->unsetFactoryForManager(m_formulaManager);
678 m_browser->unsetFactoryForManager(m_columnManager);
679 m_browser->unsetFactoryForManager(m_vectorSizeManager);
680 m_browser->unsetFactoryForManager(m_vectorDoubleManager);
681 m_browser->unsetFactoryForManager(m_parameterManager);
682}
683
686 return static_cast<PropertyHandler *>(m_compositeFunction->getHandler());
687}
688
690 PropertyHandler *h = getHandler()->addFunction(fnName);
691 emit functionChanged();
692 return h;
693}
694
696 if (handler) {
697 emit functionRemoved();
698 emit functionChanged();
700 handler->removeFunction();
701 compositeFunction()->checkFunction();
702 }
703}
704
708 QtBrowserItem *ci = m_browser->currentItem();
709 // Find the function which has ci as its top browser item
710 auto cf = getHandler()->findCompositeFunction(ci);
711 if (!cf)
712 return;
713
714 // Declare new widget for picking fit functions
716
717 connect(m_fitSelector, SIGNAL(accepted()), this, SLOT(acceptFit()));
718 connect(m_fitSelector, SIGNAL(rejected()), this, SLOT(closeFit()));
719 m_fitSelector->show();
720}
721
723 QtBrowserItem *ci = m_browser->currentItem();
724 std::shared_ptr<const Mantid::API::CompositeFunction> cf = getHandler()->findCompositeFunction(ci);
725 if (!cf)
726 return;
727 auto function = m_fitSelector->getFunction();
728 if (function.isEmpty()) {
729 return;
730 }
732 h->addFunction(function.toStdString());
733 emit functionChanged();
734
735 closeFit();
736}
737
739
746 emit functionRemoved();
747 m_autoBackground = nullptr;
748 }
749 if (!func) {
751 } else {
752 auto cf = std::dynamic_pointer_cast<Mantid::API::CompositeFunction>(func);
753 if (!cf || (cf->name() != "CompositeFunction" && cf->name() != "MultiBG" && cf->name() != "MultiDomainFunction")) {
755 m_compositeFunction->addFunction(func);
756 } else {
758 }
759 }
761
762 auto h = std::make_unique<PropertyHandler>(m_compositeFunction, Mantid::API::CompositeFunction_sptr(), this);
763 m_compositeFunction->setHandler(std::move(h));
764 setCurrentFunction(static_cast<PropertyHandler *>(m_compositeFunction->getHandler()));
765
766 if (m_auto_back) {
768 }
769
770 disableUndo();
771 setFitEnabled(m_compositeFunction->nFunctions() > 0);
772 emit functionChanged();
773}
774
780 if (str.isEmpty()) {
782 } else {
783 auto f = tryCreateFitFunction(str);
784 if (f) {
786 } else {
788 }
789 }
790}
791
793 try {
794 return Mantid::API::FunctionFactory::Instance().createInitialized(str.toStdString());
795 } catch (const std::exception &ex) {
796 QMessageBox::critical(this, "Mantid - Error", "Unexpected exception caught:\n\n" + QString(ex.what()));
797 return nullptr;
798 }
799}
800
801void FitPropertyBrowser::popupMenu(const QPoint & /*unused*/) {
802 QtBrowserItem *ci = m_browser->currentItem();
803 if (!ci)
804 return;
805 QMenu *menu = new QMenu(this);
806 QAction *action;
807
808 bool isFunctionsGroup = ci == m_functionsGroup;
809 bool isSettingsGroup = ci == m_settingsGroup;
810 bool isASetting = ci->parent() == m_settingsGroup;
811 bool isFunction = getHandler()->findFunction(ci) != nullptr;
812 bool isCompositeFunction = isFunction && getHandler()->findCompositeFunction(ci);
813
814 PropertyHandler *h = getHandler()->findHandler(ci->property());
815
816 if (isFunctionsGroup) {
817 action = new QAction("Add function", this);
818 connect(action, SIGNAL(triggered()), this, SLOT(addFunction()));
819 menu->addAction(action);
820
821 if (m_compositeFunction->name() == "MultiBG" && m_compositeFunction->nFunctions() == 1 &&
823 action = new QAction("Setup multifit", this);
824 connect(action, SIGNAL(triggered()), this, SLOT(setupMultifit()));
825 menu->addAction(action);
826 }
827
828 if (m_peakToolOn) {
829 if (h && h->hasPlot()) {
830 action = new QAction("Remove plot", this);
831 connect(action, SIGNAL(triggered()), this, SLOT(removeGuessAll()));
832 menu->addAction(action);
833 } else {
834 action = new QAction("Plot", this);
835 connect(action, SIGNAL(triggered()), this, SLOT(plotGuessAll()));
836 menu->addAction(action);
837 }
838 }
839
840 menu->addSeparator();
841
842 action = new QAction("Save", this);
843 connect(action, SIGNAL(triggered()), this, SLOT(saveFunction()));
844 menu->addAction(action);
845
846 action = new QAction("Load", this);
847 connect(action, SIGNAL(triggered()), this, SLOT(loadFunction()));
848 menu->addAction(action);
849
850 action = new QAction("Copy To Clipboard", this);
851 connect(action, SIGNAL(triggered()), this, SLOT(copy()));
852 menu->addAction(action);
853
854 menu->addSeparator();
855
856 action = new QAction("Help", this);
857 connect(action, SIGNAL(triggered()), this, SLOT(browserHelp()));
858 menu->addAction(action);
859 } else if (isSettingsGroup || isASetting) {
860 if (isFitEnabled()) {
861 action = new QAction("Fit", this);
862 connect(action, SIGNAL(triggered()), this, SLOT(fit()));
863 menu->addAction(action);
864 }
865
866 if (isUndoEnabled()) {
867 action = new QAction("Undo Fit", this);
868 connect(action, SIGNAL(triggered()), this, SLOT(undoFit()));
869 menu->addAction(action);
870 }
871
872 action = new QAction("Clear all", this);
873 connect(action, SIGNAL(triggered()), this, SLOT(clear()));
874 menu->addAction(action);
875
876 action = new QAction("Help", this);
877 connect(action, SIGNAL(triggered()), this, SLOT(browserHelp()));
878 menu->addAction(action);
879
880 } else if (isFunction) {
881 if (isCompositeFunction) {
882 action = new QAction("Add function", this);
883 connect(action, SIGNAL(triggered()), this, SLOT(addFunction()));
884 menu->addAction(action);
885 }
886
887 action = new QAction("Remove", this);
888 connect(action, SIGNAL(triggered()), this, SLOT(deleteFunction()));
889 menu->addAction(action);
890
891 if (m_peakToolOn) {
892 if (h && h->hasPlot()) {
893 action = new QAction("Remove plot", this);
894 connect(action, SIGNAL(triggered()), this, SLOT(removeGuessCurrent()));
895 menu->addAction(action);
896 } else {
897 action = new QAction("Plot", this);
898 connect(action, SIGNAL(triggered()), this, SLOT(plotGuessCurrent()));
899 menu->addAction(action);
900 }
901 }
902
903 action = new QAction("Help", this);
904 connect(action, SIGNAL(triggered()), this, SLOT(functionHelp()));
905 menu->addAction(action);
906
907 menu->addSeparator();
908 } else if (h) {
909 bool isParameter = h->isParameter(ci->property());
910 bool isTie = !isParameter && ci->property()->propertyName() == "Tie";
911 bool isLowerBound = !isParameter && ci->property()->propertyName() == "Lower Bound";
912 bool isUpperBound = !isParameter && ci->property()->propertyName() == "Upper Bound";
913 bool isType = isParameter && ci->property()->propertyName() == "Type";
914 if (isType) {
915 isParameter = false;
916 }
917 if (isTie) {
918 action = new QAction("Remove", this);
919 connect(action, SIGNAL(triggered()), this, SLOT(deleteTie()));
920 menu->addAction(action);
921 } else if (isLowerBound || isUpperBound) {
922 action = new QAction("Remove", this);
923 connect(action, SIGNAL(triggered()), this, SLOT(removeBounds()));
924 menu->addAction(action);
925 } else if (count() > 0 && isParameter) {
926 bool hasTies;
927 bool hasBounds;
928 hasConstraints(ci->property(), hasTies, hasBounds);
929
930 if (!hasTies && !hasBounds) {
931 action = new QAction("Fix", this);
932 connect(action, SIGNAL(triggered()), this, SLOT(addFixTie()));
933 menu->addAction(action);
934 }
935
936 if (!hasTies) {
937 QMenu *constraintMenu = menu->addMenu("Constraint");
938
939 QMenu *detailMenu = constraintMenu->addMenu("Lower Bound");
940
941 action = new QAction("10%", this);
942 connect(action, SIGNAL(triggered()), this, SLOT(addLowerBound10()));
943 detailMenu->addAction(action);
944
945 action = new QAction("50%", this);
946 connect(action, SIGNAL(triggered()), this, SLOT(addLowerBound50()));
947 detailMenu->addAction(action);
948
949 action = new QAction("Custom", this);
950 connect(action, SIGNAL(triggered()), this, SLOT(addLowerBound()));
951 detailMenu->addAction(action);
952 detailMenu = constraintMenu->addMenu("Upper Bound");
953
954 action = new QAction("10%", this);
955 connect(action, SIGNAL(triggered()), this, SLOT(addUpperBound10()));
956 detailMenu->addAction(action);
957
958 action = new QAction("50%", this);
959 connect(action, SIGNAL(triggered()), this, SLOT(addUpperBound50()));
960 detailMenu->addAction(action);
961
962 action = new QAction("Custom", this);
963 connect(action, SIGNAL(triggered()), this, SLOT(addUpperBound()));
964 detailMenu->addAction(action);
965 detailMenu = constraintMenu->addMenu("Both Bounds");
966
967 action = new QAction("10%", this);
968 connect(action, SIGNAL(triggered()), this, SLOT(addBothBounds10()));
969 detailMenu->addAction(action);
970
971 action = new QAction("50%", this);
972 connect(action, SIGNAL(triggered()), this, SLOT(addBothBounds50()));
973 detailMenu->addAction(action);
974
975 action = new QAction("Custom", this);
976 connect(action, SIGNAL(triggered()), this, SLOT(addBothBounds()));
977 detailMenu->addAction(action);
978 }
979
980 if (hasBounds) {
981 action = new QAction("Remove constraints", this);
982 connect(action, SIGNAL(triggered()), this, SLOT(removeBounds()));
983 menu->addAction(action);
984 }
985
986 if (!hasTies && !hasBounds) {
987 if (count() == 1) {
988 action = new QAction("Tie", this);
989 connect(action, SIGNAL(triggered()), this, SLOT(addTie()));
990 menu->addAction(action);
991 } else {
992 QMenu *detail = menu->addMenu("Tie");
993
994 action = new QAction("To function", this);
995 connect(action, SIGNAL(triggered()), this, SLOT(addTieToFunction()));
996 detail->addAction(action);
997
998 action = new QAction("Custom Tie", this);
999 connect(action, SIGNAL(triggered()), this, SLOT(addTie()));
1000 detail->addAction(action);
1001 }
1002 } else if (hasTies) {
1003 action = new QAction("Remove tie", this);
1004 connect(action, SIGNAL(triggered()), this, SLOT(deleteTie()));
1005 menu->addAction(action);
1006 }
1007 }
1008 }
1009
1010 menu->popup(QCursor::pos());
1011}
1012
1016 QtBrowserItem *ci = m_browser->currentItem();
1017 PropertyHandler *h = getHandler()->findHandler(ci->property());
1018 removeFunction(h);
1019}
1020
1021//
1022
1023// Get the default function name
1025
1026// Set the default function name
1027void FitPropertyBrowser::setDefaultFunctionType(const std::string &fnType) { m_defaultFunction = fnType; }
1028
1031 // If the default peak is not in registered peaks, default to Gaussian
1032 if (m_registeredPeaks.indexOf(QString::fromStdString(m_defaultPeak)) == -1) {
1033 g_log.warning("Could not find peak function: '" + m_defaultPeak + "'. Defaulting to Gaussian.");
1034 setDefaultPeakType("Gaussian");
1035 }
1036 return m_defaultPeak;
1037}
1039void FitPropertyBrowser::setDefaultPeakType(const std::string &fnType) {
1040 m_defaultPeak = fnType;
1041 setDefaultFunctionType(fnType);
1042}
1046void FitPropertyBrowser::setDefaultBackgroundType(const std::string &fnType) {
1047 m_defaultBackground = fnType;
1048 setDefaultFunctionType(fnType);
1049}
1050
1051std::shared_ptr<Mantid::API::Workspace> FitPropertyBrowser::getWorkspace() const {
1052 std::string wsName = workspaceName();
1053 if (wsName.empty())
1054 return std::shared_ptr<Mantid::API::Workspace>();
1055 try {
1056 return Mantid::API::AnalysisDataService::Instance().retrieve(wsName);
1057 } catch (...) {
1058 return std::shared_ptr<Mantid::API::Workspace>();
1059 }
1060}
1061
1064 int i = m_enumManager->value(m_workspace);
1065 std::string res = "";
1066 if (i >= 0) {
1067 res = m_workspaceNames[i].toStdString();
1068 }
1069 return res;
1070}
1071
1073void FitPropertyBrowser::setWorkspaceName(const QString &wsName) {
1074 int i = m_workspaceNames.indexOf(wsName);
1075 if (i < 0) {
1076 // workspace may not be found because add notification hasn't been
1077 // processed yet
1079 i = m_workspaceNames.indexOf(wsName);
1080 }
1081 if (i >= 0) {
1082 m_enumManager->setValue(m_workspace, i);
1084 try {
1085 mws = std::dynamic_pointer_cast<Mantid::API::MatrixWorkspace>(
1086 Mantid::API::AnalysisDataService::Instance().retrieve(wsName.toStdString()));
1088 }
1089 if (mws) {
1090 auto wi = static_cast<size_t>(workspaceIndex());
1091 if (wi < mws->getNumberHistograms() && !mws->x(wi).empty()) {
1092 setStartX(mws->x(wi).front());
1093 setEndX(mws->x(wi).back());
1094 }
1095 }
1096 }
1098}
1099
1102
1105 try {
1106 auto const index = getAllowedIndex(i);
1109 // ignore this error
1110 }
1111}
1112
1114std::string FitPropertyBrowser::outputName() const { return m_stringManager->value(m_output).toStdString(); }
1115
1117void FitPropertyBrowser::setOutputName(const std::string &name) {
1118 m_stringManager->setValue(m_output, QString::fromStdString(name));
1119}
1120
1122std::string FitPropertyBrowser::minimizer(bool withProperties) const {
1123 int i = m_enumManager->value(m_minimizer);
1124 QString minimStr = m_minimizers[i];
1125 // append minimizer properties as name=value pairs
1126 if (withProperties) {
1127 foreach (QtProperty *prop, m_minimizerProperties) {
1128 if (prop->propertyManager() == m_stringManager) {
1129 QString value = m_stringManager->value(prop);
1130 if (!value.isEmpty()) {
1131 minimStr += "," + prop->propertyName() + "=" + value;
1132 }
1133 } else {
1134 minimStr += "," + prop->propertyName() + "=";
1135 if (prop->propertyManager() == m_intManager) {
1136 minimStr += QString::number(m_intManager->value(prop));
1137 } else if (prop->propertyManager() == m_doubleManager) {
1138 minimStr += QString::number(m_doubleManager->value(prop));
1139 } else if (prop->propertyManager() == m_boolManager) {
1140 minimStr += QString::number(m_boolManager->value(prop));
1141 } else {
1142 throw std::runtime_error("The fit browser doesn't support the type "
1143 "of minimizer's property " +
1144 prop->propertyName().toStdString());
1145 }
1146 }
1147 }
1148 }
1149 return minimStr.toStdString();
1150}
1151
1154
1157
1160 int i = m_enumManager->value(m_costFunction);
1161 return m_costFunctions[i].toStdString();
1162}
1163
1168
1171 if (!m_evaluationType->isEnabled()) {
1172 return false;
1173 }
1174 int i = m_enumManager->value(m_evaluationType);
1175 return m_evaluationTypes[i].toStdString() == "Histogram";
1176}
1177
1180
1183
1186 return m_stringManager->value(m_excludeRange).QString::toStdString();
1187}
1188
1191 const std::vector<std::string> names = Mantid::API::FunctionFactory::Instance().getFunctionNamesGUI();
1192 m_registeredFunctions.clear();
1193 m_registeredPeaks.clear();
1195 m_registeredOther.clear();
1196
1197 const auto &functionFactory = Mantid::API::FunctionFactory::Instance();
1198 for (const auto &fnName : names) {
1199 if (fnName == "MultiBG")
1200 continue;
1202 try {
1203 function = functionFactory.createFunction(fnName);
1204 } catch (std::exception &exc) {
1205 g_log.warning() << "Unable to create " << fnName << ": " << exc.what() << "\n";
1206 continue;
1207 }
1208 QString qfnName = QString::fromStdString(fnName);
1209 m_registeredFunctions << qfnName;
1210 if (dynamic_cast<Mantid::API::IPeakFunction *>(function.get())) {
1211 m_registeredPeaks << qfnName;
1212 } else if (dynamic_cast<Mantid::API::IBackgroundFunction *>(function.get())) {
1213 m_registeredBackgrounds << qfnName;
1214 } else {
1215 m_registeredOther << qfnName;
1216 }
1217 }
1218}
1219
1223void FitPropertyBrowser::enumChanged(QtProperty *prop) {
1225 return;
1226
1227 bool storeSettings = false;
1228 if (prop == m_workspace) {
1229 workspaceChange(QString::fromStdString(workspaceName()));
1233 } else if (prop->propertyName() == "Type") {
1234 disableUndo();
1236 if (!h)
1237 return;
1238 // if (!h->parentHandler()) return;
1239 auto f = h->changeType(prop);
1240 if (!h->parentHandler()) {
1241 m_compositeFunction = std::dynamic_pointer_cast<Mantid::API::CompositeFunction>(f);
1242 }
1243 if (f)
1245 emit functionChanged();
1246
1247 } else if (prop == m_minimizer) {
1249 } else if (prop == m_evaluationType) {
1250 storeSettings = true;
1251 }
1252
1253 if (storeSettings) {
1254 QSettings settings;
1255 settings.beginGroup("Mantid/FitBrowser");
1256 auto val = m_enumManager->value(prop);
1257 settings.setValue(prop->propertyName(), val);
1258 }
1259}
1260
1264void FitPropertyBrowser::boolChanged(QtProperty *prop) {
1266 return;
1267
1268 if (prop == m_plotDiff || prop == m_plotCompositeMembers || prop == m_ignoreInvalidData ||
1269 prop == m_showParamErrors) {
1270 bool val = m_boolManager->value(prop);
1271
1272 QSettings settings;
1273 settings.beginGroup("Mantid/FitBrowser");
1274 settings.setValue(prop->propertyName(), val);
1275
1276 if (prop == m_showParamErrors) {
1277 m_parameterManager->setErrorsEnabled(val);
1278 emit errorsEnabled(val);
1279 }
1280 } else { // it could be an attribute
1282 if (!h)
1283 return;
1284 enactAttributeChange(prop, h);
1285 }
1286}
1287
1291void FitPropertyBrowser::intChanged(QtProperty *prop) {
1293 return;
1294
1295 if (prop == m_workspaceIndex) {
1296 // Get current value displayed by the workspace index spinbox
1297 auto const currentIndex = workspaceIndex();
1298 auto const allowedIndex = getAllowedIndex(currentIndex);
1299 if (allowedIndex != currentIndex) {
1300 setWorkspaceIndex(allowedIndex);
1301 emit workspaceIndexChanged(allowedIndex);
1302 }
1303 m_oldWorkspaceIndex = allowedIndex;
1304 } else if (prop->propertyName() == "Workspace Index") {
1305 // Property field from Settings. Note the white space.
1307 if (!h)
1308 return;
1310 } else if (prop->propertyName() == "WorkspaceIndex") {
1311 // Property field from functions. In a word.
1313 auto const index = prop->valueText().toInt();
1314 if (h) {
1315 h->setAttribute(prop);
1319 }
1320 } else if (prop == m_maxIterations || prop == m_peakRadius) {
1321 QSettings settings;
1322 settings.beginGroup("Mantid/FitBrowser");
1323 int val = m_intManager->value(prop);
1324 settings.setValue(prop->propertyName(), val);
1325 if (prop == m_peakRadius) {
1327 }
1328 } else { // it could be an attribute
1330 if (!h)
1331 return;
1332 enactAttributeChange(prop, h);
1333 }
1334}
1335
1341 return;
1342
1343 double value = m_doubleManager->value(prop);
1344 if (prop == m_startX) {
1345 // call setWorkspace to change maxX in functions
1347 m_doubleManager->setMinimum(m_endX, value);
1348 getHandler()->setAttribute("StartX", value);
1349 emit startXChanged(startX());
1350 emit xRangeChanged(startX(), endX());
1351 return;
1352 } else if (prop == m_endX) {
1353 // call setWorkspace to change minX in functions
1355 m_doubleManager->setMaximum(m_startX, value);
1356 getHandler()->setAttribute("EndX", value);
1357 emit endXChanged(endX());
1358 emit xRangeChanged(startX(), endX());
1359 return;
1360 } else { // check if it is a constraint
1362 if (!h)
1363 return;
1364
1365 QtProperty *parProp = h->getParameterProperty(prop);
1366 if (parProp) {
1367 if (prop->propertyName() == "LowerBound") {
1368 double loBound = m_doubleManager->value(prop);
1369 h->addConstraint(parProp, true, false, loBound, 0);
1370 } else if (prop->propertyName() == "UpperBound") {
1371 double upBound = m_doubleManager->value(prop);
1372 h->addConstraint(parProp, false, true, 0, upBound);
1373 }
1374 } else { // it could be an attribute
1375 enactAttributeChange(prop, h);
1376 }
1377 }
1378}
1379
1380void FitPropertyBrowser::enactAttributeChange(QtProperty *prop, PropertyHandler *h, const bool vectorAttribute) {
1381 try {
1382 if (vectorAttribute) {
1383 h->setVectorAttribute(prop);
1384 } else {
1385 h->setAttribute(prop);
1386 }
1387 } catch (IFunction::ValidationException &ve) {
1388 std::stringstream err_str;
1389 err_str << prop->propertyName().toStdString() << " - " << ve.what();
1390 g_log.warning(err_str.str());
1391 }
1392}
1393
1402 return;
1403
1404 getHandler()->setParameter(prop);
1405}
1406
1412 return;
1413
1414 if (prop == m_output) {
1415 std::string oName = outputName();
1416 if (oName.find_first_not_of(' ') == std::string::npos) {
1417 setOutputName("");
1418 } else if (workspaceName() == oName || oName.empty()) {
1419 m_guessOutputName = true;
1420 } else {
1421 m_guessOutputName = false;
1422 }
1423 } else if (prop->propertyName() == "Tie") {
1425 if (!h)
1426 return;
1427
1428 QtProperty *parProp = h->getParameterProperty(prop);
1429 if (!parProp)
1430 return;
1431
1432 QString parName = h->functionPrefix() + "." + parProp->propertyName();
1433
1434 // Get the tie expression stored in the function in case the new expression is invalid
1435 // and the GUI needs to be reset
1436 const auto parIndex = compositeFunction()->parameterIndex(parName.toStdString());
1437 const auto oldTie = compositeFunction()->getTie(parIndex);
1438 const auto oldTieStr = oldTie->asString();
1439 const auto oldExp = QString::fromStdString(oldTieStr.substr(oldTieStr.find("=") + 1));
1440
1441 const auto exp = m_stringManager->value(prop);
1442
1443 if (oldExp == exp)
1444 return;
1445
1446 Mantid::API::ParameterTie *tie = new Mantid::API::ParameterTie(compositeFunction().get(), parName.toStdString());
1447 try {
1448 tie->set(exp.toStdString());
1449 h->addTie(parName + "=" + exp);
1450 } catch (...) {
1451 const auto msg =
1452 "Failed to update tie on " + parName.toStdString() + ". Expression " + exp.toStdString() + " is invalid.";
1453 QMessageBox::critical(this, "Mantid - Error", msg.c_str());
1454
1455 m_stringManager->setValue(prop, oldExp);
1456 }
1457 delete tie;
1458 } else if (getHandler()->setAttribute(prop)) { // setting an attribute may
1459 // change function parameters
1460 emit functionChanged();
1461 return;
1462 }
1463}
1464
1470 return;
1471
1472 if (getHandler()->setAttribute(prop)) {
1473 return;
1474 }
1475}
1476// Centre of the current peak
1479 return m_currentHandler->pfun()->centre();
1480 }
1481 return 0;
1482}
1483
1488 if (m_currentHandler) {
1492 }
1493}
1494
1495// Height of the current peak
1498 return m_currentHandler->pfun()->height();
1499 }
1500 return 0.;
1501}
1502
1507 if (m_currentHandler) {
1511 }
1512}
1513
1514// Width of the current peak
1517 return m_currentHandler->pfun()->fwhm();
1518 }
1519 return 0;
1520}
1521
1526 if (m_currentHandler) {
1530 }
1531}
1532
1534int FitPropertyBrowser::count() const { return static_cast<int>(m_compositeFunction->nFunctions()); }
1535
1538
1543 m_currentHandler = h;
1544 if (m_currentHandler) {
1545 m_browser->setCurrentItem(m_currentHandler->item());
1546 emit currentChanged();
1547 }
1548}
1549
1554 setCurrentFunction(getHandler()->findHandler(f));
1555}
1556
1560void FitPropertyBrowser::doFit(int maxIterations) {
1561 const std::string wsName = workspaceName();
1562
1563 if (wsName.empty()) {
1564 QMessageBox::critical(this, "Mantid - Error", "Workspace name is not set");
1565 return;
1566 }
1567
1568 const auto ws = getWorkspace();
1569 if (!ws) {
1570 return;
1571 }
1572
1573 try {
1574 emit algorithmStarted(QString::fromStdString(wsName));
1575 m_initialParameters.resize(compositeFunction()->nParams());
1576 for (size_t i = 0; i < compositeFunction()->nParams(); i++) {
1577 m_initialParameters[i] = compositeFunction()->getParameter(i);
1578 }
1579 m_fitActionUndoFit->setEnabled(true);
1580
1582 alg->initialize();
1583 if (isHistogramFit()) {
1584 alg->setProperty("EvaluationType", "Histogram");
1585 }
1586 alg->setProperty("Function", std::dynamic_pointer_cast<Mantid::API::IFunction>(compositeFunction())->clone());
1587 alg->setProperty("InputWorkspace", ws);
1588 auto tbl = std::dynamic_pointer_cast<ITableWorkspace>(ws);
1589 if (!tbl) {
1590 alg->setProperty("WorkspaceIndex", workspaceIndex());
1591 } else {
1592 alg->setPropertyValue("XColumn", getXColumnName().toStdString());
1593 alg->setPropertyValue("YColumn", getYColumnName().toStdString());
1594 if (getErrColumnName().toStdString() != "")
1595 alg->setPropertyValue("ErrColumn", getErrColumnName().toStdString());
1596 }
1597 alg->setProperty("StartX", startX());
1598 alg->setProperty("EndX", endX());
1599 alg->setPropertyValue("Output", outputName());
1600 alg->setPropertyValue("Minimizer", minimizer(true));
1601 alg->setProperty("IgnoreInvalidData", ignoreInvalidData());
1602 alg->setPropertyValue("CostFunction", costFunction());
1603 alg->setProperty("MaxIterations", maxIterations);
1604 alg->setProperty("PeakRadius", getPeakRadius());
1605 if (!isHistogramFit()) {
1606 if (!tbl) {
1607 alg->setProperty("Normalise", m_shouldBeNormalised);
1608 }
1609 // Always output each composite function but not necessarily plot it
1610 alg->setProperty("OutputCompositeMembers", true);
1611 if (alg->existsProperty("ConvolveMembers")) {
1612 alg->setProperty("ConvolveMembers", convolveMembers());
1613 }
1614 }
1615 if (!getExcludeRange().empty()) {
1616 if (alg->getPropertyValue("EvaluationType") != "Histogram")
1617 alg->setProperty("Exclude", getExcludeRange());
1618 else {
1619 g_log.warning("Exclude property not avaliable when evaluating as a histogram.");
1620 }
1621 }
1622 observeFinish(alg);
1623 alg->executeAsync();
1624 m_fitAlgParameters = alg->toString();
1625 } catch (const std::exception &e) {
1626 QString msg = "Fit algorithm failed.\n\n" + QString(e.what()) + "\n";
1627 QMessageBox::critical(this, "Mantid - Error", msg);
1628 }
1629}
1630
1636 if (m_compositeFunction->nFunctions() > 1) {
1637 function = m_compositeFunction;
1638 } else {
1639 function = getFunctionAtIndex(0);
1640 }
1641 return function;
1642}
1643
1648 return m_compositeFunction->getFunction(index);
1649}
1650
1652 // Emit a signal to show that the fitting has completed. (workspaceNames that
1653 // the fit has been done against is sent as a parameter)
1654 QString name(QString::fromStdString(alg->getProperty("InputWorkspace")));
1655 if (name.contains('_')) // Must be fitting to raw data, need to group under
1656 // name without "_Raw".
1657 emit fittingDone(name.left(name.indexOf('_')));
1658 else // else fitting to current workspace, group under same name.
1659 emit fittingDone(name);
1660
1661 IFunction_sptr function = alg->getProperty("Function");
1663 if (alg->existsProperty("OutputWorkspace")) {
1664 std::string out = alg->getProperty("OutputWorkspace");
1665 emit algorithmFinished(QString::fromStdString(out));
1666 }
1667 // Update Status string in member variable (so can be retrieved)
1668 m_fitAlgOutputStatus = alg->getPropertyValue("OutputStatus");
1669 auto status = QString::fromStdString(m_fitAlgOutputStatus);
1670 emit fitResultsChanged(status);
1671 // update Quality string
1672 if (m_displayActionQuality->isChecked()) {
1673 double quality = alg->getProperty("OutputChi2overDoF");
1674 std::string costFunction = alg->getProperty("CostFunction");
1675 std::shared_ptr<Mantid::API::ICostFunction> costfun =
1677 status = (status == "success") ? "success" : "failed";
1678 emit changeWindowTitle(QString("Fit Function (") + costfun->shortName().c_str() + " = " + QString::number(quality) +
1679 ", " + status + ")");
1680 } else
1681 emit changeWindowTitle("Fit Function");
1682 if (m_compositeFunction->name() == "MultiBG") {
1683 emit multifitFinished();
1684 }
1685}
1686
1688 auto function = getFittingFunction();
1689 return function->asString();
1690}
1691
1694void FitPropertyBrowser::showFitResultStatus(const QString &status) {
1695 auto text(status);
1696 text.replace("\n", "<br>");
1697 QString color("green");
1698 if (status != "success") {
1699 color = "red";
1700 }
1701
1702 m_status->setText(QString("Status: <span style='color:%2'>%1</span>").arg(text, color));
1703 m_status->show();
1704}
1705
1708 m_status->setText("Status:");
1709 m_status->hide();
1710}
1711
1714 m_workspaceNames.clear();
1715 if (m_allowedTableWorkspace.isEmpty()) {
1716 bool allAreAllowed = m_allowedSpectra.isEmpty();
1717 QStringList allowedNames;
1718 auto wsList = Mantid::API::AnalysisDataService::Instance().getObjectNames();
1719 for (const auto &wsName : wsList) {
1720 auto const &name = QString::fromStdString(wsName);
1721 if (allAreAllowed || m_allowedSpectra.contains(name)) {
1722 allowedNames << name;
1723 }
1724 }
1725
1726 for (const auto &name : allowedNames) {
1728 if (isWorkspaceValid(ws)) {
1729 m_workspaceNames.append(name);
1730 }
1731 }
1732 } else {
1734 }
1737}
1738
1743 (void)e;
1744 // Observe what workspaces are added and deleted unless it's a custom
1745 // fitting, all workspaces for custom fitting (eg muon analysis) should be
1746 // manually added.
1749}
1750
1755 (void)e;
1756 setADSObserveEnabled(false);
1757}
1758
1760 observeAdd(enabled);
1761 observePostDelete(enabled);
1762 observeRename(enabled);
1763}
1764
1766void FitPropertyBrowser::addHandle(const std::string &wsName, const std::shared_ptr<Mantid::API::Workspace> &ws) {
1767 auto const qName = QString::fromStdString(wsName);
1768 if (!isWorkspaceValid(ws) ||
1769 (!m_allowedSpectra.isEmpty() && !m_allowedSpectra.contains(qName) && m_allowedTableWorkspace.isEmpty()))
1770 return;
1771 QString oldName = QString::fromStdString(workspaceName());
1772 int i = m_workspaceNames.indexOf(qName);
1773
1774 bool initialSignalsBlocked = m_enumManager->signalsBlocked();
1775
1776 // if new workspace append this workspace name
1777 if (i < 0) {
1778 if (!m_workspaceNames.isEmpty()) {
1779 m_enumManager->blockSignals(true);
1780 }
1781
1782 m_workspaceNames.append(qName);
1783 m_workspaceNames.sort();
1785 }
1786 // get hold of index of oldName
1787 i = m_workspaceNames.indexOf(oldName);
1788 if (i >= 0) {
1789 m_enumManager->setValue(m_workspace, i);
1790 }
1791
1792 m_enumManager->blockSignals(initialSignalsBlocked);
1793}
1794
1796void FitPropertyBrowser::postDeleteHandle(const std::string &wsName) { removeWorkspace(wsName); }
1797
1798void FitPropertyBrowser::removeWorkspace(const std::string &wsName) {
1799 QString oldName = QString::fromStdString(workspaceName());
1800 int iName = m_workspaceNames.indexOf(QString(wsName.c_str()));
1801 if (iName >= 0) {
1802 m_workspaceNames.removeAt(iName);
1803 }
1804
1805 bool initialSignalsBlocked = m_enumManager->signalsBlocked();
1806
1807 if (QString::fromStdString(wsName) != oldName) {
1808 m_enumManager->blockSignals(true);
1809 }
1810
1812
1813 iName = m_workspaceNames.indexOf(oldName);
1814 if (iName >= 0) {
1815 m_enumManager->setValue(m_workspace, iName);
1816 }
1817
1818 m_enumManager->blockSignals(initialSignalsBlocked);
1819
1820 for (auto i = 0; i < m_wsListWidget->count(); ++i) {
1821 auto item = m_wsListWidget->item(i);
1822 if (item->text().toStdString() == wsName) {
1823 m_wsListWidget->takeItem(m_wsListWidget->row(item));
1824 }
1825 }
1826
1827 if (m_wsListWidget->count() == 0) {
1828 m_wsListWidget->hide();
1829 m_workspaceLabel->hide();
1830 }
1831}
1832
1833void FitPropertyBrowser::renameHandle(const std::string &oldName, const std::string &newName) {
1834 QString oldNameQ = QString::fromStdString(oldName);
1835 QString newNameQ = QString::fromStdString(newName);
1836 auto it = m_allowedSpectra.find(oldNameQ);
1837 if (it != m_allowedSpectra.end()) {
1838 auto indices = m_allowedSpectra.value(oldNameQ);
1839 m_allowedSpectra.remove(oldNameQ);
1840 m_allowedSpectra.insert(newNameQ, indices);
1841 }
1842 int iWorkspace = m_workspaceNames.indexOf(oldNameQ);
1843 if (iWorkspace >= 0) {
1844 m_workspaceNames.replace(iWorkspace, newNameQ);
1846 }
1847 workspaceChange(newNameQ);
1848
1849 for (auto i = 0; i < m_wsListWidget->count(); ++i) {
1850 auto item = m_wsListWidget->item(i);
1851 if (item->text().toStdString() == oldName) {
1852 m_wsListWidget->takeItem(m_wsListWidget->row(item));
1853 m_wsListWidget->insertItem(m_wsListWidget->row(item), newNameQ);
1854 }
1855 }
1856}
1857
1863 return (dynamic_cast<Mantid::API::MatrixWorkspace *>(ws.get()) != nullptr ||
1864 dynamic_cast<Mantid::API::ITableWorkspace *>(ws.get()) != nullptr);
1865}
1866
1869 if (count() == 0) {
1870 return false;
1871 }
1873}
1874
1876double FitPropertyBrowser::startX() const { return m_doubleManager->value(m_startX); }
1877
1880
1882double FitPropertyBrowser::endX() const { return m_doubleManager->value(m_endX); }
1883
1886
1887void FitPropertyBrowser::setXRange(double start, double end) {
1888 disconnect(m_doubleManager, SIGNAL(propertyChanged(QtProperty *)), this, SLOT(doubleChanged(QtProperty *)));
1889
1890 m_doubleManager->setValue(m_startX, start);
1891 m_doubleManager->setValue(m_endX, end);
1892
1894 m_doubleManager->setMinimum(m_endX, start);
1895 m_doubleManager->setMaximum(m_startX, end);
1896
1897 getHandler()->setAttribute("StartX", start);
1898 getHandler()->setAttribute("EndX", end);
1899
1900 connect(m_doubleManager, SIGNAL(propertyChanged(QtProperty *)), this, SLOT(doubleChanged(QtProperty *)));
1901}
1902
1904 auto ws = getWorkspace();
1905 auto tbl = std::dynamic_pointer_cast<ITableWorkspace>(ws);
1906 auto mws = std::dynamic_pointer_cast<MatrixWorkspace>(ws);
1907 QVector<double> range;
1908 if (tbl) {
1909 auto xColumnIndex = m_columnManager->value(m_xColumn);
1910 std::vector<double> xColumnData;
1911 auto col = tbl->getColumn(xColumnIndex);
1912 try {
1913 for (size_t i = 0; i < tbl->rowCount(); ++i) {
1914 xColumnData.emplace_back(col->toDouble(i));
1915 }
1916 } catch (std::invalid_argument &err) {
1917 QMessageBox::critical(this, "Mantid - Error", "The X column is not a number");
1918 throw std::invalid_argument(err);
1919 }
1920 std::sort(xColumnData.begin(), xColumnData.end());
1921 range.push_back(xColumnData.front());
1922 range.push_back(xColumnData.back());
1923 } else if (mws) {
1924 auto xData = mws->mutableX(workspaceIndex());
1925 range.push_back(xData.front());
1926 range.push_back(xData.back());
1927 }
1928 return range;
1929}
1930
1932 const auto ws = getWorkspace();
1933 auto tbl = std::dynamic_pointer_cast<ITableWorkspace>(ws);
1934 QString columnName = "";
1935 if (tbl) {
1936 auto columns = tbl->getColumnNames();
1937 auto xIndex = m_columnManager->value(m_xColumn);
1938 if (xIndex >= static_cast<int>(columns.size())) {
1939 QMessageBox::critical(nullptr, "Mantid - Error", "X column was not found.");
1940 }
1941 columnName = QString::fromStdString(columns[xIndex]);
1942 }
1943 return columnName;
1944}
1945
1947 const auto ws = getWorkspace();
1948 auto tbl = std::dynamic_pointer_cast<ITableWorkspace>(ws);
1949 QString columnName = "";
1950 if (tbl) {
1951 auto columns = tbl->getColumnNames();
1952 auto yIndex = m_columnManager->value(m_yColumn);
1953 if (yIndex >= static_cast<int>(columns.size())) {
1954 QMessageBox::critical(nullptr, "Mantid - Error", "Y column was not found.");
1955 }
1956 columnName = QString::fromStdString(columns[yIndex]);
1957 }
1958 return columnName;
1959}
1960
1962 const auto ws = getWorkspace();
1963 auto tbl = std::dynamic_pointer_cast<ITableWorkspace>(ws);
1964 QString columnName = "";
1965 if (tbl) {
1966 auto columns = tbl->getColumnNames();
1967 // The error column has an empty first entry
1968 auto errIndex = m_columnManager->value(m_errColumn) - 1;
1969 if (errIndex >= static_cast<int>(columns.size())) {
1970 QMessageBox::warning(nullptr, "Mantid - Warning", "Error column was not found.");
1971 } else if (errIndex != -1) {
1972 columnName = QString::fromStdString(columns[errIndex]);
1973 }
1974 }
1975 return columnName;
1976}
1977
1979QtBrowserItem *FitPropertyBrowser::findItem(QtBrowserItem *parent, QtProperty *prop) const {
1980 QList<QtBrowserItem *> children = parent->children();
1981 QtBrowserItem *res = nullptr;
1982 for (auto &child : children) {
1983 if (child->property() == prop) {
1984 return child;
1985 }
1986 QList<QtBrowserItem *> grand_children = child->children();
1987 if (grand_children.size() > 0)
1988 res = findItem(child, prop);
1989 if (res)
1990 return res;
1991 }
1992 return nullptr;
1993}
1994
1998void FitPropertyBrowser::currentItemChanged(QtBrowserItem *current) {
1999 if (current) {
2000 m_currentHandler = getHandler()->findHandler(current->property());
2001 } else {
2002 m_currentHandler = nullptr;
2003 }
2004 emit currentChanged();
2005}
2006
2013 if (!h)
2014 return;
2015 enactAttributeChange(prop, h, true);
2016}
2017
2024 if (!h)
2025 return;
2026 enactAttributeChange(prop, h, true);
2027}
2028
2033
2038
2044 clearBrowser();
2046 emit functionCleared();
2047}
2048
2050 QList<QtProperty *> props = m_functionsGroup->property()->subProperties();
2051 foreach (QtProperty *prop, props) { m_functionsGroup->property()->removeSubProperty(prop); }
2052}
2053
2056 for (auto paramIndex = 0u; paramIndex < finalFunction->nParams(); ++paramIndex) {
2057 compositeFunction()->setParameter(paramIndex, finalFunction->getParameter(paramIndex));
2058 compositeFunction()->setError(paramIndex, finalFunction->getError(paramIndex));
2059 }
2062}
2063
2068 if (m_initialParameters.size() == compositeFunction()->nParams()) {
2069 for (size_t i = 0; i < compositeFunction()->nParams(); i++) {
2070 compositeFunction()->setParameter(i, m_initialParameters[i]);
2071 }
2075 emit fitUndone();
2076 }
2077 disableUndo();
2078}
2079
2082 m_initialParameters.clear();
2083 m_fitActionUndoFit->setEnabled(false);
2084}
2085
2088 return m_initialParameters.size() && compositeFunction()->nParams() == m_initialParameters.size();
2089}
2090
2093 m_fitActionFit->setEnabled(enable);
2094 m_fitActionSeqFit->setEnabled(enable);
2095}
2096
2098bool FitPropertyBrowser::isFitEnabled() const { return m_fitActionFit->isEnabled(); }
2099
2104 QtBrowserItem *ci = m_browser->currentItem();
2105 QtProperty *paramProp = ci->property();
2106 PropertyHandler *h = getHandler()->findHandler(paramProp);
2107 if (!h)
2108 return;
2109 if (!h->isParameter(paramProp))
2110 return;
2111
2112 auto f = h->function();
2113 if (!f)
2114 return;
2115
2116 bool ok = false;
2117 QString tieStr = QInputDialog::getText(this, "Mantid - Fit", "Enter tie expression", QLineEdit::Normal, "", &ok);
2118 if (ok) {
2119 tieStr = tieStr.trimmed();
2120 if (!tieStr.contains('=')) {
2121 tieStr = h->functionPrefix() + "." + paramProp->propertyName() + "=" + tieStr;
2122 }
2123 h->addTie(tieStr);
2124 } // if (ok)
2125}
2126
2132 QtBrowserItem *ci = m_browser->currentItem();
2133 QtProperty *paramProp = ci->property();
2134 PropertyHandler *h = getHandler()->findHandler(paramProp);
2135 if (!h)
2136 return;
2137 if (!h->isParameter(paramProp))
2138 return;
2139 std::string parName = paramProp->propertyName().toStdString();
2140 QStringList fnNames;
2141
2142 int iPar = -1;
2143 for (size_t i = 0; i < m_compositeFunction->nParams(); i++) {
2146
2147 // Pick out parameters with the same name as the one we're tying from
2148 if (fun->parameterName(static_cast<int>(ref.getLocalIndex())) == parName) {
2149 if (iPar == -1 && fun == h->function().get()) // If this is the 'tied from' parameter, remember it
2150 {
2151 iPar = (int)i;
2152 } else // Otherwise add it to the list of potential 'tyees'
2153 {
2154 fnNames << QString::fromStdString(m_compositeFunction->parameterName(i));
2155 }
2156 }
2157 }
2158 if (fnNames.empty() || iPar < 0) {
2159 QMessageBox::information(this, "Mantid - information", "Cannot tie this parameter to any function");
2160 return;
2161 }
2162
2163 bool ok;
2164 QString tieName = QInputDialog::getItem(this, "Mantid - Fit", "Select function", fnNames, 0, false, &ok);
2165
2166 if (!ok)
2167 return;
2168
2169 QString tieExpr = QString::fromStdString(m_compositeFunction->parameterName(iPar)) + "=" + tieName;
2170
2171 h->addTie(tieExpr);
2172}
2173
2178 QtBrowserItem *ci = m_browser->currentItem();
2179 QtProperty *paramProp = ci->property();
2180 PropertyHandler *h = getHandler()->findHandler(paramProp);
2181 if (!h)
2182 return;
2183 if (!h->isParameter(paramProp))
2184 return;
2185 h->fix(paramProp->propertyName());
2186}
2187
2192 QtBrowserItem *ci = m_browser->currentItem();
2193 QtProperty *paramProp = ci->property();
2194 PropertyHandler *h = getHandler()->findHandler(paramProp);
2195 if (!h)
2196 return;
2197 // get name of parent property (i.e. function)
2198 if (paramProp->propertyName() != "Tie") {
2199 auto parameterMap = h->getTies();
2200 auto match = parameterMap.find(paramProp->propertyName());
2201 if (match != parameterMap.end()) {
2202 paramProp = match.value();
2203 }
2204 }
2205 if (paramProp->propertyName() == "Tie") {
2206 auto ties = h->getTies();
2207 QString qParName = ties.key(paramProp, "");
2208 std::string parName = qParName.toStdString();
2209 QStringList functionNames;
2210 // ithParameter = -1 => not found
2211 int ithParameter = -1;
2212 for (size_t i = 0; i < m_compositeFunction->nParams(); i++) {
2214 Mantid::API::IFunction *function = parameterRef.getLocalFunction();
2215 // Pick out parameters with the same name as the one we're tying from
2216 if (function->parameterName(static_cast<int>(parameterRef.getLocalIndex())) == parName) {
2217 if (ithParameter == -1 && function == h->function().get()) // If this is the 'tied from'
2218 // parameter, remember it
2219 {
2220 ithParameter = static_cast<int>(i);
2221 } else // Otherwise add it to the list of potential 'tyees'
2222 {
2223 functionNames << QString::fromStdString(m_compositeFunction->parameterName(i));
2224 }
2225 }
2226 }
2227 if (functionNames.empty() && ithParameter < 0) {
2228 QMessageBox::information(this, "Mantid - information", "Cannot find a parameter with this tie");
2229 } else {
2230 QString tieExpr = QString::fromStdString(m_compositeFunction->parameterName(ithParameter));
2231 h->removeTie(paramProp, tieExpr.toStdString());
2232 }
2233 } else {
2234 h->removeTie(ci->property()->propertyName());
2235 }
2236}
2237
2243void FitPropertyBrowser::hasConstraints(QtProperty *parProp, bool &hasTie, bool &hasBounds) const {
2244 hasTie = false;
2245 hasBounds = false;
2246 QList<QtProperty *> subs = parProp->subProperties();
2247 for (auto &sub : subs) {
2248 if (sub->propertyName() == "Tie") {
2249 hasTie = true;
2250 }
2251 if (sub->propertyName() == "LowerBound") {
2252 hasBounds = true;
2253 }
2254 if (sub->propertyName() == "UpperBound") {
2255 hasBounds = true;
2256 }
2257 }
2258}
2259
2263QtProperty *FitPropertyBrowser::getTieProperty(QtProperty *parProp) const {
2264 QList<QtProperty *> subs = parProp->subProperties();
2265 for (auto &sub : subs) {
2266 if (sub->propertyName() == "Tie") {
2267 return sub;
2268 }
2269 }
2270 return nullptr;
2271}
2272
2278 Q_UNUSED(notice);
2279 // Don't call populate directly as the updates can come from a different
2280 // thread
2282}
2283
2287void FitPropertyBrowser::setTip(const QString &txt) { m_tip->setText(txt); }
2288
2293void FitPropertyBrowser::addConstraint(int f, bool lo, bool up) {
2294 QtBrowserItem *ci = m_browser->currentItem();
2295 QtProperty *parProp = ci->property();
2296 PropertyHandler *h = getHandler()->findHandler(parProp);
2297 if (!h)
2298 return;
2299
2300 double x = parProp->valueText().toDouble();
2301 double loBound = x * (1 - 0.01 * f);
2302 double upBound = x * (1 + 0.01 * f);
2303
2304 h->addConstraint(ci->property(), lo, up, loBound, upBound);
2305}
2306
2311
2316
2321
2326
2331
2336
2342
2348
2353
2358 QtBrowserItem *ci = m_browser->currentItem();
2359 QtProperty *parProp = ci->property();
2360 PropertyHandler *h = getHandler()->findHandler(parProp);
2361 if (!h)
2362 return;
2363
2364 h->removeConstraint(parProp);
2365}
2366
2371
2376
2382
2387
2389 if (getHandler()->hasPlot()) {
2391 } else {
2392 plotGuessAll();
2393 }
2394}
2395
2397
2403QtProperty *FitPropertyBrowser::addDoubleProperty(const QString &name, QtDoublePropertyManager *manager) const {
2404 if (manager == nullptr)
2405 manager = m_doubleManager;
2406 QtProperty *prop = manager->addProperty(name);
2407 manager->setDecimals(prop, m_decimals);
2408 manager->setRange(prop, -DBL_MAX, DBL_MAX);
2409 return prop;
2410}
2411
2417QtProperty *FitPropertyBrowser::addStringProperty(const QString &name) const {
2418 QtProperty *prop;
2419 QString propName = name.toLower();
2420 if (propName == "filename") {
2421 prop = m_filenameManager->addProperty(name);
2422 } else if (propName == "formula") {
2424 prop = m_formulaManager->addProperty(name);
2425 } else {
2426 prop = m_stringManager->addProperty(name);
2427 }
2428 return prop;
2429}
2430
2438QtProperty *FitPropertyBrowser::addStringListProperty(const QString &name,
2439 const std::vector<std::string> &allowed_values) const {
2440 QStringList qAllowedValues;
2441 QtProperty *prop = m_enumManager->addProperty(name);
2442
2443 for (const auto &values : allowed_values) {
2444 qAllowedValues << QString::fromStdString(values);
2445 }
2446 m_enumManager->setEnumNames(prop, qAllowedValues);
2447
2448 return prop;
2449}
2450
2456void FitPropertyBrowser::setStringPropertyValue(QtProperty *prop, const QString &value) const {
2457 auto *manager = dynamic_cast<QtStringPropertyManager *>(prop->propertyManager());
2458 if (manager) {
2459 manager->setValue(prop, value);
2460 }
2461}
2462
2463QString FitPropertyBrowser::getStringPropertyValue(QtProperty *prop) const {
2464 auto *manager = dynamic_cast<QtStringPropertyManager *>(prop->propertyManager());
2465 if (manager)
2466 return manager->value(prop);
2467 else
2468 return QString("");
2469}
2470
2472
2474
2479int FitPropertyBrowser::getAllowedIndex(int currentIndex) const {
2480 auto const workspace = std::dynamic_pointer_cast<MatrixWorkspace>(getWorkspace());
2481
2482 if (!workspace) {
2483 return 0;
2484 }
2485
2486 auto const allowedIndices =
2487 m_allowedSpectra.empty() ? QList<int>() : m_allowedSpectra[QString::fromStdString(workspaceName())];
2488 auto const firstIndex = m_allowedSpectra.empty() ? 0 : allowedIndices.front();
2489 auto const lastIndex = m_allowedSpectra.empty() ? getNumberOfSpectra(workspace) - 1 : allowedIndices.back();
2490
2491 auto allowedIndex = currentIndex;
2492 if (currentIndex < firstIndex) {
2493 allowedIndex = firstIndex;
2494 } else if (currentIndex > lastIndex) {
2495 allowedIndex = lastIndex;
2496 } else if (!m_allowedSpectra.empty() && !allowedIndices.contains(currentIndex)) {
2497 allowedIndex = m_oldWorkspaceIndex;
2498 auto i = allowedIndices.indexOf(m_oldWorkspaceIndex);
2499 if (i >= 0) {
2500 i = currentIndex > m_oldWorkspaceIndex ? i + 1 : i - 1;
2501 if (i >= 0 && i < allowedIndices.size()) {
2502 allowedIndex = allowedIndices[i];
2503 }
2504 }
2505 }
2506 return allowedIndex;
2507}
2508
2510 bool ok(false);
2511 QString fnName = QInputDialog::getText(this, tr("Mantid - Input"), tr("Please select a name for the function"),
2512 QLineEdit::Normal, "", &ok);
2513 if (ok && !fnName.isEmpty()) {
2514 saveFunction(fnName);
2515 }
2516}
2517
2518void FitPropertyBrowser::saveFunction(const QString &fnName) {
2519 QSettings settings;
2520 settings.beginGroup("Mantid/FitBrowser/SavedFunctions");
2521 QStringList names = settings.childKeys();
2522 if (names.contains(fnName) && QMessageBox::question(this, "Mantid - Question",
2523 "Function with this name already exists.\n"
2524 "Would you like to replace it?",
2525 QMessageBox::Yes) != QMessageBox::Yes) {
2526 return;
2527 }
2528 settings.setValue(fnName, QString::fromStdString(theFunction()->asString()));
2530}
2531
2533 QSettings settings;
2534 settings.beginGroup("Mantid/FitBrowser/SavedFunctions");
2535 QStringList names = settings.childKeys();
2536 if (names.isEmpty()) {
2537 QMessageBox::information(this, "Mantid - Information", "There are no saved functions");
2538 return;
2539 }
2540 QString name = QInputDialog::getItem(this, "Mantid - Input", "Please select a function to load", names, 0, false);
2541 if (!name.isEmpty()) {
2542 QString str = settings.value(name).toString();
2543
2544 loadFunction(str);
2545 }
2546}
2547
2549 QString str = QInputDialog::getText(this, "Mantid - Input", "Specify fit function string");
2550
2551 if (!str.isEmpty()) {
2552 loadFunction(str);
2553 }
2554}
2555
2556void FitPropertyBrowser::loadFunction(const QString &funcString) {
2557 // when loading a function from a string initially
2558 // do not try to do auto background even if set
2559 bool isAutoBGset = false;
2560 if (m_auto_back) {
2561 isAutoBGset = true;
2562 m_auto_back = false;
2563 }
2564
2566 clearBrowser();
2567 createCompositeFunction(funcString);
2568 emit functionLoaded(funcString);
2569
2570 if (isAutoBGset)
2571 m_auto_back = true;
2572}
2573
2575 QClipboard *clipboard = QApplication::clipboard();
2576 clipboard->setText(QString::fromStdString(theFunction()->asString()));
2577}
2578
2580 QClipboard *clipboard = QApplication::clipboard();
2581 QString str = clipboard->text();
2583}
2584
2586 QString str = QString::fromStdString(theFunction()->asString());
2587 // getHandler()->removeAllPlots();// this crashes mantidplot
2588 clearBrowser();
2590}
2591
2593 std::string wsName = workspaceName();
2594 if (!wsName.empty()) {
2595 try {
2596 auto ws = Mantid::API::AnalysisDataService::Instance().retrieve(wsName);
2597 auto mws = std::dynamic_pointer_cast<Mantid::API::MatrixWorkspace>(ws);
2598 if (mws) {
2599 function->setMatrixWorkspace(mws, workspaceIndex(), startX(), endX());
2600 } else {
2601 function->setWorkspace(ws);
2602 }
2603 } catch (...) {
2604 }
2605 }
2606}
2607
2609 if (m_autoBgName.isEmpty())
2610 return;
2611 bool hasPlot = false;
2613 if (m_autoBackground) { // remove old background
2614 if (ch == m_autoBackground) {
2615 ch = nullptr;
2616 }
2617 hasPlot = m_autoBackground->hasPlot();
2619 m_autoBackground = nullptr;
2620 }
2621 // Create the function
2622 PropertyHandler *h = getHandler()->addFunction(m_autoBgName.toStdString());
2623 if (!h)
2624 return;
2625 if (!m_autoBgAttributes.isEmpty()) { // set attributes
2626 QStringList attList = m_autoBgAttributes.split(' ');
2627 foreach (QString att, attList) {
2628 QStringList name_value = att.split('=');
2629 if (name_value.size() == 2) {
2630 QString name = name_value[0].trimmed();
2631 QString value = name_value[1].trimmed();
2632 if (h->function()->hasAttribute(name.toStdString())) {
2633 h->setAttribute(name, value);
2634 }
2635 }
2636 }
2637 }
2638 h->fit();
2639 m_autoBackground = h;
2641 if (hasPlot) {
2643 emit plotCurrentGuess();
2644 if (ch) {
2646 }
2647 }
2648}
2649
2651 if (m_autoBackground) {
2653 }
2654}
2655
2663 try {
2664 QStringList nameList = aName.split(' ');
2665 if (nameList.isEmpty())
2666 return;
2667 QString name = nameList[0];
2668 std::shared_ptr<Mantid::API::IFunction> f = std::shared_ptr<Mantid::API::IFunction>(
2669 Mantid::API::FunctionFactory::Instance().createFunction(name.toStdString()));
2670 m_auto_back = true;
2671 m_autoBgName = name;
2672 if (nameList.size() > 1) {
2673 nameList.removeFirst();
2674 m_autoBgAttributes = nameList.join(" ");
2675 }
2676 Mantid::Kernel::ConfigService::Instance().setString("curvefitting.autoBackground", aName.toStdString());
2677 } catch (...) {
2678 m_auto_back = false;
2679 }
2680}
2681
2683 auto *dlg = new SequentialFitDialog(this, m_mantidui);
2684 std::string wsName = workspaceName();
2685 if (!wsName.empty() && dlg->addWorkspaces(QStringList(QString::fromStdString(wsName)))) {
2686 dlg->show();
2687 }
2688}
2689
2691 std::string wsName = workspaceName();
2692 if (wsName.empty()) {
2693 QMessageBox::critical(this, "Mantid - Error", "Workspace name is not set");
2694 return;
2695 }
2696
2697 std::string peakListName = wsName + "_PeakList_tmp";
2698
2699 int FWHM, Tolerance;
2700 QString setting =
2701 QString::fromStdString(Mantid::Kernel::ConfigService::Instance().getString("curvefitting.findPeaksFWHM"));
2702 FWHM = setting.isEmpty() ? 7 : setting.toInt();
2703
2704 setting =
2705 QString::fromStdString(Mantid::Kernel::ConfigService::Instance().getString("curvefitting.findPeaksTolerance"));
2706 Tolerance = setting.isEmpty() ? 4 : setting.toInt();
2707
2709 alg->initialize();
2710 alg->setPropertyValue("InputWorkspace", wsName);
2711 alg->setProperty("WorkspaceIndex", workspaceIndex());
2712 alg->setPropertyValue("PeaksList", peakListName);
2713 alg->setProperty("FWHM", FWHM);
2714 alg->setProperty("Tolerance", Tolerance);
2715
2716 QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
2717
2718 Mantid::API::MatrixWorkspace_sptr inputWS = std::dynamic_pointer_cast<Mantid::API::MatrixWorkspace>(
2720
2721 try {
2722 alg->execute();
2723 Mantid::API::ITableWorkspace_sptr ws = std::dynamic_pointer_cast<Mantid::API::ITableWorkspace>(
2724 Mantid::API::AnalysisDataService::Instance().retrieve(peakListName));
2725
2726 clear();
2727 Mantid::API::ColumnVector<double> centre = ws->getVector("centre");
2728 Mantid::API::ColumnVector<double> width = ws->getVector("width");
2729 Mantid::API::ColumnVector<double> height = ws->getVector("height");
2730 for (size_t i = 0; i < centre.size(); ++i) {
2731 if (centre[i] < startX() || centre[i] > endX())
2732 continue;
2733 auto f = std::dynamic_pointer_cast<Mantid::API::IPeakFunction>(
2735 if (!f)
2736 break;
2737 f->setMatrixWorkspace(inputWS, workspaceIndex(), startX(), endX());
2738 f->setCentre(centre[i]);
2739 f->setFwhm(width[i]);
2740 f->setHeight(height[i]);
2741 addFunction(f->asString());
2742 }
2743 } catch (...) {
2744 QApplication::restoreOverrideCursor();
2745 throw;
2746 }
2747
2748 QApplication::restoreOverrideCursor();
2749}
2750
2752 m_peakToolOn = on;
2753 m_displayActionPlotGuess->setEnabled(on);
2754}
2755
2760 if (m_decimals < 0) {
2761 QSettings settings;
2762 settings.beginGroup("Mantid/FitBrowser");
2763 m_decimals = settings.value("decimals", 6).toInt();
2764 }
2765 QSet<QtProperty *> props = m_doubleManager->properties();
2766 foreach (QtProperty *prop, props) { m_doubleManager->setDecimals(prop, m_decimals); }
2767}
2768
2770 m_decimals = d;
2771 QSettings settings;
2772 settings.beginGroup("Mantid/FitBrowser");
2773 settings.setValue("decimals", d);
2775}
2776
2778
2781
2783
2784void FitPropertyBrowser::setTextPlotGuess(const QString &text) { m_displayActionPlotGuess->setText(text); }
2785
2789void FitPropertyBrowser::workspaceChange(const QString &wsName) {
2790 if (m_guessOutputName) {
2791 m_stringManager->setValue(m_output, QString::fromStdString(workspaceName()));
2792 }
2793
2794 emit workspaceNameChanged(wsName);
2795 emit wsChangePPAssign(wsName);
2796}
2797
2802
2807 auto *dlg = new MultifitSetupDialog(this);
2808 dlg->exec();
2809 QStringList ties = dlg->getParameterTies();
2810
2811 if (!ties.isEmpty()) {
2812 QString wsName = QString::fromStdString(workspaceName());
2813 Mantid::API::MatrixWorkspace_sptr mws = std::dynamic_pointer_cast<Mantid::API::MatrixWorkspace>(
2815 if (mws) {
2816 auto fun = getFunctionAtIndex(0);
2817 QString fun1Ini = QString::fromStdString(fun->asString());
2818 QString funIni = "composite=MultiBG;" + fun1Ini + ",Workspace=" + wsName + ",WSParam=(WorkspaceIndex=0);";
2819 QString tieStr;
2820 for (size_t i = 1; i < mws->getNumberHistograms(); ++i) {
2821 QString comma = i > 1 ? "," : "";
2822 QString fi = comma + "f" + QString::number(i) + ".";
2823 for (int j = 0; j < static_cast<int>(fun->nParams()); ++j) {
2824 if (!ties[j].isEmpty()) {
2825 tieStr += fi + QString::fromStdString(fun->parameterName(j)) + "=" + ties[j];
2826 }
2827 }
2828 QString wsParam = ",WSParam=(WorkspaceIndex=" + QString::number(i);
2829 wsParam += ",StartX=" + QString::number(startX()) + ",EndX=" + QString::number(endX()) + ")";
2830 funIni += fun1Ini + ",Workspace=" + wsName + wsParam + ";";
2831 }
2832 if (!tieStr.isEmpty()) {
2833 funIni += "ties=(" + tieStr + ")";
2834 }
2835 loadFunction(funIni);
2836 }
2837 }
2838}
2839
2842 if (compositeFunction()->name() != "MultiBG")
2843 return;
2844
2845 // if all member functions are of the same type and composition
2846 // create a TableWorkspace with parameter series
2847
2848 // check if member functions are the same
2849 QStringList parNames;
2850 auto fun0 = getFunctionAtIndex(0);
2851 if (!fun0) {
2852 throw std::runtime_error("IFunction expected but func function of another type");
2853 }
2854 for (size_t i = 0; i < fun0->nParams(); ++i) {
2855 parNames << QString::fromStdString(fun0->parameterName(i));
2856 }
2857
2858 for (size_t i = 1; i < compositeFunction()->nFunctions(); ++i) {
2859 auto fun = getFunctionAtIndex(i);
2860 if (!fun) {
2861 throw std::runtime_error("IFunction expected but func function of another type");
2862 }
2863 for (size_t j = 0; j < fun->nParams(); ++j) {
2864 if (parNames.indexOf(QString::fromStdString(fun->parameterName(j))) < 0) {
2865 // Functions are different, stop
2866 return;
2867 }
2868 }
2869 }
2870
2871 QApplication::setOverrideCursor(Qt::WaitCursor);
2872 // create a TableWorkspace: first column - function index
2873 // other colomns - the parameters
2874 Mantid::API::ITableWorkspace_sptr table = Mantid::API::WorkspaceFactory::Instance().createTable("TableWorkspace");
2875 table->addColumn("int", "Index");
2876 foreach (QString par, parNames) { table->addColumn("double", par.toStdString()); }
2877 // Create WorkspaceGroup with the fit results
2878 std::vector<std::string> worspaceNames(compositeFunction()->nFunctions());
2879 for (size_t i = 0; i < compositeFunction()->nFunctions(); ++i) {
2880 // Mantid::API::TableRow row = table->appendRow();
2881 // row << int(i);
2882 // Mantid::API::IFunctionMW* fun =
2883 // dynamic_cast<Mantid::API::IFunctionMW*>(compositeFunction()->getFunction(i));
2884 // for(size_t j = 0; j < fun->nParams(); ++j)
2885 //{
2886 // row << fun->getParameter(j);
2887 //}
2888 // size_t wi = fun->getWorkspaceIndex();
2889 // Mantid::API::MatrixWorkspace_sptr mws =
2890 // fun->createCalculatedWorkspace(fun->getMatrixWorkspace(),wi);
2891 // worspaceNames[i] =
2892 // workspaceNames()+"_"+QString::number(wi).toStdString()+"_Workspace";
2893 // Mantid::API::AnalysisDataService::Instance().addOrReplace(worspaceNames[i],mws);
2894 }
2895
2896 // Save the table
2897 Mantid::API::AnalysisDataService::Instance().addOrReplace(workspaceName() + "_Param_series", table);
2898 try {
2900 group->setProperty("InputWorkspaces", worspaceNames);
2901 group->setPropertyValue("OutputWorkspace", workspaceName() + "_Workspace");
2902 group->execute();
2903 } catch (...) {
2904 }
2905 QApplication::restoreOverrideCursor();
2906}
2907
2914 // remove old properties
2915 if (m_browser->isItemVisible(m_settingsGroup)) {
2916 if (m_settingsGroup->property()->subProperties().contains(m_workspaceIndex)) {
2917 m_settingsGroup->property()->removeSubProperty(m_workspaceIndex);
2918 } else if (m_settingsGroup->property()->subProperties().contains(m_xColumn)) {
2919 m_settingsGroup->property()->removeSubProperty(m_xColumn);
2920 m_settingsGroup->property()->removeSubProperty(m_yColumn);
2921 m_settingsGroup->property()->removeSubProperty(m_errColumn);
2922 }
2923 }
2924
2926 try {
2928 } catch (...) {
2929 return;
2930 }
2931 if (!ws)
2932 return;
2933
2934 // If this is a MuonFitPropertyBrowser, "evaluation type" goes in the Custom
2935 // Settings group.
2936 // If not, there is no Custom Settings group and it goes in the regular
2937 // Settings group.
2939
2940 if (settings->property()->subProperties().contains(m_evaluationType)) {
2941 settings->property()->removeSubProperty(m_evaluationType);
2942 m_evaluationType->setEnabled(false);
2943 // if it is a MatrixWorkspace insert WorkspaceIndex
2944 auto mws = std::dynamic_pointer_cast<Mantid::API::MatrixWorkspace>(ws);
2945 if (mws) {
2947 auto isHistogram = mws->isHistogramData();
2948 m_evaluationType->setEnabled(isHistogram);
2949 if (isHistogram) {
2950 settings->property()->addSubProperty(m_evaluationType);
2951 }
2952 return;
2953 }
2954 }
2955
2956 // if it is a TableWorkspace insert the column properties
2957 auto tws = std::dynamic_pointer_cast<Mantid::API::ITableWorkspace>(ws);
2958 if (tws) {
2960 // insert properties
2961 m_settingsGroup->property()->insertSubProperty(m_xColumn, m_workspace);
2962 m_settingsGroup->property()->insertSubProperty(m_yColumn, m_xColumn);
2963 m_settingsGroup->property()->insertSubProperty(m_errColumn, m_yColumn);
2965 return;
2966 QString xName;
2967 QString yName;
2968 QString errName;
2969 auto names = tws->getColumnNames();
2970 QStringList columns;
2971 for (const auto &name : names) {
2972 columns << QString::fromStdString(name);
2973 auto col = tws->getColumn(name);
2974 if (xName.isEmpty() && col->getPlotType() == 1 /*X*/) {
2975 xName = QString::fromStdString(name);
2976 }
2977 if (yName.isEmpty() && col->getPlotType() == 2 /*Y*/) {
2978 yName = QString::fromStdString(name);
2979 }
2980 if (errName.isEmpty() && col->getPlotType() == 5 /*yErr*/) {
2981 errName = QString::fromStdString(name);
2982 }
2983 }
2984 m_columnManager->setEnumNames(m_xColumn, columns);
2985 m_columnManager->setEnumNames(m_yColumn, columns);
2986 // set the column values
2987 if (!xName.isEmpty()) {
2988 m_columnManager->setValue(m_xColumn, columns.indexOf(xName));
2989 } else {
2990 foreach (QString name, columns) {
2991 if (name != yName) {
2992 m_columnManager->setValue(m_xColumn, columns.indexOf(name));
2993 break;
2994 }
2995 }
2996 }
2997 if (!yName.isEmpty()) {
2998 m_columnManager->setValue(m_yColumn, columns.indexOf(yName));
2999 } else {
3000 foreach (QString name, columns) {
3001 if (name != xName) {
3002 m_columnManager->setValue(m_yColumn, columns.indexOf(name));
3003 break;
3004 }
3005 }
3006 }
3007 columns.prepend("");
3008 m_columnManager->setEnumNames(m_errColumn, columns);
3009 if (!errName.isEmpty()) {
3010 m_columnManager->setValue(m_errColumn, columns.indexOf(errName));
3011 } else {
3012 m_columnManager->setValue(m_errColumn, 0);
3013 }
3014 return;
3015 }
3016}
3017
3019 if (m_browser->isItemVisible(m_settingsGroup)) {
3020 if (!m_settingsGroup->property()->subProperties().contains(m_workspaceIndex)) {
3021 m_settingsGroup->property()->insertSubProperty(m_workspaceIndex, m_workspace);
3022 }
3023 }
3024}
3025
3032}
3033
3038 if (m_browser->isItemVisible(m_settingsGroup)) {
3039 m_browser->setItemVisible(m_settingsGroup, false);
3040 } else {
3041 m_browser->setItemVisible(m_settingsGroup, true);
3042 }
3043}
3044
3049void FitPropertyBrowser::removePropertiesFromSettingsBrowser(const QStringList &propsToRemove) {
3050 // get settings properties
3051 QList<QtProperty *> props = m_settingsGroup->property()->subProperties();
3052 for (auto &prop : props) {
3053 if (propsToRemove.contains(prop->propertyName())) {
3054 m_settingsGroup->property()->removeSubProperty(prop);
3055 }
3056 }
3057}
3058
3060
3067 if (prop == m_xColumn) { // update startX and endX
3068 try {
3070 auto tws = std::dynamic_pointer_cast<Mantid::API::ITableWorkspace>(ws);
3071 if (!tws)
3072 return;
3073 int i = m_columnManager->value(m_xColumn);
3074 if (i < 0 || i >= static_cast<int>(tws->rowCount()) || tws->rowCount() == 0)
3075 return;
3076 auto col = tws->getColumn(static_cast<size_t>(i));
3077 const double startX = col->toDouble(0);
3078 const double endX = col->toDouble(tws->rowCount() - 1);
3079 m_doubleManager->setValue(m_startX, startX);
3080 m_doubleManager->setValue(m_endX, endX);
3081 } catch (...) {
3082 // do nothing
3083 }
3084 }
3085}
3086
3091 // delete old minimizer properties
3092 foreach (QtProperty *prop, m_minimizerProperties) { m_settingsGroup->property()->removeSubProperty(prop); }
3093
3094 // add new minimizer properties
3095 auto minzer = Mantid::API::FuncMinimizerFactory::Instance().createMinimizer(this->minimizer());
3096 auto &properties = minzer->getProperties();
3097 for (auto property : properties) {
3098 QString propName = QString::fromStdString((*property).name());
3099 QtProperty *prop = nullptr;
3100 if (auto prp = dynamic_cast<Mantid::Kernel::PropertyWithValue<bool> *>(property)) {
3101 prop = m_boolManager->addProperty(propName);
3102 bool val = *prp;
3103 m_boolManager->setValue(prop, val);
3104 } else if (auto prp = dynamic_cast<Mantid::Kernel::PropertyWithValue<double> *>(property)) {
3105 prop = this->addDoubleProperty(propName);
3106 double val = *prp;
3107 m_doubleManager->setValue(prop, val);
3108 } else if (auto prp = dynamic_cast<Mantid::Kernel::PropertyWithValue<int> *>(property)) {
3109 prop = m_intManager->addProperty(propName);
3110 int val = *prp;
3111 m_intManager->setValue(prop, val);
3112 } else if (auto prp = dynamic_cast<Mantid::Kernel::PropertyWithValue<size_t> *>(property)) {
3113 prop = m_intManager->addProperty(propName);
3114 size_t val = *prp;
3115 m_intManager->setValue(prop, static_cast<int>(val));
3116 } else if (auto prp = dynamic_cast<Mantid::Kernel::PropertyWithValue<std::string> *>(property)) {
3117 prop = m_stringManager->addProperty(propName);
3118 QString val = QString::fromStdString(prp->value());
3119 m_stringManager->setValue(prop, val);
3120 } else if (dynamic_cast<Mantid::API::IWorkspaceProperty *>(property)) {
3121 prop = m_stringManager->addProperty(propName);
3122 m_stringManager->setValue(prop, QString::fromStdString((*property).value()));
3123 } else {
3124 QMessageBox::warning(this, "Mantid - Error",
3125 "Type of minimizer's property " + propName + " is not yet supported by the browser.");
3126 continue;
3127 }
3128
3129 if (!prop)
3130 continue;
3131 // set the tooltip from property doc string
3132 QString toolTip = QString::fromStdString((*property).documentation());
3133 if (!toolTip.isEmpty()) {
3134 prop->setToolTip(toolTip);
3135 }
3136 m_settingsGroup->property()->addSubProperty(prop);
3137 m_minimizerProperties.append(prop);
3138 }
3139}
3140
3145 auto fun = theFunction();
3146 size_t np = fun->nParams();
3147 QList<double> out;
3148 for (size_t i = 0; i < np; ++i) {
3149 const double parValue = fun->getParameter(i);
3150 out.append(parValue);
3151 }
3152 return out;
3153}
3154
3159 auto fun = theFunction();
3160 size_t np = fun->nParams();
3161 QStringList out;
3162 for (size_t i = 0; i < np; ++i) {
3163 std::string parName = fun->parameterName(i);
3164 out.append(QString::fromStdString(parName));
3165 }
3166 return out;
3167}
3172
3177
3182 PropertyHandler *handler = currentHandler();
3183 if (handler) {
3185 }
3186}
3187
3192 MantidDesktopServices::openUrl(QUrl("http://www.mantidproject.org/"
3193 "MantidPlot:_Simple_Peak_Fitting_with_the_Fit_"
3194 "Wizard#Fit_Properties_Browser"));
3195}
3196
3203 if (m_fitActionSeqFit) {
3204 if (allow) {
3205 m_fitActionSeqFit->setEnabled(m_compositeFunction->nFunctions() > 0);
3206 } else {
3207 m_fitActionSeqFit->setEnabled(false);
3208 }
3209 }
3210}
3211
3212void FitPropertyBrowser::modifyFitMenu(QAction *fitAction, bool enabled) {
3213 if (enabled) {
3214 m_fitMenu->addAction(fitAction);
3215 } else {
3216 m_fitMenu->removeAction(fitAction);
3217 }
3218}
3219
3221 return m_functionsGroup->children().size();
3222}
3223
3224void FitPropertyBrowser::addAllowedSpectra(const QString &wsName, const QList<int> &wsSpectra) {
3225 auto const name = wsName.toStdString();
3226 auto ws = AnalysisDataService::Instance().retrieveWS<MatrixWorkspace>(name);
3227 if (ws) {
3228 QList<int> indices;
3229 indices.reserve(wsSpectra.size());
3230 std::transform(wsSpectra.cbegin(), wsSpectra.cend(), std::back_inserter(indices),
3231 [&ws](const auto i) { return static_cast<int>(ws->getIndexFromSpectrumNumber(i)); });
3232
3233 auto wsFound = m_allowedSpectra.find(wsName);
3234 m_allowedSpectra.insert(wsName, indices);
3235 if (wsFound != m_allowedSpectra.end()) {
3236 // we already knew about this workspace
3237 // update workspace index list
3239 } else {
3240 // new workspace, update workspace names
3242 }
3243 } else {
3244 throw std::runtime_error("Workspace " + name + " is not a MatrixWorkspace");
3245 }
3246}
3247
3248void FitPropertyBrowser::removeWorkspaceAndSpectra(const std::string &wsName) {
3249 removeWorkspace(wsName);
3250 // remove spectra
3251 QString qWsName = QString::fromStdString(wsName);
3252 m_allowedSpectra.erase(m_allowedSpectra.find(qWsName));
3253}
3254
3256 auto const name = wsName.toStdString();
3257 auto ws = AnalysisDataService::Instance().retrieveWS<ITableWorkspace>(name);
3258 if (ws) {
3259 m_allowedTableWorkspace = wsName;
3260 } else {
3261 throw std::runtime_error("Workspace " + name + " is not a TableWorkspace");
3262 }
3263}
3264
3273QString FitPropertyBrowser::addFunction(const QString &fnName) {
3274 return addFunction(fnName.toStdString())->functionPrefix();
3275}
3276
3278 if (prefix.isEmpty())
3279 throw std::runtime_error("Peak function prefix cannot be empty");
3280 auto const indexList = prefix.split(".");
3281 auto const n = indexList.size() - 1;
3282 auto handler = getHandler();
3283 for (int i = 0; i < n; ++i) {
3284 auto const index = indexList[i].mid(1).toInt();
3285 handler = handler->getHandler(index);
3286 }
3287 return handler->getHandler(indexList[n].mid(1).toInt());
3288}
3289
3290void FitPropertyBrowser::setPeakCentreOf(const QString &prefix, double value) {
3291 auto handler = getPeakHandler(prefix);
3292 handler->setCentre(value);
3293 handler->updateParameters();
3294}
3295
3296double FitPropertyBrowser::getPeakCentreOf(const QString &prefix) {
3297 auto handler = getPeakHandler(prefix);
3298 return handler->centre();
3299}
3300
3301void FitPropertyBrowser::setPeakHeightOf(const QString &prefix, double value) {
3302 auto handler = getPeakHandler(prefix);
3303 handler->setHeight(value);
3304 handler->updateParameters();
3305}
3306
3307double FitPropertyBrowser::getPeakHeightOf(const QString &prefix) {
3308 auto handler = getPeakHandler(prefix);
3309 return handler->height();
3310}
3311
3312void FitPropertyBrowser::setPeakFwhmOf(const QString &prefix, double value) {
3313 auto handler = getPeakHandler(prefix);
3314 handler->setFwhm(value);
3315 handler->updateParameters();
3316}
3317
3318double FitPropertyBrowser::getPeakFwhmOf(const QString &prefix) {
3319 auto handler = getPeakHandler(prefix);
3320 return handler->fwhm();
3321}
3322
3323std::string FitPropertyBrowser::getWidthParameterNameOf(const QString &prefix) {
3324 auto handler = getPeakHandler(prefix);
3325 return handler->getWidthParameterName();
3326}
3327
3328std::string FitPropertyBrowser::getCentreParameterNameOf(const QString &prefix) {
3329 auto handler = getPeakHandler(prefix);
3330 return handler->getCentreParameterName();
3331}
3332
3333bool FitPropertyBrowser::isParameterExplicitlySetOf(const QString &prefix, const std::string &param) {
3334 auto handler = getPeakHandler(prefix);
3335 return handler->isParameterExplicitlySet(param);
3336}
3337
3339 QStringList peaks;
3340 auto parentHandler = getHandler();
3341 auto nFunctions = parentHandler->cfun()->nFunctions();
3342 for (size_t i = 0; i < nFunctions; ++i) {
3343 auto handler = parentHandler->getHandler(i);
3344 if (handler->pfun()) {
3345 peaks << handler->functionPrefix();
3346 }
3347 }
3348 return peaks;
3349}
3350
3351} // namespace MantidWidgets
3352} // namespace MantidQt
CostFunctions::CostFuncFitting & m_costFunction
The cost function.
double value
The value of the point.
Definition: FitMW.cpp:51
IPeaksWorkspace_sptr workspace
Definition: IndexPeaks.cpp:114
std::map< DeltaEMode::Type, std::string > index
Definition: DeltaEMode.cpp:19
static void showFitFunction(const std::string &name=std::string())
Definition: HelpWindow.cpp:80
static bool openUrl(const QUrl &url)
Opens a url in the appropriate web browser.
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.
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.
std::string defaultBackgroundType() const
Get the default background type.
QStringList m_registeredBackgrounds
A list of registered backgrounds.
int workspaceIndex() const
Get workspace index.
QVector< double > getXRange()
Get the X limits of the workspace.
void setStartX(double start) override
Set the start X.
void addAutoBackground()
Creates and adds the autobackground.
QStringList m_registeredOther
A list of registered functions that are neither peaks nor backgrounds.
bool isUndoEnabled() const
Tells if undo can be done.
FitPropertyBrowser(QWidget *parent=nullptr, QObject *mantidui=nullptr)
Constructor.
void createEditors(QWidget *w)
Create editors and assign them to the managers.
QtProperty * getTieProperty(QtProperty *parProp) const
Returns the tie property for a parameter property, or NULL.
void removeBounds()
Slot.Removes lower and upper bounds from the selected parameter property.
void addUpperBound()
Slot.Adds upper bound to the selected parameter property.
Mantid::API::IFunction_sptr getFittingFunction() const
Return the fitting function.
std::vector< double > m_initialParameters
To keep a copy of the initial parameters in case for undo fit.
void handleFactoryUpdate(Mantid::API::FunctionFactoryUpdateNotification_ptr)
Callback for FunctionFactory update notifications.
void doFit(int maxIterations)
Do the fitting.
virtual void intChanged(QtProperty *prop)
Called when an int property changed.
bool isPeak() const
Is the current function a peak?
bool isFitEnabled() const
Returns true if the function is ready for a fit.
int maxIterations() const
Get the max number of iterations.
QtGroupPropertyManager * m_groupManager
Property managers:
void paste()
Paste a function string from the clipboard.
int m_oldWorkspaceIndex
Store workspace index to revert to in case validation fails.
QStringList m_registeredPeaks
A list of registered peaks.
std::string m_defaultPeak
Default peak name.
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.
std::string getFitAlgorithmParameters() const
================================================================================================= Get...
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)
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 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 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.
void hasConstraints(QtProperty *parProp, bool &hasTie, bool &hasBounds) const
Does a parameter have a tie.
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.
std::string getFitAlgorithmOutputStatus() const
================================================================================================= Get...
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
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.
void addAllowedTableWorkspace(const QString &wsName)
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.
void workspaceDoubleClicked(QListWidgetItem *item)
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.
std::string defaultFunctionType() const
Get the default function type.
QStringList m_costFunctions
A list of available cost functions.
QtBrowserItem * m_customSettingsGroup
Group for custom options available on muon analysis widget.
QStringList getWorkspaceNames()
Returns the list of workspaces that are currently been worked on by the fit property browser.
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.
void updateErrors()
Set all parameter error values in the manager.
QMap< QString, QtProperty * > getTies()
PropertyHandler * findHandler(const Mantid::API::IFunction *fun)
void setCentre(const double &c)
Set the centre of the handled peak function.
void setVectorAttribute(QtProperty *prop)
Set function vector attribute value.
void calcBaseAll()
If the handled function is composite calculate the peak baselines for all members.
void setHeight(const double &h)
Set the height of the handled peak function.
void removeAllPlots()
Remove all plots including children's.
std::shared_ptr< Mantid::API::IFunction > ifun() const
std::shared_ptr< const Mantid::API::CompositeFunction > findCompositeFunction(QtBrowserItem *item) const
Returns 'this' if item == m_item and this is a composite function or calls findCompositeFunction recu...
std::shared_ptr< const Mantid::API::IFunction > findFunction(QtBrowserItem *item) const
Returns 'this' if item == m_item or calls findFunction recursively with all its children or zero.
std::shared_ptr< Mantid::API::IFunction > changeType(QtProperty *prop)
Change the type of the function (replace the function)
QString updateStructureTooltip()
Update high-level structure tooltip and return it.
void clearErrors()
Clear all parameter error values in the manager.
void updateParameters()
Sync all parameter values with the manager.
QtProperty * getParameterProperty(const QString &parName) const
void updateAttributes()
Sync all parameter values with the manager.
Select a function type out of a list of available ones.
QString getFunction() const
Return selected function.
void observeFinish(const IAlgorithm_const_sptr &alg)
Connect to algorithm alg and observe its finish notification.
ColumnVector gives access to the column elements without alowing its resizing.
A composite function is a function containing other functions.
IFunction_sptr function() const
Return the handled function.
Definition: IFunction.h:755
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:163
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...
Definition: IPeakFunction.h:51
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.
Ties fitting parameters.
Definition: ParameterTie.h:35
virtual void set(const std::string &expr)
Set the tie expression.
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:52
void warning(const std::string &msg)
Logs at warning level.
Definition: Logger.cpp:86
The concrete, templated class for properties.
Manage the lifetime of a class intended to be a singleton.
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
Definition: Workspace_fwd.h:20
Kernel::Logger g_log("ExperimentInfo")
static logger object
std::shared_ptr< IFunction > IFunction_sptr
shared pointer to the function base class
Definition: IFunction.h:732
std::shared_ptr< const IFunction > IFunction_const_sptr
shared pointer to the function base class (const version)
Definition: IFunction.h:734
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
constexpr double Tolerance
Standard tolerance value.
Definition: Tolerance.h:12
Helper class which provides the Collimation Length for SANS instruments.
Simple Exception Struct to differentiate validation error from other exceptions.
Definition: IFunction.h:168