diff --git a/App/inc/ROOTMinimizer.h b/App/inc/ROOTMinimizer.h
index 5878c288e7f41d08e9a132bb41a04923a2652935..79d1b5de1501433146b9db3c62fcd15884340aa9 100644
--- a/App/inc/ROOTMinimizer.h
+++ b/App/inc/ROOTMinimizer.h
@@ -71,6 +71,7 @@ public:
 private:
     ROOT::Math::Minimizer *m_root_minimizer;
     ROOT::Math::Functor *m_fcn;
+    //ROOT::Math::GradFunctor *m_fcn;
 };
 
 #endif // ROOTMINIMIZER_H
diff --git a/App/inc/TestIsGISAXS12.h b/App/inc/TestIsGISAXS12.h
index 9faf27bb1f60099d3b4a1058430947eadb302fed..dbb1d2a62f1f0eea2c3dbf34c7f346964806afb3 100644
--- a/App/inc/TestIsGISAXS12.h
+++ b/App/inc/TestIsGISAXS12.h
@@ -35,7 +35,10 @@ public:
     virtual void execute();
 
 private:
-    typedef std::vector<OutputData<double > *> DataScan_t;
+//    typedef std::vector<OutputData<double > *> DataScan_t;
+//    enum isgisaxs_scans {kFixedAlphaf, kFixedPhif };
+
+
 
     //! builds sample for fitter testing
     class TestSampleBuilder : public ISampleBuilder
@@ -48,17 +51,49 @@ private:
     protected:
         //! initialize pool parameters, i.e. register some of class members for later access via parameter pool
         virtual void init_parameters();
-        double m_particle_probability;
+        double m_particle_probability1;
         double m_particle_radius1;
-        double m_particle_radius2;
         double m_dispersion_radius1;
-        double m_dispersion_radius2;
         double m_height_aspect_ratio1;
+        double m_particle_probability2;
+        double m_particle_radius2;
+        double m_dispersion_radius2;
         double m_height_aspect_ratio2;
         double m_interf_distance;
         double m_interf_width;
     };
 
+    //! represent collection of OutputData object's
+    class DataSet {
+    public:
+        typedef std::vector<OutputData<double > *> dataset_t;
+        typedef std::vector<OutputData<double > *>::iterator iterator;
+        typedef std::vector<OutputData<double > *>::const_iterator const_iterator;
+        DataSet(){}
+        ~DataSet() {  clear(); }
+        void clear() {for(size_t i=0; i<m_data.size(); ++i) delete m_data[i]; m_data.clear(); }
+        DataSet(const DataSet &other)
+        {
+            for(size_t i=0; i<other.m_data.size(); ++i) m_data.push_back(other.m_data[i]->clone());
+        }
+        DataSet &operator=(const DataSet &other)
+        {
+            if( this != &other ) {
+                clear();
+                for(size_t i=0; i<other.m_data.size(); ++i) m_data.push_back(other.m_data[i]->clone());
+            }
+            return *this;
+        }
+        void push_back(OutputData<double > *data) { m_data.push_back(data); }
+        dataset_t::iterator begin() { return m_data.begin(); }
+        dataset_t::iterator end() { return m_data.end(); }
+        size_t size() { return m_data.size(); }
+        const OutputData<double> *operator[](int index) const { return m_data[index]; }
+        OutputData<double> *operator[](int index) { return m_data[index]; }
+
+        dataset_t m_data;
+    };
+
     //! represent single line stored in isgisaxs *.dat file with data to fit
     class IsgiData {
     public:
@@ -76,9 +111,6 @@ private:
     //! run standard isgisaxs comparison for the given sample
     void run_isgisaxs_comparison();
 
-    //! run test fit
-    void run_test_fit();
-
     //! run isgisaxs ex-12 style fit
     void run_isgisaxs_fit();
 
@@ -86,17 +118,29 @@ private:
     void plot_isgisaxs_data();
 
     //!  read special isgisaxs *.dat file with data to fit
-    void read_isgisaxs_datfile(const std::string &filename);
+    void read_isgisaxs_datfile(const std::string &filename, DataSet &dataset);
+
+    //!  read special isgisaxs *.out file with isgisaxs results
+    void read_isgisaxs_outfile(const std::string &filename, DataSet &dataset, bool read_fit_results = false);
 
     //! convert isgisaxs 1d scan to output data 2d object
     OutputData<double> *convert_isgi_scan(std::vector<IsgiData > &isgi_data);
 
+    //! run test minimizer to check whole chain
+    void run_test_minimizer();
+
+    //! run chi module test on isgisaxs data/result pair to check module numericaly
+    void run_test_chimodule();
+
+    void print_axes(DataSet &data);
+
+
     std::string m_data_path;
     GISASExperiment *m_experiment;
     ISampleBuilder *m_sample_builder;
     FitSuite *m_fitSuite;
 
-    DataScan_t m_isgi_scans; //! vector of OutputData's representing isgisaxs scans
+//    DataScan_t m_isgi_scans; //! vector of OutputData's representing isgisaxs scans
     double m_isgi_fixed_alphaf;
     double m_isgi_fixed_phif;
 };
diff --git a/App/src/IsGISAXSTools.cpp b/App/src/IsGISAXSTools.cpp
index 3c81357910dc039cdd75a51fce1618326d780e34..cdb08ccc697f26f5766f343be8f9dc59e5df4172 100644
--- a/App/src/IsGISAXSTools.cpp
+++ b/App/src/IsGISAXSTools.cpp
@@ -299,7 +299,7 @@ void IsGISAXSTools::drawOutputDataDifference1D(const OutputData<double> &left, c
         h1_spect.Fill( x );
     }
 
-    gPad->SetLogy();
+//    gPad->SetLogy();
     gPad->SetRightMargin(0.115);
     gPad->SetLeftMargin(0.115);
     h1_spect.SetStats(1);
diff --git a/App/src/ROOTMinimizer.cpp b/App/src/ROOTMinimizer.cpp
index 829726f6304cdaa2be186fd4ba4650a99c62ff31..8f57e6468091d8ffe1bea488492fd72b3b000e98 100644
--- a/App/src/ROOTMinimizer.cpp
+++ b/App/src/ROOTMinimizer.cpp
@@ -61,6 +61,7 @@ void ROOTMinimizer::minimize()
 void ROOTMinimizer::setFunction(boost::function<double(const double *)> fcn, int ndim)
 {
     m_fcn = new ROOT::Math::Functor(fcn, ndim);
+//    m_fcn = new ROOT::Math::GradFunctor(fcn, ndim);
     m_root_minimizer->SetFunction(*m_fcn);
 }
 
diff --git a/App/src/TestDetectorResolution.cpp b/App/src/TestDetectorResolution.cpp
index f7f3a5382c7947288843ab77cb2648937fc0b604..a0e7129b66c2efdb8a875111434da103cabc8b95 100644
--- a/App/src/TestDetectorResolution.cpp
+++ b/App/src/TestDetectorResolution.cpp
@@ -13,13 +13,13 @@
 
 namespace
 {
-double testResolutionFunction(double u, double v)
-{
-    double sigma_u = 0.001;
-    double sigma_v = 0.001;
-    return MathFunctions::IntegratedGaussian(u, 0.0, sigma_u)
-            * MathFunctions::IntegratedGaussian(v, 0.0, sigma_v);
-}
+//double testResolutionFunction(double u, double v)
+//{
+//    double sigma_u = 0.001;
+//    double sigma_v = 0.001;
+//    return MathFunctions::IntegratedGaussian(u, 0.0, sigma_u)
+//            * MathFunctions::IntegratedGaussian(v, 0.0, sigma_v);
+//}
 }
 
 TestDetectorResolution::TestDetectorResolution()
diff --git a/App/src/TestFittingModule1.cpp b/App/src/TestFittingModule1.cpp
index b2ad0a236d2cab90b87af14c5259510ba090a6f6..12b05872d642e101a3fd17b7dd93c217539e9294 100644
--- a/App/src/TestFittingModule1.cpp
+++ b/App/src/TestFittingModule1.cpp
@@ -186,7 +186,7 @@ void TestFittingModule1::initializeRealData()
     if( !mp_experiment ) throw NullPointerException("TestFittingModule2::initializeRealData() -> Error! No experiment o sample defined ");
 
     mp_experiment->runSimulation();
-    mp_experiment->normalize();
+    //mp_experiment->normalize();
     delete mp_real_data;
     mp_real_data = IsGISAXSTools::createNoisyData(*mp_experiment->getOutputData());
 }
diff --git a/App/src/TestFittingModule2.cpp b/App/src/TestFittingModule2.cpp
index e761bb4341e0a846ac83e46c1d66a7c34344a3e1..627a9d88578c7d7b1e60176865b9780ba211dc81 100644
--- a/App/src/TestFittingModule2.cpp
+++ b/App/src/TestFittingModule2.cpp
@@ -101,21 +101,26 @@ void TestFittingModule2::fit_example_chimodule()
     //mp_experiment->setDetectorResolutionFunction(new ResolutionFunction2DSimple(0.0002, 0.0002));
     initializeRealData();
 
+//    m_fitSuite->addFitParameter("*SampleBuilder/m_cylinder_height",  12*Units::nanometer, 1*Units::nanometer, AttLimits::lowerLimited(0.01) );
+//    m_fitSuite->addFitParameter("*SampleBuilder/m_cylinder_radius",  2*Units::nanometer, 1*Units::nanometer, AttLimits::lowerLimited(0.01) );
+//    m_fitSuite->addFitParameter("*SampleBuilder/m_prism3_half_side", 12*Units::nanometer, 1*Units::nanometer, AttLimits::lowerLimited(0.01) );
+//    m_fitSuite->addFitParameter("*SampleBuilder/m_prism3_height",    2*Units::nanometer, 1*Units::nanometer, AttLimits::lowerLimited(0.01) );
 
-    m_fitSuite->addFitParameter("*SampleBuilder/m_cylinder_height",  12*Units::nanometer, 1*Units::nanometer, AttLimits::lowerLimited(0.01) );
-    m_fitSuite->addFitParameter("*SampleBuilder/m_cylinder_radius",  2*Units::nanometer, 1*Units::nanometer, AttLimits::lowerLimited(0.01) );
-    m_fitSuite->addFitParameter("*SampleBuilder/m_prism3_half_side", 12*Units::nanometer, 1*Units::nanometer, AttLimits::lowerLimited(0.01) );
-    m_fitSuite->addFitParameter("*SampleBuilder/m_prism3_height",    2*Units::nanometer, 1*Units::nanometer, AttLimits::lowerLimited(0.01) );
-//    m_fitSuite->addFitParameter("*Normalizer/scale", 1e10, 1e3, AttLimits::limited(1e8, 1e12));
+    m_fitSuite->addFitParameter("*SampleBuilder/m_cylinder_height",  12*Units::nanometer, 0.01*Units::nanometer, AttLimits::lowerLimited(0.01) );
+    m_fitSuite->addFitParameter("*SampleBuilder/m_cylinder_radius",  2*Units::nanometer, 0.01*Units::nanometer, AttLimits::lowerLimited(0.01) );
+    m_fitSuite->addFitParameter("*SampleBuilder/m_prism3_half_side", 12*Units::nanometer, 0.01*Units::nanometer, AttLimits::lowerLimited(0.01) );
+    m_fitSuite->addFitParameter("*SampleBuilder/m_prism3_height",    2*Units::nanometer, 0.01*Units::nanometer, AttLimits::lowerLimited(0.01) );
+//    m_fitSuite->addFitParameter("*Normalizer/scale", 1e10, 10., AttLimits::limited(1e9, 2*1e10));
 
     // setting up fitSuite
     ChiSquaredModule chiModule;
     //chiModule.setChiSquaredFunction( SquaredFunctionDefault() );
+//    chiModule.setChiSquaredFunction( SquaredFunctionWhichOnlyWorks() ); // it works only with resolution function, without it fit doesn't converge
     chiModule.setChiSquaredFunction( SquaredFunctionWithSystematicError() );
