From e799e5215284645ba85dcc21e280f64e873cacd6 Mon Sep 17 00:00:00 2001
From: pospelov <pospelov@fz-juelich.de>
Date: Tue, 26 Jun 2012 17:53:22 +0200
Subject: [PATCH] New classes for boost python interface

---
 App/inc/DrawHelper.h                          |   4 +
 App/src/TestFresnelCoeff.cpp                  |   2 +-
 App/src/main.cpp                              |   6 +-
 .../inc/PythonAlgorithmsInterface.h           |  22 ++
 .../src/PythonAlgorithmsInterface.cpp         |  11 +
 Core/Core.pro                                 |  13 +-
 Core/Samples/inc/HomogeneousMaterial.h        |   4 +-
 Core/Samples/inc/IMaterial.h                  |   3 +-
 Core/Samples/inc/ISample.h                    |   8 +-
 Core/Samples/inc/Layer.h                      |   2 +-
 Core/Samples/inc/LayerRoughness.h             |   2 +-
 Core/Samples/inc/MaterialManager.h            |  28 +-
 Core/Samples/inc/MultiLayer.h                 |  16 +-
 Core/Samples/inc/ParameterPool.h              |   3 -
 Core/Samples/inc/PythonSamplesInterface.h     |  24 ++
 Core/Samples/src/MaterialManager.cpp          |   7 +-
 Core/Samples/src/MultiLayer.cpp               |  13 +-
 Core/Samples/src/PythonSamplesInterface.cpp   | 331 ++++++++++++++++++
 Core/Tools/inc/ISingleton.h                   |  10 +-
 Core/Tools/inc/PythonModule.h                 |  23 ++
 Core/Tools/inc/PythonToolsInterface.h         |  22 ++
 Core/Tools/src/PythonModule.cpp               |  11 +
 Core/Tools/src/PythonToolsInterface.cpp       |  61 ++++
 GISASFW.pro                                   |   5 +-
 24 files changed, 590 insertions(+), 41 deletions(-)
 create mode 100644 Core/Algorithms/inc/PythonAlgorithmsInterface.h
 create mode 100644 Core/Algorithms/src/PythonAlgorithmsInterface.cpp
 create mode 100644 Core/Samples/inc/PythonSamplesInterface.h
 create mode 100644 Core/Samples/src/PythonSamplesInterface.cpp
 create mode 100644 Core/Tools/inc/PythonModule.h
 create mode 100644 Core/Tools/inc/PythonToolsInterface.h
 create mode 100644 Core/Tools/src/PythonModule.cpp
 create mode 100644 Core/Tools/src/PythonToolsInterface.cpp

diff --git a/App/inc/DrawHelper.h b/App/inc/DrawHelper.h
index 8978cf61bf6..e5bfd0d7d2e 100644
--- a/App/inc/DrawHelper.h
+++ b/App/inc/DrawHelper.h
@@ -50,6 +50,10 @@ public:
   //! draw multilayer structure in TPad
   void DrawMultilayer(const MultiLayer *sample);
 
+protected:
+    DrawHelper(){}
+    friend class ISingleton<DrawHelper >;
+
 private:
 //  /// prevents client from creating a copy of the singleton
 //  DrawHelper();
