diff --git a/Param/Node/INode.h b/Param/Node/INode.h
index ee401a5b5aa6335ce773ddfa694d3f1351c56aff..f68756e324682d5e9d0b4d2652261ccb106fea71 100644
--- a/Param/Node/INode.h
+++ b/Param/Node/INode.h
@@ -65,12 +65,6 @@ public:
     //! Returns a vector of all descendants
     std::vector<const INode*> progeny() const;
 
-    //! Action to be taken in inherited class when a value has changed. Formerly this was also
-    //! called when a change via registered parameter took place. This is now obsolete, but the
-    //! onChange() call is still relevant for calculations when a value is changed by different
-    //! means (e.g. after initialization).
-    virtual void onChange() {}
-
     virtual std::string className() const = 0;
 
 protected:
diff --git a/Sample/Aggregate/Interference2DLattice.cpp b/Sample/Aggregate/Interference2DLattice.cpp
index 3c2b9155d769714766cdcc9fda63c70c9fd5b3f9..933ddd193d097e5bca67a1383b89a28138dbd119 100644
--- a/Sample/Aggregate/Interference2DLattice.cpp
+++ b/Sample/Aggregate/Interference2DLattice.cpp
@@ -29,7 +29,13 @@ Interference2DLattice::Interference2DLattice(const Lattice2D& lattice)
     : IInterference(0), m_integrate_xi(false)
 {
     m_lattice.reset(lattice.clone());
-    initialize_rec_vectors();
+    if (!m_lattice)
+        throw std::runtime_error("Interference2DLattice::initialize_rec_vectors() -> "
+                                 "Error. No lattice defined yet");
+
+    BasicLattice2D base_lattice(m_lattice->length1(), m_lattice->length2(),
+                                m_lattice->latticeAngle(), 0.);
+    m_sbase = base_lattice.reciprocalBases();
 }
 
 Interference2DLattice::~Interference2DLattice() = default;
@@ -49,7 +55,18 @@ Interference2DLattice* Interference2DLattice::clone() const
 void Interference2DLattice::setDecayFunction(const IFTDecayFunction2D& decay)
 {
     m_decay.reset(decay.clone());
-    initialize_calc_factors();
+    if (!m_decay)
+        throw std::runtime_error("Interference2DLattice::initialize_calc_factors"
+                                 " -> Error! No decay function defined.");
+
+    // number of reciprocal lattice points to use
+    auto q_bounds = m_decay->boundingReciprocalLatticeCoordinates(
+        nmax / m_decay->decayLengthX(), nmax / m_decay->decayLengthY(), m_lattice->length1(),
+        m_lattice->length2(), m_lattice->latticeAngle());
+    m_na = static_cast<int>(std::lround(q_bounds.first + 0.5));
+    m_nb = static_cast<int>(std::lround(q_bounds.second + 0.5));
+    m_na = std::max(m_na, min_points);
+    m_nb = std::max(m_nb, min_points);
 }
 
 void Interference2DLattice::setIntegrationOverXi(bool integrate_xi)
@@ -77,12 +94,6 @@ std::vector<const INode*> Interference2DLattice::getChildren() const
     return std::vector<const INode*>() << m_decay << m_lattice;
 }
 
-void Interference2DLattice::onChange()
-{
-    initialize_rec_vectors();
-    initialize_calc_factors();
-}
-
 double Interference2DLattice::iff_without_dw(const R3 q) const
 {
     if (!m_decay)
@@ -152,31 +163,3 @@ Interference2DLattice::calculateReciprocalVectorFraction(double qx, double qy, d
     double qy_frac = qy_rot - qa_int * m_sbase.m_asy - qb_int * m_sbase.m_bsy;
     return {qx_frac, qy_frac};
 }
-
-// Do not store xi in the reciprocal lattice
-void Interference2DLattice::initialize_rec_vectors()
-{
-    if (!m_lattice)
-        throw std::runtime_error("Interference2DLattice::initialize_rec_vectors() -> "
-                                 "Error. No lattice defined yet");
-
-    BasicLattice2D base_lattice(m_lattice->length1(), m_lattice->length2(),
-                                m_lattice->latticeAngle(), 0.);
-    m_sbase = base_lattice.reciprocalBases();
-}
-
-void Interference2DLattice::initialize_calc_factors()
-{
-    if (!m_decay)
-        throw std::runtime_error("Interference2DLattice::initialize_calc_factors"
-                                 " -> Error! No decay function defined.");
-
-    // number of reciprocal lattice points to use
-    auto q_bounds = m_decay->boundingReciprocalLatticeCoordinates(
-        nmax / m_decay->decayLengthX(), nmax / m_decay->decayLengthY(), m_lattice->length1(),
-        m_lattice->length2(), m_lattice->latticeAngle());
-    m_na = static_cast<int>(std::lround(q_bounds.first + 0.5));
-    m_nb = static_cast<int>(std::lround(q_bounds.second + 0.5));
-    m_na = std::max(m_na, min_points);
-    m_nb = std::max(m_nb, min_points);
-}
diff --git a/Sample/Aggregate/Interference2DLattice.h b/Sample/Aggregate/Interference2DLattice.h
index 88bb0a09ac08cde7e3b991849d73a15c95bf0ad8..f05b2cbd163b0870476429d559f2ba5bba2fef7e 100644
--- a/Sample/Aggregate/Interference2DLattice.h
+++ b/Sample/Aggregate/Interference2DLattice.h
@@ -47,8 +47,6 @@ public:
 
     std::vector<const INode*> getChildren() const override;
 
-    void onChange() override;
-
 private:
     double iff_without_dw(R3 q) const override;
 
@@ -65,12 +63,6 @@ private:
     std::pair<double, double> calculateReciprocalVectorFraction(double qx, double qy,
                                                                 double xi) const;
 
-    //! Initializes the x,y coordinates of the a*,b* reciprocal bases
-    void initialize_rec_vectors();
-
-    //! Initializes factors needed in each calculation
-    void initialize_calc_factors();
-
     bool m_integrate_xi; //!< Integrate over the orientation xi
     std::unique_ptr<IFTDecayFunction2D> m_decay;
     std::unique_ptr<Lattice2D> m_lattice;
diff --git a/Sample/Aggregate/Interference3DLattice.cpp b/Sample/Aggregate/Interference3DLattice.cpp
index c3dbb9247cbc61e1d1ef0433a85798fee54b581e..16abbc3ce4bfc79096ada73ad047b449686fb8b1 100644
--- a/Sample/Aggregate/Interference3DLattice.cpp
+++ b/Sample/Aggregate/Interference3DLattice.cpp
@@ -21,7 +21,12 @@
 Interference3DLattice::Interference3DLattice(const Lattice3D& lattice)
     : IInterference(0), m_lattice(lattice), m_peak_shape(nullptr), m_rec_radius(0.0)
 {
-    initRecRadius();
+    R3 a1 = m_lattice.getBasisVectorA();
+    R3 a2 = m_lattice.getBasisVectorB();
+    R3 a3 = m_lattice.getBasisVectorC();
+
+    m_rec_radius = std::max(M_PI / a1.mag(), M_PI / a2.mag());
+    m_rec_radius = std::max(m_rec_radius, M_PI / a3.mag());
 }
 
 Interference3DLattice::~Interference3DLattice() = default;
@@ -50,11 +55,6 @@ std::vector<const INode*> Interference3DLattice::getChildren() const
     return {};
 }
 
-void Interference3DLattice::onChange()
-{
-    initRecRadius();
-}
-
 double Interference3DLattice::iff_without_dw(const R3 q) const
 {
     ASSERT(m_peak_shape);
@@ -80,13 +80,3 @@ double Interference3DLattice::iff_without_dw(const R3 q) const
     //        }
     return result;
 }
-
-void Interference3DLattice::initRecRadius()
-{
-    R3 a1 = m_lattice.getBasisVectorA();
-    R3 a2 = m_lattice.getBasisVectorB();
-    R3 a3 = m_lattice.getBasisVectorC();
-
-    m_rec_radius = std::max(M_PI / a1.mag(), M_PI / a2.mag());
-    m_rec_radius = std::max(m_rec_radius, M_PI / a3.mag());
-}
diff --git a/Sample/Aggregate/Interference3DLattice.h b/Sample/Aggregate/Interference3DLattice.h
index 08f844307324b7482908cd580160ab2bcdd5f079..0176f6c4e42a9aa1fe9c13fee4beb36a0563ba87 100644
--- a/Sample/Aggregate/Interference3DLattice.h
+++ b/Sample/Aggregate/Interference3DLattice.h
@@ -43,11 +43,8 @@ public:
 
     std::vector<const INode*> getChildren() const override;
 
-    void onChange() override;
-
 private:
     double iff_without_dw(R3 q) const override;
-    void initRecRadius();
 
     Lattice3D m_lattice; // TODO unique_ptr as in other Interference%s
     std::unique_ptr<IPeakShape> m_peak_shape;
diff --git a/Sample/HardParticle/FormFactorAnisoPyramid.cpp b/Sample/HardParticle/FormFactorAnisoPyramid.cpp
index 162a0196ce38facdfc517f0e3db3d1e2e9fba0e7..28a84fc67f6a117e71ca14fe7f072334d1c83316 100644
--- a/Sample/HardParticle/FormFactorAnisoPyramid.cpp
+++ b/Sample/HardParticle/FormFactorAnisoPyramid.cpp
@@ -37,27 +37,6 @@ FormFactorAnisoPyramid::FormFactorAnisoPyramid(const std::vector<double> P)
     , m_width(m_P[1])
     , m_height(m_P[2])
     , m_alpha(m_P[3])
-{
-    onChange();
-}
-
-FormFactorAnisoPyramid::FormFactorAnisoPyramid(double length, double width, double height,
-                                               double alpha)
-    : FormFactorAnisoPyramid(std::vector<double>{length, width, height, alpha})
-{
-}
-
-IFormFactor* FormFactorAnisoPyramid::sliceFormFactor(ZLimits limits, const IRotation& rot,
-                                                     R3 translation) const
-{
-    auto effects = computeSlicingEffects(limits, translation, m_height);
-    double dbase_edge = 2 * effects.dz_bottom * Math::cot(m_alpha);
-    FormFactorAnisoPyramid slicedff(m_length - dbase_edge, m_width - dbase_edge,
-                                    m_height - effects.dz_bottom - effects.dz_top, m_alpha);
-    return createTransformedFormFactor(slicedff, rot, effects.position);
-}
-
-void FormFactorAnisoPyramid::onChange()
 {
     double cot_alpha = Math::cot(m_alpha);
     if (!std::isfinite(cot_alpha) || cot_alpha < 0)
@@ -95,3 +74,19 @@ void FormFactorAnisoPyramid::onChange()
                    {d, w, m_height - zcom},
                    {-d, w, m_height - zcom}});
 }
+
+FormFactorAnisoPyramid::FormFactorAnisoPyramid(double length, double width, double height,
+                                               double alpha)
+    : FormFactorAnisoPyramid(std::vector<double>{length, width, height, alpha})
+{
+}
+
+IFormFactor* FormFactorAnisoPyramid::sliceFormFactor(ZLimits limits, const IRotation& rot,
+                                                     R3 translation) const
+{
+    auto effects = computeSlicingEffects(limits, translation, m_height);
+    double dbase_edge = 2 * effects.dz_bottom * Math::cot(m_alpha);
+    FormFactorAnisoPyramid slicedff(m_length - dbase_edge, m_width - dbase_edge,
+                                    m_height - effects.dz_bottom - effects.dz_top, m_alpha);
+    return createTransformedFormFactor(slicedff, rot, effects.position);
+}
diff --git a/Sample/HardParticle/FormFactorAnisoPyramid.h b/Sample/HardParticle/FormFactorAnisoPyramid.h
index 554989cd8d70ad90697e65f69589a3a57f087b74..cc365832372aa0b5a3675e20bcf87d09887bce92 100644
--- a/Sample/HardParticle/FormFactorAnisoPyramid.h
+++ b/Sample/HardParticle/FormFactorAnisoPyramid.h
@@ -43,8 +43,6 @@ protected:
     IFormFactor* sliceFormFactor(ZLimits limits, const IRotation& rot,
                                  R3 translation) const override;
 
-    void onChange() override;
-
 private:
     static const ff::PolyhedralTopology topology;
 
diff --git a/Sample/HardParticle/FormFactorBox.cpp b/Sample/HardParticle/FormFactorBox.cpp
index 66727e1f3dfbbecc40905b232be787cb8605f975..f4f3ec1a382b260bd960b643d2d3b08bd177ae2b 100644
--- a/Sample/HardParticle/FormFactorBox.cpp
+++ b/Sample/HardParticle/FormFactorBox.cpp
@@ -26,7 +26,10 @@ FormFactorBox::FormFactorBox(const std::vector<double> P)
     , m_width(m_P[1])
     , m_height(m_P[2])
 {
-    onChange();
+    double a = m_length / 2;
+    double b = m_width / 2;
+    std::vector<R3> V{{a, b, 0.}, {-a, b, 0.}, {-a, -b, 0.}, {a, -b, 0}};
+    setPrism(true, V);
 }
 
 FormFactorBox::FormFactorBox(double length, double width, double height)
@@ -48,11 +51,3 @@ IFormFactor* FormFactorBox::sliceFormFactor(ZLimits limits, const IRotation& rot
     FormFactorBox slicedff(m_length, m_width, m_height - effects.dz_bottom - effects.dz_top);
     return createTransformedFormFactor(slicedff, rot, effects.position);
 }
-
-void FormFactorBox::onChange()
-{
-    double a = m_length / 2;
-    double b = m_width / 2;
-    std::vector<R3> V{{a, b, 0.}, {-a, b, 0.}, {-a, -b, 0.}, {a, -b, 0}};
-    setPrism(true, V);
-}
diff --git a/Sample/HardParticle/FormFactorBox.h b/Sample/HardParticle/FormFactorBox.h
index 033e624c2bd7e673622ef898ca5783cd82ce6e48..568d89004635e2e02fd4a6faf102293950860c73 100644
--- a/Sample/HardParticle/FormFactorBox.h
+++ b/Sample/HardParticle/FormFactorBox.h
@@ -43,7 +43,6 @@ protected:
     IFormFactor* sliceFormFactor(ZLimits limits, const IRotation& rot,
                                  R3 translation) const override;
 
