From b62b24162aaa640da6888cfd3e7a05ca889827bb Mon Sep 17 00:00:00 2001
From: Gennady Pospelov <g.pospelov@fz-juelich.de>
Date: Mon, 11 Aug 2014 17:37:26 +0200
Subject: [PATCH] Clip functionality for IAxis family.

---
 Core/Samples/inc/Samples.h                    |  1 -
 Core/Tools/inc/ConstKBinAxis.h                |  4 ++
 Core/Tools/inc/CustomBinAxis.h                |  2 +
 Core/Tools/inc/FixedBinAxis.h                 |  2 +
 Core/Tools/inc/IAxis.h                        |  9 ++++
 Core/Tools/inc/IntensityDataFunctions.h       |  3 ++
 Core/Tools/inc/VariableBinAxis.h              |  2 +
 Core/Tools/src/ConstKBinAxis.cpp              | 37 ++++++++++++++
 Core/Tools/src/CustomBinAxis.cpp              |  5 ++
 Core/Tools/src/FixedBinAxis.cpp               | 14 ++++++
 Core/Tools/src/IntensityDataFunctions.cpp     | 11 ++++
 Core/Tools/src/VariableBinAxis.cpp            | 21 ++++++++
 Tests/UnitTests/TestCore/ConstKBinAxisTest.h  | 50 +++++++------------
 Tests/UnitTests/TestCore/FixedBinAxisTest.h   | 20 ++++++++
 .../UnitTests/TestCore/VariableBinAxisTest.h  | 34 +++++++++++++
 15 files changed, 183 insertions(+), 32 deletions(-)

diff --git a/Core/Samples/inc/Samples.h b/Core/Samples/inc/Samples.h
index 81dd0b244ac..7202787246f 100644
--- a/Core/Samples/inc/Samples.h
+++ b/Core/Samples/inc/Samples.h
@@ -17,7 +17,6 @@
 #define SAMPLES_H
 
 #include "Crystal.h"
-#include "MaterialManager.h"
 #include "Layer.h"
 #include "LayerInterface.h"
 #include "MultiLayer.h"
diff --git a/Core/Tools/inc/ConstKBinAxis.h b/Core/Tools/inc/ConstKBinAxis.h
index 8f9f46b0295..c4a5a6c3fa6 100644
--- a/Core/Tools/inc/ConstKBinAxis.h
+++ b/Core/Tools/inc/ConstKBinAxis.h
@@ -36,7 +36,11 @@ public:
 
     ConstKBinAxis *clone() const;
 
+    ConstKBinAxis *createClippedAxis(double left, double right) const;
+
 protected:
+    ConstKBinAxis(const std::string &name, size_t nbins);
+
     void print(std::ostream& ostr) const;
     bool equals(const IAxis& other) const;
 
diff --git a/Core/Tools/inc/CustomBinAxis.h b/Core/Tools/inc/CustomBinAxis.h
index c34881cdc77..3500fe663ba 100644
--- a/Core/Tools/inc/CustomBinAxis.h
+++ b/Core/Tools/inc/CustomBinAxis.h
@@ -42,6 +42,8 @@ public:
 
     std::vector<double > getBinCenters() const;
 
+    CustomBinAxis *createClippedAxis(double left, double right) const;
+
 protected:
     void print(std::ostream& ostr) const;
     bool equals(const IAxis& other) const;
diff --git a/Core/Tools/inc/FixedBinAxis.h b/Core/Tools/inc/FixedBinAxis.h
index 24bd37ccf5a..002f8ed1ccf 100644
--- a/Core/Tools/inc/FixedBinAxis.h
+++ b/Core/Tools/inc/FixedBinAxis.h
@@ -52,6 +52,8 @@ public:
 
     std::vector<double > getBinBoundaries() const;
 
+    FixedBinAxis *createClippedAxis(double left, double right) const;
+
 protected:
     void print(std::ostream& ostr) const;
     virtual bool equals(const IAxis& other) const;
diff --git a/Core/Tools/inc/IAxis.h b/Core/Tools/inc/IAxis.h
index d10f81aa5de..2ce545212ec 100644
--- a/Core/Tools/inc/IAxis.h
+++ b/Core/Tools/inc/IAxis.h
@@ -71,6 +71,9 @@ public:
 
     virtual  std::vector<double > getBinBoundaries() const;
 
