diff --git a/qt/python/mantidqt/mantidqt/_common.sip b/qt/python/mantidqt/mantidqt/_common.sip index 57fb824407ff..bbba2c2c95b0 100644 --- a/qt/python/mantidqt/mantidqt/_common.sip +++ b/qt/python/mantidqt/mantidqt/_common.sip @@ -911,10 +911,10 @@ public: void setNumberOfDatasets(int n); void setCurrentDataset(int i) throw(std::exception); int getCurrentDataset() const; - void setDatasets(const QStringList &datasetNames); - void addDatasets(const QStringList &names); + void setDatasets(const std::vector &datasetNames); + void addDatasets(const std::vector &names); void removeDatasets(QList indices); - QStringList getDatasetNames() const; + std::vector getDatasetNames() const; void setErrorsEnabled(bool enabled); void hideGlobalCheckbox(); void showGlobalCheckbox(); diff --git a/qt/scientific_interfaces/Inelastic/Common/InterfaceUtils.cpp b/qt/scientific_interfaces/Inelastic/Common/InterfaceUtils.cpp index 7c9406e2215f..ab4e82b90777 100644 --- a/qt/scientific_interfaces/Inelastic/Common/InterfaceUtils.cpp +++ b/qt/scientific_interfaces/Inelastic/Common/InterfaceUtils.cpp @@ -5,6 +5,7 @@ // Institut Laue - Langevin & CSNS, Institute of High Energy Physics, CAS // SPDX - License - Identifier: GPL - 3.0 + #include "Common/InterfaceUtils.h" +#include "Common/SettingsHelper.h" #include "MantidKernel/Logger.h" #include "MantidQtWidgets/Common/ParseKeyValueString.h" #include @@ -67,6 +68,11 @@ static std::string getInterfaceAttribute(QDomElement const &root, std::string co return ""; } +/// The function to use to check whether input data should be restricted based on its name. +/// This is defined, rather than calling SettingsHelper::restrictInputDataByName() directly, to make it +/// possible to override it in tests in order to mock out the SettingsHelper. +std::function restrictInputDataByName = SettingsHelper::restrictInputDataByName; + std::string getInterfaceProperty(std::string const &interfaceName, std::string const &propertyName, std::string const &attribute) { QFile file(":/interface-properties.xml"); @@ -87,52 +93,58 @@ QStringList getCalibrationExtensions(std::string const &interfaceName) { return toQStringList(getInterfaceProperty(interfaceName, "EXTENSIONS", "calibration"), ","); } -QStringList getSampleFBSuffixes(std::string const &interfaceName) { - return toQStringList(getInterfaceProperty(interfaceName, "FILE-SUFFIXES", "sample"), ","); +QStringList getFBSuffixes(std::string const &interfaceName, std::string const &fileType) { + if (!restrictInputDataByName()) { + return getExtensions(interfaceName); + } + return toQStringList(getInterfaceProperty(interfaceName, "FILE-SUFFIXES", fileType), ","); } -QStringList getSampleWSSuffixes(std::string const &interfaceName) { - return toQStringList(getInterfaceProperty(interfaceName, "WORKSPACE-SUFFIXES", "sample"), ","); +QStringList getWSSuffixes(std::string const &interfaceName, std::string const &fileType) { + if (!restrictInputDataByName()) { + return QStringList{""}; + } + return toQStringList(getInterfaceProperty(interfaceName, "WORKSPACE-SUFFIXES", fileType), ","); } -QStringList getVanadiumFBSuffixes(std::string const &interfaceName) { - return toQStringList(getInterfaceProperty(interfaceName, "FILE-SUFFIXES", "vanadium"), ","); -} +QStringList getSampleFBSuffixes(std::string const &interfaceName) { return getFBSuffixes(interfaceName, "sample"); } -QStringList getVanadiumWSSuffixes(std::string const &interfaceName) { - return toQStringList(getInterfaceProperty(interfaceName, "WORKSPACE-SUFFIXES", "vanadium"), ","); -} +QStringList getSampleWSSuffixes(std::string const &interfaceName) { return getWSSuffixes(interfaceName, "sample"); } + +QStringList getVanadiumFBSuffixes(std::string const &interfaceName) { return getFBSuffixes(interfaceName, "vanadium"); } + +QStringList getVanadiumWSSuffixes(std::string const &interfaceName) { return getWSSuffixes(interfaceName, "vanadium"); } QStringList getResolutionFBSuffixes(std::string const &interfaceName) { - return toQStringList(getInterfaceProperty(interfaceName, "FILE-SUFFIXES", "resolution"), ","); + return getFBSuffixes(interfaceName, "resolution"); } QStringList getResolutionWSSuffixes(std::string const &interfaceName) { - return toQStringList(getInterfaceProperty(interfaceName, "WORKSPACE-SUFFIXES", "resolution"), ","); + return getWSSuffixes(interfaceName, "resolution"); } QStringList getCalibrationFBSuffixes(std::string const &interfaceName) { - return toQStringList(getInterfaceProperty(interfaceName, "FILE-SUFFIXES", "calibration"), ","); + return getFBSuffixes(interfaceName, "calibration"); } QStringList getCalibrationWSSuffixes(std::string const &interfaceName) { - return toQStringList(getInterfaceProperty(interfaceName, "WORKSPACE-SUFFIXES", "calibration"), ","); + return getWSSuffixes(interfaceName, "calibration"); } QStringList getContainerFBSuffixes(std::string const &interfaceName) { - return toQStringList(getInterfaceProperty(interfaceName, "FILE-SUFFIXES", "container"), ","); + return getFBSuffixes(interfaceName, "container"); } QStringList getContainerWSSuffixes(std::string const &interfaceName) { - return toQStringList(getInterfaceProperty(interfaceName, "WORKSPACE-SUFFIXES", "container"), ","); + return getWSSuffixes(interfaceName, "container"); } QStringList getCorrectionsFBSuffixes(std::string const &interfaceName) { - return toQStringList(getInterfaceProperty(interfaceName, "FILE-SUFFIXES", "corrections"), ","); + return getFBSuffixes(interfaceName, "corrections"); } QStringList getCorrectionsWSSuffixes(std::string const &interfaceName) { - return toQStringList(getInterfaceProperty(interfaceName, "WORKSPACE-SUFFIXES", "corrections"), ","); + return getWSSuffixes(interfaceName, "corrections"); } QPair convertTupleToQPair(std::tuple const &doubleTuple) { diff --git a/qt/scientific_interfaces/Inelastic/Common/InterfaceUtils.h b/qt/scientific_interfaces/Inelastic/Common/InterfaceUtils.h index af647d54ca23..306e4b38c75d 100644 --- a/qt/scientific_interfaces/Inelastic/Common/InterfaceUtils.h +++ b/qt/scientific_interfaces/Inelastic/Common/InterfaceUtils.h @@ -14,6 +14,11 @@ namespace MantidQt { namespace CustomInterfaces { namespace InterfaceUtils { +/// The function to use to check whether input data should be restricted based on its name. +/// This is defined, rather than calling SettingsHelper::restrictInputDataByName() directly, to make it +/// possible to override it in tests in order to mock out the SettingsHelper. +MANTIDQT_INELASTIC_DLL extern std::function restrictInputDataByName; + MANTIDQT_INELASTIC_DLL std::string getInterfaceProperty(std::string const &interfaceName, std::string const &propertyName, std::string const &attribute); diff --git a/qt/scientific_interfaces/Inelastic/QENSFitting/ConvFitDataView.cpp b/qt/scientific_interfaces/Inelastic/QENSFitting/ConvFitDataView.cpp index 9ad77b8c164a..a395e24bed6f 100644 --- a/qt/scientific_interfaces/Inelastic/QENSFitting/ConvFitDataView.cpp +++ b/qt/scientific_interfaces/Inelastic/QENSFitting/ConvFitDataView.cpp @@ -5,7 +5,9 @@ // Institut Laue - Langevin & CSNS, Institute of High Energy Physics, CAS // SPDX - License - Identifier: GPL - 3.0 + #include "ConvFitDataView.h" +#include "Common/InterfaceUtils.h" #include "ConvFitAddWorkspaceDialog.h" +#include "FitDataPresenter.h" #include #include @@ -38,11 +40,12 @@ void ConvFitDataView::showAddWorkspaceDialog() { connect(dialog, SIGNAL(addData(MantidWidgets::IAddWorkspaceDialog *)), this, SLOT(notifyAddData(MantidWidgets::IAddWorkspaceDialog *))); + auto tabName = m_presenter->tabName(); dialog->setAttribute(Qt::WA_DeleteOnClose); - dialog->setWSSuffices(m_wsSampleSuffixes); - dialog->setFBSuffices(m_fbSampleSuffixes); - dialog->setResolutionWSSuffices(m_wsResolutionSuffixes); - dialog->setResolutionFBSuffices(m_fbResolutionSuffixes); + dialog->setWSSuffices(InterfaceUtils::getSampleWSSuffixes(tabName)); + dialog->setFBSuffices(InterfaceUtils::getSampleFBSuffixes(tabName)); + dialog->setResolutionWSSuffices(InterfaceUtils::getResolutionWSSuffixes(tabName)); + dialog->setResolutionFBSuffices(InterfaceUtils::getResolutionFBSuffixes(tabName)); dialog->updateSelectedSpectra(); dialog->show(); } diff --git a/qt/scientific_interfaces/Inelastic/QENSFitting/ConvFitDataView.h b/qt/scientific_interfaces/Inelastic/QENSFitting/ConvFitDataView.h index 98788721e201..a57dc98483c9 100644 --- a/qt/scientific_interfaces/Inelastic/QENSFitting/ConvFitDataView.h +++ b/qt/scientific_interfaces/Inelastic/QENSFitting/ConvFitDataView.h @@ -22,11 +22,11 @@ Presenter for a table of convolution fitting data. class MANTIDQT_INELASTIC_DLL ConvFitDataView : public FitDataView { Q_OBJECT public: - ConvFitDataView(QWidget *parent = nullptr); + ConvFitDataView(QWidget *parent); void addTableEntry(size_t row, FitDataRow newRow) override; protected: - ConvFitDataView(const QStringList &headers, QWidget *parent = nullptr); + ConvFitDataView(const QStringList &headers, QWidget *parent); protected slots: void showAddWorkspaceDialog() override; diff --git a/qt/scientific_interfaces/Inelastic/QENSFitting/FitDataModel.cpp b/qt/scientific_interfaces/Inelastic/QENSFitting/FitDataModel.cpp index 953d4c05fe09..cff40b236884 100644 --- a/qt/scientific_interfaces/Inelastic/QENSFitting/FitDataModel.cpp +++ b/qt/scientific_interfaces/Inelastic/QENSFitting/FitDataModel.cpp @@ -61,6 +61,11 @@ FunctionModelSpectra FitDataModel::getSpectra(WorkspaceID workspaceID) const { return FunctionModelSpectra(""); } +FunctionModelDataset FitDataModel::getDataset(WorkspaceID workspaceID) const { + auto const name = getWorkspace(workspaceID)->getName(); + return FunctionModelDataset(name, getSpectra(workspaceID)); +} + std::string FitDataModel::createDisplayName(WorkspaceID workspaceID) const { if (getNumberOfWorkspaces() > workspaceID) return getFitDataName(getWorkspaceNames()[workspaceID.value], getSpectra(workspaceID)); diff --git a/qt/scientific_interfaces/Inelastic/QENSFitting/FitDataModel.h b/qt/scientific_interfaces/Inelastic/QENSFitting/FitDataModel.h index 4c715a392dff..fd8a92e664b7 100644 --- a/qt/scientific_interfaces/Inelastic/QENSFitting/FitDataModel.h +++ b/qt/scientific_interfaces/Inelastic/QENSFitting/FitDataModel.h @@ -11,6 +11,7 @@ #include "IFitDataModel.h" #include "MantidAPI/MatrixWorkspace.h" +#include "MantidQtWidgets/Common/FunctionModelDataset.h" #include "MantidQtWidgets/Common/FunctionModelSpectra.h" #include "MantidQtWidgets/Common/IndexTypes.h" @@ -43,6 +44,7 @@ class MANTIDQT_INELASTIC_DLL FitDataModel : public IFitDataModel { void setSpectra(FunctionModelSpectra &&spectra, WorkspaceID workspaceID) override; void setSpectra(const FunctionModelSpectra &spectra, WorkspaceID workspaceID) override; FunctionModelSpectra getSpectra(WorkspaceID workspaceID) const override; + FunctionModelDataset getDataset(WorkspaceID workspaceID) const override; size_t getSpectrum(FitDomainIndex index) const override; size_t getNumberOfSpectra(WorkspaceID workspaceID) const override; diff --git a/qt/scientific_interfaces/Inelastic/QENSFitting/FitDataPresenter.cpp b/qt/scientific_interfaces/Inelastic/QENSFitting/FitDataPresenter.cpp index f684632649a1..7bd5655e1683 100644 --- a/qt/scientific_interfaces/Inelastic/QENSFitting/FitDataPresenter.cpp +++ b/qt/scientific_interfaces/Inelastic/QENSFitting/FitDataPresenter.cpp @@ -26,6 +26,8 @@ std::vector *FitDataPresenter::getFittingData() { return m_model->getFi IFitDataView const *FitDataPresenter::getView() const { return m_view; } +std::string FitDataPresenter::tabName() const { return m_tab->tabName(); } + bool FitDataPresenter::addWorkspaceFromDialog(MantidWidgets::IAddWorkspaceDialog const *dialog) { if (const auto indirectDialog = dynamic_cast(dialog)) { addWorkspace(indirectDialog->workspaceName(), indirectDialog->workspaceIndices()); @@ -45,18 +47,6 @@ void FitDataPresenter::setResolution(const std::string &name) { } } -void FitDataPresenter::setSampleWSSuffices(const QStringList &suffixes) { m_view->setSampleWSSuffices(suffixes); } - -void FitDataPresenter::setSampleFBSuffices(const QStringList &suffixes) { m_view->setSampleFBSuffices(suffixes); } - -void FitDataPresenter::setResolutionWSSuffices(const QStringList &suffixes) { - m_view->setResolutionWSSuffices(suffixes); -} - -void FitDataPresenter::setResolutionFBSuffices(const QStringList &suffixes) { - m_view->setResolutionFBSuffices(suffixes); -} - void FitDataPresenter::setStartX(double startX, WorkspaceID workspaceID) { if (m_model->getNumberOfWorkspaces() > workspaceID) { m_model->setStartX(startX, workspaceID); @@ -85,7 +75,7 @@ std::vector> FitDataPresenter::getResolutionsForF return m_model->getResolutionsForFit(); } -UserInputValidator &FitDataPresenter::validate(UserInputValidator &validator) { return m_view->validate(validator); } +void FitDataPresenter::validate(UserInputValidator &validator) { m_view->validate(validator); } void FitDataPresenter::handleAddData(MantidWidgets::IAddWorkspaceDialog const *dialog) { try { @@ -110,8 +100,14 @@ WorkspaceID FitDataPresenter::getNumberOfWorkspaces() const { return m_model->ge size_t FitDataPresenter::getNumberOfDomains() const { return m_model->getNumberOfDomains(); } -FunctionModelSpectra FitDataPresenter::getSpectra(WorkspaceID workspaceID) const { - return m_model->getSpectra(workspaceID); +QList FitDataPresenter::getDatasets() const { + QList datasets; + + for (auto i = 0u; i < m_model->getNumberOfWorkspaces().value; ++i) { + WorkspaceID workspaceID{i}; + datasets.append(m_model->getDataset(workspaceID)); + } + return datasets; } DataForParameterEstimationCollection diff --git a/qt/scientific_interfaces/Inelastic/QENSFitting/FitDataPresenter.h b/qt/scientific_interfaces/Inelastic/QENSFitting/FitDataPresenter.h index 03b1fc41f817..d91e20bc218f 100644 --- a/qt/scientific_interfaces/Inelastic/QENSFitting/FitDataPresenter.h +++ b/qt/scientific_interfaces/Inelastic/QENSFitting/FitDataPresenter.h @@ -24,6 +24,8 @@ class IFitTab; class MANTIDQT_INELASTIC_DLL IFitDataPresenter { public: + virtual std::string tabName() const = 0; + virtual void handleAddData(MantidWidgets::IAddWorkspaceDialog const *dialog) = 0; virtual void handleRemoveClicked() = 0; virtual void handleUnifyClicked() = 0; @@ -38,10 +40,6 @@ class MANTIDQT_INELASTIC_DLL FitDataPresenter : public IFitDataPresenter, public virtual bool addWorkspaceFromDialog(MantidWidgets::IAddWorkspaceDialog const *dialog); void addWorkspace(const std::string &workspaceName, const FunctionModelSpectra &workspaceIndices); void setResolution(const std::string &name); - void setSampleWSSuffices(const QStringList &suffices); - void setSampleFBSuffices(const QStringList &suffices); - void setResolutionWSSuffices(const QStringList &suffices); - void setResolutionFBSuffices(const QStringList &suffices); void setStartX(double startX, WorkspaceID workspaceID); void setStartX(double startX, WorkspaceID workspaceID, WorkspaceIndex spectrum); void setEndX(double startX, WorkspaceID workspaceID); @@ -52,11 +50,11 @@ class MANTIDQT_INELASTIC_DLL FitDataPresenter : public IFitDataPresenter, public void updateTableFromModel(); WorkspaceID getNumberOfWorkspaces() const; size_t getNumberOfDomains() const; - FunctionModelSpectra getSpectra(WorkspaceID workspaceID) const; + QList getDatasets() const; DataForParameterEstimationCollection getDataForParameterEstimation(const EstimationDataSelector &selector) const; std::vector getQValuesForData() const; std::vector createDisplayNames() const; - UserInputValidator &validate(UserInputValidator &validator); + void validate(UserInputValidator &validator); virtual void addWorkspace(const std::string &workspaceName, const std::string ¶mType, const int &spectrum_index) { UNUSED_ARG(workspaceName); @@ -77,6 +75,8 @@ class MANTIDQT_INELASTIC_DLL FitDataPresenter : public IFitDataPresenter, public virtual void subscribeFitPropertyBrowser(IInelasticFitPropertyBrowser *browser) { UNUSED_ARG(browser); }; + std::string tabName() const override; + void handleAddData(MantidWidgets::IAddWorkspaceDialog const *dialog) override; void handleRemoveClicked() override; void handleUnifyClicked() override; diff --git a/qt/scientific_interfaces/Inelastic/QENSFitting/FitDataView.cpp b/qt/scientific_interfaces/Inelastic/QENSFitting/FitDataView.cpp index b4ae8bda980c..564f7a0ba0cc 100644 --- a/qt/scientific_interfaces/Inelastic/QENSFitting/FitDataView.cpp +++ b/qt/scientific_interfaces/Inelastic/QENSFitting/FitDataView.cpp @@ -68,10 +68,9 @@ void FitDataView::setHorizontalHeaders(const QStringList &headers) { m_uiForm->tbFitData->verticalHeader()->setVisible(false); } -UserInputValidator &FitDataView::validate(UserInputValidator &validator) { +void FitDataView::validate(UserInputValidator &validator) { if (m_uiForm->tbFitData->rowCount() == 0) validator.addErrorMessage("No input data has been provided."); - return validator; } void FitDataView::displayWarning(const std::string &warning) { @@ -131,22 +130,15 @@ QModelIndexList FitDataView::getSelectedIndexes() const { return m_uiForm->tbFitData->selectionModel()->selectedIndexes(); } -void FitDataView::setSampleWSSuffices(const QStringList &suffixes) { m_wsSampleSuffixes = suffixes; } - -void FitDataView::setSampleFBSuffices(const QStringList &suffixes) { m_fbSampleSuffixes = suffixes; } - -void FitDataView::setResolutionWSSuffices(const QStringList &suffixes) { m_wsResolutionSuffixes = suffixes; } - -void FitDataView::setResolutionFBSuffices(const QStringList &suffixes) { m_fbResolutionSuffixes = suffixes; } - void FitDataView::showAddWorkspaceDialog() { auto dialog = new MantidWidgets::AddWorkspaceDialog(parentWidget()); connect(dialog, SIGNAL(addData(MantidWidgets::IAddWorkspaceDialog *)), this, SLOT(notifyAddData(MantidWidgets::IAddWorkspaceDialog *))); + auto tabName = m_presenter->tabName(); dialog->setAttribute(Qt::WA_DeleteOnClose); - dialog->setWSSuffices(m_wsSampleSuffixes); - dialog->setFBSuffices(m_fbSampleSuffixes); + dialog->setWSSuffices(InterfaceUtils::getSampleWSSuffixes(tabName)); + dialog->setFBSuffices(InterfaceUtils::getSampleFBSuffixes(tabName)); dialog->updateSelectedSpectra(); dialog->show(); } diff --git a/qt/scientific_interfaces/Inelastic/QENSFitting/FitDataView.h b/qt/scientific_interfaces/Inelastic/QENSFitting/FitDataView.h index c098960abc55..cb4030fc0b93 100644 --- a/qt/scientific_interfaces/Inelastic/QENSFitting/FitDataView.h +++ b/qt/scientific_interfaces/Inelastic/QENSFitting/FitDataView.h @@ -36,7 +36,7 @@ class MANTIDQT_INELASTIC_DLL FitDataView : public QTabWidget, public IFitDataVie QTableWidget *getDataTable() const override; bool isTableEmpty() const override; - UserInputValidator &validate(UserInputValidator &validator) override; + void validate(UserInputValidator &validator) override; virtual void addTableEntry(size_t row, FitDataRow newRow) override; virtual void updateNumCellEntry(double numEntry, size_t row, size_t column) override; int getColumnIndexFromName(std::string const &ColName) override; @@ -45,11 +45,6 @@ class MANTIDQT_INELASTIC_DLL FitDataView : public QTabWidget, public IFitDataVie QModelIndexList getSelectedIndexes() const override; bool dataColumnContainsText(std::string const &columnText) const override; - void setSampleWSSuffices(const QStringList &suffices) override; - void setSampleFBSuffices(const QStringList &suffices) override; - void setResolutionWSSuffices(const QStringList &suffices) override; - void setResolutionFBSuffices(const QStringList &suffices) override; - void displayWarning(const std::string &warning) override; protected slots: @@ -61,11 +56,6 @@ protected slots: std::unique_ptr m_uiForm; void setCell(std::unique_ptr cell, size_t row, size_t column); - QStringList m_wsSampleSuffixes; - QStringList m_fbSampleSuffixes; - QStringList m_wsResolutionSuffixes; - QStringList m_fbResolutionSuffixes; - IFitDataPresenter *m_presenter; protected slots: diff --git a/qt/scientific_interfaces/Inelastic/QENSFitting/FitTab.cpp b/qt/scientific_interfaces/Inelastic/QENSFitting/FitTab.cpp index caa1d8ce6ce4..38031313495a 100644 --- a/qt/scientific_interfaces/Inelastic/QENSFitting/FitTab.cpp +++ b/qt/scientific_interfaces/Inelastic/QENSFitting/FitTab.cpp @@ -7,75 +7,31 @@ #include "FitTab.h" #include "Common/InterfaceUtils.h" #include "Common/SettingsHelper.h" -#include "MantidQtWidgets/Common/WorkspaceUtils.h" - #include "FitPlotView.h" -#include "FitTabConstants.h" -#include "MantidAPI/FunctionFactory.h" #include "MantidAPI/MultiDomainFunction.h" -#include "MantidAPI/TextAxis.h" -#include "MantidAPI/WorkspaceFactory.h" - -#include "MantidQtWidgets/Common/FittingMode.h" -#include "MantidQtWidgets/Common/PropertyHandler.h" +#include "MantidQtWidgets/Common/WorkspaceUtils.h" -#include #include -#include - -#include -#include using namespace Mantid::API; -using namespace MantidQt::MantidWidgets; - -namespace { -/// Logger -Mantid::Kernel::Logger g_log("QENS Fitting"); -} // namespace namespace MantidQt { namespace CustomInterfaces { namespace Inelastic { -/** - * @param functionName The name of the function. - * @param compositeFunction The function to search within. - * @return The number of custom functions, with the specified name, - * included in the selected model. - */ -size_t FitTab::getNumberOfSpecificFunctionContained(const std::string &functionName, - const IFunction *compositeFunction) { - // Whilst this could be a free method it would require its own - // dll_export in the header, so it's easier to make it static - assert(compositeFunction); - - if (compositeFunction->nFunctions() == 0) { - return compositeFunction->name() == functionName ? 1 : 0; - } else { - size_t count{0}; - for (size_t i{0}; i < compositeFunction->nFunctions(); i++) { - count += getNumberOfSpecificFunctionContained(functionName, compositeFunction->getFunction(i).get()); - } - return count; - } -} - -FitTab::FitTab(std::string const &tabName, bool const hasResolution, QWidget *parent) - : IndirectTab(parent), m_uiForm(new Ui::FitTab), m_tabName(tabName), m_hasResolution(hasResolution) { +FitTab::FitTab(QWidget *parent, std::string const &tabName) + : IndirectTab(parent), m_uiForm(new Ui::FitTab), m_dataPresenter(), m_fittingModel(), m_plotPresenter(), + m_outOptionsPresenter(), m_fitPropertyBrowser(), m_fittingAlgorithm() { m_uiForm->setupUi(parent); + parent->setWindowTitle(QString::fromStdString(tabName)); } void FitTab::setup() { connect(m_uiForm->pbRun, SIGNAL(clicked()), this, SLOT(runTab())); updateResultOptions(); - connectFitPropertyBrowser(); -} - -void FitTab::connectFitPropertyBrowser() { - connect(m_fitPropertyBrowser, SIGNAL(functionChanged()), this, SLOT(respondToFunctionChanged())); + connect(m_fitPropertyBrowser, SIGNAL(functionChanged()), this, SLOT(handleFunctionChanged())); } void FitTab::subscribeFitBrowserToDataPresenter() { @@ -100,89 +56,21 @@ void FitTab::setupPlotView(std::optional> const &xPlot m_plotPresenter->updatePlots(); } -void FitTab::setRunIsRunning(bool running) { m_uiForm->pbRun->setText(running ? "Running..." : "Run"); } - -void FitTab::setRunEnabled(bool enable) { m_uiForm->pbRun->setEnabled(enable); } - -void FitTab::setFileExtensionsByName(bool filter) { - auto const tab = getTabName(); - setSampleSuffixes(tab, filter); - if (hasResolution()) - setResolutionSuffixes(tab, filter); -} - -void FitTab::setSampleSuffixes(std::string const &tab, bool filter) { - QStringList const noSuffixes{""}; - setSampleWSSuffixes(filter ? InterfaceUtils::getSampleWSSuffixes(tab) : noSuffixes); - setSampleFBSuffixes(filter ? InterfaceUtils::getSampleFBSuffixes(tab) : InterfaceUtils::getExtensions(tab)); -} - -void FitTab::setResolutionSuffixes(std::string const &tab, bool filter) { - QStringList const noSuffixes{""}; - setResolutionWSSuffixes(filter ? InterfaceUtils::getResolutionWSSuffixes(tab) : noSuffixes); - setResolutionFBSuffixes(filter ? InterfaceUtils::getResolutionFBSuffixes(tab) : InterfaceUtils::getExtensions(tab)); -} - -void FitTab::setSampleWSSuffixes(const QStringList &suffices) { m_dataPresenter->setSampleWSSuffices(suffices); } - -void FitTab::setSampleFBSuffixes(const QStringList &suffices) { m_dataPresenter->setSampleFBSuffices(suffices); } - -void FitTab::setResolutionWSSuffixes(const QStringList &suffices) { - m_dataPresenter->setResolutionWSSuffices(suffices); -} - -void FitTab::setResolutionFBSuffixes(const QStringList &suffices) { - m_dataPresenter->setResolutionFBSuffices(suffices); -} - -WorkspaceID FitTab::getSelectedDataIndex() const { return m_plotPresenter->getActiveWorkspaceID(); } - -WorkspaceIndex FitTab::getSelectedSpectrum() const { return m_plotPresenter->getActiveWorkspaceIndex(); } - -bool FitTab::isRangeCurrentlySelected(WorkspaceID workspaceID, WorkspaceIndex spectrum) const { - return m_plotPresenter->isCurrentlySelected(workspaceID, spectrum); -} - -FittingModel *FitTab::getFittingModel() const { return m_fittingModel.get(); } - -/** - * @param functionName The name of the function. - * @return The number of custom functions, with the specified name, - * included in the selected model. - */ -size_t FitTab::getNumberOfCustomFunctions(const std::string &functionName) const { - auto fittingFunction = m_fittingModel->getFitFunction(); - if (fittingFunction && fittingFunction->nFunctions() > 0) - return getNumberOfSpecificFunctionContained(functionName, fittingFunction->getFunction(0).get()); - else - return 0; -} - void FitTab::setModelFitFunction() { auto func = m_fitPropertyBrowser->getFitFunction(); m_plotPresenter->setFitFunction(func); m_fittingModel->setFitFunction(func); } -void FitTab::setModelStartX(double startX) { - const auto dataIndex = getSelectedDataIndex(); - m_dataPresenter->setStartX(startX, dataIndex, getSelectedSpectrum()); -} - -void FitTab::setModelEndX(double endX) { - const auto dataIndex = getSelectedDataIndex(); - m_dataPresenter->setStartX(endX, dataIndex, getSelectedSpectrum()); -} - void FitTab::handleTableStartXChanged(double startX, WorkspaceID workspaceID, WorkspaceIndex spectrum) { - if (isRangeCurrentlySelected(workspaceID, spectrum)) { + if (m_plotPresenter->isCurrentlySelected(workspaceID, spectrum)) { m_plotPresenter->setStartX(startX); m_plotPresenter->updateGuess(); } } void FitTab::handleTableEndXChanged(double endX, WorkspaceID workspaceID, WorkspaceIndex spectrum) { - if (isRangeCurrentlySelected(workspaceID, spectrum)) { + if (m_plotPresenter->isCurrentlySelected(workspaceID, spectrum)) { m_plotPresenter->setEndX(endX); m_plotPresenter->updateGuess(); } @@ -204,18 +92,6 @@ void FitTab::handleEndXChanged(double endX) { m_dataPresenter->updateTableFromModel(); } -/** - * Sets whether fit members should be convolved with the resolution after a fit. - * - * @param convolveMembers If true, members are to be convolved. - */ -void FitTab::setConvolveMembers(bool convolveMembers) { - m_fitPropertyBrowser->setConvolveMembers(convolveMembers); - // if convolve members is on, output members should also be on - if (convolveMembers) - m_fitPropertyBrowser->setOutputCompositeMembers(true); -} - void FitTab::updateFitOutput(bool error) { disconnect(m_batchAlgoRunner, SIGNAL(batchComplete(bool)), this, SLOT(updateFitOutput(bool))); @@ -231,10 +107,12 @@ void FitTab::updateSingleFitOutput(bool error) { disconnect(m_batchAlgoRunner, SIGNAL(batchComplete(bool)), this, SLOT(updateSingleFitOutput(bool))); if (error) { - m_fittingModel->cleanFailedSingleRun(m_fittingAlgorithm, m_activeWorkspaceID); + m_fittingModel->cleanFailedSingleRun(m_fittingAlgorithm, m_plotPresenter->getActiveWorkspaceID()); m_fittingAlgorithm.reset(); - } else - m_fittingModel->addSingleFitOutput(m_fittingAlgorithm, m_activeWorkspaceID, m_activeSpectrumIndex); + } else { + m_fittingModel->addSingleFitOutput(m_fittingAlgorithm, m_plotPresenter->getActiveWorkspaceID(), + m_plotPresenter->getActiveWorkspaceIndex()); + } } /** @@ -242,7 +120,6 @@ void FitTab::updateSingleFitOutput(bool error) { * and completed within this interface. */ void FitTab::fitAlgorithmComplete(bool error) { - setRunIsRunning(false); m_plotPresenter->setFitSingleSpectrumIsFitting(false); enableFitButtons(true); enableOutputOptions(!error); @@ -256,30 +133,8 @@ void FitTab::fitAlgorithmComplete(bool error) { disconnect(m_batchAlgoRunner, SIGNAL(batchComplete(bool)), this, SLOT(fitAlgorithmComplete(bool))); } -/** - * Updates the parameter values and errors in the fit property browser. - */ -void FitTab::updateParameterValues() { - updateParameterValues(m_fittingModel->getParameterValues(getSelectedDataIndex(), getSelectedSpectrum())); -} - -/** - * Updates the parameter values and errors in the fit property browser. - * - * @param parameters The parameter values to update the browser with. - */ -void FitTab::updateParameterValues(const std::unordered_map ¶ms) { - try { - updateFitBrowserParameterValues(params); - } catch (const std::out_of_range &) { - g_log.warning("Warning issue updating parameter values in fit property browser"); - } catch (const std::invalid_argument &) { - g_log.warning("Warning issue updating parameter values in fit property browser"); - } -} - void FitTab::updateFitBrowserParameterValues(const std::unordered_map ¶ms) { - IFunction_sptr fun = m_fittingModel->getFitFunction(); + auto fun = m_fittingModel->getFitFunction(); if (fun) { for (auto const &pair : params) { fun->setParameter(pair.first, pair.second.value); @@ -293,35 +148,28 @@ void FitTab::updateFitBrowserParameterValues(const std::unordered_mapgetFittingMode() == FittingMode::SEQUENTIAL) { - auto const paramWsName = m_fittingAlgorithm->getPropertyValue("OutputParameterWorkspace"); - auto paramWs = AnalysisDataService::Instance().retrieveWS(paramWsName); - auto rowCount = static_cast(paramWs->rowCount()); - if (rowCount == static_cast(m_dataPresenter->getNumberOfDomains())) - m_fitPropertyBrowser->updateMultiDatasetParameters(*paramWs); - } else { - IFunction_sptr fun = m_fittingAlgorithm->getProperty("Function"); - if (fun->getNumberDomains() > 1) - m_fitPropertyBrowser->updateMultiDatasetParameters(*fun); - else - m_fitPropertyBrowser->updateParameters(*fun); - } + updateFitBrowserParameterValues(); + if (m_fittingAlgorithm) { + QSignalBlocker blocker(m_fitPropertyBrowser); + if (m_fittingModel->getFittingMode() == FittingMode::SEQUENTIAL) { + auto const paramWsName = m_fittingAlgorithm->getPropertyValue("OutputParameterWorkspace"); + auto paramWs = AnalysisDataService::Instance().retrieveWS(paramWsName); + auto rowCount = static_cast(paramWs->rowCount()); + if (rowCount == static_cast(m_dataPresenter->getNumberOfDomains())) + m_fitPropertyBrowser->updateMultiDatasetParameters(*paramWs); + } else { + IFunction_sptr fun = m_fittingAlgorithm->getProperty("Function"); + if (fun->getNumberDomains() > 1) + m_fitPropertyBrowser->updateMultiDatasetParameters(*fun); + else + m_fitPropertyBrowser->updateParameters(*fun); } - } catch (const std::out_of_range &) { - g_log.warning("Warning issue updating parameter values in fit property browser"); - } catch (const std::invalid_argument &) { - g_log.warning("Warning issue updating parameter values in fit property browser"); } } /** * Updates the fit output status */ void FitTab::updateFitStatus() { - if (m_fittingModel->getFittingMode() == FittingMode::SIMULTANEOUS) { std::string fit_status = m_fittingAlgorithm->getProperty("OutputStatus"); double chi2 = m_fittingAlgorithm->getProperty("OutputChiSquared"); @@ -339,94 +187,39 @@ void FitTab::updateFitStatus() { */ void FitTab::handlePlotSelectedSpectra() { enableFitButtons(false); - plotSelectedSpectra(m_outOptionsPresenter->getSpectraToPlot()); + for (auto const &spectrum : m_outOptionsPresenter->getSpectraToPlot()) + m_plotter->plotSpectra(spectrum.first, std::to_string(spectrum.second), SettingsHelper::externalPlotErrorBars()); + m_outOptionsPresenter->clearSpectraToPlot(); enableFitButtons(true); m_outOptionsPresenter->setPlotting(false); } -/** - * Plots the spectra corresponding to the selected parameters - * @param spectra :: a vector of spectra to plot from a group workspace - */ -void FitTab::plotSelectedSpectra(std::vector const &spectra) { - for (auto const &spectrum : spectra) - plotSpectrum(spectrum.first, spectrum.second); - m_outOptionsPresenter->clearSpectraToPlot(); -} - -/** - * Plots a spectrum with the specified index in a workspace - * @workspaceName :: the workspace containing the spectrum to plot - * @index :: the index in the workspace - * @errorBars :: true if you want error bars to be plotted - */ -void FitTab::plotSpectrum(std::string const &workspaceName, std::size_t const &index) { - m_plotter->plotSpectra(workspaceName, std::to_string(index), SettingsHelper::externalPlotErrorBars()); -} - -/** - * Gets the name used for the base of the result workspaces - */ -std::string FitTab::getOutputBasename() const { return m_fittingModel->getOutputBasename(); } - -/** - * Gets the Result workspace from a fit - */ -WorkspaceGroup_sptr FitTab::getResultWorkspace() const { return m_fittingModel->getResultWorkspace(); } - -/** - * Gets the names of the Fit Parameters - */ -std::vector FitTab::getFitParameterNames() const { return m_fittingModel->getFitParameterNames(); } - -/** - * Executes the single fit algorithm defined in this indirect fit analysis tab. - */ -void FitTab::singleFit() { handleSingleFitClicked(getSelectedDataIndex(), getSelectedSpectrum()); } - void FitTab::handleSingleFitClicked(WorkspaceID workspaceID, WorkspaceIndex spectrum) { if (validate()) { - m_activeSpectrumIndex = spectrum; m_plotPresenter->setFitSingleSpectrumIsFitting(true); enableFitButtons(false); enableOutputOptions(false); m_fittingModel->setFittingMode(FittingMode::SIMULTANEOUS); - m_activeWorkspaceID = workspaceID; runSingleFit(m_fittingModel->getSingleFit(workspaceID, spectrum)); } } -/** - * Executes the sequential fit algorithm defined in this indirect fit analysis - * tab. - */ -void FitTab::executeFit() { - if (validate()) { - setRunIsRunning(true); - enableFitButtons(false); - enableOutputOptions(false); - runFitAlgorithm(m_fittingModel->getFittingAlgorithm(m_fittingModel->getFittingMode())); - } -} - bool FitTab::validate() { UserInputValidator validator; m_dataPresenter->validate(validator); + m_fittingModel->validate(validator); - const auto invalidFunction = m_fittingModel->isInvalidFunction(); - if (invalidFunction) - validator.addErrorMessage(QString::fromStdString(*invalidFunction)); - - const auto error = validator.generateErrorMessage(); - emit showMessageBox(error); - return error.isEmpty(); + const auto error = validator.generateErrorMessage().toStdString(); + if (!error.empty()) { + displayWarning(error); + } + return error.empty(); } /** * Called when the 'Run' button is called in the IndirectTab. */ void FitTab::run() { - setRunIsRunning(true); enableFitButtons(false); enableOutputOptions(false); m_fittingModel->setFittingMode(m_fitPropertyBrowser->getFittingMode()); @@ -439,7 +232,8 @@ void FitTab::run() { * @param enable :: true to enable buttons */ void FitTab::enableFitButtons(bool enable) { - setRunEnabled(enable); + m_uiForm->pbRun->setText(enable ? "Run" : "Running..."); + m_uiForm->pbRun->setEnabled(enable); m_plotPresenter->setFitSingleSpectrumEnabled(enable); m_fitPropertyBrowser->setFitEnabled(enable); } @@ -451,8 +245,8 @@ void FitTab::enableFitButtons(bool enable) { */ void FitTab::enableOutputOptions(bool enable) { if (enable) { - m_outOptionsPresenter->setResultWorkspace(getResultWorkspace()); - setPDFWorkspace(getOutputBasename() + "_PDFs"); + m_outOptionsPresenter->setResultWorkspace(m_fittingModel->getResultWorkspace()); + setPDFWorkspace(m_fittingModel->getOutputBasename() + "_PDFs"); m_outOptionsPresenter->setPlotTypes("Result Group"); } else m_outOptionsPresenter->setMultiWorkspaceOptionsVisible(enable); @@ -482,40 +276,14 @@ void FitTab::setPDFWorkspace(std::string const &workspaceName) { void FitTab::updateParameterEstimationData() { m_fitPropertyBrowser->updateParameterEstimationData( m_dataPresenter->getDataForParameterEstimation(m_fitPropertyBrowser->getEstimationDataSelector())); - const bool isFit = m_fittingModel->isPreviouslyFit(getSelectedDataIndex(), getSelectedSpectrum()); + const bool isFit = m_fittingModel->isPreviouslyFit(m_plotPresenter->getActiveWorkspaceID(), + m_plotPresenter->getActiveWorkspaceIndex()); // If we haven't fit the data yet we may update the guess if (!isFit) { m_fitPropertyBrowser->estimateFunctionParameters(); } } -/** - * Sets the visiblity of the output options Edit Result button - * @param visible :: true to make the edit result button visible - */ -void FitTab::setEditResultVisible(bool visible) { m_outOptionsPresenter->setEditResultVisible(visible); } - -void FitTab::setAlgorithmProperties(const IAlgorithm_sptr &fitAlgorithm) const { - fitAlgorithm->setProperty("Minimizer", m_fitPropertyBrowser->minimizer(true)); - fitAlgorithm->setProperty("MaxIterations", m_fitPropertyBrowser->maxIterations()); - fitAlgorithm->setProperty("PeakRadius", m_fitPropertyBrowser->getPeakRadius()); - fitAlgorithm->setProperty("CostFunction", m_fitPropertyBrowser->costFunction()); - fitAlgorithm->setProperty("IgnoreInvalidData", m_fitPropertyBrowser->ignoreInvalidData()); - fitAlgorithm->setProperty("EvaluationType", m_fitPropertyBrowser->fitEvaluationType()); - fitAlgorithm->setProperty("PeakRadius", m_fitPropertyBrowser->getPeakRadius()); - if (m_fitPropertyBrowser->convolveMembers()) { - fitAlgorithm->setProperty("ConvolveMembers", true); - fitAlgorithm->setProperty("OutputCompositeMembers", true); - } else { - fitAlgorithm->setProperty("OutputCompositeMembers", m_fitPropertyBrowser->outputCompositeMembers()); - } - - if (m_fittingModel->getFittingMode() == FittingMode::SEQUENTIAL) { - fitAlgorithm->setProperty("FitType", m_fitPropertyBrowser->fitType()); - } - fitAlgorithm->setProperty("OutputFitStatus", true); -} - /* * Runs the specified fit algorithm and calls the algorithmComplete * method of this fit analysis tab once completed. @@ -535,27 +303,15 @@ void FitTab::runSingleFit(IAlgorithm_sptr fitAlgorithm) { } void FitTab::setupFit(IAlgorithm_sptr fitAlgorithm) { - setAlgorithmProperties(fitAlgorithm); + auto properties = m_fitPropertyBrowser->fitProperties(m_fittingModel->getFittingMode()); m_fittingAlgorithm = fitAlgorithm; - m_batchAlgoRunner->addAlgorithm(fitAlgorithm); + m_batchAlgoRunner->addAlgorithm(fitAlgorithm, std::move(properties)); connect(m_batchAlgoRunner, SIGNAL(batchComplete(bool)), this, SLOT(fitAlgorithmComplete(bool))); } -QList FitTab::getDatasets() const { - QList datasets; - - for (auto i = 0u; i < m_dataPresenter->getNumberOfWorkspaces().value; ++i) { - WorkspaceID workspaceID{i}; - - auto const name = m_fittingModel->getWorkspace(workspaceID)->getName(); - datasets.append(FunctionModelDataset(QString::fromStdString(name), m_dataPresenter->getSpectra(workspaceID))); - } - return datasets; -} - void FitTab::updateDataReferences() { m_fitPropertyBrowser->updateFunctionBrowserData(static_cast(m_dataPresenter->getNumberOfDomains()), - getDatasets(), m_dataPresenter->getQValuesForData(), + m_dataPresenter->getDatasets(), m_dataPresenter->getQValuesForData(), m_dataPresenter->getResolutionsForFit()); setModelFitFunction(); } @@ -565,14 +321,17 @@ void FitTab::updateDataReferences() { * enabled/disabled. */ void FitTab::updateResultOptions() { - const bool isFit = m_fittingModel->isPreviouslyFit(getSelectedDataIndex(), getSelectedSpectrum()); + const bool isFit = m_fittingModel->isPreviouslyFit(m_plotPresenter->getActiveWorkspaceID(), + m_plotPresenter->getActiveWorkspaceIndex()); if (isFit) - m_outOptionsPresenter->setResultWorkspace(getResultWorkspace()); + m_outOptionsPresenter->setResultWorkspace(m_fittingModel->getResultWorkspace()); m_outOptionsPresenter->setPlotEnabled(isFit); m_outOptionsPresenter->setEditResultEnabled(isFit); m_outOptionsPresenter->setSaveEnabled(isFit); } +std::string FitTab::tabName() const { return m_parentWidget->windowTitle().toStdString(); } + void FitTab::handleDataChanged() { updateDataReferences(); m_fittingModel->removeFittingData(); @@ -617,33 +376,12 @@ void FitTab::handleBackgroundChanged(double value) { m_plotPresenter->updateGuess(); } -void FitTab::respondToFunctionChanged() { +void FitTab::handleFunctionChanged() { setModelFitFunction(); m_fittingModel->removeFittingData(); m_plotPresenter->updatePlots(); m_plotPresenter->updateFit(); - m_fittingModel->setFitTypeString(getFitTypeString()); -} - -std::string FitTab::getFitTypeString() const { - auto const multiDomainFunction = m_fittingModel->getFitFunction(); - if (!multiDomainFunction || multiDomainFunction->nFunctions() == 0) { - return "NoCurrentFunction"; - } - - std::string fitType{""}; - for (auto const &fitFunctionName : FUNCTION_STRINGS) { - auto occurances = getNumberOfCustomFunctions(fitFunctionName.first); - if (occurances > 0) { - fitType += std::to_string(occurances) + fitFunctionName.second; - } - } - - if (getNumberOfCustomFunctions("DeltaFunction") > 0) { - fitType += "Delta"; - } - - return fitType; + m_fittingModel->updateFitTypeString(); } } // namespace Inelastic diff --git a/qt/scientific_interfaces/Inelastic/QENSFitting/FitTab.h b/qt/scientific_interfaces/Inelastic/QENSFitting/FitTab.h index 1be9c8bd2402..cc9593bb4511 100644 --- a/qt/scientific_interfaces/Inelastic/QENSFitting/FitTab.h +++ b/qt/scientific_interfaces/Inelastic/QENSFitting/FitTab.h @@ -16,18 +16,9 @@ #include "InelasticFitPropertyBrowser.h" #include "ui_FitTab.h" -#include "MantidQtWidgets/Common/FunctionModelDataset.h" - -#include - -#include - #include #include -#include -#include -#include #include namespace MantidQt { @@ -37,6 +28,7 @@ namespace Inelastic { class MANTIDQT_INELASTIC_DLL IFitTab { public: // Used by FitDataPresenter + virtual std::string tabName() const = 0; virtual void handleDataAdded(IAddWorkspaceDialog const *dialog) = 0; virtual void handleDataChanged() = 0; virtual void handleDataRemoved() = 0; @@ -53,13 +45,16 @@ class MANTIDQT_INELASTIC_DLL IFitTab { // Used by FitOutputOptionsPresenter virtual void handlePlotSelectedSpectra() = 0; + + // Used by InelasticFitPropertyBrowser + virtual void handleFunctionChanged() = 0; }; class MANTIDQT_INELASTIC_DLL FitTab : public IndirectTab, public IFitTab { Q_OBJECT public: - FitTab(std::string const &tabName, bool const hasResolution, QWidget *parent = nullptr); + FitTab(QWidget *parent, std::string const &tabName); virtual ~FitTab() override = default; template void setupFittingModel() { m_fittingModel = std::make_unique(); } @@ -74,7 +69,9 @@ class MANTIDQT_INELASTIC_DLL FitTab : public IndirectTab, public IFitTab { m_uiForm->dockArea->m_fitPropertyBrowser->init(); m_uiForm->dockArea->m_fitPropertyBrowser->setHiddenProperties(hiddenProperties); m_fitPropertyBrowser = m_uiForm->dockArea->m_fitPropertyBrowser; - setConvolveMembers(convolveMembers); + m_fitPropertyBrowser->setConvolveMembers(convolveMembers); + if (convolveMembers) + m_fitPropertyBrowser->setOutputCompositeMembers(true); } template void setupFitDataView() { @@ -90,18 +87,7 @@ class MANTIDQT_INELASTIC_DLL FitTab : public IndirectTab, public IFitTab { void setupPlotView(std::optional> const &xPlotBounds = std::nullopt); void subscribeFitBrowserToDataPresenter(); - WorkspaceID getSelectedDataIndex() const; - WorkspaceIndex getSelectedSpectrum() const; - bool isRangeCurrentlySelected(WorkspaceID workspaceID, WorkspaceIndex spectrum) const; - size_t getNumberOfCustomFunctions(const std::string &functionName) const; - void setConvolveMembers(bool convolveMembers); - - static size_t getNumberOfSpecificFunctionContained(const std::string &functionName, - const IFunction *compositeFunction); - - std::string getTabName() const noexcept { return m_tabName; } - bool hasResolution() const noexcept { return m_hasResolution; } - void setFileExtensionsByName(bool filter); + std::string tabName() const override; void handleDataAdded(IAddWorkspaceDialog const *dialog) override; void handleDataChanged() override; @@ -120,73 +106,44 @@ public slots: void handleStartXChanged(double startX) override; void handleEndXChanged(double endX) override; -protected: - FittingModel *getFittingModel() const; - void run() override; - void setSampleWSSuffixes(const QStringList &suffices); - void setSampleFBSuffixes(const QStringList &suffices); - void setResolutionWSSuffixes(const QStringList &suffices); - void setResolutionFBSuffixes(const QStringList &suffices); - void setSampleSuffixes(std::string const &tab, bool filter); - void setResolutionSuffixes(std::string const &tab, bool filter); - - void setAlgorithmProperties(const Mantid::API::IAlgorithm_sptr &fitAlgorithm) const; - void runFitAlgorithm(Mantid::API::IAlgorithm_sptr fitAlgorithm); - void runSingleFit(Mantid::API::IAlgorithm_sptr fitAlgorithm); - void setupFit(Mantid::API::IAlgorithm_sptr fitAlgorithm); - - void setRunIsRunning(bool running); - void setRunEnabled(bool enable); - void setEditResultVisible(bool visible); - std::unique_ptr m_dataPresenter; - std::unique_ptr m_plotPresenter; - std::unique_ptr m_fittingModel; - InelasticFitPropertyBrowser *m_fitPropertyBrowser{nullptr}; - WorkspaceID m_activeWorkspaceID; - WorkspaceIndex m_activeSpectrumIndex; + void handleFunctionChanged() override; - std::unique_ptr m_uiForm; +private slots: + void updateFitOutput(bool error); + void updateSingleFitOutput(bool error); + void fitAlgorithmComplete(bool error); private: void setup() override; bool validate() override; - void connectFitPropertyBrowser(); - void plotSelectedSpectra(std::vector const &spectra); - void plotSpectrum(std::string const &workspaceName, std::size_t const &index); - std::string getOutputBasename() const; - Mantid::API::WorkspaceGroup_sptr getResultWorkspace() const; - std::vector getFitParameterNames() const; - QList getDatasets() const; + void run() override; + + void runFitAlgorithm(Mantid::API::IAlgorithm_sptr fitAlgorithm); + void runSingleFit(Mantid::API::IAlgorithm_sptr fitAlgorithm); + void setupFit(Mantid::API::IAlgorithm_sptr fitAlgorithm); + void enableFitButtons(bool enable); void enableOutputOptions(bool enable); void setPDFWorkspace(std::string const &workspaceName); + void setModelFitFunction(); + void updateParameterEstimationData(); - std::string getFitTypeString() const; + void updateFitStatus(); + void updateDataReferences(); + void updateResultOptions(); + void updateFitBrowserParameterValues(const std::unordered_map ¶meters = + std::unordered_map()); + void updateFitBrowserParameterValuesFromAlg(); - std::string m_tabName; - bool m_hasResolution; + std::unique_ptr m_uiForm; + std::unique_ptr m_dataPresenter; + std::unique_ptr m_fittingModel; + std::unique_ptr m_plotPresenter; std::unique_ptr m_outOptionsPresenter; - Mantid::API::IAlgorithm_sptr m_fittingAlgorithm; + InelasticFitPropertyBrowser *m_fitPropertyBrowser; -protected slots: - void setModelFitFunction(); - void setModelStartX(double startX); - void setModelEndX(double endX); - void updateFitOutput(bool error); - void updateSingleFitOutput(bool error); - void fitAlgorithmComplete(bool error); - void singleFit(); - void executeFit(); - void updateParameterValues(); - void updateParameterValues(const std::unordered_map ¶meters); - void updateFitBrowserParameterValues(const std::unordered_map ¶meters = - std::unordered_map()); - void updateFitBrowserParameterValuesFromAlg(); - void updateFitStatus(); - void updateDataReferences(); - void updateResultOptions(); - void respondToFunctionChanged(); + Mantid::API::IAlgorithm_sptr m_fittingAlgorithm; }; } // namespace Inelastic diff --git a/qt/scientific_interfaces/Inelastic/QENSFitting/FitTabConstants.h b/qt/scientific_interfaces/Inelastic/QENSFitting/FitTabConstants.h index 6eea73c572cb..0f6ac088a20a 100644 --- a/qt/scientific_interfaces/Inelastic/QENSFitting/FitTabConstants.h +++ b/qt/scientific_interfaces/Inelastic/QENSFitting/FitTabConstants.h @@ -49,7 +49,6 @@ static const auto FUNCTION_STRINGS = namespace MSDFit { static const auto TAB_NAME = "MSDFit"; -static const auto HAS_RESOLUTION = false; static const auto HIDDEN_PROPS = std::vector({"CreateOutput", "LogValue", "PassWSIndexToFunction", "ConvolveMembers", "OutputCompositeMembers", "OutputWorkspace", "Output", "PeakRadius", "PlotParameter"}); @@ -65,7 +64,6 @@ static const auto ALL_FITS = namespace IqtFit { static const auto TAB_NAME = "IqtFit"; -static const auto HAS_RESOLUTION = false; static const auto HIDDEN_PROPS = std::vector({"CreateOutput", "LogValue", "PassWSIndexToFunction", "ConvolveMembers", "OutputCompositeMembers", "OutputWorkspace", "Output", "PeakRadius", "PlotParameter"}); @@ -80,7 +78,6 @@ inline auto templateSubTypes() { namespace ConvFit { static const auto TAB_NAME = "ConvFit"; -static const auto HAS_RESOLUTION = true; static const auto HIDDEN_PROPS = std::vector( {"CreateOutput", "LogValue", "PassWSIndexToFunction", "OutputWorkspace", "Output", "PeakRadius", "PlotParameter"}); @@ -95,7 +92,6 @@ inline auto templateSubTypes() { namespace FqFit { static const auto TAB_NAME = "FQFit"; -static const auto HAS_RESOLUTION = false; static const auto HIDDEN_PROPS = std::vector({"CreateOutput", "LogValue", "PassWSIndexToFunction", "ConvolveMembers", "OutputCompositeMembers", "OutputWorkspace", "Output", "PeakRadius", "PlotParameter"}); diff --git a/qt/scientific_interfaces/Inelastic/QENSFitting/FittingModel.cpp b/qt/scientific_interfaces/Inelastic/QENSFitting/FittingModel.cpp index a6e3f620b1dd..2ab0f9cdd942 100644 --- a/qt/scientific_interfaces/Inelastic/QENSFitting/FittingModel.cpp +++ b/qt/scientific_interfaces/Inelastic/QENSFitting/FittingModel.cpp @@ -7,6 +7,7 @@ #include "FittingModel.h" #include "FitDataModel.h" #include "FitOutput.h" +#include "FitTabConstants.h" #include "MantidAPI/AlgorithmManager.h" #include "MantidAPI/AnalysisDataService.h" @@ -278,6 +279,27 @@ void setFirstBackground(IFunction_sptr function, double value) { firstFunctionWithParameter(function, "Background", "A0")->setParameter("A0", value); } +size_t getNumberOfSpecificFunctionContained(const std::string &functionName, const IFunction *compositeFunction) { + assert(compositeFunction); + + if (compositeFunction->nFunctions() == 0) { + return compositeFunction->name() == functionName ? 1 : 0; + } + + size_t count{0}; + for (size_t i{0}; i < compositeFunction->nFunctions(); i++) { + count += getNumberOfSpecificFunctionContained(functionName, compositeFunction->getFunction(i).get()); + } + return count; +} + +size_t getNumberOfCustomFunctions(MultiDomainFunction_const_sptr const &fittingFunction, + const std::string &functionName) { + if (fittingFunction && fittingFunction->nFunctions() > 0) + return getNumberOfSpecificFunctionContained(functionName, fittingFunction->getFunction(0).get()); + return 0u; +} + } // namespace namespace MantidQt::CustomInterfaces::Inelastic { @@ -289,6 +311,11 @@ FittingModel::FittingModel() : m_fitDataModel(std::make_unique()), m_previousModelSelected(false), m_fittingMode(FittingMode::SEQUENTIAL), m_fitOutput(std::make_unique()) {} +void FittingModel::validate(UserInputValidator &validator) const { + if (auto const invalidFunction = isInvalidFunction()) + validator.addErrorMessage(QString::fromStdString(*invalidFunction)); +} + // Functions that interact with FitDataModel void FittingModel::addDefaultParameters() { m_defaultParameters.emplace_back(createDefaultParameters(WorkspaceID{0})); } @@ -313,7 +340,25 @@ WorkspaceID FittingModel::getNumberOfWorkspaces() const { return m_fitDataModel- bool FittingModel::isMultiFit() const { return m_fitDataModel->getNumberOfWorkspaces().value > 1; } // Other Functions -void FittingModel::setFitTypeString(const std::string &fitType) { m_fitString = fitType; } +void FittingModel::updateFitTypeString() { + auto const multiDomainFunction = getFitFunction(); + if (!multiDomainFunction || multiDomainFunction->nFunctions() == 0) { + m_fitString = "NoCurrentFunction"; + return; + } + + m_fitString.clear(); + for (auto const &fitFunctionName : FUNCTION_STRINGS) { + auto occurances = getNumberOfCustomFunctions(multiDomainFunction, fitFunctionName.first); + if (occurances > 0) { + m_fitString += std::to_string(occurances) + fitFunctionName.second; + } + } + + if (getNumberOfCustomFunctions(multiDomainFunction, "DeltaFunction") > 0) { + m_fitString += "Delta"; + } +} std::string FittingModel::createOutputName(const std::string &fitMode, const std::string &workspaceName, const std::string &spectra) const { diff --git a/qt/scientific_interfaces/Inelastic/QENSFitting/FittingModel.h b/qt/scientific_interfaces/Inelastic/QENSFitting/FittingModel.h index a91ee7bf6cad..17afd61a0a01 100644 --- a/qt/scientific_interfaces/Inelastic/QENSFitting/FittingModel.h +++ b/qt/scientific_interfaces/Inelastic/QENSFitting/FittingModel.h @@ -15,6 +15,7 @@ #include "MantidAPI/IAlgorithm.h" #include "MantidAPI/WorkspaceGroup.h" #include "MantidQtWidgets/Common/FunctionModelSpectra.h" +#include "MantidQtWidgets/Common/UserInputValidator.h" #include #include @@ -45,6 +46,8 @@ class MANTIDQT_INELASTIC_DLL FittingModel : public IFittingModel { FittingModel(); virtual ~FittingModel() = default; + void validate(UserInputValidator &validator) const; + // Functions that interact with FitDataModel void clearWorkspaces() override; Mantid::API::MatrixWorkspace_sptr getWorkspace(WorkspaceID workspaceID) const override; @@ -77,7 +80,7 @@ class MANTIDQT_INELASTIC_DLL FittingModel : public IFittingModel { void setFittingMode(FittingMode mode) override; FittingMode getFittingMode() const override; - void setFitTypeString(const std::string &fitType) override; + void updateFitTypeString() override; boost::optional getResultLocation(WorkspaceID workspaceID, WorkspaceIndex spectrum) const override; Mantid::API::WorkspaceGroup_sptr getResultWorkspace() const override; Mantid::API::WorkspaceGroup_sptr getResultGroup() const override; @@ -94,6 +97,9 @@ class MANTIDQT_INELASTIC_DLL FittingModel : public IFittingModel { IFitDataModel *getFitDataModel() override; + // Used for testing purposes + [[nodiscard]] inline std::string getFitString() const noexcept { return m_fitString; } + protected: std::string createOutputName(const std::string &fitMode, const std::string &workspaceName, const std::string &spectra) const; diff --git a/qt/scientific_interfaces/Inelastic/QENSFitting/FqFitDataView.cpp b/qt/scientific_interfaces/Inelastic/QENSFitting/FqFitDataView.cpp index 0a287ec71542..1db0c2de559c 100644 --- a/qt/scientific_interfaces/Inelastic/QENSFitting/FqFitDataView.cpp +++ b/qt/scientific_interfaces/Inelastic/QENSFitting/FqFitDataView.cpp @@ -5,6 +5,8 @@ // Institut Laue - Langevin & CSNS, Institute of High Energy Physics, CAS // SPDX - License - Identifier: GPL - 3.0 + #include "FqFitDataView.h" +#include "Common/InterfaceUtils.h" +#include "Common/SettingsHelper.h" #include "FqFitAddWorkspaceDialog.h" #include "FqFitDataPresenter.h" @@ -45,9 +47,10 @@ void FqFitDataView::showAddWorkspaceDialog() { connect(dialog, SIGNAL(parameterTypeChanged(FqFitAddWorkspaceDialog *, const std::string &)), this, SLOT(notifyParameterTypeChanged(FqFitAddWorkspaceDialog *, const std::string &))); + auto tabName = m_presenter->tabName(); dialog->setAttribute(Qt::WA_DeleteOnClose); - dialog->setWSSuffices(m_wsSampleSuffixes); - dialog->setFBSuffices(m_fbSampleSuffixes); + dialog->setWSSuffices(InterfaceUtils::getSampleWSSuffixes(tabName)); + dialog->setFBSuffices(InterfaceUtils::getSampleFBSuffixes(tabName)); dialog->updateSelectedSpectra(); dialog->show(); } diff --git a/qt/scientific_interfaces/Inelastic/QENSFitting/FqFitDataView.h b/qt/scientific_interfaces/Inelastic/QENSFitting/FqFitDataView.h index a45bf43db83e..cc93f6c491de 100644 --- a/qt/scientific_interfaces/Inelastic/QENSFitting/FqFitDataView.h +++ b/qt/scientific_interfaces/Inelastic/QENSFitting/FqFitDataView.h @@ -23,11 +23,11 @@ Presenter for a table of convolution fitting data. class MANTIDQT_INELASTIC_DLL FqFitDataView : public FitDataView { Q_OBJECT public: - FqFitDataView(QWidget *parent = nullptr); + FqFitDataView(QWidget *parent); void addTableEntry(size_t row, FitDataRow newRow) override; protected: - FqFitDataView(const QStringList &headers, QWidget *parent = nullptr); + FqFitDataView(const QStringList &headers, QWidget *parent); protected slots: void showAddWorkspaceDialog() override; diff --git a/qt/scientific_interfaces/Inelastic/QENSFitting/FunctionBrowser/FunctionTemplatePresenter.cpp b/qt/scientific_interfaces/Inelastic/QENSFitting/FunctionBrowser/FunctionTemplatePresenter.cpp index a28301bbeef2..fa4817ce5f99 100644 --- a/qt/scientific_interfaces/Inelastic/QENSFitting/FunctionBrowser/FunctionTemplatePresenter.cpp +++ b/qt/scientific_interfaces/Inelastic/QENSFitting/FunctionBrowser/FunctionTemplatePresenter.cpp @@ -72,9 +72,11 @@ void FunctionTemplatePresenter::setDatasets(const QListsetDatasets(datasets); } -QStringList FunctionTemplatePresenter::getDatasetNames() const { return m_model->getDatasetNames(); } +std::vector FunctionTemplatePresenter::getDatasetNames() const { return m_model->getDatasetNames(); } -QStringList FunctionTemplatePresenter::getDatasetDomainNames() const { return m_model->getDatasetDomainNames(); } +std::vector FunctionTemplatePresenter::getDatasetDomainNames() const { + return m_model->getDatasetDomainNames(); +} void FunctionTemplatePresenter::setErrorsEnabled(bool enabled) { m_view->setErrorsEnabled(enabled); } @@ -123,8 +125,7 @@ void FunctionTemplatePresenter::handleEditLocalParameter(std::string const ¶ QList fixes; QStringList ties; QStringList constraints; - const int n = domainNames.size(); - for (auto i = 0; i < n; ++i) { + for (auto i = 0; i < static_cast(domainNames.size()); ++i) { const double value = getLocalParameterValue(parameterName, i); values.push_back(value); const bool fixed = isLocalParameterFixed(parameterName, i); diff --git a/qt/scientific_interfaces/Inelastic/QENSFitting/FunctionBrowser/FunctionTemplatePresenter.h b/qt/scientific_interfaces/Inelastic/QENSFitting/FunctionBrowser/FunctionTemplatePresenter.h index 8a2d248c59f3..d3662e91aaae 100644 --- a/qt/scientific_interfaces/Inelastic/QENSFitting/FunctionBrowser/FunctionTemplatePresenter.h +++ b/qt/scientific_interfaces/Inelastic/QENSFitting/FunctionBrowser/FunctionTemplatePresenter.h @@ -81,8 +81,8 @@ class MANTIDQT_INELASTIC_DLL FunctionTemplatePresenter : public ITemplatePresent protected: virtual void updateView() = 0; - QStringList getDatasetNames() const; - QStringList getDatasetDomainNames() const; + std::vector getDatasetNames() const; + std::vector getDatasetDomainNames() const; void setLocalParameterValue(std::string const ¶meterName, int i, double value); void setLocalParameterTie(std::string const ¶meterName, int i, std::string const &tie); diff --git a/qt/scientific_interfaces/Inelastic/QENSFitting/FunctionBrowser/FunctionTemplateView.cpp b/qt/scientific_interfaces/Inelastic/QENSFitting/FunctionBrowser/FunctionTemplateView.cpp index 02bace145a54..26a99c1e39f5 100644 --- a/qt/scientific_interfaces/Inelastic/QENSFitting/FunctionBrowser/FunctionTemplateView.cpp +++ b/qt/scientific_interfaces/Inelastic/QENSFitting/FunctionBrowser/FunctionTemplateView.cpp @@ -165,7 +165,8 @@ void FunctionTemplateView::updateMultiDatasetParameters(const ITableWorkspace &t void FunctionTemplateView::updateParameters(const IFunction &fun) { m_presenter->updateParameters(fun); } void FunctionTemplateView::openEditLocalParameterDialog(std::string const ¶meterName, - QStringList const &datasetNames, QStringList const &domainNames, + std::vector const &datasetNames, + std::vector const &domainNames, QList const &values, QList const &fixes, QStringList const &ties, QStringList const &constraints) { auto dialog = diff --git a/qt/scientific_interfaces/Inelastic/QENSFitting/FunctionBrowser/FunctionTemplateView.h b/qt/scientific_interfaces/Inelastic/QENSFitting/FunctionBrowser/FunctionTemplateView.h index e47d14a35b5e..312e122e48a1 100644 --- a/qt/scientific_interfaces/Inelastic/QENSFitting/FunctionBrowser/FunctionTemplateView.h +++ b/qt/scientific_interfaces/Inelastic/QENSFitting/FunctionBrowser/FunctionTemplateView.h @@ -15,6 +15,9 @@ #include "MantidQtWidgets/Common/FunctionModelDataset.h" #include "MantidQtWidgets/Common/IndexTypes.h" +#include +#include + #include #include #include @@ -84,8 +87,8 @@ class MANTIDQT_INELASTIC_DLL FunctionTemplateView : public QWidget { void emitFunctionStructureChanged() { emit functionStructureChanged(); } - void openEditLocalParameterDialog(std::string const ¶meterName, QStringList const &datasetNames, - QStringList const &domainNames, QList const &values, + void openEditLocalParameterDialog(std::string const ¶meterName, std::vector const &datasetNames, + std::vector const &domainNames, QList const &values, QList const &fixes, QStringList const &ties, QStringList const &constraints); signals: diff --git a/qt/scientific_interfaces/Inelastic/QENSFitting/FunctionBrowser/MultiFunctionTemplateModel.cpp b/qt/scientific_interfaces/Inelastic/QENSFitting/FunctionBrowser/MultiFunctionTemplateModel.cpp index ea5eba5eb293..530dc666e775 100644 --- a/qt/scientific_interfaces/Inelastic/QENSFitting/FunctionBrowser/MultiFunctionTemplateModel.cpp +++ b/qt/scientific_interfaces/Inelastic/QENSFitting/FunctionBrowser/MultiFunctionTemplateModel.cpp @@ -64,9 +64,11 @@ void MultiFunctionTemplateModel::setDatasets(const QList & m_model->setDatasets(datasets); } -QStringList MultiFunctionTemplateModel::getDatasetNames() const { return m_model->getDatasetNames(); } +std::vector MultiFunctionTemplateModel::getDatasetNames() const { return m_model->getDatasetNames(); } -QStringList MultiFunctionTemplateModel::getDatasetDomainNames() const { return m_model->getDatasetDomainNames(); } +std::vector MultiFunctionTemplateModel::getDatasetDomainNames() const { + return m_model->getDatasetDomainNames(); +} void MultiFunctionTemplateModel::setCurrentDomainIndex(int i) { m_model->setCurrentDomainIndex(i); } diff --git a/qt/scientific_interfaces/Inelastic/QENSFitting/FunctionBrowser/MultiFunctionTemplateModel.h b/qt/scientific_interfaces/Inelastic/QENSFitting/FunctionBrowser/MultiFunctionTemplateModel.h index 129b241a8b43..e4bd8794ab5e 100644 --- a/qt/scientific_interfaces/Inelastic/QENSFitting/FunctionBrowser/MultiFunctionTemplateModel.h +++ b/qt/scientific_interfaces/Inelastic/QENSFitting/FunctionBrowser/MultiFunctionTemplateModel.h @@ -47,8 +47,8 @@ class MANTIDQT_INELASTIC_DLL MultiFunctionTemplateModel : public IFunctionModel void setNumberDomains(int) override; int getNumberDomains() const override; void setDatasets(const QList &datasets) override; - QStringList getDatasetNames() const override; - QStringList getDatasetDomainNames() const override; + std::vector getDatasetNames() const override; + std::vector getDatasetDomainNames() const override; void setCurrentDomainIndex(int i) override; int currentDomainIndex() const override; diff --git a/qt/scientific_interfaces/Inelastic/QENSFitting/IFitDataModel.h b/qt/scientific_interfaces/Inelastic/QENSFitting/IFitDataModel.h index 6a130aa4a8cf..02abec0cc0db 100644 --- a/qt/scientific_interfaces/Inelastic/QENSFitting/IFitDataModel.h +++ b/qt/scientific_interfaces/Inelastic/QENSFitting/IFitDataModel.h @@ -11,6 +11,7 @@ #include "DllConfig.h" #include "FitData.h" #include "MantidAPI/MatrixWorkspace.h" +#include "MantidQtWidgets/Common/FunctionModelDataset.h" #include "MantidQtWidgets/Common/FunctionModelSpectra.h" #include "MantidQtWidgets/Common/IndexTypes.h" @@ -33,6 +34,7 @@ class MANTIDQT_INELASTIC_DLL IFitDataModel { virtual bool hasWorkspace(std::string const &workspaceName) const = 0; virtual Mantid::API::MatrixWorkspace_sptr getWorkspace(WorkspaceID workspaceID) const = 0; virtual FunctionModelSpectra getSpectra(WorkspaceID workspaceID) const = 0; + virtual FunctionModelDataset getDataset(WorkspaceID workspaceID) const = 0; virtual WorkspaceID getNumberOfWorkspaces() const = 0; virtual size_t getNumberOfSpectra(WorkspaceID workspaceID) const = 0; virtual size_t getNumberOfDomains() const = 0; diff --git a/qt/scientific_interfaces/Inelastic/QENSFitting/IFitDataView.h b/qt/scientific_interfaces/Inelastic/QENSFitting/IFitDataView.h index 63b2b86d1b8b..b46d14eda549 100644 --- a/qt/scientific_interfaces/Inelastic/QENSFitting/IFitDataView.h +++ b/qt/scientific_interfaces/Inelastic/QENSFitting/IFitDataView.h @@ -36,7 +36,7 @@ class MANTIDQT_INELASTIC_DLL IFitDataView { virtual QTableWidget *getDataTable() const = 0; virtual bool isTableEmpty() const = 0; - virtual UserInputValidator &validate(UserInputValidator &validator) = 0; + virtual void validate(UserInputValidator &validator) = 0; virtual void addTableEntry(size_t row, FitDataRow newRow) = 0; virtual void updateNumCellEntry(double numEntry, size_t row, size_t column) = 0; virtual int getColumnIndexFromName(std::string const &ColName) = 0; @@ -45,11 +45,6 @@ class MANTIDQT_INELASTIC_DLL IFitDataView { virtual QModelIndexList getSelectedIndexes() const = 0; virtual bool dataColumnContainsText(std::string const &columnText) const = 0; - virtual void setSampleWSSuffices(const QStringList &suffices) = 0; - virtual void setSampleFBSuffices(const QStringList &suffices) = 0; - virtual void setResolutionWSSuffices(const QStringList &suffices) = 0; - virtual void setResolutionFBSuffices(const QStringList &suffices) = 0; - virtual void displayWarning(std::string const &warning) = 0; }; } // namespace Inelastic diff --git a/qt/scientific_interfaces/Inelastic/QENSFitting/IFittingModel.h b/qt/scientific_interfaces/Inelastic/QENSFitting/IFittingModel.h index e025df3ee7a2..84efebf727c0 100644 --- a/qt/scientific_interfaces/Inelastic/QENSFitting/IFittingModel.h +++ b/qt/scientific_interfaces/Inelastic/QENSFitting/IFittingModel.h @@ -57,7 +57,7 @@ class MANTIDQT_INELASTIC_DLL IFittingModel { virtual void setFittingMode(FittingMode mode) = 0; virtual FittingMode getFittingMode() const = 0; - virtual void setFitTypeString(const std::string &fitType) = 0; + virtual void updateFitTypeString() = 0; virtual boost::optional getResultLocation(WorkspaceID workspaceID, WorkspaceIndex spectrum) const = 0; virtual Mantid::API::WorkspaceGroup_sptr getResultWorkspace() const = 0; diff --git a/qt/scientific_interfaces/Inelastic/QENSFitting/InelasticFitPropertyBrowser.cpp b/qt/scientific_interfaces/Inelastic/QENSFitting/InelasticFitPropertyBrowser.cpp index 5001545e969c..9b2b69464e96 100644 --- a/qt/scientific_interfaces/Inelastic/QENSFitting/InelasticFitPropertyBrowser.cpp +++ b/qt/scientific_interfaces/Inelastic/QENSFitting/InelasticFitPropertyBrowser.cpp @@ -11,6 +11,7 @@ #include "FunctionBrowser/SingleFunctionTemplateView.h" #include "MantidAPI/AlgorithmManager.h" +#include "MantidAPI/AlgorithmProperties.h" #include "MantidAPI/FrameworkManager.h" #include "MantidAPI/ITableWorkspace.h" #include "MantidAPI/MatrixWorkspace.h" @@ -249,6 +250,30 @@ std::string InelasticFitPropertyBrowser::fitType() const { return m_fitOptionsBrowser->getProperty("FitType").toStdString(); } +std::unique_ptr +InelasticFitPropertyBrowser::fitProperties(FittingMode const &fittingMode) const { + auto properties = std::make_unique(); + Mantid::API::AlgorithmProperties::update("Minimizer", minimizer(true), *properties); + Mantid::API::AlgorithmProperties::update("MaxIterations", maxIterations(), *properties); + Mantid::API::AlgorithmProperties::update("PeakRadius", getPeakRadius(), *properties); + Mantid::API::AlgorithmProperties::update("CostFunction", costFunction(), *properties); + Mantid::API::AlgorithmProperties::update("IgnoreInvalidData", ignoreInvalidData(), *properties); + Mantid::API::AlgorithmProperties::update("EvaluationType", fitEvaluationType(), *properties); + Mantid::API::AlgorithmProperties::update("PeakRadius", getPeakRadius(), *properties); + Mantid::API::AlgorithmProperties::update("CostFunction", costFunction(), *properties); + Mantid::API::AlgorithmProperties::update("ConvolveMembers", convolveMembers(), *properties); + if (convolveMembers()) { + Mantid::API::AlgorithmProperties::update("OutputCompositeMembers", true, *properties); + } else { + Mantid::API::AlgorithmProperties::update("OutputCompositeMembers", outputCompositeMembers(), *properties); + } + if (fittingMode == FittingMode::SEQUENTIAL) { + Mantid::API::AlgorithmProperties::update("FitType", fitType(), *properties); + } + Mantid::API::AlgorithmProperties::update("OutputFitStatus", true, *properties); + return properties; +} + int InelasticFitPropertyBrowser::getNumberOfDatasets() const { return isFullFunctionBrowserActive() ? m_functionBrowser->getNumberOfDatasets() : m_templatePresenter->getNumberOfDatasets(); diff --git a/qt/scientific_interfaces/Inelastic/QENSFitting/InelasticFitPropertyBrowser.h b/qt/scientific_interfaces/Inelastic/QENSFitting/InelasticFitPropertyBrowser.h index d3c29a0f08d1..35a800ed00c0 100644 --- a/qt/scientific_interfaces/Inelastic/QENSFitting/InelasticFitPropertyBrowser.h +++ b/qt/scientific_interfaces/Inelastic/QENSFitting/InelasticFitPropertyBrowser.h @@ -8,6 +8,7 @@ #include "DllConfig.h" #include "FunctionBrowser/ITemplatePresenter.h" +#include "MantidAPI/AlgorithmRuntimeProps.h" #include "MantidAPI/IFunction_fwd.h" #include "MantidAPI/ITableWorkspace_fwd.h" #include "MantidAPI/MatrixWorkspace_fwd.h" @@ -68,6 +69,7 @@ class MANTIDQT_INELASTIC_DLL InelasticFitPropertyBrowser : public QDockWidget, p std::string fitEvaluationType() const; std::string fitType() const; bool ignoreInvalidData() const; + std::unique_ptr fitProperties(FittingMode const &fittingMode) const; void updateParameters(const IFunction &fun); void updateMultiDatasetParameters(const IFunction &fun); void updateMultiDatasetParameters(const ITableWorkspace ¶ms); diff --git a/qt/scientific_interfaces/Inelastic/QENSFitting/QENSFitting.cpp b/qt/scientific_interfaces/Inelastic/QENSFitting/QENSFitting.cpp index 435d8929691f..a702f60891a2 100644 --- a/qt/scientific_interfaces/Inelastic/QENSFitting/QENSFitting.cpp +++ b/qt/scientific_interfaces/Inelastic/QENSFitting/QENSFitting.cpp @@ -25,12 +25,6 @@ QENSFitting::QENSFitting(QWidget *parent) m_tabs.emplace(FQ_FIT, tabFactory->makeFqFitTab(FQ_FIT)); } -void QENSFitting::applySettings(std::map const &settings) { - for (auto tab = m_tabs.begin(); tab != m_tabs.end(); ++tab) { - tab->second->setFileExtensionsByName(settings.at("RestrictInput").toBool()); - } -} - /** * Initialised the layout of the interface. MUST be called. */ diff --git a/qt/scientific_interfaces/Inelastic/QENSFitting/QENSFitting.h b/qt/scientific_interfaces/Inelastic/QENSFitting/QENSFitting.h index a20c794d262b..b594261424cf 100644 --- a/qt/scientific_interfaces/Inelastic/QENSFitting/QENSFitting.h +++ b/qt/scientific_interfaces/Inelastic/QENSFitting/QENSFitting.h @@ -50,8 +50,6 @@ private slots: private: std::string documentationPage() const override; - void applySettings(std::map const &settings) override; - /// UI form containing all Qt elements. Ui::QENSFitting m_uiForm; /// The settings group diff --git a/qt/scientific_interfaces/Inelastic/QENSFitting/TabFactory.cpp b/qt/scientific_interfaces/Inelastic/QENSFitting/TabFactory.cpp index f39f996db95c..743084f25124 100644 --- a/qt/scientific_interfaces/Inelastic/QENSFitting/TabFactory.cpp +++ b/qt/scientific_interfaces/Inelastic/QENSFitting/TabFactory.cpp @@ -39,7 +39,7 @@ namespace MantidQt::CustomInterfaces::Inelastic { TabFactory::TabFactory(QTabWidget *tabWidget) : m_tabWidget(tabWidget) {} FitTab *TabFactory::makeMSDFitTab(int const index) const { - auto tab = new FitTab(MSDFit::TAB_NAME, MSDFit::HAS_RESOLUTION, m_tabWidget->widget(index)); + auto tab = new FitTab(m_tabWidget->widget(index), MSDFit::TAB_NAME); tab->setupFittingModel(); tab->setupFitPropertyBrowser( MSDFit::HIDDEN_PROPS); @@ -51,7 +51,7 @@ FitTab *TabFactory::makeMSDFitTab(int const index) const { } FitTab *TabFactory::makeIqtFitTab(int const index) const { - auto tab = new FitTab(IqtFit::TAB_NAME, IqtFit::HAS_RESOLUTION, m_tabWidget->widget(index)); + auto tab = new FitTab(m_tabWidget->widget(index), IqtFit::TAB_NAME); tab->setupFittingModel(); auto browserCustomizations = packBrowserCustomizations(IqtFit::templateSubTypes()); tab->setupFitPropertyBrowser( @@ -64,7 +64,7 @@ FitTab *TabFactory::makeIqtFitTab(int const index) const { } FitTab *TabFactory::makeConvFitTab(int const index) const { - auto tab = new FitTab(ConvFit::TAB_NAME, ConvFit::HAS_RESOLUTION, m_tabWidget->widget(index)); + auto tab = new FitTab(m_tabWidget->widget(index), ConvFit::TAB_NAME); tab->setupFittingModel(); auto browserCustomizations = packBrowserCustomizations(ConvFit::templateSubTypes()); tab->setupFitPropertyBrowser( @@ -77,7 +77,7 @@ FitTab *TabFactory::makeConvFitTab(int const index) const { } FitTab *TabFactory::makeFqFitTab(int const index) const { - auto tab = new FitTab(FqFit::TAB_NAME, FqFit::HAS_RESOLUTION, m_tabWidget->widget(index)); + auto tab = new FitTab(m_tabWidget->widget(index), FqFit::TAB_NAME); tab->setupFittingModel(); tab->setupFitPropertyBrowser( FqFit::HIDDEN_PROPS); diff --git a/qt/scientific_interfaces/Inelastic/test/Common/InterfaceUtilsTest.h b/qt/scientific_interfaces/Inelastic/test/Common/InterfaceUtilsTest.h index 804ae30020fa..14470b5a723c 100644 --- a/qt/scientific_interfaces/Inelastic/test/Common/InterfaceUtilsTest.h +++ b/qt/scientific_interfaces/Inelastic/test/Common/InterfaceUtilsTest.h @@ -15,7 +15,7 @@ #include using namespace Mantid::API; -using namespace Mantid::IndirectFitDataCreationHelper; +using namespace MantidQt::CustomInterfaces; using namespace MantidQt::CustomInterfaces::InterfaceUtils; class InterfaceUtilsTest : public CxxTest::TestSuite { @@ -28,7 +28,19 @@ class InterfaceUtilsTest : public CxxTest::TestSuite { TS_ASSERT_EQUALS(getInterfaceProperty("Empty", "EXTENSIONS", "all"), ""); } - void test_get_FB_WS_suffixes_function_returns_proper_interface_suffixes() { + void test_get_FB_WS_suffixes_when_restrict_data_is_off() { + auto mockRestrictInputDataByName = []() { return false; }; + InterfaceUtils::restrictInputDataByName = mockRestrictInputDataByName; + + // There are many similar functions in the interface, this test will try only one pair of such functions + TS_ASSERT_EQUALS(getResolutionWSSuffixes("Iqt"), QStringList({""})); + TS_ASSERT_EQUALS(getResolutionFBSuffixes("Iqt"), QStringList({".nxs"})); + } + + void test_get_FB_WS_suffixes_when_restrict_data_is_on() { + auto mockRestrictInputDataByName = []() { return true; }; + InterfaceUtils::restrictInputDataByName = mockRestrictInputDataByName; + // There are many similar functions in the interface, this test will try only one pair of such functions TS_ASSERT_EQUALS(getResolutionWSSuffixes("Iqt"), QStringList({"_res", "_red", "_sqw"})); TS_ASSERT_EQUALS(getResolutionFBSuffixes("Iqt"), QStringList({"_res.nxs", "_red.nxs", "_sqw.nxs"})); diff --git a/qt/scientific_interfaces/Inelastic/test/QENSFitting/CMakeLists.txt b/qt/scientific_interfaces/Inelastic/test/QENSFitting/CMakeLists.txt index 2bf6d1c6ccaa..263231a6ceac 100644 --- a/qt/scientific_interfaces/Inelastic/test/QENSFitting/CMakeLists.txt +++ b/qt/scientific_interfaces/Inelastic/test/QENSFitting/CMakeLists.txt @@ -4,7 +4,6 @@ set(TEST_FILES ConvFitModelTest.h ConvFitDataPresenterTest.h ConvFunctionTemplateModelTest.h - FitTabTest.h FqFitDataPresenterTest.h FqFitModelTest.h FitDataPresenterTest.h diff --git a/qt/scientific_interfaces/Inelastic/test/QENSFitting/FitDataPresenterTest.h b/qt/scientific_interfaces/Inelastic/test/QENSFitting/FitDataPresenterTest.h index 66f7cfe41a36..a33c14155081 100644 --- a/qt/scientific_interfaces/Inelastic/test/QENSFitting/FitDataPresenterTest.h +++ b/qt/scientific_interfaces/Inelastic/test/QENSFitting/FitDataPresenterTest.h @@ -163,38 +163,6 @@ class FitDataPresenterTest : public CxxTest::TestSuite { m_presenter->setResolution("WorkspaceName"); } - void test_that_setSampleWSSuffices_will_set_the_sample_workspace_suffices_in_the_view() { - QStringList const suffices{"suffix1", "suffix2"}; - - EXPECT_CALL(*m_view, setSampleWSSuffices(suffices)).Times(Exactly(1)); - - m_presenter->setSampleWSSuffices(suffices); - } - - void test_that_setSampleFBSuffices_will_set_the_sample_file_suffices_in_the_view() { - QStringList const suffices{"suffix1", "suffix2"}; - - EXPECT_CALL(*m_view, setSampleFBSuffices(suffices)).Times(Exactly(1)); - - m_presenter->setSampleFBSuffices(suffices); - } - - void test_that_setResolutionWSSuffices_will_set_the_Resolution_workspace_suffices_in_the_view() { - QStringList const suffices{"suffix1", "suffix2"}; - - EXPECT_CALL(*m_view, setResolutionWSSuffices(suffices)).Times(Exactly(1)); - - m_presenter->setResolutionWSSuffices(suffices); - } - - void test_that_setResolutionFBSuffices_will_set_the_Resolution_file_suffices_in_the_view() { - QStringList const suffices{"suffix1", "suffix2"}; - - EXPECT_CALL(*m_view, setResolutionFBSuffices(suffices)).Times(Exactly(1)); - - m_presenter->setResolutionFBSuffices(suffices); - } - void test_getResolutionsForFit_calls_from_model() { std::vector> resolutions = {{"string", 1}}; EXPECT_CALL(*m_model, getResolutionsForFit()).Times(Exactly(1)).WillOnce(Return(resolutions)); diff --git a/qt/scientific_interfaces/Inelastic/test/QENSFitting/FitTabTest.h b/qt/scientific_interfaces/Inelastic/test/QENSFitting/FitTabTest.h deleted file mode 100644 index 8d7967b7780c..000000000000 --- a/qt/scientific_interfaces/Inelastic/test/QENSFitting/FitTabTest.h +++ /dev/null @@ -1,54 +0,0 @@ -// Mantid Repository : https://github.com/mantidproject/mantid -// -// Copyright © 2019 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 + -#pragma once - -#include "QENSFitting/FitTab.h" - -#include "MantidAPI/FunctionFactory.h" -#include -#include - -using namespace MantidQt::CustomInterfaces::Inelastic; - -class FitTabTest : public CxxTest::TestSuite { -public: - static FitTabTest *createSuite() { return new FitTabTest(); } - - static void destroySuite(FitTabTest *suite) { delete suite; } - - void test_that_single_function_correctly_identified() { - std::string functionName = "ExpDecay"; - auto fitFunction = Mantid::API::FunctionFactory::Instance().createFunction(functionName); - auto occurances = FitTab::getNumberOfSpecificFunctionContained(functionName, fitFunction.get()); - TS_ASSERT_EQUALS(occurances, 1); - } - - void test_that_single_layer_composite_function_handled_correctly() { - std::string functionName = "name=ExpDecay;name=StretchExp"; - auto fitFunction = Mantid::API::FunctionFactory::Instance().createInitialized(functionName); - auto occurances = FitTab::getNumberOfSpecificFunctionContained("ExpDecay", fitFunction.get()); - auto stretchOccurances = FitTab::getNumberOfSpecificFunctionContained("StretchExp", fitFunction.get()); - TS_ASSERT_EQUALS(occurances, 1); - TS_ASSERT_EQUALS(stretchOccurances, 1); - } - - void test_that_no_matched_name_is_correct() { - std::string functionName = "name=ExpDecay;name=StretchExp"; - auto fitFunction = Mantid::API::FunctionFactory::Instance().createInitialized(functionName); - auto occurances = FitTab::getNumberOfSpecificFunctionContained("NotHere", fitFunction.get()); - TS_ASSERT_EQUALS(occurances, 0); - } - - void test_that_multi_layer_composite_function_handled_correctly() { - std::string functionName = "name=ExpDecay;name=ExpDecay;(composite=" - "ProductFunction,NumDeriv=false;name=ExpDecay;" - "name=ExpDecay)"; - auto fitFunction = Mantid::API::FunctionFactory::Instance().createInitialized(functionName); - auto occurances = FitTab::getNumberOfSpecificFunctionContained("ExpDecay", fitFunction.get()); - TS_ASSERT_EQUALS(occurances, 4); - } -}; diff --git a/qt/scientific_interfaces/Inelastic/test/QENSFitting/FittingModelTest.h b/qt/scientific_interfaces/Inelastic/test/QENSFitting/FittingModelTest.h index 297d0e7f31c0..d4540b90c6fc 100644 --- a/qt/scientific_interfaces/Inelastic/test/QENSFitting/FittingModelTest.h +++ b/qt/scientific_interfaces/Inelastic/test/QENSFitting/FittingModelTest.h @@ -376,9 +376,9 @@ class FittingModelTest : public CxxTest::TestSuite { TS_ASSERT_EQUALS(m_model->getFittingMode(), simultaneous); } - void test_setFitTypeString_sets_member() { + void test_updateFitTypeString_does_not_throw() { addWorkspaceToModel("Workspace1", 3, "0-2"); - TS_ASSERT_THROWS_NOTHING(m_model->setFitTypeString("TestString")); + TS_ASSERT_THROWS_NOTHING(m_model->updateFitTypeString()); } void test_getResultLocation_returns_none_when_out_of_index() { @@ -435,6 +435,46 @@ class FittingModelTest : public CxxTest::TestSuite { TS_ASSERT_EQUALS(m_model->getOutputBasename(), outputString); } + void test_that_single_function_correctly_identified() { + auto const function = getFunction("composite=MultiDomainFunction,NumDeriv=true;(composite=Convolution," + "NumDeriv=true,FixResolution=true,$domains=i;name=Resolution," + "WorkspaceIndex=0,X=(),Y=();(name=ExpDecay,Height=1,Lifetime=1;));"); + m_model->setFitFunction(function); + m_model->updateFitTypeString(); + TS_ASSERT_EQUALS("1E", m_model->getFitString()); + } + + void test_that_single_layer_composite_function_handled_correctly() { + auto const function = getFunction("composite=MultiDomainFunction,NumDeriv=true;(composite=Convolution," + "NumDeriv=true,FixResolution=true,$domains=i;name=Resolution," + "WorkspaceIndex=0,X=(),Y=();(name=ExpDecay,Height=1,Lifetime=1;name=StretchExp," + "Height=1,Lifetime=1,Stretching=1;));"); + m_model->setFitFunction(function); + m_model->updateFitTypeString(); + auto const fitString = m_model->getFitString(); + TS_ASSERT(fitString.find("1E") != std::string::npos); + TS_ASSERT(fitString.find("1S") != std::string::npos); + } + + void test_that_no_matched_name_is_correct() { + auto const function = getFunction("composite=MultiDomainFunction,NumDeriv=true;(composite=Convolution," + "NumDeriv=true,FixResolution=true,$domains=i;name=Resolution," + "WorkspaceIndex=0,X=(),Y=();(name=ExpDecayMuon,A=1,Lambda=1;));"); + m_model->setFitFunction(function); + m_model->updateFitTypeString(); + TS_ASSERT_EQUALS("", m_model->getFitString()); + } + + void test_that_multi_layer_composite_function_handled_correctly() { + auto const function = getFunction( + "composite=MultiDomainFunction,NumDeriv=true;(composite=Convolution," + "NumDeriv=true,FixResolution=true,$domains=i;name=Resolution," + "WorkspaceIndex=0,X=(),Y=();(name=ExpDecay,Height=1,Lifetime=1;name=ExpDecay,Height=1,Lifetime=1;));"); + m_model->setFitFunction(function); + m_model->updateFitTypeString(); + TS_ASSERT_EQUALS("2E", m_model->getFitString()); + } + private: void addWorkspaceToModel(std::string workspaceName, int numberOfSpectra, std::string const &spectra) { SetUpADSWithWorkspace ads(workspaceName, createWorkspace(numberOfSpectra)); diff --git a/qt/scientific_interfaces/Inelastic/test/QENSFitting/InelasticFitPropertyBrowserTest.h b/qt/scientific_interfaces/Inelastic/test/QENSFitting/InelasticFitPropertyBrowserTest.h index 6d91cb80cc44..67b75e9e50c8 100644 --- a/qt/scientific_interfaces/Inelastic/test/QENSFitting/InelasticFitPropertyBrowserTest.h +++ b/qt/scientific_interfaces/Inelastic/test/QENSFitting/InelasticFitPropertyBrowserTest.h @@ -219,7 +219,7 @@ class InelasticFitPropertyBrowserTest : public CxxTest::TestSuite { WorkspaceID workspaceID{i}; auto const name = "wsName" + std::to_string(i); - datasets.append(FunctionModelDataset(QString::fromStdString(name), FunctionModelSpectra("0"))); + datasets.append(FunctionModelDataset(name, FunctionModelSpectra("0"))); } std::vector qValues = {0.0, 1.0}; std::vector> fitResolutions(1, std::make_pair("resWS", 0)); diff --git a/qt/scientific_interfaces/Inelastic/test/QENSFitting/MockObjects.h b/qt/scientific_interfaces/Inelastic/test/QENSFitting/MockObjects.h index 718c4eda87d5..232da1a96a71 100644 --- a/qt/scientific_interfaces/Inelastic/test/QENSFitting/MockObjects.h +++ b/qt/scientific_interfaces/Inelastic/test/QENSFitting/MockObjects.h @@ -41,6 +41,7 @@ class MockFitTab : public IFitTab { public: virtual ~MockFitTab() = default; + MOCK_CONST_METHOD0(tabName, std::string()); MOCK_METHOD1(handleDataAdded, void(MantidQt::MantidWidgets::IAddWorkspaceDialog const *dialog)); MOCK_METHOD0(handleDataChanged, void()); MOCK_METHOD0(handleDataRemoved, void()); @@ -55,6 +56,8 @@ class MockFitTab : public IFitTab { MOCK_METHOD1(handleBackgroundChanged, void(double background)); MOCK_METHOD0(handlePlotSelectedSpectra, void()); + + MOCK_METHOD0(handleFunctionChanged, void()); }; class MockFitPlotView : public IFitPlotView { @@ -204,6 +207,7 @@ class MockFitDataModel : public IFitDataModel { MOCK_METHOD2(setSpectra, void(FunctionModelSpectra &&spectra, WorkspaceID workspaceID)); MOCK_METHOD2(setSpectra, void(const FunctionModelSpectra &spectra, WorkspaceID workspaceID)); MOCK_CONST_METHOD1(getSpectra, FunctionModelSpectra(WorkspaceID workspaceID)); + MOCK_CONST_METHOD1(getDataset, FunctionModelDataset(WorkspaceID workspaceID)); MOCK_CONST_METHOD1(getSpectrum, size_t(FitDomainIndex index)); MOCK_CONST_METHOD1(getNumberOfSpectra, size_t(WorkspaceID workspaceID)); @@ -247,8 +251,7 @@ class MockFitDataView : public IFitDataView { MOCK_CONST_METHOD0(getDataTable, QTableWidget *()); MOCK_CONST_METHOD0(isTableEmpty, bool()); - MOCK_METHOD1(validate, MantidQt::CustomInterfaces::UserInputValidator &( - MantidQt::CustomInterfaces::UserInputValidator &validator)); + MOCK_METHOD1(validate, void(MantidQt::CustomInterfaces::UserInputValidator &validator)); MOCK_METHOD2(addTableEntry, void(size_t row, FitDataRow newRow)); MOCK_METHOD3(updateNumCellEntry, void(double numEntry, size_t row, size_t column)); MOCK_METHOD1(getColumnIndexFromName, int(std::string const &ColName)); diff --git a/qt/widgets/common/inc/MantidQtWidgets/Common/EditLocalParameterDialog.h b/qt/widgets/common/inc/MantidQtWidgets/Common/EditLocalParameterDialog.h index 96a960c74173..0224dc3fcfad 100644 --- a/qt/widgets/common/inc/MantidQtWidgets/Common/EditLocalParameterDialog.h +++ b/qt/widgets/common/inc/MantidQtWidgets/Common/EditLocalParameterDialog.h @@ -12,6 +12,8 @@ #include "ui_EditLocalParameterDialog.h" #include +#include +#include #include @@ -28,9 +30,9 @@ class FunctionMultiDomainPresenter; class EXPORT_OPT_MANTIDQT_COMMON EditLocalParameterDialog : public MantidQt::API::MantidDialog { Q_OBJECT public: - EditLocalParameterDialog(QWidget *parent, const std::string &parName, const QStringList &datasetNames, - const QStringList &datasetDomainNames, const QList &values, const QList &fixes, - const QStringList &ties, const QStringList &constraints); + EditLocalParameterDialog(QWidget *parent, const std::string &parName, const std::vector &datasetNames, + const std::vector &datasetDomainNames, const QList &values, + const QList &fixes, const QStringList &ties, const QStringList &constraints); std::string getParameterName() const { return m_parName; } QList getValues() const; @@ -66,7 +68,8 @@ private slots: void setAllValuesToLog(); private: - void doSetup(const std::string &parName, const QStringList &datasetDomains, const QStringList &datasetDomainNames); + void doSetup(const std::string &parName, const std::vector &datasetDomains, + const std::vector &datasetDomainNames); bool eventFilter(QObject *obj, QEvent *ev) override; void showContextMenu(); void redrawCells(); diff --git a/qt/widgets/common/inc/MantidQtWidgets/Common/FunctionBrowser.h b/qt/widgets/common/inc/MantidQtWidgets/Common/FunctionBrowser.h index 00180d8393cd..db560df2e18e 100644 --- a/qt/widgets/common/inc/MantidQtWidgets/Common/FunctionBrowser.h +++ b/qt/widgets/common/inc/MantidQtWidgets/Common/FunctionBrowser.h @@ -77,9 +77,9 @@ class EXPORT_OPT_MANTIDQT_COMMON FunctionBrowser : public QWidget, public IFunct /// Get the number of datasets int getNumberOfDatasets() const override; /// Get the names of datasets - QStringList getDatasetNames() const override; + std::vector getDatasetNames() const override; /// Get the names of the dataset domains - QStringList getDatasetDomainNames() const override; + std::vector getDatasetDomainNames() const override; /// Get value of a local parameter double getLocalParameterValue(std::string const ¶meterName, int i) const override; /// Set value of a local parameter @@ -137,12 +137,12 @@ public slots: // Handling of multiple datasets void setNumberOfDatasets(int n) override; - void setDatasets(const QStringList &datasetNames) override; + void setDatasets(const std::vector &datasetNames) override; void setDatasets(const QList &datasets) override; void resetLocalParameters(); void setCurrentDataset(int i) override; void removeDatasets(const QList &indices); - void addDatasets(const QStringList &names); + void addDatasets(const std::vector &names); protected: std::unique_ptr m_presenter; diff --git a/qt/widgets/common/inc/MantidQtWidgets/Common/FunctionModel.h b/qt/widgets/common/inc/MantidQtWidgets/Common/FunctionModel.h index 07cfde6fbd14..5d08f3296993 100644 --- a/qt/widgets/common/inc/MantidQtWidgets/Common/FunctionModel.h +++ b/qt/widgets/common/inc/MantidQtWidgets/Common/FunctionModel.h @@ -44,12 +44,12 @@ class EXPORT_OPT_MANTIDQT_COMMON FunctionModel : public IFunctionModel { IFunction_sptr getSingleFunction(int index) const override; IFunction_sptr getCurrentFunction() const override; void setNumberDomains(int) override; - void setDatasets(const QStringList &datasetNames); + void setDatasets(const std::vector &datasetNames); void setDatasets(const QList &datasets) override; - void addDatasets(const QStringList &datasetNames); + void addDatasets(const std::vector &datasetNames); void removeDatasets(QList &indices); - QStringList getDatasetNames() const override; - QStringList getDatasetDomainNames() const override; + std::vector getDatasetNames() const override; + std::vector getDatasetDomainNames() const override; int getNumberDomains() const override; int currentDomainIndex() const override; void setCurrentDomainIndex(int) override; diff --git a/qt/widgets/common/inc/MantidQtWidgets/Common/FunctionModelDataset.h b/qt/widgets/common/inc/MantidQtWidgets/Common/FunctionModelDataset.h index c64dfa72a907..9b1eb705a60e 100644 --- a/qt/widgets/common/inc/MantidQtWidgets/Common/FunctionModelDataset.h +++ b/qt/widgets/common/inc/MantidQtWidgets/Common/FunctionModelDataset.h @@ -9,9 +9,8 @@ #include "DllOption.h" #include "MantidQtWidgets/Common/FunctionModelSpectra.h" -#include -#include -#include +#include +#include namespace MantidQt { namespace MantidWidgets { @@ -24,15 +23,15 @@ namespace MantidWidgets { */ struct EXPORT_OPT_MANTIDQT_COMMON FunctionModelDataset { public: - FunctionModelDataset(QString workspaceName, FunctionModelSpectra spectra); + FunctionModelDataset(std::string workspaceName, FunctionModelSpectra spectra); - inline QString datasetName() const noexcept { return m_workspaceName; } - QStringList domainNames() const; + inline std::string datasetName() const noexcept { return m_workspaceName; } + std::vector domainNames() const; inline std::size_t numberOfSpectra() const noexcept { return m_spectra.size().value; } private: - QString m_workspaceName; + std::string m_workspaceName; FunctionModelSpectra m_spectra; }; diff --git a/qt/widgets/common/inc/MantidQtWidgets/Common/FunctionMultiDomainPresenter.h b/qt/widgets/common/inc/MantidQtWidgets/Common/FunctionMultiDomainPresenter.h index 240f3a6bf150..fac1b21c7a86 100644 --- a/qt/widgets/common/inc/MantidQtWidgets/Common/FunctionMultiDomainPresenter.h +++ b/qt/widgets/common/inc/MantidQtWidgets/Common/FunctionMultiDomainPresenter.h @@ -49,11 +49,11 @@ class EXPORT_OPT_MANTIDQT_COMMON FunctionMultiDomainPresenter : public QObject { void clearErrors(); boost::optional currentFunctionIndex() const; void setNumberOfDatasets(int); - void setDatasets(const QStringList &datasetNames); + void setDatasets(const std::vector &datasetNames); void setDatasets(const QList &datasets); - void addDatasets(const QStringList &datasetNames); - QStringList getDatasetNames() const; - QStringList getDatasetDomainNames() const; + void addDatasets(const std::vector &datasetNames); + std::vector getDatasetNames() const; + std::vector getDatasetDomainNames() const; int getNumberOfDatasets() const; int getCurrentDataset() const; void setCurrentDataset(int); diff --git a/qt/widgets/common/inc/MantidQtWidgets/Common/IFunctionBrowser.h b/qt/widgets/common/inc/MantidQtWidgets/Common/IFunctionBrowser.h index 52231494c855..71da09d2d9bb 100644 --- a/qt/widgets/common/inc/MantidQtWidgets/Common/IFunctionBrowser.h +++ b/qt/widgets/common/inc/MantidQtWidgets/Common/IFunctionBrowser.h @@ -12,10 +12,12 @@ #include "MantidAPI/IFunction_fwd.h" #include "MantidAPI/ITableWorkspace_fwd.h" +#include +#include + #include #include #include -#include namespace MantidQt { namespace MantidWidgets { @@ -34,7 +36,7 @@ class EXPORT_OPT_MANTIDQT_COMMON IFunctionBrowser { virtual void clearErrors() = 0; virtual void setFunction(std::string const &funStr) = 0; virtual void setNumberOfDatasets(int n) = 0; - virtual void setDatasets(const QStringList &datasetNames) = 0; + virtual void setDatasets(const std::vector &datasetNames) = 0; virtual void setDatasets(const QList &datasets) = 0; virtual Mantid::API::IFunction_sptr getGlobalFunction() = 0; virtual void updateMultiDatasetParameters(const Mantid::API::IFunction &fun) = 0; @@ -43,8 +45,8 @@ class EXPORT_OPT_MANTIDQT_COMMON IFunctionBrowser { virtual double getLocalParameterValue(std::string const ¶meterName, int i) const = 0; virtual std::string getLocalParameterTie(std::string const ¶meterName, int i) const = 0; virtual int getNumberOfDatasets() const = 0; - virtual QStringList getDatasetNames() const = 0; - virtual QStringList getDatasetDomainNames() const = 0; + virtual std::vector getDatasetNames() const = 0; + virtual std::vector getDatasetDomainNames() const = 0; virtual void setLocalParameterValue(std::string const ¶meterName, int i, double value) = 0; virtual void setLocalParameterFixed(std::string const ¶meterName, int i, bool fixed) = 0; virtual void setLocalParameterTie(std::string const ¶meterName, int i, std::string const &tie) = 0; diff --git a/qt/widgets/common/inc/MantidQtWidgets/Common/IFunctionModel.h b/qt/widgets/common/inc/MantidQtWidgets/Common/IFunctionModel.h index 9d61514fcbeb..e987ac328c2b 100644 --- a/qt/widgets/common/inc/MantidQtWidgets/Common/IFunctionModel.h +++ b/qt/widgets/common/inc/MantidQtWidgets/Common/IFunctionModel.h @@ -46,8 +46,8 @@ class EXPORT_OPT_MANTIDQT_COMMON IFunctionModel { virtual IFunction_sptr getCurrentFunction() const = 0; virtual void setNumberDomains(int) = 0; virtual void setDatasets(const QList &datasets) = 0; - virtual QStringList getDatasetNames() const = 0; - virtual QStringList getDatasetDomainNames() const = 0; + virtual std::vector getDatasetNames() const = 0; + virtual std::vector getDatasetDomainNames() const = 0; virtual int getNumberDomains() const = 0; virtual int currentDomainIndex() const = 0; virtual void setCurrentDomainIndex(int) = 0; diff --git a/qt/widgets/common/src/EditLocalParameterDialog.cpp b/qt/widgets/common/src/EditLocalParameterDialog.cpp index e99f263f5ce6..d986dc6ce6d6 100644 --- a/qt/widgets/common/src/EditLocalParameterDialog.cpp +++ b/qt/widgets/common/src/EditLocalParameterDialog.cpp @@ -8,6 +8,7 @@ #include "MantidQtWidgets/Common/FunctionMultiDomainPresenter.h" #include "MantidQtWidgets/Common/LocalParameterItemDelegate.h" +#include "MantidQtWidgets/Common/ParseKeyValueString.h" #include #include @@ -35,10 +36,10 @@ namespace MantidQt::MantidWidgets { * @param constraints :: [input] Parameter constraints. */ EditLocalParameterDialog::EditLocalParameterDialog(QWidget *parent, const std::string &parName, - const QStringList &datasetNames, - const QStringList &datasetDomainNames, const QList &values, - const QList &fixes, const QStringList &ties, - const QStringList &constraints) + const std::vector &datasetNames, + const std::vector &datasetDomainNames, + const QList &values, const QList &fixes, + const QStringList &ties, const QStringList &constraints) : MantidDialog(parent), m_parName(parName), m_values(values), m_fixes(fixes), m_ties(std::move(ties)), m_constraints(std::move(constraints)) { assert(values.size() == datasetDomainNames.size()); @@ -58,9 +59,9 @@ EditLocalParameterDialog::EditLocalParameterDialog(QWidget *parent, const std::s * @param datasetNames :: [input] Names of workspaces being fitted. * @param datasetDomainNames :: [input] Names given to the domains being fitted. */ -void EditLocalParameterDialog::doSetup(const std::string &parName, const QStringList &datasetNames, - const QStringList &datasetDomainNames) { - m_logFinder = std::make_unique(datasetNames); +void EditLocalParameterDialog::doSetup(const std::string &parName, const std::vector &datasetNames, + const std::vector &datasetDomainNames) { + m_logFinder = std::make_unique(stdVectorToQStringList(datasetNames)); // Populate list of logs auto *logCombo = m_uiForm.logValueSelector->getLogComboBox(); for (const auto &logName : m_logFinder->getLogNames()) { @@ -78,7 +79,7 @@ void EditLocalParameterDialog::doSetup(const std::string &parName, const QString m_uiForm.tableWidget->insertRow(i); auto cell = new QTableWidgetItem(makeNumber(m_values[i])); m_uiForm.tableWidget->setItem(i, valueColumn, cell); - auto headerItem = new QTableWidgetItem(datasetDomainNames[i]); + auto headerItem = new QTableWidgetItem(QString::fromStdString(datasetDomainNames[i])); m_uiForm.tableWidget->setVerticalHeaderItem(i, headerItem); cell = new QTableWidgetItem(""); auto flags = cell->flags(); diff --git a/qt/widgets/common/src/FitScriptGeneratorView.cpp b/qt/widgets/common/src/FitScriptGeneratorView.cpp index 4058a1bd435b..9e7ca183733b 100644 --- a/qt/widgets/common/src/FitScriptGeneratorView.cpp +++ b/qt/widgets/common/src/FitScriptGeneratorView.cpp @@ -358,8 +358,8 @@ void FitScriptGeneratorView::openEditLocalParameterDialog( std::vector const &domainNames, std::vector const &values, std::vector const &fixes, std::vector const &ties, std::vector const &constraints) { m_editLocalParameterDialog = new EditLocalParameterDialog( - this, parameter, stdVectorToQStringList(workspaceNames), stdVectorToQStringList(domainNames), - convertToQList(values), convertToQList(fixes), stdVectorToQStringList(ties), stdVectorToQStringList(constraints)); + this, parameter, workspaceNames, domainNames, convertToQList(values), convertToQList(fixes), + stdVectorToQStringList(ties), stdVectorToQStringList(constraints)); connect(m_editLocalParameterDialog, SIGNAL(finished(int)), this, SLOT(onEditLocalParameterFinished(int))); diff --git a/qt/widgets/common/src/FunctionBrowser.cpp b/qt/widgets/common/src/FunctionBrowser.cpp index 0c3841544122..39b306e1f390 100644 --- a/qt/widgets/common/src/FunctionBrowser.cpp +++ b/qt/widgets/common/src/FunctionBrowser.cpp @@ -133,10 +133,10 @@ bool FunctionBrowser::hasFunction() const { return m_presenter->hasFunction(); } int FunctionBrowser::getNumberOfDatasets() const { return m_presenter->getNumberOfDatasets(); } /// Get the names of datasets -QStringList FunctionBrowser::getDatasetNames() const { return m_presenter->getDatasetNames(); } +std::vector FunctionBrowser::getDatasetNames() const { return m_presenter->getDatasetNames(); } /// Get the names of the dataset domains -QStringList FunctionBrowser::getDatasetDomainNames() const { return m_presenter->getDatasetDomainNames(); } +std::vector FunctionBrowser::getDatasetDomainNames() const { return m_presenter->getDatasetDomainNames(); } /// Set new number of the datasets /// @param n :: New value for the number of datasets. @@ -145,7 +145,9 @@ void FunctionBrowser::setNumberOfDatasets(int n) { m_presenter->setNumberOfDatas /// Sets the datasets being fitted. They will be displayed by the /// local parameter editing dialog. /// @param datasetNames :: Names of the datasets -void FunctionBrowser::setDatasets(const QStringList &datasetNames) { m_presenter->setDatasets(datasetNames); } +void FunctionBrowser::setDatasets(const std::vector &datasetNames) { + m_presenter->setDatasets(datasetNames); +} /// Sets the datasets being fitted. They will be displayed by the /// local parameter editing dialog. @@ -185,7 +187,7 @@ void FunctionBrowser::removeDatasets(const QList &indices) { m_presenter->r /// Add some datasets to those already set. /// @param names :: A list of names for the new datasets. -void FunctionBrowser::addDatasets(const QStringList &names) { m_presenter->addDatasets(names); } +void FunctionBrowser::addDatasets(const std::vector &names) { m_presenter->addDatasets(names); } /// Return the multidomain function for multi-dataset fitting IFunction_sptr FunctionBrowser::getGlobalFunction() { return m_presenter->getFitFunction(); } diff --git a/qt/widgets/common/src/FunctionModel.cpp b/qt/widgets/common/src/FunctionModel.cpp index c2abdb4711d5..5ea4f4e37167 100644 --- a/qt/widgets/common/src/FunctionModel.cpp +++ b/qt/widgets/common/src/FunctionModel.cpp @@ -273,7 +273,7 @@ void FunctionModel::setNumberDomains(int nDomains) { /// Sets the datasets based on their workspace names. This assumes there is only /// a single spectrum in the workspaces being fitted. /// @param datasetNames :: Names of the workspaces to be fitted. -void FunctionModel::setDatasets(const QStringList &datasetNames) { +void FunctionModel::setDatasets(const std::vector &datasetNames) { QList datasets; for (const auto &datasetName : datasetNames) datasets.append(FunctionModelDataset(datasetName, FunctionModelSpectra("0"))); @@ -293,7 +293,7 @@ void FunctionModel::setDatasets(const QList &datasets) { /// Adds datasets based on their workspace names. This assumes there is only /// a single spectrum in the added workspaces. /// @param datasetNames :: Names of the workspaces to be added. -void FunctionModel::addDatasets(const QStringList &datasetNames) { +void FunctionModel::addDatasets(const std::vector &datasetNames) { for (const auto &datasetName : datasetNames) m_datasets.append(FunctionModelDataset(datasetName, FunctionModelSpectra("0"))); @@ -324,24 +324,26 @@ void FunctionModel::removeDatasets(QList &indices) { /// Returns the workspace names of the datasets. If a dataset has N spectra, /// then the workspace name is multiplied by N. This is required for /// EditLocalParameterDialog. -QStringList FunctionModel::getDatasetNames() const { - QStringList datasetNames; +std::vector FunctionModel::getDatasetNames() const { + std::vector allDatasetNames; for (const auto &dataset : m_datasets) for (auto i = 0u; i < dataset.numberOfSpectra(); ++i) { UNUSED_ARG(i); - datasetNames << dataset.datasetName(); + allDatasetNames.emplace_back(dataset.datasetName()); } - return datasetNames; + return allDatasetNames; } /// Returns names for the domains of each dataset. If a dataset has multiple /// spectra, then a domain name will include the spectrum number of a domain in /// a workspace. This is required for EditLocalParameterDialog. -QStringList FunctionModel::getDatasetDomainNames() const { - QStringList domainNames; - for (const auto &dataset : m_datasets) - domainNames << dataset.domainNames(); - return domainNames; +std::vector FunctionModel::getDatasetDomainNames() const { + std::vector allDomainNames; + for (const auto &dataset : m_datasets) { + auto const domainNames = dataset.domainNames(); + allDomainNames.insert(allDomainNames.end(), domainNames.cbegin(), domainNames.cend()); + } + return allDomainNames; } int FunctionModel::getNumberDomains() const { return static_cast(m_numberDomains); } @@ -499,7 +501,7 @@ void FunctionModel::checkDatasets() { if (numberOfDomains(m_datasets) != static_cast(m_numberDomains)) { m_datasets.clear(); for (auto i = 0u; i < m_numberDomains; ++i) - m_datasets.append(FunctionModelDataset(QString::number(i), FunctionModelSpectra("0"))); + m_datasets.append(FunctionModelDataset(std::to_string(i), FunctionModelSpectra("0"))); } } diff --git a/qt/widgets/common/src/FunctionModelDataset.cpp b/qt/widgets/common/src/FunctionModelDataset.cpp index e3f7ba2dcebd..27d1aebf0fee 100644 --- a/qt/widgets/common/src/FunctionModelDataset.cpp +++ b/qt/widgets/common/src/FunctionModelDataset.cpp @@ -11,7 +11,7 @@ namespace MantidQt::MantidWidgets { -FunctionModelDataset::FunctionModelDataset(QString workspaceName, FunctionModelSpectra spectra) +FunctionModelDataset::FunctionModelDataset(std::string workspaceName, FunctionModelSpectra spectra) : m_workspaceName(std::move(workspaceName)), m_spectra(std::move(spectra)) {} /** @@ -20,16 +20,16 @@ FunctionModelDataset::FunctionModelDataset(QString workspaceName, FunctionModelS * * @returns the names given to each domain (i.e. spectrum) in this dataset. */ -QStringList FunctionModelDataset::domainNames() const { +std::vector FunctionModelDataset::domainNames() const { const auto numOfSpectra = m_spectra.size().value; if (numOfSpectra == 0u) throw std::runtime_error("There are no spectra in this Dataset."); if (numOfSpectra == 1u) - return QStringList(m_workspaceName); + return std::vector{m_workspaceName}; else { - QStringList domains; - for (const auto &spectrum : m_spectra) - domains << m_workspaceName + " (" + QString::number(spectrum.value) + ")"; + std::vector domains; + std::transform(m_spectra.begin(), m_spectra.end(), std::back_inserter(domains), + [&](auto const &spectrum) { return m_workspaceName + " (" + std::to_string(spectrum.value) + ")"; }); return domains; } } diff --git a/qt/widgets/common/src/FunctionMultiDomainPresenter.cpp b/qt/widgets/common/src/FunctionMultiDomainPresenter.cpp index 777be7527c3e..21d5bd6b298e 100644 --- a/qt/widgets/common/src/FunctionMultiDomainPresenter.cpp +++ b/qt/widgets/common/src/FunctionMultiDomainPresenter.cpp @@ -117,17 +117,23 @@ boost::optional FunctionMultiDomainPresenter::currentFunctionIndex( void FunctionMultiDomainPresenter::setNumberOfDatasets(int n) { m_model->setNumberDomains(n); } -void FunctionMultiDomainPresenter::setDatasets(const QStringList &datasetNames) { m_model->setDatasets(datasetNames); } +void FunctionMultiDomainPresenter::setDatasets(const std::vector &datasetNames) { + m_model->setDatasets(datasetNames); +} void FunctionMultiDomainPresenter::setDatasets(const QList &datasets) { m_model->setDatasets(datasets); } -void FunctionMultiDomainPresenter::addDatasets(const QStringList &datasetNames) { m_model->addDatasets(datasetNames); } +void FunctionMultiDomainPresenter::addDatasets(const std::vector &datasetNames) { + m_model->addDatasets(datasetNames); +} -QStringList FunctionMultiDomainPresenter::getDatasetNames() const { return m_model->getDatasetNames(); } +std::vector FunctionMultiDomainPresenter::getDatasetNames() const { return m_model->getDatasetNames(); } -QStringList FunctionMultiDomainPresenter::getDatasetDomainNames() const { return m_model->getDatasetDomainNames(); } +std::vector FunctionMultiDomainPresenter::getDatasetDomainNames() const { + return m_model->getDatasetDomainNames(); +} int FunctionMultiDomainPresenter::getNumberOfDatasets() const { return m_model->getNumberDomains(); } @@ -326,8 +332,7 @@ void FunctionMultiDomainPresenter::editLocalParameter(std::string const ¶met QList fixes; QStringList ties; QStringList constraints; - const int n = domainNames.size(); - for (int i = 0; i < n; ++i) { + for (int i = 0; i < static_cast(domainNames.size()); ++i) { const double value = getLocalParameterValue(parameterName, i); values.push_back(value); const bool fixed = isLocalParameterFixed(parameterName, i);