diff --git a/App/src/TestFresnelCoeff.cpp b/App/src/TestFresnelCoeff.cpp
index 8e53314a73c..8806e805950 100644
--- a/App/src/TestFresnelCoeff.cpp
+++ b/App/src/TestFresnelCoeff.cpp
@@ -237,7 +237,7 @@ void TestFresnelCoeff::test_roughness()
 {
     m_sample = dynamic_cast<MultiLayer *>(SampleFactory::instance().createItem("SimpleMultilayer"));
 
-    m_sample->print();
+    std::cout << *m_sample << std::endl;
     ParameterPool *newpool = m_sample->createParameterTree();
     std::cout << *newpool << std::endl;
 
diff --git a/App/src/main.cpp b/App/src/main.cpp
index 1b1748c45c9..1d3962c0bd2 100644
--- a/App/src/main.cpp
+++ b/App/src/main.cpp
@@ -6,12 +6,16 @@
 #include <string>
 #include "TApplication.h"
 
-
+#include "MaterialManager.h"
 
 int main(int argc, char **argv)
 {
     std::cout << "Hello Brave New World!" << std::endl;
 
+//    MaterialManager *mm = new MaterialManager;
+//    std::cout << *mm << std::endl;
+    return 0;
+
     CommandLine args(argc, argv); // parsing command line arguments
 
     TApplication theApp("theApp", &argc, argv);
diff --git a/Core/Algorithms/inc/PythonAlgorithmsInterface.h b/Core/Algorithms/inc/PythonAlgorithmsInterface.h
new file mode 100644
index 00000000000..7b19b12018f
--- /dev/null
+++ b/Core/Algorithms/inc/PythonAlgorithmsInterface.h
@@ -0,0 +1,22 @@
+#ifndef PYTHONALGORITHMSINTERFACE_H
+#define PYTHONALGORITHMSINTERFACE_H
+// ********************************************************************
+// * The BornAgain project                                            *
+// * Simulation of neutron and x-ray scattering at grazing incidence  *
+// *                                                                  *
+// * LICENSE AND DISCLAIMER                                           *
+// * Lorem ipsum dolor sit amet, consectetur adipiscing elit.  Mauris *
+// * eget quam orci. Quisque  porta  varius  dui,  quis  posuere nibh *
+// * mollis quis. Mauris commodo rhoncus porttitor.                   *
+// ********************************************************************
+//! @file   PythonAlgorithmsInterface.h
+//! @brief  Collection of interfaces for python
+//! @author Scientific Computing Group at FRM II
+//! @date   22.06.2012
+
+
+namespace PythonInterface {
+    void export_algorithms();
+}
+
+#endif // PYTHONALGORITHMSINTERFACE_H
diff --git a/Core/Algorithms/src/PythonAlgorithmsInterface.cpp b/Core/Algorithms/src/PythonAlgorithmsInterface.cpp
new file mode 100644
index 00000000000..67a24d0da63
--- /dev/null
+++ b/Core/Algorithms/src/PythonAlgorithmsInterface.cpp
@@ -0,0 +1,11 @@
+#include "PythonAlgorithmsInterface.h"
+
+#include <boost/python.hpp>
+using namespace boost::python;
+
+
+void PythonInterface::export_algorithms()
+{
+
+}
+
diff --git a/Core/Core.pro b/Core/Core.pro
index beae65e3c5d..2a1cb37b259 100644
--- a/Core/Core.pro
+++ b/Core/Core.pro
@@ -14,6 +14,7 @@ SOURCES += \
     Algorithms/src/DWBAFormFactor.cpp \
     Algorithms/src/DWBAFormFactorConstZ.cpp \
     Algorithms/src/OpticalFresnel.cpp \
+    Algorithms/src/PythonAlgorithmsInterface.cpp \
     \
     Samples/src/FormFactorCylinder.cpp \
     Samples/src/HomogeneousMaterial.cpp \
@@ -31,6 +32,7 @@ SOURCES += \
     Samples/src/NanoParticle.cpp \
     Samples/src/NanoParticleDecorator.cpp \
     Samples/src/ParameterPool.cpp \
+    Samples/src/PythonSamplesInterface.cpp \
     \
     Tools/src/Convolve.cpp \
     Tools/src/DoubleToComplexInterpolatingFunction.cpp \
@@ -40,6 +42,8 @@ SOURCES += \
     Tools/src/ISingleton.cpp \
     Tools/src/MathFunctions.cpp \
     Tools/src/OutputData.cpp \
+    Tools/src/PythonModule.cpp \
+    Tools/src/PythonToolsInterface.cpp \
     Tools/src/StochasticGaussian.cpp \
     Tools/src/Types.cpp \
     Tools/src/Utils.cpp
@@ -50,6 +54,7 @@ HEADERS += \
     Algorithms/inc/DWBAFormFactorConstZ.h \
     Algorithms/inc/ISimulation.h \
     Algorithms/inc/OpticalFresnel.h \
+    Algorithms/inc/PythonAlgorithmsInterface.h \
     \
     Samples/inc/FormFactorCylinder.h \
     Samples/inc/HomogeneousMaterial.h \
@@ -70,6 +75,7 @@ HEADERS += \
     Samples/inc/NanoParticle.h \
     Samples/inc/NanoParticleDecorator.h \
     Samples/inc/ParameterPool.h \
+    Samples/inc/PythonSamplesInterface.h \
     \
     Tools/inc/Convolve.h \
     Tools/inc/DoubleToComplexInterpolatingFunction.h \
@@ -84,6 +90,8 @@ HEADERS += \
     Tools/inc/Numeric.h \
     Tools/inc/OutputData.h \
     Tools/inc/StochasticDiracDelta.h \
+    Tools/inc/PythonModule.h \
+    Tools/inc/PythonToolsInterface.h \
     Tools/inc/StochasticGaussian.h \
     Tools/inc/Types.h \
     Tools/inc/Units.h \
@@ -96,9 +104,10 @@ OBJECTS_DIR = obj
 
 macx {
   INCLUDEPATH += /opt/local/include
-  LIBS += -L /opt/local/lib/ -lgsl -lfftw3
+  INCLUDEPATH += /opt/local/Library/Frameworks/Python.framework/Versions/2.7/include/python2.7
+  LIBS += -L /opt/local/lib/ -lgslcblas -lgsl  -lfftw3 -lpython2.7 -lboost_python
 } else {
-  LIBS += -L /usr/lib64/ -lgsl -lgslcblas -lfftw3
+  LIBS += -L /usr/lib64/ -lgslcblas -lgsl -lfftw3 -lpython2.7 -lboost_python
 }
 
 
diff --git a/Core/Samples/inc/HomogeneousMaterial.h b/Core/Samples/inc/HomogeneousMaterial.h
index a45093538c9..509f5d2f5d9 100644
--- a/Core/Samples/inc/HomogeneousMaterial.h
+++ b/Core/Samples/inc/HomogeneousMaterial.h
@@ -41,8 +41,8 @@ public:
 protected:
     //! print material class
     virtual void print(std::ostream &ostr) const {
-        IMaterial::print(ostr);
-        ostr << " " << m_refractive_index;
+        //IMaterial::print(ostr);
+        ostr << typeid(*this).name() << " " << this << " " << m_refractive_index;
     }
 
     complex_t m_refractive_index; ///< complex index of refraction
diff --git a/Core/Samples/inc/IMaterial.h b/Core/Samples/inc/IMaterial.h
index 72339045eb6..ee475ee6d3f 100644
--- a/Core/Samples/inc/IMaterial.h
+++ b/Core/Samples/inc/IMaterial.h
@@ -16,6 +16,7 @@
 
 #include <string>
 #include <iostream>
+#include <typeinfo>
 #include "INamed.h"
 
 
@@ -41,7 +42,7 @@ public:
 protected:
     //! print material class
     virtual void print(std::ostream &ostr) const {
-        ostr << this << " '" << m_name << "'";
+        ostr << typeid(*this).name() << " " << this;
     }
 
 };
diff --git a/Core/Samples/inc/ISample.h b/Core/Samples/inc/ISample.h
index 150fd67ac67..6bc134f78ba 100644
--- a/Core/Samples/inc/ISample.h
+++ b/Core/Samples/inc/ISample.h
@@ -39,9 +39,6 @@ public:
     //! clone sample (to overload)
     virtual ISample *clone();
 
-    //! initialize pool parameters, i.e. register some of class members for later access via parameter pool (to overload)
-    virtual void init_parameters();
-
     //! (temporary for debugging) return sample Id
     long getId() const {return m_id; }
 
@@ -54,10 +51,13 @@ public:
     //! same as above, demonstration of iterators instead of nested calls
     virtual ParameterPool *createParameterTreeTest();
 
+protected:
+    //! initialize pool parameters, i.e. register some of class members for later access via parameter pool (to overload)
+    virtual void init_parameters();
+
     //! add parameters from local pool to external pool and call recursion over direct children
     virtual void addParametersToExternalPool(std::string path, ParameterPool *external_pool, int copy_number=-1);
 
-protected:
     long m_id; //! temporary debug variable to track id of instance
     static long m_id_last; //! temporary debug variable to track id of instance
 
diff --git a/Core/Samples/inc/Layer.h b/Core/Samples/inc/Layer.h
index a65197b53c8..1a0664d8fd5 100644
--- a/Core/Samples/inc/Layer.h
+++ b/Core/Samples/inc/Layer.h
@@ -56,10 +56,10 @@ public:
     //! return refractive index of the layer's material
     virtual complex_t getRefractiveIndex() const { return (dynamic_cast<const HomogeneousMaterial *>(mp_material))->getRefractiveIndex(); }
 
+private:
     //! initialize pool parameters, i.e. register some of class members for later access via parameter pool
     virtual void init_parameters();
 
-private:
     const IMaterial* mp_material;    //!< pointer to the material
     double m_thickness;              //!< layer thickness in _angstrom_
 };
