From 82d6eb79ada29d5265d4bd33d11067f7f36571d6 Mon Sep 17 00:00:00 2001
From: Walter Van Herck <w.van.herck@fz-juelich.de>
Date: Thu, 12 Dec 2013 15:20:08 +0100
Subject: [PATCH] Added form factor for full sphere which is integrated over a
 uniform radius distribution

---
 .../inc/FormFactorSphereGaussianRadius.h      |  66 +--
 .../inc/FormFactorSphereUniformRadius.h       |  54 ++
 Core/FormFactors/src/FormFactorFullSphere.cpp |   2 +-
 .../src/FormFactorSphereGaussianRadius.cpp    |  87 +++
 .../src/FormFactorSphereUniformRadius.cpp     |  94 +++
 .../inc/FormFactorSphereUniformRadius.pypp.h  |  11 +
 Core/PythonAPI/inc/PythonCoreList.h           |   1 +
 .../FormFactorSphereUniformRadius.pypp.cpp    | 537 ++++++++++++++++++
 Core/PythonAPI/src/PythonModule.cpp           |   2 +
 Core/StandardSamples/MesoCrystal01Builder.cpp |  24 +-
 Core/python_module.pri                        |   2 +
 dev-tools/python-bindings/MakePyCore.py       |   1 +
 12 files changed, 805 insertions(+), 76 deletions(-)
 create mode 100644 Core/FormFactors/inc/FormFactorSphereUniformRadius.h
 create mode 100644 Core/FormFactors/src/FormFactorSphereGaussianRadius.cpp
 create mode 100644 Core/FormFactors/src/FormFactorSphereUniformRadius.cpp
 create mode 100644 Core/PythonAPI/inc/FormFactorSphereUniformRadius.pypp.h
 create mode 100644 Core/PythonAPI/src/FormFactorSphereUniformRadius.pypp.cpp

diff --git a/Core/FormFactors/inc/FormFactorSphereGaussianRadius.h b/Core/FormFactors/inc/FormFactorSphereGaussianRadius.h
index eca022fc44a..286879dd449 100644
--- a/Core/FormFactors/inc/FormFactorSphereGaussianRadius.h
+++ b/Core/FormFactors/inc/FormFactorSphereGaussianRadius.h
@@ -42,6 +42,9 @@ public:
 
     virtual complex_t evaluate_for_q(const cvector_t& q) const;
 
+protected:
+    virtual void init_parameters();
+
 private:
     double calculateMeanR3() const;
 
@@ -49,71 +52,8 @@ private:
     double m_sigma;
     double m_mean_r3; //!< This is the radius that gives the mean volume
     FormFactorFullSphere *p_ff_sphere;
-    cvector_t m_zero_vector;
 };
 
-inline FormFactorSphereGaussianRadius::FormFactorSphereGaussianRadius(double mean, double sigma)
-: m_mean(mean)
-, m_sigma(sigma)
-, m_mean_r3(0.0)
-, p_ff_sphere(0)
-, m_zero_vector(0.0, 0.0, 0.0)
-{
-    setName("FormFactorSphereGaussianRadius");
-    m_mean_r3 = calculateMeanR3();
-    p_ff_sphere = new FormFactorFullSphere(m_mean_r3);
-}
-
-inline FormFactorSphereGaussianRadius* FormFactorSphereGaussianRadius::clone() const
-{
-    FormFactorSphereGaussianRadius *result =
-        new FormFactorSphereGaussianRadius(m_mean, m_sigma);
-    result->setName(getName());
-    return result;
-}
-
-inline FormFactorSphereGaussianRadius::~FormFactorSphereGaussianRadius()
-{
-    delete p_ff_sphere;
-}
-inline int FormFactorSphereGaussianRadius::getNumberOfStochasticParameters() const
-{
-    return 2;
-}
-
-inline complex_t FormFactorSphereGaussianRadius::evaluate_for_q(const cvector_t& q) const
-{
-    double q2 = std::norm(q.x()) + std::norm(q.y()) + std::norm(q.z());
-    double dw = std::exp(-q2*m_sigma*m_sigma/2.0);
-    return dw*p_ff_sphere->evaluate_for_q(q);
-}
-
-inline double FormFactorSphereGaussianRadius::calculateMeanR3() const
-{
-    return std::pow(m_mean*(m_mean*m_mean+3.0*m_sigma*m_sigma),1.0/3.0);
-}
-
-inline void FormFactorSphereGaussianRadius::createDistributedFormFactors(
-        std::vector<IFormFactor*>& form_factors,
-        std::vector<double>& probabilities, size_t nbr_samples) const
-{
-    double sigma_range = 2.0*m_sigma;
-    double step = 2.0*sigma_range/(nbr_samples-1.0);
-    double radius_start = m_mean-step*(nbr_samples/2); // 2 and not 2. is on purpose
-    double total_prob = 0.0;
-    for (size_t i=0; i<nbr_samples; ++i) {
-        double radius = radius_start + (double)i*step;
-        double probability = MathFunctions::Gaussian(radius, m_mean, m_sigma);
-        form_factors.push_back(new FormFactorFullSphere(radius));
-        probabilities.push_back(probability);
-        total_prob += probability;
-    }
-    assert(total_prob);
-    for (size_t i=0; i<probabilities.size(); ++i) {
-        probabilities[i] /= total_prob;
-    }
-}
-
 #endif /* FORMFACTORSPHEREGAUSSIANRADIUS_H_ */
 
 
