From 21fe2f693fadbff6ddeefcfdf8a8e8609410a88a Mon Sep 17 00:00:00 2001
From: Joachim Wuttke <j.wuttke@fz-juelich.de>
Date: Tue, 4 Jan 2022 22:45:46 +0100
Subject: [PATCH] add parDefs to many clases

---
 Core/Background/PoissonNoiseBackground.h      |   1 -
 Device/Detector/RectangularDetector.h         |   3 +-
 Device/Detector/SphericalDetector.h           |   3 +-
 Device/Pol/PolFilter.h                        |   5 +
 .../Resolution/ResolutionFunction2DGaussian.h |   4 +
 Param/Node/INode.cpp                          |   6 -
 Param/Node/INode.h                            |   3 +-
 Sample/Aggregate/Interference1DLattice.h      |   5 +
 Sample/Aggregate/Interference2DParaCrystal.h  |   6 +
 Sample/Aggregate/Interference2DSuperLattice.h |   7 +
 Sample/Aggregate/InterferenceHardDisk.h       |   6 +
 .../Aggregate/InterferenceRadialParaCrystal.h |   5 +
 Sample/Aggregate/InterferenceTwin.h           |   6 +
 Sample/Aggregate/ParticleLayout.h             |   4 +
 Sample/Correlations/IPeakShape.h              |  35 ++
 Sample/Interface/LayerRoughness.h             |   6 +
 Sample/Lattice/Lattice2D.h                    |  15 +
 Sample/Multilayer/Layer.h                     |   4 +
 Sample/Particle/Crystal.h                     |   4 +
 Sample/Scattering/Rotations.h                 |   1 -
 Tests/Unit/Param/INodeTest.cpp                |  72 ---
 auto/Wrap/doxygenCore.i                       |   3 -
 auto/Wrap/doxygenDevice.i                     |   6 +
 auto/Wrap/doxygenParam.i                      |   2 +-
 auto/Wrap/doxygenSample.i                     |  62 +-
 auto/Wrap/libBornAgainCore.py                 |   8 -
 auto/Wrap/libBornAgainCore_wrap.cpp           |  28 -
 auto/Wrap/libBornAgainDevice.py               |   8 +
 auto/Wrap/libBornAgainDevice_wrap.cpp         |  28 +
 auto/Wrap/libBornAgainParam.py                |   2 +-
 auto/Wrap/libBornAgainParam_wrap.cpp          |   2 +-
 auto/Wrap/libBornAgainSample.py               | 162 ++++-
 auto/Wrap/libBornAgainSample_wrap.cpp         | 560 +++++++++++++++++-
 33 files changed, 903 insertions(+), 169 deletions(-)
 delete mode 100644 Tests/Unit/Param/INodeTest.cpp

diff --git a/Core/Background/PoissonNoiseBackground.h b/Core/Background/PoissonNoiseBackground.h
index 71a189ddfa2..25002bdbce7 100644
--- a/Core/Background/PoissonNoiseBackground.h
+++ b/Core/Background/PoissonNoiseBackground.h
@@ -27,7 +27,6 @@ public:
     PoissonNoiseBackground* clone() const override;
     std::string className() const final { return "PoissonNoiseBackground"; }
     // const auto tooltip = "class_tooltip";
-    std::vector<ParaMeta> parDefs() const final { return {}; }
 
     double addBackground(double intensity) const override;
 };
diff --git a/Device/Detector/RectangularDetector.h b/Device/Detector/RectangularDetector.h
index 6996c0f5777..1b594314a17 100644
--- a/Device/Detector/RectangularDetector.h
+++ b/Device/Detector/RectangularDetector.h
@@ -41,12 +41,11 @@ public:
     RectangularDetector(size_t nxbins, double width, size_t nybins, double height);
 
     RectangularDetector(const RectangularDetector& other);
+    ~RectangularDetector() override;
 
     RectangularDetector* clone() const override;
     std::string className() const final { return "RectangularDetector"; }
 
-    ~RectangularDetector() override;
-
     void setDetectorNormal(const Direction& direction) override;
 
     void setDetectorPosition(R3 normal_to_detector, double u0, double v0,
diff --git a/Device/Detector/SphericalDetector.h b/Device/Detector/SphericalDetector.h
index e993a8804ba..b2850abcf06 100644
--- a/Device/Detector/SphericalDetector.h
+++ b/Device/Detector/SphericalDetector.h
@@ -45,12 +45,11 @@ public:
     SphericalDetector(size_t n_bin, double width, double phi, double alpha);
 
     SphericalDetector(const SphericalDetector& other);
+    ~SphericalDetector() override = default;
 
     SphericalDetector* clone() const override;
     std::string className() const override { return "SphericalDetector"; }
 
-    ~SphericalDetector() override = default;
-
     //! return default axes units
     Axes::Coords defaultCoords() const override { return Axes::Coords::RADIANS; }
 
diff --git a/Device/Pol/PolFilter.h b/Device/Pol/PolFilter.h
index 91243d995d4..bd9bb6af6d3 100644
--- a/Device/Pol/PolFilter.h
+++ b/Device/Pol/PolFilter.h
@@ -35,6 +35,11 @@ public:
     ~PolFilter() override = default;
 
     std::string className() const final { return "PolFilter"; }
+    std::vector<ParaMeta> parDefs() const final
+    {
+        return {{"Efficiency", "", "efficiency", 0, 1, 1},
+                {"Transmission", "", "total transmission", 0, 1, 1}};
+    }
 
     //! Sets the polarization analyzer characteristics of the detector
     void setDirEffTra(R3 direction, double efficiency, double total_transmission);
diff --git a/Device/Resolution/ResolutionFunction2DGaussian.h b/Device/Resolution/ResolutionFunction2DGaussian.h
index 4c32b9589f6..2a73ba5beda 100644
--- a/Device/Resolution/ResolutionFunction2DGaussian.h
+++ b/Device/Resolution/ResolutionFunction2DGaussian.h
@@ -28,6 +28,10 @@ public:
         return new ResolutionFunction2DGaussian(m_sigma_x, m_sigma_y);
     }
     std::string className() const final { return "ResolutionFunction2DGaussian"; }
+    std::vector<ParaMeta> parDefs() const final
+    {
+        return {{"Sigma_x", "?", "sigma_x", 0, +INF, 0}, {"Sigma_y", "?", "sigma_y", 0, +INF, 0}};
+    }
 
     double evaluateCDF(double x, double y) const override;
 
diff --git a/Param/Node/INode.cpp b/Param/Node/INode.cpp
index d6963e4e578..e446223c08f 100644
--- a/Param/Node/INode.cpp
+++ b/Param/Node/INode.cpp
@@ -50,12 +50,6 @@ void INode::checkNodeArgs() const
     }
 }
 
-std::vector<ParaMeta> INode::parDefs() const
-{
-    ASSERT(m_parDefs);
-    return m_parDefs.value();
-}
-
 std::vector<const INode*> INode::nodeChildren() const
 {
     return {};
diff --git a/Param/Node/INode.h b/Param/Node/INode.h
index c00eec65ae5..28610ff8210 100644
--- a/Param/Node/INode.h
+++ b/Param/Node/INode.h
@@ -48,7 +48,7 @@ public:
     virtual std::string className() const = 0;
 
     //! Returns the parameter definitions, to be hard-coded in each leaf class.
-    virtual std::vector<ParaMeta> parDefs() const;
+    virtual std::vector<ParaMeta> parDefs() const { return {}; }
 
     //! Raises exception if a parameter value is invalid.
     void checkNodeArgs() const;
@@ -61,7 +61,6 @@ public:
 
 protected:
     std::vector<double> m_P;
-    std::optional<std::vector<ParaMeta>> m_parDefs;
 };
 
 //  ************************************************************************************************
diff --git a/Sample/Aggregate/Interference1DLattice.h b/Sample/Aggregate/Interference1DLattice.h
index 754319d7f26..a07eb4af219 100644
--- a/Sample/Aggregate/Interference1DLattice.h
+++ b/Sample/Aggregate/Interference1DLattice.h
@@ -29,6 +29,11 @@ public:
 
     Interference1DLattice* clone() const override;
     std::string className() const final { return "Interference1DLattice"; }
+    std::vector<ParaMeta> parDefs() const final
+    {
+        return {{"Length", "nm", "lattice constant", 0, +INF, 0},
+                {"Xi", "rad", "angle x axis and lattice vector??", -INF, +INF, 0}};
+    }
 
     void setDecayFunction(const IFTDecayFunction1D& decay);
 
diff --git a/Sample/Aggregate/Interference2DParaCrystal.h b/Sample/Aggregate/Interference2DParaCrystal.h
index bc65d3aba4e..ce8333539dd 100644
--- a/Sample/Aggregate/Interference2DParaCrystal.h
+++ b/Sample/Aggregate/Interference2DParaCrystal.h
@@ -35,6 +35,12 @@ public:
 
     Interference2DParaCrystal* clone() const override;
     std::string className() const final { return "Interference2DParaCrystal"; }
+    std::vector<ParaMeta> parDefs() const final
+    {
+        return {{"DampingLength", "nm", "damping length Lambda", 0, +INF, 0},
+                {"DomainSize 1", "nm", "domain size in lattice direction 1", 0, +INF, 0},
+                {"DomainSize 2", "nm", "domain size in lattice direction 2", 0, +INF, 0}};
+    }
 
     void setDomainSizes(double size_1, double size_2);
 
diff --git a/Sample/Aggregate/Interference2DSuperLattice.h b/Sample/Aggregate/Interference2DSuperLattice.h
index badd8e9a5cf..b4ec96df376 100644
--- a/Sample/Aggregate/Interference2DSuperLattice.h
+++ b/Sample/Aggregate/Interference2DSuperLattice.h
@@ -31,6 +31,13 @@ public:
 
     Interference2DSuperLattice* clone() const override;
     std::string className() const final { return "Interference2DSuperLattice"; }
+    std::vector<ParaMeta> parDefs() const final
+    {
+        return {{"Length1", "nm", "lattice constant 1", 0, +INF, 0},
+                {"Length2", "nm", "lattice constant 2", 0, +INF, 0},
+                {"Alpha", "rad", "angle between lattice vectors 1 and 2", -INF, +INF, 0},
+                {"Xi", "rad", "angle between x axis and lattice vector 1", -INF, +INF, 0}};
+    }
 
     void setSubstructureIFF(const IInterference& sub_iff);
     const IInterference& substructureIFF() const;