diff --git a/Core/Samples/inc/LayerRoughness.h b/Core/Samples/inc/LayerRoughness.h
index 5661fbdf9d9..af70f49ddd4 100644
--- a/Core/Samples/inc/LayerRoughness.h
+++ b/Core/Samples/inc/LayerRoughness.h
@@ -55,10 +55,10 @@ public:
     //! return latteral correlation length
     inline double getLatteralCorrLength() const { return m_latteralCorrLength; }
 
+protected:
     //! initialize pool parameters, i.e. register some of class members for later access via parameter pool
     virtual void init_parameters();
 
-protected:
     double m_sigma;                //!< rms of roughness
     double m_hurstParameter;       //!< Hurst parameter which describes how jagged the interface, 0<H<=1
     double m_latteralCorrLength;   //!< latteral correlation length of the roughness
diff --git a/Core/Samples/inc/MaterialManager.h b/Core/Samples/inc/MaterialManager.h
index 2a8aeefdf58..81be9b2fd59 100644
--- a/Core/Samples/inc/MaterialManager.h
+++ b/Core/Samples/inc/MaterialManager.h
@@ -30,9 +30,19 @@
 //! It is a singleton which provides common and unique interface for
 //! material creation and access. No thread safety.
 //- -------------------------------------------------------------------
+
+//class MaterialManager;
+//typedef ISingleton<MaterialManager> MaterialManagerSingleton;
+
+//class MaterialManager: public MaterialManagerSingleton
 class MaterialManager: public ISingleton<MaterialManager>
 {
+//    friend ISingleton<MaterialManager>;
+
 public:
+    //! definition of materials container
+    typedef std::map<std::string, IMaterial *> materials_t;
+
     //! return material from database
     const IMaterial *getMaterial(const std::string &name);
 
@@ -42,12 +52,20 @@ public:
     //! clean collection of material
     void clear();
 
-    //! print material database
-    void print() const;
+    //! print material class
+    friend std::ostream &operator<<(std::ostream &ostr, const MaterialManager &m)
+    {
+        m.print(ostr); return ostr;
+    }
 
-private:
-    typedef std::map<std::string, IMaterial *> materials_t;
-    materials_t m_materials;
+protected:
+    MaterialManager(){}
+    friend class ISingleton<MaterialManager >;
+
+    //! print material class
+    virtual void print(std::ostream &ostr) const;
+
+    materials_t m_materials; //! container with defined materials
 };
 
 #endif // MATERIALMANAGER_H
diff --git a/Core/Samples/inc/MultiLayer.h b/Core/Samples/inc/MultiLayer.h
index 55fea1a2f96..fc37405c479 100644
--- a/Core/Samples/inc/MultiLayer.h
+++ b/Core/Samples/inc/MultiLayer.h
@@ -87,17 +87,20 @@ public:
     //! change thickness of layer
     void setLayerThickness(size_t i_layer, double thickness);
 
-    //! initialize pool parameters, i.e. register some of class members for later access via parameter pool
-    virtual void init_parameters();
-
-    //! print structure of multilayer
-    void print();
+    //! print class
+    friend std::ostream &operator<<(std::ostream &ostr, const MultiLayer &m)
+    {
+        m.print(ostr); return ostr;
+    }
 
 private:
     //! hiding copy constructor & assignment operator
     MultiLayer(const MultiLayer &);
     MultiLayer &operator=(const MultiLayer &);
 