diff --git a/Core/FormFactors/inc/FormFactorSphereUniformRadius.h b/Core/FormFactors/inc/FormFactorSphereUniformRadius.h
new file mode 100644
index 00000000000..9bd348d18d0
--- /dev/null
+++ b/Core/FormFactors/inc/FormFactorSphereUniformRadius.h
@@ -0,0 +1,54 @@
+// ************************************************************************** //
+//
+//  BornAgain: simulate and fit scattering at grazing incidence
+//
+//! @file      FormFactorSphereUniformRadius.h
+//! @brief     Defines class .
+//!
+//! @homepage  http://apps.jcns.fz-juelich.de/BornAgain
+//! @license   GNU General Public License v3 or higher (see COPYING)
+//! @copyright Forschungszentrum Jülich GmbH 2013
+//! @authors   Scientific Computing Group at MLZ Garching
+//! @authors   C. Durniak, G. Pospelov, W. Van Herck, J. Wuttke
+//
+// ************************************************************************** //
+
+#ifndef FORMFACTORSPHEREUNIFORMRADIUS_H_
+#define FORMFACTORSPHEREUNIFORMRADIUS_H_
+
+#include "MathFunctions.h"
+
+#include "IFormFactor.h"
+#include "FormFactorFullSphere.h"
+#include <cassert>
+
+//! Integrated full sphere form factor over a uniform distribution of radii
+class BA_CORE_API_ FormFactorSphereUniformRadius : public IFormFactorBorn
+{
+public:
+    FormFactorSphereUniformRadius(double mean, double full_width);
+    virtual FormFactorSphereUniformRadius *clone() const;
+    virtual ~FormFactorSphereUniformRadius();
+
+    virtual void accept(ISampleVisitor *visitor) const { visitor->visit(this); }
+
+    virtual int getNumberOfStochasticParameters() const;
+    virtual bool isDistributedFormFactor() const { return true; }
+    virtual void createDistributedFormFactors(
+        std::vector<IFormFactor*>& form_factors,
+        std::vector<double>& probabilities, size_t nbr_samples) const;
+
+    virtual double getHeight() const { return 2.0*m_mean; }
+
+    virtual complex_t evaluate_for_q(const cvector_t& q) const;
+
+protected:
+    virtual void init_parameters();
+
+private:
+    bool checkParameters() const;
+    double m_mean; //!< This is the mean radius
+    double m_full_width; //!< This is the full width of the radius distribution
+};
+
+#endif /* FORMFACTORSPHEREUNIFORMRADIUS_H_ */
diff --git a/Core/FormFactors/src/FormFactorFullSphere.cpp b/Core/FormFactors/src/FormFactorFullSphere.cpp
index 91b7836b9f9..5f11fdc8b51 100644
--- a/Core/FormFactors/src/FormFactorFullSphere.cpp
+++ b/Core/FormFactors/src/FormFactorFullSphere.cpp
@@ -21,9 +21,9 @@
 //#include <cmath>
 
 FormFactorFullSphere::FormFactorFullSphere(double radius)
+: m_radius(radius)
 {
     setName("FormFactorFullSphere");
-    m_radius = radius;
     init_parameters();
 }
 