+    //! Creates a new clipped axis
+    virtual IAxis *createClippedAxis(double left, double right) const;
+
 protected:
     virtual void print(std::ostream& ostr) const=0;
     virtual bool equals(const IAxis& other) const;
@@ -109,6 +112,12 @@ inline std::vector<double> IAxis::getBinBoundaries() const
     throw Exceptions::NotImplementedException("IAxis::getBinBoundaries() -> Error. Not implemented.");
 }
 
+inline IAxis *IAxis::createClippedAxis(double /* left */, double /* right */) const
+{
+    throw Exceptions::NotImplementedException("IAxis::createClippedAxis() -> Error. Not implemented.");
+}
+
+
 //! global helper function for comparison of axes
 inline bool HaveSameNameAndShape(const IAxis& left, const IAxis& right)
 {
diff --git a/Core/Tools/inc/IntensityDataFunctions.h b/Core/Tools/inc/IntensityDataFunctions.h
index 7f531a95cde..dbcfd5ad191 100644
--- a/Core/Tools/inc/IntensityDataFunctions.h
+++ b/Core/Tools/inc/IntensityDataFunctions.h
@@ -42,6 +42,9 @@ public:
     static double GetRelativeDifference(const OutputData<double> &result,
                          const OutputData<double> &reference);
 
+    //! Returns new IntensityData objects which axes clipped to represent the specified rectangle
+    static OutputData<double> *createClippedDataSet(const OutputData<double> &origin, double x1, double y1, double x2, double y2);
+
 };
 
 
diff --git a/Core/Tools/inc/VariableBinAxis.h b/Core/Tools/inc/VariableBinAxis.h
index 38c94fa227a..d49404e4f94 100644
--- a/Core/Tools/inc/VariableBinAxis.h
+++ b/Core/Tools/inc/VariableBinAxis.h
@@ -52,6 +52,8 @@ public:
 
     std::vector<double > getBinBoundaries() const;
 
+    VariableBinAxis *createClippedAxis(double left, double right) const;
+
 protected:
     VariableBinAxis(const std::string &name, int nbins = 0);
     void setBinBoundaries(const std::vector<double> &bin_boundaries);
diff --git a/Core/Tools/src/ConstKBinAxis.cpp b/Core/Tools/src/ConstKBinAxis.cpp
index cfa041691a9..179cb541fdd 100644
--- a/Core/Tools/src/ConstKBinAxis.cpp
+++ b/Core/Tools/src/ConstKBinAxis.cpp
@@ -3,6 +3,15 @@
 #include <iomanip>
 #include <iostream>
 
+ConstKBinAxis::ConstKBinAxis(const std::string &name, size_t nbins)
+    : VariableBinAxis(name, nbins)
+    , m_start(0)
+    , m_end(0)
+{
+
+}
+
+
 ConstKBinAxis::ConstKBinAxis(const std::string &name, size_t nbins, double start, double end)
     : VariableBinAxis(name, nbins)
     , m_start(start)
@@ -29,6 +38,34 @@ ConstKBinAxis *ConstKBinAxis::clone() const
     return new ConstKBinAxis(getName(), m_nbins, m_start, m_end);
 }
 