+    //! print class
+    void print(std::ostream &ostr) const;
+
     //! adding the layer with simultaneous registration in parent class
     void addAndRegisterLayer(Layer *child)
     {
@@ -118,6 +121,9 @@ private:
     //! check index of interface w.r.t. vector length
     inline size_t check_interface_index(size_t i_interface) const { return i_interface < m_interfaces.size() ? i_interface : throw OutOfBoundsException("Interface index is out of bounds"); }
 
+    //! initialize pool parameters, i.e. register some of class members for later access via parameter pool
+    virtual void init_parameters();
+
     std::vector<Layer *> m_layers;                ///< stack of layers [nlayers]
     std::vector<double > m_layers_z;              ///< coordinate of layer's bottoms [nlayers]
     std::vector<LayerInterface *> m_interfaces;   ///< stack of layer interfaces [nlayers-1]
diff --git a/Core/Samples/inc/ParameterPool.h b/Core/Samples/inc/ParameterPool.h
index f82ab984700..d50452a73b5 100644
--- a/Core/Samples/inc/ParameterPool.h
+++ b/Core/Samples/inc/ParameterPool.h
@@ -63,9 +63,6 @@ public:
         obj.print(ostr); return ostr;
     }
 
-    //! print content of parameter pool on the screen
-    void print();
-
 protected:
     //! hiding copy constructors and assignment operators to allow only conscious cloning
     ParameterPool(const ParameterPool &other);
