From 3d11b2123bffc41ee33c48f781f3683e0557e7ef Mon Sep 17 00:00:00 2001
From: Gennady Pospelov <g.pospelov@fz-juelich.de>
Date: Wed, 23 Sep 2015 14:14:40 +0200
Subject: [PATCH] Additional methods for histograms to find global bins, unit
 tests.

---
 Core/PythonAPI/src/Histogram1D.pypp.cpp    | 20 ++++++++++++++---
 Core/PythonAPI/src/IHistogram.pypp.cpp     | 26 +++++++++++++++++++++-
 Core/PythonAPI/src/IntensityData.pypp.cpp  |  8 +++----
 Core/Tools/inc/Histogram1D.h               |  3 +++
 Core/Tools/inc/IHistogram.h                |  6 +++++
 Core/Tools/inc/OutputData.h                |  4 ++--
 Core/Tools/src/Histogram1D.cpp             | 21 +++++++++++++++++
 Core/Tools/src/Histogram2D.cpp             |  2 +-
 Core/Tools/src/IHistogram.cpp              |  8 +++++++
 Tests/UnitTests/TestCore/Histogram1DTest.h | 22 ++++++++++++++++++
 Tests/UnitTests/TestCore/Histogram2DTest.h |  5 +++++
 11 files changed, 114 insertions(+), 11 deletions(-)