-    void onChange() override;
     double height() const override { return m_height; }
 
 private:
diff --git a/Sample/HardParticle/FormFactorCantellatedCube.cpp b/Sample/HardParticle/FormFactorCantellatedCube.cpp
index 2de3e3bcd75a64db3c04ad626df3ff2e780cb1fd..5d221fe0862f3afd01c423ad7a700450d177fcbf 100644
--- a/Sample/HardParticle/FormFactorCantellatedCube.cpp
+++ b/Sample/HardParticle/FormFactorCantellatedCube.cpp
@@ -55,16 +55,6 @@ FormFactorCantellatedCube::FormFactorCantellatedCube(const std::vector<double> P
         P)
     , m_length(m_P[0])
     , m_removed_length(m_P[1])
-{
-    onChange();
-}
-
-FormFactorCantellatedCube::FormFactorCantellatedCube(double length, double removed_length)
-    : FormFactorCantellatedCube(std::vector<double>{length, removed_length})
-{
-}
-
-void FormFactorCantellatedCube::onChange()
 {
     if (m_removed_length > 0.5 * m_length) {
         std::ostringstream ostr;
@@ -85,3 +75,8 @@ void FormFactorCantellatedCube::onChange()
                                  {+a, -c, -c}, {+c, +a, -c}, {-a, +c, -c}, {-c, -c, -a}, // point 20
                                  {+c, -c, -a}, {+c, +c, -a}, {-c, +c, -a}});
 }
+
+FormFactorCantellatedCube::FormFactorCantellatedCube(double length, double removed_length)
+    : FormFactorCantellatedCube(std::vector<double>{length, removed_length})
+{
+}
diff --git a/Sample/HardParticle/FormFactorCantellatedCube.h b/Sample/HardParticle/FormFactorCantellatedCube.h
index 2c414125209ffd1e6d77fdf73468d8b4db3bafd5..4bf96946661768f02e22e0a9612e6508077bb027 100644
--- a/Sample/HardParticle/FormFactorCantellatedCube.h
+++ b/Sample/HardParticle/FormFactorCantellatedCube.h
@@ -37,9 +37,6 @@ public:
     double getLength() const { return m_length; }
     double getRemovedLength() const { return m_removed_length; }
 
-protected:
-    void onChange() override;
-
 private:
     static const ff::PolyhedralTopology topology;
     const double& m_length;
diff --git a/Sample/HardParticle/FormFactorCone.cpp b/Sample/HardParticle/FormFactorCone.cpp
index 387d2da1f1585330615172311e6d828712fa498c..c47254883a3758e64827ec8f57df8a05fd14fd64 100644
--- a/Sample/HardParticle/FormFactorCone.cpp
+++ b/Sample/HardParticle/FormFactorCone.cpp
@@ -43,7 +43,9 @@ FormFactorCone::FormFactorCone(const std::vector<double> P)
         ostr << "Check for 'height <= radius*tan(alpha)' failed.";
         throw std::runtime_error(ostr.str());
     }
-    onChange();
+    m_cot_alpha = Math::cot(m_alpha);
+    double radius2 = m_radius - m_height * m_cot_alpha;
+    m_shape3D = std::make_unique<DoubleEllipse>(m_radius, m_radius, m_height, radius2, radius2);
 }
 
 FormFactorCone::FormFactorCone(double radius, double height, double alpha)
@@ -81,10 +83,3 @@ IFormFactor* FormFactorCone::sliceFormFactor(ZLimits limits, const IRotation& ro
                             m_alpha);
     return createTransformedFormFactor(slicedff, rot, effects.position);
 }
-
-void FormFactorCone::onChange()
-{
-    m_cot_alpha = Math::cot(m_alpha);
-    double radius2 = m_radius - m_height * m_cot_alpha;
-    m_shape3D = std::make_unique<DoubleEllipse>(m_radius, m_radius, m_height, radius2, radius2);
-}
diff --git a/Sample/HardParticle/FormFactorCone.h b/Sample/HardParticle/FormFactorCone.h
index 25cf0120bc1eb90950381d21b51bca873d83e444..39de28d6a8bbb326f5dd8ac0eea3ae0f3f5e0b00 100644
--- a/Sample/HardParticle/FormFactorCone.h
+++ b/Sample/HardParticle/FormFactorCone.h
@@ -46,8 +46,6 @@ protected:
     IFormFactor* sliceFormFactor(ZLimits limits, const IRotation& rot,
                                  R3 translation) const override;
 
-    void onChange() override;
-
 private:
     const double& m_radius;
     const double& m_height;
diff --git a/Sample/HardParticle/FormFactorCone6.cpp b/Sample/HardParticle/FormFactorCone6.cpp
index 561a143534f5dfcda054c75336ef2b9e06006cef..84a9164a16ff5181535afb6c5b911be4b375a494 100644
--- a/Sample/HardParticle/FormFactorCone6.cpp
+++ b/Sample/HardParticle/FormFactorCone6.cpp
@@ -39,26 +39,6 @@ FormFactorCone6::FormFactorCone6(const std::vector<double> P)
     , m_base_edge(m_P[0])
     , m_height(m_P[1])
     , m_alpha(m_P[2])
-{
-    onChange();
-}
-
-FormFactorCone6::FormFactorCone6(double base_edge, double height, double alpha)
-    : FormFactorCone6(std::vector<double>{base_edge, height, alpha})
-{
-}
-
-IFormFactor* FormFactorCone6::sliceFormFactor(ZLimits limits, const IRotation& rot,
-                                              R3 translation) const
-{
-    auto effects = computeSlicingEffects(limits, translation, m_height);
-    double dbase_edge = effects.dz_bottom * Math::cot(m_alpha);
-    FormFactorCone6 slicedff(m_base_edge - dbase_edge,
-                             m_height - effects.dz_bottom - effects.dz_top, m_alpha);
-    return createTransformedFormFactor(slicedff, rot, effects.position);
-}
-
-void FormFactorCone6::onChange()
 {
     double cot_alpha = Math::cot(m_alpha);
     if (!std::isfinite(cot_alpha) || cot_alpha < 0)
@@ -98,3 +78,18 @@ void FormFactorCone6::onChange()
                    {-bs, -bc, m_height - zcom},
                    {bs, -bc, m_height - zcom}});
 }
+
+FormFactorCone6::FormFactorCone6(double base_edge, double height, double alpha)
+    : FormFactorCone6(std::vector<double>{base_edge, height, alpha})
+{
+}
+
+IFormFactor* FormFactorCone6::sliceFormFactor(ZLimits limits, const IRotation& rot,
+                                              R3 translation) const
+{
+    auto effects = computeSlicingEffects(limits, translation, m_height);
+    double dbase_edge = effects.dz_bottom * Math::cot(m_alpha);
+    FormFactorCone6 slicedff(m_base_edge - dbase_edge,
+                             m_height - effects.dz_bottom - effects.dz_top, m_alpha);
+    return createTransformedFormFactor(slicedff, rot, effects.position);
+}
diff --git a/Sample/HardParticle/FormFactorCone6.h b/Sample/HardParticle/FormFactorCone6.h
index e48c041198cc232e57dc810202315cff180d7514..e40b224bf891bec6ed621a371c428fd0874dce90 100644
--- a/Sample/HardParticle/FormFactorCone6.h
+++ b/Sample/HardParticle/FormFactorCone6.h
@@ -42,8 +42,6 @@ protected:
     IFormFactor* sliceFormFactor(ZLimits limits, const IRotation& rot,
                                  R3 translation) const override;
 
-    void onChange() override;
-
 private:
     static const ff::PolyhedralTopology topology;
     const double& m_base_edge;
diff --git a/Sample/HardParticle/FormFactorCuboctahedron.cpp b/Sample/HardParticle/FormFactorCuboctahedron.cpp
index 96b39a36e88f843bbbeaae65d2c6a14692073bd3..3ae1bf0021f7d2d92825be9ae252753e552b46d0 100644
--- a/Sample/HardParticle/FormFactorCuboctahedron.cpp
+++ b/Sample/HardParticle/FormFactorCuboctahedron.cpp
@@ -42,40 +42,6 @@ FormFactorCuboctahedron::FormFactorCuboctahedron(const std::vector<double> P)
     , m_height(m_P[1])
     , m_height_ratio(m_P[2])
     , m_alpha(m_P[3])
-{
-    onChange();
-}
-
-FormFactorCuboctahedron::FormFactorCuboctahedron(double length, double height, double height_ratio,
-                                                 double alpha)
-    : FormFactorCuboctahedron(std::vector<double>{length, height, height_ratio, alpha})
-{
-}
-
-IFormFactor* FormFactorCuboctahedron::sliceFormFactor(ZLimits limits, const IRotation& rot,
-                                                      R3 translation) const
-{
-    auto effects = computeSlicingEffects(limits, translation, m_height * (1 + m_height_ratio));
-    if (effects.dz_bottom > m_height) {
-        double dbase_edge = 2 * (effects.dz_bottom - m_height) * Math::cot(m_alpha);
-        FormFactorPyramid slicedff(
-            m_length - dbase_edge,
-            m_height * (1 + m_height_ratio) - effects.dz_bottom - effects.dz_top, m_alpha);
-        return createTransformedFormFactor(slicedff, rot, effects.position);
-    }
-    if (effects.dz_top > m_height_ratio * m_height) {
-        double dbase_edge = 2 * (m_height - effects.dz_bottom) * Math::cot(m_alpha);
-        FormFactorPyramid slicedff(
-            m_length - dbase_edge,
-            m_height * (1 + m_height_ratio) - effects.dz_bottom - effects.dz_top, M_PI - m_alpha);
-        return createTransformedFormFactor(slicedff, rot, effects.position);
-    }
-    FormFactorCuboctahedron slicedff(m_length, m_height - effects.dz_bottom,
-                                     m_height_ratio * m_height - effects.dz_top, m_alpha);
-    return createTransformedFormFactor(slicedff, rot, effects.position);
-}
-
-void FormFactorCuboctahedron::onChange()
 {
     double cot_alpha = Math::cot(m_alpha);
     if (!std::isfinite(cot_alpha) || cot_alpha < 0)
@@ -121,3 +87,32 @@ void FormFactorCuboctahedron::onChange()
                    {c, c, zc},
                    {-c, c, zc}});
 }
+
+FormFactorCuboctahedron::FormFactorCuboctahedron(double length, double height, double height_ratio,
+                                                 double alpha)
+    : FormFactorCuboctahedron(std::vector<double>{length, height, height_ratio, alpha})
+{
+}
+
+IFormFactor* FormFactorCuboctahedron::sliceFormFactor(ZLimits limits, const IRotation& rot,
+                                                      R3 translation) const
+{
+    auto effects = computeSlicingEffects(limits, translation, m_height * (1 + m_height_ratio));
+    if (effects.dz_bottom > m_height) {
+        double dbase_edge = 2 * (effects.dz_bottom - m_height) * Math::cot(m_alpha);
+        FormFactorPyramid slicedff(
+            m_length - dbase_edge,
+            m_height * (1 + m_height_ratio) - effects.dz_bottom - effects.dz_top, m_alpha);
+        return createTransformedFormFactor(slicedff, rot, effects.position);
+    }
+    if (effects.dz_top > m_height_ratio * m_height) {
+        double dbase_edge = 2 * (m_height - effects.dz_bottom) * Math::cot(m_alpha);
+        FormFactorPyramid slicedff(
+            m_length - dbase_edge,
+            m_height * (1 + m_height_ratio) - effects.dz_bottom - effects.dz_top, M_PI - m_alpha);
+        return createTransformedFormFactor(slicedff, rot, effects.position);
+    }
+    FormFactorCuboctahedron slicedff(m_length, m_height - effects.dz_bottom,
+                                     m_height_ratio * m_height - effects.dz_top, m_alpha);
+    return createTransformedFormFactor(slicedff, rot, effects.position);
+}
diff --git a/Sample/HardParticle/FormFactorCuboctahedron.h b/Sample/HardParticle/FormFactorCuboctahedron.h
index c48308f92340d0f8aaa674de87e719183a2b428e..8fabb59b377357d257b8b93c45ef0e225a73889b 100644
--- a/Sample/HardParticle/FormFactorCuboctahedron.h
+++ b/Sample/HardParticle/FormFactorCuboctahedron.h
@@ -43,8 +43,6 @@ protected:
     IFormFactor* sliceFormFactor(ZLimits limits, const IRotation& rot,
                                  R3 translation) const override;
 
-    void onChange() override;
-
 private:
     static const ff::PolyhedralTopology topology;
 
diff --git a/Sample/HardParticle/FormFactorCylinder.cpp b/Sample/HardParticle/FormFactorCylinder.cpp
index 4a539b301fd859e63c4ec582390b76242831bb59..f4ebed7f47668c79e8a7d7acbdac34f45025df58 100644
--- a/Sample/HardParticle/FormFactorCylinder.cpp
+++ b/Sample/HardParticle/FormFactorCylinder.cpp
@@ -27,7 +27,7 @@ FormFactorCylinder::FormFactorCylinder(const std::vector<double> P)
     , m_radius(m_P[0])
     , m_height(m_P[1])
 {
-    onChange();
+    m_shape3D = std::make_unique<DoubleEllipse>(m_radius, m_radius, m_height, m_radius, m_radius);
 }
 
 FormFactorCylinder::FormFactorCylinder(double radius, double height)
@@ -56,8 +56,3 @@ IFormFactor* FormFactorCylinder::sliceFormFactor(ZLimits limits, const IRotation
     FormFactorCylinder slicedff(m_radius, m_height - effects.dz_bottom - effects.dz_top);
     return createTransformedFormFactor(slicedff, rot, effects.position);
 }
