From e577396e8d881816e48fca37ce236bfde44eb87f Mon Sep 17 00:00:00 2001 From: Tom Perkins <thomas.perkins@stfc.ac.uk> Date: Mon, 11 Jul 2016 14:08:28 +0100 Subject: [PATCH] Handle fitted workspaces after sequential fit Process workspaces after a combined sequential fit over runs in which each run involves a simultaneous fit over groups/periods. Results table should work properly. re #15518 --- .../Muon/MuonAnalysisFitDataPresenter.h | 6 +- .../Muon/MuonSequentialFitDialog.h | 6 ++ .../src/Muon/MuonAnalysisFitDataPresenter.cpp | 35 +++++--- .../src/Muon/MuonSequentialFitDialog.cpp | 80 ++++++++++++++++--- 4 files changed, 101 insertions(+), 26 deletions(-) diff --git a/MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/Muon/MuonAnalysisFitDataPresenter.h b/MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/Muon/MuonAnalysisFitDataPresenter.h index 6a69243cc3a..16c91c50494 100644 --- a/MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/Muon/MuonAnalysisFitDataPresenter.h +++ b/MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/Muon/MuonAnalysisFitDataPresenter.h @@ -86,9 +86,11 @@ public: /// Create workspaces to fit void createWorkspacesToFit(const std::vector<std::string> &names) const; /// Rename fit workspaces, add logs and generate params table - void handleFittedWorkspaces(const std::string &groupName) const; + void handleFittedWorkspaces(const std::string &baseName, + const std::string &groupName = "") const; /// Extract workspaces from group and move up a level - void extractFittedWorkspaces(const std::string &groupName) const; + void extractFittedWorkspaces(const std::string &baseName, + const std::string &groupName = "") const; public slots: /// Transforms fit results when a simultaneous fit finishes diff --git a/MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/Muon/MuonSequentialFitDialog.h b/MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/Muon/MuonSequentialFitDialog.h index 83dfd690ebb..55b2a439f21 100644 --- a/MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/Muon/MuonSequentialFitDialog.h +++ b/MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/Muon/MuonSequentialFitDialog.h @@ -77,6 +77,12 @@ private: /// Helper function to create new item for Diagnosis table QTableWidgetItem *createTableWidgetItem(const QString &text); + /// Reorganise workspaces after fit of one run finished + void finishAfterRun(const std::string &labelGroupName, + const Mantid::API::IAlgorithm_sptr &fitAlg, + bool simultaneous, + const Mantid::API::MatrixWorkspace_sptr &firstWS) const; + // -- MEMBER VARIABLES ----------------------------------------------- /// UI form diff --git a/MantidQt/CustomInterfaces/src/Muon/MuonAnalysisFitDataPresenter.cpp b/MantidQt/CustomInterfaces/src/Muon/MuonAnalysisFitDataPresenter.cpp index f044ba89943..96eed5a5de8 100644 --- a/MantidQt/CustomInterfaces/src/Muon/MuonAnalysisFitDataPresenter.cpp +++ b/MantidQt/CustomInterfaces/src/Muon/MuonAnalysisFitDataPresenter.cpp @@ -418,15 +418,17 @@ void MuonAnalysisFitDataPresenter::handleFitFinished( /** * Rename fitted workspaces so they can be linked to the input and found by the * results table generation code. Add special logs and generate params table. - * @param groupName :: [input] Name of group that workspaces belong to + * @param baseName :: [input] Base name for workspaces + * @param groupName :: [input] Name of group that workspaces belong to. Leave + * empty to be the same as baseName (usual case). */ void MuonAnalysisFitDataPresenter::handleFittedWorkspaces( - const std::string &groupName) const { + const std::string &baseName, const std::string &groupName) const { AnalysisDataServiceImpl &ads = AnalysisDataService::Instance(); const auto resultsGroup = - ads.retrieveWS<WorkspaceGroup>(groupName + "_Workspaces"); + ads.retrieveWS<WorkspaceGroup>( baseName + "_Workspaces"); const auto paramsTable = - ads.retrieveWS<ITableWorkspace>(groupName + "_Parameters"); + ads.retrieveWS<ITableWorkspace>(baseName + "_Parameters"); if (resultsGroup && paramsTable) { const size_t offset = paramsTable->rowCount() - resultsGroup->size(); for (size_t i = 0; i < resultsGroup->size(); i++) { @@ -438,7 +440,7 @@ void MuonAnalysisFitDataPresenter::handleFittedWorkspaces( addSpecialLogs(oldName, wsDetails); // Generate new name and rename workspace std::ostringstream newName; - newName << groupName << "_" << wsDetails.label << "_" + newName << baseName << "_" << wsDetails.label << "_" << wsDetails.itemName << "_" << wsDetails.periods; ads.rename(oldName, newName.str() + "_Workspace"); // Generate new parameters table for this dataset @@ -446,28 +448,37 @@ void MuonAnalysisFitDataPresenter::handleFittedWorkspaces( if (fitTable) { const std::string fitTableName = newName.str() + "_Parameters"; ads.add(fitTableName, fitTable); - ads.addToGroup(groupName, fitTableName); + // If user has specified a group to add to, add to that. + // Otherwise the group is called the same thing as the base name. + const std::string groupToAddTo = + groupName.empty() ? baseName : groupName; + ads.addToGroup(groupToAddTo, fitTableName); } } // Now that we have split parameters table, can delete it - ads.remove(groupName + "_Parameters"); + ads.remove(baseName + "_Parameters"); } } /** * Moves all workspaces in group "groupName_Workspaces" up a level into * "groupName" - * @param groupName :: [input] Name of upper group e.g. "MuonSimulFit_Label" + * @param baseName :: [input] Base name for workspaces + * @param groupName :: [input] Name of upper group e.g. "MuonSimulFit_Label". If + * empty, use same as baseName. */ void MuonAnalysisFitDataPresenter::extractFittedWorkspaces( - const std::string &groupName) const { + const std::string &baseName, const std::string &groupName) const { AnalysisDataServiceImpl &ads = AnalysisDataService::Instance(); - const std::string resultsGroupName = groupName + "_Workspaces"; + const std::string resultsGroupName = baseName + "_Workspaces"; const auto resultsGroup = ads.retrieveWS<WorkspaceGroup>(resultsGroupName); - if (ads.doesExist(groupName) && resultsGroup) { + // If user has specified a group to add to, add to that. + // Otherwise the group is called the same thing as the base name. + const std::string groupToAddTo = groupName.empty() ? baseName : groupName; + if (ads.doesExist(groupToAddTo) && resultsGroup) { for (const auto &name : resultsGroup->getNames()) { ads.removeFromGroup(resultsGroupName, name); - ads.addToGroup(groupName, name); + ads.addToGroup(groupToAddTo, name); } ads.remove(resultsGroupName); // should be empty now } diff --git a/MantidQt/CustomInterfaces/src/Muon/MuonSequentialFitDialog.cpp b/MantidQt/CustomInterfaces/src/Muon/MuonSequentialFitDialog.cpp index fddf4fe7ecb..fddef594562 100644 --- a/MantidQt/CustomInterfaces/src/Muon/MuonSequentialFitDialog.cpp +++ b/MantidQt/CustomInterfaces/src/Muon/MuonSequentialFitDialog.cpp @@ -4,6 +4,8 @@ #include "MantidAPI/AlgorithmProxy.h" #include "MantidAPI/ITableWorkspace.h" #include "MantidAPI/MatrixWorkspace.h" +#include "MantidAPI/TableRow.h" +#include "MantidAPI/WorkspaceGroup.h" #include "MantidAPI/WorkspaceProperty.h" #include "MantidGeometry/Instrument.h" #include "MantidQtCustomInterfaces/Muon/MuonAnalysisFitDataPresenter.h" @@ -471,22 +473,15 @@ void MuonSequentialFitDialog::continueFit() { break; } + // Copy log values and group created fit workspaces + finishAfterRun(labelGroupName, fit, datasetsPerRun > 1, matrixWS); + // If fit was simultaneous, transform results if (datasetsPerRun > 1) { - m_dataPresenter->handleFittedWorkspaces(wsBaseName); - m_dataPresenter->extractFittedWorkspaces(wsBaseName); + m_dataPresenter->handleFittedWorkspaces(wsBaseName, labelGroupName); + m_dataPresenter->extractFittedWorkspaces(wsBaseName, labelGroupName); } - // Make sure created fit workspaces end up in the group - // TODO: this really should use loop - ads.addToGroup(labelGroupName, wsBaseName + "_NormalisedCovarianceMatrix"); - ads.addToGroup(labelGroupName, wsBaseName + "_Parameters"); - ads.addToGroup(labelGroupName, wsBaseName + "_Workspace"); - - // Copy log values - auto fitWs = ads.retrieveWS<MatrixWorkspace>(wsBaseName + "_Workspace"); - fitWs->copyExperimentInfoFrom(matrixWS.get()); - // Add information about the fit to the diagnosis table addDiagnosisEntry(runTitle, fit->getProperty("OutputChi2OverDof"), functionToFit); @@ -499,6 +494,67 @@ void MuonSequentialFitDialog::continueFit() { setState(Stopped); } +/** + * Handle reorganising workspaces after fit of a single run has finished + * Group output together and copy log values + * @param labelGroupName :: [input] Label for group + * @param fitAlg :: [input] Pointer to fit algorithm + * @param simultaneous :: [input] Whether several groups/periods were fitted + * simultaneously or not + * @param firstWS :: [input] Pointer to first input workspace (to copy logs + * from) + */ +void MuonSequentialFitDialog::finishAfterRun( + const std::string &labelGroupName, const IAlgorithm_sptr &fitAlg, + bool simultaneous, const MatrixWorkspace_sptr &firstWS) const { + auto &ads = AnalysisDataService::Instance(); + const std::string wsBaseName = fitAlg->getPropertyValue("Output"); + if (simultaneous) { + // copy logs + auto fitWSGroup = + ads.retrieveWS<WorkspaceGroup>(wsBaseName + "_Workspaces"); + for (size_t i = 0; i < fitWSGroup->size(); i++) { + auto fitWs = + boost::dynamic_pointer_cast<MatrixWorkspace>(fitWSGroup->getItem(i)); + if (fitWs) { + fitWs->copyExperimentInfoFrom(firstWS.get()); + } + } + // insert workspace names into table + try { + const std::string paramTableName = + fitAlg->getProperty("OutputParameters"); + const auto paramTable = ads.retrieveWS<ITableWorkspace>(paramTableName); + if (paramTable) { + Mantid::API::TableRow f0Row = paramTable->appendRow(); + f0Row << "f0=" + fitAlg->getPropertyValue("InputWorkspace") << 0.0 + << 0.0; + for (size_t i = 1; i < fitWSGroup->size(); i++) { + const std::string suffix = boost::lexical_cast<std::string>(i); + const auto wsName = + fitAlg->getPropertyValue("InputWorkspace_" + suffix); + Mantid::API::TableRow row = paramTable->appendRow(); + row << "f" + suffix + "=" + wsName << 0.0 << 0.0; + } + } + } catch (const Mantid::Kernel::Exception::NotFoundError &) { + // Not a fatal error, but shouldn't happen + g_log.warning( + "Could not find output parameters table for simultaneous fit"); + } + // Group output together + ads.addToGroup(labelGroupName, wsBaseName + "_NormalisedCovarianceMatrix"); + ads.addToGroup(labelGroupName, wsBaseName + "_Parameters"); + ads.addToGroup(labelGroupName, wsBaseName + "_Workspaces"); + } else { + ads.addToGroup(labelGroupName, wsBaseName + "_NormalisedCovarianceMatrix"); + ads.addToGroup(labelGroupName, wsBaseName + "_Parameters"); + ads.addToGroup(labelGroupName, wsBaseName + "_Workspace"); + auto fitWs = ads.retrieveWS<MatrixWorkspace>(wsBaseName + "_Workspace"); + fitWs->copyExperimentInfoFrom(firstWS.get()); + } +} + /** * Stop fitting process. */ -- GitLab