diff --git a/Device/Detector/IDetector2D.cpp b/Device/Detector/IDetector2D.cpp
index 35b074e3a210f4263e5a474de6aff9ff922083e2..b307ceecf6916f45480085b0f0e442c29351c6c7 100644
--- a/Device/Detector/IDetector2D.cpp
+++ b/Device/Detector/IDetector2D.cpp
@@ -14,11 +14,13 @@
 
 #include "Device/Detector/IDetector2D.h"
 #include "Base/Const/Units.h"
+#include "Base/Axis/IAxis.h"
 #include "Device/Beam/Beam.h"
 #include "Device/Detector/DetectorContext.h"
 #include "Device/Mask/DetectorMask.h"
 #include "Device/Mask/InfinitePlane.h"
 #include "Resample/Element/DiffuseElement.h"
+#include "Base/Util/Assert.h"
 
 namespace {
 
diff --git a/Device/Mask/DetectorMask.cpp b/Device/Mask/DetectorMask.cpp
index de536bcfdd2f64225ca2a341850e4a1be036fb33..aede37399f16834f34552fcd1806410a563a2842 100644
--- a/Device/Mask/DetectorMask.cpp
+++ b/Device/Mask/DetectorMask.cpp
@@ -16,19 +16,28 @@
 #include "Base/Axis/IAxis.h"
 #include "Device/Histo/Histogram2D.h"
 #include "Device/Mask/IShape2D.h"
+#include "Device/Data/Powerfield.h"
+
+MaskPattern::MaskPattern(IShape2D* shape_, bool doMask_) : shape(shape_), doMask(doMask_) {}
+MaskPattern::~MaskPattern() { delete shape; }
+MaskPattern* MaskPattern::clone() const { return new MaskPattern(shape->clone(), doMask); }
+
 
 DetectorMask::DetectorMask()
-    : m_number_of_masked_channels(0)
+    : m_masked(new Powerfield<bool>)
+    , m_number_of_masked_channels(0)
 {
 }
 
 DetectorMask::DetectorMask(const IAxis& xAxis, const IAxis& yAxis)
+    : DetectorMask()
 {
-    ASSERT(m_shapes.size() == m_mask_of_shape.size());
-    m_mask_data.clear();
+    m_masked->clear();
+
+    m_masked->addAxis(xAxis);
+    m_masked->addAxis(yAxis);
 
-    m_mask_data.addAxis(xAxis);
-    m_mask_data.addAxis(yAxis);
+//    m_masked.reset(new Powerfield<bool>(xAxis, yAxis));
 
     process_masks();
 }
@@ -36,95 +45,78 @@ DetectorMask::DetectorMask(const IAxis& xAxis, const IAxis& yAxis)
 DetectorMask::~DetectorMask() = default;
 
 DetectorMask::DetectorMask(const DetectorMask& other)
-    : m_shapes(other.m_shapes)
-    , m_mask_of_shape(other.m_mask_of_shape)
+    : m_stack(other.m_stack)
+    , m_masked(other.m_masked->clone())
     , m_number_of_masked_channels(other.m_number_of_masked_channels)
 {
-    m_mask_data.copyFrom(other.m_mask_data);
+    m_masked->copyFrom(*other.m_masked);
 }
 
 DetectorMask& DetectorMask::operator=(const DetectorMask& other)
 {
     if (this != &other) {
-        m_shapes = other.m_shapes;
-        m_mask_of_shape = other.m_mask_of_shape;
-        m_mask_data.copyFrom(other.m_mask_data);
+        m_stack = other.m_stack;
+        m_masked.reset(other.m_masked->clone());
         m_number_of_masked_channels = other.m_number_of_masked_channels;
-        //        DetectorMask tmp(other);
-        //        tmp.swapContent(*this);
     }
     return *this;
 }
 
 void DetectorMask::addMask(const IShape2D& shape, bool mask_value)
 {
-    m_shapes.emplace_back(shape.clone());
-    m_mask_of_shape.push_back(mask_value);
-    m_mask_data.clear();
+    m_stack.emplace_back(new MaskPattern(shape.clone(), mask_value));
+    m_masked->clear();
     m_number_of_masked_channels = 0;
 }
 
 void DetectorMask::initMaskData(const IAxis& xAxis, const IAxis& yAxis)
 {
-    ASSERT(m_shapes.size() == m_mask_of_shape.size());
-    m_mask_data.clear();
+    m_masked->clear();
 
-    m_mask_data.addAxis(xAxis);
-    m_mask_data.addAxis(yAxis);
+    m_masked->addAxis(xAxis);
+    m_masked->addAxis(yAxis);
 
     process_masks();
 }
 
 bool DetectorMask::isMasked(size_t index) const
 {
-    return m_number_of_masked_channels == 0 ? false : m_mask_data[index];
-}
-
-Histogram2D* DetectorMask::createHistogram() const
-{
-    Powerfield<double> data;
-    data.copyShapeFrom(m_mask_data);
-    for (size_t i = 0; i < m_mask_data.getAllocatedSize(); ++i)
-        data[i] = static_cast<double>(m_mask_data[i]);
-    return dynamic_cast<Histogram2D*>(IHistogram::createHistogram(data));
+    return m_number_of_masked_channels == 0 ? false : (*m_masked)[index];
 }
 
 bool DetectorMask::hasMasks() const
 {
-    return !m_shapes.empty();
+    return !m_stack.empty();
 }
 
 size_t DetectorMask::numberOfMasks() const
 {
-    return m_shapes.size();
+    return m_stack.size();
 }
 
-const IShape2D* DetectorMask::getMaskShape(size_t mask_index, bool& mask_value) const
+const MaskPattern* DetectorMask::patternAt(size_t iMask) const
 {
-    if (mask_index >= numberOfMasks())
-        return nullptr;
-    mask_value = m_mask_of_shape[mask_index];
-    return m_shapes[mask_index];
+    return m_stack.at(iMask);
 }
 
 void DetectorMask::process_masks()
 {
-    m_mask_data.setAllTo(false);
-    if (!!m_shapes.empty())
+    m_masked->setAllTo(false);
+    if (!!m_stack.empty())
         return;
 
     m_number_of_masked_channels = 0;
-    for (size_t index = 0; index < m_mask_data.getAllocatedSize(); ++index) {
-        Bin1D binx = m_mask_data.getAxisBin(index, 0);
-        Bin1D biny = m_mask_data.getAxisBin(index, 1);
+    for (size_t index = 0; index < m_masked->getAllocatedSize(); ++index) {
+        Bin1D binx = m_masked->getAxisBin(index, 0);
+        Bin1D biny = m_masked->getAxisBin(index, 1);
         // setting mask to the data starting from last shape added
         bool is_masked(false);
-        for (size_t i_shape = m_shapes.size(); i_shape > 0; --i_shape) {
-            const IShape2D* const shape = m_shapes[i_shape - 1];
-            if (shape->contains(binx, biny)) {
-                if (m_mask_of_shape[i_shape - 1])
+        for (size_t k = m_stack.size(); k > 0; --k) {
+            const MaskPattern* const pat = m_stack[k - 1];
+            if (pat->shape->contains(binx, biny)) {
+                if (pat->doMask)
                     is_masked = true;
-                m_mask_data[index] = m_mask_of_shape[i_shape - 1];
+                (*m_masked)[index] = pat->doMask;
                 break; // index is covered by the shape, stop looking further
             }
         }
diff --git a/Device/Mask/DetectorMask.h b/Device/Mask/DetectorMask.h
index ea63d292a47c5f73116cf72bc9f14d16c2ccfcfa..762e33269b3a5e5743b5ca1260451da3a2af29fe 100644
--- a/Device/Mask/DetectorMask.h
+++ b/Device/Mask/DetectorMask.h
@@ -15,7 +15,8 @@
 #ifndef BORNAGAIN_DEVICE_MASK_DETECTORMASK_H
 #define BORNAGAIN_DEVICE_MASK_DETECTORMASK_H
 
-#include "Device/Data/Powerfield.h"
+#include <memory>
+
 #ifndef SWIG
 #include "Base/Types/OwningVector.h"
 #endif
@@ -27,6 +28,16 @@ class IShape2D;
 template <class T>
 class Powerfield;
 
+class MaskPattern {
+public:
+    MaskPattern(IShape2D* shape_, bool doMask_);
+    MaskPattern(const MaskPattern&) = delete;
+    ~MaskPattern();
+    MaskPattern* clone() const;
+    IShape2D* shape; // owning
+    bool doMask;
+};
+
 //! Collection of detector masks.
 //! @ingroup detector
 
@@ -49,9 +60,7 @@ public:
 
     bool isMasked(size_t index) const;
 
-    const Powerfield<bool>* getMaskData() const { return &m_mask_data; }
-
-    Histogram2D* createHistogram() const;
+    const Powerfield<bool>* getMaskData() const { return m_masked.get(); }
 
     //! Returns true if has masks
     bool hasMasks() const;
@@ -60,16 +69,18 @@ public:
 
     size_t numberOfMasks() const;
 
-    const IShape2D* getMaskShape(size_t mask_index, bool& mask_value) const;
+    const MaskPattern* patternAt(size_t iMask) const;
 
 private:
     void process_masks();
 
+    // primary data:
 #ifndef SWIG
-    OwningVector<IShape2D> m_shapes;
+    OwningVector<MaskPattern> m_stack;
 #endif
-    std::vector<bool> m_mask_of_shape;
-    Powerfield<bool> m_mask_data;
+
+    // cached secondary data:
+    std::unique_ptr<Powerfield<bool>> m_masked;
     int m_number_of_masked_channels;
 };
 
diff --git a/GUI/View/FromDomain/FromDomain.cpp b/GUI/View/FromDomain/FromDomain.cpp
index 9162ad9ab2202d72abb329642c33c78a20da0fd0..e569f7599ea2426822bd1f80c582548b163f8908 100644
--- a/GUI/View/FromDomain/FromDomain.cpp
+++ b/GUI/View/FromDomain/FromDomain.cpp
@@ -643,8 +643,9 @@ void GUI::Transform::FromDomain::setMaskContainer(MaskItems* destMaskItems,
 {
     const auto* detectorMask = detector.detectorMask();
     for (size_t i_mask = 0; i_mask < detectorMask->numberOfMasks(); ++i_mask) {
-        bool mask_value(false);
-        const IShape2D* shape = detectorMask->getMaskShape(i_mask, mask_value);
+        const MaskPattern* pat = detectorMask->patternAt(i_mask);
+        IShape2D* shape = pat->shape;
+        bool mask_value = pat->doMask;
 
         if (const auto* ellipse = dynamic_cast<const Ellipse*>(shape)) {
             auto* ellipseItem = new EllipseItem();
diff --git a/Sim/Export/SimulationToPython.cpp b/Sim/Export/SimulationToPython.cpp
index 2eeb1c464005d6ed7591a569bf857be3c97be59e..dfd4239a3d8d42b1588a0475a036731487c72daa 100644
--- a/Sim/Export/SimulationToPython.cpp
+++ b/Sim/Export/SimulationToPython.cpp
@@ -362,8 +362,9 @@ std::string defineMasks(const ISimulation* simulation)
     if (detectorMask && detectorMask->hasMasks()) {
         result << "\n";
         for (size_t i_mask = 0; i_mask < detectorMask->numberOfMasks(); ++i_mask) {
-            bool mask_value(false);
-            const IShape2D* shape = detectorMask->getMaskShape(i_mask, mask_value);
+            const MaskPattern* pat = detectorMask->patternAt(i_mask);
+            IShape2D* shape = pat->shape;
+            bool mask_value = pat->doMask;
             result << Py::Fmt2::representShape2D(indent(), shape, mask_value, printFunc(detector));
         }
         result << "\n";
diff --git a/Tests/Unit/Device/DetectorMaskTest.cpp b/Tests/Unit/Device/DetectorMaskTest.cpp
index 25c7b4bf4b1800fbbf0a271e84b25daf3b170f19..540de4a0724f45f895051e250ea03199d61a8515 100644
--- a/Tests/Unit/Device/DetectorMaskTest.cpp
+++ b/Tests/Unit/Device/DetectorMaskTest.cpp
@@ -2,6 +2,7 @@
 #include "Device/Detector/SphericalDetector.h"
 #include "Device/Mask/Polygon.h"
 #include "Tests/GTestWrapper/google_test.h"
+#include "Device/Data/Powerfield.h"
 #include <memory>
 
 class DetectorMaskTest : public ::testing::Test {
diff --git a/auto/Wrap/doxygenDevice.i b/auto/Wrap/doxygenDevice.i
index 1eb9c324bc3380094bb92510ea70a5332f536a6a..02d761d73d08a55a7f1e77a954024e9cdfccd66f 100644
--- a/auto/Wrap/doxygenDevice.i
+++ b/auto/Wrap/doxygenDevice.i
@@ -442,9 +442,6 @@ Init the map of masks for the given detector plane.
 %feature("docstring")  DetectorMask::getMaskData "const Powerfield<bool>* DetectorMask::getMaskData() const
 ";
 
-%feature("docstring")  DetectorMask::createHistogram "Histogram2D * DetectorMask::createHistogram() const
-";
-
 %feature("docstring")  DetectorMask::hasMasks "bool DetectorMask::hasMasks() const
 
 Returns true if has masks. 
@@ -456,7 +453,7 @@ Returns true if has masks.
 %feature("docstring")  DetectorMask::numberOfMasks "size_t DetectorMask::numberOfMasks() const
 ";
 
-%feature("docstring")  DetectorMask::getMaskShape "const IShape2D * DetectorMask::getMaskShape(size_t mask_index, bool &mask_value) const
+%feature("docstring")  DetectorMask::patternAt "const MaskPattern * DetectorMask::patternAt(size_t iMask) const
 ";
 
 
@@ -1884,6 +1881,22 @@ C++ includes: LLData.h
 ";
 
 
+// File: classMaskPattern.xml
+%feature("docstring") MaskPattern "";
+
+%feature("docstring")  MaskPattern::MaskPattern "MaskPattern::MaskPattern(IShape2D *shape_, bool doMask_)
+";
+
+%feature("docstring")  MaskPattern::MaskPattern "MaskPattern::MaskPattern(const MaskPattern &)=delete
+";
+
+%feature("docstring")  MaskPattern::~MaskPattern "MaskPattern::~MaskPattern()
+";
+
+%feature("docstring")  MaskPattern::clone "MaskPattern * MaskPattern::clone() const
+";
+
+
 // File: classOffSpecularCoordinates.xml
 %feature("docstring") OffSpecularCoordinates "
 
diff --git a/auto/Wrap/libBornAgainDevice.py b/auto/Wrap/libBornAgainDevice.py
index 707ea5b481273471d7fc975073e8ebd383328fe8..4b6dfd76ee5ea113a85f9eae0b579fbdfb79d447 100644
--- a/auto/Wrap/libBornAgainDevice.py
+++ b/auto/Wrap/libBornAgainDevice.py
@@ -3576,6 +3576,34 @@ class Axes(object):
 # Register Axes in _libBornAgainDevice:
 _libBornAgainDevice.Axes_swigregister(Axes)
 
+class MaskPattern(object):
+    r"""Proxy of C++ MaskPattern class."""
+
+    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
+    __repr__ = _swig_repr
+
+    def __init__(self, shape_, doMask_):
+        r"""
+        __init__(MaskPattern self, IShape2D shape_, bool doMask_) -> MaskPattern
+        MaskPattern::MaskPattern(const MaskPattern &)=delete
+
+        """
+        _libBornAgainDevice.MaskPattern_swiginit(self, _libBornAgainDevice.new_MaskPattern(shape_, doMask_))
+    __swig_destroy__ = _libBornAgainDevice.delete_MaskPattern
+
+    def clone(self):
+        r"""
+        clone(MaskPattern self) -> MaskPattern
+        MaskPattern * MaskPattern::clone() const
+
+        """
+        return _libBornAgainDevice.MaskPattern_clone(self)
+    shape = property(_libBornAgainDevice.MaskPattern_shape_get, _libBornAgainDevice.MaskPattern_shape_set, doc=r"""shape : p.IShape2D""")
+    doMask = property(_libBornAgainDevice.MaskPattern_doMask_get, _libBornAgainDevice.MaskPattern_doMask_set, doc=r"""doMask : bool""")
+
+# Register MaskPattern in _libBornAgainDevice:
+_libBornAgainDevice.MaskPattern_swigregister(MaskPattern)
+
 class DetectorMask(object):
     r"""
 
@@ -3645,14 +3673,6 @@ class DetectorMask(object):
         """
         return _libBornAgainDevice.DetectorMask_getMaskData(self)
 
-    def createHistogram(self):
-        r"""
-        createHistogram(DetectorMask self) -> Histogram2D
-        Histogram2D * DetectorMask::createHistogram() const
-
-        """
-        return _libBornAgainDevice.DetectorMask_createHistogram(self)
-
     def hasMasks(self):
         r"""
         hasMasks(DetectorMask self) -> bool
@@ -3679,13 +3699,13 @@ class DetectorMask(object):
         """
         return _libBornAgainDevice.DetectorMask_numberOfMasks(self)
 
-    def getMaskShape(self, mask_index, mask_value):
+    def patternAt(self, iMask):
         r"""
-        getMaskShape(DetectorMask self, size_t mask_index, bool & mask_value) -> IShape2D
-        const IShape2D * DetectorMask::getMaskShape(size_t mask_index, bool &mask_value) const
+        patternAt(DetectorMask self, size_t iMask) -> MaskPattern
+        const MaskPattern * DetectorMask::patternAt(size_t iMask) const
 
         """
-        return _libBornAgainDevice.DetectorMask_getMaskShape(self, mask_index, mask_value)
+        return _libBornAgainDevice.DetectorMask_patternAt(self, iMask)
 
 # Register DetectorMask in _libBornAgainDevice:
 _libBornAgainDevice.DetectorMask_swigregister(DetectorMask)
diff --git a/auto/Wrap/libBornAgainDevice_wrap.cpp b/auto/Wrap/libBornAgainDevice_wrap.cpp
index 32df9be11570459cae4ce20493d8dccea26340fb..253875ceecd71323466389870fb9b5088e6750b8 100644
--- a/auto/Wrap/libBornAgainDevice_wrap.cpp
+++ b/auto/Wrap/libBornAgainDevice_wrap.cpp
@@ -3126,29 +3126,29 @@ namespace Swig {
 #define SWIGTYPE_p_IShape2D swig_types[26]
 #define SWIGTYPE_p_Instrument swig_types[27]
 #define SWIGTYPE_p_Line swig_types[28]
-#define SWIGTYPE_p_OwningVectorT_IAxis_t swig_types[29]
-#define SWIGTYPE_p_PolMatrices swig_types[30]
-#define SWIGTYPE_p_Polygon swig_types[31]
-#define SWIGTYPE_p_PolygonPrivate swig_types[32]
-#define SWIGTYPE_p_PowerfieldIteratorT_double_PowerfieldT_double_t_t swig_types[33]
-#define SWIGTYPE_p_PowerfieldIteratorT_double_const_PowerfieldT_double_t_const_t swig_types[34]
-#define SWIGTYPE_p_PowerfieldT_CumulativeValue_t swig_types[35]
-#define SWIGTYPE_p_PowerfieldT_bool_t swig_types[36]
-#define SWIGTYPE_p_PowerfieldT_double_t swig_types[37]
-#define SWIGTYPE_p_RealLimits swig_types[38]
-#define SWIGTYPE_p_Rectangle swig_types[39]
-#define SWIGTYPE_p_RectangularDetector swig_types[40]
-#define SWIGTYPE_p_RectangularPixel swig_types[41]
-#define SWIGTYPE_p_ResolutionFunction2DGaussian swig_types[42]
-#define SWIGTYPE_p_SimulationResult swig_types[43]
-#define SWIGTYPE_p_SphericalDetector swig_types[44]
-#define SWIGTYPE_p_SpinMatrix swig_types[45]
-#define SWIGTYPE_p_Vec3T_double_t swig_types[46]
-#define SWIGTYPE_p_Vec3T_int_t swig_types[47]
-#define SWIGTYPE_p_Vec3T_std__complexT_double_t_t swig_types[48]
-#define SWIGTYPE_p_VerticalLine swig_types[49]
-#define SWIGTYPE_p_allocator_type swig_types[50]
-#define SWIGTYPE_p_bool swig_types[51]
+#define SWIGTYPE_p_MaskPattern swig_types[29]
+#define SWIGTYPE_p_OwningVectorT_IAxis_t swig_types[30]
+#define SWIGTYPE_p_PolMatrices swig_types[31]
+#define SWIGTYPE_p_Polygon swig_types[32]
+#define SWIGTYPE_p_PolygonPrivate swig_types[33]
+#define SWIGTYPE_p_PowerfieldIteratorT_double_PowerfieldT_double_t_t swig_types[34]
+#define SWIGTYPE_p_PowerfieldIteratorT_double_const_PowerfieldT_double_t_const_t swig_types[35]
+#define SWIGTYPE_p_PowerfieldT_CumulativeValue_t swig_types[36]
+#define SWIGTYPE_p_PowerfieldT_bool_t swig_types[37]
+#define SWIGTYPE_p_PowerfieldT_double_t swig_types[38]
+#define SWIGTYPE_p_RealLimits swig_types[39]
+#define SWIGTYPE_p_Rectangle swig_types[40]
+#define SWIGTYPE_p_RectangularDetector swig_types[41]
+#define SWIGTYPE_p_RectangularPixel swig_types[42]
+#define SWIGTYPE_p_ResolutionFunction2DGaussian swig_types[43]
+#define SWIGTYPE_p_SimulationResult swig_types[44]
+#define SWIGTYPE_p_SphericalDetector swig_types[45]
+#define SWIGTYPE_p_SpinMatrix swig_types[46]
+#define SWIGTYPE_p_Vec3T_double_t swig_types[47]
+#define SWIGTYPE_p_Vec3T_int_t swig_types[48]
+#define SWIGTYPE_p_Vec3T_std__complexT_double_t_t swig_types[49]
+#define SWIGTYPE_p_VerticalLine swig_types[50]
+#define SWIGTYPE_p_allocator_type swig_types[51]
 #define SWIGTYPE_p_char swig_types[52]
 #define SWIGTYPE_p_const_iterator swig_types[53]
 #define SWIGTYPE_p_corr_matrix_t swig_types[54]
@@ -33174,6 +33174,196 @@ SWIGINTERN PyObject *Axes_swiginit(PyObject *SWIGUNUSEDPARM(self), PyObject *arg
   return SWIG_Python_InitShadowInstance(args);
 }
 
+SWIGINTERN PyObject *_wrap_new_MaskPattern(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *resultobj = 0;
+  IShape2D *arg1 = (IShape2D *) 0 ;
+  bool arg2 ;
+  void *argp1 = 0 ;
+  int res1 = 0 ;
+  bool val2 ;
+  int ecode2 = 0 ;
+  PyObject *swig_obj[2] ;
+  MaskPattern *result = 0 ;
+  
+  if (!SWIG_Python_UnpackTuple(args, "new_MaskPattern", 2, 2, swig_obj)) SWIG_fail;
+  res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_IShape2D, 0 |  0 );
+  if (!SWIG_IsOK(res1)) {
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "new_MaskPattern" "', argument " "1"" of type '" "IShape2D *""'"); 
+  }
+  arg1 = reinterpret_cast< IShape2D * >(argp1);
+  ecode2 = SWIG_AsVal_bool(swig_obj[1], &val2);
+  if (!SWIG_IsOK(ecode2)) {
+    SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "new_MaskPattern" "', argument " "2"" of type '" "bool""'");
+  } 
+  arg2 = static_cast< bool >(val2);
+  result = (MaskPattern *)new MaskPattern(arg1,arg2);
+  resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_MaskPattern, SWIG_POINTER_NEW |  0 );
+  return resultobj;
+fail:
+  return NULL;
+}
+
+
+SWIGINTERN PyObject *_wrap_delete_MaskPattern(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *resultobj = 0;
+  MaskPattern *arg1 = (MaskPattern *) 0 ;
+  void *argp1 = 0 ;
+  int res1 = 0 ;
+  PyObject *swig_obj[1] ;
+  
+  if (!args) SWIG_fail;
+  swig_obj[0] = args;
+  res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_MaskPattern, SWIG_POINTER_DISOWN |  0 );
+  if (!SWIG_IsOK(res1)) {
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "delete_MaskPattern" "', argument " "1"" of type '" "MaskPattern *""'"); 
+  }
+  arg1 = reinterpret_cast< MaskPattern * >(argp1);
+  delete arg1;
+  resultobj = SWIG_Py_Void();
+  return resultobj;
+fail:
+  return NULL;
+}
+
+
+SWIGINTERN PyObject *_wrap_MaskPattern_clone(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *resultobj = 0;
+  MaskPattern *arg1 = (MaskPattern *) 0 ;
+  void *argp1 = 0 ;
+  int res1 = 0 ;
+  PyObject *swig_obj[1] ;
+  MaskPattern *result = 0 ;
+  
+  if (!args) SWIG_fail;
+  swig_obj[0] = args;
+  res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_MaskPattern, 0 |  0 );
+  if (!SWIG_IsOK(res1)) {
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "MaskPattern_clone" "', argument " "1"" of type '" "MaskPattern const *""'"); 
+  }
+  arg1 = reinterpret_cast< MaskPattern * >(argp1);
+  result = (MaskPattern *)((MaskPattern const *)arg1)->clone();
+  resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_MaskPattern, 0 |  0 );
+  return resultobj;
+fail:
+  return NULL;
+}
+
+
+SWIGINTERN PyObject *_wrap_MaskPattern_shape_set(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *resultobj = 0;
+  MaskPattern *arg1 = (MaskPattern *) 0 ;
+  IShape2D *arg2 = (IShape2D *) 0 ;
+  void *argp1 = 0 ;
+  int res1 = 0 ;
+  void *argp2 = 0 ;
+  int res2 = 0 ;
+  PyObject *swig_obj[2] ;
+  
+  if (!SWIG_Python_UnpackTuple(args, "MaskPattern_shape_set", 2, 2, swig_obj)) SWIG_fail;
+  res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_MaskPattern, 0 |  0 );
+  if (!SWIG_IsOK(res1)) {
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "MaskPattern_shape_set" "', argument " "1"" of type '" "MaskPattern *""'"); 
+  }
+  arg1 = reinterpret_cast< MaskPattern * >(argp1);
+  res2 = SWIG_ConvertPtr(swig_obj[1], &argp2,SWIGTYPE_p_IShape2D, SWIG_POINTER_DISOWN |  0 );
+  if (!SWIG_IsOK(res2)) {
+    SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "MaskPattern_shape_set" "', argument " "2"" of type '" "IShape2D *""'"); 
+  }
+  arg2 = reinterpret_cast< IShape2D * >(argp2);
+  if (arg1) (arg1)->shape = arg2;
+  resultobj = SWIG_Py_Void();
+  return resultobj;
+fail:
+  return NULL;
+}
+
+
+SWIGINTERN PyObject *_wrap_MaskPattern_shape_get(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *resultobj = 0;
+  MaskPattern *arg1 = (MaskPattern *) 0 ;
+  void *argp1 = 0 ;
+  int res1 = 0 ;
+  PyObject *swig_obj[1] ;
+  IShape2D *result = 0 ;
+  
+  if (!args) SWIG_fail;
+  swig_obj[0] = args;
+  res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_MaskPattern, 0 |  0 );
+  if (!SWIG_IsOK(res1)) {
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "MaskPattern_shape_get" "', argument " "1"" of type '" "MaskPattern *""'"); 
+  }
+  arg1 = reinterpret_cast< MaskPattern * >(argp1);
+  result = (IShape2D *) ((arg1)->shape);
+  resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_IShape2D, 0 |  0 );
+  return resultobj;
+fail:
+  return NULL;
+}
+
+
+SWIGINTERN PyObject *_wrap_MaskPattern_doMask_set(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *resultobj = 0;
+  MaskPattern *arg1 = (MaskPattern *) 0 ;
+  bool arg2 ;
+  void *argp1 = 0 ;
+  int res1 = 0 ;
+  bool val2 ;
+  int ecode2 = 0 ;
+  PyObject *swig_obj[2] ;
+  
+  if (!SWIG_Python_UnpackTuple(args, "MaskPattern_doMask_set", 2, 2, swig_obj)) SWIG_fail;
+  res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_MaskPattern, 0 |  0 );
+  if (!SWIG_IsOK(res1)) {
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "MaskPattern_doMask_set" "', argument " "1"" of type '" "MaskPattern *""'"); 
+  }
+  arg1 = reinterpret_cast< MaskPattern * >(argp1);
+  ecode2 = SWIG_AsVal_bool(swig_obj[1], &val2);
+  if (!SWIG_IsOK(ecode2)) {
+    SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "MaskPattern_doMask_set" "', argument " "2"" of type '" "bool""'");
+  } 
+  arg2 = static_cast< bool >(val2);
+  if (arg1) (arg1)->doMask = arg2;
+  resultobj = SWIG_Py_Void();
+  return resultobj;
+fail:
+  return NULL;
+}
+
+
+SWIGINTERN PyObject *_wrap_MaskPattern_doMask_get(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *resultobj = 0;
+  MaskPattern *arg1 = (MaskPattern *) 0 ;
+  void *argp1 = 0 ;
+  int res1 = 0 ;
+  PyObject *swig_obj[1] ;
+  bool result;
+  
+  if (!args) SWIG_fail;
+  swig_obj[0] = args;
+  res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_MaskPattern, 0 |  0 );
+  if (!SWIG_IsOK(res1)) {
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "MaskPattern_doMask_get" "', argument " "1"" of type '" "MaskPattern *""'"); 
+  }
+  arg1 = reinterpret_cast< MaskPattern * >(argp1);
+  result = (bool) ((arg1)->doMask);
+  resultobj = SWIG_From_bool(static_cast< bool >(result));
+  return resultobj;
+fail:
+  return NULL;
+}
+
+
+SWIGINTERN PyObject *MaskPattern_swigregister(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *obj;
+  if (!SWIG_Python_UnpackTuple(args, "swigregister", 1, 1, &obj)) return NULL;
+  SWIG_TypeNewClientData(SWIGTYPE_p_MaskPattern, SWIG_NewClientData(obj));
+  return SWIG_Py_Void();
+}
+
+SWIGINTERN PyObject *MaskPattern_swiginit(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  return SWIG_Python_InitShadowInstance(args);
+}
+
 SWIGINTERN PyObject *_wrap_new_DetectorMask__SWIG_0(PyObject *SWIGUNUSEDPARM(self), Py_ssize_t nobjs, PyObject **SWIGUNUSEDPARM(swig_obj)) {
   PyObject *resultobj = 0;
   DetectorMask *result = 0 ;
@@ -33446,29 +33636,6 @@ fail:
 }
 
 