-
-void FormFactorCylinder::onChange()
-{
-    m_shape3D = std::make_unique<DoubleEllipse>(m_radius, m_radius, m_height, m_radius, m_radius);
-}
diff --git a/Sample/HardParticle/FormFactorCylinder.h b/Sample/HardParticle/FormFactorCylinder.h
index 6d5ec34275c9e5a39bceda74349507d634632a8e..017c0b0f2e04103e731022c64e569688a80de36c 100644
--- a/Sample/HardParticle/FormFactorCylinder.h
+++ b/Sample/HardParticle/FormFactorCylinder.h
@@ -45,8 +45,6 @@ protected:
     IFormFactor* sliceFormFactor(ZLimits limits, const IRotation& rot,
                                  R3 translation) const override;
 
-    void onChange() override;
-
 private:
     const double& m_radius;
     const double& m_height;
diff --git a/Sample/HardParticle/FormFactorDodecahedron.cpp b/Sample/HardParticle/FormFactorDodecahedron.cpp
index 2080608287d7cc02ad14cfd3f716b9e17685f4f7..7f52c17bfe9b4e551b7a181bfcbd356e34c037d0 100644
--- a/Sample/HardParticle/FormFactorDodecahedron.cpp
+++ b/Sample/HardParticle/FormFactorDodecahedron.cpp
@@ -36,16 +36,6 @@ FormFactorDodecahedron::FormFactorDodecahedron(const std::vector<double> P)
     : IFormFactorPolyhedron(
         {"Dodecahedron", "regular dodecahedron", {{"Edge", "nm", "edge length", 0, +INF, 0}}}, P)
     , m_edge(m_P[0])
-{
-    onChange();
-}
-
-FormFactorDodecahedron::FormFactorDodecahedron(double edge)
-    : FormFactorDodecahedron(std::vector<double>{edge})
-{
-}
-
-void FormFactorDodecahedron::onChange()
 {
     double a = m_edge;
     setPolyhedron(topology, -1.113516364411607 * a,
@@ -71,3 +61,8 @@ void FormFactorDodecahedron::onChange()
                    {-0.2628655560595668 * a, 0.8090169943749473 * a, 1.113516364411607 * a}});
     assert_platonic();
 }
+
+FormFactorDodecahedron::FormFactorDodecahedron(double edge)
+    : FormFactorDodecahedron(std::vector<double>{edge})
+{
+}
diff --git a/Sample/HardParticle/FormFactorDodecahedron.h b/Sample/HardParticle/FormFactorDodecahedron.h
index 4b6e975dd375d87d7b1a383f36efcc3e3dbd253b..690e3b460fde5b1270149cc7989a8d02e25832fa 100644
--- a/Sample/HardParticle/FormFactorDodecahedron.h
+++ b/Sample/HardParticle/FormFactorDodecahedron.h
@@ -33,9 +33,6 @@ public:
 
     double getEdge() const { return m_edge; }
 
-protected:
-    void onChange() override;
-
 private:
     static const ff::PolyhedralTopology topology;
     const double& m_edge;
diff --git a/Sample/HardParticle/FormFactorEllipsoidalCylinder.cpp b/Sample/HardParticle/FormFactorEllipsoidalCylinder.cpp
index f6612b4f643b13095b608c946f70f8722d96a7b9..284e752fa7628a259aa28dde4663f2c612d97c55 100644
--- a/Sample/HardParticle/FormFactorEllipsoidalCylinder.cpp
+++ b/Sample/HardParticle/FormFactorEllipsoidalCylinder.cpp
@@ -29,7 +29,8 @@ FormFactorEllipsoidalCylinder::FormFactorEllipsoidalCylinder(const std::vector<d
     , m_radius_y(m_P[1])
     , m_height(m_P[2])
 {
-    onChange();
+    m_shape3D =
+        std::make_unique<DoubleEllipse>(m_radius_x, m_radius_y, m_height, m_radius_x, m_radius_y);
 }
 
 FormFactorEllipsoidalCylinder::FormFactorEllipsoidalCylinder(double radius_x, double radius_y,
@@ -64,9 +65,3 @@ IFormFactor* FormFactorEllipsoidalCylinder::sliceFormFactor(ZLimits limits, cons
                                            m_height - effects.dz_bottom - effects.dz_top);
     return createTransformedFormFactor(slicedff, rot, effects.position);
 }
-
-void FormFactorEllipsoidalCylinder::onChange()
-{
-    m_shape3D =
-        std::make_unique<DoubleEllipse>(m_radius_x, m_radius_y, m_height, m_radius_x, m_radius_y);
-}
diff --git a/Sample/HardParticle/FormFactorEllipsoidalCylinder.h b/Sample/HardParticle/FormFactorEllipsoidalCylinder.h
index fff0746f9d1f09b5b80ff7bf85cc2b70f2e7a43f..d06467991e8d141e2a12ddee3125a52fd6b22eb2 100644
--- a/Sample/HardParticle/FormFactorEllipsoidalCylinder.h
+++ b/Sample/HardParticle/FormFactorEllipsoidalCylinder.h
@@ -46,8 +46,6 @@ protected:
     IFormFactor* sliceFormFactor(ZLimits limits, const IRotation& rot,
                                  R3 translation) const override;
 
-    void onChange() override;
-
 private:
     const double& m_radius_x;
     const double& m_radius_y;
diff --git a/Sample/HardParticle/FormFactorFullSphere.cpp b/Sample/HardParticle/FormFactorFullSphere.cpp
index 6004656ecb60771433bace81a25577fc111bb92f..0a65823d235b7018fe0d58bc4e05b6250f1f4ce9 100644
--- a/Sample/HardParticle/FormFactorFullSphere.cpp
+++ b/Sample/HardParticle/FormFactorFullSphere.cpp
@@ -23,7 +23,6 @@ FormFactorFullSphere::FormFactorFullSphere(const std::vector<double> P, bool pos
     , m_radius(m_P[0])
     , m_position_at_center(position_at_center)
 {
-    onChange();
 }
 
 FormFactorFullSphere::FormFactorFullSphere(double radius, bool position_at_center)
@@ -69,5 +68,3 @@ IFormFactor* FormFactorFullSphere::sliceFormFactor(ZLimits limits, const IRotati
     FormFactorTruncatedSphere slicedff(m_radius, height - effects.dz_bottom, effects.dz_top);
     return createTransformedFormFactor(slicedff, IdentityRotation(), effects.position);
 }
-
-void FormFactorFullSphere::onChange() {}
diff --git a/Sample/HardParticle/FormFactorFullSphere.h b/Sample/HardParticle/FormFactorFullSphere.h
index ee72d7c3d42418b62e8df7e78d94d7a43e045984..66d87c42d5a5449dc0ce71cdbe00aff714d81d4f 100644
--- a/Sample/HardParticle/FormFactorFullSphere.h
+++ b/Sample/HardParticle/FormFactorFullSphere.h
@@ -50,8 +50,6 @@ protected:
     IFormFactor* sliceFormFactor(ZLimits limits, const IRotation& rot,
                                  R3 translation) const override;
 
-    void onChange() override;
-
 private:
     const double& m_radius;
     bool m_position_at_center;
diff --git a/Sample/HardParticle/FormFactorFullSpheroid.cpp b/Sample/HardParticle/FormFactorFullSpheroid.cpp
index 930d9763c0b0f01f3b8da1f7d1f38f45bef03fd8..f191af755dcdcfc34126dbf8961d8c1b1762771c 100644
--- a/Sample/HardParticle/FormFactorFullSpheroid.cpp
+++ b/Sample/HardParticle/FormFactorFullSpheroid.cpp
@@ -29,7 +29,8 @@ FormFactorFullSpheroid::FormFactorFullSpheroid(const std::vector<double> P)
     , m_radius(m_P[0])
     , m_height(m_P[1])
 {
-    onChange();
+    m_shape3D =
+        std::make_unique<TruncatedEllipsoid>(m_radius, m_radius, m_height / 2.0, m_height, 0.0);
 }
 
 FormFactorFullSpheroid::FormFactorFullSpheroid(double radius, double height)
@@ -64,9 +65,3 @@ IFormFactor* FormFactorFullSpheroid::sliceFormFactor(ZLimits limits, const IRota
                                          effects.dz_top);
     return createTransformedFormFactor(slicedff, rot, effects.position);
 }
-
-void FormFactorFullSpheroid::onChange()
-{
-    m_shape3D =
-        std::make_unique<TruncatedEllipsoid>(m_radius, m_radius, m_height / 2.0, m_height, 0.0);
-}
diff --git a/Sample/HardParticle/FormFactorFullSpheroid.h b/Sample/HardParticle/FormFactorFullSpheroid.h
index 6d0ad86bc61475c149537728fc5a1a1a864e1068..8c8195de08762dffa24eb9840fd4a90a200d0acb 100644
--- a/Sample/HardParticle/FormFactorFullSpheroid.h
+++ b/Sample/HardParticle/FormFactorFullSpheroid.h
@@ -45,8 +45,6 @@ protected:
     IFormFactor* sliceFormFactor(ZLimits limits, const IRotation& rot,
                                  R3 translation) const override;
 
-    void onChange() override;
-
 private:
     const double& m_radius;
     const double& m_height;
diff --git a/Sample/HardParticle/FormFactorHemiEllipsoid.cpp b/Sample/HardParticle/FormFactorHemiEllipsoid.cpp
index 86e43e06eb878c6ab22916bb4a6821ac462760b4..ceb6a93af55d55a793923b4a5be2f8a751a0912c 100644
--- a/Sample/HardParticle/FormFactorHemiEllipsoid.cpp
+++ b/Sample/HardParticle/FormFactorHemiEllipsoid.cpp
@@ -30,7 +30,8 @@ FormFactorHemiEllipsoid::FormFactorHemiEllipsoid(const std::vector<double> P)
     , m_radius_y(m_P[1])
     , m_height(m_P[2])
 {
-    onChange();
+    m_shape3D =
+        std::make_unique<TruncatedEllipsoid>(m_radius_x, m_radius_x, m_height, m_height, 0.0);
 }
 
 FormFactorHemiEllipsoid::FormFactorHemiEllipsoid(double radius_x, double radius_y, double height)
@@ -72,9 +73,3 @@ complex_t FormFactorHemiEllipsoid::formfactor(C3 q) const
                },
                0., H);
 }
-
-void FormFactorHemiEllipsoid::onChange()
-{
-    m_shape3D =
-        std::make_unique<TruncatedEllipsoid>(m_radius_x, m_radius_x, m_height, m_height, 0.0);
-}
diff --git a/Sample/HardParticle/FormFactorHemiEllipsoid.h b/Sample/HardParticle/FormFactorHemiEllipsoid.h
index 4c38d41acd5c56faaed29cf74ab8ec464688c1ad..f110008a9b63a2523ec24d40dd9a3194f53959bc 100644
--- a/Sample/HardParticle/FormFactorHemiEllipsoid.h
+++ b/Sample/HardParticle/FormFactorHemiEllipsoid.h
@@ -44,9 +44,6 @@ public:
 
     complex_t formfactor(C3 q) const override;
 
-protected:
-    void onChange() override;
-
 private:
     const double& m_radius_x;
     const double& m_radius_y;
diff --git a/Sample/HardParticle/FormFactorHollowSphere.cpp b/Sample/HardParticle/FormFactorHollowSphere.cpp
index 5c6b2f0f8d98cdf1d2d247f05a9a81de3613e15f..dc2f2f406005dd1c6a055a9bd62f4c6f0438955e 100644
--- a/Sample/HardParticle/FormFactorHollowSphere.cpp
+++ b/Sample/HardParticle/FormFactorHollowSphere.cpp
@@ -29,7 +29,7 @@ FormFactorHollowSphere::FormFactorHollowSphere(const std::vector<double> P)
     if (!checkParameters())
         throw std::runtime_error("FormFactorHollowSphere::FormFactorHollowSphere:"
                                  " mean radius must be bigger than the half width");
-    onChange();
+    m_shape3D = std::make_unique<TruncatedEllipsoid>(m_mean, m_mean, m_mean, 2.0 * m_mean, 0.0);
 }
 
 FormFactorHollowSphere::FormFactorHollowSphere(double mean, double full_width)
@@ -54,11 +54,6 @@ complex_t FormFactorHollowSphere::formfactor(C3 q) const
     return nominator / (q2 * q2 * W);
 }
 
-void FormFactorHollowSphere::onChange()
-{
-    m_shape3D = std::make_unique<TruncatedEllipsoid>(m_mean, m_mean, m_mean, 2.0 * m_mean, 0.0);
-}
-
 bool FormFactorHollowSphere::checkParameters() const
 {
     if (m_full_width <= 0.0)
diff --git a/Sample/HardParticle/FormFactorHollowSphere.h b/Sample/HardParticle/FormFactorHollowSphere.h
index 35fef39fdc46fd405dc465e534d5c32e5af25b93..dea911caef267fb9bf911e809d866cf3ca126cca 100644
--- a/Sample/HardParticle/FormFactorHollowSphere.h
+++ b/Sample/HardParticle/FormFactorHollowSphere.h
@@ -38,9 +38,6 @@ public:
 
     complex_t formfactor(C3 q) const override;
 
-protected:
-    void onChange() override;
-
 private:
     bool checkParameters() const;
     const double& m_mean;       //!< This is the mean radius
diff --git a/Sample/HardParticle/FormFactorIcosahedron.cpp b/Sample/HardParticle/FormFactorIcosahedron.cpp
index 13ff6eecba9491474377589853ec54aed722e128..925adddda3347daa74c0505753b10729f19a98a7 100644
--- a/Sample/HardParticle/FormFactorIcosahedron.cpp
+++ b/Sample/HardParticle/FormFactorIcosahedron.cpp
@@ -46,16 +46,6 @@ FormFactorIcosahedron::FormFactorIcosahedron(const std::vector<double> P)
     : IFormFactorPolyhedron(
         {"Icosahedron", "regular icosahedron", {{"Edge", "nm", "edge length", 0, +INF, 0}}}, P)
     , m_edge(m_P[0])
-{
-    onChange();
-}
-
-FormFactorIcosahedron::FormFactorIcosahedron(double edge)
-    : FormFactorIcosahedron(std::vector<double>{edge})
-{
-}
-
-void FormFactorIcosahedron::onChange()
 {
     double a = m_edge;
     setPolyhedron(topology, -0.7557613140761708 * a,
@@ -73,3 +63,8 @@ void FormFactorIcosahedron::onChange()
                    {0.288675134594813 * a, -0.5 * a, 0.7557613140761708 * a}});
     assert_platonic();
 }