diff --git a/Core/PythonAPI/src/Histogram1D.pypp.cpp b/Core/PythonAPI/src/Histogram1D.pypp.cpp
index 249e6a71146..14a5d91756d 100644
--- a/Core/PythonAPI/src/Histogram1D.pypp.cpp
+++ b/Core/PythonAPI/src/Histogram1D.pypp.cpp
@@ -79,6 +79,18 @@ void register_Histogram1D_class(){
         Histogram1D_exposer.def( bp::init< int, std::vector< double > const & >(( bp::arg("nbinsx"), bp::arg("xbins") ), "Constructor for variable bin size histograms. @param nbinsx number of bins @param xbins Array of size nbins+1 containing low-edges for each bin and upper edge of last bin. \n\n:Parameters:\n  - 'nbinsx' - number of bins\n  - 'xbins' - Array of size nbins+1 containing low-edges for each\n") );
         Histogram1D_exposer.def( bp::init< IAxis const & >(( bp::arg("axis") ), "Constructor for 1D histogram with custom axis.") );
         Histogram1D_exposer.def( bp::init< OutputData< double > const & >(( bp::arg("data") ), "Constructor for 1D histograms from basic OutputData object.") );
+        { //::Histogram1D::crop
+        
+            typedef ::Histogram1D * ( ::Histogram1D::*crop_function_type)( double,double ) ;
+            
+            Histogram1D_exposer.def( 
+                "crop"
+                , crop_function_type( &::Histogram1D::crop )
+                , ( bp::arg("xmin"), bp::arg("xmax") )
+                , bp::return_value_policy< bp::reference_existing_object >()
+                , "Create new histogram by applying crop on axis." );
+        
+        }
         { //::Histogram1D::fill
         
             typedef int ( ::Histogram1D::*fill_function_type)( double,double ) ;
@@ -97,7 +109,7 @@ void register_Histogram1D_class(){
             Histogram1D_exposer.def( 
                 "getBinCenters"
                 , getBinCenters_function_type( &::Histogram1D::getBinCenters )
-                , "Increment bin with abscissa x with a weight." );
+                , "returns vector of histogram bin centers." );
         
         }
         { //::Histogram1D::getBinErrors
@@ -106,7 +118,8 @@ void register_Histogram1D_class(){
             
             Histogram1D_exposer.def( 
                 "getBinErrors"
-                , getBinErrors_function_type( &::Histogram1D::getBinErrors ) );
+                , getBinErrors_function_type( &::Histogram1D::getBinErrors )
+                , "returns vector of bin errors." );
         
         }
         { //::Histogram1D::getBinValues
@@ -115,7 +128,8 @@ void register_Histogram1D_class(){
             
             Histogram1D_exposer.def( 
                 "getBinValues"
-                , getBinValues_function_type( &::Histogram1D::getBinValues ) );
+                , getBinValues_function_type( &::Histogram1D::getBinValues )
+                , "returns vector of bin content (the value accumulated by bins)." );
         
         }
         { //::Histogram1D::getRank
diff --git a/Core/PythonAPI/src/IHistogram.pypp.cpp b/Core/PythonAPI/src/IHistogram.pypp.cpp
index c17fa2b6656..50a40aa6633 100644
--- a/Core/PythonAPI/src/IHistogram.pypp.cpp
+++ b/Core/PythonAPI/src/IHistogram.pypp.cpp
@@ -89,14 +89,38 @@ void register_IHistogram_class(){
                 , bp::return_value_policy< bp::manage_new_object >()
                 , "Reset histogram content (axes remains)." );
         
+        }
+        { //::IHistogram::createOutputData
+        
+            typedef ::OutputData< double > * ( ::IHistogram::*createOutputData_function_type)( ::IHistogram::DataType ) const;
+            
+            IHistogram_exposer.def( 
+                "createOutputData"
+                , createOutputData_function_type( &::IHistogram::createOutputData )
+                , ( bp::arg("dataType") )
+                , bp::return_value_policy< bp::manage_new_object >()
+                , "creates new OutputData with histogram's shape and put there values corresponding to DataType." );
+        
+        }
+        { //::IHistogram::findGlobalBin
+        
+            typedef int ( ::IHistogram::*findGlobalBin_function_type)( double,double ) const;
+            
+            IHistogram_exposer.def( 
+                "findGlobalBin"
+                , findGlobalBin_function_type( &::IHistogram::findGlobalBin )
+                , ( bp::arg("x"), bp::arg("y") )
+                , "Returns closest global bin index for given axes coordinates. For 1D @param x Value on x-axis @param y Value on y-axis @return Closest global bin index \n\n:Parameters:\n  - 'x' - Value on x-axis\n  - 'y' - Value on y-axis\n" );
+        
         }
         { //::IHistogram::getArray
         
-            typedef ::PyObject * ( ::IHistogram::*getArray_function_type)(  ) const;
+            typedef ::PyObject * ( ::IHistogram::*getArray_function_type)( ::IHistogram::DataType ) const;
             
             IHistogram_exposer.def( 
                 "getArray"
                 , getArray_function_type( &::IHistogram::getArray )
+                , ( bp::arg("dataType")=::IHistogram::INTEGRAL )
                 , "Returns numpy array with bin content (accumulated values)." );
         
         }
diff --git a/Core/PythonAPI/src/IntensityData.pypp.cpp b/Core/PythonAPI/src/IntensityData.pypp.cpp
index 854fc23e84c..14d1ec520e2 100644
--- a/Core/PythonAPI/src/IntensityData.pypp.cpp
+++ b/Core/PythonAPI/src/IntensityData.pypp.cpp
@@ -99,14 +99,14 @@ void register_IntensityData_class(){
                 , ( bp::arg("other") ) );
         
         }
-        { //::OutputData< double >::findClosestIndex
+        { //::OutputData< double >::findGlobalIndex
         
             typedef OutputData< double > exported_class_t;
-            typedef ::std::size_t ( exported_class_t::*findClosestIndex_function_type)( ::std::vector< double > const & ) const;
+            typedef ::std::size_t ( exported_class_t::*findGlobalIndex_function_type)( ::std::vector< double > const & ) const;
             
             IntensityData_exposer.def( 
-                "findClosestIndex"
-                , findClosestIndex_function_type( &::OutputData< double >::findClosestIndex )
+                "findGlobalIndex"
+                , findGlobalIndex_function_type( &::OutputData< double >::findGlobalIndex )
                 , ( bp::arg("coordinates") ) );
         
         }
diff --git a/Core/Tools/inc/Histogram1D.h b/Core/Tools/inc/Histogram1D.h
index e563848c248..c42c69a4469 100644
--- a/Core/Tools/inc/Histogram1D.h
+++ b/Core/Tools/inc/Histogram1D.h
@@ -57,6 +57,9 @@ public:
 
     //! returns vector of bin errors
     std::vector<double> getBinErrors() const;
+
+    //! Create new histogram by applying crop on axis.
+    Histogram1D *crop(double xmin, double xmax);
 };
 
 
