From 423544e43ca427d2c8f71bcc8c99f009f91666dc Mon Sep 17 00:00:00 2001 From: Owen Arnold <owen.arnold@stfc.ac.uk> Date: Tue, 19 Jun 2012 10:42:20 +0100 Subject: [PATCH] refs #5484. Works with normalisation option. --- .../MDEvents/src/QueryMDWorkspace.cpp | 80 +++++++++++++++++-- .../MDEvents/test/QueryMDWorkspaceTest.h | 79 +++++++++++++++++- 2 files changed, 153 insertions(+), 6 deletions(-) diff --git a/Code/Mantid/Framework/MDEvents/src/QueryMDWorkspace.cpp b/Code/Mantid/Framework/MDEvents/src/QueryMDWorkspace.cpp index ea4cd952a91..08b35a2e417 100644 --- a/Code/Mantid/Framework/MDEvents/src/QueryMDWorkspace.cpp +++ b/Code/Mantid/Framework/MDEvents/src/QueryMDWorkspace.cpp @@ -20,6 +20,7 @@ The table workspace can be used as a basis for plotting within MantidPlot. #include "MantidAPI/TableRow.h" #include "MantidKernel/EnabledWhenProperty.h" #include "MantidKernel/BoundedValidator.h" +#include "MantidKernel/ListValidator.h" #include "../inc/MantidMDEvents/MDEventWorkspace.h" #include "../inc/MantidMDEvents/MDEventFactory.h" @@ -34,6 +35,56 @@ namespace MDEvents // Register the class into the algorithm factory DECLARE_ALGORITHM(QueryMDWorkspace) + /** + Non-member defining the no normalisation option. + @return no normalisation option. + */ + std::string noNormalisationOption() + { + return "none"; + } + + /** + Non-member defining the volume normalisation option. + @return volume normalisation option. + */ + std::string volumeNormalisationOption() + { + return "volume"; + } + + /** + Non-member defining the number of events normalisation option. + @return number of events normalisation. + */ + std::string numberOfEventsNormalisationOption() + { + return "number of events"; + } + + /** + Non-member method to interpret an normalisation option. + @param strNormalisation: string normalisation property value. + @return MDNormalisation option. + */ + Mantid::API::MDNormalization whichNormalisation(const std::string& strNormalisation) + { + Mantid::API::MDNormalization requestedNormalisation = Mantid::API::NoNormalization; + if(strNormalisation == noNormalisationOption()) + { + requestedNormalisation = Mantid::API::NoNormalization;; + } + else if(strNormalisation == volumeNormalisationOption()) + { + requestedNormalisation = Mantid::API::VolumeNormalization; + } + else + { + requestedNormalisation = Mantid::API::NumEventsNormalization; + } + return requestedNormalisation; + } + //---------------------------------------------------------------------------------------------- /** Constructor */ @@ -69,6 +120,18 @@ namespace MDEvents declareProperty(new PropertyWithValue<int>("MaximumRows", 100000, boost::make_shared<BoundedValidator<int>>(), Direction::Input), "The number of neighbours to utilise. Defaults to 100000."); setPropertySettings("MaximumRows", new EnabledWhenProperty("LimitRows", IS_DEFAULT)); + std::vector<std::string> propOptions; + propOptions.push_back(noNormalisationOption()); + propOptions.push_back(volumeNormalisationOption()); + propOptions.push_back(numberOfEventsNormalisationOption()); + + declareProperty("Normalisation", "none", boost::make_shared<StringListValidator>(propOptions), + "What normalisation do you wish to apply" + " none: No normalisation.\n" + " volume: Normalise by the volume.\n" + " number of events: Normalise by the number of events." + ); + declareProperty(new WorkspaceProperty<ITableWorkspace>("BoxDataTable","",Direction::Output, Mantid::API::PropertyMode::Optional), "Optional output data table with MDEventWorkspace-specific box data."); @@ -149,11 +212,17 @@ namespace MDEvents /// Run the algorithm void QueryMDWorkspace::exec() { + //Extract the required normalisation. + std::string strNormalisation = getPropertyValue("Normalisation"); + MDNormalization requestedNormalisation = whichNormalisation(strNormalisation); + IMDWorkspace_sptr input = getProperty("InputWorkspace"); // Define a table workspace with a specific column schema. ITableWorkspace_sptr output = WorkspaceFactory::Instance().createTable(); - output->addColumn("double", "Signal"); - output->addColumn("double", "Error"); + const std::string signalColumnName = "Signal/" + strNormalisation; + const std::string errorColumnName = "Error/" + strNormalisation; + output->addColumn("double", signalColumnName); + output->addColumn("double", errorColumnName); output->addColumn("int", "Number of Events"); const size_t ndims = input->getNumDims(); @@ -167,11 +236,12 @@ namespace MDEvents } //Magic numbers required to configure the Y axis. - output->getColumn("Signal")->setPlotType(2); - output->getColumn("Error")->setPlotType(5); + output->getColumn(signalColumnName)->setPlotType(2); + output->getColumn(errorColumnName)->setPlotType(5); IMDIterator* it = input->createIterator(); + it->setNormalization(requestedNormalisation); bool bLimitRows = getProperty("LimitRows"); int maxRows = 0; @@ -189,7 +259,7 @@ namespace MDEvents size_t cellIndex = 0; output->appendRow(); output->cell<double>(rowCounter, cellIndex++) = it->getNormalizedSignal(); - output->cell<double>(rowCounter, cellIndex++) = std::sqrt(it->getNormalizedError()); + output->cell<double>(rowCounter, cellIndex++) = it->getNormalizedError(); output->cell<int>(rowCounter, cellIndex++) = int(it->getNumEvents()); VMD center = it->getCenter(); for(size_t index = 0; index < ndims; ++index) diff --git a/Code/Mantid/Framework/MDEvents/test/QueryMDWorkspaceTest.h b/Code/Mantid/Framework/MDEvents/test/QueryMDWorkspaceTest.h index 13f4137ebf7..3a89e63963b 100644 --- a/Code/Mantid/Framework/MDEvents/test/QueryMDWorkspaceTest.h +++ b/Code/Mantid/Framework/MDEvents/test/QueryMDWorkspaceTest.h @@ -10,10 +10,12 @@ #include "MantidTestHelpers/MDEventsTestHelper.h" #include "MantidMDEvents/QueryMDWorkspace.h" #include "MantidAPI/ITableWorkspace.h" +#include "MantidDataObjects/TableWorkspace.h" using namespace Mantid; using namespace Mantid::MDEvents; using namespace Mantid::API; +using namespace Mantid::DataObjects; class QueryMDWorkspaceTest : public CxxTest::TestSuite { @@ -24,7 +26,19 @@ public: static void destroySuite( QueryMDWorkspaceTest *suite ) { delete suite; } - void testCheckInputs() + void checkInputs(std::string strNormalisation) + { + MDEventWorkspace3Lean::sptr in_ws = MDEventsTestHelper::makeMDEW<3>(10, -10.0, 20.0, 3); + QueryMDWorkspace query; + query.initialize(); + query.setRethrows(true); + query.setProperty("InputWorkspace", in_ws); + query.setProperty("OutputWorkspace", "QueryWS"); + query.setProperty("Normalisation", "none"); + TSM_ASSERT_EQUALS("Invalid property setup", true, query.validateProperties()); + } + + void testDefaultInputs() { MDEventWorkspace3Lean::sptr in_ws = MDEventsTestHelper::makeMDEW<3>(10, -10.0, 20.0, 3); QueryMDWorkspace query; @@ -36,6 +50,23 @@ public: const int expectedRowLimit = 100000; const int actualRowLimit = query.getProperty("MaximumRows"); TSM_ASSERT_EQUALS("Wrong default number of rows", expectedRowLimit, actualRowLimit); + std::string defaultNormalisation = query.getProperty("Normalisation"); + TSM_ASSERT_EQUALS("Wrong default normalisation", "none", defaultNormalisation); + } + + void testCheckInputsWithNoNormalisation() + { + checkInputs("none"); + } + + void testCheckInputsWithVolumeNormalisation() + { + checkInputs("volume"); + } + + void testCheckInputsWithNumberOfEventsNormalisation() + { + checkInputs("number of events"); } void testExecution() @@ -49,6 +80,52 @@ public: TSM_ASSERT("Did not execute", query.isExecuted()); } + void testDifferentNormalisation() + { + MDEventWorkspace3Lean::sptr in_ws = MDEventsTestHelper::makeMDEW<3>(10, -10.0, 20.0, 3); + boost::shared_ptr<IMDIterator> it(in_ws->createIterator()); + + QueryMDWorkspace A; + A.initialize(); + A.setProperty("InputWorkspace", in_ws); + A.setPropertyValue("OutputWorkspace", "QueryWS_A"); + A.setPropertyValue("Normalisation", "none"); //Not normalising + A.execute(); + + QueryMDWorkspace B; + B.initialize(); + B.setProperty("InputWorkspace", in_ws); + B.setPropertyValue("OutputWorkspace", "QueryWS_B"); + B.setPropertyValue("Normalisation", "number of events"); //Normalising by n events + B.execute(); + + AnalysisDataServiceImpl& ADS = AnalysisDataService::Instance(); + + TableWorkspace_sptr queryA = boost::dynamic_pointer_cast<TableWorkspace>(ADS.retrieve("QueryWS_A")); + TableWorkspace_sptr queryB = boost::dynamic_pointer_cast<TableWorkspace>(ADS.retrieve("QueryWS_B")); + + TS_ASSERT_EQUALS(queryA->rowCount(), queryB->rowCount()); + + for(size_t i = 0; i < queryA->rowCount(); ++i) + { + it->next(); + TSM_ASSERT("The iterator should be valid over the range of table rows it was used to create.", it->valid()); + + double signalNotNormalised = queryA->cell<double>(i, 0); + double signalNormalisedByNumEvents = queryB->cell<double>(i, 0); + double errorNotNormalised = queryA->cell<double>(i, 1); + double errorNormalisedByNumEvents = queryB->cell<double>(i, 1); + const size_t nEvents = it->getNumEvents(); + + //Compare each signal and error result. + TS_ASSERT_DELTA(signalNotNormalised, signalNormalisedByNumEvents*nEvents, 0.0001); + TS_ASSERT_DELTA(errorNotNormalised, errorNormalisedByNumEvents*nEvents, 0.0001); + } + + ADS.remove("QueryWS_A"); + ADS.remove("QueryWS_B"); + } + void testExecution_BoxData() { MDEventWorkspace3Lean::sptr in_ws = MDEventsTestHelper::makeMDEW<3>(10, -10.0, 20.0, 3); -- GitLab