diff --git a/Base/Element/DepthProbeElement.cpp b/Base/Element/DepthProbeElement.cpp
index ec3e318b074587401fcc8529a945c8fe10db5449..47b80b728b417bb19ff7bbfb33b0879f8b4b0210 100644
--- a/Base/Element/DepthProbeElement.cpp
+++ b/Base/Element/DepthProbeElement.cpp
@@ -19,7 +19,7 @@
 const double phi_i_0 = 0.0;
 
 DepthProbeElement::DepthProbeElement(double wavelength, double alpha_i, const IAxis* z_positions)
-    : IElement(PolarizerPair())
+    : IElement(PolMatrices())
     , m_wavelength(wavelength)
     , m_alpha_i(alpha_i)
     , m_z_positions(z_positions)
@@ -32,7 +32,7 @@ DepthProbeElement::DepthProbeElement(double wavelength, double alpha_i, const IA
 }
 
 DepthProbeElement::DepthProbeElement(DepthProbeElement&& other) noexcept
-    : IElement(PolarizerPair())
+    : IElement(PolMatrices())
     , m_wavelength(other.m_wavelength)
     , m_alpha_i(other.m_alpha_i)
     , m_intensities(std::move(other.m_intensities))
diff --git a/Base/Element/IElement.h b/Base/Element/IElement.h
index 2883faccf1f6c3e6db8109b78613b04009c385c9..57dadbb80f4685ad61953427cf82700729bff0d1 100644
--- a/Base/Element/IElement.h
+++ b/Base/Element/IElement.h
@@ -20,7 +20,7 @@
 #ifndef BORNAGAIN_BASE_ELEMENT_IELEMENT_H
 #define BORNAGAIN_BASE_ELEMENT_IELEMENT_H
 
-#include "Base/Element/PolarizerPair.h"
+#include "Base/Element/PolMatrices.h"
 //#include "Base/Vector/Vectors3D.h"
 #include <memory>
 
@@ -28,10 +28,10 @@
 
 class IElement {
 public:
-    IElement(const PolarizerPair& polpair) : m_polpair(polpair) {}
+    IElement(const PolMatrices& polpair) : m_polpair(polpair) {}
 
 protected:
-    const PolarizerPair m_polpair;
+    const PolMatrices m_polpair;
 };
 
 #endif // BORNAGAIN_BASE_ELEMENT_IELEMENT_H
diff --git a/Base/Element/PolarizerPair.cpp b/Base/Element/PolMatrices.cpp
similarity index 54%
rename from Base/Element/PolarizerPair.cpp
rename to Base/Element/PolMatrices.cpp
index 2c079eb40ad305427799bcf4bd9fda7da884ee9d..c443011f0626a84a92a443a0bac8a06165b4372e 100644
--- a/Base/Element/PolarizerPair.cpp
+++ b/Base/Element/PolMatrices.cpp
@@ -2,7 +2,7 @@
 //
 //  BornAgain: simulate and fit reflection and scattering
 //
-//! @file      Base/Element/PolarizerPair.cpp
+//! @file      Base/Element/PolMatrices.cpp
 //! @brief     Implements class PolarizerPair.
 //!
 //! @homepage  http://www.bornagainproject.org
@@ -12,22 +12,16 @@
 //
 //  ************************************************************************************************
 
-#include "Base/Element/PolarizerPair.h"
+#include "Base/Element/PolMatrices.h"
 
 // corresponds to completely unpolarized beam and the absence of spin selection in the analyzer
-PolarizerPair::PolarizerPair()
-    : m_polpair(Eigen::Matrix2cd::Identity() / 2.0)
-    , m_analyzer_operator(Eigen::Matrix2cd::Identity())
+PolMatrices::PolMatrices()
+    : m_polarizer_matrix(Eigen::Matrix2cd::Identity() / 2.0)
+    , m_analyzer_matrix(Eigen::Matrix2cd::Identity())
 {
 }
 
-PolarizerPair::PolarizerPair(const Eigen::Matrix2cd& polarization, const Eigen::Matrix2cd& analyzer)
-    : m_polpair(polarization), m_analyzer_operator(analyzer)
+PolMatrices::PolMatrices(const Eigen::Matrix2cd& polarization, const Eigen::Matrix2cd& analyzer)
+    : m_polarizer_matrix(polarization), m_analyzer_matrix(analyzer)
 {
 }
-
-void PolarizerPair::swapContent(PolarizerPair& other)
-{
-    std::swap(m_polpair, other.m_polpair);
-    std::swap(m_analyzer_operator, other.m_analyzer_operator);
-}
diff --git a/Base/Element/PolarizerPair.h b/Base/Element/PolMatrices.h
similarity index 57%
rename from Base/Element/PolarizerPair.h
rename to Base/Element/PolMatrices.h
index 5e0f7b72c4197366b3bc42f2e52dace5323a0d2c..d67d721ed6cc82667ad9b6ccc25b0c5f67006327 100644
--- a/Base/Element/PolarizerPair.h
+++ b/Base/Element/PolMatrices.h
@@ -2,7 +2,7 @@
 //
 //  BornAgain: simulate and fit reflection and scattering
 //
-//! @file      Base/Element/PolarizerPair.h
+//! @file      Base/Element/PolMatrices.h
 //! @brief     Defines class PolarizerPair.
 //!
 //! @homepage  http://www.bornagainproject.org
@@ -17,37 +17,38 @@
 #endif
 
 #ifndef USER_API
-#ifndef BORNAGAIN_BASE_ELEMENT_POLARIZERPAIR_H
-#define BORNAGAIN_BASE_ELEMENT_POLARIZERPAIR_H
+#ifndef BORNAGAIN_BASE_ELEMENT_POLMATRICES_H
+#define BORNAGAIN_BASE_ELEMENT_POLMATRICES_H
 
 #include "Base/Vector/EigenCore.h"
 
 //! Convenience class for handling polarization density matrix and polarization analyzer operator
 //! @ingroup simulation
 