+ConstKBinAxis *ConstKBinAxis::createClippedAxis(double left, double right) const
+{
+    if(left >= right)
+        throw LogicErrorException("ConstKBinAxis::createClippedAxis() -> Error. 'left'' should be smaller than 'right'");
+
+    if(left < getMin()) left = getBin(0).getMidPoint();
+    if(right >= getMax()) right = getBin(getSize()-1).getMidPoint();
+
+    size_t nbin1 = findClosestIndex(left);
+    size_t nbin2 = findClosestIndex(right);
+
+//    return new ConstKBinAxis(getName(), nbin2-nbin1+1, getBin(nbin1).m_lower, getBin(nbin2).m_upper );
+
+    size_t new_nbins = nbin2-nbin1+1;
+    std::vector<double> new_boundaries;
+    std::vector<double> old_boundaries = getBinBoundaries();
+    for(size_t i=0; i<new_nbins+1; ++i) {
+        new_boundaries.push_back(old_boundaries[nbin1 + i]);
+    }
+
+    ConstKBinAxis *result = new ConstKBinAxis(getName(), new_nbins);
+    result->m_start = new_boundaries.front();
+    result->m_end = new_boundaries.back();
+    result->setBinBoundaries(new_boundaries);
+    return result;
+}
+
+
 
 bool ConstKBinAxis::equals(const IAxis& other) const
 {
diff --git a/Core/Tools/src/CustomBinAxis.cpp b/Core/Tools/src/CustomBinAxis.cpp
index a79c93f4448..c6507648b35 100644
--- a/Core/Tools/src/CustomBinAxis.cpp
+++ b/Core/Tools/src/CustomBinAxis.cpp
@@ -52,6 +52,11 @@ std::vector<double> CustomBinAxis::getBinCenters() const
     return m_bin_centers;
 }
 
+CustomBinAxis *CustomBinAxis::createClippedAxis(double /* left */, double /* right */) const
+{
+    throw Exceptions::NotImplementedException("VariableBinAxis::CustomBinAxis() -> Error. Not implemented.");
+}
+
 
 void CustomBinAxis::print(std::ostream &ostr) const
 {
diff --git a/Core/Tools/src/FixedBinAxis.cpp b/Core/Tools/src/FixedBinAxis.cpp
index a3277be9185..9f54ad241db 100644
--- a/Core/Tools/src/FixedBinAxis.cpp
+++ b/Core/Tools/src/FixedBinAxis.cpp
@@ -93,6 +93,20 @@ std::vector<double> FixedBinAxis::getBinBoundaries() const
     return result;
 }
 
+FixedBinAxis *FixedBinAxis::createClippedAxis(double left, double right) const
+{
+    if(left >= right)
+        throw LogicErrorException("FixedBinAxis::createClippedAxis() -> Error. 'left'' should be smaller than 'right'");
+
+    if(left < getMin()) left = getBin(0).getMidPoint();
+    if(right >= getMax()) right = getBin(getSize()-1).getMidPoint();
+
+    size_t nbin1 = findClosestIndex(left);
+    size_t nbin2 = findClosestIndex(right);
+
+    return new FixedBinAxis(getName(), nbin2-nbin1+1, getBin(nbin1).m_lower, getBin(nbin2).m_upper );
+}
+
 
 void FixedBinAxis::print(std::ostream& ostr) const
 {
diff --git a/Core/Tools/src/IntensityDataFunctions.cpp b/Core/Tools/src/IntensityDataFunctions.cpp
index 92b88c69c4b..87bed395287 100644
--- a/Core/Tools/src/IntensityDataFunctions.cpp
+++ b/Core/Tools/src/IntensityDataFunctions.cpp
@@ -40,3 +40,14 @@ double IntensityDataFunctions::GetRelativeDifference(const OutputData<double> &r
     return diff;
 }
 
+
+OutputData<double> *IntensityDataFunctions::createClippedDataSet(const OutputData<double> &origin, double x1, double y1, double x2, double y2)
+{
+//    if (origin.getRank() != 2) {
+//        throw LogicErrorException("IntensityDataFunctions::createClippedData()"
+//                " -> Error! Works only on two-dimensional data");
+//    }
+
+    return 0;
+}
+
diff --git a/Core/Tools/src/VariableBinAxis.cpp b/Core/Tools/src/VariableBinAxis.cpp
index ad0c37894c0..402cd7038c7 100644
--- a/Core/Tools/src/VariableBinAxis.cpp
+++ b/Core/Tools/src/VariableBinAxis.cpp
@@ -97,6 +97,27 @@ std::vector<double> VariableBinAxis::getBinBoundaries() const
     return m_bin_boundaries;
 }
 
