From 4fc6e57a31b6904c1339cbb436fd7152e5d3bbef Mon Sep 17 00:00:00 2001
From: pospelov <pospelov@fz-juelich.de>
Date: Tue, 27 Nov 2012 13:21:00 +0100
Subject: [PATCH] Refactoring in FitSuite and Co to link OutputDataNormilizer
 parameters with fit parameters

---
 App/inc/TestFittingModule2.h                  |  3 +-
 App/src/FitSuiteHelper.cpp                    | 40 +++++-----------
 App/src/IsGISAXSTools.cpp                     | 36 ++++++++------
 App/src/TestFittingModule1.cpp                |  4 +-
 App/src/TestFittingModule2.cpp                | 20 --------
 App/src/TestFittingModule3.cpp                |  7 +++
 Core/Algorithms/inc/ChiSquaredFrequency.h     |  4 +-
 Core/Algorithms/inc/ChiSquaredModule.h        |  4 +-
 Core/Algorithms/inc/IChiSquaredModule.h       | 41 +++++++++-------
 Core/Algorithms/inc/IOutputDataNormalizer.h   |  8 ++--
 Core/Algorithms/src/Beam.cpp                  |  7 ++-
 Core/Algorithms/src/ChiSquaredFrequency.cpp   | 41 ++++++++++++----
 Core/Algorithms/src/ChiSquaredModule.cpp      | 26 +++++-----
 Core/Algorithms/src/Detector.cpp              |  7 +--
 Core/Algorithms/src/Experiment.cpp            |  5 +-
 Core/Algorithms/src/IChiSquaredModule.cpp     | 47 ++++++++-----------
 Core/Algorithms/src/IOutputDataNormalizer.cpp | 23 +++++++++
 Core/Tools/inc/FitObject.h                    | 17 +++++--
 Core/Tools/inc/FitSuite.h                     |  2 +-
 Core/Tools/inc/FitSuiteObjects.h              | 16 +++++--
 Core/Tools/inc/FitSuiteParameters.h           |  7 +--
 Core/Tools/src/FitObject.cpp                  | 39 +++++++++++++++
 Core/Tools/src/FitSuite.cpp                   | 10 ++--
 Core/Tools/src/FitSuiteObjects.cpp            | 44 +++++++++++++----
 Core/Tools/src/FitSuiteParameters.cpp         | 11 +----
 25 files changed, 288 insertions(+), 181 deletions(-)

diff --git a/App/inc/TestFittingModule2.h b/App/inc/TestFittingModule2.h
index d01861fffe9..343c4d2757e 100644
--- a/App/inc/TestFittingModule2.h
+++ b/App/inc/TestFittingModule2.h
@@ -27,7 +27,8 @@ class FitSuite;
 
 //- -------------------------------------------------------------------
 //! @class TestFittingModule2
