From b8ba3e9c3d6c97e054ab3ab8dfda16a902f92fca Mon Sep 17 00:00:00 2001
From: pospelov <pospelov@fz-juelich.de>
Date: Wed, 27 Jun 2012 14:15:04 +0200
Subject: [PATCH] python interface for basic classes and OpticalFresnel
 algorithm, examples of usage from python

---
 App/src/TestFresnelCoeff.cpp                  |   6 +-
 App/src/main.cpp                              |   4 -
 Core/Algorithms/inc/OpticalFresnel.h          |  20 +++
 .../src/PythonAlgorithmsInterface.cpp         |  58 ++++++++-
 Core/Core.pro                                 |  10 +-
 Core/Samples/inc/HomogeneousMaterial.h        |   3 +-
 Core/Samples/inc/IMaterial.h                  |   8 +-
 Core/Samples/inc/Layer.h                      |   6 +
 Core/Samples/inc/LayerInterface.h             |   6 +
 Core/Samples/inc/LayerRoughness.h             |   6 +
 Core/Samples/inc/MaterialManager.h            |   5 +-
 Core/Samples/inc/MultiLayer.h                 |  11 +-
 Core/Samples/src/Layer.cpp                    |  14 ++-
 Core/Samples/src/LayerInterface.cpp           |  18 ++-
 Core/Samples/src/LayerRoughness.cpp           |  12 ++
 Core/Samples/src/MaterialManager.cpp          |   1 -
 Core/Samples/src/MultiLayer.cpp               |  50 +++-----
 Core/Samples/src/PythonSamplesInterface.cpp   |   3 +-
 Core/Tools/inc/Types.h                        |   7 ++
 Core/Tools/inc/Utils.h                        |  47 -------
 Core/Tools/src/PythonToolsInterface.cpp       | 118 +++++++++++++++++-
 Core/Tools/src/Utils.cpp                      |   2 +-
 Examples/UsageWithPython/build_multilayer.py  |  71 +++++++++++
 23 files changed, 375 insertions(+), 111 deletions(-)
 create mode 100644 Examples/UsageWithPython/build_multilayer.py

diff --git a/App/src/TestFresnelCoeff.cpp b/App/src/TestFresnelCoeff.cpp
index 8806e805950..5cd1db48866 100644
--- a/App/src/TestFresnelCoeff.cpp
+++ b/App/src/TestFresnelCoeff.cpp
@@ -37,7 +37,7 @@ void TestFresnelCoeff::execute()
     std::cout << "TestFresnelCoeff::execute() -> Info." << std::endl;
 
     // calculate fresnel coefficients for several standard multi-layer samples
-    //test_standard();
+    test_standard();
 
     // calculate fresnel coefficients for multi-layer with different roughnesses
     test_roughness();
@@ -238,8 +238,8 @@ void TestFresnelCoeff::test_roughness()
     m_sample = dynamic_cast<MultiLayer *>(SampleFactory::instance().createItem("SimpleMultilayer"));
 
     std::cout << *m_sample << std::endl;
-    ParameterPool *newpool = m_sample->createParameterTree();
-    std::cout << *newpool << 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 1d3962c0bd2..58c41a80974 100644
--- a/App/src/main.cpp
+++ b/App/src/main.cpp
@@ -12,10 +12,6 @@ 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/OpticalFresnel.h b/Core/Algorithms/inc/OpticalFresnel.h
index 263ad35af98..a9b21101e96 100644
--- a/Core/Algorithms/inc/OpticalFresnel.h
+++ b/Core/Algorithms/inc/OpticalFresnel.h
@@ -41,7 +41,19 @@ public:
     };
     typedef std::vector<FresnelCoeff > MultiLayerCoeff_t; // set of Fresnel coefficients for set of layers, [nlayer]
 
+    class MultiLayerCoeff
+    {
+    public:
+        FresnelCoeff &operator[](size_t i) { return m_data[i]; }
+        size_t size() const { return m_data.size(); }
+        MultiLayerCoeff_t m_data;
+    };
+
     static int execute(const MultiLayer &sample, const kvector_t &k, MultiLayerCoeff_t &coeff);
+    static int execute(const MultiLayer &sample, const kvector_t &k, MultiLayerCoeff &coeff)
+    {
+        execute(sample,k,coeff.m_data); return 0;
+    }
 
 private:
 
@@ -53,4 +65,12 @@ private:
     static void calculateRT2(const MultiLayer &sample, MultiLayerCoeff_t &coeff);
 };
 
