Skip to content
Snippets Groups Projects
IsGISAXSTools.cpp 28.5 KiB
Newer Older
  • Learn to ignore specific revisions
  • // ************************************************************************** //
    
    //  BornAgain: simulate and fit scattering at grazing incidence
    //
    
    //! @file      App/src/IsGISAXSTools.cpp
    
    //! @brief     Implements class IsGISAXSTools.
    //
    //! Homepage:  apps.jcns.fz-juelich.de/BornAgain
    //! License:   GNU General Public License v3 or higher (see COPYING)
    //! @copyright Forschungszentrum Jülich GmbH 2013
    //! @authors   Scientific Computing Group at MLZ Garching
    
    //! @authors   C. Durniak, G. Pospelov, W. Van Herck, J. Wuttke
    
    //
    // ************************************************************************** //
    
    
    #include "BornAgainNamespace.h"
    
    #include "MathFunctions.h"
    
    pospelov's avatar
    pospelov committed
    #include "TH1D.h"
    #include "TH2D.h"
    #include "TH3D.h"
    
    pospelov's avatar
    pospelov committed
    #include "TLine.h"
    
    #include <sstream>
    #include <vector>
    #include <iterator>
    #include <iomanip>
    
    #include <cmath>
    
    pospelov's avatar
    pospelov committed
    #include <algorithm>
    
    double IsGISAXSTools::m_hist_min = 0;
    double IsGISAXSTools::m_hist_max = 0;
    bool   IsGISAXSTools::m_has_min = false;
    bool   IsGISAXSTools::m_has_max = false;
    
    Wuttke, Joachim's avatar
    Wuttke, Joachim committed
    //! Draw 2D histogram representing logarithm of OutputData (in new canvas).
    
    void IsGISAXSTools::drawLogOutputData(const OutputData<double>& output,
            const std::string& canvas_name, const std::string& canvas_title,
    
    Wuttke, Joachim's avatar
    Wuttke, Joachim committed
            const std::string& draw_options, const std::string& histogram_title)
    
    Wuttke, Joachim's avatar
    Wuttke, Joachim committed
        TCanvas *c1 = new
            TCanvas(canvas_name.c_str(), canvas_title.c_str(), 0, 0, 1024, 768);
    
        IsGISAXSTools::setMinimum(1.);
    
        gPad->SetLogz();
        drawOutputDataInPad(output, draw_options, histogram_title);
    
    //! Draw 4 2D histograms representing logarithm of polarized OutputData
    //! (in new canvas).
    
    void IsGISAXSTools::drawLogOutputDataPol(
            const OutputData<Eigen::Matrix2d>& output,
            const std::string& canvas_name, const std::string& canvas_title,
            const std::string& draw_options, const std::string& histogram_title)
    {
        assert(&output);
        TCanvas *c1 = new
            TCanvas(canvas_name.c_str(), canvas_title.c_str(), 0, 0, 1024, 768);
        c1->Divide(2,2);
    
        OutputData<double> data;
        data.copyShapeFrom(output);
    
        // plus - plus
        c1->cd(1); gPad->SetLogz();
        gPad->SetRightMargin(0.12);
        setMinimum(1.);
        copyElementsWithPosition(output, data, 0, 0);
        drawOutputDataInPad(data, draw_options, histogram_title + ": + +");
    
        // plus - min
        c1->cd(2); gPad->SetLogz();
        gPad->SetRightMargin(0.12);
        setMinimum(1.);
    
        copyElementsWithPosition(output, data, 0, 1);
    
        drawOutputDataInPad(data, draw_options, histogram_title + ": + -");
    
        // min - plus
        c1->cd(3); gPad->SetLogz();
        gPad->SetRightMargin(0.12);
        setMinimum(1.);
    
        copyElementsWithPosition(output, data, 1, 0);
    
        drawOutputDataInPad(data, draw_options, histogram_title + ": - +");
    
        // min - min
        c1->cd(4); gPad->SetLogz();
        gPad->SetRightMargin(0.12);
        setMinimum(1.);
        copyElementsWithPosition(output, data, 1, 1);
        drawOutputDataInPad(data, draw_options, histogram_title + ": - -");
    }
    
    
    Wuttke, Joachim's avatar
    Wuttke, Joachim committed
    //! Draw 2D histogram representing OutputData (in new canvas).
    
    
    void IsGISAXSTools::drawOutputData(const OutputData<double>& output,
            const std::string& canvas_name, const std::string& canvas_title,
    
    Wuttke, Joachim's avatar
    Wuttke, Joachim committed
            const std::string& draw_options, const std::string& histogram_title)
    
    Wuttke, Joachim's avatar
    Wuttke, Joachim committed
        TCanvas *c1 = new
            TCanvas(canvas_name.c_str(), canvas_title.c_str(), 0, 0, 1024, 768);
    
        c1->cd();
        drawOutputDataInPad(output, draw_options, histogram_title);
    }
    
    Wuttke, Joachim's avatar
    Wuttke, Joachim committed
    //! Draw 1D or 2D histograms representing OutputData (in current gPad).
    
    
    void IsGISAXSTools::drawOutputDataInPad(const OutputData<double>& output,
    
    Wuttke, Joachim's avatar
    Wuttke, Joachim committed
            const std::string& draw_options, const std::string& histogram_title)
    
        if( !&output) throw NullPointerException("IsGISAXSTools::drawOutputDataInPad() -> Error! Null output data");
    
        if(!gPad) {
            throw NullPointerException("IsGISAXSTools::drawOutputDataInPad() -> Error! No canvas exists.");
        }
    
    Wuttke, Joachim's avatar
    Wuttke, Joachim committed
        if(output.getRank() == 2 ) {
    
            hist = IsGISAXSTools::getOutputDataTH2D(output, "p_hist1D");
        } else {
            hist = IsGISAXSTools::getOutputDataTH123D(output, "p_hist1D");
        }
        hist->SetContour(99);
    
    pospelov's avatar
    pospelov committed
        gStyle->SetPalette(1);
        gStyle->SetOptStat(0);
    
        if( hasMinimum() ) hist->SetMinimum(m_hist_min);
        if( hasMaximum() ) hist->SetMaximum(m_hist_max);
        hist->SetTitle(histogram_title.c_str());
        hist->DrawCopy(draw_options.c_str());
    
    
        // dealing with masks
        if(output.getMask()) {
            TPolyMarker *poly = new TPolyMarker();
            const IAxis *p_axis0 = output.getAxis(0);
            const IAxis *p_axis1 = output.getAxis(1);
            int i_point(0);
    
    Wuttke, Joachim's avatar
    Wuttke, Joachim committed
            for(OutputData<double>::const_iterator it = output.begin();
                it!= output.end(); ++it) {
    
                size_t axis0_index = output.toCoordinate(it.getIndex(), 0);
                size_t axis1_index = output.toCoordinate(it.getIndex(), 1);
                double axis0_value = (*p_axis0)[axis0_index];
                double axis1_value = (*p_axis1)[axis1_index];
                poly->SetPoint(i_point++, axis0_value, axis1_value);
            }
            poly->Draw("same");
        }
    
    
    //! Creates TH2D from OutputData.
    
    Wuttke, Joachim's avatar
    Wuttke, Joachim committed
    TH2D *IsGISAXSTools::getOutputDataTH2D(const OutputData<double>& output,
                                           const std::string& histo_name)
    
    Wuttke, Joachim's avatar
    Wuttke, Joachim committed
        if (output.getRank() !=2)
    
    Wuttke, Joachim's avatar
    Wuttke, Joachim committed
            throw( "IsGISAXSTools::getOutputDataTH2D() -> "
                   "Warning! Expected number of dimensiobs is 2.");
    
    Wuttke, Joachim's avatar
    Wuttke, Joachim committed
        haxises.resize(output.getRank());
    
        // we assume variable bin size and prepare [nbins+1] array of left edges of each bin plus right edge of the last bin
    
    Wuttke, Joachim's avatar
    Wuttke, Joachim committed
        for(size_t i_axis=0; i_axis<output.getRank(); ++i_axis) {
    
            if( !axis ) throw("IsGISAXSTools::getOutputDataTH123D() -> Error! Can't cast axis");
    
            haxises[i_axis].nbins = axis->getSize();
            haxises[i_axis].name = axis->getName();
            if( axis->getSize() == 0) {
                throw LogicErrorException("IsGISAXSTools::getOutputDataTH123D() -> Error! Axis with zero size.");
            }else if( axis->getSize() == 1 ) {
                // only one bin, let's invent fake bin size
                dx = 0.1*(*axis)[0];
                haxises[i_axis].xbins.push_back((*axis)[0]-dx/2.);
                haxises[i_axis].xbins.push_back((*axis)[0]+dx/2.);
            }else {
                for(size_t i_bin=0; i_bin<axis->getSize(); ++i_bin) {
                    if(i_bin == 0) {
                        dx = (*axis)[1]-(*axis)[0];
                    } else {
                        dx = (*axis)[i_bin] - (*axis)[i_bin-1];
                    }
                    haxises[i_axis].xbins.push_back( (*axis)[i_bin] - dx/2.);
    
            haxises[i_axis].xbins.push_back((*axis)[axis->getSize()-1] + dx/2.); // right bin edge of last bin, so for 100 bins size of vector will be 101
    
    //    std::cout << "XXXYYY " << (int)haxises[0].nbins << " "  << (int)haxises[1].nbins;
    
    pospelov's avatar
    pospelov committed
    //    for(size_t i=0; i<haxises[0].xbins.size(); ++i) {
    //        std::cout << i << " axis0:" << haxises[0].xbins[i] << std::endl;
    //    }
    //    for(size_t i=0; i<haxises[1].xbins.size(); ++i) {
    //        std::cout << i << " axis1:" << haxises[1].xbins[i] << std::endl;
    //    }
    
    
        TH2D *hist2 = new TH2D(histo_name.c_str(), histo_name.c_str(), (int)haxises[0].nbins, &haxises[0].xbins[0], (int)haxises[1].nbins, &haxises[1].xbins[0]);
    
        hist2->GetXaxis()->SetTitle( haxises[0].name.c_str() );
        hist2->GetYaxis()->SetTitle( haxises[1].name.c_str() );
    
        OutputData<double>::const_iterator it = output.begin();
        while (it != output.end())
    
            double x = output.getValueOfAxis( haxises[0].name.c_str(), it.getIndex() );
            double y = output.getValueOfAxis( haxises[1].name.c_str(), it.getIndex() );
    
        hist2->SetContour(50);
        hist2->SetStats(0);
        hist2->GetYaxis()->SetTitleOffset(1.1);
    
    
        gStyle->SetPalette(1);
        gStyle->SetOptStat(0);
    
    
    /* ************************************************************************* */
    // create TH2D from OutputData
    /* ************************************************************************* */
    //TH2D *IsGISAXSTools::getOutputDataTH2D(const OutputData<double>& output, const std::string &histo_name)
    //{
    //    assert(&output);
    //    if (output.getNdimensions() !=2) throw( "IsGISAXSTools::getOutputDataTH2D() -> Warning! Expected number of dimensiobs is 2.");
    
    //    std::vector<AxisStructure > haxises;
    //    haxises.resize(output.getNdimensions());
    
    //    // 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 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();
    //        haxises[i_axis].name = axis->getName();
    //        if( axis->getSize() == 0) {
    //            throw LogicErrorException("IsGISAXSTools::getOutputDataTH123D() -> Error! Axis with zero size.");
    //        }else if( axis->getSize() == 1 ) {
    //            // only one bin, let's invent fake bin size
    //            dx = 0.1*(*axis)[0];
    //            haxises[i_axis].xbins.push_back((*axis)[0]-dx/2.);
    //            haxises[i_axis].xbins.push_back((*axis)[0]+dx/2.);
    //        }else {
    //            for(size_t i_bin=0; i_bin<axis->getSize(); ++i_bin) {
    //                if(i_bin == 0) {
    //                    dx = (*axis)[1]-(*axis)[0];
    //                } else {
    //                    dx = (*axis)[i_bin] - (*axis)[i_bin-1];
    //                }
    //                haxises[i_axis].xbins.push_back( (*axis)[i_bin] - dx/2.);
    //            }
    //        haxises[i_axis].xbins.push_back((*axis)[axis->getSize()-1] + dx/2.); // right bin edge of last bin, so for 100 bins size of vector will be 101
    //        }
    //    }
    
    //    // creation of 2D with variable bin size
    //    std::cout << "XXXYYY " << (int)haxises[0].nbins << " "  << (int)haxises[1].nbins;
    //    for(size_t i=0; i<haxises[0].xbins.size(); ++i) {
    //        std::cout << i << " axis0:" << haxises[0].xbins[i] << std::endl;
    //    }
    //    for(size_t i=0; i<haxises[1].xbins.size(); ++i) {
    //        std::cout << i << " axis1:" << haxises[1].xbins[i] << std::endl;
    //    }
    
    //    TH2D *hist2 = new TH2D(histo_name.c_str(), histo_name.c_str(), (int)haxises[0].nbins, &haxises[0].xbins[0], (int)haxises[1].nbins, &haxises[1].xbins[0]);
    //    hist2->GetXaxis()->SetTitle( haxises[0].name.c_str() );
    //    hist2->GetYaxis()->SetTitle( haxises[1].name.c_str() );
    
    //    OutputData<double>::const_iterator it = output.begin();
    //    while (it != output.end())
    //    {
    //        double x = output.getValueOfAxis( haxises[0].name.c_str(), it.getIndex() );
    //        double y = output.getValueOfAxis( haxises[1].name.c_str(), it.getIndex() );
    //        double value = *it++;
    //        //std::cout << "OOO " << x << " " << y << std::endl;
    //        hist2->Fill(x, y, value);
    //    }
    //    hist2->SetContour(50);
    //    hist2->SetStats(0);
    //    hist2->GetYaxis()->SetTitleOffset(1.1);
    
    //    gStyle->SetPalette(1);
    //    gStyle->SetOptStat(0);
    //    return hist2;
    //}
    
    
    
    /* ************************************************************************* */
    // create TH1D, TH2D or TH3D from OutputData
    /* ************************************************************************* */
    
    Wuttke, Joachim's avatar
    Wuttke, Joachim committed
    TH1 *IsGISAXSTools::getOutputDataTH123D(const OutputData<double>& output, const std::string& histo_name)
    
    Wuttke, Joachim's avatar
    Wuttke, Joachim committed
        if (output.getRank() >3) {
    
            std::cout << "IsGISAXSTools::getOutputDataTH123D() -> Warning! Expected number of dimensions should be not more than 3" << std::endl;
            return 0;
        }
    
        std::vector<AxisStructure > haxises;
    
    Wuttke, Joachim's avatar
    Wuttke, Joachim committed
        haxises.resize(output.getRank());
    
        // we assume variable bin size and prepare [nbins+1] array of left edges of each bin plus right edge of the last bin
    
    Wuttke, Joachim's avatar
    Wuttke, Joachim committed
        for(size_t i_axis=0; i_axis<output.getRank(); ++i_axis) {
    
            if( !axis ) throw("IsGISAXSTools::getOutputDataTH123D() -> Error! Can't cast axis");
    
            double dx(0);
            haxises[i_axis].nbins = axis->getSize();
            haxises[i_axis].name = axis->getName();
    
            if( axis->getSize() == 0) {
                throw LogicErrorException("IsGISAXSTools::getOutputDataTH123D() -> Error! Axis with zero size.");
            }else if( axis->getSize() == 1 ) {
                // only one bin, let's invent fake bin size
                dx = 0.1*(*axis)[0];
                haxises[i_axis].xbins.push_back((*axis)[0]-dx/2.);
                haxises[i_axis].xbins.push_back((*axis)[0]+dx/2.);
            }else {
                for(size_t i_bin=0; i_bin<axis->getSize(); ++i_bin) {
                    if(i_bin == 0) {
                        dx = (*axis)[1]-(*axis)[0];
                    } else {
                        dx = (*axis)[i_bin] - (*axis)[i_bin-1];
                    }
                    haxises[i_axis].xbins.push_back( (*axis)[i_bin] - dx/2.);
    
                }
            haxises[i_axis].xbins.push_back((*axis)[axis->getSize()-1] + dx/2.); // right bin edge of last bin, so for 100 bins size of vector will be 101
    
    //    for(size_t i_axis=0; i_axis<output.getNdimensions(); ++i_axis) {
    //       std::cout << "axis " << i_axis << " size:" << haxises[i_axis].xbins.size() << std::endl;
    //       for(size_t i_bin=0; i_bin<haxises[i_axis].xbins.size(); ++i_bin) {
    //           std::cout << haxises[i_axis].xbins[i_bin] << " ";
    //       }
    //       std::cout << std::endl;
    
        // creation of 1D, 2D or 3D histogram with variable bin size
    
        TH1 *hist(0);
        TH1D *hist1(0);
        TH2D *hist2(0);
        TH3D *hist3(0);
    
    Wuttke, Joachim's avatar
    Wuttke, Joachim committed
        if(output.getRank() == 1) {
    
            hist1 = new TH1D(histo_name.c_str(), histo_name.c_str(), (int)haxises[0].nbins, &haxises[0].xbins[0]);
    
            hist1->GetXaxis()->SetTitle( haxises[0].name.c_str() );
            hist = hist1;
    
    Wuttke, Joachim's avatar
    Wuttke, Joachim committed
        } else if(output.getRank() == 2) {
    
            hist2 = new TH2D(histo_name.c_str(), histo_name.c_str(), (int)haxises[0].nbins, &haxises[0].xbins[0], (int)haxises[1].nbins, &haxises[1].xbins[0]);
    
            hist2->GetXaxis()->SetTitle( haxises[0].name.c_str() );
            hist2->GetYaxis()->SetTitle( haxises[1].name.c_str() );
            hist = hist2;
    
    Wuttke, Joachim's avatar
    Wuttke, Joachim committed
        } else if(output.getRank() == 3) {
    
            hist3 = new TH3D(histo_name.c_str(), histo_name.c_str(), (int)haxises[0].nbins, &haxises[0].xbins[0], (int)haxises[1].nbins, &haxises[1].xbins[0], (int)haxises[1].nbins, &haxises[1].xbins[0]);
    
            hist3->GetXaxis()->SetTitle( haxises[0].name.c_str() );
            hist3->GetYaxis()->SetTitle( haxises[1].name.c_str() );
            hist3->GetZaxis()->SetTitle( haxises[2].name.c_str() );
            hist = hist3;
    
            throw LogicErrorException("IsGISAXSTools::getOutputDataTH123D() -> Error! Wrong number of dimensions.");
    
        }
    
        OutputData<double>::const_iterator it = output.begin();
        while (it != output.end())
        {
            std::vector<double > xyz;
            for(size_t i_axis=0; i_axis<haxises.size(); ++i_axis) {
    
                xyz.push_back(output.getValueOfAxis( haxises[i_axis].name.c_str(), it.getIndex() ) );
    
            if(hist1) hist1->Fill(xyz[0], value);
            if(hist2) hist2->Fill(xyz[0], xyz[1], value);
            if(hist3) hist3->Fill(xyz[0], xyz[1], xyz[2], value);
    
        }
        hist->SetContour(50);
        hist->SetStats(0);
        hist->GetYaxis()->SetTitleOffset(1.1);
    
        gStyle->SetPalette(1);
        gStyle->SetOptStat(0);
        return hist;
    }
    
    
    
    
    /* ************************************************************************* */
    // draw 1D distribution over values stored in OutputData
    // binning of histogram is calculated on the fly
    /* ************************************************************************* */
    
    Wuttke, Joachim's avatar
    Wuttke, Joachim committed
    void IsGISAXSTools::drawOutputDataDistribution1D(const OutputData<double>& output, const std::string& draw_options, const std::string& histogram_title)
    
        if(!gPad) {
            throw NullPointerException("IsGISAXSTools::drawOutputDataDistribution1D() -> Error! No canvas exists.");
        }
    
    
        std::string histo_name = histogram_title;
        if (histo_name.empty()) {
            histo_name = gPad->GetTitle();
        }
    
        // creating histogram with automatic binning
        TH1::SetDefaultBufferSize(5000);
        TH1D h1_spect("h1_spect", histo_name.c_str(), 200, 1.0, -1.0); // xmin > xmax as a sign of automatic binning
    
    
        OutputData<double>::const_iterator it = output.begin();
        while (it != output.end())
    
            h1_spect.Fill( *it++ );
    
        }
    
        h1_spect.DrawCopy(draw_options.c_str());
    }
    
    
    /* ************************************************************************* */
    // draw 1D distribution over relative difference in two OutputData sets
    /* ************************************************************************* */
    
    Wuttke, Joachim's avatar
    Wuttke, Joachim committed
    void IsGISAXSTools::drawOutputDataDifference1D(const OutputData<double>& left, const OutputData<double>& right, const std::string& draw_options, const std::string& histogram_title)
    
        if(!gPad) {
            throw NullPointerException("IsGISAXSTools::drawOutputDataDifference1D() -> Error! No canvas exists.");
        }
    
    
        OutputData<double> *left_clone = left.clone();
        OutputData<double> *right_clone = right.clone();
    
        *left_clone -= *right_clone;
        *left_clone /= *right_clone;
    
        std::string histo_name = histogram_title;
        if (histo_name.empty()) {
            histo_name = gPad->GetTitle();
        }
    
    
        TH1D h1_spect("difference", histo_name.c_str(), 40, -20.0, 20.0);
    
    Van Herck, Walter's avatar
    Van Herck, Walter committed
        h1_spect.GetXaxis()->SetTitle("log10( (we-isgi)/isgi )");
    
        OutputData<double>::const_iterator it = left_clone->begin();
        while (it != left_clone->end())
    
            double x = *it++;
    
                // lets put the cases when the difference is exactly 0 to underflow bin
    
    pospelov's avatar
    pospelov committed
            h1_spect.Fill( x );
    
    //    gPad->SetLogy();
    
    pospelov's avatar
    pospelov committed
        gPad->SetRightMargin(0.115);
        gPad->SetLeftMargin(0.115);
    
        h1_spect.SetStats(1);
        gStyle->SetOptStat(111111);
    
    pospelov's avatar
    pospelov committed
        if( hasMinimum() ) h1_spect.SetMinimum(m_hist_min);
        if( hasMaximum() ) h1_spect.SetMaximum(m_hist_max);
    
    
        h1_spect.DrawCopy(draw_options.c_str());
        delete left_clone;
        delete right_clone;
    }
    
    
    /* ************************************************************************* */
    // draw relative difference of two 2D OutputData sets
    /* ************************************************************************* */
    
    Wuttke, Joachim's avatar
    Wuttke, Joachim committed
    void IsGISAXSTools::drawOutputDataRelativeDifference2D(const OutputData<double>& left, const OutputData<double>& right, const std::string& draw_options, const std::string& histogram_title)
    
        if(!gPad) {
            throw NullPointerException("IsGISAXSTools::drawOutputDataDifference2D -> Error! No canvas exists.");
        }
    
        OutputData<double> *left_clone = left.clone();
        OutputData<double> *right_clone = right.clone();
    
        *left_clone -= *right_clone;
        *left_clone /= *right_clone;
        left_clone->scaleAll(100.0);
    
        IsGISAXSTools::drawOutputDataInPad(*left_clone, draw_options, histogram_title);
    
        delete left_clone;
        delete right_clone;
    }
    
    
    
    /* ************************************************************************* */
    // draw relative chi2 difference of two 2D OutputData sets
    /* ************************************************************************* */
    
    Wuttke, Joachim's avatar
    Wuttke, Joachim committed
    void IsGISAXSTools::drawOutputDataChi2Difference2D(const OutputData<double>& left, const OutputData<double>& right, const std::string& draw_options, const std::string& histogram_title)
    
        if(!gPad) {
            throw NullPointerException("IsGISAXSTools::drawOutputDataDifference2D -> Error! No canvas exists.");
        }
        OutputData<double> *left_clone = left.clone();
        OutputData<double> *right_clone = right.clone();
    
        *left_clone -= *right_clone;
        OutputData<double> *tmp = left_clone->clone();
    
        *left_clone *= *tmp;
        left_clone->scaleAll(1./left_clone->totalSum());
    
        IsGISAXSTools::drawOutputDataInPad(*left_clone, draw_options, histogram_title);
    
        delete left_clone;
        delete right_clone;
        delete tmp;
    }
    
    
    
    Wuttke, Joachim's avatar
    Wuttke, Joachim committed
    void IsGISAXSTools::exportOutputDataInVectors2D(const OutputData<double>& input_data
                                            , std::vector<std::vector<double > >& v_data
                                            , std::vector<std::vector<double > >& v_axis0
                                            , std::vector<std::vector<double > >& v_axis1)
    
        assert(&input_data);
        if (input_data.getRank() != 2) return;
    
        OutputData<double> *data = input_data.clone();
    
        const IAxis *p_axis0 = data->getAxis(0);
        const IAxis *p_axis1 = data->getAxis(1);
    
        size_t axis0_size = p_axis0->getSize();
        size_t axis1_size = p_axis1->getSize();
    
        v_data.clear();
        v_axis0.clear();
        v_axis1.clear();
    
        v_data.resize(axis0_size);
        v_axis0.resize(axis0_size);
        v_axis1.resize(axis0_size);
    
        for(size_t i=0; i<axis0_size; ++i) {
            v_data[i].resize(axis1_size,0.0);
            v_axis0[i].resize(axis1_size,0.0);
            v_axis1[i].resize(axis1_size,0.0);
        }
    
    
        // saving data
        OutputData<double>::const_iterator it = data->begin();
        while (it != data->end())
    
            size_t axis0_index = data->toCoordinates(it.getIndex())[0];
            size_t axis1_index = data->toCoordinates(it.getIndex())[1];
    
            double intensity = *it++;
    
            v_data[axis0_index][axis1_index] = intensity;
    
        }
    
        // saving axis
        data->removeAllMasks();
        it = data->begin();
        while (it != data->end())
        {
            size_t axis0_index = data->toCoordinates(it.getIndex())[0];
            size_t axis1_index = data->toCoordinates(it.getIndex())[1];
            double axis0_value = (*p_axis0)[axis0_index];
            double axis1_value = (*p_axis1)[axis1_index];
    
            v_axis0[axis0_index][axis1_index] = axis0_value;
            v_axis1[axis0_index][axis1_index] = axis1_value;
    
    pospelov's avatar
    pospelov committed
    /* ************************************************************************* */
    // Create TLine for displaying of one-dimensional data scan
    // OutputData should be 2D, and one of two dimensions should have number of bins == 1
    /* ************************************************************************* */
    
    Wuttke, Joachim's avatar
    Wuttke, Joachim committed
    TLine *IsGISAXSTools::getOutputDataScanLine(const OutputData<double>& data)
    
    pospelov's avatar
    pospelov committed
    {
    
    Wuttke, Joachim's avatar
    Wuttke, Joachim committed
        if(data.getRank() != 2) throw LogicErrorException("IsGISAXSTools::getOutputDataScanLine() -> Error! Number of dimensions should be 2");
    
    pospelov's avatar
    pospelov committed
        double x1(0), x2(0), y1(0), y2(0);
    
        if( data.getAxis(BA::ALPHA_AXIS_NAME) && data.getAxis(BA::ALPHA_AXIS_NAME)->getSize() == 1) {
    
    pospelov's avatar
    pospelov committed
            // horizontal line
    
            x1 = data.getAxis(BA::PHI_AXIS_NAME)->getMin();
            x2 = data.getAxis(BA::PHI_AXIS_NAME)->getMax();
            y1 = y2 = data.getAxis(BA::ALPHA_AXIS_NAME)->getMin();
        }else if( data.getAxis(BA::PHI_AXIS_NAME) && data.getAxis(BA::PHI_AXIS_NAME)->getSize() == 1 ) {
    
    pospelov's avatar
    pospelov committed
            // it's vertical line
    
            x1 = x2 = data.getAxis(BA::PHI_AXIS_NAME)->getMin();
            y1 = data.getAxis(BA::ALPHA_AXIS_NAME)->getMin();
            y2 = data.getAxis(BA::ALPHA_AXIS_NAME)->getMax();
    
    pospelov's avatar
    pospelov committed
        } else {
            throw LogicErrorException("IsGISAXSTools::getOutputDataScanLine() -> Error! Can't handle these axes.");
        }
        TLine *line = new TLine(x1,y1,x2,y2);
        line->SetLineColor(kRed);
        line->SetLineStyle(1);
        line->SetLineWidth(2);
        return line;
    }
    
    
    /* ************************************************************************* */
    // Create TH1D for displaying of one-dimensional data scan
    // OutputData should be 2D, and one of two dimensions should have number of bins == 1
    /* ************************************************************************* */
    
    Wuttke, Joachim's avatar
    Wuttke, Joachim committed
    TH1D *IsGISAXSTools::getOutputDataScanHist(const OutputData<double>& data, const std::string& hname)
    
    pospelov's avatar
    pospelov committed
    {
    
    Wuttke, Joachim's avatar
    Wuttke, Joachim committed
        if(data.getRank() != 2) throw LogicErrorException("IsGISAXSTools::getOutputDataScanHist() -> Error! Number of dimensions should be 2");
    
        if( (data.getAxis(BA::ALPHA_AXIS_NAME) && data.getAxis(BA::ALPHA_AXIS_NAME)->getSize() != 1) && (data.getAxis(BA::PHI_AXIS_NAME) && data.getAxis(BA::PHI_AXIS_NAME)->getSize() != 1))
    
    pospelov's avatar
    pospelov committed
        {
    
            throw LogicErrorException("IsGISAXSTools::getOutputDataScanHist() -> Info. Can't create 1D histogram from these axes");
            //std::cout << "IsGISAXSTools::getOutputDataScanHist() -> Info. Can't create 1D histogram from these axes" << std::endl;
            //return 0;
    
        TH2D *hist2 = IsGISAXSTools::getOutputDataTH2D( data, hname);
    
    pospelov's avatar
    pospelov committed
    
        TH1D *hist1(0);
    
        if( data.getAxis(BA::ALPHA_AXIS_NAME) && data.getAxis(BA::ALPHA_AXIS_NAME)->getSize() == 1) {
    
            ostr_title << hname << ", alpha_f=" << data.getAxis(BA::ALPHA_AXIS_NAME)->getMin();
        }else if( data.getAxis(BA::PHI_AXIS_NAME) && data.getAxis(BA::PHI_AXIS_NAME)->getSize() == 1 ) {
    
            ostr_title << hname << ", phi_f=" << data.getAxis(BA::PHI_AXIS_NAME)->getMin();
    
    pospelov's avatar
    pospelov committed
        } else {
            throw LogicErrorException("IsGISAXSTools::getOutputDataScanHist() -> Error! Unexpected place");
        }
        delete hist2;
    
        if( !hist1 ) throw LogicErrorException("IsGISAXSTools::getOutputDataScanHist() -> Error! Failed to make projection, existing name?");
    
        hist1->SetTitle(ostr_title.str().c_str());
    
        // FIXME remove this trick to bypass weird bug with DrawCopy of TH1D projection of TH1D histograms
    
        TH1D *h1 = dynamic_cast<TH1D*>(hist1->Clone());
    
    /* ************************************************************************* */
    // add noise to data
    /* ************************************************************************* */
    
    Wuttke, Joachim's avatar
    Wuttke, Joachim committed
    OutputData<double > *IsGISAXSTools::createNoisyData(const OutputData<double>& exact_data, double noise_factor)
    
        OutputData<double > *real_data = exact_data.clone();
        OutputData<double>::iterator it = real_data->begin();
        while (it != real_data->end()) {
            double current = *it;
            double sigma = noise_factor*std::sqrt(current);
            double random = MathFunctions::GenerateNormalRandom(current, sigma);
            if (random<0.0) random = 0.0;
            *it = random;
            ++it;
        }
        return real_data;
    }
    
    
    Wuttke, Joachim's avatar
    Wuttke, Joachim committed
    OutputData<double > *IsGISAXSTools::createDataWithGaussianNoise(const OutputData<double>& exact_data, double sigma)
    
        OutputData<double > *real_data = exact_data.clone();
        OutputData<double>::iterator it = real_data->begin();
        while (it != real_data->end()) {
            double current = *it;
            double random = MathFunctions::GenerateNormalRandom(0.0, sigma);
            *it = current+random;
            ++it;
        }
        return real_data;
    }
    
    
    void IsGISAXSTools::drawOutputDataComparisonResults(
            const OutputData<double>& data, const OutputData<double>& reference,
            const std::string& name, const std::string& title, double hmin,
            double hmax, double hdiff)
    
        assert(&data);
        assert(&reference);
    
        TCanvas *c1 = DrawHelper::createAndRegisterCanvas(name, title);
    
        c1->Divide(2,2);
    
        // our calculations
        c1->cd(1); gPad->SetLogz();
        gPad->SetRightMargin(0.12);
    
        if(hasMinimum()) IsGISAXSTools::setMinimum(hmin);
        //if(hmax>0) IsGISAXSTools::setMaximum(hmax);
        if(hasMaximum()) IsGISAXSTools::setMaximum(hmax);
    
        IsGISAXSTools::drawOutputDataInPad(data, "CONT4 Z", "this");
    
        // isgisaxs data
        c1->cd(2); gPad->SetLogz();
        gPad->SetRightMargin(0.12);
        IsGISAXSTools::drawOutputDataInPad(reference, "CONT4 Z", "isgi");
    
        // difference
        c1->cd(3);
        gPad->SetRightMargin(0.12);
    
        IsGISAXSTools::setMinimum(-hdiff);
        IsGISAXSTools::setMaximum(hdiff);
    
        IsGISAXSTools::drawOutputDataRelativeDifference2D(data, reference,
                "CONT4 Z", "2D Difference map");
    
    
        // difference
        c1->cd(4);
        gPad->SetRightMargin(0.12);
        IsGISAXSTools::resetMinimumAndMaximum();
        IsGISAXSTools::setMinimum(1);
    
        IsGISAXSTools::drawOutputDataDifference1D(data, reference, "",
                "Difference spectra");
    
    void IsGISAXSTools::copyElementsWithPosition(
            const OutputData<Eigen::Matrix2d>& source,
            OutputData<double>& destination, int pos_x, int pos_y)
    {
        OutputData<Eigen::Matrix2d>::const_iterator it_source =
                source.begin();
        OutputData<double>::iterator it_dest = destination.begin();
        while (it_source != source.end()) {
            *it_dest = (*it_source)(pos_x, pos_y);
            it_source++;
            it_dest++;
        }
    }