+VariableBinAxis *VariableBinAxis::createClippedAxis(double left, double right) const
+{
+
+    if(left >= right)
+        throw LogicErrorException("VariableBinAxis::createClippedAxis() -> Error. 'left'' should be smaller than 'right'");
+
+    if(left < getMin()) left = getBin(0).getMidPoint();
+    if(right >= getMax()) right = getBin(getSize()-1).getMidPoint();
+
+    size_t nbin1 = findClosestIndex(left);
+    size_t nbin2 = findClosestIndex(right);
+
+    size_t new_nbins = nbin2-nbin1+1;
+    std::vector<double> new_boundaries;
+    for(size_t i=0; i<new_nbins+1; ++i) {
+        new_boundaries.push_back(m_bin_boundaries[nbin1 + i]);
+    }
+
+    return new VariableBinAxis(getName(), new_nbins, new_boundaries);
+}
+
 
 void VariableBinAxis::print(std::ostream& ostr) const
 {
diff --git a/Tests/UnitTests/TestCore/ConstKBinAxisTest.h b/Tests/UnitTests/TestCore/ConstKBinAxisTest.h
index c51451db0d4..c6c84136df1 100644
--- a/Tests/UnitTests/TestCore/ConstKBinAxisTest.h
+++ b/Tests/UnitTests/TestCore/ConstKBinAxisTest.h
@@ -46,6 +46,9 @@ TEST_F(ConstKBinAxisTest, TypicalAxis)
     EXPECT_EQ(m_start, m_axis.getMin());
     EXPECT_EQ(m_end, m_axis.getMax());
 
+    EXPECT_DOUBLE_EQ(m_start, m_axis.getBinBoundaries().front());
+    EXPECT_DOUBLE_EQ(m_end, m_axis.getBinBoundaries().back());
+
     for(size_t i=0; i<m_axis.getSize(); ++i) {
         EXPECT_DOUBLE_EQ( m_centers[i], m_axis[i]);
     }
@@ -76,37 +79,22 @@ TEST_F(ConstKBinAxisTest, IOStream)
     delete result;
 }
 
+//[-5.0, -3.99816897832528, -2.9975609824866662, -1.99786732193833, -0.9987818274427882, 0.0, 0.9987818274427874, 1.9978673219383292, 2.997560982486666, 3.998168978325279, 5.0]
 
-//TEST_F(ConstKBinAxisTest, BinCenters)
-//{
-//    static const double arr[] = {-1.0, -0.5, 0.5, 1.0, 2.0};
-//    std::vector<double> values (arr, arr + sizeof(arr) / sizeof(arr[0]) );
-//    VariableBinAxis axis("name", 4, values);
-
-//    std::vector<double> centers = axis.getBinCenters();
-//    EXPECT_EQ(4, centers.size());
-//    EXPECT_DOUBLE_EQ(-0.75, centers[0]);
-//    EXPECT_DOUBLE_EQ(0.0, centers[1]);
-//    EXPECT_DOUBLE_EQ(0.75, centers[2]);
-//    EXPECT_DOUBLE_EQ(1.5, centers[3]);
-//}
-
-
-//TEST_F(ConstKBinAxisTest, BinBoundaries)
-//{
-//    static const double arr[] = {-1.0, -0.5, 0.5, 1.0, 2.0};
-//    std::vector<double> values (arr, arr + sizeof(arr) / sizeof(arr[0]) );
-//    VariableBinAxis axis("name", 4, values);
-
-//    std::vector<double> boundaries = axis.getBinBoundaries();
-//    EXPECT_EQ(5, boundaries.size());
-//    EXPECT_DOUBLE_EQ(-1.0, boundaries[0]);
-//    EXPECT_DOUBLE_EQ(-0.5, boundaries[1]);
-//    EXPECT_DOUBLE_EQ(0.5, boundaries[2]);
-//    EXPECT_DOUBLE_EQ(1.0, boundaries[3]);
-//    EXPECT_DOUBLE_EQ(2.0, boundaries[4]);
-//}
-
-
+TEST_F(ConstKBinAxisTest, ClippedAxis)
+{
+    ConstKBinAxis *clip1 = m_axis.createClippedAxis(Units::deg2rad(-10.0), Units::deg2rad(10.0));
+    EXPECT_TRUE(*clip1 == m_axis);
+    delete clip1;
+
+    ConstKBinAxis *clip2 = m_axis.createClippedAxis(Units::deg2rad(-3.0), Units::deg2rad(3.0));
+    EXPECT_EQ(clip2->getSize(), 8);
+    std::vector<double> boundaries = clip2->getBinBoundaries();
+    for(size_t i=0; i<boundaries.size(); ++i) {
+        EXPECT_EQ(boundaries[i], m_axis.getBin(1+i).m_lower);
+//        EXPECT_NEAR(boundaries[i], m_axis.getBin(1+i).m_lower, 1e-10);
+    }
+    delete clip2;
+}
 
 #endif
