From 765329f490090a299f0438bbc10a05211c92d507 Mon Sep 17 00:00:00 2001
From: Gennady Pospelov <g.pospelov@fz-juelich.de>
Date: Tue, 18 Oct 2016 19:53:39 +0200
Subject: [PATCH] Two functional tests for simulation with roi and masks

---
 Core/Instrument/DetectorMask.cpp              |   4 +
 Core/Instrument/IDetector2D.h                 |   2 +-
 Core/Simulation/GISASSimulation.cpp           |  10 +++
 Core/Simulation/GISASSimulation.h             |   6 ++
 Core/StandardSamples/SimulationFactory.cpp    |   9 ++
 Core/StandardSamples/StandardSimulations.cpp  |  63 ++++++++++++--
 Core/StandardSamples/StandardSimulations.h    |   2 +
 Tests/Functional/Core/CMakeLists.txt          |   2 +
 .../StandardSimulationsRegistry.cpp           |  14 +++
 .../StandardSuite/RectDetWithRoi.int.gz       | Bin 0 -> 3135 bytes
 .../StandardSuite/SphericalDetWithRoi.int.gz  | Bin 0 -> 2644 bytes
 auto/Wrap/libBornAgainCore.py                 |  10 +++
 auto/Wrap/libBornAgainCore_wrap.cpp           |  80 ++++++++++++++++++
 13 files changed, 193 insertions(+), 9 deletions(-)
 create mode 100644 Tests/ReferenceData/StandardSuite/RectDetWithRoi.int.gz
 create mode 100644 Tests/ReferenceData/StandardSuite/SphericalDetWithRoi.int.gz

diff --git a/Core/Instrument/DetectorMask.cpp b/Core/Instrument/DetectorMask.cpp
index f7748da479a..faf3b6bcf80 100644
--- a/Core/Instrument/DetectorMask.cpp
+++ b/Core/Instrument/DetectorMask.cpp
@@ -56,6 +56,10 @@ void DetectorMask::addMask(const Geometry::IShape2D& shape, bool mask_value)
 
 void DetectorMask::initMaskData(const IDetector2D& detector)
 {
+    if(detector.getDimension() != 2)
+        throw Exceptions::RuntimeErrorException("DetectorMask::initMaskData() -> Error. Attempt "
+                                                "to add masks to uninitialized detector.");
+
     assert(m_shapes.size() == m_mask_of_shape.size());
     m_mask_data.clear();
 
diff --git a/Core/Instrument/IDetector2D.h b/Core/Instrument/IDetector2D.h
index cdcf91363fb..85a8ea390c4 100644
--- a/Core/Instrument/IDetector2D.h
+++ b/Core/Instrument/IDetector2D.h
@@ -147,7 +147,7 @@ public:
     //! Returns region of  interest if exists.
     const Geometry::Rectangle* regionOfInterest() const;
 
-    //! Sets rectangular region of interest with lower left and uppre right corners defined.
+    //! Sets rectangular region of interest with lower left and upper right corners defined.
     void setRegionOfInterest(double xlow, double ylow, double xup, double yup);
 
     //! Resets region of interest making whole detector plane available for the simulation.
diff --git a/Core/Simulation/GISASSimulation.cpp b/Core/Simulation/GISASSimulation.cpp
index 10bbd936393..3a4dab29418 100644
--- a/Core/Simulation/GISASSimulation.cpp
+++ b/Core/Simulation/GISASSimulation.cpp
@@ -127,6 +127,16 @@ std::string GISASSimulation::addParametersToExternalPool(
     return new_path;
 }
 
+void GISASSimulation::setRegionOfInterest(double xlow, double ylow, double xup, double yup)
+{
+    m_instrument.getDetector()->setRegionOfInterest(xlow, ylow, xup, yup);
+}
+
+void GISASSimulation::resetRegionOfInterest()
+{
+    m_instrument.getDetector()->resetRegionOfInterest();
+}
+
 void GISASSimulation::removeMasks()
 {
     m_instrument.getDetector()->removeMasks();
diff --git a/Core/Simulation/GISASSimulation.h b/Core/Simulation/GISASSimulation.h
index 13bc37e8724..ea61457fc47 100644
--- a/Core/Simulation/GISASSimulation.h
+++ b/Core/Simulation/GISASSimulation.h
@@ -93,6 +93,12 @@ public:
     std::string addParametersToExternalPool(
         const std::string& path, ParameterPool* external_pool, int copy_number = -1) const final;
 
+    //! Sets rectangular region of interest with lower left and upper right corners defined.
+    void setRegionOfInterest(double xlow, double ylow, double xup, double yup);
+
+    //! Resets region of interest making whole detector plane available for the simulation.
+    void resetRegionOfInterest();
+
 private:
     GISASSimulation(const GISASSimulation& other);
 
diff --git a/Core/StandardSamples/SimulationFactory.cpp b/Core/StandardSamples/SimulationFactory.cpp
index 8093fe7d17c..c91e4b3c796 100644
--- a/Core/StandardSamples/SimulationFactory.cpp
+++ b/Core/StandardSamples/SimulationFactory.cpp
@@ -97,4 +97,13 @@ SimulationFactory::SimulationFactory()
                  StandardSimulations::MiniGISASMonteCarlo,
                  "GISAS simulation with small 25x25 detector and phi[-2,2], theta[0,2], "
                  "in Monte-Carlo mode");
+
+    // region of interest
+
+    registerItem("SphericalDetWithRoi",
+                 StandardSimulations::SphericalDetWithRoi,
+                 "Spherical detector with ROI and mask");
+    registerItem("RectDetWithRoi",
+                 StandardSimulations::RectDetWithRoi,
+                 "Rectangular detector with ROI and mask");
 }