+
+// class to help pyplusplus to expose MultiLayerCoeff_t in python during automatic code generation
+//class PyHelperOpticalFresnel
+//{
+//    size_t python_boost_helper() { return sizeof(OpticalFresnel::MultiLayerCoeff_t); }
+//};
+
+
 #endif // OPTICALFRESNEL_H
diff --git a/Core/Algorithms/src/PythonAlgorithmsInterface.cpp b/Core/Algorithms/src/PythonAlgorithmsInterface.cpp
index 67a24d0da63..ce71e68614d 100644
--- a/Core/Algorithms/src/PythonAlgorithmsInterface.cpp
+++ b/Core/Algorithms/src/PythonAlgorithmsInterface.cpp
@@ -1,11 +1,65 @@
 #include "PythonAlgorithmsInterface.h"
+#include "OpticalFresnel.h"
 
 #include <boost/python.hpp>
-using namespace boost::python;
+#include <boost/python/suite/indexing/vector_indexing_suite.hpp>
+namespace bp = boost::python;
 
 
 void PythonInterface::export_algorithms()
 {
 
-}
+    { //::std::vector< OpticalFresnel::FresnelCoeff >
+        typedef bp::class_< std::vector< OpticalFresnel::FresnelCoeff > > MultiLayerCoeff_t_exposer_t;
+        MultiLayerCoeff_t_exposer_t MultiLayerCoeff_t_exposer = MultiLayerCoeff_t_exposer_t( "MultiLayerCoeff_t" );
+        bp::scope MultiLayerCoeff_t_scope( MultiLayerCoeff_t_exposer );
+        //WARNING: the next line of code will not compile, because "::OpticalFresnel::FresnelCoeff" does not have operator== !
+        //MultiLayerCoeff_t_exposer.def( bp::vector_indexing_suite< ::std::vector< OpticalFresnel::FresnelCoeff > >() );
+    }
+
+    { //::OpticalFresnel
+        typedef bp::class_< OpticalFresnel > OpticalFresnel_exposer_t;
+        OpticalFresnel_exposer_t OpticalFresnel_exposer = OpticalFresnel_exposer_t( "OpticalFresnel", bp::init< >() );
+        bp::scope OpticalFresnel_scope( OpticalFresnel_exposer );
+        bp::class_< OpticalFresnel::FresnelCoeff >( "FresnelCoeff", bp::init< >() )
+            .def_readwrite( "R", &OpticalFresnel::FresnelCoeff::R )
+            .def_readwrite( "T", &OpticalFresnel::FresnelCoeff::T )
+            .def_readwrite( "X", &OpticalFresnel::FresnelCoeff::X )
+            .def_readwrite( "kz", &OpticalFresnel::FresnelCoeff::kz )
+            .def_readwrite( "r", &OpticalFresnel::FresnelCoeff::r )
+            .def_readwrite( "rb", &OpticalFresnel::FresnelCoeff::rb )
+            .def_readwrite( "t", &OpticalFresnel::FresnelCoeff::t )
+            .def_readwrite( "tb", &OpticalFresnel::FresnelCoeff::tb );
+        bp::class_< OpticalFresnel::MultiLayerCoeff >( "MultiLayerCoeff" )
+            .def(
+                "__getitem__"
+                , (::OpticalFresnel::FresnelCoeff & ( ::OpticalFresnel::MultiLayerCoeff::* )( ::size_t ) )( &::OpticalFresnel::MultiLayerCoeff::operator[] )
+                , ( bp::arg("i") )
+                , bp::return_internal_reference< >() )
+            .def(
+                "size"
+                , (::size_t ( ::OpticalFresnel::MultiLayerCoeff::* )(  ) const)( &::OpticalFresnel::MultiLayerCoeff::size ) )
+            .def_readwrite( "m_data", &OpticalFresnel::MultiLayerCoeff::m_data );
+        { //::OpticalFresnel::execute
+
+            typedef int ( *execute_function_type )( ::MultiLayer const &,::kvector_t const &,::std::vector< OpticalFresnel::FresnelCoeff > & );
+
+            OpticalFresnel_exposer.def(
+                "execute"
+                , execute_function_type( &::OpticalFresnel::execute )
+                , ( bp::arg("sample"), bp::arg("k"), bp::arg("coeff") ) );
 
+        }
+        { //::OpticalFresnel::execute
+
+            typedef int ( *execute_function_type )( ::MultiLayer const &,::kvector_t const &,::OpticalFresnel::MultiLayerCoeff & );
+
+            OpticalFresnel_exposer.def(
+                "execute"
+                , execute_function_type( &::OpticalFresnel::execute )
+                , ( bp::arg("sample"), bp::arg("k"), bp::arg("coeff") ) );
+
+        }
+        OpticalFresnel_exposer.staticmethod( "execute" );
+    }
+}
diff --git a/Core/Core.pro b/Core/Core.pro
index 2b1458759d7..37dd0f01089 100644
--- a/Core/Core.pro
+++ b/Core/Core.pro
@@ -5,6 +5,7 @@ TARGET   = ScattCore
 TEMPLATE = lib
 CONFIG  += plugin # to remove versions from file name
 CONFIG  += debug