diff --git a/Core/Samples/inc/PythonSamplesInterface.h b/Core/Samples/inc/PythonSamplesInterface.h
new file mode 100644
index 00000000000..6acf085e7cc
--- /dev/null
+++ b/Core/Samples/inc/PythonSamplesInterface.h
@@ -0,0 +1,24 @@
+#ifndef PYTHONSAMPLESINTERFACE_H
+#define PYTHONSAMPLESINTERFACE_H
+// ********************************************************************
+// * The BornAgain project                                            *
+// * Simulation of neutron and x-ray scattering at grazing incidence  *
+// *                                                                  *
+// * LICENSE AND DISCLAIMER                                           *
+// * Lorem ipsum dolor sit amet, consectetur adipiscing elit.  Mauris *
+// * eget quam orci. Quisque  porta  varius  dui,  quis  posuere nibh *
+// * mollis quis. Mauris commodo rhoncus porttitor.                   *
+// ********************************************************************
+//! @file   PythonSamplesInterface.h
+//! @brief  Collection of interfaces for python
+//! @author Scientific Computing Group at FRM II
+//! @date   20.06.2012
+
+
+namespace PythonInterface {
+    void export_samples();
+}
+
+#endif // PYTHONSAMPLESINTERFACE_H
+
+
diff --git a/Core/Samples/src/MaterialManager.cpp b/Core/Samples/src/MaterialManager.cpp
index 11fd88835d1..0fe42877429 100644
--- a/Core/Samples/src/MaterialManager.cpp
+++ b/Core/Samples/src/MaterialManager.cpp
@@ -55,12 +55,13 @@ const IMaterial *MaterialManager::addHomogeneousMaterial(const std::string &name
 /* ************************************************************************* */
 // print content of material database on the screen
 /* ************************************************************************* */
-void MaterialManager::print() const
+void MaterialManager::print(std::ostream &ostr) const
 {
-    std::cout << "=== MaterialManager =========================================" << std::endl;
+    std::cout << "xxx" << std::endl;
+    ostr << typeid(*this).name() << " " << this << " nmaterials:" << m_materials.size() << std::endl;
     for(materials_t::const_iterator it = m_materials.begin(); it!= m_materials.end(); it++) {
         const IMaterial *mat = (*it).second;
-        std::cout << *mat << std::endl;
+        ostr << *mat << std::endl;
     }
 }
 
diff --git a/Core/Samples/src/MultiLayer.cpp b/Core/Samples/src/MultiLayer.cpp
index 841b58df189..95ef8fd7f4f 100644
--- a/Core/Samples/src/MultiLayer.cpp
+++ b/Core/Samples/src/MultiLayer.cpp
@@ -102,12 +102,13 @@ const LayerInterface *MultiLayer::getLayerBottomInterface(size_t i_layer) const
 /* ************************************************************************* */
 // print content of multilayer on the screen
 /* ************************************************************************* */
-void MultiLayer::print()
+void MultiLayer::print(std::ostream &ostr) const
 {
-    std::cout << "=== Multilayer =================================================" << std::endl;
+    ostr << typeid(*this).name() << " " << this;
+
     for(size_t i=0; i<getNumberOfLayers(); i++) {
         const Layer *layer = getLayer(i);
-        std::cout << " " << "LAYER  "
+        ostr << " " << "LAYER  "
                   << " " << "#" << std::left << std::setw(2)   << i
                   << " " << std::setw(16)  << layer
                   << " " << std::setw(5)   << layer->getThickness()
@@ -116,17 +117,15 @@ void MultiLayer::print()
                   << " " << (*layer->getMaterial())
                   << std::endl;
         const LayerInterface *interface = getLayerBottomInterface(i);
-        std::cout << " " << "------"
+        ostr << " " << "------"
                   << " " << std::setw(16)  << interface;
         if(interface) {
             std::cout << " " << " layers("
                       << " " << std::setw(16) << interface->getLayerTop()
                       << "," << std::setw(16) << interface->getLayerBottom() << ")";
         }
-        std::cout << std::endl;
+        ostr << std::endl;
     }
-    //std::cout << "yyy" << std::endl;
-    //std::cout << m_layers.size() << " " << m_interfaces.size() << " " << m_samples.size() << std::endl;
 }
 
 
diff --git a/Core/Samples/src/PythonSamplesInterface.cpp b/Core/Samples/src/PythonSamplesInterface.cpp
new file mode 100644
index 00000000000..181b4d84561
--- /dev/null
+++ b/Core/Samples/src/PythonSamplesInterface.cpp
@@ -0,0 +1,331 @@
+#include "PythonSamplesInterface.h"
+#include "IMaterial.h"
+#include "HomogeneousMaterial.h"
+#include "ISingleton.h"
+#include "MaterialManager.h"
+#include "LayerRoughness.h"
+#include "Layer.h"
+#include "MultiLayer.h"
+#include "ParameterPool.h"
+
+#include <boost/python.hpp>
+namespace bp = boost::python;
+
+struct Layer_wrapper : Layer, bp::wrapper< Layer > {
+
+    Layer_wrapper( )
+    : Layer( )
+      , bp::wrapper< Layer >(){
+        // null constructor
+
+    }
+
+    Layer_wrapper(::Layer const & other )
+    : Layer( boost::ref(other) )
+      , bp::wrapper< Layer >(){
+        // copy constructor
+
+    }
+
+    virtual ::IMaterial const * getMaterial(  ) const  {
+        if( bp::override func_getMaterial = this->get_override( "getMaterial" ) )
+            return func_getMaterial(  );
+        else{
+            return this->Layer::getMaterial(  );
+        }
+    }
+
+    ::IMaterial const * default_getMaterial(  ) const  {
+        return Layer::getMaterial( );
+    }
+
+    virtual void setMaterial( ::IMaterial const * p_material ) {
+        if( bp::override func_setMaterial = this->get_override( "setMaterial" ) )
+            func_setMaterial( boost::python::ptr(p_material) );
+        else{
+            this->Layer::setMaterial( boost::python::ptr(p_material) );
+        }
+    }
+
+    void default_setMaterial( ::IMaterial const * p_material ) {
+        Layer::setMaterial( boost::python::ptr(p_material) );
+    }
+
+    virtual void setMaterial( ::IMaterial const * p_material, double thickness ) {
+        if( bp::override func_setMaterial = this->get_override( "setMaterial" ) )
+            func_setMaterial( boost::python::ptr(p_material), thickness );
+        else{
+            this->Layer::setMaterial( boost::python::ptr(p_material), thickness );
+        }
+    }
+
+    void default_setMaterial( ::IMaterial const * p_material, double thickness ) {
+        Layer::setMaterial( boost::python::ptr(p_material), thickness );
+    }
+
+};
+
+
+
+void PythonInterface::export_samples()
+{
+    { //::IMaterial
+        typedef bp::class_< IMaterial > IMaterial_exposer_t;
+        IMaterial_exposer_t IMaterial_exposer = IMaterial_exposer_t( "IMaterial", bp::init< >() );
+        bp::scope IMaterial_scope( IMaterial_exposer );
+        IMaterial_exposer.def( bp::init< std::string const & >(( bp::arg("name") )) );
+        IMaterial_exposer.def( bp::init< IMaterial const & >(( bp::arg("other") )) );
+        { //::IMaterial::operator=
+
+            typedef ::IMaterial & ( ::IMaterial::*assign_function_type )( ::IMaterial const & ) ;
+
+            IMaterial_exposer.def(
+                "assign"
+                , assign_function_type( &::IMaterial::operator= )
+                , ( bp::arg("other") )
+                , bp::return_self< >() );
+
+        }
+        IMaterial_exposer.def( bp::self_ns::str( bp::self ) );
+    }
+
+    { //::HomogeneousMaterial
+        typedef bp::class_< HomogeneousMaterial, bp::bases< IMaterial > > HomogeneousMaterial_exposer_t;
+        HomogeneousMaterial_exposer_t HomogeneousMaterial_exposer = HomogeneousMaterial_exposer_t( "HomogeneousMaterial", bp::init< >() );
+        bp::scope HomogeneousMaterial_scope( HomogeneousMaterial_exposer );
+        HomogeneousMaterial_exposer.def( bp::init< complex_t >(( bp::arg("refractive_index") )) );
+        HomogeneousMaterial_exposer.def( bp::init< std::string const &, complex_t >(( bp::arg("name"), bp::arg("refractive_index") )) );
+        HomogeneousMaterial_exposer.def( bp::init< HomogeneousMaterial const & >(( bp::arg("other") )) );
+        { //::HomogeneousMaterial::getRefractiveIndex
+
+            typedef ::complex_t ( ::HomogeneousMaterial::*getRefractiveIndex_function_type )(  ) const;
+
+            HomogeneousMaterial_exposer.def(
+                "getRefractiveIndex"
+                , getRefractiveIndex_function_type( &::HomogeneousMaterial::getRefractiveIndex ) );
+
+        }
+        { //::HomogeneousMaterial::operator=
+
+            typedef ::HomogeneousMaterial & ( ::HomogeneousMaterial::*assign_function_type )( ::HomogeneousMaterial const & ) ;
+
+            HomogeneousMaterial_exposer.def(
+                "assign"
+                , assign_function_type( &::HomogeneousMaterial::operator= )
+                , ( bp::arg("other") )
+                , bp::return_self< >() );
+
+        }
+        { //::HomogeneousMaterial::setRefractiveIndex
+
+            typedef void ( ::HomogeneousMaterial::*setRefractiveIndex_function_type )( ::complex_t ) ;
+
+            HomogeneousMaterial_exposer.def(
+                "setRefractiveIndex"
+                , setRefractiveIndex_function_type( &::HomogeneousMaterial::setRefractiveIndex )
+                , ( bp::arg("refractive_index") ) );
+
+        }
+    }
+
+    bp::class_< ISingleton< MaterialManager >, boost::noncopyable >( "ISingleton_less__MaterialManager__greater_", bp::no_init )
+        .def(
+            "instance"
+            , (::MaterialManager & (*)(  ))( &::ISingleton< MaterialManager >::instance )
+            , bp::return_value_policy< bp::reference_existing_object >() )
+        .staticmethod( "instance" );
+
+    { //::Layer
+        typedef bp::class_< Layer_wrapper > Layer_exposer_t;
+        Layer_exposer_t Layer_exposer = Layer_exposer_t( "Layer", bp::init< >() );
+        bp::scope Layer_scope( Layer_exposer );
+        Layer_exposer.def( bp::init< Layer const & >(( bp::arg("other") )) );
+        { //::Layer::getMaterial
+
+            typedef ::IMaterial const * ( ::Layer::*getMaterial_function_type )(  ) const;
+            typedef ::IMaterial const * ( Layer_wrapper::*default_getMaterial_function_type )(  ) const;
+
+            Layer_exposer.def(
+                "getMaterial"
+                , getMaterial_function_type(&::Layer::getMaterial)
+                , default_getMaterial_function_type(&Layer_wrapper::default_getMaterial)
+                , bp::return_value_policy< bp::reference_existing_object >() );
+
+        }
+        { //::Layer::operator=
+
+            typedef ::Layer & ( ::Layer::*assign_function_type )( ::Layer const & ) ;
+
+            Layer_exposer.def(
+                "assign"
+                , assign_function_type( &::Layer::operator= )
+                , ( bp::arg("other") )
+                , bp::return_self< >() );
+
+        }
+        { //::Layer::setMaterial
+
+            typedef void ( ::Layer::*setMaterial_function_type )( ::IMaterial const * ) ;
+            typedef void ( Layer_wrapper::*default_setMaterial_function_type )( ::IMaterial const * ) ;
+
+            Layer_exposer.def(
+                "setMaterial"
+                , setMaterial_function_type(&::Layer::setMaterial)
+                , default_setMaterial_function_type(&Layer_wrapper::default_setMaterial)
+                , ( bp::arg("p_material") ) );
+
+        }
+        { //::Layer::setMaterial
+
+            typedef void ( ::Layer::*setMaterial_function_type )( ::IMaterial const *,double ) ;
+            typedef void ( Layer_wrapper::*default_setMaterial_function_type )( ::IMaterial const *,double ) ;
+
+            Layer_exposer.def(
+                "setMaterial"
+                , setMaterial_function_type(&::Layer::setMaterial)
+                , default_setMaterial_function_type(&Layer_wrapper::default_setMaterial)
+                , ( bp::arg("p_material"), bp::arg("thickness") ) );
+
+        }
+    }
+
+    { //::LayerRoughness
+        typedef bp::class_< LayerRoughness > LayerRoughness_exposer_t;
+        LayerRoughness_exposer_t LayerRoughness_exposer = LayerRoughness_exposer_t( "LayerRoughness", bp::init< >() );
+        bp::scope LayerRoughness_scope( LayerRoughness_exposer );
+        LayerRoughness_exposer.def( bp::init< double, double, double >(( bp::arg("sigma"), bp::arg("hurstParameter"), bp::arg("latteralCorrLength") )) );
+        LayerRoughness_exposer.def( bp::init< LayerRoughness const & >(( bp::arg("other") )) );
+        { //::LayerRoughness::getHurstParameter
+
+            typedef double ( ::LayerRoughness::*getHurstParameter_function_type )(  ) const;
+
+            LayerRoughness_exposer.def(
+                "getHurstParameter"
+                , getHurstParameter_function_type( &::LayerRoughness::getHurstParameter ) );
+
+        }
+        { //::LayerRoughness::getLatteralCorrLength
+
+            typedef double ( ::LayerRoughness::*getLatteralCorrLength_function_type )(  ) const;
+
+            LayerRoughness_exposer.def(
+                "getLatteralCorrLength"
+                , getLatteralCorrLength_function_type( &::LayerRoughness::getLatteralCorrLength ) );
+
+        }
+        { //::LayerRoughness::getSigma
+
+            typedef double ( ::LayerRoughness::*getSigma_function_type )(  ) const;
+
+            LayerRoughness_exposer.def(
+                "getSigma"
+                , getSigma_function_type( &::LayerRoughness::getSigma ) );
+
+        }
+        { //::LayerRoughness::operator=
+
+            typedef ::LayerRoughness & ( ::LayerRoughness::*assign_function_type )( ::LayerRoughness const & ) ;
+
+            LayerRoughness_exposer.def(
+                "assign"
+                , assign_function_type( &::LayerRoughness::operator= )
+                , ( bp::arg("other") )
+                , bp::return_self< >() );
+
+        }
+        { //::LayerRoughness::setHurstParameter
+
+            typedef void ( ::LayerRoughness::*setHurstParameter_function_type )( double ) ;
+
+            LayerRoughness_exposer.def(
+                "setHurstParameter"
+                , setHurstParameter_function_type( &::LayerRoughness::setHurstParameter )
+                , ( bp::arg("hurstParameter") ) );
+
+        }
+        { //::LayerRoughness::setLatteralCorrLength
+
+            typedef void ( ::LayerRoughness::*setLatteralCorrLength_function_type )( double ) ;
+
+            LayerRoughness_exposer.def(
+                "setLatteralCorrLength"
+                , setLatteralCorrLength_function_type( &::LayerRoughness::setLatteralCorrLength )
+                , ( bp::arg("latteralCorrLength") ) );
+
+        }
+        { //::LayerRoughness::setSigma
+
+            typedef void ( ::LayerRoughness::*setSigma_function_type )( double ) ;
+
+            LayerRoughness_exposer.def(
+                "setSigma"
+                , setSigma_function_type( &::LayerRoughness::setSigma )
+                , ( bp::arg("sigma") ) );
+
+        }
+    }
+
+    bp::class_< MaterialManager, bp::bases< ISingleton< MaterialManager > >, boost::noncopyable >( "MaterialManager", bp::no_init )
+        .def(
+            "addHomogeneousMaterial"
+            , (::IMaterial const * ( ::MaterialManager::* )( ::std::string const &,::complex_t ) )( &::MaterialManager::addHomogeneousMaterial )
+            , ( bp::arg("name"), bp::arg("refractive_index") )
+            , bp::return_internal_reference< >() )
+        .def(
+            "clear"
+            , (void ( ::MaterialManager::* )(  ) )( &::MaterialManager::clear ) )
+        .def(
+            "getMaterial"
+            , (::IMaterial const * ( ::MaterialManager::* )( ::std::string const & ) )( &::MaterialManager::getMaterial )
+            , ( bp::arg("name") )
+            , bp::return_internal_reference< >() )
+        .def( bp::self_ns::str( bp::self ) );
+
+    bp::class_< MultiLayer, boost::noncopyable >( "MultiLayer", bp::init< >() )
+        .def(
+            "addLayer"
+            , (void ( ::MultiLayer::* )( ::Layer const & ) )( &::MultiLayer::addLayer )
+            , ( bp::arg("p_child") ) )
+        .def(
+            "addLayerWithTopRoughness"
+            , (void ( ::MultiLayer::* )( ::Layer const &,::LayerRoughness const & ) )( &::MultiLayer::addLayerWithTopRoughness )
+            , ( bp::arg("layer"), bp::arg("roughness") ) )
+        .def(
+            "getCrossCorrLength"
+            , (double ( ::MultiLayer::* )(  ) const)( &::MultiLayer::getCrossCorrLength ) )
+        .def(
+            "getNumberOfLayers"
+            , (::size_t ( ::MultiLayer::* )(  ) const)( &::MultiLayer::getNumberOfLayers ) )
+        .def(
+            "setCrossCorrLength"
+            , (void ( ::MultiLayer::* )( double ) )( &::MultiLayer::setCrossCorrLength )
+            , ( bp::arg("crossCorrLength") ) )
+        .def( bp::self_ns::str( bp::self ) );
+
+    bp::class_< ParameterPool, boost::noncopyable >( "ParameterPool", bp::init< >() )
+        .def(
+            "clear"
+            , (void ( ::ParameterPool::* )(  ) )( &::ParameterPool::clear ) )
+        .def(
+            "clone"
+            , (::ParameterPool * ( ::ParameterPool::* )(  ) )( &::ParameterPool::clone )
+            , bp::return_value_policy< bp::manage_new_object >() )
+        .def(
+            "cloneWithPrefix"
+            , (::ParameterPool * ( ::ParameterPool::* )( ::std::string ) )( &::ParameterPool::cloneWithPrefix )
+            , ( bp::arg("prefix") )
+            , bp::return_value_policy< bp::manage_new_object >() )
+        .def(
+            "copyToExternalPool"
+            , (void ( ::ParameterPool::* )( ::std::string,::ParameterPool * ) )( &::ParameterPool::copyToExternalPool )
+            , ( bp::arg("prefix"), bp::arg("external_pool") ) )
+        .def(
+            "registerParameter"
+            , (bool ( ::ParameterPool::* )( ::std::string,double * ) )( &::ParameterPool::registerParameter )
+            , ( bp::arg("name"), bp::arg("par") ) )
+        .def(
+            "size"
+            , (::size_t ( ::ParameterPool::* )(  ) const)( &::ParameterPool::size ) )
+        .def( bp::self_ns::str( bp::self ) );
+
+}
diff --git a/Core/Tools/inc/ISingleton.h b/Core/Tools/inc/ISingleton.h
index b1bcbf34ddc..0acaa8aad47 100644
--- a/Core/Tools/inc/ISingleton.h
+++ b/Core/Tools/inc/ISingleton.h
@@ -48,8 +48,8 @@ public:
     }
 
 protected:
-    ISingleton() {}
-    ISingleton(const ISingleton &) {}
+    ISingleton(){}
+    virtual ~ISingleton();
 
     static void create_singleton()
     {
@@ -65,8 +65,14 @@ protected:
 
     typedef T* T_Pointer;
 
+
+private:
+    ISingleton(const ISingleton<T> &) {}
+    ISingleton &operator=(const ISingleton<T> &) {}
+
     static T_Pointer m_instance;
     static bool m_destroyed;
+
 };
 
 template<class T > typename ISingleton<T>::T_Pointer ISingleton<T>::m_instance = 0;
diff --git a/Core/Tools/inc/PythonModule.h b/Core/Tools/inc/PythonModule.h
new file mode 100644
index 00000000000..3f28ccc299f
--- /dev/null
+++ b/Core/Tools/inc/PythonModule.h
@@ -0,0 +1,23 @@
+#ifndef PYTHONINTERFACE_H
+#define PYTHONINTERFACE_H
+// ********************************************************************
+// * The BornAgain project                                            *
+// * Simulation of neutron and x-ray scattering at grazing incidence  *
+// *                                                                  *
+// * LICENSE AND DISCLAIMER                                           *
+// * Lorem ipsum dolor sit amet, consectetur adipiscing elit.  Mauris *
+// * eget quam orci. Quisque  porta  varius  dui,  quis  posuere nibh *
+// * mollis quis. Mauris commodo rhoncus porttitor.                   *
+// ********************************************************************
+//! @file   PythonModule.h
+//! @brief  Collection of wrappers for python module
+//! @author Scientific Computing Group at FRM II
+//! @date   22.06.2012
+
+#include "PythonAlgorithmsInterface.h"
+#include "PythonSamplesInterface.h"
+#include "PythonToolsInterface.h"
+
+
+
+#endif // PYTHONINTERFACE_H
diff --git a/Core/Tools/inc/PythonToolsInterface.h b/Core/Tools/inc/PythonToolsInterface.h
new file mode 100644
index 00000000000..fc299e5ac68
--- /dev/null
+++ b/Core/Tools/inc/PythonToolsInterface.h
@@ -0,0 +1,22 @@
+#ifndef PYTHOTOOLSNINTERFACE_H
+#define PYTHOTOOLSNINTERFACE_H
+// ********************************************************************
+// * The BornAgain project                                            *
+// * Simulation of neutron and x-ray scattering at grazing incidence  *
+// *                                                                  *
+// * LICENSE AND DISCLAIMER                                           *
+// * Lorem ipsum dolor sit amet, consectetur adipiscing elit.  Mauris *
+// * eget quam orci. Quisque  porta  varius  dui,  quis  posuere nibh *
+// * mollis quis. Mauris commodo rhoncus porttitor.                   *
+// ********************************************************************
+//! @file   PythonToolsInterface.h
+//! @brief  Collection of class interfaces for python
+//! @author Scientific Computing Group at FRM II
+//! @date   21.06.2012
+
+
+namespace PythonInterface {
+    void export_tools();
+}
+
+#endif // PYTHONTOOLSINTERFACE_H
diff --git a/Core/Tools/src/PythonModule.cpp b/Core/Tools/src/PythonModule.cpp
new file mode 100644
index 00000000000..be349ee73fa
--- /dev/null
+++ b/Core/Tools/src/PythonModule.cpp
@@ -0,0 +1,11 @@
+#include "PythonModule.h"
+#include <boost/python.hpp>
+
+
+BOOST_PYTHON_MODULE(libScattCore)
+{
+    PythonInterface::export_algorithms();
+    PythonInterface::export_samples();
+    PythonInterface::export_tools();
+}
+
diff --git a/Core/Tools/src/PythonToolsInterface.cpp b/Core/Tools/src/PythonToolsInterface.cpp
new file mode 100644
index 00000000000..7a54bf2abcc
--- /dev/null
+++ b/Core/Tools/src/PythonToolsInterface.cpp
@@ -0,0 +1,61 @@
+#include "PythonToolsInterface.h"
+#include "Units.h"
+
+#include <boost/python.hpp>
+namespace bp = boost::python;
+
+
+void PythonInterface::export_tools()
+{
+    { //::Units::deg2rad
+
+        typedef double ( *deg2rad_function_type )( double );
+
+        bp::def(
+            "deg2rad"
+            , deg2rad_function_type( &::Units::deg2rad )
+            , ( bp::arg("angle") ) );
+
+    }
+
+    { //::Units::rad2deg
+
+        typedef double ( *rad2deg_function_type )( double );
+
+        bp::def(
+            "rad2deg"
+            , rad2deg_function_type( &::Units::rad2deg )
+            , ( bp::arg("angle") ) );
+
+    }
+
+    bp::scope().attr("angstrom") = Units::angstrom;
+
+    bp::scope().attr("deg") = Units::deg;
+
+    bp::scope().attr("degree") = Units::degree;
+
+    bp::scope().attr("meter") = Units::meter;
+
+    bp::scope().attr("micrometer") = Units::micrometer;
+
+    bp::scope().attr("millimeter") = Units::millimeter;
+
+    bp::scope().attr("milliradian") = Units::milliradian;
+
+    bp::scope().attr("mrad") = Units::mrad;
+
+    bp::scope().attr("nanometer") = Units::nanometer;
+
+    bp::scope().attr("nm") = Units::nm;
+
+    bp::scope().attr("rad") = Units::rad;
+
+    bp::scope().attr("radian") = Units::radian;
+
+    bp::scope().attr("sr") = Units::sr;
+
+    bp::scope().attr("steradian") = Units::steradian;
+
+}
+
diff --git a/GISASFW.pro b/GISASFW.pro
index 7c375fbb635..9a8faa9233f 100644
--- a/GISASFW.pro
+++ b/GISASFW.pro
@@ -2,12 +2,11 @@ TEMPLATE = subdirs
 
 SUBDIRS += \
     Core \
-#    ThirdParty/gtest \
-#    ThirdParty/fftw++ \
+    ThirdParty/gtest \
     App \
     UnitTests/TestCore
 
-TestCore.depends = ThirdParty/gtest ThirdParty/fftw++
+TestCore.depends = ThirdParty/gtest
 
 # means that compilation will be in the listed order
 CONFIG += ordered
-- 
GitLab