diff --git a/Core/Tools/inc/IHistogram.h b/Core/Tools/inc/IHistogram.h
index e876581fa13..6e9b2ac33a9 100644
--- a/Core/Tools/inc/IHistogram.h
+++ b/Core/Tools/inc/IHistogram.h
@@ -82,6 +82,12 @@ public:
     //! @return The global bin index
     int getGlobalBin(int binx, int biny = 0) const;
 
+    //! Returns closest global bin index for given axes coordinates. For 1D
+    //! @param x Value on x-axis
+    //! @param y Value on y-axis
+    //! @return Closest global bin index
+    int findGlobalBin(double x, double y) const;
+
     //! Returns x-axis bin index for given globalbin. For 1D histograms returned value conicide
     //! with globalbin value
     int getXaxisIndex(size_t globalbin) const;
diff --git a/Core/Tools/inc/OutputData.h b/Core/Tools/inc/OutputData.h
index c875484569d..464418d1278 100644
--- a/Core/Tools/inc/OutputData.h
+++ b/Core/Tools/inc/OutputData.h
@@ -155,7 +155,7 @@ public:
     //! Returns global index for specified axes values
     //! @param coordinates Vector of axes coordinates for all specified axes in this dataset
     //! @return Closest global index
-    size_t findClosestIndex(const std::vector<double> &coordinates) const;
+    size_t findGlobalIndex(const std::vector<double> &coordinates) const;
 
     //! Returns the value of selected axis for given global_index.
     //! @param global_index The global index of this data structure.
@@ -514,7 +514,7 @@ size_t OutputData<T>::toGlobalIndex(const std::vector<int> &axes_indices) const
 
 
 template <class T>
-size_t OutputData<T>::findClosestIndex(const std::vector<double> &coordinates) const
+size_t OutputData<T>::findGlobalIndex(const std::vector<double> &coordinates) const
 {
     assert(mp_ll_data);
     if (coordinates.size() != mp_ll_data->getRank())
diff --git a/Core/Tools/src/Histogram1D.cpp b/Core/Tools/src/Histogram1D.cpp
index 0d7ed0ad887..cc9981021e5 100644
--- a/Core/Tools/src/Histogram1D.cpp
+++ b/Core/Tools/src/Histogram1D.cpp
@@ -16,6 +16,7 @@
 #include "Histogram1D.h"
 #include "FixedBinAxis.h"
 #include "VariableBinAxis.h"
+#include <boost/scoped_ptr.hpp>
 
 
 Histogram1D::Histogram1D(int nbinsx, double xlow, double xup)
@@ -65,3 +66,23 @@ std::vector<double> Histogram1D::getBinErrors() const
 {
     return IHistogram::getDataVector(IHistogram::ERROR);
 }
+
+Histogram1D *Histogram1D::crop(double xmin, double xmax)
+{
+    boost::scoped_ptr<IAxis > xaxis(getXaxis()->createClippedAxis(xmin, xmax));
+
+    Histogram1D *result = new Histogram1D(*xaxis);
+    OutputData<CumulativeValue>::const_iterator it_origin = m_data.begin();
+    OutputData<CumulativeValue>::iterator it_result = result->m_data.begin();
+    while (it_origin != m_data.end())
+    {
+        double x = m_data.getAxisValue(it_origin.getIndex(), 0);
+        if(result->getXaxis()->contains(x)) {
+            *it_result = *it_origin;
+            ++it_result;
+        }
+        ++it_origin;
+    }
+    return result;
+
+}
diff --git a/Core/Tools/src/Histogram2D.cpp b/Core/Tools/src/Histogram2D.cpp
index 919f3c7b4d6..26f23130809 100644
--- a/Core/Tools/src/Histogram2D.cpp
+++ b/Core/Tools/src/Histogram2D.cpp
@@ -51,7 +51,7 @@ int Histogram2D::fill(double x, double y, double weight)
     coordinates.push_back(x);
     coordinates.push_back(y);
 
-    size_t index = m_data.findClosestIndex(coordinates);
+    size_t index = m_data.findGlobalIndex(coordinates);
     m_data[index].add(weight);
     return (int)index;
 }
