From 9d4e151fcfc88483ef97f76d72d5ac7c40064d8d Mon Sep 17 00:00:00 2001
From: Joachim Wuttke <j.wuttke@fz-juelich.de>
Date: Wed, 31 Aug 2022 12:26:37 +0200
Subject: [PATCH] modern validation for distributions

---
 Param/Distrib/Distributions.cpp       | 112 ++++++--
 Param/Distrib/Distributions.h         |  40 ++-
 Sample/Correlations/Profiles1D.h      |  25 +-
 Sample/Correlations/Profiles2D.cpp    |  43 ++-
 Sample/Correlations/Profiles2D.h      |  62 ++---
 auto/Wrap/doxygenParam.i              |  18 ++
 auto/Wrap/doxygenSample.i             |  43 ++-
 auto/Wrap/libBornAgainParam.py        |  48 ++++
 auto/Wrap/libBornAgainParam_wrap.cpp  | 168 ++++++++++++
 auto/Wrap/libBornAgainSample.py       | 106 +++-----
 auto/Wrap/libBornAgainSample_wrap.cpp | 366 ++++++++------------------
 11 files changed, 571 insertions(+), 460 deletions(-)

diff --git a/Param/Distrib/Distributions.cpp b/Param/Distrib/Distributions.cpp
index 29872eb7b25..2bc1994d0c9 100644
--- a/Param/Distrib/Distributions.cpp
+++ b/Param/Distrib/Distributions.cpp
@@ -15,6 +15,7 @@
 #include "Param/Distrib/Distributions.h"
 #include "Base/Math/Constants.h"
 #include "Base/Py/PyFmt.h"
+#include "Base/Util/Assert.h"
 #include "Param/Distrib/ParameterSample.h"
 #include <algorithm>
 #include <cmath>
@@ -22,9 +23,16 @@
 #include <map>
 #include <sstream>
 
+
 namespace {
 
-bool DoubleEqual(double a, double b);
+bool DoubleEqual(double a, double b)
+{
+    double eps = 10.0
+                 * std::max(std::abs(a) * std::numeric_limits<double>::epsilon(),
+                            std::numeric_limits<double>::min());
+    return std::abs(a - b) < eps;
+}
 
 } // namespace
 
@@ -122,9 +130,7 @@ DistributionGate::DistributionGate(const std::vector<double> P)
     , m_min(m_P[0])
     , m_max(m_P[1])
 {
-    checkNodeArgs();
-    if (m_max < m_min)
-        throw std::runtime_error("DistributionGate: max<min");
+    validateOrThrow();
 }
 
 DistributionGate::DistributionGate(double min, double max)
@@ -165,6 +171,14 @@ std::string DistributionGate::pythonConstructor(const std::string& units) const
     return Py::Fmt::printFunction(className(), m_min, units, m_max, units);
 }
 
+std::string DistributionGate::validate() const
+{
+    if (m_max < m_min)
+        return jointError("Profile1Voigt", {"parameters violate condition min<=max"});
+    m_validated = true;
+    return "";
+}
+
 //  ************************************************************************************************
 //  class DistributionLorentz
 //  ************************************************************************************************
@@ -174,9 +188,7 @@ DistributionLorentz::DistributionLorentz(const std::vector<double> P)
     , m_mean(m_P[0])
     , m_hwhm(m_P[1])
 {
-    checkNodeArgs();
-    if (m_hwhm < 0.0)
-        throw std::runtime_error("DistributionLorentz: hwhm<0");
+    validateOrThrow();
 }
 
 DistributionLorentz::DistributionLorentz(double mean, double hwhm)