+
+FormFactorIcosahedron::FormFactorIcosahedron(double edge)
+    : FormFactorIcosahedron(std::vector<double>{edge})
+{
+}
diff --git a/Sample/HardParticle/FormFactorIcosahedron.h b/Sample/HardParticle/FormFactorIcosahedron.h
index c8663f4f2643c898b973b36859a4be65e953bbad..3895e7cbfefc5df4caf0d88c413db84a67ad5f58 100644
--- a/Sample/HardParticle/FormFactorIcosahedron.h
+++ b/Sample/HardParticle/FormFactorIcosahedron.h
@@ -33,9 +33,6 @@ public:
 
     double getEdge() const { return m_edge; }
 
-protected:
-    void onChange() override;
-
 private:
     static const ff::PolyhedralTopology topology;
     const double& m_edge;
diff --git a/Sample/HardParticle/FormFactorLongBoxGauss.cpp b/Sample/HardParticle/FormFactorLongBoxGauss.cpp
index dba39203f80471bced263f2eb98e39e823cfa1ea..d2b85b805ac5dc690a41ed6cd420c475a1b28173 100644
--- a/Sample/HardParticle/FormFactorLongBoxGauss.cpp
+++ b/Sample/HardParticle/FormFactorLongBoxGauss.cpp
@@ -27,7 +27,7 @@ FormFactorLongBoxGauss::FormFactorLongBoxGauss(const std::vector<double> P)
     , m_width(m_P[1])
     , m_height(m_P[2])
 {
-    onChange();
+    m_shape3D = std::make_unique<Box>(m_length, m_width, m_height);
 }
 
 FormFactorLongBoxGauss::FormFactorLongBoxGauss(double length, double width, double height)
@@ -53,8 +53,3 @@ IFormFactor* FormFactorLongBoxGauss::sliceFormFactor(ZLimits limits, const IRota
                                     m_height - effects.dz_bottom - effects.dz_top);
     return createTransformedFormFactor(slicedff, rot, effects.position);
 }
-
-void FormFactorLongBoxGauss::onChange()
-{
-    m_shape3D = std::make_unique<Box>(m_length, m_width, m_height);
-}
diff --git a/Sample/HardParticle/FormFactorLongBoxGauss.h b/Sample/HardParticle/FormFactorLongBoxGauss.h
index 3951a9a98db33642d486951018108b4503ebf699..4bac539bdd103efef432c182ecc02b58deb92bc5 100644
--- a/Sample/HardParticle/FormFactorLongBoxGauss.h
+++ b/Sample/HardParticle/FormFactorLongBoxGauss.h
@@ -45,8 +45,6 @@ protected:
     IFormFactor* sliceFormFactor(ZLimits limits, const IRotation& rot,
                                  R3 translation) const override;
 
-    void onChange() override;
-
 private:
     const double& m_length;
     const double& m_width;
diff --git a/Sample/HardParticle/FormFactorLongBoxLorentz.cpp b/Sample/HardParticle/FormFactorLongBoxLorentz.cpp
index 21e929e2a18de6c20d26730f4ac832d5835f9598..77035bc3446c1492acd36dfd4cbc3b0b097fb3aa 100644
--- a/Sample/HardParticle/FormFactorLongBoxLorentz.cpp
+++ b/Sample/HardParticle/FormFactorLongBoxLorentz.cpp
@@ -27,7 +27,7 @@ FormFactorLongBoxLorentz::FormFactorLongBoxLorentz(const std::vector<double> P)
     , m_width(m_P[1])
     , m_height(m_P[2])
 {
-    onChange();
+    m_shape3D = std::make_unique<Box>(m_length, m_width, m_height);
 }
 
 FormFactorLongBoxLorentz::FormFactorLongBoxLorentz(double length, double width, double height)
@@ -53,8 +53,3 @@ IFormFactor* FormFactorLongBoxLorentz::sliceFormFactor(ZLimits limits, const IRo
                                       m_height - effects.dz_bottom - effects.dz_top);
     return createTransformedFormFactor(slicedff, rot, effects.position);
 }
-
-void FormFactorLongBoxLorentz::onChange()
-{
-    m_shape3D = std::make_unique<Box>(m_length, m_width, m_height);
-}
diff --git a/Sample/HardParticle/FormFactorLongBoxLorentz.h b/Sample/HardParticle/FormFactorLongBoxLorentz.h
index 8845127961f95d6843dcb6c24ad7c58071cd7ba4..b1c43d9866398bef17cd50c2811c7d431972b7f0 100644
--- a/Sample/HardParticle/FormFactorLongBoxLorentz.h
+++ b/Sample/HardParticle/FormFactorLongBoxLorentz.h
@@ -46,8 +46,6 @@ protected:
     IFormFactor* sliceFormFactor(ZLimits limits, const IRotation& rot,
                                  R3 translation) const override;
 
-    void onChange() override;
-
 private:
     const double& m_length;
     const double& m_width;
diff --git a/Sample/HardParticle/FormFactorPrism3.cpp b/Sample/HardParticle/FormFactorPrism3.cpp
index 2d2578eac615e9ed1be8757a92c0a1ab3ef37951..ad57269d80d3f033240277153cef8c2f30e7a594 100644
--- a/Sample/HardParticle/FormFactorPrism3.cpp
+++ b/Sample/HardParticle/FormFactorPrism3.cpp
@@ -24,7 +24,12 @@ FormFactorPrism3::FormFactorPrism3(const std::vector<double> P)
     , m_base_edge(m_P[0])
     , m_height(m_P[1])
 {
-    onChange();
+    double a = m_base_edge;
+    double as = a / 2;
+    double ac = a / sqrt(3) / 2;
+    double ah = a / sqrt(3);
+    std::vector<R3> V{{-ac, as, 0.}, {-ac, -as, 0.}, {ah, 0., 0.}};
+    setPrism(false, V);
 }
 
 FormFactorPrism3::FormFactorPrism3(double base_edge, double height)
@@ -39,13 +44,3 @@ IFormFactor* FormFactorPrism3::sliceFormFactor(ZLimits limits, const IRotation&
     FormFactorPrism3 slicedff(m_base_edge, m_height - effects.dz_bottom - effects.dz_top);
     return createTransformedFormFactor(slicedff, rot, effects.position);
 }
-
-void FormFactorPrism3::onChange()
-{
-    double a = m_base_edge;
-    double as = a / 2;
-    double ac = a / sqrt(3) / 2;
-    double ah = a / sqrt(3);
-    std::vector<R3> V{{-ac, as, 0.}, {-ac, -as, 0.}, {ah, 0., 0.}};
-    setPrism(false, V);
-}
diff --git a/Sample/HardParticle/FormFactorPrism3.h b/Sample/HardParticle/FormFactorPrism3.h
index 7426a55a007b13f0c28a6ed4192af7ab1f531030..82c222b1210c297712a1ddf9a72b0ff060a3619a 100644
--- a/Sample/HardParticle/FormFactorPrism3.h
+++ b/Sample/HardParticle/FormFactorPrism3.h
@@ -37,7 +37,6 @@ protected:
     IFormFactor* sliceFormFactor(ZLimits limits, const IRotation& rot,
                                  R3 translation) const override;
 
-    void onChange() override;
     double height() const override { return m_height; }
 
 private:
diff --git a/Sample/HardParticle/FormFactorPrism6.cpp b/Sample/HardParticle/FormFactorPrism6.cpp
index 29e4510f7ec8107922652192d050b384286eb2bd..589a36ddead12d951a038d7b9d0c7a104681c678 100644
--- a/Sample/HardParticle/FormFactorPrism6.cpp
+++ b/Sample/HardParticle/FormFactorPrism6.cpp
@@ -23,7 +23,12 @@ FormFactorPrism6::FormFactorPrism6(const std::vector<double> P)
     , m_base_edge(m_P[0])
     , m_height(m_P[1])
 {
-    onChange();
+    double a = m_base_edge;
+    double as = a * sqrt(3) / 2;
+    double ac = a / 2;
+    std::vector<R3> V{{a, 0., 0.},  {ac, as, 0.},   {-ac, as, 0.},
+                      {-a, 0., 0.}, {-ac, -as, 0.}, {ac, -as, 0.}};
+    setPrism(true, V);
 }
 
 FormFactorPrism6::FormFactorPrism6(double base_edge, double height)
@@ -38,13 +43,3 @@ IFormFactor* FormFactorPrism6::sliceFormFactor(ZLimits limits, const IRotation&
     FormFactorPrism6 slicedff(m_base_edge, m_height - effects.dz_bottom - effects.dz_top);
     return createTransformedFormFactor(slicedff, rot, effects.position);
 }
-
-void FormFactorPrism6::onChange()
-{
-    double a = m_base_edge;
-    double as = a * sqrt(3) / 2;
-    double ac = a / 2;
-    std::vector<R3> V{{a, 0., 0.},  {ac, as, 0.},   {-ac, as, 0.},
-                      {-a, 0., 0.}, {-ac, -as, 0.}, {ac, -as, 0.}};
-    setPrism(true, V);
-}
diff --git a/Sample/HardParticle/FormFactorPrism6.h b/Sample/HardParticle/FormFactorPrism6.h
index c5dfa514e5ae855a18940296dfcdf1658fba68f9..a47561d3b85afafdcd98ccb944ff8195c8a20804 100644
--- a/Sample/HardParticle/FormFactorPrism6.h
+++ b/Sample/HardParticle/FormFactorPrism6.h
@@ -37,7 +37,6 @@ protected:
     IFormFactor* sliceFormFactor(ZLimits limits, const IRotation& rot,
                                  R3 translation) const override;
 
-    void onChange() override;
     double height() const override { return m_height; }
 
 private:
diff --git a/Sample/HardParticle/FormFactorPyramid.cpp b/Sample/HardParticle/FormFactorPyramid.cpp
index db584d8b42e9f86a96fb5313f0a901f6a5913a25..614696dce719334acd40321ff5e2a90dc6a0100c 100644
--- a/Sample/HardParticle/FormFactorPyramid.cpp
+++ b/Sample/HardParticle/FormFactorPyramid.cpp
@@ -37,26 +37,6 @@ FormFactorPyramid::FormFactorPyramid(const std::vector<double> P)
     , m_base_edge(m_P[0])
     , m_height(m_P[1])
     , m_alpha(m_P[2])
-{
-    onChange();
-}
-
-FormFactorPyramid::FormFactorPyramid(double base_edge, double height, double alpha)
-    : FormFactorPyramid(std::vector<double>{base_edge, height, alpha})
-{
-}
-
-IFormFactor* FormFactorPyramid::sliceFormFactor(ZLimits limits, const IRotation& rot,
-                                                R3 translation) const
-{
-    auto effects = computeSlicingEffects(limits, translation, m_height);
-    double dbase_edge = 2 * effects.dz_bottom * Math::cot(m_alpha);
-    FormFactorPyramid slicedff(m_base_edge - dbase_edge,
-                               m_height - effects.dz_bottom - effects.dz_top, m_alpha);
-    return createTransformedFormFactor(slicedff, rot, effects.position);
-}
-
-void FormFactorPyramid::onChange()
 {
     double cot_alpha = Math::cot(m_alpha);
     if (!std::isfinite(cot_alpha))
@@ -89,3 +69,18 @@ void FormFactorPyramid::onChange()
                    {b, b, m_height - zcom},
                    {-b, b, m_height - zcom}});
 }
+
+FormFactorPyramid::FormFactorPyramid(double base_edge, double height, double alpha)
+    : FormFactorPyramid(std::vector<double>{base_edge, height, alpha})
+{
+}
+
+IFormFactor* FormFactorPyramid::sliceFormFactor(ZLimits limits, const IRotation& rot,
+                                                R3 translation) const
+{
+    auto effects = computeSlicingEffects(limits, translation, m_height);
+    double dbase_edge = 2 * effects.dz_bottom * Math::cot(m_alpha);
+    FormFactorPyramid slicedff(m_base_edge - dbase_edge,
+                               m_height - effects.dz_bottom - effects.dz_top, m_alpha);
+    return createTransformedFormFactor(slicedff, rot, effects.position);
+}
diff --git a/Sample/HardParticle/FormFactorPyramid.h b/Sample/HardParticle/FormFactorPyramid.h
index 06c01e828db877fc8ffa5acb3e7d1b0a917d31ff..8fe0d305bbe8073974e7eee73e694677238004fd 100644
--- a/Sample/HardParticle/FormFactorPyramid.h
+++ b/Sample/HardParticle/FormFactorPyramid.h
@@ -42,8 +42,6 @@ protected:
     IFormFactor* sliceFormFactor(ZLimits limits, const IRotation& rot,
                                  R3 translation) const override;
 
-    void onChange() override;
-
 private:
     static const ff::PolyhedralTopology topology;
 
diff --git a/Sample/HardParticle/FormFactorTetrahedron.cpp b/Sample/HardParticle/FormFactorTetrahedron.cpp
index 7ec41aae502bbd9fb61d97a4759427e183fc723e..feb832539a5a504d393d54f70e5a9abdbe35aa8d 100644
--- a/Sample/HardParticle/FormFactorTetrahedron.cpp
+++ b/Sample/HardParticle/FormFactorTetrahedron.cpp
@@ -36,26 +36,6 @@ FormFactorTetrahedron::FormFactorTetrahedron(const std::vector<double> P)
     , m_base_edge(m_P[0])
     , m_height(m_P[1])
     , m_alpha(m_P[2])