-//! @brief Testing of fitting module with 5 parameters sample
+//! @brief Testing of fitting module with 5 parameters sample using different
+//! fit strategies
 //- -------------------------------------------------------------------
 class TestFittingModule2 : public IFunctionalTest
 {
diff --git a/App/src/FitSuiteHelper.cpp b/App/src/FitSuiteHelper.cpp
index 13e2a8f6a36..e88ce2234f4 100644
--- a/App/src/FitSuiteHelper.cpp
+++ b/App/src/FitSuiteHelper.cpp
@@ -112,8 +112,9 @@ void FitSuiteObserverDraw::update(IObservable *subject)
         enum hist_keys {kReal, kSimul, kDiff, kChi2};
         std::vector<OutputData<double > *> data2draw;
         data2draw.push_back( fitObject->getRealData()->clone() );
-        data2draw.push_back( fitObject->getSimulatedData()->clone() );
-        data2draw.push_back( getRelativeDifferenceMap(fitObject->getSimulatedData(), fitObject->getRealData() ) );
+//        data2draw.push_back( fitObject->getSimulationData()->clone() );
+        data2draw.push_back( fitObject->getChiSquaredModule()->getSimulationData()->clone() ); //chi module have normalized simulation
+        data2draw.push_back( getRelativeDifferenceMap(fitObject->getChiSquaredModule()->getSimulationData(), fitObject->getRealData() ) );
         data2draw.push_back( fitObject->getChiSquaredModule()->createChi2DifferenceMap() );
 
         // drawing
@@ -175,32 +176,15 @@ void FitSuiteObserverDraw::update(IObservable *subject)
 /* ************************************************************************* */
 TH1 *FitSuiteObserverDraw::get_histogram(const OutputData<double> &data, const std::string &hname)
 {
-    TH2D *hist2 = dynamic_cast<TH2D *>(IsGISAXSTools::getOutputDataTH123D( data, hname.c_str()));
-    if(!hist2) throw LogicErrorException("FitSuiteObserverDraw::get_histogram() -> Error! Can't cast histogram");
-
-    if( data.getAxis("alpha_f")->getSize() > 1 && data.getAxis("phi_f")->getSize() > 1) {
-        return hist2;
-    }
-
-    TH1D *hist1(0);
-    std::ostringstream ostr;
-    std::string hname_proj = hname;
-    if( data.getAxis("alpha_f")->getSize() == 1) {
-        hname_proj += std::string(" proj_on_phi");
-        hist1 = hist2->ProjectionX(hname_proj.c_str());
-        ostr << hname_proj << ", alpha_f=" << dynamic_cast<const NamedVector<double >*>(data.getAxis("alpha_f"))->getMin();
-    }else if( data.getAxis("phi_f")->getSize() == 1 ) {
-        hname_proj += std::string(" proj_on_alpha");
-        hist1 = hist2->ProjectionY(hname_proj.c_str());
-        ostr << hname_proj << ", phi_f=" << dynamic_cast<const NamedVector<double >*>(data.getAxis("phi_f"))->getMin();
-    } else {
-        throw LogicErrorException("FitSuiteObserverDraw::get_histogram() -> Error! Unexpected place");
+    if( data.getAxis("alpha_f") && data.getAxis("phi_f") ) {
+        if( data.getAxis("alpha_f")->getSize() != 1 && data.getAxis("phi_f")->getSize() != 1)
+        {
+            return IsGISAXSTools::getOutputDataTH123D( data, hname);
+        } else if(data.getAxis("alpha_f")->getSize() == 1 || data.getAxis("phi_f")->getSize() == 1){
+            return IsGISAXSTools::getOutputDataScanHist(data, hname);
+        }
     }
-    if( !hist1 ) throw LogicErrorException("FitSuiteObserverDraw::get_histogram() -> Error! Can't profile 2D histogram into 1D");
-    hist1->SetTitle(ostr.str().c_str());
-    delete hist2;
-
-    return hist1;
+    throw LogicErrorException("FitSuiteObserverDraw::get_histogram()-> Error! Can't handle axis");
 }
 
 
@@ -264,7 +248,7 @@ void FitSuiteObserverWriteTree::update(IObservable *subject)
 
     // filling data object with data from FitSuite
     const OutputData<double > *real_data = fitSuite->getFitObjects()->getRealData();
-    const OutputData<double > *simu_data = fitSuite->getFitObjects()->getSimulatedData();
+    const OutputData<double > *simu_data = fitSuite->getFitObjects()->getSimulationData();
     IsGISAXSTools::exportOutputDataInVectors2D(*real_data, event->real_data, event->axis0, event->axis1);
     IsGISAXSTools::exportOutputDataInVectors2D(*simu_data, event->fit_data, event->axis0, event->axis1);
     event->chi2 = fitSuite->getFitObjects()->getChiSquaredModule()->getValue();
diff --git a/App/src/IsGISAXSTools.cpp b/App/src/IsGISAXSTools.cpp
index b855568fdd6..ba69fd9e98c 100644
--- a/App/src/IsGISAXSTools.cpp
+++ b/App/src/IsGISAXSTools.cpp
@@ -150,7 +150,7 @@ TH1 *IsGISAXSTools::getOutputDataTH123D(const OutputData<double>& output, const
     std::vector<AxisStructure > haxises;
     haxises.resize(output.getNdimensions());
 
-    // we assume variable bin size and prepare [nbins+1] array of low edges of each bin
+    // we assume variable bin size and prepare [nbins+1] array of left edges of each bin plus right edge of the last bin
     for(size_t i_axis=0; i_axis<output.getNdimensions(); ++i_axis) {
         const NamedVector<double> *axis = reinterpret_cast<const NamedVector<double>*>(output.getAxes()[i_axis]);
         if( !axis ) throw("IsGISAXSTools::getOutputDataTH123D() -> Error! Can't cast axis");
@@ -186,19 +186,25 @@ TH1 *IsGISAXSTools::getOutputDataTH123D(const OutputData<double>& output, const
 //    }
 
     // creation of 1D, 2D or 3D histogram with variable bin size
-    TH1 *hist;
+    TH1 *hist(0);
+    TH1D *hist1(0);
+    TH2D *hist2(0);
+    TH3D *hist3(0);
     if(output.getNdimensions() == 1) {
-        hist = new TH1D(histo_name.c_str(), histo_name.c_str(), haxises[0].nbins, &haxises[0].xbins[0]);
-        hist->GetXaxis()->SetTitle( haxises[0].name.c_str() );
+        hist1 = new TH1D(histo_name.c_str(), histo_name.c_str(), haxises[0].nbins, &haxises[0].xbins[0]);
+        hist1->GetXaxis()->SetTitle( haxises[0].name.c_str() );
+        hist = hist1;
     } else if(output.getNdimensions() == 2) {
-        hist = new TH2D(histo_name.c_str(), histo_name.c_str(), haxises[0].nbins, &haxises[0].xbins[0], haxises[1].nbins, &haxises[1].xbins[0]);
-        hist->GetXaxis()->SetTitle( haxises[0].name.c_str() );
-        hist->GetYaxis()->SetTitle( haxises[1].name.c_str() );
+        hist2 = new TH2D(histo_name.c_str(), histo_name.c_str(), haxises[0].nbins, &haxises[0].xbins[0], haxises[1].nbins, &haxises[1].xbins[0]);
+        hist2->GetXaxis()->SetTitle( haxises[0].name.c_str() );
+        hist2->GetYaxis()->SetTitle( haxises[1].name.c_str() );
+        hist = hist2;
     } else if(output.getNdimensions() == 3) {
-        hist = new TH3D(histo_name.c_str(), histo_name.c_str(), haxises[0].nbins, &haxises[0].xbins[0], haxises[1].nbins, &haxises[1].xbins[0], haxises[1].nbins, &haxises[1].xbins[0]);
-        hist->GetXaxis()->SetTitle( haxises[0].name.c_str() );
-        hist->GetYaxis()->SetTitle( haxises[1].name.c_str() );
-        hist->GetZaxis()->SetTitle( haxises[2].name.c_str() );
+        hist3 = new TH3D(histo_name.c_str(), histo_name.c_str(), haxises[0].nbins, &haxises[0].xbins[0], haxises[1].nbins, &haxises[1].xbins[0], haxises[1].nbins, &haxises[1].xbins[0]);
+        hist3->GetXaxis()->SetTitle( haxises[0].name.c_str() );
+        hist3->GetYaxis()->SetTitle( haxises[1].name.c_str() );
+        hist3->GetZaxis()->SetTitle( haxises[2].name.c_str() );
+        hist = hist3;
     } else {
         throw LogicErrorException("IsGISAXSTools::getOutputDataTH123D() -> Error! Wrong number of dimensions.");
     }
@@ -211,9 +217,9 @@ TH1 *IsGISAXSTools::getOutputDataTH123D(const OutputData<double>& output, const
             xyz.push_back(output.getValueOfAxis<double>( haxises[i_axis].name, it.getIndex() ) );
         }
         double value = *it++;
-        if(output.getNdimensions() == 1) dynamic_cast<TH1D *>(hist)->Fill(xyz[0], value);
-        if(output.getNdimensions() == 2) dynamic_cast<TH2D *>(hist)->Fill(xyz[0], xyz[1], value);
-        if(output.getNdimensions() == 3) dynamic_cast<TH3D *>(hist)->Fill(xyz[0], xyz[1], xyz[2], value);
+        if(hist1) hist1->Fill(xyz[0], value);
+        if(hist2) hist2->Fill(xyz[0], xyz[1], value);
+        if(hist3) hist3->Fill(xyz[0], xyz[1], xyz[2], value);
     }
     hist->SetContour(50);
     hist->SetStats(0);
@@ -531,7 +537,7 @@ TLine *IsGISAXSTools::getOutputDataScanLine(const OutputData<double> &data)
 TH1D *IsGISAXSTools::getOutputDataScanHist(const OutputData<double> &data, const std::string &hname)
 {
     if(data.getNdimensions() != 2) throw LogicErrorException("IsGISAXSTools::getOutputDataScanHist() -> Error! Number of dimensions should be 2");
-    // on of axis should have dimension 1
+    // one of axis should have dimension 1
     if( (data.getAxis("alpha_f") && data.getAxis("alpha_f")->getSize() != 1) && (data.getAxis("phi_f") && data.getAxis("phi_f")->getSize() != 1))
     {
         std::cout << "IsGISAXSTools::getOutputDataScanHist() -> Info. Can't create 1D histogram from these axes" << std::endl;
diff --git a/App/src/TestFittingModule1.cpp b/App/src/TestFittingModule1.cpp
index 535ec09ceeb..73afcb3fee2 100644
--- a/App/src/TestFittingModule1.cpp
+++ b/App/src/TestFittingModule1.cpp
@@ -17,6 +17,7 @@
 #include "ResolutionFunction2DSimple.h"
 #include "AttLimits.h"
 #include "ISquaredFunction.h"
+#include "IOutputDataNormalizer.h"
 
 #include "IObserver.h"
 #include "FitSuite.h"
@@ -56,8 +57,6 @@ void TestFittingModule1::execute()
 
     // initializing data
     initializeSample2();
-    ParameterPool *pool = mp_sample->createParameterTree();
-    std::cout << *pool << std::endl;
 
     initializeExperiment();
     generateRealData(0.1);
@@ -72,6 +71,7 @@ void TestFittingModule1::execute()
     // setting up fitSuite
     ChiSquaredModule chiModule;
     chiModule.setChiSquaredFunction( SquaredFunctionWithSystematicError() );
+    chiModule.setOutputDataNormalizer( OutputDataNormalizerScaleAndShift(1e10,0) );
     m_fitSuite->addExperimentAndRealData(*mp_experiment, *mp_real_data, chiModule);
 
     m_fitSuite->setMinimizer( new ROOTMinimizer("Minuit2", "Migrad") );
diff --git a/App/src/TestFittingModule2.cpp b/App/src/TestFittingModule2.cpp
index a0d78bedfb1..5935983d658 100644
--- a/App/src/TestFittingModule2.cpp
+++ b/App/src/TestFittingModule2.cpp
@@ -59,26 +59,6 @@ TestFittingModule2::~TestFittingModule2()
 
 void TestFittingModule2::execute()
 {
-//    OutputData<double > *data1 = new OutputData<double>;
-//    data1->addAxis(std::string("a1"), 0., 10., 100);
-//    data1->addAxis(std::string("a2"), 0., 10., 100);
-
-//    OutputData<double > *data2 = new OutputData<double>;
-//    data2->addAxis(std::string("a1"), 0., 10., 100);
-//    data2->addAxis(std::string("a2"), 0., 10., 99.9999999999999999999);
-
-//    if( data1->hasSameDimensions(*data2) ) {
-//        std::cout << "Same dimensions " << std::endl;
-//    } else {
-//        std::cout << "Not Same dimensions " << std::endl;
-
-//    }
-//    if( data1->hasSameShape(*data2) ) {
-//        std::cout << "Same shape " << std::endl;
-//    } else {
-//        std::cout << "Not Same shape " << std::endl;
-//    }
-
     // new sample builder
     mp_sample_builder = new TestSampleBuilder();
     ParameterPool *pool = mp_sample_builder->createParameterTree();
diff --git a/App/src/TestFittingModule3.cpp b/App/src/TestFittingModule3.cpp
index 5ed1c7fdfe3..279d19c3dcd 100644
--- a/App/src/TestFittingModule3.cpp
+++ b/App/src/TestFittingModule3.cpp
@@ -67,6 +67,13 @@ void TestFittingModule3::execute()
 //    m_fitSuite->addFitParameter("*FormFactorPrism3/half_side", 5.0001*Units::nanometer, 1*Units::nanometer, AttLimits::lowerLimited(0.01) );
 //    m_fitSuite->addFitParameter("*FormFactorPrism3/height", 5.0001*Units::nanometer, 1*Units::nanometer, AttLimits::lowerLimited(0.01) );
 
+
+//    // setting up fitSuite
+//    ChiSquaredModule chiModule;
+//    chiModule.setChiSquaredFunction( SquaredFunctionWithSystematicError() );
+//    m_fitSuite->addExperimentAndRealData(*mp_experiment, *mp_real_data, chiModule);
+
+
     // putting scans
     for(DataScan_t::iterator it=m_data_scans.begin(); it!= m_data_scans.end(); ++it) {
         m_fitSuite->addExperimentAndRealData(*m_experiment, *(*it));
diff --git a/Core/Algorithms/inc/ChiSquaredFrequency.h b/Core/Algorithms/inc/ChiSquaredFrequency.h
index 9b06e07d689..c13a9d9a9da 100644
--- a/Core/Algorithms/inc/ChiSquaredFrequency.h
+++ b/Core/Algorithms/inc/ChiSquaredFrequency.h
@@ -19,10 +19,10 @@
 class ChiSquaredFrequency : public IChiSquaredModule
 {
 public:
-    ChiSquaredFrequency(const OutputData<double> &real_data);
+    ChiSquaredFrequency();
     virtual ~ChiSquaredFrequency();
 
-    virtual double calculateChiSquared(const OutputData<double> *p_simulation_data=0);
+    virtual double calculateChiSquared();
 
     void setCutoff(double cutoff) {
         if (cutoff>=0.0 && cutoff<=1.0) m_cutoff = cutoff;
diff --git a/Core/Algorithms/inc/ChiSquaredModule.h b/Core/Algorithms/inc/ChiSquaredModule.h
index bde6fe13e10..d7b1c1234c6 100644
--- a/Core/Algorithms/inc/ChiSquaredModule.h
+++ b/Core/Algorithms/inc/ChiSquaredModule.h
@@ -21,16 +21,16 @@ class ChiSquaredModule : public IChiSquaredModule
 public:
     ChiSquaredModule(){}
     ChiSquaredModule(const ChiSquaredModule &other);
-    ChiSquaredModule(const OutputData<double> &real_data);
     virtual ~ChiSquaredModule();
 
     virtual ChiSquaredModule *clone() const;
 
     //! calculate chi squared volume over experimental and simulated data
-    virtual double calculateChiSquared(const OutputData<double> *p_simulation_data=0);
+    virtual double calculateChiSquared();
 
     //! return output data which contains chi^2 values
     virtual OutputData<double > *createChi2DifferenceMap() const;
+
 private:
     // disabling assignment operator
     ChiSquaredModule &operator=(const ChiSquaredModule &);
diff --git a/Core/Algorithms/inc/IChiSquaredModule.h b/Core/Algorithms/inc/IChiSquaredModule.h
index 5b2269fedb7..088ee069178 100644
--- a/Core/Algorithms/inc/IChiSquaredModule.h
+++ b/Core/Algorithms/inc/IChiSquaredModule.h
@@ -14,6 +14,7 @@
 //! @author Scientific Computing Group at FRM II
 //! @date   Nov 5, 2012
 
+#include "IParameterized.h"
 #include "OutputData.h"
 #include "IFittingDataSelector.h"
 #include "ISquaredFunction.h"
@@ -25,36 +26,42 @@ class IChiSquaredModule
 {
 public:
     IChiSquaredModule();
-    IChiSquaredModule(const OutputData<double> &real_data);
     IChiSquaredModule(const IChiSquaredModule &other);
     virtual ~IChiSquaredModule();
 
+    //! clone method
     virtual IChiSquaredModule *clone() const = 0;
 
-    void setRealData(const OutputData<double> &real_data);
-
-    void setSimulationData(const OutputData<double> &simulation_data);
-
-    virtual void setFittingDataSelector(const IFittingDataSelector &selector);
-
-    void setChiSquaredFunction(const ISquaredFunction &squared_function);
+    //! return output data which contains chi^2 values
+    virtual OutputData<double > *createChi2DifferenceMap() const=0;
 
-    virtual double calculateChiSquared(const OutputData<double> *p_simulation_data=0) =0;
+    //! calculate chi dquared value
+    virtual double calculateChiSquared() = 0;
 
-    //! return real data
+    //! get real data
     const OutputData<double> *getRealData() const { return mp_real_data; }
-
-    //! return simulation data
+    //! get simulated data
     const OutputData<double> *getSimulationData() const { return mp_simulation_data; }
+    //! set real and simulated data pair
+    void setRealAndSimulatedData(const OutputData<double > &real_data, const OutputData<double >&simulation_data);
 
-    //! return squared function
+    //! get squared function
     const ISquaredFunction *getSquaredFunction() const { return mp_squared_function; }
+    //! set squared function
+    void setChiSquaredFunction(const ISquaredFunction &squared_function);
 
-    //! return chi2 value (should be called after calculateChiSquared)
-    virtual double getValue() const { return m_chi2_value; }
+    //! get fitting data selector
+    virtual const IFittingDataSelector *getFittingDataSelector() const {return mp_data_selector; }
+    //! set fitting data selector
+    virtual void setFittingDataSelector(const IFittingDataSelector &selector);
 
-    //! return output data which contains chi^2 values
-    virtual OutputData<double > *createChi2DifferenceMap() const=0;
+    //! get data normalizer
+    virtual const IOutputDataNormalizer *getOutputDataNormalizer() const {return mp_data_normalizer; }
+    //! set data normalizer
+    virtual void setOutputDataNormalizer(const IOutputDataNormalizer &data_normalizer);
+
+    //! return last calculated chi squared value
+    virtual double getValue() const { return m_chi2_value; }
 
 protected:
     // disabling assignment operator
diff --git a/Core/Algorithms/inc/IOutputDataNormalizer.h b/Core/Algorithms/inc/IOutputDataNormalizer.h
index c823754390b..0221b67879e 100644
--- a/Core/Algorithms/inc/IOutputDataNormalizer.h
+++ b/Core/Algorithms/inc/IOutputDataNormalizer.h
@@ -28,10 +28,6 @@ public:
 
     virtual OutputData<double> *createNormalizedData(const OutputData<double > &data) const=0;
 
-protected:
-    //! initialize pool parameters, i.e. register some of class members for later access via parameter pool
-    virtual void init_parameters(){}
-
 };
 
 
@@ -40,11 +36,13 @@ class OutputDataNormalizerScaleAndShift : public IOutputDataNormalizer
 {
 public:
     OutputDataNormalizerScaleAndShift();
+    OutputDataNormalizerScaleAndShift(double scale, double shift);
+    OutputDataNormalizerScaleAndShift(const OutputDataNormalizerScaleAndShift &other);
     virtual ~OutputDataNormalizerScaleAndShift() {}
 
     virtual OutputData<double> *createNormalizedData(const OutputData<double > &data) const;
 
-    virtual OutputDataNormalizerScaleAndShift *clone() const { return new OutputDataNormalizerScaleAndShift(*this); }
+    virtual OutputDataNormalizerScaleAndShift *clone() const;
 
 protected:
     //! initialize pool parameters, i.e. register some of class members for later access via parameter pool
diff --git a/Core/Algorithms/src/Beam.cpp b/Core/Algorithms/src/Beam.cpp
index f55d8560583..fc8d8c3de43 100644
--- a/Core/Algorithms/src/Beam.cpp
+++ b/Core/Algorithms/src/Beam.cpp
@@ -20,8 +20,11 @@ Beam::Beam(const Beam &other) : IParameterized()
 
 Beam &Beam::operator=(const Beam &other)
 {
-    Beam tmp(other);
-    tmp.swapContent(*this);
+    if( this != &other)
+    {
+        Beam tmp(other);
+        tmp.swapContent(*this);
+    }
     return *this;
 }
 
diff --git a/Core/Algorithms/src/ChiSquaredFrequency.cpp b/Core/Algorithms/src/ChiSquaredFrequency.cpp
index c8e96667893..5f0b0284564 100644
--- a/Core/Algorithms/src/ChiSquaredFrequency.cpp
+++ b/Core/Algorithms/src/ChiSquaredFrequency.cpp
@@ -1,26 +1,47 @@
 #include "ChiSquaredFrequency.h"
 #include "OutputDataFunctions.h"
 
-ChiSquaredFrequency::ChiSquaredFrequency(const OutputData<double>& real_data)
-: IChiSquaredModule(real_data)
-, mp_real_ft(0)
+ChiSquaredFrequency::ChiSquaredFrequency()
+    : mp_real_ft(0)
 , mp_simulation_ft(0)
 , m_cutoff(1.0)
 {
+
 }
 
+
 ChiSquaredFrequency::~ChiSquaredFrequency()
 {
     delete mp_real_ft;
     delete mp_simulation_ft;
 }
 
-double ChiSquaredFrequency::calculateChiSquared(
-        const OutputData<double>* p_simulation_data)
+//double ChiSquaredFrequency::calculateChiSquared(
+//        const OutputData<double>* p_simulation_data)
+//{
+//    if (p_simulation_data!=0) {
+//        setSimulationData(*p_simulation_data);
+//    }
+
+//    double result = 0.0;
+//    initWeights();
+//    size_t data_size = mp_weights->getAllocatedSize();
+//    OutputData<double> *p_difference = createChi2DifferenceMap();
+//    OutputData<double>::const_iterator it_weights = mp_weights->begin();
+//    OutputData<double>::const_iterator it_diff = p_difference->begin();
+//    while(it_diff != p_difference->end()) {
+//        result += (*it_diff++)*(*it_weights++);
+//    }
+//    delete p_difference;
+//    m_chi2_value = result/data_size;
+//    return m_chi2_value;
+//}
+
+
+double ChiSquaredFrequency::calculateChiSquared()
 {
-    if (p_simulation_data!=0) {
-        setSimulationData(*p_simulation_data);
-    }
+    if( !mp_real_data ) throw NullPointerException("ChiSquaredFrequency::calculateChiSquared() -> Error! No real data has been set");
+    if( !mp_simulation_data ) throw NullPointerException("ChiSquaredFrequency::calculateChiSquared() -> Error! No simulated data has been set");
 
     double result = 0.0;
     initWeights();
@@ -33,7 +54,9 @@ double ChiSquaredFrequency::calculateChiSquared(
     }
     delete p_difference;
     m_chi2_value = result/data_size;
-    return m_chi2_value;}
+    return m_chi2_value;
+}
+
 
 OutputData<double>* ChiSquaredFrequency::createChi2DifferenceMap() const
 {
diff --git a/Core/Algorithms/src/ChiSquaredModule.cpp b/Core/Algorithms/src/ChiSquaredModule.cpp
index d64db56e0e8..ea91a703c64 100644
--- a/Core/Algorithms/src/ChiSquaredModule.cpp
+++ b/Core/Algorithms/src/ChiSquaredModule.cpp
@@ -6,33 +6,32 @@ ChiSquaredModule::ChiSquaredModule(const ChiSquaredModule &other) : IChiSquaredM
 }
 
 
-ChiSquaredModule::ChiSquaredModule(const OutputData<double>& real_data)
-    : IChiSquaredModule(real_data)
-{
-}
-
 ChiSquaredModule::~ChiSquaredModule()
 {
 }
 
+
 ChiSquaredModule *ChiSquaredModule::clone() const
 {
     return new ChiSquaredModule(*this);
 }
 
 
-double ChiSquaredModule::calculateChiSquared(
-        const OutputData<double>* p_simulation_data)
+double ChiSquaredModule::calculateChiSquared()
 {
-    if (p_simulation_data!=0) {
-        setSimulationData(*p_simulation_data);
-    }
-    if (mp_simulation_data==0) {
-        throw LogicErrorException("No simulation data present for calculating chi squared.");
-    }
+    if( !mp_real_data ) throw NullPointerException("ChiSquaredModule::calculateChiSquared() -> Error! No real data has been set");
+    if( !mp_simulation_data ) throw NullPointerException("ChiSquaredModule::calculateChiSquared() -> Error! No simulated data has been set");
+
     double result = 0.0;
     size_t data_size = mp_real_data->getAllocatedSize();
     initWeights();
+
+    if(mp_data_normalizer) {
+        OutputData<double > *normalized_simulation = mp_data_normalizer->createNormalizedData(*mp_simulation_data);
+        delete mp_simulation_data;
+        mp_simulation_data = normalized_simulation;
+    }
+
     OutputData<double> *p_difference = createChi2DifferenceMap();
     OutputData<double>::const_iterator it_weights = mp_weights->begin();
     OutputData<double>::const_iterator it_diff = p_difference->begin();
@@ -44,6 +43,7 @@ double ChiSquaredModule::calculateChiSquared(
     return m_chi2_value;
 }
 
+
 OutputData<double>* ChiSquaredModule::createChi2DifferenceMap() const
 {
     OutputData<double > *p_difference = mp_simulation_data->clone();
diff --git a/Core/Algorithms/src/Detector.cpp b/Core/Algorithms/src/Detector.cpp
index 854b1d46cf8..1d1f3bdbcec 100644
--- a/Core/Algorithms/src/Detector.cpp
+++ b/Core/Algorithms/src/Detector.cpp
@@ -30,12 +30,13 @@ Detector::~Detector()
 
 Detector &Detector::operator=(const Detector &other)
 {
-    Detector tmp(other);
-    tmp.swapContent(*this);
+    if( this != &other) {
+        Detector tmp(other);
+        tmp.swapContent(*this);
+    }
     return *this;
 }
 
-
 void Detector::swapContent(Detector &other)
 {
     std::swap(this->m_axes, other.m_axes);
diff --git a/Core/Algorithms/src/Experiment.cpp b/Core/Algorithms/src/Experiment.cpp
index 59b746b824b..ba868594daf 100644
--- a/Core/Algorithms/src/Experiment.cpp
+++ b/Core/Algorithms/src/Experiment.cpp
@@ -142,8 +142,9 @@ std::string Experiment::addParametersToExternalPool(std::string path,
     }
     // add parameters of the sample (only in the case without sample builder)
     else if (mp_sample) {
-        std::string sample_path = new_path + mp_sample->getName();
-        mp_sample->addParametersToExternalPool(sample_path, external_pool, -1);
+//        std::string sample_path = new_path + mp_sample->getName();
+//        mp_sample->addParametersToExternalPool(sample_path, external_pool, -1);
+        mp_sample->addParametersToExternalPool(new_path, external_pool, -1);
     }
 
     return new_path;
diff --git a/Core/Algorithms/src/IChiSquaredModule.cpp b/Core/Algorithms/src/IChiSquaredModule.cpp
index 3e1ef1a183f..75b213a0b4d 100644
--- a/Core/Algorithms/src/IChiSquaredModule.cpp
+++ b/Core/Algorithms/src/IChiSquaredModule.cpp
@@ -15,21 +15,6 @@ IChiSquaredModule::IChiSquaredModule()
 }
 
 
-IChiSquaredModule::IChiSquaredModule(const OutputData<double>& real_data)
-    : mp_real_data(0)
-    , mp_simulation_data(0)
-    , mp_weights(0)
-    , mp_squared_function(0)
-    , mp_data_selector(0)
-    , mp_data_normalizer(0)
-    , m_chi2_value(0)
-{
-    mp_real_data = real_data.clone();
-    mp_squared_function = new DefaultSquaredFunction();
-    mp_data_selector = new DefaultAllDataSelector();
-}
-
-
 IChiSquaredModule::IChiSquaredModule(const IChiSquaredModule &other)
     : mp_real_data(0)
     , mp_simulation_data(0)
@@ -39,8 +24,8 @@ IChiSquaredModule::IChiSquaredModule(const IChiSquaredModule &other)
     , mp_data_normalizer(0)
     , m_chi2_value(0)
 {
-    if(other.mp_real_data) mp_real_data = other.mp_real_data->clone();
-    if(other.mp_simulation_data) mp_simulation_data = other.mp_simulation_data->clone();
+    if(other.mp_real_data) mp_real_data = other.mp_real_data;
+    if(other.mp_simulation_data) mp_simulation_data = other.mp_simulation_data;
     if(other.mp_weights) mp_weights = other.mp_weights->clone();
     if(other.mp_squared_function) mp_squared_function = other.mp_squared_function->clone();
     if(other.mp_data_selector) mp_data_selector = other.mp_data_selector->clone();
@@ -58,35 +43,41 @@ IChiSquaredModule::~IChiSquaredModule()
     delete mp_data_normalizer;
 }
 
-void IChiSquaredModule::setRealData(const OutputData<double>& real_data)
-{
-    delete mp_real_data;
-    mp_real_data = real_data.clone();
-}
 
-void IChiSquaredModule::setSimulationData(
-        const OutputData<double>& simulation_data)
+void IChiSquaredModule::setRealAndSimulatedData(const OutputData<double > &real_data, const OutputData<double >&simulation_data)
 {
+    delete mp_real_data;
+    mp_real_data=real_data.clone();
     delete mp_simulation_data;
     mp_simulation_data = simulation_data.clone();
 }
 
-void IChiSquaredModule::setFittingDataSelector(
-        const IFittingDataSelector& selector)
+
+void IChiSquaredModule::setFittingDataSelector(const IFittingDataSelector& selector)
 {
     delete mp_data_selector;
     mp_data_selector = selector.clone();
 }
 
-void IChiSquaredModule::setChiSquaredFunction(
-        const ISquaredFunction& squared_function)
+
+void IChiSquaredModule::setChiSquaredFunction(const ISquaredFunction& squared_function)
 {
     delete mp_squared_function;
     mp_squared_function = squared_function.clone();
 }
 
+void IChiSquaredModule::setOutputDataNormalizer(const IOutputDataNormalizer &data_normalizer)
+{
+    delete mp_data_normalizer;
+    mp_data_normalizer = data_normalizer.clone();
+}
+
+
 void IChiSquaredModule::initWeights()
 {
     delete mp_weights;
+    if( !mp_real_data ) throw NullPointerException("IChiSquaredModule::initWeights() -> Error! No real data has been set");
+    if( !mp_simulation_data ) throw NullPointerException("IChiSquaredModule::initWeights() -> Error! No simulated data has been set");
     mp_weights = mp_data_selector->createWeightMap(*mp_real_data, *mp_simulation_data);
 }
+
diff --git a/Core/Algorithms/src/IOutputDataNormalizer.cpp b/Core/Algorithms/src/IOutputDataNormalizer.cpp
index 8619ed3dd31..52fc5ca5bf6 100644
--- a/Core/Algorithms/src/IOutputDataNormalizer.cpp
+++ b/Core/Algorithms/src/IOutputDataNormalizer.cpp
@@ -11,6 +11,27 @@ OutputDataNormalizerScaleAndShift::OutputDataNormalizerScaleAndShift()
     init_parameters();
 }
 
+OutputDataNormalizerScaleAndShift::OutputDataNormalizerScaleAndShift(double scale, double shift)
+    : m_scale(scale)
+    , m_shift(shift)
+{
+    setName("Normalizer");
+    init_parameters();
+}
+
+OutputDataNormalizerScaleAndShift::OutputDataNormalizerScaleAndShift(const OutputDataNormalizerScaleAndShift &other) : IOutputDataNormalizer(other)
+{
+    m_scale = other.m_scale;
+    m_shift = other.m_shift;
+    init_parameters();
+}
+
+
+OutputDataNormalizerScaleAndShift *OutputDataNormalizerScaleAndShift::clone() const
+{
+    return new OutputDataNormalizerScaleAndShift(*this);
+}
+
 
 void  OutputDataNormalizerScaleAndShift::init_parameters()
 {
@@ -26,6 +47,7 @@ OutputData<double> *OutputDataNormalizerScaleAndShift::createNormalizedData(cons
 
     OutputData<double >::const_iterator cit = std::max_element(data.begin(), data.end());
     double max_intensity = (*cit);
+    std::cout << "QQQ before " << data.totalSum() << std::endl;
     if(max_intensity) {
         OutputData<double >::iterator it = normalized_data->begin();
         while(it!=normalized_data->end()) {
@@ -33,6 +55,7 @@ OutputData<double> *OutputDataNormalizerScaleAndShift::createNormalizedData(cons
             (*it) = m_scale*(value/max_intensity) + m_shift;
             ++it;
         }
+        std::cout << "QQQ after " << normalized_data->totalSum() << std::endl;
     } else {
         std::cout << "OutputDataNormalizerScaleAndShift::createNormalizedData() -> Warning! Zero maximum intensity" << std::endl;
     }
diff --git a/Core/Tools/inc/FitObject.h b/Core/Tools/inc/FitObject.h
index 80548e50ff0..054082cd91d 100644
--- a/Core/Tools/inc/FitObject.h
+++ b/Core/Tools/inc/FitObject.h
@@ -14,17 +14,18 @@
 //! @author Scientific Computing Group at FRM II
 //! @date   21.11.2012
 
-
+#include "IParameterized.h"
 #include "Experiment.h"
 #include "OutputData.h"
 #include "ChiSquaredModule.h"
 
+
 //- -------------------------------------------------------------------
 //! @class FitObject
 //! @brief Class to hold single experiment description, real data and chi2 module
 //! Used by FitSuite
 //- -------------------------------------------------------------------
-class FitObject
+class FitObject : public IParameterized
 {
 public:
     FitObject(const Experiment &experiment, const OutputData<double > &real_data, const IChiSquaredModule &chi2_module=ChiSquaredModule());
@@ -42,7 +43,7 @@ public:
     void setRealData(const OutputData<double > &real_data);
 
     //! get simulated data
-    const OutputData<double > *getSimulatedData() const { return m_experiment->getOutputData(); }
+    const OutputData<double > *getSimulationData() const { return m_experiment->getOutputData(); }
 
     //! get chi2 module
     const IChiSquaredModule *getChiSquaredModule() const {return m_chi2_module; }
@@ -50,6 +51,16 @@ public:
     //! set chi2 module
     void setChiSquaredModule(const IChiSquaredModule &chi2_module) { delete m_chi2_module; m_chi2_module = chi2_module.clone(); }
 
+    //! calculate chi squared value
+    double calculateChiSquared();
+
+    //! 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;
+
+protected:
+    //! initialize pool parameters, i.e. register some of class members for later access via parameter pool
+    virtual void init_parameters();
+
 private:
     FitObject(const FitObject &);
     FitObject &operator=(const FitObject &);
diff --git a/Core/Tools/inc/FitSuite.h b/Core/Tools/inc/FitSuite.h
index 878770d191d..49833193e84 100644
--- a/Core/Tools/inc/FitSuite.h
+++ b/Core/Tools/inc/FitSuite.h
@@ -95,7 +95,7 @@ private:
     //! check if all prerequisites to run fit fit are filled
     bool check_prerequisites();
 
-    FitSuiteObjects m_fit_objects; //! kit which contains pairs of <experiment,real_data> to fit
+    FitSuiteObjects m_fit_objects; //! kit which contains sets of <experiment,real_data,chi_module> to fit
     FitSuiteParameters m_fit_parameters; //! collection of fit parameters
     fitstrategies_t m_fit_strategies; //! collection of strategies which are executed before every minimization round
     IMinimizer  *m_minimizer; //! minimization engine
diff --git a/Core/Tools/inc/FitSuiteObjects.h b/Core/Tools/inc/FitSuiteObjects.h
index 68633005a09..47687b7a6f4 100644
--- a/Core/Tools/inc/FitSuiteObjects.h
+++ b/Core/Tools/inc/FitSuiteObjects.h
@@ -15,11 +15,11 @@
 //! @date   15.11.2012
 
 
+#include "IParameterized.h"
 #include "Experiment.h"
 #include "OutputData.h"
 #include "FitObject.h"
 
-
 #include <vector>
 
 
@@ -27,12 +27,12 @@
 //! @class FitSuiteObjects
 //! @brief Class containing vector FitObject's (experiment and real data) to fit
 //- -------------------------------------------------------------------
-class FitSuiteObjects
+class FitSuiteObjects : public IParameterized
 {
 public:
     typedef std::vector<FitObject *> FitObjects_t;
 
-    FitSuiteObjects(){}
+    FitSuiteObjects();
     virtual ~FitSuiteObjects(){}
 
     //! clear all data
@@ -63,11 +63,19 @@ public:
     IChiSquaredModule *getChiSquaredModule(int i_item = 0) { return m_fit_objects[check_index(i_item)]->getChiSquaredModule(); }
 
     //! get simulated data
-    const OutputData<double> * getSimulatedData(int i_item = 0) const { return m_fit_objects[check_index(i_item)]->getSimulatedData(); }
+    const OutputData<double> * getSimulationData(int i_item = 0) const { return m_fit_objects[check_index(i_item)]->getSimulationData(); }
 
     //! get fit object
     const FitObject *getObject(int i_item = 0) const { return m_fit_objects[check_index(i_item)]; }
     FitObject *getObject(int i_item = 0) { return m_fit_objects[check_index(i_item)]; }
+
+    //! 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;
+
+protected:
+    //! initialize pool parameters, i.e. register some of class members for later access via parameter pool
+    virtual void init_parameters();
+
 private:
     //! disabled copy constructor and assignment operator
     FitSuiteObjects &operator=(const FitSuiteObjects &);
diff --git a/Core/Tools/inc/FitSuiteParameters.h b/Core/Tools/inc/FitSuiteParameters.h
index 68bb87874bb..860fbc5fb93 100644
--- a/Core/Tools/inc/FitSuiteParameters.h
+++ b/Core/Tools/inc/FitSuiteParameters.h
@@ -18,7 +18,8 @@
 #include "FitParameterLinked.h"
 #include <vector>
 
-class Experiment;
+//class Experiment;
+class ParameterPool;
 
 //- -------------------------------------------------------------------
 //! @class FitSuiteParameters
@@ -68,8 +69,8 @@ public:
     const FitParameter *operator[](std::string name) const { return getParameter(name); }
     FitParameter *operator[](std::string name) { return getParameter(name); }
 
-    //! link fit parameters to parameters defined in experiment
-    void link_to_experiment(const Experiment *experiment);
+    //! linking fit parameters with pool parameters
+    void link_to_pool(const ParameterPool *pool);
 
 private:
     //! disabled copy constructor and assignment operator
diff --git a/Core/Tools/src/FitObject.cpp b/Core/Tools/src/FitObject.cpp
index 140dbdc99fe..ee0335df065 100644
--- a/Core/Tools/src/FitObject.cpp
+++ b/Core/Tools/src/FitObject.cpp
@@ -10,6 +10,7 @@ FitObject::FitObject(const Experiment &experiment, const OutputData<double > &re
     , m_real_data(real_data.clone())
     , m_chi2_module(chi2_module.clone())
 {
+    setName("FitObject");
     if( !m_real_data->hasSameShape(*m_experiment->getOutputData()) ) {
         std::cout << "FitObject::FitObject() -> Info. Real data and output data in the experiment have different shape. Adjusting experiment's detector." << std::endl;
     } else {
@@ -40,3 +41,41 @@ void FitObject::setRealData(const OutputData<double > &real_data)
     }
 }
 
+
+/* ************************************************************************* */
+// calculate chi squared value
+/* ************************************************************************* */
+double FitObject::calculateChiSquared()
+{
+    m_chi2_module->setRealAndSimulatedData(*m_real_data, *m_experiment->getOutputData());
+    return m_chi2_module->calculateChiSquared();
+}
+
+
+/* ************************************************************************* */
+// add parameters from local pool to external pool
+/* ************************************************************************* */
+std::string FitObject::addParametersToExternalPool(std::string path,
+        ParameterPool* external_pool, int copy_number) const
+{
+    // add own parameters
+    std::string  new_path = IParameterized::addParametersToExternalPool(path, external_pool, copy_number);
+
+    // add parameters of the experiment
+    if(m_experiment) m_experiment->addParametersToExternalPool(new_path, external_pool, -1);
+
+    if(m_chi2_module) {
+        const IOutputDataNormalizer *data_normalizer = m_chi2_module->getOutputDataNormalizer();
+        if(data_normalizer) {
+            data_normalizer->addParametersToExternalPool(new_path, external_pool, -1);
+        }
+    }
+
+    return new_path;
+}
+
+
+void FitObject::init_parameters()
+{
+
+}
diff --git a/Core/Tools/src/FitSuite.cpp b/Core/Tools/src/FitSuite.cpp
index 5c197e2710b..19a77cba18e 100644
--- a/Core/Tools/src/FitSuite.cpp
+++ b/Core/Tools/src/FitSuite.cpp
@@ -68,10 +68,12 @@ void FitSuite::addFitStrategy(IFitSuiteStrategy *strategy)
 /* ************************************************************************* */
 void FitSuite::link_fit_parameters()
 {
-    // loop over all experiments defined
-    for(size_t i_exp = 0; i_exp<m_fit_objects.size(); ++i_exp) {
-        m_fit_parameters.link_to_experiment(m_fit_objects.getExperiment(i_exp));
-    }
+    ParameterPool *pool = m_fit_objects.createParameterTree();
+    m_fit_parameters.link_to_pool(pool);
+    std::cout << "XXXXXX FitSuite::link_fit_parameters() -> " << std::endl;
+    std::cout << *pool << std::endl;
+    std::cout << "----------------" << std::endl;
+    delete pool;
 }
 
 
diff --git a/Core/Tools/src/FitSuiteObjects.cpp b/Core/Tools/src/FitSuiteObjects.cpp
index ca14c32fea5..99916ff302d 100644
--- a/Core/Tools/src/FitSuiteObjects.cpp
+++ b/Core/Tools/src/FitSuiteObjects.cpp
@@ -2,6 +2,13 @@
 
 
 
+FitSuiteObjects::FitSuiteObjects()
+{
+    setName("FitSuiteObjects");
+    init_parameters();
+}
+
+
 /* ************************************************************************* */
 // clear all data
 /* ************************************************************************* */
@@ -39,16 +46,37 @@ void FitSuiteObjects::runSimulation()
 double FitSuiteObjects::getChiSquaredValue()
 {
     double chi_squared(0);
-    for(size_t i_exp = 0; i_exp<m_fit_objects.size(); ++i_exp) {
-        const OutputData<double> *simulated_data = getSimulatedData(i_exp);
-        const OutputData<double> *real_data = getRealData(i_exp);
+    for(FitObjects_t::iterator it = m_fit_objects.begin(); it!= m_fit_objects.end(); ++it) {
+        chi_squared += (*it)->calculateChiSquared();
+    }
+    return chi_squared;
+}
 
-        IChiSquaredModule *chi2_module = getChiSquaredModule(i_exp);
 
-        chi2_module->setRealData(*real_data);
-        double value = chi2_module->calculateChiSquared(simulated_data);
-        chi_squared += value;
+/* ************************************************************************* */
+// add parameters from local pool to external pool
+/* ************************************************************************* */
+std::string FitSuiteObjects::addParametersToExternalPool(std::string path,
+        ParameterPool* external_pool, int copy_number) const
+{
+    (void)copy_number;
+    // add own parameters
+    // so far it is top object in our chain, and its without parameters, lets exclude its name from path
+    //std::string  new_path = IParameterized::addParametersToExternalPool(path, external_pool, copy_number);
+    std::string new_path = path;
+
+    int ncopy(0);
+    if(m_fit_objects.size()==1) ncopy=-1; // if we have only one object, lets get rid from copy number
+    for(FitObjects_t::const_iterator it = m_fit_objects.begin(); it!= m_fit_objects.end(); ++it, ++ncopy) {
+        (*it)->addParametersToExternalPool(new_path, external_pool, ncopy);
     }
-    return chi_squared;
+
+    return new_path;
+}
+
+
+void FitSuiteObjects::init_parameters()
+{
+
 }
 
diff --git a/Core/Tools/src/FitSuiteParameters.cpp b/Core/Tools/src/FitSuiteParameters.cpp
index b708f11d3e4..404e3afd031 100644
--- a/Core/Tools/src/FitSuiteParameters.cpp
+++ b/Core/Tools/src/FitSuiteParameters.cpp
@@ -81,15 +81,10 @@ std::vector<double > FitSuiteParameters::getValues() const
 
 
 /* ************************************************************************* */
-// link fit parameters to parameters defined in experiment
+// linking fit parameters with pool parameters
 /* ************************************************************************* */
-void FitSuiteParameters::link_to_experiment(const Experiment *experiment)
+void FitSuiteParameters::link_to_pool(const ParameterPool *pool)
 {
-    // accessing parameter pool of the sample
-    ParameterPool *pool = experiment->createParameterTree();
-    std::cout << " XXX " << std::endl;
-    std::cout << *pool << std::endl;
-
     // linking fit parameter with whose pool parameters which match name of fit parameter
     // going through all fit parameters defined
     for(parameters_t::iterator it = m_parameters.begin(); it!= m_parameters.end(); ++it) {
@@ -97,8 +92,6 @@ void FitSuiteParameters::link_to_experiment(const Experiment *experiment)
         if( !par ) throw LogicErrorException("FitSuiteParameters::link_to_experiment() -> Error! Can't cast to FitParameterLinked.");
         par->addMatchedParametersFromPool(pool);
     }
-
-    delete pool;
 }
 
 
-- 
GitLab