+#CONFIG  += nopython # to not generate interface to python
 QT      -= core gui
 
 QMAKE_EXTENSION_SHLIB = so
@@ -89,7 +90,7 @@ HEADERS += \
     Samples/inc/MaterialManager.h \
     Samples/inc/MultiLayer.h \
     Samples/inc/NanoParticle.h \
-    Samples/inc/NanoParticleDecorator.h \
+    Samples/inc/NanoParticleDecoration.h \
     Samples/inc/ParameterPool.h \
     Samples/inc/PythonSamplesInterface.h \
     \
@@ -113,6 +114,13 @@ HEADERS += \
     Tools/inc/Units.h \
     Tools/inc/Utils.h
 
+# excluding files with python interface to not to expose library in python
+CONFIG(nopython) {
+  HEADERS -= Tools/inc/PythonToolsInterface.h Samples/inc/PythonSamplesInterface.h Algorithms/inc/PythonAlgorithmsInterface.h Tools/inc/PythonModule.h
+  SOURCES -= Tools/src/PythonToolsInterface.cpp Samples/src/PythonSamplesInterface.cpp Algorithms/src/PythonAlgorithmsInterface.cpp Tools/src/PythonModule.cpp
+}
+
+
 INCLUDEPATH += ./Algorithms/inc ./Samples/inc ./Tools/inc
 DEPENDPATH += ./Algorithms/inc ./Samples/inc ./Tools/inc
 
diff --git a/Core/Samples/inc/HomogeneousMaterial.h b/Core/Samples/inc/HomogeneousMaterial.h
index 509f5d2f5d9..2a0d605f5b3 100644
--- a/Core/Samples/inc/HomogeneousMaterial.h
+++ b/Core/Samples/inc/HomogeneousMaterial.h
@@ -41,8 +41,7 @@ public:
 protected:
     //! print material class
     virtual void print(std::ostream &ostr) const {
-        //IMaterial::print(ostr);
-        ostr << typeid(*this).name() << " " << this << " " << m_refractive_index;
+        ostr  << "Homogeneous " << this << " " << getName() << " rindx:" << 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 ee475ee6d3f..cde80da0736 100644
--- a/Core/Samples/inc/IMaterial.h
+++ b/Core/Samples/inc/IMaterial.h
@@ -34,15 +34,13 @@ public:
     virtual ~IMaterial() {}
 
     //! print material class
-    friend std::ostream &operator<<(std::ostream &ostr, const IMaterial &m)
-    {
-        m.print(ostr); return ostr;
-    }
+    friend std::ostream &operator<<(std::ostream &ostr, const IMaterial &m) { m.print(ostr); return ostr; }
 
 protected:
     //! print material class
     virtual void print(std::ostream &ostr) const {
-        ostr << typeid(*this).name() << " " << this;
+        //ostr << typeid(*this).name() << " " << this;
+        ostr << getName() << " " << this;
     }
 
 };
diff --git a/Core/Samples/inc/Layer.h b/Core/Samples/inc/Layer.h
index 7477b0c0dab..230daa117f9 100644
--- a/Core/Samples/inc/Layer.h
+++ b/Core/Samples/inc/Layer.h
@@ -59,10 +59,16 @@ public:
     //
     virtual LayerDWBASimulation *getDWBASimulation() const { return 0; }
 
+    //! print class
+    friend std::ostream &operator<<(std::ostream &ostr, const Layer &m) { m.print(ostr); return ostr; }
+
 private:
     //! initialize pool parameters, i.e. register some of class members for later access via parameter pool
     virtual void init_parameters();
 
+    //! print class
+    void print(std::ostream &ostr) const;
+
     const IMaterial* mp_material;    //!< pointer to the material
     double m_thickness;              //!< layer thickness in _angstrom_
 };