-{
-    onChange();
-}
-
-FormFactorTetrahedron::FormFactorTetrahedron(double base_edge, double height, double alpha)
-    : FormFactorTetrahedron(std::vector<double>{base_edge, height, alpha})
-{
-}
-
-IFormFactor* FormFactorTetrahedron::sliceFormFactor(ZLimits limits, const IRotation& rot,
-                                                    R3 translation) const
-{
-    auto effects = computeSlicingEffects(limits, translation, m_height);
-    double dbase_edge = 2 * sqrt(3) * effects.dz_bottom * Math::cot(m_alpha);
-    FormFactorTetrahedron slicedff(m_base_edge - dbase_edge,
-                                   m_height - effects.dz_bottom - effects.dz_top, m_alpha);
-    return createTransformedFormFactor(slicedff, rot, effects.position);
-}
-
-void FormFactorTetrahedron::onChange()
 {
     double cot_alpha = Math::cot(m_alpha);
     if (!std::isfinite(cot_alpha) || cot_alpha < 0)
@@ -91,3 +71,18 @@ void FormFactorTetrahedron::onChange()
                    {-bc, -bs, m_height - zcom},
                    {bh, 0., m_height - zcom}});
 }
+
+FormFactorTetrahedron::FormFactorTetrahedron(double base_edge, double height, double alpha)
+    : FormFactorTetrahedron(std::vector<double>{base_edge, height, alpha})
+{
+}
+
+IFormFactor* FormFactorTetrahedron::sliceFormFactor(ZLimits limits, const IRotation& rot,
+                                                    R3 translation) const
+{
+    auto effects = computeSlicingEffects(limits, translation, m_height);
+    double dbase_edge = 2 * sqrt(3) * effects.dz_bottom * Math::cot(m_alpha);
+    FormFactorTetrahedron slicedff(m_base_edge - dbase_edge,
+                                   m_height - effects.dz_bottom - effects.dz_top, m_alpha);
+    return createTransformedFormFactor(slicedff, rot, effects.position);
+}
diff --git a/Sample/HardParticle/FormFactorTetrahedron.h b/Sample/HardParticle/FormFactorTetrahedron.h
index 546cedc137991e3f7382634da3fd470c6e6867a9..45404719aed3df13b7c8532cbbf0e0f14fc2b954 100644
--- a/Sample/HardParticle/FormFactorTetrahedron.h
+++ b/Sample/HardParticle/FormFactorTetrahedron.h
@@ -42,8 +42,6 @@ protected:
     IFormFactor* sliceFormFactor(ZLimits limits, const IRotation& rot,
                                  R3 translation) const override;
 
-    void onChange() override;
-
 private:
     static const ff::PolyhedralTopology topology;
     const double& m_base_edge;
diff --git a/Sample/HardParticle/FormFactorTruncatedCube.cpp b/Sample/HardParticle/FormFactorTruncatedCube.cpp
index 6d16fcb9e82457b9436bc9271357e18fccddec56..ce2a92324d7c14c982e46fc7a3ecfe3f3508f00a 100644
--- a/Sample/HardParticle/FormFactorTruncatedCube.cpp
+++ b/Sample/HardParticle/FormFactorTruncatedCube.cpp
@@ -40,16 +40,6 @@ FormFactorTruncatedCube::FormFactorTruncatedCube(const std::vector<double> P)
         P)
     , m_length(m_P[0])
     , m_removed_length(m_P[1])
-{
-    onChange();
-}
-
-FormFactorTruncatedCube::FormFactorTruncatedCube(double length, double removed_length)
-    : FormFactorTruncatedCube(std::vector<double>{length, removed_length})
-{
-}
-
-void FormFactorTruncatedCube::onChange()
 {
     if (m_removed_length > 0.5 * m_length) {
         std::ostringstream ostr;
@@ -69,3 +59,8 @@ void FormFactorTruncatedCube::onChange()
                    {-c, -a, a},  {-a, -c, a},  {-a, -a, c},  {c, -a, a},  {a, -c, a},  {a, -a, c},
                    {-c, a, a},   {-a, c, a},   {-a, a, c},   {c, a, a},   {a, c, a},   {a, a, c}});
 }
+
+FormFactorTruncatedCube::FormFactorTruncatedCube(double length, double removed_length)
+    : FormFactorTruncatedCube(std::vector<double>{length, removed_length})
+{
+}
diff --git a/Sample/HardParticle/FormFactorTruncatedCube.h b/Sample/HardParticle/FormFactorTruncatedCube.h
index 874e18d4d026ffbe2838e28afffc34de609b9a93..e56d24790c1998401fa354790d939a20fce06fd9 100644
--- a/Sample/HardParticle/FormFactorTruncatedCube.h
+++ b/Sample/HardParticle/FormFactorTruncatedCube.h
@@ -37,9 +37,6 @@ public:
     double getLength() const { return m_length; }
     double getRemovedLength() const { return m_removed_length; }
 
-protected:
-    void onChange() override;
-
 private:
     static const ff::PolyhedralTopology topology;
     const double& m_length;
diff --git a/Sample/HardParticle/FormFactorTruncatedSphere.cpp b/Sample/HardParticle/FormFactorTruncatedSphere.cpp
index 9d8a24e16554864a0e0ed198304912526e7e66b0..dcedc407d4df22e32f22a9668d006c6118d37757 100644
--- a/Sample/HardParticle/FormFactorTruncatedSphere.cpp
+++ b/Sample/HardParticle/FormFactorTruncatedSphere.cpp
@@ -30,18 +30,6 @@ FormFactorTruncatedSphere::FormFactorTruncatedSphere(const std::vector<double> P
     , m_height(m_P[1])
     , m_dh(m_P[2])
 {
-    check_initialization();
-    onChange();
-}
-
-FormFactorTruncatedSphere::FormFactorTruncatedSphere(double radius, double height, double dh)
-    : FormFactorTruncatedSphere(std::vector<double>{radius, height, dh})
-{
-}
-
-bool FormFactorTruncatedSphere::check_initialization() const
-{
-    bool result(true);
     if (m_height > 2. * m_radius || m_dh > m_height) {
         std::ostringstream ostr;
         ostr << "::FormFactorTruncatedSphere() -> Error in class initialization ";
@@ -50,7 +38,12 @@ bool FormFactorTruncatedSphere::check_initialization() const
         ostr << "Check for height <= 2.*radius AND delta_height < height failed.";
         throw std::runtime_error(ostr.str());
     }
-    return result;
+    m_shape3D = std::make_unique<TruncatedEllipsoid>(m_radius, m_radius, m_radius, m_height, m_dh);
+}
+
+FormFactorTruncatedSphere::FormFactorTruncatedSphere(double radius, double height, double dh)
+    : FormFactorTruncatedSphere(std::vector<double>{radius, height, dh})
+{
 }
 
 //! Complex form factor.
@@ -82,8 +75,3 @@ IFormFactor* FormFactorTruncatedSphere::sliceFormFactor(ZLimits limits, const IR
                                        effects.dz_top + m_dh);
     return createTransformedFormFactor(slicedff, rot, effects.position);
 }
-
-void FormFactorTruncatedSphere::onChange()
-{
-    m_shape3D = std::make_unique<TruncatedEllipsoid>(m_radius, m_radius, m_radius, m_height, m_dh);
-}
diff --git a/Sample/HardParticle/FormFactorTruncatedSphere.h b/Sample/HardParticle/FormFactorTruncatedSphere.h
index 2cf506621e1bc6a49a0ae9e5edf971b80c73776b..1c02f0c424d6baebfc2e1ade8647e7976ed65c06 100644
--- a/Sample/HardParticle/FormFactorTruncatedSphere.h
+++ b/Sample/HardParticle/FormFactorTruncatedSphere.h
@@ -46,11 +46,7 @@ protected:
     IFormFactor* sliceFormFactor(ZLimits limits, const IRotation& rot,
                                  R3 translation) const override;
 
-    void onChange() override;
-
 private:
-    bool check_initialization() const;
-
     const double& m_radius;
     const double& m_height;
     const double& m_dh;
diff --git a/Sample/HardParticle/FormFactorTruncatedSpheroid.cpp b/Sample/HardParticle/FormFactorTruncatedSpheroid.cpp
index e7a713ced3d5beaa5b50140cbea352199be3bd0c..bc178dc909361006cf91dbbb1c73e0cc2934c097 100644
--- a/Sample/HardParticle/FormFactorTruncatedSpheroid.cpp
+++ b/Sample/HardParticle/FormFactorTruncatedSpheroid.cpp
@@ -32,19 +32,6 @@ FormFactorTruncatedSpheroid::FormFactorTruncatedSpheroid(const std::vector<doubl
     , m_height_flattening(m_P[2])
     , m_dh(m_P[3])
 {
-    check_initialization();
-    onChange();
-}
-
-FormFactorTruncatedSpheroid::FormFactorTruncatedSpheroid(double radius, double height,
-                                                         double height_flattening, double dh)
-    : FormFactorTruncatedSpheroid(std::vector<double>{radius, height, height_flattening, dh})
-{
-}
-
-bool FormFactorTruncatedSpheroid::check_initialization() const
-{
-    bool result(true);
     if (m_height > 2. * m_radius * m_height_flattening || m_dh > m_height) {
         std::ostringstream ostr;
         ostr << "::FormFactorTruncatedSpheroid() -> Error in class initialization with parameters ";
@@ -54,7 +41,14 @@ bool FormFactorTruncatedSpheroid::check_initialization() const
         ostr << "Check for 'height <= 2.*radius*height_flattening' failed.";
         throw std::runtime_error(ostr.str());
     }
-    return result;
+    m_shape3D = std::make_unique<TruncatedEllipsoid>(
+        m_radius, m_radius, m_height_flattening * m_radius, m_height, m_dh);
+}
+
+FormFactorTruncatedSpheroid::FormFactorTruncatedSpheroid(double radius, double height,
+                                                         double height_flattening, double dh)
+    : FormFactorTruncatedSpheroid(std::vector<double>{radius, height, height_flattening, dh})
+{
 }
 
 complex_t FormFactorTruncatedSpheroid::formfactor(C3 q) const
@@ -91,9 +85,3 @@ IFormFactor* FormFactorTruncatedSpheroid::sliceFormFactor(ZLimits limits, const
                                          effects.dz_top + m_dh);
     return createTransformedFormFactor(slicedff, rot, effects.position);
 }
-
-void FormFactorTruncatedSpheroid::onChange()
-{
-    m_shape3D = std::make_unique<TruncatedEllipsoid>(
-        m_radius, m_radius, m_height_flattening * m_radius, m_height, m_dh);
-}
diff --git a/Sample/HardParticle/FormFactorTruncatedSpheroid.h b/Sample/HardParticle/FormFactorTruncatedSpheroid.h
index 098820eceb41fbe8a75e596ab08e6b6e983747c4..3f3456f10cc183b405e2884294d28c103fa83592 100644
--- a/Sample/HardParticle/FormFactorTruncatedSpheroid.h
+++ b/Sample/HardParticle/FormFactorTruncatedSpheroid.h
@@ -48,11 +48,7 @@ protected:
     IFormFactor* sliceFormFactor(ZLimits limits, const IRotation& rot,
                                  R3 translation) const override;
 
-    void onChange() override;
-
 private:
-    bool check_initialization() const;
-
     const double& m_radius;
     const double& m_height;
     const double& m_height_flattening;
diff --git a/Sample/HardParticle/IProfileRipple.cpp b/Sample/HardParticle/IProfileRipple.cpp
index ce3635d1c8e5b179dabc309b6e8c782765ade58f..66b1dd80e6c223c0605b5e7ee5eed853ab3c6fcd 100644
--- a/Sample/HardParticle/IProfileRipple.cpp
+++ b/Sample/HardParticle/IProfileRipple.cpp
@@ -52,7 +52,7 @@ IProfileRectangularRipple::IProfileRectangularRipple(const NodeMeta& meta,
                                                      const std::vector<double>& PValues)
     : IProfileRipple(meta, PValues)
 {
-    onChange();
+    m_shape3D = std::make_unique<Box>(m_length, m_width, m_height);
 }
 
 //! Complex form factor.
@@ -61,11 +61,6 @@ complex_t IProfileRectangularRipple::factor_yz(complex_t qy, complex_t qz) const
     return ripples::profile_yz_bar(qy, qz, m_width, m_height);
 }
 
-void IProfileRectangularRipple::onChange()
-{
-    m_shape3D = std::make_unique<Box>(m_length, m_width, m_height);
-}
-
 //  ************************************************************************************************
 //  interface ICosineRipple
 //  ************************************************************************************************
@@ -73,7 +68,7 @@ void IProfileRectangularRipple::onChange()
 ICosineRipple::ICosineRipple(const NodeMeta& meta, const std::vector<double>& PValues)
     : IProfileRipple(meta, PValues)
 {
-    onChange();
+    m_shape3D = std::make_unique<RippleCosine>(m_length, m_width, m_height);
 }
 
 //! Complex form factor.
@@ -82,11 +77,6 @@ complex_t ICosineRipple::factor_yz(complex_t qy, complex_t qz) const
     return ripples::profile_yz_cosine(qy, qz, m_width, m_height);
 }
 
-void ICosineRipple::onChange()
-{
-    m_shape3D = std::make_unique<RippleCosine>(m_length, m_width, m_height);
-}
-
 //  ************************************************************************************************
 //  interface ISawtoothRipple
 //  ************************************************************************************************
@@ -97,7 +87,7 @@ ISawtoothRipple::ISawtoothRipple(const NodeMeta& meta, const std::vector<double>
         PValues)
     , m_asymmetry(m_P[3])
 {
-    onChange();
+    m_shape3D = std::make_unique<RippleSawtooth>(m_length, m_width, m_height, m_asymmetry);
 }
 
 //! Complex form factor.
@@ -105,8 +95,3 @@ complex_t ISawtoothRipple::factor_yz(complex_t qy, complex_t qz) const
 {
     return ripples::profile_yz_triangular(qy, qz, m_width, m_height, m_asymmetry);
 }
-
-void ISawtoothRipple::onChange()
-{
-    m_shape3D = std::make_unique<RippleSawtooth>(m_length, m_width, m_height, m_asymmetry);
-}
diff --git a/Sample/HardParticle/IProfileRipple.h b/Sample/HardParticle/IProfileRipple.h
index 5a043dfffb881788a0dbc57a37e6013191fa09cb..fb8b20e70d239101c463373cd1b3f619458fd86d 100644
--- a/Sample/HardParticle/IProfileRipple.h
+++ b/Sample/HardParticle/IProfileRipple.h
@@ -37,7 +37,6 @@ protected:
     const double& m_width;
     const double& m_height;
 
