diff --git a/Base/Axis/ConstKBinAxis.cpp b/Base/Axis/ConstKBinAxis.cpp
index 546bdb3e4c078fe4f684bc344d65e272c02426e4..ac2b29179c911be49007972275a9ee1dbdfbafdd 100644
--- a/Base/Axis/ConstKBinAxis.cpp
+++ b/Base/Axis/ConstKBinAxis.cpp
@@ -13,7 +13,6 @@
 //  ************************************************************************************************
 
 #include "Base/Axis/ConstKBinAxis.h"
-#include "Base/Types/Exceptions.h"
 #include "Base/Utils/Algorithms.h"
 #include <iomanip>
 
@@ -23,7 +22,7 @@ ConstKBinAxis::ConstKBinAxis(const std::string& name, size_t nbins)
 ConstKBinAxis::ConstKBinAxis(const std::string& name, size_t nbins, double start, double end)
     : VariableBinAxis(name, nbins), m_start(start), m_end(end) {
     if (m_start >= m_end)
-        throw Exceptions::LogicErrorException(
+        throw std::runtime_error(
             "ConstKBinAxis::ConstKBinAxis() -> Error. start >= end is not allowed.");
 
     double start_sin = std::sin(m_start);
@@ -44,7 +43,7 @@ ConstKBinAxis* ConstKBinAxis::clone() const {
 
 ConstKBinAxis* ConstKBinAxis::createClippedAxis(double left, double right) const {
     if (left >= right)
-        throw Exceptions::LogicErrorException(
+        throw std::runtime_error(
             "ConstKBinAxis::createClippedAxis() -> Error. 'left'' should be smaller than 'right'");
 
     if (left < lowerBound())
diff --git a/Base/Axis/CustomBinAxis.cpp b/Base/Axis/CustomBinAxis.cpp
index 4812cfaef637b3e4d9459d4c98dbdfb66a9e48a7..4a65292dfa03557a76edefd32db94a5a48603a3b 100644
--- a/Base/Axis/CustomBinAxis.cpp
+++ b/Base/Axis/CustomBinAxis.cpp
@@ -13,7 +13,6 @@
 //  ************************************************************************************************
 
 #include "Base/Axis/CustomBinAxis.h"
-#include "Base/Types/Exceptions.h"
 #include "Base/Utils/Algorithms.h"
 #include <iomanip>
 #include <limits>
@@ -21,8 +20,8 @@
 CustomBinAxis::CustomBinAxis(const std::string& name, size_t nbins, double start, double end)
     : VariableBinAxis(name, nbins), m_start(start), m_end(end) {
     if (m_start >= m_end)
-        throw Exceptions::LogicErrorException("CustomBinAxis::CustomBinAxis() -> Error."
-                                              " start >= end is not allowed.");
+        throw std::runtime_error("CustomBinAxis::CustomBinAxis() -> Error."
+                                 " start >= end is not allowed.");
 
     double start_sin = std::sin(start);
     double end_sin = std::sin(end);
@@ -47,7 +46,7 @@ CustomBinAxis* CustomBinAxis::clone() const {
 
 Bin1D CustomBinAxis::bin(size_t index) const {
     if (index >= m_nbins)
-        throw Exceptions::OutOfBoundsException("CustomBinAxis::bin() -> Error. Wrong index.");
+        throw std::runtime_error("CustomBinAxis::bin() -> Error. Wrong index.");
 
     Bin1D result(m_bin_centers[index], m_bin_centers[index]);
     return result;
@@ -58,8 +57,8 @@ std::vector<double> CustomBinAxis::binCenters() const {
 }
 
 CustomBinAxis* CustomBinAxis::createClippedAxis(double /* left */, double /* right */) const {
-    throw Exceptions::NotImplementedException("VariableBinAxis::CustomBinAxis() -> Error."
-                                              " Not implemented.");
+    throw std::runtime_error("VariableBinAxis::CustomBinAxis() -> Error."
+                             " Not implemented.");
 }
 
 void CustomBinAxis::print(std::ostream& ostr) const {
diff --git a/Base/Axis/FixedBinAxis.cpp b/Base/Axis/FixedBinAxis.cpp
index 9a25c492220c3af333221675f2e5496b4e650357..aa6f874cff4334976441234270b4602108fb746d 100644
--- a/Base/Axis/FixedBinAxis.cpp
+++ b/Base/Axis/FixedBinAxis.cpp
@@ -13,7 +13,6 @@
 //  ************************************************************************************************
 
 #include "Base/Axis/FixedBinAxis.h"
-#include "Base/Types/Exceptions.h"
 #include "Base/Utils/Algorithms.h"
 #include "Base/Utils/PyFmt.h"
 #include <iomanip>
@@ -29,7 +28,7 @@ FixedBinAxis* FixedBinAxis::clone() const {
 
 double FixedBinAxis::operator[](size_t index) const {
     if (index >= m_nbins)
-        throw Exceptions::OutOfBoundsException("FixedBinAxis::operator[] -> Error. Wrong index.");
+        throw std::runtime_error("FixedBinAxis::operator[] -> Error. Wrong index.");
 
     double step = (m_end - m_start) / m_nbins;
     return m_start + (index + 0.5) * step;
@@ -37,7 +36,7 @@ double FixedBinAxis::operator[](size_t index) const {
 
 Bin1D FixedBinAxis::bin(size_t index) const {
     if (index >= m_nbins)
-        throw Exceptions::OutOfBoundsException("FixedBinAxis::bin() -> Error. Wrong index.");
+        throw std::runtime_error("FixedBinAxis::bin() -> Error. Wrong index.");
 
     double step = (m_end - m_start) / m_nbins;
     Bin1D result(m_start + step * index, m_start + step * (index + 1));
@@ -76,8 +75,8 @@ std::vector<double> FixedBinAxis::binBoundaries() const {
 
 FixedBinAxis* FixedBinAxis::createClippedAxis(double left, double right) const {
     if (left >= right)
-        throw Exceptions::LogicErrorException("FixedBinAxis::createClippedAxis() -> Error. "
-                                              "'left' should be smaller than 'right'");
+        throw std::runtime_error("FixedBinAxis::createClippedAxis() -> Error. "
+                                 "'left' should be smaller than 'right'");
 
     if (left < lowerBound())
         left = bin(0).center();
diff --git a/Base/Axis/IAxis.cpp b/Base/Axis/IAxis.cpp
index 0a508d3f9b1646c886c2d493bdb4df2f0b525500..5b56e268500e76560ec4944f93193ae9de427001 100644
--- a/Base/Axis/IAxis.cpp
+++ b/Base/Axis/IAxis.cpp
@@ -13,23 +13,21 @@
 //  ************************************************************************************************
 
 #include "Base/Axis/IAxis.h"
-#include "Base/Types/Exceptions.h"
 
 bool IAxis::equals(const IAxis& other) const {
     return getName() == other.getName();
 }
 
 std::vector<double> IAxis::binCenters() const {
-    throw Exceptions::NotImplementedException("IAxis::binCenters() -> Error. Not implemented.");
+    throw std::runtime_error("IAxis::binCenters() -> Error. Not implemented.");
 }
 
 std::vector<double> IAxis::binBoundaries() const {
-    throw Exceptions::NotImplementedException("IAxis::binBoundaries() -> Error. Not implemented.");
+    throw std::runtime_error("IAxis::binBoundaries() -> Error. Not implemented.");
 }
 
 IAxis* IAxis::createClippedAxis(double /* left */, double /* right */) const {
-    throw Exceptions::NotImplementedException(
-        "IAxis::createClippedAxis() -> Error. Not implemented.");
+    throw std::runtime_error("IAxis::createClippedAxis() -> Error. Not implemented.");
 }
 
 bool IAxis::contains(double value) const {
diff --git a/Base/Axis/VariableBinAxis.cpp b/Base/Axis/VariableBinAxis.cpp
index cef438eb988c2a2fa152fbb7e38b8a9dda88bdb0..6662d1c4ec9bb87c5afcdbeb997a63f0be0b315d 100644
--- a/Base/Axis/VariableBinAxis.cpp
+++ b/Base/Axis/VariableBinAxis.cpp
@@ -13,7 +13,6 @@
 //  ************************************************************************************************
 
 #include "Base/Axis/VariableBinAxis.h"
-#include "Base/Types/Exceptions.h"
 #include "Base/Utils/Algorithms.h"
 #include <algorithm>
 #include <iomanip>
@@ -22,9 +21,8 @@ VariableBinAxis::VariableBinAxis(const std::string& name, size_t nbins,
                                  const std::vector<double>& bin_boundaries)
     : IAxis(name), m_nbins(nbins) {
     if (m_nbins != bin_boundaries.size() - 1)
-        throw Exceptions::LogicErrorException(
-            "VariableBinAxis::VariableBinAxis() -> Error! "
-            "The size of bin_boundaries should be of size [nbins+1].");
+        throw std::runtime_error("VariableBinAxis::VariableBinAxis() -> Error! "
+                                 "The size of bin_boundaries should be of size [nbins+1].");
 
     setBinBoundaries(bin_boundaries);
 }
@@ -43,7 +41,7 @@ double VariableBinAxis::operator[](size_t index) const {
 
 Bin1D VariableBinAxis::bin(size_t index) const {
     if (index >= m_nbins)
-        throw Exceptions::OutOfBoundsException("VariableBinAxis::bin() -> Error. Wrong index.");
+        throw std::runtime_error("VariableBinAxis::bin() -> Error. Wrong index.");
 
     Bin1D result(m_bin_boundaries[index], m_bin_boundaries[index + 1]);
     return result;
@@ -63,9 +61,8 @@ double VariableBinAxis::binCenter(size_t index) const {
 
 size_t VariableBinAxis::findClosestIndex(double value) const {
     if (m_bin_boundaries.size() < 2)
-        throw Exceptions::ClassInitializationException(
-            "VariableBinAxis::findClosestIndex() -> Error! "
-            "VariableBinAxis not  correctly initialized");
+        throw std::runtime_error("VariableBinAxis::findClosestIndex() -> Error! "
+                                 "VariableBinAxis not  correctly initialized");
     if (value < lowerBound()) {
         return 0;
     } else if (value >= upperBound()) {
@@ -92,8 +89,8 @@ std::vector<double> VariableBinAxis::binCenters() const {
 VariableBinAxis* VariableBinAxis::createClippedAxis(double left, double right) const {
 
     if (left >= right)
-        throw Exceptions::LogicErrorException("VariableBinAxis::createClippedAxis() -> Error. "
-                                              "'left'' should be smaller than 'right'");
+        throw std::runtime_error("VariableBinAxis::createClippedAxis() -> Error. "
+                                 "'left'' should be smaller than 'right'");
 
     if (left < lowerBound())
         left = bin(0).center();
@@ -148,16 +145,16 @@ void VariableBinAxis::setBinBoundaries(const std::vector<double>& bin_boundaries
     std::sort(vec_sorted.begin(), vec_sorted.end());
     for (size_t i = 0; i < bin_boundaries.size(); ++i) {
         if (vec_sorted[i] != bin_boundaries[i])
-            throw Exceptions::LogicErrorException("VariableBinAxis::VariableBinAxis() -> Error. "
-                                                  "Array with bin edges is not sorted.");
+            throw std::runtime_error("VariableBinAxis::VariableBinAxis() -> Error. "
+                                     "Array with bin edges is not sorted.");
     }
 
     std::vector<double> vec = bin_boundaries;
     vec.erase(std::unique(vec.begin(), vec.end()), vec.end());
 
     if (vec.size() != bin_boundaries.size())
-        throw Exceptions::LogicErrorException("VariableBinAxis::VariableBinAxis() -> Error. "
-                                              "Array with bin edges contains repeating values.");
+        throw std::runtime_error("VariableBinAxis::VariableBinAxis() -> Error. "
+                                 "Array with bin edges contains repeating values.");
 
     m_bin_boundaries = bin_boundaries;
 }
diff --git a/Base/Types/Exceptions.cpp b/Base/Types/Exceptions.cpp
deleted file mode 100644
index e8f0339e8ced063e7b56320d310bd3c05c8fd1c1..0000000000000000000000000000000000000000
--- a/Base/Types/Exceptions.cpp
+++ /dev/null
@@ -1,70 +0,0 @@
-//  ************************************************************************************************
-//
-//  BornAgain: simulate and fit scattering at grazing incidence
-//
-//! @file      Base/Types/Exceptions.cpp
-//! @brief     Implements class Exceptions.
-//!
-//! @homepage  http://www.bornagainproject.org
-//! @license   GNU General Public License v3 or higher (see COPYING)
-//! @copyright Forschungszentrum Jülich GmbH 2018
-//! @authors   Scientific Computing Group at MLZ (see CITATION, AUTHORS)
-//
-//  ************************************************************************************************
-
-#include "Base/Types/Exceptions.h"
-#include <iostream>
-
-namespace Exceptions {
-
-void LogExceptionMessage(const std::string&) {
-    //    std::cerr << message << std::endl;
-}
-
-NotImplementedException::NotImplementedException(const std::string& message)
-    : std::logic_error(message) {
-    LogExceptionMessage(message);
-}
-
-NullPointerException::NullPointerException(const std::string& message) : std::logic_error(message) {
-    LogExceptionMessage(message);
-}
-
-OutOfBoundsException::OutOfBoundsException(const std::string& message) : std::logic_error(message) {
-    LogExceptionMessage(message);
-}
-
-ClassInitializationException::ClassInitializationException(const std::string& message)
-    : std::runtime_error(message) {
-    LogExceptionMessage(message);
-}
-
-LogicErrorException::LogicErrorException(const std::string& message) : std::logic_error(message) {
-    LogExceptionMessage(message);
-}
-
-RuntimeErrorException::RuntimeErrorException(const std::string& message)
-    : std::runtime_error(message) {
-    LogExceptionMessage(message);
-}
-
-DomainErrorException::DomainErrorException(const std::string& message)
-    : std::domain_error(message) {
-    LogExceptionMessage(message);
-}
-
-FileNotIsOpenException::FileNotIsOpenException(const std::string& message)
-    : std::runtime_error(message) {
-    LogExceptionMessage(message);
-}
-
-FileIsBadException::FileIsBadException(const std::string& message) : std::runtime_error(message) {
-    LogExceptionMessage(message);
-}
-
-FormatErrorException::FormatErrorException(const std::string& message)
-    : std::runtime_error(message) {
-    LogExceptionMessage(message);
-}
-
-} // namespace Exceptions
diff --git a/Base/Types/Exceptions.h b/Base/Types/Exceptions.h
deleted file mode 100644
index 2ed8ba761299055c0ee0d8c1d09300d7fbd40d0a..0000000000000000000000000000000000000000
--- a/Base/Types/Exceptions.h
+++ /dev/null
@@ -1,92 +0,0 @@
-//  ************************************************************************************************
-//
-//  BornAgain: simulate and fit scattering at grazing incidence
-//
-//! @file      Base/Types/Exceptions.h
-//! @brief     Defines many exception classes in namespace Exceptionss.
-//!
-//! @homepage  http://www.bornagainproject.org
-//! @license   GNU General Public License v3 or higher (see COPYING)
-//! @copyright Forschungszentrum Jülich GmbH 2018
-//! @authors   Scientific Computing Group at MLZ (see CITATION, AUTHORS)
-//
-//  ************************************************************************************************
-
-#ifndef BORNAGAIN_BASE_TYPES_EXCEPTIONS_H
-#define BORNAGAIN_BASE_TYPES_EXCEPTIONS_H
-
-#include <stdexcept>
-#include <string>
-
-#ifdef _WIN32
-#ifdef _MSC_VER
-#pragma warning(push)
-#pragma warning(disable : 4275)
-#endif
-#endif
-
-//! Different exceptions, all inheriting from std::exception.
-
-namespace Exceptions {
-
-class NotImplementedException : public std::logic_error {
-public:
-    NotImplementedException(const std::string& message);
-};
-
-class NullPointerException : public std::logic_error {
-public:
-    NullPointerException(const std::string& message);
-};
-
-class OutOfBoundsException : public std::logic_error {
-public:
-    OutOfBoundsException(const std::string& message);
-};
-
-class ClassInitializationException : public std::runtime_error {
-public:
-    ClassInitializationException(const std::string& message);
-};
-
-class LogicErrorException : public std::logic_error {
-public:
-    LogicErrorException(const std::string& message);
-};
-
-class RuntimeErrorException : public std::runtime_error {
-public:
-    RuntimeErrorException(const std::string& message);
-};
-
-class DomainErrorException : public std::domain_error {
-public:
-    DomainErrorException(const std::string& message);
-};
-
-class FileNotIsOpenException : public std::runtime_error {
-public:
-    FileNotIsOpenException(const std::string& message);
-};
-
-class FileIsBadException : public std::runtime_error {
-public:
-    FileIsBadException(const std::string& message);
-};
-
-class FormatErrorException : public std::runtime_error {
-public:
-    FormatErrorException(const std::string& message);
-};
-
-void LogExceptionMessage(const std::string& message);
-
-} // namespace Exceptions
-
-#ifdef _WIN32
-#ifdef _MSC_VER
-#pragma warning(pop)
-#endif
-#endif
-
-#endif // BORNAGAIN_BASE_TYPES_EXCEPTIONS_H
diff --git a/Base/Utils/FileSystemUtils.cpp b/Base/Utils/FileSystemUtils.cpp
index 8a330c9e52db7fc83002e496ae6ae4956d3feea4..3b5d60bd866a42c025a0f32be5d53e3dff1671d0 100644
--- a/Base/Utils/FileSystemUtils.cpp
+++ b/Base/Utils/FileSystemUtils.cpp
@@ -13,7 +13,6 @@
 //  ************************************************************************************************
 
 #include "Base/Utils/FileSystemUtils.h"
-#include "Base/Types/Exceptions.h"
 #include "Base/Utils/Assert.h"
 #include <boost/filesystem.hpp>
 #include <codecvt>
diff --git a/Base/Utils/PyFmt.cpp b/Base/Utils/PyFmt.cpp
index 3305797a1ce4bd0a14b86e2f9b1307b073364205..bf7f3691efb9817f846f830aebd623891f1e84cd 100644
--- a/Base/Utils/PyFmt.cpp
+++ b/Base/Utils/PyFmt.cpp
@@ -23,15 +23,11 @@ namespace pyfmt {
 std::string scriptPreamble() {
     const std::string result = "import numpy\n"
                                "import bornagain as ba\n"
-                               "from bornagain import deg, angstrom, nm, nm2, kvector_t\n\n\n";
+                               "from bornagain import deg, nm, nm2, kvector_t\n\n\n";
 
     return result;
 }
 
-std::string getSampleFunctionName() {
-    return "get_sample";
-}
-
 std::string printBool(double value) {
     return value ? "True" : "False";
 }
diff --git a/Base/Utils/PyFmt.h b/Base/Utils/PyFmt.h
index 5dc8f17e09e1b8d3c4fdd857d8f763005f262d04..ffa4069bd19aa3baa544c9a7b80671f846cf05a0 100644
--- a/Base/Utils/PyFmt.h
+++ b/Base/Utils/PyFmt.h
@@ -25,7 +25,6 @@ class RealLimits;
 namespace pyfmt {
 
 std::string scriptPreamble();
-std::string getSampleFunctionName();
 
 std::string printInt(int value);
 std::string printBool(double value);
diff --git a/Core/Computation/ParticleLayoutComputation.cpp b/Core/Computation/ParticleLayoutComputation.cpp
index 16359a569a147996baaf212d937b40ee94e1558d..3a3ff5986593dde310ca1c442577aacf1d94c872 100644
--- a/Core/Computation/ParticleLayoutComputation.cpp
+++ b/Core/Computation/ParticleLayoutComputation.cpp
@@ -14,7 +14,6 @@
 
 #include "Core/Computation/ParticleLayoutComputation.h"
 #include "Base/Pixel/SimulationElement.h"
-#include "Base/Types/Exceptions.h"
 #include "Sample/Aggregate/InterferenceFunctionRadialParaCrystal.h"
 #include "Sample/Interference/DecouplingApproximationStrategy.h"
 #include "Sample/Interference/SSCApproximationStrategy.h"
diff --git a/Core/Export/ExportToPython.cpp b/Core/Export/ExportToPython.cpp
index 10305e9d43cdaa26dfaa08eacef407a102bf4558..3060d6dd25fd3584e0dff0c892f7f0d3fe94584e 100644
--- a/Core/Export/ExportToPython.cpp
+++ b/Core/Export/ExportToPython.cpp
@@ -15,28 +15,15 @@
 #include "Core/Export/ExportToPython.h"
 #include "Core/Export/SampleToPython.h"
 #include "Core/Export/SimulationToPython.h"
-#include "Core/Simulation/GISASSimulation.h"
-
-namespace {
-std::string simulationCode(const ISimulation& simulation,
-                           SimulationToPython::EMainType mainFunctionType) {
-    std::unique_ptr<ISimulation> sim(simulation.clone());
-    sim->prepareSimulation();
-
-    SimulationToPython generator;
-    return generator.generateSimulationCode(*sim, mainFunctionType);
-}
-} // namespace
+#include "Core/Simulation/ISimulation.h"
 
 std::string ExportToPython::generateSampleCode(const MultiLayer& multilayer) {
-    SampleToPython generator;
-    return generator.generateSampleCode(multilayer);
+    return SampleToPython().generateSampleCode(multilayer);
 }
 
 std::string ExportToPython::generateSimulationCode(const ISimulation& simulation) {
-    return simulationCode(simulation, SimulationToPython::RUN_SIMULATION);
-}
+    std::unique_ptr<ISimulation> sim(simulation.clone());
+    sim->prepareSimulation();
 
-std::string ExportToPython::generatePyExportTest(const ISimulation& simulation) {
-    return simulationCode(simulation, SimulationToPython::SAVE_DATA);
+    return SimulationToPython().generateSimulationCode(*sim);
 }
diff --git a/Core/Export/ExportToPython.h b/Core/Export/ExportToPython.h
index d74a5a1d9cd82eaa5f1d91b91a64d29f57fb3ace..ff2ad0d87c1e510e2635f213e85979e74f0ffcb4 100644
--- a/Core/Export/ExportToPython.h
+++ b/Core/Export/ExportToPython.h
@@ -26,7 +26,6 @@ namespace ExportToPython {
 
 std::string generateSampleCode(const MultiLayer& multilayer);
 std::string generateSimulationCode(const ISimulation& simulation);
-std::string generatePyExportTest(const ISimulation& simulation);
 
 } // namespace ExportToPython
 
diff --git a/Core/Export/PyFmt2.cpp b/Core/Export/PyFmt2.cpp
index 395036944278a4f48e64abd1b4a7b75fa8957657..67d8c641e7077c6e06b7f5beb99172ce4919fbcb 100644
--- a/Core/Export/PyFmt2.cpp
+++ b/Core/Export/PyFmt2.cpp
@@ -12,12 +12,13 @@
 //
 //  ************************************************************************************************
 
-#include "Device/Instrument/PyFmt2.h"
+#include "Core/Export/PyFmt2.h"
 #include "Base/Const/Units.h"
 #include "Base/Math/Constants.h"
 #include "Base/Utils/Algorithms.h"
 #include "Base/Utils/PyFmt.h"
 #include "Base/Utils/StringUtils.h"
+#include "Core/Export/PyFmtLimits.h"
 #include "Device/Mask/Ellipse.h"
 #include "Device/Mask/InfinitePlane.h"
 #include "Device/Mask/Line.h"
@@ -27,7 +28,7 @@
 #include "Param/Base/RealParameter.h"
 #include "Param/Distrib/Distributions.h"
 #include "Param/Distrib/ParameterDistribution.h"
-#include "Param/Varia/PyFmtLimits.h"
+#include "Param/Distrib/RangedDistributions.h"
 #include <iomanip>
 
 namespace pyfmt2 {
@@ -132,4 +133,15 @@ std::string printParameterDistribution(const ParameterDistribution& par_distr,
     return result.str();
 }
 
+std::string printRangedDistribution(const IRangedDistribution& distr) {
+    std::ostringstream result;
+    result << pyfmt::indent() << "distribution = ba.";
+    result << distr.name();
+    result << "(" << distr.nSamples() << ", " << pyfmt::printDouble(distr.sigmaFactor());
+    if (!distr.limits().isLimitless())
+        result << pyfmt::printRealLimitsArg(distr.limits());
+    result << ")";
+    return result.str();
+}
+
 } // namespace pyfmt2
diff --git a/Device/Instrument/PyFmt2.h b/Core/Export/PyFmt2.h
similarity index 91%
rename from Device/Instrument/PyFmt2.h
rename to Core/Export/PyFmt2.h
index 099af771478b5cab98ce7ecf99b43024890b6ead..6cf8b4380cd3850a07af0da76b061d9a714f0c0b 100644
--- a/Device/Instrument/PyFmt2.h
+++ b/Core/Export/PyFmt2.h
@@ -2,7 +2,7 @@
 //
 //  BornAgain: simulate and fit scattering at grazing incidence
 //
-//! @file      Device/Instrument/PyFmt2.h
+//! @file      Core/Export/PyFmt2.h
 //! @brief     Defines namespace pyfmt2.
 //!
 //! @homepage  http://www.bornagainproject.org
@@ -21,8 +21,9 @@
 class IDistribution1D;
 class IParameterized;
 class IShape2D;
-class RealParameter;
 class ParameterDistribution;
+class IRangedDistribution;
+class RealParameter;
 
 //! Utility functions for writing Python code snippets.
 
@@ -39,6 +40,9 @@ std::string printDistribution(const IDistribution1D& par_distr, const std::strin
 std::string printParameterDistribution(const ParameterDistribution& par_distr,
                                        const std::string& distVarName,
                                        const std::string& units = "");
+
+std::string printRangedDistribution(const IRangedDistribution& distr);
+
 } // namespace pyfmt2
 
 #endif // BORNAGAIN_DEVICE_INSTRUMENT_PYFMT2_H
diff --git a/Param/Varia/PyFmtLimits.cpp b/Core/Export/PyFmtLimits.cpp
similarity index 96%
rename from Param/Varia/PyFmtLimits.cpp
rename to Core/Export/PyFmtLimits.cpp
index 816dd668215a53c53bd531c312cc50b8c0172cff..dbfb64c6058a2aa25d292008b492c6246936a628 100644
--- a/Param/Varia/PyFmtLimits.cpp
+++ b/Core/Export/PyFmtLimits.cpp
@@ -2,7 +2,7 @@
 //
 //  BornAgain: simulate and fit scattering at grazing incidence
 //
-//! @file      Param/Varia/PyFmtLimits.cpp
+//! @file      Core/Export/PyFmtLimits.cpp
 //! @brief     Implements functions from namespace pyfmt.
 //!
 //! @homepage  http://www.bornagainproject.org
@@ -12,7 +12,7 @@
 //
 //  ************************************************************************************************
 
-#include "Param/Varia/PyFmtLimits.h"
+#include "Core/Export/PyFmtLimits.h"
 #include "Base/Utils/PyFmt.h"
 #include "Fit/Param/RealLimits.h"
 #include <iomanip>
diff --git a/Param/Varia/PyFmtLimits.h b/Core/Export/PyFmtLimits.h
similarity index 96%
rename from Param/Varia/PyFmtLimits.h
rename to Core/Export/PyFmtLimits.h
index 4ffd3ebd634abe2009a72fcd38e3dc0396ef5017..60cd8181a996e500b9e84c0dfd11215f8826239d 100644
--- a/Param/Varia/PyFmtLimits.h
+++ b/Core/Export/PyFmtLimits.h
@@ -2,7 +2,7 @@
 //
 //  BornAgain: simulate and fit scattering at grazing incidence
 //
-//! @file      Param/Varia/PyFmtLimits.h
+//! @file      Core/Export/PyFmtLimits.h
 //! @brief     Defines functions in namespace pyfmt.
 //!
 //! @homepage  http://www.bornagainproject.org
diff --git a/Core/Export/SampleLabelHandler.cpp b/Core/Export/SampleLabelHandler.cpp
index 611990dcd9f1cec31b499be2f7171cc2cd35ad66..ce9b858d33b87a4a6071c1e67eb7ec35d791d58d 100644
--- a/Core/Export/SampleLabelHandler.cpp
+++ b/Core/Export/SampleLabelHandler.cpp
@@ -70,8 +70,7 @@ std::string SampleLabelHandler::labelParticle(const IAbstractParticle* abspartic
         return m_ParticleCompositionLabel[lattice_basis];
     if (const auto mesocrystal = dynamic_cast<const MesoCrystal*>(absparticle))
         return m_MesoCrystalLabel[mesocrystal];
-    throw Exceptions::NotImplementedException(
-        "SampleLabelHandler::getLabel: called for unknown IParticle type");
+    throw std::runtime_error("SampleLabelHandler::getLabel: called for unknown IParticle type");
 }
 
 std::string SampleLabelHandler::labelRotation(const IRotation* rot) {
diff --git a/Core/Export/SampleLabelHandler.h b/Core/Export/SampleLabelHandler.h
index 10c136a3dd3d97cdd76aa2b01ea4940abd427205..9d9a0f5cec54db5b116f073f2d2b0ed17743da01 100644
--- a/Core/Export/SampleLabelHandler.h
+++ b/Core/Export/SampleLabelHandler.h
@@ -15,7 +15,6 @@
 #ifndef BORNAGAIN_CORE_EXPORT_SAMPLELABELHANDLER_H
 #define BORNAGAIN_CORE_EXPORT_SAMPLELABELHANDLER_H
 
-#include "Base/Types/Exceptions.h"
 #include "Core/Export/OrderedMap.h"
 
 class Crystal;
diff --git a/Core/Export/SampleToPython.cpp b/Core/Export/SampleToPython.cpp
index 4dd93ef4ad02dfa4e643cf71a61881631e7f11c6..1d5d7d150a2fb76b293ab7f887b4d4dc3033b96f 100644
--- a/Core/Export/SampleToPython.cpp
+++ b/Core/Export/SampleToPython.cpp
@@ -16,8 +16,8 @@
 #include "Base/Utils/PyFmt.h"
 #include "Base/Vector/Transform3D.h"
 #include "Core/Export/INodeUtils.h"
+#include "Core/Export/PyFmt2.h"
 #include "Core/Export/SampleLabelHandler.h"
-#include "Device/Instrument/PyFmt2.h"
 #include "Param/Varia/ParameterUtils.h"
 #include "Sample/Aggregate/InterferenceFunctions.h"
 #include "Sample/Aggregate/ParticleLayout.h"
@@ -85,12 +85,11 @@ SampleToPython::SampleToPython() = default;
 SampleToPython::~SampleToPython() = default;
 
 std::string SampleToPython::defineGetSample() const {
-    return "def " + pyfmt::getSampleFunctionName() + "():\n" + defineMaterials() + defineLayers()
-           + defineFormFactors() + defineParticles() + defineCoreShellParticles()
-           + defineParticleCompositions() + defineLattices2D() + defineLattices3D()
-           + defineCrystals() + defineMesoCrystals() + defineParticleDistributions()
-           + defineInterferenceFunctions() + defineParticleLayouts() + defineRoughnesses()
-           + addLayoutsToLayers() + defineMultiLayers() + "\n\n";
+    return "def get_sample():\n" + defineMaterials() + defineLayers() + defineFormFactors()
+           + defineParticles() + defineCoreShellParticles() + defineParticleCompositions()
+           + defineLattices2D() + defineLattices3D() + defineCrystals() + defineMesoCrystals()
+           + defineParticleDistributions() + defineInterferenceFunctions() + defineParticleLayouts()
+           + defineRoughnesses() + addLayoutsToLayers() + defineMultiLayers() + "\n\n";
 }
 
 const std::map<MATERIAL_TYPES, std::string> factory_names{
@@ -478,7 +477,7 @@ std::string SampleToPython::defineInterferenceFunctions() const {
                    << pyfmt::printDouble(lattice_hd->density()) << ")\n";
 
         } else
-            throw Exceptions::NotImplementedException(
+            throw std::runtime_error(
                 "Bug: ExportToPython::defineInterferenceFunctions() called with unexpected "
                 "IInterferenceFunction "
                 + interference->getName());
diff --git a/Core/Export/SimulationToPython.cpp b/Core/Export/SimulationToPython.cpp
index dc5fab1dc2cc0a3488817e1534bd3d27dd36e569..376c136879f5451b1fe0df14a7410856669f3f4f 100644
--- a/Core/Export/SimulationToPython.cpp
+++ b/Core/Export/SimulationToPython.cpp
@@ -18,8 +18,11 @@
 #include "Core/Computation/ConstantBackground.h"
 #include "Core/Computation/PoissonNoiseBackground.h"
 #include "Core/Export/INodeUtils.h"
+#include "Core/Export/PyFmt2.h"
+#include "Core/Export/PyFmtLimits.h"
 #include "Core/Export/SampleToPython.h"
-#include "Core/Scan/ISpecularScan.h"
+#include "Core/Scan/AngularSpecScan.h"
+#include "Core/Scan/QSpecScan.h"
 #include "Core/Simulation/GISASSimulation.h"
 #include "Core/Simulation/OffSpecSimulation.h"
 #include "Core/Simulation/SpecularSimulation.h"
@@ -28,34 +31,23 @@
 #include "Device/Detector/RectangularDetector.h"
 #include "Device/Detector/RegionOfInterest.h"
 #include "Device/Detector/SphericalDetector.h"
-#include "Device/Instrument/PyFmt2.h"
 #include "Device/Resolution/ConvolutionDetectorResolution.h"
 #include "Device/Resolution/ResolutionFunction2DGaussian.h"
+#include "Device/Resolution/ScanResolution.h"
+#include "Param/Distrib/RangedDistributions.h"
 #include "Param/Varia/ParameterUtils.h"
-#include "Param/Varia/PyFmtLimits.h"
 #include <iomanip>
 
 using pyfmt::indent;
 
 namespace {
-const std::string defineSimulate = "def run_simulation():\n"
-                                   "    sample = "
-                                   + pyfmt::getSampleFunctionName()
-                                   + "()\n"
-                                     "    simulation = get_simulation()\n"
-                                     "    simulation.setSample(sample)\n"
-                                     "    simulation.runSimulation()\n"
-                                     "    return simulation.result()\n"
-                                     "\n\n";
-
 //! Returns a function that converts a coordinate to a Python code snippet with appropiate unit
 std::function<std::string(double)> printFunc(const IDetector* detector) {
     if (detector->defaultAxesUnits() == Axes::Units::MM)
         return pyfmt::printDouble;
     if (detector->defaultAxesUnits() == Axes::Units::RADIANS)
         return pyfmt::printDegrees;
-    throw Exceptions::RuntimeErrorException(
-        "SimulationToPython::defineMasks() -> Error. Unknown detector units.");
+    throw std::runtime_error("SimulationToPython::defineMasks() -> Error. Unknown detector units.");
 }
 
 //! returns true if it is (0, -1, 0) vector
@@ -64,85 +56,81 @@ bool isDefaultDirection(const kvector_t direction) {
            && algo::almostEqual(direction.z(), 0.0);
 }
 
-} // namespace
-
-//! Returns a Python script that sets up a simulation and runs it if invoked as main program.
-
-std::string SimulationToPython::generateSimulationCode(const ISimulation& simulation,
-                                                       EMainType mainType) {
-    if (simulation.sample() == nullptr)
-        throw std::runtime_error("SimulationToPython::generateSimulationCode() -> Error. "
-                                 "ISimulation is not initialized.");
-
-    SampleToPython sampleGenerator;
-
-    return pyfmt::scriptPreamble() + sampleGenerator.generateSampleCode(*simulation.sample())
-           + defineGetSimulation(&simulation) + defineSimulate + defineMain(mainType);
-}
-
-std::string SimulationToPython::defineGetSimulation(const ISimulation* simulation) const {
+const std::string defineSimulate = "def run_simulation():\n"
+                                   "    sample = get_sample()\n"
+                                   "    simulation = get_simulation()\n"
+                                   "    simulation.setSample(sample)\n"
+                                   "    simulation.runSimulation()\n"
+                                   "    return simulation.result()\n"
+                                   "\n\n";
+
+std::string defineFootprintFactor(const IFootprintFactor& foot) {
     std::ostringstream result;
-    result << "def get_simulation():\n";
-
-    if (auto gisas = dynamic_cast<const GISASSimulation*>(simulation))
-        result << defineGISASSimulation(gisas);
-    else if (auto offspec = dynamic_cast<const OffSpecSimulation*>(simulation))
-        result << defineOffSpecSimulation(offspec);
-    else if (auto spec = dynamic_cast<const SpecularSimulation*>(simulation))
-        result << defineSpecularSimulation(spec);
-    else
-        throw std::runtime_error("SimulationToPython::defineGetSimulation() -> Error. "
-                                 "Wrong simulation type");
-
-    result << indent() << "return simulation\n\n\n";
+    result << indent() << "footprint = ba." << foot.name();
+    result << "(" << pyfmt::printDouble(foot.widthRatio()) << ")\n";
     return result.str();
 }
 
-std::string SimulationToPython::defineGISASSimulation(const GISASSimulation* simulation) const {
+std::string defineScanResolution(const ScanResolution& scan) {
     std::ostringstream result;
-    result << indent() << "simulation = ba.GISASSimulation()\n";
-    result << defineDetector(simulation);
-    result << defineDetectorResolutionFunction(simulation);
-    result << defineDetectorPolarizationAnalysis(simulation);
-    result << defineGISASBeam(*simulation);
-    result << defineParameterDistributions(simulation);
-    result << defineMasks(simulation);
-    result << defineSimulationOptions(simulation);
-    result << defineBackground(simulation);
+    result << pyfmt2::printRangedDistribution(*scan.distribution()) << "\n"
+           << indent() << "resolution = "
+           << "ba." << scan.name() << "(distribution, "
+           << pyfmt::printDouble(scan.delta()) << ")\n";
     return result.str();
 }
 
-std::string SimulationToPython::defineOffSpecSimulation(const OffSpecSimulation* simulation) const {
+std::string defineAngularSpecScan(const AngularSpecScan& scan) {
     std::ostringstream result;
-    result << indent() << "simulation = ba.OffSpecSimulation()\n";
-    result << defineDetector(simulation);
-    result << defineDetectorResolutionFunction(simulation);
-    result << defineDetectorPolarizationAnalysis(simulation);
-    result << defineOffSpecBeam(*simulation);
-    result << defineParameterDistributions(simulation);
-    result << defineMasks(simulation);
-    result << defineSimulationOptions(simulation);
-    result << defineBackground(simulation);
+    result << "\n"
+           << indent() << "# Define specular scan:\n"
+           << indent() << "axis = " << scan.coordinateAxis()->pyString("rad", 17 /*TODO*/)
+           << "\n"
+           << indent() << "scan = "
+           << "ba.AngularSpecScan(" << pyfmt::printDouble(scan.wavelength()) << ", axis)\n";
+
+    if (scan.footprintFactor()) {
+        result << defineFootprintFactor(*scan.footprintFactor());
+        result << indent() << "scan.setFootprintFactor(footprint)\n";
+    }
+    if (const auto* r = scan.angleResolution(); r && r->distribution()) {
+        result << defineScanResolution(*r) << "\n";
+        result << indent() << "scan.setAngleResolution(resolution)\n";
+    }
+    if (const auto* r = scan.wavelengthResolution(); r && r->distribution()) {
+        result << defineScanResolution(*r) << "\n";
+        result << indent() << "scan.setWavelengthResolution(resolution)\n";
+    }
     return result.str();
 }
 
-std::string
-SimulationToPython::defineSpecularSimulation(const SpecularSimulation* simulation) const {
+std::string defineQSpecScan(const QSpecScan& scan) {
     std::ostringstream result;
-    result << indent() << "simulation = ba.SpecularSimulation()\n";
-    result << defineDetectorPolarizationAnalysis(simulation);
-    result << defineSpecularScan(*simulation);
-    result << defineParameterDistributions(simulation);
-    result << defineSimulationOptions(simulation);
-    result << defineBackground(simulation);
+    const std::string axis_def = indent() + "axis = ";
+    result << axis_def << scan.coordinateAxis()->pyString("", axis_def.size()) << "\n";
+
+    result << indent() << "scan = ba.QSpecScan(axis)";
+    if (scan.resolution()) {
+        result << "\n";
+        result << defineScanResolution(*scan.resolution()) << "\n";
+        result << indent() << "scan.setQResolution(resolution)";
+    }
     return result.str();
 }
 
-std::string SimulationToPython::defineDetector(const ISimulation* simulation) const {
+std::string defineScan(const ISpecularScan* scan) {
+    if (const auto* s = dynamic_cast<const AngularSpecScan*>(scan); s)
+        return defineAngularSpecScan(*s);
+    if (const auto* s = dynamic_cast<const QSpecScan*>(scan); s)
+        return defineQSpecScan(*s);
+    ASSERT(0);
+}
+
+std::string defineDetector(const ISimulation* simulation) {
     const IDetector* const detector = simulation->instrument().getDetector();
     if (detector->dimension() != 2)
-        throw Exceptions::RuntimeErrorException("SimulationToPython::defineDetector: "
-                                                "detector must be two-dimensional for GISAS");
+        throw std::runtime_error("defineDetector: "
+                                 "detector must be two-dimensional for GISAS");
     std::ostringstream result;
     result << std::setprecision(12);
 
@@ -158,8 +146,8 @@ std::string SimulationToPython::defineDetector(const ISimulation* simulation) co
         result << ")\n";
     } else if (const auto* const det = dynamic_cast<const RectangularDetector*>(detector)) {
         result << "\n";
-        result << indent() << "detector = ba.RectangularDetector(" << det->getNbinsX()
-               << ", " << pyfmt::printDouble(det->getWidth()) << ", " << det->getNbinsY() << ", "
+        result << indent() << "detector = ba.RectangularDetector(" << det->getNbinsX() << ", "
+               << pyfmt::printDouble(det->getWidth()) << ", " << det->getNbinsY() << ", "
                << pyfmt::printDouble(det->getHeight()) << ")\n";
         if (det->getDetectorArrangment() == RectangularDetector::GENERIC) {
             result << indent() << "detector.setPosition("
@@ -193,13 +181,11 @@ std::string SimulationToPython::defineDetector(const ISimulation* simulation) co
                    << pyfmt::printDouble(det->getDirectBeamU0()) << ", "
                    << pyfmt::printDouble(det->getDirectBeamV0()) << ")\n";
         } else
-            throw Exceptions::RuntimeErrorException(
-                "SimulationToPython::defineDetector() -> Error. Unknown alignment.");
+            throw std::runtime_error("defineDetector() -> Error. Unknown alignment.");
 
         result << indent() << "simulation.setDetector(detector)\n";
     } else
-        throw Exceptions::RuntimeErrorException("SimulationToPython::defineDetector() -> Error. "
-                                                "Unknown detector");
+        throw std::runtime_error("defineDetector() -> Error. Unknown detector");
     if (detector->regionOfInterest()) {
         result << indent() << "simulation.setRegionOfInterest("
                << printFunc(detector)(detector->regionOfInterest()->getXlow()) << ", "
@@ -211,33 +197,29 @@ std::string SimulationToPython::defineDetector(const ISimulation* simulation) co
     return result.str();
 }
 
-std::string
-SimulationToPython::defineDetectorResolutionFunction(const ISimulation* simulation) const {
+std::string defineDetectorResolutionFunction(const ISimulation* simulation) {
     std::ostringstream result;
     const IDetector* detector = simulation->instrument().getDetector();
 
-    if (const IDetectorResolution* p_resfunc = detector->detectorResolution()) {
-        if (auto* p_convfunc = dynamic_cast<const ConvolutionDetectorResolution*>(p_resfunc)) {
+    if (const IDetectorResolution* resfunc = detector->detectorResolution()) {
+        if (auto* convfunc = dynamic_cast<const ConvolutionDetectorResolution*>(resfunc)) {
             if (auto* resfunc = dynamic_cast<const ResolutionFunction2DGaussian*>(
-                    p_convfunc->getResolutionFunction2D())) {
+                    convfunc->getResolutionFunction2D())) {
                 result << indent() << "simulation.setDetectorResolutionFunction(";
                 result << "ba.ResolutionFunction2DGaussian(";
                 result << printFunc(detector)(resfunc->getSigmaX()) << ", ";
                 result << printFunc(detector)(resfunc->getSigmaY()) << "))\n";
             } else
-                throw Exceptions::RuntimeErrorException(
-                    "SimulationToPython::defineDetectorResolutionFunction() -> Error. "
-                    "Unknown detector resolution function");
+                throw std::runtime_error("defineDetectorResolutionFunction() -> Error. "
+                                         "Unknown detector resolution function");
         } else
-            throw Exceptions::RuntimeErrorException(
-                "SimulationToPython::defineDetectorResolutionFunction() -> Error. "
-                "Not a ConvolutionDetectorResolution function");
+            throw std::runtime_error("defineDetectorResolutionFunction() -> Error. "
+                                     "Not a ConvolutionDetectorResolution function");
     }
     return result.str();
 }
 
-std::string
-SimulationToPython::defineDetectorPolarizationAnalysis(const ISimulation* simulation) const {
+std::string defineDetectorPolarizationAnalysis(const ISimulation* simulation) {
     std::ostringstream result;
     const IDetector* detector = simulation->instrument().getDetector();
     kvector_t analyzer_direction = detector->detectionProperties().analyzerDirection();
@@ -258,13 +240,36 @@ SimulationToPython::defineDetectorPolarizationAnalysis(const ISimulation* simula
     return result.str();
 }
 
-std::string SimulationToPython::defineGISASBeam(const GISASSimulation& simulation) const {
+std::string defineBeamPolarization(const Beam& beam) {
+    std::ostringstream result;
+    auto bloch_vector = beam.getBlochVector();
+    if (bloch_vector.mag() > 0.0) {
+        std::string beam_polarization = "beam_polarization";
+        result << indent() << beam_polarization << " = kvector_t("
+               << pyfmt::printDouble(bloch_vector.x()) << ", "
+               << pyfmt::printDouble(bloch_vector.y()) << ", "
+               << pyfmt::printDouble(bloch_vector.z()) << ")\n";
+        result << indent() << "simulation.setBeamPolarization(" << beam_polarization << ")\n";
+    }
+    return result.str();
+}
+
+std::string defineBeamIntensity(const Beam& beam) {
+    std::ostringstream result;
+    double beam_intensity = beam.getIntensity();
+    if (beam_intensity > 0.0)
+        result << indent() << "simulation.setBeamIntensity("
+               << pyfmt::printScientificDouble(beam_intensity) << ")\n";
+    return result.str();
+}
+
+std::string defineGISASBeam(const GISASSimulation& simulation) {
     std::ostringstream result;
     const Beam& beam = simulation.instrument().beam();
 
-    result << indent() << "simulation.setBeamParameters("
-           << pyfmt::printNm(beam.getWavelength()) << ", " << pyfmt::printDegrees(beam.getAlpha())
-           << ", " << pyfmt::printDegrees(beam.getPhi()) << ")\n";
+    result << indent() << "simulation.setBeamParameters(" << pyfmt::printNm(beam.getWavelength())
+           << ", " << pyfmt::printDegrees(beam.getAlpha()) << ", "
+           << pyfmt::printDegrees(beam.getPhi()) << ")\n";
 
     result << defineBeamPolarization(beam);
     result << defineBeamIntensity(beam);
@@ -272,15 +277,15 @@ std::string SimulationToPython::defineGISASBeam(const GISASSimulation& simulatio
     return result.str();
 }
 
-std::string SimulationToPython::defineOffSpecBeam(const OffSpecSimulation& simulation) const {
+std::string defineOffSpecBeam(const OffSpecSimulation& simulation) {
     std::ostringstream result;
     const Beam& beam = simulation.instrument().beam();
 
-    const std::string axis_def = indent() + "alpha_i_axis = ";
-    result << axis_def << simulation.beamAxis()->pyString("rad", axis_def.size()) << "\n";
+    const std::string axidef = indent() + "alpha_i_axis = ";
+    result << axidef << simulation.beamAxis()->pyString("rad", axidef.size()) << "\n";
 
-    result << indent() << "simulation.setBeamParameters("
-           << pyfmt::printNm(beam.getWavelength()) << ", "
+    result << indent() << "simulation.setBeamParameters(" << pyfmt::printNm(beam.getWavelength())
+           << ", "
            << "alpha_i_axis, " << pyfmt::printDegrees(beam.getPhi()) << ")\n";
 
     result << defineBeamPolarization(beam);
@@ -288,45 +293,19 @@ std::string SimulationToPython::defineOffSpecBeam(const OffSpecSimulation& simul
     return result.str();
 }
 
-std::string SimulationToPython::defineSpecularScan(const SpecularSimulation& simulation) const {
+std::string defineSpecularScan(const SpecularSimulation& simulation) {
     std::ostringstream result;
     const ISpecularScan* scan = simulation.dataHandler();
     if (!scan)
-        throw std::runtime_error("Error SimulationToPython::defineSpecularScan: passed simulation "
+        throw std::runtime_error("Error defineSpecularScan: passed simulation "
                                  "does not contain any scan");
-    result << *scan << "\n";
-
+    result << defineScan(scan) << "\n";
     result << indent() << "simulation.setScan(scan)\n";
-    result << defineBeamIntensity(simulation.instrument().beam());
-    result << "\n";
+    result << defineBeamIntensity(simulation.instrument().beam()) << "\n";
     return result.str();
 }
 
-std::string SimulationToPython::defineBeamPolarization(const Beam& beam) const {
-    std::ostringstream result;
-    auto bloch_vector = beam.getBlochVector();
-    if (bloch_vector.mag() > 0.0) {
-        std::string beam_polarization = "beam_polarization";
-        result << indent() << beam_polarization << " = kvector_t("
-               << pyfmt::printDouble(bloch_vector.x()) << ", "
-               << pyfmt::printDouble(bloch_vector.y()) << ", "
-               << pyfmt::printDouble(bloch_vector.z()) << ")\n";
-        result << indent() << "simulation.setBeamPolarization(" << beam_polarization
-               << ")\n";
-    }
-    return result.str();
-}
-
-std::string SimulationToPython::defineBeamIntensity(const Beam& beam) const {
-    std::ostringstream result;
-    double beam_intensity = beam.getIntensity();
-    if (beam_intensity > 0.0)
-        result << indent() << "simulation.setBeamIntensity("
-               << pyfmt::printScientificDouble(beam_intensity) << ")\n";
-    return result.str();
-}
-
-std::string SimulationToPython::defineParameterDistributions(const ISimulation* simulation) const {
+std::string defineParameterDistributions(const ISimulation* simulation) {
     std::ostringstream result;
     const std::vector<ParameterDistribution>& distributions =
         simulation->getDistributionHandler().getDistributions();
@@ -340,20 +319,19 @@ std::string SimulationToPython::defineParameterDistributions(const ISimulation*
         size_t nbr_samples = distributions[i].getNbrSamples();
         double sigma_factor = distributions[i].getSigmaFactor();
 
-        std::string s_distr = "distr_" + std::to_string(i + 1);
-        result << indent() << s_distr << " = "
+        std::string distr = "distr_" + std::to_string(i + 1);
+        result << indent() << distr << " = "
                << pyfmt2::printDistribution(*distributions[i].getDistribution(), mainParUnits)
                << "\n";
 
-        result << indent() << "simulation.addParameterDistribution(\"" << main_par_name
-               << "\", " << s_distr << ", " << nbr_samples << ", "
-               << pyfmt::printDouble(sigma_factor)
+        result << indent() << "simulation.addParameterDistribution(\"" << main_par_name << "\", "
+               << distr << ", " << nbr_samples << ", " << pyfmt::printDouble(sigma_factor)
                << pyfmt::printRealLimitsArg(distributions[i].getLimits(), mainParUnits) << ")\n";
     }
     return result.str();
 }
 
-std::string SimulationToPython::defineMasks(const ISimulation* simulation) const {
+std::string defineMasks(const ISimulation* simulation) {
     std::ostringstream result;
     result << std::setprecision(12);
 
@@ -364,15 +342,14 @@ std::string SimulationToPython::defineMasks(const ISimulation* simulation) const
         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);
-            result << pyfmt2::representShape2D(indent(), shape, mask_value,
-                                               printFunc(detector));
+            result << pyfmt2::representShape2D(indent(), shape, mask_value, printFunc(detector));
         }
         result << "\n";
     }
     return result.str();
 }
 
-std::string SimulationToPython::defineSimulationOptions(const ISimulation* simulation) const {
+std::string defineSimulationOptions(const ISimulation* simulation) {
     std::ostringstream result;
     result << std::setprecision(12);
 
@@ -390,39 +367,100 @@ std::string SimulationToPython::defineSimulationOptions(const ISimulation* simul
     return result.str();
 }
 
-std::string SimulationToPython::defineBackground(const ISimulation* simulation) const {
+std::string defineBackground(const ISimulation* simulation) {
     std::ostringstream result;
 
-    auto p_bg = simulation->background();
-    if (auto p_constant_bg = dynamic_cast<const ConstantBackground*>(p_bg)) {
-        if (p_constant_bg->backgroundValue() > 0.0) {
+    auto bg = simulation->background();
+    if (auto constant_bg = dynamic_cast<const ConstantBackground*>(bg)) {
+        if (constant_bg->backgroundValue() > 0.0) {
             result << indent() << "background = ba.ConstantBackground("
-                   << pyfmt::printScientificDouble(p_constant_bg->backgroundValue()) << ")\n";
+                   << pyfmt::printScientificDouble(constant_bg->backgroundValue()) << ")\n";
             result << indent() << "simulation.setBackground(background)\n";
         }
-    } else if (dynamic_cast<const PoissonNoiseBackground*>(p_bg)) {
+    } else if (dynamic_cast<const PoissonNoiseBackground*>(bg)) {
         result << indent() << "background = ba.PoissonNoiseBackground()\n";
         result << indent() << "simulation.setBackground(background)\n";
     }
     return result.str();
 }
 
-std::string SimulationToPython::defineMain(SimulationToPython::EMainType mainType) {
-    std::string result;
-    if (mainType == RUN_SIMULATION) {
-        result = "if __name__ == '__main__':\n"
-                 "    result = run_simulation()\n"
-                 "    ba.plot_simulation_result(result)\n";
-    } else if (mainType == SAVE_DATA) {
-        result = "if __name__ == '__main__':\n"
-                 "    result = run_simulation()\n"
-                 "    import sys\n"
-                 "    if len(sys.argv)>=2:\n"
-                 "        ba.IntensityDataIOFactory.writeSimulationResult(result, sys.argv[1])\n"
-                 "    else:\n"
-                 "        ba.plot_simulation_result(result, cmap='jet', aspect='auto')\n";
-    } else {
-        throw std::runtime_error("SimulationToPython::defineMain() -> Error. Unknown main type.");
-    }
-    return result;
+std::string defineGISASSimulation(const GISASSimulation* simulation) {
+    std::ostringstream result;
+    result << indent() << "simulation = ba.GISASSimulation()\n";
+    result << defineDetector(simulation);
+    result << defineDetectorResolutionFunction(simulation);
+    result << defineDetectorPolarizationAnalysis(simulation);
+    result << defineGISASBeam(*simulation);
+    result << defineParameterDistributions(simulation);
+    result << defineMasks(simulation);
+    result << defineSimulationOptions(simulation);
+    result << defineBackground(simulation);
+    return result.str();
+}
+
+std::string defineOffSpecSimulation(const OffSpecSimulation* simulation) {
+    std::ostringstream result;
+    result << indent() << "simulation = ba.OffSpecSimulation()\n";
+    result << defineDetector(simulation);
+    result << defineDetectorResolutionFunction(simulation);
+    result << defineDetectorPolarizationAnalysis(simulation);
+    result << defineOffSpecBeam(*simulation);
+    result << defineParameterDistributions(simulation);
+    result << defineMasks(simulation);
+    result << defineSimulationOptions(simulation);
+    result << defineBackground(simulation);
+    return result.str();
+}
+
+std::string defineSpecularSimulation(const SpecularSimulation* simulation) {
+    std::ostringstream result;
+    result << indent() << "simulation = ba.SpecularSimulation()\n";
+    result << defineDetectorPolarizationAnalysis(simulation);
+    result << defineSpecularScan(*simulation);
+    result << defineParameterDistributions(simulation);
+    result << defineSimulationOptions(simulation);
+    result << defineBackground(simulation);
+    return result.str();
+}
+
+std::string defineGetSimulation(const ISimulation* simulation) {
+    std::ostringstream result;
+    result << "def get_simulation():\n";
+
+    if (auto gisas = dynamic_cast<const GISASSimulation*>(simulation))
+        result << defineGISASSimulation(gisas);
+    else if (auto offspec = dynamic_cast<const OffSpecSimulation*>(simulation))
+        result << defineOffSpecSimulation(offspec);
+    else if (auto spec = dynamic_cast<const SpecularSimulation*>(simulation))
+        result << defineSpecularSimulation(spec);
+    else
+        throw std::runtime_error("defineGetSimulation() -> Error. "
+                                 "Wrong simulation type");
+
+    result << indent() << "return simulation\n\n\n";
+    return result.str();
+}
+
+const std::string defineMain =
+    "if __name__ == '__main__':\n"
+    "    result = run_simulation()\n"
+    "    import sys\n"
+    "    if len(sys.argv)>=2:\n"
+    "        ba.IntensityDataIOFactory.writeSimulationResult(result, sys.argv[1])\n"
+    "    else:\n"
+    "        ba.plot_simulation_result(result, cmap='jet', aspect='auto')\n";
+
+} // namespace
+
+//! Returns a Python script that sets up a simulation and runs it if invoked as main program.
+
+std::string SimulationToPython::generateSimulationCode(const ISimulation& simulation) {
+    if (simulation.sample() == nullptr)
+        throw std::runtime_error("SimulationToPython::generateSimulationCode() -> Error. "
+                                 "ISimulation is not initialized.");
+
+    SampleToPython sampleGenerator;
+
+    return pyfmt::scriptPreamble() + sampleGenerator.generateSampleCode(*simulation.sample())
+           + defineGetSimulation(&simulation) + defineSimulate + defineMain;
 }
diff --git a/Core/Export/SimulationToPython.h b/Core/Export/SimulationToPython.h
index afcdc9b0ef8083cd1ed8fec32861cce904445687..13b4abacf5d10f5fdbd8bca2bc7523ab693014ca 100644
--- a/Core/Export/SimulationToPython.h
+++ b/Core/Export/SimulationToPython.h
@@ -15,49 +15,15 @@
 #ifndef BORNAGAIN_CORE_EXPORT_SIMULATIONTOPYTHON_H
 #define BORNAGAIN_CORE_EXPORT_SIMULATIONTOPYTHON_H
 
-#include <memory>
 #include <string>
 
-class Beam;
-class IFootprintFactor;
-class GISASSimulation;
-class OffSpecSimulation;
 class ISimulation;
-class SpecularSimulation;
 
 //! Write a Python script that allows to run the current simulation.
 
 class SimulationToPython {
 public:
-    enum EMainType {
-        RUN_SIMULATION, //!< main function runs simulation
-        SAVE_DATA       //!< main function saves intensity data
-    };
-
-    std::string generateSimulationCode(const ISimulation& simulation, EMainType mainType);
-
-private:
-    std::string definePreamble() const;
-    std::string defineGetSimulation(const ISimulation* simulation) const;
-    std::string defineGISASSimulation(const GISASSimulation* simulation) const;
-    std::string defineOffSpecSimulation(const OffSpecSimulation* simulation) const;
-    std::string defineSpecularSimulation(const SpecularSimulation* simulation) const;
-    std::string defineDetector(const ISimulation* simulation) const;
-    std::string defineDetectorResolutionFunction(const ISimulation* simulation) const;
-    std::string defineDetectorPolarizationAnalysis(const ISimulation* simulation) const;
-
-    std::string defineGISASBeam(const GISASSimulation& simulation) const;
-    std::string defineOffSpecBeam(const OffSpecSimulation& simulation) const;
-    std::string defineSpecularScan(const SpecularSimulation& simulation) const;
-
-    std::string defineBeamPolarization(const Beam& beam) const;
-    std::string defineBeamIntensity(const Beam& beam) const;
-
-    std::string defineParameterDistributions(const ISimulation* simulation) const;
-    std::string defineMasks(const ISimulation* simulation) const;
-    std::string defineSimulationOptions(const ISimulation* simulation) const;
-    std::string defineBackground(const ISimulation* simulation) const;
-    std::string defineMain(EMainType mainType = RUN_SIMULATION);
+    std::string generateSimulationCode(const ISimulation& simulation);
 };
 
 #endif // BORNAGAIN_CORE_EXPORT_SIMULATIONTOPYTHON_H
diff --git a/Core/Scan/AngularSpecScan.cpp b/Core/Scan/AngularSpecScan.cpp
index ffec862f5ccf88680cf418dd74b4c1a6529425af..2cc9cac4423f102c7e9481164108505a0e818502 100644
--- a/Core/Scan/AngularSpecScan.cpp
+++ b/Core/Scan/AngularSpecScan.cpp
@@ -15,7 +15,6 @@
 #include "Core/Scan/AngularSpecScan.h"
 #include "Base/Axis/FixedBinAxis.h"
 #include "Base/Axis/PointwiseAxis.h"
-#include "Base/Utils/PyFmt.h"
 #include "Core/Element/SpecularSimulationElement.h"
 #include "Device/Beam/IFootprintFactor.h"
 #include "Device/Resolution/ScanResolution.h"
@@ -107,28 +106,28 @@ void AngularSpecScan::setWavelengthResolution(const ScanResolution& resolution)
     m_wl_res_cache.shrink_to_fit();
 }
 
-void AngularSpecScan::setRelativeWavelengthResolution(const RangedDistribution& distr,
+void AngularSpecScan::setRelativeWavelengthResolution(const IRangedDistribution& distr,
                                                       double rel_dev) {
     std::unique_ptr<ScanResolution> resolution(
         ScanResolution::scanRelativeResolution(distr, rel_dev));
     setWavelengthResolution(*resolution);
 }
 
-void AngularSpecScan::setRelativeWavelengthResolution(const RangedDistribution& distr,
+void AngularSpecScan::setRelativeWavelengthResolution(const IRangedDistribution& distr,
                                                       const std::vector<double>& rel_dev) {
     std::unique_ptr<ScanResolution> resolution(
         ScanResolution::scanRelativeResolution(distr, rel_dev));
     setWavelengthResolution(*resolution);
 }
 
-void AngularSpecScan::setAbsoluteWavelengthResolution(const RangedDistribution& distr,
+void AngularSpecScan::setAbsoluteWavelengthResolution(const IRangedDistribution& distr,
                                                       double std_dev) {
     std::unique_ptr<ScanResolution> resolution(
         ScanResolution::scanAbsoluteResolution(distr, std_dev));
     setWavelengthResolution(*resolution);
 }
 
-void AngularSpecScan::setAbsoluteWavelengthResolution(const RangedDistribution& distr,
+void AngularSpecScan::setAbsoluteWavelengthResolution(const IRangedDistribution& distr,
                                                       const std::vector<double>& std_dev) {
     std::unique_ptr<ScanResolution> resolution(
         ScanResolution::scanAbsoluteResolution(distr, std_dev));
@@ -141,28 +140,28 @@ void AngularSpecScan::setAngleResolution(const ScanResolution& resolution) {
     m_inc_res_cache.shrink_to_fit();
 }
 
-void AngularSpecScan::setRelativeAngularResolution(const RangedDistribution& distr,
+void AngularSpecScan::setRelativeAngularResolution(const IRangedDistribution& distr,
                                                    double rel_dev) {
     std::unique_ptr<ScanResolution> resolution(
         ScanResolution::scanRelativeResolution(distr, rel_dev));
     setAngleResolution(*resolution);
 }
 
-void AngularSpecScan::setRelativeAngularResolution(const RangedDistribution& distr,
+void AngularSpecScan::setRelativeAngularResolution(const IRangedDistribution& distr,
                                                    const std::vector<double>& rel_dev) {
     std::unique_ptr<ScanResolution> resolution(
         ScanResolution::scanRelativeResolution(distr, rel_dev));
     setAngleResolution(*resolution);
 }
 
-void AngularSpecScan::setAbsoluteAngularResolution(const RangedDistribution& distr,
+void AngularSpecScan::setAbsoluteAngularResolution(const IRangedDistribution& distr,
                                                    double std_dev) {
     std::unique_ptr<ScanResolution> resolution(
         ScanResolution::scanAbsoluteResolution(distr, std_dev));
     setAngleResolution(*resolution);
 }
 
-void AngularSpecScan::setAbsoluteAngularResolution(const RangedDistribution& distr,
+void AngularSpecScan::setAbsoluteAngularResolution(const IRangedDistribution& distr,
                                                    const std::vector<double>& std_dev) {
     std::unique_ptr<ScanResolution> resolution(
         ScanResolution::scanAbsoluteResolution(distr, std_dev));
@@ -233,32 +232,6 @@ std::vector<double> AngularSpecScan::createIntensities(
     return result;
 }
 
-std::string AngularSpecScan::print() const {
-    std::stringstream result;
-    result << "\n" << pyfmt::indent() << "# Defining specular scan:\n";
-    const std::string axis_def = pyfmt::indent() + "axis = ";
-    result << axis_def << coordinateAxis()->pyString("rad", axis_def.size()) << "\n";
-
-    result << pyfmt::indent() << "scan = ";
-    result << "ba.AngularSpecScan(" << pyfmt::printDouble(m_wl) << ", axis)\n";
-
-    if (m_footprint) {
-        result << *m_footprint << "\n";
-        result << pyfmt::indent() << "scan.setFootprintFactor(footprint)\n";
-    }
-    if (!m_inc_resolution->empty()) {
-        result << "\n" << pyfmt::indent() << "# Defining angular resolution\n";
-        result << *m_inc_resolution << "\n";
-        result << pyfmt::indent() << "scan.setAngleResolution(resolution)\n";
-    }
-    if (!m_wl_resolution->empty()) {
-        result << "\n" << pyfmt::indent() << "# Defining wavelength resolution\n";
-        result << *m_wl_resolution << "\n";
-        result << pyfmt::indent() << "scan.setWavelengthResolution(resolution)\n";
-    }
-    return result.str();
-}
-
 void AngularSpecScan::checkInitialization() {
     if (m_wl <= 0.0)
         throw std::runtime_error(
diff --git a/Core/Scan/AngularSpecScan.h b/Core/Scan/AngularSpecScan.h
index ca0027b6fd64f66e81a53988f6654b371edfb11a..d8c7d24690257b02b95bc108c5ad3cd7cfe332db 100644
--- a/Core/Scan/AngularSpecScan.h
+++ b/Core/Scan/AngularSpecScan.h
@@ -19,7 +19,7 @@
 #include <memory>
 
 class ParameterSample;
-class RangedDistribution;
+class IRangedDistribution;
 class ScanResolution;
 
 //! Scan type with inclination angles as coordinate values and a unique wavelength.
@@ -59,9 +59,6 @@ public:
     std::vector<double>
     createIntensities(const std::vector<SpecularSimulationElement>& sim_elements) const override;
 
-    //! Print scan definition in python format
-    std::string print() const override;
-
     double wavelength() const { return m_wl; }
 
     // TODO: remove these getters after transition to the new resolution machinery is finished
@@ -75,37 +72,37 @@ public:
     //! Sets wavelength resolution values via ScanResolution object.
     void setWavelengthResolution(const ScanResolution& resolution);
 
-    void setRelativeWavelengthResolution(const RangedDistribution& distr, double rel_dev);
-    //! Sets wavelength resolution values via RangedDistribution and values of relative deviations
+    void setRelativeWavelengthResolution(const IRangedDistribution& distr, double rel_dev);
+    //! Sets wavelength resolution values via IRangedDistribution and values of relative deviations
     //! (that is, _rel_dev_ equals standard deviation divided by the mean value).
     //! _rel_dev_ can be either single-valued or a numpy array. In the latter case the length of the
     //! array should coinside with the length of the inclination angle axis.
-    void setRelativeWavelengthResolution(const RangedDistribution& distr,
+    void setRelativeWavelengthResolution(const IRangedDistribution& distr,
                                          const std::vector<double>& rel_dev);
 
-    void setAbsoluteWavelengthResolution(const RangedDistribution& distr, double std_dev);
-    //! Sets wavelength resolution values via RangedDistribution and values of standard deviations.
+    void setAbsoluteWavelengthResolution(const IRangedDistribution& distr, double std_dev);
+    //! Sets wavelength resolution values via IRangedDistribution and values of standard deviations.
     //! _std_dev_ can be either single-valued or a numpy array. In the latter case the length of the
     //! array should coinside with the length of the inclination angle axis.
-    void setAbsoluteWavelengthResolution(const RangedDistribution& distr,
+    void setAbsoluteWavelengthResolution(const IRangedDistribution& distr,
                                          const std::vector<double>& std_dev);
 
     //! Sets angle resolution values via ScanResolution object.
     void setAngleResolution(const ScanResolution& resolution);
 
-    void setRelativeAngularResolution(const RangedDistribution& distr, double rel_dev);
-    //! Sets angular resolution values via RangedDistribution and values of relative deviations
+    void setRelativeAngularResolution(const IRangedDistribution& distr, double rel_dev);
+    //! Sets angular resolution values via IRangedDistribution and values of relative deviations
     //! (that is, _rel_dev_ equals standard deviation divided by the mean value).
     //! _rel_dev_ can be either single-valued or a numpy array. In the latter case the length of the
     //! array should coinside with the length of the inclination angle axis.
-    void setRelativeAngularResolution(const RangedDistribution& distr,
+    void setRelativeAngularResolution(const IRangedDistribution& distr,
                                       const std::vector<double>& rel_dev);
 
-    void setAbsoluteAngularResolution(const RangedDistribution& distr, double std_dev);
-    //! Sets angular resolution values via RangedDistribution and values of standard deviations.
+    void setAbsoluteAngularResolution(const IRangedDistribution& distr, double std_dev);
+    //! Sets angular resolution values via IRangedDistribution and values of standard deviations.
     //! _std_dev_ can be either single-valued or a numpy array. In the latter case the length of the
     //! array should coinside with the length of the inclination angle axis.
-    void setAbsoluteAngularResolution(const RangedDistribution& distr,
+    void setAbsoluteAngularResolution(const IRangedDistribution& distr,
                                       const std::vector<double>& std_dev);
 
 private:
diff --git a/Core/Scan/ISpecularScan.h b/Core/Scan/ISpecularScan.h
index cd2214fcd97f8bf5920e42f580d237fa3dc9fe75..30ceb9e0b6e21574ce634b2933830c7717d7a33e 100644
--- a/Core/Scan/ISpecularScan.h
+++ b/Core/Scan/ISpecularScan.h
@@ -54,12 +54,7 @@ public:
     virtual std::vector<double>
     createIntensities(const std::vector<SpecularSimulationElement>& sim_elements) const = 0;
 
-    //! Print scan definition in python format
-    virtual std::string print() const = 0;
 #endif // SWIG
 };
 
-inline std::ostream& operator<<(std::ostream& os, const ISpecularScan& scan) {
-    return os << scan.print();
-}
 #endif // BORNAGAIN_CORE_SCAN_ISPECULARSCAN_H
diff --git a/Core/Scan/QSpecScan.cpp b/Core/Scan/QSpecScan.cpp
index 17de3c898415919b2d65876663f543620f71d78a..8e464ec1333b9191859f95d361239a095188b4f1 100644
--- a/Core/Scan/QSpecScan.cpp
+++ b/Core/Scan/QSpecScan.cpp
@@ -15,7 +15,6 @@
 #include "Core/Scan/QSpecScan.h"
 #include "Base/Axis/FixedBinAxis.h"
 #include "Base/Axis/PointwiseAxis.h"
-#include "Base/Utils/PyFmt.h"
 #include "Core/Element/SpecularSimulationElement.h"
 #include "Device/Resolution/ScanResolution.h"
 #include "Param/Distrib/RangedDistributions.h"
@@ -87,46 +86,32 @@ QSpecScan::createIntensities(const std::vector<SpecularSimulationElement>& sim_e
     return result;
 }
 
-std::string QSpecScan::print() const {
-    std::stringstream result;
-    const std::string axis_def = pyfmt::indent() + "axis = ";
-    result << axis_def << coordinateAxis()->pyString("", axis_def.size()) << "\n";
-
-    result << pyfmt::indent() << "scan = ba.QSpecScan(axis)";
-    if (!m_resolution->empty()) {
-        result << "\n";
-        result << *m_resolution << "\n";
-        result << pyfmt::indent() << "scan.setQResolution(resolution)";
-    }
-    return result.str();
-}
-
 void QSpecScan::setQResolution(const ScanResolution& resolution) {
     m_resolution.reset(resolution.clone());
     m_q_res_cache.clear();
     m_q_res_cache.shrink_to_fit();
 }
 
-void QSpecScan::setRelativeQResolution(const RangedDistribution& distr, double rel_dev) {
+void QSpecScan::setRelativeQResolution(const IRangedDistribution& distr, double rel_dev) {
     std::unique_ptr<ScanResolution> resolution(
         ScanResolution::scanRelativeResolution(distr, rel_dev));
     setQResolution(*resolution);
 }
 
-void QSpecScan::setRelativeQResolution(const RangedDistribution& distr,
+void QSpecScan::setRelativeQResolution(const IRangedDistribution& distr,
                                        const std::vector<double>& rel_dev) {
     std::unique_ptr<ScanResolution> resolution(
         ScanResolution::scanRelativeResolution(distr, rel_dev));
     setQResolution(*resolution);
 }
 
-void QSpecScan::setAbsoluteQResolution(const RangedDistribution& distr, double std_dev) {
+void QSpecScan::setAbsoluteQResolution(const IRangedDistribution& distr, double std_dev) {
     std::unique_ptr<ScanResolution> resolution(
         ScanResolution::scanAbsoluteResolution(distr, std_dev));
     setQResolution(*resolution);
 }
 
-void QSpecScan::setAbsoluteQResolution(const RangedDistribution& distr,
+void QSpecScan::setAbsoluteQResolution(const IRangedDistribution& distr,
                                        const std::vector<double>& std_dev) {
     std::unique_ptr<ScanResolution> resolution(
         ScanResolution::scanAbsoluteResolution(distr, std_dev));
diff --git a/Core/Scan/QSpecScan.h b/Core/Scan/QSpecScan.h
index 7ecfb4147ebc069c455f77e0bdc46db6fdd35917..0f6289e17232516707c9ccc268eeac66aa05ed7e 100644
--- a/Core/Scan/QSpecScan.h
+++ b/Core/Scan/QSpecScan.h
@@ -19,7 +19,7 @@
 #include <memory>
 
 class ParameterSample;
-class RangedDistribution;
+class IRangedDistribution;
 class ScanResolution;
 
 //! Scan type with z-components of scattering vector as coordinate values.
@@ -39,6 +39,8 @@ public:
     ~QSpecScan() override;
     QSpecScan* clone() const override;
 
+    const ScanResolution* resolution() const { return m_resolution.get(); }
+
 #ifndef SWIG
     //! Generates simulation elements for specular simulations
     std::vector<SpecularSimulationElement>
@@ -61,26 +63,24 @@ public:
     std::vector<double>
     createIntensities(const std::vector<SpecularSimulationElement>& sim_elements) const override;
 
-    //! Print scan definition in python format
-    std::string print() const override;
 #endif // SWIG
 
     //! Sets q resolution values via ScanResolution object.
     void setQResolution(const ScanResolution& resolution);
 
-    void setRelativeQResolution(const RangedDistribution& distr, double rel_dev);
-    //! Sets qz resolution values via RangedDistribution and values of relative deviations
+    void setRelativeQResolution(const IRangedDistribution& distr, double rel_dev);
+    //! Sets qz resolution values via IRangedDistribution and values of relative deviations
     //! (that is, _rel_dev_ equals standard deviation divided by the mean value).
     //! _rel_dev_ can be either single-valued or a numpy array. In the latter case the length of the
     //! array should coinside with the length of the qz-axis.
-    void setRelativeQResolution(const RangedDistribution& distr,
+    void setRelativeQResolution(const IRangedDistribution& distr,
                                 const std::vector<double>& rel_dev);
 
-    void setAbsoluteQResolution(const RangedDistribution& distr, double std_dev);
-    //! Sets qz resolution values via RangedDistribution and values of standard deviations.
+    void setAbsoluteQResolution(const IRangedDistribution& distr, double std_dev);
+    //! Sets qz resolution values via IRangedDistribution and values of standard deviations.
     //! _std_dev_ can be either single-valued or a numpy array. In the latter case the length of the
     //! array should coinside with the length of the qz-axis.
-    void setAbsoluteQResolution(const RangedDistribution& distr,
+    void setAbsoluteQResolution(const IRangedDistribution& distr,
                                 const std::vector<double>& std_dev);
 
 private:
diff --git a/Core/Simulation/GISASSimulation.cpp b/Core/Simulation/GISASSimulation.cpp
index f15db695882362e6eb8698b585f629b43dd6d852..c4f54d5ed3c03ac0a006dc19b38835382b611d2a 100644
--- a/Core/Simulation/GISASSimulation.cpp
+++ b/Core/Simulation/GISASSimulation.cpp
@@ -26,9 +26,8 @@ GISASSimulation::GISASSimulation() {
 
 void GISASSimulation::prepareSimulation() {
     if (instrument().getDetectorDimension() != 2)
-        throw Exceptions::LogicErrorException(
-            "GISASSimulation::prepareSimulation() "
-            "-> Error. The detector was not properly configured.");
+        throw std::runtime_error("GISASSimulation::prepareSimulation() "
+                                 "-> Error. The detector was not properly configured.");
     instrument().initDetector();
     ISimulation2D::prepareSimulation();
 }
@@ -42,7 +41,7 @@ SimulationResult GISASSimulation::result() const {
 
 void GISASSimulation::setBeamParameters(double wavelength, double alpha_i, double phi_i) {
     if (wavelength <= 0.0)
-        throw Exceptions::ClassInitializationException(
+        throw std::runtime_error(
             "ISimulation::setBeamParameters() -> Error. Incoming wavelength <= 0.");
     instrument().setBeamParameters(wavelength, alpha_i, phi_i);
 }
diff --git a/Core/Simulation/ISimulation.cpp b/Core/Simulation/ISimulation.cpp
index 0e39995d59bbc3071497393702246f2d6d573bae..f3b1c5021b850e088591342012334e522a5ff5ca 100644
--- a/Core/Simulation/ISimulation.cpp
+++ b/Core/Simulation/ISimulation.cpp
@@ -72,10 +72,10 @@ void runComputations(std::vector<std::unique_ptr<IComputation>>& computations) {
         if (computation->isCompleted())
             return;
         std::string message = computation->errorMessage();
-        throw Exceptions::RuntimeErrorException("Error in runComputations: ISimulation has "
-                                                "terminated unexpectedly with following error: "
-                                                "message.\n"
-                                                + message);
+        throw std::runtime_error("Error in runComputations: ISimulation has "
+                                 "terminated unexpectedly with following error: "
+                                 "message.\n"
+                                 + message);
     }
 
     // Running computations in several threads.
@@ -99,11 +99,10 @@ void runComputations(std::vector<std::unique_ptr<IComputation>>& computations) {
 
     if (failure_messages.empty())
         return;
-    throw Exceptions::RuntimeErrorException(
-        "Error in runComputations: "
-        "At least one simulation thread has terminated unexpectedly.\n"
-        "Messages: "
-        + StringUtils::join(failure_messages, " --- "));
+    throw std::runtime_error("Error in runComputations: "
+                             "At least one simulation thread has terminated unexpectedly.\n"
+                             "Messages: "
+                             + StringUtils::join(failure_messages, " --- "));
 }
 
 } // namespace
diff --git a/Core/Simulation/OffSpecSimulation.cpp b/Core/Simulation/OffSpecSimulation.cpp
index 5b33ab01b5cebce8bffd712debe323e3a4381b8a..a13b6e6b609d32c69e4f3d7b3fac6c27a749b23c 100644
--- a/Core/Simulation/OffSpecSimulation.cpp
+++ b/Core/Simulation/OffSpecSimulation.cpp
@@ -46,8 +46,8 @@ void OffSpecSimulation::setBeamParameters(double wavelength, const IAxis& alpha_
                                           double phi_i) {
     m_alpha_i_axis.reset(alpha_axis.clone());
     if (alpha_axis.size() < 1)
-        throw Exceptions::ClassInitializationException("OffSpecSimulation::prepareSimulation() "
-                                                       "-> Error. Incoming alpha range size < 1.");
+        throw std::runtime_error("OffSpecSimulation::prepareSimulation() "
+                                 "-> Error. Incoming alpha range size < 1.");
     const double alpha_zero = alpha_axis.lowerBound();
     instrument().setBeamParameters(wavelength, alpha_zero, phi_i);
     updateIntensityMap();
@@ -116,7 +116,7 @@ void OffSpecSimulation::transferResultsToIntensityMap() {
     const IAxis& phi_axis = instrument().getDetectorAxis(0);
     size_t phi_f_size = phi_axis.size();
     if (phi_f_size * m_intensity_map.getAllocatedSize() != m_sim_elements.size())
-        throw Exceptions::RuntimeErrorException(
+        throw std::runtime_error(
             "OffSpecSimulation::transferResultsToIntensityMap: "
             "intensity map size does not conform to number of calculated intensities");
     for (size_t i = 0; i < m_alpha_i_axis->size(); ++i)
@@ -149,10 +149,10 @@ void OffSpecSimulation::transferDetectorImage(size_t index) {
 
 void OffSpecSimulation::checkInitialization() const {
     if (!m_alpha_i_axis || m_alpha_i_axis->size() < 1)
-        throw Exceptions::ClassInitializationException("OffSpecSimulation::checkInitialization() "
-                                                       "Incoming alpha range not configured.");
+        throw std::runtime_error("OffSpecSimulation::checkInitialization() "
+                                 "Incoming alpha range not configured.");
     if (instrument().getDetectorDimension() != 2)
-        throw Exceptions::RuntimeErrorException(
+        throw std::runtime_error(
             "OffSpecSimulation::checkInitialization: detector is not two-dimensional");
 }
 
diff --git a/Device/Beam/Beam.cpp b/Device/Beam/Beam.cpp
index 958c5260fcafe5e46bd7b1d6bb6a14f2e51ec252..5e7386fb4d571006da8cae1595ccea1f424a77c3 100644
--- a/Device/Beam/Beam.cpp
+++ b/Device/Beam/Beam.cpp
@@ -15,7 +15,6 @@
 #include "Device/Beam/Beam.h"
 #include "Base/Math/Constants.h"
 #include "Base/Types/Complex.h"
-#include "Base/Types/Exceptions.h"
 #include "Base/Utils/Assert.h"
 #include "Device/Beam/FootprintGauss.h"
 #include "Param/Base/RealParameter.h"
@@ -70,10 +69,10 @@ kvector_t Beam::getCentralK() const {
 
 void Beam::setCentralK(double wavelength, double alpha_i, double phi_i) {
     if (wavelength <= 0.0)
-        throw Exceptions::ClassInitializationException(
+        throw std::runtime_error(
             "Beam::setCentralK() -> Error. Wavelength can't be negative or zero.");
     if (alpha_i < 0.0)
-        throw Exceptions::ClassInitializationException(
+        throw std::runtime_error(
             "Beam::setCentralK() -> Error. Inclination angle alpha_i can't be negative.");
     m_wavelength = wavelength;
     m_alpha = alpha_i;
@@ -98,7 +97,7 @@ void Beam::setWidthRatio(double width_ratio) {
 
 void Beam::setPolarization(const kvector_t bloch_vector) {
     if (bloch_vector.mag() > 1.0) {
-        throw Exceptions::ClassInitializationException(
+        throw std::runtime_error(
             "Beam::setPolarization: "
             "The given Bloch vector cannot represent a real physical ensemble");
     }
diff --git a/Device/Beam/FootprintGauss.cpp b/Device/Beam/FootprintGauss.cpp
index aed8c01ebbf707c40c5431c4a9cc6217c1cd7e27..f7fe7d0219395891a05671d2b5e65b3fb339a120 100644
--- a/Device/Beam/FootprintGauss.cpp
+++ b/Device/Beam/FootprintGauss.cpp
@@ -15,7 +15,6 @@
 #include "Device/Beam/FootprintGauss.h"
 #include "Base/Math/Constants.h"
 #include "Base/Math/Functions.h"
-#include "Base/Utils/PyFmt.h"
 
 FootprintGauss::FootprintGauss(const std::vector<double> P)
     : IFootprintFactor({"FootprintGauss", "class_tooltip", {}}, P) {}
@@ -36,15 +35,6 @@ double FootprintGauss::calculate(double alpha) const {
     return Math::erf(arg);
 }
 
-std::string FootprintGauss::print() const {
-    std::stringstream result;
-    result << "\n" << pyfmt::indent() << "# Defining footprint:\n";
-    result << pyfmt::indent() << "footprint = ";
-    result << "ba.FootprintGauss";
-    result << "(" << pyfmt::printDouble(widthRatio()) << ")";
-    return result.str();
-}
-
 static_assert(!std::is_copy_constructible<FootprintGauss>::value,
               "FootprintGauss should not be copy constructable");
 static_assert(!std::is_copy_assignable<FootprintGauss>::value,
diff --git a/Device/Beam/FootprintGauss.h b/Device/Beam/FootprintGauss.h
index cf3a15b6aac49fd33c60c7881f72ef025e12785c..1a945c109f447556c680b1dc1c3159d5534e56eb 100644
--- a/Device/Beam/FootprintGauss.h
+++ b/Device/Beam/FootprintGauss.h
@@ -34,8 +34,7 @@ public:
     //! Calculate footprint correction coefficient from the beam incident angle _alpha_.
     double calculate(double alpha) const override;
 
-    //! Print python-formatted footprint definition
-    std::string print() const override;
+    std::string name() const override { return "FootprintGauss"; }
 };
 
 #endif // BORNAGAIN_DEVICE_BEAM_FOOTPRINTGAUSS_H
diff --git a/Device/Beam/FootprintSquare.cpp b/Device/Beam/FootprintSquare.cpp
index 7b336d32d4479ed3cf26503f7b2120a85d0fac73..5f7274e0d65d272a986ec20d9819388f65348fd0 100644
--- a/Device/Beam/FootprintSquare.cpp
+++ b/Device/Beam/FootprintSquare.cpp
@@ -14,7 +14,6 @@
 
 #include "Device/Beam/FootprintSquare.h"
 #include "Base/Math/Constants.h"
-#include "Base/Utils/PyFmt.h"
 #include <algorithm>
 #include <stdexcept>
 
@@ -37,15 +36,6 @@ double FootprintSquare::calculate(double alpha) const {
     return std::min(arg, 1.0);
 }
 
-std::string FootprintSquare::print() const {
-    std::stringstream result;
-    result << "\n" << pyfmt::indent() << "# Defining footprint:\n";
-    result << pyfmt::indent() << "footprint = ";
-    result << "ba.FootprintSquare";
-    result << "(" << pyfmt::printDouble(widthRatio()) << ")";
-    return result.str();
-}
-
 static_assert(!std::is_copy_constructible<FootprintSquare>::value,
               "FootprintSquare should not be copy constructable");
 static_assert(!std::is_copy_assignable<FootprintSquare>::value,
diff --git a/Device/Beam/FootprintSquare.h b/Device/Beam/FootprintSquare.h
index e97a337badc54dd3f53b65df455d2775f014731b..84922298f776a40f0e0cf2007b6599c256a126ae 100644
--- a/Device/Beam/FootprintSquare.h
+++ b/Device/Beam/FootprintSquare.h
@@ -32,8 +32,7 @@ public:
     //! Calculate footprint correction coefficient from the beam incident angle _alpha_.
     double calculate(double alpha) const override;
 
-    //! Print python-formatted footprint definition
-    std::string print() const override;
+    std::string name() const override { return "FootprintSquare"; }
 };
 
 #endif // BORNAGAIN_DEVICE_BEAM_FOOTPRINTSQUARE_H
diff --git a/Device/Beam/IFootprintFactor.h b/Device/Beam/IFootprintFactor.h
index 6a52dc52f99555181013ae8ace5cbda13f9be710..6196537593f678c2bf5710cf3b1589cddc679453 100644
--- a/Device/Beam/IFootprintFactor.h
+++ b/Device/Beam/IFootprintFactor.h
@@ -38,8 +38,7 @@ public:
     //! Calculate footprint correction coefficient from the beam incident angle _alpha_.
     virtual double calculate(double alpha) const = 0;
 
-    //! Print python-formatted footprint definition
-    virtual std::string print() const = 0;
+    virtual std::string name() const = 0;
 
 protected:
     const double& m_width_ratio; //! Beam to sample width ratio
@@ -48,8 +47,4 @@ private:
     void initialize();
 };
 
-inline std::ostream& operator<<(std::ostream& os, const IFootprintFactor& f_factor) {
-    return os << f_factor.print();
-}
-
 #endif // BORNAGAIN_DEVICE_BEAM_IFOOTPRINTFACTOR_H
diff --git a/Device/Data/LLData.h b/Device/Data/LLData.h
index fb76c6a0c6d2d5766281798aafbd679cdb3d2cd2..5f097da00f1624b0c90c1fa07ee91761cff86500 100644
--- a/Device/Data/LLData.h
+++ b/Device/Data/LLData.h
@@ -15,7 +15,6 @@
 #ifndef BORNAGAIN_DEVICE_DATA_LLDATA_H
 #define BORNAGAIN_DEVICE_DATA_LLDATA_H
 
-#include "Base/Types/Exceptions.h"
 #include "Base/Vector/EigenCore.h"
 #include <algorithm>
 #include <limits>
@@ -126,7 +125,7 @@ template <class T> inline const T& LLData<T>::atCoordinate(int* coordinate) cons
 
 template <class T> LLData<T>& LLData<T>::operator+=(const LLData<T>& right) {
     if (!HaveSameDimensions(*this, right))
-        throw Exceptions::RuntimeErrorException(
+        throw std::runtime_error(
             "Operation += on LLData requires both operands to have the same dimensions");
     for (size_t i = 0; i < getTotalSize(); ++i) {
         m_data_array[i] += right[i];
@@ -136,7 +135,7 @@ template <class T> LLData<T>& LLData<T>::operator+=(const LLData<T>& right) {
 
 template <class T> LLData<T>& LLData<T>::operator-=(const LLData& right) {
     if (!HaveSameDimensions(*this, right))
-        throw Exceptions::RuntimeErrorException(
+        throw std::runtime_error(
             "Operation -= on LLData requires both operands to have the same dimensions");
     for (size_t i = 0; i < getTotalSize(); ++i) {
         m_data_array[i] -= right[i];
@@ -146,7 +145,7 @@ template <class T> LLData<T>& LLData<T>::operator-=(const LLData& right) {
 
 template <class T> LLData<T>& LLData<T>::operator*=(const LLData& right) {
     if (!HaveSameDimensions(*this, right))
-        throw Exceptions::RuntimeErrorException(
+        throw std::runtime_error(
             "Operation *= on LLData requires both operands to have the same dimensions");
     for (size_t i = 0; i < getTotalSize(); ++i) {
         m_data_array[i] *= right[i];
@@ -156,7 +155,7 @@ template <class T> LLData<T>& LLData<T>::operator*=(const LLData& right) {
 
 template <class T> LLData<T>& LLData<T>::operator/=(const LLData& right) {
     if (!HaveSameDimensions(*this, right))
-        throw Exceptions::RuntimeErrorException(
+        throw std::runtime_error(
             "Operation /= on LLData requires both operands to have the same dimensions");
     for (size_t i = 0; i < getTotalSize(); ++i) {
         double ratio;
diff --git a/Device/Data/OutputData.cpp b/Device/Data/OutputData.cpp
index 0a14b1aba67656598977be7537e89d0cb7d1be5c..10563f7cc68d3a3d47cc2b2ed4d3d844c85efc63 100644
--- a/Device/Data/OutputData.cpp
+++ b/Device/Data/OutputData.cpp
@@ -38,7 +38,7 @@ template <> PyObject* OutputData<double>::getArray() const {
     PyObject* pyarray = PyArray_SimpleNew(ndim_numpy, ndimsizes_numpy, NPY_DOUBLE);
     delete[] ndimsizes_numpy;
     if (pyarray == nullptr)
-        throw Exceptions::RuntimeErrorException("ExportOutputData() -> Panic in PyArray_SimpleNew");
+        throw std::runtime_error("ExportOutputData() -> Panic in PyArray_SimpleNew");
 
     // getting pointer to data buffer of numpy array
     double* array_buffer = (double*)PyArray_DATA((PyArrayObject*)pyarray);
diff --git a/Device/Data/OutputData.h b/Device/Data/OutputData.h
index 41dc79b31c2d97123ecd6dc8aa8d5ffb6420cb88..beb4a15a54fe227b722dc914a3849c4f497a3aaa 100644
--- a/Device/Data/OutputData.h
+++ b/Device/Data/OutputData.h
@@ -280,10 +280,9 @@ template <class T> OutputData<double>* OutputData<T>::meanValues() const {
 
 template <class T> void OutputData<T>::addAxis(const IAxis& new_axis) {
     if (axisNameExists(new_axis.getName()))
-        throw Exceptions::LogicErrorException(
-            "OutputData<T>::addAxis(const IAxis& new_axis) -> "
-            "Error! Attempt to add axis with already existing name '"
-            + new_axis.getName() + "'");
+        throw std::runtime_error("OutputData<T>::addAxis(const IAxis& new_axis) -> "
+                                 "Error! Attempt to add axis with already existing name '"
+                                 + new_axis.getName() + "'");
     if (new_axis.size() > 0) {
         m_value_axes.push_back(new_axis.clone());
         allocate();
@@ -293,10 +292,9 @@ template <class T> void OutputData<T>::addAxis(const IAxis& new_axis) {
 template <class T>
 void OutputData<T>::addAxis(const std::string& name, size_t size, double start, double end) {
     if (axisNameExists(name))
-        throw Exceptions::LogicErrorException(
-            "OutputData<T>::addAxis(std::string name) -> "
-            "Error! Attempt to add axis with already existing name '"
-            + name + "'");
+        throw std::runtime_error("OutputData<T>::addAxis(std::string name) -> "
+                                 "Error! Attempt to add axis with already existing name '"
+                                 + name + "'");
     FixedBinAxis new_axis(name, size, start, end);
     addAxis(new_axis);
 }
@@ -361,8 +359,8 @@ size_t OutputData<T>::getAxisBinIndex(size_t global_index, size_t i_selected_axi
             return result;
         remainder /= m_value_axes[i_axis]->size();
     }
-    throw Exceptions::LogicErrorException("OutputData<T>::getAxisBinIndex() -> "
-                                          "Error! No axis with given number");
+    throw std::runtime_error("OutputData<T>::getAxisBinIndex() -> "
+                             "Error! No axis with given number");
 }
 
 template <class T>
@@ -374,9 +372,8 @@ template <class T>
 size_t OutputData<T>::toGlobalIndex(const std::vector<unsigned>& axes_indices) const {
     ASSERT(m_ll_data);
     if (axes_indices.size() != m_ll_data->rank())
-        throw Exceptions::LogicErrorException(
-            "size_t OutputData<T>::toGlobalIndex() -> "
-            "Error! Number of coordinates must match rank of data structure");
+        throw std::runtime_error("size_t OutputData<T>::toGlobalIndex() -> "
+                                 "Error! Number of coordinates must match rank of data structure");
     size_t result = 0;
     size_t step_size = 1;
     for (size_t i = m_ll_data->rank(); i > 0; --i) {
@@ -386,7 +383,7 @@ size_t OutputData<T>::toGlobalIndex(const std::vector<unsigned>& axes_indices) c
             message << axes_indices[i - 1] << " is out of range. Axis ";
             message << m_value_axes[i - 1]->getName();
             message << " size " << m_value_axes[i - 1]->size() << ".\n";
-            throw Exceptions::LogicErrorException(message.str());
+            throw std::runtime_error(message.str());
         }
         result += axes_indices[i - 1] * step_size;
         step_size *= m_value_axes[i - 1]->size();
@@ -398,9 +395,8 @@ template <class T>
 size_t OutputData<T>::findGlobalIndex(const std::vector<double>& coordinates) const {
     ASSERT(m_ll_data);
     if (coordinates.size() != m_ll_data->rank())
-        throw Exceptions::LogicErrorException(
-            "OutputData<T>::findClosestIndex() -> "
-            "Error! Number of coordinates must match rank of data structure");
+        throw std::runtime_error("OutputData<T>::findClosestIndex() -> "
+                                 "Error! Number of coordinates must match rank of data structure");
     std::vector<unsigned> axes_indexes;
     axes_indexes.resize(m_ll_data->rank());
     for (size_t i = 0; i < m_ll_data->rank(); ++i)
@@ -450,14 +446,14 @@ template <class T> void OutputData<T>::clear() {
 
 template <class T> void OutputData<T>::setAllTo(const T& value) {
     if (!m_ll_data)
-        throw Exceptions::ClassInitializationException(
+        throw std::runtime_error(
             "OutputData::setAllTo() -> Error! Low-level data object was not yet initialized.");
     m_ll_data->setAll(value);
 }
 
 template <class T> void OutputData<T>::scaleAll(const T& factor) {
     if (!m_ll_data)
-        throw Exceptions::ClassInitializationException(
+        throw std::runtime_error(
             "OutputData::scaleAll() -> Error! Low-level data object was not yet initialized.");
     m_ll_data->scaleAll(factor);
 }
@@ -521,7 +517,7 @@ template <class T> void OutputData<T>::allocate() {
 
 template <class T> inline void OutputData<T>::setRawDataVector(const std::vector<T>& data_vector) {
     if (data_vector.size() != getAllocatedSize())
-        throw Exceptions::RuntimeErrorException(
+        throw std::runtime_error(
             "OutputData<T>::setRawDataVector() -> Error! "
             "setRawDataVector can only be called with a data vector of the correct size.");
     for (size_t i = 0; i < getAllocatedSize(); ++i)
@@ -572,9 +568,9 @@ template <class T> size_t OutputData<T>::getAxisIndex(const std::string& axis_na
     for (size_t i = 0; i < m_value_axes.size(); ++i)
         if (m_value_axes[i]->getName() == axis_name)
             return i;
-    throw Exceptions::LogicErrorException("OutputData<T>::getAxisIndex() -> "
-                                          "Error! Axis with given name not found '"
-                                          + axis_name + "'");
+    throw std::runtime_error("OutputData<T>::getAxisIndex() -> "
+                             "Error! Axis with given name not found '"
+                             + axis_name + "'");
 }
 
 template <class T> bool OutputData<T>::axisNameExists(const std::string& axis_name) const {
diff --git a/Device/Detector/DetectionProperties.cpp b/Device/Detector/DetectionProperties.cpp
index 7d828ceb3a1951b13e1ab84c65b45081963dcfe3..fda9bf57d7e07d4535979c1b7265620521e27dd0 100644
--- a/Device/Detector/DetectionProperties.cpp
+++ b/Device/Detector/DetectionProperties.cpp
@@ -14,7 +14,6 @@
 
 #include "Device/Detector/DetectionProperties.h"
 #include "Base/Types/Complex.h"
-#include "Base/Types/Exceptions.h"
 #include "Param/Base/RealParameter.h"
 
 DetectionProperties::DetectionProperties(kvector_t direction, double efficiency,
@@ -34,8 +33,8 @@ DetectionProperties::DetectionProperties(const DetectionProperties& other)
 void DetectionProperties::setAnalyzerProperties(const kvector_t direction, double efficiency,
                                                 double total_transmission) {
     if (!checkAnalyzerProperties(direction, efficiency, total_transmission))
-        throw Exceptions::ClassInitializationException("IDetector2D::setAnalyzerProperties: the "
-                                                       "given properties are not physical");
+        throw std::runtime_error("IDetector2D::setAnalyzerProperties: the "
+                                 "given properties are not physical");
     if (efficiency == 0.0 || total_transmission == 0.0 || direction.mag() == 0.0) {
         m_direction = kvector_t{};
         m_efficiency = 0.0;
diff --git a/Device/Detector/DetectorMask.cpp b/Device/Detector/DetectorMask.cpp
index 36ad3eb2592711b9f28e7333e37fc7c21612878f..61a56b618b6298f55c06351ab2e5881001bb5337 100644
--- a/Device/Detector/DetectorMask.cpp
+++ b/Device/Detector/DetectorMask.cpp
@@ -46,8 +46,8 @@ void DetectorMask::addMask(const IShape2D& shape, bool mask_value) {
 
 void DetectorMask::initMaskData(const IDetector2D& detector) {
     if (detector.dimension() != 2)
-        throw Exceptions::RuntimeErrorException("DetectorMask::initMaskData() -> Error. Attempt "
-                                                "to add masks to uninitialized detector.");
+        throw std::runtime_error("DetectorMask::initMaskData() -> Error. Attempt "
+                                 "to add masks to uninitialized detector.");
 
     ASSERT(m_shapes.size() == m_mask_of_shape.size());
     m_mask_data.clear();
diff --git a/Device/Detector/IDetector.cpp b/Device/Detector/IDetector.cpp
index 93937f9513830621f743c15eab7e6bb926738269..853ca6f5586aa1fc0266d6f8ad3aab676f6a9959 100644
--- a/Device/Detector/IDetector.cpp
+++ b/Device/Detector/IDetector.cpp
@@ -71,10 +71,9 @@ size_t IDetector::axisBinIndex(size_t index, size_t selected_axis) const {
 std::unique_ptr<IAxis> IDetector::createAxis(size_t index, size_t n_bins, double min,
                                              double max) const {
     if (max <= min)
-        throw Exceptions::LogicErrorException("IDetector::createAxis() -> Error! max <= min");
+        throw std::runtime_error("IDetector::createAxis() -> Error! max <= min");
     if (n_bins == 0)
-        throw Exceptions::LogicErrorException(
-            "IDetector::createAxis() -> Error! Number n_bins can't be zero.");
+        throw std::runtime_error("IDetector::createAxis() -> Error! Number n_bins can't be zero.");
     return std::make_unique<FixedBinAxis>(axisName(index), n_bins, min, max);
 }
 
@@ -135,8 +134,8 @@ OutputData<double>*
 IDetector::createDetectorIntensity(const std::vector<SimulationElement>& elements) const {
     std::unique_ptr<OutputData<double>> detectorMap(createDetectorMap());
     if (!detectorMap)
-        throw Exceptions::RuntimeErrorException("Instrument::createDetectorIntensity:"
-                                                "can't create detector map.");
+        throw std::runtime_error("Instrument::createDetectorIntensity:"
+                                 "can't create detector map.");
 
     setDataToDetectorMap(*detectorMap, elements);
     if (m_detector_resolution)
diff --git a/Device/Detector/IsGISAXSDetector.cpp b/Device/Detector/IsGISAXSDetector.cpp
index 7d8c0545185b3218213bce1baedf08c26d913311..817ef6ef83d17c9fd35a3d6331babf9582f4eacd 100644
--- a/Device/Detector/IsGISAXSDetector.cpp
+++ b/Device/Detector/IsGISAXSDetector.cpp
@@ -36,11 +36,10 @@ IsGISAXSDetector* IsGISAXSDetector::clone() const {
 std::unique_ptr<IAxis> IsGISAXSDetector::createAxis(size_t index, size_t n_bins, double min,
                                                     double max) const {
     if (max <= min) {
-        throw Exceptions::LogicErrorException(
-            "IsGISAXSDetector::createAxis() -> Error! max <= min");
+        throw std::runtime_error("IsGISAXSDetector::createAxis() -> Error! max <= min");
     }
     if (n_bins == 0) {
-        throw Exceptions::LogicErrorException(
+        throw std::runtime_error(
             "IsGISAXSDetector::createAxis() -> Error! Number n_bins can't be zero.");
     }
     return std::make_unique<CustomBinAxis>(axisName(index), n_bins, min, max);
diff --git a/Device/Detector/RectangularDetector.cpp b/Device/Detector/RectangularDetector.cpp
index 919d19d86aaa4108cda4d748e0df971e696cd8b7..c78fe81e531a89efc8d80929f4cf07625e962658 100644
--- a/Device/Detector/RectangularDetector.cpp
+++ b/Device/Detector/RectangularDetector.cpp
@@ -189,7 +189,7 @@ std::string RectangularDetector::axisName(size_t index) const {
     case 1:
         return "v";
     default:
-        throw Exceptions::LogicErrorException(
+        throw std::runtime_error(
             "RectangularDetector::getAxisName(size_t index) -> Error! index > 1");
     }
 }
@@ -220,7 +220,7 @@ void RectangularDetector::setDistanceAndOffset(double distance, double u0, doubl
         std::ostringstream message;
         message << "RectangularDetector::setPerpendicularToSample() -> Error. "
                 << "Distance to sample can't be negative or zero";
-        throw Exceptions::LogicErrorException(message.str());
+        throw std::runtime_error(message.str());
     }
     m_distance = distance;
     m_u0 = u0;
@@ -249,8 +249,7 @@ void RectangularDetector::initNormalVector(const kvector_t central_k) {
     }
 
     else {
-        throw Exceptions::LogicErrorException(
-            "RectangularDetector::init() -> Unknown detector arrangement");
+        throw std::runtime_error("RectangularDetector::init() -> Unknown detector arrangement");
     }
 }
 
diff --git a/Device/Detector/RegionOfInterest.cpp b/Device/Detector/RegionOfInterest.cpp
index 3929ad4e9177d24de5a980a803ae1cb7fb10be2f..acf838a3115230cc0520f163c7892edd0d4a27f6 100644
--- a/Device/Detector/RegionOfInterest.cpp
+++ b/Device/Detector/RegionOfInterest.cpp
@@ -26,8 +26,8 @@ RegionOfInterest::RegionOfInterest(const OutputData<double>& data, double xlow,
                                    double xup, double yup)
     : RegionOfInterest(xlow, ylow, xup, yup) {
     if (data.rank() != 2)
-        throw Exceptions::RuntimeErrorException("RegionOfInterest::RegionOfInterest() -> Error. "
-                                                "Data is not two-dimensional.");
+        throw std::runtime_error("RegionOfInterest::RegionOfInterest() -> Error. "
+                                 "Data is not two-dimensional.");
 
     initFrom(data.axis(0), data.axis(1));
 }
@@ -81,11 +81,11 @@ size_t RegionOfInterest::detectorIndex(size_t roiIndex) const {
 size_t RegionOfInterest::roiIndex(size_t globalIndex) const {
     size_t ny = ycoord(globalIndex, m_detector_dims);
     if (ny < m_ay1 || ny > m_ay2)
-        throw Exceptions::RuntimeErrorException("RegionOfInterest::roiIndex() -> Error.");
+        throw std::runtime_error("RegionOfInterest::roiIndex() -> Error.");
 
     size_t nx = xcoord(globalIndex, m_detector_dims);
     if (nx < m_ax1 || nx > m_ax2)
-        throw Exceptions::RuntimeErrorException("RegionOfInterest::roiIndex() -> Error.");
+        throw std::runtime_error("RegionOfInterest::roiIndex() -> Error.");
 
     return ny - m_ay1 + (nx - m_ax1) * m_roi_dims[1];
 }
diff --git a/Device/Detector/SimulationAreaIterator.cpp b/Device/Detector/SimulationAreaIterator.cpp
index 24f6f818291c0e45271b19981fc0779745a6f032..906ac3b8f66557c0dcece29c188578e6726759ab 100644
--- a/Device/Detector/SimulationAreaIterator.cpp
+++ b/Device/Detector/SimulationAreaIterator.cpp
@@ -18,8 +18,8 @@
 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");
+        throw std::runtime_error("SimulationAreaIterator::SimulationAreaIterator() "
+                                 "-> Error. Invalid initial index");
 
     if (m_index != m_area->totalSize() && m_area->isMasked(m_index))
         m_index = nextIndex(m_index);
diff --git a/Device/Detector/SphericalDetector.cpp b/Device/Detector/SphericalDetector.cpp
index eab85862c54afb03e386703e076877fffe933bb2..5f61a66758704421ae2352a0c64b7d6c7a2c1515 100644
--- a/Device/Detector/SphericalDetector.cpp
+++ b/Device/Detector/SphericalDetector.cpp
@@ -60,7 +60,7 @@ std::string SphericalDetector::axisName(size_t index) const {
     case 1:
         return "alpha_f";
     default:
-        throw Exceptions::LogicErrorException(
+        throw std::runtime_error(
             "SphericalDetector::getAxisName(size_t index) -> Error! index > 1");
     }
 }
diff --git a/Device/Histo/Histogram2D.cpp b/Device/Histo/Histogram2D.cpp
index 34ef6e4ccc09b00880a7f2b9d9d33ff0080c7f46..e123af7ed0f9054beec41c458b0aef0d21616802 100644
--- a/Device/Histo/Histogram2D.cpp
+++ b/Device/Histo/Histogram2D.cpp
@@ -119,7 +119,7 @@ void Histogram2D::addContent(const std::vector<std::vector<double>>& data) {
              << "] doesn't mach histogram axes. "
              << "X-axis size: " << m_data.axis(0).size()
              << "Y-axis size: " << m_data.axis(1).size();
-        throw Exceptions::LogicErrorException(ostr.str());
+        throw std::runtime_error(ostr.str());
     }
 
     for (size_t row = 0; row < nrows; ++row) {
diff --git a/Device/Histo/Histogram2D.h b/Device/Histo/Histogram2D.h
index 0647ce939d3ae65fe489e56d2fd363723d0ec9e5..7507cc960e049723753ecd9a58a915748486910e 100644
--- a/Device/Histo/Histogram2D.h
+++ b/Device/Histo/Histogram2D.h
@@ -117,8 +117,8 @@ template <typename T> void Histogram2D::initFromShape(const T& data) {
     const size_t ncols = shape.second;
 
     if (nrows == 0 || ncols == 0)
-        throw Exceptions::LogicErrorException("Histogram2D::Histogram2D() -> Error. "
-                                              "Not a two-dimensional numpy array");
+        throw std::runtime_error("Histogram2D::Histogram2D() -> Error. "
+                                 "Not a two-dimensional numpy array");
 
     m_data.addAxis(FixedBinAxis("x-axis", ncols, 0.0, static_cast<double>(ncols)));
     m_data.addAxis(FixedBinAxis("y-axis", nrows, 0.0, static_cast<double>(nrows)));
diff --git a/Device/Histo/IHistogram.cpp b/Device/Histo/IHistogram.cpp
index d80dc02c7f3ebae3d20d380e6e3ea07bb171834b..4d85c621f7a6722da88ec2587c5d150b156511dc 100644
--- a/Device/Histo/IHistogram.cpp
+++ b/Device/Histo/IHistogram.cpp
@@ -211,7 +211,7 @@ IHistogram* IHistogram::createHistogram(const OutputData<double>& source) {
         message << "IHistogram::createHistogram(const OutputData<double>& source) -> Error. ";
         message << "The rank of source " << source.rank() << " ";
         message << "is not suitable for creation neither 1-dim nor 2-dim histograms.";
-        throw Exceptions::LogicErrorException(message.str());
+        throw std::runtime_error(message.str());
     }
 }
 
@@ -228,7 +228,7 @@ void IHistogram::check_x_axis() const {
         std::ostringstream message;
         message << "IHistogram::check_x_axis() -> Error. X-xis does not exist. ";
         message << "Rank of histogram " << rank() << "." << std::endl;
-        throw Exceptions::LogicErrorException(message.str());
+        throw std::runtime_error(message.str());
     }
 }
 
@@ -237,7 +237,7 @@ void IHistogram::check_y_axis() const {
         std::ostringstream message;
         message << "IHistogram::check_y_axis() -> Error. Y-axis does not exist. ";
         message << "Rank of histogram " << rank() << "." << std::endl;
-        throw Exceptions::LogicErrorException(message.str());
+        throw std::runtime_error(message.str());
     }
 }
 
@@ -247,7 +247,7 @@ void IHistogram::init_from_data(const OutputData<double>& source) {
         message << "IHistogram::IHistogram(const OutputData<double>& data) -> Error. ";
         message << "The dimension of this histogram " << rank() << " ";
         message << "is differ from the dimension of source " << m_data.rank() << std::endl;
-        throw Exceptions::LogicErrorException(message.str());
+        throw std::runtime_error(message.str());
     }
 
     m_data.copyShapeFrom(source);
@@ -267,7 +267,7 @@ double IHistogram::binData(size_t i, IHistogram::DataType dataType) const {
     } else if (dataType == DataType::NENTRIES) {
         return binNumberOfEntries(i);
     } else
-        throw Exceptions::LogicErrorException("IHistogram::binData() -> Error. Unknown data type.");
+        throw std::runtime_error("IHistogram::binData() -> Error. Unknown data type.");
 }
 
 //! returns vector of values of requested DataType
@@ -283,7 +283,7 @@ std::vector<double> IHistogram::getDataVector(IHistogram::DataType dataType) con
 //! Copy content (but not the axes) from other histogram. Dimensions should be the same.
 void IHistogram::copyContentFrom(const IHistogram& other) {
     if (!hasSameDimensions(other))
-        throw Exceptions::LogicErrorException(
+        throw std::runtime_error(
             "IHistogram::copyContentFrom() -> Error. Can't copy the data of different shape.");
     reset();
     for (size_t i = 0; i < getTotalNumberOfBins(); ++i) {
@@ -311,7 +311,7 @@ bool IHistogram::hasSameDimensions(const IHistogram& other) const {
 
 const IHistogram& IHistogram::operator+=(const IHistogram& right) {
     if (!hasSameDimensions(right))
-        throw Exceptions::LogicErrorException(
+        throw std::runtime_error(
             "IHistogram::operator+=() -> Error. Histograms have different dimension");
     for (size_t i = 0; i < getTotalNumberOfBins(); ++i)
         addBinContent(i, right.binContent(i));
@@ -320,8 +320,8 @@ const IHistogram& IHistogram::operator+=(const IHistogram& right) {
 
 IHistogram* IHistogram::relativeDifferenceHistogram(const IHistogram& rhs) {
     if (!hasSameDimensions(rhs))
-        throw Exceptions::LogicErrorException("IHistogram::relativeDifferenceHistogram() -> Error. "
-                                              "Histograms have different dimensions");
+        throw std::runtime_error("IHistogram::relativeDifferenceHistogram() -> Error. "
+                                 "Histograms have different dimensions");
 
     IHistogram* result = this->clone();
     result->reset();
diff --git a/Device/InputOutput/DataFormatUtils.cpp b/Device/InputOutput/DataFormatUtils.cpp
index 7f3ae56bbbb002903bf674c5393217021f79a540..41cd8bb6f725c5a328c7bd23fe780d7df5420ba0 100644
--- a/Device/InputOutput/DataFormatUtils.cpp
+++ b/Device/InputOutput/DataFormatUtils.cpp
@@ -84,15 +84,15 @@ std::unique_ptr<IAxis> DataFormatUtils::createAxis(std::istream& input_stream) {
     auto iss = getAxisStringRepresentation(input_stream);
     std::string type;
     if (!(iss >> type))
-        throw Exceptions::FormatErrorException(
+        throw std::runtime_error(
             "Error in DataFormatUtils::createAxis:: couldn't read axis type from input");
 
     for (auto iter = type_map.cbegin(); iter != type_map.end(); ++iter)
         if (iter->first == type)
             return iter->second(std::move(iss));
-    throw Exceptions::LogicErrorException("Error in DataFormatUtils::createAxis:"
-                                          "Unknown axis type '"
-                                          + type + "'");
+    throw std::runtime_error("Error in DataFormatUtils::createAxis:"
+                             "Unknown axis type '"
+                             + type + "'");
 }
 
 //! Fills output data raw buffer from input stream
@@ -113,8 +113,7 @@ void DataFormatUtils::fillOutputData(OutputData<double>* data, std::istream& inp
         }
     }
     if (it != data->end())
-        throw Exceptions::FormatErrorException(
-            "DataFormatUtils::fillOutputData() -> Error while parsing data.");
+        throw std::runtime_error("DataFormatUtils::fillOutputData() -> Error while parsing data.");
 }
 
 //! Parse double values from string to vector of double
@@ -159,15 +158,13 @@ template <class Axis> std::unique_ptr<IAxis> createFixedBinLikeAxis(std::istring
     std::string name;
     size_t nbins(0);
     if (!(iss >> name >> nbins))
-        throw Exceptions::FormatErrorException(
-            "createFixedBinLikeAxis() -> Error. Can't parse the string.");
+        throw std::runtime_error("createFixedBinLikeAxis() -> Error. Can't parse the string.");
 
     std::vector<double> boundaries;
     DataFormatUtils::readLineOfDoubles(boundaries, iss);
     if (boundaries.size() != 2)
-        throw Exceptions::FormatErrorException(
-            "Error in createFixedBinLikeAxis: Can't parse the string while "
-            "reading boundaries.");
+        throw std::runtime_error("Error in createFixedBinLikeAxis: Can't parse the string while "
+                                 "reading boundaries.");
 
     return std::make_unique<Axis>(name, nbins, boundaries[0], boundaries[1]);
 }
@@ -178,13 +175,12 @@ std::unique_ptr<IAxis> createVariableBinAxis(std::istringstream iss) {
     std::string name;
     size_t nbins(0);
     if (!(iss >> name >> nbins))
-        throw Exceptions::FormatErrorException(
-            "Error in createVariableBinAxis: Can't parse the string.");
+        throw std::runtime_error("Error in createVariableBinAxis: Can't parse the string.");
 
     std::vector<double> boundaries;
     DataFormatUtils::readLineOfDoubles(boundaries, iss);
     if (boundaries.size() != nbins + 1)
-        throw Exceptions::FormatErrorException(
+        throw std::runtime_error(
             "Error in createVariableBinAxis: wrong number of boundaries read.");
 
     return std::make_unique<VariableBinAxis>(name, nbins, boundaries);
@@ -195,8 +191,7 @@ std::unique_ptr<IAxis> createVariableBinAxis(std::istringstream iss) {
 std::unique_ptr<IAxis> createPointwiseAxis(std::istringstream iss) {
     std::string name;
     if (!(iss >> name))
-        throw Exceptions::FormatErrorException(
-            "Error in createPointwiseAxis:Can't parse the string.");
+        throw std::runtime_error("Error in createPointwiseAxis:Can't parse the string.");
 
     std::vector<double> coordinates;
     DataFormatUtils::readLineOfDoubles(coordinates, iss);
diff --git a/Device/InputOutput/OutputDataReadFactory.cpp b/Device/InputOutput/OutputDataReadFactory.cpp
index 0c7986042b961fd3e2709a29c92a95bb75b98441..15160855589c44ec1910895ab0d9d3dbde38c0d0 100644
--- a/Device/InputOutput/OutputDataReadFactory.cpp
+++ b/Device/InputOutput/OutputDataReadFactory.cpp
@@ -13,7 +13,6 @@
 //  ************************************************************************************************
 
 #include "Device/InputOutput/OutputDataReadFactory.h"
-#include "Base/Types/Exceptions.h"
 #include "Device/InputOutput/DataFormatUtils.h"
 
 OutputDataReader* OutputDataReadFactory::getReader(const std::string& file_name) {
diff --git a/Device/InputOutput/OutputDataReader.cpp b/Device/InputOutput/OutputDataReader.cpp
index 0148f7dbf761fce4a38b3df4f14228f8c447a72d..06b92dede28f2e4e3c7090ca5e2bc93ea5aa0098 100644
--- a/Device/InputOutput/OutputDataReader.cpp
+++ b/Device/InputOutput/OutputDataReader.cpp
@@ -50,7 +50,7 @@ OutputDataReader::OutputDataReader(const std::string& file_name) : m_file_name(f
 OutputData<double>* OutputDataReader::getOutputData() {
     using namespace DataFormatUtils;
     if (!m_read_strategy)
-        throw Exceptions::NullPointerException(
+        throw std::runtime_error(
             "OutputDataReader::getOutputData() -> Error! No read strategy defined");
 
     std::ifstream fin;
@@ -65,12 +65,11 @@ OutputData<double>* OutputDataReader::getOutputData() {
 #endif
 
     if (!fin.is_open())
-        throw Exceptions::FileNotIsOpenException(
-            "OutputDataReader::getOutputData() -> Error. Can't open file '" + m_file_name
-            + "' for reading.");
+        throw std::runtime_error("OutputDataReader::getOutputData() -> Error. Can't open file '"
+                                 + m_file_name + "' for reading.");
     if (!fin.good())
-        throw Exceptions::FileIsBadException("OutputDataReader::getOutputData() -> Error! "
-                                             "File is not good, probably it is a directory.");
+        throw std::runtime_error("OutputDataReader::getOutputData() -> Error! "
+                                 "File is not good, probably it is a directory.");
 
     std::stringstream strstream = getFromFilteredStream(fin, m_file_name);
 
diff --git a/Device/InputOutput/OutputDataWriteFactory.cpp b/Device/InputOutput/OutputDataWriteFactory.cpp
index e88da3abca0002465c946e799ce8ad14feb0ef85..4e19cd0b6f48c5f23f0efbbcb5f90de7be1901d0 100644
--- a/Device/InputOutput/OutputDataWriteFactory.cpp
+++ b/Device/InputOutput/OutputDataWriteFactory.cpp
@@ -12,7 +12,6 @@
 //
 //  ************************************************************************************************
 #include "Device/InputOutput/OutputDataWriteFactory.h"
-#include "Base/Types/Exceptions.h"
 #include "Device/InputOutput/DataFormatUtils.h"
 
 OutputDataWriter* OutputDataWriteFactory::getWriter(const std::string& file_name) {
diff --git a/Device/InputOutput/OutputDataWriter.cpp b/Device/InputOutput/OutputDataWriter.cpp
index b93c022d78449c65b063488bc8c8d43ba64fa78e..acaa1688eed5e96c96d860176de7b4f8135a1cf9 100644
--- a/Device/InputOutput/OutputDataWriter.cpp
+++ b/Device/InputOutput/OutputDataWriter.cpp
@@ -31,8 +31,8 @@ OutputDataWriter::OutputDataWriter(const std::string& file_name) : m_file_name(f
 void OutputDataWriter::writeOutputData(const OutputData<double>& data) {
     using namespace DataFormatUtils;
     if (!m_write_strategy)
-        throw Exceptions::NullPointerException("OutputDataWriter::getOutputData() ->"
-                                               " Error! No read strategy defined");
+        throw std::runtime_error("OutputDataWriter::getOutputData() ->"
+                                 " Error! No read strategy defined");
 
     std::ofstream fout;
     std::ios_base::openmode openmode = std::ios::out;
@@ -46,12 +46,12 @@ void OutputDataWriter::writeOutputData(const OutputData<double>& data) {
 #endif
 
     if (!fout.is_open())
-        throw Exceptions::FileNotIsOpenException("OutputDataWriter::writeOutputData() -> Error. "
-                                                 "Can't open file '"
-                                                 + m_file_name + "' for writing.");
+        throw std::runtime_error("OutputDataWriter::writeOutputData() -> Error. "
+                                 "Can't open file '"
+                                 + m_file_name + "' for writing.");
     if (!fout.good())
-        throw Exceptions::FileIsBadException("OutputDataReader::writeOutputData() -> Error! "
-                                             "File is not good, probably it is a directory.");
+        throw std::runtime_error("OutputDataReader::writeOutputData() -> Error! "
+                                 "File is not good, probably it is a directory.");
     std::stringstream ss;
     m_write_strategy->writeOutputData(data, ss);
 
diff --git a/Device/InputOutput/TiffHandler.cpp b/Device/InputOutput/TiffHandler.cpp
index 1704132757a90c080c087134bb932d3a5f54669e..68672fde466d3d39b9417c0248c600c040d030fd 100644
--- a/Device/InputOutput/TiffHandler.cpp
+++ b/Device/InputOutput/TiffHandler.cpp
@@ -33,7 +33,7 @@ TiffHandler::~TiffHandler() {
 void TiffHandler::read(std::istream& input_stream) {
     m_tiff = TIFFStreamOpen("MemTIFF", &input_stream);
     if (!m_tiff) {
-        throw Exceptions::FormatErrorException("TiffHandler::read() -> Can't open the file.");
+        throw std::runtime_error("TiffHandler::read() -> Can't open the file.");
     }
     read_header();
     read_data();
@@ -47,8 +47,8 @@ const OutputData<double>* TiffHandler::getOutputData() const {
 void TiffHandler::write(const OutputData<double>& data, std::ostream& output_stream) {
     m_data.reset(data.clone());
     if (m_data->rank() != 2)
-        throw Exceptions::LogicErrorException("TiffHandler::write -> Error. "
-                                              "Only 2-dim arrays supported");
+        throw std::runtime_error("TiffHandler::write -> Error. "
+                                 "Only 2-dim arrays supported");
     m_tiff = TIFFStreamOpen("MemTIFF", &output_stream);
     m_width = m_data->axis(0).size();
     m_height = m_data->axis(1).size(); // this does not exist for 1d data
@@ -63,8 +63,8 @@ void TiffHandler::read_header() {
     uint32 height(0);
     if (!TIFFGetField(m_tiff, TIFFTAG_IMAGEWIDTH, &width)
         || !TIFFGetField(m_tiff, TIFFTAG_IMAGELENGTH, &height)) {
-        throw Exceptions::FormatErrorException("TiffHandler::read_header() -> Error. "
-                                               "Can't read width/height.");
+        throw std::runtime_error("TiffHandler::read_header() -> Error. "
+                                 "Can't read width/height.");
     }
 
     m_width = (size_t)width;
@@ -109,7 +109,7 @@ void TiffHandler::read_header() {
                 << "    TIFFTAG_BITSPERSAMPLE: " << m_bitsPerSample << std::endl
                 << "    TIFFTAG_SAMPLESPERPIXEL: " << m_samplesPerPixel << std::endl
                 << "    TIFFTAG_SAMPLEFORMAT: " << m_sampleFormat << std::endl;
-        throw Exceptions::FormatErrorException(message.str());
+        throw std::runtime_error(message.str());
     }
 }
 
@@ -121,13 +121,11 @@ void TiffHandler::read_data() {
     tmsize_t buf_size = TIFFScanlineSize(m_tiff);
     tmsize_t expected_size = bytesPerSample * m_width;
     if (buf_size != expected_size)
-        throw Exceptions::FormatErrorException(
-            "TiffHandler::read_data() -> Error. Wrong scanline size.");
+        throw std::runtime_error("TiffHandler::read_data() -> Error. Wrong scanline size.");
 
     tdata_t buf = _TIFFmalloc(buf_size);
     if (!buf)
-        throw Exceptions::FormatErrorException(
-            "TiffHandler::read_data() -> Error. Can't allocate buffer.");
+        throw std::runtime_error("TiffHandler::read_data() -> Error. Can't allocate buffer.");
 
     create_output_data();
 
@@ -138,8 +136,7 @@ void TiffHandler::read_data() {
 
     for (uint32 row = 0; row < (uint32)m_height; row++) {
         if (TIFFReadScanline(m_tiff, buf, row) < 0)
-            throw Exceptions::FormatErrorException(
-                "TiffHandler::read_data() -> Error. Error in scanline.");
+            throw std::runtime_error("TiffHandler::read_data() -> Error. Error in scanline.");
 
         memcpy(&line_buf[0], buf, buf_size);
 
@@ -182,7 +179,7 @@ void TiffHandler::read_data() {
                 sample = double(*reinterpret_cast<float*>(incoming));
                 break;
             default:
-                throw Exceptions::FormatErrorException("TiffHandler: unexpected sample format");
+                throw std::runtime_error("TiffHandler: unexpected sample format");
             }
 
             (*m_data)[global_index] = sample;
@@ -217,8 +214,7 @@ void TiffHandler::write_data() {
     tmsize_t buf_size = sizeof(sample_t) * m_width;
     tdata_t buf = _TIFFmalloc(buf_size);
     if (!buf)
-        throw Exceptions::FormatErrorException(
-            "TiffHandler::write_data() -> Error. Can't allocate buffer.");
+        throw std::runtime_error("TiffHandler::write_data() -> Error. Can't allocate buffer.");
 
     std::vector<sample_t> line_buf;
     line_buf.resize(m_width, 0);
@@ -233,7 +229,7 @@ void TiffHandler::write_data() {
         memcpy(buf, &line_buf[0], buf_size);
 
         if (TIFFWriteScanline(m_tiff, buf, row) < 0)
-            throw Exceptions::FormatErrorException(
+            throw std::runtime_error(
                 "TiffHandler::write_data() -> Error. Error in TIFFWriteScanline.");
     }
     _TIFFfree(buf);
diff --git a/Device/Instrument/FourierTransform.cpp b/Device/Instrument/FourierTransform.cpp
index d524989146bce88336d9c0de9a63e7fb63d0f802..3805beacb569048189266f4a8a2d61377bf362e9 100644
--- a/Device/Instrument/FourierTransform.cpp
+++ b/Device/Instrument/FourierTransform.cpp
@@ -14,7 +14,6 @@
 //  ************************************************************************************************
 
 #include "Device/Instrument/FourierTransform.h"
-#include "Base/Types/Exceptions.h"
 #include <algorithm>
 #include <cmath>
 #include <iostream>
@@ -124,7 +123,7 @@ void FourierTransform::fft(const double1d_t& source, double1d_t& result) {
     fft(source2d, result2d);
 
     if (result2d.size() != 1)
-        throw Exceptions::RuntimeErrorException("FourierTransform::fft -> Panic in 1d");
+        throw std::runtime_error("FourierTransform::fft -> Panic in 1d");
 
     result = result2d[0];
 }
@@ -151,7 +150,7 @@ void FourierTransform::init(int h_src, int w_src) {
         std::ostringstream os;
         os << "FourierTransform::init() -> Panic! Wrong dimensions " << h_src << " " << w_src
            << std::endl;
-        throw Exceptions::RuntimeErrorException(os.str());
+        throw std::runtime_error(os.str());
     }
 
     ws.clear();
@@ -172,7 +171,7 @@ void FourierTransform::init(int h_src, int w_src) {
     //                                     static_cast<double*>(ws.out_src), FFTW_ESTIMATE);
 
     if (ws.p_forw_src == nullptr)
-        throw Exceptions::RuntimeErrorException(
+        throw std::runtime_error(
             "FourierTransform::init() -> Error! Can't initialise p_forw_src plan.");
 }
 
@@ -182,7 +181,7 @@ void FourierTransform::init(int h_src, int w_src) {
 
 void FourierTransform::fftw_forward_FT(const double2d_t& src) {
     if (ws.h_fftw <= 0 || ws.w_fftw <= 0)
-        throw Exceptions::RuntimeErrorException(
+        throw std::runtime_error(
             "FourierTransform::fftw_forward_FT() -> Panic! Initialisation is missed.");
 
     double *ptr, *ptr_end;
diff --git a/Device/Instrument/Instrument.cpp b/Device/Instrument/Instrument.cpp
index 6fab0c1e6931e4bafb081cfcc38e844271cbc614..8df69595b7b6cfe85ec11c2f5c45eaba3ab834bd 100644
--- a/Device/Instrument/Instrument.cpp
+++ b/Device/Instrument/Instrument.cpp
@@ -50,7 +50,7 @@ void Instrument::setDetector(const IDetector& detector) {
 
 void Instrument::initDetector() {
     if (!m_detector)
-        throw Exceptions::RuntimeErrorException(
+        throw std::runtime_error(
             "Instrument::initDetector() -> Error. Detector is not initialized.");
     m_detector->init(beam());
 }
diff --git a/Device/Instrument/IntensityDataFunctions.cpp b/Device/Instrument/IntensityDataFunctions.cpp
index 6faa28376e246407c0db23df3ed99f25c41fa5be..bded700dbeac7d1ee7b3d0654d212f0c1579c926 100644
--- a/Device/Instrument/IntensityDataFunctions.cpp
+++ b/Device/Instrument/IntensityDataFunctions.cpp
@@ -43,9 +43,8 @@ double IntensityDataFunctions::RelativeDifference(const SimulationResult& dat,
 double IntensityDataFunctions::getRelativeDifference(const OutputData<double>& dat,
                                                      const OutputData<double>& ref) {
     if (!dat.hasSameDimensions(ref))
-        throw Exceptions::RuntimeErrorException(
-            "IntensityDataFunctions::getRelativeDifference() -> "
-            "Error. Different dimensions of data and reference.");
+        throw std::runtime_error("IntensityDataFunctions::getRelativeDifference() -> "
+                                 "Error. Different dimensions of data and reference.");
 
     double diff = 0.0;
     for (size_t i = 0; i < dat.getAllocatedSize(); ++i)
@@ -53,7 +52,7 @@ double IntensityDataFunctions::getRelativeDifference(const OutputData<double>& d
     diff /= dat.getAllocatedSize();
 
     if (std::isnan(diff))
-        throw Exceptions::RuntimeErrorException("diff=NaN!");
+        throw std::runtime_error("diff=NaN!");
     return diff;
 }
 
@@ -84,9 +83,8 @@ std::unique_ptr<OutputData<double>>
 IntensityDataFunctions::createRelativeDifferenceData(const OutputData<double>& data,
                                                      const OutputData<double>& reference) {
     if (!data.hasSameDimensions(reference))
-        throw Exceptions::RuntimeErrorException(
-            "IntensityDataFunctions::createRelativeDifferenceData() -> "
-            "Error. Different dimensions of data and reference.");
+        throw std::runtime_error("IntensityDataFunctions::createRelativeDifferenceData() -> "
+                                 "Error. Different dimensions of data and reference.");
     std::unique_ptr<OutputData<double>> result(reference.clone());
     for (size_t i = 0; i < result->getAllocatedSize(); ++i)
         (*result)[i] = Numeric::GetRelativeDifference(data[i], reference[i]);
@@ -96,8 +94,8 @@ IntensityDataFunctions::createRelativeDifferenceData(const OutputData<double>& d
 std::unique_ptr<OutputData<double>>
 IntensityDataFunctions::createRearrangedDataSet(const OutputData<double>& data, int n) {
     if (data.rank() != 2)
-        throw Exceptions::LogicErrorException("IntensityDataFunctions::rotateDataByN90Deg()"
-                                              " -> Error! Works only on two-dimensional data");
+        throw std::runtime_error("IntensityDataFunctions::rotateDataByN90Deg()"
+                                 " -> Error! Works only on two-dimensional data");
     n = (4 + n % 4) % 4;
     if (n == 0)
         return std::unique_ptr<OutputData<double>>(data.clone());
@@ -142,8 +140,8 @@ std::unique_ptr<OutputData<double>>
 IntensityDataFunctions::createClippedDataSet(const OutputData<double>& origin, double x1, double y1,
                                              double x2, double y2) {
     if (origin.rank() != 2)
-        throw Exceptions::LogicErrorException("IntensityDataFunctions::createClippedData()"
-                                              " -> Error! Works only on two-dimensional data");
+        throw std::runtime_error("IntensityDataFunctions::createClippedData()"
+                                 " -> Error! Works only on two-dimensional data");
 
     std::unique_ptr<OutputData<double>> result(new OutputData<double>);
     for (size_t i_axis = 0; i_axis < origin.rank(); i_axis++) {
@@ -219,9 +217,8 @@ void IntensityDataFunctions::coordinateFromBinf(double& x, double& y,
 std::vector<std::vector<double>>
 IntensityDataFunctions::create2DArrayfromOutputData(const OutputData<double>& data) {
     if (data.rank() != 2)
-        throw Exceptions::LogicErrorException(
-            "IntensityDataFunctions::create2DArrayfromOutputData() -> "
-            "Error! Works only on two-dimensional data");
+        throw std::runtime_error("IntensityDataFunctions::create2DArrayfromOutputData() -> "
+                                 "Error! Works only on two-dimensional data");
 
     std::vector<std::vector<double>> array_2d;
     std::vector<double> row_vec; // row vector for constructing each row of 2D array
diff --git a/Device/Intensity/ArrayUtils.cpp b/Device/Intensity/ArrayUtils.cpp
index 0a896fc49293acaa37e0c4e65a093f181789c9e6..7f7ddd699262cd739f22574ff05d501790b9ff6b 100644
--- a/Device/Intensity/ArrayUtils.cpp
+++ b/Device/Intensity/ArrayUtils.cpp
@@ -27,7 +27,7 @@ PyObject* ArrayUtils::createNumpyArray(const std::vector<double>& data) {
     PyObject* pyarray = PyArray_SimpleNew(ndim_numpy, ndimsizes_numpy, NPY_DOUBLE);
     delete[] ndimsizes_numpy;
     if (pyarray == nullptr)
-        throw Exceptions::RuntimeErrorException("ExportOutputData() -> Panic in PyArray_SimpleNew");
+        throw std::runtime_error("ExportOutputData() -> Panic in PyArray_SimpleNew");
 
     // getting pointer to data buffer of numpy array
     double* array_buffer = (double*)PyArray_DATA((PyArrayObject*)pyarray);
diff --git a/Device/Mask/Ellipse.cpp b/Device/Mask/Ellipse.cpp
index 6084c13da94dd4d5a4622f77024c97bf7c19efd6..787a0fa6c06cb2fec6b9e24f141874ba4e92568b 100644
--- a/Device/Mask/Ellipse.cpp
+++ b/Device/Mask/Ellipse.cpp
@@ -14,7 +14,6 @@
 
 #include "Device/Mask/Ellipse.h"
 #include "Base/Axis/Bin.h"
-#include "Base/Types/Exceptions.h"
 
 //! @param xcenter x-coordinate of Ellipse's center
 //! @param ycenter y-coordinate of Ellipse's center
@@ -29,7 +28,7 @@ Ellipse::Ellipse(double xcenter, double ycenter, double xradius, double yradius,
     , m_yr(yradius)
     , m_theta(theta) {
     if (xradius <= 0.0 || yradius <= 0.0)
-        throw Exceptions::LogicErrorException(
+        throw std::runtime_error(
             "Ellipse::Ellipse(double xcenter, double ycenter, double xradius, double yradius) "
             "-> Error. Radius can't be negative\n");
 }
diff --git a/Device/Mask/Polygon.cpp b/Device/Mask/Polygon.cpp
index e84f449771be55ab9a1ae7ec6857598f855f3e57..05b74e9db94bd16c12a281a4f377e10af44aa55a 100644
--- a/Device/Mask/Polygon.cpp
+++ b/Device/Mask/Polygon.cpp
@@ -14,7 +14,6 @@
 
 #include "Device/Mask/Polygon.h"
 #include "Base/Axis/Bin.h"
-#include "Base/Types/Exceptions.h"
 
 #include <boost/geometry.hpp>
 #include <boost/geometry/geometries/point_xy.hpp>
@@ -34,7 +33,7 @@ public:
 
 void PolygonPrivate::init_from(const std::vector<double>& x, const std::vector<double>& y) {
     if (x.size() != y.size())
-        throw Exceptions::LogicErrorException(
+        throw std::runtime_error(
             "Polygon::Polygon(const std::vector<double>& x, const std::vector<double>& y) "
             "Error. Sizes of arrays must conincide.");
     std::vector<point_t> points;
@@ -76,7 +75,7 @@ Polygon::Polygon(const std::vector<std::vector<double>> points)
     std::vector<double> y;
     for (size_t i = 0; i < points.size(); ++i) {
         if (points[i].size() != 2)
-            throw Exceptions::LogicErrorException(
+            throw std::runtime_error(
                 "Polygon(const std::vector<std::vector<double> >& points) -> Error. "
                 " Should be two-dimensional array with second dimension of 2 size.");
         x.push_back(points[i][0]);
diff --git a/Device/Mask/Rectangle.cpp b/Device/Mask/Rectangle.cpp
index c47ac24dcdb90b6ae199e8c62dfc2adbbdd6f283..7f1705470937896bed3304e87360c4e484eba5cb 100644
--- a/Device/Mask/Rectangle.cpp
+++ b/Device/Mask/Rectangle.cpp
@@ -14,7 +14,6 @@
 
 #include "Device/Mask/Rectangle.h"
 #include "Base/Axis/Bin.h"
-#include "Base/Types/Exceptions.h"
 
 //! @param xlow x-coordinate of lower left corner
 //! @param ylow y-coordinate of lower left corner
@@ -25,13 +24,13 @@ Rectangle::Rectangle(double xlow, double ylow, double xup, double yup) : IShape2
         std::ostringstream message;
         message << "Rectangle(double xlow, double ylow, double xup, double yup) -> Error. ";
         message << " xup <= xlow" << std::endl;
-        throw Exceptions::LogicErrorException(message.str());
+        throw std::runtime_error(message.str());
     }
     if (yup <= ylow) {
         std::ostringstream message;
         message << "Rectangle(double xlow, double ylow, double xup, double yup) -> Error. ";
         message << " yup <= ylow" << std::endl;
-        throw Exceptions::LogicErrorException(message.str());
+        throw std::runtime_error(message.str());
     }
     m_xlow = xlow;
     m_ylow = ylow;
diff --git a/Device/Resolution/ConvolutionDetectorResolution.cpp b/Device/Resolution/ConvolutionDetectorResolution.cpp
index 3e2e30d83f3a69ba9add36e8ba345e96a83c5be1..f75598b17f1a7f22feabb1269f3a34774616b0ed 100644
--- a/Device/Resolution/ConvolutionDetectorResolution.cpp
+++ b/Device/Resolution/ConvolutionDetectorResolution.cpp
@@ -49,7 +49,7 @@ std::vector<const INode*> ConvolutionDetectorResolution::getChildren() const {
 void ConvolutionDetectorResolution::applyDetectorResolution(
     OutputData<double>* p_intensity_map) const {
     if (p_intensity_map->rank() != m_dimension) {
-        throw Exceptions::RuntimeErrorException(
+        throw std::runtime_error(
             "ConvolutionDetectorResolution::applyDetectorResolution() -> Error! "
             "Intensity map must have same dimension as detector resolution function.");
     }
@@ -61,7 +61,7 @@ void ConvolutionDetectorResolution::applyDetectorResolution(
         apply2dConvolution(p_intensity_map);
         break;
     default:
-        throw Exceptions::LogicErrorException(
+        throw std::runtime_error(
             "ConvolutionDetectorResolution::applyDetectorResolution() -> Error! "
             "Class ConvolutionDetectorResolution must be initialized with dimension 1 or 2.");
     }
@@ -74,11 +74,10 @@ void ConvolutionDetectorResolution::setResolutionFunction(const IResolutionFunct
 
 void ConvolutionDetectorResolution::apply1dConvolution(OutputData<double>* p_intensity_map) const {
     if (m_res_function_1d == 0)
-        throw Exceptions::LogicErrorException(
-            "ConvolutionDetectorResolution::apply1dConvolution() -> Error! "
-            "No 1d resolution function present for convolution of 1d data.");
+        throw std::runtime_error("ConvolutionDetectorResolution::apply1dConvolution() -> Error! "
+                                 "No 1d resolution function present for convolution of 1d data.");
     if (p_intensity_map->rank() != 1)
-        throw Exceptions::LogicErrorException(
+        throw std::runtime_error(
             "ConvolutionDetectorResolution::apply1dConvolution() -> Error! "
             "Number of axes for intensity map does not correspond to the dimension of the map.");
     const IAxis& axis = p_intensity_map->axis(0);
@@ -89,7 +88,7 @@ void ConvolutionDetectorResolution::apply1dConvolution(OutputData<double>* p_int
         return; // No convolution for sets of zero or one element
     // Construct kernel vector from resolution function
     if (axis.size() != data_size)
-        throw Exceptions::LogicErrorException(
+        throw std::runtime_error(
             "ConvolutionDetectorResolution::apply1dConvolution() -> Error! "
             "Size of axis for intensity map does not correspond to size of data in the map.");
     double step_size = std::abs(axis[0] - axis[axis.size() - 1]) / (data_size - 1);
@@ -109,11 +108,10 @@ void ConvolutionDetectorResolution::apply1dConvolution(OutputData<double>* p_int
 
 void ConvolutionDetectorResolution::apply2dConvolution(OutputData<double>* p_intensity_map) const {
     if (m_res_function_2d == 0)
-        throw Exceptions::LogicErrorException(
-            "ConvolutionDetectorResolution::apply2dConvolution() -> Error! "
-            "No 2d resolution function present for convolution of 2d data.");
+        throw std::runtime_error("ConvolutionDetectorResolution::apply2dConvolution() -> Error! "
+                                 "No 2d resolution function present for convolution of 2d data.");
     if (p_intensity_map->rank() != 2)
-        throw Exceptions::LogicErrorException(
+        throw std::runtime_error(
             "ConvolutionDetectorResolution::apply2dConvolution() -> Error! "
             "Number of axes for intensity map does not correspond to the dimension of the map.");
     const IAxis& axis_1 = p_intensity_map->axis(0);
@@ -127,7 +125,7 @@ void ConvolutionDetectorResolution::apply2dConvolution(OutputData<double>* p_int
     std::vector<std::vector<double>> source;
     size_t raw_data_size = raw_source_vector.size();
     if (raw_data_size != axis_size_1 * axis_size_2)
-        throw Exceptions::LogicErrorException(
+        throw std::runtime_error(
             "ConvolutionDetectorResolution::apply2dConvolution() -> Error! "
             "Intensity map data size does not match the product of its axes' sizes");
     for (auto it = raw_source_vector.begin(); it != raw_source_vector.end(); it += axis_size_2) {
diff --git a/Device/Resolution/Convolve.cpp b/Device/Resolution/Convolve.cpp
index 91d348c4e1fd8a5cdfea804bdfc9a700469133c0..a5afe95e2ac84eb9a5ad2b93d80004aa3e7dc888 100644
--- a/Device/Resolution/Convolve.cpp
+++ b/Device/Resolution/Convolve.cpp
@@ -13,7 +13,6 @@
 //  ************************************************************************************************
 
 #include "Device/Resolution/Convolve.h"
-#include "Base/Types/Exceptions.h"
 #include <iostream>
 #include <sstream>
 #include <stdexcept> // need overlooked by g++ 5.4
@@ -139,7 +138,7 @@ void Convolve::fftconvolve(const double1d_t& source, const double1d_t& kernel, d
     double2d_t result2d;
     fftconvolve(source2d, kernel2d, result2d);
     if (result2d.size() != 1)
-        throw Exceptions::RuntimeErrorException("Convolve::fftconvolve -> Panic in 1d");
+        throw std::runtime_error("Convolve::fftconvolve -> Panic in 1d");
     result = result2d[0];
 }
 
@@ -151,7 +150,7 @@ void Convolve::init(int h_src, int w_src, int h_kernel, int w_kernel) {
         std::ostringstream os;
         os << "Convolve::init() -> Panic! Wrong dimensions " << h_src << " " << w_src << " "
            << h_kernel << " " << w_kernel << std::endl;
-        throw Exceptions::RuntimeErrorException(os.str());
+        throw std::runtime_error(os.str());
     }
 
     ws.clear();
@@ -245,21 +244,18 @@ void Convolve::init(int h_src, int w_src, int h_kernel, int w_kernel) {
     ws.p_forw_src = fftw_plan_dft_r2c_2d(ws.h_fftw, ws.w_fftw, ws.in_src, (fftw_complex*)ws.out_src,
                                          FFTW_ESTIMATE);
     if (ws.p_forw_src == nullptr)
-        throw Exceptions::RuntimeErrorException(
-            "Convolve::init() -> Error! Can't initialise p_forw_src plan.");
+        throw std::runtime_error("Convolve::init() -> Error! Can't initialise p_forw_src plan.");
 
     ws.p_forw_kernel = fftw_plan_dft_r2c_2d(ws.h_fftw, ws.w_fftw, ws.in_kernel,
                                             (fftw_complex*)ws.out_kernel, FFTW_ESTIMATE);
     if (ws.p_forw_kernel == nullptr)
-        throw Exceptions::RuntimeErrorException(
-            "Convolve::init() -> Error! Can't initialise p_forw_kernel plan.");
+        throw std::runtime_error("Convolve::init() -> Error! Can't initialise p_forw_kernel plan.");
 
     // The backward FFT takes ws.out_kernel as input
     ws.p_back = fftw_plan_dft_c2r_2d(ws.h_fftw, ws.w_fftw, (fftw_complex*)ws.out_kernel, ws.dst_fft,
                                      FFTW_ESTIMATE);
     if (ws.p_back == nullptr)
-        throw Exceptions::RuntimeErrorException(
-            "Convolve::init() -> Error! Can't initialise p_back plan.");
+        throw std::runtime_error("Convolve::init() -> Error! Can't initialise p_back plan.");
 }
 
 /* ************************************************************************* */
@@ -268,8 +264,7 @@ void Convolve::init(int h_src, int w_src, int h_kernel, int w_kernel) {
 
 void Convolve::fftw_circular_convolution(const double2d_t& src, const double2d_t& kernel) {
     if (ws.h_fftw <= 0 || ws.w_fftw <= 0)
-        throw Exceptions::RuntimeErrorException(
-            "Convolve::fftw_convolve() -> Panic! Initialisation is missed.");
+        throw std::runtime_error("Convolve::fftw_convolve() -> Panic! Initialisation is missed.");
 
     double *ptr, *ptr_end, *ptr2;
 
diff --git a/Device/Resolution/ScanResolution.cpp b/Device/Resolution/ScanResolution.cpp
index 7dadd1da2962f617c055a2d9876981d26c815765..bf5e224e01b25e082ebfa6c23cf830c7a22ad09e 100644
--- a/Device/Resolution/ScanResolution.cpp
+++ b/Device/Resolution/ScanResolution.cpp
@@ -13,19 +13,17 @@
 //  ************************************************************************************************
 
 #include "Device/Resolution/ScanResolution.h"
-#include "Base/Utils/PyFmt.h"
 #include "Param/Distrib/RangedDistributions.h"
 
 namespace {
 void checkIfEmpty(const std::vector<double>& input);
-std::string printDeltas(const std::vector<double>& deltas);
 
 const std::string relative_resolution = "ScanRelativeResolution";
 const std::string absolute_resolution = "ScanAbsoluteResolution";
 
 class ScanSingleRelativeResolution : public ScanResolution {
 public:
-    ScanSingleRelativeResolution(const RangedDistribution& distr, double reldev)
+    ScanSingleRelativeResolution(const IRangedDistribution& distr, double reldev)
         : ScanResolution(distr), m_reldev(reldev) {}
     ~ScanSingleRelativeResolution() override = default;
 
@@ -38,9 +36,10 @@ public:
     std::vector<double> stdDevs(double mean, size_t n_times) const override;
     std::vector<double> stdDevs(const std::vector<double>& mean) const override;
 
+    double delta() const override { return m_reldev; }
+
 protected:
     std::string name() const override { return relative_resolution; }
-    std::string printStdDevs() const override { return pyfmt::printDouble(m_reldev); }
 
 private:
     double m_reldev; //!< deltas for computing resolutions
@@ -48,7 +47,7 @@ private:
 
 class ScanSingleAbsoluteResolution : public ScanResolution {
 public:
-    ScanSingleAbsoluteResolution(const RangedDistribution& distr, double stddev)
+    ScanSingleAbsoluteResolution(const IRangedDistribution& distr, double stddev)
         : ScanResolution(distr), m_stddev(stddev) {}
     ~ScanSingleAbsoluteResolution() override = default;
 
@@ -61,9 +60,10 @@ public:
     std::vector<double> stdDevs(double mean, size_t n_times) const override;
     std::vector<double> stdDevs(const std::vector<double>& mean) const override;
 
+    double delta() const override { return m_stddev; }
+
 protected:
     std::string name() const override { return absolute_resolution; }
-    std::string printStdDevs() const override { return pyfmt::printDouble(m_stddev); }
 
 private:
     double m_stddev; //!< deltas for computing resolutions
@@ -71,7 +71,8 @@ private:
 
 class ScanVectorRelativeResolution : public ScanResolution {
 public:
-    ScanVectorRelativeResolution(const RangedDistribution& distr, const std::vector<double>& reldev)
+    ScanVectorRelativeResolution(const IRangedDistribution& distr,
+                                 const std::vector<double>& reldev)
         : ScanResolution(distr), m_reldev(reldev) {
         checkIfEmpty(m_reldev);
     }
@@ -86,9 +87,10 @@ public:
     std::vector<double> stdDevs(double mean, size_t n_times) const override;
     std::vector<double> stdDevs(const std::vector<double>& mean) const override;
 
+    double delta() const override { return 0; } // TODO
+
 protected:
     std::string name() const override { return relative_resolution; }
-    std::string printStdDevs() const override { return printDeltas(m_reldev); }
 
 private:
     std::vector<double> m_reldev; //!< deltas for computing resolutions
@@ -96,7 +98,8 @@ private:
 
 class ScanVectorAbsoluteResolution : public ScanResolution {
 public:
-    ScanVectorAbsoluteResolution(const RangedDistribution& distr, const std::vector<double>& stddev)
+    ScanVectorAbsoluteResolution(const IRangedDistribution& distr,
+                                 const std::vector<double>& stddev)
         : ScanResolution(distr), m_stddev(stddev) {
         checkIfEmpty(m_stddev);
     }
@@ -111,9 +114,10 @@ public:
     std::vector<double> stdDevs(double mean, size_t n_times) const override;
     std::vector<double> stdDevs(const std::vector<double>& mean) const override;
 
+    double delta() const override { return 0; } // TODO
+
 protected:
     std::string name() const override { return absolute_resolution; }
-    std::string printStdDevs() const override { return printDeltas(m_stddev); }
 
 private:
     std::vector<double> m_stddev; //!< deltas for computing resolutions
@@ -132,30 +136,31 @@ public:
     std::vector<double> stdDevs(double mean, size_t n_times) const override;
     std::vector<double> stdDevs(const std::vector<double>& mean) const override;
 
+    double delta() const override { return 0; }
+
 protected:
     std::string name() const override;
-    std::string printStdDevs() const override;
 };
 } // namespace
 
 ScanResolution::~ScanResolution() = default;
 
-ScanResolution* ScanResolution::scanRelativeResolution(const RangedDistribution& distr,
+ScanResolution* ScanResolution::scanRelativeResolution(const IRangedDistribution& distr,
                                                        double stddev) {
     return new ScanSingleRelativeResolution(distr, stddev);
 }
 
-ScanResolution* ScanResolution::scanRelativeResolution(const RangedDistribution& distr,
+ScanResolution* ScanResolution::scanRelativeResolution(const IRangedDistribution& distr,
                                                        const std::vector<double>& stddevs) {
     return new ScanVectorRelativeResolution(distr, stddevs);
 }
 
-ScanResolution* ScanResolution::scanAbsoluteResolution(const RangedDistribution& distr,
+ScanResolution* ScanResolution::scanAbsoluteResolution(const IRangedDistribution& distr,
                                                        double stddev) {
     return new ScanSingleAbsoluteResolution(distr, stddev);
 }
 
-ScanResolution* ScanResolution::scanAbsoluteResolution(const RangedDistribution& distr,
+ScanResolution* ScanResolution::scanAbsoluteResolution(const IRangedDistribution& distr,
                                                        const std::vector<double>& stddevs) {
     return new ScanVectorAbsoluteResolution(distr, stddevs);
 }
@@ -170,22 +175,9 @@ size_t ScanResolution::nSamples() const {
     return 1;
 }
 
-std::string ScanResolution::print() const {
-    std::stringstream result;
-    result << *m_distr << "\n";
-    result << pyfmt::indent() << "resolution = ";
-    result << "ba." << name();
-    result << "("
-           << "distribution"
-           << ", ";
-    result << printStdDevs();
-    result << ")";
-    return result.str();
-}
-
 ScanResolution::ScanResolution() = default;
 
-ScanResolution::ScanResolution(const RangedDistribution& distr) : m_distr(distr.clone()) {}
+ScanResolution::ScanResolution(const IRangedDistribution& distr) : m_distr(distr.clone()) {}
 
 namespace {
 ScanResolution::DistrOutput ScanSingleRelativeResolution::generateSamples(double mean,
@@ -324,15 +316,6 @@ std::string ScanEmptyResolution::name() const {
         "Error in ScanEmptyResolution::name: attempt to get a name of an empty resolution object.");
 }
 
-std::string ScanEmptyResolution::printStdDevs() const {
-    throw std::runtime_error("Error in ScanEmptyResolution::printStdDevs: attempt to print data "
-                             "from empty resolution object.");
-}
-
-std::string printDeltas(const std::vector<double>&) {
-    throw std::runtime_error("Error in printDeltas: function is not implemented");
-}
-
 void checkIfEmpty(const std::vector<double>& input) {
     if (input.empty())
         throw std::runtime_error("Error in ScanResolution: passed vector is empty");
diff --git a/Device/Resolution/ScanResolution.h b/Device/Resolution/ScanResolution.h
index e75f56cabd41a8d569fdd0f5455ec36ddf7e81a2..f4298c8e4b921202dce80b0b71e95ed8afcc0352 100644
--- a/Device/Resolution/ScanResolution.h
+++ b/Device/Resolution/ScanResolution.h
@@ -21,7 +21,7 @@
 #include <string>
 #include <vector>
 
-class RangedDistribution;
+class IRangedDistribution;
 class RealLimits;
 
 //! Container for reflectivity resolution data.
@@ -31,17 +31,17 @@ protected:
 
 public:
     ~ScanResolution() override;
-    static ScanResolution* scanRelativeResolution(const RangedDistribution& distr, double stddev);
-    static ScanResolution* scanRelativeResolution(const RangedDistribution& distr,
+    static ScanResolution* scanRelativeResolution(const IRangedDistribution& distr, double stddev);
+    static ScanResolution* scanRelativeResolution(const IRangedDistribution& distr,
                                                   const std::vector<double>& stddevs);
-    static ScanResolution* scanAbsoluteResolution(const RangedDistribution& distr, double stddev);
-    static ScanResolution* scanAbsoluteResolution(const RangedDistribution& distr,
+    static ScanResolution* scanAbsoluteResolution(const IRangedDistribution& distr, double stddev);
+    static ScanResolution* scanAbsoluteResolution(const IRangedDistribution& distr,
                                                   const std::vector<double>& stddevs);
 #ifndef SWIG
     static ScanResolution* scanEmptyResolution();
 
     ScanResolution* clone() const override = 0;
-    const RangedDistribution* distribution() const { return m_distr.get(); }
+    const IRangedDistribution* distribution() const { return m_distr.get(); }
     size_t nSamples() const;
 
     virtual DistrOutput generateSamples(double mean, size_t n_times) const = 0;
@@ -50,21 +50,16 @@ public:
     virtual std::vector<double> stdDevs(const std::vector<double>& mean) const = 0;
     bool empty() const { return !m_distr; }
 
-    //! Prints object definition in python format.
-    std::string print() const;
+    virtual std::string name() const = 0;
+    virtual double delta() const = 0;
+
 #endif // SWIG
 protected:
     ScanResolution();
-    ScanResolution(const RangedDistribution& distr);
-    virtual std::string name() const = 0;
-    virtual std::string printStdDevs() const = 0;
+    ScanResolution(const IRangedDistribution& distr);
 
 private:
-    std::unique_ptr<RangedDistribution> m_distr; //!< basic distribution function
+    std::unique_ptr<IRangedDistribution> m_distr; //!< basic distribution function
 };
 
-inline std::ostream& operator<<(std::ostream& os, const ScanResolution& scan_resolution) {
-    return os << scan_resolution.print();
-}
-
 #endif // BORNAGAIN_DEVICE_RESOLUTION_SCANRESOLUTION_H
diff --git a/Fit/Test/Functional/Minimizer/ClassicalTestFunctions.h b/Fit/Test/Functional/Minimizer/ClassicalTestFunctions.h
index b8e1944371d25c7783f899bee5c62dd32877335e..2d9d9f1f440e43c2b91c1a9bb927bff03f745f15 100644
--- a/Fit/Test/Functional/Minimizer/ClassicalTestFunctions.h
+++ b/Fit/Test/Functional/Minimizer/ClassicalTestFunctions.h
@@ -12,8 +12,8 @@
 //
 //  ************************************************************************************************
 
-#ifndef BORNAGAIN_TESTS_FUNCTIONAL_FIT_MINIMIZER_CLASSICALTESTFUNCTIONS_H
-#define BORNAGAIN_TESTS_FUNCTIONAL_FIT_MINIMIZER_CLASSICALTESTFUNCTIONS_H
+#ifndef BORNAGAIN_FIT_TEST_FUNCTIONAL_MINIMIZER_CLASSICALTESTFUNCTIONS_H
+#define BORNAGAIN_FIT_TEST_FUNCTIONAL_MINIMIZER_CLASSICALTESTFUNCTIONS_H
 
 #include <vector>
 
@@ -28,4 +28,4 @@ double WoodFour(const std::vector<double>& par);
 double DecayingSin(double x, const std::vector<double>& par);
 } // namespace TestFunctions
 
-#endif // BORNAGAIN_TESTS_FUNCTIONAL_FIT_MINIMIZER_CLASSICALTESTFUNCTIONS_H
+#endif // BORNAGAIN_FIT_TEST_FUNCTIONAL_MINIMIZER_CLASSICALTESTFUNCTIONS_H
diff --git a/Fit/Test/Functional/Minimizer/PlanCases.h b/Fit/Test/Functional/Minimizer/PlanCases.h
index f32129f7c3d1e3f5c7d1f4869eb27424f1d164f6..aba15fcc0bcdf3ac58171d23002cbf0011c6e76f 100644
--- a/Fit/Test/Functional/Minimizer/PlanCases.h
+++ b/Fit/Test/Functional/Minimizer/PlanCases.h
@@ -12,8 +12,8 @@
 //
 //  ************************************************************************************************
 
-#ifndef BORNAGAIN_TESTS_FUNCTIONAL_FIT_MINIMIZER_PLANCASES_H
-#define BORNAGAIN_TESTS_FUNCTIONAL_FIT_MINIMIZER_PLANCASES_H
+#ifndef BORNAGAIN_FIT_TEST_FUNCTIONAL_MINIMIZER_PLANCASES_H
+#define BORNAGAIN_FIT_TEST_FUNCTIONAL_MINIMIZER_PLANCASES_H
 
 #include "Fit/Test/Functional/Minimizer/ResidualTestPlan.h"
 #include "Fit/Test/Functional/Minimizer/ScalarTestPlan.h"
@@ -70,4 +70,4 @@ public:
     TestMinimizerPlan();
 };
 
-#endif // BORNAGAIN_TESTS_FUNCTIONAL_FIT_MINIMIZER_PLANCASES_H
+#endif // BORNAGAIN_FIT_TEST_FUNCTIONAL_MINIMIZER_PLANCASES_H
diff --git a/Fit/Test/Functional/Minimizer/PlanFactory.h b/Fit/Test/Functional/Minimizer/PlanFactory.h
index 7275fa8d4a3232b3224bc71cd10686d9b201ea70..e3b3ad775524b0fc57153a1dc071f47c1d74f4ec 100644
--- a/Fit/Test/Functional/Minimizer/PlanFactory.h
+++ b/Fit/Test/Functional/Minimizer/PlanFactory.h
@@ -12,8 +12,8 @@
 //
 //  ************************************************************************************************
 
-#ifndef BORNAGAIN_TESTS_FUNCTIONAL_FIT_MINIMIZER_PLANFACTORY_H
-#define BORNAGAIN_TESTS_FUNCTIONAL_FIT_MINIMIZER_PLANFACTORY_H
+#ifndef BORNAGAIN_FIT_TEST_FUNCTIONAL_MINIMIZER_PLANFACTORY_H
+#define BORNAGAIN_FIT_TEST_FUNCTIONAL_MINIMIZER_PLANFACTORY_H
 
 #include "Fit/TestEngine/IFactory.h"
 #include "Fit/TestEngine/MinimizerTestPlan.h"
@@ -25,4 +25,4 @@ public:
     PlanFactory();
 };
 
-#endif // BORNAGAIN_TESTS_FUNCTIONAL_FIT_MINIMIZER_PLANFACTORY_H
+#endif // BORNAGAIN_FIT_TEST_FUNCTIONAL_MINIMIZER_PLANFACTORY_H
diff --git a/Fit/Test/Functional/Minimizer/ResidualTestPlan.h b/Fit/Test/Functional/Minimizer/ResidualTestPlan.h
index 07fba72a587016b5021ed135bdd7f47c43caa3fc..004c95eab80bd8cf302520f56dfef6dda3595806 100644
--- a/Fit/Test/Functional/Minimizer/ResidualTestPlan.h
+++ b/Fit/Test/Functional/Minimizer/ResidualTestPlan.h
@@ -12,8 +12,8 @@
 //
 //  ************************************************************************************************
 
-#ifndef BORNAGAIN_TESTS_FUNCTIONAL_FIT_MINIMIZER_RESIDUALTESTPLAN_H
-#define BORNAGAIN_TESTS_FUNCTIONAL_FIT_MINIMIZER_RESIDUALTESTPLAN_H
+#ifndef BORNAGAIN_FIT_TEST_FUNCTIONAL_MINIMIZER_RESIDUALTESTPLAN_H
+#define BORNAGAIN_FIT_TEST_FUNCTIONAL_MINIMIZER_RESIDUALTESTPLAN_H
 
 #include "Fit/Minimizer/Types.h"
 #include "Fit/TestEngine/MinimizerTestPlan.h"
@@ -37,4 +37,4 @@ private:
     test_funct_t m_test_func;
 };
 
-#endif // BORNAGAIN_TESTS_FUNCTIONAL_FIT_MINIMIZER_RESIDUALTESTPLAN_H
+#endif // BORNAGAIN_FIT_TEST_FUNCTIONAL_MINIMIZER_RESIDUALTESTPLAN_H
diff --git a/Fit/Test/Functional/Minimizer/ScalarTestPlan.h b/Fit/Test/Functional/Minimizer/ScalarTestPlan.h
index df4fd34ab9ab781b1b7a1c3a3b857e29a87c8d2a..03fcc9d5ac30886e3fc2ddd985a9e5078ad12bb7 100644
--- a/Fit/Test/Functional/Minimizer/ScalarTestPlan.h
+++ b/Fit/Test/Functional/Minimizer/ScalarTestPlan.h
@@ -12,8 +12,8 @@
 //
 //  ************************************************************************************************
 
-#ifndef BORNAGAIN_TESTS_FUNCTIONAL_FIT_MINIMIZER_SCALARTESTPLAN_H
-#define BORNAGAIN_TESTS_FUNCTIONAL_FIT_MINIMIZER_SCALARTESTPLAN_H
+#ifndef BORNAGAIN_FIT_TEST_FUNCTIONAL_MINIMIZER_SCALARTESTPLAN_H
+#define BORNAGAIN_FIT_TEST_FUNCTIONAL_MINIMIZER_SCALARTESTPLAN_H
 
 #include "Fit/Minimizer/Types.h"
 #include "Fit/TestEngine/MinimizerTestPlan.h"
@@ -37,4 +37,4 @@ private:
     double m_tolerance_on_minimum;
 };
 
-#endif // BORNAGAIN_TESTS_FUNCTIONAL_FIT_MINIMIZER_SCALARTESTPLAN_H
+#endif // BORNAGAIN_FIT_TEST_FUNCTIONAL_MINIMIZER_SCALARTESTPLAN_H
diff --git a/GUI/coregui/Models/DistributionItems.cpp b/GUI/coregui/Models/DistributionItems.cpp
index ed9c5159869c7634e3ec02ca27b4b8c97405d63e..fa26a24d86aeba85df3c0e319a0ce20dad0c647d 100644
--- a/GUI/coregui/Models/DistributionItems.cpp
+++ b/GUI/coregui/Models/DistributionItems.cpp
@@ -20,8 +20,8 @@
 
 namespace {
 template <class DistrType>
-std::unique_ptr<RangedDistribution>
-createRangedDistribution(const SymmetricDistributionItem& distr_item, double scale);
+std::unique_ptr<IRangedDistribution>
+createIRangedDistribution(const SymmetricDistributionItem& distr_item, double scale);
 }
 
 const QString DistributionItem::P_NUMBER_OF_SAMPLES = "Number of samples";
@@ -104,7 +104,7 @@ std::unique_ptr<IDistribution1D> DistributionNoneItem::createDistribution(double
     return nullptr;
 }
 
-std::unique_ptr<RangedDistribution> DistributionNoneItem::createRangedDistribution(double) const {
+std::unique_ptr<IRangedDistribution> DistributionNoneItem::createIRangedDistribution(double) const {
     return nullptr;
 }
 
@@ -162,9 +162,9 @@ std::unique_ptr<IDistribution1D> DistributionLorentzItem::createDistribution(dou
     return std::make_unique<DistributionLorentz>(scale * mean, scale * hwhm);
 }
 
-std::unique_ptr<RangedDistribution>
-DistributionLorentzItem::createRangedDistribution(double scale) const {
-    return ::createRangedDistribution<RangedDistributionLorentz>(*this, scale);
+std::unique_ptr<IRangedDistribution>
+DistributionLorentzItem::createIRangedDistribution(double scale) const {
+    return ::createIRangedDistribution<RangedDistributionLorentz>(*this, scale);
 }
 
 double DistributionLorentzItem::deviation(double scale) const {
@@ -200,9 +200,9 @@ std::unique_ptr<IDistribution1D> DistributionGaussianItem::createDistribution(do
     return std::make_unique<DistributionGaussian>(scale * mean, scale * std_dev);
 }
 
-std::unique_ptr<RangedDistribution>
-DistributionGaussianItem::createRangedDistribution(double scale) const {
-    return ::createRangedDistribution<RangedDistributionGaussian>(*this, scale);
+std::unique_ptr<IRangedDistribution>
+DistributionGaussianItem::createIRangedDistribution(double scale) const {
+    return ::createIRangedDistribution<RangedDistributionGaussian>(*this, scale);
 }
 
 double DistributionGaussianItem::deviation(double scale) const {
@@ -270,9 +270,9 @@ std::unique_ptr<IDistribution1D> DistributionCosineItem::createDistribution(doub
     return std::make_unique<DistributionCosine>(scale * mean, scale * sigma);
 }
 
-std::unique_ptr<RangedDistribution>
-DistributionCosineItem::createRangedDistribution(double scale) const {
-    return ::createRangedDistribution<RangedDistributionCosine>(*this, scale);
+std::unique_ptr<IRangedDistribution>
+DistributionCosineItem::createIRangedDistribution(double scale) const {
+    return ::createIRangedDistribution<RangedDistributionCosine>(*this, scale);
 }
 
 double DistributionCosineItem::deviation(double scale) const {
@@ -330,8 +330,8 @@ void DistributionTrapezoidItem::showMean(bool flag) {
 
 namespace {
 template <class DistrType>
-std::unique_ptr<RangedDistribution>
-createRangedDistribution(const SymmetricDistributionItem& distr_item, double scale) {
+std::unique_ptr<IRangedDistribution>
+createIRangedDistribution(const SymmetricDistributionItem& distr_item, double scale) {
     int n_samples = distr_item.getItemValue(SymmetricDistributionItem::P_NUMBER_OF_SAMPLES).toInt();
     double n_sig = distr_item.getItemValue(SymmetricDistributionItem::P_SIGMA_FACTOR).toDouble();
 
diff --git a/GUI/coregui/Models/DistributionItems.h b/GUI/coregui/Models/DistributionItems.h
index 577901bcfda38e2ae3d87d0c97c9b6317aa372f2..2278464985c92c804058b30f591236eae61c4841 100644
--- a/GUI/coregui/Models/DistributionItems.h
+++ b/GUI/coregui/Models/DistributionItems.h
@@ -18,7 +18,7 @@
 #include "GUI/coregui/Models/SessionItem.h"
 
 class IDistribution1D;
-class RangedDistribution;
+class IRangedDistribution;
 
 class BA_CORE_API_ DistributionItem : public SessionItem {
 public:
@@ -47,7 +47,7 @@ public:
     explicit SymmetricDistributionItem(const QString& name);
     void showMean(bool flag) override;
 
-    virtual std::unique_ptr<RangedDistribution> createRangedDistribution(double scale) const = 0;
+    virtual std::unique_ptr<IRangedDistribution> createIRangedDistribution(double scale) const = 0;
     virtual double deviation(double scale) const = 0;
 };
 
@@ -57,7 +57,7 @@ public:
     DistributionNoneItem();
 
     std::unique_ptr<IDistribution1D> createDistribution(double scale = 1.0) const override;
-    std::unique_ptr<RangedDistribution> createRangedDistribution(double scale) const override;
+    std::unique_ptr<IRangedDistribution> createIRangedDistribution(double scale) const override;
     double deviation(double scale) const override;
     void init_distribution(double value) override;
 };
@@ -79,7 +79,7 @@ public:
     DistributionLorentzItem();
 
     std::unique_ptr<IDistribution1D> createDistribution(double scale = 1.0) const override;
-    std::unique_ptr<RangedDistribution> createRangedDistribution(double scale) const override;
+    std::unique_ptr<IRangedDistribution> createIRangedDistribution(double scale) const override;
     double deviation(double scale) const override;
     void init_distribution(double value) override;
 };
@@ -90,7 +90,7 @@ public:
     DistributionGaussianItem();
 
     std::unique_ptr<IDistribution1D> createDistribution(double scale = 1.0) const override;
-    std::unique_ptr<RangedDistribution> createRangedDistribution(double scale) const override;
+    std::unique_ptr<IRangedDistribution> createIRangedDistribution(double scale) const override;
     double deviation(double scale) const override;
     void init_distribution(double value) override;
 };
@@ -113,7 +113,7 @@ public:
     DistributionCosineItem();
 
     std::unique_ptr<IDistribution1D> createDistribution(double scale = 1.0) const override;
-    std::unique_ptr<RangedDistribution> createRangedDistribution(double scale) const override;
+    std::unique_ptr<IRangedDistribution> createIRangedDistribution(double scale) const override;
     double deviation(double scale) const override;
     void init_distribution(double value) override;
 };
diff --git a/GUI/coregui/Models/TransformFromDomain.cpp b/GUI/coregui/Models/TransformFromDomain.cpp
index 9a0d98540c8100ed5391a26bafa11347cf481d71..540cbcc6acc0c14abda0c70520e2b4b6b6874790 100644
--- a/GUI/coregui/Models/TransformFromDomain.cpp
+++ b/GUI/coregui/Models/TransformFromDomain.cpp
@@ -82,7 +82,7 @@ void addDistributionToBeamItem(const std::string& parameter_name, const QString&
                                const ParameterDistribution& distribution,
                                const BeamItem* beam_item);
 
-void addRangedDistributionToItem(SessionItem* item, const RangedDistribution& ranged, double mean,
+void addRangedDistributionToItem(SessionItem* item, const IRangedDistribution& ranged, double mean,
                                  double std_dev);
 } // namespace
 
@@ -823,7 +823,7 @@ void addDistributionToBeamItem(const std::string& parameter_name, const QString&
     TransformFromDomain::setItemFromSample(beam_parameter, distribution);
 }
 
-void addRangedDistributionToItem(SessionItem* item, const RangedDistribution& ranged, double mean,
+void addRangedDistributionToItem(SessionItem* item, const IRangedDistribution& ranged, double mean,
                                  double std_dev) {
     auto distr_item = dynamic_cast<BeamDistributionItem*>(item);
     if (!distr_item)
diff --git a/GUI/coregui/Models/TransformToDomain.cpp b/GUI/coregui/Models/TransformToDomain.cpp
index 1c844256a3200c0be3da4c243bc5b0ea7e94c492..4e59b0264ba2536a33420c18a6ec4b7a7d916602 100644
--- a/GUI/coregui/Models/TransformToDomain.cpp
+++ b/GUI/coregui/Models/TransformToDomain.cpp
@@ -249,7 +249,7 @@ std::unique_ptr<ScanResolution> createScanResolution(const SessionItem* item) {
         return nullptr;
 
     const double scale = beam_item->scaleFactor();
-    auto ranged_distr = distr_item->createRangedDistribution(scale);
+    auto ranged_distr = distr_item->createIRangedDistribution(scale);
     if (!ranged_distr)
         return nullptr;
 
diff --git a/GUI/coregui/Views/ImportDataWidgets/CsvImportAssistant/CsvImportAssistant.cpp b/GUI/coregui/Views/ImportDataWidgets/CsvImportAssistant/CsvImportAssistant.cpp
index 5a8229104158afec6592800fa24bdf13016ded8c..cfc43d2bdbc3bc986bee938132b3a600661b1e32 100644
--- a/GUI/coregui/Views/ImportDataWidgets/CsvImportAssistant/CsvImportAssistant.cpp
+++ b/GUI/coregui/Views/ImportDataWidgets/CsvImportAssistant/CsvImportAssistant.cpp
@@ -260,8 +260,7 @@ void CsvImportAssistant::removeBlankColumns() {
     size_t nCols = m_csvArray[0].size();
 
     if (!hasEqualLengthLines(m_csvArray)) {
-        throw Exceptions::NotImplementedException(
-            "All inner vectors should have the same length already.");
+        throw std::runtime_error("All inner vectors should have the same length already.");
     }
 
     // traverse the array columnwise -- this may be inneficient.
diff --git a/GUI/coregui/Views/RealSpaceWidgets/RealSpaceBuilderUtils.cpp b/GUI/coregui/Views/RealSpaceWidgets/RealSpaceBuilderUtils.cpp
index 72b56b88098b0cf048c63dd21c406ae05f722cc3..a4ade5682101274c594e45d6a11f49fe4d8838fb 100644
--- a/GUI/coregui/Views/RealSpaceWidgets/RealSpaceBuilderUtils.cpp
+++ b/GUI/coregui/Views/RealSpaceWidgets/RealSpaceBuilderUtils.cpp
@@ -14,7 +14,6 @@
 
 #include "GUI/coregui/Views/RealSpaceWidgets/RealSpaceBuilderUtils.h"
 #include "Base/Const/Units.h"
-#include "Base/Types/Exceptions.h"
 #include "GUI/coregui/Models/InterferenceFunctionItems.h"
 #include "GUI/coregui/Models/Lattice2DItems.h"
 #include "GUI/coregui/Models/LayerItem.h"
@@ -350,7 +349,7 @@ Particle3DContainer RealSpaceBuilderUtils::particleComposition3DContainer(
             std::ostringstream ostr;
             ostr << "Sorry, MesoCrystal inside ParticleComposition not yet implemented";
             ostr << "\n\nStay tuned!";
-            throw Exceptions::ClassInitializationException(ostr.str());
+            throw std::runtime_error(ostr.str());
         } else {
             auto particle = dynamic_cast<const Particle*>(pc_particle);
             particle3DContainer = singleParticle3DContainer(*particle, 1.0, origin);
@@ -391,7 +390,7 @@ std::vector<Particle3DContainer> RealSpaceBuilderUtils::particleDistribution3DCo
             std::ostringstream ostr;
             ostr << "Sorry, MesoCrystal inside ParticleDistribution not yet implemented";
             ostr << "\n\nStay tuned!";
-            throw Exceptions::ClassInitializationException(ostr.str());
+            throw std::runtime_error(ostr.str());
         } else {
             auto particle = dynamic_cast<const Particle*>(pd_particle);
             particle3DContainer = singleParticle3DContainer(*particle, total_abundance, origin);
diff --git a/GUI/coregui/Views/RealSpaceWidgets/RealSpaceMesoCrystalUtils.cpp b/GUI/coregui/Views/RealSpaceWidgets/RealSpaceMesoCrystalUtils.cpp
index 05b00758dad5b57cf6864ba1dc127569bd2f2b7e..10010f66fab6e61138a1102bc23f045a99529196 100644
--- a/GUI/coregui/Views/RealSpaceWidgets/RealSpaceMesoCrystalUtils.cpp
+++ b/GUI/coregui/Views/RealSpaceWidgets/RealSpaceMesoCrystalUtils.cpp
@@ -14,7 +14,6 @@
 
 #include "GUI/coregui/Views/RealSpaceWidgets/RealSpaceMesoCrystalUtils.h"
 #include "Base/Const/Units.h"
-#include "Base/Types/Exceptions.h"
 #include "GUI/coregui/Models/Lattice2DItems.h"
 #include "GUI/coregui/Models/MesoCrystalItem.h"
 #include "GUI/coregui/Models/ParticleCompositionItem.h"
@@ -136,12 +135,12 @@ bool isPositionInsideMesoCrystal(const IFormFactor* outerShape, kvector_t positi
         std::ostringstream ostr;
         ostr << "Sorry, outer shape Dodecahedron not yet implemented for Mesocrystal";
         ostr << "\n\nStay tuned!";
-        throw Exceptions::ClassInitializationException(ostr.str());
+        throw std::runtime_error(ostr.str());
     } else if (dynamic_cast<const FormFactorDot*>(outerShape)) {
         std::ostringstream ostr;
         ostr << "Cannot display particles inside the Mesocrystal!";
         ostr << "\n\nOuter shape is a Dot!";
-        throw Exceptions::ClassInitializationException(ostr.str());
+        throw std::runtime_error(ostr.str());
     } else if (auto ff_EllipsoidalCylinder =
                    dynamic_cast<const FormFactorEllipsoidalCylinder*>(outerShape)) {
         double a = ff_EllipsoidalCylinder->getRadiusX(); // semi-axis length along x
@@ -196,7 +195,7 @@ bool isPositionInsideMesoCrystal(const IFormFactor* outerShape, kvector_t positi
         std::ostringstream ostr;
         ostr << "Sorry, outer shape Icosahedron not yet implemented for Mesocrystal";
         ostr << "\n\nStay tuned!";
-        throw Exceptions::ClassInitializationException(ostr.str());
+        throw std::runtime_error(ostr.str());
     } else if (auto ff_Prism3 = dynamic_cast<const FormFactorPrism3*>(outerShape)) {
         double B = ff_Prism3->getBaseEdge();
         double H = ff_Prism3->getHeight();
@@ -254,37 +253,37 @@ bool isPositionInsideMesoCrystal(const IFormFactor* outerShape, kvector_t positi
         std::ostringstream ostr;
         ostr << "Sorry, outer shape CosineRippleBox not yet implemented for Mesocrystal";
         ostr << "\n\nStay tuned!";
-        throw Exceptions::ClassInitializationException(ostr.str());
+        throw std::runtime_error(ostr.str());
     } else if (dynamic_cast<const FormFactorCosineRippleGauss*>(outerShape)) {
         // TODO: Implement CosineRippleGauss
         std::ostringstream ostr;
         ostr << "Sorry, outer shape CosineRippleGauss not yet implemented for Mesocrystal";
         ostr << "\n\nStay tuned!";
-        throw Exceptions::ClassInitializationException(ostr.str());
+        throw std::runtime_error(ostr.str());
     } else if (dynamic_cast<const FormFactorCosineRippleLorentz*>(outerShape)) {
         // TODO: Implement CosineRippleLorentz
         std::ostringstream ostr;
         ostr << "Sorry, outer shape CosineRippleLorentz not yet implemented for Mesocrystal";
         ostr << "\n\nStay tuned!";
-        throw Exceptions::ClassInitializationException(ostr.str());
+        throw std::runtime_error(ostr.str());
     } else if (dynamic_cast<const FormFactorSawtoothRippleBox*>(outerShape)) {
         // TODO: Implement SawtoothRippleBox
         std::ostringstream ostr;
         ostr << "Sorry, outer shape SawtoothRippleBox not yet implemented for Mesocrystal";
         ostr << "\n\nStay tuned!";
-        throw Exceptions::ClassInitializationException(ostr.str());
+        throw std::runtime_error(ostr.str());
     } else if (dynamic_cast<const FormFactorSawtoothRippleGauss*>(outerShape)) {
         // TODO: Implement SawtoothRippleGauss
         std::ostringstream ostr;
         ostr << "Sorry, outer shape SawtoothRippleGauss not yet implemented for Mesocrystal";
         ostr << "\n\nStay tuned!";
-        throw Exceptions::ClassInitializationException(ostr.str());
+        throw std::runtime_error(ostr.str());
     } else if (dynamic_cast<const FormFactorSawtoothRippleLorentz*>(outerShape)) {
         // TODO: Implement SawtoothRippleLorentz
         std::ostringstream ostr;
         ostr << "Sorry, outer shape SawtoothRippleLorentz not yet implemented for Mesocrystal";
         ostr << "\n\nStay tuned!";
-        throw Exceptions::ClassInitializationException(ostr.str());
+        throw std::runtime_error(ostr.str());
     } else if (auto ff_Tetrahedron = dynamic_cast<const FormFactorTetrahedron*>(outerShape)) {
         double B = ff_Tetrahedron->getBaseEdge();
         double H = ff_Tetrahedron->getHeight();
@@ -317,7 +316,7 @@ bool isPositionInsideMesoCrystal(const IFormFactor* outerShape, kvector_t positi
         std::ostringstream ostr;
         ostr << "Sorry, outer shape Truncated cube not yet implemented for Mesocrystal";
         ostr << "\n\nStay tuned!";
-        throw Exceptions::ClassInitializationException(ostr.str());
+        throw std::runtime_error(ostr.str());
     } else if (auto ff_TruncatedSphere =
                    dynamic_cast<const FormFactorTruncatedSphere*>(outerShape)) {
         double R = ff_TruncatedSphere->getRadius();
@@ -336,7 +335,7 @@ bool isPositionInsideMesoCrystal(const IFormFactor* outerShape, kvector_t positi
         std::ostringstream ostr;
         ostr << "Sorry, outer shape Truncated spheroid not yet implemented for Mesocrystal";
         ostr << "\n\nStay tuned!";
-        throw Exceptions::ClassInitializationException(ostr.str());
+        throw std::runtime_error(ostr.str());
     }
     return check;
 }
@@ -381,7 +380,7 @@ Particle3DContainer RealSpaceMesoCrystal::populateMesoCrystal() {
         std::ostringstream ostr;
         ostr << "Sorry, MesoCrystal inside MesoCrystal not yet implemented";
         ostr << "\n\nStay tuned!";
-        throw Exceptions::ClassInitializationException(ostr.str());
+        throw std::runtime_error(ostr.str());
     } else {
         auto particle = dynamic_cast<const Particle*>(particleBasis.get());
         mesoCrystalBasis3DContainer =
diff --git a/Param/Base/IParameterized.cpp b/Param/Base/IParameterized.cpp
index db193af0b6264f661f3a825de9e389c95f36c3b3..8d5327636f821b5f7873ca296c4dd0e8c2dbc1f0 100644
--- a/Param/Base/IParameterized.cpp
+++ b/Param/Base/IParameterized.cpp
@@ -13,7 +13,6 @@
 //  ************************************************************************************************
 
 #include "Param/Base/IParameterized.h"
-#include "Base/Types/Exceptions.h"
 #include "Param/Base/ParameterPool.h"
 #include "Param/Base/RealParameter.h"
 #include <iostream>
diff --git a/Param/Base/ParameterPool.cpp b/Param/Base/ParameterPool.cpp
index 67f49f91c512e3437bfcfdc2f2dc43dca2d3d17c..4d9b273a8c8f5750bbc050d55cc609105bc27676 100644
--- a/Param/Base/ParameterPool.cpp
+++ b/Param/Base/ParameterPool.cpp
@@ -13,7 +13,6 @@
 //  ************************************************************************************************
 
 #include "Param/Base/ParameterPool.h"
-#include "Base/Types/Exceptions.h"
 #include "Base/Utils/Assert.h"
 #include "Base/Utils/StringUtils.h"
 #include "Param/Base/RealParameter.h"
@@ -55,10 +54,9 @@ void ParameterPool::clear() {
 RealParameter& ParameterPool::addParameter(RealParameter* newPar) {
     for (const auto* par : m_params)
         if (par->getName() == newPar->getName())
-            throw Exceptions::RuntimeErrorException("ParameterPool::addParameter() -> Error. "
-                                                    "Parameter '"
-                                                    + newPar->getName()
-                                                    + "' is already registered");
+            throw std::runtime_error("ParameterPool::addParameter() -> Error. "
+                                     "Parameter '"
+                                     + newPar->getName() + "' is already registered");
     m_params.push_back(newPar);
     return *newPar;
 }
@@ -106,11 +104,11 @@ std::vector<RealParameter*> ParameterPool::getMatchedParameters(const std::strin
 RealParameter* ParameterPool::getUniqueMatch(const std::string& pattern) const {
     std::vector<RealParameter*> matches = getMatchedParameters(pattern);
     if (matches.empty())
-        throw Exceptions::RuntimeErrorException(
-            "ParameterPool::getUniqueMatch: there is no match for '" + pattern + "'");
+        throw std::runtime_error("ParameterPool::getUniqueMatch: there is no match for '" + pattern
+                                 + "'");
     if (matches.size() != 1)
-        throw Exceptions::RuntimeErrorException("ParameterPool::getUniqueMatch: pattern '" + pattern
-                                                + "' is not unique");
+        throw std::runtime_error("ParameterPool::getUniqueMatch: pattern '" + pattern
+                                 + "' is not unique");
     return matches[0];
 }
 
@@ -128,7 +126,7 @@ void ParameterPool::setParameterValue(const std::string& name, double value) {
         message << "ParameterPool::getParameter() -> Warning. No parameter with name '" + name
                        + "'\n"
                 << "Available parameters:" << *this;
-        throw Exceptions::RuntimeErrorException(message.str());
+        throw std::runtime_error(message.str());
     }
 }
 
@@ -153,8 +151,8 @@ int ParameterPool::setMatchedParametersValue(const std::string& pattern, double
 
 void ParameterPool::setUniqueMatchValue(const std::string& pattern, double value) {
     if (setMatchedParametersValue(pattern, value) != 1)
-        throw Exceptions::RuntimeErrorException("ParameterPool::setUniqueMatchValue: pattern '"
-                                                + pattern + "' is not unique");
+        throw std::runtime_error("ParameterPool::setUniqueMatchValue: pattern '" + pattern
+                                 + "' is not unique");
 }
 
 std::vector<std::string> ParameterPool::parameterNames() const {
@@ -195,7 +193,7 @@ void ParameterPool::report_find_matched_parameters_error(const std::string& patt
          << "' have been found. Existing keys are:" << std::endl;
     for (const auto* par : m_params)
         ostr << "'" << par->getName() << "'\n";
-    throw Exceptions::RuntimeErrorException(ostr.str());
+    throw std::runtime_error(ostr.str());
 }
 
 //! Reports error while setting parname to given value.
@@ -206,7 +204,7 @@ void ParameterPool::report_set_value_error(const std::string& parname, double va
     ostr << " for parameter '" << parname << "' failed.";
     ostr << " Parameter limits: '" << parameter(parname)->limits() << "'.\n";
     ostr << "Original exception message: " << message << std::endl;
-    throw Exceptions::RuntimeErrorException(ostr.str());
+    throw std::runtime_error(ostr.str());
 }
 
 size_t ParameterPool::check_index(size_t index) const {
diff --git a/Param/Distrib/DistributionHandler.cpp b/Param/Distrib/DistributionHandler.cpp
index 6f9e03874994c006f4e0d5001b450936f16d8228..e31f6313541e60fa44147a60e0cf2a1a4892d978 100644
--- a/Param/Distrib/DistributionHandler.cpp
+++ b/Param/Distrib/DistributionHandler.cpp
@@ -13,7 +13,6 @@
 //  ************************************************************************************************
 
 #include "Param/Distrib/DistributionHandler.h"
-#include "Base/Types/Exceptions.h"
 #include "Param/Base/ParameterPool.h"
 #include "Param/Distrib/Distributions.h"
 
@@ -37,7 +36,7 @@ size_t DistributionHandler::getTotalNumberOfSamples() const {
 
 double DistributionHandler::setParameterValues(ParameterPool* p_parameter_pool, size_t index) {
     if (index >= m_nbr_combinations)
-        throw Exceptions::RuntimeErrorException(
+        throw std::runtime_error(
             "DistributionWeighter::setParameterValues: "
             "index must be smaller than the total number of parameter combinations");
     size_t n_distr = m_distributions.size();
@@ -51,9 +50,9 @@ double DistributionHandler::setParameterValues(ParameterPool* p_parameter_pool,
             m_distributions[param_index].getMainParameterName(),
             m_cached_samples[param_index][remainder].value);
         if (changed != 1) {
-            throw Exceptions::RuntimeErrorException("DistributionWeighter::setParameterValues: "
-                                                    "parameter name matches nothing or more than "
-                                                    "one parameter");
+            throw std::runtime_error("DistributionWeighter::setParameterValues: "
+                                     "parameter name matches nothing or more than "
+                                     "one parameter");
         }
         weight *= m_cached_samples[param_index][remainder].weight;
         if (param_index == 0)
diff --git a/Param/Distrib/Distributions.cpp b/Param/Distrib/Distributions.cpp
index 395bcd00e43799eca89fe900852778d18c75112e..a480881e6e1c16fb4ae249f430acbee53372eddc 100644
--- a/Param/Distrib/Distributions.cpp
+++ b/Param/Distrib/Distributions.cpp
@@ -14,7 +14,6 @@
 
 #include "Param/Distrib/Distributions.h"
 #include "Base/Math/Constants.h"
-#include "Base/Types/Exceptions.h"
 #include "Param/Base/ParameterPool.h"
 #include "Param/Base/RealParameter.h"
 #include "Param/Varia/ParameterSample.h"
@@ -40,9 +39,8 @@ std::vector<ParameterSample> IDistribution1D::equidistantSamples(size_t nbr_samp
                                                                  double sigma_factor,
                                                                  const RealLimits& limits) const {
     if (nbr_samples == 0)
-        throw Exceptions::OutOfBoundsException(
-            "IDistribution1D::generateSamples: "
-            "number of generated samples must be bigger than zero");
+        throw std::runtime_error("IDistribution1D::generateSamples: "
+                                 "number of generated samples must be bigger than zero");
     if (isDelta())
         return {ParameterSample(getMean())};
     return generateSamplesFromValues(equidistantPoints(nbr_samples, sigma_factor, limits));
@@ -53,9 +51,8 @@ std::vector<ParameterSample> IDistribution1D::equidistantSamples(size_t nbr_samp
 std::vector<ParameterSample>
 IDistribution1D::equidistantSamplesInRange(size_t nbr_samples, double xmin, double xmax) const {
     if (nbr_samples == 0)
-        throw Exceptions::OutOfBoundsException(
-            "IDistribution1D::generateSamples: "
-            "number of generated samples must be bigger than zero");
+        throw std::runtime_error("IDistribution1D::generateSamples: "
+                                 "number of generated samples must be bigger than zero");
     if (isDelta())
         return {ParameterSample(getMean())};
     return generateSamplesFromValues(equidistantPointsInRange(nbr_samples, xmin, xmax));
@@ -88,7 +85,7 @@ void IDistribution1D::adjustMinMaxForLimits(double& xmin, double& xmax,
         std::ostringstream ostr;
         ostr << "IDistribution1D::adjustMinMaxForLimits() -> Error. Can't' adjust ";
         ostr << "xmin:" << xmin << " xmax:" << xmax << " for given limits " << limits << std::endl;
-        throw Exceptions::DomainErrorException(ostr.str());
+        throw std::runtime_error(ostr.str());
     }
 }
 
@@ -104,8 +101,8 @@ IDistribution1D::generateSamplesFromValues(const std::vector<double>& sample_val
         norm_factor += pdf;
     }
     if (norm_factor <= 0.0)
-        throw Exceptions::RuntimeErrorException("IDistribution1D::generateSamples: "
-                                                "total probability must be bigger than zero");
+        throw std::runtime_error("IDistribution1D::generateSamples: "
+                                 "total probability must be bigger than zero");
     for (ParameterSample& sample : result)
         sample.weight /= norm_factor;
     return result;
@@ -124,7 +121,7 @@ DistributionGate::DistributionGate(const std::vector<double> P)
     , m_min(m_P[0])
     , m_max(m_P[1]) {
     if (m_max < m_min)
-        throw Exceptions::ClassInitializationException("DistributionGate: max<min");
+        throw std::runtime_error("DistributionGate: max<min");
 }
 
 DistributionGate::DistributionGate(double min, double max)
@@ -165,7 +162,7 @@ DistributionLorentz::DistributionLorentz(const std::vector<double> P)
     , m_mean(m_P[0])
     , m_hwhm(m_P[1]) {
     if (m_hwhm < 0.0)
-        throw Exceptions::ClassInitializationException("DistributionLorentz: hwhm<0");
+        throw std::runtime_error("DistributionLorentz: hwhm<0");
 }
 
 DistributionLorentz::DistributionLorentz(double mean, double hwhm)
@@ -206,7 +203,7 @@ DistributionGaussian::DistributionGaussian(const std::vector<double> P)
     , m_mean(m_P[0])
     , m_std_dev(m_P[1]) {
     if (m_std_dev < 0.0)
-        throw Exceptions::ClassInitializationException("DistributionGaussian: std_dev < 0");
+        throw std::runtime_error("DistributionGaussian: std_dev < 0");
 }
 
 DistributionGaussian::DistributionGaussian(double mean, double std_dev)
@@ -248,9 +245,9 @@ DistributionLogNormal::DistributionLogNormal(const std::vector<double> P)
     , m_median(m_P[0])
     , m_scale_param(m_P[1]) {
     if (m_scale_param < 0.0)
-        throw Exceptions::ClassInitializationException("DistributionLogNormal: scale_param < 0");
+        throw std::runtime_error("DistributionLogNormal: scale_param < 0");
     if (m_median <= 0.0)
-        throw Exceptions::ClassInitializationException("DistributionLogNormal: median < 0");
+        throw std::runtime_error("DistributionLogNormal: median < 0");
 }
 
 DistributionLogNormal::DistributionLogNormal(double median, double scale_param)
@@ -308,7 +305,7 @@ DistributionCosine::DistributionCosine(const std::vector<double> P)
     , m_mean(m_P[0])
     , m_sigma(m_P[1]) {
     if (m_sigma < 0.0)
-        throw Exceptions::ClassInitializationException("DistributionCosine: sigma<0");
+        throw std::runtime_error("DistributionCosine: sigma<0");
 }
 
 DistributionCosine::DistributionCosine(double mean, double sigma)
@@ -355,11 +352,11 @@ DistributionTrapezoid::DistributionTrapezoid(const std::vector<double> P)
     , m_middle(m_P[2])
     , m_right(m_P[3]) {
     if (m_left < 0.0)
-        throw Exceptions::ClassInitializationException("DistributionTrapezoid: leftWidth < 0");
+        throw std::runtime_error("DistributionTrapezoid: leftWidth < 0");
     if (m_middle < 0.0)
-        throw Exceptions::ClassInitializationException("DistributionTrapezoid: middleWidth < 0");
+        throw std::runtime_error("DistributionTrapezoid: middleWidth < 0");
     if (m_right < 0.0)
-        throw Exceptions::ClassInitializationException("DistributionTrapezoid: rightWidth < 0");
+        throw std::runtime_error("DistributionTrapezoid: rightWidth < 0");
 }
 
 DistributionTrapezoid::DistributionTrapezoid(double center, double left, double middle,
diff --git a/Param/Distrib/ParameterDistribution.cpp b/Param/Distrib/ParameterDistribution.cpp
index dd929e53746a3973668e7bf9f698b269488201df..e600e53dda2daad03dc373f173af0e152fb364e9 100644
--- a/Param/Distrib/ParameterDistribution.cpp
+++ b/Param/Distrib/ParameterDistribution.cpp
@@ -13,7 +13,6 @@
 //  ************************************************************************************************
 
 #include "Param/Distrib/ParameterDistribution.h"
-#include "Base/Types/Exceptions.h"
 #include "Param/Distrib/Distributions.h"
 
 ParameterDistribution::ParameterDistribution(const std::string& par_name,
@@ -29,13 +28,11 @@ ParameterDistribution::ParameterDistribution(const std::string& par_name,
     , m_xmax(-1.0) {
     m_distribution.reset(distribution.clone());
     if (m_sigma_factor < 0.0)
-        throw Exceptions::RuntimeErrorException(
-            "ParameterDistribution::ParameterDistribution() -> Error."
-            "sigma factor cannot be negative");
+        throw std::runtime_error("ParameterDistribution::ParameterDistribution() -> Error."
+                                 "sigma factor cannot be negative");
     if (nbr_samples == 0)
-        throw Exceptions::RuntimeErrorException(
-            "ParameterDistribution::ParameterDistribution() -> Error."
-            "Number of samples can't be zero.");
+        throw std::runtime_error("ParameterDistribution::ParameterDistribution() -> Error."
+                                 "Number of samples can't be zero.");
 }
 
 ParameterDistribution::ParameterDistribution(const std::string& par_name,
@@ -49,19 +46,16 @@ ParameterDistribution::ParameterDistribution(const std::string& par_name,
     , m_xmax(xmax) {
     m_distribution.reset(distribution.clone());
     if (m_sigma_factor < 0.0) {
-        throw Exceptions::RuntimeErrorException(
-            "ParameterDistribution::ParameterDistribution() -> Error."
-            "sigma factor cannot be negative");
+        throw std::runtime_error("ParameterDistribution::ParameterDistribution() -> Error."
+                                 "sigma factor cannot be negative");
     }
     if (nbr_samples == 0) {
-        throw Exceptions::RuntimeErrorException(
-            "ParameterDistribution::ParameterDistribution() -> Error."
-            "Number of samples can't be zero.");
+        throw std::runtime_error("ParameterDistribution::ParameterDistribution() -> Error."
+                                 "Number of samples can't be zero.");
     }
     if (xmin >= xmax) {
-        throw Exceptions::RuntimeErrorException(
-            "ParameterDistribution::ParameterDistribution() -> Error."
-            "xmin>=xmax");
+        throw std::runtime_error("ParameterDistribution::ParameterDistribution() -> Error."
+                                 "xmin>=xmax");
     }
 }
 
diff --git a/Param/Distrib/RangedDistributions.cpp b/Param/Distrib/RangedDistributions.cpp
index 4de51297e4178c3525b27031eaad0d32cd2dcc16..cc134c3f8bc2c656b7ac5cb1bf78fb989de92499 100644
--- a/Param/Distrib/RangedDistributions.cpp
+++ b/Param/Distrib/RangedDistributions.cpp
@@ -13,40 +13,47 @@
 //  ************************************************************************************************
 
 #include "Param/Distrib/RangedDistributions.h"
-#include "Base/Utils/PyFmt.h"
 #include "Param/Distrib/Distributions.h"
 #include "Param/Varia/ParameterSample.h"
-#include "Param/Varia/PyFmtLimits.h"
 #include <limits>
 
 namespace {
-template <class T> std::unique_ptr<T> makeCopy(const T& item);
+
+template <class T> std::unique_ptr<T> makeCopy(const T& item) {
+    return std::make_unique<T>(item.nSamples(), item.sigmaFactor(), item.limits());
+}
 
 const double gate_stddev_factor = 2.0 * std::sqrt(3.0);
+
 } // namespace
 
-RangedDistribution::RangedDistribution()
+//  ************************************************************************************************
+//  interface IRangedDistribution
+//  ************************************************************************************************
+
+IRangedDistribution::IRangedDistribution()
     : m_n_samples(5), m_sigma_factor(2.0), m_limits(RealLimits::limitless()) {
     checkInitialization();
 }
 
-RangedDistribution::RangedDistribution(size_t n_samples, double sigma_factor,
-                                       const RealLimits& limits)
+IRangedDistribution::IRangedDistribution(size_t n_samples, double sigma_factor,
+                                         const RealLimits& limits)
     : m_n_samples(n_samples), m_sigma_factor(sigma_factor), m_limits(limits) {
     checkInitialization();
 }
 
-RangedDistribution::RangedDistribution(size_t n_samples, double sigma_factor, double min,
-                                       double max)
+IRangedDistribution::IRangedDistribution(size_t n_samples, double sigma_factor, double min,
+                                         double max)
     : m_n_samples(n_samples)
     , m_sigma_factor(sigma_factor)
     , m_limits(RealLimits::limited(min, max)) {
     checkInitialization();
 }
 
-RangedDistribution::~RangedDistribution() = default;
+IRangedDistribution::~IRangedDistribution() = default;
 
-std::vector<ParameterSample> RangedDistribution::generateSamples(double mean, double stddev) const {
+std::vector<ParameterSample> IRangedDistribution::generateSamples(double mean,
+                                                                  double stddev) const {
     auto generator = distribution(mean, stddev);
     if (!generator->isDelta())
         return generator->equidistantSamples(m_n_samples, m_sigma_factor, m_limits);
@@ -59,10 +66,10 @@ std::vector<ParameterSample> RangedDistribution::generateSamples(double mean, do
 }
 
 std::vector<std::vector<ParameterSample>>
-RangedDistribution::generateSamples(const std::vector<double>& mean,
-                                    const std::vector<double>& stddev) const {
+IRangedDistribution::generateSamples(const std::vector<double>& mean,
+                                     const std::vector<double>& stddev) const {
     if (mean.size() != stddev.size())
-        throw std::runtime_error("Error in RangedDistribution::generateSamples: mean and variance "
+        throw std::runtime_error("Error in IRangedDistribution::generateSamples: mean and variance "
                                  "vectors shall be of the same size");
 
     const size_t size = mean.size();
@@ -74,57 +81,51 @@ RangedDistribution::generateSamples(const std::vector<double>& mean,
     return result;
 }
 
-std::unique_ptr<IDistribution1D> RangedDistribution::distribution(double mean,
-                                                                  double stddev) const {
+std::unique_ptr<IDistribution1D> IRangedDistribution::distribution(double mean,
+                                                                   double stddev) const {
     if (stddev < 0.0)
         throw std::runtime_error(
-            "Error in RangedDistribution::distribution: standard deviation is less than zero");
+            "Error in IRangedDistribution::distribution: standard deviation is less than zero");
     return distribution_impl(mean, stddev);
 }
 
-std::string RangedDistribution::pyString() const {
-    std::stringstream result;
-    result << pyfmt::indent() << "distribution = " << name();
-    result << "(" << m_n_samples << ", " << pyfmt::printDouble(m_sigma_factor);
-    if (!m_limits.isLimitless())
-        result << pyfmt::printRealLimitsArg(m_limits);
-    result << ")";
-    return result.str();
-}
-
-void RangedDistribution::checkInitialization() {
+void IRangedDistribution::checkInitialization() {
     if (m_n_samples < 1u)
-        throw std::runtime_error("Error in RangedDistribution::checkInitialization: number of "
+        throw std::runtime_error("Error in IRangedDistribution::checkInitialization: number of "
                                  "samples shall be positive");
 
     if (m_sigma_factor < 0.0)
-        throw std::runtime_error("Error in RangedDistribution::checkInitialization: sigma factor "
+        throw std::runtime_error("Error in IRangedDistribution::checkInitialization: sigma factor "
                                  "shall be non-negative.");
 
     if (!m_limits.hasLowerAndUpperLimits())
         return;
 
     if (m_limits.lowerLimit() >= m_limits.upperLimit())
-        throw std::runtime_error("Error in RangedDistribution::checkInitialization: lower limit "
+        throw std::runtime_error("Error in IRangedDistribution::checkInitialization: lower limit "
                                  "shall not exceed the upper one.");
 }
 
-RangedDistributionGate::RangedDistributionGate() : RangedDistribution() {}
+//  ************************************************************************************************
+//  class RangedDistributionGate
+//  ************************************************************************************************
+
+RangedDistributionGate::RangedDistributionGate() : IRangedDistribution() {}
 
 RangedDistributionGate::RangedDistributionGate(size_t n_samples, double sigma_factor,
                                                const RealLimits& limits)
-    : RangedDistribution(n_samples, sigma_factor, limits) {}
+    : IRangedDistribution(n_samples, sigma_factor, limits) {}
 
 RangedDistributionGate::RangedDistributionGate(size_t n_samples, double sigma_factor, double min,
                                                double max)
-    : RangedDistribution(n_samples, sigma_factor, min, max) {}
+    : IRangedDistribution(n_samples, sigma_factor, min, max) {}
 
 RangedDistributionGate* RangedDistributionGate::clone() const {
     return makeCopy(*this).release();
 }
 
 std::string RangedDistributionGate::name() const {
-    return "ba.RangedDistributionGate";
+    return "RangedDistributionGate";
 }
 
 std::unique_ptr<IDistribution1D> RangedDistributionGate::distribution_impl(double mean,
@@ -134,22 +135,26 @@ std::unique_ptr<IDistribution1D> RangedDistributionGate::distribution_impl(doubl
     return std::make_unique<DistributionGate>(x_min, x_max);
 }
 
-RangedDistributionLorentz::RangedDistributionLorentz() : RangedDistribution() {}
+//  ************************************************************************************************
+//  class RangedDistributionLorentz
+//  ************************************************************************************************
+
+RangedDistributionLorentz::RangedDistributionLorentz() : IRangedDistribution() {}
 
 RangedDistributionLorentz::RangedDistributionLorentz(size_t n_samples, double hwhm_factor,
                                                      const RealLimits& limits)
-    : RangedDistribution(n_samples, hwhm_factor, limits) {}
+    : IRangedDistribution(n_samples, hwhm_factor, limits) {}
 
 RangedDistributionLorentz::RangedDistributionLorentz(size_t n_samples, double hwhm_factor,
                                                      double min, double max)
-    : RangedDistribution(n_samples, hwhm_factor, min, max) {}
+    : IRangedDistribution(n_samples, hwhm_factor, min, max) {}
 
 RangedDistributionLorentz* RangedDistributionLorentz::clone() const {
     return makeCopy(*this).release();
 }
 
 std::string RangedDistributionLorentz::name() const {
-    return "ba.RangedDistributionLorentz";
+    return "RangedDistributionLorentz";
 }
 
 std::unique_ptr<IDistribution1D> RangedDistributionLorentz::distribution_impl(double median,
@@ -157,22 +162,26 @@ std::unique_ptr<IDistribution1D> RangedDistributionLorentz::distribution_impl(do
     return std::make_unique<DistributionLorentz>(median, hwhm);
 }
 
-RangedDistributionGaussian::RangedDistributionGaussian() : RangedDistribution() {}
+//  ************************************************************************************************
+//  class RangedDistributionGaussian
+//  ************************************************************************************************
+
+RangedDistributionGaussian::RangedDistributionGaussian() : IRangedDistribution() {}
 
 RangedDistributionGaussian::RangedDistributionGaussian(size_t n_samples, double sigma_factor,
                                                        const RealLimits& limits)
-    : RangedDistribution(n_samples, sigma_factor, limits) {}
+    : IRangedDistribution(n_samples, sigma_factor, limits) {}
 
 RangedDistributionGaussian::RangedDistributionGaussian(size_t n_samples, double sigma_factor,
                                                        double min, double max)
-    : RangedDistribution(n_samples, sigma_factor, min, max) {}
+    : IRangedDistribution(n_samples, sigma_factor, min, max) {}
 
 RangedDistributionGaussian* RangedDistributionGaussian::clone() const {
     return makeCopy(*this).release();
 }
 
 std::string RangedDistributionGaussian::name() const {
-    return "ba.RangedDistributionGaussian";
+    return "RangedDistributionGaussian";
 }
 
 std::unique_ptr<IDistribution1D>
@@ -180,22 +189,26 @@ RangedDistributionGaussian::distribution_impl(double mean, double stddev) const
     return std::make_unique<DistributionGaussian>(mean, stddev);
 }
 
-RangedDistributionLogNormal::RangedDistributionLogNormal() : RangedDistribution() {}
+//  ************************************************************************************************
+//  class RangedDistributionLogNormal
+//  ************************************************************************************************
+
+RangedDistributionLogNormal::RangedDistributionLogNormal() : IRangedDistribution() {}
 
 RangedDistributionLogNormal::RangedDistributionLogNormal(size_t n_samples, double sigma_factor,
                                                          const RealLimits& limits)
-    : RangedDistribution(n_samples, sigma_factor, limits) {}
+    : IRangedDistribution(n_samples, sigma_factor, limits) {}
 
 RangedDistributionLogNormal::RangedDistributionLogNormal(size_t n_samples, double sigma_factor,
                                                          double min, double max)
-    : RangedDistribution(n_samples, sigma_factor, min, max) {}
+    : IRangedDistribution(n_samples, sigma_factor, min, max) {}
 
 RangedDistributionLogNormal* RangedDistributionLogNormal::clone() const {
     return makeCopy(*this).release();
 }
 
 std::string RangedDistributionLogNormal::name() const {
-    return "ba.RangedDistributionLogNormal";
+    return "RangedDistributionLogNormal";
 }
 
 std::unique_ptr<IDistribution1D>
@@ -210,31 +223,29 @@ RangedDistributionLogNormal::distribution_impl(double mean, double stddev) const
     return std::make_unique<DistributionLogNormal>(median, scale);
 }
 
-RangedDistributionCosine::RangedDistributionCosine() : RangedDistribution() {}
+//  ************************************************************************************************
+//  class RangedDistributionCosine
+//  ************************************************************************************************
+
+RangedDistributionCosine::RangedDistributionCosine() : IRangedDistribution() {}
 
 RangedDistributionCosine::RangedDistributionCosine(size_t n_samples, double sigma_factor,
                                                    const RealLimits& limits)
-    : RangedDistribution(n_samples, sigma_factor, limits) {}
+    : IRangedDistribution(n_samples, sigma_factor, limits) {}
 
 RangedDistributionCosine::RangedDistributionCosine(size_t n_samples, double sigma_factor,
                                                    double min, double max)
-    : RangedDistribution(n_samples, sigma_factor, min, max) {}
+    : IRangedDistribution(n_samples, sigma_factor, min, max) {}
 
 RangedDistributionCosine* RangedDistributionCosine::clone() const {
     return makeCopy(*this).release();
 }
 
 std::string RangedDistributionCosine::name() const {
-    return "ba.RangedDistributionCosine";
+    return "RangedDistributionCosine";
 }
 
 std::unique_ptr<IDistribution1D> RangedDistributionCosine::distribution_impl(double mean,
                                                                              double stddev) const {
     return std::make_unique<DistributionCosine>(mean, stddev);
 }
-
-namespace {
-template <class T> std::unique_ptr<T> makeCopy(const T& item) {
-    return std::make_unique<T>(item.nSamples(), item.sigmaFactor(), item.limits());
-}
-} // namespace
diff --git a/Param/Distrib/RangedDistributions.h b/Param/Distrib/RangedDistributions.h
index 828b0d77fb5d1cd8a5391cfb0fc02df0cd71923a..1224d9fc9c75c784e7abbcac1418dd13475537e4 100644
--- a/Param/Distrib/RangedDistributions.h
+++ b/Param/Distrib/RangedDistributions.h
@@ -33,19 +33,19 @@ class ParameterSample;
 //! (except for RangedDistributionLorentz which uses median and hwhm).
 //! @ingroup distribution_internal
 
-class RangedDistribution : public ICloneable {
+class IRangedDistribution : public ICloneable {
 public:
-    RangedDistribution();
-    RangedDistribution(size_t n_samples, double sigma_factor,
-                       const RealLimits& limits = RealLimits::limitless());
+    IRangedDistribution();
+    IRangedDistribution(size_t n_samples, double sigma_factor,
+                        const RealLimits& limits = RealLimits::limitless());
     //! Initializes Ranged distribution with given number of samples, sigma factor
     //! (range in standard deviations to take into account during sample generation)
     //! and limits (either RealLimits object or just min and max limits).
     //! By default _n_samples_ = 5, _sigma_factor_ = 2.0, while the limits are (-inf, +inf).
-    RangedDistribution(size_t n_samples, double sigma_factor, double min, double max);
-    RangedDistribution* clone() const override = 0;
+    IRangedDistribution(size_t n_samples, double sigma_factor, double min, double max);
+    IRangedDistribution* clone() const override = 0;
 
-    ~RangedDistribution() override;
+    ~IRangedDistribution() override;
 
     std::vector<ParameterSample> generateSamples(double mean, double stddev) const;
     //! Generates list of sampled values with their weights from given means and standard
@@ -69,12 +69,10 @@ public:
 
     void setLimits(const RealLimits& limits) { m_limits = limits; }
 
-    //! Prints python-formatted definition of the distribution
-    std::string pyString() const;
-
-protected:
     //! Returns distribution name for python-formatted text.
     virtual std::string name() const = 0;
+
+protected:
     //! Returns underlying IDistribution1D object
     virtual std::unique_ptr<IDistribution1D> distribution_impl(double mean,
                                                                double stddev) const = 0;
@@ -94,7 +92,7 @@ private:
 //! Uniform distribution function.
 //! @ingroup paramDistribution
 
-class RangedDistributionGate : public RangedDistribution {
+class RangedDistributionGate : public IRangedDistribution {
 public:
     RangedDistributionGate();
     RangedDistributionGate(size_t n_samples, double sigma_factor,
@@ -108,9 +106,10 @@ public:
     RangedDistributionGate* clone() const override;
     ~RangedDistributionGate() override = default;
 
-protected:
     //! Returns distribution name for python-formatted text.
     std::string name() const override;
+
+protected:
     //! Returns underlying IDistribution1D object
     std::unique_ptr<IDistribution1D> distribution_impl(double mean, double stddev) const override;
 };
@@ -118,7 +117,7 @@ protected:
 //! Lorentz distribution with median and hwhm.
 //! @ingroup paramDistribution
 
-class RangedDistributionLorentz : public RangedDistribution {
+class RangedDistributionLorentz : public IRangedDistribution {
 public:
     RangedDistributionLorentz();
     RangedDistributionLorentz(size_t n_samples, double hwhm_factor,
@@ -132,9 +131,10 @@ public:
     RangedDistributionLorentz* clone() const override;
     ~RangedDistributionLorentz() override = default;
 
-protected:
     //! Returns distribution name for python-formatted text.
     std::string name() const override;
+
+protected:
     //! Returns underlying IDistribution1D object
     std::unique_ptr<IDistribution1D> distribution_impl(double median, double hwhm) const override;
 };
@@ -142,7 +142,7 @@ protected:
 //! Gaussian distribution with standard deviation std_dev.
 //! @ingroup paramDistribution
 
-class RangedDistributionGaussian : public RangedDistribution {
+class RangedDistributionGaussian : public IRangedDistribution {
 public:
     RangedDistributionGaussian();
     RangedDistributionGaussian(size_t n_samples, double sigma_factor,
@@ -156,9 +156,10 @@ public:
     RangedDistributionGaussian* clone() const override;
     ~RangedDistributionGaussian() override = default;
 
-protected:
     //! Returns distribution name for python-formatted text.
     std::string name() const override;
+
+protected:
     //! Returns underlying IDistribution1D object
     std::unique_ptr<IDistribution1D> distribution_impl(double mean, double stddev) const override;
 };
@@ -166,7 +167,7 @@ protected:
 //! Log-normal distribution.
 //! @ingroup paramDistribution
 
-class RangedDistributionLogNormal : public RangedDistribution {
+class RangedDistributionLogNormal : public IRangedDistribution {
 public:
     RangedDistributionLogNormal();
     RangedDistributionLogNormal(size_t n_samples, double sigma_factor,
@@ -180,9 +181,10 @@ public:
     RangedDistributionLogNormal* clone() const override;
     ~RangedDistributionLogNormal() override = default;
 
-protected:
     //! Returns distribution name for python-formatted text.
     std::string name() const override;
+
+protected:
     //! Returns underlying IDistribution1D object
     std::unique_ptr<IDistribution1D> distribution_impl(double mean, double stddev) const override;
 };
@@ -190,7 +192,7 @@ protected:
 //! Cosine distribution.
 //! @ingroup paramDistribution
 
-class RangedDistributionCosine : public RangedDistribution {
+class RangedDistributionCosine : public IRangedDistribution {
 public:
     RangedDistributionCosine();
     RangedDistributionCosine(size_t n_samples, double sigma_factor,
@@ -204,15 +206,12 @@ public:
     RangedDistributionCosine* clone() const override;
     ~RangedDistributionCosine() override = default;
 
-protected:
     //! Returns distribution name for python-formatted text.
     std::string name() const override;
+
+protected:
     //! Returns underlying IDistribution1D object
     std::unique_ptr<IDistribution1D> distribution_impl(double mean, double stddev) const override;
 };
 
-inline std::ostream& operator<<(std::ostream& os, const RangedDistribution& distribution) {
-    return os << distribution.pyString();
-}
-
 #endif // BORNAGAIN_PARAM_DISTRIB_RANGEDDISTRIBUTIONS_H
diff --git a/Param/Node/NodeUtils.cpp b/Param/Node/NodeUtils.cpp
index a62e0d9e22c630ab1f33bba61303b00bdd5e35c9..a9ec109cc309c2bdce29002f9e48c37d15c81ea8 100644
--- a/Param/Node/NodeUtils.cpp
+++ b/Param/Node/NodeUtils.cpp
@@ -13,7 +13,6 @@
 //  ************************************************************************************************
 
 #include "Param/Node/NodeUtils.h"
-#include "Base/Types/Exceptions.h"
 #include "Param/Base/ParameterPool.h"
 #include "Param/Base/RealParameter.h"
 #include "Param/Node/IterationStrategy.h"
@@ -84,8 +83,8 @@ std::string NodeUtils::nodePath(const INode& node, const INode* root) {
     }
 
     if (root != nullptr && current != root) {
-        throw Exceptions::RuntimeErrorException("NodeUtils::nodePath() -> Error. Node doesn't "
-                                                "belong to root's branch");
+        throw std::runtime_error("NodeUtils::nodePath() -> Error. Node doesn't "
+                                 "belong to root's branch");
     }
 
     std::reverse(pathElements.begin(), pathElements.end());
diff --git a/Sample/Aggregate/InterferenceFunction1DLattice.cpp b/Sample/Aggregate/InterferenceFunction1DLattice.cpp
index 2ef04be29407dcba858ec095dc0f33c6ad628d43..e380f702ed6db47458cbf187b68ea54475eaecd6 100644
--- a/Sample/Aggregate/InterferenceFunction1DLattice.cpp
+++ b/Sample/Aggregate/InterferenceFunction1DLattice.cpp
@@ -13,7 +13,6 @@
 //  ************************************************************************************************
 
 #include "Sample/Aggregate/InterferenceFunction1DLattice.h"
-#include "Base/Types/Exceptions.h"
 #include "Base/Utils/Assert.h"
 #include "Param/Base/RealParameter.h"
 #include "Sample/Correlations/FTDecay1D.h"
diff --git a/Sample/Aggregate/InterferenceFunction2DLattice.cpp b/Sample/Aggregate/InterferenceFunction2DLattice.cpp
index eb8ec2fc01b7bc64951ffbe490374f2821da6c90..bd8a0d067cb3ed851b8fe5d0a947f5a0d8b69d40 100644
--- a/Sample/Aggregate/InterferenceFunction2DLattice.cpp
+++ b/Sample/Aggregate/InterferenceFunction2DLattice.cpp
@@ -14,7 +14,6 @@
 
 #include "Sample/Aggregate/InterferenceFunction2DLattice.h"
 #include "Base/Math/Integrator.h"
-#include "Base/Types/Exceptions.h"
 #include "Param/Base/RealParameter.h"
 #include <algorithm>
 
@@ -80,8 +79,8 @@ void InterferenceFunction2DLattice::onChange() {
 
 double InterferenceFunction2DLattice::iff_without_dw(const kvector_t q) const {
     if (!m_decay)
-        throw Exceptions::NullPointerException("InterferenceFunction2DLattice::evaluate"
-                                               " -> Error! No decay function defined.");
+        throw std::runtime_error("InterferenceFunction2DLattice::evaluate"
+                                 " -> Error! No decay function defined.");
     m_qx = q.x();
     m_qy = q.y();
     if (!m_integrate_xi)
@@ -107,9 +106,8 @@ double InterferenceFunction2DLattice::interferenceForXi(double xi) const {
 
 double InterferenceFunction2DLattice::interferenceAtOneRecLatticePoint(double qx, double qy) const {
     if (!m_decay)
-        throw Exceptions::NullPointerException(
-            "InterferenceFunction2DLattice::interferenceAtOneRecLatticePoint"
-            " -> Error! No decay function defined.");
+        throw std::runtime_error("InterferenceFunction2DLattice::interferenceAtOneRecLatticePoint"
+                                 " -> Error! No decay function defined.");
     double gamma = m_decay->gamma();
     auto qXY = rotateOrthonormal(qx, qy, gamma);
     return m_decay->evaluate(qXY.first, qXY.second);
@@ -159,9 +157,8 @@ void InterferenceFunction2DLattice::initialize_rec_vectors() {
 
 void InterferenceFunction2DLattice::initialize_calc_factors() {
     if (!m_decay)
-        throw Exceptions::NullPointerException(
-            "InterferenceFunction2DLattice::initialize_calc_factors"
-            " -> Error! No decay function defined.");
+        throw std::runtime_error("InterferenceFunction2DLattice::initialize_calc_factors"
+                                 " -> Error! No decay function defined.");
 
     // number of reciprocal lattice points to use
     auto q_bounds = m_decay->boundingReciprocalLatticeCoordinates(
diff --git a/Sample/Aggregate/InterferenceFunction2DParaCrystal.cpp b/Sample/Aggregate/InterferenceFunction2DParaCrystal.cpp
index 5aa22997a06aed8816e4e05b48a36aa591067267..eff1a68cb5e1ee28887dfd206763930b479548ca 100644
--- a/Sample/Aggregate/InterferenceFunction2DParaCrystal.cpp
+++ b/Sample/Aggregate/InterferenceFunction2DParaCrystal.cpp
@@ -14,7 +14,6 @@
 
 #include "Sample/Aggregate/InterferenceFunction2DParaCrystal.h"
 #include "Base/Math/Integrator.h"
-#include "Base/Types/Exceptions.h"
 #include "Param/Base/ParameterPool.h"
 #include "Param/Base/RealParameter.h"
 #include <limits>
@@ -111,15 +110,13 @@ double InterferenceFunction2DParaCrystal::interferenceForXi(double xi) const {
 double InterferenceFunction2DParaCrystal::interference1D(double qx, double qy, double xi,
                                                          size_t index) const {
     if (index > 1)
-        throw Exceptions::OutOfBoundsException(
-            "InterferenceFunction2DParaCrystal::"
-            "interference1D() -> Error! Index of interference function "
-            "probability must be < 2");
+        throw std::runtime_error("InterferenceFunction2DParaCrystal::"
+                                 "interference1D() -> Error! Index of interference function "
+                                 "probability must be < 2");
     if (!m_pdf1 || !m_pdf2)
-        throw Exceptions::NullPointerException(
-            "InterferenceFunction2DParaCrystal::"
-            "interference1D() -> Error! Probability distributions for "
-            "interference function not properly initialized");
+        throw std::runtime_error("InterferenceFunction2DParaCrystal::"
+                                 "interference1D() -> Error! Probability distributions for "
+                                 "interference function not properly initialized");
 
     double length = index ? m_lattice->length2() : m_lattice->length1();
     int n = static_cast<int>(std::abs(m_domain_sizes[index] / length));
diff --git a/Sample/Aggregate/InterferenceFunction2DSuperLattice.cpp b/Sample/Aggregate/InterferenceFunction2DSuperLattice.cpp
index 727eff9b5d50e341b4c72ce79c7fbf090f977d14..8c61e01698e2064a334f1e5bb3d4553bdb48c7bd 100644
--- a/Sample/Aggregate/InterferenceFunction2DSuperLattice.cpp
+++ b/Sample/Aggregate/InterferenceFunction2DSuperLattice.cpp
@@ -16,7 +16,6 @@
 #include "Base/Math/Constants.h"
 #include "Base/Math/Functions.h"
 #include "Base/Math/Integrator.h"
-#include "Base/Types/Exceptions.h"
 #include "Param/Base/RealParameter.h"
 #include "Sample/Aggregate/InterferenceFunctionNone.h"
 
diff --git a/Sample/Aggregate/InterferenceFunctionFinite2DLattice.cpp b/Sample/Aggregate/InterferenceFunctionFinite2DLattice.cpp
index 5306dcecb74351faa590f8434dbfe4d26113daf1..59562d7a006068c301ab882b0d96a1fa073ff9cb 100644
--- a/Sample/Aggregate/InterferenceFunctionFinite2DLattice.cpp
+++ b/Sample/Aggregate/InterferenceFunctionFinite2DLattice.cpp
@@ -16,7 +16,6 @@
 #include "Base/Math/Constants.h"
 #include "Base/Math/Functions.h"
 #include "Base/Math/Integrator.h"
-#include "Base/Types/Exceptions.h"
 #include "Param/Base/RealParameter.h"
 
 #include <limits>
diff --git a/Sample/Aggregate/InterferenceFunctionFinite3DLattice.cpp b/Sample/Aggregate/InterferenceFunctionFinite3DLattice.cpp
index 269fc462badb42435beb17711269c551d3f870eb..d6a61d7069236a5e6bc8f48140b22bac52e00c7d 100644
--- a/Sample/Aggregate/InterferenceFunctionFinite3DLattice.cpp
+++ b/Sample/Aggregate/InterferenceFunctionFinite3DLattice.cpp
@@ -15,7 +15,6 @@
 #include "Sample/Aggregate/InterferenceFunctionFinite3DLattice.h"
 #include "Base/Math/Constants.h"
 #include "Base/Math/Functions.h"
-#include "Base/Types/Exceptions.h"
 #include "Param/Base/RealParameter.h"
 
 #include <limits>
diff --git a/Sample/Aggregate/InterferenceFunctionRadialParaCrystal.cpp b/Sample/Aggregate/InterferenceFunctionRadialParaCrystal.cpp
index 1119a8909744605ba6e510f0eb1a3aecd8ce9f25..437661e87f01ad9bc7838e79c625284135bf0c03 100644
--- a/Sample/Aggregate/InterferenceFunctionRadialParaCrystal.cpp
+++ b/Sample/Aggregate/InterferenceFunctionRadialParaCrystal.cpp
@@ -13,7 +13,6 @@
 //  ************************************************************************************************
 
 #include "Sample/Aggregate/InterferenceFunctionRadialParaCrystal.h"
-#include "Base/Types/Exceptions.h"
 #include "Param/Base/ParameterPool.h"
 #include "Param/Base/RealParameter.h"
 #include <limits>
@@ -88,9 +87,9 @@ std::vector<const INode*> InterferenceFunctionRadialParaCrystal::getChildren() c
 
 double InterferenceFunctionRadialParaCrystal::iff_without_dw(const kvector_t q) const {
     if (!m_pdf)
-        throw Exceptions::NullPointerException("InterferenceFunctionRadialParaCrystal::"
-                                               "evaluate() -> Error! Probability distribution for "
-                                               "interference function not properly initialized");
+        throw std::runtime_error("InterferenceFunctionRadialParaCrystal::"
+                                 "evaluate() -> Error! Probability distribution for "
+                                 "interference function not properly initialized");
     double result = 0.0;
     double qxr = q.x();
     double qyr = q.y();
diff --git a/Sample/Aggregate/ParticleLayout.cpp b/Sample/Aggregate/ParticleLayout.cpp
index 3bd52a674ba9071f781929bbb828481f9285b79f..664cac9ea39374c4230e9b5c1362676841e5265b 100644
--- a/Sample/Aggregate/ParticleLayout.cpp
+++ b/Sample/Aggregate/ParticleLayout.cpp
@@ -13,7 +13,6 @@
 //  ************************************************************************************************
 
 #include "Sample/Aggregate/ParticleLayout.h"
-#include "Base/Types/Exceptions.h"
 #include "Param/Base/ParameterPool.h"
 #include "Param/Base/RealParameter.h"
 #include "Sample/Aggregate/InterferenceFunctionNone.h"
diff --git a/Sample/Correlations/FTDistributions1D.cpp b/Sample/Correlations/FTDistributions1D.cpp
index 08b2c9c47e7586327905091791641d77b7e48886..0df62f6865b875802103f891096b9cc6e23438ef 100644
--- a/Sample/Correlations/FTDistributions1D.cpp
+++ b/Sample/Correlations/FTDistributions1D.cpp
@@ -15,7 +15,6 @@
 #include "Sample/Correlations/FTDistributions1D.h"
 #include "Base/Math/Constants.h"
 #include "Base/Math/Functions.h"
-#include "Base/Types/Exceptions.h"
 #include <limits>
 
 namespace {
@@ -201,5 +200,5 @@ std::unique_ptr<IDistribution1DSampler> FTDistribution1DVoigt::createSampler() c
     std::ostringstream ostr;
     ostr << "FTDistribution1DVoigt::createSampler() -> Error in class initialization";
     ostr << "\n\n Has not been implemented yet...stay tuned!";
-    throw Exceptions::ClassInitializationException(ostr.str());
+    throw std::runtime_error(ostr.str());
 }
diff --git a/Sample/Correlations/FTDistributions2D.cpp b/Sample/Correlations/FTDistributions2D.cpp
index ba1d270443ce3c5d31aefa96ed5ace36b5f9555d..208e7719007573475b60944c5c727bec1c74b3ca 100644
--- a/Sample/Correlations/FTDistributions2D.cpp
+++ b/Sample/Correlations/FTDistributions2D.cpp
@@ -15,7 +15,6 @@
 #include "Sample/Correlations/FTDistributions2D.h"
 #include "Base/Math/Bessel.h"
 #include "Base/Math/Integrator.h"
-#include "Base/Types/Exceptions.h"
 #include <limits>
 
 //  ************************************************************************************************
@@ -165,5 +164,5 @@ std::unique_ptr<IDistribution2DSampler> FTDistribution2DVoigt::createSampler() c
     std::ostringstream ostr;
     ostr << "FTDistribution2DVoigt::createSampler() -> Error in class initialization";
     ostr << "\n\n Has not been implemented yet...stay tuned!";
-    throw Exceptions::ClassInitializationException(ostr.str());
+    throw std::runtime_error(ostr.str());
 }
diff --git a/Sample/Fresnel/FormFactorCoherentSum.cpp b/Sample/Fresnel/FormFactorCoherentSum.cpp
index 0be1b223b5bf7564f5fa89f72e432c431743434e..1f899a2a8e3aef410f1d42e5ddff2f1c72816a17 100644
--- a/Sample/Fresnel/FormFactorCoherentSum.cpp
+++ b/Sample/Fresnel/FormFactorCoherentSum.cpp
@@ -14,7 +14,6 @@
 
 #include "Sample/Fresnel/FormFactorCoherentSum.h"
 #include "Base/Pixel/SimulationElement.h"
-#include "Base/Types/Exceptions.h"
 
 FormFactorCoherentSum::FormFactorCoherentSum(double abundance) : m_abundance(abundance) {}
 
@@ -38,8 +37,8 @@ Eigen::Matrix2cd FormFactorCoherentSum::evaluatePol(const SimulationElement& sim
 
 void FormFactorCoherentSum::scaleRelativeAbundance(double total_abundance) {
     if (total_abundance <= 0.0)
-        throw Exceptions::LogicErrorException("FormFactorCoherentSum::scaleRelativeAbundance: "
-                                              "Trying to scale with non strictly positive factor.");
+        throw std::runtime_error("FormFactorCoherentSum::scaleRelativeAbundance: "
+                                 "Trying to scale with non strictly positive factor.");
     m_abundance /= total_abundance;
 }
 
diff --git a/Sample/HardParticle/FormFactorAnisoPyramid.cpp b/Sample/HardParticle/FormFactorAnisoPyramid.cpp
index 4081b3884634f2f87400fa97faa0feab1192eed8..1b653dafbce89157cf21556af0150d47cff5f2c5 100644
--- a/Sample/HardParticle/FormFactorAnisoPyramid.cpp
+++ b/Sample/HardParticle/FormFactorAnisoPyramid.cpp
@@ -15,7 +15,6 @@
 #include "Sample/HardParticle/FormFactorAnisoPyramid.h"
 #include "Base/Math/Constants.h"
 #include "Base/Math/Functions.h"
-#include "Base/Types/Exceptions.h"
 
 const PolyhedralTopology FormFactorAnisoPyramid::topology = {{{{3, 2, 1, 0}, true},
                                                               {{0, 1, 5, 4}, false},
@@ -57,7 +56,7 @@ IFormFactor* FormFactorAnisoPyramid::sliceFormFactor(ZLimits limits, const IRota
 void FormFactorAnisoPyramid::onChange() {
     double cot_alpha = Math::cot(m_alpha);
     if (!std::isfinite(cot_alpha) || cot_alpha < 0)
-        throw Exceptions::OutOfBoundsException("AnisoPyramid: angle alpha out of bounds");
+        throw std::runtime_error("AnisoPyramid: angle alpha out of bounds");
     double r = cot_alpha * 2 * m_height / m_length;
     double s = cot_alpha * 2 * m_height / m_width;
     if (r > 1 || s > 1) {
@@ -68,7 +67,7 @@ void FormFactorAnisoPyramid::onChange() {
         ostr << " height:" << m_height;
         ostr << " alpha[rad]:" << m_alpha << "\n\n";
         ostr << "Check for '2*height <= (length,width)*tan(alpha)' failed.";
-        throw Exceptions::ClassInitializationException(ostr.str());
+        throw std::runtime_error(ostr.str());
     }
 
     double D = m_length / 2;
diff --git a/Sample/HardParticle/FormFactorCantellatedCube.cpp b/Sample/HardParticle/FormFactorCantellatedCube.cpp
index 1364302b5e8c8c90d7e531f0a2e40dba6e3bc369..e0ceb2fafcdd7f183a659424293550055c6c0628 100644
--- a/Sample/HardParticle/FormFactorCantellatedCube.cpp
+++ b/Sample/HardParticle/FormFactorCantellatedCube.cpp
@@ -13,7 +13,6 @@
 //  ************************************************************************************************
 
 #include "Sample/HardParticle/FormFactorCantellatedCube.h"
-#include "Base/Types/Exceptions.h"
 
 const PolyhedralTopology FormFactorCantellatedCube::topology = {
     {
@@ -69,7 +68,7 @@ void FormFactorCantellatedCube::onChange() {
         ostr << "with parameters 'length':" << m_length;
         ostr << " 'removed_length':" << m_removed_length << "\n\n";
         ostr << "Check for removed_length <= 0.5*length failed.";
-        throw Exceptions::ClassInitializationException(ostr.str());
+        throw std::runtime_error(ostr.str());
     }
     double a = m_length / 2;
     double b = m_removed_length;
diff --git a/Sample/HardParticle/FormFactorCone.cpp b/Sample/HardParticle/FormFactorCone.cpp
index 2ff6a874e2e75f1a1f5bd34a13af453e505e1796..2e13ab61bba8433838e7367fc3fff9c0970f9a3b 100644
--- a/Sample/HardParticle/FormFactorCone.cpp
+++ b/Sample/HardParticle/FormFactorCone.cpp
@@ -17,7 +17,6 @@
 #include "Base/Math/Constants.h"
 #include "Base/Math/Functions.h"
 #include "Base/Math/Integrator.h"
-#include "Base/Types/Exceptions.h"
 #include "Sample/Shapes/DoubleEllipse.h"
 #include <limits>
 
@@ -33,7 +32,7 @@ FormFactorCone::FormFactorCone(const std::vector<double> P)
     , m_alpha(m_P[2]) {
     m_cot_alpha = Math::cot(m_alpha);
     if (!std::isfinite(m_cot_alpha) || m_cot_alpha < 0)
-        throw Exceptions::OutOfBoundsException("pyramid angle alpha out of bounds");
+        throw std::runtime_error("pyramid angle alpha out of bounds");
     if (m_cot_alpha * m_height > m_radius) {
         std::ostringstream ostr;
         ostr << "FormFactorCone() -> Error in class initialization ";
@@ -41,7 +40,7 @@ FormFactorCone::FormFactorCone(const std::vector<double> P)
         ostr << " m_height:" << m_height;
         ostr << " alpha[rad]:" << m_alpha << "\n\n";
         ostr << "Check for 'height <= radius*tan(alpha)' failed.";
-        throw Exceptions::ClassInitializationException(ostr.str());
+        throw std::runtime_error(ostr.str());
     }
     onChange();
 }
diff --git a/Sample/HardParticle/FormFactorCone6.cpp b/Sample/HardParticle/FormFactorCone6.cpp
index bb17ab17fd66ff90ccaf558148a1760c28c6defd..959849551f1f701d7f25a27f41a666756e836b42 100644
--- a/Sample/HardParticle/FormFactorCone6.cpp
+++ b/Sample/HardParticle/FormFactorCone6.cpp
@@ -15,7 +15,6 @@
 #include "Sample/HardParticle/FormFactorCone6.h"
 #include "Base/Math/Constants.h"
 #include "Base/Math/Functions.h"
-#include "Base/Types/Exceptions.h"
 
 const PolyhedralTopology FormFactorCone6::topology = {{{{5, 4, 3, 2, 1, 0}, true},
                                                        {{0, 1, 7, 6}, false},
@@ -56,7 +55,7 @@ IFormFactor* FormFactorCone6::sliceFormFactor(ZLimits limits, const IRotation& r
 void FormFactorCone6::onChange() {
     double cot_alpha = Math::cot(m_alpha);
     if (!std::isfinite(cot_alpha) || cot_alpha < 0)
-        throw Exceptions::OutOfBoundsException("pyramid angle alpha out of bounds");
+        throw std::runtime_error("pyramid angle alpha out of bounds");
     double r = cot_alpha * 2 / sqrt(3) * m_height / m_base_edge; // L(top)/L(base)
     if (r > 1) {
         std::ostringstream ostr;
@@ -64,7 +63,7 @@ void FormFactorCone6::onChange() {
         ostr << "(base_edge=" << m_base_edge;
         ostr << ", height:" << m_height;
         ostr << ", alpha[rad]:" << m_alpha << ")";
-        throw Exceptions::ClassInitializationException(ostr.str());
+        throw std::runtime_error(ostr.str());
     }
 
     double a = m_base_edge;
diff --git a/Sample/HardParticle/FormFactorCuboctahedron.cpp b/Sample/HardParticle/FormFactorCuboctahedron.cpp
index 0dbf65df380f142744ec880e59d4d1c3e37f7b65..16a329e7ca5fdbbab9c08571246852abe9e99b47 100644
--- a/Sample/HardParticle/FormFactorCuboctahedron.cpp
+++ b/Sample/HardParticle/FormFactorCuboctahedron.cpp
@@ -15,7 +15,6 @@
 #include "Sample/HardParticle/FormFactorCuboctahedron.h"
 #include "Base/Math/Constants.h"
 #include "Base/Math/Functions.h"
-#include "Base/Types/Exceptions.h"
 #include "Sample/HardParticle/FormFactorPyramid.h"
 
 const PolyhedralTopology FormFactorCuboctahedron::topology = {{{{3, 2, 1, 0}, true},
@@ -75,7 +74,7 @@ IFormFactor* FormFactorCuboctahedron::sliceFormFactor(ZLimits limits, const IRot
 void FormFactorCuboctahedron::onChange() {
     double cot_alpha = Math::cot(m_alpha);
     if (!std::isfinite(cot_alpha) || cot_alpha < 0)
-        throw Exceptions::OutOfBoundsException("pyramid angle alpha out of bounds");
+        throw std::runtime_error("pyramid angle alpha out of bounds");
     double x = m_height_ratio;
     double r = cot_alpha * 2 * m_height / m_length;
     if (std::max(1., x) * r > 1) {
@@ -86,7 +85,7 @@ void FormFactorCuboctahedron::onChange() {
         ostr << " height_ratio:" << m_height_ratio;
         ostr << " alpha[rad]:" << m_alpha << "\n\n";
         ostr << "Check for '2.*height <= length*tan(alpha)*min(1.,1.0/height_ratio)' failed.";
-        throw Exceptions::ClassInitializationException(ostr.str());
+        throw std::runtime_error(ostr.str());
     }
 
     double a = m_length / 2 * (1 - r);
diff --git a/Sample/HardParticle/FormFactorHollowSphere.cpp b/Sample/HardParticle/FormFactorHollowSphere.cpp
index df8894bb9c9e0fdd460d4140982c586fa0fb83e6..b8de362a7fceb2b335fc1f7723bb17ca6bf3e0ba 100644
--- a/Sample/HardParticle/FormFactorHollowSphere.cpp
+++ b/Sample/HardParticle/FormFactorHollowSphere.cpp
@@ -14,7 +14,6 @@
 
 #include "Sample/HardParticle/FormFactorHollowSphere.h"
 #include "Base/Math/Constants.h"
-#include "Base/Types/Exceptions.h"
 #include "Sample/Shapes/TruncatedEllipsoid.h"
 #include <limits>
 
@@ -27,9 +26,8 @@ FormFactorHollowSphere::FormFactorHollowSphere(const std::vector<double> P)
     , m_mean(m_P[0])
     , m_full_width(m_P[1]) {
     if (!checkParameters())
-        throw Exceptions::ClassInitializationException(
-            "FormFactorHollowSphere::FormFactorHollowSphere:"
-            " mean radius must be bigger than the half width");
+        throw std::runtime_error("FormFactorHollowSphere::FormFactorHollowSphere:"
+                                 " mean radius must be bigger than the half width");
     onChange();
 }
 
diff --git a/Sample/HardParticle/FormFactorPyramid.cpp b/Sample/HardParticle/FormFactorPyramid.cpp
index febf03f9a3bf551dae5febb460bf868a409c3ef0..c87aff72685b299214ffc4e161842d526378fae2 100644
--- a/Sample/HardParticle/FormFactorPyramid.cpp
+++ b/Sample/HardParticle/FormFactorPyramid.cpp
@@ -15,7 +15,6 @@
 #include "Sample/HardParticle/FormFactorPyramid.h"
 #include "Base/Math/Constants.h"
 #include "Base/Math/Functions.h"
-#include "Base/Types/Exceptions.h"
 
 const PolyhedralTopology FormFactorPyramid::topology = {{
                                                             {{3, 2, 1, 0}, true}, // TODO -> true
@@ -55,7 +54,7 @@ IFormFactor* FormFactorPyramid::sliceFormFactor(ZLimits limits, const IRotation&
 void FormFactorPyramid::onChange() {
     double cot_alpha = Math::cot(m_alpha);
     if (!std::isfinite(cot_alpha))
-        throw Exceptions::OutOfBoundsException("pyramid angle alpha out of bounds");
+        throw std::runtime_error("pyramid angle alpha out of bounds");
     double r = cot_alpha * 2 * m_height / m_base_edge; // [L(base)-L(top)]/L(base)
     if (r > 1) {
         std::ostringstream ostr;
@@ -64,7 +63,7 @@ void FormFactorPyramid::onChange() {
         ostr << " height:" << m_height;
         ostr << " alpha[rad]:" << m_alpha << "\n\n";
         ostr << "Check for 'height <= base_edge*tan(alpha)' failed.";
-        throw Exceptions::ClassInitializationException(ostr.str());
+        throw std::runtime_error(ostr.str());
     }
 
     double a = m_base_edge / 2;
diff --git a/Sample/HardParticle/FormFactorTetrahedron.cpp b/Sample/HardParticle/FormFactorTetrahedron.cpp
index 030e4bb0d6f8b1bc7d9550ea1cf25ebf5b529c8d..eb688ebdda711ffcaba4e18c3475c63224875224 100644
--- a/Sample/HardParticle/FormFactorTetrahedron.cpp
+++ b/Sample/HardParticle/FormFactorTetrahedron.cpp
@@ -15,7 +15,6 @@
 #include "Sample/HardParticle/FormFactorTetrahedron.h"
 #include "Base/Math/Constants.h"
 #include "Base/Math/Functions.h"
-#include "Base/Types/Exceptions.h"
 
 const PolyhedralTopology FormFactorTetrahedron::topology = {{{{2, 1, 0}, false},
                                                              {{0, 1, 4, 3}, false},
@@ -53,7 +52,7 @@ IFormFactor* FormFactorTetrahedron::sliceFormFactor(ZLimits limits, const IRotat
 void FormFactorTetrahedron::onChange() {
     double cot_alpha = Math::cot(m_alpha);
     if (!std::isfinite(cot_alpha) || cot_alpha < 0)
-        throw Exceptions::OutOfBoundsException("pyramid angle alpha out of bounds");
+        throw std::runtime_error("pyramid angle alpha out of bounds");
     double r = cot_alpha * 2 * std::sqrt(3.) * m_height / m_base_edge; // L(top)/L(base)
     if (r > 1) {
         std::ostringstream ostr;
@@ -61,7 +60,7 @@ void FormFactorTetrahedron::onChange() {
         ostr << "(base_edge=" << m_base_edge;
         ostr << ", height:" << m_height;
         ostr << ", alpha[rad]:" << m_alpha << ")";
-        throw Exceptions::ClassInitializationException(ostr.str());
+        throw std::runtime_error(ostr.str());
     }
 
     double a = m_base_edge;
diff --git a/Sample/HardParticle/FormFactorTruncatedCube.cpp b/Sample/HardParticle/FormFactorTruncatedCube.cpp
index 7d55bd80d3548861eb21961e7132a836b835985b..ec5e79f59415b77f4dd8ff0b6af5041445c62701 100644
--- a/Sample/HardParticle/FormFactorTruncatedCube.cpp
+++ b/Sample/HardParticle/FormFactorTruncatedCube.cpp
@@ -13,7 +13,6 @@
 //  ************************************************************************************************
 
 #include "Sample/HardParticle/FormFactorTruncatedCube.h"
-#include "Base/Types/Exceptions.h"
 
 const PolyhedralTopology FormFactorTruncatedCube::topology = {
     {{{0, 1, 7, 6, 9, 10, 4, 3}, true},
@@ -54,7 +53,7 @@ void FormFactorTruncatedCube::onChange() {
         ostr << "with parameters 'length':" << m_length;
         ostr << " 'removed_length':" << m_removed_length << "\n\n";
         ostr << "Check for removed_length <= 0.5*length failed.";
-        throw Exceptions::ClassInitializationException(ostr.str());
+        throw std::runtime_error(ostr.str());
     }
 
     double a = m_length / 2;
diff --git a/Sample/HardParticle/FormFactorTruncatedSphere.cpp b/Sample/HardParticle/FormFactorTruncatedSphere.cpp
index 0d8033c7e385c6a72f9f46d664b3810b89759350..fde3f33a88010b899d996e2a0534d6c55d8cb020 100644
--- a/Sample/HardParticle/FormFactorTruncatedSphere.cpp
+++ b/Sample/HardParticle/FormFactorTruncatedSphere.cpp
@@ -16,7 +16,6 @@
 #include "Base/Math/Bessel.h"
 #include "Base/Math/Constants.h"
 #include "Base/Math/Integrator.h"
-#include "Base/Types/Exceptions.h"
 #include "Sample/Shapes/TruncatedEllipsoid.h"
 #include <limits>
 
@@ -45,7 +44,7 @@ bool FormFactorTruncatedSphere::check_initialization() const {
         ostr << "with parameters 'radius':" << m_radius << " 'height':" << m_height
              << " 'delta_height':" << m_dh << "\n\n";
         ostr << "Check for height <= 2.*radius AND delta_height < height failed.";
-        throw Exceptions::ClassInitializationException(ostr.str());
+        throw std::runtime_error(ostr.str());
     }
     return result;
 }
diff --git a/Sample/HardParticle/FormFactorTruncatedSpheroid.cpp b/Sample/HardParticle/FormFactorTruncatedSpheroid.cpp
index d6627d3f7325236fe4dea8bfef40233749e8fdca..98f8244b5545558261c6ce1c82342f890c97a3b3 100644
--- a/Sample/HardParticle/FormFactorTruncatedSpheroid.cpp
+++ b/Sample/HardParticle/FormFactorTruncatedSpheroid.cpp
@@ -16,7 +16,6 @@
 #include "Base/Math/Bessel.h"
 #include "Base/Math/Constants.h"
 #include "Base/Math/Integrator.h"
-#include "Base/Types/Exceptions.h"
 #include "Sample/Shapes/TruncatedEllipsoid.h"
 #include <limits>
 
@@ -49,7 +48,7 @@ bool FormFactorTruncatedSpheroid::check_initialization() const {
         ostr << " height:" << m_height;
         ostr << " height_flattening:" << m_height_flattening << "\n\n";
         ostr << "Check for 'height <= 2.*radius*height_flattening' failed.";
-        throw Exceptions::ClassInitializationException(ostr.str());
+        throw std::runtime_error(ostr.str());
     }
     return result;
 }
diff --git a/Sample/Interference/DecouplingApproximationStrategy.cpp b/Sample/Interference/DecouplingApproximationStrategy.cpp
index 6d3200eb141dc57117f1a0dfc3f8ff4b3a1417bc..9418dd3c70e48a5762efb58afda2778bd5146ea1 100644
--- a/Sample/Interference/DecouplingApproximationStrategy.cpp
+++ b/Sample/Interference/DecouplingApproximationStrategy.cpp
@@ -15,7 +15,6 @@
 #include "Sample/Interference/DecouplingApproximationStrategy.h"
 #include "Base/Math/Functions.h"
 #include "Base/Pixel/SimulationElement.h"
-#include "Base/Types/Exceptions.h"
 #include "Param/Base/RealParameter.h"
 #include "Sample/Aggregate/InterferenceFunctionNone.h"
 #include "Sample/Fresnel/FormFactorCoherentSum.h"
@@ -38,7 +37,7 @@ DecouplingApproximationStrategy::scalarCalculation(const SimulationElement& sim_
     for (const auto& ffw : m_weighted_formfactors) {
         const complex_t ff = ffw.evaluate(sim_element);
         if (std::isnan(ff.real()))
-            throw Exceptions::RuntimeErrorException(
+            throw std::runtime_error(
                 "DecouplingApproximationStrategy::scalarCalculation() -> Error! Amplitude is NaN");
         double fraction = ffw.relativeAbundance();
         amplitude += fraction * ff;
@@ -59,9 +58,8 @@ DecouplingApproximationStrategy::polarizedCalculation(const SimulationElement& s
     for (const auto& ffw : m_weighted_formfactors) {
         const Eigen::Matrix2cd ff = ffw.evaluatePol(sim_element);
         if (!ff.allFinite())
-            throw Exceptions::RuntimeErrorException(
-                "DecouplingApproximationStrategy::polarizedCalculation() -> "
-                "Error! Form factor contains NaN or infinite");
+            throw std::runtime_error("DecouplingApproximationStrategy::polarizedCalculation() -> "
+                                     "Error! Form factor contains NaN or infinite");
         const double fraction = ffw.relativeAbundance();
         mean_amplitude += fraction * ff;
         mean_intensity += fraction * (ff * polarization_handler.getPolarization() * ff.adjoint());
diff --git a/Sample/Interference/IInterferenceFunctionStrategy.cpp b/Sample/Interference/IInterferenceFunctionStrategy.cpp
index e88799e061467d9363125df9aa5da79db62a3a20..df48316ed5be0778c310e40d72a6557d4db771a3 100644
--- a/Sample/Interference/IInterferenceFunctionStrategy.cpp
+++ b/Sample/Interference/IInterferenceFunctionStrategy.cpp
@@ -15,7 +15,6 @@
 #include "Sample/Interference/IInterferenceFunctionStrategy.h"
 #include "Base/Math/IntegratorMCMiser.h"
 #include "Base/Pixel/SimulationElement.h"
-#include "Base/Types/Exceptions.h"
 #include "Base/Utils/Assert.h"
 #include "Sample/Fresnel/FormFactorCoherentSum.h"
 
diff --git a/Sample/Interference/SSCApproximationStrategy.cpp b/Sample/Interference/SSCApproximationStrategy.cpp
index 08865ac5217c8c1dad10c57e8d1ce173d66e755b..bb1cdb30a1f1a96ef1b8d4c082a077d33ed8c303 100644
--- a/Sample/Interference/SSCApproximationStrategy.cpp
+++ b/Sample/Interference/SSCApproximationStrategy.cpp
@@ -14,7 +14,6 @@
 
 #include "Sample/Interference/SSCApproximationStrategy.h"
 #include "Base/Pixel/SimulationElement.h"
-#include "Base/Types/Exceptions.h"
 #include "Sample/Aggregate/InterferenceFunctionRadialParaCrystal.h"
 #include "Sample/Fresnel/FormFactorCoherentSum.h"
 
diff --git a/Sample/Material/Material.cpp b/Sample/Material/Material.cpp
index 96aef5472e31a0d425f1c5ccb4849fe694264f44..900106cab3a3e88f5436207d95dcd51899cd9bff 100644
--- a/Sample/Material/Material.cpp
+++ b/Sample/Material/Material.cpp
@@ -13,7 +13,6 @@
 //  ************************************************************************************************
 
 #include "Sample/Material/Material.h"
-#include "Base/Types/Exceptions.h"
 #include "Base/Vector/Transform3D.h"
 #include "Sample/Material/WavevectorInfo.h"
 #include <typeinfo>
@@ -23,15 +22,13 @@ Material::Material(std::unique_ptr<BaseMaterialImpl> material_impl)
 
 Material::Material(const Material& material) {
     if (material.isEmpty())
-        throw Exceptions::NullPointerException(
-            "Material: Error! Attempt to initialize material with nullptr.");
+        throw std::runtime_error("Material: Error! Attempt to initialize material with nullptr.");
     m_material_impl.reset(material.m_material_impl->clone());
 }
 
 Material& Material::operator=(const Material& other) {
     if (other.isEmpty())
-        throw Exceptions::NullPointerException(
-            "Material: Error! Attempt to assign nullptr to material.");
+        throw std::runtime_error("Material: Error! Attempt to assign nullptr to material.");
     m_material_impl.reset(other.m_material_impl->clone());
     return *this;
 }
diff --git a/Sample/Multilayer/Layer.cpp b/Sample/Multilayer/Layer.cpp
index 111901edb6b5ae9d892cda8d236ded4ebd73875d..b4ec21466ab2ec553f7b863421abb2a36c27c7ce 100644
--- a/Sample/Multilayer/Layer.cpp
+++ b/Sample/Multilayer/Layer.cpp
@@ -13,7 +13,6 @@
 //  ************************************************************************************************
 
 #include "Sample/Multilayer/Layer.h"
-#include "Base/Types/Exceptions.h"
 #include "Param/Base/ParameterPool.h"
 #include "Param/Base/RealParameter.h"
 #include "Sample/Aggregate/ParticleLayout.h"
@@ -42,7 +41,7 @@ Layer* Layer::clone() const {
 //! Sets layer thickness in nanometers.
 void Layer::setThickness(double thickness) {
     if (thickness < 0.)
-        throw Exceptions::DomainErrorException("Layer thickness cannot be negative");
+        throw std::runtime_error("Layer thickness cannot be negative");
     m_thickness = thickness;
 }
 
diff --git a/Sample/Multilayer/MultiLayer.cpp b/Sample/Multilayer/MultiLayer.cpp
index 1e4d2711c27b4a508352a0041aa65724e4e2b19f..a678bb5c19ba743ae3e81da6b3db975bd5e3233d 100644
--- a/Sample/Multilayer/MultiLayer.cpp
+++ b/Sample/Multilayer/MultiLayer.cpp
@@ -13,7 +13,6 @@
 //  ************************************************************************************************
 
 #include "Sample/Multilayer/MultiLayer.h"
-#include "Base/Types/Exceptions.h"
 #include "Param/Base/ParameterPool.h"
 #include "Param/Base/RealParameter.h"
 #include "Sample/Aggregate/ParticleLayout.h"
@@ -91,7 +90,7 @@ const LayerInterface* MultiLayer::layerInterface(size_t i_interface) const {
 
 void MultiLayer::setCrossCorrLength(double crossCorrLength) {
     if (crossCorrLength < 0.0)
-        throw Exceptions::LogicErrorException("Attempt to set crossCorrLength to negative value");
+        throw std::runtime_error("Attempt to set crossCorrLength to negative value");
     m_crossCorrLength = crossCorrLength;
 }
 
@@ -136,12 +135,12 @@ void MultiLayer::handleLayerThicknessRegistration() {
 
 size_t MultiLayer::check_layer_index(size_t i_layer) const {
     if (i_layer >= m_layers.size())
-        throw Exceptions::OutOfBoundsException("Layer index is out of bounds");
+        throw std::runtime_error("Layer index is out of bounds");
     return i_layer;
 }
 
 size_t MultiLayer::check_interface_index(size_t i_interface) const {
     if (i_interface >= m_interfaces.size())
-        throw Exceptions::OutOfBoundsException("Interface index is out of bounds");
+        throw std::runtime_error("Interface index is out of bounds");
     return i_interface;
 }
diff --git a/Sample/Particle/FormFactorCrystal.cpp b/Sample/Particle/FormFactorCrystal.cpp
index dcea5c98dff3c0f8d0a7a0f1a83cf4b1aa2f9771..b0d9edc0a1bd8bdc240c5b6cdc40faff8cfa4c99 100644
--- a/Sample/Particle/FormFactorCrystal.cpp
+++ b/Sample/Particle/FormFactorCrystal.cpp
@@ -14,7 +14,6 @@
 
 #include "Sample/Particle/FormFactorCrystal.h"
 #include "Base/Math/Constants.h"
-#include "Base/Types/Exceptions.h"
 #include "Sample/Material/WavevectorInfo.h"
 
 FormFactorCrystal::FormFactorCrystal(const Lattice3D& lattice, const IFormFactor& basis_form_factor,
diff --git a/Sample/Particle/ParticleComposition.cpp b/Sample/Particle/ParticleComposition.cpp
index f8feb238334b677837d5f796b1d3245fd695a149..25ad730208e3c744d1287e8e0c8a79f15088c430 100644
--- a/Sample/Particle/ParticleComposition.cpp
+++ b/Sample/Particle/ParticleComposition.cpp
@@ -13,7 +13,6 @@
 //  ************************************************************************************************
 
 #include "Sample/Particle/ParticleComposition.h"
-#include "Base/Types/Exceptions.h"
 #include "Sample/Particle/FormFactorWeighted.h"
 #include "Sample/Particle/ParticleDistribution.h"
 #include "Sample/Scattering/Rotations.h"
@@ -109,7 +108,7 @@ ParticleLimits ParticleComposition::bottomTopZ() const {
 size_t ParticleComposition::check_index(size_t index) const {
     return index < m_particles.size()
                ? index
-               : throw Exceptions::OutOfBoundsException(
+               : throw std::runtime_error(
                    "ParticleComposition::check_index() -> Index is out of bounds");
 }
 
diff --git a/Sample/Particle/ParticleDistribution.cpp b/Sample/Particle/ParticleDistribution.cpp
index 26b79a8fae323bb54dbab9b7750a63840624e503..76c4b7bb6fd7f0ad31a23663f6d8fe6c4e2632e2 100644
--- a/Sample/Particle/ParticleDistribution.cpp
+++ b/Sample/Particle/ParticleDistribution.cpp
@@ -13,7 +13,6 @@
 //  ************************************************************************************************
 
 #include "Sample/Particle/ParticleDistribution.h"
-#include "Base/Types/Exceptions.h"
 #include "Param/Base/ParameterPool.h"
 #include "Param/Base/RealParameter.h"
 #include "Param/Distrib/Distributions.h"
diff --git a/Sample/Processed/MultiLayerFuncs.h b/Sample/Processed/MultiLayerFuncs.h
index 2581f6483ddee45ecd64f959766824c4860ee685..b21d06092c616484e04fcc14476f0cd9a0c567fd 100644
--- a/Sample/Processed/MultiLayerFuncs.h
+++ b/Sample/Processed/MultiLayerFuncs.h
@@ -25,7 +25,7 @@ class MultiLayer;
 
 //! Calculate average material profile for given multilayer
 std::vector<complex_t> materialProfileSLD(const MultiLayer& multilayer, int n_points, double z_min,
-                                       double z_max);
+                                          double z_max);
 
 //! Get default z limits for generating a material profile
 std::pair<double, double> defaultMaterialProfileLimits(const MultiLayer& multilayer);
diff --git a/Sample/RT/ILayerRTCoefficients.h b/Sample/RT/ILayerRTCoefficients.h
index 694778e2d965b5103453f04bcaf5d9c12ac86f77..e3896fb9a9fc400d7a30d04b6c32709b79c7a372 100644
--- a/Sample/RT/ILayerRTCoefficients.h
+++ b/Sample/RT/ILayerRTCoefficients.h
@@ -16,7 +16,6 @@
 #define BORNAGAIN_SAMPLE_RT_ILAYERRTCOEFFICIENTS_H
 
 #include "Base/Types/Complex.h"
-#include "Base/Types/Exceptions.h"
 #include "Base/Vector/EigenCore.h"
 
 //! Interface to access reflection/transmission coefficients.
@@ -45,20 +44,20 @@ public:
     //! be used when the derived object is really scalar
 #endif
     virtual complex_t getScalarT() const {
-        throw Exceptions::NotImplementedException("ILayerRTCoefficients::"
-                                                  "getScalarT(): coefficients are not scalar.");
+        throw std::runtime_error("ILayerRTCoefficients::"
+                                 "getScalarT(): coefficients are not scalar.");
     }
     virtual complex_t getScalarR() const {
-        throw Exceptions::NotImplementedException("ILayerRTCoefficients::"
-                                                  "getScalarR(): coefficients are not scalar.");
+        throw std::runtime_error("ILayerRTCoefficients::"
+                                 "getScalarR(): coefficients are not scalar.");
     }
     virtual complex_t getScalarKz() const {
-        throw Exceptions::NotImplementedException("ILayerRTCoefficients::"
-                                                  "getScalarKz(): coefficients are not scalar.");
+        throw std::runtime_error("ILayerRTCoefficients::"
+                                 "getScalarKz(): coefficients are not scalar.");
     }
 
     virtual Eigen::Matrix2cd getReflectionMatrix() const {
-        throw Exceptions::NotImplementedException("Only defined for Matrix coefficeints");
+        throw std::runtime_error("Only defined for Matrix coefficeints");
     }
 };
 
diff --git a/Sample/Scattering/IBornFF.cpp b/Sample/Scattering/IBornFF.cpp
index 79cb7cc1e60510090c0eb0d0cbd0abe716bd4f62..c4f30394d3dad54e6a8f940faa8b62c3bfc50c6e 100644
--- a/Sample/Scattering/IBornFF.cpp
+++ b/Sample/Scattering/IBornFF.cpp
@@ -13,7 +13,6 @@
 //  ************************************************************************************************
 
 #include "Sample/Scattering/IBornFF.h"
-#include "Base/Types/Exceptions.h"
 #include "Base/Utils/Algorithms.h"
 #include "Sample/Material/WavevectorInfo.h"
 #include "Sample/Scattering/Rotations.h"
diff --git a/Sample/Scattering/ISample.cpp b/Sample/Scattering/ISample.cpp
index 80732eeee4d9c7af4fe13e73770fa1e9bef01567..81a7581b7e0145926f29ab5798f237d66b1d5f8a 100644
--- a/Sample/Scattering/ISample.cpp
+++ b/Sample/Scattering/ISample.cpp
@@ -13,7 +13,6 @@
 //  ************************************************************************************************
 
 #include "Sample/Scattering/ISample.h"
-#include "Base/Types/Exceptions.h"
 #include "Param/Base/ParameterPool.h"
 #include "Sample/Material/Material.h"
 #include <algorithm>
diff --git a/Sample/Slice/LayerInterface.cpp b/Sample/Slice/LayerInterface.cpp
index 07d961b88f051170f628ad231bf1972279d3c8ed..d0310c5b223a12f115a5162f0a932b215551d4f5 100644
--- a/Sample/Slice/LayerInterface.cpp
+++ b/Sample/Slice/LayerInterface.cpp
@@ -13,7 +13,6 @@
 //  ************************************************************************************************
 
 #include "Sample/Slice/LayerInterface.h"
-#include "Base/Types/Exceptions.h"
 #include "Sample/Slice/LayerRoughness.h"
 
 LayerInterface::LayerInterface() : m_topLayer(nullptr), m_bottomLayer(nullptr) {
@@ -23,7 +22,7 @@ LayerInterface::LayerInterface() : m_topLayer(nullptr), m_bottomLayer(nullptr) {
 LayerInterface::~LayerInterface() = default;
 
 LayerInterface* LayerInterface::clone() const {
-    throw Exceptions::NotImplementedException("LayerInterface::clone() -> Not allowed to clone.");
+    throw std::runtime_error("LayerInterface::clone() -> Not allowed to clone.");
 }
 
 LayerInterface* LayerInterface::createSmoothInterface(const Layer* top_layer,
@@ -54,8 +53,8 @@ std::vector<const INode*> LayerInterface::getChildren() const {
 
 void LayerInterface::setLayersTopBottom(const Layer* top_layer, const Layer* bottom_layer) {
     if (top_layer == nullptr || bottom_layer == nullptr)
-        throw Exceptions::RuntimeErrorException("LayerInterface::setLayersTopBottom() -> Error. "
-                                                "Attempt to set nullptr.");
+        throw std::runtime_error("LayerInterface::setLayersTopBottom() -> Error. "
+                                 "Attempt to set nullptr.");
     m_topLayer = top_layer;
     m_bottomLayer = bottom_layer;
 }
diff --git a/Tests/Functional/Core/Std/Check.cpp b/Tests/Functional/Core/Std/Check.cpp
index 0a8a056b840c17a8dede02a8be34c0ba3fbcaa22..5071c320efdca4968eaec8e6beb4d9e8e2d816f2 100644
--- a/Tests/Functional/Core/Std/Check.cpp
+++ b/Tests/Functional/Core/Std/Check.cpp
@@ -35,8 +35,8 @@ bool checkSimulation(const std::string& name, const ISimulation& direct_simulati
     // Load reference if available.
     ASSERT(name != "");
     try {
-        const std::string refPath = FileSystemUtils::jointPath(
-            BATesting::ReferenceDir_Std(), name + ".int.gz");
+        const std::string refPath =
+            FileSystemUtils::jointPath(BATesting::ReferenceDir_Std(), name + ".int.gz");
         std::cout << "- reference: " << refPath << "\n";
         reference.reset(IntensityDataIOFactory::readOutputData(refPath));
     } catch (const std::exception&) {
diff --git a/Tests/Functional/Python/PyEmbedded/Tests.cpp b/Tests/Functional/Python/PyEmbedded/Tests.cpp
index 2ce7b659551ef829e6bb8b3a9f9d7ceaf5ab248a..978d3c8582c4fc3583c241d67da21f9367775a57 100644
--- a/Tests/Functional/Python/PyEmbedded/Tests.cpp
+++ b/Tests/Functional/Python/PyEmbedded/Tests.cpp
@@ -367,15 +367,15 @@ TEST_F(PyEmbedded, ExportToPythonAndBack) {
     std::stringstream snippet;
     snippet << pyfmt::scriptPreamble() << code;
 
-    auto multilayer = PyImport::createFromPython(snippet.str(), pyfmt::getSampleFunctionName(),
-                                                 BABuild::buildLibDir());
+    auto multilayer =
+        PyImport::createFromPython(snippet.str(), "get_sample", BABuild::buildLibDir());
     auto new_code = ExportToPython::generateSampleCode(*multilayer);
 
     EXPECT_TRUE(code == new_code);
 }
 
 //! Retrieves list of functions from the imported script and checks, that there is
-//! one function in a dictioonary with name "get_simulation".
+//! one function in a dictionary with name "get_simulation".
 
 TEST_F(PyEmbedded, ModuleFunctionsList) {
     // compile our function
diff --git a/Tests/Functional/Python/Std/Check.cpp b/Tests/Functional/Python/Std/Check.cpp
index fc372e9db518f188f5ef95ad536aed793ae9a32f..594dddc2d78396ecdd06401afcca9131a08c5a10 100644
--- a/Tests/Functional/Python/Std/Check.cpp
+++ b/Tests/Functional/Python/Std/Check.cpp
@@ -30,13 +30,13 @@ std::unique_ptr<OutputData<double>> domainData(const std::string& test_name,
         FileSystemUtils::jointPath(BATesting::TestOutDir_PyStd(), test_name);
     const std::string output_path = output_name + ".ref.int.gz";
     std::remove(output_path.c_str());
-    std::cout << "- removed old output " << output_path << "\n";
+    std::cout << "- removed old output " << output_path << std::endl;
 
     // Generate Python script
     const std::string pyscript_filename =
         FileSystemUtils::jointPath(BATesting::TestOutDir_PyStd(), test_name + ".py");
     std::ofstream pythonFile(pyscript_filename);
-    pythonFile << ExportToPython::generatePyExportTest(direct_simulation);
+    pythonFile << ExportToPython::generateSimulationCode(direct_simulation);
     pythonFile.close();
 
     // Run Python script
@@ -50,7 +50,7 @@ std::unique_ptr<OutputData<double>> domainData(const std::string& test_name,
                                     + std::string("set NOPLOT=TRUE") + " & \""
                                     + BABuild::pythonExecutable() + "\" -B " + py_command;
 #endif
-    std::cout << "- system call: " << sys_command << std::endl; // note: endl = \n + flush
+    std::cout << "- system call: " << sys_command << std::endl;
     int ret = std::system(sys_command.c_str());
     if (ret != 0) {
         std::stringstream msg;
diff --git a/Tests/README.md b/Tests/README.md
new file mode 100644
index 0000000000000000000000000000000000000000..6e4f9b116c5c806716da77f116162466cb8a2ed3
--- /dev/null
+++ b/Tests/README.md
@@ -0,0 +1,33 @@
+#### BornAgain tests
+
+All tests are under CTest control.
+
+We usually run them with the command
+
+```
+ctest
+```
+
+There is little advantage in running ctest multi-threaded (flag `-j<n>`)
+because each single simulation test uses multi-threading internally.
+
+## How to debug
+
+To find out how CTest is running a specific test, use
+
+```
+ctest -V -N -R <test_name>
+```
+
+The answer typically looks like
+
+```
+<build>/bin/<test_binary> --gtest_filter=<test_name>" <minor_options>
+```
+
+So we start the debugger with
+
+```
+gdb <build>/bin/<test_binary>
+run --gtest_filter=<test_name>
+```
diff --git a/Tests/UnitTests/Core/Axes/FixedBinAxisTest.cpp b/Tests/UnitTests/Core/Axes/FixedBinAxisTest.cpp
index 331f86ee806b4abae04fd992889e4e5010b09e0a..f26ccc155ef49b2b2985b875ed86d41817bb9efe 100644
--- a/Tests/UnitTests/Core/Axes/FixedBinAxisTest.cpp
+++ b/Tests/UnitTests/Core/Axes/FixedBinAxisTest.cpp
@@ -1,5 +1,4 @@
 #include "Base/Axis/FixedBinAxis.h"
-#include "Base/Types/Exceptions.h"
 #include "Device/InputOutput/DataFormatUtils.h"
 #include "Tests/GTestWrapper/google_test.h"
 #include <iostream>
@@ -20,7 +19,7 @@ TEST_F(FixedBinAxisTest, IndexedAccessor) {
     EXPECT_DOUBLE_EQ(-1.0, a2[0]);
     EXPECT_DOUBLE_EQ(0.0, a2[1]);
     EXPECT_DOUBLE_EQ(1.0, a2[2]);
-    ASSERT_THROW(a2[3], Exceptions::OutOfBoundsException);
+    ASSERT_THROW(a2[3], std::runtime_error);
 }
 
 TEST_F(FixedBinAxisTest, VectorOfUnitLength) {
@@ -38,7 +37,7 @@ TEST_F(FixedBinAxisTest, FindClosestIndex) {
     EXPECT_EQ(size_t(0), v1.findClosestIndex(0.25));
     EXPECT_EQ(size_t(1), v1.findClosestIndex(0.5));
     EXPECT_EQ(size_t(1), v1.findClosestIndex(0.6));
-    //    ASSERT_THROW( v1.findClosestIndex(1.0), Exceptions::OutOfBoundsException);
+    //    ASSERT_THROW( v1.findClosestIndex(1.0), std::runtime_error);
     EXPECT_EQ(size_t(1), v1.findClosestIndex(1.0));
 
     FixedBinAxis v2("name", 3, -1.5, 1.5);
@@ -48,7 +47,7 @@ TEST_F(FixedBinAxisTest, FindClosestIndex) {
     EXPECT_EQ(size_t(1), v2.findClosestIndex(0.0));
     EXPECT_EQ(size_t(2), v2.findClosestIndex(0.5));
     EXPECT_EQ(size_t(2), v2.findClosestIndex(1.499));
-    //    ASSERT_THROW( v2.findClosestIndex(1.5), Exceptions::OutOfBoundsException);
+    //    ASSERT_THROW( v2.findClosestIndex(1.5), std::runtime_error);
     EXPECT_EQ(size_t(2), v2.findClosestIndex(1.5));
 }
 
@@ -77,7 +76,7 @@ TEST_F(FixedBinAxisTest, CheckBin) {
     EXPECT_DOUBLE_EQ(9.5, bin19.m_lower);
     EXPECT_DOUBLE_EQ(10.0, bin19.m_upper);
 
-    ASSERT_THROW(axis.bin(20), Exceptions::OutOfBoundsException);
+    ASSERT_THROW(axis.bin(20), std::runtime_error);
 
     FixedBinAxis axis2("name", 3, -1, 2.0);
     EXPECT_DOUBLE_EQ(-0.5, axis2.bin(0).center());
diff --git a/Tests/UnitTests/Core/Axes/Histogram1DTest.cpp b/Tests/UnitTests/Core/Axes/Histogram1DTest.cpp
index 7527ee5c110e24952d09facedcb023d3067843c2..9a7ba52d8ad33fc9a334ee9988b718508e8f20bc 100644
--- a/Tests/UnitTests/Core/Axes/Histogram1DTest.cpp
+++ b/Tests/UnitTests/Core/Axes/Histogram1DTest.cpp
@@ -11,7 +11,7 @@ TEST_F(Histogram1DTest, FixedBinConstructor) {
     EXPECT_EQ(size_t(5), hist.getTotalNumberOfBins());
     EXPECT_EQ(0.0, hist.getXmin());
     EXPECT_EQ(5.0, hist.getXmax());
-    EXPECT_THROW(hist.yAxis(), Exceptions::LogicErrorException);
+    EXPECT_THROW(hist.yAxis(), std::runtime_error);
     for (size_t index = 0; index < hist.getTotalNumberOfBins(); ++index) {
         EXPECT_EQ(index, hist.getGlobalBin(index));
         EXPECT_EQ(index, hist.xAxisIndex(index));
diff --git a/Tests/UnitTests/Core/Axes/VariableBinAxisTest.cpp b/Tests/UnitTests/Core/Axes/VariableBinAxisTest.cpp
index 54f2a966680226252e1d0a200f05755909f178a5..1d128a35b7e456afdf55972b98678c8636f4a232 100644
--- a/Tests/UnitTests/Core/Axes/VariableBinAxisTest.cpp
+++ b/Tests/UnitTests/Core/Axes/VariableBinAxisTest.cpp
@@ -1,5 +1,4 @@
 #include "Base/Axis/VariableBinAxis.h"
-#include "Base/Types/Exceptions.h"
 #include "Device/InputOutput/DataFormatUtils.h"
 #include "Tests/GTestWrapper/google_test.h"
 
@@ -17,17 +16,17 @@ TEST_F(VariableBinAxisTest, VectorOfUnitLength) {
 
 TEST_F(VariableBinAxisTest, ValidityOfCOnstructor) {
     std::vector<double> values;
-    ASSERT_THROW(VariableBinAxis("name", 1, values), Exceptions::LogicErrorException);
+    ASSERT_THROW(VariableBinAxis("name", 1, values), std::runtime_error);
     values.resize(5);
-    ASSERT_THROW(VariableBinAxis("name", 5, values), Exceptions::LogicErrorException);
+    ASSERT_THROW(VariableBinAxis("name", 5, values), std::runtime_error);
 
     static const double arr1[] = {-1.5, -1.5, 0.5, 1.5};
     std::vector<double> v1(arr1, arr1 + sizeof(arr1) / sizeof(arr1[0]));
-    ASSERT_THROW(VariableBinAxis("name", 3, v1), Exceptions::LogicErrorException);
+    ASSERT_THROW(VariableBinAxis("name", 3, v1), std::runtime_error);
 
     static const double arr2[] = {1.5, -0.5, 0.5, -1.5};
     std::vector<double> v2(arr2, arr2 + sizeof(arr2) / sizeof(arr2[0]));
-    ASSERT_THROW(VariableBinAxis("name", 3, v2), Exceptions::LogicErrorException);
+    ASSERT_THROW(VariableBinAxis("name", 3, v2), std::runtime_error);
 }
 
 TEST_F(VariableBinAxisTest, IndexedAccessor) {
@@ -57,7 +56,7 @@ TEST_F(VariableBinAxisTest, IndexedAccessor) {
     EXPECT_DOUBLE_EQ(-1.0, a2[0]);
     EXPECT_DOUBLE_EQ(0.0, a2[1]);
     EXPECT_DOUBLE_EQ(1.0, a2[2]);
-    ASSERT_THROW(a2[3], Exceptions::OutOfBoundsException);
+    ASSERT_THROW(a2[3], std::runtime_error);
 }
 
 TEST_F(VariableBinAxisTest, FindClosestIndex) {
@@ -70,7 +69,7 @@ TEST_F(VariableBinAxisTest, FindClosestIndex) {
     EXPECT_EQ(size_t(0), v1.findClosestIndex(0.25));
     EXPECT_EQ(size_t(1), v1.findClosestIndex(0.5));
     EXPECT_EQ(size_t(1), v1.findClosestIndex(0.6));
-    //    ASSERT_THROW( v1.findClosestIndex(1.0), Exceptions::OutOfBoundsException);
+    //    ASSERT_THROW( v1.findClosestIndex(1.0), std::runtime_error);
     EXPECT_EQ(size_t(1), v1.findClosestIndex(1.0));
 
     static const double arr2[] = {-1.5, -0.5, 0.5, 1.5};
@@ -82,7 +81,7 @@ TEST_F(VariableBinAxisTest, FindClosestIndex) {
     EXPECT_EQ(size_t(1), v2.findClosestIndex(0.0));
     EXPECT_EQ(size_t(2), v2.findClosestIndex(0.5));
     EXPECT_EQ(size_t(2), v2.findClosestIndex(1.499));
-    //    ASSERT_THROW( v2.findClosestIndex(1.5), Exceptions::OutOfBoundsException);
+    //    ASSERT_THROW( v2.findClosestIndex(1.5), std::runtime_error);
     EXPECT_EQ(size_t(2), v2.findClosestIndex(1.5));
 
     static const double arr3[] = {-1.0, -0.5, 0.5, 1.0, 2.0};
diff --git a/Tests/UnitTests/Core/DataStructure/LLDataTest.cpp b/Tests/UnitTests/Core/DataStructure/LLDataTest.cpp
index f675e6ab002bf250fcd13b4595a86b24642ad23d..23432bfd51e1eadb984fc74f8ee73bf31db8420b 100644
--- a/Tests/UnitTests/Core/DataStructure/LLDataTest.cpp
+++ b/Tests/UnitTests/Core/DataStructure/LLDataTest.cpp
@@ -160,7 +160,7 @@ TEST_F(LLDataTest, Addition) {
     LLData<float>* fl_data_1d2 = new LLData<float>(1u, odim1);
     fl_data_1d2->setAll(10.0);
 
-    EXPECT_THROW((*fl_data_1d) += (*fl_data_1d2), Exceptions::RuntimeErrorException);
+    EXPECT_THROW((*fl_data_1d) += (*fl_data_1d2), std::runtime_error);
 
     LLData<Eigen::Matrix2d>* other_matrix_data_2d = new LLData<Eigen::Matrix2d>(*matrix_data_2d);
     matrix_data_2d->setAll(Eigen::Matrix2d::Identity());
@@ -198,7 +198,7 @@ TEST_F(LLDataTest, Substraction) {
     LLData<float>* fl_data_1d2 = new LLData<float>(1u, odim1);
     fl_data_1d2->setAll(10.0);
 
-    EXPECT_THROW((*fl_data_1d) -= (*fl_data_1d2), Exceptions::RuntimeErrorException);
+    EXPECT_THROW((*fl_data_1d) -= (*fl_data_1d2), std::runtime_error);
 
     LLData<Eigen::Matrix2d>* other_matrix_data_2d = new LLData<Eigen::Matrix2d>(*matrix_data_2d);
     matrix_data_2d->setAll(Eigen::Matrix2d::Identity());
@@ -235,7 +235,7 @@ TEST_F(LLDataTest, Multiplication) {
     LLData<float>* fl_data_1d2 = new LLData<float>(1u, odim1);
     fl_data_1d2->setAll(10.0);
 
-    EXPECT_THROW((*fl_data_1d) *= (*fl_data_1d2), Exceptions::RuntimeErrorException);
+    EXPECT_THROW((*fl_data_1d) *= (*fl_data_1d2), std::runtime_error);
 
     LLData<Eigen::Matrix2d>* other_matrix_data_2d = new LLData<Eigen::Matrix2d>(*matrix_data_2d);
     matrix_data_2d->setAll(2 * Eigen::Matrix2d::Identity());
@@ -272,7 +272,7 @@ TEST_F(LLDataTest, Division) {
     LLData<float>* fl_data_1d2 = new LLData<float>(1u, odim1);
     fl_data_1d2->setAll(10.0);
 
-    EXPECT_THROW((*fl_data_1d) /= (*fl_data_1d2), Exceptions::RuntimeErrorException);
+    EXPECT_THROW((*fl_data_1d) /= (*fl_data_1d2), std::runtime_error);
 
     delete fl_data_1d2;
     delete[] odim1;
diff --git a/Tests/UnitTests/Core/Detector/RectangularDetectorTest.cpp b/Tests/UnitTests/Core/Detector/RectangularDetectorTest.cpp
index 95a89252aac5e274acd9d6abddfc60abb9d43801..e4ca458b924273703a63e68d5bf93f45dd15e5c5 100644
--- a/Tests/UnitTests/Core/Detector/RectangularDetectorTest.cpp
+++ b/Tests/UnitTests/Core/Detector/RectangularDetectorTest.cpp
@@ -260,7 +260,7 @@ TEST_F(RectangularDetectorTest, AnalyzerProperties) {
 
     // if direction is the zero vector, an exception is thrown
     EXPECT_THROW(detector.setAnalyzerProperties(direction, efficiency, total_transmission),
-                 Exceptions::ClassInitializationException);
+                 std::runtime_error);
 
     // zero efficiency
     direction = kvector_t(1.0, 0.0, 0.0);
diff --git a/Tests/UnitTests/Core/Detector/RegionOfInterestTest.cpp b/Tests/UnitTests/Core/Detector/RegionOfInterestTest.cpp
index 0735b45dd626630e1273553e0ce72351dd1d7317..88f509c452777fe2d48b6ac305027c6c80bc338b 100644
--- a/Tests/UnitTests/Core/Detector/RegionOfInterestTest.cpp
+++ b/Tests/UnitTests/Core/Detector/RegionOfInterestTest.cpp
@@ -30,7 +30,7 @@ TEST_F(RegionOfInterestTest, constructor) {
     EXPECT_EQ(roi.roiIndex(9), 2u);
     EXPECT_EQ(roi.roiIndex(21), 8u);
     EXPECT_EQ(roi.roiIndex(22), 9u);
-    EXPECT_THROW(roi.roiIndex(23), Exceptions::RuntimeErrorException);
+    EXPECT_THROW(roi.roiIndex(23), std::runtime_error);
 
     // converting local ro index to global detector index
     EXPECT_EQ(roi.detectorIndex(0), 5u);
@@ -93,7 +93,7 @@ TEST_F(RegionOfInterestTest, clone) {
     EXPECT_EQ(clone->roiIndex(9), 2u);
     EXPECT_EQ(clone->roiIndex(21), 8u);
     EXPECT_EQ(clone->roiIndex(22), 9u);
-    EXPECT_THROW(clone->roiIndex(23), Exceptions::RuntimeErrorException);
+    EXPECT_THROW(clone->roiIndex(23), std::runtime_error);
 
     // converting local ro index to global detector index
     EXPECT_EQ(clone->detectorIndex(0), 5u);
diff --git a/Tests/UnitTests/Core/Detector/SphericalDetectorTest.cpp b/Tests/UnitTests/Core/Detector/SphericalDetectorTest.cpp
index 16abd26e79cb2ca809f3fd89cf4d8e8d8e1814ad..c01f6fa780b8f43eb77d809b0042dc674f1e1ae4 100644
--- a/Tests/UnitTests/Core/Detector/SphericalDetectorTest.cpp
+++ b/Tests/UnitTests/Core/Detector/SphericalDetectorTest.cpp
@@ -221,7 +221,7 @@ TEST_F(SphericalDetectorTest, AnalyzerProperties) {
 
     // if direction is the zero vector, an exception is thrown
     EXPECT_THROW(detector.setAnalyzerProperties(direction, efficiency, total_transmission),
-                 Exceptions::ClassInitializationException);
+                 std::runtime_error);
 
     // zero efficiency
     direction = kvector_t(1.0, 0.0, 0.0);
diff --git a/Tests/UnitTests/Core/ExportToPython/PythonFormattingTest.cpp b/Tests/UnitTests/Core/ExportToPython/PythonFormattingTest.cpp
index e62fa353bd655f840ad5bab3a3bbe349b0d34f43..71b7fc2f2367d1690e986359ff1a25996eb41622 100644
--- a/Tests/UnitTests/Core/ExportToPython/PythonFormattingTest.cpp
+++ b/Tests/UnitTests/Core/ExportToPython/PythonFormattingTest.cpp
@@ -2,10 +2,10 @@
 #include "Base/Axis/PointwiseAxis.h"
 #include "Base/Const/Units.h"
 #include "Base/Utils/PyFmt.h"
-#include "Device/Instrument/PyFmt2.h"
+#include "Core/Export/PyFmt2.h"
+#include "Core/Export/PyFmtLimits.h"
 #include "Param/Distrib/Distributions.h"
 #include "Param/Distrib/ParameterDistribution.h"
-#include "Param/Varia/PyFmtLimits.h"
 #include "Tests/GTestWrapper/google_test.h"
 
 class PythonFormattingTest : public ::testing::Test {};
diff --git a/Tests/UnitTests/Core/Other/MaterialTest.cpp b/Tests/UnitTests/Core/Other/MaterialTest.cpp
index fd27aeb37895f576db6a6e31390e5f849d5b73e5..51048ec42eed5aed4ad1f1878953f31930ba754a 100644
--- a/Tests/UnitTests/Core/Other/MaterialTest.cpp
+++ b/Tests/UnitTests/Core/Other/MaterialTest.cpp
@@ -1,5 +1,4 @@
 #include "Base/Const/Units.h"
-#include "Base/Types/Exceptions.h"
 #include "Base/Vector/Transform3D.h"
 #include "Sample/Material/MaterialBySLDImpl.h"
 #include "Sample/Material/RefractiveMaterialImpl.h"
diff --git a/Tests/UnitTests/Core/Parameters/DistributionsTest.cpp b/Tests/UnitTests/Core/Parameters/DistributionsTest.cpp
index a04db0f30dc5dce312c45fa92dbe70301c304d43..d08f92f3e9486c2c820c7a6ca9a3aadcc3f0b584 100644
--- a/Tests/UnitTests/Core/Parameters/DistributionsTest.cpp
+++ b/Tests/UnitTests/Core/Parameters/DistributionsTest.cpp
@@ -1,6 +1,5 @@
 #include "Param/Distrib/Distributions.h"
 #include "Base/Math/Constants.h"
-#include "Base/Types/Exceptions.h"
 #include "Param/Base/RealParameter.h"
 #include "Param/Varia/ParameterSample.h"
 #include "Tests/GTestWrapper/google_test.h"
@@ -29,7 +28,7 @@ TEST_F(DistributionsTest, DistributionGateDefaultConstructor) {
 
 TEST_F(DistributionsTest, DistributionGateConstructor) {
     // Throw error when m_min > m_max:
-    EXPECT_THROW(DistributionGate(1.1, 1.0), Exceptions::ClassInitializationException);
+    EXPECT_THROW(DistributionGate(1.1, 1.0), std::runtime_error);
 
     // When m_min == m_max, only one sample is generated (the mean):
     DistributionGate distr1(1.0, 1.0);
diff --git a/Tests/UnitTests/Core/Parameters/ParameterDistributionTest.cpp b/Tests/UnitTests/Core/Parameters/ParameterDistributionTest.cpp
index afe6941162dab09bd0510c6ea8d6094ca9d1aed4..0b9c6bf21f0d8353684d0f15e25a664fbfe16bb0 100644
--- a/Tests/UnitTests/Core/Parameters/ParameterDistributionTest.cpp
+++ b/Tests/UnitTests/Core/Parameters/ParameterDistributionTest.cpp
@@ -1,5 +1,4 @@
 #include "Param/Distrib/ParameterDistribution.h"
-#include "Base/Types/Exceptions.h"
 #include "Param/Distrib/Distributions.h"
 #include "Param/Varia/ParameterUtils.h"
 #include "Tests/GTestWrapper/google_test.h"
@@ -10,9 +9,8 @@ class ParameterDistributionTest : public ::testing::Test {};
 TEST_F(ParameterDistributionTest, ParameterDistributionConstructor) {
     std::string name = "MainParameterName";
     DistributionGate distribution(1.0, 2.0);
-    EXPECT_THROW(ParameterDistribution(name, distribution, 1, -1.0),
-                 Exceptions::RuntimeErrorException);
-    EXPECT_THROW(ParameterDistribution(name, distribution, 0), Exceptions::RuntimeErrorException);
+    EXPECT_THROW(ParameterDistribution(name, distribution, 1, -1.0), std::runtime_error);
+    EXPECT_THROW(ParameterDistribution(name, distribution, 0), std::runtime_error);
 
     // Sigma constructor
     ParameterDistribution pardistr(name, distribution, 1);
diff --git a/Tests/UnitTests/Core/Parameters/ParameterPoolTest.cpp b/Tests/UnitTests/Core/Parameters/ParameterPoolTest.cpp
index 83ea71f1442d6873d6193ee8ccf53e404834fe66..2a68eb0b224dd8e1e41b5ddfc10893c15fe711b9 100644
--- a/Tests/UnitTests/Core/Parameters/ParameterPoolTest.cpp
+++ b/Tests/UnitTests/Core/Parameters/ParameterPoolTest.cpp
@@ -1,5 +1,4 @@
 #include "Param/Base/ParameterPool.h"
-#include "Base/Types/Exceptions.h"
 #include "Param/Base/RealParameter.h"
 #include "Tests/GTestWrapper/google_test.h"
 
@@ -22,7 +21,7 @@ TEST_F(ParameterPoolTest, addParameter) {
     EXPECT_EQ(pool.size(), 2u);
 
     // attempt to add same parameter twice
-    EXPECT_THROW(pool.addParameter(rp1), Exceptions::RuntimeErrorException);
+    EXPECT_THROW(pool.addParameter(rp1), std::runtime_error);
 
     // getting parameters
     EXPECT_EQ(pool.parameter("rp1"), rp1);
@@ -58,7 +57,7 @@ TEST_F(ParameterPoolTest, matchedParameters) {
 
     // unique match
     EXPECT_EQ(rp2, pool.getUniqueMatch("*xxx*"));
-    EXPECT_THROW(pool.getUniqueMatch("*par*"), Exceptions::RuntimeErrorException);
+    EXPECT_THROW(pool.getUniqueMatch("*par*"), std::runtime_error);
 }
 
 TEST_F(ParameterPoolTest, setValue) {
@@ -72,20 +71,18 @@ TEST_F(ParameterPoolTest, setValue) {
     // set single parameter value
     pool.setParameterValue("par1", 10.0);
     EXPECT_EQ(par1, 10.0);
-    EXPECT_THROW(pool.setParameterValue("non-existing", 10.0), Exceptions::RuntimeErrorException);
+    EXPECT_THROW(pool.setParameterValue("non-existing", 10.0), std::runtime_error);
 
     // set matched parameter values
     EXPECT_EQ(pool.setMatchedParametersValue("*par*", 99.0), 2);
     EXPECT_EQ(par1, 99.0);
     EXPECT_EQ(par3, 99.0);
-    EXPECT_THROW(pool.setMatchedParametersValue("*non-existing*", 10.0),
-                 Exceptions::RuntimeErrorException);
+    EXPECT_THROW(pool.setMatchedParametersValue("*non-existing*", 10.0), std::runtime_error);
 
     // set unique match value
     pool.setUniqueMatchValue("*xxx*", 88.0);
     EXPECT_EQ(par2, 88.0);
-    EXPECT_THROW(pool.setUniqueMatchValue("*non-existing*", 10.0),
-                 Exceptions::RuntimeErrorException);
+    EXPECT_THROW(pool.setUniqueMatchValue("*non-existing*", 10.0), std::runtime_error);
 }
 
 TEST_F(ParameterPoolTest, clone) {
diff --git a/Tests/UnitTests/Core/Parameters/RangedDistributionTest.cpp b/Tests/UnitTests/Core/Parameters/RangedDistributionTest.cpp
index b176eb50da052ba0c055465e9df0cd4f13ffde0c..00fe10600536724569dca1a7e3e58cb23965517b 100644
--- a/Tests/UnitTests/Core/Parameters/RangedDistributionTest.cpp
+++ b/Tests/UnitTests/Core/Parameters/RangedDistributionTest.cpp
@@ -5,7 +5,7 @@
 
 class RangedDistributionTest : public ::testing::Test {
 protected:
-    void checkDefaults(const RangedDistribution& distr);
+    void checkDefaults(const IRangedDistribution& distr);
 
     template <class T> void checkThrows();
 
@@ -16,7 +16,7 @@ protected:
     template <class T> void checkZeroWidth();
 };
 
-void RangedDistributionTest::checkDefaults(const RangedDistribution& distr) {
+void RangedDistributionTest::checkDefaults(const IRangedDistribution& distr) {
     EXPECT_EQ(distr.nSamples(), 5u);
     EXPECT_EQ(distr.sigmaFactor(), 2.0);
     EXPECT_EQ(distr.limits(), RealLimits::limitless());
@@ -65,21 +65,6 @@ template <class T> void RangedDistributionTest::checkStandardSampling() {
     EXPECT_EQ(samples_2.size(), 3u);
 }
 
-template <class T> void RangedDistributionTest::checkPrinting(std::string expected_name) {
-    T distr(3, 1.0);
-    std::stringstream print_ref;
-    print_ref << "    distribution = ba." << expected_name << "(3, 1.0)";
-    std::string actual = distr.pyString();
-    EXPECT_EQ(print_ref.str(), actual);
-
-    T distr2(3, 1.0, 1.0, 2.0);
-    std::stringstream print_ref2;
-    print_ref2 << "    distribution = ba." << expected_name
-               << "(3, 1.0, ba.RealLimits.limited(1.0, 2.0))";
-    actual = distr2.pyString();
-    EXPECT_EQ(print_ref2.str(), actual);
-}
-
 template <class T> void RangedDistributionTest::checkZeroWidth() {
     T distr(/*n_samples = */ 10, /*sigma_factor = */ 3.0);
     const std::vector<ParameterSample>& samples = distr.generateSamples(1.0, 0.0);
@@ -107,7 +92,6 @@ TEST_F(RangedDistributionTest, GateDistribution) {
     checkDefaults(RangedDistributionGate());
     checkThrows<RangedDistributionGate>();
     checkStandardSampling<RangedDistributionGate>();
-    checkPrinting<RangedDistributionGate>("RangedDistributionGate");
     checkZeroWidth<RangedDistributionGate>();
 }
 
@@ -115,7 +99,6 @@ TEST_F(RangedDistributionTest, LorentzDistribution) {
     checkDefaults(RangedDistributionLorentz());
     checkThrows<RangedDistributionLorentz>();
     checkStandardSampling<RangedDistributionLorentz>();
-    checkPrinting<RangedDistributionLorentz>("RangedDistributionLorentz");
     checkZeroWidth<RangedDistributionLorentz>();
 }
 
@@ -123,7 +106,6 @@ TEST_F(RangedDistributionTest, GaussianDistribution) {
     checkDefaults(RangedDistributionGaussian());
     checkThrows<RangedDistributionGaussian>();
     checkStandardSampling<RangedDistributionGaussian>();
-    checkPrinting<RangedDistributionGaussian>("RangedDistributionGaussian");
     checkZeroWidth<RangedDistributionGaussian>();
 }
 
@@ -131,7 +113,6 @@ TEST_F(RangedDistributionTest, LogNormalDistribution) {
     checkDefaults(RangedDistributionLogNormal());
     checkThrows<RangedDistributionLogNormal>();
     checkStandardSampling<RangedDistributionLogNormal>();
-    checkPrinting<RangedDistributionLogNormal>("RangedDistributionLogNormal");
     checkZeroWidth<RangedDistributionLogNormal>();
 
     RangedDistributionLogNormal log_norm;
@@ -142,6 +123,5 @@ TEST_F(RangedDistributionTest, CosineDistribution) {
     checkDefaults(RangedDistributionCosine());
     checkThrows<RangedDistributionCosine>();
     checkStandardSampling<RangedDistributionCosine>();
-    checkPrinting<RangedDistributionCosine>("RangedDistributionCosine");
     checkZeroWidth<RangedDistributionCosine>();
 }
diff --git a/Tests/UnitTests/Core/Parameters/ScanResolutionTest.cpp b/Tests/UnitTests/Core/Parameters/ScanResolutionTest.cpp
index c9d169bd52589840543df5cc14186fc441bed422..03aec40750ff384bbec8066004e5c9851963f2b1 100644
--- a/Tests/UnitTests/Core/Parameters/ScanResolutionTest.cpp
+++ b/Tests/UnitTests/Core/Parameters/ScanResolutionTest.cpp
@@ -34,10 +34,6 @@ TEST_F(ScanResolutionTest, RelativeSingleValued) {
     actual = resolution->generateSamples(1.0, 3);
     compareResults(ref_result, actual);
 
-    std::stringstream print_ref;
-    print_ref << "    distribution = ba.RangedDistributionGate(3, 1.0)\n"
-              << "    resolution = ba.ScanRelativeResolution(distribution, 0.1)";
-    EXPECT_EQ(print_ref.str(), resolution->print());
     EXPECT_THROW(resolution->generateSamples(std::vector<double>()), std::runtime_error);
 }
 
@@ -55,10 +51,6 @@ TEST_F(ScanResolutionTest, AbsoluteSingleValued) {
     actual = resolution->generateSamples(1.0, 3);
     compareResults(ref_result, actual);
 
-    std::stringstream print_ref;
-    print_ref << "    distribution = ba.RangedDistributionGate(3, 1.0)\n"
-              << "    resolution = ba.ScanAbsoluteResolution(distribution, 0.1)";
-    EXPECT_EQ(print_ref.str(), resolution->print());
     EXPECT_THROW(resolution->generateSamples(std::vector<double>()), std::runtime_error);
 }
 
@@ -81,7 +73,6 @@ TEST_F(ScanResolutionTest, RelativeVectorValued) {
     actual = resolution->generateSamples(1.0, 3);
     compareResults(ref_result, actual);
 
-    EXPECT_THROW(resolution->print(), std::runtime_error);
     EXPECT_THROW(resolution->generateSamples(std::vector<double>()), std::runtime_error);
     EXPECT_THROW(resolution->generateSamples(std::vector<double>(2, 1.0)), std::runtime_error);
     EXPECT_THROW(resolution->generateSamples(std::vector<double>(10, 1.0)), std::runtime_error);
@@ -106,7 +97,6 @@ TEST_F(ScanResolutionTest, AbsoluteVectorValued) {
     actual = resolution->generateSamples(1.0, 3);
     compareResults(ref_result, actual);
 
-    EXPECT_THROW(resolution->print(), std::runtime_error);
     EXPECT_THROW(resolution->generateSamples(std::vector<double>()), std::runtime_error);
     EXPECT_THROW(resolution->generateSamples(std::vector<double>(2, 1.0)), std::runtime_error);
     EXPECT_THROW(resolution->generateSamples(std::vector<double>(10, 1.0)), std::runtime_error);
diff --git a/Tests/UnitTests/Core/Sample/FormFactorCoherentSumTest.cpp b/Tests/UnitTests/Core/Sample/FormFactorCoherentSumTest.cpp
index 5e58f3e344a793d2e13d2a1032a5e754f6c72b66..40b34823cbcc03664b5daaa72ba2dca5d671084e 100644
--- a/Tests/UnitTests/Core/Sample/FormFactorCoherentSumTest.cpp
+++ b/Tests/UnitTests/Core/Sample/FormFactorCoherentSumTest.cpp
@@ -1,5 +1,4 @@
 #include "Sample/Fresnel/FormFactorCoherentSum.h"
-#include "Base/Types/Exceptions.h"
 #include "Sample/FFCompute/ComputeBA.h"
 #include "Sample/HardParticle/FormFactorDot.h"
 #include "Tests/GTestWrapper/google_test.h"
@@ -16,6 +15,6 @@ TEST_F(FormFactorCoherentSumTest, RelAbundance) {
     EXPECT_EQ(0.0, ffw.radialExtension());
     ffw.scaleRelativeAbundance(2.0);
     EXPECT_NEAR(0.5, ffw.relativeAbundance(), epsilon);
-    EXPECT_THROW(ffw.scaleRelativeAbundance(0.0), Exceptions::LogicErrorException);
+    EXPECT_THROW(ffw.scaleRelativeAbundance(0.0), std::runtime_error);
     EXPECT_EQ(0.0, ffw.radialExtension());
 }
diff --git a/Tests/UnitTests/Core/Sample/INodeTest.cpp b/Tests/UnitTests/Core/Sample/INodeTest.cpp
index eb2a96c070e6be1a109a9a1f5fafea9f64381ae6..c7982dde963f83095380954781dc4f355f871615 100644
--- a/Tests/UnitTests/Core/Sample/INodeTest.cpp
+++ b/Tests/UnitTests/Core/Sample/INodeTest.cpp
@@ -1,5 +1,4 @@
 #include "Param/Node/INode.h"
-#include "Base/Types/Exceptions.h"
 #include "Param/Base/ParameterPool.h"
 #include "Param/Base/RealParameter.h"
 #include "Param/Node/NodeUtils.h"
@@ -122,7 +121,7 @@ TEST_F(INodeTest, nodePath) {
     EXPECT_EQ(NodeUtils::nodePath(*grandchild, child0), "/grandchild");
 
     // Check if exception is thrown when grandchild doesn't belong to child's branch
-    EXPECT_THROW(NodeUtils::nodePath(*grandchild, child1), Exceptions::RuntimeErrorException);
+    EXPECT_THROW(NodeUtils::nodePath(*grandchild, child1), std::runtime_error);
 }
 
 //! Checking parameter tree for INode structure.
diff --git a/Wrap/swig/libBornAgainDevice.i b/Wrap/swig/libBornAgainDevice.i
index f03e463da12b492e5dc83b28dc51c317cf855d09..4d53072ab788da0e87219e489118782e74cc8457 100644
--- a/Wrap/swig/libBornAgainDevice.i
+++ b/Wrap/swig/libBornAgainDevice.i
@@ -159,7 +159,7 @@
         Creates a scan resolution from the given distribution and
         relative deviation values (that is, the ratios of standard
         deviations and means).
-        :param distribution: bornagain.RangedDistribution object
+        :param distribution: bornagain.IRangedDistribution object
         :param rel_dev: either single-valued or a numpy array.
                         In the latter case should coinside in
                         size with later used mean values array.
@@ -171,7 +171,7 @@
         """
         Creates a scan resolution from the given distribution and
         standard deviation values.
-        :param distribution: bornagain.RangedDistribution object
+        :param distribution: bornagain.IRangedDistribution object
         :param std_dev: either single-valued or a numpy array.
                         In the latter case should coinside in
                         size with later used mean values array.
diff --git a/Wrap/swig/libBornAgainParam.i b/Wrap/swig/libBornAgainParam.i
index e62a62dc7338ae65b7942f5328064d87861885b7..a0232e2fda8dc4710aac518af8152783225a5105 100644
--- a/Wrap/swig/libBornAgainParam.i
+++ b/Wrap/swig/libBornAgainParam.i
@@ -50,7 +50,7 @@
 
 %ignore IParameterized::addParametersToExternalPool(const std::string&, ParameterPool*, int) const;
 %ignore IParameterized::addParametersToExternalPool(const std::string&, ParameterPool*) const;
-%ignore RangedDistribution;
+%ignore IRangedDistribution;
 
 %template(swig_dummy_type_inode_vector) std::vector<INode*>;
 %template(swig_dummy_type_const_inode_vector) std::vector<const INode*>;
diff --git a/auto/Wrap/doxygenBase.i b/auto/Wrap/doxygenBase.i
index e7af05b5a5dc508e8ea370bb7f1d0295f5bc17c7..39a6eaf65d873c066f26d000314c5f21c1197684 100644
--- a/auto/Wrap/doxygenBase.i
+++ b/auto/Wrap/doxygenBase.i
@@ -240,13 +240,6 @@ C++ includes: IntegratorMCMiser.h
 ";
 
 
-// File: classExceptions_1_1ClassInitializationException.xml
-%feature("docstring") Exceptions::ClassInitializationException "";
-
-%feature("docstring")  Exceptions::ClassInitializationException::ClassInitializationException "Exceptions::ClassInitializationException::ClassInitializationException(const std::string &message)
-";
-
-
 // File: classCloneableVector.xml
 %feature("docstring") CloneableVector "
 
@@ -396,27 +389,6 @@ Increments inner counter; at regular intervals updates progress handler.
 ";
 
 
-// File: classExceptions_1_1DomainErrorException.xml
-%feature("docstring") Exceptions::DomainErrorException "";
-
-%feature("docstring")  Exceptions::DomainErrorException::DomainErrorException "Exceptions::DomainErrorException::DomainErrorException(const std::string &message)
-";
-
-
-// File: classExceptions_1_1FileIsBadException.xml
-%feature("docstring") Exceptions::FileIsBadException "";
-
-%feature("docstring")  Exceptions::FileIsBadException::FileIsBadException "Exceptions::FileIsBadException::FileIsBadException(const std::string &message)
-";
-
-
-// File: classExceptions_1_1FileNotIsOpenException.xml
-%feature("docstring") Exceptions::FileNotIsOpenException "";
-
-%feature("docstring")  Exceptions::FileNotIsOpenException::FileNotIsOpenException "Exceptions::FileNotIsOpenException::FileNotIsOpenException(const std::string &message)
-";
-
-
 // File: classFixedBinAxis.xml
 %feature("docstring") FixedBinAxis "
 
@@ -496,13 +468,6 @@ Creates a new clipped axis.
 ";
 
 
-// File: classExceptions_1_1FormatErrorException.xml
-%feature("docstring") Exceptions::FormatErrorException "";
-
-%feature("docstring")  Exceptions::FormatErrorException::FormatErrorException "Exceptions::FormatErrorException::FormatErrorException(const std::string &message)
-";
-
-
 // File: classIAxis.xml
 %feature("docstring") IAxis "
 
@@ -704,34 +669,6 @@ C++ includes: IPixel.h
 ";
 
 
-// File: classExceptions_1_1LogicErrorException.xml
-%feature("docstring") Exceptions::LogicErrorException "";
-
-%feature("docstring")  Exceptions::LogicErrorException::LogicErrorException "Exceptions::LogicErrorException::LogicErrorException(const std::string &message)
-";
-
-
-// File: classExceptions_1_1NotImplementedException.xml
-%feature("docstring") Exceptions::NotImplementedException "";
-
-%feature("docstring")  Exceptions::NotImplementedException::NotImplementedException "Exceptions::NotImplementedException::NotImplementedException(const std::string &message)
-";
-
-
-// File: classExceptions_1_1NullPointerException.xml
-%feature("docstring") Exceptions::NullPointerException "";
-
-%feature("docstring")  Exceptions::NullPointerException::NullPointerException "Exceptions::NullPointerException::NullPointerException(const std::string &message)
-";
-
-
-// File: classExceptions_1_1OutOfBoundsException.xml
-%feature("docstring") Exceptions::OutOfBoundsException "";
-
-%feature("docstring")  Exceptions::OutOfBoundsException::OutOfBoundsException "Exceptions::OutOfBoundsException::OutOfBoundsException(const std::string &message)
-";
-
-
 // File: classPointwiseAxis.xml
 %feature("docstring") PointwiseAxis "
 
@@ -893,13 +830,6 @@ C++ includes: Integrator.h
 ";
 
 
-// File: classExceptions_1_1RuntimeErrorException.xml
-%feature("docstring") Exceptions::RuntimeErrorException "";
-
-%feature("docstring")  Exceptions::RuntimeErrorException::RuntimeErrorException "Exceptions::RuntimeErrorException::RuntimeErrorException(const std::string &message)
-";
-
-
 // File: classSafePointerVector.xml
 %feature("docstring") SafePointerVector "
 
@@ -1219,7 +1149,7 @@ Creates a new clipped axis.
 ";
 
 
-// File: namespace_0D16.xml
+// File: namespace_0d16.xml
 
 
 // File: namespacealgo.xml
@@ -1244,11 +1174,6 @@ Returns the concatenation of two std::vectors.
 ";
 
 
-// File: namespaceExceptions.xml
-%feature("docstring")  Exceptions::LogExceptionMessage "void Exceptions::LogExceptionMessage(const std::string &)
-";
-
-
 // File: namespaceFileSystemUtils.xml
 %feature("docstring")  FileSystemUtils::extension "std::string FileSystemUtils::extension(const std::string &path)
 
@@ -1461,9 +1386,6 @@ Returns string representing python stack trace.
 %feature("docstring")  pyfmt::scriptPreamble "std::string pyfmt::scriptPreamble()
 ";
 
-%feature("docstring")  pyfmt::getSampleFunctionName "std::string pyfmt::getSampleFunctionName()
-";
-
 %feature("docstring")  pyfmt::printBool "std::string pyfmt::printBool(double value)
 ";
 
@@ -1719,12 +1641,6 @@ Returns exp(I*z), where I is the imaginary unit.
 ";
 
 
-// File: Exceptions_8cpp.xml
-
-
-// File: Exceptions_8h.xml
-
-
 // File: ICloneable_8h.xml
 
 
diff --git a/auto/Wrap/doxygenCore.i b/auto/Wrap/doxygenCore.i
index 329624469ec31800eb733b4527c1d8aafa904217..ee4d1e870317277d337cc191796552fc417d7630 100644
--- a/auto/Wrap/doxygenCore.i
+++ b/auto/Wrap/doxygenCore.i
@@ -56,11 +56,6 @@ Returns the number of simulation elements.
 Returns intensity vector corresponding to convolution of given simulation elements. 
 ";
 
-%feature("docstring")  AngularSpecScan::print "std::string AngularSpecScan::print() const override
-
-Print scan definition in python format. 
-";
-
 %feature("docstring")  AngularSpecScan::wavelength "double AngularSpecScan::wavelength() const
 ";
 
@@ -80,20 +75,20 @@ Sets footprint correction factor.
 Sets wavelength resolution values via ScanResolution object. 
 ";
 
-%feature("docstring")  AngularSpecScan::setRelativeWavelengthResolution "void AngularSpecScan::setRelativeWavelengthResolution(const RangedDistribution &distr, double rel_dev)
+%feature("docstring")  AngularSpecScan::setRelativeWavelengthResolution "void AngularSpecScan::setRelativeWavelengthResolution(const IRangedDistribution &distr, double rel_dev)
 ";
 
-%feature("docstring")  AngularSpecScan::setRelativeWavelengthResolution "void AngularSpecScan::setRelativeWavelengthResolution(const RangedDistribution &distr, const std::vector< double > &rel_dev)
+%feature("docstring")  AngularSpecScan::setRelativeWavelengthResolution "void AngularSpecScan::setRelativeWavelengthResolution(const IRangedDistribution &distr, const std::vector< double > &rel_dev)
 
-Sets wavelength resolution values via RangedDistribution and values of relative deviations (that is,  rel_dev equals standard deviation divided by the mean value).  rel_dev can be either single-valued or a numpy array. In the latter case the length of the array should coinside with the length of the inclination angle axis. 
+Sets wavelength resolution values via IRangedDistribution and values of relative deviations (that is,  rel_dev equals standard deviation divided by the mean value).  rel_dev can be either single-valued or a numpy array. In the latter case the length of the array should coinside with the length of the inclination angle axis. 
 ";
 
-%feature("docstring")  AngularSpecScan::setAbsoluteWavelengthResolution "void AngularSpecScan::setAbsoluteWavelengthResolution(const RangedDistribution &distr, double std_dev)
+%feature("docstring")  AngularSpecScan::setAbsoluteWavelengthResolution "void AngularSpecScan::setAbsoluteWavelengthResolution(const IRangedDistribution &distr, double std_dev)
 ";
 
-%feature("docstring")  AngularSpecScan::setAbsoluteWavelengthResolution "void AngularSpecScan::setAbsoluteWavelengthResolution(const RangedDistribution &distr, const std::vector< double > &std_dev)
+%feature("docstring")  AngularSpecScan::setAbsoluteWavelengthResolution "void AngularSpecScan::setAbsoluteWavelengthResolution(const IRangedDistribution &distr, const std::vector< double > &std_dev)
 
-Sets wavelength resolution values via RangedDistribution and values of standard deviations.  std_dev can be either single-valued or a numpy array. In the latter case the length of the array should coinside with the length of the inclination angle axis. 
+Sets wavelength resolution values via IRangedDistribution and values of standard deviations.  std_dev can be either single-valued or a numpy array. In the latter case the length of the array should coinside with the length of the inclination angle axis. 
 ";
 
 %feature("docstring")  AngularSpecScan::setAngleResolution "void AngularSpecScan::setAngleResolution(const ScanResolution &resolution)
@@ -101,20 +96,20 @@ Sets wavelength resolution values via RangedDistribution and values of standard
 Sets angle resolution values via ScanResolution object. 
 ";
 
-%feature("docstring")  AngularSpecScan::setRelativeAngularResolution "void AngularSpecScan::setRelativeAngularResolution(const RangedDistribution &distr, double rel_dev)
+%feature("docstring")  AngularSpecScan::setRelativeAngularResolution "void AngularSpecScan::setRelativeAngularResolution(const IRangedDistribution &distr, double rel_dev)
 ";
 
-%feature("docstring")  AngularSpecScan::setRelativeAngularResolution "void AngularSpecScan::setRelativeAngularResolution(const RangedDistribution &distr, const std::vector< double > &rel_dev)
+%feature("docstring")  AngularSpecScan::setRelativeAngularResolution "void AngularSpecScan::setRelativeAngularResolution(const IRangedDistribution &distr, const std::vector< double > &rel_dev)
 
-Sets angular resolution values via RangedDistribution and values of relative deviations (that is,  rel_dev equals standard deviation divided by the mean value).  rel_dev can be either single-valued or a numpy array. In the latter case the length of the array should coinside with the length of the inclination angle axis. 
+Sets angular resolution values via IRangedDistribution and values of relative deviations (that is,  rel_dev equals standard deviation divided by the mean value).  rel_dev can be either single-valued or a numpy array. In the latter case the length of the array should coinside with the length of the inclination angle axis. 
 ";
 
-%feature("docstring")  AngularSpecScan::setAbsoluteAngularResolution "void AngularSpecScan::setAbsoluteAngularResolution(const RangedDistribution &distr, double std_dev)
+%feature("docstring")  AngularSpecScan::setAbsoluteAngularResolution "void AngularSpecScan::setAbsoluteAngularResolution(const IRangedDistribution &distr, double std_dev)
 ";
 
-%feature("docstring")  AngularSpecScan::setAbsoluteAngularResolution "void AngularSpecScan::setAbsoluteAngularResolution(const RangedDistribution &distr, const std::vector< double > &std_dev)
+%feature("docstring")  AngularSpecScan::setAbsoluteAngularResolution "void AngularSpecScan::setAbsoluteAngularResolution(const IRangedDistribution &distr, const std::vector< double > &std_dev)
 
-Sets angular resolution values via RangedDistribution and values of standard deviations.  std_dev can be either single-valued or a numpy array. In the latter case the length of the array should coinside with the length of the inclination angle axis. 
+Sets angular resolution values via IRangedDistribution and values of standard deviations.  std_dev can be either single-valued or a numpy array. In the latter case the length of the array should coinside with the length of the inclination angle axis. 
 ";
 
 
@@ -1121,11 +1116,6 @@ Returns the number of simulation elements.
 Returns intensity vector corresponding to convolution of given simulation elements. 
 ";
 
-%feature("docstring")  ISpecularScan::print "virtual std::string ISpecularScan::print() const =0
-
-Print scan definition in python format. 
-";
-
 
 // File: classIterationInfo.xml
 %feature("docstring") IterationInfo "
@@ -1466,6 +1456,43 @@ weight_factors:
 user-defined weighting factors. Used linearly, no matter which norm is chosen. 
 ";
 
+%feature("docstring")  PoissonLikeMetric::computeFromArrays "double Chi2Metric::computeFromArrays(std::vector< double > sim_data, std::vector< double > exp_data, std::vector< double > uncertainties, std::vector< double > weight_factors) const override
+
+Computes metric value from data arrays. Negative values in exp_data are ignored as well as non-positive weight_factors and uncertainties. All arrays involved in the computation must be of the same size.
+
+Parameters:
+-----------
+
+sim_data: 
+array with simulated intensities.
+
+exp_data: 
+array with intensity values obtained from an experiment.
+
+uncertainties: 
+array with experimental data uncertainties.
+
+weight_factors: 
+user-defined weighting factors. Used linearly, no matter which norm is chosen. 
+";
+
+%feature("docstring")  PoissonLikeMetric::computeFromArrays "double Chi2Metric::computeFromArrays(std::vector< double > sim_data, std::vector< double > exp_data, std::vector< double > weight_factors) const override
+
+Computes metric value from data arrays. Negative values in exp_data are ignored as well as non-positive weight_factors. All arrays involved in the computation must be of the same size.
+
+Parameters:
+-----------
+
+sim_data: 
+array with simulated intensities.
+
+exp_data: 
+array with intensity values obtained from an experiment.
+
+weight_factors: 
+user-defined weighting factors. Used linearly, no matter which norm is chosen. 
+";
+
 
 // File: classPoissonNoiseBackground.xml
 %feature("docstring") PoissonNoiseBackground "
@@ -1551,6 +1578,9 @@ Sets q-defined specular scan. Accepts either numpy array of q-values sorted in a
 %feature("docstring")  QSpecScan::clone "QSpecScan * QSpecScan::clone() const override
 ";
 
+%feature("docstring")  QSpecScan::resolution "const ScanResolution* QSpecScan::resolution() const
+";
+
 %feature("docstring")  QSpecScan::generateSimulationElements "std::vector< SpecularSimulationElement > QSpecScan::generateSimulationElements(const Instrument &instrument) const override
 
 Generates simulation elements for specular simulations. 
@@ -1581,30 +1611,25 @@ Returns the number of simulation elements.
 Returns intensity vector corresponding to convolution of given simulation elements. 
 ";
 
-%feature("docstring")  QSpecScan::print "std::string QSpecScan::print() const override
-
-Print scan definition in python format. 
-";
-
 %feature("docstring")  QSpecScan::setQResolution "void QSpecScan::setQResolution(const ScanResolution &resolution)
 
 Sets q resolution values via ScanResolution object. 
 ";
 
-%feature("docstring")  QSpecScan::setRelativeQResolution "void QSpecScan::setRelativeQResolution(const RangedDistribution &distr, double rel_dev)
+%feature("docstring")  QSpecScan::setRelativeQResolution "void QSpecScan::setRelativeQResolution(const IRangedDistribution &distr, double rel_dev)
 ";
 
-%feature("docstring")  QSpecScan::setRelativeQResolution "void QSpecScan::setRelativeQResolution(const RangedDistribution &distr, const std::vector< double > &rel_dev)
+%feature("docstring")  QSpecScan::setRelativeQResolution "void QSpecScan::setRelativeQResolution(const IRangedDistribution &distr, const std::vector< double > &rel_dev)
 
-Sets qz resolution values via RangedDistribution and values of relative deviations (that is,  rel_dev equals standard deviation divided by the mean value).  rel_dev can be either single-valued or a numpy array. In the latter case the length of the array should coinside with the length of the qz-axis. 
+Sets qz resolution values via IRangedDistribution and values of relative deviations (that is,  rel_dev equals standard deviation divided by the mean value).  rel_dev can be either single-valued or a numpy array. In the latter case the length of the array should coinside with the length of the qz-axis. 
 ";
 
-%feature("docstring")  QSpecScan::setAbsoluteQResolution "void QSpecScan::setAbsoluteQResolution(const RangedDistribution &distr, double std_dev)
+%feature("docstring")  QSpecScan::setAbsoluteQResolution "void QSpecScan::setAbsoluteQResolution(const IRangedDistribution &distr, double std_dev)
 ";
 
-%feature("docstring")  QSpecScan::setAbsoluteQResolution "void QSpecScan::setAbsoluteQResolution(const RangedDistribution &distr, const std::vector< double > &std_dev)
+%feature("docstring")  QSpecScan::setAbsoluteQResolution "void QSpecScan::setAbsoluteQResolution(const IRangedDistribution &distr, const std::vector< double > &std_dev)
 
-Sets qz resolution values via RangedDistribution and values of standard deviations.  std_dev can be either single-valued or a numpy array. In the latter case the length of the array should coinside with the length of the qz-axis. 
+Sets qz resolution values via IRangedDistribution and values of standard deviations.  std_dev can be either single-valued or a numpy array. In the latter case the length of the array should coinside with the length of the qz-axis. 
 ";
 
 
@@ -1639,6 +1664,43 @@ weight_factors:
 user-defined weighting factors. Used linearly, no matter which norm is chosen. 
 ";
 
+%feature("docstring")  RelativeDifferenceMetric::computeFromArrays "double Chi2Metric::computeFromArrays(std::vector< double > sim_data, std::vector< double > exp_data, std::vector< double > uncertainties, std::vector< double > weight_factors) const override
+
+Computes metric value from data arrays. Negative values in exp_data are ignored as well as non-positive weight_factors and uncertainties. All arrays involved in the computation must be of the same size.
+
+Parameters:
+-----------
+
+sim_data: 
+array with simulated intensities.
+
+exp_data: 
+array with intensity values obtained from an experiment.
+
+uncertainties: 
+array with experimental data uncertainties.
+
+weight_factors: 
+user-defined weighting factors. Used linearly, no matter which norm is chosen. 
+";
+
+%feature("docstring")  RelativeDifferenceMetric::computeFromArrays "double Chi2Metric::computeFromArrays(std::vector< double > sim_data, std::vector< double > exp_data, std::vector< double > weight_factors) const override
+
+Computes metric value from data arrays. Negative values in exp_data are ignored as well as non-positive weight_factors. All arrays involved in the computation must be of the same size.
+
+Parameters:
+-----------
+
+sim_data: 
+array with simulated intensities.
+
+exp_data: 
+array with intensity values obtained from an experiment.
+
+weight_factors: 
+user-defined weighting factors. Used linearly, no matter which norm is chosen. 
+";
+
 
 // File: classRoughMultiLayerComputation.xml
 %feature("docstring") RoughMultiLayerComputation "
@@ -1950,7 +2012,7 @@ Write a Python script that allows to run the current simulation.
 C++ includes: SimulationToPython.h
 ";
 
-%feature("docstring")  SimulationToPython::generateSimulationCode "std::string SimulationToPython::generateSimulationCode(const ISimulation &simulation, EMainType mainType)
+%feature("docstring")  SimulationToPython::generateSimulationCode "std::string SimulationToPython::generateSimulationCode(const ISimulation &simulation)
 
 Returns a Python script that sets up a simulation and runs it if invoked as main program. 
 ";
@@ -2235,49 +2297,46 @@ Returns default units to convert to.
 ";
 
 
-// File: namespace_0D15.xml
-
+// File: namespace_0d15.xml
 
-// File: namespace_0D19.xml
 
+// File: namespace_0d19.xml
 
-// File: namespace_0D27.xml
 
+// File: namespace_0d39.xml
 
-// File: namespace_0D35.xml
 
+// File: namespace_0d44.xml
 
-// File: namespace_0D40.xml
 
+// File: namespace_0d53.xml
 
-// File: namespace_0D49.xml
 
+// File: namespace_0d55.xml
 
-// File: namespace_0D51.xml
 
+// File: namespace_0d59.xml
 
-// File: namespace_0D55.xml
 
+// File: namespace_0d61.xml
 
-// File: namespace_0D57.xml
 
+// File: namespace_0d66.xml
 
-// File: namespace_0D62.xml
 
+// File: namespace_0d68.xml
 
-// File: namespace_0D64.xml
 
+// File: namespace_0d72.xml
 
-// File: namespace_0D68.xml
 
+// File: namespace_0d82.xml
 
-// File: namespace_0D78.xml
 
+// File: namespace_0d84.xml
 
-// File: namespace_0D80.xml
 
-
-// File: namespace_0D86.xml
+// File: namespace_0d90.xml
 
 
 // File: namespaceExportToPython.xml
@@ -2287,9 +2346,6 @@ Returns default units to convert to.
 %feature("docstring")  ExportToPython::generateSimulationCode "std::string ExportToPython::generateSimulationCode(const ISimulation &simulation)
 ";
 
-%feature("docstring")  ExportToPython::generatePyExportTest "std::string ExportToPython::generatePyExportTest(const ISimulation &simulation)
-";
-
 
 // File: namespaceINodeUtils.xml
 %feature("docstring")  INodeUtils::ChildNodesOfType "std::vector<const T*> INodeUtils::ChildNodesOfType(const INode &node)
@@ -2352,6 +2408,44 @@ Returns default metric name.
 ";
 
 
+// File: namespacepyfmt.xml
+%feature("docstring")  pyfmt::printRealLimits "std::string pyfmt::printRealLimits(const RealLimits &limits, const std::string &units)
+";
+
+%feature("docstring")  pyfmt::printRealLimitsArg "std::string pyfmt::printRealLimitsArg(const RealLimits &limits, const std::string &units)
+
+Prints RealLimits in the form of argument (in the context of ParameterDistribution and similar). Default RealLimits will not be printed, any other will be printed as \", ba.RealLimits.limited(1*deg, 2*deg)\" 
+";
+
+
+// File: namespacepyfmt2.xml
+%feature("docstring")  pyfmt2::representShape2D "std::string pyfmt2::representShape2D(const std::string &indent, const IShape2D *ishape, bool mask_value, std::function< std::string(double)> printValueFunc)
+
+Returns fixed Python code snippet that defines the function \"runSimulation\". 
+";
+
+%feature("docstring")  pyfmt2::valueTimesUnit "std::string pyfmt2::valueTimesUnit(const RealParameter *par)
+
+Returns parameter value, followed by its unit multiplicator (like \"* nm\"). 
+";
+
+%feature("docstring")  pyfmt2::argumentList "std::string pyfmt2::argumentList(const IParameterized *ip)
+
+Returns comma-separated list of parameter values, including unit multiplicator (like \"* nm\"). 
+";
+
+%feature("docstring")  pyfmt2::printDistribution "std::string pyfmt2::printDistribution(const IDistribution1D &par_distr, const std::string &units)
+
+Prints distribution with constructor parameters in given units. ba.DistributionGaussian(2.0*deg, 0.02*deg) 
+";
+
+%feature("docstring")  pyfmt2::printParameterDistribution "std::string pyfmt2::printParameterDistribution(const ParameterDistribution &par_distr, const std::string &distVarName, const std::string &units)
+";
+
+%feature("docstring")  pyfmt2::printRangedDistribution "std::string pyfmt2::printRangedDistribution(const IRangedDistribution &distr)
+";
+
+
 // File: namespaceStandardSimulations.xml
 %feature("docstring")  StandardSimulations::BasicGISAS "GISASSimulation * StandardSimulations::BasicGISAS()
 
@@ -2643,6 +2737,18 @@ Helper factory function to use in  GISASSimulation. Depending on the type of det
 // File: OrderedMap_8h.xml
 
 
+// File: PyFmt2_8cpp.xml
+
+
+// File: PyFmt2_8h.xml
+
+
+// File: PyFmtLimits_8cpp.xml
+
+
+// File: PyFmtLimits_8h.xml
+
+
 // File: SampleLabelHandler_8cpp.xml
 
 
diff --git a/auto/Wrap/doxygenDevice.i b/auto/Wrap/doxygenDevice.i
index d8f8115e0fb3d41bbf3e67cffe2df7a89a24d396..2ec50fb1c7a5f83fdb889573cb4f591b59d66794 100644
--- a/auto/Wrap/doxygenDevice.i
+++ b/auto/Wrap/doxygenDevice.i
@@ -496,9 +496,7 @@ C++ includes: FootprintGauss.h
 Calculate footprint correction coefficient from the beam incident angle  alpha. 
 ";
 
-%feature("docstring")  FootprintGauss::print "std::string FootprintGauss::print() const override
-
-Print python-formatted footprint definition. 
+%feature("docstring")  FootprintGauss::name "std::string FootprintGauss::name() const override
 ";
 
 
@@ -527,9 +525,7 @@ C++ includes: FootprintSquare.h
 Calculate footprint correction coefficient from the beam incident angle  alpha. 
 ";
 
-%feature("docstring")  FootprintSquare::print "std::string FootprintSquare::print() const override
-
-Print python-formatted footprint definition. 
+%feature("docstring")  FootprintSquare::name "std::string FootprintSquare::name() const override
 ";
 
 
@@ -1164,9 +1160,7 @@ C++ includes: IFootprintFactor.h
 Calculate footprint correction coefficient from the beam incident angle  alpha. 
 ";
 
-%feature("docstring")  IFootprintFactor::print "virtual std::string IFootprintFactor::print() const =0
-
-Print python-formatted footprint definition. 
+%feature("docstring")  IFootprintFactor::name "virtual std::string IFootprintFactor::name() const =0
 ";
 
 
@@ -1560,7 +1554,9 @@ init detector with beam settings
 // File: classIntensityDataIOFactory.xml
 %feature("docstring") IntensityDataIOFactory "
 
-Provides users with possibility to read and write IntensityData from/to files in different format. Type of the file will be deduced from file name. *.txt - ASCII file with 2D array [nrow][ncol], layout as in numpy. *.int - BornAgain internal ASCII format. *.tif - 32-bits tiff file. If file name ends woth \"*.gz\" or \"*.bz2\" the file will be zipped on the fly using appropriate algorithm. Usage:
+Provides users with possibility to read and write IntensityData from/to files in different format. Type of the file will be deduced from file name. *.txt - ASCII file with 2D array [nrow][ncol], layout as in numpy. *.int - BornAgain internal ASCII format. *.tif - 32-bits tiff file. If file name ends woth \"*.gz\" or \"*.bz2\" the file will be zipped on the fly using appropriate algorithm.
+
+Usage:
 
 C++ includes: IntensityDataIOFactory.h
 ";
@@ -2353,7 +2349,7 @@ Sets concrete writing strategy.
 // File: classPolygon.xml
 %feature("docstring") Polygon "
 
-A polygon in 2D space.Polygon defined by two arrays with x and y coordinates of points. Sizes of arrays should coincide. If polygon is unclosed (the last point doesn't repeat the first one), it will be closed automatically.
+A polygon in 2D space.  Polygon defined by two arrays with x and y coordinates of points. Sizes of arrays should coincide. If polygon is unclosed (the last point doesn't repeat the first one), it will be closed automatically.
 
 C++ includes: Polygon.h
 ";
@@ -2736,7 +2732,7 @@ C++ includes: ScanResolution.h
 %feature("docstring")  ScanResolution::clone "ScanResolution* ScanResolution::clone() const override=0
 ";
 
-%feature("docstring")  ScanResolution::distribution "const RangedDistribution* ScanResolution::distribution() const
+%feature("docstring")  ScanResolution::distribution "const IRangedDistribution* ScanResolution::distribution() const
 ";
 
 %feature("docstring")  ScanResolution::nSamples "size_t ScanResolution::nSamples() const
@@ -2757,9 +2753,10 @@ C++ includes: ScanResolution.h
 %feature("docstring")  ScanResolution::empty "bool ScanResolution::empty() const
 ";
 
-%feature("docstring")  ScanResolution::print "std::string ScanResolution::print() const
+%feature("docstring")  ScanResolution::name "virtual std::string ScanResolution::name() const =0
+";
 
-Prints object definition in python format. 
+%feature("docstring")  ScanResolution::delta "virtual double ScanResolution::delta() const =0
 ";
 
 
@@ -3159,22 +3156,22 @@ Returns true if area defined by two bins is inside or on border of polygon (more
 // File: classConvolve_1_1Workspace.xml
 
 
-// File: namespace_0D113.xml
+// File: namespace_0d111.xml
 
 
-// File: namespace_0D33.xml
+// File: namespace_0d33.xml
 
 
-// File: namespace_0D56.xml
+// File: namespace_0d56.xml
 
 
-// File: namespace_0D58.xml
+// File: namespace_0d58.xml
 
 
-// File: namespace_0D62.xml
+// File: namespace_0d62.xml
 
 
-// File: namespace_0D68.xml
+// File: namespace_0d68.xml
 
 
 // File: namespaceArrayUtils.xml
@@ -3375,31 +3372,6 @@ for importing 2D array of doubles from python into  OutputData
 ";
 
 
-// File: namespacepyfmt2.xml
-%feature("docstring")  pyfmt2::representShape2D "std::string pyfmt2::representShape2D(const std::string &indent, const IShape2D *ishape, bool mask_value, std::function< std::string(double)> printValueFunc)
-
-Returns fixed Python code snippet that defines the function \"runSimulation\". 
-";
-
-%feature("docstring")  pyfmt2::valueTimesUnit "std::string pyfmt2::valueTimesUnit(const RealParameter *par)
-
-Returns parameter value, followed by its unit multiplicator (like \"* nm\"). 
-";
-
-%feature("docstring")  pyfmt2::argumentList "std::string pyfmt2::argumentList(const IParameterized *ip)
-
-Returns comma-separated list of parameter values, including unit multiplicator (like \"* nm\"). 
-";
-
-%feature("docstring")  pyfmt2::printDistribution "std::string pyfmt2::printDistribution(const IDistribution1D &par_distr, const std::string &units)
-
-Prints distribution with constructor parameters in given units. ba.DistributionGaussian(2.0*deg, 0.02*deg) 
-";
-
-%feature("docstring")  pyfmt2::printParameterDistribution "std::string pyfmt2::printParameterDistribution(const ParameterDistribution &par_distr, const std::string &distVarName, const std::string &units)
-";
-
-
 // File: namespaceSpectrumUtils.xml
 %feature("docstring")  SpectrumUtils::FindPeaks "std::vector< std::pair< double, double > > SpectrumUtils::FindPeaks(const Histogram2D &hist, double sigma=2, const std::string &option={}, double threshold=0.05)
 ";
@@ -3663,12 +3635,6 @@ make Swappable
 // File: PyArrayImportUtils_8h.xml
 
 
-// File: PyFmt2_8cpp.xml
-
-
-// File: PyFmt2_8h.xml
-
-
 // File: SpectrumUtils_8cpp.xml
 
 
diff --git a/auto/Wrap/doxygenParam.i b/auto/Wrap/doxygenParam.i
index 31b26b87f774db9aad0ec79cdba7538c680e8620..3ab8392b46a9e348043dfd60788623141cbb0157 100644
--- a/auto/Wrap/doxygenParam.i
+++ b/auto/Wrap/doxygenParam.i
@@ -965,6 +965,68 @@ Action to be taken in inherited class when a parameter has changed.
 ";
 
 
+// File: classIRangedDistribution.xml
+%feature("docstring") IRangedDistribution "
+
+Interface for one-dimensional ranged distributions. All derived distributions allow for generating samples in-place for known mean and standard deviation (except for  RangedDistributionLorentz which uses median and hwhm).
+
+C++ includes: RangedDistributions.h
+";
+
+%feature("docstring")  IRangedDistribution::IRangedDistribution "IRangedDistribution::IRangedDistribution()
+";
+
+%feature("docstring")  IRangedDistribution::IRangedDistribution "IRangedDistribution::IRangedDistribution(size_t n_samples, double sigma_factor, const RealLimits &limits=RealLimits::limitless())
+";
+
+%feature("docstring")  IRangedDistribution::IRangedDistribution "IRangedDistribution::IRangedDistribution(size_t n_samples, double sigma_factor, double min, double max)
+
+Initializes Ranged distribution with given number of samples, sigma factor (range in standard deviations to take into account during sample generation) and limits (either RealLimits object or just min and max limits). By default  n_samples = 5,  sigma_factor = 2.0, while the limits are (-inf, +inf). 
+";
+
+%feature("docstring")  IRangedDistribution::clone "IRangedDistribution* IRangedDistribution::clone() const override=0
+";
+
+%feature("docstring")  IRangedDistribution::~IRangedDistribution "IRangedDistribution::~IRangedDistribution() override
+";
+
+%feature("docstring")  IRangedDistribution::generateSamples "std::vector< ParameterSample > IRangedDistribution::generateSamples(double mean, double stddev) const
+";
+
+%feature("docstring")  IRangedDistribution::generateSamples "std::vector< std::vector< ParameterSample > > IRangedDistribution::generateSamples(const std::vector< double > &mean, const std::vector< double > &stddev) const
+
+Generates list of sampled values with their weights from given means and standard deviations. 
+";
+
+%feature("docstring")  IRangedDistribution::distribution "std::unique_ptr< IDistribution1D > IRangedDistribution::distribution(double mean, double stddev) const
+
+Public interface function to underlying  IDistribution1D object. 
+";
+
+%feature("docstring")  IRangedDistribution::limits "RealLimits IRangedDistribution::limits() const
+
+Returns current limits of the distribution. 
+";
+
+%feature("docstring")  IRangedDistribution::sigmaFactor "double IRangedDistribution::sigmaFactor() const
+
+Returns sigma factor to use during sampling. 
+";
+
+%feature("docstring")  IRangedDistribution::nSamples "size_t IRangedDistribution::nSamples() const
+
+Returns number of samples to generate. 
+";
+
+%feature("docstring")  IRangedDistribution::setLimits "void IRangedDistribution::setLimits(const RealLimits &limits)
+";
+
+%feature("docstring")  IRangedDistribution::name "virtual std::string IRangedDistribution::name() const =0
+
+Returns distribution name for python-formatted text. 
+";
+
+
 // File: classIterationStrategy.xml
 %feature("docstring") IterationStrategy "
 
@@ -1038,7 +1100,7 @@ C++ includes: NodeIterator.h
 %feature("docstring")  IteratorState::IteratorState "IteratorState::IteratorState(const INode *single_element)
 ";
 
-%feature("docstring")  IteratorState::IteratorState "IteratorState::IteratorState(std::vector< const INode *> samples)
+%feature("docstring")  IteratorState::IteratorState "IteratorState::IteratorState(std::vector< const INode * > samples)
 ";
 
 %feature("docstring")  IteratorState::~IteratorState "virtual IteratorState::~IteratorState()
@@ -1235,7 +1297,7 @@ Returns number of parameters in the pool.
 
 Adds parameter to the pool, and returns reference to the input pointer.
 
-Returning the input pointer allows us to concatenate function calls like pool->addParameter( new  RealParameter(...) ).setLimits(-1,+1).setFixed().setUnit(\"nm\") 
+Returning the input pointer allows us to concatenate function calls like pool->addParameter( new RealParameter(...) ).setLimits(-1,+1).setFixed().setUnit(\"nm\") 
 ";
 
 %feature("docstring")  ParameterPool::parameter "RealParameter * ParameterPool::parameter(const std::string &name)
@@ -1323,68 +1385,6 @@ C++ includes: IterationStrategy.h
 ";
 
 
-// File: classRangedDistribution.xml
-%feature("docstring") RangedDistribution "
-
-Interface for one-dimensional ranged distributions. All derived distributions allow for generating samples in-place for known mean and standard deviation (except for  RangedDistributionLorentz which uses median and hwhm).
-
-C++ includes: RangedDistributions.h
-";
-
-%feature("docstring")  RangedDistribution::RangedDistribution "RangedDistribution::RangedDistribution()
-";
-
-%feature("docstring")  RangedDistribution::RangedDistribution "RangedDistribution::RangedDistribution(size_t n_samples, double sigma_factor, const RealLimits &limits=RealLimits::limitless())
-";
-
-%feature("docstring")  RangedDistribution::RangedDistribution "RangedDistribution::RangedDistribution(size_t n_samples, double sigma_factor, double min, double max)
-
-Initializes Ranged distribution with given number of samples, sigma factor (range in standard deviations to take into account during sample generation) and limits (either RealLimits object or just min and max limits). By default  n_samples = 5,  sigma_factor = 2.0, while the limits are (-inf, +inf). 
-";
-
-%feature("docstring")  RangedDistribution::clone "RangedDistribution* RangedDistribution::clone() const override=0
-";
-
-%feature("docstring")  RangedDistribution::~RangedDistribution "RangedDistribution::~RangedDistribution() override
-";
-
-%feature("docstring")  RangedDistribution::generateSamples "std::vector< ParameterSample > RangedDistribution::generateSamples(double mean, double stddev) const
-";
-
-%feature("docstring")  RangedDistribution::generateSamples "std::vector< std::vector< ParameterSample > > RangedDistribution::generateSamples(const std::vector< double > &mean, const std::vector< double > &stddev) const
-
-Generates list of sampled values with their weights from given means and standard deviations. 
-";
-
-%feature("docstring")  RangedDistribution::distribution "std::unique_ptr< IDistribution1D > RangedDistribution::distribution(double mean, double stddev) const
-
-Public interface function to underlying  IDistribution1D object. 
-";
-
-%feature("docstring")  RangedDistribution::limits "RealLimits RangedDistribution::limits() const
-
-Returns current limits of the distribution. 
-";
-
-%feature("docstring")  RangedDistribution::sigmaFactor "double RangedDistribution::sigmaFactor() const
-
-Returns sigma factor to use during sampling. 
-";
-
-%feature("docstring")  RangedDistribution::nSamples "size_t RangedDistribution::nSamples() const
-
-Returns number of samples to generate. 
-";
-
-%feature("docstring")  RangedDistribution::setLimits "void RangedDistribution::setLimits(const RealLimits &limits)
-";
-
-%feature("docstring")  RangedDistribution::pyString "std::string RangedDistribution::pyString() const
-
-Prints python-formatted definition of the distribution. 
-";
-
-
 // File: classRangedDistributionCosine.xml
 %feature("docstring") RangedDistributionCosine "
 
@@ -1410,6 +1410,11 @@ Initializes Ranged distribution with given number of samples, sigma factor (rang
 %feature("docstring")  RangedDistributionCosine::~RangedDistributionCosine "RangedDistributionCosine::~RangedDistributionCosine() override=default
 ";
 
+%feature("docstring")  RangedDistributionCosine::name "std::string RangedDistributionCosine::name() const override
+
+Returns distribution name for python-formatted text. 
+";
+
 
 // File: classRangedDistributionGate.xml
 %feature("docstring") RangedDistributionGate "
@@ -1436,6 +1441,11 @@ Initializes Ranged distribution with given number of samples, sigma factor (rang
 %feature("docstring")  RangedDistributionGate::~RangedDistributionGate "RangedDistributionGate::~RangedDistributionGate() override=default
 ";
 
+%feature("docstring")  RangedDistributionGate::name "std::string RangedDistributionGate::name() const override
+
+Returns distribution name for python-formatted text. 
+";
+
 
 // File: classRangedDistributionGaussian.xml
 %feature("docstring") RangedDistributionGaussian "
@@ -1462,6 +1472,11 @@ Initializes Ranged distribution with given number of samples, sigma factor (rang
 %feature("docstring")  RangedDistributionGaussian::~RangedDistributionGaussian "RangedDistributionGaussian::~RangedDistributionGaussian() override=default
 ";
 
+%feature("docstring")  RangedDistributionGaussian::name "std::string RangedDistributionGaussian::name() const override
+
+Returns distribution name for python-formatted text. 
+";
+
 
 // File: classRangedDistributionLogNormal.xml
 %feature("docstring") RangedDistributionLogNormal "
@@ -1488,6 +1503,11 @@ Initializes Ranged distribution with given number of samples, sigma factor (rang
 %feature("docstring")  RangedDistributionLogNormal::~RangedDistributionLogNormal "RangedDistributionLogNormal::~RangedDistributionLogNormal() override=default
 ";
 
+%feature("docstring")  RangedDistributionLogNormal::name "std::string RangedDistributionLogNormal::name() const override
+
+Returns distribution name for python-formatted text. 
+";
+
 
 // File: classRangedDistributionLorentz.xml
 %feature("docstring") RangedDistributionLorentz "
@@ -1514,6 +1534,11 @@ Initializes Ranged distribution with given number of samples, sigma factor (rang
 %feature("docstring")  RangedDistributionLorentz::~RangedDistributionLorentz "RangedDistributionLorentz::~RangedDistributionLorentz() override=default
 ";
 
+%feature("docstring")  RangedDistributionLorentz::name "std::string RangedDistributionLorentz::name() const override
+
+Returns distribution name for python-formatted text. 
+";
+
 
 // File: classRealParameter.xml
 %feature("docstring") RealParameter "
@@ -1582,16 +1607,16 @@ C++ includes: Unit.h
 ";
 
 
-// File: namespace_0D10.xml
+// File: namespace_0d10.xml
 
 
-// File: namespace_0D14.xml
+// File: namespace_0d14.xml
 
 
-// File: namespace_0D24.xml
+// File: namespace_0d24.xml
 
 
-// File: namespace_0D29.xml
+// File: namespace_0d29.xml
 
 
 // File: namespaceNodeUtils.xml
@@ -1618,16 +1643,6 @@ Returns units of main parameter.
 ";
 
 
-// File: namespacepyfmt.xml
-%feature("docstring")  pyfmt::printRealLimits "std::string pyfmt::printRealLimits(const RealLimits &limits, const std::string &units)
-";
-
-%feature("docstring")  pyfmt::printRealLimitsArg "std::string pyfmt::printRealLimitsArg(const RealLimits &limits, const std::string &units)
-
-Prints RealLimits in the form of argument (in the context of  ParameterDistribution and similar). Default RealLimits will not be printed, any other will be printed as \", ba.RealLimits.limited(1*deg, 2*deg)\" 
-";
-
-
 // File: IParameter_8h.xml
 
 
@@ -1729,12 +1744,6 @@ Prints RealLimits in the form of argument (in the context of  ParameterDistribut
 // File: ParameterUtils_8h.xml
 
 
-// File: PyFmtLimits_8cpp.xml
-
-
-// File: PyFmtLimits_8h.xml
-
-
 // File: dir_a1f38e94e849d0203a55ad5a19f2f15a.xml
 
 
diff --git a/auto/Wrap/doxygenSample.i b/auto/Wrap/doxygenSample.i
index 82e19d701f29bc862f66e961b5168a93f01ec6fa..e2ef874b1004f9abe119edd3f480ffcb426193ca 100644
--- a/auto/Wrap/doxygenSample.i
+++ b/auto/Wrap/doxygenSample.i
@@ -5040,7 +5040,7 @@ Returns lateral correlation length.
 // File: classLayersWithAbsorptionBuilder.xml
 %feature("docstring") LayersWithAbsorptionBuilder "
 
-The  LayersWithAbsorptionBuilder class generates a multilayer with 3 layers with absorption (refractive index has imaginary part).The middle layer is populated with particles. Requires IComponentService which generates form factors, used for bulk form factors testing.
+The  LayersWithAbsorptionBuilder class generates a multilayer with 3 layers with absorption (refractive index has imaginary part). The middle layer is populated with particles. Requires IComponentService which generates form factors, used for bulk form factors testing.
 
 C++ includes: LayersWithAbsorptionBuilder.h
 ";
@@ -5695,7 +5695,7 @@ Indicates if the peak shape encodes angular disorder, in which case all peaks in
 // File: classMultiLayer.xml
 %feature("docstring") MultiLayer "
 
-Our sample model: a stack of layers one below the other.Example of system of 4 layers (3 interfaces):
+Our sample model: a stack of layers one below the other. Example of system of 4 layers (3 interfaces):
 
 ambience layer #0 ------ interface #0 z=0.0 Fe, 20A layer #1 ------ interface #1 z=-20.0 Cr, 40A layer #2 ------ interface #2 z=-60.0 substrate layer #3
 
@@ -7618,124 +7618,124 @@ C++ includes: ZLimits.h
 ";
 
 
-// File: namespace_0D122.xml
+// File: namespace_0d122.xml
 
 
-// File: namespace_0D125.xml
+// File: namespace_0d125.xml
 
 
-// File: namespace_0D149.xml
+// File: namespace_0d149.xml
 
 
-// File: namespace_0D153.xml
+// File: namespace_0d153.xml
 
 
-// File: namespace_0D157.xml
+// File: namespace_0d157.xml
 
 
-// File: namespace_0D16.xml
+// File: namespace_0d16.xml
 
 
-// File: namespace_0D167.xml
+// File: namespace_0d167.xml
 
 
-// File: namespace_0D169.xml
+// File: namespace_0d169.xml
 
 
-// File: namespace_0D171.xml
+// File: namespace_0d171.xml
 
 
-// File: namespace_0D181.xml
+// File: namespace_0d181.xml
 
 
-// File: namespace_0D2.xml
+// File: namespace_0d2.xml
 
 
-// File: namespace_0D201.xml
+// File: namespace_0d201.xml
 
 
-// File: namespace_0D203.xml
+// File: namespace_0d203.xml
 
 
-// File: namespace_0D205.xml
+// File: namespace_0d205.xml
 
 
-// File: namespace_0D210.xml
+// File: namespace_0d210.xml
 
 
-// File: namespace_0D212.xml
+// File: namespace_0d212.xml
 
 
-// File: namespace_0D222.xml
+// File: namespace_0d222.xml
 
 
-// File: namespace_0D236.xml
+// File: namespace_0d236.xml
 
 
-// File: namespace_0D241.xml
+// File: namespace_0d241.xml
 
 
-// File: namespace_0D25.xml
+// File: namespace_0d25.xml
 
 
-// File: namespace_0D259.xml
+// File: namespace_0d259.xml
 
 
-// File: namespace_0D267.xml
+// File: namespace_0d267.xml
 
 
-// File: namespace_0D277.xml
+// File: namespace_0d277.xml
 
 
-// File: namespace_0D279.xml
+// File: namespace_0d279.xml
 
 
-// File: namespace_0D281.xml
+// File: namespace_0d281.xml
 
 
-// File: namespace_0D283.xml
+// File: namespace_0d283.xml
 
 
-// File: namespace_0D285.xml
+// File: namespace_0d285.xml
 
 
-// File: namespace_0D289.xml
+// File: namespace_0d289.xml
 
 
-// File: namespace_0D291.xml
+// File: namespace_0d291.xml
 
 
-// File: namespace_0D295.xml
+// File: namespace_0d295.xml
 
 
-// File: namespace_0D307.xml
+// File: namespace_0d307.xml
 
 
-// File: namespace_0D31.xml
+// File: namespace_0d31.xml
 
 
-// File: namespace_0D313.xml
+// File: namespace_0d313.xml
 
 
-// File: namespace_0D317.xml
+// File: namespace_0d317.xml
 
 
-// File: namespace_0D335.xml
+// File: namespace_0d335.xml
 
 
-// File: namespace_0D354.xml
+// File: namespace_0d354.xml
 
 
-// File: namespace_0D37.xml
+// File: namespace_0d37.xml
 
 
-// File: namespace_0D39.xml
+// File: namespace_0d39.xml
 
 
-// File: namespace_0D4.xml
+// File: namespace_0d4.xml
 
 
-// File: namespace_0D47.xml
+// File: namespace_0d47.xml
 
 
 // File: namespacebake.xml
@@ -7803,7 +7803,7 @@ Function for calculating the reduced potential, used for obtaining the Fresnel c
 %feature("docstring")  MaterialUtils::MagnetizationCorrection "Eigen::Matrix2cd MaterialUtils::MagnetizationCorrection(complex_t unit_factor, double magnetic_factor, BasicVector3D< T > polarization)
 ";
 
-%feature("docstring")  MaterialUtils::checkMaterialTypes "MATERIAL_TYPES MaterialUtils::checkMaterialTypes(const std::vector< const Material *> &materials)
+%feature("docstring")  MaterialUtils::checkMaterialTypes "MATERIAL_TYPES MaterialUtils::checkMaterialTypes(const std::vector< const Material * > &materials)
 
 Checks if all non-default materials in  materials are of the same type and returns this type. If several types of materials are involved, InvalidMaterialType identifier is returned. 
 ";
diff --git a/auto/Wrap/libBornAgainCore.py b/auto/Wrap/libBornAgainCore.py
index 16366a5959fb8a2152a80c799bc29106f12ae059..e87d9628e8b73a38c7d6f8ae6975977ff3d00278 100644
--- a/auto/Wrap/libBornAgainCore.py
+++ b/auto/Wrap/libBornAgainCore.py
@@ -3427,22 +3427,22 @@ class AngularSpecScan(object):
 
     def setRelativeWavelengthResolution(self, *args):
         r"""
-        setRelativeWavelengthResolution(AngularSpecScan self, RangedDistribution const & distr, double rel_dev)
-        setRelativeWavelengthResolution(AngularSpecScan self, RangedDistribution const & distr, vdouble1d_t rel_dev)
-        void AngularSpecScan::setRelativeWavelengthResolution(const RangedDistribution &distr, const std::vector< double > &rel_dev)
+        setRelativeWavelengthResolution(AngularSpecScan self, IRangedDistribution const & distr, double rel_dev)
+        setRelativeWavelengthResolution(AngularSpecScan self, IRangedDistribution const & distr, vdouble1d_t rel_dev)
+        void AngularSpecScan::setRelativeWavelengthResolution(const IRangedDistribution &distr, const std::vector< double > &rel_dev)
 
-        Sets wavelength resolution values via RangedDistribution and values of relative deviations (that is,  rel_dev equals standard deviation divided by the mean value).  rel_dev can be either single-valued or a numpy array. In the latter case the length of the array should coinside with the length of the inclination angle axis. 
+        Sets wavelength resolution values via IRangedDistribution and values of relative deviations (that is,  rel_dev equals standard deviation divided by the mean value).  rel_dev can be either single-valued or a numpy array. In the latter case the length of the array should coinside with the length of the inclination angle axis. 
 
         """
         return _libBornAgainCore.AngularSpecScan_setRelativeWavelengthResolution(self, *args)
 
     def setAbsoluteWavelengthResolution(self, *args):
         r"""
-        setAbsoluteWavelengthResolution(AngularSpecScan self, RangedDistribution const & distr, double std_dev)
-        setAbsoluteWavelengthResolution(AngularSpecScan self, RangedDistribution const & distr, vdouble1d_t std_dev)
-        void AngularSpecScan::setAbsoluteWavelengthResolution(const RangedDistribution &distr, const std::vector< double > &std_dev)
+        setAbsoluteWavelengthResolution(AngularSpecScan self, IRangedDistribution const & distr, double std_dev)
+        setAbsoluteWavelengthResolution(AngularSpecScan self, IRangedDistribution const & distr, vdouble1d_t std_dev)
+        void AngularSpecScan::setAbsoluteWavelengthResolution(const IRangedDistribution &distr, const std::vector< double > &std_dev)
 
-        Sets wavelength resolution values via RangedDistribution and values of standard deviations.  std_dev can be either single-valued or a numpy array. In the latter case the length of the array should coinside with the length of the inclination angle axis. 
+        Sets wavelength resolution values via IRangedDistribution and values of standard deviations.  std_dev can be either single-valued or a numpy array. In the latter case the length of the array should coinside with the length of the inclination angle axis. 
 
         """
         return _libBornAgainCore.AngularSpecScan_setAbsoluteWavelengthResolution(self, *args)
@@ -3459,22 +3459,22 @@ class AngularSpecScan(object):
 
     def setRelativeAngularResolution(self, *args):
         r"""
-        setRelativeAngularResolution(AngularSpecScan self, RangedDistribution const & distr, double rel_dev)
-        setRelativeAngularResolution(AngularSpecScan self, RangedDistribution const & distr, vdouble1d_t rel_dev)
-        void AngularSpecScan::setRelativeAngularResolution(const RangedDistribution &distr, const std::vector< double > &rel_dev)
+        setRelativeAngularResolution(AngularSpecScan self, IRangedDistribution const & distr, double rel_dev)
+        setRelativeAngularResolution(AngularSpecScan self, IRangedDistribution const & distr, vdouble1d_t rel_dev)
+        void AngularSpecScan::setRelativeAngularResolution(const IRangedDistribution &distr, const std::vector< double > &rel_dev)
 
-        Sets angular resolution values via RangedDistribution and values of relative deviations (that is,  rel_dev equals standard deviation divided by the mean value).  rel_dev can be either single-valued or a numpy array. In the latter case the length of the array should coinside with the length of the inclination angle axis. 
+        Sets angular resolution values via IRangedDistribution and values of relative deviations (that is,  rel_dev equals standard deviation divided by the mean value).  rel_dev can be either single-valued or a numpy array. In the latter case the length of the array should coinside with the length of the inclination angle axis. 
 
         """
         return _libBornAgainCore.AngularSpecScan_setRelativeAngularResolution(self, *args)
 
     def setAbsoluteAngularResolution(self, *args):
         r"""
-        setAbsoluteAngularResolution(AngularSpecScan self, RangedDistribution const & distr, double std_dev)
-        setAbsoluteAngularResolution(AngularSpecScan self, RangedDistribution const & distr, vdouble1d_t std_dev)
-        void AngularSpecScan::setAbsoluteAngularResolution(const RangedDistribution &distr, const std::vector< double > &std_dev)
+        setAbsoluteAngularResolution(AngularSpecScan self, IRangedDistribution const & distr, double std_dev)
+        setAbsoluteAngularResolution(AngularSpecScan self, IRangedDistribution const & distr, vdouble1d_t std_dev)
+        void AngularSpecScan::setAbsoluteAngularResolution(const IRangedDistribution &distr, const std::vector< double > &std_dev)
 
-        Sets angular resolution values via RangedDistribution and values of standard deviations.  std_dev can be either single-valued or a numpy array. In the latter case the length of the array should coinside with the length of the inclination angle axis. 
+        Sets angular resolution values via IRangedDistribution and values of standard deviations.  std_dev can be either single-valued or a numpy array. In the latter case the length of the array should coinside with the length of the inclination angle axis. 
 
         """
         return _libBornAgainCore.AngularSpecScan_setAbsoluteAngularResolution(self, *args)
@@ -3516,6 +3516,14 @@ class QSpecScan(object):
         """
         return _libBornAgainCore.QSpecScan_clone(self)
 
+    def resolution(self):
+        r"""
+        resolution(QSpecScan self) -> ScanResolution const *
+        const ScanResolution* QSpecScan::resolution() const
+
+        """
+        return _libBornAgainCore.QSpecScan_resolution(self)
+
     def setQResolution(self, resolution):
         r"""
         setQResolution(QSpecScan self, ScanResolution const & resolution)
@@ -3528,22 +3536,22 @@ class QSpecScan(object):
 
     def setRelativeQResolution(self, *args):
         r"""
-        setRelativeQResolution(QSpecScan self, RangedDistribution const & distr, double rel_dev)
-        setRelativeQResolution(QSpecScan self, RangedDistribution const & distr, vdouble1d_t rel_dev)
-        void QSpecScan::setRelativeQResolution(const RangedDistribution &distr, const std::vector< double > &rel_dev)
+        setRelativeQResolution(QSpecScan self, IRangedDistribution const & distr, double rel_dev)
+        setRelativeQResolution(QSpecScan self, IRangedDistribution const & distr, vdouble1d_t rel_dev)
+        void QSpecScan::setRelativeQResolution(const IRangedDistribution &distr, const std::vector< double > &rel_dev)
 
-        Sets qz resolution values via RangedDistribution and values of relative deviations (that is,  rel_dev equals standard deviation divided by the mean value).  rel_dev can be either single-valued or a numpy array. In the latter case the length of the array should coinside with the length of the qz-axis. 
+        Sets qz resolution values via IRangedDistribution and values of relative deviations (that is,  rel_dev equals standard deviation divided by the mean value).  rel_dev can be either single-valued or a numpy array. In the latter case the length of the array should coinside with the length of the qz-axis. 
 
         """
         return _libBornAgainCore.QSpecScan_setRelativeQResolution(self, *args)
 
     def setAbsoluteQResolution(self, *args):
         r"""
-        setAbsoluteQResolution(QSpecScan self, RangedDistribution const & distr, double std_dev)
-        setAbsoluteQResolution(QSpecScan self, RangedDistribution const & distr, vdouble1d_t std_dev)
-        void QSpecScan::setAbsoluteQResolution(const RangedDistribution &distr, const std::vector< double > &std_dev)
+        setAbsoluteQResolution(QSpecScan self, IRangedDistribution const & distr, double std_dev)
+        setAbsoluteQResolution(QSpecScan self, IRangedDistribution const & distr, vdouble1d_t std_dev)
+        void QSpecScan::setAbsoluteQResolution(const IRangedDistribution &distr, const std::vector< double > &std_dev)
 
-        Sets qz resolution values via RangedDistribution and values of standard deviations.  std_dev can be either single-valued or a numpy array. In the latter case the length of the array should coinside with the length of the qz-axis. 
+        Sets qz resolution values via IRangedDistribution and values of standard deviations.  std_dev can be either single-valued or a numpy array. In the latter case the length of the array should coinside with the length of the qz-axis. 
 
         """
         return _libBornAgainCore.QSpecScan_setAbsoluteQResolution(self, *args)
@@ -4494,14 +4502,6 @@ def generateSimulationCode(simulation):
     """
     return _libBornAgainCore.generateSimulationCode(simulation)
 
-def generatePyExportTest(simulation):
-    r"""
-    generatePyExportTest(ISimulation simulation) -> std::string
-    std::string ExportToPython::generatePyExportTest(const ISimulation &simulation)
-
-    """
-    return _libBornAgainCore.generatePyExportTest(simulation)
-
 class SimulationBuilderWrapper(PyBuilderCallback):
     def __init__(self, f):
         super(SimulationBuilderWrapper, self).__init__()
diff --git a/auto/Wrap/libBornAgainCore_wrap.cpp b/auto/Wrap/libBornAgainCore_wrap.cpp
index 8b4783958585a78f8b790e6283c0b4584312b5c4..19c2b81a5bb8c5fa821f4f2a67fd76d7c698df83 100644
--- a/auto/Wrap/libBornAgainCore_wrap.cpp
+++ b/auto/Wrap/libBornAgainCore_wrap.cpp
@@ -3124,25 +3124,25 @@ namespace Swig {
 #define SWIGTYPE_p_IObservable swig_types[24]
 #define SWIGTYPE_p_IObserver swig_types[25]
 #define SWIGTYPE_p_IParameterized swig_types[26]
-#define SWIGTYPE_p_IResolutionFunction2D swig_types[27]
-#define SWIGTYPE_p_ISample swig_types[28]
-#define SWIGTYPE_p_IShape2D swig_types[29]
-#define SWIGTYPE_p_ISimulation swig_types[30]
-#define SWIGTYPE_p_ISimulation2D swig_types[31]
-#define SWIGTYPE_p_ISpecularScan swig_types[32]
-#define SWIGTYPE_p_Instrument swig_types[33]
-#define SWIGTYPE_p_IterationInfo swig_types[34]
-#define SWIGTYPE_p_MultiLayer swig_types[35]
-#define SWIGTYPE_p_OffSpecSimulation swig_types[36]
-#define SWIGTYPE_p_OutputDataT_double_t swig_types[37]
-#define SWIGTYPE_p_ParameterDistribution swig_types[38]
-#define SWIGTYPE_p_ParameterPool swig_types[39]
-#define SWIGTYPE_p_PoissonNoiseBackground swig_types[40]
-#define SWIGTYPE_p_ProgressHandler__Callback_t swig_types[41]
-#define SWIGTYPE_p_PyBuilderCallback swig_types[42]
-#define SWIGTYPE_p_PyObserverCallback swig_types[43]
-#define SWIGTYPE_p_QSpecScan swig_types[44]
-#define SWIGTYPE_p_RangedDistribution swig_types[45]
+#define SWIGTYPE_p_IRangedDistribution swig_types[27]
+#define SWIGTYPE_p_IResolutionFunction2D swig_types[28]
+#define SWIGTYPE_p_ISample swig_types[29]
+#define SWIGTYPE_p_IShape2D swig_types[30]
+#define SWIGTYPE_p_ISimulation swig_types[31]
+#define SWIGTYPE_p_ISimulation2D swig_types[32]
+#define SWIGTYPE_p_ISpecularScan swig_types[33]
+#define SWIGTYPE_p_Instrument swig_types[34]
+#define SWIGTYPE_p_IterationInfo swig_types[35]
+#define SWIGTYPE_p_MultiLayer swig_types[36]
+#define SWIGTYPE_p_OffSpecSimulation swig_types[37]
+#define SWIGTYPE_p_OutputDataT_double_t swig_types[38]
+#define SWIGTYPE_p_ParameterDistribution swig_types[39]
+#define SWIGTYPE_p_ParameterPool swig_types[40]
+#define SWIGTYPE_p_PoissonNoiseBackground swig_types[41]
+#define SWIGTYPE_p_ProgressHandler__Callback_t swig_types[42]
+#define SWIGTYPE_p_PyBuilderCallback swig_types[43]
+#define SWIGTYPE_p_PyObserverCallback swig_types[44]
+#define SWIGTYPE_p_QSpecScan swig_types[45]
 #define SWIGTYPE_p_RealLimits swig_types[46]
 #define SWIGTYPE_p_ScanResolution swig_types[47]
 #define SWIGTYPE_p_SimulationFactory swig_types[48]
@@ -37935,7 +37935,7 @@ fail:
 SWIGINTERN PyObject *_wrap_AngularSpecScan_setRelativeWavelengthResolution__SWIG_0(PyObject *SWIGUNUSEDPARM(self), Py_ssize_t nobjs, PyObject **swig_obj) {
   PyObject *resultobj = 0;
   AngularSpecScan *arg1 = (AngularSpecScan *) 0 ;
-  RangedDistribution *arg2 = 0 ;
+  IRangedDistribution *arg2 = 0 ;
   double arg3 ;
   void *argp1 = 0 ;
   int res1 = 0 ;
@@ -37950,20 +37950,20 @@ SWIGINTERN PyObject *_wrap_AngularSpecScan_setRelativeWavelengthResolution__SWIG
     SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "AngularSpecScan_setRelativeWavelengthResolution" "', argument " "1"" of type '" "AngularSpecScan *""'"); 
   }
   arg1 = reinterpret_cast< AngularSpecScan * >(argp1);
-  res2 = SWIG_ConvertPtr(swig_obj[1], &argp2, SWIGTYPE_p_RangedDistribution,  0  | 0);
+  res2 = SWIG_ConvertPtr(swig_obj[1], &argp2, SWIGTYPE_p_IRangedDistribution,  0  | 0);
   if (!SWIG_IsOK(res2)) {
-    SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "AngularSpecScan_setRelativeWavelengthResolution" "', argument " "2"" of type '" "RangedDistribution const &""'"); 
+    SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "AngularSpecScan_setRelativeWavelengthResolution" "', argument " "2"" of type '" "IRangedDistribution const &""'"); 
   }
   if (!argp2) {
-    SWIG_exception_fail(SWIG_ValueError, "invalid null reference " "in method '" "AngularSpecScan_setRelativeWavelengthResolution" "', argument " "2"" of type '" "RangedDistribution const &""'"); 
+    SWIG_exception_fail(SWIG_ValueError, "invalid null reference " "in method '" "AngularSpecScan_setRelativeWavelengthResolution" "', argument " "2"" of type '" "IRangedDistribution const &""'"); 
   }
-  arg2 = reinterpret_cast< RangedDistribution * >(argp2);
+  arg2 = reinterpret_cast< IRangedDistribution * >(argp2);
   ecode3 = SWIG_AsVal_double(swig_obj[2], &val3);
   if (!SWIG_IsOK(ecode3)) {
     SWIG_exception_fail(SWIG_ArgError(ecode3), "in method '" "AngularSpecScan_setRelativeWavelengthResolution" "', argument " "3"" of type '" "double""'");
   } 
   arg3 = static_cast< double >(val3);
-  (arg1)->setRelativeWavelengthResolution((RangedDistribution const &)*arg2,arg3);
+  (arg1)->setRelativeWavelengthResolution((IRangedDistribution const &)*arg2,arg3);
   resultobj = SWIG_Py_Void();
   return resultobj;
 fail:
@@ -37974,7 +37974,7 @@ fail:
 SWIGINTERN PyObject *_wrap_AngularSpecScan_setRelativeWavelengthResolution__SWIG_1(PyObject *SWIGUNUSEDPARM(self), Py_ssize_t nobjs, PyObject **swig_obj) {
   PyObject *resultobj = 0;
   AngularSpecScan *arg1 = (AngularSpecScan *) 0 ;
-  RangedDistribution *arg2 = 0 ;
+  IRangedDistribution *arg2 = 0 ;
   std::vector< double,std::allocator< double > > *arg3 = 0 ;
   void *argp1 = 0 ;
   int res1 = 0 ;
@@ -37988,14 +37988,14 @@ SWIGINTERN PyObject *_wrap_AngularSpecScan_setRelativeWavelengthResolution__SWIG
     SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "AngularSpecScan_setRelativeWavelengthResolution" "', argument " "1"" of type '" "AngularSpecScan *""'"); 
   }
   arg1 = reinterpret_cast< AngularSpecScan * >(argp1);
-  res2 = SWIG_ConvertPtr(swig_obj[1], &argp2, SWIGTYPE_p_RangedDistribution,  0  | 0);
+  res2 = SWIG_ConvertPtr(swig_obj[1], &argp2, SWIGTYPE_p_IRangedDistribution,  0  | 0);
   if (!SWIG_IsOK(res2)) {
-    SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "AngularSpecScan_setRelativeWavelengthResolution" "', argument " "2"" of type '" "RangedDistribution const &""'"); 
+    SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "AngularSpecScan_setRelativeWavelengthResolution" "', argument " "2"" of type '" "IRangedDistribution const &""'"); 
   }
   if (!argp2) {
-    SWIG_exception_fail(SWIG_ValueError, "invalid null reference " "in method '" "AngularSpecScan_setRelativeWavelengthResolution" "', argument " "2"" of type '" "RangedDistribution const &""'"); 
+    SWIG_exception_fail(SWIG_ValueError, "invalid null reference " "in method '" "AngularSpecScan_setRelativeWavelengthResolution" "', argument " "2"" of type '" "IRangedDistribution const &""'"); 
   }
-  arg2 = reinterpret_cast< RangedDistribution * >(argp2);
+  arg2 = reinterpret_cast< IRangedDistribution * >(argp2);
   {
     std::vector< double,std::allocator< double > > *ptr = (std::vector< double,std::allocator< double > > *)0;
     res3 = swig::asptr(swig_obj[2], &ptr);
@@ -38007,7 +38007,7 @@ SWIGINTERN PyObject *_wrap_AngularSpecScan_setRelativeWavelengthResolution__SWIG
     }
     arg3 = ptr;
   }
-  (arg1)->setRelativeWavelengthResolution((RangedDistribution const &)*arg2,(std::vector< double,std::allocator< double > > const &)*arg3);
+  (arg1)->setRelativeWavelengthResolution((IRangedDistribution const &)*arg2,(std::vector< double,std::allocator< double > > const &)*arg3);
   resultobj = SWIG_Py_Void();
   if (SWIG_IsNewObj(res3)) delete arg3;
   return resultobj;
@@ -38031,7 +38031,7 @@ SWIGINTERN PyObject *_wrap_AngularSpecScan_setRelativeWavelengthResolution(PyObj
     int res = SWIG_ConvertPtr(argv[0], &vptr, SWIGTYPE_p_AngularSpecScan, 0);
     _v = SWIG_CheckState(res);
     if (_v) {
-      int res = SWIG_ConvertPtr(argv[1], 0, SWIGTYPE_p_RangedDistribution, SWIG_POINTER_NO_NULL | 0);
+      int res = SWIG_ConvertPtr(argv[1], 0, SWIGTYPE_p_IRangedDistribution, SWIG_POINTER_NO_NULL | 0);
       _v = SWIG_CheckState(res);
       if (_v) {
         {
@@ -38050,7 +38050,7 @@ SWIGINTERN PyObject *_wrap_AngularSpecScan_setRelativeWavelengthResolution(PyObj
     int res = SWIG_ConvertPtr(argv[0], &vptr, SWIGTYPE_p_AngularSpecScan, 0);
     _v = SWIG_CheckState(res);
     if (_v) {
-      int res = SWIG_ConvertPtr(argv[1], 0, SWIGTYPE_p_RangedDistribution, SWIG_POINTER_NO_NULL | 0);
+      int res = SWIG_ConvertPtr(argv[1], 0, SWIGTYPE_p_IRangedDistribution, SWIG_POINTER_NO_NULL | 0);
       _v = SWIG_CheckState(res);
       if (_v) {
         int res = swig::asptr(argv[2], (std::vector< double,std::allocator< double > >**)(0));
@@ -38065,8 +38065,8 @@ SWIGINTERN PyObject *_wrap_AngularSpecScan_setRelativeWavelengthResolution(PyObj
 fail:
   SWIG_Python_RaiseOrModifyTypeError("Wrong number or type of arguments for overloaded function 'AngularSpecScan_setRelativeWavelengthResolution'.\n"
     "  Possible C/C++ prototypes are:\n"
-    "    AngularSpecScan::setRelativeWavelengthResolution(RangedDistribution const &,double)\n"
-    "    AngularSpecScan::setRelativeWavelengthResolution(RangedDistribution const &,std::vector< double,std::allocator< double > > const &)\n");
+    "    AngularSpecScan::setRelativeWavelengthResolution(IRangedDistribution const &,double)\n"
+    "    AngularSpecScan::setRelativeWavelengthResolution(IRangedDistribution const &,std::vector< double,std::allocator< double > > const &)\n");
   return 0;
 }
 
@@ -38074,7 +38074,7 @@ fail:
 SWIGINTERN PyObject *_wrap_AngularSpecScan_setAbsoluteWavelengthResolution__SWIG_0(PyObject *SWIGUNUSEDPARM(self), Py_ssize_t nobjs, PyObject **swig_obj) {
   PyObject *resultobj = 0;
   AngularSpecScan *arg1 = (AngularSpecScan *) 0 ;
-  RangedDistribution *arg2 = 0 ;
+  IRangedDistribution *arg2 = 0 ;
   double arg3 ;
   void *argp1 = 0 ;
   int res1 = 0 ;
@@ -38089,20 +38089,20 @@ SWIGINTERN PyObject *_wrap_AngularSpecScan_setAbsoluteWavelengthResolution__SWIG
     SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "AngularSpecScan_setAbsoluteWavelengthResolution" "', argument " "1"" of type '" "AngularSpecScan *""'"); 
   }
   arg1 = reinterpret_cast< AngularSpecScan * >(argp1);
-  res2 = SWIG_ConvertPtr(swig_obj[1], &argp2, SWIGTYPE_p_RangedDistribution,  0  | 0);
+  res2 = SWIG_ConvertPtr(swig_obj[1], &argp2, SWIGTYPE_p_IRangedDistribution,  0  | 0);
   if (!SWIG_IsOK(res2)) {
-    SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "AngularSpecScan_setAbsoluteWavelengthResolution" "', argument " "2"" of type '" "RangedDistribution const &""'"); 
+    SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "AngularSpecScan_setAbsoluteWavelengthResolution" "', argument " "2"" of type '" "IRangedDistribution const &""'"); 
   }
   if (!argp2) {
-    SWIG_exception_fail(SWIG_ValueError, "invalid null reference " "in method '" "AngularSpecScan_setAbsoluteWavelengthResolution" "', argument " "2"" of type '" "RangedDistribution const &""'"); 
+    SWIG_exception_fail(SWIG_ValueError, "invalid null reference " "in method '" "AngularSpecScan_setAbsoluteWavelengthResolution" "', argument " "2"" of type '" "IRangedDistribution const &""'"); 
   }
-  arg2 = reinterpret_cast< RangedDistribution * >(argp2);
+  arg2 = reinterpret_cast< IRangedDistribution * >(argp2);
   ecode3 = SWIG_AsVal_double(swig_obj[2], &val3);
   if (!SWIG_IsOK(ecode3)) {
     SWIG_exception_fail(SWIG_ArgError(ecode3), "in method '" "AngularSpecScan_setAbsoluteWavelengthResolution" "', argument " "3"" of type '" "double""'");
   } 
   arg3 = static_cast< double >(val3);
-  (arg1)->setAbsoluteWavelengthResolution((RangedDistribution const &)*arg2,arg3);
+  (arg1)->setAbsoluteWavelengthResolution((IRangedDistribution const &)*arg2,arg3);
   resultobj = SWIG_Py_Void();
   return resultobj;
 fail:
@@ -38113,7 +38113,7 @@ fail:
 SWIGINTERN PyObject *_wrap_AngularSpecScan_setAbsoluteWavelengthResolution__SWIG_1(PyObject *SWIGUNUSEDPARM(self), Py_ssize_t nobjs, PyObject **swig_obj) {
   PyObject *resultobj = 0;
   AngularSpecScan *arg1 = (AngularSpecScan *) 0 ;
-  RangedDistribution *arg2 = 0 ;
+  IRangedDistribution *arg2 = 0 ;
   std::vector< double,std::allocator< double > > *arg3 = 0 ;
   void *argp1 = 0 ;
   int res1 = 0 ;
@@ -38127,14 +38127,14 @@ SWIGINTERN PyObject *_wrap_AngularSpecScan_setAbsoluteWavelengthResolution__SWIG
     SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "AngularSpecScan_setAbsoluteWavelengthResolution" "', argument " "1"" of type '" "AngularSpecScan *""'"); 
   }
   arg1 = reinterpret_cast< AngularSpecScan * >(argp1);
-  res2 = SWIG_ConvertPtr(swig_obj[1], &argp2, SWIGTYPE_p_RangedDistribution,  0  | 0);
+  res2 = SWIG_ConvertPtr(swig_obj[1], &argp2, SWIGTYPE_p_IRangedDistribution,  0  | 0);
   if (!SWIG_IsOK(res2)) {
-    SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "AngularSpecScan_setAbsoluteWavelengthResolution" "', argument " "2"" of type '" "RangedDistribution const &""'"); 
+    SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "AngularSpecScan_setAbsoluteWavelengthResolution" "', argument " "2"" of type '" "IRangedDistribution const &""'"); 
   }
   if (!argp2) {
-    SWIG_exception_fail(SWIG_ValueError, "invalid null reference " "in method '" "AngularSpecScan_setAbsoluteWavelengthResolution" "', argument " "2"" of type '" "RangedDistribution const &""'"); 
+    SWIG_exception_fail(SWIG_ValueError, "invalid null reference " "in method '" "AngularSpecScan_setAbsoluteWavelengthResolution" "', argument " "2"" of type '" "IRangedDistribution const &""'"); 
   }
-  arg2 = reinterpret_cast< RangedDistribution * >(argp2);
+  arg2 = reinterpret_cast< IRangedDistribution * >(argp2);
   {
     std::vector< double,std::allocator< double > > *ptr = (std::vector< double,std::allocator< double > > *)0;
     res3 = swig::asptr(swig_obj[2], &ptr);
@@ -38146,7 +38146,7 @@ SWIGINTERN PyObject *_wrap_AngularSpecScan_setAbsoluteWavelengthResolution__SWIG
     }
     arg3 = ptr;
   }
-  (arg1)->setAbsoluteWavelengthResolution((RangedDistribution const &)*arg2,(std::vector< double,std::allocator< double > > const &)*arg3);
+  (arg1)->setAbsoluteWavelengthResolution((IRangedDistribution const &)*arg2,(std::vector< double,std::allocator< double > > const &)*arg3);
   resultobj = SWIG_Py_Void();
   if (SWIG_IsNewObj(res3)) delete arg3;
   return resultobj;
@@ -38170,7 +38170,7 @@ SWIGINTERN PyObject *_wrap_AngularSpecScan_setAbsoluteWavelengthResolution(PyObj
     int res = SWIG_ConvertPtr(argv[0], &vptr, SWIGTYPE_p_AngularSpecScan, 0);
     _v = SWIG_CheckState(res);
     if (_v) {
-      int res = SWIG_ConvertPtr(argv[1], 0, SWIGTYPE_p_RangedDistribution, SWIG_POINTER_NO_NULL | 0);
+      int res = SWIG_ConvertPtr(argv[1], 0, SWIGTYPE_p_IRangedDistribution, SWIG_POINTER_NO_NULL | 0);
       _v = SWIG_CheckState(res);
       if (_v) {
         {
@@ -38189,7 +38189,7 @@ SWIGINTERN PyObject *_wrap_AngularSpecScan_setAbsoluteWavelengthResolution(PyObj
     int res = SWIG_ConvertPtr(argv[0], &vptr, SWIGTYPE_p_AngularSpecScan, 0);
     _v = SWIG_CheckState(res);
     if (_v) {
-      int res = SWIG_ConvertPtr(argv[1], 0, SWIGTYPE_p_RangedDistribution, SWIG_POINTER_NO_NULL | 0);
+      int res = SWIG_ConvertPtr(argv[1], 0, SWIGTYPE_p_IRangedDistribution, SWIG_POINTER_NO_NULL | 0);
       _v = SWIG_CheckState(res);
       if (_v) {
         int res = swig::asptr(argv[2], (std::vector< double,std::allocator< double > >**)(0));
@@ -38204,8 +38204,8 @@ SWIGINTERN PyObject *_wrap_AngularSpecScan_setAbsoluteWavelengthResolution(PyObj
 fail:
   SWIG_Python_RaiseOrModifyTypeError("Wrong number or type of arguments for overloaded function 'AngularSpecScan_setAbsoluteWavelengthResolution'.\n"
     "  Possible C/C++ prototypes are:\n"
-    "    AngularSpecScan::setAbsoluteWavelengthResolution(RangedDistribution const &,double)\n"
-    "    AngularSpecScan::setAbsoluteWavelengthResolution(RangedDistribution const &,std::vector< double,std::allocator< double > > const &)\n");
+    "    AngularSpecScan::setAbsoluteWavelengthResolution(IRangedDistribution const &,double)\n"
+    "    AngularSpecScan::setAbsoluteWavelengthResolution(IRangedDistribution const &,std::vector< double,std::allocator< double > > const &)\n");
   return 0;
 }
 
@@ -38245,7 +38245,7 @@ fail:
 SWIGINTERN PyObject *_wrap_AngularSpecScan_setRelativeAngularResolution__SWIG_0(PyObject *SWIGUNUSEDPARM(self), Py_ssize_t nobjs, PyObject **swig_obj) {
   PyObject *resultobj = 0;
   AngularSpecScan *arg1 = (AngularSpecScan *) 0 ;
-  RangedDistribution *arg2 = 0 ;
+  IRangedDistribution *arg2 = 0 ;
   double arg3 ;
   void *argp1 = 0 ;
   int res1 = 0 ;
@@ -38260,20 +38260,20 @@ SWIGINTERN PyObject *_wrap_AngularSpecScan_setRelativeAngularResolution__SWIG_0(
     SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "AngularSpecScan_setRelativeAngularResolution" "', argument " "1"" of type '" "AngularSpecScan *""'"); 
   }
   arg1 = reinterpret_cast< AngularSpecScan * >(argp1);
-  res2 = SWIG_ConvertPtr(swig_obj[1], &argp2, SWIGTYPE_p_RangedDistribution,  0  | 0);
+  res2 = SWIG_ConvertPtr(swig_obj[1], &argp2, SWIGTYPE_p_IRangedDistribution,  0  | 0);
   if (!SWIG_IsOK(res2)) {
-    SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "AngularSpecScan_setRelativeAngularResolution" "', argument " "2"" of type '" "RangedDistribution const &""'"); 
+    SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "AngularSpecScan_setRelativeAngularResolution" "', argument " "2"" of type '" "IRangedDistribution const &""'"); 
   }
   if (!argp2) {
-    SWIG_exception_fail(SWIG_ValueError, "invalid null reference " "in method '" "AngularSpecScan_setRelativeAngularResolution" "', argument " "2"" of type '" "RangedDistribution const &""'"); 
+    SWIG_exception_fail(SWIG_ValueError, "invalid null reference " "in method '" "AngularSpecScan_setRelativeAngularResolution" "', argument " "2"" of type '" "IRangedDistribution const &""'"); 
   }
-  arg2 = reinterpret_cast< RangedDistribution * >(argp2);
+  arg2 = reinterpret_cast< IRangedDistribution * >(argp2);
   ecode3 = SWIG_AsVal_double(swig_obj[2], &val3);
   if (!SWIG_IsOK(ecode3)) {
     SWIG_exception_fail(SWIG_ArgError(ecode3), "in method '" "AngularSpecScan_setRelativeAngularResolution" "', argument " "3"" of type '" "double""'");
   } 
   arg3 = static_cast< double >(val3);
-  (arg1)->setRelativeAngularResolution((RangedDistribution const &)*arg2,arg3);
+  (arg1)->setRelativeAngularResolution((IRangedDistribution const &)*arg2,arg3);
   resultobj = SWIG_Py_Void();
   return resultobj;
 fail:
@@ -38284,7 +38284,7 @@ fail:
 SWIGINTERN PyObject *_wrap_AngularSpecScan_setRelativeAngularResolution__SWIG_1(PyObject *SWIGUNUSEDPARM(self), Py_ssize_t nobjs, PyObject **swig_obj) {
   PyObject *resultobj = 0;
   AngularSpecScan *arg1 = (AngularSpecScan *) 0 ;
-  RangedDistribution *arg2 = 0 ;
+  IRangedDistribution *arg2 = 0 ;
   std::vector< double,std::allocator< double > > *arg3 = 0 ;
   void *argp1 = 0 ;
   int res1 = 0 ;
@@ -38298,14 +38298,14 @@ SWIGINTERN PyObject *_wrap_AngularSpecScan_setRelativeAngularResolution__SWIG_1(
     SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "AngularSpecScan_setRelativeAngularResolution" "', argument " "1"" of type '" "AngularSpecScan *""'"); 
   }
   arg1 = reinterpret_cast< AngularSpecScan * >(argp1);
-  res2 = SWIG_ConvertPtr(swig_obj[1], &argp2, SWIGTYPE_p_RangedDistribution,  0  | 0);
+  res2 = SWIG_ConvertPtr(swig_obj[1], &argp2, SWIGTYPE_p_IRangedDistribution,  0  | 0);
   if (!SWIG_IsOK(res2)) {
-    SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "AngularSpecScan_setRelativeAngularResolution" "', argument " "2"" of type '" "RangedDistribution const &""'"); 
+    SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "AngularSpecScan_setRelativeAngularResolution" "', argument " "2"" of type '" "IRangedDistribution const &""'"); 
   }
   if (!argp2) {
-    SWIG_exception_fail(SWIG_ValueError, "invalid null reference " "in method '" "AngularSpecScan_setRelativeAngularResolution" "', argument " "2"" of type '" "RangedDistribution const &""'"); 
+    SWIG_exception_fail(SWIG_ValueError, "invalid null reference " "in method '" "AngularSpecScan_setRelativeAngularResolution" "', argument " "2"" of type '" "IRangedDistribution const &""'"); 
   }
-  arg2 = reinterpret_cast< RangedDistribution * >(argp2);
+  arg2 = reinterpret_cast< IRangedDistribution * >(argp2);
   {
     std::vector< double,std::allocator< double > > *ptr = (std::vector< double,std::allocator< double > > *)0;
     res3 = swig::asptr(swig_obj[2], &ptr);
@@ -38317,7 +38317,7 @@ SWIGINTERN PyObject *_wrap_AngularSpecScan_setRelativeAngularResolution__SWIG_1(
     }
     arg3 = ptr;
   }
-  (arg1)->setRelativeAngularResolution((RangedDistribution const &)*arg2,(std::vector< double,std::allocator< double > > const &)*arg3);
+  (arg1)->setRelativeAngularResolution((IRangedDistribution const &)*arg2,(std::vector< double,std::allocator< double > > const &)*arg3);
   resultobj = SWIG_Py_Void();
   if (SWIG_IsNewObj(res3)) delete arg3;
   return resultobj;
@@ -38341,7 +38341,7 @@ SWIGINTERN PyObject *_wrap_AngularSpecScan_setRelativeAngularResolution(PyObject
     int res = SWIG_ConvertPtr(argv[0], &vptr, SWIGTYPE_p_AngularSpecScan, 0);
     _v = SWIG_CheckState(res);
     if (_v) {
-      int res = SWIG_ConvertPtr(argv[1], 0, SWIGTYPE_p_RangedDistribution, SWIG_POINTER_NO_NULL | 0);
+      int res = SWIG_ConvertPtr(argv[1], 0, SWIGTYPE_p_IRangedDistribution, SWIG_POINTER_NO_NULL | 0);
       _v = SWIG_CheckState(res);
       if (_v) {
         {
@@ -38360,7 +38360,7 @@ SWIGINTERN PyObject *_wrap_AngularSpecScan_setRelativeAngularResolution(PyObject
     int res = SWIG_ConvertPtr(argv[0], &vptr, SWIGTYPE_p_AngularSpecScan, 0);
     _v = SWIG_CheckState(res);
     if (_v) {
-      int res = SWIG_ConvertPtr(argv[1], 0, SWIGTYPE_p_RangedDistribution, SWIG_POINTER_NO_NULL | 0);
+      int res = SWIG_ConvertPtr(argv[1], 0, SWIGTYPE_p_IRangedDistribution, SWIG_POINTER_NO_NULL | 0);
       _v = SWIG_CheckState(res);
       if (_v) {
         int res = swig::asptr(argv[2], (std::vector< double,std::allocator< double > >**)(0));
@@ -38375,8 +38375,8 @@ SWIGINTERN PyObject *_wrap_AngularSpecScan_setRelativeAngularResolution(PyObject
 fail:
   SWIG_Python_RaiseOrModifyTypeError("Wrong number or type of arguments for overloaded function 'AngularSpecScan_setRelativeAngularResolution'.\n"
     "  Possible C/C++ prototypes are:\n"
-    "    AngularSpecScan::setRelativeAngularResolution(RangedDistribution const &,double)\n"
-    "    AngularSpecScan::setRelativeAngularResolution(RangedDistribution const &,std::vector< double,std::allocator< double > > const &)\n");
+    "    AngularSpecScan::setRelativeAngularResolution(IRangedDistribution const &,double)\n"
+    "    AngularSpecScan::setRelativeAngularResolution(IRangedDistribution const &,std::vector< double,std::allocator< double > > const &)\n");
   return 0;
 }
 
@@ -38384,7 +38384,7 @@ fail:
 SWIGINTERN PyObject *_wrap_AngularSpecScan_setAbsoluteAngularResolution__SWIG_0(PyObject *SWIGUNUSEDPARM(self), Py_ssize_t nobjs, PyObject **swig_obj) {
   PyObject *resultobj = 0;
   AngularSpecScan *arg1 = (AngularSpecScan *) 0 ;
-  RangedDistribution *arg2 = 0 ;
+  IRangedDistribution *arg2 = 0 ;
   double arg3 ;
   void *argp1 = 0 ;
   int res1 = 0 ;
@@ -38399,20 +38399,20 @@ SWIGINTERN PyObject *_wrap_AngularSpecScan_setAbsoluteAngularResolution__SWIG_0(
     SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "AngularSpecScan_setAbsoluteAngularResolution" "', argument " "1"" of type '" "AngularSpecScan *""'"); 
   }
   arg1 = reinterpret_cast< AngularSpecScan * >(argp1);
-  res2 = SWIG_ConvertPtr(swig_obj[1], &argp2, SWIGTYPE_p_RangedDistribution,  0  | 0);
+  res2 = SWIG_ConvertPtr(swig_obj[1], &argp2, SWIGTYPE_p_IRangedDistribution,  0  | 0);
   if (!SWIG_IsOK(res2)) {
-    SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "AngularSpecScan_setAbsoluteAngularResolution" "', argument " "2"" of type '" "RangedDistribution const &""'"); 
+    SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "AngularSpecScan_setAbsoluteAngularResolution" "', argument " "2"" of type '" "IRangedDistribution const &""'"); 
   }
   if (!argp2) {
-    SWIG_exception_fail(SWIG_ValueError, "invalid null reference " "in method '" "AngularSpecScan_setAbsoluteAngularResolution" "', argument " "2"" of type '" "RangedDistribution const &""'"); 
+    SWIG_exception_fail(SWIG_ValueError, "invalid null reference " "in method '" "AngularSpecScan_setAbsoluteAngularResolution" "', argument " "2"" of type '" "IRangedDistribution const &""'"); 
   }
-  arg2 = reinterpret_cast< RangedDistribution * >(argp2);
+  arg2 = reinterpret_cast< IRangedDistribution * >(argp2);
   ecode3 = SWIG_AsVal_double(swig_obj[2], &val3);
   if (!SWIG_IsOK(ecode3)) {
     SWIG_exception_fail(SWIG_ArgError(ecode3), "in method '" "AngularSpecScan_setAbsoluteAngularResolution" "', argument " "3"" of type '" "double""'");
   } 
   arg3 = static_cast< double >(val3);
-  (arg1)->setAbsoluteAngularResolution((RangedDistribution const &)*arg2,arg3);
+  (arg1)->setAbsoluteAngularResolution((IRangedDistribution const &)*arg2,arg3);
   resultobj = SWIG_Py_Void();
   return resultobj;
 fail:
@@ -38423,7 +38423,7 @@ fail:
 SWIGINTERN PyObject *_wrap_AngularSpecScan_setAbsoluteAngularResolution__SWIG_1(PyObject *SWIGUNUSEDPARM(self), Py_ssize_t nobjs, PyObject **swig_obj) {
   PyObject *resultobj = 0;
   AngularSpecScan *arg1 = (AngularSpecScan *) 0 ;
-  RangedDistribution *arg2 = 0 ;
+  IRangedDistribution *arg2 = 0 ;
   std::vector< double,std::allocator< double > > *arg3 = 0 ;
   void *argp1 = 0 ;
   int res1 = 0 ;
@@ -38437,14 +38437,14 @@ SWIGINTERN PyObject *_wrap_AngularSpecScan_setAbsoluteAngularResolution__SWIG_1(
     SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "AngularSpecScan_setAbsoluteAngularResolution" "', argument " "1"" of type '" "AngularSpecScan *""'"); 
   }
   arg1 = reinterpret_cast< AngularSpecScan * >(argp1);
-  res2 = SWIG_ConvertPtr(swig_obj[1], &argp2, SWIGTYPE_p_RangedDistribution,  0  | 0);
+  res2 = SWIG_ConvertPtr(swig_obj[1], &argp2, SWIGTYPE_p_IRangedDistribution,  0  | 0);
   if (!SWIG_IsOK(res2)) {
-    SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "AngularSpecScan_setAbsoluteAngularResolution" "', argument " "2"" of type '" "RangedDistribution const &""'"); 
+    SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "AngularSpecScan_setAbsoluteAngularResolution" "', argument " "2"" of type '" "IRangedDistribution const &""'"); 
   }
   if (!argp2) {
-    SWIG_exception_fail(SWIG_ValueError, "invalid null reference " "in method '" "AngularSpecScan_setAbsoluteAngularResolution" "', argument " "2"" of type '" "RangedDistribution const &""'"); 
+    SWIG_exception_fail(SWIG_ValueError, "invalid null reference " "in method '" "AngularSpecScan_setAbsoluteAngularResolution" "', argument " "2"" of type '" "IRangedDistribution const &""'"); 
   }
-  arg2 = reinterpret_cast< RangedDistribution * >(argp2);
+  arg2 = reinterpret_cast< IRangedDistribution * >(argp2);
   {
     std::vector< double,std::allocator< double > > *ptr = (std::vector< double,std::allocator< double > > *)0;
     res3 = swig::asptr(swig_obj[2], &ptr);
@@ -38456,7 +38456,7 @@ SWIGINTERN PyObject *_wrap_AngularSpecScan_setAbsoluteAngularResolution__SWIG_1(
     }
     arg3 = ptr;
   }
-  (arg1)->setAbsoluteAngularResolution((RangedDistribution const &)*arg2,(std::vector< double,std::allocator< double > > const &)*arg3);
+  (arg1)->setAbsoluteAngularResolution((IRangedDistribution const &)*arg2,(std::vector< double,std::allocator< double > > const &)*arg3);
   resultobj = SWIG_Py_Void();
   if (SWIG_IsNewObj(res3)) delete arg3;
   return resultobj;
@@ -38480,7 +38480,7 @@ SWIGINTERN PyObject *_wrap_AngularSpecScan_setAbsoluteAngularResolution(PyObject
     int res = SWIG_ConvertPtr(argv[0], &vptr, SWIGTYPE_p_AngularSpecScan, 0);
     _v = SWIG_CheckState(res);
     if (_v) {
-      int res = SWIG_ConvertPtr(argv[1], 0, SWIGTYPE_p_RangedDistribution, SWIG_POINTER_NO_NULL | 0);
+      int res = SWIG_ConvertPtr(argv[1], 0, SWIGTYPE_p_IRangedDistribution, SWIG_POINTER_NO_NULL | 0);
       _v = SWIG_CheckState(res);
       if (_v) {
         {
@@ -38499,7 +38499,7 @@ SWIGINTERN PyObject *_wrap_AngularSpecScan_setAbsoluteAngularResolution(PyObject
     int res = SWIG_ConvertPtr(argv[0], &vptr, SWIGTYPE_p_AngularSpecScan, 0);
     _v = SWIG_CheckState(res);
     if (_v) {
-      int res = SWIG_ConvertPtr(argv[1], 0, SWIGTYPE_p_RangedDistribution, SWIG_POINTER_NO_NULL | 0);
+      int res = SWIG_ConvertPtr(argv[1], 0, SWIGTYPE_p_IRangedDistribution, SWIG_POINTER_NO_NULL | 0);
       _v = SWIG_CheckState(res);
       if (_v) {
         int res = swig::asptr(argv[2], (std::vector< double,std::allocator< double > >**)(0));
@@ -38514,8 +38514,8 @@ SWIGINTERN PyObject *_wrap_AngularSpecScan_setAbsoluteAngularResolution(PyObject
 fail:
   SWIG_Python_RaiseOrModifyTypeError("Wrong number or type of arguments for overloaded function 'AngularSpecScan_setAbsoluteAngularResolution'.\n"
     "  Possible C/C++ prototypes are:\n"
-    "    AngularSpecScan::setAbsoluteAngularResolution(RangedDistribution const &,double)\n"
-    "    AngularSpecScan::setAbsoluteAngularResolution(RangedDistribution const &,std::vector< double,std::allocator< double > > const &)\n");
+    "    AngularSpecScan::setAbsoluteAngularResolution(IRangedDistribution const &,double)\n"
+    "    AngularSpecScan::setAbsoluteAngularResolution(IRangedDistribution const &,std::vector< double,std::allocator< double > > const &)\n");
   return 0;
 }
 
@@ -38717,6 +38717,29 @@ fail:
 }
 
 
+SWIGINTERN PyObject *_wrap_QSpecScan_resolution(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *resultobj = 0;
+  QSpecScan *arg1 = (QSpecScan *) 0 ;
+  void *argp1 = 0 ;
+  int res1 = 0 ;
+  PyObject *swig_obj[1] ;
+  ScanResolution *result = 0 ;
+  
+  if (!args) SWIG_fail;
+  swig_obj[0] = args;
+  res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_QSpecScan, 0 |  0 );
+  if (!SWIG_IsOK(res1)) {
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "QSpecScan_resolution" "', argument " "1"" of type '" "QSpecScan const *""'"); 
+  }
+  arg1 = reinterpret_cast< QSpecScan * >(argp1);
+  result = (ScanResolution *)((QSpecScan const *)arg1)->resolution();
+  resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_ScanResolution, 0 |  0 );
+  return resultobj;
+fail:
+  return NULL;
+}
+
+
 SWIGINTERN PyObject *_wrap_QSpecScan_setQResolution(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
   PyObject *resultobj = 0;
   QSpecScan *arg1 = (QSpecScan *) 0 ;
@@ -38752,7 +38775,7 @@ fail:
 SWIGINTERN PyObject *_wrap_QSpecScan_setRelativeQResolution__SWIG_0(PyObject *SWIGUNUSEDPARM(self), Py_ssize_t nobjs, PyObject **swig_obj) {
   PyObject *resultobj = 0;
   QSpecScan *arg1 = (QSpecScan *) 0 ;
-  RangedDistribution *arg2 = 0 ;
+  IRangedDistribution *arg2 = 0 ;
   double arg3 ;
   void *argp1 = 0 ;
   int res1 = 0 ;
@@ -38767,20 +38790,20 @@ SWIGINTERN PyObject *_wrap_QSpecScan_setRelativeQResolution__SWIG_0(PyObject *SW
     SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "QSpecScan_setRelativeQResolution" "', argument " "1"" of type '" "QSpecScan *""'"); 
   }
   arg1 = reinterpret_cast< QSpecScan * >(argp1);
-  res2 = SWIG_ConvertPtr(swig_obj[1], &argp2, SWIGTYPE_p_RangedDistribution,  0  | 0);
+  res2 = SWIG_ConvertPtr(swig_obj[1], &argp2, SWIGTYPE_p_IRangedDistribution,  0  | 0);
   if (!SWIG_IsOK(res2)) {
-    SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "QSpecScan_setRelativeQResolution" "', argument " "2"" of type '" "RangedDistribution const &""'"); 
+    SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "QSpecScan_setRelativeQResolution" "', argument " "2"" of type '" "IRangedDistribution const &""'"); 
   }
   if (!argp2) {
-    SWIG_exception_fail(SWIG_ValueError, "invalid null reference " "in method '" "QSpecScan_setRelativeQResolution" "', argument " "2"" of type '" "RangedDistribution const &""'"); 
+    SWIG_exception_fail(SWIG_ValueError, "invalid null reference " "in method '" "QSpecScan_setRelativeQResolution" "', argument " "2"" of type '" "IRangedDistribution const &""'"); 
   }
-  arg2 = reinterpret_cast< RangedDistribution * >(argp2);
+  arg2 = reinterpret_cast< IRangedDistribution * >(argp2);
   ecode3 = SWIG_AsVal_double(swig_obj[2], &val3);
   if (!SWIG_IsOK(ecode3)) {
     SWIG_exception_fail(SWIG_ArgError(ecode3), "in method '" "QSpecScan_setRelativeQResolution" "', argument " "3"" of type '" "double""'");
   } 
   arg3 = static_cast< double >(val3);
-  (arg1)->setRelativeQResolution((RangedDistribution const &)*arg2,arg3);
+  (arg1)->setRelativeQResolution((IRangedDistribution const &)*arg2,arg3);
   resultobj = SWIG_Py_Void();
   return resultobj;
 fail:
@@ -38791,7 +38814,7 @@ fail:
 SWIGINTERN PyObject *_wrap_QSpecScan_setRelativeQResolution__SWIG_1(PyObject *SWIGUNUSEDPARM(self), Py_ssize_t nobjs, PyObject **swig_obj) {
   PyObject *resultobj = 0;
   QSpecScan *arg1 = (QSpecScan *) 0 ;
-  RangedDistribution *arg2 = 0 ;
+  IRangedDistribution *arg2 = 0 ;
   std::vector< double,std::allocator< double > > *arg3 = 0 ;
   void *argp1 = 0 ;
   int res1 = 0 ;
@@ -38805,14 +38828,14 @@ SWIGINTERN PyObject *_wrap_QSpecScan_setRelativeQResolution__SWIG_1(PyObject *SW
     SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "QSpecScan_setRelativeQResolution" "', argument " "1"" of type '" "QSpecScan *""'"); 
   }
   arg1 = reinterpret_cast< QSpecScan * >(argp1);
-  res2 = SWIG_ConvertPtr(swig_obj[1], &argp2, SWIGTYPE_p_RangedDistribution,  0  | 0);
+  res2 = SWIG_ConvertPtr(swig_obj[1], &argp2, SWIGTYPE_p_IRangedDistribution,  0  | 0);
   if (!SWIG_IsOK(res2)) {
-    SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "QSpecScan_setRelativeQResolution" "', argument " "2"" of type '" "RangedDistribution const &""'"); 
+    SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "QSpecScan_setRelativeQResolution" "', argument " "2"" of type '" "IRangedDistribution const &""'"); 
   }
   if (!argp2) {
-    SWIG_exception_fail(SWIG_ValueError, "invalid null reference " "in method '" "QSpecScan_setRelativeQResolution" "', argument " "2"" of type '" "RangedDistribution const &""'"); 
+    SWIG_exception_fail(SWIG_ValueError, "invalid null reference " "in method '" "QSpecScan_setRelativeQResolution" "', argument " "2"" of type '" "IRangedDistribution const &""'"); 
   }
-  arg2 = reinterpret_cast< RangedDistribution * >(argp2);
+  arg2 = reinterpret_cast< IRangedDistribution * >(argp2);
   {
     std::vector< double,std::allocator< double > > *ptr = (std::vector< double,std::allocator< double > > *)0;
     res3 = swig::asptr(swig_obj[2], &ptr);
@@ -38824,7 +38847,7 @@ SWIGINTERN PyObject *_wrap_QSpecScan_setRelativeQResolution__SWIG_1(PyObject *SW
     }
     arg3 = ptr;
   }
-  (arg1)->setRelativeQResolution((RangedDistribution const &)*arg2,(std::vector< double,std::allocator< double > > const &)*arg3);
+  (arg1)->setRelativeQResolution((IRangedDistribution const &)*arg2,(std::vector< double,std::allocator< double > > const &)*arg3);
   resultobj = SWIG_Py_Void();
   if (SWIG_IsNewObj(res3)) delete arg3;
   return resultobj;
@@ -38848,7 +38871,7 @@ SWIGINTERN PyObject *_wrap_QSpecScan_setRelativeQResolution(PyObject *self, PyOb
     int res = SWIG_ConvertPtr(argv[0], &vptr, SWIGTYPE_p_QSpecScan, 0);
     _v = SWIG_CheckState(res);
     if (_v) {
-      int res = SWIG_ConvertPtr(argv[1], 0, SWIGTYPE_p_RangedDistribution, SWIG_POINTER_NO_NULL | 0);
+      int res = SWIG_ConvertPtr(argv[1], 0, SWIGTYPE_p_IRangedDistribution, SWIG_POINTER_NO_NULL | 0);
       _v = SWIG_CheckState(res);
       if (_v) {
         {
@@ -38867,7 +38890,7 @@ SWIGINTERN PyObject *_wrap_QSpecScan_setRelativeQResolution(PyObject *self, PyOb
     int res = SWIG_ConvertPtr(argv[0], &vptr, SWIGTYPE_p_QSpecScan, 0);
     _v = SWIG_CheckState(res);
     if (_v) {
-      int res = SWIG_ConvertPtr(argv[1], 0, SWIGTYPE_p_RangedDistribution, SWIG_POINTER_NO_NULL | 0);
+      int res = SWIG_ConvertPtr(argv[1], 0, SWIGTYPE_p_IRangedDistribution, SWIG_POINTER_NO_NULL | 0);
       _v = SWIG_CheckState(res);
       if (_v) {
         int res = swig::asptr(argv[2], (std::vector< double,std::allocator< double > >**)(0));
@@ -38882,8 +38905,8 @@ SWIGINTERN PyObject *_wrap_QSpecScan_setRelativeQResolution(PyObject *self, PyOb
 fail:
   SWIG_Python_RaiseOrModifyTypeError("Wrong number or type of arguments for overloaded function 'QSpecScan_setRelativeQResolution'.\n"
     "  Possible C/C++ prototypes are:\n"
-    "    QSpecScan::setRelativeQResolution(RangedDistribution const &,double)\n"
-    "    QSpecScan::setRelativeQResolution(RangedDistribution const &,std::vector< double,std::allocator< double > > const &)\n");
+    "    QSpecScan::setRelativeQResolution(IRangedDistribution const &,double)\n"
+    "    QSpecScan::setRelativeQResolution(IRangedDistribution const &,std::vector< double,std::allocator< double > > const &)\n");
   return 0;
 }
 
@@ -38891,7 +38914,7 @@ fail:
 SWIGINTERN PyObject *_wrap_QSpecScan_setAbsoluteQResolution__SWIG_0(PyObject *SWIGUNUSEDPARM(self), Py_ssize_t nobjs, PyObject **swig_obj) {
   PyObject *resultobj = 0;
   QSpecScan *arg1 = (QSpecScan *) 0 ;
-  RangedDistribution *arg2 = 0 ;
+  IRangedDistribution *arg2 = 0 ;
   double arg3 ;
   void *argp1 = 0 ;
   int res1 = 0 ;
@@ -38906,20 +38929,20 @@ SWIGINTERN PyObject *_wrap_QSpecScan_setAbsoluteQResolution__SWIG_0(PyObject *SW
     SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "QSpecScan_setAbsoluteQResolution" "', argument " "1"" of type '" "QSpecScan *""'"); 
   }
   arg1 = reinterpret_cast< QSpecScan * >(argp1);
-  res2 = SWIG_ConvertPtr(swig_obj[1], &argp2, SWIGTYPE_p_RangedDistribution,  0  | 0);
+  res2 = SWIG_ConvertPtr(swig_obj[1], &argp2, SWIGTYPE_p_IRangedDistribution,  0  | 0);
   if (!SWIG_IsOK(res2)) {
-    SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "QSpecScan_setAbsoluteQResolution" "', argument " "2"" of type '" "RangedDistribution const &""'"); 
+    SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "QSpecScan_setAbsoluteQResolution" "', argument " "2"" of type '" "IRangedDistribution const &""'"); 
   }
   if (!argp2) {
-    SWIG_exception_fail(SWIG_ValueError, "invalid null reference " "in method '" "QSpecScan_setAbsoluteQResolution" "', argument " "2"" of type '" "RangedDistribution const &""'"); 
+    SWIG_exception_fail(SWIG_ValueError, "invalid null reference " "in method '" "QSpecScan_setAbsoluteQResolution" "', argument " "2"" of type '" "IRangedDistribution const &""'"); 
   }
-  arg2 = reinterpret_cast< RangedDistribution * >(argp2);
+  arg2 = reinterpret_cast< IRangedDistribution * >(argp2);
   ecode3 = SWIG_AsVal_double(swig_obj[2], &val3);
   if (!SWIG_IsOK(ecode3)) {
     SWIG_exception_fail(SWIG_ArgError(ecode3), "in method '" "QSpecScan_setAbsoluteQResolution" "', argument " "3"" of type '" "double""'");
   } 
   arg3 = static_cast< double >(val3);
-  (arg1)->setAbsoluteQResolution((RangedDistribution const &)*arg2,arg3);
+  (arg1)->setAbsoluteQResolution((IRangedDistribution const &)*arg2,arg3);
   resultobj = SWIG_Py_Void();
   return resultobj;
 fail:
@@ -38930,7 +38953,7 @@ fail:
 SWIGINTERN PyObject *_wrap_QSpecScan_setAbsoluteQResolution__SWIG_1(PyObject *SWIGUNUSEDPARM(self), Py_ssize_t nobjs, PyObject **swig_obj) {
   PyObject *resultobj = 0;
   QSpecScan *arg1 = (QSpecScan *) 0 ;
-  RangedDistribution *arg2 = 0 ;
+  IRangedDistribution *arg2 = 0 ;
   std::vector< double,std::allocator< double > > *arg3 = 0 ;
   void *argp1 = 0 ;
   int res1 = 0 ;
@@ -38944,14 +38967,14 @@ SWIGINTERN PyObject *_wrap_QSpecScan_setAbsoluteQResolution__SWIG_1(PyObject *SW
     SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "QSpecScan_setAbsoluteQResolution" "', argument " "1"" of type '" "QSpecScan *""'"); 
   }
   arg1 = reinterpret_cast< QSpecScan * >(argp1);
-  res2 = SWIG_ConvertPtr(swig_obj[1], &argp2, SWIGTYPE_p_RangedDistribution,  0  | 0);
+  res2 = SWIG_ConvertPtr(swig_obj[1], &argp2, SWIGTYPE_p_IRangedDistribution,  0  | 0);
   if (!SWIG_IsOK(res2)) {
-    SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "QSpecScan_setAbsoluteQResolution" "', argument " "2"" of type '" "RangedDistribution const &""'"); 
+    SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "QSpecScan_setAbsoluteQResolution" "', argument " "2"" of type '" "IRangedDistribution const &""'"); 
   }
   if (!argp2) {
-    SWIG_exception_fail(SWIG_ValueError, "invalid null reference " "in method '" "QSpecScan_setAbsoluteQResolution" "', argument " "2"" of type '" "RangedDistribution const &""'"); 
+    SWIG_exception_fail(SWIG_ValueError, "invalid null reference " "in method '" "QSpecScan_setAbsoluteQResolution" "', argument " "2"" of type '" "IRangedDistribution const &""'"); 
   }
-  arg2 = reinterpret_cast< RangedDistribution * >(argp2);
+  arg2 = reinterpret_cast< IRangedDistribution * >(argp2);
   {
     std::vector< double,std::allocator< double > > *ptr = (std::vector< double,std::allocator< double > > *)0;
     res3 = swig::asptr(swig_obj[2], &ptr);
@@ -38963,7 +38986,7 @@ SWIGINTERN PyObject *_wrap_QSpecScan_setAbsoluteQResolution__SWIG_1(PyObject *SW
     }
     arg3 = ptr;
   }
-  (arg1)->setAbsoluteQResolution((RangedDistribution const &)*arg2,(std::vector< double,std::allocator< double > > const &)*arg3);
+  (arg1)->setAbsoluteQResolution((IRangedDistribution const &)*arg2,(std::vector< double,std::allocator< double > > const &)*arg3);
   resultobj = SWIG_Py_Void();
   if (SWIG_IsNewObj(res3)) delete arg3;
   return resultobj;
@@ -38987,7 +39010,7 @@ SWIGINTERN PyObject *_wrap_QSpecScan_setAbsoluteQResolution(PyObject *self, PyOb
     int res = SWIG_ConvertPtr(argv[0], &vptr, SWIGTYPE_p_QSpecScan, 0);
     _v = SWIG_CheckState(res);
     if (_v) {
-      int res = SWIG_ConvertPtr(argv[1], 0, SWIGTYPE_p_RangedDistribution, SWIG_POINTER_NO_NULL | 0);
+      int res = SWIG_ConvertPtr(argv[1], 0, SWIGTYPE_p_IRangedDistribution, SWIG_POINTER_NO_NULL | 0);
       _v = SWIG_CheckState(res);
       if (_v) {
         {
@@ -39006,7 +39029,7 @@ SWIGINTERN PyObject *_wrap_QSpecScan_setAbsoluteQResolution(PyObject *self, PyOb
     int res = SWIG_ConvertPtr(argv[0], &vptr, SWIGTYPE_p_QSpecScan, 0);
     _v = SWIG_CheckState(res);
     if (_v) {
-      int res = SWIG_ConvertPtr(argv[1], 0, SWIGTYPE_p_RangedDistribution, SWIG_POINTER_NO_NULL | 0);
+      int res = SWIG_ConvertPtr(argv[1], 0, SWIGTYPE_p_IRangedDistribution, SWIG_POINTER_NO_NULL | 0);
       _v = SWIG_CheckState(res);
       if (_v) {
         int res = swig::asptr(argv[2], (std::vector< double,std::allocator< double > >**)(0));
@@ -39021,8 +39044,8 @@ SWIGINTERN PyObject *_wrap_QSpecScan_setAbsoluteQResolution(PyObject *self, PyOb
 fail:
   SWIG_Python_RaiseOrModifyTypeError("Wrong number or type of arguments for overloaded function 'QSpecScan_setAbsoluteQResolution'.\n"
     "  Possible C/C++ prototypes are:\n"
-    "    QSpecScan::setAbsoluteQResolution(RangedDistribution const &,double)\n"
-    "    QSpecScan::setAbsoluteQResolution(RangedDistribution const &,std::vector< double,std::allocator< double > > const &)\n");
+    "    QSpecScan::setAbsoluteQResolution(IRangedDistribution const &,double)\n"
+    "    QSpecScan::setAbsoluteQResolution(IRangedDistribution const &,std::vector< double,std::allocator< double > > const &)\n");
   return 0;
 }
 
@@ -42349,32 +42372,6 @@ fail:
 }
 
 
-SWIGINTERN PyObject *_wrap_generatePyExportTest(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
-  ISimulation *arg1 = 0 ;
-  void *argp1 = 0 ;
-  int res1 = 0 ;
-  PyObject *swig_obj[1] ;
-  std::string result;
-  
-  if (!args) SWIG_fail;
-  swig_obj[0] = args;
-  res1 = SWIG_ConvertPtr(swig_obj[0], &argp1, SWIGTYPE_p_ISimulation,  0  | 0);
-  if (!SWIG_IsOK(res1)) {
-    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "generatePyExportTest" "', argument " "1"" of type '" "ISimulation const &""'"); 
-  }
-  if (!argp1) {
-    SWIG_exception_fail(SWIG_ValueError, "invalid null reference " "in method '" "generatePyExportTest" "', argument " "1"" of type '" "ISimulation const &""'"); 
-  }
-  arg1 = reinterpret_cast< ISimulation * >(argp1);
-  result = ExportToPython::generatePyExportTest((ISimulation const &)*arg1);
-  resultobj = SWIG_From_std_string(static_cast< std::string >(result));
-  return resultobj;
-fail:
-  return NULL;
-}
-
-
 static PyMethodDef SwigMethods[] = {
 	 { "SWIG_PyInstanceMethod_New", SWIG_PyInstanceMethod_New, METH_O, NULL},
 	 { "delete_SwigPyIterator", _wrap_delete_SwigPyIterator, METH_O, "delete_SwigPyIterator(SwigPyIterator self)"},
@@ -43660,19 +43657,19 @@ static PyMethodDef SwigMethods[] = {
 		"\n"
 		""},
 	 { "AngularSpecScan_setRelativeWavelengthResolution", _wrap_AngularSpecScan_setRelativeWavelengthResolution, METH_VARARGS, "\n"
-		"AngularSpecScan_setRelativeWavelengthResolution(AngularSpecScan self, RangedDistribution const & distr, double rel_dev)\n"
-		"AngularSpecScan_setRelativeWavelengthResolution(AngularSpecScan self, RangedDistribution const & distr, vdouble1d_t rel_dev)\n"
-		"void AngularSpecScan::setRelativeWavelengthResolution(const RangedDistribution &distr, const std::vector< double > &rel_dev)\n"
+		"AngularSpecScan_setRelativeWavelengthResolution(AngularSpecScan self, IRangedDistribution const & distr, double rel_dev)\n"
+		"AngularSpecScan_setRelativeWavelengthResolution(AngularSpecScan self, IRangedDistribution const & distr, vdouble1d_t rel_dev)\n"
+		"void AngularSpecScan::setRelativeWavelengthResolution(const IRangedDistribution &distr, const std::vector< double > &rel_dev)\n"
 		"\n"
-		"Sets wavelength resolution values via RangedDistribution and values of relative deviations (that is,  rel_dev equals standard deviation divided by the mean value).  rel_dev can be either single-valued or a numpy array. In the latter case the length of the array should coinside with the length of the inclination angle axis. \n"
+		"Sets wavelength resolution values via IRangedDistribution and values of relative deviations (that is,  rel_dev equals standard deviation divided by the mean value).  rel_dev can be either single-valued or a numpy array. In the latter case the length of the array should coinside with the length of the inclination angle axis. \n"
 		"\n"
 		""},
 	 { "AngularSpecScan_setAbsoluteWavelengthResolution", _wrap_AngularSpecScan_setAbsoluteWavelengthResolution, METH_VARARGS, "\n"
-		"AngularSpecScan_setAbsoluteWavelengthResolution(AngularSpecScan self, RangedDistribution const & distr, double std_dev)\n"
-		"AngularSpecScan_setAbsoluteWavelengthResolution(AngularSpecScan self, RangedDistribution const & distr, vdouble1d_t std_dev)\n"
-		"void AngularSpecScan::setAbsoluteWavelengthResolution(const RangedDistribution &distr, const std::vector< double > &std_dev)\n"
+		"AngularSpecScan_setAbsoluteWavelengthResolution(AngularSpecScan self, IRangedDistribution const & distr, double std_dev)\n"
+		"AngularSpecScan_setAbsoluteWavelengthResolution(AngularSpecScan self, IRangedDistribution const & distr, vdouble1d_t std_dev)\n"
+		"void AngularSpecScan::setAbsoluteWavelengthResolution(const IRangedDistribution &distr, const std::vector< double > &std_dev)\n"
 		"\n"
-		"Sets wavelength resolution values via RangedDistribution and values of standard deviations.  std_dev can be either single-valued or a numpy array. In the latter case the length of the array should coinside with the length of the inclination angle axis. \n"
+		"Sets wavelength resolution values via IRangedDistribution and values of standard deviations.  std_dev can be either single-valued or a numpy array. In the latter case the length of the array should coinside with the length of the inclination angle axis. \n"
 		"\n"
 		""},
 	 { "AngularSpecScan_setAngleResolution", _wrap_AngularSpecScan_setAngleResolution, METH_VARARGS, "\n"
@@ -43683,19 +43680,19 @@ static PyMethodDef SwigMethods[] = {
 		"\n"
 		""},
 	 { "AngularSpecScan_setRelativeAngularResolution", _wrap_AngularSpecScan_setRelativeAngularResolution, METH_VARARGS, "\n"
-		"AngularSpecScan_setRelativeAngularResolution(AngularSpecScan self, RangedDistribution const & distr, double rel_dev)\n"
-		"AngularSpecScan_setRelativeAngularResolution(AngularSpecScan self, RangedDistribution const & distr, vdouble1d_t rel_dev)\n"
-		"void AngularSpecScan::setRelativeAngularResolution(const RangedDistribution &distr, const std::vector< double > &rel_dev)\n"
+		"AngularSpecScan_setRelativeAngularResolution(AngularSpecScan self, IRangedDistribution const & distr, double rel_dev)\n"
+		"AngularSpecScan_setRelativeAngularResolution(AngularSpecScan self, IRangedDistribution const & distr, vdouble1d_t rel_dev)\n"
+		"void AngularSpecScan::setRelativeAngularResolution(const IRangedDistribution &distr, const std::vector< double > &rel_dev)\n"
 		"\n"
-		"Sets angular resolution values via RangedDistribution and values of relative deviations (that is,  rel_dev equals standard deviation divided by the mean value).  rel_dev can be either single-valued or a numpy array. In the latter case the length of the array should coinside with the length of the inclination angle axis. \n"
+		"Sets angular resolution values via IRangedDistribution and values of relative deviations (that is,  rel_dev equals standard deviation divided by the mean value).  rel_dev can be either single-valued or a numpy array. In the latter case the length of the array should coinside with the length of the inclination angle axis. \n"
 		"\n"
 		""},
 	 { "AngularSpecScan_setAbsoluteAngularResolution", _wrap_AngularSpecScan_setAbsoluteAngularResolution, METH_VARARGS, "\n"
-		"AngularSpecScan_setAbsoluteAngularResolution(AngularSpecScan self, RangedDistribution const & distr, double std_dev)\n"
-		"AngularSpecScan_setAbsoluteAngularResolution(AngularSpecScan self, RangedDistribution const & distr, vdouble1d_t std_dev)\n"
-		"void AngularSpecScan::setAbsoluteAngularResolution(const RangedDistribution &distr, const std::vector< double > &std_dev)\n"
+		"AngularSpecScan_setAbsoluteAngularResolution(AngularSpecScan self, IRangedDistribution const & distr, double std_dev)\n"
+		"AngularSpecScan_setAbsoluteAngularResolution(AngularSpecScan self, IRangedDistribution const & distr, vdouble1d_t std_dev)\n"
+		"void AngularSpecScan::setAbsoluteAngularResolution(const IRangedDistribution &distr, const std::vector< double > &std_dev)\n"
 		"\n"
-		"Sets angular resolution values via RangedDistribution and values of standard deviations.  std_dev can be either single-valued or a numpy array. In the latter case the length of the array should coinside with the length of the inclination angle axis. \n"
+		"Sets angular resolution values via IRangedDistribution and values of standard deviations.  std_dev can be either single-valued or a numpy array. In the latter case the length of the array should coinside with the length of the inclination angle axis. \n"
 		"\n"
 		""},
 	 { "AngularSpecScan_swigregister", AngularSpecScan_swigregister, METH_O, NULL},
@@ -43719,6 +43716,11 @@ static PyMethodDef SwigMethods[] = {
 		"QSpecScan * QSpecScan::clone() const override\n"
 		"\n"
 		""},
+	 { "QSpecScan_resolution", _wrap_QSpecScan_resolution, METH_O, "\n"
+		"QSpecScan_resolution(QSpecScan self) -> ScanResolution const *\n"
+		"const ScanResolution* QSpecScan::resolution() const\n"
+		"\n"
+		""},
 	 { "QSpecScan_setQResolution", _wrap_QSpecScan_setQResolution, METH_VARARGS, "\n"
 		"QSpecScan_setQResolution(QSpecScan self, ScanResolution const & resolution)\n"
 		"void QSpecScan::setQResolution(const ScanResolution &resolution)\n"
@@ -43727,19 +43729,19 @@ static PyMethodDef SwigMethods[] = {
 		"\n"
 		""},
 	 { "QSpecScan_setRelativeQResolution", _wrap_QSpecScan_setRelativeQResolution, METH_VARARGS, "\n"
-		"QSpecScan_setRelativeQResolution(QSpecScan self, RangedDistribution const & distr, double rel_dev)\n"
-		"QSpecScan_setRelativeQResolution(QSpecScan self, RangedDistribution const & distr, vdouble1d_t rel_dev)\n"
-		"void QSpecScan::setRelativeQResolution(const RangedDistribution &distr, const std::vector< double > &rel_dev)\n"
+		"QSpecScan_setRelativeQResolution(QSpecScan self, IRangedDistribution const & distr, double rel_dev)\n"
+		"QSpecScan_setRelativeQResolution(QSpecScan self, IRangedDistribution const & distr, vdouble1d_t rel_dev)\n"
+		"void QSpecScan::setRelativeQResolution(const IRangedDistribution &distr, const std::vector< double > &rel_dev)\n"
 		"\n"
-		"Sets qz resolution values via RangedDistribution and values of relative deviations (that is,  rel_dev equals standard deviation divided by the mean value).  rel_dev can be either single-valued or a numpy array. In the latter case the length of the array should coinside with the length of the qz-axis. \n"
+		"Sets qz resolution values via IRangedDistribution and values of relative deviations (that is,  rel_dev equals standard deviation divided by the mean value).  rel_dev can be either single-valued or a numpy array. In the latter case the length of the array should coinside with the length of the qz-axis. \n"
 		"\n"
 		""},
 	 { "QSpecScan_setAbsoluteQResolution", _wrap_QSpecScan_setAbsoluteQResolution, METH_VARARGS, "\n"
-		"QSpecScan_setAbsoluteQResolution(QSpecScan self, RangedDistribution const & distr, double std_dev)\n"
-		"QSpecScan_setAbsoluteQResolution(QSpecScan self, RangedDistribution const & distr, vdouble1d_t std_dev)\n"
-		"void QSpecScan::setAbsoluteQResolution(const RangedDistribution &distr, const std::vector< double > &std_dev)\n"
+		"QSpecScan_setAbsoluteQResolution(QSpecScan self, IRangedDistribution const & distr, double std_dev)\n"
+		"QSpecScan_setAbsoluteQResolution(QSpecScan self, IRangedDistribution const & distr, vdouble1d_t std_dev)\n"
+		"void QSpecScan::setAbsoluteQResolution(const IRangedDistribution &distr, const std::vector< double > &std_dev)\n"
 		"\n"
-		"Sets qz resolution values via RangedDistribution and values of standard deviations.  std_dev can be either single-valued or a numpy array. In the latter case the length of the array should coinside with the length of the qz-axis. \n"
+		"Sets qz resolution values via IRangedDistribution and values of standard deviations.  std_dev can be either single-valued or a numpy array. In the latter case the length of the array should coinside with the length of the qz-axis. \n"
 		"\n"
 		""},
 	 { "QSpecScan_swigregister", QSpecScan_swigregister, METH_O, NULL},
@@ -44316,11 +44318,6 @@ static PyMethodDef SwigMethods[] = {
 		"std::string ExportToPython::generateSimulationCode(const ISimulation &simulation)\n"
 		"\n"
 		""},
-	 { "generatePyExportTest", _wrap_generatePyExportTest, METH_O, "\n"
-		"generatePyExportTest(ISimulation simulation) -> std::string\n"
-		"std::string ExportToPython::generatePyExportTest(const ISimulation &simulation)\n"
-		"\n"
-		""},
 	 { NULL, NULL, 0, NULL }
 };
 
@@ -44522,6 +44519,7 @@ static swig_type_info _swigt__p_INodeVisitor = {"_p_INodeVisitor", "INodeVisitor
 static swig_type_info _swigt__p_IObservable = {"_p_IObservable", "IObservable *", 0, 0, (void*)0, 0};
 static swig_type_info _swigt__p_IObserver = {"_p_IObserver", "IObserver *", 0, 0, (void*)0, 0};
 static swig_type_info _swigt__p_IParameterized = {"_p_IParameterized", "IParameterized *", 0, 0, (void*)0, 0};
+static swig_type_info _swigt__p_IRangedDistribution = {"_p_IRangedDistribution", "IRangedDistribution *", 0, 0, (void*)0, 0};
 static swig_type_info _swigt__p_IResolutionFunction2D = {"_p_IResolutionFunction2D", "IResolutionFunction2D *", 0, 0, (void*)0, 0};
 static swig_type_info _swigt__p_IShape2D = {"_p_IShape2D", "IShape2D *", 0, 0, (void*)0, 0};
 static swig_type_info _swigt__p_ISimulation = {"_p_ISimulation", "ISimulation *", 0, 0, (void*)0, 0};
@@ -44538,7 +44536,6 @@ static swig_type_info _swigt__p_ProgressHandler__Callback_t = {"_p_ProgressHandl
 static swig_type_info _swigt__p_PyBuilderCallback = {"_p_PyBuilderCallback", "PyBuilderCallback *", 0, 0, (void*)0, 0};
 static swig_type_info _swigt__p_PyObserverCallback = {"_p_PyObserverCallback", "PyObserverCallback *", 0, 0, (void*)0, 0};
 static swig_type_info _swigt__p_QSpecScan = {"_p_QSpecScan", "QSpecScan *", 0, 0, (void*)0, 0};
-static swig_type_info _swigt__p_RangedDistribution = {"_p_RangedDistribution", "RangedDistribution *", 0, 0, (void*)0, 0};
 static swig_type_info _swigt__p_RealLimits = {"_p_RealLimits", "RealLimits *", 0, 0, (void*)0, 0};
 static swig_type_info _swigt__p_ScanResolution = {"_p_ScanResolution", "ScanResolution *", 0, 0, (void*)0, 0};
 static swig_type_info _swigt__p_SimulationFactory = {"_p_SimulationFactory", "SimulationFactory *", 0, 0, (void*)0, 0};
@@ -44631,6 +44628,7 @@ static swig_type_info *swig_type_initial[] = {
   &_swigt__p_IObservable,
   &_swigt__p_IObserver,
   &_swigt__p_IParameterized,
+  &_swigt__p_IRangedDistribution,
   &_swigt__p_IResolutionFunction2D,
   &_swigt__p_ISample,
   &_swigt__p_IShape2D,
@@ -44649,7 +44647,6 @@ static swig_type_info *swig_type_initial[] = {
   &_swigt__p_PyBuilderCallback,
   &_swigt__p_PyObserverCallback,
   &_swigt__p_QSpecScan,
-  &_swigt__p_RangedDistribution,
   &_swigt__p_RealLimits,
   &_swigt__p_ScanResolution,
   &_swigt__p_SimulationFactory,
@@ -44744,6 +44741,7 @@ static swig_cast_info _swigc__p_INodeVisitor[] = {  {&_swigt__p_INodeVisitor, 0,
 static swig_cast_info _swigc__p_IObservable[] = {  {&_swigt__p_IObservable, 0, 0, 0},{0, 0, 0, 0}};
 static swig_cast_info _swigc__p_IObserver[] = {  {&_swigt__p_IObserver, 0, 0, 0},{0, 0, 0, 0}};
 static swig_cast_info _swigc__p_IParameterized[] = {  {&_swigt__p_IFormFactor, _p_IFormFactorTo_p_IParameterized, 0, 0},  {&_swigt__p_SpecularSimulation, _p_SpecularSimulationTo_p_IParameterized, 0, 0},  {&_swigt__p_DepthProbeSimulation, _p_DepthProbeSimulationTo_p_IParameterized, 0, 0},  {&_swigt__p_OffSpecSimulation, _p_OffSpecSimulationTo_p_IParameterized, 0, 0},  {&_swigt__p_GISASSimulation, _p_GISASSimulationTo_p_IParameterized, 0, 0},  {&_swigt__p_ISimulation, _p_ISimulationTo_p_IParameterized, 0, 0},  {&_swigt__p_PoissonNoiseBackground, _p_PoissonNoiseBackgroundTo_p_IParameterized, 0, 0},  {&_swigt__p_ConstantBackground, _p_ConstantBackgroundTo_p_IParameterized, 0, 0},  {&_swigt__p_IBackground, _p_IBackgroundTo_p_IParameterized, 0, 0},  {&_swigt__p_IBornFF, _p_IBornFFTo_p_IParameterized, 0, 0},  {&_swigt__p_ISample, _p_ISampleTo_p_IParameterized, 0, 0},  {&_swigt__p_ParameterDistribution, _p_ParameterDistributionTo_p_IParameterized, 0, 0},  {&_swigt__p_IParameterized, 0, 0, 0},  {&_swigt__p_ISimulation2D, _p_ISimulation2DTo_p_IParameterized, 0, 0},  {&_swigt__p_INode, _p_INodeTo_p_IParameterized, 0, 0},{0, 0, 0, 0}};
+static swig_cast_info _swigc__p_IRangedDistribution[] = {  {&_swigt__p_IRangedDistribution, 0, 0, 0},{0, 0, 0, 0}};
 static swig_cast_info _swigc__p_IResolutionFunction2D[] = {  {&_swigt__p_IResolutionFunction2D, 0, 0, 0},{0, 0, 0, 0}};
 static swig_cast_info _swigc__p_IShape2D[] = {  {&_swigt__p_IShape2D, 0, 0, 0},{0, 0, 0, 0}};
 static swig_cast_info _swigc__p_ISimulation[] = {  {&_swigt__p_ISimulation2D, _p_ISimulation2DTo_p_ISimulation, 0, 0},  {&_swigt__p_ISimulation, 0, 0, 0},  {&_swigt__p_GISASSimulation, _p_GISASSimulationTo_p_ISimulation, 0, 0},  {&_swigt__p_OffSpecSimulation, _p_OffSpecSimulationTo_p_ISimulation, 0, 0},  {&_swigt__p_DepthProbeSimulation, _p_DepthProbeSimulationTo_p_ISimulation, 0, 0},  {&_swigt__p_SpecularSimulation, _p_SpecularSimulationTo_p_ISimulation, 0, 0},{0, 0, 0, 0}};
@@ -44760,7 +44758,6 @@ static swig_cast_info _swigc__p_ProgressHandler__Callback_t[] = {  {&_swigt__p_P
 static swig_cast_info _swigc__p_PyBuilderCallback[] = {  {&_swigt__p_PyBuilderCallback, 0, 0, 0},{0, 0, 0, 0}};
 static swig_cast_info _swigc__p_PyObserverCallback[] = {  {&_swigt__p_PyObserverCallback, 0, 0, 0},{0, 0, 0, 0}};
 static swig_cast_info _swigc__p_QSpecScan[] = {  {&_swigt__p_QSpecScan, 0, 0, 0},{0, 0, 0, 0}};
-static swig_cast_info _swigc__p_RangedDistribution[] = {  {&_swigt__p_RangedDistribution, 0, 0, 0},{0, 0, 0, 0}};
 static swig_cast_info _swigc__p_RealLimits[] = {  {&_swigt__p_RealLimits, 0, 0, 0},{0, 0, 0, 0}};
 static swig_cast_info _swigc__p_ScanResolution[] = {  {&_swigt__p_ScanResolution, 0, 0, 0},{0, 0, 0, 0}};
 static swig_cast_info _swigc__p_SimulationFactory[] = {  {&_swigt__p_SimulationFactory, 0, 0, 0},{0, 0, 0, 0}};
@@ -44853,6 +44850,7 @@ static swig_cast_info *swig_cast_initial[] = {
   _swigc__p_IObservable,
   _swigc__p_IObserver,
   _swigc__p_IParameterized,
+  _swigc__p_IRangedDistribution,
   _swigc__p_IResolutionFunction2D,
   _swigc__p_ISample,
   _swigc__p_IShape2D,
@@ -44871,7 +44869,6 @@ static swig_cast_info *swig_cast_initial[] = {
   _swigc__p_PyBuilderCallback,
   _swigc__p_PyObserverCallback,
   _swigc__p_QSpecScan,
-  _swigc__p_RangedDistribution,
   _swigc__p_RealLimits,
   _swigc__p_ScanResolution,
   _swigc__p_SimulationFactory,
diff --git a/auto/Wrap/libBornAgainDevice.py b/auto/Wrap/libBornAgainDevice.py
index 1ca03058809c707dbdf2b5e26f53317c8e3a3731..e81a989a8ee955bff707a6893bf1f5fd3d8a2685 100644
--- a/auto/Wrap/libBornAgainDevice.py
+++ b/auto/Wrap/libBornAgainDevice.py
@@ -2830,15 +2830,13 @@ class IFootprintFactor(libBornAgainBase.ICloneable, libBornAgainParam.INode):
         """
         return _libBornAgainDevice.IFootprintFactor_calculate(self, alpha)
 
-    def _print(self):
+    def name(self):
         r"""
-        _print(IFootprintFactor self) -> std::string
-        virtual std::string IFootprintFactor::print() const =0
-
-        Print python-formatted footprint definition. 
+        name(IFootprintFactor self) -> std::string
+        virtual std::string IFootprintFactor::name() const =0
 
         """
-        return _libBornAgainDevice.IFootprintFactor__print(self)
+        return _libBornAgainDevice.IFootprintFactor_name(self)
 
 # Register IFootprintFactor in _libBornAgainDevice:
 _libBornAgainDevice.IFootprintFactor_swigregister(IFootprintFactor)
@@ -2891,15 +2889,13 @@ class FootprintGauss(IFootprintFactor):
         """
         return _libBornAgainDevice.FootprintGauss_calculate(self, alpha)
 
-    def _print(self):
+    def name(self):
         r"""
-        _print(FootprintGauss self) -> std::string
-        std::string FootprintGauss::print() const override
-
-        Print python-formatted footprint definition. 
+        name(FootprintGauss self) -> std::string
+        std::string FootprintGauss::name() const override
 
         """
-        return _libBornAgainDevice.FootprintGauss__print(self)
+        return _libBornAgainDevice.FootprintGauss_name(self)
     __swig_destroy__ = _libBornAgainDevice.delete_FootprintGauss
 
 # Register FootprintGauss in _libBornAgainDevice:
@@ -2953,15 +2949,13 @@ class FootprintSquare(IFootprintFactor):
         """
         return _libBornAgainDevice.FootprintSquare_calculate(self, alpha)
 
-    def _print(self):
+    def name(self):
         r"""
-        _print(FootprintSquare self) -> std::string
-        std::string FootprintSquare::print() const override
-
-        Print python-formatted footprint definition. 
+        name(FootprintSquare self) -> std::string
+        std::string FootprintSquare::name() const override
 
         """
-        return _libBornAgainDevice.FootprintSquare__print(self)
+        return _libBornAgainDevice.FootprintSquare_name(self)
     __swig_destroy__ = _libBornAgainDevice.delete_FootprintSquare
 
 # Register FootprintSquare in _libBornAgainDevice:
@@ -3398,7 +3392,7 @@ class Polygon(IShape2D):
     r"""
 
 
-    A polygon in 2D space.Polygon defined by two arrays with x and y coordinates of points. Sizes of arrays should coincide. If polygon is unclosed (the last point doesn't repeat the first one), it will be closed automatically.
+    A polygon in 2D space.  Polygon defined by two arrays with x and y coordinates of points. Sizes of arrays should coincide. If polygon is unclosed (the last point doesn't repeat the first one), it will be closed automatically.
 
     C++ includes: Polygon.h
 
@@ -3714,16 +3708,16 @@ class ScanResolution(libBornAgainBase.ICloneable):
     @staticmethod
     def scanRelativeResolution(*args):
         r"""
-        scanRelativeResolution(RangedDistribution const & distr, double stddev) -> ScanResolution
-        scanRelativeResolution(RangedDistribution const & distr, vdouble1d_t stddevs) -> ScanResolution
+        scanRelativeResolution(IRangedDistribution const & distr, double stddev) -> ScanResolution
+        scanRelativeResolution(IRangedDistribution const & distr, vdouble1d_t stddevs) -> ScanResolution
         """
         return _libBornAgainDevice.ScanResolution_scanRelativeResolution(*args)
 
     @staticmethod
     def scanAbsoluteResolution(*args):
         r"""
-        scanAbsoluteResolution(RangedDistribution const & distr, double stddev) -> ScanResolution
-        scanAbsoluteResolution(RangedDistribution const & distr, vdouble1d_t stddevs) -> ScanResolution
+        scanAbsoluteResolution(IRangedDistribution const & distr, double stddev) -> ScanResolution
+        scanAbsoluteResolution(IRangedDistribution const & distr, vdouble1d_t stddevs) -> ScanResolution
         """
         return _libBornAgainDevice.ScanResolution_scanAbsoluteResolution(*args)
 
@@ -3732,15 +3726,15 @@ _libBornAgainDevice.ScanResolution_swigregister(ScanResolution)
 
 def ScanResolution_scanRelativeResolution(*args):
     r"""
-    ScanResolution_scanRelativeResolution(RangedDistribution const & distr, double stddev) -> ScanResolution
-    ScanResolution_scanRelativeResolution(RangedDistribution const & distr, vdouble1d_t stddevs) -> ScanResolution
+    ScanResolution_scanRelativeResolution(IRangedDistribution const & distr, double stddev) -> ScanResolution
+    ScanResolution_scanRelativeResolution(IRangedDistribution const & distr, vdouble1d_t stddevs) -> ScanResolution
     """
     return _libBornAgainDevice.ScanResolution_scanRelativeResolution(*args)
 
 def ScanResolution_scanAbsoluteResolution(*args):
     r"""
-    ScanResolution_scanAbsoluteResolution(RangedDistribution const & distr, double stddev) -> ScanResolution
-    ScanResolution_scanAbsoluteResolution(RangedDistribution const & distr, vdouble1d_t stddevs) -> ScanResolution
+    ScanResolution_scanAbsoluteResolution(IRangedDistribution const & distr, double stddev) -> ScanResolution
+    ScanResolution_scanAbsoluteResolution(IRangedDistribution const & distr, vdouble1d_t stddevs) -> ScanResolution
     """
     return _libBornAgainDevice.ScanResolution_scanAbsoluteResolution(*args)
 
@@ -5949,7 +5943,9 @@ class IntensityDataIOFactory(object):
     r"""
 
 
-    Provides users with possibility to read and write IntensityData from/to files in different format. Type of the file will be deduced from file name. *.txt - ASCII file with 2D array [nrow][ncol], layout as in numpy. *.int - BornAgain internal ASCII format. *.tif - 32-bits tiff file. If file name ends woth "*.gz" or "*.bz2" the file will be zipped on the fly using appropriate algorithm. Usage:
+    Provides users with possibility to read and write IntensityData from/to files in different format. Type of the file will be deduced from file name. *.txt - ASCII file with 2D array [nrow][ncol], layout as in numpy. *.int - BornAgain internal ASCII format. *.tif - 32-bits tiff file. If file name ends woth "*.gz" or "*.bz2" the file will be zipped on the fly using appropriate algorithm.
+
+    Usage:
 
     C++ includes: IntensityDataIOFactory.h
 
@@ -5993,7 +5989,9 @@ class IntensityDataIOFactory(object):
         __init__(IntensityDataIOFactory self) -> IntensityDataIOFactory
 
 
-        Provides users with possibility to read and write IntensityData from/to files in different format. Type of the file will be deduced from file name. *.txt - ASCII file with 2D array [nrow][ncol], layout as in numpy. *.int - BornAgain internal ASCII format. *.tif - 32-bits tiff file. If file name ends woth "*.gz" or "*.bz2" the file will be zipped on the fly using appropriate algorithm. Usage:
+        Provides users with possibility to read and write IntensityData from/to files in different format. Type of the file will be deduced from file name. *.txt - ASCII file with 2D array [nrow][ncol], layout as in numpy. *.int - BornAgain internal ASCII format. *.tif - 32-bits tiff file. If file name ends woth "*.gz" or "*.bz2" the file will be zipped on the fly using appropriate algorithm.
+
+        Usage:
 
         C++ includes: IntensityDataIOFactory.h
 
@@ -6175,7 +6173,7 @@ def ScanRelativeResolution(distribution, rel_dev):
     Creates a scan resolution from the given distribution and
     relative deviation values (that is, the ratios of standard
     deviations and means).
-    :param distribution: bornagain.RangedDistribution object
+    :param distribution: bornagain.IRangedDistribution object
     :param rel_dev: either single-valued or a numpy array.
                     In the latter case should coinside in
                     size with later used mean values array.
@@ -6187,7 +6185,7 @@ def ScanAbsoluteResolution(distribution, std_dev):
     """
     Creates a scan resolution from the given distribution and
     standard deviation values.
-    :param distribution: bornagain.RangedDistribution object
+    :param distribution: bornagain.IRangedDistribution object
     :param std_dev: either single-valued or a numpy array.
                     In the latter case should coinside in
                     size with later used mean values array.
diff --git a/auto/Wrap/libBornAgainDevice_wrap.cpp b/auto/Wrap/libBornAgainDevice_wrap.cpp
index 409a15b1937da44ee9c89506b1d6ebd1acfeb82d..2eaf9ae94299dc9ba0a3828c1c35f6db38e007e0 100644
--- a/auto/Wrap/libBornAgainDevice_wrap.cpp
+++ b/auto/Wrap/libBornAgainDevice_wrap.cpp
@@ -3126,26 +3126,26 @@ namespace Swig {
 #define SWIGTYPE_p_INodeVisitor swig_types[26]
 #define SWIGTYPE_p_IParameterized swig_types[27]
 #define SWIGTYPE_p_IPixel swig_types[28]
-#define SWIGTYPE_p_IResolutionFunction2D swig_types[29]
-#define SWIGTYPE_p_IShape2D swig_types[30]
-#define SWIGTYPE_p_IUnitConverter swig_types[31]
-#define SWIGTYPE_p_IVarianceFunction swig_types[32]
-#define SWIGTYPE_p_Instrument swig_types[33]
-#define SWIGTYPE_p_IntensityDataIOFactory swig_types[34]
-#define SWIGTYPE_p_IntensityFunctionLog swig_types[35]
-#define SWIGTYPE_p_IntensityFunctionSqrt swig_types[36]
-#define SWIGTYPE_p_IsGISAXSDetector swig_types[37]
-#define SWIGTYPE_p_Line swig_types[38]
-#define SWIGTYPE_p_OutputDataIteratorT_double_OutputDataT_double_t_t swig_types[39]
-#define SWIGTYPE_p_OutputDataIteratorT_double_const_OutputDataT_double_t_const_t swig_types[40]
-#define SWIGTYPE_p_OutputDataT_CumulativeValue_t swig_types[41]
-#define SWIGTYPE_p_OutputDataT_bool_t swig_types[42]
-#define SWIGTYPE_p_OutputDataT_double_t swig_types[43]
-#define SWIGTYPE_p_ParameterDistribution swig_types[44]
-#define SWIGTYPE_p_ParameterPool swig_types[45]
-#define SWIGTYPE_p_Polygon swig_types[46]
-#define SWIGTYPE_p_PolygonPrivate swig_types[47]
-#define SWIGTYPE_p_RangedDistribution swig_types[48]
+#define SWIGTYPE_p_IRangedDistribution swig_types[29]
+#define SWIGTYPE_p_IResolutionFunction2D swig_types[30]
+#define SWIGTYPE_p_IShape2D swig_types[31]
+#define SWIGTYPE_p_IUnitConverter swig_types[32]
+#define SWIGTYPE_p_IVarianceFunction swig_types[33]
+#define SWIGTYPE_p_Instrument swig_types[34]
+#define SWIGTYPE_p_IntensityDataIOFactory swig_types[35]
+#define SWIGTYPE_p_IntensityFunctionLog swig_types[36]
+#define SWIGTYPE_p_IntensityFunctionSqrt swig_types[37]
+#define SWIGTYPE_p_IsGISAXSDetector swig_types[38]
+#define SWIGTYPE_p_Line swig_types[39]
+#define SWIGTYPE_p_OutputDataIteratorT_double_OutputDataT_double_t_t swig_types[40]
+#define SWIGTYPE_p_OutputDataIteratorT_double_const_OutputDataT_double_t_const_t swig_types[41]
+#define SWIGTYPE_p_OutputDataT_CumulativeValue_t swig_types[42]
+#define SWIGTYPE_p_OutputDataT_bool_t swig_types[43]
+#define SWIGTYPE_p_OutputDataT_double_t swig_types[44]
+#define SWIGTYPE_p_ParameterDistribution swig_types[45]
+#define SWIGTYPE_p_ParameterPool swig_types[46]
+#define SWIGTYPE_p_Polygon swig_types[47]
+#define SWIGTYPE_p_PolygonPrivate swig_types[48]
 #define SWIGTYPE_p_Rectangle swig_types[49]
 #define SWIGTYPE_p_RectangularDetector swig_types[50]
 #define SWIGTYPE_p_RectangularPixel swig_types[51]
@@ -31251,7 +31251,7 @@ fail:
 }
 
 
-SWIGINTERN PyObject *_wrap_IFootprintFactor__print(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+SWIGINTERN PyObject *_wrap_IFootprintFactor_name(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
   PyObject *resultobj = 0;
   IFootprintFactor *arg1 = (IFootprintFactor *) 0 ;
   void *argp1 = 0 ;
@@ -31263,10 +31263,10 @@ SWIGINTERN PyObject *_wrap_IFootprintFactor__print(PyObject *SWIGUNUSEDPARM(self
   swig_obj[0] = args;
   res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_IFootprintFactor, 0 |  0 );
   if (!SWIG_IsOK(res1)) {
-    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "IFootprintFactor__print" "', argument " "1"" of type '" "IFootprintFactor const *""'"); 
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "IFootprintFactor_name" "', argument " "1"" of type '" "IFootprintFactor const *""'"); 
   }
   arg1 = reinterpret_cast< IFootprintFactor * >(argp1);
-  result = ((IFootprintFactor const *)arg1)->print();
+  result = ((IFootprintFactor const *)arg1)->name();
   resultobj = SWIG_From_std_string(static_cast< std::string >(result));
   return resultobj;
 fail:
@@ -31443,7 +31443,7 @@ fail:
 }
 
 
-SWIGINTERN PyObject *_wrap_FootprintGauss__print(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+SWIGINTERN PyObject *_wrap_FootprintGauss_name(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
   PyObject *resultobj = 0;
   FootprintGauss *arg1 = (FootprintGauss *) 0 ;
   void *argp1 = 0 ;
@@ -31455,10 +31455,10 @@ SWIGINTERN PyObject *_wrap_FootprintGauss__print(PyObject *SWIGUNUSEDPARM(self),
   swig_obj[0] = args;
   res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_FootprintGauss, 0 |  0 );
   if (!SWIG_IsOK(res1)) {
-    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "FootprintGauss__print" "', argument " "1"" of type '" "FootprintGauss const *""'"); 
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "FootprintGauss_name" "', argument " "1"" of type '" "FootprintGauss const *""'"); 
   }
   arg1 = reinterpret_cast< FootprintGauss * >(argp1);
-  result = ((FootprintGauss const *)arg1)->print();
+  result = ((FootprintGauss const *)arg1)->name();
   resultobj = SWIG_From_std_string(static_cast< std::string >(result));
   return resultobj;
 fail:
@@ -31661,7 +31661,7 @@ fail:
 }
 
 
-SWIGINTERN PyObject *_wrap_FootprintSquare__print(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+SWIGINTERN PyObject *_wrap_FootprintSquare_name(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
   PyObject *resultobj = 0;
   FootprintSquare *arg1 = (FootprintSquare *) 0 ;
   void *argp1 = 0 ;
@@ -31673,10 +31673,10 @@ SWIGINTERN PyObject *_wrap_FootprintSquare__print(PyObject *SWIGUNUSEDPARM(self)
   swig_obj[0] = args;
   res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_FootprintSquare, 0 |  0 );
   if (!SWIG_IsOK(res1)) {
-    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "FootprintSquare__print" "', argument " "1"" of type '" "FootprintSquare const *""'"); 
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "FootprintSquare_name" "', argument " "1"" of type '" "FootprintSquare const *""'"); 
   }
   arg1 = reinterpret_cast< FootprintSquare * >(argp1);
-  result = ((FootprintSquare const *)arg1)->print();
+  result = ((FootprintSquare const *)arg1)->name();
   resultobj = SWIG_From_std_string(static_cast< std::string >(result));
   return resultobj;
 fail:
@@ -34514,7 +34514,7 @@ fail:
 
 SWIGINTERN PyObject *_wrap_ScanResolution_scanRelativeResolution__SWIG_0(PyObject *SWIGUNUSEDPARM(self), Py_ssize_t nobjs, PyObject **swig_obj) {
   PyObject *resultobj = 0;
-  RangedDistribution *arg1 = 0 ;
+  IRangedDistribution *arg1 = 0 ;
   double arg2 ;
   void *argp1 = 0 ;
   int res1 = 0 ;
@@ -34523,20 +34523,20 @@ SWIGINTERN PyObject *_wrap_ScanResolution_scanRelativeResolution__SWIG_0(PyObjec
   ScanResolution *result = 0 ;
   
   if ((nobjs < 2) || (nobjs > 2)) SWIG_fail;
-  res1 = SWIG_ConvertPtr(swig_obj[0], &argp1, SWIGTYPE_p_RangedDistribution,  0  | 0);
+  res1 = SWIG_ConvertPtr(swig_obj[0], &argp1, SWIGTYPE_p_IRangedDistribution,  0  | 0);
   if (!SWIG_IsOK(res1)) {
-    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "ScanResolution_scanRelativeResolution" "', argument " "1"" of type '" "RangedDistribution const &""'"); 
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "ScanResolution_scanRelativeResolution" "', argument " "1"" of type '" "IRangedDistribution const &""'"); 
   }
   if (!argp1) {
-    SWIG_exception_fail(SWIG_ValueError, "invalid null reference " "in method '" "ScanResolution_scanRelativeResolution" "', argument " "1"" of type '" "RangedDistribution const &""'"); 
+    SWIG_exception_fail(SWIG_ValueError, "invalid null reference " "in method '" "ScanResolution_scanRelativeResolution" "', argument " "1"" of type '" "IRangedDistribution const &""'"); 
   }
-  arg1 = reinterpret_cast< RangedDistribution * >(argp1);
+  arg1 = reinterpret_cast< IRangedDistribution * >(argp1);
   ecode2 = SWIG_AsVal_double(swig_obj[1], &val2);
   if (!SWIG_IsOK(ecode2)) {
     SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "ScanResolution_scanRelativeResolution" "', argument " "2"" of type '" "double""'");
   } 
   arg2 = static_cast< double >(val2);
-  result = (ScanResolution *)ScanResolution::scanRelativeResolution((RangedDistribution const &)*arg1,arg2);
+  result = (ScanResolution *)ScanResolution::scanRelativeResolution((IRangedDistribution const &)*arg1,arg2);
   resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_ScanResolution, SWIG_POINTER_OWN |  0 );
   return resultobj;
 fail:
@@ -34546,7 +34546,7 @@ fail:
 
 SWIGINTERN PyObject *_wrap_ScanResolution_scanRelativeResolution__SWIG_1(PyObject *SWIGUNUSEDPARM(self), Py_ssize_t nobjs, PyObject **swig_obj) {
   PyObject *resultobj = 0;
-  RangedDistribution *arg1 = 0 ;
+  IRangedDistribution *arg1 = 0 ;
   std::vector< double,std::allocator< double > > *arg2 = 0 ;
   void *argp1 = 0 ;
   int res1 = 0 ;
@@ -34554,14 +34554,14 @@ SWIGINTERN PyObject *_wrap_ScanResolution_scanRelativeResolution__SWIG_1(PyObjec
   ScanResolution *result = 0 ;
   
   if ((nobjs < 2) || (nobjs > 2)) SWIG_fail;
-  res1 = SWIG_ConvertPtr(swig_obj[0], &argp1, SWIGTYPE_p_RangedDistribution,  0  | 0);
+  res1 = SWIG_ConvertPtr(swig_obj[0], &argp1, SWIGTYPE_p_IRangedDistribution,  0  | 0);
   if (!SWIG_IsOK(res1)) {
-    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "ScanResolution_scanRelativeResolution" "', argument " "1"" of type '" "RangedDistribution const &""'"); 
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "ScanResolution_scanRelativeResolution" "', argument " "1"" of type '" "IRangedDistribution const &""'"); 
   }
   if (!argp1) {
-    SWIG_exception_fail(SWIG_ValueError, "invalid null reference " "in method '" "ScanResolution_scanRelativeResolution" "', argument " "1"" of type '" "RangedDistribution const &""'"); 
+    SWIG_exception_fail(SWIG_ValueError, "invalid null reference " "in method '" "ScanResolution_scanRelativeResolution" "', argument " "1"" of type '" "IRangedDistribution const &""'"); 
   }
-  arg1 = reinterpret_cast< RangedDistribution * >(argp1);
+  arg1 = reinterpret_cast< IRangedDistribution * >(argp1);
   {
     std::vector< double,std::allocator< double > > *ptr = (std::vector< double,std::allocator< double > > *)0;
     res2 = swig::asptr(swig_obj[1], &ptr);
@@ -34573,7 +34573,7 @@ SWIGINTERN PyObject *_wrap_ScanResolution_scanRelativeResolution__SWIG_1(PyObjec
     }
     arg2 = ptr;
   }
-  result = (ScanResolution *)ScanResolution::scanRelativeResolution((RangedDistribution const &)*arg1,(std::vector< double,std::allocator< double > > const &)*arg2);
+  result = (ScanResolution *)ScanResolution::scanRelativeResolution((IRangedDistribution const &)*arg1,(std::vector< double,std::allocator< double > > const &)*arg2);
   resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_ScanResolution, SWIG_POINTER_OWN |  0 );
   if (SWIG_IsNewObj(res2)) delete arg2;
   return resultobj;
@@ -34593,7 +34593,7 @@ SWIGINTERN PyObject *_wrap_ScanResolution_scanRelativeResolution(PyObject *self,
   --argc;
   if (argc == 2) {
     int _v;
-    int res = SWIG_ConvertPtr(argv[0], 0, SWIGTYPE_p_RangedDistribution, SWIG_POINTER_NO_NULL | 0);
+    int res = SWIG_ConvertPtr(argv[0], 0, SWIGTYPE_p_IRangedDistribution, SWIG_POINTER_NO_NULL | 0);
     _v = SWIG_CheckState(res);
     if (_v) {
       {
@@ -34607,7 +34607,7 @@ SWIGINTERN PyObject *_wrap_ScanResolution_scanRelativeResolution(PyObject *self,
   }
   if (argc == 2) {
     int _v;
-    int res = SWIG_ConvertPtr(argv[0], 0, SWIGTYPE_p_RangedDistribution, SWIG_POINTER_NO_NULL | 0);
+    int res = SWIG_ConvertPtr(argv[0], 0, SWIGTYPE_p_IRangedDistribution, SWIG_POINTER_NO_NULL | 0);
     _v = SWIG_CheckState(res);
     if (_v) {
       int res = swig::asptr(argv[1], (std::vector< double,std::allocator< double > >**)(0));
@@ -34621,15 +34621,15 @@ SWIGINTERN PyObject *_wrap_ScanResolution_scanRelativeResolution(PyObject *self,
 fail:
   SWIG_Python_RaiseOrModifyTypeError("Wrong number or type of arguments for overloaded function 'ScanResolution_scanRelativeResolution'.\n"
     "  Possible C/C++ prototypes are:\n"
-    "    ScanResolution::scanRelativeResolution(RangedDistribution const &,double)\n"
-    "    ScanResolution::scanRelativeResolution(RangedDistribution const &,std::vector< double,std::allocator< double > > const &)\n");
+    "    ScanResolution::scanRelativeResolution(IRangedDistribution const &,double)\n"
+    "    ScanResolution::scanRelativeResolution(IRangedDistribution const &,std::vector< double,std::allocator< double > > const &)\n");
   return 0;
 }
 
 
 SWIGINTERN PyObject *_wrap_ScanResolution_scanAbsoluteResolution__SWIG_0(PyObject *SWIGUNUSEDPARM(self), Py_ssize_t nobjs, PyObject **swig_obj) {
   PyObject *resultobj = 0;
-  RangedDistribution *arg1 = 0 ;
+  IRangedDistribution *arg1 = 0 ;
   double arg2 ;
   void *argp1 = 0 ;
   int res1 = 0 ;
@@ -34638,20 +34638,20 @@ SWIGINTERN PyObject *_wrap_ScanResolution_scanAbsoluteResolution__SWIG_0(PyObjec
   ScanResolution *result = 0 ;
   
   if ((nobjs < 2) || (nobjs > 2)) SWIG_fail;
-  res1 = SWIG_ConvertPtr(swig_obj[0], &argp1, SWIGTYPE_p_RangedDistribution,  0  | 0);
+  res1 = SWIG_ConvertPtr(swig_obj[0], &argp1, SWIGTYPE_p_IRangedDistribution,  0  | 0);
   if (!SWIG_IsOK(res1)) {
-    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "ScanResolution_scanAbsoluteResolution" "', argument " "1"" of type '" "RangedDistribution const &""'"); 
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "ScanResolution_scanAbsoluteResolution" "', argument " "1"" of type '" "IRangedDistribution const &""'"); 
   }
   if (!argp1) {
-    SWIG_exception_fail(SWIG_ValueError, "invalid null reference " "in method '" "ScanResolution_scanAbsoluteResolution" "', argument " "1"" of type '" "RangedDistribution const &""'"); 
+    SWIG_exception_fail(SWIG_ValueError, "invalid null reference " "in method '" "ScanResolution_scanAbsoluteResolution" "', argument " "1"" of type '" "IRangedDistribution const &""'"); 
   }
-  arg1 = reinterpret_cast< RangedDistribution * >(argp1);
+  arg1 = reinterpret_cast< IRangedDistribution * >(argp1);
   ecode2 = SWIG_AsVal_double(swig_obj[1], &val2);
   if (!SWIG_IsOK(ecode2)) {
     SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "ScanResolution_scanAbsoluteResolution" "', argument " "2"" of type '" "double""'");
   } 
   arg2 = static_cast< double >(val2);
-  result = (ScanResolution *)ScanResolution::scanAbsoluteResolution((RangedDistribution const &)*arg1,arg2);
+  result = (ScanResolution *)ScanResolution::scanAbsoluteResolution((IRangedDistribution const &)*arg1,arg2);
   resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_ScanResolution, SWIG_POINTER_OWN |  0 );
   return resultobj;
 fail:
@@ -34661,7 +34661,7 @@ fail:
 
 SWIGINTERN PyObject *_wrap_ScanResolution_scanAbsoluteResolution__SWIG_1(PyObject *SWIGUNUSEDPARM(self), Py_ssize_t nobjs, PyObject **swig_obj) {
   PyObject *resultobj = 0;
-  RangedDistribution *arg1 = 0 ;
+  IRangedDistribution *arg1 = 0 ;
   std::vector< double,std::allocator< double > > *arg2 = 0 ;
   void *argp1 = 0 ;
   int res1 = 0 ;
@@ -34669,14 +34669,14 @@ SWIGINTERN PyObject *_wrap_ScanResolution_scanAbsoluteResolution__SWIG_1(PyObjec
   ScanResolution *result = 0 ;
   
   if ((nobjs < 2) || (nobjs > 2)) SWIG_fail;
-  res1 = SWIG_ConvertPtr(swig_obj[0], &argp1, SWIGTYPE_p_RangedDistribution,  0  | 0);
+  res1 = SWIG_ConvertPtr(swig_obj[0], &argp1, SWIGTYPE_p_IRangedDistribution,  0  | 0);
   if (!SWIG_IsOK(res1)) {
-    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "ScanResolution_scanAbsoluteResolution" "', argument " "1"" of type '" "RangedDistribution const &""'"); 
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "ScanResolution_scanAbsoluteResolution" "', argument " "1"" of type '" "IRangedDistribution const &""'"); 
   }
   if (!argp1) {
-    SWIG_exception_fail(SWIG_ValueError, "invalid null reference " "in method '" "ScanResolution_scanAbsoluteResolution" "', argument " "1"" of type '" "RangedDistribution const &""'"); 
+    SWIG_exception_fail(SWIG_ValueError, "invalid null reference " "in method '" "ScanResolution_scanAbsoluteResolution" "', argument " "1"" of type '" "IRangedDistribution const &""'"); 
   }
-  arg1 = reinterpret_cast< RangedDistribution * >(argp1);
+  arg1 = reinterpret_cast< IRangedDistribution * >(argp1);
   {
     std::vector< double,std::allocator< double > > *ptr = (std::vector< double,std::allocator< double > > *)0;
     res2 = swig::asptr(swig_obj[1], &ptr);
@@ -34688,7 +34688,7 @@ SWIGINTERN PyObject *_wrap_ScanResolution_scanAbsoluteResolution__SWIG_1(PyObjec
     }
     arg2 = ptr;
   }
-  result = (ScanResolution *)ScanResolution::scanAbsoluteResolution((RangedDistribution const &)*arg1,(std::vector< double,std::allocator< double > > const &)*arg2);
+  result = (ScanResolution *)ScanResolution::scanAbsoluteResolution((IRangedDistribution const &)*arg1,(std::vector< double,std::allocator< double > > const &)*arg2);
   resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_ScanResolution, SWIG_POINTER_OWN |  0 );
   if (SWIG_IsNewObj(res2)) delete arg2;
   return resultobj;
@@ -34708,7 +34708,7 @@ SWIGINTERN PyObject *_wrap_ScanResolution_scanAbsoluteResolution(PyObject *self,
   --argc;
   if (argc == 2) {
     int _v;
-    int res = SWIG_ConvertPtr(argv[0], 0, SWIGTYPE_p_RangedDistribution, SWIG_POINTER_NO_NULL | 0);
+    int res = SWIG_ConvertPtr(argv[0], 0, SWIGTYPE_p_IRangedDistribution, SWIG_POINTER_NO_NULL | 0);
     _v = SWIG_CheckState(res);
     if (_v) {
       {
@@ -34722,7 +34722,7 @@ SWIGINTERN PyObject *_wrap_ScanResolution_scanAbsoluteResolution(PyObject *self,
   }
   if (argc == 2) {
     int _v;
-    int res = SWIG_ConvertPtr(argv[0], 0, SWIGTYPE_p_RangedDistribution, SWIG_POINTER_NO_NULL | 0);
+    int res = SWIG_ConvertPtr(argv[0], 0, SWIGTYPE_p_IRangedDistribution, SWIG_POINTER_NO_NULL | 0);
     _v = SWIG_CheckState(res);
     if (_v) {
       int res = swig::asptr(argv[1], (std::vector< double,std::allocator< double > >**)(0));
@@ -34736,8 +34736,8 @@ SWIGINTERN PyObject *_wrap_ScanResolution_scanAbsoluteResolution(PyObject *self,
 fail:
   SWIG_Python_RaiseOrModifyTypeError("Wrong number or type of arguments for overloaded function 'ScanResolution_scanAbsoluteResolution'.\n"
     "  Possible C/C++ prototypes are:\n"
-    "    ScanResolution::scanAbsoluteResolution(RangedDistribution const &,double)\n"
-    "    ScanResolution::scanAbsoluteResolution(RangedDistribution const &,std::vector< double,std::allocator< double > > const &)\n");
+    "    ScanResolution::scanAbsoluteResolution(IRangedDistribution const &,double)\n"
+    "    ScanResolution::scanAbsoluteResolution(IRangedDistribution const &,std::vector< double,std::allocator< double > > const &)\n");
   return 0;
 }
 
@@ -46821,11 +46821,9 @@ static PyMethodDef SwigMethods[] = {
 		"Calculate footprint correction coefficient from the beam incident angle  alpha. \n"
 		"\n"
 		""},
-	 { "IFootprintFactor__print", _wrap_IFootprintFactor__print, METH_O, "\n"
-		"IFootprintFactor__print(IFootprintFactor self) -> std::string\n"
-		"virtual std::string IFootprintFactor::print() const =0\n"
-		"\n"
-		"Print python-formatted footprint definition. \n"
+	 { "IFootprintFactor_name", _wrap_IFootprintFactor_name, METH_O, "\n"
+		"IFootprintFactor_name(IFootprintFactor self) -> std::string\n"
+		"virtual std::string IFootprintFactor::name() const =0\n"
 		"\n"
 		""},
 	 { "IFootprintFactor_swigregister", IFootprintFactor_swigregister, METH_O, NULL},
@@ -46852,11 +46850,9 @@ static PyMethodDef SwigMethods[] = {
 		"Calculate footprint correction coefficient from the beam incident angle  alpha. \n"
 		"\n"
 		""},
-	 { "FootprintGauss__print", _wrap_FootprintGauss__print, METH_O, "\n"
-		"FootprintGauss__print(FootprintGauss self) -> std::string\n"
-		"std::string FootprintGauss::print() const override\n"
-		"\n"
-		"Print python-formatted footprint definition. \n"
+	 { "FootprintGauss_name", _wrap_FootprintGauss_name, METH_O, "\n"
+		"FootprintGauss_name(FootprintGauss self) -> std::string\n"
+		"std::string FootprintGauss::name() const override\n"
 		"\n"
 		""},
 	 { "delete_FootprintGauss", _wrap_delete_FootprintGauss, METH_O, "delete_FootprintGauss(FootprintGauss self)"},
@@ -46885,11 +46881,9 @@ static PyMethodDef SwigMethods[] = {
 		"Calculate footprint correction coefficient from the beam incident angle  alpha. \n"
 		"\n"
 		""},
-	 { "FootprintSquare__print", _wrap_FootprintSquare__print, METH_O, "\n"
-		"FootprintSquare__print(FootprintSquare self) -> std::string\n"
-		"std::string FootprintSquare::print() const override\n"
-		"\n"
-		"Print python-formatted footprint definition. \n"
+	 { "FootprintSquare_name", _wrap_FootprintSquare_name, METH_O, "\n"
+		"FootprintSquare_name(FootprintSquare self) -> std::string\n"
+		"std::string FootprintSquare::name() const override\n"
 		"\n"
 		""},
 	 { "delete_FootprintSquare", _wrap_delete_FootprintSquare, METH_O, "delete_FootprintSquare(FootprintSquare self)"},
@@ -47290,12 +47284,12 @@ static PyMethodDef SwigMethods[] = {
 		"\n"
 		""},
 	 { "ScanResolution_scanRelativeResolution", _wrap_ScanResolution_scanRelativeResolution, METH_VARARGS, "\n"
-		"ScanResolution_scanRelativeResolution(RangedDistribution const & distr, double stddev) -> ScanResolution\n"
-		"ScanResolution_scanRelativeResolution(RangedDistribution const & distr, vdouble1d_t stddevs) -> ScanResolution\n"
+		"ScanResolution_scanRelativeResolution(IRangedDistribution const & distr, double stddev) -> ScanResolution\n"
+		"ScanResolution_scanRelativeResolution(IRangedDistribution const & distr, vdouble1d_t stddevs) -> ScanResolution\n"
 		""},
 	 { "ScanResolution_scanAbsoluteResolution", _wrap_ScanResolution_scanAbsoluteResolution, METH_VARARGS, "\n"
-		"ScanResolution_scanAbsoluteResolution(RangedDistribution const & distr, double stddev) -> ScanResolution\n"
-		"ScanResolution_scanAbsoluteResolution(RangedDistribution const & distr, vdouble1d_t stddevs) -> ScanResolution\n"
+		"ScanResolution_scanAbsoluteResolution(IRangedDistribution const & distr, double stddev) -> ScanResolution\n"
+		"ScanResolution_scanAbsoluteResolution(IRangedDistribution const & distr, vdouble1d_t stddevs) -> ScanResolution\n"
 		""},
 	 { "ScanResolution_swigregister", ScanResolution_swigregister, METH_O, NULL},
 	 { "delete_IChiSquaredModule", _wrap_delete_IChiSquaredModule, METH_O, "\n"
@@ -48651,7 +48645,9 @@ static PyMethodDef SwigMethods[] = {
 		"new_IntensityDataIOFactory() -> IntensityDataIOFactory\n"
 		"\n"
 		"\n"
-		"Provides users with possibility to read and write IntensityData from/to files in different format. Type of the file will be deduced from file name. *.txt - ASCII file with 2D array [nrow][ncol], layout as in numpy. *.int - BornAgain internal ASCII format. *.tif - 32-bits tiff file. If file name ends woth \"*.gz\" or \"*.bz2\" the file will be zipped on the fly using appropriate algorithm. Usage:\n"
+		"Provides users with possibility to read and write IntensityData from/to files in different format. Type of the file will be deduced from file name. *.txt - ASCII file with 2D array [nrow][ncol], layout as in numpy. *.int - BornAgain internal ASCII format. *.tif - 32-bits tiff file. If file name ends woth \"*.gz\" or \"*.bz2\" the file will be zipped on the fly using appropriate algorithm.\n"
+		"\n"
+		"Usage:\n"
 		"\n"
 		"C++ includes: IntensityDataIOFactory.h\n"
 		"\n"
@@ -49005,6 +49001,7 @@ static swig_type_info _swigt__p_INodeVisitor = {"_p_INodeVisitor", "INodeVisitor
 static swig_type_info _swigt__p_IParameterized = {"_p_IParameterized", "IParameterized *", 0, 0, (void*)0, 0};
 static swig_type_info _swigt__p_ParameterDistribution = {"_p_ParameterDistribution", 0, 0, 0, 0, 0};
 static swig_type_info _swigt__p_IPixel = {"_p_IPixel", "IPixel *", 0, 0, (void*)0, 0};
+static swig_type_info _swigt__p_IRangedDistribution = {"_p_IRangedDistribution", "IRangedDistribution *", 0, 0, (void*)0, 0};
 static swig_type_info _swigt__p_IResolutionFunction2D = {"_p_IResolutionFunction2D", "IResolutionFunction2D *", 0, 0, (void*)0, 0};
 static swig_type_info _swigt__p_IShape2D = {"_p_IShape2D", "IShape2D *", 0, 0, (void*)0, 0};
 static swig_type_info _swigt__p_IUnitConverter = {"_p_IUnitConverter", "IUnitConverter *", 0, 0, (void*)0, 0};
@@ -49022,7 +49019,6 @@ static swig_type_info _swigt__p_OutputDataT_bool_t = {"_p_OutputDataT_bool_t", "
 static swig_type_info _swigt__p_OutputDataT_double_t = {"_p_OutputDataT_double_t", "OutputData< double > *", 0, 0, (void*)0, 0};
 static swig_type_info _swigt__p_Polygon = {"_p_Polygon", "Polygon *", 0, 0, (void*)0, 0};
 static swig_type_info _swigt__p_PolygonPrivate = {"_p_PolygonPrivate", "PolygonPrivate *", 0, 0, (void*)0, 0};
-static swig_type_info _swigt__p_RangedDistribution = {"_p_RangedDistribution", "RangedDistribution *", 0, 0, (void*)0, 0};
 static swig_type_info _swigt__p_Rectangle = {"_p_Rectangle", "Rectangle *", 0, 0, (void*)0, 0};
 static swig_type_info _swigt__p_RectangularDetector = {"_p_RectangularDetector", "RectangularDetector *", 0, 0, (void*)0, 0};
 static swig_type_info _swigt__p_RectangularPixel = {"_p_RectangularPixel", "RectangularPixel *", 0, 0, (void*)0, 0};
@@ -49124,6 +49120,7 @@ static swig_type_info *swig_type_initial[] = {
   &_swigt__p_INodeVisitor,
   &_swigt__p_IParameterized,
   &_swigt__p_IPixel,
+  &_swigt__p_IRangedDistribution,
   &_swigt__p_IResolutionFunction2D,
   &_swigt__p_IShape2D,
   &_swigt__p_IUnitConverter,
@@ -49143,7 +49140,6 @@ static swig_type_info *swig_type_initial[] = {
   &_swigt__p_ParameterPool,
   &_swigt__p_Polygon,
   &_swigt__p_PolygonPrivate,
-  &_swigt__p_RangedDistribution,
   &_swigt__p_Rectangle,
   &_swigt__p_RectangularDetector,
   &_swigt__p_RectangularPixel,
@@ -49247,6 +49243,7 @@ static swig_cast_info _swigc__p_INodeVisitor[] = {  {&_swigt__p_INodeVisitor, 0,
 static swig_cast_info _swigc__p_ParameterDistribution[] = {{&_swigt__p_ParameterDistribution, 0, 0, 0},{0, 0, 0, 0}};
 static swig_cast_info _swigc__p_IParameterized[] = {  {&_swigt__p_Beam, _p_BeamTo_p_IParameterized, 0, 0},  {&_swigt__p_FootprintGauss, _p_FootprintGaussTo_p_IParameterized, 0, 0},  {&_swigt__p_IDetectorResolution, _p_IDetectorResolutionTo_p_IParameterized, 0, 0},  {&_swigt__p_IDetector2D, _p_IDetector2DTo_p_IParameterized, 0, 0},  {&_swigt__p_ResolutionFunction2DGaussian, _p_ResolutionFunction2DGaussianTo_p_IParameterized, 0, 0},  {&_swigt__p_IFootprintFactor, _p_IFootprintFactorTo_p_IParameterized, 0, 0},  {&_swigt__p_Instrument, _p_InstrumentTo_p_IParameterized, 0, 0},  {&_swigt__p_IDetector, _p_IDetectorTo_p_IParameterized, 0, 0},  {&_swigt__p_IsGISAXSDetector, _p_IsGISAXSDetectorTo_p_IParameterized, 0, 0},  {&_swigt__p_SphericalDetector, _p_SphericalDetectorTo_p_IParameterized, 0, 0},  {&_swigt__p_RectangularDetector, _p_RectangularDetectorTo_p_IParameterized, 0, 0},  {&_swigt__p_ParameterDistribution, _p_ParameterDistributionTo_p_IParameterized, 0, 0},  {&_swigt__p_FootprintSquare, _p_FootprintSquareTo_p_IParameterized, 0, 0},  {&_swigt__p_IParameterized, 0, 0, 0},  {&_swigt__p_INode, _p_INodeTo_p_IParameterized, 0, 0},  {&_swigt__p_IResolutionFunction2D, _p_IResolutionFunction2DTo_p_IParameterized, 0, 0},{0, 0, 0, 0}};
 static swig_cast_info _swigc__p_IPixel[] = {  {&_swigt__p_IPixel, 0, 0, 0},{0, 0, 0, 0}};
+static swig_cast_info _swigc__p_IRangedDistribution[] = {  {&_swigt__p_IRangedDistribution, 0, 0, 0},{0, 0, 0, 0}};
 static swig_cast_info _swigc__p_IResolutionFunction2D[] = {  {&_swigt__p_IResolutionFunction2D, 0, 0, 0},  {&_swigt__p_ResolutionFunction2DGaussian, _p_ResolutionFunction2DGaussianTo_p_IResolutionFunction2D, 0, 0},{0, 0, 0, 0}};
 static swig_cast_info _swigc__p_IShape2D[] = {  {&_swigt__p_Polygon, _p_PolygonTo_p_IShape2D, 0, 0},  {&_swigt__p_Line, _p_LineTo_p_IShape2D, 0, 0},  {&_swigt__p_VerticalLine, _p_VerticalLineTo_p_IShape2D, 0, 0},  {&_swigt__p_Ellipse, _p_EllipseTo_p_IShape2D, 0, 0},  {&_swigt__p_HorizontalLine, _p_HorizontalLineTo_p_IShape2D, 0, 0},  {&_swigt__p_Rectangle, _p_RectangleTo_p_IShape2D, 0, 0},  {&_swigt__p_IShape2D, 0, 0, 0},{0, 0, 0, 0}};
 static swig_cast_info _swigc__p_IUnitConverter[] = {  {&_swigt__p_IUnitConverter, 0, 0, 0},{0, 0, 0, 0}};
@@ -49264,7 +49261,6 @@ static swig_cast_info _swigc__p_OutputDataT_bool_t[] = {  {&_swigt__p_OutputData
 static swig_cast_info _swigc__p_OutputDataT_double_t[] = {  {&_swigt__p_OutputDataT_double_t, 0, 0, 0},{0, 0, 0, 0}};
 static swig_cast_info _swigc__p_Polygon[] = {  {&_swigt__p_Polygon, 0, 0, 0},{0, 0, 0, 0}};
 static swig_cast_info _swigc__p_PolygonPrivate[] = {  {&_swigt__p_PolygonPrivate, 0, 0, 0},{0, 0, 0, 0}};
-static swig_cast_info _swigc__p_RangedDistribution[] = {  {&_swigt__p_RangedDistribution, 0, 0, 0},{0, 0, 0, 0}};
 static swig_cast_info _swigc__p_Rectangle[] = {  {&_swigt__p_Rectangle, 0, 0, 0},{0, 0, 0, 0}};
 static swig_cast_info _swigc__p_RectangularDetector[] = {  {&_swigt__p_RectangularDetector, 0, 0, 0},{0, 0, 0, 0}};
 static swig_cast_info _swigc__p_RectangularPixel[] = {  {&_swigt__p_RectangularPixel, 0, 0, 0},{0, 0, 0, 0}};
@@ -49366,6 +49362,7 @@ static swig_cast_info *swig_cast_initial[] = {
   _swigc__p_INodeVisitor,
   _swigc__p_IParameterized,
   _swigc__p_IPixel,
+  _swigc__p_IRangedDistribution,
   _swigc__p_IResolutionFunction2D,
   _swigc__p_IShape2D,
   _swigc__p_IUnitConverter,
@@ -49385,7 +49382,6 @@ static swig_cast_info *swig_cast_initial[] = {
   _swigc__p_ParameterPool,
   _swigc__p_Polygon,
   _swigc__p_PolygonPrivate,
-  _swigc__p_RangedDistribution,
   _swigc__p_Rectangle,
   _swigc__p_RectangularDetector,
   _swigc__p_RectangularPixel,
diff --git a/auto/Wrap/libBornAgainParam.py b/auto/Wrap/libBornAgainParam.py
index af1d487e80fc729a100c4f5a79ddee7e3a4b1e86..3af7aa4923b931bc7665d009c02f3254291cbc95 100644
--- a/auto/Wrap/libBornAgainParam.py
+++ b/auto/Wrap/libBornAgainParam.py
@@ -2793,7 +2793,7 @@ class ParameterPool(libBornAgainBase.ICloneable):
 
         Adds parameter to the pool, and returns reference to the input pointer.
 
-        Returning the input pointer allows us to concatenate function calls like pool->addParameter( new  RealParameter(...) ).setLimits(-1,+1).setFixed().setUnit("nm") 
+        Returning the input pointer allows us to concatenate function calls like pool->addParameter( new RealParameter(...) ).setLimits(-1,+1).setFixed().setUnit("nm") 
 
         """
         return _libBornAgainParam.ParameterPool_addParameter(self, newPar)
@@ -4311,6 +4311,16 @@ class RangedDistributionGate(object):
         return _libBornAgainParam.RangedDistributionGate_clone(self)
     __swig_destroy__ = _libBornAgainParam.delete_RangedDistributionGate
 
+    def name(self):
+        r"""
+        name(RangedDistributionGate self) -> std::string
+        std::string RangedDistributionGate::name() const override
+
+        Returns distribution name for python-formatted text. 
+
+        """
+        return _libBornAgainParam.RangedDistributionGate_name(self)
+
 # Register RangedDistributionGate in _libBornAgainParam:
 _libBornAgainParam.RangedDistributionGate_swigregister(RangedDistributionGate)
 
@@ -4348,6 +4358,16 @@ class RangedDistributionLorentz(object):
         return _libBornAgainParam.RangedDistributionLorentz_clone(self)
     __swig_destroy__ = _libBornAgainParam.delete_RangedDistributionLorentz
 
+    def name(self):
+        r"""
+        name(RangedDistributionLorentz self) -> std::string
+        std::string RangedDistributionLorentz::name() const override
+
+        Returns distribution name for python-formatted text. 
+
+        """
+        return _libBornAgainParam.RangedDistributionLorentz_name(self)
+
 # Register RangedDistributionLorentz in _libBornAgainParam:
 _libBornAgainParam.RangedDistributionLorentz_swigregister(RangedDistributionLorentz)
 
@@ -4385,6 +4405,16 @@ class RangedDistributionGaussian(object):
         return _libBornAgainParam.RangedDistributionGaussian_clone(self)
     __swig_destroy__ = _libBornAgainParam.delete_RangedDistributionGaussian
 
+    def name(self):
+        r"""
+        name(RangedDistributionGaussian self) -> std::string
+        std::string RangedDistributionGaussian::name() const override
+
+        Returns distribution name for python-formatted text. 
+
+        """
+        return _libBornAgainParam.RangedDistributionGaussian_name(self)
+
 # Register RangedDistributionGaussian in _libBornAgainParam:
 _libBornAgainParam.RangedDistributionGaussian_swigregister(RangedDistributionGaussian)
 
@@ -4422,6 +4452,16 @@ class RangedDistributionLogNormal(object):
         return _libBornAgainParam.RangedDistributionLogNormal_clone(self)
     __swig_destroy__ = _libBornAgainParam.delete_RangedDistributionLogNormal
 
+    def name(self):
+        r"""
+        name(RangedDistributionLogNormal self) -> std::string
+        std::string RangedDistributionLogNormal::name() const override
+
+        Returns distribution name for python-formatted text. 
+
+        """
+        return _libBornAgainParam.RangedDistributionLogNormal_name(self)
+
 # Register RangedDistributionLogNormal in _libBornAgainParam:
 _libBornAgainParam.RangedDistributionLogNormal_swigregister(RangedDistributionLogNormal)
 
@@ -4459,6 +4499,16 @@ class RangedDistributionCosine(object):
         return _libBornAgainParam.RangedDistributionCosine_clone(self)
     __swig_destroy__ = _libBornAgainParam.delete_RangedDistributionCosine
 
+    def name(self):
+        r"""
+        name(RangedDistributionCosine self) -> std::string
+        std::string RangedDistributionCosine::name() const override
+
+        Returns distribution name for python-formatted text. 
+
+        """
+        return _libBornAgainParam.RangedDistributionCosine_name(self)
+
 # Register RangedDistributionCosine in _libBornAgainParam:
 _libBornAgainParam.RangedDistributionCosine_swigregister(RangedDistributionCosine)
 
diff --git a/auto/Wrap/libBornAgainParam_wrap.cpp b/auto/Wrap/libBornAgainParam_wrap.cpp
index 0455f1ab2e556cfb0cb0b4c757f39740100028ff..b8a18971da64e504b719ff9842e49fa0ecfd989d 100644
--- a/auto/Wrap/libBornAgainParam_wrap.cpp
+++ b/auto/Wrap/libBornAgainParam_wrap.cpp
@@ -3189,40 +3189,40 @@ namespace Swig {
 #define SWIGTYPE_p_IParameterized swig_types[89]
 #define SWIGTYPE_p_IParticle swig_types[90]
 #define SWIGTYPE_p_IPeakShape swig_types[91]
-#define SWIGTYPE_p_IRotation swig_types[92]
-#define SWIGTYPE_p_ISample swig_types[93]
-#define SWIGTYPE_p_IdentityRotation swig_types[94]
-#define SWIGTYPE_p_Instrument swig_types[95]
-#define SWIGTYPE_p_InterferenceFunction1DLattice swig_types[96]
-#define SWIGTYPE_p_InterferenceFunction2DLattice swig_types[97]
-#define SWIGTYPE_p_InterferenceFunction2DParaCrystal swig_types[98]
-#define SWIGTYPE_p_InterferenceFunction2DSuperLattice swig_types[99]
-#define SWIGTYPE_p_InterferenceFunction3DLattice swig_types[100]
-#define SWIGTYPE_p_InterferenceFunctionFinite2DLattice swig_types[101]
-#define SWIGTYPE_p_InterferenceFunctionFinite3DLattice swig_types[102]
-#define SWIGTYPE_p_InterferenceFunctionHardDisk swig_types[103]
-#define SWIGTYPE_p_InterferenceFunctionNone swig_types[104]
-#define SWIGTYPE_p_InterferenceFunctionRadialParaCrystal swig_types[105]
-#define SWIGTYPE_p_InterferenceFunctionTwin swig_types[106]
-#define SWIGTYPE_p_IsGISAXSDetector swig_types[107]
-#define SWIGTYPE_p_Layer swig_types[108]
-#define SWIGTYPE_p_LayerInterface swig_types[109]
-#define SWIGTYPE_p_LayerRoughness swig_types[110]
-#define SWIGTYPE_p_MesoCrystal swig_types[111]
-#define SWIGTYPE_p_MultiLayer swig_types[112]
-#define SWIGTYPE_p_NodeMeta swig_types[113]
-#define SWIGTYPE_p_OffSpecSimulation swig_types[114]
-#define SWIGTYPE_p_ParaMeta swig_types[115]
-#define SWIGTYPE_p_ParameterDistribution swig_types[116]
-#define SWIGTYPE_p_ParameterPool swig_types[117]
-#define SWIGTYPE_p_ParameterSample swig_types[118]
-#define SWIGTYPE_p_Particle swig_types[119]
-#define SWIGTYPE_p_ParticleComposition swig_types[120]
-#define SWIGTYPE_p_ParticleCoreShell swig_types[121]
-#define SWIGTYPE_p_ParticleDistribution swig_types[122]
-#define SWIGTYPE_p_ParticleLayout swig_types[123]
-#define SWIGTYPE_p_PoissonNoiseBackground swig_types[124]
-#define SWIGTYPE_p_RangedDistribution swig_types[125]
+#define SWIGTYPE_p_IRangedDistribution swig_types[92]
+#define SWIGTYPE_p_IRotation swig_types[93]
+#define SWIGTYPE_p_ISample swig_types[94]
+#define SWIGTYPE_p_IdentityRotation swig_types[95]
+#define SWIGTYPE_p_Instrument swig_types[96]
+#define SWIGTYPE_p_InterferenceFunction1DLattice swig_types[97]
+#define SWIGTYPE_p_InterferenceFunction2DLattice swig_types[98]
+#define SWIGTYPE_p_InterferenceFunction2DParaCrystal swig_types[99]
+#define SWIGTYPE_p_InterferenceFunction2DSuperLattice swig_types[100]
+#define SWIGTYPE_p_InterferenceFunction3DLattice swig_types[101]
+#define SWIGTYPE_p_InterferenceFunctionFinite2DLattice swig_types[102]
+#define SWIGTYPE_p_InterferenceFunctionFinite3DLattice swig_types[103]
+#define SWIGTYPE_p_InterferenceFunctionHardDisk swig_types[104]
+#define SWIGTYPE_p_InterferenceFunctionNone swig_types[105]
+#define SWIGTYPE_p_InterferenceFunctionRadialParaCrystal swig_types[106]
+#define SWIGTYPE_p_InterferenceFunctionTwin swig_types[107]
+#define SWIGTYPE_p_IsGISAXSDetector swig_types[108]
+#define SWIGTYPE_p_Layer swig_types[109]
+#define SWIGTYPE_p_LayerInterface swig_types[110]
+#define SWIGTYPE_p_LayerRoughness swig_types[111]
+#define SWIGTYPE_p_MesoCrystal swig_types[112]
+#define SWIGTYPE_p_MultiLayer swig_types[113]
+#define SWIGTYPE_p_NodeMeta swig_types[114]
+#define SWIGTYPE_p_OffSpecSimulation swig_types[115]
+#define SWIGTYPE_p_ParaMeta swig_types[116]
+#define SWIGTYPE_p_ParameterDistribution swig_types[117]
+#define SWIGTYPE_p_ParameterPool swig_types[118]
+#define SWIGTYPE_p_ParameterSample swig_types[119]
+#define SWIGTYPE_p_Particle swig_types[120]
+#define SWIGTYPE_p_ParticleComposition swig_types[121]
+#define SWIGTYPE_p_ParticleCoreShell swig_types[122]
+#define SWIGTYPE_p_ParticleDistribution swig_types[123]
+#define SWIGTYPE_p_ParticleLayout swig_types[124]
+#define SWIGTYPE_p_PoissonNoiseBackground swig_types[125]
 #define SWIGTYPE_p_RangedDistributionCosine swig_types[126]
 #define SWIGTYPE_p_RangedDistributionGate swig_types[127]
 #define SWIGTYPE_p_RangedDistributionGaussian swig_types[128]
@@ -46576,6 +46576,29 @@ fail:
 }
 
 
+SWIGINTERN PyObject *_wrap_RangedDistributionGate_name(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *resultobj = 0;
+  RangedDistributionGate *arg1 = (RangedDistributionGate *) 0 ;
+  void *argp1 = 0 ;
+  int res1 = 0 ;
+  PyObject *swig_obj[1] ;
+  std::string result;
+  
+  if (!args) SWIG_fail;
+  swig_obj[0] = args;
+  res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_RangedDistributionGate, 0 |  0 );
+  if (!SWIG_IsOK(res1)) {
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "RangedDistributionGate_name" "', argument " "1"" of type '" "RangedDistributionGate const *""'"); 
+  }
+  arg1 = reinterpret_cast< RangedDistributionGate * >(argp1);
+  result = ((RangedDistributionGate const *)arg1)->name();
+  resultobj = SWIG_From_std_string(static_cast< std::string >(result));
+  return resultobj;
+fail:
+  return NULL;
+}
+
+
 SWIGINTERN PyObject *RangedDistributionGate_swigregister(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
   PyObject *obj;
   if (!SWIG_Python_UnpackTuple(args, "swigregister", 1, 1, &obj)) return NULL;
@@ -46846,6 +46869,29 @@ fail:
 }
 
 
+SWIGINTERN PyObject *_wrap_RangedDistributionLorentz_name(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *resultobj = 0;
+  RangedDistributionLorentz *arg1 = (RangedDistributionLorentz *) 0 ;
+  void *argp1 = 0 ;
+  int res1 = 0 ;
+  PyObject *swig_obj[1] ;
+  std::string result;
+  
+  if (!args) SWIG_fail;
+  swig_obj[0] = args;
+  res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_RangedDistributionLorentz, 0 |  0 );
+  if (!SWIG_IsOK(res1)) {
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "RangedDistributionLorentz_name" "', argument " "1"" of type '" "RangedDistributionLorentz const *""'"); 
+  }
+  arg1 = reinterpret_cast< RangedDistributionLorentz * >(argp1);
+  result = ((RangedDistributionLorentz const *)arg1)->name();
+  resultobj = SWIG_From_std_string(static_cast< std::string >(result));
+  return resultobj;
+fail:
+  return NULL;
+}
+
+
 SWIGINTERN PyObject *RangedDistributionLorentz_swigregister(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
   PyObject *obj;
   if (!SWIG_Python_UnpackTuple(args, "swigregister", 1, 1, &obj)) return NULL;
@@ -47116,6 +47162,29 @@ fail:
 }
 
 
+SWIGINTERN PyObject *_wrap_RangedDistributionGaussian_name(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *resultobj = 0;
+  RangedDistributionGaussian *arg1 = (RangedDistributionGaussian *) 0 ;
+  void *argp1 = 0 ;
+  int res1 = 0 ;
+  PyObject *swig_obj[1] ;
+  std::string result;
+  
+  if (!args) SWIG_fail;
+  swig_obj[0] = args;
+  res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_RangedDistributionGaussian, 0 |  0 );
+  if (!SWIG_IsOK(res1)) {
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "RangedDistributionGaussian_name" "', argument " "1"" of type '" "RangedDistributionGaussian const *""'"); 
+  }
+  arg1 = reinterpret_cast< RangedDistributionGaussian * >(argp1);
+  result = ((RangedDistributionGaussian const *)arg1)->name();
+  resultobj = SWIG_From_std_string(static_cast< std::string >(result));
+  return resultobj;
+fail:
+  return NULL;
+}
+
+
 SWIGINTERN PyObject *RangedDistributionGaussian_swigregister(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
   PyObject *obj;
   if (!SWIG_Python_UnpackTuple(args, "swigregister", 1, 1, &obj)) return NULL;
@@ -47386,6 +47455,29 @@ fail:
 }
 
 
+SWIGINTERN PyObject *_wrap_RangedDistributionLogNormal_name(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *resultobj = 0;
+  RangedDistributionLogNormal *arg1 = (RangedDistributionLogNormal *) 0 ;
+  void *argp1 = 0 ;
+  int res1 = 0 ;
+  PyObject *swig_obj[1] ;
+  std::string result;
+  
+  if (!args) SWIG_fail;
+  swig_obj[0] = args;
+  res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_RangedDistributionLogNormal, 0 |  0 );
+  if (!SWIG_IsOK(res1)) {
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "RangedDistributionLogNormal_name" "', argument " "1"" of type '" "RangedDistributionLogNormal const *""'"); 
+  }
+  arg1 = reinterpret_cast< RangedDistributionLogNormal * >(argp1);
+  result = ((RangedDistributionLogNormal const *)arg1)->name();
+  resultobj = SWIG_From_std_string(static_cast< std::string >(result));
+  return resultobj;
+fail:
+  return NULL;
+}
+
+
 SWIGINTERN PyObject *RangedDistributionLogNormal_swigregister(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
   PyObject *obj;
   if (!SWIG_Python_UnpackTuple(args, "swigregister", 1, 1, &obj)) return NULL;
@@ -47656,6 +47748,29 @@ fail:
 }
 
 
+SWIGINTERN PyObject *_wrap_RangedDistributionCosine_name(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *resultobj = 0;
+  RangedDistributionCosine *arg1 = (RangedDistributionCosine *) 0 ;
+  void *argp1 = 0 ;
+  int res1 = 0 ;
+  PyObject *swig_obj[1] ;
+  std::string result;
+  
+  if (!args) SWIG_fail;
+  swig_obj[0] = args;
+  res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_RangedDistributionCosine, 0 |  0 );
+  if (!SWIG_IsOK(res1)) {
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "RangedDistributionCosine_name" "', argument " "1"" of type '" "RangedDistributionCosine const *""'"); 
+  }
+  arg1 = reinterpret_cast< RangedDistributionCosine * >(argp1);
+  result = ((RangedDistributionCosine const *)arg1)->name();
+  resultobj = SWIG_From_std_string(static_cast< std::string >(result));
+  return resultobj;
+fail:
+  return NULL;
+}
+
+
 SWIGINTERN PyObject *RangedDistributionCosine_swigregister(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
   PyObject *obj;
   if (!SWIG_Python_UnpackTuple(args, "swigregister", 1, 1, &obj)) return NULL;
@@ -50769,7 +50884,7 @@ static PyMethodDef SwigMethods[] = {
 		"\n"
 		"Adds parameter to the pool, and returns reference to the input pointer.\n"
 		"\n"
-		"Returning the input pointer allows us to concatenate function calls like pool->addParameter( new  RealParameter(...) ).setLimits(-1,+1).setFixed().setUnit(\"nm\") \n"
+		"Returning the input pointer allows us to concatenate function calls like pool->addParameter( new RealParameter(...) ).setLimits(-1,+1).setFixed().setUnit(\"nm\") \n"
 		"\n"
 		""},
 	 { "ParameterPool_parameter", _wrap_ParameterPool_parameter, METH_VARARGS, "\n"
@@ -51717,6 +51832,13 @@ static PyMethodDef SwigMethods[] = {
 		"RangedDistributionGate::~RangedDistributionGate() override=default\n"
 		"\n"
 		""},
+	 { "RangedDistributionGate_name", _wrap_RangedDistributionGate_name, METH_O, "\n"
+		"RangedDistributionGate_name(RangedDistributionGate self) -> std::string\n"
+		"std::string RangedDistributionGate::name() const override\n"
+		"\n"
+		"Returns distribution name for python-formatted text. \n"
+		"\n"
+		""},
 	 { "RangedDistributionGate_swigregister", RangedDistributionGate_swigregister, METH_O, NULL},
 	 { "RangedDistributionGate_swiginit", RangedDistributionGate_swiginit, METH_VARARGS, NULL},
 	 { "new_RangedDistributionLorentz", _wrap_new_RangedDistributionLorentz, METH_VARARGS, "\n"
@@ -51738,6 +51860,13 @@ static PyMethodDef SwigMethods[] = {
 		"RangedDistributionLorentz::~RangedDistributionLorentz() override=default\n"
 		"\n"
 		""},
+	 { "RangedDistributionLorentz_name", _wrap_RangedDistributionLorentz_name, METH_O, "\n"
+		"RangedDistributionLorentz_name(RangedDistributionLorentz self) -> std::string\n"
+		"std::string RangedDistributionLorentz::name() const override\n"
+		"\n"
+		"Returns distribution name for python-formatted text. \n"
+		"\n"
+		""},
 	 { "RangedDistributionLorentz_swigregister", RangedDistributionLorentz_swigregister, METH_O, NULL},
 	 { "RangedDistributionLorentz_swiginit", RangedDistributionLorentz_swiginit, METH_VARARGS, NULL},
 	 { "new_RangedDistributionGaussian", _wrap_new_RangedDistributionGaussian, METH_VARARGS, "\n"
@@ -51759,6 +51888,13 @@ static PyMethodDef SwigMethods[] = {
 		"RangedDistributionGaussian::~RangedDistributionGaussian() override=default\n"
 		"\n"
 		""},
+	 { "RangedDistributionGaussian_name", _wrap_RangedDistributionGaussian_name, METH_O, "\n"
+		"RangedDistributionGaussian_name(RangedDistributionGaussian self) -> std::string\n"
+		"std::string RangedDistributionGaussian::name() const override\n"
+		"\n"
+		"Returns distribution name for python-formatted text. \n"
+		"\n"
+		""},
 	 { "RangedDistributionGaussian_swigregister", RangedDistributionGaussian_swigregister, METH_O, NULL},
 	 { "RangedDistributionGaussian_swiginit", RangedDistributionGaussian_swiginit, METH_VARARGS, NULL},
 	 { "new_RangedDistributionLogNormal", _wrap_new_RangedDistributionLogNormal, METH_VARARGS, "\n"
@@ -51780,6 +51916,13 @@ static PyMethodDef SwigMethods[] = {
 		"RangedDistributionLogNormal::~RangedDistributionLogNormal() override=default\n"
 		"\n"
 		""},
+	 { "RangedDistributionLogNormal_name", _wrap_RangedDistributionLogNormal_name, METH_O, "\n"
+		"RangedDistributionLogNormal_name(RangedDistributionLogNormal self) -> std::string\n"
+		"std::string RangedDistributionLogNormal::name() const override\n"
+		"\n"
+		"Returns distribution name for python-formatted text. \n"
+		"\n"
+		""},
 	 { "RangedDistributionLogNormal_swigregister", RangedDistributionLogNormal_swigregister, METH_O, NULL},
 	 { "RangedDistributionLogNormal_swiginit", RangedDistributionLogNormal_swiginit, METH_VARARGS, NULL},
 	 { "new_RangedDistributionCosine", _wrap_new_RangedDistributionCosine, METH_VARARGS, "\n"
@@ -51801,6 +51944,13 @@ static PyMethodDef SwigMethods[] = {
 		"RangedDistributionCosine::~RangedDistributionCosine() override=default\n"
 		"\n"
 		""},
+	 { "RangedDistributionCosine_name", _wrap_RangedDistributionCosine_name, METH_O, "\n"
+		"RangedDistributionCosine_name(RangedDistributionCosine self) -> std::string\n"
+		"std::string RangedDistributionCosine::name() const override\n"
+		"\n"
+		"Returns distribution name for python-formatted text. \n"
+		"\n"
+		""},
 	 { "RangedDistributionCosine_swigregister", RangedDistributionCosine_swigregister, METH_O, NULL},
 	 { "RangedDistributionCosine_swiginit", RangedDistributionCosine_swiginit, METH_VARARGS, NULL},
 	 { "new_ParameterSample", _wrap_new_ParameterSample, METH_VARARGS, "\n"
@@ -51917,23 +52067,23 @@ static void *_p_DistributionTrapezoidTo_p_IParameterized(void *x, int *SWIGUNUSE
 static void *_p_DistributionLogNormalTo_p_IParameterized(void *x, int *SWIGUNUSEDPARM(newmemory)) {
     return (void *)((IParameterized *) (INode *)(IDistribution1D *) ((DistributionLogNormal *) x));
 }
-static void *_p_RangedDistributionCosineTo_p_RangedDistribution(void *x, int *SWIGUNUSEDPARM(newmemory)) {
-    return (void *)((RangedDistribution *)  ((RangedDistributionCosine *) x));
+static void *_p_RangedDistributionCosineTo_p_IRangedDistribution(void *x, int *SWIGUNUSEDPARM(newmemory)) {
+    return (void *)((IRangedDistribution *)  ((RangedDistributionCosine *) x));
 }
-static void *_p_RangedDistributionLorentzTo_p_RangedDistribution(void *x, int *SWIGUNUSEDPARM(newmemory)) {
-    return (void *)((RangedDistribution *)  ((RangedDistributionLorentz *) x));
+static void *_p_RangedDistributionLorentzTo_p_IRangedDistribution(void *x, int *SWIGUNUSEDPARM(newmemory)) {
+    return (void *)((IRangedDistribution *)  ((RangedDistributionLorentz *) x));
 }
-static void *_p_RangedDistributionGaussianTo_p_RangedDistribution(void *x, int *SWIGUNUSEDPARM(newmemory)) {
-    return (void *)((RangedDistribution *)  ((RangedDistributionGaussian *) x));
+static void *_p_RangedDistributionGaussianTo_p_IRangedDistribution(void *x, int *SWIGUNUSEDPARM(newmemory)) {
+    return (void *)((IRangedDistribution *)  ((RangedDistributionGaussian *) x));
 }
-static void *_p_RangedDistributionGateTo_p_RangedDistribution(void *x, int *SWIGUNUSEDPARM(newmemory)) {
-    return (void *)((RangedDistribution *)  ((RangedDistributionGate *) x));
+static void *_p_RangedDistributionGateTo_p_IRangedDistribution(void *x, int *SWIGUNUSEDPARM(newmemory)) {
+    return (void *)((IRangedDistribution *)  ((RangedDistributionGate *) x));
 }
-static void *_p_RangedDistributionLogNormalTo_p_RangedDistribution(void *x, int *SWIGUNUSEDPARM(newmemory)) {
-    return (void *)((RangedDistribution *)  ((RangedDistributionLogNormal *) x));
+static void *_p_RangedDistributionLogNormalTo_p_IRangedDistribution(void *x, int *SWIGUNUSEDPARM(newmemory)) {
+    return (void *)((IRangedDistribution *)  ((RangedDistributionLogNormal *) x));
 }
 static void *_p_RangedDistributionGateTo_p_ICloneable(void *x, int *SWIGUNUSEDPARM(newmemory)) {
-    return (void *)((ICloneable *) (RangedDistribution *) ((RangedDistributionGate *) x));
+    return (void *)((ICloneable *) (IRangedDistribution *) ((RangedDistributionGate *) x));
 }
 static void *_p_DistributionGateTo_p_ICloneable(void *x, int *SWIGUNUSEDPARM(newmemory)) {
     return (void *)((ICloneable *) (IDistribution1D *) ((DistributionGate *) x));
@@ -51945,7 +52095,7 @@ static void *_p_DistributionTrapezoidTo_p_ICloneable(void *x, int *SWIGUNUSEDPAR
     return (void *)((ICloneable *) (IDistribution1D *) ((DistributionTrapezoid *) x));
 }
 static void *_p_RangedDistributionGaussianTo_p_ICloneable(void *x, int *SWIGUNUSEDPARM(newmemory)) {
-    return (void *)((ICloneable *) (RangedDistribution *) ((RangedDistributionGaussian *) x));
+    return (void *)((ICloneable *) (IRangedDistribution *) ((RangedDistributionGaussian *) x));
 }
 static void *_p_DistributionGaussianTo_p_ICloneable(void *x, int *SWIGUNUSEDPARM(newmemory)) {
     return (void *)((ICloneable *) (IDistribution1D *) ((DistributionGaussian *) x));
@@ -51954,25 +52104,25 @@ static void *_p_ParameterPoolTo_p_ICloneable(void *x, int *SWIGUNUSEDPARM(newmem
     return (void *)((ICloneable *)  ((ParameterPool *) x));
 }
 static void *_p_RangedDistributionCosineTo_p_ICloneable(void *x, int *SWIGUNUSEDPARM(newmemory)) {
-    return (void *)((ICloneable *) (RangedDistribution *) ((RangedDistributionCosine *) x));
+    return (void *)((ICloneable *) (IRangedDistribution *) ((RangedDistributionCosine *) x));
 }
 static void *_p_DistributionCosineTo_p_ICloneable(void *x, int *SWIGUNUSEDPARM(newmemory)) {
     return (void *)((ICloneable *) (IDistribution1D *) ((DistributionCosine *) x));
 }
 static void *_p_RangedDistributionLorentzTo_p_ICloneable(void *x, int *SWIGUNUSEDPARM(newmemory)) {
-    return (void *)((ICloneable *) (RangedDistribution *) ((RangedDistributionLorentz *) x));
+    return (void *)((ICloneable *) (IRangedDistribution *) ((RangedDistributionLorentz *) x));
 }
 static void *_p_DistributionLorentzTo_p_ICloneable(void *x, int *SWIGUNUSEDPARM(newmemory)) {
     return (void *)((ICloneable *) (IDistribution1D *) ((DistributionLorentz *) x));
 }
 static void *_p_RangedDistributionLogNormalTo_p_ICloneable(void *x, int *SWIGUNUSEDPARM(newmemory)) {
-    return (void *)((ICloneable *) (RangedDistribution *) ((RangedDistributionLogNormal *) x));
+    return (void *)((ICloneable *) (IRangedDistribution *) ((RangedDistributionLogNormal *) x));
 }
 static void *_p_DistributionLogNormalTo_p_ICloneable(void *x, int *SWIGUNUSEDPARM(newmemory)) {
     return (void *)((ICloneable *) (IDistribution1D *) ((DistributionLogNormal *) x));
 }
-static void *_p_RangedDistributionTo_p_ICloneable(void *x, int *SWIGUNUSEDPARM(newmemory)) {
-    return (void *)((ICloneable *)  ((RangedDistribution *) x));
+static void *_p_IRangedDistributionTo_p_ICloneable(void *x, int *SWIGUNUSEDPARM(newmemory)) {
+    return (void *)((ICloneable *)  ((IRangedDistribution *) x));
 }
 static void *_p_DistributionCosineTo_p_INode(void *x, int *SWIGUNUSEDPARM(newmemory)) {
     return (void *)((INode *) (IDistribution1D *) ((DistributionCosine *) x));
@@ -52105,6 +52255,7 @@ static swig_type_info _swigt__p_IParameterT_double_t = {"_p_IParameterT_double_t
 static swig_type_info _swigt__p_IParameterized = {"_p_IParameterized", "IParameterized *", 0, 0, (void*)0, 0};
 static swig_type_info _swigt__p_IParticle = {"_p_IParticle", "IParticle *", 0, 0, (void*)0, 0};
 static swig_type_info _swigt__p_IPeakShape = {"_p_IPeakShape", "IPeakShape *", 0, 0, (void*)0, 0};
+static swig_type_info _swigt__p_IRangedDistribution = {"_p_IRangedDistribution", "IRangedDistribution *", 0, 0, (void*)0, 0};
 static swig_type_info _swigt__p_IRotation = {"_p_IRotation", "IRotation *", 0, 0, (void*)0, 0};
 static swig_type_info _swigt__p_ISample = {"_p_ISample", "ISample *", 0, 0, (void*)0, 0};
 static swig_type_info _swigt__p_IdentityRotation = {"_p_IdentityRotation", "IdentityRotation *", 0, 0, (void*)0, 0};
@@ -52138,7 +52289,6 @@ static swig_type_info _swigt__p_ParticleCoreShell = {"_p_ParticleCoreShell", "Pa
 static swig_type_info _swigt__p_ParticleDistribution = {"_p_ParticleDistribution", "ParticleDistribution *", 0, 0, (void*)0, 0};
 static swig_type_info _swigt__p_ParticleLayout = {"_p_ParticleLayout", "ParticleLayout *", 0, 0, (void*)0, 0};
 static swig_type_info _swigt__p_PoissonNoiseBackground = {"_p_PoissonNoiseBackground", "PoissonNoiseBackground *", 0, 0, (void*)0, 0};
-static swig_type_info _swigt__p_RangedDistribution = {"_p_RangedDistribution", "RangedDistribution *", 0, 0, (void*)0, 0};
 static swig_type_info _swigt__p_RangedDistributionCosine = {"_p_RangedDistributionCosine", "RangedDistributionCosine *", 0, 0, (void*)0, 0};
 static swig_type_info _swigt__p_RangedDistributionGate = {"_p_RangedDistributionGate", "RangedDistributionGate *", 0, 0, (void*)0, 0};
 static swig_type_info _swigt__p_RangedDistributionGaussian = {"_p_RangedDistributionGaussian", "RangedDistributionGaussian *", 0, 0, (void*)0, 0};
@@ -52305,6 +52455,7 @@ static swig_type_info *swig_type_initial[] = {
   &_swigt__p_IParameterized,
   &_swigt__p_IParticle,
   &_swigt__p_IPeakShape,
+  &_swigt__p_IRangedDistribution,
   &_swigt__p_IRotation,
   &_swigt__p_ISample,
   &_swigt__p_IdentityRotation,
@@ -52338,7 +52489,6 @@ static swig_type_info *swig_type_initial[] = {
   &_swigt__p_ParticleDistribution,
   &_swigt__p_ParticleLayout,
   &_swigt__p_PoissonNoiseBackground,
-  &_swigt__p_RangedDistribution,
   &_swigt__p_RangedDistributionCosine,
   &_swigt__p_RangedDistributionGate,
   &_swigt__p_RangedDistributionGaussian,
@@ -52493,7 +52643,7 @@ static swig_cast_info _swigc__p_GISASSimulation[] = {  {&_swigt__p_GISASSimulati
 static swig_cast_info _swigc__p_HexagonalLattice2D[] = {  {&_swigt__p_HexagonalLattice2D, 0, 0, 0},{0, 0, 0, 0}};
 static swig_cast_info _swigc__p_IAbstractParticle[] = {  {&_swigt__p_IAbstractParticle, 0, 0, 0},{0, 0, 0, 0}};
 static swig_cast_info _swigc__p_IBornFF[] = {  {&_swigt__p_IBornFF, 0, 0, 0},{0, 0, 0, 0}};
-static swig_cast_info _swigc__p_ICloneable[] = {  {&_swigt__p_RangedDistributionGate, _p_RangedDistributionGateTo_p_ICloneable, 0, 0},  {&_swigt__p_DistributionGate, _p_DistributionGateTo_p_ICloneable, 0, 0},  {&_swigt__p_IDistribution1D, _p_IDistribution1DTo_p_ICloneable, 0, 0},  {&_swigt__p_DistributionTrapezoid, _p_DistributionTrapezoidTo_p_ICloneable, 0, 0},  {&_swigt__p_ICloneable, 0, 0, 0},  {&_swigt__p_RangedDistributionGaussian, _p_RangedDistributionGaussianTo_p_ICloneable, 0, 0},  {&_swigt__p_DistributionGaussian, _p_DistributionGaussianTo_p_ICloneable, 0, 0},  {&_swigt__p_ParameterPool, _p_ParameterPoolTo_p_ICloneable, 0, 0},  {&_swigt__p_RangedDistributionCosine, _p_RangedDistributionCosineTo_p_ICloneable, 0, 0},  {&_swigt__p_DistributionCosine, _p_DistributionCosineTo_p_ICloneable, 0, 0},  {&_swigt__p_RangedDistributionLorentz, _p_RangedDistributionLorentzTo_p_ICloneable, 0, 0},  {&_swigt__p_DistributionLorentz, _p_DistributionLorentzTo_p_ICloneable, 0, 0},  {&_swigt__p_RangedDistributionLogNormal, _p_RangedDistributionLogNormalTo_p_ICloneable, 0, 0},  {&_swigt__p_DistributionLogNormal, _p_DistributionLogNormalTo_p_ICloneable, 0, 0},  {&_swigt__p_RangedDistribution, _p_RangedDistributionTo_p_ICloneable, 0, 0},{0, 0, 0, 0}};
+static swig_cast_info _swigc__p_ICloneable[] = {  {&_swigt__p_RangedDistributionGate, _p_RangedDistributionGateTo_p_ICloneable, 0, 0},  {&_swigt__p_DistributionGate, _p_DistributionGateTo_p_ICloneable, 0, 0},  {&_swigt__p_IDistribution1D, _p_IDistribution1DTo_p_ICloneable, 0, 0},  {&_swigt__p_DistributionTrapezoid, _p_DistributionTrapezoidTo_p_ICloneable, 0, 0},  {&_swigt__p_ICloneable, 0, 0, 0},  {&_swigt__p_RangedDistributionGaussian, _p_RangedDistributionGaussianTo_p_ICloneable, 0, 0},  {&_swigt__p_DistributionGaussian, _p_DistributionGaussianTo_p_ICloneable, 0, 0},  {&_swigt__p_ParameterPool, _p_ParameterPoolTo_p_ICloneable, 0, 0},  {&_swigt__p_RangedDistributionCosine, _p_RangedDistributionCosineTo_p_ICloneable, 0, 0},  {&_swigt__p_DistributionCosine, _p_DistributionCosineTo_p_ICloneable, 0, 0},  {&_swigt__p_RangedDistributionLorentz, _p_RangedDistributionLorentzTo_p_ICloneable, 0, 0},  {&_swigt__p_DistributionLorentz, _p_DistributionLorentzTo_p_ICloneable, 0, 0},  {&_swigt__p_RangedDistributionLogNormal, _p_RangedDistributionLogNormalTo_p_ICloneable, 0, 0},  {&_swigt__p_DistributionLogNormal, _p_DistributionLogNormalTo_p_ICloneable, 0, 0},  {&_swigt__p_IRangedDistribution, _p_IRangedDistributionTo_p_ICloneable, 0, 0},{0, 0, 0, 0}};
 static swig_cast_info _swigc__p_IClusteredParticles[] = {  {&_swigt__p_IClusteredParticles, 0, 0, 0},{0, 0, 0, 0}};
 static swig_cast_info _swigc__p_IDistribution1D[] = {  {&_swigt__p_DistributionCosine, _p_DistributionCosineTo_p_IDistribution1D, 0, 0},  {&_swigt__p_DistributionLorentz, _p_DistributionLorentzTo_p_IDistribution1D, 0, 0},  {&_swigt__p_DistributionGaussian, _p_DistributionGaussianTo_p_IDistribution1D, 0, 0},  {&_swigt__p_IDistribution1D, 0, 0, 0},  {&_swigt__p_DistributionGate, _p_DistributionGateTo_p_IDistribution1D, 0, 0},  {&_swigt__p_DistributionTrapezoid, _p_DistributionTrapezoidTo_p_IDistribution1D, 0, 0},  {&_swigt__p_DistributionLogNormal, _p_DistributionLogNormalTo_p_IDistribution1D, 0, 0},{0, 0, 0, 0}};
 static swig_cast_info _swigc__p_IFormFactor[] = {  {&_swigt__p_IFormFactor, 0, 0, 0},{0, 0, 0, 0}};
@@ -52505,6 +52655,7 @@ static swig_cast_info _swigc__p_IParameterT_double_t[] = {  {&_swigt__p_IParamet
 static swig_cast_info _swigc__p_IParameterized[] = {  {&_swigt__p_DistributionCosine, _p_DistributionCosineTo_p_IParameterized, 0, 0},  {&_swigt__p_INode, _p_INodeTo_p_IParameterized, 0, 0},  {&_swigt__p_DistributionLorentz, _p_DistributionLorentzTo_p_IParameterized, 0, 0},  {&_swigt__p_ParameterDistribution, _p_ParameterDistributionTo_p_IParameterized, 0, 0},  {&_swigt__p_DistributionGaussian, _p_DistributionGaussianTo_p_IParameterized, 0, 0},  {&_swigt__p_IParameterized, 0, 0, 0},  {&_swigt__p_IDistribution1D, _p_IDistribution1DTo_p_IParameterized, 0, 0},  {&_swigt__p_DistributionGate, _p_DistributionGateTo_p_IParameterized, 0, 0},  {&_swigt__p_DistributionTrapezoid, _p_DistributionTrapezoidTo_p_IParameterized, 0, 0},  {&_swigt__p_DistributionLogNormal, _p_DistributionLogNormalTo_p_IParameterized, 0, 0},{0, 0, 0, 0}};
 static swig_cast_info _swigc__p_IParticle[] = {  {&_swigt__p_IParticle, 0, 0, 0},{0, 0, 0, 0}};
 static swig_cast_info _swigc__p_IPeakShape[] = {  {&_swigt__p_IPeakShape, 0, 0, 0},{0, 0, 0, 0}};
+static swig_cast_info _swigc__p_IRangedDistribution[] = {  {&_swigt__p_RangedDistributionCosine, _p_RangedDistributionCosineTo_p_IRangedDistribution, 0, 0},  {&_swigt__p_IRangedDistribution, 0, 0, 0},  {&_swigt__p_RangedDistributionLorentz, _p_RangedDistributionLorentzTo_p_IRangedDistribution, 0, 0},  {&_swigt__p_RangedDistributionGaussian, _p_RangedDistributionGaussianTo_p_IRangedDistribution, 0, 0},  {&_swigt__p_RangedDistributionGate, _p_RangedDistributionGateTo_p_IRangedDistribution, 0, 0},  {&_swigt__p_RangedDistributionLogNormal, _p_RangedDistributionLogNormalTo_p_IRangedDistribution, 0, 0},{0, 0, 0, 0}};
 static swig_cast_info _swigc__p_IRotation[] = {  {&_swigt__p_IRotation, 0, 0, 0},{0, 0, 0, 0}};
 static swig_cast_info _swigc__p_ISample[] = {  {&_swigt__p_ISample, 0, 0, 0},{0, 0, 0, 0}};
 static swig_cast_info _swigc__p_IdentityRotation[] = {  {&_swigt__p_IdentityRotation, 0, 0, 0},{0, 0, 0, 0}};
@@ -52538,7 +52689,6 @@ static swig_cast_info _swigc__p_ParticleCoreShell[] = {  {&_swigt__p_ParticleCor
 static swig_cast_info _swigc__p_ParticleDistribution[] = {  {&_swigt__p_ParticleDistribution, 0, 0, 0},{0, 0, 0, 0}};
 static swig_cast_info _swigc__p_ParticleLayout[] = {  {&_swigt__p_ParticleLayout, 0, 0, 0},{0, 0, 0, 0}};
 static swig_cast_info _swigc__p_PoissonNoiseBackground[] = {  {&_swigt__p_PoissonNoiseBackground, 0, 0, 0},{0, 0, 0, 0}};
-static swig_cast_info _swigc__p_RangedDistribution[] = {  {&_swigt__p_RangedDistributionCosine, _p_RangedDistributionCosineTo_p_RangedDistribution, 0, 0},  {&_swigt__p_RangedDistribution, 0, 0, 0},  {&_swigt__p_RangedDistributionLorentz, _p_RangedDistributionLorentzTo_p_RangedDistribution, 0, 0},  {&_swigt__p_RangedDistributionGaussian, _p_RangedDistributionGaussianTo_p_RangedDistribution, 0, 0},  {&_swigt__p_RangedDistributionGate, _p_RangedDistributionGateTo_p_RangedDistribution, 0, 0},  {&_swigt__p_RangedDistributionLogNormal, _p_RangedDistributionLogNormalTo_p_RangedDistribution, 0, 0},{0, 0, 0, 0}};
 static swig_cast_info _swigc__p_RangedDistributionCosine[] = {  {&_swigt__p_RangedDistributionCosine, 0, 0, 0},{0, 0, 0, 0}};
 static swig_cast_info _swigc__p_RangedDistributionGate[] = {  {&_swigt__p_RangedDistributionGate, 0, 0, 0},{0, 0, 0, 0}};
 static swig_cast_info _swigc__p_RangedDistributionGaussian[] = {  {&_swigt__p_RangedDistributionGaussian, 0, 0, 0},{0, 0, 0, 0}};
@@ -52705,6 +52855,7 @@ static swig_cast_info *swig_cast_initial[] = {
   _swigc__p_IParameterized,
   _swigc__p_IParticle,
   _swigc__p_IPeakShape,
+  _swigc__p_IRangedDistribution,
   _swigc__p_IRotation,
   _swigc__p_ISample,
   _swigc__p_IdentityRotation,
@@ -52738,7 +52889,6 @@ static swig_cast_info *swig_cast_initial[] = {
   _swigc__p_ParticleDistribution,
   _swigc__p_ParticleLayout,
   _swigc__p_PoissonNoiseBackground,
-  _swigc__p_RangedDistribution,
   _swigc__p_RangedDistributionCosine,
   _swigc__p_RangedDistributionGate,
   _swigc__p_RangedDistributionGaussian,
diff --git a/auto/Wrap/libBornAgainSample.py b/auto/Wrap/libBornAgainSample.py
index a41337f82643c3988ce2325456ff3383e6b8651d..2428c736f440103466448105468182b2ad4a8c3f 100644
--- a/auto/Wrap/libBornAgainSample.py
+++ b/auto/Wrap/libBornAgainSample.py
@@ -8406,7 +8406,7 @@ class MultiLayer(ISample):
     r"""
 
 
-    Our sample model: a stack of layers one below the other.Example of system of 4 layers (3 interfaces):
+    Our sample model: a stack of layers one below the other. Example of system of 4 layers (3 interfaces):
 
     ambience layer #0 ------ interface #0 z=0.0 Fe, 20A layer #1 ------ interface #1 z=-20.0 Cr, 40A layer #2 ------ interface #2 z=-60.0 substrate layer #3
 
diff --git a/devtools/code-tools/normalize-usercode.py b/devtools/code-tools/normalize-usercode.py
index b1d2436780de887e9d543cfdda7b8d492055a8c9..0c202c817b798418b64e5679a11da5e4aebb34b6 100755
--- a/devtools/code-tools/normalize-usercode.py
+++ b/devtools/code-tools/normalize-usercode.py
@@ -8,9 +8,7 @@ Export to normal form is done by BornAgain's ExportToPython function.
 import argparse
 import bornagain as ba
 
-def normalize_script(fname, inplace):
-    with open(fname, 'rb') as f:
-        ti = f.read()
+def normalize_text(ti, fname):
     c=compile(ti, fname, 'exec')
     ns = {}
     exec(c,ns)
@@ -18,20 +16,61 @@ def normalize_script(fname, inplace):
     s = get_simulation()
     s.setSample(get_sample())
     t = ba.generatePyExportTest(s)
-    if t == ti:
-        print(f'Nothing changed in file {fname}')
-        return
-    if inplace:
-        with open(fname, 'w') as f:
-            f.write(t)
-    else:
-        print(t)
+    return t
+
+def normalize_file(fname, inplace):
+    try:
+        print(f'FILE {fname}:')
+
+        # read file, normalize
+        with open(fname, 'r') as f:
+            ti = f.read()
+            if verbose:
+                print(f'.. read {len(ti.split())} lines')
+        t = normalize_text(ti, fname)
+        if verbose:
+            print(f'.. normalized')
+        if t == ti:
+            if verbose:
+                print(f'.. nothing changed')
+            return 0
+
+        # output
+        if inplace:
+            with open(fname, 'w') as f:
+                f.write(t)
+            print(f'=> NORMALIZED')
+        else:
+            print(t)
+
+        # check invariance under second normalization
+        t2 = normalize_text(t, fname)
+        if verbose:
+            print(f'.. re-normalized')
+        if t2 != t:
+            with open('reno.py', 'w') as f:
+                f.write(t2)
+            exit(f'=> BUG - changed under second normalization, see reno.py')
+
+        return 1
+
+    except Exception as e:
+        print(f'=> FAILED - {e}')
+        return 2
+
 
 if __name__ == '__main__':
 
     parser = argparse.ArgumentParser()
-    parser.add_argument("simulation_script", type=str)
+    parser.add_argument("input_files", nargs='+', type=str)
     parser.add_argument("-i", "--in-place", action="store_true")
+    parser.add_argument("-v", "--verbose", action="store_true")
     args = parser.parse_args()
+    verbose = args.verbose
+
+    count = [0, 0, 0]
+    for f in args.input_files:
+        ret = normalize_file(f, args.in_place)
+        count[ret] += 1
 
-    normalize_script(args.simulation_script, args.in_place)
+    print(f'TOTAL: {count[0]} unchanged, {count[1]} normalized, {count[2]} failed')