diff --git a/Core/Samples/inc/LayerInterface.h b/Core/Samples/inc/LayerInterface.h
index 6be3f294022..0c24318399f 100644
--- a/Core/Samples/inc/LayerInterface.h
+++ b/Core/Samples/inc/LayerInterface.h
@@ -60,11 +60,17 @@ public:
     //! get bottom layer
     inline const Layer *getLayerBottom() const { return m_LayerBottom; }
 
+    //! print class
+    friend std::ostream &operator<<(std::ostream &ostr, const LayerInterface &m) { m.print(ostr); return ostr; }
+
 private:
     LayerInterface();
     LayerInterface(const LayerInterface &);
     LayerInterface &operator=(const LayerInterface &);
 
+    //! print class
+    void print(std::ostream &ostr) const;
+
     LayerRoughness *m_roughness;   //!< roughness of the interface
     const Layer *m_LayerTop;       //!< pointer to the layer above interface
     const Layer *m_LayerBottom;    //!< pointer to the layer below interface
diff --git a/Core/Samples/inc/LayerRoughness.h b/Core/Samples/inc/LayerRoughness.h
index af70f49ddd4..54eea1c23ad 100644
--- a/Core/Samples/inc/LayerRoughness.h
+++ b/Core/Samples/inc/LayerRoughness.h
@@ -55,10 +55,16 @@ public:
     //! return latteral correlation length
     inline double getLatteralCorrLength() const { return m_latteralCorrLength; }
 
+    //! print class
+    friend std::ostream &operator<<(std::ostream &ostr, const LayerRoughness &m) { m.print(ostr); return ostr; }
+
 protected:
     //! initialize pool parameters, i.e. register some of class members for later access via parameter pool
     virtual void init_parameters();
 
+    //! print class
+    void print(std::ostream &ostr) const;
+
     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 81be9b2fd59..7b2b3a2552d 100644
--- a/Core/Samples/inc/MaterialManager.h
+++ b/Core/Samples/inc/MaterialManager.h
@@ -53,10 +53,7 @@ public:
     void clear();
 
     //! print material class
-    friend std::ostream &operator<<(std::ostream &ostr, const MaterialManager &m)
-    {
-        m.print(ostr); return ostr;
-    }
+    friend std::ostream &operator<<(std::ostream &ostr, const MaterialManager &m) { m.print(ostr); return ostr; }
 
 protected:
     MaterialManager(){}
diff --git a/Core/Samples/inc/MultiLayer.h b/Core/Samples/inc/MultiLayer.h
index fc37405c479..18687bd4fbf 100644
--- a/Core/Samples/inc/MultiLayer.h
+++ b/Core/Samples/inc/MultiLayer.h
@@ -88,19 +88,13 @@ public:
     void setLayerThickness(size_t i_layer, double thickness);
 
     //! print class
-    friend std::ostream &operator<<(std::ostream &ostr, const MultiLayer &m)
-    {
-        m.print(ostr); return ostr;
-    }
+    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)
     {
@@ -124,6 +118,9 @@ private:
     //! initialize pool parameters, i.e. register some of class members for later access via parameter pool
     virtual void init_parameters();
 
+    //! print class
+    void print(std::ostream &ostr) const;
+
     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/src/Layer.cpp b/Core/Samples/src/Layer.cpp
index fd7576e166e..2eb2e7edc3e 100644
--- a/Core/Samples/src/Layer.cpp
+++ b/Core/Samples/src/Layer.cpp
@@ -1,6 +1,6 @@
 #include "Layer.h"
 #include "Exceptions.h"
-
+#include <iomanip>
 
 /* ************************************************************************* */
 // constructors, assignment operator, destructors
@@ -77,3 +77,15 @@ void Layer::setMaterial(const IMaterial* p_material, double thickness)
     setThickness(thickness);
 }
 
+
+/* ************************************************************************* */
+// print content of multilayer
+/* ************************************************************************* */
+void Layer::print(std::ostream &ostr) const
+{
+    ostr << getName()
+         << " " << std::setw(12) << this
+         << " " << getThickness() << "nm > "
+         << *getMaterial();
+}
+
diff --git a/Core/Samples/src/LayerInterface.cpp b/Core/Samples/src/LayerInterface.cpp
index dd94f71aa46..2bc74b3ad36 100644
--- a/Core/Samples/src/LayerInterface.cpp
+++ b/Core/Samples/src/LayerInterface.cpp
@@ -1,7 +1,7 @@
 #include "LayerInterface.h"
 
 #include <iostream>
-
+#include <iomanip>
 
 LayerInterface::LayerInterface() : m_roughness(0), m_LayerTop(0), m_LayerBottom(0)
 {
@@ -46,3 +46,19 @@ void LayerInterface::setRoughness(const LayerRoughness &roughness)
     registerChild(m_roughness);
 }
 
