Newer
Older
// Mantid Repository : https://github.com/mantidproject/mantid
//
// Copyright © 2020 ISIS Rutherford Appleton Laboratory UKRI,
// NScD Oak Ridge National Laboratory, European Spallation Source,
// Institut Laue - Langevin & CSNS, Institute of High Energy Physics, CAS
// SPDX - License - Identifier: GPL - 3.0 +
#include "MantidQtWidgets/Common/FitScriptGeneratorPresenter.h"
#include "MantidQtWidgets/Common/FittingGlobals.h"
#include "MantidQtWidgets/Common/IFitScriptGeneratorModel.h"
#include "MantidQtWidgets/Common/IFitScriptGeneratorView.h"
#include "MantidAPI/AnalysisDataService.h"
#include "MantidAPI/IFunction.h"
#include "MantidAPI/MatrixWorkspace.h"
#include <algorithm>
#include <iterator>
#include <sstream>
namespace MantidQt {
namespace MantidWidgets {
FitScriptGeneratorPresenter::FitScriptGeneratorPresenter(
IFitScriptGeneratorView *view, IFitScriptGeneratorModel *model,
QStringList const &workspaceNames, double startX, double endX)
: m_warnings(), m_view(view), m_model(model) {
m_model->subscribePresenter(this);
m_view->subscribePresenter(this);
setWorkspaces(workspaceNames, startX, endX);
}
FitScriptGeneratorPresenter::~FitScriptGeneratorPresenter() {}
void FitScriptGeneratorPresenter::notifyPresenter(ViewEvent const &event,
std::string const &arg1,
std::string const &arg2) {
if (arg1.empty())
UNUSED_ARG(arg1);
if (arg2.empty())
UNUSED_ARG(arg2);
handleRemoveClicked();
return;
case ViewEvent::AddClicked:
handleAddWorkspaceClicked();
case ViewEvent::StartXChanged:
case ViewEvent::EndXChanged:
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
case ViewEvent::SelectionChanged:
handleSelectionChanged();
return;
case ViewEvent::FunctionRemoved:
handleFunctionRemoved(arg1);
return;
case ViewEvent::FunctionAdded:
handleFunctionAdded(arg1);
return;
case ViewEvent::FunctionReplaced:
handleFunctionReplaced(arg1);
return;
case ViewEvent::ParameterChanged:
handleParameterChanged(arg1);
return;
case ViewEvent::AttributeChanged:
handleAttributeChanged(arg1);
return;
case ViewEvent::ParameterTieChanged:
handleParameterTieChanged(arg1, arg2);
return;
case ViewEvent::ParameterConstraintRemoved:
handleParameterConstraintRemoved(arg1);
return;
case ViewEvent::ParameterConstraintChanged:
handleParameterConstraintChanged(arg1, arg2);
return;
default:
throw std::runtime_error(
"Failed to notify the FitScriptGeneratorPresenter.");
}
}
void FitScriptGeneratorPresenter::notifyPresenter(
ViewEvent const &event, std::vector<std::string> const &vec) {
switch (event) {
case ViewEvent::GlobalParametersChanged:
handleGlobalParametersChanged(vec);
return;
default:
throw std::runtime_error(
"Failed to notify the FitScriptGeneratorPresenter.");
void FitScriptGeneratorPresenter::notifyPresenter(ViewEvent const &event,
FittingMode fittingMode) {
switch (event) {
case ViewEvent::FittingModeChanged:
handleFittingModeChanged(fittingMode);
return;
default:
throw std::runtime_error(
"Failed to notify the FitScriptGeneratorPresenter.");
}
void FitScriptGeneratorPresenter::openFitScriptGenerator() { m_view->show(); }
void FitScriptGeneratorPresenter::handleRemoveClicked() {
for (auto const &index : m_view->selectedRows()) {
auto const workspaceName = m_view->workspaceName(index);
auto const workspaceIndex = m_view->workspaceIndex(index);
m_view->removeWorkspaceDomain(workspaceName, workspaceIndex);
m_model->removeWorkspaceDomain(workspaceName, workspaceIndex);
}
handleSelectionChanged();
}
void FitScriptGeneratorPresenter::handleAddWorkspaceClicked() {
if (m_view->openAddWorkspaceDialog()) {
auto const workspaces = m_view->getDialogWorkspaces();
auto const workspaceIndices = m_view->getDialogWorkspaceIndices();
if (!workspaces.empty() && !workspaceIndices.empty())
addWorkspaces(workspaces, workspaceIndices);
void FitScriptGeneratorPresenter::handleStartXChanged() {
auto const selectedRows = m_view->selectedRows();
if (!selectedRows.empty()) {
auto const workspaceName = m_view->workspaceName(selectedRows[0]);
auto const workspaceIndex = m_view->workspaceIndex(selectedRows[0]);
auto const startX = m_view->startX(selectedRows[0]);
updateStartX(workspaceName, workspaceIndex, startX);
}
}
void FitScriptGeneratorPresenter::handleEndXChanged() {
auto const selectedRows = m_view->selectedRows();
if (!selectedRows.empty()) {
auto const workspaceName = m_view->workspaceName(selectedRows[0]);
auto const workspaceIndex = m_view->workspaceIndex(selectedRows[0]);
auto const endX = m_view->endX(selectedRows[0]);
updateEndX(workspaceName, workspaceIndex, endX);
void FitScriptGeneratorPresenter::handleSelectionChanged() {
auto const fittingMode = m_model->getFittingMode();
m_view->setSimultaneousMode(fittingMode == FittingMode::SIMULTANEOUS);
auto const selectedRows = m_view->selectedRows();
if (!selectedRows.empty()) {
auto const workspaceName = m_view->workspaceName(selectedRows[0]);
auto const workspaceIndex = m_view->workspaceIndex(selectedRows[0]);
m_view->setFunction(m_model->getFunction(workspaceName, workspaceIndex));
setGlobalParameters(m_model->getGlobalParameters());
} else {
m_view->clearFunction();
}
}
void FitScriptGeneratorPresenter::handleFunctionRemoved(
std::string const &function) {
if (m_view->hasLoadedData()) {
updateDomainFunctions<&IFitScriptGeneratorModel::removeFunction>(function);
handleSelectionChanged();
}
}
void FitScriptGeneratorPresenter::handleFunctionAdded(
std::string const &function) {
if (m_view->hasLoadedData()) {
try {
updateDomainFunctions<&IFitScriptGeneratorModel::addFunction>(function);
} catch (std::invalid_argument const &ex) {
m_view->displayWarning(ex.what());
}
} else {
m_view->displayWarning("Data needs to be loaded before adding a function.");
m_view->clearFunction();
}
}
void FitScriptGeneratorPresenter::handleFunctionReplaced(
std::string const &function) {
if (m_view->hasLoadedData()) {
updateDomainFunctions<&IFitScriptGeneratorModel::setFunction>(function);
} else {
m_view->displayWarning("Data needs to be loaded before adding a function.");
m_view->clearFunction();
}
}
void FitScriptGeneratorPresenter::handleParameterChanged(
std::string const ¶meter) {
auto const newValue = m_view->parameterValue(parameter);
for (auto const &rowIndex : getRowIndices()) {
auto const workspaceName = m_view->workspaceName(rowIndex);
auto const workspaceIndex = m_view->workspaceIndex(rowIndex);
auto const equivalentParameter =
m_model->getEquivalentFunctionIndexForDomain(workspaceName,
workspaceIndex, parameter);
m_model->updateParameterValue(workspaceName, workspaceIndex,
equivalentParameter, newValue);
}
handleSelectionChanged();
}
void FitScriptGeneratorPresenter::handleAttributeChanged(
std::string const &attribute) {
auto const newValue = m_view->attributeValue(attribute);
for (auto const &rowIndex : getRowIndices()) {
auto const workspaceName = m_view->workspaceName(rowIndex);
auto const workspaceIndex = m_view->workspaceIndex(rowIndex);
m_model->updateAttributeValue(workspaceName, workspaceIndex, attribute,
newValue);
}
}
void FitScriptGeneratorPresenter::handleParameterTieChanged(
std::string const ¶meter, std::string const &tie) {
for (auto const &rowIndex : getRowIndices()) {
auto const workspaceName = m_view->workspaceName(rowIndex);
auto const workspaceIndex = m_view->workspaceIndex(rowIndex);
updateParameterTie(workspaceName, workspaceIndex, parameter, tie);
}
checkForWarningMessages();
setGlobalTies(m_model->getGlobalTies());
handleSelectionChanged();
}
void FitScriptGeneratorPresenter::handleParameterConstraintRemoved(
std::string const ¶meter) {
for (auto const &rowIndex : getRowIndices()) {
auto const workspaceName = m_view->workspaceName(rowIndex);
auto const workspaceIndex = m_view->workspaceIndex(rowIndex);
m_model->removeParameterConstraint(workspaceName, workspaceIndex,
parameter);
}
handleSelectionChanged();
}
void FitScriptGeneratorPresenter::handleParameterConstraintChanged(
std::string const &functionIndex, std::string const &constraint) {
for (auto const &rowIndex : getRowIndices()) {
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
auto const workspaceName = m_view->workspaceName(rowIndex);
auto const workspaceIndex = m_view->workspaceIndex(rowIndex);
auto const equivalentFunctionIndex =
m_model->getEquivalentFunctionIndexForDomain(
workspaceName, workspaceIndex, functionIndex);
m_model->updateParameterConstraint(workspaceName, workspaceIndex,
equivalentFunctionIndex, constraint);
}
handleSelectionChanged();
}
void FitScriptGeneratorPresenter::handleGlobalParametersChanged(
std::vector<std::string> const &globalParameters) {
try {
m_model->setGlobalParameters(globalParameters);
} catch (std::invalid_argument const &ex) {
m_view->displayWarning(ex.what());
}
handleSelectionChanged();
}
void FitScriptGeneratorPresenter::handleFittingModeChanged(
FittingMode fittingMode) {
m_model->setFittingMode(fittingMode);
handleSelectionChanged();
}
void FitScriptGeneratorPresenter::setGlobalTies(
std::vector<GlobalTie> const &globalTies) {
m_view->setGlobalTies(globalTies);
}
void FitScriptGeneratorPresenter::setGlobalParameters(
std::vector<GlobalParameter> const &globalParameters) {
m_view->setGlobalParameters(globalParameters);
}
void FitScriptGeneratorPresenter::setWorkspaces(
QStringList const &workspaceNames, double startX, double endX) {
for (auto const &workspaceName : workspaceNames)
addWorkspace(workspaceName.toStdString(), startX, endX);
checkForWarningMessages();
void FitScriptGeneratorPresenter::addWorkspaces(
std::vector<MatrixWorkspace_const_sptr> const &workspaces,
std::vector<WorkspaceIndex> const &workspaceIndices) {
for (auto const &workspace : workspaces)
for (auto const &workspaceIndex : workspaceIndices) {
auto const xData = workspace->x(workspaceIndex.value);
addWorkspace(workspace, workspaceIndex, xData.front(), xData.back());
}
checkForWarningMessages();
}
void FitScriptGeneratorPresenter::addWorkspace(std::string const &workspaceName,
double startX, double endX) {
auto &ads = AnalysisDataService::Instance();
if (ads.doesExist(workspaceName))
addWorkspace(ads.retrieveWS<MatrixWorkspace>(workspaceName), startX, endX);
}
void FitScriptGeneratorPresenter::addWorkspace(
MatrixWorkspace_const_sptr const &workspace, double startX, double endX) {
for (auto index = 0u; index < workspace->getNumberHistograms(); ++index)
addWorkspace(workspace, WorkspaceIndex{index}, startX, endX);
}
void FitScriptGeneratorPresenter::addWorkspace(
MatrixWorkspace_const_sptr const &workspace, WorkspaceIndex workspaceIndex,
double startX, double endX) {
addWorkspace(workspace->getName(), workspaceIndex, startX, endX);
}
void FitScriptGeneratorPresenter::addWorkspace(std::string const &workspaceName,
WorkspaceIndex workspaceIndex,
double startX, double endX) {
try {
m_model->addWorkspaceDomain(workspaceName, workspaceIndex, startX, endX);
m_view->addWorkspaceDomain(workspaceName, workspaceIndex, startX, endX);
} catch (std::invalid_argument const &ex) {
m_warnings.emplace_back(ex.what());
}
}
void FitScriptGeneratorPresenter::updateStartX(std::string const &workspaceName,
WorkspaceIndex workspaceIndex,
double startX) {
if (!m_model->updateStartX(workspaceName, workspaceIndex, startX)) {
m_view->displayWarning("The StartX provided must be within the x limits of "
"its workspace, and less than the EndX.");
}
}
void FitScriptGeneratorPresenter::updateEndX(std::string const &workspaceName,
WorkspaceIndex workspaceIndex,
double endX) {
if (!m_model->updateEndX(workspaceName, workspaceIndex, endX)) {
m_view->displayWarning("The EndX provided must be within the x limits of "
"its workspace, and greater than the StartX.");
template <void (IFitScriptGeneratorModel::*func)(
std::string const &workspaceName, WorkspaceIndex workspaceIndex,
std::string const &function)>
void FitScriptGeneratorPresenter::updateDomainFunctions(
std::string const &function) {
for (auto const &domainIndex : getRowIndices()) {
auto const workspaceName = m_view->workspaceName(domainIndex);
auto const workspaceIndex = m_view->workspaceIndex(domainIndex);
(m_model->*func)(workspaceName, workspaceIndex, function);
}
}
void FitScriptGeneratorPresenter::updateParameterTie(
std::string const &workspaceName, WorkspaceIndex workspaceIndex,
std::string const ¶meter, std::string const &tie) {
auto const equivalentParameter = m_model->getEquivalentFunctionIndexForDomain(
workspaceName, workspaceIndex, parameter);
auto const equivalentTie = m_model->getEquivalentParameterTieForDomain(
workspaceName, workspaceIndex, parameter, tie);
try {
m_model->updateParameterTie(workspaceName, workspaceIndex,
equivalentParameter, equivalentTie);
} catch (std::invalid_argument const &ex) {
m_warnings.emplace_back(ex.what());
}
}
std::vector<FitDomainIndex> FitScriptGeneratorPresenter::getRowIndices() const {
return m_view->applyFunctionChangesToAll() ? m_view->allRows()
: m_view->selectedRows();
}
void FitScriptGeneratorPresenter::checkForWarningMessages() {
if (!m_warnings.empty()) {
std::stringstream ss;
std::copy(m_warnings.cbegin(), m_warnings.cend(),
std::ostream_iterator<std::string>(ss, "\n"));
m_view->displayWarning(ss.str());
m_warnings.clear();
} // namespace MantidWidgets
} // namespace MantidQt