@@ -191,6 +203,7 @@ DistributionLorentz::DistributionLorentz()
 
 double DistributionLorentz::probabilityDensity(double x) const
 {
+    ASSERT(m_validated);
     if (m_hwhm == 0.0)
         return DoubleEqual(x, m_mean) ? 1.0 : 0.0;
     return m_hwhm / (m_hwhm * m_hwhm + (x - m_mean) * (x - m_mean)) / M_PI;
@@ -199,6 +212,7 @@ double DistributionLorentz::probabilityDensity(double x) const
 std::vector<double> DistributionLorentz::equidistantPoints(size_t nbr_samples, double sigma_factor,
                                                            const RealLimits& limits) const
 {
+    ASSERT(m_validated);
     if (sigma_factor <= 0.0)
         sigma_factor = 2.0;
     double xmin = m_mean - sigma_factor * m_hwhm;
@@ -217,6 +231,17 @@ std::string DistributionLorentz::pythonConstructor(const std::string& units) con
     return Py::Fmt::printFunction(className(), m_mean, units, m_hwhm, units);
 }
 
+std::string DistributionLorentz::validate() const
+{
+    std::vector<std::string> errs;
+    requestGe0(errs, m_hwhm, "hwhm");
+    if (!errs.empty())
+        return jointError("Profile1Voigt", errs);
+    m_validated = true;
+    return "";
+}
+
+
 //  ************************************************************************************************
 //  class DistributionGaussian
 //  ************************************************************************************************
@@ -226,7 +251,7 @@ DistributionGaussian::DistributionGaussian(const std::vector<double> P)
     , m_mean(m_P[0])
     , m_std_dev(m_P[1])
 {
-    checkNodeArgs();
+    validateOrThrow();
     if (m_std_dev < 0.0)
         throw std::runtime_error("DistributionGaussian: std_dev < 0");
 }
@@ -243,6 +268,7 @@ DistributionGaussian::DistributionGaussian()
 
 double DistributionGaussian::probabilityDensity(double x) const
 {
+    ASSERT(m_validated);
     if (m_std_dev == 0.0)
         return DoubleEqual(x, m_mean) ? 1.0 : 0.0;
     double exponential = std::exp(-(x - m_mean) * (x - m_mean) / (2.0 * m_std_dev * m_std_dev));
@@ -252,6 +278,7 @@ double DistributionGaussian::probabilityDensity(double x) const
 std::vector<double> DistributionGaussian::equidistantPoints(size_t nbr_samples, double sigma_factor,
                                                             const RealLimits& limits) const
 {
+    ASSERT(m_validated);
     if (sigma_factor <= 0.0)
         sigma_factor = 2.0;
     double xmin = m_mean - sigma_factor * m_std_dev;
@@ -270,6 +297,16 @@ std::string DistributionGaussian::pythonConstructor(const std::string& units) co
     return Py::Fmt::printFunction(className(), m_mean, units, m_std_dev, units);
 }
 
+std::string DistributionGaussian::validate() const
+{
+    std::vector<std::string> errs;
+    requestGe0(errs, m_std_dev, "stdv");
+    if (!errs.empty())
+        return jointError("Profile1Voigt", errs);
+    m_validated = true;
+    return "";
+}
+
 //  ************************************************************************************************
 //  class DistributionLogNormal
 //  ************************************************************************************************
@@ -279,11 +316,7 @@ DistributionLogNormal::DistributionLogNormal(const std::vector<double> P)
     , m_median(m_P[0])
     , m_scale_param(m_P[1])
 {
-    checkNodeArgs();
-    if (m_scale_param < 0.0)
-        throw std::runtime_error("DistributionLogNormal: scale_param < 0");
-    if (m_median <= 0.0)
-        throw std::runtime_error("DistributionLogNormal: median < 0");
+    validateOrThrow();
 }
 
 DistributionLogNormal::DistributionLogNormal(double median, double scale_param)
@@ -293,6 +326,7 @@ DistributionLogNormal::DistributionLogNormal(double median, double scale_param)
 
 double DistributionLogNormal::probabilityDensity(double x) const
 {
+    ASSERT(m_validated);
     if (m_scale_param == 0.0)
         return DoubleEqual(x, m_median) ? 1.0 : 0.0;
     double t = std::log(x / m_median) / m_scale_param;
@@ -301,6 +335,7 @@ double DistributionLogNormal::probabilityDensity(double x) const
 
 double DistributionLogNormal::mean() const
 {
+    ASSERT(m_validated);
     double exponent = m_scale_param * m_scale_param / 2.0;
     return m_median * std::exp(exponent);
 }
@@ -309,6 +344,7 @@ std::vector<double> DistributionLogNormal::equidistantPoints(size_t nbr_samples,
                                                              double sigma_factor,
                                                              const RealLimits& limits) const
 {
+    ASSERT(m_validated);
     if (nbr_samples < 2) {
         std::vector<double> result;
         result.push_back(m_median);
@@ -333,6 +369,17 @@ std::string DistributionLogNormal::pythonConstructor(const std::string& units) c
     return Py::Fmt::printFunction(className(), m_median, units, m_scale_param, "");
 }
 
+std::string DistributionLogNormal::validate() const
+{
+    std::vector<std::string> errs;
+    requestGe0(errs, m_scale_param, "scale_param");
+    requestGt0(errs, m_median, "median");
+    if (!errs.empty())
+        return jointError("Profile1Voigt", errs);
+    m_validated = true;
+    return "";
+}
+
 //  ************************************************************************************************
 //  class DistributionCosine
 //  ************************************************************************************************
@@ -342,9 +389,7 @@ DistributionCosine::DistributionCosine(const std::vector<double> P)
     , m_mean(m_P[0])
     , m_sigma(m_P[1])
 {
-    checkNodeArgs();
-    if (m_sigma < 0.0)
-        throw std::runtime_error("DistributionCosine: sigma<0");
+    validateOrThrow();
 }
 
 DistributionCosine::DistributionCosine(double mean, double sigma)
@@ -359,6 +404,7 @@ DistributionCosine::DistributionCosine()
 
 double DistributionCosine::probabilityDensity(double x) const
 {
+    ASSERT(m_validated);
     if (m_sigma == 0.0)
         return DoubleEqual(x, m_mean) ? 1.0 : 0.0;
     if (std::abs(x - m_mean) > M_PI * m_sigma)
@@ -369,6 +415,7 @@ double DistributionCosine::probabilityDensity(double x) const
 std::vector<double> DistributionCosine::equidistantPoints(size_t nbr_samples, double sigma_factor,
                                                           const RealLimits& limits) const
 {
+    ASSERT(m_validated);
     if (sigma_factor <= 0.0 || sigma_factor > 2.0)
         sigma_factor = 2.0;
     double xmin = m_mean - sigma_factor * m_sigma * M_PI_2;
@@ -387,6 +434,16 @@ std::string DistributionCosine::pythonConstructor(const std::string& units) cons
     return Py::Fmt::printFunction(className(), m_mean, units, m_sigma, units);
 }
 
+std::string DistributionCosine::validate() const
+{
+    std::vector<std::string> errs;
+    requestGe0(errs, m_sigma, "sigma");
+    if (!errs.empty())
+        return jointError("Profile1Voigt", errs);
+    m_validated = true;
+    return "";
+}
+
 //  ************************************************************************************************
 //  class DistributionTrapezoidal
 //  ************************************************************************************************
@@ -398,7 +455,7 @@ DistributionTrapezoid::DistributionTrapezoid(const std::vector<double> P)
     , m_middle(m_P[2])
     , m_right(m_P[3])
 {
-    checkNodeArgs();
+    validateOrThrow();
     if (m_left < 0.0)
         throw std::runtime_error("DistributionTrapezoid: leftWidth < 0");
     if (m_middle < 0.0)
@@ -420,6 +477,7 @@ DistributionTrapezoid::DistributionTrapezoid()
 
 double DistributionTrapezoid::probabilityDensity(double x) const
 {
+    ASSERT(m_validated);
     double height = 2.0 / (m_left + 2.0 * m_middle + m_right);
     double min = m_center - m_middle / 2.0 - m_left;
     if (x < min)
@@ -436,6 +494,7 @@ double DistributionTrapezoid::probabilityDensity(double x) const
 std::vector<double> DistributionTrapezoid::equidistantPoints(size_t nbr_samples, double,
                                                              const RealLimits& limits) const
 {
+    ASSERT(m_validated);
     double xmin = m_center - m_middle / 2.0 - m_left;
     double xmax = xmin + m_left + m_middle + m_right;
     adjustLimitsToNonZeroSamples(xmin, xmax, nbr_samples);
@@ -473,14 +532,15 @@ void DistributionTrapezoid::adjustLimitsToNonZeroSamples(double& min, double& ma
         max -= step;
 }
 
-namespace {
-
-bool DoubleEqual(double a, double b)
+std::string DistributionTrapezoid::validate() const
 {
-    double eps = 10.0
-                 * std::max(std::abs(a) * std::numeric_limits<double>::epsilon(),
-                            std::numeric_limits<double>::min());
-    return std::abs(a - b) < eps;
+    std::vector<std::string> errs;
+    if (m_left>m_middle)
+        errs.push_back("parameters violate condition left<=middle");
+    if (m_middle>m_right)
+        errs.push_back("parameters violate condition middle<=right");
+    if (!errs.empty())
+        return jointError("Profile1Voigt", errs);
+    m_validated = true;
+    return "";
 }
-
-} // namespace
diff --git a/Param/Distrib/Distributions.h b/Param/Distrib/Distributions.h
index 8e23b467c95..250644fcf64 100644
--- a/Param/Distrib/Distributions.h
+++ b/Param/Distrib/Distributions.h
@@ -96,8 +96,8 @@ public:
     std::string className() const final { return "DistributionGate"; }
     std::vector<ParaMeta> parDefs() const final
     {
-        return {{"Min", "", "para_tooltip", -INF, +INF, 0},
-                {"Max", "", "para_tooltip", -INF, +INF, 0}};
+        return {{"Min", ""},
+                {"Max", ""}};
     }
 
     double probabilityDensity(double x) const override;
@@ -115,6 +115,8 @@ public:
     std::string pythonConstructor(const std::string& units) const override;
 #endif
 
+    std::string validate() const final;
+
 private:
     const double& m_min;
     const double& m_max;
@@ -137,8 +139,8 @@ public:
     std::string className() const final { return "DistributionLorentz"; }
     std::vector<ParaMeta> parDefs() const final
     {
-        return {{"Mean", "", "para_tooltip", -INF, +INF, 0},
-                {"HWHM", "", "para_tooltip", -INF, +INF, 0}};
+        return {{"Mean", ""},
+                {"HWHM", ""}};
     }
 
     double probabilityDensity(double x) const override;
@@ -155,6 +157,8 @@ public:
     std::string pythonConstructor(const std::string& units) const override;
 #endif
 
+    std::string validate() const final;
+
 private:
     const double& m_mean;
     const double& m_hwhm;
@@ -180,8 +184,8 @@ public:
     std::string className() const final { return "DistributionGaussian"; }
     std::vector<ParaMeta> parDefs() const final
     {
-        return {{"Mean", "", "para_tooltip", -INF, +INF, 0},
-                {"StdDev", "", "para_tooltip", -INF, +INF, 0}};
+        return {{"Mean", ""},
+                {"StdDev", ""}};
     }
 
     double probabilityDensity(double x) const override;
@@ -198,6 +202,8 @@ public:
     std::string pythonConstructor(const std::string& units) const override;
 #endif
 
+    std::string validate() const final;
+
 private:
     const double& m_mean;
     const double& m_std_dev;
@@ -222,8 +228,8 @@ public:
     std::string className() const final { return "DistributionLogNormal"; }
     std::vector<ParaMeta> parDefs() const final
     {
-        return {{"Median", "", "para_tooltip", -INF, +INF, 0},
-                {"ScaleParameter", "", "para_tooltip", -INF, +INF, 0}};
+        return {{"Median", ""},
+                {"ScaleParameter", ""}};
     }
 
     double probabilityDensity(double x) const override;
@@ -241,6 +247,8 @@ public:
     std::string pythonConstructor(const std::string& units) const override;
 #endif
 
+    std::string validate() const final;
+
 private:
     const double& m_median;
     const double& m_scale_param;
@@ -265,8 +273,8 @@ public:
     std::string className() const final { return "DistributionCosine"; }
     std::vector<ParaMeta> parDefs() const final
     {
-        return {{"Mean", "", "para_tooltip", -INF, +INF, 0},
-                {"Sigma", "", "para_tooltip", -INF, +INF, 0}};
+        return {{"Mean", ""},
+                {"Sigma", ""}};
     }
 
     double probabilityDensity(double x) const override;
@@ -283,6 +291,8 @@ public:
     std::string pythonConstructor(const std::string& units) const override;
 #endif
 
+    std::string validate() const final;
+
 private:
     const double& m_mean;
     const double& m_sigma;
@@ -308,10 +318,10 @@ public:
     std::string className() const final { return "DistributionTrapezoid"; }
     std::vector<ParaMeta> parDefs() const final
     {
-        return {{"Center", "", "para_tooltip", -INF, +INF, 0},
-                {"LeftWidth", "", "para_tooltip", -INF, +INF, 0},
-                {"MiddleWidth", "", "para_tooltip", -INF, +INF, 0},
-                {"RightWidth", "", "para_tooltip", -INF, +INF, 0}};
+        return {{"Center", ""},
+                {"LeftWidth", ""},
+                {"MiddleWidth", ""},
+                {"RightWidth", ""}};
     }
 
     double probabilityDensity(double x) const override;
@@ -330,6 +340,8 @@ public:
     std::string pythonConstructor(const std::string& units) const override;
 #endif
 
+    std::string validate() const final;
+
 private:
     void adjustLimitsToNonZeroSamples(double& min, double& max, size_t nbr_samples) const;
     const double& m_center;
diff --git a/Sample/Correlations/Profiles1D.h b/Sample/Correlations/Profiles1D.h
index 1590d27cac4..99e05fa1026 100644
--- a/Sample/Correlations/Profiles1D.h
+++ b/Sample/Correlations/Profiles1D.h
@@ -32,6 +32,11 @@ public:
 
     IProfile1D* clone() const override = 0;
 
+    std::vector<ParaMeta> parDefs() const override
+    {
+        return {{"Omega", "nm"}};
+    }
+
     //! Returns Fourier transform of the normalized distribution;
     //! is a decay function starting at standardizedFT(0)=1.
     virtual double standardizedFT(double q) const = 0;
@@ -69,10 +74,6 @@ public:
 
     Profile1DCauchy* clone() const override;
     std::string className() const final { return "Profile1DCauchy"; }
-    std::vector<ParaMeta> parDefs() const final
-    {
-        return {{"Omega", "nm"}};
-    }
     double standardizedFT(double q) const override;
     double decayFT(double q) const override;
     double qSecondDerivative() const override;
@@ -92,10 +93,6 @@ public:
 
     Profile1DGauss* clone() const override;
     std::string className() const final { return "Profile1DGauss"; }
-    std::vector<ParaMeta> parDefs() const final
-    {
-        return {{"Omega", "nm"}};
-    }
     double standardizedFT(double q) const override;
     double decayFT(double q) const override;
     double qSecondDerivative() const override;
@@ -115,10 +112,6 @@ public:
 
     Profile1DGate* clone() const override;
     std::string className() const final { return "Profile1DGate"; }
-    std::vector<ParaMeta> parDefs() const final
-    {
-        return {{"Omega", "nm"}};
-    }
     double standardizedFT(double q) const override;
     double decayFT(double q) const override;
     double qSecondDerivative() const override;
@@ -139,10 +132,6 @@ public:
 
     Profile1DTriangle* clone() const override;
     std::string className() const final { return "Profile1DTriangle"; }
-    std::vector<ParaMeta> parDefs() const final
-    {
-        return {{"Omega", "nm"}};
-    }
     double standardizedFT(double q) const override;
     double decayFT(double q) const override;
     double qSecondDerivative() const override;
@@ -163,10 +152,6 @@ public:
 
     Profile1DCosine* clone() const override;
     std::string className() const final { return "Profile1DCosine"; }
-    std::vector<ParaMeta> parDefs() const final
-    {
-        return {{"Omega", "nm"}};
-    }
     double standardizedFT(double q) const override;
     double decayFT(double q) const override;
     double qSecondDerivative() const override;
diff --git a/Sample/Correlations/Profiles2D.cpp b/Sample/Correlations/Profiles2D.cpp
index b78d1305827..3508d5d1260 100644
--- a/Sample/Correlations/Profiles2D.cpp
+++ b/Sample/Correlations/Profiles2D.cpp
@@ -40,9 +40,21 @@ std::string IProfile2D::pythonConstructor() const
 
 double IProfile2D::sumsq(double qx, double qy) const
 {
+    ASSERT(m_validated);
     return qx * qx * m_omega_x * m_omega_x + qy * qy * m_omega_y * m_omega_y;
 }
 
+std::string IProfile2D::validate() const
+{
+    std::vector<std::string> errs;
+    requestGt0(errs, m_omega_x, "omega_x");
+    requestGt0(errs, m_omega_y, "omega_y");
+    if (!errs.empty())
+        return jointError("Profile1Voigt", errs);
+    m_validated = true;
+    return "";
+}
+
 //  ************************************************************************************************
 //  class Profile2DCauchy
 //  ************************************************************************************************
@@ -50,7 +62,7 @@ double IProfile2D::sumsq(double qx, double qy) const
 Profile2DCauchy::Profile2DCauchy(const std::vector<double> P)
     : IProfile2D(P)
 {
-    checkNodeArgs();
+    validateOrThrow();
 }
 
 Profile2DCauchy::Profile2DCauchy(double omega_x, double omega_y, double gamma)
@@ -65,11 +77,13 @@ Profile2DCauchy* Profile2DCauchy::clone() const
 
 double Profile2DCauchy::standardizedFT2D(double qx, double qy) const
 {
+    ASSERT(m_validated);
     return std::pow(1.0 + sumsq(qx, qy), -1.5);
 }
 
 double Profile2DCauchy::decayFT2D(double qx, double qy) const
 {
+    ASSERT(m_validated);
     double sum_sq = qx * qx * m_omega_x * m_omega_x + qy * qy * m_omega_y * m_omega_y;
     return M_TWOPI * m_omega_x * m_omega_y * std::pow(1.0 + sum_sq, -1.5);
 }
@@ -86,7 +100,7 @@ std::unique_ptr<IDistribution2DSampler> Profile2DCauchy::createSampler() const
 Profile2DGauss::Profile2DGauss(const std::vector<double> P)
     : IProfile2D(P)
 {
-    checkNodeArgs();
+    validateOrThrow();
 }
 
 Profile2DGauss::Profile2DGauss(double omega_x, double omega_y, double gamma)
@@ -101,11 +115,13 @@ Profile2DGauss* Profile2DGauss::clone() const
 
 double Profile2DGauss::standardizedFT2D(double qx, double qy) const
 {
+    ASSERT(m_validated);
     return std::exp(-sumsq(qx, qy) / 2);
 }
 
 double Profile2DGauss::decayFT2D(double qx, double qy) const
 {
+    ASSERT(m_validated);
     double sum_sq = qx * qx * m_omega_x * m_omega_x + qy * qy * m_omega_y * m_omega_y;
     return M_TWOPI * m_omega_x * m_omega_y * std::exp(-sum_sq / 2.0);
 }
@@ -122,7 +138,7 @@ std::unique_ptr<IDistribution2DSampler> Profile2DGauss::createSampler() const
 Profile2DGate::Profile2DGate(const std::vector<double> P)
     : IProfile2D(P)
 {
-    checkNodeArgs();
+    validateOrThrow();
 }
 
 Profile2DGate::Profile2DGate(double omega_x, double omega_y, double gamma)
@@ -137,6 +153,7 @@ Profile2DGate* Profile2DGate::clone() const
 
 double Profile2DGate::standardizedFT2D(double qx, double qy) const
 {
+    ASSERT(m_validated);
     double scaled_q = std::sqrt(sumsq(qx, qy));
     return Math::Bessel::J1c(scaled_q) * 2.0;
 }
@@ -158,7 +175,7 @@ std::unique_ptr<IDistribution2DSampler> Profile2DGate::createSampler() const
 Profile2DCone::Profile2DCone(const std::vector<double> P)
     : IProfile2D(P)
 {
-    checkNodeArgs();
+    validateOrThrow();
 }
 
 Profile2DCone::Profile2DCone(double omega_x, double omega_y, double gamma)
@@ -173,6 +190,7 @@ Profile2DCone* Profile2DCone::clone() const
 
 double Profile2DCone::standardizedFT2D(double qx, double qy) const
 {
+    ASSERT(m_validated);
     double scaled_q = std::sqrt(sumsq(qx, qy));
     if (scaled_q < std::numeric_limits<double>::epsilon())
         return 1.0 - 3.0 * scaled_q * scaled_q / 40.0;
@@ -200,7 +218,7 @@ Profile2DVoigt::Profile2DVoigt(const std::vector<double> P)
     : IProfile2D(P)
     , m_eta(m_P[3])
 {
-    checkNodeArgs();
+    validateOrThrow();
 }
 
 Profile2DVoigt::Profile2DVoigt(double omega_x, double omega_y, double gamma, double eta)
@@ -215,12 +233,14 @@ Profile2DVoigt* Profile2DVoigt::clone() const
 
 double Profile2DVoigt::standardizedFT2D(double qx, double qy) const
 {
+    ASSERT(m_validated);
     double sum_sq = sumsq(qx, qy);
     return m_eta * std::exp(-sum_sq / 2) + (1.0 - m_eta) * std::pow(1.0 + sum_sq, -1.5);
 }
 
 double Profile2DVoigt::decayFT2D(double qx, double qy) const
 {
+    ASSERT(m_validated);
     double sum_sq = qx * qx * m_omega_x * m_omega_x + qy * qy * m_omega_y * m_omega_y;
     return M_TWOPI * m_omega_x * m_omega_y
            * (m_eta * std::exp(-sum_sq / 2.0) + (1.0 - m_eta) * std::pow(1.0 + sum_sq, -1.5));
@@ -242,3 +262,16 @@ std::string Profile2DVoigt::pythonConstructor() const
     return Py::Fmt::printFunction(
         className(), {{m_omega_x, "nm"}, {m_omega_y, "nm"}, {m_gamma, "rad"}, {m_eta, ""}});
 }
+
+std::string Profile2DVoigt::validate() const
+{
+    std::vector<std::string> errs;
+    requestGt0(errs, m_omega_x, "omega_x");
+    requestGt0(errs, m_omega_y, "omega_y");
+    if (m_eta<0 || m_eta>1)
+        errs.push_back("eta="+std::to_string(m_eta)+" outside interval 0..1");
+    if (!errs.empty())
+        return jointError("Profile1Voigt", errs);
+    m_validated = true;
+    return "";
+}
diff --git a/Sample/Correlations/Profiles2D.h b/Sample/Correlations/Profiles2D.h
index c9f698a05fb..3bc98ac0492 100644
--- a/Sample/Correlations/Profiles2D.h
+++ b/Sample/Correlations/Profiles2D.h
@@ -32,6 +32,13 @@ public:
 
     IProfile2D* clone() const override = 0;
 
+    std::vector<ParaMeta> parDefs() const override
+    {
+        return {{"OmegaX", "nm"},
+                {"OmegaY", "nm"},
+                {"Gamma", "rad"}};
+    }
+
     double omegaX() const { return m_omega_x; }
     double omegaY() const { return m_omega_y; }
     double decayLengthX() const { return m_omega_x; }
@@ -53,12 +60,14 @@ public:
     virtual std::string pythonConstructor() const;
 #endif
 
+    std::string validate() const override;
+
 protected:
     double sumsq(double qx, double qy) const;
 
-    const double& m_omega_x;
-    const double& m_omega_y;
-    const double& m_gamma;
+    const double& m_omega_x; //!< Half-width along x axis
+    const double& m_omega_y; //!< Half-width along y axis
+    const double& m_gamma; //!< direct-space orientation with respect to the first lattice vector
 };
 
 #endif // USER_API
@@ -75,14 +84,6 @@ public:
 
     Profile2DCauchy* clone() const override;
     std::string className() const final { return "Profile2DCauchy"; }
-    std::vector<ParaMeta> parDefs() const final
-    {
-        return {{"OmegaX", "nm", "Half-width along x axis", 0, INF, 1.},
-                {"OmegaY", "nm", "Half-width along y axis", 0, INF, 1.},
-                {"Gamma", "rad",
-                 "direct-space orientation with respect to the first lattice vector", -M_PI_2,
-                 +M_PI_2, 0}};
-    }
     double standardizedFT2D(double qx, double qy) const override;
     double decayFT2D(double qx, double qy) const override;
 #ifndef SWIG
@@ -102,14 +103,6 @@ public:
 
     Profile2DGauss* clone() const override;
     std::string className() const final { return "Profile2DGauss"; }
-    std::vector<ParaMeta> parDefs() const final
-    {
-        return {{"OmegaX", "nm", "Half-width along x axis", 0, INF, 1.},
-                {"OmegaY", "nm", "Half-width along y axis", 0, INF, 1.},
-                {"Gamma", "rad",
-                 "direct-space orientation with respect to the first lattice vector", -M_PI_2,
-                 +M_PI_2, 0}};
-    }
     double standardizedFT2D(double qx, double qy) const override;
     double decayFT2D(double qx, double qy) const override;
 #ifndef SWIG
@@ -129,14 +122,6 @@ public:
 
     Profile2DGate* clone() const override;
     std::string className() const final { return "Profile2DGate"; }
-    std::vector<ParaMeta> parDefs() const final
-    {
-        return {{"OmegaX", "nm", "Half-width along x axis", 0, INF, 1.},
-                {"OmegaY", "nm", "Half-width along y axis", 0, INF, 1.},
-                {"Gamma", "rad",
-                 "direct-space orientation with respect to the first lattice vector", -M_PI_2,
-                 +M_PI_2, 0}};
-    }
     double standardizedFT2D(double qx, double qy) const override;
     double decayFT2D(double qx, double qy) const override;
 #ifndef SWIG
@@ -156,14 +141,6 @@ public:
 
     Profile2DCone* clone() const override;
     std::string className() const final { return "Profile2DCone"; }
-    std::vector<ParaMeta> parDefs() const final
-    {
-        return {{"OmegaX", "nm", "Half-width along x axis", 0, INF, 1.},
-                {"OmegaY", "nm", "Half-width along y axis", 0, INF, 1.},
-                {"Gamma", "rad",
-                 "direct-space orientation with respect to the first lattice vector", -M_PI_2,
-                 +M_PI_2, 0}};
-    }
     double standardizedFT2D(double qx, double qy) const override;
     double decayFT2D(double qx, double qy) const override;
 #ifndef SWIG
@@ -184,22 +161,21 @@ public:
     std::string className() const final { return "Profile2DVoigt"; }
     std::vector<ParaMeta> parDefs() const final
     {
-        return {{"OmegaX", "nm", "Half-width along x axis", 0, INF, 1.},
-                {"OmegaY", "nm", "Half-width along y axis", 0, INF, 1.},
-                {"Gamma", "rad",
-                 "direct-space orientation with respect to the first lattice vector", -M_PI_2,
-                 +M_PI_2, 0},
-                {"Eta", "", "balances between Gauss (eta=0) and Lorentz (eta=1) limiting cases", 0,
-                 1, .5}};
+        return {{"OmegaX", "nm"},
+                {"OmegaY", "nm"},
+                {"Gamma", "rad"},
+                {"Eta", ""}};
     }
     double standardizedFT2D(double qx, double qy) const override;
     double decayFT2D(double qx, double qy) const override;
-    double eta() const { return m_eta; }
+    double eta() const { return m_eta; } //!< balances between Gauss (eta=0) and Lorentz (eta=1)
 #ifndef SWIG
     std::unique_ptr<IDistribution2DSampler> createSampler() const override;
     std::string pythonConstructor() const override;
 #endif
 
+    std::string validate() const final;
+
 protected:
     const double& m_eta;
 };
diff --git a/auto/Wrap/doxygenParam.i b/auto/Wrap/doxygenParam.i
index ddec5e65f76..217cc8224a7 100644
--- a/auto/Wrap/doxygenParam.i
+++ b/auto/Wrap/doxygenParam.i
@@ -59,6 +59,9 @@ DistributionCosine::pythonConstructor
 Prints distribution with constructor parameters in given units. ba.DistributionGaussian(2.0*deg, 0.02*deg) 
 ";
 
+%feature("docstring")  DistributionCosine::validate "std::string DistributionCosine::validate() const final
+DistributionCosine::validate";
+
 
 // File: classDistributionGate.xml
 %feature("docstring") DistributionGate "
@@ -121,6 +124,9 @@ DistributionGate::pythonConstructor
 Prints distribution with constructor parameters in given units. ba.DistributionGaussian(2.0*deg, 0.02*deg) 
 ";
 
+%feature("docstring")  DistributionGate::validate "std::string DistributionGate::validate() const final
+DistributionGate::validate";
+
 
 // File: classDistributionGaussian.xml
 %feature("docstring") DistributionGaussian "
@@ -180,6 +186,9 @@ DistributionGaussian::pythonConstructor
 Prints distribution with constructor parameters in given units. ba.DistributionGaussian(2.0*deg, 0.02*deg) 
 ";
 
+%feature("docstring")  DistributionGaussian::validate "std::string DistributionGaussian::validate() const final
+DistributionGaussian::validate";
+
 
 // File: classDistributionHandler.xml
 %feature("docstring") DistributionHandler "
@@ -273,6 +282,9 @@ DistributionLogNormal::pythonConstructor
 Prints distribution with constructor parameters in given units. ba.DistributionGaussian(2.0*deg, 0.02*deg) 
 ";
 
+%feature("docstring")  DistributionLogNormal::validate "std::string DistributionLogNormal::validate() const final
+DistributionLogNormal::validate";
+
 
 // File: classDistributionLorentz.xml
 %feature("docstring") DistributionLorentz "
@@ -332,6 +344,9 @@ DistributionLorentz::pythonConstructor
 Prints distribution with constructor parameters in given units. ba.DistributionGaussian(2.0*deg, 0.02*deg) 
 ";
 
+%feature("docstring")  DistributionLorentz::validate "std::string DistributionLorentz::validate() const final
+DistributionLorentz::validate";
+
 
 // File: classDistributionTrapezoid.xml
 %feature("docstring") DistributionTrapezoid "
@@ -397,6 +412,9 @@ DistributionTrapezoid::pythonConstructor
 Prints distribution with constructor parameters in given units. ba.DistributionGaussian(2.0*deg, 0.02*deg) 
 ";
 
+%feature("docstring")  DistributionTrapezoid::validate "std::string DistributionTrapezoid::validate() const final
+DistributionTrapezoid::validate";
+
 
 // File: classIDistribution1D.xml
 %feature("docstring") IDistribution1D "
diff --git a/auto/Wrap/doxygenSample.i b/auto/Wrap/doxygenSample.i
index 0ce45c00ea5..9b89529f379 100644
--- a/auto/Wrap/doxygenSample.i
+++ b/auto/Wrap/doxygenSample.i
@@ -2029,6 +2029,9 @@ IProfile1D::IProfile1D";
 %feature("docstring")  IProfile1D::clone "IProfile1D * IProfile1D::clone() const override=0
 IProfile1D::clone";
 
+%feature("docstring")  IProfile1D::parDefs "std::vector< ParaMeta > IProfile1D::parDefs() const override
+IProfile1D::parDefs";
+
 %feature("docstring")  IProfile1D::standardizedFT "virtual double IProfile1D::standardizedFT(double q) const =0
 IProfile1D::standardizedFT
 Returns Fourier transform of the normalized distribution; is a decay function starting at standardizedFT(0)=1. 
@@ -2076,6 +2079,9 @@ IProfile2D::IProfile2D";
 %feature("docstring")  IProfile2D::clone "IProfile2D * IProfile2D::clone() const override=0
 IProfile2D::clone";
 
+%feature("docstring")  IProfile2D::parDefs "std::vector< ParaMeta > IProfile2D::parDefs() const override
+IProfile2D::parDefs";
+
 %feature("docstring")  IProfile2D::omegaX "double IProfile2D::omegaX() const
 IProfile2D::omegaX";
 
@@ -2112,6 +2118,9 @@ IProfile2D::pythonConstructor
 Creates the Python constructor of this class (or derived classes) 
 ";
 
+%feature("docstring")  IProfile2D::validate "std::string IProfile2D::validate() const override
+IProfile2D::validate";
+
 
 // File: classIProfileRectangularRipple.xml
 %feature("docstring") IProfileRectangularRipple "
@@ -3558,9 +3567,6 @@ Profile1DCauchy::clone";
 %feature("docstring")  Profile1DCauchy::className "std::string Profile1DCauchy::className() const final
 Profile1DCauchy::className";
 
-%feature("docstring")  Profile1DCauchy::parDefs "std::vector< ParaMeta > Profile1DCauchy::parDefs() const final
-Profile1DCauchy::parDefs";
-
 %feature("docstring")  Profile1DCauchy::standardizedFT "double Profile1DCauchy::standardizedFT(double q) const override
 Profile1DCauchy::standardizedFT
 Returns Fourier transform of the normalized distribution; is a decay function starting at standardizedFT(0)=1. 
@@ -3600,9 +3606,6 @@ Profile1DCosine::clone";
 %feature("docstring")  Profile1DCosine::className "std::string Profile1DCosine::className() const final
 Profile1DCosine::className";
 
-%feature("docstring")  Profile1DCosine::parDefs "std::vector< ParaMeta > Profile1DCosine::parDefs() const final
-Profile1DCosine::parDefs";
-
 %feature("docstring")  Profile1DCosine::standardizedFT "double Profile1DCosine::standardizedFT(double q) const override
 Profile1DCosine::standardizedFT
 Returns Fourier transform of the normalized distribution; is a decay function starting at standardizedFT(0)=1. 
@@ -3642,9 +3645,6 @@ Profile1DGate::clone";
 %feature("docstring")  Profile1DGate::className "std::string Profile1DGate::className() const final
 Profile1DGate::className";
 
-%feature("docstring")  Profile1DGate::parDefs "std::vector< ParaMeta > Profile1DGate::parDefs() const final
-Profile1DGate::parDefs";
-
 %feature("docstring")  Profile1DGate::standardizedFT "double Profile1DGate::standardizedFT(double q) const override
 Profile1DGate::standardizedFT
 Returns Fourier transform of the normalized distribution; is a decay function starting at standardizedFT(0)=1. 
@@ -3684,9 +3684,6 @@ Profile1DGauss::clone";
 %feature("docstring")  Profile1DGauss::className "std::string Profile1DGauss::className() const final
 Profile1DGauss::className";
 
-%feature("docstring")  Profile1DGauss::parDefs "std::vector< ParaMeta > Profile1DGauss::parDefs() const final
-Profile1DGauss::parDefs";
-
 %feature("docstring")  Profile1DGauss::standardizedFT "double Profile1DGauss::standardizedFT(double q) const override
 Profile1DGauss::standardizedFT
 Returns Fourier transform of the normalized distribution; is a decay function starting at standardizedFT(0)=1. 
@@ -3726,9 +3723,6 @@ Profile1DTriangle::clone";
 %feature("docstring")  Profile1DTriangle::className "std::string Profile1DTriangle::className() const final
 Profile1DTriangle::className";
 
-%feature("docstring")  Profile1DTriangle::parDefs "std::vector< ParaMeta > Profile1DTriangle::parDefs() const final
-Profile1DTriangle::parDefs";
-
 %feature("docstring")  Profile1DTriangle::standardizedFT "double Profile1DTriangle::standardizedFT(double q) const override
 Profile1DTriangle::standardizedFT
 Returns Fourier transform of the normalized distribution; is a decay function starting at standardizedFT(0)=1. 
@@ -3821,9 +3815,6 @@ Profile2DCauchy::clone";
 %feature("docstring")  Profile2DCauchy::className "std::string Profile2DCauchy::className() const final
 Profile2DCauchy::className";
 
-%feature("docstring")  Profile2DCauchy::parDefs "std::vector< ParaMeta > Profile2DCauchy::parDefs() const final
-Profile2DCauchy::parDefs";
-
 %feature("docstring")  Profile2DCauchy::standardizedFT2D "double Profile2DCauchy::standardizedFT2D(double qx, double qy) const override
 Profile2DCauchy::standardizedFT2D
 Fourier transformed distribution for q in X,Y coordinates the original distribution (in real space) is assumed to be normalized: total integral is equal to 1 
@@ -3868,9 +3859,6 @@ Profile2DCone::clone";
 %feature("docstring")  Profile2DCone::className "std::string Profile2DCone::className() const final
 Profile2DCone::className";
 
-%feature("docstring")  Profile2DCone::parDefs "std::vector< ParaMeta > Profile2DCone::parDefs() const final
-Profile2DCone::parDefs";
-
 %feature("docstring")  Profile2DCone::standardizedFT2D "double Profile2DCone::standardizedFT2D(double qx, double qy) const override
 Profile2DCone::standardizedFT2D
 Fourier transformed distribution for q in X,Y coordinates the original distribution (in real space) is assumed to be normalized: total integral is equal to 1 
@@ -3903,9 +3891,6 @@ Profile2DGate::clone";
 %feature("docstring")  Profile2DGate::className "std::string Profile2DGate::className() const final
 Profile2DGate::className";
 
-%feature("docstring")  Profile2DGate::parDefs "std::vector< ParaMeta > Profile2DGate::parDefs() const final
-Profile2DGate::parDefs";
-
 %feature("docstring")  Profile2DGate::standardizedFT2D "double Profile2DGate::standardizedFT2D(double qx, double qy) const override
 Profile2DGate::standardizedFT2D
 Fourier transformed distribution for q in X,Y coordinates the original distribution (in real space) is assumed to be normalized: total integral is equal to 1 
@@ -3938,9 +3923,6 @@ Profile2DGauss::clone";
 %feature("docstring")  Profile2DGauss::className "std::string Profile2DGauss::className() const final
 Profile2DGauss::className";
 
-%feature("docstring")  Profile2DGauss::parDefs "std::vector< ParaMeta > Profile2DGauss::parDefs() const final
-Profile2DGauss::parDefs";
-
 %feature("docstring")  Profile2DGauss::standardizedFT2D "double Profile2DGauss::standardizedFT2D(double qx, double qy) const override
 Profile2DGauss::standardizedFT2D
 Fourier transformed distribution for q in X,Y coordinates the original distribution (in real space) is assumed to be normalized: total integral is equal to 1 
@@ -3985,7 +3967,9 @@ Fourier transformed distribution for q in X,Y coordinates the original distribut
 Profile2DVoigt::decayFT2D";
 
 %feature("docstring")  Profile2DVoigt::eta "double Profile2DVoigt::eta() const
-Profile2DVoigt::eta";
+Profile2DVoigt::eta
+balances between Gauss (eta=0) and Lorentz (eta=1) 
+";
 
 %feature("docstring")  Profile2DVoigt::createSampler "std::unique_ptr< IDistribution2DSampler > Profile2DVoigt::createSampler() const override
 Profile2DVoigt::createSampler";
@@ -3995,6 +3979,9 @@ Profile2DVoigt::pythonConstructor
 Creates the Python constructor of this class (or derived classes) 
 ";
 
+%feature("docstring")  Profile2DVoigt::validate "std::string Profile2DVoigt::validate() const final
+Profile2DVoigt::validate";
+
 
 // File: classPyramid2.xml
 %feature("docstring") Pyramid2 "
diff --git a/auto/Wrap/libBornAgainParam.py b/auto/Wrap/libBornAgainParam.py
index 312656642dc..b695ac026fd 100644
--- a/auto/Wrap/libBornAgainParam.py
+++ b/auto/Wrap/libBornAgainParam.py
@@ -2381,6 +2381,14 @@ class DistributionGate(IDistribution1D):
 
         """
         return _libBornAgainParam.DistributionGate_isDelta(self)
+
+    def validate(self):
+        r"""
+        validate(DistributionGate self) -> std::string
+        std::string DistributionGate::validate() const final
+        DistributionGate::validate
+        """
+        return _libBornAgainParam.DistributionGate_validate(self)
     __swig_destroy__ = _libBornAgainParam.delete_DistributionGate
 
 # Register DistributionGate in _libBornAgainParam:
@@ -2484,6 +2492,14 @@ class DistributionLorentz(IDistribution1D):
 
         """
         return _libBornAgainParam.DistributionLorentz_isDelta(self)
+
+    def validate(self):
+        r"""
+        validate(DistributionLorentz self) -> std::string
+        std::string DistributionLorentz::validate() const final
+        DistributionLorentz::validate
+        """
+        return _libBornAgainParam.DistributionLorentz_validate(self)
     __swig_destroy__ = _libBornAgainParam.delete_DistributionLorentz
 
 # Register DistributionLorentz in _libBornAgainParam:
@@ -2587,6 +2603,14 @@ class DistributionGaussian(IDistribution1D):
 
         """
         return _libBornAgainParam.DistributionGaussian_isDelta(self)
+
+    def validate(self):
+        r"""
+        validate(DistributionGaussian self) -> std::string
+        std::string DistributionGaussian::validate() const final
+        DistributionGaussian::validate
+        """
+        return _libBornAgainParam.DistributionGaussian_validate(self)
     __swig_destroy__ = _libBornAgainParam.delete_DistributionGaussian
 
 # Register DistributionGaussian in _libBornAgainParam:
@@ -2697,6 +2721,14 @@ class DistributionLogNormal(IDistribution1D):
 
         """
         return _libBornAgainParam.DistributionLogNormal_isDelta(self)
+
+    def validate(self):
+        r"""
+        validate(DistributionLogNormal self) -> std::string
+        std::string DistributionLogNormal::validate() const final
+        DistributionLogNormal::validate
+        """
+        return _libBornAgainParam.DistributionLogNormal_validate(self)
     __swig_destroy__ = _libBornAgainParam.delete_DistributionLogNormal
 
 # Register DistributionLogNormal in _libBornAgainParam:
@@ -2800,6 +2832,14 @@ class DistributionCosine(IDistribution1D):
 
         """
         return _libBornAgainParam.DistributionCosine_isDelta(self)
+
+    def validate(self):
+        r"""
+        validate(DistributionCosine self) -> std::string
+        std::string DistributionCosine::validate() const final
+        DistributionCosine::validate
+        """
+        return _libBornAgainParam.DistributionCosine_validate(self)
     __swig_destroy__ = _libBornAgainParam.delete_DistributionCosine
 
 # Register DistributionCosine in _libBornAgainParam:
@@ -2919,6 +2959,14 @@ class DistributionTrapezoid(IDistribution1D):
 
         """
         return _libBornAgainParam.DistributionTrapezoid_isDelta(self)
+
+    def validate(self):
+        r"""
+        validate(DistributionTrapezoid self) -> std::string
+        std::string DistributionTrapezoid::validate() const final
+        DistributionTrapezoid::validate
+        """
+        return _libBornAgainParam.DistributionTrapezoid_validate(self)
     __swig_destroy__ = _libBornAgainParam.delete_DistributionTrapezoid
 
 # Register DistributionTrapezoid in _libBornAgainParam:
diff --git a/auto/Wrap/libBornAgainParam_wrap.cpp b/auto/Wrap/libBornAgainParam_wrap.cpp
index 20752e756b6..758b1a2777f 100644
--- a/auto/Wrap/libBornAgainParam_wrap.cpp
+++ b/auto/Wrap/libBornAgainParam_wrap.cpp
@@ -29509,6 +29509,29 @@ fail:
 }
 
 
+SWIGINTERN PyObject *_wrap_DistributionGate_validate(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *resultobj = 0;
+  DistributionGate *arg1 = (DistributionGate *) 0 ;
+  void *argp1 = 0 ;
+  int res1 = 0 ;
+  PyObject *swig_obj[1] ;
+  std::string result;
+  
+  if (!args) SWIG_fail;
+  swig_obj[0] = args;
+  res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_DistributionGate, 0 |  0 );
+  if (!SWIG_IsOK(res1)) {
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "DistributionGate_validate" "', argument " "1"" of type '" "DistributionGate const *""'"); 
+  }
+  arg1 = reinterpret_cast< DistributionGate * >(argp1);
+  result = ((DistributionGate const *)arg1)->validate();
+  resultobj = SWIG_From_std_string(static_cast< std::string >(result));
+  return resultobj;
+fail:
+  return NULL;
+}
+
+
 SWIGINTERN PyObject *_wrap_delete_DistributionGate(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
   PyObject *resultobj = 0;
   DistributionGate *arg1 = (DistributionGate *) 0 ;
@@ -29970,6 +29993,29 @@ fail:
 }
 
 
+SWIGINTERN PyObject *_wrap_DistributionLorentz_validate(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *resultobj = 0;
+  DistributionLorentz *arg1 = (DistributionLorentz *) 0 ;
+  void *argp1 = 0 ;
+  int res1 = 0 ;
+  PyObject *swig_obj[1] ;
+  std::string result;
+  
+  if (!args) SWIG_fail;
+  swig_obj[0] = args;
+  res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_DistributionLorentz, 0 |  0 );
+  if (!SWIG_IsOK(res1)) {
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "DistributionLorentz_validate" "', argument " "1"" of type '" "DistributionLorentz const *""'"); 
+  }
+  arg1 = reinterpret_cast< DistributionLorentz * >(argp1);
+  result = ((DistributionLorentz const *)arg1)->validate();
+  resultobj = SWIG_From_std_string(static_cast< std::string >(result));
+  return resultobj;
+fail:
+  return NULL;
+}
+
+
 SWIGINTERN PyObject *_wrap_delete_DistributionLorentz(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
   PyObject *resultobj = 0;
   DistributionLorentz *arg1 = (DistributionLorentz *) 0 ;
@@ -30431,6 +30477,29 @@ fail:
 }
 
 
+SWIGINTERN PyObject *_wrap_DistributionGaussian_validate(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *resultobj = 0;
+  DistributionGaussian *arg1 = (DistributionGaussian *) 0 ;
+  void *argp1 = 0 ;
+  int res1 = 0 ;
+  PyObject *swig_obj[1] ;
+  std::string result;
+  
+  if (!args) SWIG_fail;
+  swig_obj[0] = args;
+  res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_DistributionGaussian, 0 |  0 );
+  if (!SWIG_IsOK(res1)) {
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "DistributionGaussian_validate" "', argument " "1"" of type '" "DistributionGaussian const *""'"); 
+  }
+  arg1 = reinterpret_cast< DistributionGaussian * >(argp1);
+  result = ((DistributionGaussian const *)arg1)->validate();
+  resultobj = SWIG_From_std_string(static_cast< std::string >(result));
+  return resultobj;
+fail:
+  return NULL;
+}
+
+
 SWIGINTERN PyObject *_wrap_delete_DistributionGaussian(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
   PyObject *resultobj = 0;
   DistributionGaussian *arg1 = (DistributionGaussian *) 0 ;
@@ -30898,6 +30967,29 @@ fail:
 }
 
 