diff --git a/Tests/UnitTests/TestCore/FixedBinAxisTest.h b/Tests/UnitTests/TestCore/FixedBinAxisTest.h
index 878a54bbdde..a578c369b08 100644
--- a/Tests/UnitTests/TestCore/FixedBinAxisTest.h
+++ b/Tests/UnitTests/TestCore/FixedBinAxisTest.h
@@ -152,4 +152,24 @@ TEST_F(FixedBinAxisTest, BinBoundaries)
 }
 
 
+TEST_F(FixedBinAxisTest, ClippedAxis)
+{
+    FixedBinAxis axis("name", 4, -1.0, 3.0);
+
+    FixedBinAxis *clip1 = axis.createClippedAxis(-0.5, 2.5);
+    EXPECT_EQ(clip1->getSize(), axis.getSize());
+    EXPECT_EQ(clip1->getMin(), axis.getMin());
+    EXPECT_EQ(clip1->getMax(), axis.getMax());
+    EXPECT_TRUE(*clip1 == axis);
+    delete clip1;
+
+    FixedBinAxis *clip2 = axis.createClippedAxis(0.0, 1.99);
+    EXPECT_EQ(clip2->getSize(), 2);
+    EXPECT_EQ(clip2->getMin(), 0.0);
+    EXPECT_EQ(clip2->getMax(), 2.0);
+    EXPECT_TRUE(*clip2 != axis);
+    delete clip2;
+}
+
+
 #endif
diff --git a/Tests/UnitTests/TestCore/VariableBinAxisTest.h b/Tests/UnitTests/TestCore/VariableBinAxisTest.h
index d39f123826e..405f67689cd 100644
--- a/Tests/UnitTests/TestCore/VariableBinAxisTest.h
+++ b/Tests/UnitTests/TestCore/VariableBinAxisTest.h
@@ -218,6 +218,40 @@ TEST_F(VariableBinAxisTest, BinBoundaries)
     EXPECT_DOUBLE_EQ(2.0, boundaries[4]);
 }
 
+TEST_F(VariableBinAxisTest, ClippedAxis)
+{
+    static const double arr[] = {-1.0, -0.5, 0.5, 1.0, 2.0};
+    std::vector<double> values (arr, arr + sizeof(arr) / sizeof(arr[0]) );
+    VariableBinAxis axis("name", 4, values);
+
+    VariableBinAxis *clip1 = axis.createClippedAxis(-1.0, 2.0);
+    EXPECT_TRUE(axis == *clip1);
+    delete clip1;
+
+    VariableBinAxis *clip2 = axis.createClippedAxis(-0.5, 1.5);
+    EXPECT_EQ(clip2->getSize(), 3);
+    EXPECT_EQ(clip2->getMin(), -0.5);
+    EXPECT_EQ(clip2->getMax(), 2.0);
+    std::vector<double> centers = clip2->getBinCenters();
+    EXPECT_EQ(centers[0], 0.0);
+    EXPECT_EQ(centers[1], 0.75);
+    EXPECT_EQ(centers[2], 1.5);
+    EXPECT_TRUE(axis != *clip2);
+    delete clip2;
+
+    VariableBinAxis *clip3 = axis.createClippedAxis(-0.5, 0.99);
+    EXPECT_EQ(clip3->getSize(), 2);
+    EXPECT_EQ(clip3->getMin(), -0.5);
+    EXPECT_EQ(clip3->getMax(), 1.0);
+    std::vector<double> boundaries = clip3->getBinBoundaries();
+    EXPECT_EQ(boundaries[0], -0.5);
+    EXPECT_EQ(boundaries[1], 0.5);
+    EXPECT_EQ(boundaries[2], 1.0);
+    delete clip3;
+
+
+}
+
 
 
 #endif
-- 
GitLab