diff --git a/Core/FormFactors/src/FormFactorSphereGaussianRadius.cpp b/Core/FormFactors/src/FormFactorSphereGaussianRadius.cpp
new file mode 100644
index 00000000000..bd862d6c9a2
--- /dev/null
+++ b/Core/FormFactors/src/FormFactorSphereGaussianRadius.cpp
@@ -0,0 +1,87 @@
+// ************************************************************************** //
+//
+//  BornAgain: simulate and fit scattering at grazing incidence
+//
+//! @file      FormFactorSphereGaussianRadius.cpp
+//! @brief     Defines class .
+//!
+//! @homepage  http://apps.jcns.fz-juelich.de/BornAgain
+//! @license   GNU General Public License v3 or higher (see COPYING)
+//! @copyright Forschungszentrum Jülich GmbH 2013
+//! @authors   Scientific Computing Group at MLZ Garching
+//! @authors   C. Durniak, G. Pospelov, W. Van Herck, J. Wuttke
+//
+// ************************************************************************** //
+
+#include "FormFactorSphereGaussianRadius.h"
+
+FormFactorSphereGaussianRadius::FormFactorSphereGaussianRadius(double mean, double sigma)
+: m_mean(mean)
+, m_sigma(sigma)
+, m_mean_r3(0.0)
+, p_ff_sphere(0)
+{
+    setName("FormFactorSphereGaussianRadius");
+    m_mean_r3 = calculateMeanR3();
+    p_ff_sphere = new FormFactorFullSphere(m_mean_r3);
+    init_parameters();
+}
+
+FormFactorSphereGaussianRadius* FormFactorSphereGaussianRadius::clone() const
+{
+    FormFactorSphereGaussianRadius *result =
+        new FormFactorSphereGaussianRadius(m_mean, m_sigma);
+    result->setName(getName());
+    return result;
+}
+
+FormFactorSphereGaussianRadius::~FormFactorSphereGaussianRadius()
+{
+    delete p_ff_sphere;
+}
+
+int FormFactorSphereGaussianRadius::getNumberOfStochasticParameters() const
+{
+    return 2;
+}
+
+complex_t FormFactorSphereGaussianRadius::evaluate_for_q(const cvector_t& q) const
+{
+    double q2 = std::norm(q.x()) + std::norm(q.y()) + std::norm(q.z());
+    double dw = std::exp(-q2*m_sigma*m_sigma/2.0);
+    return dw*p_ff_sphere->evaluate_for_q(q);
+}
+
+double FormFactorSphereGaussianRadius::calculateMeanR3() const
+{
+    return std::pow(m_mean*(m_mean*m_mean+3.0*m_sigma*m_sigma),1.0/3.0);
+}
+
+void FormFactorSphereGaussianRadius::createDistributedFormFactors(
+        std::vector<IFormFactor*>& form_factors,
+        std::vector<double>& probabilities, size_t nbr_samples) const
+{
+    assert(nbr_samples>1);
+    double sigma_range = 2.0*m_sigma;
+    double step = 2.0*sigma_range/(nbr_samples-1.0);
+    double radius_start = m_mean-step*(nbr_samples/2); // 2 and not 2. is on purpose
+    double total_prob = 0.0;
+    for (size_t i=0; i<nbr_samples; ++i) {
+        double radius = radius_start + (double)i*step;
+        double probability = MathFunctions::Gaussian(radius, m_mean, m_sigma);
+        form_factors.push_back(new FormFactorFullSphere(radius));
+        probabilities.push_back(probability);
+        total_prob += probability;
+    }
+    assert(total_prob);
+    for (size_t i=0; i<probabilities.size(); ++i) {
+        probabilities[i] /= total_prob;
+    }
+}
+
+void FormFactorSphereGaussianRadius::init_parameters()
+{
+    clearParameterPool();
+    registerParameter("mean_radius", &m_mean);
+    registerParameter("sigma_radius", &m_sigma);
+}
diff --git a/Core/FormFactors/src/FormFactorSphereUniformRadius.cpp b/Core/FormFactors/src/FormFactorSphereUniformRadius.cpp
new file mode 100644
index 00000000000..05c9a8742c9
--- /dev/null
+++ b/Core/FormFactors/src/FormFactorSphereUniformRadius.cpp
@@ -0,0 +1,94 @@
+// ************************************************************************** //
+//
+//  BornAgain: simulate and fit scattering at grazing incidence
+//
+//! @file      FormFactorSphereUniformRadius.cpp
+//! @brief     Defines class .
+//!
+//! @homepage  http://apps.jcns.fz-juelich.de/BornAgain
+//! @license   GNU General Public License v3 or higher (see COPYING)
+//! @copyright Forschungszentrum Jülich GmbH 2013
+//! @authors   Scientific Computing Group at MLZ Garching
+//! @authors   C. Durniak, G. Pospelov, W. Van Herck, J. Wuttke
+//
+// ************************************************************************** //
+
+#include "FormFactorSphereUniformRadius.h"
+
+FormFactorSphereUniformRadius::FormFactorSphereUniformRadius(double mean,
+        double full_width)
+: m_mean(mean)
+, m_full_width(full_width)
+{
+    if(!checkParameters()) {
+        throw Exceptions::ClassInitializationException(
+                "FormFactorSphereUniformRadius::FormFactorSphereUniformRadius:"
+                " mean radius must be bigger than the half width");
+    }
+    setName("FormFactorSphereUniformRadius");
+    init_parameters();
+}
+
+FormFactorSphereUniformRadius* FormFactorSphereUniformRadius::clone() const
+{
+    FormFactorSphereUniformRadius *result = FormFactorSphereUniformRadius(
+            m_mean, m_full_width);
+    result->setName(getName());
+    return result;
+}
+
+FormFactorSphereUniformRadius::~FormFactorSphereUniformRadius()
+{
+}
+
+int FormFactorSphereUniformRadius::getNumberOfStochasticParameters() const
+{
+    return 2;
+}
+
+void FormFactorSphereUniformRadius::createDistributedFormFactors(
+        std::vector<IFormFactor*>& form_factors,
+        std::vector<double>& probabilities, size_t nbr_samples) const
+{
+    assert(nbr_samples>1);
+    double step = m_full_width/(nbr_samples+1.0);
+    double radius_start = m_mean - m_full_width/2.0;
+    double probability = 1.0/nbr_samples;
+    for (size_t i=0; i<nbr_samples; ++i) {
+        double radius = radius_start + (double)i*step;
+        form_factors.push_back(new FormFactorFullSphere(radius));
+        probabilities.push_back(probability);
+    }
+}
+
+complex_t FormFactorSphereUniformRadius::evaluate_for_q(
+        const cvector_t& q) const
+{
+    double R = m_mean;
+    double W = m_full_width;
+    double q2 = std::norm(q.x()) + std::norm(q.y()) + std::norm(q.z());
+    double q_r = std::sqrt(q2);
+    if (q_r*R < Numeric::double_epsilon) {
+        return (4.0*M_PI*R*R*R + M_PI*R*W*W)/3.0;
+    }
+    double qR = q_r*R;
+    double qW = q_r*W;
+    double nominator = 4*M_PI*( 4*std::sin(qR)*std::sin(qW/2.0)
+                             - qW*std::cos(qW/2.0)*std::sin(qR)
+                             - 2.0*qR*std::cos(qR)*std::sin(qW/2.0));
+    return nominator/(q2*q2*W);
+}
+
+void FormFactorSphereUniformRadius::init_parameters()
+{
+    clearParameterPool();
+    registerParameter("mean_radius", &m_mean);
+    registerParameter("width_radius", &m_full_width);
+}
+
+bool FormFactorSphereUniformRadius::checkParameters() const
+{
+    if (m_full_width<=0.0) return false;
+    if (2.0*m_mean<m_full_width) return false;
+    return true;
+}
diff --git a/Core/PythonAPI/inc/FormFactorSphereUniformRadius.pypp.h b/Core/PythonAPI/inc/FormFactorSphereUniformRadius.pypp.h
new file mode 100644
index 00000000000..33431347b45
--- /dev/null
+++ b/Core/PythonAPI/inc/FormFactorSphereUniformRadius.pypp.h
@@ -0,0 +1,11 @@
+// This file has been generated by Py++.
+
+// BornAgain: simulate and fit scattering at grazing incidence 
+//! @brief automatically generated boost::python code for PythonCoreAPI  
+
+#ifndef FormFactorSphereUniformRadius_hpp__pyplusplus_wrapper
+#define FormFactorSphereUniformRadius_hpp__pyplusplus_wrapper
+
+void register_FormFactorSphereUniformRadius_class();
+
+#endif//FormFactorSphereUniformRadius_hpp__pyplusplus_wrapper
diff --git a/Core/PythonAPI/inc/PythonCoreList.h b/Core/PythonAPI/inc/PythonCoreList.h
index 884d36197f7..7b0fb7991d7 100644
--- a/Core/PythonAPI/inc/PythonCoreList.h
+++ b/Core/PythonAPI/inc/PythonCoreList.h
@@ -32,6 +32,7 @@
 #include "FormFactorPyramid.h"
 #include "FormFactorSphere.h"
 #include "FormFactorSphereGaussianRadius.h"
+#include "FormFactorSphereUniformRadius.h"
 #include "FormFactorSpheroid.h"
 #include "HomogeneousMaterial.h"
 #include "ICloneable.h"