-    void onChange() override = 0;
     virtual complex_t factor_x(complex_t qx) const = 0;
     virtual complex_t factor_yz(complex_t qy, complex_t qz) const = 0;
 };
@@ -49,7 +48,6 @@ public:
     IProfileRectangularRipple(const NodeMeta& meta, const std::vector<double>& PValues);
 
 private:
-    void onChange() override;
     complex_t factor_yz(complex_t qy, complex_t qz) const override;
 };
 
@@ -60,7 +58,6 @@ public:
     ICosineRipple(const NodeMeta& meta, const std::vector<double>& PValues);
 
 private:
-    void onChange() override;
     complex_t factor_yz(complex_t qy, complex_t qz) const override;
 };
 
@@ -76,7 +73,6 @@ protected:
     const double& m_asymmetry;
 
 private:
-    void onChange() override;
     complex_t factor_yz(complex_t qy, complex_t qz) const override;
 };
 
diff --git a/Sample/Lattice/Lattice3D.cpp b/Sample/Lattice/Lattice3D.cpp
index 2f6fe8f3ba099a714fc39ffdf9b08715d5732818..aa6eb39f31a4b6b19e205e8ad7b2fec9fa2594a8 100644
--- a/Sample/Lattice/Lattice3D.cpp
+++ b/Sample/Lattice/Lattice3D.cpp
@@ -31,11 +31,6 @@ Lattice3D::Lattice3D(const Lattice3D& lattice) : Lattice3D(lattice.m_a, lattice.
 
 Lattice3D::~Lattice3D() = default;
 
-void Lattice3D::onChange()
-{
-    computeReciprocalVectors();
-}
-
 Lattice3D Lattice3D::transformed(const Transform3D& transform) const
 {
     R3 q1 = transform.transformed(m_a);
diff --git a/Sample/Lattice/Lattice3D.h b/Sample/Lattice/Lattice3D.h
index 4b22fe163e994b8d65f9cb21fc91580bb5616371..acb8ab3ce2ab0de0182ccad5f1dc0349fd319df0 100644
--- a/Sample/Lattice/Lattice3D.h
+++ b/Sample/Lattice/Lattice3D.h
@@ -70,8 +70,6 @@ public:
     void setSelectionRule(const ISelectionRule& selection_rule);
 
 private:
-    void onChange() override;
-
     void computeReciprocalVectors() const;
 
     R3 m_a, m_b, m_c; //!< Basis vectors in real space
diff --git a/Sample/SoftParticle/FormFactorGauss.cpp b/Sample/SoftParticle/FormFactorGauss.cpp
index ee491f0f17acc4f90e1c8ebbb0f587eea1b50e52..277084babd21a532b86e709abccf4c0213a08563 100644
--- a/Sample/SoftParticle/FormFactorGauss.cpp
+++ b/Sample/SoftParticle/FormFactorGauss.cpp
@@ -24,7 +24,6 @@ FormFactorGaussSphere::FormFactorGaussSphere(const std::vector<double> P)
               P)
     , m_mean_radius(m_P[0])
 {
-    onChange();
 }
 
 FormFactorGaussSphere::FormFactorGaussSphere(double mean_radius)
diff --git a/Sample/SoftParticle/FormFactorGauss.h b/Sample/SoftParticle/FormFactorGauss.h
index 2b3b721f4ca3432ebb6929a30a662f0f63e22047..f5c6caba1aba4fe7a2ef444d0d4e9a7b148a419c 100644
--- a/Sample/SoftParticle/FormFactorGauss.h
+++ b/Sample/SoftParticle/FormFactorGauss.h
@@ -40,9 +40,6 @@ public:
 
     complex_t formfactor(C3 q) const override;
 
-protected:
-    void onChange() override{};
-
 private:
     const double& m_mean_radius;
     void initialize();
diff --git a/Sample/SoftParticle/FormFactorSphereGaussianRadius.cpp b/Sample/SoftParticle/FormFactorSphereGaussianRadius.cpp
index d8929d2146c259442f7fbe4b838ad688f1a5531b..d9bf2a780f5b2f2f4f3266323d68e28280090bcb 100644
--- a/Sample/SoftParticle/FormFactorSphereGaussianRadius.cpp
+++ b/Sample/SoftParticle/FormFactorSphereGaussianRadius.cpp
@@ -26,7 +26,7 @@ FormFactorSphereGaussianRadius::FormFactorSphereGaussianRadius(const std::vector
     , m_sigma(m_P[1])
 {
     m_mean_r3 = calculateMeanR3();
-    onChange();
+    m_shape3D = std::make_unique<TruncatedEllipsoid>(m_mean, m_mean, m_mean, 2.0 * m_mean, 0.0);
 }
 
 FormFactorSphereGaussianRadius::FormFactorSphereGaussianRadius(double mean, double sigma)
@@ -42,11 +42,6 @@ complex_t FormFactorSphereGaussianRadius::formfactor(C3 q) const
     // TODO: don't center at bottom; revise mesocrystal1.py
 }
 
-void FormFactorSphereGaussianRadius::onChange()
-{
-    m_shape3D = std::make_unique<TruncatedEllipsoid>(m_mean, m_mean, m_mean, 2.0 * m_mean, 0.0);
-}
-
 double FormFactorSphereGaussianRadius::calculateMeanR3() const
 {
     return std::pow(m_mean * (m_mean * m_mean + 3.0 * m_sigma * m_sigma), 1.0 / 3.0);
diff --git a/Sample/SoftParticle/FormFactorSphereGaussianRadius.h b/Sample/SoftParticle/FormFactorSphereGaussianRadius.h
index c23e56dfcaadccc1a19a7dca904a86be01113fc4..de0ddc0816d84572978dcc53fba2b3861ff37d3c 100644
--- a/Sample/SoftParticle/FormFactorSphereGaussianRadius.h
+++ b/Sample/SoftParticle/FormFactorSphereGaussianRadius.h
@@ -40,9 +40,6 @@ public:
 
     complex_t formfactor(C3 q) const override;
 
-protected:
-    void onChange() override;
-
 private:
     double calculateMeanR3() const;
 
diff --git a/Sample/SoftParticle/FormFactorSphereLogNormalRadius.cpp b/Sample/SoftParticle/FormFactorSphereLogNormalRadius.cpp
index b0480848613dbd46c22fc043f57da6dc937c02ad..c1a26cdffbe1f4510add9ee1278c5a50acc201a7 100644
--- a/Sample/SoftParticle/FormFactorSphereLogNormalRadius.cpp
+++ b/Sample/SoftParticle/FormFactorSphereLogNormalRadius.cpp
@@ -37,8 +37,7 @@ FormFactorSphereLogNormalRadius::FormFactorSphereLogNormalRadius(const std::vect
         m_radii.push_back(sample.value);
         m_probabilities.push_back(sample.weight);
     }
-
-    onChange();
+    m_shape3D = std::make_unique<TruncatedEllipsoid>(m_mean, m_mean, m_mean, 2.0 * m_mean, 0.0);
 }
 
 FormFactorSphereLogNormalRadius::FormFactorSphereLogNormalRadius(double mean, double scale_param,
@@ -71,8 +70,3 @@ std::string FormFactorSphereLogNormalRadius::pythonConstructor() const
 
     return className() + "(" + Py::Fmt::printArguments(arguments) + ")";
 }
-
-void FormFactorSphereLogNormalRadius::onChange()
-{
-    m_shape3D = std::make_unique<TruncatedEllipsoid>(m_mean, m_mean, m_mean, 2.0 * m_mean, 0.0);
-}
diff --git a/Sample/SoftParticle/FormFactorSphereLogNormalRadius.h b/Sample/SoftParticle/FormFactorSphereLogNormalRadius.h
index 4bf9d20bfe14f0e23b1d43adb17ac3b2ee6f6b43..e26da4d3dab1e68afcedc9a14b69928ed7430aee 100644
--- a/Sample/SoftParticle/FormFactorSphereLogNormalRadius.h
+++ b/Sample/SoftParticle/FormFactorSphereLogNormalRadius.h
@@ -41,9 +41,6 @@ public:
     std::string pythonConstructor() const override;
 #endif
 
-protected:
-    void onChange() override;
-
 private:
     const double& m_mean;
     const double& m_scale_param;
diff --git a/auto/Wrap/doxygenParam.i b/auto/Wrap/doxygenParam.i
index 0bb00b3e70f4b4d7bc9997252726106535374e61..88435d8bcf09be738455823a1c3941d9d16d7261 100644
--- a/auto/Wrap/doxygenParam.i
+++ b/auto/Wrap/doxygenParam.i
@@ -483,11 +483,6 @@ Returns a vector of children.
 Returns a vector of all descendants. 
 ";
 
-%feature("docstring")  INode::onChange "virtual void INode::onChange()
-
-Action to be taken in inherited class when a value has changed. Formerly this was also called when a change via registered parameter took place. This is now obsolete, but the  onChange() call is still relevant for calculations when a value is changed by different means (e.g. after initialization). 
-";
-
 %feature("docstring")  INode::className "virtual std::string INode::className() const =0
 ";
 
diff --git a/auto/Wrap/doxygenSample.i b/auto/Wrap/doxygenSample.i
index 4ab3c6281862e7b60b90cf4596c030ef04dead24..699b473803f4135882424f9d9928c220394d3d19 100644
--- a/auto/Wrap/doxygenSample.i
+++ b/auto/Wrap/doxygenSample.i
@@ -3173,9 +3173,6 @@ Returns the particle density associated with this 2d lattice.
 %feature("docstring")  Interference2DLattice::getChildren "std::vector< const INode * > Interference2DLattice::getChildren() const override
 ";
 
-%feature("docstring")  Interference2DLattice::onChange "void Interference2DLattice::onChange() override
-";
-
 
 // File: classInterference2DParaCrystal.xml
 %feature("docstring") Interference2DParaCrystal "
@@ -3399,9 +3396,6 @@ Indicates if this interference function can be used with a multilayer (DWBA mode
 %feature("docstring")  Interference3DLattice::getChildren "std::vector< const INode * > Interference3DLattice::getChildren() const override
 ";
 
-%feature("docstring")  Interference3DLattice::onChange "void Interference3DLattice::onChange() override
-";
-
 
 // File: classInterferenceFinite2DLattice.xml
 %feature("docstring") InterferenceFinite2DLattice "
diff --git a/auto/Wrap/libBornAgainParam.py b/auto/Wrap/libBornAgainParam.py
index f9d0d218f2afa1b081a44c3e860f6c92cc5c2bf0..c31f9c80082b640bd3c766b71ce5b2666b311d99 100644
--- a/auto/Wrap/libBornAgainParam.py
+++ b/auto/Wrap/libBornAgainParam.py
@@ -2366,16 +2366,6 @@ class INode(object):
         """
         return _libBornAgainParam.INode_progeny(self)
 
-    def onChange(self):
-        r"""
-        onChange(INode self)
-        virtual void INode::onChange()
-
-        Action to be taken in inherited class when a value has changed. Formerly this was also called when a change via registered parameter took place. This is now obsolete, but the  onChange() call is still relevant for calculations when a value is changed by different means (e.g. after initialization). 
-
-        """
-        return _libBornAgainParam.INode_onChange(self)
-
     def className(self):
         r"""
         className(INode self) -> std::string
diff --git a/auto/Wrap/libBornAgainParam_wrap.cpp b/auto/Wrap/libBornAgainParam_wrap.cpp
index 10d67b388f2f6082562c45c3fe883df695488d05..f41707118c109d1d1a3c1fa8bc05f0664eedf1a4 100644
--- a/auto/Wrap/libBornAgainParam_wrap.cpp
+++ b/auto/Wrap/libBornAgainParam_wrap.cpp
@@ -7433,36 +7433,13 @@ std::vector< INode const *, std::allocator< INode const * > > SwigDirector_INode
 }
 
 
-void SwigDirector_INode::onChange() {
-  if (!swig_get_self()) {
-    Swig::DirectorException::raise("'self' uninitialized, maybe you forgot to call INode.__init__.");
-  }
-#if defined(SWIG_PYTHON_DIRECTOR_VTABLE)
-  const size_t swig_method_index = 2;
-  const char *const swig_method_name = "onChange";
-  PyObject *method = swig_get_method(swig_method_index, swig_method_name);
-  swig::SwigVar_PyObject args = PyTuple_New(0);
-  swig::SwigVar_PyObject result = PyObject_Call(method, (PyObject *) args, NULL);
-#else
-  swig::SwigVar_PyObject swig_method_name = SWIG_Python_str_FromChar("onChange");
-  swig::SwigVar_PyObject result = PyObject_CallMethodObjArgs(swig_get_self(), (PyObject *) swig_method_name, NULL);
-#endif
-  if (!result) {
-    PyObject *error = PyErr_Occurred();
-    if (error) {
-      Swig::DirectorMethodException::raise("Error detected when calling 'INode.onChange'");
-    }
-  }
-}
-
-
 std::string SwigDirector_INode::className() const {
   std::string c_result;
   if (!swig_get_self()) {
     Swig::DirectorException::raise("'self' uninitialized, maybe you forgot to call INode.__init__.");
   }
 #if defined(SWIG_PYTHON_DIRECTOR_VTABLE)
-  const size_t swig_method_index = 3;
+  const size_t swig_method_index = 2;
   const char *const swig_method_name = "className";
   PyObject *method = swig_get_method(swig_method_index, swig_method_name);
   swig::SwigVar_PyObject args = PyTuple_New(0);
@@ -31150,40 +31127,6 @@ fail:
 }
 
 
-SWIGINTERN PyObject *_wrap_INode_onChange(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
-  INode *arg1 = (INode *) 0 ;
-  void *argp1 = 0 ;
-  int res1 = 0 ;
-  PyObject *swig_obj[1] ;
-  Swig::Director *director = 0;
-  bool upcall = false;
-  
-  if (!args) SWIG_fail;
-  swig_obj[0] = args;
-  res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_INode, 0 |  0 );
-  if (!SWIG_IsOK(res1)) {
-    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "INode_onChange" "', argument " "1"" of type '" "INode *""'"); 
-  }
-  arg1 = reinterpret_cast< INode * >(argp1);
-  director = SWIG_DIRECTOR_CAST(arg1);
-  upcall = (director && (director->swig_get_self()==swig_obj[0]));
-  try {
-    if (upcall) {
-      (arg1)->INode::onChange();
-    } else {
-      (arg1)->onChange();
-    }
-  } catch (Swig::DirectorException&) {
-    SWIG_fail;
-  }
-  resultobj = SWIG_Py_Void();
-  return resultobj;
-fail:
-  return NULL;
-}
-
-
 SWIGINTERN PyObject *_wrap_INode_className(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
   PyObject *resultobj = 0;
   INode *arg1 = (INode *) 0 ;
@@ -44951,13 +44894,6 @@ static PyMethodDef SwigMethods[] = {
 		"Returns a vector of all descendants. \n"
 		"\n"
 		""},
-	 { "INode_onChange", _wrap_INode_onChange, METH_O, "\n"
-		"INode_onChange(INode self)\n"
-		"virtual void INode::onChange()\n"
-		"\n"
-		"Action to be taken in inherited class when a value has changed. Formerly this was also called when a change via registered parameter took place. This is now obsolete, but the  onChange() call is still relevant for calculations when a value is changed by different means (e.g. after initialization). \n"
-		"\n"
-		""},
 	 { "INode_className", _wrap_INode_className, METH_O, "\n"
 		"INode_className(INode self) -> std::string\n"
 		"virtual std::string INode::className() const =0\n"
diff --git a/auto/Wrap/libBornAgainParam_wrap.h b/auto/Wrap/libBornAgainParam_wrap.h
index 23f12180b69307618ac556746180abb558b23c40..12e69adb39cf4d4e15f078b4203f4a557c7a9d4a 100644
--- a/auto/Wrap/libBornAgainParam_wrap.h
+++ b/auto/Wrap/libBornAgainParam_wrap.h
@@ -23,7 +23,6 @@ public:
     virtual ~SwigDirector_INode();
     virtual void accept(INodeVisitor *visitor) const;
     virtual std::vector< INode const *, std::allocator< INode const * > > getChildren() const;
-    virtual void onChange();
     virtual std::string className() const;
 
 /* Internal director utilities */
@@ -55,7 +54,7 @@ private:
       return method;
     }
 private:
-    mutable swig::SwigVar_PyObject vtable[4];
+    mutable swig::SwigVar_PyObject vtable[3];
 #endif
 
 };
