diff --git a/Base/Axis/IAxis.cpp b/Base/Axis/IAxis.cpp
index 051c9ba8a9b9cc29ff4f1554e8c02e314ffb372e..4dfdc78fd500cbd60244bb9794d85bba4254a1b7 100644
--- a/Base/Axis/IAxis.cpp
+++ b/Base/Axis/IAxis.cpp
@@ -39,5 +39,5 @@ double IAxis::span() const {
 }
 
 double IAxis::center() const {
-    return (upperBound() + lowerBound())/2;
+    return (upperBound() + lowerBound()) / 2;
 }
diff --git a/Base/Axis/PointwiseAxis.h b/Base/Axis/PointwiseAxis.h
index 82499fcde21ebbecd80dc9daadd6dc32ce1dc95e..82de012a21d3f38b1e4d2d0eb29c6d673d2fdeca 100644
--- a/Base/Axis/PointwiseAxis.h
+++ b/Base/Axis/PointwiseAxis.h
@@ -16,6 +16,7 @@
 #error no need to expose this header to Swig
 #endif
 
+#ifndef USER_API
 #ifndef BORNAGAIN_BASE_AXIS_POINTWISEAXIS_H
 #define BORNAGAIN_BASE_AXIS_POINTWISEAXIS_H
 
@@ -89,3 +90,4 @@ private:
 };
 
 #endif // BORNAGAIN_BASE_AXIS_POINTWISEAXIS_H
+#endif // USER_API
diff --git a/Base/Const/PhysicalConstants.h b/Base/Const/PhysicalConstants.h
index d76ddd9afa14bff4c709a72e345e35efd90f21df..5ff809e4877ef0815bd13f882fbf6810ebb7b66a 100644
--- a/Base/Const/PhysicalConstants.h
+++ b/Base/Const/PhysicalConstants.h
@@ -16,6 +16,7 @@
 #error no need to expose this header to Swig
 #endif
 
+#ifndef USER_API
 #ifndef BORNAGAIN_BASE_CONST_PHYSICALCONSTANTS_H
 #define BORNAGAIN_BASE_CONST_PHYSICALCONSTANTS_H
 
@@ -35,3 +36,4 @@ constexpr double g_factor_n = -3.82608545; //!< neutron g-factor
 } // namespace PhysConsts
 
 #endif // BORNAGAIN_BASE_CONST_PHYSICALCONSTANTS_H
+#endif // USER_API
diff --git a/Base/Const/Units.h b/Base/Const/Units.h
index b8ce27bb73ea5950d1502f5e409e5bb90d9c75bc..5832545c91903fe344209e97e5c32d574c18271a 100644
--- a/Base/Const/Units.h
+++ b/Base/Const/Units.h
@@ -16,45 +16,49 @@
 #define BORNAGAIN_BASE_CONST_UNITS_H
 
 //! Constants and functions for physical unit conversions.
+//!
+//! In user code, quantities that have a physical dimension should always
+//! be given in the form _value * unit_, e.g. 0.529 * angstrom for a length,
+//! or 45 * deg for an angle.
+//!
+//! Internally, BornAgain has length, angle, magnetic field units of nanometer,
+//! radians, Tesla. Therefore, in principle, the multipliers nm, rad, tesla could
+//! be ommited from code. However, to make code more readable, and to prevent
+//! misunderstandings, we recommend that physical dimension be always made clear
+//! by multiplying values with an appropriate constant, even if this expands to 1.
 
 namespace Units {
 
 // Length
-static constexpr double nanometer = 1.;
+static constexpr double nanometer = 1.; //!< Internal unit for lengths
 static constexpr double angstrom = 1.e-1 * nanometer;
 static constexpr double micrometer = 1.e+3 * nanometer;
 static constexpr double millimeter = 1.e+6 * nanometer;
-static constexpr double meter = 1.e+9 * nanometer;
 
 // Symbols for length
 static constexpr double nm = nanometer;
 
 // Area (cross-section)
 static constexpr double nm2 = nanometer * nanometer;
-static constexpr double barn = nanometer * nanometer * 1e-10;
 
 // Angle
-static constexpr double radian = 1.;
-static constexpr double milliradian = 1.e-3 * radian;
-static constexpr double degree = (3.1415926535897932 / 180.0) * radian;
-static constexpr double steradian = 1.;
+static constexpr double rad = 1.; //!< Radian, internal unit for angles
+static constexpr double deg = (3.1415926535897932 / 180.0) * rad;
+
+// Magnetic field
+static constexpr double tesla = 1.; //!< Internal unit for magnetic fields
+static constexpr double gauss = 1e-4;
 
+// Converters
+
+#ifndef SWIG
 inline double rad2deg(double angle) {
-    return angle / degree;
+    return angle / deg;
 }
 inline double deg2rad(double angle) {
-    return angle * degree;
+    return angle * deg;
 }
-
-// Symbols for (solid) angle
-static constexpr double rad = radian;
-static constexpr double mrad = milliradian;
-static constexpr double sr = steradian;
-static constexpr double deg = degree;
-
-// Magnetic field
-static constexpr double tesla = 1.;
-static constexpr double gauss = 1e-4;
+#endif // USER_API
 
 } // namespace Units
 
diff --git a/Base/Math/Bessel.h b/Base/Math/Bessel.h
index cdc9c69350942e10ca39338706ca00adf7957c8e..c9e8ee853db374c1183b5dc81e614230c3000e46 100644
--- a/Base/Math/Bessel.h
+++ b/Base/Math/Bessel.h
@@ -16,6 +16,7 @@
 #error no need to expose this header to Swig
 #endif
 
+#ifndef USER_API
 #ifndef BORNAGAIN_BASE_MATH_BESSEL_H
 #define BORNAGAIN_BASE_MATH_BESSEL_H
 
@@ -52,3 +53,4 @@ complex_t J1c(const complex_t z);
 } // namespace Math
 
 #endif // BORNAGAIN_BASE_MATH_BESSEL_H
+#endif // USER_API
diff --git a/Base/Math/Constants.h b/Base/Math/Constants.h
index a0ea072179330815627b6d786d0bf8654cd8a085..1e6d891c2c726a4c7c4cf69b350398c47a1f7327 100644
--- a/Base/Math/Constants.h
+++ b/Base/Math/Constants.h
@@ -16,6 +16,7 @@
 #error no need to expose this header to Swig
 #endif
 
+#ifndef USER_API
 #ifndef BORNAGAIN_BASE_MATH_CONSTANTS_H
 #define BORNAGAIN_BASE_MATH_CONSTANTS_H
 
@@ -53,3 +54,4 @@
 #define M_TWOPI 6.28318530717958647693
 
 #endif // BORNAGAIN_BASE_MATH_CONSTANTS_H
+#endif // USER_API
diff --git a/Base/Math/Functions.h b/Base/Math/Functions.h
index 4455282d90c3309291586b00f931dc0f2838e247..9ec04441a8ab3b4b0b78023c3b9f6f6799237e9e 100644
--- a/Base/Math/Functions.h
+++ b/Base/Math/Functions.h
@@ -16,6 +16,7 @@
 #error no need to expose this header to Swig
 #endif
 
+#ifndef USER_API
 #ifndef BORNAGAIN_BASE_MATH_FUNCTIONS_H
 #define BORNAGAIN_BASE_MATH_FUNCTIONS_H
 
@@ -64,3 +65,4 @@ double GeneratePoissonRandom(double average);
 } // Namespace Math
 
 #endif // BORNAGAIN_BASE_MATH_FUNCTIONS_H
+#endif // USER_API
diff --git a/Base/Math/IntegratorGK.h b/Base/Math/IntegratorGK.h
index b498482148577ab9e53ae14dbec43af81300c38f..c1e9d2253b95d1f0ccf19d8f5a320199beb94566 100644
--- a/Base/Math/IntegratorGK.h
+++ b/Base/Math/IntegratorGK.h
@@ -16,6 +16,7 @@
 #error no need to expose this header to Swig
 #endif
 
+#ifndef USER_API
 #ifndef BORNAGAIN_BASE_MATH_INTEGRATORGK_H
 #define BORNAGAIN_BASE_MATH_INTEGRATORGK_H
 
@@ -49,3 +50,4 @@ private:
 };
 
 #endif // BORNAGAIN_BASE_MATH_INTEGRATORGK_H
+#endif // USER_API
diff --git a/Base/Math/IntegratorMCMiser.h b/Base/Math/IntegratorMCMiser.h
index 6ebd742efe8ff86ec0be1836029ca7334bf2000c..c28bbaf956e948853885f468a715b9164a7dc598 100644
--- a/Base/Math/IntegratorMCMiser.h
+++ b/Base/Math/IntegratorMCMiser.h
@@ -16,6 +16,7 @@
 #error no need to expose this header to Swig
 #endif
 
+#ifndef USER_API
 #ifndef BORNAGAIN_BASE_MATH_INTEGRATORMCMISER_H
 #define BORNAGAIN_BASE_MATH_INTEGRATORMCMISER_H
 
@@ -119,3 +120,4 @@ double IntegratorMCMiser<T>::integrate(double* min_array, double* max_array, voi
 }
 
 #endif // BORNAGAIN_BASE_MATH_INTEGRATORMCMISER_H
+#endif // USER_API
diff --git a/Base/Math/Numeric.h b/Base/Math/Numeric.h
index 252fa097229c3690e926216c6f751375aeba4a62..022736d6099a3a0edbaa28814ec3c8655e2c68b1 100644
--- a/Base/Math/Numeric.h
+++ b/Base/Math/Numeric.h
@@ -16,6 +16,7 @@
 #error no need to expose this header to Swig
 #endif
 
+#ifndef USER_API
 #ifndef BORNAGAIN_BASE_MATH_NUMERIC_H
 #define BORNAGAIN_BASE_MATH_NUMERIC_H
 
@@ -34,3 +35,4 @@ double GetLogDifference(double a, double b);
 } // namespace Numeric
 
 #endif // BORNAGAIN_BASE_MATH_NUMERIC_H
+#endif // USER_API
diff --git a/Base/Math/Precomputed.h b/Base/Math/Precomputed.h
index 8270134a5ec1502fd0f09f64f8e213911f58ed9f..7207ce7d4140fb739552b9a8e0ae8209f66650e7 100644
--- a/Base/Math/Precomputed.h
+++ b/Base/Math/Precomputed.h
@@ -16,6 +16,7 @@
 #error no need to expose this header to Swig
 #endif
 
+#ifndef USER_API
 #ifndef BORNAGAIN_BASE_MATH_PRECOMPUTED_H
 #define BORNAGAIN_BASE_MATH_PRECOMPUTED_H
 
@@ -48,3 +49,4 @@ constexpr std::array<double, N> generateReciprocalFactorialArray() {
 } // namespace Math
 
 #endif // BORNAGAIN_BASE_MATH_PRECOMPUTED_H
+#endif // USER_API
diff --git a/Base/Pixel/PolarizationHandler.h b/Base/Pixel/PolarizationHandler.h
index 9f4ce9240d33e23b725ee5bac7a638c0949dc03d..de31a5e5640efa408a6c3461efba8eaa753459df 100644
--- a/Base/Pixel/PolarizationHandler.h
+++ b/Base/Pixel/PolarizationHandler.h
@@ -16,6 +16,7 @@
 #error no need to expose this header to Swig
 #endif
 
+#ifndef USER_API
 #ifndef BORNAGAIN_BASE_PIXEL_POLARIZATIONHANDLER_H
 #define BORNAGAIN_BASE_PIXEL_POLARIZATIONHANDLER_H
 
@@ -49,3 +50,4 @@ private:
 };
 
 #endif // BORNAGAIN_BASE_PIXEL_POLARIZATIONHANDLER_H
+#endif // USER_API
diff --git a/Base/Pixel/SimulationElement.h b/Base/Pixel/SimulationElement.h
index 7b52531e32ebd837514343cf357232f18b2e3f1d..de13b05992e7ee2b733790cd90206d6b930f5fee 100644
--- a/Base/Pixel/SimulationElement.h
+++ b/Base/Pixel/SimulationElement.h
@@ -16,6 +16,7 @@
 #error no need to expose this header to Swig
 #endif
 
+#ifndef USER_API
 #ifndef BORNAGAIN_BASE_PIXEL_SIMULATIONELEMENT_H
 #define BORNAGAIN_BASE_PIXEL_SIMULATIONELEMENT_H
 
@@ -84,3 +85,4 @@ private:
 };
 
 #endif // BORNAGAIN_BASE_PIXEL_SIMULATIONELEMENT_H
+#endif // USER_API
diff --git a/Base/Progress/DelayedProgressCounter.h b/Base/Progress/DelayedProgressCounter.h
index 9667d009de71e2fc63b598183d16ce3ed4a06dcb..e7b661a2a70341836c8d6a397b0f9b4dbfe46d62 100644
--- a/Base/Progress/DelayedProgressCounter.h
+++ b/Base/Progress/DelayedProgressCounter.h
@@ -16,6 +16,7 @@
 #error no need to expose this header to Swig
 #endif
 
+#ifndef USER_API
 #ifndef BORNAGAIN_BASE_PROGRESS_DELAYEDPROGRESSCOUNTER_H
 #define BORNAGAIN_BASE_PROGRESS_DELAYEDPROGRESSCOUNTER_H
 
@@ -40,3 +41,4 @@ private:
 };
 
 #endif // BORNAGAIN_BASE_PROGRESS_DELAYEDPROGRESSCOUNTER_H
+#endif // USER_API
diff --git a/Base/Progress/ProgressHandler.h b/Base/Progress/ProgressHandler.h
index 02b2ba6a4d8bd3899b2cfefebab03a6e4b074a03..53e0cfbabe757f286f93e12bf50fff7e91af577d 100644
--- a/Base/Progress/ProgressHandler.h
+++ b/Base/Progress/ProgressHandler.h
@@ -16,6 +16,7 @@
 #error no need to expose this header to Swig
 #endif
 
+#ifndef USER_API
 #ifndef BORNAGAIN_BASE_PROGRESS_PROGRESSHANDLER_H
 #define BORNAGAIN_BASE_PROGRESS_PROGRESSHANDLER_H
 
@@ -62,3 +63,4 @@ private:
 };
 
 #endif // BORNAGAIN_BASE_PROGRESS_PROGRESSHANDLER_H
+#endif // USER_API
diff --git a/Base/Py/PyEmbeddedUtils.h b/Base/Py/PyEmbeddedUtils.h
index c24cbb109c189e354ccdb36ea37b6824d8da1ada..a3fe229b91f9c06ca761c54b39077f2f0e7baa7d 100644
--- a/Base/Py/PyEmbeddedUtils.h
+++ b/Base/Py/PyEmbeddedUtils.h
@@ -16,6 +16,7 @@
 #error no need to expose this header to Swig
 #endif
 
+#ifndef USER_API
 #ifndef BORNAGAIN_BASE_PY_PYEMBEDDEDUTILS_H
 #define BORNAGAIN_BASE_PY_PYEMBEDDEDUTILS_H
 
@@ -53,3 +54,4 @@ std::string pythonStackTrace();
 #endif // BORNAGAIN_PYTHON
 
 #endif // BORNAGAIN_BASE_PY_PYEMBEDDEDUTILS_H
+#endif // USER_API
diff --git a/Base/Py/PyObject.h b/Base/Py/PyObject.h
index c22c63aa9c24429c8b86a233db03849f7a86db56..0d78a56d4e08dddef54e9f963de3839953c98676 100644
--- a/Base/Py/PyObject.h
+++ b/Base/Py/PyObject.h
@@ -16,6 +16,7 @@
 #error no need to expose this header to Swig
 #endif
 
+#ifndef USER_API
 #ifndef BORNAGAIN_BASE_PY_PYOBJECT_H
 #define BORNAGAIN_BASE_PY_PYOBJECT_H
 
@@ -27,3 +28,4 @@ typedef _object PyObject;
 #endif
 
 #endif // BORNAGAIN_BASE_PY_PYOBJECT_H
+#endif // USER_API
diff --git a/Base/Py/PythonCore.h b/Base/Py/PythonCore.h
index 380e25400ca5dc78583b0f2f28e35f2b259c73cb..11cd0d4518d5a642b7d2cb122fb7d30559db9bfa 100644
--- a/Base/Py/PythonCore.h
+++ b/Base/Py/PythonCore.h
@@ -16,6 +16,7 @@
 #error no need to expose this header to Swig
 #endif
 
+#ifndef USER_API
 #ifndef BORNAGAIN_BASE_PY_PYTHONCORE_H
 #define BORNAGAIN_BASE_PY_PYTHONCORE_H
 
@@ -46,3 +47,4 @@
 #endif // BORNAGAIN_PYTHON
 
 #endif // BORNAGAIN_BASE_PY_PYTHONCORE_H
+#endif // USER_API
diff --git a/Base/Types/CloneableVector.h b/Base/Types/CloneableVector.h
index 5ed210b48d826f69382a9d55bbc3c9f1e928981d..cf207935bf285b6512a902c5eac97a25d938c221 100644
--- a/Base/Types/CloneableVector.h
+++ b/Base/Types/CloneableVector.h
@@ -16,6 +16,7 @@
 #error no need to expose this header to Swig
 #endif
 
+#ifndef USER_API
 #ifndef BORNAGAIN_BASE_TYPES_CLONEABLEVECTOR_H
 #define BORNAGAIN_BASE_TYPES_CLONEABLEVECTOR_H
 
@@ -46,3 +47,4 @@ public:
 };
 
 #endif // BORNAGAIN_BASE_TYPES_CLONEABLEVECTOR_H
+#endif // USER_API
diff --git a/Base/Types/SafePointerVector.h b/Base/Types/SafePointerVector.h
index 257ccc8987e0143bfa56356e718533865f95156b..2306a3cad1fd51dec6541c2eca9ed12544a489d5 100644
--- a/Base/Types/SafePointerVector.h
+++ b/Base/Types/SafePointerVector.h
@@ -16,6 +16,7 @@
 #error no need to expose this header to Swig
 #endif
 
+#ifndef USER_API
 #ifndef BORNAGAIN_BASE_TYPES_SAFEPOINTERVECTOR_H
 #define BORNAGAIN_BASE_TYPES_SAFEPOINTERVECTOR_H
 
@@ -90,3 +91,4 @@ template <class T> void SafePointerVector<T>::clear() {
 }
 
 #endif // BORNAGAIN_BASE_TYPES_SAFEPOINTERVECTOR_H
+#endif // USER_API
diff --git a/Base/Utils/Algorithms.h b/Base/Utils/Algorithms.h
index f5e6a6d181826d78732a6fcaa7f7d67e1f77cfac..014b21dce309366bbf145b1bc816817fb2bfbcc5 100644
--- a/Base/Utils/Algorithms.h
+++ b/Base/Utils/Algorithms.h
@@ -16,6 +16,7 @@
 #error no need to expose this header to Swig
 #endif
 
+#ifndef USER_API
 #ifndef BORNAGAIN_BASE_UTILS_ALGORITHMS_H
 #define BORNAGAIN_BASE_UTILS_ALGORITHMS_H
 
@@ -79,3 +80,4 @@ template <class T> std::vector<T> algo::concat(const std::vector<T>& v1, const s
 }
 
 #endif // BORNAGAIN_BASE_UTILS_ALGORITHMS_H
+#endif // USER_API
diff --git a/Base/Utils/Assert.h b/Base/Utils/Assert.h
index a4f3bcd3e691c644ffe74d2dfe95124b4eafd217..bc8ab08ef958befc167c12f5ea6ba18731df6d64 100644
--- a/Base/Utils/Assert.h
+++ b/Base/Utils/Assert.h
@@ -16,6 +16,7 @@
 #error no need to expose this header to Swig
 #endif
 
+#ifndef USER_API
 #ifndef BORNAGAIN_BASE_UTILS_ASSERT_H
 #define BORNAGAIN_BASE_UTILS_ASSERT_H
 
@@ -35,3 +36,4 @@
     }
 
 #endif // BORNAGAIN_BASE_UTILS_ASSERT_H
+#endif // USER_API
diff --git a/Base/Utils/FileSystemUtils.h b/Base/Utils/FileSystemUtils.h
index 86dc937ae8a76f5b2b145f97eb39788aeb8fb14f..1d3f0f2f72b0d0cc709fdc3503be686ed2592987 100644
--- a/Base/Utils/FileSystemUtils.h
+++ b/Base/Utils/FileSystemUtils.h
@@ -16,6 +16,7 @@
 #error no need to expose this header to Swig
 #endif
 
+#ifndef USER_API
 #ifndef BORNAGAIN_BASE_UTILS_FILESYSTEMUTILS_H
 #define BORNAGAIN_BASE_UTILS_FILESYSTEMUTILS_H
 
@@ -69,3 +70,4 @@ bool IsFileExists(const std::string& path);
 } // namespace FileSystemUtils
 
 #endif // BORNAGAIN_BASE_UTILS_FILESYSTEMUTILS_H
+#endif // USER_API
diff --git a/Base/Utils/StringUtils.h b/Base/Utils/StringUtils.h
index 73c26cd0bbf5a96c10b34392c9f71c981b0640a0..e3e090c262d5b32d0ebc1b36109f6967fc804e2b 100644
--- a/Base/Utils/StringUtils.h
+++ b/Base/Utils/StringUtils.h
@@ -16,6 +16,7 @@
 #error no need to expose this header to Swig
 #endif
 
+#ifndef USER_API
 #ifndef BORNAGAIN_BASE_UTILS_STRINGUTILS_H
 #define BORNAGAIN_BASE_UTILS_STRINGUTILS_H
 
@@ -64,3 +65,4 @@ template <typename T> std::string StringUtils::scientific(const T value, int n)
 }
 
 #endif // BORNAGAIN_BASE_UTILS_STRINGUTILS_H
+#endif // USER_API
diff --git a/Base/Utils/SysUtils.h b/Base/Utils/SysUtils.h
index 536ff1333ddd40bd07c7f1e9742e992d682f07c8..23449da5ffa18ac8756bb544e53e1bdf5096370b 100644
--- a/Base/Utils/SysUtils.h
+++ b/Base/Utils/SysUtils.h
@@ -16,6 +16,7 @@
 #error no need to expose this header to Swig
 #endif
 
+#ifndef USER_API
 #ifndef BORNAGAIN_BASE_UTILS_SYSUTILS_H
 #define BORNAGAIN_BASE_UTILS_SYSUTILS_H
 
@@ -39,3 +40,4 @@ bool isWindowsHost();
 } // namespace SysUtils
 
 #endif // BORNAGAIN_BASE_UTILS_SYSUTILS_H
+#endif // USER_API
diff --git a/Base/Vector/BasicVector3D.h b/Base/Vector/BasicVector3D.h
index 6893c3f053ed4c4953551de2aec33f05ba180ec2..94fabbd7bfe7220a55215d3cecb7474160bb0247 100644
--- a/Base/Vector/BasicVector3D.h
+++ b/Base/Vector/BasicVector3D.h
@@ -9,17 +9,17 @@
 //! @license   GNU General Public License v3 or higher (see COPYING)
 //! @copyright Forschungszentrum Jülich GmbH 2018
 //! @authors   Scientific Computing Group at MLZ (see CITATION, AUTHORS)
+//!
+//! Forked from CLHEP/Geometry by E. Chernyaev <Evgueni.Tcherniaev@cern.ch>,
+//! then reworked beyond recognition. Removed split of point and vector semantics.
+//! Transforms are relegated to a separate class Transform3D.
 //
 //  ************************************************************************************************
 
 #ifndef BORNAGAIN_BASE_VECTOR_BASICVECTOR3D_H
 #define BORNAGAIN_BASE_VECTOR_BASICVECTOR3D_H
 
-//! Forked from CLHEP/Geometry by E. Chernyaev <Evgueni.Tcherniaev@cern.ch>,
-//! then reworked beyond recognition. Removed split of point and vector semantics.
-//! Transforms are relegated to a separate class Transform3D.
-
-#include <complex>
+#include "Base/Types/Complex.h"
 
 //! Three-dimensional vector template, for use with integer, double, or complex components.
 //! @ingroup tools_internal
@@ -99,7 +99,7 @@ public:
         v_[2] *= a;
         return *this;
     }
-#endif // SWIG
+#endif // USER_API
 
     //! Divides this by a scalar, and returns result.
 #ifndef SWIG
@@ -109,7 +109,7 @@ public:
         v_[2] /= a;
         return *this;
     }
-#endif // SWIG
+#endif // USER_API
 
     // -------------------------------------------------------------------------
     // Functions of this (with no further argument)
@@ -146,7 +146,7 @@ public:
     BasicVector3D<T> unit() const;
 
     //! Returns this, trivially converted to complex type.
-    BasicVector3D<std::complex<double>> complex() const;
+    BasicVector3D<complex_t> complex() const;
 
     //! Returns real parts.
     BasicVector3D<double> real() const;
@@ -158,12 +158,12 @@ public:
     //! Returns dot product of vectors (antilinear in the first [=self] argument).
 #ifndef SWIG
     template <class U> auto dot(const BasicVector3D<U>& v) const;
-#endif // SWIG
+#endif // USER_API
 
     //! Returns cross product of vectors (linear in both arguments).
 #ifndef SWIG
     template <class U> auto cross(const BasicVector3D<U>& v) const;
-#endif // SWIG
+#endif // USER_API
 
     //! Returns angle with respect to another vector.
     double angle(const BasicVector3D<T>& v) const;
@@ -239,7 +239,7 @@ inline BasicVector3D<T> operator-(const BasicVector3D<T>& a, const BasicVector3D
 template <class T, class U> inline auto operator*(const BasicVector3D<T>& v, const U a) {
     return BasicVector3D<decltype(v.x() * a)>(v.x() * a, v.y() * a, v.z() * a);
 }
-#endif // SWIG
+#endif // USER_API
 
 //! Multiplication scalar by vector.
 //! @relates BasicVector3D
@@ -247,7 +247,7 @@ template <class T, class U> inline auto operator*(const BasicVector3D<T>& v, con
 template <class T, class U> inline auto operator*(const U a, const BasicVector3D<T>& v) {
     return BasicVector3D<decltype(a * v.x())>(a * v.x(), a * v.y(), a * v.z());
 }
-#endif // SWIG
+#endif // USER_API
 
 // vector*vector not supported
 //    (We do not provide the operator form a*b of the dot product:
@@ -284,7 +284,7 @@ inline auto BasicVector3D<T>::dot(const BasicVector3D<U>& v) const {
     BasicVector3D<T> left_star = this->conj();
     return left_star.x() * v.x() + left_star.y() * v.y() + left_star.z() * v.z();
 }
-#endif // SWIG
+#endif // USER_API
 
 //! Returns cross product of (complex) vectors.
 #ifndef SWIG
@@ -294,11 +294,11 @@ inline auto BasicVector3D<T>::cross(const BasicVector3D<U>& v) const {
     return BasicVector3D<decltype(this->x() * v.x())>(
         y() * v.z() - v.y() * z(), z() * v.x() - v.z() * x(), x() * v.y() - v.x() * y());
 }
-#endif // SWIG
+#endif // USER_API
 
 template <> BasicVector3D<double> BasicVector3D<double>::conj() const;
 
-template <> BasicVector3D<std::complex<double>> BasicVector3D<std::complex<double>>::conj() const;
+template <> BasicVector3D<complex_t> BasicVector3D<complex_t>::conj() const;
 
 template <> double BasicVector3D<double>::phi() const;
 
@@ -308,15 +308,15 @@ template <> double BasicVector3D<double>::cosTheta() const;
 
 template <> double BasicVector3D<double>::sin2Theta() const;
 
-template <> BasicVector3D<std::complex<double>> BasicVector3D<double>::complex() const;
+template <> BasicVector3D<complex_t> BasicVector3D<double>::complex() const;
 
 template <> BasicVector3D<double> BasicVector3D<double>::real() const;
 
-template <> BasicVector3D<double> BasicVector3D<std::complex<double>>::real() const;
+template <> BasicVector3D<double> BasicVector3D<complex_t>::real() const;
 
 template <> BasicVector3D<double> BasicVector3D<double>::unit() const;
 
-template <> BasicVector3D<std::complex<double>> BasicVector3D<std::complex<double>>::unit() const;
+template <> BasicVector3D<complex_t> BasicVector3D<complex_t>::unit() const;
 
 template <> double BasicVector3D<double>::angle(const BasicVector3D<double>& v) const;
 
diff --git a/Base/Vector/Direction.h b/Base/Vector/Direction.h
index 5aa0b4e6aa1bcf74e57015fe0634bf1f1a02db62..47b704539b1d1141b7ea2e93b3149f9573741272 100644
--- a/Base/Vector/Direction.h
+++ b/Base/Vector/Direction.h
@@ -19,6 +19,8 @@
 
 kvector_t vecOfLambdaAlphaPhi(double _lambda, double _alpha, double _phi);
 
+//! A direction in three-dimensional space.
+
 class Direction {
 public:
     Direction(double alpha, double phi) : m_alpha(alpha), m_phi(phi) {}
diff --git a/Base/Vector/EigenCore.h b/Base/Vector/EigenCore.h
index 12c07911a573254cf3b012cae3b94fd5246bb9a8..68ca88e4efb3363770d696d414a4b8f966527240 100644
--- a/Base/Vector/EigenCore.h
+++ b/Base/Vector/EigenCore.h
@@ -16,6 +16,7 @@
 #error no need to expose this header to Swig
 #endif
 
+#ifndef USER_API
 #ifndef BORNAGAIN_BASE_VECTOR_EIGENCORE_H
 #define BORNAGAIN_BASE_VECTOR_EIGENCORE_H
 
@@ -34,3 +35,4 @@
 #endif
 
 #endif // BORNAGAIN_BASE_VECTOR_EIGENCORE_H
+#endif // USER_API
diff --git a/Base/Vector/Transform3D.h b/Base/Vector/Transform3D.h
index 5e4cdac7ecd94bcc12066811c3edd62305065095..66ee79934603b48b5027c7dfecb3fba0a5ec3e66 100644
--- a/Base/Vector/Transform3D.h
+++ b/Base/Vector/Transform3D.h
@@ -16,6 +16,7 @@
 #error no need to expose this header to Swig
 #endif
 
+#ifndef USER_API
 #ifndef BORNAGAIN_BASE_VECTOR_TRANSFORM3D_H
 #define BORNAGAIN_BASE_VECTOR_TRANSFORM3D_H
 
@@ -113,3 +114,4 @@ private:
 };
 
 #endif // BORNAGAIN_BASE_VECTOR_TRANSFORM3D_H
+#endif // USER_API
diff --git a/Base/Vector/Vectors3D.h b/Base/Vector/Vectors3D.h
index f599ef439a3998892f25f449ad1a895cc9e86b11..692fb0475a6df2154b57f6e18216371e0ae554f3 100644
--- a/Base/Vector/Vectors3D.h
+++ b/Base/Vector/Vectors3D.h
@@ -19,6 +19,6 @@
 
 using ivector_t = BasicVector3D<int>;
 using kvector_t = BasicVector3D<double>;
-using cvector_t = BasicVector3D<std::complex<double>>;
+using cvector_t = BasicVector3D<complex_t>;
 
 #endif // BORNAGAIN_BASE_VECTOR_VECTORS3D_H
diff --git a/CHANGELOG b/CHANGELOG
index fa35811f78963848abfb40e1e60d0c43a1160502..049d162bd1ab3ca3b77c77121752cc62199dd57e 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -4,14 +4,16 @@ BornAgain-1.18.99, ongoing development
     * Removed "get" from several accessor functions
     * Class Instrument removed  from Python API (instead use simulation.beam() etc)
     * Lattice has been renamed to Lattice3D, for clearer disambuation from Lattice2D
+    * "OffSpecular" instead of "OffSpec"
     * Removed some interference functions constructors
     * Remove old R&T computations from API (now in Code/Legacy and Tests)
     * Python plot API entirely keyword based
   > Fixes of unreported bugs:
     * Several GUI bugs that caused crashes
     * For alpha_i=0, set scattered intensity to 0
-  > Examples:
-    * Uniform API usage in line with exported Python code
+  > Documentation:
+    * Unified API usage in many examples, using BornAgain's Python exporter
+    * Removed many entries from Doxygen user API
   > Internal refactoring:
     * Moved code to break directory include cycles
     * Renamed a few classes (ISimulation)
diff --git a/CMakeLists.txt b/CMakeLists.txt
index cceaf3cc385497a0ce53b79aba5cac6b2b29e745..7903e34465e01ae0f9d21cd9b2479bf0d436f7bc 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -72,9 +72,10 @@ endif()
 ## Various CMake settings (include order is of critical importance)
 
 # function definitions
-include(commons/GetFilenameComponent) # overwrite CMake command
-include(BornAgain/MakeLib)
-include(BornAgain/SwigLib)
+include(commons/GetFilenameComponent) # fct get_filename_component (overwrites CMake's built-in)
+include(BornAgain/PythonDocs) # fct GeneratePythonDocs
+include(BornAgain/SwigLib) # fct SwigLib
+include(BornAgain/MakeLib) # fct MakeLib
 
 # main settings
 
@@ -104,7 +105,6 @@ include(BornAgain/Config)
 if(BORNAGAIN_PYTHON)
     include(BornAgain/PythonAPI)
 endif()
-include(BornAgain/PythonDocs)
 
 # debug optimization
 if(BORNAGAIN_DEBUG_OPTIMIZATION)
diff --git a/Core/Computation/ComputationStatus.h b/Core/Computation/ComputationStatus.h
index b8722c5ec697d1ec0547f00787be6089ba3a8cd6..dc772ae0a780d9a7d7da395b9a8130f5a3590516 100644
--- a/Core/Computation/ComputationStatus.h
+++ b/Core/Computation/ComputationStatus.h
@@ -16,6 +16,7 @@
 #error no need to expose this header to Swig
 #endif
 
+#ifndef USER_API
 #ifndef BORNAGAIN_CORE_COMPUTATION_COMPUTATIONSTATUS_H
 #define BORNAGAIN_CORE_COMPUTATION_COMPUTATIONSTATUS_H
 
@@ -46,3 +47,4 @@ private:
 };
 
 #endif // BORNAGAIN_CORE_COMPUTATION_COMPUTATIONSTATUS_H
+#endif // USER_API
diff --git a/Core/Computation/DWBAComputation.h b/Core/Computation/DWBAComputation.h
index d4219a5b5f1aacf4a862688c24ef02100d69d44d..f6d10cea7212c0cfeeab57e414328db67c2bdecc 100644
--- a/Core/Computation/DWBAComputation.h
+++ b/Core/Computation/DWBAComputation.h
@@ -16,6 +16,7 @@
 #error no need to expose this header to Swig
 #endif
 
+#ifndef USER_API
 #ifndef BORNAGAIN_CORE_COMPUTATION_DWBACOMPUTATION_H
 #define BORNAGAIN_CORE_COMPUTATION_DWBACOMPUTATION_H
 
@@ -48,3 +49,4 @@ private:
 };
 
 #endif // BORNAGAIN_CORE_COMPUTATION_DWBACOMPUTATION_H
+#endif // USER_API
diff --git a/Core/Computation/DWBASingleComputation.h b/Core/Computation/DWBASingleComputation.h
index 9afed99c0b0c8f7c2480142357fae91aa4a2f7d0..c686c2263c84bd5842206aae47bb019087b63029 100644
--- a/Core/Computation/DWBASingleComputation.h
+++ b/Core/Computation/DWBASingleComputation.h
@@ -16,6 +16,7 @@
 #error no need to expose this header to Swig
 #endif
 
+#ifndef USER_API
 #ifndef BORNAGAIN_CORE_COMPUTATION_DWBASINGLECOMPUTATION_H
 #define BORNAGAIN_CORE_COMPUTATION_DWBASINGLECOMPUTATION_H
 
@@ -59,3 +60,4 @@ private:
 };
 
 #endif // BORNAGAIN_CORE_COMPUTATION_DWBASINGLECOMPUTATION_H
+#endif // USER_API
diff --git a/Core/Computation/DepthProbeComputation.h b/Core/Computation/DepthProbeComputation.h
index f1b7a0d9bd6956c167107435faf7a0685cdfca74..f1f9c96326d0ebeee820c41204b93b44f18bb040 100644
--- a/Core/Computation/DepthProbeComputation.h
+++ b/Core/Computation/DepthProbeComputation.h
@@ -16,6 +16,7 @@
 #error no need to expose this header to Swig
 #endif
 
+#ifndef USER_API
 #ifndef BORNAGAIN_CORE_COMPUTATION_DEPTHPROBECOMPUTATION_H
 #define BORNAGAIN_CORE_COMPUTATION_DEPTHPROBECOMPUTATION_H
 
@@ -47,3 +48,4 @@ private:
 };
 
 #endif // BORNAGAIN_CORE_COMPUTATION_DEPTHPROBECOMPUTATION_H
+#endif // USER_API
diff --git a/Core/Computation/GISASSpecularComputation.h b/Core/Computation/GISASSpecularComputation.h
index 6ad78fcc13af44a9dc2a5f35d0623c330d01d441..0302aa78bd788db1342db1d08b63191037b30ea1 100644
--- a/Core/Computation/GISASSpecularComputation.h
+++ b/Core/Computation/GISASSpecularComputation.h
@@ -16,6 +16,7 @@
 #error no need to expose this header to Swig
 #endif
 
+#ifndef USER_API
 #ifndef BORNAGAIN_CORE_COMPUTATION_GISASSPECULARCOMPUTATION_H
 #define BORNAGAIN_CORE_COMPUTATION_GISASSPECULARCOMPUTATION_H
 
@@ -36,3 +37,4 @@ private:
 };
 
 #endif // BORNAGAIN_CORE_COMPUTATION_GISASSPECULARCOMPUTATION_H
+#endif // USER_API
diff --git a/Core/Computation/IComputation.h b/Core/Computation/IComputation.h
index 64e500e348359a9b45721a30f7d638dd013834e3..6b7e9e83246f662ea08d2c0982b654f9bc1fa188 100644
--- a/Core/Computation/IComputation.h
+++ b/Core/Computation/IComputation.h
@@ -16,6 +16,7 @@
 #error no need to expose this header to Swig
 #endif
 
+#ifndef USER_API
 #ifndef BORNAGAIN_CORE_COMPUTATION_ICOMPUTATION_H
 #define BORNAGAIN_CORE_COMPUTATION_ICOMPUTATION_H
 
@@ -57,3 +58,4 @@ private:
 };
 
 #endif // BORNAGAIN_CORE_COMPUTATION_ICOMPUTATION_H
+#endif // USER_API
diff --git a/Core/Computation/ParticleLayoutComputation.h b/Core/Computation/ParticleLayoutComputation.h
index ece5291210950a55e3f567b99d8320c3cfe52aa2..ce37377cb62ec84162c48a2411229bb664b4794d 100644
--- a/Core/Computation/ParticleLayoutComputation.h
+++ b/Core/Computation/ParticleLayoutComputation.h
@@ -16,6 +16,7 @@
 #error no need to expose this header to Swig
 #endif
 
+#ifndef USER_API
 #ifndef BORNAGAIN_CORE_COMPUTATION_PARTICLELAYOUTCOMPUTATION_H
 #define BORNAGAIN_CORE_COMPUTATION_PARTICLELAYOUTCOMPUTATION_H
 
@@ -51,3 +52,4 @@ private:
 };
 
 #endif // BORNAGAIN_CORE_COMPUTATION_PARTICLELAYOUTCOMPUTATION_H
+#endif // USER_API
diff --git a/Core/Computation/RoughMultiLayerComputation.h b/Core/Computation/RoughMultiLayerComputation.h
index 0cf04d5d59896f1aa7529397814374e0c83026b0..453694b283a4eab76f79885656d6361c9bcc485e 100644
--- a/Core/Computation/RoughMultiLayerComputation.h
+++ b/Core/Computation/RoughMultiLayerComputation.h
@@ -16,6 +16,7 @@
 #error no need to expose this header to Swig
 #endif
 
+#ifndef USER_API
 #ifndef BORNAGAIN_CORE_COMPUTATION_ROUGHMULTILAYERCOMPUTATION_H
 #define BORNAGAIN_CORE_COMPUTATION_ROUGHMULTILAYERCOMPUTATION_H
 
@@ -41,3 +42,4 @@ private:
 };
 
 #endif // BORNAGAIN_CORE_COMPUTATION_ROUGHMULTILAYERCOMPUTATION_H
+#endif // USER_API
diff --git a/Core/Computation/SpecularComputation.h b/Core/Computation/SpecularComputation.h
index b28e414ed935e9fd0de8a9f1ee42449d9dbdfcf9..298914c8ecc4bbf07f7340983c900513c2fbbee6 100644
--- a/Core/Computation/SpecularComputation.h
+++ b/Core/Computation/SpecularComputation.h
@@ -16,6 +16,7 @@
 #error no need to expose this header to Swig
 #endif
 
+#ifndef USER_API
 #ifndef BORNAGAIN_CORE_COMPUTATION_SPECULARCOMPUTATION_H
 #define BORNAGAIN_CORE_COMPUTATION_SPECULARCOMPUTATION_H
 
@@ -49,3 +50,4 @@ private:
 };
 
 #endif // BORNAGAIN_CORE_COMPUTATION_SPECULARCOMPUTATION_H
+#endif // USER_API
diff --git a/Core/Element/DepthProbeElement.h b/Core/Element/DepthProbeElement.h
index 04b23e9ad588973ca214c8188305df47f886d5dd..73c0d1c4cd51a5f0924dd7ce3149c2fb9ccc3976 100644
--- a/Core/Element/DepthProbeElement.h
+++ b/Core/Element/DepthProbeElement.h
@@ -16,6 +16,7 @@
 #error no need to expose this header to Swig
 #endif
 
+#ifndef USER_API
 #ifndef BORNAGAIN_CORE_ELEMENT_DEPTHPROBEELEMENT_H
 #define BORNAGAIN_CORE_ELEMENT_DEPTHPROBEELEMENT_H
 
@@ -67,3 +68,4 @@ private:
 };
 
 #endif // BORNAGAIN_CORE_ELEMENT_DEPTHPROBEELEMENT_H
+#endif // USER_API
diff --git a/Core/Element/SpecularSimulationElement.h b/Core/Element/SpecularSimulationElement.h
index f2172237d011f600035b6d349b397368d6ddb661..07877f48efb721c20d0c8ce1e5cad2b2f1134f33 100644
--- a/Core/Element/SpecularSimulationElement.h
+++ b/Core/Element/SpecularSimulationElement.h
@@ -16,6 +16,7 @@
 #error no need to expose this header to Swig
 #endif
 
+#ifndef USER_API
 #ifndef BORNAGAIN_CORE_ELEMENT_SPECULARSIMULATIONELEMENT_H
 #define BORNAGAIN_CORE_ELEMENT_SPECULARSIMULATIONELEMENT_H
 
@@ -64,3 +65,4 @@ private:
 };
 
 #endif // BORNAGAIN_CORE_ELEMENT_SPECULARSIMULATIONELEMENT_H
+#endif // USER_API
diff --git a/Core/Export/ComponentKeyHandler.h b/Core/Export/ComponentKeyHandler.h
index d13f5b186a12040e642cd9a0798a4bef94101485..e4d39ae0b05913fa18ab56f5d241f5e95bc764e3 100644
--- a/Core/Export/ComponentKeyHandler.h
+++ b/Core/Export/ComponentKeyHandler.h
@@ -16,6 +16,7 @@
 #error no need to expose this header to Swig
 #endif
 
+#ifndef USER_API
 #ifndef BORNAGAIN_CORE_EXPORT_COMPONENTKEYHANDLER_H
 #define BORNAGAIN_CORE_EXPORT_COMPONENTKEYHANDLER_H
 
@@ -49,3 +50,4 @@ template <class T> std::vector<const T*> ComponentKeyHandler::objectsOfType() co
 }
 
 #endif // BORNAGAIN_CORE_EXPORT_COMPONENTKEYHANDLER_H
+#endif // USER_API
diff --git a/Core/Export/MaterialKeyHandler.h b/Core/Export/MaterialKeyHandler.h
index c0356ca249175044f53c7659a3845b9849b55389..7ca324a2f53c7f1a3397c18ca063200c9c083b00 100644
--- a/Core/Export/MaterialKeyHandler.h
+++ b/Core/Export/MaterialKeyHandler.h
@@ -16,6 +16,7 @@
 #error no need to expose this header to Swig
 #endif
 
+#ifndef USER_API
 #ifndef BORNAGAIN_CORE_EXPORT_MATERIALKEYHANDLER_H
 #define BORNAGAIN_CORE_EXPORT_MATERIALKEYHANDLER_H
 
@@ -41,3 +42,4 @@ private:
 };
 
 #endif // BORNAGAIN_CORE_EXPORT_MATERIALKEYHANDLER_H
+#endif // USER_API
diff --git a/Core/Export/NodeProgeny.h b/Core/Export/NodeProgeny.h
index 74ea17191494aee96060e7a8e9200014bdd040ac..e6ea027979ccc7353e0f022032160fc0fab85507 100644
--- a/Core/Export/NodeProgeny.h
+++ b/Core/Export/NodeProgeny.h
@@ -16,6 +16,7 @@
 #error no need to expose this header to Swig
 #endif
 
+#ifndef USER_API
 #ifndef BORNAGAIN_CORE_EXPORT_NODEPROGENY_H
 #define BORNAGAIN_CORE_EXPORT_NODEPROGENY_H
 
@@ -53,3 +54,4 @@ template <typename T> std::vector<const T*> AllDescendantsOfType(const INode& no
 } // namespace node_progeny
 
 #endif // BORNAGAIN_CORE_EXPORT_NODEPROGENY_H
+#endif // USER_API
diff --git a/Core/Export/PyFmt.cpp b/Core/Export/PyFmt.cpp
index fb24b391dbb2acdf4233e59bcf5b9582bf8f3e27..c19b4e5f7b73acbfe9058b5ced20d978950173f8 100644
--- a/Core/Export/PyFmt.cpp
+++ b/Core/Export/PyFmt.cpp
@@ -22,8 +22,8 @@ namespace pyfmt {
 
 std::string scriptPreamble() {
     return "import numpy, sys\n"
-        "import bornagain as ba\n"
-        "from bornagain import angstrom, deg, micrometer, nm, nm2, kvector_t\n\n\n";
+           "import bornagain as ba\n"
+           "from bornagain import angstrom, deg, micrometer, nm, nm2, kvector_t\n\n\n";
 }
 
 std::string printBool(double value) {
diff --git a/Core/Export/PyFmt.h b/Core/Export/PyFmt.h
index bc199db5f8af7f501aadf60335af9454e152ddc9..5bcd068d5a1293c7ac55a761cf2b964bd572724a 100644
--- a/Core/Export/PyFmt.h
+++ b/Core/Export/PyFmt.h
@@ -16,6 +16,7 @@
 #error no need to expose this header to Swig
 #endif
 
+#ifndef USER_API
 #ifndef BORNAGAIN_CORE_EXPORT_PYFMT_H
 #define BORNAGAIN_CORE_EXPORT_PYFMT_H
 
@@ -51,3 +52,4 @@ std::string indent(size_t width = 4u);
 } // namespace pyfmt
 
 #endif // BORNAGAIN_CORE_EXPORT_PYFMT_H
+#endif // USER_API
diff --git a/Core/Export/PyFmt2.h b/Core/Export/PyFmt2.h
index 9770bef40afafcb41d08bb62d2fd7f3657aab39e..e91045b89235b71f5838bff2a0b37e00072d2f22 100644
--- a/Core/Export/PyFmt2.h
+++ b/Core/Export/PyFmt2.h
@@ -16,6 +16,7 @@
 #error no need to expose this header to Swig
 #endif
 
+#ifndef USER_API
 #ifndef BORNAGAIN_CORE_EXPORT_PYFMT2_H
 #define BORNAGAIN_CORE_EXPORT_PYFMT2_H
 
@@ -53,3 +54,4 @@ std::string printRangedDistribution(const IRangedDistribution& distr);
 } // namespace pyfmt2
 
 #endif // BORNAGAIN_CORE_EXPORT_PYFMT2_H
+#endif // USER_API
diff --git a/Core/Export/PyFmtLimits.h b/Core/Export/PyFmtLimits.h
index 9bb5dfd9d0f7cbe8166508e9fbda0d85ca06bce8..2684435c88e016d7774c3a7cb35ab5a9867a7059 100644
--- a/Core/Export/PyFmtLimits.h
+++ b/Core/Export/PyFmtLimits.h
@@ -16,6 +16,7 @@
 #error no need to expose this header to Swig
 #endif
 
+#ifndef USER_API
 #ifndef BORNAGAIN_CORE_EXPORT_PYFMTLIMITS_H
 #define BORNAGAIN_CORE_EXPORT_PYFMTLIMITS_H
 
@@ -31,3 +32,4 @@ std::string printRealLimitsArg(const RealLimits& limits, const std::string& unit
 } // namespace pyfmt
 
 #endif // BORNAGAIN_CORE_EXPORT_PYFMTLIMITS_H
+#endif // USER_API
diff --git a/Core/Export/SampleToPython.h b/Core/Export/SampleToPython.h
index 18074fdb2185a50d0a2da436c2f8bfff6ef17a53..b195d0bb025277514d83ac649081e416e91c69c3 100644
--- a/Core/Export/SampleToPython.h
+++ b/Core/Export/SampleToPython.h
@@ -16,6 +16,7 @@
 #error no need to expose this header to Swig
 #endif
 
+#ifndef USER_API
 #ifndef BORNAGAIN_CORE_EXPORT_SAMPLETOPYTHON_H
 #define BORNAGAIN_CORE_EXPORT_SAMPLETOPYTHON_H
 
@@ -61,3 +62,4 @@ private:
 };
 
 #endif // BORNAGAIN_CORE_EXPORT_SAMPLETOPYTHON_H
+#endif // USER_API
diff --git a/Core/Export/SimulationToPython.cpp b/Core/Export/SimulationToPython.cpp
index 178fb875ed9c8484d86b323e1af3a6f513f06c94..710d3a25ad4fd3def2ef09beb08d28b4a652e9c4 100644
--- a/Core/Export/SimulationToPython.cpp
+++ b/Core/Export/SimulationToPython.cpp
@@ -24,7 +24,7 @@
 #include "Core/Scan/AngularSpecScan.h"
 #include "Core/Scan/QSpecScan.h"
 #include "Core/Simulation/GISASSimulation.h"
-#include "Core/Simulation/OffSpecSimulation.h"
+#include "Core/Simulation/OffSpecularSimulation.h"
 #include "Core/Simulation/SpecularSimulation.h"
 #include "Device/Beam/FootprintGauss.h"
 #include "Device/Beam/FootprintSquare.h"
@@ -128,7 +128,7 @@ std::string defineDetector(const ISimulation* simulation) {
     result << std::setprecision(12);
 
     if (const auto* const det = dynamic_cast<const SphericalDetector*>(detector)) {
-        ASSERT(det->dimension()==2);
+        ASSERT(det->dimension() == 2);
         if (DetectorUtils::isQuadratic(*det)) {
             result << indent() << "nbin = " << det->axis(0).size() << "\n";
             result << indent() << "detector = ba.SphericalDetector(nbin, "
@@ -141,8 +141,7 @@ std::string defineDetector(const ISimulation* simulation) {
             result << indent() << "detector = ba.SphericalDetector(nx, "
                    << pyfmt::printDegrees(det->axis(0).lowerBound()) << ", "
                    << pyfmt::printDegrees(det->axis(0).upperBound()) << ", "
-                   << "ny , "
-                   << pyfmt::printDegrees(det->axis(1).lowerBound()) << ", "
+                   << "ny , " << pyfmt::printDegrees(det->axis(1).lowerBound()) << ", "
                    << pyfmt::printDegrees(det->axis(1).upperBound());
         }
         result << ")\n";
@@ -258,7 +257,7 @@ std::string defineBeamIntensity(const Beam& beam) {
     std::ostringstream result;
     double beam_intensity = beam.intensity();
     if (beam_intensity > 0.0)
-        result << indent() << "simulation.setBeamIntensity("
+        result << indent() << "simulation.beam().setIntensity("
                << pyfmt::printScientificDouble(beam_intensity) << ")\n";
     return result.str();
 }
@@ -277,7 +276,7 @@ std::string defineGISASBeam(const GISASSimulation& simulation) {
     return result.str();
 }
 
-std::string defineOffSpecBeam(const OffSpecSimulation& simulation) {
+std::string defineOffSpecularBeam(const OffSpecularSimulation& simulation) {
     std::ostringstream result;
     const Beam& beam = simulation.instrument().beam();
 
@@ -398,13 +397,13 @@ std::string defineGISASSimulation(const GISASSimulation* simulation) {
     return result.str();
 }
 
-std::string defineOffSpecSimulation(const OffSpecSimulation* simulation) {
+std::string defineOffSpecularSimulation(const OffSpecularSimulation* simulation) {
     std::ostringstream result;
-    result << indent() << "simulation = ba.OffSpecSimulation()\n";
+    result << indent() << "simulation = ba.OffSpecularSimulation()\n";
     result << defineDetector(simulation);
     result << defineDetectorResolutionFunction(simulation);
     result << defineDetectorPolarizationAnalysis(simulation);
-    result << defineOffSpecBeam(*simulation);
+    result << defineOffSpecularBeam(*simulation);
     result << defineParameterDistributions(simulation);
     result << defineMasks(simulation);
     result << defineSimulationOptions(simulation);
@@ -430,8 +429,8 @@ std::string defineSimulate(const ISimulation* simulation) {
     result << "def get_simulation():\n";
     if (auto gisas = dynamic_cast<const GISASSimulation*>(simulation))
         result << defineGISASSimulation(gisas);
-    else if (auto offspec = dynamic_cast<const OffSpecSimulation*>(simulation))
-        result << defineOffSpecSimulation(offspec);
+    else if (auto offspec = dynamic_cast<const OffSpecularSimulation*>(simulation))
+        result << defineOffSpecularSimulation(offspec);
     else if (auto spec = dynamic_cast<const SpecularSimulation*>(simulation))
         result << defineSpecularSimulation(spec);
     else
diff --git a/Core/Export/SimulationToPython.h b/Core/Export/SimulationToPython.h
index 655f4c3cee7301bb115669e496b55fabf27f30f5..2110dc202a28451b1ba4fd8da4178f872213bb29 100644
--- a/Core/Export/SimulationToPython.h
+++ b/Core/Export/SimulationToPython.h
@@ -16,6 +16,7 @@
 #error no need to expose this header to Swig
 #endif
 
+#ifndef USER_API
 #ifndef BORNAGAIN_CORE_EXPORT_SIMULATIONTOPYTHON_H
 #define BORNAGAIN_CORE_EXPORT_SIMULATIONTOPYTHON_H
 
@@ -32,3 +33,4 @@ public:
 };
 
 #endif // BORNAGAIN_CORE_EXPORT_SIMULATIONTOPYTHON_H
+#endif // USER_API
diff --git a/Core/Fitting/FitObjective.h b/Core/Fitting/FitObjective.h
index e3d1570096a439ab4689fb877b9f683b8649d49d..ac0afea08b35c56b38116f7dd58cd7d03d1e4f76 100644
--- a/Core/Fitting/FitObjective.h
+++ b/Core/Fitting/FitObjective.h
@@ -126,7 +126,7 @@ public:
     bool isFirstIteration() const;
 
     void setObjectiveMetric(std::unique_ptr<ObjectiveMetric> metric);
-#endif // SWIG
+#endif // USER_API
 
 private:
     typedef std::vector<double> (SimDataPair::*DataPairAccessor)() const;
diff --git a/Core/Fitting/FitObserver.h b/Core/Fitting/FitObserver.h
index 8a913270791d58f8e8fcf091a71e83d019bc55f1..cf0b74f8058382c5fe286dff41d8027a90ce0e6b 100644
--- a/Core/Fitting/FitObserver.h
+++ b/Core/Fitting/FitObserver.h
@@ -16,6 +16,7 @@
 #error no need to expose this header to Swig
 #endif
 
+#ifndef USER_API
 #ifndef BORNAGAIN_CORE_FITTING_FITOBSERVER_H
 #define BORNAGAIN_CORE_FITTING_FITOBSERVER_H
 
@@ -86,3 +87,4 @@ template <class T> bool FitObserver<T>::need_notify(int every_nth) {
 }
 
 #endif // BORNAGAIN_CORE_FITTING_FITOBSERVER_H
+#endif // USER_API
diff --git a/Core/Fitting/FitPrintService.h b/Core/Fitting/FitPrintService.h
index f4a55916b99caaef0d690a6f81ddbd2e33b75352..cd0125ee62593b9e385865d9d5fbbd2bb18f29c1 100644
--- a/Core/Fitting/FitPrintService.h
+++ b/Core/Fitting/FitPrintService.h
@@ -16,6 +16,7 @@
 #error no need to expose this header to Swig
 #endif
 
+#ifndef USER_API
 #ifndef BORNAGAIN_CORE_FITTING_FITPRINTSERVICE_H
 #define BORNAGAIN_CORE_FITTING_FITPRINTSERVICE_H
 
@@ -43,3 +44,4 @@ private:
 };
 
 #endif // BORNAGAIN_CORE_FITTING_FITPRINTSERVICE_H
+#endif // USER_API
diff --git a/Core/Fitting/FitStatus.h b/Core/Fitting/FitStatus.h
index ce5cbe66705e1fa57865cadc7a5a078ceb0240a3..d53db89e0967510ca3a170deeed1119d21077661 100644
--- a/Core/Fitting/FitStatus.h
+++ b/Core/Fitting/FitStatus.h
@@ -16,6 +16,7 @@
 #error no need to expose this header to Swig
 #endif
 
+#ifndef USER_API
 #ifndef BORNAGAIN_CORE_FITTING_FITSTATUS_H
 #define BORNAGAIN_CORE_FITTING_FITSTATUS_H
 
@@ -67,3 +68,4 @@ private:
 };
 
 #endif // BORNAGAIN_CORE_FITTING_FITSTATUS_H
+#endif // USER_API
diff --git a/Core/Fitting/FitTypes.h b/Core/Fitting/FitTypes.h
index 4b2baa06ca7a284188e6e31237a8340eb6041b15..17351e31750aeb6e94e9f2aeede082e446c43aae 100644
--- a/Core/Fitting/FitTypes.h
+++ b/Core/Fitting/FitTypes.h
@@ -16,6 +16,7 @@
 #error no need to expose this header to Swig
 #endif
 
+#ifndef USER_API
 #ifndef BORNAGAIN_CORE_FITTING_FITTYPES_H
 #define BORNAGAIN_CORE_FITTING_FITTYPES_H
 
@@ -34,3 +35,4 @@ using simulation_builder_t =
 using fit_observer_t = std::function<void(const FitObjective&)>;
 
 #endif // BORNAGAIN_CORE_FITTING_FITTYPES_H
+#endif // USER_API
diff --git a/Core/Fitting/IObserver.cpp b/Core/Fitting/IObserver.cpp
deleted file mode 100644
index 3758b81cf5db58fa50f1575cbc089348024bc7fa..0000000000000000000000000000000000000000
--- a/Core/Fitting/IObserver.cpp
+++ /dev/null
@@ -1,28 +0,0 @@
-//  ************************************************************************************************
-//
-//  BornAgain: simulate and fit scattering at grazing incidence
-//
-//! @file      Core/Fitting/IObserver.cpp
-//! @brief     Implements interface IObserver, mostly by including IObserver.h.
-//!
-//! @homepage  http://www.bornagainproject.org
-//! @license   GNU General Public License v3 or higher (see COPYING)
-//! @copyright Forschungszentrum Jülich GmbH 2018
-//! @authors   Scientific Computing Group at MLZ (see CITATION, AUTHORS)
-//
-//  ************************************************************************************************
-
-#include "Core/Fitting/IObserver.h"
-
-void IObservable::attachObserver(observer_t obj) {
-    m_observers.push_back(obj);
-}
-
-void IObservable::notifyObservers() {
-    for (auto it : m_observers)
-        it->notify(this);
-}
-
-IObserver::~IObserver() = default;
-
-IObservable::~IObservable() = default;
diff --git a/Core/Fitting/IObserver.h b/Core/Fitting/IObserver.h
deleted file mode 100644
index caecd709cb88ddb9c2bd6400dfb81815ccd41e24..0000000000000000000000000000000000000000
--- a/Core/Fitting/IObserver.h
+++ /dev/null
@@ -1,54 +0,0 @@
-//  ************************************************************************************************
-//
-//  BornAgain: simulate and fit scattering at grazing incidence
-//
-//! @file      Core/Fitting/IObserver.h
-//! @brief     Defines classes IObserver and IObservable (Observer pattern).
-//!
-//! @homepage  http://www.bornagainproject.org
-//! @license   GNU General Public License v3 or higher (see COPYING)
-//! @copyright Forschungszentrum Jülich GmbH 2018
-//! @authors   Scientific Computing Group at MLZ (see CITATION, AUTHORS)
-//
-//  ************************************************************************************************
-
-#ifndef BORNAGAIN_CORE_FITTING_IOBSERVER_H
-#define BORNAGAIN_CORE_FITTING_IOBSERVER_H
-
-#include <list>
-#include <memory>
-
-class IObservable;
-
-//! Observer interface from %Observer pattern.
-//! @ingroup tools_internal
-
-class IObserver {
-public:
-    virtual ~IObserver();
-
-    //! method which is used by observable subject to notify change in status
-    virtual void notify(IObservable* subject) = 0;
-};
-
-//! Observable interface from %Observer pattern
-//! @ingroup tools_internal
-
-class IObservable {
-public:
-    //! Shared pointer is used when passing these objects from Python to C++
-    typedef std::shared_ptr<IObserver> observer_t;
-
-    virtual ~IObservable();
-
-    //! attach observer to the list of observers
-    virtual void attachObserver(observer_t obj);
-
-    //! notify observers about change in status
-    virtual void notifyObservers();
-
-private:
-    std::list<observer_t> m_observers;
-};
-
-#endif // BORNAGAIN_CORE_FITTING_IOBSERVER_H
diff --git a/Core/Fitting/ObjectiveMetric.h b/Core/Fitting/ObjectiveMetric.h
index f514d1ddd01ad87deb2e2dd1b910d590a8cc5598..f00a56478ac0880c6e13d2f3fb50a5afc57a8624 100644
--- a/Core/Fitting/ObjectiveMetric.h
+++ b/Core/Fitting/ObjectiveMetric.h
@@ -16,6 +16,7 @@
 #error no need to expose this header to Swig
 #endif
 
+#ifndef USER_API
 #ifndef BORNAGAIN_CORE_FITTING_OBJECTIVEMETRIC_H
 #define BORNAGAIN_CORE_FITTING_OBJECTIVEMETRIC_H
 
@@ -198,3 +199,4 @@ public:
 };
 
 #endif // BORNAGAIN_CORE_FITTING_OBJECTIVEMETRIC_H
+#endif // USER_API
diff --git a/Core/Fitting/ObjectiveMetricUtils.h b/Core/Fitting/ObjectiveMetricUtils.h
index 25d73db4144882d77bf6b77fdb020f27414e51b2..f6f50a127ea368775fea2314797e9d69d523c063 100644
--- a/Core/Fitting/ObjectiveMetricUtils.h
+++ b/Core/Fitting/ObjectiveMetricUtils.h
@@ -16,6 +16,7 @@
 #error no need to expose this header to Swig
 #endif
 
+#ifndef USER_API
 #ifndef BORNAGAIN_CORE_FITTING_OBJECTIVEMETRICUTILS_H
 #define BORNAGAIN_CORE_FITTING_OBJECTIVEMETRICUTILS_H
 
@@ -59,3 +60,4 @@ std::string defaultMetricName();
 } // namespace ObjectiveMetricUtils
 
 #endif // BORNAGAIN_CORE_FITTING_OBJECTIVEMETRICUTILS_H
+#endif // USER_API
diff --git a/Core/Fitting/SimDataPair.h b/Core/Fitting/SimDataPair.h
index 3da9ac94e500a2becb21f56f39b1197a230f8806..1eebd6f632c0c720dc24dc706f24968463870489 100644
--- a/Core/Fitting/SimDataPair.h
+++ b/Core/Fitting/SimDataPair.h
@@ -16,6 +16,7 @@
 #error no need to expose this header to Swig
 #endif
 
+#ifndef USER_API
 #ifndef BORNAGAIN_CORE_FITTING_SIMDATAPAIR_H
 #define BORNAGAIN_CORE_FITTING_SIMDATAPAIR_H
 
@@ -109,3 +110,4 @@ private:
 };
 
 #endif // BORNAGAIN_CORE_FITTING_SIMDATAPAIR_H
+#endif // USER_API
diff --git a/Core/Legacy/MatrixRTCoefficients_v1.h b/Core/Legacy/MatrixRTCoefficients_v1.h
index 761c79e7da5e5fef98c4b7f7a990ea64b8e90437..a92cc405fc4e531d10a65967609aca24bb846b66 100644
--- a/Core/Legacy/MatrixRTCoefficients_v1.h
+++ b/Core/Legacy/MatrixRTCoefficients_v1.h
@@ -16,6 +16,7 @@
 #error no need to expose this header to Swig
 #endif
 
+#ifndef USER_API
 #ifndef BORNAGAIN_CORE_LEGACY_MATRIXRTCOEFFICIENTS_V1_H
 #define BORNAGAIN_CORE_LEGACY_MATRIXRTCOEFFICIENTS_V1_H
 
@@ -71,3 +72,4 @@ public:
 };
 
 #endif // BORNAGAIN_CORE_LEGACY_MATRIXRTCOEFFICIENTS_V1_H
+#endif // USER_API
diff --git a/Core/Legacy/MatrixRTCoefficients_v2.h b/Core/Legacy/MatrixRTCoefficients_v2.h
index 5d12d998bf6c215bc60324c81faac20dfac87515..71d94277b7224f02b194e93436c8a1a13f12e099 100644
--- a/Core/Legacy/MatrixRTCoefficients_v2.h
+++ b/Core/Legacy/MatrixRTCoefficients_v2.h
@@ -16,6 +16,7 @@
 #error no need to expose this header to Swig
 #endif
 
+#ifndef USER_API
 #ifndef BORNAGAIN_CORE_LEGACY_MATRIXRTCOEFFICIENTS_V2_H
 #define BORNAGAIN_CORE_LEGACY_MATRIXRTCOEFFICIENTS_V2_H
 
@@ -72,3 +73,4 @@ private:
 };
 
 #endif // BORNAGAIN_CORE_LEGACY_MATRIXRTCOEFFICIENTS_V2_H
+#endif // USER_API
diff --git a/Core/Legacy/SpecularMagneticStrategy_v1.h b/Core/Legacy/SpecularMagneticStrategy_v1.h
index eab0fb2b920f4851a1724d5ad98c7ea0dcb3228f..d0982395b4a6e4f194167c030258bc82adef0248 100644
--- a/Core/Legacy/SpecularMagneticStrategy_v1.h
+++ b/Core/Legacy/SpecularMagneticStrategy_v1.h
@@ -16,6 +16,7 @@
 #error no need to expose this header to Swig
 #endif
 
+#ifndef USER_API
 #ifndef BORNAGAIN_CORE_LEGACY_SPECULARMAGNETICSTRATEGY_V1_H
 #define BORNAGAIN_CORE_LEGACY_SPECULARMAGNETICSTRATEGY_V1_H
 
@@ -48,3 +49,4 @@ public:
 }; // class SpecularMagneticStrategy_v1
 
 #endif // BORNAGAIN_CORE_LEGACY_SPECULARMAGNETICSTRATEGY_V1_H
+#endif // USER_API
diff --git a/Core/Legacy/SpecularMagneticStrategy_v2.h b/Core/Legacy/SpecularMagneticStrategy_v2.h
index 003e60cac849eecd4f04f72995962443b7136822..978cf606ba64231d000ac81f93bf112485b8e919 100644
--- a/Core/Legacy/SpecularMagneticStrategy_v2.h
+++ b/Core/Legacy/SpecularMagneticStrategy_v2.h
@@ -16,6 +16,7 @@
 #error no need to expose this header to Swig
 #endif
 
+#ifndef USER_API
 #ifndef BORNAGAIN_CORE_LEGACY_SPECULARMAGNETICSTRATEGY_V2_H
 #define BORNAGAIN_CORE_LEGACY_SPECULARMAGNETICSTRATEGY_V2_H
 
@@ -78,3 +79,4 @@ private:
 };
 
 #endif // BORNAGAIN_CORE_LEGACY_SPECULARMAGNETICSTRATEGY_V2_H
+#endif // USER_API
diff --git a/Core/Scan/AngularSpecScan.h b/Core/Scan/AngularSpecScan.h
index d8c7d24690257b02b95bc108c5ad3cd7cfe332db..a073a15ad27124adb31c56fe7716d81776546d50 100644
--- a/Core/Scan/AngularSpecScan.h
+++ b/Core/Scan/AngularSpecScan.h
@@ -64,7 +64,7 @@ public:
     // TODO: remove these getters after transition to the new resolution machinery is finished
     const ScanResolution* wavelengthResolution() const { return m_wl_resolution.get(); }
     const ScanResolution* angleResolution() const { return m_inc_resolution.get(); }
-#endif // SWIG
+#endif // USER_API
 
     //! Sets footprint correction factor
     void setFootprintFactor(const IFootprintFactor* f_factor);
diff --git a/Core/Scan/ISpecularScan.h b/Core/Scan/ISpecularScan.h
index 30ceb9e0b6e21574ce634b2933830c7717d7a33e..c3b0fe4971ed9bf3a2859bc3ce4b52f0e237418d 100644
--- a/Core/Scan/ISpecularScan.h
+++ b/Core/Scan/ISpecularScan.h
@@ -54,7 +54,7 @@ public:
     virtual std::vector<double>
     createIntensities(const std::vector<SpecularSimulationElement>& sim_elements) const = 0;
 
-#endif // SWIG
+#endif // USER_API
 };
 
 #endif // BORNAGAIN_CORE_SCAN_ISPECULARSCAN_H
diff --git a/Core/Scan/QSpecScan.h b/Core/Scan/QSpecScan.h
index 0f6289e17232516707c9ccc268eeac66aa05ed7e..89bf72cfe5d5e744577b0df861cecf54758446c7 100644
--- a/Core/Scan/QSpecScan.h
+++ b/Core/Scan/QSpecScan.h
@@ -63,7 +63,7 @@ public:
     std::vector<double>
     createIntensities(const std::vector<SpecularSimulationElement>& sim_elements) const override;
 
-#endif // SWIG
+#endif // USER_API
 
     //! Sets q resolution values via ScanResolution object.
     void setQResolution(const ScanResolution& resolution);
diff --git a/Core/Scan/UnitConverter1D.h b/Core/Scan/UnitConverter1D.h
index deac928ceb6b43c990e817c9ff146b12322683fb..88b373e07f0ff07e12c0a80c72dceb1d16935b79 100644
--- a/Core/Scan/UnitConverter1D.h
+++ b/Core/Scan/UnitConverter1D.h
@@ -16,6 +16,7 @@
 #error no need to expose this header to Swig
 #endif
 
+#ifndef USER_API
 #ifndef BORNAGAIN_CORE_SCAN_UNITCONVERTER1D_H
 #define BORNAGAIN_CORE_SCAN_UNITCONVERTER1D_H
 
@@ -131,3 +132,4 @@ protected:
     std::unique_ptr<IAxis> m_axis; //!< qz values (in inv. nm).
 };
 #endif // BORNAGAIN_CORE_SCAN_UNITCONVERTER1D_H
+#endif // USER_API
diff --git a/Core/Simulation/ISimulation.cpp b/Core/Simulation/ISimulation.cpp
index 402d1fc08121dbaa13a6435c794caa4008b91bc8..4baa823d776e642fec12b169b72db38dae7700b7 100644
--- a/Core/Simulation/ISimulation.cpp
+++ b/Core/Simulation/ISimulation.cpp
@@ -162,15 +162,6 @@ void ISimulation::setAnalyzerProperties(const kvector_t direction, double effici
     detector().setAnalyzerProperties(direction, efficiency, total_transmission);
 }
 
-void ISimulation::setBeamIntensity(double intensity) {
-    beam().setIntensity(intensity);
-}
-
-//! Sets the beam polarization according to the given Bloch vector
-void ISimulation::setBeamPolarization(const kvector_t bloch_vector) {
-    beam().setPolarization(bloch_vector);
-}
-
 void ISimulation::prepareSimulation() {
     m_sample_provider.updateSample();
     if (!MultiLayerUtils::ContainsCompatibleMaterials(*m_sample_provider.sample()))
diff --git a/Core/Simulation/ISimulation.h b/Core/Simulation/ISimulation.h
index f14278900e4d1231f1e14027135091b65aa56704..f88b535bbb2c4a6321f4a1a7bf0a900d38af4085 100644
--- a/Core/Simulation/ISimulation.h
+++ b/Core/Simulation/ISimulation.h
@@ -61,10 +61,6 @@ public:
     IDetector& detector() { return m_instrument.detector(); }
     const IDetector& detector() const { return m_instrument.detector(); }
 
-    void setBeamIntensity(double intensity);
-
-    void setBeamPolarization(const kvector_t bloch_vector);
-
     void setDetectorResolutionFunction(const IResolutionFunction2D& resolution_function);
 
     void setAnalyzerProperties(const kvector_t direction, double efficiency,
diff --git a/Core/Simulation/MPISimulation.h b/Core/Simulation/MPISimulation.h
index 67e644e47e92a5ac639b9f998e9cdd945d4bf828..e52901456f228f235770973f9e11390c282cd81c 100644
--- a/Core/Simulation/MPISimulation.h
+++ b/Core/Simulation/MPISimulation.h
@@ -17,6 +17,7 @@
 #error no need to expose this header to Swig
 #endif
 
+#ifndef USER_API
 #ifndef BORNAGAIN_CORE_SIMULATION_MPISIMULATION_H
 #define BORNAGAIN_CORE_SIMULATION_MPISIMULATION_H
 
@@ -28,3 +29,4 @@ public:
 };
 
 #endif // BORNAGAIN_CORE_SIMULATION_MPISIMULATION_H
+#endif // USER_API
diff --git a/Core/Simulation/OffSpecSimulation.cpp b/Core/Simulation/OffSpecularSimulation.cpp
similarity index 70%
rename from Core/Simulation/OffSpecSimulation.cpp
rename to Core/Simulation/OffSpecularSimulation.cpp
index 176b059ba0e8c78b43fd8a5f2a5df06c0af9d060..58e32d43b8dbb1b7085a62087548e5ec0d811f4b 100644
--- a/Core/Simulation/OffSpecSimulation.cpp
+++ b/Core/Simulation/OffSpecularSimulation.cpp
@@ -2,8 +2,8 @@
 //
 //  BornAgain: simulate and fit scattering at grazing incidence
 //
-//! @file      Core/Simulation/OffSpecSimulation.cpp
-//! @brief     Implements class OffSpecSimulation.
+//! @file      Core/Simulation/OffSpecularSimulation.cpp
+//! @brief     Implements class OffSpecularSimulation.
 //!
 //! @homepage  http://www.bornagainproject.org
 //! @license   GNU General Public License v3 or higher (see COPYING)
@@ -12,7 +12,7 @@
 //
 //  ************************************************************************************************
 
-#include "Core/Simulation/OffSpecSimulation.h"
+#include "Core/Simulation/OffSpecularSimulation.h"
 #include "Core/Computation/DWBAComputation.h"
 #include "Device/Detector/SimpleUnitConverters.h"
 #include "Device/Histo/Histogram2D.h"
@@ -22,67 +22,68 @@
 #include "Sample/Multilayer/MultiLayer.h"
 #include "Sample/SampleBuilderEngine/ISampleBuilder.h"
 
-OffSpecSimulation::OffSpecSimulation(const Beam& beam, const MultiLayer& sample,
-                                     const IDetector& detector)
+OffSpecularSimulation::OffSpecularSimulation(const Beam& beam, const MultiLayer& sample,
+                                             const IDetector& detector)
     : ISimulation2D(beam, sample, detector) {}
 
-OffSpecSimulation::OffSpecSimulation() {
+OffSpecularSimulation::OffSpecularSimulation() {
     initialize();
 }
 
-void OffSpecSimulation::prepareSimulation() {
+void OffSpecularSimulation::prepareSimulation() {
     checkInitialization();
     ISimulation2D::prepareSimulation();
 }
 
-size_t OffSpecSimulation::numberOfSimulationElements() const {
+size_t OffSpecularSimulation::numberOfSimulationElements() const {
     checkInitialization();
     return ISimulation2D::numberOfSimulationElements() * m_alpha_i_axis->size();
 }
 
-SimulationResult OffSpecSimulation::result() const {
+SimulationResult OffSpecularSimulation::result() const {
     auto data = std::unique_ptr<OutputData<double>>(m_intensity_map.clone());
     OffSpecularConverter converter(instrument().detector2D(), instrument().beam(), *m_alpha_i_axis);
     return SimulationResult(*data, converter);
 }
 
-void OffSpecSimulation::setBeamParameters(double wavelength, const IAxis& alpha_axis,
-                                          double phi_i) {
+void OffSpecularSimulation::setBeamParameters(double wavelength, const IAxis& alpha_axis,
+                                              double phi_i) {
     m_alpha_i_axis.reset(alpha_axis.clone());
     if (alpha_axis.size() < 1)
-        throw std::runtime_error("OffSpecSimulation::prepareSimulation() "
+        throw std::runtime_error("OffSpecularSimulation::prepareSimulation() "
                                  "-> Error. Incoming alpha range size < 1.");
     const double alpha_zero = alpha_axis.lowerBound();
     instrument().setBeamParameters(wavelength, alpha_zero, phi_i);
     updateIntensityMap();
 }
 
-const IAxis* OffSpecSimulation::beamAxis() const {
+const IAxis* OffSpecularSimulation::beamAxis() const {
     return m_alpha_i_axis.get();
 }
 
-std::unique_ptr<IUnitConverter> OffSpecSimulation::createUnitConverter() const {
+std::unique_ptr<IUnitConverter> OffSpecularSimulation::createUnitConverter() const {
     const IAxis* axis = beamAxis();
     if (!axis)
-        throw std::runtime_error("Error in OffSpecSimulation::createUnitConverter:"
+        throw std::runtime_error("Error in OffSpecularSimulation::createUnitConverter:"
                                  " missing inclination angle axis");
     return std::make_unique<OffSpecularConverter>(instrument().detector2D(), instrument().beam(),
                                                   *axis);
 }
 
-size_t OffSpecSimulation::intensityMapSize() const {
+size_t OffSpecularSimulation::intensityMapSize() const {
     checkInitialization();
     return m_alpha_i_axis->size() * detector().axis(1).size();
 }
 
-OffSpecSimulation::OffSpecSimulation(const OffSpecSimulation& other) : ISimulation2D(other) {
+OffSpecularSimulation::OffSpecularSimulation(const OffSpecularSimulation& other)
+    : ISimulation2D(other) {
     if (other.m_alpha_i_axis)
         m_alpha_i_axis.reset(other.m_alpha_i_axis->clone());
     m_intensity_map.copyFrom(other.m_intensity_map);
     initialize();
 }
 
-void OffSpecSimulation::initSimulationElementVector() {
+void OffSpecularSimulation::initSimulationElementVector() {
     m_sim_elements.clear();
     Beam beam = instrument().beam();
     for (size_t i = 0; i < m_alpha_i_axis->size(); ++i) {
@@ -95,7 +96,7 @@ void OffSpecSimulation::initSimulationElementVector() {
         m_cache.resize(m_sim_elements.size(), 0.0);
 }
 
-void OffSpecSimulation::validateParametrization(const ParameterDistribution& par_distr) const {
+void OffSpecularSimulation::validateParametrization(const ParameterDistribution& par_distr) const {
     const bool zero_mean = par_distr.getDistribution()->getMean() == 0.0;
     if (zero_mean)
         return;
@@ -105,23 +106,23 @@ void OffSpecSimulation::validateParametrization(const ParameterDistribution& par
         parameter_pool->getMatchedParameters(par_distr.getMainParameterName());
     for (const auto par : names)
         if (par->getName().find("InclinationAngle") != std::string::npos && !zero_mean)
-            throw std::runtime_error("Error in OffSpecSimulation: parameter distribution of "
+            throw std::runtime_error("Error in OffSpecularSimulation: parameter distribution of "
                                      "beam inclination angle should have zero mean.");
 }
 
-void OffSpecSimulation::transferResultsToIntensityMap() {
+void OffSpecularSimulation::transferResultsToIntensityMap() {
     checkInitialization();
     const IAxis& phi_axis = detector().axis(0);
     size_t phi_f_size = phi_axis.size();
     if (phi_f_size * m_intensity_map.getAllocatedSize() != m_sim_elements.size())
         throw std::runtime_error(
-            "OffSpecSimulation::transferResultsToIntensityMap: "
+            "OffSpecularSimulation::transferResultsToIntensityMap: "
             "intensity map size does not conform to number of calculated intensities");
     for (size_t i = 0; i < m_alpha_i_axis->size(); ++i)
         transferDetectorImage(i);
 }
 
-void OffSpecSimulation::updateIntensityMap() {
+void OffSpecularSimulation::updateIntensityMap() {
     m_intensity_map.clear();
     if (m_alpha_i_axis)
         m_intensity_map.addAxis(*m_alpha_i_axis);
@@ -131,7 +132,7 @@ void OffSpecSimulation::updateIntensityMap() {
     m_intensity_map.setAllTo(0.);
 }
 
-void OffSpecSimulation::transferDetectorImage(size_t index) {
+void OffSpecularSimulation::transferDetectorImage(size_t index) {
     OutputData<double> detector_image;
     size_t detector_dimension = detector().dimension();
     for (size_t dim = 0; dim < detector_dimension; ++dim)
@@ -145,15 +146,15 @@ void OffSpecSimulation::transferDetectorImage(size_t index) {
         m_intensity_map[index * y_axis_size + i % y_axis_size] += detector_image[i];
 }
 
-void OffSpecSimulation::checkInitialization() const {
+void OffSpecularSimulation::checkInitialization() const {
     if (!m_alpha_i_axis || m_alpha_i_axis->size() < 1)
-        throw std::runtime_error("OffSpecSimulation::checkInitialization() "
+        throw std::runtime_error("OffSpecularSimulation::checkInitialization() "
                                  "Incoming alpha range not configured.");
     if (detector().dimension() != 2)
         throw std::runtime_error(
-            "OffSpecSimulation::checkInitialization: detector is not two-dimensional");
+            "OffSpecularSimulation::checkInitialization: detector is not two-dimensional");
 }
 
-void OffSpecSimulation::initialize() {
-    setName("OffSpecSimulation");
+void OffSpecularSimulation::initialize() {
+    setName("OffSpecularSimulation");
 }
diff --git a/Core/Simulation/OffSpecSimulation.h b/Core/Simulation/OffSpecularSimulation.h
similarity index 84%
rename from Core/Simulation/OffSpecSimulation.h
rename to Core/Simulation/OffSpecularSimulation.h
index 25e72c996dc2eafd5b07c46e1fe355ec0714243f..01ab51a8c713920495e8930d4d5c06f98608068d 100644
--- a/Core/Simulation/OffSpecSimulation.h
+++ b/Core/Simulation/OffSpecularSimulation.h
@@ -2,8 +2,8 @@
 //
 //  BornAgain: simulate and fit scattering at grazing incidence
 //
-//! @file      Core/Simulation/OffSpecSimulation.h
-//! @brief     Defines class OffSpecSimulation.
+//! @file      Core/Simulation/OffSpecularSimulation.h
+//! @brief     Defines class OffSpecularSimulation.
 //!
 //! @homepage  http://www.bornagainproject.org
 //! @license   GNU General Public License v3 or higher (see COPYING)
@@ -23,13 +23,13 @@ class Histogram2D;
 //! Main class to run an off-specular simulation.
 //! @ingroup simulation
 
-class OffSpecSimulation : public ISimulation2D {
+class OffSpecularSimulation : public ISimulation2D {
 public:
-    OffSpecSimulation(const Beam& beam, const MultiLayer& sample, const IDetector& detector);
-    OffSpecSimulation();
-    ~OffSpecSimulation() override {}
+    OffSpecularSimulation(const Beam& beam, const MultiLayer& sample, const IDetector& detector);
+    OffSpecularSimulation();
+    ~OffSpecularSimulation() override {}
 
-    OffSpecSimulation* clone() const override { return new OffSpecSimulation(*this); }
+    OffSpecularSimulation* clone() const override { return new OffSpecularSimulation(*this); }
 
     void accept(INodeVisitor* visitor) const override { visitor->visit(this); }
 
@@ -54,7 +54,7 @@ public:
     size_t intensityMapSize() const override;
 
 private:
-    OffSpecSimulation(const OffSpecSimulation& other);
+    OffSpecularSimulation(const OffSpecularSimulation& other);
 
     //! Initializes the vector of ISimulation elements
     void initSimulationElementVector() override;
diff --git a/Core/Simulation/SimulationFactory.cpp b/Core/Simulation/SimulationFactory.cpp
index f85e1d56f357b824b075cd0e5c41226ca506096d..d744bbe7c9f0ba9b9adc9d96988032d3b316006a 100644
--- a/Core/Simulation/SimulationFactory.cpp
+++ b/Core/Simulation/SimulationFactory.cpp
@@ -14,7 +14,7 @@
 
 #include "Core/Simulation/SimulationFactory.h"
 #include "Core/Simulation/DepthProbeSimulation.h"
-#include "Core/Simulation/OffSpecSimulation.h"
+#include "Core/Simulation/OffSpecularSimulation.h"
 #include "Core/Simulation/SpecularSimulation.h"
 #include "Core/Simulation/StandardSimulations.h"
 #include "Param/Base/RealParameter.h"
@@ -100,7 +100,7 @@ SimulationFactory::SimulationFactory() {
 
     registerItem("TOFRWithPointwiseResolution", StandardSimulations::TOFRWithPointwiseResolution);
 
-    registerItem("OffSpecMini", StandardSimulations::MiniOffSpec);
+    registerItem("OffSpecularMini", StandardSimulations::MiniOffSpecular);
 
     // polarized specular
 
diff --git a/Core/Simulation/SimulationFactory.h b/Core/Simulation/SimulationFactory.h
index 9c31fb459f2f1a020a35da04d87e709b422029a5..8b566ee7937608c035ff59d412d0814e45e986ba 100644
--- a/Core/Simulation/SimulationFactory.h
+++ b/Core/Simulation/SimulationFactory.h
@@ -16,6 +16,7 @@
 #error no need to expose this header to Swig
 #endif
 
+#ifndef USER_API
 #ifndef BORNAGAIN_CORE_SIMULATION_SIMULATIONFACTORY_H
 #define BORNAGAIN_CORE_SIMULATION_SIMULATIONFACTORY_H
 
@@ -33,3 +34,4 @@ public:
 };
 
 #endif // BORNAGAIN_CORE_SIMULATION_SIMULATIONFACTORY_H
+#endif // USER_API
diff --git a/Core/Simulation/SpecularSimulation.cpp b/Core/Simulation/SpecularSimulation.cpp
index 02af3b78ceb9a2bed4001628a0db6494226fd939..aaedd6f7dc4be85577122e8b8bdbf4a80d68dcac 100644
--- a/Core/Simulation/SpecularSimulation.cpp
+++ b/Core/Simulation/SpecularSimulation.cpp
@@ -3,7 +3,7 @@
 //  BornAgain: simulate and fit scattering at grazing incidence
 //
 //! @file      Core/Simulation/SpecularSimulation.cpp
-//! @brief     Implements class OffSpecSimulation.
+//! @brief     Implements class OffSpecularSimulation.
 //!
 //! @homepage  http://www.bornagainproject.org
 //! @license   GNU General Public License v3 or higher (see COPYING)
diff --git a/Core/Simulation/SpecularSimulation.h b/Core/Simulation/SpecularSimulation.h
index 9581348329bf0966b8cc57e7445b62972439f83e..3d29924121c42abe2948ee6a1b2e7893541dcb4b 100644
--- a/Core/Simulation/SpecularSimulation.h
+++ b/Core/Simulation/SpecularSimulation.h
@@ -61,7 +61,7 @@ public:
 #ifndef SWIG
     //! Returns internal data handler
     const ISpecularScan* dataHandler() const { return m_scan.get(); }
-#endif // SWIG
+#endif // USER_API
 
 private:
     SpecularSimulation(const SpecularSimulation& other); // used by clone()
diff --git a/Core/Simulation/StandardSimulations.cpp b/Core/Simulation/StandardSimulations.cpp
index 649dc1301bc3b01f47d77d7dd06cc1dc031dc1ce..2c564d519817fa3ff7196c3f5e54ca78498e9b0c 100644
--- a/Core/Simulation/StandardSimulations.cpp
+++ b/Core/Simulation/StandardSimulations.cpp
@@ -19,7 +19,7 @@
 #include "Core/Scan/QSpecScan.h"
 #include "Core/Simulation/DepthProbeSimulation.h"
 #include "Core/Simulation/GISASSimulation.h"
-#include "Core/Simulation/OffSpecSimulation.h"
+#include "Core/Simulation/OffSpecularSimulation.h"
 #include "Core/Simulation/SpecularSimulation.h"
 #include "Device/Beam/FootprintGauss.h"
 #include "Device/Beam/FootprintSquare.h"
@@ -58,7 +58,7 @@ GISASSimulation* StandardSimulations::BasicGISAS() {
 GISASSimulation* StandardSimulations::BasicGISAS00() {
     GISASSimulation* result = BasicGISAS();
     kvector_t zplus(0.0, 0.0, 1.0);
-    result->setBeamPolarization(zplus);
+    result->beam().setPolarization(zplus);
     result->setAnalyzerProperties(zplus, 1.0, 0.5);
     return result;
 }
@@ -68,7 +68,7 @@ GISASSimulation* StandardSimulations::BasicGISAS00() {
 GISASSimulation* StandardSimulations::BasicPolarizedGISAS() {
     GISASSimulation* result = BasicGISAS();
     kvector_t zplus(0.0, 0.0, 1.0);
-    result->setBeamPolarization(zplus);
+    result->beam().setPolarization(zplus);
     result->setAnalyzerProperties(zplus, -1.0, 0.5);
     return result;
 }
@@ -122,7 +122,7 @@ GISASSimulation* StandardSimulations::GISASWithMasks() {
     result->setDetectorParameters(50, -1.0 * Units::deg, 1.0 * Units::deg, 50, 0.0 * Units::deg,
                                   2.0 * Units::deg);
     result->setBeamParameters(1.0 * Units::angstrom, 0.2 * Units::deg, 0.0 * Units::deg);
-    result->setBeamIntensity(1e+7);
+    result->beam().setIntensity(1e+7);
 
     result->maskAll();
     // pacman
@@ -163,7 +163,7 @@ GISASSimulation* StandardSimulations::MiniGISASPolarizationPP() {
     kvector_t analyzer_dir(0.0, 0.0, 1.0);
     kvector_t beampol(0.0, 0.0, 1.0);
 
-    result->setBeamPolarization(beampol);
+    result->beam().setPolarization(beampol);
     result->setAnalyzerProperties(analyzer_dir, 1.0, 0.5);
     return result;
 }
@@ -174,7 +174,7 @@ GISASSimulation* StandardSimulations::MiniGISASPolarizationPM() {
     kvector_t analyzer_dir(0.0, 0.0, -1.0);
     kvector_t beampol(0.0, 0.0, 1.0);
 
-    result->setBeamPolarization(beampol);
+    result->beam().setPolarization(beampol);
     result->setAnalyzerProperties(analyzer_dir, 1.0, 0.5);
     return result;
 }
@@ -185,7 +185,7 @@ GISASSimulation* StandardSimulations::MiniGISASPolarizationMP() {
     kvector_t analyzer_dir(0.0, 0.0, 1.0);
     kvector_t beampol(0.0, 0.0, -1.0);
 
-    result->setBeamPolarization(beampol);
+    result->beam().setPolarization(beampol);
     result->setAnalyzerProperties(analyzer_dir, 1.0, 0.5);
     return result;
 }
@@ -196,7 +196,7 @@ GISASSimulation* StandardSimulations::MiniGISASPolarizationMM() {
     kvector_t analyzer_dir(0.0, 0.0, -1.0);
     kvector_t beampol(0.0, 0.0, -1.0);
 
-    result->setBeamPolarization(beampol);
+    result->beam().setPolarization(beampol);
     result->setAnalyzerProperties(analyzer_dir, 1.0, 0.5);
     return result;
 }
@@ -227,7 +227,7 @@ GISASSimulation* StandardSimulations::MaxiGISAS() {
 GISASSimulation* StandardSimulations::MaxiGISAS00() {
     GISASSimulation* result = MaxiGISAS();
     kvector_t zplus(0.0, 0.0, 1.0);
-    result->setBeamPolarization(zplus);
+    result->beam().setPolarization(zplus);
     result->setAnalyzerProperties(zplus, 1.0, 0.5);
     return result;
 }
@@ -370,7 +370,7 @@ GISASSimulation* StandardSimulations::ExtraLongWavelengthGISAS() {
                                       2.0 * Units::deg);
 
     simulation->setBeamParameters(13.52 * Units::nm, 0.2 * Units::deg, 0.0 * Units::deg);
-    simulation->setBeamIntensity(1.0e+08);
+    simulation->beam().setIntensity(1.0e+08);
     simulation->getOptions().setIncludeSpecular(true);
     return simulation;
 }
@@ -495,65 +495,65 @@ SpecularSimulation* StandardSimulations::TOFRWithPointwiseResolution() {
 // ------------ polarized specular ----------------
 SpecularSimulation* StandardSimulations::BasicSpecularPP() {
     auto* simulation = BasicSpecular();
-    simulation->setBeamPolarization({0.0, 1.0, 0.0});
+    simulation->beam().setPolarization({0.0, 1.0, 0.0});
     simulation->setAnalyzerProperties({0.0, 1.0, 0.0}, 1.0, 0.5);
     return simulation;
 }
 
 SpecularSimulation* StandardSimulations::BasicSpecularPM() {
     auto* simulation = BasicSpecular();
-    simulation->setBeamPolarization({0.0, 1.0, 0.0});
+    simulation->beam().setPolarization({0.0, 1.0, 0.0});
     simulation->setAnalyzerProperties({0.0, -1.0, 0.0}, 1.0, 0.5);
     return simulation;
 }
 
 SpecularSimulation* StandardSimulations::BasicSpecularMP() {
     auto* simulation = BasicSpecular();
-    simulation->setBeamPolarization({0.0, -1.0, 0.0});
+    simulation->beam().setPolarization({0.0, -1.0, 0.0});
     simulation->setAnalyzerProperties({0.0, 1.0, 0.0}, 1.0, 0.5);
     return simulation;
 }
 
 SpecularSimulation* StandardSimulations::BasicSpecularMM() {
     auto* simulation = BasicSpecular();
-    simulation->setBeamPolarization({0.0, -1.0, 0.0});
+    simulation->beam().setPolarization({0.0, -1.0, 0.0});
     simulation->setAnalyzerProperties({0.0, -1.0, 0.0}, 1.0, 0.5);
     return simulation;
 }
 
 SpecularSimulation* StandardSimulations::BasicSpecularQPP() {
     auto* simulation = BasicSpecularQ();
-    simulation->setBeamPolarization({0.0, 1.0, 0.0});
+    simulation->beam().setPolarization({0.0, 1.0, 0.0});
     simulation->setAnalyzerProperties({0.0, 1.0, 0.0}, 1.0, 0.5);
     return simulation;
 }
 
 SpecularSimulation* StandardSimulations::BasicSpecularQMM() {
     auto* simulation = BasicSpecularQ();
-    simulation->setBeamPolarization({0.0, -1.0, 0.0});
+    simulation->beam().setPolarization({0.0, -1.0, 0.0});
     simulation->setAnalyzerProperties({0.0, -1.0, 0.0}, 1.0, 0.5);
     return simulation;
 }
 
 SpecularSimulation* StandardSimulations::BasicSpecularQPM() {
     auto* simulation = BasicSpecularQ();
-    simulation->setBeamPolarization({0.0, 1.0, 0.0});
+    simulation->beam().setPolarization({0.0, 1.0, 0.0});
     simulation->setAnalyzerProperties({0.0, -1.0, 0.0}, 1.0, 0.5);
     return simulation;
 }
 
 SpecularSimulation* StandardSimulations::BasicSpecularQMP() {
     auto* simulation = BasicSpecularQ();
-    simulation->setBeamPolarization({0.0, -1.0, 0.0});
+    simulation->beam().setPolarization({0.0, -1.0, 0.0});
     simulation->setAnalyzerProperties({0.0, 1.0, 0.0}, 1.0, 0.5);
     return simulation;
 }
 
 // ----------------------- off-spec simulations ------------------
 
-// OffSpec simulation used in ResonatorOffSpecSetup.py
-OffSpecSimulation* StandardSimulations::MiniOffSpec() {
-    auto* result = new OffSpecSimulation;
+// OffSpecular simulation used in ResonatorOffSpecularSetup.py
+OffSpecularSimulation* StandardSimulations::MiniOffSpecular() {
+    auto* result = new OffSpecularSimulation;
 
     const int n_alpha(19);
     const double alpha_min(0.0 * Units::deg);
@@ -571,7 +571,7 @@ OffSpecSimulation* StandardSimulations::MiniOffSpec() {
     FixedBinAxis alpha_i_axis("alpha_i", n_scan_points, alpha_i_min, alpha_i_max);
     result->setBeamParameters(5.0 * Units::angstrom, alpha_i_axis, 0.0);
 
-    result->setBeamIntensity(1e9);
+    result->beam().setIntensity(1e9);
     result->getOptions().setIncludeSpecular(true);
 
     return result;
@@ -601,6 +601,6 @@ GISASSimulation* StandardSimulations::MiniGISASFit() {
     result->setDetectorParameters(25, -2.0 * Units::deg, 2.0 * Units::deg, 25, 0.0 * Units::deg,
                                   2.0 * Units::deg);
     result->setBeamParameters(1.0 * Units::angstrom, 0.2 * Units::deg, 0.0 * Units::deg);
-    result->setBeamIntensity(1e6);
+    result->beam().setIntensity(1e6);
     return result;
 }
diff --git a/Core/Simulation/StandardSimulations.h b/Core/Simulation/StandardSimulations.h
index 630c81778ff62862ab3673332f39421fead0c30a..03d7720bed635e4a317a746430b45ab3d3e73817 100644
--- a/Core/Simulation/StandardSimulations.h
+++ b/Core/Simulation/StandardSimulations.h
@@ -16,13 +16,14 @@
 #error no need to expose this header to Swig
 #endif
 
+#ifndef USER_API
 #ifndef BORNAGAIN_CORE_SIMULATION_STANDARDSIMULATIONS_H
 #define BORNAGAIN_CORE_SIMULATION_STANDARDSIMULATIONS_H
 
 class DepthProbeSimulation;
 class GISASSimulation;
 class SpecularSimulation;
-class OffSpecSimulation;
+class OffSpecularSimulation;
 
 //! Standard pre-defined simulations.
 
@@ -79,8 +80,8 @@ SpecularSimulation* BasicSpecularQMM();
 SpecularSimulation* BasicSpecularQPM();
 SpecularSimulation* BasicSpecularQMP();
 
-// OffSpec simulations
-OffSpecSimulation* MiniOffSpec();
+// OffSpecular simulations
+OffSpecularSimulation* MiniOffSpecular();
 
 // Depth probe simulations
 DepthProbeSimulation* BasicDepthProbe();
@@ -88,3 +89,4 @@ DepthProbeSimulation* BasicDepthProbe();
 } // namespace StandardSimulations
 
 #endif // BORNAGAIN_CORE_SIMULATION_STANDARDSIMULATIONS_H
+#endif // USER_API
diff --git a/Core/Simulation/UnitConverterUtils.cpp b/Core/Simulation/UnitConverterUtils.cpp
index 21439b45ea1844d72679ac38832cafd11be8e7a9..b6fb8e9438ca3e7fa5b226e462c45c5fb3fde03c 100644
--- a/Core/Simulation/UnitConverterUtils.cpp
+++ b/Core/Simulation/UnitConverterUtils.cpp
@@ -16,7 +16,7 @@
 #include "Core/Scan/UnitConverter1D.h"
 #include "Core/Simulation/DepthProbeSimulation.h"
 #include "Core/Simulation/GISASSimulation.h"
-#include "Core/Simulation/OffSpecSimulation.h"
+#include "Core/Simulation/OffSpecularSimulation.h"
 #include "Core/Simulation/SpecularSimulation.h"
 #include "Device/Detector/RectangularDetector.h"
 #include "Device/Detector/SimpleUnitConverters.h"
@@ -53,7 +53,7 @@ std::unique_ptr<IUnitConverter> UnitConverterUtils::createConverter(const ISimul
     } else if (auto probe = dynamic_cast<const DepthProbeSimulation*>(&simulation)) {
         return probe->createUnitConverter();
 
-    } else if (auto off_spec = dynamic_cast<const OffSpecSimulation*>(&simulation)) {
+    } else if (auto off_spec = dynamic_cast<const OffSpecularSimulation*>(&simulation)) {
         return off_spec->createUnitConverter();
 
     } else {
diff --git a/Core/Simulation/UnitConverterUtils.h b/Core/Simulation/UnitConverterUtils.h
index bf57ad4ee8dc8b14f33981dc1b2c392f5ba13c73..9c5666e3a5bba9f625749f220cd013ef0ca30073 100644
--- a/Core/Simulation/UnitConverterUtils.h
+++ b/Core/Simulation/UnitConverterUtils.h
@@ -16,6 +16,7 @@
 #error no need to expose this header to Swig
 #endif
 
+#ifndef USER_API
 #ifndef BORNAGAIN_CORE_SIMULATION_UNITCONVERTERUTILS_H
 #define BORNAGAIN_CORE_SIMULATION_UNITCONVERTERUTILS_H
 
@@ -41,3 +42,4 @@ std::unique_ptr<IUnitConverter> createConverter(const ISimulation& simulation);
 } // namespace UnitConverterUtils
 
 #endif // BORNAGAIN_CORE_SIMULATION_UNITCONVERTERUTILS_H
+#endif // USER_API
diff --git a/Core/Term/DepthProbeComputationTerm.h b/Core/Term/DepthProbeComputationTerm.h
index ff548e1cc721993b51cb5315d5383876dd2cdf1c..caaefd9a516f2ffbe917d195f351139e2984968e 100644
--- a/Core/Term/DepthProbeComputationTerm.h
+++ b/Core/Term/DepthProbeComputationTerm.h
@@ -16,6 +16,7 @@
 #error no need to expose this header to Swig
 #endif
 
+#ifndef USER_API
 #ifndef BORNAGAIN_CORE_TERM_DEPTHPROBECOMPUTATIONTERM_H
 #define BORNAGAIN_CORE_TERM_DEPTHPROBECOMPUTATIONTERM_H
 
@@ -41,3 +42,4 @@ private:
 };
 
 #endif // BORNAGAIN_CORE_TERM_DEPTHPROBECOMPUTATIONTERM_H
+#endif // USER_API
diff --git a/Core/Term/SpecularComputationTerm.h b/Core/Term/SpecularComputationTerm.h
index 092be278b91263c4b7f56d778b49dab8900ebf6a..85faa86356948a1ce457a1437e2d9c0156c103c3 100644
--- a/Core/Term/SpecularComputationTerm.h
+++ b/Core/Term/SpecularComputationTerm.h
@@ -16,6 +16,7 @@
 #error no need to expose this header to Swig
 #endif
 
+#ifndef USER_API
 #ifndef BORNAGAIN_CORE_TERM_SPECULARCOMPUTATIONTERM_H
 #define BORNAGAIN_CORE_TERM_SPECULARCOMPUTATIONTERM_H
 
@@ -85,3 +86,4 @@ private:
 };
 
 #endif // BORNAGAIN_CORE_TERM_SPECULARCOMPUTATIONTERM_H
+#endif // USER_API
diff --git a/Device/Data/CumulativeValue.h b/Device/Data/CumulativeValue.h
index c669e56267ed1b43f01cc7bc250af535d3fd17cd..e5ae038a171ad694af7adde6b4dd6d07fd46d6cf 100644
--- a/Device/Data/CumulativeValue.h
+++ b/Device/Data/CumulativeValue.h
@@ -16,6 +16,7 @@
 #error no need to expose this header to Swig
 #endif
 
+#ifndef USER_API
 #ifndef BORNAGAIN_DEVICE_DATA_CUMULATIVEVALUE_H
 #define BORNAGAIN_DEVICE_DATA_CUMULATIVEVALUE_H
 
@@ -47,3 +48,4 @@ bool operator<(const CumulativeValue& lhs, const CumulativeValue& rhs);
 bool operator>(const CumulativeValue& lhs, const CumulativeValue& rhs);
 
 #endif // BORNAGAIN_DEVICE_DATA_CUMULATIVEVALUE_H
+#endif // USER_API
diff --git a/Device/Data/LLData.h b/Device/Data/LLData.h
index a3b84ea5f14b18e0f42e093d5e5e3c007db1c171..72f54a1ec6bd379856205c88a1a70fed67279c3b 100644
--- a/Device/Data/LLData.h
+++ b/Device/Data/LLData.h
@@ -16,6 +16,7 @@
 #error no need to expose this header to Swig
 #endif
 
+#ifndef USER_API
 #ifndef BORNAGAIN_DEVICE_DATA_LLDATA_H
 #define BORNAGAIN_DEVICE_DATA_LLDATA_H
 
@@ -285,3 +286,4 @@ template <class T> bool HaveSameDimensions(const LLData<T>& left, const LLData<T
 }
 
 #endif // BORNAGAIN_DEVICE_DATA_LLDATA_H
+#endif // USER_API
diff --git a/Device/Data/OutputData.h b/Device/Data/OutputData.h
index 5aaba72399e973d9a6a9a68f37aa7a812511fa84..ab60d1e28427c6ccae92e539f2a03e8d95c3c55f 100644
--- a/Device/Data/OutputData.h
+++ b/Device/Data/OutputData.h
@@ -3,7 +3,7 @@
 //  BornAgain: simulate and fit scattering at grazing incidence
 //
 //! @file      Device/Data/OutputData.h
-//! @brief     Defines and implements template class OutputData.
+//! @brief     Defines and implements templated class OutputData.
 //!
 //! @homepage  http://www.bornagainproject.org
 //! @license   GNU General Public License v3 or higher (see COPYING)
@@ -26,7 +26,7 @@
 
 using std::size_t;
 
-//! Template class to store data of any type in multi-dimensional space.
+//! Templated class to store data of type double or CumulativeValue in multi-dimensional space.
 //! @ingroup tools
 
 template <class T> class OutputData {
@@ -49,9 +49,6 @@ public:
     //! returns axis with given serial number
     const IAxis& axis(size_t serial_number) const;
 
-    //! returns axis with given name
-    const IAxis& axis(const std::string& axis_name) const;
-
     // retrieve basic info
 
     //! Returns number of dimensions.
@@ -303,10 +300,6 @@ template <class T> const IAxis& OutputData<T>::axis(size_t serial_number) const
     return *m_value_axes[serial_number];
 }
 
-template <class T> const IAxis& OutputData<T>::axis(const std::string& axis_name) const {
-    return axis(getAxisIndex(axis_name));
-}
-
 template <class T> inline std::vector<size_t> OutputData<T>::getAllSizes() const {
     ASSERT(m_ll_data);
     std::vector<size_t> result;
diff --git a/Device/Data/OutputDataIterator.h b/Device/Data/OutputDataIterator.h
index c65ccc362495e874833dde46460439d7d0a7a94b..f1c32bad2a206c66c82e0bdbd7f54b02567d9d9d 100644
--- a/Device/Data/OutputDataIterator.h
+++ b/Device/Data/OutputDataIterator.h
@@ -16,6 +16,7 @@
 #error no need to expose this header to Swig
 #endif
 
+#ifndef USER_API
 #ifndef BORNAGAIN_DEVICE_DATA_OUTPUTDATAITERATOR_H
 #define BORNAGAIN_DEVICE_DATA_OUTPUTDATAITERATOR_H
 
@@ -199,3 +200,4 @@ bool operator!=(const OutputDataIterator<TValue1, TContainer1>& left,
 }
 
 #endif // BORNAGAIN_DEVICE_DATA_OUTPUTDATAITERATOR_H
+#endif // USER_API
diff --git a/Device/Detector/DetectionProperties.h b/Device/Detector/DetectionProperties.h
index eedd05c70560088d00dea29371b23e0c22e72145..e5806f73ebd46d9c6eae1af94787483c982f8975 100644
--- a/Device/Detector/DetectionProperties.h
+++ b/Device/Detector/DetectionProperties.h
@@ -16,6 +16,7 @@
 #error no need to expose this header to Swig
 #endif
 
+#ifndef USER_API
 #ifndef BORNAGAIN_DEVICE_DETECTOR_DETECTIONPROPERTIES_H
 #define BORNAGAIN_DEVICE_DETECTOR_DETECTIONPROPERTIES_H
 
@@ -58,3 +59,4 @@ private:
 };
 
 #endif // BORNAGAIN_DEVICE_DETECTOR_DETECTIONPROPERTIES_H
+#endif // USER_API
diff --git a/Device/Detector/DetectorContext.h b/Device/Detector/DetectorContext.h
index deecf6d296452e59f09777df7d273d181c33c61c..39ac3c2d3e34cd52c88ffc3d9d2faae7ec46664b 100644
--- a/Device/Detector/DetectorContext.h
+++ b/Device/Detector/DetectorContext.h
@@ -16,6 +16,7 @@
 #error no need to expose this header to Swig
 #endif
 
+#ifndef USER_API
 #ifndef BORNAGAIN_DEVICE_DETECTOR_DETECTORCONTEXT_H
 #define BORNAGAIN_DEVICE_DETECTOR_DETECTORCONTEXT_H
 
@@ -51,3 +52,4 @@ private:
 };
 
 #endif // BORNAGAIN_DEVICE_DETECTOR_DETECTORCONTEXT_H
+#endif // USER_API
diff --git a/Device/Detector/DetectorUtils.cpp b/Device/Detector/DetectorUtils.cpp
index fdf1a5af6fbc0bc76ecef5ff515490e42dbc8797..983e45d280f6006392b489776b39df004b1f3da4 100644
--- a/Device/Detector/DetectorUtils.cpp
+++ b/Device/Detector/DetectorUtils.cpp
@@ -16,11 +16,11 @@
 #include "Device/Detector/IDetector2D.h"
 
 bool DetectorUtils::isQuadratic(const IDetector2D& det) {
-    ASSERT(det.dimension()==2);
-    if (det.axis(0).size()!=det.axis(1).size())
+    ASSERT(det.dimension() == 2);
+    if (det.axis(0).size() != det.axis(1).size())
         return false;
-    if (std::abs(det.axis(0).span() - det.axis(1).span()) >
-        1e-12*(det.axis(0).span() + det.axis(1).span()))
+    if (std::abs(det.axis(0).span() - det.axis(1).span())
+        > 1e-12 * (det.axis(0).span() + det.axis(1).span()))
         return false;
     return true;
 }
diff --git a/Device/Detector/IDetector.h b/Device/Detector/IDetector.h
index 995c6c22b70a383dc2a9c735e9405fc86a86de0c..d7cb234e595f6db65a70eadd996c1dfd3a8374d5 100644
--- a/Device/Detector/IDetector.h
+++ b/Device/Detector/IDetector.h
@@ -76,7 +76,7 @@ public:
 #ifndef SWIG
     //! Returns empty detector map in given axes units.
     std::unique_ptr<OutputData<double>> createDetectorMap() const;
-#endif // SWIG
+#endif // USER_API
     //! Returns detection properties
     const DetectionProperties& detectionProperties() const { return m_detection_properties; }
 
diff --git a/Device/Detector/RectangularPixel.h b/Device/Detector/RectangularPixel.h
index a61a082cdea65ba811bf487a60d6833541cb0162..0c83ee83a81d1f7e570b4a6da5077cecf966dd64 100644
--- a/Device/Detector/RectangularPixel.h
+++ b/Device/Detector/RectangularPixel.h
@@ -16,6 +16,7 @@
 #error no need to expose this header to Swig
 #endif
 
+#ifndef USER_API
 #ifndef BORNAGAIN_DEVICE_DETECTOR_RECTANGULARPIXEL_H
 #define BORNAGAIN_DEVICE_DETECTOR_RECTANGULARPIXEL_H
 
@@ -46,3 +47,4 @@ private:
 };
 
 #endif // BORNAGAIN_DEVICE_DETECTOR_RECTANGULARPIXEL_H
+#endif // USER_API
diff --git a/Device/Detector/RegionOfInterest.h b/Device/Detector/RegionOfInterest.h
index 3466366fbf044d64d8126322f1c8a4f21e093109..d56430a026e3914d2f0645ed6a27b9b7a6b01d73 100644
--- a/Device/Detector/RegionOfInterest.h
+++ b/Device/Detector/RegionOfInterest.h
@@ -16,6 +16,7 @@
 #error no need to expose this header to Swig
 #endif
 
+#ifndef USER_API
 #ifndef BORNAGAIN_DEVICE_DETECTOR_REGIONOFINTEREST_H
 #define BORNAGAIN_DEVICE_DETECTOR_REGIONOFINTEREST_H
 
@@ -89,3 +90,4 @@ inline size_t RegionOfInterest::ycoord(size_t index, const std::vector<size_t>&
 }
 
 #endif // BORNAGAIN_DEVICE_DETECTOR_REGIONOFINTEREST_H
+#endif // USER_API
diff --git a/Device/Detector/SimpleUnitConverters.cpp b/Device/Detector/SimpleUnitConverters.cpp
index 17bfce06064e588b57d8b890e8aac977b82c1894..ec0d4ba82ae1dda88ad0ef9f21ef017239c47716 100644
--- a/Device/Detector/SimpleUnitConverters.cpp
+++ b/Device/Detector/SimpleUnitConverters.cpp
@@ -325,8 +325,8 @@ double OffSpecularConverter::calculateValue(size_t, Axes::Units units_type, doub
 
 std::vector<std::map<Axes::Units, std::string>> OffSpecularConverter::createNameMaps() const {
     std::vector<std::map<Axes::Units, std::string>> result;
-    result.push_back(AxisNames::InitOffSpecAxis0());
-    result.push_back(AxisNames::InitOffSpecAxis1());
+    result.push_back(AxisNames::InitOffSpecularAxis0());
+    result.push_back(AxisNames::InitOffSpecularAxis1());
     return result;
 }
 
diff --git a/Device/Detector/SimpleUnitConverters.h b/Device/Detector/SimpleUnitConverters.h
index 2b100f2f7756bb36641944aa1bc1b393abf58b95..08d3f1993aa0281ce681c8043adcaa478f75a630 100644
--- a/Device/Detector/SimpleUnitConverters.h
+++ b/Device/Detector/SimpleUnitConverters.h
@@ -16,6 +16,7 @@
 #error no need to expose this header to Swig
 #endif
 
+#ifndef USER_API
 #ifndef BORNAGAIN_DEVICE_DETECTOR_SIMPLEUNITCONVERTERS_H
 #define BORNAGAIN_DEVICE_DETECTOR_SIMPLEUNITCONVERTERS_H
 
@@ -165,3 +166,4 @@ private:
 };
 
 #endif // BORNAGAIN_DEVICE_DETECTOR_SIMPLEUNITCONVERTERS_H
+#endif // USER_API
diff --git a/Device/Detector/SimulationArea.h b/Device/Detector/SimulationArea.h
index 10ea8c4bed5c6520dc2d7ae28a6a84c726ebc0f4..cb06a117efb2198f8a56a411e9ec4fd5a3014c50 100644
--- a/Device/Detector/SimulationArea.h
+++ b/Device/Detector/SimulationArea.h
@@ -16,6 +16,7 @@
 #error no need to expose this header to Swig
 #endif
 
+#ifndef USER_API
 #ifndef BORNAGAIN_DEVICE_DETECTOR_SIMULATIONAREA_H
 #define BORNAGAIN_DEVICE_DETECTOR_SIMULATIONAREA_H
 
@@ -68,3 +69,4 @@ public:
 };
 
 #endif // BORNAGAIN_DEVICE_DETECTOR_SIMULATIONAREA_H
+#endif // USER_API
diff --git a/Device/Detector/SimulationAreaIterator.h b/Device/Detector/SimulationAreaIterator.h
index 8593ea79c7a7556a8c7579c7a4baa15a8ef561c6..95d951b5855df9f0c34ba2439eb691b61c20daa0 100644
--- a/Device/Detector/SimulationAreaIterator.h
+++ b/Device/Detector/SimulationAreaIterator.h
@@ -16,6 +16,7 @@
 #error no need to expose this header to Swig
 #endif
 
+#ifndef USER_API
 #ifndef BORNAGAIN_DEVICE_DETECTOR_SIMULATIONAREAITERATOR_H
 #define BORNAGAIN_DEVICE_DETECTOR_SIMULATIONAREAITERATOR_H
 
@@ -59,3 +60,4 @@ inline bool SimulationAreaIterator::operator!=(const SimulationAreaIterator& rig
 }
 
 #endif // BORNAGAIN_DEVICE_DETECTOR_SIMULATIONAREAITERATOR_H
+#endif // USER_API
diff --git a/Device/Detector/SpecularDetector1D.h b/Device/Detector/SpecularDetector1D.h
index 38b3e7494ad33ea51717afbfba01962ec4c4c4a0..fc330ceaaa158dc8efa00a4b2322f5a7aaaddef2 100644
--- a/Device/Detector/SpecularDetector1D.h
+++ b/Device/Detector/SpecularDetector1D.h
@@ -16,6 +16,7 @@
 #error no need to expose this header to Swig
 #endif
 
+#ifndef USER_API
 #ifndef BORNAGAIN_DEVICE_DETECTOR_SPECULARDETECTOR1D_H
 #define BORNAGAIN_DEVICE_DETECTOR_SPECULARDETECTOR1D_H
 
@@ -56,3 +57,4 @@ protected:
 };
 
 #endif // BORNAGAIN_DEVICE_DETECTOR_SPECULARDETECTOR1D_H
+#endif // USER_API
diff --git a/Device/Detector/SphericalDetector.cpp b/Device/Detector/SphericalDetector.cpp
index 24ddc90549ed201f5c422239cd92392523e5d913..761aff47d1aa46fed0bb7581271f613127cf49b0 100644
--- a/Device/Detector/SphericalDetector.cpp
+++ b/Device/Detector/SphericalDetector.cpp
@@ -31,8 +31,8 @@ SphericalDetector::SphericalDetector(size_t n_phi, double phi_min, double phi_ma
 }
 
 SphericalDetector::SphericalDetector(size_t n_bin, double width, double phi, double alpha)
-    : SphericalDetector(n_bin, phi-width/2, phi+width/2, n_bin, alpha-width/2, alpha+width/2) {
-}
+    : SphericalDetector(n_bin, phi - width / 2, phi + width / 2, n_bin, alpha - width / 2,
+                        alpha + width / 2) {}
 
 SphericalDetector::SphericalDetector(const SphericalDetector& other) : IDetector2D(other) {
     setName("SphericalDetector");
diff --git a/Device/Detector/SphericalPixel.h b/Device/Detector/SphericalPixel.h
index 2577b4c2685554c2555641160451c3af4f2590a8..2c7ccc7a64bdbfd736003b579fed0872c6ec4052 100644
--- a/Device/Detector/SphericalPixel.h
+++ b/Device/Detector/SphericalPixel.h
@@ -16,6 +16,7 @@
 #error no need to expose this header to Swig
 #endif
 
+#ifndef USER_API
 #ifndef BORNAGAIN_DEVICE_DETECTOR_SPHERICALPIXEL_H
 #define BORNAGAIN_DEVICE_DETECTOR_SPHERICALPIXEL_H
 
@@ -44,3 +45,4 @@ private:
 };
 
 #endif // BORNAGAIN_DEVICE_DETECTOR_SPHERICALPIXEL_H
+#endif // USER_API
diff --git a/Device/Instrument/SpectrumUtils.cpp b/Device/Histo/ImageUtils.cpp
similarity index 88%
rename from Device/Instrument/SpectrumUtils.cpp
rename to Device/Histo/ImageUtils.cpp
index 87b192fcd57a42aaff940643bca702089864a803..aeee4b4296cb5928fc74f677ff0ee5df68cd3eb1 100644
--- a/Device/Instrument/SpectrumUtils.cpp
+++ b/Device/Histo/ImageUtils.cpp
@@ -2,7 +2,7 @@
 //
 //  BornAgain: simulate and fit scattering at grazing incidence
 //
-//! @file      Device/Instrument/SpectrumUtils.cpp
+//! @file      Device/Histo/ImageUtils.cpp
 //! @brief     PyObvject forward declaration.
 //!
 //! @homepage  http://www.bornagainproject.org
@@ -12,11 +12,11 @@
 //
 //  ************************************************************************************************
 
-#include "Device/Instrument/SpectrumUtils.h"
+#include "Device/Histo/ImageUtils.h"
 #include <cmath>
-#include <tspectrum.h>
+#include <tspectrum.h> // third-party code, extracted from CERN ROOT (class TSpectrum2)
 
-std::vector<std::pair<double, double>> SpectrumUtils::FindPeaks(const Histogram2D& hist,
+std::vector<std::pair<double, double>> ImageUtils::FindPeaks(const Histogram2D& hist,
                                                                 double sigma,
                                                                 const std::string& option,
                                                                 double threshold) {
diff --git a/Device/Instrument/SpectrumUtils.h b/Device/Histo/ImageUtils.h
similarity index 82%
rename from Device/Instrument/SpectrumUtils.h
rename to Device/Histo/ImageUtils.h
index a8c897386d0cbe222f64b863edbddd3c1de9c393..21554bf29d7e90564a3018089e283d6a3c144924 100644
--- a/Device/Instrument/SpectrumUtils.h
+++ b/Device/Histo/ImageUtils.h
@@ -2,7 +2,7 @@
 //
 //  BornAgain: simulate and fit scattering at grazing incidence
 //
-//! @file      Device/Instrument/SpectrumUtils.h
+//! @file      Device/Histo/ImageUtils.h
 //! @brief     PyObvject forward declaration.
 //!
 //! @homepage  http://www.bornagainproject.org
@@ -21,9 +21,11 @@
 
 class Histogram2D;
 
-//! Collection of utils for 1D and 2D spectrum processing (background, peaks, ets).
+//! Collection of utils for 1D and 2D image processing (background, peaks, ets).
 
-namespace SpectrumUtils {
+namespace ImageUtils {
+
+//! Returns vector of peak center coordinates, for peaks in given histogram.
 
 std::vector<std::pair<double, double>> FindPeaks(const Histogram2D& hist, double sigma = 2,
                                                  const std::string& option = {},
diff --git a/Device/InputOutput/DataFormatUtils.h b/Device/InputOutput/DataFormatUtils.h
index 90fe0778af5c405a601a6b71b3c00a09914f2e32..b95a4eb3dea80e3a3921320341f850342015bc25 100644
--- a/Device/InputOutput/DataFormatUtils.h
+++ b/Device/InputOutput/DataFormatUtils.h
@@ -16,6 +16,7 @@
 #error no need to expose this header to Swig
 #endif
 
+#ifndef USER_API
 #ifndef BORNAGAIN_DEVICE_INPUTOUTPUT_DATAFORMATUTILS_H
 #define BORNAGAIN_DEVICE_INPUTOUTPUT_DATAFORMATUTILS_H
 
@@ -57,3 +58,4 @@ void readLineOfDoubles(std::vector<double>& buffer, std::istringstream& iss);
 } // namespace DataFormatUtils
 
 #endif // BORNAGAIN_DEVICE_INPUTOUTPUT_DATAFORMATUTILS_H
+#endif // USER_API
diff --git a/Device/InputOutput/OutputDataReadReflectometry.h b/Device/InputOutput/OutputDataReadReflectometry.h
index 4a536ce063dcf4e2619585b7e1b7fd875efb04de..8c04603ed1793d3087cfc54cdb2dd5301287f150 100644
--- a/Device/InputOutput/OutputDataReadReflectometry.h
+++ b/Device/InputOutput/OutputDataReadReflectometry.h
@@ -16,6 +16,7 @@
 #error no need to expose this header to Swig
 #endif
 
+#ifndef USER_API
 #ifndef BORNAGAIN_DEVICE_INPUTOUTPUT_OUTPUTDATAREADREFLECTOMETRY_H
 #define BORNAGAIN_DEVICE_INPUTOUTPUT_OUTPUTDATAREADREFLECTOMETRY_H
 
@@ -32,3 +33,4 @@ public:
 };
 
 #endif // BORNAGAIN_DEVICE_INPUTOUTPUT_OUTPUTDATAREADREFLECTOMETRY_H
+#endif // USER_API
diff --git a/Device/InputOutput/OutputDataReadWriteINT.h b/Device/InputOutput/OutputDataReadWriteINT.h
index 7e354328da62aa0c6c8190eee20e543d809ffece..a4003b4367a27a338f9dd5f6984aac8221b64a08 100644
--- a/Device/InputOutput/OutputDataReadWriteINT.h
+++ b/Device/InputOutput/OutputDataReadWriteINT.h
@@ -16,6 +16,7 @@
 #error no need to expose this header to Swig
 #endif
 
+#ifndef USER_API
 #ifndef BORNAGAIN_DEVICE_INPUTOUTPUT_OUTPUTDATAREADWRITEINT_H
 #define BORNAGAIN_DEVICE_INPUTOUTPUT_OUTPUTDATAREADWRITEINT_H
 
@@ -38,3 +39,4 @@ private:
 };
 
 #endif // BORNAGAIN_DEVICE_INPUTOUTPUT_OUTPUTDATAREADWRITEINT_H
+#endif // USER_API
diff --git a/Device/InputOutput/OutputDataReadWriteNumpyTXT.h b/Device/InputOutput/OutputDataReadWriteNumpyTXT.h
index f8199964809d88615756b88d2bff22fb14c0b847..ffb45d82ab08d24770cd6bbda23a81e6a1c93543 100644
--- a/Device/InputOutput/OutputDataReadWriteNumpyTXT.h
+++ b/Device/InputOutput/OutputDataReadWriteNumpyTXT.h
@@ -16,6 +16,7 @@
 #error no need to expose this header to Swig
 #endif
 
+#ifndef USER_API
 #ifndef BORNAGAIN_DEVICE_INPUTOUTPUT_OUTPUTDATAREADWRITENUMPYTXT_H
 #define BORNAGAIN_DEVICE_INPUTOUTPUT_OUTPUTDATAREADWRITENUMPYTXT_H
 
@@ -39,3 +40,4 @@ private:
 };
 
 #endif // BORNAGAIN_DEVICE_INPUTOUTPUT_OUTPUTDATAREADWRITENUMPYTXT_H
+#endif // USER_API
diff --git a/Device/InputOutput/OutputDataReadWriteTiff.h b/Device/InputOutput/OutputDataReadWriteTiff.h
index 286caa5b138aae0eac593d31feda43d0d1197d4d..b126f79b1b7a2583c483903f8c14ae8a5b1bed19 100644
--- a/Device/InputOutput/OutputDataReadWriteTiff.h
+++ b/Device/InputOutput/OutputDataReadWriteTiff.h
@@ -16,6 +16,7 @@
 #error no need to expose this header to Swig
 #endif
 
+#ifndef USER_API
 #ifndef BORNAGAIN_DEVICE_INPUTOUTPUT_OUTPUTDATAREADWRITETIFF_H
 #define BORNAGAIN_DEVICE_INPUTOUTPUT_OUTPUTDATAREADWRITETIFF_H
 
@@ -54,3 +55,4 @@ private:
 #endif // BORNAGAIN_TIFF_SUPPORT
 
 #endif // BORNAGAIN_DEVICE_INPUTOUTPUT_OUTPUTDATAREADWRITETIFF_H
+#endif // USER_API
diff --git a/Device/InputOutput/boost_streams.h b/Device/InputOutput/boost_streams.h
index aeda4f3cb92eefad9c31d308f37fec4e9441b1ef..db405d75d07e5d653385e4c574c6b98debb440e6 100644
--- a/Device/InputOutput/boost_streams.h
+++ b/Device/InputOutput/boost_streams.h
@@ -16,6 +16,7 @@
 #error no need to expose this header to Swig
 #endif
 
+#ifndef USER_API
 #ifndef BORNAGAIN_DEVICE_INPUTOUTPUT_BOOST_STREAMS_H
 #define BORNAGAIN_DEVICE_INPUTOUTPUT_BOOST_STREAMS_H
 
@@ -32,3 +33,4 @@
 #endif
 
 #endif // BORNAGAIN_DEVICE_INPUTOUTPUT_BOOST_STREAMS_H
+#endif // USER_API
diff --git a/Device/Instrument/FourierTransform.h b/Device/Instrument/FourierTransform.h
index 07e08ee8d252f66cab00207208e99acda1c1c590..25551f22f3aa8cc825a713f906bd655f37114f9c 100644
--- a/Device/Instrument/FourierTransform.h
+++ b/Device/Instrument/FourierTransform.h
@@ -17,6 +17,7 @@
 #error no need to expose this header to Swig
 #endif
 
+#ifndef USER_API
 #ifndef BORNAGAIN_DEVICE_INSTRUMENT_FOURIERTRANSFORM_H
 #define BORNAGAIN_DEVICE_INSTRUMENT_FOURIERTRANSFORM_H
 
@@ -94,3 +95,4 @@ private:
 };
 
 #endif // BORNAGAIN_DEVICE_INSTRUMENT_FOURIERTRANSFORM_H
+#endif // USER_API
diff --git a/Device/Instrument/Instrument.cpp b/Device/Instrument/Instrument.cpp
index dec056caedc9c75c0912a0d12bec6be76158725d..4ac393487904e6ac2f6f89821ba5c2e131c9f63e 100644
--- a/Device/Instrument/Instrument.cpp
+++ b/Device/Instrument/Instrument.cpp
@@ -80,14 +80,6 @@ void Instrument::setBeam(const Beam& beam) {
         initDetector();
 }
 
-void Instrument::setBeamIntensity(double intensity) {
-    m_beam.setIntensity(intensity);
-}
-
-void Instrument::setBeamPolarization(const kvector_t bloch_vector) {
-    m_beam.setPolarization(bloch_vector);
-}
-
 const IDetector* Instrument::getDetector() const {
     ASSERT(m_detector);
     return m_detector.get();
diff --git a/Device/Instrument/Instrument.h b/Device/Instrument/Instrument.h
index 76639628b5cb4e8f32438fc7665cc9b0da935fcb..7db47e2f5717b13b2ddb1c4e7611be20d0689eeb 100644
--- a/Device/Instrument/Instrument.h
+++ b/Device/Instrument/Instrument.h
@@ -16,6 +16,7 @@
 #error no need to expose this header to Swig
 #endif
 
+#ifndef USER_API
 #ifndef BORNAGAIN_DEVICE_INSTRUMENT_INSTRUMENT_H
 #define BORNAGAIN_DEVICE_INSTRUMENT_INSTRUMENT_H
 
@@ -46,11 +47,6 @@ public:
     //! Sets the beam wavelength and incoming angles
     void setBeamParameters(double wavelength, double alpha_i, double phi_i);
 
-    void setBeamIntensity(double intensity);
-
-    //! Sets the beam's polarization according to the given Bloch vector
-    void setBeamPolarization(const kvector_t bloch_vector);
-
     const IDetector* getDetector() const;
     IDetector& detector();
     const IDetector& detector() const;
@@ -72,3 +68,4 @@ protected:
 };
 
 #endif // BORNAGAIN_DEVICE_INSTRUMENT_INSTRUMENT_H
+#endif // USER_API
diff --git a/Device/Instrument/IntensityDataFunctions.h b/Device/Instrument/IntensityDataFunctions.h
index f81986a4ff04f27d1c952b354645cec64a7cc953..3d93337231f36c275d36e4ee2319b65a38734bfb 100644
--- a/Device/Instrument/IntensityDataFunctions.h
+++ b/Device/Instrument/IntensityDataFunctions.h
@@ -79,7 +79,7 @@ createOutputDatafrom2DArray(const std::vector<std::vector<double>>& array_2d);
 //! Creates Fourier Transform (OutputData format) of intensity map (OutputData format).
 std::unique_ptr<OutputData<double>> createFFT(const OutputData<double>& data);
 
-#endif // SWIG
+#endif // USER_API
 
 }; // namespace IntensityDataFunctions
 
diff --git a/Device/Intensity/ArrayUtils.h b/Device/Intensity/ArrayUtils.h
index 105daba33698de04f8cf001ad82f72101016a835..5d6e365b02515b9b81c01ac060afa2f03e90d121 100644
--- a/Device/Intensity/ArrayUtils.h
+++ b/Device/Intensity/ArrayUtils.h
@@ -16,6 +16,7 @@
 #error no need to expose this header to Swig
 #endif
 
+#ifndef USER_API
 #ifndef BORNAGAIN_DEVICE_INTENSITY_ARRAYUTILS_H
 #define BORNAGAIN_DEVICE_INTENSITY_ARRAYUTILS_H
 
@@ -160,3 +161,4 @@ template <class T> decltype(auto) ArrayUtils::createVector2D(const T& data) {
 }
 
 #endif // BORNAGAIN_DEVICE_INTENSITY_ARRAYUTILS_H
+#endif // USER_API
diff --git a/Device/Mask/InfinitePlane.h b/Device/Mask/InfinitePlane.h
index 83df83711fb406737dd7b0556bf561acb73f253b..c57101022c23e0e5ce22f3f1aad0082746b3af50 100644
--- a/Device/Mask/InfinitePlane.h
+++ b/Device/Mask/InfinitePlane.h
@@ -16,6 +16,7 @@
 #error no need to expose this header to Swig
 #endif
 
+#ifndef USER_API
 #ifndef BORNAGAIN_DEVICE_MASK_INFINITEPLANE_H
 #define BORNAGAIN_DEVICE_MASK_INFINITEPLANE_H
 
@@ -34,3 +35,4 @@ public:
 };
 
 #endif // BORNAGAIN_DEVICE_MASK_INFINITEPLANE_H
+#endif // USER_API
diff --git a/Device/Resolution/ConvolutionDetectorResolution.h b/Device/Resolution/ConvolutionDetectorResolution.h
index 88d757ea1d2e76f8bd7eb8f4d84932bc99a688da..a24d2c8dcfd0f06bb830e99ae162b23124bdeecd 100644
--- a/Device/Resolution/ConvolutionDetectorResolution.h
+++ b/Device/Resolution/ConvolutionDetectorResolution.h
@@ -16,6 +16,7 @@
 #error no need to expose this header to Swig
 #endif
 
+#ifndef USER_API
 #ifndef BORNAGAIN_DEVICE_RESOLUTION_CONVOLUTIONDETECTORRESOLUTION_H
 #define BORNAGAIN_DEVICE_RESOLUTION_CONVOLUTIONDETECTORRESOLUTION_H
 
@@ -70,3 +71,4 @@ inline const IResolutionFunction2D* ConvolutionDetectorResolution::getResolution
 }
 
 #endif // BORNAGAIN_DEVICE_RESOLUTION_CONVOLUTIONDETECTORRESOLUTION_H
+#endif // USER_API
diff --git a/Device/Resolution/Convolve.h b/Device/Resolution/Convolve.h
index d83dd05e4c5bb32f08201ebdf09420400f78fa33..0b70b4265b1527e683ea928e4836f7f3b67243a0 100644
--- a/Device/Resolution/Convolve.h
+++ b/Device/Resolution/Convolve.h
@@ -16,6 +16,7 @@
 #error no need to expose this header to Swig
 #endif
 
+#ifndef USER_API
 #ifndef BORNAGAIN_DEVICE_RESOLUTION_CONVOLVE_H
 #define BORNAGAIN_DEVICE_RESOLUTION_CONVOLVE_H
 
@@ -122,3 +123,4 @@ private:
 };
 
 #endif // BORNAGAIN_DEVICE_RESOLUTION_CONVOLVE_H
+#endif // USER_API
diff --git a/Device/Resolution/ScanResolution.h b/Device/Resolution/ScanResolution.h
index f4298c8e4b921202dce80b0b71e95ed8afcc0352..a1aaddced35233fa52fde0a8a27cd51ab18ce4a9 100644
--- a/Device/Resolution/ScanResolution.h
+++ b/Device/Resolution/ScanResolution.h
@@ -53,7 +53,7 @@ public:
     virtual std::string name() const = 0;
     virtual double delta() const = 0;
 
-#endif // SWIG
+#endif // USER_API
 protected:
     ScanResolution();
     ScanResolution(const IRangedDistribution& distr);
diff --git a/Device/Unit/AxisNames.cpp b/Device/Unit/AxisNames.cpp
index e2ff4f806619f5baf402941280f202dc2cbf4986..34e8278e9ba59913b79747abeeb690f48805685b 100644
--- a/Device/Unit/AxisNames.cpp
+++ b/Device/Unit/AxisNames.cpp
@@ -58,14 +58,14 @@ std::map<Axes::Units, std::string> InitRectangularAxis1() {
 }
 // For off-specular simulations (both spherical and rectangular detectors)
 // Currently 'mm' is not supported for the y-axis
-std::map<Axes::Units, std::string> InitOffSpecAxis0() {
+std::map<Axes::Units, std::string> InitOffSpecularAxis0() {
     std::map<Axes::Units, std::string> result;
     result[Axes::Units::NBINS] = "X [nbins]";
     result[Axes::Units::RADIANS] = "alpha_i [rad]";
     result[Axes::Units::DEGREES] = "alpha_i [deg]";
     return result;
 }
-std::map<Axes::Units, std::string> InitOffSpecAxis1() {
+std::map<Axes::Units, std::string> InitOffSpecularAxis1() {
     std::map<Axes::Units, std::string> result;
     result[Axes::Units::NBINS] = "Y [nbins]";
     result[Axes::Units::RADIANS] = "alpha_f [rad]";
diff --git a/Device/Unit/AxisNames.h b/Device/Unit/AxisNames.h
index 62c47573a9f222787b2f771a7cecd35310f1f8d7..120f5a2122ddff39141e877711d567a0422cc781 100644
--- a/Device/Unit/AxisNames.h
+++ b/Device/Unit/AxisNames.h
@@ -16,6 +16,7 @@
 #error no need to expose this header to Swig
 #endif
 
+#ifndef USER_API
 #ifndef BORNAGAIN_DEVICE_UNIT_AXISNAMES_H
 #define BORNAGAIN_DEVICE_UNIT_AXISNAMES_H
 
@@ -31,11 +32,12 @@ std::map<Axes::Units, std::string> InitSphericalAxis0();
 std::map<Axes::Units, std::string> InitSphericalAxis1();
 std::map<Axes::Units, std::string> InitRectangularAxis0();
 std::map<Axes::Units, std::string> InitRectangularAxis1();
-std::map<Axes::Units, std::string> InitOffSpecAxis0();
-std::map<Axes::Units, std::string> InitOffSpecAxis1();
+std::map<Axes::Units, std::string> InitOffSpecularAxis0();
+std::map<Axes::Units, std::string> InitOffSpecularAxis1();
 std::map<Axes::Units, std::string> InitSpecAxis();
 std::map<Axes::Units, std::string> InitSpecAxisQ();
 std::map<Axes::Units, std::string> InitSampleDepthAxis();
 } // namespace AxisNames
 
 #endif // BORNAGAIN_DEVICE_UNIT_AXISNAMES_H
+#endif // USER_API
diff --git a/Device/Unit/IUnitConverter.h b/Device/Unit/IUnitConverter.h
index c95d4c9891348e2b207977a414c9fc5950d94bdc..00463e648431c5affbe0721a23e2c541298801d7 100644
--- a/Device/Unit/IUnitConverter.h
+++ b/Device/Unit/IUnitConverter.h
@@ -65,13 +65,13 @@ public:
     //! Creates OutputData array in converter units.
     virtual std::unique_ptr<OutputData<double>> createConvertedData(const OutputData<double>& data,
                                                                     Axes::Units units) const;
-#endif // SWIG
+#endif // USER_API
 
 protected:
     void checkIndex(size_t i_axis) const;
 #ifndef SWIG
     [[noreturn]] void throwUnitsError(std::string method, std::vector<Axes::Units> available) const;
-#endif // SWIG
+#endif // USER_API
 
 private:
     virtual std::vector<std::map<Axes::Units, std::string>> createNameMaps() const = 0;
diff --git a/Doc/Doxygen/CMakeLists.txt b/Doc/Doxygen/CMakeLists.txt
index ddc6f220e43f499da2c97d440bf06483d0972768..01f7cd6cf3d048e19c902be7c1cdc9fd60f38945 100644
--- a/Doc/Doxygen/CMakeLists.txt
+++ b/Doc/Doxygen/CMakeLists.txt
@@ -4,7 +4,7 @@ file(MAKE_DIRECTORY ${AUTO_DOX_DIR})
 file(MAKE_DIRECTORY ${CMAKE_BINARY_DIR}/html)
 add_custom_target(doxy) # this target builds _all_ documentation flavors
 foreach(flavor user long)
-    configure_file(Doxyfile.${flavor}.in
+    configure_file(${flavor}/Doxyfile.in
         ${AUTO_DOX_DIR}/Doxyfile.${flavor} @ONLY)
     add_custom_target(doxy${flavor}
         COMMAND doxygen ${AUTO_DOX_DIR}/Doxyfile.${flavor} )
diff --git a/Doc/Doxygen/README.md b/Doc/Doxygen/README.md
index 33122b51814f5556a545e5eb2b8f528770c397f8..eb04b640117411534dd7508253f4d816282a9232 100644
--- a/Doc/Doxygen/README.md
+++ b/Doc/Doxygen/README.md
@@ -2,7 +2,6 @@ We support different flavors of Doxygen documentation:
 
 - "user", the BornAgain user API
 - "long", full C++ source documentation for developers
-- "dirgraphs", for analysing include dependences
 
 To build the documentation,
 ```
@@ -10,12 +9,13 @@ cd build
 # configure:
 cmake -DBORNAGAIN_CONFIGURE_DOXY=ON ..
 # make:
-make doxyuser # other make targets are 'doxylong' etc,
-              # or 'doxy' to build all available flavors
+make doxyuser
+make doxylong
+make doxy     # to build both flavors
 ```
 
 The configure step writes Doxyfiles to the directory
 `<build>/doxygen`. Do not edit these files.
 
 The make step writes the documentation to directories
-`<build>/html/user` etc.
+`<build>/html/user`, `<build>/html/long`.
diff --git a/Doc/Doxygen/defgroups.dox b/Doc/Doxygen/common/defgroups.dox
similarity index 100%
rename from Doc/Doxygen/defgroups.dox
rename to Doc/Doxygen/common/defgroups.dox
diff --git a/Doc/Doxygen/Doxyfile.long.in b/Doc/Doxygen/long/Doxyfile.in
similarity index 99%
rename from Doc/Doxygen/Doxyfile.long.in
rename to Doc/Doxygen/long/Doxyfile.in
index 1ea3268dd066e68234edf430fd585acea5667381..d76c1cbdb9f3222875ce6df064effaaa66532b29 100644
--- a/Doc/Doxygen/Doxyfile.long.in
+++ b/Doc/Doxygen/long/Doxyfile.in
@@ -106,7 +106,7 @@ OUTPUT_TEXT_DIRECTION  = None
 # documentation (similar to Javadoc). Set to NO to disable this.
 # The default value is: YES.
 
-BRIEF_MEMBER_DESC      = NO
+BRIEF_MEMBER_DESC      = YES
 
 # If the REPEAT_BRIEF tag is set to YES, doxygen will prepend the brief
 # description of a member or function before the detailed description
@@ -835,7 +835,8 @@ WARN_LOGFILE           =
 # spaces. See also FILE_PATTERNS and EXTENSION_MAPPING
 # Note: If this tag is empty the current directory is searched.
 
-INPUT                  = @CMAKE_SOURCE_DIR@/Doc/Doxygen \
+INPUT                  = @CMAKE_SOURCE_DIR@/Doc/Doxygen/long \
+                         @CMAKE_SOURCE_DIR@/Doc/Doxygen/common \
                          @CMAKE_SOURCE_DIR@/Base \
                          @CMAKE_SOURCE_DIR@/Fit \
                          @CMAKE_SOURCE_DIR@/Param \
@@ -870,7 +871,8 @@ INPUT_ENCODING         = UTF-8
 
 FILE_PATTERNS          = *.cpp \
                          *.h \
-                         *.dox
+                         *.dox \
+                         *.md
 
 # The RECURSIVE tag can be used to specify whether or not subdirectories should
 # be searched for input files as well.
@@ -901,7 +903,7 @@ EXCLUDE_SYMLINKS       = NO
 # Note that the wildcards are matched against the file with absolute path, so to
 # exclude all test directories for example use the pattern */test/*
 
-EXCLUDE_PATTERNS       = */PythonAPI/*
+EXCLUDE_PATTERNS       = */3rdParty/* */Test/*
 
 # The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names
 # (namespaces, classes, functions, etc.) that should be excluded from the
diff --git a/Doc/Doxygen/long/mainpage.md b/Doc/Doxygen/long/mainpage.md
new file mode 100644
index 0000000000000000000000000000000000000000..60c0f397075f0558028f793cd8e4bc72333c70b2
--- /dev/null
+++ b/Doc/Doxygen/long/mainpage.md
@@ -0,0 +1,27 @@
+## BornAgain developer reference {#mainpage}
+
+C++ developer reference of <a href="http://www.bornagainproject.org">BornAgain Project</a>,
+ an open-source software to simulate and fit
+ neutron and x-ray reflectometry and grazing-incidence small-angle scattering.
+
+### See also
+
+* <https://bornagainproject.org>, project homepage;
+* <https://github.com/scgmlz/BornAgain>, source repository;
+
+### License
+
+[GNU General Public License v3 or higher](https://github.com/scgmlz/BornAgain/blob/master/COPYING)
+
+Copyright Forschungszentrum Jülich GmbH 2015-
+
+
+### Authors
+
+Scientific Computing Group at MLZ Garching.
+
+See file [AUTHORS](https://github.com/scgmlz/BornAgain/blob/master/AUTHORS).
+
+### Citation
+
+See file [CITATION](https://github.com/scgmlz/BornAgain/blob/master/CITATION).
diff --git a/Doc/Doxygen/mainpage.dox b/Doc/Doxygen/mainpage.dox
deleted file mode 100644
index 238aa7a5033c1de75d797fce03fa625d08db8446..0000000000000000000000000000000000000000
--- a/Doc/Doxygen/mainpage.dox
+++ /dev/null
@@ -1,38 +0,0 @@
-/*!
-\mainpage
-
-C++ API Reference of <a href="http://www.bornagainproject.org">BornAgain Project</a>,
- an open-source software to simulate and fit
- neutron and x-ray reflectometry and grazing-incidence small-angle scattering.
-
-<ul>
-<li> Section <a href="userapi.html">User API</a>
-  contains list of main classes to run the simulation.
-<li> Section <a href="annotated.html">Full C++ API</a>
-  contains a full list of classes belonging to the %BornAgain framework.
-<li> Section <a href="namespace.html">Namespace List</a>
-  contains a full list of namespaces belonging to the %BornAgain framework.
-<li> Section <a href="files.html">File List</a>
-  lets you browse the C++ source code.
-
-</ul>
-
-
-<b> License: </b>
-<br>
-<a href="https://github.com/scgmlz/BornAgain/blob/master/COPYING"
-  >GNU General Public License v3 or higher</a>
-<br>
-Copyright Forschungszentrum Jülich GmbH 2015-
-
-
-<b> Authors:  </b>
-<br>
-Scientific Computing Group at MLZ Garching.
-<br>
-See file <a href="https://github.com/scgmlz/BornAgain/blob/master/AUTHORS">AUTHORS</a>
-
-<b> Citation:  </b>
-See file <a href="https://github.com/scgmlz/BornAgain/blob/master/CITATION">CITATION</a>
-
-*/
diff --git a/Doc/Doxygen/Doxyfile.user.in b/Doc/Doxygen/user/Doxyfile.in
similarity index 99%
rename from Doc/Doxygen/Doxyfile.user.in
rename to Doc/Doxygen/user/Doxyfile.in
index 457a9b872c264a8b4ff437f8c17c075c937f7523..093c3c45712c4601498780786b981b238bd6feff 100644
--- a/Doc/Doxygen/Doxyfile.user.in
+++ b/Doc/Doxygen/user/Doxyfile.in
@@ -497,7 +497,7 @@ EXTRACT_PACKAGE        = NO
 # included in the documentation.
 # The default value is: NO.
 
-EXTRACT_STATIC         = NO
+EXTRACT_STATIC         = YES
 
 # If the EXTRACT_LOCAL_CLASSES tag is set to YES, classes (and structs) defined
 # locally in source files will be included in the documentation. If set to NO,
@@ -505,7 +505,7 @@ EXTRACT_STATIC         = NO
 # for Java sources.
 # The default value is: YES.
 
-EXTRACT_LOCAL_CLASSES  = YES
+EXTRACT_LOCAL_CLASSES  = NO
 
 # This flag is only useful for Objective-C code. If set to YES, local methods,
 # which are defined in the implementation section but not in the interface are
@@ -607,14 +607,14 @@ FORCE_LOCAL_INCLUDES   = YES
 # documentation for inline members.
 # The default value is: YES.
 
-INLINE_INFO            = YES
+INLINE_INFO            = NO
 
 # If the SORT_MEMBER_DOCS tag is set to YES then doxygen will sort the
 # (detailed) documentation of file and class members alphabetically by member
 # name. If set to NO, the members will appear in declaration order.
 # The default value is: YES.
 
-SORT_MEMBER_DOCS       = NO
+SORT_MEMBER_DOCS       = YES
 
 # If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the brief
 # descriptions of file, namespace and class members alphabetically by member
@@ -622,7 +622,7 @@ SORT_MEMBER_DOCS       = NO
 # this will also influence the order of the classes in the class list.
 # The default value is: NO.
 
-SORT_BRIEF_DOCS        = NO
+SORT_BRIEF_DOCS        = YES
 
 # If the SORT_MEMBERS_CTORS_1ST tag is set to YES then doxygen will sort the
 # (brief and detailed) documentation of class members so that constructors and
@@ -634,14 +634,14 @@ SORT_BRIEF_DOCS        = NO
 # detailed member documentation.
 # The default value is: NO.
 
-SORT_MEMBERS_CTORS_1ST = NO
+SORT_MEMBERS_CTORS_1ST = YES
 
 # If the SORT_GROUP_NAMES tag is set to YES then doxygen will sort the hierarchy
 # of group names into alphabetical order. If set to NO the group names will
 # appear in their defined order.
 # The default value is: NO.
 
-SORT_GROUP_NAMES       = NO
+SORT_GROUP_NAMES       = YES
 
 # If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be sorted by
 # fully-qualified names, including namespaces. If set to NO, the class list will
@@ -667,19 +667,19 @@ STRICT_PROTO_MATCHING  = NO
 # list. This list is created by putting \todo commands in the documentation.
 # The default value is: YES.
 
-GENERATE_TODOLIST      = YES
+GENERATE_TODOLIST      = NO
 
 # The GENERATE_TESTLIST tag can be used to enable (YES) or disable (NO) the test
 # list. This list is created by putting \test commands in the documentation.
 # The default value is: YES.
 
-GENERATE_TESTLIST      = YES
+GENERATE_TESTLIST      = NO
 
 # The GENERATE_BUGLIST tag can be used to enable (YES) or disable (NO) the bug
 # list. This list is created by putting \bug commands in the documentation.
 # The default value is: YES.
 
-GENERATE_BUGLIST       = YES
+GENERATE_BUGLIST       = NO
 
 # The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or disable (NO)
 # the deprecated list. This list is created by putting \deprecated commands in
@@ -835,7 +835,8 @@ WARN_LOGFILE           =
 # spaces. See also FILE_PATTERNS and EXTENSION_MAPPING
 # Note: If this tag is empty the current directory is searched.
 
-INPUT                  = @CMAKE_SOURCE_DIR@/Doc/Doxygen \
+INPUT                  = @CMAKE_SOURCE_DIR@/Doc/Doxygen/user \
+                         @CMAKE_SOURCE_DIR@/Doc/Doxygen/common \
                          @CMAKE_SOURCE_DIR@/Base \
                          @CMAKE_SOURCE_DIR@/Fit \
                          @CMAKE_SOURCE_DIR@/Param \
@@ -870,7 +871,8 @@ INPUT_ENCODING         = UTF-8
 
 FILE_PATTERNS          = *.cpp \
                          *.h \
-                         *.dox
+                         *.dox \
+                         *.md
 
 # The RECURSIVE tag can be used to specify whether or not subdirectories should
 # be searched for input files as well.
@@ -901,7 +903,7 @@ EXCLUDE_SYMLINKS       = NO
 # Note that the wildcards are matched against the file with absolute path, so to
 # exclude all test directories for example use the pattern */test/*
 
-EXCLUDE_PATTERNS       = */PythonAPI/*
+EXCLUDE_PATTERNS       = */3rdParty/* */Test/*
 
 # The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names
 # (namespaces, classes, functions, etc.) that should be excluded from the
@@ -1007,7 +1009,7 @@ USE_MDFILE_AS_MAINPAGE =
 # also VERBATIM_HEADERS is set to NO.
 # The default value is: NO.
 
-SOURCE_BROWSER         = YES
+SOURCE_BROWSER         = NO
 
 # Setting the INLINE_SOURCES tag to YES will include the body of functions,
 # classes and enums directly into the documentation.
@@ -1123,7 +1125,7 @@ CLANG_DATABASE_PATH    =
 # classes, structs, unions or interfaces.
 # The default value is: YES.
 
-ALPHABETICAL_INDEX     = YES
+ALPHABETICAL_INDEX     = NO
 
 # The COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns in
 # which the alphabetical index list will be split.
@@ -2183,7 +2185,9 @@ INCLUDE_FILE_PATTERNS  =
 # recursively expanded use the := operator instead of the = operator.
 # This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
 
-PREDEFINED             = BORNAGAIN_PYTHON
+PREDEFINED             = BORNAGAIN_PYTHON \
+                         SWIG \
+                         USER_API
 
 # If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then this
 # tag can be used to specify a list of macro names that should be expanded. The
@@ -2419,7 +2423,7 @@ CALLER_GRAPH           = NO
 # The default value is: YES.
 # This tag requires that the tag HAVE_DOT is set to YES.
 
-GRAPHICAL_HIERARCHY    = YES
+GRAPHICAL_HIERARCHY    = NO
 
 # If the DIRECTORY_GRAPH tag is set to YES then doxygen will show the
 # dependencies a directory has on other directories in a graphical way. The
diff --git a/Doc/Doxygen/userapi.dox b/Doc/Doxygen/user/mainpage.md
similarity index 73%
rename from Doc/Doxygen/userapi.dox
rename to Doc/Doxygen/user/mainpage.md
index 792593fd4ab0b25cd6a200b59159b295786ad4ac..6e210cda4cf3a79c9fedf6a52c646b91c1e19d6e 100644
--- a/Doc/Doxygen/userapi.dox
+++ b/Doc/Doxygen/user/mainpage.md
@@ -1,5 +1,11 @@
-/*!
-\page userapi User API
+## BornAgain Python user reference {#mainpage}
+
+Python user reference of <a href="http://www.bornagainproject.org">BornAgain Project</a>,
+ an open-source software to simulate and fit
+ neutron and x-ray reflectometry and grazing-incidence small-angle scattering.
+
+
+<div>
 
 Here is a list of classes grouped in several categories to create the sample, describe scattering geometry, run the simulation and perform fitting.
 
@@ -50,8 +56,29 @@ Here is a list of additional classes from internal API.
 <li> \ref formfactors_internal "Form factors internals" <br>
 <li> \ref distribution_internal "Distribution function internals"
 <li> \ref tools_internal "Tools internals" <br>
-<li> \ref input_output_internal "Input/output internals" <br>
 <li> \ref fitting_internal "Fitting internals" <br>
 </ul>
 
-*/
+</div>
+
+### See also
+
+* <https://bornagainproject.org>, project homepage;
+* <https://github.com/scgmlz/BornAgain>, source repository;
+
+### License
+
+[GNU General Public License v3 or higher](https://github.com/scgmlz/BornAgain/blob/master/COPYING)
+
+Copyright Forschungszentrum Jülich GmbH 2015-
+
+
+### Authors
+
+Scientific Computing Group at MLZ Garching.
+
+See file [AUTHORS](https://github.com/scgmlz/BornAgain/blob/master/AUTHORS).
+
+### Citation
+
+See file [CITATION](https://github.com/scgmlz/BornAgain/blob/master/CITATION).
diff --git a/Doc/FFCatalog/fig/ff2/bornplot.py b/Doc/FFCatalog/fig/ff2/bornplot.py
index a834a978c71c011f17798058a6e66f4e1c48fc44..7e8ecc7b9d71f9fe603d4f66d43a3c4e69be04ac 100644
--- a/Doc/FFCatalog/fig/ff2/bornplot.py
+++ b/Doc/FFCatalog/fig/ff2/bornplot.py
@@ -10,7 +10,7 @@ rc('text', usetex=True)
 rc('image', cmap='inferno')
 
 import bornagain as ba
-from bornagain import nm, deg, angstrom, deg2rad
+from bornagain import deg, angstrom
 
 
 class BinRange:
diff --git a/Examples/Python/fit55_SpecularIntro/PolarizedSpinAsymmetryFit.py b/Examples/Python/fit55_SpecularIntro/PolarizedSpinAsymmetryFit.py
index 4b89d453bb1122cf8f5bec6cc9d7d21f0b596751..970338e1de1c273111fb3925eb0aa6cf635ab805 100644
--- a/Examples/Python/fit55_SpecularIntro/PolarizedSpinAsymmetryFit.py
+++ b/Examples/Python/fit55_SpecularIntro/PolarizedSpinAsymmetryFit.py
@@ -91,7 +91,7 @@ def get_simulation(q_axis, parameters, polarization, analyzer):
     distr = ba.RangedDistributionGaussian(n_samples, n_sig)
     scan.setAbsoluteQResolution(distr, parameters["q_res"])
 
-    simulation.setBeamPolarization(polarization)
+    simulation.beam().setPolarization(polarization)
     simulation.setAnalyzerProperties(analyzer, 1.0, 0.5)
 
     simulation.setScan(scan)
diff --git a/Examples/Python/sim11_Device/OffSpecularSimulation.py b/Examples/Python/sim11_Device/OffSpecularSimulation.py
index 7784246f726613695eafa3ba83749b7853c4cff9..495eb8923d019df0cca88c5e6b431e89b27418b0 100644
--- a/Examples/Python/sim11_Device/OffSpecularSimulation.py
+++ b/Examples/Python/sim11_Device/OffSpecularSimulation.py
@@ -57,7 +57,7 @@ def get_simulation():
     """
     Returns an off-specular simulation with beam and detector defined.
     """
-    simulation = ba.OffSpecSimulation()
+    simulation = ba.OffSpecularSimulation()
     simulation.setDetectorParameters(20, phi_f_min*deg, phi_f_max*deg, 200,
                                      alpha_f_min*deg, alpha_f_max*deg)
     # define the beam with alpha_i varied between alpha_i_min and alpha_i_max
diff --git a/Examples/Python/sim11_Device/ResonatorOffSpecSetup.py b/Examples/Python/sim11_Device/ResonatorOffSpecSetup.py
index 2ea4b1cc604c01e3fe6bcc1b629c631aee5aba74..2d3a022203632101d248811b651abfed644dec2a 100644
--- a/Examples/Python/sim11_Device/ResonatorOffSpecSetup.py
+++ b/Examples/Python/sim11_Device/ResonatorOffSpecSetup.py
@@ -56,7 +56,7 @@ def get_offspec_simulation():
     """
 
     # create OffSpecular simulation
-    simulation = ba.OffSpecSimulation()
+    simulation = ba.OffSpecularSimulation()
     if not "__no_terminal__" in globals():
         simulation.setTerminalProgressMonitor()
 
diff --git a/Examples/Python/sim21_Reflectometry/BasicPolarizedReflectometry.py b/Examples/Python/sim21_Reflectometry/BasicPolarizedReflectometry.py
index a61b8f9da614369882137b1e201b4eba94cbb7da..876ffbc11af1a46f5c2ff85aed3b2f6f556d65ed 100644
--- a/Examples/Python/sim21_Reflectometry/BasicPolarizedReflectometry.py
+++ b/Examples/Python/sim21_Reflectometry/BasicPolarizedReflectometry.py
@@ -53,7 +53,7 @@ def run_simulation(polarization=ba.kvector_t(0, 1, 0),
     simulation = get_simulation()
 
     # adding polarization and analyzer operator
-    simulation.setBeamPolarization(polarization)
+    simulation.beam().setPolarization(polarization)
     simulation.setAnalyzerProperties(analyzer, 1.0, 0.5)
 
     simulation.setSample(sample)
diff --git a/Examples/Python/sim21_Reflectometry/PolarizedNoAnalyzer.py b/Examples/Python/sim21_Reflectometry/PolarizedNoAnalyzer.py
index 3be7294ae9257c39797f09005a7d29121cd65613..2235504c4acb7e00659ef0cc0b8f0518b3ee5e91 100644
--- a/Examples/Python/sim21_Reflectometry/PolarizedNoAnalyzer.py
+++ b/Examples/Python/sim21_Reflectometry/PolarizedNoAnalyzer.py
@@ -52,7 +52,7 @@ def run_simulation(polarization=ba.kvector_t(0.0, 1.0, 0.0), analyzer=None):
     simulation = get_simulation()
 
     # adding polarization and analyzer operator
-    simulation.setBeamPolarization(polarization)
+    simulation.beam().setPolarization(polarization)
     if analyzer:
         simulation.setAnalyzerProperties(analyzer, 1.0, 0.5)
 
diff --git a/Examples/Python/sim21_Reflectometry/PolarizedNonperfectAnalyzerPolarizer.py b/Examples/Python/sim21_Reflectometry/PolarizedNonperfectAnalyzerPolarizer.py
index 449294f4e1668ecc04836a64b337520e1e3cf718..9d1f7089067fcd9e6155e181652bd2d8ca85748a 100644
--- a/Examples/Python/sim21_Reflectometry/PolarizedNonperfectAnalyzerPolarizer.py
+++ b/Examples/Python/sim21_Reflectometry/PolarizedNonperfectAnalyzerPolarizer.py
@@ -81,7 +81,7 @@ def run_simulation(*,
 
     simulation = get_simulation()
 
-    simulation.setBeamPolarization(polarization*polarizer_efficiency)
+    simulation.beam().setPolarization(polarization*polarizer_efficiency)
     simulation.setAnalyzerProperties(analyzer, analyzer_efficiency, 0.5)
 
     simulation.setBackground(ba.ConstantBackground(1e-7))
diff --git a/Examples/Python/sim21_Reflectometry/PolarizedSpinAsymmetry.py b/Examples/Python/sim21_Reflectometry/PolarizedSpinAsymmetry.py
index 68d9a849b06db28ed3ffaf0f927c8533f80d4cae..069a4e34a79afcc62704cbc08676eff2b3e9d36d 100644
--- a/Examples/Python/sim21_Reflectometry/PolarizedSpinAsymmetry.py
+++ b/Examples/Python/sim21_Reflectometry/PolarizedSpinAsymmetry.py
@@ -91,7 +91,7 @@ def get_simulation(q_axis, parameters, polarization, analyzer):
     distr = ba.RangedDistributionGaussian(n_samples, n_sig)
     scan.setAbsoluteQResolution(distr, parameters["q_res"])
 
-    simulation.setBeamPolarization(polarization)
+    simulation.beam().setPolarization(polarization)
     simulation.setAnalyzerProperties(analyzer, 1.0, 0.5)
 
     simulation.setScan(scan)
diff --git a/Examples/Python/sim21_Reflectometry/PolarizedSpinFlip.py b/Examples/Python/sim21_Reflectometry/PolarizedSpinFlip.py
index 901087ebb03e3a7cdba54d300c2bdb7811e9a2e2..293c35a741cc6c0ed63556d52ac233600102bf9f 100644
--- a/Examples/Python/sim21_Reflectometry/PolarizedSpinFlip.py
+++ b/Examples/Python/sim21_Reflectometry/PolarizedSpinFlip.py
@@ -54,7 +54,7 @@ def run_simulation(polarization=ba.kvector_t(0, 1, 0),
     simulation = get_simulation()
 
     # adding polarization and analyzer operator
-    simulation.setBeamPolarization(polarization)
+    simulation.beam().setPolarization(polarization)
     simulation.setAnalyzerProperties(analyzer, 1.0, 0.5)
 
     simulation.setSample(sample)
diff --git a/Examples/Python/sim23_SAS/PolarizedSANS.py b/Examples/Python/sim23_SAS/PolarizedSANS.py
index 5c7f8a6f7c6cbac99e4ea1cb9928f0318e4d3782..72544844103c7bc3f7b681df218fa6df4e9bc0a5 100644
--- a/Examples/Python/sim23_SAS/PolarizedSANS.py
+++ b/Examples/Python/sim23_SAS/PolarizedSANS.py
@@ -68,7 +68,7 @@ def get_simulation():
     # Defining beam polarization and polarization analysis for spin-flip channel
     analyzer_dir = kvector_t(0.0, 0.0, -1.0)
     beampol = kvector_t(0.0, 0.0, 1.0)
-    simulation.setBeamPolarization(beampol)
+    simulation.beam().setPolarization(beampol)
     simulation.setAnalyzerProperties(analyzer_dir, 1.0, 0.5)
 
     return simulation
diff --git a/Fit/Adapter/GSLLevenbergMarquardtMinimizer.h b/Fit/Adapter/GSLLevenbergMarquardtMinimizer.h
index 7fa2133283f0ed7d2d5c96ec7bc1505326a155ce..05d891daa96851ee7cbd905ecb2c5cf99ebf5f51 100644
--- a/Fit/Adapter/GSLLevenbergMarquardtMinimizer.h
+++ b/Fit/Adapter/GSLLevenbergMarquardtMinimizer.h
@@ -16,6 +16,7 @@
 #error no need to expose this header to Swig
 #endif
 
+#ifndef USER_API
 #ifndef BORNAGAIN_FIT_ADAPTER_GSLLEVENBERGMARQUARDTMINIMIZER_H
 #define BORNAGAIN_FIT_ADAPTER_GSLLEVENBERGMARQUARDTMINIMIZER_H
 
@@ -64,3 +65,4 @@ private:
 };
 
 #endif // BORNAGAIN_FIT_ADAPTER_GSLLEVENBERGMARQUARDTMINIMIZER_H
+#endif // USER_API
diff --git a/Fit/Adapter/GSLMultiMinimizer.h b/Fit/Adapter/GSLMultiMinimizer.h
index 9ccf52a9489b4fe3e9e4b2bfd0330077cf8d4be8..0e1703908adcf293c32920585891cbe989d78871 100644
--- a/Fit/Adapter/GSLMultiMinimizer.h
+++ b/Fit/Adapter/GSLMultiMinimizer.h
@@ -16,6 +16,7 @@
 #error no need to expose this header to Swig
 #endif
 
+#ifndef USER_API
 #ifndef BORNAGAIN_FIT_ADAPTER_GSLMULTIMINIMIZER_H
 #define BORNAGAIN_FIT_ADAPTER_GSLMULTIMINIMIZER_H
 
@@ -54,3 +55,4 @@ private:
 };
 
 #endif // BORNAGAIN_FIT_ADAPTER_GSLMULTIMINIMIZER_H
+#endif // USER_API
diff --git a/Fit/Adapter/GeneticMinimizer.h b/Fit/Adapter/GeneticMinimizer.h
index c3a2f548e67508f1a537e974e9b89a0eb3d1982a..26194b4ec935ab7492fa631eff83c1529e0a29c7 100644
--- a/Fit/Adapter/GeneticMinimizer.h
+++ b/Fit/Adapter/GeneticMinimizer.h
@@ -16,6 +16,7 @@
 #error no need to expose this header to Swig
 #endif
 
+#ifndef USER_API
 #ifndef BORNAGAIN_FIT_ADAPTER_GENETICMINIMIZER_H
 #define BORNAGAIN_FIT_ADAPTER_GENETICMINIMIZER_H
 
@@ -71,3 +72,4 @@ private:
 };
 
 #endif // BORNAGAIN_FIT_ADAPTER_GENETICMINIMIZER_H
+#endif // USER_API
diff --git a/Fit/Adapter/IFunctionAdapter.h b/Fit/Adapter/IFunctionAdapter.h
index 2cc5ea801f27e0fd2ed86fe8c667f82d34d268a9..7d7cd3b8af59ae3af3aebc321fa8989c9c1276ba 100644
--- a/Fit/Adapter/IFunctionAdapter.h
+++ b/Fit/Adapter/IFunctionAdapter.h
@@ -16,6 +16,7 @@
 #error no need to expose this header to Swig
 #endif
 
+#ifndef USER_API
 #ifndef BORNAGAIN_FIT_ADAPTER_IFUNCTIONADAPTER_H
 #define BORNAGAIN_FIT_ADAPTER_IFUNCTIONADAPTER_H
 
@@ -40,3 +41,4 @@ protected:
 } // namespace mumufit
 
 #endif // BORNAGAIN_FIT_ADAPTER_IFUNCTIONADAPTER_H
+#endif // USER_API
diff --git a/Fit/Adapter/MinimizerAdapter.h b/Fit/Adapter/MinimizerAdapter.h
index 4127c5935b5ef30bcac97091bc525158a805c136..a778917be1d46b8562ad86a89c6f2e93db96d877 100644
--- a/Fit/Adapter/MinimizerAdapter.h
+++ b/Fit/Adapter/MinimizerAdapter.h
@@ -16,6 +16,7 @@
 #error no need to expose this header to Swig
 #endif
 
+#ifndef USER_API
 #ifndef BORNAGAIN_FIT_ADAPTER_MINIMIZERADAPTER_H
 #define BORNAGAIN_FIT_ADAPTER_MINIMIZERADAPTER_H
 
@@ -121,3 +122,4 @@ template <class T> T MinimizerAdapter::optionValue(const std::string& optionName
 }
 
 #endif // BORNAGAIN_FIT_ADAPTER_MINIMIZERADAPTER_H
+#endif // USER_API
diff --git a/Fit/Adapter/Minuit2Minimizer.h b/Fit/Adapter/Minuit2Minimizer.h
index 0784dfd33505a0b239c29abd151ad07ac674cae0..faa26e75207dd1a1458d34fbdc7be3aebe0c5c07 100644
--- a/Fit/Adapter/Minuit2Minimizer.h
+++ b/Fit/Adapter/Minuit2Minimizer.h
@@ -16,6 +16,7 @@
 #error no need to expose this header to Swig
 #endif
 
+#ifndef USER_API
 #ifndef BORNAGAIN_FIT_ADAPTER_MINUIT2MINIMIZER_H
 #define BORNAGAIN_FIT_ADAPTER_MINUIT2MINIMIZER_H
 
@@ -84,3 +85,4 @@ private:
 };
 
 #endif // BORNAGAIN_FIT_ADAPTER_MINUIT2MINIMIZER_H
+#endif // USER_API
diff --git a/Fit/Adapter/ObjectiveFunctionAdapter.h b/Fit/Adapter/ObjectiveFunctionAdapter.h
index f0513d65e08911ae27d9d5e654e774e462964477..ef1df8d348b2021f10cce3c7eddddf51e44aa1e4 100644
--- a/Fit/Adapter/ObjectiveFunctionAdapter.h
+++ b/Fit/Adapter/ObjectiveFunctionAdapter.h
@@ -16,6 +16,7 @@
 #error no need to expose this header to Swig
 #endif
 
+#ifndef USER_API
 #ifndef BORNAGAIN_FIT_ADAPTER_OBJECTIVEFUNCTIONADAPTER_H
 #define BORNAGAIN_FIT_ADAPTER_OBJECTIVEFUNCTIONADAPTER_H
 
@@ -53,3 +54,4 @@ private:
 } // namespace mumufit
 
 #endif // BORNAGAIN_FIT_ADAPTER_OBJECTIVEFUNCTIONADAPTER_H
+#endif // USER_API
diff --git a/Fit/Adapter/Report.h b/Fit/Adapter/Report.h
index e00130bf7f8a6d2e319567d8d8901f82537ddaa9..2097fc56cc6542657d0f72d7fc2ba4a691caeb12 100644
--- a/Fit/Adapter/Report.h
+++ b/Fit/Adapter/Report.h
@@ -16,6 +16,7 @@
 #error no need to expose this header to Swig
 #endif
 
+#ifndef USER_API
 #ifndef BORNAGAIN_FIT_ADAPTER_REPORT_H
 #define BORNAGAIN_FIT_ADAPTER_REPORT_H
 
@@ -33,3 +34,4 @@ std::string reportToString(const MinimizerAdapter& minimizer);
 }; // namespace mumufit::internal
 
 #endif // BORNAGAIN_FIT_ADAPTER_REPORT_H
+#endif // USER_API
diff --git a/Fit/Adapter/ResidualFunctionAdapter.h b/Fit/Adapter/ResidualFunctionAdapter.h
index 6372d89bcf1510c1a8914d27d6383a571b3cd933..b2735f57ee8a47e5b064087963b8ddfbba59bb3a 100644
--- a/Fit/Adapter/ResidualFunctionAdapter.h
+++ b/Fit/Adapter/ResidualFunctionAdapter.h
@@ -16,6 +16,7 @@
 #error no need to expose this header to Swig
 #endif
 
+#ifndef USER_API
 #ifndef BORNAGAIN_FIT_ADAPTER_RESIDUALFUNCTIONADAPTER_H
 #define BORNAGAIN_FIT_ADAPTER_RESIDUALFUNCTIONADAPTER_H
 
@@ -61,3 +62,4 @@ private:
 } //  namespace mumufit
 
 #endif // BORNAGAIN_FIT_ADAPTER_RESIDUALFUNCTIONADAPTER_H
+#endif // USER_API
diff --git a/Fit/Adapter/RootResidualFunction.h b/Fit/Adapter/RootResidualFunction.h
index bdd9b646bb4a3d54d7b7dfc832ad7b4e8756c714..828becee6a13c345a726ac86a7ab32a169899e97 100644
--- a/Fit/Adapter/RootResidualFunction.h
+++ b/Fit/Adapter/RootResidualFunction.h
@@ -16,6 +16,7 @@
 #error no need to expose this header to Swig
 #endif
 
+#ifndef USER_API
 #ifndef BORNAGAIN_FIT_ADAPTER_ROOTRESIDUALFUNCTION_H
 #define BORNAGAIN_FIT_ADAPTER_ROOTRESIDUALFUNCTION_H
 
@@ -60,3 +61,4 @@ private:
 };
 
 #endif // BORNAGAIN_FIT_ADAPTER_ROOTRESIDUALFUNCTION_H
+#endif // USER_API
diff --git a/Fit/Adapter/RootScalarFunction.h b/Fit/Adapter/RootScalarFunction.h
index df593e1739529cc23aaeb80a1c903047c2a41761..b2dce86cc960f638ddb413a2749a2702f6702922 100644
--- a/Fit/Adapter/RootScalarFunction.h
+++ b/Fit/Adapter/RootScalarFunction.h
@@ -16,6 +16,7 @@
 #error no need to expose this header to Swig
 #endif
 
+#ifndef USER_API
 #ifndef BORNAGAIN_FIT_ADAPTER_ROOTSCALARFUNCTION_H
 #define BORNAGAIN_FIT_ADAPTER_ROOTSCALARFUNCTION_H
 
@@ -39,3 +40,4 @@ public:
 };
 
 #endif // BORNAGAIN_FIT_ADAPTER_ROOTSCALARFUNCTION_H
+#endif // USER_API
diff --git a/Fit/Adapter/ScalarFunctionAdapter.h b/Fit/Adapter/ScalarFunctionAdapter.h
index 18f0d55523eadac1eddcb3282409f2f9f41bd929..7b08704545beab25daf0a4656f49da78b2d5c5cb 100644
--- a/Fit/Adapter/ScalarFunctionAdapter.h
+++ b/Fit/Adapter/ScalarFunctionAdapter.h
@@ -16,6 +16,7 @@
 #error no need to expose this header to Swig
 #endif
 
+#ifndef USER_API
 #ifndef BORNAGAIN_FIT_ADAPTER_SCALARFUNCTIONADAPTER_H
 #define BORNAGAIN_FIT_ADAPTER_SCALARFUNCTIONADAPTER_H
 
@@ -51,3 +52,4 @@ private:
 } //  namespace mumufit
 
 #endif // BORNAGAIN_FIT_ADAPTER_SCALARFUNCTIONADAPTER_H
+#endif // USER_API
diff --git a/Fit/Adapter/SimAnMinimizer.h b/Fit/Adapter/SimAnMinimizer.h
index 8e88432c366c457653649326bfe27b7908bd14e9..2fdd0c2b40f715bd25650a2f2d8136fe406d756d 100644
--- a/Fit/Adapter/SimAnMinimizer.h
+++ b/Fit/Adapter/SimAnMinimizer.h
@@ -16,6 +16,7 @@
 #error no need to expose this header to Swig
 #endif
 
+#ifndef USER_API
 #ifndef BORNAGAIN_FIT_ADAPTER_SIMANMINIMIZER_H
 #define BORNAGAIN_FIT_ADAPTER_SIMANMINIMIZER_H
 
@@ -77,3 +78,4 @@ private:
 };
 
 #endif // BORNAGAIN_FIT_ADAPTER_SIMANMINIMIZER_H
+#endif // USER_API
diff --git a/Fit/Kernel/Kernel.h b/Fit/Kernel/Kernel.h
index 2a6cee927a80273432d2671d313e6fe27c2ac28a..808759b5feab9ce07047936814c1fc0f187b06de 100644
--- a/Fit/Kernel/Kernel.h
+++ b/Fit/Kernel/Kernel.h
@@ -16,6 +16,7 @@
 #error no need to expose this header to Swig
 #endif
 
+#ifndef USER_API
 #ifndef BORNAGAIN_FIT_KERNEL_KERNEL_H
 #define BORNAGAIN_FIT_KERNEL_KERNEL_H
 
@@ -57,3 +58,4 @@ private:
 } // namespace mumufit
 
 #endif // BORNAGAIN_FIT_KERNEL_KERNEL_H
+#endif // USER_API
diff --git a/Fit/Minimizer/IMinimizer.h b/Fit/Minimizer/IMinimizer.h
index a155e9f93a00e38a7229bbec61f770f72f3c3ea6..8c6e7f7bbc8ca5e0051ca2bdd5f26c85e6be9968 100644
--- a/Fit/Minimizer/IMinimizer.h
+++ b/Fit/Minimizer/IMinimizer.h
@@ -56,7 +56,7 @@ public:
 #ifndef SWIG
     //! Returns true if minimizer computations are residual-based, false otherwise
     virtual bool requiresResiduals() { return false; }
-#endif // SWIG
+#endif // USER_API
 };
 
 #endif // BORNAGAIN_FIT_MINIMIZER_IMINIMIZER_H
diff --git a/Fit/Minimizer/MinimizerInfo.h b/Fit/Minimizer/MinimizerInfo.h
index d86ef8d2be291180b6e286843c3df5788355812b..6cd5072aee8eec71afed736aec30f0e9d8bc16a2 100644
--- a/Fit/Minimizer/MinimizerInfo.h
+++ b/Fit/Minimizer/MinimizerInfo.h
@@ -16,6 +16,7 @@
 #error no need to expose this header to Swig
 #endif
 
+#ifndef USER_API
 #ifndef BORNAGAIN_FIT_MINIMIZER_MINIMIZERINFO_H
 #define BORNAGAIN_FIT_MINIMIZER_MINIMIZERINFO_H
 
@@ -77,3 +78,4 @@ private:
 };
 
 #endif // BORNAGAIN_FIT_MINIMIZER_MINIMIZERINFO_H
+#endif // USER_API
diff --git a/Fit/Minimizer/MinimizerOptions.h b/Fit/Minimizer/MinimizerOptions.h
index f0b6110f484c6850e16ded6a87dff3982cc8e690..d8dc88fcd4db6895188e81eb7e11f7369aa0fc6b 100644
--- a/Fit/Minimizer/MinimizerOptions.h
+++ b/Fit/Minimizer/MinimizerOptions.h
@@ -16,6 +16,7 @@
 #error no need to expose this header to Swig
 #endif
 
+#ifndef USER_API
 #ifndef BORNAGAIN_FIT_MINIMIZER_MINIMIZEROPTIONS_H
 #define BORNAGAIN_FIT_MINIMIZER_MINIMIZEROPTIONS_H
 
@@ -37,3 +38,4 @@ private:
 };
 
 #endif // BORNAGAIN_FIT_MINIMIZER_MINIMIZEROPTIONS_H
+#endif // USER_API
diff --git a/Fit/Minimizer/TestMinimizer.h b/Fit/Minimizer/TestMinimizer.h
index b0708efa6ad08444b87dc0f8b9a0e3c637736747..3bb59d547c85cf1d3d25ced73c7b54570a30c7b3 100644
--- a/Fit/Minimizer/TestMinimizer.h
+++ b/Fit/Minimizer/TestMinimizer.h
@@ -16,6 +16,7 @@
 #error no need to expose this header to Swig
 #endif
 
+#ifndef USER_API
 #ifndef BORNAGAIN_FIT_MINIMIZER_TESTMINIMIZER_H
 #define BORNAGAIN_FIT_MINIMIZER_TESTMINIMIZER_H
 
@@ -40,3 +41,4 @@ private:
 };
 
 #endif // BORNAGAIN_FIT_MINIMIZER_TESTMINIMIZER_H
+#endif // USER_API
diff --git a/Fit/Minimizer/Types.h b/Fit/Minimizer/Types.h
index 976532d54df71abacd9d4e54aacf2099ff705605..ea32497d1e9dad5e0e14b1e91a8d1892f044a48e 100644
--- a/Fit/Minimizer/Types.h
+++ b/Fit/Minimizer/Types.h
@@ -16,6 +16,7 @@
 #error no need to expose this header to Swig
 #endif
 
+#ifndef USER_API
 #ifndef BORNAGAIN_FIT_MINIMIZER_TYPES_H
 #define BORNAGAIN_FIT_MINIMIZER_TYPES_H
 
@@ -39,3 +40,4 @@ using fcn_scalar_t = std::function<double(const mumufit::Parameters&)>;
 using fcn_residual_t = std::function<std::vector<double>(const mumufit::Parameters&)>;
 
 #endif // BORNAGAIN_FIT_MINIMIZER_TYPES_H
+#endif // USER_API
diff --git a/Fit/Param/ParameterPlan.h b/Fit/Param/ParameterPlan.h
index 3e34cb54a5bd646c049e8aef654739353d025950..d472f5dfbea4baf28fbdd75d8b27ded8f2b89907 100644
--- a/Fit/Param/ParameterPlan.h
+++ b/Fit/Param/ParameterPlan.h
@@ -16,6 +16,7 @@
 #error no need to expose this header to Swig
 #endif
 
+#ifndef USER_API
 #ifndef BORNAGAIN_FIT_PARAM_PARAMETERPLAN_H
 #define BORNAGAIN_FIT_PARAM_PARAMETERPLAN_H
 
@@ -42,3 +43,4 @@ private:
 };
 
 #endif // BORNAGAIN_FIT_PARAM_PARAMETERPLAN_H
+#endif // USER_API
diff --git a/Fit/TestEngine/IFactory.h b/Fit/TestEngine/IFactory.h
index 673a4a0d7fde197fe403efd8bbed250c9a98ff94..834d908ffb3853e5ea88b4d193ffa2d744ae4abc 100644
--- a/Fit/TestEngine/IFactory.h
+++ b/Fit/TestEngine/IFactory.h
@@ -16,6 +16,7 @@
 #error no need to expose this header to Swig
 #endif
 
+#ifndef USER_API
 #ifndef BORNAGAIN_FIT_TESTENGINE_IFACTORY_H
 #define BORNAGAIN_FIT_TESTENGINE_IFACTORY_H
 
@@ -82,3 +83,4 @@ template <class T> T* create_new() {
 } // namespace mumufit::test
 
 #endif // BORNAGAIN_FIT_TESTENGINE_IFACTORY_H
+#endif // USER_API
diff --git a/Fit/TestEngine/MinimizerTestPlan.h b/Fit/TestEngine/MinimizerTestPlan.h
index 972ccb567aea35a2bc4cb6f6ba6e07213e25bbb4..bb4e937420ea7215f49dd76a723d18b5291f457d 100644
--- a/Fit/TestEngine/MinimizerTestPlan.h
+++ b/Fit/TestEngine/MinimizerTestPlan.h
@@ -16,6 +16,7 @@
 #error no need to expose this header to Swig
 #endif
 
+#ifndef USER_API
 #ifndef BORNAGAIN_FIT_TESTENGINE_MINIMIZERTESTPLAN_H
 #define BORNAGAIN_FIT_TESTENGINE_MINIMIZERTESTPLAN_H
 
@@ -55,3 +56,4 @@ protected:
 };
 
 #endif // BORNAGAIN_FIT_TESTENGINE_MINIMIZERTESTPLAN_H
+#endif // USER_API
diff --git a/Fit/Tools/MinimizerUtils.h b/Fit/Tools/MinimizerUtils.h
index 703b5474cda70a75623c558cd62383753af4cce7..77e3fbce263d0e6c3f600dc5470991db7f38fabf 100644
--- a/Fit/Tools/MinimizerUtils.h
+++ b/Fit/Tools/MinimizerUtils.h
@@ -16,6 +16,7 @@
 #error no need to expose this header to Swig
 #endif
 
+#ifndef USER_API
 #ifndef BORNAGAIN_FIT_TOOLS_MINIMIZERUTILS_H
 #define BORNAGAIN_FIT_TOOLS_MINIMIZERUTILS_H
 
@@ -40,3 +41,4 @@ std::string sectionString(const std::string& sectionName = "", size_t report_wid
 } // namespace mumufit::utils
 
 #endif // BORNAGAIN_FIT_TOOLS_MINIMIZERUTILS_H
+#endif // USER_API
diff --git a/Fit/Tools/MultiOption.h b/Fit/Tools/MultiOption.h
index b15dc55a1206f3debfca0e18addd136d7012ec10..67d34d9db3c82ab74a9d3ba0a38218d6bfd17653 100644
--- a/Fit/Tools/MultiOption.h
+++ b/Fit/Tools/MultiOption.h
@@ -16,6 +16,7 @@
 #error no need to expose this header to Swig
 #endif
 
+#ifndef USER_API
 #ifndef BORNAGAIN_FIT_TOOLS_MULTIOPTION_H
 #define BORNAGAIN_FIT_TOOLS_MULTIOPTION_H
 
@@ -75,3 +76,4 @@ template <typename T> T MultiOption::getDefault() const {
 }
 
 #endif // BORNAGAIN_FIT_TOOLS_MULTIOPTION_H
+#endif // USER_API
diff --git a/Fit/Tools/OptionContainer.h b/Fit/Tools/OptionContainer.h
index f279bc0a1bb3ea8b531da87979be585b7720350a..106e6655fc486e378a92ec23e0bb04593fd22402 100644
--- a/Fit/Tools/OptionContainer.h
+++ b/Fit/Tools/OptionContainer.h
@@ -16,6 +16,7 @@
 #error no need to expose this header to Swig
 #endif
 
+#ifndef USER_API
 #ifndef BORNAGAIN_FIT_TOOLS_OPTIONCONTAINER_H
 #define BORNAGAIN_FIT_TOOLS_OPTIONCONTAINER_H
 
@@ -91,3 +92,4 @@ template <class T> void OptionContainer::setOptionValue(const std::string& optio
 }
 
 #endif // BORNAGAIN_FIT_TOOLS_OPTIONCONTAINER_H
+#endif // USER_API
diff --git a/Fit/Tools/StringUtils.h b/Fit/Tools/StringUtils.h
index 18212851c31479f89e2f4162cde067c3db221903..20ed0514e082f9de2b7b424af0070980fd8c6ce8 100644
--- a/Fit/Tools/StringUtils.h
+++ b/Fit/Tools/StringUtils.h
@@ -16,6 +16,7 @@
 #error no need to expose this header to Swig
 #endif
 
+#ifndef USER_API
 #ifndef BORNAGAIN_FIT_TOOLS_STRINGUTILS_H
 #define BORNAGAIN_FIT_TOOLS_STRINGUTILS_H
 
@@ -46,3 +47,4 @@ template <typename T> std::string scientific(const T value, int n) {
 } // namespace mumufit::stringUtils
 
 #endif // BORNAGAIN_FIT_TOOLS_STRINGUTILS_H
+#endif // USER_API
diff --git a/Fit/Tools/WallclockTimer.h b/Fit/Tools/WallclockTimer.h
index d8625e4bad2000b0348bb55b2e93076ca5822608..82327c5d43f0917d0b3d3396829a51bd9403cd04 100644
--- a/Fit/Tools/WallclockTimer.h
+++ b/Fit/Tools/WallclockTimer.h
@@ -16,6 +16,7 @@
 #error no need to expose this header to Swig
 #endif
 
+#ifndef USER_API
 #ifndef BORNAGAIN_FIT_TOOLS_WALLCLOCKTIMER_H
 #define BORNAGAIN_FIT_TOOLS_WALLCLOCKTIMER_H
 
@@ -41,3 +42,4 @@ private:
 };
 
 #endif // BORNAGAIN_FIT_TOOLS_WALLCLOCKTIMER_H
+#endif // USER_API
diff --git a/GUI/coregui/Models/ApplicationModels.cpp b/GUI/coregui/Models/ApplicationModels.cpp
index bdeb6cef3e39b5164ca2ad226b8691cf13683192..d73fc6ccf43277210d5f2e26d798198a36b4e549 100644
--- a/GUI/coregui/Models/ApplicationModels.cpp
+++ b/GUI/coregui/Models/ApplicationModels.cpp
@@ -13,7 +13,7 @@
 //  ************************************************************************************************
 
 #include "GUI/coregui/Models/ApplicationModels.h"
-#include "Core/Simulation/OffSpecSimulation.h"
+#include "Core/Simulation/OffSpecularSimulation.h"
 #include "Core/Simulation/StandardSimulations.h"
 #include "Device/Histo/IntensityDataIOFactory.h"
 #include "GUI/coregui/Models/DocumentModel.h"
@@ -154,7 +154,7 @@ void ApplicationModels::createTestSample() {
     GUIObjectBuilder::populateSampleModel(m_sampleModel, m_materialModel, *P_sample);
 
     // to populate InstrumentView with predefined instrument
-    const std::unique_ptr<OffSpecSimulation> simulation(StandardSimulations::MiniOffSpec());
+    const std::unique_ptr<OffSpecularSimulation> simulation(StandardSimulations::MiniOffSpecular());
     GUIObjectBuilder::populateInstrumentModel(m_instrumentModel, *simulation);
 }
 
diff --git a/GUI/coregui/Models/DomainObjectBuilder.cpp b/GUI/coregui/Models/DomainObjectBuilder.cpp
index 36f137bcfc104d49872ca06c03741dd80d7fa638..b1c7025f0525aa92571b33932d88346d1ef631e6 100644
--- a/GUI/coregui/Models/DomainObjectBuilder.cpp
+++ b/GUI/coregui/Models/DomainObjectBuilder.cpp
@@ -139,9 +139,9 @@ DomainObjectBuilder::createUnitConverter(const InstrumentItem* instrumentItem) {
     if (instrumentItem->modelType() == "GISASInstrument")
         return UnitConverterUtils::createConverterForGISAS(*instrument);
 
-    if (instrumentItem->modelType() == "OffSpecInstrument") {
+    if (instrumentItem->modelType() == "OffSpecularInstrument") {
         auto axis_item = dynamic_cast<BasicAxisItem*>(
-            instrumentItem->getItem(OffSpecInstrumentItem::P_ALPHA_AXIS));
+            instrumentItem->getItem(OffSpecularInstrumentItem::P_ALPHA_AXIS));
         const auto detector2d = dynamic_cast<const IDetector2D*>(instrument->getDetector());
         return std::make_unique<OffSpecularConverter>(*detector2d, instrument->beam(),
                                                       *axis_item->createAxis(Units::deg));
diff --git a/GUI/coregui/Models/DomainSimulationBuilder.cpp b/GUI/coregui/Models/DomainSimulationBuilder.cpp
index b544247e94ba4e0ff503150b63ecb4ab01625c64..4cd6c41a12dd8d0b8c412de6459cf6242aa7428c 100644
--- a/GUI/coregui/Models/DomainSimulationBuilder.cpp
+++ b/GUI/coregui/Models/DomainSimulationBuilder.cpp
@@ -18,7 +18,7 @@
 #include "Core/Scan/AngularSpecScan.h"
 #include "Core/Simulation/DepthProbeSimulation.h"
 #include "Core/Simulation/GISASSimulation.h"
-#include "Core/Simulation/OffSpecSimulation.h"
+#include "Core/Simulation/OffSpecularSimulation.h"
 #include "Core/Simulation/SpecularSimulation.h"
 #include "Device/Beam/IFootprintFactor.h"
 #include "GUI/coregui/Models/AxesItems.h"
@@ -40,10 +40,10 @@ std::unique_ptr<GISASSimulation> createGISASSimulation(std::unique_ptr<MultiLaye
                                                        const GISASInstrumentItem* gisasInstrument,
                                                        const SimulationOptionsItem* optionsItem);
 
-std::unique_ptr<OffSpecSimulation>
-createOffSpecSimulation(std::unique_ptr<MultiLayer> P_multilayer,
-                        const OffSpecInstrumentItem* offspecInstrument,
-                        const SimulationOptionsItem* optionsItem);
+std::unique_ptr<OffSpecularSimulation>
+createOffSpecularSimulation(std::unique_ptr<MultiLayer> P_multilayer,
+                            const OffSpecularInstrumentItem* offspecInstrument,
+                            const SimulationOptionsItem* optionsItem);
 
 std::unique_ptr<SpecularSimulation>
 createSpecularSimulation(std::unique_ptr<MultiLayer> P_multilayer,
@@ -71,8 +71,9 @@ DomainSimulationBuilder::createSimulation(const MultiLayerItem* sampleItem,
 
     if (auto gisasInstrument = dynamic_cast<const GISASInstrumentItem*>(instrumentItem))
         return createGISASSimulation(std::move(P_multilayer), gisasInstrument, optionsItem);
-    else if (auto offspecInstrument = dynamic_cast<const OffSpecInstrumentItem*>(instrumentItem))
-        return createOffSpecSimulation(std::move(P_multilayer), offspecInstrument, optionsItem);
+    else if (auto offspecInstrument =
+                 dynamic_cast<const OffSpecularInstrumentItem*>(instrumentItem))
+        return createOffSpecularSimulation(std::move(P_multilayer), offspecInstrument, optionsItem);
     else if (auto specular_instrument = dynamic_cast<const SpecularInstrumentItem*>(instrumentItem))
         return createSpecularSimulation(std::move(P_multilayer), specular_instrument, optionsItem);
     else if (auto penetrator = dynamic_cast<const DepthProbeInstrumentItem*>(instrumentItem))
@@ -107,18 +108,18 @@ std::unique_ptr<GISASSimulation> createGISASSimulation(std::unique_ptr<MultiLaye
     return ret;
 }
 
-std::unique_ptr<OffSpecSimulation>
-createOffSpecSimulation(std::unique_ptr<MultiLayer> P_multilayer,
-                        const OffSpecInstrumentItem* instrument,
-                        const SimulationOptionsItem* optionsItem) {
-    std::unique_ptr<OffSpecSimulation> ret(new OffSpecSimulation);
+std::unique_ptr<OffSpecularSimulation>
+createOffSpecularSimulation(std::unique_ptr<MultiLayer> P_multilayer,
+                            const OffSpecularInstrumentItem* instrument,
+                            const SimulationOptionsItem* optionsItem) {
+    std::unique_ptr<OffSpecularSimulation> ret(new OffSpecularSimulation);
     auto P_instrument = DomainObjectBuilder::buildInstrument(*instrument);
     ret->setSample(*P_multilayer);
     ret->setInstrument(*P_instrument);
 
     auto beamItem = instrument->beamItem();
     auto axisItem =
-        dynamic_cast<BasicAxisItem*>(instrument->getItem(OffSpecInstrumentItem::P_ALPHA_AXIS));
+        dynamic_cast<BasicAxisItem*>(instrument->getItem(OffSpecularInstrumentItem::P_ALPHA_AXIS));
     ret->setBeamParameters(beamItem->wavelength(), *axisItem->createAxis(Units::deg),
                            beamItem->getAzimuthalAngle());
 
@@ -151,7 +152,7 @@ createSpecularSimulation(std::unique_ptr<MultiLayer> P_multilayer,
 
     TransformToDomain::addBeamDivergencesToScan(*beam_item, scan);
 
-    ret->setBeamIntensity(beam_item->intensity());
+    ret->beam().setIntensity(beam_item->intensity());
     ret->setScan(scan);
 
     // ISimulation options
diff --git a/GUI/coregui/Models/GUIObjectBuilder.cpp b/GUI/coregui/Models/GUIObjectBuilder.cpp
index 0a3f6efa458ea3b7d183da8674e5353e7d520f5b..3cc8ee09b416628643145caa7a43fa887692245b 100644
--- a/GUI/coregui/Models/GUIObjectBuilder.cpp
+++ b/GUI/coregui/Models/GUIObjectBuilder.cpp
@@ -15,7 +15,7 @@
 #include "GUI/coregui/Models/GUIObjectBuilder.h"
 #include "Base/Const/Units.h"
 #include "Core/Simulation/GISASSimulation.h"
-#include "Core/Simulation/OffSpecSimulation.h"
+#include "Core/Simulation/OffSpecularSimulation.h"
 #include "Core/Simulation/SpecularSimulation.h"
 #include "GUI/coregui/Models/DocumentModel.h"
 #include "GUI/coregui/Models/GUIDomainSampleVisitor.h"
@@ -32,9 +32,9 @@ GISASInstrumentItem* createGISASInstrumentItem(InstrumentModel* model,
                                                const GISASSimulation& simulation,
                                                const QString& name);
 
-OffSpecInstrumentItem* createOffSpecInstrumentItem(InstrumentModel* model,
-                                                   const OffSpecSimulation& simulation,
-                                                   const QString& name);
+OffSpecularInstrumentItem* createOffSpecularInstrumentItem(InstrumentModel* model,
+                                                           const OffSpecularSimulation& simulation,
+                                                           const QString& name);
 
 SpecularInstrumentItem* createSpecularInstrumentItem(InstrumentModel* model,
                                                      const SpecularSimulation& simulation,
@@ -69,8 +69,8 @@ SessionItem* GUIObjectBuilder::populateInstrumentModel(InstrumentModel* p_instru
 
     if (auto gisasSimulation = dynamic_cast<const GISASSimulation*>(&simulation)) {
         return createGISASInstrumentItem(p_instrument_model, *gisasSimulation, name);
-    } else if (auto offSpecSimulation = dynamic_cast<const OffSpecSimulation*>(&simulation)) {
-        return createOffSpecInstrumentItem(p_instrument_model, *offSpecSimulation, name);
+    } else if (auto offSpecSimulation = dynamic_cast<const OffSpecularSimulation*>(&simulation)) {
+        return createOffSpecularInstrumentItem(p_instrument_model, *offSpecSimulation, name);
     } else if (auto spec_simulation = dynamic_cast<const SpecularSimulation*>(&simulation)) {
         return createSpecularInstrumentItem(p_instrument_model, *spec_simulation, name);
     }
@@ -112,17 +112,18 @@ GISASInstrumentItem* createGISASInstrumentItem(InstrumentModel* model,
     return result;
 }
 
-OffSpecInstrumentItem* createOffSpecInstrumentItem(InstrumentModel* model,
-                                                   const OffSpecSimulation& simulation,
-                                                   const QString& name) {
-    auto result = dynamic_cast<OffSpecInstrumentItem*>(model->insertNewItem("OffSpecInstrument"));
+OffSpecularInstrumentItem* createOffSpecularInstrumentItem(InstrumentModel* model,
+                                                           const OffSpecularSimulation& simulation,
+                                                           const QString& name) {
+    auto result =
+        dynamic_cast<OffSpecularInstrumentItem*>(model->insertNewItem("OffSpecularInstrument"));
 
     result->setItemName(name);
-    TransformFromDomain::setOffSpecBeamItem(result->beamItem(), simulation);
+    TransformFromDomain::setOffSpecularBeamItem(result->beamItem(), simulation);
     TransformFromDomain::setDetector(result, simulation);
     TransformFromDomain::setBackground(result, simulation);
 
-    auto axisItem = result->getItem(OffSpecInstrumentItem::P_ALPHA_AXIS);
+    auto axisItem = result->getItem(OffSpecularInstrumentItem::P_ALPHA_AXIS);
     TransformFromDomain::setAxisItem(axisItem, *simulation.beamAxis(), 1. / Units::deg);
 
     return result;
diff --git a/GUI/coregui/Models/InstrumentItems.cpp b/GUI/coregui/Models/InstrumentItems.cpp
index d4c2843a51a91319b7dde1570d27236c5f46b013..defb6a826851925ab75287a2e63d597b8d8e5775 100644
--- a/GUI/coregui/Models/InstrumentItems.cpp
+++ b/GUI/coregui/Models/InstrumentItems.cpp
@@ -30,7 +30,8 @@
 
 namespace {
 const QString background_group_label = "Type";
-const QStringList instrument_names{"GISASInstrument", "OffSpecInstrument", "SpecularInstrument"};
+const QStringList instrument_names{"GISASInstrument", "OffSpecularInstrument",
+                                   "SpecularInstrument"};
 void addAxisGroupProperty(SessionItem* parent, const QString& tag);
 } // namespace
 
@@ -219,9 +220,9 @@ void GISASInstrumentItem::updateToRealData(const RealDataItem* item) {
     detectorItem()->setYSize(data_shape[1]);
 }
 
-const QString OffSpecInstrumentItem::P_ALPHA_AXIS = "Alpha axis";
+const QString OffSpecularInstrumentItem::P_ALPHA_AXIS = "Alpha axis";
 
-OffSpecInstrumentItem::OffSpecInstrumentItem() : Instrument2DItem("OffSpecInstrument") {
+OffSpecularInstrumentItem::OffSpecularInstrumentItem() : Instrument2DItem("OffSpecularInstrument") {
     addAxisGroupProperty(this, P_ALPHA_AXIS);
     auto inclination_item = getItem(P_ALPHA_AXIS)->getItem(BasicAxisItem::P_MIN_DEG);
     auto beam_item = beamItem();
@@ -232,21 +233,21 @@ OffSpecInstrumentItem::OffSpecInstrumentItem() : Instrument2DItem("OffSpecInstru
     });
 }
 
-std::vector<int> OffSpecInstrumentItem::shape() const {
+std::vector<int> OffSpecularInstrumentItem::shape() const {
     const int x_size = getItem(P_ALPHA_AXIS)->getItemValue(BasicAxisItem::P_NBINS).toInt();
     auto detector_item = detectorItem();
     return {x_size, detector_item->ySize()};
 }
 
-void OffSpecInstrumentItem::updateToRealData(const RealDataItem* item) {
+void OffSpecularInstrumentItem::updateToRealData(const RealDataItem* item) {
     if (!item)
         return;
 
     const auto data_shape = item->shape();
     if (shape().size() != data_shape.size())
-        throw GUIHelpers::Error("Error in OffSpecInstrumentItem::updateToRealData: The type of "
+        throw GUIHelpers::Error("Error in OffSpecularInstrumentItem::updateToRealData: The type of "
                                 "instrument is incompatible with passed data shape.");
-    getItem(OffSpecInstrumentItem::P_ALPHA_AXIS)
+    getItem(OffSpecularInstrumentItem::P_ALPHA_AXIS)
         ->setItemValue(BasicAxisItem::P_NBINS, data_shape[0]);
     detectorItem()->setYSize(data_shape[1]);
 }
diff --git a/GUI/coregui/Models/InstrumentItems.h b/GUI/coregui/Models/InstrumentItems.h
index 2356174e73f0e037fa445c534d89d4e9035c22da..92f369b213918ff0e68a4915021d44f36d0ebcbc 100644
--- a/GUI/coregui/Models/InstrumentItems.h
+++ b/GUI/coregui/Models/InstrumentItems.h
@@ -94,11 +94,11 @@ public:
     void updateToRealData(const RealDataItem* item) override;
 };
 
-class BA_CORE_API_ OffSpecInstrumentItem : public Instrument2DItem {
+class BA_CORE_API_ OffSpecularInstrumentItem : public Instrument2DItem {
 public:
     static const QString P_ALPHA_AXIS;
 
-    OffSpecInstrumentItem();
+    OffSpecularInstrumentItem();
     std::vector<int> shape() const override;
     void updateToRealData(const RealDataItem* item) override;
 };
diff --git a/GUI/coregui/Models/ItemCatalog.cpp b/GUI/coregui/Models/ItemCatalog.cpp
index 603146535ef3d0e7d99235ea83bba3033353985c..f57306e34d6a2acfa676e78faaff4403ba229eae 100644
--- a/GUI/coregui/Models/ItemCatalog.cpp
+++ b/GUI/coregui/Models/ItemCatalog.cpp
@@ -79,7 +79,7 @@ ItemCatalog::ItemCatalog() {
     add("InterferenceHardDisk", create_new<InterferenceFunctionHardDiskItem>);
     add("InterferenceRadialParaCrystal", create_new<InterferenceFunctionRadialParaCrystalItem>);
     add("GISASInstrument", create_new<GISASInstrumentItem>);
-    add("OffSpecInstrument", create_new<OffSpecInstrumentItem>);
+    add("OffSpecularInstrument", create_new<OffSpecularInstrumentItem>);
     add("SpecularInstrument", create_new<SpecularInstrumentItem>);
     add("GISASBeam", create_new<GISASBeamItem>);
     add("SpecularBeam", create_new<SpecularBeamItem>);
diff --git a/GUI/coregui/Models/JobItem.cpp b/GUI/coregui/Models/JobItem.cpp
index bc75abbc8b1bd8b89c685a630cdf8923c775a53d..78188a3362248e59f2629acc5e0fa0140d5896ae 100644
--- a/GUI/coregui/Models/JobItem.cpp
+++ b/GUI/coregui/Models/JobItem.cpp
@@ -73,7 +73,7 @@ JobItem::JobItem() : SessionItem("JobItem") {
     registerTag(T_MATERIAL_CONTAINER, 1, 1, QStringList{"MaterialContainer"});
     registerTag(T_INSTRUMENT, 1, 1,
                 QStringList() << "GISASInstrument"
-                              << "OffSpecInstrument"
+                              << "OffSpecularInstrument"
                               << "SpecularInstrument"
                               << "DepthProbeInstrument");
     registerTag(T_OUTPUT, 1, 1,
diff --git a/GUI/coregui/Models/JobModelFunctions.cpp b/GUI/coregui/Models/JobModelFunctions.cpp
index 079b42f5edaf6815b55757da42009c91d0ad6384..630940be8b8304fc6bb01fb1f3905169f7e38f7f 100644
--- a/GUI/coregui/Models/JobModelFunctions.cpp
+++ b/GUI/coregui/Models/JobModelFunctions.cpp
@@ -142,7 +142,7 @@ void JobModelFunctions::setupJobItemOutput(JobItem* jobItem) {
     if (instrumentType == "SpecularInstrument") {
         model->insertNewItem("SpecularData", model->indexOfItem(jobItem), -1, JobItem::T_OUTPUT);
 
-    } else if (instrumentType == "GISASInstrument" || instrumentType == "OffSpecInstrument"
+    } else if (instrumentType == "GISASInstrument" || instrumentType == "OffSpecularInstrument"
                || instrumentType == "DepthProbeInstrument") {
         model->insertNewItem("IntensityData", model->indexOfItem(jobItem), -1, JobItem::T_OUTPUT);
 
diff --git a/GUI/coregui/Models/RealDataItem.cpp b/GUI/coregui/Models/RealDataItem.cpp
index 71f3d6f0b0622f0ccacd4068afe618e646176484..65041518756918af10311a0db057643039597c63 100644
--- a/GUI/coregui/Models/RealDataItem.cpp
+++ b/GUI/coregui/Models/RealDataItem.cpp
@@ -97,8 +97,9 @@ void RealDataItem::setOutputData(OutputData<double>* data) {
     ASSERT(data && "Assertion failed in RealDataItem::setOutputData: passed data is nullptr");
     ASSERT(data->rank() < 3 && data->rank() > 0);
 
-    const QString& target_model_type =
-        data->rank() == 2 ? "IntensityData" : data->rank() == 1 ? "SpecularData" : "";
+    const QString& target_model_type = data->rank() == 2   ? "IntensityData"
+                                       : data->rank() == 1 ? "SpecularData"
+                                                           : "";
     auto data_item = getItem(T_INTENSITY_DATA);
     if (data_item && data_item->modelType() != target_model_type)
         throw GUIHelpers::Error("Error in RealDataItem::setOutputData: trying to set data "
diff --git a/GUI/coregui/Models/SessionDecorationModel.cpp b/GUI/coregui/Models/SessionDecorationModel.cpp
index 4efd79e2a1c9f66bf9ccbf0a99ee45f2f4bf1f71..18be6250a85629486242d97a3eefb27172d5399e 100644
--- a/GUI/coregui/Models/SessionDecorationModel.cpp
+++ b/GUI/coregui/Models/SessionDecorationModel.cpp
@@ -62,7 +62,7 @@ QVariant itemIcon(const SessionItem* item) {
     if (modelType == "GISASInstrument") {
         return QVariant(icons.gisasIcon);
 
-    } else if (modelType == "OffSpecInstrument") {
+    } else if (modelType == "OffSpecularInstrument") {
         return QVariant(icons.offspecIcon);
 
     } else if (modelType == "SpecularInstrument") {
diff --git a/GUI/coregui/Models/TransformFromDomain.cpp b/GUI/coregui/Models/TransformFromDomain.cpp
index c0d4d35552fc31a7ed79594dc335f8f4aa47a6a0..e74ed7f5ff79d3d17186178363be0e0a7a3e8c67 100644
--- a/GUI/coregui/Models/TransformFromDomain.cpp
+++ b/GUI/coregui/Models/TransformFromDomain.cpp
@@ -19,7 +19,7 @@
 #include "Core/Export/NodeProgeny.h"
 #include "Core/Scan/AngularSpecScan.h"
 #include "Core/Simulation/GISASSimulation.h"
-#include "Core/Simulation/OffSpecSimulation.h"
+#include "Core/Simulation/OffSpecularSimulation.h"
 #include "Core/Simulation/SpecularSimulation.h"
 #include "Device/Beam/FootprintGauss.h"
 #include "Device/Beam/FootprintSquare.h"
@@ -251,8 +251,8 @@ void TransformFromDomain::setGISASBeamItem(BeamItem* beam_item, const GISASSimul
     SetVectorItem(*beam_item, BeamItem::P_POLARIZATION, beam.getBlochVector());
 }
 
-void TransformFromDomain::setOffSpecBeamItem(BeamItem* beam_item,
-                                             const OffSpecSimulation& simulation) {
+void TransformFromDomain::setOffSpecularBeamItem(BeamItem* beam_item,
+                                                 const OffSpecularSimulation& simulation) {
     Beam beam = simulation.instrument().beam();
 
     beam_item->setIntensity(beam.intensity());
diff --git a/GUI/coregui/Models/TransformFromDomain.h b/GUI/coregui/Models/TransformFromDomain.h
index f7013f297fd0d7fd512d3b9f0aed5b6d9c8a05af..71e01aeb1b7bf547b4b064f5602d20f84679a02d 100644
--- a/GUI/coregui/Models/TransformFromDomain.h
+++ b/GUI/coregui/Models/TransformFromDomain.h
@@ -47,7 +47,7 @@ class GISASInstrumentItem;
 class Instrument2DItem;
 class InstrumentItem;
 class ISimulation2D;
-class OffSpecSimulation;
+class OffSpecularSimulation;
 class IAxis;
 
 namespace TransformFromDomain {
@@ -74,7 +74,7 @@ bool isValidRoughness(const LayerRoughness* roughness);
 
 void setGISASBeamItem(BeamItem* beam_item, const GISASSimulation& simulation);
 
-void setOffSpecBeamItem(BeamItem* beam_item, const OffSpecSimulation& simulation);
+void setOffSpecularBeamItem(BeamItem* beam_item, const OffSpecularSimulation& simulation);
 
 void setSpecularBeamItem(SpecularBeamItem* beam_item, const SpecularSimulation& simulation);
 
diff --git a/GUI/coregui/Views/InstrumentWidgets/InstrumentPresenter.cpp b/GUI/coregui/Views/InstrumentWidgets/InstrumentPresenter.cpp
index 1bc37d8cd46e03829924eca8ea9750c0ee2cc7df..4615b4bd1ada39c195c489f0319ffdb549fb995a 100644
--- a/GUI/coregui/Views/InstrumentWidgets/InstrumentPresenter.cpp
+++ b/GUI/coregui/Views/InstrumentWidgets/InstrumentPresenter.cpp
@@ -16,20 +16,20 @@
 #include "GUI/coregui/Models/SessionItem.h"
 #include "GUI/coregui/Views/InstrumentWidgets/DepthProbeInstrumentEditor.h"
 #include "GUI/coregui/Views/InstrumentWidgets/GISASInstrumentEditor.h"
-#include "GUI/coregui/Views/InstrumentWidgets/OffSpecInstrumentEditor.h"
+#include "GUI/coregui/Views/InstrumentWidgets/OffSpecularInstrumentEditor.h"
 #include "GUI/coregui/Views/InstrumentWidgets/SpecularInstrumentEditor.h"
 #include "GUI/coregui/utils/GUIHelpers.h"
 
 namespace {
 const QString GISASPresentation = "GISAS";
-const QString OffSpecPresentation = "OffSpec";
+const QString OffSpecularPresentation = "OffSpecular";
 const QString SpecularPresentation = "Specular";
 const QString DepthProbePresentation = "DepthProbe";
 } // namespace
 
 InstrumentPresenter::InstrumentPresenter(QWidget* parent) : ItemComboWidget(parent) {
     registerWidget(GISASPresentation, create_new<GISASInstrumentEditor>);
-    registerWidget(OffSpecPresentation, create_new<OffSpecInstrumentEditor>);
+    registerWidget(OffSpecularPresentation, create_new<OffSpecularInstrumentEditor>);
     registerWidget(SpecularPresentation, create_new<SpecularInstrumentEditor>);
     registerWidget(DepthProbePresentation, create_new<DepthProbeInstrumentEditor>);
     setToolBarVisible(false);
@@ -41,8 +41,8 @@ QString InstrumentPresenter::itemPresentation() const {
 
     if (currentItem()->modelType() == "GISASInstrument")
         return GISASPresentation;
-    else if (currentItem()->modelType() == "OffSpecInstrument")
-        return OffSpecPresentation;
+    else if (currentItem()->modelType() == "OffSpecularInstrument")
+        return OffSpecularPresentation;
     else if (currentItem()->modelType() == "SpecularInstrument")
         return SpecularPresentation;
     else if (currentItem()->modelType() == "DepthProbeInstrument")
@@ -55,6 +55,6 @@ QString InstrumentPresenter::itemPresentation() const {
 
 QStringList InstrumentPresenter::activePresentationList(SessionItem* item) {
     Q_UNUSED(item);
-    return QStringList() << GISASPresentation << OffSpecPresentation << SpecularPresentation
+    return QStringList() << GISASPresentation << OffSpecularPresentation << SpecularPresentation
                          << DepthProbePresentation;
 }
diff --git a/GUI/coregui/Views/InstrumentWidgets/InstrumentPresenter.h b/GUI/coregui/Views/InstrumentWidgets/InstrumentPresenter.h
index 885e5bbfe87fc1ea00545b6d21b6c73b779dac60..5c42ebc39b36cdf0beb2219b7d52ac7240805f72 100644
--- a/GUI/coregui/Views/InstrumentWidgets/InstrumentPresenter.h
+++ b/GUI/coregui/Views/InstrumentWidgets/InstrumentPresenter.h
@@ -18,7 +18,7 @@
 #include "GUI/coregui/Views/CommonWidgets/ItemComboWidget.h"
 
 //! Contains stack of instrument editors and the logic to show proper editor for certain type
-//! of instrument (GISAS, OffSpec and Specular). Main component of InstrumentEditorWidget.
+//! of instrument (GISAS, OffSpecular and Specular). Main component of InstrumentEditorWidget.
 
 class InstrumentPresenter : public ItemComboWidget {
     Q_OBJECT
diff --git a/GUI/coregui/Views/InstrumentWidgets/InstrumentViewActions.cpp b/GUI/coregui/Views/InstrumentWidgets/InstrumentViewActions.cpp
index 9a64d8040ec0bb6c0dba4311b11db3a696955052..613b203689946f599a9db4c714a189e5c15560e1 100644
--- a/GUI/coregui/Views/InstrumentWidgets/InstrumentViewActions.cpp
+++ b/GUI/coregui/Views/InstrumentWidgets/InstrumentViewActions.cpp
@@ -75,9 +75,9 @@ void InstrumentViewActions::onAddInstrument() {
     if (instrumentType == "GISASInstrument") {
         auto instrument = m_model->insertNewItem(instrumentType);
         instrument->setItemName(suggestInstrumentName("GISAS"));
-    } else if (instrumentType == "OffSpecInstrument") {
+    } else if (instrumentType == "OffSpecularInstrument") {
         auto instrument = m_model->insertNewItem(instrumentType);
-        instrument->setItemName(suggestInstrumentName("OffSpec"));
+        instrument->setItemName(suggestInstrumentName("OffSpecular"));
     } else if (instrumentType == "SpecularInstrument") {
         auto instrument = m_model->insertNewItem(instrumentType);
         instrument->setItemName(suggestInstrumentName("Specular"));
@@ -211,9 +211,9 @@ void InstrumentViewActions::initAddInstrumentMenu() {
     connect(action, &QAction::triggered, this, &InstrumentViewActions::onAddInstrument);
     m_addInstrumentMenu->setDefaultAction(action);
 
-    action = m_addInstrumentMenu->addAction("OffSpec");
-    action->setData(QVariant::fromValue(QString{"OffSpecInstrument"}));
-    action->setToolTip("Add OffSpec instrument with default settings");
+    action = m_addInstrumentMenu->addAction("OffSpecular");
+    action->setData(QVariant::fromValue(QString{"OffSpecularInstrument"}));
+    action->setToolTip("Add OffSpecular instrument with default settings");
     connect(action, &QAction::triggered, this, &InstrumentViewActions::onAddInstrument);
 
     action = m_addInstrumentMenu->addAction("Specular");
diff --git a/GUI/coregui/Views/InstrumentWidgets/OffSpecBeamEditor.cpp b/GUI/coregui/Views/InstrumentWidgets/OffSpecularBeamEditor.cpp
similarity index 77%
rename from GUI/coregui/Views/InstrumentWidgets/OffSpecBeamEditor.cpp
rename to GUI/coregui/Views/InstrumentWidgets/OffSpecularBeamEditor.cpp
index 3b310285a52c89186abf805b9aaac40883c9077d..942d0429ca64a818135a0199fbfe64279b5acb4e 100644
--- a/GUI/coregui/Views/InstrumentWidgets/OffSpecBeamEditor.cpp
+++ b/GUI/coregui/Views/InstrumentWidgets/OffSpecularBeamEditor.cpp
@@ -2,8 +2,8 @@
 //
 //  BornAgain: simulate and fit scattering at grazing incidence
 //
-//! @file      GUI/coregui/Views/InstrumentWidgets/OffSpecBeamEditor.cpp
-//! @brief     Implements class OffSpecBeamEditor
+//! @file      GUI/coregui/Views/InstrumentWidgets/OffSpecularBeamEditor.cpp
+//! @brief     Implements class OffSpecularBeamEditor
 //!
 //! @homepage  http://www.bornagainproject.org
 //! @license   GNU General Public License v3 or higher (see COPYING)
@@ -12,7 +12,7 @@
 //
 //  ************************************************************************************************
 
-#include "GUI/coregui/Views/InstrumentWidgets/OffSpecBeamEditor.h"
+#include "GUI/coregui/Views/InstrumentWidgets/OffSpecularBeamEditor.h"
 #include "GUI/coregui/Models/BeamDistributionItem.h"
 #include "GUI/coregui/Models/InstrumentItems.h"
 #include "GUI/coregui/Views/CommonWidgets/ColumnResizer.h"
@@ -28,7 +28,7 @@ const QString azimuthal_title("Azimuthal angle [deg]");
 const QString polarization_title("Polarization (Bloch vector)");
 } // namespace
 
-OffSpecBeamEditor::OffSpecBeamEditor(ColumnResizer* columnResizer, QWidget* parent)
+OffSpecularBeamEditor::OffSpecularBeamEditor(ColumnResizer* columnResizer, QWidget* parent)
     : SessionItemWidget(parent)
     , m_columnResizer(columnResizer)
     , m_intensityEditor(new ComponentEditor(ComponentEditor::PlainWidget))
@@ -47,48 +47,48 @@ OffSpecBeamEditor::OffSpecBeamEditor(ColumnResizer* columnResizer, QWidget* pare
     setLayout(mainLayout);
 
     connect(m_wavelengthEditor, &ComponentEditor::dialogRequest, this,
-            &OffSpecBeamEditor::onDialogRequest);
+            &OffSpecularBeamEditor::onDialogRequest);
     connect(m_inclinationEditor, &ComponentEditor::dialogRequest, this,
-            &OffSpecBeamEditor::onDialogRequest);
+            &OffSpecularBeamEditor::onDialogRequest);
     connect(m_azimuthalEditor, &ComponentEditor::dialogRequest, this,
-            &OffSpecBeamEditor::onDialogRequest);
+            &OffSpecularBeamEditor::onDialogRequest);
 
     m_columnResizer->addWidgetsFromGridLayout(m_gridLayout, 0);
     m_columnResizer->addWidgetsFromGridLayout(m_gridLayout, 1);
     m_columnResizer->addWidgetsFromGridLayout(m_gridLayout, 2);
 }
 
-void OffSpecBeamEditor::subscribeToItem() {
+void OffSpecularBeamEditor::subscribeToItem() {
     m_intensityEditor->setItem(beamItem()->getItem(BeamItem::P_INTENSITY));
 
     auto wavelengthItem = beamItem()->getItem(BeamItem::P_WAVELENGTH);
     m_wavelengthEditor->setItem(wavelengthItem->getItem(BeamDistributionItem::P_DISTRIBUTION));
 
-    auto inclinationItem = instrumentItem()->getItem(OffSpecInstrumentItem::P_ALPHA_AXIS);
+    auto inclinationItem = instrumentItem()->getItem(OffSpecularInstrumentItem::P_ALPHA_AXIS);
     m_inclinationEditor->setItem(inclinationItem);
 
     auto azimuthalItem = beamItem()->getItem(BeamItem::P_AZIMUTHAL_ANGLE);
     m_azimuthalEditor->setItem(azimuthalItem->getItem(BeamDistributionItem::P_DISTRIBUTION));
 }
 
-void OffSpecBeamEditor::unsubscribeFromItem() {
+void OffSpecularBeamEditor::unsubscribeFromItem() {
     m_intensityEditor->clearEditor();
     m_wavelengthEditor->clearEditor();
     m_inclinationEditor->clearEditor();
     m_azimuthalEditor->clearEditor();
 }
 
-OffSpecInstrumentItem* OffSpecBeamEditor::instrumentItem() {
-    auto result = dynamic_cast<OffSpecInstrumentItem*>(currentItem());
+OffSpecularInstrumentItem* OffSpecularBeamEditor::instrumentItem() {
+    auto result = dynamic_cast<OffSpecularInstrumentItem*>(currentItem());
     ASSERT(result);
     return result;
 }
 
-BeamItem* OffSpecBeamEditor::beamItem() {
+BeamItem* OffSpecularBeamEditor::beamItem() {
     return instrumentItem()->beamItem();
 }
 
-void OffSpecBeamEditor::onDialogRequest(SessionItem* item, const QString& name) {
+void OffSpecularBeamEditor::onDialogRequest(SessionItem* item, const QString& name) {
     if (!item)
         return;
 
diff --git a/GUI/coregui/Views/InstrumentWidgets/OffSpecBeamEditor.h b/GUI/coregui/Views/InstrumentWidgets/OffSpecularBeamEditor.h
similarity index 79%
rename from GUI/coregui/Views/InstrumentWidgets/OffSpecBeamEditor.h
rename to GUI/coregui/Views/InstrumentWidgets/OffSpecularBeamEditor.h
index 87d9c50a6bcc711f0e6c3a7adb81687e78cfe276..10f4ca6e4d346f669822bc60f0498245c360a51f 100644
--- a/GUI/coregui/Views/InstrumentWidgets/OffSpecBeamEditor.h
+++ b/GUI/coregui/Views/InstrumentWidgets/OffSpecularBeamEditor.h
@@ -2,8 +2,8 @@
 //
 //  BornAgain: simulate and fit scattering at grazing incidence
 //
-//! @file      GUI/coregui/Views/InstrumentWidgets/OffSpecBeamEditor.h
-//! @brief     Defines class OffSpecBeamEditor
+//! @file      GUI/coregui/Views/InstrumentWidgets/OffSpecularBeamEditor.h
+//! @brief     Defines class OffSpecularBeamEditor
 //!
 //! @homepage  http://www.bornagainproject.org
 //! @license   GNU General Public License v3 or higher (see COPYING)
@@ -19,24 +19,24 @@
 
 class ComponentEditor;
 class QGridLayout;
-class OffSpecInstrumentItem;
+class OffSpecularInstrumentItem;
 class BeamItem;
 class ColumnResizer;
 
 //! GISAS beam editor. Operates on GISASInstrumentItem.
 
-class OffSpecBeamEditor : public SessionItemWidget {
+class OffSpecularBeamEditor : public SessionItemWidget {
     Q_OBJECT
 
 public:
-    explicit OffSpecBeamEditor(ColumnResizer* columnResizer, QWidget* parent = nullptr);
+    explicit OffSpecularBeamEditor(ColumnResizer* columnResizer, QWidget* parent = nullptr);
 
 protected:
     void subscribeToItem();
     void unsubscribeFromItem();
 
 private:
-    OffSpecInstrumentItem* instrumentItem();
+    OffSpecularInstrumentItem* instrumentItem();
     BeamItem* beamItem();
     void onDialogRequest(SessionItem* item, const QString& name);
 
diff --git a/GUI/coregui/Views/InstrumentWidgets/OffSpecInstrumentEditor.cpp b/GUI/coregui/Views/InstrumentWidgets/OffSpecularInstrumentEditor.cpp
similarity index 74%
rename from GUI/coregui/Views/InstrumentWidgets/OffSpecInstrumentEditor.cpp
rename to GUI/coregui/Views/InstrumentWidgets/OffSpecularInstrumentEditor.cpp
index 5a83492af0c10b0848d78fadcaf9669440a8c4ca..0f11d05d0f7436796b482714f1f96b90af18f097 100644
--- a/GUI/coregui/Views/InstrumentWidgets/OffSpecInstrumentEditor.cpp
+++ b/GUI/coregui/Views/InstrumentWidgets/OffSpecularInstrumentEditor.cpp
@@ -2,8 +2,8 @@
 //
 //  BornAgain: simulate and fit scattering at grazing incidence
 //
-//! @file      GUI/coregui/Views/InstrumentWidgets/OffSpecInstrumentEditor.cpp
-//! @brief     Implements class OffSpecInstrumentEditor
+//! @file      GUI/coregui/Views/InstrumentWidgets/OffSpecularInstrumentEditor.cpp
+//! @brief     Implements class OffSpecularInstrumentEditor
 //!
 //! @homepage  http://www.bornagainproject.org
 //! @license   GNU General Public License v3 or higher (see COPYING)
@@ -12,20 +12,20 @@
 //
 //  ************************************************************************************************
 
-#include "GUI/coregui/Views/InstrumentWidgets/OffSpecInstrumentEditor.h"
+#include "GUI/coregui/Views/InstrumentWidgets/OffSpecularInstrumentEditor.h"
 #include "GUI/coregui/Models/InstrumentItems.h"
 #include "GUI/coregui/Views/CommonWidgets/ColumnResizer.h"
 #include "GUI/coregui/Views/InstrumentWidgets/EnvironmentEditor.h"
 #include "GUI/coregui/Views/InstrumentWidgets/GISASDetectorEditor.h"
-#include "GUI/coregui/Views/InstrumentWidgets/OffSpecBeamEditor.h"
+#include "GUI/coregui/Views/InstrumentWidgets/OffSpecularBeamEditor.h"
 #include "GUI/coregui/Views/InstrumentWidgets/PolarizationAnalysisEditor.h"
 #include "GUI/coregui/utils/StyleUtils.h"
 #include <QVBoxLayout>
 
-OffSpecInstrumentEditor::OffSpecInstrumentEditor(QWidget* parent)
+OffSpecularInstrumentEditor::OffSpecularInstrumentEditor(QWidget* parent)
     : SessionItemWidget(parent)
     , m_columnResizer(new ColumnResizer(this))
-    , m_beamEditor(new OffSpecBeamEditor(m_columnResizer))
+    , m_beamEditor(new OffSpecularBeamEditor(m_columnResizer))
     , m_detectorEditor(new GISASDetectorEditor)
     // temporary switched off to avoid memory leakage
     //, m_environmentEditor(new EnvironmentEditor(m_columnResizer))
@@ -41,15 +41,15 @@ OffSpecInstrumentEditor::OffSpecInstrumentEditor(QWidget* parent)
     setLayout(mainLayout);
 }
 
-void OffSpecInstrumentEditor::subscribeToItem() {
+void OffSpecularInstrumentEditor::subscribeToItem() {
     m_beamEditor->setItem(instrumentItem());
     m_detectorEditor->setItem(instrumentItem());
     //    m_environmentEditor->setItem(instrumentItem());
     //    m_polarizationAnalysisEditor->setItem(instrumentItem());
 }
 
-OffSpecInstrumentItem* OffSpecInstrumentEditor::instrumentItem() {
-    auto result = dynamic_cast<OffSpecInstrumentItem*>(currentItem());
+OffSpecularInstrumentItem* OffSpecularInstrumentEditor::instrumentItem() {
+    auto result = dynamic_cast<OffSpecularInstrumentItem*>(currentItem());
     ASSERT(result);
     return result;
 }
diff --git a/GUI/coregui/Views/InstrumentWidgets/OffSpecInstrumentEditor.h b/GUI/coregui/Views/InstrumentWidgets/OffSpecularInstrumentEditor.h
similarity index 74%
rename from GUI/coregui/Views/InstrumentWidgets/OffSpecInstrumentEditor.h
rename to GUI/coregui/Views/InstrumentWidgets/OffSpecularInstrumentEditor.h
index 18ccc5fd818a41c196423687aa8f923a30875b04..85c0bd451c784b367d6a70fdb1df92d08588347e 100644
--- a/GUI/coregui/Views/InstrumentWidgets/OffSpecInstrumentEditor.h
+++ b/GUI/coregui/Views/InstrumentWidgets/OffSpecularInstrumentEditor.h
@@ -2,8 +2,8 @@
 //
 //  BornAgain: simulate and fit scattering at grazing incidence
 //
-//! @file      GUI/coregui/Views/InstrumentWidgets/OffSpecInstrumentEditor.h
-//! @brief     Defines class OffSpecInstrumentEditor
+//! @file      GUI/coregui/Views/InstrumentWidgets/OffSpecularInstrumentEditor.h
+//! @brief     Defines class OffSpecularInstrumentEditor
 //!
 //! @homepage  http://www.bornagainproject.org
 //! @license   GNU General Public License v3 or higher (see COPYING)
@@ -17,26 +17,26 @@
 
 #include "GUI/coregui/Views/CommonWidgets/SessionItemWidget.h"
 
-class OffSpecInstrumentItem;
-class OffSpecBeamEditor;
+class OffSpecularInstrumentItem;
+class OffSpecularBeamEditor;
 class GISASDetectorEditor;
 class EnvironmentEditor;
 class PolarizationAnalysisEditor;
 class ColumnResizer;
 
-class OffSpecInstrumentEditor : public SessionItemWidget {
+class OffSpecularInstrumentEditor : public SessionItemWidget {
     Q_OBJECT
 
 public:
-    OffSpecInstrumentEditor(QWidget* parent = nullptr);
+    OffSpecularInstrumentEditor(QWidget* parent = nullptr);
 
 protected:
     void subscribeToItem();
 
 private:
-    OffSpecInstrumentItem* instrumentItem();
+    OffSpecularInstrumentItem* instrumentItem();
     ColumnResizer* m_columnResizer;
-    OffSpecBeamEditor* m_beamEditor;
+    OffSpecularBeamEditor* m_beamEditor;
     GISASDetectorEditor* m_detectorEditor;
     EnvironmentEditor* m_environmentEditor;
     PolarizationAnalysisEditor* m_polarizationAnalysisEditor;
diff --git a/GUI/coregui/Views/JobWidgets/JobResultsPresenter.cpp b/GUI/coregui/Views/JobWidgets/JobResultsPresenter.cpp
index 27e3a44b53c24e2217b8f6fd0f71f39994f3d84d..eef69b73a085066fd36fb0973b48d14d9d0f9ec5 100644
--- a/GUI/coregui/Views/JobWidgets/JobResultsPresenter.cpp
+++ b/GUI/coregui/Views/JobWidgets/JobResultsPresenter.cpp
@@ -28,13 +28,13 @@ const bool use_job_last_presentation = true;
 const std::map<QString, QString> instrument_to_default_presentaion{
     {"SpecularInstrument", "Reflectometry"},
     {"GISASInstrument", "Color Map"},
-    {"OffSpecInstrument", "Color Map"},
+    {"OffSpecularInstrument", "Color Map"},
     {"DepthProbeInstrument", "Color Map"}};
 
 const std::map<QString, QString> instrument_to_fit_presentaion{
     {"SpecularInstrument", "Fit 1D Data"},
     {"GISASInstrument", "Fit 2D Data"},
-    {"OffSpecInstrument", "Fit 2D Data"}};
+    {"OffSpecularInstrument", "Fit 2D Data"}};
 
 const std::map<JobViewFlags::EActivities, std::map<QString, QString>> activity_to_presentation{
     {JobViewFlags::FITTING_ACTIVITY, instrument_to_fit_presentaion},
@@ -44,7 +44,7 @@ const std::map<JobViewFlags::EActivities, std::map<QString, QString>> activity_t
 const std::map<QString, QStringList> default_active_presentation_list{
     {"SpecularInstrument", {"Reflectometry"}},
     {{"GISASInstrument"}, {"Color Map", "Projections"}},
-    {{"OffSpecInstrument"}, {"Color Map", "Projections"}},
+    {{"OffSpecularInstrument"}, {"Color Map", "Projections"}},
     {{"DepthProbeInstrument"}, {"Color Map", "Projections"}}};
 
 template <class QStringObj>
diff --git a/GUI/coregui/Views/PropertyEditor/PropertyEditorFactory.cpp b/GUI/coregui/Views/PropertyEditor/PropertyEditorFactory.cpp
index 68532ef8b35ea19d41cc9b0a3a9a32c39f9bc1c0..d32ee45e46cc6dda1a665d2c4e0ee0c972df7a94 100644
--- a/GUI/coregui/Views/PropertyEditor/PropertyEditorFactory.cpp
+++ b/GUI/coregui/Views/PropertyEditor/PropertyEditorFactory.cpp
@@ -82,9 +82,9 @@ QString PropertyEditorFactory::toString(const QModelIndex& index) {
         auto item = static_cast<SessionItem*>(index.internalPointer());
         return item->editorType() == "ScientificDouble"
                    ? QString::number(item->value().toDouble(), 'g')
-                   : item->editorType() == "ScientificSpinBox"
-                         ? ScientificSpinBox::toString(item->value().toDouble(), item->decimals())
-                         : QString::number(item->value().toDouble(), 'f', item->decimals());
+               : item->editorType() == "ScientificSpinBox"
+                   ? ScientificSpinBox::toString(item->value().toDouble(), item->decimals())
+                   : QString::number(item->value().toDouble(), 'f', item->decimals());
     }
 
     return "";
diff --git a/Param/Base/Unit.h b/Param/Base/Unit.h
index 26d46c39c2e7ea96c8e48cd5a36c8a6ff51feda4..84755a1f39901a379eb48c365d681813c1a87246 100644
--- a/Param/Base/Unit.h
+++ b/Param/Base/Unit.h
@@ -16,6 +16,7 @@
 #error no need to expose this header to Swig
 #endif
 
+#ifndef USER_API
 #ifndef BORNAGAIN_PARAM_BASE_UNIT_H
 #define BORNAGAIN_PARAM_BASE_UNIT_H
 
@@ -34,3 +35,4 @@ private:
 };
 
 #endif // BORNAGAIN_PARAM_BASE_UNIT_H
+#endif // USER_API
diff --git a/Param/Distrib/DistributionHandler.h b/Param/Distrib/DistributionHandler.h
index 064d990abd62f78c5768e86bcd6abf40642805d7..ed4b9c1740a1379b0bb8bab6d3bb7bf5f98d8b41 100644
--- a/Param/Distrib/DistributionHandler.h
+++ b/Param/Distrib/DistributionHandler.h
@@ -16,6 +16,7 @@
 #error no need to expose this header to Swig
 #endif
 
+#ifndef USER_API
 #ifndef BORNAGAIN_PARAM_DISTRIB_DISTRIBUTIONHANDLER_H
 #define BORNAGAIN_PARAM_DISTRIB_DISTRIBUTIONHANDLER_H
 
@@ -61,3 +62,4 @@ private:
 };
 
 #endif // BORNAGAIN_PARAM_DISTRIB_DISTRIBUTIONHANDLER_H
+#endif // USER_API
diff --git a/Param/Node/INodeVisitor.h b/Param/Node/INodeVisitor.h
index 2acf99b0819f038920b4944c476ca08eb0d8d68d..72146de4c769662439dfae95a22e31164e8dfb20 100644
--- a/Param/Node/INodeVisitor.h
+++ b/Param/Node/INodeVisitor.h
@@ -120,7 +120,7 @@ class LayerInterface;
 class LayerRoughness;
 class MesoCrystal;
 class MultiLayer;
-class OffSpecSimulation;
+class OffSpecularSimulation;
 class Particle;
 class ParticleComposition;
 class ParticleCoreShell;
@@ -252,7 +252,7 @@ public:
     virtual void visit(const LayerRoughness*) {}
     virtual void visit(const MesoCrystal*) {}
     virtual void visit(const MultiLayer*) {}
-    virtual void visit(const OffSpecSimulation*) {}
+    virtual void visit(const OffSpecularSimulation*) {}
     virtual void visit(const Particle*) {}
     virtual void visit(const ParticleComposition*) {}
     virtual void visit(const ParticleCoreShell*) {}
diff --git a/Param/Node/NodeUtils.h b/Param/Node/NodeUtils.h
index 578d8222f68b78ec88b32d234c6b6784229cba1d..0fb362d85fd77d2a9995c5506873a67e49f4ab10 100644
--- a/Param/Node/NodeUtils.h
+++ b/Param/Node/NodeUtils.h
@@ -16,6 +16,7 @@
 #error no need to expose this header to Swig
 #endif
 
+#ifndef USER_API
 #ifndef BORNAGAIN_PARAM_NODE_NODEUTILS_H
 #define BORNAGAIN_PARAM_NODE_NODEUTILS_H
 
@@ -39,3 +40,4 @@ std::string nodePath(const INode* node, const INode* root = nullptr);
 } // namespace NodeUtils
 
 #endif // BORNAGAIN_PARAM_NODE_NODEUTILS_H
+#endif // USER_API
diff --git a/Param/Varia/ParameterPattern.h b/Param/Varia/ParameterPattern.h
index 6bc7a0f4604adc8b03fdf9480945a8890009d558..801834ea1569791fbc5351f46d4762bafbf0dfa6 100644
--- a/Param/Varia/ParameterPattern.h
+++ b/Param/Varia/ParameterPattern.h
@@ -16,6 +16,7 @@
 #error no need to expose this header to Swig
 #endif
 
+#ifndef USER_API
 #ifndef BORNAGAIN_PARAM_VARIA_PARAMETERPATTERN_H
 #define BORNAGAIN_PARAM_VARIA_PARAMETERPATTERN_H
 
@@ -39,3 +40,4 @@ private:
 };
 
 #endif // BORNAGAIN_PARAM_VARIA_PARAMETERPATTERN_H
+#endif // USER_API
diff --git a/Param/Varia/ParameterUtils.h b/Param/Varia/ParameterUtils.h
index 994c483379c8916f492cddcb50896eb8884e6911..7fcb601f1209f5ec3883ff26055a9fcf8e8c4f66 100644
--- a/Param/Varia/ParameterUtils.h
+++ b/Param/Varia/ParameterUtils.h
@@ -16,6 +16,7 @@
 #error no need to expose this header to Swig
 #endif
 
+#ifndef USER_API
 #ifndef BORNAGAIN_PARAM_VARIA_PARAMETERUTILS_H
 #define BORNAGAIN_PARAM_VARIA_PARAMETERUTILS_H
 
@@ -34,3 +35,4 @@ std::string poolParameterUnits(const IParametricComponent& node, const std::stri
 } // namespace ParameterUtils
 
 #endif // BORNAGAIN_PARAM_VARIA_PARAMETERUTILS_H
+#endif // USER_API
diff --git a/Sample/Aggregate/InterferenceFunctions.h b/Sample/Aggregate/InterferenceFunctions.h
index afcf7003ccafaac822ff0612bc076d26944dcfc6..db1154e5656add363231bcde1f38ae08c88ff800 100644
--- a/Sample/Aggregate/InterferenceFunctions.h
+++ b/Sample/Aggregate/InterferenceFunctions.h
@@ -16,6 +16,7 @@
 #error no need to expose this header to Swig
 #endif
 
+#ifndef USER_API
 #ifndef BORNAGAIN_SAMPLE_AGGREGATE_INTERFERENCEFUNCTIONS_H
 #define BORNAGAIN_SAMPLE_AGGREGATE_INTERFERENCEFUNCTIONS_H
 
@@ -32,3 +33,4 @@
 #include "Sample/Aggregate/InterferenceFunctionTwin.h"
 
 #endif // BORNAGAIN_SAMPLE_AGGREGATE_INTERFERENCEFUNCTIONS_H
+#endif // USER_API
diff --git a/Sample/Correlations/IDistribution1DSampler.h b/Sample/Correlations/IDistribution1DSampler.h
index a1399a61a2e9898d3c99f06f8646b6fa6adea235..13a159e2b07b2e681182c026b1c11e63a3fd2594 100644
--- a/Sample/Correlations/IDistribution1DSampler.h
+++ b/Sample/Correlations/IDistribution1DSampler.h
@@ -16,6 +16,7 @@
 #error no need to expose this header to Swig
 #endif
 
+#ifndef USER_API
 #ifndef BORNAGAIN_SAMPLE_CORRELATIONS_IDISTRIBUTION1DSAMPLER_H
 #define BORNAGAIN_SAMPLE_CORRELATIONS_IDISTRIBUTION1DSAMPLER_H
 
@@ -73,3 +74,4 @@ private:
 };
 
 #endif // BORNAGAIN_SAMPLE_CORRELATIONS_IDISTRIBUTION1DSAMPLER_H
+#endif // USER_API
diff --git a/Sample/Correlations/IDistribution2DSampler.h b/Sample/Correlations/IDistribution2DSampler.h
index fda6cb305082ca28c9c2f09067475feaebe722a1..b164b83a863021eaeab5841faca848f5208c407c 100644
--- a/Sample/Correlations/IDistribution2DSampler.h
+++ b/Sample/Correlations/IDistribution2DSampler.h
@@ -16,6 +16,7 @@
 #error no need to expose this header to Swig
 #endif
 
+#ifndef USER_API
 #ifndef BORNAGAIN_SAMPLE_CORRELATIONS_IDISTRIBUTION2DSAMPLER_H
 #define BORNAGAIN_SAMPLE_CORRELATIONS_IDISTRIBUTION2DSAMPLER_H
 
@@ -70,3 +71,4 @@ private:
 };
 
 #endif // BORNAGAIN_SAMPLE_CORRELATIONS_IDISTRIBUTION2DSAMPLER_H
+#endif // USER_API
diff --git a/Sample/FFCompute/ComputeBA.h b/Sample/FFCompute/ComputeBA.h
index a246855534bcc92ac7b5f4a94ee9bf4d7a263cf0..cb4990d5c2531cce760144226bd41bccad29b642 100644
--- a/Sample/FFCompute/ComputeBA.h
+++ b/Sample/FFCompute/ComputeBA.h
@@ -16,6 +16,7 @@
 #error no need to expose this header to Swig
 #endif
 
+#ifndef USER_API
 #ifndef BORNAGAIN_SAMPLE_FFCOMPUTE_COMPUTEBA_H
 #define BORNAGAIN_SAMPLE_FFCOMPUTE_COMPUTEBA_H
 
@@ -38,3 +39,4 @@ public:
 };
 
 #endif // BORNAGAIN_SAMPLE_FFCOMPUTE_COMPUTEBA_H
+#endif // USER_API
diff --git a/Sample/FFCompute/ComputeBAPol.h b/Sample/FFCompute/ComputeBAPol.h
index a52901f5fdbc88a65bd3fe0370029de3b6eca661..5959afe03b2c5927ce22cc4f2ea92383baac4f9a 100644
--- a/Sample/FFCompute/ComputeBAPol.h
+++ b/Sample/FFCompute/ComputeBAPol.h
@@ -16,6 +16,7 @@
 #error no need to expose this header to Swig
 #endif
 
+#ifndef USER_API
 #ifndef BORNAGAIN_SAMPLE_FFCOMPUTE_COMPUTEBAPOL_H
 #define BORNAGAIN_SAMPLE_FFCOMPUTE_COMPUTEBAPOL_H
 
@@ -42,3 +43,4 @@ public:
 };
 
 #endif // BORNAGAIN_SAMPLE_FFCOMPUTE_COMPUTEBAPOL_H
+#endif // USER_API
diff --git a/Sample/FFCompute/ComputeDWBA.h b/Sample/FFCompute/ComputeDWBA.h
index 0ddd0acb335b4ec9cba8a2b0e5b7431dd50c32b0..9e3eb5b5a1477973593d8d604581f2d7fdb5d6b2 100644
--- a/Sample/FFCompute/ComputeDWBA.h
+++ b/Sample/FFCompute/ComputeDWBA.h
@@ -16,6 +16,7 @@
 #error no need to expose this header to Swig
 #endif
 
+#ifndef USER_API
 #ifndef BORNAGAIN_SAMPLE_FFCOMPUTE_COMPUTEDWBA_H
 #define BORNAGAIN_SAMPLE_FFCOMPUTE_COMPUTEDWBA_H
 
@@ -49,3 +50,4 @@ private:
 };
 
 #endif // BORNAGAIN_SAMPLE_FFCOMPUTE_COMPUTEDWBA_H
+#endif // USER_API
diff --git a/Sample/FFCompute/ComputeDWBAPol.cpp b/Sample/FFCompute/ComputeDWBAPol.cpp
index befc74c84a8f241da5e2b5b29dff37f8e4a0f346..58aa9707556591376618f005929991ef2e43896a 100644
--- a/Sample/FFCompute/ComputeDWBAPol.cpp
+++ b/Sample/FFCompute/ComputeDWBAPol.cpp
@@ -18,8 +18,8 @@
 #include "Sample/Scattering/IFormFactor.h"
 
 namespace {
-std::complex<double> VecMatVecProduct(const Eigen::Vector2cd& vec1, const Eigen::Matrix2cd& ff,
-                                      const Eigen::Vector2cd& vec2) {
+complex_t VecMatVecProduct(const Eigen::Vector2cd& vec1, const Eigen::Matrix2cd& ff,
+                           const Eigen::Vector2cd& vec2) {
     return vec1.transpose() * ff * vec2;
 }
 } // namespace
diff --git a/Sample/FFCompute/ComputeDWBAPol.h b/Sample/FFCompute/ComputeDWBAPol.h
index 4b8fb81427dd4042085a4d21813b80803410efe8..30587534a1aa030356a7be64115df47aba11a0fb 100644
--- a/Sample/FFCompute/ComputeDWBAPol.h
+++ b/Sample/FFCompute/ComputeDWBAPol.h
@@ -16,6 +16,7 @@
 #error no need to expose this header to Swig
 #endif
 
+#ifndef USER_API
 #ifndef BORNAGAIN_SAMPLE_FFCOMPUTE_COMPUTEDWBAPOL_H
 #define BORNAGAIN_SAMPLE_FFCOMPUTE_COMPUTEDWBAPOL_H
 
@@ -52,3 +53,4 @@ private:
 };
 
 #endif // BORNAGAIN_SAMPLE_FFCOMPUTE_COMPUTEDWBAPOL_H
+#endif // USER_API
diff --git a/Sample/FFCompute/IComputeFF.h b/Sample/FFCompute/IComputeFF.h
index d567ef99584fe1480e847886d56db383543c158f..bbd9d4761ccd26214fd63c182782b6bd8e6f27c0 100644
--- a/Sample/FFCompute/IComputeFF.h
+++ b/Sample/FFCompute/IComputeFF.h
@@ -16,6 +16,7 @@
 #error no need to expose this header to Swig
 #endif
 
+#ifndef USER_API
 #ifndef BORNAGAIN_SAMPLE_FFCOMPUTE_ICOMPUTEFF_H
 #define BORNAGAIN_SAMPLE_FFCOMPUTE_ICOMPUTEFF_H
 
@@ -64,3 +65,4 @@ protected:
 };
 
 #endif // BORNAGAIN_SAMPLE_FFCOMPUTE_ICOMPUTEFF_H
+#endif // USER_API
diff --git a/Sample/Fresnel/FormFactorCoherentPart.h b/Sample/Fresnel/FormFactorCoherentPart.h
index 717b76902d694193a6180aaf85352e7fcd83bf3d..64fd53b00b03d42ae85f95a326dcacb1399da3e9 100644
--- a/Sample/Fresnel/FormFactorCoherentPart.h
+++ b/Sample/Fresnel/FormFactorCoherentPart.h
@@ -16,6 +16,7 @@
 #error no need to expose this header to Swig
 #endif
 
+#ifndef USER_API
 #ifndef BORNAGAIN_SAMPLE_FRESNEL_FORMFACTORCOHERENTPART_H
 #define BORNAGAIN_SAMPLE_FRESNEL_FORMFACTORCOHERENTPART_H
 
@@ -54,3 +55,4 @@ private:
 };
 
 #endif // BORNAGAIN_SAMPLE_FRESNEL_FORMFACTORCOHERENTPART_H
+#endif // USER_API
diff --git a/Sample/Fresnel/FormFactorCoherentSum.h b/Sample/Fresnel/FormFactorCoherentSum.h
index 3edc468827f1c683709bbbe215e97c33c72583b4..a03847610728e0e7086c16a3aaaf535be560a250 100644
--- a/Sample/Fresnel/FormFactorCoherentSum.h
+++ b/Sample/Fresnel/FormFactorCoherentSum.h
@@ -16,6 +16,7 @@
 #error no need to expose this header to Swig
 #endif
 
+#ifndef USER_API
 #ifndef BORNAGAIN_SAMPLE_FRESNEL_FORMFACTORCOHERENTSUM_H
 #define BORNAGAIN_SAMPLE_FRESNEL_FORMFACTORCOHERENTSUM_H
 
@@ -50,3 +51,4 @@ private:
 };
 
 #endif // BORNAGAIN_SAMPLE_FRESNEL_FORMFACTORCOHERENTSUM_H
+#endif // USER_API
diff --git a/Sample/Fresnel/IFresnelMap.h b/Sample/Fresnel/IFresnelMap.h
index ab37382a759196d8f0fbe909953e641720f1816f..f14ccd6bd7e08f781e4bc7db73e44e38f734546a 100644
--- a/Sample/Fresnel/IFresnelMap.h
+++ b/Sample/Fresnel/IFresnelMap.h
@@ -16,6 +16,7 @@
 #error no need to expose this header to Swig
 #endif
 
+#ifndef USER_API
 #ifndef BORNAGAIN_SAMPLE_FRESNEL_IFRESNELMAP_H
 #define BORNAGAIN_SAMPLE_FRESNEL_IFRESNELMAP_H
 
@@ -63,3 +64,4 @@ protected:
 };
 
 #endif // BORNAGAIN_SAMPLE_FRESNEL_IFRESNELMAP_H
+#endif // USER_API
diff --git a/Sample/Fresnel/MatrixFresnelMap.h b/Sample/Fresnel/MatrixFresnelMap.h
index dadeaaa563c6ac2bbf58d44d293d7f19aed810ef..0e4c8310b8cc50de5156e9dc9885cfadd2c89a4c 100644
--- a/Sample/Fresnel/MatrixFresnelMap.h
+++ b/Sample/Fresnel/MatrixFresnelMap.h
@@ -16,6 +16,7 @@
 #error no need to expose this header to Swig
 #endif
 
+#ifndef USER_API
 #ifndef BORNAGAIN_SAMPLE_FRESNEL_MATRIXFRESNELMAP_H
 #define BORNAGAIN_SAMPLE_FRESNEL_MATRIXFRESNELMAP_H
 
@@ -71,3 +72,4 @@ private:
 };
 
 #endif // BORNAGAIN_SAMPLE_FRESNEL_MATRIXFRESNELMAP_H
+#endif // USER_API
diff --git a/Sample/Fresnel/ScalarFresnelMap.cpp b/Sample/Fresnel/ScalarFresnelMap.cpp
index 409ecbcf9409be9038efb04b1bd158e89e37c590..ea36b4137884c86e4d7f1bb1590f9047a29d9a45 100644
--- a/Sample/Fresnel/ScalarFresnelMap.cpp
+++ b/Sample/Fresnel/ScalarFresnelMap.cpp
@@ -22,8 +22,8 @@ ScalarFresnelMap::ScalarFresnelMap(std::unique_ptr<ISpecularStrategy> strategy)
 ScalarFresnelMap::~ScalarFresnelMap() = default;
 
 //! Returns hash value of a pair of doubles, computed by exclusive-or of the component hash values.
-size_t ScalarFresnelMap::Hash2Doubles::operator()(const std::pair<double, double>& doubles) const
-    noexcept {
+size_t ScalarFresnelMap::Hash2Doubles::operator()(
+    const std::pair<double, double>& doubles) const noexcept {
     return std::hash<double>{}(doubles.first) ^ std::hash<double>{}(doubles.second);
 }
 
diff --git a/Sample/Fresnel/ScalarFresnelMap.h b/Sample/Fresnel/ScalarFresnelMap.h
index 7a02e8a26339f80dc1850c40d81e2b8106a7dd4d..29a00b5161cc00f3caf52227660dc486de5635ef 100644
--- a/Sample/Fresnel/ScalarFresnelMap.h
+++ b/Sample/Fresnel/ScalarFresnelMap.h
@@ -16,6 +16,7 @@
 #error no need to expose this header to Swig
 #endif
 
+#ifndef USER_API
 #ifndef BORNAGAIN_SAMPLE_FRESNEL_SCALARFRESNELMAP_H
 #define BORNAGAIN_SAMPLE_FRESNEL_SCALARFRESNELMAP_H
 
@@ -59,3 +60,4 @@ private:
 };
 
 #endif // BORNAGAIN_SAMPLE_FRESNEL_SCALARFRESNELMAP_H
+#endif // USER_API
diff --git a/Sample/HardParticle/FormFactorBar.h b/Sample/HardParticle/FormFactorBar.h
index c4c0be554527a98a563461f1b3b97df3e480bf44..ebaaf11be6eea7f2ef85e3cdcab5510ed42c2548 100644
--- a/Sample/HardParticle/FormFactorBar.h
+++ b/Sample/HardParticle/FormFactorBar.h
@@ -16,6 +16,7 @@
 #error no need to expose this header to Swig
 #endif
 
+#ifndef USER_API
 #ifndef BORNAGAIN_SAMPLE_HARDPARTICLE_FORMFACTORBAR_H
 #define BORNAGAIN_SAMPLE_HARDPARTICLE_FORMFACTORBAR_H
 
@@ -48,3 +49,4 @@ private:
 };
 
 #endif // BORNAGAIN_SAMPLE_HARDPARTICLE_FORMFACTORBAR_H
+#endif // USER_API
diff --git a/Sample/HardParticle/HardParticles.h b/Sample/HardParticle/HardParticles.h
index 296fd4d3ecf26bfb8f5f159dff42f87776172a9d..c2844eacc17ca3fc503529063f4be0661e4559ff 100644
--- a/Sample/HardParticle/HardParticles.h
+++ b/Sample/HardParticle/HardParticles.h
@@ -16,6 +16,7 @@
 #error no need to expose this header to Swig
 #endif
 
+#ifndef USER_API
 #ifndef BORNAGAIN_SAMPLE_HARDPARTICLE_HARDPARTICLES_H
 #define BORNAGAIN_SAMPLE_HARDPARTICLE_HARDPARTICLES_H
 
@@ -47,3 +48,4 @@
 #include "Sample/HardParticle/FormFactorTruncatedSpheroid.h"
 
 #endif // BORNAGAIN_SAMPLE_HARDPARTICLE_HARDPARTICLES_H
+#endif // USER_API
diff --git a/Sample/HardParticle/PolyhedralComponents.h b/Sample/HardParticle/PolyhedralComponents.h
index 34b88c71bf2fe8910bcce9cd6f48a09cd5de6c15..d7ac4772b92caa1a472dd310c8cdb2898de2b8c5 100644
--- a/Sample/HardParticle/PolyhedralComponents.h
+++ b/Sample/HardParticle/PolyhedralComponents.h
@@ -16,6 +16,7 @@
 #error no need to expose this header to Swig
 #endif
 
+#ifndef USER_API
 #ifndef BORNAGAIN_SAMPLE_HARDPARTICLE_POLYHEDRALCOMPONENTS_H
 #define BORNAGAIN_SAMPLE_HARDPARTICLE_POLYHEDRALCOMPONENTS_H
 
@@ -83,3 +84,4 @@ private:
 };
 
 #endif // BORNAGAIN_SAMPLE_HARDPARTICLE_POLYHEDRALCOMPONENTS_H
+#endif // USER_API
diff --git a/Sample/HardParticle/PolyhedralTopology.h b/Sample/HardParticle/PolyhedralTopology.h
index 020efad91e8bbfead648cb46e73add449d53727e..29e79f206176ea2e1268526d7d9fc36e3b1ddf62 100644
--- a/Sample/HardParticle/PolyhedralTopology.h
+++ b/Sample/HardParticle/PolyhedralTopology.h
@@ -16,6 +16,7 @@
 #error no need to expose this header to Swig
 #endif
 
+#ifndef USER_API
 #ifndef BORNAGAIN_SAMPLE_HARDPARTICLE_POLYHEDRALTOPOLOGY_H
 #define BORNAGAIN_SAMPLE_HARDPARTICLE_POLYHEDRALTOPOLOGY_H
 
@@ -36,3 +37,4 @@ public:
 };
 
 #endif // BORNAGAIN_SAMPLE_HARDPARTICLE_POLYHEDRALTOPOLOGY_H
+#endif // USER_API
diff --git a/Sample/HardParticle/Polyhedron.h b/Sample/HardParticle/Polyhedron.h
index 443aadaaa2622b605962e7e47cda545fda5943bb..18d02a0a1b1e5937faa471ebe19f4089675f32ae 100644
--- a/Sample/HardParticle/Polyhedron.h
+++ b/Sample/HardParticle/Polyhedron.h
@@ -16,6 +16,7 @@
 #error no need to expose this header to Swig
 #endif
 
+#ifndef USER_API
 #ifndef BORNAGAIN_SAMPLE_HARDPARTICLE_POLYHEDRON_H
 #define BORNAGAIN_SAMPLE_HARDPARTICLE_POLYHEDRON_H
 
@@ -50,3 +51,4 @@ private:
 };
 
 #endif // BORNAGAIN_SAMPLE_HARDPARTICLE_POLYHEDRON_H
+#endif // USER_API
diff --git a/Sample/HardParticle/Prism.h b/Sample/HardParticle/Prism.h
index b2649933e8a6411e0225a1023820a1fa40f8cac1..8e1b3b6c7d043c4250ec83244c800f4af11a020b 100644
--- a/Sample/HardParticle/Prism.h
+++ b/Sample/HardParticle/Prism.h
@@ -16,6 +16,7 @@
 #error no need to expose this header to Swig
 #endif
 
+#ifndef USER_API
 #ifndef BORNAGAIN_SAMPLE_HARDPARTICLE_PRISM_H
 #define BORNAGAIN_SAMPLE_HARDPARTICLE_PRISM_H
 
@@ -39,3 +40,4 @@ private:
 };
 
 #endif // BORNAGAIN_SAMPLE_HARDPARTICLE_PRISM_H
+#endif // USER_API
diff --git a/Sample/HardParticle/Ripples.h b/Sample/HardParticle/Ripples.h
index e5e03553dc970b09c32a2cc2f7fe72e84682e99b..18b2f573ff7dce6d62d25b3fa99dec56a07cf367 100644
--- a/Sample/HardParticle/Ripples.h
+++ b/Sample/HardParticle/Ripples.h
@@ -16,6 +16,7 @@
 #error no need to expose this header to Swig
 #endif
 
+#ifndef USER_API
 #ifndef BORNAGAIN_SAMPLE_HARDPARTICLE_RIPPLES_H
 #define BORNAGAIN_SAMPLE_HARDPARTICLE_RIPPLES_H
 
@@ -36,3 +37,4 @@ complex_t profile_yz_triangular(complex_t qy, complex_t qz, double width, double
 } // namespace ripples
 
 #endif // BORNAGAIN_SAMPLE_HARDPARTICLE_RIPPLES_H
+#endif // USER_API
diff --git a/Sample/Interference/DecouplingApproximationStrategy.h b/Sample/Interference/DecouplingApproximationStrategy.h
index 8a33b35dbb224fba129e66abd2a0143ccf628c22..708e011900c77966c1754a3a1b9d73e4a6283655 100644
--- a/Sample/Interference/DecouplingApproximationStrategy.h
+++ b/Sample/Interference/DecouplingApproximationStrategy.h
@@ -16,6 +16,7 @@
 #error no need to expose this header to Swig
 #endif
 
+#ifndef USER_API
 #ifndef BORNAGAIN_SAMPLE_INTERFERENCE_DECOUPLINGAPPROXIMATIONSTRATEGY_H
 #define BORNAGAIN_SAMPLE_INTERFERENCE_DECOUPLINGAPPROXIMATIONSTRATEGY_H
 
@@ -41,3 +42,4 @@ private:
 };
 
 #endif // BORNAGAIN_SAMPLE_INTERFERENCE_DECOUPLINGAPPROXIMATIONSTRATEGY_H
+#endif // USER_API
diff --git a/Sample/Interference/FormFactorPrecompute.h b/Sample/Interference/FormFactorPrecompute.h
index f5cecc8e33e4082b89676fa2daf3547f7fc4d4d7..eba208bd6706b33cdcafe7304e277af303b8d052 100644
--- a/Sample/Interference/FormFactorPrecompute.h
+++ b/Sample/Interference/FormFactorPrecompute.h
@@ -16,6 +16,7 @@
 #error no need to expose this header to Swig
 #endif
 
+#ifndef USER_API
 #ifndef BORNAGAIN_SAMPLE_INTERFERENCE_FORMFACTORPRECOMPUTE_H
 #define BORNAGAIN_SAMPLE_INTERFERENCE_FORMFACTORPRECOMPUTE_H
 
@@ -37,3 +38,4 @@ matrixFFVector_t polarized(const SimulationElement& sim_element,
 } // namespace FormFactorPrecompute
 
 #endif // BORNAGAIN_SAMPLE_INTERFERENCE_FORMFACTORPRECOMPUTE_H
+#endif // USER_API
diff --git a/Sample/Interference/IInterferenceFunctionStrategy.h b/Sample/Interference/IInterferenceFunctionStrategy.h
index de52ab267513f4635bd2077d10114dfbc609a8ea..c911697a40e8279810653caf88e464a3b70ee40d 100644
--- a/Sample/Interference/IInterferenceFunctionStrategy.h
+++ b/Sample/Interference/IInterferenceFunctionStrategy.h
@@ -16,6 +16,7 @@
 #error no need to expose this header to Swig
 #endif
 
+#ifndef USER_API
 #ifndef BORNAGAIN_SAMPLE_INTERFERENCE_IINTERFERENCEFUNCTIONSTRATEGY_H
 #define BORNAGAIN_SAMPLE_INTERFERENCE_IINTERFERENCEFUNCTIONSTRATEGY_H
 
@@ -72,3 +73,4 @@ private:
 };
 
 #endif // BORNAGAIN_SAMPLE_INTERFERENCE_IINTERFERENCEFUNCTIONSTRATEGY_H
+#endif // USER_API
diff --git a/Sample/Interference/SSCApproximationStrategy.h b/Sample/Interference/SSCApproximationStrategy.h
index b3712a4a6f57d0cdc25e64c7f4a9dcf37f2eab0c..71c7d1f2f705bd9bdb07254dcd6b057dff1c1969 100644
--- a/Sample/Interference/SSCApproximationStrategy.h
+++ b/Sample/Interference/SSCApproximationStrategy.h
@@ -16,6 +16,7 @@
 #error no need to expose this header to Swig
 #endif
 
+#ifndef USER_API
 #ifndef BORNAGAIN_SAMPLE_INTERFERENCE_SSCAPPROXIMATIONSTRATEGY_H
 #define BORNAGAIN_SAMPLE_INTERFERENCE_SSCAPPROXIMATIONSTRATEGY_H
 
@@ -52,3 +53,4 @@ private:
 };
 
 #endif // BORNAGAIN_SAMPLE_INTERFERENCE_SSCAPPROXIMATIONSTRATEGY_H
+#endif // USER_API
diff --git a/Sample/Lattice/Lattice2D.h b/Sample/Lattice/Lattice2D.h
index 77a3685ecc98ba283ced69cb6882ab4b12d6feb3..6be45527ec4b292d099a25a137234066ee87aa25 100644
--- a/Sample/Lattice/Lattice2D.h
+++ b/Sample/Lattice/Lattice2D.h
@@ -18,6 +18,8 @@
 #include "Base/Types/ICloneable.h"
 #include "Param/Node/INode.h"
 
+//! A two-dimensional Bravais lattice.
+
 class Lattice2D : public ICloneable, public INode {
 public:
     Lattice2D(const NodeMeta& meta, const std::vector<double>& PValues);
@@ -46,6 +48,8 @@ protected:
     double m_xi;
 };
 
+//! A two-dimensional Bravais lattice with no special symmetry.
+
 class BasicLattice2D : public Lattice2D {
 public:
     BasicLattice2D(double length1, double length2, double angle, double xi);
@@ -64,6 +68,8 @@ private:
     double m_angle;
 };
 
+//! A two-dimensional Bravais lattice with square unit cell.
+
 class SquareLattice2D : public Lattice2D {
 public:
     SquareLattice2D(double length, double xi = 0.0);
@@ -81,6 +87,8 @@ private:
     double m_length;
 };
 
+//! A two-dimensional Bravais lattice with hexagonal symmetry.
+
 class HexagonalLattice2D : public Lattice2D {
 public:
     HexagonalLattice2D(double length, double xi);
diff --git a/Sample/LibFF/SomeFormFactors.h b/Sample/LibFF/SomeFormFactors.h
index d879af7f89a3f9fb430d94259fb0c666e05dcb25..80883678150f82bca459d637b7e080ec1f05d0db 100644
--- a/Sample/LibFF/SomeFormFactors.h
+++ b/Sample/LibFF/SomeFormFactors.h
@@ -16,6 +16,7 @@
 #error no need to expose this header to Swig
 #endif
 
+#ifndef USER_API
 #ifndef BORNAGAIN_SAMPLE_LIBFF_SOMEFORMFACTORS_H
 #define BORNAGAIN_SAMPLE_LIBFF_SOMEFORMFACTORS_H
 
@@ -31,3 +32,4 @@ complex_t ffSphere(cvector_t q, double R);
 } // namespace someff
 
 #endif // BORNAGAIN_SAMPLE_LIBFF_SOMEFORMFACTORS_H
+#endif // USER_API
diff --git a/Sample/Material/BaseMaterialImpl.h b/Sample/Material/BaseMaterialImpl.h
index b484af4e33366c110c47a449b51db528266c18bf..d3f17df05d27acff1311ecc38325e433628391f1 100644
--- a/Sample/Material/BaseMaterialImpl.h
+++ b/Sample/Material/BaseMaterialImpl.h
@@ -16,6 +16,7 @@
 #error no need to expose this header to Swig
 #endif
 
+#ifndef USER_API
 #ifndef BORNAGAIN_SAMPLE_MATERIAL_BASEMATERIALIMPL_H
 #define BORNAGAIN_SAMPLE_MATERIAL_BASEMATERIALIMPL_H
 
@@ -85,3 +86,4 @@ private:
 };
 
 #endif // BORNAGAIN_SAMPLE_MATERIAL_BASEMATERIALIMPL_H
+#endif // USER_API
diff --git a/Sample/Material/MagneticMaterialImpl.h b/Sample/Material/MagneticMaterialImpl.h
index a5a30613cedfc073c828c56b9ff69a4735e0a2ef..fceda02bb5286843d0d5700ed77512c20a44c111 100644
--- a/Sample/Material/MagneticMaterialImpl.h
+++ b/Sample/Material/MagneticMaterialImpl.h
@@ -16,6 +16,7 @@
 #error no need to expose this header to Swig
 #endif
 
+#ifndef USER_API
 #ifndef BORNAGAIN_SAMPLE_MATERIAL_MAGNETICMATERIALIMPL_H
 #define BORNAGAIN_SAMPLE_MATERIAL_MAGNETICMATERIALIMPL_H
 
@@ -63,3 +64,4 @@ private:
 };
 
 #endif // BORNAGAIN_SAMPLE_MATERIAL_MAGNETICMATERIALIMPL_H
+#endif // USER_API
diff --git a/Sample/Material/Material.h b/Sample/Material/Material.h
index 8ceb5ce52515f064cf6fc2d3fa1aef57c861d5a1..02a2192d72ee2f64140a5f829b4a7385e7ee76cb 100644
--- a/Sample/Material/Material.h
+++ b/Sample/Material/Material.h
@@ -31,17 +31,17 @@ public:
 #ifndef SWIG
     //! Creates material with particular material implementation
     Material(std::unique_ptr<BaseMaterialImpl> material_impl);
-#endif // SWIG
+#endif // USER_API
 
     Material(const Material& material);
 #ifndef SWIG
     Material(Material&& material) = default;
-#endif // SWIG
+#endif // USER_API
 
     Material& operator=(const Material& other);
 #ifndef SWIG
     Material& operator=(Material&& other) = default;
-#endif // SWIG
+#endif // USER_API
 
     //! Constructs a material with inverted magnetization
     Material inverted() const;
@@ -64,7 +64,7 @@ public:
 #ifndef SWIG
     //! Returns the type of underlying material implementation
     MATERIAL_TYPES typeID() const;
-#endif // SWIG
+#endif // USER_API
 
     //! Get the magnetization (in A/m)
     kvector_t magnetization() const;
diff --git a/Sample/Material/MaterialBySLDImpl.h b/Sample/Material/MaterialBySLDImpl.h
index 95863ced0711d9d4942a20f70d6a0b1fe4788688..0d9b578b235d39dde3f750a641384740bc4263ff 100644
--- a/Sample/Material/MaterialBySLDImpl.h
+++ b/Sample/Material/MaterialBySLDImpl.h
@@ -16,6 +16,7 @@
 #error no need to expose this header to Swig
 #endif
 
+#ifndef USER_API
 #ifndef BORNAGAIN_SAMPLE_MATERIAL_MATERIALBYSLDIMPL_H
 #define BORNAGAIN_SAMPLE_MATERIAL_MATERIALBYSLDIMPL_H
 
@@ -67,3 +68,4 @@ private:
 };
 
 #endif // BORNAGAIN_SAMPLE_MATERIAL_MATERIALBYSLDIMPL_H
+#endif // USER_API
diff --git a/Sample/Material/MaterialUtils.h b/Sample/Material/MaterialUtils.h
index d8acb02edfb976bce328e8b05fd6e5b10cf2b1ac..7c44d51e818f9e4fae6081193386f348bd69a727 100644
--- a/Sample/Material/MaterialUtils.h
+++ b/Sample/Material/MaterialUtils.h
@@ -16,6 +16,7 @@
 #error no need to expose this header to Swig
 #endif
 
+#ifndef USER_API
 #ifndef BORNAGAIN_SAMPLE_MATERIAL_MATERIALUTILS_H
 #define BORNAGAIN_SAMPLE_MATERIAL_MATERIALUTILS_H
 
@@ -52,3 +53,4 @@ MATERIAL_TYPES checkMaterialTypes(const std::vector<const Material*>& materials)
 } // namespace MaterialUtils
 
 #endif // BORNAGAIN_SAMPLE_MATERIAL_MATERIALUTILS_H
+#endif // USER_API
diff --git a/Sample/Material/RefractiveMaterialImpl.h b/Sample/Material/RefractiveMaterialImpl.h
index 35912e0ff6dcc0ef4080a9f8b78effb0245a7bdb..950ea43e347ebb9b78af64154df15b008f4a915c 100644
--- a/Sample/Material/RefractiveMaterialImpl.h
+++ b/Sample/Material/RefractiveMaterialImpl.h
@@ -16,6 +16,7 @@
 #error no need to expose this header to Swig
 #endif
 
+#ifndef USER_API
 #ifndef BORNAGAIN_SAMPLE_MATERIAL_REFRACTIVEMATERIALIMPL_H
 #define BORNAGAIN_SAMPLE_MATERIAL_REFRACTIVEMATERIALIMPL_H
 
@@ -70,3 +71,4 @@ private:
 };
 
 #endif // BORNAGAIN_SAMPLE_MATERIAL_REFRACTIVEMATERIALIMPL_H
+#endif // USER_API
diff --git a/Sample/Multilayer/Layer.h b/Sample/Multilayer/Layer.h
index 89a20a96a04f48a606999c7e3b48f5365ac2ad2d..1a53cabdff8685dd745a5a186dcbd30d5e57060c 100644
--- a/Sample/Multilayer/Layer.h
+++ b/Sample/Multilayer/Layer.h
@@ -21,7 +21,7 @@
 
 class ParticleLayout;
 
-//! A layer, with thickness (in nanometer) and material.
+//! A layer in a MultiLayer sample.
 //! @ingroup samples
 
 class Layer : public ISampleNode {
diff --git a/Sample/Multilayer/MultiLayerUtils.h b/Sample/Multilayer/MultiLayerUtils.h
index a637ae33d4563db3a66138c52d305c423e3cc338..40c9cd6d53310523c9c60c482cbe00012332a00f 100644
--- a/Sample/Multilayer/MultiLayerUtils.h
+++ b/Sample/Multilayer/MultiLayerUtils.h
@@ -16,6 +16,7 @@
 #error no need to expose this header to Swig
 #endif
 
+#ifndef USER_API
 #ifndef BORNAGAIN_SAMPLE_MULTILAYER_MULTILAYERUTILS_H
 #define BORNAGAIN_SAMPLE_MULTILAYER_MULTILAYERUTILS_H
 
@@ -42,3 +43,4 @@ bool hasRoughness(const MultiLayer& sample);
 } // namespace MultiLayerUtils
 
 #endif // BORNAGAIN_SAMPLE_MULTILAYER_MULTILAYERUTILS_H
+#endif // USER_API
diff --git a/Sample/Multilayer/PyImport.h b/Sample/Multilayer/PyImport.h
index 44d7040a75652077f6815ac58715f00365726cf7..6cca33d04bbf58e08a69330b93f5e1d90326d485 100644
--- a/Sample/Multilayer/PyImport.h
+++ b/Sample/Multilayer/PyImport.h
@@ -16,6 +16,7 @@
 #error no need to expose this header to Swig
 #endif
 
+#ifndef USER_API
 #ifndef BORNAGAIN_SAMPLE_MULTILAYER_PYIMPORT_H
 #define BORNAGAIN_SAMPLE_MULTILAYER_PYIMPORT_H
 
@@ -49,3 +50,4 @@ std::vector<std::string> listOfFunctions(const std::string& script, const std::s
 #endif // BORNAGAIN_PYTHON
 
 #endif // BORNAGAIN_SAMPLE_MULTILAYER_PYIMPORT_H
+#endif // USER_API
diff --git a/Sample/Particle/FormFactorCoreShell.h b/Sample/Particle/FormFactorCoreShell.h
index 0b6fdce882f2294b8e49f9ff5beacb7bdaad2bf5..1eea2a8e0c67d0eea7bf873ed44531670ff8ac29 100644
--- a/Sample/Particle/FormFactorCoreShell.h
+++ b/Sample/Particle/FormFactorCoreShell.h
@@ -16,6 +16,7 @@
 #error no need to expose this header to Swig
 #endif
 
+#ifndef USER_API
 #ifndef BORNAGAIN_SAMPLE_PARTICLE_FORMFACTORCORESHELL_H
 #define BORNAGAIN_SAMPLE_PARTICLE_FORMFACTORCORESHELL_H
 
@@ -59,3 +60,4 @@ protected:
 };
 
 #endif // BORNAGAIN_SAMPLE_PARTICLE_FORMFACTORCORESHELL_H
+#endif // USER_API
diff --git a/Sample/Particle/HomogeneousRegion.h b/Sample/Particle/HomogeneousRegion.h
index 0519b6c40aed59c54beedca9f4ec62396e9d256a..1fec82b22fdb4f81986a0d0646235317f81e9f34 100644
--- a/Sample/Particle/HomogeneousRegion.h
+++ b/Sample/Particle/HomogeneousRegion.h
@@ -16,6 +16,7 @@
 #error no need to expose this header to Swig
 #endif
 
+#ifndef USER_API
 #ifndef BORNAGAIN_SAMPLE_PARTICLE_HOMOGENEOUSREGION_H
 #define BORNAGAIN_SAMPLE_PARTICLE_HOMOGENEOUSREGION_H
 
@@ -42,6 +43,7 @@ struct HomogeneousRegion {
 Material createAveragedMaterial(const Material& layer_mat,
                                 const std::vector<HomogeneousRegion>& regions);
 
-#endif // SWIG
+#endif // USER_API
 
 #endif // BORNAGAIN_SAMPLE_PARTICLE_HOMOGENEOUSREGION_H
+#endif // USER_API
diff --git a/Sample/Particle/SlicedParticle.h b/Sample/Particle/SlicedParticle.h
index 3eba07be1fba65bac197c367087e6f1c28f10a2e..cc837b0e31cca30e81cf6ff671bf8d2bb950ff27 100644
--- a/Sample/Particle/SlicedParticle.h
+++ b/Sample/Particle/SlicedParticle.h
@@ -16,6 +16,7 @@
 #error no need to expose this header to Swig
 #endif
 
+#ifndef USER_API
 #ifndef BORNAGAIN_SAMPLE_PARTICLE_SLICEDPARTICLE_H
 #define BORNAGAIN_SAMPLE_PARTICLE_SLICEDPARTICLE_H
 
@@ -35,3 +36,4 @@ struct SlicedParticle {
 };
 
 #endif // BORNAGAIN_SAMPLE_PARTICLE_SLICEDPARTICLE_H
+#endif // USER_API
diff --git a/Sample/Particle/TRange.h b/Sample/Particle/TRange.h
index 613c23f6dc2c8605446a129bd628dcfe499d60ad..8f51fd7f5caa1013c5fed0c9776f07c745ebc3f8 100644
--- a/Sample/Particle/TRange.h
+++ b/Sample/Particle/TRange.h
@@ -16,6 +16,7 @@
 #error no need to expose this header to Swig
 #endif
 
+#ifndef USER_API
 #ifndef BORNAGAIN_SAMPLE_PARTICLE_TRANGE_H
 #define BORNAGAIN_SAMPLE_PARTICLE_TRANGE_H
 
@@ -53,3 +54,4 @@ private:
 };
 
 #endif // BORNAGAIN_SAMPLE_PARTICLE_TRANGE_H
+#endif // USER_API
diff --git a/Sample/Processed/MultiLayerFuncs.h b/Sample/Processed/MultiLayerFuncs.h
index 8aadfc55fd78ce7444353a5c31f57768ae8e96c1..002158acddf89d8c14bc3c79a868411a0bc8c3fd 100644
--- a/Sample/Processed/MultiLayerFuncs.h
+++ b/Sample/Processed/MultiLayerFuncs.h
@@ -12,6 +12,7 @@
 //
 //  ************************************************************************************************
 
+#ifndef USER_API
 #ifndef BORNAGAIN_SAMPLE_PROCESSED_MULTILAYERFUNCS_H
 #define BORNAGAIN_SAMPLE_PROCESSED_MULTILAYERFUNCS_H
 
@@ -38,3 +39,4 @@ std::pair<double, double> defaultMaterialProfileLimits(const MultiLayer& multila
 } // namespace swigAPI
 
 #endif // BORNAGAIN_SAMPLE_PROCESSED_MULTILAYERFUNCS_H
+#endif // USER_API
diff --git a/Sample/Processed/ProcessedLayout.h b/Sample/Processed/ProcessedLayout.h
index 38f6a0cfc4d367515ba7ead153c3e606af809ede..2a6a8580dc02f7fd4991a841e6ea37737adcfa53 100644
--- a/Sample/Processed/ProcessedLayout.h
+++ b/Sample/Processed/ProcessedLayout.h
@@ -16,6 +16,7 @@
 #error no need to expose this header to Swig
 #endif
 
+#ifndef USER_API
 #ifndef BORNAGAIN_SAMPLE_PROCESSED_PROCESSEDLAYOUT_H
 #define BORNAGAIN_SAMPLE_PROCESSED_PROCESSEDLAYOUT_H
 
@@ -67,3 +68,4 @@ private:
 };
 
 #endif // BORNAGAIN_SAMPLE_PROCESSED_PROCESSEDLAYOUT_H
+#endif // USER_API
diff --git a/Sample/Processed/ProcessedSample.h b/Sample/Processed/ProcessedSample.h
index 150dac0385740bb44541ec9f106c4061f6c82852..336037d452f82d3bc16be45580f390942603e3f2 100644
--- a/Sample/Processed/ProcessedSample.h
+++ b/Sample/Processed/ProcessedSample.h
@@ -16,6 +16,7 @@
 #error no need to expose this header to Swig
 #endif
 
+#ifndef USER_API
 #ifndef BORNAGAIN_SAMPLE_PROCESSED_PROCESSEDSAMPLE_H
 #define BORNAGAIN_SAMPLE_PROCESSED_PROCESSEDSAMPLE_H
 
@@ -82,3 +83,4 @@ private:
 };
 
 #endif // BORNAGAIN_SAMPLE_PROCESSED_PROCESSEDSAMPLE_H
+#endif // USER_API
diff --git a/Sample/Processed/ProfileHelper.h b/Sample/Processed/ProfileHelper.h
index bbeeea8d453cabf43931ca53f6dfad7cf2ec843f..bc0329396192271014f24423d8491ec59379484c 100644
--- a/Sample/Processed/ProfileHelper.h
+++ b/Sample/Processed/ProfileHelper.h
@@ -16,6 +16,7 @@
 #error no need to expose this header to Swig
 #endif
 
+#ifndef USER_API
 #ifndef BORNAGAIN_SAMPLE_PROCESSED_PROFILEHELPER_H
 #define BORNAGAIN_SAMPLE_PROCESSED_PROFILEHELPER_H
 
@@ -47,3 +48,4 @@ private:
 };
 
 #endif // BORNAGAIN_SAMPLE_PROCESSED_PROFILEHELPER_H
+#endif // USER_API
diff --git a/Sample/RT/ILayerRTCoefficients.h b/Sample/RT/ILayerRTCoefficients.h
index 647902aa57954cbfa90ab3de1d6984ecb66e3128..4bdea5e8de96a1ea3a3bc126644ae4688e6d36c5 100644
--- a/Sample/RT/ILayerRTCoefficients.h
+++ b/Sample/RT/ILayerRTCoefficients.h
@@ -16,6 +16,7 @@
 #error no need to expose this header to Swig
 #endif
 
+#ifndef USER_API
 #ifndef BORNAGAIN_SAMPLE_RT_ILAYERRTCOEFFICIENTS_H
 #define BORNAGAIN_SAMPLE_RT_ILAYERRTCOEFFICIENTS_H
 
@@ -66,3 +67,4 @@ public:
 };
 
 #endif // BORNAGAIN_SAMPLE_RT_ILAYERRTCOEFFICIENTS_H
+#endif // USER_API
diff --git a/Sample/RT/MatrixRTCoefficients.h b/Sample/RT/MatrixRTCoefficients.h
index b10fa8a895bab9abe8b70db5b7f254d22a60cc0f..e16063a0b633690f7d7319e6a7753e8ca2023569 100644
--- a/Sample/RT/MatrixRTCoefficients.h
+++ b/Sample/RT/MatrixRTCoefficients.h
@@ -16,6 +16,7 @@
 #error no need to expose this header to Swig
 #endif
 
+#ifndef USER_API
 #ifndef BORNAGAIN_SAMPLE_RT_MATRIXRTCOEFFICIENTS_H
 #define BORNAGAIN_SAMPLE_RT_MATRIXRTCOEFFICIENTS_H
 
@@ -79,3 +80,4 @@ private:
 };
 
 #endif // BORNAGAIN_SAMPLE_RT_MATRIXRTCOEFFICIENTS_H
+#endif // USER_API
diff --git a/Sample/RT/ScalarRTCoefficients.h b/Sample/RT/ScalarRTCoefficients.h
index f9eb38944357dc6b133004eb12fee1b2930d2c37..e21adc356d857363124ccbd7f844c5c1f8cea072 100644
--- a/Sample/RT/ScalarRTCoefficients.h
+++ b/Sample/RT/ScalarRTCoefficients.h
@@ -16,6 +16,7 @@
 #error no need to expose this header to Swig
 #endif
 
+#ifndef USER_API
 #ifndef BORNAGAIN_SAMPLE_RT_SCALARRTCOEFFICIENTS_H
 #define BORNAGAIN_SAMPLE_RT_SCALARRTCOEFFICIENTS_H
 
@@ -132,3 +133,4 @@ inline complex_t ScalarRTCoefficients::getScalarT() const {
 }
 
 #endif // BORNAGAIN_SAMPLE_RT_SCALARRTCOEFFICIENTS_H
+#endif // USER_API
diff --git a/Sample/SampleBuilderEngine/FixedBuilder.h b/Sample/SampleBuilderEngine/FixedBuilder.h
index b0b15b24d9136f2d2e33610599fe61ed9180715a..98ecdcec0b4c3325c5bd055b5e96267e52d40ccd 100644
--- a/Sample/SampleBuilderEngine/FixedBuilder.h
+++ b/Sample/SampleBuilderEngine/FixedBuilder.h
@@ -16,6 +16,7 @@
 #error no need to expose this header to Swig
 #endif
 
+#ifndef USER_API
 #ifndef BORNAGAIN_SAMPLE_SAMPLEBUILDERENGINE_FIXEDBUILDER_H
 #define BORNAGAIN_SAMPLE_SAMPLEBUILDERENGINE_FIXEDBUILDER_H
 
@@ -37,3 +38,4 @@ private:
 };
 
 #endif // BORNAGAIN_SAMPLE_SAMPLEBUILDERENGINE_FIXEDBUILDER_H
+#endif // USER_API
diff --git a/Sample/SampleBuilderEngine/IRegistry.h b/Sample/SampleBuilderEngine/IRegistry.h
index 1ebae261c838ff9f1785a8642e560833b0bb3273..6af06f60a7beacacfb7f287240e6fc38a6f8b4f2 100644
--- a/Sample/SampleBuilderEngine/IRegistry.h
+++ b/Sample/SampleBuilderEngine/IRegistry.h
@@ -16,6 +16,7 @@
 #error no need to expose this header to Swig
 #endif
 
+#ifndef USER_API
 #ifndef BORNAGAIN_SAMPLE_SAMPLEBUILDERENGINE_IREGISTRY_H
 #define BORNAGAIN_SAMPLE_SAMPLEBUILDERENGINE_IREGISTRY_H
 
@@ -59,3 +60,4 @@ private:
 };
 
 #endif // BORNAGAIN_SAMPLE_SAMPLEBUILDERENGINE_IREGISTRY_H
+#endif // USER_API
diff --git a/Sample/SampleBuilderEngine/SampleBuilderNode.h b/Sample/SampleBuilderEngine/SampleBuilderNode.h
index 0fb43532aa4eb539f20a73bff80fbec287009533..19f3efb35bd098aeff317bfb7e656fd0d751a262 100644
--- a/Sample/SampleBuilderEngine/SampleBuilderNode.h
+++ b/Sample/SampleBuilderEngine/SampleBuilderNode.h
@@ -16,6 +16,7 @@
 #error no need to expose this header to Swig
 #endif
 
+#ifndef USER_API
 #ifndef BORNAGAIN_SAMPLE_SAMPLEBUILDERENGINE_SAMPLEBUILDERNODE_H
 #define BORNAGAIN_SAMPLE_SAMPLEBUILDERENGINE_SAMPLEBUILDERNODE_H
 
@@ -53,3 +54,4 @@ private:
 };
 
 #endif // BORNAGAIN_SAMPLE_SAMPLEBUILDERENGINE_SAMPLEBUILDERNODE_H
+#endif // USER_API
diff --git a/Sample/SampleBuilderEngine/SampleComponents.h b/Sample/SampleBuilderEngine/SampleComponents.h
index 17f107bac148516ab242d7b486d1d57084a52a24..e1fa4f3c838dc8f5135066259d3c4649de93a1ee 100644
--- a/Sample/SampleBuilderEngine/SampleComponents.h
+++ b/Sample/SampleBuilderEngine/SampleComponents.h
@@ -16,6 +16,7 @@
 #error no need to expose this header to Swig
 #endif
 
+#ifndef USER_API
 #ifndef BORNAGAIN_SAMPLE_SAMPLEBUILDERENGINE_SAMPLECOMPONENTS_H
 #define BORNAGAIN_SAMPLE_SAMPLEBUILDERENGINE_SAMPLECOMPONENTS_H
 
@@ -39,3 +40,4 @@ public:
 };
 
 #endif // BORNAGAIN_SAMPLE_SAMPLEBUILDERENGINE_SAMPLECOMPONENTS_H
+#endif // USER_API
diff --git a/Sample/SampleBuilderEngine/SampleProvider.h b/Sample/SampleBuilderEngine/SampleProvider.h
index 8c0b67e904495842644f61237126523bca9eb497..6b66a4e033c4573e5f7ce80f39767f525065652b 100644
--- a/Sample/SampleBuilderEngine/SampleProvider.h
+++ b/Sample/SampleBuilderEngine/SampleProvider.h
@@ -16,6 +16,7 @@
 #error no need to expose this header to Swig
 #endif
 
+#ifndef USER_API
 #ifndef BORNAGAIN_SAMPLE_SAMPLEBUILDERENGINE_SAMPLEPROVIDER_H
 #define BORNAGAIN_SAMPLE_SAMPLEBUILDERENGINE_SAMPLEPROVIDER_H
 
@@ -55,3 +56,4 @@ private:
 };
 
 #endif // BORNAGAIN_SAMPLE_SAMPLEBUILDERENGINE_SAMPLEPROVIDER_H
+#endif // USER_API
diff --git a/Sample/Scattering/FormFactorDecoratorMaterial.h b/Sample/Scattering/FormFactorDecoratorMaterial.h
index a23a988d11d8381734282a1fe3fcc7f665efa0aa..81648cd6006785f406902163d67ef8732f934b40 100644
--- a/Sample/Scattering/FormFactorDecoratorMaterial.h
+++ b/Sample/Scattering/FormFactorDecoratorMaterial.h
@@ -16,6 +16,7 @@
 #error no need to expose this header to Swig
 #endif
 
+#ifndef USER_API
 #ifndef BORNAGAIN_SAMPLE_SCATTERING_FORMFACTORDECORATORMATERIAL_H
 #define BORNAGAIN_SAMPLE_SCATTERING_FORMFACTORDECORATORMATERIAL_H
 
@@ -57,3 +58,4 @@ private:
 };
 
 #endif // BORNAGAIN_SAMPLE_SCATTERING_FORMFACTORDECORATORMATERIAL_H
+#endif // USER_API
diff --git a/Sample/Scattering/FormFactorDecoratorPositionFactor.h b/Sample/Scattering/FormFactorDecoratorPositionFactor.h
index abe3c90e51fc195a714b8eda93c575e4bb5a55f4..a550afec31844feb4213b242dd7fe0f66414b927 100644
--- a/Sample/Scattering/FormFactorDecoratorPositionFactor.h
+++ b/Sample/Scattering/FormFactorDecoratorPositionFactor.h
@@ -16,6 +16,7 @@
 #error no need to expose this header to Swig
 #endif
 
+#ifndef USER_API
 #ifndef BORNAGAIN_SAMPLE_SCATTERING_FORMFACTORDECORATORPOSITIONFACTOR_H
 #define BORNAGAIN_SAMPLE_SCATTERING_FORMFACTORDECORATORPOSITIONFACTOR_H
 
@@ -50,3 +51,4 @@ private:
 };
 
 #endif // BORNAGAIN_SAMPLE_SCATTERING_FORMFACTORDECORATORPOSITIONFACTOR_H
+#endif // USER_API
diff --git a/Sample/Scattering/FormFactorDecoratorRotation.h b/Sample/Scattering/FormFactorDecoratorRotation.h
index 80fea1616bb0579a3c36965b12a7034889e9815c..102ec63a95c4c3d2302a5df3debb6e4fd358ebc1 100644
--- a/Sample/Scattering/FormFactorDecoratorRotation.h
+++ b/Sample/Scattering/FormFactorDecoratorRotation.h
@@ -16,6 +16,7 @@
 #error no need to expose this header to Swig
 #endif
 
+#ifndef USER_API
 #ifndef BORNAGAIN_SAMPLE_SCATTERING_FORMFACTORDECORATORROTATION_H
 #define BORNAGAIN_SAMPLE_SCATTERING_FORMFACTORDECORATORROTATION_H
 
@@ -52,3 +53,4 @@ private:
 };
 
 #endif // BORNAGAIN_SAMPLE_SCATTERING_FORMFACTORDECORATORROTATION_H
+#endif // USER_API
diff --git a/Sample/Scattering/LayerFillLimits.h b/Sample/Scattering/LayerFillLimits.h
index 39c7252dfaaabb10c3a681b9cb725a7857847080..308c74d60e64d21b7f1fb5011afd92b062bc4025 100644
--- a/Sample/Scattering/LayerFillLimits.h
+++ b/Sample/Scattering/LayerFillLimits.h
@@ -16,6 +16,7 @@
 #error no need to expose this header to Swig
 #endif
 
+#ifndef USER_API
 #ifndef BORNAGAIN_SAMPLE_SCATTERING_LAYERFILLLIMITS_H
 #define BORNAGAIN_SAMPLE_SCATTERING_LAYERFILLLIMITS_H
 
@@ -50,3 +51,4 @@ private:
 };
 
 #endif // BORNAGAIN_SAMPLE_SCATTERING_LAYERFILLLIMITS_H
+#endif // USER_API
diff --git a/Sample/Scattering/ZLimits.h b/Sample/Scattering/ZLimits.h
index 46f81f2f422e14d49efa65d6c9f12e65cef784e8..a77cb854de3efc121c676695529267506f9a2668 100644
--- a/Sample/Scattering/ZLimits.h
+++ b/Sample/Scattering/ZLimits.h
@@ -16,6 +16,7 @@
 #error no need to expose this header to Swig
 #endif
 
+#ifndef USER_API
 #ifndef BORNAGAIN_SAMPLE_SCATTERING_ZLIMITS_H
 #define BORNAGAIN_SAMPLE_SCATTERING_ZLIMITS_H
 
@@ -71,3 +72,4 @@ bool operator!=(const ZLimits& left, const ZLimits& right);
 std::ostream& operator<<(std::ostream& ostr, const ZLimits& limits);
 
 #endif // BORNAGAIN_SAMPLE_SCATTERING_ZLIMITS_H
+#endif // USER_API
diff --git a/Sample/Shapes/Box.h b/Sample/Shapes/Box.h
index e166bf89e9a6339377bbc80939366959121dea00..9fcdc287505bb6e5b8153632f29cb6bbbf698bed 100644
--- a/Sample/Shapes/Box.h
+++ b/Sample/Shapes/Box.h
@@ -16,6 +16,7 @@
 #error no need to expose this header to Swig
 #endif
 
+#ifndef USER_API
 #ifndef BORNAGAIN_SAMPLE_SHAPES_BOX_H
 #define BORNAGAIN_SAMPLE_SHAPES_BOX_H
 
@@ -28,3 +29,4 @@ public:
 };
 
 #endif // BORNAGAIN_SAMPLE_SHAPES_BOX_H
+#endif // USER_API
diff --git a/Sample/Shapes/DoubleEllipse.h b/Sample/Shapes/DoubleEllipse.h
index c616b6cfb97e67cdb0621c1eafe3ada23c469d3f..874d28be4ca197f0db896377d4e03833bc5ad2cf 100644
--- a/Sample/Shapes/DoubleEllipse.h
+++ b/Sample/Shapes/DoubleEllipse.h
@@ -16,6 +16,7 @@
 #error no need to expose this header to Swig
 #endif
 
+#ifndef USER_API
 #ifndef BORNAGAIN_SAMPLE_SHAPES_DOUBLEELLIPSE_H
 #define BORNAGAIN_SAMPLE_SHAPES_DOUBLEELLIPSE_H
 
@@ -28,3 +29,4 @@ public:
 };
 
 #endif // BORNAGAIN_SAMPLE_SHAPES_DOUBLEELLIPSE_H
+#endif // USER_API
diff --git a/Sample/Shapes/IShape.h b/Sample/Shapes/IShape.h
index 96d4c30b6ff8080b389323610ebfec5880eebaa2..75b747750b27f6e718c2c96afcf34fa5441e27f7 100644
--- a/Sample/Shapes/IShape.h
+++ b/Sample/Shapes/IShape.h
@@ -16,6 +16,7 @@
 #error no need to expose this header to Swig
 #endif
 
+#ifndef USER_API
 #ifndef BORNAGAIN_SAMPLE_SHAPES_ISHAPE_H
 #define BORNAGAIN_SAMPLE_SHAPES_ISHAPE_H
 
@@ -52,3 +53,4 @@ std::vector<kvector_t> RectangleVertices(double length, double width, double z);
 std::vector<kvector_t> EllipseVertices(double r_x, double r_y, double z);
 
 #endif // BORNAGAIN_SAMPLE_SHAPES_ISHAPE_H
+#endif // USER_API
diff --git a/Sample/Shapes/RippleCosine.h b/Sample/Shapes/RippleCosine.h
index cef9cdd584d9204da56f597e77f093ed9ed763b7..ce9356d44c9cdaef81dd06e620edf77243371564 100644
--- a/Sample/Shapes/RippleCosine.h
+++ b/Sample/Shapes/RippleCosine.h
@@ -16,6 +16,7 @@
 #error no need to expose this header to Swig
 #endif
 
+#ifndef USER_API
 #ifndef BORNAGAIN_SAMPLE_SHAPES_RIPPLECOSINE_H
 #define BORNAGAIN_SAMPLE_SHAPES_RIPPLECOSINE_H
 
@@ -28,3 +29,4 @@ public:
 };
 
 #endif // BORNAGAIN_SAMPLE_SHAPES_RIPPLECOSINE_H
+#endif // USER_API
diff --git a/Sample/Shapes/RippleSawtooth.h b/Sample/Shapes/RippleSawtooth.h
index 6e1c971c45d203d74f3a2d0f5637a04a8927f5ab..b9592b116bf27c958997362d5d97ff7bbe43d07a 100644
--- a/Sample/Shapes/RippleSawtooth.h
+++ b/Sample/Shapes/RippleSawtooth.h
@@ -16,6 +16,7 @@
 #error no need to expose this header to Swig
 #endif
 
+#ifndef USER_API
 #ifndef BORNAGAIN_SAMPLE_SHAPES_RIPPLESAWTOOTH_H
 #define BORNAGAIN_SAMPLE_SHAPES_RIPPLESAWTOOTH_H
 
@@ -28,3 +29,4 @@ public:
 };
 
 #endif // BORNAGAIN_SAMPLE_SHAPES_RIPPLESAWTOOTH_H
+#endif // USER_API
diff --git a/Sample/Shapes/TruncatedEllipsoid.h b/Sample/Shapes/TruncatedEllipsoid.h
index ff139024741cf71c5521217bf37754d93bb7c9d9..d90f9589183969427b334b1aba859079a784a466 100644
--- a/Sample/Shapes/TruncatedEllipsoid.h
+++ b/Sample/Shapes/TruncatedEllipsoid.h
@@ -16,6 +16,7 @@
 #error no need to expose this header to Swig
 #endif
 
+#ifndef USER_API
 #ifndef BORNAGAIN_SAMPLE_SHAPES_TRUNCATEDELLIPSOID_H
 #define BORNAGAIN_SAMPLE_SHAPES_TRUNCATEDELLIPSOID_H
 
@@ -28,3 +29,4 @@ public:
 };
 
 #endif // BORNAGAIN_SAMPLE_SHAPES_TRUNCATEDELLIPSOID_H
+#endif // USER_API
diff --git a/Sample/Slice/KzComputation.h b/Sample/Slice/KzComputation.h
index b64b97bad052ec9dd12741704240ef0cbbb521c8..491213450dd9db6bd56321f40511d38f9f2cbf83 100644
--- a/Sample/Slice/KzComputation.h
+++ b/Sample/Slice/KzComputation.h
@@ -16,6 +16,7 @@
 #error no need to expose this header to Swig
 #endif
 
+#ifndef USER_API
 #ifndef BORNAGAIN_SAMPLE_SLICE_KZCOMPUTATION_H
 #define BORNAGAIN_SAMPLE_SLICE_KZCOMPUTATION_H
 
@@ -52,3 +53,4 @@ std::vector<complex_t> computeKzFromRefIndices(const std::vector<Slice>& slices,
 } // namespace KzComputation
 
 #endif // BORNAGAIN_SAMPLE_SLICE_KZCOMPUTATION_H
+#endif // USER_API
diff --git a/Sample/Slice/LayerInterface.h b/Sample/Slice/LayerInterface.h
index 3528b31fcc056d4ffa51fa4a28de558bdfd58226..f0c5cd824b122ca243ed59e2ef9b4c923350b2f7 100644
--- a/Sample/Slice/LayerInterface.h
+++ b/Sample/Slice/LayerInterface.h
@@ -16,6 +16,7 @@
 #error no need to expose this header to Swig
 #endif
 
+#ifndef USER_API
 #ifndef BORNAGAIN_SAMPLE_SLICE_LAYERINTERFACE_H
 #define BORNAGAIN_SAMPLE_SLICE_LAYERINTERFACE_H
 
@@ -76,3 +77,4 @@ inline const Layer* LayerInterface::bottomLayer() const {
 }
 
 #endif // BORNAGAIN_SAMPLE_SLICE_LAYERINTERFACE_H
+#endif // USER_API
diff --git a/Sample/Slice/Slice.h b/Sample/Slice/Slice.h
index 9c83e230326f18082a2d80a07ac41ae43496ce41..e35e43b3e78d472304631a01b9afde676f5c096c 100644
--- a/Sample/Slice/Slice.h
+++ b/Sample/Slice/Slice.h
@@ -16,6 +16,7 @@
 #error no need to expose this header to Swig
 #endif
 
+#ifndef USER_API
 #ifndef BORNAGAIN_SAMPLE_SLICE_SLICE_H
 #define BORNAGAIN_SAMPLE_SLICE_SLICE_H
 
@@ -68,3 +69,4 @@ private:
 };
 
 #endif // BORNAGAIN_SAMPLE_SLICE_SLICE_H
+#endif // USER_API
diff --git a/Sample/Slice/SlicedFormFactorList.h b/Sample/Slice/SlicedFormFactorList.h
index 6780b0221a5601e676cfc2a77be32b035e571b13..ff6ea915afd4589eab243ed5a9d24e2a3ae92c27 100644
--- a/Sample/Slice/SlicedFormFactorList.h
+++ b/Sample/Slice/SlicedFormFactorList.h
@@ -16,6 +16,7 @@
 #error no need to expose this header to Swig
 #endif
 
+#ifndef USER_API
 #ifndef BORNAGAIN_SAMPLE_SLICE_SLICEDFORMFACTORLIST_H
 #define BORNAGAIN_SAMPLE_SLICE_SLICEDFORMFACTORLIST_H
 
@@ -56,3 +57,4 @@ private:
 };
 
 #endif // BORNAGAIN_SAMPLE_SLICE_SLICEDFORMFACTORLIST_H
+#endif // USER_API
diff --git a/Sample/SoftParticle/SoftParticles.h b/Sample/SoftParticle/SoftParticles.h
index 9e73cbdbb6234b6a5eec532ec21bea73389564e1..2f4ba048cae73333c21ba300c81582de3649cef9 100644
--- a/Sample/SoftParticle/SoftParticles.h
+++ b/Sample/SoftParticle/SoftParticles.h
@@ -16,6 +16,7 @@
 #error no need to expose this header to Swig
 #endif
 
+#ifndef USER_API
 #ifndef BORNAGAIN_SAMPLE_SOFTPARTICLE_SOFTPARTICLES_H
 #define BORNAGAIN_SAMPLE_SOFTPARTICLE_SOFTPARTICLES_H
 
@@ -24,3 +25,4 @@
 #include "Sample/SoftParticle/FormFactorSphereLogNormalRadius.h"
 
 #endif // BORNAGAIN_SAMPLE_SOFTPARTICLE_SOFTPARTICLES_H
+#endif // USER_API
diff --git a/Sample/Specular/ISpecularStrategy.h b/Sample/Specular/ISpecularStrategy.h
index 3fe2700168cce7e453477dbf380a74f5ca9efd9e..a4958fe6faf699ec85cf9c4ab17d1d3441e6a76a 100644
--- a/Sample/Specular/ISpecularStrategy.h
+++ b/Sample/Specular/ISpecularStrategy.h
@@ -16,6 +16,7 @@
 #error no need to expose this header to Swig
 #endif
 
+#ifndef USER_API
 #ifndef BORNAGAIN_SAMPLE_SPECULAR_ISPECULARSTRATEGY_H
 #define BORNAGAIN_SAMPLE_SPECULAR_ISPECULARSTRATEGY_H
 
@@ -49,3 +50,4 @@ public:
 };
 
 #endif // BORNAGAIN_SAMPLE_SPECULAR_ISPECULARSTRATEGY_H
+#endif // USER_API
diff --git a/Sample/Specular/SpecularMagneticNCStrategy.h b/Sample/Specular/SpecularMagneticNCStrategy.h
index da43b6575a130ba8c9bdbf6d40f0ee66ea058d6a..6ad085e86c6c8376868a0eca31b2e42f961b8405 100644
--- a/Sample/Specular/SpecularMagneticNCStrategy.h
+++ b/Sample/Specular/SpecularMagneticNCStrategy.h
@@ -16,6 +16,7 @@
 #error no need to expose this header to Swig
 #endif
 
+#ifndef USER_API
 #ifndef BORNAGAIN_SAMPLE_SPECULAR_SPECULARMAGNETICNCSTRATEGY_H
 #define BORNAGAIN_SAMPLE_SPECULAR_SPECULARMAGNETICNCSTRATEGY_H
 
@@ -43,3 +44,4 @@ private:
 };
 
 #endif // BORNAGAIN_SAMPLE_SPECULAR_SPECULARMAGNETICNCSTRATEGY_H
+#endif // USER_API
diff --git a/Sample/Specular/SpecularMagneticStrategy.h b/Sample/Specular/SpecularMagneticStrategy.h
index f936cc94d8b124eb7a430ecdd0f27d1ac1d76892..e948dc435c537ef81280533111d72687e47569f4 100644
--- a/Sample/Specular/SpecularMagneticStrategy.h
+++ b/Sample/Specular/SpecularMagneticStrategy.h
@@ -16,6 +16,7 @@
 #error no need to expose this header to Swig
 #endif
 
+#ifndef USER_API
 #ifndef BORNAGAIN_SAMPLE_SPECULAR_SPECULARMAGNETICSTRATEGY_H
 #define BORNAGAIN_SAMPLE_SPECULAR_SPECULARMAGNETICSTRATEGY_H
 
@@ -64,3 +65,4 @@ private:
 };
 
 #endif // BORNAGAIN_SAMPLE_SPECULAR_SPECULARMAGNETICSTRATEGY_H
+#endif // USER_API
diff --git a/Sample/Specular/SpecularMagneticTanhStrategy.h b/Sample/Specular/SpecularMagneticTanhStrategy.h
index 52322a81a7529ad9aa333ede9f79dade3e987cc2..01a0632a9bfa0015799f65d4ba72cc51de632c5d 100644
--- a/Sample/Specular/SpecularMagneticTanhStrategy.h
+++ b/Sample/Specular/SpecularMagneticTanhStrategy.h
@@ -16,6 +16,7 @@
 #error no need to expose this header to Swig
 #endif
 
+#ifndef USER_API
 #ifndef BORNAGAIN_SAMPLE_SPECULAR_SPECULARMAGNETICTANHSTRATEGY_H
 #define BORNAGAIN_SAMPLE_SPECULAR_SPECULARMAGNETICTANHSTRATEGY_H
 
@@ -40,3 +41,4 @@ private:
 };
 
 #endif // BORNAGAIN_SAMPLE_SPECULAR_SPECULARMAGNETICTANHSTRATEGY_H
+#endif // USER_API
diff --git a/Sample/Specular/SpecularScalarNCStrategy.h b/Sample/Specular/SpecularScalarNCStrategy.h
index f492ae35d2af3f410f555295e9aa0d07b2f666d5..d6b566d5c0799105bb7b627f08b2e0a32a51d9bf 100644
--- a/Sample/Specular/SpecularScalarNCStrategy.h
+++ b/Sample/Specular/SpecularScalarNCStrategy.h
@@ -16,6 +16,7 @@
 #error no need to expose this header to Swig
 #endif
 
+#ifndef USER_API
 #ifndef BORNAGAIN_SAMPLE_SPECULAR_SPECULARSCALARNCSTRATEGY_H
 #define BORNAGAIN_SAMPLE_SPECULAR_SPECULARSCALARNCSTRATEGY_H
 
@@ -42,3 +43,4 @@ private:
 };
 
 #endif // BORNAGAIN_SAMPLE_SPECULAR_SPECULARSCALARNCSTRATEGY_H
+#endif // USER_API
diff --git a/Sample/Specular/SpecularScalarStrategy.h b/Sample/Specular/SpecularScalarStrategy.h
index 6ba7a7ddd4bdbbe4ea8ff2da81055f346d17eb22..599b609138a18b8ff617dc250c494c69f0a6cdb8 100644
--- a/Sample/Specular/SpecularScalarStrategy.h
+++ b/Sample/Specular/SpecularScalarStrategy.h
@@ -16,6 +16,7 @@
 #error no need to expose this header to Swig
 #endif
 
+#ifndef USER_API
 #ifndef BORNAGAIN_SAMPLE_SPECULAR_SPECULARSCALARSTRATEGY_H
 #define BORNAGAIN_SAMPLE_SPECULAR_SPECULARSCALARSTRATEGY_H
 
@@ -65,3 +66,4 @@ private:
 };
 
 #endif // BORNAGAIN_SAMPLE_SPECULAR_SPECULARSCALARSTRATEGY_H
+#endif // USER_API
diff --git a/Sample/Specular/SpecularScalarTanhStrategy.h b/Sample/Specular/SpecularScalarTanhStrategy.h
index bf8f908f141cb53cb98bb250773d7b86fff0913b..19de5f143afe5e7cec34c9b62f972669a1080549 100644
--- a/Sample/Specular/SpecularScalarTanhStrategy.h
+++ b/Sample/Specular/SpecularScalarTanhStrategy.h
@@ -16,6 +16,7 @@
 #error no need to expose this header to Swig
 #endif
 
+#ifndef USER_API
 #ifndef BORNAGAIN_SAMPLE_SPECULAR_SPECULARSCALARTANHSTRATEGY_H
 #define BORNAGAIN_SAMPLE_SPECULAR_SPECULARSCALARTANHSTRATEGY_H
 
@@ -38,3 +39,4 @@ private:
 };
 
 #endif // BORNAGAIN_SAMPLE_SPECULAR_SPECULARSCALARTANHSTRATEGY_H
+#endif // USER_API
diff --git a/Sample/Specular/SpecularStrategyBuilder.h b/Sample/Specular/SpecularStrategyBuilder.h
index ee0c01cc950963591a2a2fca573c59b773b90a34..a13336e14b9584d1583e6c6e496be86c68b5f347 100644
--- a/Sample/Specular/SpecularStrategyBuilder.h
+++ b/Sample/Specular/SpecularStrategyBuilder.h
@@ -16,6 +16,7 @@
 #error no need to expose this header to Swig
 #endif
 
+#ifndef USER_API
 #ifndef BORNAGAIN_SAMPLE_SPECULAR_SPECULARSTRATEGYBUILDER_H
 #define BORNAGAIN_SAMPLE_SPECULAR_SPECULARSTRATEGYBUILDER_H
 
@@ -29,3 +30,4 @@ public:
 };
 
 #endif // BORNAGAIN_SAMPLE_SPECULAR_SPECULARSTRATEGYBUILDER_H
+#endif // USER_API
diff --git a/Sample/StandardSamples/BoxCompositionBuilder.h b/Sample/StandardSamples/BoxCompositionBuilder.h
index 12603fb3b61811dc6b40d69e7a81fcffbddf5db9..65204fb1ecad0cfea23905545b25b11628693b3b 100644
--- a/Sample/StandardSamples/BoxCompositionBuilder.h
+++ b/Sample/StandardSamples/BoxCompositionBuilder.h
@@ -16,6 +16,7 @@
 #error no need to expose this header to Swig
 #endif
 
+#ifndef USER_API
 #ifndef BORNAGAIN_SAMPLE_STANDARDSAMPLES_BOXCOMPOSITIONBUILDER_H
 #define BORNAGAIN_SAMPLE_STANDARDSAMPLES_BOXCOMPOSITIONBUILDER_H
 
@@ -62,3 +63,4 @@ public:
 };
 
 #endif // BORNAGAIN_SAMPLE_STANDARDSAMPLES_BOXCOMPOSITIONBUILDER_H
+#endif // USER_API
diff --git a/Sample/StandardSamples/BoxesSquareLatticeBuilder.h b/Sample/StandardSamples/BoxesSquareLatticeBuilder.h
index 9af2f5c4dff194e54b8e03c09852488bd7ab21bc..4a52ab83531505b85f1bc24e14f1c98a2bf562aa 100644
--- a/Sample/StandardSamples/BoxesSquareLatticeBuilder.h
+++ b/Sample/StandardSamples/BoxesSquareLatticeBuilder.h
@@ -16,6 +16,7 @@
 #error no need to expose this header to Swig
 #endif
 
+#ifndef USER_API
 #ifndef BORNAGAIN_SAMPLE_STANDARDSAMPLES_BOXESSQUARELATTICEBUILDER_H
 #define BORNAGAIN_SAMPLE_STANDARDSAMPLES_BOXESSQUARELATTICEBUILDER_H
 
@@ -30,3 +31,4 @@ public:
 };
 
 #endif // BORNAGAIN_SAMPLE_STANDARDSAMPLES_BOXESSQUARELATTICEBUILDER_H
+#endif // USER_API
diff --git a/Sample/StandardSamples/CoreShellParticleBuilder.h b/Sample/StandardSamples/CoreShellParticleBuilder.h
index 3dde8bda2585721f20975fc5c059d706a93541be..c706aa0e3da6b6741b62a52074e939103363dfba 100644
--- a/Sample/StandardSamples/CoreShellParticleBuilder.h
+++ b/Sample/StandardSamples/CoreShellParticleBuilder.h
@@ -16,6 +16,7 @@
 #error no need to expose this header to Swig
 #endif
 
+#ifndef USER_API
 #ifndef BORNAGAIN_SAMPLE_STANDARDSAMPLES_CORESHELLPARTICLEBUILDER_H
 #define BORNAGAIN_SAMPLE_STANDARDSAMPLES_CORESHELLPARTICLEBUILDER_H
 
@@ -38,3 +39,4 @@ public:
 };
 
 #endif // BORNAGAIN_SAMPLE_STANDARDSAMPLES_CORESHELLPARTICLEBUILDER_H
+#endif // USER_API
diff --git a/Sample/StandardSamples/CustomMorphologyBuilder.h b/Sample/StandardSamples/CustomMorphologyBuilder.h
index a6e5767ad69df914814a49fba9ccd99c1dbf6cfc..f1b997e29a8067033eac776bbdb6caef5661be88 100644
--- a/Sample/StandardSamples/CustomMorphologyBuilder.h
+++ b/Sample/StandardSamples/CustomMorphologyBuilder.h
@@ -16,6 +16,7 @@
 #error no need to expose this header to Swig
 #endif
 
+#ifndef USER_API
 #ifndef BORNAGAIN_SAMPLE_STANDARDSAMPLES_CUSTOMMORPHOLOGYBUILDER_H
 #define BORNAGAIN_SAMPLE_STANDARDSAMPLES_CUSTOMMORPHOLOGYBUILDER_H
 
@@ -30,3 +31,4 @@ public:
 };
 
 #endif // BORNAGAIN_SAMPLE_STANDARDSAMPLES_CUSTOMMORPHOLOGYBUILDER_H
+#endif // USER_API
diff --git a/Sample/StandardSamples/CylindersAndPrismsBuilder.h b/Sample/StandardSamples/CylindersAndPrismsBuilder.h
index 5d18aa8384ce07ba7ebdd789898ea65d855bf6fa..282195abf110123f701637e57e8c427677d7c113 100644
--- a/Sample/StandardSamples/CylindersAndPrismsBuilder.h
+++ b/Sample/StandardSamples/CylindersAndPrismsBuilder.h
@@ -16,6 +16,7 @@
 #error no need to expose this header to Swig
 #endif
 
+#ifndef USER_API
 #ifndef BORNAGAIN_SAMPLE_STANDARDSAMPLES_CYLINDERSANDPRISMSBUILDER_H
 #define BORNAGAIN_SAMPLE_STANDARDSAMPLES_CYLINDERSANDPRISMSBUILDER_H
 
@@ -30,3 +31,4 @@ public:
 };
 
 #endif // BORNAGAIN_SAMPLE_STANDARDSAMPLES_CYLINDERSANDPRISMSBUILDER_H
+#endif // USER_API
diff --git a/Sample/StandardSamples/CylindersBuilder.h b/Sample/StandardSamples/CylindersBuilder.h
index cad88c2fea9919e9412ad0f4a2c5f8e2c7c2980d..cfa02327f09a42bd53645ee12ee4f46c5cfe72b1 100644
--- a/Sample/StandardSamples/CylindersBuilder.h
+++ b/Sample/StandardSamples/CylindersBuilder.h
@@ -16,6 +16,7 @@
 #error no need to expose this header to Swig
 #endif
 
+#ifndef USER_API
 #ifndef BORNAGAIN_SAMPLE_STANDARDSAMPLES_CYLINDERSBUILDER_H
 #define BORNAGAIN_SAMPLE_STANDARDSAMPLES_CYLINDERSBUILDER_H
 
@@ -74,3 +75,4 @@ private:
 };
 
 #endif // BORNAGAIN_SAMPLE_STANDARDSAMPLES_CYLINDERSBUILDER_H
+#endif // USER_API
diff --git a/Sample/StandardSamples/FeNiBilayerBuilder.h b/Sample/StandardSamples/FeNiBilayerBuilder.h
index 0feb343dbd6906af7a4803795e4b1299b31cccb1..90f9f9c505d20dea671c6eb7b00f48668f703a63 100644
--- a/Sample/StandardSamples/FeNiBilayerBuilder.h
+++ b/Sample/StandardSamples/FeNiBilayerBuilder.h
@@ -17,6 +17,7 @@
 #error no need to expose this header to Swig
 #endif
 
+#ifndef USER_API
 #ifndef BORNAGAIN_SAMPLE_STANDARDSAMPLES_FENIBILAYERBUILDER_H
 #define BORNAGAIN_SAMPLE_STANDARDSAMPLES_FENIBILAYERBUILDER_H
 
@@ -53,3 +54,4 @@ public:
 };
 
 #endif // BORNAGAIN_SAMPLE_STANDARDSAMPLES_FENIBILAYERBUILDER_H
+#endif // USER_API
diff --git a/Sample/StandardSamples/HomogeneousMultilayerBuilder.h b/Sample/StandardSamples/HomogeneousMultilayerBuilder.h
index 3cd30a87737661581c98622116beeb3ebe54127e..466504bde80e7645e9fc12df93a82d6999ca7997 100644
--- a/Sample/StandardSamples/HomogeneousMultilayerBuilder.h
+++ b/Sample/StandardSamples/HomogeneousMultilayerBuilder.h
@@ -16,6 +16,7 @@
 #error no need to expose this header to Swig
 #endif
 
+#ifndef USER_API
 #ifndef BORNAGAIN_SAMPLE_STANDARDSAMPLES_HOMOGENEOUSMULTILAYERBUILDER_H
 #define BORNAGAIN_SAMPLE_STANDARDSAMPLES_HOMOGENEOUSMULTILAYERBUILDER_H
 
@@ -32,3 +33,4 @@ public:
 };
 
 #endif // BORNAGAIN_SAMPLE_STANDARDSAMPLES_HOMOGENEOUSMULTILAYERBUILDER_H
+#endif // USER_API
diff --git a/Sample/StandardSamples/LatticeBuilder.h b/Sample/StandardSamples/LatticeBuilder.h
index 997e74fc250585fa8e0b20a8cfc67a2ae95ae2ad..9ffa62c6c0fcdc8ad60fdf7d779ad8852bbde4f7 100644
--- a/Sample/StandardSamples/LatticeBuilder.h
+++ b/Sample/StandardSamples/LatticeBuilder.h
@@ -16,6 +16,7 @@
 #error no need to expose this header to Swig
 #endif
 
+#ifndef USER_API
 #ifndef BORNAGAIN_SAMPLE_STANDARDSAMPLES_LATTICEBUILDER_H
 #define BORNAGAIN_SAMPLE_STANDARDSAMPLES_LATTICEBUILDER_H
 
@@ -30,3 +31,4 @@ public:
 };
 
 #endif // BORNAGAIN_SAMPLE_STANDARDSAMPLES_LATTICEBUILDER_H
+#endif // USER_API
diff --git a/Sample/StandardSamples/LayersWithAbsorptionBuilder.h b/Sample/StandardSamples/LayersWithAbsorptionBuilder.h
index 22688c186bd8222c9b7b79a4b6413ecc77e5b313..ded0762d5a53764a58ce4d625ad9dcea3e5d0fe2 100644
--- a/Sample/StandardSamples/LayersWithAbsorptionBuilder.h
+++ b/Sample/StandardSamples/LayersWithAbsorptionBuilder.h
@@ -16,6 +16,7 @@
 #error no need to expose this header to Swig
 #endif
 
+#ifndef USER_API
 #ifndef BORNAGAIN_SAMPLE_STANDARDSAMPLES_LAYERSWITHABSORPTIONBUILDER_H
 #define BORNAGAIN_SAMPLE_STANDARDSAMPLES_LAYERSWITHABSORPTIONBUILDER_H
 
@@ -45,3 +46,4 @@ private:
 };
 
 #endif // BORNAGAIN_SAMPLE_STANDARDSAMPLES_LAYERSWITHABSORPTIONBUILDER_H
+#endif // USER_API
diff --git a/Sample/StandardSamples/LayersWithAbsorptionBySLDBuilder.h b/Sample/StandardSamples/LayersWithAbsorptionBySLDBuilder.h
index ae805e2b63bad22c37290976d2e0415cafdb8bf7..74348bba2e86f471d2e5e591d76b157b28d7c82c 100644
--- a/Sample/StandardSamples/LayersWithAbsorptionBySLDBuilder.h
+++ b/Sample/StandardSamples/LayersWithAbsorptionBySLDBuilder.h
@@ -16,6 +16,7 @@
 #error no need to expose this header to Swig
 #endif
 
+#ifndef USER_API
 #ifndef BORNAGAIN_SAMPLE_STANDARDSAMPLES_LAYERSWITHABSORPTIONBYSLDBUILDER_H
 #define BORNAGAIN_SAMPLE_STANDARDSAMPLES_LAYERSWITHABSORPTIONBYSLDBUILDER_H
 
@@ -32,3 +33,4 @@ public:
 };
 
 #endif // BORNAGAIN_SAMPLE_STANDARDSAMPLES_LAYERSWITHABSORPTIONBYSLDBUILDER_H
+#endif // USER_API
diff --git a/Sample/StandardSamples/MagneticLayersBuilder.h b/Sample/StandardSamples/MagneticLayersBuilder.h
index 7b43960a7da610e91c049791ac70c8bf4e96a810..befd86602ed7d121268daaa59d2139a561a2f6e0 100644
--- a/Sample/StandardSamples/MagneticLayersBuilder.h
+++ b/Sample/StandardSamples/MagneticLayersBuilder.h
@@ -16,6 +16,7 @@
 #error no need to expose this header to Swig
 #endif
 
+#ifndef USER_API
 #ifndef BORNAGAIN_SAMPLE_STANDARDSAMPLES_MAGNETICLAYERSBUILDER_H
 #define BORNAGAIN_SAMPLE_STANDARDSAMPLES_MAGNETICLAYERSBUILDER_H
 
@@ -66,3 +67,4 @@ public:
 };
 
 #endif // BORNAGAIN_SAMPLE_STANDARDSAMPLES_MAGNETICLAYERSBUILDER_H
+#endif // USER_API
diff --git a/Sample/StandardSamples/MagneticParticlesBuilder.h b/Sample/StandardSamples/MagneticParticlesBuilder.h
index 3c258b94cc9685493f8bbb0059959a5ed6adc468..b758b0a5902b224eb9ad750d6deb8ce438a39a5c 100644
--- a/Sample/StandardSamples/MagneticParticlesBuilder.h
+++ b/Sample/StandardSamples/MagneticParticlesBuilder.h
@@ -16,6 +16,7 @@
 #error no need to expose this header to Swig
 #endif
 
+#ifndef USER_API
 #ifndef BORNAGAIN_SAMPLE_STANDARDSAMPLES_MAGNETICPARTICLESBUILDER_H
 #define BORNAGAIN_SAMPLE_STANDARDSAMPLES_MAGNETICPARTICLESBUILDER_H
 
@@ -46,3 +47,4 @@ public:
 };
 
 #endif // BORNAGAIN_SAMPLE_STANDARDSAMPLES_MAGNETICPARTICLESBUILDER_H
+#endif // USER_API
diff --git a/Sample/StandardSamples/MesoCrystalBuilder.h b/Sample/StandardSamples/MesoCrystalBuilder.h
index 77f27453af7c6dd78d1a3b9fffcbe705726da531..d9afaf8897eb86109b23d6e71c8e76efb9ea7484 100644
--- a/Sample/StandardSamples/MesoCrystalBuilder.h
+++ b/Sample/StandardSamples/MesoCrystalBuilder.h
@@ -16,6 +16,7 @@
 #error no need to expose this header to Swig
 #endif
 
+#ifndef USER_API
 #ifndef BORNAGAIN_SAMPLE_STANDARDSAMPLES_MESOCRYSTALBUILDER_H
 #define BORNAGAIN_SAMPLE_STANDARDSAMPLES_MESOCRYSTALBUILDER_H
 
@@ -30,3 +31,4 @@ public:
 };
 
 #endif // BORNAGAIN_SAMPLE_STANDARDSAMPLES_MESOCRYSTALBUILDER_H
+#endif // USER_API
diff --git a/Sample/StandardSamples/MultiLayerWithNCRoughnessBuilder.h b/Sample/StandardSamples/MultiLayerWithNCRoughnessBuilder.h
index ad0aa325d57ef61ec1bfdd21e5af8495c4de5000..eff31cf24a204d57b7c50a8efe160bc069dd1300 100644
--- a/Sample/StandardSamples/MultiLayerWithNCRoughnessBuilder.h
+++ b/Sample/StandardSamples/MultiLayerWithNCRoughnessBuilder.h
@@ -16,6 +16,7 @@
 #error no need to expose this header to Swig
 #endif
 
+#ifndef USER_API
 #ifndef BORNAGAIN_SAMPLE_STANDARDSAMPLES_MULTILAYERWITHNCROUGHNESSBUILDER_H
 #define BORNAGAIN_SAMPLE_STANDARDSAMPLES_MULTILAYERWITHNCROUGHNESSBUILDER_H
 
@@ -30,3 +31,4 @@ public:
 };
 
 #endif // BORNAGAIN_SAMPLE_STANDARDSAMPLES_MULTILAYERWITHNCROUGHNESSBUILDER_H
+#endif // USER_API
diff --git a/Sample/StandardSamples/MultiLayerWithRoughnessBuilder.h b/Sample/StandardSamples/MultiLayerWithRoughnessBuilder.h
index f87040eb72c4b4fa219364a5728569c0f7b515ec..80d6c514fa8c9b972e4ab1598e89bd4b294ecd64 100644
--- a/Sample/StandardSamples/MultiLayerWithRoughnessBuilder.h
+++ b/Sample/StandardSamples/MultiLayerWithRoughnessBuilder.h
@@ -16,6 +16,7 @@
 #error no need to expose this header to Swig
 #endif
 
+#ifndef USER_API
 #ifndef BORNAGAIN_SAMPLE_STANDARDSAMPLES_MULTILAYERWITHROUGHNESSBUILDER_H
 #define BORNAGAIN_SAMPLE_STANDARDSAMPLES_MULTILAYERWITHROUGHNESSBUILDER_H
 
@@ -30,3 +31,4 @@ public:
 };
 
 #endif // BORNAGAIN_SAMPLE_STANDARDSAMPLES_MULTILAYERWITHROUGHNESSBUILDER_H
+#endif // USER_API
diff --git a/Sample/StandardSamples/MultipleLayoutBuilder.h b/Sample/StandardSamples/MultipleLayoutBuilder.h
index 05ee9b0e8cadaaa6819c29d4e24a2861a147cade..452f3f813959f3db34b337a9157dafc81d9a43dc 100644
--- a/Sample/StandardSamples/MultipleLayoutBuilder.h
+++ b/Sample/StandardSamples/MultipleLayoutBuilder.h
@@ -16,6 +16,7 @@
 #error no need to expose this header to Swig
 #endif
 
+#ifndef USER_API
 #ifndef BORNAGAIN_SAMPLE_STANDARDSAMPLES_MULTIPLELAYOUTBUILDER_H
 #define BORNAGAIN_SAMPLE_STANDARDSAMPLES_MULTIPLELAYOUTBUILDER_H
 
@@ -31,3 +32,4 @@ public:
 };
 
 #endif // BORNAGAIN_SAMPLE_STANDARDSAMPLES_MULTIPLELAYOUTBUILDER_H
+#endif // USER_API
diff --git a/Sample/StandardSamples/ParaCrystalBuilder.h b/Sample/StandardSamples/ParaCrystalBuilder.h
index 51fc6573e9f604077319dabd44e2c7e05fa90464..94a019e472012f7d6ac28e1f048c2ee0f7393b85 100644
--- a/Sample/StandardSamples/ParaCrystalBuilder.h
+++ b/Sample/StandardSamples/ParaCrystalBuilder.h
@@ -16,6 +16,7 @@
 #error no need to expose this header to Swig
 #endif
 
+#ifndef USER_API
 #ifndef BORNAGAIN_SAMPLE_STANDARDSAMPLES_PARACRYSTALBUILDER_H
 #define BORNAGAIN_SAMPLE_STANDARDSAMPLES_PARACRYSTALBUILDER_H
 
@@ -67,3 +68,4 @@ public:
 };
 
 #endif // BORNAGAIN_SAMPLE_STANDARDSAMPLES_PARACRYSTALBUILDER_H
+#endif // USER_API
diff --git a/Sample/StandardSamples/ParticleCompositionBuilder.h b/Sample/StandardSamples/ParticleCompositionBuilder.h
index 22ca2a9395322b0e12ba2873ef661fca45c72bbe..0f7eb497737bf0ad08dc2c4989fe3bea08678649 100644
--- a/Sample/StandardSamples/ParticleCompositionBuilder.h
+++ b/Sample/StandardSamples/ParticleCompositionBuilder.h
@@ -16,6 +16,7 @@
 #error no need to expose this header to Swig
 #endif
 
+#ifndef USER_API
 #ifndef BORNAGAIN_SAMPLE_STANDARDSAMPLES_PARTICLECOMPOSITIONBUILDER_H
 #define BORNAGAIN_SAMPLE_STANDARDSAMPLES_PARTICLECOMPOSITIONBUILDER_H
 
@@ -30,3 +31,4 @@ public:
 };
 
 #endif // BORNAGAIN_SAMPLE_STANDARDSAMPLES_PARTICLECOMPOSITIONBUILDER_H
+#endif // USER_API
diff --git a/Sample/StandardSamples/ParticleDistributionsBuilder.h b/Sample/StandardSamples/ParticleDistributionsBuilder.h
index f0c643f643cffe83c3071905103215ac5ad053a0..d3335a80fc06959d94dd7dae718fb6a4be9596cf 100644
--- a/Sample/StandardSamples/ParticleDistributionsBuilder.h
+++ b/Sample/StandardSamples/ParticleDistributionsBuilder.h
@@ -16,6 +16,7 @@
 #error no need to expose this header to Swig
 #endif
 
+#ifndef USER_API
 #ifndef BORNAGAIN_SAMPLE_STANDARDSAMPLES_PARTICLEDISTRIBUTIONSBUILDER_H
 #define BORNAGAIN_SAMPLE_STANDARDSAMPLES_PARTICLEDISTRIBUTIONSBUILDER_H
 
@@ -89,3 +90,4 @@ public:
 };
 
 #endif // BORNAGAIN_SAMPLE_STANDARDSAMPLES_PARTICLEDISTRIBUTIONSBUILDER_H
+#endif // USER_API
diff --git a/Sample/StandardSamples/ParticleInVacuumBuilder.h b/Sample/StandardSamples/ParticleInVacuumBuilder.h
index 200c6a5f156518bcd929f3fd743d9070bb0684fd..11b1e8a91a67f309e9258670f4d724475eb703b9 100644
--- a/Sample/StandardSamples/ParticleInVacuumBuilder.h
+++ b/Sample/StandardSamples/ParticleInVacuumBuilder.h
@@ -16,6 +16,7 @@
 #error no need to expose this header to Swig
 #endif
 
+#ifndef USER_API
 #ifndef BORNAGAIN_SAMPLE_STANDARDSAMPLES_PARTICLEINVACUUMBUILDER_H
 #define BORNAGAIN_SAMPLE_STANDARDSAMPLES_PARTICLEINVACUUMBUILDER_H
 
@@ -42,3 +43,4 @@ protected:
 };
 
 #endif // BORNAGAIN_SAMPLE_STANDARDSAMPLES_PARTICLEINVACUUMBUILDER_H
+#endif // USER_API
diff --git a/Sample/StandardSamples/PercusYevickBuilder.h b/Sample/StandardSamples/PercusYevickBuilder.h
index 06cc34d1198c1401ae2b2a4c5d6e281c2c5df9d6..3a2ede1f6fc3571f0df551e199658c2823743ae9 100644
--- a/Sample/StandardSamples/PercusYevickBuilder.h
+++ b/Sample/StandardSamples/PercusYevickBuilder.h
@@ -16,6 +16,7 @@
 #error no need to expose this header to Swig
 #endif
 
+#ifndef USER_API
 #ifndef BORNAGAIN_SAMPLE_STANDARDSAMPLES_PERCUSYEVICKBUILDER_H
 #define BORNAGAIN_SAMPLE_STANDARDSAMPLES_PERCUSYEVICKBUILDER_H
 
@@ -30,3 +31,4 @@ public:
 };
 
 #endif // BORNAGAIN_SAMPLE_STANDARDSAMPLES_PERCUSYEVICKBUILDER_H
+#endif // USER_API
diff --git a/Sample/StandardSamples/PlainMultiLayerBySLDBuilder.h b/Sample/StandardSamples/PlainMultiLayerBySLDBuilder.h
index 5faf02f2e03883249f2e38f55be05e9e905e50e5..2fa5955e5d7e96e70873838768ae53e3ed2de6dd 100644
--- a/Sample/StandardSamples/PlainMultiLayerBySLDBuilder.h
+++ b/Sample/StandardSamples/PlainMultiLayerBySLDBuilder.h
@@ -16,6 +16,7 @@
 #error no need to expose this header to Swig
 #endif
 
+#ifndef USER_API
 #ifndef BORNAGAIN_SAMPLE_STANDARDSAMPLES_PLAINMULTILAYERBYSLDBUILDER_H
 #define BORNAGAIN_SAMPLE_STANDARDSAMPLES_PLAINMULTILAYERBYSLDBUILDER_H
 
@@ -44,3 +45,4 @@ protected:
 };
 
 #endif // BORNAGAIN_SAMPLE_STANDARDSAMPLES_PLAINMULTILAYERBYSLDBUILDER_H
+#endif // USER_API
diff --git a/Sample/StandardSamples/ReferenceMaterials.h b/Sample/StandardSamples/ReferenceMaterials.h
index bd57e6dd130f24f6c8258efec32ae606ee2a2f20..1b4fb4b9e9eebd12c0ab6458dc8bc9e9f1d5d1b2 100644
--- a/Sample/StandardSamples/ReferenceMaterials.h
+++ b/Sample/StandardSamples/ReferenceMaterials.h
@@ -16,6 +16,7 @@
 #error no need to expose this header to Swig
 #endif
 
+#ifndef USER_API
 #ifndef BORNAGAIN_SAMPLE_STANDARDSAMPLES_REFERENCEMATERIALS_H
 #define BORNAGAIN_SAMPLE_STANDARDSAMPLES_REFERENCEMATERIALS_H
 
@@ -38,3 +39,4 @@ static const Material Substrate2 = HomogeneousMaterial("Substrate2", 3.212e-6, 3
 } // namespace refMat
 
 #endif // BORNAGAIN_SAMPLE_STANDARDSAMPLES_REFERENCEMATERIALS_H
+#endif // USER_API
diff --git a/Sample/StandardSamples/ResonatorBuilder.h b/Sample/StandardSamples/ResonatorBuilder.h
index 31271cd3da817722b4bf68887fdcf1766dd57efc..3e456a64259f9da65afad99cb18eb407c641d748 100644
--- a/Sample/StandardSamples/ResonatorBuilder.h
+++ b/Sample/StandardSamples/ResonatorBuilder.h
@@ -16,6 +16,7 @@
 #error no need to expose this header to Swig
 #endif
 
+#ifndef USER_API
 #ifndef BORNAGAIN_SAMPLE_STANDARDSAMPLES_RESONATORBUILDER_H
 #define BORNAGAIN_SAMPLE_STANDARDSAMPLES_RESONATORBUILDER_H
 
@@ -34,3 +35,4 @@ private:
 };
 
 #endif // BORNAGAIN_SAMPLE_STANDARDSAMPLES_RESONATORBUILDER_H
+#endif // USER_API
diff --git a/Sample/StandardSamples/RipplesBuilder.h b/Sample/StandardSamples/RipplesBuilder.h
index 47f611b315e543447ef9f5024d7ab7bf9a54680a..5367d0e2ecbeee6d0f752facb2606dfe1a1eee99 100644
--- a/Sample/StandardSamples/RipplesBuilder.h
+++ b/Sample/StandardSamples/RipplesBuilder.h
@@ -16,6 +16,7 @@
 #error no need to expose this header to Swig
 #endif
 
+#ifndef USER_API
 #ifndef BORNAGAIN_SAMPLE_STANDARDSAMPLES_RIPPLESBUILDER_H
 #define BORNAGAIN_SAMPLE_STANDARDSAMPLES_RIPPLESBUILDER_H
 
@@ -47,3 +48,4 @@ public:
 };
 
 #endif // BORNAGAIN_SAMPLE_STANDARDSAMPLES_RIPPLESBUILDER_H
+#endif // USER_API
diff --git a/Sample/StandardSamples/RotatedPyramidsBuilder.h b/Sample/StandardSamples/RotatedPyramidsBuilder.h
index 7bf8d02379f41768a1f64247d36bdf1542caaf17..cfba796dd6acd8d4c7ecba272b672883620174c9 100644
--- a/Sample/StandardSamples/RotatedPyramidsBuilder.h
+++ b/Sample/StandardSamples/RotatedPyramidsBuilder.h
@@ -16,6 +16,7 @@
 #error no need to expose this header to Swig
 #endif
 
+#ifndef USER_API
 #ifndef BORNAGAIN_SAMPLE_STANDARDSAMPLES_ROTATEDPYRAMIDSBUILDER_H
 #define BORNAGAIN_SAMPLE_STANDARDSAMPLES_ROTATEDPYRAMIDSBUILDER_H
 
@@ -30,3 +31,4 @@ public:
 };
 
 #endif // BORNAGAIN_SAMPLE_STANDARDSAMPLES_ROTATEDPYRAMIDSBUILDER_H
+#endif // USER_API
diff --git a/Sample/StandardSamples/SizeDistributionModelsBuilder.h b/Sample/StandardSamples/SizeDistributionModelsBuilder.h
index 757fc77bf3f9741d12e37bad18164dfc42d49b49..7e01c21c55181a610d6d0574f58b686b5b3804e4 100644
--- a/Sample/StandardSamples/SizeDistributionModelsBuilder.h
+++ b/Sample/StandardSamples/SizeDistributionModelsBuilder.h
@@ -16,6 +16,7 @@
 #error no need to expose this header to Swig
 #endif
 
+#ifndef USER_API
 #ifndef BORNAGAIN_SAMPLE_STANDARDSAMPLES_SIZEDISTRIBUTIONMODELSBUILDER_H
 #define BORNAGAIN_SAMPLE_STANDARDSAMPLES_SIZEDISTRIBUTIONMODELSBUILDER_H
 
@@ -57,3 +58,4 @@ public:
 };
 
 #endif // BORNAGAIN_SAMPLE_STANDARDSAMPLES_SIZEDISTRIBUTIONMODELSBUILDER_H
+#endif // USER_API
diff --git a/Sample/StandardSamples/SlicedCompositionBuilder.h b/Sample/StandardSamples/SlicedCompositionBuilder.h
index 8770fe902381e469ba378dc13e54b1c6f36ca868..368e4e113fde959fd56562067ea2b40040a77acd 100644
--- a/Sample/StandardSamples/SlicedCompositionBuilder.h
+++ b/Sample/StandardSamples/SlicedCompositionBuilder.h
@@ -16,6 +16,7 @@
 #error no need to expose this header to Swig
 #endif
 
+#ifndef USER_API
 #ifndef BORNAGAIN_SAMPLE_STANDARDSAMPLES_SLICEDCOMPOSITIONBUILDER_H
 #define BORNAGAIN_SAMPLE_STANDARDSAMPLES_SLICEDCOMPOSITIONBUILDER_H
 
@@ -30,3 +31,4 @@ public:
 };
 
 #endif // BORNAGAIN_SAMPLE_STANDARDSAMPLES_SLICEDCOMPOSITIONBUILDER_H
+#endif // USER_API
diff --git a/Sample/StandardSamples/SlicedCylindersBuilder.h b/Sample/StandardSamples/SlicedCylindersBuilder.h
index 848d8836338b1bb33c60460b19f94fa7339dfed7..729b2a3de72b493369adb997f9aadca52be2ca8d 100644
--- a/Sample/StandardSamples/SlicedCylindersBuilder.h
+++ b/Sample/StandardSamples/SlicedCylindersBuilder.h
@@ -16,6 +16,7 @@
 #error no need to expose this header to Swig
 #endif
 
+#ifndef USER_API
 #ifndef BORNAGAIN_SAMPLE_STANDARDSAMPLES_SLICEDCYLINDERSBUILDER_H
 #define BORNAGAIN_SAMPLE_STANDARDSAMPLES_SLICEDCYLINDERSBUILDER_H
 
@@ -49,3 +50,4 @@ public:
 };
 
 #endif // BORNAGAIN_SAMPLE_STANDARDSAMPLES_SLICEDCYLINDERSBUILDER_H
+#endif // USER_API
diff --git a/Sample/StandardSamples/ThickAbsorptiveSampleBuilder.h b/Sample/StandardSamples/ThickAbsorptiveSampleBuilder.h
index f2daabaec738b81a524ede75a1379db045cd35c2..0ba7bfae303eab223879649cd176a260a94ff39a 100644
--- a/Sample/StandardSamples/ThickAbsorptiveSampleBuilder.h
+++ b/Sample/StandardSamples/ThickAbsorptiveSampleBuilder.h
@@ -16,6 +16,7 @@
 #error no need to expose this header to Swig
 #endif
 
+#ifndef USER_API
 #ifndef BORNAGAIN_SAMPLE_STANDARDSAMPLES_THICKABSORPTIVESAMPLEBUILDER_H
 #define BORNAGAIN_SAMPLE_STANDARDSAMPLES_THICKABSORPTIVESAMPLEBUILDER_H
 
@@ -27,3 +28,4 @@ public:
 };
 
 #endif // BORNAGAIN_SAMPLE_STANDARDSAMPLES_THICKABSORPTIVESAMPLEBUILDER_H
+#endif // USER_API
diff --git a/Sample/StandardSamples/TransformationsBuilder.h b/Sample/StandardSamples/TransformationsBuilder.h
index 3b722d179e4b131d45f42b694961a5dd56aeb0e6..dbae7ffd97e904118d93f4e0948cc08d9bbb4348 100644
--- a/Sample/StandardSamples/TransformationsBuilder.h
+++ b/Sample/StandardSamples/TransformationsBuilder.h
@@ -16,6 +16,7 @@
 #error no need to expose this header to Swig
 #endif
 
+#ifndef USER_API
 #ifndef BORNAGAIN_SAMPLE_STANDARDSAMPLES_TRANSFORMATIONSBUILDER_H
 #define BORNAGAIN_SAMPLE_STANDARDSAMPLES_TRANSFORMATIONSBUILDER_H
 
@@ -30,3 +31,4 @@ public:
 };
 
 #endif // BORNAGAIN_SAMPLE_STANDARDSAMPLES_TRANSFORMATIONSBUILDER_H
+#endif // USER_API
diff --git a/Sample/StandardSamples/TwoDimLatticeBuilder.h b/Sample/StandardSamples/TwoDimLatticeBuilder.h
index 7c144696f0efd93df13d7135cb245af5dd0b057d..edc22ba3955b1bf8e245ebb68cb1f8ea5388dcae 100644
--- a/Sample/StandardSamples/TwoDimLatticeBuilder.h
+++ b/Sample/StandardSamples/TwoDimLatticeBuilder.h
@@ -16,6 +16,7 @@
 #error no need to expose this header to Swig
 #endif
 
+#ifndef USER_API
 #ifndef BORNAGAIN_SAMPLE_STANDARDSAMPLES_TWODIMLATTICEBUILDER_H
 #define BORNAGAIN_SAMPLE_STANDARDSAMPLES_TWODIMLATTICEBUILDER_H
 
@@ -72,3 +73,4 @@ public:
 };
 
 #endif // BORNAGAIN_SAMPLE_STANDARDSAMPLES_TWODIMLATTICEBUILDER_H
+#endif // USER_API
diff --git a/Sample/StandardSamples/TwoLayerRoughnessBuilder.h b/Sample/StandardSamples/TwoLayerRoughnessBuilder.h
index bebd5f18589a7000a492e7d3112a824b5de1259c..7056e43f7b061f2ffc195b8af1c8d65688f92580 100644
--- a/Sample/StandardSamples/TwoLayerRoughnessBuilder.h
+++ b/Sample/StandardSamples/TwoLayerRoughnessBuilder.h
@@ -16,6 +16,7 @@
 #error no need to expose this header to Swig
 #endif
 
+#ifndef USER_API
 #ifndef BORNAGAIN_SAMPLE_STANDARDSAMPLES_TWOLAYERROUGHNESSBUILDER_H
 #define BORNAGAIN_SAMPLE_STANDARDSAMPLES_TWOLAYERROUGHNESSBUILDER_H
 
@@ -30,3 +31,4 @@ public:
 };
 
 #endif // BORNAGAIN_SAMPLE_STANDARDSAMPLES_TWOLAYERROUGHNESSBUILDER_H
+#endif // USER_API
diff --git a/Tests/Functional/Core/Fitting/FitTests.cpp b/Tests/Functional/Core/Fitting/FitTests.cpp
index 0cdc5c2bb8ca914081224ae5a59f34b653beea13..0285653423a65eeaaf50871ba7046083971e1772 100644
--- a/Tests/Functional/Core/Fitting/FitTests.cpp
+++ b/Tests/Functional/Core/Fitting/FitTests.cpp
@@ -85,6 +85,6 @@ TEST_F(Fitting, MultipleSpecFittingTest) {
     EXPECT_TRUE(run("Minuit2", "Migrad", "MultipleSpecPlan"));
 }
 
-TEST_F(Fitting, OffSpecFitTest) {
-    EXPECT_TRUE(run("Minuit2", "Migrad", "OffSpecPlan"));
+TEST_F(Fitting, OffSpecularFitTest) {
+    EXPECT_TRUE(run("Minuit2", "Migrad", "OffSpecularPlan"));
 }
diff --git a/Tests/Functional/Core/Fitting/PlanCases.cpp b/Tests/Functional/Core/Fitting/PlanCases.cpp
index 63b60720d28ec448ab213b9d2ab5f657ded3ccd0..211627665c9735285a4d69931b257b595cef17c6 100644
--- a/Tests/Functional/Core/Fitting/PlanCases.cpp
+++ b/Tests/Functional/Core/Fitting/PlanCases.cpp
@@ -127,9 +127,9 @@ std::unique_ptr<FitObjective> MultipleSpecPlan::createFitObjective() const {
 
 // ----------------------------------------------------------------------------
 
-OffSpecPlan::OffSpecPlan() : Plan("OffSpecPlan") {
+OffSpecularPlan::OffSpecularPlan() : Plan("OffSpecularPlan") {
     setBuilderName("ResonatorBuilder");
-    setSimulationName("OffSpecMini");
+    setSimulationName("OffSpecularMini");
     addParameter(
         Parameter("ti_thickness", 12.0 * nm, AttLimits::limited(11.5 * nm, 14.0 * nm), 0.1 * nm),
         13.0 * nm);
diff --git a/Tests/Functional/Core/Fitting/PlanCases.h b/Tests/Functional/Core/Fitting/PlanCases.h
index f1ea57480eb69ed519ed11a7f635311c2c660e05..f35ae32678550cc74c77fefeab4c76d125f0b0b3 100644
--- a/Tests/Functional/Core/Fitting/PlanCases.h
+++ b/Tests/Functional/Core/Fitting/PlanCases.h
@@ -79,10 +79,10 @@ protected:
 
 //! Fit for off-specular experiment
 
-class OffSpecPlan : public Plan {
+class OffSpecularPlan : public Plan {
 public:
-    OffSpecPlan();
-    ~OffSpecPlan() override = default;
+    OffSpecularPlan();
+    ~OffSpecularPlan() override = default;
 };
 
 #endif // BORNAGAIN_TESTS_FUNCTIONAL_CORE_FITTING_PLANCASES_H
diff --git a/Tests/Functional/Core/Fitting/PlanFactory.cpp b/Tests/Functional/Core/Fitting/PlanFactory.cpp
index 3a72fea24f1188b00f4bd679abe454afb6d1fcca..6bc03c0bb5af3a497da0d804b689a8f9d7ccc52b 100644
--- a/Tests/Functional/Core/Fitting/PlanFactory.cpp
+++ b/Tests/Functional/Core/Fitting/PlanFactory.cpp
@@ -25,5 +25,5 @@ PlanFactory::PlanFactory() {
     registerItem("SpecularPlan", create_new<SpecularPlan>);
     registerItem("SpecularPlanQ", create_new<SpecularPlanQ>);
     registerItem("MultipleSpecPlan", create_new<MultipleSpecPlan>);
-    registerItem("OffSpecPlan", create_new<OffSpecPlan>);
+    registerItem("OffSpecularPlan", create_new<OffSpecularPlan>);
 }
diff --git a/Tests/Functional/GUI/Translate/GUITranslationTest.cpp b/Tests/Functional/GUI/Translate/GUITranslationTest.cpp
index 62d036edf8b233a1b60afda5663cffba859ed4ff..f6932385e74d20af235513220e788c71e13ad45d 100644
--- a/Tests/Functional/GUI/Translate/GUITranslationTest.cpp
+++ b/Tests/Functional/GUI/Translate/GUITranslationTest.cpp
@@ -51,7 +51,7 @@ const QVector<QPair<QStringList, QStringList>> black_list{
      {""},
      {"Sigma factor", "MaterialRefractiveData", "MaterialSLDData", MaterialItem::P_MAGNETIZATION}},
     {// Instrument scope
-     {"GISASInstrument", "OffSpecInstrument", "SpecularInstrument"},
+     {"GISASInstrument", "OffSpecularInstrument", "SpecularInstrument"},
      {// Distribution types
       "DistributionGate", "DistributionLorentz", "DistributionGaussian", "DistributionLogNormal",
       "DistributionCosine", "DistributionTrapezoid",
@@ -59,7 +59,7 @@ const QVector<QPair<QStringList, QStringList>> black_list{
       // Detector axes
       SphericalDetectorItem::P_PHI_AXIS, SphericalDetectorItem::P_ALPHA_AXIS,
       RectangularDetectorItem::P_X_AXIS, RectangularDetectorItem::P_Y_AXIS,
-      OffSpecInstrumentItem::P_ALPHA_AXIS,
+      OffSpecularInstrumentItem::P_ALPHA_AXIS,
 
       // Rectangular detector positioning
       RectangularDetectorItem::P_ALIGNMENT, RectangularDetectorItem::P_NORMAL,
diff --git a/Tests/Functional/Python/PyCore/intensitydata_io.py b/Tests/Functional/Python/PyCore/intensitydata_io.py
index d11811068d2c1daa1e9d61dcc9abfda6fb6dba38..476285466cdae0c82773c72972283e1a7ba3ee22 100644
--- a/Tests/Functional/Python/PyCore/intensitydata_io.py
+++ b/Tests/Functional/Python/PyCore/intensitydata_io.py
@@ -2,7 +2,7 @@
 
 import math, numpy, os, sys, time, unittest
 import bornagain as ba
-from bornagain import deg, deg2rad, rad2deg
+from bornagain import deg
 
 
 def fill_data(data):
@@ -35,11 +35,11 @@ def get_boundaries_flat_in_sin(nbins, start, end):
     Returns flat_in_sin binning of angle axis
     """
     result = []
-    start_sin = math.sin(deg2rad(start))
-    end_sin = math.sin(deg2rad(end))
+    start_sin = math.sin(start)
+    end_sin = math.sin(end)
     step = (end_sin - start_sin)/nbins
     for i in range(0, nbins + 1):
-        result.append(rad2deg(math.asin(start_sin + step*i)))
+        result.append(math.degrees(math.asin(start_sin + step*i)))
     return result
 
 
@@ -78,7 +78,7 @@ class OutputDataIOTest(unittest.TestCase):
         data = ba.IntensityData()
         data.addAxis(
             ba.VariableBinAxis("axis0", 10,
-                               get_boundaries_flat_in_sin(10, -5.0, 5.0)))
+                               get_boundaries_flat_in_sin(10, -5*deg, 5*deg)))
         fill_data(data)
         ba.IntensityDataIOFactory.writeOutputData(data, "tmp.int")
         newdata = ba.IntensityDataIOFactory.readOutputData("tmp.int")
@@ -88,10 +88,10 @@ class OutputDataIOTest(unittest.TestCase):
         data = ba.IntensityData()
         data.addAxis(
             ba.VariableBinAxis("axis0", 10,
-                               get_boundaries_flat_in_sin(10, -5.0, 5.0)))
+                               get_boundaries_flat_in_sin(10, -5*deg, 5*deg)))
         data.addAxis(
             ba.VariableBinAxis("axis1", 3,
-                               get_boundaries_flat_in_sin(3, 0.0, 2.0)))
+                               get_boundaries_flat_in_sin(3, 0*deg, 2*deg)))
         fill_data(data)
         ba.IntensityDataIOFactory.writeOutputData(data, "tmp.int")
         newdata = ba.IntensityDataIOFactory.readOutputData("tmp.int")
@@ -102,7 +102,7 @@ class OutputDataIOTest(unittest.TestCase):
         data.addAxis(ba.FixedBinAxis("axis0", 10, -5.0, 5.0))
         data.addAxis(
             ba.VariableBinAxis("axis1", 3,
-                               get_boundaries_flat_in_sin(3, 0.0, 2.0)))
+                               get_boundaries_flat_in_sin(3, 0*deg, 2*deg)))
         fill_data(data)
         ba.IntensityDataIOFactory.writeOutputData(data, "tmp.int")
         newdata = ba.IntensityDataIOFactory.readOutputData("tmp.int")
diff --git a/Tests/Functional/Python/PyCore/polmagcylinders2.py b/Tests/Functional/Python/PyCore/polmagcylinders2.py
index 3e969efa3c3bc0a638e0e72de106e7bd0b09d806..783a446486eddbacd76495553eb887d30eadd645 100644
--- a/Tests/Functional/Python/PyCore/polmagcylinders2.py
+++ b/Tests/Functional/Python/PyCore/polmagcylinders2.py
@@ -45,7 +45,7 @@ def getSimulationIntensity(rho_beam, efficiency):
     zplus = kvector_t(0.0, 0.0, 1.0)
     simulation.setAnalyzerProperties(zplus, efficiency, 0.5)
     simulation.setBeamParameters(1.0*angstrom, 0.2*deg, 0.0*deg)
-    simulation.setBeamPolarization(rho_beam)
+    simulation.beam().setPolarization(rho_beam)
     simulation.setSample(multi_layer)
     simulation.beam().setIntensity(1e9)
     simulation.runSimulation()
diff --git a/Tests/Functional/Std/StandardTests.h b/Tests/Functional/Std/StandardTests.h
index 521d9b1c90eca3d2c5a2deb5d6a7406e1eea1f51..401991a016c36eeb39bb9d1093ae5e4056b3b67c 100644
--- a/Tests/Functional/Std/StandardTests.h
+++ b/Tests/Functional/Std/StandardTests.h
@@ -367,7 +367,7 @@ TEST_F(Std, RelativeResolutionTOF) {
 #ifndef PYTHON_STD_TEST
 
 TEST_F(Std, OffSpecularResonator) {
-    EXPECT_TRUE(run("OffSpecularResonator", "OffSpecMini", "ResonatorBuilder", 1e-10));
+    EXPECT_TRUE(run("OffSpecularResonator", "OffSpecularMini", "ResonatorBuilder", 1e-10));
 }
 
 TEST_F(Std, FormFactorsWithAbsorption) {
diff --git a/Tests/Performance/Core/Mesocrystal.cpp b/Tests/Performance/Core/Mesocrystal.cpp
index fa0e9ffa2934ab8167a0543d5b8ed8575d383f3a..602e9ed5b83d38f6c361731fa1330629b1555236 100644
--- a/Tests/Performance/Core/Mesocrystal.cpp
+++ b/Tests/Performance/Core/Mesocrystal.cpp
@@ -195,7 +195,7 @@ int main() {
     simulation.setDetector(*detector);
 
     simulation.setBeamParameters(1.77 * Units::angstrom, 0.4 * Units::deg, 0.0);
-    simulation.setBeamIntensity(6.1e+12);
+    simulation.beam().setIntensity(6.1e+12);
 
     std::shared_ptr<ISampleBuilder> builder(new MesoCrystalPerformanceBuilder);
     simulation.setSampleBuilder(builder);
diff --git a/Tests/UnitTests/Core/Fresnel/DepthProbeSimulationTest.cpp b/Tests/UnitTests/Core/Fresnel/DepthProbeSimulationTest.cpp
index d647752596219e792f2cd20e55bebb67f0b5f9d5..a7b7a66eb87eb1c01ebd7349c9ef3f43b7dc03ec 100644
--- a/Tests/UnitTests/Core/Fresnel/DepthProbeSimulationTest.cpp
+++ b/Tests/UnitTests/Core/Fresnel/DepthProbeSimulationTest.cpp
@@ -104,7 +104,7 @@ TEST_F(DepthProbeSimulationTest, SetBeamParameters) {
 
     checkBeamState(sim);
 
-    sim.setBeamIntensity(2.0);
+    sim.beam().setIntensity(2.0);
     EXPECT_EQ(2.0, beam.intensity());
 
     EXPECT_THROW(sim.setBeamParameters(1.0, 10, -2.0, 3.0), std::runtime_error);
diff --git a/Tests/UnitTests/Core/Fresnel/SpecularSimulationTest.cpp b/Tests/UnitTests/Core/Fresnel/SpecularSimulationTest.cpp
index 0956f0c5146b8c0c701448eb07fb5365bf51798d..2e2f6edd10d9ec639840af31fefc0925f711a7ff 100644
--- a/Tests/UnitTests/Core/Fresnel/SpecularSimulationTest.cpp
+++ b/Tests/UnitTests/Core/Fresnel/SpecularSimulationTest.cpp
@@ -91,7 +91,7 @@ TEST_F(SpecularSimulationTest, SetAngularScan) {
 
     checkBeamState(sim);
 
-    sim.setBeamIntensity(2.0);
+    sim.beam().setIntensity(2.0);
     EXPECT_EQ(2.0, beam.intensity());
 
     AngularSpecScan scan2(1.0, 10, 1.0 * Units::deg, 10.0 * Units::deg);
@@ -139,7 +139,7 @@ TEST_F(SpecularSimulationTest, SetQScan) {
 
     checkBeamState(sim);
 
-    sim.setBeamIntensity(2.0);
+    sim.beam().setIntensity(2.0);
     EXPECT_EQ(2.0, beam.intensity());
 
     QSpecScan scan2(10, 1.0, 10.0);
diff --git a/Tests/UnitTests/Core/Other/SpectrumTest.cpp b/Tests/UnitTests/Core/Other/SpectrumTest.cpp
index 61a29e150f42c0d02a775c4545a34ac0a093c25c..ccac8f1e97b002617c436a25e401a15a36cfabec 100644
--- a/Tests/UnitTests/Core/Other/SpectrumTest.cpp
+++ b/Tests/UnitTests/Core/Other/SpectrumTest.cpp
@@ -1,4 +1,4 @@
-#include "Device/Instrument/SpectrumUtils.h"
+#include "Device/Histo/ImageUtils.h"
 #include "Tests/GTestWrapper/google_test.h"
 #include <iostream>
 #include <tspectrum.h>
@@ -33,7 +33,7 @@ TEST_F(SpectrumTest, histogramPeaks) {
 
     EXPECT_EQ(hist.binContent(4, 2), 10.0);
 
-    auto peaks = SpectrumUtils::FindPeaks(hist, 3, "nomarkov", 0.1);
+    auto peaks = ImageUtils::FindPeaks(hist, 3, "nomarkov", 0.1);
     EXPECT_NEAR(peaks[0].first, 55.0, 0.01);  // center of histogram x-axis bin with index=4
     EXPECT_NEAR(peaks[0].second, 25.0, 0.01); // center of histogram y-axis bin with index=2
 }
diff --git a/Wrap/Python/plot_utils.py b/Wrap/Python/plot_utils.py
index 6b569d757f72ee5de8ad7934d57b9876cfc1a151..d451cd7ddddf09255a4098dc17ead7c974d1b0aa 100644
--- a/Wrap/Python/plot_utils.py
+++ b/Wrap/Python/plot_utils.py
@@ -145,7 +145,7 @@ def plot_histogram(hist, **kwargs):
 def plot_colormap(result, **kwargs):
     """
     Plots intensity data as color map
-    :param result: SimulationResult from GISAS/OffSpecSimulation
+    :param result: SimulationResult from GISAS/OffSpecularSimulation
     :param zmin: Min value on amplitude's color bar
     :param zmax: Max value on amplitude's color bar
     """
@@ -198,7 +198,7 @@ def plot_specular_simulation_result(result, **kwargs):
 def plot_simulation_result(result, **kwargs):
     """
     Draws simulation result and (optionally) shows the plot.
-    :param result_: SimulationResult object obtained from GISAS/OffSpec/SpecularSimulation
+    :param result_: SimulationResult object obtained from GISAS/OffSpecular/SpecularSimulation
     :param intensity_min: Min value on amplitude's axis or color bar
     :param intensity_max: Max value on amplitude's axis or color bar
     :param units: units for plot axes
diff --git a/Wrap/Swig/DoxyfileSwig.in b/Wrap/Swig/DoxyfileSwig.in
index 82a483d43e88713cd556603541c5c5908cc3d598..16ea2c8bea06ea79e9790c0d14ab4b5a704457e6 100644
--- a/Wrap/Swig/DoxyfileSwig.in
+++ b/Wrap/Swig/DoxyfileSwig.in
@@ -880,7 +880,7 @@ RECURSIVE              = YES
 # Note that relative paths are relative to the directory from which doxygen is
 # run.
 
-EXCLUDE                =
+EXCLUDE                = 3rdParty
 
 # The EXCLUDE_SYMLINKS tag can be used to select whether or not files or
 # directories that are symbolic links (a Unix file system feature) are excluded
@@ -896,7 +896,7 @@ EXCLUDE_SYMLINKS       = NO
 # Note that the wildcards are matched against the file with absolute path, so to
 # exclude all test directories for example use the pattern */test/*
 
-EXCLUDE_PATTERNS       = */PythonAPI/*
+EXCLUDE_PATTERNS       =
 
 # The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names
 # (namespaces, classes, functions, etc.) that should be excluded from the
diff --git a/Wrap/Swig/libBornAgainBase.i b/Wrap/Swig/libBornAgainBase.i
index 2497f9d26aa94c173e774a4ef48f4f7b7315e677..4d280f2088a96d071e9b0304d4c6331dbad56ac5 100644
--- a/Wrap/Swig/libBornAgainBase.i
+++ b/Wrap/Swig/libBornAgainBase.i
@@ -25,10 +25,10 @@
 #include "Base/Types/Complex.h"
 #include "Base/Types/ICloneable.h"
 
-#include "Base/Utils/ThreadInfo.h"
-
 #include "Base/Const/Units.h"
 
+#include "Base/Utils/ThreadInfo.h"
+
 #include "Base/Vector/BasicVector3D.h"
 #include "Base/Vector/Vectors3D.h"
 #include "Base/Vector/Direction.h"
diff --git a/Wrap/Swig/libBornAgainCore.i b/Wrap/Swig/libBornAgainCore.i
index 69114fd852ee5a329f8089a88f44df97c4548639..145631a3fa34bf4c124fae22c3da1a50653743e6 100644
--- a/Wrap/Swig/libBornAgainCore.i
+++ b/Wrap/Swig/libBornAgainCore.i
@@ -63,7 +63,6 @@
 #include "Core/Computation/PoissonNoiseBackground.h"
 #include "Core/Export/ExportToPython.h"
 #include "Core/Fitting/FitObjective.h"
-#include "Core/Fitting/IObserver.h"
 #include "Core/Fitting/IterationInfo.h"
 #include "Core/Fitting/PyFittingCallbacks.h"
 #include "Core/Scan/AngularSpecScan.h"
@@ -72,7 +71,7 @@
 #include "Core/Simulation/GISASSimulation.h"
 #include "Core/Simulation/ISimulation.h"
 #include "Core/Simulation/ISimulation2D.h"
-#include "Core/Simulation/OffSpecSimulation.h"
+#include "Core/Simulation/OffSpecularSimulation.h"
 #include "Core/Simulation/SimulationFactory.h"
 #include "Core/Simulation/SpecularSimulation.h"
 %}
@@ -99,7 +98,6 @@
 
 %include "BAVersion.h"
 
-%include "Core/Fitting/IObserver.h"
 %include "Core/Fitting/IterationInfo.h"
 %include "Core/Fitting/PyFittingCallbacks.h"
 
@@ -112,7 +110,7 @@
 %include "Core/Simulation/GISASSimulation.h"
 %include "Core/Simulation/DepthProbeSimulation.h"
 %include "Core/Simulation/SpecularSimulation.h"
-%include "Core/Simulation/OffSpecSimulation.h"
+%include "Core/Simulation/OffSpecularSimulation.h"
 
 %include "Core/Computation/IBackground.h"
 %include "Core/Computation/ConstantBackground.h"
diff --git a/Wrap/Swig/libBornAgainDevice.i b/Wrap/Swig/libBornAgainDevice.i
index e795c309a36a34ff144437e76514bb21c3dcdfbb..98c2a2038065f966742db8d85afa93acff1d56b7 100644
--- a/Wrap/Swig/libBornAgainDevice.i
+++ b/Wrap/Swig/libBornAgainDevice.i
@@ -53,7 +53,7 @@
 #include "Device/Instrument/IChiSquaredModule.h"
 #include "Device/Instrument/IntensityDataFunctions.h"
 #include "Device/Instrument/PyArrayImportUtils.h"
-#include "Device/Instrument/SpectrumUtils.h"
+#include "Device/Histo/ImageUtils.h"
 #include "Device/Instrument/VarianceFunctions.h"
 #include "Device/Intensity/IIntensityFunction.h"
 #include "Device/Intensity/IIntensityFunction.h"
@@ -114,7 +114,7 @@
 %include "Device/Instrument/ChiSquaredModule.h"
 %include "Device/Instrument/IntensityDataFunctions.h"
 %include "Device/Instrument/PyArrayImportUtils.h"
-%include "Device/Instrument/SpectrumUtils.h"
+%include "Device/Histo/ImageUtils.h"
 %include "Device/Instrument/VarianceFunctions.h"
 
 %include "Device/Unit/IUnitConverter.h"
diff --git a/auto/Wrap/doxygenBase.i b/auto/Wrap/doxygenBase.i
index b9bb4d6f0f66217816bb62387d10017d5bda3046..b6beb3d2abaab97ebbe70e03cf7b0bb42cd094b3 100644
--- a/auto/Wrap/doxygenBase.i
+++ b/auto/Wrap/doxygenBase.i
@@ -4,7 +4,7 @@
 // File: classBasicVector3D.xml
 %feature("docstring") BasicVector3D "
 
-Forked from CLHEP/Geometry by E. Chernyaev Evgueni.Tcherniaev@cern.ch, then reworked beyond recognition. Removed split of point and vector semantics. Transforms are relegated to a separate class  Transform3D. Three-dimensional vector template, for use with integer, double, or complex components.
+Three-dimensional vector template, for use with integer, double, or complex components.
 
 C++ includes: BasicVector3D.h
 ";
@@ -99,7 +99,7 @@ Returns squared sine of polar angle.
 Returns unit vector in direction of this. Throws for null vector. 
 ";
 
-%feature("docstring")  BasicVector3D::complex "BasicVector3D<std::complex<double> > BasicVector3D< T >::complex() const
+%feature("docstring")  BasicVector3D::complex "BasicVector3D<complex_t> BasicVector3D< T >::complex() const
 
 Returns this, trivially converted to complex type. 
 ";
@@ -153,15 +153,6 @@ Returns result of rotation around z-axis.
 Returns result of rotation around the axis specified by another vector. 
 ";
 
-%feature("docstring")  BasicVector3D::conj "BasicVector3D< complex_t > BasicVector3D< complex_t >::conj() const
-";
-
-%feature("docstring")  BasicVector3D::real "BasicVector3D< double > BasicVector3D< complex_t >::real() const
-";
-
-%feature("docstring")  BasicVector3D::unit "BasicVector3D< complex_t > BasicVector3D< complex_t >::unit() const
-";
-
 
 // File: structBin1D.xml
 %feature("docstring") Bin1D "";
@@ -390,7 +381,12 @@ Increments inner counter; at regular intervals updates progress handler.
 
 
 // File: classDirection.xml
-%feature("docstring") Direction "";
+%feature("docstring") Direction "
+
+A direction in three-dimensional space.
+
+C++ includes: Direction.h
+";
 
 %feature("docstring")  Direction::Direction "Direction::Direction(double alpha, double phi)
 ";
diff --git a/auto/Wrap/doxygenCore.i b/auto/Wrap/doxygenCore.i
index d0749185511c3e8b5f18dd03f6f77d8cd4255913..1e1f4cd81c8728f584e7b6d1bdf5d6ec620537b8 100644
--- a/auto/Wrap/doxygenCore.i
+++ b/auto/Wrap/doxygenCore.i
@@ -853,20 +853,20 @@ C++ includes: IComputation.h
 // File: classIObservable.xml
 %feature("docstring") IObservable "
 
-Observable interface from Observer pattern
+Observable interface from Observer pattern. Shared pointer is used when passing these objects from Python to C++.
 
 C++ includes: IObserver.h
 ";
 
-%feature("docstring")  IObservable::~IObservable "IObservable::~IObservable()
+%feature("docstring")  IObservable::~IObservable "virtual IObservable::~IObservable()=default
 ";
 
-%feature("docstring")  IObservable::attachObserver "void IObservable::attachObserver(observer_t obj)
+%feature("docstring")  IObservable::attachObserver "virtual void IObservable::attachObserver(std::shared_ptr< IObserver > obj)
 
 attach observer to the list of observers 
 ";
 
-%feature("docstring")  IObservable::notifyObservers "void IObservable::notifyObservers()
+%feature("docstring")  IObservable::notifyObservers "virtual void IObservable::notifyObservers()
 
 notify observers about change in status 
 ";
@@ -880,7 +880,7 @@ Observer interface from Observer pattern.
 C++ includes: IObserver.h
 ";
 
-%feature("docstring")  IObserver::~IObserver "IObserver::~IObserver()
+%feature("docstring")  IObserver::~IObserver "virtual IObserver::~IObserver()=default
 ";
 
 %feature("docstring")  IObserver::notify "virtual void IObserver::notify(IObservable *subject)=0
@@ -892,7 +892,7 @@ method which is used by observable subject to notify change in status
 // File: classISimulation.xml
 %feature("docstring") ISimulation "
 
-Abstract base class of OffSpecularSimulation,  GISASSimulation and  SpecularSimulation. Holds the common infrastructure to run a simulation: multithreading, batch processing, weighting over parameter distributions, ...
+Abstract base class of  OffSpecularSimulation,  GISASSimulation and  SpecularSimulation. Holds the common infrastructure to run a simulation: multithreading, batch processing, weighting over parameter distributions, ...
 
 C++ includes: ISimulation.h
 ";
@@ -947,14 +947,6 @@ Run a simulation in a MPI environment.
 %feature("docstring")  ISimulation::detector "const IDetector& ISimulation::detector() const
 ";
 
-%feature("docstring")  ISimulation::setBeamIntensity "void ISimulation::setBeamIntensity(double intensity)
-";
-
-%feature("docstring")  ISimulation::setBeamPolarization "void ISimulation::setBeamPolarization(const kvector_t bloch_vector)
-
-Sets the beam polarization according to the given Bloch vector. 
-";
-
 %feature("docstring")  ISimulation::setDetectorResolutionFunction "void ISimulation::setDetectorResolutionFunction(const IResolutionFunction2D &resolution_function)
 ";
 
@@ -1028,7 +1020,7 @@ Convert user data to SimulationResult object for later drawing in various axes u
 // File: classISimulation2D.xml
 %feature("docstring") ISimulation2D "
 
-Abstract base class of OffSpecularSimulation and  GISASSimulation. Holds the common implementations for simulations with a 2D detector
+Abstract base class of  OffSpecularSimulation and  GISASSimulation. Holds the common implementations for simulations with a 2D detector
 
 C++ includes: ISimulation2D.h
 ";
@@ -1456,53 +1448,53 @@ Returns a copy of the normalization function used.
 // File: classFitObserver_1_1ObserverData.xml
 
 
-// File: classOffSpecSimulation.xml
-%feature("docstring") OffSpecSimulation "
+// File: classOffSpecularSimulation.xml
+%feature("docstring") OffSpecularSimulation "
 
 Main class to run an off-specular simulation.
 
-C++ includes: OffSpecSimulation.h
+C++ includes: OffSpecularSimulation.h
 ";
 
-%feature("docstring")  OffSpecSimulation::OffSpecSimulation "OffSpecSimulation::OffSpecSimulation(const Beam &beam, const MultiLayer &sample, const IDetector &detector)
+%feature("docstring")  OffSpecularSimulation::OffSpecularSimulation "OffSpecularSimulation::OffSpecularSimulation(const Beam &beam, const MultiLayer &sample, const IDetector &detector)
 ";
 
-%feature("docstring")  OffSpecSimulation::OffSpecSimulation "OffSpecSimulation::OffSpecSimulation()
+%feature("docstring")  OffSpecularSimulation::OffSpecularSimulation "OffSpecularSimulation::OffSpecularSimulation()
 ";
 
-%feature("docstring")  OffSpecSimulation::~OffSpecSimulation "OffSpecSimulation::~OffSpecSimulation() override
+%feature("docstring")  OffSpecularSimulation::~OffSpecularSimulation "OffSpecularSimulation::~OffSpecularSimulation() override
 ";
 
-%feature("docstring")  OffSpecSimulation::clone "OffSpecSimulation* OffSpecSimulation::clone() const override
+%feature("docstring")  OffSpecularSimulation::clone "OffSpecularSimulation* OffSpecularSimulation::clone() const override
 ";
 
-%feature("docstring")  OffSpecSimulation::accept "void OffSpecSimulation::accept(INodeVisitor *visitor) const override
+%feature("docstring")  OffSpecularSimulation::accept "void OffSpecularSimulation::accept(INodeVisitor *visitor) const override
 ";
 
-%feature("docstring")  OffSpecSimulation::prepareSimulation "void OffSpecSimulation::prepareSimulation() override
+%feature("docstring")  OffSpecularSimulation::prepareSimulation "void OffSpecularSimulation::prepareSimulation() override
 
 Put into a clean state for running a simulation. 
 ";
 
-%feature("docstring")  OffSpecSimulation::result "SimulationResult OffSpecSimulation::result() const override
+%feature("docstring")  OffSpecularSimulation::result "SimulationResult OffSpecularSimulation::result() const override
 
 Returns the results of the simulation in a format that supports unit conversion and export to numpy arrays 
 ";
 
-%feature("docstring")  OffSpecSimulation::setBeamParameters "void OffSpecSimulation::setBeamParameters(double wavelength, const IAxis &alpha_axis, double phi_i)
+%feature("docstring")  OffSpecularSimulation::setBeamParameters "void OffSpecularSimulation::setBeamParameters(double wavelength, const IAxis &alpha_axis, double phi_i)
 
 Sets beam parameters from here (forwarded to Instrument) 
 ";
 
-%feature("docstring")  OffSpecSimulation::beamAxis "const IAxis * OffSpecSimulation::beamAxis() const
+%feature("docstring")  OffSpecularSimulation::beamAxis "const IAxis * OffSpecularSimulation::beamAxis() const
 
 Returns axis of the beam. 
 ";
 
-%feature("docstring")  OffSpecSimulation::createUnitConverter "std::unique_ptr< IUnitConverter > OffSpecSimulation::createUnitConverter() const
+%feature("docstring")  OffSpecularSimulation::createUnitConverter "std::unique_ptr< IUnitConverter > OffSpecularSimulation::createUnitConverter() const
 ";
 
-%feature("docstring")  OffSpecSimulation::intensityMapSize "size_t OffSpecSimulation::intensityMapSize() const override
+%feature("docstring")  OffSpecularSimulation::intensityMapSize "size_t OffSpecularSimulation::intensityMapSize() const override
 
 Returns the total number of the intensity values in the simulation result. 
 ";
@@ -2301,7 +2293,7 @@ Returns default units to convert to.
 ";
 
 
-// File: namespace_0d101.xml
+// File: namespace_0d100.xml
 
 
 // File: namespace_0d15.xml
@@ -2319,40 +2311,40 @@ Returns default units to convert to.
 // File: namespace_0d47.xml
 
 
-// File: namespace_0d56.xml
+// File: namespace_0d55.xml
 
 
-// File: namespace_0d58.xml
+// File: namespace_0d57.xml
 
 
-// File: namespace_0d62.xml
+// File: namespace_0d61.xml
 
 
-// File: namespace_0d66.xml
+// File: namespace_0d65.xml
 
 
-// File: namespace_0d68.xml
+// File: namespace_0d67.xml
 
 
-// File: namespace_0d70.xml
+// File: namespace_0d69.xml
 
 
-// File: namespace_0d72.xml
+// File: namespace_0d71.xml
 
 
-// File: namespace_0d77.xml
+// File: namespace_0d76.xml
 
 
-// File: namespace_0d79.xml
+// File: namespace_0d78.xml
 
 
-// File: namespace_0d83.xml
+// File: namespace_0d82.xml
 
 
-// File: namespace_0d93.xml
+// File: namespace_0d92.xml
 
 
-// File: namespace_0d95.xml
+// File: namespace_0d94.xml
 
 
 // File: namespaceExportToPython.xml
@@ -2687,7 +2679,7 @@ GISAS simulation with an extra long wavelength.
 %feature("docstring")  StandardSimulations::BasicSpecularQMP "SpecularSimulation * StandardSimulations::BasicSpecularQMP()
 ";
 
-%feature("docstring")  StandardSimulations::MiniOffSpec "OffSpecSimulation * StandardSimulations::MiniOffSpec()
+%feature("docstring")  StandardSimulations::MiniOffSpecular "OffSpecularSimulation * StandardSimulations::MiniOffSpecular()
 ";
 
 %feature("docstring")  StandardSimulations::BasicDepthProbe "DepthProbeSimulation * StandardSimulations::BasicDepthProbe()
@@ -2865,9 +2857,6 @@ Helper factory function to use in  GISASSimulation. Depending on the type of det
 // File: FitTypes_8h.xml
 
 
-// File: IObserver_8cpp.xml
-
-
 // File: IObserver_8h.xml
 
 
@@ -2976,10 +2965,10 @@ Helper factory function to use in  GISASSimulation. Depending on the type of det
 // File: MPISimulation_8h.xml
 
 
-// File: OffSpecSimulation_8cpp.xml
+// File: OffSpecularSimulation_8cpp.xml
 
 
-// File: OffSpecSimulation_8h.xml
+// File: OffSpecularSimulation_8h.xml
 
 
 // File: SimulationFactory_8cpp.xml
diff --git a/auto/Wrap/doxygenDevice.i b/auto/Wrap/doxygenDevice.i
index c1a20b8f1ca65a87e951a4fdea27fb9a59aaf111..741d670165914644ad1f9aa6862432e2ee8d6443 100644
--- a/auto/Wrap/doxygenDevice.i
+++ b/auto/Wrap/doxygenDevice.i
@@ -1471,14 +1471,6 @@ C++ includes: Instrument.h
 Sets the beam wavelength and incoming angles. 
 ";
 
-%feature("docstring")  Instrument::setBeamIntensity "void Instrument::setBeamIntensity(double intensity)
-";
-
-%feature("docstring")  Instrument::setBeamPolarization "void Instrument::setBeamPolarization(const kvector_t bloch_vector)
-
-Sets the beam's polarization according to the given Bloch vector. 
-";
-
 %feature("docstring")  Instrument::getDetector "const IDetector * Instrument::getDetector() const
 ";
 
@@ -1793,7 +1785,7 @@ C++ includes: SimpleUnitConverters.h
 // File: classOutputData.xml
 %feature("docstring") OutputData "
 
-Template class to store data of any type in multi-dimensional space.
+Templated class to store data of type double or  CumulativeValue in multi-dimensional space.
 
 C++ includes: OutputData.h
 ";
@@ -1830,11 +1822,6 @@ C++ includes: OutputData.h
 returns axis with given serial number 
 ";
 
-%feature("docstring")  OutputData::axis "const IAxis & OutputData< T >::axis(const std::string &axis_name) const
-
-returns axis with given name 
-";
-
 %feature("docstring")  OutputData::rank "size_t OutputData< T >::rank() const
 
 Returns number of dimensions. 
@@ -3029,10 +3016,10 @@ Returns true if area defined by two bins is inside or on border of polygon (more
 // File: namespace_0d35.xml
 
 
-// File: namespace_0d58.xml
+// File: namespace_0d60.xml
 
 
-// File: namespace_0d64.xml
+// File: namespace_0d66.xml
 
 
 // File: namespaceArrayUtils.xml
@@ -3073,10 +3060,10 @@ Creates 2D vector from  OutputData.
 %feature("docstring")  AxisNames::InitRectangularAxis1 "std::map< Axes::Units, std::string > AxisNames::InitRectangularAxis1()
 ";
 
-%feature("docstring")  AxisNames::InitOffSpecAxis0 "std::map< Axes::Units, std::string > AxisNames::InitOffSpecAxis0()
+%feature("docstring")  AxisNames::InitOffSpecularAxis0 "std::map< Axes::Units, std::string > AxisNames::InitOffSpecularAxis0()
 ";
 
-%feature("docstring")  AxisNames::InitOffSpecAxis1 "std::map< Axes::Units, std::string > AxisNames::InitOffSpecAxis1()
+%feature("docstring")  AxisNames::InitOffSpecularAxis1 "std::map< Axes::Units, std::string > AxisNames::InitOffSpecularAxis1()
 ";
 
 %feature("docstring")  AxisNames::InitSpecAxis "std::map< Axes::Units, std::string > AxisNames::InitSpecAxis()
@@ -3151,6 +3138,13 @@ Parse double values from string to vector of double.
 ";
 
 
+// File: namespaceImageUtils.xml
+%feature("docstring")  ImageUtils::FindPeaks "std::vector< std::pair< double, double > > ImageUtils::FindPeaks(const Histogram2D &hist, double sigma=2, const std::string &option={}, double threshold=0.05)
+
+Returns vector of peak center coordinates, for peaks in given histogram. 
+";
+
+
 // File: namespaceIntensityDataFunctions.xml
 %feature("docstring")  IntensityDataFunctions::RelativeDifference "double IntensityDataFunctions::RelativeDifference(const SimulationResult &dat, const SimulationResult &ref)
 
@@ -3238,11 +3232,6 @@ for importing 2D array of doubles from python into  OutputData
 ";
 
 
-// File: namespaceSpectrumUtils.xml
-%feature("docstring")  SpectrumUtils::FindPeaks "std::vector< std::pair< double, double > > SpectrumUtils::FindPeaks(const Histogram2D &hist, double sigma=2, const std::string &option={}, double threshold=0.05)
-";
-
-
 // File: Beam_8cpp.xml
 
 
@@ -3408,6 +3397,12 @@ make Swappable
 // File: IHistogram_8h.xml
 
 
+// File: ImageUtils_8cpp.xml
+
+
+// File: ImageUtils_8h.xml
+
+
 // File: IntensityDataIOFactory_8cpp.xml
 
 
@@ -3489,12 +3484,6 @@ make Swappable
 // File: PyArrayImportUtils_8h.xml
 
 
-// File: SpectrumUtils_8cpp.xml
-
-
-// File: SpectrumUtils_8h.xml
-
-
 // File: VarianceFunctions_8cpp.xml
 
 
diff --git a/auto/Wrap/doxygenParam.i b/auto/Wrap/doxygenParam.i
index 5c39d00ae1e728ca78f0fa88fefcbfec7f032970..a68ced9d3c587e56437e8069d98d5e3ebfb91199 100644
--- a/auto/Wrap/doxygenParam.i
+++ b/auto/Wrap/doxygenParam.i
@@ -816,7 +816,7 @@ C++ includes: INodeVisitor.h
 %feature("docstring")  INodeVisitor::visit "virtual void INodeVisitor::visit(const MultiLayer *)
 ";
 
-%feature("docstring")  INodeVisitor::visit "virtual void INodeVisitor::visit(const OffSpecSimulation *)
+%feature("docstring")  INodeVisitor::visit "virtual void INodeVisitor::visit(const OffSpecularSimulation *)
 ";
 
 %feature("docstring")  INodeVisitor::visit "virtual void INodeVisitor::visit(const Particle *)
diff --git a/auto/Wrap/doxygenSample.i b/auto/Wrap/doxygenSample.i
index f113d09dbfbcf1f3d95c3c9548bf7fa225ed5a67..6189deafeed87639b13091df2b0d704e0e96d377 100644
--- a/auto/Wrap/doxygenSample.i
+++ b/auto/Wrap/doxygenSample.i
@@ -140,7 +140,12 @@ C++ includes: ParaCrystalBuilder.h
 
 
 // File: classBasicLattice2D.xml
-%feature("docstring") BasicLattice2D "";
+%feature("docstring") BasicLattice2D "
+
+A two-dimensional Bravais lattice with no special symmetry.
+
+C++ includes: Lattice2D.h
+";
 
 %feature("docstring")  BasicLattice2D::BasicLattice2D "BasicLattice2D::BasicLattice2D(double length1, double length2, double angle, double xi)
 ";
@@ -2855,7 +2860,12 @@ C++ includes: PercusYevickBuilder.h
 
 
 // File: classHexagonalLattice2D.xml
-%feature("docstring") HexagonalLattice2D "";
+%feature("docstring") HexagonalLattice2D "
+
+A two-dimensional Bravais lattice with hexagonal symmetry.
+
+C++ includes: Lattice2D.h
+";
 
 %feature("docstring")  HexagonalLattice2D::HexagonalLattice2D "HexagonalLattice2D::HexagonalLattice2D(double length, double xi)
 ";
@@ -4704,7 +4714,12 @@ C++ includes: LatticeBuilder.h
 
 
 // File: classLattice2D.xml
-%feature("docstring") Lattice2D "";
+%feature("docstring") Lattice2D "
+
+A two-dimensional Bravais lattice.
+
+C++ includes: Lattice2D.h
+";
 
 %feature("docstring")  Lattice2D::Lattice2D "Lattice2D::Lattice2D(const NodeMeta &meta, const std::vector< double > &PValues)
 ";
@@ -4823,7 +4838,7 @@ Sets a selection rule for the reciprocal vectors.
 // File: classLayer.xml
 %feature("docstring") Layer "
 
-A layer, with thickness (in nanometer) and material.
+A layer in a  MultiLayer sample.
 
 C++ includes: Layer.h
 ";
@@ -7232,7 +7247,12 @@ C++ includes: ParticleDistributionsBuilder.h
 
 
 // File: classSquareLattice2D.xml
-%feature("docstring") SquareLattice2D "";
+%feature("docstring") SquareLattice2D "
+
+A two-dimensional Bravais lattice with square unit cell.
+
+C++ includes: Lattice2D.h
+";
 
 %feature("docstring")  SquareLattice2D::SquareLattice2D "SquareLattice2D::SquareLattice2D(double length, double xi=0.0)
 ";
diff --git a/auto/Wrap/libBornAgainBase.py b/auto/Wrap/libBornAgainBase.py
index 42bc36a22441656ddad66f52c1772fc53170097f..d1bfa23c9cf0e5b9288cdd9946776fad087f5d07 100644
--- a/auto/Wrap/libBornAgainBase.py
+++ b/auto/Wrap/libBornAgainBase.py
@@ -1769,22 +1769,6 @@ class ThreadInfo(object):
 _libBornAgainBase.ThreadInfo_swigregister(ThreadInfo)
 
 
-def rad2deg(angle):
-    r"""
-    rad2deg(double angle) -> double
-    double Units::rad2deg(double angle)
-
-    """
-    return _libBornAgainBase.rad2deg(angle)
-
-def deg2rad(angle):
-    r"""
-    deg2rad(double angle) -> double
-    double Units::deg2rad(double angle)
-
-    """
-    return _libBornAgainBase.deg2rad(angle)
-
 def vecOfLambdaAlphaPhi(_lambda, _alpha, _phi):
     r"""
     vecOfLambdaAlphaPhi(double _lambda, double _alpha, double _phi) -> kvector_t
@@ -1793,7 +1777,14 @@ def vecOfLambdaAlphaPhi(_lambda, _alpha, _phi):
     """
     return _libBornAgainBase.vecOfLambdaAlphaPhi(_lambda, _alpha, _phi)
 class Direction(object):
-    r"""Proxy of C++ Direction class."""
+    r"""
+
+
+    A direction in three-dimensional space.
+
+    C++ includes: Direction.h
+
+    """
 
     thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
     __repr__ = _swig_repr
@@ -1856,17 +1847,9 @@ nanometer = cvar.nanometer
 angstrom = cvar.angstrom
 micrometer = cvar.micrometer
 millimeter = cvar.millimeter
-meter = cvar.meter
 nm = cvar.nm
 nm2 = cvar.nm2
-barn = cvar.barn
-radian = cvar.radian
-milliradian = cvar.milliradian
-degree = cvar.degree
-steradian = cvar.steradian
 rad = cvar.rad
-mrad = cvar.mrad
-sr = cvar.sr
 deg = cvar.deg
 tesla = cvar.tesla
 gauss = cvar.gauss
@@ -2677,7 +2660,7 @@ class kvector_t(object):
     r"""
 
 
-    Forked from CLHEP/Geometry by E. Chernyaev Evgueni.Tcherniaev@cern.ch, then reworked beyond recognition. Removed split of point and vector semantics. Transforms are relegated to a separate class  Transform3D. Three-dimensional vector template, for use with integer, double, or complex components.
+    Three-dimensional vector template, for use with integer, double, or complex components.
 
     C++ includes: BasicVector3D.h
 
@@ -2768,7 +2751,9 @@ class kvector_t(object):
     def conj(self):
         r"""
         conj(kvector_t self) -> kvector_t
-        BasicVector3D< complex_t > BasicVector3D< complex_t >::conj() const
+        BasicVector3D<T> BasicVector3D< T >::conj() const
+
+        Returns complex conjugate vector. 
 
         """
         return _libBornAgainBase.kvector_t_conj(self)
@@ -2856,7 +2841,9 @@ class kvector_t(object):
     def unit(self):
         r"""
         unit(kvector_t self) -> kvector_t
-        BasicVector3D< complex_t > BasicVector3D< complex_t >::unit() const
+        BasicVector3D<T> BasicVector3D< T >::unit() const
+
+        Returns unit vector in direction of this. Throws for null vector. 
 
         """
         return _libBornAgainBase.kvector_t_unit(self)
@@ -2864,7 +2851,7 @@ class kvector_t(object):
     def complex(self):
         r"""
         complex(kvector_t self) -> cvector_t
-        BasicVector3D<std::complex<double> > BasicVector3D< T >::complex() const
+        BasicVector3D<complex_t> BasicVector3D< T >::complex() const
 
         Returns this, trivially converted to complex type. 
 
@@ -2874,7 +2861,9 @@ class kvector_t(object):
     def real(self):
         r"""
         real(kvector_t self) -> kvector_t
-        BasicVector3D< double > BasicVector3D< complex_t >::real() const
+        BasicVector3D<double> BasicVector3D< T >::real() const
+
+        Returns real parts. 
 
         """
         return _libBornAgainBase.kvector_t_real(self)
@@ -3074,7 +3063,7 @@ class cvector_t(object):
     r"""
 
 
-    Forked from CLHEP/Geometry by E. Chernyaev Evgueni.Tcherniaev@cern.ch, then reworked beyond recognition. Removed split of point and vector semantics. Transforms are relegated to a separate class  Transform3D. Three-dimensional vector template, for use with integer, double, or complex components.
+    Three-dimensional vector template, for use with integer, double, or complex components.
 
     C++ includes: BasicVector3D.h
 
@@ -3165,7 +3154,9 @@ class cvector_t(object):
     def conj(self):
         r"""
         conj(cvector_t self) -> cvector_t
-        BasicVector3D< complex_t > BasicVector3D< complex_t >::conj() const
+        BasicVector3D<T> BasicVector3D< T >::conj() const
+
+        Returns complex conjugate vector. 
 
         """
         return _libBornAgainBase.cvector_t_conj(self)
@@ -3213,7 +3204,9 @@ class cvector_t(object):
     def unit(self):
         r"""
         unit(cvector_t self) -> cvector_t
-        BasicVector3D< complex_t > BasicVector3D< complex_t >::unit() const
+        BasicVector3D<T> BasicVector3D< T >::unit() const
+
+        Returns unit vector in direction of this. Throws for null vector. 
 
         """
         return _libBornAgainBase.cvector_t_unit(self)
@@ -3221,7 +3214,9 @@ class cvector_t(object):
     def real(self):
         r"""
         real(cvector_t self) -> kvector_t
-        BasicVector3D< double > BasicVector3D< complex_t >::real() const
+        BasicVector3D<double> BasicVector3D< T >::real() const
+
+        Returns real parts. 
 
         """
         return _libBornAgainBase.cvector_t_real(self)
diff --git a/auto/Wrap/libBornAgainBase_wrap.cpp b/auto/Wrap/libBornAgainBase_wrap.cpp
index c0aa71b944b19ac95bc887ea291f25d177a4c9c5..6b9093a40e0d19dc63a3eb8691987835f6d28517 100644
--- a/auto/Wrap/libBornAgainBase_wrap.cpp
+++ b/auto/Wrap/libBornAgainBase_wrap.cpp
@@ -6654,10 +6654,10 @@ SWIGINTERN void std_vector_Sl_std_pair_Sl_double_Sc_double_Sg__Sg__insert__SWIG_
 #include "Base/Types/Complex.h"
 #include "Base/Types/ICloneable.h"
 
-#include "Base/Utils/ThreadInfo.h"
-
 #include "Base/Const/Units.h"
 
+#include "Base/Utils/ThreadInfo.h"
+
 #include "Base/Vector/BasicVector3D.h"
 #include "Base/Vector/Vectors3D.h"
 #include "Base/Vector/Direction.h"
@@ -24297,20 +24297,6 @@ SWIGINTERN PyObject *Swig_var_millimeter_get(void) {
 }
 
 
-SWIGINTERN int Swig_var_meter_set(PyObject *) {
-  SWIG_Error(SWIG_AttributeError,"Variable meter is read-only.");
-  return 1;
-}
-
-
-SWIGINTERN PyObject *Swig_var_meter_get(void) {
-  PyObject *pyobj = 0;
-  
-  pyobj = SWIG_From_double(static_cast< double >(Units::meter));
-  return pyobj;
-}
-
-
 SWIGINTERN int Swig_var_nm_set(PyObject *) {
   SWIG_Error(SWIG_AttributeError,"Variable nm is read-only.");
   return 1;
@@ -24339,122 +24325,6 @@ SWIGINTERN PyObject *Swig_var_nm2_get(void) {
 }
 
 
-SWIGINTERN int Swig_var_barn_set(PyObject *) {
-  SWIG_Error(SWIG_AttributeError,"Variable barn is read-only.");
-  return 1;
-}
-
-
-SWIGINTERN PyObject *Swig_var_barn_get(void) {
-  PyObject *pyobj = 0;
-  
-  pyobj = SWIG_From_double(static_cast< double >(Units::barn));
-  return pyobj;
-}
-
-
-SWIGINTERN int Swig_var_radian_set(PyObject *) {
-  SWIG_Error(SWIG_AttributeError,"Variable radian is read-only.");
-  return 1;
-}
-
-
-SWIGINTERN PyObject *Swig_var_radian_get(void) {
-  PyObject *pyobj = 0;
-  
-  pyobj = SWIG_From_double(static_cast< double >(Units::radian));
-  return pyobj;
-}
-
-
-SWIGINTERN int Swig_var_milliradian_set(PyObject *) {
-  SWIG_Error(SWIG_AttributeError,"Variable milliradian is read-only.");
-  return 1;
-}
-
-
-SWIGINTERN PyObject *Swig_var_milliradian_get(void) {
-  PyObject *pyobj = 0;
-  
-  pyobj = SWIG_From_double(static_cast< double >(Units::milliradian));
-  return pyobj;
-}
-
-
-SWIGINTERN int Swig_var_degree_set(PyObject *) {
-  SWIG_Error(SWIG_AttributeError,"Variable degree is read-only.");
-  return 1;
-}
-
-
-SWIGINTERN PyObject *Swig_var_degree_get(void) {
-  PyObject *pyobj = 0;
-  
-  pyobj = SWIG_From_double(static_cast< double >(Units::degree));
-  return pyobj;
-}
-
-
-SWIGINTERN int Swig_var_steradian_set(PyObject *) {
-  SWIG_Error(SWIG_AttributeError,"Variable steradian is read-only.");
-  return 1;
-}
-
-
-SWIGINTERN PyObject *Swig_var_steradian_get(void) {
-  PyObject *pyobj = 0;
-  
-  pyobj = SWIG_From_double(static_cast< double >(Units::steradian));
-  return pyobj;
-}
-
-
-SWIGINTERN PyObject *_wrap_rad2deg(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
-  double arg1 ;
-  double val1 ;
-  int ecode1 = 0 ;
-  PyObject *swig_obj[1] ;
-  double result;
-  
-  if (!args) SWIG_fail;
-  swig_obj[0] = args;
-  ecode1 = SWIG_AsVal_double(swig_obj[0], &val1);
-  if (!SWIG_IsOK(ecode1)) {
-    SWIG_exception_fail(SWIG_ArgError(ecode1), "in method '" "rad2deg" "', argument " "1"" of type '" "double""'");
-  } 
-  arg1 = static_cast< double >(val1);
-  result = (double)Units::rad2deg(arg1);
-  resultobj = SWIG_From_double(static_cast< double >(result));
-  return resultobj;
-fail:
-  return NULL;
-}
-
-
-SWIGINTERN PyObject *_wrap_deg2rad(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
-  double arg1 ;
-  double val1 ;
-  int ecode1 = 0 ;
-  PyObject *swig_obj[1] ;
-  double result;
-  
-  if (!args) SWIG_fail;
-  swig_obj[0] = args;
-  ecode1 = SWIG_AsVal_double(swig_obj[0], &val1);
-  if (!SWIG_IsOK(ecode1)) {
-    SWIG_exception_fail(SWIG_ArgError(ecode1), "in method '" "deg2rad" "', argument " "1"" of type '" "double""'");
-  } 
-  arg1 = static_cast< double >(val1);
-  result = (double)Units::deg2rad(arg1);
-  resultobj = SWIG_From_double(static_cast< double >(result));
-  return resultobj;
-fail:
-  return NULL;
-}
-
-
 SWIGINTERN int Swig_var_rad_set(PyObject *) {
   SWIG_Error(SWIG_AttributeError,"Variable rad is read-only.");
   return 1;
@@ -24469,34 +24339,6 @@ SWIGINTERN PyObject *Swig_var_rad_get(void) {
 }
 
 
-SWIGINTERN int Swig_var_mrad_set(PyObject *) {
-  SWIG_Error(SWIG_AttributeError,"Variable mrad is read-only.");
-  return 1;
-}
-
-
-SWIGINTERN PyObject *Swig_var_mrad_get(void) {
-  PyObject *pyobj = 0;
-  
-  pyobj = SWIG_From_double(static_cast< double >(Units::mrad));
-  return pyobj;
-}
-
-
-SWIGINTERN int Swig_var_sr_set(PyObject *) {
-  SWIG_Error(SWIG_AttributeError,"Variable sr is read-only.");
-  return 1;
-}
-
-
-SWIGINTERN PyObject *Swig_var_sr_get(void) {
-  PyObject *pyobj = 0;
-  
-  pyobj = SWIG_From_double(static_cast< double >(Units::sr));
-  return pyobj;
-}
-
-
 SWIGINTERN int Swig_var_deg_set(PyObject *) {
   SWIG_Error(SWIG_AttributeError,"Variable deg is read-only.");
   return 1;
@@ -28178,7 +28020,7 @@ SWIGINTERN PyObject *_wrap_kvector_t_complex(PyObject *SWIGUNUSEDPARM(self), PyO
   void *argp1 = 0 ;
   int res1 = 0 ;
   PyObject *swig_obj[1] ;
-  BasicVector3D< std::complex< double > > result;
+  BasicVector3D< complex_t > result;
   
   if (!args) SWIG_fail;
   swig_obj[0] = args;
@@ -28188,7 +28030,7 @@ SWIGINTERN PyObject *_wrap_kvector_t_complex(PyObject *SWIGUNUSEDPARM(self), PyO
   }
   arg1 = reinterpret_cast< BasicVector3D< double > * >(argp1);
   result = ((BasicVector3D< double > const *)arg1)->complex();
-  resultobj = SWIG_NewPointerObj((new BasicVector3D< std::complex< double > >(static_cast< const BasicVector3D< std::complex< double > >& >(result))), SWIGTYPE_p_BasicVector3DT_std__complexT_double_t_t, SWIG_POINTER_OWN |  0 );
+  resultobj = SWIG_NewPointerObj((new BasicVector3D< complex_t >(static_cast< const BasicVector3D< complex_t >& >(result))), SWIGTYPE_p_BasicVector3DT_std__complexT_double_t_t, SWIG_POINTER_OWN |  0 );
   return resultobj;
 fail:
   return NULL;
@@ -33130,16 +32972,6 @@ static PyMethodDef SwigMethods[] = {
 	 { "delete_ThreadInfo", _wrap_delete_ThreadInfo, METH_O, "delete_ThreadInfo(ThreadInfo self)"},
 	 { "ThreadInfo_swigregister", ThreadInfo_swigregister, METH_O, NULL},
 	 { "ThreadInfo_swiginit", ThreadInfo_swiginit, METH_VARARGS, NULL},
-	 { "rad2deg", _wrap_rad2deg, METH_O, "\n"
-		"rad2deg(double angle) -> double\n"
-		"double Units::rad2deg(double angle)\n"
-		"\n"
-		""},
-	 { "deg2rad", _wrap_deg2rad, METH_O, "\n"
-		"deg2rad(double angle) -> double\n"
-		"double Units::deg2rad(double angle)\n"
-		"\n"
-		""},
 	 { "vecOfLambdaAlphaPhi", _wrap_vecOfLambdaAlphaPhi, METH_VARARGS, "\n"
 		"vecOfLambdaAlphaPhi(double _lambda, double _alpha, double _phi) -> kvector_t\n"
 		"kvector_t vecOfLambdaAlphaPhi(double _lambda, double _alpha, double _phi)\n"
@@ -33747,7 +33579,9 @@ static PyMethodDef SwigMethods[] = {
 	 { "kvector_t___isub__", _wrap_kvector_t___isub__, METH_VARARGS, "kvector_t___isub__(kvector_t self, kvector_t v) -> kvector_t"},
 	 { "kvector_t_conj", _wrap_kvector_t_conj, METH_O, "\n"
 		"kvector_t_conj(kvector_t self) -> kvector_t\n"
-		"BasicVector3D< complex_t > BasicVector3D< complex_t >::conj() const\n"
+		"BasicVector3D<T> BasicVector3D< T >::conj() const\n"
+		"\n"
+		"Returns complex conjugate vector. \n"
 		"\n"
 		""},
 	 { "kvector_t_mag2", _wrap_kvector_t_mag2, METH_O, "\n"
@@ -33808,19 +33642,23 @@ static PyMethodDef SwigMethods[] = {
 		""},
 	 { "kvector_t_unit", _wrap_kvector_t_unit, METH_O, "\n"
 		"kvector_t_unit(kvector_t self) -> kvector_t\n"
-		"BasicVector3D< complex_t > BasicVector3D< complex_t >::unit() const\n"
+		"BasicVector3D<T> BasicVector3D< T >::unit() const\n"
+		"\n"
+		"Returns unit vector in direction of this. Throws for null vector. \n"
 		"\n"
 		""},
 	 { "kvector_t_complex", _wrap_kvector_t_complex, METH_O, "\n"
 		"kvector_t_complex(kvector_t self) -> cvector_t\n"
-		"BasicVector3D<std::complex<double> > BasicVector3D< T >::complex() const\n"
+		"BasicVector3D<complex_t> BasicVector3D< T >::complex() const\n"
 		"\n"
 		"Returns this, trivially converted to complex type. \n"
 		"\n"
 		""},
 	 { "kvector_t_real", _wrap_kvector_t_real, METH_O, "\n"
 		"kvector_t_real(kvector_t self) -> kvector_t\n"
-		"BasicVector3D< double > BasicVector3D< complex_t >::real() const\n"
+		"BasicVector3D<double> BasicVector3D< T >::real() const\n"
+		"\n"
+		"Returns real parts. \n"
 		"\n"
 		""},
 	 { "kvector_t_angle", _wrap_kvector_t_angle, METH_VARARGS, "\n"
@@ -33956,7 +33794,9 @@ static PyMethodDef SwigMethods[] = {
 	 { "cvector_t___isub__", _wrap_cvector_t___isub__, METH_VARARGS, "cvector_t___isub__(cvector_t self, cvector_t v) -> cvector_t"},
 	 { "cvector_t_conj", _wrap_cvector_t_conj, METH_O, "\n"
 		"cvector_t_conj(cvector_t self) -> cvector_t\n"
-		"BasicVector3D< complex_t > BasicVector3D< complex_t >::conj() const\n"
+		"BasicVector3D<T> BasicVector3D< T >::conj() const\n"
+		"\n"
+		"Returns complex conjugate vector. \n"
 		"\n"
 		""},
 	 { "cvector_t_mag2", _wrap_cvector_t_mag2, METH_O, "\n"
@@ -33989,12 +33829,16 @@ static PyMethodDef SwigMethods[] = {
 		""},
 	 { "cvector_t_unit", _wrap_cvector_t_unit, METH_O, "\n"
 		"cvector_t_unit(cvector_t self) -> cvector_t\n"
-		"BasicVector3D< complex_t > BasicVector3D< complex_t >::unit() const\n"
+		"BasicVector3D<T> BasicVector3D< T >::unit() const\n"
+		"\n"
+		"Returns unit vector in direction of this. Throws for null vector. \n"
 		"\n"
 		""},
 	 { "cvector_t_real", _wrap_cvector_t_real, METH_O, "\n"
 		"cvector_t_real(cvector_t self) -> kvector_t\n"
-		"BasicVector3D< double > BasicVector3D< complex_t >::real() const\n"
+		"BasicVector3D<double> BasicVector3D< T >::real() const\n"
+		"\n"
+		"Returns real parts. \n"
 		"\n"
 		""},
 	 { "cvector_t_project", _wrap_cvector_t_project, METH_VARARGS, "\n"
@@ -34099,7 +33943,7 @@ static void *_p_FixedBinAxisTo_p_IAxis(void *x, int *SWIGUNUSEDPARM(newmemory))
 }
 static swig_type_info _swigt__p_BasicVector3DT_double_t = {"_p_BasicVector3DT_double_t", "std::vector< BasicVector3D< double > >::value_type *|kvector_t *|BasicVector3D< double > *", 0, 0, (void*)0, 0};
 static swig_type_info _swigt__p_BasicVector3DT_int_t = {"_p_BasicVector3DT_int_t", "ivector_t *|BasicVector3D< int > *", 0, 0, (void*)0, 0};
-static swig_type_info _swigt__p_BasicVector3DT_std__complexT_double_t_t = {"_p_BasicVector3DT_std__complexT_double_t_t", "BasicVector3D< std::complex< double > > *|std::vector< BasicVector3D< std::complex< double > > >::value_type *|cvector_t *", 0, 0, (void*)0, 0};
+static swig_type_info _swigt__p_BasicVector3DT_std__complexT_double_t_t = {"_p_BasicVector3DT_std__complexT_double_t_t", "BasicVector3D< std::complex< double > > *|std::vector< BasicVector3D< std::complex< double > > >::value_type *|cvector_t *|BasicVector3D< complex_t > *", 0, 0, (void*)0, 0};
 static swig_type_info _swigt__p_Bin1D = {"_p_Bin1D", "Bin1D *", 0, 0, (void*)0, 0};
 static swig_type_info _swigt__p_Bin1DCVector = {"_p_Bin1DCVector", "Bin1DCVector *", 0, 0, (void*)0, 0};
 static swig_type_info _swigt__p_Bin1DKVector = {"_p_Bin1DKVector", "Bin1DKVector *", 0, 0, (void*)0, 0};
@@ -35102,17 +34946,9 @@ SWIG_init(void) {
   SWIG_addvarlink(globals, "angstrom", Swig_var_angstrom_get, Swig_var_angstrom_set);
   SWIG_addvarlink(globals, "micrometer", Swig_var_micrometer_get, Swig_var_micrometer_set);
   SWIG_addvarlink(globals, "millimeter", Swig_var_millimeter_get, Swig_var_millimeter_set);
-  SWIG_addvarlink(globals, "meter", Swig_var_meter_get, Swig_var_meter_set);
   SWIG_addvarlink(globals, "nm", Swig_var_nm_get, Swig_var_nm_set);
   SWIG_addvarlink(globals, "nm2", Swig_var_nm2_get, Swig_var_nm2_set);
-  SWIG_addvarlink(globals, "barn", Swig_var_barn_get, Swig_var_barn_set);
-  SWIG_addvarlink(globals, "radian", Swig_var_radian_get, Swig_var_radian_set);
-  SWIG_addvarlink(globals, "milliradian", Swig_var_milliradian_get, Swig_var_milliradian_set);
-  SWIG_addvarlink(globals, "degree", Swig_var_degree_get, Swig_var_degree_set);
-  SWIG_addvarlink(globals, "steradian", Swig_var_steradian_get, Swig_var_steradian_set);
   SWIG_addvarlink(globals, "rad", Swig_var_rad_get, Swig_var_rad_set);
-  SWIG_addvarlink(globals, "mrad", Swig_var_mrad_get, Swig_var_mrad_set);
-  SWIG_addvarlink(globals, "sr", Swig_var_sr_get, Swig_var_sr_set);
   SWIG_addvarlink(globals, "deg", Swig_var_deg_get, Swig_var_deg_set);
   SWIG_addvarlink(globals, "tesla", Swig_var_tesla_get, Swig_var_tesla_set);
   SWIG_addvarlink(globals, "gauss", Swig_var_gauss_get, Swig_var_gauss_set);
diff --git a/auto/Wrap/libBornAgainCore.py b/auto/Wrap/libBornAgainCore.py
index b29772e589413c6221be05902c337aa03a72b949..09255ebdb11f489ee273cbd7a6146a78cdaeca77 100644
--- a/auto/Wrap/libBornAgainCore.py
+++ b/auto/Wrap/libBornAgainCore.py
@@ -3108,89 +3108,6 @@ def GetName():
 def GetVersionNumber():
     r"""GetVersionNumber() -> std::string"""
     return _libBornAgainCore.GetVersionNumber()
-class IObserver(object):
-    r"""
-
-
-    Observer interface from Observer pattern.
-
-    C++ includes: IObserver.h
-
-    """
-
-    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
-
-    def __init__(self, *args, **kwargs):
-        raise AttributeError("No constructor defined - class is abstract")
-    __repr__ = _swig_repr
-    __swig_destroy__ = _libBornAgainCore.delete_IObserver
-
-    def notify(self, subject):
-        r"""
-        notify(IObserver self, IObservable subject)
-        virtual void IObserver::notify(IObservable *subject)=0
-
-        method which is used by observable subject to notify change in status 
-
-        """
-        return _libBornAgainCore.IObserver_notify(self, subject)
-
-# Register IObserver in _libBornAgainCore:
-_libBornAgainCore.IObserver_swigregister(IObserver)
-cvar = _libBornAgainCore.cvar
-major_version_number = cvar.major_version_number
-minor_version_number = cvar.minor_version_number
-patch_version_number = cvar.patch_version_number
-
-class IObservable(object):
-    r"""
-
-
-    Observable interface from Observer pattern
-
-    C++ includes: IObserver.h
-
-    """
-
-    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
-    __repr__ = _swig_repr
-    __swig_destroy__ = _libBornAgainCore.delete_IObservable
-
-    def attachObserver(self, obj):
-        r"""
-        attachObserver(IObservable self, IObservable::observer_t obj)
-        void IObservable::attachObserver(observer_t obj)
-
-        attach observer to the list of observers 
-
-        """
-        return _libBornAgainCore.IObservable_attachObserver(self, obj)
-
-    def notifyObservers(self):
-        r"""
-        notifyObservers(IObservable self)
-        void IObservable::notifyObservers()
-
-        notify observers about change in status 
-
-        """
-        return _libBornAgainCore.IObservable_notifyObservers(self)
-
-    def __init__(self):
-        r"""
-        __init__(IObservable self) -> IObservable
-
-
-        Observable interface from Observer pattern
-
-        C++ includes: IObserver.h
-
-        """
-        _libBornAgainCore.IObservable_swiginit(self, _libBornAgainCore.new_IObservable())
-
-# Register IObservable in _libBornAgainCore:
-_libBornAgainCore.IObservable_swigregister(IObservable)
-
 class IterationInfo(object):
     r"""
 
@@ -3259,6 +3176,10 @@ class IterationInfo(object):
 
 # Register IterationInfo in _libBornAgainCore:
 _libBornAgainCore.IterationInfo_swigregister(IterationInfo)
+cvar = _libBornAgainCore.cvar
+major_version_number = cvar.major_version_number
+minor_version_number = cvar.minor_version_number
+patch_version_number = cvar.patch_version_number
 
 class PyBuilderCallback(object):
     r"""
@@ -3534,7 +3455,7 @@ class ISimulation(libBornAgainBase.ICloneable, libBornAgainParam.INode):
     r"""
 
 
-    Abstract base class of OffSpecularSimulation,  GISASSimulation and  SpecularSimulation. Holds the common infrastructure to run a simulation: multithreading, batch processing, weighting over parameter distributions, ...
+    Abstract base class of  OffSpecularSimulation,  GISASSimulation and  SpecularSimulation. Holds the common infrastructure to run a simulation: multithreading, batch processing, weighting over parameter distributions, ...
 
     C++ includes: ISimulation.h
 
@@ -3622,24 +3543,6 @@ class ISimulation(libBornAgainBase.ICloneable, libBornAgainParam.INode):
         """
         return _libBornAgainCore.ISimulation_detector(self, *args)
 
-    def setBeamIntensity(self, intensity):
-        r"""
-        setBeamIntensity(ISimulation self, double intensity)
-        void ISimulation::setBeamIntensity(double intensity)
-
-        """
-        return _libBornAgainCore.ISimulation_setBeamIntensity(self, intensity)
-
-    def setBeamPolarization(self, bloch_vector):
-        r"""
-        setBeamPolarization(ISimulation self, kvector_t bloch_vector)
-        void ISimulation::setBeamPolarization(const kvector_t bloch_vector)
-
-        Sets the beam polarization according to the given Bloch vector. 
-
-        """
-        return _libBornAgainCore.ISimulation_setBeamPolarization(self, bloch_vector)
-
     def setDetectorResolutionFunction(self, resolution_function):
         r"""
         setDetectorResolutionFunction(ISimulation self, IResolutionFunction2D const & resolution_function)
@@ -3802,7 +3705,7 @@ class ISimulation2D(ISimulation):
     r"""
 
 
-    Abstract base class of OffSpecularSimulation and  GISASSimulation. Holds the common implementations for simulations with a 2D detector
+    Abstract base class of  OffSpecularSimulation and  GISASSimulation. Holds the common implementations for simulations with a 2D detector
 
     C++ includes: ISimulation2D.h
 
@@ -4198,13 +4101,13 @@ class SpecularSimulation(ISimulation):
 # Register SpecularSimulation in _libBornAgainCore:
 _libBornAgainCore.SpecularSimulation_swigregister(SpecularSimulation)
 
-class OffSpecSimulation(ISimulation2D):
+class OffSpecularSimulation(ISimulation2D):
     r"""
 
 
     Main class to run an off-specular simulation.
 
-    C++ includes: OffSpecSimulation.h
+    C++ includes: OffSpecularSimulation.h
 
     """
 
@@ -4213,82 +4116,82 @@ class OffSpecSimulation(ISimulation2D):
 
     def __init__(self, *args):
         r"""
-        __init__(OffSpecSimulation self, Beam const & beam, MultiLayer const & sample, IDetector const & detector) -> OffSpecSimulation
-        __init__(OffSpecSimulation self) -> OffSpecSimulation
-        OffSpecSimulation::OffSpecSimulation()
+        __init__(OffSpecularSimulation self, Beam const & beam, MultiLayer const & sample, IDetector const & detector) -> OffSpecularSimulation
+        __init__(OffSpecularSimulation self) -> OffSpecularSimulation
+        OffSpecularSimulation::OffSpecularSimulation()
 
         """
-        _libBornAgainCore.OffSpecSimulation_swiginit(self, _libBornAgainCore.new_OffSpecSimulation(*args))
-    __swig_destroy__ = _libBornAgainCore.delete_OffSpecSimulation
+        _libBornAgainCore.OffSpecularSimulation_swiginit(self, _libBornAgainCore.new_OffSpecularSimulation(*args))
+    __swig_destroy__ = _libBornAgainCore.delete_OffSpecularSimulation
 
     def clone(self):
         r"""
-        clone(OffSpecSimulation self) -> OffSpecSimulation
-        OffSpecSimulation* OffSpecSimulation::clone() const override
+        clone(OffSpecularSimulation self) -> OffSpecularSimulation
+        OffSpecularSimulation* OffSpecularSimulation::clone() const override
 
         """
-        return _libBornAgainCore.OffSpecSimulation_clone(self)
+        return _libBornAgainCore.OffSpecularSimulation_clone(self)
 
     def accept(self, visitor):
         r"""
-        accept(OffSpecSimulation self, INodeVisitor * visitor)
-        void OffSpecSimulation::accept(INodeVisitor *visitor) const override
+        accept(OffSpecularSimulation self, INodeVisitor * visitor)
+        void OffSpecularSimulation::accept(INodeVisitor *visitor) const override
 
         """
-        return _libBornAgainCore.OffSpecSimulation_accept(self, visitor)
+        return _libBornAgainCore.OffSpecularSimulation_accept(self, visitor)
 
     def prepareSimulation(self):
         r"""
-        prepareSimulation(OffSpecSimulation self)
-        void OffSpecSimulation::prepareSimulation() override
+        prepareSimulation(OffSpecularSimulation self)
+        void OffSpecularSimulation::prepareSimulation() override
 
         Put into a clean state for running a simulation. 
 
         """
-        return _libBornAgainCore.OffSpecSimulation_prepareSimulation(self)
+        return _libBornAgainCore.OffSpecularSimulation_prepareSimulation(self)
 
     def result(self):
         r"""
-        result(OffSpecSimulation self) -> SimulationResult
-        SimulationResult OffSpecSimulation::result() const override
+        result(OffSpecularSimulation self) -> SimulationResult
+        SimulationResult OffSpecularSimulation::result() const override
 
         Returns the results of the simulation in a format that supports unit conversion and export to numpy arrays 
 
         """
-        return _libBornAgainCore.OffSpecSimulation_result(self)
+        return _libBornAgainCore.OffSpecularSimulation_result(self)
 
     def setBeamParameters(self, wavelength, alpha_axis, phi_i):
         r"""
-        setBeamParameters(OffSpecSimulation self, double wavelength, IAxis alpha_axis, double phi_i)
-        void OffSpecSimulation::setBeamParameters(double wavelength, const IAxis &alpha_axis, double phi_i)
+        setBeamParameters(OffSpecularSimulation self, double wavelength, IAxis alpha_axis, double phi_i)
+        void OffSpecularSimulation::setBeamParameters(double wavelength, const IAxis &alpha_axis, double phi_i)
 
         Sets beam parameters from here (forwarded to Instrument) 
 
         """
-        return _libBornAgainCore.OffSpecSimulation_setBeamParameters(self, wavelength, alpha_axis, phi_i)
+        return _libBornAgainCore.OffSpecularSimulation_setBeamParameters(self, wavelength, alpha_axis, phi_i)
 
     def beamAxis(self):
         r"""
-        beamAxis(OffSpecSimulation self) -> IAxis
-        const IAxis * OffSpecSimulation::beamAxis() const
+        beamAxis(OffSpecularSimulation self) -> IAxis
+        const IAxis * OffSpecularSimulation::beamAxis() const
 
         Returns axis of the beam. 
 
         """
-        return _libBornAgainCore.OffSpecSimulation_beamAxis(self)
+        return _libBornAgainCore.OffSpecularSimulation_beamAxis(self)
 
     def intensityMapSize(self):
         r"""
-        intensityMapSize(OffSpecSimulation self) -> size_t
-        size_t OffSpecSimulation::intensityMapSize() const override
+        intensityMapSize(OffSpecularSimulation self) -> size_t
+        size_t OffSpecularSimulation::intensityMapSize() const override
 
         Returns the total number of the intensity values in the simulation result. 
 
         """
-        return _libBornAgainCore.OffSpecSimulation_intensityMapSize(self)
+        return _libBornAgainCore.OffSpecularSimulation_intensityMapSize(self)
 
-# Register OffSpecSimulation in _libBornAgainCore:
-_libBornAgainCore.OffSpecSimulation_swigregister(OffSpecSimulation)
+# Register OffSpecularSimulation in _libBornAgainCore:
+_libBornAgainCore.OffSpecularSimulation_swigregister(OffSpecularSimulation)
 
 class IBackground(libBornAgainBase.ICloneable, libBornAgainParam.INode):
     r"""
diff --git a/auto/Wrap/libBornAgainCore_wrap.cpp b/auto/Wrap/libBornAgainCore_wrap.cpp
index 2ac6c2e76d9156c9890c4370a38b047d02a780f9..ef0267b6428aef71ea96d957195fd5ede23c0421 100644
--- a/auto/Wrap/libBornAgainCore_wrap.cpp
+++ b/auto/Wrap/libBornAgainCore_wrap.cpp
@@ -3121,91 +3121,87 @@ namespace Swig {
 #define SWIGTYPE_p_IFormFactor swig_types[21]
 #define SWIGTYPE_p_INode swig_types[22]
 #define SWIGTYPE_p_INodeVisitor swig_types[23]
-#define SWIGTYPE_p_IObservable swig_types[24]
-#define SWIGTYPE_p_IObserver swig_types[25]
-#define SWIGTYPE_p_IParametricComponent swig_types[26]
-#define SWIGTYPE_p_IRangedDistribution swig_types[27]
-#define SWIGTYPE_p_IResolutionFunction2D swig_types[28]
-#define SWIGTYPE_p_ISampleNode swig_types[29]
-#define SWIGTYPE_p_IShape2D swig_types[30]
-#define SWIGTYPE_p_ISimulation swig_types[31]
-#define SWIGTYPE_p_ISimulation2D swig_types[32]
-#define SWIGTYPE_p_ISpecularScan swig_types[33]
-#define SWIGTYPE_p_Instrument swig_types[34]
-#define SWIGTYPE_p_IterationInfo swig_types[35]
-#define SWIGTYPE_p_MultiLayer swig_types[36]
-#define SWIGTYPE_p_OffSpecSimulation swig_types[37]
-#define SWIGTYPE_p_OutputDataT_double_t swig_types[38]
-#define SWIGTYPE_p_ParameterDistribution swig_types[39]
-#define SWIGTYPE_p_ParameterPool swig_types[40]
-#define SWIGTYPE_p_PoissonNoiseBackground swig_types[41]
-#define SWIGTYPE_p_ProgressHandler__Callback_t swig_types[42]
-#define SWIGTYPE_p_PyBuilderCallback swig_types[43]
-#define SWIGTYPE_p_PyObserverCallback swig_types[44]
-#define SWIGTYPE_p_QSpecScan swig_types[45]
-#define SWIGTYPE_p_RealLimits swig_types[46]
-#define SWIGTYPE_p_ScanResolution swig_types[47]
-#define SWIGTYPE_p_SimulationOptions swig_types[48]
-#define SWIGTYPE_p_SimulationResult swig_types[49]
-#define SWIGTYPE_p_SpecularSimulation swig_types[50]
-#define SWIGTYPE_p_allocator_type swig_types[51]
-#define SWIGTYPE_p_char swig_types[52]
-#define SWIGTYPE_p_difference_type swig_types[53]
-#define SWIGTYPE_p_first_type swig_types[54]
-#define SWIGTYPE_p_int swig_types[55]
-#define SWIGTYPE_p_key_type swig_types[56]
-#define SWIGTYPE_p_long_long swig_types[57]
-#define SWIGTYPE_p_mapped_type swig_types[58]
-#define SWIGTYPE_p_mumufit__MinimizerResult swig_types[59]
-#define SWIGTYPE_p_mumufit__Parameters swig_types[60]
-#define SWIGTYPE_p_observer_t swig_types[61]
-#define SWIGTYPE_p_p_PyObject swig_types[62]
-#define SWIGTYPE_p_second_type swig_types[63]
-#define SWIGTYPE_p_short swig_types[64]
-#define SWIGTYPE_p_signed_char swig_types[65]
-#define SWIGTYPE_p_size_type swig_types[66]
-#define SWIGTYPE_p_std__allocatorT_AxisInfo_t swig_types[67]
-#define SWIGTYPE_p_std__allocatorT_BasicVector3DT_double_t_t swig_types[68]
-#define SWIGTYPE_p_std__allocatorT_BasicVector3DT_std__complexT_double_t_t_t swig_types[69]
-#define SWIGTYPE_p_std__allocatorT_INode_const_p_t swig_types[70]
-#define SWIGTYPE_p_std__allocatorT_INode_p_t swig_types[71]
-#define SWIGTYPE_p_std__allocatorT_double_t swig_types[72]
-#define SWIGTYPE_p_std__allocatorT_int_t swig_types[73]
-#define SWIGTYPE_p_std__allocatorT_std__complexT_double_t_t swig_types[74]
-#define SWIGTYPE_p_std__allocatorT_std__pairT_double_double_t_t swig_types[75]
-#define SWIGTYPE_p_std__allocatorT_std__pairT_std__string_const_double_t_t swig_types[76]
-#define SWIGTYPE_p_std__allocatorT_std__string_t swig_types[77]
-#define SWIGTYPE_p_std__allocatorT_std__vectorT_double_std__allocatorT_double_t_t_t swig_types[78]
-#define SWIGTYPE_p_std__allocatorT_std__vectorT_int_std__allocatorT_int_t_t_t swig_types[79]
-#define SWIGTYPE_p_std__allocatorT_unsigned_long_t swig_types[80]
-#define SWIGTYPE_p_std__complexT_double_t swig_types[81]
-#define SWIGTYPE_p_std__invalid_argument swig_types[82]
-#define SWIGTYPE_p_std__lessT_std__string_t swig_types[83]
-#define SWIGTYPE_p_std__mapT_std__string_double_std__lessT_std__string_t_std__allocatorT_std__pairT_std__string_const_double_t_t_t swig_types[84]
-#define SWIGTYPE_p_std__pairT_double_double_t swig_types[85]
-#define SWIGTYPE_p_std__shared_ptrT_IObserver_t swig_types[86]
-#define SWIGTYPE_p_std__shared_ptrT_ISampleBuilder_t swig_types[87]
-#define SWIGTYPE_p_std__vectorT_AxisInfo_std__allocatorT_AxisInfo_t_t swig_types[88]
-#define SWIGTYPE_p_std__vectorT_BasicVector3DT_double_t_std__allocatorT_BasicVector3DT_double_t_t_t swig_types[89]
-#define SWIGTYPE_p_std__vectorT_BasicVector3DT_std__complexT_double_t_t_std__allocatorT_BasicVector3DT_std__complexT_double_t_t_t_t swig_types[90]
-#define SWIGTYPE_p_std__vectorT_INode_const_p_std__allocatorT_INode_const_p_t_t swig_types[91]
-#define SWIGTYPE_p_std__vectorT_INode_p_std__allocatorT_INode_p_t_t swig_types[92]
-#define SWIGTYPE_p_std__vectorT_double_std__allocatorT_double_t_t swig_types[93]
-#define SWIGTYPE_p_std__vectorT_int_std__allocatorT_int_t_t swig_types[94]
-#define SWIGTYPE_p_std__vectorT_std__complexT_double_t_std__allocatorT_std__complexT_double_t_t_t swig_types[95]
-#define SWIGTYPE_p_std__vectorT_std__pairT_double_double_t_std__allocatorT_std__pairT_double_double_t_t_t swig_types[96]
-#define SWIGTYPE_p_std__vectorT_std__string_std__allocatorT_std__string_t_t swig_types[97]
-#define SWIGTYPE_p_std__vectorT_std__vectorT_double_std__allocatorT_double_t_t_std__allocatorT_std__vectorT_double_std__allocatorT_double_t_t_t_t swig_types[98]
-#define SWIGTYPE_p_std__vectorT_std__vectorT_int_std__allocatorT_int_t_t_std__allocatorT_std__vectorT_int_std__allocatorT_int_t_t_t_t swig_types[99]
-#define SWIGTYPE_p_std__vectorT_unsigned_long_std__allocatorT_unsigned_long_t_t swig_types[100]
-#define SWIGTYPE_p_swig__SwigPyIterator swig_types[101]
-#define SWIGTYPE_p_unsigned_char swig_types[102]
-#define SWIGTYPE_p_unsigned_int swig_types[103]
-#define SWIGTYPE_p_unsigned_long_long swig_types[104]
-#define SWIGTYPE_p_unsigned_short swig_types[105]
-#define SWIGTYPE_p_value_type swig_types[106]
-static swig_type_info *swig_types[108];
-static swig_module_info swig_module = {swig_types, 107, 0, 0, 0, 0};
+#define SWIGTYPE_p_IParametricComponent swig_types[24]
+#define SWIGTYPE_p_IRangedDistribution swig_types[25]
+#define SWIGTYPE_p_IResolutionFunction2D swig_types[26]
+#define SWIGTYPE_p_ISampleNode swig_types[27]
+#define SWIGTYPE_p_IShape2D swig_types[28]
+#define SWIGTYPE_p_ISimulation swig_types[29]
+#define SWIGTYPE_p_ISimulation2D swig_types[30]
+#define SWIGTYPE_p_ISpecularScan swig_types[31]
+#define SWIGTYPE_p_Instrument swig_types[32]
+#define SWIGTYPE_p_IterationInfo swig_types[33]
+#define SWIGTYPE_p_MultiLayer swig_types[34]
+#define SWIGTYPE_p_OffSpecularSimulation swig_types[35]
+#define SWIGTYPE_p_OutputDataT_double_t swig_types[36]
+#define SWIGTYPE_p_ParameterDistribution swig_types[37]
+#define SWIGTYPE_p_ParameterPool swig_types[38]
+#define SWIGTYPE_p_PoissonNoiseBackground swig_types[39]
+#define SWIGTYPE_p_ProgressHandler__Callback_t swig_types[40]
+#define SWIGTYPE_p_PyBuilderCallback swig_types[41]
+#define SWIGTYPE_p_PyObserverCallback swig_types[42]
+#define SWIGTYPE_p_QSpecScan swig_types[43]
+#define SWIGTYPE_p_RealLimits swig_types[44]
+#define SWIGTYPE_p_ScanResolution swig_types[45]
+#define SWIGTYPE_p_SimulationOptions swig_types[46]
+#define SWIGTYPE_p_SimulationResult swig_types[47]
+#define SWIGTYPE_p_SpecularSimulation swig_types[48]
+#define SWIGTYPE_p_allocator_type swig_types[49]
+#define SWIGTYPE_p_char swig_types[50]
+#define SWIGTYPE_p_difference_type swig_types[51]
+#define SWIGTYPE_p_first_type swig_types[52]
+#define SWIGTYPE_p_int swig_types[53]
+#define SWIGTYPE_p_key_type swig_types[54]
+#define SWIGTYPE_p_long_long swig_types[55]
+#define SWIGTYPE_p_mapped_type swig_types[56]
+#define SWIGTYPE_p_mumufit__MinimizerResult swig_types[57]
+#define SWIGTYPE_p_mumufit__Parameters swig_types[58]
+#define SWIGTYPE_p_p_PyObject swig_types[59]
+#define SWIGTYPE_p_second_type swig_types[60]
+#define SWIGTYPE_p_short swig_types[61]
+#define SWIGTYPE_p_signed_char swig_types[62]
+#define SWIGTYPE_p_size_type swig_types[63]
+#define SWIGTYPE_p_std__allocatorT_AxisInfo_t swig_types[64]
+#define SWIGTYPE_p_std__allocatorT_BasicVector3DT_double_t_t swig_types[65]
+#define SWIGTYPE_p_std__allocatorT_BasicVector3DT_std__complexT_double_t_t_t swig_types[66]
+#define SWIGTYPE_p_std__allocatorT_INode_const_p_t swig_types[67]
+#define SWIGTYPE_p_std__allocatorT_INode_p_t swig_types[68]
+#define SWIGTYPE_p_std__allocatorT_double_t swig_types[69]
+#define SWIGTYPE_p_std__allocatorT_int_t swig_types[70]
+#define SWIGTYPE_p_std__allocatorT_std__complexT_double_t_t swig_types[71]
+#define SWIGTYPE_p_std__allocatorT_std__pairT_double_double_t_t swig_types[72]
+#define SWIGTYPE_p_std__allocatorT_std__pairT_std__string_const_double_t_t swig_types[73]
+#define SWIGTYPE_p_std__allocatorT_std__string_t swig_types[74]
+#define SWIGTYPE_p_std__allocatorT_std__vectorT_double_std__allocatorT_double_t_t_t swig_types[75]
+#define SWIGTYPE_p_std__allocatorT_std__vectorT_int_std__allocatorT_int_t_t_t swig_types[76]
+#define SWIGTYPE_p_std__allocatorT_unsigned_long_t swig_types[77]
+#define SWIGTYPE_p_std__complexT_double_t swig_types[78]
+#define SWIGTYPE_p_std__invalid_argument swig_types[79]
+#define SWIGTYPE_p_std__lessT_std__string_t swig_types[80]
+#define SWIGTYPE_p_std__mapT_std__string_double_std__lessT_std__string_t_std__allocatorT_std__pairT_std__string_const_double_t_t_t swig_types[81]
+#define SWIGTYPE_p_std__pairT_double_double_t swig_types[82]
+#define SWIGTYPE_p_std__shared_ptrT_ISampleBuilder_t swig_types[83]
+#define SWIGTYPE_p_std__vectorT_AxisInfo_std__allocatorT_AxisInfo_t_t swig_types[84]
+#define SWIGTYPE_p_std__vectorT_BasicVector3DT_double_t_std__allocatorT_BasicVector3DT_double_t_t_t swig_types[85]
+#define SWIGTYPE_p_std__vectorT_BasicVector3DT_std__complexT_double_t_t_std__allocatorT_BasicVector3DT_std__complexT_double_t_t_t_t swig_types[86]
+#define SWIGTYPE_p_std__vectorT_INode_const_p_std__allocatorT_INode_const_p_t_t swig_types[87]
+#define SWIGTYPE_p_std__vectorT_INode_p_std__allocatorT_INode_p_t_t swig_types[88]
+#define SWIGTYPE_p_std__vectorT_double_std__allocatorT_double_t_t swig_types[89]
+#define SWIGTYPE_p_std__vectorT_int_std__allocatorT_int_t_t swig_types[90]
+#define SWIGTYPE_p_std__vectorT_std__complexT_double_t_std__allocatorT_std__complexT_double_t_t_t swig_types[91]
+#define SWIGTYPE_p_std__vectorT_std__pairT_double_double_t_std__allocatorT_std__pairT_double_double_t_t_t swig_types[92]
+#define SWIGTYPE_p_std__vectorT_std__string_std__allocatorT_std__string_t_t swig_types[93]
+#define SWIGTYPE_p_std__vectorT_std__vectorT_double_std__allocatorT_double_t_t_std__allocatorT_std__vectorT_double_std__allocatorT_double_t_t_t_t swig_types[94]
+#define SWIGTYPE_p_std__vectorT_std__vectorT_int_std__allocatorT_int_t_t_std__allocatorT_std__vectorT_int_std__allocatorT_int_t_t_t_t swig_types[95]
+#define SWIGTYPE_p_std__vectorT_unsigned_long_std__allocatorT_unsigned_long_t_t swig_types[96]
+#define SWIGTYPE_p_swig__SwigPyIterator swig_types[97]
+#define SWIGTYPE_p_unsigned_char swig_types[98]
+#define SWIGTYPE_p_unsigned_int swig_types[99]
+#define SWIGTYPE_p_unsigned_long_long swig_types[100]
+#define SWIGTYPE_p_unsigned_short swig_types[101]
+#define SWIGTYPE_p_value_type swig_types[102]
+static swig_type_info *swig_types[104];
+static swig_module_info swig_module = {swig_types, 103, 0, 0, 0, 0};
 #define SWIG_TypeQuery(name) SWIG_TypeQueryModule(&swig_module, &swig_module, name)
 #define SWIG_MangledTypeQuery(name) SWIG_MangledTypeQueryModule(&swig_module, &swig_module, name)
 
@@ -6704,7 +6700,6 @@ SWIGINTERN void std_vector_Sl_std_pair_Sl_double_Sc_double_Sg__Sg__insert__SWIG_
 #include "Core/Computation/PoissonNoiseBackground.h"
 #include "Core/Export/ExportToPython.h"
 #include "Core/Fitting/FitObjective.h"
-#include "Core/Fitting/IObserver.h"
 #include "Core/Fitting/IterationInfo.h"
 #include "Core/Fitting/PyFittingCallbacks.h"
 #include "Core/Scan/AngularSpecScan.h"
@@ -6713,7 +6708,7 @@ SWIGINTERN void std_vector_Sl_std_pair_Sl_double_Sc_double_Sg__Sg__insert__SWIG_
 #include "Core/Simulation/GISASSimulation.h"
 #include "Core/Simulation/ISimulation.h"
 #include "Core/Simulation/ISimulation2D.h"
-#include "Core/Simulation/OffSpecSimulation.h"
+#include "Core/Simulation/OffSpecularSimulation.h"
 #include "Core/Simulation/SimulationFactory.h"
 #include "Core/Simulation/SpecularSimulation.h"
 
@@ -25011,7 +25006,7 @@ SWIGINTERN PyObject *_wrap_kvector_t_complex(PyObject *SWIGUNUSEDPARM(self), PyO
   void *argp1 = 0 ;
   int res1 = 0 ;
   PyObject *swig_obj[1] ;
-  BasicVector3D< std::complex< double > > result;
+  BasicVector3D< complex_t > result;
   
   if (!args) SWIG_fail;
   swig_obj[0] = args;
@@ -25021,7 +25016,7 @@ SWIGINTERN PyObject *_wrap_kvector_t_complex(PyObject *SWIGUNUSEDPARM(self), PyO
   }
   arg1 = reinterpret_cast< BasicVector3D< double > * >(argp1);
   result = ((BasicVector3D< double > const *)arg1)->complex();
-  resultobj = SWIG_NewPointerObj((new BasicVector3D< std::complex< double > >(static_cast< const BasicVector3D< std::complex< double > >& >(result))), SWIGTYPE_p_BasicVector3DT_std__complexT_double_t_t, SWIG_POINTER_OWN |  0 );
+  resultobj = SWIG_NewPointerObj((new BasicVector3D< complex_t >(static_cast< const BasicVector3D< complex_t >& >(result))), SWIGTYPE_p_BasicVector3DT_std__complexT_double_t_t, SWIG_POINTER_OWN |  0 );
   return resultobj;
 fail:
   return NULL;
@@ -36843,169 +36838,6 @@ fail:
 }
 
 
-SWIGINTERN PyObject *_wrap_delete_IObserver(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
-  IObserver *arg1 = (IObserver *) 0 ;
-  void *argp1 = 0 ;
-  int res1 = 0 ;
-  PyObject *swig_obj[1] ;
-  
-  if (!args) SWIG_fail;
-  swig_obj[0] = args;
-  res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_IObserver, SWIG_POINTER_DISOWN |  0 );
-  if (!SWIG_IsOK(res1)) {
-    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "delete_IObserver" "', argument " "1"" of type '" "IObserver *""'"); 
-  }
-  arg1 = reinterpret_cast< IObserver * >(argp1);
-  delete arg1;
-  resultobj = SWIG_Py_Void();
-  return resultobj;
-fail:
-  return NULL;
-}
-
-
-SWIGINTERN PyObject *_wrap_IObserver_notify(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
-  IObserver *arg1 = (IObserver *) 0 ;
-  IObservable *arg2 = (IObservable *) 0 ;
-  void *argp1 = 0 ;
-  int res1 = 0 ;
-  void *argp2 = 0 ;
-  int res2 = 0 ;
-  PyObject *swig_obj[2] ;
-  
-  if (!SWIG_Python_UnpackTuple(args, "IObserver_notify", 2, 2, swig_obj)) SWIG_fail;
-  res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_IObserver, 0 |  0 );
-  if (!SWIG_IsOK(res1)) {
-    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "IObserver_notify" "', argument " "1"" of type '" "IObserver *""'"); 
-  }
-  arg1 = reinterpret_cast< IObserver * >(argp1);
-  res2 = SWIG_ConvertPtr(swig_obj[1], &argp2,SWIGTYPE_p_IObservable, 0 |  0 );
-  if (!SWIG_IsOK(res2)) {
-    SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "IObserver_notify" "', argument " "2"" of type '" "IObservable *""'"); 
-  }
-  arg2 = reinterpret_cast< IObservable * >(argp2);
-  (arg1)->notify(arg2);
-  resultobj = SWIG_Py_Void();
-  return resultobj;
-fail:
-  return NULL;
-}
-
-
-SWIGINTERN PyObject *IObserver_swigregister(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *obj;
-  if (!SWIG_Python_UnpackTuple(args, "swigregister", 1, 1, &obj)) return NULL;
-  SWIG_TypeNewClientData(SWIGTYPE_p_IObserver, SWIG_NewClientData(obj));
-  return SWIG_Py_Void();
-}
-
-SWIGINTERN PyObject *_wrap_delete_IObservable(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
-  IObservable *arg1 = (IObservable *) 0 ;
-  void *argp1 = 0 ;
-  int res1 = 0 ;
-  PyObject *swig_obj[1] ;
-  
-  if (!args) SWIG_fail;
-  swig_obj[0] = args;
-  res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_IObservable, SWIG_POINTER_DISOWN |  0 );
-  if (!SWIG_IsOK(res1)) {
-    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "delete_IObservable" "', argument " "1"" of type '" "IObservable *""'"); 
-  }
-  arg1 = reinterpret_cast< IObservable * >(argp1);
-  delete arg1;
-  resultobj = SWIG_Py_Void();
-  return resultobj;
-fail:
-  return NULL;
-}
-
-
-SWIGINTERN PyObject *_wrap_IObservable_attachObserver(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
-  IObservable *arg1 = (IObservable *) 0 ;
-  SwigValueWrapper< std::shared_ptr< IObserver > > arg2 ;
-  void *argp1 = 0 ;
-  int res1 = 0 ;
-  void *argp2 ;
-  int res2 = 0 ;
-  PyObject *swig_obj[2] ;
-  
-  if (!SWIG_Python_UnpackTuple(args, "IObservable_attachObserver", 2, 2, swig_obj)) SWIG_fail;
-  res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_IObservable, 0 |  0 );
-  if (!SWIG_IsOK(res1)) {
-    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "IObservable_attachObserver" "', argument " "1"" of type '" "IObservable *""'"); 
-  }
-  arg1 = reinterpret_cast< IObservable * >(argp1);
-  {
-    res2 = SWIG_ConvertPtr(swig_obj[1], &argp2, SWIGTYPE_p_std__shared_ptrT_IObserver_t,  0  | 0);
-    if (!SWIG_IsOK(res2)) {
-      SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "IObservable_attachObserver" "', argument " "2"" of type '" "IObservable::observer_t""'"); 
-    }  
-    if (!argp2) {
-      SWIG_exception_fail(SWIG_ValueError, "invalid null reference " "in method '" "IObservable_attachObserver" "', argument " "2"" of type '" "IObservable::observer_t""'");
-    } else {
-      IObservable::observer_t * temp = reinterpret_cast< IObservable::observer_t * >(argp2);
-      arg2 = *temp;
-      if (SWIG_IsNewObj(res2)) delete temp;
-    }
-  }
-  (arg1)->attachObserver(arg2);
-  resultobj = SWIG_Py_Void();
-  return resultobj;
-fail:
-  return NULL;
-}
-
-
-SWIGINTERN PyObject *_wrap_IObservable_notifyObservers(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
-  IObservable *arg1 = (IObservable *) 0 ;
-  void *argp1 = 0 ;
-  int res1 = 0 ;
-  PyObject *swig_obj[1] ;
-  
-  if (!args) SWIG_fail;
-  swig_obj[0] = args;
-  res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_IObservable, 0 |  0 );
-  if (!SWIG_IsOK(res1)) {
-    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "IObservable_notifyObservers" "', argument " "1"" of type '" "IObservable *""'"); 
-  }
-  arg1 = reinterpret_cast< IObservable * >(argp1);
-  (arg1)->notifyObservers();
-  resultobj = SWIG_Py_Void();
-  return resultobj;
-fail:
-  return NULL;
-}
-
-
-SWIGINTERN PyObject *_wrap_new_IObservable(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
-  IObservable *result = 0 ;
-  
-  if (!SWIG_Python_UnpackTuple(args, "new_IObservable", 0, 0, 0)) SWIG_fail;
-  result = (IObservable *)new IObservable();
-  resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_IObservable, SWIG_POINTER_NEW |  0 );
-  return resultobj;
-fail:
-  return NULL;
-}
-
-
-SWIGINTERN PyObject *IObservable_swigregister(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *obj;
-  if (!SWIG_Python_UnpackTuple(args, "swigregister", 1, 1, &obj)) return NULL;
-  SWIG_TypeNewClientData(SWIGTYPE_p_IObservable, SWIG_NewClientData(obj));
-  return SWIG_Py_Void();
-}
-
-SWIGINTERN PyObject *IObservable_swiginit(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  return SWIG_Python_InitShadowInstance(args);
-}
-
 SWIGINTERN PyObject *_wrap_new_IterationInfo(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
   PyObject *resultobj = 0;
   IterationInfo *result = 0 ;
@@ -39240,72 +39072,6 @@ fail:
 }
 
 
-SWIGINTERN PyObject *_wrap_ISimulation_setBeamIntensity(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
-  ISimulation *arg1 = (ISimulation *) 0 ;
-  double arg2 ;
-  void *argp1 = 0 ;
-  int res1 = 0 ;
-  double val2 ;
-  int ecode2 = 0 ;
-  PyObject *swig_obj[2] ;
-  
-  if (!SWIG_Python_UnpackTuple(args, "ISimulation_setBeamIntensity", 2, 2, swig_obj)) SWIG_fail;
-  res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_ISimulation, 0 |  0 );
-  if (!SWIG_IsOK(res1)) {
-    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "ISimulation_setBeamIntensity" "', argument " "1"" of type '" "ISimulation *""'"); 
-  }
-  arg1 = reinterpret_cast< ISimulation * >(argp1);
-  ecode2 = SWIG_AsVal_double(swig_obj[1], &val2);
-  if (!SWIG_IsOK(ecode2)) {
-    SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "ISimulation_setBeamIntensity" "', argument " "2"" of type '" "double""'");
-  } 
-  arg2 = static_cast< double >(val2);
-  (arg1)->setBeamIntensity(arg2);
-  resultobj = SWIG_Py_Void();
-  return resultobj;
-fail:
-  return NULL;
-}
-
-
-SWIGINTERN PyObject *_wrap_ISimulation_setBeamPolarization(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
-  ISimulation *arg1 = (ISimulation *) 0 ;
-  kvector_t arg2 ;
-  void *argp1 = 0 ;
-  int res1 = 0 ;
-  void *argp2 ;
-  int res2 = 0 ;
-  PyObject *swig_obj[2] ;
-  
-  if (!SWIG_Python_UnpackTuple(args, "ISimulation_setBeamPolarization", 2, 2, swig_obj)) SWIG_fail;
-  res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_ISimulation, 0 |  0 );
-  if (!SWIG_IsOK(res1)) {
-    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "ISimulation_setBeamPolarization" "', argument " "1"" of type '" "ISimulation *""'"); 
-  }
-  arg1 = reinterpret_cast< ISimulation * >(argp1);
-  {
-    res2 = SWIG_ConvertPtr(swig_obj[1], &argp2, SWIGTYPE_p_BasicVector3DT_double_t,  0  | 0);
-    if (!SWIG_IsOK(res2)) {
-      SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "ISimulation_setBeamPolarization" "', argument " "2"" of type '" "kvector_t const""'"); 
-    }  
-    if (!argp2) {
-      SWIG_exception_fail(SWIG_ValueError, "invalid null reference " "in method '" "ISimulation_setBeamPolarization" "', argument " "2"" of type '" "kvector_t const""'");
-    } else {
-      kvector_t * temp = reinterpret_cast< kvector_t * >(argp2);
-      arg2 = *temp;
-      if (SWIG_IsNewObj(res2)) delete temp;
-    }
-  }
-  (arg1)->setBeamPolarization(arg2);
-  resultobj = SWIG_Py_Void();
-  return resultobj;
-fail:
-  return NULL;
-}
-
-
 SWIGINTERN PyObject *_wrap_ISimulation_setDetectorResolutionFunction(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
   PyObject *resultobj = 0;
   ISimulation *arg1 = (ISimulation *) 0 ;
@@ -41605,7 +41371,7 @@ SWIGINTERN PyObject *SpecularSimulation_swiginit(PyObject *SWIGUNUSEDPARM(self),
   return SWIG_Python_InitShadowInstance(args);
 }
 
-SWIGINTERN PyObject *_wrap_new_OffSpecSimulation__SWIG_0(PyObject *SWIGUNUSEDPARM(self), Py_ssize_t nobjs, PyObject **swig_obj) {
+SWIGINTERN PyObject *_wrap_new_OffSpecularSimulation__SWIG_0(PyObject *SWIGUNUSEDPARM(self), Py_ssize_t nobjs, PyObject **swig_obj) {
   PyObject *resultobj = 0;
   Beam *arg1 = 0 ;
   MultiLayer *arg2 = 0 ;
@@ -41616,64 +41382,64 @@ SWIGINTERN PyObject *_wrap_new_OffSpecSimulation__SWIG_0(PyObject *SWIGUNUSEDPAR
   int res2 = 0 ;
   void *argp3 = 0 ;
   int res3 = 0 ;
-  OffSpecSimulation *result = 0 ;
+  OffSpecularSimulation *result = 0 ;
   
   if ((nobjs < 3) || (nobjs > 3)) SWIG_fail;
   res1 = SWIG_ConvertPtr(swig_obj[0], &argp1, SWIGTYPE_p_Beam,  0  | 0);
   if (!SWIG_IsOK(res1)) {
-    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "new_OffSpecSimulation" "', argument " "1"" of type '" "Beam const &""'"); 
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "new_OffSpecularSimulation" "', argument " "1"" of type '" "Beam const &""'"); 
   }
   if (!argp1) {
-    SWIG_exception_fail(SWIG_ValueError, "invalid null reference " "in method '" "new_OffSpecSimulation" "', argument " "1"" of type '" "Beam const &""'"); 
+    SWIG_exception_fail(SWIG_ValueError, "invalid null reference " "in method '" "new_OffSpecularSimulation" "', argument " "1"" of type '" "Beam const &""'"); 
   }
   arg1 = reinterpret_cast< Beam * >(argp1);
   res2 = SWIG_ConvertPtr(swig_obj[1], &argp2, SWIGTYPE_p_MultiLayer,  0  | 0);
   if (!SWIG_IsOK(res2)) {
-    SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "new_OffSpecSimulation" "', argument " "2"" of type '" "MultiLayer const &""'"); 
+    SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "new_OffSpecularSimulation" "', argument " "2"" of type '" "MultiLayer const &""'"); 
   }
   if (!argp2) {
-    SWIG_exception_fail(SWIG_ValueError, "invalid null reference " "in method '" "new_OffSpecSimulation" "', argument " "2"" of type '" "MultiLayer const &""'"); 
+    SWIG_exception_fail(SWIG_ValueError, "invalid null reference " "in method '" "new_OffSpecularSimulation" "', argument " "2"" of type '" "MultiLayer const &""'"); 
   }
   arg2 = reinterpret_cast< MultiLayer * >(argp2);
   res3 = SWIG_ConvertPtr(swig_obj[2], &argp3, SWIGTYPE_p_IDetector,  0  | 0);
   if (!SWIG_IsOK(res3)) {
-    SWIG_exception_fail(SWIG_ArgError(res3), "in method '" "new_OffSpecSimulation" "', argument " "3"" of type '" "IDetector const &""'"); 
+    SWIG_exception_fail(SWIG_ArgError(res3), "in method '" "new_OffSpecularSimulation" "', argument " "3"" of type '" "IDetector const &""'"); 
   }
   if (!argp3) {
-    SWIG_exception_fail(SWIG_ValueError, "invalid null reference " "in method '" "new_OffSpecSimulation" "', argument " "3"" of type '" "IDetector const &""'"); 
+    SWIG_exception_fail(SWIG_ValueError, "invalid null reference " "in method '" "new_OffSpecularSimulation" "', argument " "3"" of type '" "IDetector const &""'"); 
   }
   arg3 = reinterpret_cast< IDetector * >(argp3);
-  result = (OffSpecSimulation *)new OffSpecSimulation((Beam const &)*arg1,(MultiLayer const &)*arg2,(IDetector const &)*arg3);
-  resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_OffSpecSimulation, SWIG_POINTER_NEW |  0 );
+  result = (OffSpecularSimulation *)new OffSpecularSimulation((Beam const &)*arg1,(MultiLayer const &)*arg2,(IDetector const &)*arg3);
+  resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_OffSpecularSimulation, SWIG_POINTER_NEW |  0 );
   return resultobj;
 fail:
   return NULL;
 }
 
 
-SWIGINTERN PyObject *_wrap_new_OffSpecSimulation__SWIG_1(PyObject *SWIGUNUSEDPARM(self), Py_ssize_t nobjs, PyObject **SWIGUNUSEDPARM(swig_obj)) {
+SWIGINTERN PyObject *_wrap_new_OffSpecularSimulation__SWIG_1(PyObject *SWIGUNUSEDPARM(self), Py_ssize_t nobjs, PyObject **SWIGUNUSEDPARM(swig_obj)) {
   PyObject *resultobj = 0;
-  OffSpecSimulation *result = 0 ;
+  OffSpecularSimulation *result = 0 ;
   
   if ((nobjs < 0) || (nobjs > 0)) SWIG_fail;
-  result = (OffSpecSimulation *)new OffSpecSimulation();
-  resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_OffSpecSimulation, SWIG_POINTER_NEW |  0 );
+  result = (OffSpecularSimulation *)new OffSpecularSimulation();
+  resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_OffSpecularSimulation, SWIG_POINTER_NEW |  0 );
   return resultobj;
 fail:
   return NULL;
 }
 
 
-SWIGINTERN PyObject *_wrap_new_OffSpecSimulation(PyObject *self, PyObject *args) {
+SWIGINTERN PyObject *_wrap_new_OffSpecularSimulation(PyObject *self, PyObject *args) {
   Py_ssize_t argc;
   PyObject *argv[4] = {
     0
   };
   
-  if (!(argc = SWIG_Python_UnpackTuple(args, "new_OffSpecSimulation", 0, 3, argv))) SWIG_fail;
+  if (!(argc = SWIG_Python_UnpackTuple(args, "new_OffSpecularSimulation", 0, 3, argv))) SWIG_fail;
   --argc;
   if (argc == 0) {
-    return _wrap_new_OffSpecSimulation__SWIG_1(self, argc, argv);
+    return _wrap_new_OffSpecularSimulation__SWIG_1(self, argc, argv);
   }
   if (argc == 3) {
     int _v;
@@ -41686,35 +41452,35 @@ SWIGINTERN PyObject *_wrap_new_OffSpecSimulation(PyObject *self, PyObject *args)
         int res = SWIG_ConvertPtr(argv[2], 0, SWIGTYPE_p_IDetector, SWIG_POINTER_NO_NULL | 0);
         _v = SWIG_CheckState(res);
         if (_v) {
-          return _wrap_new_OffSpecSimulation__SWIG_0(self, argc, argv);
+          return _wrap_new_OffSpecularSimulation__SWIG_0(self, argc, argv);
         }
       }
     }
   }
   
 fail:
-  SWIG_Python_RaiseOrModifyTypeError("Wrong number or type of arguments for overloaded function 'new_OffSpecSimulation'.\n"
+  SWIG_Python_RaiseOrModifyTypeError("Wrong number or type of arguments for overloaded function 'new_OffSpecularSimulation'.\n"
     "  Possible C/C++ prototypes are:\n"
-    "    OffSpecSimulation::OffSpecSimulation(Beam const &,MultiLayer const &,IDetector const &)\n"
-    "    OffSpecSimulation::OffSpecSimulation()\n");
+    "    OffSpecularSimulation::OffSpecularSimulation(Beam const &,MultiLayer const &,IDetector const &)\n"
+    "    OffSpecularSimulation::OffSpecularSimulation()\n");
   return 0;
 }
 
 
-SWIGINTERN PyObject *_wrap_delete_OffSpecSimulation(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+SWIGINTERN PyObject *_wrap_delete_OffSpecularSimulation(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
   PyObject *resultobj = 0;
-  OffSpecSimulation *arg1 = (OffSpecSimulation *) 0 ;
+  OffSpecularSimulation *arg1 = (OffSpecularSimulation *) 0 ;
   void *argp1 = 0 ;
   int res1 = 0 ;
   PyObject *swig_obj[1] ;
   
   if (!args) SWIG_fail;
   swig_obj[0] = args;
-  res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_OffSpecSimulation, SWIG_POINTER_DISOWN |  0 );
+  res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_OffSpecularSimulation, SWIG_POINTER_DISOWN |  0 );
   if (!SWIG_IsOK(res1)) {
-    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "delete_OffSpecSimulation" "', argument " "1"" of type '" "OffSpecSimulation *""'"); 
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "delete_OffSpecularSimulation" "', argument " "1"" of type '" "OffSpecularSimulation *""'"); 
   }
-  arg1 = reinterpret_cast< OffSpecSimulation * >(argp1);
+  arg1 = reinterpret_cast< OffSpecularSimulation * >(argp1);
   delete arg1;
   resultobj = SWIG_Py_Void();
   return resultobj;
@@ -41723,32 +41489,32 @@ fail:
 }
 
 
-SWIGINTERN PyObject *_wrap_OffSpecSimulation_clone(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+SWIGINTERN PyObject *_wrap_OffSpecularSimulation_clone(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
   PyObject *resultobj = 0;
-  OffSpecSimulation *arg1 = (OffSpecSimulation *) 0 ;
+  OffSpecularSimulation *arg1 = (OffSpecularSimulation *) 0 ;
   void *argp1 = 0 ;
   int res1 = 0 ;
   PyObject *swig_obj[1] ;
-  OffSpecSimulation *result = 0 ;
+  OffSpecularSimulation *result = 0 ;
   
   if (!args) SWIG_fail;
   swig_obj[0] = args;
-  res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_OffSpecSimulation, 0 |  0 );
+  res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_OffSpecularSimulation, 0 |  0 );
   if (!SWIG_IsOK(res1)) {
-    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "OffSpecSimulation_clone" "', argument " "1"" of type '" "OffSpecSimulation const *""'"); 
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "OffSpecularSimulation_clone" "', argument " "1"" of type '" "OffSpecularSimulation const *""'"); 
   }
-  arg1 = reinterpret_cast< OffSpecSimulation * >(argp1);
-  result = (OffSpecSimulation *)((OffSpecSimulation const *)arg1)->clone();
-  resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_OffSpecSimulation, 0 |  0 );
+  arg1 = reinterpret_cast< OffSpecularSimulation * >(argp1);
+  result = (OffSpecularSimulation *)((OffSpecularSimulation const *)arg1)->clone();
+  resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_OffSpecularSimulation, 0 |  0 );
   return resultobj;
 fail:
   return NULL;
 }
 
 
-SWIGINTERN PyObject *_wrap_OffSpecSimulation_accept(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+SWIGINTERN PyObject *_wrap_OffSpecularSimulation_accept(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
   PyObject *resultobj = 0;
-  OffSpecSimulation *arg1 = (OffSpecSimulation *) 0 ;
+  OffSpecularSimulation *arg1 = (OffSpecularSimulation *) 0 ;
   INodeVisitor *arg2 = (INodeVisitor *) 0 ;
   void *argp1 = 0 ;
   int res1 = 0 ;
@@ -41756,18 +41522,18 @@ SWIGINTERN PyObject *_wrap_OffSpecSimulation_accept(PyObject *SWIGUNUSEDPARM(sel
   int res2 = 0 ;
   PyObject *swig_obj[2] ;
   
-  if (!SWIG_Python_UnpackTuple(args, "OffSpecSimulation_accept", 2, 2, swig_obj)) SWIG_fail;
-  res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_OffSpecSimulation, 0 |  0 );
+  if (!SWIG_Python_UnpackTuple(args, "OffSpecularSimulation_accept", 2, 2, swig_obj)) SWIG_fail;
+  res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_OffSpecularSimulation, 0 |  0 );
   if (!SWIG_IsOK(res1)) {
-    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "OffSpecSimulation_accept" "', argument " "1"" of type '" "OffSpecSimulation const *""'"); 
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "OffSpecularSimulation_accept" "', argument " "1"" of type '" "OffSpecularSimulation const *""'"); 
   }
-  arg1 = reinterpret_cast< OffSpecSimulation * >(argp1);
+  arg1 = reinterpret_cast< OffSpecularSimulation * >(argp1);
   res2 = SWIG_ConvertPtr(swig_obj[1], &argp2,SWIGTYPE_p_INodeVisitor, 0 |  0 );
   if (!SWIG_IsOK(res2)) {
-    SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "OffSpecSimulation_accept" "', argument " "2"" of type '" "INodeVisitor *""'"); 
+    SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "OffSpecularSimulation_accept" "', argument " "2"" of type '" "INodeVisitor *""'"); 
   }
   arg2 = reinterpret_cast< INodeVisitor * >(argp2);
-  ((OffSpecSimulation const *)arg1)->accept(arg2);
+  ((OffSpecularSimulation const *)arg1)->accept(arg2);
   resultobj = SWIG_Py_Void();
   return resultobj;
 fail:
@@ -41775,20 +41541,20 @@ fail:
 }
 
 
-SWIGINTERN PyObject *_wrap_OffSpecSimulation_prepareSimulation(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+SWIGINTERN PyObject *_wrap_OffSpecularSimulation_prepareSimulation(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
   PyObject *resultobj = 0;
-  OffSpecSimulation *arg1 = (OffSpecSimulation *) 0 ;
+  OffSpecularSimulation *arg1 = (OffSpecularSimulation *) 0 ;
   void *argp1 = 0 ;
   int res1 = 0 ;
   PyObject *swig_obj[1] ;
   
   if (!args) SWIG_fail;
   swig_obj[0] = args;
-  res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_OffSpecSimulation, 0 |  0 );
+  res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_OffSpecularSimulation, 0 |  0 );
   if (!SWIG_IsOK(res1)) {
-    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "OffSpecSimulation_prepareSimulation" "', argument " "1"" of type '" "OffSpecSimulation *""'"); 
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "OffSpecularSimulation_prepareSimulation" "', argument " "1"" of type '" "OffSpecularSimulation *""'"); 
   }
-  arg1 = reinterpret_cast< OffSpecSimulation * >(argp1);
+  arg1 = reinterpret_cast< OffSpecularSimulation * >(argp1);
   (arg1)->prepareSimulation();
   resultobj = SWIG_Py_Void();
   return resultobj;
@@ -41797,9 +41563,9 @@ fail:
 }
 
 
-SWIGINTERN PyObject *_wrap_OffSpecSimulation_result(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+SWIGINTERN PyObject *_wrap_OffSpecularSimulation_result(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
   PyObject *resultobj = 0;
-  OffSpecSimulation *arg1 = (OffSpecSimulation *) 0 ;
+  OffSpecularSimulation *arg1 = (OffSpecularSimulation *) 0 ;
   void *argp1 = 0 ;
   int res1 = 0 ;
   PyObject *swig_obj[1] ;
@@ -41807,12 +41573,12 @@ SWIGINTERN PyObject *_wrap_OffSpecSimulation_result(PyObject *SWIGUNUSEDPARM(sel
   
   if (!args) SWIG_fail;
   swig_obj[0] = args;
-  res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_OffSpecSimulation, 0 |  0 );
+  res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_OffSpecularSimulation, 0 |  0 );
   if (!SWIG_IsOK(res1)) {
-    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "OffSpecSimulation_result" "', argument " "1"" of type '" "OffSpecSimulation const *""'"); 
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "OffSpecularSimulation_result" "', argument " "1"" of type '" "OffSpecularSimulation const *""'"); 
   }
-  arg1 = reinterpret_cast< OffSpecSimulation * >(argp1);
-  result = ((OffSpecSimulation const *)arg1)->result();
+  arg1 = reinterpret_cast< OffSpecularSimulation * >(argp1);
+  result = ((OffSpecularSimulation const *)arg1)->result();
   resultobj = SWIG_NewPointerObj((new SimulationResult(static_cast< const SimulationResult& >(result))), SWIGTYPE_p_SimulationResult, SWIG_POINTER_OWN |  0 );
   return resultobj;
 fail:
@@ -41820,9 +41586,9 @@ fail:
 }
 
 
-SWIGINTERN PyObject *_wrap_OffSpecSimulation_setBeamParameters(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+SWIGINTERN PyObject *_wrap_OffSpecularSimulation_setBeamParameters(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
   PyObject *resultobj = 0;
-  OffSpecSimulation *arg1 = (OffSpecSimulation *) 0 ;
+  OffSpecularSimulation *arg1 = (OffSpecularSimulation *) 0 ;
   double arg2 ;
   IAxis *arg3 = 0 ;
   double arg4 ;
@@ -41836,28 +41602,28 @@ SWIGINTERN PyObject *_wrap_OffSpecSimulation_setBeamParameters(PyObject *SWIGUNU
   int ecode4 = 0 ;
   PyObject *swig_obj[4] ;
   
-  if (!SWIG_Python_UnpackTuple(args, "OffSpecSimulation_setBeamParameters", 4, 4, swig_obj)) SWIG_fail;
-  res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_OffSpecSimulation, 0 |  0 );
+  if (!SWIG_Python_UnpackTuple(args, "OffSpecularSimulation_setBeamParameters", 4, 4, swig_obj)) SWIG_fail;
+  res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_OffSpecularSimulation, 0 |  0 );
   if (!SWIG_IsOK(res1)) {
-    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "OffSpecSimulation_setBeamParameters" "', argument " "1"" of type '" "OffSpecSimulation *""'"); 
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "OffSpecularSimulation_setBeamParameters" "', argument " "1"" of type '" "OffSpecularSimulation *""'"); 
   }
-  arg1 = reinterpret_cast< OffSpecSimulation * >(argp1);
+  arg1 = reinterpret_cast< OffSpecularSimulation * >(argp1);
   ecode2 = SWIG_AsVal_double(swig_obj[1], &val2);
   if (!SWIG_IsOK(ecode2)) {
-    SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "OffSpecSimulation_setBeamParameters" "', argument " "2"" of type '" "double""'");
+    SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "OffSpecularSimulation_setBeamParameters" "', argument " "2"" of type '" "double""'");
   } 
   arg2 = static_cast< double >(val2);
   res3 = SWIG_ConvertPtr(swig_obj[2], &argp3, SWIGTYPE_p_IAxis,  0  | 0);
   if (!SWIG_IsOK(res3)) {
-    SWIG_exception_fail(SWIG_ArgError(res3), "in method '" "OffSpecSimulation_setBeamParameters" "', argument " "3"" of type '" "IAxis const &""'"); 
+    SWIG_exception_fail(SWIG_ArgError(res3), "in method '" "OffSpecularSimulation_setBeamParameters" "', argument " "3"" of type '" "IAxis const &""'"); 
   }
   if (!argp3) {
-    SWIG_exception_fail(SWIG_ValueError, "invalid null reference " "in method '" "OffSpecSimulation_setBeamParameters" "', argument " "3"" of type '" "IAxis const &""'"); 
+    SWIG_exception_fail(SWIG_ValueError, "invalid null reference " "in method '" "OffSpecularSimulation_setBeamParameters" "', argument " "3"" of type '" "IAxis const &""'"); 
   }
   arg3 = reinterpret_cast< IAxis * >(argp3);
   ecode4 = SWIG_AsVal_double(swig_obj[3], &val4);
   if (!SWIG_IsOK(ecode4)) {
-    SWIG_exception_fail(SWIG_ArgError(ecode4), "in method '" "OffSpecSimulation_setBeamParameters" "', argument " "4"" of type '" "double""'");
+    SWIG_exception_fail(SWIG_ArgError(ecode4), "in method '" "OffSpecularSimulation_setBeamParameters" "', argument " "4"" of type '" "double""'");
   } 
   arg4 = static_cast< double >(val4);
   (arg1)->setBeamParameters(arg2,(IAxis const &)*arg3,arg4);
@@ -41868,9 +41634,9 @@ fail:
 }
 
 
-SWIGINTERN PyObject *_wrap_OffSpecSimulation_beamAxis(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+SWIGINTERN PyObject *_wrap_OffSpecularSimulation_beamAxis(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
   PyObject *resultobj = 0;
-  OffSpecSimulation *arg1 = (OffSpecSimulation *) 0 ;
+  OffSpecularSimulation *arg1 = (OffSpecularSimulation *) 0 ;
   void *argp1 = 0 ;
   int res1 = 0 ;
   PyObject *swig_obj[1] ;
@@ -41878,12 +41644,12 @@ SWIGINTERN PyObject *_wrap_OffSpecSimulation_beamAxis(PyObject *SWIGUNUSEDPARM(s
   
   if (!args) SWIG_fail;
   swig_obj[0] = args;
-  res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_OffSpecSimulation, 0 |  0 );
+  res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_OffSpecularSimulation, 0 |  0 );
   if (!SWIG_IsOK(res1)) {
-    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "OffSpecSimulation_beamAxis" "', argument " "1"" of type '" "OffSpecSimulation const *""'"); 
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "OffSpecularSimulation_beamAxis" "', argument " "1"" of type '" "OffSpecularSimulation const *""'"); 
   }
-  arg1 = reinterpret_cast< OffSpecSimulation * >(argp1);
-  result = (IAxis *)((OffSpecSimulation const *)arg1)->beamAxis();
+  arg1 = reinterpret_cast< OffSpecularSimulation * >(argp1);
+  result = (IAxis *)((OffSpecularSimulation const *)arg1)->beamAxis();
   resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_IAxis, 0 |  0 );
   return resultobj;
 fail:
@@ -41891,9 +41657,9 @@ fail:
 }
 
 
-SWIGINTERN PyObject *_wrap_OffSpecSimulation_intensityMapSize(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+SWIGINTERN PyObject *_wrap_OffSpecularSimulation_intensityMapSize(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
   PyObject *resultobj = 0;
-  OffSpecSimulation *arg1 = (OffSpecSimulation *) 0 ;
+  OffSpecularSimulation *arg1 = (OffSpecularSimulation *) 0 ;
   void *argp1 = 0 ;
   int res1 = 0 ;
   PyObject *swig_obj[1] ;
@@ -41901,12 +41667,12 @@ SWIGINTERN PyObject *_wrap_OffSpecSimulation_intensityMapSize(PyObject *SWIGUNUS
   
   if (!args) SWIG_fail;
   swig_obj[0] = args;
-  res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_OffSpecSimulation, 0 |  0 );
+  res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_OffSpecularSimulation, 0 |  0 );
   if (!SWIG_IsOK(res1)) {
-    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "OffSpecSimulation_intensityMapSize" "', argument " "1"" of type '" "OffSpecSimulation const *""'"); 
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "OffSpecularSimulation_intensityMapSize" "', argument " "1"" of type '" "OffSpecularSimulation const *""'"); 
   }
-  arg1 = reinterpret_cast< OffSpecSimulation * >(argp1);
-  result = ((OffSpecSimulation const *)arg1)->intensityMapSize();
+  arg1 = reinterpret_cast< OffSpecularSimulation * >(argp1);
+  result = ((OffSpecularSimulation const *)arg1)->intensityMapSize();
   resultobj = SWIG_From_size_t(static_cast< size_t >(result));
   return resultobj;
 fail:
@@ -41914,14 +41680,14 @@ fail:
 }
 
 
-SWIGINTERN PyObject *OffSpecSimulation_swigregister(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+SWIGINTERN PyObject *OffSpecularSimulation_swigregister(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
   PyObject *obj;
   if (!SWIG_Python_UnpackTuple(args, "swigregister", 1, 1, &obj)) return NULL;
-  SWIG_TypeNewClientData(SWIGTYPE_p_OffSpecSimulation, SWIG_NewClientData(obj));
+  SWIG_TypeNewClientData(SWIGTYPE_p_OffSpecularSimulation, SWIG_NewClientData(obj));
   return SWIG_Py_Void();
 }
 
-SWIGINTERN PyObject *OffSpecSimulation_swiginit(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+SWIGINTERN PyObject *OffSpecularSimulation_swiginit(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
   return SWIG_Python_InitShadowInstance(args);
 }
 
@@ -43532,49 +43298,6 @@ static PyMethodDef SwigMethods[] = {
 	 { "GetPatchVersionNumber", _wrap_GetPatchVersionNumber, METH_NOARGS, "GetPatchVersionNumber() -> int"},
 	 { "GetName", _wrap_GetName, METH_NOARGS, "GetName() -> std::string"},
 	 { "GetVersionNumber", _wrap_GetVersionNumber, METH_NOARGS, "GetVersionNumber() -> std::string"},
-	 { "delete_IObserver", _wrap_delete_IObserver, METH_O, "\n"
-		"delete_IObserver(IObserver self)\n"
-		"IObserver::~IObserver()\n"
-		"\n"
-		""},
-	 { "IObserver_notify", _wrap_IObserver_notify, METH_VARARGS, "\n"
-		"IObserver_notify(IObserver self, IObservable subject)\n"
-		"virtual void IObserver::notify(IObservable *subject)=0\n"
-		"\n"
-		"method which is used by observable subject to notify change in status \n"
-		"\n"
-		""},
-	 { "IObserver_swigregister", IObserver_swigregister, METH_O, NULL},
-	 { "delete_IObservable", _wrap_delete_IObservable, METH_O, "\n"
-		"delete_IObservable(IObservable self)\n"
-		"IObservable::~IObservable()\n"
-		"\n"
-		""},
-	 { "IObservable_attachObserver", _wrap_IObservable_attachObserver, METH_VARARGS, "\n"
-		"IObservable_attachObserver(IObservable self, IObservable::observer_t obj)\n"
-		"void IObservable::attachObserver(observer_t obj)\n"
-		"\n"
-		"attach observer to the list of observers \n"
-		"\n"
-		""},
-	 { "IObservable_notifyObservers", _wrap_IObservable_notifyObservers, METH_O, "\n"
-		"IObservable_notifyObservers(IObservable self)\n"
-		"void IObservable::notifyObservers()\n"
-		"\n"
-		"notify observers about change in status \n"
-		"\n"
-		""},
-	 { "new_IObservable", _wrap_new_IObservable, METH_NOARGS, "\n"
-		"new_IObservable() -> IObservable\n"
-		"\n"
-		"\n"
-		"Observable interface from Observer pattern\n"
-		"\n"
-		"C++ includes: IObserver.h\n"
-		"\n"
-		""},
-	 { "IObservable_swigregister", IObservable_swigregister, METH_O, NULL},
-	 { "IObservable_swiginit", IObservable_swiginit, METH_VARARGS, NULL},
 	 { "new_IterationInfo", _wrap_new_IterationInfo, METH_NOARGS, "\n"
 		"new_IterationInfo() -> IterationInfo\n"
 		"IterationInfo::IterationInfo()\n"
@@ -43827,18 +43550,6 @@ static PyMethodDef SwigMethods[] = {
 		"const IDetector& ISimulation::detector() const\n"
 		"\n"
 		""},
-	 { "ISimulation_setBeamIntensity", _wrap_ISimulation_setBeamIntensity, METH_VARARGS, "\n"
-		"ISimulation_setBeamIntensity(ISimulation self, double intensity)\n"
-		"void ISimulation::setBeamIntensity(double intensity)\n"
-		"\n"
-		""},
-	 { "ISimulation_setBeamPolarization", _wrap_ISimulation_setBeamPolarization, METH_VARARGS, "\n"
-		"ISimulation_setBeamPolarization(ISimulation self, kvector_t bloch_vector)\n"
-		"void ISimulation::setBeamPolarization(const kvector_t bloch_vector)\n"
-		"\n"
-		"Sets the beam polarization according to the given Bloch vector. \n"
-		"\n"
-		""},
 	 { "ISimulation_setDetectorResolutionFunction", _wrap_ISimulation_setDetectorResolutionFunction, METH_VARARGS, "\n"
 		"ISimulation_setDetectorResolutionFunction(ISimulation self, IResolutionFunction2D const & resolution_function)\n"
 		"void ISimulation::setDetectorResolutionFunction(const IResolutionFunction2D &resolution_function)\n"
@@ -44201,64 +43912,64 @@ static PyMethodDef SwigMethods[] = {
 		""},
 	 { "SpecularSimulation_swigregister", SpecularSimulation_swigregister, METH_O, NULL},
 	 { "SpecularSimulation_swiginit", SpecularSimulation_swiginit, METH_VARARGS, NULL},
-	 { "new_OffSpecSimulation", _wrap_new_OffSpecSimulation, METH_VARARGS, "\n"
-		"OffSpecSimulation(Beam const & beam, MultiLayer const & sample, IDetector const & detector)\n"
-		"new_OffSpecSimulation() -> OffSpecSimulation\n"
-		"OffSpecSimulation::OffSpecSimulation()\n"
+	 { "new_OffSpecularSimulation", _wrap_new_OffSpecularSimulation, METH_VARARGS, "\n"
+		"OffSpecularSimulation(Beam const & beam, MultiLayer const & sample, IDetector const & detector)\n"
+		"new_OffSpecularSimulation() -> OffSpecularSimulation\n"
+		"OffSpecularSimulation::OffSpecularSimulation()\n"
 		"\n"
 		""},
-	 { "delete_OffSpecSimulation", _wrap_delete_OffSpecSimulation, METH_O, "\n"
-		"delete_OffSpecSimulation(OffSpecSimulation self)\n"
-		"OffSpecSimulation::~OffSpecSimulation() override\n"
+	 { "delete_OffSpecularSimulation", _wrap_delete_OffSpecularSimulation, METH_O, "\n"
+		"delete_OffSpecularSimulation(OffSpecularSimulation self)\n"
+		"OffSpecularSimulation::~OffSpecularSimulation() override\n"
 		"\n"
 		""},
-	 { "OffSpecSimulation_clone", _wrap_OffSpecSimulation_clone, METH_O, "\n"
-		"OffSpecSimulation_clone(OffSpecSimulation self) -> OffSpecSimulation\n"
-		"OffSpecSimulation* OffSpecSimulation::clone() const override\n"
+	 { "OffSpecularSimulation_clone", _wrap_OffSpecularSimulation_clone, METH_O, "\n"
+		"OffSpecularSimulation_clone(OffSpecularSimulation self) -> OffSpecularSimulation\n"
+		"OffSpecularSimulation* OffSpecularSimulation::clone() const override\n"
 		"\n"
 		""},
-	 { "OffSpecSimulation_accept", _wrap_OffSpecSimulation_accept, METH_VARARGS, "\n"
-		"OffSpecSimulation_accept(OffSpecSimulation self, INodeVisitor * visitor)\n"
-		"void OffSpecSimulation::accept(INodeVisitor *visitor) const override\n"
+	 { "OffSpecularSimulation_accept", _wrap_OffSpecularSimulation_accept, METH_VARARGS, "\n"
+		"OffSpecularSimulation_accept(OffSpecularSimulation self, INodeVisitor * visitor)\n"
+		"void OffSpecularSimulation::accept(INodeVisitor *visitor) const override\n"
 		"\n"
 		""},
-	 { "OffSpecSimulation_prepareSimulation", _wrap_OffSpecSimulation_prepareSimulation, METH_O, "\n"
-		"OffSpecSimulation_prepareSimulation(OffSpecSimulation self)\n"
-		"void OffSpecSimulation::prepareSimulation() override\n"
+	 { "OffSpecularSimulation_prepareSimulation", _wrap_OffSpecularSimulation_prepareSimulation, METH_O, "\n"
+		"OffSpecularSimulation_prepareSimulation(OffSpecularSimulation self)\n"
+		"void OffSpecularSimulation::prepareSimulation() override\n"
 		"\n"
 		"Put into a clean state for running a simulation. \n"
 		"\n"
 		""},
-	 { "OffSpecSimulation_result", _wrap_OffSpecSimulation_result, METH_O, "\n"
-		"OffSpecSimulation_result(OffSpecSimulation self) -> SimulationResult\n"
-		"SimulationResult OffSpecSimulation::result() const override\n"
+	 { "OffSpecularSimulation_result", _wrap_OffSpecularSimulation_result, METH_O, "\n"
+		"OffSpecularSimulation_result(OffSpecularSimulation self) -> SimulationResult\n"
+		"SimulationResult OffSpecularSimulation::result() const override\n"
 		"\n"
 		"Returns the results of the simulation in a format that supports unit conversion and export to numpy arrays \n"
 		"\n"
 		""},
-	 { "OffSpecSimulation_setBeamParameters", _wrap_OffSpecSimulation_setBeamParameters, METH_VARARGS, "\n"
-		"OffSpecSimulation_setBeamParameters(OffSpecSimulation self, double wavelength, IAxis alpha_axis, double phi_i)\n"
-		"void OffSpecSimulation::setBeamParameters(double wavelength, const IAxis &alpha_axis, double phi_i)\n"
+	 { "OffSpecularSimulation_setBeamParameters", _wrap_OffSpecularSimulation_setBeamParameters, METH_VARARGS, "\n"
+		"OffSpecularSimulation_setBeamParameters(OffSpecularSimulation self, double wavelength, IAxis alpha_axis, double phi_i)\n"
+		"void OffSpecularSimulation::setBeamParameters(double wavelength, const IAxis &alpha_axis, double phi_i)\n"
 		"\n"
 		"Sets beam parameters from here (forwarded to Instrument) \n"
 		"\n"
 		""},
-	 { "OffSpecSimulation_beamAxis", _wrap_OffSpecSimulation_beamAxis, METH_O, "\n"
-		"OffSpecSimulation_beamAxis(OffSpecSimulation self) -> IAxis\n"
-		"const IAxis * OffSpecSimulation::beamAxis() const\n"
+	 { "OffSpecularSimulation_beamAxis", _wrap_OffSpecularSimulation_beamAxis, METH_O, "\n"
+		"OffSpecularSimulation_beamAxis(OffSpecularSimulation self) -> IAxis\n"
+		"const IAxis * OffSpecularSimulation::beamAxis() const\n"
 		"\n"
 		"Returns axis of the beam. \n"
 		"\n"
 		""},
-	 { "OffSpecSimulation_intensityMapSize", _wrap_OffSpecSimulation_intensityMapSize, METH_O, "\n"
-		"OffSpecSimulation_intensityMapSize(OffSpecSimulation self) -> size_t\n"
-		"size_t OffSpecSimulation::intensityMapSize() const override\n"
+	 { "OffSpecularSimulation_intensityMapSize", _wrap_OffSpecularSimulation_intensityMapSize, METH_O, "\n"
+		"OffSpecularSimulation_intensityMapSize(OffSpecularSimulation self) -> size_t\n"
+		"size_t OffSpecularSimulation::intensityMapSize() const override\n"
 		"\n"
 		"Returns the total number of the intensity values in the simulation result. \n"
 		"\n"
 		""},
-	 { "OffSpecSimulation_swigregister", OffSpecSimulation_swigregister, METH_O, NULL},
-	 { "OffSpecSimulation_swiginit", OffSpecSimulation_swiginit, METH_VARARGS, NULL},
+	 { "OffSpecularSimulation_swigregister", OffSpecularSimulation_swigregister, METH_O, NULL},
+	 { "OffSpecularSimulation_swiginit", OffSpecularSimulation_swiginit, METH_VARARGS, NULL},
 	 { "delete_IBackground", _wrap_delete_IBackground, METH_O, "\n"
 		"delete_IBackground(IBackground self)\n"
 		"IBackground::~IBackground()\n"
@@ -44365,8 +44076,8 @@ static void *_p_DepthProbeSimulationTo_p_ISimulation(void *x, int *SWIGUNUSEDPAR
 static void *_p_SpecularSimulationTo_p_ISimulation(void *x, int *SWIGUNUSEDPARM(newmemory)) {
     return (void *)((ISimulation *)  ((SpecularSimulation *) x));
 }
-static void *_p_OffSpecSimulationTo_p_ISimulation(void *x, int *SWIGUNUSEDPARM(newmemory)) {
-    return (void *)((ISimulation *) (ISimulation2D *) ((OffSpecSimulation *) x));
+static void *_p_OffSpecularSimulationTo_p_ISimulation(void *x, int *SWIGUNUSEDPARM(newmemory)) {
+    return (void *)((ISimulation *) (ISimulation2D *) ((OffSpecularSimulation *) x));
 }
 static void *_p_AngularSpecScanTo_p_ISpecularScan(void *x, int *SWIGUNUSEDPARM(newmemory)) {
     return (void *)((ISpecularScan *)  ((AngularSpecScan *) x));
@@ -44377,8 +44088,8 @@ static void *_p_QSpecScanTo_p_ISpecularScan(void *x, int *SWIGUNUSEDPARM(newmemo
 static void *_p_IFormFactorTo_p_IComponent(void *x, int *SWIGUNUSEDPARM(newmemory)) {
     return (void *)((IComponent *) (IParametricComponent *)(INode *)(ISampleNode *) ((IFormFactor *) x));
 }
-static void *_p_OffSpecSimulationTo_p_IComponent(void *x, int *SWIGUNUSEDPARM(newmemory)) {
-    return (void *)((IComponent *) (IParametricComponent *)(INode *)(ISimulation *)(ISimulation2D *) ((OffSpecSimulation *) x));
+static void *_p_OffSpecularSimulationTo_p_IComponent(void *x, int *SWIGUNUSEDPARM(newmemory)) {
+    return (void *)((IComponent *) (IParametricComponent *)(INode *)(ISimulation *)(ISimulation2D *) ((OffSpecularSimulation *) x));
 }
 static void *_p_SpecularSimulationTo_p_IComponent(void *x, int *SWIGUNUSEDPARM(newmemory)) {
     return (void *)((IComponent *) (IParametricComponent *)(INode *)(ISimulation *) ((SpecularSimulation *) x));
@@ -44422,8 +44133,8 @@ static void *_p_ISimulation2DTo_p_IComponent(void *x, int *SWIGUNUSEDPARM(newmem
 static void *_p_IFormFactorTo_p_IParametricComponent(void *x, int *SWIGUNUSEDPARM(newmemory)) {
     return (void *)((IParametricComponent *) (INode *)(ISampleNode *) ((IFormFactor *) x));
 }
-static void *_p_OffSpecSimulationTo_p_IParametricComponent(void *x, int *SWIGUNUSEDPARM(newmemory)) {
-    return (void *)((IParametricComponent *) (INode *)(ISimulation *)(ISimulation2D *) ((OffSpecSimulation *) x));
+static void *_p_OffSpecularSimulationTo_p_IParametricComponent(void *x, int *SWIGUNUSEDPARM(newmemory)) {
+    return (void *)((IParametricComponent *) (INode *)(ISimulation *)(ISimulation2D *) ((OffSpecularSimulation *) x));
 }
 static void *_p_SpecularSimulationTo_p_IParametricComponent(void *x, int *SWIGUNUSEDPARM(newmemory)) {
     return (void *)((IParametricComponent *) (INode *)(ISimulation *) ((SpecularSimulation *) x));
@@ -44479,8 +44190,8 @@ static void *_p_DepthProbeSimulationTo_p_INode(void *x, int *SWIGUNUSEDPARM(newm
 static void *_p_SpecularSimulationTo_p_INode(void *x, int *SWIGUNUSEDPARM(newmemory)) {
     return (void *)((INode *) (ISimulation *) ((SpecularSimulation *) x));
 }
-static void *_p_OffSpecSimulationTo_p_INode(void *x, int *SWIGUNUSEDPARM(newmemory)) {
-    return (void *)((INode *) (ISimulation *)(ISimulation2D *) ((OffSpecSimulation *) x));
+static void *_p_OffSpecularSimulationTo_p_INode(void *x, int *SWIGUNUSEDPARM(newmemory)) {
+    return (void *)((INode *) (ISimulation *)(ISimulation2D *) ((OffSpecularSimulation *) x));
 }
 static void *_p_IBackgroundTo_p_INode(void *x, int *SWIGUNUSEDPARM(newmemory)) {
     return (void *)((INode *)  ((IBackground *) x));
@@ -44500,14 +44211,14 @@ static void *_p_IBornFFTo_p_INode(void *x, int *SWIGUNUSEDPARM(newmemory)) {
 static void *_p_GISASSimulationTo_p_ISimulation2D(void *x, int *SWIGUNUSEDPARM(newmemory)) {
     return (void *)((ISimulation2D *)  ((GISASSimulation *) x));
 }
-static void *_p_OffSpecSimulationTo_p_ISimulation2D(void *x, int *SWIGUNUSEDPARM(newmemory)) {
-    return (void *)((ISimulation2D *)  ((OffSpecSimulation *) x));
+static void *_p_OffSpecularSimulationTo_p_ISimulation2D(void *x, int *SWIGUNUSEDPARM(newmemory)) {
+    return (void *)((ISimulation2D *)  ((OffSpecularSimulation *) x));
 }
 static void *_p_IFormFactorTo_p_ICloneable(void *x, int *SWIGUNUSEDPARM(newmemory)) {
     return (void *)((ICloneable *) (ISampleNode *) ((IFormFactor *) x));
 }
-static void *_p_OffSpecSimulationTo_p_ICloneable(void *x, int *SWIGUNUSEDPARM(newmemory)) {
-    return (void *)((ICloneable *) (ISimulation *)(ISimulation2D *) ((OffSpecSimulation *) x));
+static void *_p_OffSpecularSimulationTo_p_ICloneable(void *x, int *SWIGUNUSEDPARM(newmemory)) {
+    return (void *)((ICloneable *) (ISimulation *)(ISimulation2D *) ((OffSpecularSimulation *) x));
 }
 static void *_p_SpecularSimulationTo_p_ICloneable(void *x, int *SWIGUNUSEDPARM(newmemory)) {
     return (void *)((ICloneable *) (ISimulation *) ((SpecularSimulation *) x));
@@ -44555,7 +44266,7 @@ static swig_type_info _swigt__p_AngularSpecScan = {"_p_AngularSpecScan", "Angula
 static swig_type_info _swigt__p_AxisInfo = {"_p_AxisInfo", "std::vector< AxisInfo >::value_type *|AxisInfo *", 0, 0, (void*)0, 0};
 static swig_type_info _swigt__p_BasicVector3DT_double_t = {"_p_BasicVector3DT_double_t", "std::vector< BasicVector3D< double > >::value_type *|kvector_t *|BasicVector3D< double > *", 0, 0, (void*)0, 0};
 static swig_type_info _swigt__p_BasicVector3DT_int_t = {"_p_BasicVector3DT_int_t", "ivector_t *|BasicVector3D< int > *", 0, 0, (void*)0, 0};
-static swig_type_info _swigt__p_BasicVector3DT_std__complexT_double_t_t = {"_p_BasicVector3DT_std__complexT_double_t_t", "BasicVector3D< std::complex< double > > *|std::vector< BasicVector3D< std::complex< double > > >::value_type *|cvector_t *", 0, 0, (void*)0, 0};
+static swig_type_info _swigt__p_BasicVector3DT_std__complexT_double_t_t = {"_p_BasicVector3DT_std__complexT_double_t_t", "BasicVector3D< std::complex< double > > *|std::vector< BasicVector3D< std::complex< double > > >::value_type *|cvector_t *|BasicVector3D< complex_t > *", 0, 0, (void*)0, 0};
 static swig_type_info _swigt__p_Beam = {"_p_Beam", "Beam *", 0, 0, (void*)0, 0};
 static swig_type_info _swigt__p_ConstantBackground = {"_p_ConstantBackground", "ConstantBackground *", 0, 0, (void*)0, 0};
 static swig_type_info _swigt__p_DepthProbeSimulation = {"_p_DepthProbeSimulation", "DepthProbeSimulation *", 0, 0, (void*)0, 0};
@@ -44577,8 +44288,6 @@ static swig_type_info _swigt__p_IDistribution1D = {"_p_IDistribution1D", "IDistr
 static swig_type_info _swigt__p_IFootprintFactor = {"_p_IFootprintFactor", "IFootprintFactor *", 0, 0, (void*)0, 0};
 static swig_type_info _swigt__p_INode = {"_p_INode", "INode *|std::vector< INode * >::value_type|std::vector< INode const * >::value_type", 0, 0, (void*)0, 0};
 static swig_type_info _swigt__p_INodeVisitor = {"_p_INodeVisitor", "INodeVisitor *", 0, 0, (void*)0, 0};
-static swig_type_info _swigt__p_IObservable = {"_p_IObservable", "IObservable *", 0, 0, (void*)0, 0};
-static swig_type_info _swigt__p_IObserver = {"_p_IObserver", "IObserver *", 0, 0, (void*)0, 0};
 static swig_type_info _swigt__p_IParametricComponent = {"_p_IParametricComponent", "IParametricComponent *", 0, 0, (void*)0, 0};
 static swig_type_info _swigt__p_IRangedDistribution = {"_p_IRangedDistribution", "IRangedDistribution *", 0, 0, (void*)0, 0};
 static swig_type_info _swigt__p_IResolutionFunction2D = {"_p_IResolutionFunction2D", "IResolutionFunction2D *", 0, 0, (void*)0, 0};
@@ -44589,7 +44298,7 @@ static swig_type_info _swigt__p_ISpecularScan = {"_p_ISpecularScan", "ISpecularS
 static swig_type_info _swigt__p_Instrument = {"_p_Instrument", "Instrument *", 0, 0, (void*)0, 0};
 static swig_type_info _swigt__p_IterationInfo = {"_p_IterationInfo", "IterationInfo *", 0, 0, (void*)0, 0};
 static swig_type_info _swigt__p_MultiLayer = {"_p_MultiLayer", "MultiLayer *", 0, 0, (void*)0, 0};
-static swig_type_info _swigt__p_OffSpecSimulation = {"_p_OffSpecSimulation", "OffSpecSimulation *", 0, 0, (void*)0, 0};
+static swig_type_info _swigt__p_OffSpecularSimulation = {"_p_OffSpecularSimulation", "OffSpecularSimulation *", 0, 0, (void*)0, 0};
 static swig_type_info _swigt__p_OutputDataT_double_t = {"_p_OutputDataT_double_t", "OutputData< double > *", 0, 0, (void*)0, 0};
 static swig_type_info _swigt__p_ParameterDistribution = {"_p_ParameterDistribution", "ParameterDistribution *", 0, 0, (void*)0, 0};
 static swig_type_info _swigt__p_PoissonNoiseBackground = {"_p_PoissonNoiseBackground", "PoissonNoiseBackground *", 0, 0, (void*)0, 0};
@@ -44612,7 +44321,6 @@ static swig_type_info _swigt__p_long_long = {"_p_long_long", "int_least64_t *|in
 static swig_type_info _swigt__p_mapped_type = {"_p_mapped_type", "mapped_type *", 0, 0, (void*)0, 0};
 static swig_type_info _swigt__p_mumufit__MinimizerResult = {"_p_mumufit__MinimizerResult", "mumufit::MinimizerResult *", 0, 0, (void*)0, 0};
 static swig_type_info _swigt__p_mumufit__Parameters = {"_p_mumufit__Parameters", "mumufit::Parameters *", 0, 0, (void*)0, 0};
-static swig_type_info _swigt__p_observer_t = {"_p_observer_t", "observer_t *", 0, 0, (void*)0, 0};
 static swig_type_info _swigt__p_p_PyObject = {"_p_p_PyObject", "PyObject **", 0, 0, (void*)0, 0};
 static swig_type_info _swigt__p_second_type = {"_p_second_type", "second_type *", 0, 0, (void*)0, 0};
 static swig_type_info _swigt__p_short = {"_p_short", "short *|int_least16_t *|int16_t *", 0, 0, (void*)0, 0};
@@ -44637,7 +44345,6 @@ static swig_type_info _swigt__p_std__invalid_argument = {"_p_std__invalid_argume
 static swig_type_info _swigt__p_std__lessT_std__string_t = {"_p_std__lessT_std__string_t", "std::less< std::string > *", 0, 0, (void*)0, 0};
 static swig_type_info _swigt__p_std__mapT_std__string_double_std__lessT_std__string_t_std__allocatorT_std__pairT_std__string_const_double_t_t_t = {"_p_std__mapT_std__string_double_std__lessT_std__string_t_std__allocatorT_std__pairT_std__string_const_double_t_t_t", "std::map< std::string,double,std::less< std::string >,std::allocator< std::pair< std::string const,double > > > *|std::map< std::string,double > *", 0, 0, (void*)0, 0};
 static swig_type_info _swigt__p_std__pairT_double_double_t = {"_p_std__pairT_double_double_t", "std::pair< double,double > *", 0, 0, (void*)0, 0};
-static swig_type_info _swigt__p_std__shared_ptrT_IObserver_t = {"_p_std__shared_ptrT_IObserver_t", "std::shared_ptr< IObserver > *|IObservable::observer_t *", 0, 0, (void*)0, 0};
 static swig_type_info _swigt__p_std__shared_ptrT_ISampleBuilder_t = {"_p_std__shared_ptrT_ISampleBuilder_t", "std::shared_ptr< ISampleBuilder > *", 0, 0, (void*)0, 0};
 static swig_type_info _swigt__p_std__vectorT_AxisInfo_std__allocatorT_AxisInfo_t_t = {"_p_std__vectorT_AxisInfo_std__allocatorT_AxisInfo_t_t", "std::vector< AxisInfo,std::allocator< AxisInfo > > *|std::vector< AxisInfo > *", 0, 0, (void*)0, 0};
 static swig_type_info _swigt__p_std__vectorT_BasicVector3DT_double_t_std__allocatorT_BasicVector3DT_double_t_t_t = {"_p_std__vectorT_BasicVector3DT_double_t_std__allocatorT_BasicVector3DT_double_t_t_t", "std::vector< BasicVector3D< double > > *|std::vector< BasicVector3D< double >,std::allocator< BasicVector3D< double > > > *", 0, 0, (void*)0, 0};
@@ -44684,8 +44391,6 @@ static swig_type_info *swig_type_initial[] = {
   &_swigt__p_IFormFactor,
   &_swigt__p_INode,
   &_swigt__p_INodeVisitor,
-  &_swigt__p_IObservable,
-  &_swigt__p_IObserver,
   &_swigt__p_IParametricComponent,
   &_swigt__p_IRangedDistribution,
   &_swigt__p_IResolutionFunction2D,
@@ -44697,7 +44402,7 @@ static swig_type_info *swig_type_initial[] = {
   &_swigt__p_Instrument,
   &_swigt__p_IterationInfo,
   &_swigt__p_MultiLayer,
-  &_swigt__p_OffSpecSimulation,
+  &_swigt__p_OffSpecularSimulation,
   &_swigt__p_OutputDataT_double_t,
   &_swigt__p_ParameterDistribution,
   &_swigt__p_ParameterPool,
@@ -44721,7 +44426,6 @@ static swig_type_info *swig_type_initial[] = {
   &_swigt__p_mapped_type,
   &_swigt__p_mumufit__MinimizerResult,
   &_swigt__p_mumufit__Parameters,
-  &_swigt__p_observer_t,
   &_swigt__p_p_PyObject,
   &_swigt__p_second_type,
   &_swigt__p_short,
@@ -44746,7 +44450,6 @@ static swig_type_info *swig_type_initial[] = {
   &_swigt__p_std__lessT_std__string_t,
   &_swigt__p_std__mapT_std__string_double_std__lessT_std__string_t_std__allocatorT_std__pairT_std__string_const_double_t_t_t,
   &_swigt__p_std__pairT_double_double_t,
-  &_swigt__p_std__shared_ptrT_IObserver_t,
   &_swigt__p_std__shared_ptrT_ISampleBuilder_t,
   &_swigt__p_std__vectorT_AxisInfo_std__allocatorT_AxisInfo_t_t,
   &_swigt__p_std__vectorT_BasicVector3DT_double_t_std__allocatorT_BasicVector3DT_double_t_t_t,
@@ -44787,27 +44490,25 @@ static swig_cast_info _swigc__p_IFormFactor[] = {{&_swigt__p_IFormFactor, 0, 0,
 static swig_cast_info _swigc__p_ParameterPool[] = {{&_swigt__p_ParameterPool, 0, 0, 0},{0, 0, 0, 0}};
 static swig_cast_info _swigc__p_IBornFF[] = {{&_swigt__p_IBornFF, 0, 0, 0},{0, 0, 0, 0}};
 static swig_cast_info _swigc__p_ISampleNode[] = {{&_swigt__p_ISampleNode, 0, 0, 0},{0, 0, 0, 0}};
-static swig_cast_info _swigc__p_ICloneable[] = {  {&_swigt__p_IFormFactor, _p_IFormFactorTo_p_ICloneable, 0, 0},  {&_swigt__p_SpecularSimulation, _p_SpecularSimulationTo_p_ICloneable, 0, 0},  {&_swigt__p_DepthProbeSimulation, _p_DepthProbeSimulationTo_p_ICloneable, 0, 0},  {&_swigt__p_OffSpecSimulation, _p_OffSpecSimulationTo_p_ICloneable, 0, 0},  {&_swigt__p_GISASSimulation, _p_GISASSimulationTo_p_ICloneable, 0, 0},  {&_swigt__p_ISimulation, _p_ISimulationTo_p_ICloneable, 0, 0},  {&_swigt__p_ICloneable, 0, 0, 0},  {&_swigt__p_IBackground, _p_IBackgroundTo_p_ICloneable, 0, 0},  {&_swigt__p_ConstantBackground, _p_ConstantBackgroundTo_p_ICloneable, 0, 0},  {&_swigt__p_PoissonNoiseBackground, _p_PoissonNoiseBackgroundTo_p_ICloneable, 0, 0},  {&_swigt__p_ParameterPool, _p_ParameterPoolTo_p_ICloneable, 0, 0},  {&_swigt__p_ISpecularScan, _p_ISpecularScanTo_p_ICloneable, 0, 0},  {&_swigt__p_IBornFF, _p_IBornFFTo_p_ICloneable, 0, 0},  {&_swigt__p_AngularSpecScan, _p_AngularSpecScanTo_p_ICloneable, 0, 0},  {&_swigt__p_QSpecScan, _p_QSpecScanTo_p_ICloneable, 0, 0},  {&_swigt__p_ISampleNode, _p_ISampleNodeTo_p_ICloneable, 0, 0},  {&_swigt__p_ISimulation2D, _p_ISimulation2DTo_p_ICloneable, 0, 0},{0, 0, 0, 0}};
-static swig_cast_info _swigc__p_IComponent[] = {  {&_swigt__p_IFormFactor, _p_IFormFactorTo_p_IComponent, 0, 0},  {&_swigt__p_SpecularSimulation, _p_SpecularSimulationTo_p_IComponent, 0, 0},  {&_swigt__p_DepthProbeSimulation, _p_DepthProbeSimulationTo_p_IComponent, 0, 0},  {&_swigt__p_OffSpecSimulation, _p_OffSpecSimulationTo_p_IComponent, 0, 0},  {&_swigt__p_GISASSimulation, _p_GISASSimulationTo_p_IComponent, 0, 0},  {&_swigt__p_ISimulation, _p_ISimulationTo_p_IComponent, 0, 0},  {&_swigt__p_IParametricComponent, _p_IParametricComponentTo_p_IComponent, 0, 0},  {&_swigt__p_IComponent, 0, 0, 0},  {&_swigt__p_PoissonNoiseBackground, _p_PoissonNoiseBackgroundTo_p_IComponent, 0, 0},  {&_swigt__p_ConstantBackground, _p_ConstantBackgroundTo_p_IComponent, 0, 0},  {&_swigt__p_IBackground, _p_IBackgroundTo_p_IComponent, 0, 0},  {&_swigt__p_IBornFF, _p_IBornFFTo_p_IComponent, 0, 0},  {&_swigt__p_ISampleNode, _p_ISampleNodeTo_p_IComponent, 0, 0},  {&_swigt__p_ParameterDistribution, _p_ParameterDistributionTo_p_IComponent, 0, 0},  {&_swigt__p_ISimulation2D, _p_ISimulation2DTo_p_IComponent, 0, 0},  {&_swigt__p_INode, _p_INodeTo_p_IComponent, 0, 0},{0, 0, 0, 0}};
+static swig_cast_info _swigc__p_ICloneable[] = {  {&_swigt__p_IFormFactor, _p_IFormFactorTo_p_ICloneable, 0, 0},  {&_swigt__p_SpecularSimulation, _p_SpecularSimulationTo_p_ICloneable, 0, 0},  {&_swigt__p_DepthProbeSimulation, _p_DepthProbeSimulationTo_p_ICloneable, 0, 0},  {&_swigt__p_OffSpecularSimulation, _p_OffSpecularSimulationTo_p_ICloneable, 0, 0},  {&_swigt__p_GISASSimulation, _p_GISASSimulationTo_p_ICloneable, 0, 0},  {&_swigt__p_ISimulation, _p_ISimulationTo_p_ICloneable, 0, 0},  {&_swigt__p_ICloneable, 0, 0, 0},  {&_swigt__p_IBackground, _p_IBackgroundTo_p_ICloneable, 0, 0},  {&_swigt__p_ConstantBackground, _p_ConstantBackgroundTo_p_ICloneable, 0, 0},  {&_swigt__p_PoissonNoiseBackground, _p_PoissonNoiseBackgroundTo_p_ICloneable, 0, 0},  {&_swigt__p_ParameterPool, _p_ParameterPoolTo_p_ICloneable, 0, 0},  {&_swigt__p_ISpecularScan, _p_ISpecularScanTo_p_ICloneable, 0, 0},  {&_swigt__p_IBornFF, _p_IBornFFTo_p_ICloneable, 0, 0},  {&_swigt__p_AngularSpecScan, _p_AngularSpecScanTo_p_ICloneable, 0, 0},  {&_swigt__p_QSpecScan, _p_QSpecScanTo_p_ICloneable, 0, 0},  {&_swigt__p_ISampleNode, _p_ISampleNodeTo_p_ICloneable, 0, 0},  {&_swigt__p_ISimulation2D, _p_ISimulation2DTo_p_ICloneable, 0, 0},{0, 0, 0, 0}};
+static swig_cast_info _swigc__p_IComponent[] = {  {&_swigt__p_IFormFactor, _p_IFormFactorTo_p_IComponent, 0, 0},  {&_swigt__p_SpecularSimulation, _p_SpecularSimulationTo_p_IComponent, 0, 0},  {&_swigt__p_DepthProbeSimulation, _p_DepthProbeSimulationTo_p_IComponent, 0, 0},  {&_swigt__p_OffSpecularSimulation, _p_OffSpecularSimulationTo_p_IComponent, 0, 0},  {&_swigt__p_GISASSimulation, _p_GISASSimulationTo_p_IComponent, 0, 0},  {&_swigt__p_ISimulation, _p_ISimulationTo_p_IComponent, 0, 0},  {&_swigt__p_IParametricComponent, _p_IParametricComponentTo_p_IComponent, 0, 0},  {&_swigt__p_IComponent, 0, 0, 0},  {&_swigt__p_PoissonNoiseBackground, _p_PoissonNoiseBackgroundTo_p_IComponent, 0, 0},  {&_swigt__p_ConstantBackground, _p_ConstantBackgroundTo_p_IComponent, 0, 0},  {&_swigt__p_IBackground, _p_IBackgroundTo_p_IComponent, 0, 0},  {&_swigt__p_IBornFF, _p_IBornFFTo_p_IComponent, 0, 0},  {&_swigt__p_ISampleNode, _p_ISampleNodeTo_p_IComponent, 0, 0},  {&_swigt__p_ParameterDistribution, _p_ParameterDistributionTo_p_IComponent, 0, 0},  {&_swigt__p_ISimulation2D, _p_ISimulation2DTo_p_IComponent, 0, 0},  {&_swigt__p_INode, _p_INodeTo_p_IComponent, 0, 0},{0, 0, 0, 0}};
 static swig_cast_info _swigc__p_IDetector[] = {  {&_swigt__p_IDetector, 0, 0, 0},{0, 0, 0, 0}};
 static swig_cast_info _swigc__p_IDetector2D[] = {  {&_swigt__p_IDetector2D, 0, 0, 0},{0, 0, 0, 0}};
 static swig_cast_info _swigc__p_IDistribution1D[] = {  {&_swigt__p_IDistribution1D, 0, 0, 0},{0, 0, 0, 0}};
 static swig_cast_info _swigc__p_IFootprintFactor[] = {  {&_swigt__p_IFootprintFactor, 0, 0, 0},{0, 0, 0, 0}};
-static swig_cast_info _swigc__p_INode[] = {  {&_swigt__p_INode, 0, 0, 0},  {&_swigt__p_IFormFactor, _p_IFormFactorTo_p_INode, 0, 0},  {&_swigt__p_ISimulation2D, _p_ISimulation2DTo_p_INode, 0, 0},  {&_swigt__p_GISASSimulation, _p_GISASSimulationTo_p_INode, 0, 0},  {&_swigt__p_OffSpecSimulation, _p_OffSpecSimulationTo_p_INode, 0, 0},  {&_swigt__p_ISimulation, _p_ISimulationTo_p_INode, 0, 0},  {&_swigt__p_DepthProbeSimulation, _p_DepthProbeSimulationTo_p_INode, 0, 0},  {&_swigt__p_SpecularSimulation, _p_SpecularSimulationTo_p_INode, 0, 0},  {&_swigt__p_IBackground, _p_IBackgroundTo_p_INode, 0, 0},  {&_swigt__p_ConstantBackground, _p_ConstantBackgroundTo_p_INode, 0, 0},  {&_swigt__p_PoissonNoiseBackground, _p_PoissonNoiseBackgroundTo_p_INode, 0, 0},  {&_swigt__p_ISampleNode, _p_ISampleNodeTo_p_INode, 0, 0},  {&_swigt__p_IBornFF, _p_IBornFFTo_p_INode, 0, 0},{0, 0, 0, 0}};
+static swig_cast_info _swigc__p_INode[] = {  {&_swigt__p_INode, 0, 0, 0},  {&_swigt__p_IFormFactor, _p_IFormFactorTo_p_INode, 0, 0},  {&_swigt__p_ISimulation2D, _p_ISimulation2DTo_p_INode, 0, 0},  {&_swigt__p_GISASSimulation, _p_GISASSimulationTo_p_INode, 0, 0},  {&_swigt__p_OffSpecularSimulation, _p_OffSpecularSimulationTo_p_INode, 0, 0},  {&_swigt__p_ISimulation, _p_ISimulationTo_p_INode, 0, 0},  {&_swigt__p_DepthProbeSimulation, _p_DepthProbeSimulationTo_p_INode, 0, 0},  {&_swigt__p_SpecularSimulation, _p_SpecularSimulationTo_p_INode, 0, 0},  {&_swigt__p_IBackground, _p_IBackgroundTo_p_INode, 0, 0},  {&_swigt__p_ConstantBackground, _p_ConstantBackgroundTo_p_INode, 0, 0},  {&_swigt__p_PoissonNoiseBackground, _p_PoissonNoiseBackgroundTo_p_INode, 0, 0},  {&_swigt__p_ISampleNode, _p_ISampleNodeTo_p_INode, 0, 0},  {&_swigt__p_IBornFF, _p_IBornFFTo_p_INode, 0, 0},{0, 0, 0, 0}};
 static swig_cast_info _swigc__p_INodeVisitor[] = {  {&_swigt__p_INodeVisitor, 0, 0, 0},{0, 0, 0, 0}};
-static swig_cast_info _swigc__p_IObservable[] = {  {&_swigt__p_IObservable, 0, 0, 0},{0, 0, 0, 0}};
-static swig_cast_info _swigc__p_IObserver[] = {  {&_swigt__p_IObserver, 0, 0, 0},{0, 0, 0, 0}};
-static swig_cast_info _swigc__p_IParametricComponent[] = {  {&_swigt__p_IFormFactor, _p_IFormFactorTo_p_IParametricComponent, 0, 0},  {&_swigt__p_SpecularSimulation, _p_SpecularSimulationTo_p_IParametricComponent, 0, 0},  {&_swigt__p_DepthProbeSimulation, _p_DepthProbeSimulationTo_p_IParametricComponent, 0, 0},  {&_swigt__p_OffSpecSimulation, _p_OffSpecSimulationTo_p_IParametricComponent, 0, 0},  {&_swigt__p_GISASSimulation, _p_GISASSimulationTo_p_IParametricComponent, 0, 0},  {&_swigt__p_ISimulation, _p_ISimulationTo_p_IParametricComponent, 0, 0},  {&_swigt__p_IParametricComponent, 0, 0, 0},  {&_swigt__p_PoissonNoiseBackground, _p_PoissonNoiseBackgroundTo_p_IParametricComponent, 0, 0},  {&_swigt__p_ConstantBackground, _p_ConstantBackgroundTo_p_IParametricComponent, 0, 0},  {&_swigt__p_IBackground, _p_IBackgroundTo_p_IParametricComponent, 0, 0},  {&_swigt__p_IBornFF, _p_IBornFFTo_p_IParametricComponent, 0, 0},  {&_swigt__p_ISampleNode, _p_ISampleNodeTo_p_IParametricComponent, 0, 0},  {&_swigt__p_ParameterDistribution, _p_ParameterDistributionTo_p_IParametricComponent, 0, 0},  {&_swigt__p_ISimulation2D, _p_ISimulation2DTo_p_IParametricComponent, 0, 0},  {&_swigt__p_INode, _p_INodeTo_p_IParametricComponent, 0, 0},{0, 0, 0, 0}};
+static swig_cast_info _swigc__p_IParametricComponent[] = {  {&_swigt__p_IFormFactor, _p_IFormFactorTo_p_IParametricComponent, 0, 0},  {&_swigt__p_SpecularSimulation, _p_SpecularSimulationTo_p_IParametricComponent, 0, 0},  {&_swigt__p_DepthProbeSimulation, _p_DepthProbeSimulationTo_p_IParametricComponent, 0, 0},  {&_swigt__p_OffSpecularSimulation, _p_OffSpecularSimulationTo_p_IParametricComponent, 0, 0},  {&_swigt__p_GISASSimulation, _p_GISASSimulationTo_p_IParametricComponent, 0, 0},  {&_swigt__p_ISimulation, _p_ISimulationTo_p_IParametricComponent, 0, 0},  {&_swigt__p_IParametricComponent, 0, 0, 0},  {&_swigt__p_PoissonNoiseBackground, _p_PoissonNoiseBackgroundTo_p_IParametricComponent, 0, 0},  {&_swigt__p_ConstantBackground, _p_ConstantBackgroundTo_p_IParametricComponent, 0, 0},  {&_swigt__p_IBackground, _p_IBackgroundTo_p_IParametricComponent, 0, 0},  {&_swigt__p_IBornFF, _p_IBornFFTo_p_IParametricComponent, 0, 0},  {&_swigt__p_ISampleNode, _p_ISampleNodeTo_p_IParametricComponent, 0, 0},  {&_swigt__p_ParameterDistribution, _p_ParameterDistributionTo_p_IParametricComponent, 0, 0},  {&_swigt__p_ISimulation2D, _p_ISimulation2DTo_p_IParametricComponent, 0, 0},  {&_swigt__p_INode, _p_INodeTo_p_IParametricComponent, 0, 0},{0, 0, 0, 0}};
 static swig_cast_info _swigc__p_IRangedDistribution[] = {  {&_swigt__p_IRangedDistribution, 0, 0, 0},{0, 0, 0, 0}};
 static swig_cast_info _swigc__p_IResolutionFunction2D[] = {  {&_swigt__p_IResolutionFunction2D, 0, 0, 0},{0, 0, 0, 0}};
 static swig_cast_info _swigc__p_IShape2D[] = {  {&_swigt__p_IShape2D, 0, 0, 0},{0, 0, 0, 0}};
-static swig_cast_info _swigc__p_ISimulation[] = {  {&_swigt__p_ISimulation2D, _p_ISimulation2DTo_p_ISimulation, 0, 0},  {&_swigt__p_ISimulation, 0, 0, 0},  {&_swigt__p_GISASSimulation, _p_GISASSimulationTo_p_ISimulation, 0, 0},  {&_swigt__p_OffSpecSimulation, _p_OffSpecSimulationTo_p_ISimulation, 0, 0},  {&_swigt__p_DepthProbeSimulation, _p_DepthProbeSimulationTo_p_ISimulation, 0, 0},  {&_swigt__p_SpecularSimulation, _p_SpecularSimulationTo_p_ISimulation, 0, 0},{0, 0, 0, 0}};
-static swig_cast_info _swigc__p_ISimulation2D[] = {  {&_swigt__p_ISimulation2D, 0, 0, 0},  {&_swigt__p_GISASSimulation, _p_GISASSimulationTo_p_ISimulation2D, 0, 0},  {&_swigt__p_OffSpecSimulation, _p_OffSpecSimulationTo_p_ISimulation2D, 0, 0},{0, 0, 0, 0}};
+static swig_cast_info _swigc__p_ISimulation[] = {  {&_swigt__p_ISimulation2D, _p_ISimulation2DTo_p_ISimulation, 0, 0},  {&_swigt__p_ISimulation, 0, 0, 0},  {&_swigt__p_GISASSimulation, _p_GISASSimulationTo_p_ISimulation, 0, 0},  {&_swigt__p_OffSpecularSimulation, _p_OffSpecularSimulationTo_p_ISimulation, 0, 0},  {&_swigt__p_DepthProbeSimulation, _p_DepthProbeSimulationTo_p_ISimulation, 0, 0},  {&_swigt__p_SpecularSimulation, _p_SpecularSimulationTo_p_ISimulation, 0, 0},{0, 0, 0, 0}};
+static swig_cast_info _swigc__p_ISimulation2D[] = {  {&_swigt__p_ISimulation2D, 0, 0, 0},  {&_swigt__p_GISASSimulation, _p_GISASSimulationTo_p_ISimulation2D, 0, 0},  {&_swigt__p_OffSpecularSimulation, _p_OffSpecularSimulationTo_p_ISimulation2D, 0, 0},{0, 0, 0, 0}};
 static swig_cast_info _swigc__p_ISpecularScan[] = {  {&_swigt__p_AngularSpecScan, _p_AngularSpecScanTo_p_ISpecularScan, 0, 0},  {&_swigt__p_QSpecScan, _p_QSpecScanTo_p_ISpecularScan, 0, 0},  {&_swigt__p_ISpecularScan, 0, 0, 0},{0, 0, 0, 0}};
 static swig_cast_info _swigc__p_Instrument[] = {  {&_swigt__p_Instrument, 0, 0, 0},{0, 0, 0, 0}};
 static swig_cast_info _swigc__p_IterationInfo[] = {  {&_swigt__p_IterationInfo, 0, 0, 0},{0, 0, 0, 0}};
 static swig_cast_info _swigc__p_MultiLayer[] = {  {&_swigt__p_MultiLayer, 0, 0, 0},{0, 0, 0, 0}};
-static swig_cast_info _swigc__p_OffSpecSimulation[] = {  {&_swigt__p_OffSpecSimulation, 0, 0, 0},{0, 0, 0, 0}};
+static swig_cast_info _swigc__p_OffSpecularSimulation[] = {  {&_swigt__p_OffSpecularSimulation, 0, 0, 0},{0, 0, 0, 0}};
 static swig_cast_info _swigc__p_OutputDataT_double_t[] = {  {&_swigt__p_OutputDataT_double_t, 0, 0, 0},{0, 0, 0, 0}};
 static swig_cast_info _swigc__p_ParameterDistribution[] = {  {&_swigt__p_ParameterDistribution, 0, 0, 0},{0, 0, 0, 0}};
 static swig_cast_info _swigc__p_PoissonNoiseBackground[] = {  {&_swigt__p_PoissonNoiseBackground, 0, 0, 0},{0, 0, 0, 0}};
@@ -44830,7 +44531,6 @@ static swig_cast_info _swigc__p_long_long[] = {  {&_swigt__p_long_long, 0, 0, 0}
 static swig_cast_info _swigc__p_mapped_type[] = {  {&_swigt__p_mapped_type, 0, 0, 0},{0, 0, 0, 0}};
 static swig_cast_info _swigc__p_mumufit__MinimizerResult[] = {  {&_swigt__p_mumufit__MinimizerResult, 0, 0, 0},{0, 0, 0, 0}};
 static swig_cast_info _swigc__p_mumufit__Parameters[] = {  {&_swigt__p_mumufit__Parameters, 0, 0, 0},{0, 0, 0, 0}};
-static swig_cast_info _swigc__p_observer_t[] = {  {&_swigt__p_observer_t, 0, 0, 0},{0, 0, 0, 0}};
 static swig_cast_info _swigc__p_p_PyObject[] = {  {&_swigt__p_p_PyObject, 0, 0, 0},{0, 0, 0, 0}};
 static swig_cast_info _swigc__p_second_type[] = {  {&_swigt__p_second_type, 0, 0, 0},{0, 0, 0, 0}};
 static swig_cast_info _swigc__p_short[] = {  {&_swigt__p_short, 0, 0, 0},{0, 0, 0, 0}};
@@ -44855,7 +44555,6 @@ static swig_cast_info _swigc__p_std__invalid_argument[] = {  {&_swigt__p_std__in
 static swig_cast_info _swigc__p_std__lessT_std__string_t[] = {  {&_swigt__p_std__lessT_std__string_t, 0, 0, 0},{0, 0, 0, 0}};
 static swig_cast_info _swigc__p_std__mapT_std__string_double_std__lessT_std__string_t_std__allocatorT_std__pairT_std__string_const_double_t_t_t[] = {  {&_swigt__p_std__mapT_std__string_double_std__lessT_std__string_t_std__allocatorT_std__pairT_std__string_const_double_t_t_t, 0, 0, 0},{0, 0, 0, 0}};
 static swig_cast_info _swigc__p_std__pairT_double_double_t[] = {  {&_swigt__p_std__pairT_double_double_t, 0, 0, 0},{0, 0, 0, 0}};
-static swig_cast_info _swigc__p_std__shared_ptrT_IObserver_t[] = {  {&_swigt__p_std__shared_ptrT_IObserver_t, 0, 0, 0},{0, 0, 0, 0}};
 static swig_cast_info _swigc__p_std__shared_ptrT_ISampleBuilder_t[] = {  {&_swigt__p_std__shared_ptrT_ISampleBuilder_t, 0, 0, 0},{0, 0, 0, 0}};
 static swig_cast_info _swigc__p_std__vectorT_AxisInfo_std__allocatorT_AxisInfo_t_t[] = {  {&_swigt__p_std__vectorT_AxisInfo_std__allocatorT_AxisInfo_t_t, 0, 0, 0},{0, 0, 0, 0}};
 static swig_cast_info _swigc__p_std__vectorT_BasicVector3DT_double_t_std__allocatorT_BasicVector3DT_double_t_t_t[] = {  {&_swigt__p_std__vectorT_BasicVector3DT_double_t_std__allocatorT_BasicVector3DT_double_t_t_t, 0, 0, 0},{0, 0, 0, 0}};
@@ -44902,8 +44601,6 @@ static swig_cast_info *swig_cast_initial[] = {
   _swigc__p_IFormFactor,
   _swigc__p_INode,
   _swigc__p_INodeVisitor,
-  _swigc__p_IObservable,
-  _swigc__p_IObserver,
   _swigc__p_IParametricComponent,
   _swigc__p_IRangedDistribution,
   _swigc__p_IResolutionFunction2D,
@@ -44915,7 +44612,7 @@ static swig_cast_info *swig_cast_initial[] = {
   _swigc__p_Instrument,
   _swigc__p_IterationInfo,
   _swigc__p_MultiLayer,
-  _swigc__p_OffSpecSimulation,
+  _swigc__p_OffSpecularSimulation,
   _swigc__p_OutputDataT_double_t,
   _swigc__p_ParameterDistribution,
   _swigc__p_ParameterPool,
@@ -44939,7 +44636,6 @@ static swig_cast_info *swig_cast_initial[] = {
   _swigc__p_mapped_type,
   _swigc__p_mumufit__MinimizerResult,
   _swigc__p_mumufit__Parameters,
-  _swigc__p_observer_t,
   _swigc__p_p_PyObject,
   _swigc__p_second_type,
   _swigc__p_short,
@@ -44964,7 +44660,6 @@ static swig_cast_info *swig_cast_initial[] = {
   _swigc__p_std__lessT_std__string_t,
   _swigc__p_std__mapT_std__string_double_std__lessT_std__string_t_std__allocatorT_std__pairT_std__string_const_double_t_t_t,
   _swigc__p_std__pairT_double_double_t,
-  _swigc__p_std__shared_ptrT_IObserver_t,
   _swigc__p_std__shared_ptrT_ISampleBuilder_t,
   _swigc__p_std__vectorT_AxisInfo_std__allocatorT_AxisInfo_t_t,
   _swigc__p_std__vectorT_BasicVector3DT_double_t_std__allocatorT_BasicVector3DT_double_t_t_t,
diff --git a/auto/Wrap/libBornAgainDevice.py b/auto/Wrap/libBornAgainDevice.py
index 15bb81134b2bff3b13dce40d6c6ce168aea6fa74..496c7e4749ad991e0fc9ba4d7775e1c38375d961 100644
--- a/auto/Wrap/libBornAgainDevice.py
+++ b/auto/Wrap/libBornAgainDevice.py
@@ -2217,7 +2217,7 @@ class IntensityData(object):
     r"""
 
 
-    Template class to store data of any type in multi-dimensional space.
+    Templated class to store data of type double or  CumulativeValue in multi-dimensional space.
 
     C++ includes: OutputData.h
 
@@ -2268,16 +2268,15 @@ class IntensityData(object):
         """
         return _libBornAgainDevice.IntensityData_addAxis(self, *args)
 
-    def axis(self, *args):
+    def axis(self, serial_number):
         r"""
         axis(IntensityData self, size_t serial_number) -> IAxis
-        axis(IntensityData self, std::string const & axis_name) -> IAxis
-        const IAxis & OutputData< T >::axis(const std::string &axis_name) const
+        const IAxis & OutputData< T >::axis(size_t serial_number) const
 
-        returns axis with given name 
+        returns axis with given serial number 
 
         """
-        return _libBornAgainDevice.IntensityData_axis(self, *args)
+        return _libBornAgainDevice.IntensityData_axis(self, serial_number)
 
     def rank(self):
         r"""
@@ -3954,7 +3953,9 @@ def importArrayToOutputData(*args):
 def FindPeaks(*args):
     r"""
     FindPeaks(Histogram2D hist, double sigma=2, std::string const & option={}, double threshold=0.05) -> vector_pvacuum_double_t
-    std::vector< std::pair< double, double > > SpectrumUtils::FindPeaks(const Histogram2D &hist, double sigma=2, const std::string &option={}, double threshold=0.05)
+    std::vector< std::pair< double, double > > ImageUtils::FindPeaks(const Histogram2D &hist, double sigma=2, const std::string &option={}, double threshold=0.05)
+
+    Returns vector of peak center coordinates, for peaks in given histogram. 
 
     """
     return _libBornAgainDevice.FindPeaks(*args)
diff --git a/auto/Wrap/libBornAgainDevice_wrap.cpp b/auto/Wrap/libBornAgainDevice_wrap.cpp
index bfa18e94307cadf43cddd59109f8a8298dcaa4ac..c1fa45c44e7df4ca94d739ca7dd4f5cceb076871 100644
--- a/auto/Wrap/libBornAgainDevice_wrap.cpp
+++ b/auto/Wrap/libBornAgainDevice_wrap.cpp
@@ -6730,7 +6730,7 @@ SWIGINTERN void std_vector_Sl_std_pair_Sl_double_Sc_double_Sg__Sg__insert__SWIG_
 #include "Device/Instrument/IChiSquaredModule.h"
 #include "Device/Instrument/IntensityDataFunctions.h"
 #include "Device/Instrument/PyArrayImportUtils.h"
-#include "Device/Instrument/SpectrumUtils.h"
+#include "Device/Histo/ImageUtils.h"
 #include "Device/Instrument/VarianceFunctions.h"
 #include "Device/Intensity/IIntensityFunction.h"
 #include "Device/Intensity/IIntensityFunction.h"
@@ -24550,7 +24550,7 @@ SWIGINTERN PyObject *_wrap_kvector_t_complex(PyObject *SWIGUNUSEDPARM(self), PyO
   void *argp1 = 0 ;
   int res1 = 0 ;
   PyObject *swig_obj[1] ;
-  BasicVector3D< std::complex< double > > result;
+  BasicVector3D< complex_t > result;
   
   if (!args) SWIG_fail;
   swig_obj[0] = args;
@@ -24560,7 +24560,7 @@ SWIGINTERN PyObject *_wrap_kvector_t_complex(PyObject *SWIGUNUSEDPARM(self), PyO
   }
   arg1 = reinterpret_cast< BasicVector3D< double > * >(argp1);
   result = ((BasicVector3D< double > const *)arg1)->complex();
-  resultobj = SWIG_NewPointerObj((new BasicVector3D< std::complex< double > >(static_cast< const BasicVector3D< std::complex< double > >& >(result))), SWIGTYPE_p_BasicVector3DT_std__complexT_double_t_t, SWIG_POINTER_OWN |  0 );
+  resultobj = SWIG_NewPointerObj((new BasicVector3D< complex_t >(static_cast< const BasicVector3D< complex_t >& >(result))), SWIGTYPE_p_BasicVector3DT_std__complexT_double_t_t, SWIG_POINTER_OWN |  0 );
   return resultobj;
 fail:
   return NULL;
@@ -29146,7 +29146,7 @@ fail:
 }
 
 
-SWIGINTERN PyObject *_wrap_IntensityData_axis__SWIG_0(PyObject *SWIGUNUSEDPARM(self), Py_ssize_t nobjs, PyObject **swig_obj) {
+SWIGINTERN PyObject *_wrap_IntensityData_axis(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
   PyObject *resultobj = 0;
   OutputData< double > *arg1 = (OutputData< double > *) 0 ;
   size_t arg2 ;
@@ -29154,9 +29154,10 @@ SWIGINTERN PyObject *_wrap_IntensityData_axis__SWIG_0(PyObject *SWIGUNUSEDPARM(s
   int res1 = 0 ;
   size_t val2 ;
   int ecode2 = 0 ;
+  PyObject *swig_obj[2] ;
   IAxis *result = 0 ;
   
-  if ((nobjs < 2) || (nobjs > 2)) SWIG_fail;
+  if (!SWIG_Python_UnpackTuple(args, "IntensityData_axis", 2, 2, swig_obj)) SWIG_fail;
   res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_OutputDataT_double_t, 0 |  0 );
   if (!SWIG_IsOK(res1)) {
     SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "IntensityData_axis" "', argument " "1"" of type '" "OutputData< double > const *""'"); 
@@ -29175,88 +29176,6 @@ fail:
 }
 
 
-SWIGINTERN PyObject *_wrap_IntensityData_axis__SWIG_1(PyObject *SWIGUNUSEDPARM(self), Py_ssize_t nobjs, PyObject **swig_obj) {
-  PyObject *resultobj = 0;
-  OutputData< double > *arg1 = (OutputData< double > *) 0 ;
-  std::string *arg2 = 0 ;
-  void *argp1 = 0 ;
-  int res1 = 0 ;
-  int res2 = SWIG_OLDOBJ ;
-  IAxis *result = 0 ;
-  
-  if ((nobjs < 2) || (nobjs > 2)) SWIG_fail;
-  res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_OutputDataT_double_t, 0 |  0 );
-  if (!SWIG_IsOK(res1)) {
-    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "IntensityData_axis" "', argument " "1"" of type '" "OutputData< double > const *""'"); 
-  }
-  arg1 = reinterpret_cast< OutputData< double > * >(argp1);
-  {
-    std::string *ptr = (std::string *)0;
-    res2 = SWIG_AsPtr_std_string(swig_obj[1], &ptr);
-    if (!SWIG_IsOK(res2)) {
-      SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "IntensityData_axis" "', argument " "2"" of type '" "std::string const &""'"); 
-    }
-    if (!ptr) {
-      SWIG_exception_fail(SWIG_ValueError, "invalid null reference " "in method '" "IntensityData_axis" "', argument " "2"" of type '" "std::string const &""'"); 
-    }
-    arg2 = ptr;
-  }
-  result = (IAxis *) &((OutputData< double > const *)arg1)->axis((std::string const &)*arg2);
-  resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_IAxis, 0 |  0 );
-  if (SWIG_IsNewObj(res2)) delete arg2;
-  return resultobj;
-fail:
-  if (SWIG_IsNewObj(res2)) delete arg2;
-  return NULL;
-}
-
-
-SWIGINTERN PyObject *_wrap_IntensityData_axis(PyObject *self, PyObject *args) {
-  Py_ssize_t argc;
-  PyObject *argv[3] = {
-    0
-  };
-  
-  if (!(argc = SWIG_Python_UnpackTuple(args, "IntensityData_axis", 0, 2, argv))) SWIG_fail;
-  --argc;
-  if (argc == 2) {
-    int _v;
-    void *vptr = 0;
-    int res = SWIG_ConvertPtr(argv[0], &vptr, SWIGTYPE_p_OutputDataT_double_t, 0);
-    _v = SWIG_CheckState(res);
-    if (_v) {
-      {
-        int res = SWIG_AsVal_size_t(argv[1], NULL);
-        _v = SWIG_CheckState(res);
-      }
-      if (_v) {
-        return _wrap_IntensityData_axis__SWIG_0(self, argc, argv);
-      }
-    }
-  }
-  if (argc == 2) {
-    int _v;
-    void *vptr = 0;
-    int res = SWIG_ConvertPtr(argv[0], &vptr, SWIGTYPE_p_OutputDataT_double_t, 0);
-    _v = SWIG_CheckState(res);
-    if (_v) {
-      int res = SWIG_AsPtr_std_string(argv[1], (std::string**)(0));
-      _v = SWIG_CheckState(res);
-      if (_v) {
-        return _wrap_IntensityData_axis__SWIG_1(self, argc, argv);
-      }
-    }
-  }
-  
-fail:
-  SWIG_Python_RaiseOrModifyTypeError("Wrong number or type of arguments for overloaded function 'IntensityData_axis'.\n"
-    "  Possible C/C++ prototypes are:\n"
-    "    OutputData< double >::axis(size_t) const\n"
-    "    OutputData< double >::axis(std::string const &) const\n");
-  return 0;
-}
-
-
 SWIGINTERN PyObject *_wrap_IntensityData_rank(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
   PyObject *resultobj = 0;
   OutputData< double > *arg1 = (OutputData< double > *) 0 ;
@@ -35771,7 +35690,7 @@ SWIGINTERN PyObject *_wrap_FindPeaks__SWIG_0(PyObject *SWIGUNUSEDPARM(self), Py_
     SWIG_exception_fail(SWIG_ArgError(ecode4), "in method '" "FindPeaks" "', argument " "4"" of type '" "double""'");
   } 
   arg4 = static_cast< double >(val4);
-  result = SpectrumUtils::FindPeaks((Histogram2D const &)*arg1,arg2,(std::string const &)*arg3,arg4);
+  result = ImageUtils::FindPeaks((Histogram2D const &)*arg1,arg2,(std::string const &)*arg3,arg4);
   resultobj = swig::from(static_cast< std::vector< std::pair< double,double >,std::allocator< std::pair< double,double > > > >(result));
   if (SWIG_IsNewObj(res3)) delete arg3;
   return resultobj;
@@ -35818,7 +35737,7 @@ SWIGINTERN PyObject *_wrap_FindPeaks__SWIG_1(PyObject *SWIGUNUSEDPARM(self), Py_
     }
     arg3 = ptr;
   }
-  result = SpectrumUtils::FindPeaks((Histogram2D const &)*arg1,arg2,(std::string const &)*arg3);
+  result = ImageUtils::FindPeaks((Histogram2D const &)*arg1,arg2,(std::string const &)*arg3);
   resultobj = swig::from(static_cast< std::vector< std::pair< double,double >,std::allocator< std::pair< double,double > > > >(result));
   if (SWIG_IsNewObj(res3)) delete arg3;
   return resultobj;
@@ -35852,7 +35771,7 @@ SWIGINTERN PyObject *_wrap_FindPeaks__SWIG_2(PyObject *SWIGUNUSEDPARM(self), Py_
     SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "FindPeaks" "', argument " "2"" of type '" "double""'");
   } 
   arg2 = static_cast< double >(val2);
-  result = SpectrumUtils::FindPeaks((Histogram2D const &)*arg1,arg2);
+  result = ImageUtils::FindPeaks((Histogram2D const &)*arg1,arg2);
   resultobj = swig::from(static_cast< std::vector< std::pair< double,double >,std::allocator< std::pair< double,double > > > >(result));
   return resultobj;
 fail:
@@ -35876,7 +35795,7 @@ SWIGINTERN PyObject *_wrap_FindPeaks__SWIG_3(PyObject *SWIGUNUSEDPARM(self), Py_
     SWIG_exception_fail(SWIG_ValueError, "invalid null reference " "in method '" "FindPeaks" "', argument " "1"" of type '" "Histogram2D const &""'"); 
   }
   arg1 = reinterpret_cast< Histogram2D * >(argp1);
-  result = SpectrumUtils::FindPeaks((Histogram2D const &)*arg1);
+  result = ImageUtils::FindPeaks((Histogram2D const &)*arg1);
   resultobj = swig::from(static_cast< std::vector< std::pair< double,double >,std::allocator< std::pair< double,double > > > >(result));
   return resultobj;
 fail:
@@ -35960,10 +35879,10 @@ SWIGINTERN PyObject *_wrap_FindPeaks(PyObject *self, PyObject *args) {
 fail:
   SWIG_Python_RaiseOrModifyTypeError("Wrong number or type of arguments for overloaded function 'FindPeaks'.\n"
     "  Possible C/C++ prototypes are:\n"
-    "    SpectrumUtils::FindPeaks(Histogram2D const &,double,std::string const &,double)\n"
-    "    SpectrumUtils::FindPeaks(Histogram2D const &,double,std::string const &)\n"
-    "    SpectrumUtils::FindPeaks(Histogram2D const &,double)\n"
-    "    SpectrumUtils::FindPeaks(Histogram2D const &)\n");
+    "    ImageUtils::FindPeaks(Histogram2D const &,double,std::string const &,double)\n"
+    "    ImageUtils::FindPeaks(Histogram2D const &,double,std::string const &)\n"
+    "    ImageUtils::FindPeaks(Histogram2D const &,double)\n"
+    "    ImageUtils::FindPeaks(Histogram2D const &)\n");
   return 0;
 }
 
@@ -45621,10 +45540,9 @@ static PyMethodDef SwigMethods[] = {
 		""},
 	 { "IntensityData_axis", _wrap_IntensityData_axis, METH_VARARGS, "\n"
 		"IntensityData_axis(IntensityData self, size_t serial_number) -> IAxis\n"
-		"IntensityData_axis(IntensityData self, std::string const & axis_name) -> IAxis\n"
-		"const IAxis & OutputData< T >::axis(const std::string &axis_name) const\n"
+		"const IAxis & OutputData< T >::axis(size_t serial_number) const\n"
 		"\n"
-		"returns axis with given name \n"
+		"returns axis with given serial number \n"
 		"\n"
 		""},
 	 { "IntensityData_rank", _wrap_IntensityData_rank, METH_O, "\n"
@@ -46605,7 +46523,9 @@ static PyMethodDef SwigMethods[] = {
 		""},
 	 { "FindPeaks", _wrap_FindPeaks, METH_VARARGS, "\n"
 		"FindPeaks(Histogram2D hist, double sigma=2, std::string const & option={}, double threshold=0.05) -> vector_pvacuum_double_t\n"
-		"std::vector< std::pair< double, double > > SpectrumUtils::FindPeaks(const Histogram2D &hist, double sigma=2, const std::string &option={}, double threshold=0.05)\n"
+		"std::vector< std::pair< double, double > > ImageUtils::FindPeaks(const Histogram2D &hist, double sigma=2, const std::string &option={}, double threshold=0.05)\n"
+		"\n"
+		"Returns vector of peak center coordinates, for peaks in given histogram. \n"
 		"\n"
 		""},
 	 { "delete_IVarianceFunction", _wrap_delete_IVarianceFunction, METH_O, "\n"
@@ -48041,7 +47961,7 @@ static swig_type_info _swigt__p_Axes = {"_p_Axes", "Axes *", 0, 0, (void*)0, 0};
 static swig_type_info _swigt__p_AxisInfo = {"_p_AxisInfo", "AxisInfo *", 0, 0, (void*)0, 0};
 static swig_type_info _swigt__p_BasicVector3DT_double_t = {"_p_BasicVector3DT_double_t", "std::vector< BasicVector3D< double > >::value_type *|kvector_t *|BasicVector3D< double > *", 0, 0, (void*)0, 0};
 static swig_type_info _swigt__p_BasicVector3DT_int_t = {"_p_BasicVector3DT_int_t", "ivector_t *|BasicVector3D< int > *", 0, 0, (void*)0, 0};
-static swig_type_info _swigt__p_BasicVector3DT_std__complexT_double_t_t = {"_p_BasicVector3DT_std__complexT_double_t_t", "BasicVector3D< std::complex< double > > *|std::vector< BasicVector3D< std::complex< double > > >::value_type *|cvector_t *", 0, 0, (void*)0, 0};
+static swig_type_info _swigt__p_BasicVector3DT_std__complexT_double_t_t = {"_p_BasicVector3DT_std__complexT_double_t_t", "BasicVector3D< std::complex< double > > *|std::vector< BasicVector3D< std::complex< double > > >::value_type *|cvector_t *|BasicVector3D< complex_t > *", 0, 0, (void*)0, 0};
 static swig_type_info _swigt__p_Beam = {"_p_Beam", "Beam *", 0, 0, (void*)0, 0};
 static swig_type_info _swigt__p_Bin1D = {"_p_Bin1D", "Bin1D *", 0, 0, (void*)0, 0};
 static swig_type_info _swigt__p_ChiSquaredModule = {"_p_ChiSquaredModule", "ChiSquaredModule *", 0, 0, (void*)0, 0};
diff --git a/auto/Wrap/libBornAgainParam.py b/auto/Wrap/libBornAgainParam.py
index ccd5a62b6833e3e358e852330bdd8c104d177508..276bcb5386e7fa3b0c01822866439985778bcb53 100644
--- a/auto/Wrap/libBornAgainParam.py
+++ b/auto/Wrap/libBornAgainParam.py
@@ -3447,7 +3447,7 @@ class INodeVisitor(object):
         visit(INodeVisitor self, LayerRoughness const * arg2)
         visit(INodeVisitor self, MesoCrystal const * arg2)
         visit(INodeVisitor self, MultiLayer const * arg2)
-        visit(INodeVisitor self, OffSpecSimulation const * arg2)
+        visit(INodeVisitor self, OffSpecularSimulation const * arg2)
         visit(INodeVisitor self, Particle const * arg2)
         visit(INodeVisitor self, ParticleComposition const * arg2)
         visit(INodeVisitor self, ParticleCoreShell const * arg2)
diff --git a/auto/Wrap/libBornAgainParam_wrap.cpp b/auto/Wrap/libBornAgainParam_wrap.cpp
index 52e2a6cca627deb63db10d156a8ffa3774db2037..85144395c3277514a7c79c5424adc9d25d884cf5 100644
--- a/auto/Wrap/libBornAgainParam_wrap.cpp
+++ b/auto/Wrap/libBornAgainParam_wrap.cpp
@@ -3213,7 +3213,7 @@ namespace Swig {
 #define SWIGTYPE_p_MesoCrystal swig_types[113]
 #define SWIGTYPE_p_MultiLayer swig_types[114]
 #define SWIGTYPE_p_NodeMeta swig_types[115]
-#define SWIGTYPE_p_OffSpecSimulation swig_types[116]
+#define SWIGTYPE_p_OffSpecularSimulation swig_types[116]
 #define SWIGTYPE_p_ParaMeta swig_types[117]
 #define SWIGTYPE_p_ParameterDistribution swig_types[118]
 #define SWIGTYPE_p_ParameterPool swig_types[119]
@@ -25163,7 +25163,7 @@ SWIGINTERN PyObject *_wrap_kvector_t_complex(PyObject *SWIGUNUSEDPARM(self), PyO
   void *argp1 = 0 ;
   int res1 = 0 ;
   PyObject *swig_obj[1] ;
-  BasicVector3D< std::complex< double > > result;
+  BasicVector3D< complex_t > result;
   
   if (!args) SWIG_fail;
   swig_obj[0] = args;
@@ -25173,7 +25173,7 @@ SWIGINTERN PyObject *_wrap_kvector_t_complex(PyObject *SWIGUNUSEDPARM(self), PyO
   }
   arg1 = reinterpret_cast< BasicVector3D< double > * >(argp1);
   result = ((BasicVector3D< double > const *)arg1)->complex();
-  resultobj = SWIG_NewPointerObj((new BasicVector3D< std::complex< double > >(static_cast< const BasicVector3D< std::complex< double > >& >(result))), SWIGTYPE_p_BasicVector3DT_std__complexT_double_t_t, SWIG_POINTER_OWN |  0 );
+  resultobj = SWIG_NewPointerObj((new BasicVector3D< complex_t >(static_cast< const BasicVector3D< complex_t >& >(result))), SWIGTYPE_p_BasicVector3DT_std__complexT_double_t_t, SWIG_POINTER_OWN |  0 );
   return resultobj;
 fail:
   return NULL;
@@ -39947,7 +39947,7 @@ fail:
 SWIGINTERN PyObject *_wrap_INodeVisitor_visit__SWIG_105(PyObject *SWIGUNUSEDPARM(self), Py_ssize_t nobjs, PyObject **swig_obj) {
   PyObject *resultobj = 0;
   INodeVisitor *arg1 = (INodeVisitor *) 0 ;
-  OffSpecSimulation *arg2 = (OffSpecSimulation *) 0 ;
+  OffSpecularSimulation *arg2 = (OffSpecularSimulation *) 0 ;
   void *argp1 = 0 ;
   int res1 = 0 ;
   void *argp2 = 0 ;
@@ -39959,12 +39959,12 @@ SWIGINTERN PyObject *_wrap_INodeVisitor_visit__SWIG_105(PyObject *SWIGUNUSEDPARM
     SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "INodeVisitor_visit" "', argument " "1"" of type '" "INodeVisitor *""'"); 
   }
   arg1 = reinterpret_cast< INodeVisitor * >(argp1);
-  res2 = SWIG_ConvertPtr(swig_obj[1], &argp2,SWIGTYPE_p_OffSpecSimulation, 0 |  0 );
+  res2 = SWIG_ConvertPtr(swig_obj[1], &argp2,SWIGTYPE_p_OffSpecularSimulation, 0 |  0 );
   if (!SWIG_IsOK(res2)) {
-    SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "INodeVisitor_visit" "', argument " "2"" of type '" "OffSpecSimulation const *""'"); 
+    SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "INodeVisitor_visit" "', argument " "2"" of type '" "OffSpecularSimulation const *""'"); 
   }
-  arg2 = reinterpret_cast< OffSpecSimulation * >(argp2);
-  (arg1)->visit((OffSpecSimulation const *)arg2);
+  arg2 = reinterpret_cast< OffSpecularSimulation * >(argp2);
+  (arg1)->visit((OffSpecularSimulation const *)arg2);
   resultobj = SWIG_Py_Void();
   return resultobj;
 fail:
@@ -41877,7 +41877,7 @@ SWIGINTERN PyObject *_wrap_INodeVisitor_visit(PyObject *self, PyObject *args) {
     _v = SWIG_CheckState(res);
     if (_v) {
       void *vptr = 0;
-      int res = SWIG_ConvertPtr(argv[1], &vptr, SWIGTYPE_p_OffSpecSimulation, 0);
+      int res = SWIG_ConvertPtr(argv[1], &vptr, SWIGTYPE_p_OffSpecularSimulation, 0);
       _v = SWIG_CheckState(res);
       if (_v) {
         return _wrap_INodeVisitor_visit__SWIG_105(self, argc, argv);
@@ -42203,7 +42203,7 @@ fail:
     "    INodeVisitor::visit(LayerRoughness const *)\n"
     "    INodeVisitor::visit(MesoCrystal const *)\n"
     "    INodeVisitor::visit(MultiLayer const *)\n"
-    "    INodeVisitor::visit(OffSpecSimulation const *)\n"
+    "    INodeVisitor::visit(OffSpecularSimulation const *)\n"
     "    INodeVisitor::visit(Particle const *)\n"
     "    INodeVisitor::visit(ParticleComposition const *)\n"
     "    INodeVisitor::visit(ParticleCoreShell const *)\n"
@@ -51385,7 +51385,7 @@ static PyMethodDef SwigMethods[] = {
 		"INodeVisitor_visit(INodeVisitor self, LayerRoughness const * arg2)\n"
 		"INodeVisitor_visit(INodeVisitor self, MesoCrystal const * arg2)\n"
 		"INodeVisitor_visit(INodeVisitor self, MultiLayer const * arg2)\n"
-		"INodeVisitor_visit(INodeVisitor self, OffSpecSimulation const * arg2)\n"
+		"INodeVisitor_visit(INodeVisitor self, OffSpecularSimulation const * arg2)\n"
 		"INodeVisitor_visit(INodeVisitor self, Particle const * arg2)\n"
 		"INodeVisitor_visit(INodeVisitor self, ParticleComposition const * arg2)\n"
 		"INodeVisitor_visit(INodeVisitor self, ParticleCoreShell const * arg2)\n"
@@ -52298,7 +52298,7 @@ static swig_type_info _swigt__p_Attributes = {"_p_Attributes", "Attributes *", 0
 static swig_type_info _swigt__p_BasicLattice2D = {"_p_BasicLattice2D", "BasicLattice2D *", 0, 0, (void*)0, 0};
 static swig_type_info _swigt__p_BasicVector3DT_double_t = {"_p_BasicVector3DT_double_t", "std::vector< BasicVector3D< double > >::value_type *|kvector_t *|BasicVector3D< double > *", 0, 0, (void*)0, 0};
 static swig_type_info _swigt__p_BasicVector3DT_int_t = {"_p_BasicVector3DT_int_t", "ivector_t *|BasicVector3D< int > *", 0, 0, (void*)0, 0};
-static swig_type_info _swigt__p_BasicVector3DT_std__complexT_double_t_t = {"_p_BasicVector3DT_std__complexT_double_t_t", "BasicVector3D< std::complex< double > > *|std::vector< BasicVector3D< std::complex< double > > >::value_type *|cvector_t *", 0, 0, (void*)0, 0};
+static swig_type_info _swigt__p_BasicVector3DT_std__complexT_double_t_t = {"_p_BasicVector3DT_std__complexT_double_t_t", "BasicVector3D< std::complex< double > > *|std::vector< BasicVector3D< std::complex< double > > >::value_type *|cvector_t *|BasicVector3D< complex_t > *", 0, 0, (void*)0, 0};
 static swig_type_info _swigt__p_Beam = {"_p_Beam", "Beam *", 0, 0, (void*)0, 0};
 static swig_type_info _swigt__p_ConstantBackground = {"_p_ConstantBackground", "ConstantBackground *", 0, 0, (void*)0, 0};
 static swig_type_info _swigt__p_ConvolutionDetectorResolution = {"_p_ConvolutionDetectorResolution", "ConvolutionDetectorResolution *", 0, 0, (void*)0, 0};
@@ -52410,7 +52410,7 @@ static swig_type_info _swigt__p_LayerRoughness = {"_p_LayerRoughness", "LayerRou
 static swig_type_info _swigt__p_MesoCrystal = {"_p_MesoCrystal", "MesoCrystal *", 0, 0, (void*)0, 0};
 static swig_type_info _swigt__p_MultiLayer = {"_p_MultiLayer", "MultiLayer *", 0, 0, (void*)0, 0};
 static swig_type_info _swigt__p_NodeMeta = {"_p_NodeMeta", "NodeMeta *", 0, 0, (void*)0, 0};
-static swig_type_info _swigt__p_OffSpecSimulation = {"_p_OffSpecSimulation", "OffSpecSimulation *", 0, 0, (void*)0, 0};
+static swig_type_info _swigt__p_OffSpecularSimulation = {"_p_OffSpecularSimulation", "OffSpecularSimulation *", 0, 0, (void*)0, 0};
 static swig_type_info _swigt__p_ParaMeta = {"_p_ParaMeta", "ParaMeta *", 0, 0, (void*)0, 0};
 static swig_type_info _swigt__p_ParameterDistribution = {"_p_ParameterDistribution", "ParameterDistribution *", 0, 0, (void*)0, 0};
 static swig_type_info _swigt__p_ParameterPool = {"_p_ParameterPool", "ParameterPool *", 0, 0, (void*)0, 0};
@@ -52611,7 +52611,7 @@ static swig_type_info *swig_type_initial[] = {
   &_swigt__p_MesoCrystal,
   &_swigt__p_MultiLayer,
   &_swigt__p_NodeMeta,
-  &_swigt__p_OffSpecSimulation,
+  &_swigt__p_OffSpecularSimulation,
   &_swigt__p_ParaMeta,
   &_swigt__p_ParameterDistribution,
   &_swigt__p_ParameterPool,
@@ -52812,7 +52812,7 @@ static swig_cast_info _swigc__p_LayerRoughness[] = {  {&_swigt__p_LayerRoughness
 static swig_cast_info _swigc__p_MesoCrystal[] = {  {&_swigt__p_MesoCrystal, 0, 0, 0},{0, 0, 0, 0}};
 static swig_cast_info _swigc__p_MultiLayer[] = {  {&_swigt__p_MultiLayer, 0, 0, 0},{0, 0, 0, 0}};
 static swig_cast_info _swigc__p_NodeMeta[] = {  {&_swigt__p_NodeMeta, 0, 0, 0},{0, 0, 0, 0}};
-static swig_cast_info _swigc__p_OffSpecSimulation[] = {  {&_swigt__p_OffSpecSimulation, 0, 0, 0},{0, 0, 0, 0}};
+static swig_cast_info _swigc__p_OffSpecularSimulation[] = {  {&_swigt__p_OffSpecularSimulation, 0, 0, 0},{0, 0, 0, 0}};
 static swig_cast_info _swigc__p_ParaMeta[] = {  {&_swigt__p_ParaMeta, 0, 0, 0},{0, 0, 0, 0}};
 static swig_cast_info _swigc__p_ParameterDistribution[] = {  {&_swigt__p_ParameterDistribution, 0, 0, 0},{0, 0, 0, 0}};
 static swig_cast_info _swigc__p_ParameterPool[] = {  {&_swigt__p_ParameterPool, 0, 0, 0},{0, 0, 0, 0}};
@@ -53013,7 +53013,7 @@ static swig_cast_info *swig_cast_initial[] = {
   _swigc__p_MesoCrystal,
   _swigc__p_MultiLayer,
   _swigc__p_NodeMeta,
-  _swigc__p_OffSpecSimulation,
+  _swigc__p_OffSpecularSimulation,
   _swigc__p_ParaMeta,
   _swigc__p_ParameterDistribution,
   _swigc__p_ParameterPool,
diff --git a/auto/Wrap/libBornAgainSample.py b/auto/Wrap/libBornAgainSample.py
index fdbdd51b1e11202bd84c6e045e438a5eef0b6eb2..07ed91ac638bc004e6c607b482b9d14417a489bf 100644
--- a/auto/Wrap/libBornAgainSample.py
+++ b/auto/Wrap/libBornAgainSample.py
@@ -8258,7 +8258,7 @@ class Layer(ISampleNode):
     r"""
 
 
-    A layer, with thickness (in nanometer) and material.
+    A layer in a  MultiLayer sample.
 
     C++ includes: Layer.h
 
@@ -11370,7 +11370,14 @@ class Lattice3D(libBornAgainParam.INode):
 _libBornAgainSample.Lattice3D_swigregister(Lattice3D)
 
 class Lattice2D(libBornAgainBase.ICloneable, libBornAgainParam.INode):
-    r"""Proxy of C++ Lattice2D class."""
+    r"""
+
+
+    A two-dimensional Bravais lattice.
+
+    C++ includes: Lattice2D.h
+
+    """
 
     thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
 
@@ -11447,7 +11454,14 @@ class Lattice2D(libBornAgainBase.ICloneable, libBornAgainParam.INode):
 _libBornAgainSample.Lattice2D_swigregister(Lattice2D)
 
 class BasicLattice2D(Lattice2D):
-    r"""Proxy of C++ BasicLattice2D class."""
+    r"""
+
+
+    A two-dimensional Bravais lattice with no special symmetry.
+
+    C++ includes: Lattice2D.h
+
+    """
 
     thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
     __repr__ = _swig_repr
@@ -11513,7 +11527,14 @@ class BasicLattice2D(Lattice2D):
 _libBornAgainSample.BasicLattice2D_swigregister(BasicLattice2D)
 
 class SquareLattice2D(Lattice2D):
-    r"""Proxy of C++ SquareLattice2D class."""
+    r"""
+
+
+    A two-dimensional Bravais lattice with square unit cell.
+
+    C++ includes: Lattice2D.h
+
+    """
 
     thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
     __repr__ = _swig_repr
@@ -11579,7 +11600,14 @@ class SquareLattice2D(Lattice2D):
 _libBornAgainSample.SquareLattice2D_swigregister(SquareLattice2D)
 
 class HexagonalLattice2D(Lattice2D):
-    r"""Proxy of C++ HexagonalLattice2D class."""
+    r"""
+
+
+    A two-dimensional Bravais lattice with hexagonal symmetry.
+
+    C++ includes: Lattice2D.h
+
+    """
 
     thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
     __repr__ = _swig_repr
diff --git a/auto/Wrap/libBornAgainSample_wrap.cpp b/auto/Wrap/libBornAgainSample_wrap.cpp
index 53071a0b3fb570f28157af990b8903e60825cd04..2b3a728a2b5ed0018bfe039fe493ce64b690eaaf 100644
--- a/auto/Wrap/libBornAgainSample_wrap.cpp
+++ b/auto/Wrap/libBornAgainSample_wrap.cpp
@@ -26598,7 +26598,7 @@ SWIGINTERN PyObject *_wrap_kvector_t_complex(PyObject *SWIGUNUSEDPARM(self), PyO
   void *argp1 = 0 ;
   int res1 = 0 ;
   PyObject *swig_obj[1] ;
-  BasicVector3D< std::complex< double > > result;
+  BasicVector3D< complex_t > result;
   
   if (!args) SWIG_fail;
   swig_obj[0] = args;
@@ -26608,7 +26608,7 @@ SWIGINTERN PyObject *_wrap_kvector_t_complex(PyObject *SWIGUNUSEDPARM(self), PyO
   }
   arg1 = reinterpret_cast< BasicVector3D< double > * >(argp1);
   result = ((BasicVector3D< double > const *)arg1)->complex();
-  resultobj = SWIG_NewPointerObj((new BasicVector3D< std::complex< double > >(static_cast< const BasicVector3D< std::complex< double > >& >(result))), SWIGTYPE_p_BasicVector3DT_std__complexT_double_t_t, SWIG_POINTER_OWN |  0 );
+  resultobj = SWIG_NewPointerObj((new BasicVector3D< complex_t >(static_cast< const BasicVector3D< complex_t >& >(result))), SWIGTYPE_p_BasicVector3DT_std__complexT_double_t_t, SWIG_POINTER_OWN |  0 );
   return resultobj;
 fail:
   return NULL;
@@ -77485,7 +77485,7 @@ static void *_p_FTDistribution2DConeTo_p_IFTDistribution2D(void *x, int *SWIGUNU
 static swig_type_info _swigt__p_BasicLattice2D = {"_p_BasicLattice2D", "BasicLattice2D *", 0, 0, (void*)0, 0};
 static swig_type_info _swigt__p_BasicVector3DT_double_t = {"_p_BasicVector3DT_double_t", "std::vector< BasicVector3D< double > >::value_type *|kvector_t *|BasicVector3D< double > *", 0, 0, (void*)0, 0};
 static swig_type_info _swigt__p_BasicVector3DT_int_t = {"_p_BasicVector3DT_int_t", "ivector_t *|BasicVector3D< int > *", 0, 0, (void*)0, 0};
-static swig_type_info _swigt__p_BasicVector3DT_std__complexT_double_t_t = {"_p_BasicVector3DT_std__complexT_double_t_t", "BasicVector3D< std::complex< double > > *|std::vector< BasicVector3D< std::complex< double > > >::value_type *|cvector_t *", 0, 0, (void*)0, 0};
+static swig_type_info _swigt__p_BasicVector3DT_std__complexT_double_t_t = {"_p_BasicVector3DT_std__complexT_double_t_t", "BasicVector3D< std::complex< double > > *|std::vector< BasicVector3D< std::complex< double > > >::value_type *|cvector_t *|BasicVector3D< complex_t > *", 0, 0, (void*)0, 0};
 static swig_type_info _swigt__p_CallbackMap_t = {"_p_CallbackMap_t", "CallbackMap_t *", 0, 0, (void*)0, 0};
 static swig_type_info _swigt__p_CreateItemCallback = {"_p_CreateItemCallback", "CreateItemCallback *", 0, 0, (void*)0, 0};
 static swig_type_info _swigt__p_Crystal = {"_p_Crystal", "Crystal *", 0, 0, (void*)0, 0};
diff --git a/cmake/BornAgain/MakeLib.cmake b/cmake/BornAgain/MakeLib.cmake
index 684f2421896567e07b49621513b0f833a189788f..3e2d6ea84ae001c04cd531fe5d5e03ea6b34e0fe 100644
--- a/cmake/BornAgain/MakeLib.cmake
+++ b/cmake/BornAgain/MakeLib.cmake
@@ -1,3 +1,5 @@
+# Configure one component library.
+
 function(MakeLib name lib tmpdir)
 
     if(BORNAGAIN_PYTHON)
diff --git a/cmake/BornAgain/PythonDocs.cmake b/cmake/BornAgain/PythonDocs.cmake
index 4d880d703c78a39e5e78bd33b45fd8bf253effc4..38a218ef900ba492e309747a5518735bf604a1a6 100644
--- a/cmake/BornAgain/PythonDocs.cmake
+++ b/cmake/BornAgain/PythonDocs.cmake
@@ -1,4 +1,5 @@
 # Autogenerate a .i file from doxygen comments, provided -DCONFIGURE_PYTHON_DOCS=ON.
+# Called from function SwigLib.
 
 function(GeneratePythonDocs PD_TARGET SWIG_DIR)
     if(CONFIGURE_PYTHON_DOCS)
diff --git a/cmake/BornAgain/SwigLib.cmake b/cmake/BornAgain/SwigLib.cmake
index 8495507f5abb54507c8e5ca21633058447a9ee0e..1513b5e1c459509b14e8aa300148e99e48fc4329 100644
--- a/cmake/BornAgain/SwigLib.cmake
+++ b/cmake/BornAgain/SwigLib.cmake
@@ -1,3 +1,6 @@
+# Configure Python bindings for one component library.
+# Called from function MakeLib.
+
 function(SwigLib name lib TMP_DIR)
 
     if(NOT BORNAGAIN_PYTHON)
@@ -10,8 +13,7 @@ function(SwigLib name lib TMP_DIR)
 
         file(MAKE_DIRECTORY ${TMP_DIR})
 
-        GeneratePythonDocs(${AUTO_DIR}/doxygen${name}.i ${SWIG_DIR})
-
+        # static (manually written) input files
         set(swig_dependencies
             ${SWIG_DIR}/lib${lib}.i
             ${SWIG_DIR}/deprecation.i
@@ -24,6 +26,9 @@ function(SwigLib name lib TMP_DIR)
                 message(FATAL_ERROR "Could NOT find SWIG input ${FNAM}")
             endif()
         endforeach()
+
+        # dynamic (autogenerated) input files
+        GeneratePythonDocs(${AUTO_DIR}/doxygen${name}.i ${SWIG_DIR})
         list(APPEND swig_dependencies ${AUTO_DIR}/doxygen${name}.i)
 
         # Run Swig.