diff --git a/Core/PythonAPI/src/FormFactorSphereUniformRadius.pypp.cpp b/Core/PythonAPI/src/FormFactorSphereUniformRadius.pypp.cpp
new file mode 100644
index 00000000000..6e5fbc83f15
--- /dev/null
+++ b/Core/PythonAPI/src/FormFactorSphereUniformRadius.pypp.cpp
@@ -0,0 +1,537 @@
+// This file has been generated by Py++.
+
+// BornAgain: simulate and fit scattering at grazing incidence 
+//! @brief automatically generated boost::python code for PythonCoreAPI  
+
+#include "Macros.h"
+GCC_DIAG_OFF(unused-parameter);
+GCC_DIAG_OFF(missing-field-initializers);
+#include "boost/python.hpp"
+GCC_DIAG_ON(unused-parameter);
+GCC_DIAG_ON(missing-field-initializers);
+#include "__call_policies.pypp.hpp"
+#include "__convenience.pypp.hpp"
+#include "PythonCoreList.h"
+#include "FormFactorSphereUniformRadius.pypp.h"
+
+namespace bp = boost::python;
+
+struct FormFactorSphereUniformRadius_wrapper : FormFactorSphereUniformRadius, bp::wrapper< FormFactorSphereUniformRadius > {
+
+    FormFactorSphereUniformRadius_wrapper(double mean, double full_width )
+    : FormFactorSphereUniformRadius( mean, full_width )
+      , bp::wrapper< FormFactorSphereUniformRadius >(){
+        // constructor
+    
+    }
+
+    virtual ::FormFactorSphereUniformRadius * clone(  ) const  {
+        if( bp::override func_clone = this->get_override( "clone" ) )
+            return func_clone(  );
+        else{
+            return this->FormFactorSphereUniformRadius::clone(  );
+        }
+    }
+    
+    ::FormFactorSphereUniformRadius * default_clone(  ) const  {
+        return FormFactorSphereUniformRadius::clone( );
+    }
+
+    virtual void createDistributedFormFactors( ::std::vector< IFormFactor* > & form_factors, ::std::vector< double > & probabilities, ::size_t nbr_samples ) const  {
+        if( bp::override func_createDistributedFormFactors = this->get_override( "createDistributedFormFactors" ) )
+            func_createDistributedFormFactors( boost::ref(form_factors), boost::ref(probabilities), nbr_samples );
+        else{
+            this->FormFactorSphereUniformRadius::createDistributedFormFactors( boost::ref(form_factors), boost::ref(probabilities), nbr_samples );
+        }
+    }
+    
+    void default_createDistributedFormFactors( ::std::vector< IFormFactor* > & form_factors, ::std::vector< double > & probabilities, ::size_t nbr_samples ) const  {
+        FormFactorSphereUniformRadius::createDistributedFormFactors( boost::ref(form_factors), boost::ref(probabilities), nbr_samples );
+    }
+
+    virtual ::complex_t evaluate_for_q( ::cvector_t const & q ) const  {
+        if( bp::override func_evaluate_for_q = this->get_override( "evaluate_for_q" ) )
+            return func_evaluate_for_q( boost::ref(q) );
+        else{
+            return this->FormFactorSphereUniformRadius::evaluate_for_q( boost::ref(q) );
+        }
+    }
+    
+    ::complex_t default_evaluate_for_q( ::cvector_t const & q ) const  {
+        return FormFactorSphereUniformRadius::evaluate_for_q( boost::ref(q) );
+    }
+
+    virtual double getHeight(  ) const  {
+        if( bp::override func_getHeight = this->get_override( "getHeight" ) )
+            return func_getHeight(  );
+        else{
+            return this->FormFactorSphereUniformRadius::getHeight(  );
+        }
+    }
+    
+    double default_getHeight(  ) const  {
+        return FormFactorSphereUniformRadius::getHeight( );
+    }
+
+    virtual int getNumberOfStochasticParameters(  ) const  {
+        if( bp::override func_getNumberOfStochasticParameters = this->get_override( "getNumberOfStochasticParameters" ) )
+            return func_getNumberOfStochasticParameters(  );
+        else{
+            return this->FormFactorSphereUniformRadius::getNumberOfStochasticParameters(  );
+        }
+    }
+    
+    int default_getNumberOfStochasticParameters(  ) const  {
+        return FormFactorSphereUniformRadius::getNumberOfStochasticParameters( );
+    }
+
+    virtual bool isDistributedFormFactor(  ) const  {
+        if( bp::override func_isDistributedFormFactor = this->get_override( "isDistributedFormFactor" ) )
+            return func_isDistributedFormFactor(  );
+        else{
+            return this->FormFactorSphereUniformRadius::isDistributedFormFactor(  );
+        }
+    }
+    
+    bool default_isDistributedFormFactor(  ) const  {
+        return FormFactorSphereUniformRadius::isDistributedFormFactor( );
+    }
+
+    virtual bool areParametersChanged(  ) {
+        if( bp::override func_areParametersChanged = this->get_override( "areParametersChanged" ) )
+            return func_areParametersChanged(  );
+        else{
+            return this->IParameterized::areParametersChanged(  );
+        }
+    }
+    
+    bool default_areParametersChanged(  ) {
+        return IParameterized::areParametersChanged( );
+    }
+
+    virtual void clearParameterPool(  ) {
+        if( bp::override func_clearParameterPool = this->get_override( "clearParameterPool" ) )
+            func_clearParameterPool(  );
+        else{
+            this->IParameterized::clearParameterPool(  );
+        }
+    }
+    
+    void default_clearParameterPool(  ) {
+        IParameterized::clearParameterPool( );
+    }
+
+    virtual ::ISample * cloneInvertB(  ) const  {
+        if( bp::override func_cloneInvertB = this->get_override( "cloneInvertB" ) )
+            return func_cloneInvertB(  );
+        else{
+            return this->ISample::cloneInvertB(  );
+        }
+    }
+    
+    ::ISample * default_cloneInvertB(  ) const  {
+        return ISample::cloneInvertB( );
+    }
+
+    virtual bool containsMagneticMaterial(  ) const  {
+        if( bp::override func_containsMagneticMaterial = this->get_override( "containsMagneticMaterial" ) )
+            return func_containsMagneticMaterial(  );
+        else{
+            return this->ISample::containsMagneticMaterial(  );
+        }
+    }
+    
+    bool default_containsMagneticMaterial(  ) const  {
+        return ISample::containsMagneticMaterial( );
+    }
+
+    virtual ::ParameterPool * createParameterTree(  ) const  {
+        if( bp::override func_createParameterTree = this->get_override( "createParameterTree" ) )
+            return func_createParameterTree(  );
+        else{
+            return this->IParameterized::createParameterTree(  );
+        }
+    }
+    
+    ::ParameterPool * default_createParameterTree(  ) const  {
+        return IParameterized::createParameterTree( );
+    }
+
+    virtual ::complex_t evaluate( ::cvector_t const & k_i, ::Bin1DCVector const & k_f_bin, ::Bin1D alpha_f_bin ) const  {
+        if( bp::override func_evaluate = this->get_override( "evaluate" ) )
+            return func_evaluate( boost::ref(k_i), boost::ref(k_f_bin), alpha_f_bin );
+        else{
+            return this->IFormFactorBorn::evaluate( boost::ref(k_i), boost::ref(k_f_bin), alpha_f_bin );
+        }
+    }
+    
+    ::complex_t default_evaluate( ::cvector_t const & k_i, ::Bin1DCVector const & k_f_bin, ::Bin1D alpha_f_bin ) const  {
+        return IFormFactorBorn::evaluate( boost::ref(k_i), boost::ref(k_f_bin), alpha_f_bin );
+    }
+
+    virtual ::ICompositeSample * getCompositeSample(  ) {
+        if( bp::override func_getCompositeSample = this->get_override( "getCompositeSample" ) )
+            return func_getCompositeSample(  );
+        else{
+            return this->ISample::getCompositeSample(  );
+        }
+    }
+    
+    ::ICompositeSample * default_getCompositeSample(  ) {
+        return ISample::getCompositeSample( );
+    }
+
+    virtual ::ICompositeSample const * getCompositeSample(  ) const  {
+        if( bp::override func_getCompositeSample = this->get_override( "getCompositeSample" ) )
+            return func_getCompositeSample(  );
+        else{
+            return this->ISample::getCompositeSample(  );
+        }
+    }
+    
+    ::ICompositeSample const * default_getCompositeSample(  ) const  {
+        return ISample::getCompositeSample( );
+    }
+
+    virtual double getRadius(  ) const  {
+        if( bp::override func_getRadius = this->get_override( "getRadius" ) )
+            return func_getRadius(  );
+        else{
+            return this->IFormFactor::getRadius(  );
+        }
+    }
+    
+    double default_getRadius(  ) const  {
+        return IFormFactor::getRadius( );
+    }
+
+    virtual double getVolume(  ) const  {
+        if( bp::override func_getVolume = this->get_override( "getVolume" ) )
+            return func_getVolume(  );
+        else{
+            return this->IFormFactorBorn::getVolume(  );
+        }
+    }
+    
+    double default_getVolume(  ) const  {
+        return IFormFactorBorn::getVolume( );
+    }
+
+    virtual void printParameters(  ) const  {
+        if( bp::override func_printParameters = this->get_override( "printParameters" ) )
+            func_printParameters(  );
+        else{
+            this->IParameterized::printParameters(  );
+        }
+    }
+    
+    void default_printParameters(  ) const  {
+        IParameterized::printParameters( );
+    }
+
+    virtual void printSampleTree(  ) {
+        if( bp::override func_printSampleTree = this->get_override( "printSampleTree" ) )
+            func_printSampleTree(  );
+        else{
+            this->ISample::printSampleTree(  );
+        }
+    }
+    
+    void default_printSampleTree(  ) {
+        ISample::printSampleTree( );
+    }
+
+    virtual void registerParameter( ::std::string const & name, double * parpointer ) {
+        namespace bpl = boost::python;
+        if( bpl::override func_registerParameter = this->get_override( "registerParameter" ) ){
+            bpl::object py_result = bpl::call<bpl::object>( func_registerParameter.ptr(), name, parpointer );
+        }
+        else{
+            IParameterized::registerParameter( name, parpointer );
+        }
+    }
+    
+    static void default_registerParameter( ::IParameterized & inst, ::std::string const & name, long unsigned int parpointer ){
+        if( dynamic_cast< FormFactorSphereUniformRadius_wrapper * >( boost::addressof( inst ) ) ){
+            inst.::IParameterized::registerParameter(name, reinterpret_cast< double * >( parpointer ));
+        }
+        else{
+            inst.registerParameter(name, reinterpret_cast< double * >( parpointer ));
+        }
+    }
+
+    virtual bool setParameterValue( ::std::string const & name, double value ) {
+        if( bp::override func_setParameterValue = this->get_override( "setParameterValue" ) )
+            return func_setParameterValue( name, value );
+        else{
+            return this->IParameterized::setParameterValue( name, value );
+        }
+    }
+    
+    bool default_setParameterValue( ::std::string const & name, double value ) {
+        return IParameterized::setParameterValue( name, value );
+    }
+
+    virtual void setParametersAreChanged(  ) {
+        if( bp::override func_setParametersAreChanged = this->get_override( "setParametersAreChanged" ) )
+            func_setParametersAreChanged(  );
+        else{
+            this->IParameterized::setParametersAreChanged(  );
+        }
+    }
+    
+    void default_setParametersAreChanged(  ) {
+        IParameterized::setParametersAreChanged( );
+    }
+
+};
+
+void register_FormFactorSphereUniformRadius_class(){
+
+    { //::FormFactorSphereUniformRadius
+        typedef bp::class_< FormFactorSphereUniformRadius_wrapper, bp::bases< IFormFactorBorn >, boost::noncopyable > FormFactorSphereUniformRadius_exposer_t;
+        FormFactorSphereUniformRadius_exposer_t FormFactorSphereUniformRadius_exposer = FormFactorSphereUniformRadius_exposer_t( "FormFactorSphereUniformRadius", bp::init< double, double >(( bp::arg("mean"), bp::arg("full_width") )) );
+        bp::scope FormFactorSphereUniformRadius_scope( FormFactorSphereUniformRadius_exposer );
+        { //::FormFactorSphereUniformRadius::clone
+        
+            typedef ::FormFactorSphereUniformRadius * ( ::FormFactorSphereUniformRadius::*clone_function_type )(  ) const;
+            typedef ::FormFactorSphereUniformRadius * ( FormFactorSphereUniformRadius_wrapper::*default_clone_function_type )(  ) const;
+            
+            FormFactorSphereUniformRadius_exposer.def( 
+                "clone"
+                , clone_function_type(&::FormFactorSphereUniformRadius::clone)
+                , default_clone_function_type(&FormFactorSphereUniformRadius_wrapper::default_clone)
+                , bp::return_value_policy< bp::manage_new_object >() );
+        
+        }
+        { //::FormFactorSphereUniformRadius::createDistributedFormFactors
+        
+            typedef void ( ::FormFactorSphereUniformRadius::*createDistributedFormFactors_function_type )( ::std::vector< IFormFactor* > &,::std::vector< double > &,::size_t ) const;
+            typedef void ( FormFactorSphereUniformRadius_wrapper::*default_createDistributedFormFactors_function_type )( ::std::vector< IFormFactor* > &,::std::vector< double > &,::size_t ) const;
+            
+            FormFactorSphereUniformRadius_exposer.def( 
+                "createDistributedFormFactors"
+                , createDistributedFormFactors_function_type(&::FormFactorSphereUniformRadius::createDistributedFormFactors)
+                , default_createDistributedFormFactors_function_type(&FormFactorSphereUniformRadius_wrapper::default_createDistributedFormFactors)
+                , ( bp::arg("form_factors"), bp::arg("probabilities"), bp::arg("nbr_samples") )
+                , bp::return_value_policy< bp::manage_new_object >() );
+        
+        }
+        { //::FormFactorSphereUniformRadius::evaluate_for_q
+        
+            typedef ::complex_t ( ::FormFactorSphereUniformRadius::*evaluate_for_q_function_type )( ::cvector_t const & ) const;
+            typedef ::complex_t ( FormFactorSphereUniformRadius_wrapper::*default_evaluate_for_q_function_type )( ::cvector_t const & ) const;
+            
+            FormFactorSphereUniformRadius_exposer.def( 
+                "evaluate_for_q"
+                , evaluate_for_q_function_type(&::FormFactorSphereUniformRadius::evaluate_for_q)
+                , default_evaluate_for_q_function_type(&FormFactorSphereUniformRadius_wrapper::default_evaluate_for_q)
+                , ( bp::arg("q") ) );
+        
+        }
+        { //::FormFactorSphereUniformRadius::getHeight
+        
+            typedef double ( ::FormFactorSphereUniformRadius::*getHeight_function_type )(  ) const;
+            typedef double ( FormFactorSphereUniformRadius_wrapper::*default_getHeight_function_type )(  ) const;
+            
+            FormFactorSphereUniformRadius_exposer.def( 
+                "getHeight"
+                , getHeight_function_type(&::FormFactorSphereUniformRadius::getHeight)
+                , default_getHeight_function_type(&FormFactorSphereUniformRadius_wrapper::default_getHeight) );
+        
+        }
+        { //::FormFactorSphereUniformRadius::getNumberOfStochasticParameters
+        
+            typedef int ( ::FormFactorSphereUniformRadius::*getNumberOfStochasticParameters_function_type )(  ) const;
+            typedef int ( FormFactorSphereUniformRadius_wrapper::*default_getNumberOfStochasticParameters_function_type )(  ) const;
+            
+            FormFactorSphereUniformRadius_exposer.def( 
+                "getNumberOfStochasticParameters"
+                , getNumberOfStochasticParameters_function_type(&::FormFactorSphereUniformRadius::getNumberOfStochasticParameters)
+                , default_getNumberOfStochasticParameters_function_type(&FormFactorSphereUniformRadius_wrapper::default_getNumberOfStochasticParameters) );
+        
+        }
+        { //::FormFactorSphereUniformRadius::isDistributedFormFactor
+        
+            typedef bool ( ::FormFactorSphereUniformRadius::*isDistributedFormFactor_function_type )(  ) const;
+            typedef bool ( FormFactorSphereUniformRadius_wrapper::*default_isDistributedFormFactor_function_type )(  ) const;
+            
+            FormFactorSphereUniformRadius_exposer.def( 
+                "isDistributedFormFactor"
+                , isDistributedFormFactor_function_type(&::FormFactorSphereUniformRadius::isDistributedFormFactor)
+                , default_isDistributedFormFactor_function_type(&FormFactorSphereUniformRadius_wrapper::default_isDistributedFormFactor) );
+        
+        }
+        { //::IParameterized::areParametersChanged
+        
+            typedef bool ( ::IParameterized::*areParametersChanged_function_type )(  ) ;
+            typedef bool ( FormFactorSphereUniformRadius_wrapper::*default_areParametersChanged_function_type )(  ) ;
+            
+            FormFactorSphereUniformRadius_exposer.def( 
+                "areParametersChanged"
+                , areParametersChanged_function_type(&::IParameterized::areParametersChanged)
+                , default_areParametersChanged_function_type(&FormFactorSphereUniformRadius_wrapper::default_areParametersChanged) );
+        
+        }
+        { //::IParameterized::clearParameterPool
+        
+            typedef void ( ::IParameterized::*clearParameterPool_function_type )(  ) ;
+            typedef void ( FormFactorSphereUniformRadius_wrapper::*default_clearParameterPool_function_type )(  ) ;
+            
+            FormFactorSphereUniformRadius_exposer.def( 
+                "clearParameterPool"
+                , clearParameterPool_function_type(&::IParameterized::clearParameterPool)
+                , default_clearParameterPool_function_type(&FormFactorSphereUniformRadius_wrapper::default_clearParameterPool) );
+        
+        }
+        { //::ISample::cloneInvertB
+        
+            typedef ::ISample * ( ::ISample::*cloneInvertB_function_type )(  ) const;
+            typedef ::ISample * ( FormFactorSphereUniformRadius_wrapper::*default_cloneInvertB_function_type )(  ) const;
+            
+            FormFactorSphereUniformRadius_exposer.def( 
+                "cloneInvertB"
+                , cloneInvertB_function_type(&::ISample::cloneInvertB)
+                , default_cloneInvertB_function_type(&FormFactorSphereUniformRadius_wrapper::default_cloneInvertB)
+                , bp::return_value_policy< bp::reference_existing_object >() );
+        
+        }
+        { //::ISample::containsMagneticMaterial
+        
+            typedef bool ( ::ISample::*containsMagneticMaterial_function_type )(  ) const;
+            typedef bool ( FormFactorSphereUniformRadius_wrapper::*default_containsMagneticMaterial_function_type )(  ) const;
+            
+            FormFactorSphereUniformRadius_exposer.def( 
+                "containsMagneticMaterial"
+                , containsMagneticMaterial_function_type(&::ISample::containsMagneticMaterial)
+                , default_containsMagneticMaterial_function_type(&FormFactorSphereUniformRadius_wrapper::default_containsMagneticMaterial) );
+        
+        }
+        { //::IParameterized::createParameterTree
+        
+            typedef ::ParameterPool * ( ::IParameterized::*createParameterTree_function_type )(  ) const;
+            typedef ::ParameterPool * ( FormFactorSphereUniformRadius_wrapper::*default_createParameterTree_function_type )(  ) const;
+            
+            FormFactorSphereUniformRadius_exposer.def( 
+                "createParameterTree"
+                , createParameterTree_function_type(&::IParameterized::createParameterTree)
+                , default_createParameterTree_function_type(&FormFactorSphereUniformRadius_wrapper::default_createParameterTree)
+                , bp::return_value_policy< bp::manage_new_object >() );
+        
+        }
+        { //::IFormFactorBorn::evaluate
+        
+            typedef ::complex_t ( ::IFormFactorBorn::*evaluate_function_type )( ::cvector_t const &,::Bin1DCVector const &,::Bin1D ) const;
+            typedef ::complex_t ( FormFactorSphereUniformRadius_wrapper::*default_evaluate_function_type )( ::cvector_t const &,::Bin1DCVector const &,::Bin1D ) const;
+            
+            FormFactorSphereUniformRadius_exposer.def( 
+                "evaluate"
+                , evaluate_function_type(&::IFormFactorBorn::evaluate)
+                , default_evaluate_function_type(&FormFactorSphereUniformRadius_wrapper::default_evaluate)
+                , ( bp::arg("k_i"), bp::arg("k_f_bin"), bp::arg("alpha_f_bin") ) );
+        
+        }
+        { //::ISample::getCompositeSample
+        
+            typedef ::ICompositeSample * ( ::ISample::*getCompositeSample_function_type )(  ) ;
+            typedef ::ICompositeSample * ( FormFactorSphereUniformRadius_wrapper::*default_getCompositeSample_function_type )(  ) ;
+            
+            FormFactorSphereUniformRadius_exposer.def( 
+                "getCompositeSample"
+                , getCompositeSample_function_type(&::ISample::getCompositeSample)
+                , default_getCompositeSample_function_type(&FormFactorSphereUniformRadius_wrapper::default_getCompositeSample)
+                , bp::return_value_policy< bp::reference_existing_object >() );
+        
+        }
+        { //::ISample::getCompositeSample
+        
+            typedef ::ICompositeSample const * ( ::ISample::*getCompositeSample_function_type )(  ) const;
+            typedef ::ICompositeSample const * ( FormFactorSphereUniformRadius_wrapper::*default_getCompositeSample_function_type )(  ) const;
+            
+            FormFactorSphereUniformRadius_exposer.def( 
+                "getCompositeSample"
+                , getCompositeSample_function_type(&::ISample::getCompositeSample)
+                , default_getCompositeSample_function_type(&FormFactorSphereUniformRadius_wrapper::default_getCompositeSample)
+                , bp::return_value_policy< bp::reference_existing_object >() );
+        
+        }
+        { //::IFormFactor::getRadius
+        
+            typedef double ( ::IFormFactor::*getRadius_function_type )(  ) const;
+            typedef double ( FormFactorSphereUniformRadius_wrapper::*default_getRadius_function_type )(  ) const;
+            
+            FormFactorSphereUniformRadius_exposer.def( 
+                "getRadius"
+                , getRadius_function_type(&::IFormFactor::getRadius)
+                , default_getRadius_function_type(&FormFactorSphereUniformRadius_wrapper::default_getRadius) );
+        
+        }
+        { //::IFormFactorBorn::getVolume
+        
+            typedef double ( ::IFormFactorBorn::*getVolume_function_type )(  ) const;
+            typedef double ( FormFactorSphereUniformRadius_wrapper::*default_getVolume_function_type )(  ) const;
+            
+            FormFactorSphereUniformRadius_exposer.def( 
+                "getVolume"
+                , getVolume_function_type(&::IFormFactorBorn::getVolume)
+                , default_getVolume_function_type(&FormFactorSphereUniformRadius_wrapper::default_getVolume) );
+        
+        }
+        { //::IParameterized::printParameters
+        
+            typedef void ( ::IParameterized::*printParameters_function_type )(  ) const;
+            typedef void ( FormFactorSphereUniformRadius_wrapper::*default_printParameters_function_type )(  ) const;
+            
+            FormFactorSphereUniformRadius_exposer.def( 
+                "printParameters"
+                , printParameters_function_type(&::IParameterized::printParameters)
+                , default_printParameters_function_type(&FormFactorSphereUniformRadius_wrapper::default_printParameters) );
+        
+        }
+        { //::ISample::printSampleTree
+        
+            typedef void ( ::ISample::*printSampleTree_function_type )(  ) ;
+            typedef void ( FormFactorSphereUniformRadius_wrapper::*default_printSampleTree_function_type )(  ) ;
+            
+            FormFactorSphereUniformRadius_exposer.def( 
+                "printSampleTree"
+                , printSampleTree_function_type(&::ISample::printSampleTree)
+                , default_printSampleTree_function_type(&FormFactorSphereUniformRadius_wrapper::default_printSampleTree) );
+        
+        }
+        { //::IParameterized::registerParameter
+        
+            typedef void ( *default_registerParameter_function_type )( ::IParameterized &,::std::string const &,long unsigned int );
+            
+            FormFactorSphereUniformRadius_exposer.def( 
+                "registerParameter"
+                , default_registerParameter_function_type( &FormFactorSphereUniformRadius_wrapper::default_registerParameter )
+                , ( bp::arg("inst"), bp::arg("name"), bp::arg("parpointer") ) );
+        
+        }
+        { //::IParameterized::setParameterValue
+        
+            typedef bool ( ::IParameterized::*setParameterValue_function_type )( ::std::string const &,double ) ;
+            typedef bool ( FormFactorSphereUniformRadius_wrapper::*default_setParameterValue_function_type )( ::std::string const &,double ) ;
+            
+            FormFactorSphereUniformRadius_exposer.def( 
+                "setParameterValue"
+                , setParameterValue_function_type(&::IParameterized::setParameterValue)
+                , default_setParameterValue_function_type(&FormFactorSphereUniformRadius_wrapper::default_setParameterValue)
+                , ( bp::arg("name"), bp::arg("value") ) );
+        
+        }
+        { //::IParameterized::setParametersAreChanged
+        
+            typedef void ( ::IParameterized::*setParametersAreChanged_function_type )(  ) ;
+            typedef void ( FormFactorSphereUniformRadius_wrapper::*default_setParametersAreChanged_function_type )(  ) ;
+            
+            FormFactorSphereUniformRadius_exposer.def( 
+                "setParametersAreChanged"
+                , setParametersAreChanged_function_type(&::IParameterized::setParametersAreChanged)
+                , default_setParametersAreChanged_function_type(&FormFactorSphereUniformRadius_wrapper::default_setParametersAreChanged) );
+        
+        }
+    }
+
+}
diff --git a/Core/PythonAPI/src/PythonModule.cpp b/Core/PythonAPI/src/PythonModule.cpp
index ca90597c290..2362add4bc3 100644
--- a/Core/PythonAPI/src/PythonModule.cpp
+++ b/Core/PythonAPI/src/PythonModule.cpp
@@ -32,6 +32,7 @@
 #include "FormFactorPyramid.pypp.h" 
 #include "FormFactorSphere.pypp.h" 
 #include "FormFactorSphereGaussianRadius.pypp.h" 
+#include "FormFactorSphereUniformRadius.pypp.h" 
 #include "FormFactorSpheroid.pypp.h" 
 #include "FTDistribution2DCauchy.pypp.h" 
 #include "HomogeneousMaterial.pypp.h" 
@@ -149,6 +150,7 @@ BOOST_PYTHON_MODULE(libBornAgainCore){
     register_FormFactorPyramid_class();
     register_FormFactorSphere_class();
     register_FormFactorSphereGaussianRadius_class();
+    register_FormFactorSphereUniformRadius_class();
     register_FormFactorSpheroid_class();
     register_kvector_t_class();
     register_cvector_t_class();
diff --git a/Core/StandardSamples/MesoCrystal01Builder.cpp b/Core/StandardSamples/MesoCrystal01Builder.cpp
index 50ea1b84f43..a96738dc24b 100644
--- a/Core/StandardSamples/MesoCrystal01Builder.cpp
+++ b/Core/StandardSamples/MesoCrystal01Builder.cpp
@@ -13,18 +13,18 @@
 
 
 MesoCrystal01Builder::MesoCrystal01Builder()
-    : m_lattice_length_a(6.2091e+00*Units::nanometer)
-    , m_lattice_length_c(6.5677e+00*Units::nanometer)
-    , m_nanoparticle_radius(4.6976e+00*Units::nanometer)
-    , m_sigma_nanoparticle_radius(3.6720e-01*Units::nanometer)
-    , m_meso_height(1.1221e+02*Units::nanometer)
-    , m_meso_radius(9.4567e+02*Units::nanometer)
-    , m_sigma_meso_height(1.3310e+00*Units::nanometer)
-    , m_sigma_meso_radius(1.3863e+00*Units::nanometer)
-    , m_sigma_lattice_length_a(1.1601e+00*Units::nanometer)
-    , m_surface_filling_ratio(1.7286e-01)
-    , m_roughness(2.8746e+01*Units::nanometer)
-    , m_nphi_rotations(2)
+: m_lattice_length_a(6.2091e+00*Units::nanometer)
+, m_lattice_length_c(6.5677e+00*Units::nanometer)
+, m_nanoparticle_radius(4.6976e+00*Units::nanometer)
+, m_sigma_nanoparticle_radius(3.6720e-01*Units::nanometer)
+, m_meso_height(1.1221e+02*Units::nanometer)
+, m_meso_radius(9.4567e+02*Units::nanometer)
+, m_sigma_meso_height(1.3310e+00*Units::nanometer)
+, m_sigma_meso_radius(1.3863e+00*Units::nanometer)
+, m_sigma_lattice_length_a(1.1601e+00*Units::nanometer)
+, m_surface_filling_ratio(1.7286e-01)
+, m_roughness(2.8746e+01*Units::nanometer)
+, m_nphi_rotations(2)
 {
     init_parameters();
 }
diff --git a/Core/python_module.pri b/Core/python_module.pri
index 86e6a14ce40..2c2ce09a1cf 100644
--- a/Core/python_module.pri
+++ b/Core/python_module.pri
@@ -32,6 +32,7 @@ HEADERS +=  \
     PythonAPI/inc/FormFactorPyramid.pypp.h \
     PythonAPI/inc/FormFactorSphere.pypp.h \
     PythonAPI/inc/FormFactorSphereGaussianRadius.pypp.h \
+    PythonAPI/inc/FormFactorSphereUniformRadius.pypp.h \
     PythonAPI/inc/FormFactorSpheroid.pypp.h \
     PythonAPI/inc/FTDistribution2DCauchy.pypp.h \
     PythonAPI/inc/HomogeneousMaterial.pypp.h \
@@ -132,6 +133,7 @@ SOURCES +=  \
     PythonAPI/src/FormFactorPyramid.pypp.cpp \
     PythonAPI/src/FormFactorSphere.pypp.cpp \
     PythonAPI/src/FormFactorSphereGaussianRadius.pypp.cpp \
+    PythonAPI/src/FormFactorSphereUniformRadius.pypp.cpp \
     PythonAPI/src/FormFactorSpheroid.pypp.cpp \
     PythonAPI/src/FTDistribution2DCauchy.pypp.cpp \
     PythonAPI/src/HomogeneousMaterial.pypp.cpp \
diff --git a/dev-tools/python-bindings/MakePyCore.py b/dev-tools/python-bindings/MakePyCore.py
index 2b8116030eb..9c4dbff3d96 100644
--- a/dev-tools/python-bindings/MakePyCore.py
+++ b/dev-tools/python-bindings/MakePyCore.py
@@ -60,6 +60,7 @@ include_classes = [
     "FormFactorPyramid",
     "FormFactorSphere",
     "FormFactorSphereGaussianRadius",
+    "FormFactorSphereUniformRadius",
     "FormFactorSpheroid",
     "HomogeneousMaterial",
     "IAxis",
-- 
GitLab