From 25d01d44ed6e395e9e16c20c0f3d824770034bf1 Mon Sep 17 00:00:00 2001
From: Russell Taylor <taylorrj@ornl.gov>
Date: Thu, 26 Jul 2012 17:47:05 -0400
Subject: [PATCH] Re #5572. Very quick first implementation of FilterPeaks.

---
 Code/Mantid/Framework/Crystal/CMakeLists.txt  |   3 +
 .../Crystal/inc/MantidCrystal/FilterPeaks.h   |  56 +++++++
 .../Framework/Crystal/src/FilterPeaks.cpp     | 145 ++++++++++++++++++
 .../Framework/Crystal/test/FilterPeaksTest.h  |  63 ++++++++
 4 files changed, 267 insertions(+)
 create mode 100644 Code/Mantid/Framework/Crystal/inc/MantidCrystal/FilterPeaks.h
 create mode 100644 Code/Mantid/Framework/Crystal/src/FilterPeaks.cpp
 create mode 100644 Code/Mantid/Framework/Crystal/test/FilterPeaksTest.h

diff --git a/Code/Mantid/Framework/Crystal/CMakeLists.txt b/Code/Mantid/Framework/Crystal/CMakeLists.txt
index b0c9781ca49..0d43c9c3f8b 100644
--- a/Code/Mantid/Framework/Crystal/CMakeLists.txt
+++ b/Code/Mantid/Framework/Crystal/CMakeLists.txt
@@ -5,6 +5,7 @@ set ( SRC_FILES
 	src/CentroidPeaks.cpp
 	src/CombinePeaksWorkspaces.cpp
 	src/DiffPeaksWorkspaces.cpp
+	src/FilterPeaks.cpp
 	src/FindSXPeaks.cpp
 	src/FindUBUsingFFT.cpp
 	src/FindUBUsingIndexedPeaks.cpp
@@ -45,6 +46,7 @@ set ( INC_FILES
 	inc/MantidCrystal/CentroidPeaks.h
 	inc/MantidCrystal/CombinePeaksWorkspaces.h
 	inc/MantidCrystal/DiffPeaksWorkspaces.h
+	inc/MantidCrystal/FilterPeaks.h
 	inc/MantidCrystal/FindSXPeaks.h
 	inc/MantidCrystal/FindUBUsingFFT.h
 	inc/MantidCrystal/FindUBUsingIndexedPeaks.h
@@ -85,6 +87,7 @@ set ( TEST_FILES
 	test/CentroidPeaksTest.h
 	test/CombinePeaksWorkspacesTest.h
 	test/DiffPeaksWorkspacesTest.h
+	test/FilterPeaksTest.h
 	test/FindSXPeaksTest.h
 	test/FindUBUsingFFTTest.h
 	test/FindUBUsingIndexedPeaksTest.h
diff --git a/Code/Mantid/Framework/Crystal/inc/MantidCrystal/FilterPeaks.h b/Code/Mantid/Framework/Crystal/inc/MantidCrystal/FilterPeaks.h
new file mode 100644
index 00000000000..7f2c520a00b
--- /dev/null
+++ b/Code/Mantid/Framework/Crystal/inc/MantidCrystal/FilterPeaks.h
@@ -0,0 +1,56 @@
+#ifndef MANTID_CRYSTAL_FILTERPEAKS_H_
+#define MANTID_CRYSTAL_FILTERPEAKS_H_
+
+#include "MantidKernel/System.h"
+#include "MantidAPI/Algorithm.h"
+
+namespace Mantid
+{
+namespace Crystal
+{
+
+  /** FilterPeaks : TODO: DESCRIPTION
+    
+    Copyright &copy; 2012 ISIS Rutherford Appleton Laboratory & NScD Oak Ridge National Laboratory
+
+    This file is part of Mantid.
+
+    Mantid is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 3 of the License, or
+    (at your option) any later version.
+
+    Mantid is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+    File change history is stored at: <https://svn.mantidproject.org/mantid/trunk/Code/Mantid>
+    Code Documentation is available at: <http://doxygen.mantidproject.org>
+  */
+  class DLLExport FilterPeaks  : public API::Algorithm
+  {
+  public:
+    FilterPeaks();
+    virtual ~FilterPeaks();
+    
+    virtual const std::string name() const;
+    virtual int version() const;
+    virtual const std::string category() const;
+
+  private:
+    virtual void initDocs();
+    void init();
+    void exec();
+
+
+  };
+
+
+} // namespace Crystal
+} // namespace Mantid
+
+#endif  /* MANTID_CRYSTAL_FILTERPEAKS_H_ */
\ No newline at end of file
diff --git a/Code/Mantid/Framework/Crystal/src/FilterPeaks.cpp b/Code/Mantid/Framework/Crystal/src/FilterPeaks.cpp
new file mode 100644
index 00000000000..dd6b94f0c24
--- /dev/null
+++ b/Code/Mantid/Framework/Crystal/src/FilterPeaks.cpp
@@ -0,0 +1,145 @@
+/*WIKI*
+TODO: Enter a full wiki-markup description of your algorithm here. You can then use the Build/wiki_maker.py script to generate your full wiki page.
+*WIKI*/
+
+#include "MantidCrystal/FilterPeaks.h"
+#include "MantidKernel/ListValidator.h"
+#include "MantidKernel/MandatoryValidator.h"
+#include "MantidDataObjects/PeaksWorkspace.h"
+
+namespace {
+  double HKL(const Mantid::DataObjects::Peak & p)
+  {
+    return p.getH() + p.getK() + p.getL();
+  }
+
+  double HKL2(const Mantid::DataObjects::Peak & p)
+  {
+    return p.getH()*p.getH() + p.getK()*p.getK() + p.getL()*p.getL();
+  }
+
+  double intensity(const Mantid::DataObjects::Peak & p)
+  {
+    return p.getIntensity();
+  }
+
+  double SN(const Mantid::DataObjects::Peak & p)
+  {
+    return p.getIntensity()/p.getSigmaIntensity();
+  }
+}
+
+namespace Mantid
+{
+namespace Crystal
+{
+  // Register the algorithm into the AlgorithmFactory
+  DECLARE_ALGORITHM(FilterPeaks)
+
+  using namespace Kernel;
+  using namespace API;
+  using DataObjects::PeaksWorkspace;
+  using DataObjects::PeaksWorkspace_const_sptr;
+  using DataObjects::PeaksWorkspace_sptr;
+  using DataObjects::Peak;
+
+  /** Constructor
+   */
+  FilterPeaks::FilterPeaks()
+  {
+  }
+    
+  /** Destructor
+   */
+  FilterPeaks::~FilterPeaks()
+  {
+  }
+  
+  /// Algorithm's name for identification. @see Algorithm::name
+  const std::string FilterPeaks::name() const { return "FilterPeaks";};
+  /// Algorithm's version for identification. @see Algorithm::version
+  int FilterPeaks::version() const { return 1;};
+  /// Algorithm's category for identification. @see Algorithm::category
+  const std::string FilterPeaks::category() const { return "Crystal";}
+
+  /// Sets documentation strings for this algorithm
+  void FilterPeaks::initDocs()
+  {
+    this->setWikiSummary("Filters the peaks in a peaks workspace based upon a chosen  ");
+    this->setOptionalMessage("TODO: Enter a quick description of your algorithm.");
+  }
+
+  /** Initialize the algorithm's properties.
+   */
+  void FilterPeaks::init()
+  {
+    declareProperty(new WorkspaceProperty<PeaksWorkspace>("InputWorkspace","",Direction::Input), "The input workspace");
+    declareProperty(new WorkspaceProperty<IPeaksWorkspace>("OutputWorkspace","",Direction::Output), "The filtered workspace");
+
+    std::vector<std::string> filters;
+    filters.push_back("H+K+L");
+    filters.push_back("H2+K2+L2");
+    filters.push_back("Intensity");
+    filters.push_back("Signal/Noise");
+    declareProperty("FilterVariable","",boost::make_shared<StringListValidator>(filters),"The variable on which to filter the peaks");
+
+    declareProperty("FilterValue", EMPTY_DBL(), boost::make_shared<MandatoryValidator<double>>(),
+                    "The value of the FilterVariable to compare each peak to");
+
+    std::vector<std::string> operation;
+    operation.push_back("<");
+    operation.push_back(">");
+    operation.push_back("=");
+    operation.push_back("<=");
+    operation.push_back(">=");
+    declareProperty("Operator","<",boost::make_shared<StringListValidator>(operation),"");
+  }
+
+  /** Execute the algorithm.
+   */
+  void FilterPeaks::exec()
+  {
+    PeaksWorkspace_const_sptr inputWS = getProperty("InputWorkspace");
+
+    IPeaksWorkspace_sptr filteredWS = WorkspaceFactory::Instance().createPeaks();
+    // Copy over ExperimentInfo from input workspace
+    filteredWS->copyExperimentInfoFrom(inputWS.get());
+
+    // TODO: Refactor to avoid all the else-ifs and multiple edits required on adding new variables
+
+    const std::string FilterVariable = getProperty("FilterVariable");
+    double (*variable)(const Mantid::DataObjects::Peak &);
+    if ( FilterVariable == "H+K+L" )
+      variable = &HKL;
+    else if ( FilterVariable == "H2+K2+L2" )
+      variable = &HKL2;
+    else if ( FilterVariable == "Intensity" )
+      variable = &intensity;
+    else if ( FilterVariable == "Signal/Noise" )
+      variable = &SN;
+
+    const double FilterValue = getProperty("FilterValue");
+    const std::string Operator = getProperty("Operator");
+
+    for ( int i = 0; i < inputWS->getNumberPeaks(); ++i )
+    {
+      bool pass;
+      const Peak& currentPeak = inputWS->getPeak(i);
+      const double currentValue = variable(currentPeak);
+
+      if ( Operator == "<" ) pass = (currentValue < FilterValue);
+      else if ( Operator == ">" ) pass = (currentValue > FilterValue);
+      else if ( Operator == "=" ) pass = (currentValue == FilterValue);
+      else if ( Operator == "<=" ) pass = (currentValue <= FilterValue);
+      else if ( Operator == ">=" ) pass = (currentValue >= FilterValue);
+
+      if ( pass ) filteredWS->addPeak(currentPeak);
+    }
+
+    setProperty("OutputWorkspace", filteredWS);
+  }
+
+
+
+} // namespace Crystal
+} // namespace Mantid
diff --git a/Code/Mantid/Framework/Crystal/test/FilterPeaksTest.h b/Code/Mantid/Framework/Crystal/test/FilterPeaksTest.h
new file mode 100644
index 00000000000..9f18a104194
--- /dev/null
+++ b/Code/Mantid/Framework/Crystal/test/FilterPeaksTest.h
@@ -0,0 +1,63 @@
+#ifndef MANTID_CRYSTAL_FILTERPEAKSTEST_H_
+#define MANTID_CRYSTAL_FILTERPEAKSTEST_H_
+
+#include <cxxtest/TestSuite.h>
+
+#include "MantidTestHelpers/WorkspaceCreationHelper.h"
+#include "MantidCrystal/FilterPeaks.h"
+#include "MantidDataObjects/PeaksWorkspace.h"
+
+using Mantid::Crystal::FilterPeaks;
+
+class FilterPeaksTest : public CxxTest::TestSuite
+{
+public:
+  // This pair of boilerplate methods prevent the suite being created statically
+  // This means the constructor isn't called when running other tests
+  static FilterPeaksTest *createSuite() { return new FilterPeaksTest(); }
+  static void destroySuite( FilterPeaksTest *suite ) { delete suite; }
+
+  void test_Init()
+  {
+    FilterPeaks alg;
+    TS_ASSERT_THROWS_NOTHING( alg.initialize() )
+    TS_ASSERT( alg.isInitialized() )
+  }
+  
+  void test_exec()
+  {
+    using namespace Mantid::API;
+    using namespace Mantid::DataObjects;
+
+    PeaksWorkspace_sptr inputWS = WorkspaceCreationHelper::createPeaksWorkspace();
+
+    // Name of the output workspace.
+    std::string outWSName("FilterPeaksTest_OutputWS");
+  
+    FilterPeaks alg;
+    TS_ASSERT_THROWS_NOTHING( alg.initialize() )
+    TS_ASSERT( alg.isInitialized() )
+    TS_ASSERT_THROWS_NOTHING( alg.setProperty("InputWorkspace", inputWS) )
+    TS_ASSERT_THROWS_NOTHING( alg.setPropertyValue("OutputWorkspace", outWSName) )
+    TS_ASSERT_THROWS_NOTHING( alg.setPropertyValue("FilterVariable", "H+K+L") )
+    TS_ASSERT_THROWS_NOTHING( alg.setProperty("FilterValue", 0.0) )
+    TS_ASSERT_THROWS_NOTHING( alg.setPropertyValue("Operator", ">") )
+    TS_ASSERT( alg.execute() )
+    
+    // Retrieve the workspace from data service.
+    IPeaksWorkspace_const_sptr ws;
+    TS_ASSERT_THROWS_NOTHING( ws = AnalysisDataService::Instance().retrieveWS<IPeaksWorkspace>(outWSName) );
+    TS_ASSERT(ws);
+    if (!ws) return;
+    
+    // Will be empty as indices not set
+    TS_ASSERT_EQUALS( ws->getNumberPeaks(), 0 )
+    
+    // Remove workspace from the data service.
+    AnalysisDataService::Instance().remove(outWSName);
+  }
+
+};
+
+
+#endif /* MANTID_CRYSTAL_FILTERPEAKSTEST_H_ */
-- 
GitLab