+
+/* ************************************************************************* */
+// print
+/* ************************************************************************* */
+void LayerInterface::print(std::ostream &ostr) const
+{
+    ostr << getName()
+         << " " << std::setw(12) << this
+         << " top:"<< getLayerTop() << " bottom:" << getLayerBottom() << "   ";
+    const LayerRoughness *roughness = getRoughness();
+    if(roughness) {
+        ostr << "> " << *roughness;
+    }else{
+        ostr << "> no roughness";
+    }
+}
diff --git a/Core/Samples/src/LayerRoughness.cpp b/Core/Samples/src/LayerRoughness.cpp
index e336a9a0551..bb5bdb4af42 100644
--- a/Core/Samples/src/LayerRoughness.cpp
+++ b/Core/Samples/src/LayerRoughness.cpp
@@ -1,6 +1,7 @@
 #include "LayerRoughness.h"
 #include <cmath>
 #include <iostream>
+#include <iomanip>
 
 LayerRoughness::LayerRoughness() : m_sigma(0), m_hurstParameter(0), m_latteralCorrLength(0)
 {
@@ -77,3 +78,14 @@ double LayerRoughness::getCorrFun(const kvector_t &k) const
     double R = sqrt(k.x()*k.x() + k.y()*k.y());
     return m_sigma*m_sigma*std::exp( -1.0*std::pow(R/clength, 2.*H) );
 }
+
+
+/* ************************************************************************* */
+// print
+/* ************************************************************************* */
+void LayerRoughness::print(std::ostream &ostr) const
+{
+    ostr << getName()
+         << " " << std::setw(12) << this;
+    ostr << "(s:" << m_sigma << ",H:"<<m_hurstParameter<< ",C:"<<m_latteralCorrLength << ")";
+}
diff --git a/Core/Samples/src/MaterialManager.cpp b/Core/Samples/src/MaterialManager.cpp
index 0fe42877429..f17c625cacb 100644
--- a/Core/Samples/src/MaterialManager.cpp
+++ b/Core/Samples/src/MaterialManager.cpp
@@ -57,7 +57,6 @@ const IMaterial *MaterialManager::addHomogeneousMaterial(const std::string &name
 /* ************************************************************************* */
 void MaterialManager::print(std::ostream &ostr) const
 {
-    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;
diff --git a/Core/Samples/src/MultiLayer.cpp b/Core/Samples/src/MultiLayer.cpp
index d5634b5ee6d..47db223e1cb 100644
--- a/Core/Samples/src/MultiLayer.cpp
+++ b/Core/Samples/src/MultiLayer.cpp
@@ -99,36 +99,6 @@ const LayerInterface *MultiLayer::getLayerBottomInterface(size_t i_layer) const
 }
 
 
-/* ************************************************************************* */
-// print content of multilayer on the screen
-/* ************************************************************************* */
-void MultiLayer::print(std::ostream &ostr) const
-{
-    ostr << typeid(*this).name() << " " << this;
-
-    for(size_t i=0; i<getNumberOfLayers(); i++) {
-        const Layer *layer = getLayer(i);
-        ostr << " " << "LAYER  "
-                  << " " << "#" << std::left << std::setw(2)   << i
-                  << " " << std::setw(16)  << layer
-                  << " " << std::setw(5)   << layer->getThickness()
-                  << " " << "z:" << std::setw(6)   << getLayerBottomZ(i)
-                  << " " << std::setw(11)  << " material>"
-                  << " " << (*layer->getMaterial())
-                  << std::endl;
-        const LayerInterface *interface = getLayerBottomInterface(i);
-        ostr << " " << "------"
-                  << " " << std::setw(16)  << interface;
-        if(interface) {
-            std::cout << " " << " layers("
-                      << " " << std::setw(16) << interface->getLayerTop()
-                      << "," << std::setw(16) << interface->getLayerBottom() << ")";
-        }
-        ostr << std::endl;
-    }
-}
-
-
 /* ************************************************************************* */
 // add layer with top roughness
 /* ************************************************************************* */
@@ -212,3 +182,23 @@ void MultiLayer::setLayerThickness(size_t i_layer, double thickness)
 }
 
 
