diff --git a/Core/Binning/SimulationElement.cpp b/Core/Binning/SimulationElement.cpp
index 5bd2690cf32f1adaad568c9043d26431d9f70e07..90d3fb3dae12f7efdc2504cbc85c5b0ccb8b4d0e 100644
--- a/Core/Binning/SimulationElement.cpp
+++ b/Core/Binning/SimulationElement.cpp
@@ -19,11 +19,14 @@
 #include <vector>
 
 SimulationElement::SimulationElement(double wavelength, double alpha_i, double phi_i,
-                                     const IPixelMap* pixelmap)
-    : m_wavelength(wavelength), m_alpha_i(alpha_i), m_phi_i(phi_i), m_intensity(0.0)
+                                     std::unique_ptr<IPixelMap> pixelmap)
+    : m_wavelength(wavelength)
+    , m_alpha_i(alpha_i)
+    , m_phi_i(phi_i)
+    , m_intensity(0.0)
+    , mP_pixel_map(std::move(pixelmap))
     , m_contains_specular(false)
 {
-    mP_pixel_map.reset(pixelmap->clone());
     initPolarization();
 }
 
diff --git a/Core/Binning/SimulationElement.h b/Core/Binning/SimulationElement.h
index cb8de5adc5f11449d0a482fae970533fa2cf5a2c..6b5b08d496401298bb23617e327a5bafa8ac29c0 100644
--- a/Core/Binning/SimulationElement.h
+++ b/Core/Binning/SimulationElement.h
@@ -32,7 +32,7 @@ class BA_CORE_API_ SimulationElement
 {
 public:
     SimulationElement(double wavelength, double alpha_i, double phi_i,
-                      const IPixelMap* pixelmap);
+                      std::unique_ptr<IPixelMap> pixelmap);
     SimulationElement(const SimulationElement &other);
     SimulationElement &operator=(const SimulationElement &other);
 
diff --git a/Core/Instrument/IDetector2D.cpp b/Core/Instrument/IDetector2D.cpp
index ce556abc6cf8cd4448bb5f291694c4fb54eac91e..6acb1923f0576f6d1f7a64b91170f1da96e9d839 100644
--- a/Core/Instrument/IDetector2D.cpp
+++ b/Core/Instrument/IDetector2D.cpp
@@ -19,6 +19,10 @@
 #include "InfinitePlane.h"
 #include "Logger.h"
 #include "SimulationElement.h"
+#include "SimulationArea.h"
+#include "BornAgainNamespace.h"
+#include "Units.h"
+#include "Exceptions.h"
 
 IDetector2D::IDetector2D()
     : m_axes()
@@ -28,12 +32,16 @@ IDetector2D::IDetector2D()
 }
 
 IDetector2D::IDetector2D(const IDetector2D &other)
-    : IParameterized(), m_axes(other.m_axes),
-      m_analyzer_operator(other.m_analyzer_operator), m_detector_mask(other.m_detector_mask)
+    : IParameterized(),
+      m_axes(other.m_axes),
+      m_analyzer_operator(other.m_analyzer_operator),
+      m_detector_mask(other.m_detector_mask)
 {
     setName(other.getName());
     if (other.mP_detector_resolution)
         mP_detector_resolution.reset(other.mP_detector_resolution->clone());
+    if(other.regionOfInterest())
+        m_region_of_interest.reset(other.regionOfInterest()->clone());
     init_parameters();
 }
 
@@ -109,9 +117,39 @@ std::string IDetector2D::addParametersToExternalPool(
     return new_path;
 }
 
-OutputData<double>* IDetector2D::createDetectorMap(const Beam&, EAxesUnits) const
+OutputData<double> *IDetector2D::getDetectorIntensity(const OutputData<double> &data,
+                                                      const Beam& beam,
+                                                      IDetector2D::EAxesUnits units_type) const
 {
-    return nullptr;
+    std::unique_ptr<OutputData<double>> result(data.clone());
+    applyDetectorResolution(result.get());
+
+    if(units_type == IDetector2D::DEFAULT && regionOfInterest() == nullptr)
+        return result.release();
+
+    std::unique_ptr<OutputData<double>> detectorMap(createDetectorMap(beam, units_type));
+    if(!detectorMap)
+        throw Exceptions::RuntimeErrorException("Instrument::getDetectorIntensity() -> Error."
+                                    "Can't create detector map.");
+
+    setDataToDetectorMap(*detectorMap.get(), *result.get());
+
+    return detectorMap.release();
+}
+
+OutputData<double>* IDetector2D::createDetectorMap(const Beam& beam, EAxesUnits units) const
+{
+    std::unique_ptr<OutputData<double>> result(new OutputData<double>);
+    result->addAxis(*constructAxis(BornAgain::X_AXIS_INDEX, beam, units));
+    result->addAxis(*constructAxis(BornAgain::Y_AXIS_INDEX, beam, units));
+    return result.release();
+}
+
+void IDetector2D::initOutputData(OutputData<double> &data) const {
+  data.clear();
+  for (size_t i = 0; i < getDimension(); ++i)
+      data.addAxis(getAxis(i));
+  data.setAllTo(0.);
 }
 
 std::vector<IDetector2D::EAxesUnits> IDetector2D::getValidAxesUnits() const
@@ -120,6 +158,21 @@ std::vector<IDetector2D::EAxesUnits> IDetector2D::getValidAxesUnits() const
     return result;
 }
 
