diff --git a/App/inc/TestIsGISAXS9.h b/App/inc/TestIsGISAXS9.h
index 70699483b98a53e0ba76640e2b61cbbba75f8c0d..86260bc4665d8eb91c8d2dc6759415c219c42479 100644
--- a/App/inc/TestIsGISAXS9.h
+++ b/App/inc/TestIsGISAXS9.h
@@ -17,6 +17,7 @@
 #include "IFunctionalTest.h"
 #include "OutputData.h"
 #include "ISample.h"
+#include "SafePointerVector.h"
 
 
 //- -------------------------------------------------------------------
@@ -34,7 +35,7 @@ public:
 
     void clear();
 private:
-    std::vector<OutputData<double> *> m_results;
+    SafePointerVector<OutputData<double> > m_results;
 };
 
 
diff --git a/App/src/IsGISAXSTools.cpp b/App/src/IsGISAXSTools.cpp
index 3a979480e9bf842dbf6138d1045b8cd3a675444b..4310e8c220d8a3a9d7954369c17a5863218a97e4 100644
--- a/App/src/IsGISAXSTools.cpp
+++ b/App/src/IsGISAXSTools.cpp
@@ -90,7 +90,7 @@ TH2D *IsGISAXSTools::getOutputDataTH2D(const OutputData<double>& output, const s
 
     // 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 AxisDouble *axis = output.getAxis(i_axis);
+        const IAxis *axis = output.getAxis(i_axis);
         if( !axis ) throw("IsGISAXSTools::getOutputDataTH123D() -> Error! Can't cast axis");
         double dx(0);
         haxises[i_axis].nbins = axis->getSize();
@@ -154,7 +154,7 @@ TH1 *IsGISAXSTools::getOutputDataTH123D(const OutputData<double>& output, const
 
     // 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 AxisDouble *axis = output.getAxis(i_axis);
+        const IAxis *axis = output.getAxis(i_axis);
         if( !axis ) throw("IsGISAXSTools::getOutputDataTH123D() -> Error! Can't cast axis");
         double dx(0);
         haxises[i_axis].nbins = axis->getSize();
@@ -465,8 +465,8 @@ void IsGISAXSTools::exportOutputDataInVectors2D(const OutputData<double> &output
 {
     if (output_data.getRank() != 2) return;
 
-    const AxisDouble *p_axis0 = output_data.getAxis(0);
-    const AxisDouble *p_axis1 = output_data.getAxis(1);
+    const IAxis *p_axis0 = output_data.getAxis(0);
+    const IAxis *p_axis1 = output_data.getAxis(1);
     //std::string axis0_name = p_axis0->getName();
     //std::string axis1_name = p_axis1->getName();
     size_t axis0_size = p_axis0->getSize();
diff --git a/App/src/TestFormFactor.cpp b/App/src/TestFormFactor.cpp
index 45df3456288963c44fe0d7b24c97814b9e64126f..acd7f3844d91fa8e9a9445f4a45762c1ee8412b3 100644
--- a/App/src/TestFormFactor.cpp
+++ b/App/src/TestFormFactor.cpp
@@ -27,8 +27,8 @@ TestFormFactor::~TestFormFactor()
 void TestFormFactor::execute()
 {
     OutputData<double>::iterator it = mp_intensity_output->begin();
-    const AxisDouble *p_y_axis = mp_intensity_output->getAxis("detector y-axis");
-    const AxisDouble *p_z_axis = mp_intensity_output->getAxis("detector z-axis");
+    const IAxis *p_y_axis = mp_intensity_output->getAxis("detector y-axis");
+    const IAxis *p_z_axis = mp_intensity_output->getAxis("detector z-axis");
     double lambda = 1.0;
     double alpha_i = 0.2*M_PI/180.0;
     cvector_t k_i;
@@ -53,8 +53,8 @@ void TestFormFactor::draw()
     TCanvas *c1 = new TCanvas("c1_test_formfactor", "Cylinder Formfactor", 0, 0, 1024, 768);
     (void)c1;
 
-    const AxisDouble *p_y_axis = mp_intensity_output->getAxis("detector y-axis");
-    const AxisDouble *p_z_axis = mp_intensity_output->getAxis("detector z-axis");
+    const IAxis *p_y_axis = mp_intensity_output->getAxis("detector y-axis");
+    const IAxis *p_z_axis = mp_intensity_output->getAxis("detector z-axis");
     size_t y_size = p_y_axis->getSize();
     size_t z_size = p_z_axis->getSize();
     double y_start = (*p_y_axis)[0];
diff --git a/App/src/TestFresnelCoeff.cpp b/App/src/TestFresnelCoeff.cpp
index 2476675cb306a0f28bf5c2f08a026f1b9508d3a9..671108d6276cfd03db2e05aa99d5b8a77b0f0d4f 100644
--- a/App/src/TestFresnelCoeff.cpp
+++ b/App/src/TestFresnelCoeff.cpp
@@ -268,7 +268,7 @@ void TestFresnelCoeff::draw_roughness_set()
     size_t ncoeffs = 2;
     enum key_coeffs { kCoeffR, kCoeffT};
 
-    const AxisDouble *p_rough = mp_coeffs->getAxis("roughness");
+    const IAxis *p_rough = mp_coeffs->getAxis("roughness");
     size_t nroughness = p_rough->getSize();
 
 
diff --git a/App/src/TestFumiliLMA.cpp b/App/src/TestFumiliLMA.cpp
index 6ab407368921a163737af8057203d5d2eaa4232b..dc5cf8a1b3a51e52c9cb1face8c977d9e02f1922 100644
--- a/App/src/TestFumiliLMA.cpp
+++ b/App/src/TestFumiliLMA.cpp
@@ -165,8 +165,8 @@ void TestFumiliLMA::FillOutputDataFromFunction(OutputData<double> &data, TF2 *fu
     data.setAllTo(0.0);
 
     OutputData<double>::iterator it=data.begin();
-    const AxisDouble *xaxis = data.getAxis(0);
-    const AxisDouble *yaxis = data.getAxis(1);
+    const IAxis *xaxis = data.getAxis(0);
+    const IAxis *yaxis = data.getAxis(1);
     while( it!= data.end() )
     {
         size_t index_x = data.toCoordinates(it.getIndex())[0];
@@ -185,8 +185,8 @@ double MyChi2Function::DataElement(const double *pars, unsigned int index, doubl
     std::cout << " DataElement() -> " << g << " " << index;
     for(int ipar=0; ipar<m_test->m_func->GetNpar(); ++ipar) std::cout << " " << pars[ipar];
     std::cout << std::endl;
-    const AxisDouble *xaxis = m_test->m_real_data->getAxis(0);
-    const AxisDouble *yaxis = m_test->m_real_data->getAxis(1);
+    const IAxis *xaxis = m_test->m_real_data->getAxis(0);
+    const IAxis *yaxis = m_test->m_real_data->getAxis(1);
     size_t index_x = m_test->m_real_data->toCoordinates(index)[0];
     size_t index_y = m_test->m_real_data->toCoordinates(index)[1];
     double x = (*xaxis)[index_x];
diff --git a/App/src/TestIsGISAXS12.cpp b/App/src/TestIsGISAXS12.cpp
index 8157ba801ca60aadbe5a729486b9128d97ca78b8..21ba23fe8eb9e1e1300690debf4c3a7fd5d189d3 100644
--- a/App/src/TestIsGISAXS12.cpp
+++ b/App/src/TestIsGISAXS12.cpp
@@ -210,7 +210,7 @@ void TestIsGISAXS12::run_isgisaxs_fit()
     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);
+        c2->cd((int)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");
@@ -234,7 +234,7 @@ void TestIsGISAXS12::run_isgisaxs_fit()
         OutputData<double > *real = obj->getChiSquaredModule()->getRealData()->clone();
         OutputData<double > *simul = obj->getChiSquaredModule()->getSimulationData()->clone();
 
-        c2->cd(i_set+3);
+        c2->cd((int)(i_set+3));
         *simul /= *real;
         TH1D *hratio = IsGISAXSTools::getOutputDataScanHist(*simul,"gisasfw_real_simul_ratio");
         hratio->DrawCopy();
@@ -271,7 +271,7 @@ void TestIsGISAXS12::run_test_chimodule()
     OutputDataNormalizerScaleAndShift normalizer(1.31159E+05, -8.10009E-02);
 
     double max_intensity(0);
-    for(size_t i=0; i<isgi_results.size(); ++i) {
+    for(int i=0; i<(int)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);
     }
@@ -281,10 +281,10 @@ void TestIsGISAXS12::run_test_chimodule()
     chiModule.setOutputDataNormalizer( normalizer );
 
     double chi_sum(0);
-    for(size_t i=0; i<isgi_scans.size(); ++i) {
+    for(int i=0; i<(int)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);
+        chiModule.setNdegreeOfFreedom((int)(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;
@@ -322,7 +322,7 @@ void TestIsGISAXS12::plot_isgisaxs_data()
     leg1->SetBorderSize(1);
     leg1->SetFillStyle(0);
 
-    for(size_t i_set=0; i_set<isgi_scans.size(); ++i_set) {
+    for(int i_set=0; i_set<(int)isgi_scans.size(); ++i_set) {
         c1->cd(1+i_set); gPad->SetLogy();
         TH1D *hdata = IsGISAXSTools::getOutputDataScanHist(*isgi_scans[i_set], "data");
         hdata->DrawCopy();
@@ -339,7 +339,7 @@ void TestIsGISAXS12::plot_isgisaxs_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) {
+    for(int i_set=0; i_set<(int)isgi_scans.size(); ++i_set) {
         c1->cd(3+i_set); gPad->SetLogy();
         TH1D *hdata = IsGISAXSTools::getOutputDataScanHist(*isgi_results[i_set], "data");
         hdata->SetLineColor(kRed);
@@ -357,7 +357,7 @@ void TestIsGISAXS12::plot_isgisaxs_data()
     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) {
+    for(int i_set=0; i_set<(int)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");
@@ -426,7 +426,7 @@ void TestIsGISAXS12::run_test_minimizer()
     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) {
+    for(int i_set=0; i_set<(int)isgi_results.size(); ++i_set) {
         c1->cd(1+i_set);
         gPad->SetLogy();
         TH1D *hdata = IsGISAXSTools::getOutputDataScanHist(*isgi_results[i_set], "data");
@@ -446,7 +446,7 @@ void TestIsGISAXS12::run_test_minimizer()
     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) {
+    for(int i_set=0; i_set<(int)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];
@@ -764,8 +764,8 @@ 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 AxisDouble *axis = data[i_set]->getAxis(i_axis);
+        for(size_t i_axis=0; i_axis<data[(int)i_set]->getNdimensions(); ++i_axis) {
+            const IAxis *axis = data[(int)i_set]->getAxis(i_axis);
             std::cout << "( " << axis->getName() << ", " << axis->getSize() << ", " << axis->getMin() << ", " << axis->getMax() << " )   ";
         }
         std::cout << std::endl;
diff --git a/App/src/TestIsGISAXS8.cpp b/App/src/TestIsGISAXS8.cpp
index afd55fc599c36efcd4d0b4254274f8a1710c6886..bf731c5e799e68e6adb3cada1fc932b7245a3357 100644
--- a/App/src/TestIsGISAXS8.cpp
+++ b/App/src/TestIsGISAXS8.cpp
@@ -17,8 +17,6 @@ TestIsGISAXS8::TestIsGISAXS8() : IFunctionalTest("TestIsGISAXS8")
 
 void TestIsGISAXS8::execute()
 {
-    gsl_set_error_handler_off();
-
     GISASExperiment experiment(mp_options);
     experiment.setDetectorParameters(100, 0.0*Units::degree, 2.0*Units::degree, 100, 0.0*Units::degree, 2.0*Units::degree, true);
     experiment.setBeamParameters(1.0*Units::angstrom, -0.2*Units::degree, 0.0*Units::degree);
diff --git a/App/src/TestIsGISAXS9.cpp b/App/src/TestIsGISAXS9.cpp
index ad7c418235761e42d18af6022af3976a66cc63e7..a5c933d00dd1718991b6d5783a779f9ce8f328ad 100644
--- a/App/src/TestIsGISAXS9.cpp
+++ b/App/src/TestIsGISAXS9.cpp
@@ -22,9 +22,6 @@ TestIsGISAXS9::~TestIsGISAXS9()
 
 void TestIsGISAXS9::clear()
 {
-    for(std::vector<OutputData<double> *>::iterator it=m_results.begin(); it!=m_results.end(); ++it) {
-        delete (*it);
-    }
     m_results.clear();
 }
 
@@ -38,22 +35,25 @@ void TestIsGISAXS9::execute()
     experiment.setDetectorParameters(100, 0.0*Units::degree, 2.0*Units::degree, 100, 0.0*Units::degree, 2.0*Units::degree, true);
     experiment.setBeamParameters(1.0*Units::angstrom, -0.2*Units::degree, 0.0*Units::degree);
 
+    MultiLayer *p_sample;
+
     // pyramid
-    MultiLayer *sample = dynamic_cast<MultiLayer *>(SampleFactory::instance().createItem("IsGISAXS9_Pyramid"));
-    experiment.setSample(*sample);
+    p_sample = dynamic_cast<MultiLayer *>(SampleFactory::instance().createItem("IsGISAXS9_Pyramid"));
+    experiment.setSample(*p_sample);
     experiment.runSimulation();
     OutputData<double> *data = experiment.getOutputDataClone();
     m_results.push_back( data );
     IsGISAXSTools::writeOutputDataToFile(*m_results.back(), Utils::FileSystem::GetHomePath()+"./Examples/IsGISAXS_examples/ex-9/this_pyramid_Z0.ima");
+    delete p_sample;
 
     // rotated pyramid
-    sample = dynamic_cast<MultiLayer *>(SampleFactory::instance().createItem("IsGISAXS9_RotatedPyramid"));
-    experiment.setSample(*sample);
+    p_sample = dynamic_cast<MultiLayer *>(SampleFactory::instance().createItem("IsGISAXS9_RotatedPyramid"));
+    experiment.setSample(*p_sample);
     experiment.runSimulation();
     data = experiment.getOutputDataClone();
     m_results.push_back( data );
     IsGISAXSTools::writeOutputDataToFile(*m_results.back(), Utils::FileSystem::GetHomePath()+"./Examples/IsGISAXS_examples/ex-9/this_pyramid_Z45.ima");
-
+    delete p_sample;
 }
 
 
diff --git a/App/src/TestMesoCrystal2.cpp b/App/src/TestMesoCrystal2.cpp
index 083b28231f99e8edd37f36b2417d12d08c1197c6..c6e2a5e20d63cec5633d430ab81214c398da09e4 100644
--- a/App/src/TestMesoCrystal2.cpp
+++ b/App/src/TestMesoCrystal2.cpp
@@ -226,8 +226,8 @@ void TestMesoCrystal2::initializeExperiment(const OutputData<double> *output_dat
         mp_experiment->setDetectorParameters(200, 0.3*Units::degree, 0.073, 200, -0.4*Units::degree, 0.066);
     } else {
         // if there is output_data as input parameter, build detector using output_data axises
-        const AxisDouble *axis0 = output_data->getAxis(0);
-        const AxisDouble *axis1 = output_data->getAxis(1);
+        const IAxis *axis0 = output_data->getAxis(0);
+        const IAxis *axis1 = output_data->getAxis(1);
         //std::cout << axis0->getSize() << " " << axis0->getMin() << " " << axis0->getMax() << " " << axis1->getSize() << " " << axis1->getMin() << " " << axis1->getMax() << std::endl;
         mp_experiment->setDetectorParameters(axis0->getSize(), axis0->getMin(), axis0->getMax(), axis1->getSize(), axis1->getMin(), axis1->getMax());
     }
diff --git a/App/src/TestMiscellaneous.cpp b/App/src/TestMiscellaneous.cpp
index c2ddc317ccc0612eeaf31f0d2c843858c1afd3bc..1add96973a7b1933b19e0cb9d0046ac9b077eef7 100644
--- a/App/src/TestMiscellaneous.cpp
+++ b/App/src/TestMiscellaneous.cpp
@@ -300,7 +300,7 @@ void TestMiscellaneous::test_DoubleToComplexInterpolatingFunction()
 
     OpticalFresnel fresnelCalculator;
 
-    const AxisDouble *p_alpha_axis = data_alpha->getAxis("alpha_f");
+    const IAxis *p_alpha_axis = data_alpha->getAxis("alpha_f");
     std::map<double, OpticalFresnel::MultiLayerCoeff_t> fresnel_coeff_map;
     for (size_t i=0; i<p_alpha_axis->getSize(); ++i) {
         double angle = (*p_alpha_axis)[i];
diff --git a/App/src/TestRootTree.cpp b/App/src/TestRootTree.cpp
index a2e50f9aea6a01e5b730d536a383673d9a061f62..ffbd26dfa4e67d8361b0b9cac58aefbf752f740c 100644
--- a/App/src/TestRootTree.cpp
+++ b/App/src/TestRootTree.cpp
@@ -259,8 +259,8 @@ void TestRootTree::simple_write()
 
         mp_data = mp_experiment->getOutputDataClone();
         // accessing to scattering data
-        const AxisDouble *axis0 = mp_data->getAxis(0);
-        const AxisDouble *axis1 = mp_data->getAxis(1);
+        const IAxis *axis0 = mp_data->getAxis(0);
+        const IAxis *axis1 = mp_data->getAxis(1);
         std::string axis0_name = axis0->getName();
         std::string axis1_name = axis1->getName();
 
diff --git a/Core/Algorithms/inc/Detector.h b/Core/Algorithms/inc/Detector.h
index 26ad22825b35bf4064d4dd8d6d5395d95149be79..8bc3ad098c2a8b40c8b42574981a9d9d428365a2 100644
--- a/Core/Algorithms/inc/Detector.h
+++ b/Core/Algorithms/inc/Detector.h
@@ -15,7 +15,9 @@
 //! @date   Jun 21, 2012
 
 #include "IDetectorResolution.h"
+#include "DetectorParameters.h"
 #include "IParameterized.h"
+#include "SafePointerVector.h"
 
 
 #include <vector>
@@ -33,8 +35,9 @@ public:
 
 	virtual ~Detector();
 
-	void addAxis(const AxisDouble &axis);
-	AxisDouble getAxis(size_t index) const;
+	void addAxis(const IAxis &axis);
+	void addAxis(const AxisParameters &axis_params);
+	const IAxis &getAxis(size_t index) const;
 	size_t getDimension() const { return m_axes.size(); }
 	void clear();
     void setDetectorResolution(IDetectorResolution *p_detector_resolution) { delete mp_detector_resolution; mp_detector_resolution = p_detector_resolution; }
@@ -52,7 +55,10 @@ private:
     //! swap function
     void swapContent(Detector &other);
 
-	std::vector<AxisDouble > m_axes;
+    //! initialize axis the way IsGISAXS does
+    void initializeAnglesIsgisaxs(AxisDouble *p_axis, const TSampledRange<double> &axis_range);
+
+    SafePointerVector<IAxis> m_axes;
 	IDetectorResolution *mp_detector_resolution;
 };
 
diff --git a/Core/Algorithms/inc/DetectorParameters.h b/Core/Algorithms/inc/DetectorParameters.h
new file mode 100644
index 0000000000000000000000000000000000000000..25e9bbd2d3f7058812c0e35434d51e0f2bdaebb5
--- /dev/null
+++ b/Core/Algorithms/inc/DetectorParameters.h
@@ -0,0 +1,54 @@
+#ifndef DETECTORPARAMETERS_H_
+#define DETECTORPARAMETERS_H_
+// ********************************************************************
+// * The BornAgain project                                            *
+// * Simulation of neutron and x-ray scattering at grazing incidence  *
+// *                                                                  *
+// * LICENSE AND DISCLAIMER                                           *
+// * Lorem ipsum dolor sit amet, consectetur adipiscing elit.  Mauris *
+// * eget quam orci. Quisque  porta  varius  dui,  quis  posuere nibh *
+// * mollis quis. Mauris commodo rhoncus porttitor.                   *
+// ********************************************************************
+//! @file   DetectorParameters.h
+//! @brief  Definition of DetectorParameters class
+//! @author Scientific Computing Group at FRM II
+//! @date   Dec 12, 2012
+
+#include "TRange.h"
+
+//- -------------------------------------------------------------------
+//! @class AxisParameters
+//! @brief Definition of AxisParameters class to store parameters
+//! for specifying an axis' data
+//- -------------------------------------------------------------------
+struct AxisParameters
+{
+    AxisParameters();
+    std::string m_name;
+    TSampledRange<double> m_range;
+    enum {
+        E_DEFAULT,
+        E_ISGISAXS,
+    } m_sample_method;
+};
+
+inline AxisParameters::AxisParameters()
+: m_name("")
+, m_range(0, 0.0, 0.0)
+, m_sample_method(AxisParameters::E_DEFAULT)
+{
+}
+
+//- -------------------------------------------------------------------
+//! @class DetectorParameters
+//! @brief Definition of DetectorParameters class to store parameters
+//! for specifying a 2D detector
+//- -------------------------------------------------------------------
+struct DetectorParameters
+{
+    AxisParameters m_phi_params;
+    AxisParameters m_alpha_params;
+};
+
+#endif /* DETECTORPARAMETERS_H_ */
+
diff --git a/Core/Algorithms/inc/GISASExperiment.h b/Core/Algorithms/inc/GISASExperiment.h
index 18deb506bfbace1ea2c18a6465beb7ff637fca4e..c2a95bc5f60ad2e557c4e4496ef53dff9dafa15f 100644
--- a/Core/Algorithms/inc/GISASExperiment.h
+++ b/Core/Algorithms/inc/GISASExperiment.h
@@ -16,6 +16,7 @@
 
 
 #include "Experiment.h"
+#include "DetectorParameters.h"
 #include "IResolutionFunction2D.h"
 
 
@@ -40,12 +41,16 @@ public:
     void setDetectorParameters(size_t n_phi, double phi_f_min, double phi_f_max,
             size_t n_alpha, double alpha_f_min, double alpha_f_max, bool isgisaxs_style=false);
 
-	void setDetectorResolutionFunction(IResolutionFunction2D *p_resolution_function);
+    void setDetectorParameters(const DetectorParameters &params);
+
+    void setDetectorResolutionFunction(IResolutionFunction2D *p_resolution_function);
 
 	void smearIntensityFromZAxisTilting();
 
     virtual GISASExperiment *clone() const;
 
+    static const std::string PHI_AXIS_NAME;
+    static const std::string ALPHA_AXIS_NAME;
 protected:
     // hiding copy constructor and disabling assignment operator
     GISASExperiment(const GISASExperiment &other);
@@ -55,13 +60,11 @@ private:
     //! initialize pool parameters, i.e. register some of class members for later access via parameter pool
     virtual void init_parameters();
 
-	void initializeAnglesIsgisaxs(AxisDouble *p_axis, double start, double end, size_t size);
 	double getSolidAngle(size_t index) const;
 	double deltaAlpha(double alpha, double zeta) const;
 	double deltaPhi(double alpha, double phi, double zeta);
 	void createZetaAndProbVectors(std::vector<double> &zetas, std::vector<double> &probs, size_t nbr_zetas, double zeta_sigma);
 	void addToIntensityMap(double alpha, double phi, double value);
-	int findClosestIndex(const AxisDouble *p_axis, double value);
 };
 
 #endif /* GISASEXPERIMENT_H_ */
diff --git a/Core/Algorithms/src/ConvolutionDetectorResolution.cpp b/Core/Algorithms/src/ConvolutionDetectorResolution.cpp
index a77ee5a546764083e17759b78477ce1bf2cb7655..ecaac74237405286f944caca8e2cce51423c1659 100644
--- a/Core/Algorithms/src/ConvolutionDetectorResolution.cpp
+++ b/Core/Algorithms/src/ConvolutionDetectorResolution.cpp
@@ -98,7 +98,7 @@ void ConvolutionDetectorResolution::apply1dConvolution(OutputData<double>* p_int
     if (p_intensity_map->getRank() != 1) {
         throw LogicErrorException("ConvolutionDetectorResolution::apply1dConvolution() -> Error! Number of axes for intensity map does not correspond to the dimension of the map.");
     }
-    const AxisDouble *p_axis = p_intensity_map->getAxis(0);
+    const IAxis *p_axis = p_intensity_map->getAxis(0);
     // Construct source vector from original intensity map
     std::vector<double> source_vector = p_intensity_map->getRawDataVector();
     size_t data_size = source_vector.size();
@@ -131,8 +131,8 @@ void ConvolutionDetectorResolution::apply2dConvolution(OutputData<double>* p_int
     if (p_intensity_map->getRank() != 2) {
         throw LogicErrorException("ConvolutionDetectorResolution::apply2dConvolution() -> Error! Number of axes for intensity map does not correspond to the dimension of the map.");
     }
-    const AxisDouble *p_axis_1 = p_intensity_map->getAxis(0);
-    const AxisDouble *p_axis_2 = p_intensity_map->getAxis(1);
+    const IAxis *p_axis_1 = p_intensity_map->getAxis(0);
+    const IAxis *p_axis_2 = p_intensity_map->getAxis(1);
     size_t axis_size_1 = p_axis_1->getSize();
     size_t axis_size_2 = p_axis_2->getSize();
     if (axis_size_1 < 2 || axis_size_2 < 2) {
diff --git a/Core/Algorithms/src/Detector.cpp b/Core/Algorithms/src/Detector.cpp
index 133d45c58a56bf4a4e1c836127757e0c2d45f003..df8d67a39bf96182c5ee66e1037e3de4e9883322 100644
--- a/Core/Algorithms/src/Detector.cpp
+++ b/Core/Algorithms/src/Detector.cpp
@@ -1,4 +1,6 @@
 #include "Detector.h"
+#include "AxisBin.h"
+#include "AxisDouble.h"
 #include "Exceptions.h"
 
 
@@ -47,15 +49,39 @@ void Detector::swapContent(Detector &other)
 /* ************************************************************************* */
 // other methods
 /* ************************************************************************* */
-void Detector::addAxis(const AxisDouble &axis)
+void Detector::addAxis(const IAxis &axis)
 {
-	m_axes.push_back(axis);
+	m_axes.push_back(axis.clone());
 }
 
-AxisDouble Detector::getAxis(size_t index) const
+void Detector::addAxis(const AxisParameters &axis_params)
+{
+    IAxis *p_new_axis(0);
+    switch (axis_params.m_sample_method)
+    {
+    case AxisParameters::E_DEFAULT:
+    {
+        p_new_axis = new AxisBin(axis_params.m_name, axis_params.m_range.getNSamples(),
+                axis_params.m_range.getMin(), axis_params.m_range.getMax());
+        break;
+    }
+    case AxisParameters::E_ISGISAXS:
+    {
+        AxisDouble *p_axis = new AxisDouble(axis_params.m_name);
+        initializeAnglesIsgisaxs(p_axis, axis_params.m_range);
+        p_new_axis = p_axis;
+        break;
+    }
+    default:
+        throw RuntimeErrorException("Invalid sample method for axis.");
+    }
+    if (p_new_axis) m_axes.push_back(p_new_axis);
+}
+
+const IAxis &Detector::getAxis(size_t index) const
 {
 	if (isCorrectAxisIndex(index)) {
-		return m_axes[index];
+		return *m_axes[index];
 	}
 	throw OutOfBoundsException("Not so many axes in this detector.");
 }
@@ -94,3 +120,13 @@ std::string Detector::addParametersToExternalPool(std::string path,
 void Detector::init_parameters()
 {
 }
+
+void Detector::initializeAnglesIsgisaxs(AxisDouble* p_axis, const TSampledRange<double>& axis_range)
+{
+    double start_sin = std::sin(axis_range.getMin());
+    double end_sin = std::sin(axis_range.getMax());
+    double step = (end_sin-start_sin)/(axis_range.getNSamples()-1);
+    for(size_t i=0; i<axis_range.getNSamples(); ++i) {
+        p_axis->push_back(std::asin(start_sin + step*i));
+    }
+}
diff --git a/Core/Algorithms/src/Experiment.cpp b/Core/Algorithms/src/Experiment.cpp
index acd279d1e8d8e3f678efce2a97549d55b05b6e89..2367c8a1ac34525cb0b3404356a08d889d802878 100644
--- a/Core/Algorithms/src/Experiment.cpp
+++ b/Core/Algorithms/src/Experiment.cpp
@@ -87,11 +87,7 @@ void Experiment::normalize()
 {
     double incident_intensity = m_beam.getIntensity();
     if (!m_is_normalized && incident_intensity!=1.0) {
-        OutputData<double>::iterator it = m_intensity_map.begin();
-        while (it != m_intensity_map.end()) {
-            *it *= incident_intensity;
-            ++it;
-        }
+        m_intensity_map.scaleAll(incident_intensity);
         m_is_normalized = true;
     }
 }
@@ -191,7 +187,7 @@ 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;
     m_detector.clear();
     for(size_t i_axis=0; i_axis<output_data.getNdimensions(); ++i_axis) {
-        const AxisDouble *axis = output_data.getAxis(i_axis);
+        const IAxis *axis = output_data.getAxis(i_axis);
         m_detector.addAxis(*axis);
     }
     updateIntensityMapAxes();
diff --git a/Core/Algorithms/src/GISASExperiment.cpp b/Core/Algorithms/src/GISASExperiment.cpp
index d2add40bcf771fb8a2deb4eb0b693ed86e5a9acc..70235f2dfd23025b4f1e7c3178506317efaf1531 100644
--- a/Core/Algorithms/src/GISASExperiment.cpp
+++ b/Core/Algorithms/src/GISASExperiment.cpp
@@ -35,6 +35,8 @@ GISASExperiment::GISASExperiment(const GISASExperiment &other) : Experiment(othe
 
 }
 
+const std::string GISASExperiment::PHI_AXIS_NAME = "phi_f";
+const std::string GISASExperiment::ALPHA_AXIS_NAME = "alpha_f";
 
 /* ************************************************************************* */
 // clone method
@@ -147,25 +149,33 @@ void GISASExperiment::normalize()
 void GISASExperiment::setDetectorParameters(size_t n_phi, double phi_f_min, double phi_f_max,
                                             size_t n_alpha, double alpha_f_min, double alpha_f_max, bool isgisaxs_style)
 {
-    const std::string s_phi_f("phi_f");
-    const std::string s_alpha_f("alpha_f");
-
-    m_detector.clear();
-    AxisDouble phi_axis(s_phi_f);
-    AxisDouble alpha_axis(s_alpha_f);
+    AxisParameters phi_params;
+    phi_params.m_name = PHI_AXIS_NAME;
+    phi_params.m_range = TSampledRange<double>(n_phi, phi_f_min, phi_f_max);
+    AxisParameters alpha_params;
+    alpha_params.m_name = ALPHA_AXIS_NAME;
+    alpha_params.m_range = TSampledRange<double>(n_alpha, alpha_f_min, alpha_f_max);
     if (isgisaxs_style) {
-        initializeAnglesIsgisaxs(&phi_axis, phi_f_min, phi_f_max, n_phi);
-        initializeAnglesIsgisaxs(&alpha_axis, alpha_f_min, alpha_f_max, n_alpha);
+        phi_params.m_sample_method = AxisParameters::E_ISGISAXS;
+        alpha_params.m_sample_method = AxisParameters::E_ISGISAXS;
     }
     else {
-        phi_axis.initElements(n_phi, phi_f_min, phi_f_max);
-        alpha_axis.initElements(n_alpha, alpha_f_min, alpha_f_max);
+        phi_params.m_sample_method = AxisParameters::E_DEFAULT;
+        alpha_params.m_sample_method = AxisParameters::E_DEFAULT;
     }
-    m_detector.addAxis(phi_axis);
-    m_detector.addAxis(alpha_axis);
-    updateIntensityMapAxes();
+    DetectorParameters detector_params = { phi_params, alpha_params };
+    setDetectorParameters(detector_params);
 }
 
+void GISASExperiment::setDetectorParameters(const DetectorParameters &params)
+{
+    m_detector.clear();
+
+    m_detector.addAxis(params.m_phi_params);
+    m_detector.addAxis(params.m_alpha_params);
+
+    updateIntensityMapAxes();
+}
 
 void GISASExperiment::setDetectorResolutionFunction(IResolutionFunction2D *p_resolution_function)
 {
@@ -174,9 +184,6 @@ void GISASExperiment::setDetectorResolutionFunction(IResolutionFunction2D *p_res
 
 void GISASExperiment::smearIntensityFromZAxisTilting()
 {
-    const std::string s_phi_f("phi_f");
-    const std::string s_alpha_f("alpha_f");
-
     size_t nbr_zetas = 5;
     double zeta_sigma = 45.0*Units::degree;
     std::vector<double> zetas;
@@ -187,8 +194,8 @@ void GISASExperiment::smearIntensityFromZAxisTilting()
     m_intensity_map.setAllTo(0.0);
     OutputData<double>::const_iterator it_clone = p_clone->begin();
     while (it_clone != p_clone->end()) {
-        double old_phi = p_clone->getValueOfAxis(s_phi_f, it_clone.getIndex());
-        double old_alpha = p_clone->getValueOfAxis(s_alpha_f, it_clone.getIndex());
+        double old_phi = p_clone->getValueOfAxis(PHI_AXIS_NAME, it_clone.getIndex());
+        double old_alpha = p_clone->getValueOfAxis(ALPHA_AXIS_NAME, it_clone.getIndex());
         for (size_t zeta_index=0; zeta_index<zetas.size(); ++zeta_index) {
             double newphi = old_phi + deltaPhi(old_alpha, old_phi, zetas[zeta_index]);
             double newalpha = old_alpha + deltaAlpha(old_alpha, zetas[zeta_index]);
@@ -202,27 +209,13 @@ void GISASExperiment::init_parameters()
 {
 }
 
-void GISASExperiment::initializeAnglesIsgisaxs(AxisDouble *p_axis, double start, double end, size_t size) {
-    double start_sin = std::sin(start);
-    double end_sin = std::sin(end);
-    double step = (end_sin-start_sin)/(size-1);
-    for(size_t i=0; i<size; ++i) {
-        p_axis->push_back(std::asin(start_sin + step*i));
-    }
-    return;
-}
-
-
 double GISASExperiment::getSolidAngle(size_t index) const
 {
-    const std::string s_phi_f("phi_f");
-    const std::string s_alpha_f("alpha_f");
-
-    const AxisDouble *p_alpha_axis = m_intensity_map.getAxis(s_alpha_f);
-    const AxisDouble *p_phi_axis = m_intensity_map.getAxis(s_phi_f);
-    size_t alpha_index = m_intensity_map.getIndexOfAxis(s_alpha_f, index);
+    const IAxis *p_alpha_axis = m_intensity_map.getAxis(ALPHA_AXIS_NAME);
+    const IAxis *p_phi_axis = m_intensity_map.getAxis(PHI_AXIS_NAME);
+    size_t alpha_index = m_intensity_map.getIndexOfAxis(ALPHA_AXIS_NAME, index);
     size_t alpha_size = p_alpha_axis->getSize();
-    size_t phi_index = m_intensity_map.getIndexOfAxis(s_phi_f, index);
+    size_t phi_index = m_intensity_map.getIndexOfAxis(PHI_AXIS_NAME, index);
     size_t phi_size = p_phi_axis->getSize();
     if (alpha_size<2 && phi_size<2) {
         // Cannot determine detector cell size!
@@ -230,18 +223,18 @@ double GISASExperiment::getSolidAngle(size_t index) const
     }
     double dalpha(0), dphi(0);
 
-    double alpha_f = m_intensity_map.getValueOfAxis(s_alpha_f, index);
+    double alpha_f = m_intensity_map.getValueOfAxis(ALPHA_AXIS_NAME, index);
     double cos_alpha_f = std::cos(alpha_f);
 
     if(alpha_size>1) {
         if (alpha_index==0) {
-            dalpha = p_alpha_axis->operator[](1) - p_alpha_axis->operator[](0);
+            dalpha = (*p_alpha_axis)[1] - (*p_alpha_axis)[0];
         }
         else if (alpha_index==alpha_size-1) {
-            dalpha = p_alpha_axis->operator[](alpha_size-1) - p_alpha_axis->operator[](alpha_size-2);
+            dalpha = (*p_alpha_axis)[alpha_size-1] - (*p_alpha_axis)[alpha_size-2];
         }
         else {
-            dalpha = (p_alpha_axis->operator[](alpha_index+1) - p_alpha_axis->operator[](alpha_index-1))/2.0;
+            dalpha = ((*p_alpha_axis)[alpha_index+1] - (*p_alpha_axis)[alpha_index-1])/2.0;
         }
         dalpha = std::abs(dalpha);
     } else {
@@ -249,13 +242,13 @@ double GISASExperiment::getSolidAngle(size_t index) const
     }
     if(phi_size > 1) {
         if (phi_index==0) {
-            dphi = p_phi_axis->operator[](1) - p_phi_axis->operator[](0);
+            dphi = (*p_phi_axis)[1] - (*p_phi_axis)[0];
         }
         else if (phi_index==phi_size-1) {
-            dphi = p_phi_axis->operator[](phi_size-1) - p_phi_axis->operator[](phi_size-2);
+            dphi = (*p_phi_axis)[phi_size-1] - (*p_phi_axis)[phi_size-2];
         }
         else {
-            dphi = (p_phi_axis->operator[](phi_index+1) - p_phi_axis->operator[](phi_index-1))/2.0;
+            dphi = ((*p_phi_axis)[phi_index+1] - (*p_phi_axis)[phi_index-1])/2.0;
         }
         dphi = std::abs(dphi);
     } else {
@@ -307,23 +300,23 @@ void GISASExperiment::createZetaAndProbVectors(std::vector<double>& zetas,
 
 void GISASExperiment::addToIntensityMap(double alpha, double phi, double value)
 {
-    const AxisDouble *p_alpha_axis = m_intensity_map.getAxis("alpha_f");
-    const AxisDouble *p_phi_axis = m_intensity_map.getAxis("phi_f");
+    const IAxis *p_alpha_axis = m_intensity_map.getAxis(ALPHA_AXIS_NAME);
+    const IAxis *p_phi_axis = m_intensity_map.getAxis(PHI_AXIS_NAME);
     std::vector<int> coordinates;
-    coordinates.push_back(findClosestIndex(p_alpha_axis, alpha));
-    coordinates.push_back(findClosestIndex(p_phi_axis, phi));
+    coordinates.push_back((int)p_alpha_axis->findClosestIndex(alpha));
+    coordinates.push_back((int)p_phi_axis->findClosestIndex(phi));
     m_intensity_map[m_intensity_map.toIndex(coordinates)] += value;
 }
 
-int GISASExperiment::findClosestIndex(const AxisDouble *p_axis, double value)
-{
-    int result = 0;
-    double smallest_diff = std::abs(value-(*p_axis)[0]);
-    for (size_t i=1; i<p_axis->getSize(); ++i) {
-        double new_diff = std::abs(value-(*p_axis)[i]);
-        if (new_diff > smallest_diff) break;
-        result = (int)i;
-        smallest_diff = new_diff;
-    }
-    return result;
-}
+//int GISASExperiment::findClosestIndex(const AxisDouble *p_axis, double value)
+//{
+//    int result = 0;
+//    double smallest_diff = std::abs(value-(*p_axis)[0]);
+//    for (size_t i=1; i<p_axis->getSize(); ++i) {
+//        double new_diff = std::abs(value-(*p_axis)[i]);
+//        if (new_diff > smallest_diff) break;
+//        result = (int)i;
+//        smallest_diff = new_diff;
+//    }
+//    return result;
+//}
diff --git a/Core/Algorithms/src/MultiLayerDWBASimulation.cpp b/Core/Algorithms/src/MultiLayerDWBASimulation.cpp
index 5e9eaaea6a8dcb54428892c23266cdabfc9ff4a1..b53ef1e5ce99460c5f7d712339dfbd36e7b6ec4a 100644
--- a/Core/Algorithms/src/MultiLayerDWBASimulation.cpp
+++ b/Core/Algorithms/src/MultiLayerDWBASimulation.cpp
@@ -60,7 +60,7 @@ void MultiLayerDWBASimulation::run()
     kvector_t m_ki_real(m_ki.x().real(), m_ki.y().real(), m_ki.z().real());
 
     m_dwba_intensity.setAllTo(0.0);
-    const AxisDouble *p_alpha_axis = getDWBAIntensity().getAxis("alpha_f");
+    const IAxis *p_alpha_axis = getDWBAIntensity().getAxis("alpha_f");
     double lambda = 2.0*M_PI/m_ki_real.mag();
 
     typedef std::pair<double, OpticalFresnel::MultiLayerCoeff_t > doublefresnel_t;
diff --git a/Core/Core.pro b/Core/Core.pro
index 143396d92f5d86783a82db5d875f27a368c75d7b..9f838bb2a619e5f2076c41e8824507fb83db940f 100644
--- a/Core/Core.pro
+++ b/Core/Core.pro
@@ -88,7 +88,8 @@ SOURCES += \
     Samples/src/ParticleDecoration.cpp \
     Samples/src/ParticleInfo.cpp \
     \
-    Tools/src/Axisdouble.cpp \
+    Tools/src/AxisBin.cpp \
+    Tools/src/AxisDouble.cpp \
     Tools/src/Convolve.cpp \
     Tools/src/CoreOptionsDescription.cpp \
     Tools/src/DoubleToComplexInterpolatingFunction.cpp \
@@ -134,6 +135,7 @@ HEADERS += \
     Algorithms/inc/ConvolutionDetectorResolution.h \
     Algorithms/inc/DecouplingApproximationStrategy.h \
     Algorithms/inc/Detector.h \
+    Algorithms/inc/DetectorParameters.h \
     Algorithms/inc/DiffuseDWBASimulation.h \
     Algorithms/inc/DWBADiffuseReflection.h \
     Algorithms/inc/DWBASimulation.h \
@@ -223,8 +225,10 @@ HEADERS += \
     Samples/inc/ParticleDecoration.h \
     Samples/inc/ParticleInfo.h \
     \
+    Tools/inc/AxisBin.h \
+    Tools/inc/AxisDouble.h \
     Tools/inc/AttLimits.h \
-    Tools/inc/Axisdouble.h \
+    Tools/inc/Bin.h \
     Tools/inc/Convolve.h \
     Tools/inc/Coordinate3D.h \
     Tools/inc/DoubleToComplexInterpolatingFunction.h \
@@ -237,6 +241,7 @@ HEADERS += \
     Tools/inc/FitSuiteObjects.h \
     Tools/inc/FitSuiteParameters.h \
     Tools/inc/FitSuiteStrategy.h \
+    Tools/inc/IAxis.h \
     Tools/inc/IDoubleToComplexFunction.h \
     Tools/inc/IFactory.h \
     Tools/inc/IMinimizer.h \
diff --git a/Core/FormFactors/src/FormFactorPyramid.cpp b/Core/FormFactors/src/FormFactorPyramid.cpp
index 1914cd6034d5076b7dbb77fd5a2e27d812685e50..dffcb051a8bf65c2bfeb63c45980cbc66247f8cd 100644
--- a/Core/FormFactors/src/FormFactorPyramid.cpp
+++ b/Core/FormFactors/src/FormFactorPyramid.cpp
@@ -84,7 +84,7 @@ complex_t FormFactorPyramid::evaluate_for_q(const cvector_t &q) const
         K2 = -MathFunctions::Sinc(q1)*std::exp(im*q1)*im + MathFunctions::Sinc(q2)*std::exp(-im*q2)*im;
         K3 = MathFunctions::Sinc(q3)*std::exp(im*q3)    + MathFunctions::Sinc(q4)*std::exp(-im*q4);
         K4 = -MathFunctions::Sinc(q3)*std::exp(im*q3)*im + MathFunctions::Sinc(q4)*std::exp(-im*q4)*im;
-        F = K1*cos( (qx-qy)*R ) + K2*sin( (qx-qy)*R ) - K3*cos( (qx+qy)*R ) - K4*sin( (qx+qy)*R );
+        F = K1*std::cos( (qx-qy)*R ) + K2*std::sin( (qx-qy)*R ) - K3*std::cos( (qx+qy)*R ) - K4*std::sin( (qx+qy)*R );
         F = F*H/(qx*qy);
     } else if(std::abs(qx) <= Numeric::double_epsilon && std::abs(qy) <= Numeric::double_epsilon) {
         F=(4.*im*(-2./tga/tga - 2.*im*qz*R/tga + qz*qz*R*R - std::exp(im*H*qz) * ((-1.+im + H*qz)/tga - qz*R)*((1.+im + H*qz)/tga - qz*R)  ))/std::pow(qz,3);
@@ -95,13 +95,13 @@ complex_t FormFactorPyramid::evaluate_for_q(const cvector_t &q) const
         } else{
             qxy=qy;
         }
-        F=(4.*(qxy*tga*(-(qxy*qxy*R) + qz*tga*(complex_t(0,-2) + qz*R*tga))*std::cos(qxy*R) -
-               std::exp(im*H*qz)*qxy*(H*std::pow(qxy,2) - qxy*qxy*R*tga - qz*(complex_t(0,2) + H*qz)*std::pow(tga,2) +
+        F=(4.*(qxy*tga*(-(qxy*qxy*R) + qz*tga*(complex_t(0.0,-2.0) + qz*R*tga))*std::cos(qxy*R) -
+               std::exp(im*H*qz)*qxy*(H*std::pow(qxy,2) - qxy*qxy*R*tga - qz*(complex_t(0.0,2.0) + H*qz)*std::pow(tga,2) +
                   std::pow(qz,2)*R*std::pow(tga,3))*std::cos(qxy*(R - H/tga)) +
-               tga*(std::pow(qxy,2)*(1. - complex_t(0,1)*qz*R*tga) + std::pow(qz,2)*std::pow(tga,2)*(1. + complex_t(0,1)*qz*R*tga))*
-                std::sin(qxy*R) + complex_t(0,1)*std::exp(im*H*qz)*tga*
-                (std::pow(qz,2)*std::pow(tga,2)*(complex_t(0,1) + H*qz - qz*R*tga) +
-                  std::pow(qxy,2)*(complex_t(0,1) - H*qz + qz*R*tga))*std::sin(qxy*(R - H/tga))))/
+               tga*(std::pow(qxy,2)*(1. - complex_t(0.0,1.0)*qz*R*tga) + std::pow(qz,2)*std::pow(tga,2)*(1. + complex_t(0.0,1.0)*qz*R*tga))*
+                std::sin(qxy*R) + complex_t(0.0,1.0)*std::exp(im*H*qz)*tga*
+                (std::pow(qz,2)*std::pow(tga,2)*(complex_t(0.0,1.0) + H*qz - qz*R*tga) +
+                  std::pow(qxy,2)*(complex_t(0.0,1.0) - H*qz + qz*R*tga))*std::sin(qxy*(R - H/tga))))/
            (qxy*std::pow(qxy - qz*tga,2)*std::pow(qxy + qz*tga,2));
     }
     return F;
diff --git a/Core/Tools/inc/AxisBin.h b/Core/Tools/inc/AxisBin.h
new file mode 100644
index 0000000000000000000000000000000000000000..8e2f0e2614a78bdb0bd4afd8d2a018b95b036fed
--- /dev/null
+++ b/Core/Tools/inc/AxisBin.h
@@ -0,0 +1,69 @@
+#ifndef AXISBIN_H_
+#define AXISBIN_H_
+// ********************************************************************
+// * The BornAgain project                                            *
+// * Simulation of neutron and x-ray scattering at grazing incidence  *
+// *                                                                  *
+// * LICENSE AND DISCLAIMER                                           *
+// * Lorem ipsum dolor sit amet, consectetur adipiscing elit.  Mauris *
+// * eget quam orci. Quisque  porta  varius  dui,  quis  posuere nibh *
+// * mollis quis. Mauris commodo rhoncus porttitor.                   *
+// ********************************************************************
+//! @file   BinAxis.h
+//! @brief  Definition of BinAxis class
+//! @author Scientific Computing Group at FRM II
+//! @date   Dec 6, 2012
+
+#include "IAxis.h"
+
+#include <string>
+#include <vector>
+
+//- -------------------------------------------------------------------
+//! @class BinAxis
+//! @brief Definition of BinAxis class that stores the bins of an axis
+//- -------------------------------------------------------------------
+class AxisBin : public IAxis
+{
+public:
+    //! constructors
+    AxisBin(std::string name);
+    AxisBin(std::string name, size_t nbr_bins, double start, double end);
+
+    //! clone function
+    virtual AxisBin *clone() const;
+
+    //! create a new axis with half the number of bins
+    virtual AxisBin *createDoubleBinSize() const;
+
+    //! destructor
+    virtual ~AxisBin() {}
+
+    //! add new bin limit to the end
+    void push_back(double limit) { m_value_vector.push_back(limit); }
+
+    virtual size_t getSize() const;
+
+   //! indexed accessor retrieves midpoint of given bin
+    virtual double operator[](size_t index) const;
+
+    virtual Bin1D getBin(size_t index) const;
+
+    virtual double getMin() const { return m_value_vector.front(); }
+
+    virtual double getMax() const { return m_value_vector.back(); }
+
+    //! initialize axis bins
+    void initBins(size_t nbr_bins, double start, double end);
+
+    virtual size_t findClosestIndex(double value) const;
+
+//    //! find the bin that contains the given value
+//    Bin1D findMatchingBin(double value) const;
+protected:
+    virtual bool equals(const IAxis &other) const;
+private:
+    std::vector<double> m_value_vector;  //!< vector containing the bin limits
+};
+
+#endif /* AXISBIN_H_ */
diff --git a/Core/Tools/inc/AxisDouble.h b/Core/Tools/inc/AxisDouble.h
index f4ee265c1619f87fa3e17beaeb46d37cd10bde14..6f49aadfe9b2f7e4b9c56980840dfda3644608e2 100644
--- a/Core/Tools/inc/AxisDouble.h
+++ b/Core/Tools/inc/AxisDouble.h
@@ -14,58 +14,56 @@
 //! @author Scientific Computing Group at FRM II
 //! @date   Dec 4, 2012
 
+#include "IAxis.h"
+
 #include <string>
 #include <vector>
 
+// Forward declaration of BinAxis class, as needed for conversion constructor
+class AxisBin;
+
 //- -------------------------------------------------------------------
 //! @class AxisDouble
 //! @brief Definition of AxisDouble class that stores the points of an axis
 //- -------------------------------------------------------------------
-class AxisDouble
+class AxisDouble : public IAxis
 {
 public:
     //! constructors
     AxisDouble(std::string name);
     AxisDouble(std::string name, size_t size, double start, double end);
 
-    //! clone function
-    AxisDouble* clone() const;
+    //! explicit conversion from BinAxis
+    //TODO: make explicit
+    AxisDouble(const AxisBin &source);
 
-    //! create a new axis with half the number of bins
-    AxisDouble createDoubleBinSize() const;
-
-    //! destructor
-    ~AxisDouble() {}
+    virtual AxisDouble *clone() const;
 
-    //! retrieve the number of bins
-    inline size_t getSize() const { return m_value_vector.size(); }
+    virtual AxisDouble *createDoubleBinSize() const;
 
-    //! retrieve the label of the axis
-    inline std::string getName() const { return m_name; }
+    //! destructor
+    virtual ~AxisDouble() {}
 
-    //! set the axis label
-    inline void setName(std::string name) { m_name = name; }
+    virtual size_t getSize() const { return m_sample_vector.size(); }
 
     //! add point to the end of the axis
-    inline void push_back(double element) { m_value_vector.push_back(element); }
+    void push_back(double element) { m_sample_vector.push_back(element); }
 
-    //! indexed accessor
-    inline double& operator[](size_t index) { return m_value_vector.at(index); }
+    virtual double operator[](size_t index) const { return m_sample_vector[index]; }
 
-    //! const indexed accessor
-    inline const double& operator[](size_t index) const { return m_value_vector.at(index); }
+    virtual Bin1D getBin(size_t index) const;
 
     //! get value of first point of axis
-    inline double getMin() const { return m_value_vector.front(); }
+    virtual double getMin() const { return m_sample_vector.front(); }
 
     //! get value of last point of axis
-    inline double getMax() const { return m_value_vector.back(); }
+    virtual double getMax() const { return m_sample_vector.back(); }
 
     //! initialize axis points
     void initElements(size_t size, double start, double end);
 
     //! find number of bin which is closest to given value
-    size_t findClosestIndex(double value) const;
+    virtual size_t findClosestIndex(double value) const;
 
     //! find the index that corresponds to the given lower bound (index is inclusive)
     size_t getLowerBoundIndex(double value) const;
@@ -73,13 +71,9 @@ public:
     //! find the index that corresponds to the given upper bound (index is inclusive)
     size_t getUpperBoundIndex(double value) const;
 private:
-    std::string m_name;  //!< axis label
-    std::vector<double> m_value_vector;  //!< vector containing the axis points
+    virtual bool equals(const IAxis &other) const;
+    std::vector<double> m_sample_vector;  //!< vector containing the axis points
+    double m_bin_size;
 };
 
-//! global helper function for comparison of axes
-bool HaveSameNameAndShape(const AxisDouble &left, const AxisDouble &right);
-
-
-
 #endif /* AXISDOUBLE_H_ */
diff --git a/Core/Tools/inc/Bin.h b/Core/Tools/inc/Bin.h
new file mode 100644
index 0000000000000000000000000000000000000000..655d6c4bd1a1e39bb98b269306d592cc23cc07c2
--- /dev/null
+++ b/Core/Tools/inc/Bin.h
@@ -0,0 +1,46 @@
+#ifndef BIN_H_
+#define BIN_H_
+// ********************************************************************
+// * The BornAgain project                                            *
+// * Simulation of neutron and x-ray scattering at grazing incidence  *
+// *                                                                  *
+// * LICENSE AND DISCLAIMER                                           *
+// * Lorem ipsum dolor sit amet, consectetur adipiscing elit.  Mauris *
+// * eget quam orci. Quisque  porta  varius  dui,  quis  posuere nibh *
+// * mollis quis. Mauris commodo rhoncus porttitor.                   *
+// ********************************************************************
+//! @file   Bin.h
+//! @brief  Definition of Bin classes
+//! @author Scientific Computing Group at FRM II
+//! @date   Dec 10, 2012
+
+#include "Numeric.h"
+
+#include <cmath>
+
+//- -------------------------------------------------------------------
+//! @class Bin1D
+//! @brief Definition of Bin1D class that stores the bounds of a
+//! one-dimensional bin
+//- -------------------------------------------------------------------
+struct Bin1D
+{
+    double m_lower;  //!< lower bound of the bin
+    double m_upper;  //!< upper bound of the bin
+    double getMidPoint() const { return (m_lower + m_upper)/2.0; }
+};
+
+//! equality operator for bins
+inline bool operator==(const Bin1D &left, const Bin1D &right)
+{
+    if (std::abs(left.m_lower - right.m_lower) > Numeric::double_epsilon) return false;
+    if (std::abs(left.m_upper - right.m_upper) > Numeric::double_epsilon) return false;
+    return true;
+}
+
+//! inequality operator for bins
+inline bool operator!=(const Bin1D &left, const Bin1D &right) {
+    return !(left==right);
+}
+
+#endif /* BIN_H_ */
diff --git a/Core/Tools/inc/IAxis.h b/Core/Tools/inc/IAxis.h
new file mode 100644
index 0000000000000000000000000000000000000000..ced92e9c13e7c5a32852a0c5bbd2e89ffa6ab37e
--- /dev/null
+++ b/Core/Tools/inc/IAxis.h
@@ -0,0 +1,96 @@
+#ifndef IAXIS_H_
+#define IAXIS_H_
+// ********************************************************************
+// * The BornAgain project                                            *
+// * Simulation of neutron and x-ray scattering at grazing incidence  *
+// *                                                                  *
+// * LICENSE AND DISCLAIMER                                           *
+// * Lorem ipsum dolor sit amet, consectetur adipiscing elit.  Mauris *
+// * eget quam orci. Quisque  porta  varius  dui,  quis  posuere nibh *
+// * mollis quis. Mauris commodo rhoncus porttitor.                   *
+// ********************************************************************
+//! @file   IAxis.h
+//! @brief  Definition of IAxis interface
+//! @author Scientific Computing Group at FRM II
+//! @date   Dec 10, 2012
+
+#include "Bin.h"
+
+#include <string>
+
+//- -------------------------------------------------------------------
+//! @class IAxis
+//! @brief Definition of IAxis interface for 1d axes
+//- -------------------------------------------------------------------
+
+class IAxis
+{
+public:
+    //! constructors
+    IAxis(std::string name) : m_name(name) {}
+
+    //! clone function
+    virtual IAxis *clone() const=0;
+
+    //! create a new axis with half the number of bins
+    virtual IAxis *createDoubleBinSize() const=0;
+
+    //! destructor
+    virtual ~IAxis() {}
+
+    //! retrieve the number of bins
+    virtual size_t getSize() const=0;
+
+    //! retrieve the label of the axis
+    std::string getName() const { return m_name; }
+
+    //! set the axis label
+    void setName(std::string name) { m_name = name; }
+
+    //! indexed accessor retrieves a sample
+    virtual double operator[](size_t index) const=0;
+
+    //! retrieve a 1d bin for the given index
+    virtual Bin1D getBin(size_t index) const=0;
+
+    //! get value of first point of axis
+    virtual double getMin() const=0;
+
+    //! get value of last point of axis
+    virtual double getMax() const=0;
+
+    //! find bin index which is best match for given value
+    virtual size_t findClosestIndex(double value) const=0;
+
+    //! test for equality
+    friend bool operator==(const IAxis &left, const IAxis &right) {
+        return left.equals(right);
+    }
+
+//    //! find the index that corresponds to the given lower bound (index is inclusive)
+//    virtual size_t getLowerBoundIndex(double value) const=0;
+//
+//    //! find the index that corresponds to the given upper bound (index is inclusive)
+//    virtual size_t getUpperBoundIndex(double value) const=0;
+protected:
+    virtual bool equals(const IAxis &other) const;
+    std::string m_name;  //!< axis label
+};
+
+inline bool IAxis::equals(const IAxis& other) const
+{
+    return getName()==other.getName();
+}
+
+//! test for inequality
+inline bool operator!=(const IAxis &left, const IAxis &right) {
+    return !(left ==  right);
+}
+
+//! global helper function for comparison of axes
+inline bool HaveSameNameAndShape(const IAxis &left, const IAxis &right)
+{
+    return left == right;
+}
+
+#endif /* IAXIS_H_ */
diff --git a/Core/Tools/inc/IMinimizer.h b/Core/Tools/inc/IMinimizer.h
index b25f3cabaa354a1834a5bffee965f4b2a342c85a..7df17f8678ff098e121528e3af44c6b68a56e952 100644
--- a/Core/Tools/inc/IMinimizer.h
+++ b/Core/Tools/inc/IMinimizer.h
@@ -110,7 +110,7 @@ public:
     //! 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);
+        std::map<int, double >::const_iterator pos = m_values.find((int)i);
         if(pos != m_values.end()){
             return pos->second;
         } else {
diff --git a/Core/Tools/inc/OutputData.h b/Core/Tools/inc/OutputData.h
index 37fdf160bc9272d93f1d2c568453fb247f719bf9..e942ff832590c535cb71c8c3bf5a21aa001016ca 100644
--- a/Core/Tools/inc/OutputData.h
+++ b/Core/Tools/inc/OutputData.h
@@ -19,6 +19,7 @@
 #include "Types.h"
 #include "LLData.h"
 #include "OutputDataIterator.h"
+#include "SafePointerVector.h"
 
 #include <string>
 #include <sstream>
@@ -32,17 +33,17 @@ template <class T> class OutputData
 {
 public:
     OutputData();
-    virtual ~OutputData();
+    ~OutputData();
     //! make object clone
     OutputData* clone() const;
 
     void copyFrom(const OutputData<T> &x);
 
-    void addAxis(const AxisDouble &new_axis);
+    void addAxis(const IAxis &new_axis);
     void addAxis(std::string name, size_t size, double start, double end);
 
-    const AxisDouble *getAxis(size_t index) const;
-    const AxisDouble *getAxis(std::string label) const;
+    const IAxis *getAxis(size_t index) const;
+    const IAxis *getAxis(std::string label) const;
     size_t getAxisIndex(const std::string &label) const;
 
     // ---------------------------------
@@ -199,7 +200,7 @@ private:
     //! memory allocation for current dimensions configuration
     void allocate();
 
-    std::vector<AxisDouble> m_value_axes;
+    SafePointerVector<IAxis> m_value_axes;
     LLData<T> *mp_ll_data;
     Mask *mp_mask;
 };
@@ -250,12 +251,12 @@ template <class T> void OutputData<T>::copyFrom(const OutputData<T> &other)
 
 
 
-template <class T> void OutputData<T>::addAxis(const AxisDouble &new_axis)
+template <class T> void OutputData<T>::addAxis(const IAxis &new_axis)
 {
-    if( getAxis(new_axis.getName()) ) throw LogicErrorException("OutputData<T>::addAxis(AxisDouble *) -> Error! Attempt to add axis with already existing name '"+ new_axis.getName()+std::string("'"));
+    if( getAxis(new_axis.getName()) ) throw LogicErrorException("OutputData<T>::addAxis(const IAxis &new_axis) -> Error! Attempt to add axis with already existing name '"+ new_axis.getName()+std::string("'"));
     if (new_axis.getSize()>0)
     {
-        m_value_axes.push_back(new_axis);
+        m_value_axes.push_back(new_axis.clone());
         allocate();
     }
 }
@@ -268,18 +269,18 @@ void OutputData<T>::addAxis(std::string name, size_t size, double start, double
     addAxis(new_axis);
 }
 
-template <class T> const AxisDouble *OutputData<T>::getAxis(size_t index) const
+template <class T> const IAxis *OutputData<T>::getAxis(size_t index) const
 {
-    return &m_value_axes.at(index);
+    return m_value_axes[index];
 }
 
-template <class T> const AxisDouble *OutputData<T>::getAxis(std::string label) const
+template <class T> const IAxis *OutputData<T>::getAxis(std::string label) const
 {
-    for (std::vector<AxisDouble>::const_iterator it = m_value_axes.begin(); it != m_value_axes.end(); ++it)
+    for (size_t i = 0; i < m_value_axes.size(); ++i)
     {
-        if (it->getName() == label)
+        if (m_value_axes[i]->getName() == label)
         {
-            return &(*it);
+            return m_value_axes[i];
         }
     }
     return 0;
@@ -288,10 +289,9 @@ template <class T> const AxisDouble *OutputData<T>::getAxis(std::string label) c
 // return index of axis
 template <class T> size_t OutputData<T>::getAxisIndex(const std::string &label) const
 {
-    size_t index(0);
-    for (std::vector<AxisDouble>::const_iterator it = m_value_axes.begin(); it != m_value_axes.end(); ++it, ++index)
+    for (size_t i = 0; i < m_value_axes.size(); ++i)
     {
-        if (it->getName() == label) return index;
+        if (m_value_axes[i]->getName() == label) return i;
     }
     throw LogicErrorException("OutputData<T>::getIndexOfAxis() -> Error! Axis with given name not found '"+label+std::string("'"));
 }
@@ -377,8 +377,8 @@ template<class T> std::vector<int> OutputData<T>::toCoordinates(size_t index) co
     result.resize(mp_ll_data->getRank());
     for (size_t i=0; i<mp_ll_data->getRank(); ++i)
     {
-        result[mp_ll_data->getRank()-1-i] = (int)(remainder % m_value_axes[mp_ll_data->getRank()-1-i].getSize());
-        remainder /= m_value_axes[mp_ll_data->getRank()-1-i].getSize();
+        result[mp_ll_data->getRank()-1-i] = (int)(remainder % m_value_axes[mp_ll_data->getRank()-1-i]->getSize());
+        remainder /= m_value_axes[mp_ll_data->getRank()-1-i]->getSize();
     }
     return result;
 }
@@ -389,9 +389,9 @@ template<class T> int OutputData<T>::toCoordinate(size_t index, size_t i_selecte
     for (size_t i=0; i<mp_ll_data->getRank(); ++i)
     {
         size_t i_axis = mp_ll_data->getRank()-1-i;
-        int result = (int)(remainder % m_value_axes[i_axis].getSize());
+        int result = (int)(remainder % m_value_axes[i_axis]->getSize());
         if(i_selected_axis == i_axis ) return result;
-        remainder /= m_value_axes[i_axis].getSize();
+        remainder /= m_value_axes[i_axis]->getSize();
     }
     throw LogicErrorException("OutputData<T>::toCoordinate() -> Error! No axis with given number");
 }
@@ -407,7 +407,7 @@ template <class T> size_t OutputData<T>::toIndex(std::vector<int> coordinates) c
     for (size_t i=mp_ll_data->getRank(); i>0; --i)
     {
         result += coordinates[i-1]*step_size;
-        step_size *= m_value_axes[i-1].getSize();
+        step_size *= m_value_axes[i-1]->getSize();
     }
     return result;
 }
@@ -416,34 +416,21 @@ template <class T> size_t OutputData<T>::getIndexOfAxis(const std::string &axis_
 {
     std::vector<int> coordinates = toCoordinates(total_index);
     for (size_t i=0; i<m_value_axes.size(); ++i) {
-        if (m_value_axes[i].getName() == axis_name) {
+        if (m_value_axes[i]->getName() == axis_name) {
             return coordinates[i];
         }
     }
     throw LogicErrorException("OutputData<T>::getIndexOfAxis() -> Error! Axis with given name not found '"+std::string(axis_name)+std::string("'"));
 }
 
-//template <class T>
-//double OutputData<T>::getValueOfAxis(const char *axis_name, size_t index) const
-////double OutputData<T>::getValueOfAxis(std::string axis_name, size_t index) const
-//{
-//    std::vector<int> coordinates = toCoordinates(index);
-//    for (size_t i=0; i<m_value_axes.size(); ++i) {
-//        if (m_value_axes[i].getName() == axis_name) {
-//            return m_value_axes[i][coordinates[i]];
-//        }
-//    }
-//    throw LogicErrorException("OutputData<T>::getValueOfAxis() -> Error! Axis with given name not found '"+std::string(axis_name)+std::string("'"));
-//}
-
 
 template <class T>
 double OutputData<T>::getValueOfAxis(const std::string &axis_name, size_t index) const
 {
     for (size_t i=0; i<m_value_axes.size(); ++i) {
-        if (m_value_axes[i].getName() == axis_name) {
+        if (m_value_axes[i]->getName() == axis_name) {
             int axis_index = toCoordinate(index, i);
-            return m_value_axes[i][axis_index];
+            return (*m_value_axes[i])[axis_index];
         }
     }
     throw LogicErrorException("OutputData<T>::getValueOfAxis() -> Error! Axis with given name not found '"+std::string(axis_name)+std::string("'"));
@@ -559,10 +546,10 @@ bool OutputData<T>::hasSameShape(const OutputData<T> &right) const
         throw LogicErrorException("OutputData<T>::hasSameShape() -> Panic! Inconsistent dimensions in LLData and axes");
     }
     for (size_t i=0; i<m_value_axes.size(); ++i) {
-        const AxisDouble axis_left = m_value_axes[i];
-        const AxisDouble axis_right = right.m_value_axes[i];
+        const IAxis *p_axis_left = m_value_axes[i];
+        const IAxis *p_axis_right = right.m_value_axes[i];
 
-        if( !HaveSameNameAndShape(axis_left, axis_right)) return false;
+        if( !HaveSameNameAndShape(*p_axis_left, *p_axis_right)) return false;
     }
     return true;
 }
diff --git a/Core/Tools/inc/SafePointerVector.h b/Core/Tools/inc/SafePointerVector.h
new file mode 100644
index 0000000000000000000000000000000000000000..bfdc59626dc1d7d86fca410128100ac4e9e2e7a8
--- /dev/null
+++ b/Core/Tools/inc/SafePointerVector.h
@@ -0,0 +1,111 @@
+#ifndef SAFEPOINTERVECTOR_H_
+#define SAFEPOINTERVECTOR_H_
+// ********************************************************************
+// * The BornAgain project                                            *
+// * Simulation of neutron and x-ray scattering at grazing incidence  *
+// *                                                                  *
+// * LICENSE AND DISCLAIMER                                           *
+// * Lorem ipsum dolor sit amet, consectetur adipiscing elit.  Mauris *
+// * eget quam orci. Quisque  porta  varius  dui,  quis  posuere nibh *
+// * mollis quis. Mauris commodo rhoncus porttitor.                   *
+// ********************************************************************
+//! @file   SafePointerVector.h
+//! @brief  Definition of SafePointerVector template
+//! @author Scientific Computing Group at FRM II
+//! @date   Dec 10, 2012
+
+#include <vector>
+
+//- -------------------------------------------------------------------
+//! @class SafePointerVector
+//! @brief Definition of SafePointerVector<T> template for safe handling
+//! of vectors of pointers that are owned by the vector
+//- -------------------------------------------------------------------
+template <class T> class SafePointerVector
+{
+public:
+    typedef typename std::vector<T *>::iterator iterator;
+    typedef typename std::vector<T *>::const_iterator const_iterator;
+    SafePointerVector();
+    SafePointerVector(const SafePointerVector &other);
+    ~SafePointerVector();
+
+    SafePointerVector &operator=(const SafePointerVector &right);
+    size_t size() const;
+    void push_back(T *pointer);
+    T *operator[](size_t index);
+    const T *operator[](size_t index) const;
+    iterator begin() { return m_pointers.begin(); }
+    const_iterator begin() const { return m_pointers.begin(); }
+    iterator end() { return m_pointers.end(); }
+    const_iterator end() const { return m_pointers.end(); }
+
+    T *back() { return m_pointers.back(); }
+    T *const back() const { return m_pointers.back(); }
+    void clear();
+private:
+    std::vector<T *> m_pointers;
+};
+
+template<class T> SafePointerVector<T>::SafePointerVector()
+{
+}
+
+template<class T> SafePointerVector<T>::SafePointerVector(const SafePointerVector<T> &other)
+{
+    for (const_iterator it = other.begin();
+            it != other.end(); ++it) {
+        m_pointers.push_back((*it)->clone());
+    }
+}
+
+template<class T> SafePointerVector<T>::~SafePointerVector()
+{
+    clear();
+}
+
+template<class T> SafePointerVector<T> &SafePointerVector<T>::operator=(
+        const SafePointerVector<T> &right)
+{
+    if (this == &right) return *this;
+    clear();
+    for (const_iterator it = right.begin();
+            it != right.end(); ++it) {
+        m_pointers.push_back((*it)->clone());
+    }
+    return *this;
+}
+
+template<class T>
+inline size_t SafePointerVector<T>::size() const
+{
+    return m_pointers.size();
+}
+
+template<class T>
+inline void SafePointerVector<T>::push_back(T* pointer)
+{
+    m_pointers.push_back(pointer);
+}
+
+template<class T>
+inline T* SafePointerVector<T>::operator[](size_t index)
+{
+    return m_pointers[index];
+}
+
+template<class T>
+inline const T* SafePointerVector<T>::operator[](size_t index) const
+{
+    return m_pointers[index];
+}
+
+template<class T> void SafePointerVector<T>::clear()
+{
+    for (iterator it = begin(); it != end(); ++it) {
+        delete (*it);
+    }
+    m_pointers.clear();
+}
+
+#endif /* SAFEPOINTERVECTOR_H_ */
diff --git a/Core/Tools/inc/TRange.h b/Core/Tools/inc/TRange.h
index 684c24fd6ffb633cde815a002738525766949519..6ab79366235bcc54a1ca13cb2f9acadf43188191 100644
--- a/Core/Tools/inc/TRange.h
+++ b/Core/Tools/inc/TRange.h
@@ -28,4 +28,14 @@ private:
     T m_min, m_max;
 };
 
+template <class T> class TSampledRange : public TRange<T>
+{
+public:
+    TSampledRange(size_t n_samples, T min, T max) : TRange<T>(min, max), m_n_samples(n_samples) {}
+
+    size_t getNSamples() const { return m_n_samples; }
+private:
+    size_t m_n_samples;
+};
+
 #endif /* TRANGE_H_ */
diff --git a/Core/Tools/src/AxisBin.cpp b/Core/Tools/src/AxisBin.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..e9fb04e868ae434ac6cab0aec7ef93ec6ab471e2
--- /dev/null
+++ b/Core/Tools/src/AxisBin.cpp
@@ -0,0 +1,97 @@
+#include "AxisBin.h"
+#include "Numeric.h"
+#include "Exceptions.h"
+
+AxisBin::AxisBin(std::string name)
+: IAxis(name)
+{
+}
+
+AxisBin::AxisBin(std::string name, size_t nbr_bins, double start, double end)
+: IAxis(name)
+{
+    initBins(nbr_bins, start, end);
+}
+
+AxisBin *AxisBin::clone() const
+{
+    AxisBin *p_clone = new AxisBin(getName());
+    p_clone->m_value_vector = this->m_value_vector;
+    return p_clone;
+}
+
+AxisBin *AxisBin::createDoubleBinSize() const
+{
+    if (getSize() < 2) {
+        return clone();
+    }
+    AxisBin *p_result = new AxisBin(getName());
+    for (size_t source_index=0; source_index<getSize(); source_index+=2)
+    {
+        p_result->push_back(m_value_vector[source_index]);
+    }
+    p_result->push_back(m_value_vector[getSize()]);
+    return p_result;
+}
+
+size_t AxisBin::getSize() const
+{
+    if (m_value_vector.size()<2) {
+        return 0;
+    }
+    return m_value_vector.size() - 1;
+}
+
+double AxisBin::operator[](size_t index) const
+{
+    return getBin(index).getMidPoint();
+}
+
+Bin1D AxisBin::getBin(size_t index) const
+{
+    Bin1D result = { m_value_vector[index], m_value_vector[index+1] };
+    return result;
+}
+
+void AxisBin::initBins(size_t nbr_bins, double start, double end)
+{
+    double step = (end - start)/(nbr_bins);
+    for (size_t i=0; i<nbr_bins+1; ++i)
+    {
+        push_back(start + step*(int)i);
+    }
+}
+
+size_t AxisBin::findClosestIndex(double value) const
+{
+    if(m_value_vector.size()<2) {
+        throw ClassInitializationException("AxisBin not (yet) correctly initialized");
+    }
+    if (value < getMin() || value > getMax()) {
+        throw OutOfBoundsException("Given value not in any bin");
+    }
+    std::vector<double>::const_iterator top_limit = std::lower_bound(m_value_vector.begin(), m_value_vector.end(), value);
+    if(top_limit != m_value_vector.begin() ) --top_limit;
+    size_t nbin = top_limit - m_value_vector.begin();
+    return nbin;
+}
+
+//Bin1D AxisBin::findMatchingBin(double value) const
+//{
+//    return (*this)[findMatchingBinIndex(value)];
+//}
+//
+bool AxisBin::equals(const IAxis& other) const
+{
+    if (!IAxis::equals(other)) return false;
+    if (const AxisBin *p_other_cast = dynamic_cast<const AxisBin *>(&other)) {
+        if (getSize() != p_other_cast->getSize()) return false;
+        for(size_t i=0; i<m_value_vector.size(); ++i) {
+            if( std::abs(m_value_vector[i] - p_other_cast->m_value_vector[i]) > Numeric::double_epsilon ) {
+                return false;
+            }
+        }
+        return true;
+    }
+    return false;
+}
diff --git a/Core/Tools/src/AxisDouble.cpp b/Core/Tools/src/AxisDouble.cpp
index 16b12f965ce4a007d6a989af1ca943e5f7601127..729fa2963c5aa668a84bbb49f0ba2bc2dece6cf1 100644
--- a/Core/Tools/src/AxisDouble.cpp
+++ b/Core/Tools/src/AxisDouble.cpp
@@ -1,45 +1,62 @@
 #include "AxisDouble.h"
+#include "AxisBin.h"
 #include "Numeric.h"
 #include "Exceptions.h"
 
-#include <cmath>
-#include <algorithm>
-
 AxisDouble::AxisDouble(std::string name)
-: m_name(name)
+: IAxis(name)
+, m_bin_size(0)
 {
 }
 
 AxisDouble::AxisDouble(std::string name, size_t size, double start, double end)
-: m_name(name)
+: IAxis(name)
+, m_bin_size(0)
 {
     initElements(size, start, end);
 }
 
-AxisDouble* AxisDouble::clone() const
+AxisDouble::AxisDouble(const AxisBin& source)
+: IAxis(source.getName())
+, m_bin_size(0)
+{
+    for (size_t i=0; i<source.getSize(); ++i) {
+        m_sample_vector.push_back(source[i]);
+    }
+}
+
+AxisDouble *AxisDouble::clone() const
 {
     AxisDouble *p_clone = new AxisDouble(getName());
-    p_clone->m_value_vector = this->m_value_vector;
+    p_clone->m_sample_vector = this->m_sample_vector;
+    p_clone->m_bin_size = this->m_bin_size;
     return p_clone;
 }
 
-AxisDouble AxisDouble::createDoubleBinSize() const
+AxisDouble *AxisDouble::createDoubleBinSize() const
 {
     if (getSize() < 2) {
-        return *this;
+        return clone();
     }
-    AxisDouble result(getName());
+    AxisDouble *p_result = new AxisDouble(getName());
     for (size_t source_index=0; source_index<getSize(); source_index+=2)
     {
         double value;
         if (source_index==getSize()-1) {
-            value = (3.0*m_value_vector.at(source_index) - m_value_vector.at(source_index-1))/2.0;
+            value = (3.0*m_sample_vector.at(source_index) - m_sample_vector.at(source_index-1))/2.0;
         }
         else {
-            value =  (m_value_vector.at(source_index) + m_value_vector.at(source_index+1))/2.0;
+            value =  (m_sample_vector.at(source_index) + m_sample_vector.at(source_index+1))/2.0;
         }
-        result.push_back(value);
+        p_result->push_back(value);
     }
+    p_result->m_bin_size = m_bin_size*2.0;
+    return p_result;
+}
+
+Bin1D AxisDouble::getBin(size_t index) const
+{
+    Bin1D result = { m_sample_vector[index] - m_bin_size/2.0, m_sample_vector[index] + m_bin_size/2.0 };
     return result;
 }
 
@@ -54,38 +71,45 @@ void AxisDouble::initElements(size_t size, double start, double end)
 
 size_t AxisDouble::findClosestIndex(double value) const
 {
-    if(m_value_vector.size()<2) return 0;
-    std::vector<double>::const_iterator before = std::lower_bound(m_value_vector.begin(), m_value_vector.end(), value);
-    if(before == m_value_vector.end() ) --before;
-    if(before == m_value_vector.begin() ) ++before;
+    if(m_sample_vector.size()<2) return 0;
+    std::vector<double>::const_iterator before = std::lower_bound(m_sample_vector.begin(), m_sample_vector.end(), value);
+    if(before == m_sample_vector.end() ) --before;
+    if(before == m_sample_vector.begin() ) ++before;
     std::vector<double>::const_iterator after = before;
     --before;
     size_t nbin(0);
-    ( *after-value) < (value - *before) ? nbin = std::distance(m_value_vector.begin(), after) : nbin = std::distance(m_value_vector.begin(), before);
+    ( *after-value) < (value - *before) ? nbin = std::distance(m_sample_vector.begin(), after) : nbin = std::distance(m_sample_vector.begin(), before);
     return nbin;
 }
 
 size_t AxisDouble::getLowerBoundIndex(double value) const
 {
-    if(m_value_vector.size()<2) return 0;
-    std::vector<double>::const_iterator lbound_it = std::lower_bound(m_value_vector.begin(), m_value_vector.end(), value);
-    if(lbound_it == m_value_vector.end() ) {
+    if(m_sample_vector.size()<2) return 0;
+    std::vector<double>::const_iterator lbound_it = std::lower_bound(m_sample_vector.begin(), m_sample_vector.end(), value);
+    if(lbound_it == m_sample_vector.end() ) {
         throw RuntimeErrorException("Given lower bound higher than highest present value");
     }
-    return lbound_it - m_value_vector.begin();
+    return lbound_it - m_sample_vector.begin();
 }
 
 size_t AxisDouble::getUpperBoundIndex(double value) const
 {
-    if(m_value_vector.size()<2) return 0;
-    std::vector<double>::const_iterator lbound_it = std::upper_bound(m_value_vector.begin(), m_value_vector.end(), value);
-    return (lbound_it - m_value_vector.begin()) - 1;
+    if(m_sample_vector.size()<2) return 0;
+    std::vector<double>::const_iterator lbound_it = std::upper_bound(m_sample_vector.begin(), m_sample_vector.end(), value);
+    return (lbound_it - m_sample_vector.begin()) - 1;
 }
 
-bool HaveSameNameAndShape(const AxisDouble& left, const AxisDouble& right)
+bool AxisDouble::equals(const IAxis& other) const
 {
-    if(left.getSize() != right.getSize()) return false;
-    if(left.getName() != right.getName()) return false;
-    for(size_t i=0; i<left.getSize(); ++i) if( std::abs(left[i] - right[i]) > Numeric::double_epsilon)  return false;
-    return true;
+    if (!IAxis::equals(other)) return false;
+    if (const AxisDouble *p_other_cast = dynamic_cast<const AxisDouble *>(&other)) {
+        if (getSize() != p_other_cast->getSize()) return false;
+        for(size_t i=0; i<m_sample_vector.size(); ++i) {
+            if( std::abs(m_sample_vector[i] - p_other_cast->m_sample_vector[i]) > Numeric::double_epsilon ) {
+                return false;
+            }
+        }
+        return true;
+    }
+    return false;
 }
diff --git a/Core/Tools/src/FitSuite.cpp b/Core/Tools/src/FitSuite.cpp
index 6ef0468a6d8ba0a8554e7e730c6ab9016cf07ab8..350278e42c05b223b068ad26c8bff6c90e5f2ef2 100644
--- a/Core/Tools/src/FitSuite.cpp
+++ b/Core/Tools/src/FitSuite.cpp
@@ -168,7 +168,7 @@ double FitSuite::functionToMinimize(const double *pars_current_values)
     m_fit_objects.runSimulation();
 
     // caclulate chi2 value
-    double chi_squared = m_fit_objects.getChiSquaredValue(m_fit_parameters.getNfreeParameters());
+    double chi_squared = m_fit_objects.getChiSquaredValue((int)m_fit_parameters.getNfreeParameters());
 
     notifyObservers();
     m_n_call++;
diff --git a/Core/Tools/src/FitSuiteObjects.cpp b/Core/Tools/src/FitSuiteObjects.cpp
index 90a01a1f9b92b191de042d59027e5d7c69ce7864..393e7043f22997f4e00a6ec070059c916b2fd92b 100644
--- a/Core/Tools/src/FitSuiteObjects.cpp
+++ b/Core/Tools/src/FitSuiteObjects.cpp
@@ -52,7 +52,7 @@ double FitSuiteObjects::getChiSquaredValue(int n_free_fit_parameters)
     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);
+        chi->setNdegreeOfFreedom( (int)(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( max_intensity );
diff --git a/Core/Tools/src/OutputDataFunctions.cpp b/Core/Tools/src/OutputDataFunctions.cpp
index 6e2e36819b9f3d0b34745b19c22a97243d8b7bb6..06dff54e45d29bb1b24155055e6ca3aa133999b8 100644
--- a/Core/Tools/src/OutputDataFunctions.cpp
+++ b/Core/Tools/src/OutputDataFunctions.cpp
@@ -23,8 +23,10 @@ OutputData<double> *OutputDataFunctions::doubleBinSize(const OutputData<double>
     // create new axes
     for (size_t i=0; i<dimension; ++i) {
         needs_resizing.push_back(source_sizes[i] > 1);
-        const AxisDouble *source_axis = source.getAxis(i);
-        p_result->addAxis(source_axis->createDoubleBinSize());
+        const IAxis *source_axis = source.getAxis(i);
+        IAxis *p_new_axis = source_axis->createDoubleBinSize();
+        p_result->addAxis(*p_new_axis);
+        delete p_new_axis;
     }
     // calculate new data content
     OutputData<double>::const_iterator it_source = source.begin();
@@ -210,10 +212,10 @@ OutputData<double> *OutputDataFunctions::sliceAccrossOneAxis(const OutputData<do
 
     OutputData<double > *sliced_data = new OutputData<double >;
 
-    const AxisDouble *fixed_axis(0);
+    const IAxis *fixed_axis(0);
     int fixed_axis_index(-1);
     for(size_t i_axis=0; i_axis<data.getNdimensions(); i_axis++) {
-        const AxisDouble *axis = data.getAxis(i_axis);
+        const IAxis *axis = data.getAxis(i_axis);
         if( axis->getName() != fixed_axis_name ) {
             sliced_data->addAxis(*axis);
         } else {
@@ -252,7 +254,7 @@ OutputData<double> *OutputDataFunctions::selectRangeOnOneAxis(const OutputData<d
         throw LogicErrorException("OutputDataFunctions::selectRangeOnOneAxis() -> Error! It was checked only with number of dimensions equal 2.");
     }
 
-    const AxisDouble *selected_axis = data.getAxis(selected_axis_name);
+    const IAxis *selected_axis = data.getAxis(selected_axis_name);
     if( !selected_axis ) {
         throw LogicErrorException("OutputDataFunctions::selectRangeOnOneAxis() -> Error! No axis with name "+selected_axis_name);
     }
@@ -270,7 +272,7 @@ OutputData<double> *OutputDataFunctions::selectRangeOnOneAxis(const OutputData<d
     // preparing new data with modified axes
     OutputData<double > *new_data = new OutputData<double >;
     for(size_t i_axis=0; i_axis<data.getNdimensions(); i_axis++) {
-        const AxisDouble *axis = data.getAxis(i_axis);
+        const IAxis *axis = data.getAxis(i_axis);
         if( axis->getName() != selected_axis_name ) {
             new_data->addAxis(*axis);
         } else {
@@ -343,9 +345,9 @@ Mask* OutputDataFunctions::CreateRectangularMask(const OutputData<double>& data,
     int *maxima_i = new int[rank];
     int *dims_i = new int[rank];
     for (size_t i=0; i<rank; ++i) {
-        const AxisDouble *p_axis = data.getAxis(i);
-        minima_i[i] = (int)p_axis->getLowerBoundIndex(minima[i]);
-        maxima_i[i] = (int)p_axis->getUpperBoundIndex(maxima[i]);
+        const IAxis *p_axis = data.getAxis(i);
+        minima_i[i] = (int)p_axis->findClosestIndex(minima[i]);
+        maxima_i[i] = (int)p_axis->findClosestIndex(maxima[i]);
         dims_i[i] = (int)p_axis->getSize();
     }
     MaskCoordinateRectangleFunction *p_rectangle_function = new MaskCoordinateRectangleFunction(rank, minima_i, maxima_i);
@@ -366,9 +368,9 @@ Mask* OutputDataFunctions::CreateEllipticMask(const OutputData<double>& data,
     int *radii_i = new int[rank];
     int *dims_i = new int[rank];
     for (size_t i=0; i<rank; ++i) {
-        const AxisDouble *p_axis = data.getAxis(i);
-        center_i[i] = (int)p_axis->getLowerBoundIndex(center[i]);
-        int lower_index = (int)p_axis->getLowerBoundIndex((*p_axis)[center_i[i]] - radii[i]);
+        const IAxis *p_axis = data.getAxis(i);
+        center_i[i] = (int)p_axis->findClosestIndex(center[i]);
+        int lower_index = (int)p_axis->findClosestIndex((*p_axis)[center_i[i]] - radii[i]);
         radii_i[i] = center_i[i] - lower_index;
         dims_i[i] = (int)p_axis->getSize();
     }
diff --git a/UnitTests/TestCore/DetectorTest.h b/UnitTests/TestCore/DetectorTest.h
index 89be1d35b359d6b96280d46b18c7ea77742b40a8..b6d5def59ce449be9d248e596289b66b28f925b3 100644
--- a/UnitTests/TestCore/DetectorTest.h
+++ b/UnitTests/TestCore/DetectorTest.h
@@ -57,9 +57,10 @@ TEST_F(DetectorTest, DetectorConstruction)
     AxisDouble axis1("axis1", 20, 0.0, 20.0);
     constructedDetector.addAxis(axis0);
     constructedDetector.addAxis(axis1);
+
     EXPECT_EQ((size_t)2, constructedDetector.getDimension());
-    AxisDouble axis0copy = constructedDetector.getAxis(0);
-    AxisDouble axis1copy = constructedDetector.getAxis(1);
+    const IAxis &axis0copy = constructedDetector.getAxis(0);
+    const IAxis &axis1copy = constructedDetector.getAxis(1);
     ASSERT_TRUE(axis0.getMin() == axis0copy.getMin() );
     ASSERT_TRUE(axis0.getMax() == axis0copy.getMax() );
     ASSERT_TRUE(axis0.getName() == axis0copy.getName() );
diff --git a/XCode_GISASFW.xcodeproj/project.pbxproj b/XCode_GISASFW.xcodeproj/project.pbxproj
index f6af84fb7eb7ba043463d43d540c2d6785e3ae36..2c9fc394500a5d38f3a4e4a1d7a155a547c7a154 100644
--- a/XCode_GISASFW.xcodeproj/project.pbxproj
+++ b/XCode_GISASFW.xcodeproj/project.pbxproj
@@ -7,6 +7,7 @@
 	objects = {
 
 /* Begin PBXBuildFile section */
+		62027ED516775A7700A0D41C /* AxisBin.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 62027ED416775A7700A0D41C /* AxisBin.cpp */; };
 		6204B7991667A408003BF358 /* IOutputDataNormalizer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6204B7981667A407003BF358 /* IOutputDataNormalizer.cpp */; };
 		6218B466161B2577007FFA5C /* FormFactorParallelepiped.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6218B465161B2577007FFA5C /* FormFactorParallelepiped.cpp */; };
 		6218B469161B25BC007FFA5C /* TestIsGISAXS11.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6218B468161B25BC007FFA5C /* TestIsGISAXS11.cpp */; };
@@ -235,6 +236,11 @@
 /* End PBXCopyFilesBuildPhase section */
 
 /* Begin PBXFileReference section */
+		62027ECF16775A6B00A0D41C /* AxisBin.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AxisBin.h; sourceTree = "<group>"; };
+		62027ED016775A6B00A0D41C /* Bin.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Bin.h; sourceTree = "<group>"; };
+		62027ED116775A6B00A0D41C /* IAxis.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IAxis.h; sourceTree = "<group>"; };
+		62027ED216775A6B00A0D41C /* SafePointerVector.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SafePointerVector.h; sourceTree = "<group>"; };
+		62027ED416775A7700A0D41C /* AxisBin.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = AxisBin.cpp; sourceTree = "<group>"; };
 		6204B7961667A3FC003BF358 /* IIntensityFunction.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IIntensityFunction.h; sourceTree = "<group>"; };
 		6204B7971667A3FC003BF358 /* IOutputDataNormalizer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IOutputDataNormalizer.h; sourceTree = "<group>"; };
 		6204B7981667A407003BF358 /* IOutputDataNormalizer.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = IOutputDataNormalizer.cpp; sourceTree = "<group>"; };
@@ -1675,6 +1681,10 @@
 		622222F2160CB745008205AC /* inc */ = {
 			isa = PBXGroup;
 			children = (
+				62027ECF16775A6B00A0D41C /* AxisBin.h */,
+				62027ED016775A6B00A0D41C /* Bin.h */,
+				62027ED116775A6B00A0D41C /* IAxis.h */,
+				62027ED216775A6B00A0D41C /* SafePointerVector.h */,
 				62D7A934166E3F81009A45CE /* AxisDouble.h */,
 				62CC097C166504D600A5B720 /* AttLimits.h */,
 				62CC097D166504D600A5B720 /* FitObject.h */,
@@ -1725,6 +1735,7 @@
 		6222230A160CB745008205AC /* src */ = {
 			isa = PBXGroup;
 			children = (
+				62027ED416775A7700A0D41C /* AxisBin.cpp */,
 				62D7A935166E3F8D009A45CE /* AxisDouble.cpp */,
 				62CC0986166504E700A5B720 /* FitObject.cpp */,
 				62CC0987166504E700A5B720 /* FitParameterLinked.cpp */,
@@ -68683,6 +68694,7 @@
 				6254C2651666652E0098EE7E /* IFormFactorBorn.cpp in Sources */,
 				6204B7991667A408003BF358 /* IOutputDataNormalizer.cpp in Sources */,
 				62D7A936166E3F8D009A45CE /* AxisDouble.cpp in Sources */,
+				62027ED516775A7700A0D41C /* AxisBin.cpp in Sources */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};
diff --git a/shared.pri b/shared.pri
index 8a97ab6dd4c5ed36cb6417b46122f7a933ede75d..305feea9f38f82a1ba591b7de6b398d68f830c6b 100644
--- a/shared.pri
+++ b/shared.pri
@@ -105,8 +105,7 @@ CONFIG(JCNS) {
 QMAKE_CXXFLAGS_DEBUG += -fdiagnostics-show-option # to find out in gcc which option control warning
 #QMAKE_CXXFLAGS_RELEASE += -O3 -ffast-math -msse3
 QMAKE_CXXFLAGS_RELEASE -= -O2
-QMAKE_CXXFLAGS_RELEASE += -g -O3
-#QMAKE_CXXFLAGS_RELEASE += -g -O3
+QMAKE_CXXFLAGS_RELEASE += -g -O3  # -ffast-math removed because of problems with NaNs
 # uncommenting line below produces non-stripped (very large) libraries
 #QMAKE_STRIP=: