From 88a78371407db48614637bdcaae1431a6c152352 Mon Sep 17 00:00:00 2001
From: Walter Van Herck <w.van.herck@fz-juelich.de>
Date: Fri, 28 Nov 2014 14:42:06 +0100
Subject: [PATCH] Added ParticleCollection and IParticle interface

---
 Core/Algorithms/inc/DiffuseDWBASimulation.h   |   6 +-
 Core/Algorithms/inc/Distributions.h           |  77 +--
 Core/Algorithms/src/DiffuseDWBASimulation.cpp |   7 +-
 Core/Algorithms/src/DistributionHandler.cpp   |  72 +--
 Core/Algorithms/src/Distributions.cpp         |  66 ++-
 Core/Algorithms/src/LayerStrategyBuilder.cpp  |   2 +-
 Core/PythonAPI/inc/IParticle.pypp.h           |  11 +
 Core/PythonAPI/inc/PythonCoreList.h           |   1 +
 .../PythonAPI/src/DistributionCosine.pypp.cpp |  10 +-
 Core/PythonAPI/src/DistributionGate.pypp.cpp  |  10 +-
 .../src/DistributionGaussian.pypp.cpp         |  10 +-
 .../src/DistributionLogNormal.pypp.cpp        |  10 +-
 .../src/DistributionLorentz.pypp.cpp          |  10 +-
 Core/PythonAPI/src/IParticle.pypp.cpp         | 555 ++++++++++++++++++
 Core/PythonAPI/src/LatticeBasis.pypp.cpp      |  20 +-
 Core/PythonAPI/src/MesoCrystal.pypp.cpp       |  20 +-
 Core/PythonAPI/src/Particle.pypp.cpp          |  84 ++-
 Core/PythonAPI/src/ParticleCoreShell.pypp.cpp |  20 +-
 Core/PythonAPI/src/ParticleInfo.pypp.cpp      |   6 +-
 Core/PythonAPI/src/ParticleLayout.pypp.cpp    |  12 +-
 .../src/PositionParticleInfo.pypp.cpp         |  14 +-
 Core/PythonAPI/src/PythonModule.cpp           |   3 +
 Core/Samples/inc/DiffuseParticleInfo.h        |   2 +-
 Core/Samples/inc/IParticle.h                  | 142 +++++
 Core/Samples/inc/ISampleVisitor.h             |   2 +
 Core/Samples/inc/Particle.h                   |  18 +-
 Core/Samples/inc/ParticleCollection.h         |  93 +++
 Core/Samples/inc/ParticleInfo.h               |  18 +-
 Core/Samples/inc/ParticleLayout.h             |   6 +-
 Core/Samples/inc/PositionParticleInfo.h       |   7 +-
 Core/Samples/src/ISampleVisitor.cpp           |   5 +
 Core/Samples/src/Particle.cpp                 |  33 +-
 Core/Samples/src/ParticleCollection.cpp       |  59 ++
 Core/Samples/src/ParticleInfo.cpp             |  12 +-
 Core/Samples/src/ParticleLayout.cpp           |  12 +-
 Core/Samples/src/PositionParticleInfo.cpp     |   6 +-
 Core/Tools/inc/Compare.h                      |   4 +-
 Core/Tools/inc/LabelSample.h                  |   4 +-
 Core/Tools/inc/ParameterDistribution.h        |  42 +-
 Core/Tools/src/Compare.cpp                    |   2 +-
 Core/Tools/src/LabelSample.cpp                |  10 +-
 Core/Tools/src/ParameterDistribution.cpp      |  63 +-
 dev-tools/python-bindings/settings_core.py    |   3 +-
 43 files changed, 1236 insertions(+), 333 deletions(-)
 create mode 100644 Core/PythonAPI/inc/IParticle.pypp.h
 create mode 100644 Core/PythonAPI/src/IParticle.pypp.cpp
 create mode 100644 Core/Samples/inc/IParticle.h
 create mode 100644 Core/Samples/inc/ParticleCollection.h
 create mode 100644 Core/Samples/src/ParticleCollection.cpp

diff --git a/Core/Algorithms/inc/DiffuseDWBASimulation.h b/Core/Algorithms/inc/DiffuseDWBASimulation.h
index 4983e2f2bf7..907eb1efac8 100644
--- a/Core/Algorithms/inc/DiffuseDWBASimulation.h
+++ b/Core/Algorithms/inc/DiffuseDWBASimulation.h
@@ -59,11 +59,7 @@ private:
     struct DiffuseFormFactorTerm {
         DiffuseFormFactorTerm()
             : m_form_factors(), m_probabilities(), m_factor(0.) {}
-        ~DiffuseFormFactorTerm()
-        {
-            for (size_t i=0; i<m_form_factors.size(); ++i)
-                delete m_form_factors[i];
-        }
+        ~DiffuseFormFactorTerm();
         std::vector<IFormFactor*> m_form_factors;
         std::vector<double> m_probabilities;
         double m_factor;
diff --git a/Core/Algorithms/inc/Distributions.h b/Core/Algorithms/inc/Distributions.h
index 645e7d7069f..8dd6cc96b1e 100644
--- a/Core/Algorithms/inc/Distributions.h
+++ b/Core/Algorithms/inc/Distributions.h
@@ -30,7 +30,7 @@ public:
 
     //! clone method
     virtual IDistribution1D *clone() const {
-    	throw NotImplementedException("IDistribution1D cannot be cloned");
+        throw NotImplementedException("IDistribution1D cannot be cloned");
     }
 
     //! get the probability density for value x
@@ -41,7 +41,7 @@ public:
 
     //! generate list of sampled values with their weight
     std::vector<ParameterSample> generateSamples(size_t nbr_samples,
-    		double sigma_factor=0.0) const;
+            double sigma_factor=0.0) const;
 
     //! generate list of sample values
     virtual std::vector<double> generateValueList(size_t nbr_samples,
@@ -59,25 +59,26 @@ protected:
 class BA_CORE_API_ DistributionGate : public IDistribution1D
 {
 public:
-	DistributionGate(double mean, double hwhm);
-	virtual ~DistributionGate() {}
+    DistributionGate();
+    DistributionGate(double mean, double hwhm);
+    virtual ~DistributionGate() {}
 
     //! clone method
-	virtual DistributionGate *clone() const {
-		return new DistributionGate(m_mean, m_hwhm);
-	}
+    virtual DistributionGate *clone() const {
+        return new DistributionGate(m_mean, m_hwhm);
+    }
 
     //! get the probability density for value x
     virtual double probabilityDensity(double x) const;
 
     //! get the mean of the distribution
     virtual double getMean() const {
-    	return m_mean;
+        return m_mean;
     }
 
     //! generate list of sample values
     virtual std::vector<double> generateValueList(size_t nbr_samples,
-    		double sigma_factor) const;
+            double sigma_factor) const;
 
 protected:
     //! Registers some class members for later access via parameter pool
@@ -96,25 +97,26 @@ private:
 class BA_CORE_API_ DistributionLorentz : public IDistribution1D
 {
 public:
-	DistributionLorentz(double mean, double hwhm);
-	virtual ~DistributionLorentz() {}
+    DistributionLorentz();
+    DistributionLorentz(double mean, double hwhm);
+    virtual ~DistributionLorentz() {}
 
     //! clone method
-	virtual DistributionLorentz *clone() const {
-		return new DistributionLorentz(m_mean, m_hwhm);
-	}
+    virtual DistributionLorentz *clone() const {
+        return new DistributionLorentz(m_mean, m_hwhm);
+    }
 
     //! get the probability density for value x
     virtual double probabilityDensity(double x) const;
 
     //! get the mean of the distribution
     virtual double getMean() const {
-    	return m_mean;
+        return m_mean;
     }
 
     //! generate list of sample values
     virtual std::vector<double> generateValueList(size_t nbr_samples,
-    		double sigma_factor) const;
+            double sigma_factor) const;
 
 protected:
     //! Registers some class members for later access via parameter pool
@@ -132,25 +134,26 @@ private:
 class BA_CORE_API_ DistributionGaussian: public IDistribution1D
 {
 public:
-	DistributionGaussian(double mean, double std_dev);
-	virtual ~DistributionGaussian() {}
+    DistributionGaussian();
+    DistributionGaussian(double mean, double std_dev);
+    virtual ~DistributionGaussian() {}
 
     //! clone method
-	virtual DistributionGaussian *clone() const {
-		return new DistributionGaussian(m_mean, m_std_dev);
-	}
+    virtual DistributionGaussian *clone() const {
+        return new DistributionGaussian(m_mean, m_std_dev);
+    }
 
     //! get the probability density for value x
     virtual double probabilityDensity(double x) const;
 
     //! get the mean of the distribution
     virtual double getMean() const {
-    	return m_mean;
+        return m_mean;
     }
 
     //! generate list of sample values
     virtual std::vector<double> generateValueList(size_t nbr_samples,
-    		double sigma_factor) const;
+            double sigma_factor) const;
 
 protected:
     //! Registers some class members for later access via parameter pool
@@ -168,13 +171,14 @@ private:
 class BA_CORE_API_ DistributionLogNormal: public IDistribution1D
 {
 public:
-	DistributionLogNormal(double median, double scale_param);
-	virtual ~DistributionLogNormal() {}
+    DistributionLogNormal(double scale_param);
+    DistributionLogNormal(double median, double scale_param);
+    virtual ~DistributionLogNormal() {}
 
     //! clone method
-	virtual DistributionLogNormal *clone() const {
-		return new DistributionLogNormal(m_median, m_scale_param);
-	}
+    virtual DistributionLogNormal *clone() const {
+        return new DistributionLogNormal(m_median, m_scale_param);
+    }
 
     //! get the probability density for value x
     virtual double probabilityDensity(double x) const;
@@ -184,7 +188,7 @@ public:
 
     //! generate list of sample values
     virtual std::vector<double> generateValueList(size_t nbr_samples,
-    		double sigma_factor) const;
+            double sigma_factor) const;
 
 protected:
     //! Registers some class members for later access via parameter pool
@@ -202,25 +206,26 @@ private:
 class BA_CORE_API_ DistributionCosine: public IDistribution1D
 {
 public:
-	DistributionCosine(double mean, double sigma);
-	virtual ~DistributionCosine() {}
+    DistributionCosine();
+    DistributionCosine(double mean, double sigma);
+    virtual ~DistributionCosine() {}
 
     //! clone method
-	virtual DistributionCosine *clone() const {
-		return new DistributionCosine(m_mean, m_sigma);
-	}
+    virtual DistributionCosine *clone() const {
+        return new DistributionCosine(m_mean, m_sigma);
+    }
 
     //! get the probability density for value x
     virtual double probabilityDensity(double x) const;
 
     //! get the mean of the distribution
     virtual double getMean() const {
-    	return m_mean;
+        return m_mean;
     }
 
     //! generate list of sample values
     virtual std::vector<double> generateValueList(size_t nbr_samples,
-    		double sigma_factor) const;
+            double sigma_factor) const;
 
 protected:
     //! Registers some class members for later access via parameter pool
diff --git a/Core/Algorithms/src/DiffuseDWBASimulation.cpp b/Core/Algorithms/src/DiffuseDWBASimulation.cpp
index b28b903a873..680004d6d6e 100644
--- a/Core/Algorithms/src/DiffuseDWBASimulation.cpp
+++ b/Core/Algorithms/src/DiffuseDWBASimulation.cpp
@@ -175,7 +175,7 @@ void DiffuseDWBASimulation::initDiffuseFormFactorTerms(
     msglog(MSG::DEBUG2) << "DiffuseDWBASimulation::init...()";
     for (size_t i=0; i<m_np_infos.size(); ++i) {
         DiffuseParticleInfo *p_diff_info = m_np_infos[i];
-        Particle *p_particle = p_diff_info->getParticle()->clone();
+        IParticle *p_particle = p_diff_info->getParticle()->clone();
         double total_particle_density = p_diff_info->getNumberPerMeso();
         double density_per_height_per_particle =
             total_particle_density/nbr_heights;
@@ -210,3 +210,8 @@ void DiffuseDWBASimulation::initDiffuseFormFactorTerms(
     }
 }
 
+DiffuseDWBASimulation::DiffuseFormFactorTerm::~DiffuseFormFactorTerm()
+{
+    for (size_t i=0; i<m_form_factors.size(); ++i)
+        delete m_form_factors[i];
+}
diff --git a/Core/Algorithms/src/DistributionHandler.cpp b/Core/Algorithms/src/DistributionHandler.cpp
index 483efe16787..b8e82078cb7 100644
--- a/Core/Algorithms/src/DistributionHandler.cpp
+++ b/Core/Algorithms/src/DistributionHandler.cpp
@@ -25,49 +25,49 @@ DistributionHandler::~DistributionHandler()
 }
 
 void DistributionHandler::addParameterDistribution(
-		const std::string &param_name, const IDistribution1D &distribution,
-		size_t nbr_samples, double sigma_factor)
+        const std::string &param_name, const IDistribution1D &distribution,
+        size_t nbr_samples, double sigma_factor)
 {
-	if (nbr_samples > 0) {
-		ParameterDistribution par_distr(param_name);
-		par_distr.setDistribution(distribution, nbr_samples, sigma_factor);
-		m_distributions.push_back(par_distr);
-		m_nbr_combinations *= nbr_samples;
-		m_cached_samples.push_back(par_distr.generateSamples());
-	}
+    if (nbr_samples > 0) {
+        ParameterDistribution par_distr(param_name, distribution,
+                                        nbr_samples, sigma_factor);
+        m_distributions.push_back(par_distr);
+        m_nbr_combinations *= nbr_samples;
+        m_cached_samples.push_back(par_distr.generateSamples());
+    }
 }
 
 size_t DistributionHandler::getTotalNumberOfSamples() const
 {
-	return m_nbr_combinations;
+    return m_nbr_combinations;
 }
 
 double DistributionHandler::setParameterValues(ParameterPool *p_parameter_pool,
-		size_t index)
+        size_t index)
 {
-	if (index >= m_nbr_combinations) {
-		throw Exceptions::RuntimeErrorException(
-				"DistributionWeighter::setParameterValues: "
-				"index must be smaller than the total number of parameter "
-				"combinations");
-	}
-	size_t n_distr = m_distributions.size();
-	double weight = 1.0;
-	if (n_distr == 0) return weight;
-	for (size_t param_index=n_distr-1; ; --param_index) {
-		size_t remainder = index % m_distributions[param_index].getNbrSamples();
-		index /= m_distributions[param_index].getNbrSamples();
-		int changed = p_parameter_pool->setMatchedParametersValue(
-				m_distributions[param_index].getParameterName(),
-				m_cached_samples[param_index][remainder].value);
-		if (changed != 1) {
-			throw Exceptions::RuntimeErrorException(
-					"DistributionWeighter::setParameterValues: "
-					" parameter name matches nothing or more than "
-					"one parameter");
-		}
-		weight *= m_cached_samples[param_index][remainder].weight;
-		if (param_index==0) break;
-	}
-	return weight;
+    if (index >= m_nbr_combinations) {
+        throw Exceptions::RuntimeErrorException(
+                "DistributionWeighter::setParameterValues: "
+                "index must be smaller than the total number of parameter "
+                "combinations");
+    }
+    size_t n_distr = m_distributions.size();
+    double weight = 1.0;
+    if (n_distr == 0) return weight;
+    for (size_t param_index=n_distr-1; ; --param_index) {
+        size_t remainder = index % m_distributions[param_index].getNbrSamples();
+        index /= m_distributions[param_index].getNbrSamples();
+        int changed = p_parameter_pool->setMatchedParametersValue(
+                m_distributions[param_index].getMainParameterName(),
+                m_cached_samples[param_index][remainder].value);
+        if (changed != 1) {
+            throw Exceptions::RuntimeErrorException(
+                    "DistributionWeighter::setParameterValues: "
+                    " parameter name matches nothing or more than "
+                    "one parameter");
+        }
+        weight *= m_cached_samples[param_index][remainder].weight;
+        if (param_index==0) break;
+    }
+    return weight;
 }