diff --git a/Sample/Aggregate/InterferenceHardDisk.h b/Sample/Aggregate/InterferenceHardDisk.h
index e87b572c3e1..120901692ad 100644
--- a/Sample/Aggregate/InterferenceHardDisk.h
+++ b/Sample/Aggregate/InterferenceHardDisk.h
@@ -28,6 +28,12 @@ class InterferenceHardDisk : public IInterference {
 public:
     InterferenceHardDisk(double radius, double density, double position_var = 0);
     ~InterferenceHardDisk() override = default;
+    std::vector<ParaMeta> parDefs() const final
+    {
+        return {{"Radius", "nm", "particle radius", 0, +INF, 0},
+                {"Density", "nm^-2", "particle density", 0, +INF, 0},
+                {"Variance", "nm?", "position variance", 0, +INF, 0}};
+    }
 
     InterferenceHardDisk* clone() const override;
     std::string className() const final { return "InterferenceHardDisk"; }
diff --git a/Sample/Aggregate/InterferenceRadialParaCrystal.h b/Sample/Aggregate/InterferenceRadialParaCrystal.h
index b11aaf5593f..ef93820ddbf 100644
--- a/Sample/Aggregate/InterferenceRadialParaCrystal.h
+++ b/Sample/Aggregate/InterferenceRadialParaCrystal.h
@@ -28,6 +28,11 @@ public:
     InterferenceRadialParaCrystal(double peak_distance, double damping_length);
     InterferenceRadialParaCrystal* clone() const override;
     std::string className() const final { return "InterferenceRadialParaCrystal"; }
+    std::vector<ParaMeta> parDefs() const final
+    {
+        return {{"PeakDistance", "nm", "peak distance", 0, +INF, 0},
+                {"DampingLength", "nm", "damping length", 0, +INF, 0}};
+    }
 
     void setKappa(double kappa);
     double kappa() const;
diff --git a/Sample/Aggregate/InterferenceTwin.h b/Sample/Aggregate/InterferenceTwin.h
index fd7ef38ae37..6b32b8e9c43 100644
--- a/Sample/Aggregate/InterferenceTwin.h
+++ b/Sample/Aggregate/InterferenceTwin.h
@@ -19,6 +19,7 @@
 
 //! Interference function for two particles at a mean distance and given standard deviation
 //! from each other in a given direction.
+//! TODO: RENAME (has nothing to do with crystallographic twin)
 //! @ingroup interference
 
 class InterferenceTwin : public IInterference {
@@ -27,6 +28,11 @@ public:
 
     InterferenceTwin* clone() const override;
     std::string className() const final { return "InterferenceTwin"; }
+    std::vector<ParaMeta> parDefs() const final
+    {
+        return {{"MeanDistance", "nm", "mean distance", 0, +INF, 0},
+                {"StdDeviation", "nm", "standard deviation of distance", 0, +INF, 0}};
+    }
 
     R3 direction() const;
     double meanDistance() const;
diff --git a/Sample/Aggregate/ParticleLayout.h b/Sample/Aggregate/ParticleLayout.h
index 96224f75578..c3b6418f811 100644
--- a/Sample/Aggregate/ParticleLayout.h
+++ b/Sample/Aggregate/ParticleLayout.h
@@ -34,6 +34,10 @@ public:
 
     ParticleLayout* clone() const override;
     std::string className() const final { return "ParticleLayout"; }
+    std::vector<ParaMeta> parDefs() const final
+    {
+        return {{"Abundance", "", "e.g. surface fraction covered by this layout", 0, +INF, -1}};
+    }
     std::vector<const INode*> nodeChildren() const override;
 
     void addParticle(const IParticle& particle, double abundance = -1.0, R3 position = {},
diff --git a/Sample/Correlations/IPeakShape.h b/Sample/Correlations/IPeakShape.h
index cd536ef1461..065e2087b07 100644
--- a/Sample/Correlations/IPeakShape.h
+++ b/Sample/Correlations/IPeakShape.h
@@ -48,6 +48,11 @@ public:
 
     IsotropicGaussPeakShape* clone() const override;
     std::string className() const final { return "IsotropicGaussPeakShape"; }
+    std::vector<ParaMeta> parDefs() const final
+    {
+        return {{"MaxIntensity", "", "maximum intensity", 0, +INF, -1},
+                {"DomainSize", "nm", "domain size", 0, +INF, -1}};
+    }
 
     double evaluate(R3 q, R3 q_lattice_point) const override;
 
@@ -66,6 +71,11 @@ public:
 
     IsotropicLorentzPeakShape* clone() const override;
     std::string className() const final { return "IsotropicLorentzPeakShape"; }
+    std::vector<ParaMeta> parDefs() const final
+    {
+        return {{"MaxIntensity", "", "maximum intensity", 0, +INF, -1},
+                {"DomainSize", "nm", "domain size", 0, +INF, -1}};
+    }
 
     double evaluate(R3 q, R3 q_lattice_point) const override;
 
@@ -85,6 +95,12 @@ public:
 
     GaussFisherPeakShape* clone() const override;
     std::string className() const final { return "GaussFisherPeakShape"; }
+    std::vector<ParaMeta> parDefs() const final
+    {
+        return {{"MaxIntensity", "", "maximum intensity", 0, +INF, -1},
+                {"DomainSize", "nm", "domain size", 0, +INF, -1},
+                {"Kappa", "", "?", 0, +INF, -1}};
+    }
 
     double evaluate(R3 q, R3 q_lattice_point) const override;
 
@@ -106,6 +122,12 @@ public:
 
     LorentzFisherPeakShape* clone() const override;
     std::string className() const final { return "LorentzFisherPeakShape"; }
+    std::vector<ParaMeta> parDefs() const final
+    {
+        return {{"MaxIntensity", "", "maximum intensity", 0, +INF, -1},
+                {"DomainSize", "nm", "domain size", 0, +INF, -1},
+                {"Kappa", "", "?", 0, +INF, -1}};
+    }
 
     double evaluate(R3 q, R3 q_lattice_point) const override;
 
@@ -128,6 +150,13 @@ public:
 
     MisesFisherGaussPeakShape* clone() const override;
     std::string className() const final { return "MisesFisherGaussPeakShape"; }
+    std::vector<ParaMeta> parDefs() const final
+    {
+        return {{"MaxIntensity", "", "maximum intensity", 0, +INF, -1},
+                {"Radial Size", "nm", "radial size", 0, +INF, -1},
+                {"Kappa1", "", "?", 0, +INF, -1},
+                {"Kappa2", "", "?", 0, +INF, -1}};
+    }
 
     double evaluate(R3 q, R3 q_lattice_point) const override;
 
@@ -149,6 +178,12 @@ public:
 
     MisesGaussPeakShape* clone() const override;
     std::string className() const final { return "MisesGaussPeakShape"; }
+    std::vector<ParaMeta> parDefs() const final
+    {
+        return {{"MaxIntensity", "", "maximum intensity", 0, +INF, -1},
+                {"Radial Size", "nm", "radial size", 0, +INF, -1},
+                {"Kappa", "", "?", 0, +INF, -1}};
+    }
 
     double evaluate(R3 q, R3 q_lattice_point) const override;
 
diff --git a/Sample/Interface/LayerRoughness.h b/Sample/Interface/LayerRoughness.h
index 74f27590bff..b45693c64a6 100644
--- a/Sample/Interface/LayerRoughness.h
+++ b/Sample/Interface/LayerRoughness.h
@@ -36,6 +36,12 @@ public:
         return new LayerRoughness(m_sigma, m_hurstParameter, m_lateralCorrLength);
     }
     std::string className() const final { return "LayerRoughness"; }
+    std::vector<ParaMeta> parDefs() const final
+    {
+        return {{"Sigma", "", "roughness amplitude", 0, +INF, 0},
+                {"Hurst", "", "Power law exponent??", 0, +INF, 0},
+                {"CorrLength", "nm", "lateral correlation length", 0, +INF, 0}};
+    }
 
     //! Returns power spectral density of the surface roughness
     double spectralFunction(R3 kvec) const;
diff --git a/Sample/Lattice/Lattice2D.h b/Sample/Lattice/Lattice2D.h
index 832eeb2b29d..ae23c9c3c3b 100644
--- a/Sample/Lattice/Lattice2D.h
+++ b/Sample/Lattice/Lattice2D.h
@@ -54,6 +54,12 @@ public:
 
     BasicLattice2D* clone() const override;
     std::string className() const final { return "BasicLattice2D"; }
+    std::vector<ParaMeta> parDefs() const final
+    {
+        return {{"Length1", "nm", "lattice constant 1", 0, +INF, 0},
+                {"Length2", "nm", "lattice constant 2", 0, +INF, 0},
+                {"Alpha", "rad", "angle between lattice vectors 1 and 2", -INF, +INF, 0}};
+    }
 
     double length1() const override { return m_length1; }
     double length2() const override { return m_length2; }
@@ -73,6 +79,10 @@ public:
 
     SquareLattice2D* clone() const override;
     std::string className() const final { return "SquareLattice2D"; }
+    std::vector<ParaMeta> parDefs() const final
+    {
+        return {{"Length", "nm", "lattice constant", 0, +INF, 0}};
+    }
 
     double length1() const override { return m_length; }
     double length2() const override { return m_length; }
@@ -91,6 +101,11 @@ public:
 
     HexagonalLattice2D* clone() const override;
     std::string className() const final { return "HexagonalLattice2D"; }
+    std::vector<ParaMeta> parDefs() const final
+    {
+        return {{"Length", "nm", "lattice constant", 0, +INF, 0},
+                {"Xi", "rad", "angle between x axis and lattice vector", -INF, +INF, 0}};
+    }
 
     double length1() const override { return m_length; }
     double length2() const override { return m_length; }
diff --git a/Sample/Multilayer/Layer.h b/Sample/Multilayer/Layer.h
index 045ddd4e4f9..375ba5d0059 100644
--- a/Sample/Multilayer/Layer.h
+++ b/Sample/Multilayer/Layer.h
@@ -30,6 +30,10 @@ public:
 
     Layer* clone() const override;
     std::string className() const final { return "Layer"; }
+    std::vector<ParaMeta> parDefs() const final
+    {
+        return {{"Thickness", "nm", "thickness", 0, +INF, 0}};
+    }
     std::vector<const INode*> nodeChildren() const override;
 
     const Material* material() const override { return &m_material; }
diff --git a/Sample/Particle/Crystal.h b/Sample/Particle/Crystal.h
index 748237b5cb4..8724e3c9b37 100644
--- a/Sample/Particle/Crystal.h
+++ b/Sample/Particle/Crystal.h
@@ -39,6 +39,10 @@ public:
     Crystal* clone() const override;
     std::string className() const final { return "Crystal"; }
     std::vector<const INode*> nodeChildren() const override;
+    std::vector<ParaMeta> parDefs() const final
+    {
+        return {{"Variance", "nm?", "position variance", 0, +INF, 0}};
+    }
 
     const IParticle* basis() const { return m_basis.get(); }
     const Lattice3D* lattice() const { return m_lattice.get(); }
diff --git a/Sample/Scattering/Rotations.h b/Sample/Scattering/Rotations.h
index 81159b27c9f..01e722e415e 100644
--- a/Sample/Scattering/Rotations.h
+++ b/Sample/Scattering/Rotations.h
@@ -62,7 +62,6 @@ public:
     IdentityRotation* clone() const override { return new IdentityRotation(); }
     std::string className() const final { return "IdentityRotation"; }
     // const auto tooltip = "Identity rotation, does nothing";
-    std::vector<ParaMeta> parDefs() const final { return {}; }
     IdentityRotation* createInverse() const override { return new IdentityRotation(); }
 
     RotMatrix rotMatrix() const override;
diff --git a/Tests/Unit/Param/INodeTest.cpp b/Tests/Unit/Param/INodeTest.cpp
deleted file mode 100644
index bbfdd599919..00000000000
--- a/Tests/Unit/Param/INodeTest.cpp
+++ /dev/null
@@ -1,72 +0,0 @@
-#include "Param/Node/INode.h"
-#include "Fit/Param/RealLimits.h"
-#include "Param/Node/NodeUtils.h"
-#include "Tests/GTestWrapper/google_test.h"
-#include <memory>
-#include <stdexcept>
-
-namespace {
-
-const std::string test_class_name = "TestClass";
-const std::string another_test_class_name = "AnotherTestClass";
-
-} // namespace
-
-class INodeTest : public ::testing::Test {
-public:
-    class TestClass : public INode {
-    public:
-        inline static const std::string class_name = "TestClass";
-        std::string className() const final { return class_name; }
-
-        TestClass() = default;
-
-        ~TestClass() override
-        {
-            for (auto* child : m_nodes)
-                delete child;
-        }
-
-        void appendChild(INode* node) { m_nodes.push_back(node); }
-
-        std::vector<const INode*> nodeChildren() const override
-        {
-            return {m_nodes.begin(), m_nodes.end()};
-        }
-
-        std::vector<INode*> m_nodes;
-        double m_parameter1;
-
-        friend class INodeTest_fullQualifiedParameters_Test;
-        friend class INodeTest_createChildParameterTree_Test;
-    };
-};
-
-TEST_F(INodeTest, initialState)
-{
-    INodeTest::TestClass node;
-    EXPECT_EQ(node.nodeChildren().size(), 0u);
-}
-
-TEST_F(INodeTest, appendChild)
-{
-    INodeTest::TestClass node;
-
-    auto* child0 = new INodeTest::TestClass();
-
-    // inserting single child
-    node.appendChild(child0);
-
-    // accessing vector of children
-    auto children = node.nodeChildren();
-    EXPECT_EQ(children.size(), 1u);
-    EXPECT_TRUE(std::find(children.begin(), children.end(), child0) != children.end());
-}
-
-TEST_F(INodeTest, checkLimits)
-{
-    // this checks only the function if RealLimits.check() works in principle.
-    // More tests regarding RealLimits should be done in dedicated RealLimits unit tests.
-    EXPECT_NO_THROW(RealLimits::nonnegative().check("A", 0));
-    EXPECT_THROW(RealLimits::positive().check("A", 0), std::runtime_error);
-}
diff --git a/auto/Wrap/doxygenCore.i b/auto/Wrap/doxygenCore.i
index ab46337f163..4982f70114e 100644
--- a/auto/Wrap/doxygenCore.i
+++ b/auto/Wrap/doxygenCore.i
@@ -1477,9 +1477,6 @@ C++ includes: PoissonNoiseBackground.h
 %feature("docstring")  PoissonNoiseBackground::className "std::string PoissonNoiseBackground::className() const final
 ";
 
-%feature("docstring")  PoissonNoiseBackground::parDefs "std::vector<ParaMeta> PoissonNoiseBackground::parDefs() const final
-";
-
 %feature("docstring")  PoissonNoiseBackground::addBackground "double PoissonNoiseBackground::addBackground(double intensity) const override
 ";
 
diff --git a/auto/Wrap/doxygenDevice.i b/auto/Wrap/doxygenDevice.i
index 8fe5aa865f5..1455bee30dd 100644
--- a/auto/Wrap/doxygenDevice.i
+++ b/auto/Wrap/doxygenDevice.i
@@ -2147,6 +2147,9 @@ C++ includes: PolFilter.h
 %feature("docstring")  PolFilter::className "std::string PolFilter::className() const final
 ";
 
+%feature("docstring")  PolFilter::parDefs "std::vector<ParaMeta> PolFilter::parDefs() const final
+";
+
 %feature("docstring")  PolFilter::setDirEffTra "void PolFilter::setDirEffTra(R3 direction, double efficiency, double total_transmission)
 
 Sets the polarization analyzer characteristics of the detector. 
@@ -2426,6 +2429,9 @@ C++ includes: ResolutionFunction2DGaussian.h
 %feature("docstring")  ResolutionFunction2DGaussian::className "std::string ResolutionFunction2DGaussian::className() const final
 ";
 
+%feature("docstring")  ResolutionFunction2DGaussian::parDefs "std::vector<ParaMeta> ResolutionFunction2DGaussian::parDefs() const final
+";
+
 %feature("docstring")  ResolutionFunction2DGaussian::evaluateCDF "double ResolutionFunction2DGaussian::evaluateCDF(double x, double y) const override
 ";
 
diff --git a/auto/Wrap/doxygenParam.i b/auto/Wrap/doxygenParam.i
index d6d8ff485f3..252d73ec0fa 100644
--- a/auto/Wrap/doxygenParam.i
+++ b/auto/Wrap/doxygenParam.i
@@ -485,7 +485,7 @@ C++ includes: INode.h
 Returns the class name, to be hard-coded in each leaf class that inherits from  INode. 
 ";
 
-%feature("docstring")  INode::parDefs "std::vector< ParaMeta > INode::parDefs() const
+%feature("docstring")  INode::parDefs "virtual std::vector<ParaMeta> INode::parDefs() const
 
 Returns the parameter definitions, to be hard-coded in each leaf class. 
 ";
diff --git a/auto/Wrap/doxygenSample.i b/auto/Wrap/doxygenSample.i
index 6c90f7c5f33..3099e3fa8c6 100644
--- a/auto/Wrap/doxygenSample.i
+++ b/auto/Wrap/doxygenSample.i
@@ -118,6 +118,9 @@ C++ includes: Lattice2D.h
 %feature("docstring")  BasicLattice2D::className "std::string BasicLattice2D::className() const final
 ";
 
+%feature("docstring")  BasicLattice2D::parDefs "std::vector<ParaMeta> BasicLattice2D::parDefs() const final
+";
+
 %feature("docstring")  BasicLattice2D::length1 "double BasicLattice2D::length1() const override
 ";
 
@@ -170,6 +173,9 @@ Returns a clone of this  ISampleNode object.
 %feature("docstring")  Crystal::nodeChildren "std::vector< const INode * > Crystal::nodeChildren() const override
 ";
 
+%feature("docstring")  Crystal::parDefs "std::vector<ParaMeta> Crystal::parDefs() const final
+";
+
 %feature("docstring")  Crystal::basis "const IParticle* Crystal::basis() const
 ";
 
@@ -2133,6 +2139,9 @@ C++ includes: IPeakShape.h
 %feature("docstring")  GaussFisherPeakShape::className "std::string GaussFisherPeakShape::className() const final
 ";
 
+%feature("docstring")  GaussFisherPeakShape::parDefs "std::vector<ParaMeta> GaussFisherPeakShape::parDefs() const final
+";
+
 %feature("docstring")  GaussFisherPeakShape::evaluate "double GaussFisherPeakShape::evaluate(R3 q, R3 q_lattice_point) const override
 
 Evaluates the peak shape at q from a reciprocal lattice point at q_lattice_point. 
@@ -2161,6 +2170,9 @@ C++ includes: Lattice2D.h
 %feature("docstring")  HexagonalLattice2D::className "std::string HexagonalLattice2D::className() const final
 ";
 
+%feature("docstring")  HexagonalLattice2D::parDefs "std::vector<ParaMeta> HexagonalLattice2D::parDefs() const final
+";
+
 %feature("docstring")  HexagonalLattice2D::length1 "double HexagonalLattice2D::length1() const override
 ";
 
@@ -2269,9 +2281,6 @@ C++ includes: Rotations.h
 %feature("docstring")  IdentityRotation::className "std::string IdentityRotation::className() const final
 ";
 
-%feature("docstring")  IdentityRotation::parDefs "std::vector<ParaMeta> IdentityRotation::parDefs() const final
-";
-
 %feature("docstring")  IdentityRotation::createInverse "IdentityRotation* IdentityRotation::createInverse() const override
 
 Returns a new  IRotation object that is the current object's inverse. 
@@ -2616,6 +2625,9 @@ rotation of lattice with respect to x-axis in radians
 %feature("docstring")  Interference1DLattice::className "std::string Interference1DLattice::className() const final
 ";
 
+%feature("docstring")  Interference1DLattice::parDefs "std::vector<ParaMeta> Interference1DLattice::parDefs() const final
+";
+
 %feature("docstring")  Interference1DLattice::setDecayFunction "void Interference1DLattice::setDecayFunction(const IFTDecayFunction1D &decay)
 
 Sets one-dimensional decay function.
@@ -2706,6 +2718,9 @@ C++ includes: Interference2DParaCrystal.h
 %feature("docstring")  Interference2DParaCrystal::className "std::string Interference2DParaCrystal::className() const final
 ";
 
+%feature("docstring")  Interference2DParaCrystal::parDefs "std::vector<ParaMeta> Interference2DParaCrystal::parDefs() const final
+";
+
 %feature("docstring")  Interference2DParaCrystal::setDomainSizes "void Interference2DParaCrystal::setDomainSizes(double size_1, double size_2)
 
 Sets the sizes of coherence domains.
@@ -2829,6 +2844,9 @@ correlation length in direction 2
 %feature("docstring")  Interference2DSuperLattice::className "std::string Interference2DSuperLattice::className() const final
 ";
 
+%feature("docstring")  Interference2DSuperLattice::parDefs "std::vector<ParaMeta> Interference2DSuperLattice::parDefs() const final
+";
+
 %feature("docstring")  Interference2DSuperLattice::setSubstructureIFF "void Interference2DSuperLattice::setSubstructureIFF(const IInterference &sub_iff)
 ";
 
@@ -3009,6 +3027,9 @@ C++ includes: InterferenceHardDisk.h
 %feature("docstring")  InterferenceHardDisk::~InterferenceHardDisk "InterferenceHardDisk::~InterferenceHardDisk() override=default
 ";
 
+%feature("docstring")  InterferenceHardDisk::parDefs "std::vector<ParaMeta> InterferenceHardDisk::parDefs() const final
+";
+
 %feature("docstring")  InterferenceHardDisk::clone "InterferenceHardDisk * InterferenceHardDisk::clone() const override
 ";
 
@@ -3073,6 +3094,9 @@ the damping (coherence) length of the paracrystal in nanometers
 %feature("docstring")  InterferenceRadialParaCrystal::className "std::string InterferenceRadialParaCrystal::className() const final
 ";
 
+%feature("docstring")  InterferenceRadialParaCrystal::parDefs "std::vector<ParaMeta> InterferenceRadialParaCrystal::parDefs() const final
+";
+
 %feature("docstring")  InterferenceRadialParaCrystal::setKappa "void InterferenceRadialParaCrystal::setKappa(double kappa)
 
 Sets size spacing coupling parameter of the Size Spacing Correlation Approximation. 
@@ -3125,7 +3149,7 @@ probability distribution (Fourier transform of probability density)
 // File: classInterferenceTwin.xml
 %feature("docstring") InterferenceTwin "
 
-Interference function for two particles at a mean distance and given standard deviation from each other in a given direction.
+Interference function for two particles at a mean distance and given standard deviation from each other in a given direction. TODO: RENAME (has nothing to do with crystallographic twin)
 
 C++ includes: InterferenceTwin.h
 ";
@@ -3139,6 +3163,9 @@ C++ includes: InterferenceTwin.h
 %feature("docstring")  InterferenceTwin::className "std::string InterferenceTwin::className() const final
 ";
 
+%feature("docstring")  InterferenceTwin::parDefs "std::vector<ParaMeta> InterferenceTwin::parDefs() const final
+";
+
 %feature("docstring")  InterferenceTwin::direction "R3 InterferenceTwin::direction() const
 ";
 
@@ -3477,6 +3504,9 @@ C++ includes: IPeakShape.h
 %feature("docstring")  IsotropicGaussPeakShape::className "std::string IsotropicGaussPeakShape::className() const final
 ";
 
+%feature("docstring")  IsotropicGaussPeakShape::parDefs "std::vector<ParaMeta> IsotropicGaussPeakShape::parDefs() const final
+";
+
 %feature("docstring")  IsotropicGaussPeakShape::evaluate "double IsotropicGaussPeakShape::evaluate(R3 q, R3 q_lattice_point) const override
 
 Evaluates the peak shape at q from a reciprocal lattice point at q_lattice_point. 
@@ -3503,6 +3533,9 @@ C++ includes: IPeakShape.h
 %feature("docstring")  IsotropicLorentzPeakShape::className "std::string IsotropicLorentzPeakShape::className() const final
 ";
 
+%feature("docstring")  IsotropicLorentzPeakShape::parDefs "std::vector<ParaMeta> IsotropicLorentzPeakShape::parDefs() const final
+";
+
 %feature("docstring")  IsotropicLorentzPeakShape::evaluate "double IsotropicLorentzPeakShape::evaluate(R3 q, R3 q_lattice_point) const override
 
 Evaluates the peak shape at q from a reciprocal lattice point at q_lattice_point. 
@@ -3656,6 +3689,9 @@ Returns a clone of this  ISampleNode object.
 %feature("docstring")  Layer::className "std::string Layer::className() const final
 ";
 
+%feature("docstring")  Layer::parDefs "std::vector<ParaMeta> Layer::parDefs() const final
+";
+
 %feature("docstring")  Layer::nodeChildren "std::vector< const INode * > Layer::nodeChildren() const override
 ";
 
@@ -3760,6 +3796,9 @@ Returns a clone of this  ISampleNode object.
 %feature("docstring")  LayerRoughness::className "std::string LayerRoughness::className() const final
 ";
 
+%feature("docstring")  LayerRoughness::parDefs "std::vector<ParaMeta> LayerRoughness::parDefs() const final
+";
+
 %feature("docstring")  LayerRoughness::spectralFunction "double LayerRoughness::spectralFunction(R3 kvec) const
 
 Returns power spectral density of the surface roughness.
@@ -3830,6 +3869,9 @@ C++ includes: IPeakShape.h
 %feature("docstring")  LorentzFisherPeakShape::className "std::string LorentzFisherPeakShape::className() const final
 ";
 
+%feature("docstring")  LorentzFisherPeakShape::parDefs "std::vector<ParaMeta> LorentzFisherPeakShape::parDefs() const final
+";
+
 %feature("docstring")  LorentzFisherPeakShape::evaluate "double LorentzFisherPeakShape::evaluate(R3 q, R3 q_lattice_point) const override
 
 Evaluates the peak shape at q from a reciprocal lattice point at q_lattice_point. 
@@ -4074,6 +4116,9 @@ C++ includes: IPeakShape.h
 %feature("docstring")  MisesFisherGaussPeakShape::className "std::string MisesFisherGaussPeakShape::className() const final
 ";
 
+%feature("docstring")  MisesFisherGaussPeakShape::parDefs "std::vector<ParaMeta> MisesFisherGaussPeakShape::parDefs() const final
+";
+
 %feature("docstring")  MisesFisherGaussPeakShape::evaluate "double MisesFisherGaussPeakShape::evaluate(R3 q, R3 q_lattice_point) const override
 
 Evaluates the peak shape at q from a reciprocal lattice point at q_lattice_point. 
@@ -4105,6 +4150,9 @@ C++ includes: IPeakShape.h
 %feature("docstring")  MisesGaussPeakShape::className "std::string MisesGaussPeakShape::className() const final
 ";
 
+%feature("docstring")  MisesGaussPeakShape::parDefs "std::vector<ParaMeta> MisesGaussPeakShape::parDefs() const final
+";
+
 %feature("docstring")  MisesGaussPeakShape::evaluate "double MisesGaussPeakShape::evaluate(R3 q, R3 q_lattice_point) const override
 
 Evaluates the peak shape at q from a reciprocal lattice point at q_lattice_point. 
@@ -4350,6 +4398,9 @@ Returns a clone of this  ISampleNode object.
 %feature("docstring")  ParticleLayout::className "std::string ParticleLayout::className() const final
 ";
 
+%feature("docstring")  ParticleLayout::parDefs "std::vector<ParaMeta> ParticleLayout::parDefs() const final
+";
+
 %feature("docstring")  ParticleLayout::nodeChildren "std::vector< const INode * > ParticleLayout::nodeChildren() const override
 ";
 
@@ -4859,6 +4910,9 @@ C++ includes: Lattice2D.h
 %feature("docstring")  SquareLattice2D::className "std::string SquareLattice2D::className() const final
 ";
 
+%feature("docstring")  SquareLattice2D::parDefs "std::vector<ParaMeta> SquareLattice2D::parDefs() const final
+";
+
 %feature("docstring")  SquareLattice2D::length1 "double SquareLattice2D::length1() const override
 ";
 
diff --git a/auto/Wrap/libBornAgainCore.py b/auto/Wrap/libBornAgainCore.py
index 92cfaaaa9f6..6a66c20d345 100644
--- a/auto/Wrap/libBornAgainCore.py
+++ b/auto/Wrap/libBornAgainCore.py
@@ -4473,14 +4473,6 @@ class PoissonNoiseBackground(IBackground):
         """
         return _libBornAgainCore.PoissonNoiseBackground_className(self)
 
-    def parDefs(self):
-        r"""
-        parDefs(PoissonNoiseBackground self) -> std::vector< ParaMeta,std::allocator< ParaMeta > >
-        std::vector<ParaMeta> PoissonNoiseBackground::parDefs() const final
-
-        """
-        return _libBornAgainCore.PoissonNoiseBackground_parDefs(self)
-
     def addBackground(self, intensity):
         r"""
         addBackground(PoissonNoiseBackground self, double intensity) -> double
diff --git a/auto/Wrap/libBornAgainCore_wrap.cpp b/auto/Wrap/libBornAgainCore_wrap.cpp
index a5d73009008..f08f98a8b0e 100644
--- a/auto/Wrap/libBornAgainCore_wrap.cpp
+++ b/auto/Wrap/libBornAgainCore_wrap.cpp
@@ -44563,29 +44563,6 @@ fail:
 }
 
 
-SWIGINTERN PyObject *_wrap_PoissonNoiseBackground_parDefs(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
-  PoissonNoiseBackground *arg1 = (PoissonNoiseBackground *) 0 ;
-  void *argp1 = 0 ;
-  int res1 = 0 ;
-  PyObject *swig_obj[1] ;
-  SwigValueWrapper< std::vector< ParaMeta,std::allocator< ParaMeta > > > result;
-  
-  if (!args) SWIG_fail;
-  swig_obj[0] = args;
-  res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_PoissonNoiseBackground, 0 |  0 );
-  if (!SWIG_IsOK(res1)) {
-    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "PoissonNoiseBackground_parDefs" "', argument " "1"" of type '" "PoissonNoiseBackground const *""'"); 
-  }
-  arg1 = reinterpret_cast< PoissonNoiseBackground * >(argp1);
-  result = ((PoissonNoiseBackground const *)arg1)->parDefs();
-  resultobj = SWIG_NewPointerObj((new std::vector< ParaMeta,std::allocator< ParaMeta > >(static_cast< const std::vector< ParaMeta,std::allocator< ParaMeta > >& >(result))), SWIGTYPE_p_std__vectorT_ParaMeta_std__allocatorT_ParaMeta_t_t, SWIG_POINTER_OWN |  0 );
-  return resultobj;
-fail:
-  return NULL;
-}
-
-
 SWIGINTERN PyObject *_wrap_PoissonNoiseBackground_addBackground(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
   PyObject *resultobj = 0;
   PoissonNoiseBackground *arg1 = (PoissonNoiseBackground *) 0 ;
@@ -47623,11 +47600,6 @@ static PyMethodDef SwigMethods[] = {
 		"std::string PoissonNoiseBackground::className() const final\n"
 		"\n"
 		""},
-	 { "PoissonNoiseBackground_parDefs", _wrap_PoissonNoiseBackground_parDefs, METH_O, "\n"
-		"PoissonNoiseBackground_parDefs(PoissonNoiseBackground self) -> std::vector< ParaMeta,std::allocator< ParaMeta > >\n"
-		"std::vector<ParaMeta> PoissonNoiseBackground::parDefs() const final\n"
-		"\n"
-		""},
 	 { "PoissonNoiseBackground_addBackground", _wrap_PoissonNoiseBackground_addBackground, METH_VARARGS, "\n"
 		"PoissonNoiseBackground_addBackground(PoissonNoiseBackground self, double intensity) -> double\n"
 		"double PoissonNoiseBackground::addBackground(double intensity) const override\n"
diff --git a/auto/Wrap/libBornAgainDevice.py b/auto/Wrap/libBornAgainDevice.py
index f85ab105192..741f6036402 100644
--- a/auto/Wrap/libBornAgainDevice.py
+++ b/auto/Wrap/libBornAgainDevice.py
@@ -3890,6 +3890,14 @@ class ResolutionFunction2DGaussian(IResolutionFunction2D):
         """
         return _libBornAgainDevice.ResolutionFunction2DGaussian_className(self)
 
+    def parDefs(self):
+        r"""
+        parDefs(ResolutionFunction2DGaussian self) -> std::vector< ParaMeta,std::allocator< ParaMeta > >
+        std::vector<ParaMeta> ResolutionFunction2DGaussian::parDefs() const final
+
+        """
+        return _libBornAgainDevice.ResolutionFunction2DGaussian_parDefs(self)
+
     def evaluateCDF(self, x, y):
         r"""
         evaluateCDF(ResolutionFunction2DGaussian self, double x, double y) -> double
diff --git a/auto/Wrap/libBornAgainDevice_wrap.cpp b/auto/Wrap/libBornAgainDevice_wrap.cpp
index a63a37d998b..8035efcf32b 100644
--- a/auto/Wrap/libBornAgainDevice_wrap.cpp
+++ b/auto/Wrap/libBornAgainDevice_wrap.cpp
@@ -37428,6 +37428,29 @@ fail:
 }
 
 
+SWIGINTERN PyObject *_wrap_ResolutionFunction2DGaussian_parDefs(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *resultobj = 0;
+  ResolutionFunction2DGaussian *arg1 = (ResolutionFunction2DGaussian *) 0 ;
+  void *argp1 = 0 ;
+  int res1 = 0 ;
+  PyObject *swig_obj[1] ;
+  SwigValueWrapper< std::vector< ParaMeta,std::allocator< ParaMeta > > > result;
+  
+  if (!args) SWIG_fail;
+  swig_obj[0] = args;
+  res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_ResolutionFunction2DGaussian, 0 |  0 );
+  if (!SWIG_IsOK(res1)) {
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "ResolutionFunction2DGaussian_parDefs" "', argument " "1"" of type '" "ResolutionFunction2DGaussian const *""'"); 
+  }
+  arg1 = reinterpret_cast< ResolutionFunction2DGaussian * >(argp1);
+  result = ((ResolutionFunction2DGaussian const *)arg1)->parDefs();
+  resultobj = SWIG_NewPointerObj((new std::vector< ParaMeta,std::allocator< ParaMeta > >(static_cast< const std::vector< ParaMeta,std::allocator< ParaMeta > >& >(result))), SWIGTYPE_p_std__vectorT_ParaMeta_std__allocatorT_ParaMeta_t_t, SWIG_POINTER_OWN |  0 );
+  return resultobj;
+fail:
+  return NULL;
+}
+
+
 SWIGINTERN PyObject *_wrap_ResolutionFunction2DGaussian_evaluateCDF(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
   PyObject *resultobj = 0;
   ResolutionFunction2DGaussian *arg1 = (ResolutionFunction2DGaussian *) 0 ;
@@ -48294,6 +48317,11 @@ static PyMethodDef SwigMethods[] = {
 		"std::string ResolutionFunction2DGaussian::className() const final\n"
 		"\n"
 		""},
+	 { "ResolutionFunction2DGaussian_parDefs", _wrap_ResolutionFunction2DGaussian_parDefs, METH_O, "\n"
+		"ResolutionFunction2DGaussian_parDefs(ResolutionFunction2DGaussian self) -> std::vector< ParaMeta,std::allocator< ParaMeta > >\n"
+		"std::vector<ParaMeta> ResolutionFunction2DGaussian::parDefs() const final\n"
+		"\n"
+		""},
 	 { "ResolutionFunction2DGaussian_evaluateCDF", _wrap_ResolutionFunction2DGaussian_evaluateCDF, METH_VARARGS, "\n"
 		"ResolutionFunction2DGaussian_evaluateCDF(ResolutionFunction2DGaussian self, double x, double y) -> double\n"
 		"double ResolutionFunction2DGaussian::evaluateCDF(double x, double y) const override\n"
diff --git a/auto/Wrap/libBornAgainParam.py b/auto/Wrap/libBornAgainParam.py
index 02cb8643aca..77deb1c531a 100644
--- a/auto/Wrap/libBornAgainParam.py
+++ b/auto/Wrap/libBornAgainParam.py
@@ -2314,7 +2314,7 @@ class INode(object):
     def parDefs(self):
         r"""
         parDefs(INode self) -> std::vector< ParaMeta,std::allocator< ParaMeta > >
-        std::vector< ParaMeta > INode::parDefs() const
+        virtual std::vector<ParaMeta> INode::parDefs() const
 
         Returns the parameter definitions, to be hard-coded in each leaf class. 
 
diff --git a/auto/Wrap/libBornAgainParam_wrap.cpp b/auto/Wrap/libBornAgainParam_wrap.cpp
index 4546824b912..b5ea658d3a1 100644
--- a/auto/Wrap/libBornAgainParam_wrap.cpp
+++ b/auto/Wrap/libBornAgainParam_wrap.cpp
@@ -39354,7 +39354,7 @@ static PyMethodDef SwigMethods[] = {
 		""},
 	 { "INode_parDefs", _wrap_INode_parDefs, METH_O, "\n"
 		"INode_parDefs(INode self) -> std::vector< ParaMeta,std::allocator< ParaMeta > >\n"
-		"std::vector< ParaMeta > INode::parDefs() const\n"
+		"virtual std::vector<ParaMeta> INode::parDefs() const\n"
 		"\n"
 		"Returns the parameter definitions, to be hard-coded in each leaf class. \n"
 		"\n"
diff --git a/auto/Wrap/libBornAgainSample.py b/auto/Wrap/libBornAgainSample.py
index 5dc2bd38010..ad79cabb02d 100644
--- a/auto/Wrap/libBornAgainSample.py
+++ b/auto/Wrap/libBornAgainSample.py
@@ -3297,14 +3297,6 @@ class IdentityRotation(IRotation):
         """
         return _libBornAgainSample.IdentityRotation_className(self)
 
-    def parDefs(self):
-        r"""
-        parDefs(IdentityRotation self) -> std::vector< ParaMeta,std::allocator< ParaMeta > >
-        std::vector<ParaMeta> IdentityRotation::parDefs() const final
-
-        """
-        return _libBornAgainSample.IdentityRotation_parDefs(self)
-
     def createInverse(self):
         r"""
         createInverse(IdentityRotation self) -> IdentityRotation
@@ -3719,6 +3711,14 @@ class Crystal(ISampleNode):
         """
         return _libBornAgainSample.Crystal_nodeChildren(self)
 
+    def parDefs(self):
+        r"""
+        parDefs(Crystal self) -> std::vector< ParaMeta,std::allocator< ParaMeta > >
+        std::vector<ParaMeta> Crystal::parDefs() const final
+
+        """
+        return _libBornAgainSample.Crystal_parDefs(self)
+
     def basis(self):
         r"""
         basis(Crystal self) -> IParticle
@@ -5681,6 +5681,14 @@ class IsotropicGaussPeakShape(IPeakShape):
         """
         return _libBornAgainSample.IsotropicGaussPeakShape_className(self)
 
+    def parDefs(self):
+        r"""
+        parDefs(IsotropicGaussPeakShape self) -> std::vector< ParaMeta,std::allocator< ParaMeta > >
+        std::vector<ParaMeta> IsotropicGaussPeakShape::parDefs() const final
+
+        """
+        return _libBornAgainSample.IsotropicGaussPeakShape_parDefs(self)
+
     def evaluate(self, q, q_lattice_point):
         r"""
         evaluate(IsotropicGaussPeakShape self, R3 q, R3 q_lattice_point) -> double
@@ -5732,6 +5740,14 @@ class IsotropicLorentzPeakShape(IPeakShape):
         """
         return _libBornAgainSample.IsotropicLorentzPeakShape_className(self)
 
+    def parDefs(self):
+        r"""
+        parDefs(IsotropicLorentzPeakShape self) -> std::vector< ParaMeta,std::allocator< ParaMeta > >
+        std::vector<ParaMeta> IsotropicLorentzPeakShape::parDefs() const final
+
+        """
+        return _libBornAgainSample.IsotropicLorentzPeakShape_parDefs(self)
+
     def evaluate(self, q, q_lattice_point):
         r"""
         evaluate(IsotropicLorentzPeakShape self, R3 q, R3 q_lattice_point) -> double
@@ -5783,6 +5799,14 @@ class GaussFisherPeakShape(IPeakShape):
         """
         return _libBornAgainSample.GaussFisherPeakShape_className(self)
 
+    def parDefs(self):
+        r"""
+        parDefs(GaussFisherPeakShape self) -> std::vector< ParaMeta,std::allocator< ParaMeta > >
+        std::vector<ParaMeta> GaussFisherPeakShape::parDefs() const final
+
+        """
+        return _libBornAgainSample.GaussFisherPeakShape_parDefs(self)
+
     def evaluate(self, q, q_lattice_point):
         r"""
         evaluate(GaussFisherPeakShape self, R3 q, R3 q_lattice_point) -> double
@@ -5844,6 +5868,14 @@ class LorentzFisherPeakShape(IPeakShape):
         """
         return _libBornAgainSample.LorentzFisherPeakShape_className(self)
 
+    def parDefs(self):
+        r"""
+        parDefs(LorentzFisherPeakShape self) -> std::vector< ParaMeta,std::allocator< ParaMeta > >
+        std::vector<ParaMeta> LorentzFisherPeakShape::parDefs() const final
+
+        """
+        return _libBornAgainSample.LorentzFisherPeakShape_parDefs(self)
+
     def evaluate(self, q, q_lattice_point):
         r"""
         evaluate(LorentzFisherPeakShape self, R3 q, R3 q_lattice_point) -> double
@@ -5905,6 +5937,14 @@ class MisesFisherGaussPeakShape(IPeakShape):
         """
         return _libBornAgainSample.MisesFisherGaussPeakShape_className(self)
 
+    def parDefs(self):
+        r"""
+        parDefs(MisesFisherGaussPeakShape self) -> std::vector< ParaMeta,std::allocator< ParaMeta > >
+        std::vector<ParaMeta> MisesFisherGaussPeakShape::parDefs() const final
+
+        """
+        return _libBornAgainSample.MisesFisherGaussPeakShape_parDefs(self)
+
     def evaluate(self, q, q_lattice_point):
         r"""
         evaluate(MisesFisherGaussPeakShape self, R3 q, R3 q_lattice_point) -> double
@@ -5966,6 +6006,14 @@ class MisesGaussPeakShape(IPeakShape):
         """
         return _libBornAgainSample.MisesGaussPeakShape_className(self)
 
+    def parDefs(self):
+        r"""
+        parDefs(MisesGaussPeakShape self) -> std::vector< ParaMeta,std::allocator< ParaMeta > >
+        std::vector<ParaMeta> MisesGaussPeakShape::parDefs() const final
+
+        """
+        return _libBornAgainSample.MisesGaussPeakShape_parDefs(self)
+
     def evaluate(self, q, q_lattice_point):
         r"""
         evaluate(MisesGaussPeakShape self, R3 q, R3 q_lattice_point) -> double
@@ -6126,6 +6174,14 @@ class Interference1DLattice(IInterference):
         """
         return _libBornAgainSample.Interference1DLattice_className(self)
 
+    def parDefs(self):
+        r"""
+        parDefs(Interference1DLattice self) -> std::vector< ParaMeta,std::allocator< ParaMeta > >
+        std::vector<ParaMeta> Interference1DLattice::parDefs() const final
+
+        """
+        return _libBornAgainSample.Interference1DLattice_parDefs(self)
+
     def setDecayFunction(self, decay):
         r"""
         setDecayFunction(Interference1DLattice self, IFTDecayFunction1D decay)
@@ -6306,6 +6362,14 @@ class Interference2DParaCrystal(IInterference):
         """
         return _libBornAgainSample.Interference2DParaCrystal_className(self)
 
+    def parDefs(self):
+        r"""
+        parDefs(Interference2DParaCrystal self) -> std::vector< ParaMeta,std::allocator< ParaMeta > >
+        std::vector<ParaMeta> Interference2DParaCrystal::parDefs() const final
+
+        """
+        return _libBornAgainSample.Interference2DParaCrystal_parDefs(self)
+
     def setDomainSizes(self, size_1, size_2):
         r"""
         setDomainSizes(Interference2DParaCrystal self, double size_1, double size_2)
@@ -6507,6 +6571,14 @@ class Interference2DSuperLattice(IInterference):
         """
         return _libBornAgainSample.Interference2DSuperLattice_className(self)
 
+    def parDefs(self):
+        r"""
+        parDefs(Interference2DSuperLattice self) -> std::vector< ParaMeta,std::allocator< ParaMeta > >
+        std::vector<ParaMeta> Interference2DSuperLattice::parDefs() const final
+
+        """
+        return _libBornAgainSample.Interference2DSuperLattice_parDefs(self)
+
     def setSubstructureIFF(self, sub_iff):
         r"""
         setSubstructureIFF(Interference2DSuperLattice self, IInterference sub_iff)
@@ -6887,6 +6959,14 @@ class InterferenceHardDisk(IInterference):
         _libBornAgainSample.InterferenceHardDisk_swiginit(self, _libBornAgainSample.new_InterferenceHardDisk(radius, density, position_var))
     __swig_destroy__ = _libBornAgainSample.delete_InterferenceHardDisk
 
+    def parDefs(self):
+        r"""
+        parDefs(InterferenceHardDisk self) -> std::vector< ParaMeta,std::allocator< ParaMeta > >
+        std::vector<ParaMeta> InterferenceHardDisk::parDefs() const final
+
+        """
+        return _libBornAgainSample.InterferenceHardDisk_parDefs(self)
+
     def clone(self):
         r"""
         clone(InterferenceHardDisk self) -> InterferenceHardDisk
@@ -7021,6 +7101,14 @@ class InterferenceRadialParaCrystal(IInterference):
         """
         return _libBornAgainSample.InterferenceRadialParaCrystal_className(self)
 
+    def parDefs(self):
+        r"""
+        parDefs(InterferenceRadialParaCrystal self) -> std::vector< ParaMeta,std::allocator< ParaMeta > >
+        std::vector<ParaMeta> InterferenceRadialParaCrystal::parDefs() const final
+
+        """
+        return _libBornAgainSample.InterferenceRadialParaCrystal_parDefs(self)
+
     def setKappa(self, kappa):
         r"""
         setKappa(InterferenceRadialParaCrystal self, double kappa)
@@ -7127,7 +7215,7 @@ class InterferenceTwin(IInterference):
     r"""
 
 
-    Interference function for two particles at a mean distance and given standard deviation from each other in a given direction.
+    Interference function for two particles at a mean distance and given standard deviation from each other in a given direction. TODO: RENAME (has nothing to do with crystallographic twin)
 
     C++ includes: InterferenceTwin.h
 
@@ -7160,6 +7248,14 @@ class InterferenceTwin(IInterference):
         """
         return _libBornAgainSample.InterferenceTwin_className(self)
 
+    def parDefs(self):
+        r"""
+        parDefs(InterferenceTwin self) -> std::vector< ParaMeta,std::allocator< ParaMeta > >
+        std::vector<ParaMeta> InterferenceTwin::parDefs() const final
+
+        """
+        return _libBornAgainSample.InterferenceTwin_parDefs(self)
+
     def direction(self):
         r"""
         direction(InterferenceTwin self) -> R3
@@ -7229,6 +7325,14 @@ class ParticleLayout(ISampleNode):
         """
         return _libBornAgainSample.ParticleLayout_className(self)
 
+    def parDefs(self):
+        r"""
+        parDefs(ParticleLayout self) -> std::vector< ParaMeta,std::allocator< ParaMeta > >
+        std::vector<ParaMeta> ParticleLayout::parDefs() const final
+
+        """
+        return _libBornAgainSample.ParticleLayout_parDefs(self)
+
     def nodeChildren(self):
         r"""
         nodeChildren(ParticleLayout self) -> swig_dummy_type_const_inode_vector
@@ -7393,6 +7497,14 @@ class LayerRoughness(ISampleNode):
         """
         return _libBornAgainSample.LayerRoughness_className(self)
 
+    def parDefs(self):
+        r"""
+        parDefs(LayerRoughness self) -> std::vector< ParaMeta,std::allocator< ParaMeta > >
+        std::vector<ParaMeta> LayerRoughness::parDefs() const final
+
+        """
+        return _libBornAgainSample.LayerRoughness_parDefs(self)
+
     def spectralFunction(self, kvec):
         r"""
         spectralFunction(LayerRoughness self, R3 kvec) -> double
@@ -7532,6 +7644,14 @@ class Layer(ISampleNode):
         """
         return _libBornAgainSample.Layer_className(self)
 
+    def parDefs(self):
+        r"""
+        parDefs(Layer self) -> std::vector< ParaMeta,std::allocator< ParaMeta > >
+        std::vector<ParaMeta> Layer::parDefs() const final
+
+        """
+        return _libBornAgainSample.Layer_parDefs(self)
+
     def nodeChildren(self):
         r"""
         nodeChildren(Layer self) -> swig_dummy_type_const_inode_vector
@@ -10829,6 +10949,14 @@ class BasicLattice2D(Lattice2D):
         """
         return _libBornAgainSample.BasicLattice2D_className(self)
 
+    def parDefs(self):
+        r"""
+        parDefs(BasicLattice2D self) -> std::vector< ParaMeta,std::allocator< ParaMeta > >
+        std::vector<ParaMeta> BasicLattice2D::parDefs() const final
+
+        """
+        return _libBornAgainSample.BasicLattice2D_parDefs(self)
+
     def length1(self):
         r"""
         length1(BasicLattice2D self) -> double
@@ -10902,6 +11030,14 @@ class SquareLattice2D(Lattice2D):
         """
         return _libBornAgainSample.SquareLattice2D_className(self)
 
+    def parDefs(self):
+        r"""
+        parDefs(SquareLattice2D self) -> std::vector< ParaMeta,std::allocator< ParaMeta > >
+        std::vector<ParaMeta> SquareLattice2D::parDefs() const final
+
+        """
+        return _libBornAgainSample.SquareLattice2D_parDefs(self)
+
     def length1(self):
         r"""
         length1(SquareLattice2D self) -> double
@@ -10975,6 +11111,14 @@ class HexagonalLattice2D(Lattice2D):
         """
         return _libBornAgainSample.HexagonalLattice2D_className(self)
 
+    def parDefs(self):
+        r"""
+        parDefs(HexagonalLattice2D self) -> std::vector< ParaMeta,std::allocator< ParaMeta > >
+        std::vector<ParaMeta> HexagonalLattice2D::parDefs() const final
+
+        """
+        return _libBornAgainSample.HexagonalLattice2D_parDefs(self)
+
     def length1(self):
         r"""
         length1(HexagonalLattice2D self) -> double
diff --git a/auto/Wrap/libBornAgainSample_wrap.cpp b/auto/Wrap/libBornAgainSample_wrap.cpp
index 80b79cbda77..6a46cda4258 100644
--- a/auto/Wrap/libBornAgainSample_wrap.cpp
+++ b/auto/Wrap/libBornAgainSample_wrap.cpp
@@ -38182,29 +38182,6 @@ fail:
 }
 
 
-SWIGINTERN PyObject *_wrap_IdentityRotation_parDefs(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
-  IdentityRotation *arg1 = (IdentityRotation *) 0 ;
-  void *argp1 = 0 ;
-  int res1 = 0 ;
-  PyObject *swig_obj[1] ;
-  SwigValueWrapper< std::vector< ParaMeta,std::allocator< ParaMeta > > > result;
-  
-  if (!args) SWIG_fail;
-  swig_obj[0] = args;
-  res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_IdentityRotation, 0 |  0 );
-  if (!SWIG_IsOK(res1)) {
-    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "IdentityRotation_parDefs" "', argument " "1"" of type '" "IdentityRotation const *""'"); 
-  }
-  arg1 = reinterpret_cast< IdentityRotation * >(argp1);
-  result = ((IdentityRotation const *)arg1)->parDefs();
-  resultobj = SWIG_NewPointerObj((new std::vector< ParaMeta,std::allocator< ParaMeta > >(static_cast< const std::vector< ParaMeta,std::allocator< ParaMeta > >& >(result))), SWIGTYPE_p_std__vectorT_ParaMeta_std__allocatorT_ParaMeta_t_t, SWIG_POINTER_OWN |  0 );
-  return resultobj;
-fail:
-  return NULL;
-}
-
-
 SWIGINTERN PyObject *_wrap_IdentityRotation_createInverse(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
   PyObject *resultobj = 0;
   IdentityRotation *arg1 = (IdentityRotation *) 0 ;
@@ -39602,6 +39579,29 @@ fail:
 }
 
 
+SWIGINTERN PyObject *_wrap_Crystal_parDefs(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *resultobj = 0;
+  Crystal *arg1 = (Crystal *) 0 ;
+  void *argp1 = 0 ;
+  int res1 = 0 ;
+  PyObject *swig_obj[1] ;
+  SwigValueWrapper< std::vector< ParaMeta,std::allocator< ParaMeta > > > result;
+  
+  if (!args) SWIG_fail;
+  swig_obj[0] = args;
+  res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_Crystal, 0 |  0 );
+  if (!SWIG_IsOK(res1)) {
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Crystal_parDefs" "', argument " "1"" of type '" "Crystal const *""'"); 
+  }
+  arg1 = reinterpret_cast< Crystal * >(argp1);
+  result = ((Crystal const *)arg1)->parDefs();
+  resultobj = SWIG_NewPointerObj((new std::vector< ParaMeta,std::allocator< ParaMeta > >(static_cast< const std::vector< ParaMeta,std::allocator< ParaMeta > >& >(result))), SWIGTYPE_p_std__vectorT_ParaMeta_std__allocatorT_ParaMeta_t_t, SWIG_POINTER_OWN |  0 );
+  return resultobj;
+fail:
+  return NULL;
+}
+
+
 SWIGINTERN PyObject *_wrap_Crystal_basis(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
   PyObject *resultobj = 0;
   Crystal *arg1 = (Crystal *) 0 ;
@@ -46482,6 +46482,29 @@ fail:
 }
 
 
+SWIGINTERN PyObject *_wrap_IsotropicGaussPeakShape_parDefs(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *resultobj = 0;
+  IsotropicGaussPeakShape *arg1 = (IsotropicGaussPeakShape *) 0 ;
+  void *argp1 = 0 ;
+  int res1 = 0 ;
+  PyObject *swig_obj[1] ;
+  SwigValueWrapper< std::vector< ParaMeta,std::allocator< ParaMeta > > > result;
+  
+  if (!args) SWIG_fail;
+  swig_obj[0] = args;
+  res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_IsotropicGaussPeakShape, 0 |  0 );
+  if (!SWIG_IsOK(res1)) {
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "IsotropicGaussPeakShape_parDefs" "', argument " "1"" of type '" "IsotropicGaussPeakShape const *""'"); 
+  }
+  arg1 = reinterpret_cast< IsotropicGaussPeakShape * >(argp1);
+  result = ((IsotropicGaussPeakShape const *)arg1)->parDefs();
+  resultobj = SWIG_NewPointerObj((new std::vector< ParaMeta,std::allocator< ParaMeta > >(static_cast< const std::vector< ParaMeta,std::allocator< ParaMeta > >& >(result))), SWIGTYPE_p_std__vectorT_ParaMeta_std__allocatorT_ParaMeta_t_t, SWIG_POINTER_OWN |  0 );
+  return resultobj;
+fail:
+  return NULL;
+}
+
+
 SWIGINTERN PyObject *_wrap_IsotropicGaussPeakShape_evaluate(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
   PyObject *resultobj = 0;
   IsotropicGaussPeakShape *arg1 = (IsotropicGaussPeakShape *) 0 ;
@@ -46645,6 +46668,29 @@ fail:
 }
 
 
+SWIGINTERN PyObject *_wrap_IsotropicLorentzPeakShape_parDefs(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *resultobj = 0;
+  IsotropicLorentzPeakShape *arg1 = (IsotropicLorentzPeakShape *) 0 ;
+  void *argp1 = 0 ;
+  int res1 = 0 ;
+  PyObject *swig_obj[1] ;
+  SwigValueWrapper< std::vector< ParaMeta,std::allocator< ParaMeta > > > result;
+  
+  if (!args) SWIG_fail;
+  swig_obj[0] = args;
+  res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_IsotropicLorentzPeakShape, 0 |  0 );
+  if (!SWIG_IsOK(res1)) {
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "IsotropicLorentzPeakShape_parDefs" "', argument " "1"" of type '" "IsotropicLorentzPeakShape const *""'"); 
+  }
+  arg1 = reinterpret_cast< IsotropicLorentzPeakShape * >(argp1);
+  result = ((IsotropicLorentzPeakShape const *)arg1)->parDefs();
+  resultobj = SWIG_NewPointerObj((new std::vector< ParaMeta,std::allocator< ParaMeta > >(static_cast< const std::vector< ParaMeta,std::allocator< ParaMeta > >& >(result))), SWIGTYPE_p_std__vectorT_ParaMeta_std__allocatorT_ParaMeta_t_t, SWIG_POINTER_OWN |  0 );
+  return resultobj;
+fail:
+  return NULL;
+}
+
+
 SWIGINTERN PyObject *_wrap_IsotropicLorentzPeakShape_evaluate(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
   PyObject *resultobj = 0;
   IsotropicLorentzPeakShape *arg1 = (IsotropicLorentzPeakShape *) 0 ;
@@ -46816,6 +46862,29 @@ fail:
 }
 
 
+SWIGINTERN PyObject *_wrap_GaussFisherPeakShape_parDefs(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *resultobj = 0;
+  GaussFisherPeakShape *arg1 = (GaussFisherPeakShape *) 0 ;
+  void *argp1 = 0 ;
+  int res1 = 0 ;
+  PyObject *swig_obj[1] ;
+  SwigValueWrapper< std::vector< ParaMeta,std::allocator< ParaMeta > > > result;
+  
+  if (!args) SWIG_fail;
+  swig_obj[0] = args;
+  res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_GaussFisherPeakShape, 0 |  0 );
+  if (!SWIG_IsOK(res1)) {
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "GaussFisherPeakShape_parDefs" "', argument " "1"" of type '" "GaussFisherPeakShape const *""'"); 
+  }
+  arg1 = reinterpret_cast< GaussFisherPeakShape * >(argp1);
+  result = ((GaussFisherPeakShape const *)arg1)->parDefs();
+  resultobj = SWIG_NewPointerObj((new std::vector< ParaMeta,std::allocator< ParaMeta > >(static_cast< const std::vector< ParaMeta,std::allocator< ParaMeta > >& >(result))), SWIGTYPE_p_std__vectorT_ParaMeta_std__allocatorT_ParaMeta_t_t, SWIG_POINTER_OWN |  0 );
+  return resultobj;
+fail:
+  return NULL;
+}
+
+
 SWIGINTERN PyObject *_wrap_GaussFisherPeakShape_evaluate(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
   PyObject *resultobj = 0;
   GaussFisherPeakShape *arg1 = (GaussFisherPeakShape *) 0 ;
@@ -47010,6 +47079,29 @@ fail:
 }
 
 
+SWIGINTERN PyObject *_wrap_LorentzFisherPeakShape_parDefs(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *resultobj = 0;
+  LorentzFisherPeakShape *arg1 = (LorentzFisherPeakShape *) 0 ;
+  void *argp1 = 0 ;
+  int res1 = 0 ;
+  PyObject *swig_obj[1] ;
+  SwigValueWrapper< std::vector< ParaMeta,std::allocator< ParaMeta > > > result;
+  
+  if (!args) SWIG_fail;
+  swig_obj[0] = args;
+  res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_LorentzFisherPeakShape, 0 |  0 );
+  if (!SWIG_IsOK(res1)) {
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "LorentzFisherPeakShape_parDefs" "', argument " "1"" of type '" "LorentzFisherPeakShape const *""'"); 
+  }
+  arg1 = reinterpret_cast< LorentzFisherPeakShape * >(argp1);
+  result = ((LorentzFisherPeakShape const *)arg1)->parDefs();
+  resultobj = SWIG_NewPointerObj((new std::vector< ParaMeta,std::allocator< ParaMeta > >(static_cast< const std::vector< ParaMeta,std::allocator< ParaMeta > >& >(result))), SWIGTYPE_p_std__vectorT_ParaMeta_std__allocatorT_ParaMeta_t_t, SWIG_POINTER_OWN |  0 );
+  return resultobj;
+fail:
+  return NULL;
+}
+
+
 SWIGINTERN PyObject *_wrap_LorentzFisherPeakShape_evaluate(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
   PyObject *resultobj = 0;
   LorentzFisherPeakShape *arg1 = (LorentzFisherPeakShape *) 0 ;
@@ -47228,6 +47320,29 @@ fail:
 }
 
 
+SWIGINTERN PyObject *_wrap_MisesFisherGaussPeakShape_parDefs(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *resultobj = 0;
+  MisesFisherGaussPeakShape *arg1 = (MisesFisherGaussPeakShape *) 0 ;
+  void *argp1 = 0 ;
+  int res1 = 0 ;
+  PyObject *swig_obj[1] ;
+  SwigValueWrapper< std::vector< ParaMeta,std::allocator< ParaMeta > > > result;
+  
+  if (!args) SWIG_fail;
+  swig_obj[0] = args;
+  res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_MisesFisherGaussPeakShape, 0 |  0 );
+  if (!SWIG_IsOK(res1)) {
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "MisesFisherGaussPeakShape_parDefs" "', argument " "1"" of type '" "MisesFisherGaussPeakShape const *""'"); 
+  }
+  arg1 = reinterpret_cast< MisesFisherGaussPeakShape * >(argp1);
+  result = ((MisesFisherGaussPeakShape const *)arg1)->parDefs();
+  resultobj = SWIG_NewPointerObj((new std::vector< ParaMeta,std::allocator< ParaMeta > >(static_cast< const std::vector< ParaMeta,std::allocator< ParaMeta > >& >(result))), SWIGTYPE_p_std__vectorT_ParaMeta_std__allocatorT_ParaMeta_t_t, SWIG_POINTER_OWN |  0 );
+  return resultobj;
+fail:
+  return NULL;
+}
+
+
 SWIGINTERN PyObject *_wrap_MisesFisherGaussPeakShape_evaluate(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
   PyObject *resultobj = 0;
   MisesFisherGaussPeakShape *arg1 = (MisesFisherGaussPeakShape *) 0 ;
@@ -47438,6 +47553,29 @@ fail:
 }
 
 
+SWIGINTERN PyObject *_wrap_MisesGaussPeakShape_parDefs(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *resultobj = 0;
+  MisesGaussPeakShape *arg1 = (MisesGaussPeakShape *) 0 ;
+  void *argp1 = 0 ;
+  int res1 = 0 ;
+  PyObject *swig_obj[1] ;
+  SwigValueWrapper< std::vector< ParaMeta,std::allocator< ParaMeta > > > result;
+  
+  if (!args) SWIG_fail;
+  swig_obj[0] = args;
+  res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_MisesGaussPeakShape, 0 |  0 );
+  if (!SWIG_IsOK(res1)) {
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "MisesGaussPeakShape_parDefs" "', argument " "1"" of type '" "MisesGaussPeakShape const *""'"); 
+  }
+  arg1 = reinterpret_cast< MisesGaussPeakShape * >(argp1);
+  result = ((MisesGaussPeakShape const *)arg1)->parDefs();
+  resultobj = SWIG_NewPointerObj((new std::vector< ParaMeta,std::allocator< ParaMeta > >(static_cast< const std::vector< ParaMeta,std::allocator< ParaMeta > >& >(result))), SWIGTYPE_p_std__vectorT_ParaMeta_std__allocatorT_ParaMeta_t_t, SWIG_POINTER_OWN |  0 );
+  return resultobj;
+fail:
+  return NULL;
+}
+
+
 SWIGINTERN PyObject *_wrap_MisesGaussPeakShape_evaluate(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
   PyObject *resultobj = 0;
   MisesGaussPeakShape *arg1 = (MisesGaussPeakShape *) 0 ;
@@ -47944,6 +48082,29 @@ fail:
 }
 
 
+SWIGINTERN PyObject *_wrap_Interference1DLattice_parDefs(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *resultobj = 0;
+  Interference1DLattice *arg1 = (Interference1DLattice *) 0 ;
+  void *argp1 = 0 ;
+  int res1 = 0 ;
+  PyObject *swig_obj[1] ;
+  SwigValueWrapper< std::vector< ParaMeta,std::allocator< ParaMeta > > > result;
+  
+  if (!args) SWIG_fail;
+  swig_obj[0] = args;
+  res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_Interference1DLattice, 0 |  0 );
+  if (!SWIG_IsOK(res1)) {
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Interference1DLattice_parDefs" "', argument " "1"" of type '" "Interference1DLattice const *""'"); 
+  }
+  arg1 = reinterpret_cast< Interference1DLattice * >(argp1);
+  result = ((Interference1DLattice const *)arg1)->parDefs();
+  resultobj = SWIG_NewPointerObj((new std::vector< ParaMeta,std::allocator< ParaMeta > >(static_cast< const std::vector< ParaMeta,std::allocator< ParaMeta > >& >(result))), SWIGTYPE_p_std__vectorT_ParaMeta_std__allocatorT_ParaMeta_t_t, SWIG_POINTER_OWN |  0 );
+  return resultobj;
+fail:
+  return NULL;
+}
+
+
 SWIGINTERN PyObject *_wrap_Interference1DLattice_setDecayFunction(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
   PyObject *resultobj = 0;
   Interference1DLattice *arg1 = (Interference1DLattice *) 0 ;
@@ -48431,6 +48592,29 @@ fail:
 }
 
 
+SWIGINTERN PyObject *_wrap_Interference2DParaCrystal_parDefs(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *resultobj = 0;
+  Interference2DParaCrystal *arg1 = (Interference2DParaCrystal *) 0 ;
+  void *argp1 = 0 ;
+  int res1 = 0 ;
+  PyObject *swig_obj[1] ;
+  SwigValueWrapper< std::vector< ParaMeta,std::allocator< ParaMeta > > > result;
+  
+  if (!args) SWIG_fail;
+  swig_obj[0] = args;
+  res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_Interference2DParaCrystal, 0 |  0 );
+  if (!SWIG_IsOK(res1)) {
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Interference2DParaCrystal_parDefs" "', argument " "1"" of type '" "Interference2DParaCrystal const *""'"); 
+  }
+  arg1 = reinterpret_cast< Interference2DParaCrystal * >(argp1);
+  result = ((Interference2DParaCrystal const *)arg1)->parDefs();
+  resultobj = SWIG_NewPointerObj((new std::vector< ParaMeta,std::allocator< ParaMeta > >(static_cast< const std::vector< ParaMeta,std::allocator< ParaMeta > >& >(result))), SWIGTYPE_p_std__vectorT_ParaMeta_std__allocatorT_ParaMeta_t_t, SWIG_POINTER_OWN |  0 );
+  return resultobj;
+fail:
+  return NULL;
+}
+
+
 SWIGINTERN PyObject *_wrap_Interference2DParaCrystal_setDomainSizes(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
   PyObject *resultobj = 0;
   Interference2DParaCrystal *arg1 = (Interference2DParaCrystal *) 0 ;
@@ -49011,6 +49195,29 @@ fail:
 }
 
 
+SWIGINTERN PyObject *_wrap_Interference2DSuperLattice_parDefs(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *resultobj = 0;
+  Interference2DSuperLattice *arg1 = (Interference2DSuperLattice *) 0 ;
+  void *argp1 = 0 ;
+  int res1 = 0 ;
+  PyObject *swig_obj[1] ;
+  SwigValueWrapper< std::vector< ParaMeta,std::allocator< ParaMeta > > > result;
+  
+  if (!args) SWIG_fail;
+  swig_obj[0] = args;
+  res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_Interference2DSuperLattice, 0 |  0 );
+  if (!SWIG_IsOK(res1)) {
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Interference2DSuperLattice_parDefs" "', argument " "1"" of type '" "Interference2DSuperLattice const *""'"); 
+  }
+  arg1 = reinterpret_cast< Interference2DSuperLattice * >(argp1);
+  result = ((Interference2DSuperLattice const *)arg1)->parDefs();
+  resultobj = SWIG_NewPointerObj((new std::vector< ParaMeta,std::allocator< ParaMeta > >(static_cast< const std::vector< ParaMeta,std::allocator< ParaMeta > >& >(result))), SWIGTYPE_p_std__vectorT_ParaMeta_std__allocatorT_ParaMeta_t_t, SWIG_POINTER_OWN |  0 );
+  return resultobj;
+fail:
+  return NULL;
+}
+
+
 SWIGINTERN PyObject *_wrap_Interference2DSuperLattice_setSubstructureIFF(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
   PyObject *resultobj = 0;
   Interference2DSuperLattice *arg1 = (Interference2DSuperLattice *) 0 ;
@@ -50256,6 +50463,29 @@ fail:
 }
 
 
+SWIGINTERN PyObject *_wrap_InterferenceHardDisk_parDefs(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *resultobj = 0;
+  InterferenceHardDisk *arg1 = (InterferenceHardDisk *) 0 ;
+  void *argp1 = 0 ;
+  int res1 = 0 ;
+  PyObject *swig_obj[1] ;
+  SwigValueWrapper< std::vector< ParaMeta,std::allocator< ParaMeta > > > result;
+  
+  if (!args) SWIG_fail;
+  swig_obj[0] = args;
+  res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_InterferenceHardDisk, 0 |  0 );
+  if (!SWIG_IsOK(res1)) {
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "InterferenceHardDisk_parDefs" "', argument " "1"" of type '" "InterferenceHardDisk const *""'"); 
+  }
+  arg1 = reinterpret_cast< InterferenceHardDisk * >(argp1);
+  result = ((InterferenceHardDisk const *)arg1)->parDefs();
+  resultobj = SWIG_NewPointerObj((new std::vector< ParaMeta,std::allocator< ParaMeta > >(static_cast< const std::vector< ParaMeta,std::allocator< ParaMeta > >& >(result))), SWIGTYPE_p_std__vectorT_ParaMeta_std__allocatorT_ParaMeta_t_t, SWIG_POINTER_OWN |  0 );
+  return resultobj;
+fail:
+  return NULL;
+}
+
+
 SWIGINTERN PyObject *_wrap_InterferenceHardDisk_clone(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
   PyObject *resultobj = 0;
   InterferenceHardDisk *arg1 = (InterferenceHardDisk *) 0 ;
@@ -50550,6 +50780,29 @@ fail:
 }
 
 
+SWIGINTERN PyObject *_wrap_InterferenceRadialParaCrystal_parDefs(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *resultobj = 0;
+  InterferenceRadialParaCrystal *arg1 = (InterferenceRadialParaCrystal *) 0 ;
+  void *argp1 = 0 ;
+  int res1 = 0 ;
+  PyObject *swig_obj[1] ;
+  SwigValueWrapper< std::vector< ParaMeta,std::allocator< ParaMeta > > > result;
+  
+  if (!args) SWIG_fail;
+  swig_obj[0] = args;
+  res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_InterferenceRadialParaCrystal, 0 |  0 );
+  if (!SWIG_IsOK(res1)) {
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "InterferenceRadialParaCrystal_parDefs" "', argument " "1"" of type '" "InterferenceRadialParaCrystal const *""'"); 
+  }
+  arg1 = reinterpret_cast< InterferenceRadialParaCrystal * >(argp1);
+  result = ((InterferenceRadialParaCrystal const *)arg1)->parDefs();
+  resultobj = SWIG_NewPointerObj((new std::vector< ParaMeta,std::allocator< ParaMeta > >(static_cast< const std::vector< ParaMeta,std::allocator< ParaMeta > >& >(result))), SWIGTYPE_p_std__vectorT_ParaMeta_std__allocatorT_ParaMeta_t_t, SWIG_POINTER_OWN |  0 );
+  return resultobj;
+fail:
+  return NULL;
+}
+
+
 SWIGINTERN PyObject *_wrap_InterferenceRadialParaCrystal_setKappa(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
   PyObject *resultobj = 0;
   InterferenceRadialParaCrystal *arg1 = (InterferenceRadialParaCrystal *) 0 ;
@@ -50928,6 +51181,29 @@ fail:
 }
 
 
+SWIGINTERN PyObject *_wrap_InterferenceTwin_parDefs(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *resultobj = 0;
+  InterferenceTwin *arg1 = (InterferenceTwin *) 0 ;
+  void *argp1 = 0 ;
+  int res1 = 0 ;
+  PyObject *swig_obj[1] ;
+  SwigValueWrapper< std::vector< ParaMeta,std::allocator< ParaMeta > > > result;
+  
+  if (!args) SWIG_fail;
+  swig_obj[0] = args;
+  res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_InterferenceTwin, 0 |  0 );
+  if (!SWIG_IsOK(res1)) {
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "InterferenceTwin_parDefs" "', argument " "1"" of type '" "InterferenceTwin const *""'"); 
+  }
+  arg1 = reinterpret_cast< InterferenceTwin * >(argp1);
+  result = ((InterferenceTwin const *)arg1)->parDefs();
+  resultobj = SWIG_NewPointerObj((new std::vector< ParaMeta,std::allocator< ParaMeta > >(static_cast< const std::vector< ParaMeta,std::allocator< ParaMeta > >& >(result))), SWIGTYPE_p_std__vectorT_ParaMeta_std__allocatorT_ParaMeta_t_t, SWIG_POINTER_OWN |  0 );
+  return resultobj;
+fail:
+  return NULL;
+}
+
+
 SWIGINTERN PyObject *_wrap_InterferenceTwin_direction(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
   PyObject *resultobj = 0;
   InterferenceTwin *arg1 = (InterferenceTwin *) 0 ;
@@ -51211,6 +51487,29 @@ fail:
 }
 
 
+SWIGINTERN PyObject *_wrap_ParticleLayout_parDefs(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *resultobj = 0;
+  ParticleLayout *arg1 = (ParticleLayout *) 0 ;
+  void *argp1 = 0 ;
+  int res1 = 0 ;
+  PyObject *swig_obj[1] ;
+  SwigValueWrapper< std::vector< ParaMeta,std::allocator< ParaMeta > > > result;
+  
+  if (!args) SWIG_fail;
+  swig_obj[0] = args;
+  res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_ParticleLayout, 0 |  0 );
+  if (!SWIG_IsOK(res1)) {
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "ParticleLayout_parDefs" "', argument " "1"" of type '" "ParticleLayout const *""'"); 
+  }
+  arg1 = reinterpret_cast< ParticleLayout * >(argp1);
+  result = ((ParticleLayout const *)arg1)->parDefs();
+  resultobj = SWIG_NewPointerObj((new std::vector< ParaMeta,std::allocator< ParaMeta > >(static_cast< const std::vector< ParaMeta,std::allocator< ParaMeta > >& >(result))), SWIGTYPE_p_std__vectorT_ParaMeta_std__allocatorT_ParaMeta_t_t, SWIG_POINTER_OWN |  0 );
+  return resultobj;
+fail:
+  return NULL;
+}
+
+
 SWIGINTERN PyObject *_wrap_ParticleLayout_nodeChildren(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
   PyObject *resultobj = 0;
   ParticleLayout *arg1 = (ParticleLayout *) 0 ;
@@ -51983,6 +52282,29 @@ fail:
 }
 
 
+SWIGINTERN PyObject *_wrap_LayerRoughness_parDefs(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *resultobj = 0;
+  LayerRoughness *arg1 = (LayerRoughness *) 0 ;
+  void *argp1 = 0 ;
+  int res1 = 0 ;
+  PyObject *swig_obj[1] ;
+  SwigValueWrapper< std::vector< ParaMeta,std::allocator< ParaMeta > > > result;
+  
+  if (!args) SWIG_fail;
+  swig_obj[0] = args;
+  res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_LayerRoughness, 0 |  0 );
+  if (!SWIG_IsOK(res1)) {
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "LayerRoughness_parDefs" "', argument " "1"" of type '" "LayerRoughness const *""'"); 
+  }
+  arg1 = reinterpret_cast< LayerRoughness * >(argp1);
+  result = ((LayerRoughness const *)arg1)->parDefs();
+  resultobj = SWIG_NewPointerObj((new std::vector< ParaMeta,std::allocator< ParaMeta > >(static_cast< const std::vector< ParaMeta,std::allocator< ParaMeta > >& >(result))), SWIGTYPE_p_std__vectorT_ParaMeta_std__allocatorT_ParaMeta_t_t, SWIG_POINTER_OWN |  0 );
+  return resultobj;
+fail:
+  return NULL;
+}
+
+
 SWIGINTERN PyObject *_wrap_LayerRoughness_spectralFunction(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
   PyObject *resultobj = 0;
   LayerRoughness *arg1 = (LayerRoughness *) 0 ;
@@ -52422,6 +52744,29 @@ fail:
 }
 
 
+SWIGINTERN PyObject *_wrap_Layer_parDefs(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *resultobj = 0;
+  Layer *arg1 = (Layer *) 0 ;
+  void *argp1 = 0 ;
+  int res1 = 0 ;
+  PyObject *swig_obj[1] ;
+  SwigValueWrapper< std::vector< ParaMeta,std::allocator< ParaMeta > > > result;
+  
+  if (!args) SWIG_fail;
+  swig_obj[0] = args;
+  res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_Layer, 0 |  0 );
+  if (!SWIG_IsOK(res1)) {
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Layer_parDefs" "', argument " "1"" of type '" "Layer const *""'"); 
+  }
+  arg1 = reinterpret_cast< Layer * >(argp1);
+  result = ((Layer const *)arg1)->parDefs();
+  resultobj = SWIG_NewPointerObj((new std::vector< ParaMeta,std::allocator< ParaMeta > >(static_cast< const std::vector< ParaMeta,std::allocator< ParaMeta > >& >(result))), SWIGTYPE_p_std__vectorT_ParaMeta_std__allocatorT_ParaMeta_t_t, SWIG_POINTER_OWN |  0 );
+  return resultobj;
+fail:
+  return NULL;
+}
+
+
 SWIGINTERN PyObject *_wrap_Layer_nodeChildren(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
   PyObject *resultobj = 0;
   Layer *arg1 = (Layer *) 0 ;
@@ -63974,6 +64319,29 @@ fail:
 }
 
 
+SWIGINTERN PyObject *_wrap_BasicLattice2D_parDefs(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *resultobj = 0;
+  BasicLattice2D *arg1 = (BasicLattice2D *) 0 ;
+  void *argp1 = 0 ;
+  int res1 = 0 ;
+  PyObject *swig_obj[1] ;
+  SwigValueWrapper< std::vector< ParaMeta,std::allocator< ParaMeta > > > result;
+  
+  if (!args) SWIG_fail;
+  swig_obj[0] = args;
+  res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_BasicLattice2D, 0 |  0 );
+  if (!SWIG_IsOK(res1)) {
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "BasicLattice2D_parDefs" "', argument " "1"" of type '" "BasicLattice2D const *""'"); 
+  }
+  arg1 = reinterpret_cast< BasicLattice2D * >(argp1);
+  result = ((BasicLattice2D const *)arg1)->parDefs();
+  resultobj = SWIG_NewPointerObj((new std::vector< ParaMeta,std::allocator< ParaMeta > >(static_cast< const std::vector< ParaMeta,std::allocator< ParaMeta > >& >(result))), SWIGTYPE_p_std__vectorT_ParaMeta_std__allocatorT_ParaMeta_t_t, SWIG_POINTER_OWN |  0 );
+  return resultobj;
+fail:
+  return NULL;
+}
+
+
 SWIGINTERN PyObject *_wrap_BasicLattice2D_length1(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
   PyObject *resultobj = 0;
   BasicLattice2D *arg1 = (BasicLattice2D *) 0 ;
@@ -64239,6 +64607,29 @@ fail:
 }
 
 
+SWIGINTERN PyObject *_wrap_SquareLattice2D_parDefs(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *resultobj = 0;
+  SquareLattice2D *arg1 = (SquareLattice2D *) 0 ;
+  void *argp1 = 0 ;
+  int res1 = 0 ;
+  PyObject *swig_obj[1] ;
+  SwigValueWrapper< std::vector< ParaMeta,std::allocator< ParaMeta > > > result;
+  
+  if (!args) SWIG_fail;
+  swig_obj[0] = args;
+  res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_SquareLattice2D, 0 |  0 );
+  if (!SWIG_IsOK(res1)) {
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "SquareLattice2D_parDefs" "', argument " "1"" of type '" "SquareLattice2D const *""'"); 
+  }
+  arg1 = reinterpret_cast< SquareLattice2D * >(argp1);
+  result = ((SquareLattice2D const *)arg1)->parDefs();
+  resultobj = SWIG_NewPointerObj((new std::vector< ParaMeta,std::allocator< ParaMeta > >(static_cast< const std::vector< ParaMeta,std::allocator< ParaMeta > >& >(result))), SWIGTYPE_p_std__vectorT_ParaMeta_std__allocatorT_ParaMeta_t_t, SWIG_POINTER_OWN |  0 );
+  return resultobj;
+fail:
+  return NULL;
+}
+
+
 SWIGINTERN PyObject *_wrap_SquareLattice2D_length1(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
   PyObject *resultobj = 0;
   SquareLattice2D *arg1 = (SquareLattice2D *) 0 ;
@@ -64440,6 +64831,29 @@ fail:
 }
 
 
+SWIGINTERN PyObject *_wrap_HexagonalLattice2D_parDefs(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *resultobj = 0;
+  HexagonalLattice2D *arg1 = (HexagonalLattice2D *) 0 ;
+  void *argp1 = 0 ;
+  int res1 = 0 ;
+  PyObject *swig_obj[1] ;
+  SwigValueWrapper< std::vector< ParaMeta,std::allocator< ParaMeta > > > result;
+  
+  if (!args) SWIG_fail;
+  swig_obj[0] = args;
+  res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_HexagonalLattice2D, 0 |  0 );
+  if (!SWIG_IsOK(res1)) {
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "HexagonalLattice2D_parDefs" "', argument " "1"" of type '" "HexagonalLattice2D const *""'"); 
+  }
+  arg1 = reinterpret_cast< HexagonalLattice2D * >(argp1);
+  result = ((HexagonalLattice2D const *)arg1)->parDefs();
+  resultobj = SWIG_NewPointerObj((new std::vector< ParaMeta,std::allocator< ParaMeta > >(static_cast< const std::vector< ParaMeta,std::allocator< ParaMeta > >& >(result))), SWIGTYPE_p_std__vectorT_ParaMeta_std__allocatorT_ParaMeta_t_t, SWIG_POINTER_OWN |  0 );
+  return resultobj;
+fail:
+  return NULL;
+}
+
+
 SWIGINTERN PyObject *_wrap_HexagonalLattice2D_length1(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
   PyObject *resultobj = 0;
   HexagonalLattice2D *arg1 = (HexagonalLattice2D *) 0 ;
@@ -65985,11 +66399,6 @@ static PyMethodDef SwigMethods[] = {
 		"std::string IdentityRotation::className() const final\n"
 		"\n"
 		""},
-	 { "IdentityRotation_parDefs", _wrap_IdentityRotation_parDefs, METH_O, "\n"
-		"IdentityRotation_parDefs(IdentityRotation self) -> std::vector< ParaMeta,std::allocator< ParaMeta > >\n"
-		"std::vector<ParaMeta> IdentityRotation::parDefs() const final\n"
-		"\n"
-		""},
 	 { "IdentityRotation_createInverse", _wrap_IdentityRotation_createInverse, METH_O, "\n"
 		"IdentityRotation_createInverse(IdentityRotation self) -> IdentityRotation\n"
 		"IdentityRotation* IdentityRotation::createInverse() const override\n"
@@ -66223,6 +66632,11 @@ static PyMethodDef SwigMethods[] = {
 		"std::vector< const INode * > Crystal::nodeChildren() const override\n"
 		"\n"
 		""},
+	 { "Crystal_parDefs", _wrap_Crystal_parDefs, METH_O, "\n"
+		"Crystal_parDefs(Crystal self) -> std::vector< ParaMeta,std::allocator< ParaMeta > >\n"
+		"std::vector<ParaMeta> Crystal::parDefs() const final\n"
+		"\n"
+		""},
 	 { "Crystal_basis", _wrap_Crystal_basis, METH_O, "\n"
 		"Crystal_basis(Crystal self) -> IParticle\n"
 		"const IParticle* Crystal::basis() const\n"
@@ -67288,6 +67702,11 @@ static PyMethodDef SwigMethods[] = {
 		"std::string IsotropicGaussPeakShape::className() const final\n"
 		"\n"
 		""},
+	 { "IsotropicGaussPeakShape_parDefs", _wrap_IsotropicGaussPeakShape_parDefs, METH_O, "\n"
+		"IsotropicGaussPeakShape_parDefs(IsotropicGaussPeakShape self) -> std::vector< ParaMeta,std::allocator< ParaMeta > >\n"
+		"std::vector<ParaMeta> IsotropicGaussPeakShape::parDefs() const final\n"
+		"\n"
+		""},
 	 { "IsotropicGaussPeakShape_evaluate", _wrap_IsotropicGaussPeakShape_evaluate, METH_VARARGS, "\n"
 		"IsotropicGaussPeakShape_evaluate(IsotropicGaussPeakShape self, R3 q, R3 q_lattice_point) -> double\n"
 		"double IsotropicGaussPeakShape::evaluate(R3 q, R3 q_lattice_point) const override\n"
@@ -67317,6 +67736,11 @@ static PyMethodDef SwigMethods[] = {
 		"std::string IsotropicLorentzPeakShape::className() const final\n"
 		"\n"
 		""},
+	 { "IsotropicLorentzPeakShape_parDefs", _wrap_IsotropicLorentzPeakShape_parDefs, METH_O, "\n"
+		"IsotropicLorentzPeakShape_parDefs(IsotropicLorentzPeakShape self) -> std::vector< ParaMeta,std::allocator< ParaMeta > >\n"
+		"std::vector<ParaMeta> IsotropicLorentzPeakShape::parDefs() const final\n"
+		"\n"
+		""},
 	 { "IsotropicLorentzPeakShape_evaluate", _wrap_IsotropicLorentzPeakShape_evaluate, METH_VARARGS, "\n"
 		"IsotropicLorentzPeakShape_evaluate(IsotropicLorentzPeakShape self, R3 q, R3 q_lattice_point) -> double\n"
 		"double IsotropicLorentzPeakShape::evaluate(R3 q, R3 q_lattice_point) const override\n"
@@ -67346,6 +67770,11 @@ static PyMethodDef SwigMethods[] = {
 		"std::string GaussFisherPeakShape::className() const final\n"
 		"\n"
 		""},
+	 { "GaussFisherPeakShape_parDefs", _wrap_GaussFisherPeakShape_parDefs, METH_O, "\n"
+		"GaussFisherPeakShape_parDefs(GaussFisherPeakShape self) -> std::vector< ParaMeta,std::allocator< ParaMeta > >\n"
+		"std::vector<ParaMeta> GaussFisherPeakShape::parDefs() const final\n"
+		"\n"
+		""},
 	 { "GaussFisherPeakShape_evaluate", _wrap_GaussFisherPeakShape_evaluate, METH_VARARGS, "\n"
 		"GaussFisherPeakShape_evaluate(GaussFisherPeakShape self, R3 q, R3 q_lattice_point) -> double\n"
 		"double GaussFisherPeakShape::evaluate(R3 q, R3 q_lattice_point) const override\n"
@@ -67382,6 +67811,11 @@ static PyMethodDef SwigMethods[] = {
 		"std::string LorentzFisherPeakShape::className() const final\n"
 		"\n"
 		""},
+	 { "LorentzFisherPeakShape_parDefs", _wrap_LorentzFisherPeakShape_parDefs, METH_O, "\n"
+		"LorentzFisherPeakShape_parDefs(LorentzFisherPeakShape self) -> std::vector< ParaMeta,std::allocator< ParaMeta > >\n"
+		"std::vector<ParaMeta> LorentzFisherPeakShape::parDefs() const final\n"
+		"\n"
+		""},
 	 { "LorentzFisherPeakShape_evaluate", _wrap_LorentzFisherPeakShape_evaluate, METH_VARARGS, "\n"
 		"LorentzFisherPeakShape_evaluate(LorentzFisherPeakShape self, R3 q, R3 q_lattice_point) -> double\n"
 		"double LorentzFisherPeakShape::evaluate(R3 q, R3 q_lattice_point) const override\n"
@@ -67418,6 +67852,11 @@ static PyMethodDef SwigMethods[] = {
 		"std::string MisesFisherGaussPeakShape::className() const final\n"
 		"\n"
 		""},
+	 { "MisesFisherGaussPeakShape_parDefs", _wrap_MisesFisherGaussPeakShape_parDefs, METH_O, "\n"
+		"MisesFisherGaussPeakShape_parDefs(MisesFisherGaussPeakShape self) -> std::vector< ParaMeta,std::allocator< ParaMeta > >\n"
+		"std::vector<ParaMeta> MisesFisherGaussPeakShape::parDefs() const final\n"
+		"\n"
+		""},
 	 { "MisesFisherGaussPeakShape_evaluate", _wrap_MisesFisherGaussPeakShape_evaluate, METH_VARARGS, "\n"
 		"MisesFisherGaussPeakShape_evaluate(MisesFisherGaussPeakShape self, R3 q, R3 q_lattice_point) -> double\n"
 		"double MisesFisherGaussPeakShape::evaluate(R3 q, R3 q_lattice_point) const override\n"
@@ -67454,6 +67893,11 @@ static PyMethodDef SwigMethods[] = {
 		"std::string MisesGaussPeakShape::className() const final\n"
 		"\n"
 		""},
+	 { "MisesGaussPeakShape_parDefs", _wrap_MisesGaussPeakShape_parDefs, METH_O, "\n"
+		"MisesGaussPeakShape_parDefs(MisesGaussPeakShape self) -> std::vector< ParaMeta,std::allocator< ParaMeta > >\n"
+		"std::vector<ParaMeta> MisesGaussPeakShape::parDefs() const final\n"
+		"\n"
+		""},
 	 { "MisesGaussPeakShape_evaluate", _wrap_MisesGaussPeakShape_evaluate, METH_VARARGS, "\n"
 		"MisesGaussPeakShape_evaluate(MisesGaussPeakShape self, R3 q, R3 q_lattice_point) -> double\n"
 		"double MisesGaussPeakShape::evaluate(R3 q, R3 q_lattice_point) const override\n"
@@ -67550,6 +67994,11 @@ static PyMethodDef SwigMethods[] = {
 		"std::string Interference1DLattice::className() const final\n"
 		"\n"
 		""},
+	 { "Interference1DLattice_parDefs", _wrap_Interference1DLattice_parDefs, METH_O, "\n"
+		"Interference1DLattice_parDefs(Interference1DLattice self) -> std::vector< ParaMeta,std::allocator< ParaMeta > >\n"
+		"std::vector<ParaMeta> Interference1DLattice::parDefs() const final\n"
+		"\n"
+		""},
 	 { "Interference1DLattice_setDecayFunction", _wrap_Interference1DLattice_setDecayFunction, METH_VARARGS, "\n"
 		"Interference1DLattice_setDecayFunction(Interference1DLattice self, IFTDecayFunction1D decay)\n"
 		"void Interference1DLattice::setDecayFunction(const IFTDecayFunction1D &decay)\n"
@@ -67662,6 +68111,11 @@ static PyMethodDef SwigMethods[] = {
 		"std::string Interference2DParaCrystal::className() const final\n"
 		"\n"
 		""},
+	 { "Interference2DParaCrystal_parDefs", _wrap_Interference2DParaCrystal_parDefs, METH_O, "\n"
+		"Interference2DParaCrystal_parDefs(Interference2DParaCrystal self) -> std::vector< ParaMeta,std::allocator< ParaMeta > >\n"
+		"std::vector<ParaMeta> Interference2DParaCrystal::parDefs() const final\n"
+		"\n"
+		""},
 	 { "Interference2DParaCrystal_setDomainSizes", _wrap_Interference2DParaCrystal_setDomainSizes, METH_VARARGS, "\n"
 		"Interference2DParaCrystal_setDomainSizes(Interference2DParaCrystal self, double size_1, double size_2)\n"
 		"void Interference2DParaCrystal::setDomainSizes(double size_1, double size_2)\n"
@@ -67808,6 +68262,11 @@ static PyMethodDef SwigMethods[] = {
 		"std::string Interference2DSuperLattice::className() const final\n"
 		"\n"
 		""},
+	 { "Interference2DSuperLattice_parDefs", _wrap_Interference2DSuperLattice_parDefs, METH_O, "\n"
+		"Interference2DSuperLattice_parDefs(Interference2DSuperLattice self) -> std::vector< ParaMeta,std::allocator< ParaMeta > >\n"
+		"std::vector<ParaMeta> Interference2DSuperLattice::parDefs() const final\n"
+		"\n"
+		""},
 	 { "Interference2DSuperLattice_setSubstructureIFF", _wrap_Interference2DSuperLattice_setSubstructureIFF, METH_VARARGS, "\n"
 		"Interference2DSuperLattice_setSubstructureIFF(Interference2DSuperLattice self, IInterference sub_iff)\n"
 		"void Interference2DSuperLattice::setSubstructureIFF(const IInterference &sub_iff)\n"
@@ -68038,6 +68497,11 @@ static PyMethodDef SwigMethods[] = {
 		"InterferenceHardDisk::~InterferenceHardDisk() override=default\n"
 		"\n"
 		""},
+	 { "InterferenceHardDisk_parDefs", _wrap_InterferenceHardDisk_parDefs, METH_O, "\n"
+		"InterferenceHardDisk_parDefs(InterferenceHardDisk self) -> std::vector< ParaMeta,std::allocator< ParaMeta > >\n"
+		"std::vector<ParaMeta> InterferenceHardDisk::parDefs() const final\n"
+		"\n"
+		""},
 	 { "InterferenceHardDisk_clone", _wrap_InterferenceHardDisk_clone, METH_O, "\n"
 		"InterferenceHardDisk_clone(InterferenceHardDisk self) -> InterferenceHardDisk\n"
 		"InterferenceHardDisk * InterferenceHardDisk::clone() const override\n"
@@ -68111,6 +68575,11 @@ static PyMethodDef SwigMethods[] = {
 		"std::string InterferenceRadialParaCrystal::className() const final\n"
 		"\n"
 		""},
+	 { "InterferenceRadialParaCrystal_parDefs", _wrap_InterferenceRadialParaCrystal_parDefs, METH_O, "\n"
+		"InterferenceRadialParaCrystal_parDefs(InterferenceRadialParaCrystal self) -> std::vector< ParaMeta,std::allocator< ParaMeta > >\n"
+		"std::vector<ParaMeta> InterferenceRadialParaCrystal::parDefs() const final\n"
+		"\n"
+		""},
 	 { "InterferenceRadialParaCrystal_setKappa", _wrap_InterferenceRadialParaCrystal_setKappa, METH_VARARGS, "\n"
 		"InterferenceRadialParaCrystal_setKappa(InterferenceRadialParaCrystal self, double kappa)\n"
 		"void InterferenceRadialParaCrystal::setKappa(double kappa)\n"
@@ -68197,6 +68666,11 @@ static PyMethodDef SwigMethods[] = {
 		"std::string InterferenceTwin::className() const final\n"
 		"\n"
 		""},
+	 { "InterferenceTwin_parDefs", _wrap_InterferenceTwin_parDefs, METH_O, "\n"
+		"InterferenceTwin_parDefs(InterferenceTwin self) -> std::vector< ParaMeta,std::allocator< ParaMeta > >\n"
+		"std::vector<ParaMeta> InterferenceTwin::parDefs() const final\n"
+		"\n"
+		""},
 	 { "InterferenceTwin_direction", _wrap_InterferenceTwin_direction, METH_O, "\n"
 		"InterferenceTwin_direction(InterferenceTwin self) -> R3\n"
 		"R3 InterferenceTwin::direction() const\n"
@@ -68238,6 +68712,11 @@ static PyMethodDef SwigMethods[] = {
 		"std::string ParticleLayout::className() const final\n"
 		"\n"
 		""},
+	 { "ParticleLayout_parDefs", _wrap_ParticleLayout_parDefs, METH_O, "\n"
+		"ParticleLayout_parDefs(ParticleLayout self) -> std::vector< ParaMeta,std::allocator< ParaMeta > >\n"
+		"std::vector<ParaMeta> ParticleLayout::parDefs() const final\n"
+		"\n"
+		""},
 	 { "ParticleLayout_nodeChildren", _wrap_ParticleLayout_nodeChildren, METH_O, "\n"
 		"ParticleLayout_nodeChildren(ParticleLayout self) -> swig_dummy_type_const_inode_vector\n"
 		"std::vector< const INode * > ParticleLayout::nodeChildren() const override\n"
@@ -68344,6 +68823,11 @@ static PyMethodDef SwigMethods[] = {
 		"std::string LayerRoughness::className() const final\n"
 		"\n"
 		""},
+	 { "LayerRoughness_parDefs", _wrap_LayerRoughness_parDefs, METH_O, "\n"
+		"LayerRoughness_parDefs(LayerRoughness self) -> std::vector< ParaMeta,std::allocator< ParaMeta > >\n"
+		"std::vector<ParaMeta> LayerRoughness::parDefs() const final\n"
+		"\n"
+		""},
 	 { "LayerRoughness_spectralFunction", _wrap_LayerRoughness_spectralFunction, METH_VARARGS, "\n"
 		"LayerRoughness_spectralFunction(LayerRoughness self, R3 kvec) -> double\n"
 		"double LayerRoughness::spectralFunction(R3 kvec) const\n"
@@ -68440,6 +68924,11 @@ static PyMethodDef SwigMethods[] = {
 		"std::string Layer::className() const final\n"
 		"\n"
 		""},
+	 { "Layer_parDefs", _wrap_Layer_parDefs, METH_O, "\n"
+		"Layer_parDefs(Layer self) -> std::vector< ParaMeta,std::allocator< ParaMeta > >\n"
+		"std::vector<ParaMeta> Layer::parDefs() const final\n"
+		"\n"
+		""},
 	 { "Layer_nodeChildren", _wrap_Layer_nodeChildren, METH_O, "\n"
 		"Layer_nodeChildren(Layer self) -> swig_dummy_type_const_inode_vector\n"
 		"std::vector< const INode * > Layer::nodeChildren() const override\n"
@@ -70228,6 +70717,11 @@ static PyMethodDef SwigMethods[] = {
 		"std::string BasicLattice2D::className() const final\n"
 		"\n"
 		""},
+	 { "BasicLattice2D_parDefs", _wrap_BasicLattice2D_parDefs, METH_O, "\n"
+		"BasicLattice2D_parDefs(BasicLattice2D self) -> std::vector< ParaMeta,std::allocator< ParaMeta > >\n"
+		"std::vector<ParaMeta> BasicLattice2D::parDefs() const final\n"
+		"\n"
+		""},
 	 { "BasicLattice2D_length1", _wrap_BasicLattice2D_length1, METH_O, "\n"
 		"BasicLattice2D_length1(BasicLattice2D self) -> double\n"
 		"double BasicLattice2D::length1() const override\n"
@@ -70266,6 +70760,11 @@ static PyMethodDef SwigMethods[] = {
 		"std::string SquareLattice2D::className() const final\n"
 		"\n"
 		""},
+	 { "SquareLattice2D_parDefs", _wrap_SquareLattice2D_parDefs, METH_O, "\n"
+		"SquareLattice2D_parDefs(SquareLattice2D self) -> std::vector< ParaMeta,std::allocator< ParaMeta > >\n"
+		"std::vector<ParaMeta> SquareLattice2D::parDefs() const final\n"
+		"\n"
+		""},
 	 { "SquareLattice2D_length1", _wrap_SquareLattice2D_length1, METH_O, "\n"
 		"SquareLattice2D_length1(SquareLattice2D self) -> double\n"
 		"double SquareLattice2D::length1() const override\n"
@@ -70304,6 +70803,11 @@ static PyMethodDef SwigMethods[] = {
 		"std::string HexagonalLattice2D::className() const final\n"
 		"\n"
 		""},
+	 { "HexagonalLattice2D_parDefs", _wrap_HexagonalLattice2D_parDefs, METH_O, "\n"
+		"HexagonalLattice2D_parDefs(HexagonalLattice2D self) -> std::vector< ParaMeta,std::allocator< ParaMeta > >\n"
+		"std::vector<ParaMeta> HexagonalLattice2D::parDefs() const final\n"
+		"\n"
+		""},
 	 { "HexagonalLattice2D_length1", _wrap_HexagonalLattice2D_length1, METH_O, "\n"
 		"HexagonalLattice2D_length1(HexagonalLattice2D self) -> double\n"
 		"double HexagonalLattice2D::length1() const override\n"
-- 
GitLab