+/* ************************************************************************* */
+// print content of multilayer
+/* ************************************************************************* */
+void MultiLayer::print(std::ostream &ostr) const
+{
+    ostr << getName() << " " << this << std::endl;
+
+    for(size_t i=0; i<getNumberOfLayers(); i++) {
+        const Layer *layer = getLayer(i);
+        ostr << " " << "#" << std::left << std::setw(2) << i
+             << *layer
+             << std::endl;
+        const LayerInterface *interface = getLayerBottomInterface(i);
+        if(interface) {
+            ostr << " " << "------" << *interface << std::endl;
+        } else {
+            ostr << " " << "------ no interface " << std::endl;
+        }
+    }
+}
diff --git a/Core/Samples/src/PythonSamplesInterface.cpp b/Core/Samples/src/PythonSamplesInterface.cpp
index 181b4d84561..80802088292 100644
--- a/Core/Samples/src/PythonSamplesInterface.cpp
+++ b/Core/Samples/src/PythonSamplesInterface.cpp
@@ -66,7 +66,6 @@ struct Layer_wrapper : Layer, bp::wrapper< Layer > {
 };
 
 
-
 void PythonInterface::export_samples()
 {
     { //::IMaterial
@@ -187,6 +186,7 @@ void PythonInterface::export_samples()
                 , ( bp::arg("p_material"), bp::arg("thickness") ) );
 
         }
+        Layer_exposer.def( bp::self_ns::str( bp::self ) );
     }
 
     { //::LayerRoughness
@@ -263,6 +263,7 @@ void PythonInterface::export_samples()
                 , ( bp::arg("sigma") ) );
 
         }
+        LayerRoughness_exposer.def( bp::self_ns::str( bp::self ) );
     }
 
     bp::class_< MaterialManager, bp::bases< ISingleton< MaterialManager > >, boost::noncopyable >( "MaterialManager", bp::no_init )