+SWIGINTERN PyObject *_wrap_DistributionLogNormal_validate(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *resultobj = 0;
+  DistributionLogNormal *arg1 = (DistributionLogNormal *) 0 ;
+  void *argp1 = 0 ;
+  int res1 = 0 ;
+  PyObject *swig_obj[1] ;
+  std::string result;
+  
+  if (!args) SWIG_fail;
+  swig_obj[0] = args;
+  res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_DistributionLogNormal, 0 |  0 );
+  if (!SWIG_IsOK(res1)) {
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "DistributionLogNormal_validate" "', argument " "1"" of type '" "DistributionLogNormal const *""'"); 
+  }
+  arg1 = reinterpret_cast< DistributionLogNormal * >(argp1);
+  result = ((DistributionLogNormal const *)arg1)->validate();
+  resultobj = SWIG_From_std_string(static_cast< std::string >(result));
+  return resultobj;
+fail:
+  return NULL;
+}
+
+
 SWIGINTERN PyObject *_wrap_delete_DistributionLogNormal(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
   PyObject *resultobj = 0;
   DistributionLogNormal *arg1 = (DistributionLogNormal *) 0 ;
@@ -31359,6 +31451,29 @@ fail:
 }
 
 
+SWIGINTERN PyObject *_wrap_DistributionCosine_validate(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *resultobj = 0;
+  DistributionCosine *arg1 = (DistributionCosine *) 0 ;
+  void *argp1 = 0 ;
+  int res1 = 0 ;
+  PyObject *swig_obj[1] ;
+  std::string result;
+  
+  if (!args) SWIG_fail;
+  swig_obj[0] = args;
+  res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_DistributionCosine, 0 |  0 );
+  if (!SWIG_IsOK(res1)) {
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "DistributionCosine_validate" "', argument " "1"" of type '" "DistributionCosine const *""'"); 
+  }
+  arg1 = reinterpret_cast< DistributionCosine * >(argp1);
+  result = ((DistributionCosine const *)arg1)->validate();
+  resultobj = SWIG_From_std_string(static_cast< std::string >(result));
+  return resultobj;
+fail:
+  return NULL;
+}
+
+
 SWIGINTERN PyObject *_wrap_delete_DistributionCosine(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
   PyObject *resultobj = 0;
   DistributionCosine *arg1 = (DistributionCosine *) 0 ;
@@ -31894,6 +32009,29 @@ fail:
 }
 
 