diff --git a/auto/Wrap/libBornAgainSample.py b/auto/Wrap/libBornAgainSample.py
index 3fb20854a6f3806391c1e36d49e1c3dfb9a881a6..be78a11f812c201bf336eaeaa2d7f31123424fe6 100644
--- a/auto/Wrap/libBornAgainSample.py
+++ b/auto/Wrap/libBornAgainSample.py
@@ -7145,14 +7145,6 @@ class Interference2DLattice(IInterference):
         """
         return _libBornAgainSample.Interference2DLattice_getChildren(self)
 
-    def onChange(self):
-        r"""
-        onChange(Interference2DLattice self)
-        void Interference2DLattice::onChange() override
-
-        """
-        return _libBornAgainSample.Interference2DLattice_onChange(self)
-
 # Register Interference2DLattice in _libBornAgainSample:
 _libBornAgainSample.Interference2DLattice_swigregister(Interference2DLattice)
 
@@ -7580,14 +7572,6 @@ class Interference3DLattice(IInterference):
         """
         return _libBornAgainSample.Interference3DLattice_getChildren(self)
 
-    def onChange(self):
-        r"""
-        onChange(Interference3DLattice self)
-        void Interference3DLattice::onChange() override
-
-        """
-        return _libBornAgainSample.Interference3DLattice_onChange(self)
-
 # Register Interference3DLattice in _libBornAgainSample:
 _libBornAgainSample.Interference3DLattice_swigregister(Interference3DLattice)
 
diff --git a/auto/Wrap/libBornAgainSample_wrap.cpp b/auto/Wrap/libBornAgainSample_wrap.cpp
index 2d337559e36e743b458375de5750db9878c01aca..90cc40c8d22ad4b502198e8a7af7541bd183691d 100644
--- a/auto/Wrap/libBornAgainSample_wrap.cpp
+++ b/auto/Wrap/libBornAgainSample_wrap.cpp
@@ -7812,36 +7812,13 @@ std::vector< INode const *, std::allocator< INode const * > > SwigDirector_ISamp
 }
 
 
-void SwigDirector_ISampleNode::onChange() {
-  if (!swig_get_self()) {
-    Swig::DirectorException::raise("'self' uninitialized, maybe you forgot to call ISampleNode.__init__.");
-  }
-#if defined(SWIG_PYTHON_DIRECTOR_VTABLE)
-  const size_t swig_method_index = 4;
-  const char *const swig_method_name = "onChange";
-  PyObject *method = swig_get_method(swig_method_index, swig_method_name);
-  swig::SwigVar_PyObject args = PyTuple_New(0);
-  swig::SwigVar_PyObject result = PyObject_Call(method, (PyObject *) args, NULL);
-#else
-  swig::SwigVar_PyObject swig_method_name = SWIG_Python_str_FromChar("onChange");
-  swig::SwigVar_PyObject result = PyObject_CallMethodObjArgs(swig_get_self(), (PyObject *) swig_method_name, NULL);
-#endif
-  if (!result) {
-    PyObject *error = PyErr_Occurred();
-    if (error) {
-      Swig::DirectorMethodException::raise("Error detected when calling 'ISampleNode.onChange'");
-    }
-  }
-}
-
-
 std::string SwigDirector_ISampleNode::className() const {
   std::string c_result;
   if (!swig_get_self()) {
     Swig::DirectorException::raise("'self' uninitialized, maybe you forgot to call ISampleNode.__init__.");
   }
 #if defined(SWIG_PYTHON_DIRECTOR_VTABLE)
-  const size_t swig_method_index = 5;
+  const size_t swig_method_index = 4;
   const char *const swig_method_name = "className";
   PyObject *method = swig_get_method(swig_method_index, swig_method_name);
   swig::SwigVar_PyObject args = PyTuple_New(0);
@@ -7877,7 +7854,7 @@ Material const *SwigDirector_ISampleNode::material() const {
     Swig::DirectorException::raise("'self' uninitialized, maybe you forgot to call ISampleNode.__init__.");
   }
 #if defined(SWIG_PYTHON_DIRECTOR_VTABLE)
-  const size_t swig_method_index = 6;
+  const size_t swig_method_index = 5;
   const char *const swig_method_name = "material";
   PyObject *method = swig_get_method(swig_method_index, swig_method_name);
   swig::SwigVar_PyObject args = PyTuple_New(0);
@@ -8033,36 +8010,13 @@ std::vector< INode const *, std::allocator< INode const * > > SwigDirector_IForm
 }
 
 
-void SwigDirector_IFormFactor::onChange() {
-  if (!swig_get_self()) {
-    Swig::DirectorException::raise("'self' uninitialized, maybe you forgot to call IFormFactor.__init__.");
-  }
-#if defined(SWIG_PYTHON_DIRECTOR_VTABLE)
-  const size_t swig_method_index = 4;
-  const char *const swig_method_name = "onChange";
-  PyObject *method = swig_get_method(swig_method_index, swig_method_name);
-  swig::SwigVar_PyObject args = PyTuple_New(0);
-  swig::SwigVar_PyObject result = PyObject_Call(method, (PyObject *) args, NULL);
-#else
-  swig::SwigVar_PyObject swig_method_name = SWIG_Python_str_FromChar("onChange");
-  swig::SwigVar_PyObject result = PyObject_CallMethodObjArgs(swig_get_self(), (PyObject *) swig_method_name, NULL);
-#endif
-  if (!result) {
-    PyObject *error = PyErr_Occurred();
-    if (error) {
-      Swig::DirectorMethodException::raise("Error detected when calling 'IFormFactor.onChange'");
-    }
-  }
-}
-
-
 std::string SwigDirector_IFormFactor::className() const {
   std::string c_result;
   if (!swig_get_self()) {
     Swig::DirectorException::raise("'self' uninitialized, maybe you forgot to call IFormFactor.__init__.");
   }
 #if defined(SWIG_PYTHON_DIRECTOR_VTABLE)
-  const size_t swig_method_index = 5;
+  const size_t swig_method_index = 4;
   const char *const swig_method_name = "className";
   PyObject *method = swig_get_method(swig_method_index, swig_method_name);
   swig::SwigVar_PyObject args = PyTuple_New(0);
@@ -8098,7 +8052,7 @@ Material const *SwigDirector_IFormFactor::material() const {
     Swig::DirectorException::raise("'self' uninitialized, maybe you forgot to call IFormFactor.__init__.");
   }
 #if defined(SWIG_PYTHON_DIRECTOR_VTABLE)
-  const size_t swig_method_index = 6;
+  const size_t swig_method_index = 5;
   const char *const swig_method_name = "material";
   PyObject *method = swig_get_method(swig_method_index, swig_method_name);
   swig::SwigVar_PyObject args = PyTuple_New(0);
@@ -8130,7 +8084,7 @@ void SwigDirector_IFormFactor::setAmbientMaterial(Material const &arg0) {
     Swig::DirectorException::raise("'self' uninitialized, maybe you forgot to call IFormFactor.__init__.");
   }
 #if defined(SWIG_PYTHON_DIRECTOR_VTABLE)
-  const size_t swig_method_index = 7;
+  const size_t swig_method_index = 6;
   const char *const swig_method_name = "setAmbientMaterial";
   PyObject *method = swig_get_method(swig_method_index, swig_method_name);
   swig::SwigVar_PyObject result = PyObject_CallFunctionObjArgs(method ,(PyObject *)obj0, NULL);
@@ -8155,7 +8109,7 @@ complex_t SwigDirector_IFormFactor::theFF(WavevectorInfo const &wavevectors) con
     Swig::DirectorException::raise("'self' uninitialized, maybe you forgot to call IFormFactor.__init__.");
   }
 #if defined(SWIG_PYTHON_DIRECTOR_VTABLE)
-  const size_t swig_method_index = 8;
+  const size_t swig_method_index = 7;
   const char *const swig_method_name = "theFF";
   PyObject *method = swig_get_method(swig_method_index, swig_method_name);
   swig::SwigVar_PyObject result = PyObject_CallFunctionObjArgs(method ,(PyObject *)obj0, NULL);
@@ -8186,7 +8140,7 @@ double SwigDirector_IFormFactor::volume() const {
     Swig::DirectorException::raise("'self' uninitialized, maybe you forgot to call IFormFactor.__init__.");
   }
 #if defined(SWIG_PYTHON_DIRECTOR_VTABLE)
-  const size_t swig_method_index = 9;
+  const size_t swig_method_index = 8;
   const char *const swig_method_name = "volume";
   PyObject *method = swig_get_method(swig_method_index, swig_method_name);
   swig::SwigVar_PyObject args = PyTuple_New(0);
@@ -8218,7 +8172,7 @@ double SwigDirector_IFormFactor::radialExtension() const {
     Swig::DirectorException::raise("'self' uninitialized, maybe you forgot to call IFormFactor.__init__.");
   }
 #if defined(SWIG_PYTHON_DIRECTOR_VTABLE)
-  const size_t swig_method_index = 10;
+  const size_t swig_method_index = 9;
   const char *const swig_method_name = "radialExtension";
   PyObject *method = swig_get_method(swig_method_index, swig_method_name);
   swig::SwigVar_PyObject args = PyTuple_New(0);
@@ -8252,7 +8206,7 @@ double SwigDirector_IFormFactor::bottomZ(IRotation const &rotation) const {
     Swig::DirectorException::raise("'self' uninitialized, maybe you forgot to call IFormFactor.__init__.");
   }
 #if defined(SWIG_PYTHON_DIRECTOR_VTABLE)
-  const size_t swig_method_index = 11;
+  const size_t swig_method_index = 10;
   const char *const swig_method_name = "bottomZ";
   PyObject *method = swig_get_method(swig_method_index, swig_method_name);
   swig::SwigVar_PyObject result = PyObject_CallFunctionObjArgs(method ,(PyObject *)obj0, NULL);
@@ -8285,7 +8239,7 @@ double SwigDirector_IFormFactor::topZ(IRotation const &rotation) const {
     Swig::DirectorException::raise("'self' uninitialized, maybe you forgot to call IFormFactor.__init__.");
   }
 #if defined(SWIG_PYTHON_DIRECTOR_VTABLE)
-  const size_t swig_method_index = 12;
+  const size_t swig_method_index = 11;
   const char *const swig_method_name = "topZ";
   PyObject *method = swig_get_method(swig_method_index, swig_method_name);
   swig::SwigVar_PyObject result = PyObject_CallFunctionObjArgs(method ,(PyObject *)obj0, NULL);
@@ -8319,7 +8273,7 @@ bool SwigDirector_IFormFactor::canSliceAnalytically(IRotation const &rot) const
     Swig::DirectorException::raise("'self' uninitialized, maybe you forgot to call IFormFactor.__init__.");
   }
 #if defined(SWIG_PYTHON_DIRECTOR_VTABLE)
-  const size_t swig_method_index = 13;
+  const size_t swig_method_index = 12;
   const char *const swig_method_name = "canSliceAnalytically";
   PyObject *method = swig_get_method(swig_method_index, swig_method_name);
   swig::SwigVar_PyObject result = PyObject_CallFunctionObjArgs(method ,(PyObject *)obj0, NULL);
@@ -8361,7 +8315,7 @@ IFormFactor *SwigDirector_IFormFactor::sliceFormFactor(ZLimits limits, IRotation
     Swig::DirectorException::raise("'self' uninitialized, maybe you forgot to call IFormFactor.__init__.");
   }
 #if defined(SWIG_PYTHON_DIRECTOR_VTABLE)
-  const size_t swig_method_index = 14;
+  const size_t swig_method_index = 13;
   const char *const swig_method_name = "sliceFormFactor";
   PyObject *method = swig_get_method(swig_method_index, swig_method_name);
   swig::SwigVar_PyObject result = PyObject_CallFunctionObjArgs(method ,(PyObject *)obj0,(PyObject *)obj1,(PyObject *)obj2, NULL);