diff --git a/Core/StandardSamples/StandardSimulations.cpp b/Core/StandardSamples/StandardSimulations.cpp
index b5b946d4d78..af4a8d62d92 100644
--- a/Core/StandardSamples/StandardSimulations.cpp
+++ b/Core/StandardSamples/StandardSimulations.cpp
@@ -51,7 +51,8 @@ GISASSimulation* StandardSimulations::PolarizedDWBAMagCylinders2()
     return result;
 }
 
-//! Basic GISAS simulation with the detector phi[0,2], theta[0,2]
+//! Basic GISAS simulation with the detector phi[0,2], theta[0,2].
+
 GISASSimulation* StandardSimulations::BasicGISAS()
 {
     GISASSimulation* result = new GISASSimulation();
@@ -61,7 +62,8 @@ GISASSimulation* StandardSimulations::BasicGISAS()
     return result;
 }
 
-//! Basic GISAS for polarization studies
+//! Basic GISAS for polarization studies.
+
 GISASSimulation* StandardSimulations::BasicGISAS00()
 {
     GISASSimulation* result = BasicGISAS();
@@ -71,7 +73,8 @@ GISASSimulation* StandardSimulations::BasicGISAS00()
     return result;
 }
 
-//! GISAS simulation with small detector and phi[-2,2], theta[0,2]
+//! GISAS simulation with small detector and phi[-2,2], theta[0,2].
+
 GISASSimulation* StandardSimulations::MiniGISAS()
 {
     GISASSimulation* result = new GISASSimulation();
@@ -81,7 +84,8 @@ GISASSimulation* StandardSimulations::MiniGISAS()
     return result;
 }
 
-//! GISAS simulation with small detector and phi[-1,1], theta[0,1]
+//! GISAS simulation with small detector and phi[-1,1], theta[0,1].
+
 GISASSimulation* StandardSimulations::MiniGISAS_v2()
 {
     GISASSimulation* result = new GISASSimulation();
@@ -91,6 +95,8 @@ GISASSimulation* StandardSimulations::MiniGISAS_v2()
     return result;
 }
 
+//! GISAS simulation with beam divergence applied.
+
 GISASSimulation* StandardSimulations::MiniGISASBeamDivergence()
 {
     GISASSimulation* result = MiniGISAS();
@@ -112,6 +118,8 @@ GISASSimulation* StandardSimulations::MiniGISASBeamDivergence()
     return result;
 }
 