+SWIGINTERN PyObject *_wrap_DistributionTrapezoid_validate(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *resultobj = 0;
+  DistributionTrapezoid *arg1 = (DistributionTrapezoid *) 0 ;
+  void *argp1 = 0 ;
+  int res1 = 0 ;
+  PyObject *swig_obj[1] ;
+  std::string result;
+  
+  if (!args) SWIG_fail;
+  swig_obj[0] = args;
+  res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_DistributionTrapezoid, 0 |  0 );
+  if (!SWIG_IsOK(res1)) {
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "DistributionTrapezoid_validate" "', argument " "1"" of type '" "DistributionTrapezoid const *""'"); 
+  }
+  arg1 = reinterpret_cast< DistributionTrapezoid * >(argp1);
+  result = ((DistributionTrapezoid const *)arg1)->validate();
+  resultobj = SWIG_From_std_string(static_cast< std::string >(result));
+  return resultobj;
+fail:
+  return NULL;
+}
+
+
 SWIGINTERN PyObject *_wrap_delete_DistributionTrapezoid(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
   PyObject *resultobj = 0;
   DistributionTrapezoid *arg1 = (DistributionTrapezoid *) 0 ;
@@ -35187,6 +35325,11 @@ static PyMethodDef SwigMethods[] = {
 		"Returns true if the distribution is in the limit case of a Dirac delta distribution. \n"
 		"\n"
 		""},
+	 { "DistributionGate_validate", _wrap_DistributionGate_validate, METH_O, "\n"
+		"DistributionGate_validate(DistributionGate self) -> std::string\n"
+		"std::string DistributionGate::validate() const final\n"
+		"DistributionGate::validate\n"
+		""},
 	 { "delete_DistributionGate", _wrap_delete_DistributionGate, METH_O, "delete_DistributionGate(DistributionGate self)"},
 	 { "DistributionGate_swigregister", DistributionGate_swigregister, METH_O, NULL},
 	 { "DistributionGate_swiginit", DistributionGate_swiginit, METH_VARARGS, NULL},
@@ -35249,6 +35392,11 @@ static PyMethodDef SwigMethods[] = {
 		"Returns true if the distribution is in the limit case of a Dirac delta distribution. \n"
 		"\n"
 		""},
+	 { "DistributionLorentz_validate", _wrap_DistributionLorentz_validate, METH_O, "\n"
+		"DistributionLorentz_validate(DistributionLorentz self) -> std::string\n"
+		"std::string DistributionLorentz::validate() const final\n"
+		"DistributionLorentz::validate\n"
+		""},
 	 { "delete_DistributionLorentz", _wrap_delete_DistributionLorentz, METH_O, "delete_DistributionLorentz(DistributionLorentz self)"},
 	 { "DistributionLorentz_swigregister", DistributionLorentz_swigregister, METH_O, NULL},
 	 { "DistributionLorentz_swiginit", DistributionLorentz_swiginit, METH_VARARGS, NULL},
@@ -35311,6 +35459,11 @@ static PyMethodDef SwigMethods[] = {
 		"Returns true if the distribution is in the limit case of a Dirac delta distribution. \n"
 		"\n"
 		""},
+	 { "DistributionGaussian_validate", _wrap_DistributionGaussian_validate, METH_O, "\n"
+		"DistributionGaussian_validate(DistributionGaussian self) -> std::string\n"
+		"std::string DistributionGaussian::validate() const final\n"
+		"DistributionGaussian::validate\n"
+		""},
 	 { "delete_DistributionGaussian", _wrap_delete_DistributionGaussian, METH_O, "delete_DistributionGaussian(DistributionGaussian self)"},
 	 { "DistributionGaussian_swigregister", DistributionGaussian_swigregister, METH_O, NULL},
 	 { "DistributionGaussian_swiginit", DistributionGaussian_swiginit, METH_VARARGS, NULL},
@@ -35377,6 +35530,11 @@ static PyMethodDef SwigMethods[] = {
 		"Returns true if the distribution is in the limit case of a Dirac delta distribution. \n"
 		"\n"
 		""},
+	 { "DistributionLogNormal_validate", _wrap_DistributionLogNormal_validate, METH_O, "\n"
+		"DistributionLogNormal_validate(DistributionLogNormal self) -> std::string\n"
+		"std::string DistributionLogNormal::validate() const final\n"
+		"DistributionLogNormal::validate\n"
+		""},
 	 { "delete_DistributionLogNormal", _wrap_delete_DistributionLogNormal, METH_O, "delete_DistributionLogNormal(DistributionLogNormal self)"},
 	 { "DistributionLogNormal_swigregister", DistributionLogNormal_swigregister, METH_O, NULL},
 	 { "DistributionLogNormal_swiginit", DistributionLogNormal_swiginit, METH_VARARGS, NULL},
@@ -35439,6 +35597,11 @@ static PyMethodDef SwigMethods[] = {
 		"Returns true if the distribution is in the limit case of a Dirac delta distribution. \n"
 		"\n"
 		""},
+	 { "DistributionCosine_validate", _wrap_DistributionCosine_validate, METH_O, "\n"
+		"DistributionCosine_validate(DistributionCosine self) -> std::string\n"
+		"std::string DistributionCosine::validate() const final\n"
+		"DistributionCosine::validate\n"
+		""},
 	 { "delete_DistributionCosine", _wrap_delete_DistributionCosine, METH_O, "delete_DistributionCosine(DistributionCosine self)"},
 	 { "DistributionCosine_swigregister", DistributionCosine_swigregister, METH_O, NULL},
 	 { "DistributionCosine_swiginit", DistributionCosine_swiginit, METH_VARARGS, NULL},
@@ -35511,6 +35674,11 @@ static PyMethodDef SwigMethods[] = {
 		"Returns true if the distribution is in the limit case of a Dirac delta distribution. \n"
 		"\n"
 		""},
+	 { "DistributionTrapezoid_validate", _wrap_DistributionTrapezoid_validate, METH_O, "\n"
+		"DistributionTrapezoid_validate(DistributionTrapezoid self) -> std::string\n"
+		"std::string DistributionTrapezoid::validate() const final\n"
+		"DistributionTrapezoid::validate\n"
+		""},
 	 { "delete_DistributionTrapezoid", _wrap_delete_DistributionTrapezoid, METH_O, "delete_DistributionTrapezoid(DistributionTrapezoid self)"},
 	 { "DistributionTrapezoid_swigregister", DistributionTrapezoid_swigregister, METH_O, NULL},
 	 { "DistributionTrapezoid_swiginit", DistributionTrapezoid_swiginit, METH_VARARGS, NULL},
diff --git a/auto/Wrap/libBornAgainSample.py b/auto/Wrap/libBornAgainSample.py
index c816d0c04f7..e70eda8034e 100644
--- a/auto/Wrap/libBornAgainSample.py
+++ b/auto/Wrap/libBornAgainSample.py
@@ -3877,6 +3877,14 @@ class IProfile1D(libBornAgainBase.ICloneable, libBornAgainParam.INode):
         """
         return _libBornAgainSample.IProfile1D_clone(self)
 
+    def parDefs(self):
+        r"""
+        parDefs(IProfile1D self) -> std::vector< ParaMeta,std::allocator< ParaMeta > >
+        std::vector< ParaMeta > IProfile1D::parDefs() const override
+        IProfile1D::parDefs
+        """
+        return _libBornAgainSample.IProfile1D_parDefs(self)
+
     def standardizedFT(self, q):
         r"""
         standardizedFT(IProfile1D self, double q) -> double
@@ -3973,14 +3981,6 @@ class Profile1DCauchy(IProfile1D):
         """
         return _libBornAgainSample.Profile1DCauchy_className(self)
 
-    def parDefs(self):
-        r"""
-        parDefs(Profile1DCauchy self) -> std::vector< ParaMeta,std::allocator< ParaMeta > >
-        std::vector< ParaMeta > Profile1DCauchy::parDefs() const final
-        Profile1DCauchy::parDefs
-        """
-        return _libBornAgainSample.Profile1DCauchy_parDefs(self)
-
     def standardizedFT(self, q):
         r"""
         standardizedFT(Profile1DCauchy self, double q) -> double
@@ -4053,14 +4053,6 @@ class Profile1DGauss(IProfile1D):
         """
         return _libBornAgainSample.Profile1DGauss_className(self)
 
-    def parDefs(self):
-        r"""
-        parDefs(Profile1DGauss self) -> std::vector< ParaMeta,std::allocator< ParaMeta > >
-        std::vector< ParaMeta > Profile1DGauss::parDefs() const final
-        Profile1DGauss::parDefs
-        """
-        return _libBornAgainSample.Profile1DGauss_parDefs(self)
-
     def standardizedFT(self, q):
         r"""
         standardizedFT(Profile1DGauss self, double q) -> double
@@ -4133,14 +4125,6 @@ class Profile1DGate(IProfile1D):
         """
         return _libBornAgainSample.Profile1DGate_className(self)
 
-    def parDefs(self):
-        r"""
-        parDefs(Profile1DGate self) -> std::vector< ParaMeta,std::allocator< ParaMeta > >
-        std::vector< ParaMeta > Profile1DGate::parDefs() const final
-        Profile1DGate::parDefs
-        """
-        return _libBornAgainSample.Profile1DGate_parDefs(self)
-
     def standardizedFT(self, q):
         r"""
         standardizedFT(Profile1DGate self, double q) -> double
@@ -4213,14 +4197,6 @@ class Profile1DTriangle(IProfile1D):
         """
         return _libBornAgainSample.Profile1DTriangle_className(self)
 
-    def parDefs(self):
-        r"""
-        parDefs(Profile1DTriangle self) -> std::vector< ParaMeta,std::allocator< ParaMeta > >
-        std::vector< ParaMeta > Profile1DTriangle::parDefs() const final
-        Profile1DTriangle::parDefs
-        """
-        return _libBornAgainSample.Profile1DTriangle_parDefs(self)
-
     def standardizedFT(self, q):
         r"""
         standardizedFT(Profile1DTriangle self, double q) -> double
@@ -4293,14 +4269,6 @@ class Profile1DCosine(IProfile1D):
         """
         return _libBornAgainSample.Profile1DCosine_className(self)
 
-    def parDefs(self):
-        r"""
-        parDefs(Profile1DCosine self) -> std::vector< ParaMeta,std::allocator< ParaMeta > >
-        std::vector< ParaMeta > Profile1DCosine::parDefs() const final
-        Profile1DCosine::parDefs
-        """
-        return _libBornAgainSample.Profile1DCosine_parDefs(self)
-
     def standardizedFT(self, q):
         r"""
         standardizedFT(Profile1DCosine self, double q) -> double
@@ -4455,6 +4423,14 @@ class IProfile2D(libBornAgainBase.ICloneable, libBornAgainParam.INode):
         """
         return _libBornAgainSample.IProfile2D_clone(self)
 
+    def parDefs(self):
+        r"""
+        parDefs(IProfile2D self) -> std::vector< ParaMeta,std::allocator< ParaMeta > >
+        std::vector< ParaMeta > IProfile2D::parDefs() const override
+        IProfile2D::parDefs
+        """
+        return _libBornAgainSample.IProfile2D_parDefs(self)
+
     def omegaX(self):
         r"""
         omegaX(IProfile2D self) -> double
@@ -4522,6 +4498,14 @@ class IProfile2D(libBornAgainBase.ICloneable, libBornAgainParam.INode):
         IProfile2D::decayFT2D
         """
         return _libBornAgainSample.IProfile2D_decayFT2D(self, qx, qy)
+
+    def validate(self):
+        r"""
+        validate(IProfile2D self) -> std::string
+        std::string IProfile2D::validate() const override
+        IProfile2D::validate
+        """
+        return _libBornAgainSample.IProfile2D_validate(self)
     __swig_destroy__ = _libBornAgainSample.delete_IProfile2D
 
 # Register IProfile2D in _libBornAgainSample:
@@ -4565,14 +4549,6 @@ class Profile2DCauchy(IProfile2D):
         """
         return _libBornAgainSample.Profile2DCauchy_className(self)
 
-    def parDefs(self):
-        r"""
-        parDefs(Profile2DCauchy self) -> std::vector< ParaMeta,std::allocator< ParaMeta > >
-        std::vector< ParaMeta > Profile2DCauchy::parDefs() const final
-        Profile2DCauchy::parDefs
-        """
-        return _libBornAgainSample.Profile2DCauchy_parDefs(self)
-
     def standardizedFT2D(self, qx, qy):
         r"""
         standardizedFT2D(Profile2DCauchy self, double qx, double qy) -> double
@@ -4633,14 +4609,6 @@ class Profile2DGauss(IProfile2D):
         """
         return _libBornAgainSample.Profile2DGauss_className(self)
 
-    def parDefs(self):
-        r"""
-        parDefs(Profile2DGauss self) -> std::vector< ParaMeta,std::allocator< ParaMeta > >
-        std::vector< ParaMeta > Profile2DGauss::parDefs() const final
-        Profile2DGauss::parDefs
-        """
-        return _libBornAgainSample.Profile2DGauss_parDefs(self)
-
     def standardizedFT2D(self, qx, qy):
         r"""
         standardizedFT2D(Profile2DGauss self, double qx, double qy) -> double
@@ -4701,14 +4669,6 @@ class Profile2DGate(IProfile2D):
         """
         return _libBornAgainSample.Profile2DGate_className(self)
 
-    def parDefs(self):
-        r"""
-        parDefs(Profile2DGate self) -> std::vector< ParaMeta,std::allocator< ParaMeta > >
-        std::vector< ParaMeta > Profile2DGate::parDefs() const final
-        Profile2DGate::parDefs
-        """
-        return _libBornAgainSample.Profile2DGate_parDefs(self)
-
     def standardizedFT2D(self, qx, qy):
         r"""
         standardizedFT2D(Profile2DGate self, double qx, double qy) -> double
@@ -4769,14 +4729,6 @@ class Profile2DCone(IProfile2D):
         """
         return _libBornAgainSample.Profile2DCone_className(self)
 
-    def parDefs(self):
-        r"""
-        parDefs(Profile2DCone self) -> std::vector< ParaMeta,std::allocator< ParaMeta > >
-        std::vector< ParaMeta > Profile2DCone::parDefs() const final
-        Profile2DCone::parDefs
-        """
-        return _libBornAgainSample.Profile2DCone_parDefs(self)
-
     def standardizedFT2D(self, qx, qy):
         r"""
         standardizedFT2D(Profile2DCone self, double qx, double qy) -> double
@@ -4868,8 +4820,18 @@ class Profile2DVoigt(IProfile2D):
         eta(Profile2DVoigt self) -> double
         double Profile2DVoigt::eta() const
         Profile2DVoigt::eta
+        balances between Gauss (eta=0) and Lorentz (eta=1) 
+
         """
         return _libBornAgainSample.Profile2DVoigt_eta(self)
+
+    def validate(self):
+        r"""
+        validate(Profile2DVoigt self) -> std::string
+        std::string Profile2DVoigt::validate() const final
+        Profile2DVoigt::validate
+        """
+        return _libBornAgainSample.Profile2DVoigt_validate(self)
     __swig_destroy__ = _libBornAgainSample.delete_Profile2DVoigt
 
 # Register Profile2DVoigt in _libBornAgainSample:
diff --git a/auto/Wrap/libBornAgainSample_wrap.cpp b/auto/Wrap/libBornAgainSample_wrap.cpp
index 22f549834d8..a01bb16d026 100644
--- a/auto/Wrap/libBornAgainSample_wrap.cpp
+++ b/auto/Wrap/libBornAgainSample_wrap.cpp
@@ -37027,6 +37027,29 @@ fail:
 }
 
 
