Mantid
Loading...
Searching...
No Matches
FitScriptGeneratorView.cpp
Go to the documentation of this file.
1// Mantid Repository : https://github.com/mantidproject/mantid
2//
3// Copyright © 2020 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 +
15#include "MantidQtWidgets/Common/QtPropertyBrowser/DoubleDialogEditor.h"
16#include "MantidQtWidgets/Common/QtPropertyBrowser/qttreepropertybrowser.h"
17
20
21#include <algorithm>
22#include <iterator>
23
24#include <QApplication>
25#include <QClipboard>
26#include <QFileDialog>
27#include <QMessageBox>
28#include <QMetaObject>
29#include <QThread>
30
31using namespace Mantid::Kernel;
32using namespace MantidQt::API;
33
34namespace {
36
37template <typename T> std::vector<T> convertQListToStdVector(QList<T> const &qList) {
38 std::vector<T> vec;
39 vec.reserve(static_cast<std::size_t>(qList.size()));
40 std::transform(qList.cbegin(), qList.cend(), std::back_inserter(vec), [](T const &element) { return element; });
41 return vec;
42}
43
44template <typename T> QList<T> convertToQList(std::vector<T> const &vec) {
45 QList<T> qList;
46 qList.reserve(static_cast<int>(vec.size()));
47 std::transform(vec.cbegin(), vec.cend(), std::back_inserter(qList), [](T const &element) { return element; });
48 return qList;
49}
50
51QString getDefaultScriptDirectory() {
52 auto const previousDirectory = AlgorithmInputHistory::Instance().getPreviousDirectory();
53 if (previousDirectory.isEmpty())
54 return QString::fromStdString(ConfigService::Instance().getString("pythonscripts.directory"));
55 return previousDirectory;
56}
57
58} // namespace
59
61
64
66 QMap<QString, QString> const &fitOptions)
67 : IFitScriptGeneratorView(parent), m_presenter(), m_dataTable(std::make_unique<FitScriptGeneratorDataTable>()),
68 m_functionTreeView(std::make_unique<FunctionTreeView>(nullptr, true)),
69 m_fitOptionsBrowser(std::make_unique<FitScriptOptionsBrowser>(nullptr)), m_editLocalParameterDialog(nullptr) {
70 m_ui.setupUi(this);
71
72 m_ui.fDataTable->layout()->addWidget(m_dataTable.get());
73 m_ui.splitterVertical->addWidget(m_functionTreeView.get());
74 m_ui.splitterVertical->addWidget(m_fitOptionsBrowser.get());
75 m_ui.splitterVertical->setSizes({360, 120});
76
77 setFittingMode(fittingMode);
80
81 observeDelete(true);
82 observeClear(true);
83 observeRename(true);
84}
85
95
97 connect(m_ui.pbRemoveDomain, SIGNAL(clicked()), this, SLOT(onRemoveDomainClicked()));
98 connect(m_ui.pbAddDomain, SIGNAL(clicked()), this, SLOT(onAddDomainClicked()));
99 connect(m_dataTable.get(), SIGNAL(cellChanged(int, int)), this, SLOT(onCellChanged(int, int)));
100 connect(m_dataTable.get(), SIGNAL(itemSelectionChanged()), this, SLOT(onItemSelected()));
101
102 connect(m_functionTreeView.get(), SIGNAL(functionRemovedString(std::string const &)), this,
103 SLOT(onFunctionRemoved(std::string const &)));
104 connect(m_functionTreeView.get(), SIGNAL(functionAdded(std::string const &)), this,
105 SLOT(onFunctionAdded(const std::string &)));
106 connect(m_functionTreeView.get(), SIGNAL(functionReplaced(std::string const &)), this,
107 SLOT(onFunctionReplaced(std::string const &)));
108 connect(m_functionTreeView.get(), SIGNAL(parameterChanged(std::string const &)), this,
109 SLOT(onParameterChanged(std::string const &)));
110 connect(m_functionTreeView.get(), SIGNAL(attributePropertyChanged(std::string const &)), this,
111 SLOT(onAttributeChanged(std::string const &)));
112 connect(m_functionTreeView.get(), SIGNAL(parameterTieChanged(std::string const &, std::string const &)), this,
113 SLOT(onParameterTieChanged(std::string const &, std::string const &)));
114 connect(m_functionTreeView.get(), SIGNAL(parameterConstraintRemoved(std::string const &)), this,
115 SLOT(onParameterConstraintRemoved(std::string const &)));
116 connect(m_functionTreeView.get(), SIGNAL(parameterConstraintAdded(std::string const &, std::string const &)), this,
117 SLOT(onParameterConstraintChanged(std::string const &, std::string const &)));
118 connect(m_functionTreeView.get(), SIGNAL(globalsChanged(std::vector<std::string> const &)), this,
119 SLOT(onGlobalParametersChanged(std::vector<std::string> const &)));
120 connect(m_functionTreeView.get(), SIGNAL(copyToClipboardRequest()), this, SLOT(onCopyFunctionToClipboard()));
121 connect(m_functionTreeView.get(), SIGNAL(functionHelpRequest()), this, SLOT(onFunctionHelpRequested()));
122 connect(m_functionTreeView.get(), SIGNAL(localParameterButtonClicked(std::string const &)), this,
123 SLOT(onEditLocalParameterClicked(std::string const &)));
124
125 connect(m_fitOptionsBrowser.get(), SIGNAL(outputBaseNameChanged(std::string const &)), this,
126 SLOT(onOutputBaseNameChanged(std::string const &)));
127 connect(m_fitOptionsBrowser.get(), SIGNAL(fittingModeChanged(FittingMode)), this,
129
130 connect(m_ui.pbGenerateScriptToFile, SIGNAL(clicked()), this, SLOT(onGenerateScriptToFileClicked()));
131 connect(m_ui.pbGenerateScriptToClipboard, SIGNAL(clicked()), this, SLOT(onGenerateScriptToClipboardClicked()));
132 connect(m_ui.pbHelp, SIGNAL(clicked()), this, SLOT(onHelpClicked()));
133
139 disconnect(m_functionTreeView->doubleEditorFactory(), SIGNAL(closeEditor()), m_functionTreeView->treeBrowser(),
140 SLOT(closeEditor()));
141}
142
143void FitScriptGeneratorView::setFitBrowserOptions(QMap<QString, QString> const &fitOptions) {
144 for (auto it = fitOptions.constBegin(); it != fitOptions.constEnd(); ++it)
145 m_fitOptionsBrowser->setProperty(it.key().toStdString(), it.value().toStdString());
146}
147
149 m_fitOptionsBrowser->setFittingMode(fittingMode);
150}
151
153 m_presenter = presenter;
154 m_presenter->notifyPresenter(ViewEvent::FittingModeChanged, m_fitOptionsBrowser->getFittingMode());
155}
156
157void FitScriptGeneratorView::deleteHandle(std::string const &wsName, [[maybe_unused]] Workspace_sptr const &ws) {
158 if (QThread::currentThread() != QApplication::instance()->thread()) {
159 QMetaObject::invokeMethod(this, "notifyADSDeleteEvent", Qt::AutoConnection, Q_ARG(std::string const &, wsName));
160 } else {
161 notifyADSDeleteEvent(wsName);
162 }
163}
164
166 if (QThread::currentThread() != QApplication::instance()->thread()) {
167 QMetaObject::invokeMethod(this, "notifyADSClearEvent", Qt::AutoConnection);
168 } else {
170 }
171}
172
173void FitScriptGeneratorView::renameHandle(std::string const &wsName, std::string const &newName) {
174 if (QThread::currentThread() != QApplication::instance()->thread()) {
175 QMetaObject::invokeMethod(this, "notifyADSRenameEvent", Qt::AutoConnection, Q_ARG(std::string const &, wsName),
176 Q_ARG(std::string const &, newName));
177 } else {
178 notifyADSRenameEvent(wsName, newName);
179 }
180}
181
182void FitScriptGeneratorView::notifyADSDeleteEvent(std::string const &workspaceName) {
183 m_presenter->notifyPresenter(ViewEvent::ADSDeleteEvent, workspaceName);
184}
185
187
188void FitScriptGeneratorView::notifyADSRenameEvent(std::string const &workspaceName, std::string const &newName) {
189 m_presenter->notifyPresenter(ViewEvent::ADSRenameEvent, workspaceName, newName);
190}
191
193
195
196void FitScriptGeneratorView::onCellChanged(int row, int column) {
197 UNUSED_ARG(row);
198
199 if (column == ColumnIndex::StartX) {
200 m_dataTable->formatSelection();
201 m_presenter->notifyPresenter(ViewEvent::StartXChanged);
202 } else if (column == ColumnIndex::EndX) {
203 m_dataTable->formatSelection();
204 m_presenter->notifyPresenter(ViewEvent::EndXChanged);
205 }
206}
207
209
210void FitScriptGeneratorView::onFunctionRemoved(std::string const &function) {
211 m_presenter->notifyPresenter(ViewEvent::FunctionRemoved, function);
212}
213
214void FitScriptGeneratorView::onFunctionAdded(std::string const &function) {
215 m_presenter->notifyPresenter(ViewEvent::FunctionAdded, function);
216}
217
218void FitScriptGeneratorView::onFunctionReplaced(std::string const &function) {
219 m_presenter->notifyPresenter(ViewEvent::FunctionReplaced, function);
220}
221
222void FitScriptGeneratorView::onParameterChanged(std::string const &parameter) {
223 m_presenter->notifyPresenter(ViewEvent::ParameterChanged, parameter);
224}
225
226void FitScriptGeneratorView::onAttributeChanged(std::string const &attribute) {
227 m_presenter->notifyPresenter(ViewEvent::AttributeChanged, attribute);
228}
229
230void FitScriptGeneratorView::onParameterTieChanged(std::string const &parameter, std::string const &tie) {
231 m_presenter->notifyPresenter(ViewEvent::ParameterTieChanged, parameter, tie);
232}
233
235 m_presenter->notifyPresenter(ViewEvent::ParameterConstraintRemoved, parameter);
236}
237
238void FitScriptGeneratorView::onParameterConstraintChanged(std::string const &functionIndex,
239 std::string const &constraint) {
240 m_presenter->notifyPresenter(ViewEvent::ParameterConstraintChanged, functionIndex, constraint);
241}
242
243void FitScriptGeneratorView::onGlobalParametersChanged(std::vector<std::string> const &globalParameters) {
244 m_presenter->notifyPresenter(ViewEvent::GlobalParametersChanged, globalParameters);
245}
246
248 if (auto const function = m_functionTreeView->getSelectedFunction())
249 saveTextToClipboard(function->asString());
250}
251
253 if (auto const function = m_functionTreeView->getSelectedFunction())
254 m_functionTreeView->showFunctionHelp(function->name());
255}
256
257void FitScriptGeneratorView::onOutputBaseNameChanged(std::string const &outputBaseName) {
258 m_presenter->notifyPresenter(ViewEvent::OutputBaseNameChanged, outputBaseName);
259}
260
262 m_presenter->notifyPresenter(ViewEvent::FittingModeChanged, fittingMode);
263}
264
265void FitScriptGeneratorView::onEditLocalParameterClicked(std::string const &parameter) {
266 m_presenter->notifyPresenter(ViewEvent::EditLocalParameterClicked, parameter);
267}
268
270 if (result == QDialog::Accepted)
271 m_presenter->notifyPresenter(ViewEvent::EditLocalParameterFinished);
272
274}
275
277 m_presenter->notifyPresenter(ViewEvent::GenerateScriptToFileClicked);
278}
279
281 m_presenter->notifyPresenter(ViewEvent::GenerateScriptToClipboardClicked);
282}
283
285 MantidQt::API::HelpWindow::showCustomInterface("Fit Script Generator", QString("general"));
286}
287
289 return m_dataTable->workspaceName(index);
290}
291
295
297
299
300std::vector<FitDomainIndex> FitScriptGeneratorView::allRows() const { return m_dataTable->allRows(); }
301
302std::vector<FitDomainIndex> FitScriptGeneratorView::selectedRows() const { return m_dataTable->selectedRows(); }
303
305
306bool FitScriptGeneratorView::hasLoadedData() const { return m_dataTable->hasLoadedData(); }
307
308double FitScriptGeneratorView::parameterValue(std::string const &parameter) const {
309 return m_functionTreeView->getParameter(parameter);
310}
311
313 return m_functionTreeView->getAttribute(attribute);
314}
315
316void FitScriptGeneratorView::renameWorkspace(std::string const &workspaceName, std::string const &newName) {
317 m_dataTable->renameWorkspace(QString::fromStdString(workspaceName), QString::fromStdString(newName));
318}
319
320void FitScriptGeneratorView::removeDomain(FitDomainIndex domainIndex) { m_dataTable->removeDomain(domainIndex); }
321
322void FitScriptGeneratorView::addWorkspaceDomain(std::string const &workspaceName, WorkspaceIndex workspaceIndex,
323 double startX, double endX) {
324 m_dataTable->addDomain(QString::fromStdString(workspaceName), workspaceIndex, startX, endX);
325}
326
328 auto dialog = new AddWorkspaceDialog(this);
329 dialog->setAttribute(Qt::WA_DeleteOnClose);
330 dialog->show();
331 connect(dialog, SIGNAL(addData(MantidWidgets::IAddWorkspaceDialog *)), this,
333}
334
336 if (auto addWorkspaceDialog = dynamic_cast<MantidWidgets::AddWorkspaceDialog const *>(dialog)) {
337 m_presenter->handleAddDomainAccepted(getDialogWorkspaces(dialog), addWorkspaceDialog->workspaceIndices());
338 }
339}
340
341std::vector<MatrixWorkspace_const_sptr>
343 std::vector<MatrixWorkspace_const_sptr> workspaces;
344 if (dialog) {
345 auto const wsName = dialog->workspaceName();
346 auto &ads = AnalysisDataService::Instance();
347 if (ads.doesExist(wsName)) {
348 workspaces.emplace_back(ads.retrieveWS<MatrixWorkspace>(wsName));
349 } else {
350 displayWarning("Failed to add workspace: '" + wsName + "' doesn't exist.");
351 }
352 }
353 return workspaces;
354}
355
357 std::string const &parameter, std::vector<std::string> const &workspaceNames,
358 std::vector<std::string> const &domainNames, std::vector<double> const &values, std::vector<bool> const &fixes,
359 std::vector<std::string> const &ties, std::vector<std::string> const &constraints) {
361 this, parameter, workspaceNames, domainNames, convertToQList(values), convertToQList(fixes),
363
364 connect(m_editLocalParameterDialog, SIGNAL(finished(int)), this, SLOT(onEditLocalParameterFinished(int)));
365
367}
368
369std::tuple<std::string, std::vector<double>, std::vector<bool>, std::vector<std::string>, std::vector<std::string>>
377
378std::tuple<std::string, std::string, std::string, std::string, std::string, bool>
380 return {m_fitOptionsBrowser->getProperty("Max Iterations"), m_fitOptionsBrowser->getProperty("Minimizer"),
381 m_fitOptionsBrowser->getProperty("Cost Function"), m_fitOptionsBrowser->getProperty("Evaluation Type"),
382 m_fitOptionsBrowser->getProperty("Output Base Name"), m_fitOptionsBrowser->getBoolProperty("Plot Output")};
383}
384
386 auto const defaultDirectory = getDefaultScriptDirectory();
387 auto const filePath = QFileDialog::getSaveFileName(this->parentWidget(), tr("Save Script As "), defaultDirectory,
388 tr("Script files (*.py)"));
389
390 if (!filePath.isEmpty())
391 API::AlgorithmInputHistory::Instance().setPreviousDirectory(QFileInfo(filePath).absoluteDir().path());
392
393 return filePath.toStdString();
394}
395
397
399 return m_ui.cbApplyFunctionChangesTo->currentText() == "All Domains";
400}
401
403
405 m_dataTable->setFunctionPrefixVisible(simultaneousMode);
406 m_functionTreeView->setMultiDomainFunctionPrefix(
407 simultaneousMode ? m_dataTable->selectedDomainFunctionPrefix().toStdString() : "");
408
409 if (simultaneousMode)
410 m_functionTreeView->showGlobals();
411 else
412 m_functionTreeView->hideGlobals();
413}
414
416 if (function)
417 m_functionTreeView->setFunction(function);
418 else
419 m_functionTreeView->clear();
420}
421
422void FitScriptGeneratorView::setGlobalTies(std::vector<GlobalTie> const &globalTies) {
423 m_functionTreeView->setGlobalTies(globalTies);
424}
425
426void FitScriptGeneratorView::setGlobalParameters(std::vector<GlobalParameter> const &globalParameters) {
427 std::vector<std::string> globals;
428 globals.reserve(globalParameters.size());
429 std::transform(globalParameters.cbegin(), globalParameters.cend(), std::back_inserter(globals),
430 [](GlobalParameter const &globalParam) { return globalParam.m_parameter; });
431 m_functionTreeView->setGlobalParameters(globals);
432}
433
434void FitScriptGeneratorView::setSuccessText(std::string const &text) {
435 m_ui.lbMessage->setText(QString::fromStdString(text));
436}
437
438void FitScriptGeneratorView::saveTextToClipboard(std::string const &text) const {
439 if (QClipboard *clipboard = QApplication::clipboard())
440 clipboard->setText(QString::fromStdString(text));
441}
442
443void FitScriptGeneratorView::displayWarning(std::string const &message) {
444 QMessageBox::warning(this, "Warning!", QString::fromStdString(message));
445}
446
447} // namespace MantidQt::MantidWidgets
std::map< DeltaEMode::Type, std::string > index
std::vector< T > const * vec
#define UNUSED_ARG(x)
Function arguments are sometimes unused in certain implmentations but are required for documentation ...
Definition System.h:48
static void showCustomInterface(const QString &name, const QString &area=QString(), const QString &section=QString())
A dialog for displaying and editing values of local parameters.
const QList< double > & getValues() const
Get the list of new parameter values.
const QStringList & getConstraints() const
Get a list of the constraints.
const QStringList & getTies() const
Get a list of the ties.
const QList< bool > & getFixes() const
Get a list with the "fixed" attribute.
This class represents the table widget which holds domain data for the FitScriptGenerator interface.
std::unique_ptr< FitScriptOptionsBrowser > m_fitOptionsBrowser
FitScriptGeneratorView(QWidget *parent=nullptr, FittingMode fittingMode=FittingMode::SEQUENTIAL, QMap< QString, QString > const &fitOptions=QMap< QString, QString >())
void onParameterConstraintChanged(std::string const &functionIndex, std::string const &constraint)
std::string workspaceName(FitDomainIndex index) const override
double parameterValue(std::string const &parameter) const override
std::tuple< std::string, std::vector< double >, std::vector< bool >, std::vector< std::string >, std::vector< std::string > > getEditLocalParameterResults() const override
void setSuccessText(std::string const &text) override
void saveTextToClipboard(std::string const &text) const override
void subscribePresenter(IFitScriptGeneratorPresenter *presenter) override
std::unique_ptr< FunctionTreeView > m_functionTreeView
void onEditLocalParameterClicked(std::string const &parameter)
void renameHandle(std::string const &wsName, std::string const &newName) override
If a workspace is renamed in the ADS, then this function will trigger, works by overloading this clas...
void onOutputBaseNameChanged(std::string const &outputBaseName)
void clearHandle() override
If the ADS is cleared, then this function will trigger, works by overloading this class and overridin...
void renameWorkspace(std::string const &workspaceName, std::string const &newName) override
Mantid::API::IFunction::Attribute attributeValue(std::string const &attribute) const override
void notifyADSRenameEvent(std::string const &workspaceName, std::string const &newName)
void setGlobalParameters(std::vector< GlobalParameter > const &globalParameter) override
void setGlobalTies(std::vector< GlobalTie > const &globalTies) override
std::tuple< std::string, std::string, std::string, std::string, std::string, bool > fitOptions() const override
void setSimultaneousMode(bool simultaneousMode) override
std::vector< FitDomainIndex > allRows() const override
void setFunction(Mantid::API::IFunction_sptr const &function) const override
void setFitBrowserOptions(QMap< QString, QString > const &fitOptions)
void notifyADSDeleteEvent(std::string const &workspaceName)
void openEditLocalParameterDialog(std::string const &parameter, std::vector< std::string > const &workspaceNames, std::vector< std::string > const &domainNames, std::vector< double > const &values, std::vector< bool > const &fixes, std::vector< std::string > const &ties, std::vector< std::string > const &constraints) override
void removeDomain(FitDomainIndex domainIndex) override
std::vector< FitDomainIndex > selectedRows() const override
WorkspaceIndex workspaceIndex(FitDomainIndex index) const override
std::vector< Mantid::API::MatrixWorkspace_const_sptr > getDialogWorkspaces(MantidWidgets::IAddWorkspaceDialog *dialog) override
void addWorkspaceDialogAccepted(MantidWidgets::IAddWorkspaceDialog *dialog)
void onGlobalParametersChanged(std::vector< std::string > const &globalParameters)
std::unique_ptr< FitScriptGeneratorDataTable > m_dataTable
void addWorkspaceDomain(std::string const &workspaceName, WorkspaceIndex workspaceIndex, double startX, double endX) override
void deleteHandle(std::string const &wsName, Workspace_sptr const &ws) override
If a workspace is deleted from the ADS, then this function will trigger, works by overloading this cl...
void onParameterConstraintRemoved(std::string const &parameter)
double startX(FitDomainIndex index) const override
double endX(FitDomainIndex index) const override
void displayWarning(std::string const &message) override
void onParameterTieChanged(std::string const &parameter, std::string const &tie)
The BasicFitOptionsBrowser class implements a QtPropertyBrowser to display fitting properties found i...
Class FitPropertyBrowser implements QtPropertyBrowser to display and control fitting function paramet...
virtual std::string workspaceName() const =0
virtual void handleAddDomainAccepted(std::vector< Mantid::API::MatrixWorkspace_const_sptr > const &workspaces, FunctionModelSpectra const &workspaceIndices)=0
virtual void notifyPresenter(ViewEvent const &event, std::string const &arg1="", std::string const &arg2="")=0
void observeRename(bool turnOn=true)
Function will add/remove the observer to the ADS for when a workspace is renamed.
void observeDelete(bool turnOn=true)
Function will add/remove the observer to the ADS for when a workspace is deleted.
void observeClear(bool turnOn=true)
Function will add/remove the observer to the ADS for when the ADS is cleared.
Attribute is a non-fitting parameter.
Definition IFunction.h:285
Base MatrixWorkspace Abstract Class.
QStringList EXPORT_OPT_MANTIDQT_COMMON stdVectorToQStringList(std::vector< std::string > const &vec)
IFitScriptGeneratorView::Event ViewEvent
FitScriptGeneratorDataTable::ColumnIndex ColumnIndex
std::vector< std::string > EXPORT_OPT_MANTIDQT_COMMON qStringListToStdVector(QStringList const &qList)
std::shared_ptr< Workspace > Workspace_sptr
shared pointer to Mantid::API::Workspace
std::shared_ptr< IFunction > IFunction_sptr
shared pointer to the function base class
Definition IFunction.h:743
STL namespace.
This struct stores the name of a global parameter which is shared across ALL domains in a multi datas...