From fb87fc50300f66da39cb0d4a668f993b0b6fc9a1 Mon Sep 17 00:00:00 2001
From: pospelov <pospelov@fz-juelich.de>
Date: Fri, 14 Dec 2012 17:57:22 +0100
Subject: [PATCH] New signal mechanism for PoolParameter/IParameterized, set of
 dedicated units tests

---
 Core/Core.pro                                 |   5 +-
 .../src/PythonInterface_classes_3.cpp         |  14 +--
 Core/Tools/inc/FitParameterLinked.h           |   5 +-
 Core/Tools/inc/IChangeable.h                  |  41 ++++++++
 Core/Tools/inc/IParameterized.h               |  11 +-
 Core/Tools/inc/ParameterPool.h                |  39 ++------
 Core/Tools/inc/RealParameterWrapper.h         |  68 +++++++++++++
 Core/Tools/src/FitParameterLinked.cpp         |   4 +-
 Core/Tools/src/ParameterPool.cpp              |  60 ++++-------
 Core/Tools/src/RealParameterWrapper.cpp       |  23 +++++
 Doc/Doxygen/Doxyfile                          |   2 +-
 Macros/BoostPythonGenerator/codegenerator.py  |   1 +
 Macros/GitUtils/gisasfw_loc.png               | Bin 16893 -> 16905 bytes
 UnitTests/TestCore/IParameterizedTest.h       |  61 ++++++++++++
 UnitTests/TestCore/ParameterPoolTest.h        |  90 +++++++++++++++++
 UnitTests/TestCore/RealParameterWrapperTest.h |  94 ++++++++++++++++++
 UnitTests/TestCore/TestCore.pro               |  13 ++-
 UnitTests/TestCore/main.cpp                   |   3 +
 shared.pri                                    |   4 +-
 19 files changed, 444 insertions(+), 94 deletions(-)
 create mode 100644 Core/Tools/inc/IChangeable.h
 create mode 100644 Core/Tools/inc/RealParameterWrapper.h
 create mode 100644 Core/Tools/src/RealParameterWrapper.cpp
 create mode 100644 UnitTests/TestCore/IParameterizedTest.h
 create mode 100644 UnitTests/TestCore/ParameterPoolTest.h
 create mode 100644 UnitTests/TestCore/RealParameterWrapperTest.h

diff --git a/Core/Core.pro b/Core/Core.pro
index 9f838bb2a61..9b9f3625cea 100644
--- a/Core/Core.pro
+++ b/Core/Core.pro
@@ -113,6 +113,7 @@ SOURCES += \
     Tools/src/OutputDataWriter.cpp \
     Tools/src/ParameterPool.cpp \
     Tools/src/ProgramOptions.cpp \
+    Tools/src/RealParameterWrapper.cpp \
     Tools/src/StochasticGaussian.cpp \
     Tools/src/StochasticSampledParameter.cpp \
     Tools/src/Types.cpp \
@@ -145,6 +146,7 @@ HEADERS += \
     Algorithms/inc/IChiSquaredModule.h \
     Algorithms/inc/IDetectorResolution.h \
     Algorithms/inc/IFittingDataSelector.h \
+    Algorithms/inc/IIntensityFunction.h \
     Algorithms/inc/IInterferenceFunctionStrategy.h \
     Algorithms/inc/IOutputDataNormalizer.h \
     Algorithms/inc/IResolutionFunction2D.h \
@@ -263,6 +265,7 @@ HEADERS += \
     Tools/inc/OutputDataWriter.h \
     Tools/inc/ParameterPool.h \
     Tools/inc/ProgramOptions.h \
+    Tools/inc/RealParameterWrapper.h \
     Tools/inc/TRange.h \
     Tools/inc/StochasticDiracDelta.h \
     Tools/inc/StochasticGaussian.h \
@@ -282,7 +285,7 @@ HEADERS += \
     PythonAPI/inc/PythonOutputData.h \
     PythonAPI/inc/PythonPlusplusHelper.h \
     PythonAPI/inc/IPythonWrapper.h \
-    Algorithms/inc/IIntensityFunction.h
+    Tools/inc/IChangeable.h
 
 INCLUDEPATH += ./Algorithms/inc ./FormFactors/inc ./Geometry/inc ./Samples/inc ./Tools/inc ./PythonAPI/inc
 DEPENDPATH  += ./Algorithms/inc ./FormFactors/inc ./Geometry/inc ./Samples/inc ./Tools/inc ./PythonAPI/inc