@@ -8517,36 +8471,13 @@ std::vector< INode const *, std::allocator< INode const * > > SwigDirector_IBorn
 }
 
 
-void SwigDirector_IBornFF::onChange() {
-  if (!swig_get_self()) {
-    Swig::DirectorException::raise("'self' uninitialized, maybe you forgot to call IBornFF.__init__.");
-  }
-#if defined(SWIG_PYTHON_DIRECTOR_VTABLE)
-  const size_t swig_method_index = 4;
-  const char *const swig_method_name = "onChange";
-  PyObject *method = swig_get_method(swig_method_index, swig_method_name);
-  swig::SwigVar_PyObject args = PyTuple_New(0);
-  swig::SwigVar_PyObject result = PyObject_Call(method, (PyObject *) args, NULL);
-#else
-  swig::SwigVar_PyObject swig_method_name = SWIG_Python_str_FromChar("onChange");
-  swig::SwigVar_PyObject result = PyObject_CallMethodObjArgs(swig_get_self(), (PyObject *) swig_method_name, NULL);
-#endif
-  if (!result) {
-    PyObject *error = PyErr_Occurred();
-    if (error) {
-      Swig::DirectorMethodException::raise("Error detected when calling 'IBornFF.onChange'");
-    }
-  }
-}
-
-
 std::string SwigDirector_IBornFF::className() const {
   std::string c_result;
   if (!swig_get_self()) {
     Swig::DirectorException::raise("'self' uninitialized, maybe you forgot to call IBornFF.__init__.");
   }
 #if defined(SWIG_PYTHON_DIRECTOR_VTABLE)
-  const size_t swig_method_index = 5;
+  const size_t swig_method_index = 4;
   const char *const swig_method_name = "className";
   PyObject *method = swig_get_method(swig_method_index, swig_method_name);
   swig::SwigVar_PyObject args = PyTuple_New(0);
@@ -8582,7 +8513,7 @@ Material const *SwigDirector_IBornFF::material() const {
     Swig::DirectorException::raise("'self' uninitialized, maybe you forgot to call IBornFF.__init__.");
   }
 #if defined(SWIG_PYTHON_DIRECTOR_VTABLE)
-  const size_t swig_method_index = 6;
+  const size_t swig_method_index = 5;
   const char *const swig_method_name = "material";
   PyObject *method = swig_get_method(swig_method_index, swig_method_name);
   swig::SwigVar_PyObject args = PyTuple_New(0);
@@ -8614,7 +8545,7 @@ void SwigDirector_IBornFF::setAmbientMaterial(Material const &arg0) {
     Swig::DirectorException::raise("'self' uninitialized, maybe you forgot to call IBornFF.__init__.");
   }
 #if defined(SWIG_PYTHON_DIRECTOR_VTABLE)
-  const size_t swig_method_index = 7;
+  const size_t swig_method_index = 6;
   const char *const swig_method_name = "setAmbientMaterial";
   PyObject *method = swig_get_method(swig_method_index, swig_method_name);
   swig::SwigVar_PyObject result = PyObject_CallFunctionObjArgs(method ,(PyObject *)obj0, NULL);
@@ -8639,7 +8570,7 @@ complex_t SwigDirector_IBornFF::theFF(WavevectorInfo const &wavevectors) const {
     Swig::DirectorException::raise("'self' uninitialized, maybe you forgot to call IBornFF.__init__.");
   }
 #if defined(SWIG_PYTHON_DIRECTOR_VTABLE)
-  const size_t swig_method_index = 8;
+  const size_t swig_method_index = 7;
   const char *const swig_method_name = "theFF";
   PyObject *method = swig_get_method(swig_method_index, swig_method_name);
   swig::SwigVar_PyObject result = PyObject_CallFunctionObjArgs(method ,(PyObject *)obj0, NULL);
@@ -8670,7 +8601,7 @@ double SwigDirector_IBornFF::volume() const {
     Swig::DirectorException::raise("'self' uninitialized, maybe you forgot to call IBornFF.__init__.");
   }
 #if defined(SWIG_PYTHON_DIRECTOR_VTABLE)
-  const size_t swig_method_index = 9;
+  const size_t swig_method_index = 8;
   const char *const swig_method_name = "volume";
   PyObject *method = swig_get_method(swig_method_index, swig_method_name);
   swig::SwigVar_PyObject args = PyTuple_New(0);
@@ -8702,7 +8633,7 @@ double SwigDirector_IBornFF::radialExtension() const {
     Swig::DirectorException::raise("'self' uninitialized, maybe you forgot to call IBornFF.__init__.");
   }
 #if defined(SWIG_PYTHON_DIRECTOR_VTABLE)
-  const size_t swig_method_index = 10;
+  const size_t swig_method_index = 9;
   const char *const swig_method_name = "radialExtension";
   PyObject *method = swig_get_method(swig_method_index, swig_method_name);
   swig::SwigVar_PyObject args = PyTuple_New(0);
@@ -8736,7 +8667,7 @@ double SwigDirector_IBornFF::bottomZ(IRotation const &rotation) const {
     Swig::DirectorException::raise("'self' uninitialized, maybe you forgot to call IBornFF.__init__.");
   }
 #if defined(SWIG_PYTHON_DIRECTOR_VTABLE)
-  const size_t swig_method_index = 11;
+  const size_t swig_method_index = 10;
   const char *const swig_method_name = "bottomZ";
   PyObject *method = swig_get_method(swig_method_index, swig_method_name);
   swig::SwigVar_PyObject result = PyObject_CallFunctionObjArgs(method ,(PyObject *)obj0, NULL);
@@ -8769,7 +8700,7 @@ double SwigDirector_IBornFF::topZ(IRotation const &rotation) const {
     Swig::DirectorException::raise("'self' uninitialized, maybe you forgot to call IBornFF.__init__.");
   }
 #if defined(SWIG_PYTHON_DIRECTOR_VTABLE)
-  const size_t swig_method_index = 12;
+  const size_t swig_method_index = 11;
   const char *const swig_method_name = "topZ";
   PyObject *method = swig_get_method(swig_method_index, swig_method_name);
   swig::SwigVar_PyObject result = PyObject_CallFunctionObjArgs(method ,(PyObject *)obj0, NULL);
@@ -8803,7 +8734,7 @@ bool SwigDirector_IBornFF::canSliceAnalytically(IRotation const &rot) const {
     Swig::DirectorException::raise("'self' uninitialized, maybe you forgot to call IBornFF.__init__.");
   }
 #if defined(SWIG_PYTHON_DIRECTOR_VTABLE)
-  const size_t swig_method_index = 13;
+  const size_t swig_method_index = 12;
   const char *const swig_method_name = "canSliceAnalytically";
   PyObject *method = swig_get_method(swig_method_index, swig_method_name);
   swig::SwigVar_PyObject result = PyObject_CallFunctionObjArgs(method ,(PyObject *)obj0, NULL);
@@ -8845,7 +8776,7 @@ IFormFactor *SwigDirector_IBornFF::sliceFormFactor(ZLimits limits, IRotation con
     Swig::DirectorException::raise("'self' uninitialized, maybe you forgot to call IBornFF.__init__.");
   }
 #if defined(SWIG_PYTHON_DIRECTOR_VTABLE)
-  const size_t swig_method_index = 14;
+  const size_t swig_method_index = 13;
   const char *const swig_method_name = "sliceFormFactor";
   PyObject *method = swig_get_method(swig_method_index, swig_method_name);
   swig::SwigVar_PyObject result = PyObject_CallFunctionObjArgs(method ,(PyObject *)obj0,(PyObject *)obj1,(PyObject *)obj2, NULL);
@@ -8878,7 +8809,7 @@ complex_t SwigDirector_IBornFF::formfactor(C3 q) const {
     Swig::DirectorException::raise("'self' uninitialized, maybe you forgot to call IBornFF.__init__.");
   }
 #if defined(SWIG_PYTHON_DIRECTOR_VTABLE)
-  const size_t swig_method_index = 15;
+  const size_t swig_method_index = 14;
   const char *const swig_method_name = "formfactor";
   PyObject *method = swig_get_method(swig_method_index, swig_method_name);
   swig::SwigVar_PyObject result = PyObject_CallFunctionObjArgs(method ,(PyObject *)obj0, NULL);
@@ -53546,28 +53477,6 @@ fail:
 }
 
 
-SWIGINTERN PyObject *_wrap_Interference2DLattice_onChange(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
-  Interference2DLattice *arg1 = (Interference2DLattice *) 0 ;
-  void *argp1 = 0 ;
-  int res1 = 0 ;
-  PyObject *swig_obj[1] ;
-  
-  if (!args) SWIG_fail;
-  swig_obj[0] = args;
-  res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_Interference2DLattice, 0 |  0 );
-  if (!SWIG_IsOK(res1)) {
-    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Interference2DLattice_onChange" "', argument " "1"" of type '" "Interference2DLattice *""'"); 
-  }
-  arg1 = reinterpret_cast< Interference2DLattice * >(argp1);
-  (arg1)->onChange();
-  resultobj = SWIG_Py_Void();
-  return resultobj;
-fail:
-  return NULL;
-}
-
-
 SWIGINTERN PyObject *Interference2DLattice_swigregister(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
   PyObject *obj;
   if (!SWIG_Python_UnpackTuple(args, "swigregister", 1, 1, &obj)) return NULL;
@@ -54900,28 +54809,6 @@ fail:
 }
 
 
-SWIGINTERN PyObject *_wrap_Interference3DLattice_onChange(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
-  Interference3DLattice *arg1 = (Interference3DLattice *) 0 ;
-  void *argp1 = 0 ;
-  int res1 = 0 ;
-  PyObject *swig_obj[1] ;
-  
-  if (!args) SWIG_fail;
-  swig_obj[0] = args;
-  res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_Interference3DLattice, 0 |  0 );
-  if (!SWIG_IsOK(res1)) {
-    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Interference3DLattice_onChange" "', argument " "1"" of type '" "Interference3DLattice *""'"); 
-  }
-  arg1 = reinterpret_cast< Interference3DLattice * >(argp1);
-  (arg1)->onChange();
-  resultobj = SWIG_Py_Void();
-  return resultobj;
-fail:
-  return NULL;
-}
-
-
 SWIGINTERN PyObject *Interference3DLattice_swigregister(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
   PyObject *obj;
   if (!SWIG_Python_UnpackTuple(args, "swigregister", 1, 1, &obj)) return NULL;
@@ -74027,11 +73914,6 @@ static PyMethodDef SwigMethods[] = {
 		"std::vector< const INode * > Interference2DLattice::getChildren() const override\n"
 		"\n"
 		""},
-	 { "Interference2DLattice_onChange", _wrap_Interference2DLattice_onChange, METH_O, "\n"
-		"Interference2DLattice_onChange(Interference2DLattice self)\n"
-		"void Interference2DLattice::onChange() override\n"
-		"\n"
-		""},
 	 { "Interference2DLattice_swigregister", Interference2DLattice_swigregister, METH_O, NULL},
 	 { "Interference2DLattice_swiginit", Interference2DLattice_swiginit, METH_VARARGS, NULL},
 	 { "Interference2DParaCrystal_className", _wrap_Interference2DParaCrystal_className, METH_O, "\n"
@@ -74312,11 +74194,6 @@ static PyMethodDef SwigMethods[] = {
 		"std::vector< const INode * > Interference3DLattice::getChildren() const override\n"
 		"\n"
 		""},
-	 { "Interference3DLattice_onChange", _wrap_Interference3DLattice_onChange, METH_O, "\n"
-		"Interference3DLattice_onChange(Interference3DLattice self)\n"
-		"void Interference3DLattice::onChange() override\n"
-		"\n"
-		""},
 	 { "Interference3DLattice_swigregister", Interference3DLattice_swigregister, METH_O, NULL},
 	 { "Interference3DLattice_swiginit", Interference3DLattice_swiginit, METH_VARARGS, NULL},
 	 { "InterferenceFinite2DLattice_className", _wrap_InterferenceFinite2DLattice_className, METH_O, "\n"
diff --git a/auto/Wrap/libBornAgainSample_wrap.h b/auto/Wrap/libBornAgainSample_wrap.h
index 7855c2236665ef1ccbc5c4031553b3a39ff880f2..cd52dc25340dd1111d56dc7cf062cc97f7e1bf5a 100644
--- a/auto/Wrap/libBornAgainSample_wrap.h
+++ b/auto/Wrap/libBornAgainSample_wrap.h
@@ -25,7 +25,6 @@ public:
     virtual void transferToCPP();
     virtual void accept(INodeVisitor *visitor) const;
     virtual std::vector< INode const *, std::allocator< INode const * > > getChildren() const;
-    virtual void onChange();
     virtual std::string className() const;
     virtual Material const *material() const;
 
@@ -58,7 +57,7 @@ private:
       return method;
     }
 private:
-    mutable swig::SwigVar_PyObject vtable[7];
+    mutable swig::SwigVar_PyObject vtable[6];
 #endif
 
 };
@@ -74,7 +73,6 @@ public:
     virtual void transferToCPP();
     virtual void accept(INodeVisitor *visitor) const;
     virtual std::vector< INode const *, std::allocator< INode const * > > getChildren() const;
-    virtual void onChange();
     virtual std::string className() const;
     virtual Material const *material() const;
     virtual void setAmbientMaterial(Material const &arg0);
@@ -121,7 +119,7 @@ private:
       return method;
     }
 private:
-    mutable swig::SwigVar_PyObject vtable[15];
+    mutable swig::SwigVar_PyObject vtable[14];
 #endif
 
 };
@@ -137,7 +135,6 @@ public:
     virtual void transferToCPP();
     virtual void accept(INodeVisitor *visitor) const;
     virtual std::vector< INode const *, std::allocator< INode const * > > getChildren() const;
-    virtual void onChange();
     virtual std::string className() const;
     virtual Material const *material() const;
     virtual void setAmbientMaterial(Material const &arg0);
@@ -185,7 +182,7 @@ private:
       return method;
     }
 private:
-    mutable swig::SwigVar_PyObject vtable[16];
+    mutable swig::SwigVar_PyObject vtable[15];
 #endif
 
 };