+//! GISAS simulation with multiple masks on the detector plane.
+
 GISASSimulation* StandardSimulations::GISASWithMasks()
 {
     GISASSimulation* result = new GISASSimulation();
@@ -143,6 +151,8 @@ GISASSimulation* StandardSimulations::GISASWithMasks()
     return result;
 }
 
+//! GISAS simulation with detector resolution.
+
 GISASSimulation* StandardSimulations::MiniGISASDetectorResolution()
 {
     GISASSimulation* result = MiniGISAS();
@@ -151,7 +161,8 @@ GISASSimulation* StandardSimulations::MiniGISASDetectorResolution()
     return result;
 }
 
-//! GISAS simulation with large detector to test performance
+//! GISAS simulation with large detector to test performance.
+
 GISASSimulation* StandardSimulations::MaxiGISAS()
 {
     GISASSimulation* result = new GISASSimulation();
@@ -161,7 +172,8 @@ GISASSimulation* StandardSimulations::MaxiGISAS()
     return result;
 }
 
-//! Basic GISAS for polarization studies
+//! Basic GISAS for polarization studies.
+
 GISASSimulation* StandardSimulations::MaxiGISAS00()
 {
     GISASSimulation* result = MaxiGISAS();
@@ -171,8 +183,8 @@ GISASSimulation* StandardSimulations::MaxiGISAS00()
     return result;
 }
 
+//! Typical IsGISAXS simulation with the detector phi[-1,1], theta[0,2].
 
-//! Typical IsGISAXS simulation with the detector phi[-1,1], theta[0,2]
 GISASSimulation* StandardSimulations::IsGISAXSSimulation1()
 {
     GISASSimulation* result = new GISASSimulation();
@@ -184,8 +196,8 @@ GISASSimulation* StandardSimulations::IsGISAXSSimulation1()
     return result;
 }
 
+//! Typical IsGISAXS simulation with the detector phi[0,2], theta[0,2].
 
-//! Typical IsGISAXS simulation with the detector phi[0,2], theta[0,2]
 GISASSimulation* StandardSimulations::IsGISAXSSimulation2()
 {
     GISASSimulation* result = new GISASSimulation();
@@ -197,6 +209,8 @@ GISASSimulation* StandardSimulations::IsGISAXSSimulation2()
     return result;
 }
 
+//! GISAS simulation with generic rectangular detector.
+
 GISASSimulation* StandardSimulations::RectDetectorGeneric()
 {
     GISASSimulation* result = new GISASSimulation();
@@ -210,6 +224,8 @@ GISASSimulation* StandardSimulations::RectDetectorGeneric()
     return result;
 }
 
+//! GISAS simulation with the rectangular detector perpendicular to the sample.
+
 GISASSimulation* StandardSimulations::RectDetectorPerpToSample()
 {
     GISASSimulation* result = new GISASSimulation();
@@ -222,6 +238,7 @@ GISASSimulation* StandardSimulations::RectDetectorPerpToSample()
     return result;
 }
 
+//! GISAS simulation with the rectangular detector perpendicular to the direct beam.
 
 GISASSimulation* StandardSimulations::RectDetectorPerpToDirectBeam()
 {
@@ -235,6 +252,7 @@ GISASSimulation* StandardSimulations::RectDetectorPerpToDirectBeam()
     return result;
 }
 
+//! GISAS simulation with the rectangular detector perpendicular to the reflected beam.
 
 GISASSimulation* StandardSimulations::RectDetectorPerpToReflectedBeam()
 {
@@ -248,6 +266,8 @@ GISASSimulation* StandardSimulations::RectDetectorPerpToReflectedBeam()
     return result;
 }
 