diff --git a/Core/Tools/inc/Types.h b/Core/Tools/inc/Types.h
index 749281744a2..c72a002e511 100644
--- a/Core/Tools/inc/Types.h
+++ b/Core/Tools/inc/Types.h
@@ -83,6 +83,7 @@ template<typename T> KVector<T> operator-(const KVector<T> &a, const KVector<T>
 
 
 typedef KVector<double>  kvector_t;
+
 //typedef KVector<complex_t> complex_vector_t;
 //
 //inline complex_vector_t getComplexVector(kvector_t real_vector)
@@ -91,6 +92,12 @@ typedef KVector<double>  kvector_t;
 //			complex_t(real_vector.y()), complex_t(real_vector.z()));
 //}
 
+// class to help pyplusplus to expose kvector_t in python during automatic code generation
+class KVectorPyHelper
+{
+public:
+    size_t python_boost_helper() { return sizeof(KVector<double>); }
+};
 
 
 #endif // TYPES_H
diff --git a/Core/Tools/inc/Utils.h b/Core/Tools/inc/Utils.h
index 4da38595e1a..8eef2ef9760 100644
--- a/Core/Tools/inc/Utils.h
+++ b/Core/Tools/inc/Utils.h
@@ -130,50 +130,3 @@ protected:
 #endif // UTILS_H
 
 
-//class StringUsageDir
-//{
-//public:
-//    typedef std::vector<StringUsageMap > nstringmap_t;
-//    typedef nstringmap_t::iterator iterator_t;
-
-//    StringUsageDir(){}
-//    ~StringUsageDir(){}
-
-//    bool add(std::string name, size_t dirlevel) {
-//        std::cout << "qqq " << name << " " << dirlevel << std::endl;
-//        // adjusting stack of dir names to current dirlevel
-//        while(m_stringstack.size() > dirlevel ) {
-//            m_stringstack.pop_back();
-//        }
-//        // pushing new name in the stack
-//        m_stringstack.push_back(name);
-//        // adding new name in the map of used name to know how may times given name is repeated on current level
-//        if(dirlevel >= m_nstringdir.size() ) m_nstringdir.resize(dirlevel+1);
-//        return m_nstringdir[dirlevel].add(name);
-//    }
-
-//    std::string get_path()
-//    {
-//        std::string result;
-//        for(size_t i_level=0; i_level<m_stringstack.size(); i_level++) {
-//            std::string &currentLevelName = m_stringstack[i_level];
-//            StringUsageMap &strUsageMap = m_nstringdir[i_level];
-
-//            std::ostringstream os;
-//            int nOfUsage = strUsageMap[currentLevelName];
-//            if(nOfUsage != 1) os<<nOfUsage;
-//            result += std::string("/") + currentLevelName+os.str();
-//        }
-//        return result;
-//    }
-
-//    iterator_t begin() { return m_nstringdir.begin(); }
-//    iterator_t end() { return m_nstringdir.end(); }
-//    size_t size() const { return m_nstringdir.size(); }
-//    StringUsageMap &operator[](size_t i) { return m_nstringdir[i]; }
-//    StringUsageMap const &operator[](size_t i) const { return m_nstringdir[i]; }
-
-//protected:
-//    std::vector<StringUsageMap > m_nstringdir;
-//    std::vector<std::string > m_stringstack;
-//};
diff --git a/Core/Tools/src/PythonToolsInterface.cpp b/Core/Tools/src/PythonToolsInterface.cpp
index 7a54bf2abcc..7a06ed2f5c5 100644
--- a/Core/Tools/src/PythonToolsInterface.cpp
+++ b/Core/Tools/src/PythonToolsInterface.cpp
@@ -1,5 +1,6 @@
 #include "PythonToolsInterface.h"
 #include "Units.h"
+#include "Types.h"
 
 #include <boost/python.hpp>
 namespace bp = boost::python;
@@ -7,6 +8,122 @@ namespace bp = boost::python;
 
 void PythonInterface::export_tools()
 {
+    { //::KVector< double >
+        typedef bp::class_< KVector< double > > kvector_t_exposer_t;
+        kvector_t_exposer_t kvector_t_exposer = kvector_t_exposer_t( "kvector_t", bp::init< >() );
+        bp::scope kvector_t_scope( kvector_t_exposer );
+        kvector_t_exposer.def( bp::init< double, double, double >(( bp::arg("x"), bp::arg("y"), bp::arg("z") )) );
+        { //::KVector< double >::LambdaAlphaPhi
+
+            typedef KVector< double > exported_class_t;
+            typedef ::KVector< double > ( *LambdaAlphaPhi_function_type )( double,double,double );
+
+            kvector_t_exposer.def(
+                "LambdaAlphaPhi"
+                , LambdaAlphaPhi_function_type( &::KVector< double >::LambdaAlphaPhi )
+                , ( bp::arg("lambda"), bp::arg("alpha"), bp::arg("phi") ) );
+
+        }
+        { //::KVector< double >::mag
+
+            typedef KVector< double > exported_class_t;
+            typedef double ( exported_class_t::*mag_function_type )(  ) const;
+
+            kvector_t_exposer.def(
+                "mag"
+                , mag_function_type( &::KVector< double >::mag ) );
+
+        }
+        { //::KVector< double >::mag2
+
+            typedef KVector< double > exported_class_t;
+            typedef double ( exported_class_t::*mag2_function_type )(  ) const;
+
+            kvector_t_exposer.def(
+                "mag2"
+                , mag2_function_type( &::KVector< double >::mag2 ) );
+
+        }
+        { //::KVector< double >::magxy
+
+            typedef KVector< double > exported_class_t;
+            typedef double ( exported_class_t::*magxy_function_type )(  ) const;
+
+            kvector_t_exposer.def(
+                "magxy"
+                , magxy_function_type( &::KVector< double >::magxy ) );
+
+        }
+        kvector_t_exposer.def( bp::self += bp::self );
+        kvector_t_exposer.def( bp::self -= bp::self );
+        { //::KVector< double >::operator=
+
+            typedef KVector< double > exported_class_t;
+            typedef ::KVector< double > & ( exported_class_t::*assign_function_type )( ::KVector< double > const & ) ;
+
+            kvector_t_exposer.def(
+                "assign"
+                , assign_function_type( &::KVector< double >::operator= )
+                , ( bp::arg("other") )
+                , bp::return_self< >() );
+
+        }
+        { //::KVector< double >::setLambdaAlphaPhi
+
+            typedef KVector< double > exported_class_t;
+            typedef void ( exported_class_t::*setLambdaAlphaPhi_function_type )( double,double,double ) ;
+
+            kvector_t_exposer.def(
+                "setLambdaAlphaPhi"
+                , setLambdaAlphaPhi_function_type( &::KVector< double >::setLambdaAlphaPhi )
+                , ( bp::arg("lambda"), bp::arg("alpha"), bp::arg("phi") ) );
+
+        }
+        { //::KVector< double >::setMagThetaPhi
+
+            typedef KVector< double > exported_class_t;
+            typedef void ( exported_class_t::*setMagThetaPhi_function_type )( double,double,double ) ;
+
+            kvector_t_exposer.def(
+                "setMagThetaPhi"
+                , setMagThetaPhi_function_type( &::KVector< double >::setMagThetaPhi )
+                , ( bp::arg("mag"), bp::arg("theta"), bp::arg("phi") ) );
+
+        }
+        { //::KVector< double >::x
+
+            typedef KVector< double > exported_class_t;
+            typedef double ( exported_class_t::*x_function_type )(  ) const;
+
+            kvector_t_exposer.def(
+                "x"
+                , x_function_type( &::KVector< double >::x ) );
+
+        }
+        { //::KVector< double >::y
+
+            typedef KVector< double > exported_class_t;
+            typedef double ( exported_class_t::*y_function_type )(  ) const;
+
+            kvector_t_exposer.def(
+                "y"
+                , y_function_type( &::KVector< double >::y ) );
+
+        }
+        { //::KVector< double >::z
+
+            typedef KVector< double > exported_class_t;
+            typedef double ( exported_class_t::*z_function_type )(  ) const;
+
+            kvector_t_exposer.def(
+                "z"
+                , z_function_type( &::KVector< double >::z ) );
+
+        }
+        kvector_t_exposer.staticmethod( "LambdaAlphaPhi" );
+        kvector_t_exposer.def( bp::self_ns::str( bp::self ) );
+    }
+
     { //::Units::deg2rad
 
         typedef double ( *deg2rad_function_type )( double );
@@ -56,6 +173,5 @@ void PythonInterface::export_tools()
     bp::scope().attr("sr") = Units::sr;
 
     bp::scope().attr("steradian") = Units::steradian;
-
 }
 
diff --git a/Core/Tools/src/Utils.cpp b/Core/Tools/src/Utils.cpp
index 8b137891791..5ac8949c013 100644
--- a/Core/Tools/src/Utils.cpp
+++ b/Core/Tools/src/Utils.cpp
@@ -1 +1 @@
-
+#include "Utils.h"
diff --git a/Examples/UsageWithPython/build_multilayer.py b/Examples/UsageWithPython/build_multilayer.py
new file mode 100644
index 00000000000..a69ef713460
--- /dev/null
+++ b/Examples/UsageWithPython/build_multilayer.py
@@ -0,0 +1,71 @@
+import sys
+from numpy import linspace, array, zeros
+import pylab
+
+sys.path.append("../../lib")
+module = __import__("libScattCore")
+reload(module)
+
+#import libScattCore
+from libScattCore import *
+
+# ------------------------------------------------
+#defining materials
+matMng = MaterialManager.instance()
+mAmbience = matMng.addHomogeneousMaterial("ambience", complex(1,0) )
+mAg = matMng.addHomogeneousMaterial("ag1", complex(1.0-5e-6, 0) )
+mCr = matMng.addHomogeneousMaterial("cr1", complex(1.0-10e-6, 0) )
+mSubstrate = matMng.addHomogeneousMaterial("substrate", complex(1-15e-6,0) )
+
+# ------------------------------------------------
+#defining layers
+lAmbience = Layer()
+lAmbience.setMaterial(mAmbience, 0)
+
+lAg = Layer()
+lAg.setMaterial(mAg, 150.0*nanometer)
+
+lCr = Layer()
+lCr.setMaterial(mCr, 120.0*nanometer)
+
+lSubstrate = Layer()
+lSubstrate.setMaterial(mSubstrate, 0);
+
+#defining roughness
+roughness = LayerRoughness()
+roughness.setSigma(1.0*nanometer);
+roughness.setHurstParameter(0.3);
+roughness.setLatteralCorrLength(5000*nanometer);
+
+sample = MultiLayer()
+
+sample.addLayer(lAmbience)
+for i in range(0,2):
+  sample.addLayerWithTopRoughness(lAg, roughness)
+  sample.addLayerWithTopRoughness(lCr, roughness)
+
+sample.addLayerWithTopRoughness(lSubstrate, roughness)
+
+print sample
+
+# ------------------------------------------------
+# calculations
+calculator = OpticalFresnel()
+
+fresnelCoeff = OpticalFresnel.MultiLayerCoeff()
+
+alpha=linspace(0., 2.0*degree, 2000)
+ai = array(alpha)
+rcoeff = zeros(ai.shape)
+
+for i in range(0,len(ai)):
+  kvec = kvector_t.LambdaAlphaPhi(1.54*angstrom, -ai[i], 0.0)
+  calculator.execute(sample, kvec, fresnelCoeff)
+  rcoeff[i]=abs(fresnelCoeff[0].R)
+  print i, rcoeff[i]
+
+fg = pylab.figure()
+pylab.semilogy(ai, rcoeff)
+pylab.show()
+
+  
\ No newline at end of file
-- 
GitLab