+const Geometry::Rectangle *IDetector2D::regionOfInterest() const
+{
+    return m_region_of_interest.get();
+}
+
+void IDetector2D::setRegionOfInterest(double xlow, double ylow, double xup, double yup)
+{
+    m_region_of_interest.reset(new Geometry::Rectangle(xlow, ylow, xup, yup));
+}
+
+void IDetector2D::resetRegionOfInterest()
+{
+    m_region_of_interest.reset();
+}
+
 void IDetector2D::removeMasks()
 {
     m_detector_mask.removeMasks();
@@ -173,35 +226,40 @@ std::vector<SimulationElement> IDetector2D::createSimulationElements(const Beam
     Eigen::Matrix2cd beam_polarization = beam.getPolarization();
     Eigen::Matrix2cd analyzer_operator = getAnalyzerOperator();
 
-    if (getDimension()!=2)
-        throw Exceptions::RuntimeErrorException(
-            "IDetector2D::createSimulationElements: detector is not two-dimensional");
     if (!hasMasks())
         m_detector_mask.initMaskData(*this);
     size_t spec_index = getIndexOfSpecular(beam);
-    const OutputData<bool>* mask_data = m_detector_mask.getMaskData();
-    for (size_t index=0; index<mask_data->getAllocatedSize(); ++index) {
-        if ((*mask_data)[index]) continue;
-        const std::unique_ptr<IPixelMap> P_pixel_map(createPixelMap(index));
-        SimulationElement sim_element(wavelength, alpha_i, phi_i, P_pixel_map.get());
+
+    SimulationArea area(this);
+    for(SimulationArea::iterator it = area.begin(); it!=area.end(); ++it) {
+        SimulationElement sim_element(wavelength, alpha_i, phi_i,
+                                      std::unique_ptr<IPixelMap>(createPixelMap(it.index())));
         sim_element.setPolarization(beam_polarization);
         sim_element.setAnalyzerOperator(analyzer_operator);
-        if (index==spec_index) {
+        if (it.index()==spec_index) {
             sim_element.setSpecular(true);
         }
         result.push_back(sim_element);
     }
+
     return result;
 }
 
-//! create single simulation element
 SimulationElement IDetector2D::getSimulationElement(size_t index, const Beam &beam) const
 {
     double wavelength = beam.getWavelength();
     double alpha_i = - beam.getAlpha();  // Defined to be always positive in Beam
     double phi_i = beam.getPhi();
-    const std::unique_ptr<IPixelMap> P_pixel_map(createPixelMap(index));
-    return SimulationElement(wavelength, alpha_i, phi_i, P_pixel_map.get());
+    return SimulationElement(wavelength, alpha_i, phi_i,
+                             std::unique_ptr<IPixelMap>(createPixelMap(index)));
+}
+
+void IDetector2D::transferResultsToIntensityMap(OutputData<double> &data,
+    const std::vector<SimulationElement> &elements) const
+{
+    SimulationArea area(this);
+    for(SimulationArea::iterator it = area.begin(); it!=area.end(); ++it)
+        data[it.index()] = elements[it.elementIndex()].getIntensity();
 }
 
 bool IDetector2D::dataShapeMatches(const OutputData<double> *p_data) const
@@ -236,18 +294,84 @@ size_t IDetector2D::getAxisBinIndex(size_t index, size_t selected_axis) const
                                           "Error! No axis with given number");
 }
 
-size_t IDetector2D::getGlobalIndex(size_t x, size_t y) const
+std::unique_ptr<IAxis> IDetector2D::constructAxis(size_t axis_index, const Beam &beam,
+                                                  IDetector2D::EAxesUnits units) const
 {
-    if (getDimension()!=2) return getTotalSize();
-    return x*m_axes[1]->getSize()+y;
+    double amin(0), amax(0);
+    calculateAxisRange(axis_index, beam, units, amin, amax);
+
+    std::unique_ptr<IAxis> result(new FixedBinAxis(getAxisName(axis_index),
+                                                   getAxis(axis_index).getSize(), amin, amax));
+
+    if(m_region_of_interest) {
+        return clipAxisToRoi(axis_index, *result.get());
+    } else {
+        return result;
+    }
+}
+
+std::unique_ptr<IAxis> IDetector2D::clipAxisToRoi(size_t axis_index, const IAxis &axis) const
+{
+    if(!m_region_of_interest)
+        throw Exceptions::RuntimeErrorException("IDetector2D::clipAxisToRoi() -> Error. ROI is "
+                                                "absent");
+
+    size_t nbin1(0), nbin2(axis.getSize()-1);
+    if(axis_index == BornAgain::X_AXIS_INDEX) {
+        nbin1 = getAxis(axis_index).findClosestIndex(m_region_of_interest->getXlow());
+        nbin2 = getAxis(axis_index).findClosestIndex(m_region_of_interest->getXup());
+
+    }else if(axis_index == BornAgain::Y_AXIS_INDEX) {
+        nbin1 = getAxis(axis_index).findClosestIndex(m_region_of_interest->getYlow());
+        nbin2 = getAxis(axis_index).findClosestIndex(m_region_of_interest->getYup());
+    }
+
+    return std::unique_ptr<IAxis>(new FixedBinAxis(axis.getName(), nbin2-nbin1+1,
+                                    axis.getBin(nbin1).m_lower, axis.getBin(nbin2).m_upper));
 }
 
-void IDetector2D::swapContent(IDetector2D &other)
+void IDetector2D::calculateAxisRange(size_t axis_index, const Beam &beam,
+        IDetector2D::EAxesUnits units, double &amin, double &amax) const
 {
-    std::swap(this->m_axes, other.m_axes);
-    std::swap(this->mP_detector_resolution, other.mP_detector_resolution);
-    std::swap(this->m_analyzer_operator, other.m_analyzer_operator);
-    std::swap(this->m_detector_mask, other.m_detector_mask);
+    amin = 0.0; amax=0.0;
+
+    if(units == DEFAULT) {
+        amin = getAxis(axis_index).getMin();
+        amax = getAxis(axis_index).getMax();
+
+    }else if(units == NBINS) {
+        amin = 0.0;
+        amax = static_cast<double>(getAxis(axis_index).getSize());
+
+    } else if(units == QYQZ && axis_index == BornAgain::X_AXIS_INDEX) {
+        const IAxis &aX = getAxis(BornAgain::X_AXIS_INDEX);
+        SimulationElement el_left_bottom
+            = getSimulationElement(getGlobalIndex(0, 0), beam);
+        SimulationElement el_right_bottom
+            = getSimulationElement(getGlobalIndex(aX.getSize()-1, 0), beam);
+        amin = el_left_bottom.getQ(0.0, 0.0).y();
+        amax = el_right_bottom.getQ(1.0, 0.0).y();
+
+    } else if(units == QYQZ && axis_index == BornAgain::Y_AXIS_INDEX) {
+        const IAxis &aX = getAxis(BornAgain::X_AXIS_INDEX);
+        const IAxis &aY = getAxis(BornAgain::Y_AXIS_INDEX);
+        SimulationElement el_center_bottom
+            = getSimulationElement(getGlobalIndex(aX.getSize()/2, 0), beam);
+        SimulationElement el_center_top
+            = getSimulationElement(getGlobalIndex(aX.getSize()/2, aY.getSize()-1), beam);
+        amin = -el_center_bottom.getQ(0.5, 0.0).z();
+        amax = -el_center_top.getQ(0.5, 1.0).z();
+
+    } else {
+        throw Exceptions::RuntimeErrorException("IDetector2D::calculateAxisRange() -> Error. "
+                                                "Unknown units " +std::to_string(units));
+    }
+}
+
+size_t IDetector2D::getGlobalIndex(size_t x, size_t y) const
+{
+    if (getDimension()!=2) return getTotalSize();
+    return x*m_axes[1]->getSize()+y;
 }
 
 size_t IDetector2D::getTotalSize() const
@@ -292,6 +416,33 @@ Eigen::Matrix2cd IDetector2D::calculateAnalyzerOperator(
     return result;
 }
 
+void IDetector2D::setDataToDetectorMap(OutputData<double> &detectorMap,
+                                       const OutputData<double> &data) const
+{
+    if(detectorMap.getAllocatedSize() == data.getAllocatedSize()) {
+        detectorMap.setRawDataVector(data.getRawDataVector());
+        return;
+    }
+
+    if(const Geometry::Rectangle *roi = regionOfInterest()) {
+        size_t roi_x = getAxis(BornAgain::X_AXIS_INDEX).findClosestIndex(roi->getXlow());
+        size_t roi_y = getAxis(BornAgain::Y_AXIS_INDEX).findClosestIndex(roi->getYlow());
+        size_t index0 = getGlobalIndex(roi_x, roi_y);
+        const IAxis &yAxisOfDetector = getAxis(BornAgain::Y_AXIS_INDEX);
+
+        const IAxis &xAxisOfMap = *detectorMap.getAxis(BornAgain::X_AXIS_INDEX);
+        const IAxis &yAxisOfMap = *detectorMap.getAxis(BornAgain::Y_AXIS_INDEX);
+        for(size_t ix=0; ix<xAxisOfMap.getSize(); ++ix) {
+            for(size_t iy=0; iy<yAxisOfMap.getSize(); ++iy) {
+                size_t mapIndex = iy + ix*yAxisOfMap.getSize();
+                size_t globalIndex = index0 + iy + ix*yAxisOfDetector.getSize();
+                detectorMap[mapIndex] = data[globalIndex];
+            }
+        }
+    }
+
+}
+
 void IDetector2D::addAxis(const IAxis& axis)
 {
     m_axes.push_back(axis.clone());
diff --git a/Core/Instrument/IDetector2D.h b/Core/Instrument/IDetector2D.h
index fc3d84665098ffbe5dd8d3204dfdbd5357a1a573..cdcf91363fbd6e2c365bfb2eef86b4362cf76db6 100644
--- a/Core/Instrument/IDetector2D.h
+++ b/Core/Instrument/IDetector2D.h
@@ -22,6 +22,7 @@
 #include "EigenCore.h"
 #include "SafePointerVector.h"
 #include "Vectors3D.h"
+#include "Rectangle.h"
 #include <memory>
 
 template<class T> class OutputData;
@@ -38,13 +39,12 @@ namespace Geometry {
 //! @ingroup simulation
 //! @brief The detector interface.
 
-class BA_CORE_API_ IDetector2D : public IParameterized
+class BA_CORE_API_ IDetector2D : public ICloneable, public IParameterized
 {
 public:
     enum EAxesUnits {DEFAULT, NBINS, RADIANS, DEGREES, MM, QYQZ};
 
     IDetector2D();
-    IDetector2D(const IDetector2D& other);
 
     virtual IDetector2D* clone() const=0;
 
@@ -114,15 +114,29 @@ public:
 #ifndef SWIG
     //! Create a vector of SimulationElement objects according to the detector and its mask
     std::vector<SimulationElement> createSimulationElements(const Beam& beam);
+
+    //! Creates single simulation element.
     SimulationElement getSimulationElement(size_t index, const Beam& beam) const;
+
+    void transferResultsToIntensityMap(OutputData<double> &data,
+                                       const std::vector<SimulationElement> &elements) const;
 #endif
 
     //! Adds parameters from local pool to external pool and recursively calls its direct children.
     virtual std::string addParametersToExternalPool(
         const std::string& path, ParameterPool* external_pool, int copy_number = -1) const;
 
+    //! Returns clone of the intensity map with detector resolution applied,
+    //! axes of map will be in requested units
+    OutputData<double>* getDetectorIntensity(
+        const OutputData<double>& data, const Beam& beam,
+        IDetector2D::EAxesUnits units_type=IDetector2D::DEFAULT) const;
+
     //! Returns detector map in given axes units
-    virtual OutputData<double>* createDetectorMap(const Beam&, EAxesUnits) const;
+    virtual OutputData<double>* createDetectorMap(const Beam& beam, EAxesUnits units) const;
+
+    //! Inits axes of OutputData to match the detector and sets values to zero.
+    virtual void initOutputData(OutputData<double> &data) const;
 
     //! returns vector of valid axes units
     virtual std::vector<EAxesUnits> getValidAxesUnits() const;
@@ -130,7 +144,24 @@ public:
     //! return default axes units
     virtual EAxesUnits getDefaultAxesUnits() const { return DEFAULT; }
 
+    //! Returns region of  interest if exists.
+    const Geometry::Rectangle* regionOfInterest() const;
+
+    //! Sets rectangular region of interest with lower left and uppre right corners defined.
+    void setRegionOfInterest(double xlow, double ylow, double xup, double yup);
+
+    //! Resets region of interest making whole detector plane available for the simulation.
+    void resetRegionOfInterest();
+
+    //! Returns total number of pixels
+    size_t getTotalSize() const;
+
+    //! Calculate axis index for given global index
+    size_t getAxisBinIndex(size_t index, size_t selected_axis) const;
+
 protected:
+    IDetector2D(const IDetector2D& other);
+
     //! Create an IPixelMap for the given OutputData object and index
     virtual IPixelMap* createPixelMap(size_t index) const=0;
 
@@ -140,6 +171,16 @@ protected:
     //! Generates an axis with correct name and default binning for given index
     virtual IAxis* createAxis(size_t index, size_t n_bins, double min, double max) const=0;
 
+    //! Constructs axis with min,max corresponding to selected units
+    std::unique_ptr<IAxis> constructAxis(size_t axis_index, const Beam& beam,
+                                         EAxesUnits units) const;
+
+    std::unique_ptr<IAxis> clipAxisToRoi(size_t axis_index, const IAxis &axis) const;
+
+    //! Calculates axis range from original detector axes in given units (mm, rad, etc)
+    virtual void calculateAxisRange(size_t axis_index, const Beam& beam, EAxesUnits units,
+                                    double &amin, double &amax) const;
+
     //! Returns the name for the axis with given index
     virtual std::string getAxisName(size_t index) const=0;
 
@@ -151,23 +192,14 @@ protected:
     //! Initialize polarization (for constructors)
     void initPolarizationOperator();
 
-    //! Calculate axis index for given global index
-    size_t getAxisBinIndex(size_t index, size_t selected_axis) const;
-
     //! Calculate global index from two axis indices
     size_t getGlobalIndex(size_t x, size_t y) const;
 
-    //! swap function
-    void swapContent(IDetector2D& other);
-
     //! Returns index of pixel that contains the specular wavevector.
     //! If no pixel contains this specular wavevector, the number of pixels is
     //! returned. This corresponds to an overflow index.
     virtual size_t getIndexOfSpecular(const Beam& beam) const=0;
 
-    //! Returns total number of pixels
-    size_t getTotalSize() const;
-
     SafePointerVector<IAxis> m_axes;
     std::unique_ptr<IDetectorResolution> mP_detector_resolution;
 #ifndef SWIG
@@ -183,6 +215,11 @@ private:
     Eigen::Matrix2cd calculateAnalyzerOperator(
         const kvector_t direction, double efficiency, double total_transmission = 1.0) const;
 #endif
+
+    void setDataToDetectorMap(OutputData<double> &detectorMap,
+                              const OutputData<double> &data) const;
+
+    std::unique_ptr<Geometry::Rectangle> m_region_of_interest;
 };
 
 #endif // IDETECTOR2D_H
diff --git a/Core/Instrument/Instrument.cpp b/Core/Instrument/Instrument.cpp
index 01a3a5974518df72389de1d25fc8061c76425c3c..2672fd9e101c81c473175a81e40d9ec1369e1f75 100644
--- a/Core/Instrument/Instrument.cpp
+++ b/Core/Instrument/Instrument.cpp
@@ -122,19 +122,7 @@ void Instrument::applyDetectorResolution(OutputData<double>* p_intensity_map) co
 OutputData<double>* Instrument::getDetectorIntensity(
     const OutputData<double> &data, IDetector2D::EAxesUnits units_type) const
 {
-    std::unique_ptr<OutputData<double> > result (data.clone());
-    applyDetectorResolution(result.get());
-
-    if(units_type == IDetector2D::DEFAULT) {
-        return result.release();
-    } else {
-        OutputData<double>* detectorMap = mP_detector->createDetectorMap(m_beam, units_type);
-        if(!detectorMap)
-            throw Exceptions::RuntimeErrorException("Instrument::getDetectorIntensity() -> Error."
-                                        "Can't create detector map.");
-        detectorMap->setRawDataVector(result->getRawDataVector());
-        return detectorMap;
-    }
+    return mP_detector->getDetectorIntensity(data, m_beam, units_type);
 }
 
 void Instrument::print(std::ostream& ostr) const
diff --git a/Core/Instrument/IsGISAXSDetector.cpp b/Core/Instrument/IsGISAXSDetector.cpp
index d67134b11562541c7e94fea1154781e018c8d420..5b9815576d544b4a793a772ca692a8abd82fc6f1 100644
--- a/Core/Instrument/IsGISAXSDetector.cpp
+++ b/Core/Instrument/IsGISAXSDetector.cpp
@@ -39,15 +39,6 @@ IsGISAXSDetector::IsGISAXSDetector(const IsGISAXSDetector &other)
     init_parameters();
 }
 
-IsGISAXSDetector &IsGISAXSDetector::operator=(const IsGISAXSDetector &other)
-{
-    if (this != &other) {
-        IsGISAXSDetector tmp(other);
-        tmp.swapContent(*this);
-    }
-    return *this;
-}
-
 IsGISAXSDetector *IsGISAXSDetector::clone() const
 {
     return new IsGISAXSDetector(*this);
diff --git a/Core/Instrument/IsGISAXSDetector.h b/Core/Instrument/IsGISAXSDetector.h
index ce3477c9caa628d4f1136c453734ac45a894189c..ad55b950178536874b6b7a121b30c5be1b6f7015 100644
--- a/Core/Instrument/IsGISAXSDetector.h
+++ b/Core/Instrument/IsGISAXSDetector.h
@@ -27,10 +27,8 @@ class BA_CORE_API_ IsGISAXSDetector : public SphericalDetector
 public:
     IsGISAXSDetector();
     IsGISAXSDetector(size_t n_phi, double phi_min, double phi_max,
-                      size_t n_alpha, double alpha_min, double alpha_max);
-
+                     size_t n_alpha, double alpha_min, double alpha_max);
     IsGISAXSDetector(const IsGISAXSDetector &other);
-    IsGISAXSDetector &operator=(const IsGISAXSDetector &other);
 
     IsGISAXSDetector* clone() const override;
 
diff --git a/Core/Instrument/RectangularDetector.cpp b/Core/Instrument/RectangularDetector.cpp
index e263734473fbff9a5c230236e51d4e9f5267a43a..c98a8c4b2b7d77a105780ef70c47f43b7150dfd9 100644
--- a/Core/Instrument/RectangularDetector.cpp
+++ b/Core/Instrument/RectangularDetector.cpp
@@ -54,15 +54,6 @@ RectangularDetector::RectangularDetector(const RectangularDetector& other)
 
 RectangularDetector::~RectangularDetector() {}
 
-RectangularDetector& RectangularDetector::operator=(const RectangularDetector& other)
-{
-    if (this != &other) {
-        RectangularDetector tmp(other);
-        tmp.swapContent(*this);
-    }
-    return *this;
-}
-
 RectangularDetector *RectangularDetector::clone() const
 {
     return new RectangularDetector(*this);
@@ -202,69 +193,6 @@ RectangularDetector::EDetectorArrangement RectangularDetector::getDetectorArrang
     return m_detector_arrangement;
 }
 
-OutputData<double> *RectangularDetector::createDetectorMap(
-    const Beam& beam, IDetector2D::EAxesUnits units_type) const
-{
-    if (getDimension() != 2)
-        return 0;
-
-    std::unique_ptr<OutputData<double>> result(new OutputData<double>);
-    const IAxis& aX = getAxis(BornAgain::X_AXIS_INDEX);
-    const IAxis& aY = getAxis(BornAgain::Y_AXIS_INDEX);
-
-    result->addAxis(aX);
-    result->addAxis(aY);
-
-    if (units_type == DEFAULT)
-        return result.release();
-
-    std::vector<int> indices_left_bottom = {0, 0};
-    std::vector<int> indices_right_bottom = {(int)aX.getSize() - 1, 0};
-    std::vector<int> indices_center_bottom = {(int)aX.getSize() / 2, 0};
-    std::vector<int> indices_center_top = {(int)aX.getSize() / 2, (int)aY.getSize() - 1};
-    SimulationElement el_left_bottom
-        = getSimulationElement(result->toGlobalIndex(indices_left_bottom), beam);
-    SimulationElement el_right_bottom
-        = getSimulationElement(result->toGlobalIndex(indices_right_bottom), beam);
-    SimulationElement el_center_bottom
-        = getSimulationElement(result->toGlobalIndex(indices_center_bottom), beam);
-    SimulationElement el_center_top
-        = getSimulationElement(result->toGlobalIndex(indices_center_top), beam);
-
-    result->clear();
-
-    double xmin(aX.getMin()), xmax(aX.getMax()), ymin(aY.getMin()), ymax(aY.getMax());
-
-    if (units_type == NBINS) {
-        xmin = 0.0;
-        ymin = 0.0;
-        xmax = double(aX.getSize());
-        ymax = double(aY.getSize());
-    }
-
-    else if (units_type == RADIANS || units_type == DEGREES) {
-        double scale(1.0);
-        if (units_type == DEGREES)
-            scale = 1. / Units::degree;
-        xmin = scale * el_left_bottom.getPhi(0.0, 0.0);
-        xmax = scale * el_right_bottom.getPhi(1.0, 0.0);
-        ymin = scale * el_center_bottom.getAlpha(0.5, 0.0);
-        ymax = scale * el_center_top.getAlpha(0.5, 1.0);
-    }
-
-    else if (units_type == QYQZ) {
-        xmin = el_left_bottom.getQ(0.0, 0.0).y();
-        xmax = el_right_bottom.getQ(1.0, 0.0).y();
-        ymin = -el_center_bottom.getQ(0.5, 0.0).z();
-        ymax = -el_center_top.getQ(0.5, 1.0).z();
-    }
-
-    result->addAxis(FixedBinAxis(BornAgain::U_AXIS_NAME, aX.getSize(), xmin, xmax));
-    result->addAxis(FixedBinAxis(BornAgain::V_AXIS_NAME, aY.getSize(), ymin, ymax));
-
-    return result.release();
-}
-
 std::vector<IDetector2D::EAxesUnits> RectangularDetector::getValidAxesUnits() const
 {
     std::vector<IDetector2D::EAxesUnits> result = IDetector2D::getValidAxesUnits();
@@ -297,6 +225,43 @@ IAxis *RectangularDetector::createAxis(size_t index, size_t n_bins, double min,
     return new FixedBinAxis(getAxisName(index), n_bins, min, max);
 }
 
+void RectangularDetector::calculateAxisRange(size_t axis_index, const Beam &beam,
+    IDetector2D::EAxesUnits units, double &amin, double &amax) const
+{
+    amin = 0.0; amax=0.0;
+    if(units == MM) {
+        amin = getAxis(axis_index).getMin();
+        amax = getAxis(axis_index).getMax();
+    }else if(units == RADIANS || units == DEGREES) {
+        double scale(1.0);
+        if (units == DEGREES)
+            scale = 1. / Units::degree;
+
+        if(axis_index == BornAgain::X_AXIS_INDEX) {
+            const IAxis &aX = getAxis(BornAgain::X_AXIS_INDEX);
+            SimulationElement el_left_bottom
+                = getSimulationElement(getGlobalIndex(0, 0), beam);
+            SimulationElement el_right_bottom
+                = getSimulationElement(getGlobalIndex(aX.getSize()-1, 0), beam);
+            amin = scale * el_left_bottom.getPhi(0.0, 0.0);
+            amax = scale * el_right_bottom.getPhi(1.0, 0.0);
+        } else if(axis_index == BornAgain::Y_AXIS_INDEX) {
+            const IAxis &aX = getAxis(BornAgain::X_AXIS_INDEX);
+            const IAxis &aY = getAxis(BornAgain::Y_AXIS_INDEX);
+            SimulationElement el_center_bottom
+                = getSimulationElement(getGlobalIndex(aX.getSize()/2, 0), beam);
+            SimulationElement el_center_top
+                = getSimulationElement(getGlobalIndex(aX.getSize()/2, aY.getSize()-1), beam);
+            amin = scale * el_center_bottom.getAlpha(0.5, 0.0);
+            amax = scale * el_center_top.getAlpha(0.5, 1.0);
+        }
+
+    } else {
+        IDetector2D::calculateAxisRange(axis_index, beam, units, amin, amax);
+    }
+
+}
+
 std::string RectangularDetector::getAxisName(size_t index) const
 {
     switch (index) {
@@ -332,14 +297,6 @@ size_t RectangularDetector::getIndexOfSpecular(const Beam& beam) const
     return getTotalSize();
 }
 
-void RectangularDetector::swapContent(RectangularDetector& other)
-{
-    IDetector2D::swapContent(other);
-    std::swap(this->m_normal_to_detector, other.m_normal_to_detector);
-    std::swap(this->m_u_unit, other.m_u_unit);
-    std::swap(this->m_v_unit, other.m_v_unit);
-}
-
 void RectangularDetector::setDistanceAndOffset(double distance, double u0, double v0)
 {
     if(distance <= 0.0) {
diff --git a/Core/Instrument/RectangularDetector.h b/Core/Instrument/RectangularDetector.h
index eb6f5f6834a3665be869c8f8a4dc91f0bdd1697c..10ce698d7919ea6584684724ea0a24413b7ccdd8 100644
--- a/Core/Instrument/RectangularDetector.h
+++ b/Core/Instrument/RectangularDetector.h
@@ -42,7 +42,6 @@ public:
     RectangularDetector(int nxbins, double width, int nybins, double height);
 
     RectangularDetector(const RectangularDetector& other);
-    RectangularDetector& operator=(const RectangularDetector& other);
 
     RectangularDetector* clone() const override;
 
@@ -76,9 +75,6 @@ public:
     double getDirectBeamV0() const;
     EDetectorArrangement getDetectorArrangment() const;
 
-    //! Returns detector map in given axes units
-    OutputData<double>* createDetectorMap(const Beam& beam, EAxesUnits units_type) const override;
-
     //! returns vector of valid axes units
     std::vector<EAxesUnits> getValidAxesUnits() const override;
 
@@ -97,6 +93,10 @@ protected:
     //! Generates an axis with correct name and default binning for given index
     IAxis* createAxis(size_t index, size_t n_bins, double min, double max) const override;
 
+    //! Calculates axis range from original detector axes in given units (mm, rad, etc)
+    virtual void calculateAxisRange(size_t axis_index, const Beam& beam, EAxesUnits units,
+                                    double &amin, double &amax) const override;
+
     //! Returns the name for the axis with given index
     std::string getAxisName(size_t index) const override;
 
diff --git a/Core/Instrument/SimulationArea.cpp b/Core/Instrument/SimulationArea.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..7337f083323067326bde7147dc4dd303cb00e012
--- /dev/null
+++ b/Core/Instrument/SimulationArea.cpp
@@ -0,0 +1,79 @@
+// ************************************************************************** //
+//
+//  BornAgain: simulate and fit scattering at grazing incidence
+//
+//! @file      Core/Instrument/SimulationArea.cpp
+//! @brief     Implements class SimulationArea.
+//!
+//! @homepage  http://www.bornagainproject.org
+//! @license   GNU General Public License v3 or higher (see COPYING)
+//! @copyright Forschungszentrum Jülich GmbH 2015
+//! @authors   Scientific Computing Group at MLZ Garching
+//! @authors   C. Durniak, M. Ganeva, G. Pospelov, W. Van Herck, J. Wuttke
+//
+// ************************************************************************** //
+
+#include "SimulationArea.h"
+#include "IDetector2D.h"
+#include "Exceptions.h"
+#include "Rectangle.h"
+#include "IntensityDataFunctions.h"
+#include "BornAgainNamespace.h"
+#include <sstream>
+
+SimulationArea::SimulationArea(const IDetector2D *detector)
+    : m_detector(detector)
+    , m_roi_x1(0)
+    , m_roi_x2(0)
+    , m_roi_y1(0)
+    , m_roi_y2(0)
+{
+    if(detector == nullptr)
+        throw Exceptions::RuntimeErrorException("SimulationArea::SimulationArea -> Error. "
+                                                "Detector nullptr.");
+
+    if (m_detector->getDimension()!=2)
+        throw Exceptions::RuntimeErrorException(
+            "SimulationArea::SimulationArea: detector is not two-dimensional");
+
+    if(const Geometry::Rectangle *roi = m_detector->regionOfInterest()) {
+        m_roi_x1 = detector->getAxis(BornAgain::X_AXIS_INDEX).findClosestIndex(roi->getXlow());
+        m_roi_x2 = detector->getAxis(BornAgain::X_AXIS_INDEX).findClosestIndex(roi->getXup());
+        m_roi_y1 = detector->getAxis(BornAgain::Y_AXIS_INDEX).findClosestIndex(roi->getYlow());
+        m_roi_y2 = detector->getAxis(BornAgain::Y_AXIS_INDEX).findClosestIndex(roi->getYup());
+    }
+}
+
+SimulationAreaIterator SimulationArea::begin()
+{
+    return SimulationAreaIterator(this, 0);
+}
+
+SimulationAreaIterator SimulationArea::end()
+{
+    return SimulationAreaIterator(this, m_detector->getTotalSize());
+}
+
+bool SimulationArea::isMasked(size_t index) const
+{
+    if(index >= m_detector->getTotalSize()) {
+        std::ostringstream message;
+        message << "SimulationArea::isActive() -> Error. Index " << index << " is out of range, "
+             << "totalSize=" << m_detector->getTotalSize();
+        throw Exceptions::RuntimeErrorException(message.str());
+    }
+
+    if(m_detector->regionOfInterest()) {
+        size_t nx = m_detector->getAxisBinIndex(index, BornAgain::X_AXIS_INDEX);
+        if(nx<m_roi_x1 || nx>m_roi_x2) return true;
+        size_t ny = m_detector->getAxisBinIndex(index, BornAgain::Y_AXIS_INDEX);
+        if(ny<m_roi_y1 || ny>m_roi_y2) return true;
+    }
+
+    return m_detector->isMasked(index);
+}
+
+size_t SimulationArea::totalSize() const
+{
+    return m_detector->getTotalSize();
+}
diff --git a/Core/Instrument/SimulationArea.h b/Core/Instrument/SimulationArea.h
new file mode 100644
index 0000000000000000000000000000000000000000..c1ce8aa375f484e8e37e928ee2dc001975b80018
--- /dev/null
+++ b/Core/Instrument/SimulationArea.h
@@ -0,0 +1,47 @@
+// ************************************************************************** //
+//
+//  BornAgain: simulate and fit scattering at grazing incidence
+//
+//! @file      Core/Instrument/SimulationArea.h
+//! @brief     Defines class SimulationArea.
+//!
+//! @homepage  http://www.bornagainproject.org
+//! @license   GNU General Public License v3 or higher (see COPYING)
+//! @copyright Forschungszentrum Jülich GmbH 2015
+//! @authors   Scientific Computing Group at MLZ Garching
+//! @authors   C. Durniak, M. Ganeva, G. Pospelov, W. Van Herck, J. Wuttke
+//
+// ************************************************************************** //
+
+#ifndef SIMULATIONAREA_H
+#define SIMULATIONAREA_H
+
+#include "WinDllMacros.h"
+#include "SimulationAreaIterator.h"
+class IDetector2D;
+
+//! @class SimulationArea
+//! @ingroup simulation
+//! @brief The SimulationArea class holds iteration logic over active detector channels
+//! in the presence of masked areas and RegionOfInterest defined.
+
+class BA_CORE_API_ SimulationArea
+{
+public:
+    using iterator = SimulationAreaIterator;
+    explicit SimulationArea(const IDetector2D *detector);
+
+    SimulationAreaIterator begin();
+    SimulationAreaIterator end();
+
+    bool isMasked(size_t index) const;
+
+    size_t totalSize() const;
+
+private:
+    const IDetector2D *m_detector;
+    size_t m_roi_x1, m_roi_x2, m_roi_y1, m_roi_y2;
+};
+
+
+#endif
diff --git a/Core/Instrument/SimulationAreaIterator.cpp b/Core/Instrument/SimulationAreaIterator.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..dbbded7dc08f1c343228cf52481e2470e8896175
--- /dev/null
+++ b/Core/Instrument/SimulationAreaIterator.cpp
@@ -0,0 +1,64 @@
+// ************************************************************************** //
+//
+//  BornAgain: simulate and fit scattering at grazing incidence
+//
+//! @file      Core/Instrument/SimulationAreaIterator.cpp
+//! @brief     Implements class SimulationAreaIterator.
+//!
+//! @homepage  http://www.bornagainproject.org
+//! @license   GNU General Public License v3 or higher (see COPYING)
+//! @copyright Forschungszentrum Jülich GmbH 2015
+//! @authors   Scientific Computing Group at MLZ Garching
+//! @authors   C. Durniak, M. Ganeva, G. Pospelov, W. Van Herck, J. Wuttke
+//
+// ************************************************************************** //
+
+#include "SimulationAreaIterator.h"
+#include "SimulationArea.h"
+#include "IDetector2D.h"
+
+SimulationAreaIterator::SimulationAreaIterator(const SimulationArea *area, size_t start_at_index)
+    : m_area(area)
+    , m_index(start_at_index)
+    , m_element_index(0)
+{
+    if(m_index > m_area->totalSize())
+        throw Exceptions::RuntimeErrorException("SimulationAreaIterator::SimulationAreaIterator() "
+                                                "-> Error. Invalid initial index");
+
+    if(m_index != m_area->totalSize() && m_area->isMasked(m_index))
+        m_index = nextIndex(m_index);
+}
+
+SimulationAreaIterator &SimulationAreaIterator::operator++()
+{
+    size_t index = nextIndex(m_index);
+    if(index != m_index) {
+        ++m_element_index;
+        m_index = index;
+    }
+    return *this;
+}
+
+SimulationAreaIterator SimulationAreaIterator::operator++(int)
+{
+    SimulationAreaIterator result(*this);
+    this->operator++();
+    return result;
+}
+
+size_t SimulationAreaIterator::nextIndex(size_t currentIndex)
+{
+    size_t result = ++currentIndex;
+    if(result < m_area->totalSize()) {
+        while(m_area->isMasked(result)) {
+            ++result;
+            if(result == m_area->totalSize())
+                break;
+        }
+    } else {
+        return m_area->totalSize();
+    }
+    return result;
+}
+
diff --git a/Core/Instrument/SimulationAreaIterator.h b/Core/Instrument/SimulationAreaIterator.h
new file mode 100644
index 0000000000000000000000000000000000000000..b123975f24e3a6cf6b062f06b84880663178e022
--- /dev/null
+++ b/Core/Instrument/SimulationAreaIterator.h
@@ -0,0 +1,61 @@
+// ************************************************************************** //
+//
+//  BornAgain: simulate and fit scattering at grazing incidence
+//
+//! @file      Core/Instrument/SimulationAreaIterator.h
+//! @brief     Defines class SimulationAreaIterator.
+//!
+//! @homepage  http://www.bornagainproject.org
+//! @license   GNU General Public License v3 or higher (see COPYING)
+//! @copyright Forschungszentrum Jülich GmbH 2015
+//! @authors   Scientific Computing Group at MLZ Garching
+//! @authors   C. Durniak, M. Ganeva, G. Pospelov, W. Van Herck, J. Wuttke
+//
+// ************************************************************************** //
+
+#ifndef SIMULATIONAREAITERATOR_H
+#define SIMULATIONAREAITERATOR_H
+
+#include "WinDllMacros.h"
+#include <cstdlib>
+class SimulationArea;
+
+//! @class SimulationAreaIterator
+//! @ingroup simulation
+//! @brief The SimulationAreaIterator class is an iterator for SimulationArea.
+
+class BA_CORE_API_ SimulationAreaIterator
+{
+public:
+    explicit SimulationAreaIterator(const SimulationArea *area, size_t start_at_index);
+
+    size_t index() const { return m_index; }
+    size_t elementIndex() const { return m_element_index;}
+
+    bool operator==(const SimulationAreaIterator &other) const;
+    bool operator!=(const SimulationAreaIterator &other) const;
+
+    //! prefix increment
+    SimulationAreaIterator& operator++();
+
+    //! postfix increment
+    SimulationAreaIterator operator++(int);
+
+private:
+    size_t nextIndex(size_t currentIndex);
+    const SimulationArea *m_area;
+    size_t m_index;  //!< global index in detector plane defined by its axes
+    size_t m_element_index; //!< sequential number for SimulationElementVector
+};
+
+inline bool SimulationAreaIterator::operator==(const SimulationAreaIterator &other) const
+{
+  return m_area == other.m_area && m_index == other.m_index;
+}
+
+inline bool SimulationAreaIterator::operator!=(const SimulationAreaIterator &right) const
+{
+    return !(*this == right);
+}
+
+#endif
diff --git a/Core/Instrument/SphericalDetector.cpp b/Core/Instrument/SphericalDetector.cpp
index 2fc96693c114f48bfe1998f15d7343b5d9362de0..ec89427829eef2740522dac274bbabb35a7a2305 100644
--- a/Core/Instrument/SphericalDetector.cpp
+++ b/Core/Instrument/SphericalDetector.cpp
@@ -42,15 +42,6 @@ SphericalDetector::SphericalDetector(const SphericalDetector& other)
     init_parameters();
 }
 
-SphericalDetector& SphericalDetector::operator=(const SphericalDetector& other)
-{
-    if (this !=& other) {
-        SphericalDetector tmp(other);
-        tmp.swapContent(*this);
-    }
-    return *this;
-}
-
 SphericalDetector* SphericalDetector::clone() const
 {
     return new SphericalDetector(*this);
@@ -69,70 +60,6 @@ std::string SphericalDetector::addParametersToExternalPool(
     return new_path;
 }
 
-OutputData<double>* SphericalDetector::createDetectorMap(const Beam& beam,
-                                                         IDetector2D::EAxesUnits units_type) const
-{
-    if (getDimension() != 2)
-        return 0;
-
-    std::unique_ptr<OutputData<double>> result(new OutputData<double>);
-
-    const IAxis& aX = getAxis(BornAgain::X_AXIS_INDEX);
-    const IAxis& aY = getAxis(BornAgain::Y_AXIS_INDEX);
-
-    result->addAxis(aX);
-    result->addAxis(aY);
-
-    if (units_type == DEFAULT)
-        return result.release();
-
-    std::vector<int> indices_left_bottom = {0, 0};
-    std::vector<int> indices_right_bottom = {(int)aX.getSize() - 1, 0};
-    std::vector<int> indices_center_bottom = {(int)aX.getSize() / 2, 0};
-    std::vector<int> indices_center_top = {(int)aX.getSize() / 2, (int)aY.getSize() - 1};
-    SimulationElement el_left_bottom
-        = getSimulationElement(result->toGlobalIndex(indices_left_bottom), beam);
-    SimulationElement el_right_bottom
-        = getSimulationElement(result->toGlobalIndex(indices_right_bottom), beam);
-    SimulationElement el_center_bottom
-        = getSimulationElement(result->toGlobalIndex(indices_center_bottom), beam);
-    SimulationElement el_center_top
-        = getSimulationElement(result->toGlobalIndex(indices_center_top), beam);
-
-    result->clear();
-
-    double xmin(aX.getMin()), xmax(aX.getMax()), ymin(aY.getMin()), ymax(aY.getMax());
-
-    if (units_type == MM)
-        return 0;
-
-    else if (units_type == NBINS) {
-        xmin = 0.0;
-        ymin = 0.0;
-        xmax = double(aX.getSize());
-        ymax = double(aY.getSize());
-    }
-
-    else if (units_type == DEGREES) {
-        xmin = aX.getMin() / Units::degree;
-        xmax = aX.getMax() / Units::degree;
-        ymin = aY.getMin() / Units::degree;
-        ymax = aY.getMax() / Units::degree;
-    }
-
-    else if (units_type == QYQZ) {
-        xmin = el_left_bottom.getQ(0.0, 0.0).y();
-        xmax = el_right_bottom.getQ(1.0, 0.0).y();
-        ymin = -el_center_bottom.getQ(0.5, 0.0).z();
-        ymax = -el_center_top.getQ(0.5, 1.0).z();
-    }
-
-    result->addAxis(FixedBinAxis(BornAgain::PHI_AXIS_NAME, aX.getSize(), xmin, xmax));
-    result->addAxis(FixedBinAxis(BornAgain::ALPHA_AXIS_NAME, aY.getSize(), ymin, ymax));
-
-    return result.release();
-}
-
 std::vector<IDetector2D::EAxesUnits> SphericalDetector::getValidAxesUnits() const
 {
     std::vector<IDetector2D::EAxesUnits> result = IDetector2D::getValidAxesUnits();
@@ -177,6 +104,21 @@ IAxis* SphericalDetector::createAxis(size_t index, size_t n_bins, double min, do
     return new FixedBinAxis(getAxisName(index), n_bins, min, max);
 }
 
+void SphericalDetector::calculateAxisRange(size_t axis_index, const Beam &beam,
+        IDetector2D::EAxesUnits units, double &amin, double &amax) const
+{
+    amin = 0.0; amax=0.0;
+    if(units == DEGREES) {
+        amin = getAxis(axis_index).getMin()/Units::degree;
+        amax = getAxis(axis_index).getMax()/Units::degree;
+    }else if(units == RADIANS) {
+        amin = getAxis(axis_index).getMin();
+        amax = getAxis(axis_index).getMax();
+    } else {
+        IDetector2D::calculateAxisRange(axis_index, beam, units, amin, amax);
+    }
+}
+
 std::string SphericalDetector::getAxisName(size_t index) const
 {
     switch (index) {
diff --git a/Core/Instrument/SphericalDetector.h b/Core/Instrument/SphericalDetector.h
index fe38df6a952315e5f5a98d1d41c0273b4b758df0..81a6e588f8abcebe22f507c314f65f9b14df50ad 100644
--- a/Core/Instrument/SphericalDetector.h
+++ b/Core/Instrument/SphericalDetector.h
@@ -39,7 +39,6 @@ public:
                       size_t n_alpha, double alpha_min, double alpha_max);
 
     SphericalDetector(const SphericalDetector &other);
-    SphericalDetector &operator=(const SphericalDetector &other);
 
     SphericalDetector* clone() const override;
 
@@ -49,9 +48,6 @@ public:
     std::string addParametersToExternalPool(
         const std::string& path, ParameterPool* external_pool, int copy_number = -1) const override;
 
-    //! Returns detector map in given axes units
-    OutputData<double> *createDetectorMap(const Beam& beam, EAxesUnits units_type) const override;
-
     //! returns vector of valid axes units
     std::vector<EAxesUnits> getValidAxesUnits() const override;
 
@@ -70,6 +66,10 @@ protected:
     //! Generates an axis with correct name and default binning for given index
     IAxis* createAxis(size_t index, size_t n_bins, double min, double max) const override;
 
+    //! Calculates axis range from original detector axes in given units (mm, rad, etc)
+    virtual void calculateAxisRange(size_t axis_index, const Beam& beam, EAxesUnits units,
+                                    double &amin, double &amax) const override;
+
     //! Returns the name for the axis with given index
     std::string getAxisName(size_t index) const override;
 
diff --git a/Core/Simulation/GISASSimulation.cpp b/Core/Simulation/GISASSimulation.cpp
index 985c735e765246d2603485bd6b88f36e9af8206e..10bbd93639325f5c0f63d63ddbcdfdc976598173 100644
--- a/Core/Simulation/GISASSimulation.cpp
+++ b/Core/Simulation/GISASSimulation.cpp
@@ -58,7 +58,7 @@ int GISASSimulation::getNumberOfSimulationElements() const
         throw Exceptions::RuntimeErrorException("GISASSimulation::getNumberOfSimulationElements: "
                                     "detector is not two-dimensional");
     const IAxis& x_axis = m_instrument.getDetectorAxis(BornAgain::X_AXIS_INDEX);
-    const IAxis& y_axis = m_instrument.getDetectorAxis(BornAgain::X_AXIS_INDEX);
+    const IAxis& y_axis = m_instrument.getDetectorAxis(BornAgain::Y_AXIS_INDEX);
     int nmasked = getInstrument().getDetector()->getNumberOfMaskedChannels();
     return x_axis.getSize()*y_axis.getSize() - nmasked;
 }
@@ -142,8 +142,6 @@ void GISASSimulation::maskAll()
     m_instrument.getDetector()->maskAll();
 }
 
-// *** protected ***
-
 void GISASSimulation::initSimulationElementVector()
 {
     m_sim_elements = m_instrument.createSimulationElements();
@@ -151,26 +149,12 @@ void GISASSimulation::initSimulationElementVector()
 
 void GISASSimulation::transferResultsToIntensityMap()
 {
-    size_t detector_dimension = m_instrument.getDetectorDimension();
-    if (detector_dimension!=2)
-        throw Exceptions::RuntimeErrorException("GISASSimulation::transferResultsToIntensityMap: "
-                                    "detector is not two-dimensional");
-    updateIntensityMap();
-
-    size_t element_index(0);
-    for(size_t index=0; index<m_intensity_map.getAllocatedSize(); ++index) {
-        if(m_instrument.getDetector()->isMasked(index)) continue;
-        m_intensity_map[index] = m_sim_elements[element_index++].getIntensity();
-    }
+    m_instrument.getDetector()->transferResultsToIntensityMap(m_intensity_map, m_sim_elements);
 }
 
 void GISASSimulation::updateIntensityMap()
 {
-    m_intensity_map.clear();
-    size_t detector_dimension = m_instrument.getDetectorDimension();
-    for (size_t dim=0; dim<detector_dimension; ++dim)
-        m_intensity_map.addAxis(m_instrument.getDetectorAxis(dim));
-    m_intensity_map.setAllTo(0.);
+    m_instrument.getDetector()->initOutputData(m_intensity_map);
 }
 
 void GISASSimulation::initialize()
diff --git a/Core/Simulation/GISASSimulation.h b/Core/Simulation/GISASSimulation.h
index a32b5e400aed884ee7d14a043e2dabf7b1a57d88..13bc37e8724c6d961394ce9c3c16c424242bc6e1 100644
--- a/Core/Simulation/GISASSimulation.h
+++ b/Core/Simulation/GISASSimulation.h
@@ -62,6 +62,7 @@ public:
     void setDetector(const IDetector2D& detector);
 
     //! Sets detector parameters using axes of output data
+    //! TODO -> remove this after RegionOfInterest
     void setDetectorParameters(const OutputData<double>& output_data);
     void setDetectorParameters(const IHistogram& histogram);
 
diff --git a/Core/Simulation/OffSpecSimulation.cpp b/Core/Simulation/OffSpecSimulation.cpp
index 34b77b73a14648d86f8aa912261e229cec6f319f..c0c966d1886131649655938a9dad8aacbac87873 100644
--- a/Core/Simulation/OffSpecSimulation.cpp
+++ b/Core/Simulation/OffSpecSimulation.cpp
@@ -110,8 +110,6 @@ std::string OffSpecSimulation::addParametersToExternalPool(
     return new_path;
 }
 
-// *** protected ***
-
 void OffSpecSimulation::initSimulationElementVector()
 {
     m_sim_elements.clear();
@@ -135,7 +133,6 @@ void OffSpecSimulation::initSimulationElementVector()
 void OffSpecSimulation::transferResultsToIntensityMap()
 {
     checkInitialization();
-    updateIntensityMap();
     const IAxis& phi_axis = m_instrument.getDetectorAxis(0);
     size_t phi_f_size = phi_axis.getSize();
     if (phi_f_size*m_intensity_map.getAllocatedSize()!=m_sim_elements.size())
diff --git a/Core/StandardSamples/IFactory.h b/Core/StandardSamples/IFactory.h
index 138ca353304eb45cc2a39750cc143650f50c7a2e..5ef4e84e286af18349b92b248531540b5a9038d6 100644
--- a/Core/StandardSamples/IFactory.h
+++ b/Core/StandardSamples/IFactory.h
@@ -19,6 +19,7 @@
 #include "Exceptions.h"
 #include <functional>
 #include <map>
+#include <sstream>
 
 //! Base class for all factories.
 //! @ingroup tools_internal
@@ -43,19 +44,24 @@ public:
     //! Creates object by calling creation function corresponded to given identifier
     AbstractProduct* createItem(const Key& item_key) {
         auto it = m_callbacks.find(item_key);
-        if( it == m_callbacks.end() ) // unexpectedly not found
-            throw Exceptions::UnknownClassRegistrationException(
-                    "IFactory::createItem() -> Panic. Unknown item key");
-        // invoke the creation function
+        if( it == m_callbacks.end() ) {
+            std::ostringstream message;
+            message << "IFactory::createItem() -> Error. Unknown item key '"
+                    << item_key << "'";
+            throw Exceptions::RuntimeErrorException(message.str());
+        }
         return (it->second)();
     }
 
     //! Registers object's creation function and store object description
     bool registerItem(const Key& item_key, CreateItemCallback CreateFn,
                       const std::string& itemDescription="") {
-        if (m_callbacks.find(item_key) != m_callbacks.end())
-            throw Exceptions::ExistingClassRegistrationException(
-                    "IFactory::registerItem() -> Panic! Already registered item key");
+        if (m_callbacks.find(item_key) != m_callbacks.end()) {
+            std::ostringstream message;
+            message << "IFactory::createItem() -> Error. Already registered item key '"
+                    << item_key << "'";
+            throw Exceptions::RuntimeErrorException(message.str());
+        }
         if (itemDescription!="")
             m_descriptions.insert(make_pair(item_key, itemDescription));
         return m_callbacks.insert(make_pair(item_key, CreateFn)).second;
diff --git a/Core/StandardSamples/SimulationFactory.cpp b/Core/StandardSamples/SimulationFactory.cpp
index acf4bef5f1a57d51f8ecba32fe738bbd3b0c609a..8093fe7d17ca602db8756e4c0614ebbbe5c6954a 100644
--- a/Core/StandardSamples/SimulationFactory.cpp
+++ b/Core/StandardSamples/SimulationFactory.cpp
@@ -97,5 +97,4 @@ SimulationFactory::SimulationFactory()
                  StandardSimulations::MiniGISASMonteCarlo,
                  "GISAS simulation with small 25x25 detector and phi[-2,2], theta[0,2], "
                  "in Monte-Carlo mode");
-
 }
diff --git a/Core/StandardSamples/SimulationFactory.h b/Core/StandardSamples/SimulationFactory.h
index e631b92a5bfd03c022f43fe0c263bb06f37f3cac..be4315942c3316b9c76f74f9d6cae16631ac2a3d 100644
--- a/Core/StandardSamples/SimulationFactory.h
+++ b/Core/StandardSamples/SimulationFactory.h
@@ -17,13 +17,15 @@
 #define SIMULATIONFACTORY_H
 
 #include "IFactory.h"
+#include "GISASSimulation.h"
+#include <string>
 
 //! @class SimulationFactory
 //! @ingroup standard_samples
 //! @brief Registry to create standard pre-defined simulations.
 //! Used in functional tests, performance measurements, etc.
 
-class BA_CORE_API_ SimulationFactory : public IFactory<std::string, class GISASSimulation>
+class BA_CORE_API_ SimulationFactory : public IFactory<std::string, GISASSimulation>
 {
 public:
     SimulationFactory();
diff --git a/GUI/coregui/Views/CommonWidgets/ItemComboWidget.cpp b/GUI/coregui/Views/CommonWidgets/ItemComboWidget.cpp
index f6a15e3c6238488df3dc7a56bf9a5dfa319ae0ca..0dd60c028cc08dddacc099768a969bf818c8528d 100644
--- a/GUI/coregui/Views/CommonWidgets/ItemComboWidget.cpp
+++ b/GUI/coregui/Views/CommonWidgets/ItemComboWidget.cpp
@@ -17,6 +17,7 @@
 #include "ItemComboWidget.h"
 #include "ItemComboToolBar.h"
 #include "SessionItemWidget.h"
+#include "GUIHelpers.h"
 #include <QComboBox>
 #include <QDebug>
 #include <QEvent>
diff --git a/GUI/coregui/utils/GUIHelpers.h b/GUI/coregui/utils/GUIHelpers.h
index 442aeb50a96c514eb81d323b5ed855f4b75f461f..502cc94f64f782427167335413a53a9f5662edb2 100644
--- a/GUI/coregui/utils/GUIHelpers.h
+++ b/GUI/coregui/utils/GUIHelpers.h
@@ -21,6 +21,7 @@
 #include <QStringList>
 #include <QWidget>
 #include <memory>
+#include <sstream>
 
 class JobItem;
 class RealDataItem;
@@ -84,4 +85,12 @@ BA_CORE_API_ bool isTheSame(const QStringList &lhs, const QStringList &rhs);
 
 } // namespace GUIHelpers
 
+inline std::ostream&  operator <<(std::ostream &stream,const QString &str)
+{
+   stream << str.toStdString();
+   return stream;
+}
+
+
+
 #endif // GUIHELPERS_H
diff --git a/Tests/PerformanceTests/test_performance.py b/Tests/PerformanceTests/test_performance.py
index d93eac293414f9d81448b612855813c8caad1cbc..a254a57887d79aed8f79ef49b483eb51723331d8 100755
--- a/Tests/PerformanceTests/test_performance.py
+++ b/Tests/PerformanceTests/test_performance.py
@@ -87,14 +87,14 @@ class FactoryTest:
 
         if simulation_name != None and sample_builder != None:
             self.m_sample_factory = SampleBuilderFactory()
-            self.m_simulation_registry = SimulationRegistry()
-            self.m_simulation = self.m_simulation_registry.createSimulation(self.m_simulation_name)
-            self.m_sample_builder = self.m_sample_factory.createBuilder(self.m_sample_builder_name)
+            self.m_simulation_factory = SimulationFactory()
+            self.m_simulation = self.m_simulation_factory.createItem(self.m_simulation_name)
+            self.m_sample = self.m_sample_factory.createSample(self.m_sample_builder_name)
         else:
             self.m_sample_factory = None
-            self.m_simulation_registry = None
+            self.m_simulation_factory = None
             self.m_simulation = None
-            self.m_sample_builder = None
+            self.m_sample = None
 
     def prepare(self):
         pass
@@ -103,7 +103,7 @@ class FactoryTest:
     def run_loop(self):
         # actual work is done here
         for i in range(self.m_nrepetitions):
-            self.m_simulation.setSampleBuilder(self.m_sample_builder)
+            self.m_simulation.setSample(self.m_sample)
             self.m_simulation.runSimulation()
 
     def run(self):
@@ -197,16 +197,16 @@ class PerformanceTests:
         self.m_pyversion = ""
         self.m_filename = filename
 
-        self.add("MultiLayer",         "MaxiGISAS",    "MultiLayerWithRoughnessBuilder", 1);
-        self.add("CylindersInDWBA",    "MaxiGISAS",    "CylindersInDWBABuilder", 10);
-        self.add("RotatedPyramids",    "MaxiGISAS",    "RotatedPyramidsBuilder", 10);
-        self.add("CoreShell",          "MaxiGISAS",    "CoreShellParticleBuilder", 10);
-        self.add("SquareLattice",      "MaxiGISAS",    "SquareLatticeBuilder", 10);
-        self.add("RadialParaCrystal",  "MaxiGISAS",    "RadialParaCrystalBuilder", 10);
-        self.add("HexParaCrystal",     "BasicGISAS",   "HexParaCrystalBuilder", 1);
-        self.add("SSCA",               "MaxiGISAS",    "SizeDistributionSSCAModelBuilder", 10);
-        self.add("Mesocrystal",        "MaxiGISAS",    "MesoCrystalBuilder", 2);
-        self.add("PolMagCyl",          "MaxiGISAS00",  "MagneticCylindersBuilder", 10);
+        self.add("MultiLayer",         "MaxiGISAS",    "MultiLayerWithRoughnessBuilder", 1)
+        self.add("CylindersInDWBA",    "MaxiGISAS",    "CylindersInDWBABuilder", 10)
+        self.add("RotatedPyramids",    "MaxiGISAS",    "RotatedPyramidsBuilder", 10)
+        self.add("CoreShell",          "MaxiGISAS",    "CoreShellParticleBuilder", 10)
+        self.add("SquareLattice",      "MaxiGISAS",    "SquareLatticeBuilder", 10)
+        self.add("RadialParaCrystal",  "MaxiGISAS",    "RadialParaCrystalBuilder", 10)
+        self.add("HexParaCrystal",     "BasicGISAS",   "HexParaCrystalBuilder", 1)
+        self.add("SSCA",               "MaxiGISAS",    "SizeDistributionSSCAModelBuilder", 10)
+        self.add("Mesocrystal",        "MaxiGISAS",    "MesoCrystalBuilder", 2)
+        self.add("PolMagCyl",          "MaxiGISAS00",  "MagneticCylindersBuilder", 10)
 
         # custom form factor is a special case since it's not in the registry
         self.m_tests.append(CustomTest("Custom FF", 10))
diff --git a/Tests/UnitTests/Core/3/DetectorTest.h b/Tests/UnitTests/Core/3/DetectorTest.h
deleted file mode 100644
index 41bf3bdf8192da9a78ad317645a895b7a0d92150..0000000000000000000000000000000000000000
--- a/Tests/UnitTests/Core/3/DetectorTest.h
+++ /dev/null
@@ -1,134 +0,0 @@
-#ifndef DETECTORTEST_H
-#define DETECTORTEST_H
-
-#include "SphericalDetector.h"
-#include "Exceptions.h"
-#include "OutputData.h"
-#include "FixedBinAxis.h"
-#include "ConvolutionDetectorResolution.h"
-#include "ResolutionFunction2DGaussian.h"
-#include "Polygon.h"
-#include <memory>
-
-class DetectorTest : public ::testing::Test
-{
- protected:
-    DetectorTest();
-    virtual ~DetectorTest();
-
-    SphericalDetector emptyDetector;
-    SphericalDetector constructedDetector;
-    SphericalDetector *originalDetector;
-    SphericalDetector copyOfOriginalDetector;
-};
-
-DetectorTest::DetectorTest()
-{
-    originalDetector = new SphericalDetector();
-    FixedBinAxis axis0("axis0", 10, 0.0, 10.0);
-    FixedBinAxis axis1("axis1", 20, 0.0, 20.0);
-    originalDetector->addAxis(axis0);
-    originalDetector->addAxis(axis1);
-    originalDetector->setDetectorResolution(new ConvolutionDetectorResolution(
-            new ResolutionFunction2DGaussian(1,1)));
-}
-
-DetectorTest::~DetectorTest()
-{
-    delete originalDetector;
-}
-
-TEST_F(DetectorTest, InitialDetectorState)
-{
-    EXPECT_EQ((size_t)0, emptyDetector.getDimension());
-    ASSERT_THROW(emptyDetector.getAxis(0), Exceptions::OutOfBoundsException);
-    OutputData<double>* p_intensity_map(nullptr);
-    ASSERT_THROW(emptyDetector.applyDetectorResolution(p_intensity_map),
-                 Exceptions::NullPointerException);
-}
-
-TEST_F(DetectorTest, DetectorConstruction)
-{
-    // pushing two axes
-    FixedBinAxis axis0("axis0", 10, 0.0, 10.0);
-    FixedBinAxis axis1("axis1", 20, 0.0, 20.0);
-    constructedDetector.addAxis(axis0);
-    constructedDetector.addAxis(axis1);
-
-    EXPECT_EQ((size_t)2, constructedDetector.getDimension());
-    const IAxis& axis0copy = constructedDetector.getAxis(0);
-    const IAxis& axis1copy = constructedDetector.getAxis(1);
-    ASSERT_TRUE(axis0.getMin() == axis0copy.getMin() );
-    ASSERT_TRUE(axis0.getMax() == axis0copy.getMax() );
-    ASSERT_TRUE(axis0.getName() == axis0copy.getName() );
-    ASSERT_TRUE(axis1.getName() == axis1copy.getName() );
-    ASSERT_TRUE(axis1.getMin() == axis1copy.getMin() );
-    ASSERT_TRUE(axis1.getMax() == axis1copy.getMax() );
-    constructedDetector.clear();
-    EXPECT_EQ((size_t)0, constructedDetector.getDimension());
-}
-
-TEST_F(DetectorTest, DetectorCopying)
-{
-    copyOfOriginalDetector = *originalDetector;
-    delete originalDetector;
-    originalDetector = 0;
-    ASSERT_TRUE( copyOfOriginalDetector.getDimension() == 2 );
-    EXPECT_EQ( (double)0, copyOfOriginalDetector.getAxis(0).getMin() );
-    EXPECT_EQ( (double)10, copyOfOriginalDetector.getAxis(0).getMax() );
-    EXPECT_EQ( (size_t)10, copyOfOriginalDetector.getAxis(0).getSize() );
-    EXPECT_EQ( (double)0, copyOfOriginalDetector.getAxis(1).getMin() );
-    EXPECT_EQ( (double)20, copyOfOriginalDetector.getAxis(1).getMax() );
-    EXPECT_EQ( (size_t)20, copyOfOriginalDetector.getAxis(1).getSize() );
-    EXPECT_TRUE(std::string("ConvolutionDetectorResolution")
-        == copyOfOriginalDetector.getDetectorResolutionFunction()->getName());
-}
-
-TEST_F(DetectorTest, MaskOfDetector)
-{
-    SphericalDetector detector;
-    detector.addAxis(FixedBinAxis("x-axis", 12, -4.0, 8.0));
-    detector.addAxis(FixedBinAxis("y-axis", 6, -2.0, 4.0));
-
-    std::vector<double> x = {4.0, -4.0, -4.0, 4.0, 4.0};
-    std::vector<double> y = {2.0, 2.0, -2.0, -2.0, 2.0};
-
-    Geometry::Polygon polygon(x, y);
-    detector.addMask(polygon, true);
-
-    const OutputData<bool> *mask = detector.getDetectorMask()->getMaskData();
-    for(size_t index=0; index<mask->getAllocatedSize(); ++index) {
-        double x = mask->getAxisValue(index, 0);
-        double y = mask->getAxisValue(index, 1);
-        if( x>= -4.0 && x <=4.0 && y>=-2.0 && y<=2.0) {
-            EXPECT_TRUE(detector.isMasked(index));
-        } else {
-            EXPECT_FALSE(detector.isMasked(index));
-        }
-    }
-
-    SphericalDetector detector2 = detector;
-    mask = detector2.getDetectorMask()->getMaskData();
-    for(size_t index=0; index<mask->getAllocatedSize(); ++index) {
-        double x = mask->getAxisValue(index, 0);
-        double y = mask->getAxisValue(index, 1);
-        if( x>= -4.0 && x <=4.0 && y>=-2.0 && y<=2.0) {
-            EXPECT_TRUE(detector2.isMasked(index));
-        } else {
-            EXPECT_FALSE(detector2.isMasked(index));
-        }
-    }
-
-    mask = detector.getDetectorMask()->getMaskData();
-    for(size_t index=0; index<mask->getAllocatedSize(); ++index) {
-        double x = mask->getAxisValue(index, 0);
-        double y = mask->getAxisValue(index, 1);
-        if( x>= -4.0 && x <=4.0 && y>=-2.0 && y<=2.0) {
-            EXPECT_TRUE(detector.isMasked(index));
-        } else {
-            EXPECT_FALSE(detector.isMasked(index));
-        }
-    }
-}
-
-#endif // DETECTORTEST_H
diff --git a/Tests/UnitTests/Core/3/SimulationAreaTest.h b/Tests/UnitTests/Core/3/SimulationAreaTest.h
new file mode 100644
index 0000000000000000000000000000000000000000..8ca8250cec8cdc1e96086a4d00fc5acfbdc8d4ee
--- /dev/null
+++ b/Tests/UnitTests/Core/3/SimulationAreaTest.h
@@ -0,0 +1,165 @@
+#ifndef SIMULATIONAREATEST_H
+#define SIMULATIONAREATEST_H
+
+#include "SimulationArea.h"
+#include "SphericalDetector.h"
+#include "Rectangle.h"
+#include <memory>
+#include <iostream>
+
+class SimulationAreaTest : public ::testing::Test
+{
+ protected:
+    SimulationAreaTest(){}
+    virtual ~SimulationAreaTest(){}
+};
+
+// Iterators test
+
+TEST_F(SimulationAreaTest, iteratorOperations)
+{
+    SphericalDetector detector(4, -1.0, 3.0, 2, 0.0, 2.0);
+    SimulationArea area(&detector);
+
+    // begin iterator
+    SimulationArea::iterator it_begin = area.begin();
+    EXPECT_EQ(it_begin.index(), 0);
+    EXPECT_EQ(it_begin.elementIndex(), 0);
+    EXPECT_TRUE(it_begin == area.begin());
+    EXPECT_FALSE(it_begin != area.begin());
+
+    // end iterator
+    SimulationArea::iterator it_end = area.end();
+    EXPECT_EQ(it_end.index(), detector.getTotalSize());
+    EXPECT_EQ(it_end.elementIndex(), 0); // has initial value
+
+    // begin/end comparison
+    EXPECT_TRUE(it_begin != it_end);
+    EXPECT_FALSE(it_begin == it_end);
+
+    // assignment
+    SimulationArea::iterator it = area.begin();
+    EXPECT_TRUE(it == it_begin);
+    EXPECT_FALSE(it != it_begin);
+
+    // increment
+    it++;
+    EXPECT_EQ(it.index(), 1);
+    EXPECT_EQ(it.elementIndex(), 1);
+    EXPECT_TRUE(it != it_begin);
+    EXPECT_FALSE(it == it_begin);
+    ++it;
+    EXPECT_EQ(it.index(), 2);
+    EXPECT_EQ(it.elementIndex(), 2);
+
+    // incrementing well behind the end
+    for(size_t i=0; i<100; ++i) ++it;
+    EXPECT_EQ(it.index(), detector.getTotalSize());
+    EXPECT_EQ(it.elementIndex(), detector.getTotalSize());
+}
+
+//! Iteration over non-masked detector
+
+TEST_F(SimulationAreaTest, detectorIteration)
+{
+    SphericalDetector detector(4, -1.0, 3.0, 2, 0.0, 2.0);
+    SimulationArea area(&detector);
+
+    std::vector<int> expectedIndexes = {0, 1, 2, 3, 4, 5, 6, 7};
+    std::vector<int> expectedElementIndexes = {0, 1, 2, 3, 4, 5, 6, 7};
+
+    std::vector<int> indexes;
+    std::vector<int> elementIndexes;
+    for(SimulationArea::iterator it = area.begin(); it!=area.end(); ++it) {
+        indexes.push_back(it.index());
+        elementIndexes.push_back(it.elementIndex());
+    }
+    EXPECT_EQ(indexes, expectedIndexes);
+    EXPECT_EQ(elementIndexes, expectedElementIndexes);
+}
+
+//! Iteration over masked detector
+
+TEST_F(SimulationAreaTest, maskedIteration)
+{
+    SphericalDetector detector(5, -1.0, 4.0, 4, 0.0, 4.0);
+    detector.addMask(Geometry::Rectangle(0.1, 1.1, 2.9, 2.9), true);
+    detector.addMask(Geometry::Rectangle(3.1, 3.1, 3.9, 3.9), true);
+    SimulationArea area(&detector);
+
+    std::vector<int> expectedIndexes = {0, 1, 2, 3, 4, 7, 8, 11, 12, 15, 16, 17, 18};
+    std::vector<int> expectedElementIndexes = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12};
+    std::vector<int> indexes;
+    std::vector<int> elementIndexes;
+    for(SimulationArea::iterator it = area.begin(); it!=area.end(); ++it) {
+        indexes.push_back(it.index());
+        elementIndexes.push_back(it.elementIndex());
+    }
+    EXPECT_EQ(indexes, expectedIndexes);
+    EXPECT_EQ(elementIndexes, expectedElementIndexes);
+}
+
+//! Iteration over the detector with first and alst bin masked
+
+TEST_F(SimulationAreaTest, maskedCornerIteration)
+{
+    SphericalDetector detector(5, -1.0, 4.0, 4, 0.0, 4.0);
+    detector.addMask(Geometry::Rectangle(-0.9, 0.1, -0.1, 0.9), true);
+    detector.addMask(Geometry::Rectangle(3.1, 3.1, 3.9, 3.9), true);
+    SimulationArea area(&detector);
+
+    std::vector<int> expectedIndexes
+            = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18};
+    std::vector<int> expectedElementIndexes
+            = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17};
+    std::vector<int> indexes;
+    std::vector<int> elementIndexes;
+    for(SimulationArea::iterator it = area.begin(); it!=area.end(); ++it) {
+        indexes.push_back(it.index());
+        elementIndexes.push_back(it.elementIndex());
+    }
+    EXPECT_EQ(indexes, expectedIndexes);
+    EXPECT_EQ(elementIndexes, expectedElementIndexes);
+}
+
+//! Iteration when whole detector is masked
+
+TEST_F(SimulationAreaTest, allMaskedIteration)
+{
+    SphericalDetector detector(5, -1.0, 4.0, 4, 0.0, 4.0);
+    detector.addMask(Geometry::Rectangle(-0.9, 0.1, 3.9, 3.9), true);
+    SimulationArea area(&detector);
+
+    std::vector<int> indexes;
+    std::vector<int> elementIndexes;
+    for(SimulationArea::iterator it = area.begin(); it!=area.end(); ++it) {
+        indexes.push_back(it.index());
+        elementIndexes.push_back(it.elementIndex());
+    }
+    EXPECT_EQ(indexes.size(), size_t(0));
+    EXPECT_EQ(elementIndexes.size(), size_t(0));
+}
+
+//! Iteration when RegionOfInterest is present
+
+TEST_F(SimulationAreaTest, maskAndRoiIteration)
+{
+    SphericalDetector detector(5, -1.0, 4.0, 4, 0.0, 4.0);
+    detector.setRegionOfInterest(0.1, 1.1, 2.9, 3.9);
+    detector.addMask(Geometry::Rectangle(-0.9, 0.1, 0.9, 1.9), true);
+    SimulationArea area(&detector);
+
+    std::vector<int> expectedIndexes = {6, 7, 9, 10, 11, 13, 14, 15};
+    std::vector<int> expectedElementIndexes = {0, 1, 2, 3, 4, 5, 6, 7};
+    std::vector<int> indexes;
+    std::vector<int> elementIndexes;
+    for(SimulationArea::iterator it = area.begin(); it!=area.end(); ++it) {
+        indexes.push_back(it.index());
+        elementIndexes.push_back(it.elementIndex());
+    }
+    EXPECT_EQ(indexes, expectedIndexes);
+    EXPECT_EQ(elementIndexes, expectedElementIndexes);
+
+}
+
+#endif
diff --git a/Tests/UnitTests/Core/3/SphericalDetectorTest.h b/Tests/UnitTests/Core/3/SphericalDetectorTest.h
new file mode 100644
index 0000000000000000000000000000000000000000..9f935d232194ecf1a2c9a8119ce59c7cf8669348
--- /dev/null
+++ b/Tests/UnitTests/Core/3/SphericalDetectorTest.h
@@ -0,0 +1,369 @@
+#ifndef SPHERICALDETECTORTEST_H
+#define SPHERICALDETECTORTEST_H
+
+#include "SphericalDetector.h"
+#include "Exceptions.h"
+#include "OutputData.h"
+#include "FixedBinAxis.h"
+#include "ConvolutionDetectorResolution.h"
+#include "ResolutionFunction2DGaussian.h"
+#include "Polygon.h"
+#include "BornAgainNamespace.h"
+#include "Rectangle.h"
+#include "Units.h"
+#include "Beam.h"
+#include "SimulationArea.h"
+#include <memory>
+
+class SphericalDetectorTest : public ::testing::Test
+{
+ protected:
+    SphericalDetectorTest(){}
+    virtual ~SphericalDetectorTest(){}
+};
+
+//! Default detector construction
+
+TEST_F(SphericalDetectorTest, initialState)
+{
+    SphericalDetector detector;
+
+    // checking size
+    EXPECT_EQ((size_t)0, detector.getDimension());
+    EXPECT_EQ(IDetector2D::RADIANS, detector.getDefaultAxesUnits());
+
+    // detector units
+    std::vector<IDetector2D::EAxesUnits> validUnits =
+        {IDetector2D::NBINS, IDetector2D::RADIANS, IDetector2D::DEGREES, IDetector2D::QYQZ};
+    EXPECT_EQ(validUnits, detector.getValidAxesUnits());
+
+    // masks
+    EXPECT_FALSE(detector.hasMasks());
+    EXPECT_EQ(0, detector.getNumberOfMaskedChannels());
+
+    // resolution function
+    EXPECT_EQ(nullptr, detector.getDetectorResolutionFunction());
+
+    // region of interest
+    EXPECT_EQ(nullptr, detector.regionOfInterest());
+
+    // behavior
+    ASSERT_THROW(detector.getAxis(0), Exceptions::OutOfBoundsException);
+    OutputData<double>* p_intensity_map(nullptr);
+    ASSERT_THROW(detector.applyDetectorResolution(p_intensity_map),
+                 Exceptions::NullPointerException);
+}
+
+//! Construction of the detector with axes.
+
+TEST_F(SphericalDetectorTest, constructionWithAxes)
+{
+    SphericalDetector detector;
+    FixedBinAxis axis0("axis0", 10, 0.0, 10.0);
+    FixedBinAxis axis1("axis1", 20, 0.0, 20.0);
+    detector.addAxis(axis0);
+    detector.addAxis(axis1);
+
+    // checking dimension and axes
+    EXPECT_EQ((size_t)2, detector.getDimension());
+    EXPECT_EQ(axis0.getMin(), detector.getAxis(0).getMin() );
+    EXPECT_EQ(axis0.getMax(), detector.getAxis(0).getMax() );
+    EXPECT_EQ(axis0.getName(), detector.getAxis(0).getName() );
+    EXPECT_EQ(axis1.getName(), detector.getAxis(1).getName() );
+    EXPECT_EQ(axis1.getMin(), detector.getAxis(1).getMin() );
+    EXPECT_EQ(axis1.getMax(), detector.getAxis(1).getMax() );
+
+    // clearing detector
+    detector.clear();
+    EXPECT_EQ((size_t)0, detector.getDimension());
+}
+
+//! Construction of the detector via classical constructor.
+
+TEST_F(SphericalDetectorTest, constructionWithParameters)
+{
+    SphericalDetector detector(10, -1.0, 1.0, 20, 0.0, 2.0);
+    EXPECT_EQ(10, detector.getAxis(0).getSize() );
+    EXPECT_EQ(-1.0, detector.getAxis(0).getMin() );
+    EXPECT_EQ(1.0, detector.getAxis(0).getMax() );
+    EXPECT_EQ(BornAgain::PHI_AXIS_NAME, detector.getAxis(0).getName());
+    EXPECT_EQ(20, detector.getAxis(1).getSize() );
+    EXPECT_EQ(0.0, detector.getAxis(1).getMin() );
+    EXPECT_EQ(2.0, detector.getAxis(1).getMax() );
+    EXPECT_EQ(BornAgain::ALPHA_AXIS_NAME, detector.getAxis(1).getName());
+}
+
+//! Init external data with detector axes.
+
+TEST_F(SphericalDetectorTest, initOutputData)
+{
+    SphericalDetector detector(10, -1.0, 1.0, 20, 0.0, 2.0);
+    OutputData<double> data;
+    detector.initOutputData(data);
+
+    EXPECT_EQ(data.getAllocatedSize(), 200);
+
+    EXPECT_EQ(10, data.getAxis(0)->getSize() );
+    EXPECT_EQ(-1.0, data.getAxis(0)->getMin() );
+    EXPECT_EQ(1.0, data.getAxis(0)->getMax() );
+    EXPECT_EQ(BornAgain::PHI_AXIS_NAME, data.getAxis(0)->getName());
+    EXPECT_EQ(20, data.getAxis(1)->getSize() );
+    EXPECT_EQ(0.0, data.getAxis(1)->getMin() );
+    EXPECT_EQ(2.0, data.getAxis(1)->getMax() );
+    EXPECT_EQ(BornAgain::ALPHA_AXIS_NAME, data.getAxis(1)->getName());
+}
+
+//! Creation of the detector map with axes in given units
+
+TEST_F(SphericalDetectorTest, createDetectorMap)
+{
+    SphericalDetector detector(10, -1.0*Units::deg, 1.0*Units::deg,
+                               20, 0.0*Units::deg, 2.0*Units::deg);
+
+    Beam beam;
+    beam.setCentralK(1.0*Units::angstrom, 0.4*Units::deg, 0.0);
+
+    // creating map in default units, which are radians and checking axes
+    std::unique_ptr<OutputData<double>> data(
+                detector.createDetectorMap(beam, IDetector2D::DEFAULT));
+    EXPECT_EQ(data->getAxis(0)->getSize(), 10);
+    EXPECT_EQ(data->getAxis(0)->getMin(), -1.0*Units::deg);
+    EXPECT_EQ(data->getAxis(0)->getMax(), 1.0*Units::deg);
+    EXPECT_EQ(data->getAxis(1)->getSize(), 20);
+    EXPECT_EQ(data->getAxis(1)->getMin(), 0.0*Units::deg);
+    EXPECT_EQ(data->getAxis(1)->getMax(), 2.0*Units::deg);
+
+    // creating map in degrees and checking axes
+    data.reset(detector.createDetectorMap(beam, IDetector2D::DEGREES));
+    EXPECT_EQ(data->getAxis(0)->getSize(), 10);
+    EXPECT_FLOAT_EQ(data->getAxis(0)->getMin(), -1.0);
+    EXPECT_FLOAT_EQ(data->getAxis(0)->getMax(), 1.0);
+    EXPECT_EQ(data->getAxis(1)->getSize(), 20);
+    EXPECT_FLOAT_EQ(data->getAxis(1)->getMin(), 0.0);
+    EXPECT_FLOAT_EQ(data->getAxis(1)->getMax(), 2.0);
+
+    // creating map in nbins and checking axes
+    data.reset(detector.createDetectorMap(beam, IDetector2D::NBINS));
+    EXPECT_EQ(data->getAxis(0)->getSize(), 10);
+    EXPECT_FLOAT_EQ(data->getAxis(0)->getMin(), 0.0);
+    EXPECT_FLOAT_EQ(data->getAxis(0)->getMax(), 10.0);
+    EXPECT_EQ(data->getAxis(1)->getSize(), 20);
+    EXPECT_FLOAT_EQ(data->getAxis(1)->getMin(), 0.0);
+    EXPECT_FLOAT_EQ(data->getAxis(1)->getMax(), 20.0);
+}
+
+//! Testing region of interest.
+
+TEST_F(SphericalDetectorTest, regionOfInterest)
+{
+    SphericalDetector detector;
+    detector.addAxis(FixedBinAxis("axis0", 8, -3.0, 5.0));
+    detector.addAxis(FixedBinAxis("axis1", 4, 0.0, 4.0));
+
+    // creating region of interest
+    double xlow(-2.0), ylow(1.0), xup(4.0), yup(3.0);
+    detector.setRegionOfInterest(xlow, ylow, xup, yup);
+    EXPECT_FALSE(nullptr == detector.regionOfInterest());
+    EXPECT_EQ(detector.regionOfInterest()->getXlow(), xlow);
+    EXPECT_EQ(detector.regionOfInterest()->getYlow(), ylow);
+    EXPECT_EQ(detector.regionOfInterest()->getXup(), xup);
+    EXPECT_EQ(detector.regionOfInterest()->getYup(), yup);
+
+    // replacing region of interest with a new one
+    double xlow2(-2.1), ylow2(1.1), xup2(4.1), yup2(3.1);
+    detector.setRegionOfInterest(xlow2, ylow2, xup2, yup2);
+    EXPECT_EQ(detector.regionOfInterest()->getXlow(), xlow2);
+    EXPECT_EQ(detector.regionOfInterest()->getYlow(), ylow2);
+    EXPECT_EQ(detector.regionOfInterest()->getXup(), xup2);
+    EXPECT_EQ(detector.regionOfInterest()->getYup(), yup2);
+
+    // removing region of interest
+    detector.resetRegionOfInterest();
+    EXPECT_TRUE(nullptr == detector.regionOfInterest());
+}
+
+//! Init external data with detector axes when region of interest is present.
+
+TEST_F(SphericalDetectorTest, regionOfInterestAndData)
+{
+    SphericalDetector detector;
+    detector.addAxis(FixedBinAxis("axis0", 8, -3.0, 5.0));
+    detector.addAxis(FixedBinAxis("axis1", 4, 0.0, 4.0));
+
+    // creating region of interest
+    detector.setRegionOfInterest(-1.8, 0.5, 3.0, 2.5);
+
+    // initializing data via the detector and making sure that data axes are exactly as in detector
+    // (i.e. to confirm that regionOfInterest doesn't change data structure)
+    OutputData<double> data;
+    detector.initOutputData(data);
+    EXPECT_EQ(data.getAllocatedSize(), 32);
+    EXPECT_EQ(data.getAxis(0)->getSize(), 8);
+    EXPECT_EQ(data.getAxis(0)->getMin(), -3.0);
+    EXPECT_EQ(data.getAxis(0)->getMax(), 5.0);
+    EXPECT_EQ(data.getAxis(1)->getSize(), 4);
+    EXPECT_EQ(data.getAxis(1)->getMin(), 0.0);
+    EXPECT_EQ(data.getAxis(1)->getMax(), 4.0);
+}
+
+//! Create detector map in the presence of region of interest.
+
+TEST_F(SphericalDetectorTest, regionOfInterestAndDetectorMap)
+{
+    SphericalDetector detector(6, -1.0*Units::deg, 5.0*Units::deg,
+                               4, 0.0*Units::deg, 4.0*Units::deg);
+
+    detector.setRegionOfInterest(0.1*Units::deg, 1.1*Units::deg, 3.0*Units::deg, 2.9*Units::deg);
+    Beam beam;
+    beam.setCentralK(1.0*Units::angstrom, 0.4*Units::deg, 0.0);
+
+    // Creating map in default units, which are radians and checking that axes are clipped
+    // to region of interest.
+    std::unique_ptr<OutputData<double>> data(
+                detector.createDetectorMap(beam, IDetector2D::DEFAULT));
+    EXPECT_EQ(data->getAxis(0)->getSize(), 4);
+    EXPECT_EQ(data->getAxis(0)->getMin(), 0.0*Units::deg);
+    EXPECT_EQ(data->getAxis(0)->getMax(), 4.0*Units::deg);
+    EXPECT_EQ(data->getAxis(1)->getSize(), 2);
+    EXPECT_EQ(data->getAxis(1)->getMin(), 1.0*Units::deg);
+    EXPECT_EQ(data->getAxis(1)->getMax(), 3.0*Units::deg);
+
+    // Creating map with axes in degrees, and checking that it is clipped to the region of interest
+    data.reset(detector.createDetectorMap(beam, IDetector2D::DEGREES));
+    EXPECT_EQ(data->getAxis(0)->getSize(), 4);
+    EXPECT_EQ(data->getAxis(0)->getMin(), 0.0);
+    EXPECT_EQ(data->getAxis(0)->getMax(), 4.0);
+    EXPECT_EQ(data->getAxis(1)->getSize(), 2);
+    EXPECT_EQ(data->getAxis(1)->getMin(), 1.0);
+    EXPECT_EQ(data->getAxis(1)->getMax(), 3.0);
+}
+
+//! Checking IDetector2D::getIntensityData in the presence of region of interest.
+
+TEST_F(SphericalDetectorTest, getIntensityData)
+{
+    SphericalDetector detector(6, -1.0*Units::deg, 5.0*Units::deg,
+                               4, 0.0*Units::deg, 4.0*Units::deg);
+    detector.setRegionOfInterest(0.1*Units::deg, 1.1*Units::deg, 3.0*Units::deg, 2.9*Units::deg);
+    Beam beam;
+    beam.setCentralK(1.0*Units::angstrom, 0.4*Units::deg, 0.0);
+
+    // Initializing data (no region of interest involved yet) and filling with amplitudes
+    OutputData<double> intensityData;
+    detector.initOutputData(intensityData);
+    EXPECT_EQ(intensityData.getAllocatedSize(), 6*4);
+    for(size_t i=0; i<intensityData.getAllocatedSize(); ++i) {
+        intensityData[i] = static_cast<double>(i);
+    }
+    EXPECT_EQ(intensityData[intensityData.getAllocatedSize()-1], 23.0);
+
+    // Getting detectorIntensity and checking that amplitudes are correct and it is clipped to
+    // region of interest.
+
+    std::unique_ptr<OutputData<double>> detectorIntensity(
+                detector.getDetectorIntensity(intensityData, beam, IDetector2D::DEGREES));
+
+    EXPECT_EQ(detectorIntensity->getAllocatedSize(), 8);
+    EXPECT_EQ((*detectorIntensity)[0], 5.0);
+    EXPECT_EQ((*detectorIntensity)[7], 18.0);
+    EXPECT_EQ(detectorIntensity->getAxis(0)->getSize(), 4);
+    EXPECT_EQ(detectorIntensity->getAxis(0)->getMin(), 0.0);
+    EXPECT_EQ(detectorIntensity->getAxis(0)->getMax(), 4.0);
+    EXPECT_EQ(detectorIntensity->getAxis(1)->getSize(), 2);
+    EXPECT_EQ(detectorIntensity->getAxis(1)->getMin(), 1.0);
+    EXPECT_EQ(detectorIntensity->getAxis(1)->getMax(), 3.0);
+}
+
+TEST_F(SphericalDetectorTest, MaskOfDetector)
+{
+    SphericalDetector detector;
+    detector.addAxis(FixedBinAxis("x-axis", 12, -4.0, 8.0));
+    detector.addAxis(FixedBinAxis("y-axis", 6, -2.0, 4.0));
+
+    std::vector<double> x = {4.0, -4.0, -4.0, 4.0, 4.0};
+    std::vector<double> y = {2.0, 2.0, -2.0, -2.0, 2.0};
+
+    Geometry::Polygon polygon(x, y);
+    detector.addMask(polygon, true);
+
+    const OutputData<bool> *mask = detector.getDetectorMask()->getMaskData();
+    for(size_t index=0; index<mask->getAllocatedSize(); ++index) {
+        double x = mask->getAxisValue(index, 0);
+        double y = mask->getAxisValue(index, 1);
+        if( x>= -4.0 && x <=4.0 && y>=-2.0 && y<=2.0) {
+            EXPECT_TRUE(detector.isMasked(index));
+        } else {
+            EXPECT_FALSE(detector.isMasked(index));
+        }
+    }
+
+    SphericalDetector detector2(detector);
+    mask = detector2.getDetectorMask()->getMaskData();
+    for(size_t index=0; index<mask->getAllocatedSize(); ++index) {
+        double x = mask->getAxisValue(index, 0);
+        double y = mask->getAxisValue(index, 1);
+        if( x>= -4.0 && x <=4.0 && y>=-2.0 && y<=2.0) {
+            EXPECT_TRUE(detector2.isMasked(index));
+        } else {
+            EXPECT_FALSE(detector2.isMasked(index));
+        }
+    }
+
+    mask = detector.getDetectorMask()->getMaskData();
+    for(size_t index=0; index<mask->getAllocatedSize(); ++index) {
+        double x = mask->getAxisValue(index, 0);
+        double y = mask->getAxisValue(index, 1);
+        if( x>= -4.0 && x <=4.0 && y>=-2.0 && y<=2.0) {
+            EXPECT_TRUE(detector.isMasked(index));
+        } else {
+            EXPECT_FALSE(detector.isMasked(index));
+        }
+    }
+}
+
+//! Checking clone in the presence of ROI and masks.
+
+TEST_F(SphericalDetectorTest, Clone)
+{
+    Beam beam;
+    beam.setCentralK(1.0*Units::angstrom, 0.4*Units::deg, 0.0);
+
+    SphericalDetector detector(6, -1.0*Units::deg, 5.0*Units::deg,
+                               4, 0.0*Units::deg, 4.0*Units::deg);
+    detector.setRegionOfInterest(0.1*Units::deg, 1.1*Units::deg, 3.0*Units::deg, 2.9*Units::deg);
+    detector.addMask(Geometry::Rectangle(-0.9*Units::deg, 0.1*Units::deg, 0.9*Units::deg, 1.9*Units::deg), true);
+    detector.addMask(Geometry::Rectangle(3.1*Units::deg, 2.1*Units::deg, 4.9*Units::deg, 3.9*Units::deg), true);
+    detector.setDetectorResolution(new ConvolutionDetectorResolution(
+            new ResolutionFunction2DGaussian(1,1)));
+
+    std::unique_ptr<SphericalDetector> clone(detector.clone());
+
+    std::unique_ptr<OutputData<double>> data(
+                clone->createDetectorMap(beam, IDetector2D::DEGREES));
+    EXPECT_EQ(data->getAxis(0)->getSize(), 4);
+    EXPECT_EQ(data->getAxis(0)->getMin(), 0.0);
+    EXPECT_EQ(data->getAxis(0)->getMax(), 4.0);
+    EXPECT_EQ(data->getAxis(1)->getSize(), 2);
+    EXPECT_EQ(data->getAxis(1)->getMin(), 1.0);
+    EXPECT_EQ(data->getAxis(1)->getMax(), 3.0);
+
+    EXPECT_EQ(std::string("ConvolutionDetectorResolution"),
+              clone->getDetectorResolutionFunction()->getName());
+
+    EXPECT_EQ(clone->getNumberOfMaskedChannels(), 8);
+
+    // checking iteration over the map of cloned detector
+    SimulationArea area(clone.get());
+    std::vector<int> expectedIndexes = {6, 9, 10, 13, 14, 17};
+    std::vector<int> expectedElementIndexes = {0, 1, 2, 3, 4, 5};
+    std::vector<int> indexes;
+    std::vector<int> elementIndexes;
+    for(SimulationArea::iterator it = area.begin(); it!=area.end(); ++it) {
+        indexes.push_back(it.index());
+        elementIndexes.push_back(it.elementIndex());
+    }
+    EXPECT_EQ(indexes, expectedIndexes);
+    EXPECT_EQ(elementIndexes, expectedElementIndexes);
+}
+
+#endif // SPHERICALDETECTORTEST_H
diff --git a/Tests/UnitTests/Core/3/testlist.h b/Tests/UnitTests/Core/3/testlist.h
index f6856492d5bb56c9c31677dbc44479ac7f1ce86d..f21d9b82e515a7f14e5f6f7f3508c3a66f394a04 100644
--- a/Tests/UnitTests/Core/3/testlist.h
+++ b/Tests/UnitTests/Core/3/testlist.h
@@ -6,4 +6,5 @@
 #include "SpecialFunctionsTest.h"
 #include "RectangularDetectorTest.h"
 #include "PrecomputedTest.h"
-#include "DetectorTest.h"
+#include "SphericalDetectorTest.h"
+#include "SimulationAreaTest.h"
diff --git a/Wrap/swig/libBornAgainCore.i b/Wrap/swig/libBornAgainCore.i
index fbd1d26d2b8eb3ed523fef7ec4afed71c3679b8e..b5744b20c1d8e28916a27178bdff130e9f7d10b6 100644
--- a/Wrap/swig/libBornAgainCore.i
+++ b/Wrap/swig/libBornAgainCore.i
@@ -419,9 +419,9 @@
 %include "ISelectionRule.h"
 %include "SpecularSimulation.h"
 %include "ThreadInfo.h"
-%template(SampleBuilderFactory) IFactory<std::string, IMultiLayerBuilder>;
-//%include "SampleBuilderFactory.h"
-%template(SimulationFactory) IFactory<std::string, GISASSimulation>;
-//%include "SimulationFactory.h"
+%template(SampleBuilderFactoryTemp) IFactory<std::string, IMultiLayerBuilder>;
+%include "SampleBuilderFactory.h"
+%template(SimulationFactoryTemp) IFactory<std::string, GISASSimulation>;
+%include "SimulationFactory.h"
 
 %include "extendCore.i"
diff --git a/auto/Wrap/libBornAgainCore.py b/auto/Wrap/libBornAgainCore.py
index 94d1155d25402fae5f5b0abaf578d969412f092f..a814c0ed7a20a6f62eac28af6c521fcb203af40b 100644
--- a/auto/Wrap/libBornAgainCore.py
+++ b/auto/Wrap/libBornAgainCore.py
@@ -16704,15 +16704,15 @@ class HomogeneousMagneticMaterial(HomogeneousMaterial):
 HomogeneousMagneticMaterial_swigregister = _libBornAgainCore.HomogeneousMagneticMaterial_swigregister
 HomogeneousMagneticMaterial_swigregister(HomogeneousMagneticMaterial)
 
-class IDetector2D(IParameterized):
+class IDetector2D(ICloneable, IParameterized):
     """Proxy of C++ IDetector2D class."""
 
     __swig_setmethods__ = {}
-    for _s in [IParameterized]:
+    for _s in [ICloneable, IParameterized]:
         __swig_setmethods__.update(getattr(_s, '__swig_setmethods__', {}))
     __setattr__ = lambda self, name, value: _swig_setattr(self, IDetector2D, name, value)
     __swig_getmethods__ = {}
-    for _s in [IParameterized]:
+    for _s in [ICloneable, IParameterized]:
         __swig_getmethods__.update(getattr(_s, '__swig_getmethods__', {}))
     __getattr__ = lambda self, name: _swig_getattr(self, IDetector2D, name)
 
@@ -16961,16 +16961,29 @@ class IDetector2D(IParameterized):
         return _libBornAgainCore.IDetector2D_hasMasks(self)
 
 
-    def createDetectorMap(self, arg2, arg3):
+    def getDetectorIntensity(self, *args):
+        """
+        getDetectorIntensity(IDetector2D self, IntensityData data, Beam beam, IDetector2D::EAxesUnits units_type) -> IntensityData
+        getDetectorIntensity(IDetector2D self, IntensityData data, Beam beam) -> IntensityData
+        """
+        return _libBornAgainCore.IDetector2D_getDetectorIntensity(self, *args)
+
+
+    def createDetectorMap(self, beam, units):
         """
-        createDetectorMap(IDetector2D self, Beam arg2, IDetector2D::EAxesUnits arg3) -> IntensityData
+        createDetectorMap(IDetector2D self, Beam beam, IDetector2D::EAxesUnits units) -> IntensityData
 
         OutputData< double > * IDetector2D::createDetectorMap(const Beam &, EAxesUnits) const
 
         Returns detector map in given axes units. 
 
         """
-        return _libBornAgainCore.IDetector2D_createDetectorMap(self, arg2, arg3)
+        return _libBornAgainCore.IDetector2D_createDetectorMap(self, beam, units)
+
+
+    def initOutputData(self, data):
+        """initOutputData(IDetector2D self, IntensityData data)"""
+        return _libBornAgainCore.IDetector2D_initOutputData(self, data)
 
 
     def getValidAxesUnits(self):
@@ -16996,6 +17009,31 @@ class IDetector2D(IParameterized):
         """
         return _libBornAgainCore.IDetector2D_getDefaultAxesUnits(self)
 
+
+    def regionOfInterest(self):
+        """regionOfInterest(IDetector2D self) -> Rectangle"""
+        return _libBornAgainCore.IDetector2D_regionOfInterest(self)
+
+
+    def setRegionOfInterest(self, xlow, ylow, xup, yup):
+        """setRegionOfInterest(IDetector2D self, double xlow, double ylow, double xup, double yup)"""
+        return _libBornAgainCore.IDetector2D_setRegionOfInterest(self, xlow, ylow, xup, yup)
+
+
+    def resetRegionOfInterest(self):
+        """resetRegionOfInterest(IDetector2D self)"""
+        return _libBornAgainCore.IDetector2D_resetRegionOfInterest(self)
+
+
+    def getTotalSize(self):
+        """getTotalSize(IDetector2D self) -> size_t"""
+        return _libBornAgainCore.IDetector2D_getTotalSize(self)
+
+
+    def getAxisBinIndex(self, index, selected_axis):
+        """getAxisBinIndex(IDetector2D self, size_t index, size_t selected_axis) -> size_t"""
+        return _libBornAgainCore.IDetector2D_getAxisBinIndex(self, index, selected_axis)
+
 IDetector2D_swigregister = _libBornAgainCore.IDetector2D_swigregister
 IDetector2D_swigregister(IDetector2D)
 
@@ -19714,18 +19752,6 @@ class SphericalDetector(IDetector2D):
     __swig_destroy__ = _libBornAgainCore.delete_SphericalDetector
     __del__ = lambda self: None
 
-    def createDetectorMap(self, beam, units_type):
-        """
-        createDetectorMap(SphericalDetector self, Beam beam, IDetector2D::EAxesUnits units_type) -> IntensityData
-
-        OutputData< double > * SphericalDetector::createDetectorMap(const Beam &beam, EAxesUnits units_type) const override
-
-        Returns detector map in given axes units. 
-
-        """
-        return _libBornAgainCore.SphericalDetector_createDetectorMap(self, beam, units_type)
-
-
     def getValidAxesUnits(self):
         """
         getValidAxesUnits(SphericalDetector self) -> std::vector< IDetector2D::EAxesUnits,std::allocator< IDetector2D::EAxesUnits > >
@@ -23961,18 +23987,6 @@ class RectangularDetector(IDetector2D):
         return _libBornAgainCore.RectangularDetector_getDetectorArrangment(self)
 
 
-    def createDetectorMap(self, beam, units_type):
-        """
-        createDetectorMap(RectangularDetector self, Beam beam, IDetector2D::EAxesUnits units_type) -> IntensityData
-
-        OutputData< double > * RectangularDetector::createDetectorMap(const Beam &beam, EAxesUnits units_type) const override
-
-        Returns detector map in given axes units. 
-
-        """
-        return _libBornAgainCore.RectangularDetector_createDetectorMap(self, beam, units_type)
-
-
     def getValidAxesUnits(self):
         """
         getValidAxesUnits(RectangularDetector self) -> std::vector< IDetector2D::EAxesUnits,std::allocator< IDetector2D::EAxesUnits > >
@@ -24406,7 +24420,7 @@ class ThreadInfo(_object):
 ThreadInfo_swigregister = _libBornAgainCore.ThreadInfo_swigregister
 ThreadInfo_swigregister(ThreadInfo)
 
-class SampleBuilderFactory(_object):
+class SampleBuilderFactoryTemp(_object):
     """
 
 
@@ -24417,19 +24431,19 @@ class SampleBuilderFactory(_object):
     """
 
     __swig_setmethods__ = {}
-    __setattr__ = lambda self, name, value: _swig_setattr(self, SampleBuilderFactory, name, value)
+    __setattr__ = lambda self, name, value: _swig_setattr(self, SampleBuilderFactoryTemp, name, value)
     __swig_getmethods__ = {}
-    __getattr__ = lambda self, name: _swig_getattr(self, SampleBuilderFactory, name)
+    __getattr__ = lambda self, name: _swig_getattr(self, SampleBuilderFactoryTemp, name)
     __repr__ = _swig_repr
 
     def __init__(self):
         """
-        __init__(IFactory<(std::string,IMultiLayerBuilder)> self) -> SampleBuilderFactory
+        __init__(IFactory<(std::string,IMultiLayerBuilder)> self) -> SampleBuilderFactoryTemp
 
         IFactory< Key, AbstractProduct >::IFactory()
 
         """
-        this = _libBornAgainCore.new_SampleBuilderFactory()
+        this = _libBornAgainCore.new_SampleBuilderFactoryTemp()
         try:
             self.this.append(this)
         except Exception:
@@ -24437,66 +24451,115 @@ class SampleBuilderFactory(_object):
 
     def createItem(self, item_key):
         """
-        createItem(SampleBuilderFactory self, std::string const & item_key) -> IMultiLayerBuilder
+        createItem(SampleBuilderFactoryTemp self, std::string const & item_key) -> IMultiLayerBuilder
 
         AbstractProduct* IFactory< Key, AbstractProduct >::createItem(const Key &item_key)
 
         Creates object by calling creation function corresponded to given identifier. 
 
         """
-        return _libBornAgainCore.SampleBuilderFactory_createItem(self, item_key)
+        return _libBornAgainCore.SampleBuilderFactoryTemp_createItem(self, item_key)
 
 
     def registerItem(self, *args):
         """
-        registerItem(SampleBuilderFactory self, std::string const & item_key, IFactory< std::string,IMultiLayerBuilder >::CreateItemCallback CreateFn, std::string const & itemDescription) -> bool
-        registerItem(SampleBuilderFactory self, std::string const & item_key, IFactory< std::string,IMultiLayerBuilder >::CreateItemCallback CreateFn) -> bool
+        registerItem(SampleBuilderFactoryTemp self, std::string const & item_key, IFactory< std::string,IMultiLayerBuilder >::CreateItemCallback CreateFn, std::string const & itemDescription) -> bool
+        registerItem(SampleBuilderFactoryTemp self, std::string const & item_key, IFactory< std::string,IMultiLayerBuilder >::CreateItemCallback CreateFn) -> bool
 
         bool IFactory< Key, AbstractProduct >::registerItem(const Key &item_key, CreateItemCallback CreateFn, const std::string &itemDescription="")
 
         Registers object's creation function and store object description. 
 
         """
-        return _libBornAgainCore.SampleBuilderFactory_registerItem(self, *args)
+        return _libBornAgainCore.SampleBuilderFactoryTemp_registerItem(self, *args)
 
-    __swig_destroy__ = _libBornAgainCore.delete_SampleBuilderFactory
+    __swig_destroy__ = _libBornAgainCore.delete_SampleBuilderFactoryTemp
     __del__ = lambda self: None
 
     def getNumberOfRegistered(self):
         """
-        getNumberOfRegistered(SampleBuilderFactory self) -> size_t
+        getNumberOfRegistered(SampleBuilderFactoryTemp self) -> size_t
 
         size_t IFactory< Key, AbstractProduct >::getNumberOfRegistered() const
 
         Returns number of registered objects. 
 
         """
-        return _libBornAgainCore.SampleBuilderFactory_getNumberOfRegistered(self)
+        return _libBornAgainCore.SampleBuilderFactoryTemp_getNumberOfRegistered(self)
 
 
     def begin(self):
         """
-        begin(SampleBuilderFactory self) -> IFactory< std::string,IMultiLayerBuilder >::const_iterator
+        begin(SampleBuilderFactoryTemp self) -> IFactory< std::string,IMultiLayerBuilder >::const_iterator
 
         const_iterator IFactory< Key, AbstractProduct >::begin() const 
 
         """
-        return _libBornAgainCore.SampleBuilderFactory_begin(self)
+        return _libBornAgainCore.SampleBuilderFactoryTemp_begin(self)
 
 
     def end(self):
         """
-        end(SampleBuilderFactory self) -> IFactory< std::string,IMultiLayerBuilder >::const_iterator
+        end(SampleBuilderFactoryTemp self) -> IFactory< std::string,IMultiLayerBuilder >::const_iterator
 
         const_iterator IFactory< Key, AbstractProduct >::end() const 
 
         """
-        return _libBornAgainCore.SampleBuilderFactory_end(self)
+        return _libBornAgainCore.SampleBuilderFactoryTemp_end(self)
+
+SampleBuilderFactoryTemp_swigregister = _libBornAgainCore.SampleBuilderFactoryTemp_swigregister
+SampleBuilderFactoryTemp_swigregister(SampleBuilderFactoryTemp)
+
+class SampleBuilderFactory(SampleBuilderFactoryTemp):
+    """
+
+
+    Factory to create standard pre-defined samples.
+
+    C++ includes: SampleBuilderFactory.h
+
+    """
+
+    __swig_setmethods__ = {}
+    for _s in [SampleBuilderFactoryTemp]:
+        __swig_setmethods__.update(getattr(_s, '__swig_setmethods__', {}))
+    __setattr__ = lambda self, name, value: _swig_setattr(self, SampleBuilderFactory, name, value)
+    __swig_getmethods__ = {}
+    for _s in [SampleBuilderFactoryTemp]:
+        __swig_getmethods__.update(getattr(_s, '__swig_getmethods__', {}))
+    __getattr__ = lambda self, name: _swig_getattr(self, SampleBuilderFactory, name)
+    __repr__ = _swig_repr
+
+    def __init__(self):
+        """
+        __init__(SampleBuilderFactory self) -> SampleBuilderFactory
+
+        SampleBuilderFactory::SampleBuilderFactory()
+
+        """
+        this = _libBornAgainCore.new_SampleBuilderFactory()
+        try:
+            self.this.append(this)
+        except Exception:
+            self.this = this
 
+    def createSample(self, name):
+        """
+        createSample(SampleBuilderFactory self, std::string const & name) -> MultiLayer
+
+        MultiLayer * SampleBuilderFactory::createSample(const std::string &name)
+
+        Retrieves a SampleBuilder from the registry, does the build, and returns the result. 
+
+        """
+        return _libBornAgainCore.SampleBuilderFactory_createSample(self, name)
+
+    __swig_destroy__ = _libBornAgainCore.delete_SampleBuilderFactory
+    __del__ = lambda self: None
 SampleBuilderFactory_swigregister = _libBornAgainCore.SampleBuilderFactory_swigregister
 SampleBuilderFactory_swigregister(SampleBuilderFactory)
 
-class SimulationFactory(_object):
+class SimulationFactoryTemp(_object):
     """
 
 
@@ -24507,19 +24570,19 @@ class SimulationFactory(_object):
     """
 
     __swig_setmethods__ = {}
-    __setattr__ = lambda self, name, value: _swig_setattr(self, SimulationFactory, name, value)
+    __setattr__ = lambda self, name, value: _swig_setattr(self, SimulationFactoryTemp, name, value)
     __swig_getmethods__ = {}
-    __getattr__ = lambda self, name: _swig_getattr(self, SimulationFactory, name)
+    __getattr__ = lambda self, name: _swig_getattr(self, SimulationFactoryTemp, name)
     __repr__ = _swig_repr
 
     def __init__(self):
         """
-        __init__(IFactory<(std::string,GISASSimulation)> self) -> SimulationFactory
+        __init__(IFactory<(std::string,GISASSimulation)> self) -> SimulationFactoryTemp
 
         IFactory< Key, AbstractProduct >::IFactory()
 
         """
-        this = _libBornAgainCore.new_SimulationFactory()
+        this = _libBornAgainCore.new_SimulationFactoryTemp()
         try:
             self.this.append(this)
         except Exception:
@@ -24527,62 +24590,99 @@ class SimulationFactory(_object):
 
     def createItem(self, item_key):
         """
-        createItem(SimulationFactory self, std::string const & item_key) -> GISASSimulation
+        createItem(SimulationFactoryTemp self, std::string const & item_key) -> GISASSimulation
 
         AbstractProduct* IFactory< Key, AbstractProduct >::createItem(const Key &item_key)
 
         Creates object by calling creation function corresponded to given identifier. 
 
         """
-        return _libBornAgainCore.SimulationFactory_createItem(self, item_key)
+        return _libBornAgainCore.SimulationFactoryTemp_createItem(self, item_key)
 
 
     def registerItem(self, *args):
         """
-        registerItem(SimulationFactory self, std::string const & item_key, IFactory< std::string,GISASSimulation >::CreateItemCallback CreateFn, std::string const & itemDescription) -> bool
-        registerItem(SimulationFactory self, std::string const & item_key, IFactory< std::string,GISASSimulation >::CreateItemCallback CreateFn) -> bool
+        registerItem(SimulationFactoryTemp self, std::string const & item_key, IFactory< std::string,GISASSimulation >::CreateItemCallback CreateFn, std::string const & itemDescription) -> bool
+        registerItem(SimulationFactoryTemp self, std::string const & item_key, IFactory< std::string,GISASSimulation >::CreateItemCallback CreateFn) -> bool
 
         bool IFactory< Key, AbstractProduct >::registerItem(const Key &item_key, CreateItemCallback CreateFn, const std::string &itemDescription="")
 
         Registers object's creation function and store object description. 
 
         """
-        return _libBornAgainCore.SimulationFactory_registerItem(self, *args)
+        return _libBornAgainCore.SimulationFactoryTemp_registerItem(self, *args)
 
-    __swig_destroy__ = _libBornAgainCore.delete_SimulationFactory
+    __swig_destroy__ = _libBornAgainCore.delete_SimulationFactoryTemp
     __del__ = lambda self: None
 
     def getNumberOfRegistered(self):
         """
-        getNumberOfRegistered(SimulationFactory self) -> size_t
+        getNumberOfRegistered(SimulationFactoryTemp self) -> size_t
 
         size_t IFactory< Key, AbstractProduct >::getNumberOfRegistered() const
 
         Returns number of registered objects. 
 
         """
-        return _libBornAgainCore.SimulationFactory_getNumberOfRegistered(self)
+        return _libBornAgainCore.SimulationFactoryTemp_getNumberOfRegistered(self)
 
 
     def begin(self):
         """
-        begin(SimulationFactory self) -> IFactory< std::string,GISASSimulation >::const_iterator
+        begin(SimulationFactoryTemp self) -> IFactory< std::string,GISASSimulation >::const_iterator
 
         const_iterator IFactory< Key, AbstractProduct >::begin() const 
 
         """
-        return _libBornAgainCore.SimulationFactory_begin(self)
+        return _libBornAgainCore.SimulationFactoryTemp_begin(self)
 
 
     def end(self):
         """
-        end(SimulationFactory self) -> IFactory< std::string,GISASSimulation >::const_iterator
+        end(SimulationFactoryTemp self) -> IFactory< std::string,GISASSimulation >::const_iterator
 
         const_iterator IFactory< Key, AbstractProduct >::end() const 
 
         """
-        return _libBornAgainCore.SimulationFactory_end(self)
+        return _libBornAgainCore.SimulationFactoryTemp_end(self)
+
+SimulationFactoryTemp_swigregister = _libBornAgainCore.SimulationFactoryTemp_swigregister
+SimulationFactoryTemp_swigregister(SimulationFactoryTemp)
+
+class SimulationFactory(SimulationFactoryTemp):
+    """
+
+
+    Registry to create standard pre-defined simulations. Used in functional tests, performance measurements, etc.
+
+    C++ includes: SimulationFactory.h
+
+    """
+
+    __swig_setmethods__ = {}
+    for _s in [SimulationFactoryTemp]:
+        __swig_setmethods__.update(getattr(_s, '__swig_setmethods__', {}))
+    __setattr__ = lambda self, name, value: _swig_setattr(self, SimulationFactory, name, value)
+    __swig_getmethods__ = {}
+    for _s in [SimulationFactoryTemp]:
+        __swig_getmethods__.update(getattr(_s, '__swig_getmethods__', {}))
+    __getattr__ = lambda self, name: _swig_getattr(self, SimulationFactory, name)
+    __repr__ = _swig_repr
+
+    def __init__(self):
+        """
+        __init__(SimulationFactory self) -> SimulationFactory
 
+        SimulationFactory::SimulationFactory()
+
+        """
+        this = _libBornAgainCore.new_SimulationFactory()
+        try:
+            self.this.append(this)
+        except Exception:
+            self.this = this
+    __swig_destroy__ = _libBornAgainCore.delete_SimulationFactory
+    __del__ = lambda self: None
 SimulationFactory_swigregister = _libBornAgainCore.SimulationFactory_swigregister
 SimulationFactory_swigregister(SimulationFactory)
 
diff --git a/auto/Wrap/libBornAgainCore_wrap.cpp b/auto/Wrap/libBornAgainCore_wrap.cpp
index e52d454a67b9f95ec74663b72f1dd9bfd6349dc6..a3221c56b0d8c5a24c4fcbb1396fd56ba733c7b9 100644
--- a/auto/Wrap/libBornAgainCore_wrap.cpp
+++ b/auto/Wrap/libBornAgainCore_wrap.cpp
@@ -3665,90 +3665,92 @@ namespace Swig {
 #define SWIGTYPE_p_RotationY swig_types[208]
 #define SWIGTYPE_p_RotationZ swig_types[209]
 #define SWIGTYPE_p_SafePointerVectorT_IParticle_const_t swig_types[210]
-#define SWIGTYPE_p_SimpleSelectionRule swig_types[211]
-#define SWIGTYPE_p_Simulation swig_types[212]
-#define SWIGTYPE_p_SimulationOptions swig_types[213]
-#define SWIGTYPE_p_SpecularSimulation swig_types[214]
-#define SWIGTYPE_p_SphericalDetector swig_types[215]
-#define SWIGTYPE_p_SquaredFunctionDefault swig_types[216]
-#define SWIGTYPE_p_SquaredFunctionGaussianError swig_types[217]
-#define SWIGTYPE_p_SquaredFunctionMeanSquaredError swig_types[218]
-#define SWIGTYPE_p_SquaredFunctionSimError swig_types[219]
-#define SWIGTYPE_p_SquaredFunctionSystematicError swig_types[220]
-#define SWIGTYPE_p_ThreadInfo swig_types[221]
-#define SWIGTYPE_p_Transform3D swig_types[222]
-#define SWIGTYPE_p_VariableBinAxis swig_types[223]
-#define SWIGTYPE_p_WavevectorInfo swig_types[224]
-#define SWIGTYPE_p__object swig_types[225]
-#define SWIGTYPE_p_allocator_type swig_types[226]
-#define SWIGTYPE_p_bool swig_types[227]
-#define SWIGTYPE_p_char swig_types[228]
-#define SWIGTYPE_p_const_iterator swig_types[229]
-#define SWIGTYPE_p_const_reference swig_types[230]
-#define SWIGTYPE_p_difference_type swig_types[231]
-#define SWIGTYPE_p_double swig_types[232]
-#define SWIGTYPE_p_int swig_types[233]
-#define SWIGTYPE_p_iterator swig_types[234]
-#define SWIGTYPE_p_long_long swig_types[235]
-#define SWIGTYPE_p_observer_t swig_types[236]
-#define SWIGTYPE_p_observerlist_t swig_types[237]
-#define SWIGTYPE_p_p__object swig_types[238]
-#define SWIGTYPE_p_reference swig_types[239]
-#define SWIGTYPE_p_short swig_types[240]
-#define SWIGTYPE_p_signed_char swig_types[241]
-#define SWIGTYPE_p_size_type swig_types[242]
-#define SWIGTYPE_p_std__allocatorT_BasicVector3DT_double_t_t swig_types[243]
-#define SWIGTYPE_p_std__allocatorT_BasicVector3DT_std__complexT_double_t_t_t swig_types[244]
-#define SWIGTYPE_p_std__allocatorT_IFormFactor_p_t swig_types[245]
-#define SWIGTYPE_p_std__allocatorT_ISample_const_p_t swig_types[246]
-#define SWIGTYPE_p_std__allocatorT_ISample_p_t swig_types[247]
-#define SWIGTYPE_p_std__allocatorT_double_t swig_types[248]
-#define SWIGTYPE_p_std__allocatorT_int_t swig_types[249]
-#define SWIGTYPE_p_std__allocatorT_std__complexT_double_t_t swig_types[250]
-#define SWIGTYPE_p_std__allocatorT_std__string_t swig_types[251]
-#define SWIGTYPE_p_std__allocatorT_std__vectorT_double_std__allocatorT_double_t_t_t swig_types[252]
-#define SWIGTYPE_p_std__allocatorT_unsigned_long_t swig_types[253]
-#define SWIGTYPE_p_std__complexT_double_t swig_types[254]
-#define SWIGTYPE_p_std__functionT_GISASSimulation_pfF_t swig_types[255]
-#define SWIGTYPE_p_std__functionT_IMultiLayerBuilder_pfF_t swig_types[256]
-#define SWIGTYPE_p_std__functionT_void_fF_t swig_types[257]
-#define SWIGTYPE_p_std__invalid_argument swig_types[258]
-#define SWIGTYPE_p_std__mapT_std__string_std__string_t__const_iterator swig_types[259]
-#define SWIGTYPE_p_std__ostream swig_types[260]
-#define SWIGTYPE_p_std__shared_ptrT_IFitObserver_t swig_types[261]
-#define SWIGTYPE_p_std__shared_ptrT_ILayerRTCoefficients_const_t swig_types[262]
-#define SWIGTYPE_p_std__shared_ptrT_IMultiLayerBuilder_t swig_types[263]
-#define SWIGTYPE_p_std__shared_ptrT_IObserver_t swig_types[264]
-#define SWIGTYPE_p_std__vectorT_BasicVector3DT_double_t_std__allocatorT_BasicVector3DT_double_t_t_t swig_types[265]
-#define SWIGTYPE_p_std__vectorT_BasicVector3DT_std__complexT_double_t_t_std__allocatorT_BasicVector3DT_std__complexT_double_t_t_t_t swig_types[266]
-#define SWIGTYPE_p_std__vectorT_FitElement_std__allocatorT_FitElement_t_t swig_types[267]
-#define SWIGTYPE_p_std__vectorT_FitElement_std__allocatorT_FitElement_t_t__const_iterator swig_types[268]
-#define SWIGTYPE_p_std__vectorT_FitElement_std__allocatorT_FitElement_t_t__iterator swig_types[269]
-#define SWIGTYPE_p_std__vectorT_IDetector2D__EAxesUnits_std__allocatorT_IDetector2D__EAxesUnits_t_t swig_types[270]
-#define SWIGTYPE_p_std__vectorT_IFTDistribution2D_const_p_std__allocatorT_IFTDistribution2D_const_p_t_t swig_types[271]
-#define SWIGTYPE_p_std__vectorT_IFormFactor_p_std__allocatorT_IFormFactor_p_t_t swig_types[272]
-#define SWIGTYPE_p_std__vectorT_IMaterial_const_p_std__allocatorT_IMaterial_const_p_t_t swig_types[273]
-#define SWIGTYPE_p_std__vectorT_IParticle_const_p_std__allocatorT_IParticle_const_p_t_t swig_types[274]
-#define SWIGTYPE_p_std__vectorT_ISample_const_p_std__allocatorT_ISample_const_p_t_t swig_types[275]
-#define SWIGTYPE_p_std__vectorT_ISample_p_std__allocatorT_ISample_p_t_t swig_types[276]
-#define SWIGTYPE_p_std__vectorT_ParameterSample_std__allocatorT_ParameterSample_t_t swig_types[277]
-#define SWIGTYPE_p_std__vectorT_PolygonalTopology_std__allocatorT_PolygonalTopology_t_t swig_types[278]
-#define SWIGTYPE_p_std__vectorT_RealParameter_p_std__allocatorT_RealParameter_p_t_t swig_types[279]
-#define SWIGTYPE_p_std__vectorT_double_std__allocatorT_double_t_t swig_types[280]
-#define SWIGTYPE_p_std__vectorT_int_std__allocatorT_int_t_t swig_types[281]
-#define SWIGTYPE_p_std__vectorT_size_t_std__allocatorT_size_t_t_t swig_types[282]
-#define SWIGTYPE_p_std__vectorT_std__complexT_double_t_std__allocatorT_std__complexT_double_t_t_t swig_types[283]
-#define SWIGTYPE_p_std__vectorT_std__string_std__allocatorT_std__string_t_t swig_types[284]
-#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[285]
-#define SWIGTYPE_p_std__vectorT_unsigned_long_std__allocatorT_unsigned_long_t_t swig_types[286]
-#define SWIGTYPE_p_swig__SwigPyIterator swig_types[287]
-#define SWIGTYPE_p_unsigned_char swig_types[288]
-#define SWIGTYPE_p_unsigned_int swig_types[289]
-#define SWIGTYPE_p_unsigned_long_long swig_types[290]
-#define SWIGTYPE_p_unsigned_short swig_types[291]
-#define SWIGTYPE_p_value_type swig_types[292]
-static swig_type_info *swig_types[294];
-static swig_module_info swig_module = {swig_types, 293, 0, 0, 0, 0};
+#define SWIGTYPE_p_SampleBuilderFactory swig_types[211]
+#define SWIGTYPE_p_SimpleSelectionRule swig_types[212]
+#define SWIGTYPE_p_Simulation swig_types[213]
+#define SWIGTYPE_p_SimulationFactory swig_types[214]
+#define SWIGTYPE_p_SimulationOptions swig_types[215]
+#define SWIGTYPE_p_SpecularSimulation swig_types[216]
+#define SWIGTYPE_p_SphericalDetector swig_types[217]
+#define SWIGTYPE_p_SquaredFunctionDefault swig_types[218]
+#define SWIGTYPE_p_SquaredFunctionGaussianError swig_types[219]
+#define SWIGTYPE_p_SquaredFunctionMeanSquaredError swig_types[220]
+#define SWIGTYPE_p_SquaredFunctionSimError swig_types[221]
+#define SWIGTYPE_p_SquaredFunctionSystematicError swig_types[222]
+#define SWIGTYPE_p_ThreadInfo swig_types[223]
+#define SWIGTYPE_p_Transform3D swig_types[224]
+#define SWIGTYPE_p_VariableBinAxis swig_types[225]
+#define SWIGTYPE_p_WavevectorInfo swig_types[226]
+#define SWIGTYPE_p__object swig_types[227]
+#define SWIGTYPE_p_allocator_type swig_types[228]
+#define SWIGTYPE_p_bool swig_types[229]
+#define SWIGTYPE_p_char swig_types[230]
+#define SWIGTYPE_p_const_iterator swig_types[231]
+#define SWIGTYPE_p_const_reference swig_types[232]
+#define SWIGTYPE_p_difference_type swig_types[233]
+#define SWIGTYPE_p_double swig_types[234]
+#define SWIGTYPE_p_int swig_types[235]
+#define SWIGTYPE_p_iterator swig_types[236]
+#define SWIGTYPE_p_long_long swig_types[237]
+#define SWIGTYPE_p_observer_t swig_types[238]
+#define SWIGTYPE_p_observerlist_t swig_types[239]
+#define SWIGTYPE_p_p__object swig_types[240]
+#define SWIGTYPE_p_reference swig_types[241]
+#define SWIGTYPE_p_short swig_types[242]
+#define SWIGTYPE_p_signed_char swig_types[243]
+#define SWIGTYPE_p_size_type swig_types[244]
+#define SWIGTYPE_p_std__allocatorT_BasicVector3DT_double_t_t swig_types[245]
+#define SWIGTYPE_p_std__allocatorT_BasicVector3DT_std__complexT_double_t_t_t swig_types[246]
+#define SWIGTYPE_p_std__allocatorT_IFormFactor_p_t swig_types[247]
+#define SWIGTYPE_p_std__allocatorT_ISample_const_p_t swig_types[248]
+#define SWIGTYPE_p_std__allocatorT_ISample_p_t swig_types[249]
+#define SWIGTYPE_p_std__allocatorT_double_t swig_types[250]
+#define SWIGTYPE_p_std__allocatorT_int_t swig_types[251]
+#define SWIGTYPE_p_std__allocatorT_std__complexT_double_t_t swig_types[252]
+#define SWIGTYPE_p_std__allocatorT_std__string_t swig_types[253]
+#define SWIGTYPE_p_std__allocatorT_std__vectorT_double_std__allocatorT_double_t_t_t swig_types[254]
+#define SWIGTYPE_p_std__allocatorT_unsigned_long_t swig_types[255]
+#define SWIGTYPE_p_std__complexT_double_t swig_types[256]
+#define SWIGTYPE_p_std__functionT_GISASSimulation_pfF_t swig_types[257]
+#define SWIGTYPE_p_std__functionT_IMultiLayerBuilder_pfF_t swig_types[258]
+#define SWIGTYPE_p_std__functionT_void_fF_t swig_types[259]
+#define SWIGTYPE_p_std__invalid_argument swig_types[260]
+#define SWIGTYPE_p_std__mapT_std__string_std__string_t__const_iterator swig_types[261]
+#define SWIGTYPE_p_std__ostream swig_types[262]
+#define SWIGTYPE_p_std__shared_ptrT_IFitObserver_t swig_types[263]
+#define SWIGTYPE_p_std__shared_ptrT_ILayerRTCoefficients_const_t swig_types[264]
+#define SWIGTYPE_p_std__shared_ptrT_IMultiLayerBuilder_t swig_types[265]
+#define SWIGTYPE_p_std__shared_ptrT_IObserver_t swig_types[266]
+#define SWIGTYPE_p_std__vectorT_BasicVector3DT_double_t_std__allocatorT_BasicVector3DT_double_t_t_t swig_types[267]
+#define SWIGTYPE_p_std__vectorT_BasicVector3DT_std__complexT_double_t_t_std__allocatorT_BasicVector3DT_std__complexT_double_t_t_t_t swig_types[268]
+#define SWIGTYPE_p_std__vectorT_FitElement_std__allocatorT_FitElement_t_t swig_types[269]
+#define SWIGTYPE_p_std__vectorT_FitElement_std__allocatorT_FitElement_t_t__const_iterator swig_types[270]
+#define SWIGTYPE_p_std__vectorT_FitElement_std__allocatorT_FitElement_t_t__iterator swig_types[271]
+#define SWIGTYPE_p_std__vectorT_IDetector2D__EAxesUnits_std__allocatorT_IDetector2D__EAxesUnits_t_t swig_types[272]
+#define SWIGTYPE_p_std__vectorT_IFTDistribution2D_const_p_std__allocatorT_IFTDistribution2D_const_p_t_t swig_types[273]
+#define SWIGTYPE_p_std__vectorT_IFormFactor_p_std__allocatorT_IFormFactor_p_t_t swig_types[274]
+#define SWIGTYPE_p_std__vectorT_IMaterial_const_p_std__allocatorT_IMaterial_const_p_t_t swig_types[275]
+#define SWIGTYPE_p_std__vectorT_IParticle_const_p_std__allocatorT_IParticle_const_p_t_t swig_types[276]
+#define SWIGTYPE_p_std__vectorT_ISample_const_p_std__allocatorT_ISample_const_p_t_t swig_types[277]
+#define SWIGTYPE_p_std__vectorT_ISample_p_std__allocatorT_ISample_p_t_t swig_types[278]
+#define SWIGTYPE_p_std__vectorT_ParameterSample_std__allocatorT_ParameterSample_t_t swig_types[279]
+#define SWIGTYPE_p_std__vectorT_PolygonalTopology_std__allocatorT_PolygonalTopology_t_t swig_types[280]
+#define SWIGTYPE_p_std__vectorT_RealParameter_p_std__allocatorT_RealParameter_p_t_t swig_types[281]
+#define SWIGTYPE_p_std__vectorT_double_std__allocatorT_double_t_t swig_types[282]
+#define SWIGTYPE_p_std__vectorT_int_std__allocatorT_int_t_t swig_types[283]
+#define SWIGTYPE_p_std__vectorT_size_t_std__allocatorT_size_t_t_t swig_types[284]
+#define SWIGTYPE_p_std__vectorT_std__complexT_double_t_std__allocatorT_std__complexT_double_t_t_t swig_types[285]
+#define SWIGTYPE_p_std__vectorT_std__string_std__allocatorT_std__string_t_t swig_types[286]
+#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[287]
+#define SWIGTYPE_p_std__vectorT_unsigned_long_std__allocatorT_unsigned_long_t_t swig_types[288]
+#define SWIGTYPE_p_swig__SwigPyIterator swig_types[289]
+#define SWIGTYPE_p_unsigned_char swig_types[290]
+#define SWIGTYPE_p_unsigned_int swig_types[291]
+#define SWIGTYPE_p_unsigned_long_long swig_types[292]
+#define SWIGTYPE_p_unsigned_short swig_types[293]
+#define SWIGTYPE_p_value_type swig_types[294]
+static swig_type_info *swig_types[296];
+static swig_module_info swig_module = {swig_types, 295, 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)
 
@@ -5874,7 +5876,7 @@ SWIG_AsVal_std_complex_Sl_double_Sg_  (PyObject *o, std::complex<double>* val)
 
 
 SWIGINTERNINLINE PyObject*
-SWIG_From_std_complex_Sl_double_Sg_  (/*@SWIG:/usr/share/swig3.0/typemaps/swigmacros.swg,104,%ifcplusplus@*/
+SWIG_From_std_complex_Sl_double_Sg_  (/*@SWIG:/home/pospelov/software/local/share/swig/3.0.8/typemaps/swigmacros.swg,104,%ifcplusplus@*/
 
 const std::complex<double>&
 
@@ -76105,6 +76107,169 @@ fail:
 }
 
 
+SWIGINTERN PyObject *_wrap_IDetector2D_getDetectorIntensity__SWIG_0(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *resultobj = 0;
+  IDetector2D *arg1 = (IDetector2D *) 0 ;
+  OutputData< double > *arg2 = 0 ;
+  Beam *arg3 = 0 ;
+  IDetector2D::EAxesUnits arg4 ;
+  void *argp1 = 0 ;
+  int res1 = 0 ;
+  void *argp2 = 0 ;
+  int res2 = 0 ;
+  void *argp3 = 0 ;
+  int res3 = 0 ;
+  int val4 ;
+  int ecode4 = 0 ;
+  PyObject * obj0 = 0 ;
+  PyObject * obj1 = 0 ;
+  PyObject * obj2 = 0 ;
+  PyObject * obj3 = 0 ;
+  OutputData< double > *result = 0 ;
+  
+  if (!PyArg_ParseTuple(args,(char *)"OOOO:IDetector2D_getDetectorIntensity",&obj0,&obj1,&obj2,&obj3)) SWIG_fail;
+  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_IDetector2D, 0 |  0 );
+  if (!SWIG_IsOK(res1)) {
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "IDetector2D_getDetectorIntensity" "', argument " "1"" of type '" "IDetector2D const *""'"); 
+  }
+  arg1 = reinterpret_cast< IDetector2D * >(argp1);
+  res2 = SWIG_ConvertPtr(obj1, &argp2, SWIGTYPE_p_OutputDataT_double_t,  0  | 0);
+  if (!SWIG_IsOK(res2)) {
+    SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "IDetector2D_getDetectorIntensity" "', argument " "2"" of type '" "OutputData< double > const &""'"); 
+  }
+  if (!argp2) {
+    SWIG_exception_fail(SWIG_ValueError, "invalid null reference " "in method '" "IDetector2D_getDetectorIntensity" "', argument " "2"" of type '" "OutputData< double > const &""'"); 
+  }
+  arg2 = reinterpret_cast< OutputData< double > * >(argp2);
+  res3 = SWIG_ConvertPtr(obj2, &argp3, SWIGTYPE_p_Beam,  0  | 0);
+  if (!SWIG_IsOK(res3)) {
+    SWIG_exception_fail(SWIG_ArgError(res3), "in method '" "IDetector2D_getDetectorIntensity" "', argument " "3"" of type '" "Beam const &""'"); 
+  }
+  if (!argp3) {
+    SWIG_exception_fail(SWIG_ValueError, "invalid null reference " "in method '" "IDetector2D_getDetectorIntensity" "', argument " "3"" of type '" "Beam const &""'"); 
+  }
+  arg3 = reinterpret_cast< Beam * >(argp3);
+  ecode4 = SWIG_AsVal_int(obj3, &val4);
+  if (!SWIG_IsOK(ecode4)) {
+    SWIG_exception_fail(SWIG_ArgError(ecode4), "in method '" "IDetector2D_getDetectorIntensity" "', argument " "4"" of type '" "IDetector2D::EAxesUnits""'");
+  } 
+  arg4 = static_cast< IDetector2D::EAxesUnits >(val4);
+  result = (OutputData< double > *)((IDetector2D const *)arg1)->getDetectorIntensity((OutputData< double > const &)*arg2,(Beam const &)*arg3,arg4);
+  resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_OutputDataT_double_t, 0 |  0 );
+  return resultobj;
+fail:
+  return NULL;
+}
+
+
+SWIGINTERN PyObject *_wrap_IDetector2D_getDetectorIntensity__SWIG_1(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *resultobj = 0;
+  IDetector2D *arg1 = (IDetector2D *) 0 ;
+  OutputData< double > *arg2 = 0 ;
+  Beam *arg3 = 0 ;
+  void *argp1 = 0 ;
+  int res1 = 0 ;
+  void *argp2 = 0 ;
+  int res2 = 0 ;
+  void *argp3 = 0 ;
+  int res3 = 0 ;
+  PyObject * obj0 = 0 ;
+  PyObject * obj1 = 0 ;
+  PyObject * obj2 = 0 ;
+  OutputData< double > *result = 0 ;
+  
+  if (!PyArg_ParseTuple(args,(char *)"OOO:IDetector2D_getDetectorIntensity",&obj0,&obj1,&obj2)) SWIG_fail;
+  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_IDetector2D, 0 |  0 );
+  if (!SWIG_IsOK(res1)) {
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "IDetector2D_getDetectorIntensity" "', argument " "1"" of type '" "IDetector2D const *""'"); 
+  }
+  arg1 = reinterpret_cast< IDetector2D * >(argp1);
+  res2 = SWIG_ConvertPtr(obj1, &argp2, SWIGTYPE_p_OutputDataT_double_t,  0  | 0);
+  if (!SWIG_IsOK(res2)) {
+    SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "IDetector2D_getDetectorIntensity" "', argument " "2"" of type '" "OutputData< double > const &""'"); 
+  }
+  if (!argp2) {
+    SWIG_exception_fail(SWIG_ValueError, "invalid null reference " "in method '" "IDetector2D_getDetectorIntensity" "', argument " "2"" of type '" "OutputData< double > const &""'"); 
+  }
+  arg2 = reinterpret_cast< OutputData< double > * >(argp2);
+  res3 = SWIG_ConvertPtr(obj2, &argp3, SWIGTYPE_p_Beam,  0  | 0);
+  if (!SWIG_IsOK(res3)) {
+    SWIG_exception_fail(SWIG_ArgError(res3), "in method '" "IDetector2D_getDetectorIntensity" "', argument " "3"" of type '" "Beam const &""'"); 
+  }
+  if (!argp3) {
+    SWIG_exception_fail(SWIG_ValueError, "invalid null reference " "in method '" "IDetector2D_getDetectorIntensity" "', argument " "3"" of type '" "Beam const &""'"); 
+  }
+  arg3 = reinterpret_cast< Beam * >(argp3);
+  result = (OutputData< double > *)((IDetector2D const *)arg1)->getDetectorIntensity((OutputData< double > const &)*arg2,(Beam const &)*arg3);
+  resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_OutputDataT_double_t, 0 |  0 );
+  return resultobj;
+fail:
+  return NULL;
+}
+
+
+SWIGINTERN PyObject *_wrap_IDetector2D_getDetectorIntensity(PyObject *self, PyObject *args) {
+  Py_ssize_t argc;
+  PyObject *argv[5] = {
+    0
+  };
+  Py_ssize_t ii;
+  
+  if (!PyTuple_Check(args)) SWIG_fail;
+  argc = args ? PyObject_Length(args) : 0;
+  for (ii = 0; (ii < 4) && (ii < argc); ii++) {
+    argv[ii] = PyTuple_GET_ITEM(args,ii);
+  }
+  if (argc == 3) {
+    int _v;
+    void *vptr = 0;
+    int res = SWIG_ConvertPtr(argv[0], &vptr, SWIGTYPE_p_IDetector2D, 0);
+    _v = SWIG_CheckState(res);
+    if (_v) {
+      int res = SWIG_ConvertPtr(argv[1], 0, SWIGTYPE_p_OutputDataT_double_t, 0);
+      _v = SWIG_CheckState(res);
+      if (_v) {
+        int res = SWIG_ConvertPtr(argv[2], 0, SWIGTYPE_p_Beam, 0);
+        _v = SWIG_CheckState(res);
+        if (_v) {
+          return _wrap_IDetector2D_getDetectorIntensity__SWIG_1(self, args);
+        }
+      }
+    }
+  }
+  if (argc == 4) {
+    int _v;
+    void *vptr = 0;
+    int res = SWIG_ConvertPtr(argv[0], &vptr, SWIGTYPE_p_IDetector2D, 0);
+    _v = SWIG_CheckState(res);
+    if (_v) {
+      int res = SWIG_ConvertPtr(argv[1], 0, SWIGTYPE_p_OutputDataT_double_t, 0);
+      _v = SWIG_CheckState(res);
+      if (_v) {
+        int res = SWIG_ConvertPtr(argv[2], 0, SWIGTYPE_p_Beam, 0);
+        _v = SWIG_CheckState(res);
+        if (_v) {
+          {
+            int res = SWIG_AsVal_int(argv[3], NULL);
+            _v = SWIG_CheckState(res);
+          }
+          if (_v) {
+            return _wrap_IDetector2D_getDetectorIntensity__SWIG_0(self, args);
+          }
+        }
+      }
+    }
+  }
+  
+fail:
+  SWIG_SetErrorMsg(PyExc_NotImplementedError,"Wrong number or type of arguments for overloaded function 'IDetector2D_getDetectorIntensity'.\n"
+    "  Possible C/C++ prototypes are:\n"
+    "    IDetector2D::getDetectorIntensity(OutputData< double > const &,Beam const &,IDetector2D::EAxesUnits) const\n"
+    "    IDetector2D::getDetectorIntensity(OutputData< double > const &,Beam const &) const\n");
+  return 0;
+}
+
+
 SWIGINTERN PyObject *_wrap_IDetector2D_createDetectorMap(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
   PyObject *resultobj = 0;
   IDetector2D *arg1 = (IDetector2D *) 0 ;
@@ -76148,6 +76313,39 @@ fail:
 }
 
 
+SWIGINTERN PyObject *_wrap_IDetector2D_initOutputData(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *resultobj = 0;
+  IDetector2D *arg1 = (IDetector2D *) 0 ;
+  OutputData< double > *arg2 = 0 ;
+  void *argp1 = 0 ;
+  int res1 = 0 ;
+  void *argp2 = 0 ;
+  int res2 = 0 ;
+  PyObject * obj0 = 0 ;
+  PyObject * obj1 = 0 ;
+  
+  if (!PyArg_ParseTuple(args,(char *)"OO:IDetector2D_initOutputData",&obj0,&obj1)) SWIG_fail;
+  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_IDetector2D, 0 |  0 );
+  if (!SWIG_IsOK(res1)) {
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "IDetector2D_initOutputData" "', argument " "1"" of type '" "IDetector2D const *""'"); 
+  }
+  arg1 = reinterpret_cast< IDetector2D * >(argp1);
+  res2 = SWIG_ConvertPtr(obj1, &argp2, SWIGTYPE_p_OutputDataT_double_t,  0 );
+  if (!SWIG_IsOK(res2)) {
+    SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "IDetector2D_initOutputData" "', argument " "2"" of type '" "OutputData< double > &""'"); 
+  }
+  if (!argp2) {
+    SWIG_exception_fail(SWIG_ValueError, "invalid null reference " "in method '" "IDetector2D_initOutputData" "', argument " "2"" of type '" "OutputData< double > &""'"); 
+  }
+  arg2 = reinterpret_cast< OutputData< double > * >(argp2);
+  ((IDetector2D const *)arg1)->initOutputData(*arg2);
+  resultobj = SWIG_Py_Void();
+  return resultobj;
+fail:
+  return NULL;
+}
+
+
 SWIGINTERN PyObject *_wrap_IDetector2D_getValidAxesUnits(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
   PyObject *resultobj = 0;
   IDetector2D *arg1 = (IDetector2D *) 0 ;
@@ -76192,6 +76390,168 @@ fail:
 }
 
 
+SWIGINTERN PyObject *_wrap_IDetector2D_regionOfInterest(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *resultobj = 0;
+  IDetector2D *arg1 = (IDetector2D *) 0 ;
+  void *argp1 = 0 ;
+  int res1 = 0 ;
+  PyObject * obj0 = 0 ;
+  Geometry::Rectangle *result = 0 ;
+  
+  if (!PyArg_ParseTuple(args,(char *)"O:IDetector2D_regionOfInterest",&obj0)) SWIG_fail;
+  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_IDetector2D, 0 |  0 );
+  if (!SWIG_IsOK(res1)) {
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "IDetector2D_regionOfInterest" "', argument " "1"" of type '" "IDetector2D const *""'"); 
+  }
+  arg1 = reinterpret_cast< IDetector2D * >(argp1);
+  result = (Geometry::Rectangle *)((IDetector2D const *)arg1)->regionOfInterest();
+  resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_Geometry__Rectangle, 0 |  0 );
+  return resultobj;
+fail:
+  return NULL;
+}
+
+
+SWIGINTERN PyObject *_wrap_IDetector2D_setRegionOfInterest(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *resultobj = 0;
+  IDetector2D *arg1 = (IDetector2D *) 0 ;
+  double arg2 ;
+  double arg3 ;
+  double arg4 ;
+  double arg5 ;
+  void *argp1 = 0 ;
+  int res1 = 0 ;
+  double val2 ;
+  int ecode2 = 0 ;
+  double val3 ;
+  int ecode3 = 0 ;
+  double val4 ;
+  int ecode4 = 0 ;
+  double val5 ;
+  int ecode5 = 0 ;
+  PyObject * obj0 = 0 ;
+  PyObject * obj1 = 0 ;
+  PyObject * obj2 = 0 ;
+  PyObject * obj3 = 0 ;
+  PyObject * obj4 = 0 ;
+  
+  if (!PyArg_ParseTuple(args,(char *)"OOOOO:IDetector2D_setRegionOfInterest",&obj0,&obj1,&obj2,&obj3,&obj4)) SWIG_fail;
+  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_IDetector2D, 0 |  0 );
+  if (!SWIG_IsOK(res1)) {
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "IDetector2D_setRegionOfInterest" "', argument " "1"" of type '" "IDetector2D *""'"); 
+  }
+  arg1 = reinterpret_cast< IDetector2D * >(argp1);
+  ecode2 = SWIG_AsVal_double(obj1, &val2);
+  if (!SWIG_IsOK(ecode2)) {
+    SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "IDetector2D_setRegionOfInterest" "', argument " "2"" of type '" "double""'");
+  } 
+  arg2 = static_cast< double >(val2);
+  ecode3 = SWIG_AsVal_double(obj2, &val3);
+  if (!SWIG_IsOK(ecode3)) {
+    SWIG_exception_fail(SWIG_ArgError(ecode3), "in method '" "IDetector2D_setRegionOfInterest" "', argument " "3"" of type '" "double""'");
+  } 
+  arg3 = static_cast< double >(val3);
+  ecode4 = SWIG_AsVal_double(obj3, &val4);
+  if (!SWIG_IsOK(ecode4)) {
+    SWIG_exception_fail(SWIG_ArgError(ecode4), "in method '" "IDetector2D_setRegionOfInterest" "', argument " "4"" of type '" "double""'");
+  } 
+  arg4 = static_cast< double >(val4);
+  ecode5 = SWIG_AsVal_double(obj4, &val5);
+  if (!SWIG_IsOK(ecode5)) {
+    SWIG_exception_fail(SWIG_ArgError(ecode5), "in method '" "IDetector2D_setRegionOfInterest" "', argument " "5"" of type '" "double""'");
+  } 
+  arg5 = static_cast< double >(val5);
+  (arg1)->setRegionOfInterest(arg2,arg3,arg4,arg5);
+  resultobj = SWIG_Py_Void();
+  return resultobj;
+fail:
+  return NULL;
+}
+
+
+SWIGINTERN PyObject *_wrap_IDetector2D_resetRegionOfInterest(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *resultobj = 0;
+  IDetector2D *arg1 = (IDetector2D *) 0 ;
+  void *argp1 = 0 ;
+  int res1 = 0 ;
+  PyObject * obj0 = 0 ;
+  
+  if (!PyArg_ParseTuple(args,(char *)"O:IDetector2D_resetRegionOfInterest",&obj0)) SWIG_fail;
+  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_IDetector2D, 0 |  0 );
+  if (!SWIG_IsOK(res1)) {
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "IDetector2D_resetRegionOfInterest" "', argument " "1"" of type '" "IDetector2D *""'"); 
+  }
+  arg1 = reinterpret_cast< IDetector2D * >(argp1);
+  (arg1)->resetRegionOfInterest();
+  resultobj = SWIG_Py_Void();
+  return resultobj;
+fail:
+  return NULL;
+}
+
+
+SWIGINTERN PyObject *_wrap_IDetector2D_getTotalSize(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *resultobj = 0;
+  IDetector2D *arg1 = (IDetector2D *) 0 ;
+  void *argp1 = 0 ;
+  int res1 = 0 ;
+  PyObject * obj0 = 0 ;
+  size_t result;
+  
+  if (!PyArg_ParseTuple(args,(char *)"O:IDetector2D_getTotalSize",&obj0)) SWIG_fail;
+  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_IDetector2D, 0 |  0 );
+  if (!SWIG_IsOK(res1)) {
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "IDetector2D_getTotalSize" "', argument " "1"" of type '" "IDetector2D const *""'"); 
+  }
+  arg1 = reinterpret_cast< IDetector2D * >(argp1);
+  result = ((IDetector2D const *)arg1)->getTotalSize();
+  resultobj = SWIG_From_size_t(static_cast< size_t >(result));
+  return resultobj;
+fail:
+  return NULL;
+}
+
+
+SWIGINTERN PyObject *_wrap_IDetector2D_getAxisBinIndex(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *resultobj = 0;
+  IDetector2D *arg1 = (IDetector2D *) 0 ;
+  size_t arg2 ;
+  size_t arg3 ;
+  void *argp1 = 0 ;
+  int res1 = 0 ;
+  size_t val2 ;
+  int ecode2 = 0 ;
+  size_t val3 ;
+  int ecode3 = 0 ;
+  PyObject * obj0 = 0 ;
+  PyObject * obj1 = 0 ;
+  PyObject * obj2 = 0 ;
+  size_t result;
+  
+  if (!PyArg_ParseTuple(args,(char *)"OOO:IDetector2D_getAxisBinIndex",&obj0,&obj1,&obj2)) SWIG_fail;
+  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_IDetector2D, 0 |  0 );
+  if (!SWIG_IsOK(res1)) {
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "IDetector2D_getAxisBinIndex" "', argument " "1"" of type '" "IDetector2D const *""'"); 
+  }
+  arg1 = reinterpret_cast< IDetector2D * >(argp1);
+  ecode2 = SWIG_AsVal_size_t(obj1, &val2);
+  if (!SWIG_IsOK(ecode2)) {
+    SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "IDetector2D_getAxisBinIndex" "', argument " "2"" of type '" "size_t""'");
+  } 
+  arg2 = static_cast< size_t >(val2);
+  ecode3 = SWIG_AsVal_size_t(obj2, &val3);
+  if (!SWIG_IsOK(ecode3)) {
+    SWIG_exception_fail(SWIG_ArgError(ecode3), "in method '" "IDetector2D_getAxisBinIndex" "', argument " "3"" of type '" "size_t""'");
+  } 
+  arg3 = static_cast< size_t >(val3);
+  result = ((IDetector2D const *)arg1)->getAxisBinIndex(arg2,arg3);
+  resultobj = SWIG_From_size_t(static_cast< size_t >(result));
+  return resultobj;
+fail:
+  return NULL;
+}
+
+
 SWIGINTERN PyObject *IDetector2D_swigregister(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
   PyObject *obj;
   if (!PyArg_ParseTuple(args,(char*)"O:swigregister", &obj)) return NULL;
@@ -84047,49 +84407,6 @@ fail:
 }
 
 
-SWIGINTERN PyObject *_wrap_SphericalDetector_createDetectorMap(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
-  SphericalDetector *arg1 = (SphericalDetector *) 0 ;
-  Beam *arg2 = 0 ;
-  IDetector2D::EAxesUnits arg3 ;
-  void *argp1 = 0 ;
-  int res1 = 0 ;
-  void *argp2 = 0 ;
-  int res2 = 0 ;
-  int val3 ;
-  int ecode3 = 0 ;
-  PyObject * obj0 = 0 ;
-  PyObject * obj1 = 0 ;
-  PyObject * obj2 = 0 ;
-  OutputData< double > *result = 0 ;
-  
-  if (!PyArg_ParseTuple(args,(char *)"OOO:SphericalDetector_createDetectorMap",&obj0,&obj1,&obj2)) SWIG_fail;
-  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_SphericalDetector, 0 |  0 );
-  if (!SWIG_IsOK(res1)) {
-    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "SphericalDetector_createDetectorMap" "', argument " "1"" of type '" "SphericalDetector const *""'"); 
-  }
-  arg1 = reinterpret_cast< SphericalDetector * >(argp1);
-  res2 = SWIG_ConvertPtr(obj1, &argp2, SWIGTYPE_p_Beam,  0  | 0);
-  if (!SWIG_IsOK(res2)) {
-    SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "SphericalDetector_createDetectorMap" "', argument " "2"" of type '" "Beam const &""'"); 
-  }
-  if (!argp2) {
-    SWIG_exception_fail(SWIG_ValueError, "invalid null reference " "in method '" "SphericalDetector_createDetectorMap" "', argument " "2"" of type '" "Beam const &""'"); 
-  }
-  arg2 = reinterpret_cast< Beam * >(argp2);
-  ecode3 = SWIG_AsVal_int(obj2, &val3);
-  if (!SWIG_IsOK(ecode3)) {
-    SWIG_exception_fail(SWIG_ArgError(ecode3), "in method '" "SphericalDetector_createDetectorMap" "', argument " "3"" of type '" "IDetector2D::EAxesUnits""'");
-  } 
-  arg3 = static_cast< IDetector2D::EAxesUnits >(val3);
-  result = (OutputData< double > *)((SphericalDetector const *)arg1)->createDetectorMap((Beam const &)*arg2,arg3);
-  resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_OutputDataT_double_t, 0 |  0 );
-  return resultobj;
-fail:
-  return NULL;
-}
-
-
 SWIGINTERN PyObject *_wrap_SphericalDetector_getValidAxesUnits(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
   PyObject *resultobj = 0;
   SphericalDetector *arg1 = (SphericalDetector *) 0 ;
@@ -98546,49 +98863,6 @@ fail:
 }
 
 
-SWIGINTERN PyObject *_wrap_RectangularDetector_createDetectorMap(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
-  RectangularDetector *arg1 = (RectangularDetector *) 0 ;
-  Beam *arg2 = 0 ;
-  IDetector2D::EAxesUnits arg3 ;
-  void *argp1 = 0 ;
-  int res1 = 0 ;
-  void *argp2 = 0 ;
-  int res2 = 0 ;
-  int val3 ;
-  int ecode3 = 0 ;
-  PyObject * obj0 = 0 ;
-  PyObject * obj1 = 0 ;
-  PyObject * obj2 = 0 ;
-  OutputData< double > *result = 0 ;
-  
-  if (!PyArg_ParseTuple(args,(char *)"OOO:RectangularDetector_createDetectorMap",&obj0,&obj1,&obj2)) SWIG_fail;
-  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_RectangularDetector, 0 |  0 );
-  if (!SWIG_IsOK(res1)) {
-    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "RectangularDetector_createDetectorMap" "', argument " "1"" of type '" "RectangularDetector const *""'"); 
-  }
-  arg1 = reinterpret_cast< RectangularDetector * >(argp1);
-  res2 = SWIG_ConvertPtr(obj1, &argp2, SWIGTYPE_p_Beam,  0  | 0);
-  if (!SWIG_IsOK(res2)) {
-    SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "RectangularDetector_createDetectorMap" "', argument " "2"" of type '" "Beam const &""'"); 
-  }
-  if (!argp2) {
-    SWIG_exception_fail(SWIG_ValueError, "invalid null reference " "in method '" "RectangularDetector_createDetectorMap" "', argument " "2"" of type '" "Beam const &""'"); 
-  }
-  arg2 = reinterpret_cast< Beam * >(argp2);
-  ecode3 = SWIG_AsVal_int(obj2, &val3);
-  if (!SWIG_IsOK(ecode3)) {
-    SWIG_exception_fail(SWIG_ArgError(ecode3), "in method '" "RectangularDetector_createDetectorMap" "', argument " "3"" of type '" "IDetector2D::EAxesUnits""'");
-  } 
-  arg3 = static_cast< IDetector2D::EAxesUnits >(val3);
-  result = (OutputData< double > *)((RectangularDetector const *)arg1)->createDetectorMap((Beam const &)*arg2,arg3);
-  resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_OutputDataT_double_t, 0 |  0 );
-  return resultobj;
-fail:
-  return NULL;
-}
-
-
 SWIGINTERN PyObject *_wrap_RectangularDetector_getValidAxesUnits(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
   PyObject *resultobj = 0;
   RectangularDetector *arg1 = (RectangularDetector *) 0 ;
@@ -100109,11 +100383,11 @@ SWIGINTERN PyObject *ThreadInfo_swigregister(PyObject *SWIGUNUSEDPARM(self), PyO
   return SWIG_Py_Void();
 }
 
-SWIGINTERN PyObject *_wrap_new_SampleBuilderFactory(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+SWIGINTERN PyObject *_wrap_new_SampleBuilderFactoryTemp(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
   PyObject *resultobj = 0;
   IFactory< std::string,IMultiLayerBuilder > *result = 0 ;
   
-  if (!PyArg_ParseTuple(args,(char *)":new_SampleBuilderFactory")) SWIG_fail;
+  if (!PyArg_ParseTuple(args,(char *)":new_SampleBuilderFactoryTemp")) SWIG_fail;
   result = (IFactory< std::string,IMultiLayerBuilder > *)new IFactory< std::string,IMultiLayerBuilder >();
   resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_IFactoryT_std__string_IMultiLayerBuilder_t, SWIG_POINTER_NEW |  0 );
   return resultobj;
@@ -100122,7 +100396,7 @@ fail:
 }
 
 
-SWIGINTERN PyObject *_wrap_SampleBuilderFactory_createItem(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+SWIGINTERN PyObject *_wrap_SampleBuilderFactoryTemp_createItem(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
   PyObject *resultobj = 0;
   IFactory< std::string,IMultiLayerBuilder > *arg1 = (IFactory< std::string,IMultiLayerBuilder > *) 0 ;
   std::string *arg2 = 0 ;
@@ -100134,20 +100408,20 @@ SWIGINTERN PyObject *_wrap_SampleBuilderFactory_createItem(PyObject *SWIGUNUSEDP
   Swig::Director *director = 0;
   IMultiLayerBuilder *result = 0 ;
   
-  if (!PyArg_ParseTuple(args,(char *)"OO:SampleBuilderFactory_createItem",&obj0,&obj1)) SWIG_fail;
+  if (!PyArg_ParseTuple(args,(char *)"OO:SampleBuilderFactoryTemp_createItem",&obj0,&obj1)) SWIG_fail;
   res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_IFactoryT_std__string_IMultiLayerBuilder_t, 0 |  0 );
   if (!SWIG_IsOK(res1)) {
-    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "SampleBuilderFactory_createItem" "', argument " "1"" of type '" "IFactory< std::string,IMultiLayerBuilder > *""'"); 
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "SampleBuilderFactoryTemp_createItem" "', argument " "1"" of type '" "IFactory< std::string,IMultiLayerBuilder > *""'"); 
   }
   arg1 = reinterpret_cast< IFactory< std::string,IMultiLayerBuilder > * >(argp1);
   {
     std::string *ptr = (std::string *)0;
     res2 = SWIG_AsPtr_std_string(obj1, &ptr);
     if (!SWIG_IsOK(res2)) {
-      SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "SampleBuilderFactory_createItem" "', argument " "2"" of type '" "std::string const &""'"); 
+      SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "SampleBuilderFactoryTemp_createItem" "', argument " "2"" of type '" "std::string const &""'"); 
     }
     if (!ptr) {
-      SWIG_exception_fail(SWIG_ValueError, "invalid null reference " "in method '" "SampleBuilderFactory_createItem" "', argument " "2"" of type '" "std::string const &""'"); 
+      SWIG_exception_fail(SWIG_ValueError, "invalid null reference " "in method '" "SampleBuilderFactoryTemp_createItem" "', argument " "2"" of type '" "std::string const &""'"); 
     }
     arg2 = ptr;
   }
@@ -100170,7 +100444,7 @@ fail:
 }
 
 
-SWIGINTERN PyObject *_wrap_SampleBuilderFactory_registerItem__SWIG_0(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+SWIGINTERN PyObject *_wrap_SampleBuilderFactoryTemp_registerItem__SWIG_0(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
   PyObject *resultobj = 0;
   IFactory< std::string,IMultiLayerBuilder > *arg1 = (IFactory< std::string,IMultiLayerBuilder > *) 0 ;
   std::string *arg2 = 0 ;
@@ -100188,30 +100462,30 @@ SWIGINTERN PyObject *_wrap_SampleBuilderFactory_registerItem__SWIG_0(PyObject *S
   PyObject * obj3 = 0 ;
   bool result;
   
-  if (!PyArg_ParseTuple(args,(char *)"OOOO:SampleBuilderFactory_registerItem",&obj0,&obj1,&obj2,&obj3)) SWIG_fail;
+  if (!PyArg_ParseTuple(args,(char *)"OOOO:SampleBuilderFactoryTemp_registerItem",&obj0,&obj1,&obj2,&obj3)) SWIG_fail;
   res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_IFactoryT_std__string_IMultiLayerBuilder_t, 0 |  0 );
   if (!SWIG_IsOK(res1)) {
-    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "SampleBuilderFactory_registerItem" "', argument " "1"" of type '" "IFactory< std::string,IMultiLayerBuilder > *""'"); 
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "SampleBuilderFactoryTemp_registerItem" "', argument " "1"" of type '" "IFactory< std::string,IMultiLayerBuilder > *""'"); 
   }
   arg1 = reinterpret_cast< IFactory< std::string,IMultiLayerBuilder > * >(argp1);
   {
     std::string *ptr = (std::string *)0;
     res2 = SWIG_AsPtr_std_string(obj1, &ptr);
     if (!SWIG_IsOK(res2)) {
-      SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "SampleBuilderFactory_registerItem" "', argument " "2"" of type '" "std::string const &""'"); 
+      SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "SampleBuilderFactoryTemp_registerItem" "', argument " "2"" of type '" "std::string const &""'"); 
     }
     if (!ptr) {
-      SWIG_exception_fail(SWIG_ValueError, "invalid null reference " "in method '" "SampleBuilderFactory_registerItem" "', argument " "2"" of type '" "std::string const &""'"); 
+      SWIG_exception_fail(SWIG_ValueError, "invalid null reference " "in method '" "SampleBuilderFactoryTemp_registerItem" "', argument " "2"" of type '" "std::string const &""'"); 
     }
     arg2 = ptr;
   }
   {
     res3 = SWIG_ConvertPtr(obj2, &argp3, SWIGTYPE_p_std__functionT_IMultiLayerBuilder_pfF_t,  0  | 0);
     if (!SWIG_IsOK(res3)) {
-      SWIG_exception_fail(SWIG_ArgError(res3), "in method '" "SampleBuilderFactory_registerItem" "', argument " "3"" of type '" "IFactory< std::string,IMultiLayerBuilder >::CreateItemCallback""'"); 
+      SWIG_exception_fail(SWIG_ArgError(res3), "in method '" "SampleBuilderFactoryTemp_registerItem" "', argument " "3"" of type '" "IFactory< std::string,IMultiLayerBuilder >::CreateItemCallback""'"); 
     }  
     if (!argp3) {
-      SWIG_exception_fail(SWIG_ValueError, "invalid null reference " "in method '" "SampleBuilderFactory_registerItem" "', argument " "3"" of type '" "IFactory< std::string,IMultiLayerBuilder >::CreateItemCallback""'");
+      SWIG_exception_fail(SWIG_ValueError, "invalid null reference " "in method '" "SampleBuilderFactoryTemp_registerItem" "', argument " "3"" of type '" "IFactory< std::string,IMultiLayerBuilder >::CreateItemCallback""'");
     } else {
       IFactory< std::string,IMultiLayerBuilder >::CreateItemCallback * temp = reinterpret_cast< IFactory< std::string,IMultiLayerBuilder >::CreateItemCallback * >(argp3);
       arg3 = *temp;
@@ -100222,10 +100496,10 @@ SWIGINTERN PyObject *_wrap_SampleBuilderFactory_registerItem__SWIG_0(PyObject *S
     std::string *ptr = (std::string *)0;
     res4 = SWIG_AsPtr_std_string(obj3, &ptr);
     if (!SWIG_IsOK(res4)) {
-      SWIG_exception_fail(SWIG_ArgError(res4), "in method '" "SampleBuilderFactory_registerItem" "', argument " "4"" of type '" "std::string const &""'"); 
+      SWIG_exception_fail(SWIG_ArgError(res4), "in method '" "SampleBuilderFactoryTemp_registerItem" "', argument " "4"" of type '" "std::string const &""'"); 
     }
     if (!ptr) {
-      SWIG_exception_fail(SWIG_ValueError, "invalid null reference " "in method '" "SampleBuilderFactory_registerItem" "', argument " "4"" of type '" "std::string const &""'"); 
+      SWIG_exception_fail(SWIG_ValueError, "invalid null reference " "in method '" "SampleBuilderFactoryTemp_registerItem" "', argument " "4"" of type '" "std::string const &""'"); 
     }
     arg4 = ptr;
   }
@@ -100241,7 +100515,7 @@ fail:
 }
 
 
-SWIGINTERN PyObject *_wrap_SampleBuilderFactory_registerItem__SWIG_1(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+SWIGINTERN PyObject *_wrap_SampleBuilderFactoryTemp_registerItem__SWIG_1(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
   PyObject *resultobj = 0;
   IFactory< std::string,IMultiLayerBuilder > *arg1 = (IFactory< std::string,IMultiLayerBuilder > *) 0 ;
   std::string *arg2 = 0 ;
@@ -100256,30 +100530,30 @@ SWIGINTERN PyObject *_wrap_SampleBuilderFactory_registerItem__SWIG_1(PyObject *S
   PyObject * obj2 = 0 ;
   bool result;
   
-  if (!PyArg_ParseTuple(args,(char *)"OOO:SampleBuilderFactory_registerItem",&obj0,&obj1,&obj2)) SWIG_fail;
+  if (!PyArg_ParseTuple(args,(char *)"OOO:SampleBuilderFactoryTemp_registerItem",&obj0,&obj1,&obj2)) SWIG_fail;
   res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_IFactoryT_std__string_IMultiLayerBuilder_t, 0 |  0 );
   if (!SWIG_IsOK(res1)) {
-    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "SampleBuilderFactory_registerItem" "', argument " "1"" of type '" "IFactory< std::string,IMultiLayerBuilder > *""'"); 
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "SampleBuilderFactoryTemp_registerItem" "', argument " "1"" of type '" "IFactory< std::string,IMultiLayerBuilder > *""'"); 
   }
   arg1 = reinterpret_cast< IFactory< std::string,IMultiLayerBuilder > * >(argp1);
   {
     std::string *ptr = (std::string *)0;
     res2 = SWIG_AsPtr_std_string(obj1, &ptr);
     if (!SWIG_IsOK(res2)) {
-      SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "SampleBuilderFactory_registerItem" "', argument " "2"" of type '" "std::string const &""'"); 
+      SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "SampleBuilderFactoryTemp_registerItem" "', argument " "2"" of type '" "std::string const &""'"); 
     }
     if (!ptr) {
-      SWIG_exception_fail(SWIG_ValueError, "invalid null reference " "in method '" "SampleBuilderFactory_registerItem" "', argument " "2"" of type '" "std::string const &""'"); 
+      SWIG_exception_fail(SWIG_ValueError, "invalid null reference " "in method '" "SampleBuilderFactoryTemp_registerItem" "', argument " "2"" of type '" "std::string const &""'"); 
     }
     arg2 = ptr;
   }
   {
     res3 = SWIG_ConvertPtr(obj2, &argp3, SWIGTYPE_p_std__functionT_IMultiLayerBuilder_pfF_t,  0  | 0);
     if (!SWIG_IsOK(res3)) {
-      SWIG_exception_fail(SWIG_ArgError(res3), "in method '" "SampleBuilderFactory_registerItem" "', argument " "3"" of type '" "IFactory< std::string,IMultiLayerBuilder >::CreateItemCallback""'"); 
+      SWIG_exception_fail(SWIG_ArgError(res3), "in method '" "SampleBuilderFactoryTemp_registerItem" "', argument " "3"" of type '" "IFactory< std::string,IMultiLayerBuilder >::CreateItemCallback""'"); 
     }  
     if (!argp3) {
-      SWIG_exception_fail(SWIG_ValueError, "invalid null reference " "in method '" "SampleBuilderFactory_registerItem" "', argument " "3"" of type '" "IFactory< std::string,IMultiLayerBuilder >::CreateItemCallback""'");
+      SWIG_exception_fail(SWIG_ValueError, "invalid null reference " "in method '" "SampleBuilderFactoryTemp_registerItem" "', argument " "3"" of type '" "IFactory< std::string,IMultiLayerBuilder >::CreateItemCallback""'");
     } else {
       IFactory< std::string,IMultiLayerBuilder >::CreateItemCallback * temp = reinterpret_cast< IFactory< std::string,IMultiLayerBuilder >::CreateItemCallback * >(argp3);
       arg3 = *temp;
@@ -100296,7 +100570,7 @@ fail:
 }
 
 
-SWIGINTERN PyObject *_wrap_SampleBuilderFactory_registerItem(PyObject *self, PyObject *args) {
+SWIGINTERN PyObject *_wrap_SampleBuilderFactoryTemp_registerItem(PyObject *self, PyObject *args) {
   Py_ssize_t argc;
   PyObject *argv[5] = {
     0
@@ -100320,7 +100594,7 @@ SWIGINTERN PyObject *_wrap_SampleBuilderFactory_registerItem(PyObject *self, PyO
         int res = SWIG_ConvertPtr(argv[2], 0, SWIGTYPE_p_std__functionT_IMultiLayerBuilder_pfF_t, 0);
         _v = SWIG_CheckState(res);
         if (_v) {
-          return _wrap_SampleBuilderFactory_registerItem__SWIG_1(self, args);
+          return _wrap_SampleBuilderFactoryTemp_registerItem__SWIG_1(self, args);
         }
       }
     }
@@ -100340,7 +100614,7 @@ SWIGINTERN PyObject *_wrap_SampleBuilderFactory_registerItem(PyObject *self, PyO
           int res = SWIG_AsPtr_std_string(argv[3], (std::string**)(0));
           _v = SWIG_CheckState(res);
           if (_v) {
-            return _wrap_SampleBuilderFactory_registerItem__SWIG_0(self, args);
+            return _wrap_SampleBuilderFactoryTemp_registerItem__SWIG_0(self, args);
           }
         }
       }
@@ -100348,7 +100622,7 @@ SWIGINTERN PyObject *_wrap_SampleBuilderFactory_registerItem(PyObject *self, PyO
   }
   
 fail:
-  SWIG_SetErrorMsg(PyExc_NotImplementedError,"Wrong number or type of arguments for overloaded function 'SampleBuilderFactory_registerItem'.\n"
+  SWIG_SetErrorMsg(PyExc_NotImplementedError,"Wrong number or type of arguments for overloaded function 'SampleBuilderFactoryTemp_registerItem'.\n"
     "  Possible C/C++ prototypes are:\n"
     "    IFactory< std::string,IMultiLayerBuilder >::registerItem(std::string const &,IFactory< std::string,IMultiLayerBuilder >::CreateItemCallback,std::string const &)\n"
     "    IFactory< std::string,IMultiLayerBuilder >::registerItem(std::string const &,IFactory< std::string,IMultiLayerBuilder >::CreateItemCallback)\n");
@@ -100356,17 +100630,17 @@ fail:
 }
 
 
-SWIGINTERN PyObject *_wrap_delete_SampleBuilderFactory(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+SWIGINTERN PyObject *_wrap_delete_SampleBuilderFactoryTemp(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
   PyObject *resultobj = 0;
   IFactory< std::string,IMultiLayerBuilder > *arg1 = (IFactory< std::string,IMultiLayerBuilder > *) 0 ;
   void *argp1 = 0 ;
   int res1 = 0 ;
   PyObject * obj0 = 0 ;
   
-  if (!PyArg_ParseTuple(args,(char *)"O:delete_SampleBuilderFactory",&obj0)) SWIG_fail;
+  if (!PyArg_ParseTuple(args,(char *)"O:delete_SampleBuilderFactoryTemp",&obj0)) SWIG_fail;
   res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_IFactoryT_std__string_IMultiLayerBuilder_t, SWIG_POINTER_DISOWN |  0 );
   if (!SWIG_IsOK(res1)) {
-    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "delete_SampleBuilderFactory" "', argument " "1"" of type '" "IFactory< std::string,IMultiLayerBuilder > *""'"); 
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "delete_SampleBuilderFactoryTemp" "', argument " "1"" of type '" "IFactory< std::string,IMultiLayerBuilder > *""'"); 
   }
   arg1 = reinterpret_cast< IFactory< std::string,IMultiLayerBuilder > * >(argp1);
   delete arg1;
@@ -100377,7 +100651,7 @@ fail:
 }
 
 
-SWIGINTERN PyObject *_wrap_SampleBuilderFactory_getNumberOfRegistered(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+SWIGINTERN PyObject *_wrap_SampleBuilderFactoryTemp_getNumberOfRegistered(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
   PyObject *resultobj = 0;
   IFactory< std::string,IMultiLayerBuilder > *arg1 = (IFactory< std::string,IMultiLayerBuilder > *) 0 ;
   void *argp1 = 0 ;
@@ -100385,10 +100659,10 @@ SWIGINTERN PyObject *_wrap_SampleBuilderFactory_getNumberOfRegistered(PyObject *
   PyObject * obj0 = 0 ;
   size_t result;
   
-  if (!PyArg_ParseTuple(args,(char *)"O:SampleBuilderFactory_getNumberOfRegistered",&obj0)) SWIG_fail;
+  if (!PyArg_ParseTuple(args,(char *)"O:SampleBuilderFactoryTemp_getNumberOfRegistered",&obj0)) SWIG_fail;
   res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_IFactoryT_std__string_IMultiLayerBuilder_t, 0 |  0 );
   if (!SWIG_IsOK(res1)) {
-    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "SampleBuilderFactory_getNumberOfRegistered" "', argument " "1"" of type '" "IFactory< std::string,IMultiLayerBuilder > const *""'"); 
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "SampleBuilderFactoryTemp_getNumberOfRegistered" "', argument " "1"" of type '" "IFactory< std::string,IMultiLayerBuilder > const *""'"); 
   }
   arg1 = reinterpret_cast< IFactory< std::string,IMultiLayerBuilder > * >(argp1);
   result = ((IFactory< std::string,IMultiLayerBuilder > const *)arg1)->getNumberOfRegistered();
@@ -100399,7 +100673,7 @@ fail:
 }
 
 
-SWIGINTERN PyObject *_wrap_SampleBuilderFactory_begin(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+SWIGINTERN PyObject *_wrap_SampleBuilderFactoryTemp_begin(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
   PyObject *resultobj = 0;
   IFactory< std::string,IMultiLayerBuilder > *arg1 = (IFactory< std::string,IMultiLayerBuilder > *) 0 ;
   void *argp1 = 0 ;
@@ -100407,10 +100681,10 @@ SWIGINTERN PyObject *_wrap_SampleBuilderFactory_begin(PyObject *SWIGUNUSEDPARM(s
   PyObject * obj0 = 0 ;
   SwigValueWrapper< std::map< std::string,std::string >::const_iterator > result;
   
-  if (!PyArg_ParseTuple(args,(char *)"O:SampleBuilderFactory_begin",&obj0)) SWIG_fail;
+  if (!PyArg_ParseTuple(args,(char *)"O:SampleBuilderFactoryTemp_begin",&obj0)) SWIG_fail;
   res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_IFactoryT_std__string_IMultiLayerBuilder_t, 0 |  0 );
   if (!SWIG_IsOK(res1)) {
-    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "SampleBuilderFactory_begin" "', argument " "1"" of type '" "IFactory< std::string,IMultiLayerBuilder > const *""'"); 
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "SampleBuilderFactoryTemp_begin" "', argument " "1"" of type '" "IFactory< std::string,IMultiLayerBuilder > const *""'"); 
   }
   arg1 = reinterpret_cast< IFactory< std::string,IMultiLayerBuilder > * >(argp1);
   result = ((IFactory< std::string,IMultiLayerBuilder > const *)arg1)->begin();
@@ -100421,7 +100695,7 @@ fail:
 }
 
 
-SWIGINTERN PyObject *_wrap_SampleBuilderFactory_end(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+SWIGINTERN PyObject *_wrap_SampleBuilderFactoryTemp_end(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
   PyObject *resultobj = 0;
   IFactory< std::string,IMultiLayerBuilder > *arg1 = (IFactory< std::string,IMultiLayerBuilder > *) 0 ;
   void *argp1 = 0 ;
@@ -100429,10 +100703,10 @@ SWIGINTERN PyObject *_wrap_SampleBuilderFactory_end(PyObject *SWIGUNUSEDPARM(sel
   PyObject * obj0 = 0 ;
   SwigValueWrapper< std::map< std::string,std::string >::const_iterator > result;
   
-  if (!PyArg_ParseTuple(args,(char *)"O:SampleBuilderFactory_end",&obj0)) SWIG_fail;
+  if (!PyArg_ParseTuple(args,(char *)"O:SampleBuilderFactoryTemp_end",&obj0)) SWIG_fail;
   res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_IFactoryT_std__string_IMultiLayerBuilder_t, 0 |  0 );
   if (!SWIG_IsOK(res1)) {
-    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "SampleBuilderFactory_end" "', argument " "1"" of type '" "IFactory< std::string,IMultiLayerBuilder > const *""'"); 
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "SampleBuilderFactoryTemp_end" "', argument " "1"" of type '" "IFactory< std::string,IMultiLayerBuilder > const *""'"); 
   }
   arg1 = reinterpret_cast< IFactory< std::string,IMultiLayerBuilder > * >(argp1);
   result = ((IFactory< std::string,IMultiLayerBuilder > const *)arg1)->end();
@@ -100443,18 +100717,97 @@ fail:
 }
 
 
-SWIGINTERN PyObject *SampleBuilderFactory_swigregister(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+SWIGINTERN PyObject *SampleBuilderFactoryTemp_swigregister(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
   PyObject *obj;
   if (!PyArg_ParseTuple(args,(char*)"O:swigregister", &obj)) return NULL;
   SWIG_TypeNewClientData(SWIGTYPE_p_IFactoryT_std__string_IMultiLayerBuilder_t, SWIG_NewClientData(obj));
   return SWIG_Py_Void();
 }
 
-SWIGINTERN PyObject *_wrap_new_SimulationFactory(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+SWIGINTERN PyObject *_wrap_new_SampleBuilderFactory(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *resultobj = 0;
+  SampleBuilderFactory *result = 0 ;
+  
+  if (!PyArg_ParseTuple(args,(char *)":new_SampleBuilderFactory")) SWIG_fail;
+  result = (SampleBuilderFactory *)new SampleBuilderFactory();
+  resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_SampleBuilderFactory, SWIG_POINTER_NEW |  0 );
+  return resultobj;
+fail:
+  return NULL;
+}
+
+
+SWIGINTERN PyObject *_wrap_SampleBuilderFactory_createSample(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *resultobj = 0;
+  SampleBuilderFactory *arg1 = (SampleBuilderFactory *) 0 ;
+  std::string *arg2 = 0 ;
+  void *argp1 = 0 ;
+  int res1 = 0 ;
+  int res2 = SWIG_OLDOBJ ;
+  PyObject * obj0 = 0 ;
+  PyObject * obj1 = 0 ;
+  MultiLayer *result = 0 ;
+  
+  if (!PyArg_ParseTuple(args,(char *)"OO:SampleBuilderFactory_createSample",&obj0,&obj1)) SWIG_fail;
+  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_SampleBuilderFactory, 0 |  0 );
+  if (!SWIG_IsOK(res1)) {
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "SampleBuilderFactory_createSample" "', argument " "1"" of type '" "SampleBuilderFactory *""'"); 
+  }
+  arg1 = reinterpret_cast< SampleBuilderFactory * >(argp1);
+  {
+    std::string *ptr = (std::string *)0;
+    res2 = SWIG_AsPtr_std_string(obj1, &ptr);
+    if (!SWIG_IsOK(res2)) {
+      SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "SampleBuilderFactory_createSample" "', argument " "2"" of type '" "std::string const &""'"); 
+    }
+    if (!ptr) {
+      SWIG_exception_fail(SWIG_ValueError, "invalid null reference " "in method '" "SampleBuilderFactory_createSample" "', argument " "2"" of type '" "std::string const &""'"); 
+    }
+    arg2 = ptr;
+  }
+  result = (MultiLayer *)(arg1)->createSample((std::string const &)*arg2);
+  resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_MultiLayer, 0 |  0 );
+  if (SWIG_IsNewObj(res2)) delete arg2;
+  return resultobj;
+fail:
+  if (SWIG_IsNewObj(res2)) delete arg2;
+  return NULL;
+}
+
+
+SWIGINTERN PyObject *_wrap_delete_SampleBuilderFactory(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *resultobj = 0;
+  SampleBuilderFactory *arg1 = (SampleBuilderFactory *) 0 ;
+  void *argp1 = 0 ;
+  int res1 = 0 ;
+  PyObject * obj0 = 0 ;
+  
+  if (!PyArg_ParseTuple(args,(char *)"O:delete_SampleBuilderFactory",&obj0)) SWIG_fail;
+  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_SampleBuilderFactory, SWIG_POINTER_DISOWN |  0 );
+  if (!SWIG_IsOK(res1)) {
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "delete_SampleBuilderFactory" "', argument " "1"" of type '" "SampleBuilderFactory *""'"); 
+  }
+  arg1 = reinterpret_cast< SampleBuilderFactory * >(argp1);
+  delete arg1;
+  resultobj = SWIG_Py_Void();
+  return resultobj;
+fail:
+  return NULL;
+}
+
+
+SWIGINTERN PyObject *SampleBuilderFactory_swigregister(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *obj;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigregister", &obj)) return NULL;
+  SWIG_TypeNewClientData(SWIGTYPE_p_SampleBuilderFactory, SWIG_NewClientData(obj));
+  return SWIG_Py_Void();
+}
+
+SWIGINTERN PyObject *_wrap_new_SimulationFactoryTemp(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
   PyObject *resultobj = 0;
   IFactory< std::string,GISASSimulation > *result = 0 ;
   
-  if (!PyArg_ParseTuple(args,(char *)":new_SimulationFactory")) SWIG_fail;
+  if (!PyArg_ParseTuple(args,(char *)":new_SimulationFactoryTemp")) SWIG_fail;
   result = (IFactory< std::string,GISASSimulation > *)new IFactory< std::string,GISASSimulation >();
   resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_IFactoryT_std__string_GISASSimulation_t, SWIG_POINTER_NEW |  0 );
   return resultobj;
@@ -100463,7 +100816,7 @@ fail:
 }
 
 
-SWIGINTERN PyObject *_wrap_SimulationFactory_createItem(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+SWIGINTERN PyObject *_wrap_SimulationFactoryTemp_createItem(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
   PyObject *resultobj = 0;
   IFactory< std::string,GISASSimulation > *arg1 = (IFactory< std::string,GISASSimulation > *) 0 ;
   std::string *arg2 = 0 ;
@@ -100474,20 +100827,20 @@ SWIGINTERN PyObject *_wrap_SimulationFactory_createItem(PyObject *SWIGUNUSEDPARM
   PyObject * obj1 = 0 ;
   GISASSimulation *result = 0 ;
   
-  if (!PyArg_ParseTuple(args,(char *)"OO:SimulationFactory_createItem",&obj0,&obj1)) SWIG_fail;
+  if (!PyArg_ParseTuple(args,(char *)"OO:SimulationFactoryTemp_createItem",&obj0,&obj1)) SWIG_fail;
   res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_IFactoryT_std__string_GISASSimulation_t, 0 |  0 );
   if (!SWIG_IsOK(res1)) {
-    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "SimulationFactory_createItem" "', argument " "1"" of type '" "IFactory< std::string,GISASSimulation > *""'"); 
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "SimulationFactoryTemp_createItem" "', argument " "1"" of type '" "IFactory< std::string,GISASSimulation > *""'"); 
   }
   arg1 = reinterpret_cast< IFactory< std::string,GISASSimulation > * >(argp1);
   {
     std::string *ptr = (std::string *)0;
     res2 = SWIG_AsPtr_std_string(obj1, &ptr);
     if (!SWIG_IsOK(res2)) {
-      SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "SimulationFactory_createItem" "', argument " "2"" of type '" "std::string const &""'"); 
+      SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "SimulationFactoryTemp_createItem" "', argument " "2"" of type '" "std::string const &""'"); 
     }
     if (!ptr) {
-      SWIG_exception_fail(SWIG_ValueError, "invalid null reference " "in method '" "SimulationFactory_createItem" "', argument " "2"" of type '" "std::string const &""'"); 
+      SWIG_exception_fail(SWIG_ValueError, "invalid null reference " "in method '" "SimulationFactoryTemp_createItem" "', argument " "2"" of type '" "std::string const &""'"); 
     }
     arg2 = ptr;
   }
@@ -100501,7 +100854,7 @@ fail:
 }
 
 
-SWIGINTERN PyObject *_wrap_SimulationFactory_registerItem__SWIG_0(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+SWIGINTERN PyObject *_wrap_SimulationFactoryTemp_registerItem__SWIG_0(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
   PyObject *resultobj = 0;
   IFactory< std::string,GISASSimulation > *arg1 = (IFactory< std::string,GISASSimulation > *) 0 ;
   std::string *arg2 = 0 ;
@@ -100519,30 +100872,30 @@ SWIGINTERN PyObject *_wrap_SimulationFactory_registerItem__SWIG_0(PyObject *SWIG
   PyObject * obj3 = 0 ;
   bool result;
   
-  if (!PyArg_ParseTuple(args,(char *)"OOOO:SimulationFactory_registerItem",&obj0,&obj1,&obj2,&obj3)) SWIG_fail;
+  if (!PyArg_ParseTuple(args,(char *)"OOOO:SimulationFactoryTemp_registerItem",&obj0,&obj1,&obj2,&obj3)) SWIG_fail;
   res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_IFactoryT_std__string_GISASSimulation_t, 0 |  0 );
   if (!SWIG_IsOK(res1)) {
-    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "SimulationFactory_registerItem" "', argument " "1"" of type '" "IFactory< std::string,GISASSimulation > *""'"); 
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "SimulationFactoryTemp_registerItem" "', argument " "1"" of type '" "IFactory< std::string,GISASSimulation > *""'"); 
   }
   arg1 = reinterpret_cast< IFactory< std::string,GISASSimulation > * >(argp1);
   {
     std::string *ptr = (std::string *)0;
     res2 = SWIG_AsPtr_std_string(obj1, &ptr);
     if (!SWIG_IsOK(res2)) {
-      SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "SimulationFactory_registerItem" "', argument " "2"" of type '" "std::string const &""'"); 
+      SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "SimulationFactoryTemp_registerItem" "', argument " "2"" of type '" "std::string const &""'"); 
     }
     if (!ptr) {
-      SWIG_exception_fail(SWIG_ValueError, "invalid null reference " "in method '" "SimulationFactory_registerItem" "', argument " "2"" of type '" "std::string const &""'"); 
+      SWIG_exception_fail(SWIG_ValueError, "invalid null reference " "in method '" "SimulationFactoryTemp_registerItem" "', argument " "2"" of type '" "std::string const &""'"); 
     }
     arg2 = ptr;
   }
   {
     res3 = SWIG_ConvertPtr(obj2, &argp3, SWIGTYPE_p_std__functionT_GISASSimulation_pfF_t,  0  | 0);
     if (!SWIG_IsOK(res3)) {
-      SWIG_exception_fail(SWIG_ArgError(res3), "in method '" "SimulationFactory_registerItem" "', argument " "3"" of type '" "IFactory< std::string,GISASSimulation >::CreateItemCallback""'"); 
+      SWIG_exception_fail(SWIG_ArgError(res3), "in method '" "SimulationFactoryTemp_registerItem" "', argument " "3"" of type '" "IFactory< std::string,GISASSimulation >::CreateItemCallback""'"); 
     }  
     if (!argp3) {
-      SWIG_exception_fail(SWIG_ValueError, "invalid null reference " "in method '" "SimulationFactory_registerItem" "', argument " "3"" of type '" "IFactory< std::string,GISASSimulation >::CreateItemCallback""'");
+      SWIG_exception_fail(SWIG_ValueError, "invalid null reference " "in method '" "SimulationFactoryTemp_registerItem" "', argument " "3"" of type '" "IFactory< std::string,GISASSimulation >::CreateItemCallback""'");
     } else {
       IFactory< std::string,GISASSimulation >::CreateItemCallback * temp = reinterpret_cast< IFactory< std::string,GISASSimulation >::CreateItemCallback * >(argp3);
       arg3 = *temp;
@@ -100553,10 +100906,10 @@ SWIGINTERN PyObject *_wrap_SimulationFactory_registerItem__SWIG_0(PyObject *SWIG
     std::string *ptr = (std::string *)0;
     res4 = SWIG_AsPtr_std_string(obj3, &ptr);
     if (!SWIG_IsOK(res4)) {
-      SWIG_exception_fail(SWIG_ArgError(res4), "in method '" "SimulationFactory_registerItem" "', argument " "4"" of type '" "std::string const &""'"); 
+      SWIG_exception_fail(SWIG_ArgError(res4), "in method '" "SimulationFactoryTemp_registerItem" "', argument " "4"" of type '" "std::string const &""'"); 
     }
     if (!ptr) {
-      SWIG_exception_fail(SWIG_ValueError, "invalid null reference " "in method '" "SimulationFactory_registerItem" "', argument " "4"" of type '" "std::string const &""'"); 
+      SWIG_exception_fail(SWIG_ValueError, "invalid null reference " "in method '" "SimulationFactoryTemp_registerItem" "', argument " "4"" of type '" "std::string const &""'"); 
     }
     arg4 = ptr;
   }
@@ -100572,7 +100925,7 @@ fail:
 }
 
 
-SWIGINTERN PyObject *_wrap_SimulationFactory_registerItem__SWIG_1(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+SWIGINTERN PyObject *_wrap_SimulationFactoryTemp_registerItem__SWIG_1(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
   PyObject *resultobj = 0;
   IFactory< std::string,GISASSimulation > *arg1 = (IFactory< std::string,GISASSimulation > *) 0 ;
   std::string *arg2 = 0 ;
@@ -100587,30 +100940,30 @@ SWIGINTERN PyObject *_wrap_SimulationFactory_registerItem__SWIG_1(PyObject *SWIG
   PyObject * obj2 = 0 ;
   bool result;
   
-  if (!PyArg_ParseTuple(args,(char *)"OOO:SimulationFactory_registerItem",&obj0,&obj1,&obj2)) SWIG_fail;
+  if (!PyArg_ParseTuple(args,(char *)"OOO:SimulationFactoryTemp_registerItem",&obj0,&obj1,&obj2)) SWIG_fail;
   res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_IFactoryT_std__string_GISASSimulation_t, 0 |  0 );
   if (!SWIG_IsOK(res1)) {
-    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "SimulationFactory_registerItem" "', argument " "1"" of type '" "IFactory< std::string,GISASSimulation > *""'"); 
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "SimulationFactoryTemp_registerItem" "', argument " "1"" of type '" "IFactory< std::string,GISASSimulation > *""'"); 
   }
   arg1 = reinterpret_cast< IFactory< std::string,GISASSimulation > * >(argp1);
   {
     std::string *ptr = (std::string *)0;
     res2 = SWIG_AsPtr_std_string(obj1, &ptr);
     if (!SWIG_IsOK(res2)) {
-      SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "SimulationFactory_registerItem" "', argument " "2"" of type '" "std::string const &""'"); 
+      SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "SimulationFactoryTemp_registerItem" "', argument " "2"" of type '" "std::string const &""'"); 
     }
     if (!ptr) {
-      SWIG_exception_fail(SWIG_ValueError, "invalid null reference " "in method '" "SimulationFactory_registerItem" "', argument " "2"" of type '" "std::string const &""'"); 
+      SWIG_exception_fail(SWIG_ValueError, "invalid null reference " "in method '" "SimulationFactoryTemp_registerItem" "', argument " "2"" of type '" "std::string const &""'"); 
     }
     arg2 = ptr;
   }
   {
     res3 = SWIG_ConvertPtr(obj2, &argp3, SWIGTYPE_p_std__functionT_GISASSimulation_pfF_t,  0  | 0);
     if (!SWIG_IsOK(res3)) {
-      SWIG_exception_fail(SWIG_ArgError(res3), "in method '" "SimulationFactory_registerItem" "', argument " "3"" of type '" "IFactory< std::string,GISASSimulation >::CreateItemCallback""'"); 
+      SWIG_exception_fail(SWIG_ArgError(res3), "in method '" "SimulationFactoryTemp_registerItem" "', argument " "3"" of type '" "IFactory< std::string,GISASSimulation >::CreateItemCallback""'"); 
     }  
     if (!argp3) {
-      SWIG_exception_fail(SWIG_ValueError, "invalid null reference " "in method '" "SimulationFactory_registerItem" "', argument " "3"" of type '" "IFactory< std::string,GISASSimulation >::CreateItemCallback""'");
+      SWIG_exception_fail(SWIG_ValueError, "invalid null reference " "in method '" "SimulationFactoryTemp_registerItem" "', argument " "3"" of type '" "IFactory< std::string,GISASSimulation >::CreateItemCallback""'");
     } else {
       IFactory< std::string,GISASSimulation >::CreateItemCallback * temp = reinterpret_cast< IFactory< std::string,GISASSimulation >::CreateItemCallback * >(argp3);
       arg3 = *temp;
@@ -100627,7 +100980,7 @@ fail:
 }
 
 
-SWIGINTERN PyObject *_wrap_SimulationFactory_registerItem(PyObject *self, PyObject *args) {
+SWIGINTERN PyObject *_wrap_SimulationFactoryTemp_registerItem(PyObject *self, PyObject *args) {
   Py_ssize_t argc;
   PyObject *argv[5] = {
     0
@@ -100651,7 +101004,7 @@ SWIGINTERN PyObject *_wrap_SimulationFactory_registerItem(PyObject *self, PyObje
         int res = SWIG_ConvertPtr(argv[2], 0, SWIGTYPE_p_std__functionT_GISASSimulation_pfF_t, 0);
         _v = SWIG_CheckState(res);
         if (_v) {
-          return _wrap_SimulationFactory_registerItem__SWIG_1(self, args);
+          return _wrap_SimulationFactoryTemp_registerItem__SWIG_1(self, args);
         }
       }
     }
@@ -100671,7 +101024,7 @@ SWIGINTERN PyObject *_wrap_SimulationFactory_registerItem(PyObject *self, PyObje
           int res = SWIG_AsPtr_std_string(argv[3], (std::string**)(0));
           _v = SWIG_CheckState(res);
           if (_v) {
-            return _wrap_SimulationFactory_registerItem__SWIG_0(self, args);
+            return _wrap_SimulationFactoryTemp_registerItem__SWIG_0(self, args);
           }
         }
       }
@@ -100679,7 +101032,7 @@ SWIGINTERN PyObject *_wrap_SimulationFactory_registerItem(PyObject *self, PyObje
   }
   
 fail:
-  SWIG_SetErrorMsg(PyExc_NotImplementedError,"Wrong number or type of arguments for overloaded function 'SimulationFactory_registerItem'.\n"
+  SWIG_SetErrorMsg(PyExc_NotImplementedError,"Wrong number or type of arguments for overloaded function 'SimulationFactoryTemp_registerItem'.\n"
     "  Possible C/C++ prototypes are:\n"
     "    IFactory< std::string,GISASSimulation >::registerItem(std::string const &,IFactory< std::string,GISASSimulation >::CreateItemCallback,std::string const &)\n"
     "    IFactory< std::string,GISASSimulation >::registerItem(std::string const &,IFactory< std::string,GISASSimulation >::CreateItemCallback)\n");
@@ -100687,17 +101040,17 @@ fail:
 }
 
 
-SWIGINTERN PyObject *_wrap_delete_SimulationFactory(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+SWIGINTERN PyObject *_wrap_delete_SimulationFactoryTemp(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
   PyObject *resultobj = 0;
   IFactory< std::string,GISASSimulation > *arg1 = (IFactory< std::string,GISASSimulation > *) 0 ;
   void *argp1 = 0 ;
   int res1 = 0 ;
   PyObject * obj0 = 0 ;
   
-  if (!PyArg_ParseTuple(args,(char *)"O:delete_SimulationFactory",&obj0)) SWIG_fail;
+  if (!PyArg_ParseTuple(args,(char *)"O:delete_SimulationFactoryTemp",&obj0)) SWIG_fail;
   res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_IFactoryT_std__string_GISASSimulation_t, SWIG_POINTER_DISOWN |  0 );
   if (!SWIG_IsOK(res1)) {
-    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "delete_SimulationFactory" "', argument " "1"" of type '" "IFactory< std::string,GISASSimulation > *""'"); 
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "delete_SimulationFactoryTemp" "', argument " "1"" of type '" "IFactory< std::string,GISASSimulation > *""'"); 
   }
   arg1 = reinterpret_cast< IFactory< std::string,GISASSimulation > * >(argp1);
   delete arg1;
@@ -100708,7 +101061,7 @@ fail:
 }
 
 
-SWIGINTERN PyObject *_wrap_SimulationFactory_getNumberOfRegistered(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+SWIGINTERN PyObject *_wrap_SimulationFactoryTemp_getNumberOfRegistered(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
   PyObject *resultobj = 0;
   IFactory< std::string,GISASSimulation > *arg1 = (IFactory< std::string,GISASSimulation > *) 0 ;
   void *argp1 = 0 ;
@@ -100716,10 +101069,10 @@ SWIGINTERN PyObject *_wrap_SimulationFactory_getNumberOfRegistered(PyObject *SWI
   PyObject * obj0 = 0 ;
   size_t result;
   
-  if (!PyArg_ParseTuple(args,(char *)"O:SimulationFactory_getNumberOfRegistered",&obj0)) SWIG_fail;
+  if (!PyArg_ParseTuple(args,(char *)"O:SimulationFactoryTemp_getNumberOfRegistered",&obj0)) SWIG_fail;
   res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_IFactoryT_std__string_GISASSimulation_t, 0 |  0 );
   if (!SWIG_IsOK(res1)) {
-    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "SimulationFactory_getNumberOfRegistered" "', argument " "1"" of type '" "IFactory< std::string,GISASSimulation > const *""'"); 
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "SimulationFactoryTemp_getNumberOfRegistered" "', argument " "1"" of type '" "IFactory< std::string,GISASSimulation > const *""'"); 
   }
   arg1 = reinterpret_cast< IFactory< std::string,GISASSimulation > * >(argp1);
   result = ((IFactory< std::string,GISASSimulation > const *)arg1)->getNumberOfRegistered();
@@ -100730,7 +101083,7 @@ fail:
 }
 
 
-SWIGINTERN PyObject *_wrap_SimulationFactory_begin(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+SWIGINTERN PyObject *_wrap_SimulationFactoryTemp_begin(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
   PyObject *resultobj = 0;
   IFactory< std::string,GISASSimulation > *arg1 = (IFactory< std::string,GISASSimulation > *) 0 ;
   void *argp1 = 0 ;
@@ -100738,10 +101091,10 @@ SWIGINTERN PyObject *_wrap_SimulationFactory_begin(PyObject *SWIGUNUSEDPARM(self
   PyObject * obj0 = 0 ;
   SwigValueWrapper< std::map< std::string,std::string >::const_iterator > result;
   
-  if (!PyArg_ParseTuple(args,(char *)"O:SimulationFactory_begin",&obj0)) SWIG_fail;
+  if (!PyArg_ParseTuple(args,(char *)"O:SimulationFactoryTemp_begin",&obj0)) SWIG_fail;
   res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_IFactoryT_std__string_GISASSimulation_t, 0 |  0 );
   if (!SWIG_IsOK(res1)) {
-    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "SimulationFactory_begin" "', argument " "1"" of type '" "IFactory< std::string,GISASSimulation > const *""'"); 
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "SimulationFactoryTemp_begin" "', argument " "1"" of type '" "IFactory< std::string,GISASSimulation > const *""'"); 
   }
   arg1 = reinterpret_cast< IFactory< std::string,GISASSimulation > * >(argp1);
   result = ((IFactory< std::string,GISASSimulation > const *)arg1)->begin();
@@ -100752,7 +101105,7 @@ fail:
 }
 
 
-SWIGINTERN PyObject *_wrap_SimulationFactory_end(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+SWIGINTERN PyObject *_wrap_SimulationFactoryTemp_end(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
   PyObject *resultobj = 0;
   IFactory< std::string,GISASSimulation > *arg1 = (IFactory< std::string,GISASSimulation > *) 0 ;
   void *argp1 = 0 ;
@@ -100760,10 +101113,10 @@ SWIGINTERN PyObject *_wrap_SimulationFactory_end(PyObject *SWIGUNUSEDPARM(self),
   PyObject * obj0 = 0 ;
   SwigValueWrapper< std::map< std::string,std::string >::const_iterator > result;
   
-  if (!PyArg_ParseTuple(args,(char *)"O:SimulationFactory_end",&obj0)) SWIG_fail;
+  if (!PyArg_ParseTuple(args,(char *)"O:SimulationFactoryTemp_end",&obj0)) SWIG_fail;
   res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_IFactoryT_std__string_GISASSimulation_t, 0 |  0 );
   if (!SWIG_IsOK(res1)) {
-    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "SimulationFactory_end" "', argument " "1"" of type '" "IFactory< std::string,GISASSimulation > const *""'"); 
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "SimulationFactoryTemp_end" "', argument " "1"" of type '" "IFactory< std::string,GISASSimulation > const *""'"); 
   }
   arg1 = reinterpret_cast< IFactory< std::string,GISASSimulation > * >(argp1);
   result = ((IFactory< std::string,GISASSimulation > const *)arg1)->end();
@@ -100774,13 +101127,54 @@ fail:
 }
 
 
-SWIGINTERN PyObject *SimulationFactory_swigregister(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+SWIGINTERN PyObject *SimulationFactoryTemp_swigregister(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
   PyObject *obj;
   if (!PyArg_ParseTuple(args,(char*)"O:swigregister", &obj)) return NULL;
   SWIG_TypeNewClientData(SWIGTYPE_p_IFactoryT_std__string_GISASSimulation_t, SWIG_NewClientData(obj));
   return SWIG_Py_Void();
 }
 
+SWIGINTERN PyObject *_wrap_new_SimulationFactory(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *resultobj = 0;
+  SimulationFactory *result = 0 ;
+  
+  if (!PyArg_ParseTuple(args,(char *)":new_SimulationFactory")) SWIG_fail;
+  result = (SimulationFactory *)new SimulationFactory();
+  resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_SimulationFactory, SWIG_POINTER_NEW |  0 );
+  return resultobj;
+fail:
+  return NULL;
+}
+
+
+SWIGINTERN PyObject *_wrap_delete_SimulationFactory(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *resultobj = 0;
+  SimulationFactory *arg1 = (SimulationFactory *) 0 ;
+  void *argp1 = 0 ;
+  int res1 = 0 ;
+  PyObject * obj0 = 0 ;
+  
+  if (!PyArg_ParseTuple(args,(char *)"O:delete_SimulationFactory",&obj0)) SWIG_fail;
+  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_SimulationFactory, SWIG_POINTER_DISOWN |  0 );
+  if (!SWIG_IsOK(res1)) {
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "delete_SimulationFactory" "', argument " "1"" of type '" "SimulationFactory *""'"); 
+  }
+  arg1 = reinterpret_cast< SimulationFactory * >(argp1);
+  delete arg1;
+  resultobj = SWIG_Py_Void();
+  return resultobj;
+fail:
+  return NULL;
+}
+
+
+SWIGINTERN PyObject *SimulationFactory_swigregister(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *obj;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigregister", &obj)) return NULL;
+  SWIG_TypeNewClientData(SWIGTYPE_p_SimulationFactory, SWIG_NewClientData(obj));
+  return SWIG_Py_Void();
+}
+
 static PyMethodDef SwigMethods[] = {
 	 { (char *)"SWIG_PyInstanceMethod_New", (PyCFunction)SWIG_PyInstanceMethod_New, METH_O, NULL},
 	 { (char *)"delete_SwigPyIterator", _wrap_delete_SwigPyIterator, METH_VARARGS, (char *)"delete_SwigPyIterator(SwigPyIterator self)"},
@@ -109174,14 +109568,19 @@ static PyMethodDef SwigMethods[] = {
 		"return true if has masks \n"
 		"\n"
 		""},
+	 { (char *)"IDetector2D_getDetectorIntensity", _wrap_IDetector2D_getDetectorIntensity, METH_VARARGS, (char *)"\n"
+		"getDetectorIntensity(IntensityData data, Beam beam, IDetector2D::EAxesUnits units_type) -> IntensityData\n"
+		"IDetector2D_getDetectorIntensity(IDetector2D self, IntensityData data, Beam beam) -> IntensityData\n"
+		""},
 	 { (char *)"IDetector2D_createDetectorMap", _wrap_IDetector2D_createDetectorMap, METH_VARARGS, (char *)"\n"
-		"IDetector2D_createDetectorMap(IDetector2D self, Beam arg3, IDetector2D::EAxesUnits arg4) -> IntensityData\n"
+		"IDetector2D_createDetectorMap(IDetector2D self, Beam beam, IDetector2D::EAxesUnits units) -> IntensityData\n"
 		"\n"
 		"OutputData< double > * IDetector2D::createDetectorMap(const Beam &, EAxesUnits) const\n"
 		"\n"
 		"Returns detector map in given axes units. \n"
 		"\n"
 		""},
+	 { (char *)"IDetector2D_initOutputData", _wrap_IDetector2D_initOutputData, METH_VARARGS, (char *)"IDetector2D_initOutputData(IDetector2D self, IntensityData data)"},
 	 { (char *)"IDetector2D_getValidAxesUnits", _wrap_IDetector2D_getValidAxesUnits, METH_VARARGS, (char *)"\n"
 		"IDetector2D_getValidAxesUnits(IDetector2D self) -> std::vector< IDetector2D::EAxesUnits,std::allocator< IDetector2D::EAxesUnits > >\n"
 		"\n"
@@ -109198,6 +109597,11 @@ static PyMethodDef SwigMethods[] = {
 		"return default axes units \n"
 		"\n"
 		""},
+	 { (char *)"IDetector2D_regionOfInterest", _wrap_IDetector2D_regionOfInterest, METH_VARARGS, (char *)"IDetector2D_regionOfInterest(IDetector2D self) -> Rectangle"},
+	 { (char *)"IDetector2D_setRegionOfInterest", _wrap_IDetector2D_setRegionOfInterest, METH_VARARGS, (char *)"IDetector2D_setRegionOfInterest(IDetector2D self, double xlow, double ylow, double xup, double yup)"},
+	 { (char *)"IDetector2D_resetRegionOfInterest", _wrap_IDetector2D_resetRegionOfInterest, METH_VARARGS, (char *)"IDetector2D_resetRegionOfInterest(IDetector2D self)"},
+	 { (char *)"IDetector2D_getTotalSize", _wrap_IDetector2D_getTotalSize, METH_VARARGS, (char *)"IDetector2D_getTotalSize(IDetector2D self) -> size_t"},
+	 { (char *)"IDetector2D_getAxisBinIndex", _wrap_IDetector2D_getAxisBinIndex, METH_VARARGS, (char *)"IDetector2D_getAxisBinIndex(IDetector2D self, size_t index, size_t selected_axis) -> size_t"},
 	 { (char *)"IDetector2D_swigregister", IDetector2D_swigregister, METH_VARARGS, NULL},
 	 { (char *)"delete_IDetectorResolution", _wrap_delete_IDetectorResolution, METH_VARARGS, (char *)"\n"
 		"delete_IDetectorResolution(IDetectorResolution self)\n"
@@ -110593,14 +110997,6 @@ static PyMethodDef SwigMethods[] = {
 		"SphericalDetector::~SphericalDetector() override\n"
 		"\n"
 		""},
-	 { (char *)"SphericalDetector_createDetectorMap", _wrap_SphericalDetector_createDetectorMap, METH_VARARGS, (char *)"\n"
-		"SphericalDetector_createDetectorMap(SphericalDetector self, Beam beam, IDetector2D::EAxesUnits units_type) -> IntensityData\n"
-		"\n"
-		"OutputData< double > * SphericalDetector::createDetectorMap(const Beam &beam, EAxesUnits units_type) const override\n"
-		"\n"
-		"Returns detector map in given axes units. \n"
-		"\n"
-		""},
 	 { (char *)"SphericalDetector_getValidAxesUnits", _wrap_SphericalDetector_getValidAxesUnits, METH_VARARGS, (char *)"\n"
 		"SphericalDetector_getValidAxesUnits(SphericalDetector self) -> std::vector< IDetector2D::EAxesUnits,std::allocator< IDetector2D::EAxesUnits > >\n"
 		"\n"
@@ -113023,14 +113419,6 @@ static PyMethodDef SwigMethods[] = {
 		"RectangularDetector::EDetectorArrangement RectangularDetector::getDetectorArrangment() const \n"
 		"\n"
 		""},
-	 { (char *)"RectangularDetector_createDetectorMap", _wrap_RectangularDetector_createDetectorMap, METH_VARARGS, (char *)"\n"
-		"RectangularDetector_createDetectorMap(RectangularDetector self, Beam beam, IDetector2D::EAxesUnits units_type) -> IntensityData\n"
-		"\n"
-		"OutputData< double > * RectangularDetector::createDetectorMap(const Beam &beam, EAxesUnits units_type) const override\n"
-		"\n"
-		"Returns detector map in given axes units. \n"
-		"\n"
-		""},
 	 { (char *)"RectangularDetector_getValidAxesUnits", _wrap_RectangularDetector_getValidAxesUnits, METH_VARARGS, (char *)"\n"
 		"RectangularDetector_getValidAxesUnits(RectangularDetector self) -> std::vector< IDetector2D::EAxesUnits,std::allocator< IDetector2D::EAxesUnits > >\n"
 		"\n"
@@ -113260,105 +113648,129 @@ static PyMethodDef SwigMethods[] = {
 	 { (char *)"ThreadInfo_current_batch_get", _wrap_ThreadInfo_current_batch_get, METH_VARARGS, (char *)"ThreadInfo_current_batch_get(ThreadInfo self) -> int"},
 	 { (char *)"delete_ThreadInfo", _wrap_delete_ThreadInfo, METH_VARARGS, (char *)"delete_ThreadInfo(ThreadInfo self)"},
 	 { (char *)"ThreadInfo_swigregister", ThreadInfo_swigregister, METH_VARARGS, NULL},
-	 { (char *)"new_SampleBuilderFactory", _wrap_new_SampleBuilderFactory, METH_VARARGS, (char *)"\n"
-		"new_SampleBuilderFactory() -> SampleBuilderFactory\n"
+	 { (char *)"new_SampleBuilderFactoryTemp", _wrap_new_SampleBuilderFactoryTemp, METH_VARARGS, (char *)"\n"
+		"new_SampleBuilderFactoryTemp() -> SampleBuilderFactoryTemp\n"
 		"\n"
 		"IFactory< Key, AbstractProduct >::IFactory()\n"
 		"\n"
 		""},
-	 { (char *)"SampleBuilderFactory_createItem", _wrap_SampleBuilderFactory_createItem, METH_VARARGS, (char *)"\n"
-		"SampleBuilderFactory_createItem(SampleBuilderFactory self, std::string const & item_key) -> IMultiLayerBuilder\n"
+	 { (char *)"SampleBuilderFactoryTemp_createItem", _wrap_SampleBuilderFactoryTemp_createItem, METH_VARARGS, (char *)"\n"
+		"SampleBuilderFactoryTemp_createItem(SampleBuilderFactoryTemp self, std::string const & item_key) -> IMultiLayerBuilder\n"
 		"\n"
 		"AbstractProduct* IFactory< Key, AbstractProduct >::createItem(const Key &item_key)\n"
 		"\n"
 		"Creates object by calling creation function corresponded to given identifier. \n"
 		"\n"
 		""},
-	 { (char *)"SampleBuilderFactory_registerItem", _wrap_SampleBuilderFactory_registerItem, METH_VARARGS, (char *)"\n"
+	 { (char *)"SampleBuilderFactoryTemp_registerItem", _wrap_SampleBuilderFactoryTemp_registerItem, METH_VARARGS, (char *)"\n"
 		"registerItem(std::string const & item_key, IFactory< std::string,IMultiLayerBuilder >::CreateItemCallback CreateFn, std::string const & itemDescription) -> bool\n"
-		"SampleBuilderFactory_registerItem(SampleBuilderFactory self, std::string const & item_key, IFactory< std::string,IMultiLayerBuilder >::CreateItemCallback CreateFn) -> bool\n"
+		"SampleBuilderFactoryTemp_registerItem(SampleBuilderFactoryTemp self, std::string const & item_key, IFactory< std::string,IMultiLayerBuilder >::CreateItemCallback CreateFn) -> bool\n"
 		"\n"
 		"bool IFactory< Key, AbstractProduct >::registerItem(const Key &item_key, CreateItemCallback CreateFn, const std::string &itemDescription=\"\")\n"
 		"\n"
 		"Registers object's creation function and store object description. \n"
 		"\n"
 		""},
-	 { (char *)"delete_SampleBuilderFactory", _wrap_delete_SampleBuilderFactory, METH_VARARGS, (char *)"\n"
-		"delete_SampleBuilderFactory(SampleBuilderFactory self)\n"
+	 { (char *)"delete_SampleBuilderFactoryTemp", _wrap_delete_SampleBuilderFactoryTemp, METH_VARARGS, (char *)"\n"
+		"delete_SampleBuilderFactoryTemp(SampleBuilderFactoryTemp self)\n"
 		"\n"
 		"IFactory< Key, AbstractProduct >::~IFactory()\n"
 		"\n"
 		""},
-	 { (char *)"SampleBuilderFactory_getNumberOfRegistered", _wrap_SampleBuilderFactory_getNumberOfRegistered, METH_VARARGS, (char *)"\n"
-		"SampleBuilderFactory_getNumberOfRegistered(SampleBuilderFactory self) -> size_t\n"
+	 { (char *)"SampleBuilderFactoryTemp_getNumberOfRegistered", _wrap_SampleBuilderFactoryTemp_getNumberOfRegistered, METH_VARARGS, (char *)"\n"
+		"SampleBuilderFactoryTemp_getNumberOfRegistered(SampleBuilderFactoryTemp self) -> size_t\n"
 		"\n"
 		"size_t IFactory< Key, AbstractProduct >::getNumberOfRegistered() const\n"
 		"\n"
 		"Returns number of registered objects. \n"
 		"\n"
 		""},
-	 { (char *)"SampleBuilderFactory_begin", _wrap_SampleBuilderFactory_begin, METH_VARARGS, (char *)"\n"
-		"SampleBuilderFactory_begin(SampleBuilderFactory self) -> IFactory< std::string,IMultiLayerBuilder >::const_iterator\n"
+	 { (char *)"SampleBuilderFactoryTemp_begin", _wrap_SampleBuilderFactoryTemp_begin, METH_VARARGS, (char *)"\n"
+		"SampleBuilderFactoryTemp_begin(SampleBuilderFactoryTemp self) -> IFactory< std::string,IMultiLayerBuilder >::const_iterator\n"
 		"\n"
 		"const_iterator IFactory< Key, AbstractProduct >::begin() const \n"
 		"\n"
 		""},
-	 { (char *)"SampleBuilderFactory_end", _wrap_SampleBuilderFactory_end, METH_VARARGS, (char *)"\n"
-		"SampleBuilderFactory_end(SampleBuilderFactory self) -> IFactory< std::string,IMultiLayerBuilder >::const_iterator\n"
+	 { (char *)"SampleBuilderFactoryTemp_end", _wrap_SampleBuilderFactoryTemp_end, METH_VARARGS, (char *)"\n"
+		"SampleBuilderFactoryTemp_end(SampleBuilderFactoryTemp self) -> IFactory< std::string,IMultiLayerBuilder >::const_iterator\n"
 		"\n"
 		"const_iterator IFactory< Key, AbstractProduct >::end() const \n"
 		"\n"
 		""},
+	 { (char *)"SampleBuilderFactoryTemp_swigregister", SampleBuilderFactoryTemp_swigregister, METH_VARARGS, NULL},
+	 { (char *)"new_SampleBuilderFactory", _wrap_new_SampleBuilderFactory, METH_VARARGS, (char *)"\n"
+		"new_SampleBuilderFactory() -> SampleBuilderFactory\n"
+		"\n"
+		"SampleBuilderFactory::SampleBuilderFactory()\n"
+		"\n"
+		""},
+	 { (char *)"SampleBuilderFactory_createSample", _wrap_SampleBuilderFactory_createSample, METH_VARARGS, (char *)"\n"
+		"SampleBuilderFactory_createSample(SampleBuilderFactory self, std::string const & name) -> MultiLayer\n"
+		"\n"
+		"MultiLayer * SampleBuilderFactory::createSample(const std::string &name)\n"
+		"\n"
+		"Retrieves a SampleBuilder from the registry, does the build, and returns the result. \n"
+		"\n"
+		""},
+	 { (char *)"delete_SampleBuilderFactory", _wrap_delete_SampleBuilderFactory, METH_VARARGS, (char *)"delete_SampleBuilderFactory(SampleBuilderFactory self)"},
 	 { (char *)"SampleBuilderFactory_swigregister", SampleBuilderFactory_swigregister, METH_VARARGS, NULL},
-	 { (char *)"new_SimulationFactory", _wrap_new_SimulationFactory, METH_VARARGS, (char *)"\n"
-		"new_SimulationFactory() -> SimulationFactory\n"
+	 { (char *)"new_SimulationFactoryTemp", _wrap_new_SimulationFactoryTemp, METH_VARARGS, (char *)"\n"
+		"new_SimulationFactoryTemp() -> SimulationFactoryTemp\n"
 		"\n"
 		"IFactory< Key, AbstractProduct >::IFactory()\n"
 		"\n"
 		""},
-	 { (char *)"SimulationFactory_createItem", _wrap_SimulationFactory_createItem, METH_VARARGS, (char *)"\n"
-		"SimulationFactory_createItem(SimulationFactory self, std::string const & item_key) -> GISASSimulation\n"
+	 { (char *)"SimulationFactoryTemp_createItem", _wrap_SimulationFactoryTemp_createItem, METH_VARARGS, (char *)"\n"
+		"SimulationFactoryTemp_createItem(SimulationFactoryTemp self, std::string const & item_key) -> GISASSimulation\n"
 		"\n"
 		"AbstractProduct* IFactory< Key, AbstractProduct >::createItem(const Key &item_key)\n"
 		"\n"
 		"Creates object by calling creation function corresponded to given identifier. \n"
 		"\n"
 		""},
-	 { (char *)"SimulationFactory_registerItem", _wrap_SimulationFactory_registerItem, METH_VARARGS, (char *)"\n"
+	 { (char *)"SimulationFactoryTemp_registerItem", _wrap_SimulationFactoryTemp_registerItem, METH_VARARGS, (char *)"\n"
 		"registerItem(std::string const & item_key, IFactory< std::string,GISASSimulation >::CreateItemCallback CreateFn, std::string const & itemDescription) -> bool\n"
-		"SimulationFactory_registerItem(SimulationFactory self, std::string const & item_key, IFactory< std::string,GISASSimulation >::CreateItemCallback CreateFn) -> bool\n"
+		"SimulationFactoryTemp_registerItem(SimulationFactoryTemp self, std::string const & item_key, IFactory< std::string,GISASSimulation >::CreateItemCallback CreateFn) -> bool\n"
 		"\n"
 		"bool IFactory< Key, AbstractProduct >::registerItem(const Key &item_key, CreateItemCallback CreateFn, const std::string &itemDescription=\"\")\n"
 		"\n"
 		"Registers object's creation function and store object description. \n"
 		"\n"
 		""},
-	 { (char *)"delete_SimulationFactory", _wrap_delete_SimulationFactory, METH_VARARGS, (char *)"\n"
-		"delete_SimulationFactory(SimulationFactory self)\n"
+	 { (char *)"delete_SimulationFactoryTemp", _wrap_delete_SimulationFactoryTemp, METH_VARARGS, (char *)"\n"
+		"delete_SimulationFactoryTemp(SimulationFactoryTemp self)\n"
 		"\n"
 		"IFactory< Key, AbstractProduct >::~IFactory()\n"
 		"\n"
 		""},
-	 { (char *)"SimulationFactory_getNumberOfRegistered", _wrap_SimulationFactory_getNumberOfRegistered, METH_VARARGS, (char *)"\n"
-		"SimulationFactory_getNumberOfRegistered(SimulationFactory self) -> size_t\n"
+	 { (char *)"SimulationFactoryTemp_getNumberOfRegistered", _wrap_SimulationFactoryTemp_getNumberOfRegistered, METH_VARARGS, (char *)"\n"
+		"SimulationFactoryTemp_getNumberOfRegistered(SimulationFactoryTemp self) -> size_t\n"
 		"\n"
 		"size_t IFactory< Key, AbstractProduct >::getNumberOfRegistered() const\n"
 		"\n"
 		"Returns number of registered objects. \n"
 		"\n"
 		""},
-	 { (char *)"SimulationFactory_begin", _wrap_SimulationFactory_begin, METH_VARARGS, (char *)"\n"
-		"SimulationFactory_begin(SimulationFactory self) -> IFactory< std::string,GISASSimulation >::const_iterator\n"
+	 { (char *)"SimulationFactoryTemp_begin", _wrap_SimulationFactoryTemp_begin, METH_VARARGS, (char *)"\n"
+		"SimulationFactoryTemp_begin(SimulationFactoryTemp self) -> IFactory< std::string,GISASSimulation >::const_iterator\n"
 		"\n"
 		"const_iterator IFactory< Key, AbstractProduct >::begin() const \n"
 		"\n"
 		""},
-	 { (char *)"SimulationFactory_end", _wrap_SimulationFactory_end, METH_VARARGS, (char *)"\n"
-		"SimulationFactory_end(SimulationFactory self) -> IFactory< std::string,GISASSimulation >::const_iterator\n"
+	 { (char *)"SimulationFactoryTemp_end", _wrap_SimulationFactoryTemp_end, METH_VARARGS, (char *)"\n"
+		"SimulationFactoryTemp_end(SimulationFactoryTemp self) -> IFactory< std::string,GISASSimulation >::const_iterator\n"
 		"\n"
 		"const_iterator IFactory< Key, AbstractProduct >::end() const \n"
 		"\n"
 		""},
+	 { (char *)"SimulationFactoryTemp_swigregister", SimulationFactoryTemp_swigregister, METH_VARARGS, NULL},
+	 { (char *)"new_SimulationFactory", _wrap_new_SimulationFactory, METH_VARARGS, (char *)"\n"
+		"new_SimulationFactory() -> SimulationFactory\n"
+		"\n"
+		"SimulationFactory::SimulationFactory()\n"
+		"\n"
+		""},
+	 { (char *)"delete_SimulationFactory", _wrap_delete_SimulationFactory, METH_VARARGS, (char *)"delete_SimulationFactory(SimulationFactory self)"},
 	 { (char *)"SimulationFactory_swigregister", SimulationFactory_swigregister, METH_VARARGS, NULL},
 	 { NULL, NULL, 0, NULL }
 };
@@ -113414,6 +113826,9 @@ static void *_p_FormFactorPrism3To_p_FormFactorPolygonalPrism(void *x, int *SWIG
 static void *_p_FormFactorPrism6To_p_FormFactorPolygonalPrism(void *x, int *SWIGUNUSEDPARM(newmemory)) {
     return (void *)((FormFactorPolygonalPrism *)  ((FormFactorPrism6 *) x));
 }
+static void *_p_SimulationFactoryTo_p_IFactoryT_std__string_GISASSimulation_t(void *x, int *SWIGUNUSEDPARM(newmemory)) {
+    return (void *)((IFactory< std::string,GISASSimulation > *)  ((SimulationFactory *) x));
+}
 static void *_p_FormFactorPrism6To_p_IFormFactorBorn(void *x, int *SWIGUNUSEDPARM(newmemory)) {
     return (void *)((IFormFactorBorn *) (FormFactorPolygonalPrism *) ((FormFactorPrism6 *) x));
 }
@@ -113589,6 +114004,9 @@ static void *_p_IParameterT_double_tTo_p_INoncopyable(void *x, int *SWIGUNUSEDPA
 static void *_p_InterferenceFunctionNoneTo_p_INoncopyable(void *x, int *SWIGUNUSEDPARM(newmemory)) {
     return (void *)((INoncopyable *) (ICloneable *)(ISample *)(IInterferenceFunction *) ((InterferenceFunctionNone *) x));
 }
+static void *_p_IDetector2DTo_p_INoncopyable(void *x, int *SWIGUNUSEDPARM(newmemory)) {
+    return (void *)((INoncopyable *) (ICloneable *) ((IDetector2D *) x));
+}
 static void *_p_Geometry__PolygonTo_p_INoncopyable(void *x, int *SWIGUNUSEDPARM(newmemory)) {
     return (void *)((INoncopyable *) (ICloneable *)(Geometry::IShape2D *) ((Geometry::Polygon *) x));
 }
@@ -113613,6 +114031,15 @@ static void *_p_IChiSquaredModuleTo_p_INoncopyable(void *x, int *SWIGUNUSEDPARM(
 static void *_p_Geometry__HorizontalLineTo_p_INoncopyable(void *x, int *SWIGUNUSEDPARM(newmemory)) {
     return (void *)((INoncopyable *) (ICloneable *)(Geometry::IShape2D *) ((Geometry::HorizontalLine *) x));
 }
+static void *_p_IsGISAXSDetectorTo_p_INoncopyable(void *x, int *SWIGUNUSEDPARM(newmemory)) {
+    return (void *)((INoncopyable *) (ICloneable *)(IDetector2D *)(SphericalDetector *) ((IsGISAXSDetector *) x));
+}
+static void *_p_SphericalDetectorTo_p_INoncopyable(void *x, int *SWIGUNUSEDPARM(newmemory)) {
+    return (void *)((INoncopyable *) (ICloneable *)(IDetector2D *) ((SphericalDetector *) x));
+}
+static void *_p_RectangularDetectorTo_p_INoncopyable(void *x, int *SWIGUNUSEDPARM(newmemory)) {
+    return (void *)((INoncopyable *) (ICloneable *)(IDetector2D *) ((RectangularDetector *) x));
+}
 static void *_p_FormFactorPrism3To_p_INoncopyable(void *x, int *SWIGUNUSEDPARM(newmemory)) {
     return (void *)((INoncopyable *) (ICloneable *)(ISample *)(IFormFactor *)(IFormFactorBorn *)(FormFactorPolygonalPrism *) ((FormFactorPrism3 *) x));
 }
@@ -113784,12 +114211,12 @@ static void *_p_IFormFactorDecoratorTo_p_INoncopyable(void *x, int *SWIGUNUSEDPA
 static void *_p_Geometry__LineTo_p_INoncopyable(void *x, int *SWIGUNUSEDPARM(newmemory)) {
     return (void *)((INoncopyable *) (ICloneable *)(Geometry::IShape2D *) ((Geometry::Line *) x));
 }
-static void *_p_LayerRoughnessTo_p_INoncopyable(void *x, int *SWIGUNUSEDPARM(newmemory)) {
-    return (void *)((INoncopyable *) (ICloneable *)(ISample *)(IRoughness *) ((LayerRoughness *) x));
-}
 static void *_p_IRoughnessTo_p_INoncopyable(void *x, int *SWIGUNUSEDPARM(newmemory)) {
     return (void *)((INoncopyable *) (ICloneable *)(ISample *) ((IRoughness *) x));
 }
+static void *_p_LayerRoughnessTo_p_INoncopyable(void *x, int *SWIGUNUSEDPARM(newmemory)) {
+    return (void *)((INoncopyable *) (ICloneable *)(ISample *)(IRoughness *) ((LayerRoughness *) x));
+}
 static void *_p_InterferenceFunction2DParaCrystalTo_p_INoncopyable(void *x, int *SWIGUNUSEDPARM(newmemory)) {
     return (void *)((INoncopyable *) (ICloneable *)(ISample *)(IInterferenceFunction *) ((InterferenceFunction2DParaCrystal *) x));
 }
@@ -113865,6 +114292,9 @@ static void *_p_ParticleDistributionTo_p_ICloneable(void *x, int *SWIGUNUSEDPARM
 static void *_p_InterferenceFunctionNoneTo_p_ICloneable(void *x, int *SWIGUNUSEDPARM(newmemory)) {
     return (void *)((ICloneable *) (ISample *)(IInterferenceFunction *) ((InterferenceFunctionNone *) x));
 }
+static void *_p_IDetector2DTo_p_ICloneable(void *x, int *SWIGUNUSEDPARM(newmemory)) {
+    return (void *)((ICloneable *)  ((IDetector2D *) x));
+}
 static void *_p_Geometry__PolygonTo_p_ICloneable(void *x, int *SWIGUNUSEDPARM(newmemory)) {
     return (void *)((ICloneable *) (Geometry::IShape2D *) ((Geometry::Polygon *) x));
 }
@@ -113889,6 +114319,15 @@ static void *_p_IChiSquaredModuleTo_p_ICloneable(void *x, int *SWIGUNUSEDPARM(ne
 static void *_p_Geometry__HorizontalLineTo_p_ICloneable(void *x, int *SWIGUNUSEDPARM(newmemory)) {
     return (void *)((ICloneable *) (Geometry::IShape2D *) ((Geometry::HorizontalLine *) x));
 }
+static void *_p_IsGISAXSDetectorTo_p_ICloneable(void *x, int *SWIGUNUSEDPARM(newmemory)) {
+    return (void *)((ICloneable *) (IDetector2D *)(SphericalDetector *) ((IsGISAXSDetector *) x));
+}
+static void *_p_SphericalDetectorTo_p_ICloneable(void *x, int *SWIGUNUSEDPARM(newmemory)) {
+    return (void *)((ICloneable *) (IDetector2D *) ((SphericalDetector *) x));
+}
+static void *_p_RectangularDetectorTo_p_ICloneable(void *x, int *SWIGUNUSEDPARM(newmemory)) {
+    return (void *)((ICloneable *) (IDetector2D *) ((RectangularDetector *) x));
+}
 static void *_p_FormFactorPrism3To_p_ICloneable(void *x, int *SWIGUNUSEDPARM(newmemory)) {
     return (void *)((ICloneable *) (ISample *)(IFormFactor *)(IFormFactorBorn *)(FormFactorPolygonalPrism *) ((FormFactorPrism3 *) x));
 }
@@ -114060,9 +114499,6 @@ static void *_p_LayerRoughnessTo_p_ICloneable(void *x, int *SWIGUNUSEDPARM(newme
 static void *_p_IRoughnessTo_p_ICloneable(void *x, int *SWIGUNUSEDPARM(newmemory)) {
     return (void *)((ICloneable *) (ISample *) ((IRoughness *) x));
 }
-static void *_p_MesoCrystalTo_p_ICloneable(void *x, int *SWIGUNUSEDPARM(newmemory)) {
-    return (void *)((ICloneable *) (ISample *)(ICompositeSample *)(IAbstractParticle *)(IParticle *) ((MesoCrystal *) x));
-}
 static void *_p_InterferenceFunction2DParaCrystalTo_p_ICloneable(void *x, int *SWIGUNUSEDPARM(newmemory)) {
     return (void *)((ICloneable *) (ISample *)(IInterferenceFunction *) ((InterferenceFunction2DParaCrystal *) x));
 }
@@ -114075,6 +114511,9 @@ static void *_p_CrystalTo_p_ICloneable(void *x, int *SWIGUNUSEDPARM(newmemory))
 static void *_p_FormFactorCrystalTo_p_ICloneable(void *x, int *SWIGUNUSEDPARM(newmemory)) {
     return (void *)((ICloneable *) (ISample *)(IFormFactor *) ((FormFactorCrystal *) x));
 }
+static void *_p_MesoCrystalTo_p_ICloneable(void *x, int *SWIGUNUSEDPARM(newmemory)) {
+    return (void *)((ICloneable *) (ISample *)(ICompositeSample *)(IAbstractParticle *)(IParticle *) ((MesoCrystal *) x));
+}
 static void *_p_FormFactorWeightedTo_p_ICloneable(void *x, int *SWIGUNUSEDPARM(newmemory)) {
     return (void *)((ICloneable *) (ISample *)(IFormFactor *) ((FormFactorWeighted *) x));
 }
@@ -115038,6 +115477,9 @@ static void *_p_FormFactorLongRipple2GaussTo_p_IFormFactor(void *x, int *SWIGUNU
 static void *_p_FormFactorGaussTo_p_IFormFactor(void *x, int *SWIGUNUSEDPARM(newmemory)) {
     return (void *)((IFormFactor *) (IFormFactorBorn *) ((FormFactorGauss *) x));
 }
+static void *_p_SampleBuilderFactoryTo_p_IFactoryT_std__string_IMultiLayerBuilder_t(void *x, int *SWIGUNUSEDPARM(newmemory)) {
+    return (void *)((IFactory< std::string,IMultiLayerBuilder > *)  ((SampleBuilderFactory *) x));
+}
 static void *_p_FormFactorPrism6To_p_ISample(void *x, int *SWIGUNUSEDPARM(newmemory)) {
     return (void *)((ISample *) (IFormFactor *)(IFormFactorBorn *)(FormFactorPolygonalPrism *) ((FormFactorPrism6 *) x));
 }
@@ -115639,8 +116081,10 @@ static swig_type_info _swigt__p_RotationX = {"_p_RotationX", "RotationX *", 0, 0
 static swig_type_info _swigt__p_RotationY = {"_p_RotationY", "RotationY *", 0, 0, (void*)0, 0};
 static swig_type_info _swigt__p_RotationZ = {"_p_RotationZ", "RotationZ *", 0, 0, (void*)0, 0};
 static swig_type_info _swigt__p_SafePointerVectorT_IParticle_const_t = {"_p_SafePointerVectorT_IParticle_const_t", "SafePointerVector< IParticle const > *", 0, 0, (void*)0, 0};
+static swig_type_info _swigt__p_SampleBuilderFactory = {"_p_SampleBuilderFactory", "SampleBuilderFactory *", 0, 0, (void*)0, 0};
 static swig_type_info _swigt__p_SimpleSelectionRule = {"_p_SimpleSelectionRule", "SimpleSelectionRule *", 0, 0, (void*)0, 0};
 static swig_type_info _swigt__p_Simulation = {"_p_Simulation", "Simulation *", 0, 0, (void*)0, 0};
+static swig_type_info _swigt__p_SimulationFactory = {"_p_SimulationFactory", "SimulationFactory *", 0, 0, (void*)0, 0};
 static swig_type_info _swigt__p_SimulationOptions = {"_p_SimulationOptions", "SimulationOptions *", 0, 0, (void*)0, 0};
 static swig_type_info _swigt__p_SpecularSimulation = {"_p_SpecularSimulation", "SpecularSimulation *", 0, 0, (void*)0, 0};
 static swig_type_info _swigt__p_SphericalDetector = {"_p_SphericalDetector", "SphericalDetector *", 0, 0, (void*)0, 0};
@@ -115934,8 +116378,10 @@ static swig_type_info *swig_type_initial[] = {
   &_swigt__p_RotationY,
   &_swigt__p_RotationZ,
   &_swigt__p_SafePointerVectorT_IParticle_const_t,
+  &_swigt__p_SampleBuilderFactory,
   &_swigt__p_SimpleSelectionRule,
   &_swigt__p_Simulation,
+  &_swigt__p_SimulationFactory,
   &_swigt__p_SimulationOptions,
   &_swigt__p_SpecularSimulation,
   &_swigt__p_SphericalDetector,
@@ -116132,7 +116578,7 @@ static swig_cast_info _swigc__p_HomogeneousMaterial[] = {  {&_swigt__p_Homogeneo
 static swig_cast_info _swigc__p_IAbstractParticle[] = {  {&_swigt__p_ParticleComposition, _p_ParticleCompositionTo_p_IAbstractParticle, 0, 0},  {&_swigt__p_ParticleDistribution, _p_ParticleDistributionTo_p_IAbstractParticle, 0, 0},  {&_swigt__p_MesoCrystal, _p_MesoCrystalTo_p_IAbstractParticle, 0, 0},  {&_swigt__p_IAbstractParticle, 0, 0, 0},  {&_swigt__p_IParticle, _p_IParticleTo_p_IAbstractParticle, 0, 0},  {&_swigt__p_Particle, _p_ParticleTo_p_IAbstractParticle, 0, 0},  {&_swigt__p_ParticleCoreShell, _p_ParticleCoreShellTo_p_IAbstractParticle, 0, 0},{0, 0, 0, 0}};
 static swig_cast_info _swigc__p_IAxis[] = {  {&_swigt__p_IAxis, 0, 0, 0},  {&_swigt__p_VariableBinAxis, _p_VariableBinAxisTo_p_IAxis, 0, 0},  {&_swigt__p_ConstKBinAxis, _p_ConstKBinAxisTo_p_IAxis, 0, 0},  {&_swigt__p_CustomBinAxis, _p_CustomBinAxisTo_p_IAxis, 0, 0},  {&_swigt__p_FixedBinAxis, _p_FixedBinAxisTo_p_IAxis, 0, 0},{0, 0, 0, 0}};
 static swig_cast_info _swigc__p_IChiSquaredModule[] = {  {&_swigt__p_IChiSquaredModule, 0, 0, 0},  {&_swigt__p_ChiSquaredModule, _p_ChiSquaredModuleTo_p_IChiSquaredModule, 0, 0},{0, 0, 0, 0}};
-static swig_cast_info _swigc__p_ICloneable[] = {  {&_swigt__p_FormFactorBox, _p_FormFactorBoxTo_p_ICloneable, 0, 0},  {&_swigt__p_FormFactorSphereLogNormalRadius, _p_FormFactorSphereLogNormalRadiusTo_p_ICloneable, 0, 0},  {&_swigt__p_FormFactorSphereGaussianRadius, _p_FormFactorSphereGaussianRadiusTo_p_ICloneable, 0, 0},  {&_swigt__p_MultiLayer, _p_MultiLayerTo_p_ICloneable, 0, 0},  {&_swigt__p_ParticleDistribution, _p_ParticleDistributionTo_p_ICloneable, 0, 0},  {&_swigt__p_InterferenceFunctionNone, _p_InterferenceFunctionNoneTo_p_ICloneable, 0, 0},  {&_swigt__p_Geometry__Polygon, _p_Geometry__PolygonTo_p_ICloneable, 0, 0},  {&_swigt__p_Geometry__Ellipse, _p_Geometry__EllipseTo_p_ICloneable, 0, 0},  {&_swigt__p_ILayout, _p_ILayoutTo_p_ICloneable, 0, 0},  {&_swigt__p_ParticleLayout, _p_ParticleLayoutTo_p_ICloneable, 0, 0},  {&_swigt__p_FormFactorHemiEllipsoid, _p_FormFactorHemiEllipsoidTo_p_ICloneable, 0, 0},  {&_swigt__p_ChiSquaredModule, _p_ChiSquaredModuleTo_p_ICloneable, 0, 0},  {&_swigt__p_IChiSquaredModule, _p_IChiSquaredModuleTo_p_ICloneable, 0, 0},  {&_swigt__p_Geometry__HorizontalLine, _p_Geometry__HorizontalLineTo_p_ICloneable, 0, 0},  {&_swigt__p_FormFactorPrism3, _p_FormFactorPrism3To_p_ICloneable, 0, 0},  {&_swigt__p_FormFactorTetrahedron, _p_FormFactorTetrahedronTo_p_ICloneable, 0, 0},  {&_swigt__p_FormFactorPolyhedron, _p_FormFactorPolyhedronTo_p_ICloneable, 0, 0},  {&_swigt__p_FormFactorCuboctahedron, _p_FormFactorCuboctahedronTo_p_ICloneable, 0, 0},  {&_swigt__p_FormFactorDodecahedron, _p_FormFactorDodecahedronTo_p_ICloneable, 0, 0},  {&_swigt__p_FormFactorIcosahedron, _p_FormFactorIcosahedronTo_p_ICloneable, 0, 0},  {&_swigt__p_FormFactorPrism6, _p_FormFactorPrism6To_p_ICloneable, 0, 0},  {&_swigt__p_GISASSimulation, _p_GISASSimulationTo_p_ICloneable, 0, 0},  {&_swigt__p_Simulation, _p_SimulationTo_p_ICloneable, 0, 0},  {&_swigt__p_OffSpecSimulation, _p_OffSpecSimulationTo_p_ICloneable, 0, 0},  {&_swigt__p_SpecularSimulation, _p_SpecularSimulationTo_p_ICloneable, 0, 0},  {&_swigt__p_ParticleCoreShell, _p_ParticleCoreShellTo_p_ICloneable, 0, 0},  {&_swigt__p_FormFactorTruncatedSphere, _p_FormFactorTruncatedSphereTo_p_ICloneable, 0, 0},  {&_swigt__p_FormFactorFullSphere, _p_FormFactorFullSphereTo_p_ICloneable, 0, 0},  {&_swigt__p_IFormFactor, _p_IFormFactorTo_p_ICloneable, 0, 0},  {&_swigt__p_ISample, _p_ISampleTo_p_ICloneable, 0, 0},  {&_swigt__p_ICompositeSample, _p_ICompositeSampleTo_p_ICloneable, 0, 0},  {&_swigt__p_FormFactorPolygonalSurface, _p_FormFactorPolygonalSurfaceTo_p_ICloneable, 0, 0},  {&_swigt__p_FormFactorLongBoxGauss, _p_FormFactorLongBoxGaussTo_p_ICloneable, 0, 0},  {&_swigt__p_FormFactorPolygonalPrism, _p_FormFactorPolygonalPrismTo_p_ICloneable, 0, 0},  {&_swigt__p_IRotation, _p_IRotationTo_p_ICloneable, 0, 0},  {&_swigt__p_RotationX, _p_RotationXTo_p_ICloneable, 0, 0},  {&_swigt__p_FormFactorTruncatedSpheroid, _p_FormFactorTruncatedSpheroidTo_p_ICloneable, 0, 0},  {&_swigt__p_FormFactorFullSpheroid, _p_FormFactorFullSpheroidTo_p_ICloneable, 0, 0},  {&_swigt__p_FormFactorTruncatedCube, _p_FormFactorTruncatedCubeTo_p_ICloneable, 0, 0},  {&_swigt__p_RotationY, _p_RotationYTo_p_ICloneable, 0, 0},  {&_swigt__p_Geometry__IShape2D, _p_Geometry__IShape2DTo_p_ICloneable, 0, 0},  {&_swigt__p_RotationZ, _p_RotationZTo_p_ICloneable, 0, 0},  {&_swigt__p_Geometry__Rectangle, _p_Geometry__RectangleTo_p_ICloneable, 0, 0},  {&_swigt__p_FormFactorGauss, _p_FormFactorGaussTo_p_ICloneable, 0, 0},  {&_swigt__p_FormFactorLongRipple2Gauss, _p_FormFactorLongRipple2GaussTo_p_ICloneable, 0, 0},  {&_swigt__p_Geometry__VerticalLine, _p_Geometry__VerticalLineTo_p_ICloneable, 0, 0},  {&_swigt__p_IFormFactorBorn, _p_IFormFactorBornTo_p_ICloneable, 0, 0},  {&_swigt__p_IDetectorResolution, _p_IDetectorResolutionTo_p_ICloneable, 0, 0},  {&_swigt__p_IClusteredParticles, _p_IClusteredParticlesTo_p_ICloneable, 0, 0},  {&_swigt__p_IAbstractParticle, _p_IAbstractParticleTo_p_ICloneable, 0, 0},  {&_swigt__p_IParticle, _p_IParticleTo_p_ICloneable, 0, 0},  {&_swigt__p_Particle, _p_ParticleTo_p_ICloneable, 0, 0},  {&_swigt__p_FormFactorTrivial, _p_FormFactorTrivialTo_p_ICloneable, 0, 0},  {&_swigt__p_FormFactorCone, _p_FormFactorConeTo_p_ICloneable, 0, 0},  {&_swigt__p_FormFactorRipple1, _p_FormFactorRipple1To_p_ICloneable, 0, 0},  {&_swigt__p_Layer, _p_LayerTo_p_ICloneable, 0, 0},  {&_swigt__p_FormFactorAnisoPyramid, _p_FormFactorAnisoPyramidTo_p_ICloneable, 0, 0},  {&_swigt__p_FormFactorPyramid, _p_FormFactorPyramidTo_p_ICloneable, 0, 0},  {&_swigt__p_FormFactorDecoratorDebyeWaller, _p_FormFactorDecoratorDebyeWallerTo_p_ICloneable, 0, 0},  {&_swigt__p_FormFactorRipple2, _p_FormFactorRipple2To_p_ICloneable, 0, 0},  {&_swigt__p_FormFactorEllipsoidalCylinder, _p_FormFactorEllipsoidalCylinderTo_p_ICloneable, 0, 0},  {&_swigt__p_FormFactorCylinder, _p_FormFactorCylinderTo_p_ICloneable, 0, 0},  {&_swigt__p_ParticleComposition, _p_ParticleCompositionTo_p_ICloneable, 0, 0},  {&_swigt__p_FormFactorSphereUniformRadius, _p_FormFactorSphereUniformRadiusTo_p_ICloneable, 0, 0},  {&_swigt__p_Geometry__Line, _p_Geometry__LineTo_p_ICloneable, 0, 0},  {&_swigt__p_IInterferenceFunction, _p_IInterferenceFunctionTo_p_ICloneable, 0, 0},  {&_swigt__p_FormFactorCone6, _p_FormFactorCone6To_p_ICloneable, 0, 0},  {&_swigt__p_FormFactorLongRipple1Gauss, _p_FormFactorLongRipple1GaussTo_p_ICloneable, 0, 0},  {&_swigt__p_IFormFactorDecorator, _p_IFormFactorDecoratorTo_p_ICloneable, 0, 0},  {&_swigt__p_IRoughness, _p_IRoughnessTo_p_ICloneable, 0, 0},  {&_swigt__p_LayerRoughness, _p_LayerRoughnessTo_p_ICloneable, 0, 0},  {&_swigt__p_InterferenceFunctionRadialParaCrystal, _p_InterferenceFunctionRadialParaCrystalTo_p_ICloneable, 0, 0},  {&_swigt__p_InterferenceFunction2DParaCrystal, _p_InterferenceFunction2DParaCrystalTo_p_ICloneable, 0, 0},  {&_swigt__p_Crystal, _p_CrystalTo_p_ICloneable, 0, 0},  {&_swigt__p_MesoCrystal, _p_MesoCrystalTo_p_ICloneable, 0, 0},  {&_swigt__p_FormFactorCrystal, _p_FormFactorCrystalTo_p_ICloneable, 0, 0},  {&_swigt__p_FormFactorWeighted, _p_FormFactorWeightedTo_p_ICloneable, 0, 0},  {&_swigt__p_FormFactorLorentz, _p_FormFactorLorentzTo_p_ICloneable, 0, 0},  {&_swigt__p_FormFactorLongRipple2Lorentz, _p_FormFactorLongRipple2LorentzTo_p_ICloneable, 0, 0},  {&_swigt__p_FormFactorLongRipple1Lorentz, _p_FormFactorLongRipple1LorentzTo_p_ICloneable, 0, 0},  {&_swigt__p_FormFactorLongBoxLorentz, _p_FormFactorLongBoxLorentzTo_p_ICloneable, 0, 0},  {&_swigt__p_InterferenceFunction1DLattice, _p_InterferenceFunction1DLatticeTo_p_ICloneable, 0, 0},  {&_swigt__p_InterferenceFunction2DLattice, _p_InterferenceFunction2DLatticeTo_p_ICloneable, 0, 0},  {&_swigt__p_ICloneable, 0, 0, 0},  {&_swigt__p_RotationEuler, _p_RotationEulerTo_p_ICloneable, 0, 0},{0, 0, 0, 0}};
+static swig_cast_info _swigc__p_ICloneable[] = {  {&_swigt__p_FormFactorBox, _p_FormFactorBoxTo_p_ICloneable, 0, 0},  {&_swigt__p_FormFactorSphereLogNormalRadius, _p_FormFactorSphereLogNormalRadiusTo_p_ICloneable, 0, 0},  {&_swigt__p_FormFactorSphereGaussianRadius, _p_FormFactorSphereGaussianRadiusTo_p_ICloneable, 0, 0},  {&_swigt__p_MultiLayer, _p_MultiLayerTo_p_ICloneable, 0, 0},  {&_swigt__p_ParticleDistribution, _p_ParticleDistributionTo_p_ICloneable, 0, 0},  {&_swigt__p_InterferenceFunctionNone, _p_InterferenceFunctionNoneTo_p_ICloneable, 0, 0},  {&_swigt__p_Geometry__Polygon, _p_Geometry__PolygonTo_p_ICloneable, 0, 0},  {&_swigt__p_IDetector2D, _p_IDetector2DTo_p_ICloneable, 0, 0},  {&_swigt__p_Geometry__Ellipse, _p_Geometry__EllipseTo_p_ICloneable, 0, 0},  {&_swigt__p_ParticleLayout, _p_ParticleLayoutTo_p_ICloneable, 0, 0},  {&_swigt__p_ILayout, _p_ILayoutTo_p_ICloneable, 0, 0},  {&_swigt__p_FormFactorHemiEllipsoid, _p_FormFactorHemiEllipsoidTo_p_ICloneable, 0, 0},  {&_swigt__p_ChiSquaredModule, _p_ChiSquaredModuleTo_p_ICloneable, 0, 0},  {&_swigt__p_IChiSquaredModule, _p_IChiSquaredModuleTo_p_ICloneable, 0, 0},  {&_swigt__p_Geometry__HorizontalLine, _p_Geometry__HorizontalLineTo_p_ICloneable, 0, 0},  {&_swigt__p_RectangularDetector, _p_RectangularDetectorTo_p_ICloneable, 0, 0},  {&_swigt__p_IsGISAXSDetector, _p_IsGISAXSDetectorTo_p_ICloneable, 0, 0},  {&_swigt__p_SphericalDetector, _p_SphericalDetectorTo_p_ICloneable, 0, 0},  {&_swigt__p_FormFactorPrism3, _p_FormFactorPrism3To_p_ICloneable, 0, 0},  {&_swigt__p_FormFactorTetrahedron, _p_FormFactorTetrahedronTo_p_ICloneable, 0, 0},  {&_swigt__p_FormFactorPolyhedron, _p_FormFactorPolyhedronTo_p_ICloneable, 0, 0},  {&_swigt__p_FormFactorCuboctahedron, _p_FormFactorCuboctahedronTo_p_ICloneable, 0, 0},  {&_swigt__p_FormFactorDodecahedron, _p_FormFactorDodecahedronTo_p_ICloneable, 0, 0},  {&_swigt__p_FormFactorIcosahedron, _p_FormFactorIcosahedronTo_p_ICloneable, 0, 0},  {&_swigt__p_FormFactorPrism6, _p_FormFactorPrism6To_p_ICloneable, 0, 0},  {&_swigt__p_GISASSimulation, _p_GISASSimulationTo_p_ICloneable, 0, 0},  {&_swigt__p_Simulation, _p_SimulationTo_p_ICloneable, 0, 0},  {&_swigt__p_OffSpecSimulation, _p_OffSpecSimulationTo_p_ICloneable, 0, 0},  {&_swigt__p_SpecularSimulation, _p_SpecularSimulationTo_p_ICloneable, 0, 0},  {&_swigt__p_ParticleCoreShell, _p_ParticleCoreShellTo_p_ICloneable, 0, 0},  {&_swigt__p_FormFactorFullSphere, _p_FormFactorFullSphereTo_p_ICloneable, 0, 0},  {&_swigt__p_FormFactorTruncatedSphere, _p_FormFactorTruncatedSphereTo_p_ICloneable, 0, 0},  {&_swigt__p_IFormFactor, _p_IFormFactorTo_p_ICloneable, 0, 0},  {&_swigt__p_ISample, _p_ISampleTo_p_ICloneable, 0, 0},  {&_swigt__p_FormFactorPolygonalSurface, _p_FormFactorPolygonalSurfaceTo_p_ICloneable, 0, 0},  {&_swigt__p_ICompositeSample, _p_ICompositeSampleTo_p_ICloneable, 0, 0},  {&_swigt__p_FormFactorLongBoxGauss, _p_FormFactorLongBoxGaussTo_p_ICloneable, 0, 0},  {&_swigt__p_FormFactorPolygonalPrism, _p_FormFactorPolygonalPrismTo_p_ICloneable, 0, 0},  {&_swigt__p_IRotation, _p_IRotationTo_p_ICloneable, 0, 0},  {&_swigt__p_RotationX, _p_RotationXTo_p_ICloneable, 0, 0},  {&_swigt__p_FormFactorTruncatedSpheroid, _p_FormFactorTruncatedSpheroidTo_p_ICloneable, 0, 0},  {&_swigt__p_FormFactorFullSpheroid, _p_FormFactorFullSpheroidTo_p_ICloneable, 0, 0},  {&_swigt__p_FormFactorTruncatedCube, _p_FormFactorTruncatedCubeTo_p_ICloneable, 0, 0},  {&_swigt__p_RotationY, _p_RotationYTo_p_ICloneable, 0, 0},  {&_swigt__p_Geometry__IShape2D, _p_Geometry__IShape2DTo_p_ICloneable, 0, 0},  {&_swigt__p_RotationZ, _p_RotationZTo_p_ICloneable, 0, 0},  {&_swigt__p_Geometry__Rectangle, _p_Geometry__RectangleTo_p_ICloneable, 0, 0},  {&_swigt__p_FormFactorGauss, _p_FormFactorGaussTo_p_ICloneable, 0, 0},  {&_swigt__p_FormFactorLongRipple2Gauss, _p_FormFactorLongRipple2GaussTo_p_ICloneable, 0, 0},  {&_swigt__p_Geometry__VerticalLine, _p_Geometry__VerticalLineTo_p_ICloneable, 0, 0},  {&_swigt__p_IFormFactorBorn, _p_IFormFactorBornTo_p_ICloneable, 0, 0},  {&_swigt__p_IDetectorResolution, _p_IDetectorResolutionTo_p_ICloneable, 0, 0},  {&_swigt__p_IClusteredParticles, _p_IClusteredParticlesTo_p_ICloneable, 0, 0},  {&_swigt__p_Particle, _p_ParticleTo_p_ICloneable, 0, 0},  {&_swigt__p_IParticle, _p_IParticleTo_p_ICloneable, 0, 0},  {&_swigt__p_IAbstractParticle, _p_IAbstractParticleTo_p_ICloneable, 0, 0},  {&_swigt__p_FormFactorTrivial, _p_FormFactorTrivialTo_p_ICloneable, 0, 0},  {&_swigt__p_FormFactorCone, _p_FormFactorConeTo_p_ICloneable, 0, 0},  {&_swigt__p_FormFactorRipple1, _p_FormFactorRipple1To_p_ICloneable, 0, 0},  {&_swigt__p_Layer, _p_LayerTo_p_ICloneable, 0, 0},  {&_swigt__p_FormFactorAnisoPyramid, _p_FormFactorAnisoPyramidTo_p_ICloneable, 0, 0},  {&_swigt__p_FormFactorPyramid, _p_FormFactorPyramidTo_p_ICloneable, 0, 0},  {&_swigt__p_FormFactorDecoratorDebyeWaller, _p_FormFactorDecoratorDebyeWallerTo_p_ICloneable, 0, 0},  {&_swigt__p_FormFactorRipple2, _p_FormFactorRipple2To_p_ICloneable, 0, 0},  {&_swigt__p_FormFactorEllipsoidalCylinder, _p_FormFactorEllipsoidalCylinderTo_p_ICloneable, 0, 0},  {&_swigt__p_FormFactorCylinder, _p_FormFactorCylinderTo_p_ICloneable, 0, 0},  {&_swigt__p_ParticleComposition, _p_ParticleCompositionTo_p_ICloneable, 0, 0},  {&_swigt__p_FormFactorSphereUniformRadius, _p_FormFactorSphereUniformRadiusTo_p_ICloneable, 0, 0},  {&_swigt__p_Geometry__Line, _p_Geometry__LineTo_p_ICloneable, 0, 0},  {&_swigt__p_IInterferenceFunction, _p_IInterferenceFunctionTo_p_ICloneable, 0, 0},  {&_swigt__p_FormFactorCone6, _p_FormFactorCone6To_p_ICloneable, 0, 0},  {&_swigt__p_FormFactorLongRipple1Gauss, _p_FormFactorLongRipple1GaussTo_p_ICloneable, 0, 0},  {&_swigt__p_IFormFactorDecorator, _p_IFormFactorDecoratorTo_p_ICloneable, 0, 0},  {&_swigt__p_IRoughness, _p_IRoughnessTo_p_ICloneable, 0, 0},  {&_swigt__p_LayerRoughness, _p_LayerRoughnessTo_p_ICloneable, 0, 0},  {&_swigt__p_Crystal, _p_CrystalTo_p_ICloneable, 0, 0},  {&_swigt__p_InterferenceFunctionRadialParaCrystal, _p_InterferenceFunctionRadialParaCrystalTo_p_ICloneable, 0, 0},  {&_swigt__p_InterferenceFunction2DParaCrystal, _p_InterferenceFunction2DParaCrystalTo_p_ICloneable, 0, 0},  {&_swigt__p_MesoCrystal, _p_MesoCrystalTo_p_ICloneable, 0, 0},  {&_swigt__p_FormFactorCrystal, _p_FormFactorCrystalTo_p_ICloneable, 0, 0},  {&_swigt__p_FormFactorWeighted, _p_FormFactorWeightedTo_p_ICloneable, 0, 0},  {&_swigt__p_FormFactorLorentz, _p_FormFactorLorentzTo_p_ICloneable, 0, 0},  {&_swigt__p_FormFactorLongRipple2Lorentz, _p_FormFactorLongRipple2LorentzTo_p_ICloneable, 0, 0},  {&_swigt__p_FormFactorLongRipple1Lorentz, _p_FormFactorLongRipple1LorentzTo_p_ICloneable, 0, 0},  {&_swigt__p_FormFactorLongBoxLorentz, _p_FormFactorLongBoxLorentzTo_p_ICloneable, 0, 0},  {&_swigt__p_InterferenceFunction1DLattice, _p_InterferenceFunction1DLatticeTo_p_ICloneable, 0, 0},  {&_swigt__p_InterferenceFunction2DLattice, _p_InterferenceFunction2DLatticeTo_p_ICloneable, 0, 0},  {&_swigt__p_ICloneable, 0, 0, 0},  {&_swigt__p_RotationEuler, _p_RotationEulerTo_p_ICloneable, 0, 0},{0, 0, 0, 0}};
 static swig_cast_info _swigc__p_IClusteredParticles[] = {  {&_swigt__p_IClusteredParticles, 0, 0, 0},  {&_swigt__p_Crystal, _p_CrystalTo_p_IClusteredParticles, 0, 0},{0, 0, 0, 0}};
 static swig_cast_info _swigc__p_ICompositeSample[] = {  {&_swigt__p_MultiLayer, _p_MultiLayerTo_p_ICompositeSample, 0, 0},  {&_swigt__p_Crystal, _p_CrystalTo_p_ICompositeSample, 0, 0},  {&_swigt__p_MesoCrystal, _p_MesoCrystalTo_p_ICompositeSample, 0, 0},  {&_swigt__p_IAbstractParticle, _p_IAbstractParticleTo_p_ICompositeSample, 0, 0},  {&_swigt__p_IParticle, _p_IParticleTo_p_ICompositeSample, 0, 0},  {&_swigt__p_Particle, _p_ParticleTo_p_ICompositeSample, 0, 0},  {&_swigt__p_ICompositeSample, 0, 0, 0},  {&_swigt__p_ParticleComposition, _p_ParticleCompositionTo_p_ICompositeSample, 0, 0},  {&_swigt__p_IClusteredParticles, _p_IClusteredParticlesTo_p_ICompositeSample, 0, 0},  {&_swigt__p_ILayout, _p_ILayoutTo_p_ICompositeSample, 0, 0},  {&_swigt__p_ParticleLayout, _p_ParticleLayoutTo_p_ICompositeSample, 0, 0},  {&_swigt__p_Layer, _p_LayerTo_p_ICompositeSample, 0, 0},  {&_swigt__p_ParticleDistribution, _p_ParticleDistributionTo_p_ICompositeSample, 0, 0},  {&_swigt__p_ParticleCoreShell, _p_ParticleCoreShellTo_p_ICompositeSample, 0, 0},{0, 0, 0, 0}};
 static swig_cast_info _swigc__p_IDetector2D[] = {  {&_swigt__p_SphericalDetector, _p_SphericalDetectorTo_p_IDetector2D, 0, 0},  {&_swigt__p_IsGISAXSDetector, _p_IsGISAXSDetectorTo_p_IDetector2D, 0, 0},  {&_swigt__p_RectangularDetector, _p_RectangularDetectorTo_p_IDetector2D, 0, 0},  {&_swigt__p_IDetector2D, 0, 0, 0},{0, 0, 0, 0}};
@@ -116142,8 +116588,8 @@ static swig_cast_info _swigc__p_IFTDecayFunction1D[] = {  {&_swigt__p_FTDecayFun
 static swig_cast_info _swigc__p_IFTDecayFunction2D[] = {  {&_swigt__p_FTDecayFunction2DCauchy, _p_FTDecayFunction2DCauchyTo_p_IFTDecayFunction2D, 0, 0},  {&_swigt__p_FTDecayFunction2DGauss, _p_FTDecayFunction2DGaussTo_p_IFTDecayFunction2D, 0, 0},  {&_swigt__p_IFTDecayFunction2D, 0, 0, 0},  {&_swigt__p_FTDecayFunction2DVoigt, _p_FTDecayFunction2DVoigtTo_p_IFTDecayFunction2D, 0, 0},{0, 0, 0, 0}};
 static swig_cast_info _swigc__p_IFTDistribution1D[] = {  {&_swigt__p_FTDistribution1DCauchy, _p_FTDistribution1DCauchyTo_p_IFTDistribution1D, 0, 0},  {&_swigt__p_FTDistribution1DCosine, _p_FTDistribution1DCosineTo_p_IFTDistribution1D, 0, 0},  {&_swigt__p_FTDistribution1DGauss, _p_FTDistribution1DGaussTo_p_IFTDistribution1D, 0, 0},  {&_swigt__p_FTDistribution1DGate, _p_FTDistribution1DGateTo_p_IFTDistribution1D, 0, 0},  {&_swigt__p_FTDistribution1DTriangle, _p_FTDistribution1DTriangleTo_p_IFTDistribution1D, 0, 0},  {&_swigt__p_IFTDistribution1D, 0, 0, 0},  {&_swigt__p_FTDistribution1DVoigt, _p_FTDistribution1DVoigtTo_p_IFTDistribution1D, 0, 0},{0, 0, 0, 0}};
 static swig_cast_info _swigc__p_IFTDistribution2D[] = {  {&_swigt__p_FTDistribution2DCauchy, _p_FTDistribution2DCauchyTo_p_IFTDistribution2D, 0, 0},  {&_swigt__p_FTDistribution2DGauss, _p_FTDistribution2DGaussTo_p_IFTDistribution2D, 0, 0},  {&_swigt__p_IFTDistribution2D, 0, 0, 0},  {&_swigt__p_FTDistribution2DVoigt, _p_FTDistribution2DVoigtTo_p_IFTDistribution2D, 0, 0},  {&_swigt__p_FTDistribution2DGate, _p_FTDistribution2DGateTo_p_IFTDistribution2D, 0, 0},  {&_swigt__p_FTDistribution2DCone, _p_FTDistribution2DConeTo_p_IFTDistribution2D, 0, 0},{0, 0, 0, 0}};
-static swig_cast_info _swigc__p_IFactoryT_std__string_GISASSimulation_t[] = {  {&_swigt__p_IFactoryT_std__string_GISASSimulation_t, 0, 0, 0},{0, 0, 0, 0}};
-static swig_cast_info _swigc__p_IFactoryT_std__string_IMultiLayerBuilder_t[] = {  {&_swigt__p_IFactoryT_std__string_IMultiLayerBuilder_t, 0, 0, 0},{0, 0, 0, 0}};
+static swig_cast_info _swigc__p_IFactoryT_std__string_GISASSimulation_t[] = {  {&_swigt__p_SimulationFactory, _p_SimulationFactoryTo_p_IFactoryT_std__string_GISASSimulation_t, 0, 0},  {&_swigt__p_IFactoryT_std__string_GISASSimulation_t, 0, 0, 0},{0, 0, 0, 0}};
+static swig_cast_info _swigc__p_IFactoryT_std__string_IMultiLayerBuilder_t[] = {  {&_swigt__p_IFactoryT_std__string_IMultiLayerBuilder_t, 0, 0, 0},  {&_swigt__p_SampleBuilderFactory, _p_SampleBuilderFactoryTo_p_IFactoryT_std__string_IMultiLayerBuilder_t, 0, 0},{0, 0, 0, 0}};
 static swig_cast_info _swigc__p_IFitObserver[] = {  {&_swigt__p_IFitObserver, 0, 0, 0},{0, 0, 0, 0}};
 static swig_cast_info _swigc__p_IFitParameter[] = {  {&_swigt__p_IFitParameter, 0, 0, 0},  {&_swigt__p_FitParameter, _p_FitParameterTo_p_IFitParameter, 0, 0},  {&_swigt__p_FitParameterLinked, _p_FitParameterLinkedTo_p_IFitParameter, 0, 0},{0, 0, 0, 0}};
 static swig_cast_info _swigc__p_IFitStrategy[] = {  {&_swigt__p_IFitStrategy, 0, 0, 0},  {&_swigt__p_AdjustMinimizerStrategy, _p_AdjustMinimizerStrategyTo_p_IFitStrategy, 0, 0},  {&_swigt__p_FitStrategyDefault, _p_FitStrategyDefaultTo_p_IFitStrategy, 0, 0},{0, 0, 0, 0}};
@@ -116160,7 +116606,7 @@ static swig_cast_info _swigc__p_IMaterial[] = {  {&_swigt__p_IMaterial, 0, 0, 0}
 static swig_cast_info _swigc__p_IMinimizer[] = {  {&_swigt__p_IMinimizer, 0, 0, 0},{0, 0, 0, 0}};
 static swig_cast_info _swigc__p_IMultiLayerBuilder[] = {  {&_swigt__p_IMultiLayerBuilder, 0, 0, 0},{0, 0, 0, 0}};
 static swig_cast_info _swigc__p_INamed[] = {  {&_swigt__p_FormFactorBox, _p_FormFactorBoxTo_p_INamed, 0, 0},  {&_swigt__p_FormFactorSphereGaussianRadius, _p_FormFactorSphereGaussianRadiusTo_p_INamed, 0, 0},  {&_swigt__p_FormFactorSphereLogNormalRadius, _p_FormFactorSphereLogNormalRadiusTo_p_INamed, 0, 0},  {&_swigt__p_MultiLayer, _p_MultiLayerTo_p_INamed, 0, 0},  {&_swigt__p_ParameterDistribution, _p_ParameterDistributionTo_p_INamed, 0, 0},  {&_swigt__p_ParticleDistribution, _p_ParticleDistributionTo_p_INamed, 0, 0},  {&_swigt__p_FTDistribution1DGauss, _p_FTDistribution1DGaussTo_p_INamed, 0, 0},  {&_swigt__p_FTDecayFunction1DGauss, _p_FTDecayFunction1DGaussTo_p_INamed, 0, 0},  {&_swigt__p_InterferenceFunctionNone, _p_InterferenceFunctionNoneTo_p_INamed, 0, 0},  {&_swigt__p_Geometry__Polygon, _p_Geometry__PolygonTo_p_INamed, 0, 0},  {&_swigt__p_IDetector2D, _p_IDetector2DTo_p_INamed, 0, 0},  {&_swigt__p_Geometry__Ellipse, _p_Geometry__EllipseTo_p_INamed, 0, 0},  {&_swigt__p_ILayout, _p_ILayoutTo_p_INamed, 0, 0},  {&_swigt__p_ParticleLayout, _p_ParticleLayoutTo_p_INamed, 0, 0},  {&_swigt__p_FormFactorHemiEllipsoid, _p_FormFactorHemiEllipsoidTo_p_INamed, 0, 0},  {&_swigt__p_IntensityScaleAndShiftNormalizer, _p_IntensityScaleAndShiftNormalizerTo_p_INamed, 0, 0},  {&_swigt__p_IntensityNormalizer, _p_IntensityNormalizerTo_p_INamed, 0, 0},  {&_swigt__p_IIntensityNormalizer, _p_IIntensityNormalizerTo_p_INamed, 0, 0},  {&_swigt__p_Geometry__HorizontalLine, _p_Geometry__HorizontalLineTo_p_INamed, 0, 0},  {&_swigt__p_IsGISAXSDetector, _p_IsGISAXSDetectorTo_p_INamed, 0, 0},  {&_swigt__p_SphericalDetector, _p_SphericalDetectorTo_p_INamed, 0, 0},  {&_swigt__p_RectangularDetector, _p_RectangularDetectorTo_p_INamed, 0, 0},  {&_swigt__p_FormFactorPrism3, _p_FormFactorPrism3To_p_INamed, 0, 0},  {&_swigt__p_FormFactorIcosahedron, _p_FormFactorIcosahedronTo_p_INamed, 0, 0},  {&_swigt__p_FormFactorDodecahedron, _p_FormFactorDodecahedronTo_p_INamed, 0, 0},  {&_swigt__p_FormFactorCuboctahedron, _p_FormFactorCuboctahedronTo_p_INamed, 0, 0},  {&_swigt__p_FormFactorPolyhedron, _p_FormFactorPolyhedronTo_p_INamed, 0, 0},  {&_swigt__p_FormFactorTetrahedron, _p_FormFactorTetrahedronTo_p_INamed, 0, 0},  {&_swigt__p_FormFactorPrism6, _p_FormFactorPrism6To_p_INamed, 0, 0},  {&_swigt__p_OffSpecSimulation, _p_OffSpecSimulationTo_p_INamed, 0, 0},  {&_swigt__p_GISASSimulation, _p_GISASSimulationTo_p_INamed, 0, 0},  {&_swigt__p_Simulation, _p_SimulationTo_p_INamed, 0, 0},  {&_swigt__p_SpecularSimulation, _p_SpecularSimulationTo_p_INamed, 0, 0},  {&_swigt__p_FTDistribution2DCone, _p_FTDistribution2DConeTo_p_INamed, 0, 0},  {&_swigt__p_ParticleCoreShell, _p_ParticleCoreShellTo_p_INamed, 0, 0},  {&_swigt__p_FormFactorFullSphere, _p_FormFactorFullSphereTo_p_INamed, 0, 0},  {&_swigt__p_FormFactorTruncatedSphere, _p_FormFactorTruncatedSphereTo_p_INamed, 0, 0},  {&_swigt__p_IFormFactor, _p_IFormFactorTo_p_INamed, 0, 0},  {&_swigt__p_ISample, _p_ISampleTo_p_INamed, 0, 0},  {&_swigt__p_FormFactorPolygonalSurface, _p_FormFactorPolygonalSurfaceTo_p_INamed, 0, 0},  {&_swigt__p_ICompositeSample, _p_ICompositeSampleTo_p_INamed, 0, 0},  {&_swigt__p_FormFactorLongBoxGauss, _p_FormFactorLongBoxGaussTo_p_INamed, 0, 0},  {&_swigt__p_FormFactorPolygonalPrism, _p_FormFactorPolygonalPrismTo_p_INamed, 0, 0},  {&_swigt__p_FitSuiteObjects, _p_FitSuiteObjectsTo_p_INamed, 0, 0},  {&_swigt__p_FTDistribution2DGate, _p_FTDistribution2DGateTo_p_INamed, 0, 0},  {&_swigt__p_DistributionLogNormal, _p_DistributionLogNormalTo_p_INamed, 0, 0},  {&_swigt__p_Instrument, _p_InstrumentTo_p_INamed, 0, 0},  {&_swigt__p_FTDecayFunction1DVoigt, _p_FTDecayFunction1DVoigtTo_p_INamed, 0, 0},  {&_swigt__p_FTDistribution1DVoigt, _p_FTDistribution1DVoigtTo_p_INamed, 0, 0},  {&_swigt__p_IRotation, _p_IRotationTo_p_INamed, 0, 0},  {&_swigt__p_RotationX, _p_RotationXTo_p_INamed, 0, 0},  {&_swigt__p_FormFactorTruncatedSpheroid, _p_FormFactorTruncatedSpheroidTo_p_INamed, 0, 0},  {&_swigt__p_FormFactorFullSpheroid, _p_FormFactorFullSpheroidTo_p_INamed, 0, 0},  {&_swigt__p_FormFactorTruncatedCube, _p_FormFactorTruncatedCubeTo_p_INamed, 0, 0},  {&_swigt__p_RotationY, _p_RotationYTo_p_INamed, 0, 0},  {&_swigt__p_Geometry__IShape2D, _p_Geometry__IShape2DTo_p_INamed, 0, 0},  {&_swigt__p_FTDecayFunction2DGauss, _p_FTDecayFunction2DGaussTo_p_INamed, 0, 0},  {&_swigt__p_FTDistribution2DGauss, _p_FTDistribution2DGaussTo_p_INamed, 0, 0},  {&_swigt__p_RotationZ, _p_RotationZTo_p_INamed, 0, 0},  {&_swigt__p_Geometry__Rectangle, _p_Geometry__RectangleTo_p_INamed, 0, 0},  {&_swigt__p_FitStrategyDefault, _p_FitStrategyDefaultTo_p_INamed, 0, 0},  {&_swigt__p_FormFactorGauss, _p_FormFactorGaussTo_p_INamed, 0, 0},  {&_swigt__p_FormFactorLongRipple2Gauss, _p_FormFactorLongRipple2GaussTo_p_INamed, 0, 0},  {&_swigt__p_Geometry__VerticalLine, _p_Geometry__VerticalLineTo_p_INamed, 0, 0},  {&_swigt__p_IFormFactorBorn, _p_IFormFactorBornTo_p_INamed, 0, 0},  {&_swigt__p_IDetectorResolution, _p_IDetectorResolutionTo_p_INamed, 0, 0},  {&_swigt__p_IClusteredParticles, _p_IClusteredParticlesTo_p_INamed, 0, 0},  {&_swigt__p_IMultiLayerBuilder, _p_IMultiLayerBuilderTo_p_INamed, 0, 0},  {&_swigt__p_Particle, _p_ParticleTo_p_INamed, 0, 0},  {&_swigt__p_IParticle, _p_IParticleTo_p_INamed, 0, 0},  {&_swigt__p_IAbstractParticle, _p_IAbstractParticleTo_p_INamed, 0, 0},  {&_swigt__p_FormFactorTrivial, _p_FormFactorTrivialTo_p_INamed, 0, 0},  {&_swigt__p_INamed, 0, 0, 0},  {&_swigt__p_DistributionGate, _p_DistributionGateTo_p_INamed, 0, 0},  {&_swigt__p_IDistribution1D, _p_IDistribution1DTo_p_INamed, 0, 0},  {&_swigt__p_IFTDecayFunction1D, _p_IFTDecayFunction1DTo_p_INamed, 0, 0},  {&_swigt__p_IFTDistribution1D, _p_IFTDistribution1DTo_p_INamed, 0, 0},  {&_swigt__p_FormFactorCone, _p_FormFactorConeTo_p_INamed, 0, 0},  {&_swigt__p_FormFactorRipple1, _p_FormFactorRipple1To_p_INamed, 0, 0},  {&_swigt__p_Layer, _p_LayerTo_p_INamed, 0, 0},  {&_swigt__p_IMaterial, _p_IMaterialTo_p_INamed, 0, 0},  {&_swigt__p_HomogeneousMaterial, _p_HomogeneousMaterialTo_p_INamed, 0, 0},  {&_swigt__p_HomogeneousMagneticMaterial, _p_HomogeneousMagneticMaterialTo_p_INamed, 0, 0},  {&_swigt__p_FormFactorAnisoPyramid, _p_FormFactorAnisoPyramidTo_p_INamed, 0, 0},  {&_swigt__p_FormFactorPyramid, _p_FormFactorPyramidTo_p_INamed, 0, 0},  {&_swigt__p_FormFactorDecoratorDebyeWaller, _p_FormFactorDecoratorDebyeWallerTo_p_INamed, 0, 0},  {&_swigt__p_FormFactorRipple2, _p_FormFactorRipple2To_p_INamed, 0, 0},  {&_swigt__p_FormFactorEllipsoidalCylinder, _p_FormFactorEllipsoidalCylinderTo_p_INamed, 0, 0},  {&_swigt__p_FormFactorCylinder, _p_FormFactorCylinderTo_p_INamed, 0, 0},  {&_swigt__p_IParameterT_double_t, _p_IParameterT_double_tTo_p_INamed, 0, 0},  {&_swigt__p_DistributionGaussian, _p_DistributionGaussianTo_p_INamed, 0, 0},  {&_swigt__p_ResolutionFunction2DGaussian, _p_ResolutionFunction2DGaussianTo_p_INamed, 0, 0},  {&_swigt__p_ParticleComposition, _p_ParticleCompositionTo_p_INamed, 0, 0},  {&_swigt__p_FormFactorSphereUniformRadius, _p_FormFactorSphereUniformRadiusTo_p_INamed, 0, 0},  {&_swigt__p_Geometry__Line, _p_Geometry__LineTo_p_INamed, 0, 0},  {&_swigt__p_DistributionCosine, _p_DistributionCosineTo_p_INamed, 0, 0},  {&_swigt__p_FTDistribution1DCosine, _p_FTDistribution1DCosineTo_p_INamed, 0, 0},  {&_swigt__p_FTDistribution1DGate, _p_FTDistribution1DGateTo_p_INamed, 0, 0},  {&_swigt__p_FTDistribution2DVoigt, _p_FTDistribution2DVoigtTo_p_INamed, 0, 0},  {&_swigt__p_FTDecayFunction2DVoigt, _p_FTDecayFunction2DVoigtTo_p_INamed, 0, 0},  {&_swigt__p_FTDecayFunction1DCauchy, _p_FTDecayFunction1DCauchyTo_p_INamed, 0, 0},  {&_swigt__p_FTDistribution1DCauchy, _p_FTDistribution1DCauchyTo_p_INamed, 0, 0},  {&_swigt__p_FTDistribution2DCauchy, _p_FTDistribution2DCauchyTo_p_INamed, 0, 0},  {&_swigt__p_FTDecayFunction2DCauchy, _p_FTDecayFunction2DCauchyTo_p_INamed, 0, 0},  {&_swigt__p_IInterferenceFunction, _p_IInterferenceFunctionTo_p_INamed, 0, 0},  {&_swigt__p_FitObject, _p_FitObjectTo_p_INamed, 0, 0},  {&_swigt__p_FormFactorCone6, _p_FormFactorCone6To_p_INamed, 0, 0},  {&_swigt__p_FormFactorLongRipple1Gauss, _p_FormFactorLongRipple1GaussTo_p_INamed, 0, 0},  {&_swigt__p_Beam, _p_BeamTo_p_INamed, 0, 0},  {&_swigt__p_AdjustMinimizerStrategy, _p_AdjustMinimizerStrategyTo_p_INamed, 0, 0},  {&_swigt__p_IFitStrategy, _p_IFitStrategyTo_p_INamed, 0, 0},  {&_swigt__p_IFormFactorDecorator, _p_IFormFactorDecoratorTo_p_INamed, 0, 0},  {&_swigt__p_IParameterized, _p_IParameterizedTo_p_INamed, 0, 0},  {&_swigt__p_IRoughness, _p_IRoughnessTo_p_INamed, 0, 0},  {&_swigt__p_LayerRoughness, _p_LayerRoughnessTo_p_INamed, 0, 0},  {&_swigt__p_MesoCrystal, _p_MesoCrystalTo_p_INamed, 0, 0},  {&_swigt__p_FormFactorCrystal, _p_FormFactorCrystalTo_p_INamed, 0, 0},  {&_swigt__p_InterferenceFunction2DParaCrystal, _p_InterferenceFunction2DParaCrystalTo_p_INamed, 0, 0},  {&_swigt__p_InterferenceFunctionRadialParaCrystal, _p_InterferenceFunctionRadialParaCrystalTo_p_INamed, 0, 0},  {&_swigt__p_Crystal, _p_CrystalTo_p_INamed, 0, 0},  {&_swigt__p_IFTDecayFunction2D, _p_IFTDecayFunction2DTo_p_INamed, 0, 0},  {&_swigt__p_IFTDistribution2D, _p_IFTDistribution2DTo_p_INamed, 0, 0},  {&_swigt__p_IResolutionFunction2D, _p_IResolutionFunction2DTo_p_INamed, 0, 0},  {&_swigt__p_FormFactorWeighted, _p_FormFactorWeightedTo_p_INamed, 0, 0},  {&_swigt__p_RealParameter, _p_RealParameterTo_p_INamed, 0, 0},  {&_swigt__p_FormFactorLorentz, _p_FormFactorLorentzTo_p_INamed, 0, 0},  {&_swigt__p_FormFactorLongRipple2Lorentz, _p_FormFactorLongRipple2LorentzTo_p_INamed, 0, 0},  {&_swigt__p_FormFactorLongRipple1Lorentz, _p_FormFactorLongRipple1LorentzTo_p_INamed, 0, 0},  {&_swigt__p_FormFactorLongBoxLorentz, _p_FormFactorLongBoxLorentzTo_p_INamed, 0, 0},  {&_swigt__p_InterferenceFunction1DLattice, _p_InterferenceFunction1DLatticeTo_p_INamed, 0, 0},  {&_swigt__p_InterferenceFunction2DLattice, _p_InterferenceFunction2DLatticeTo_p_INamed, 0, 0},  {&_swigt__p_DistributionLorentz, _p_DistributionLorentzTo_p_INamed, 0, 0},  {&_swigt__p_FTDecayFunction1DTriangle, _p_FTDecayFunction1DTriangleTo_p_INamed, 0, 0},  {&_swigt__p_FTDistribution1DTriangle, _p_FTDistribution1DTriangleTo_p_INamed, 0, 0},  {&_swigt__p_RotationEuler, _p_RotationEulerTo_p_INamed, 0, 0},{0, 0, 0, 0}};
-static swig_cast_info _swigc__p_INoncopyable[] = {  {&_swigt__p_FormFactorBox, _p_FormFactorBoxTo_p_INoncopyable, 0, 0},  {&_swigt__p_FormFactorSphereLogNormalRadius, _p_FormFactorSphereLogNormalRadiusTo_p_INoncopyable, 0, 0},  {&_swigt__p_FormFactorSphereGaussianRadius, _p_FormFactorSphereGaussianRadiusTo_p_INoncopyable, 0, 0},  {&_swigt__p_MultiLayer, _p_MultiLayerTo_p_INoncopyable, 0, 0},  {&_swigt__p_ParticleDistribution, _p_ParticleDistributionTo_p_INoncopyable, 0, 0},  {&_swigt__p_InterferenceFunctionNone, _p_InterferenceFunctionNoneTo_p_INoncopyable, 0, 0},  {&_swigt__p_Geometry__Polygon, _p_Geometry__PolygonTo_p_INoncopyable, 0, 0},  {&_swigt__p_Geometry__Ellipse, _p_Geometry__EllipseTo_p_INoncopyable, 0, 0},  {&_swigt__p_ILayout, _p_ILayoutTo_p_INoncopyable, 0, 0},  {&_swigt__p_ParticleLayout, _p_ParticleLayoutTo_p_INoncopyable, 0, 0},  {&_swigt__p_FormFactorHemiEllipsoid, _p_FormFactorHemiEllipsoidTo_p_INoncopyable, 0, 0},  {&_swigt__p_IChiSquaredModule, _p_IChiSquaredModuleTo_p_INoncopyable, 0, 0},  {&_swigt__p_ChiSquaredModule, _p_ChiSquaredModuleTo_p_INoncopyable, 0, 0},  {&_swigt__p_Geometry__HorizontalLine, _p_Geometry__HorizontalLineTo_p_INoncopyable, 0, 0},  {&_swigt__p_FormFactorPrism3, _p_FormFactorPrism3To_p_INoncopyable, 0, 0},  {&_swigt__p_FormFactorTetrahedron, _p_FormFactorTetrahedronTo_p_INoncopyable, 0, 0},  {&_swigt__p_FormFactorPolyhedron, _p_FormFactorPolyhedronTo_p_INoncopyable, 0, 0},  {&_swigt__p_FormFactorCuboctahedron, _p_FormFactorCuboctahedronTo_p_INoncopyable, 0, 0},  {&_swigt__p_FormFactorDodecahedron, _p_FormFactorDodecahedronTo_p_INoncopyable, 0, 0},  {&_swigt__p_FormFactorIcosahedron, _p_FormFactorIcosahedronTo_p_INoncopyable, 0, 0},  {&_swigt__p_FormFactorPrism6, _p_FormFactorPrism6To_p_INoncopyable, 0, 0},  {&_swigt__p_GISASSimulation, _p_GISASSimulationTo_p_INoncopyable, 0, 0},  {&_swigt__p_Simulation, _p_SimulationTo_p_INoncopyable, 0, 0},  {&_swigt__p_OffSpecSimulation, _p_OffSpecSimulationTo_p_INoncopyable, 0, 0},  {&_swigt__p_SpecularSimulation, _p_SpecularSimulationTo_p_INoncopyable, 0, 0},  {&_swigt__p_ParticleCoreShell, _p_ParticleCoreShellTo_p_INoncopyable, 0, 0},  {&_swigt__p_FormFactorTruncatedSphere, _p_FormFactorTruncatedSphereTo_p_INoncopyable, 0, 0},  {&_swigt__p_FormFactorFullSphere, _p_FormFactorFullSphereTo_p_INoncopyable, 0, 0},  {&_swigt__p_IFormFactor, _p_IFormFactorTo_p_INoncopyable, 0, 0},  {&_swigt__p_ISample, _p_ISampleTo_p_INoncopyable, 0, 0},  {&_swigt__p_ICompositeSample, _p_ICompositeSampleTo_p_INoncopyable, 0, 0},  {&_swigt__p_FormFactorPolygonalSurface, _p_FormFactorPolygonalSurfaceTo_p_INoncopyable, 0, 0},  {&_swigt__p_FormFactorLongBoxGauss, _p_FormFactorLongBoxGaussTo_p_INoncopyable, 0, 0},  {&_swigt__p_FormFactorPolygonalPrism, _p_FormFactorPolygonalPrismTo_p_INoncopyable, 0, 0},  {&_swigt__p_FitSuiteObjects, _p_FitSuiteObjectsTo_p_INoncopyable, 0, 0},  {&_swigt__p_IRotation, _p_IRotationTo_p_INoncopyable, 0, 0},  {&_swigt__p_RotationX, _p_RotationXTo_p_INoncopyable, 0, 0},  {&_swigt__p_FormFactorTruncatedSpheroid, _p_FormFactorTruncatedSpheroidTo_p_INoncopyable, 0, 0},  {&_swigt__p_FormFactorFullSpheroid, _p_FormFactorFullSpheroidTo_p_INoncopyable, 0, 0},  {&_swigt__p_FormFactorTruncatedCube, _p_FormFactorTruncatedCubeTo_p_INoncopyable, 0, 0},  {&_swigt__p_RotationY, _p_RotationYTo_p_INoncopyable, 0, 0},  {&_swigt__p_Geometry__IShape2D, _p_Geometry__IShape2DTo_p_INoncopyable, 0, 0},  {&_swigt__p_RotationZ, _p_RotationZTo_p_INoncopyable, 0, 0},  {&_swigt__p_Geometry__Rectangle, _p_Geometry__RectangleTo_p_INoncopyable, 0, 0},  {&_swigt__p_FormFactorGauss, _p_FormFactorGaussTo_p_INoncopyable, 0, 0},  {&_swigt__p_FormFactorLongRipple2Gauss, _p_FormFactorLongRipple2GaussTo_p_INoncopyable, 0, 0},  {&_swigt__p_Geometry__VerticalLine, _p_Geometry__VerticalLineTo_p_INoncopyable, 0, 0},  {&_swigt__p_IFormFactorBorn, _p_IFormFactorBornTo_p_INoncopyable, 0, 0},  {&_swigt__p_IDetectorResolution, _p_IDetectorResolutionTo_p_INoncopyable, 0, 0},  {&_swigt__p_IClusteredParticles, _p_IClusteredParticlesTo_p_INoncopyable, 0, 0},  {&_swigt__p_IAbstractParticle, _p_IAbstractParticleTo_p_INoncopyable, 0, 0},  {&_swigt__p_IParticle, _p_IParticleTo_p_INoncopyable, 0, 0},  {&_swigt__p_Particle, _p_ParticleTo_p_INoncopyable, 0, 0},  {&_swigt__p_FormFactorTrivial, _p_FormFactorTrivialTo_p_INoncopyable, 0, 0},  {&_swigt__p_FormFactorCone, _p_FormFactorConeTo_p_INoncopyable, 0, 0},  {&_swigt__p_INoncopyable, 0, 0, 0},  {&_swigt__p_FormFactorRipple1, _p_FormFactorRipple1To_p_INoncopyable, 0, 0},  {&_swigt__p_Layer, _p_LayerTo_p_INoncopyable, 0, 0},  {&_swigt__p_FormFactorAnisoPyramid, _p_FormFactorAnisoPyramidTo_p_INoncopyable, 0, 0},  {&_swigt__p_FormFactorPyramid, _p_FormFactorPyramidTo_p_INoncopyable, 0, 0},  {&_swigt__p_FormFactorDecoratorDebyeWaller, _p_FormFactorDecoratorDebyeWallerTo_p_INoncopyable, 0, 0},  {&_swigt__p_FormFactorRipple2, _p_FormFactorRipple2To_p_INoncopyable, 0, 0},  {&_swigt__p_FormFactorEllipsoidalCylinder, _p_FormFactorEllipsoidalCylinderTo_p_INoncopyable, 0, 0},  {&_swigt__p_FormFactorCylinder, _p_FormFactorCylinderTo_p_INoncopyable, 0, 0},  {&_swigt__p_IParameterT_double_t, _p_IParameterT_double_tTo_p_INoncopyable, 0, 0},  {&_swigt__p_ParticleComposition, _p_ParticleCompositionTo_p_INoncopyable, 0, 0},  {&_swigt__p_FormFactorSphereUniformRadius, _p_FormFactorSphereUniformRadiusTo_p_INoncopyable, 0, 0},  {&_swigt__p_Geometry__Line, _p_Geometry__LineTo_p_INoncopyable, 0, 0},  {&_swigt__p_IInterferenceFunction, _p_IInterferenceFunctionTo_p_INoncopyable, 0, 0},  {&_swigt__p_FitObject, _p_FitObjectTo_p_INoncopyable, 0, 0},  {&_swigt__p_FormFactorCone6, _p_FormFactorCone6To_p_INoncopyable, 0, 0},  {&_swigt__p_FormFactorLongRipple1Gauss, _p_FormFactorLongRipple1GaussTo_p_INoncopyable, 0, 0},  {&_swigt__p_IFormFactorDecorator, _p_IFormFactorDecoratorTo_p_INoncopyable, 0, 0},  {&_swigt__p_IRoughness, _p_IRoughnessTo_p_INoncopyable, 0, 0},  {&_swigt__p_LayerRoughness, _p_LayerRoughnessTo_p_INoncopyable, 0, 0},  {&_swigt__p_InterferenceFunctionRadialParaCrystal, _p_InterferenceFunctionRadialParaCrystalTo_p_INoncopyable, 0, 0},  {&_swigt__p_InterferenceFunction2DParaCrystal, _p_InterferenceFunction2DParaCrystalTo_p_INoncopyable, 0, 0},  {&_swigt__p_Crystal, _p_CrystalTo_p_INoncopyable, 0, 0},  {&_swigt__p_MesoCrystal, _p_MesoCrystalTo_p_INoncopyable, 0, 0},  {&_swigt__p_FormFactorCrystal, _p_FormFactorCrystalTo_p_INoncopyable, 0, 0},  {&_swigt__p_FormFactorWeighted, _p_FormFactorWeightedTo_p_INoncopyable, 0, 0},  {&_swigt__p_RealParameter, _p_RealParameterTo_p_INoncopyable, 0, 0},  {&_swigt__p_FormFactorLorentz, _p_FormFactorLorentzTo_p_INoncopyable, 0, 0},  {&_swigt__p_FormFactorLongRipple2Lorentz, _p_FormFactorLongRipple2LorentzTo_p_INoncopyable, 0, 0},  {&_swigt__p_FormFactorLongRipple1Lorentz, _p_FormFactorLongRipple1LorentzTo_p_INoncopyable, 0, 0},  {&_swigt__p_FormFactorLongBoxLorentz, _p_FormFactorLongBoxLorentzTo_p_INoncopyable, 0, 0},  {&_swigt__p_InterferenceFunction1DLattice, _p_InterferenceFunction1DLatticeTo_p_INoncopyable, 0, 0},  {&_swigt__p_InterferenceFunction2DLattice, _p_InterferenceFunction2DLatticeTo_p_INoncopyable, 0, 0},  {&_swigt__p_RotationEuler, _p_RotationEulerTo_p_INoncopyable, 0, 0},  {&_swigt__p_ICloneable, _p_ICloneableTo_p_INoncopyable, 0, 0},{0, 0, 0, 0}};
+static swig_cast_info _swigc__p_INoncopyable[] = {  {&_swigt__p_FormFactorBox, _p_FormFactorBoxTo_p_INoncopyable, 0, 0},  {&_swigt__p_FormFactorSphereLogNormalRadius, _p_FormFactorSphereLogNormalRadiusTo_p_INoncopyable, 0, 0},  {&_swigt__p_FormFactorSphereGaussianRadius, _p_FormFactorSphereGaussianRadiusTo_p_INoncopyable, 0, 0},  {&_swigt__p_MultiLayer, _p_MultiLayerTo_p_INoncopyable, 0, 0},  {&_swigt__p_ParticleDistribution, _p_ParticleDistributionTo_p_INoncopyable, 0, 0},  {&_swigt__p_InterferenceFunctionNone, _p_InterferenceFunctionNoneTo_p_INoncopyable, 0, 0},  {&_swigt__p_Geometry__Polygon, _p_Geometry__PolygonTo_p_INoncopyable, 0, 0},  {&_swigt__p_IDetector2D, _p_IDetector2DTo_p_INoncopyable, 0, 0},  {&_swigt__p_Geometry__Ellipse, _p_Geometry__EllipseTo_p_INoncopyable, 0, 0},  {&_swigt__p_ParticleLayout, _p_ParticleLayoutTo_p_INoncopyable, 0, 0},  {&_swigt__p_ILayout, _p_ILayoutTo_p_INoncopyable, 0, 0},  {&_swigt__p_FormFactorHemiEllipsoid, _p_FormFactorHemiEllipsoidTo_p_INoncopyable, 0, 0},  {&_swigt__p_ChiSquaredModule, _p_ChiSquaredModuleTo_p_INoncopyable, 0, 0},  {&_swigt__p_IChiSquaredModule, _p_IChiSquaredModuleTo_p_INoncopyable, 0, 0},  {&_swigt__p_Geometry__HorizontalLine, _p_Geometry__HorizontalLineTo_p_INoncopyable, 0, 0},  {&_swigt__p_RectangularDetector, _p_RectangularDetectorTo_p_INoncopyable, 0, 0},  {&_swigt__p_IsGISAXSDetector, _p_IsGISAXSDetectorTo_p_INoncopyable, 0, 0},  {&_swigt__p_SphericalDetector, _p_SphericalDetectorTo_p_INoncopyable, 0, 0},  {&_swigt__p_FormFactorPrism3, _p_FormFactorPrism3To_p_INoncopyable, 0, 0},  {&_swigt__p_FormFactorTetrahedron, _p_FormFactorTetrahedronTo_p_INoncopyable, 0, 0},  {&_swigt__p_FormFactorPolyhedron, _p_FormFactorPolyhedronTo_p_INoncopyable, 0, 0},  {&_swigt__p_FormFactorCuboctahedron, _p_FormFactorCuboctahedronTo_p_INoncopyable, 0, 0},  {&_swigt__p_FormFactorDodecahedron, _p_FormFactorDodecahedronTo_p_INoncopyable, 0, 0},  {&_swigt__p_FormFactorIcosahedron, _p_FormFactorIcosahedronTo_p_INoncopyable, 0, 0},  {&_swigt__p_FormFactorPrism6, _p_FormFactorPrism6To_p_INoncopyable, 0, 0},  {&_swigt__p_GISASSimulation, _p_GISASSimulationTo_p_INoncopyable, 0, 0},  {&_swigt__p_Simulation, _p_SimulationTo_p_INoncopyable, 0, 0},  {&_swigt__p_OffSpecSimulation, _p_OffSpecSimulationTo_p_INoncopyable, 0, 0},  {&_swigt__p_SpecularSimulation, _p_SpecularSimulationTo_p_INoncopyable, 0, 0},  {&_swigt__p_ParticleCoreShell, _p_ParticleCoreShellTo_p_INoncopyable, 0, 0},  {&_swigt__p_FormFactorFullSphere, _p_FormFactorFullSphereTo_p_INoncopyable, 0, 0},  {&_swigt__p_FormFactorTruncatedSphere, _p_FormFactorTruncatedSphereTo_p_INoncopyable, 0, 0},  {&_swigt__p_IFormFactor, _p_IFormFactorTo_p_INoncopyable, 0, 0},  {&_swigt__p_ISample, _p_ISampleTo_p_INoncopyable, 0, 0},  {&_swigt__p_FormFactorPolygonalSurface, _p_FormFactorPolygonalSurfaceTo_p_INoncopyable, 0, 0},  {&_swigt__p_ICompositeSample, _p_ICompositeSampleTo_p_INoncopyable, 0, 0},  {&_swigt__p_FormFactorLongBoxGauss, _p_FormFactorLongBoxGaussTo_p_INoncopyable, 0, 0},  {&_swigt__p_FormFactorPolygonalPrism, _p_FormFactorPolygonalPrismTo_p_INoncopyable, 0, 0},  {&_swigt__p_FitSuiteObjects, _p_FitSuiteObjectsTo_p_INoncopyable, 0, 0},  {&_swigt__p_IRotation, _p_IRotationTo_p_INoncopyable, 0, 0},  {&_swigt__p_RotationX, _p_RotationXTo_p_INoncopyable, 0, 0},  {&_swigt__p_FormFactorTruncatedSpheroid, _p_FormFactorTruncatedSpheroidTo_p_INoncopyable, 0, 0},  {&_swigt__p_FormFactorFullSpheroid, _p_FormFactorFullSpheroidTo_p_INoncopyable, 0, 0},  {&_swigt__p_FormFactorTruncatedCube, _p_FormFactorTruncatedCubeTo_p_INoncopyable, 0, 0},  {&_swigt__p_RotationY, _p_RotationYTo_p_INoncopyable, 0, 0},  {&_swigt__p_Geometry__IShape2D, _p_Geometry__IShape2DTo_p_INoncopyable, 0, 0},  {&_swigt__p_RotationZ, _p_RotationZTo_p_INoncopyable, 0, 0},  {&_swigt__p_Geometry__Rectangle, _p_Geometry__RectangleTo_p_INoncopyable, 0, 0},  {&_swigt__p_FormFactorGauss, _p_FormFactorGaussTo_p_INoncopyable, 0, 0},  {&_swigt__p_FormFactorLongRipple2Gauss, _p_FormFactorLongRipple2GaussTo_p_INoncopyable, 0, 0},  {&_swigt__p_Geometry__VerticalLine, _p_Geometry__VerticalLineTo_p_INoncopyable, 0, 0},  {&_swigt__p_IFormFactorBorn, _p_IFormFactorBornTo_p_INoncopyable, 0, 0},  {&_swigt__p_IDetectorResolution, _p_IDetectorResolutionTo_p_INoncopyable, 0, 0},  {&_swigt__p_IClusteredParticles, _p_IClusteredParticlesTo_p_INoncopyable, 0, 0},  {&_swigt__p_Particle, _p_ParticleTo_p_INoncopyable, 0, 0},  {&_swigt__p_IParticle, _p_IParticleTo_p_INoncopyable, 0, 0},  {&_swigt__p_IAbstractParticle, _p_IAbstractParticleTo_p_INoncopyable, 0, 0},  {&_swigt__p_FormFactorTrivial, _p_FormFactorTrivialTo_p_INoncopyable, 0, 0},  {&_swigt__p_FormFactorCone, _p_FormFactorConeTo_p_INoncopyable, 0, 0},  {&_swigt__p_INoncopyable, 0, 0, 0},  {&_swigt__p_FormFactorRipple1, _p_FormFactorRipple1To_p_INoncopyable, 0, 0},  {&_swigt__p_Layer, _p_LayerTo_p_INoncopyable, 0, 0},  {&_swigt__p_FormFactorAnisoPyramid, _p_FormFactorAnisoPyramidTo_p_INoncopyable, 0, 0},  {&_swigt__p_FormFactorPyramid, _p_FormFactorPyramidTo_p_INoncopyable, 0, 0},  {&_swigt__p_FormFactorDecoratorDebyeWaller, _p_FormFactorDecoratorDebyeWallerTo_p_INoncopyable, 0, 0},  {&_swigt__p_FormFactorRipple2, _p_FormFactorRipple2To_p_INoncopyable, 0, 0},  {&_swigt__p_FormFactorEllipsoidalCylinder, _p_FormFactorEllipsoidalCylinderTo_p_INoncopyable, 0, 0},  {&_swigt__p_FormFactorCylinder, _p_FormFactorCylinderTo_p_INoncopyable, 0, 0},  {&_swigt__p_IParameterT_double_t, _p_IParameterT_double_tTo_p_INoncopyable, 0, 0},  {&_swigt__p_ParticleComposition, _p_ParticleCompositionTo_p_INoncopyable, 0, 0},  {&_swigt__p_FormFactorSphereUniformRadius, _p_FormFactorSphereUniformRadiusTo_p_INoncopyable, 0, 0},  {&_swigt__p_Geometry__Line, _p_Geometry__LineTo_p_INoncopyable, 0, 0},  {&_swigt__p_IInterferenceFunction, _p_IInterferenceFunctionTo_p_INoncopyable, 0, 0},  {&_swigt__p_FitObject, _p_FitObjectTo_p_INoncopyable, 0, 0},  {&_swigt__p_FormFactorCone6, _p_FormFactorCone6To_p_INoncopyable, 0, 0},  {&_swigt__p_FormFactorLongRipple1Gauss, _p_FormFactorLongRipple1GaussTo_p_INoncopyable, 0, 0},  {&_swigt__p_IFormFactorDecorator, _p_IFormFactorDecoratorTo_p_INoncopyable, 0, 0},  {&_swigt__p_IRoughness, _p_IRoughnessTo_p_INoncopyable, 0, 0},  {&_swigt__p_LayerRoughness, _p_LayerRoughnessTo_p_INoncopyable, 0, 0},  {&_swigt__p_Crystal, _p_CrystalTo_p_INoncopyable, 0, 0},  {&_swigt__p_InterferenceFunctionRadialParaCrystal, _p_InterferenceFunctionRadialParaCrystalTo_p_INoncopyable, 0, 0},  {&_swigt__p_InterferenceFunction2DParaCrystal, _p_InterferenceFunction2DParaCrystalTo_p_INoncopyable, 0, 0},  {&_swigt__p_MesoCrystal, _p_MesoCrystalTo_p_INoncopyable, 0, 0},  {&_swigt__p_FormFactorCrystal, _p_FormFactorCrystalTo_p_INoncopyable, 0, 0},  {&_swigt__p_FormFactorWeighted, _p_FormFactorWeightedTo_p_INoncopyable, 0, 0},  {&_swigt__p_RealParameter, _p_RealParameterTo_p_INoncopyable, 0, 0},  {&_swigt__p_FormFactorLorentz, _p_FormFactorLorentzTo_p_INoncopyable, 0, 0},  {&_swigt__p_FormFactorLongRipple2Lorentz, _p_FormFactorLongRipple2LorentzTo_p_INoncopyable, 0, 0},  {&_swigt__p_FormFactorLongRipple1Lorentz, _p_FormFactorLongRipple1LorentzTo_p_INoncopyable, 0, 0},  {&_swigt__p_FormFactorLongBoxLorentz, _p_FormFactorLongBoxLorentzTo_p_INoncopyable, 0, 0},  {&_swigt__p_InterferenceFunction1DLattice, _p_InterferenceFunction1DLatticeTo_p_INoncopyable, 0, 0},  {&_swigt__p_InterferenceFunction2DLattice, _p_InterferenceFunction2DLatticeTo_p_INoncopyable, 0, 0},  {&_swigt__p_RotationEuler, _p_RotationEulerTo_p_INoncopyable, 0, 0},  {&_swigt__p_ICloneable, _p_ICloneableTo_p_INoncopyable, 0, 0},{0, 0, 0, 0}};
 static swig_cast_info _swigc__p_IObservable[] = {  {&_swigt__p_IObservable, 0, 0, 0},  {&_swigt__p_FitSuite, _p_FitSuiteTo_p_IObservable, 0, 0},{0, 0, 0, 0}};
 static swig_cast_info _swigc__p_IObserver[] = {  {&_swigt__p_IObserver, 0, 0, 0},  {&_swigt__p_IFitObserver, _p_IFitObserverTo_p_IObserver, 0, 0},{0, 0, 0, 0}};
 static swig_cast_info _swigc__p_IParameterT_double_t[] = {  {&_swigt__p_IParameterT_double_t, 0, 0, 0},  {&_swigt__p_RealParameter, _p_RealParameterTo_p_IParameterT_double_t, 0, 0},{0, 0, 0, 0}};
@@ -116229,8 +116675,10 @@ static swig_cast_info _swigc__p_RotationX[] = {  {&_swigt__p_RotationX, 0, 0, 0}
 static swig_cast_info _swigc__p_RotationY[] = {  {&_swigt__p_RotationY, 0, 0, 0},{0, 0, 0, 0}};
 static swig_cast_info _swigc__p_RotationZ[] = {  {&_swigt__p_RotationZ, 0, 0, 0},{0, 0, 0, 0}};
 static swig_cast_info _swigc__p_SafePointerVectorT_IParticle_const_t[] = {  {&_swigt__p_SafePointerVectorT_IParticle_const_t, 0, 0, 0},{0, 0, 0, 0}};
+static swig_cast_info _swigc__p_SampleBuilderFactory[] = {  {&_swigt__p_SampleBuilderFactory, 0, 0, 0},{0, 0, 0, 0}};
 static swig_cast_info _swigc__p_SimpleSelectionRule[] = {  {&_swigt__p_SimpleSelectionRule, 0, 0, 0},{0, 0, 0, 0}};
 static swig_cast_info _swigc__p_Simulation[] = {  {&_swigt__p_Simulation, 0, 0, 0},  {&_swigt__p_GISASSimulation, _p_GISASSimulationTo_p_Simulation, 0, 0},  {&_swigt__p_OffSpecSimulation, _p_OffSpecSimulationTo_p_Simulation, 0, 0},{0, 0, 0, 0}};
+static swig_cast_info _swigc__p_SimulationFactory[] = {  {&_swigt__p_SimulationFactory, 0, 0, 0},{0, 0, 0, 0}};
 static swig_cast_info _swigc__p_SimulationOptions[] = {  {&_swigt__p_SimulationOptions, 0, 0, 0},{0, 0, 0, 0}};
 static swig_cast_info _swigc__p_SpecularSimulation[] = {  {&_swigt__p_SpecularSimulation, 0, 0, 0},{0, 0, 0, 0}};
 static swig_cast_info _swigc__p_SphericalDetector[] = {  {&_swigt__p_SphericalDetector, 0, 0, 0},  {&_swigt__p_IsGISAXSDetector, _p_IsGISAXSDetectorTo_p_SphericalDetector, 0, 0},{0, 0, 0, 0}};
@@ -116524,8 +116972,10 @@ static swig_cast_info *swig_cast_initial[] = {
   _swigc__p_RotationY,
   _swigc__p_RotationZ,
   _swigc__p_SafePointerVectorT_IParticle_const_t,
+  _swigc__p_SampleBuilderFactory,
   _swigc__p_SimpleSelectionRule,
   _swigc__p_Simulation,
+  _swigc__p_SimulationFactory,
   _swigc__p_SimulationOptions,
   _swigc__p_SpecularSimulation,
   _swigc__p_SphericalDetector,
diff --git a/auto/Wrap/libBornAgainFit_wrap.cpp b/auto/Wrap/libBornAgainFit_wrap.cpp
index 7a13fe3e65c56630bdd898b91f569d9132cbaba6..537e535c25b861134e3681ea11ecc411e5c22366 100644
--- a/auto/Wrap/libBornAgainFit_wrap.cpp
+++ b/auto/Wrap/libBornAgainFit_wrap.cpp
@@ -5627,7 +5627,7 @@ SWIG_AsVal_std_complex_Sl_double_Sg_  (PyObject *o, std::complex<double>* val)
 
 
 SWIGINTERNINLINE PyObject*
-SWIG_From_std_complex_Sl_double_Sg_  (/*@SWIG:/usr/share/swig3.0/typemaps/swigmacros.swg,104,%ifcplusplus@*/
+SWIG_From_std_complex_Sl_double_Sg_  (/*@SWIG:/home/pospelov/software/local/share/swig/3.0.8/typemaps/swigmacros.swg,104,%ifcplusplus@*/
 
 const std::complex<double>&
 
diff --git a/dev-tools/log/perf_history.txt b/dev-tools/log/perf_history.txt
index 78edef7fc6dba20cd358fb07a96869d6e745782a..7b0db4a6e1be6e078eda625159eaf1e65f2859d6 100644
--- a/dev-tools/log/perf_history.txt
+++ b/dev-tools/log/perf_history.txt
@@ -502,3 +502,20 @@
 | date                | hostname  | sysinfo      | python | total cpu | total wall | MultiLayer | CylindersInDWBA | RotatedPyramids | CoreShell | SquareLattice | RadialParaCrystal | HexParaCrystal | SSCA   | Mesocrystal | PolMagCyl | Custom FF |
 | 2016-05-25 12:50:59 | jcnsopc22 | Linux x86_64 | 2.7    | 126.2680  | 19.0747    | 2.9620     | 0.7566          | 3.5780          | 0.5746    | 2.2319        | 0.7519            | 2.6683         | 1.0811 | 1.7840      | 1.8264    | 0.8599    |
 
+
+| date                | hostname | sysinfo      | python | total cpu | total wall | MultiLayer | CylindersInDWBA | RotatedPyramids | CoreShell | SquareLattice | RadialParaCrystal | HexParaCrystal | SSCA   | Mesocrystal | PolMagCyl | Custom FF |
+| 2016-10-12 14:58:56 | scgsun   | Linux x86_64 | 2.7    | 121.8000  | 18.9031    | 2.8314     | 0.6853          | 3.3220          | 0.5178    | 2.2989        | 0.7084            | 3.1807         | 1.0054 | 1.7599      | 1.7037    | 0.8896    |
+| 2016-10-12 15:00:12 | scgsun   | Linux x86_64 | 2.7    | 121.7560  | 19.1301    | 2.9637     | 0.6960          | 3.3558          | 0.5273    | 2.3114        | 0.7187            | 3.1900         | 1.0233 | 1.7531      | 1.7332    | 0.8575    |
+
+# removed extra call of updateIntensityMap()
+| date                | hostname | sysinfo      | python | total cpu | total wall | MultiLayer | CylindersInDWBA | RotatedPyramids | CoreShell | SquareLattice | RadialParaCrystal | HexParaCrystal | SSCA   | Mesocrystal | PolMagCyl | Custom FF |
+| 2016-10-12 15:08:03 | scgsun   | Linux x86_64 | 2.7    | 122.8240  | 21.1832    | 3.8394     | 0.7716          | 3.4871          | 0.6384    | 2.5385        | 0.8021            | 3.3587         | 1.1122 | 1.8113      | 1.8655    | 0.9583    |
+| 2016-10-12 15:15:12 | scgsun   | Linux x86_64 | 2.7    | 121.6320  | 18.9844    | 2.8292     | 0.6947          | 3.3337          | 0.5314    | 2.3015        | 0.7091            | 3.2037         | 1.0140 | 1.7533      | 1.7217    | 0.8920    |
+
+
+# after the switch to std::move in SimulationElement
+| 2016-10-14 08:51:54 | scgsun   | Linux x86_64 | 2.7    | 122.8880  | 19.3683    | 2.8577     | 0.7296          | 3.3728          | 0.5629    | 2.3569        | 0.7555            | 3.3065         | 1.0475 | 1.7642      | 1.7467    | 0.8680    |
+
+# after switch to SimulationAreaIterator
+| 2016-10-17 11:28:02 | scgsun   | Linux x86_64 | 2.7    | 122.3960  | 19.9584    | 3.0328     | 0.7849          | 3.4156          | 0.5976    | 2.3843        | 0.7670            | 3.4331         | 1.0687 | 1.7839      | 1.8056    | 0.8850    |
+