+SWIGINTERN PyObject *_wrap_IProfile1D_parDefs(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *resultobj = 0;
+  IProfile1D *arg1 = (IProfile1D *) 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_IProfile1D, 0 |  0 );
+  if (!SWIG_IsOK(res1)) {
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "IProfile1D_parDefs" "', argument " "1"" of type '" "IProfile1D const *""'"); 
+  }
+  arg1 = reinterpret_cast< IProfile1D * >(argp1);
+  result = ((IProfile1D 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_IProfile1D_standardizedFT(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
   PyObject *resultobj = 0;
   IProfile1D *arg1 = (IProfile1D *) 0 ;
@@ -37334,29 +37357,6 @@ fail:
 }
 
 
-SWIGINTERN PyObject *_wrap_Profile1DCauchy_parDefs(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
-  Profile1DCauchy *arg1 = (Profile1DCauchy *) 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_Profile1DCauchy, 0 |  0 );
-  if (!SWIG_IsOK(res1)) {
-    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Profile1DCauchy_parDefs" "', argument " "1"" of type '" "Profile1DCauchy const *""'"); 
-  }
-  arg1 = reinterpret_cast< Profile1DCauchy * >(argp1);
-  result = ((Profile1DCauchy 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_Profile1DCauchy_standardizedFT(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
   PyObject *resultobj = 0;
   Profile1DCauchy *arg1 = (Profile1DCauchy *) 0 ;
@@ -37599,29 +37599,6 @@ fail:
 }
 
 
-SWIGINTERN PyObject *_wrap_Profile1DGauss_parDefs(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
-  Profile1DGauss *arg1 = (Profile1DGauss *) 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_Profile1DGauss, 0 |  0 );
-  if (!SWIG_IsOK(res1)) {
-    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Profile1DGauss_parDefs" "', argument " "1"" of type '" "Profile1DGauss const *""'"); 
-  }
-  arg1 = reinterpret_cast< Profile1DGauss * >(argp1);
-  result = ((Profile1DGauss 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_Profile1DGauss_standardizedFT(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
   PyObject *resultobj = 0;
   Profile1DGauss *arg1 = (Profile1DGauss *) 0 ;
@@ -37864,29 +37841,6 @@ fail:
 }
 
 
-SWIGINTERN PyObject *_wrap_Profile1DGate_parDefs(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
-  Profile1DGate *arg1 = (Profile1DGate *) 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_Profile1DGate, 0 |  0 );
-  if (!SWIG_IsOK(res1)) {
-    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Profile1DGate_parDefs" "', argument " "1"" of type '" "Profile1DGate const *""'"); 
-  }
-  arg1 = reinterpret_cast< Profile1DGate * >(argp1);
-  result = ((Profile1DGate 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_Profile1DGate_standardizedFT(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
   PyObject *resultobj = 0;
   Profile1DGate *arg1 = (Profile1DGate *) 0 ;
@@ -38129,29 +38083,6 @@ fail:
 }
 
 
-SWIGINTERN PyObject *_wrap_Profile1DTriangle_parDefs(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
-  Profile1DTriangle *arg1 = (Profile1DTriangle *) 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_Profile1DTriangle, 0 |  0 );
-  if (!SWIG_IsOK(res1)) {
-    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Profile1DTriangle_parDefs" "', argument " "1"" of type '" "Profile1DTriangle const *""'"); 
-  }
-  arg1 = reinterpret_cast< Profile1DTriangle * >(argp1);
-  result = ((Profile1DTriangle 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_Profile1DTriangle_standardizedFT(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
   PyObject *resultobj = 0;
   Profile1DTriangle *arg1 = (Profile1DTriangle *) 0 ;
@@ -38394,29 +38325,6 @@ fail:
 }
 
 
-SWIGINTERN PyObject *_wrap_Profile1DCosine_parDefs(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
-  Profile1DCosine *arg1 = (Profile1DCosine *) 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_Profile1DCosine, 0 |  0 );
-  if (!SWIG_IsOK(res1)) {
-    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Profile1DCosine_parDefs" "', argument " "1"" of type '" "Profile1DCosine const *""'"); 
-  }
-  arg1 = reinterpret_cast< Profile1DCosine * >(argp1);
-  result = ((Profile1DCosine 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_Profile1DCosine_standardizedFT(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
   PyObject *resultobj = 0;
   Profile1DCosine *arg1 = (Profile1DCosine *) 0 ;
@@ -38881,6 +38789,29 @@ fail:
 }
 
 
+SWIGINTERN PyObject *_wrap_IProfile2D_parDefs(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *resultobj = 0;
+  IProfile2D *arg1 = (IProfile2D *) 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_IProfile2D, 0 |  0 );
+  if (!SWIG_IsOK(res1)) {
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "IProfile2D_parDefs" "', argument " "1"" of type '" "IProfile2D const *""'"); 
+  }
+  arg1 = reinterpret_cast< IProfile2D * >(argp1);
+  result = ((IProfile2D 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_IProfile2D_omegaX(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
   PyObject *resultobj = 0;
   IProfile2D *arg1 = (IProfile2D *) 0 ;
@@ -39095,6 +39026,29 @@ fail:
 }
 
 
+SWIGINTERN PyObject *_wrap_IProfile2D_validate(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *resultobj = 0;
+  IProfile2D *arg1 = (IProfile2D *) 0 ;
+  void *argp1 = 0 ;
+  int res1 = 0 ;
+  PyObject *swig_obj[1] ;
+  std::string result;
+  
+  if (!args) SWIG_fail;
+  swig_obj[0] = args;
+  res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_IProfile2D, 0 |  0 );
+  if (!SWIG_IsOK(res1)) {
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "IProfile2D_validate" "', argument " "1"" of type '" "IProfile2D const *""'"); 
+  }
+  arg1 = reinterpret_cast< IProfile2D * >(argp1);
+  result = ((IProfile2D const *)arg1)->validate();
+  resultobj = SWIG_From_std_string(static_cast< std::string >(result));
+  return resultobj;
+fail:
+  return NULL;
+}
+
+
 SWIGINTERN PyObject *_wrap_delete_IProfile2D(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
   PyObject *resultobj = 0;
   IProfile2D *arg1 = (IProfile2D *) 0 ;
@@ -39278,29 +39232,6 @@ fail:
 }
 
 
-SWIGINTERN PyObject *_wrap_Profile2DCauchy_parDefs(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
-  Profile2DCauchy *arg1 = (Profile2DCauchy *) 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_Profile2DCauchy, 0 |  0 );
-  if (!SWIG_IsOK(res1)) {
-    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Profile2DCauchy_parDefs" "', argument " "1"" of type '" "Profile2DCauchy const *""'"); 
-  }
-  arg1 = reinterpret_cast< Profile2DCauchy * >(argp1);
-  result = ((Profile2DCauchy 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_Profile2DCauchy_standardizedFT2D(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
   PyObject *resultobj = 0;
   Profile2DCauchy *arg1 = (Profile2DCauchy *) 0 ;
@@ -39564,29 +39495,6 @@ fail:
 }
 
 
-SWIGINTERN PyObject *_wrap_Profile2DGauss_parDefs(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
-  Profile2DGauss *arg1 = (Profile2DGauss *) 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_Profile2DGauss, 0 |  0 );
-  if (!SWIG_IsOK(res1)) {
-    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Profile2DGauss_parDefs" "', argument " "1"" of type '" "Profile2DGauss const *""'"); 
-  }
-  arg1 = reinterpret_cast< Profile2DGauss * >(argp1);
-  result = ((Profile2DGauss 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_Profile2DGauss_standardizedFT2D(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
   PyObject *resultobj = 0;
   Profile2DGauss *arg1 = (Profile2DGauss *) 0 ;
@@ -39850,29 +39758,6 @@ fail:
 }
 
 
-SWIGINTERN PyObject *_wrap_Profile2DGate_parDefs(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
-  Profile2DGate *arg1 = (Profile2DGate *) 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_Profile2DGate, 0 |  0 );
-  if (!SWIG_IsOK(res1)) {
-    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Profile2DGate_parDefs" "', argument " "1"" of type '" "Profile2DGate const *""'"); 
-  }
-  arg1 = reinterpret_cast< Profile2DGate * >(argp1);
-  result = ((Profile2DGate 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_Profile2DGate_standardizedFT2D(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
   PyObject *resultobj = 0;
   Profile2DGate *arg1 = (Profile2DGate *) 0 ;
@@ -40136,29 +40021,6 @@ fail:
 }
 
 
-SWIGINTERN PyObject *_wrap_Profile2DCone_parDefs(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
-  Profile2DCone *arg1 = (Profile2DCone *) 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_Profile2DCone, 0 |  0 );
-  if (!SWIG_IsOK(res1)) {
-    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Profile2DCone_parDefs" "', argument " "1"" of type '" "Profile2DCone const *""'"); 
-  }
-  arg1 = reinterpret_cast< Profile2DCone * >(argp1);
-  result = ((Profile2DCone 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_Profile2DCone_standardizedFT2D(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
   PyObject *resultobj = 0;
   Profile2DCone *arg1 = (Profile2DCone *) 0 ;
@@ -40558,6 +40420,29 @@ fail:
 }
 
 
+SWIGINTERN PyObject *_wrap_Profile2DVoigt_validate(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *resultobj = 0;
+  Profile2DVoigt *arg1 = (Profile2DVoigt *) 0 ;
+  void *argp1 = 0 ;
+  int res1 = 0 ;
+  PyObject *swig_obj[1] ;
+  std::string result;
+  
+  if (!args) SWIG_fail;
+  swig_obj[0] = args;
+  res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_Profile2DVoigt, 0 |  0 );
+  if (!SWIG_IsOK(res1)) {
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Profile2DVoigt_validate" "', argument " "1"" of type '" "Profile2DVoigt const *""'"); 
+  }
+  arg1 = reinterpret_cast< Profile2DVoigt * >(argp1);
+  result = ((Profile2DVoigt const *)arg1)->validate();
+  resultobj = SWIG_From_std_string(static_cast< std::string >(result));
+  return resultobj;
+fail:
+  return NULL;
+}
+
+
 SWIGINTERN PyObject *_wrap_delete_Profile2DVoigt(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
   PyObject *resultobj = 0;
   Profile2DVoigt *arg1 = (Profile2DVoigt *) 0 ;
@@ -62719,6 +62604,11 @@ static PyMethodDef SwigMethods[] = {
 		"IProfile1D * IProfile1D::clone() const override=0\n"
 		"IProfile1D::clone\n"
 		""},
+	 { "IProfile1D_parDefs", _wrap_IProfile1D_parDefs, METH_O, "\n"
+		"IProfile1D_parDefs(IProfile1D self) -> std::vector< ParaMeta,std::allocator< ParaMeta > >\n"
+		"std::vector< ParaMeta > IProfile1D::parDefs() const override\n"
+		"IProfile1D::parDefs\n"
+		""},
 	 { "IProfile1D_standardizedFT", _wrap_IProfile1D_standardizedFT, METH_VARARGS, "\n"
 		"IProfile1D_standardizedFT(IProfile1D self, double q) -> double\n"
 		"virtual double IProfile1D::standardizedFT(double q) const =0\n"
@@ -62773,11 +62663,6 @@ static PyMethodDef SwigMethods[] = {
 		"std::string Profile1DCauchy::className() const final\n"
 		"Profile1DCauchy::className\n"
 		""},
-	 { "Profile1DCauchy_parDefs", _wrap_Profile1DCauchy_parDefs, METH_O, "\n"
-		"Profile1DCauchy_parDefs(Profile1DCauchy self) -> std::vector< ParaMeta,std::allocator< ParaMeta > >\n"
-		"std::vector< ParaMeta > Profile1DCauchy::parDefs() const final\n"
-		"Profile1DCauchy::parDefs\n"
-		""},
 	 { "Profile1DCauchy_standardizedFT", _wrap_Profile1DCauchy_standardizedFT, METH_VARARGS, "\n"
 		"Profile1DCauchy_standardizedFT(Profile1DCauchy self, double q) -> double\n"
 		"double Profile1DCauchy::standardizedFT(double q) const override\n"
@@ -62818,11 +62703,6 @@ static PyMethodDef SwigMethods[] = {
 		"std::string Profile1DGauss::className() const final\n"
 		"Profile1DGauss::className\n"
 		""},
-	 { "Profile1DGauss_parDefs", _wrap_Profile1DGauss_parDefs, METH_O, "\n"
-		"Profile1DGauss_parDefs(Profile1DGauss self) -> std::vector< ParaMeta,std::allocator< ParaMeta > >\n"
-		"std::vector< ParaMeta > Profile1DGauss::parDefs() const final\n"
-		"Profile1DGauss::parDefs\n"
-		""},
 	 { "Profile1DGauss_standardizedFT", _wrap_Profile1DGauss_standardizedFT, METH_VARARGS, "\n"
 		"Profile1DGauss_standardizedFT(Profile1DGauss self, double q) -> double\n"
 		"double Profile1DGauss::standardizedFT(double q) const override\n"
@@ -62863,11 +62743,6 @@ static PyMethodDef SwigMethods[] = {
 		"std::string Profile1DGate::className() const final\n"
 		"Profile1DGate::className\n"
 		""},
-	 { "Profile1DGate_parDefs", _wrap_Profile1DGate_parDefs, METH_O, "\n"
-		"Profile1DGate_parDefs(Profile1DGate self) -> std::vector< ParaMeta,std::allocator< ParaMeta > >\n"
-		"std::vector< ParaMeta > Profile1DGate::parDefs() const final\n"
-		"Profile1DGate::parDefs\n"
-		""},
 	 { "Profile1DGate_standardizedFT", _wrap_Profile1DGate_standardizedFT, METH_VARARGS, "\n"
 		"Profile1DGate_standardizedFT(Profile1DGate self, double q) -> double\n"
 		"double Profile1DGate::standardizedFT(double q) const override\n"
@@ -62908,11 +62783,6 @@ static PyMethodDef SwigMethods[] = {
 		"std::string Profile1DTriangle::className() const final\n"
 		"Profile1DTriangle::className\n"
 		""},
-	 { "Profile1DTriangle_parDefs", _wrap_Profile1DTriangle_parDefs, METH_O, "\n"
-		"Profile1DTriangle_parDefs(Profile1DTriangle self) -> std::vector< ParaMeta,std::allocator< ParaMeta > >\n"
-		"std::vector< ParaMeta > Profile1DTriangle::parDefs() const final\n"
-		"Profile1DTriangle::parDefs\n"
-		""},
 	 { "Profile1DTriangle_standardizedFT", _wrap_Profile1DTriangle_standardizedFT, METH_VARARGS, "\n"
 		"Profile1DTriangle_standardizedFT(Profile1DTriangle self, double q) -> double\n"
 		"double Profile1DTriangle::standardizedFT(double q) const override\n"
@@ -62953,11 +62823,6 @@ static PyMethodDef SwigMethods[] = {
 		"std::string Profile1DCosine::className() const final\n"
 		"Profile1DCosine::className\n"
 		""},
-	 { "Profile1DCosine_parDefs", _wrap_Profile1DCosine_parDefs, METH_O, "\n"
-		"Profile1DCosine_parDefs(Profile1DCosine self) -> std::vector< ParaMeta,std::allocator< ParaMeta > >\n"
-		"std::vector< ParaMeta > Profile1DCosine::parDefs() const final\n"
-		"Profile1DCosine::parDefs\n"
-		""},
 	 { "Profile1DCosine_standardizedFT", _wrap_Profile1DCosine_standardizedFT, METH_VARARGS, "\n"
 		"Profile1DCosine_standardizedFT(Profile1DCosine self, double q) -> double\n"
 		"double Profile1DCosine::standardizedFT(double q) const override\n"
@@ -63042,6 +62907,11 @@ static PyMethodDef SwigMethods[] = {
 		"IProfile2D * IProfile2D::clone() const override=0\n"
 		"IProfile2D::clone\n"
 		""},
+	 { "IProfile2D_parDefs", _wrap_IProfile2D_parDefs, METH_O, "\n"
+		"IProfile2D_parDefs(IProfile2D self) -> std::vector< ParaMeta,std::allocator< ParaMeta > >\n"
+		"std::vector< ParaMeta > IProfile2D::parDefs() const override\n"
+		"IProfile2D::parDefs\n"
+		""},
 	 { "IProfile2D_omegaX", _wrap_IProfile2D_omegaX, METH_O, "\n"
 		"IProfile2D_omegaX(IProfile2D self) -> double\n"
 		"double IProfile2D::omegaX() const\n"
@@ -63086,6 +62956,11 @@ static PyMethodDef SwigMethods[] = {
 		"virtual double IProfile2D::decayFT2D(double qx, double qy) const =0\n"
 		"IProfile2D::decayFT2D\n"
 		""},
+	 { "IProfile2D_validate", _wrap_IProfile2D_validate, METH_O, "\n"
+		"IProfile2D_validate(IProfile2D self) -> std::string\n"
+		"std::string IProfile2D::validate() const override\n"
+		"IProfile2D::validate\n"
+		""},
 	 { "delete_IProfile2D", _wrap_delete_IProfile2D, METH_O, "delete_IProfile2D(IProfile2D self)"},
 	 { "IProfile2D_swigregister", IProfile2D_swigregister, METH_O, NULL},
 	 { "new_Profile2DCauchy", _wrap_new_Profile2DCauchy, METH_VARARGS, "\n"
@@ -63104,11 +62979,6 @@ static PyMethodDef SwigMethods[] = {
 		"std::string Profile2DCauchy::className() const final\n"
 		"Profile2DCauchy::className\n"
 		""},
-	 { "Profile2DCauchy_parDefs", _wrap_Profile2DCauchy_parDefs, METH_O, "\n"
-		"Profile2DCauchy_parDefs(Profile2DCauchy self) -> std::vector< ParaMeta,std::allocator< ParaMeta > >\n"
-		"std::vector< ParaMeta > Profile2DCauchy::parDefs() const final\n"
-		"Profile2DCauchy::parDefs\n"
-		""},
 	 { "Profile2DCauchy_standardizedFT2D", _wrap_Profile2DCauchy_standardizedFT2D, METH_VARARGS, "\n"
 		"Profile2DCauchy_standardizedFT2D(Profile2DCauchy self, double qx, double qy) -> double\n"
 		"double Profile2DCauchy::standardizedFT2D(double qx, double qy) const override\n"
@@ -63140,11 +63010,6 @@ static PyMethodDef SwigMethods[] = {
 		"std::string Profile2DGauss::className() const final\n"
 		"Profile2DGauss::className\n"
 		""},
-	 { "Profile2DGauss_parDefs", _wrap_Profile2DGauss_parDefs, METH_O, "\n"
-		"Profile2DGauss_parDefs(Profile2DGauss self) -> std::vector< ParaMeta,std::allocator< ParaMeta > >\n"
-		"std::vector< ParaMeta > Profile2DGauss::parDefs() const final\n"
-		"Profile2DGauss::parDefs\n"
-		""},
 	 { "Profile2DGauss_standardizedFT2D", _wrap_Profile2DGauss_standardizedFT2D, METH_VARARGS, "\n"
 		"Profile2DGauss_standardizedFT2D(Profile2DGauss self, double qx, double qy) -> double\n"
 		"double Profile2DGauss::standardizedFT2D(double qx, double qy) const override\n"
@@ -63176,11 +63041,6 @@ static PyMethodDef SwigMethods[] = {
 		"std::string Profile2DGate::className() const final\n"
 		"Profile2DGate::className\n"
 		""},
-	 { "Profile2DGate_parDefs", _wrap_Profile2DGate_parDefs, METH_O, "\n"
-		"Profile2DGate_parDefs(Profile2DGate self) -> std::vector< ParaMeta,std::allocator< ParaMeta > >\n"
-		"std::vector< ParaMeta > Profile2DGate::parDefs() const final\n"
-		"Profile2DGate::parDefs\n"
-		""},
 	 { "Profile2DGate_standardizedFT2D", _wrap_Profile2DGate_standardizedFT2D, METH_VARARGS, "\n"
 		"Profile2DGate_standardizedFT2D(Profile2DGate self, double qx, double qy) -> double\n"
 		"double Profile2DGate::standardizedFT2D(double qx, double qy) const override\n"
@@ -63212,11 +63072,6 @@ static PyMethodDef SwigMethods[] = {
 		"std::string Profile2DCone::className() const final\n"
 		"Profile2DCone::className\n"
 		""},
-	 { "Profile2DCone_parDefs", _wrap_Profile2DCone_parDefs, METH_O, "\n"
-		"Profile2DCone_parDefs(Profile2DCone self) -> std::vector< ParaMeta,std::allocator< ParaMeta > >\n"
-		"std::vector< ParaMeta > Profile2DCone::parDefs() const final\n"
-		"Profile2DCone::parDefs\n"
-		""},
 	 { "Profile2DCone_standardizedFT2D", _wrap_Profile2DCone_standardizedFT2D, METH_VARARGS, "\n"
 		"Profile2DCone_standardizedFT2D(Profile2DCone self, double qx, double qy) -> double\n"
 		"double Profile2DCone::standardizedFT2D(double qx, double qy) const override\n"
@@ -63269,6 +63124,13 @@ static PyMethodDef SwigMethods[] = {
 		"Profile2DVoigt_eta(Profile2DVoigt self) -> double\n"
 		"double Profile2DVoigt::eta() const\n"
 		"Profile2DVoigt::eta\n"
+		"balances between Gauss (eta=0) and Lorentz (eta=1) \n"
+		"\n"
+		""},
+	 { "Profile2DVoigt_validate", _wrap_Profile2DVoigt_validate, METH_O, "\n"
+		"Profile2DVoigt_validate(Profile2DVoigt self) -> std::string\n"
+		"std::string Profile2DVoigt::validate() const final\n"
+		"Profile2DVoigt::validate\n"
 		""},
 	 { "delete_Profile2DVoigt", _wrap_delete_Profile2DVoigt, METH_O, "delete_Profile2DVoigt(Profile2DVoigt self)"},
 	 { "Profile2DVoigt_swigregister", Profile2DVoigt_swigregister, METH_O, NULL},
-- 
GitLab