diff --git a/Core/PythonAPI/src/PythonInterface_classes_3.cpp b/Core/PythonAPI/src/PythonInterface_classes_3.cpp
index 723e7f5f29c..1ae48dca202 100644
--- a/Core/PythonAPI/src/PythonInterface_classes_3.cpp
+++ b/Core/PythonAPI/src/PythonInterface_classes_3.cpp
@@ -1776,24 +1776,24 @@ void register_classes_3(){
         typedef bp::class_< ParameterPool, boost::noncopyable > ParameterPool_exposer_t;
         ParameterPool_exposer_t ParameterPool_exposer = ParameterPool_exposer_t( "ParameterPool", bp::init< >() );
         bp::scope ParameterPool_scope( ParameterPool_exposer );
-        bp::class_< ParameterPool::RealPar >( "RealPar", bp::no_init )    
+        bp::class_< ParameterPool::RealParameterWrapper >( "RealPar", bp::no_init )    
             .def( 
                 "checkNull"
-                , (void ( ::ParameterPool::RealPar::* )(  ) const)( &::ParameterPool::RealPar::checkNull ) )    
+                , (void ( ::ParameterPool::RealPar::* )(  ) const)( &::ParameterPool::RealParameterWrapper::checkNull ) )    
             .def( 
                 "getValue"
-                , (double ( ::ParameterPool::RealPar::* )(  ) const)( &::ParameterPool::RealPar::getValue ) )    
+                , (double ( ::ParameterPool::RealPar::* )(  ) const)( &::ParameterPool::RealParameterWrapper::getValue ) )    
             .def( 
                 "isNull"
-                , (bool ( ::ParameterPool::RealPar::* )(  ) )( &::ParameterPool::RealPar::isNull ) )    
+                , (bool ( ::ParameterPool::RealPar::* )(  ) )( &::ParameterPool::RealParameterWrapper::isNull ) )    
             .def( 
                 "setValue"
-                , (void ( ::ParameterPool::RealPar::* )( double ) )( &::ParameterPool::RealPar::setValue )
+                , (void ( ::ParameterPool::RealPar::* )( double ) )( &::ParameterPool::RealParameterWrapper::setValue )
                 , ( bp::arg("value") ) )    
             .def( bp::self_ns::str( bp::self ) );
         { //::ParameterPool::addParameter
         
-            typedef bool ( ::ParameterPool::*addParameter_function_type )( ::std::string const &,::ParameterPool::RealPar ) ;
+            typedef bool ( ::ParameterPool::*addParameter_function_type )( ::std::string const &,::ParameterPool::RealParameterWrapper ) ;
             
             ParameterPool_exposer.def( 
                 "addParameter"
@@ -1833,7 +1833,7 @@ void register_classes_3(){
         }
         { //::ParameterPool::getParameter
         
-            typedef ::ParameterPool::RealPar ( ::ParameterPool::*getParameter_function_type )( ::std::string const & ) const;
+            typedef ::ParameterPool::RealParameterWrapper ( ::ParameterPool::*getParameter_function_type )( ::std::string const & ) const;
             
             ParameterPool_exposer.def( 
                 "getParameter"
diff --git a/Core/Tools/inc/FitParameterLinked.h b/Core/Tools/inc/FitParameterLinked.h
index 29395e50acb..bff3515ed1a 100644
--- a/Core/Tools/inc/FitParameterLinked.h
+++ b/Core/Tools/inc/FitParameterLinked.h
@@ -30,8 +30,7 @@
 class FitParameterLinked : public FitParameter
 {
 public:
-    typedef ParameterPool::RealPar PoolParameter_t;
-    typedef std::vector<PoolParameter_t > PoolParameterColl_t;
+    typedef std::vector<ParameterPool::parameter_t > PoolParameterColl_t;
 
     FitParameterLinked();
     FitParameterLinked(const std::string &name, double value, double step, const AttLimits &attlim=AttLimits::limitless());
@@ -47,7 +46,7 @@ public:
     }
 
     //! add real parameter to the collection
-    virtual void addParameter(PoolParameter_t par);
+    virtual void addParameter(ParameterPool::parameter_t par);
 
     //! add parameters from pool which match given wildcard
     virtual void addMatchedParametersFromPool(const ParameterPool *pool, const std::string &wildcard = std::string());
diff --git a/Core/Tools/inc/IChangeable.h b/Core/Tools/inc/IChangeable.h
new file mode 100644
index 00000000000..2240fe2ce73
--- /dev/null
+++ b/Core/Tools/inc/IChangeable.h
@@ -0,0 +1,41 @@
+#ifndef ICHANGEABLE_H
+#define ICHANGEABLE_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   IChangeable.h
+//! @brief  Definition of IChangeable interface
+//! @author Scientific Computing Group at FRM II
+//! @date   Dec 14, 2012
+
+
+//- -------------------------------------------------------------------
+//! @class IChangeable
+//! @brief Definition of IChangeable
+//- -------------------------------------------------------------------
+class IChangeable
+{
+public:
+    IChangeable(bool is_changed=false) : m_is_changed(is_changed){}
+    virtual ~IChangeable(){}
+
+    bool isChanged()
+    {
+        bool result = m_is_changed;
+        m_is_changed = false;
+        return result;
+    }
+
+    void setIsChanged(bool is_changed) { m_is_changed = is_changed; }
+
+private:
+    bool m_is_changed;
+};
+
+#endif // ICHANGEABLE_H
diff --git a/Core/Tools/inc/IParameterized.h b/Core/Tools/inc/IParameterized.h
index 20c30f81275..b70001161d9 100644
--- a/Core/Tools/inc/IParameterized.h
+++ b/Core/Tools/inc/IParameterized.h
@@ -15,6 +15,7 @@
 //! @date   Oct 10, 2012
 
 #include "INamed.h"
+#include "IChangeable.h"
 #include "ParameterPool.h"
 
 
@@ -35,13 +36,19 @@ public:
     //! add parameters from local pool to external pool and call recursion over direct children
     virtual std::string addParametersToExternalPool(std::string path, ParameterPool *external_pool, int copy_number=-1) const;
 
-    void printParameters() const;
+    virtual void printParameters() const;
+
+    virtual bool areParametersChanged() { return m_status.isChanged(); }
+
+    virtual void setParametersAreChanged() { m_status.setIsChanged(true); }
+
 protected:
     //! initialize pool parameters, i.e. register some of class members for later access via parameter pool (to overload)
     virtual void init_parameters();
 
     ParameterPool m_parameters; //! parameter pool
-
+    IChangeable m_status;
 };
 
+
 #endif /* IPARAMETERIZED_H_ */
diff --git a/Core/Tools/inc/ParameterPool.h b/Core/Tools/inc/ParameterPool.h
index e57f04715f8..889526f89af 100644
--- a/Core/Tools/inc/ParameterPool.h
+++ b/Core/Tools/inc/ParameterPool.h
@@ -15,6 +15,7 @@
 //! @date   18.06.2012
 
 #include "Exceptions.h"
+#include "RealParameterWrapper.h"
 #include <string>
 #include <map>
 #include <vector>
@@ -29,20 +30,9 @@
 class ParameterPool
 {
 public:
-    class RealPar {
-    public:
-        explicit RealPar(double *par) : m_data(par) {}
-        void setValue(double value) { checkNull(); *m_data = value; }
-        double getValue() const { checkNull(); return *m_data; }
-        bool isNull() { return (m_data ? false : true); }
-        void checkNull() const { if(!m_data) throw NullPointerException("ParameterPool::RealPar::getValue() -> Attempt to access uninitialised pointer."); }
-        friend std::ostream &operator<<(std::ostream &ostr, const RealPar &p) { ostr << p.m_data; return ostr; }
-    private:
-        volatile double *m_data;
-    };
-
     //! definition of parameter type and parameter container
-    typedef std::map<std::string, RealPar > parametermap_t;
+    typedef RealParameterWrapper parameter_t;
+    typedef std::map<std::string, parameter_t > parametermap_t;
 
     ParameterPool();
     virtual ~ParameterPool();
@@ -66,21 +56,13 @@ public:
     bool registerParameter(const std::string &name, double *parpointer);
 
     //! add parameter to the pool
-    bool addParameter(const std::string &name, RealPar par);
-
-//    //! access to parameter container
-//    iterator_t begin() { return m_map.begin(); }
-//    iterator_t end() { return m_map.end(); }
-
-//    //! const access to parameter container
-//    const_iterator_t begin() const { return m_map.begin(); }
-//    const_iterator_t end() const { return m_map.end(); }
+    bool addParameter(const std::string &name, parameter_t par);
 
     //! return parameter with given name
-    RealPar getParameter(const std::string &name) const;
+    parameter_t getParameter(const std::string &name) const;
 
     //! return vector of parameters which fit pattern
-    std::vector<RealPar > getMatchedParameters(const std::string &wildcards) const;
+    std::vector<parameter_t > getMatchedParameters(const std::string &wildcards) const;
 
     //! set parameter value, return true in the case of success
     bool setParameterValue(const std::string &name, double value);
@@ -89,14 +71,11 @@ public:
     int setMatchedParametersValue(const std::string &wildcards, double value);
 
     //! print parameter pool
-    friend std::ostream &operator<<(std::ostream &ostr, const ParameterPool &obj)
-    {
-        obj.print(ostr); return ostr;
-    }
+    friend std::ostream &operator<<(std::ostream &ostr, const ParameterPool &obj) { obj.print(ostr); return ostr; }
 
 protected:
-    //! disabled copy constructors and assignment operator
-    ParameterPool(const ParameterPool &);
+    //! disabling assignment operator, hiding copy constructor
+    ParameterPool(const ParameterPool &other);
     ParameterPool &operator=(const ParameterPool &);
 
     //! print parameter pool content
diff --git a/Core/Tools/inc/RealParameterWrapper.h b/Core/Tools/inc/RealParameterWrapper.h
new file mode 100644
index 00000000000..6d674184395
--- /dev/null
+++ b/Core/Tools/inc/RealParameterWrapper.h
@@ -0,0 +1,68 @@
+#ifndef REALPARAMETERWRAPPER_H
+#define REALPARAMETERWRAPPER_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   RealParameterWrapper.h
+//! @brief  Definition of RealParameterWrapper class
+//! @author Scientific Computing Group at FRM II
+//! @date   14.12.2012
+
+#include "Exceptions.h"
+#include <boost/signal.hpp>
+
+
+//- -------------------------------------------------------------------
+//! @class RealParameterWrapper
+//! @brief Definition of wrapper to real parameter for remote access to its
+//! value and callback abilities
+//- -------------------------------------------------------------------
+class RealParameterWrapper {
+public:
+    //! type of the signal given parameter can emmit
+    typedef boost::signal<void ()>  signal_t;
+
+    explicit RealParameterWrapper(double *par) : m_data(par) {}
+    RealParameterWrapper(const RealParameterWrapper &other );
+    RealParameterWrapper &operator=(const RealParameterWrapper &other);
+    ~RealParameterWrapper(){}
+
+    //! set value of wrapped parameter and emmit signal
+    void setValue(double value)
+    {
+        checkNull();
+        if(value != *m_data) {
+            *m_data = value;
+            m_signal();
+        }
+    }
+
+    //! get value of wrapped parameter
+    double getValue() const { checkNull(); return *m_data; }
+
+    //! connect external slot with signal which parameter will emmit
+    void connect(const signal_t::slot_type &slot) { m_signal.connect(slot); }
+
+    //! return true if wrapped parameter was not initialized with proper real value
+    bool isNull() const { return (m_data ? false : true); }
+
+    //! throw exception if parameter was not initialized with proper value
+    void checkNull() const { if(isNull()) throw NullPointerException("RealParameterWrapper::getValue() -> Attempt to access uninitialised pointer."); }
+
+    friend std::ostream &operator<<(std::ostream &ostr, const RealParameterWrapper &p) { ostr << p.m_data; return ostr; }
+private:
+    //! swap function
+    void swapContent(RealParameterWrapper &other);
+
+    volatile double *m_data;
+    signal_t m_signal;
+};
+
+
+#endif // REALPARAMETERPROXY_H
diff --git a/Core/Tools/src/FitParameterLinked.cpp b/Core/Tools/src/FitParameterLinked.cpp
index d2da689262d..ae1944e1c0d 100644
--- a/Core/Tools/src/FitParameterLinked.cpp
+++ b/Core/Tools/src/FitParameterLinked.cpp
@@ -17,7 +17,7 @@ FitParameterLinked::FitParameterLinked(const std::string &name, double value, do
 /* ************************************************************************* */
 //! add real parameter to the collection
 /* ************************************************************************* */
-void FitParameterLinked::addParameter(PoolParameter_t par)
+void FitParameterLinked::addParameter(ParameterPool::parameter_t par)
 {
     if( !par.isNull() ) {
         m_parametercoll.push_back(par);
@@ -35,7 +35,7 @@ void FitParameterLinked::addMatchedParametersFromPool(const ParameterPool *pool,
     std::string wildcard_to_use = getName();
     if( !wildcard.empty()) wildcard_to_use = wildcard;
 
-    std::vector<ParameterPool::RealPar > matched_pars = pool->getMatchedParameters(wildcard_to_use);
+    PoolParameterColl_t matched_pars = pool->getMatchedParameters(wildcard_to_use);
     m_parametercoll.insert(m_parametercoll.end(), matched_pars.begin(), matched_pars.end());
 
     if( matched_pars.empty() ) {
diff --git a/Core/Tools/src/ParameterPool.cpp b/Core/Tools/src/ParameterPool.cpp
index 42fecbe76f3..f9df4b9646a 100644
--- a/Core/Tools/src/ParameterPool.cpp
+++ b/Core/Tools/src/ParameterPool.cpp
@@ -5,6 +5,9 @@
 #include <sstream>
 
 
+/* ************************************************************************* */
+// constructors
+/* ************************************************************************* */
 ParameterPool::ParameterPool()
 {
 }
@@ -14,26 +17,15 @@ ParameterPool::~ParameterPool()
     clear();
 }
 
-/* ************************************************************************* */
-// copy constructor for completeness
-// declared private, to avoid unconscious copying of parameters that point to previous owner
-/* ************************************************************************* */
 ParameterPool::ParameterPool(const ParameterPool &other)
 {
     m_map = other.m_map;
 }
 
-/* ************************************************************************* */
-// assignment operator for completeness
-// declared private, to avoid unconscious copying of parameters that point to previous owner
-/* ************************************************************************* */
-ParameterPool &ParameterPool::operator=(const ParameterPool &other)
+ParameterPool *ParameterPool::clone()
 {
-    if( this != &other)
-    {
-        m_map = other.m_map;
-    }
-    return *this;
+    ParameterPool *new_pool = new ParameterPool(*this);
+    return new_pool;
 }
 
 /* ************************************************************************* */
@@ -50,11 +42,11 @@ void ParameterPool::clear()
 /* ************************************************************************* */
 bool ParameterPool::registerParameter(const std::string &name, double *parameter_address)
 {
-    RealPar par(parameter_address);
+    parameter_t par(parameter_address);
     return addParameter(name, par);
 }
 
-bool ParameterPool::addParameter(const std::string &name, RealPar par)
+bool ParameterPool::addParameter(const std::string &name, parameter_t par)
 {
     parametermap_t::iterator it = m_map.find(name);
     if( it!=m_map.end() ) {
@@ -66,16 +58,6 @@ bool ParameterPool::addParameter(const std::string &name, RealPar par)
     return m_map.insert(parametermap_t::value_type(name, par ) ).second;
 }
 
-/* ************************************************************************* */
-// Clone method. Clones everything.
-/* ************************************************************************* */
-ParameterPool *ParameterPool::clone()
-{
-    ParameterPool *new_pool = new ParameterPool;
-    new_pool->m_map = m_map;
-    return new_pool;
-}
-
 /* ************************************************************************* */
 // Clone method that adds a prefix to parameter's keys
 /* ************************************************************************* */
@@ -103,14 +85,15 @@ void ParameterPool::copyToExternalPool(const std::string &prefix, ParameterPool
 /* ************************************************************************* */
 // return parameter with given name
 /* ************************************************************************* */
-ParameterPool::RealPar ParameterPool::getParameter(const std::string &name) const
+ParameterPool::parameter_t ParameterPool::getParameter(const std::string &name) const
 {
     parametermap_t::const_iterator it = m_map.find(name);
     if( it!=m_map.end() ) {
         return (*it).second;
     } else {
-        std::cout << "ParameterPool::getParameter() -> Warning. No parameter with name '" << name << std::endl;
-        return RealPar(0);
+//        std::cout << "ParameterPool::getParameter() -> Warning. No parameter with name '" << name << std::endl;
+//        return parameter_t(0);
+        throw LogicErrorException("ParameterPool::getParameter() -> Warning. No parameter with name '"+name+"'");
     }
 }
 
@@ -118,9 +101,9 @@ ParameterPool::RealPar ParameterPool::getParameter(const std::string &name) cons
 /* ************************************************************************* */
 // return vector of parameters which fit pattern
 /* ************************************************************************* */
-std::vector<ParameterPool::RealPar >  ParameterPool::getMatchedParameters(const std::string &wildcards) const
+std::vector<ParameterPool::parameter_t >  ParameterPool::getMatchedParameters(const std::string &wildcards) const
 {
-    std::vector<ParameterPool::RealPar > selected_parameters;
+    std::vector<ParameterPool::parameter_t > selected_parameters;
     // loop over all parameters in the pool
     for(parametermap_t::const_iterator it=m_map.begin(); it!= m_map.end(); ++it) {
         // (*it).first - parameter key, (*it).second - parameter itself
@@ -145,7 +128,7 @@ std::vector<ParameterPool::RealPar >  ParameterPool::getMatchedParameters(const
 /* ************************************************************************* */
 bool ParameterPool::setParameterValue(const std::string &name, double value)
 {
-    RealPar x = getParameter(name);
+    parameter_t x = getParameter(name);
     if( x.isNull() ) {
         std::cout << "ParameterPool::setParameterValue() -> Warning. No parameter with name '" << name << "'" << std::endl;
         throw LogicErrorException("ParameterPool::setParameterValue() -> Warning. No such parameter");
@@ -175,26 +158,21 @@ int ParameterPool::setMatchedParametersValue(const std::string &wildcards, doubl
 /* ************************************************************************* */
 void ParameterPool::print(std::ostream &ostr) const
 {
-    // output depends on size of the pool
-    size_t nsize = m_map.size();
-
-    if(nsize) {
+    const int number_of_pars_in_line(4);
+    if( m_map.size() ) {
         // printing in one line
-        if(nsize < 4) {
-            ostr << "POOL_" << nsize;
+        if(m_map.size() < number_of_pars_in_line) {
+            ostr << "POOL_" << m_map.size();
             ostr << "(";
             for(parametermap_t::const_iterator it=m_map.begin(); it!= m_map.end(); ++it) {
                 std::cout << "'" << (*it).first << "'" << ":" << it->second.getValue() << " " ;
             }
             ostr << ")";
-
         // printing in several lines
         } else {
             for(parametermap_t::const_iterator it=m_map.begin(); it!= m_map.end(); ++it) {
                 std::cout << "'" << (*it).first << "'" << ":" << it->second.getValue() << std::endl;
             }
         }
-
-
     }
 }
diff --git a/Core/Tools/src/RealParameterWrapper.cpp b/Core/Tools/src/RealParameterWrapper.cpp
new file mode 100644
index 00000000000..b4e499e3ca6
--- /dev/null
+++ b/Core/Tools/src/RealParameterWrapper.cpp
@@ -0,0 +1,23 @@
+#include "RealParameterWrapper.h"
+
+
+
+RealParameterWrapper::RealParameterWrapper(const RealParameterWrapper &other )
+{
+    m_data = other.m_data;
+}
+
+RealParameterWrapper &RealParameterWrapper::operator=(const RealParameterWrapper &other)
+{
+    if( this != &other )  {
+        RealParameterWrapper tmp(other);
+        tmp.swapContent(*this);
+    }
+    return *this;
+}
+
+void RealParameterWrapper::swapContent(RealParameterWrapper &other)
+{
+    std::swap(this->m_data, other.m_data);
+}
+
diff --git a/Doc/Doxygen/Doxyfile b/Doc/Doxygen/Doxyfile
index 31fd7034bd1..2e8c4a5fe7f 100644
--- a/Doc/Doxygen/Doxyfile
+++ b/Doc/Doxygen/Doxyfile
@@ -1573,7 +1573,7 @@ HIDE_UNDOC_RELATIONS   = YES
 # toolkit from AT&T and Lucent Bell Labs. The other options in this section
 # have no effect if this option is set to NO (the default)
 
-HAVE_DOT               = NO
+HAVE_DOT               = YES
 
 # The DOT_NUM_THREADS specifies the number of dot invocations doxygen is
 # allowed to run in parallel. When set to 0 (the default) doxygen will
diff --git a/Macros/BoostPythonGenerator/codegenerator.py b/Macros/BoostPythonGenerator/codegenerator.py
index 6c03f22a946..48c0b4f879f 100644
--- a/Macros/BoostPythonGenerator/codegenerator.py
+++ b/Macros/BoostPythonGenerator/codegenerator.py
@@ -70,6 +70,7 @@ myFiles=[
   'DiffuseParticleInfo.h',
   'PythonOutputData.h',
   'PythonPlusplusHelper.h',
+  'RealParameterWrapper.h',
   'Transform3D.h',
   'Units.h',
   'Types.h',
diff --git a/Macros/GitUtils/gisasfw_loc.png b/Macros/GitUtils/gisasfw_loc.png
index 3a204838a68c5666983eea4441144df06094f070..5a0bad0546b81bba53c9a89fb05a0272edf3dca4 100644
GIT binary patch
delta 13211
zcmZ8nc|26>{~z5-QmKeGR6=%1*-gtu_AG;JL)nUqFm`iNq$pw%vLzxTOC<Y@tXYRN
z#u5|8I@#A@mfsn=xBL6{hgW6Joaa2x=kwk^hyIA|X(-!^lwGUTm$@x5Zv)Tx$67UZ
zL!3VjQ`&#tyL4hAnKAJQKUF<n%ZX#G6jZ+ASVKeEPVMAE$4#Jbvjwt=ph;{S0ImW0
zu%leXclK*^F`{~<hYucfNFct_caAZ_huc$%U2KtPUM4YSNa}v`Z=4??aP(CKuxSMy
zEEy0~^*boToyA=%`p9cmg+w**Q~yyNxCUj6LIVyfPoNk}X~1H$XtdgD0@ER%nU%h|
z`YzsfqdSd3PTmB6E`QUN0fH%3q{TEEeUL;?@sbW&-kd=I14?Uf<_a98tXhvUAhy+`
z4b`b*@$ii)(Nw<?)^9e8uSD)%Di7ZL>@{0Lv~3lPC)x%|Nv<w;8>&pq{wPO(NX4&F
z#&4_ORhRU-FWurrwBr}j-ZcmWFL#mGhHwCL(rb!3k>=Y0P??X|xdgmtBGPDNQTjkz
zWwok>C%iVAL>pH~@rs5r%9smHP{v2E+0~f=6tl^lgiUdqZWc{zGa0NvO4yFC5aEdZ
z%neF`ukgOvq3WapzqQ#xGPWMeq|dFn%@0)vQpKB75&D}yyzs(FEo=UM0rip9)bXUe
z6TfhyMlv{Bk=N|UCV^JOV(y$zW$GvT=B1mxP#BFOd|(_1S|OOD$LOPh%K~Z(_1sjs
zX0N~Q8qvmi1cQQ0B023X+*}rxE|C02pJ&|xADkN}htA%43LqWkjcf&Py_O0vsDW#<
z$eHjPQ~`f-jDtZ{`-_P%K3l(u6yE?Jx1w9F3rnd1(>a37^(Osp)s^oi_68Q`O|hbB
zLErEk>@Dj@`FyS?pyytgr7x;&{whWpoI9J&sAe)Y=WtAH+EjM*(0x8w<qggyN7N!Z
zZCwekwq^~;Wj_^%_Y&?)wE<IumA<5)rFJrEg+%Xh^r^H_1%6=ZQ-;8FxBA9p1{C}&
zy)A!aLa^N&9$eBqL|ISF;|h2mWT?6jnzmFY$dHBa+j`^(xEu+;ubtF65--^oP_sB_
zk9GfM5EjtQlz9DqY8m=?gxEbJOc_tn0@R^OC)W_Nv|bo3sE?CYcSr$PI8^Aosm687
z@X_IE>-WdhmZAk_ld?E&r{`(2Hc15I)htJ)_1N%F!xKg+);}<fOV^ALE4{a)l_qRa
z)UnjW(baq1@(fix*dpiKro>U&c@;>C8AJD)kzUXKIGIEyxYk0^6Y@XL0Bh8+)KP1i
zC=dc<Cx3dt=;cw@;)u1!uMGv_1?OT-8tbxELJG2|;pfv`rw$+Jqc#~}nVW-iC?YPb
zE7ov5)`ko{=-DxrHcuVBZBe7EnMCK5q$XVARVPP6hrK%JU~|q#8xX^bY-k7c9=}fU
z;u27uPbsY&N=*MQOaUq=;dRg-)NBm(eHo6g*`z~55W2Q=6*&vG(o^RRK`6NKe&e0N
zD%aIFX7U9`@&&KStdp2@Ql7+PL$-8Y(JB}3&D9wwlZy9uJiIr%wB8bG)iUNRuL@q6
zhT6!1_MLqeKh9p+ReMajoJ)QEryz4d5Wf-`wa9)2cnDlmjo~RjCFwEI!4Hglb1E+P
zn&{{@gi0w%hmXXQyul9f*!wJ*gr+*9sGHF}_+5fvZQ`NKABcKz+0LlB>a`&#tqvM0
zND81xK^GdpJ)ck^9edfMwAQ617))Dey1%eFw1%C?k9-^dYv79WVGiN28L&mQbj>Z^
z04qZFS_{PwMig+F!<~}fZx6G*UpX}}9it_1Eb-2Vp0&-qMc=ijGT8Nz*}+QGglf?G
zd_0aeCIe7){g1S9kaC{+tjb(J(Vw{+M6X`37Z$7Mg7KvRf&lHKS4SG>sPN|Ma9#ML
zA$#lV@9!~}pv-O@<onxo`)B#w>hTjmPo9;{-0W?vZY98Euv)8ZukwVGs-|HUB@~~*
zDkls^ov}U|t-f(Ci0h{3!lVA+KuS+u54XDgjs`BRdLg@XZT<Xdl?JefQEQc?U<P%9
zs!umB*3VkOV9katf|!h8z}rB&udO8N-s-a_0tDq}G*$t@y`}&lX#VGwAzB0171bW8
zm>@T?wc<4T2aLFH@V&IkzSRcJUjwb>NJ>vU99&5}+!K~&lRSS*lX2*$uq}<sx7ySo
z^Sx?*7(V~281H^5=};5JgQr8+2HzCIJ-;7LStra4lqw`WXG+d9=$ll2=6oF&y*x}!
z@W%$sGBQn212|c6fqu#h+l>Wlnz34nTgm>kK0KDM+h3<it4ra-k*5ybwPl2mtPs^D
zeQu0#1Y_LA4L+kzC38c^kEKnItlgu*#yiTnptMf7h0?~gg>GR%?nau|H95-%{zkNY
zd+27Wy?*Hkv1f+P9$kFe;oSB?2@Yjb&lQH|({=z+u4c4DN=l_;UmmeDzSrkdNHS9L
zLCx8ZNZ@LMHJ0JjVc&+ja4vNE&-q|An*lCTNUZ6T8`q;y+B&sq6VyKEv<86rWl)v#
zJCg|#g(%`;PzYF}TC~8Jd5>_>2l1+E*4}2$iqwWBXB+KQu7&L2r)2|?6Pu;Mv0SYH
zeXT0l#$`RWmNuPRurZ-&hz#XjvT+P4zzx4cqJm10epNIMgnfUBO>Vqfy9_TJKlC@T
zd;(Xiv{uV0Q!iQ~$`{yRpXxuJsAy=>DCiI<?PeHyPkr&L5DQ)vnZnkq0x~|YD6~Zx
zFAgFzOliRvP^FStMCqXTJ`89bN}Aju2b|GdUznswFy8+HALuzgU0<5PjkT;p9vF_?
zRU2)e=#lb>L|Aa-TF9yuPNgoLzA0x~22#H|i1YWqs2uO*%=Q%_(k_br8dx7m&LGVn
zE|^UEOdi3_>+SKX6`tuRXA$yK(bPTo=d=;%xxW{Z&{gXf`+R{CRr+!_YJQ@sK}MY%
zrsTg!)A#l4+w2@6%Il+Qor#Wf=p(qSJGQ|q1e#5dHMMH}&5w#}6;&WDY6tQFFdd@W
zbWF6sX6wLhDiYP4v~MoOcSt+m=PPcxrd1}mStf8UCMZ|;Es~^zRhFjeyk6pk$^h;+
zs2_et_Z=TKZUUr(W0ROJ6O%;E@Vx<zOK{r9z#*vF(6knGBSyt%QTJ%di3JGNzOKtT
zicI_I%#7c+XYKPm^`NFY-cRPC$?D9zuy0?fGLLW2AduWT4jJ^peUA;oN7x}2DTp?H
zyTW#-3%)xcHT(6u+xYE|1~%Z2{b+?0+VKV+eyqj@$-P~)ey_icU;LeHtPtT~W~@+L
za;@oJA$_~s?tAVRe~do{;cY`7kUp~;Vj&wDK8AKZauR*;&@Rr0H&rEN(wF{%*u6j_
z4juvS5=R|oqaZbM7AIH9k$K=Zdu6WQD;<~z<Sv-Ka=iI!xM{=k<|}F~iW6zG`P8q$
zAtax`txWQMp%Z25$-3{0+Uq7R6*Fs_L5Z>#%y={`-e54~9y&@8k?uU$Gc%F9=CB*0
z*EV8bUhp&AkT~M_d0@u9R9DAza%j2&z*ba<N7O3#*bCWnI^GmG5Kc$UnJ-x7V#K}u
znird+-AfS0kjoP2@UeW11&;<r4uxV`E}SIoc|6<hm}g6qhz(1kXcl5HepGV&Dmn2`
z4*9yUmbj8JM~Z;<aEda9ZX7=2L)k2*Wz`LLn&>Q91?x_nxWWV$Ps6Ppmw;U~?@1x6
zi{hmF|9v2C7cmt0xanVeOpKDfG>l$49%Dqf87Gc_O0OHqgDa~-!g?4HoRFGRQVny{
z(=8<_-;S*to5JD>yv)tbW4+{Lv?h+cW^K<&)`Bu+zwP`sGSO;b&Sy<T8u7qj1msMC
z=DaR2>r=^q3n2zAPc+q!X9XE}=0*w(HjBK@N?a)Q)n9LNT|L_T_nWg^(LXz%Ue*>6
z`0~{ErG`TO66as3HoEbSi2%)vr(xJ*K7I_DcTVh1YNlS)(RBB>7hDtU9&(5zD2|3|
zC@4cot1~{8?H8dyao_Sjx7F`eUQ-1r%B0{I2LCxl?(5-dkx8|B&@R$YIYnAFl{=06
zEnwQI>auwZh53&4@&A0<#3ewub^TD+I;PSgk#@D3+=8RUqhq)X*?fzKxt{F+=5+(j
z@Jr`{y03tz(Hx^=U@x8$H@D3H&cj@gK%@$5d|g7i;7FS?ancbZ9*UvUFye}PsYJvX
zM$eR=O7k=f#(yBZtd4W+GjhdD*;o1Z!KUOSCoRkE<|t8_E_!`H!|0RrXmX^hm0VN7
z5t1b=E)ruynYNE}7zVQLtZr6&<+CayzYX%{g_i<DD!QT0GjO7G(48y%k&J3HZ65fU
z1cma8#KMAHCz;Vrvh-<tWq6IDZ?OF2lq&4$c7-R$nkpMF8x>`U^cd4<osKY=cHG{I
z@xc4%BTJ{0BjDCUi~Uo`_O;`2YAU~13CjVpm_xiuFqOM<QVn>Zu_qwQ(Uo1~P6xy;
z%&gC(?*%UuzSP0ce1k(qmRyQ@+7tPsG886~ny>~Qd#IbvqD$(}L!Z>sCk}ZVtO)sS
zL={ao!jXIaN)@^!e@pUH9C*&}+x5Mj+U2?Lf1LtUxU&uC_gJQN&hOcneq)bV)&r8U
z8Il!URO)9$>A<~wDmAISk@Q`;R_V)w>?)rf4-UWDd^@K5&x!XBHB?&$jc4<LM{c4*
z*SFEg$K`$R3qWt5xJj(|RMgAN2(f4KVOi$bXO;fxwx0a9DDdYPoVj}`cVltCK>I$(
z@v<;mLVU5Gg@83c3%V#CaSKNZ=VV)g(emtv83c6yI0a6be%@Za&o1m7>h*qUR6CN5
zbL88Rf-&KDx<vu1>xl)a6J6yb?X4beZcl1K2Bk&T1|tK`hWSpvUm$5(5|K=;`*hA{
zw!ydOPnfcOXkYP9^_oZsZKx~yQonmm?m<cVx|s8#l}x#)cPi%Z?c$3vy$XV3jcxgC
zKyusQAxI>T;9E0Ki=tj?@aX!Pjf8<#h}o?;{g>MN0&VwhpJDkilZ%5u&6Q!S@zFaw
zRs&#>^otMTEC~M6A!sAvGyB;-?5s;Qll%{siu0BK)hVJRnK$F&aK9HF`Gd_av!`_A
zWSX8`?~?I0EH&GlAvkqY`K8tPKEss>PkA(7Kd81P+yeI7v0Z(>N9zqTbs!Pkz)MQM
zI3Ol>?>#r`laXStOO3y}{UEcFIhIXIfxDr*PMDS!{JFX&xd-4@G)I{^^F@X`f)w#{
zw{}>u&wH&1d%W)HZ4~kiz|el_4~wPn=_7r%wxi(gN8E0^>nJnP4UiX-POiEIr`>WV
z{&nL?OX*>eaJ8hQ<d&9fud^YnMzGSuaEPbX2EPNr?AHp0cheQJ(IEWbcH1dlu2%5F
z0Nc;2ANcFe$2QyJLpxGawwvc<PUxRiURLVxQVMIRldDUGn296&KJeF^7x?pV`4VwV
zr;hS75<krUEbk3l-cXpu*6PS-d?DBF3;%Tsyj%I#VEHXr0Wj-9ul%EV_X2Biwb!{_
z=3tbHA@|ab@*+w4-;!x2ED~Fowxvw}VXz*8)G84&-jHUEI|q{Et9okX1HZ(I{DS=a
z*j*8C=NsCTK#cIMv<af1aM2RhMRdO{CQAa#WL#sRl68@HZ?~@{3`RZF05VpxZiVs$
z@Pm<cqk6hxXvRmwsQz~B{qsvn{c~%K9t`F{__ZHH)UZl3#Jgf=(e2aVF_=nTsP8Zn
zUyG}_Zt@ih)pg?4IE2?m>5)s#U}JCZP9#U_-d;R`4!gFpzoD$05y}OzR3b9C;%_e$
zCi|dJ?y3_Wip#WwuZR_!6vTcyz-$f=!rBH<cc7F7_;x*zZWc>ffS&RpyWwT`9>+^Y
zyp?QiFUgc^Xpo!~L*4hMU_Q`~m^<SQwkxaFT;*PlYFG|<T9=&{md4tF2l2_CQ@Tbl
z7`DU4#-=3on^L0YSdubp*IC?unAI1-4fy!dy5WNXB^3Z@mEL1o;G9Op5|V54R7yFc
zN2;e^QRLFKP}nvdmDPu8q<}K-HS2IV5*e?nXrl`7Q*=jv8!Plnc|&6n^qSa-FE>B`
zMmBLZZgs-1^Re61m(Km=mp`p5LCd4FeoCd~?I`$7fHe`5J)WWq%zOu^kpB`C_w`6P
z(YMHtK9f>8y8{jTfedj|Lte0bllxWw2As{p+5g}Hw5xlI^M;8UJ<eyrn<7pP3uul5
zsH-;KV{jA<j{VZp_FR3N!~@Ebh)ZJHaW@jCm#^=g`)+jS7TgUi75Ly`Y0ve5T@yjU
zz#`|mAbNzHkJ};Qmgl-@le-D3AB9UGBylK8JEc7Z$wzmDhQT_7IC#iO+raOA@?CM*
zq)soaE)k?=9U<}K>mu<~u+)81Mf(D-1QcEVjdW_zQWMY56U*BWQbJ!X$R6eSC6V4O
zBvxgjbxhCAL*_5V3?P-;O7T)#?TCFJ8ScqmXkg=r?+@Wyx<HNpp>S{fK%DW>=9s&C
zjGOh*;>U*EqJr<Nyj~-m`qOD175Vs8S(R=4IC@Y#t>m`kOF5-qiJg7LTSOpXc=7#W
zUJ$$)<N>z8YD@#;c#W9L=1UN-Y_CoL>~{M<@Y|&KAC5@--Tqcqn06-`5ms;y{yggs
zY<T8{-?CkP4ML9BXHkg8VvF<4o4qIW4g`9}Y`U=a`$wM%fAs^KTf&>u-v3!253z8-
zaiP$y2-L4Xd34XAlmmTO)##p+Ga^9+ItW)Kk?@oh5CsZ}xt6~Q*p}^Tx|PA_=~&(Q
z=3&VrQMcQFfH+3yx_u@`F9pWJf`IkgGBU1}k^-;dJE?3C*{}b31`CV{w!)-vL1QMj
z)o6<f2>DITKls_qr2WN~_I_?1Da>vzR%_oq;|Q_wyNC`s@f5JdcD@PjEzYMDNwyaK
za4*f{bSt&OUA7_S<!<h3%oE_9v{Xy~7Yek*Plv^bbbiYnS2=T2<mQ`m5oM1-4L<13
zCsRn8Yc1l*w<WF+2r%ZfH|l`~ZR+j2B0mcQ6)4FK6q54#-SV6CAtgSd0JNGkN8h1g
zbP_la{x1^A6O+B}pVu`jz)X86*7K*r%UqEVUYq3t1;}lAg|Q2fZ#@)pjjRV^m6~g@
zRpsydOY#NGw0RE@6nJjqf>O)7!dXCGoX}EUz|?OZ!M<*ois2c`$@tcR$3LGqc_3VN
z#_AI}Ly<%q<7~=Z@9AU;t^qNq71<P-pV^h_$M+=$x~Fjd)<wn~VCjSi5vgHDoqkTn
z)raq&=M4B)L9xHF4)U)PkN$WAQ@kGMSl;JGWA{rZxX#p^ZST|gN0423efL$7vo~Dd
z5In!-BRC9(_QDCs6+Qh&MT`88j9z%&cl#`NNUW;r!)u}s$yw_@0#~wE4x#h-XLeMX
zppylz0Mpi|!9scTw7B|%7jCQC`;G5N2llVVWy=z_pLn0hrLy>tF>QnB35{|m7U?l#
z11T`EaUV51BgV*R9D8IGoSc7SvHYFMO{%x8f)0qRV7Gcl0b?Hv$UIqpghU}^cuzBh
zivzqR8sx&P7=TaJHC*vc%73^sNs{1%rs+Rsgqc?t>^4f!`L|pjSU!phtXk}B8L>~a
zH?*tXkVq@ZI3^4Ehe=Zs#E-Qtzs{nQ9CD;Xe@mY&u9yERqr2wir#AfeHfNWA<v;2W
zH}@-qTm4^7l@ft1t|Z0#<)P;Up@--u*aFjkZeDd!y#)<Dbxg+Z{IECc8}O?;d!~AQ
zpAD{e^?%%x!1H?rj<^asyc6CVmHN$pwc@J~I{cIt+a5Ij6q#)f{pqwETRD2-v=P8;
zbQq?UD%?Yy4_It_V(QsrLQO@y?!a$gUmwm1HHglfH{g%+L1EDpu~*@B_MLgy+@-v9
zCY1UDPt=tGb$WP55iG;=(`!@DEED~p)X1sei|4mX?3F#fr`u{Iam%|&7wU?eShqb)
z9pQ^F&2Q<4-w&A*29kl{XTVY3nw?SB(>I7Kpot<#w=KVWj}eDY<mcy~op7*?>X4Av
z7Iv0^EwVoqadL&XM{aHAn}T)FzZqV7igy-^c#9DSr2e)cwyzvJPseEvRj}kdt<uI4
zw<OFMkDn6#UoRI;KI9Ge4Lm^tmKOGO2s|SGv<AtnV+52Obx-5%oj}ihxTYpPmk~X7
zR=6GgviVBd-Nzt-jx2Lb)Sgthg%nA!ActzqG$1MmH=GPSNtOl1&;mw(&e9-z4!P~!
z>jhziJG}kL_EO)0jdU!ZpzFR!s`yr1{`OpKkCb}zyOr<len3e686r~`iQPOEmmFt$
z{J<fz)wtbTyuP<xpP^GpHm)M~fCjIOd9PpkyKX+M6}UsAEV9)8cw&gI7q@LQdjd<1
zpx!0T0ZRuYgE+F`Z!qG_45qaQsQky<WPY|<tk=eO&QRG1Z_m-#!?#JXa*}&ARS7u$
zLdU=#lR2EEkh2*4Ztp)w&Szem+Bz_5D=YTA*%u*Fc?xj`EyHXxk1kCsnB9kMcyLEP
z=rR=4U<+d#lM?{T3k;I2_F0UpKvTUhv-Izyr^i-R*>cFS_J+c2adQ%|>%yNp><u41
zRWT^P;Hza9h8bZ$=fL}My@Yw*YOD<e?g!#p*n#eyDdsM*XnSEXwEvL<93{Q*I{C+H
zAt-d3xZvRyjoE~wb*bQu>r$=B2Ot*wXu%VFT-`@kce2FupHSr(y5}q(kfUGHr+BaH
z`)qEx(5F+Zl;k%l+3TXt{XE9LTnLJM|Cm6^CXZL8fKF)ivL%VJ_-O}kGr7>&3(W$M
zsIxCHDs|5VlNyyuyVgD#e=Goj*yKMra3eQwob6~Mi|`9YJ#2eyKSK;0J$o;J%mVyY
zncLK2S6~i4%rz-#J9Y!-g~F=P4z8oladW<Gilxs+vRORzqbjFjsIaI23@fr_Svq=~
zLDRW!r`FtLsc+Q*mZ5=U%PRe9)|kzR5#M;H#b*cC-ZJ(ed;Pw}=|<HMuaABffcqS6
zx<a}Y<i8moD<TqG<5Ri9`Dw_KSOT}J9Q^E#16B$z6Q?1N<jiJrt0|07eA$R+ArA%<
z=KQr5NS)rKGbX3=>Qeh(=(xW!?YKzCy$WWT!mym*xF8}OaVEz{d)FeTH+@pq+!`Ny
zI7xC&!jVC#K)JaAvyLvK5`u=pKP5p@x2kwgc3%(Roi-WDZSV@Z7l~LIlQOOBA=HUC
z*HRG(H}KQf#{TN~I%2OxZ$scn6MsdAFb_&o&*h(ss2l#7UH5lU1k(-Aguiku3P|YS
zoA0&}+#jH92s^Va=C`*QH1&Xhj%t&6K^1Tc`84uorwMIj@fFdaz!gh;ui6Si9C!9%
z?6*Gie-H9xc}GD$rEd5JkA~q^JaEs98o)juhaE9zQGT3?mOTYAcq{Mu?OPZAws0JI
z>JJ1G|NfeFHhP>x;0lFX^&xuZT%>X&3EbW|!`?&DM>+3-<@*RwC+y4BQ$0V2n0vja
z?<KiQ^^1^8@Ix(+B7R4sz=Z+#(#pXO$F)3UsMkX_L;o4DhEchDf4W&lz;C_+e+7T>
zg7i{GaP96wVw!DGtghkAvI6o*IpedjGeuv#e9A=oztv*m;=X9!FC0J85Nm~|%rA1T
z?246OF2d1I&l#~fqX*8Z?ik8J9}_#n){RybyR=ir5E75Re}s20Se3VZk|#K<qgb9=
z{k#g;ZmnSXfO3)@4A(>=1^LROKX;gpUcz+*Up$cW|44MaAwkr`h($vxPzc1}Bl?Zl
zF~D|T;0``eB(iE8^5Dv=8#M3LU;i(N+xD()k@ki^-~JYSYG%|d-kL-IC`$bock3&^
z5oU7_{ihpz)C|UF_hfwm?|FweTn%^L_rdvX<oJ^rC>isx1kP`5eBo9vcbWX}^mXe|
zHNnNjJE3<9p8>9bxFOv>QYZ?B1`xCGKQ4W{lsq!crCN*fDGuXcaK|UnDo3+`gFoTD
zh%X4A%E3kn5zbHf?jLcD*0qtZv-f!@f!h%Lls*vR5VGxKg(KhYx#(Fr2nLMntTfiV
zjBKM><xT;;M*ECo8xY1td%(f+8V3S>F4kgi%pmp>a`P#J?&driUhPVJd>7!2V1R}z
z!C*jpSL%xz&L^;Ir11S$$c2fRz+iY#aDK`sAahBU?|nMT%j6#`aOQC;=ogdbQoLZW
zhE`v?&#7VSx}{xPd-1A6=94=%mPZ)$#D-$+zr8EVx-KBlG>P(4YWoLHmh%f-p>D^X
z^&mH12&&UHY*&eAaU2_(AgKk&AiF@L1`DR{UTUMS-IC6XRk<xbf!*+p(w7Q?r+_Ii
zPnNP;Y^@6Nd*KMt+PnZ1iN2Np*t5p?{B_K#Y&L+z(SueR$88(sJ1nS>uON(bNu%_A
z76Pp+u>CG)#ccFf_sjij(DWX)u(RxyKMg325unowfRL`-i3uN_j@4v=9CAnO^e@2`
zDL;4$|DW5x+{&axentu!?zanI)hbIf#>Ih}5n?CJ`iGo1#nenag%n))-88<;N_Wsa
z{xS>Z{!LAu>)vkTPKW{Xt!7q9n@FawqrZ!D>w&(d>>L)qFCo66Zt<`(w8n@E+4nK@
zH=a+LCbesHEL9Dyzg;D0{C|`lJv_oEiQi+V39bjEvH`zdw7;|^0BbIW+}N^@eW?~4
z(oPVM)7z!JXlil*;q$SmKpqqdTVsYATb7(`JS89WKnnbleSufSTxEnIuM$qK{`i!r
zVya_**7<Z?>Vu87ID!AqS&HKRD+_!6dd%XKU$jEm+#nK%odK)!0MN|sAHz>4Q+{+L
zcLZyI;`u+#M5pOSYaNjVC9gk6ilCm=Sdszcg4NZ9ZqS?FJs383962k&@`8U%-DE9X
zWCw4}_5~k`S21jMsm&uzAbI8J94UIQb7U(m*lY4n!vc)sd5X>47Q0!ZJVlV#E^h83
zo6G%7P(bx51C@iUAj#2&NX-K$1G~T>#uGx_4x3!jEqIwn@Rqz=-16t!2@1SmdhI&)
za#41~+b6EQV8_n*EbQ2%t4qJ7=Ms^@NF)JQQO-E71kz;#s03zz(JFu;&UNKaq`9Q5
zJFl}?v~v(+ZbPgb1Sx3zwU@NC)4!Sc5~pw80Z7d;`9usRfY+m=p+qXtgh!(&g4Kd~
zx#2KyD3aATx7JaP!HkS8U8hzj@aF_5t`Tq)L0G2F@8|wKAbGdMnU_@HaGnIb6&7ru
zj^ho(pE?{N9p7N0@rOo9vD+?g`FPySrT_MR$Sc;Y4fr^v%-Ptgn?;cV6Qx$yY~n@1
zth~h|?3csr<CQ=0YG`};82v9z%61`9i#>TI_w~r6nQt2@G7AbgaOwcaw?D&GyVgb{
z+606W_q-$zA3CXg=v;H1km3Ruf1jA>?|kyH(=1j_=~igP(~b}Jw^lirv59KCx%Fi4
zzv75|j6~%LC3EldTO}H#%&A`|q?}H>0ARKTFx#5us0r=x{Q}-J>QsYh`SN!IzyzFZ
zAS74<7=}{>o}`+dXO$2*sQ?9yY}R^1yz=_DBhvfZTCIYRp}31wMm%^bcWqH(8dYb&
z`aqm#o9y;(EwDi37hIEJh25JHooGkeNx;>j3|Lvm_&~EUm>vRshju0-@H`*O3>GjP
zm-@_&S&Y=VZ7X;4;Y2p~CX@l*!6jYSjVsRPHa$wCPV=tGy`F7huL1LmvERA3ivx2<
zhB@gdZ8sq<GF;hz^1&F$m6s9}2U?ZaRC4lxQDV0ZE^$jI{WAb-u^Wjp5osHYxwt3#
z2-g8{f*48allDxDEw8RJFja@#)n8t5;(NEWw;hPfK5j}i!xrpj<;8ze+v=-CxZNe+
z1CaRN(y{-;V(?jr?myIuJLCWdckQ2uodpcGM>@RNdO%^y>Q$bi)vJ&~=`C_y-Id+%
zrVJ&VD5dV2%PnS&$Nt<1s6I>2c%4k<`0#=Sc9B1<NZAPkE3L&XrO^;QRuC1WRJtvU
z^+1Nc_OU<s;tp0#vc_xMte#=nBx@C}My=dm!-|){M7#c7LxWrKRIYQgm8L5mfJpon
z$O^A9D|#LI-74tE2=B2A6$MTJYf$wEar#5^1*CI4sI8$|e_1GjnDAKbzQg1<=45>O
zBAdnT$7(VSe`6d}i=8Ls(ts94XFy!|PycUc`gsRMF%U(TApuRkH5qj#Uk_5~xoxyR
z`6Vws8+|4Et)k$%Fo<<wIl#Y&pT{<u43Vzi*7dv7f3aPz1x>+KXMFx?7)mbNYbm?s
zPOtetQ?-A^w_&t9SB(QGX^yR0^GIK1hj4(4blfoYFO4@>U)>g}{}uP5olN!~wx6Eh
z75ZTI2E<gBwv@U;Ja&UCBnHJ)LPLsI5c{;HEs09l-$T4V=<0bbEwpuz8`1`%mw@W8
zn?$4yvAJ!=Cy6#0-{)THc=NM+IxGG{9}&*2>-X9R`F_kg-|7Szlp+|@B2eq!{|M${
zAiB8@X5?0WE<LIYki4H=Cm_E?qyeug%MyYwvTZjbW;^D5PHihV7eUug51>8;BX{U?
ziT@cJmd#F2i@Pb^tY#^e&VK$z@7d+99O;etCEm{k(h;l_Ys)-|$^WG^fx%3dU(CPP
zoD3RblEv2C5THyqiwnsm{rq9hgw*hYZD*g7HaA?M9=;@H`R)Bb$cXFfdA=FYXE>3g
z^T=4=hl{tcK;#-LLKo9xO-34da25Fq#KrT?3=>n!$eV@>OVIJ`-g<C2SgA^Q3D|9?
z8~^$&5R<@H)?hGHJ>Xe75azo-Pguvey2mXJQ4X<ls$<D<#)Wcld^_l#M2TLAN=1K@
z5j-$cdhE;xxrI=2DM_{3E5h#dfOTa<XMGhuEg!T60$0L7)nrekj%jpog$UgHrTHvu
z^=Mb7LRa~PZoT@`fxJG%Y+r-47f%@+!$My}`@w65>j74#z7$lQ2<B*7ipS>NO73i;
z<RCTjySV~CM|o_3h+Q2SE<bt!TD^WYKDED(q&V$XU1@yJl2NhY?KYF^zcm-wBGfRa
zCqYMme%-P~{9x4$&`>p%ikPol?AuD$2jYN7a=9Zvh)jsxF|hc;g;xo!e1!mbs=%{I
zlY~(|7b&M}=FyRkx4mT8U#dY`!Hhvw@&0?j_S>s5&a>}w%az&`+*dNZ<X!YH1}<Fq
zRN%xK`GY6$drlZb(hOM6P-JSI*eI2CUwQroabrKNv!ZVu(#g^{cDEh{D!o}}vk+jl
zCeR$*?KFEM2T+ZD{A{o9%ir%)Y&mxGd?{?hd@XmIQxL=jgg-EPzR=!(VJC#wg`>gH
z8K0VI9NSfoHGcSSb^T71qfBfdlD~x+1hV_)mQZQRS>E{_SFn7F)r<eeff95irMvm6
zhau!>V~f4grC)Q@bU1!f)YWhw#6s?|njv!r&eWA}Co*4l{%<2z3S>{s?fEMS^7H6w
z^0UX)s-uFLyCBI=?D2<i=xD{`fb)|QHFgN!m%@qI^Bo+J$S;N2^X5SpPeYL=6W6!E
zbIVh2Ll5#5<27P@=L2cb-+(!|O}{wl2wP38RQkGpcQIG6RmSg0;6E>$fGSX#t}*+}
zf5&AmFcksQK>5;mHV8)cm%sODhWU5JSOAo=e<&5q2vR=a#$$aTFYJ1~l*%&sA-vD*
z@eU>m*ovi>IL*xe`ThqT1xqGs$JHSgm=Zo*5AHH2#NsoI59jB{4Ji~5iG-_PRhzWV
zfJGtxf?%DB)`gJ<7F0`D0X0F$hZoHw3Os_qFE+@n<1)zilmM21D<5<>{9zh2_^=Y|
zou0kOVMtY@G#qJCa8w}F$Am`4=wOfLkR!!{*jo6K{7jC&uapFJALyX`I=ZfO<lEyj
ze`#xKH3+?T(-|$eZQ^!UEy+0U$B07J<TMy|Y|Z^xX?!~h=i3qI=-+b55GcRF4=KD}
z5s@Z1@qyCMw0H%+Jpe|TlRmLs1`x=tiU`uM$GM0zsiOnfD}oH8RS1OsDQ#vd5<a<W
z?CA7Ph_}&qDs`{#h-eT5a`IjEk}F|jzf6~*K1I&vf|g`m)^~>TrG~7YVzHFwyh3wY
zz36wjSq_Lxwo7mE%BWf+Iz@Q^NZo6~9~=UghVAia3`Tmdq$Y*-1&kXCIxTbF$k2Qa
zww(~QpcIT#;NTkq6}PG$Frhc)hRSGBYuVG~+6m%ArWBi0VM5u2c5I7MDQQkPBrGR3
zskYHsFK+IfeWC7LuES_7KLIV?HWy$vX*foe*=rzhs=3w6<#WcGc><6(r8wDsILmpI
zS4<ow9gwogo`JzQg!DK&gRs{?W{XrvPz^~g`?j1JQ96Z)NZTK4dd09h4ZNeX4>sn-
zS)3TkLm0dxSt~R$Yno}3VImy;vn&`nWcu-bPRHW$lkwuT1i=!mx!jDtjk$ueR=r=R
z3|G4A&RV^|K?ugcOYFG_a<GnPkW9o|WHg_~aM}VYL>7ut0p083<-KVmYB`IdT2=bm
zm={t%RJ1d7vs<|LBKgf0k0;|^L}j%^>of;u+%y*UCvWCW985m>1+5~jeQ`sP06z)_
z9@JVbSuA`pyKgF|HqZYWIzHrzA%oF$9(xBz5;gqHa09eYC?FEDMu#s9(!dS)=zxD5
zj#<g+TbaIFp^^~PoSsv0x3|;OKIu^eNy8*;A{Yj1PI`Q$Hu4hiT{AOc^ts<J>6hXz
z{JBSC#1lIdB!Hcx)X`MSyzoI<;W@oHL7<6WO)K+mK1qBGw_Me<{6ebgFr9La^s~#2
z&R+er4j^l0f4gQA0N-5^B}5gN^LI_ebDR(iko;=0BB(r;Q@i|R#5divVdc7R!cn?r
zIwkC-AZgPiEU*0Q6QS?^CJkO>1b)+`!K&34s|u?MGZ``+;|j)JvB!|JdOVTorp;}c
z>nZQfiuTc}byGiHEA}64X$z~}nUQ85;8OKH9gu8&dk*9{n&@DqTj>D#N}L<bLvf#4
z`^w=Q+A)*tWRJjfQ^p+|BC=Z^wfV@H3T?6A3B$QE+#lnNs#x#p)ODJ6fUV1C`yBP?
zxUqi*bJ{bug*godb6Rg>+07F$`4m4+q0||F%)uHPX4jNo)>#+~2BuhPGvH-FxOxt_
zf#)~QHukuI{|U7TmI9wYUf(dG-D$Ll-yOfaV)owILnw9B9aSNHa#c0>Y&xzfHdANF
z>bbzGDgqNUdX0T~l_=Qx`SG&C^8xeheTFt?VC(mnyTuF%gk1-8#tb%3=DNbitOQ<S
z%KM^IDTiKW>Rj?%?U2F0S_4XK@c9|IjpgvUXZEYaw7*-H-oN{}v_zhR1?DGH;Ewew
z@h_$)Rq8WxXj$Ok;Zjn&Q?U{_SgW%y?rTfZ!RnYFX1=;WdNU`Kl+}z-28C-&N1w^A
z%0X%M4{5P2hE0ZyvyWxLlj&)6xq-=G3(ct=a?dyXa8NyJLZ2WA7-Mf4Uc!Z?&R9<>
zmq$M4*zf4K?v_;b<8v#?<r9{q?PR8a@6><YKpt#=f=!3Qiu8Ty?z*XW1s5W<hdgbS
z31z{AzXhep3P<>}vk&OR`Ciu&vQdUv+@EZEYm>9Mc?30B6>Zl|kLAe{e`~V0^0QC6
z=@qO*?4kJdduE200Akmd*5duoy}M-9Qc8`$gwcy`c1tj&Bw=on?Ej)FdE|74!}>XC
zsYe10siq5;MniV_V|w4%<0G?_gW(Oe`r5U!QhG;lg)5npx{i1Vge^<^?<=NvAHTHs
z$E?p7?eT9BI;Yo*#x(D>N>Dlj1JqOkF=uU2deDu<lQB{Nz=NT1w}keo`Y%+v9K|hQ
zFqVS5B6*JBG(93L7gb$?n}{W087Bl|#Ia(k;k(~OD7+ITJPAI6kQztq5C1v8aWY1y
z=){DMFo%#H;eF7~q$s%y%5jB_$r5oyOFK=~g58cP8;YwAuJwk6k&m@)#X_bwvUAt{
z7y0{39PqrFvQW##dr{Xf_G_5v&$rovZ_$8}c0B@TZ8t1&|2U?$&9z%{G(#5xsb5Z=
o;egbHp$)Dipw+L)@O3b`>b$YL^B4~<K)^rR8U}yoU$uMqe|O(KC;$Ke

delta 13271
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

diff --git a/UnitTests/TestCore/IParameterizedTest.h b/UnitTests/TestCore/IParameterizedTest.h
new file mode 100644
index 00000000000..39332d36139
--- /dev/null
+++ b/UnitTests/TestCore/IParameterizedTest.h
@@ -0,0 +1,61 @@
+#ifndef IPARAMETERIZEDTEST_H
+#define IPARAMETERIZEDTEST_H
+
+#include "IParameterized.h"
+
+
+class IParameterizedTest : public ::testing::Test
+{
+protected:
+    IParameterizedTest() {}
+    virtual ~IParameterizedTest(){}
+
+    IParameterized m_initial_object;
+
+    class ParameterizedObject : public IParameterized
+    {
+    public:
+        ParameterizedObject() : m_real_par1(0), m_real_par2(0) {
+            setName("Parameterized"); init_parameters(); }
+        double m_real_par1;
+        double m_real_par2;
+    protected:
+        virtual void init_parameters()
+        {
+            getParameterPool()->registerParameter("par1",&m_real_par1);
+            getParameterPool()->registerParameter("par2",&m_real_par2);
+        }
+    };
+    ParameterizedObject m_parameterized;
+};
+
+
+TEST_F(IParameterizedTest, InitialState)
+{
+    EXPECT_FALSE( m_initial_object.areParametersChanged() );
+    m_initial_object.setParametersAreChanged();
+    EXPECT_TRUE( m_initial_object.areParametersChanged() ); // after this call object has to change state
+    EXPECT_FALSE( m_initial_object.areParametersChanged() );
+    EXPECT_EQ( size_t(0), m_initial_object.getParameterPool()->size() );
+    IParameterized obj2(m_initial_object);
+    EXPECT_FALSE( obj2.areParametersChanged() );
+}
+
+
+TEST_F(IParameterizedTest, DealingWithPool)
+{
+    EXPECT_EQ( size_t(2), m_parameterized.getParameterPool()->size());
+    IParameterizedTest::ParameterizedObject obj2 = m_parameterized;
+    EXPECT_EQ( size_t(0), obj2.getParameterPool()->size());
+    ParameterPool *pool = m_parameterized.createParameterTree();
+    //POOL_2('/Parameterized/par1':0 '/Parameterized/par2':0 )
+    //std::cout << *pool << std::endl;
+    pool->getParameter("/Parameterized/par1").setValue(1.0);
+    pool->getParameter("/Parameterized/par2").setValue(2.0);
+    EXPECT_EQ( double(1.0), m_parameterized.m_real_par1);
+    EXPECT_EQ( double(2.0), m_parameterized.m_real_par2);
+}
+
+
+
+#endif // IPARAMETERIZEDTEST_H
diff --git a/UnitTests/TestCore/ParameterPoolTest.h b/UnitTests/TestCore/ParameterPoolTest.h
new file mode 100644
index 00000000000..d06ea262dc4
--- /dev/null
+++ b/UnitTests/TestCore/ParameterPoolTest.h
@@ -0,0 +1,90 @@
+#ifndef PARAMETERPOOLTEST_H
+#define PARAMETERPOOLTEST_H
+
+
+#include "ParameterPool.h"
+
+
+class ParameterPoolTest : public ::testing::Test
+{
+protected:
+    ParameterPoolTest();
+    virtual ~ParameterPoolTest(){}
+
+    ParameterPool m_empty_pool;
+    ParameterPool m_pool;
+    double m_real_par1;
+    double m_real_par2;
+    double m_real_par3;
+    double m_real_par4;
+};
+
+
+ParameterPoolTest::ParameterPoolTest() : m_real_par1(1.0), m_real_par2(2.0), m_real_par3(3.0), m_real_par4(4.0)
+{
+    m_pool.registerParameter("a_par1",&m_real_par1);
+    m_pool.registerParameter("a_par2",&m_real_par2);
+    ParameterPool::parameter_t poolpar(&m_real_par3);
+    m_pool.addParameter("b_par3",poolpar);
+}
+
+
+TEST_F(ParameterPoolTest, InitialState)
+{
+    EXPECT_EQ( size_t(0), m_empty_pool.size() );
+    ASSERT_THROW( m_empty_pool.getParameter("NotExistingName"), LogicErrorException );
+}
+
+
+TEST_F(ParameterPoolTest, registerParameters)
+{
+    EXPECT_EQ( size_t(3), m_pool.size() );
+    EXPECT_EQ( double(1.0), m_pool.getParameter("a_par1").getValue());
+    EXPECT_EQ( double(2.0), m_pool.getParameter("a_par2").getValue());
+    EXPECT_EQ( double(3.0), m_pool.getParameter("b_par3").getValue());
+    m_real_par3 = 3.1;
+    EXPECT_EQ( double(3.1), m_pool.getParameter("b_par3").getValue());
+    std::vector<ParameterPool::parameter_t > pars = m_pool.getMatchedParameters("*par*");
+    EXPECT_EQ( size_t(3), pars.size() );
+    pars = m_pool.getMatchedParameters("a_par*");
+    EXPECT_EQ( size_t(2), pars.size() );
+
+    ASSERT_THROW( m_pool.setParameterValue("NonExistingName", 3.2), LogicErrorException );
+    m_pool.setParameterValue("b_par3", 3.2);
+    EXPECT_EQ( double(3.2), m_pool.getParameter("b_par3").getValue());
+
+    EXPECT_EQ( int(3), m_pool.setMatchedParametersValue("*par*",5.0));
+    EXPECT_EQ( double(5.0), m_real_par1);
+    EXPECT_EQ( double(5.0), m_real_par2);
+    EXPECT_EQ( double(5.0), m_real_par3);
+}
+
+
+TEST_F(ParameterPoolTest, PoolClone)
+{
+    ParameterPool *pool = m_pool.clone();
+    EXPECT_EQ( size_t(3), pool->size() );
+}
+
+
+TEST_F(ParameterPoolTest, CopyToExternalPool)
+{
+    m_real_par1 = 1.0;
+    m_real_par2 = 2.0;
+    m_real_par3 = 3.0;
+    m_real_par4 = 4.0;
+    ParameterPool external_pool;
+    external_pool.registerParameter("par4",&m_real_par4);
+    m_pool.copyToExternalPool("Another/",&external_pool);
+    std::cout << external_pool << std::endl;
+    EXPECT_EQ( double(1.0), external_pool.getParameter("Another/a_par1").getValue());
+    EXPECT_EQ( double(2.0), external_pool.getParameter("Another/a_par2").getValue());
+    EXPECT_EQ( double(3.0), external_pool.getParameter("Another/b_par3").getValue());
+    EXPECT_EQ( double(4.0), external_pool.getParameter("par4").getValue());
+
+//    EXPECT_EQ( size_t(0), m_pool.size() );
+}
+
+
+
+#endif // PARAMETERPOOLTEST_H
diff --git a/UnitTests/TestCore/RealParameterWrapperTest.h b/UnitTests/TestCore/RealParameterWrapperTest.h
new file mode 100644
index 00000000000..3d640e09d51
--- /dev/null
+++ b/UnitTests/TestCore/RealParameterWrapperTest.h
@@ -0,0 +1,94 @@
+#ifndef REALPARAMETERWRAPPERTEST_H
+#define REALPARAMETERWRAPPERTEST_H
+
+#include "RealParameterWrapper.h"
+#include "Exceptions.h"
+#include <boost/bind.hpp>
+
+class RealParameterWrapperTest : public ::testing::Test
+{
+protected:
+    RealParameterWrapperTest();
+    virtual ~RealParameterWrapperTest();
+
+    double m_real_parameter;
+    RealParameterWrapper m_null_par;
+
+    class ObjectToNotify
+    {
+    public:
+        void set_status_true() { m_status = true; }
+        void set_status_false() { m_status = false; }
+        bool m_status;
+    };
+};
+
+
+RealParameterWrapperTest::RealParameterWrapperTest() : m_real_parameter(3.141), m_null_par(0)
+{
+
+}
+
+RealParameterWrapperTest::~RealParameterWrapperTest()
+{
+
+}
+
+TEST_F(RealParameterWrapperTest, InitialState)
+{
+    EXPECT_TRUE( m_null_par.isNull() );
+    ASSERT_THROW( m_null_par.getValue(), NullPointerException );
+    ASSERT_THROW( m_null_par.setValue(1.0), NullPointerException );
+
+    RealParameterWrapper par(m_null_par);
+    EXPECT_TRUE( par.isNull() );
+    ASSERT_THROW( par.getValue(), NullPointerException );
+    ASSERT_THROW( par.setValue(1.0), NullPointerException );
+}
+
+TEST_F(RealParameterWrapperTest, ParameterAccess)
+{
+    RealParameterWrapper par11(&m_real_parameter);
+    EXPECT_EQ( m_real_parameter, par11.getValue() );
+
+    RealParameterWrapper par12 = par11;
+    EXPECT_EQ( m_real_parameter, par12.getValue() );
+
+    m_real_parameter = 2.0;
+    EXPECT_EQ(  double(2.0), par11.getValue() );
+    EXPECT_EQ(  double(2.0), par12.getValue() );
+    std::vector<RealParameterWrapper > parameters;
+    parameters.push_back(par11);
+    parameters.push_back(par12);
+
+    parameters[0].setValue(3.0);
+    EXPECT_EQ(  double(3.0), m_real_parameter );
+    EXPECT_EQ(  double(3.0), parameters[1].getValue() );
+}
+
+TEST_F(RealParameterWrapperTest, ParameterSignals)
+{
+    // check that parameter emmits signals to two objects
+    m_real_parameter = 1.0;
+    RealParameterWrapper par(&m_real_parameter);
+    ObjectToNotify obj1, obj2;
+    RealParameterWrapper::signal_t::slot_type fun1 = boost::bind(&ObjectToNotify::set_status_true, &obj1);
+    RealParameterWrapper::signal_t::slot_type fun2 = boost::bind(&ObjectToNotify::set_status_true, &obj2);
+    par.connect(fun1);
+    par.connect(fun2);
+    obj1.m_status = false;
+    obj2.m_status = false;
+    par.setValue(2.0); // at this point status of object has to be changed by signal emmited from the parameter
+    EXPECT_TRUE( obj1.m_status );
+    EXPECT_TRUE( obj2.m_status );
+    // par2 should not emmit signals since they are not copied
+    RealParameterWrapper par2 = par;
+    obj1.m_status = false;
+    obj2.m_status = false;
+    par2.setValue(3.0);
+    EXPECT_FALSE( obj1.m_status );
+    EXPECT_FALSE( obj2.m_status );
+}
+
+
+#endif // REALPARAMETERWRAPPERTEST_H
diff --git a/UnitTests/TestCore/TestCore.pro b/UnitTests/TestCore/TestCore.pro
index a12bd08d33a..6212bf78474 100644
--- a/UnitTests/TestCore/TestCore.pro
+++ b/UnitTests/TestCore/TestCore.pro
@@ -20,7 +20,10 @@ HEADERS += \
     OutputDataTest.h \
     OutputDataIteratorTest.h \
     GISASExperimentTest.h \
-    ChiSquaredModuleTest.h
+    ChiSquaredModuleTest.h \
+    RealParameterWrapperTest.h \
+    IParameterizedTest.h \
+    ParameterPoolTest.h
 
 OBJECTS_DIR = obj
 
@@ -28,14 +31,14 @@ INCLUDEPATH += ../../Core/Algorithms/inc ../../Core/FormFactors/inc ../../Core/G
 DEPENDPATH += ../../Core/Algorithms/inc ../../Core/FormFactors/inc ../../Core/Geometry/inc ../../Core/Samples/inc ../../Core/Tools/inc ../../ThirdParty/gtest/gtest-1.6.0/include
 DEPENDPATH += $$PWD/.
 
-LIBS = -L/opt/local/lib -lfftw3
+#LIBS = -L/opt/local/lib -lfftw3
 
-CONFIG(JCNS) {
+#CONFIG(JCNS) {
   #LIBS -= -lfftw3
   #LIBS += -Bstatic -lfftw3 -Bdynamic # request for static (with fPIC option)
   # "-lfftw3f" - with fPIC option, "-lfftw3" - without fPIC option
-  LIBS = -L/usr/users/jcns/pospelov/software/lib -lfftw3
-}
+  #LIBS = -L/usr/users/jcns/pospelov/software/lib -lfftw3
+#}
 
 ###############################################################################
 # generating package dependency flags
diff --git a/UnitTests/TestCore/main.cpp b/UnitTests/TestCore/main.cpp
index d587feee84f..cdc363828ed 100644
--- a/UnitTests/TestCore/main.cpp
+++ b/UnitTests/TestCore/main.cpp
@@ -5,10 +5,13 @@
 #include "DetectorTest.h"
 #include "ExperimentTest.h"
 #include "GISASExperimentTest.h"
+#include "IParameterizedTest.h"
 #include "MaskTest.h"
 #include "AxisDoubleTest.h"
 #include "OutputDataTest.h"
 #include "OutputDataIteratorTest.h"
+#include "ParameterPoolTest.h"
+#include "RealParameterWrapperTest.h"
 
 int main(int argc, char** argv)
 {
diff --git a/shared.pri b/shared.pri
index 305feea9f38..95523d087d9 100644
--- a/shared.pri
+++ b/shared.pri
@@ -59,7 +59,7 @@ for(dir, BOOST_LIB_LOCATIONS): isEmpty(BOOST_LIB) {
 isEmpty(BOOST_LIB): message("Can't find" $${BOOST_LIBFILES} "in" $${BOOST_LIB_LOCATIONS})
 INCLUDEPATH *=  $${BOOST_INCLUDE}
 LIBS *= -L$${BOOST_LIB}
-LIBS += -lboost_program_options -lboost_iostreams -lboost_system -lboost_filesystem -lboost_regex -lboost_thread
+LIBS += -lboost_program_options -lboost_iostreams -lboost_system -lboost_signals -lboost_filesystem -lboost_regex -lboost_thread
 # checking special case when system doesn't have libboost_thread library but have libbost_thread-mt
 NumberOfSuchFiles=$$system(ls $${BOOST_LIB}/libboost_thread-mt* 2> /dev/null | wc -l)
 !isEqual(NumberOfSuchFiles, 0) {
@@ -92,7 +92,7 @@ isEqual(env_jcns_variable, "yes") {
 CONFIG(JCNS) {
   message("Special config for JCNS")
   INCLUDEPATH += /usr/users/jcns/pospelov/software/include
-  LIBS = -L/usr/users/jcns/pospelov/software/lib -L/usr/local/lib -L/usr/lib64 -lgsl -lgslcblas -lfftw3 -lboost_program_options -lboost_iostreams -lboost_system -lboost_filesystem -lboost_regex -lboost_thread
+  LIBS = -L/usr/users/jcns/pospelov/software/lib -L/usr/local/lib -L/usr/lib64 -lgsl -lgslcblas -lfftw3 -lboost_program_options -lboost_iostreams -lboost_system -lboost_signals  -lboost_filesystem -lboost_regex -lboost_thread
 }
 
 
-- 
GitLab