-SWIGINTERN PyObject *_wrap_DetectorMask_createHistogram(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
-  DetectorMask *arg1 = (DetectorMask *) 0 ;
-  void *argp1 = 0 ;
-  int res1 = 0 ;
-  PyObject *swig_obj[1] ;
-  Histogram2D *result = 0 ;
-  
-  if (!args) SWIG_fail;
-  swig_obj[0] = args;
-  res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_DetectorMask, 0 |  0 );
-  if (!SWIG_IsOK(res1)) {
-    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "DetectorMask_createHistogram" "', argument " "1"" of type '" "DetectorMask const *""'"); 
-  }
-  arg1 = reinterpret_cast< DetectorMask * >(argp1);
-  result = (Histogram2D *)((DetectorMask const *)arg1)->createHistogram();
-  resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_Histogram2D, SWIG_POINTER_OWN |  0 );
-  return resultobj;
-fail:
-  return NULL;
-}
-
-
 SWIGINTERN PyObject *_wrap_DetectorMask_hasMasks(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
   PyObject *resultobj = 0;
   DetectorMask *arg1 = (DetectorMask *) 0 ;
@@ -33538,41 +33705,30 @@ fail:
 }
 
 
-SWIGINTERN PyObject *_wrap_DetectorMask_getMaskShape(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+SWIGINTERN PyObject *_wrap_DetectorMask_patternAt(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
   PyObject *resultobj = 0;
   DetectorMask *arg1 = (DetectorMask *) 0 ;
   size_t arg2 ;
-  bool *arg3 = 0 ;
   void *argp1 = 0 ;
   int res1 = 0 ;
   size_t val2 ;
   int ecode2 = 0 ;
-  void *argp3 = 0 ;
-  int res3 = 0 ;
-  PyObject *swig_obj[3] ;
-  IShape2D *result = 0 ;
+  PyObject *swig_obj[2] ;
+  MaskPattern *result = 0 ;
   
-  if (!SWIG_Python_UnpackTuple(args, "DetectorMask_getMaskShape", 3, 3, swig_obj)) SWIG_fail;
+  if (!SWIG_Python_UnpackTuple(args, "DetectorMask_patternAt", 2, 2, swig_obj)) SWIG_fail;
   res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_DetectorMask, 0 |  0 );
   if (!SWIG_IsOK(res1)) {
-    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "DetectorMask_getMaskShape" "', argument " "1"" of type '" "DetectorMask const *""'"); 
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "DetectorMask_patternAt" "', argument " "1"" of type '" "DetectorMask const *""'"); 
   }
   arg1 = reinterpret_cast< DetectorMask * >(argp1);
   ecode2 = SWIG_AsVal_size_t(swig_obj[1], &val2);
   if (!SWIG_IsOK(ecode2)) {
-    SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "DetectorMask_getMaskShape" "', argument " "2"" of type '" "size_t""'");
+    SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "DetectorMask_patternAt" "', argument " "2"" of type '" "size_t""'");
   } 
   arg2 = static_cast< size_t >(val2);