+//! GISAS simulation with the rectangular detector perpendicular to the reflected beam when
+//! the coordinates of direct beam are known.
 
 GISASSimulation* StandardSimulations::RectDetectorPerpToReflectedBeamDpos()
 {
@@ -262,6 +282,7 @@ GISASSimulation* StandardSimulations::RectDetectorPerpToReflectedBeamDpos()
     return result;
 }
 
+//! GISAS simulation with Monte-Carlo integration switched ON.
 
 GISASSimulation* StandardSimulations::MiniGISASMonteCarlo()
 {
@@ -269,3 +290,29 @@ GISASSimulation* StandardSimulations::MiniGISASMonteCarlo()
     result->getOptions().setMonteCarloIntegration(true, 100);
     return result;
 }
+
+//! GISAS simulation with spherical detector, region of interest and mask.
+
+GISASSimulation *StandardSimulations::SphericalDetWithRoi() {
+  GISASSimulation *result = new GISASSimulation();
+  result->setDetectorParameters(40, -2.0 * Units::degree, 2.0 * Units::degree,
+                                30, 0.0 * Units::degree, 3.0 * Units::degree);
+  result->setBeamParameters(1.0 * Units::angstrom, 0.2 * Units::degree,
+                            0.0 * Units::degree);
+  result->addMask(Geometry::Rectangle(-0.5 * Units::degree, 0.3 * Units::degree,
+                                      -0.2 * Units::degree,
+                                      0.6 * Units::degree));
+  result->setRegionOfInterest(-1.5 * Units::degree, 0.25 * Units::degree,
+                              1.5 * Units::degree, 1.75 * Units::degree);
+  return result;
+}
+
+//! GISAS simulation with rectangular detector, region of interest and mask.
+
+GISASSimulation* StandardSimulations::RectDetWithRoi()
+{
+    GISASSimulation* result = RectDetectorPerpToDirectBeam();
+    result->addMask(Geometry::Rectangle(3.0, 4.0, 5.0, 7.0));
+    result->setRegionOfInterest(2.0, 3.0, 18.0, 15.0);
+    return result;
+}
diff --git a/Core/StandardSamples/StandardSimulations.h b/Core/StandardSamples/StandardSimulations.h
index bc11b50d5f1..dd658b89c9b 100644
--- a/Core/StandardSamples/StandardSimulations.h
+++ b/Core/StandardSamples/StandardSimulations.h
@@ -43,6 +43,8 @@ GISASSimulation* RectDetectorPerpToDirectBeam();
 GISASSimulation* RectDetectorPerpToReflectedBeam();
 GISASSimulation* RectDetectorPerpToReflectedBeamDpos();
 GISASSimulation* MiniGISASMonteCarlo();
+GISASSimulation* SphericalDetWithRoi();
+GISASSimulation* RectDetWithRoi();
 }
 
 #endif // STANDARDSIMULATIONS_H
diff --git a/Tests/Functional/Core/CMakeLists.txt b/Tests/Functional/Core/CMakeLists.txt
index 400dd50036f..963c00b8f15 100644
--- a/Tests/Functional/Core/CMakeLists.txt
+++ b/Tests/Functional/Core/CMakeLists.txt
@@ -56,6 +56,8 @@ set(test_cases
     TransformBox
     TriangularRipple
     TwoTypesCylindersDistribution
+    SphericalDetWithRoi
+    RectDetWithRoi
     )
 
 # Other tests:
diff --git a/Tests/Functional/TestMachinery/StandardSimulationsRegistry.cpp b/Tests/Functional/TestMachinery/StandardSimulationsRegistry.cpp
index 33acf4264f6..5528bc30008 100644
--- a/Tests/Functional/TestMachinery/StandardSimulationsRegistry.cpp
+++ b/Tests/Functional/TestMachinery/StandardSimulationsRegistry.cpp
@@ -331,6 +331,20 @@ StandardSimulationsRegistry::StandardSimulationsRegistry()
         "LargeCylindersInDWBABuilder",
         "None",
         5e-1);