-    //chiModule.setChiSquaredFunction( SquaredFunctionWhichOnlyWorks() ); // it works only with resolution function, without it fit doesn't converge
-    //chiModule.setOutputDataNormalizer( OutputDataNormalizerScaleAndShift(1e10,0) );
-    chiModule.setIntensityFunction( IntensityFunctionLog() );
+//    chiModule.setOutputDataNormalizer( OutputDataNormalizerScaleAndShift(1e10,0) );
+    //chiModule.setIntensityFunction( IntensityFunctionLog() );
     m_fitSuite->addExperimentAndRealData(*mp_experiment, *mp_real_data, chiModule);
+    m_fitSuite->getFitObjects()->setExperimentNormalize(true);
 
     m_fitSuite->runFit();
 
diff --git a/App/src/TestIsGISAXS12.cpp b/App/src/TestIsGISAXS12.cpp
index 4d580c079e0f1adb0def705ab7ed52ac0ac50b7d..e74ff6746242b11c1da170f86b3f130cf086038b 100644
--- a/App/src/TestIsGISAXS12.cpp
+++ b/App/src/TestIsGISAXS12.cpp
@@ -24,6 +24,7 @@
 #include "ROOTMinimizer.h"
 #include "OutputDataFunctions.h"
 #include "NamedVector.h"
+#include "Types.h"
 
 #include <iostream>
 #include <fstream>
@@ -34,6 +35,8 @@
 #include "TH1D.h"
 #include "TH2D.h"
 #include "TLine.h"
+#include "TROOT.h"
+#include "TLegend.h"
 
 
 
@@ -57,9 +60,6 @@ TestIsGISAXS12::~TestIsGISAXS12()
     delete m_experiment;
     delete m_sample_builder;
     delete m_fitSuite;
-    for(DataScan_t::iterator it=m_isgi_scans.begin(); it!=m_isgi_scans.end(); ++it) {
-        delete (*it);
-    }
 }
 
 
@@ -73,13 +73,18 @@ void TestIsGISAXS12::execute()
     initialiseExperiment();
 
     // run our standard isgisaxs comparison for given sample
-    run_isgisaxs_comparison();
+//    run_isgisaxs_comparison();
+
+    // plot isgisaxs data
+//    plot_isgisaxs_data();
 
     // run test fit
-    //run_test_fit();
+//    run_test_minimizer();
 
     // run isgisaxs ex-12 style fit
-    run_isgisaxs_fit();
+   run_isgisaxs_fit();
+
+//    run_test_chimodule();
 
 }
 
@@ -95,7 +100,7 @@ void TestIsGISAXS12::run_isgisaxs_comparison()
     IsGISAXSTools::writeOutputDataToFile(*(m_experiment->getOutputData()), m_data_path+"this_fitconstraints.ima");
 
     // plotting results of comparison we/isgisaxs for the sample with default parameters
-    std::string isgi_file(m_data_path+"isgi_fitconstraints.ima");
+    std::string isgi_file(m_data_path+"isgi_fitconstraints_optimal.ima");
     std::string this_file(m_data_path+"this_fitconstraints.ima");
 
     // -------------
@@ -105,12 +110,12 @@ void TestIsGISAXS12::run_isgisaxs_comparison()
     OutputData<double> *our_data = IsGISAXSTools::readOutputDataFromFile(this_file);
 
     TCanvas *c1 = DrawHelper::instance().createAndRegisterCanvas("TestIsGISAXS12_c1", "ex-12: Mixture of cylindrical particles with different size distribution");
-
     c1->Divide(2,2);
 
-    IsGISAXSTools::setMinimum(1.);
+//    IsGISAXSTools::setMinimum(1.);
     // our calculations
     c1->cd(1); gPad->SetLogz();
+//    IsGISAXSTools::drawOutputDataInPad(*(m_experiment->getOutputData()), "CONT4 Z", "this");
     IsGISAXSTools::drawOutputDataInPad(*our_data, "CONT4 Z", "this");
 
     // isgisaxs data
@@ -132,82 +137,7 @@ void TestIsGISAXS12::run_isgisaxs_comparison()
     delete isgi_data;
     delete our_data;
 
-}
-
-
-/* ************************************************************************* */
-// run test fitting
-/* ************************************************************************* */
-void TestIsGISAXS12::run_test_fit()
-{
-    // creating "real" data
-    //m_experiment->setDetectorResolutionFunction(new ResolutionFunction2DSimple(0.0002, 0.0002));
-    m_experiment->setBeamIntensity(1e10);
-    m_experiment->runSimulation();
-    m_experiment->normalize();
-
-    OutputData<double > *real_data = IsGISAXSTools::createNoisyData( *m_experiment->getOutputData() );
-
-    // setting up 1d scans by making slices on real data
-    DataScan_t data_scans;
-    data_scans.push_back( OutputDataFunctions::selectRangeOnOneAxis(*real_data, "alpha_f", 0.012, 0.012) );
-    data_scans.push_back( OutputDataFunctions::selectRangeOnOneAxis(*real_data, "phi_f", 0.011, 0.011) );
-
-    // drawing data and scans
-    TCanvas *c1 = new TCanvas("c1","c1",1024, 768);
-    c1->Divide(2,2);
-    c1->cd(1); gPad->SetLogz();
-    TH2D *hist1 = dynamic_cast<TH2D *>(IsGISAXSTools::getOutputDataTH123D( *real_data, "real_data"));
-    hist1->Draw("COLZ");
-    for(DataScan_t::const_iterator it=data_scans.begin(); it!= data_scans.end(); ++it) {
-        TLine *line = IsGISAXSTools::getOutputDataScanLine(*(*it));
-        line->DrawClone();
-        delete line;
-    }
-
-    int npad(2);
-    for(DataScan_t::iterator it=data_scans.begin(); it!= data_scans.end(); ++it, ++npad) {
-        c1->cd(npad);
-        TH1D *hist = IsGISAXSTools::getOutputDataScanHist(*(*it));
-        hist->DrawCopy();
-        delete hist;
-    }
     c1->Update();
-
-    // creating fit suite
-    m_fitSuite = new FitSuite();
-    m_fitSuite->setMinimizer( new ROOTMinimizer("Minuit2", "Migrad") );
-    m_fitSuite->attachObserver( new FitSuiteObserverPrint() );
-    m_fitSuite->attachObserver( new FitSuiteObserverDraw() );
-
-//    m_fitSuite->addFitParameter("*SampleBuilder/dispersion_radius1",  0.2*Units::nanometer, 1*Units::nanometer, AttLimits::lowerLimited(0.01) );
-//    m_fitSuite->addFitParameter("*SampleBuilder/dispersion_radius2",  0.2*Units::nanometer, 1*Units::nanometer, AttLimits::lowerLimited(0.01) );
-//    m_fitSuite->addFitParameter("*SampleBuilder/height_aspect_ratio1",  0.8*Units::nanometer, 1*Units::nanometer, AttLimits::lowerLimited(0.01) );
-//    m_fitSuite->addFitParameter("*SampleBuilder/height_aspect_ratio2",  0.8*Units::nanometer, 1*Units::nanometer, AttLimits::lowerLimited(0.01) );
-//    m_fitSuite->addFitParameter("*SampleBuilder/interf_distance",  12*Units::nanometer, 1*Units::nanometer, AttLimits::lowerLimited(0.01) );
-//    m_fitSuite->addFitParameter("*SampleBuilder/interf_width",  6*Units::nanometer, 1*Units::nanometer, AttLimits::lowerLimited(0.01) );
-//    m_fitSuite->addFitParameter("*SampleBuilder/particle_probability",  0.4, 0.1, AttLimits::lowerLimited(0.01) );
-//    m_fitSuite->addFitParameter("*SampleBuilder/particle_radius1",  4*Units::nanometer, 1*Units::nanometer, AttLimits::lowerLimited(0.01) );
-//    m_fitSuite->addFitParameter("*SampleBuilder/particle_radius2",  4*Units::nanometer, 1*Units::nanometer, AttLimits::lowerLimited(0.01) );
-
-    m_fitSuite->addFitParameter("*SampleBuilder/dispersion_radius1",  0.3*Units::nanometer, 1*Units::nanometer, AttLimits::lowerLimited(0.01) );
-    m_fitSuite->addFitParameter("*SampleBuilder/dispersion_radius2",  0.3*Units::nanometer, 1*Units::nanometer, AttLimits::lowerLimited(0.01) );
-    m_fitSuite->addFitParameter("*SampleBuilder/height_aspect_ratio1",  0.7*Units::nanometer, 1*Units::nanometer, AttLimits::lowerLimited(0.01) );
-    m_fitSuite->addFitParameter("*SampleBuilder/height_aspect_ratio2",  0.7*Units::nanometer, 1*Units::nanometer, AttLimits::lowerLimited(0.01) );
-    m_fitSuite->addFitParameter("*SampleBuilder/interf_distance",  10*Units::nanometer, 1*Units::nanometer, AttLimits::lowerLimited(0.01) );
-    m_fitSuite->addFitParameter("*SampleBuilder/interf_width",  5*Units::nanometer, 1*Units::nanometer, AttLimits::lowerLimited(0.01) );
-    m_fitSuite->addFitParameter("*SampleBuilder/particle_probability",  0.4, 0.1, AttLimits::lowerLimited(0.01) );
-    m_fitSuite->addFitParameter("*SampleBuilder/particle_radius1",  3*Units::nanometer, 1*Units::nanometer, AttLimits::lowerLimited(0.01) );
-    m_fitSuite->addFitParameter("*SampleBuilder/particle_radius2",  3*Units::nanometer, 1*Units::nanometer, AttLimits::lowerLimited(0.01) );
-
-    for(DataScan_t::iterator it=data_scans.begin(); it!= data_scans.end(); ++it) {
-        m_fitSuite->addExperimentAndRealData(*m_experiment, *(*it));
-    }
-
-    m_fitSuite->runFit();
-
-    delete real_data;
-    for(DataScan_t::iterator it=data_scans.begin(); it!= data_scans.end(); ++it) delete (*it);
 }
 
 