-  res3 = SWIG_ConvertPtr(swig_obj[2], &argp3, SWIGTYPE_p_bool,  0 );
-  if (!SWIG_IsOK(res3)) {
-    SWIG_exception_fail(SWIG_ArgError(res3), "in method '" "DetectorMask_getMaskShape" "', argument " "3"" of type '" "bool &""'"); 
-  }
-  if (!argp3) {
-    SWIG_exception_fail(SWIG_ValueError, "invalid null reference " "in method '" "DetectorMask_getMaskShape" "', argument " "3"" of type '" "bool &""'"); 
-  }
-  arg3 = reinterpret_cast< bool * >(argp3);
-  result = (IShape2D *)((DetectorMask const *)arg1)->getMaskShape(arg2,*arg3);
-  resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_IShape2D, 0 |  0 );
+  result = (MaskPattern *)((DetectorMask const *)arg1)->patternAt(arg2);
+  resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_MaskPattern, 0 |  0 );
   return resultobj;
 fail:
   return NULL;
@@ -43658,6 +43814,27 @@ static PyMethodDef SwigMethods[] = {
 	 { "delete_Axes", _wrap_delete_Axes, METH_O, "delete_Axes(Axes self)"},
 	 { "Axes_swigregister", Axes_swigregister, METH_O, NULL},
 	 { "Axes_swiginit", Axes_swiginit, METH_VARARGS, NULL},
+	 { "new_MaskPattern", _wrap_new_MaskPattern, METH_VARARGS, "\n"
+		"new_MaskPattern(IShape2D shape_, bool doMask_) -> MaskPattern\n"
+		"MaskPattern::MaskPattern(const MaskPattern &)=delete\n"
+		"\n"
+		""},
+	 { "delete_MaskPattern", _wrap_delete_MaskPattern, METH_O, "\n"
+		"delete_MaskPattern(MaskPattern self)\n"
+		"MaskPattern::~MaskPattern()\n"
+		"\n"
+		""},
+	 { "MaskPattern_clone", _wrap_MaskPattern_clone, METH_O, "\n"
+		"MaskPattern_clone(MaskPattern self) -> MaskPattern\n"
+		"MaskPattern * MaskPattern::clone() const\n"
+		"\n"
+		""},
+	 { "MaskPattern_shape_set", _wrap_MaskPattern_shape_set, METH_VARARGS, "MaskPattern_shape_set(MaskPattern self, IShape2D shape)"},
+	 { "MaskPattern_shape_get", _wrap_MaskPattern_shape_get, METH_O, "MaskPattern_shape_get(MaskPattern self) -> IShape2D"},
+	 { "MaskPattern_doMask_set", _wrap_MaskPattern_doMask_set, METH_VARARGS, "MaskPattern_doMask_set(MaskPattern self, bool doMask)"},
+	 { "MaskPattern_doMask_get", _wrap_MaskPattern_doMask_get, METH_O, "MaskPattern_doMask_get(MaskPattern self) -> bool"},
+	 { "MaskPattern_swigregister", MaskPattern_swigregister, METH_O, NULL},
+	 { "MaskPattern_swiginit", MaskPattern_swiginit, METH_VARARGS, NULL},
 	 { "delete_DetectorMask", _wrap_delete_DetectorMask, METH_O, "\n"
 		"delete_DetectorMask(DetectorMask self)\n"
 		"DetectorMask::~DetectorMask()\n"
@@ -43703,11 +43880,6 @@ static PyMethodDef SwigMethods[] = {
 		"const Powerfield<bool>* DetectorMask::getMaskData() const\n"
 		"\n"
 		""},
-	 { "DetectorMask_createHistogram", _wrap_DetectorMask_createHistogram, METH_O, "\n"
-		"DetectorMask_createHistogram(DetectorMask self) -> Histogram2D\n"
-		"Histogram2D * DetectorMask::createHistogram() const\n"
-		"\n"
-		""},
 	 { "DetectorMask_hasMasks", _wrap_DetectorMask_hasMasks, METH_O, "\n"
 		"DetectorMask_hasMasks(DetectorMask self) -> bool\n"
 		"bool DetectorMask::hasMasks() const\n"
@@ -43725,9 +43897,9 @@ static PyMethodDef SwigMethods[] = {
 		"size_t DetectorMask::numberOfMasks() const\n"
 		"\n"
 		""},
-	 { "DetectorMask_getMaskShape", _wrap_DetectorMask_getMaskShape, METH_VARARGS, "\n"
-		"DetectorMask_getMaskShape(DetectorMask self, size_t mask_index, bool & mask_value) -> IShape2D\n"
-		"const IShape2D * DetectorMask::getMaskShape(size_t mask_index, bool &mask_value) const\n"
+	 { "DetectorMask_patternAt", _wrap_DetectorMask_patternAt, METH_VARARGS, "\n"
+		"DetectorMask_patternAt(DetectorMask self, size_t iMask) -> MaskPattern\n"
+		"const MaskPattern * DetectorMask::patternAt(size_t iMask) const\n"
 		"\n"
 		""},
 	 { "DetectorMask_swigregister", DetectorMask_swigregister, METH_O, NULL},
@@ -45021,6 +45193,7 @@ static swig_type_info _swigt__p_IResolutionFunction2D = {"_p_IResolutionFunction
 static swig_type_info _swigt__p_IShape2D = {"_p_IShape2D", "IShape2D *", 0, 0, (void*)0, 0};
 static swig_type_info _swigt__p_Instrument = {"_p_Instrument", "Instrument *", 0, 0, (void*)0, 0};
 static swig_type_info _swigt__p_Line = {"_p_Line", "Line *", 0, 0, (void*)0, 0};
+static swig_type_info _swigt__p_MaskPattern = {"_p_MaskPattern", "MaskPattern *", 0, 0, (void*)0, 0};
 static swig_type_info _swigt__p_OwningVectorT_IAxis_t = {"_p_OwningVectorT_IAxis_t", "OwningVector< IAxis > *", 0, 0, (void*)0, 0};
 static swig_type_info _swigt__p_PolMatrices = {"_p_PolMatrices", "PolMatrices *", 0, 0, (void*)0, 0};
 static swig_type_info _swigt__p_Polygon = {"_p_Polygon", "Polygon *", 0, 0, (void*)0, 0};
@@ -45043,7 +45216,6 @@ static swig_type_info _swigt__p_Vec3T_int_t = {"_p_Vec3T_int_t", "I3 *|Vec3< int
 static swig_type_info _swigt__p_Vec3T_std__complexT_double_t_t = {"_p_Vec3T_std__complexT_double_t_t", "Vec3< std::complex< double > > *|C3 *", 0, 0, (void*)0, 0};
 static swig_type_info _swigt__p_VerticalLine = {"_p_VerticalLine", "VerticalLine *", 0, 0, (void*)0, 0};
 static swig_type_info _swigt__p_allocator_type = {"_p_allocator_type", "allocator_type *", 0, 0, (void*)0, 0};
-static swig_type_info _swigt__p_bool = {"_p_bool", "bool *", 0, 0, (void*)0, 0};
 static swig_type_info _swigt__p_char = {"_p_char", "char *", 0, 0, (void*)0, 0};
 static swig_type_info _swigt__p_const_iterator = {"_p_const_iterator", "const_iterator *", 0, 0, (void*)0, 0};
 static swig_type_info _swigt__p_corr_matrix_t = {"_p_corr_matrix_t", "corr_matrix_t *", 0, 0, (void*)0, 0};
@@ -45131,6 +45303,7 @@ static swig_type_info *swig_type_initial[] = {
   &_swigt__p_IShape2D,
   &_swigt__p_Instrument,
   &_swigt__p_Line,
+  &_swigt__p_MaskPattern,
   &_swigt__p_OwningVectorT_IAxis_t,
   &_swigt__p_PolMatrices,
   &_swigt__p_Polygon,
@@ -45153,7 +45326,6 @@ static swig_type_info *swig_type_initial[] = {
   &_swigt__p_Vec3T_std__complexT_double_t_t,
   &_swigt__p_VerticalLine,
   &_swigt__p_allocator_type,
-  &_swigt__p_bool,
   &_swigt__p_char,
   &_swigt__p_const_iterator,
   &_swigt__p_corr_matrix_t,
@@ -45241,6 +45413,7 @@ static swig_cast_info _swigc__p_IResolutionFunction2D[] = {  {&_swigt__p_IResolu
 static swig_cast_info _swigc__p_IShape2D[] = {  {&_swigt__p_Polygon, _p_PolygonTo_p_IShape2D, 0, 0},  {&_swigt__p_Line, _p_LineTo_p_IShape2D, 0, 0},  {&_swigt__p_VerticalLine, _p_VerticalLineTo_p_IShape2D, 0, 0},  {&_swigt__p_Ellipse, _p_EllipseTo_p_IShape2D, 0, 0},  {&_swigt__p_HorizontalLine, _p_HorizontalLineTo_p_IShape2D, 0, 0},  {&_swigt__p_Rectangle, _p_RectangleTo_p_IShape2D, 0, 0},  {&_swigt__p_IShape2D, 0, 0, 0},{0, 0, 0, 0}};
 static swig_cast_info _swigc__p_Instrument[] = {  {&_swigt__p_Instrument, 0, 0, 0},{0, 0, 0, 0}};
 static swig_cast_info _swigc__p_Line[] = {  {&_swigt__p_Line, 0, 0, 0},{0, 0, 0, 0}};
+static swig_cast_info _swigc__p_MaskPattern[] = {  {&_swigt__p_MaskPattern, 0, 0, 0},{0, 0, 0, 0}};
 static swig_cast_info _swigc__p_OwningVectorT_IAxis_t[] = {  {&_swigt__p_OwningVectorT_IAxis_t, 0, 0, 0},{0, 0, 0, 0}};
 static swig_cast_info _swigc__p_PolMatrices[] = {  {&_swigt__p_PolMatrices, 0, 0, 0},{0, 0, 0, 0}};
 static swig_cast_info _swigc__p_Polygon[] = {  {&_swigt__p_Polygon, 0, 0, 0},{0, 0, 0, 0}};
@@ -45263,7 +45436,6 @@ static swig_cast_info _swigc__p_Vec3T_int_t[] = {  {&_swigt__p_Vec3T_int_t, 0, 0
 static swig_cast_info _swigc__p_Vec3T_std__complexT_double_t_t[] = {  {&_swigt__p_Vec3T_std__complexT_double_t_t, 0, 0, 0},{0, 0, 0, 0}};
 static swig_cast_info _swigc__p_VerticalLine[] = {  {&_swigt__p_VerticalLine, 0, 0, 0},{0, 0, 0, 0}};
 static swig_cast_info _swigc__p_allocator_type[] = {  {&_swigt__p_allocator_type, 0, 0, 0},{0, 0, 0, 0}};
-static swig_cast_info _swigc__p_bool[] = {  {&_swigt__p_bool, 0, 0, 0},{0, 0, 0, 0}};
 static swig_cast_info _swigc__p_char[] = {  {&_swigt__p_char, 0, 0, 0},{0, 0, 0, 0}};
 static swig_cast_info _swigc__p_const_iterator[] = {  {&_swigt__p_const_iterator, 0, 0, 0},{0, 0, 0, 0}};
 static swig_cast_info _swigc__p_corr_matrix_t[] = {  {&_swigt__p_corr_matrix_t, 0, 0, 0},{0, 0, 0, 0}};
@@ -45351,6 +45523,7 @@ static swig_cast_info *swig_cast_initial[] = {
   _swigc__p_IShape2D,
   _swigc__p_Instrument,
   _swigc__p_Line,
+  _swigc__p_MaskPattern,
   _swigc__p_OwningVectorT_IAxis_t,
   _swigc__p_PolMatrices,
   _swigc__p_Polygon,
@@ -45373,7 +45546,6 @@ static swig_cast_info *swig_cast_initial[] = {
   _swigc__p_Vec3T_std__complexT_double_t_t,
   _swigc__p_VerticalLine,
   _swigc__p_allocator_type,
-  _swigc__p_bool,
   _swigc__p_char,
   _swigc__p_const_iterator,
   _swigc__p_corr_matrix_t,