+
+    add("SphericalDetWithRoi",
+        "Spherical detector with ROI and mask defined",
+        "SphericalDetWithRoi",
+        "CylindersAndPrismsBuilder",
+        "None",
+        1e-10);
+
+    add("RectDetWithRoi",
+        "Rectangular detector with ROI and mask defined",
+        "RectDetWithRoi",
+        "CylindersAndPrismsBuilder",
+        "None",
+        1e-10);
 }
 
 void StandardSimulationsRegistry::add(
diff --git a/Tests/ReferenceData/StandardSuite/RectDetWithRoi.int.gz b/Tests/ReferenceData/StandardSuite/RectDetWithRoi.int.gz
new file mode 100644
index 0000000000000000000000000000000000000000..33fd2d809492e8967697f7b1f84c687e20ef0f4b
GIT binary patch
literal 3135
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
ZQm+9pK}Z?Ca*q+-{TsI{gc3eH005Vu8GQf%

literal 0
HcmV?d00001

diff --git a/Tests/ReferenceData/StandardSuite/SphericalDetWithRoi.int.gz b/Tests/ReferenceData/StandardSuite/SphericalDetWithRoi.int.gz
new file mode 100644
index 0000000000000000000000000000000000000000..3215790914f9f57f03ab4a4f10ea834c27d3b66a
GIT binary patch
literal 2644
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
C9~*A~

literal 0
HcmV?d00001

diff --git a/auto/Wrap/libBornAgainCore.py b/auto/Wrap/libBornAgainCore.py
index a814c0ed7a2..29daaa94d38 100644
--- a/auto/Wrap/libBornAgainCore.py
+++ b/auto/Wrap/libBornAgainCore.py
@@ -15575,6 +15575,16 @@ class GISASSimulation(Simulation):
         """
         return _libBornAgainCore.GISASSimulation_maskAll(self)
 
+
+    def setRegionOfInterest(self, xlow, ylow, xup, yup):
+        """setRegionOfInterest(GISASSimulation self, double xlow, double ylow, double xup, double yup)"""
+        return _libBornAgainCore.GISASSimulation_setRegionOfInterest(self, xlow, ylow, xup, yup)
+
+
+    def resetRegionOfInterest(self):
+        """resetRegionOfInterest(GISASSimulation self)"""
+        return _libBornAgainCore.GISASSimulation_resetRegionOfInterest(self)
+
 GISASSimulation_swigregister = _libBornAgainCore.GISASSimulation_swigregister
 GISASSimulation_swigregister(GISASSimulation)
 
diff --git a/auto/Wrap/libBornAgainCore_wrap.cpp b/auto/Wrap/libBornAgainCore_wrap.cpp
index a3221c56b0d..f743cef0b19 100644
--- a/auto/Wrap/libBornAgainCore_wrap.cpp
+++ b/auto/Wrap/libBornAgainCore_wrap.cpp
@@ -71039,6 +71039,84 @@ fail:
 }
 
 
+SWIGINTERN PyObject *_wrap_GISASSimulation_setRegionOfInterest(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *resultobj = 0;
+  GISASSimulation *arg1 = (GISASSimulation *) 0 ;
+  double arg2 ;
+  double arg3 ;
+  double arg4 ;
+  double arg5 ;
+  void *argp1 = 0 ;
+  int res1 = 0 ;
+  double val2 ;
+  int ecode2 = 0 ;
+  double val3 ;
+  int ecode3 = 0 ;
+  double val4 ;
+  int ecode4 = 0 ;
+  double val5 ;
+  int ecode5 = 0 ;
+  PyObject * obj0 = 0 ;
+  PyObject * obj1 = 0 ;
+  PyObject * obj2 = 0 ;
+  PyObject * obj3 = 0 ;
+  PyObject * obj4 = 0 ;
+  
+  if (!PyArg_ParseTuple(args,(char *)"OOOOO:GISASSimulation_setRegionOfInterest",&obj0,&obj1,&obj2,&obj3,&obj4)) SWIG_fail;
+  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_GISASSimulation, 0 |  0 );
+  if (!SWIG_IsOK(res1)) {
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "GISASSimulation_setRegionOfInterest" "', argument " "1"" of type '" "GISASSimulation *""'"); 
+  }
+  arg1 = reinterpret_cast< GISASSimulation * >(argp1);
+  ecode2 = SWIG_AsVal_double(obj1, &val2);
+  if (!SWIG_IsOK(ecode2)) {
+    SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "GISASSimulation_setRegionOfInterest" "', argument " "2"" of type '" "double""'");
+  } 
+  arg2 = static_cast< double >(val2);
+  ecode3 = SWIG_AsVal_double(obj2, &val3);
+  if (!SWIG_IsOK(ecode3)) {
+    SWIG_exception_fail(SWIG_ArgError(ecode3), "in method '" "GISASSimulation_setRegionOfInterest" "', argument " "3"" of type '" "double""'");
+  } 
+  arg3 = static_cast< double >(val3);
+  ecode4 = SWIG_AsVal_double(obj3, &val4);
+  if (!SWIG_IsOK(ecode4)) {
+    SWIG_exception_fail(SWIG_ArgError(ecode4), "in method '" "GISASSimulation_setRegionOfInterest" "', argument " "4"" of type '" "double""'");
+  } 
+  arg4 = static_cast< double >(val4);
+  ecode5 = SWIG_AsVal_double(obj4, &val5);
+  if (!SWIG_IsOK(ecode5)) {
+    SWIG_exception_fail(SWIG_ArgError(ecode5), "in method '" "GISASSimulation_setRegionOfInterest" "', argument " "5"" of type '" "double""'");
+  } 
+  arg5 = static_cast< double >(val5);
+  (arg1)->setRegionOfInterest(arg2,arg3,arg4,arg5);
+  resultobj = SWIG_Py_Void();
+  return resultobj;
+fail:
+  return NULL;
+}
+
+
+SWIGINTERN PyObject *_wrap_GISASSimulation_resetRegionOfInterest(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *resultobj = 0;
+  GISASSimulation *arg1 = (GISASSimulation *) 0 ;
+  void *argp1 = 0 ;
+  int res1 = 0 ;
+  PyObject * obj0 = 0 ;
+  
+  if (!PyArg_ParseTuple(args,(char *)"O:GISASSimulation_resetRegionOfInterest",&obj0)) SWIG_fail;
+  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_GISASSimulation, 0 |  0 );
+  if (!SWIG_IsOK(res1)) {
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "GISASSimulation_resetRegionOfInterest" "', argument " "1"" of type '" "GISASSimulation *""'"); 
+  }
+  arg1 = reinterpret_cast< GISASSimulation * >(argp1);
+  (arg1)->resetRegionOfInterest();
+  resultobj = SWIG_Py_Void();
+  return resultobj;
+fail:
+  return NULL;
+}
+
+
 SWIGINTERN PyObject *GISASSimulation_swigregister(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
   PyObject *obj;
   if (!PyArg_ParseTuple(args,(char*)"O:swigregister", &obj)) return NULL;
@@ -108750,6 +108828,8 @@ static PyMethodDef SwigMethods[] = {
 		"Put the mask for all detector channels (i.e. exclude whole detector from the analysis) \n"
 		"\n"
 		""},
+	 { (char *)"GISASSimulation_setRegionOfInterest", _wrap_GISASSimulation_setRegionOfInterest, METH_VARARGS, (char *)"GISASSimulation_setRegionOfInterest(GISASSimulation self, double xlow, double ylow, double xup, double yup)"},
+	 { (char *)"GISASSimulation_resetRegionOfInterest", _wrap_GISASSimulation_resetRegionOfInterest, METH_VARARGS, (char *)"GISASSimulation_resetRegionOfInterest(GISASSimulation self)"},
 	 { (char *)"GISASSimulation_swigregister", GISASSimulation_swigregister, METH_VARARGS, NULL},
 	 { (char *)"delete_IHistogram", _wrap_delete_IHistogram, METH_VARARGS, (char *)"\n"
 		"delete_IHistogram(IHistogram self)\n"
-- 
GitLab