diff --git a/Core/Algorithms/src/Distributions.cpp b/Core/Algorithms/src/Distributions.cpp
index e65d92086c0..1a9df83d16d 100644
--- a/Core/Algorithms/src/Distributions.cpp
+++ b/Core/Algorithms/src/Distributions.cpp
@@ -55,9 +55,18 @@ void IDistribution1D::SignalBadInitialization(std::string distribution_name)
 }
 
 //! DistributionGate
+DistributionGate::DistributionGate()
+    : m_mean(0.0)
+    , m_hwhm(1.0)
+    {
+        setName("DistributionGate");
+        checkInitialization();
+        init_parameters();
+    }
+
 DistributionGate::DistributionGate(double mean, double hwhm)
-: m_mean(mean)
-, m_hwhm(hwhm)
+    : m_mean(mean)
+    , m_hwhm(hwhm)
 {
     setName("DistributionGate");
     checkInitialization();
@@ -105,9 +114,18 @@ bool DistributionGate::checkInitialization() const
 }
 
 //! DistributionLorenz
+DistributionLorentz::DistributionLorentz()
+    : m_mean(0.0)
+    , m_hwhm(1.0)
+    {
+        setName("DistributionLorentz");
+        checkInitialization();
+        init_parameters();
+    }
+
 DistributionLorentz::DistributionLorentz(double mean, double hwhm)
-: m_mean(mean)
-, m_hwhm(hwhm)
+    : m_mean(mean)
+    , m_hwhm(hwhm)
 {
     setName("DistributionLorentz");
     checkInitialization();
@@ -154,9 +172,18 @@ bool DistributionLorentz::checkInitialization() const
 }
 
 //! DistributionGaussian
+DistributionGaussian::DistributionGaussian()
+    : m_mean(0.0)
+    , m_std_dev(1.0)
+{
+    setName("DistributionGaussian");
+    checkInitialization();
+    init_parameters();
+}
+
 DistributionGaussian::DistributionGaussian(double mean, double std_dev)
-: m_mean(mean)
-, m_std_dev(std_dev)
+    : m_mean(mean)
+    , m_std_dev(std_dev)
 {
     setName("DistributionGaussian");
     checkInitialization();
@@ -205,9 +232,18 @@ bool DistributionGaussian::checkInitialization() const
 }
 
 //! DistributionLogNormal
+DistributionLogNormal::DistributionLogNormal(double scale_param)
+    : m_median(1.0)
+    , m_scale_param(scale_param)
+{
+    setName("DistributionLogNormal");
+    checkInitialization();
+    init_parameters();
+}
+
 DistributionLogNormal::DistributionLogNormal(double median, double scale_param)
-: m_median(median)
-, m_scale_param(scale_param)
+    : m_median(median)
+    , m_scale_param(scale_param)
 {
     setName("DistributionLogNormal");
     checkInitialization();
@@ -262,9 +298,18 @@ bool DistributionLogNormal::checkInitialization() const
 }
 
 //! DistributionCosine
+DistributionCosine::DistributionCosine()
+    : m_mean(0.0)
+    , m_sigma(1.0)
+{
+    setName("DistributionCosine");
+    checkInitialization();
+    init_parameters();
+}
+
 DistributionCosine::DistributionCosine(double mean, double sigma)
