From 0c587868d47743f07f664afdeca084f93fc399b7 Mon Sep 17 00:00:00 2001
From: Walter Van Herck <w.van.herck@fz-juelich.de>
Date: Mon, 19 Feb 2018 16:16:08 +0100
Subject: [PATCH] Allow distribution of inclination angle in OffSpecSimulation

---
 Core/Simulation/OffSpecSimulation.cpp  | 30 ++++++++++++++++++++-----
 Core/Simulation/OffSpecSimulation.h    |  7 ++++--
 Core/Simulation/SpecularSimulation.cpp |  4 ++--
 auto/Wrap/swig_runtime.h               | 31 ++++++++++++++------------
 4 files changed, 49 insertions(+), 23 deletions(-)

diff --git a/Core/Simulation/OffSpecSimulation.cpp b/Core/Simulation/OffSpecSimulation.cpp
index c5a6e697a73..bd8bba5ecaf 100644
--- a/Core/Simulation/OffSpecSimulation.cpp
+++ b/Core/Simulation/OffSpecSimulation.cpp
@@ -14,10 +14,13 @@
 
 #include "OffSpecSimulation.h"
 #include "BornAgainNamespace.h"
+#include "Distributions.h"
 #include "DWBAComputation.h"
 #include "Histogram2D.h"
 #include "IMultiLayerBuilder.h"
 #include "MultiLayer.h"
+#include "ParameterPool.h"
+#include "RealParameter.h"
 #include "SimulationElement.h"
 
 OffSpecSimulation::OffSpecSimulation()
@@ -68,8 +71,8 @@ void OffSpecSimulation::setBeamParameters(double wavelength, const IAxis& alpha_
         throw Exceptions::ClassInitializationException(
                 "OffSpecSimulation::prepareSimulation() "
                 "-> Error. Incoming alpha range size < 1.");
-    double alpha_start = alpha_axis[0];
-    m_instrument.setBeamParameters(wavelength, alpha_start, phi_i);
+    const double alpha_zero = 0.0;
+    m_instrument.setBeamParameters(wavelength, alpha_zero, phi_i);
     updateIntensityMap();
 }
 
