diff --git a/MantidQt/CustomInterfaces/src/Reflectometry/ReflGenericDataProcessorPresenterFactory.cpp b/MantidQt/CustomInterfaces/src/Reflectometry/ReflGenericDataProcessorPresenterFactory.cpp index 0b6d3a2f61b2a7bd463ad39dbe9106a4dea06991..28e4cd55933304b3b9f18bbffc3ca0f850e79fa6 100644 --- a/MantidQt/CustomInterfaces/src/Reflectometry/ReflGenericDataProcessorPresenterFactory.cpp +++ b/MantidQt/CustomInterfaces/src/Reflectometry/ReflGenericDataProcessorPresenterFactory.cpp @@ -102,8 +102,15 @@ ReflGenericDataProcessorPresenterFactory::create() { "Stitch1DMany", "IvsQ_", std::set<std::string>{"InputWorkspaces", "OutputWorkspace"}); + // Post-processing instructions linking column names to properties of the + // post-processing algorithm + // Key is column name + // Value is property name of the post-processing algorithm + std::map<std::string, std::string> postprocessMap = {{"dQ/Q", "Params"}}; + return Mantid::Kernel::make_unique<GenericDataProcessorPresenter>( - whitelist, preprocessMap, processor, postprocessor, "LoadISISNexus"); + whitelist, preprocessMap, processor, postprocessor, postprocessMap, + "LoadISISNexus"); } } } diff --git a/MantidQt/MantidWidgets/inc/MantidQtMantidWidgets/DataProcessorUI/GenericDataProcessorPresenter.h b/MantidQt/MantidWidgets/inc/MantidQtMantidWidgets/DataProcessorUI/GenericDataProcessorPresenter.h index d2f1d5843d11b0ac75ff8a3abe0c3b6915bc1f1c..fc6883de2303be7431ea83ce6304920427d793a2 100644 --- a/MantidQt/MantidWidgets/inc/MantidQtMantidWidgets/DataProcessorUI/GenericDataProcessorPresenter.h +++ b/MantidQt/MantidWidgets/inc/MantidQtMantidWidgets/DataProcessorUI/GenericDataProcessorPresenter.h @@ -60,6 +60,8 @@ public: preprocessMap, const DataProcessorProcessingAlgorithm &processor, const DataProcessorPostprocessingAlgorithm &postprocessor, + const std::map<std::string, std::string> &postprocessMap = + std::map<std::string, std::string>(), const std::string &loader = "Load"); // Constructor: no pre-processing, post-processing GenericDataProcessorPresenter( @@ -124,6 +126,8 @@ private: DataProcessorProcessingAlgorithm m_processor; // Post-processing algorithm DataProcessorPostprocessingAlgorithm m_postprocessor; + // Post-processing map + std::map<std::string, std::string> m_postprocessMap; // Loader std::string m_loader; // A boolean indicating whether a post-processing algorithm has been defined diff --git a/MantidQt/MantidWidgets/src/DataProcessorUI/GenericDataProcessorPresenter.cpp b/MantidQt/MantidWidgets/src/DataProcessorUI/GenericDataProcessorPresenter.cpp index 60daa5fb87046a219565aa4596fc9c51b1fdd91a..57158352343d44c3faa22205bde63dba53170af2 100644 --- a/MantidQt/MantidWidgets/src/DataProcessorUI/GenericDataProcessorPresenter.cpp +++ b/MantidQt/MantidWidgets/src/DataProcessorUI/GenericDataProcessorPresenter.cpp @@ -42,6 +42,8 @@ namespace MantidWidgets { * @param processor : A DataProcessorProcessingAlgorithm * @param postprocessor : A DataProcessorPostprocessingAlgorithm * workspaces +* @param postprocessMap : A map containing instructions for post-processing. +* This map links column name to properties of the post-processing algorithm * @param loader : The algorithm responsible for loading data */ GenericDataProcessorPresenter::GenericDataProcessorPresenter( @@ -50,11 +52,13 @@ GenericDataProcessorPresenter::GenericDataProcessorPresenter( preprocessMap, const DataProcessorProcessingAlgorithm &processor, const DataProcessorPostprocessingAlgorithm &postprocessor, + const std::map<std::string, std::string> &postprocessMap, const std::string &loader) : WorkspaceObserver(), m_view(nullptr), m_progressView(nullptr), m_whitelist(whitelist), m_preprocessMap(preprocessMap), - m_processor(processor), m_postprocessor(postprocessor), m_loader(loader), - m_postprocess(true), m_mainPresenter(), m_tableDirty(false) { + m_processor(processor), m_postprocessor(postprocessor), + m_postprocessMap(postprocessMap), m_loader(loader), m_postprocess(true), + m_mainPresenter(), m_tableDirty(false) { // Column Options must be added to the whitelist m_whitelist.addElement("Options", "Options", @@ -329,6 +333,21 @@ void GenericDataProcessorPresenter::postProcessGroup( } } + // Options specified via post-process map + for (const auto &prop : m_postprocessMap) { + const std::string propName = prop.second; + const std::string propValueStr = + groupData.begin()->second[m_whitelist.colIndexFromColName(prop.first)]; + if (!propValueStr.empty()) { + // Warning: we take minus the value of the properties because in + // Reflectometry this property refers to the rebin step, and they want a + // logarithmic binning. If other technique areas need to use a + // post-process map we'll need to re-think how to do this. + double propValue = boost::lexical_cast<double>(propValueStr); + alg->setPropertyValue(propName, std::to_string(-propValue)); + } + } + alg->execute(); if (!alg->isExecuted()) diff --git a/MantidQt/MantidWidgets/test/DataProcessorUI/GenericDataProcessorPresenterTest.h b/MantidQt/MantidWidgets/test/DataProcessorUI/GenericDataProcessorPresenterTest.h index 8654fc169506182d7ddf1eeae10ffce87e8581a5..e3b6fb9513aa82098bbee45230303075db428a05 100644 --- a/MantidQt/MantidWidgets/test/DataProcessorUI/GenericDataProcessorPresenterTest.h +++ b/MantidQt/MantidWidgets/test/DataProcessorUI/GenericDataProcessorPresenterTest.h @@ -3142,6 +3142,92 @@ public: std::map<int, std::vector<std::string>>()), std::runtime_error); } + + void testPostprocessMap() { + NiceMock<MockDataProcessorView> mockDataProcessorView; + NiceMock<MockProgressableView> mockProgress; + NiceMock<MockMainPresenter> mockMainPresenter; + + std::map<std::string, std::string> postprocesssMap = {{"dQ/Q", "Params"}}; + GenericDataProcessorPresenter presenter( + createReflectometryWhiteList(), createReflectometryPreprocessMap(), + createReflectometryProcessor(), createReflectometryPostprocessor(), + postprocesssMap); + presenter.acceptViews(&mockDataProcessorView, &mockProgress); + presenter.accept(&mockMainPresenter); + + // Open a table + createPrefilledWorkspace("TestWorkspace", presenter.getWhiteList()); + EXPECT_CALL(mockDataProcessorView, getWorkspaceToOpen()) + .Times(1) + .WillRepeatedly(Return("TestWorkspace")); + presenter.notify(DataProcessorPresenter::OpenTableFlag); + + createTOFWorkspace("12345", "12345"); + createTOFWorkspace("12346", "12346"); + + std::set<int> grouplist; + grouplist.insert(0); + + // We should not receive any errors + EXPECT_CALL(mockMainPresenter, giveUserCritical(_, _)).Times(0); + + // The user hits the "process" button with the first group selected + EXPECT_CALL(mockDataProcessorView, getSelectedChildren()) + .Times(1) + .WillRepeatedly(Return(std::map<int, std::set<int>>())); + EXPECT_CALL(mockDataProcessorView, getSelectedParents()) + .Times(1) + .WillRepeatedly(Return(grouplist)); + EXPECT_CALL(mockMainPresenter, getPreprocessingOptions()) + .Times(2) + .WillRepeatedly(Return(std::map<std::string, std::string>())); + EXPECT_CALL(mockMainPresenter, getProcessingOptions()) + .Times(2) + .WillRepeatedly(Return("")); + EXPECT_CALL(mockMainPresenter, getPostprocessingOptions()) + .Times(1) + .WillOnce(Return("Params='-0.10'")); + EXPECT_CALL(mockDataProcessorView, getEnableNotebook()) + .Times(1) + .WillRepeatedly(Return(false)); + EXPECT_CALL(mockDataProcessorView, requestNotebookPath()).Times(0); + + presenter.notify(DataProcessorPresenter::ProcessFlag); + + // Check output workspace was stitched with params = '-0.04' + TS_ASSERT( + AnalysisDataService::Instance().doesExist("IvsQ_TOF_12345_TOF_12346")); + + MatrixWorkspace_sptr out = + AnalysisDataService::Instance().retrieveWS<MatrixWorkspace>( + "IvsQ_TOF_12345_TOF_12346"); + TSM_ASSERT_DELTA( + "Logarithmic rebinning should have been applied, with param 0.04", + out->x(0)[0], 0.100, 1e-5); + TSM_ASSERT_DELTA( + "Logarithmic rebinning should have been applied, with param 0.04", + out->x(0)[1], 0.104, 1e-5); + TSM_ASSERT_DELTA( + "Logarithmic rebinning should have been applied, with param 0.04", + out->x(0)[2], 0.10816, 1e-5); + TSM_ASSERT_DELTA( + "Logarithmic rebinning should have been applied, with param 0.04", + out->x(0)[3], 0.11248, 1e-5); + + // Tidy up + AnalysisDataService::Instance().remove("TestWorkspace"); + AnalysisDataService::Instance().remove("IvsQ_TOF_12345"); + AnalysisDataService::Instance().remove("IvsLam_TOF_12345"); + AnalysisDataService::Instance().remove("12345"); + AnalysisDataService::Instance().remove("IvsQ_TOF_12346"); + AnalysisDataService::Instance().remove("IvsLam_TOF_12346"); + AnalysisDataService::Instance().remove("12346"); + AnalysisDataService::Instance().remove("IvsQ_TOF_12345_TOF_12346"); + + TS_ASSERT(Mock::VerifyAndClearExpectations(&mockDataProcessorView)); + TS_ASSERT(Mock::VerifyAndClearExpectations(&mockMainPresenter)); + } }; #endif /* MANTID_MANTIDWIDGETS_GENERICDATAPROCESSORPRESENTERTEST_H */ diff --git a/docs/source/interfaces/ISIS_Reflectometry.rst b/docs/source/interfaces/ISIS_Reflectometry.rst index 362f7bd97fa2217631106d1d2932e1190226a88f..7a7527eaf3d22b7b31674af35a7265838e7484ae 100644 --- a/docs/source/interfaces/ISIS_Reflectometry.rst +++ b/docs/source/interfaces/ISIS_Reflectometry.rst @@ -61,9 +61,7 @@ In addition the table workspace should be opened as well and the processing tabl Let's process the first group, which consists of the first two rows of the table (13460 and 13462). The simplest way to do this is simply to select the -two rows we want to process, and then click on **Process**. Note that for the reduction -to be successful, at least the bin size must be specified to :ref:`Stitch1DMany <algm-Stitch1DMany>`, -in the options tab (e.g. Params="-0.04"). +two rows we want to process, and then click on **Process**. .. tip:: If you receive an error, consult the `Troubleshooting`_ section of this document for guidance on fixing it. @@ -528,10 +526,12 @@ When I try to process I get an error: "Error encountered while stitching group . ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ This occurs when Mantid is unable to stitch a group. Please check that at you have -specified at least the bin width in the *Stitch1DMany* text box. To specify the bin width please -use the *Params* input property like this: ``Params="-0.03"`` (you may want to replace -``0.03`` with a bin size suitable for your reduction). Note that the "-" sign will produce -a logarithmic binning in the stitched workspace. For linear binning, use ``Params="0.03"``. +specified at least the bin width. This can be done either by setting a value in column +**dQ/Q** before processing the data, or by using the *Stitch1DMany* text +box in the **Settings** tab to provide the *Params* input property like this: +``Params="-0.03"`` (you may want to replace ``0.03`` with a bin size suitable for +your reduction). Note that the "-" sign in this case will produce a logarithmic binning in the +stitched workspace. For linear binning, use ``Params="0.03"``. When I try to process I get an error: "Invalid key value pair, '...'" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ diff --git a/docs/source/release/v3.9.0/reflectometry.rst b/docs/source/release/v3.9.0/reflectometry.rst index 1c41feaaaafde8117be5a5036f3daaf690b8a0a2..cb4ecc20fe2c0cef5fd250e099e71170d779d55a 100644 --- a/docs/source/release/v3.9.0/reflectometry.rst +++ b/docs/source/release/v3.9.0/reflectometry.rst @@ -18,8 +18,9 @@ ISIS Reflectometry (Polref) ########################### - Settings tab now displays individual global options for experiment and instrument settings. -- Documentation regarding the interface has been updated accordingly. - New 'Save ASCII' tab added, similar in function and purpose to the 'Save Workspaces' window accessible from Interfaces->ISIS Reflectometry->File->Save Workspaces. +- Column :literal:`dQ/Q` is used as the rebin parameter to stitch workspaces. +- Documentation regarding the interface has been updated accordingly. ISIS Reflectometry ##################