-: m_mean(mean)
-, m_sigma(sigma)
+    : m_mean(mean)
+    , m_sigma(sigma)
 {
     setName("DistributionCosine");
     checkInitialization();
@@ -273,6 +318,7 @@ DistributionCosine::DistributionCosine(double mean, double sigma)
 
 double DistributionCosine::probabilityDensity(double x) const
 {
+    if (std::abs(x-m_mean)>M_PI*m_sigma) return 0.0;
     return (1.0 + std::cos((x-m_mean)/m_sigma))/(m_sigma*2.0*M_PI);
 }
 
diff --git a/Core/Algorithms/src/LayerStrategyBuilder.cpp b/Core/Algorithms/src/LayerStrategyBuilder.cpp
index 6e7bbeaf217..aa0bddf61cf 100644
--- a/Core/Algorithms/src/LayerStrategyBuilder.cpp
+++ b/Core/Algorithms/src/LayerStrategyBuilder.cpp
@@ -147,7 +147,7 @@ FormFactorInfo *LayerStrategyBuilder::createFormFactorInfo(
         complex_t factor) const
 {
     FormFactorInfo *p_result = new FormFactorInfo;
-    boost::scoped_ptr<Particle> P_particle_clone(p_particle_info->
+    boost::scoped_ptr<IParticle> P_particle_clone(p_particle_info->
             getParticle()->clone());
     P_particle_clone->setAmbientMaterial(p_ambient_material);
 
diff --git a/Core/PythonAPI/inc/IParticle.pypp.h b/Core/PythonAPI/inc/IParticle.pypp.h
new file mode 100644
index 00000000000..d6962c0e39c
--- /dev/null
+++ b/Core/PythonAPI/inc/IParticle.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 IParticle_hpp__pyplusplus_wrapper
+#define IParticle_hpp__pyplusplus_wrapper
+
+void register_IParticle_class();
+
+#endif//IParticle_hpp__pyplusplus_wrapper
diff --git a/Core/PythonAPI/inc/PythonCoreList.h b/Core/PythonAPI/inc/PythonCoreList.h
index d106e3aa1dd..4ee44f5f695 100644
--- a/Core/PythonAPI/inc/PythonCoreList.h
+++ b/Core/PythonAPI/inc/PythonCoreList.h
@@ -85,6 +85,7 @@
 #include "OutputDataFunctions.h"
 #include "ParameterPool.h"
 #include "ParameterSample.h"
+#include "IParticle.h"
 #include "Particle.h"
 #include "ParticleBuilder.h"
 #include "ParticleCoreShell.h"
diff --git a/Core/PythonAPI/src/DistributionCosine.pypp.cpp b/Core/PythonAPI/src/DistributionCosine.pypp.cpp
index ae23fcf7cab..e9004afca69 100644
--- a/Core/PythonAPI/src/DistributionCosine.pypp.cpp
+++ b/Core/PythonAPI/src/DistributionCosine.pypp.cpp
@@ -25,6 +25,13 @@ struct DistributionCosine_wrapper : DistributionCosine, bp::wrapper< Distributio
         m_pyobj = 0;
     }
 
+    DistributionCosine_wrapper( )
+    : DistributionCosine( )
+      , bp::wrapper< DistributionCosine >(){
+        // null constructor
+    m_pyobj = 0;
+    }
+
     DistributionCosine_wrapper(double mean, double sigma )
     : DistributionCosine( mean, sigma )
       , bp::wrapper< DistributionCosine >(){
@@ -179,8 +186,9 @@ void register_DistributionCosine_class(){
 
     { //::DistributionCosine
         typedef bp::class_< DistributionCosine_wrapper, bp::bases< IDistribution1D >, std::auto_ptr< DistributionCosine_wrapper > > DistributionCosine_exposer_t;
-        DistributionCosine_exposer_t DistributionCosine_exposer = DistributionCosine_exposer_t( "DistributionCosine", bp::init< double, double >(( bp::arg("mean"), bp::arg("sigma") )) );
+        DistributionCosine_exposer_t DistributionCosine_exposer = DistributionCosine_exposer_t( "DistributionCosine", bp::init< >() );
         bp::scope DistributionCosine_scope( DistributionCosine_exposer );
+        DistributionCosine_exposer.def( bp::init< double, double >(( bp::arg("mean"), bp::arg("sigma") )) );
         { //::DistributionCosine::clone
         
             typedef ::DistributionCosine * ( ::DistributionCosine::*clone_function_type)(  ) const;
diff --git a/Core/PythonAPI/src/DistributionGate.pypp.cpp b/Core/PythonAPI/src/DistributionGate.pypp.cpp
index 8df89d6388e..5568d6f3924 100644
--- a/Core/PythonAPI/src/DistributionGate.pypp.cpp
+++ b/Core/PythonAPI/src/DistributionGate.pypp.cpp
@@ -25,6 +25,13 @@ struct DistributionGate_wrapper : DistributionGate, bp::wrapper< DistributionGat
         m_pyobj = 0;
     }
 
+    DistributionGate_wrapper( )
+    : DistributionGate( )
+      , bp::wrapper< DistributionGate >(){
+        // null constructor
+    m_pyobj = 0;
+    }
+
     DistributionGate_wrapper(double mean, double hwhm )
     : DistributionGate( mean, hwhm )
       , bp::wrapper< DistributionGate >(){
@@ -179,8 +186,9 @@ void register_DistributionGate_class(){
 
     { //::DistributionGate
         typedef bp::class_< DistributionGate_wrapper, bp::bases< IDistribution1D >, std::auto_ptr< DistributionGate_wrapper > > DistributionGate_exposer_t;
-        DistributionGate_exposer_t DistributionGate_exposer = DistributionGate_exposer_t( "DistributionGate", bp::init< double, double >(( bp::arg("mean"), bp::arg("hwhm") )) );
+        DistributionGate_exposer_t DistributionGate_exposer = DistributionGate_exposer_t( "DistributionGate", bp::init< >() );
         bp::scope DistributionGate_scope( DistributionGate_exposer );
+        DistributionGate_exposer.def( bp::init< double, double >(( bp::arg("mean"), bp::arg("hwhm") )) );
         { //::DistributionGate::clone
         
             typedef ::DistributionGate * ( ::DistributionGate::*clone_function_type)(  ) const;
diff --git a/Core/PythonAPI/src/DistributionGaussian.pypp.cpp b/Core/PythonAPI/src/DistributionGaussian.pypp.cpp
index a77468b87f0..fcf83ec8e6d 100644
--- a/Core/PythonAPI/src/DistributionGaussian.pypp.cpp
+++ b/Core/PythonAPI/src/DistributionGaussian.pypp.cpp
@@ -25,6 +25,13 @@ struct DistributionGaussian_wrapper : DistributionGaussian, bp::wrapper< Distrib
         m_pyobj = 0;
     }
 
+    DistributionGaussian_wrapper( )
+    : DistributionGaussian( )
+      , bp::wrapper< DistributionGaussian >(){
+        // null constructor
+    m_pyobj = 0;
+    }
+
     DistributionGaussian_wrapper(double mean, double std_dev )
     : DistributionGaussian( mean, std_dev )
       , bp::wrapper< DistributionGaussian >(){
@@ -179,8 +186,9 @@ void register_DistributionGaussian_class(){
 
     { //::DistributionGaussian
         typedef bp::class_< DistributionGaussian_wrapper, bp::bases< IDistribution1D >, std::auto_ptr< DistributionGaussian_wrapper > > DistributionGaussian_exposer_t;
-        DistributionGaussian_exposer_t DistributionGaussian_exposer = DistributionGaussian_exposer_t( "DistributionGaussian", bp::init< double, double >(( bp::arg("mean"), bp::arg("std_dev") )) );
+        DistributionGaussian_exposer_t DistributionGaussian_exposer = DistributionGaussian_exposer_t( "DistributionGaussian", bp::init< >() );
         bp::scope DistributionGaussian_scope( DistributionGaussian_exposer );
+        DistributionGaussian_exposer.def( bp::init< double, double >(( bp::arg("mean"), bp::arg("std_dev") )) );
         { //::DistributionGaussian::clone
         
             typedef ::DistributionGaussian * ( ::DistributionGaussian::*clone_function_type)(  ) const;
diff --git a/Core/PythonAPI/src/DistributionLogNormal.pypp.cpp b/Core/PythonAPI/src/DistributionLogNormal.pypp.cpp
index 095b6d7f4b1..c4a85da9ecb 100644
--- a/Core/PythonAPI/src/DistributionLogNormal.pypp.cpp
+++ b/Core/PythonAPI/src/DistributionLogNormal.pypp.cpp
@@ -25,6 +25,13 @@ struct DistributionLogNormal_wrapper : DistributionLogNormal, bp::wrapper< Distr
         m_pyobj = 0;
     }
 
+    DistributionLogNormal_wrapper(double scale_param )
+    : DistributionLogNormal( scale_param )
+      , bp::wrapper< DistributionLogNormal >(){
+        // constructor
+    m_pyobj = 0;
+    }
+
     DistributionLogNormal_wrapper(double median, double scale_param )
     : DistributionLogNormal( median, scale_param )
       , bp::wrapper< DistributionLogNormal >(){
@@ -179,8 +186,9 @@ void register_DistributionLogNormal_class(){
 
     { //::DistributionLogNormal
         typedef bp::class_< DistributionLogNormal_wrapper, bp::bases< IDistribution1D >, std::auto_ptr< DistributionLogNormal_wrapper > > DistributionLogNormal_exposer_t;
-        DistributionLogNormal_exposer_t DistributionLogNormal_exposer = DistributionLogNormal_exposer_t( "DistributionLogNormal", bp::init< double, double >(( bp::arg("median"), bp::arg("scale_param") )) );
+        DistributionLogNormal_exposer_t DistributionLogNormal_exposer = DistributionLogNormal_exposer_t( "DistributionLogNormal", bp::init< double >(( bp::arg("scale_param") )) );
         bp::scope DistributionLogNormal_scope( DistributionLogNormal_exposer );
+        DistributionLogNormal_exposer.def( bp::init< double, double >(( bp::arg("median"), bp::arg("scale_param") )) );
         { //::DistributionLogNormal::clone
         
             typedef ::DistributionLogNormal * ( ::DistributionLogNormal::*clone_function_type)(  ) const;
diff --git a/Core/PythonAPI/src/DistributionLorentz.pypp.cpp b/Core/PythonAPI/src/DistributionLorentz.pypp.cpp
index da42b96dabd..af0a04c0aba 100644
--- a/Core/PythonAPI/src/DistributionLorentz.pypp.cpp
+++ b/Core/PythonAPI/src/DistributionLorentz.pypp.cpp
@@ -25,6 +25,13 @@ struct DistributionLorentz_wrapper : DistributionLorentz, bp::wrapper< Distribut
         m_pyobj = 0;
     }
 
+    DistributionLorentz_wrapper( )
+    : DistributionLorentz( )
+      , bp::wrapper< DistributionLorentz >(){
+        // null constructor
+    m_pyobj = 0;
+    }
+
     DistributionLorentz_wrapper(double mean, double hwhm )
     : DistributionLorentz( mean, hwhm )
       , bp::wrapper< DistributionLorentz >(){
@@ -179,8 +186,9 @@ void register_DistributionLorentz_class(){
 
     { //::DistributionLorentz
         typedef bp::class_< DistributionLorentz_wrapper, bp::bases< IDistribution1D >, std::auto_ptr< DistributionLorentz_wrapper > > DistributionLorentz_exposer_t;
-        DistributionLorentz_exposer_t DistributionLorentz_exposer = DistributionLorentz_exposer_t( "DistributionLorentz", bp::init< double, double >(( bp::arg("mean"), bp::arg("hwhm") )) );
+        DistributionLorentz_exposer_t DistributionLorentz_exposer = DistributionLorentz_exposer_t( "DistributionLorentz", bp::init< >() );
         bp::scope DistributionLorentz_scope( DistributionLorentz_exposer );
+        DistributionLorentz_exposer.def( bp::init< double, double >(( bp::arg("mean"), bp::arg("hwhm") )) );
         { //::DistributionLorentz::clone
         
             typedef ::DistributionLorentz * ( ::DistributionLorentz::*clone_function_type)(  ) const;
diff --git a/Core/PythonAPI/src/IParticle.pypp.cpp b/Core/PythonAPI/src/IParticle.pypp.cpp
new file mode 100644
index 00000000000..c693a4c701c
--- /dev/null
+++ b/Core/PythonAPI/src/IParticle.pypp.cpp
@@ -0,0 +1,555 @@
+// 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 "IParticle.pypp.h"
+
+namespace bp = boost::python;
+
+struct IParticle_wrapper : IParticle, bp::wrapper< IParticle > {
+
+    virtual void applyTransformation( ::Geometry::Transform3D const & transform ) {
+        if( bp::override func_applyTransformation = this->get_override( "applyTransformation" ) )
+            func_applyTransformation( boost::ref(transform) );
+        else{
+            this->IParticle::applyTransformation( boost::ref(transform) );
+        }
+    }
+    
+    void default_applyTransformation( ::Geometry::Transform3D const & transform ) {
+        IParticle::applyTransformation( boost::ref(transform) );
+    }
+
+    virtual void applyTransformationToSubParticles( ::Geometry::Transform3D const & transform ){
+        bp::override func_applyTransformationToSubParticles = this->get_override( "applyTransformationToSubParticles" );
+        func_applyTransformationToSubParticles( boost::ref(transform) );
+    }
+
+    virtual ::IParticle * clone(  ) const {
+        bp::override func_clone = this->get_override( "clone" );
+        return func_clone(  );
+    }
+
+    virtual ::IParticle * cloneInvertB(  ) const {
+        bp::override func_cloneInvertB = this->get_override( "cloneInvertB" );
+        return func_cloneInvertB(  );
+    }
+
+    virtual ::IFormFactor * createFormFactor( ::complex_t wavevector_scattering_factor ) const {
+        bp::override func_createFormFactor = this->get_override( "createFormFactor" );
+        return func_createFormFactor( wavevector_scattering_factor );
+    }
+
+    virtual ::IMaterial const * getAmbientMaterial(  ) const {
+        bp::override func_getAmbientMaterial = this->get_override( "getAmbientMaterial" );
+        return func_getAmbientMaterial(  );
+    }
+
+    virtual ::IMaterial const * getMaterial(  ) const {
+        bp::override func_getMaterial = this->get_override( "getMaterial" );
+        return func_getMaterial(  );
+    }
+
+    virtual ::complex_t getRefractiveIndex(  ) const {
+        bp::override func_getRefractiveIndex = this->get_override( "getRefractiveIndex" );
+        return func_getRefractiveIndex(  );
+    }
+
+    virtual ::IFormFactor const * getSimpleFormFactor(  ) const {
+        bp::override func_getSimpleFormFactor = this->get_override( "getSimpleFormFactor" );
+        return func_getSimpleFormFactor(  );
+    }
+
+    virtual bool hasDistributedFormFactor(  ) const  {
+        if( bp::override func_hasDistributedFormFactor = this->get_override( "hasDistributedFormFactor" ) )
+            return func_hasDistributedFormFactor(  );
+        else{
+            return this->IParticle::hasDistributedFormFactor(  );
+        }
+    }
+    
+    bool default_hasDistributedFormFactor(  ) const  {
+        return IParticle::hasDistributedFormFactor( );
+    }
+
+    virtual void setTransformation( ::Geometry::Transform3D const & transform ) {
+        if( bp::override func_setTransformation = this->get_override( "setTransformation" ) )
+            func_setTransformation( boost::ref(transform) );
+        else{
+            this->IParticle::setTransformation( boost::ref(transform) );
+        }
+    }
+    
+    void default_setTransformation( ::Geometry::Transform3D const & transform ) {
+        IParticle::setTransformation( boost::ref(transform) );
+    }
+
+    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 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 ::ICompositeSample * getCompositeSample(  ) {
+        if( bp::override func_getCompositeSample = this->get_override( "getCompositeSample" ) )
+            return func_getCompositeSample(  );
+        else{
+            return this->ICompositeSample::getCompositeSample(  );
+        }
+    }
+    
+    ::ICompositeSample * default_getCompositeSample(  ) {
+        return ICompositeSample::getCompositeSample( );
+    }
+
+    virtual ::ICompositeSample const * getCompositeSample(  ) const  {
+        if( bp::override func_getCompositeSample = this->get_override( "getCompositeSample" ) )
+            return func_getCompositeSample(  );
+        else{
+            return this->ICompositeSample::getCompositeSample(  );
+        }
+    }
+    
+    ::ICompositeSample const * default_getCompositeSample(  ) const  {
+        return ICompositeSample::getCompositeSample( );
+    }
+
+    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< IParticle_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( );
+    }
+
+    virtual ::std::size_t size(  ) const  {
+        if( bp::override func_size = this->get_override( "size" ) )
+            return func_size(  );
+        else{
+            return this->ICompositeSample::size(  );
+        }
+    }
+    
+    ::std::size_t default_size(  ) const  {
+        return ICompositeSample::size( );
+    }
+
+    virtual void transferToCPP(  ) {
+        
+        if( !this->m_pyobj) {
+            this->m_pyobj = boost::python::detail::wrapper_base_::get_owner(*this);
+            Py_INCREF(this->m_pyobj);
+        }
+        
+        if( bp::override func_transferToCPP = this->get_override( "transferToCPP" ) )
+            func_transferToCPP(  );
+        else{
+            this->ICloneable::transferToCPP(  );
+        }
+    }
+    
+    void default_transferToCPP(  ) {
+        
+        if( !this->m_pyobj) {
+            this->m_pyobj = boost::python::detail::wrapper_base_::get_owner(*this);
+            Py_INCREF(this->m_pyobj);
+        }
+        
+        ICloneable::transferToCPP( );
+    }
+
+    PyObject* m_pyobj;
+
+};
+
+void register_IParticle_class(){
+
+    { //::IParticle
+        typedef bp::class_< IParticle_wrapper, bp::bases< ICompositeSample >, std::auto_ptr< IParticle_wrapper >, boost::noncopyable > IParticle_exposer_t;
+        IParticle_exposer_t IParticle_exposer = IParticle_exposer_t( "IParticle", bp::no_init );
+        bp::scope IParticle_scope( IParticle_exposer );
+        { //::IParticle::applyTransformation
+        
+            typedef void ( ::IParticle::*applyTransformation_function_type)( ::Geometry::Transform3D const & ) ;
+            typedef void ( IParticle_wrapper::*default_applyTransformation_function_type)( ::Geometry::Transform3D const & ) ;
+            
+            IParticle_exposer.def( 
+                "applyTransformation"
+                , applyTransformation_function_type(&::IParticle::applyTransformation)
+                , default_applyTransformation_function_type(&IParticle_wrapper::default_applyTransformation)
+                , ( bp::arg("transform") ) );
+        
+        }
+        { //::IParticle::applyTransformationToSubParticles
+        
+            typedef void ( IParticle_wrapper::*applyTransformationToSubParticles_function_type)( ::Geometry::Transform3D const & ) ;
+            
+            IParticle_exposer.def( 
+                "applyTransformationToSubParticles"
+                , applyTransformationToSubParticles_function_type( &IParticle_wrapper::applyTransformationToSubParticles )
+                , ( bp::arg("transform") ) );
+        
+        }
+        { //::IParticle::clone
+        
+            typedef ::IParticle * ( ::IParticle::*clone_function_type)(  ) const;
+            
+            IParticle_exposer.def( 
+                "clone"
+                , bp::pure_virtual( clone_function_type(&::IParticle::clone) )
+                , bp::return_value_policy< bp::manage_new_object >() );
+        
+        }
+        { //::IParticle::cloneInvertB
+        
+            typedef ::IParticle * ( ::IParticle::*cloneInvertB_function_type)(  ) const;
+            
+            IParticle_exposer.def( 
+                "cloneInvertB"
+                , bp::pure_virtual( cloneInvertB_function_type(&::IParticle::cloneInvertB) )
+                , bp::return_value_policy< bp::reference_existing_object >() );
+        
+        }
+        { //::IParticle::createFormFactor
+        
+            typedef ::IFormFactor * ( ::IParticle::*createFormFactor_function_type)( ::complex_t ) const;
+            
+            IParticle_exposer.def( 
+                "createFormFactor"
+                , bp::pure_virtual( createFormFactor_function_type(&::IParticle::createFormFactor) )
+                , ( bp::arg("wavevector_scattering_factor") )
+                , bp::return_value_policy< bp::manage_new_object >() );
+        
+        }
+        { //::IParticle::getAmbientMaterial
+        
+            typedef ::IMaterial const * ( ::IParticle::*getAmbientMaterial_function_type)(  ) const;
+            
+            IParticle_exposer.def( 
+                "getAmbientMaterial"
+                , bp::pure_virtual( getAmbientMaterial_function_type(&::IParticle::getAmbientMaterial) )
+                , bp::return_value_policy< bp::reference_existing_object >() );
+        
+        }
+        { //::IParticle::getMaterial
+        
+            typedef ::IMaterial const * ( ::IParticle::*getMaterial_function_type)(  ) const;
+            
+            IParticle_exposer.def( 
+                "getMaterial"
+                , bp::pure_virtual( getMaterial_function_type(&::IParticle::getMaterial) )
+                , bp::return_value_policy< bp::reference_existing_object >() );
+        
+        }
+        { //::IParticle::getPTransform3D
+        
+            typedef ::Geometry::Transform3D const * ( ::IParticle::*getPTransform3D_function_type)(  ) const;
+            
+            IParticle_exposer.def( 
+                "getPTransform3D"
+                , getPTransform3D_function_type( &::IParticle::getPTransform3D )
+                , bp::return_value_policy< bp::reference_existing_object >() );
+        
+        }
+        { //::IParticle::getRefractiveIndex
+        
+            typedef ::complex_t ( ::IParticle::*getRefractiveIndex_function_type)(  ) const;
+            
+            IParticle_exposer.def( 
+                "getRefractiveIndex"
+                , bp::pure_virtual( getRefractiveIndex_function_type(&::IParticle::getRefractiveIndex) ) );
+        
+        }
+        { //::IParticle::getSimpleFormFactor
+        
+            typedef ::IFormFactor const * ( ::IParticle::*getSimpleFormFactor_function_type)(  ) const;
+            
+            IParticle_exposer.def( 
+                "getSimpleFormFactor"
+                , bp::pure_virtual( getSimpleFormFactor_function_type(&::IParticle::getSimpleFormFactor) )
+                , bp::return_value_policy< bp::reference_existing_object >() );
+        
+        }
+        { //::IParticle::hasDistributedFormFactor
+        
+            typedef bool ( ::IParticle::*hasDistributedFormFactor_function_type)(  ) const;
+            typedef bool ( IParticle_wrapper::*default_hasDistributedFormFactor_function_type)(  ) const;
+            
+            IParticle_exposer.def( 
+                "hasDistributedFormFactor"
+                , hasDistributedFormFactor_function_type(&::IParticle::hasDistributedFormFactor)
+                , default_hasDistributedFormFactor_function_type(&IParticle_wrapper::default_hasDistributedFormFactor) );
+        
+        }
+        { //::IParticle::setTransformation
+        
+            typedef void ( ::IParticle::*setTransformation_function_type)( ::Geometry::Transform3D const & ) ;
+            typedef void ( IParticle_wrapper::*default_setTransformation_function_type)( ::Geometry::Transform3D const & ) ;
+            
+            IParticle_exposer.def( 
+                "setTransformation"
+                , setTransformation_function_type(&::IParticle::setTransformation)
+                , default_setTransformation_function_type(&IParticle_wrapper::default_setTransformation)
+                , ( bp::arg("transform") ) );
+        
+        }
+        { //::IParameterized::areParametersChanged
+        
+            typedef bool ( ::IParameterized::*areParametersChanged_function_type)(  ) ;
+            typedef bool ( IParticle_wrapper::*default_areParametersChanged_function_type)(  ) ;
+            
+            IParticle_exposer.def( 
+                "areParametersChanged"
+                , areParametersChanged_function_type(&::IParameterized::areParametersChanged)
+                , default_areParametersChanged_function_type(&IParticle_wrapper::default_areParametersChanged) );
+        
+        }
+        { //::IParameterized::clearParameterPool
+        
+            typedef void ( ::IParameterized::*clearParameterPool_function_type)(  ) ;
+            typedef void ( IParticle_wrapper::*default_clearParameterPool_function_type)(  ) ;
+            
+            IParticle_exposer.def( 
+                "clearParameterPool"
+                , clearParameterPool_function_type(&::IParameterized::clearParameterPool)
+                , default_clearParameterPool_function_type(&IParticle_wrapper::default_clearParameterPool) );
+        
+        }
+        { //::ISample::containsMagneticMaterial
+        
+            typedef bool ( ::ISample::*containsMagneticMaterial_function_type)(  ) const;
+            typedef bool ( IParticle_wrapper::*default_containsMagneticMaterial_function_type)(  ) const;
+            
+            IParticle_exposer.def( 
+                "containsMagneticMaterial"
+                , containsMagneticMaterial_function_type(&::ISample::containsMagneticMaterial)
+                , default_containsMagneticMaterial_function_type(&IParticle_wrapper::default_containsMagneticMaterial) );
+        
+        }
+        { //::IParameterized::createParameterTree
+        
+            typedef ::ParameterPool * ( ::IParameterized::*createParameterTree_function_type)(  ) const;
+            typedef ::ParameterPool * ( IParticle_wrapper::*default_createParameterTree_function_type)(  ) const;
+            
+            IParticle_exposer.def( 
+                "createParameterTree"
+                , createParameterTree_function_type(&::IParameterized::createParameterTree)
+                , default_createParameterTree_function_type(&IParticle_wrapper::default_createParameterTree)
+                , bp::return_value_policy< bp::manage_new_object >() );
+        
+        }
+        { //::ICompositeSample::getCompositeSample
+        
+            typedef ::ICompositeSample * ( ::ICompositeSample::*getCompositeSample_function_type)(  ) ;
+            typedef ::ICompositeSample * ( IParticle_wrapper::*default_getCompositeSample_function_type)(  ) ;
+            
+            IParticle_exposer.def( 
+                "getCompositeSample"
+                , getCompositeSample_function_type(&::ICompositeSample::getCompositeSample)
+                , default_getCompositeSample_function_type(&IParticle_wrapper::default_getCompositeSample)
+                , bp::return_value_policy< bp::reference_existing_object >() );
+        
+        }
+        { //::ICompositeSample::getCompositeSample
+        
+            typedef ::ICompositeSample const * ( ::ICompositeSample::*getCompositeSample_function_type)(  ) const;
+            typedef ::ICompositeSample const * ( IParticle_wrapper::*default_getCompositeSample_function_type)(  ) const;
+            
+            IParticle_exposer.def( 
+                "getCompositeSample"
+                , getCompositeSample_function_type(&::ICompositeSample::getCompositeSample)
+                , default_getCompositeSample_function_type(&IParticle_wrapper::default_getCompositeSample)
+                , bp::return_value_policy< bp::reference_existing_object >() );
+        
+        }
+        { //::IParameterized::printParameters
+        
+            typedef void ( ::IParameterized::*printParameters_function_type)(  ) const;
+            typedef void ( IParticle_wrapper::*default_printParameters_function_type)(  ) const;
+            
+            IParticle_exposer.def( 
+                "printParameters"
+                , printParameters_function_type(&::IParameterized::printParameters)
+                , default_printParameters_function_type(&IParticle_wrapper::default_printParameters) );
+        
+        }
+        { //::ISample::printSampleTree
+        
+            typedef void ( ::ISample::*printSampleTree_function_type)(  ) ;
+            typedef void ( IParticle_wrapper::*default_printSampleTree_function_type)(  ) ;
+            
+            IParticle_exposer.def( 
+                "printSampleTree"
+                , printSampleTree_function_type(&::ISample::printSampleTree)
+                , default_printSampleTree_function_type(&IParticle_wrapper::default_printSampleTree) );
+        
+        }
+        { //::IParameterized::registerParameter
+        
+            typedef void ( *default_registerParameter_function_type )( ::IParameterized &,::std::string const &,long unsigned int );
+            
+            IParticle_exposer.def( 
+                "registerParameter"
+                , default_registerParameter_function_type( &IParticle_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 ( IParticle_wrapper::*default_setParameterValue_function_type)( ::std::string const &,double ) ;
+            
+            IParticle_exposer.def( 
+                "setParameterValue"
+                , setParameterValue_function_type(&::IParameterized::setParameterValue)
+                , default_setParameterValue_function_type(&IParticle_wrapper::default_setParameterValue)
+                , ( bp::arg("name"), bp::arg("value") ) );
+        
+        }
+        { //::IParameterized::setParametersAreChanged
+        
+            typedef void ( ::IParameterized::*setParametersAreChanged_function_type)(  ) ;
+            typedef void ( IParticle_wrapper::*default_setParametersAreChanged_function_type)(  ) ;
+            
+            IParticle_exposer.def( 
+                "setParametersAreChanged"
+                , setParametersAreChanged_function_type(&::IParameterized::setParametersAreChanged)
+                , default_setParametersAreChanged_function_type(&IParticle_wrapper::default_setParametersAreChanged) );
+        
+        }
+        { //::ICompositeSample::size
+        
+            typedef ::std::size_t ( ::ICompositeSample::*size_function_type)(  ) const;
+            typedef ::std::size_t ( IParticle_wrapper::*default_size_function_type)(  ) const;
+            
+            IParticle_exposer.def( 
+                "size"
+                , size_function_type(&::ICompositeSample::size)
+                , default_size_function_type(&IParticle_wrapper::default_size) );
+        
+        }
+        { //::ICloneable::transferToCPP
+        
+            typedef void ( ::ICloneable::*transferToCPP_function_type)(  ) ;
+            typedef void ( IParticle_wrapper::*default_transferToCPP_function_type)(  ) ;
+            
+            IParticle_exposer.def( 
+                "transferToCPP"
+                , transferToCPP_function_type(&::ICloneable::transferToCPP)
+                , default_transferToCPP_function_type(&IParticle_wrapper::default_transferToCPP) );
+        
+        }
+    }
+
+}
diff --git a/Core/PythonAPI/src/LatticeBasis.pypp.cpp b/Core/PythonAPI/src/LatticeBasis.pypp.cpp
index 417ace642f2..8a175e7f6cb 100644
--- a/Core/PythonAPI/src/LatticeBasis.pypp.cpp
+++ b/Core/PythonAPI/src/LatticeBasis.pypp.cpp
@@ -29,12 +29,12 @@ struct LatticeBasis_wrapper : LatticeBasis, bp::wrapper< LatticeBasis > {
         if( bp::override func_applyTransformation = this->get_override( "applyTransformation" ) )
             func_applyTransformation( boost::ref(transform) );
         else{
-            this->Particle::applyTransformation( boost::ref(transform) );
+            this->IParticle::applyTransformation( boost::ref(transform) );
         }
     }
     
     void default_applyTransformation( ::Geometry::Transform3D const & transform ) {
-        Particle::applyTransformation( boost::ref(transform) );
+        IParticle::applyTransformation( boost::ref(transform) );
     }
 
     virtual bool areParametersChanged(  ) {
@@ -240,12 +240,12 @@ struct LatticeBasis_wrapper : LatticeBasis, bp::wrapper< LatticeBasis > {
         if( bp::override func_setTransformation = this->get_override( "setTransformation" ) )
             func_setTransformation( boost::ref(transform) );
         else{
-            this->Particle::setTransformation( boost::ref(transform) );
+            this->IParticle::setTransformation( boost::ref(transform) );
         }
     }
     
     void default_setTransformation( ::Geometry::Transform3D const & transform ) {
-        Particle::setTransformation( boost::ref(transform) );
+        IParticle::setTransformation( boost::ref(transform) );
     }
 
     virtual ::std::size_t size(  ) const  {
@@ -304,14 +304,14 @@ void register_LatticeBasis_class(){
                 , ( bp::arg("particle"), bp::arg("positions") ) );
         
         }
-        { //::Particle::applyTransformation
+        { //::IParticle::applyTransformation
         
-            typedef void ( ::Particle::*applyTransformation_function_type)( ::Geometry::Transform3D const & ) ;
+            typedef void ( ::IParticle::*applyTransformation_function_type)( ::Geometry::Transform3D const & ) ;
             typedef void ( LatticeBasis_wrapper::*default_applyTransformation_function_type)( ::Geometry::Transform3D const & ) ;
             
             LatticeBasis_exposer.def( 
                 "applyTransformation"
-                , applyTransformation_function_type(&::Particle::applyTransformation)
+                , applyTransformation_function_type(&::IParticle::applyTransformation)
                 , default_applyTransformation_function_type(&LatticeBasis_wrapper::default_applyTransformation)
                 , ( bp::arg("transform") ) );
         
@@ -498,14 +498,14 @@ void register_LatticeBasis_class(){
                 , default_setParametersAreChanged_function_type(&LatticeBasis_wrapper::default_setParametersAreChanged) );
         
         }
-        { //::Particle::setTransformation
+        { //::IParticle::setTransformation
         
-            typedef void ( ::Particle::*setTransformation_function_type)( ::Geometry::Transform3D const & ) ;
+            typedef void ( ::IParticle::*setTransformation_function_type)( ::Geometry::Transform3D const & ) ;
             typedef void ( LatticeBasis_wrapper::*default_setTransformation_function_type)( ::Geometry::Transform3D const & ) ;
             
             LatticeBasis_exposer.def( 
                 "setTransformation"
-                , setTransformation_function_type(&::Particle::setTransformation)
+                , setTransformation_function_type(&::IParticle::setTransformation)
                 , default_setTransformation_function_type(&LatticeBasis_wrapper::default_setTransformation)
                 , ( bp::arg("transform") ) );
         
diff --git a/Core/PythonAPI/src/MesoCrystal.pypp.cpp b/Core/PythonAPI/src/MesoCrystal.pypp.cpp
index 47bff10d7ee..640c95e599e 100644
--- a/Core/PythonAPI/src/MesoCrystal.pypp.cpp
+++ b/Core/PythonAPI/src/MesoCrystal.pypp.cpp
@@ -29,12 +29,12 @@ struct MesoCrystal_wrapper : MesoCrystal, bp::wrapper< MesoCrystal > {
         if( bp::override func_applyTransformation = this->get_override( "applyTransformation" ) )
             func_applyTransformation( boost::ref(transform) );
         else{
-            this->Particle::applyTransformation( boost::ref(transform) );
+            this->IParticle::applyTransformation( boost::ref(transform) );
         }
     }
     
     void default_applyTransformation( ::Geometry::Transform3D const & transform ) {
-        Particle::applyTransformation( boost::ref(transform) );
+        IParticle::applyTransformation( boost::ref(transform) );
     }
 
     virtual bool areParametersChanged(  ) {
@@ -228,12 +228,12 @@ struct MesoCrystal_wrapper : MesoCrystal, bp::wrapper< MesoCrystal > {
         if( bp::override func_setTransformation = this->get_override( "setTransformation" ) )
             func_setTransformation( boost::ref(transform) );
         else{
-            this->Particle::setTransformation( boost::ref(transform) );
+            this->IParticle::setTransformation( boost::ref(transform) );
         }
     }
     
     void default_setTransformation( ::Geometry::Transform3D const & transform ) {
-        Particle::setTransformation( boost::ref(transform) );
+        IParticle::setTransformation( boost::ref(transform) );
     }
 
     virtual ::std::size_t size(  ) const  {
@@ -282,14 +282,14 @@ void register_MesoCrystal_class(){
         typedef bp::class_< MesoCrystal_wrapper, bp::bases< Particle >, std::auto_ptr< MesoCrystal_wrapper >, boost::noncopyable > MesoCrystal_exposer_t;
         MesoCrystal_exposer_t MesoCrystal_exposer = MesoCrystal_exposer_t( "MesoCrystal", bp::init< IClusteredParticles const &, IFormFactor & >(( bp::arg("particle_structure"), bp::arg("form_factor") )) );
         bp::scope MesoCrystal_scope( MesoCrystal_exposer );
-        { //::Particle::applyTransformation
+        { //::IParticle::applyTransformation
         
-            typedef void ( ::Particle::*applyTransformation_function_type)( ::Geometry::Transform3D const & ) ;
+            typedef void ( ::IParticle::*applyTransformation_function_type)( ::Geometry::Transform3D const & ) ;
             typedef void ( MesoCrystal_wrapper::*default_applyTransformation_function_type)( ::Geometry::Transform3D const & ) ;
             
             MesoCrystal_exposer.def( 
                 "applyTransformation"
-                , applyTransformation_function_type(&::Particle::applyTransformation)
+                , applyTransformation_function_type(&::IParticle::applyTransformation)
                 , default_applyTransformation_function_type(&MesoCrystal_wrapper::default_applyTransformation)
                 , ( bp::arg("transform") ) );
         
@@ -464,14 +464,14 @@ void register_MesoCrystal_class(){
                 , default_setParametersAreChanged_function_type(&MesoCrystal_wrapper::default_setParametersAreChanged) );
         
         }
-        { //::Particle::setTransformation
+        { //::IParticle::setTransformation
         
-            typedef void ( ::Particle::*setTransformation_function_type)( ::Geometry::Transform3D const & ) ;
+            typedef void ( ::IParticle::*setTransformation_function_type)( ::Geometry::Transform3D const & ) ;
             typedef void ( MesoCrystal_wrapper::*default_setTransformation_function_type)( ::Geometry::Transform3D const & ) ;
             
             MesoCrystal_exposer.def( 
                 "setTransformation"
-                , setTransformation_function_type(&::Particle::setTransformation)
+                , setTransformation_function_type(&::IParticle::setTransformation)
                 , default_setTransformation_function_type(&MesoCrystal_wrapper::default_setTransformation)
                 , ( bp::arg("transform") ) );
         
diff --git a/Core/PythonAPI/src/Particle.pypp.cpp b/Core/PythonAPI/src/Particle.pypp.cpp
index d9c08dd9e4f..ceb35530b66 100644
--- a/Core/PythonAPI/src/Particle.pypp.cpp
+++ b/Core/PythonAPI/src/Particle.pypp.cpp
@@ -46,18 +46,6 @@ struct Particle_wrapper : Particle, bp::wrapper< Particle > {
     m_pyobj = 0;
     }
 
-    virtual void applyTransformation( ::Geometry::Transform3D const & transform ) {
-        if( bp::override func_applyTransformation = this->get_override( "applyTransformation" ) )
-            func_applyTransformation( boost::ref(transform) );
-        else{
-            this->Particle::applyTransformation( boost::ref(transform) );
-        }
-    }
-    
-    void default_applyTransformation( ::Geometry::Transform3D const & transform ) {
-        Particle::applyTransformation( boost::ref(transform) );
-    }
-
     virtual ::Particle * clone(  ) const  {
         if( bp::override func_clone = this->get_override( "clone" ) )
             return func_clone(  );
@@ -154,16 +142,16 @@ struct Particle_wrapper : Particle, bp::wrapper< Particle > {
         return Particle::hasDistributedFormFactor( );
     }
 
-    virtual void setTransformation( ::Geometry::Transform3D const & transform ) {
-        if( bp::override func_setTransformation = this->get_override( "setTransformation" ) )
-            func_setTransformation( boost::ref(transform) );
+    virtual void applyTransformation( ::Geometry::Transform3D const & transform ) {
+        if( bp::override func_applyTransformation = this->get_override( "applyTransformation" ) )
+            func_applyTransformation( boost::ref(transform) );
         else{
-            this->Particle::setTransformation( boost::ref(transform) );
+            this->IParticle::applyTransformation( boost::ref(transform) );
         }
     }
     
-    void default_setTransformation( ::Geometry::Transform3D const & transform ) {
-        Particle::setTransformation( boost::ref(transform) );
+    void default_applyTransformation( ::Geometry::Transform3D const & transform ) {
+        IParticle::applyTransformation( boost::ref(transform) );
     }
 
     virtual bool areParametersChanged(  ) {
@@ -305,6 +293,18 @@ struct Particle_wrapper : Particle, bp::wrapper< Particle > {
         IParameterized::setParametersAreChanged( );
     }
 
+    virtual void setTransformation( ::Geometry::Transform3D const & transform ) {
+        if( bp::override func_setTransformation = this->get_override( "setTransformation" ) )
+            func_setTransformation( boost::ref(transform) );
+        else{
+            this->IParticle::setTransformation( boost::ref(transform) );
+        }
+    }
+    
+    void default_setTransformation( ::Geometry::Transform3D const & transform ) {
+        IParticle::setTransformation( boost::ref(transform) );
+    }
+
     virtual ::std::size_t size(  ) const  {
         if( bp::override func_size = this->get_override( "size" ) )
             return func_size(  );
@@ -348,24 +348,12 @@ struct Particle_wrapper : Particle, bp::wrapper< Particle > {
 void register_Particle_class(){
 
     { //::Particle
-        typedef bp::class_< Particle_wrapper, bp::bases< ICompositeSample >, std::auto_ptr< Particle_wrapper >, boost::noncopyable > Particle_exposer_t;
+        typedef bp::class_< Particle_wrapper, bp::bases< IParticle >, std::auto_ptr< Particle_wrapper >, boost::noncopyable > Particle_exposer_t;
         Particle_exposer_t Particle_exposer = Particle_exposer_t( "Particle", bp::init< >() );
         bp::scope Particle_scope( Particle_exposer );
         Particle_exposer.def( bp::init< IMaterial const & >(( bp::arg("p_material") )) );
         Particle_exposer.def( bp::init< IMaterial const &, IFormFactor const & >(( bp::arg("p_material"), bp::arg("form_factor") )) );
         Particle_exposer.def( bp::init< IMaterial const &, IFormFactor const &, Geometry::Transform3D const & >(( bp::arg("p_material"), bp::arg("form_factor"), bp::arg("transform") )) );
-        { //::Particle::applyTransformation
-        
-            typedef void ( ::Particle::*applyTransformation_function_type)( ::Geometry::Transform3D const & ) ;
-            typedef void ( Particle_wrapper::*default_applyTransformation_function_type)( ::Geometry::Transform3D const & ) ;
-            
-            Particle_exposer.def( 
-                "applyTransformation"
-                , applyTransformation_function_type(&::Particle::applyTransformation)
-                , default_applyTransformation_function_type(&Particle_wrapper::default_applyTransformation)
-                , ( bp::arg("transform") ) );
-        
-        }
         { //::Particle::clone
         
             typedef ::Particle * ( ::Particle::*clone_function_type)(  ) const;
@@ -426,16 +414,6 @@ void register_Particle_class(){
                 , default_getMaterial_function_type(&Particle_wrapper::default_getMaterial)
                 , bp::return_value_policy< bp::reference_existing_object >() );
         
-        }
-        { //::Particle::getPTransform3D
-        
-            typedef ::Geometry::Transform3D const * ( ::Particle::*getPTransform3D_function_type)(  ) const;
-            
-            Particle_exposer.def( 
-                "getPTransform3D"
-                , getPTransform3D_function_type( &::Particle::getPTransform3D )
-                , bp::return_value_policy< bp::reference_existing_object >() );
-        
         }
         { //::Particle::getRefractiveIndex
         
@@ -471,15 +449,15 @@ void register_Particle_class(){
                 , default_hasDistributedFormFactor_function_type(&Particle_wrapper::default_hasDistributedFormFactor) );
         
         }
-        { //::Particle::setTransformation
+        { //::IParticle::applyTransformation
         
-            typedef void ( ::Particle::*setTransformation_function_type)( ::Geometry::Transform3D const & ) ;
-            typedef void ( Particle_wrapper::*default_setTransformation_function_type)( ::Geometry::Transform3D const & ) ;
+            typedef void ( ::IParticle::*applyTransformation_function_type)( ::Geometry::Transform3D const & ) ;
+            typedef void ( Particle_wrapper::*default_applyTransformation_function_type)( ::Geometry::Transform3D const & ) ;
             
             Particle_exposer.def( 
-                "setTransformation"
-                , setTransformation_function_type(&::Particle::setTransformation)
-                , default_setTransformation_function_type(&Particle_wrapper::default_setTransformation)
+                "applyTransformation"
+                , applyTransformation_function_type(&::IParticle::applyTransformation)
+                , default_applyTransformation_function_type(&Particle_wrapper::default_applyTransformation)
                 , ( bp::arg("transform") ) );
         
         }
@@ -606,6 +584,18 @@ void register_Particle_class(){
                 , setParametersAreChanged_function_type(&::IParameterized::setParametersAreChanged)
                 , default_setParametersAreChanged_function_type(&Particle_wrapper::default_setParametersAreChanged) );
         
+        }
+        { //::IParticle::setTransformation
+        
+            typedef void ( ::IParticle::*setTransformation_function_type)( ::Geometry::Transform3D const & ) ;
+            typedef void ( Particle_wrapper::*default_setTransformation_function_type)( ::Geometry::Transform3D const & ) ;
+            
+            Particle_exposer.def( 
+                "setTransformation"
+                , setTransformation_function_type(&::IParticle::setTransformation)
+                , default_setTransformation_function_type(&Particle_wrapper::default_setTransformation)
+                , ( bp::arg("transform") ) );
+        
         }
         { //::ICompositeSample::size
         
diff --git a/Core/PythonAPI/src/ParticleCoreShell.pypp.cpp b/Core/PythonAPI/src/ParticleCoreShell.pypp.cpp
index b50c156d8b4..2705aa44697 100644
--- a/Core/PythonAPI/src/ParticleCoreShell.pypp.cpp
+++ b/Core/PythonAPI/src/ParticleCoreShell.pypp.cpp
@@ -29,12 +29,12 @@ struct ParticleCoreShell_wrapper : ParticleCoreShell, bp::wrapper< ParticleCoreS
         if( bp::override func_applyTransformation = this->get_override( "applyTransformation" ) )
             func_applyTransformation( boost::ref(transform) );
         else{
-            this->Particle::applyTransformation( boost::ref(transform) );
+            this->IParticle::applyTransformation( boost::ref(transform) );
         }
     }
     
     void default_applyTransformation( ::Geometry::Transform3D const & transform ) {
-        Particle::applyTransformation( boost::ref(transform) );
+        IParticle::applyTransformation( boost::ref(transform) );
     }
 
     virtual bool areParametersChanged(  ) {
@@ -228,12 +228,12 @@ struct ParticleCoreShell_wrapper : ParticleCoreShell, bp::wrapper< ParticleCoreS
         if( bp::override func_setTransformation = this->get_override( "setTransformation" ) )
             func_setTransformation( boost::ref(transform) );
         else{
-            this->Particle::setTransformation( boost::ref(transform) );
+            this->IParticle::setTransformation( boost::ref(transform) );
         }
     }
     
     void default_setTransformation( ::Geometry::Transform3D const & transform ) {
-        Particle::setTransformation( boost::ref(transform) );
+        IParticle::setTransformation( boost::ref(transform) );
     }
 
     virtual ::std::size_t size(  ) const  {
@@ -282,14 +282,14 @@ void register_ParticleCoreShell_class(){
         typedef bp::class_< ParticleCoreShell_wrapper, bp::bases< Particle >, std::auto_ptr< ParticleCoreShell_wrapper >, boost::noncopyable > ParticleCoreShell_exposer_t;
         ParticleCoreShell_exposer_t ParticleCoreShell_exposer = ParticleCoreShell_exposer_t( "ParticleCoreShell", bp::init< Particle const &, Particle const &, kvector_t >(( bp::arg("shell"), bp::arg("core"), bp::arg("relative_core_position") )) );
         bp::scope ParticleCoreShell_scope( ParticleCoreShell_exposer );
-        { //::Particle::applyTransformation
+        { //::IParticle::applyTransformation
         
-            typedef void ( ::Particle::*applyTransformation_function_type)( ::Geometry::Transform3D const & ) ;
+            typedef void ( ::IParticle::*applyTransformation_function_type)( ::Geometry::Transform3D const & ) ;
             typedef void ( ParticleCoreShell_wrapper::*default_applyTransformation_function_type)( ::Geometry::Transform3D const & ) ;
             
             ParticleCoreShell_exposer.def( 
                 "applyTransformation"
-                , applyTransformation_function_type(&::Particle::applyTransformation)
+                , applyTransformation_function_type(&::IParticle::applyTransformation)
                 , default_applyTransformation_function_type(&ParticleCoreShell_wrapper::default_applyTransformation)
                 , ( bp::arg("transform") ) );
         
@@ -464,14 +464,14 @@ void register_ParticleCoreShell_class(){
                 , default_setParametersAreChanged_function_type(&ParticleCoreShell_wrapper::default_setParametersAreChanged) );
         
         }
-        { //::Particle::setTransformation
+        { //::IParticle::setTransformation
         
-            typedef void ( ::Particle::*setTransformation_function_type)( ::Geometry::Transform3D const & ) ;
+            typedef void ( ::IParticle::*setTransformation_function_type)( ::Geometry::Transform3D const & ) ;
             typedef void ( ParticleCoreShell_wrapper::*default_setTransformation_function_type)( ::Geometry::Transform3D const & ) ;
             
             ParticleCoreShell_exposer.def( 
                 "setTransformation"
-                , setTransformation_function_type(&::Particle::setTransformation)
+                , setTransformation_function_type(&::IParticle::setTransformation)
                 , default_setTransformation_function_type(&ParticleCoreShell_wrapper::default_setTransformation)
                 , ( bp::arg("transform") ) );
         
diff --git a/Core/PythonAPI/src/ParticleInfo.pypp.cpp b/Core/PythonAPI/src/ParticleInfo.pypp.cpp
index 1683a6fee6c..8bbb3147abe 100644
--- a/Core/PythonAPI/src/ParticleInfo.pypp.cpp
+++ b/Core/PythonAPI/src/ParticleInfo.pypp.cpp
@@ -18,7 +18,7 @@ namespace bp = boost::python;
 
 struct ParticleInfo_wrapper : ParticleInfo, bp::wrapper< ParticleInfo > {
 
-    ParticleInfo_wrapper(::Particle const & p_particle, double depth=0, double abundance=0 )
+    ParticleInfo_wrapper(::IParticle const & p_particle, double depth=0, double abundance=0 )
     : ParticleInfo( boost::ref(p_particle), depth, abundance )
       , bp::wrapper< ParticleInfo >(){
         // constructor
@@ -232,7 +232,7 @@ void register_ParticleInfo_class(){
 
     { //::ParticleInfo
         typedef bp::class_< ParticleInfo_wrapper, bp::bases< ICompositeSample >, std::auto_ptr< ParticleInfo_wrapper >, boost::noncopyable > ParticleInfo_exposer_t;
-        ParticleInfo_exposer_t ParticleInfo_exposer = ParticleInfo_exposer_t( "ParticleInfo", bp::init< Particle const &, bp::optional< double, double > >(( bp::arg("p_particle"), bp::arg("depth")=0, bp::arg("abundance")=0 )) );
+        ParticleInfo_exposer_t ParticleInfo_exposer = ParticleInfo_exposer_t( "ParticleInfo", bp::init< IParticle const &, bp::optional< double, double > >(( bp::arg("p_particle"), bp::arg("depth")=0, bp::arg("abundance")=0 )) );
         bp::scope ParticleInfo_scope( ParticleInfo_exposer );
         { //::ParticleInfo::clone
         
@@ -278,7 +278,7 @@ void register_ParticleInfo_class(){
         }
         { //::ParticleInfo::getParticle
         
-            typedef ::Particle const * ( ::ParticleInfo::*getParticle_function_type)(  ) const;
+            typedef ::IParticle const * ( ::ParticleInfo::*getParticle_function_type)(  ) const;
             
             ParticleInfo_exposer.def( 
                 "getParticle"
diff --git a/Core/PythonAPI/src/ParticleLayout.pypp.cpp b/Core/PythonAPI/src/ParticleLayout.pypp.cpp
index 8eac39eedf1..fb49d0147f8 100644
--- a/Core/PythonAPI/src/ParticleLayout.pypp.cpp
+++ b/Core/PythonAPI/src/ParticleLayout.pypp.cpp
@@ -25,8 +25,8 @@ struct ParticleLayout_wrapper : ParticleLayout, bp::wrapper< ParticleLayout > {
     m_pyobj = 0;
     }
 
-    ParticleLayout_wrapper(::Particle const & p_particle, double depth=0.0, double abundance=1.0e+0 )
-    : ParticleLayout( boost::ref(p_particle), depth, abundance )
+    ParticleLayout_wrapper(::IParticle const & particle, double depth=0.0, double abundance=1.0e+0 )
+    : ParticleLayout( boost::ref(particle), depth, abundance )
       , bp::wrapper< ParticleLayout >(){
         // constructor
     m_pyobj = 0;
@@ -301,7 +301,7 @@ void register_ParticleLayout_class(){
         typedef bp::class_< ParticleLayout_wrapper, bp::bases< ILayout >, std::auto_ptr< ParticleLayout_wrapper >, boost::noncopyable > ParticleLayout_exposer_t;
         ParticleLayout_exposer_t ParticleLayout_exposer = ParticleLayout_exposer_t( "ParticleLayout", bp::init< >() );
         bp::scope ParticleLayout_scope( ParticleLayout_exposer );
-        ParticleLayout_exposer.def( bp::init< Particle const &, bp::optional< double, double > >(( bp::arg("p_particle"), bp::arg("depth")=0.0, bp::arg("abundance")=1.0e+0 )) );
+        ParticleLayout_exposer.def( bp::init< IParticle const &, bp::optional< double, double > >(( bp::arg("particle"), bp::arg("depth")=0.0, bp::arg("abundance")=1.0e+0 )) );
         { //::ParticleLayout::addInterferenceFunction
         
             typedef void ( ::ParticleLayout::*addInterferenceFunction_function_type)( ::IInterferenceFunction const & ) ;
@@ -314,17 +314,17 @@ void register_ParticleLayout_class(){
         }
         { //::ParticleLayout::addParticle
         
-            typedef void ( ::ParticleLayout::*addParticle_function_type)( ::Particle const &,::Geometry::Transform3D const &,double,double ) ;
+            typedef void ( ::ParticleLayout::*addParticle_function_type)( ::IParticle const &,::Geometry::Transform3D const &,double,double ) ;
             
             ParticleLayout_exposer.def( 
                 "addParticle"
                 , addParticle_function_type( &::ParticleLayout::addParticle )
-                , ( bp::arg("p_particle"), bp::arg("transform"), bp::arg("depth")=0.0, bp::arg("abundance")=1.0e+0 ) );
+                , ( bp::arg("particle"), bp::arg("transform"), bp::arg("depth")=0.0, bp::arg("abundance")=1.0e+0 ) );
         
         }
         { //::ParticleLayout::addParticle
         
-            typedef void ( ::ParticleLayout::*addParticle_function_type)( ::Particle const &,double,double ) ;
+            typedef void ( ::ParticleLayout::*addParticle_function_type)( ::IParticle const &,double,double ) ;
             
             ParticleLayout_exposer.def( 
                 "addParticle"
diff --git a/Core/PythonAPI/src/PositionParticleInfo.pypp.cpp b/Core/PythonAPI/src/PositionParticleInfo.pypp.cpp
index 91416d336f4..003e1b7a5da 100644
--- a/Core/PythonAPI/src/PositionParticleInfo.pypp.cpp
+++ b/Core/PythonAPI/src/PositionParticleInfo.pypp.cpp
@@ -18,7 +18,7 @@ namespace bp = boost::python;
 
 struct PositionParticleInfo_wrapper : PositionParticleInfo, bp::wrapper< PositionParticleInfo > {
 
-    PositionParticleInfo_wrapper(::Particle const & particle, ::kvector_t position, double abundance=0 )
+    PositionParticleInfo_wrapper(::IParticle const & particle, ::kvector_t position, double abundance=0 )
     : PositionParticleInfo( boost::ref(particle), position, abundance )
       , bp::wrapper< PositionParticleInfo >(){
         // constructor
@@ -232,7 +232,7 @@ void register_PositionParticleInfo_class(){
 
     { //::PositionParticleInfo
         typedef bp::class_< PositionParticleInfo_wrapper, bp::bases< ParticleInfo >, std::auto_ptr< PositionParticleInfo_wrapper >, boost::noncopyable > PositionParticleInfo_exposer_t;
-        PositionParticleInfo_exposer_t PositionParticleInfo_exposer = PositionParticleInfo_exposer_t( "PositionParticleInfo", bp::init< Particle const &, kvector_t, bp::optional< double > >(( bp::arg("particle"), bp::arg("position"), bp::arg("abundance")=0 )) );
+        PositionParticleInfo_exposer_t PositionParticleInfo_exposer = PositionParticleInfo_exposer_t( "PositionParticleInfo", bp::init< IParticle const &, kvector_t, bp::optional< double > >(( bp::arg("particle"), bp::arg("position"), bp::arg("abundance")=0 )) );
         bp::scope PositionParticleInfo_scope( PositionParticleInfo_exposer );
         { //::PositionParticleInfo::clone
         
@@ -245,16 +245,6 @@ void register_PositionParticleInfo_class(){
                 , default_clone_function_type(&PositionParticleInfo_wrapper::default_clone)
                 , bp::return_value_policy< bp::manage_new_object >() );
         
-        }
-        { //::PositionParticleInfo::getParticle
-        
-            typedef ::Particle const * ( ::PositionParticleInfo::*getParticle_function_type)(  ) const;
-            
-            PositionParticleInfo_exposer.def( 
-                "getParticle"
-                , getParticle_function_type( &::PositionParticleInfo::getParticle )
-                , bp::return_value_policy< bp::reference_existing_object >() );
-        
         }
         { //::PositionParticleInfo::getPosition
         
diff --git a/Core/PythonAPI/src/PythonModule.cpp b/Core/PythonAPI/src/PythonModule.cpp
index 7c172b92373..9ef86e00c34 100644
--- a/Core/PythonAPI/src/PythonModule.cpp
+++ b/Core/PythonAPI/src/PythonModule.cpp
@@ -38,6 +38,7 @@ GCC_DIAG_ON(missing-field-initializers)
 #include "FTDistribution2DGate.pypp.h"
 #include "vector_kvector_t.pypp.h"
 #include "FormFactorTruncatedSpheroid.pypp.h"
+#include "IParticle.pypp.h"
 #include "Particle.pypp.h"
 #include "FormFactorTrivial.pypp.h"
 #include "ConstKBinAxis.pypp.h"
@@ -72,6 +73,7 @@ GCC_DIAG_ON(missing-field-initializers)
 #include "FormFactorPrism6.pypp.h"
 #include "IClusteredParticles.pypp.h"
 #include "VariableBinAxis.pypp.h"
+#include "IParticle.pypp.h"
 #include "DistributionCosine.pypp.h"
 #include "FormFactorHemiEllipsoid.pypp.h"
 #include "IAxis.pypp.h"
@@ -223,6 +225,7 @@ BOOST_PYTHON_MODULE(libBornAgainCore){
     register_ILayout_class();
     register_IObservable_class();
     register_IObserver_class();
+    register_IParticle_class();
     register_IResolutionFunction2D_class();
     register_ISampleBuilder_class();
     register_ISelectionRule_class();
diff --git a/Core/Samples/inc/DiffuseParticleInfo.h b/Core/Samples/inc/DiffuseParticleInfo.h
index 0606184d160..5df37fbed5a 100644
--- a/Core/Samples/inc/DiffuseParticleInfo.h
+++ b/Core/Samples/inc/DiffuseParticleInfo.h
@@ -26,7 +26,7 @@ class BA_CORE_API_ DiffuseParticleInfo : public ParticleInfo
 {
 public:
     DiffuseParticleInfo(
-        Particle *p_particle,
+        IParticle *p_particle,
         double depth=0, double abundance=0)
         : ParticleInfo(p_particle, depth, abundance)
         , m_number_per_meso(0.0)
diff --git a/Core/Samples/inc/IParticle.h b/Core/Samples/inc/IParticle.h
new file mode 100644
index 00000000000..cc7a271f803
--- /dev/null
+++ b/Core/Samples/inc/IParticle.h
@@ -0,0 +1,142 @@
+// ************************************************************************** //
+//
+//  BornAgain: simulate and fit scattering at grazing incidence
+//
+//! @file      Samples/inc/IParticle.h
+//! @brief     Defines interface IParticle.
+//!
+//! @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 IPARTICLE_H
+#define IPARTICLE_H
+
+#include "ICompositeSample.h"
+#include "IMaterial.h"
+
+#include <memory>
+#include <boost/scoped_ptr.hpp>
+
+//! @class IParticle
+//! @ingroup samples
+//! @brief Interface for a generic particle
+
+class BA_CORE_API_ IParticle : public ICompositeSample
+{
+public:
+    virtual ~IParticle() {}
+    virtual IParticle *clone() const=0;
+
+    //! Returns a clone with inverted magnetic fields
+    virtual IParticle *cloneInvertB() const=0;
+
+    //! calls the ISampleVisitor's visit method
+    virtual void accept(ISampleVisitor *visitor) const { visitor->visit(this); }
+
+    //! Sets the refractive index of the ambient material (which influences its
+    //! scattering power)
+    virtual void setAmbientMaterial(const IMaterial* p_material) {
+        (void)p_material;
+    }
+
+    //! Returns particle's material.
+    virtual const IMaterial* getAmbientMaterial() const=0;
+
+    //! Create a form factor which includes the particle's shape,
+    //! material, ambient material, an optional transformation and an extra
+    //! scattering factor
+    virtual IFormFactor* createFormFactor(
+            complex_t wavevector_scattering_factor) const=0;
+
+    //! Sets _material_ .
+    virtual void setMaterial(const IMaterial* p_material) {
+        (void)p_material;
+    }
+
+    //! Returns particle's material.
+    virtual const IMaterial* getMaterial() const=0;
+
+    //! Returns refractive index of the particle
+    virtual complex_t getRefractiveIndex() const=0;
+
+    //! Returns transformation.
+    const Geometry::Transform3D *getPTransform3D() const {
+        return mP_transform.get();
+    }
+
+    //! Sets transformation.
+    virtual void setTransformation(const Geometry::Transform3D& transform);
+
+    //! Applies transformation by composing it with the existing one
+    virtual void applyTransformation(const Geometry::Transform3D& transform);
+
+    //! Returns form factor of the particle originating from its shape only
+    virtual const IFormFactor *getSimpleFormFactor() const=0;
+
+    //! Sets the form factor of the particle (not including scattering factor
+    //! from refractive index)
+    virtual void setSimpleFormFactor(IFormFactor* p_form_factor) {
+        (void)p_form_factor;
+    }
+
+    //! Creates list of contained particles for diffuse calculations
+    virtual std::vector<DiffuseParticleInfo *> *createDiffuseParticleInfo(
+            const ParticleInfo& parent_info) const {
+        (void)parent_info;
+        return 0;
+    }
+
+    //! Indicates whether the particle consists of an assembly of different
+    //! form factors according to a certain distribution
+    virtual bool hasDistributedFormFactor() const {
+        return false;
+    }
+
+    virtual std::vector<ParticleInfo *> createDistributedParticles(
+            size_t samples_per_particle, double factor) const {
+        (void)samples_per_particle;
+        (void)factor;
+        std::vector<ParticleInfo *> result;
+        return result;
+    }
+
+protected:
+    virtual void applyTransformationToSubParticles(
+            const Geometry::Transform3D& transform)=0;
+    std::auto_ptr<Geometry::Transform3D> mP_transform;
+};
+
+
+inline void IParticle::setTransformation(const Geometry::Transform3D &transform)
+{
+    if (!mP_transform.get()) {
+        mP_transform.reset(transform.clone());
+        applyTransformationToSubParticles(transform);
+        return;
+    }
+    boost::scoped_ptr<Geometry::Transform3D> P_inverse(
+            mP_transform->createInverse());
+    applyTransformationToSubParticles(*P_inverse);
+    mP_transform.reset(transform.clone());
+    applyTransformationToSubParticles(transform);
+}
+
+inline void IParticle::applyTransformation(const Geometry::Transform3D &transform)
+{
+    Geometry::Transform3D total_transformation;
+    if (mP_transform.get()) {
+        total_transformation = transform * (*mP_transform);
+    }
+    else {
+        total_transformation = transform;
+    }
+    mP_transform.reset(total_transformation.clone());
+    applyTransformationToSubParticles(transform);
+}
+
+#endif // IPARTICLE_H
diff --git a/Core/Samples/inc/ISampleVisitor.h b/Core/Samples/inc/ISampleVisitor.h
index afe1c7d7371..50108fece21 100644
--- a/Core/Samples/inc/ISampleVisitor.h
+++ b/Core/Samples/inc/ISampleVisitor.h
@@ -34,6 +34,7 @@ class LayerInterface;
 // -
 class MultiLayer;
 // -
+class IParticle;
 class Particle;
 class LatticeBasis;
 class MesoCrystal;
@@ -132,6 +133,7 @@ public:
 
     virtual void visit(const MultiLayer *);
 
+    virtual void visit(const IParticle *);
     virtual void visit(const Particle *);
     virtual void visit(const LatticeBasis *);
     virtual void visit(const MesoCrystal *);
diff --git a/Core/Samples/inc/Particle.h b/Core/Samples/inc/Particle.h
index 1ddfa6114bd..18a360771b4 100644
--- a/Core/Samples/inc/Particle.h
+++ b/Core/Samples/inc/Particle.h
@@ -16,7 +16,7 @@
 #ifndef PARTICLE_H
 #define PARTICLE_H
 
-#include "ICompositeSample.h"
+#include "IParticle.h"
 #include "FormFactorDecoratorMaterial.h"
 #include "FormFactorDecoratorTransformation.h"
 #include "IMaterial.h"
@@ -28,7 +28,7 @@ class DiffuseParticleInfo;
 //! @ingroup samples
 //! @brief A particle with a form factor and refractive index
 
-class BA_CORE_API_ Particle : public ICompositeSample
+class BA_CORE_API_ Particle : public IParticle
 {
 public:
     Particle();
@@ -67,7 +67,7 @@ public:
     virtual IFormFactor* createFormFactor(
             complex_t wavevector_scattering_factor) const;
 
-    //! Sets _material_ and _thickness_.
+    //! Sets _material_.
     virtual void setMaterial(const IMaterial* p_material) {
         if(p_material) {
             delete mp_material;
@@ -85,16 +85,6 @@ public:
                             : complex_t(0,0));
     }
 
-    //! Returns transformation.
-    const Geometry::Transform3D *getPTransform3D() const
-    { return mP_transform.get(); }
-
-    //! Sets transformation.
-    virtual void setTransformation(const Geometry::Transform3D& transform);
-
-    //! Applies transformation by composing it with the existing one
-    virtual void applyTransformation(const Geometry::Transform3D& transform);
-
     //! Returns form factor of the particle originating from its shape only
     virtual const IFormFactor *getSimpleFormFactor() const {
         return mp_form_factor;
@@ -123,8 +113,6 @@ protected:
     IMaterial* mp_material;
     IMaterial* mp_ambient_material;
     IFormFactor* mp_form_factor;
-    std::auto_ptr<Geometry::Transform3D> mP_transform;
-    //!< pointer to the form factor
 };
 
 #endif // PARTICLE_H
diff --git a/Core/Samples/inc/ParticleCollection.h b/Core/Samples/inc/ParticleCollection.h
new file mode 100644
index 00000000000..ada3fee6466
--- /dev/null
+++ b/Core/Samples/inc/ParticleCollection.h
@@ -0,0 +1,93 @@
+// ************************************************************************** //
+//
+//  BornAgain: simulate and fit scattering at grazing incidence
+//
+//! @file      Samples/inc/ParticleCollection.h
+//! @brief     Defines class ParticleCollection.
+//!
+//! @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 PARTICLECOLLECTION_H
+#define PARTICLECOLLECTION_H
+
+#include "IParticle.h"
+#include "ParameterDistribution.h"
+
+class ParticleInfo;
+class DiffuseParticleInfo;
+
+//! @class ParticleCollection
+//! @ingroup samples
+//! @brief A particle with a form factor and refractive index
+
+class BA_CORE_API_ ParticleCollection : public IParticle
+{
+public:
+    ParticleCollection(const IParticle& prototype,
+                       const ParameterDistribution& par_distr);
+
+
+    virtual ~ParticleCollection() {}
+    virtual ParticleCollection *clone() const;
+
+    //! Returns a clone with inverted magnetic fields
+    virtual ParticleCollection *cloneInvertB() const;
+
+    //! calls the ISampleVisitor's visit method
+    virtual void accept(ISampleVisitor *visitor) const { visitor->visit(this); }
+
+    //! Sets the refractive index of the ambient material (which influences its
+    //! scattering power)
+    virtual void setAmbientMaterial(const IMaterial* p_material) {
+        mP_particle->setAmbientMaterial(p_material);
+    }
+
+    //! Returns particle's material.
+    virtual const IMaterial* getAmbientMaterial() const {
+        return mP_particle->getAmbientMaterial();
+    }
+
+    //! Should not be called for objects of this class:
+    //! The object should spawn particles that will create the
+    //! required form factors
+    virtual IFormFactor* createFormFactor(
+            complex_t wavevector_scattering_factor) const;
+
+    //! Sets _material_.
+    virtual void setMaterial(const IMaterial* p_material) {
+        if(p_material) {
+            mP_particle->setMaterial(p_material);
+        }
+    }
+
+    //! Returns particle's material.
+    virtual const IMaterial* getMaterial() const {
+        return mP_particle->getMaterial();
+    }
+
+    //! Returns refractive index of the particle
+    virtual complex_t getRefractiveIndex() const {
+        return mP_particle->getRefractiveIndex();
+    }
+
+    //! Returns form factor of the particle originating from its shape only
+    virtual const IFormFactor *getSimpleFormFactor() const;
+
+
+protected:
+    std::auto_ptr<IParticle> mP_particle;
+    ParameterDistribution m_par_distribution;
+    //! Propagates a transformation to child particles
+    virtual void applyTransformationToSubParticles(
+            const Geometry::Transform3D& transform);
+};
+
+#endif // PARTICLECOLLECTION_H
+
+
diff --git a/Core/Samples/inc/ParticleInfo.h b/Core/Samples/inc/ParticleInfo.h
index a5b4e374e83..288e92a4d45 100644
--- a/Core/Samples/inc/ParticleInfo.h
+++ b/Core/Samples/inc/ParticleInfo.h
@@ -17,7 +17,7 @@
 #define PARTICLEINFO_H
 
 #include "ICompositeSample.h"
-#include "Particle.h"
+#include "IParticle.h"
 
 //! @class ParticleInfo
 //! @ingroup samples
@@ -28,31 +28,31 @@
 class BA_CORE_API_ ParticleInfo : public ICompositeSample
 {
 public:
-    ParticleInfo(Particle *p_particle,
+    ParticleInfo(IParticle *p_particle,
                  double depth=0, double abundance=0);
-    ParticleInfo(const Particle& p_particle,
+    ParticleInfo(const IParticle& p_particle,
                  double depth=0, double abundance=0);
 
-    virtual ~ParticleInfo() { delete mp_particle; }
+    virtual ~ParticleInfo() {}
 
     virtual ParticleInfo *clone() const
     {
         return new ParticleInfo(
-            mp_particle->clone(), m_depth, m_abundance);
+            mP_particle->clone(), m_depth, m_abundance);
     }
 
     //! Returns a clone with inverted magnetic fields
     virtual ParticleInfo *cloneInvertB() const
     {
         return new ParticleInfo(
-            mp_particle->cloneInvertB(), m_depth, m_abundance);
+            mP_particle->cloneInvertB(), m_depth, m_abundance);
     }
 
     //! calls the ISampleVisitor's visit method
     virtual void accept(ISampleVisitor *visitor) const { visitor->visit(this); }
 
     //! Returns particle.
-    const Particle *getParticle() const { return mp_particle; }
+    const IParticle *getParticle() const { return mP_particle.get(); }
 
     //! Returns depth.
     double getDepth() const { return m_depth; }
@@ -68,7 +68,7 @@ public:
 
     //! Sets the ambient material
     void setAmbientMaterial(const IMaterial *p_material) {
-        mp_particle->setAmbientMaterial(p_material);
+        mP_particle->setAmbientMaterial(p_material);
     }
 
 protected:
@@ -76,7 +76,7 @@ protected:
 
     virtual void print(std::ostream& ostr) const;
 
-    Particle *mp_particle;
+    std::auto_ptr<IParticle> mP_particle;
     double m_depth;
     double m_abundance;
 };
diff --git a/Core/Samples/inc/ParticleLayout.h b/Core/Samples/inc/ParticleLayout.h
index e6880e7d7bf..30cf186810b 100644
--- a/Core/Samples/inc/ParticleLayout.h
+++ b/Core/Samples/inc/ParticleLayout.h
@@ -30,7 +30,7 @@ class BA_CORE_API_ ParticleLayout : public ILayout
 public:
     ParticleLayout();
     ParticleLayout(
-        const Particle& p_particle, double depth=0., double abundance=1.);
+        const IParticle& particle, double depth=0., double abundance=1.);
 
     virtual ~ParticleLayout();
 
@@ -44,11 +44,11 @@ public:
 
     //! Adds generic particle
     void addParticle(
-        const Particle& p_particle, const Geometry::Transform3D& transform,
+        const IParticle& particle, const Geometry::Transform3D& transform,
         double depth=0.0, double abundance=1.0);
 
     //! Adds particle without rotation
-    void addParticle(const Particle& particle, double depth=0.0,
+    void addParticle(const IParticle& particle, double depth=0.0,
                      double abundance=1.0);
 
     //! Adds particle info
diff --git a/Core/Samples/inc/PositionParticleInfo.h b/Core/Samples/inc/PositionParticleInfo.h
index 1dd931b06d9..9c1f5f2cbdd 100644
--- a/Core/Samples/inc/PositionParticleInfo.h
+++ b/Core/Samples/inc/PositionParticleInfo.h
@@ -29,10 +29,10 @@ class BA_CORE_API_ PositionParticleInfo : public ParticleInfo
 {
 public:
     PositionParticleInfo(
-        Particle *p_particle, kvector_t position, double abundance=0);
+        IParticle *p_particle, kvector_t position, double abundance=0);
 
     PositionParticleInfo(
-        const Particle& particle, kvector_t position, double abundance=0);
+        const IParticle& particle, kvector_t position, double abundance=0);
 
     virtual ~PositionParticleInfo() {}
 
@@ -41,9 +41,6 @@ public:
     //! Calls the ISampleVisitor's visit method
     virtual void accept(ISampleVisitor *visitor) const { visitor->visit(this); }
 
-    //! Returns particle.
-    const Particle *getParticle() const { return mp_particle; }
-
     //! Returns particle position, including depth.
     kvector_t getPosition() const
     { return kvector_t(m_pos_x, m_pos_y, -m_depth); }
diff --git a/Core/Samples/src/ISampleVisitor.cpp b/Core/Samples/src/ISampleVisitor.cpp
index d06e3e55f61..56b0dc0053a 100644
--- a/Core/Samples/src/ISampleVisitor.cpp
+++ b/Core/Samples/src/ISampleVisitor.cpp
@@ -90,6 +90,11 @@ void ISampleVisitor::visit(const MultiLayer *)
     throw NotImplementedException("ISampleVisitor::visit(const MultiLayer *) -> Error. Not implemented.");
 }
 
+void ISampleVisitor::visit(const IParticle *)
+{
+    throw NotImplementedException("ISampleVisitor::visit(const IParticle *) -> Error. Not implemented.");
+}
+
 
 void ISampleVisitor::visit(const Particle *)
 {
diff --git a/Core/Samples/src/Particle.cpp b/Core/Samples/src/Particle.cpp
index 29c68ee8f25..4df8d9c7095 100644
--- a/Core/Samples/src/Particle.cpp
+++ b/Core/Samples/src/Particle.cpp
@@ -32,7 +32,6 @@ Particle::Particle(const IMaterial &p_material)
     : mp_material(p_material.clone())
     , mp_ambient_material(0)
     , mp_form_factor(0)
-    , mP_transform(0)
 {
     setName("Particle");
 }
@@ -42,7 +41,6 @@ Particle::Particle(const IMaterial &p_material, const IFormFactor &form_factor)
     : mp_material(p_material.clone())
     , mp_ambient_material(0)
     , mp_form_factor(form_factor.clone())
-    , mP_transform(0)
 {
     setName("Particle");
     registerChild(mp_form_factor);
@@ -54,9 +52,9 @@ Particle::Particle(const IMaterial &p_material, const IFormFactor& form_factor,
     : mp_material(p_material.clone())
     , mp_ambient_material(0)
     , mp_form_factor(form_factor.clone())
-    , mP_transform(transform.clone())
 {
     setName("Particle");
+    mP_transform.reset(transform.clone());
     registerChild(mp_form_factor);
 }
 
@@ -66,9 +64,9 @@ Particle::Particle(IMaterial *p_material, IFormFactor *form_factor,
     : mp_material(p_material)
     , mp_ambient_material(0)
     , mp_form_factor(form_factor)
-    , mP_transform(transform)
 {
     setName("Particle");
+    mP_transform.reset(transform);
     registerChild(mp_form_factor);
 }
 
@@ -157,33 +155,6 @@ std::vector<ParticleInfo*> Particle::createDistributedParticles(
     return result;
 }
 
-void Particle::setTransformation(const Geometry::Transform3D& transform)
-{
-    if (!mP_transform.get()) {
-        mP_transform.reset(transform.clone());
-        applyTransformationToSubParticles(transform);
-        return;
-    }
-    boost::scoped_ptr<Geometry::Transform3D> P_inverse(
-            mP_transform->createInverse());
-    applyTransformationToSubParticles(*P_inverse);
-    mP_transform.reset(transform.clone());
-    applyTransformationToSubParticles(transform);
-}
-
-void Particle::applyTransformation(const Geometry::Transform3D& transform)
-{
-    Geometry::Transform3D total_transformation;
-    if (mP_transform.get()) {
-        total_transformation = transform * (*mP_transform);
-    }
-    else {
-        total_transformation = transform;
-    }
-    mP_transform.reset(total_transformation.clone());
-    applyTransformationToSubParticles(transform);
-}
-
 void Particle::setSimpleFormFactor(IFormFactor* p_form_factor)
 {
     if (!p_form_factor) return;
diff --git a/Core/Samples/src/ParticleCollection.cpp b/Core/Samples/src/ParticleCollection.cpp
new file mode 100644
index 00000000000..99511f5bffc
--- /dev/null
+++ b/Core/Samples/src/ParticleCollection.cpp
@@ -0,0 +1,59 @@
+// ************************************************************************** //
+//
+//  BornAgain: simulate and fit scattering at grazing incidence
+//
+//! @file      Samples/src/ParticleCollection.cpp
+//! @brief     Implements class ParticleCollection.
+//!
+//! @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 "ParticleCollection.h"
+
+
+ParticleCollection::ParticleCollection(const IParticle &prototype,
+                                       const ParameterDistribution &par_distr)
+    : m_par_distribution(par_distr)
+{
+    mP_particle.reset(prototype.clone());
+    setName("ParticleCollection");
+}
+
+ParticleCollection *ParticleCollection::clone() const
+{
+    ParticleCollection *p_result = new ParticleCollection(*mP_particle,
+                                                          m_par_distribution);
+    return p_result;
+}
+
+ParticleCollection *ParticleCollection::cloneInvertB() const
+{
+    throw Exceptions::NotImplementedException("ParticleCollection::"
+        "cloneInvertB: should never be called");
+}
+
+IFormFactor *ParticleCollection::createFormFactor(
+        complex_t wavevector_scattering_factor) const {
+    (void)wavevector_scattering_factor;
+    throw Exceptions::NotImplementedException("ParticleCollection::"
+        "createFormFactor: should never be called");
+}
+
+const IFormFactor *ParticleCollection::getSimpleFormFactor() const {
+    throw Exceptions::NotImplementedException("ParticleCollection::"
+        "getSimpleFormFactor: should never be called");
+}
+
+void ParticleCollection::applyTransformationToSubParticles(
+        const Geometry::Transform3D& transform)
+{
+    mP_particle->applyTransformation(transform);
+    return;
+}
+
+
diff --git a/Core/Samples/src/ParticleInfo.cpp b/Core/Samples/src/ParticleInfo.cpp
index db1dcd2e340..9b0200cd443 100644
--- a/Core/Samples/src/ParticleInfo.cpp
+++ b/Core/Samples/src/ParticleInfo.cpp
@@ -17,28 +17,28 @@
 
 
 ParticleInfo::ParticleInfo(
-    Particle *p_particle,
+    IParticle *p_particle,
     double depth,
     double abundance)
-    : mp_particle(p_particle)
+    : mP_particle(p_particle)
     , m_depth(depth)
     , m_abundance(abundance)
 {
     setName("ParticleInfo");
-    registerChild(mp_particle);
+    registerChild(mP_particle.get());
     init_parameters();
 }
 
 ParticleInfo::ParticleInfo(
-    const Particle& p_particle,
+    const IParticle& p_particle,
     double depth,
     double abundance)
-    : mp_particle(p_particle.clone())
+    : mP_particle(p_particle.clone())
     , m_depth(depth)
     , m_abundance(abundance)
 {
     setName("ParticleInfo");
-    registerChild(mp_particle);
+    registerChild(mP_particle.get());
     init_parameters();
 }
 
diff --git a/Core/Samples/src/ParticleLayout.cpp b/Core/Samples/src/ParticleLayout.cpp
index 2332ad1fa40..a558425411e 100644
--- a/Core/Samples/src/ParticleLayout.cpp
+++ b/Core/Samples/src/ParticleLayout.cpp
@@ -29,11 +29,11 @@ ParticleLayout::ParticleLayout()
 }
 
 ParticleLayout::ParticleLayout(
-        const Particle& p_particle, double depth, double abundance)
+        const IParticle& particle, double depth, double abundance)
 : m_total_abundance(0.0)
 {
     setName("ParticleLayout");
-    addParticle(p_particle, depth, abundance);
+    addParticle(particle, depth, abundance);
 }
 
 ParticleLayout::~ParticleLayout()
@@ -80,14 +80,14 @@ ParticleLayout* ParticleLayout::cloneInvertB() const
 
 //! Adds generic particle, &-version.
 void ParticleLayout::addParticle(
-    const Particle& p_particle, const Geometry::Transform3D& transform,
+    const IParticle& p_particle, const Geometry::Transform3D& transform,
     double depth, double abundance)
 {
     if(!abundance) {
         throw LogicErrorException("ParticleLayout::addParticle() ->"
                 " Error! Abundance can't be equal to 0.0");
     }
-    Particle *p_particle_clone = p_particle.clone();
+    IParticle *p_particle_clone = p_particle.clone();
     p_particle_clone->setTransformation(transform);
     addAndRegisterParticleInfo(
         new ParticleInfo(p_particle_clone, depth, abundance));
@@ -95,10 +95,10 @@ void ParticleLayout::addParticle(
 
 //! Adds particle without rotation, &-version.
 void ParticleLayout::addParticle(
-    const Particle& p_particle,
+    const IParticle& p_particle,
     double depth, double abundance)
 {
-    Particle *p_particle_clone = p_particle.clone();
+    IParticle *p_particle_clone = p_particle.clone();
     addAndRegisterParticleInfo(
         new ParticleInfo(p_particle_clone, depth, abundance));
 }
diff --git a/Core/Samples/src/PositionParticleInfo.cpp b/Core/Samples/src/PositionParticleInfo.cpp
index 6c8e6cca065..15a2798b172 100644
--- a/Core/Samples/src/PositionParticleInfo.cpp
+++ b/Core/Samples/src/PositionParticleInfo.cpp
@@ -17,7 +17,7 @@
 #include <iostream>
 
 PositionParticleInfo::PositionParticleInfo(
-    Particle* p_particle, kvector_t position, double abundance)
+    IParticle* p_particle, kvector_t position, double abundance)
     : ParticleInfo(p_particle, position.z(), abundance)
     , m_pos_x(position.x())
     , m_pos_y(position.y())
@@ -27,7 +27,7 @@ PositionParticleInfo::PositionParticleInfo(
 }
 
 PositionParticleInfo::PositionParticleInfo(
-    const Particle& particle, kvector_t position, double abundance)
+    const IParticle& particle, kvector_t position, double abundance)
     : ParticleInfo(particle.clone(), position.z(), abundance)
     , m_pos_x(position.x())
     , m_pos_y(position.y())
@@ -40,7 +40,7 @@ PositionParticleInfo* PositionParticleInfo::clone() const
 {
     kvector_t position(m_pos_x, m_pos_y, -m_depth);
     return new PositionParticleInfo(
-        mp_particle->clone(), position, m_abundance);
+        mP_particle->clone(), position, m_abundance);
 }
 
 void PositionParticleInfo::setPosition(kvector_t position)
diff --git a/Core/Tools/inc/Compare.h b/Core/Tools/inc/Compare.h
index 6c93e355c58..b637c6c36d9 100644
--- a/Core/Tools/inc/Compare.h
+++ b/Core/Tools/inc/Compare.h
@@ -3,7 +3,7 @@
 #include<iostream>
 #include "FormFactors.h"
 #include "Materials.h"
-#include "Particle.h"
+#include "IParticle.h"
 #include "ParticleLayout.h"
 #include "ParticleInfo.h"
 
@@ -36,7 +36,7 @@ public:
     bool compareFormFactorTruncatedSphere(const FormFactorTruncatedSphere *a,const FormFactorTruncatedSphere *b);
     bool compareFormFactorTruncatedSpheroid(const FormFactorTruncatedSpheroid *a,const FormFactorTruncatedSpheroid *b);
     bool compareMaterial(const IMaterial *a,const IMaterial *b);
-    bool compareParticle(const Particle *a,const Particle *b);
+    bool compareParticle(const IParticle *a,const IParticle *b);
     bool compareParticleLayout(const ParticleLayout *a, const ParticleLayout *b);
 };
 
diff --git a/Core/Tools/inc/LabelSample.h b/Core/Tools/inc/LabelSample.h
index 32e2ec823b2..73d7d269e66 100644
--- a/Core/Tools/inc/LabelSample.h
+++ b/Core/Tools/inc/LabelSample.h
@@ -3,7 +3,7 @@
 #include <map>
 #include "MultiLayer.h"
 #include "Layer.h"
-#include "Particle.h"
+#include "IParticle.h"
 #include "ParticleLayout.h"
 
 //static std::map<const Layer *,std::string> m_layerLabel;
@@ -28,7 +28,7 @@ public:
     std::string getLabel(const Layer *sample);
     std::string getLabel(const LayerRoughness *sample);
     std::string getLabel(const MultiLayer *sample);
-    std::string getLabel(const Particle *sample);
+    std::string getLabel(const IParticle *sample);
     std::string getLabel(const ParticleCoreShell *sample);
     std::string getLabel(const ParticleInfo *sample);
     std::string getLabel(const ILayout *sample);
diff --git a/Core/Tools/inc/ParameterDistribution.h b/Core/Tools/inc/ParameterDistribution.h
index 89d95b6b801..91e26610c70 100644
--- a/Core/Tools/inc/ParameterDistribution.h
+++ b/Core/Tools/inc/ParameterDistribution.h
@@ -28,27 +28,26 @@ class IDistribution1D;
 class BA_CORE_API_ ParameterDistribution : public IParameterized
 {
 public:
-	ParameterDistribution(const std::string &name);
-	ParameterDistribution(const ParameterDistribution &other);
-	~ParameterDistribution();
+    ParameterDistribution(const std::string &par_name,
+                          const IDistribution1D &distribution,
+                          size_t nbr_samples, double sigma_factor=0.0);
+    ParameterDistribution(const ParameterDistribution &other);
+    ~ParameterDistribution();
 
-	//! Overload assignment operator
-	ParameterDistribution& operator=(const ParameterDistribution &other);
+    //! Overload assignment operator
+    ParameterDistribution& operator=(const ParameterDistribution &other);
 
-	//! set the distribution type, number of samples and
-	//! the range of sample values
-	void setDistribution(const IDistribution1D &distribution,
-			size_t nbr_samples, double sigma_factor=0.0);
+    ParameterDistribution& linkParameter(std::string par_name);
 
-	//! get the parameter's name
-	std::string getParameterName() const {
-		return m_name;
-	}
+    //! get the main parameter's name
+    std::string getMainParameterName() const {
+        return m_name;
+    }
 
-	//! get number of samples for this distribution
-	size_t getNbrSamples() const {
-		return m_nbr_samples;
-	}
+    //! get number of samples for this distribution
+    size_t getNbrSamples() const {
+        return m_nbr_samples;
+    }
 
     //! generate list of sampled values with their weight
     std::vector<ParameterSample> generateSamples() const;
@@ -56,10 +55,11 @@ protected:
     //! Registers some class members for later access via parameter pool
     void init_parameters();
 private:
-	std::string m_name;
-	size_t m_nbr_samples;
-	double m_sigma_factor;
-	std::auto_ptr<IDistribution1D> mP_distribution;
+    std::string m_name;
+    std::auto_ptr<IDistribution1D> mP_distribution;
+    size_t m_nbr_samples;
+    double m_sigma_factor;
+    std::vector<std::string> m_linked_par_names;
 };
 
 
diff --git a/Core/Tools/src/Compare.cpp b/Core/Tools/src/Compare.cpp
index a4e85bb547c..2369717f520 100644
--- a/Core/Tools/src/Compare.cpp
+++ b/Core/Tools/src/Compare.cpp
@@ -401,7 +401,7 @@ bool Compare::compareMaterial(const IMaterial *a,const IMaterial *b)
         return 0;
 }
 
-bool Compare::compareParticle(const Particle *a,const Particle *b)
+bool Compare::compareParticle(const IParticle *a,const IParticle *b)
 {
     if (compareMaterial(a->getMaterial(),b->getMaterial()) == 1
             && compareFormFactor(a->getSimpleFormFactor(),b->getSimpleFormFactor()) == 1)
diff --git a/Core/Tools/src/LabelSample.cpp b/Core/Tools/src/LabelSample.cpp
index 2a8d08eab94..dc883299c05 100644
--- a/Core/Tools/src/LabelSample.cpp
+++ b/Core/Tools/src/LabelSample.cpp
@@ -37,12 +37,14 @@ std::string LabelSample::getLabel(const MultiLayer *sample)
     return m_multiLayerLabel[sample];
 }
 
-std::string LabelSample::getLabel(const Particle *sample)
+std::string LabelSample::getLabel(const IParticle *sample)
 {
-    if (const ParticleCoreShell *pcs = dynamic_cast<const ParticleCoreShell *>(sample))
+    if (const ParticleCoreShell *pcs = dynamic_cast<const ParticleCoreShell*>(sample))
         return m_particleCoreShellLabel[pcs];
-    else
-        return m_particleLabel[sample];
+    if (const Particle *p = dynamic_cast<const Particle*>(sample))
+        return m_particleLabel[p];
+    throw Exceptions::NotImplementedException("LabelSample::getLabel: called"
+                                              " for unknown IParticle type");
 }
 
 std::string LabelSample::getLabel(const ParticleCoreShell *sample)
diff --git a/Core/Tools/src/ParameterDistribution.cpp b/Core/Tools/src/ParameterDistribution.cpp
index 40b9ffa2c4c..673e729664e 100644
--- a/Core/Tools/src/ParameterDistribution.cpp
+++ b/Core/Tools/src/ParameterDistribution.cpp
@@ -18,24 +18,33 @@
 #include "Exceptions.h"
 #include "Distributions.h"
 
-ParameterDistribution::ParameterDistribution(const std::string& name)
-: IParameterized("ParameterDistribution")
-, m_name(name)
-, m_nbr_samples(0)
-, m_sigma_factor(0.0)
+
+ParameterDistribution::ParameterDistribution(const std::string &par_name,
+    const IDistribution1D &distribution, size_t nbr_samples,
+    double sigma_factor)
+    : IParameterized("ParameterDistribution")
+    , m_name(par_name)
+    , m_nbr_samples(nbr_samples)
+    , m_sigma_factor(sigma_factor)
 {
-	init_parameters();
+    mP_distribution.reset(distribution.clone());
+    if (m_sigma_factor < 0.0) {
+        throw Exceptions::RuntimeErrorException(
+                "ParameterDistribution::setDistribution: "
+                "sigma factor cannot be negative");
+    }
+    init_parameters();
 }
 
-ParameterDistribution::ParameterDistribution(
-		const ParameterDistribution& other)
+ParameterDistribution::ParameterDistribution(const ParameterDistribution& other)
 : IParameterized("ParameterDistribution")
 , m_name(other.m_name)
 , m_nbr_samples(other.m_nbr_samples)
 , m_sigma_factor(other.m_sigma_factor)
+, m_linked_par_names(other.m_linked_par_names)
 {
-	mP_distribution.reset(other.mP_distribution->clone());
-	init_parameters();
+    mP_distribution.reset(other.mP_distribution->clone());
+    init_parameters();
 }
 
 ParameterDistribution::~ParameterDistribution()
@@ -43,34 +52,28 @@ ParameterDistribution::~ParameterDistribution()
 }
 
 ParameterDistribution& ParameterDistribution::operator=(
-		const ParameterDistribution& other)
+        const ParameterDistribution& other)
 {
-	if (this != &other) {
-		m_name = other.m_name;
-		m_nbr_samples = other.m_nbr_samples;
-		m_sigma_factor = other.m_sigma_factor;
-		mP_distribution.reset(other.mP_distribution->clone());
-		init_parameters();
-	}
-	return *this;
+    if (this != &other) {
+        m_name = other.m_name;
+        m_nbr_samples = other.m_nbr_samples;
+        m_sigma_factor = other.m_sigma_factor;
+        mP_distribution.reset(other.mP_distribution->clone());
+        m_linked_par_names = other.m_linked_par_names;
+        init_parameters();
+    }
+    return *this;
 }
 
-void ParameterDistribution::setDistribution(const IDistribution1D& distribution,
-		size_t nbr_samples, double sigma_factor)
+ParameterDistribution &ParameterDistribution::linkParameter(std::string par_name)
 {
-	mP_distribution.reset(distribution.clone());
-	m_nbr_samples = nbr_samples;
-	if (sigma_factor < 0.0) {
-		throw Exceptions::RuntimeErrorException(
-				"ParameterDistribution::setDistribution: "
-				"sigma factor cannot be negative");
-	}
-	m_sigma_factor = sigma_factor;
+    m_linked_par_names.push_back(par_name);
+    return *this;
 }
 
 std::vector<ParameterSample> ParameterDistribution::generateSamples() const
 {
-	return mP_distribution->generateSamples(m_nbr_samples, m_sigma_factor);
+    return mP_distribution->generateSamples(m_nbr_samples, m_sigma_factor);
 }
 
 void ParameterDistribution::init_parameters()
diff --git a/dev-tools/python-bindings/settings_core.py b/dev-tools/python-bindings/settings_core.py
index 0a18d3b4a2f..a92db46dbe2 100644
--- a/dev-tools/python-bindings/settings_core.py
+++ b/dev-tools/python-bindings/settings_core.py
@@ -113,12 +113,11 @@ include_classes = [
     "IObserver",
     "IObservable",
     "IParameterized",
+    "IParticle",
     "IResolutionFunction2D",
     "IntensityDataFunctions",
     "ISample",
     "ISampleBuilder",
-    #"SampleBuilder_t",
-    #"ISampleVisitor",
     "ISelectionRule",
     "Transform3D",
     "Instrument",
-- 
GitLab