@@ -217,16 +147,13 @@ void TestIsGISAXS12::run_test_fit()
 void TestIsGISAXS12::run_isgisaxs_fit()
 {
     // reading info about two 1D scans defined in isgisaxs example
-    read_isgisaxs_datfile(m_data_path+"isgi_fitconstraints.dat");
-
-    // making some plots together with test simulation
-    plot_isgisaxs_data();
-//    return;
+    DataSet isgi_scans;
+    read_isgisaxs_outfile(m_data_path+"isgi_fitconstraints.out", isgi_scans);
 
     // creating fit suite
     m_fitSuite = new FitSuite();
     m_fitSuite->setMinimizer( new ROOTMinimizer("Minuit2", "Migrad") );
-    //m_fitSuite->setMinimizer( new ROOTMinimizer("GSLMultiMin", "SteepestDescent") );
+    //m_fitSuite->setMinimizer( new ROOTMinimizer("GSLMultiFit", "") );
     m_fitSuite->attachObserver( new FitSuiteObserverPrint(10) );
     m_fitSuite->attachObserver( new FitSuiteObserverDraw(50) );
 
@@ -234,115 +161,305 @@ void TestIsGISAXS12::run_isgisaxs_fit()
     minim->SetStrategy(1);
 //    minim->SetPrecision(1.);
 
-    m_fitSuite->addFitParameter("*Normalizer/scale", 1e5, 100, AttLimits::limited(1e4, 2e5));
-    m_fitSuite->addFitParameter("*Normalizer/shift", 10, 1, AttLimits::limited(1., 20.));
-    m_fitSuite->addFitParameter("*SampleBuilder/particle_probability",  0.4, 0.1, AttLimits::limited(0.01, 1.0) );
+    m_fitSuite->addFitParameter("*Normalizer/scale", 1e5, 1, AttLimits::limited(1e4, 2e5));
+    m_fitSuite->addFitParameter("*Normalizer/shift", 10, 0.01, AttLimits::limited(1., 20.));
+
+    m_fitSuite->addFitParameter("*SampleBuilder/particle_probability1",  0.4, 0.01, AttLimits::limited(0.01, 1.0) );
+    m_fitSuite->addFitParameter("*SampleBuilder/particle_radius1",  4*Units::nanometer, 0.01*Units::nanometer, AttLimits::limited(1., 10.) );
+    m_fitSuite->addFitParameter("*SampleBuilder/dispersion_radius1",  0.2, 0.01, AttLimits::limited(0.01, 1.) );
+    m_fitSuite->addFitParameter("*SampleBuilder/height_aspect_ratio1",  0.8, 0.01, AttLimits::limited(0.01, 10.) );
+
+    m_fitSuite->addFitParameter("*SampleBuilder/particle_probability2",  0.6, 0.01, AttLimits::limited(0.01, 1.0) );
+    m_fitSuite->addFitParameter("*SampleBuilder/particle_radius2",  4*Units::nanometer, 0.01*Units::nanometer, AttLimits::limited(1., 10.) );
+    m_fitSuite->addFitParameter("*SampleBuilder/dispersion_radius2",  0.2, 0.01, AttLimits::limited(0.01, 1.) );
+    m_fitSuite->addFitParameter("*SampleBuilder/height_aspect_ratio2",  0.8, 0.01, AttLimits::limited(0.01, 10.) );
+
+    m_fitSuite->addFitParameter("*SampleBuilder/interf_distance",  12*Units::nanometer, 0.01*Units::nanometer, AttLimits::limited(0.01, 50.0) );
+    m_fitSuite->addFitParameter("*SampleBuilder/interf_width",  6*Units::nanometer, 0.01*Units::nanometer, AttLimits::limited(0.01, 10.) );
 
-    m_fitSuite->addFitParameter("*SampleBuilder/particle_radius1",  4*Units::nanometer, 1*Units::nanometer, AttLimits::limited(1., 10.) );
-    m_fitSuite->addFitParameter("*SampleBuilder/dispersion_radius1",  0.2, 0.1, AttLimits::limited(0.01, 1.) );
-    m_fitSuite->addFitParameter("*SampleBuilder/height_aspect_ratio1",  0.8, 0.1, AttLimits::limited(0.01, 10.) );
 
-    m_fitSuite->addFitParameter("*SampleBuilder/particle_radius2",  4*Units::nanometer, 1*Units::nanometer, AttLimits::limited(1., 10.) );
-    m_fitSuite->addFitParameter("*SampleBuilder/dispersion_radius2",  0.2, 0.1, AttLimits::limited(0.01, 1.) );
-    m_fitSuite->addFitParameter("*SampleBuilder/height_aspect_ratio2",  0.8, 0.1, AttLimits::limited(0.01, 10.) );
+//      m_fitSuite->addFitParameter("*Normalizer/scale", 1.31159E+05, 100, AttLimits::limited(1e4, 2e5));
+//      m_fitSuite->addFitParameter("*Normalizer/shift", -8.10009E-02, 1, AttLimits::limited(-10., 20.));
 
-    m_fitSuite->addFitParameter("*SampleBuilder/interf_distance",  12*Units::nanometer, 1*Units::nanometer, AttLimits::limited(0.01, 50.0) );
-    m_fitSuite->addFitParameter("*SampleBuilder/interf_width",  6*Units::nanometer, 1*Units::nanometer, AttLimits::limited(0.01, 10.) );
+//      m_fitSuite->addFitParameter("*SampleBuilder/particle_probability1",  5.34055E-01, 0.1, AttLimits::limited(0.01, 1.0) );
+//      m_fitSuite->addFitParameter("*SampleBuilder/particle_radius1",  4.90801E+00, 1*Units::nanometer, AttLimits::limited(1., 10.) );
+//      m_fitSuite->addFitParameter("*SampleBuilder/dispersion_radius1",  1.90651E-01, 0.1, AttLimits::limited(0.01, 1.) );
+//      m_fitSuite->addFitParameter("*SampleBuilder/height_aspect_ratio1",  1.00193E+00, 0.1, AttLimits::limited(0.01, 10.) );
+
+//      m_fitSuite->addFitParameter("*SampleBuilder/particle_probability2",  4.70783E-01, 0.1, AttLimits::limited(0.01, 1.0) );
+//      m_fitSuite->addFitParameter("*SampleBuilder/particle_radius2",  5.16801E+00, 1*Units::nanometer, AttLimits::limited(1., 10.) );
+//      m_fitSuite->addFitParameter("*SampleBuilder/dispersion_radius2",  2.03908E-01, 0.1, AttLimits::limited(0.01, 1.) );
+//      m_fitSuite->addFitParameter("*SampleBuilder/height_aspect_ratio2",  9.77402E-01, 0.1, AttLimits::limited(0.01, 10.) );
+
+//      m_fitSuite->addFitParameter("*SampleBuilder/interf_distance",  1.49681E+01, 1*Units::nanometer, AttLimits::limited(0.01, 50.0) );
+//      m_fitSuite->addFitParameter("*SampleBuilder/interf_width",  3.03315E+00, 1*Units::nanometer, AttLimits::limited(0.01, 10.) );
 
     // setting up fitSuite
     ChiSquaredModule chiModule;
     chiModule.setChiSquaredFunction( SquaredFunctionWithSystematicError(0.08) );
     chiModule.setOutputDataNormalizer( OutputDataNormalizerScaleAndShift() );
 
-    for(DataScan_t::iterator it=m_isgi_scans.begin(); it!= m_isgi_scans.end(); ++it) {
+    for(DataSet::iterator it=isgi_scans.begin(); it!= isgi_scans.end(); ++it) {
         m_fitSuite->addExperimentAndRealData(*m_experiment, *(*it), chiModule);
     }
 
     m_fitSuite->runFit();
 
     // drawing results
-    TCanvas *c2 = new TCanvas("c2","c2",800,600);
+    TCanvas *c2 = new TCanvas("c2","GISASFW fit results",800,600);
     c2->Divide(2,2);
-    for(size_t i=0; i<m_fitSuite->getFitObjects()->size(); ++i) {
-        c2->cd((int)i+1);
-        const FitObject *obj = m_fitSuite->getFitObjects()->getObject(i);
-        TH1D *hreal = IsGISAXSTools::getOutputDataScanHist(*obj->getChiSquaredModule()->getRealData(),"real");
-        TH1D *hsimul = IsGISAXSTools::getOutputDataScanHist(*obj->getChiSquaredModule()->getSimulationData(),"simul");
+    TLegend *leg1 = new TLegend(0.5,0.6,0.85,0.85);
+    leg1->SetBorderSize(1);
+    leg1->SetFillStyle(0);
+    for(size_t i_set=0; i_set<m_fitSuite->getFitObjects()->size(); ++i_set) {
+        c2->cd(i_set+1);
+        const FitObject *obj = m_fitSuite->getFitObjects()->getObject(i_set);
+        TH1D *hreal = IsGISAXSTools::getOutputDataScanHist(*obj->getChiSquaredModule()->getRealData(),"gisasfw_real");
+        TH1D *hsimul = IsGISAXSTools::getOutputDataScanHist(*obj->getChiSquaredModule()->getSimulationData(),"gisasfw_simul");
         hreal->SetLineColor(kBlue);
         gPad->SetLogy();
         hreal->DrawCopy();
         hsimul->DrawCopy("same");
-        delete hreal;
-        delete hsimul;
+        if(i_set==0) leg1->AddEntry(hreal,"GISASFW data","lp");
+        if(i_set==0) leg1->AddEntry(hsimul,"GISASFW simul","lp");
+    }
+    c2->cd(1); leg1->Draw();
+    c2->cd(2); leg1->Draw();
+
+    // drawing ratio
+    TLegend *leg2 = new TLegend(0.5,0.6,0.85,0.85);
+    leg2->SetBorderSize(1);
+    leg2->SetFillStyle(0);
+    for(size_t i_set=0; i_set<m_fitSuite->getFitObjects()->size(); ++i_set) {
+        c2->cd(3+1);
+        const FitObject *obj = m_fitSuite->getFitObjects()->getObject(i_set);
+        OutputData<double > *real = obj->getChiSquaredModule()->getRealData()->clone();
+        OutputData<double > *simul = obj->getChiSquaredModule()->getSimulationData()->clone();
+
+        c2->cd(i_set+3);
+        *simul /= *real;
+        TH1D *hratio = IsGISAXSTools::getOutputDataScanHist(*simul,"gisasfw_real_simul_ratio");
+        hratio->DrawCopy();
+        if(i_set==0) {
+            leg2->AddEntry(hratio,"GISASFW simul/real","lp");
+        }
+        delete real;
+        delete simul;
     }
+    c2->cd(3); leg2->Draw();
+    c2->cd(4); leg2->Draw();
 
 
+    c2->Update();
 }
 
 
+/* ************************************************************************* */
+// run chi module test on isgisaxs data/result pair to check module numericaly
+/* ************************************************************************* */
+void TestIsGISAXS12::run_test_chimodule()
+{
+    DataSet isgi_scans;
+    read_isgisaxs_outfile(m_data_path+"isgi_fitconstraints.out", isgi_scans);
+
+    DataSet isgi_results;
+    read_isgisaxs_outfile(m_data_path+"isgi_fitconstraints.out", isgi_results, true);
+
+    // setting up fitSuite
+    ChiSquaredModule chiModule;
+    chiModule.setChiSquaredFunction( SquaredFunctionWithSystematicError(0.08) );
+    chiModule.setOutputDataNormalizer( OutputDataNormalizerScaleAndShift() );
+
+    OutputDataNormalizerScaleAndShift normalizer(1.31159E+05, -8.10009E-02);
+
+    double max_intensity(0);
+    for(size_t i=0; i<isgi_results.size(); ++i) {
+        OutputData<double>::const_iterator cit = std::max_element(isgi_results[i]->begin(), isgi_results[i]->end());
+        max_intensity = std::max(max_intensity, *cit);
+    }
+    std::cout << "XXX " << max_intensity << std::endl;
+    normalizer.setMaximumIntensity(max_intensity);
+
+    chiModule.setOutputDataNormalizer( normalizer );
+
+    double chi_sum(0);
+    for(size_t i=0; i<isgi_scans.size(); ++i) {
+        chiModule.setRealAndSimulatedData(*isgi_scans[i], *isgi_results[i]);
+        std::cout << " AAA " << isgi_scans.size()*isgi_results[i]->getAllocatedSize() - 12 << std::endl;
+        chiModule.setNdegreeOfFreedom(isgi_scans.size()*isgi_results[i]->getAllocatedSize() - 12);
+        double chi = 0.5*0.5*chiModule.calculateChiSquared();
+        chi_sum += chi;
+        std::cout << "chi : " << chi << " chi_sum:" << chi_sum << std::endl;
+    }
+    std::cout << "chi_sum " << chi_sum << std::endl;
+
+    return;
+}
+
 
 /* ************************************************************************* */
 // plot isgisaxs data together with test simulation
 /* ************************************************************************* */
 void TestIsGISAXS12::plot_isgisaxs_data()
 {
-    if(m_isgi_scans.size() != 2) throw LogicErrorException("TestIsGISAXS12::plot_isgisaxs_data() -> Load isgisaxs scans first");
-
-    enum isgisaxs_scans {kFixedAlphaf, kFixedPhif };
-
-    // making 2d OutputData with axes like in two isgisaxs scans
-    OutputData<double > *data_as_isgisaxs = new OutputData<double>;
-    const NamedVector<double > *axis_phif_scan = dynamic_cast<const NamedVector<double> *>(m_isgi_scans[kFixedAlphaf]->getAxis("phi_f"));
-    const NamedVector<double > *axis_alphaf_scan = dynamic_cast<const NamedVector<double> *>(m_isgi_scans[kFixedPhif]->getAxis("alpha_f"));
-    if( !axis_phif_scan || !axis_phif_scan ) throw NullPointerException("TestIsGISAXS12::plot_isgisaxs_data() -> Error. Can'get get axis");
-    data_as_isgisaxs->addAxis(axis_phif_scan->clone());
-    data_as_isgisaxs->addAxis(axis_alphaf_scan->clone());
-    data_as_isgisaxs->setAllTo(0.0);
-    std::cout << axis_phif_scan->getSize() << " " << axis_alphaf_scan->getSize() << " " << data_as_isgisaxs->getAllocatedSize() << std::endl;
-
-    // running 2d simulation
-    m_experiment->setDetectorParameters(*data_as_isgisaxs);
-    delete data_as_isgisaxs;
-//    m_experiment->setBeamIntensity(1e10);
-    m_experiment->runSimulation();
-//    m_experiment->normalize();
+    // reading two 1D scans defined in isgisaxs example (399 points/scan)
+    DataSet isgi_scans;
+    read_isgisaxs_datfile(m_data_path+"isgi_fitconstraints.dat", isgi_scans);
+
+    // reading isgisaxs scans which actually have been used for a fit together with fit results (100 points/scan)
+    DataSet isgi_scans_smoothed;
+    read_isgisaxs_outfile(m_data_path+"isgi_fitconstraints.out", isgi_scans_smoothed);
+    DataSet isgi_results;
+    read_isgisaxs_outfile(m_data_path+"isgi_fitconstraints.out", isgi_results, true);
 
-    // setting up 1d scans by making slices on just simulated data
-    DataScan_t data_scans;
-    data_scans.push_back( OutputDataFunctions::selectRangeOnOneAxis(*m_experiment->getOutputData(), "alpha_f", m_isgi_fixed_alphaf, m_isgi_fixed_alphaf  ));
-    data_scans.push_back( OutputDataFunctions::selectRangeOnOneAxis(*m_experiment->getOutputData(), "phi_f", m_isgi_fixed_phif, m_isgi_fixed_phif ));
+    print_axes(isgi_scans);
+    print_axes(isgi_scans_smoothed);
+    print_axes(isgi_results);
 
-    // drawing data and scans
-    TCanvas *c1 = new TCanvas("c1","c1",1024, 768);
+    TCanvas *c1 = DrawHelper::instance().createAndRegisterCanvas("c1_isgisaxs_data", "Looking on IsGISAXS data and fit results", 768, 1024);
     c1->Divide(2,3);
-    c1->cd(1); gPad->SetLogz();
-    TH2D *hist1 = dynamic_cast<TH2D *>(IsGISAXSTools::getOutputDataTH123D( *m_experiment->getOutputData(), "real_data"));
-    hist1->Draw("COLZ");
-    for(DataScan_t::const_iterator it=data_scans.begin(); it!= data_scans.end(); ++it) {
-        TLine *line = IsGISAXSTools::getOutputDataScanLine(*(*it));
-        line->DrawClone();
-        delete line;
+
+    // drawing real data with fine and coars granularity on top of each other
+    TLegend *leg1 = new TLegend(0.5,0.6,0.85,0.85);
+    leg1->SetBorderSize(1);
+    leg1->SetFillStyle(0);
+
+    for(size_t i_set=0; i_set<isgi_scans.size(); ++i_set) {
+        c1->cd(1+i_set); gPad->SetLogy();
+        TH1D *hdata = IsGISAXSTools::getOutputDataScanHist(*isgi_scans[i_set], "data");
+        hdata->DrawCopy();
+        if(i_set==0) leg1->AddEntry(hdata,"isgisaxs data fine","lp");
+        TH1D *hdata_smoothed = IsGISAXSTools::getOutputDataScanHist(*isgi_scans_smoothed[i_set], "data_smoothed");
+        hdata_smoothed->SetLineColor(kBlue);
+        hdata_smoothed->DrawCopy("same");
+        if(i_set==0) leg1->AddEntry(hdata_smoothed,"isgisaxs data","lp");
     }
-    int npad(3);
-    for(DataScan_t::iterator it=data_scans.begin(); it!= data_scans.end(); ++it, ++npad) {
-        c1->cd(npad);
-        TH1D *hist = IsGISAXSTools::getOutputDataScanHist(*(*it), "sim");
-        hist->DrawCopy();
-        delete hist;
+    c1->cd(1); leg1->Draw();
+    c1->cd(2); leg1->Draw();
+
+    // drawing isgsaxs fit results on top of isgisaxs real data
+    TLegend *leg2 = new TLegend(0.5,0.6,0.85,0.85);
+    leg2->SetBorderSize(1);
+    leg2->SetFillStyle(0);
+    for(size_t i_set=0; i_set<isgi_scans.size(); ++i_set) {
+        c1->cd(3+i_set); gPad->SetLogy();
+        TH1D *hdata = IsGISAXSTools::getOutputDataScanHist(*isgi_results[i_set], "data");
+        hdata->SetLineColor(kRed);
+        hdata->DrawCopy();
+        if(i_set==0) leg2->AddEntry(hdata,"isgisaxs results","lp");
+        TH1D *hdata_smoothed = IsGISAXSTools::getOutputDataScanHist(*isgi_scans_smoothed[i_set], "data_smoothed");
+        hdata_smoothed->SetLineColor(kBlue);
+        hdata_smoothed->DrawCopy("same");
+        if(i_set==0) leg2->AddEntry(hdata_smoothed,"isgisaxs data","lp");
     }
-
-    // drawing isgi scans
-    npad=5;
-    for(DataScan_t::iterator it=m_isgi_scans.begin(); it!= m_isgi_scans.end(); ++it, ++npad) {
-        c1->cd(npad);
-        TH1D *hist = IsGISAXSTools::getOutputDataScanHist(*(*it),"isgi");
-        hist->SetLineColor(kBlue);
-        hist->DrawCopy();
-        delete hist;
+    c1->cd(3); leg2->Draw();
+    c1->cd(4); leg2->Draw();
+
+    // drawing ratio of isgisaxs data/results
+    TLegend *leg3 = new TLegend(0.5,0.6,0.85,0.85);
+    leg3->SetBorderSize(1);
+    leg3->SetFillStyle(0);
+    for(size_t i_set=0; i_set<isgi_scans.size(); ++i_set) {
+        c1->cd(5+i_set);
+        *isgi_results[i_set] /= *isgi_scans_smoothed[i_set];
+        TH1D *hdata = IsGISAXSTools::getOutputDataScanHist(*isgi_results[i_set], "isgisaxs_results_data");
+        hdata->SetLineColor(kRed);
+        hdata->DrawCopy();
+        if(i_set==0) leg3->AddEntry(hdata,"isgisaxs results/data","lp");
     }
+    c1->cd(5); leg3->Draw();
+    c1->cd(6); leg3->Draw();
+
     c1->Update();
 
-    for(DataScan_t::iterator it=data_scans.begin(); it!= data_scans.end(); ++it) delete (*it);
+}
+
+
+/* ************************************************************************* */
+// run test minimizer to check the whole chain
+/* ************************************************************************* */
+void TestIsGISAXS12::run_test_minimizer()
+{
+    // reading isgisaxs real data
+    DataSet isgi_scans_smoothed;
+    read_isgisaxs_outfile(m_data_path+"isgi_fitconstraints.out", isgi_scans_smoothed);
+    // isgisaxs fit results
+    DataSet isgi_results;
+    read_isgisaxs_outfile(m_data_path+"isgi_fitconstraints.out", isgi_results, true);
+
+    // Putting parameters found by isgisaxs into our sample and run FitSuite once with the help of TestMinimizer to see if
+    // our simulation produces numerically same results
+
+    m_fitSuite = new FitSuite();
+    m_fitSuite->setMinimizer( new TestMinimizer() );
+
+    m_fitSuite->addFitParameter("*Normalizer/scale", 1.31159E+05, 100, AttLimits::limited(1e4, 2e5));
+    m_fitSuite->addFitParameter("*Normalizer/shift", -8.10009E-02, 1, AttLimits::limited(-10., 20.));
+
+    m_fitSuite->addFitParameter("*SampleBuilder/particle_probability1",  5.34055E-01, 0.1, AttLimits::limited(0.01, 1.0) );
+    m_fitSuite->addFitParameter("*SampleBuilder/particle_radius1",  4.90801E+00, 1*Units::nanometer, AttLimits::limited(1., 10.) );
+    m_fitSuite->addFitParameter("*SampleBuilder/dispersion_radius1",  1.90651E-01, 0.1, AttLimits::limited(0.01, 1.) );
+    m_fitSuite->addFitParameter("*SampleBuilder/height_aspect_ratio1",  1.00193E+00, 0.1, AttLimits::limited(0.01, 10.) );
+
+    m_fitSuite->addFitParameter("*SampleBuilder/particle_probability2",  4.70783E-01, 0.1, AttLimits::limited(0.01, 1.0) );
+    m_fitSuite->addFitParameter("*SampleBuilder/particle_radius2",  5.16801E+00, 1*Units::nanometer, AttLimits::limited(1., 10.) );
+    m_fitSuite->addFitParameter("*SampleBuilder/dispersion_radius2",  2.03908E-01, 0.1, AttLimits::limited(0.01, 1.) );
+    m_fitSuite->addFitParameter("*SampleBuilder/height_aspect_ratio2",  9.77402E-01, 0.1, AttLimits::limited(0.01, 10.) );
+
+    m_fitSuite->addFitParameter("*SampleBuilder/interf_distance",  1.49681E+01, 1*Units::nanometer, AttLimits::limited(0.01, 50.0) );
+    m_fitSuite->addFitParameter("*SampleBuilder/interf_width",  3.03315E+00, 1*Units::nanometer, AttLimits::limited(0.01, 10.) );
+
+    // setting up fitSuite
+    ChiSquaredModule chiModule;
+    chiModule.setChiSquaredFunction( SquaredFunctionWithSystematicError(0.08) );
+    chiModule.setOutputDataNormalizer( OutputDataNormalizerScaleAndShift() );
+//    for(DataSet::iterator it=isgi_results.begin(); it!= isgi_results.end(); ++it) {
+//        m_fitSuite->addExperimentAndRealData(*m_experiment, *(*it), chiModule);
+//    }
+    for(DataSet::iterator it=isgi_scans_smoothed.begin(); it!= isgi_scans_smoothed.end(); ++it) {
+        m_fitSuite->addExperimentAndRealData(*m_experiment, *(*it), chiModule);
+    }
+    m_fitSuite->runFit();
+
+    TCanvas *c1 = new TCanvas("c1_test_minimizer","TestMinimizer", 800, 600);
+    c1->Divide(2,2);
+
+    // drawing GISASFW simul on top of isgisaxs simul
+    TLegend *leg1 = new TLegend(0.5,0.6,0.85,0.85);
+    leg1->SetBorderSize(1);
+    leg1->SetFillStyle(0);
+    for(size_t i_set=0; i_set<isgi_results.size(); ++i_set) {
+        c1->cd(1+i_set);
+        gPad->SetLogy();
+        TH1D *hdata = IsGISAXSTools::getOutputDataScanHist(*isgi_results[i_set], "data");
+        hdata->SetLineColor(kRed);
+        hdata->DrawCopy();
+        const OutputData<double > *data = m_fitSuite->getFitObjects()->getObject(i_set)->getChiSquaredModule()->getSimulationData();
+        TH1D *simul_data = IsGISAXSTools::getOutputDataScanHist(*data, "data_from_module");
+        simul_data->SetLineColor(kBlue);
+        simul_data->DrawCopy("same");
+
+        if(i_set==0) leg1->AddEntry(hdata,"isgisaxs results","lp");
+        if(i_set==0) leg1->AddEntry(simul_data,"gisasfw simul","lp");
+    }
+    c1->cd(1); leg1->Draw();
+    c1->cd(2); leg1->Draw();
+
+    TLegend *leg2 = new TLegend(0.5,0.6,0.85,0.85);
+    leg2->SetBorderSize(1);
+    leg2->SetFillStyle(0);
+    for(size_t i_set=0; i_set<isgi_results.size(); ++i_set) {
+        c1->cd(3+i_set);
+        OutputData<double > *data = m_fitSuite->getFitObjects()->getObject(i_set)->getChiSquaredModule()->getSimulationData()->clone();
+        *data /= *isgi_results[i_set];
+        TH1D *hdata = IsGISAXSTools::getOutputDataScanHist(*data, "gisasfw_isgisaxs_simul");
+        hdata->SetLineColor(kRed);
+        hdata->DrawCopy();
+        delete data;
+        if(i_set==0) leg2->AddEntry(hdata,"gisasfw/isgisaxs simul","lp");
+    }
+    c1->cd(3); leg1->Draw();
+    c1->cd(4); leg1->Draw();
 }
 
 
@@ -366,8 +483,10 @@ void TestIsGISAXS12::initialiseExperiment()
 /* ************************************************************************* */
 // read special isgisaxs *.dat file with data to fit
 /* ************************************************************************* */
-void TestIsGISAXS12::read_isgisaxs_datfile(const std::string &filename)
+void TestIsGISAXS12::read_isgisaxs_datfile(const std::string &filename, DataSet &dataset)
 {
+    dataset.clear();
+
     // opening ASCII file
     std::ifstream fin;
     fin.open(filename.c_str(), std::ios::in);
@@ -387,8 +506,7 @@ void TestIsGISAXS12::read_isgisaxs_datfile(const std::string &filename)
             n_dataset_line = 0; // it's a beginning of new data set ("cross-section" in isgisaxs terminology)
             if( !isgiScan.empty() ) {
                 OutputData<double > *data = convert_isgi_scan(isgiScan);
-                m_isgi_scans.push_back(data);
-                std::cout << "YYY " << isgiScan.size() << std::endl;
+                dataset.push_back(data);
                 isgiScan.clear();
             }
         }
@@ -400,11 +518,9 @@ void TestIsGISAXS12::read_isgisaxs_datfile(const std::string &filename)
             if ( !(iss >> ctmp >> isgiData.phif >> isgiData.alphaf >> isgiData.intensity) ) throw FormatErrorException("TestIsGISAXS12::read_isgisaxs_datfile() -> Error!");
             iss >> isgiData.err; // column with errors can be absent in file, so no check for success here
             ctmp == 'T' ? isgiData.use_it = true : isgiData.use_it = false;
-            if(isgiData.phif > .0001) {
-                isgiData.phif = std::asin(isgiData.phif); // because isgisax in fact stores in *.dat file sin(phif), and sin(alphaf) instead of phif, alphaf
-                isgiData.alphaf = std::asin(isgiData.alphaf);  // because isgisax in fact stores in *.dat file sin(phif), and sin(alphaf) instead of phif, alphaf
-                isgiScan.push_back(isgiData);
-            }
+            isgiData.phif = std::asin(isgiData.phif); // because isgisax in fact stores in *.dat file sin(phif), and sin(alphaf) instead of phif, alphaf
+            isgiData.alphaf = std::asin(isgiData.alphaf);  // because isgisax in fact stores in *.dat file sin(phif), and sin(alphaf) instead of phif, alphaf
+            isgiScan.push_back(isgiData);
         }
 
         n_dataset_line++;
@@ -417,6 +533,71 @@ void TestIsGISAXS12::read_isgisaxs_datfile(const std::string &filename)
 }
 
 
+/* ************************************************************************* */
+// read special isgisaxs *.out file with isgisaxs adjusted data and fit results
+//
+// if read_fit_results == false, then it loads isgisaxs data to fit
+// if read_fit_results == true, then it loads isgisaxs fit results
+/* ************************************************************************* */
+void TestIsGISAXS12::read_isgisaxs_outfile(const std::string &filename, DataSet &dataset, bool read_fit_results)
+{
+    enum isgisaxs_keys_outfile {kSin_twotheta, kSin_alphaf, kQx, kQy, kQz, kGISAXS, kData2fit, kErrorbar, kIobs_Icalc, kFitted };
+
+    dataset.clear();
+
+    // opening ASCII file
+    std::ifstream fin;
+    fin.open(filename.c_str(), std::ios::in);
+    if( !fin.is_open() ) {
+        throw FileNotIsOpenException("TestIsGISAXS12::read_isgisaxs_datfile() -> Error. Can't open file '"+filename+"' for reading.");
+    }
+
+    std::vector<IsgiData > isgiScan;
+
+    std::string sline;
+    while( std::getline(fin, sline))
+    {
+        std::string::size_type pos=sline.find("# Cut # =");
+        if( pos!= std::string::npos ) {
+            //std::cout << "beginning of one dataset " << isgiScan.size() << std::endl;
+            if( !isgiScan.empty() ) {
+                OutputData<double > *data = convert_isgi_scan(isgiScan);
+                dataset.push_back(data);
+                isgiScan.clear();
+            }
+        } else if (sline[0] != '#' && sline.size() >2){
+            // not a header, parsing records
+            std::istringstream iss(sline.c_str());
+            IsgiData isgiData;
+
+            vdouble1d_t buff;
+            std::copy(std::istream_iterator<double>(iss), std::istream_iterator<double>(), back_inserter(buff));
+            if( buff.size() != kFitted+1) {
+                throw LogicErrorException("TestIsGISAXS12::read_isgisaxs_outfile -> Error! Line doesn't have enough double numbers. Not an *.out file? Line '"+sline+"'");
+            }
+
+            isgiData.phif = std::asin(buff[kSin_twotheta]);
+            isgiData.alphaf = std::asin(buff[kSin_alphaf]);
+            isgiData.intensity = buff[kData2fit];
+            if( read_fit_results ) isgiData.intensity = buff[kGISAXS];
+
+            isgiScan.push_back(isgiData);
+        }
+    }
+    if ( fin.bad() ) {
+        throw FileIsBadException("TestIsGISAXS12::read_isgisaxs_datfile() -> Error! File is bad after readline(), probably it is a directory.");
+    }
+    fin.close();
+
+    if( !isgiScan.empty() ) {
+        OutputData<double > *data = convert_isgi_scan(isgiScan);
+        dataset.push_back(data);
+        isgiScan.clear();
+    }
+}
+
+
+
 /* ************************************************************************* */
 // convert isgisaxs 1d scan to output data 2d object
 /* ************************************************************************* */
@@ -424,6 +605,14 @@ OutputData<double> *TestIsGISAXS12::convert_isgi_scan(std::vector<IsgiData > &is
 {
     if(isgi_data.size() <2 ) throw LogicErrorException("TestIsGISAXS12::convert_isgi_scan() -> Error! Too short vector.");
 
+//    // adjust data to get rid from the point with phi_f~0.0
+//    std::vector<IsgiData > adjusted_data;
+//    for(size_t i_point=0; i_point<isgi_data.size(); ++i_point) {
+//        if(isgi_data[i_point].phif > 0.001) {
+//            adjusted_data.push_back(isgi_data[i_point]);
+//        }
+//    }
+
     // check if it is scan with fixed phi_f or with fixed alpha_f
     bool fixed_phif(true);
     bool fixed_alphaf(true);
@@ -482,15 +671,18 @@ OutputData<double> *TestIsGISAXS12::convert_isgi_scan(std::vector<IsgiData > &is
 //
 /* ************************************************************************* */
 TestIsGISAXS12::TestSampleBuilder::TestSampleBuilder()
-    : m_particle_probability(0.4)
-    , m_particle_radius1(4*Units::nanometer)
-    , m_particle_radius2(4*Units::nanometer)
-    , m_dispersion_radius1(0.2)
-    , m_dispersion_radius2(0.2)
-    , m_height_aspect_ratio1(0.8)
-    , m_height_aspect_ratio2(0.8)
-    , m_interf_distance(12.0*Units::nanometer)
-    , m_interf_width(6*Units::nanometer)
+// optimal parameters as found by isgisaxs
+  : m_particle_probability1(5.34055E-01)
+  , m_particle_radius1(4.90801E+00*Units::nanometer)
+  , m_dispersion_radius1(1.90651E-01)
+  , m_height_aspect_ratio1(1.00193E+00)
+  , m_particle_probability2(4.70783E-01)
+  , m_particle_radius2(5.16801E+00*Units::nanometer)
+  , m_dispersion_radius2(2.03908E-01)
+  , m_height_aspect_ratio2(9.77402E-01)
+  , m_interf_distance(1.49681E+01*Units::nanometer)
+  , m_interf_width(3.03315E+00*Units::nanometer)
+
 {
     init_parameters();
 }
@@ -498,12 +690,13 @@ TestIsGISAXS12::TestSampleBuilder::TestSampleBuilder()
 void TestIsGISAXS12::TestSampleBuilder::init_parameters()
 {
     getParameterPool()->clear();
-    getParameterPool()->registerParameter("particle_probability", &m_particle_probability);
+    getParameterPool()->registerParameter("particle_probability1", &m_particle_probability1);
     getParameterPool()->registerParameter("particle_radius1", &m_particle_radius1);
-    getParameterPool()->registerParameter("particle_radius2", &m_particle_radius2);
     getParameterPool()->registerParameter("dispersion_radius1", &m_dispersion_radius1);
-    getParameterPool()->registerParameter("dispersion_radius2", &m_dispersion_radius2);
     getParameterPool()->registerParameter("height_aspect_ratio1", &m_height_aspect_ratio1);
+    getParameterPool()->registerParameter("particle_probability2", &m_particle_probability2);
+    getParameterPool()->registerParameter("particle_radius2", &m_particle_radius2);
+    getParameterPool()->registerParameter("dispersion_radius2", &m_dispersion_radius2);
     getParameterPool()->registerParameter("height_aspect_ratio2", &m_height_aspect_ratio2);
     getParameterPool()->registerParameter("interf_distance", &m_interf_distance);
     getParameterPool()->registerParameter("interf_width", &m_interf_width);
@@ -524,6 +717,10 @@ ISample *TestIsGISAXS12::TestSampleBuilder::buildSample() const
     Layer air_layer(air_material);
 
     // preparing nano particles prototypes for seeding layer's particle_decoration
+    double particle_probability1 = m_particle_probability1;
+//    double particle_probability2 = 1. - m_particle_probability1;
+    double particle_probability2 = m_particle_probability2;
+
     double radius1 = m_particle_radius1;
     double radius2 = m_particle_radius2;
     double height1 = m_height_aspect_ratio1*radius1;
@@ -548,9 +745,9 @@ ISample *TestIsGISAXS12::TestSampleBuilder::buildSample() const
 
     // building nano particles
     ParticleBuilder builder;
-    builder.setPrototype(cylinder1,"/Particle/FormFactorCylinder/radius", par1, m_particle_probability);
+    builder.setPrototype(cylinder1,"/Particle/FormFactorCylinder/radius", par1, particle_probability1);
     builder.plantParticles(particle_decoration);
-    builder.setPrototype(cylinder2,"/Particle/FormFactorCylinder/radius", par2, 1-m_particle_probability);
+    builder.setPrototype(cylinder2,"/Particle/FormFactorCylinder/radius", par2, particle_probability2);
     builder.plantParticles(particle_decoration);
 
     // making layer holding all whose nano particles
@@ -565,6 +762,18 @@ ISample *TestIsGISAXS12::TestSampleBuilder::buildSample() const
 }
 
 
+void TestIsGISAXS12::print_axes(DataSet &data)
+{
+    for(size_t i_set=0; i_set<data.size(); ++i_set) {
+        std::cout << "scan #" << i_set << "  ";
+        for(size_t i_axis=0; i_axis<data[i_set]->getNdimensions(); ++i_axis) {
+            const NamedVector<double > *axis = dynamic_cast<const NamedVector<double > *>(data[i_set]->getAxis(i_axis));
+            if( !axis) throw NullPointerException("TestIsGISAXS12::plot_isgisaxs_data() -> Error! Can't get axis");
+            std::cout << "( " << axis->getName() << ", " << axis->getSize() << ", " << axis->getMin() << ", " << axis->getMax() << " )   ";
+        }
+        std::cout << std::endl;
+    }
+}
 
 
 
diff --git a/Core/Algorithms/inc/IChiSquaredModule.h b/Core/Algorithms/inc/IChiSquaredModule.h
index 169647ce196b62ce1a25262dfe7af39b42170b9e..37d8a3b6ab78bae7ea078470d5da90bb939aec7b 100644
--- a/Core/Algorithms/inc/IChiSquaredModule.h
+++ b/Core/Algorithms/inc/IChiSquaredModule.h
@@ -58,6 +58,7 @@ public:
 
     //! get data normalizer
     virtual const IOutputDataNormalizer *getOutputDataNormalizer() const {return mp_data_normalizer; }
+    virtual IOutputDataNormalizer *getOutputDataNormalizer() {return mp_data_normalizer; }
     //! set data normalizer
     virtual void setOutputDataNormalizer(const IOutputDataNormalizer &data_normalizer);
 
@@ -69,6 +70,9 @@ public:
     //! return last calculated chi squared value
     virtual double getValue() const { return m_chi2_value; }
 
+    //! set number of degree of freedom
+    void setNdegreeOfFreedom(int ndegree_of_freedom) { m_ndegree_of_freedom = ndegree_of_freedom; }
+
 protected:
     // disabling assignment operator
     IChiSquaredModule &operator=(const IChiSquaredModule &);
@@ -81,6 +85,7 @@ protected:
     IFittingDataSelector *mp_data_selector;
     IOutputDataNormalizer *mp_data_normalizer;
     IIntensityFunction  *mp_intensity_function;
+    int m_ndegree_of_freedom;
 
     double m_chi2_value;
 };
diff --git a/Core/Algorithms/inc/IOutputDataNormalizer.h b/Core/Algorithms/inc/IOutputDataNormalizer.h
index 0221b67879ebda3ed3b3c361e5f526918c7dd2d3..a456b63db081a16624bbe44e1ab60ee86a73cb5f 100644
--- a/Core/Algorithms/inc/IOutputDataNormalizer.h
+++ b/Core/Algorithms/inc/IOutputDataNormalizer.h
@@ -44,6 +44,8 @@ public:
 
     virtual OutputDataNormalizerScaleAndShift *clone() const;
 
+    void setMaximumIntensity(double max_intensity) { m_max_intensity = max_intensity; }
+
 protected:
     //! initialize pool parameters, i.e. register some of class members for later access via parameter pool
     virtual void init_parameters();
@@ -54,6 +56,7 @@ private:
 
     double m_scale;
     double m_shift;
+    double m_max_intensity;
 };
 
 
diff --git a/Core/Algorithms/src/ChiSquaredModule.cpp b/Core/Algorithms/src/ChiSquaredModule.cpp
index 71005602b55b61829603a7add9730298b33aca95..bf2764c33d985c1fd55ce6bad7e9b29a7a92573f 100644
--- a/Core/Algorithms/src/ChiSquaredModule.cpp
+++ b/Core/Algorithms/src/ChiSquaredModule.cpp
@@ -23,35 +23,40 @@ double ChiSquaredModule::calculateChiSquared()
     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_intensity_function ) {
-        OutputDataFunctions::applyFunction(*mp_simulation_data, mp_intensity_function);
-        OutputDataFunctions::applyFunction(*mp_real_data, mp_intensity_function);
-    }
-
     if(mp_data_normalizer) {
         OutputData<double > *normalized_simulation = mp_data_normalizer->createNormalizedData(*mp_simulation_data);
         delete mp_simulation_data;
         mp_simulation_data = normalized_simulation;
     }
 
+    if( mp_intensity_function ) {
+        OutputDataFunctions::applyFunction(*mp_simulation_data, mp_intensity_function);
+        OutputDataFunctions::applyFunction(*mp_real_data, mp_intensity_function);
+    }
+
     OutputData<double> *p_difference = createChi2DifferenceMap();
     OutputData<double>::const_iterator it_weights = mp_weights->begin();
     OutputData<double>::const_iterator it_diff = p_difference->begin();
+    double result(0);
     while(it_diff != p_difference->end()) {
         result += (*it_diff++)*(*it_weights++);
     }
     delete p_difference;
-    m_chi2_value = result/data_size;
+
+    double fnorm(0);
+    m_ndegree_of_freedom > 0 ? fnorm=double(m_ndegree_of_freedom) : fnorm = double(mp_real_data->getAllocatedSize());
+    m_chi2_value = result/fnorm;
     return m_chi2_value;
 }
 
 
 OutputData<double>* ChiSquaredModule::createChi2DifferenceMap() const
 {
+    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");
+
     OutputData<double > *p_difference = mp_simulation_data->clone();
     p_difference->setAllTo(0.0);
 
diff --git a/Core/Algorithms/src/Experiment.cpp b/Core/Algorithms/src/Experiment.cpp
index 9196375c2243389a97a17c0c431ecb5dcd48a232..7e0b0063697b89998e9f8fa6b3bfdc3ddb093f60 100644
--- a/Core/Algorithms/src/Experiment.cpp
+++ b/Core/Algorithms/src/Experiment.cpp
@@ -181,7 +181,7 @@ void Experiment::updateSample()
 
 void Experiment::setDetectorParameters(const OutputData<double > &output_data)
 {
-//    std::cout << "Experiment::setDetectorParameters() -> Info. Adjusting detector to have shape as in given output data" << std::endl;
+    //std::cout << "Experiment::setDetectorParameters() -> Info. Adjusting detector to have shape as in given output data" << std::endl;
     m_detector.clear();
     for(size_t i_axis=0; i_axis<output_data.getNdimensions(); ++i_axis) {
         const NamedVector<double> *axis = reinterpret_cast<const NamedVector<double>*>(output_data.getAxes()[i_axis]);
diff --git a/Core/Algorithms/src/GISASExperiment.cpp b/Core/Algorithms/src/GISASExperiment.cpp
index 5209c36d9e8fd08567cbd5697cb41735c3e745da..de8c12ffa50e8137344fd9e10f78eb758d16a1ed 100644
--- a/Core/Algorithms/src/GISASExperiment.cpp
+++ b/Core/Algorithms/src/GISASExperiment.cpp
@@ -237,9 +237,12 @@ double GISASExperiment::getSolidAngle(size_t index) const
     } else {
         //std::cout << "GISASExperiment::getSolidAngle() -> Warning! Only one bin on phi_f axis, size of the bin will be taken from alpha_f axis" << std::endl;
     }
-    if(!dalpha) dalpha=dphi;
-    if(!dphi) dphi=dalpha;
-    return cos_alpha_f*dalpha*dphi;
+    if(!dalpha || !dphi) {
+        std::cout << "GISASExperiment::getSolidAngle() -> Warning! Not defined normalization" << std::endl;
+        return 1;
+    } else {
+        return cos_alpha_f*dalpha*dphi;
+    }
 }
 
 
diff --git a/Core/Algorithms/src/IChiSquaredModule.cpp b/Core/Algorithms/src/IChiSquaredModule.cpp
index 592f83d7c4a0fa0e7e81a65c01efdf21baa1d8b1..112d3db7e5a9b177e3b52406c7f5a21058175fc0 100644
--- a/Core/Algorithms/src/IChiSquaredModule.cpp
+++ b/Core/Algorithms/src/IChiSquaredModule.cpp
@@ -9,6 +9,7 @@ IChiSquaredModule::IChiSquaredModule()
     , mp_data_selector(0)
     , mp_data_normalizer(0)
     , mp_intensity_function(0)
+    , m_ndegree_of_freedom(0)
     , m_chi2_value(0)
 {
     mp_squared_function = new SquaredFunctionDefault();
@@ -24,15 +25,17 @@ IChiSquaredModule::IChiSquaredModule(const IChiSquaredModule &other)
     , mp_data_selector(0)
     , mp_data_normalizer(0)
     , mp_intensity_function(0)
+    , m_ndegree_of_freedom(0)
     , m_chi2_value(0)
 {
-    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_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_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();
     if(other.mp_data_normalizer) mp_data_normalizer = other.mp_data_normalizer->clone();
     if(other.mp_intensity_function) mp_intensity_function = other.mp_intensity_function->clone();
+    m_ndegree_of_freedom = other.m_ndegree_of_freedom;
 }
 
 
diff --git a/Core/Algorithms/src/IOutputDataNormalizer.cpp b/Core/Algorithms/src/IOutputDataNormalizer.cpp
index e5bbd0ed7e29f4022098520b0f0e946ee553601f..6ad14b8f60148f0d0f455d94d7616cae70758951 100644
--- a/Core/Algorithms/src/IOutputDataNormalizer.cpp
+++ b/Core/Algorithms/src/IOutputDataNormalizer.cpp
@@ -6,6 +6,7 @@
 OutputDataNormalizerScaleAndShift::OutputDataNormalizerScaleAndShift()
     : m_scale(1.0)
     , m_shift(0)
+    , m_max_intensity(0)
 {
     setName("Normalizer");
     init_parameters();
@@ -14,6 +15,7 @@ OutputDataNormalizerScaleAndShift::OutputDataNormalizerScaleAndShift()
 OutputDataNormalizerScaleAndShift::OutputDataNormalizerScaleAndShift(double scale, double shift)
     : m_scale(scale)
     , m_shift(shift)
+    , m_max_intensity(0)
 {
     setName("Normalizer");
     init_parameters();
@@ -23,6 +25,7 @@ OutputDataNormalizerScaleAndShift::OutputDataNormalizerScaleAndShift(const Outpu
 {
     m_scale = other.m_scale;
     m_shift = other.m_shift;
+    m_max_intensity = other.m_max_intensity;
     init_parameters();
 }
 
@@ -45,17 +48,17 @@ OutputData<double> *OutputDataNormalizerScaleAndShift::createNormalizedData(cons
 {
     OutputData<double > *normalized_data = data.clone();
 
-    OutputData<double >::const_iterator cit = std::max_element(data.begin(), data.end());
-    double max_intensity = (*cit);
-    if(max_intensity) {
-        OutputData<double >::iterator it = normalized_data->begin();
-        while(it!=normalized_data->end()) {
-            double value = (*it);
-            (*it) = m_scale*(value/max_intensity) + m_shift;
-            ++it;
-        }
-    } else {
-        std::cout << "OutputDataNormalizerScaleAndShift::createNormalizedData() -> Warning! Zero maximum intensity" << std::endl;
+    double max_intensity = m_max_intensity;
+    if( max_intensity == 0 ) {
+        OutputData<double >::const_iterator cit = std::max_element(data.begin(), data.end());
+        max_intensity = (*cit);
+    }
+    if(max_intensity == 0) throw LogicErrorException("OutputDataNormalizerScaleAndShift::createNormalizedData() -> Error! Zero maximum intensity");
+    OutputData<double >::iterator it = normalized_data->begin();
+    while(it!=normalized_data->end()) {
+        double value = (*it);
+        (*it) = m_scale*(value/max_intensity) + m_shift;
+        ++it;
     }
 
     return normalized_data;
diff --git a/Core/Core.pro b/Core/Core.pro
index dc0a46e0e385f179ef6b046ebc52db1c263d3e80..a09bd6f7e305b26376250bed1377560be9ce0472 100644
--- a/Core/Core.pro
+++ b/Core/Core.pro
@@ -5,7 +5,7 @@ TARGET   = ScattCore
 TEMPLATE = lib
 CONFIG  += plugin # to remove versions from file name
 QT      -= core gui
-CONFIG  += BUILD_PYTHON_BOOST_MODULE # to  generate python interface
+#CONFIG  += BUILD_PYTHON_BOOST_MODULE # to  generate python interface
 
 # including common project properties
 include($$PWD/../shared.pri)
diff --git a/Core/Tools/inc/FitObject.h b/Core/Tools/inc/FitObject.h
index 054082cd91da312a0263151231207f64a063652c..16516287facbded668cca87aac964a8ee7b01d20 100644
--- a/Core/Tools/inc/FitObject.h
+++ b/Core/Tools/inc/FitObject.h
@@ -28,7 +28,7 @@
 class FitObject : public IParameterized
 {
 public:
-    FitObject(const Experiment &experiment, const OutputData<double > &real_data, const IChiSquaredModule &chi2_module=ChiSquaredModule());
+    FitObject(const Experiment &experiment, const OutputData<double > &real_data, const IChiSquaredModule &chi2_module=ChiSquaredModule(), double weight = 1.0);
     ~FitObject();
 
     //! get experiment
@@ -57,6 +57,9 @@ 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;
 
+    //! return weight of data set in chi2 calculations
+    double getWeight() const { return m_weight; }
+
 protected:
     //! initialize pool parameters, i.e. register some of class members for later access via parameter pool
     virtual void init_parameters();
@@ -68,6 +71,7 @@ private:
     Experiment *m_experiment; //! external experiment (not owned by this)
     OutputData<double > *m_real_data; //! real data
     IChiSquaredModule *m_chi2_module; //! chi2 module
+    double m_weight; //! weight of data set in chi2 calculations
 
 };
 
diff --git a/Core/Tools/inc/FitSuiteObjects.h b/Core/Tools/inc/FitSuiteObjects.h
index 88e7c526629b47b979d8b5f2d88df8448247374c..02a648ad80c665f7862d8591d246ce94e87e4fd8 100644
--- a/Core/Tools/inc/FitSuiteObjects.h
+++ b/Core/Tools/inc/FitSuiteObjects.h
@@ -42,13 +42,13 @@ public:
     size_t size() const { return m_fit_objects.size(); }
 
     //! add to kit pair of (experiment, real data) for consecutive simulation and chi2 module
-    void add(const Experiment &experiment, const OutputData<double > &real_data, const IChiSquaredModule &chi2_module);
+    void add(const Experiment &experiment, const OutputData<double > &real_data, const IChiSquaredModule &chi2_module, double weight = 1.0);
 
     //! loop through all defined experiments and run they simulation
     void runSimulation();
 
-    //! get chi squared value calculated for all pairs of (experiment, real data)
-    double getChiSquaredValue();
+    //! get sum of chi squared values for all fit objects
+    double getChiSquaredValue(int n_free_fit_parameters = 0);
 
     //! get experiment
     const Experiment *getExperiment(size_t i_item = 0) const { return m_fit_objects[check_index(i_item)]->getExperiment(); }
@@ -72,10 +72,16 @@ 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;
 
+    //! set experiment normalize flag
+    void setExperimentNormalize(bool experiment_normalize) { m_experiment_normalize = experiment_normalize; }
+
 protected:
     //! initialize pool parameters, i.e. register some of class members for later access via parameter pool
     virtual void init_parameters();
 
+    //! calculate maximum intensity in simulated data
+    double getSimulationMaxIntensity();
+
 private:
     //! disabled copy constructor and assignment operator
     FitSuiteObjects &operator=(const FitSuiteObjects &);
@@ -84,7 +90,9 @@ private:
     //! check if index inside vector bounds
     inline size_t check_index(size_t index) const { return index < m_fit_objects.size() ? index : throw OutOfBoundsException("FitSuiteKit::check() -> Index outside of range"); }
 
-    FitObjects_t m_fit_objects; //  set of experiments and corresponding real data
+    FitObjects_t m_fit_objects; //!  set of experiments and corresponding real data
+    double m_total_weight; //! sum of weights of fit sets
+    bool m_experiment_normalize;
 };
 
 
diff --git a/Core/Tools/inc/FitSuiteParameters.h b/Core/Tools/inc/FitSuiteParameters.h
index f1b90aee5c87a8755720bce251394bfbe454afa3..6a0a3711da7e963b1132c2bd46d64d66f4a9ef48 100644
--- a/Core/Tools/inc/FitSuiteParameters.h
+++ b/Core/Tools/inc/FitSuiteParameters.h
@@ -72,6 +72,9 @@ public:
     //! linking fit parameters with pool parameters
     void link_to_pool(const ParameterPool *pool);
 
+    //! return number of free parameters
+    size_t getNfreeParameters() const;
+
 private:
     //! disabled copy constructor and assignment operator
     FitSuiteParameters &operator=(const FitSuiteParameters &other);
diff --git a/Core/Tools/inc/IMinimizer.h b/Core/Tools/inc/IMinimizer.h
index a4015075d3671b786b004b7824e5d3642a21e6b8..f22fd3b63ae86449c9abc5e96b749ee7cb53b0be 100644
--- a/Core/Tools/inc/IMinimizer.h
+++ b/Core/Tools/inc/IMinimizer.h
@@ -17,6 +17,8 @@
 
 #include "FitParameter.h"
 #include <boost/function.hpp>
+#include <map>
+#include "Exceptions.h"
 
 
 //- -------------------------------------------------------------------
@@ -58,4 +60,69 @@ public:
 
 };
 
+
+
+//- -------------------------------------------------------------------
+//! @class TestMinimizer
+//! @brief Minimizer which calls minimization function once to test whole chain
+//- -------------------------------------------------------------------
+class TestMinimizer : public IMinimizer
+{
+public:
+    TestMinimizer(){}
+    virtual ~TestMinimizer(){}
+
+    //! set variable
+    virtual void setVariable(int index, const FitParameter *par) { m_values[index] = par->getValue(); }
+
+    //! set function to minimize
+    virtual void setFunction(boost::function<double(const double *)> fcn, int ndim=1) { m_fcn = fcn, m_ndim = ndim; }
+
+    //! run minimization
+    virtual void minimize()
+    {
+        std::vector<double > buffer;
+        buffer.resize(m_values.size(), 0.0);
+        for(std::map<int, double >::iterator it=m_values.begin(); it!= m_values.end(); ++it ) {
+            buffer[it->first] = it->second;
+            std::cout << " minimize(): " << it->first << " " << it->second << std::endl;
+        }
+        std::cout << "TestMinimizer::minimize() -> Info. Calling fcn" << std::endl;
+        m_fcn(&buffer[0]);
+    }
+
+    //! get number of variables to fit
+    virtual size_t getNumberOfVariables() const { return m_values.size(); }
+
+    //! return minimum function value
+    virtual double getMinValue() const { throw NotImplementedException("TestMinimizer::getMinValue() -> Not implemented. "); return 0.0; }
+
+    //! return pointer to the parameters values at the minimum
+    virtual double getValueOfVariableAtMinimum(size_t i) const
+    {
+        std::map<int, double >::const_iterator pos = m_values.find(i);
+        if(pos != m_values.end()){
+            return pos->second;
+        } else {
+            throw LogicErrorException("TestMinimizer::getValueOfVariableAtMinimum() -> Not found!");
+        }
+    }
+
+    //! return pointer to the parameters values at the minimum
+    virtual double getErrorOfVariable(size_t /* i*/)  const { throw NotImplementedException("TestMinimizer::getMinValue() -> Not implemented. "); return 0.0; }
+
+    //! clear resources (parameters) for consecutives minimizations
+    virtual void clear()  { throw NotImplementedException("TestMinimizer::getMinValue() -> Not implemented. "); }
+
+    //! print fit results
+    virtual void printResults() const  { throw NotImplementedException("TestMinimizer::getMinValue() -> Not implemented. "); }
+
+private:
+    std::map<int, double > m_values;
+    boost::function<double(const double *)> m_fcn;
+    int m_ndim;
+};
+
+
+
 #endif // IMINIMIZER_H
diff --git a/Core/Tools/src/Exceptions.cpp b/Core/Tools/src/Exceptions.cpp
index 2a8de5a244885285a27ce84ac13ecd7a44c6a867..f9a68eea06953ff2bed20bfa24e8c9f85a8dbc14 100644
--- a/Core/Tools/src/Exceptions.cpp
+++ b/Core/Tools/src/Exceptions.cpp
@@ -5,7 +5,7 @@ namespace Exceptions {
 
 void LogExceptionMessage(const std::string &message)
 {
-    std::cout << message << std::endl;
+    std::cerr << message << std::endl;
 }
 
 NotImplementedException::NotImplementedException(const std::string &message)
diff --git a/Core/Tools/src/FitObject.cpp b/Core/Tools/src/FitObject.cpp
index ee0335df06554e6aefbd1ea48b2710e5d30049ac..1ceb4844f05156705f496c949ed480929df16a46 100644
--- a/Core/Tools/src/FitObject.cpp
+++ b/Core/Tools/src/FitObject.cpp
@@ -5,10 +5,11 @@
 /* ************************************************************************* */
 // FitObject c-tors
 /* ************************************************************************* */
-FitObject::FitObject(const Experiment &experiment, const OutputData<double > &real_data, const IChiSquaredModule &chi2_module)
+FitObject::FitObject(const Experiment &experiment, const OutputData<double > &real_data, const IChiSquaredModule &chi2_module, double weight)
     : m_experiment(experiment.clone())
     , m_real_data(real_data.clone())
     , m_chi2_module(chi2_module.clone())
+    , m_weight(weight)
 {
     setName("FitObject");
     if( !m_real_data->hasSameShape(*m_experiment->getOutputData()) ) {
@@ -33,9 +34,9 @@ void FitObject::setRealData(const OutputData<double > &real_data)
     m_real_data = real_data.clone();
     if( m_experiment) {
         if( !m_real_data->hasSameShape(*m_experiment->getOutputData()) ) {
-            std::cout << "FitSuiteKit::KitItem::setRealData() -> Real data and the detector have different shape. Adjusting detector..." << std::endl;
+            std::cout << "FitObject::setRealData() -> Real data and the detector have different shape. Adjusting detector..." << std::endl;
         } else {
-            std::cout << "FitSuiteKit::KitItem::setRealData() -> Real data and the detector have same shape. No nedd to adjust detector." << std::endl;
+            std::cout << "FitObject::setRealData() -> Real data and the detector have same shape. No need to adjust detector." << std::endl;
         }
         m_experiment->setDetectorParameters(*m_real_data);
     }
diff --git a/Core/Tools/src/FitSuite.cpp b/Core/Tools/src/FitSuite.cpp
index b6e93cebb8bf1b9c2afaae887cb2e22c00b24232..e08ec9cc2abf49064404dc1ce93a277e6f6c05ae 100644
--- a/Core/Tools/src/FitSuite.cpp
+++ b/Core/Tools/src/FitSuite.cpp
@@ -70,7 +70,7 @@ void FitSuite::link_fit_parameters()
 {
     ParameterPool *pool = m_fit_objects.createParameterTree();
     m_fit_parameters.link_to_pool(pool);
-    std::cout << "XXXXXX FitSuite::link_fit_parameters() -> " << std::endl;
+    std::cout << "FitSuite::link_fit_parameters() -> Parameter pool:" << std::endl;
     std::cout << *pool << std::endl;
     std::cout << "----------------" << std::endl;
     delete pool;
@@ -155,7 +155,7 @@ double FitSuite::functionToMinimize(const double *pars_current_values)
     m_fit_objects.runSimulation();
 
     // caclulate chi2 value
-    double chi_squared = m_fit_objects.getChiSquaredValue();
+    double chi_squared = m_fit_objects.getChiSquaredValue(m_fit_parameters.getNfreeParameters());
 
     notifyObservers();
     m_n_call++;
diff --git a/Core/Tools/src/FitSuiteObjects.cpp b/Core/Tools/src/FitSuiteObjects.cpp
index 99916ff302de11cfa69ebb9c562bf19ffb43e90a..2e1493edd87cd0bdba43b1c773cb5092e9d5893f 100644
--- a/Core/Tools/src/FitSuiteObjects.cpp
+++ b/Core/Tools/src/FitSuiteObjects.cpp
@@ -2,7 +2,7 @@
 
 
 
-FitSuiteObjects::FitSuiteObjects()
+FitSuiteObjects::FitSuiteObjects() : m_total_weight(0), m_experiment_normalize(false)
 {
     setName("FitSuiteObjects");
     init_parameters();
@@ -22,9 +22,10 @@ void FitSuiteObjects::clear()
 /* ************************************************************************* */
 // add to kit pair of (experiment, real data) for consecutive simulation and chi2 module
 /* ************************************************************************* */
-void FitSuiteObjects::add(const Experiment &experiment, const OutputData<double > &real_data, const IChiSquaredModule &chi2_module)
+void FitSuiteObjects::add(const Experiment &experiment, const OutputData<double > &real_data, const IChiSquaredModule &chi2_module, double weight)
 {
-    m_fit_objects.push_back(new FitObject(experiment, real_data, chi2_module));
+    m_total_weight += weight;
+    m_fit_objects.push_back(new FitObject(experiment, real_data, chi2_module, weight));
 }
 
 
@@ -35,21 +36,47 @@ void FitSuiteObjects::runSimulation()
 {
     for(FitObjects_t::iterator it = m_fit_objects.begin(); it!= m_fit_objects.end(); ++it) {
         (*it)->getExperiment()->runSimulation();
-        (*it)->getExperiment()->normalize();
+        if(m_experiment_normalize) (*it)->getExperiment()->normalize();
     }
 }
 
 
 /* ************************************************************************* */
-// loop through all defined experiments and run they simulation
+// get sum of chi squared values for all fit objects
+// FIXME: refactor FitSuiteObjects::getChiSquaredValue()
+/* ************************************************************************* */
+double FitSuiteObjects::getChiSquaredValue(int n_free_fit_parameters)
+{
+    double chi_sum(0);
+    for(FitObjects_t::iterator it = m_fit_objects.begin(); it!= m_fit_objects.end(); ++it) {
+        IChiSquaredModule *chi = (*it)->getChiSquaredModule();
+
+        chi->setNdegreeOfFreedom( m_fit_objects.size() * (*it)->getRealData()->getAllocatedSize() - n_free_fit_parameters);
+        // normalizing datasets to the maximum intensity over all fit objects defined
+        OutputDataNormalizerScaleAndShift *data_normalizer =  dynamic_cast<OutputDataNormalizerScaleAndShift *>(chi->getOutputDataNormalizer());
+        if( data_normalizer) data_normalizer->setMaximumIntensity( getSimulationMaxIntensity() );
+
+        double weight = (*it)->getWeight()/m_total_weight;
+        double chi_squared = (weight*weight) * (*it)->calculateChiSquared();
+        chi_sum += chi_squared;
+//        std::cout << " chi " << chi_squared << " chi_sum:" << chi_sum << std::endl;
+    }
+    return chi_sum;
+}
+
+
+/* ************************************************************************* */
+// calculate maximum intensity in simulated data over all fir objects defined
 /* ************************************************************************* */
-double FitSuiteObjects::getChiSquaredValue()
+double FitSuiteObjects::getSimulationMaxIntensity()
 {
-    double chi_squared(0);
+    double max_intensity(0);
     for(FitObjects_t::iterator it = m_fit_objects.begin(); it!= m_fit_objects.end(); ++it) {
-        chi_squared += (*it)->calculateChiSquared();
+        const OutputData<double > *data = (*it)->getExperiment()->getOutputData();
+        OutputData<double >::const_iterator cit = std::max_element(data->begin(), data->end());
+        max_intensity = std::max(max_intensity, *cit);
     }
-    return chi_squared;
+    return max_intensity;
 }
 
 
diff --git a/Core/Tools/src/FitSuiteParameters.cpp b/Core/Tools/src/FitSuiteParameters.cpp
index 404e3afd031b6da0404f2964fc959bd9d708464b..7543a1f52a9c2403216ce960f1eca4a490e8dee7 100644
--- a/Core/Tools/src/FitSuiteParameters.cpp
+++ b/Core/Tools/src/FitSuiteParameters.cpp
@@ -79,6 +79,17 @@ std::vector<double > FitSuiteParameters::getValues() const
 }
 
 
+size_t FitSuiteParameters::getNfreeParameters() const
+{
+    size_t n_free(0);
+    for(parameters_t::const_iterator it=m_parameters.begin(); it!=m_parameters.end(); ++it)
+    {
+        if( !(*it)->isFixed() ) n_free++;
+    }
+    return n_free;
+}
+
+
 
 /* ************************************************************************* */
 // linking fit parameters with pool parameters
diff --git a/Core/Tools/src/OutputDataReader.cpp b/Core/Tools/src/OutputDataReader.cpp
index 98cbaa8ff15c3e6e40f01518d7e244f6b3df1d5f..64de72be79953095e9d95db9c9a1fa7b5854d147 100644
--- a/Core/Tools/src/OutputDataReader.cpp
+++ b/Core/Tools/src/OutputDataReader.cpp
@@ -14,7 +14,12 @@
 #include <boost/iostreams/filtering_streambuf.hpp>
 #include <boost/iostreams/filtering_stream.hpp>
 #include <boost/iostreams/copy.hpp>
+
+#include "Macros.h"
+GCC_DIAG_OFF(unused-parameter);
 #include <boost/iostreams/filter/gzip.hpp>
+GCC_DIAG_ON(unused-parameter);
+
 
 
 OutputData<double > *OutputDataReader::getOutputData(const std::string &file_name)
diff --git a/UnitTests/TestCore/ChiSquaredModuleTest.h b/UnitTests/TestCore/ChiSquaredModuleTest.h
new file mode 100644
index 0000000000000000000000000000000000000000..6c7cb3a82aeeeb8e0006afe87daec7c0e256af10
--- /dev/null
+++ b/UnitTests/TestCore/ChiSquaredModuleTest.h
@@ -0,0 +1,126 @@
+#ifndef CHISQUAREDMODULETEST_H
+#define CHISQUAREDMODULETEST_H
+
+#include "ChiSquaredModule.h"
+#include "IFittingDataSelector.h"
+#include "ISquaredFunction.h"
+
+#include "gtest/gtest.h"
+
+
+class ChiSquaredModuleTest : public ::testing::Test
+{
+protected:
+    ChiSquaredModuleTest();
+    virtual ~ChiSquaredModuleTest();
+
+    ChiSquaredModule m_chi_empty;
+    ChiSquaredModule m_chi_default;
+    OutputData<double > m_real_data;
+    OutputData<double > m_simul_data;
+};
+
+
+ChiSquaredModuleTest::ChiSquaredModuleTest()
+{
+    m_real_data.addAxis(new NamedVector<double>("phi_f", 0.0, 10.0, 10));
+    m_real_data.addAxis(new NamedVector<double>("alpha_f", 0.0, 10.0, 10));
+    m_real_data.setAllTo(1.0);
+    m_simul_data.copyFrom(m_real_data);
+    m_simul_data.setAllTo(1.1);
+
+    // default module with set of real and simulated data
+    m_chi_default.setRealAndSimulatedData(m_real_data, m_simul_data);
+
+}
+
+
+ChiSquaredModuleTest::~ChiSquaredModuleTest()
+{
+
+}
+
+
+TEST_F(ChiSquaredModuleTest, InitialState)
+{
+    EXPECT_EQ( NULL, m_chi_empty.getRealData());
+    EXPECT_EQ( NULL, m_chi_empty.getSimulationData());
+    EXPECT_TRUE( dynamic_cast<const SquaredFunctionDefault *>(m_chi_empty.getSquaredFunction()));
+    EXPECT_TRUE( dynamic_cast<const DefaultAllDataSelector *>(m_chi_empty.getFittingDataSelector()));
+    EXPECT_EQ( NULL, m_chi_empty.getOutputDataNormalizer());
+    EXPECT_EQ( NULL, m_chi_empty.getIntensityFunction());
+    EXPECT_EQ( double(0), m_chi_empty.getValue());
+    ASSERT_THROW(m_chi_empty.calculateChiSquared(), NullPointerException);
+    ASSERT_THROW(m_chi_empty.createChi2DifferenceMap(), NullPointerException);
+}
+
+TEST_F(ChiSquaredModuleTest, CloneOfEmpty)
+{
+    ChiSquaredModule *clone_of_empty = m_chi_empty.clone();
+    EXPECT_EQ( NULL, clone_of_empty->getRealData());
+    EXPECT_EQ( NULL, clone_of_empty->getSimulationData());
+    EXPECT_TRUE( dynamic_cast<const SquaredFunctionDefault *>(clone_of_empty->getSquaredFunction()));
+    EXPECT_TRUE( dynamic_cast<const DefaultAllDataSelector *>(clone_of_empty->getFittingDataSelector()));
+    EXPECT_EQ( NULL, clone_of_empty->getOutputDataNormalizer());
+    EXPECT_EQ( NULL, clone_of_empty->getIntensityFunction());
+    EXPECT_EQ( double(0), clone_of_empty->getValue());
+    ASSERT_THROW(clone_of_empty->calculateChiSquared(), NullPointerException);
+    ASSERT_THROW(clone_of_empty->createChi2DifferenceMap(), NullPointerException);
+    delete clone_of_empty;
+}
+
+TEST_F(ChiSquaredModuleTest, DefaultModule)
+{
+    EXPECT_FLOAT_EQ( double(0.01), m_chi_default.calculateChiSquared());
+    EXPECT_FLOAT_EQ( double(0.01), m_chi_default.getValue());
+}
+
+TEST_F(ChiSquaredModuleTest, CloneOfDefault)
+{
+    ChiSquaredModule *clone_of_default = m_chi_default.clone();
+    EXPECT_FLOAT_EQ( double(0.01), clone_of_default->calculateChiSquared());
+    EXPECT_FLOAT_EQ( double(0.01), clone_of_default->getValue());
+    clone_of_default->setNdegreeOfFreedom(1);
+    EXPECT_FLOAT_EQ( double(1.0), clone_of_default->calculateChiSquared());
+    delete clone_of_default;
+}
+
+
+TEST_F(ChiSquaredModuleTest, IsGISAXSLikeModule)
+{
+    ChiSquaredModule chi_isgisaxs;
+    OutputData<double > real_data;
+    OutputData<double > simul_data;
+    const size_t nbins(5);
+    real_data.addAxis(new NamedVector<double>("phi_f", 0.0, 1.0, nbins));
+    simul_data.addAxis(new NamedVector<double>("phi_f", 0.0, 1.0, nbins));
+    const double a_real_data[nbins] = {1., 10., 100., 10., 1. };
+    const double a_simul_data[nbins] = {10., 100., 1000., 100., 10. };
+    OutputData<double >::iterator it_real = real_data.begin();
+    OutputData<double >::iterator it_simul = simul_data.begin();
+    int index(0);
+    while(it_real != real_data.end()) {
+        *it_real = a_real_data[index];
+        *it_simul = a_simul_data[index];
+        ++index; ++it_real; ++it_simul;
+    }
+    chi_isgisaxs.setRealAndSimulatedData(real_data, simul_data);
+    OutputDataNormalizerScaleAndShift normalizer(100., 0.0);
+    chi_isgisaxs.setOutputDataNormalizer( normalizer );
+    EXPECT_FLOAT_EQ( double(0.0), chi_isgisaxs.calculateChiSquared());
+
+//    m_chi_isgisaxs.setChiSquaredFunction( SquaredFunctionWithSystematicError(1.0) );
+//    EXPECT_FLOAT_EQ( double(0.005), m_chi_isgisaxs.calculateChiSquared());
+
+//    m_chi_isgisaxs.setOutputDataNormalizer( OutputDataNormalizerScaleAndShift() );
+//    EXPECT_FLOAT_EQ( double(0.005), m_chi_isgisaxs.calculateChiSquared());
+
+
+}
+
+
+#endif // CHISQUAREDMODULETEST_H
+
+
+
+
diff --git a/UnitTests/TestCore/TestCore.pro b/UnitTests/TestCore/TestCore.pro
index 2ab675f7229c86f3cfa27a3a3f095fdfbdf454fc..f8677b63241d0ede8d53de32c41a8d2a24526e8d 100644
--- a/UnitTests/TestCore/TestCore.pro
+++ b/UnitTests/TestCore/TestCore.pro
@@ -19,7 +19,8 @@ HEADERS += \
     NamedVectorTest.h \
     OutputDataTest.h \
     OutputDataIteratorTest.h \
-    GISASExperimentTest.h
+    GISASExperimentTest.h \
+    ChiSquaredModuleTest.h
 
 OBJECTS_DIR = obj
 
@@ -68,4 +69,4 @@ for(dep, MY_DEPENDENCY_LIB) {
 ###############################################################################
 # runs automatically tests right after linking
 ###############################################################################
-QMAKE_POST_LINK = ./$(TARGET)
+QMAKE_POST_LINK = ./$(TARGET) 2> /dev/null
diff --git a/UnitTests/TestCore/main.cpp b/UnitTests/TestCore/main.cpp
index 10af4c472ed6cab820bcc8bdad023c139f5683f2..17c20c1cc91f6c5b196c96f90665c19bb398a082 100644
--- a/UnitTests/TestCore/main.cpp
+++ b/UnitTests/TestCore/main.cpp
@@ -1,6 +1,7 @@
 #include "gtest/gtest.h"
 
 #include "BeamTest.h"
+#include "ChiSquaredModuleTest.h"
 #include "DetectorTest.h"
 #include "ExperimentTest.h"
 #include "GISASExperimentTest.h"