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