@@ -91,13 +94,15 @@ void OffSpecSimulation::initSimulationElementVector()
 {
     m_sim_elements.clear();
     Beam beam = m_instrument.getBeam();
-    double wavelength = beam.getWavelength();
-    double phi_i = beam.getPhi();
+    const double wavelength = beam.getWavelength();
+    const double phi_i = beam.getPhi();
+    const double alpha_shift = beam.getAlpha();
 
     for (size_t i = 0; i < mP_alpha_i_axis->size(); ++i) {
         // Incoming angle by convention defined as positive:
         double alpha_i = mP_alpha_i_axis->getBin(i).getMidPoint();
-        beam.setCentralK(wavelength, alpha_i, phi_i);
+        double total_alpha = alpha_i + alpha_shift;
+        beam.setCentralK(wavelength, total_alpha, phi_i);
         auto sim_elements_i = generateSimulationElements(beam);
         m_sim_elements.insert(m_sim_elements.end(), std::make_move_iterator(sim_elements_i.begin()),
                               std::make_move_iterator(sim_elements_i.end()));
@@ -106,6 +111,21 @@ void OffSpecSimulation::initSimulationElementVector()
         m_cache.resize(m_sim_elements.size(), 0.0);
 }
 
+void OffSpecSimulation::validateParametrization(const ParameterDistribution& par_distr) const
+{
+    const bool zero_mean = par_distr.getDistribution()->getMean() == 0.0;
+    if (zero_mean)
+        return;
+
+    std::unique_ptr<ParameterPool> parameter_pool(createParameterTree());
+    const std::vector<RealParameter*> names
+        = parameter_pool->getMatchedParameters(par_distr.getMainParameterName());
+    for (const auto par : names)
+        if (par->getName().find(BornAgain::Inclination) != std::string::npos && !zero_mean)
+            throw std::runtime_error("Error in OffSpecSimulation: parameter distribution of "
+                                     "beam inclination angle should have zero mean.");
+}
+
 void OffSpecSimulation::transferResultsToIntensityMap()
 {
     checkInitialization();
diff --git a/Core/Simulation/OffSpecSimulation.h b/Core/Simulation/OffSpecSimulation.h
index 86a7c9b7ab0..5f48896bce7 100644
--- a/Core/Simulation/OffSpecSimulation.h
+++ b/Core/Simulation/OffSpecSimulation.h
@@ -58,12 +58,15 @@ private:
     //! Initializes the vector of Simulation elements
     void initSimulationElementVector() override;
 
+    //! Checks the distribution validity for simulation.
+    void validateParametrization(const ParameterDistribution& par_distr) const override;
+
     //! Creates the appropriate data structure (e.g. 2D intensity map) from the calculated
     //! SimulationElement objects
-    void transferResultsToIntensityMap() final;
+    void transferResultsToIntensityMap() override;
 
     //! Default implementation only adds the detector axes
-    void updateIntensityMap() override final;
+    void updateIntensityMap() override;
 
     //! Normalize, apply detector resolution and transfer detector image corresponding to
     //! alpha_i = mp_alpha_i_axis->getBin(index)
diff --git a/Core/Simulation/SpecularSimulation.cpp b/Core/Simulation/SpecularSimulation.cpp
index 0a111d368eb..b67fd4a334e 100644
--- a/Core/Simulation/SpecularSimulation.cpp
+++ b/Core/Simulation/SpecularSimulation.cpp
@@ -229,8 +229,8 @@ void SpecularSimulation::validateParametrization(const ParameterDistribution& pa
         = parameter_pool->getMatchedParameters(par_distr.getMainParameterName());
     for (const auto par : names)
         if (par->getName().find(BornAgain::Inclination) != std::string::npos && !zero_mean)
-            throw std::runtime_error("Error in SpecularSimulation: parameter distribution modifies "
-                                     "beam inclination while its mean value is not zero.");
+            throw std::runtime_error("Error in SpecularSimulation: parameter distribution of "
+                                     "beam inclination angle should have zero mean.");
 }
 
 void SpecularSimulation::initialize()
diff --git a/auto/Wrap/swig_runtime.h b/auto/Wrap/swig_runtime.h
index de3fda43582..96d50bdb9a2 100644
--- a/auto/Wrap/swig_runtime.h
+++ b/auto/Wrap/swig_runtime.h
@@ -1,6 +1,6 @@
 /* ----------------------------------------------------------------------------
  * This file was automatically generated by SWIG (http://www.swig.org).
- * Version 3.0.12
+ * Version 3.0.8
  *
  * This file is not intended to be easily readable and contains a number of
  * coding conventions designed to improve portability and efficiency. Do not make
@@ -75,11 +75,9 @@
 #endif
 
 /* exporting methods */
-#if defined(__GNUC__)
-#  if (__GNUC__ >= 4) || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4)
-#    ifndef GCC_HASCLASSVISIBILITY
-#      define GCC_HASCLASSVISIBILITY
-#    endif
+#if (__GNUC__ >= 4) || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4)
+#  ifndef GCC_HASCLASSVISIBILITY
+#    define GCC_HASCLASSVISIBILITY
 #  endif
 #endif
 
@@ -644,16 +642,16 @@ SWIG_UnpackData(const char *c, void *ptr, size_t sz) {
     char d = *(c++);
     unsigned char uu;
     if ((d >= '0') && (d <= '9'))
-      uu = (unsigned char)((d - '0') << 4);
+      uu = ((d - '0') << 4);
     else if ((d >= 'a') && (d <= 'f'))
-      uu = (unsigned char)((d - ('a'-10)) << 4);
+      uu = ((d - ('a'-10)) << 4);
     else
       return (char *) 0;
     d = *(c++);
     if ((d >= '0') && (d <= '9'))
-      uu |= (unsigned char)(d - '0');
+      uu |= (d - '0');
     else if ((d >= 'a') && (d <= 'f'))
-      uu |= (unsigned char)(d - ('a'-10));
+      uu |= (d - ('a'-10));
     else
       return (char *) 0;
     *u = uu;
@@ -818,6 +816,10 @@ PyString_FromFormat(const char *fmt, ...) {
 }
 #endif
 
+/* Add PyObject_Del for old Pythons */
+#if PY_VERSION_HEX < 0x01060000
+# define PyObject_Del(op) PyMem_DEL((op))
+#endif
 #ifndef PyObject_DEL
 # define PyObject_DEL PyObject_Del
 #endif
@@ -932,7 +934,6 @@ typedef destructor freefunc;
 #if PY_VERSION_HEX < 0x03020000
 #define PyDescr_TYPE(x) (((PyDescrObject *)(x))->d_type)
 #define PyDescr_NAME(x) (((PyDescrObject *)(x))->d_name)
-#define Py_hash_t long
 #endif
 /* -----------------------------------------------------------------------------
  * error manipulation
@@ -1877,6 +1878,7 @@ SwigPyObject_TypeOnce(void) {
   static int type_init = 0;
   if (!type_init) {
     const PyTypeObject tmp = {
+      /* PyObject header changed in Python 3 */
 #if PY_VERSION_HEX >= 0x03000000
       PyVarObject_HEAD_INIT(NULL, 0)
 #else
@@ -1887,7 +1889,7 @@ SwigPyObject_TypeOnce(void) {
       sizeof(SwigPyObject),                 /* tp_basicsize */
       0,                                    /* tp_itemsize */
       (destructor)SwigPyObject_dealloc,     /* tp_dealloc */
-      0,                                    /* tp_print */
+      0,				    /* tp_print */
 #if PY_VERSION_HEX < 0x02020000
       (getattrfunc)SwigPyObject_getattr,    /* tp_getattr */
 #else
@@ -1895,7 +1897,7 @@ SwigPyObject_TypeOnce(void) {
 #endif
       (setattrfunc)0,                       /* tp_setattr */
 #if PY_VERSION_HEX >= 0x03000000
-      0, /* tp_reserved in 3.0.1, tp_compare in 3.0.0 but not used */
+    0, /* tp_reserved in 3.0.1, tp_compare in 3.0.0 but not used */
 #else
       (cmpfunc)SwigPyObject_compare,        /* tp_compare */
 #endif
@@ -1905,7 +1907,7 @@ SwigPyObject_TypeOnce(void) {
       0,                                    /* tp_as_mapping */
       (hashfunc)0,                          /* tp_hash */
       (ternaryfunc)0,                       /* tp_call */
-      0,                                    /* tp_str */
+      0,				    /* tp_str */
       PyObject_GenericGetAttr,              /* tp_getattro */
       0,                                    /* tp_setattro */
       0,                                    /* tp_as_buffer */
@@ -2068,6 +2070,7 @@ SwigPyPacked_TypeOnce(void) {
   static int type_init = 0;
   if (!type_init) {
     const PyTypeObject tmp = {
+      /* PyObject header changed in Python 3 */
 #if PY_VERSION_HEX>=0x03000000
       PyVarObject_HEAD_INIT(NULL, 0)
 #else
-- 
GitLab