diff --git a/Core/Tools/src/IHistogram.cpp b/Core/Tools/src/IHistogram.cpp
index ce2b4386bea..813b26dc001 100644
--- a/Core/Tools/src/IHistogram.cpp
+++ b/Core/Tools/src/IHistogram.cpp
@@ -100,6 +100,14 @@ int IHistogram::getGlobalBin(int binx, int biny) const
     return m_data.toGlobalIndex(axes_indices);
 }
 
+int IHistogram::findGlobalBin(double x, double y) const
+{
+    std::vector<double> coordinates;
+    coordinates.push_back(x);
+    if(getRank() == 2) coordinates.push_back(y);
+    return m_data.findGlobalIndex(coordinates);
+}
+
 int IHistogram::getXaxisIndex(size_t globalbin) const
 {
     return m_data.getAxisBinIndex(globalbin, 0);
diff --git a/Tests/UnitTests/TestCore/Histogram1DTest.h b/Tests/UnitTests/TestCore/Histogram1DTest.h
index daaee2a7479..1f3ad0052dd 100644
--- a/Tests/UnitTests/TestCore/Histogram1DTest.h
+++ b/Tests/UnitTests/TestCore/Histogram1DTest.h
@@ -118,6 +118,28 @@ TEST_F(Histogram1DTest, FixedBinFill)
 }
 
 
+//     -1.0  -0.5        0.5   1.0        2.0  X
+
+TEST_F(Histogram1DTest, crop)
+{
+    std::vector<double> xedges = boost::assign::list_of(-1.0)(-0.5)(0.5)(1.0)(2.0);
+    std::vector<double> xvalues = boost::assign::list_of(-0.75)(0.0)(0.75)(1.5);
+    Histogram1D hist(4, xedges);
+
+    for(size_t i=0; i<xvalues.size(); ++i) {
+        hist.fill(xvalues[i], i*10);
+    }
+
+    boost::scoped_ptr<Histogram1D > crop(hist.crop(-0.49, 0.99));
+
+    EXPECT_EQ(-0.5, crop->getXmin());
+    EXPECT_EQ(1.0, crop->getXmax());
+
+    EXPECT_EQ(10.0, crop->getBinContent(0));
+    EXPECT_EQ(20.0, crop->getBinContent(1));
+}
+
+
 TEST_F(Histogram1DTest, CreateHistogram)
 {
     OutputData<double> data;
diff --git a/Tests/UnitTests/TestCore/Histogram2DTest.h b/Tests/UnitTests/TestCore/Histogram2DTest.h
index 7c26a3549bd..62002511eba 100644
--- a/Tests/UnitTests/TestCore/Histogram2DTest.h
+++ b/Tests/UnitTests/TestCore/Histogram2DTest.h
@@ -95,6 +95,11 @@ TEST_F(Histogram2DTest, VariableHist)
     EXPECT_EQ(hist->getYaxisValue(10), 1.5);
     EXPECT_EQ(hist->getYaxisValue(11), 3.0);
 
+    // coordinates to global bin
+    EXPECT_EQ(hist->findGlobalBin(-0.75, 0.5), 0);
+    EXPECT_EQ(hist->findGlobalBin(0.0, 1.5), 4);
+    EXPECT_EQ(hist->findGlobalBin(1.5, 3.0), 11);
+
 }
 
 // y
-- 
GitLab