-class PolarizerPair {
+class PolMatrices {
 public:
-    PolarizerPair();
-    PolarizerPair(const Eigen::Matrix2cd& polarization, const Eigen::Matrix2cd& analyzer);
+    PolMatrices();
+    PolMatrices(const Eigen::Matrix2cd& polarization, const Eigen::Matrix2cd& analyzer);
 
     //! Sets the polarization density matrix (in spin basis along z-axis)
-    void setPolarization(const Eigen::Matrix2cd& polarization) { m_polpair = polarization; }
+    void setPolarizerMatrix(const Eigen::Matrix2cd& polarization)
+    {
+        m_polarizer_matrix = polarization;
+    }
 
     //! Gets the polarization density matrix (in spin basis along z-axis)
-    Eigen::Matrix2cd getPolarization() const { return m_polpair; }
+    Eigen::Matrix2cd polarizerMatrix() const { return m_polarizer_matrix; }
 
     //! Sets the polarization analyzer operator (in spin basis along z-axis)
-    void setAnalyzerOperator(const Eigen::Matrix2cd& analyzer) { m_analyzer_operator = analyzer; }
+    void setAnalyzerMatrix(const Eigen::Matrix2cd& analyzer) { m_analyzer_matrix = analyzer; }
 
     //! Gets the polarization analyzer operator (in spin basis along z-axis)
-    Eigen::Matrix2cd getAnalyzerOperator() const { return m_analyzer_operator; }
-
-    void swapContent(PolarizerPair& other);
+    Eigen::Matrix2cd analyzerMatrix() const { return m_analyzer_matrix; }
 
 private:
-    Eigen::Matrix2cd m_polpair;           //!< polarization density matrix
-    Eigen::Matrix2cd m_analyzer_operator; //!< polarization analyzer operator
+    Eigen::Matrix2cd m_polarizer_matrix; //!< polarization density matrix
+    Eigen::Matrix2cd m_analyzer_matrix;  //!< polarization analyzer operator
 };
 
-#endif // BORNAGAIN_BASE_ELEMENT_POLARIZERPAIR_H
+#endif // BORNAGAIN_BASE_ELEMENT_POLMATRICES_H
 #endif // USER_API
diff --git a/CHANGELOG b/CHANGELOG
index 11936e40eea2d1fee0e7195c4f778f174cba8be9..b8a85396deba9747bab34faa35eb5f1cfa4cba34 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -2,6 +2,7 @@ BornAgain-1.20?
   > API changes:
     * Rename QSpecScan, AngularSpecScan to QzScan, AlphaScan
     * Rename SimulationResult::axis to convertedBinCenters
+    * Polarizer and analyzer are now set by function Instrument::setPolFilters
     * Support soft-matter reflectometry parameterization files of Anaklasis
     * Remove FormFactorDot to avoid its inherent inconsistencies (use small sphere instead)
     * Remove unused/undocumented functions Layer::setThickness, setMaterial
diff --git a/Core/Computation/SpecularComputation.cpp b/Core/Computation/SpecularComputation.cpp
index a5364803acf56fb3734d03cdbfcc9453ad221f27..a774a44c8d19679634c3a9fdab3839558a9211d4 100644
--- a/Core/Computation/SpecularComputation.cpp
+++ b/Core/Computation/SpecularComputation.cpp
@@ -43,8 +43,8 @@ void SpecularComputation::runProtected()
         if (m_re_sample.polarizing()) {
             const Eigen::Matrix2cd R = Compute::SpecularMagnetic::topLayerR(slices, kz_stack, true);
 
-            const auto& polarization = ele.polarizationHandler().getPolarization();
-            const auto& analyzer = ele.polarizationHandler().getAnalyzerOperator();
+            const auto& polarization = ele.polarizationHandler().polarizerMatrix();
+            const auto& analyzer = ele.polarizationHandler().analyzerMatrix();
 
             const complex_t trace = (polarization * R.adjoint() * analyzer * R).trace();
 
diff --git a/Core/Examples/SimulationFactory.cpp b/Core/Examples/SimulationFactory.cpp
index 22d34a910263b2ad14c3b50283e4691d1706ff43..e7f3551fb168bc22f096c393fbe3d4b5c3c433cc 100644
--- a/Core/Examples/SimulationFactory.cpp
+++ b/Core/Examples/SimulationFactory.cpp
@@ -23,7 +23,7 @@ SimulationFactory::SimulationFactory()
 
     registerItem("BasicGISAS00", StandardSimulations::BasicGISAS00);
 
-    registerItem("BasicPolarizedGISAS", StandardSimulations::BasicPolarizedGISAS);
+    registerItem("SpinflipGISAS", StandardSimulations::SpinflipGISAS);
 
     registerItem("MiniGISAS", StandardSimulations::MiniGISAS);
 
diff --git a/Core/Examples/StandardSimulations.cpp b/Core/Examples/StandardSimulations.cpp
index e02a9d0614a0a279be4a61b2be56355dbf8b4ef5..758f9bbfc7ed495b9422be39f445642aa6ca5e39 100644
--- a/Core/Examples/StandardSimulations.cpp
+++ b/Core/Examples/StandardSimulations.cpp
@@ -42,6 +42,9 @@ namespace {
 const size_t rdet_nbinsx(40), rdet_nbinsy(30);
 const double rdet_width(20.0), rdet_height(18.0), rdet_distance(1000.0);
 
+const kvector_t zplus(0.0, 0.0, 1.0);
+const kvector_t yplus(0.0, 1.0, 0.0);
+
 } // namespace
 
 using Units::angstrom;
@@ -61,20 +64,16 @@ GISASSimulation* StandardSimulations::BasicGISAS()
 GISASSimulation* StandardSimulations::BasicGISAS00()
 {
     GISASSimulation* result = BasicGISAS();
-    kvector_t zplus(0.0, 0.0, 1.0);
-    result->beam().setPolarization(zplus);
-    result->detector().setAnalyzerProperties(zplus, 1.0, 0.5);
+    result->instrument().setPolFilters(zplus, zplus, 1.0, 0.5);
     return result;
 }
 
 //! Basic GISAS simulation for spin flip channel.
 
-GISASSimulation* StandardSimulations::BasicPolarizedGISAS()
+GISASSimulation* StandardSimulations::SpinflipGISAS()
 {
     GISASSimulation* result = BasicGISAS();
-    kvector_t zplus(0.0, 0.0, 1.0);
-    result->beam().setPolarization(zplus);
-    result->detector().setAnalyzerProperties(zplus, -1.0, 0.5);
+    result->instrument().setPolFilters(zplus, zplus, -1.0, 0.5);
     return result;
 }
 
@@ -158,48 +157,28 @@ GISASSimulation* StandardSimulations::MiniGISASDetectorResolution()
 GISASSimulation* StandardSimulations::MiniGISASPolarizationPP()
 {
     GISASSimulation* result = MiniGISAS();
-
-    kvector_t analyzer_dir(0.0, 0.0, 1.0);
-    kvector_t beampol(0.0, 0.0, 1.0);
-
-    result->beam().setPolarization(beampol);
-    result->detector().setAnalyzerProperties(analyzer_dir, 1.0, 0.5);
+    result->instrument().setPolFilters(zplus, zplus, 1.0, 0.5);
     return result;
 }
 
 GISASSimulation* StandardSimulations::MiniGISASPolarizationPM()
 {
     GISASSimulation* result = MiniGISAS();
-
-    kvector_t analyzer_dir(0.0, 0.0, -1.0);
-    kvector_t beampol(0.0, 0.0, 1.0);
-
-    result->beam().setPolarization(beampol);
-    result->detector().setAnalyzerProperties(analyzer_dir, 1.0, 0.5);
+    result->instrument().setPolFilters(zplus, -zplus, 1.0, 0.5);
     return result;
 }
 
 GISASSimulation* StandardSimulations::MiniGISASPolarizationMP()
 {
     GISASSimulation* result = MiniGISAS();
-
-    kvector_t analyzer_dir(0.0, 0.0, 1.0);
-    kvector_t beampol(0.0, 0.0, -1.0);
-
-    result->beam().setPolarization(beampol);
-    result->detector().setAnalyzerProperties(analyzer_dir, 1.0, 0.5);
+    result->instrument().setPolFilters(-zplus, zplus, 1.0, 0.5);
     return result;
 }
 
 GISASSimulation* StandardSimulations::MiniGISASPolarizationMM()
 {
     GISASSimulation* result = MiniGISAS();
-
-    kvector_t analyzer_dir(0.0, 0.0, -1.0);
-    kvector_t beampol(0.0, 0.0, -1.0);
-
-    result->beam().setPolarization(beampol);
-    result->detector().setAnalyzerProperties(analyzer_dir, 1.0, 0.5);
+    result->instrument().setPolFilters(-zplus, -zplus, 1.0, 0.5);
     return result;
 }
 
@@ -229,9 +208,7 @@ GISASSimulation* StandardSimulations::MaxiGISAS()
 GISASSimulation* StandardSimulations::MaxiGISAS00()
 {
     GISASSimulation* result = MaxiGISAS();
-    kvector_t zplus(0.0, 0.0, 1.0);
-    result->beam().setPolarization(zplus);
-    result->detector().setAnalyzerProperties(zplus, 1.0, 0.5);
+    result->instrument().setPolFilters(zplus, zplus, 1.0, 0.5);
     return result;
 }
 
@@ -484,64 +461,56 @@ SpecularSimulation* StandardSimulations::TOFRWithPointwiseResolution()
 SpecularSimulation* StandardSimulations::BasicSpecularPP()
 {
     auto* simulation = BasicSpecular();
-    simulation->beam().setPolarization({0.0, 1.0, 0.0});
-    simulation->detector().setAnalyzerProperties({0.0, 1.0, 0.0}, 1.0, 0.5);
+    simulation->instrument().setPolFilters(yplus, yplus, 1.0, 0.5);
     return simulation;
 }
 
 SpecularSimulation* StandardSimulations::BasicSpecularPM()
 {
     auto* simulation = BasicSpecular();
-    simulation->beam().setPolarization({0.0, 1.0, 0.0});
-    simulation->detector().setAnalyzerProperties({0.0, -1.0, 0.0}, 1.0, 0.5);
+    simulation->instrument().setPolFilters(yplus, -yplus, 1.0, 0.5);
     return simulation;
 }
 
 SpecularSimulation* StandardSimulations::BasicSpecularMP()
 {
     auto* simulation = BasicSpecular();
-    simulation->beam().setPolarization({0.0, -1.0, 0.0});
-    simulation->detector().setAnalyzerProperties({0.0, 1.0, 0.0}, 1.0, 0.5);
+    simulation->instrument().setPolFilters(-yplus, yplus, 1.0, 0.5);
     return simulation;
 }
 
 SpecularSimulation* StandardSimulations::BasicSpecularMM()
 {
     auto* simulation = BasicSpecular();
-    simulation->beam().setPolarization({0.0, -1.0, 0.0});
-    simulation->detector().setAnalyzerProperties({0.0, -1.0, 0.0}, 1.0, 0.5);
+    simulation->instrument().setPolFilters(-yplus, -yplus, 1.0, 0.5);
     return simulation;
 }
 
 SpecularSimulation* StandardSimulations::BasicSpecularQPP()
 {
     auto* simulation = BasicSpecularQ();
-    simulation->beam().setPolarization({0.0, 1.0, 0.0});
-    simulation->detector().setAnalyzerProperties({0.0, 1.0, 0.0}, 1.0, 0.5);
+    simulation->instrument().setPolFilters(yplus, yplus, 1.0, 0.5);
     return simulation;
 }
 
-SpecularSimulation* StandardSimulations::BasicSpecularQMM()
+SpecularSimulation* StandardSimulations::BasicSpecularQPM()
 {
     auto* simulation = BasicSpecularQ();
-    simulation->beam().setPolarization({0.0, -1.0, 0.0});
-    simulation->detector().setAnalyzerProperties({0.0, -1.0, 0.0}, 1.0, 0.5);
+    simulation->instrument().setPolFilters(yplus, -yplus, 1.0, 0.5);
     return simulation;
 }
 
-SpecularSimulation* StandardSimulations::BasicSpecularQPM()
+SpecularSimulation* StandardSimulations::BasicSpecularQMP()
 {
     auto* simulation = BasicSpecularQ();
-    simulation->beam().setPolarization({0.0, 1.0, 0.0});
-    simulation->detector().setAnalyzerProperties({0.0, -1.0, 0.0}, 1.0, 0.5);
+    simulation->instrument().setPolFilters(-yplus, yplus, 1.0, 0.5);
     return simulation;
 }
 
-SpecularSimulation* StandardSimulations::BasicSpecularQMP()
+SpecularSimulation* StandardSimulations::BasicSpecularQMM()
 {
     auto* simulation = BasicSpecularQ();
-    simulation->beam().setPolarization({0.0, -1.0, 0.0});
-    simulation->detector().setAnalyzerProperties({0.0, 1.0, 0.0}, 1.0, 0.5);
+    simulation->instrument().setPolFilters(-yplus, -yplus, 1.0, 0.5);
     return simulation;
 }
 
diff --git a/Core/Examples/StandardSimulations.h b/Core/Examples/StandardSimulations.h
index 9a534c21b5ea5cbdcfcfdf2baf080286507a6e23..eb5b770a636df101fb74622b566d326f79cac5ef 100644
--- a/Core/Examples/StandardSimulations.h
+++ b/Core/Examples/StandardSimulations.h
@@ -32,7 +32,7 @@ namespace StandardSimulations {
 // CoreSuite tests:
 GISASSimulation* BasicGISAS();
 GISASSimulation* BasicGISAS00();
-GISASSimulation* BasicPolarizedGISAS();
+GISASSimulation* SpinflipGISAS();
 GISASSimulation* MiniGISAS();
 GISASSimulation* MiniGISAS_v2();
 GISASSimulation* MiniGISASBeamDivergence();
diff --git a/Core/Export/SimulationToPython.cpp b/Core/Export/SimulationToPython.cpp
index e84f1e9dccc8da8ebfd50c863078442dd3e03f95..858afebb9366919c563bde5789da19b906709745 100644
--- a/Core/Export/SimulationToPython.cpp
+++ b/Core/Export/SimulationToPython.cpp
@@ -29,7 +29,7 @@
 #include "Device/Beam/FootprintSquare.h"
 #include "Device/Detector/RectangularDetector.h"
 #include "Device/Detector/SphericalDetector.h"
-#include "Device/ProDetector/DetectorMask.h"
+#include "Device/Mask/DetectorMask.h"
 #include "Device/Resolution/ConvolutionDetectorResolution.h"
 #include "Device/Resolution/ResolutionFunction2DGaussian.h"
 #include "Device/Resolution/ScanResolution.h"
@@ -242,9 +242,9 @@ std::string defineDetectorPolarizationAnalysis(const ISimulation* simulation)
 {
     std::ostringstream result;
     const IDetector& detector = simulation->detector();
-    kvector_t analyzer_direction = detector.detectionProperties().analyzerDirection();
-    double analyzer_efficiency = detector.detectionProperties().analyzerEfficiency();
-    double analyzer_total_transmission = detector.detectionProperties().analyzerTotalTransmission();
+    kvector_t analyzer_direction = detector.analyzer().polDirection();
+    double analyzer_efficiency = detector.analyzer().polEfficiency();
+    double analyzer_total_transmission = detector.analyzer().totalTransmission();
 
     if (analyzer_direction.mag() > 0.0) {
         std::string direction_name = "analyzer_direction";
@@ -252,8 +252,8 @@ std::string defineDetectorPolarizationAnalysis(const ISimulation* simulation)
                << Py::Fmt::printDouble(analyzer_direction.x()) << ", "
                << Py::Fmt::printDouble(analyzer_direction.y()) << ", "
                << Py::Fmt::printDouble(analyzer_direction.z()) << ")\n";
-        result << indent() << "simulation.detector().setAnalyzerProperties(" << direction_name
-               << ", " << Py::Fmt::printDouble(analyzer_efficiency) << ", "
+        result << indent() << "simulation.detector().setAnalyzer(" << direction_name << ", "
+               << Py::Fmt::printDouble(analyzer_efficiency) << ", "
                << Py::Fmt::printDouble(analyzer_total_transmission) << ")\n";
     }
     return result.str();
diff --git a/Core/Scan/AlphaScan.cpp b/Core/Scan/AlphaScan.cpp
index f10d37c9c07fe80a4540b7ad7606697c76210df2..11d80c1784858d70dea8f4e484131de62d8651ed 100644
--- a/Core/Scan/AlphaScan.cpp
+++ b/Core/Scan/AlphaScan.cpp
@@ -80,7 +80,7 @@ AlphaScan* AlphaScan::clone() const
 
 AlphaScan::~AlphaScan() = default;
 
-std::vector<SpecularElement> AlphaScan::generateElements(const PolarizerPair& polpair) const
+std::vector<SpecularElement> AlphaScan::generateElements(const PolMatrices& polpair) const
 {
     const auto wls = extractValues(applyWlResolution(),
                                    [](const ParameterSample& sample) { return sample.value; });
diff --git a/Core/Scan/AlphaScan.h b/Core/Scan/AlphaScan.h
index 1428119359fb9f1612556b076f68dc8f0c6fa630..f770e90b6ea67104a33bda0ec6d71b8d5e163757 100644
--- a/Core/Scan/AlphaScan.h
+++ b/Core/Scan/AlphaScan.h
@@ -39,7 +39,7 @@ public:
 
 #ifndef SWIG
     //! Generates simulation elements for specular simulations
-    std::vector<SpecularElement> generateElements(const PolarizerPair& polpair) const override;
+    std::vector<SpecularElement> generateElements(const PolMatrices& polpair) const override;
 
     //! Returns coordinate axis assigned to the data holder
     virtual const IAxis* coordinateAxis() const override { return m_inc_angle.get(); }
diff --git a/Core/Scan/ISpecularScan.h b/Core/Scan/ISpecularScan.h
index 13c7b1b9ef3788391eefef1cf5eb5d07d7ed756a..90605d90ffc5a61bc9f9cb277fee10123a0201e5 100644
--- a/Core/Scan/ISpecularScan.h
+++ b/Core/Scan/ISpecularScan.h
@@ -22,7 +22,7 @@
 class CoordSystem1D;
 class IAxis;
 class IFootprintFactor;
-class PolarizerPair;
+class PolMatrices;
 class SpecularElement;
 
 //! Abstract base class for all types of specular scans.
@@ -33,7 +33,7 @@ public:
 
 #ifndef SWIG
     //! Generates simulation elements for specular simulations
-    virtual std::vector<SpecularElement> generateElements(const PolarizerPair& polpair) const = 0;
+    virtual std::vector<SpecularElement> generateElements(const PolMatrices& polpair) const = 0;
 
     //! Returns coordinate axis assigned to the data holder
     virtual const IAxis* coordinateAxis() const = 0;
diff --git a/Core/Scan/QzScan.cpp b/Core/Scan/QzScan.cpp
index a4df7a61d0b3c9eeba448affc8fe8b8f30869ef0..e2f19b27dbd44b5f490e0c82ffbf8634e4b16f3b 100644
--- a/Core/Scan/QzScan.cpp
+++ b/Core/Scan/QzScan.cpp
@@ -51,7 +51,7 @@ QzScan* QzScan::clone() const
 }
 
 //! Generates simulation elements for specular simulations
-std::vector<SpecularElement> QzScan::generateElements(const PolarizerPair& polpair) const
+std::vector<SpecularElement> QzScan::generateElements(const PolMatrices& polpair) const
 {
     const std::vector<double> qz = generateQzVector();
 
diff --git a/Core/Scan/QzScan.h b/Core/Scan/QzScan.h
index f93566d97f34fe99a72aabac6d7a0087b1f0c173..1ff292e5397e8aef1950856d577b9e21accb3cb0 100644
--- a/Core/Scan/QzScan.h
+++ b/Core/Scan/QzScan.h
@@ -43,7 +43,7 @@ public:
 
 #ifndef SWIG
     //! Generates simulation elements for specular simulations
-    std::vector<SpecularElement> generateElements(const PolarizerPair& polpair) const override;
+    std::vector<SpecularElement> generateElements(const PolMatrices& polpair) const override;
 
     //! Returns coordinate axis assigned to the data holder
     virtual const IAxis* coordinateAxis() const override { return m_qs.get(); }
diff --git a/Core/Simulation/ISimulation.cpp b/Core/Simulation/ISimulation.cpp
index de93f9514daa25d8fc4a5c6e6ba09f5adfd33493..fcf061fef17ff9d0ef5fc49980eaef9cec859e73 100644
--- a/Core/Simulation/ISimulation.cpp
+++ b/Core/Simulation/ISimulation.cpp
@@ -13,17 +13,18 @@
 //  ************************************************************************************************
 
 #include "Core/Simulation/ISimulation.h"
-#include "Base/Element/PolarizerPair.h"
+#include "Base/Progress/ProgressHandler.h"
 #include "Base/Utils/Assert.h"
 #include "Base/Utils/StringUtils.h"
 #include "Core/Background/IBackground.h"
 #include "Core/Computation/IComputation.h"
 #include "Core/Simulation/MPISimulation.h"
 #include "Device/Beam/Beam.h"
+#include "Device/Detector/IDetector.h"
 #include "Resample/Options/SimulationOptions.h"
 #include "Resample/Processed/ProcessedSample.h"
 #include "Sample/Multilayer/MultilayerUtils.h"
-#include "Sample/SampleBuilderEngine/ISampleBuilder.h"
+#include "Sample/SampleBuilderEngine/SampleProvider.h"
 #include <gsl/gsl_errno.h>
 #include <iostream>
 #include <thread>
@@ -108,6 +109,8 @@ void runComputations(std::vector<std::unique_ptr<IComputation>>& computations)
 
 ISimulation::ISimulation(const Beam& beam, const MultiLayer& sample, const IDetector& detector)
     : m_options(std::make_unique<SimulationOptions>())
+    , m_progress(std::make_unique<ProgressHandler>())
+    , m_sample_provider(std::make_unique<SampleProvider>())
     , m_instrument(beam, detector)
 {
     setSample(sample);
@@ -117,6 +120,8 @@ ISimulation::ISimulation(const Beam& beam, const MultiLayer& sample, const IDete
 #ifndef SWIG
 ISimulation::ISimulation(const Beam& beam, const IDetector& detector)
     : m_options(std::make_unique<SimulationOptions>())
+    , m_progress(std::make_unique<ProgressHandler>())
+    , m_sample_provider(std::make_unique<SampleProvider>())
     , m_instrument(beam, detector)
 {
     initialize();
@@ -125,6 +130,8 @@ ISimulation::ISimulation(const Beam& beam, const IDetector& detector)
 
 ISimulation::ISimulation()
     : m_options(std::make_unique<SimulationOptions>())
+    , m_progress(std::make_unique<ProgressHandler>())
+    , m_sample_provider(std::make_unique<SampleProvider>())
 {
     initialize();
 }
@@ -134,26 +141,43 @@ ISimulation::~ISimulation() = default;
 void ISimulation::initialize()
 {
     registerChild(&m_instrument);
-    registerChild(&m_sample_provider);
+    registerChild(m_sample_provider.get());
 }
 
-void ISimulation::setOptions(const SimulationOptions& options) {
+void ISimulation::setOptions(const SimulationOptions& options)
+{
     ASSERT(m_options);
     *m_options = options;
 }
 
-const SimulationOptions& ISimulation::options() const {
+const SimulationOptions& ISimulation::options() const
+{
     ASSERT(m_options);
-    return *m_options; }
+    return *m_options;
+}
 
-SimulationOptions& ISimulation::options() {
+SimulationOptions& ISimulation::options()
+{
     ASSERT(m_options);
-    return *m_options; }
+    return *m_options;
+}
+
+ProgressHandler& ISimulation::progress()
+{
+    ASSERT(m_progress);
+    return *m_progress;
+}
+
+void ISimulation::subscribe(const std::function<bool(size_t)>& inform)
+{
+    ASSERT(m_progress);
+    m_progress->subscribe(inform);
+}
 
 //! Initializes a progress monitor that prints to stdout.
 void ISimulation::setTerminalProgressMonitor()
 {
-    m_progress.subscribe([](size_t percentage_done) -> bool {
+    m_progress->subscribe([](size_t percentage_done) -> bool {
         if (percentage_done < 100)
             std::cout << std::setprecision(2) << "\r... " << percentage_done << "%" << std::flush;
         else // wipe out
@@ -164,8 +188,8 @@ void ISimulation::setTerminalProgressMonitor()
 
 void ISimulation::prepareSimulation()
 {
-    m_sample_provider.updateSample();
-    if (!SampleUtils::Multilayer::ContainsCompatibleMaterials(*m_sample_provider.sample()))
+    m_sample_provider->updateSample();
+    if (!SampleUtils::Multilayer::ContainsCompatibleMaterials(*m_sample_provider->sample()))
         throw std::runtime_error(
             "Error in ISimulation::prepareSimulation(): non-default materials of"
             " several different types are used in the sample provided");
@@ -177,16 +201,15 @@ void ISimulation::runSimulation()
 {
     prepareSimulation();
 
-    const bool force_polarized =
-        detector().detectionProperties().analyzerDirection() != kvector_t{};
+    const bool force_polarized = detector().analyzer().polDirection() != kvector_t{};
 
     const auto re_sample = ProcessedSample::make(*sample(), options(), force_polarized);
 
     const size_t total_size = numberOfElements();
     size_t param_combinations = m_distribution_handler.getTotalNumberOfSamples();
 
-    m_progress.reset();
-    m_progress.setExpectedNTicks(param_combinations * total_size);
+    m_progress->reset();
+    m_progress->setExpectedNTicks(param_combinations * total_size);
 
     // restrict calculation to current batch
     const size_t n_batches = m_options->getNumberOfBatches();
@@ -241,23 +264,17 @@ void ISimulation::runMPISimulation()
 //! The MultiLayer object will not be owned by the ISimulation object
 void ISimulation::setSample(const MultiLayer& sample)
 {
-    m_sample_provider.setSample(sample);
+    m_sample_provider->setSample(sample);
 }
 
 const MultiLayer* ISimulation::sample() const
 {
-    return m_sample_provider.sample();
+    return m_sample_provider->sample();
 }
 
 void ISimulation::setSampleBuilder(const std::shared_ptr<class ISampleBuilder>& sample_builder)
 {
-    m_sample_provider.setBuilder(sample_builder);
-}
-
-PolarizerPair ISimulation::polarizerPair() const
-{
-    return {m_instrument.beam().getPolarization(),
-        m_instrument.detector().detectionProperties().analyzerOperator()};
+    m_sample_provider->setBuilder(sample_builder);
 }
 
 void ISimulation::setBackground(const IBackground& bg)
@@ -270,7 +287,7 @@ std::vector<const INode*> ISimulation::getChildren() const
 {
     std::vector<const INode*> result;
     result.push_back(&instrument());
-    result << m_sample_provider.getChildren();
+    result << m_sample_provider->getChildren();
     if (m_background)
         result.push_back(m_background.get());
     return result;
diff --git a/Core/Simulation/ISimulation.h b/Core/Simulation/ISimulation.h
index 519d097062afed972e8fe29bc93c1d97526d188c..cd56af065a601d5c427fc9acae6b4f7572f0e79f 100644
--- a/Core/Simulation/ISimulation.h
+++ b/Core/Simulation/ISimulation.h
@@ -16,11 +16,8 @@
 #ifndef BORNAGAIN_CORE_SIMULATION_ISIMULATION_H
 #define BORNAGAIN_CORE_SIMULATION_ISIMULATION_H
 
-#include "Base/Progress/ProgressHandler.h"
-#include "Device/Detector/IDetector2D.h"
 #include "Device/Instrument/Instrument.h"
 #include "Param/Distrib/DistributionHandler.h"
-#include "Sample/SampleBuilderEngine/SampleProvider.h"
 
 template <class T> class OutputData;
 class IBackground;
@@ -28,8 +25,9 @@ class IComputation;
 class ICoordSystem;
 class ISampleBuilder;
 class MultiLayer;
-class PolarizerPair;
 class ProcessedSample;
+class ProgressHandler;
+class SampleProvider;
 class SimulationOptions;
 class SimulationResult;
 
@@ -64,8 +62,6 @@ public:
 
     void setSampleBuilder(const std::shared_ptr<ISampleBuilder>& sample_builder);
 
-    PolarizerPair polarizerPair() const;
-
     void setBackground(const IBackground& bg);
     const IBackground* background() const { return m_background.get(); }
 
@@ -87,7 +83,7 @@ public:
     const SimulationOptions& options() const;
     SimulationOptions& options();
 
-    void subscribe(ProgressHandler::Callback_t inform) { m_progress.subscribe(inform); }
+    void subscribe(const std::function<bool(size_t)>& inform);
     void setTerminalProgressMonitor();
 
     std::vector<const INode*> getChildren() const;
@@ -117,7 +113,7 @@ protected:
     //! Gets the number of elements this simulation needs to calculate
     virtual size_t numberOfElements() const = 0;
 
-    ProgressHandler& progress() { return m_progress; }
+    ProgressHandler& progress();
 
 private:
     void initialize();
@@ -151,8 +147,8 @@ private:
     virtual void setRawResults(const std::vector<double>& raw_data) = 0;
 
     std::unique_ptr<SimulationOptions> m_options;
-    ProgressHandler m_progress;
-    SampleProvider m_sample_provider;
+    std::unique_ptr<ProgressHandler> m_progress;
+    std::unique_ptr<SampleProvider> m_sample_provider;
     DistributionHandler m_distribution_handler;
     Instrument m_instrument;
     std::unique_ptr<IBackground> m_background;
diff --git a/Core/Simulation/ISimulation2D.cpp b/Core/Simulation/ISimulation2D.cpp
index 0456a0bb6eb2ef170cddfd35fe10841144da3aea..d6cb02d7848e4e71fb74d1029ff2ebfec29ba55e 100644
--- a/Core/Simulation/ISimulation2D.cpp
+++ b/Core/Simulation/ISimulation2D.cpp
@@ -110,7 +110,7 @@ std::vector<std::unique_ptr<DiffuseElement>> ISimulation2D::generateElements(con
     const Eigen::Matrix2cd beam_polpair = beam.getPolarization();
 
     const IDetector2D& detector = detector2D();
-    const Eigen::Matrix2cd analyzer_operator = detector.detectionProperties().analyzerOperator();
+    const Eigen::Matrix2cd analyzer_operator = detector.analyzer().matrix();
     const size_t spec_index = detector.indexOfSpecular(beam);
 
     const size_t N = m_detector_context->numberOfElements();
diff --git a/Core/Simulation/SpecularSimulation.cpp b/Core/Simulation/SpecularSimulation.cpp
index 77de63ca0ae66a97e4a370b7da6b9262827fedbe..a2ec7121b66c6ac593231834c86acd1f5b40e8e7 100644
--- a/Core/Simulation/SpecularSimulation.cpp
+++ b/Core/Simulation/SpecularSimulation.cpp
@@ -137,9 +137,9 @@ void SpecularSimulation::initElementVector()
 
     // TODO: remove if statement when pointwise resolution is implemented
     if (const auto* aScan = dynamic_cast<const AlphaScan*>(m_scan.get()))
-        m_eles = mangledScan(*aScan, beam())->generateElements(polarizerPair());
+        m_eles = mangledScan(*aScan, beam())->generateElements(instrument().polarizerPair());
     else
-        m_eles = m_scan->generateElements(polarizerPair());
+        m_eles = m_scan->generateElements(instrument().polarizerPair());
 
     if (!m_cache.empty())
         return;
diff --git a/Device/Detector/DetectorContext.cpp b/Device/Detector/DetectorContext.cpp
index 6786c71cf37549d92a7a62d24bd97418eb163c02..579b4c1009f525cd6a94d00aee97fb52fe1e230d 100644
--- a/Device/Detector/DetectorContext.cpp
+++ b/Device/Detector/DetectorContext.cpp
@@ -42,7 +42,7 @@ size_t DetectorContext::detectorIndex(size_t element_index) const
 void DetectorContext::setup_context(const IDetector2D* detector)
 {
     m_active_indices = detector->active_indices();
-    m_analyzer_operator = detector->detectionProperties().analyzerOperator();
+    m_analyzer_operator = detector->analyzer().matrix();
     m_pixels.reserve(m_active_indices.size());
     for (auto detector_index : m_active_indices)
         m_pixels.emplace_back(detector->createPixel(detector_index));
diff --git a/Device/Detector/IDetector.cpp b/Device/Detector/IDetector.cpp
index b0f769efd4fc9d718b209cc63cb033768b24b65a..c5f7b2b3f711d70f71d49ef1790b7b15fb84c8b5 100644
--- a/Device/Detector/IDetector.cpp
+++ b/Device/Detector/IDetector.cpp
@@ -14,7 +14,7 @@
 
 #include "Device/Detector/IDetector.h"
 #include "Base/Utils/Assert.h"
-#include "Device/ProDetector/DetectorMask.h"
+#include "Device/Mask/DetectorMask.h"
 #include "Device/Resolution/ConvolutionDetectorResolution.h"
 #include "Resample/Element/DiffuseElement.h"
 
@@ -154,10 +154,9 @@ size_t IDetector::detectorIndexToRegionOfInterestIndex(const size_t detectorInde
                              "implemented by derived class.");
 }
 
-void IDetector::setAnalyzerProperties(const kvector_t direction, double efficiency,
-                                      double total_transmission)
+void IDetector::setAnalyzer(const kvector_t direction, double efficiency, double total_transmission)
 {
-    m_detection_properties.setAnalyzerProperties(direction, efficiency, total_transmission);
+    m_detection_properties.setDirEffTra(direction, efficiency, total_transmission);
 }
 
 void IDetector::setDetectorResolution(const IDetectorResolution& p_detector_resolution)
diff --git a/Device/Detector/IDetector.h b/Device/Detector/IDetector.h
index f49e14485e63a4051dab545fe3283fc7cea89a4f..f89638848f47bf35eb2bc543de6037674303c93a 100644
--- a/Device/Detector/IDetector.h
+++ b/Device/Detector/IDetector.h
@@ -21,7 +21,7 @@
 #include "Base/Vector/Vectors3D.h"
 #include "Device/Coord/Axes.h"
 #include "Device/Detector/SimulationAreaIterator.h"
-#include "Device/ProDetector/DetectionProperties.h"
+#include "Device/Pol/PolFilter.h"
 
 class DetectorMask;
 class Direction;
@@ -63,8 +63,7 @@ public:
     void addAxis(const IAxis& axis);
 
     //! Sets the polarization analyzer characteristics of the detector
-    void setAnalyzerProperties(const kvector_t direction, double efficiency,
-                               double total_transmission);
+    void setAnalyzer(const kvector_t direction, double efficiency, double total_transmission);
     //! Sets the detector resolution
     void setDetectorResolution(const IDetectorResolution& p_detector_resolution);
     void setResolutionFunction(const IResolutionFunction2D& resFunc);
@@ -157,7 +156,7 @@ public:
 #endif // USER_API
 
     //! Returns detection properties
-    const DetectionProperties& detectionProperties() const { return m_detection_properties; }
+    const PolFilter& analyzer() const { return m_detection_properties; }
 
     //! Returns new intensity map with resolution applied, and cropped to ROI if applicable.
     OutputData<double>*
@@ -222,7 +221,7 @@ private:
                               const std::vector<std::unique_ptr<DiffuseElement>>& elements) const;
 
     CloneableVector<IAxis> m_axes;
-    DetectionProperties m_detection_properties;
+    PolFilter m_detection_properties;
     std::unique_ptr<IDetectorResolution> m_detector_resolution;
 };
 
diff --git a/Device/Detector/IDetector2D.cpp b/Device/Detector/IDetector2D.cpp
index 10a044ad516e661ff7d4ddb0e01a504836966793..b6fcbb5db01d71743fd9abd5eff676f652db3599 100644
--- a/Device/Detector/IDetector2D.cpp
+++ b/Device/Detector/IDetector2D.cpp
@@ -16,8 +16,8 @@
 #include "Base/Const/Units.h"
 #include "Device/Beam/Beam.h"
 #include "Device/Detector/DetectorContext.h"
+#include "Device/Mask/DetectorMask.h"
 #include "Device/Mask/InfinitePlane.h"
-#include "Device/ProDetector/DetectorMask.h"
 #include "Resample/Element/DiffuseElement.h"
 
 namespace {
diff --git a/Device/Detector/SimulationAreaIterator.cpp b/Device/Detector/SimulationAreaIterator.cpp
index 49d5b3e8d1421bb41eec2b6acd96da39fc7c7cbd..e5ab4ef1962194b7996e68b8f9ee95ca5a2f61f1 100644
--- a/Device/Detector/SimulationAreaIterator.cpp
+++ b/Device/Detector/SimulationAreaIterator.cpp
@@ -13,7 +13,7 @@
 //  ************************************************************************************************
 
 #include "Device/Detector/IDetector2D.h"
-#include "Device/ProDetector/DetectorMask.h"
+#include "Device/Mask/DetectorMask.h"
 
 SimulationAreaIterator::SimulationAreaIterator(const IDetector* detector, Mode mode,
                                                size_t start_at_index)
diff --git a/Device/Instrument/Instrument.cpp b/Device/Instrument/Instrument.cpp
index 541d4031d2e571707b4cd3137a22c13ab8a40fc8..0f8af32abdb64385fe77929284d08d57cf9c4454 100644
--- a/Device/Instrument/Instrument.cpp
+++ b/Device/Instrument/Instrument.cpp
@@ -13,6 +13,7 @@
 //  ************************************************************************************************
 
 #include "Device/Instrument/Instrument.h"
+#include "Base/Element/PolMatrices.h"
 #include "Base/Pixel/RectangularPixel.h"
 #include "Device/Beam/Beam.h"
 #include "Device/Coord/CoordSystem2D.h"
@@ -113,6 +114,18 @@ IDetector& Instrument::detector()
     return *m_detector;
 }
 
+PolMatrices Instrument::polarizerPair() const
+{
+    return {m_beam->getPolarization(), m_detector->analyzer().matrix()};
+}
+
+void Instrument::setPolFilters(const kvector_t& polarizer_dir, const kvector_t& analyzer_dir,
+                               double analyzer_efficiency, double analyzer_transmission)
+{
+    m_beam->setPolarization(polarizer_dir);
+    m_detector->setAnalyzer(analyzer_dir, analyzer_efficiency, analyzer_transmission);
+}
+
 CoordSystem2D* Instrument::createScatteringCoords() const
 {
     const IDetector* const detector = getDetector();
diff --git a/Device/Instrument/Instrument.h b/Device/Instrument/Instrument.h
index c5dd09a1196200730dd0e34c7b12250496a1ada1..22c0de9986aee3888e3924b27e5816e215dca879 100644
--- a/Device/Instrument/Instrument.h
+++ b/Device/Instrument/Instrument.h
@@ -12,20 +12,18 @@
 //
 //  ************************************************************************************************
 
-#ifdef SWIG
-#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
 
+#include "Base/Vector/Vectors3D.h"
 #include "Param/Node/INode.h"
 #include <memory>
 
 class Beam;
 class CoordSystem2D;
 class IDetector;
+class PolMatrices;
 
 //! Assembles beam, detector and their relative positions with respect to the sample.
 
@@ -58,6 +56,10 @@ public:
     //! init detector with beam settings
     void initDetector();
 
+    void setPolFilters(const kvector_t& polarizer_dir, const kvector_t& analyzer_dir,
+                       double analyzer_efficiency, double analyzer_transmission);
+    PolMatrices polarizerPair() const;
+
     std::vector<const INode*> getChildren() const override;
 
     CoordSystem2D* createScatteringCoords() const;
diff --git a/Device/ProDetector/DetectorMask.cpp b/Device/Mask/DetectorMask.cpp
similarity index 97%
rename from Device/ProDetector/DetectorMask.cpp
rename to Device/Mask/DetectorMask.cpp
index 71d4bbacb71c677857015047c22b1e7e3684f2da..c5b8c577b4009b9fda769e80590734ba0948e748 100644
--- a/Device/ProDetector/DetectorMask.cpp
+++ b/Device/Mask/DetectorMask.cpp
@@ -2,7 +2,7 @@
 //
 //  BornAgain: simulate and fit reflection and scattering
 //
-//! @file      Device/ProDetector/DetectorMask.cpp
+//! @file      Device/Mask/DetectorMask.cpp
 //! @brief     Implements class DetectorMask.
 //!
 //! @homepage  http://www.bornagainproject.org
@@ -12,7 +12,7 @@
 //
 //  ************************************************************************************************
 
-#include "Device/ProDetector/DetectorMask.h"
+#include "Device/Mask/DetectorMask.h"
 #include "Base/Axis/IAxis.h"
 #include "Device/Histo/Histogram2D.h"
 
diff --git a/Device/ProDetector/DetectorMask.h b/Device/Mask/DetectorMask.h
similarity index 90%
rename from Device/ProDetector/DetectorMask.h
rename to Device/Mask/DetectorMask.h
index 5c01199eec4deb788892e0aa6b8eeec33b2abe8b..e0c1b79cb4bbcf5e3775b09b484a22deafe22bc2 100644
--- a/Device/ProDetector/DetectorMask.h
+++ b/Device/Mask/DetectorMask.h
@@ -2,7 +2,7 @@
 //
 //  BornAgain: simulate and fit reflection and scattering
 //
-//! @file      Device/ProDetector/DetectorMask.h
+//! @file      Device/Mask/DetectorMask.h
 //! @brief     Defines class DetectorMask.
 //!
 //! @homepage  http://www.bornagainproject.org
@@ -12,8 +12,8 @@
 //
 //  ************************************************************************************************
 
-#ifndef BORNAGAIN_DEVICE_PRODETECTOR_DETECTORMASK_H
-#define BORNAGAIN_DEVICE_PRODETECTOR_DETECTORMASK_H
+#ifndef BORNAGAIN_DEVICE_MASK_DETECTORMASK_H
+#define BORNAGAIN_DEVICE_MASK_DETECTORMASK_H
 
 #include "Base/Types/CloneableVector.h"
 #include "Device/Data/OutputData.h"
@@ -65,4 +65,4 @@ private:
     int m_number_of_masked_channels;
 };
 
-#endif // BORNAGAIN_DEVICE_PRODETECTOR_DETECTORMASK_H
+#endif // BORNAGAIN_DEVICE_MASK_DETECTORMASK_H
diff --git a/Device/ProDetector/DetectionProperties.cpp b/Device/Pol/PolFilter.cpp
similarity index 64%
rename from Device/ProDetector/DetectionProperties.cpp
rename to Device/Pol/PolFilter.cpp
index e250f98681eb0ef13d025c086ec4370cf55d169b..98b0a6885d95ea5f2d58ddc1eca9c18d438ecc45 100644
--- a/Device/ProDetector/DetectionProperties.cpp
+++ b/Device/Pol/PolFilter.cpp
@@ -2,7 +2,7 @@
 //
 //  BornAgain: simulate and fit reflection and scattering
 //
-//! @file      Device/ProDetector/DetectionProperties.cpp
+//! @file      Device/Pol/PolFilter.cpp
 //! @brief     Implements class DetectionProperties.
 //!
 //! @homepage  http://www.bornagainproject.org
@@ -12,11 +12,10 @@
 //
 //  ************************************************************************************************
 
-#include "Device/ProDetector/DetectionProperties.h"
+#include "Device/Pol/PolFilter.h"
 #include "Fit/Param/RealLimits.h"
 
-DetectionProperties::DetectionProperties(kvector_t direction, double efficiency,
-                                         double total_transmission)
+PolFilter::PolFilter(kvector_t direction, double efficiency, double total_transmission)
     : m_direction(direction), m_efficiency(efficiency), m_total_transmission(total_transmission)
 {
     setName("Analyzer");
@@ -24,18 +23,18 @@ DetectionProperties::DetectionProperties(kvector_t direction, double efficiency,
     checkLimits("Transmission", m_total_transmission, RealLimits::nonnegative());
 }
 
-DetectionProperties::DetectionProperties() : DetectionProperties({}, {}, 1.0) {}
+PolFilter::PolFilter() : PolFilter({}, {}, 1.0) {}
 
-DetectionProperties::DetectionProperties(const DetectionProperties& other)
-    : DetectionProperties(other.m_direction, other.m_efficiency, other.m_total_transmission)
+PolFilter::PolFilter(const PolFilter& other)
+    : PolFilter(other.m_direction, other.m_efficiency, other.m_total_transmission)
 {
 }
 
-void DetectionProperties::setAnalyzerProperties(const kvector_t direction, double efficiency,
-                                                double total_transmission)
+void PolFilter::setDirEffTra(const kvector_t direction, double efficiency,
+                             double total_transmission)
 {
-    if (!checkAnalyzerProperties(direction, efficiency, total_transmission))
-        throw std::runtime_error("IDetector2D::setAnalyzerProperties: the "
+    if (!check(direction, efficiency, total_transmission))
+        throw std::runtime_error("IDetector2D::setAnalyzer: the "
                                  "given properties are not physical");
     if (efficiency == 0.0 || total_transmission == 0.0 || direction.mag() == 0.0) {
         m_direction = kvector_t{};
@@ -47,7 +46,7 @@ void DetectionProperties::setAnalyzerProperties(const kvector_t direction, doubl
     m_total_transmission = total_transmission;
 }
 
-Eigen::Matrix2cd DetectionProperties::analyzerOperator() const
+Eigen::Matrix2cd PolFilter::matrix() const
 {
     if (m_direction.mag() == 0.0 || m_efficiency == 0.0)
         return m_total_transmission * Eigen::Matrix2cd::Identity();
@@ -65,23 +64,22 @@ Eigen::Matrix2cd DetectionProperties::analyzerOperator() const
     return result;
 }
 
-kvector_t DetectionProperties::analyzerDirection() const
+kvector_t PolFilter::polDirection() const
 {
     return m_direction;
 }
 
-double DetectionProperties::analyzerEfficiency() const
+double PolFilter::polEfficiency() const
 {
     return m_efficiency;
 }
 
-double DetectionProperties::analyzerTotalTransmission() const
+double PolFilter::totalTransmission() const
 {
     return m_total_transmission;
 }
 
-bool DetectionProperties::checkAnalyzerProperties(const kvector_t direction, double efficiency,
-                                                  double total_transmission) const
+bool PolFilter::check(const kvector_t direction, double efficiency, double total_transmission) const
 {
     if (direction.mag() == 0.0)
         return false;
diff --git a/Device/ProDetector/DetectionProperties.h b/Device/Pol/PolFilter.h
similarity index 58%
rename from Device/ProDetector/DetectionProperties.h
rename to Device/Pol/PolFilter.h
index ebfd2a1be435f0bb2a0388043dbfdb76b66b7d2b..0476b651430bdd909a0873bf4a9c7ad6db3483ea 100644
--- a/Device/ProDetector/DetectionProperties.h
+++ b/Device/Pol/PolFilter.h
@@ -2,7 +2,7 @@
 //
 //  BornAgain: simulate and fit reflection and scattering
 //
-//! @file      Device/ProDetector/DetectionProperties.h
+//! @file      Device/Pol/PolFilter.h
 //! @brief     Defines class DetectionProperties.
 //!
 //! @homepage  http://www.bornagainproject.org
@@ -17,47 +17,45 @@
 #endif
 
 #ifndef USER_API
-#ifndef BORNAGAIN_DEVICE_PRODETECTOR_DETECTIONPROPERTIES_H
-#define BORNAGAIN_DEVICE_PRODETECTOR_DETECTIONPROPERTIES_H
+#ifndef BORNAGAIN_DEVICE_POL_POLFILTER_H
+#define BORNAGAIN_DEVICE_POL_POLFILTER_H
 
-#include "Param/Node/INode.h"
 #include "Base/Vector/EigenCore.h"
 #include "Base/Vector/Vectors3D.h"
+#include "Param/Node/INode.h"
 
 //! Detector properties (efficiency, transmission).
 //! @ingroup detector
 
-class DetectionProperties : public INode {
+class PolFilter : public INode {
 public:
-    DetectionProperties(kvector_t direction, double efficiency, double total_transmission);
-    DetectionProperties();
-    DetectionProperties(const DetectionProperties& other);
+    PolFilter(kvector_t direction, double efficiency, double total_transmission);
+    PolFilter();
+    PolFilter(const PolFilter& other);
 
-    virtual ~DetectionProperties() = default;
+    virtual ~PolFilter() = default;
 
     //! Sets the polarization analyzer characteristics of the detector
-    void setAnalyzerProperties(const kvector_t direction, double efficiency,
-                               double total_transmission);
+    void setDirEffTra(const kvector_t direction, double efficiency, double total_transmission);
 
     //! Return the polarization density matrix (in spin basis along z-axis)
-    Eigen::Matrix2cd analyzerOperator() const;
+    Eigen::Matrix2cd matrix() const;
 
     //! Retrieve the analyzer characteristics
-    kvector_t analyzerDirection() const;
-    double analyzerEfficiency() const; //!< will always return positive value
-    double analyzerTotalTransmission() const;
+    kvector_t polDirection() const;
+    double polEfficiency() const; //!< will always return positive value
+    double totalTransmission() const;
 
     void accept(INodeVisitor* visitor) const override { visitor->visit(this); }
 
 private:
     //! Verify if the given analyzer properties are physical
-    bool checkAnalyzerProperties(const kvector_t direction, double efficiency,
-                                 double total_transmission) const;
+    bool check(const kvector_t direction, double efficiency, double total_transmission) const;
 
     kvector_t m_direction;       //!< direction of polarization analysis
     double m_efficiency;         //!< efficiency of polarization analysis
     double m_total_transmission; //!< total transmission of polarization analysis
 };
 
-#endif // BORNAGAIN_DEVICE_PRODETECTOR_DETECTIONPROPERTIES_H
+#endif // BORNAGAIN_DEVICE_POL_POLFILTER_H
 #endif // USER_API
diff --git a/Examples/anaklasis/calculate_bimodal_brush.py b/Examples/anaklasis/calculate_bimodal_brush.py
index bc04fd53768c5b790062897e16b87f3e6ee0fbf8..673493979e8976cab4e12534e94cd9fbfc2ae6d6 100644
--- a/Examples/anaklasis/calculate_bimodal_brush.py
+++ b/Examples/anaklasis/calculate_bimodal_brush.py
@@ -18,13 +18,13 @@ system.append([
 
 # We define the expression for the solvent volume fraction within the brush layer
 e = ("1-Max(p1-(p1/(p2**p5))*((p4/50.0)*(n-1.5))**p5,0)-p3+"
-    "(p3/(p4**p6))*((p4/50.0)*(n-1.5))**p6")
+     "(p3/(p4**p6))*((p4/50.0)*(n-1.5))**p6")
 
 # we insert 50 "brush" slabs after the SiO2 layer.
 # Re_sld Im-sld  thk       rough      solv  description
 for i in range(50):
-    system[0].insert(
-        2, ['p7', 0.0, 'p4/50.0', 'p4/100.0', e, 'brush_layer'])
+    system[0].insert(2,
+                     ['p7', 0.0, 'p4/50.0', 'p4/100.0', e, 'brush_layer'])
 
 global_param = [
     # name value  description
diff --git a/Examples/fit/algo/fit_rosenbrock.py b/Examples/fit/algo/fit_rosenbrock.py
index a0889c6e601d51fbb9eca274dd62fd0a2866bbff..dfbeffca0fe6b0b0a04e090097f5e90d0cee3b6d 100755
--- a/Examples/fit/algo/fit_rosenbrock.py
+++ b/Examples/fit/algo/fit_rosenbrock.py
@@ -2,12 +2,14 @@
 
 import bornagain as ba
 
+
 def rosenbrock(params):
     x = params["x"].value
     y = params["y"].value
-    tmp1 = y - x * x
+    tmp1 = y - x*x
     tmp2 = 1 - x
-    return 100 * tmp1 * tmp1 + tmp2 * tmp2
+    return 100*tmp1*tmp1 + tmp2*tmp2
+
 
 params = ba.Parameters()
 params.add("x", value=-1.2, min=-5.0, max=5.0, step=0.01)
diff --git a/Examples/fit/gisas2d/fit_gisas.py b/Examples/fit/gisas2d/fit_gisas.py
index abd933db1e17ffbccbd38552499c07d6a625558e..ac89b47cc24aadc7b474a4abf16fe539f9710cd4 100755
--- a/Examples/fit/gisas2d/fit_gisas.py
+++ b/Examples/fit/gisas2d/fit_gisas.py
@@ -15,7 +15,8 @@ from matplotlib import pyplot as plt
 
 def run_fitting():
     datadir = os.getenv('BORNAGAIN_EXAMPLE_DATA_DIR', '')
-    real_data = np.loadtxt(os.path.join(datadir, "faked-gisas1.txt.gz"), dtype=float)
+    real_data = np.loadtxt(os.path.join(datadir, "faked-gisas1.txt.gz"),
+                           dtype=float)
 
     fit_objective = ba.FitObjective()
     fit_objective.addSimulationAndData(model.get_simulation, real_data)
diff --git a/Examples/fit/gisas2d/gisas_model1.py b/Examples/fit/gisas2d/gisas_model1.py
index 5d10c35719a7fc22c30e40f5f394ee1fd5fe0548..d5ec769641ec1547491791e85acb0e4645b8df6e 100644
--- a/Examples/fit/gisas2d/gisas_model1.py
+++ b/Examples/fit/gisas2d/gisas_model1.py
@@ -42,6 +42,7 @@ def get_simulation(params):
 
     return simulation
 
+
 def start_parameters_1():
     params = ba.Parameters()
     params.add("lg(intensity)", 5)
diff --git a/Examples/fit52_Advanced/multiple_datasets.py b/Examples/fit52_Advanced/multiple_datasets.py
index 9eb9272e1dc242ac665735bdff5e8cdb161a788f..eb83e74b63fdd34470f6901eb6e56a75b4c2e31f 100755
--- a/Examples/fit52_Advanced/multiple_datasets.py
+++ b/Examples/fit52_Advanced/multiple_datasets.py
@@ -10,6 +10,7 @@ import bornagain as ba
 from bornagain import deg, nm
 import bornagain.ba_plot as bp
 
+
 def get_sample(params):
     """
     Returns a sample with uncorrelated cylinders and pyramids.
diff --git a/Examples/fit55_SpecularIntro/PolarizedSpinAsymmetryFit.py b/Examples/fit55_SpecularIntro/PolarizedSpinAsymmetryFit.py
index 905e58b55eb9a2bac1bd28e7557336473d22e9c6..937f1a5d33a86d8f891ac8e496fe7823381f89a5 100755
--- a/Examples/fit55_SpecularIntro/PolarizedSpinAsymmetryFit.py
+++ b/Examples/fit55_SpecularIntro/PolarizedSpinAsymmetryFit.py
@@ -64,7 +64,7 @@ def get_sample(params):
     return multi_layer
 
 
-def get_simulation(q_axis, parameters, polarization, analyzer):
+def get_simulation(q_axis, parameters, polarizer_dir, analyzer_dir):
     """
     Returns a simulation object.
     Polarization, analyzer and resolution are set
@@ -81,14 +81,14 @@ def get_simulation(q_axis, parameters, polarization, analyzer):
     distr = ba.RangedDistributionGaussian(n_samples, n_sig)
     scan.setAbsoluteQResolution(distr, parameters["q_res"])
 
-    simulation.beam().setPolarization(polarization)
-    simulation.detector().setAnalyzerProperties(analyzer, 1, 0.5)
+    simulation.instrument().setPolFilters(polarizer_dir, analyzer_dir, 1,
+                                          0.5)
 
     simulation.setScan(scan)
     return simulation
 
 
-def run_simulation(q_axis, fitParams, *, polarization, analyzer):
+def run_simulation(q_axis, fitParams, *, polarizer_dir, analyzer_dir):
     """
     Run a simulation on the given q-axis, where the sample is constructed
     with the given parameters.
@@ -97,7 +97,8 @@ def run_simulation(q_axis, fitParams, *, polarization, analyzer):
     parameters = dict(fitParams, **fixedParams)
 
     sample = get_sample(parameters)
-    simulation = get_simulation(q_axis, parameters, polarization, analyzer)
+    simulation = get_simulation(q_axis, parameters, polarizer_dir,
+                                analyzer_dir)
 
     simulation.setSample(sample)
     simulation.runSimulation()
@@ -188,6 +189,7 @@ def plotSpinAsymmetry(data_pp, data_mm, q, r_pp, r_mm, filename):
 #                          Data Handling                           #
 ####################################################################
 
+
 def load_exp(fname):
     dat = numpy.loadtxt(fname)
     return numpy.transpose(dat)
@@ -231,6 +233,7 @@ def run_fit_ba(q_axis, r_data, r_uncertainty, simulationFactory,
 
     return {r.name(): r.value for r in result.parameters()}
 
+
 ####################################################################
 #                          Main Function                           #
 ####################################################################
@@ -240,8 +243,8 @@ if __name__ == '__main__':
     datadir = os.getenv('BORNAGAIN_EXAMPLE_DATA_DIR', '')
     fname_stem = os.path.join(datadir, "MAFO_Saturated_")
 
-    expdata_pp = load_exp(fname_stem+"pp.tab")
-    expdata_mm = load_exp(fname_stem+"mm.tab")
+    expdata_pp = load_exp(fname_stem + "pp.tab")
+    expdata_mm = load_exp(fname_stem + "mm.tab")
 
     if len(argv) > 1 and argv[1] == "fit":
         fixedParams = {
diff --git a/Examples/fit55_SpecularIntro/RealLifeReflectometryFitting.py b/Examples/fit55_SpecularIntro/RealLifeReflectometryFitting.py
index 13127e01aac97535f4914bb3aa7bc5740eac1007..f31243d98690bafff96e7ac27cd2323d6d9c000e 100755
--- a/Examples/fit55_SpecularIntro/RealLifeReflectometryFitting.py
+++ b/Examples/fit55_SpecularIntro/RealLifeReflectometryFitting.py
@@ -39,7 +39,6 @@ from bornagain import ba_plot
 from scipy.optimize import differential_evolution
 
 
-
 def get_real_data(filename):
     """
     Loads real data files and merges them once.
@@ -97,8 +96,7 @@ def create_simulation(arg_dict, bin_start, bin_end):
     alpha_distr = ba.RangedDistributionGaussian(30, 3)
     footprint = ba.FootprintGauss(arg_dict["footprint_factor"])
 
-    scan = ba.AlphaScan(wavelength,
-                              get_real_data_axis(bin_start, bin_end))
+    scan = ba.AlphaScan(wavelength, get_real_data_axis(bin_start, bin_end))
     scan.setAbsoluteAngularResolution(alpha_distr, arg_dict["divergence"])
     scan.setFootprintFactor(footprint)
 
@@ -153,7 +151,7 @@ def chi_2(real_data, sim_data, weights):
     Computes chi_2 metrics and returns its value
     """
     sim_data_upsc = np.multiply(weights, sim_data)
-    sim_data_upsc[sim_data_upsc==0] = 1e-30
+    sim_data_upsc[sim_data_upsc == 0] = 1e-30
     real_data_upsc = np.multiply(weights, real_data)
     diff = real_data_upsc - sim_data_upsc
     return np.sum(np.divide(np.multiply(diff, diff), sim_data_upsc))
diff --git a/Examples/fit56_SpecularAdvanced/Honeycomb_fit.py b/Examples/fit56_SpecularAdvanced/Honeycomb_fit.py
index 692e808a152627de100e8cd526bd288d32541b3c..d2befbbdf97b43321fc038cf2605362b41ae459a 100755
--- a/Examples/fit56_SpecularAdvanced/Honeycomb_fit.py
+++ b/Examples/fit56_SpecularAdvanced/Honeycomb_fit.py
@@ -13,7 +13,6 @@ import numpy, os, sys
 import matplotlib.pyplot as plt
 from scipy.optimize import differential_evolution
 
-
 # number of points on which the computed result is plotted
 scan_size = 1500
 
diff --git a/Examples/fit61_Galaxi/fit_galaxi_data.py b/Examples/fit61_Galaxi/fit_galaxi_data.py
index ef24d65c633ee761d73a1c0aced3adf1761c8fcc..707c736cb2137817f45465149d965d0927d394e5 100755
--- a/Examples/fit61_Galaxi/fit_galaxi_data.py
+++ b/Examples/fit61_Galaxi/fit_galaxi_data.py
@@ -21,6 +21,7 @@ beam_xpos, beam_ypos = 597.1, 323.4  # in pixels
 
 datadir = os.getenv('BORNAGAIN_EXAMPLE_DATA_DIR', '')
 
+
 def create_detector():
     """
     Returns a model of the GALAXY detector
@@ -40,8 +41,9 @@ def create_simulation(params):
     Creates and returns GISAS simulation with beam and detector defined
     """
     beam = ba.Beam(1.2e7, wavelength, ba.Direction(alpha_i, 0))
-    simulation = ba.GISASSimulation(
-        beam, SampleBuilder().create_sample(params), create_detector())
+    simulation = ba.GISASSimulation(beam,
+                                    SampleBuilder().create_sample(params),
+                                    create_detector())
 
     simulation.setRegionOfInterest(85, 70, 120, 92.)
     # beamstop:
diff --git a/Examples/scatter2d/BeamDivergence.py b/Examples/scatter2d/BeamDivergence.py
index a0f09254b9a892db628f4f5f5c2c1862d55b8fbc..cd872b4a594bbbff7278de7b39736ccc83ca35bc 100755
--- a/Examples/scatter2d/BeamDivergence.py
+++ b/Examples/scatter2d/BeamDivergence.py
@@ -45,14 +45,14 @@ def get_simulation(sample):
     detector = ba.SphericalDetector(100, 2*deg, 1*deg, 1*deg)
     simulation = ba.GISASSimulation(beam, sample, detector)
     distr_1 = ba.DistributionLogNormal(0.1*nm, 0.1)
-    simulation.addParameterDistribution(ba.ParameterDistribution.BeamWavelength,
-                                        distr_1, 5, 0)
+    simulation.addParameterDistribution(
+        ba.ParameterDistribution.BeamWavelength, distr_1, 5, 0)
     distr_2 = ba.DistributionGaussian(0.2*deg, 0.1*deg)
     simulation.addParameterDistribution(
         ba.ParameterDistribution.BeamInclinationAngle, distr_2, 5, 0)
     distr_3 = ba.DistributionGaussian(0, 0.1*deg)
-    simulation.addParameterDistribution(ba.ParameterDistribution.BeamAzimuthalAngle,
-                                        distr_3, 5, 0)
+    simulation.addParameterDistribution(
+        ba.ParameterDistribution.BeamAzimuthalAngle, distr_3, 5, 0)
     return simulation
 
 
diff --git a/Examples/scatter2d/Interference2DCenteredSquareLattice.py b/Examples/scatter2d/Interference2DCenteredSquareLattice.py
index 6da1f63d585d754616dcd2a0837cec7151d37455..0e1f92cb58daa60a2a5f764952b7bb8299e9faad 100755
--- a/Examples/scatter2d/Interference2DCenteredSquareLattice.py
+++ b/Examples/scatter2d/Interference2DCenteredSquareLattice.py
@@ -6,7 +6,8 @@ import bornagain as ba
 from bornagain import deg, nm, kvector_t
 
 r = 3*nm  # particle radius
-a = 25*nm # lattice constant
+a = 25*nm  # lattice constant
+
 
 def get_sample():
     """
diff --git a/Examples/scatter2d/MagneticSpheres.py b/Examples/scatter2d/MagneticSpheres.py
index f06fd7d58ba5d039632666965082840cd5c96bde..404393d6ddd62a31a19feb7f90e434ecda3695fe 100755
--- a/Examples/scatter2d/MagneticSpheres.py
+++ b/Examples/scatter2d/MagneticSpheres.py
@@ -48,12 +48,14 @@ def get_sample():
 
 def get_simulation(sample):
     beam = ba.Beam(1e12, 0.1*nm, ba.Direction(0.5*deg, 0))
-    beam_polpair = kvector_t(0, 0, 1)
-    beam.setPolarization(beam_polpair)
     detector = ba.SphericalDetector(200, 6*deg, 0, 3*deg)
     simulation = ba.GISASSimulation(beam, sample, detector)
-    analyzer_direction = kvector_t(0, 0, -1)
-    simulation.detector().setAnalyzerProperties(analyzer_direction, 1, 0.5)
+
+    polarizer_dir = kvector_t(0, 0, 1)
+    analyzer_dir = kvector_t(0, 0, -1)
+    simulation.instrument().setPolFilters(polarizer_dir, analyzer_dir, 1,
+                                          0.5)
+
     return simulation
 
 
diff --git a/Examples/scatter2d/PolarizedSANS.py b/Examples/scatter2d/PolarizedSANS.py
index 02d9138ed604b1bbd29c4763c8d3236d6dacc4c2..9b312cbd9065e4e1766c26ebb9cb0246b6c9bd90 100755
--- a/Examples/scatter2d/PolarizedSANS.py
+++ b/Examples/scatter2d/PolarizedSANS.py
@@ -7,6 +7,7 @@ simulated with BornAgain.
 import bornagain as ba
 from bornagain import angstrom, deg, nm, nm2, kvector_t
 
+
 def get_sample():
     """
     Returns a sample with a magnetic core-shell particle in a solvent.
@@ -54,7 +55,6 @@ def get_simulation(sample):
     """
     # Beam from above (perpendicular to sample):
     beam = ba.Beam(1, 0.4*nm, ba.Direction(90*deg, 0))
-    beam.setPolarization(kvector_t(0, 1, 0))
 
     # Detector opposite to source:
     detPos = 2000  # distance from sample center to detector in mm
@@ -62,13 +62,17 @@ def get_simulation(sample):
     detPix = 200  # number of pixels per direction
     det = ba.RectangularDetector(detPix, detWid, detPix, detWid)
     det.setPerpendicularToDirectBeam(detPos, detWid/2, detWid/2)
-    det.setAnalyzerProperties(kvector_t(0, -1, 0), 1, 0.5)
 
-    return ba.GISASSimulation(beam, sample, det)
+    sim = ba.GISASSimulation(beam, sample, det)
+
+    sim.instrument().setPolFilters(kvector_t(0, 1, 0), kvector_t(0, -1, 0),
+                                   1, 0.5)
+
+    return sim
 
 
 if __name__ == '__main__':
     from bornagain import ba_plot
     sample = get_sample()
     simulation = get_simulation(sample)
-    ba_plot.run_and_plot(simulation) # TODO: restore units=ba.Axes.QSPACE)
+    ba_plot.run_and_plot(simulation)  # TODO: restore units=ba.Axes.QSPACE)
diff --git a/Examples/scatter2d/PositionVariance.py b/Examples/scatter2d/PositionVariance.py
index 5ad816efd9b24e935aa4542952512c7cd65fdecb..be0d2925c944ac09f1b22ef477fddaca79e67792 100755
--- a/Examples/scatter2d/PositionVariance.py
+++ b/Examples/scatter2d/PositionVariance.py
@@ -60,19 +60,19 @@ def run_one(hasVariance, xi, nPlot, title):
     plt.subplot(3, 2, nPlot)
 
     return ba_plot.plot_colormap(result,
-                          title=title,
-                          intensity_max=3e7,
-                          intensity_min=3e0,
-                          zlabel=None,
-                          aspect='equal',
-                          with_cb=False)
+                                 title=title,
+                                 intensity_max=3e7,
+                                 intensity_min=3e0,
+                                 zlabel=None,
+                                 aspect='equal',
+                                 with_cb=False)
 
 
 if __name__ == '__main__':
     from bornagain import ba_plot
     fig, axs = plt.subplots(3, 2, figsize=(10, 13))
 
-    xi1 =  5*deg
+    xi1 = 5*deg
     xi2 = 15*deg
     im = run_one(False, 0*deg, 1, "xi=0 deg, fixed positions")
     run_one(True, 0*deg, 2, "position variance 0.3 nm")
diff --git a/Examples/specular/BeamAngularDivergence.py b/Examples/specular/BeamAngularDivergence.py
index 76405d5a1a3868684f90837065b106bb91718180..1614ba5c40c29235a84a3eac8bb5038efb1ad523 100755
--- a/Examples/specular/BeamAngularDivergence.py
+++ b/Examples/specular/BeamAngularDivergence.py
@@ -74,8 +74,7 @@ def get_simulation(sample, scan_size=500):
     footprint = ba.FootprintSquare(beam_sample_ratio)
     alpha_distr = ba.RangedDistributionGaussian(n_points, n_sig)
 
-    scan = ba.AlphaScan(wavelength, scan_size, alpha_i_min,
-                              alpha_i_max)
+    scan = ba.AlphaScan(wavelength, scan_size, alpha_i_min, alpha_i_max)
     scan.setFootprintFactor(footprint)
     scan.setAbsoluteAngularResolution(alpha_distr, d_ang)
 
diff --git a/Examples/specular/BeamFullDivergence.py b/Examples/specular/BeamFullDivergence.py
index 6426060d1ec38547c25bee1cf49cf70858d6fb42..ff9cc38a9df9de2794b49930f135aa5ca71adefa 100755
--- a/Examples/specular/BeamFullDivergence.py
+++ b/Examples/specular/BeamFullDivergence.py
@@ -59,8 +59,7 @@ def get_simulation(sample, scan_size=500):
     alpha_distr = ba.RangedDistributionGaussian(n_points, n_sig)
     wavelength_distr = ba.RangedDistributionGaussian(n_points, n_sig)
 
-    scan = ba.AlphaScan(wavelength, scan_size, alpha_i_min,
-                              alpha_i_max)
+    scan = ba.AlphaScan(wavelength, scan_size, alpha_i_min, alpha_i_max)
     scan.setAbsoluteAngularResolution(alpha_distr, d_ang)
     scan.setAbsoluteWavelengthResolution(wavelength_distr, d_wl)
 
diff --git a/Examples/varia/BasicPolarizedReflectometry.py b/Examples/varia/BasicPolarizedReflectometry.py
index 64d993343675604a68b1d5338aa78547692aa7ee..73208aa1fe9d3b561738d35c70eb6ff0ba7e2302 100755
--- a/Examples/varia/BasicPolarizedReflectometry.py
+++ b/Examples/varia/BasicPolarizedReflectometry.py
@@ -47,8 +47,8 @@ def get_simulation(sample, scan_size=500):
     return simulation
 
 
-def run_simulation(polarization=ba.kvector_t(0, 1, 0),
-                   analyzer=ba.kvector_t(0, 1, 0)):
+def run_simulation(polarizer_dir=ba.kvector_t(0, 1, 0),
+                   analyzer_dir=ba.kvector_t(0, 1, 0)):
     """
     Runs simulation and returns its result.
     """
@@ -56,8 +56,8 @@ def run_simulation(polarization=ba.kvector_t(0, 1, 0),
     simulation = get_simulation(sample)
 
     # adding polarization and analyzer operator
-    simulation.beam().setPolarization(polarization)
-    simulation.detector().setAnalyzerProperties(analyzer, 1, 0.5)
+    simulation.instrument().setPolFilters(polarizer_dir, analyzer_dir, 1,
+                                          0.5)
 
     simulation.runSimulation()
     return simulation.result()
@@ -67,7 +67,10 @@ def plot(data, labels):
 
     plt.figure()
     for d, l in zip(data, labels):
-        plt.semilogy(d.convertedBinCenters(), d.array(), label=l, linewidth=1)
+        plt.semilogy(d.convertedBinCenters(),
+                     d.array(),
+                     label=l,
+                     linewidth=1)
 
     plt.legend(loc='upper right')
     plt.gca().yaxis.set_ticks_position('both')
diff --git a/Examples/varia/DepthProbe.py b/Examples/varia/DepthProbe.py
index 00b8ce7b94172aab5afca3625e171749c0643f8a..039471d66bb83249c4e43b80aa0b381918f1f2b0 100755
--- a/Examples/varia/DepthProbe.py
+++ b/Examples/varia/DepthProbe.py
@@ -76,7 +76,8 @@ def get_simulation(sample):
     simulation.setBeamParameters(wl, n_ai_bins, ai_min, ai_max, footprint)
     simulation.setZSpan(n_z_bins, z_min, z_max)
     simulation.addParameterDistribution(
-        ba.ParameterDistribution.BeamInclinationAngle, alpha_distr, n_points, n_sig)
+        ba.ParameterDistribution.BeamInclinationAngle, alpha_distr,
+        n_points, n_sig)
     simulation.setSample(sample)
     return simulation
 
diff --git a/Examples/varia/PolarizedNoAnalyzer.py b/Examples/varia/PolarizedNoAnalyzer.py
index 7bd98b02da8546154c95195f56e6cf46d510f5cc..875e7cdeb79a3df99a91312a4cdce8a824c9865b 100755
--- a/Examples/varia/PolarizedNoAnalyzer.py
+++ b/Examples/varia/PolarizedNoAnalyzer.py
@@ -10,6 +10,7 @@ import bornagain as ba
 from bornagain import angstrom, deg, nm, nm2, kvector_t
 from math import sqrt
 
+
 def get_sample():
     """
     Defines sample and returns it
@@ -48,17 +49,17 @@ def get_simulation(sample, scan_size=500):
     return simulation
 
 
-def run_simulation(polarization=ba.kvector_t(0, 1, 0), analyzer=None):
+def run_simulation(polarizer_dir=ba.kvector_t(0, 1, 0), analyzer_dir=None):
     """
     Runs simulation and returns its result.
     """
     sample = get_sample()
     simulation = get_simulation(sample)
 
-    # adding polarization and analyzer operator
-    simulation.beam().setPolarization(polarization)
-    if analyzer:
-        simulation.detector().setAnalyzerProperties(analyzer, 1, 0.5)
+    # adding polarizer and analyzer operator
+    simulation.beam().setPolarization(polarizer_dir)
+    if analyzer_dir:
+        simulation.detector().setAnalyzer(analyzer_dir, 1, 0.5)
 
     simulation.runSimulation()
     result = simulation.result()
diff --git a/Examples/varia/PolarizedNonperfectAnalyzerPolarizer.py b/Examples/varia/PolarizedNonperfectAnalyzerPolarizer.py
index 2b88a1c1f3bc6125aeccae4c5d887bd039d30383..27a07754b678aa97c18b6369d8a32cc0e51f7a6d 100755
--- a/Examples/varia/PolarizedNonperfectAnalyzerPolarizer.py
+++ b/Examples/varia/PolarizedNonperfectAnalyzerPolarizer.py
@@ -71,9 +71,9 @@ def get_simulation(sample, scan_size=1500):
 
 
 def run_simulation(*,
-                   polarization=ba.kvector_t(0, 1, 0),
+                   polarizer_dir=ba.kvector_t(0, 1, 0),
                    polarizer_efficiency=1,
-                   analyzer=ba.kvector_t(0, 1, 0),
+                   analyzer_dir=ba.kvector_t(0, 1, 0),
                    analyzer_efficiency=1):
     """
     Runs simulation and returns its result.
@@ -81,9 +81,9 @@ def run_simulation(*,
     sample = get_sample()
     simulation = get_simulation(sample)
 
-    simulation.beam().setPolarization(polarization*polarizer_efficiency)
-    simulation.detector().setAnalyzerProperties(analyzer,
-                                                analyzer_efficiency, 0.5)
+    simulation.instrument().setPolFilters(
+        polarizer_dir*polarizer_efficiency, analyzer_dir,
+        analyzer_efficiency, 0.5)
 
     simulation.setBackground(ba.ConstantBackground(1e-7))
 
@@ -116,21 +116,21 @@ if __name__ == '__main__':
     polarizer_efficiency = 0.986
     analyzer_efficiency = 0.970
 
-    results_pp = run_simulation(polarization=ba.kvector_t(0, 1, 0),
-                                analyzer=ba.kvector_t(0, 1, 0),
+    results_pp = run_simulation(polarizer_dir=ba.kvector_t(0, 1, 0),
+                                analyzer_dir=ba.kvector_t(0, 1, 0),
                                 polarizer_efficiency=polarizer_efficiency,
                                 analyzer_efficiency=analyzer_efficiency)
-    results_mm = run_simulation(polarization=ba.kvector_t(0, -1, 0),
-                                analyzer=ba.kvector_t(0, -1, 0),
+    results_mm = run_simulation(polarizer_dir=ba.kvector_t(0, -1, 0),
+                                analyzer_dir=ba.kvector_t(0, -1, 0),
                                 polarizer_efficiency=polarizer_efficiency,
                                 analyzer_efficiency=analyzer_efficiency)
 
-    results_pm = run_simulation(polarization=ba.kvector_t(0, 1, 0),
-                                analyzer=ba.kvector_t(0, -1, 0),
+    results_pm = run_simulation(polarizer_dir=ba.kvector_t(0, 1, 0),
+                                analyzer_dir=ba.kvector_t(0, -1, 0),
                                 polarizer_efficiency=polarizer_efficiency,
                                 analyzer_efficiency=analyzer_efficiency)
-    results_mp = run_simulation(polarization=ba.kvector_t(0, -1, 0),
-                                analyzer=ba.kvector_t(0, 1, 0),
+    results_mp = run_simulation(polarizer_dir=ba.kvector_t(0, -1, 0),
+                                analyzer_dir=ba.kvector_t(0, 1, 0),
                                 polarizer_efficiency=polarizer_efficiency,
                                 analyzer_efficiency=analyzer_efficiency)
 
diff --git a/Examples/varia/PolarizedSpinAsymmetry.py b/Examples/varia/PolarizedSpinAsymmetry.py
index ee6f01c436a7625dfa584b532a630b9b96836a39..f3e9f39b2572065dc37b836b7d5fa72ca918c645 100755
--- a/Examples/varia/PolarizedSpinAsymmetry.py
+++ b/Examples/varia/PolarizedSpinAsymmetry.py
@@ -63,7 +63,7 @@ def get_sample(params):
     return multi_layer
 
 
-def get_simulation(q_axis, parameters, polarization, analyzer):
+def get_simulation(q_axis, parameters, polarizer_dir, analyzer_dir):
     """
     Returns a simulation object.
     Polarization, analyzer and resolution are set
@@ -80,14 +80,14 @@ def get_simulation(q_axis, parameters, polarization, analyzer):
     distr = ba.RangedDistributionGaussian(n_samples, n_sig)
     scan.setAbsoluteQResolution(distr, parameters["q_res"])
 
-    simulation.beam().setPolarization(polarization)
-    simulation.detector().setAnalyzerProperties(analyzer, 1, 0.5)
+    simulation.instrument().setPolFilters(polarizer_dir, analyzer_dir, 1,
+                                          0.5)
 
     simulation.setScan(scan)
     return simulation
 
 
-def run_simulation(q_axis, fitParams, *, polarization, analyzer):
+def run_simulation(q_axis, fitParams, *, polarizer_dir, analyzer_dir):
     """
     Run a simulation on the given q-axis, where the sample is
     constructed with the given parameters.
@@ -96,7 +96,8 @@ def run_simulation(q_axis, fitParams, *, polarization, analyzer):
     parameters = dict(fitParams, **fixedParams)
 
     sample = get_sample(parameters)
-    simulation = get_simulation(q_axis, parameters, polarization, analyzer)
+    simulation = get_simulation(q_axis, parameters, polarizer_dir,
+                                analyzer_dir)
 
     simulation.setSample(sample)
     simulation.runSimulation()
@@ -207,8 +208,8 @@ if __name__ == '__main__':
     datadir = os.getenv('BORNAGAIN_EXAMPLE_DATA_DIR', '')
     fname_stem = os.path.join(datadir, "MAFO_Saturated_")
 
-    expdata_pp = load_exp(fname_stem+"pp.tab")
-    expdata_mm = load_exp(fname_stem+"mm.tab")
+    expdata_pp = load_exp(fname_stem + "pp.tab")
+    expdata_mm = load_exp(fname_stem + "mm.tab")
 
     fixedParams = {
         # parameters from our own fit run
@@ -224,14 +225,14 @@ if __name__ == '__main__':
     def run_Simulation_pp(qzs, params):
         return run_simulation(qzs,
                               params,
-                              polarization=ba.kvector_t(0, 1, 0),
-                              analyzer=ba.kvector_t(0, 1, 0))
+                              polarizer_dir=ba.kvector_t(0, 1, 0),
+                              analyzer_dir=ba.kvector_t(0, 1, 0))
 
     def run_Simulation_mm(qzs, params):
         return run_simulation(qzs,
                               params,
-                              polarization=ba.kvector_t(0, -1, 0),
-                              analyzer=ba.kvector_t(0, -1, 0))
+                              polarizer_dir=ba.kvector_t(0, -1, 0),
+                              analyzer_dir=ba.kvector_t(0, -1, 0))
 
     qzs = numpy.linspace(qmin, qmax, scan_size)
     q_pp, r_pp = qr(run_Simulation_pp(qzs, fixedParams))
diff --git a/Examples/varia/PolarizedSpinFlip.py b/Examples/varia/PolarizedSpinFlip.py
index 3449746b1fac004dafbb2e752380ba0133898d4c..b58ae701963f0eb6d1edaa92b5651a3bed9e9ec4 100755
--- a/Examples/varia/PolarizedSpinFlip.py
+++ b/Examples/varia/PolarizedSpinFlip.py
@@ -9,6 +9,7 @@ from bornagain import angstrom, deg, nm, nm2, kvector_t
 import matplotlib.pyplot as plt
 from math import sqrt
 
+
 def get_sample():
     """
     Defines sample and returns it
@@ -47,17 +48,16 @@ def get_simulation(sample, scan_size=500):
     return simulation
 
 
-def run_simulation(polarization=ba.kvector_t(0, 1, 0),
-                   analyzer=ba.kvector_t(0, 1, 0)):
+def run_simulation(polarizer_dir=ba.kvector_t(0, 1, 0),
+                   analyzer_dir=ba.kvector_t(0, 1, 0)):
     """
     Runs simulation and returns its result.
     """
     sample = get_sample()
     simulation = get_simulation(sample)
 
-    # adding polarization and analyzer operator
-    simulation.beam().setPolarization(polarization)
-    simulation.detector().setAnalyzerProperties(analyzer, 1, 0.5)
+    simulation.instrument().setPolFilters(polarizer_dir, analyzer_dir, 1,
+                                          0.5)
 
     simulation.runSimulation()
     return simulation.result()
@@ -67,7 +67,10 @@ def plot(data, labels):
 
     plt.figure()
     for d, l in zip(data, labels):
-        plt.semilogy(d.convertedBinCenters(), d.array(), label=l, linewidth=1)
+        plt.semilogy(d.convertedBinCenters(),
+                     d.array(),
+                     label=l,
+                     linewidth=1)
 
     plt.legend(loc='upper right')
     plt.gca().yaxis.set_ticks_position('both')
diff --git a/GUI/Models/DetectorItems.cpp b/GUI/Models/DetectorItems.cpp
index 1fc6d46244fb58200208fce713ff8c6f0ceeac64..22681c0b7137bdc40b7b2dadb475c7a72776136c 100644
--- a/GUI/Models/DetectorItems.cpp
+++ b/GUI/Models/DetectorItems.cpp
@@ -47,7 +47,7 @@ std::unique_ptr<IDetector2D> DetectorItem::createDetector() const
     double analyzer_eff = getItemValue(P_ANALYZER_EFFICIENCY).toDouble();
     double analyzer_total_trans = getItemValue(P_ANALYZER_TOTAL_TRANSMISSION).toDouble();
     if (analyzer_dir.mag() > 0.0)
-        result->setAnalyzerProperties(analyzer_dir, analyzer_eff, analyzer_total_trans);
+        result->setAnalyzer(analyzer_dir, analyzer_eff, analyzer_total_trans);
 
     return result;
 }
@@ -82,7 +82,7 @@ SessionItem* DetectorItem::resolutionFunctionItem() const
     return getItem(P_RESOLUTION_FUNCTION);
 }
 
-void DetectorItem::setAnalyserDirection(const kvector_t& direction)
+void DetectorItem::setAnalyzerDirection(const kvector_t& direction)
 {
     item<VectorItem>(P_ANALYZER_DIRECTION)->setVector(direction);
 }
@@ -92,7 +92,7 @@ SessionItem* DetectorItem::analyserDirectionItem() const
     return getItem(P_ANALYZER_DIRECTION);
 }
 
-void DetectorItem::setAnalyserEfficiency(const double efficiency)
+void DetectorItem::setAnalyzerEfficiency(const double efficiency)
 {
     setItemValue(P_ANALYZER_EFFICIENCY, efficiency);
 }
@@ -102,7 +102,7 @@ SessionItem* DetectorItem::analyserEfficiencyItem() const
     return getItem(P_ANALYZER_EFFICIENCY);
 }
 
-void DetectorItem::setAnalyserTotalTransmission(const double transmission)
+void DetectorItem::setAnalyzerTotalTransmission(const double transmission)
 {
     setItemValue(P_ANALYZER_TOTAL_TRANSMISSION, transmission);
 }
diff --git a/GUI/Models/DetectorItems.h b/GUI/Models/DetectorItems.h
index cdefb2c26683e9d874e9b13fb7b6bb0dec9b2083..f6f4fb74f00b23129537b16a056ac465ce97f0ee 100644
--- a/GUI/Models/DetectorItems.h
+++ b/GUI/Models/DetectorItems.h
@@ -60,13 +60,13 @@ public:
     template <typename T> T* setResolutionFunctionType();
     SessionItem* resolutionFunctionItem() const;
 
-    void setAnalyserDirection(const kvector_t& directorion);
+    void setAnalyzerDirection(const kvector_t& directorion);
     SessionItem* analyserDirectionItem() const;
 
-    void setAnalyserEfficiency(double efficiency);
+    void setAnalyzerEfficiency(double efficiency);
     SessionItem* analyserEfficiencyItem() const;
 
-    void setAnalyserTotalTransmission(double efficiency);
+    void setAnalyzerTotalTransmission(double efficiency);
     SessionItem* analyserTotalTransmissionItem() const;
 
 protected:
diff --git a/GUI/Models/TransformFromDomain.cpp b/GUI/Models/TransformFromDomain.cpp
index 0075b9fce6e33682d710a88f67f9a11d13ceffee..db7c15888c82290d6b994bacd263607bda47637a 100644
--- a/GUI/Models/TransformFromDomain.cpp
+++ b/GUI/Models/TransformFromDomain.cpp
@@ -24,12 +24,12 @@
 #include "Device/Beam/FootprintSquare.h"
 #include "Device/Detector/RectangularDetector.h"
 #include "Device/Detector/SphericalDetector.h"
+#include "Device/Mask/DetectorMask.h"
 #include "Device/Mask/Ellipse.h"
 #include "Device/Mask/InfinitePlane.h"
 #include "Device/Mask/Line.h"
 #include "Device/Mask/Polygon.h"
 #include "Device/Mask/Rectangle.h"
-#include "Device/ProDetector/DetectorMask.h"
 #include "Device/Resolution/ConvolutionDetectorResolution.h"
 #include "Device/Resolution/ResolutionFunction2DGaussian.h"
 #include "Device/Resolution/ScanResolution.h"
@@ -560,15 +560,15 @@ void GUI::Transform::FromDomain::setDetectorResolution(DetectorItem* detector_it
 void GUI::Transform::FromDomain::setDetectorProperties(DetectorItem* detector_item,
                                                        const IDetector& detector)
 {
-    double total_transmission = detector.detectionProperties().analyzerTotalTransmission();
+    double total_transmission = detector.analyzer().totalTransmission();
     if (total_transmission <= 0.0)
         return;
 
-    kvector_t analyzer_dir = detector.detectionProperties().analyzerDirection();
-    double efficiency = detector.detectionProperties().analyzerEfficiency();
-    detector_item->setAnalyserDirection(analyzer_dir);
-    detector_item->setAnalyserEfficiency(efficiency);
-    detector_item->setAnalyserTotalTransmission(total_transmission);
+    kvector_t analyzer_dir = detector.analyzer().polDirection();
+    double efficiency = detector.analyzer().polEfficiency();
+    detector_item->setAnalyzerDirection(analyzer_dir);
+    detector_item->setAnalyzerEfficiency(efficiency);
+    detector_item->setAnalyzerTotalTransmission(total_transmission);
 }
 
 void GUI::Transform::FromDomain::setSphericalDetector(SphericalDetectorItem* detector_item,
diff --git a/GUI/Views/InstrumentWidgets/PolarizationAnalysisEditor.cpp b/GUI/Views/InstrumentWidgets/PolarizationAnalysisEditor.cpp
index b66d3fda24d9caf973218268cddd6e4ac7c00493..dea0a39961932b7ec41e0ac1e06fb4249a1abc50 100644
--- a/GUI/Views/InstrumentWidgets/PolarizationAnalysisEditor.cpp
+++ b/GUI/Views/InstrumentWidgets/PolarizationAnalysisEditor.cpp
@@ -59,11 +59,11 @@ void PolarizationAnalysisEditor::subscribeToItem()
     currentItem()->mapper()->setOnPropertyChange(
         [this](const QString& name) {
             if (Instrument2DItem::isDetectorPropertyName(name))
-                updateAnalyserEditor();
+                updateAnalyzerEditor();
         },
         this);
 
-    updateAnalyserEditor();
+    updateAnalyzerEditor();
 }
 
 void PolarizationAnalysisEditor::unsubscribeFromItem()
@@ -93,7 +93,7 @@ DetectorItem* PolarizationAnalysisEditor::detectorItem()
 //! Updates analyser editor to display properties of currently selected detector
 //! (spherical/rectangular).
 
-void PolarizationAnalysisEditor::updateAnalyserEditor()
+void PolarizationAnalysisEditor::updateAnalyzerEditor()
 {
     m_analyserDirectionEditor->clearEditor();
     m_analyserPropertiesEditor->clearEditor();
diff --git a/GUI/Views/InstrumentWidgets/PolarizationAnalysisEditor.h b/GUI/Views/InstrumentWidgets/PolarizationAnalysisEditor.h
index 4c0e77800faabb9e5b05204b7ed3ceac854de516..55d5e47af2b4ff8dc4ab78c9bee42aa574bf5831 100644
--- a/GUI/Views/InstrumentWidgets/PolarizationAnalysisEditor.h
+++ b/GUI/Views/InstrumentWidgets/PolarizationAnalysisEditor.h
@@ -41,7 +41,7 @@ private:
     GISASInstrumentItem* instrumentItem();
     BeamItem* beamItem();
     DetectorItem* detectorItem();
-    void updateAnalyserEditor();
+    void updateAnalyzerEditor();
 
     ColumnResizer* m_columnResizer;
     ComponentEditor* m_polpairEditor;
diff --git a/GUI/Views/MaskWidgets/MaskResultsPresenter.cpp b/GUI/Views/MaskWidgets/MaskResultsPresenter.cpp
index 64d73b173926d76444499d72f0df8dde0b34a050..93b2685c67e07d7206c7f609cae1181675464c74 100644
--- a/GUI/Views/MaskWidgets/MaskResultsPresenter.cpp
+++ b/GUI/Views/MaskWidgets/MaskResultsPresenter.cpp
@@ -13,7 +13,7 @@
 //  ************************************************************************************************
 
 #include "GUI/Views/MaskWidgets/MaskResultsPresenter.h"
-#include "Device/ProDetector/DetectorMask.h"
+#include "Device/Mask/DetectorMask.h"
 #include "GUI/Models/IntensityDataItem.h"
 #include "GUI/Models/MaskItems.h"
 #include "GUI/Models/SessionModel.h"
diff --git a/Resample/Element/DiffuseElement.cpp b/Resample/Element/DiffuseElement.cpp
index 962e1f3c9630605fa8aaa52b823c91d6f2461830..f10a89c5e422176766d3230ee02c077daa15d76f 100644
--- a/Resample/Element/DiffuseElement.cpp
+++ b/Resample/Element/DiffuseElement.cpp
@@ -75,8 +75,8 @@ DiffuseElement DiffuseElement::pointElement(double x, double y) const
             m_alpha_i,
             m_phi_i,
             std::unique_ptr<IPixel>(m_pixel->createZeroSizePixel(x, y)), // TODO simplify
-            m_polpair.getPolarization(),
-            m_polpair.getAnalyzerOperator(),
+            m_polpair.polarizerMatrix(),
+            m_polpair.analyzerMatrix(),
             m_is_specular,
             m_fluxes_in,
             m_fluxes_out};
diff --git a/Resample/Element/DiffuseElement.h b/Resample/Element/DiffuseElement.h
index b961d4086493b9012e646b4f9ab3b4b9a23e8876..c40ac072c884e2101551e314ff6d6c413cdc29d0 100644
--- a/Resample/Element/DiffuseElement.h
+++ b/Resample/Element/DiffuseElement.h
@@ -51,7 +51,7 @@ public:
     DiffuseElement pointElement(double x, double y) const;
 
     //! Returns assigned PolarizerPair
-    const PolarizerPair& polarizationHandler() const { return m_polpair; }
+    const PolMatrices& polarizationHandler() const { return m_polpair; }
 
     double wavelength() const { return m_wavelength; }
     double getAlphaI() const { return m_alpha_i; }
diff --git a/Resample/Element/SpecularElement.cpp b/Resample/Element/SpecularElement.cpp
index fdcd13defa8a5da53ec692f9c8fa91e9edaf0b96..9d2fc832352daa8f6a184acb9039c25629f5bb5a 100644
--- a/Resample/Element/SpecularElement.cpp
+++ b/Resample/Element/SpecularElement.cpp
@@ -16,7 +16,7 @@
 #include "Base/Vector/Direction.h"
 #include "Resample/Slice/KzComputation.h"
 
-SpecularElement::SpecularElement(double kz, const PolarizerPair& polpair, bool computable)
+SpecularElement::SpecularElement(double kz, const PolMatrices& polpair, bool computable)
     : IElement(polpair)
     , m_intensity(0.0)
     , m_computable(computable)
@@ -25,7 +25,7 @@ SpecularElement::SpecularElement(double kz, const PolarizerPair& polpair, bool c
 {
 }
 
-SpecularElement::SpecularElement(double wavelength, double alpha, const PolarizerPair& polpair,
+SpecularElement::SpecularElement(double wavelength, double alpha, const PolMatrices& polpair,
                                  bool computable)
     : IElement(polpair)
     , m_intensity(0.0)
diff --git a/Resample/Element/SpecularElement.h b/Resample/Element/SpecularElement.h
index 8ed9651d43171fed0d3c9f967a13015b73979246..66d090d503f31b651e01a170fe7ed825a81dd2ae 100644
--- a/Resample/Element/SpecularElement.h
+++ b/Resample/Element/SpecularElement.h
@@ -32,8 +32,8 @@ class SliceStack;
 
 class SpecularElement : public IElement {
 public:
-    SpecularElement(double kz, const PolarizerPair& polpair, bool computable);
-    SpecularElement(double wavelength, double alpha, const PolarizerPair& polpair, bool computable);
+    SpecularElement(double kz, const PolMatrices& polpair, bool computable);
+    SpecularElement(double wavelength, double alpha, const PolMatrices& polpair, bool computable);
 
     SpecularElement(const SpecularElement& other) = delete;
     SpecularElement(SpecularElement&& other);
@@ -41,7 +41,7 @@ public:
     ~SpecularElement();
 
     //! Returns assigned PolarizerPair.
-    const PolarizerPair& polarizationHandler() const { return m_polpair; }
+    const PolMatrices& polarizationHandler() const { return m_polpair; }
 
     double intensity() const { return m_intensity; }
     void setIntensity(double intensity) { m_intensity = intensity; }
diff --git a/Resample/Interparticle/DecouplingApproximationStrategy.cpp b/Resample/Interparticle/DecouplingApproximationStrategy.cpp
index 9dbc3c8428a6b24fa764d357052a21d0c81e57df..ae3dba725d595f9ea91aa245d003e3d52a30f814 100644
--- a/Resample/Interparticle/DecouplingApproximationStrategy.cpp
+++ b/Resample/Interparticle/DecouplingApproximationStrategy.cpp
@@ -62,13 +62,13 @@ double DecouplingApproximationStrategy::polarizedCalculation(const DiffuseElemen
                 "numerical error in coherent sum (polarized, DA): amplitude is NaN");
         const double fraction = ffw->relativeAbundance();
         mean_amplitude += fraction * ff;
-        mean_intensity += fraction * (ff * polarization_handler.getPolarization() * ff.adjoint());
+        mean_intensity += fraction * (ff * polarization_handler.polarizerMatrix() * ff.adjoint());
     }
-    const Eigen::Matrix2cd amplitude_matrix =
-        polarization_handler.getAnalyzerOperator() * mean_amplitude
-        * polarization_handler.getPolarization() * mean_amplitude.adjoint();
+    const Eigen::Matrix2cd amplitude_matrix = polarization_handler.analyzerMatrix() * mean_amplitude
+                                              * polarization_handler.polarizerMatrix()
+                                              * mean_amplitude.adjoint();
     const Eigen::Matrix2cd intensity_matrix =
-        polarization_handler.getAnalyzerOperator() * mean_intensity;
+        polarization_handler.analyzerMatrix() * mean_intensity;
     const double amplitude_trace = std::abs(amplitude_matrix.trace());
     const double intensity_trace = std::abs(intensity_matrix.trace());
     const double coherence_factor = m_iff->evaluate(ele.meanQ());
diff --git a/Resample/Interparticle/SSCAStrategy.cpp b/Resample/Interparticle/SSCAStrategy.cpp
index 268b9c23534563cfbb24b3dc85e2f5eeabd2b2ee..be1783c9f64b0b5e1ee034766c36c20ccc5c7af7 100644
--- a/Resample/Interparticle/SSCAStrategy.cpp
+++ b/Resample/Interparticle/SSCAStrategy.cpp
@@ -78,7 +78,7 @@ double SSCAStrategy::polarizedCalculation(const DiffuseElement& ele) const
     for (const auto& ffw : m_weighted_formfactors) {
         const Eigen::Matrix2cd ff = ffw->summedPolFF(ele);
         const double fraction = ffw->relativeAbundance();
-        diffuse_matrix += fraction * (ff * polarization_handler.getPolarization() * ff.adjoint());
+        diffuse_matrix += fraction * (ff * polarization_handler.polarizerMatrix() * ff.adjoint());
         const double radial_extension = ffw->radialExtension();
         const complex_t prefac =
             ffw->relativeAbundance() * calculatePositionOffsetPhase(qp, radial_extension);
@@ -87,11 +87,10 @@ double SSCAStrategy::polarizedCalculation(const DiffuseElement& ele) const
     }
     const complex_t p2kappa = getCharacteristicSizeCoupling(qp, m_weighted_formfactors);
     const complex_t omega = m_iff->FTPDF(qp);
-    const Eigen::Matrix2cd interference_matrix =
-        (2.0 * omega / (1.0 - p2kappa * omega)) * polarization_handler.getAnalyzerOperator()
-        * ff_orig * polarization_handler.getPolarization() * ff_conj;
-    const Eigen::Matrix2cd diffuse_matrix2 =
-        polarization_handler.getAnalyzerOperator() * diffuse_matrix;
+    const Eigen::Matrix2cd interference_matrix = (2.0 * omega / (1.0 - p2kappa * omega))
+                                                 * polarization_handler.analyzerMatrix() * ff_orig
+                                                 * polarization_handler.polarizerMatrix() * ff_conj;
+    const Eigen::Matrix2cd diffuse_matrix2 = polarization_handler.analyzerMatrix() * diffuse_matrix;
     const double interference_trace = std::abs(interference_matrix.trace());
     const double diffuse_trace = std::abs(diffuse_matrix2.trace());
     const double dw_factor = m_iff->DWfactor(ele.meanQ());
diff --git a/Sample/Aggregate/IInterferenceFunction.h b/Sample/Aggregate/IInterferenceFunction.h
index 47c72e7479782da723764a8e4f592be58d9a784e..2ae4d4bf3239aded0ada57d784f047ca83e13c9e 100644
--- a/Sample/Aggregate/IInterferenceFunction.h
+++ b/Sample/Aggregate/IInterferenceFunction.h
@@ -16,8 +16,8 @@
 #ifndef BORNAGAIN_SAMPLE_AGGREGATE_IINTERFERENCEFUNCTION_H
 #define BORNAGAIN_SAMPLE_AGGREGATE_IINTERFERENCEFUNCTION_H
 
-#include "Sample/Scattering/ISampleNode.h"
 #include "Base/Vector/Vectors3D.h"
+#include "Sample/Scattering/ISampleNode.h"
 
 //! Abstract base class of interference functions.
 
diff --git a/Sample/Correlations/IPeakShape.h b/Sample/Correlations/IPeakShape.h
index 1e0d4aea8917a7dfc12aa7242aa38a25d38dffdf..42dcc46262e829f718f91a1c939255e8305d6943 100644
--- a/Sample/Correlations/IPeakShape.h
+++ b/Sample/Correlations/IPeakShape.h
@@ -16,8 +16,8 @@
 #ifndef BORNAGAIN_SAMPLE_CORRELATIONS_IPEAKSHAPE_H
 #define BORNAGAIN_SAMPLE_CORRELATIONS_IPEAKSHAPE_H
 
-#include "Sample/Scattering/ISampleNode.h"
 #include "Base/Vector/Vectors3D.h"
+#include "Sample/Scattering/ISampleNode.h"
 
 //! Abstract base class class that defines the peak shape of a Bragg peak.
 
diff --git a/Sample/Interface/LayerRoughness.h b/Sample/Interface/LayerRoughness.h
index bd22235b77f1dc9fc9e3b594ca579a92f1fae00b..a0956114cda135908d01a0a0fafaa52a5382b08f 100644
--- a/Sample/Interface/LayerRoughness.h
+++ b/Sample/Interface/LayerRoughness.h
@@ -15,8 +15,8 @@
 #ifndef BORNAGAIN_SAMPLE_INTERFACE_LAYERROUGHNESS_H
 #define BORNAGAIN_SAMPLE_INTERFACE_LAYERROUGHNESS_H
 
-#include "Sample/Scattering/ISampleNode.h"
 #include "Base/Vector/Vectors3D.h"
+#include "Sample/Scattering/ISampleNode.h"
 
 //! A roughness of interface between two layers.
 //!
diff --git a/Sample/Lattice/Lattice3D.h b/Sample/Lattice/Lattice3D.h
index d7fd2ed50c45a9fad7f08f100ec0856213aa59bf..f2268ffdc8388012fa2a654624fc1292f3eadae4 100644
--- a/Sample/Lattice/Lattice3D.h
+++ b/Sample/Lattice/Lattice3D.h
@@ -15,8 +15,8 @@
 #ifndef BORNAGAIN_SAMPLE_LATTICE_LATTICE3D_H
 #define BORNAGAIN_SAMPLE_LATTICE_LATTICE3D_H
 
-#include "Param/Node/INode.h"
 #include "Base/Vector/Vectors3D.h"
+#include "Param/Node/INode.h"
 #include <memory>
 #include <vector>
 
diff --git a/Sample/Particle/IAbstractParticle.h b/Sample/Particle/IAbstractParticle.h
index 93401fbf70eac0d3df1016fcd452de3ab7efcf8a..185b34d1d8cbcba9b8078fa58766459e1210fcc7 100644
--- a/Sample/Particle/IAbstractParticle.h
+++ b/Sample/Particle/IAbstractParticle.h
@@ -16,8 +16,8 @@
 #ifndef BORNAGAIN_SAMPLE_PARTICLE_IABSTRACTPARTICLE_H
 #define BORNAGAIN_SAMPLE_PARTICLE_IABSTRACTPARTICLE_H
 
-#include "Sample/Scattering/ISampleNode.h"
 #include "Base/Vector/Vectors3D.h"
+#include "Sample/Scattering/ISampleNode.h"
 
 class IRotation;
 
diff --git a/Sample/Scattering/IFormFactor.h b/Sample/Scattering/IFormFactor.h
index cbf3776c17db697e8774b3633c794e33dec9f3c0..872db3c3540b57a30f5d6cd4a4e784f95df84e70 100644
--- a/Sample/Scattering/IFormFactor.h
+++ b/Sample/Scattering/IFormFactor.h
@@ -16,9 +16,9 @@
 #ifndef BORNAGAIN_SAMPLE_SCATTERING_IFORMFACTOR_H
 #define BORNAGAIN_SAMPLE_SCATTERING_IFORMFACTOR_H
 
+#include "Base/Vector/Vectors3D.h"
 #include "Sample/Scattering/ISampleNode.h"
 #include "Sample/Scattering/ZLimits.h"
-#include "Base/Vector/Vectors3D.h"
 #include <Eigen/Core>
 
 class IRotation;
diff --git a/Sample/Scattering/Rotations.h b/Sample/Scattering/Rotations.h
index 28e2451386065206d48f9fa5b8f08465a2acb3c8..4685921dc5c18d4655a42693c7a9f08c3de94457 100644
--- a/Sample/Scattering/Rotations.h
+++ b/Sample/Scattering/Rotations.h
@@ -16,8 +16,8 @@
 #define BORNAGAIN_SAMPLE_SCATTERING_ROTATIONS_H
 
 #include "Base/Types/ICloneable.h"
-#include "Param/Node/INode.h"
 #include "Base/Vector/Vectors3D.h"
+#include "Param/Node/INode.h"
 
 class Transform3D;
 
diff --git a/Tests/Functional/PyCore/polmagcylinders2.py b/Tests/Functional/PyCore/polmagcylinders2.py
index 9a94fd39dce7f8acb788608b155e34cf3f503acd..80e30f75d356e4dfe0089c2ba9d68840bd17e560 100644
--- a/Tests/Functional/PyCore/polmagcylinders2.py
+++ b/Tests/Functional/PyCore/polmagcylinders2.py
@@ -12,7 +12,7 @@ from bornagain import *
 # ----------------------------------
 # describe sample and run simulation
 # ----------------------------------
-def getSimulationIntensity(rho_beam, efficiency):
+def getSimulationIntensity(polarizer_dir, efficiency):
     print("- simulate", flush=True)
     # defining materials
     mAmbience = HomogeneousMaterial("Vacuum", 0, 0)
@@ -43,9 +43,11 @@ def getSimulationIntensity(rho_beam, efficiency):
     simulation = GISASSimulation()
     simulation.setDetectorParameters(100, -1*deg, 1*deg, 100, 0, 2*deg)
     zplus = kvector_t(0, 0, 1)
-    simulation.detector().setAnalyzerProperties(zplus, efficiency, 0.5)
     simulation.setBeamParameters(1*angstrom, 0.2*deg, 0)
-    simulation.beam().setPolarization(rho_beam)
+
+    simulation.instrument().setPolFilters(polarizer_dir, zplus, efficiency,
+                                          0.5)
+
     simulation.setSample(multi_layer)
     simulation.beam().setIntensity(1e9)
     simulation.runSimulation()
diff --git a/Tests/Unit/Core/RectangularDetectorTest.cpp b/Tests/Unit/Core/RectangularDetectorTest.cpp
index de7640fae09571aa8725c73ad95feb8fb18375ce..8a0e00ee9824d7bfc47efa85c9253efa8e861cf3 100644
--- a/Tests/Unit/Core/RectangularDetectorTest.cpp
+++ b/Tests/Unit/Core/RectangularDetectorTest.cpp
@@ -197,75 +197,75 @@ TEST_F(RectangularDetectorTest, AnalyzerProperties)
     kvector_t unit_direction;
 
     // if direction is the zero vector, an exception is thrown
-    EXPECT_THROW(detector.setAnalyzerProperties(direction, efficiency, total_transmission),
+    EXPECT_THROW(detector.setAnalyzer(direction, efficiency, total_transmission),
                  std::runtime_error);
 
     // zero efficiency
     direction = kvector_t(1.0, 0.0, 0.0);
     unit_direction = direction.unit();
-    detector.setAnalyzerProperties(direction, efficiency, total_transmission);
-    const DetectionProperties& detect_properties = detector.detectionProperties();
+    detector.setAnalyzer(direction, efficiency, total_transmission);
+    const PolFilter& detect_properties = detector.analyzer();
 
-    EXPECT_NEAR(detect_properties.analyzerEfficiency(), efficiency, 1e-8);
-    EXPECT_NEAR(detect_properties.analyzerTotalTransmission(), total_transmission, 1e-8);
+    EXPECT_NEAR(detect_properties.polEfficiency(), efficiency, 1e-8);
+    EXPECT_NEAR(detect_properties.totalTransmission(), total_transmission, 1e-8);
     // direction vector returned is zero vector because efficiency is zero
-    EXPECT_NEAR(detect_properties.analyzerDirection().x(), 0.0, 1e-8);
-    EXPECT_NEAR(detect_properties.analyzerDirection().y(), 0.0, 1e-8);
-    EXPECT_NEAR(detect_properties.analyzerDirection().z(), 0.0, 1e-8);
+    EXPECT_NEAR(detect_properties.polDirection().x(), 0.0, 1e-8);
+    EXPECT_NEAR(detect_properties.polDirection().y(), 0.0, 1e-8);
+    EXPECT_NEAR(detect_properties.polDirection().z(), 0.0, 1e-8);
 
     // intermediate efficiency
     direction = kvector_t(1.0, 0.0, 0.0);
     efficiency = 0.5;
     total_transmission = 0.6;
     unit_direction = direction.unit();
-    detector.setAnalyzerProperties(direction, efficiency, total_transmission);
-    const DetectionProperties& detect_properties2 = detector.detectionProperties();
+    detector.setAnalyzer(direction, efficiency, total_transmission);
+    const PolFilter& detect_properties2 = detector.analyzer();
 
-    EXPECT_NEAR(detect_properties2.analyzerEfficiency(), efficiency, 1e-8);
-    EXPECT_NEAR(detect_properties2.analyzerTotalTransmission(), total_transmission, 1e-8);
-    EXPECT_NEAR(detect_properties2.analyzerDirection().x(), unit_direction.x(), 1e-8);
-    EXPECT_NEAR(detect_properties2.analyzerDirection().y(), unit_direction.y(), 1e-8);
-    EXPECT_NEAR(detect_properties2.analyzerDirection().z(), unit_direction.z(), 1e-8);
+    EXPECT_NEAR(detect_properties2.polEfficiency(), efficiency, 1e-8);
+    EXPECT_NEAR(detect_properties2.totalTransmission(), total_transmission, 1e-8);
+    EXPECT_NEAR(detect_properties2.polDirection().x(), unit_direction.x(), 1e-8);
+    EXPECT_NEAR(detect_properties2.polDirection().y(), unit_direction.y(), 1e-8);
+    EXPECT_NEAR(detect_properties2.polDirection().z(), unit_direction.z(), 1e-8);
 
     // maximum efficiency
     direction = kvector_t(1.0, 0.0, 0.0);
     efficiency = 1.0;
     total_transmission = 0.5;
     unit_direction = direction.unit();
-    detector.setAnalyzerProperties(direction, efficiency, total_transmission);
-    const DetectionProperties& detect_properties3 = detector.detectionProperties();
+    detector.setAnalyzer(direction, efficiency, total_transmission);
+    const PolFilter& detect_properties3 = detector.analyzer();
 
-    EXPECT_NEAR(detect_properties3.analyzerEfficiency(), efficiency, 1e-8);
-    EXPECT_NEAR(detect_properties3.analyzerTotalTransmission(), total_transmission, 1e-8);
-    EXPECT_NEAR(detect_properties3.analyzerDirection().x(), unit_direction.x(), 1e-8);
-    EXPECT_NEAR(detect_properties3.analyzerDirection().y(), unit_direction.y(), 1e-8);
-    EXPECT_NEAR(detect_properties3.analyzerDirection().z(), unit_direction.z(), 1e-8);
+    EXPECT_NEAR(detect_properties3.polEfficiency(), efficiency, 1e-8);
+    EXPECT_NEAR(detect_properties3.totalTransmission(), total_transmission, 1e-8);
+    EXPECT_NEAR(detect_properties3.polDirection().x(), unit_direction.x(), 1e-8);
+    EXPECT_NEAR(detect_properties3.polDirection().y(), unit_direction.y(), 1e-8);
+    EXPECT_NEAR(detect_properties3.polDirection().z(), unit_direction.z(), 1e-8);
 
     // non-axis direction
     direction = kvector_t(1.0, 2.0, 3.0);
     efficiency = 1.0;
     total_transmission = 0.5;
     unit_direction = direction.unit();
-    detector.setAnalyzerProperties(direction, efficiency, total_transmission);
-    const DetectionProperties& detect_properties4 = detector.detectionProperties();
+    detector.setAnalyzer(direction, efficiency, total_transmission);
+    const PolFilter& detect_properties4 = detector.analyzer();
 
-    EXPECT_NEAR(detect_properties4.analyzerEfficiency(), efficiency, 1e-8);
-    EXPECT_NEAR(detect_properties4.analyzerTotalTransmission(), total_transmission, 1e-8);
-    EXPECT_NEAR(detect_properties4.analyzerDirection().x(), unit_direction.x(), 1e-8);
-    EXPECT_NEAR(detect_properties4.analyzerDirection().y(), unit_direction.y(), 1e-8);
-    EXPECT_NEAR(detect_properties4.analyzerDirection().z(), unit_direction.z(), 1e-8);
+    EXPECT_NEAR(detect_properties4.polEfficiency(), efficiency, 1e-8);
+    EXPECT_NEAR(detect_properties4.totalTransmission(), total_transmission, 1e-8);
+    EXPECT_NEAR(detect_properties4.polDirection().x(), unit_direction.x(), 1e-8);
+    EXPECT_NEAR(detect_properties4.polDirection().y(), unit_direction.y(), 1e-8);
+    EXPECT_NEAR(detect_properties4.polDirection().z(), unit_direction.z(), 1e-8);
 
     // maximum efficiency and negative efficiency
     direction = kvector_t(0.0, -1.0, -1.0);
     efficiency = -1.0;
     total_transmission = 0.5;
     unit_direction = direction.unit();
-    detector.setAnalyzerProperties(direction, efficiency, total_transmission);
-    const DetectionProperties& detect_properties5 = detector.detectionProperties();
-
-    EXPECT_NEAR(detect_properties5.analyzerEfficiency(), efficiency, 1e-8);
-    EXPECT_NEAR(detect_properties5.analyzerTotalTransmission(), total_transmission, 1e-8);
-    EXPECT_NEAR(detect_properties5.analyzerDirection().x(), unit_direction.x(), 1e-8);
-    EXPECT_NEAR(detect_properties5.analyzerDirection().y(), unit_direction.y(), 1e-8);
-    EXPECT_NEAR(detect_properties5.analyzerDirection().z(), unit_direction.z(), 1e-8);
+    detector.setAnalyzer(direction, efficiency, total_transmission);
+    const PolFilter& detect_properties5 = detector.analyzer();
+
+    EXPECT_NEAR(detect_properties5.polEfficiency(), efficiency, 1e-8);
+    EXPECT_NEAR(detect_properties5.totalTransmission(), total_transmission, 1e-8);
+    EXPECT_NEAR(detect_properties5.polDirection().x(), unit_direction.x(), 1e-8);
+    EXPECT_NEAR(detect_properties5.polDirection().y(), unit_direction.y(), 1e-8);
+    EXPECT_NEAR(detect_properties5.polDirection().z(), unit_direction.z(), 1e-8);
 }
diff --git a/Tests/Unit/Core/SpecularSimulationTest.cpp b/Tests/Unit/Core/SpecularSimulationTest.cpp
index d93c6de948af84783eee24b841332cbd32675230..0567d3069a8ce403ae69e42e9bb740f7fdf9645d 100644
--- a/Tests/Unit/Core/SpecularSimulationTest.cpp
+++ b/Tests/Unit/Core/SpecularSimulationTest.cpp
@@ -98,10 +98,9 @@ TEST_F(SpecularSimulationTest, SetAngularScan)
 
     SpecularSimulation sim4;
     AlphaScan scan4(1.0, 10, .0 * Units::deg, 2.0 * Units::deg);
-    const auto polarization = kvector_t({0., 0., 0.876});
-    const auto analyzer = kvector_t({0., 0., 1.});
-    sim4.beam().setPolarization(polarization);
-    sim4.detector().setAnalyzerProperties(analyzer, 0.33, 0.22);
+    const auto polarizer_dir = kvector_t({0., 0., 0.876});
+    const auto analyzer_dir = kvector_t({0., 0., 1.});
+    sim4.instrument().setPolFilters(polarizer_dir, analyzer_dir, 0.33, 0.22);
     sim4.setScan(scan4);
     EXPECT_THROW(sim4.setScan(scan4), std::runtime_error);
 
@@ -113,10 +112,10 @@ TEST_F(SpecularSimulationTest, SetAngularScan)
     EXPECT_EQ(0.0, sim4.beam().direction().alpha());
     EXPECT_EQ(0.0, sim4.beam().direction().phi());
 
-    EXPECT_EQ(sim4.beam().getBlochVector(), polarization);
-    EXPECT_EQ(sim4.detector().detectionProperties().analyzerDirection(), analyzer);
-    EXPECT_EQ(sim4.detector().detectionProperties().analyzerEfficiency(), 0.33);
-    EXPECT_EQ(sim4.detector().detectionProperties().analyzerTotalTransmission(), 0.22);
+    EXPECT_EQ(sim4.beam().getBlochVector(), polarizer_dir);
+    EXPECT_EQ(sim4.detector().analyzer().polDirection(), analyzer_dir);
+    EXPECT_EQ(sim4.detector().analyzer().polEfficiency(), 0.33);
+    EXPECT_EQ(sim4.detector().analyzer().totalTransmission(), 0.22);
 }
 
 TEST_F(SpecularSimulationTest, SetQScan)
@@ -152,10 +151,9 @@ TEST_F(SpecularSimulationTest, SetQScan)
 
     SpecularSimulation sim3;
     QzScan scan3(10, 1.0, 10.0);
-    const auto polarization = kvector_t({0., 0., 0.876});
-    const auto analyzer = kvector_t({0., 0., 1.});
-    sim3.beam().setPolarization(polarization);
-    sim3.detector().setAnalyzerProperties(analyzer, 0.33, 0.22);
+    const auto polarizer_dir = kvector_t({0., 0., 0.876});
+    const auto analyzer_dir = kvector_t({0., 0., 1.});
+    sim3.instrument().setPolFilters(polarizer_dir, analyzer_dir, 0.33, 0.22);
     sim3.setScan(scan3);
 
     EXPECT_EQ(1.0, sim3.coordinateAxis()->lowerBound());
@@ -166,10 +164,10 @@ TEST_F(SpecularSimulationTest, SetQScan)
     EXPECT_EQ(0.0, sim3.beam().direction().alpha());
     EXPECT_EQ(0.0, sim3.beam().direction().phi());
 
-    EXPECT_EQ(sim3.beam().getBlochVector(), polarization);
-    EXPECT_EQ(sim3.detector().detectionProperties().analyzerDirection(), analyzer);
-    EXPECT_EQ(sim3.detector().detectionProperties().analyzerEfficiency(), 0.33);
-    EXPECT_EQ(sim3.detector().detectionProperties().analyzerTotalTransmission(), 0.22);
+    EXPECT_EQ(sim3.beam().getBlochVector(), polarizer_dir);
+    EXPECT_EQ(sim3.detector().analyzer().polDirection(), analyzer_dir);
+    EXPECT_EQ(sim3.detector().analyzer().polEfficiency(), 0.33);
+    EXPECT_EQ(sim3.detector().analyzer().totalTransmission(), 0.22);
 }
 
 TEST_F(SpecularSimulationTest, ConstructSimulation)
diff --git a/Tests/Unit/Device/BeamTest.cpp b/Tests/Unit/Device/BeamTest.cpp
deleted file mode 100644
index 420e70e6fdc0800089d69756f710a335089046e5..0000000000000000000000000000000000000000
--- a/Tests/Unit/Device/BeamTest.cpp
+++ /dev/null
@@ -1,22 +0,0 @@
-#include "Device/Beam/Beam.h"
-#include "Base/Math/Constants.h"
-#include "Device/Beam/FootprintGauss.h"
-#include "Device/Beam/FootprintSquare.h"
-#include "Tests/GTestWrapper/google_test.h"
-
-#include <memory>
-
-class BeamTest : public ::testing::Test {
-};
-
-TEST_F(BeamTest, BeamPolarization)
-{
-    Beam beam = Beam::horizontalBeam();
-    kvector_t polarization(0.1, -0.2, 0.4);
-    beam.setPolarization(polarization);
-
-    kvector_t bloch_vector = beam.getBlochVector();
-    EXPECT_NEAR(0.1, bloch_vector.x(), 1e-8);
-    EXPECT_NEAR(-0.2, bloch_vector.y(), 1e-8);
-    EXPECT_NEAR(0.4, bloch_vector.z(), 1e-8);
-}
diff --git a/Tests/Unit/Device/DetectorMaskTest.cpp b/Tests/Unit/Device/DetectorMaskTest.cpp
index 0b80b1f124cca6b070c62e74ae60910cdc5aba0d..2b6c7400dff0de29544b3798c8bfc9a3e106187c 100644
--- a/Tests/Unit/Device/DetectorMaskTest.cpp
+++ b/Tests/Unit/Device/DetectorMaskTest.cpp
@@ -1,4 +1,4 @@
-#include "Device/ProDetector/DetectorMask.h"
+#include "Device/Mask/DetectorMask.h"
 #include "Base/Axis/FixedBinAxis.h"
 #include "Device/Detector/SphericalDetector.h"
 #include "Device/Mask/Polygon.h"
diff --git a/Tests/Unit/Device/SpecularDetector1DTest.cpp b/Tests/Unit/Device/SpecularDetector1DTest.cpp
index d17050c0c37f0834871ecf0666e78db9f331629d..037a70d23e301619a2e49577c419949a40849232 100644
--- a/Tests/Unit/Device/SpecularDetector1DTest.cpp
+++ b/Tests/Unit/Device/SpecularDetector1DTest.cpp
@@ -48,7 +48,7 @@ TEST_F(SpecularDetectorTest, Clone)
     SpecularDetector1D detector(axis);
 
     const auto analyzer = kvector_t({0., 0., 1.});
-    detector.setAnalyzerProperties(analyzer, 0.33, 0.22);
+    detector.setAnalyzer(analyzer, 0.33, 0.22);
 
     std::unique_ptr<SpecularDetector1D> clone(detector.clone());
 
@@ -67,7 +67,7 @@ TEST_F(SpecularDetectorTest, Clone)
         detectorIndexes.push_back(it.detectorIndex());
     EXPECT_EQ(detectorIndexes, expectedDetectorIndexes);
 
-    EXPECT_EQ(clone->detectionProperties().analyzerDirection(), analyzer);
-    EXPECT_EQ(clone->detectionProperties().analyzerEfficiency(), 0.33);
-    EXPECT_EQ(clone->detectionProperties().analyzerTotalTransmission(), 0.22);
+    EXPECT_EQ(clone->analyzer().polDirection(), analyzer);
+    EXPECT_EQ(clone->analyzer().polEfficiency(), 0.33);
+    EXPECT_EQ(clone->analyzer().totalTransmission(), 0.22);
 }
diff --git a/Tests/Unit/Device/SphericalDetectorTest.cpp b/Tests/Unit/Device/SphericalDetectorTest.cpp
index ae0cb9715d0be72f4fa07d1f858f11b3130c97ec..70665afeef4bf777561ba2e126a138649b879c62 100644
--- a/Tests/Unit/Device/SphericalDetectorTest.cpp
+++ b/Tests/Unit/Device/SphericalDetectorTest.cpp
@@ -2,9 +2,9 @@
 #include "Base/Axis/FixedBinAxis.h"
 #include "Base/Const/Units.h"
 #include "Device/Beam/Beam.h"
+#include "Device/Mask/DetectorMask.h"
 #include "Device/Mask/Polygon.h"
 #include "Device/Mask/Rectangle.h"
-#include "Device/ProDetector/DetectorMask.h"
 #include "Device/Resolution/ConvolutionDetectorResolution.h"
 #include "Device/Resolution/ResolutionFunction2DGaussian.h"
 #include "Tests/GTestWrapper/google_test.h"
@@ -224,75 +224,75 @@ TEST_F(SphericalDetectorTest, AnalyzerProperties)
     kvector_t unit_direction;
 
     // if direction is the zero vector, an exception is thrown
-    EXPECT_THROW(detector.setAnalyzerProperties(direction, efficiency, total_transmission),
+    EXPECT_THROW(detector.setAnalyzer(direction, efficiency, total_transmission),
                  std::runtime_error);
 
     // zero efficiency
     direction = kvector_t(1.0, 0.0, 0.0);
     unit_direction = direction.unit();
-    detector.setAnalyzerProperties(direction, efficiency, total_transmission);
-    const DetectionProperties& detect_properties = detector.detectionProperties();
+    detector.setAnalyzer(direction, efficiency, total_transmission);
+    const PolFilter& detect_properties = detector.analyzer();
 
-    EXPECT_NEAR(detect_properties.analyzerEfficiency(), efficiency, 1e-8);
-    EXPECT_NEAR(detect_properties.analyzerTotalTransmission(), total_transmission, 1e-8);
+    EXPECT_NEAR(detect_properties.polEfficiency(), efficiency, 1e-8);
+    EXPECT_NEAR(detect_properties.totalTransmission(), total_transmission, 1e-8);
     // direction vector returned is zero vector because efficiency is zero
-    EXPECT_NEAR(detect_properties.analyzerDirection().x(), 0.0, 1e-8);
-    EXPECT_NEAR(detect_properties.analyzerDirection().y(), 0.0, 1e-8);
-    EXPECT_NEAR(detect_properties.analyzerDirection().z(), 0.0, 1e-8);
+    EXPECT_NEAR(detect_properties.polDirection().x(), 0.0, 1e-8);
+    EXPECT_NEAR(detect_properties.polDirection().y(), 0.0, 1e-8);
+    EXPECT_NEAR(detect_properties.polDirection().z(), 0.0, 1e-8);
 
     // intermediate efficiency
     direction = kvector_t(1.0, 0.0, 0.0);
     efficiency = 0.5;
     total_transmission = 0.6;
     unit_direction = direction.unit();
-    detector.setAnalyzerProperties(direction, efficiency, total_transmission);
-    const DetectionProperties& detect_properties2 = detector.detectionProperties();
+    detector.setAnalyzer(direction, efficiency, total_transmission);
+    const PolFilter& detect_properties2 = detector.analyzer();
 
-    EXPECT_NEAR(detect_properties2.analyzerEfficiency(), efficiency, 1e-8);
-    EXPECT_NEAR(detect_properties2.analyzerTotalTransmission(), total_transmission, 1e-8);
-    EXPECT_NEAR(detect_properties2.analyzerDirection().x(), unit_direction.x(), 1e-8);
-    EXPECT_NEAR(detect_properties2.analyzerDirection().y(), unit_direction.y(), 1e-8);
-    EXPECT_NEAR(detect_properties2.analyzerDirection().z(), unit_direction.z(), 1e-8);
+    EXPECT_NEAR(detect_properties2.polEfficiency(), efficiency, 1e-8);
+    EXPECT_NEAR(detect_properties2.totalTransmission(), total_transmission, 1e-8);
+    EXPECT_NEAR(detect_properties2.polDirection().x(), unit_direction.x(), 1e-8);
+    EXPECT_NEAR(detect_properties2.polDirection().y(), unit_direction.y(), 1e-8);
+    EXPECT_NEAR(detect_properties2.polDirection().z(), unit_direction.z(), 1e-8);
 
     // maximum efficiency
     direction = kvector_t(1.0, 0.0, 0.0);
     efficiency = 1.0;
     total_transmission = 0.5;
     unit_direction = direction.unit();
-    detector.setAnalyzerProperties(direction, efficiency, total_transmission);
-    const DetectionProperties& detect_properties3 = detector.detectionProperties();
+    detector.setAnalyzer(direction, efficiency, total_transmission);
+    const PolFilter& detect_properties3 = detector.analyzer();
 
-    EXPECT_NEAR(detect_properties3.analyzerEfficiency(), efficiency, 1e-8);
-    EXPECT_NEAR(detect_properties3.analyzerTotalTransmission(), total_transmission, 1e-8);
-    EXPECT_NEAR(detect_properties3.analyzerDirection().x(), unit_direction.x(), 1e-8);
-    EXPECT_NEAR(detect_properties3.analyzerDirection().y(), unit_direction.y(), 1e-8);
-    EXPECT_NEAR(detect_properties3.analyzerDirection().z(), unit_direction.z(), 1e-8);
+    EXPECT_NEAR(detect_properties3.polEfficiency(), efficiency, 1e-8);
+    EXPECT_NEAR(detect_properties3.totalTransmission(), total_transmission, 1e-8);
+    EXPECT_NEAR(detect_properties3.polDirection().x(), unit_direction.x(), 1e-8);
+    EXPECT_NEAR(detect_properties3.polDirection().y(), unit_direction.y(), 1e-8);
+    EXPECT_NEAR(detect_properties3.polDirection().z(), unit_direction.z(), 1e-8);
 
     // non-axis direction
     direction = kvector_t(1.0, 2.0, 3.0);
     efficiency = 1.0;
     total_transmission = 0.5;
     unit_direction = direction.unit();
-    detector.setAnalyzerProperties(direction, efficiency, total_transmission);
-    const DetectionProperties& detect_properties4 = detector.detectionProperties();
+    detector.setAnalyzer(direction, efficiency, total_transmission);
+    const PolFilter& detect_properties4 = detector.analyzer();
 
-    EXPECT_NEAR(detect_properties4.analyzerEfficiency(), efficiency, 1e-8);
-    EXPECT_NEAR(detect_properties4.analyzerTotalTransmission(), total_transmission, 1e-8);
-    EXPECT_NEAR(detect_properties4.analyzerDirection().x(), unit_direction.x(), 1e-8);
-    EXPECT_NEAR(detect_properties4.analyzerDirection().y(), unit_direction.y(), 1e-8);
-    EXPECT_NEAR(detect_properties4.analyzerDirection().z(), unit_direction.z(), 1e-8);
+    EXPECT_NEAR(detect_properties4.polEfficiency(), efficiency, 1e-8);
+    EXPECT_NEAR(detect_properties4.totalTransmission(), total_transmission, 1e-8);
+    EXPECT_NEAR(detect_properties4.polDirection().x(), unit_direction.x(), 1e-8);
+    EXPECT_NEAR(detect_properties4.polDirection().y(), unit_direction.y(), 1e-8);
+    EXPECT_NEAR(detect_properties4.polDirection().z(), unit_direction.z(), 1e-8);
 
     // maximum efficiency and negative efficiency
     direction = kvector_t(0.0, -1.0, -1.0);
     efficiency = -1.0;
     total_transmission = 0.5;
     unit_direction = direction.unit();
-    detector.setAnalyzerProperties(direction, efficiency, total_transmission);
-    const DetectionProperties& detect_properties5 = detector.detectionProperties();
-
-    EXPECT_NEAR(detect_properties5.analyzerEfficiency(), efficiency, 1e-8);
-    EXPECT_NEAR(detect_properties5.analyzerTotalTransmission(), total_transmission, 1e-8);
-    EXPECT_NEAR(detect_properties5.analyzerDirection().x(), unit_direction.x(), 1e-8);
-    EXPECT_NEAR(detect_properties5.analyzerDirection().y(), unit_direction.y(), 1e-8);
-    EXPECT_NEAR(detect_properties5.analyzerDirection().z(), unit_direction.z(), 1e-8);
+    detector.setAnalyzer(direction, efficiency, total_transmission);
+    const PolFilter& detect_properties5 = detector.analyzer();
+
+    EXPECT_NEAR(detect_properties5.polEfficiency(), efficiency, 1e-8);
+    EXPECT_NEAR(detect_properties5.totalTransmission(), total_transmission, 1e-8);
+    EXPECT_NEAR(detect_properties5.polDirection().x(), unit_direction.x(), 1e-8);
+    EXPECT_NEAR(detect_properties5.polDirection().y(), unit_direction.y(), 1e-8);
+    EXPECT_NEAR(detect_properties5.polDirection().z(), unit_direction.z(), 1e-8);
 }
diff --git a/Wrap/Python/bornagain_python_install.py b/Wrap/Python/bornagain_python_install.py
index a3952a0959af58a93594ec929686ffbc0daf7189..c52e391e96a5d0085f8b3cee8198d159fde84866 100755
--- a/Wrap/Python/bornagain_python_install.py
+++ b/Wrap/Python/bornagain_python_install.py
@@ -1,5 +1,4 @@
 #!/usr/bin/env python3
-
 """
 Installs BornAgain libraries into user Python (Mac only).
 
diff --git a/Wrap/Swig/libBornAgainDevice.i b/Wrap/Swig/libBornAgainDevice.i
index c2d2eaedb1902ce615b4de2363d7320175a00e51..f648a3d1ec5d2c62664dc1353c7e4543ee140de2 100644
--- a/Wrap/Swig/libBornAgainDevice.i
+++ b/Wrap/Swig/libBornAgainDevice.i
@@ -34,6 +34,7 @@
  };
 
 %{
+#include "Base/Element/PolMatrices.h"
 #include "Param/Distrib/ParameterDistribution.h"
 #include "Device/Beam/Beam.h"
 #include "Device/Beam/FootprintGauss.h"
@@ -47,11 +48,12 @@
 #include "Device/Histo/Histogram2D.h"
 #include "Device/Histo/IntensityDataIOFactory.h"
 #include "Device/Histo/SimulationResult.h"
+#include "Device/Instrument/Instrument.h"
 #include "Device/Mask/Ellipse.h"
 #include "Device/Mask/Line.h"
 #include "Device/Mask/Polygon.h"
 #include "Device/Mask/Rectangle.h"
-#include "Device/ProDetector/DetectorMask.h"
+#include "Device/Mask/DetectorMask.h"
 #include "Device/Resolution/IDetectorResolution.h"
 #include "Device/Resolution/ResolutionFunction2DGaussian.h"
 #include "Device/Resolution/ScanResolution.h"
@@ -101,13 +103,15 @@
 
 %include "Device/Coord/Axes.h"
 
-%include "Device/ProDetector/DetectorMask.h"
+%include "Device/Mask/DetectorMask.h"
 %include "Device/Detector/IDetector.h"
 %include "Device/Detector/IDetector2D.h"
 %include "Device/Detector/RectangularDetector.h"
 %include "Device/Detector/SphericalDetector.h"
 %include "Device/Detector/IsGISAXSDetector.h"
 
+%include "Device/Instrument/Instrument.h"
+
 %include "Device/Histo/HistoUtils.h"
 %include "Device/Histo/IHistogram.h"
 %include "Device/Histo/Histogram1D.h"
diff --git a/auto/Wrap/doxygenBase.i b/auto/Wrap/doxygenBase.i
index 128e1c61366004565f1ec757d0ec25db1aa2aee2..1bb99222f8a6f7f2c827d97f982251f1889b5ef1 100644
--- a/auto/Wrap/doxygenBase.i
+++ b/auto/Wrap/doxygenBase.i
@@ -434,104 +434,6 @@ Set calculation flag (if it's false, zero intensity is assigned to the element)
 ";
 
 
-// File: classDiffuseElement.xml
-%feature("docstring") DiffuseElement "
-
-Data stucture containing both input and output of a single detector cell.
-
-C++ includes: DiffuseElement.h
-";
-
-%feature("docstring")  DiffuseElement::DiffuseElement "DiffuseElement::DiffuseElement(double wavelength, double alpha_i, double phi_i, std::unique_ptr< IPixel > pixel, const Eigen::Matrix2cd &beam_polpair, const Eigen::Matrix2cd &analyzer, bool isSpecular_, const Fluxes *const fluxes_in=nullptr, const Fluxes *const fluxes_out=nullptr)
-";
-
-%feature("docstring")  DiffuseElement::DiffuseElement "DiffuseElement::DiffuseElement(const DiffuseElement &)=delete
-";
-
-%feature("docstring")  DiffuseElement::DiffuseElement "DiffuseElement::DiffuseElement(DiffuseElement &&)
-";
-
-%feature("docstring")  DiffuseElement::~DiffuseElement "DiffuseElement::~DiffuseElement()
-";
-
-%feature("docstring")  DiffuseElement::setFluxes "void DiffuseElement::setFluxes(const Fluxes *fluxes_in, const Fluxes *fluxes_out)
-";
-
-%feature("docstring")  DiffuseElement::fluxIn "const IFlux * DiffuseElement::fluxIn(size_t i_layer) const
-";
-
-%feature("docstring")  DiffuseElement::fluxOut "const IFlux * DiffuseElement::fluxOut(size_t i_layer) const
-";
-
-%feature("docstring")  DiffuseElement::pointElement "DiffuseElement DiffuseElement::pointElement(double x, double y) const
-
-Returns copy of this  DiffuseElement with k_f given by in-pixel coordinate x,y. 
-";
-
-%feature("docstring")  DiffuseElement::polarizationHandler "const PolarizerPair& DiffuseElement::polarizationHandler() const
-
-Returns assigned  PolarizerPair. 
-";
-
-%feature("docstring")  DiffuseElement::wavelength "double DiffuseElement::wavelength() const
-";
-
-%feature("docstring")  DiffuseElement::getAlphaI "double DiffuseElement::getAlphaI() const
-";
-
-%feature("docstring")  DiffuseElement::getPhiI "double DiffuseElement::getPhiI() const
-";
-
-%feature("docstring")  DiffuseElement::getAlphaMean "double DiffuseElement::getAlphaMean() const
-";
-
-%feature("docstring")  DiffuseElement::getPhiMean "double DiffuseElement::getPhiMean() const
-";
-
-%feature("docstring")  DiffuseElement::setIntensity "void DiffuseElement::setIntensity(double intensity)
-";
-
-%feature("docstring")  DiffuseElement::addIntensity "void DiffuseElement::addIntensity(double intensity)
-";
-
-%feature("docstring")  DiffuseElement::intensity "double DiffuseElement::intensity() const
-";
-
-%feature("docstring")  DiffuseElement::getKi "kvector_t DiffuseElement::getKi() const
-";
-
-%feature("docstring")  DiffuseElement::getMeanKf "kvector_t DiffuseElement::getMeanKf() const
-";
-
-%feature("docstring")  DiffuseElement::meanQ "kvector_t DiffuseElement::meanQ() const
-";
-
-%feature("docstring")  DiffuseElement::getQ "kvector_t DiffuseElement::getQ(double x, double y) const
-
-Returns scattering vector Q, with Kf determined from in-pixel coordinates x,y. In-pixel coordinates take values from 0 to 1. 
-";
-
-%feature("docstring")  DiffuseElement::integrationFactor "double DiffuseElement::integrationFactor(double x, double y) const
-";
-
-%feature("docstring")  DiffuseElement::solidAngle "double DiffuseElement::solidAngle() const
-";
-
-%feature("docstring")  DiffuseElement::getAlpha "double DiffuseElement::getAlpha(double x, double y) const
-";
-
-%feature("docstring")  DiffuseElement::getPhi "double DiffuseElement::getPhi(double x, double y) const
-";
-
-%feature("docstring")  DiffuseElement::wavevectorInfo "WavevectorInfo DiffuseElement::wavevectorInfo() const
-";
-
-%feature("docstring")  DiffuseElement::isSpecular "bool DiffuseElement::isSpecular() const
-
-Tells if simulation element corresponds to a specular peak. 
-";
-
-
 // File: classDirection.xml
 %feature("docstring") Direction "
 
@@ -815,7 +717,7 @@ Used for Python overriding of clone (see swig/tweaks.py)
 // File: classIElement.xml
 %feature("docstring") IElement "";
 
-%feature("docstring")  IElement::IElement "IElement::IElement(const PolarizerPair &polpair)
+%feature("docstring")  IElement::IElement "IElement::IElement(const PolMatrices &polpair)
 ";
 
 
@@ -969,43 +871,40 @@ Clips this axis to the given values.
 ";
 
 
-// File: classPolarizerPair.xml
-%feature("docstring") PolarizerPair "
+// File: classPolMatrices.xml
+%feature("docstring") PolMatrices "
 
 Convenience class for handling polarization density matrix and polarization analyzer operator
 
-C++ includes: PolarizerPair.h
+C++ includes: PolMatrices.h
 ";
 
-%feature("docstring")  PolarizerPair::PolarizerPair "PolarizerPair::PolarizerPair()
+%feature("docstring")  PolMatrices::PolMatrices "PolMatrices::PolMatrices()
 ";
 
-%feature("docstring")  PolarizerPair::PolarizerPair "PolarizerPair::PolarizerPair(const Eigen::Matrix2cd &polarization, const Eigen::Matrix2cd &analyzer)
+%feature("docstring")  PolMatrices::PolMatrices "PolMatrices::PolMatrices(const Eigen::Matrix2cd &polarization, const Eigen::Matrix2cd &analyzer)
 ";
 
-%feature("docstring")  PolarizerPair::setPolarization "void PolarizerPair::setPolarization(const Eigen::Matrix2cd &polarization)
+%feature("docstring")  PolMatrices::setPolarizerMatrix "void PolMatrices::setPolarizerMatrix(const Eigen::Matrix2cd &polarization)
 
 Sets the polarization density matrix (in spin basis along z-axis) 
 ";
 
-%feature("docstring")  PolarizerPair::getPolarization "Eigen::Matrix2cd PolarizerPair::getPolarization() const
+%feature("docstring")  PolMatrices::polarizerMatrix "Eigen::Matrix2cd PolMatrices::polarizerMatrix() const
 
 Gets the polarization density matrix (in spin basis along z-axis) 
 ";
 
-%feature("docstring")  PolarizerPair::setAnalyzerOperator "void PolarizerPair::setAnalyzerOperator(const Eigen::Matrix2cd &analyzer)
+%feature("docstring")  PolMatrices::setAnalyzerMatrix "void PolMatrices::setAnalyzerMatrix(const Eigen::Matrix2cd &analyzer)
 
 Sets the polarization analyzer operator (in spin basis along z-axis) 
 ";
 
-%feature("docstring")  PolarizerPair::getAnalyzerOperator "Eigen::Matrix2cd PolarizerPair::getAnalyzerOperator() const
+%feature("docstring")  PolMatrices::analyzerMatrix "Eigen::Matrix2cd PolMatrices::analyzerMatrix() const
 
 Gets the polarization analyzer operator (in spin basis along z-axis) 
 ";
 
-%feature("docstring")  PolarizerPair::swapContent "void PolarizerPair::swapContent(PolarizerPair &other)
-";
-
 
 // File: classProgressHandler.xml
 %feature("docstring") ProgressHandler "
@@ -1385,7 +1284,7 @@ C++ includes: WavevectorInfo.h
 // File: classFourierTransform_1_1Workspace.xml
 
 
-// File: namespace_0d23.xml
+// File: namespace_0d21.xml
 
 
 // File: namespaceBaseUtils.xml
@@ -1870,19 +1769,13 @@ Checks if value is contained in bin: value in [m_lower, m_upper)
 // File: DepthProbeElement_8h.xml
 
 
-// File: DiffuseElement_8cpp.xml
-
-
-// File: DiffuseElement_8h.xml
-
-
 // File: IElement_8h.xml
 
 
-// File: PolarizerPair_8cpp.xml
+// File: PolMatrices_8cpp.xml
 
 
-// File: PolarizerPair_8h.xml
+// File: PolMatrices_8h.xml
 
 
 // File: Bessel_8cpp.xml
diff --git a/auto/Wrap/doxygenCore.i b/auto/Wrap/doxygenCore.i
index 2ceac7cc006f9f49e68b68a8ab71c83d7330ed49..1b0279059af4eff932154f57d3720ff59d4c2728 100644
--- a/auto/Wrap/doxygenCore.i
+++ b/auto/Wrap/doxygenCore.i
@@ -26,7 +26,7 @@ Sets angle-defined specular scan. The first parameter is always a wavelength in
 %feature("docstring")  AlphaScan::clone "AlphaScan * AlphaScan::clone() const override
 ";
 
-%feature("docstring")  AlphaScan::generateElements "std::vector< SpecularElement > AlphaScan::generateElements(const PolarizerPair &polpair) const override
+%feature("docstring")  AlphaScan::generateElements "std::vector< SpecularElement > AlphaScan::generateElements(const PolMatrices &polpair) const override
 
 Generates simulation elements for specular simulations. 
 ";
@@ -936,9 +936,6 @@ The MultiLayer object will not be owned by the  ISimulation object.
 %feature("docstring")  ISimulation::setSampleBuilder "void ISimulation::setSampleBuilder(const std::shared_ptr< ISampleBuilder > &sample_builder)
 ";
 
-%feature("docstring")  ISimulation::polarizerPair "PolarizerPair ISimulation::polarizerPair() const
-";
-
 %feature("docstring")  ISimulation::setBackground "void ISimulation::setBackground(const IBackground &bg)
 ";
 
@@ -973,7 +970,7 @@ Returns the results of the simulation in a format that supports unit conversion
 %feature("docstring")  ISimulation::options "SimulationOptions & ISimulation::options()
 ";
 
-%feature("docstring")  ISimulation::subscribe "void ISimulation::subscribe(ProgressHandler::Callback_t inform)
+%feature("docstring")  ISimulation::subscribe "void ISimulation::subscribe(const std::function< bool(size_t)> &inform)
 ";
 
 %feature("docstring")  ISimulation::setTerminalProgressMonitor "void ISimulation::setTerminalProgressMonitor()
@@ -1087,7 +1084,7 @@ C++ includes: ISpecularScan.h
 %feature("docstring")  ISpecularScan::clone "ISpecularScan* ISpecularScan::clone() const override=0
 ";
 
-%feature("docstring")  ISpecularScan::generateElements "virtual std::vector<SpecularElement> ISpecularScan::generateElements(const PolarizerPair &polpair) const =0
+%feature("docstring")  ISpecularScan::generateElements "virtual std::vector<SpecularElement> ISpecularScan::generateElements(const PolMatrices &polpair) const =0
 
 Generates simulation elements for specular simulations. 
 ";
@@ -1562,7 +1559,7 @@ Sets q-defined specular scan. Accepts either numpy array of q-values sorted in a
 %feature("docstring")  QzScan::resolution "const ScanResolution* QzScan::resolution() const
 ";
 
-%feature("docstring")  QzScan::generateElements "std::vector< SpecularElement > QzScan::generateElements(const PolarizerPair &polpair) const override
+%feature("docstring")  QzScan::generateElements "std::vector< SpecularElement > QzScan::generateElements(const PolMatrices &polpair) const override
 
 Generates simulation elements for specular simulations. 
 ";
@@ -2129,7 +2126,7 @@ Basic GISAS simulation with the detector phi[0,2], theta[0,2].
 Basic GISAS for polarization studies. 
 ";
 
-%feature("docstring")  StandardSimulations::BasicPolarizedGISAS "GISASSimulation * StandardSimulations::BasicPolarizedGISAS()
+%feature("docstring")  StandardSimulations::SpinflipGISAS "GISASSimulation * StandardSimulations::SpinflipGISAS()
 
 Basic GISAS simulation for spin flip channel. 
 ";
diff --git a/auto/Wrap/doxygenDevice.i b/auto/Wrap/doxygenDevice.i
index 24dbfa4968d39022355c06bb209d19aae8fe9911..1d5081d71b05df2591153687cc4cc0a442c987fa 100644
--- a/auto/Wrap/doxygenDevice.i
+++ b/auto/Wrap/doxygenDevice.i
@@ -371,53 +371,6 @@ Returns the list of all available units.
 ";
 
 
-// File: classDetectionProperties.xml
-%feature("docstring") DetectionProperties "
-
-Detector properties (efficiency, transmission).
-
-C++ includes: DetectionProperties.h
-";
-
-%feature("docstring")  DetectionProperties::DetectionProperties "DetectionProperties::DetectionProperties(kvector_t direction, double efficiency, double total_transmission)
-";
-
-%feature("docstring")  DetectionProperties::DetectionProperties "DetectionProperties::DetectionProperties()
-";
-
-%feature("docstring")  DetectionProperties::DetectionProperties "DetectionProperties::DetectionProperties(const DetectionProperties &other)
-";
-
-%feature("docstring")  DetectionProperties::~DetectionProperties "virtual DetectionProperties::~DetectionProperties()=default
-";
-
-%feature("docstring")  DetectionProperties::setAnalyzerProperties "void DetectionProperties::setAnalyzerProperties(const kvector_t direction, double efficiency, double total_transmission)
-
-Sets the polarization analyzer characteristics of the detector. 
-";
-
-%feature("docstring")  DetectionProperties::analyzerOperator "Eigen::Matrix2cd DetectionProperties::analyzerOperator() const
-
-Return the polarization density matrix (in spin basis along z-axis) 
-";
-
-%feature("docstring")  DetectionProperties::analyzerDirection "kvector_t DetectionProperties::analyzerDirection() const
-
-Retrieve the analyzer characteristics. 
-";
-
-%feature("docstring")  DetectionProperties::analyzerEfficiency "double DetectionProperties::analyzerEfficiency() const
-
-will always return positive value 
-";
-
-%feature("docstring")  DetectionProperties::analyzerTotalTransmission "double DetectionProperties::analyzerTotalTransmission() const
-";
-
-%feature("docstring")  DetectionProperties::accept "void DetectionProperties::accept(INodeVisitor *visitor) const override
-";
-
-
 // File: classDetectorContext.xml
 %feature("docstring") DetectorContext "
 
@@ -989,7 +942,7 @@ Inits detector with the beam settings.
 %feature("docstring")  IDetector::addAxis "void IDetector::addAxis(const IAxis &axis)
 ";
 
-%feature("docstring")  IDetector::setAnalyzerProperties "void IDetector::setAnalyzerProperties(const kvector_t direction, double efficiency, double total_transmission)
+%feature("docstring")  IDetector::setAnalyzer "void IDetector::setAnalyzer(const kvector_t direction, double efficiency, double total_transmission)
 
 Sets the polarization analyzer characteristics of the detector. 
 ";
@@ -1108,7 +1061,7 @@ Returns a pointer to detector resolution object.
 Returns empty detector map in given axes units. This map is a data array limited to the size of the \"Region of interest\" 
 ";
 
-%feature("docstring")  IDetector::detectionProperties "const DetectionProperties& IDetector::detectionProperties() const
+%feature("docstring")  IDetector::analyzer "const PolFilter& IDetector::analyzer() const
 
 Returns detection properties. 
 ";
@@ -1620,6 +1573,12 @@ Sets the detector (axes can be overwritten later)
 init detector with beam settings 
 ";
 
+%feature("docstring")  Instrument::setPolFilters "void Instrument::setPolFilters(const kvector_t &polarizer_dir, const kvector_t &analyzer_dir, double analyzer_efficiency, double analyzer_transmission)
+";
+
+%feature("docstring")  Instrument::polarizerPair "PolMatrices Instrument::polarizerPair() const
+";
+
 %feature("docstring")  Instrument::getChildren "std::vector< const INode * > Instrument::getChildren() const override
 ";
 
@@ -2206,6 +2165,53 @@ C++ includes: OutputDataReadWriteNumpyTXT.h
 ";
 
 
+// File: classPolFilter.xml
+%feature("docstring") PolFilter "
+
+Detector properties (efficiency, transmission).
+
+C++ includes: PolFilter.h
+";
+
+%feature("docstring")  PolFilter::PolFilter "PolFilter::PolFilter(kvector_t direction, double efficiency, double total_transmission)
+";
+
+%feature("docstring")  PolFilter::PolFilter "PolFilter::PolFilter()
+";
+
+%feature("docstring")  PolFilter::PolFilter "PolFilter::PolFilter(const PolFilter &other)
+";
+
+%feature("docstring")  PolFilter::~PolFilter "virtual PolFilter::~PolFilter()=default
+";
+
+%feature("docstring")  PolFilter::setDirEffTra "void PolFilter::setDirEffTra(const kvector_t direction, double efficiency, double total_transmission)
+
+Sets the polarization analyzer characteristics of the detector. 
+";
+
+%feature("docstring")  PolFilter::matrix "Eigen::Matrix2cd PolFilter::matrix() const
+
+Return the polarization density matrix (in spin basis along z-axis) 
+";
+
+%feature("docstring")  PolFilter::polDirection "kvector_t PolFilter::polDirection() const
+
+Retrieve the analyzer characteristics. 
+";
+
+%feature("docstring")  PolFilter::polEfficiency "double PolFilter::polEfficiency() const
+
+will always return positive value 
+";
+
+%feature("docstring")  PolFilter::totalTransmission "double PolFilter::totalTransmission() const
+";
+
+%feature("docstring")  PolFilter::accept "void PolFilter::accept(INodeVisitor *visitor) const override
+";
+
+
 // File: classPolygon.xml
 %feature("docstring") Polygon "
 
@@ -3227,6 +3233,12 @@ make Swappable
 // File: Instrument_8h.xml
 
 
+// File: DetectorMask_8cpp.xml
+
+
+// File: DetectorMask_8h.xml
+
+
 // File: Ellipse_8cpp.xml
 
 
@@ -3257,16 +3269,10 @@ make Swappable
 // File: Rectangle_8h.xml
 
 
-// File: DetectionProperties_8cpp.xml
-
+// File: PolFilter_8cpp.xml
 
-// File: DetectionProperties_8h.xml
 
-
-// File: DetectorMask_8cpp.xml
-
-
-// File: DetectorMask_8h.xml
+// File: PolFilter_8h.xml
 
 
 // File: ConvolutionDetectorResolution_8cpp.xml
@@ -3332,7 +3338,7 @@ make Swappable
 // File: dir_4866552d576e04b61ad8ade47c8db877.xml
 
 
-// File: dir_da994f4366e479a3c15631d7a5d6d07d.xml
+// File: dir_6f4ccf6b1bfd53aaa1440d548704c25a.xml
 
 
 // File: dir_aa6451b5aab7f40a79bc1a0dc7cac3c6.xml
diff --git a/auto/Wrap/doxygenResample.i b/auto/Wrap/doxygenResample.i
index 0636ab8e166777b445323beb432ffa19076a5446..5212a995982317bd2238620b5258b5594d6ae80c 100644
--- a/auto/Wrap/doxygenResample.i
+++ b/auto/Wrap/doxygenResample.i
@@ -71,7 +71,7 @@ C++ includes: DiffuseElement.h
 Returns copy of this  DiffuseElement with k_f given by in-pixel coordinate x,y. 
 ";
 
-%feature("docstring")  DiffuseElement::polarizationHandler "const PolarizerPair& DiffuseElement::polarizationHandler() const
+%feature("docstring")  DiffuseElement::polarizationHandler "const PolMatrices& DiffuseElement::polarizationHandler() const
 
 Returns assigned PolarizerPair. 
 ";
@@ -702,10 +702,10 @@ Data stucture containing both input and output of a single image pixel for specu
 C++ includes: SpecularElement.h
 ";
 
-%feature("docstring")  SpecularElement::SpecularElement "SpecularElement::SpecularElement(double kz, const PolarizerPair &polpair, bool computable)
+%feature("docstring")  SpecularElement::SpecularElement "SpecularElement::SpecularElement(double kz, const PolMatrices &polpair, bool computable)
 ";
 
-%feature("docstring")  SpecularElement::SpecularElement "SpecularElement::SpecularElement(double wavelength, double alpha, const PolarizerPair &polpair, bool computable)
+%feature("docstring")  SpecularElement::SpecularElement "SpecularElement::SpecularElement(double wavelength, double alpha, const PolMatrices &polpair, bool computable)
 ";
 
 %feature("docstring")  SpecularElement::SpecularElement "SpecularElement::SpecularElement(const SpecularElement &other)=delete
@@ -717,7 +717,7 @@ C++ includes: SpecularElement.h
 %feature("docstring")  SpecularElement::~SpecularElement "SpecularElement::~SpecularElement()
 ";
 
-%feature("docstring")  SpecularElement::polarizationHandler "const PolarizerPair& SpecularElement::polarizationHandler() const
+%feature("docstring")  SpecularElement::polarizationHandler "const PolMatrices& SpecularElement::polarizationHandler() const
 
 Returns assigned PolarizerPair. 
 ";
diff --git a/auto/Wrap/libBornAgainCore.py b/auto/Wrap/libBornAgainCore.py
index d5efed45890b63daef244c9d3146db45db6e8819..3aa9469ec035b5284e283c58a61abd08c79208e5 100644
--- a/auto/Wrap/libBornAgainCore.py
+++ b/auto/Wrap/libBornAgainCore.py
@@ -3526,14 +3526,6 @@ class ISimulation(libBornAgainParam.INode):
         """
         return _libBornAgainCore.ISimulation_setSampleBuilderCpp(self, sample_builder)
 
-    def polarizerPair(self):
-        r"""
-        polarizerPair(ISimulation self) -> PolarizerPair
-        PolarizerPair ISimulation::polarizerPair() const
-
-        """
-        return _libBornAgainCore.ISimulation_polarizerPair(self)
-
     def setBackground(self, bg):
         r"""
         setBackground(ISimulation self, IBackground bg)
@@ -3606,8 +3598,8 @@ class ISimulation(libBornAgainParam.INode):
 
     def subscribe(self, inform):
         r"""
-        subscribe(ISimulation self, ProgressHandler::Callback_t inform)
-        void ISimulation::subscribe(ProgressHandler::Callback_t inform)
+        subscribe(ISimulation self, std::function< bool (size_t) > const & inform)
+        void ISimulation::subscribe(const std::function< bool(size_t)> &inform)
 
         """
         return _libBornAgainCore.ISimulation_subscribe(self, inform)
diff --git a/auto/Wrap/libBornAgainCore_wrap.cpp b/auto/Wrap/libBornAgainCore_wrap.cpp
index 5fe2f85b14a4c50c07f68354d88f3a6c348a0e30..ebbc31d8e0f5f5b186642a9239c04d173203cb55 100644
--- a/auto/Wrap/libBornAgainCore_wrap.cpp
+++ b/auto/Wrap/libBornAgainCore_wrap.cpp
@@ -3137,75 +3137,74 @@ namespace Swig {
 #define SWIGTYPE_p_OffSpecularSimulation swig_types[37]
 #define SWIGTYPE_p_ParameterDistribution swig_types[38]
 #define SWIGTYPE_p_PoissonNoiseBackground swig_types[39]
-#define SWIGTYPE_p_PolarizerPair swig_types[40]
-#define SWIGTYPE_p_ProgressHandler__Callback_t swig_types[41]
-#define SWIGTYPE_p_PyBuilderCallback swig_types[42]
-#define SWIGTYPE_p_PyObserverCallback swig_types[43]
-#define SWIGTYPE_p_QzScan swig_types[44]
-#define SWIGTYPE_p_RealLimits swig_types[45]
-#define SWIGTYPE_p_ScanResolution swig_types[46]
-#define SWIGTYPE_p_SimulationOptions swig_types[47]
-#define SWIGTYPE_p_SimulationResult swig_types[48]
-#define SWIGTYPE_p_SpecularSimulation swig_types[49]
-#define SWIGTYPE_p_VarianceConstantFunction swig_types[50]
-#define SWIGTYPE_p_VarianceSimFunction swig_types[51]
-#define SWIGTYPE_p_allocator_type swig_types[52]
-#define SWIGTYPE_p_char swig_types[53]
-#define SWIGTYPE_p_difference_type swig_types[54]
-#define SWIGTYPE_p_first_type swig_types[55]
-#define SWIGTYPE_p_int swig_types[56]
-#define SWIGTYPE_p_key_type swig_types[57]
-#define SWIGTYPE_p_long_long swig_types[58]
-#define SWIGTYPE_p_mapped_type swig_types[59]
-#define SWIGTYPE_p_mumufit__MinimizerResult swig_types[60]
-#define SWIGTYPE_p_mumufit__Parameters 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_ISampleBuilder_t swig_types[86]
-#define SWIGTYPE_p_std__vectorT_AxisInfo_std__allocatorT_AxisInfo_t_t swig_types[87]
-#define SWIGTYPE_p_std__vectorT_BasicVector3DT_double_t_std__allocatorT_BasicVector3DT_double_t_t_t swig_types[88]
-#define SWIGTYPE_p_std__vectorT_BasicVector3DT_std__complexT_double_t_t_std__allocatorT_BasicVector3DT_std__complexT_double_t_t_t_t swig_types[89]
-#define SWIGTYPE_p_std__vectorT_INode_const_p_std__allocatorT_INode_const_p_t_t swig_types[90]
-#define SWIGTYPE_p_std__vectorT_INode_p_std__allocatorT_INode_p_t_t swig_types[91]
-#define SWIGTYPE_p_std__vectorT_ParameterDistribution_std__allocatorT_ParameterDistribution_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_PyBuilderCallback swig_types[40]
+#define SWIGTYPE_p_PyObserverCallback swig_types[41]
+#define SWIGTYPE_p_QzScan swig_types[42]
+#define SWIGTYPE_p_RealLimits swig_types[43]
+#define SWIGTYPE_p_ScanResolution swig_types[44]
+#define SWIGTYPE_p_SimulationOptions swig_types[45]
+#define SWIGTYPE_p_SimulationResult swig_types[46]
+#define SWIGTYPE_p_SpecularSimulation swig_types[47]
+#define SWIGTYPE_p_VarianceConstantFunction swig_types[48]
+#define SWIGTYPE_p_VarianceSimFunction swig_types[49]
+#define SWIGTYPE_p_allocator_type swig_types[50]
+#define SWIGTYPE_p_char swig_types[51]
+#define SWIGTYPE_p_difference_type swig_types[52]
+#define SWIGTYPE_p_first_type swig_types[53]
+#define SWIGTYPE_p_int swig_types[54]
+#define SWIGTYPE_p_key_type swig_types[55]
+#define SWIGTYPE_p_long_long swig_types[56]
+#define SWIGTYPE_p_mapped_type swig_types[57]
+#define SWIGTYPE_p_mumufit__MinimizerResult swig_types[58]
+#define SWIGTYPE_p_mumufit__Parameters swig_types[59]
+#define SWIGTYPE_p_p_PyObject swig_types[60]
+#define SWIGTYPE_p_second_type swig_types[61]
+#define SWIGTYPE_p_short swig_types[62]
+#define SWIGTYPE_p_signed_char swig_types[63]
+#define SWIGTYPE_p_size_type swig_types[64]
+#define SWIGTYPE_p_std__allocatorT_AxisInfo_t swig_types[65]
+#define SWIGTYPE_p_std__allocatorT_BasicVector3DT_double_t_t swig_types[66]
+#define SWIGTYPE_p_std__allocatorT_BasicVector3DT_std__complexT_double_t_t_t swig_types[67]
+#define SWIGTYPE_p_std__allocatorT_INode_const_p_t swig_types[68]
+#define SWIGTYPE_p_std__allocatorT_INode_p_t swig_types[69]
+#define SWIGTYPE_p_std__allocatorT_double_t swig_types[70]
+#define SWIGTYPE_p_std__allocatorT_int_t swig_types[71]
+#define SWIGTYPE_p_std__allocatorT_std__complexT_double_t_t swig_types[72]
+#define SWIGTYPE_p_std__allocatorT_std__pairT_double_double_t_t swig_types[73]
+#define SWIGTYPE_p_std__allocatorT_std__pairT_std__string_const_double_t_t swig_types[74]
+#define SWIGTYPE_p_std__allocatorT_std__string_t swig_types[75]
+#define SWIGTYPE_p_std__allocatorT_std__vectorT_double_std__allocatorT_double_t_t_t swig_types[76]
+#define SWIGTYPE_p_std__allocatorT_std__vectorT_int_std__allocatorT_int_t_t_t swig_types[77]
+#define SWIGTYPE_p_std__allocatorT_unsigned_long_t swig_types[78]
+#define SWIGTYPE_p_std__complexT_double_t swig_types[79]
+#define SWIGTYPE_p_std__functionT_bool_fsize_tF_t swig_types[80]
+#define SWIGTYPE_p_std__invalid_argument swig_types[81]
+#define SWIGTYPE_p_std__lessT_std__string_t swig_types[82]
+#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[83]
+#define SWIGTYPE_p_std__pairT_double_double_t swig_types[84]
+#define SWIGTYPE_p_std__shared_ptrT_ISampleBuilder_t swig_types[85]
+#define SWIGTYPE_p_std__vectorT_AxisInfo_std__allocatorT_AxisInfo_t_t swig_types[86]
+#define SWIGTYPE_p_std__vectorT_BasicVector3DT_double_t_std__allocatorT_BasicVector3DT_double_t_t_t swig_types[87]
+#define SWIGTYPE_p_std__vectorT_BasicVector3DT_std__complexT_double_t_t_std__allocatorT_BasicVector3DT_std__complexT_double_t_t_t_t swig_types[88]
+#define SWIGTYPE_p_std__vectorT_INode_const_p_std__allocatorT_INode_const_p_t_t swig_types[89]
+#define SWIGTYPE_p_std__vectorT_INode_p_std__allocatorT_INode_p_t_t swig_types[90]
+#define SWIGTYPE_p_std__vectorT_ParameterDistribution_std__allocatorT_ParameterDistribution_t_t swig_types[91]
+#define SWIGTYPE_p_std__vectorT_double_std__allocatorT_double_t_t swig_types[92]
+#define SWIGTYPE_p_std__vectorT_int_std__allocatorT_int_t_t swig_types[93]
+#define SWIGTYPE_p_std__vectorT_std__complexT_double_t_std__allocatorT_std__complexT_double_t_t_t swig_types[94]
+#define SWIGTYPE_p_std__vectorT_std__pairT_double_double_t_std__allocatorT_std__pairT_double_double_t_t_t swig_types[95]
+#define SWIGTYPE_p_std__vectorT_std__string_std__allocatorT_std__string_t_t swig_types[96]
+#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[97]
+#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[98]
+#define SWIGTYPE_p_std__vectorT_unsigned_long_std__allocatorT_unsigned_long_t_t swig_types[99]
+#define SWIGTYPE_p_swig__SwigPyIterator swig_types[100]
+#define SWIGTYPE_p_unsigned_char swig_types[101]
+#define SWIGTYPE_p_unsigned_int swig_types[102]
+#define SWIGTYPE_p_unsigned_long_long swig_types[103]
+#define SWIGTYPE_p_unsigned_short swig_types[104]
+#define SWIGTYPE_p_value_type swig_types[105]
+static swig_type_info *swig_types[107];
+static swig_module_info swig_module = {swig_types, 106, 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)
 
@@ -39104,29 +39103,6 @@ fail:
 }
 
 
-SWIGINTERN PyObject *_wrap_ISimulation_polarizerPair(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
-  ISimulation *arg1 = (ISimulation *) 0 ;
-  void *argp1 = 0 ;
-  int res1 = 0 ;
-  PyObject *swig_obj[1] ;
-  PolarizerPair result;
-  
-  if (!args) SWIG_fail;
-  swig_obj[0] = args;
-  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_polarizerPair" "', argument " "1"" of type '" "ISimulation const *""'"); 
-  }
-  arg1 = reinterpret_cast< ISimulation * >(argp1);
-  result = ((ISimulation const *)arg1)->polarizerPair();
-  resultobj = SWIG_NewPointerObj((new PolarizerPair(static_cast< const PolarizerPair& >(result))), SWIGTYPE_p_PolarizerPair, SWIG_POINTER_OWN |  0 );
-  return resultobj;
-fail:
-  return NULL;
-}
-
-
 SWIGINTERN PyObject *_wrap_ISimulation_setBackground(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
   PyObject *resultobj = 0;
   ISimulation *arg1 = (ISimulation *) 0 ;
@@ -39687,10 +39663,10 @@ fail:
 SWIGINTERN PyObject *_wrap_ISimulation_subscribe(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
   PyObject *resultobj = 0;
   ISimulation *arg1 = (ISimulation *) 0 ;
-  ProgressHandler::Callback_t arg2 ;
+  std::function< bool (size_t) > *arg2 = 0 ;
   void *argp1 = 0 ;
   int res1 = 0 ;
-  void *argp2 ;
+  void *argp2 = 0 ;
   int res2 = 0 ;
   PyObject *swig_obj[2] ;
   
@@ -39700,20 +39676,15 @@ SWIGINTERN PyObject *_wrap_ISimulation_subscribe(PyObject *SWIGUNUSEDPARM(self),
     SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "ISimulation_subscribe" "', argument " "1"" of type '" "ISimulation *""'"); 
   }
   arg1 = reinterpret_cast< ISimulation * >(argp1);
-  {
-    res2 = SWIG_ConvertPtr(swig_obj[1], &argp2, SWIGTYPE_p_ProgressHandler__Callback_t,  0  | 0);
-    if (!SWIG_IsOK(res2)) {
-      SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "ISimulation_subscribe" "', argument " "2"" of type '" "ProgressHandler::Callback_t""'"); 
-    }  
-    if (!argp2) {
-      SWIG_exception_fail(SWIG_ValueError, "invalid null reference " "in method '" "ISimulation_subscribe" "', argument " "2"" of type '" "ProgressHandler::Callback_t""'");
-    } else {
-      ProgressHandler::Callback_t * temp = reinterpret_cast< ProgressHandler::Callback_t * >(argp2);
-      arg2 = *temp;
-      if (SWIG_IsNewObj(res2)) delete temp;
-    }
+  res2 = SWIG_ConvertPtr(swig_obj[1], &argp2, SWIGTYPE_p_std__functionT_bool_fsize_tF_t,  0  | 0);
+  if (!SWIG_IsOK(res2)) {
+    SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "ISimulation_subscribe" "', argument " "2"" of type '" "std::function< bool (size_t) > const &""'"); 
   }
-  (arg1)->subscribe(arg2);
+  if (!argp2) {
+    SWIG_exception_fail(SWIG_ValueError, "invalid null reference " "in method '" "ISimulation_subscribe" "', argument " "2"" of type '" "std::function< bool (size_t) > const &""'"); 
+  }
+  arg2 = reinterpret_cast< std::function< bool (size_t) > * >(argp2);
+  (arg1)->subscribe((std::function< bool (size_t) > const &)*arg2);
   resultobj = SWIG_Py_Void();
   return resultobj;
 fail:
@@ -44263,11 +44234,6 @@ static PyMethodDef SwigMethods[] = {
 		"void ISimulation::setSampleBuilder(const std::shared_ptr< ISampleBuilder > &sample_builder)\n"
 		"\n"
 		""},
-	 { "ISimulation_polarizerPair", _wrap_ISimulation_polarizerPair, METH_O, "\n"
-		"ISimulation_polarizerPair(ISimulation self) -> PolarizerPair\n"
-		"PolarizerPair ISimulation::polarizerPair() const\n"
-		"\n"
-		""},
 	 { "ISimulation_setBackground", _wrap_ISimulation_setBackground, METH_VARARGS, "\n"
 		"ISimulation_setBackground(ISimulation self, IBackground bg)\n"
 		"void ISimulation::setBackground(const IBackground &bg)\n"
@@ -44315,8 +44281,8 @@ static PyMethodDef SwigMethods[] = {
 		"\n"
 		""},
 	 { "ISimulation_subscribe", _wrap_ISimulation_subscribe, METH_VARARGS, "\n"
-		"ISimulation_subscribe(ISimulation self, ProgressHandler::Callback_t inform)\n"
-		"void ISimulation::subscribe(ProgressHandler::Callback_t inform)\n"
+		"ISimulation_subscribe(ISimulation self, std::function< bool (size_t) > const & inform)\n"
+		"void ISimulation::subscribe(const std::function< bool(size_t)> &inform)\n"
 		"\n"
 		""},
 	 { "ISimulation_setTerminalProgressMonitor", _wrap_ISimulation_setTerminalProgressMonitor, METH_O, "\n"
@@ -45096,8 +45062,6 @@ static swig_type_info _swigt__p_MultiLayer = {"_p_MultiLayer", "MultiLayer *", 0
 static swig_type_info _swigt__p_OffSpecularSimulation = {"_p_OffSpecularSimulation", "OffSpecularSimulation *", 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};
-static swig_type_info _swigt__p_PolarizerPair = {"_p_PolarizerPair", "PolarizerPair *", 0, 0, (void*)0, 0};
-static swig_type_info _swigt__p_ProgressHandler__Callback_t = {"_p_ProgressHandler__Callback_t", "ProgressHandler::Callback_t *", 0, 0, (void*)0, 0};
 static swig_type_info _swigt__p_PyBuilderCallback = {"_p_PyBuilderCallback", "PyBuilderCallback *", 0, 0, (void*)0, 0};
 static swig_type_info _swigt__p_PyObserverCallback = {"_p_PyObserverCallback", "PyObserverCallback *", 0, 0, (void*)0, 0};
 static swig_type_info _swigt__p_QzScan = {"_p_QzScan", "QzScan *", 0, 0, (void*)0, 0};
@@ -45138,6 +45102,7 @@ static swig_type_info _swigt__p_std__allocatorT_std__vectorT_double_std__allocat
 static swig_type_info _swigt__p_std__allocatorT_std__vectorT_int_std__allocatorT_int_t_t_t = {"_p_std__allocatorT_std__vectorT_int_std__allocatorT_int_t_t_t", "std::vector< std::vector< int > >::allocator_type *|std::allocator< std::vector< int,std::allocator< int > > > *", 0, 0, (void*)0, 0};
 static swig_type_info _swigt__p_std__allocatorT_unsigned_long_t = {"_p_std__allocatorT_unsigned_long_t", "std::vector< unsigned long >::allocator_type *|std::allocator< unsigned long > *", 0, 0, (void*)0, 0};
 static swig_type_info _swigt__p_std__complexT_double_t = {"_p_std__complexT_double_t", "complex_t *|std::complex< double > *", 0, 0, (void*)0, 0};
+static swig_type_info _swigt__p_std__functionT_bool_fsize_tF_t = {"_p_std__functionT_bool_fsize_tF_t", "std::function< bool (size_t) > *", 0, 0, (void*)0, 0};
 static swig_type_info _swigt__p_std__invalid_argument = {"_p_std__invalid_argument", "std::invalid_argument *", 0, 0, (void*)0, 0};
 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};
@@ -45205,8 +45170,6 @@ static swig_type_info *swig_type_initial[] = {
   &_swigt__p_OffSpecularSimulation,
   &_swigt__p_ParameterDistribution,
   &_swigt__p_PoissonNoiseBackground,
-  &_swigt__p_PolarizerPair,
-  &_swigt__p_ProgressHandler__Callback_t,
   &_swigt__p_PyBuilderCallback,
   &_swigt__p_PyObserverCallback,
   &_swigt__p_QzScan,
@@ -45247,6 +45210,7 @@ static swig_type_info *swig_type_initial[] = {
   &_swigt__p_std__allocatorT_std__vectorT_int_std__allocatorT_int_t_t_t,
   &_swigt__p_std__allocatorT_unsigned_long_t,
   &_swigt__p_std__complexT_double_t,
+  &_swigt__p_std__functionT_bool_fsize_tF_t,
   &_swigt__p_std__invalid_argument,
   &_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,
@@ -45314,8 +45278,6 @@ static swig_cast_info _swigc__p_MultiLayer[] = {  {&_swigt__p_MultiLayer, 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_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}};
-static swig_cast_info _swigc__p_PolarizerPair[] = {  {&_swigt__p_PolarizerPair, 0, 0, 0},{0, 0, 0, 0}};
-static swig_cast_info _swigc__p_ProgressHandler__Callback_t[] = {  {&_swigt__p_ProgressHandler__Callback_t, 0, 0, 0},{0, 0, 0, 0}};
 static swig_cast_info _swigc__p_PyBuilderCallback[] = {  {&_swigt__p_PyBuilderCallback, 0, 0, 0},{0, 0, 0, 0}};
 static swig_cast_info _swigc__p_PyObserverCallback[] = {  {&_swigt__p_PyObserverCallback, 0, 0, 0},{0, 0, 0, 0}};
 static swig_cast_info _swigc__p_QzScan[] = {  {&_swigt__p_QzScan, 0, 0, 0},{0, 0, 0, 0}};
@@ -45356,6 +45318,7 @@ static swig_cast_info _swigc__p_std__allocatorT_std__vectorT_double_std__allocat
 static swig_cast_info _swigc__p_std__allocatorT_std__vectorT_int_std__allocatorT_int_t_t_t[] = {  {&_swigt__p_std__allocatorT_std__vectorT_int_std__allocatorT_int_t_t_t, 0, 0, 0},{0, 0, 0, 0}};
 static swig_cast_info _swigc__p_std__allocatorT_unsigned_long_t[] = {  {&_swigt__p_std__allocatorT_unsigned_long_t, 0, 0, 0},{0, 0, 0, 0}};
 static swig_cast_info _swigc__p_std__complexT_double_t[] = {  {&_swigt__p_std__complexT_double_t, 0, 0, 0},{0, 0, 0, 0}};
+static swig_cast_info _swigc__p_std__functionT_bool_fsize_tF_t[] = {  {&_swigt__p_std__functionT_bool_fsize_tF_t, 0, 0, 0},{0, 0, 0, 0}};
 static swig_cast_info _swigc__p_std__invalid_argument[] = {  {&_swigt__p_std__invalid_argument, 0, 0, 0},{0, 0, 0, 0}};
 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}};
@@ -45423,8 +45386,6 @@ static swig_cast_info *swig_cast_initial[] = {
   _swigc__p_OffSpecularSimulation,
   _swigc__p_ParameterDistribution,
   _swigc__p_PoissonNoiseBackground,
-  _swigc__p_PolarizerPair,
-  _swigc__p_ProgressHandler__Callback_t,
   _swigc__p_PyBuilderCallback,
   _swigc__p_PyObserverCallback,
   _swigc__p_QzScan,
@@ -45465,6 +45426,7 @@ static swig_cast_info *swig_cast_initial[] = {
   _swigc__p_std__allocatorT_std__vectorT_int_std__allocatorT_int_t_t_t,
   _swigc__p_std__allocatorT_unsigned_long_t,
   _swigc__p_std__complexT_double_t,
+  _swigc__p_std__functionT_bool_fsize_tF_t,
   _swigc__p_std__invalid_argument,
   _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,
diff --git a/auto/Wrap/libBornAgainDevice.py b/auto/Wrap/libBornAgainDevice.py
index 14eb174cfc6d587dce926e693627cfad7d426af4..ce538af4b0b128158e7323255d5f1fa084f5f4bb 100644
--- a/auto/Wrap/libBornAgainDevice.py
+++ b/auto/Wrap/libBornAgainDevice.py
@@ -3934,15 +3934,15 @@ class IDetector(libBornAgainBase.ICloneable, libBornAgainParam.INode):
         """
         return _libBornAgainDevice.IDetector_addAxis(self, axis)
 
-    def setAnalyzerProperties(self, direction, efficiency, total_transmission):
+    def setAnalyzer(self, direction, efficiency, total_transmission):
         r"""
-        setAnalyzerProperties(IDetector self, kvector_t direction, double efficiency, double total_transmission)
-        void IDetector::setAnalyzerProperties(const kvector_t direction, double efficiency, double total_transmission)
+        setAnalyzer(IDetector self, kvector_t direction, double efficiency, double total_transmission)
+        void IDetector::setAnalyzer(const kvector_t direction, double efficiency, double total_transmission)
 
         Sets the polarization analyzer characteristics of the detector. 
 
         """
-        return _libBornAgainDevice.IDetector_setAnalyzerProperties(self, direction, efficiency, total_transmission)
+        return _libBornAgainDevice.IDetector_setAnalyzer(self, direction, efficiency, total_transmission)
 
     def setDetectorResolution(self, p_detector_resolution):
         r"""
@@ -4128,15 +4128,15 @@ class IDetector(libBornAgainBase.ICloneable, libBornAgainParam.INode):
         """
         return _libBornAgainDevice.IDetector_detectorResolution(self)
 
-    def detectionProperties(self):
+    def analyzer(self):
         r"""
-        detectionProperties(IDetector self) -> DetectionProperties const &
-        const DetectionProperties& IDetector::detectionProperties() const
+        analyzer(IDetector self) -> PolFilter const &
+        const PolFilter& IDetector::analyzer() const
 
         Returns detection properties. 
 
         """
-        return _libBornAgainDevice.IDetector_detectionProperties(self)
+        return _libBornAgainDevice.IDetector_analyzer(self)
 
     def createDetectorIntensity(self, elements):
         r"""
@@ -4629,6 +4629,138 @@ class IsGISAXSDetector(SphericalDetector):
 # Register IsGISAXSDetector in _libBornAgainDevice:
 _libBornAgainDevice.IsGISAXSDetector_swigregister(IsGISAXSDetector)
 
+class Instrument(libBornAgainParam.INode):
+    r"""
+
+
+    Assembles beam, detector and their relative positions with respect to the sample.
+
+    C++ includes: Instrument.h
+
+    """
+
+    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
+    __repr__ = _swig_repr
+
+    def __init__(self, *args):
+        r"""
+        __init__(Instrument self) -> Instrument
+        __init__(Instrument self, Beam beam, IDetector detector) -> Instrument
+        __init__(Instrument self, Instrument other) -> Instrument
+        Instrument::Instrument(const Instrument &other)
+
+        """
+        _libBornAgainDevice.Instrument_swiginit(self, _libBornAgainDevice.new_Instrument(*args))
+    __swig_destroy__ = _libBornAgainDevice.delete_Instrument
+
+    def accept(self, visitor):
+        r"""
+        accept(Instrument self, INodeVisitor * visitor)
+        void Instrument::accept(INodeVisitor *visitor) const override
+
+        """
+        return _libBornAgainDevice.Instrument_accept(self, visitor)
+
+    def beam(self, *args):
+        r"""
+        beam(Instrument self) -> Beam
+        beam(Instrument self) -> Beam
+        const Beam& Instrument::beam() const
+
+        """
+        return _libBornAgainDevice.Instrument_beam(self, *args)
+
+    def setBeam(self, beam):
+        r"""
+        setBeam(Instrument self, Beam beam)
+        void Instrument::setBeam(const Beam &beam)
+
+        """
+        return _libBornAgainDevice.Instrument_setBeam(self, beam)
+
+    def setBeamParameters(self, wavelength, alpha_i, phi_i):
+        r"""
+        setBeamParameters(Instrument self, double wavelength, double alpha_i, double phi_i)
+        void Instrument::setBeamParameters(double wavelength, double alpha_i, double phi_i)
+
+        Sets the beam wavelength and incoming angles. 
+
+        """
+        return _libBornAgainDevice.Instrument_setBeamParameters(self, wavelength, alpha_i, phi_i)
+
+    def getDetector(self, *args):
+        r"""
+        getDetector(Instrument self) -> IDetector
+        getDetector(Instrument self) -> IDetector
+        const IDetector * Instrument::getDetector() const
+
+        """
+        return _libBornAgainDevice.Instrument_getDetector(self, *args)
+
+    def detector(self, *args):
+        r"""
+        detector(Instrument self) -> IDetector
+        detector(Instrument self) -> IDetector
+        const IDetector & Instrument::detector() const
+
+        """
+        return _libBornAgainDevice.Instrument_detector(self, *args)
+
+    def setDetector(self, detector):
+        r"""
+        setDetector(Instrument self, IDetector detector)
+        void Instrument::setDetector(const IDetector &detector)
+
+        Sets the detector (axes can be overwritten later) 
+
+        """
+        return _libBornAgainDevice.Instrument_setDetector(self, detector)
+
+    def initDetector(self):
+        r"""
+        initDetector(Instrument self)
+        void Instrument::initDetector()
+
+        init detector with beam settings 
+
+        """
+        return _libBornAgainDevice.Instrument_initDetector(self)
+
+    def setPolFilters(self, polarizer_dir, analyzer_dir, analyzer_efficiency, analyzer_transmission):
+        r"""
+        setPolFilters(Instrument self, kvector_t polarizer_dir, kvector_t analyzer_dir, double analyzer_efficiency, double analyzer_transmission)
+        void Instrument::setPolFilters(const kvector_t &polarizer_dir, const kvector_t &analyzer_dir, double analyzer_efficiency, double analyzer_transmission)
+
+        """
+        return _libBornAgainDevice.Instrument_setPolFilters(self, polarizer_dir, analyzer_dir, analyzer_efficiency, analyzer_transmission)
+
+    def polarizerPair(self):
+        r"""
+        polarizerPair(Instrument self) -> PolMatrices
+        PolMatrices Instrument::polarizerPair() const
+
+        """
+        return _libBornAgainDevice.Instrument_polarizerPair(self)
+
+    def getChildren(self):
+        r"""
+        getChildren(Instrument self) -> std::vector< INode const *,std::allocator< INode const * > >
+        std::vector< const INode * > Instrument::getChildren() const override
+
+        """
+        return _libBornAgainDevice.Instrument_getChildren(self)
+
+    def createScatteringCoords(self):
+        r"""
+        createScatteringCoords(Instrument self) -> CoordSystem2D *
+        CoordSystem2D * Instrument::createScatteringCoords() const
+
+        """
+        return _libBornAgainDevice.Instrument_createScatteringCoords(self)
+
+# Register Instrument in _libBornAgainDevice:
+_libBornAgainDevice.Instrument_swigregister(Instrument)
+
 
 def FindPeaks(*args):
     r"""
diff --git a/auto/Wrap/libBornAgainDevice_wrap.cpp b/auto/Wrap/libBornAgainDevice_wrap.cpp
index ae273b9b312d3dcd4beb0776edb89b881d7b90ae..5855aa29240ef80f8e2f282aa97652765e8d9fca 100644
--- a/auto/Wrap/libBornAgainDevice_wrap.cpp
+++ b/auto/Wrap/libBornAgainDevice_wrap.cpp
@@ -3105,7 +3105,7 @@ namespace Swig {
 #define SWIGTYPE_p_Beam swig_types[5]
 #define SWIGTYPE_p_Bin1D swig_types[6]
 #define SWIGTYPE_p_CloneableVectorT_IAxis_t swig_types[7]
-#define SWIGTYPE_p_DetectionProperties swig_types[8]
+#define SWIGTYPE_p_CoordSystem2D swig_types[8]
 #define SWIGTYPE_p_DetectorMask swig_types[9]
 #define SWIGTYPE_p_Direction swig_types[10]
 #define SWIGTYPE_p_Ellipse swig_types[11]
@@ -3129,86 +3129,89 @@ namespace Swig {
 #define SWIGTYPE_p_IRangedDistribution swig_types[29]
 #define SWIGTYPE_p_IResolutionFunction2D swig_types[30]
 #define SWIGTYPE_p_IShape2D swig_types[31]
-#define SWIGTYPE_p_IntensityDataIOFactory swig_types[32]
-#define SWIGTYPE_p_IsGISAXSDetector swig_types[33]
-#define SWIGTYPE_p_Line swig_types[34]
-#define SWIGTYPE_p_OutputDataIteratorT_double_OutputDataT_double_t_t swig_types[35]
-#define SWIGTYPE_p_OutputDataIteratorT_double_const_OutputDataT_double_t_const_t swig_types[36]
-#define SWIGTYPE_p_OutputDataT_CumulativeValue_t swig_types[37]
-#define SWIGTYPE_p_OutputDataT_bool_t swig_types[38]
-#define SWIGTYPE_p_OutputDataT_double_t swig_types[39]
-#define SWIGTYPE_p_ParameterDistribution swig_types[40]
-#define SWIGTYPE_p_Polygon swig_types[41]
-#define SWIGTYPE_p_PolygonPrivate swig_types[42]
-#define SWIGTYPE_p_RealLimits swig_types[43]
-#define SWIGTYPE_p_Rectangle swig_types[44]
-#define SWIGTYPE_p_RectangularDetector swig_types[45]
-#define SWIGTYPE_p_RectangularPixel swig_types[46]
-#define SWIGTYPE_p_ResolutionFunction2DGaussian swig_types[47]
-#define SWIGTYPE_p_ScanResolution swig_types[48]
-#define SWIGTYPE_p_SimulationResult swig_types[49]
-#define SWIGTYPE_p_SphericalDetector swig_types[50]
-#define SWIGTYPE_p_VerticalLine swig_types[51]
-#define SWIGTYPE_p_allocator_type swig_types[52]
-#define SWIGTYPE_p_bool swig_types[53]
-#define SWIGTYPE_p_char swig_types[54]
-#define SWIGTYPE_p_const_iterator swig_types[55]
-#define SWIGTYPE_p_corr_matrix_t swig_types[56]
-#define SWIGTYPE_p_difference_type swig_types[57]
-#define SWIGTYPE_p_double swig_types[58]
-#define SWIGTYPE_p_first_type swig_types[59]
-#define SWIGTYPE_p_int swig_types[60]
-#define SWIGTYPE_p_iterator swig_types[61]
-#define SWIGTYPE_p_key_type swig_types[62]
-#define SWIGTYPE_p_long_long swig_types[63]
-#define SWIGTYPE_p_mapped_type swig_types[64]
-#define SWIGTYPE_p_p_ICoordSystem swig_types[65]
-#define SWIGTYPE_p_p_PyObject swig_types[66]
-#define SWIGTYPE_p_parameters_t swig_types[67]
-#define SWIGTYPE_p_second_type swig_types[68]
-#define SWIGTYPE_p_short swig_types[69]
-#define SWIGTYPE_p_signed_char swig_types[70]
-#define SWIGTYPE_p_size_type swig_types[71]
-#define SWIGTYPE_p_std__allocatorT_BasicVector3DT_double_t_t swig_types[72]
-#define SWIGTYPE_p_std__allocatorT_BasicVector3DT_std__complexT_double_t_t_t swig_types[73]
-#define SWIGTYPE_p_std__allocatorT_double_t swig_types[74]
-#define SWIGTYPE_p_std__allocatorT_int_t swig_types[75]
-#define SWIGTYPE_p_std__allocatorT_std__complexT_double_t_t swig_types[76]
-#define SWIGTYPE_p_std__allocatorT_std__pairT_double_double_t_t swig_types[77]
-#define SWIGTYPE_p_std__allocatorT_std__pairT_std__string_const_double_t_t swig_types[78]
-#define SWIGTYPE_p_std__allocatorT_std__string_t swig_types[79]
-#define SWIGTYPE_p_std__allocatorT_std__vectorT_double_std__allocatorT_double_t_t_t swig_types[80]
-#define SWIGTYPE_p_std__allocatorT_std__vectorT_int_std__allocatorT_int_t_t_t swig_types[81]
-#define SWIGTYPE_p_std__allocatorT_unsigned_long_t swig_types[82]
-#define SWIGTYPE_p_std__complexT_double_t swig_types[83]
-#define SWIGTYPE_p_std__functionT_void_fSimulationAreaIterator_const_RF_t swig_types[84]
-#define SWIGTYPE_p_std__invalid_argument swig_types[85]
-#define SWIGTYPE_p_std__lessT_std__string_t swig_types[86]
-#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[87]
-#define SWIGTYPE_p_std__pairT_double_double_t swig_types[88]
-#define SWIGTYPE_p_std__vectorT_AxisInfo_std__allocatorT_AxisInfo_t_t swig_types[89]
-#define SWIGTYPE_p_std__vectorT_BasicVector3DT_double_t_std__allocatorT_BasicVector3DT_double_t_t_t swig_types[90]
-#define SWIGTYPE_p_std__vectorT_BasicVector3DT_std__complexT_double_t_t_std__allocatorT_BasicVector3DT_std__complexT_double_t_t_t_t swig_types[91]
-#define SWIGTYPE_p_std__vectorT_INode_const_p_std__allocatorT_INode_const_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_size_t_std__allocatorT_size_t_t_t swig_types[95]
-#define SWIGTYPE_p_std__vectorT_std__complexT_double_t_std__allocatorT_std__complexT_double_t_t_t swig_types[96]
-#define SWIGTYPE_p_std__vectorT_std__pairT_double_double_t_std__allocatorT_std__pairT_double_double_t_t_t swig_types[97]
-#define SWIGTYPE_p_std__vectorT_std__string_std__allocatorT_std__string_t_t swig_types[98]
-#define SWIGTYPE_p_std__vectorT_std__unique_ptrT_DiffuseElement_t_std__allocatorT_std__unique_ptrT_DiffuseElement_t_t_t swig_types[99]
-#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[100]
-#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[101]
-#define SWIGTYPE_p_std__vectorT_unsigned_int_std__allocatorT_unsigned_int_t_t swig_types[102]
-#define SWIGTYPE_p_std__vectorT_unsigned_long_std__allocatorT_unsigned_long_t_t swig_types[103]
-#define SWIGTYPE_p_swig__SwigPyIterator swig_types[104]
-#define SWIGTYPE_p_unsigned_char swig_types[105]
-#define SWIGTYPE_p_unsigned_int swig_types[106]
-#define SWIGTYPE_p_unsigned_long_long swig_types[107]
-#define SWIGTYPE_p_unsigned_short swig_types[108]
-#define SWIGTYPE_p_value_type swig_types[109]
-static swig_type_info *swig_types[111];
-static swig_module_info swig_module = {swig_types, 110, 0, 0, 0, 0};
+#define SWIGTYPE_p_Instrument swig_types[32]
+#define SWIGTYPE_p_IntensityDataIOFactory swig_types[33]
+#define SWIGTYPE_p_IsGISAXSDetector swig_types[34]
+#define SWIGTYPE_p_Line swig_types[35]
+#define SWIGTYPE_p_OutputDataIteratorT_double_OutputDataT_double_t_t swig_types[36]
+#define SWIGTYPE_p_OutputDataIteratorT_double_const_OutputDataT_double_t_const_t swig_types[37]
+#define SWIGTYPE_p_OutputDataT_CumulativeValue_t swig_types[38]
+#define SWIGTYPE_p_OutputDataT_bool_t swig_types[39]
+#define SWIGTYPE_p_OutputDataT_double_t swig_types[40]
+#define SWIGTYPE_p_ParameterDistribution swig_types[41]
+#define SWIGTYPE_p_PolFilter swig_types[42]
+#define SWIGTYPE_p_PolMatrices swig_types[43]
+#define SWIGTYPE_p_Polygon swig_types[44]
+#define SWIGTYPE_p_PolygonPrivate swig_types[45]
+#define SWIGTYPE_p_RealLimits swig_types[46]
+#define SWIGTYPE_p_Rectangle swig_types[47]
+#define SWIGTYPE_p_RectangularDetector swig_types[48]
+#define SWIGTYPE_p_RectangularPixel swig_types[49]
+#define SWIGTYPE_p_ResolutionFunction2DGaussian swig_types[50]
+#define SWIGTYPE_p_ScanResolution swig_types[51]
+#define SWIGTYPE_p_SimulationResult swig_types[52]
+#define SWIGTYPE_p_SphericalDetector swig_types[53]
+#define SWIGTYPE_p_VerticalLine swig_types[54]
+#define SWIGTYPE_p_allocator_type swig_types[55]
+#define SWIGTYPE_p_bool swig_types[56]
+#define SWIGTYPE_p_char swig_types[57]
+#define SWIGTYPE_p_const_iterator swig_types[58]
+#define SWIGTYPE_p_corr_matrix_t swig_types[59]
+#define SWIGTYPE_p_difference_type swig_types[60]
+#define SWIGTYPE_p_double swig_types[61]
+#define SWIGTYPE_p_first_type swig_types[62]
+#define SWIGTYPE_p_int swig_types[63]
+#define SWIGTYPE_p_iterator swig_types[64]
+#define SWIGTYPE_p_key_type swig_types[65]
+#define SWIGTYPE_p_long_long swig_types[66]
+#define SWIGTYPE_p_mapped_type swig_types[67]
+#define SWIGTYPE_p_p_ICoordSystem swig_types[68]
+#define SWIGTYPE_p_p_PyObject swig_types[69]
+#define SWIGTYPE_p_parameters_t swig_types[70]
+#define SWIGTYPE_p_second_type swig_types[71]
+#define SWIGTYPE_p_short swig_types[72]
+#define SWIGTYPE_p_signed_char swig_types[73]
+#define SWIGTYPE_p_size_type swig_types[74]
+#define SWIGTYPE_p_std__allocatorT_BasicVector3DT_double_t_t swig_types[75]
+#define SWIGTYPE_p_std__allocatorT_BasicVector3DT_std__complexT_double_t_t_t swig_types[76]
+#define SWIGTYPE_p_std__allocatorT_double_t swig_types[77]
+#define SWIGTYPE_p_std__allocatorT_int_t swig_types[78]
+#define SWIGTYPE_p_std__allocatorT_std__complexT_double_t_t swig_types[79]
+#define SWIGTYPE_p_std__allocatorT_std__pairT_double_double_t_t swig_types[80]
+#define SWIGTYPE_p_std__allocatorT_std__pairT_std__string_const_double_t_t swig_types[81]
+#define SWIGTYPE_p_std__allocatorT_std__string_t swig_types[82]
+#define SWIGTYPE_p_std__allocatorT_std__vectorT_double_std__allocatorT_double_t_t_t swig_types[83]
+#define SWIGTYPE_p_std__allocatorT_std__vectorT_int_std__allocatorT_int_t_t_t swig_types[84]
+#define SWIGTYPE_p_std__allocatorT_unsigned_long_t swig_types[85]
+#define SWIGTYPE_p_std__complexT_double_t swig_types[86]
+#define SWIGTYPE_p_std__functionT_void_fSimulationAreaIterator_const_RF_t swig_types[87]
+#define SWIGTYPE_p_std__invalid_argument swig_types[88]
+#define SWIGTYPE_p_std__lessT_std__string_t swig_types[89]
+#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[90]
+#define SWIGTYPE_p_std__pairT_double_double_t swig_types[91]
+#define SWIGTYPE_p_std__vectorT_AxisInfo_std__allocatorT_AxisInfo_t_t swig_types[92]
+#define SWIGTYPE_p_std__vectorT_BasicVector3DT_double_t_std__allocatorT_BasicVector3DT_double_t_t_t swig_types[93]
+#define SWIGTYPE_p_std__vectorT_BasicVector3DT_std__complexT_double_t_t_std__allocatorT_BasicVector3DT_std__complexT_double_t_t_t_t swig_types[94]
+#define SWIGTYPE_p_std__vectorT_INode_const_p_std__allocatorT_INode_const_p_t_t swig_types[95]
+#define SWIGTYPE_p_std__vectorT_double_std__allocatorT_double_t_t swig_types[96]
+#define SWIGTYPE_p_std__vectorT_int_std__allocatorT_int_t_t swig_types[97]
+#define SWIGTYPE_p_std__vectorT_size_t_std__allocatorT_size_t_t_t swig_types[98]
+#define SWIGTYPE_p_std__vectorT_std__complexT_double_t_std__allocatorT_std__complexT_double_t_t_t swig_types[99]
+#define SWIGTYPE_p_std__vectorT_std__pairT_double_double_t_std__allocatorT_std__pairT_double_double_t_t_t swig_types[100]
+#define SWIGTYPE_p_std__vectorT_std__string_std__allocatorT_std__string_t_t swig_types[101]
+#define SWIGTYPE_p_std__vectorT_std__unique_ptrT_DiffuseElement_t_std__allocatorT_std__unique_ptrT_DiffuseElement_t_t_t swig_types[102]
+#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[103]
+#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[104]
+#define SWIGTYPE_p_std__vectorT_unsigned_int_std__allocatorT_unsigned_int_t_t swig_types[105]
+#define SWIGTYPE_p_std__vectorT_unsigned_long_std__allocatorT_unsigned_long_t_t swig_types[106]
+#define SWIGTYPE_p_swig__SwigPyIterator swig_types[107]
+#define SWIGTYPE_p_unsigned_char swig_types[108]
+#define SWIGTYPE_p_unsigned_int swig_types[109]
+#define SWIGTYPE_p_unsigned_long_long swig_types[110]
+#define SWIGTYPE_p_unsigned_short swig_types[111]
+#define SWIGTYPE_p_value_type swig_types[112]
+static swig_type_info *swig_types[114];
+static swig_module_info swig_module = {swig_types, 113, 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)
 
@@ -6701,6 +6704,7 @@ SWIGINTERN std::vector< std::pair< double,double > >::iterator std_vector_Sl_std
 SWIGINTERN std::vector< std::pair< double,double > >::iterator std_vector_Sl_std_pair_Sl_double_Sc_double_Sg__Sg__insert__SWIG_0(std::vector< std::pair< double,double > > *self,std::vector< std::pair< double,double > >::iterator pos,std::vector< std::pair< double,double > >::value_type const &x){ return self->insert(pos, x); }
 SWIGINTERN void std_vector_Sl_std_pair_Sl_double_Sc_double_Sg__Sg__insert__SWIG_1(std::vector< std::pair< double,double > > *self,std::vector< std::pair< double,double > >::iterator pos,std::vector< std::pair< double,double > >::size_type n,std::vector< std::pair< double,double > >::value_type const &x){ self->insert(pos, n, x); }
 
+#include "Base/Element/PolMatrices.h"
 #include "Param/Distrib/ParameterDistribution.h"
 #include "Device/Beam/Beam.h"
 #include "Device/Beam/FootprintGauss.h"
@@ -6714,11 +6718,12 @@ SWIGINTERN void std_vector_Sl_std_pair_Sl_double_Sc_double_Sg__Sg__insert__SWIG_
 #include "Device/Histo/Histogram2D.h"
 #include "Device/Histo/IntensityDataIOFactory.h"
 #include "Device/Histo/SimulationResult.h"
+#include "Device/Instrument/Instrument.h"
 #include "Device/Mask/Ellipse.h"
 #include "Device/Mask/Line.h"
 #include "Device/Mask/Polygon.h"
 #include "Device/Mask/Rectangle.h"
-#include "Device/ProDetector/DetectorMask.h"
+#include "Device/Mask/DetectorMask.h"
 #include "Device/Resolution/IDetectorResolution.h"
 #include "Device/Resolution/ResolutionFunction2DGaussian.h"
 #include "Device/Resolution/ScanResolution.h"
@@ -35727,7 +35732,7 @@ fail:
 }
 
 
-SWIGINTERN PyObject *_wrap_IDetector_setAnalyzerProperties(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+SWIGINTERN PyObject *_wrap_IDetector_setAnalyzer(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
   PyObject *resultobj = 0;
   IDetector *arg1 = (IDetector *) 0 ;
   kvector_t arg2 ;
@@ -35743,19 +35748,19 @@ SWIGINTERN PyObject *_wrap_IDetector_setAnalyzerProperties(PyObject *SWIGUNUSEDP
   int ecode4 = 0 ;
   PyObject *swig_obj[4] ;
   
-  if (!SWIG_Python_UnpackTuple(args, "IDetector_setAnalyzerProperties", 4, 4, swig_obj)) SWIG_fail;
+  if (!SWIG_Python_UnpackTuple(args, "IDetector_setAnalyzer", 4, 4, swig_obj)) SWIG_fail;
   res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_IDetector, 0 |  0 );
   if (!SWIG_IsOK(res1)) {
-    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "IDetector_setAnalyzerProperties" "', argument " "1"" of type '" "IDetector *""'"); 
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "IDetector_setAnalyzer" "', argument " "1"" of type '" "IDetector *""'"); 
   }
   arg1 = reinterpret_cast< IDetector * >(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 '" "IDetector_setAnalyzerProperties" "', argument " "2"" of type '" "kvector_t const""'"); 
+      SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "IDetector_setAnalyzer" "', argument " "2"" of type '" "kvector_t const""'"); 
     }  
     if (!argp2) {
-      SWIG_exception_fail(SWIG_ValueError, "invalid null reference " "in method '" "IDetector_setAnalyzerProperties" "', argument " "2"" of type '" "kvector_t const""'");
+      SWIG_exception_fail(SWIG_ValueError, "invalid null reference " "in method '" "IDetector_setAnalyzer" "', argument " "2"" of type '" "kvector_t const""'");
     } else {
       kvector_t * temp = reinterpret_cast< kvector_t * >(argp2);
       arg2 = *temp;
@@ -35764,15 +35769,15 @@ SWIGINTERN PyObject *_wrap_IDetector_setAnalyzerProperties(PyObject *SWIGUNUSEDP
   }
   ecode3 = SWIG_AsVal_double(swig_obj[2], &val3);
   if (!SWIG_IsOK(ecode3)) {
-    SWIG_exception_fail(SWIG_ArgError(ecode3), "in method '" "IDetector_setAnalyzerProperties" "', argument " "3"" of type '" "double""'");
+    SWIG_exception_fail(SWIG_ArgError(ecode3), "in method '" "IDetector_setAnalyzer" "', argument " "3"" of type '" "double""'");
   } 
   arg3 = static_cast< double >(val3);
   ecode4 = SWIG_AsVal_double(swig_obj[3], &val4);
   if (!SWIG_IsOK(ecode4)) {
-    SWIG_exception_fail(SWIG_ArgError(ecode4), "in method '" "IDetector_setAnalyzerProperties" "', argument " "4"" of type '" "double""'");
+    SWIG_exception_fail(SWIG_ArgError(ecode4), "in method '" "IDetector_setAnalyzer" "', argument " "4"" of type '" "double""'");
   } 
   arg4 = static_cast< double >(val4);
-  (arg1)->setAnalyzerProperties(arg2,arg3,arg4);
+  (arg1)->setAnalyzer(arg2,arg3,arg4);
   resultobj = SWIG_Py_Void();
   return resultobj;
 fail:
@@ -36304,23 +36309,23 @@ fail:
 }
 
 
-SWIGINTERN PyObject *_wrap_IDetector_detectionProperties(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+SWIGINTERN PyObject *_wrap_IDetector_analyzer(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
   PyObject *resultobj = 0;
   IDetector *arg1 = (IDetector *) 0 ;
   void *argp1 = 0 ;
   int res1 = 0 ;
   PyObject *swig_obj[1] ;
-  DetectionProperties *result = 0 ;
+  PolFilter *result = 0 ;
   
   if (!args) SWIG_fail;
   swig_obj[0] = args;
   res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_IDetector, 0 |  0 );
   if (!SWIG_IsOK(res1)) {
-    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "IDetector_detectionProperties" "', argument " "1"" of type '" "IDetector const *""'"); 
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "IDetector_analyzer" "', argument " "1"" of type '" "IDetector const *""'"); 
   }
   arg1 = reinterpret_cast< IDetector * >(argp1);
-  result = (DetectionProperties *) &((IDetector const *)arg1)->detectionProperties();
-  resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_DetectionProperties, 0 |  0 );
+  result = (PolFilter *) &((IDetector const *)arg1)->analyzer();
+  resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_PolFilter, 0 |  0 );
   return resultobj;
 fail:
   return NULL;
@@ -38602,6 +38607,675 @@ SWIGINTERN PyObject *IsGISAXSDetector_swiginit(PyObject *SWIGUNUSEDPARM(self), P
   return SWIG_Python_InitShadowInstance(args);
 }
 
+SWIGINTERN PyObject *_wrap_new_Instrument__SWIG_0(PyObject *SWIGUNUSEDPARM(self), Py_ssize_t nobjs, PyObject **SWIGUNUSEDPARM(swig_obj)) {
+  PyObject *resultobj = 0;
+  Instrument *result = 0 ;
+  
+  if ((nobjs < 0) || (nobjs > 0)) SWIG_fail;
+  result = (Instrument *)new Instrument();
+  resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_Instrument, SWIG_POINTER_NEW |  0 );
+  return resultobj;
+fail:
+  return NULL;
+}
+
+
+SWIGINTERN PyObject *_wrap_new_Instrument__SWIG_1(PyObject *SWIGUNUSEDPARM(self), Py_ssize_t nobjs, PyObject **swig_obj) {
+  PyObject *resultobj = 0;
+  Beam *arg1 = 0 ;
+  IDetector *arg2 = 0 ;
+  void *argp1 = 0 ;
+  int res1 = 0 ;
+  void *argp2 = 0 ;
+  int res2 = 0 ;
+  Instrument *result = 0 ;
+  
+  if ((nobjs < 2) || (nobjs > 2)) 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_Instrument" "', argument " "1"" of type '" "Beam const &""'"); 
+  }
+  if (!argp1) {
+    SWIG_exception_fail(SWIG_ValueError, "invalid null reference " "in method '" "new_Instrument" "', argument " "1"" of type '" "Beam const &""'"); 
+  }
+  arg1 = reinterpret_cast< Beam * >(argp1);
+  res2 = SWIG_ConvertPtr(swig_obj[1], &argp2, SWIGTYPE_p_IDetector,  0  | 0);
+  if (!SWIG_IsOK(res2)) {
+    SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "new_Instrument" "', argument " "2"" of type '" "IDetector const &""'"); 
+  }
+  if (!argp2) {
+    SWIG_exception_fail(SWIG_ValueError, "invalid null reference " "in method '" "new_Instrument" "', argument " "2"" of type '" "IDetector const &""'"); 
+  }
+  arg2 = reinterpret_cast< IDetector * >(argp2);
+  result = (Instrument *)new Instrument((Beam const &)*arg1,(IDetector const &)*arg2);
+  resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_Instrument, SWIG_POINTER_NEW |  0 );
+  return resultobj;
+fail:
+  return NULL;
+}
+
+
+SWIGINTERN PyObject *_wrap_new_Instrument__SWIG_2(PyObject *SWIGUNUSEDPARM(self), Py_ssize_t nobjs, PyObject **swig_obj) {
+  PyObject *resultobj = 0;
+  Instrument *arg1 = 0 ;
+  void *argp1 = 0 ;
+  int res1 = 0 ;
+  Instrument *result = 0 ;
+  
+  if ((nobjs < 1) || (nobjs > 1)) SWIG_fail;
+  res1 = SWIG_ConvertPtr(swig_obj[0], &argp1, SWIGTYPE_p_Instrument,  0  | 0);
+  if (!SWIG_IsOK(res1)) {
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "new_Instrument" "', argument " "1"" of type '" "Instrument const &""'"); 
+  }
+  if (!argp1) {
+    SWIG_exception_fail(SWIG_ValueError, "invalid null reference " "in method '" "new_Instrument" "', argument " "1"" of type '" "Instrument const &""'"); 
+  }
+  arg1 = reinterpret_cast< Instrument * >(argp1);
+  result = (Instrument *)new Instrument((Instrument const &)*arg1);
+  resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_Instrument, SWIG_POINTER_NEW |  0 );
+  return resultobj;
+fail:
+  return NULL;
+}
+
+
+SWIGINTERN PyObject *_wrap_new_Instrument(PyObject *self, PyObject *args) {
+  Py_ssize_t argc;
+  PyObject *argv[3] = {
+    0
+  };
+  
+  if (!(argc = SWIG_Python_UnpackTuple(args, "new_Instrument", 0, 2, argv))) SWIG_fail;
+  --argc;
+  if (argc == 0) {
+    return _wrap_new_Instrument__SWIG_0(self, argc, argv);
+  }
+  if (argc == 1) {
+    int _v;
+    int res = SWIG_ConvertPtr(argv[0], 0, SWIGTYPE_p_Instrument, SWIG_POINTER_NO_NULL | 0);
+    _v = SWIG_CheckState(res);
+    if (_v) {
+      return _wrap_new_Instrument__SWIG_2(self, argc, argv);
+    }
+  }
+  if (argc == 2) {
+    int _v;
+    int res = SWIG_ConvertPtr(argv[0], 0, SWIGTYPE_p_Beam, SWIG_POINTER_NO_NULL | 0);
+    _v = SWIG_CheckState(res);
+    if (_v) {
+      int res = SWIG_ConvertPtr(argv[1], 0, SWIGTYPE_p_IDetector, SWIG_POINTER_NO_NULL | 0);
+      _v = SWIG_CheckState(res);
+      if (_v) {
+        return _wrap_new_Instrument__SWIG_1(self, argc, argv);
+      }
+    }
+  }
+  
+fail:
+  SWIG_Python_RaiseOrModifyTypeError("Wrong number or type of arguments for overloaded function 'new_Instrument'.\n"
+    "  Possible C/C++ prototypes are:\n"
+    "    Instrument::Instrument()\n"
+    "    Instrument::Instrument(Beam const &,IDetector const &)\n"
+    "    Instrument::Instrument(Instrument const &)\n");
+  return 0;
+}
+
+
+SWIGINTERN PyObject *_wrap_delete_Instrument(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *resultobj = 0;
+  Instrument *arg1 = (Instrument *) 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_Instrument, SWIG_POINTER_DISOWN |  0 );
+  if (!SWIG_IsOK(res1)) {
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "delete_Instrument" "', argument " "1"" of type '" "Instrument *""'"); 
+  }
+  arg1 = reinterpret_cast< Instrument * >(argp1);
+  delete arg1;
+  resultobj = SWIG_Py_Void();
+  return resultobj;
+fail:
+  return NULL;
+}
+
+
+SWIGINTERN PyObject *_wrap_Instrument_accept(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *resultobj = 0;
+  Instrument *arg1 = (Instrument *) 0 ;
+  INodeVisitor *arg2 = (INodeVisitor *) 0 ;
+  void *argp1 = 0 ;
+  int res1 = 0 ;
+  void *argp2 = 0 ;
+  int res2 = 0 ;
+  PyObject *swig_obj[2] ;
+  
+  if (!SWIG_Python_UnpackTuple(args, "Instrument_accept", 2, 2, swig_obj)) SWIG_fail;
+  res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_Instrument, 0 |  0 );
+  if (!SWIG_IsOK(res1)) {
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Instrument_accept" "', argument " "1"" of type '" "Instrument const *""'"); 
+  }
+  arg1 = reinterpret_cast< Instrument * >(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 '" "Instrument_accept" "', argument " "2"" of type '" "INodeVisitor *""'"); 
+  }
+  arg2 = reinterpret_cast< INodeVisitor * >(argp2);
+  ((Instrument const *)arg1)->accept(arg2);
+  resultobj = SWIG_Py_Void();
+  return resultobj;
+fail:
+  return NULL;
+}
+
+
+SWIGINTERN PyObject *_wrap_Instrument_beam__SWIG_0(PyObject *SWIGUNUSEDPARM(self), Py_ssize_t nobjs, PyObject **swig_obj) {
+  PyObject *resultobj = 0;
+  Instrument *arg1 = (Instrument *) 0 ;
+  void *argp1 = 0 ;
+  int res1 = 0 ;
+  Beam *result = 0 ;
+  
+  if ((nobjs < 1) || (nobjs > 1)) SWIG_fail;
+  res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_Instrument, 0 |  0 );
+  if (!SWIG_IsOK(res1)) {
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Instrument_beam" "', argument " "1"" of type '" "Instrument *""'"); 
+  }
+  arg1 = reinterpret_cast< Instrument * >(argp1);
+  result = (Beam *) &(arg1)->beam();
+  resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_Beam, 0 |  0 );
+  return resultobj;
+fail:
+  return NULL;
+}
+
+
+SWIGINTERN PyObject *_wrap_Instrument_beam__SWIG_1(PyObject *SWIGUNUSEDPARM(self), Py_ssize_t nobjs, PyObject **swig_obj) {
+  PyObject *resultobj = 0;
+  Instrument *arg1 = (Instrument *) 0 ;
+  void *argp1 = 0 ;
+  int res1 = 0 ;
+  Beam *result = 0 ;
+  
+  if ((nobjs < 1) || (nobjs > 1)) SWIG_fail;
+  res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_Instrument, 0 |  0 );
+  if (!SWIG_IsOK(res1)) {
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Instrument_beam" "', argument " "1"" of type '" "Instrument const *""'"); 
+  }
+  arg1 = reinterpret_cast< Instrument * >(argp1);
+  result = (Beam *) &((Instrument const *)arg1)->beam();
+  resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_Beam, 0 |  0 );
+  return resultobj;
+fail:
+  return NULL;
+}
+
+
+SWIGINTERN PyObject *_wrap_Instrument_beam(PyObject *self, PyObject *args) {
+  Py_ssize_t argc;
+  PyObject *argv[2] = {
+    0
+  };
+  
+  if (!(argc = SWIG_Python_UnpackTuple(args, "Instrument_beam", 0, 1, argv))) SWIG_fail;
+  --argc;
+  if (argc == 1) {
+    int _v;
+    void *vptr = 0;
+    int res = SWIG_ConvertPtr(argv[0], &vptr, SWIGTYPE_p_Instrument, 0);
+    _v = SWIG_CheckState(res);
+    if (_v) {
+      return _wrap_Instrument_beam__SWIG_0(self, argc, argv);
+    }
+  }
+  if (argc == 1) {
+    int _v;
+    void *vptr = 0;
+    int res = SWIG_ConvertPtr(argv[0], &vptr, SWIGTYPE_p_Instrument, 0);
+    _v = SWIG_CheckState(res);
+    if (_v) {
+      return _wrap_Instrument_beam__SWIG_1(self, argc, argv);
+    }
+  }
+  
+fail:
+  SWIG_Python_RaiseOrModifyTypeError("Wrong number or type of arguments for overloaded function 'Instrument_beam'.\n"
+    "  Possible C/C++ prototypes are:\n"
+    "    Instrument::beam()\n"
+    "    Instrument::beam() const\n");
+  return 0;
+}
+
+
+SWIGINTERN PyObject *_wrap_Instrument_setBeam(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *resultobj = 0;
+  Instrument *arg1 = (Instrument *) 0 ;
+  Beam *arg2 = 0 ;
+  void *argp1 = 0 ;
+  int res1 = 0 ;
+  void *argp2 = 0 ;
+  int res2 = 0 ;
+  PyObject *swig_obj[2] ;
+  
+  if (!SWIG_Python_UnpackTuple(args, "Instrument_setBeam", 2, 2, swig_obj)) SWIG_fail;
+  res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_Instrument, 0 |  0 );
+  if (!SWIG_IsOK(res1)) {
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Instrument_setBeam" "', argument " "1"" of type '" "Instrument *""'"); 
+  }
+  arg1 = reinterpret_cast< Instrument * >(argp1);
+  res2 = SWIG_ConvertPtr(swig_obj[1], &argp2, SWIGTYPE_p_Beam,  0  | 0);
+  if (!SWIG_IsOK(res2)) {
+    SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "Instrument_setBeam" "', argument " "2"" of type '" "Beam const &""'"); 
+  }
+  if (!argp2) {
+    SWIG_exception_fail(SWIG_ValueError, "invalid null reference " "in method '" "Instrument_setBeam" "', argument " "2"" of type '" "Beam const &""'"); 
+  }
+  arg2 = reinterpret_cast< Beam * >(argp2);
+  (arg1)->setBeam((Beam const &)*arg2);
+  resultobj = SWIG_Py_Void();
+  return resultobj;
+fail:
+  return NULL;
+}
+
+
+SWIGINTERN PyObject *_wrap_Instrument_setBeamParameters(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *resultobj = 0;
+  Instrument *arg1 = (Instrument *) 0 ;
+  double arg2 ;
+  double arg3 ;
+  double arg4 ;
+  void *argp1 = 0 ;
+  int res1 = 0 ;
+  double val2 ;
+  int ecode2 = 0 ;
+  double val3 ;
+  int ecode3 = 0 ;
+  double val4 ;
+  int ecode4 = 0 ;
+  PyObject *swig_obj[4] ;
+  
+  if (!SWIG_Python_UnpackTuple(args, "Instrument_setBeamParameters", 4, 4, swig_obj)) SWIG_fail;
+  res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_Instrument, 0 |  0 );
+  if (!SWIG_IsOK(res1)) {
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Instrument_setBeamParameters" "', argument " "1"" of type '" "Instrument *""'"); 
+  }
+  arg1 = reinterpret_cast< Instrument * >(argp1);
+  ecode2 = SWIG_AsVal_double(swig_obj[1], &val2);
+  if (!SWIG_IsOK(ecode2)) {
+    SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "Instrument_setBeamParameters" "', argument " "2"" of type '" "double""'");
+  } 
+  arg2 = static_cast< double >(val2);
+  ecode3 = SWIG_AsVal_double(swig_obj[2], &val3);
+  if (!SWIG_IsOK(ecode3)) {
+    SWIG_exception_fail(SWIG_ArgError(ecode3), "in method '" "Instrument_setBeamParameters" "', argument " "3"" of type '" "double""'");
+  } 
+  arg3 = static_cast< double >(val3);
+  ecode4 = SWIG_AsVal_double(swig_obj[3], &val4);
+  if (!SWIG_IsOK(ecode4)) {
+    SWIG_exception_fail(SWIG_ArgError(ecode4), "in method '" "Instrument_setBeamParameters" "', argument " "4"" of type '" "double""'");
+  } 
+  arg4 = static_cast< double >(val4);
+  (arg1)->setBeamParameters(arg2,arg3,arg4);
+  resultobj = SWIG_Py_Void();
+  return resultobj;
+fail:
+  return NULL;
+}
+
+
+SWIGINTERN PyObject *_wrap_Instrument_getDetector__SWIG_0(PyObject *SWIGUNUSEDPARM(self), Py_ssize_t nobjs, PyObject **swig_obj) {
+  PyObject *resultobj = 0;
+  Instrument *arg1 = (Instrument *) 0 ;
+  void *argp1 = 0 ;
+  int res1 = 0 ;
+  IDetector *result = 0 ;
+  
+  if ((nobjs < 1) || (nobjs > 1)) SWIG_fail;
+  res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_Instrument, 0 |  0 );
+  if (!SWIG_IsOK(res1)) {
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Instrument_getDetector" "', argument " "1"" of type '" "Instrument *""'"); 
+  }
+  arg1 = reinterpret_cast< Instrument * >(argp1);
+  result = (IDetector *)(arg1)->getDetector();
+  resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_IDetector, 0 |  0 );
+  return resultobj;
+fail:
+  return NULL;
+}
+
+
+SWIGINTERN PyObject *_wrap_Instrument_getDetector__SWIG_1(PyObject *SWIGUNUSEDPARM(self), Py_ssize_t nobjs, PyObject **swig_obj) {
+  PyObject *resultobj = 0;
+  Instrument *arg1 = (Instrument *) 0 ;
+  void *argp1 = 0 ;
+  int res1 = 0 ;
+  IDetector *result = 0 ;
+  
+  if ((nobjs < 1) || (nobjs > 1)) SWIG_fail;
+  res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_Instrument, 0 |  0 );
+  if (!SWIG_IsOK(res1)) {
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Instrument_getDetector" "', argument " "1"" of type '" "Instrument const *""'"); 
+  }
+  arg1 = reinterpret_cast< Instrument * >(argp1);
+  result = (IDetector *)((Instrument const *)arg1)->getDetector();
+  resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_IDetector, 0 |  0 );
+  return resultobj;
+fail:
+  return NULL;
+}
+
+
+SWIGINTERN PyObject *_wrap_Instrument_getDetector(PyObject *self, PyObject *args) {
+  Py_ssize_t argc;
+  PyObject *argv[2] = {
+    0
+  };
+  
+  if (!(argc = SWIG_Python_UnpackTuple(args, "Instrument_getDetector", 0, 1, argv))) SWIG_fail;
+  --argc;
+  if (argc == 1) {
+    int _v;
+    void *vptr = 0;
+    int res = SWIG_ConvertPtr(argv[0], &vptr, SWIGTYPE_p_Instrument, 0);
+    _v = SWIG_CheckState(res);
+    if (_v) {
+      return _wrap_Instrument_getDetector__SWIG_0(self, argc, argv);
+    }
+  }
+  if (argc == 1) {
+    int _v;
+    void *vptr = 0;
+    int res = SWIG_ConvertPtr(argv[0], &vptr, SWIGTYPE_p_Instrument, 0);
+    _v = SWIG_CheckState(res);
+    if (_v) {
+      return _wrap_Instrument_getDetector__SWIG_1(self, argc, argv);
+    }
+  }
+  
+fail:
+  SWIG_Python_RaiseOrModifyTypeError("Wrong number or type of arguments for overloaded function 'Instrument_getDetector'.\n"
+    "  Possible C/C++ prototypes are:\n"
+    "    Instrument::getDetector()\n"
+    "    Instrument::getDetector() const\n");
+  return 0;
+}
+
+
+SWIGINTERN PyObject *_wrap_Instrument_detector__SWIG_0(PyObject *SWIGUNUSEDPARM(self), Py_ssize_t nobjs, PyObject **swig_obj) {
+  PyObject *resultobj = 0;
+  Instrument *arg1 = (Instrument *) 0 ;
+  void *argp1 = 0 ;
+  int res1 = 0 ;
+  IDetector *result = 0 ;
+  
+  if ((nobjs < 1) || (nobjs > 1)) SWIG_fail;
+  res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_Instrument, 0 |  0 );
+  if (!SWIG_IsOK(res1)) {
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Instrument_detector" "', argument " "1"" of type '" "Instrument *""'"); 
+  }
+  arg1 = reinterpret_cast< Instrument * >(argp1);
+  result = (IDetector *) &(arg1)->detector();
+  resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_IDetector, 0 |  0 );
+  return resultobj;
+fail:
+  return NULL;
+}
+
+
+SWIGINTERN PyObject *_wrap_Instrument_detector__SWIG_1(PyObject *SWIGUNUSEDPARM(self), Py_ssize_t nobjs, PyObject **swig_obj) {
+  PyObject *resultobj = 0;
+  Instrument *arg1 = (Instrument *) 0 ;
+  void *argp1 = 0 ;
+  int res1 = 0 ;
+  IDetector *result = 0 ;
+  
+  if ((nobjs < 1) || (nobjs > 1)) SWIG_fail;
+  res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_Instrument, 0 |  0 );
+  if (!SWIG_IsOK(res1)) {
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Instrument_detector" "', argument " "1"" of type '" "Instrument const *""'"); 
+  }
+  arg1 = reinterpret_cast< Instrument * >(argp1);
+  result = (IDetector *) &((Instrument const *)arg1)->detector();
+  resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_IDetector, 0 |  0 );
+  return resultobj;
+fail:
+  return NULL;
+}
+
+
+SWIGINTERN PyObject *_wrap_Instrument_detector(PyObject *self, PyObject *args) {
+  Py_ssize_t argc;
+  PyObject *argv[2] = {
+    0
+  };
+  
+  if (!(argc = SWIG_Python_UnpackTuple(args, "Instrument_detector", 0, 1, argv))) SWIG_fail;
+  --argc;
+  if (argc == 1) {
+    int _v;
+    void *vptr = 0;
+    int res = SWIG_ConvertPtr(argv[0], &vptr, SWIGTYPE_p_Instrument, 0);
+    _v = SWIG_CheckState(res);
+    if (_v) {
+      return _wrap_Instrument_detector__SWIG_0(self, argc, argv);
+    }
+  }
+  if (argc == 1) {
+    int _v;
+    void *vptr = 0;
+    int res = SWIG_ConvertPtr(argv[0], &vptr, SWIGTYPE_p_Instrument, 0);
+    _v = SWIG_CheckState(res);
+    if (_v) {
+      return _wrap_Instrument_detector__SWIG_1(self, argc, argv);
+    }
+  }
+  
+fail:
+  SWIG_Python_RaiseOrModifyTypeError("Wrong number or type of arguments for overloaded function 'Instrument_detector'.\n"
+    "  Possible C/C++ prototypes are:\n"
+    "    Instrument::detector()\n"
+    "    Instrument::detector() const\n");
+  return 0;
+}
+
+
+SWIGINTERN PyObject *_wrap_Instrument_setDetector(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *resultobj = 0;
+  Instrument *arg1 = (Instrument *) 0 ;
+  IDetector *arg2 = 0 ;
+  void *argp1 = 0 ;
+  int res1 = 0 ;
+  void *argp2 = 0 ;
+  int res2 = 0 ;
+  PyObject *swig_obj[2] ;
+  
+  if (!SWIG_Python_UnpackTuple(args, "Instrument_setDetector", 2, 2, swig_obj)) SWIG_fail;
+  res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_Instrument, 0 |  0 );
+  if (!SWIG_IsOK(res1)) {
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Instrument_setDetector" "', argument " "1"" of type '" "Instrument *""'"); 
+  }
+  arg1 = reinterpret_cast< Instrument * >(argp1);
+  res2 = SWIG_ConvertPtr(swig_obj[1], &argp2, SWIGTYPE_p_IDetector,  0  | 0);
+  if (!SWIG_IsOK(res2)) {
+    SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "Instrument_setDetector" "', argument " "2"" of type '" "IDetector const &""'"); 
+  }
+  if (!argp2) {
+    SWIG_exception_fail(SWIG_ValueError, "invalid null reference " "in method '" "Instrument_setDetector" "', argument " "2"" of type '" "IDetector const &""'"); 
+  }
+  arg2 = reinterpret_cast< IDetector * >(argp2);
+  (arg1)->setDetector((IDetector const &)*arg2);
+  resultobj = SWIG_Py_Void();
+  return resultobj;
+fail:
+  return NULL;
+}
+
+
+SWIGINTERN PyObject *_wrap_Instrument_initDetector(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *resultobj = 0;
+  Instrument *arg1 = (Instrument *) 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_Instrument, 0 |  0 );
+  if (!SWIG_IsOK(res1)) {
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Instrument_initDetector" "', argument " "1"" of type '" "Instrument *""'"); 
+  }
+  arg1 = reinterpret_cast< Instrument * >(argp1);
+  (arg1)->initDetector();
+  resultobj = SWIG_Py_Void();
+  return resultobj;
+fail:
+  return NULL;
+}
+
+
+SWIGINTERN PyObject *_wrap_Instrument_setPolFilters(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *resultobj = 0;
+  Instrument *arg1 = (Instrument *) 0 ;
+  kvector_t *arg2 = 0 ;
+  kvector_t *arg3 = 0 ;
+  double arg4 ;
+  double arg5 ;
+  void *argp1 = 0 ;
+  int res1 = 0 ;
+  void *argp2 = 0 ;
+  int res2 = 0 ;
+  void *argp3 = 0 ;
+  int res3 = 0 ;
+  double val4 ;
+  int ecode4 = 0 ;
+  double val5 ;
+  int ecode5 = 0 ;
+  PyObject *swig_obj[5] ;
+  
+  if (!SWIG_Python_UnpackTuple(args, "Instrument_setPolFilters", 5, 5, swig_obj)) SWIG_fail;
+  res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_Instrument, 0 |  0 );
+  if (!SWIG_IsOK(res1)) {
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Instrument_setPolFilters" "', argument " "1"" of type '" "Instrument *""'"); 
+  }
+  arg1 = reinterpret_cast< Instrument * >(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 '" "Instrument_setPolFilters" "', argument " "2"" of type '" "kvector_t const &""'"); 
+  }
+  if (!argp2) {
+    SWIG_exception_fail(SWIG_ValueError, "invalid null reference " "in method '" "Instrument_setPolFilters" "', argument " "2"" of type '" "kvector_t const &""'"); 
+  }
+  arg2 = reinterpret_cast< kvector_t * >(argp2);
+  res3 = SWIG_ConvertPtr(swig_obj[2], &argp3, SWIGTYPE_p_BasicVector3DT_double_t,  0  | 0);
+  if (!SWIG_IsOK(res3)) {
+    SWIG_exception_fail(SWIG_ArgError(res3), "in method '" "Instrument_setPolFilters" "', argument " "3"" of type '" "kvector_t const &""'"); 
+  }
+  if (!argp3) {
+    SWIG_exception_fail(SWIG_ValueError, "invalid null reference " "in method '" "Instrument_setPolFilters" "', argument " "3"" of type '" "kvector_t const &""'"); 
+  }
+  arg3 = reinterpret_cast< kvector_t * >(argp3);
+  ecode4 = SWIG_AsVal_double(swig_obj[3], &val4);
+  if (!SWIG_IsOK(ecode4)) {
+    SWIG_exception_fail(SWIG_ArgError(ecode4), "in method '" "Instrument_setPolFilters" "', argument " "4"" of type '" "double""'");
+  } 
+  arg4 = static_cast< double >(val4);
+  ecode5 = SWIG_AsVal_double(swig_obj[4], &val5);
+  if (!SWIG_IsOK(ecode5)) {
+    SWIG_exception_fail(SWIG_ArgError(ecode5), "in method '" "Instrument_setPolFilters" "', argument " "5"" of type '" "double""'");
+  } 
+  arg5 = static_cast< double >(val5);
+  (arg1)->setPolFilters((kvector_t const &)*arg2,(kvector_t const &)*arg3,arg4,arg5);
+  resultobj = SWIG_Py_Void();
+  return resultobj;
+fail:
+  return NULL;
+}
+
+
+SWIGINTERN PyObject *_wrap_Instrument_polarizerPair(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *resultobj = 0;
+  Instrument *arg1 = (Instrument *) 0 ;
+  void *argp1 = 0 ;
+  int res1 = 0 ;
+  PyObject *swig_obj[1] ;
+  PolMatrices result;
+  
+  if (!args) SWIG_fail;
+  swig_obj[0] = args;
+  res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_Instrument, 0 |  0 );
+  if (!SWIG_IsOK(res1)) {
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Instrument_polarizerPair" "', argument " "1"" of type '" "Instrument const *""'"); 
+  }
+  arg1 = reinterpret_cast< Instrument * >(argp1);
+  result = ((Instrument const *)arg1)->polarizerPair();
+  resultobj = SWIG_NewPointerObj((new PolMatrices(static_cast< const PolMatrices& >(result))), SWIGTYPE_p_PolMatrices, SWIG_POINTER_OWN |  0 );
+  return resultobj;
+fail:
+  return NULL;
+}
+
+
+SWIGINTERN PyObject *_wrap_Instrument_getChildren(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *resultobj = 0;
+  Instrument *arg1 = (Instrument *) 0 ;
+  void *argp1 = 0 ;
+  int res1 = 0 ;
+  PyObject *swig_obj[1] ;
+  SwigValueWrapper< std::vector< INode const *,std::allocator< INode const * > > > result;
+  
+  if (!args) SWIG_fail;
+  swig_obj[0] = args;
+  res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_Instrument, 0 |  0 );
+  if (!SWIG_IsOK(res1)) {
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Instrument_getChildren" "', argument " "1"" of type '" "Instrument const *""'"); 
+  }
+  arg1 = reinterpret_cast< Instrument * >(argp1);
+  result = ((Instrument const *)arg1)->getChildren();
+  resultobj = SWIG_NewPointerObj((new std::vector< INode const *,std::allocator< INode const * > >(static_cast< const std::vector< INode const *,std::allocator< INode const * > >& >(result))), SWIGTYPE_p_std__vectorT_INode_const_p_std__allocatorT_INode_const_p_t_t, SWIG_POINTER_OWN |  0 );
+  return resultobj;
+fail:
+  return NULL;
+}
+
+
+SWIGINTERN PyObject *_wrap_Instrument_createScatteringCoords(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *resultobj = 0;
+  Instrument *arg1 = (Instrument *) 0 ;
+  void *argp1 = 0 ;
+  int res1 = 0 ;
+  PyObject *swig_obj[1] ;
+  CoordSystem2D *result = 0 ;
+  
+  if (!args) SWIG_fail;
+  swig_obj[0] = args;
+  res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_Instrument, 0 |  0 );
+  if (!SWIG_IsOK(res1)) {
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Instrument_createScatteringCoords" "', argument " "1"" of type '" "Instrument const *""'"); 
+  }
+  arg1 = reinterpret_cast< Instrument * >(argp1);
+  result = (CoordSystem2D *)((Instrument const *)arg1)->createScatteringCoords();
+  resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_CoordSystem2D, 0 |  0 );
+  return resultobj;
+fail:
+  return NULL;
+}
+
+
+SWIGINTERN PyObject *Instrument_swigregister(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *obj;
+  if (!SWIG_Python_UnpackTuple(args, "swigregister", 1, 1, &obj)) return NULL;
+  SWIG_TypeNewClientData(SWIGTYPE_p_Instrument, SWIG_NewClientData(obj));
+  return SWIG_Py_Void();
+}
+
+SWIGINTERN PyObject *Instrument_swiginit(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  return SWIG_Python_InitShadowInstance(args);
+}
+
 SWIGINTERN PyObject *_wrap_FindPeaks__SWIG_0(PyObject *SWIGUNUSEDPARM(self), Py_ssize_t nobjs, PyObject **swig_obj) {
   PyObject *resultobj = 0;
   Histogram2D *arg1 = 0 ;
@@ -45619,9 +46293,9 @@ static PyMethodDef SwigMethods[] = {
 		"void IDetector::addAxis(const IAxis &axis)\n"
 		"\n"
 		""},
-	 { "IDetector_setAnalyzerProperties", _wrap_IDetector_setAnalyzerProperties, METH_VARARGS, "\n"
-		"IDetector_setAnalyzerProperties(IDetector self, kvector_t direction, double efficiency, double total_transmission)\n"
-		"void IDetector::setAnalyzerProperties(const kvector_t direction, double efficiency, double total_transmission)\n"
+	 { "IDetector_setAnalyzer", _wrap_IDetector_setAnalyzer, METH_VARARGS, "\n"
+		"IDetector_setAnalyzer(IDetector self, kvector_t direction, double efficiency, double total_transmission)\n"
+		"void IDetector::setAnalyzer(const kvector_t direction, double efficiency, double total_transmission)\n"
 		"\n"
 		"Sets the polarization analyzer characteristics of the detector. \n"
 		"\n"
@@ -45753,9 +46427,9 @@ static PyMethodDef SwigMethods[] = {
 		"Returns a pointer to detector resolution object. \n"
 		"\n"
 		""},
-	 { "IDetector_detectionProperties", _wrap_IDetector_detectionProperties, METH_O, "\n"
-		"IDetector_detectionProperties(IDetector self) -> DetectionProperties const &\n"
-		"const DetectionProperties& IDetector::detectionProperties() const\n"
+	 { "IDetector_analyzer", _wrap_IDetector_analyzer, METH_O, "\n"
+		"IDetector_analyzer(IDetector self) -> PolFilter const &\n"
+		"const PolFilter& IDetector::analyzer() const\n"
 		"\n"
 		"Returns detection properties. \n"
 		"\n"
@@ -46056,6 +46730,89 @@ static PyMethodDef SwigMethods[] = {
 	 { "delete_IsGISAXSDetector", _wrap_delete_IsGISAXSDetector, METH_O, "delete_IsGISAXSDetector(IsGISAXSDetector self)"},
 	 { "IsGISAXSDetector_swigregister", IsGISAXSDetector_swigregister, METH_O, NULL},
 	 { "IsGISAXSDetector_swiginit", IsGISAXSDetector_swiginit, METH_VARARGS, NULL},
+	 { "new_Instrument", _wrap_new_Instrument, METH_VARARGS, "\n"
+		"Instrument()\n"
+		"Instrument(Beam beam, IDetector detector)\n"
+		"new_Instrument(Instrument other) -> Instrument\n"
+		"Instrument::Instrument(const Instrument &other)\n"
+		"\n"
+		""},
+	 { "delete_Instrument", _wrap_delete_Instrument, METH_O, "\n"
+		"delete_Instrument(Instrument self)\n"
+		"Instrument::~Instrument()\n"
+		"\n"
+		""},
+	 { "Instrument_accept", _wrap_Instrument_accept, METH_VARARGS, "\n"
+		"Instrument_accept(Instrument self, INodeVisitor * visitor)\n"
+		"void Instrument::accept(INodeVisitor *visitor) const override\n"
+		"\n"
+		""},
+	 { "Instrument_beam", _wrap_Instrument_beam, METH_VARARGS, "\n"
+		"Instrument_beam(Instrument self) -> Beam\n"
+		"Instrument_beam(Instrument self) -> Beam\n"
+		"const Beam& Instrument::beam() const\n"
+		"\n"
+		""},
+	 { "Instrument_setBeam", _wrap_Instrument_setBeam, METH_VARARGS, "\n"
+		"Instrument_setBeam(Instrument self, Beam beam)\n"
+		"void Instrument::setBeam(const Beam &beam)\n"
+		"\n"
+		""},
+	 { "Instrument_setBeamParameters", _wrap_Instrument_setBeamParameters, METH_VARARGS, "\n"
+		"Instrument_setBeamParameters(Instrument self, double wavelength, double alpha_i, double phi_i)\n"
+		"void Instrument::setBeamParameters(double wavelength, double alpha_i, double phi_i)\n"
+		"\n"
+		"Sets the beam wavelength and incoming angles. \n"
+		"\n"
+		""},
+	 { "Instrument_getDetector", _wrap_Instrument_getDetector, METH_VARARGS, "\n"
+		"Instrument_getDetector(Instrument self) -> IDetector\n"
+		"Instrument_getDetector(Instrument self) -> IDetector\n"
+		"const IDetector * Instrument::getDetector() const\n"
+		"\n"
+		""},
+	 { "Instrument_detector", _wrap_Instrument_detector, METH_VARARGS, "\n"
+		"Instrument_detector(Instrument self) -> IDetector\n"
+		"Instrument_detector(Instrument self) -> IDetector\n"
+		"const IDetector & Instrument::detector() const\n"
+		"\n"
+		""},
+	 { "Instrument_setDetector", _wrap_Instrument_setDetector, METH_VARARGS, "\n"
+		"Instrument_setDetector(Instrument self, IDetector detector)\n"
+		"void Instrument::setDetector(const IDetector &detector)\n"
+		"\n"
+		"Sets the detector (axes can be overwritten later) \n"
+		"\n"
+		""},
+	 { "Instrument_initDetector", _wrap_Instrument_initDetector, METH_O, "\n"
+		"Instrument_initDetector(Instrument self)\n"
+		"void Instrument::initDetector()\n"
+		"\n"
+		"init detector with beam settings \n"
+		"\n"
+		""},
+	 { "Instrument_setPolFilters", _wrap_Instrument_setPolFilters, METH_VARARGS, "\n"
+		"Instrument_setPolFilters(Instrument self, kvector_t polarizer_dir, kvector_t analyzer_dir, double analyzer_efficiency, double analyzer_transmission)\n"
+		"void Instrument::setPolFilters(const kvector_t &polarizer_dir, const kvector_t &analyzer_dir, double analyzer_efficiency, double analyzer_transmission)\n"
+		"\n"
+		""},
+	 { "Instrument_polarizerPair", _wrap_Instrument_polarizerPair, METH_O, "\n"
+		"Instrument_polarizerPair(Instrument self) -> PolMatrices\n"
+		"PolMatrices Instrument::polarizerPair() const\n"
+		"\n"
+		""},
+	 { "Instrument_getChildren", _wrap_Instrument_getChildren, METH_O, "\n"
+		"Instrument_getChildren(Instrument self) -> std::vector< INode const *,std::allocator< INode const * > >\n"
+		"std::vector< const INode * > Instrument::getChildren() const override\n"
+		"\n"
+		""},
+	 { "Instrument_createScatteringCoords", _wrap_Instrument_createScatteringCoords, METH_O, "\n"
+		"Instrument_createScatteringCoords(Instrument self) -> CoordSystem2D *\n"
+		"CoordSystem2D * Instrument::createScatteringCoords() const\n"
+		"\n"
+		""},
+	 { "Instrument_swigregister", Instrument_swigregister, METH_O, NULL},
+	 { "Instrument_swiginit", Instrument_swiginit, METH_VARARGS, NULL},
 	 { "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 > > DataUtils::Histo::FindPeaks(const Histogram2D &hist, double sigma=2, const std::string &option={}, double threshold=0.05)\n"
@@ -46653,47 +47410,68 @@ static PyMethodDef SwigMethods_proxydocs[] = {
 
 /* -------- TYPE CONVERSION AND EQUIVALENCE RULES (BEGIN) -------- */
 
-static void *_p_RectangularDetectorTo_p_IDetector2D(void *x, int *SWIGUNUSEDPARM(newmemory)) {
-    return (void *)((IDetector2D *)  ((RectangularDetector *) x));
+static void *_p_Histogram2DTo_p_IHistogram(void *x, int *SWIGUNUSEDPARM(newmemory)) {
+    return (void *)((IHistogram *)  ((Histogram2D *) x));
 }
-static void *_p_SphericalDetectorTo_p_IDetector2D(void *x, int *SWIGUNUSEDPARM(newmemory)) {
-    return (void *)((IDetector2D *)  ((SphericalDetector *) x));
+static void *_p_Histogram1DTo_p_IHistogram(void *x, int *SWIGUNUSEDPARM(newmemory)) {
+    return (void *)((IHistogram *)  ((Histogram1D *) x));
 }
-static void *_p_IsGISAXSDetectorTo_p_IDetector2D(void *x, int *SWIGUNUSEDPARM(newmemory)) {
-    return (void *)((IDetector2D *) (SphericalDetector *) ((IsGISAXSDetector *) x));
+static void *_p_FootprintGaussTo_p_ICloneable(void *x, int *SWIGUNUSEDPARM(newmemory)) {
+    return (void *)((ICloneable *) (IFootprintFactor *) ((FootprintGauss *) x));
 }
-static void *_p_IsGISAXSDetectorTo_p_SphericalDetector(void *x, int *SWIGUNUSEDPARM(newmemory)) {
-    return (void *)((SphericalDetector *)  ((IsGISAXSDetector *) x));
+static void *_p_ScanResolutionTo_p_ICloneable(void *x, int *SWIGUNUSEDPARM(newmemory)) {
+    return (void *)((ICloneable *)  ((ScanResolution *) x));
 }
-static void *_p_RectangularDetectorTo_p_IDetector(void *x, int *SWIGUNUSEDPARM(newmemory)) {
-    return (void *)((IDetector *) (IDetector2D *) ((RectangularDetector *) x));
+static void *_p_IDetectorResolutionTo_p_ICloneable(void *x, int *SWIGUNUSEDPARM(newmemory)) {
+    return (void *)((ICloneable *)  ((IDetectorResolution *) x));
 }
-static void *_p_SphericalDetectorTo_p_IDetector(void *x, int *SWIGUNUSEDPARM(newmemory)) {
-    return (void *)((IDetector *) (IDetector2D *) ((SphericalDetector *) x));
+static void *_p_IDetector2DTo_p_ICloneable(void *x, int *SWIGUNUSEDPARM(newmemory)) {
+    return (void *)((ICloneable *) (IDetector *) ((IDetector2D *) x));
 }
-static void *_p_IsGISAXSDetectorTo_p_IDetector(void *x, int *SWIGUNUSEDPARM(newmemory)) {
-    return (void *)((IDetector *) (IDetector2D *)(SphericalDetector *) ((IsGISAXSDetector *) x));
+static void *_p_RectangleTo_p_ICloneable(void *x, int *SWIGUNUSEDPARM(newmemory)) {
+    return (void *)((ICloneable *) (IShape2D *) ((Rectangle *) x));
 }
-static void *_p_IDetector2DTo_p_IDetector(void *x, int *SWIGUNUSEDPARM(newmemory)) {
-    return (void *)((IDetector *)  ((IDetector2D *) x));
+static void *_p_ResolutionFunction2DGaussianTo_p_ICloneable(void *x, int *SWIGUNUSEDPARM(newmemory)) {
+    return (void *)((ICloneable *) (IResolutionFunction2D *) ((ResolutionFunction2DGaussian *) x));
 }
-static void *_p_PolygonTo_p_IShape2D(void *x, int *SWIGUNUSEDPARM(newmemory)) {
-    return (void *)((IShape2D *)  ((Polygon *) x));
+static void *_p_IFootprintFactorTo_p_ICloneable(void *x, int *SWIGUNUSEDPARM(newmemory)) {
+    return (void *)((ICloneable *)  ((IFootprintFactor *) x));
 }
-static void *_p_LineTo_p_IShape2D(void *x, int *SWIGUNUSEDPARM(newmemory)) {
-    return (void *)((IShape2D *)  ((Line *) x));
+static void *_p_IShape2DTo_p_ICloneable(void *x, int *SWIGUNUSEDPARM(newmemory)) {
+    return (void *)((ICloneable *)  ((IShape2D *) x));
 }
-static void *_p_VerticalLineTo_p_IShape2D(void *x, int *SWIGUNUSEDPARM(newmemory)) {
-    return (void *)((IShape2D *)  ((VerticalLine *) x));
+static void *_p_EllipseTo_p_ICloneable(void *x, int *SWIGUNUSEDPARM(newmemory)) {
+    return (void *)((ICloneable *) (IShape2D *) ((Ellipse *) x));
 }
-static void *_p_EllipseTo_p_IShape2D(void *x, int *SWIGUNUSEDPARM(newmemory)) {
-    return (void *)((IShape2D *)  ((Ellipse *) x));
+static void *_p_HorizontalLineTo_p_ICloneable(void *x, int *SWIGUNUSEDPARM(newmemory)) {
+    return (void *)((ICloneable *) (IShape2D *) ((HorizontalLine *) x));
 }
-static void *_p_HorizontalLineTo_p_IShape2D(void *x, int *SWIGUNUSEDPARM(newmemory)) {
-    return (void *)((IShape2D *)  ((HorizontalLine *) x));
+static void *_p_VerticalLineTo_p_ICloneable(void *x, int *SWIGUNUSEDPARM(newmemory)) {
+    return (void *)((ICloneable *) (IShape2D *) ((VerticalLine *) x));
 }
-static void *_p_RectangleTo_p_IShape2D(void *x, int *SWIGUNUSEDPARM(newmemory)) {
-    return (void *)((IShape2D *)  ((Rectangle *) x));
+static void *_p_IDetectorTo_p_ICloneable(void *x, int *SWIGUNUSEDPARM(newmemory)) {
+    return (void *)((ICloneable *)  ((IDetector *) x));
+}
+static void *_p_RectangularDetectorTo_p_ICloneable(void *x, int *SWIGUNUSEDPARM(newmemory)) {
+    return (void *)((ICloneable *) (IDetector *)(IDetector2D *) ((RectangularDetector *) x));
+}
+static void *_p_SphericalDetectorTo_p_ICloneable(void *x, int *SWIGUNUSEDPARM(newmemory)) {
+    return (void *)((ICloneable *) (IDetector *)(IDetector2D *) ((SphericalDetector *) x));
+}
+static void *_p_IsGISAXSDetectorTo_p_ICloneable(void *x, int *SWIGUNUSEDPARM(newmemory)) {
+    return (void *)((ICloneable *) (IDetector *)(IDetector2D *)(SphericalDetector *) ((IsGISAXSDetector *) x));
+}
+static void *_p_PolygonTo_p_ICloneable(void *x, int *SWIGUNUSEDPARM(newmemory)) {
+    return (void *)((ICloneable *) (IShape2D *) ((Polygon *) x));
+}
+static void *_p_FootprintSquareTo_p_ICloneable(void *x, int *SWIGUNUSEDPARM(newmemory)) {
+    return (void *)((ICloneable *) (IFootprintFactor *) ((FootprintSquare *) x));
+}
+static void *_p_IResolutionFunction2DTo_p_ICloneable(void *x, int *SWIGUNUSEDPARM(newmemory)) {
+    return (void *)((ICloneable *)  ((IResolutionFunction2D *) x));
+}
+static void *_p_LineTo_p_ICloneable(void *x, int *SWIGUNUSEDPARM(newmemory)) {
+    return (void *)((ICloneable *) (IShape2D *) ((Line *) x));
 }
 static void *_p_FootprintGaussTo_p_IParametric(void *x, int *SWIGUNUSEDPARM(newmemory)) {
     return (void *)((IParametric *) (INode *)(IFootprintFactor *) ((FootprintGauss *) x));
@@ -46713,6 +47491,9 @@ static void *_p_ResolutionFunction2DGaussianTo_p_IParametric(void *x, int *SWIGU
 static void *_p_IFootprintFactorTo_p_IParametric(void *x, int *SWIGUNUSEDPARM(newmemory)) {
     return (void *)((IParametric *) (INode *) ((IFootprintFactor *) x));
 }
+static void *_p_InstrumentTo_p_IParametric(void *x, int *SWIGUNUSEDPARM(newmemory)) {
+    return (void *)((IParametric *) (INode *) ((Instrument *) x));
+}
 static void *_p_BeamTo_p_IParametric(void *x, int *SWIGUNUSEDPARM(newmemory)) {
     return (void *)((IParametric *) (INode *) ((Beam *) x));
 }
@@ -46737,24 +47518,15 @@ static void *_p_FootprintSquareTo_p_IParametric(void *x, int *SWIGUNUSEDPARM(new
 static void *_p_IResolutionFunction2DTo_p_IParametric(void *x, int *SWIGUNUSEDPARM(newmemory)) {
     return (void *)((IParametric *) (INode *) ((IResolutionFunction2D *) x));
 }
-static void *_p_FootprintSquareTo_p_IFootprintFactor(void *x, int *SWIGUNUSEDPARM(newmemory)) {
-    return (void *)((IFootprintFactor *)  ((FootprintSquare *) x));
-}
-static void *_p_FootprintGaussTo_p_IFootprintFactor(void *x, int *SWIGUNUSEDPARM(newmemory)) {
-    return (void *)((IFootprintFactor *)  ((FootprintGauss *) x));
-}
-static void *_p_Histogram2DTo_p_IHistogram(void *x, int *SWIGUNUSEDPARM(newmemory)) {
-    return (void *)((IHistogram *)  ((Histogram2D *) x));
-}
-static void *_p_Histogram1DTo_p_IHistogram(void *x, int *SWIGUNUSEDPARM(newmemory)) {
-    return (void *)((IHistogram *)  ((Histogram1D *) x));
-}
 static void *_p_FootprintSquareTo_p_INode(void *x, int *SWIGUNUSEDPARM(newmemory)) {
     return (void *)((INode *) (IFootprintFactor *) ((FootprintSquare *) x));
 }
 static void *_p_IDetectorResolutionTo_p_INode(void *x, int *SWIGUNUSEDPARM(newmemory)) {
     return (void *)((INode *)  ((IDetectorResolution *) x));
 }
+static void *_p_InstrumentTo_p_INode(void *x, int *SWIGUNUSEDPARM(newmemory)) {
+    return (void *)((INode *)  ((Instrument *) x));
+}
 static void *_p_IFootprintFactorTo_p_INode(void *x, int *SWIGUNUSEDPARM(newmemory)) {
     return (void *)((INode *)  ((IFootprintFactor *) x));
 }
@@ -46785,65 +47557,56 @@ static void *_p_FootprintGaussTo_p_INode(void *x, int *SWIGUNUSEDPARM(newmemory)
 static void *_p_IDetector2DTo_p_INode(void *x, int *SWIGUNUSEDPARM(newmemory)) {
     return (void *)((INode *) (IDetector *) ((IDetector2D *) x));
 }
-static void *_p_ResolutionFunction2DGaussianTo_p_IResolutionFunction2D(void *x, int *SWIGUNUSEDPARM(newmemory)) {
-    return (void *)((IResolutionFunction2D *)  ((ResolutionFunction2DGaussian *) x));
-}
-static void *_p_FootprintGaussTo_p_ICloneable(void *x, int *SWIGUNUSEDPARM(newmemory)) {
-    return (void *)((ICloneable *) (IFootprintFactor *) ((FootprintGauss *) x));
-}
-static void *_p_ScanResolutionTo_p_ICloneable(void *x, int *SWIGUNUSEDPARM(newmemory)) {
-    return (void *)((ICloneable *)  ((ScanResolution *) x));
-}
-static void *_p_IDetectorResolutionTo_p_ICloneable(void *x, int *SWIGUNUSEDPARM(newmemory)) {
-    return (void *)((ICloneable *)  ((IDetectorResolution *) x));
+static void *_p_RectangularDetectorTo_p_IDetector(void *x, int *SWIGUNUSEDPARM(newmemory)) {
+    return (void *)((IDetector *) (IDetector2D *) ((RectangularDetector *) x));
 }
-static void *_p_IDetector2DTo_p_ICloneable(void *x, int *SWIGUNUSEDPARM(newmemory)) {
-    return (void *)((ICloneable *) (IDetector *) ((IDetector2D *) x));
+static void *_p_SphericalDetectorTo_p_IDetector(void *x, int *SWIGUNUSEDPARM(newmemory)) {
+    return (void *)((IDetector *) (IDetector2D *) ((SphericalDetector *) x));
 }
-static void *_p_RectangleTo_p_ICloneable(void *x, int *SWIGUNUSEDPARM(newmemory)) {
-    return (void *)((ICloneable *) (IShape2D *) ((Rectangle *) x));
+static void *_p_IsGISAXSDetectorTo_p_IDetector(void *x, int *SWIGUNUSEDPARM(newmemory)) {
+    return (void *)((IDetector *) (IDetector2D *)(SphericalDetector *) ((IsGISAXSDetector *) x));
 }
-static void *_p_ResolutionFunction2DGaussianTo_p_ICloneable(void *x, int *SWIGUNUSEDPARM(newmemory)) {
-    return (void *)((ICloneable *) (IResolutionFunction2D *) ((ResolutionFunction2DGaussian *) x));
+static void *_p_IDetector2DTo_p_IDetector(void *x, int *SWIGUNUSEDPARM(newmemory)) {
+    return (void *)((IDetector *)  ((IDetector2D *) x));
 }
-static void *_p_IFootprintFactorTo_p_ICloneable(void *x, int *SWIGUNUSEDPARM(newmemory)) {
-    return (void *)((ICloneable *)  ((IFootprintFactor *) x));
+static void *_p_IsGISAXSDetectorTo_p_SphericalDetector(void *x, int *SWIGUNUSEDPARM(newmemory)) {
+    return (void *)((SphericalDetector *)  ((IsGISAXSDetector *) x));
 }
-static void *_p_IShape2DTo_p_ICloneable(void *x, int *SWIGUNUSEDPARM(newmemory)) {
-    return (void *)((ICloneable *)  ((IShape2D *) x));
+static void *_p_PolygonTo_p_IShape2D(void *x, int *SWIGUNUSEDPARM(newmemory)) {
+    return (void *)((IShape2D *)  ((Polygon *) x));
 }
-static void *_p_EllipseTo_p_ICloneable(void *x, int *SWIGUNUSEDPARM(newmemory)) {
-    return (void *)((ICloneable *) (IShape2D *) ((Ellipse *) x));
+static void *_p_LineTo_p_IShape2D(void *x, int *SWIGUNUSEDPARM(newmemory)) {
+    return (void *)((IShape2D *)  ((Line *) x));
 }
-static void *_p_HorizontalLineTo_p_ICloneable(void *x, int *SWIGUNUSEDPARM(newmemory)) {
-    return (void *)((ICloneable *) (IShape2D *) ((HorizontalLine *) x));
+static void *_p_VerticalLineTo_p_IShape2D(void *x, int *SWIGUNUSEDPARM(newmemory)) {
+    return (void *)((IShape2D *)  ((VerticalLine *) x));
 }
-static void *_p_VerticalLineTo_p_ICloneable(void *x, int *SWIGUNUSEDPARM(newmemory)) {
-    return (void *)((ICloneable *) (IShape2D *) ((VerticalLine *) x));
+static void *_p_EllipseTo_p_IShape2D(void *x, int *SWIGUNUSEDPARM(newmemory)) {
+    return (void *)((IShape2D *)  ((Ellipse *) x));
 }
-static void *_p_IDetectorTo_p_ICloneable(void *x, int *SWIGUNUSEDPARM(newmemory)) {
-    return (void *)((ICloneable *)  ((IDetector *) x));
+static void *_p_HorizontalLineTo_p_IShape2D(void *x, int *SWIGUNUSEDPARM(newmemory)) {
+    return (void *)((IShape2D *)  ((HorizontalLine *) x));
 }
-static void *_p_RectangularDetectorTo_p_ICloneable(void *x, int *SWIGUNUSEDPARM(newmemory)) {
-    return (void *)((ICloneable *) (IDetector *)(IDetector2D *) ((RectangularDetector *) x));
+static void *_p_RectangleTo_p_IShape2D(void *x, int *SWIGUNUSEDPARM(newmemory)) {
+    return (void *)((IShape2D *)  ((Rectangle *) x));
 }
-static void *_p_SphericalDetectorTo_p_ICloneable(void *x, int *SWIGUNUSEDPARM(newmemory)) {
-    return (void *)((ICloneable *) (IDetector *)(IDetector2D *) ((SphericalDetector *) x));
+static void *_p_RectangularDetectorTo_p_IDetector2D(void *x, int *SWIGUNUSEDPARM(newmemory)) {
+    return (void *)((IDetector2D *)  ((RectangularDetector *) x));
 }
-static void *_p_IsGISAXSDetectorTo_p_ICloneable(void *x, int *SWIGUNUSEDPARM(newmemory)) {
-    return (void *)((ICloneable *) (IDetector *)(IDetector2D *)(SphericalDetector *) ((IsGISAXSDetector *) x));
+static void *_p_SphericalDetectorTo_p_IDetector2D(void *x, int *SWIGUNUSEDPARM(newmemory)) {
+    return (void *)((IDetector2D *)  ((SphericalDetector *) x));
 }
-static void *_p_PolygonTo_p_ICloneable(void *x, int *SWIGUNUSEDPARM(newmemory)) {
-    return (void *)((ICloneable *) (IShape2D *) ((Polygon *) x));
+static void *_p_IsGISAXSDetectorTo_p_IDetector2D(void *x, int *SWIGUNUSEDPARM(newmemory)) {
+    return (void *)((IDetector2D *) (SphericalDetector *) ((IsGISAXSDetector *) x));
 }
-static void *_p_FootprintSquareTo_p_ICloneable(void *x, int *SWIGUNUSEDPARM(newmemory)) {
-    return (void *)((ICloneable *) (IFootprintFactor *) ((FootprintSquare *) x));
+static void *_p_FootprintSquareTo_p_IFootprintFactor(void *x, int *SWIGUNUSEDPARM(newmemory)) {
+    return (void *)((IFootprintFactor *)  ((FootprintSquare *) x));
 }
-static void *_p_IResolutionFunction2DTo_p_ICloneable(void *x, int *SWIGUNUSEDPARM(newmemory)) {
-    return (void *)((ICloneable *)  ((IResolutionFunction2D *) x));
+static void *_p_FootprintGaussTo_p_IFootprintFactor(void *x, int *SWIGUNUSEDPARM(newmemory)) {
+    return (void *)((IFootprintFactor *)  ((FootprintGauss *) x));
 }
-static void *_p_LineTo_p_ICloneable(void *x, int *SWIGUNUSEDPARM(newmemory)) {
-    return (void *)((ICloneable *) (IShape2D *) ((Line *) x));
+static void *_p_ResolutionFunction2DGaussianTo_p_IResolutionFunction2D(void *x, int *SWIGUNUSEDPARM(newmemory)) {
+    return (void *)((IResolutionFunction2D *)  ((ResolutionFunction2DGaussian *) x));
 }
 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};
@@ -46853,7 +47616,7 @@ static swig_type_info _swigt__p_BasicVector3DT_std__complexT_double_t_t = {"_p_B
 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_CloneableVectorT_IAxis_t = {"_p_CloneableVectorT_IAxis_t", "CloneableVector< IAxis > *", 0, 0, (void*)0, 0};
-static swig_type_info _swigt__p_DetectionProperties = {"_p_DetectionProperties", "DetectionProperties *", 0, 0, (void*)0, 0};
+static swig_type_info _swigt__p_CoordSystem2D = {"_p_CoordSystem2D", "CoordSystem2D *", 0, 0, (void*)0, 0};
 static swig_type_info _swigt__p_DetectorMask = {"_p_DetectorMask", "DetectorMask *", 0, 0, (void*)0, 0};
 static swig_type_info _swigt__p_Direction = {"_p_Direction", "Direction *", 0, 0, (void*)0, 0};
 static swig_type_info _swigt__p_Ellipse = {"_p_Ellipse", "Ellipse *", 0, 0, (void*)0, 0};
@@ -46878,6 +47641,7 @@ static swig_type_info _swigt__p_IPixel = {"_p_IPixel", "IPixel *", 0, 0, (void*)
 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};
 static swig_type_info _swigt__p_IShape2D = {"_p_IShape2D", "IShape2D *", 0, 0, (void*)0, 0};
+static swig_type_info _swigt__p_Instrument = {"_p_Instrument", "Instrument *", 0, 0, (void*)0, 0};
 static swig_type_info _swigt__p_IntensityDataIOFactory = {"_p_IntensityDataIOFactory", "IntensityDataIOFactory *", 0, 0, (void*)0, 0};
 static swig_type_info _swigt__p_IsGISAXSDetector = {"_p_IsGISAXSDetector", "IsGISAXSDetector *", 0, 0, (void*)0, 0};
 static swig_type_info _swigt__p_Line = {"_p_Line", "Line *", 0, 0, (void*)0, 0};
@@ -46886,6 +47650,8 @@ static swig_type_info _swigt__p_OutputDataIteratorT_double_const_OutputDataT_dou
 static swig_type_info _swigt__p_OutputDataT_CumulativeValue_t = {"_p_OutputDataT_CumulativeValue_t", "OutputData< CumulativeValue > *", 0, 0, (void*)0, 0};
 static swig_type_info _swigt__p_OutputDataT_bool_t = {"_p_OutputDataT_bool_t", "OutputData< bool > *", 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_PolFilter = {"_p_PolFilter", "PolFilter *", 0, 0, (void*)0, 0};
+static swig_type_info _swigt__p_PolMatrices = {"_p_PolMatrices", "PolMatrices *", 0, 0, (void*)0, 0};
 static swig_type_info _swigt__p_Polygon = {"_p_Polygon", "Polygon *", 0, 0, (void*)0, 0};
 static swig_type_info _swigt__p_PolygonPrivate = {"_p_PolygonPrivate", "PolygonPrivate *", 0, 0, (void*)0, 0};
 static swig_type_info _swigt__p_RealLimits = {"_p_RealLimits", "RealLimits *", 0, 0, (void*)0, 0};
@@ -46965,7 +47731,7 @@ static swig_type_info *swig_type_initial[] = {
   &_swigt__p_Beam,
   &_swigt__p_Bin1D,
   &_swigt__p_CloneableVectorT_IAxis_t,
-  &_swigt__p_DetectionProperties,
+  &_swigt__p_CoordSystem2D,
   &_swigt__p_DetectorMask,
   &_swigt__p_Direction,
   &_swigt__p_Ellipse,
@@ -46989,6 +47755,7 @@ static swig_type_info *swig_type_initial[] = {
   &_swigt__p_IRangedDistribution,
   &_swigt__p_IResolutionFunction2D,
   &_swigt__p_IShape2D,
+  &_swigt__p_Instrument,
   &_swigt__p_IntensityDataIOFactory,
   &_swigt__p_IsGISAXSDetector,
   &_swigt__p_Line,
@@ -46998,6 +47765,8 @@ static swig_type_info *swig_type_initial[] = {
   &_swigt__p_OutputDataT_bool_t,
   &_swigt__p_OutputDataT_double_t,
   &_swigt__p_ParameterDistribution,
+  &_swigt__p_PolFilter,
+  &_swigt__p_PolMatrices,
   &_swigt__p_Polygon,
   &_swigt__p_PolygonPrivate,
   &_swigt__p_RealLimits,
@@ -47077,7 +47846,7 @@ static swig_cast_info _swigc__p_BasicVector3DT_std__complexT_double_t_t[] = {  {
 static swig_cast_info _swigc__p_Beam[] = {  {&_swigt__p_Beam, 0, 0, 0},{0, 0, 0, 0}};
 static swig_cast_info _swigc__p_Bin1D[] = {  {&_swigt__p_Bin1D, 0, 0, 0},{0, 0, 0, 0}};
 static swig_cast_info _swigc__p_CloneableVectorT_IAxis_t[] = {  {&_swigt__p_CloneableVectorT_IAxis_t, 0, 0, 0},{0, 0, 0, 0}};
-static swig_cast_info _swigc__p_DetectionProperties[] = {  {&_swigt__p_DetectionProperties, 0, 0, 0},{0, 0, 0, 0}};
+static swig_cast_info _swigc__p_CoordSystem2D[] = {  {&_swigt__p_CoordSystem2D, 0, 0, 0},{0, 0, 0, 0}};
 static swig_cast_info _swigc__p_DetectorMask[] = {  {&_swigt__p_DetectorMask, 0, 0, 0},{0, 0, 0, 0}};
 static swig_cast_info _swigc__p_Direction[] = {  {&_swigt__p_Direction, 0, 0, 0},{0, 0, 0, 0}};
 static swig_cast_info _swigc__p_Ellipse[] = {  {&_swigt__p_Ellipse, 0, 0, 0},{0, 0, 0, 0}};
@@ -47094,14 +47863,15 @@ static swig_cast_info _swigc__p_IDetector2D[] = {  {&_swigt__p_RectangularDetect
 static swig_cast_info _swigc__p_IDetectorResolution[] = {  {&_swigt__p_IDetectorResolution, 0, 0, 0},{0, 0, 0, 0}};
 static swig_cast_info _swigc__p_IFootprintFactor[] = {  {&_swigt__p_FootprintSquare, _p_FootprintSquareTo_p_IFootprintFactor, 0, 0},  {&_swigt__p_IFootprintFactor, 0, 0, 0},  {&_swigt__p_FootprintGauss, _p_FootprintGaussTo_p_IFootprintFactor, 0, 0},{0, 0, 0, 0}};
 static swig_cast_info _swigc__p_IHistogram[] = {  {&_swigt__p_IHistogram, 0, 0, 0},  {&_swigt__p_Histogram2D, _p_Histogram2DTo_p_IHistogram, 0, 0},  {&_swigt__p_Histogram1D, _p_Histogram1DTo_p_IHistogram, 0, 0},{0, 0, 0, 0}};
-static swig_cast_info _swigc__p_INode[] = {  {&_swigt__p_INode, 0, 0, 0},  {&_swigt__p_FootprintSquare, _p_FootprintSquareTo_p_INode, 0, 0},  {&_swigt__p_IDetectorResolution, _p_IDetectorResolutionTo_p_INode, 0, 0},  {&_swigt__p_IFootprintFactor, _p_IFootprintFactorTo_p_INode, 0, 0},  {&_swigt__p_Beam, _p_BeamTo_p_INode, 0, 0},  {&_swigt__p_IResolutionFunction2D, _p_IResolutionFunction2DTo_p_INode, 0, 0},  {&_swigt__p_ResolutionFunction2DGaussian, _p_ResolutionFunction2DGaussianTo_p_INode, 0, 0},  {&_swigt__p_IDetector, _p_IDetectorTo_p_INode, 0, 0},  {&_swigt__p_RectangularDetector, _p_RectangularDetectorTo_p_INode, 0, 0},  {&_swigt__p_SphericalDetector, _p_SphericalDetectorTo_p_INode, 0, 0},  {&_swigt__p_IsGISAXSDetector, _p_IsGISAXSDetectorTo_p_INode, 0, 0},  {&_swigt__p_FootprintGauss, _p_FootprintGaussTo_p_INode, 0, 0},  {&_swigt__p_IDetector2D, _p_IDetector2DTo_p_INode, 0, 0},{0, 0, 0, 0}};
+static swig_cast_info _swigc__p_INode[] = {  {&_swigt__p_Beam, _p_BeamTo_p_INode, 0, 0},  {&_swigt__p_FootprintGauss, _p_FootprintGaussTo_p_INode, 0, 0},  {&_swigt__p_IDetectorResolution, _p_IDetectorResolutionTo_p_INode, 0, 0},  {&_swigt__p_IDetector2D, _p_IDetector2DTo_p_INode, 0, 0},  {&_swigt__p_ResolutionFunction2DGaussian, _p_ResolutionFunction2DGaussianTo_p_INode, 0, 0},  {&_swigt__p_IFootprintFactor, _p_IFootprintFactorTo_p_INode, 0, 0},  {&_swigt__p_Instrument, _p_InstrumentTo_p_INode, 0, 0},  {&_swigt__p_IDetector, _p_IDetectorTo_p_INode, 0, 0},  {&_swigt__p_IsGISAXSDetector, _p_IsGISAXSDetectorTo_p_INode, 0, 0},  {&_swigt__p_SphericalDetector, _p_SphericalDetectorTo_p_INode, 0, 0},  {&_swigt__p_RectangularDetector, _p_RectangularDetectorTo_p_INode, 0, 0},  {&_swigt__p_FootprintSquare, _p_FootprintSquareTo_p_INode, 0, 0},  {&_swigt__p_IResolutionFunction2D, _p_IResolutionFunction2DTo_p_INode, 0, 0},  {&_swigt__p_INode, 0, 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_ParameterDistribution[] = {{&_swigt__p_ParameterDistribution, 0, 0, 0},{0, 0, 0, 0}};
-static swig_cast_info _swigc__p_IParametric[] = {  {&_swigt__p_Beam, _p_BeamTo_p_IParametric, 0, 0},  {&_swigt__p_FootprintGauss, _p_FootprintGaussTo_p_IParametric, 0, 0},  {&_swigt__p_IDetectorResolution, _p_IDetectorResolutionTo_p_IParametric, 0, 0},  {&_swigt__p_IDetector2D, _p_IDetector2DTo_p_IParametric, 0, 0},  {&_swigt__p_IParametric, 0, 0, 0},  {&_swigt__p_ResolutionFunction2DGaussian, _p_ResolutionFunction2DGaussianTo_p_IParametric, 0, 0},  {&_swigt__p_IFootprintFactor, _p_IFootprintFactorTo_p_IParametric, 0, 0},  {&_swigt__p_IDetector, _p_IDetectorTo_p_IParametric, 0, 0},  {&_swigt__p_IsGISAXSDetector, _p_IsGISAXSDetectorTo_p_IParametric, 0, 0},  {&_swigt__p_SphericalDetector, _p_SphericalDetectorTo_p_IParametric, 0, 0},  {&_swigt__p_RectangularDetector, _p_RectangularDetectorTo_p_IParametric, 0, 0},  {&_swigt__p_ParameterDistribution, _p_ParameterDistributionTo_p_IParametric, 0, 0},  {&_swigt__p_FootprintSquare, _p_FootprintSquareTo_p_IParametric, 0, 0},  {&_swigt__p_INode, _p_INodeTo_p_IParametric, 0, 0},  {&_swigt__p_IResolutionFunction2D, _p_IResolutionFunction2DTo_p_IParametric, 0, 0},{0, 0, 0, 0}};
+static swig_cast_info _swigc__p_IParametric[] = {  {&_swigt__p_Beam, _p_BeamTo_p_IParametric, 0, 0},  {&_swigt__p_FootprintGauss, _p_FootprintGaussTo_p_IParametric, 0, 0},  {&_swigt__p_IDetectorResolution, _p_IDetectorResolutionTo_p_IParametric, 0, 0},  {&_swigt__p_IDetector2D, _p_IDetector2DTo_p_IParametric, 0, 0},  {&_swigt__p_IParametric, 0, 0, 0},  {&_swigt__p_ResolutionFunction2DGaussian, _p_ResolutionFunction2DGaussianTo_p_IParametric, 0, 0},  {&_swigt__p_IFootprintFactor, _p_IFootprintFactorTo_p_IParametric, 0, 0},  {&_swigt__p_Instrument, _p_InstrumentTo_p_IParametric, 0, 0},  {&_swigt__p_IDetector, _p_IDetectorTo_p_IParametric, 0, 0},  {&_swigt__p_IsGISAXSDetector, _p_IsGISAXSDetectorTo_p_IParametric, 0, 0},  {&_swigt__p_SphericalDetector, _p_SphericalDetectorTo_p_IParametric, 0, 0},  {&_swigt__p_RectangularDetector, _p_RectangularDetectorTo_p_IParametric, 0, 0},  {&_swigt__p_ParameterDistribution, _p_ParameterDistributionTo_p_IParametric, 0, 0},  {&_swigt__p_FootprintSquare, _p_FootprintSquareTo_p_IParametric, 0, 0},  {&_swigt__p_INode, _p_INodeTo_p_IParametric, 0, 0},  {&_swigt__p_IResolutionFunction2D, _p_IResolutionFunction2DTo_p_IParametric, 0, 0},{0, 0, 0, 0}};
 static swig_cast_info _swigc__p_IPixel[] = {  {&_swigt__p_IPixel, 0, 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},  {&_swigt__p_ResolutionFunction2DGaussian, _p_ResolutionFunction2DGaussianTo_p_IResolutionFunction2D, 0, 0},{0, 0, 0, 0}};
 static swig_cast_info _swigc__p_IShape2D[] = {  {&_swigt__p_Polygon, _p_PolygonTo_p_IShape2D, 0, 0},  {&_swigt__p_Line, _p_LineTo_p_IShape2D, 0, 0},  {&_swigt__p_VerticalLine, _p_VerticalLineTo_p_IShape2D, 0, 0},  {&_swigt__p_Ellipse, _p_EllipseTo_p_IShape2D, 0, 0},  {&_swigt__p_HorizontalLine, _p_HorizontalLineTo_p_IShape2D, 0, 0},  {&_swigt__p_Rectangle, _p_RectangleTo_p_IShape2D, 0, 0},  {&_swigt__p_IShape2D, 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_IntensityDataIOFactory[] = {  {&_swigt__p_IntensityDataIOFactory, 0, 0, 0},{0, 0, 0, 0}};
 static swig_cast_info _swigc__p_IsGISAXSDetector[] = {  {&_swigt__p_IsGISAXSDetector, 0, 0, 0},{0, 0, 0, 0}};
 static swig_cast_info _swigc__p_Line[] = {  {&_swigt__p_Line, 0, 0, 0},{0, 0, 0, 0}};
@@ -47110,6 +47880,8 @@ static swig_cast_info _swigc__p_OutputDataIteratorT_double_const_OutputDataT_dou
 static swig_cast_info _swigc__p_OutputDataT_CumulativeValue_t[] = {  {&_swigt__p_OutputDataT_CumulativeValue_t, 0, 0, 0},{0, 0, 0, 0}};
 static swig_cast_info _swigc__p_OutputDataT_bool_t[] = {  {&_swigt__p_OutputDataT_bool_t, 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_PolFilter[] = {  {&_swigt__p_PolFilter, 0, 0, 0},{0, 0, 0, 0}};
+static swig_cast_info _swigc__p_PolMatrices[] = {  {&_swigt__p_PolMatrices, 0, 0, 0},{0, 0, 0, 0}};
 static swig_cast_info _swigc__p_Polygon[] = {  {&_swigt__p_Polygon, 0, 0, 0},{0, 0, 0, 0}};
 static swig_cast_info _swigc__p_PolygonPrivate[] = {  {&_swigt__p_PolygonPrivate, 0, 0, 0},{0, 0, 0, 0}};
 static swig_cast_info _swigc__p_RealLimits[] = {  {&_swigt__p_RealLimits, 0, 0, 0},{0, 0, 0, 0}};
@@ -47189,7 +47961,7 @@ static swig_cast_info *swig_cast_initial[] = {
   _swigc__p_Beam,
   _swigc__p_Bin1D,
   _swigc__p_CloneableVectorT_IAxis_t,
-  _swigc__p_DetectionProperties,
+  _swigc__p_CoordSystem2D,
   _swigc__p_DetectorMask,
   _swigc__p_Direction,
   _swigc__p_Ellipse,
@@ -47213,6 +47985,7 @@ static swig_cast_info *swig_cast_initial[] = {
   _swigc__p_IRangedDistribution,
   _swigc__p_IResolutionFunction2D,
   _swigc__p_IShape2D,
+  _swigc__p_Instrument,
   _swigc__p_IntensityDataIOFactory,
   _swigc__p_IsGISAXSDetector,
   _swigc__p_Line,
@@ -47222,6 +47995,8 @@ static swig_cast_info *swig_cast_initial[] = {
   _swigc__p_OutputDataT_bool_t,
   _swigc__p_OutputDataT_double_t,
   _swigc__p_ParameterDistribution,
+  _swigc__p_PolFilter,
+  _swigc__p_PolMatrices,
   _swigc__p_Polygon,
   _swigc__p_PolygonPrivate,
   _swigc__p_RealLimits,