#include "DataProcessing.h"
#include "FemtoUtils.h"
#include "HbtFitter.h"
#include <TLegend.h>
#include <TCanvas.h>
#include <TMath.h>

const Double_t MHC     = 0.197326960277;  // GeV * fm
const Double_t MHC_SQR = 0.038937929230;  // GeV^2 *fm^2
const Double_t INVSQRTPI = 0.564189584;   // 1/sqrt(pi)

vector<double> DoFit(TH1* histo, Int_t PartType=4,
                     Int_t SourceFunc=0, Int_t NonFemtoFunc=1,
                     Bool_t DrawFitLegend=false, Bool_t ExcludePoints=false); //Histogram, ParticleType, SourceFuncType, NonFemtoFuncType,DrawLegend

vector<double> DoSeparatedFit(TH1* expHisto, TH1* mcHisto, Int_t PartType=4,
                              Int_t SourceFunc=0, Int_t NonFemtoFunc=1,
                              Bool_t DrawFitLegend=false);

//_________________
DataProcessing::DataProcessing() {

  mExpFileName = "~/work/star/data/pp200/expMesonHBT_pp200_2012.root";
  mMcFileName = "~/work/star/data/pp200/mcMesonHbtFemtoDst_pp200_tuneA.root";
  mOutFileName = "~/work/star/soft/star_software/processing/pp/oMeson_pp200_1D.root";

  mQinvBins = 120;
  mQinvLow = 0.;
  mQinvHi = 2.4;

  mExpFile = NULL;
  mMcFile = NULL;
  mOutFile = NULL;

  mUseMC = true;
  mDoFit = true;
  mProcInt = true;
  mProcMult = true;
  mProcKt = true;
  mIsKaon = true;

  mDetSelection = 2;

  mExpColor = 2;
  mExpLineWidth = 2;
  mExpMarkerStyle = 20;
  mExpMarkerSize = 1.5;

  mMcColor = 4;
  mMcLineWidth = 2;
  mMcMarkerStyle = 24;
  mMcMarkerSize = 1.5;

  mCorrFctnColor = 1;
  mCorrFctnLineWidth = 2;
  mCorrFctnMarkerStyle = 20;
  mCorrFctnMarkerSize = 1.5;

  mYaxisLo = 0.6;
  mYaxisHi = 1.8;

  //Intervals to get
  mMultVals = 3;
  mKtVals = 4;

  //How many bins to read
  mMultBins = 3;
  mKtBins = 10;

  mSourceFunc = 0;
  mNonFemtoFunc = 1;
  mDrawLegend = true;
}

//_________________
DataProcessing::~DataProcessing() {

}

//_________________
void DataProcessing::SetExpStyle(Int_t color, Int_t width, Int_t style, Double_t size) {
  mExpColor = color;
  mExpLineWidth = width;
  mExpMarkerStyle = style;
  mExpMarkerSize = size;
}

//_________________
void DataProcessing::SetMcStyle(Int_t color, Int_t width, Int_t style, Double_t size) {
  mMcColor = color;
  mMcLineWidth = width;
  mMcMarkerStyle = style;
  mMcMarkerSize = size;
}

//_________________
void DataProcessing::SetCorrFctnStyle(Int_t color, Int_t width, Int_t style, Double_t size) {
  mCorrFctnColor = color;
  mCorrFctnLineWidth = width;
  mCorrFctnMarkerStyle = style;
  mCorrFctnMarkerSize = size;
}

//_________________
void DataProcessing::DoProcessing() {

  std::cout << "Start processing..." << std::endl;
  OpenFiles();
  ReadHistos();
  ProcessHistos();
  if (mDoFit) {
    FitHistos();
    if (!mUseMC)
      PrintFitUncorrectedParms();
    else
      PrintFitCorrectedParms();
  }
  Finish();
  std::cout << "Processing is finished" << std::endl;
}

//_________________
void DataProcessing::OpenFiles() {

  std::cout << "Opening file with experimental data: " << mExpFileName;
  mExpFile = TFile::Open(mExpFileName);
  std::cout << "\t [DONE]" << std::endl;
  std::cout << "Opening file with simulated data: " << mMcFileName;
  mMcFile = TFile::Open(mMcFileName);
  std::cout << "\t [DONE]" << std::endl;
  std::cout << "Creating output file: " << mOutFileName;
  mOutFile = new TFile(mOutFileName,"recreate");
  std::cout << "\t [DONE]" << std::endl;
}

//_________________
void DataProcessing::ReadHistos() {

  std::cout << "Retrieving histograms from files...";

  for(Int_t iCharge=0; iCharge<2; iCharge++) {
    for(Int_t iMult=0; iMult<mMultBins; iMult++) {
      if (mIsKaon) {
        //Kaons
        TH1F *hExpKaonMixNum =
            (TH1F*)mExpFile->Get(Form("hKaonQinvMixMult_MomAndEnCons_%d_%d_Num",
                                      iCharge,
                                      iMult));
        TH1F *hExpKaonMixDen =
            (TH1F*)mExpFile->Get(Form("hKaonQinvMixMult_MomAndEnCons_%d_%d_Den",
                                      iCharge,
                                      iMult));
        hExpKaonQinvMixNum.push_back(hExpKaonMixNum);
        hExpKaonQinvMixDen.push_back(hExpKaonMixDen);

        TH1F *hExpKaonRotNum =
            (TH1F*)mExpFile->Get(Form("hKaonQinvRotMult_%d_%d_Num",
                                      iCharge,
                                      iMult));
        TH1F *hExpKaonRotDen =
            (TH1F*)mExpFile->Get(Form("hKaonQinvRotMult_%d_%d_Den",
                                      iCharge,
                                      iMult));
        hExpKaonQinvRotNum.push_back(hExpKaonRotNum);
        hExpKaonQinvRotDen.push_back(hExpKaonRotDen);

        TH1F *hExpKaonOppNum =
            (TH1F*)mExpFile->Get(Form("hKaonQinvOppMult_%d_%d_Num",
                                      iCharge,
                                      iMult));
        TH1F *hExpKaonOppDen =
            (TH1F*)mExpFile->Get(Form("hKaonQinvOppMult_%d_%d_Den",
                                      iCharge,
                                      iMult));
        hExpKaonQinvOppNum.push_back(hExpKaonOppNum);
        hExpKaonQinvOppDen.push_back(hExpKaonOppDen);
      }
      else {
        //Pions

        TH1F *hExpPionMixNum =
            (TH1F*)mExpFile->Get(Form("hPionQinvMixMult_%d_%d_Num",
                                      iCharge,
                                      iMult));
        TH1F *hExpPionMixDen =
            (TH1F*)mExpFile->Get(Form("hPionQinvMixMult_%d_%d_Den",
                                      iCharge,
                                      iMult));
        hExpPionQinvMixNum.push_back(hExpPionMixNum);
        hExpPionQinvMixDen.push_back(hExpPionMixDen);

        TH1F *hExpPionRotNum =
            (TH1F*)mExpFile->Get(Form("hPionQinvRotMult_%d_%d_Num",
                                      iCharge,
                                      iMult));
        TH1F *hExpPionRotDen =
            (TH1F*)mExpFile->Get(Form("hPionQinvRotMult_%d_%d_Den",
                                      iCharge,
                                      iMult));
        hExpPionQinvRotNum.push_back(hExpPionRotNum);
        hExpPionQinvRotDen.push_back(hExpPionRotDen);

        TH1F *hExpPionOppNum =
            (TH1F*)mExpFile->Get(Form("hPionQinvOppMult_%d_%d_Num",
                                      iCharge,
                                      iMult));
        TH1F *hExpPionOppDen =
            (TH1F*)mExpFile->Get(Form("hPionQinvOppMult_%d_%d_Den",
                                      iCharge,
                                      iMult));
        hExpPionQinvOppNum.push_back(hExpPionOppNum);
        hExpPionQinvOppDen.push_back(hExpPionOppDen);
      }
    }

    for(Int_t iKt=0; iKt<mKtBins; iKt++) {
      if (mIsKaon) {
        //Kaons
        TH1F *hExpKaonKtMixNum =
            (TH1F*)mExpFile->Get(Form("hKaonQinvMixKt_MomAndEnCons_%d_Num_bin_%d",
                                      iCharge,
                                      iKt));
        TH1F *hExpKaonKtMixDen =
            (TH1F*)mExpFile->Get(Form("hKaonQinvMixKt_MomAndEnCons_%d_Den_bin_%d",
                                      iCharge,
                                      iKt));
        hExpKaonQinvKtMixNum.push_back(hExpKaonKtMixNum);
        hExpKaonQinvKtMixDen.push_back(hExpKaonKtMixDen);

        TH1F *hExpKaonKtRotNum =
            (TH1F*)mExpFile->Get(Form("hKaonQinvRotKt_%d_Num_bin_%d",
                                      iCharge,
                                      iKt));
        TH1F *hExpKaonKtRotDen =
            (TH1F*)mExpFile->Get(Form("hKaonQinvRotKt_%d_Den_bin_%d",
                                      iCharge,
                                      iKt));
        hExpKaonQinvKtRotNum.push_back(hExpKaonKtRotNum);
        hExpKaonQinvKtRotDen.push_back(hExpKaonKtRotDen);

        TH1F *hExpKaonKtOppNum =
            (TH1F*)mExpFile->Get(Form("hKaonQinvOppKt_%d_Num_bin_%d",
                                      iCharge,
                                      iKt));
        TH1F *hExpKaonKtOppDen =
            (TH1F*)mExpFile->Get(Form("hKaonQinvOppKt_%d_Den_bin_%d",
                                      iCharge,
                                      iKt));
        hExpKaonQinvKtOppNum.push_back(hExpKaonKtOppNum);
        hExpKaonQinvKtOppDen.push_back(hExpKaonKtOppDen);
      }
      else {
        //Pions
        TH1F *hExpPionKtMixNum =
            (TH1F*)mExpFile->Get(Form("hPionQinvMixKt_%d_Num_bin_%d",
                                      iCharge,
                                      iKt));
        TH1F *hExpPionKtMixDen =
            (TH1F*)mExpFile->Get(Form("hPionQinvMixKt_%d_Den_bin_%d",
                                      iCharge,
                                      iKt));
        hExpPionQinvKtMixNum.push_back(hExpPionKtMixNum);
        hExpPionQinvKtMixDen.push_back(hExpPionKtMixDen);

        TH1F *hExpPionKtRotNum =
            (TH1F*)mExpFile->Get(Form("hPionQinvRotKt_%d_Num_bin_%d",
                                      iCharge,
                                      iKt));
        TH1F *hExpPionKtRotDen =
            (TH1F*)mExpFile->Get(Form("hPionQinvRotKt_%d_Den_bin_%d",
                                      iCharge,
                                      iKt));
        hExpPionQinvKtRotNum.push_back(hExpPionKtRotNum);
        hExpPionQinvKtRotDen.push_back(hExpPionKtRotDen);

        TH1F *hExpPionKtOppNum =
            (TH1F*)mExpFile->Get(Form("hPionQinvOppKt_%d_Num_bin_%d",
                                      iCharge,
                                      iKt));
        TH1F *hExpPionKtOppDen =
            (TH1F*)mExpFile->Get(Form("hPionQinvOppKt_%d_Den_bin_%d",
                                      iCharge,
                                      iKt));
        hExpPionQinvKtOppNum.push_back(hExpPionKtOppNum);
        hExpPionQinvKtOppDen.push_back(hExpPionKtOppDen);
      }
      if(mUseMC) {
        if (mIsKaon) {
          //Kaons
          TH1F *hMcKaonKtMixNum =
              (TH1F*)mMcFile->Get(Form("hKaonQinvMixKt_MomAndEnCons_%d_Num_bin_%d",
                                       iCharge,
                                       iKt));
          //CorrectBins(hMcKaonKtMixNum);

          TH1F *hMcKaonKtMixDen =
              (TH1F*)mMcFile->Get(Form("hKaonQinvMixKt_MomAndEnCons_%d_Den_bin_%d",
                                       iCharge,
                                       iKt));
          //CorrectBins(hMcKaonKtMixDen);
          hMcKaonQinvMixNum.push_back(hMcKaonKtMixNum);
          hMcKaonQinvMixDen.push_back(hMcKaonKtMixDen);

          TH1F *hMcKaonKtRotNum =
              (TH1F*)mMcFile->Get(Form("hKaonQinvRotKt_%d_Num_bin_%d",
                                       iCharge,
                                       iKt));
          //CorrectBins(hMcKaonKtRotNum);
          TH1F *hMcKaonKtRotDen =
              (TH1F*)mMcFile->Get(Form("hKaonQinvRotKt_%d_Den_bin_%d",
                                       iCharge,
                                       iKt));
          //CorrectBins(hMcKaonKtRotDen);
          hMcKaonQinvRotNum.push_back(hMcKaonKtRotNum);
          hMcKaonQinvRotDen.push_back(hMcKaonKtRotDen);

          TH1F *hMcKaonKtOppNum =
              (TH1F*)mMcFile->Get(Form("hKaonQinvOppKt_%d_Num_bin_%d",
                                       iCharge,
                                       iKt));
          //CorrectBins(hMcKaonKtOppNum);
          TH1F *hMcKaonKtOppDen =
              (TH1F*)mMcFile->Get(Form("hKaonQinvOppKt_%d_Den_bin_%d",
                                       iCharge,
                                       iKt));
          //CorrectBins(hMcKaonKtOppDen);
          hMcKaonQinvOppNum.push_back(hMcKaonKtOppNum);
          hMcKaonQinvOppDen.push_back(hMcKaonKtOppDen);
        }
        else {
          //Pions
          TH1F *hMcPionKtMixNum =
              (TH1F*)mMcFile->Get(Form("hPionQinvMixKt_%d_Num_bin_%d",
                                       iCharge,
                                       iKt));
          //CorrectBins(hMcPionKtMixNum);
          TH1F *hMcPionKtMixDen =
              (TH1F*)mMcFile->Get(Form("hPionQinvMixKt_%d_Den_bin_%d",
                                       iCharge,
                                       iKt));
          //CorrectBins(hMcPionKtMixDen);
          hMcPionQinvMixNum.push_back(hMcPionKtMixNum);
          hMcPionQinvMixDen.push_back(hMcPionKtMixDen);

          TH1F *hMcPionKtRotNum =
              (TH1F*)mMcFile->Get(Form("hPionQinvRotKt_%d_Num_bin_%d",
                                       iCharge,
                                       iKt));
          //CorrectBins(hMcPionKtRotNum);
          TH1F *hMcPionKtRotDen =
              (TH1F*)mMcFile->Get(Form("hPionQinvRotKt_%d_Den_bin_%d",
                                       iCharge,
                                       iKt));
          //CorrectBins(hMcPionKtRotDen);
          hMcPionQinvRotNum.push_back(hMcPionKtRotNum);
          hMcPionQinvRotDen.push_back(hMcPionKtRotDen);

          TH1F *hMcPionKtOppNum =
              (TH1F*)mMcFile->Get(Form("hPionQinvOppKt_%d_Num_bin_%d",
                                       iCharge,
                                       iKt));
          //CorrectBins(hMcPionKtOppNum);
          TH1F *hMcPionKtOppDen =
              (TH1F*)mMcFile->Get(Form("hPionQinvOppKt_%d_Den_bin_%d",
                                       iCharge,
                                       iKt));
          //CorrectBins(hMcPionKtOppDen);
          hMcPionQinvOppNum.push_back(hMcPionKtOppNum);
          hMcPionQinvOppDen.push_back(hMcPionKtOppDen);
        }
      }
    } //for(Int_t iKt=0; iKt<20; iKt++)
  } //for(Int_t iCharge=0; iCharge<2; iCharge++)

  std::cout << "\t [DONE]" << std::endl;
}

//_________________
void DataProcessing::ProcessHistos() {

  if (mProcInt) {
    std::cout << "Processing integrated histograms...";
    ProcessIntegratedHistos();
    std::cout << "\t [DONE]" << std::endl;
  }
  if (mProcMult) {
    std::cout << "Processing multiplicity histograms...";
    ProcessMultHistos();
    std::cout << "\t [DONE]" << std::endl;
  }
  if (mProcKt) {
    std::cout << "Processing kT histograms...";
    ProcessKtHistos();
    std::cout << "\t [DONE]" << std::endl;
  }
}

//_________________
TH1F* DataProcessing::BuildIntegrCF(Int_t charge, Int_t refSample, Bool_t isExpData, Bool_t isKaon) {

  if(charge<0 || charge>2) {
    std::cout << "DataProcessing::BuildIntegrCF [WARNING] - Wrong charge: " << charge
        << std::endl;
    return 0;
  }

  if(refSample<0 || refSample>2) {
    std::cout << "DataProcessing::BuildIntegrCF [WARNING] - Wrong reference sample: " << refSample
        << std::endl;
    return 0;
  }

  TH1F *hNumSum = new TH1F("hNumSum","",mQinvBins, mQinvLow, mQinvHi);
  TH1F *hDenSum = new TH1F("hDenSum","",mQinvBins, mQinvLow, mQinvHi);
  TH1F *hRatio;
  TString sName = "h";
  TString sParticle;
  TString sExp;
  TString sRefSample;

  //Define particle type
  if(isKaon)
    sParticle = "Kaon";
  else 
    sParticle = "Pion";

  //Define experiment or MC
  if(isExpData)
    sExp = "Exp";
  else 
    sExp = "Mc";

  //Define reference sample
  if(refSample == 0) 
    sRefSample = "Mix";
  else if(refSample == 1)
    sRefSample = "Rot";
  else if(refSample == 2)
    sRefSample = "Opp";

  sName += sExp;
  sName += sParticle;
  sName += sRefSample;
  sName += "IntegrCF_";
  sName += charge;

  hRatio = new TH1F(sName.Data(),"",mQinvBins,mQinvLow,mQinvHi);

  //Positive and negative particles
  if(isExpData) {
    if(charge<2) {
      for(Int_t iKt=0; iKt<mKtBins; iKt++) {
        if(isKaon) {
          if(refSample == 0) {
            hNumSum->Add(hExpKaonQinvKtMixNum[charge*mMultBins*mKtBins+iKt]);
            hDenSum->Add(hExpKaonQinvKtMixDen[charge*mMultBins*mKtBins+iKt]);
          }
          else if(refSample == 1) {
            hNumSum->Add(hExpKaonQinvKtRotNum[charge*mMultBins*mKtBins+iKt]);
            hDenSum->Add(hExpKaonQinvKtRotDen[charge*mMultBins*mKtBins+iKt]);
          }
          else if(refSample == 2) {
            hNumSum->Add(hExpKaonQinvKtOppNum[charge*mMultBins*mKtBins+iKt]);
            hDenSum->Add(hExpKaonQinvKtOppDen[charge*mMultBins*mKtBins+iKt]);
          }
        } //if(isKaon)
        else {
          if(refSample == 0) {
            hNumSum->Add(hExpPionQinvKtMixNum[charge*mMultBins*mKtBins+iKt]);
            hDenSum->Add(hExpPionQinvKtMixDen[charge*mMultBins*mKtBins+iKt]);
          }
          else if(refSample == 1) {
            hNumSum->Add(hExpPionQinvKtRotNum[charge*mMultBins*mKtBins+iKt]);
            hDenSum->Add(hExpPionQinvKtRotDen[charge*mMultBins*mKtBins+iKt]);
          }
          else if(refSample == 2) {
            hNumSum->Add(hExpPionQinvKtOppNum[charge*mMultBins*mKtBins+iKt]);
            hDenSum->Add(hExpPionQinvKtOppDen[charge*mMultBins*mKtBins+iKt]);
          }
        } //if(!isKaon)
      } //for(Int_t iKt=0; iKt<mKtBins; iKt++)
    }
    else {
      for(Int_t iCharge=0; iCharge<2; iCharge++) {
        for(Int_t iKt=0; iKt<mKtBins; iKt++) {
          if(isKaon) {
            if(refSample == 0) {
              hNumSum->Add(hExpKaonQinvKtMixNum[iCharge*mMultBins*mKtBins+iKt]);
              hDenSum->Add(hExpKaonQinvKtMixDen[iCharge*mMultBins*mKtBins+iKt]);
            }
            else if(refSample == 1) {
              hNumSum->Add(hExpKaonQinvKtRotNum[iCharge*mMultBins*mKtBins+iKt]);
              hDenSum->Add(hExpKaonQinvKtRotDen[iCharge*mMultBins*mKtBins+iKt]);
            }
            else if(refSample == 2) {
              hNumSum->Add(hExpKaonQinvKtOppNum[iCharge*mMultBins*mKtBins+iKt]);
              hDenSum->Add(hExpKaonQinvKtOppDen[iCharge*mMultBins*mKtBins+iKt]);
            }
          } //if(isKaon)
          else {
            if(refSample == 0) {
              hNumSum->Add(hExpPionQinvKtMixNum[iCharge*mMultBins*mKtBins+iKt]);
              hDenSum->Add(hExpPionQinvKtMixDen[iCharge*mMultBins*mKtBins+iKt]);
            }
            else if(refSample == 1) {
              hNumSum->Add(hExpPionQinvKtRotNum[iCharge*mMultBins*mKtBins+iKt]);
              hDenSum->Add(hExpPionQinvKtRotDen[iCharge*mMultBins*mKtBins+iKt]);
            }
            else if(refSample == 2) {
              hNumSum->Add(hExpPionQinvKtOppNum[iCharge*mMultBins*mKtBins+iKt]);
              hDenSum->Add(hExpPionQinvKtOppDen[iCharge*mMultBins*mKtBins+iKt]);
            }
          } //if(!isKaon)
        } //for(Int_t iKt=0; iKt<mKtBins; iKt++)
      } //for(Int_t iCharge=0; iCharge<2; iCharge++)
    }
  } //if(isExpData)
  else { //MC data
    if(charge<2) {
      for(Int_t iKt=0; iKt<mKtBins; iKt++) {
        if(isKaon) {
          if(refSample == 0) {
            hNumSum->Add(hMcKaonQinvMixNum[charge*mMultBins*mKtBins+iKt]);
            hDenSum->Add(hMcKaonQinvMixDen[charge*mMultBins*mKtBins+iKt]);
          }
          else if(refSample == 1) {
            hNumSum->Add(hMcKaonQinvRotNum[charge*mMultBins*mKtBins+iKt]);
            hDenSum->Add(hMcKaonQinvRotDen[charge*mMultBins*mKtBins+iKt]);
          }
          else if(refSample == 2) {
            hNumSum->Add(hMcKaonQinvOppNum[charge*mMultBins*mKtBins+iKt]);
            hDenSum->Add(hMcKaonQinvOppDen[charge*mMultBins*mKtBins+iKt]);
          }
        } //if(isKaon)
        else {
          if(refSample == 0) {
            hNumSum->Add(hMcPionQinvMixNum[charge*mMultBins*mKtBins+iKt]);
            hDenSum->Add(hMcPionQinvMixDen[charge*mMultBins*mKtBins+iKt]);
          }
          else if(refSample == 1) {
            hNumSum->Add(hMcPionQinvRotNum[charge*mMultBins*mKtBins+iKt]);
            hDenSum->Add(hMcPionQinvRotDen[charge*mMultBins*mKtBins+iKt]);
          }
          else if(refSample == 2) {
            hNumSum->Add(hMcPionQinvOppNum[charge*mMultBins*mKtBins+iKt]);
            hDenSum->Add(hMcPionQinvOppDen[charge*mMultBins*mKtBins+iKt]);
          }
        } //if(!isKaon)
      } //for(Int_t iKt=0; iKt<mKtBins; iKt++)
    }
    else {
      for(Int_t iCharge=0; iCharge<2; iCharge++) {
        for(Int_t iKt=0; iKt<mKtBins; iKt++) {
          if(isKaon) {
            if(refSample == 0) {
              hNumSum->Add(hMcKaonQinvMixNum[iCharge*mMultBins*mKtBins+iKt]);
              hDenSum->Add(hMcKaonQinvMixDen[iCharge*mMultBins*mKtBins+iKt]);
            }
            else if(refSample == 1) {
              hNumSum->Add(hMcKaonQinvRotNum[iCharge*mMultBins*mKtBins+iKt]);
              hDenSum->Add(hMcKaonQinvRotDen[iCharge*mMultBins*mKtBins+iKt]);
            }
            else if(refSample == 2) {
              hNumSum->Add(hMcKaonQinvOppNum[iCharge*mMultBins*mKtBins+iKt]);
              hDenSum->Add(hMcKaonQinvOppDen[iCharge*mMultBins*mKtBins+iKt]);
            }
          } //if(isKaon)
          else {
            if(refSample == 0) {
              hNumSum->Add(hMcPionQinvMixNum[iCharge*mMultBins*mKtBins+iKt]);
              hDenSum->Add(hMcPionQinvMixDen[iCharge*mMultBins*mKtBins+iKt]);
            }
            else if(refSample == 1) {
              hNumSum->Add(hMcPionQinvRotNum[iCharge*mMultBins*mKtBins+iKt]);
              hDenSum->Add(hMcPionQinvRotDen[iCharge*mMultBins*mKtBins+iKt]);
            }
            else if(refSample == 2) {
              hNumSum->Add(hMcPionQinvOppNum[iCharge*mMultBins*mKtBins+iKt]);
              hDenSum->Add(hMcPionQinvOppDen[iCharge*mMultBins*mKtBins+iKt]);
            }
          } //if(!isKaon)
        } //for(Int_t iKt=0; iKt<mKtBins; iKt++)
      } //for(Int_t iCharge=0; iCharge<2; iCharge++)
    }
  } //MC data

  Make1DCorrFctn(hRatio,hNumSum,hDenSum, 0.6, 1.2);
  delete hNumSum;
  delete hDenSum;

  return hRatio;
}

//_________________
TH1F* DataProcessing::BuildMultCF(Int_t charge, Int_t BinLo, Int_t BinHi, Int_t refSample, 
                                  Bool_t isExpData, Bool_t isKaon) {
  if(charge<0 || charge>2) {
    std::cout << "DataProcessing::BuildMultCF [WARNING] - Wrong charge: " << charge
        << std::endl;
    return 0;
  }

  if(refSample<0 || refSample>2) {
    std::cout << "DataProcessing::BuildMultCF [WARNING] - Wrong reference sample: " << refSample
        << std::endl;
    return 0;
  }

  if(BinLo<0 || BinHi>=mMultBins) {
    std::cout << "DataProcessing::BuildMultCF [WARNING] - Wrong multiplicity bins: " << BinLo << "_" << BinHi
        << std::endl;
    return 0;
  }

  TH1F *hNumSum = new TH1F("hNumSum","",mQinvBins, mQinvLow, mQinvHi);
  TH1F *hDenSum = new TH1F("hDenSum","",mQinvBins, mQinvLow, mQinvHi);
  TH1F *hRatio;
  TString sName = "h";
  TString sParticle;
  TString sExp;
  TString sRefSample;
  TString sBinLo, sBinHi;

  //Define particle type
  if(isKaon)
    sParticle = "Kaon";
  else 
    sParticle = "Pion";

  //Define experiment or MC
  if(isExpData)
    sExp = "Exp";
  else 
    sExp = "Mc";

  //Define reference sample
  if(refSample == 0) 
    sRefSample = "Mix";
  else if(refSample == 1)
    sRefSample = "Rot";
  else if(refSample == 2)
    sRefSample = "Opp";

  sName += sExp;
  sName += sParticle;
  sName += sRefSample;
  sName += "MultCF_";
  sName += charge;
  sName += "_";
  sName += BinLo;
  sName += "_";
  sName += BinHi;

  hRatio = new TH1F(sName.Data(),"",mQinvBins,mQinvLow,mQinvHi);

  if(isExpData) {
    if(charge<2) {
      for(Int_t iMult=BinLo; iMult<=BinHi; iMult++) {
        if(isKaon) {
          if(refSample == 0) {
            hNumSum->Add(hExpKaonQinvMixNum[charge*mMultBins + iMult]);
            hDenSum->Add(hExpKaonQinvMixDen[charge*mMultBins + iMult]);
          }
          else if(refSample == 1) {
            hNumSum->Add(hExpKaonQinvRotNum[charge*mMultBins + iMult]);
            hDenSum->Add(hExpKaonQinvRotDen[charge*mMultBins + iMult]);
          }
          else if(refSample == 2) {
            hNumSum->Add(hExpKaonQinvOppNum[charge*mMultBins + iMult]);
            hDenSum->Add(hExpKaonQinvOppDen[charge*mMultBins + iMult]);
          }
        } //if(isKaon)
        else {
          if(refSample == 0) {
            hNumSum->Add(hExpPionQinvMixNum[charge*mMultBins + iMult]);
            hDenSum->Add(hExpPionQinvMixDen[charge*mMultBins + iMult]);
          }
          else if(refSample == 1) {
            hNumSum->Add(hExpPionQinvRotNum[charge*mMultBins + iMult]);
            hDenSum->Add(hExpPionQinvRotDen[charge*mMultBins + iMult]);
          }
          else if(refSample == 2) {
            hNumSum->Add(hExpPionQinvOppNum[charge*mMultBins + iMult]);
            hDenSum->Add(hExpPionQinvOppDen[charge*mMultBins + iMult]);
          }
        }
      }
    }
    else {
      for(Int_t iCharge=0; iCharge<2; iCharge++) {
        for(Int_t iMult=BinLo; iMult<=BinHi; iMult++) {
          if(isKaon) {
            if(refSample == 0) {
              hNumSum->Add(hExpKaonQinvMixNum[iCharge*mMultBins + iMult]);
              hDenSum->Add(hExpKaonQinvMixDen[iCharge*mMultBins + iMult]);
            }
            else if(refSample == 1) {
              hNumSum->Add(hExpKaonQinvRotNum[iCharge*mMultBins + iMult]);
              hDenSum->Add(hExpKaonQinvRotDen[iCharge*mMultBins + iMult]);
            }
            else if(refSample == 2) {
              hNumSum->Add(hExpKaonQinvOppNum[iCharge*mMultBins + iMult]);
              hDenSum->Add(hExpKaonQinvOppDen[iCharge*mMultBins + iMult]);
            }
          } //if(isKaon)
          else {
            if(refSample == 0) {
              hNumSum->Add(hExpPionQinvMixNum[iCharge*mMultBins + iMult]);
              hDenSum->Add(hExpPionQinvMixDen[iCharge*mMultBins + iMult]);
            }
            else if(refSample == 1) {
              hNumSum->Add(hExpPionQinvRotNum[iCharge*mMultBins + iMult]);
              hDenSum->Add(hExpPionQinvRotDen[iCharge*mMultBins + iMult]);
            }
            else if(refSample == 2) {
              hNumSum->Add(hExpPionQinvOppNum[iCharge*mMultBins + iMult]);
              hDenSum->Add(hExpPionQinvOppDen[iCharge*mMultBins + iMult]);
            }
          }
        }
      }
    }
  }
  else { //MC data
    if(charge<2) {
      for(Int_t iMult=BinLo; iMult<=BinHi; iMult++) {
        if(isKaon) {
          if(refSample == 0) {
            hNumSum->Add(hMcKaonQinvMixNum[charge*mMultBins + iMult]);
            hDenSum->Add(hMcKaonQinvMixDen[charge*mMultBins + iMult]);
          }
          else if(refSample == 1) {
            hNumSum->Add(hMcKaonQinvRotNum[charge*mMultBins + iMult]);
            hDenSum->Add(hMcKaonQinvRotDen[charge*mMultBins + iMult]);
          }
          else if(refSample == 2) {
            hNumSum->Add(hMcKaonQinvOppNum[charge*mMultBins + iMult]);
            hDenSum->Add(hMcKaonQinvOppDen[charge*mMultBins + iMult]);
          }
        } //if(isKaon)
        else {
          if(refSample == 0) {
            hNumSum->Add(hMcPionQinvMixNum[charge*mMultBins + iMult]);
            hDenSum->Add(hMcPionQinvMixDen[charge*mMultBins + iMult]);
          }
          else if(refSample == 1) {
            hNumSum->Add(hMcPionQinvRotNum[charge*mMultBins + iMult]);
            hDenSum->Add(hMcPionQinvRotDen[charge*mMultBins + iMult]);
          }
          else if(refSample == 2) {
            hNumSum->Add(hMcPionQinvOppNum[charge*mMultBins + iMult]);
            hDenSum->Add(hMcPionQinvOppDen[charge*mMultBins + iMult]);
          }
        }
      }
    }
    else {
      for(Int_t iCharge=0; iCharge<2; iCharge++) {
        for(Int_t iMult=BinLo; iMult<=BinHi; iMult++) {
          if(isKaon) {
            if(refSample == 0) {
              hNumSum->Add(hMcKaonQinvMixNum[iCharge*mMultBins + iMult]);
              hDenSum->Add(hMcKaonQinvMixDen[iCharge*mMultBins + iMult]);
            }
            else if(refSample == 1) {
              hNumSum->Add(hMcKaonQinvRotNum[iCharge*mMultBins + iMult]);
              hDenSum->Add(hMcKaonQinvRotDen[iCharge*mMultBins + iMult]);
            }
            else if(refSample == 2) {
              hNumSum->Add(hMcKaonQinvOppNum[iCharge*mMultBins + iMult]);
              hDenSum->Add(hMcKaonQinvOppDen[iCharge*mMultBins + iMult]);
            }
          } //if(isKaon)
          else {
            if(refSample == 0) {
              hNumSum->Add(hMcPionQinvMixNum[iCharge*mMultBins + iMult]);
              hDenSum->Add(hMcPionQinvMixDen[iCharge*mMultBins + iMult]);
            }
            else if(refSample == 1) {
              hNumSum->Add(hMcPionQinvRotNum[iCharge*mMultBins + iMult]);
              hDenSum->Add(hMcPionQinvRotDen[iCharge*mMultBins + iMult]);
            }
            else if(refSample == 2) {
              hNumSum->Add(hMcPionQinvOppNum[iCharge*mMultBins + iMult]);
              hDenSum->Add(hMcPionQinvOppDen[iCharge*mMultBins + iMult]);
            }
          }
        }
      }
    }
  }

  Make1DCorrFctn(hRatio,hNumSum,hDenSum, 0.6, 1.2);
  delete hNumSum;
  delete hDenSum;

  return hRatio;
}

//_________________
TH1F* DataProcessing::BuildMultCorrectedCF(Int_t charge, Int_t multBin, Int_t refSample, Bool_t isKaon) {

  if(charge<0 || charge>2) {
    std::cout << "DataProcessing::BuildMultCorrectedCF [WARNING] - Wrong charge: " << charge
        << std::endl;
    return 0;
  }

  if(refSample<0 || refSample>2) {
    std::cout << "DataProcessing::BuildMultCorrectedCF [WARNING] - Wrong reference sample: " << refSample
        << std::endl;
    return 0;
  }

  TH1F *hNumSum = new TH1F("hNumSum","",mQinvBins, mQinvLow, mQinvHi);
  TH1F *hDenSum = new TH1F("hDenSum","",mQinvBins, mQinvLow, mQinvHi);
  TH1F *hRatio;
  TString sName = "h";
  TString sParticle;
  TString sRefSample;

  //Define particle type
  if(isKaon)
    sParticle = "Kaon";
  else 
    sParticle = "Pion";

  //Define reference sample
  if(refSample == 0) 
    sRefSample = "Mix";
  else if(refSample == 1)
    sRefSample = "Rot";
  else if(refSample == 2)
    sRefSample = "Opp";

  sName += sParticle;
  sName += sRefSample;
  sName += "MultCF_";
  sName += charge;
  sName += "_";
  sName += multBin;

  hRatio = new TH1F(sName.Data(),"",mQinvBins,mQinvLow,mQinvHi);

  if(isKaon) {
    if(refSample==0) {
      hNumSum->Add(hExpKaonMixMultCF.at(charge*mMultVals+multBin));
      hDenSum->Add(hMcKaonMixMultCF.at(charge*mMultVals+multBin));
    }
    else if(refSample==1) {
      hNumSum->Add(hExpKaonRotMultCF.at(charge*mMultVals+multBin));
      hDenSum->Add(hMcKaonRotMultCF.at(charge*mMultVals+multBin));
    }
    if(refSample==2) {
      hNumSum->Add(hExpKaonOppMultCF.at(charge*mMultVals+multBin));
      hDenSum->Add(hMcKaonOppMultCF.at(charge*mMultVals+multBin));
    }
  } //if(isKaon)
  else  { //isPion
    if(refSample==0) {
      hNumSum->Add(hExpPionMixMultCF.at(charge*mMultVals+multBin));
      hDenSum->Add(hMcPionMixMultCF.at(charge*mMultVals+multBin));
    }
    else if(refSample==1) {
      hNumSum->Add(hExpPionRotMultCF.at(charge*mMultVals+multBin));
      hDenSum->Add(hMcPionRotMultCF.at(charge*mMultVals+multBin));
    }
    if(refSample==2) {
      hNumSum->Add(hExpPionOppMultCF.at(charge*mMultVals+multBin));
      hDenSum->Add(hMcPionOppMultCF.at(charge*mMultVals+multBin));
    }
  } //isPion

  Correct1DCorrFctn(hRatio,hNumSum,hDenSum);
  delete hNumSum;
  delete hDenSum;

  return hRatio;
}

//_________________
TH1F* DataProcessing::BuildKtCF(Int_t charge, Int_t BinLo, Int_t BinHi,
                                Int_t refSample, Bool_t isExpData, Bool_t isKaon) {


  if(charge<0 || charge>2) {
    std::cout << "DataProcessing::BuildKtCF [WARNING] - Wrong charge: " << charge
        << std::endl;
    return 0;
  }

  if(refSample<0 || refSample>2) {
    std::cout << "DataProcessing::BuildKtCF [WARNING] - Wrong reference sample: " << refSample
        << std::endl;
    return 0;
  }

  if(BinLo<0 || BinHi>=mKtBins) {
    std::cout << "DataProcessing::BuildKtCF [WARNING] - Wrong bin interval: " << BinLo << "-" << BinHi
        << std::endl;
    return 0;
  }

  TH1F *hNumSum = new TH1F("hNumSum","",mQinvBins, mQinvLow, mQinvHi);
  TH1F *hDenSum = new TH1F("hDenSum","",mQinvBins, mQinvLow, mQinvHi);
  TH1F *hRatio;
  TString sName = "h";
  TString sParticle;
  TString sExp;
  TString sRefSample;
  TString sBinLo, sBinHi;

  //Define particle type
  if(isKaon)
    sParticle = "Kaon";
  else 
    sParticle = "Pion";

  //Define experiment or MC
  if(isExpData)
    sExp = "Exp";
  else 
    sExp = "Mc";

  //Define reference sample
  if(refSample == 0) 
    sRefSample = "Mix";
  else if(refSample == 1)
    sRefSample = "Rot";
  else if(refSample == 2)
    sRefSample = "Opp";

  sName += sExp;
  sName += sParticle;
  sName += sRefSample;
  sName += "KtCF_";
  sName += charge;
  sName += "_";
  sName += BinLo;
  sName += "_";
  sName += BinHi;

  hRatio = new TH1F(sName.Data(),"",mQinvBins,mQinvLow,mQinvHi);

  if(isExpData) {
    if(charge<2) {
      for(Int_t iKt=BinLo; iKt<=BinHi; iKt++) {

        if(isKaon) {
          if(refSample == 0) {
            hNumSum->Add(hExpKaonQinvKtMixNum[charge*mKtBins+iKt]);
            hDenSum->Add(hExpKaonQinvKtMixDen[charge*mKtBins+iKt]);
          }
          else if(refSample == 1) {
            hNumSum->Add(hExpKaonQinvKtRotNum[charge*mKtBins+iKt]);
            hDenSum->Add(hExpKaonQinvKtRotDen[charge*mKtBins+iKt]);
          }
          else if(refSample == 2) {
            hNumSum->Add(hExpKaonQinvKtOppNum[charge*mKtBins+iKt]);
            hDenSum->Add(hExpKaonQinvKtOppDen[charge*mKtBins+iKt]);
          }
        } //if(isKaon)
        else {
          if(refSample == 0) {
            hNumSum->Add(hExpPionQinvKtMixNum[charge*mKtBins+iKt]);
            hDenSum->Add(hExpPionQinvKtMixDen[charge*mKtBins+iKt]);
          }
          else if(refSample == 1) {
            hNumSum->Add(hExpPionQinvKtRotNum[charge*mKtBins+iKt]);
            hDenSum->Add(hExpPionQinvKtRotDen[charge*mKtBins+iKt]);
          }
          else if(refSample == 2) {
            hNumSum->Add(hExpPionQinvKtOppNum[charge*mKtBins+iKt]);
            hDenSum->Add(hExpPionQinvKtOppDen[charge*mKtBins+iKt]);
          }
        }
      } //for(Int_t iKt=BinLo; iKt<BinHi; iKt++)
    } //if(charge<2)
    else {
      for(Int_t iCharge=0; iCharge<2; iCharge++) {
        for(Int_t iKt=BinLo; iKt<=BinHi; iKt++) {

          if(isKaon) {
            if(refSample == 0) {
              hNumSum->Add(hExpKaonQinvKtMixNum[iCharge*mKtBins+iKt]);
              hDenSum->Add(hExpKaonQinvKtMixDen[iCharge*mKtBins+iKt]);
            }
            else if(refSample == 1) {
              hNumSum->Add(hExpKaonQinvKtRotNum[iCharge*mKtBins+iKt]);
              hDenSum->Add(hExpKaonQinvKtRotDen[iCharge*mKtBins+iKt]);
            }
            else if(refSample == 2) {
              hNumSum->Add(hExpKaonQinvKtOppNum[iCharge*mKtBins+iKt]);
              hDenSum->Add(hExpKaonQinvKtOppDen[iCharge*mKtBins+iKt]);
            }
          } //if(isKaon)
          else {
            if(refSample == 0) {
              hNumSum->Add(hExpPionQinvKtMixNum[iCharge*mKtBins+iKt]);
              hDenSum->Add(hExpPionQinvKtMixDen[iCharge*mKtBins+iKt]);
            }
            else if(refSample == 1) {
              hNumSum->Add(hExpPionQinvKtRotNum[iCharge*mKtBins+iKt]);
              hDenSum->Add(hExpPionQinvKtRotDen[iCharge*mKtBins+iKt]);
            }
            else if(refSample == 2) {
              hNumSum->Add(hExpPionQinvKtOppNum[iCharge*mKtBins+iKt]);
              hDenSum->Add(hExpPionQinvKtOppDen[iCharge*mKtBins+iKt]);
            }
          }
        } //for(Int_t iKt=BinLo; iKt<=BinHi; iKt++)
      } //for(Int_t iCharge=0; iCharge<2; iCharge++)
    } //if(charge==2)
  } //if(isExpData)
  else { //MC data
    if(charge<2) {
      for(Int_t iKt=BinLo; iKt<=BinHi; iKt++) {

        if(isKaon) {
          if(refSample == 0) {
            hNumSum->Add(hMcKaonQinvMixNum[charge*mMultBins*mKtBins+iKt]);
            hDenSum->Add(hMcKaonQinvMixDen[charge*mMultBins*mKtBins+iKt]);
          }
          else if(refSample == 1) {
            hNumSum->Add(hMcKaonQinvRotNum[charge*mMultBins*mKtBins+iKt]);
            hDenSum->Add(hMcKaonQinvRotDen[charge*mMultBins*mKtBins+iKt]);
          }
          else if(refSample == 2) {
            hNumSum->Add(hMcKaonQinvOppNum[charge*mMultBins*mKtBins+iKt]);
            hDenSum->Add(hMcKaonQinvOppDen[charge*mMultBins*mKtBins+iKt]);
          }
        } //if(isKaon)
        else {
          if(refSample == 0) {
            hNumSum->Add(hMcPionQinvMixNum[charge*mMultBins*mKtBins+iKt]);
            hDenSum->Add(hMcPionQinvMixDen[charge*mMultBins*mKtBins+iKt]);
          }
          else if(refSample == 1) {
            hNumSum->Add(hMcPionQinvRotNum[charge*mMultBins*mKtBins+iKt]);
            hDenSum->Add(hMcPionQinvRotDen[charge*mMultBins*mKtBins+iKt]);
          }
          else if(refSample == 2) {
            hNumSum->Add(hMcPionQinvOppNum[charge*mMultBins*mKtBins+iKt]);
            hDenSum->Add(hMcPionQinvOppDen[charge*mMultBins*mKtBins+iKt]);
          }
        }
      } //for(Int_t iKt=BinLo; iKt<=BinHi; iKt++)
    } //if(charge<2)
    else {
      for(Int_t iCharge=0; iCharge<2; iCharge++) {
        for(Int_t iKt=BinLo; iKt<=BinHi; iKt++) {

          if(isKaon) {
            if(refSample == 0) {
              hNumSum->Add(hMcKaonQinvMixNum[iCharge*mMultBins*mKtBins+iKt]);
              hDenSum->Add(hMcKaonQinvMixDen[iCharge*mMultBins*mKtBins+iKt]);
            }
            else if(refSample == 1) {
              hNumSum->Add(hMcKaonQinvRotNum[iCharge*mMultBins*mKtBins+iKt]);
              hDenSum->Add(hMcKaonQinvRotDen[iCharge*mMultBins*mKtBins+iKt]);
            }
            else if(refSample == 2) {
              hNumSum->Add(hMcKaonQinvOppNum[iCharge*mMultBins*mKtBins+iKt]);
              hDenSum->Add(hMcKaonQinvOppDen[iCharge*mMultBins*mKtBins+iKt]);
            }
          } //if(isKaon)
          else {
            if(refSample == 0) {
              hNumSum->Add(hMcPionQinvMixNum[iCharge*mMultBins*mKtBins+iKt]);
              hDenSum->Add(hMcPionQinvMixDen[iCharge*mMultBins*mKtBins+iKt]);
            }
            else if(refSample == 1) {
              hNumSum->Add(hMcPionQinvRotNum[iCharge*mMultBins*mKtBins+iKt]);
              hDenSum->Add(hMcPionQinvRotDen[iCharge*mMultBins*mKtBins+iKt]);
            }
            else if(refSample == 2) {
              hNumSum->Add(hMcPionQinvOppNum[iCharge*mMultBins*mKtBins+iKt]);
              hDenSum->Add(hMcPionQinvOppDen[iCharge*mMultBins*mKtBins+iKt]);
            }
          }
        } //for(Int_t iKt=BinLo; iKt<=BinHi; iKt++)
      } //for(Int_t iCharge=0; iCharge<2; iCharge++)
    } //if(charge==2)
  } //if(!isExpData)

  Make1DCorrFctn(hRatio,hNumSum,hDenSum, 0.6, 1.2);
  delete hNumSum;
  delete hDenSum;

  return hRatio;
}

//_________________
TH1F* DataProcessing::BuildKtCorrectedCF(Int_t charge, Int_t ktBin, 
                                         Int_t refSample, Bool_t isKaon) {
  if(charge<0 || charge>2) {
    std::cout << "DataProcessing::BuildKtCorrectedCF [WARNING] - Wrong charge: " << charge
        << std::endl;
    return 0;
  }

  if(refSample<0 || refSample>2) {
    std::cout << "DataProcessing::BuildKtCorrectedCF [WARNING] - Wrong reference sample: " << refSample
        << std::endl;
    return 0;
  }

  TH1F *hNumSum = new TH1F("hNumSum","",mQinvBins, mQinvLow, mQinvHi);
  TH1F *hDenSum = new TH1F("hDenSum","",mQinvBins, mQinvLow, mQinvHi);
  TH1F *hRatio;
  TString sName = "h";
  TString sParticle;
  TString sRefSample;

  //Define particle type
  if(isKaon)
    sParticle = "Kaon";
  else 
    sParticle = "Pion";

  //Define reference sample
  if(refSample == 0) 
    sRefSample = "Mix";
  else if(refSample == 1)
    sRefSample = "Rot";
  else if(refSample == 2)
    sRefSample = "Opp";

  sName += sParticle;
  sName += sRefSample;
  sName += "KtCF_";
  sName += charge;
  sName += "_";
  sName += ktBin;

  hRatio = new TH1F(sName.Data(),"",mQinvBins,mQinvLow,mQinvHi);

  if(isKaon) {
    if(refSample==0) {
      hNumSum->Add(hExpKaonMixKtCF.at(charge*mKtVals+ktBin));
      hDenSum->Add(hMcKaonMixKtCF.at(charge*mKtVals+ktBin));
    }
    else if(refSample==1) {
      hNumSum->Add(hExpKaonRotKtCF.at(charge*mKtVals+ktBin));
      hDenSum->Add(hMcKaonRotKtCF.at(charge*mKtVals+ktBin));
    }
    if(refSample==2) {
      hNumSum->Add(hExpKaonOppKtCF.at(charge*mKtVals+ktBin));
      hDenSum->Add(hMcKaonOppKtCF.at(charge*mKtVals+ktBin));
    }
  } //if(isKaon)
  else  { //isPion
    if(refSample==0) {
      hNumSum->Add(hExpPionMixKtCF.at(charge*mKtVals+ktBin));
      hDenSum->Add(hMcPionMixKtCF.at(charge*mKtVals+ktBin));
    }
    else if(refSample==1) {
      hNumSum->Add(hExpPionRotKtCF.at(charge*mKtVals+ktBin));
      hDenSum->Add(hMcPionRotKtCF.at(charge*mKtVals+ktBin));
    }
    if(refSample==2) {
      hNumSum->Add(hExpPionOppKtCF.at(charge*mKtVals+ktBin));
      hDenSum->Add(hMcPionOppKtCF.at(charge*mKtVals+ktBin));
    }
  } //isPion

  Correct1DCorrFctn(hRatio,hNumSum,hDenSum);
  delete hNumSum;
  delete hDenSum;

  return hRatio;
}

//_________________
TH1F* DataProcessing::BuildMultKtCF(Int_t charge, Int_t MultBinLo, Int_t MultBinHi,
                                    Int_t KtBinLo, Int_t KtBinHi,
                                    Int_t refSample, Bool_t isExpData, Bool_t isKaon) {

  return 0;
}

//_________________
void DataProcessing::SetExpHistoStyle(TH1 *h) {
  h->SetLineColor(mExpColor);
  h->SetLineWidth(mExpLineWidth);
  h->SetMarkerStyle(mExpMarkerStyle);
  h->SetMarkerSize(mExpMarkerSize);
  h->SetMarkerColor(mExpColor);
  h->GetYaxis()->SetRangeUser(mYaxisLo,mYaxisHi);
}

//_________________
void DataProcessing::SetMcHistoStyle(TH1 *h) {
  h->SetLineColor(mMcColor);
  h->SetLineWidth(mMcLineWidth);
  h->SetMarkerStyle(mMcMarkerStyle);
  h->SetMarkerSize(mMcMarkerSize);
  h->SetMarkerColor(mMcColor);
  h->GetYaxis()->SetRangeUser(mYaxisLo,mYaxisHi);
}

//_________________
void DataProcessing::SetHistoStyle(TH1 *h) {
  h->SetLineColor(mCorrFctnColor);
  h->SetLineWidth(mCorrFctnLineWidth);
  h->SetMarkerStyle(mCorrFctnMarkerStyle);
  h->SetMarkerSize(mCorrFctnMarkerSize);
  h->SetMarkerColor(mCorrFctnColor);
  h->GetYaxis()->SetRangeUser(mYaxisLo,mYaxisHi);
}

//_________________
void DataProcessing::Finish() {

  mOutFile->Write();
  mOutFile->Close();
  if (mUseMC)
    mMcFile->Close();
  mExpFile->Close();
}

//_________________
void DataProcessing::CorrectBins(TH1F *from) {

  TH1F* tmp = new TH1F("tmp","",mQinvBins,mQinvLow,mQinvHi);;

  for(Int_t iBin=0; iBin<(mQinvBins+1); iBin++) {
    tmp->SetBinContent(iBin, from->GetBinContent(iBin));
    tmp->SetBinError(iBin, from->GetBinError(iBin));
  }
  TString newName = "hMc";
  TString name = from->GetName();
  name.Remove(0,1);
  newName += name;

  tmp->SetNameTitle(newName.Data(),from->GetTitle());

  *from = *tmp;
}

//_________________
void DataProcessing::ProcessIntegratedHistos() {

  //////////////////////////////////
  //Integrated over all parameters//
  //////////////////////////////////
  for(Int_t iCharge=0; iCharge<3; iCharge++) {
    for(Int_t iRefSample=0; iRefSample<3; iRefSample++) { //Mix, Rot, Opp
      if(mIsKaon == false) { //Pions
        if(mUseMC) { //Mc
          if(iRefSample==0) { 
            hMcPionMixIntegrCF.push_back( BuildIntegrCF(iCharge,iRefSample,mUseMC,mIsKaon) );
            SetMcHistoStyle(hMcPionMixIntegrCF.back());
          }
          else if(iRefSample==1) {
            hMcPionRotIntegrCF.push_back( BuildIntegrCF(iCharge,iRefSample,mUseMC,mIsKaon) );
          }
          else if(iRefSample==2) {
            hMcPionOppIntegrCF.push_back( BuildIntegrCF(iCharge,iRefSample,mUseMC,mIsKaon) );
          }
        }
        else { //Exp
          if(iRefSample == 0) {
            hExpPionMixIntegrCF.push_back( BuildIntegrCF(iCharge,iRefSample,
                                                         mUseMC,mIsKaon) );
            SetExpHistoStyle(hExpPionMixIntegrCF.back());
          }
          else if(iRefSample==1) {
            hExpPionRotIntegrCF.push_back( BuildIntegrCF(iCharge,iRefSample,
                                                         mUseMC,mIsKaon) );
          }
          else if(iRefSample==2) {
            hExpPionOppIntegrCF.push_back( BuildIntegrCF(iCharge,iRefSample,
                                                         mUseMC,mIsKaon) );
          }
        }
      }
      else { //Kaons
        if(mUseMC) { //Mc
          if(iRefSample==0) { 
            hMcKaonMixIntegrCF.push_back( BuildIntegrCF(iCharge,iRefSample,
                                                        mUseMC,mIsKaon) );
            SetMcHistoStyle(hMcKaonMixIntegrCF.back());
          }
          else if(iRefSample==1) {
            hMcKaonRotIntegrCF.push_back( BuildIntegrCF(iCharge,iRefSample,
                                                        mUseMC,mIsKaon) );
          }
          else if(iRefSample==2) {
            hMcKaonOppIntegrCF.push_back( BuildIntegrCF(iCharge,iRefSample,
                                                        mUseMC,mIsKaon) );
          }
        }
        else { //Exp
          if(iRefSample==0) {
            hExpKaonMixIntegrCF.push_back( BuildIntegrCF(iCharge,iRefSample,
                                                         mUseMC,mIsKaon) );
            SetExpHistoStyle(hExpKaonMixIntegrCF.back());
          }
          else if(iRefSample==1) {
            hExpKaonRotIntegrCF.push_back( BuildIntegrCF(iCharge,iRefSample,
                                                         mUseMC,mIsKaon) );
          }
          else if(iRefSample==2) {
            hExpKaonOppIntegrCF.push_back( BuildIntegrCF(iCharge,iRefSample,
                                                         mUseMC,mIsKaon) );
          }
        }
      }
    } //for(Int_t iRefSample=0; iRefSample<3; iRefSample++)
  } //for(Int_t iCharge=0; iCharge<3; iCharge++)

  if (mUseMC) {
    //Exp divide on MC
    for(Int_t iCharge=0; iCharge<3; iCharge++) {
      for(Int_t iRefSample=0; iRefSample<3; iRefSample++) {
        if(mIsKaon) {
          if(iRefSample==0) {
            hKaonMixIntegrCF.push_back( BuildIntegrCorrectedCF(iCharge,iRefSample,mIsKaon) );
            SetHistoStyle(hKaonMixIntegrCF.back());
          }
          else if(iRefSample==1) {
            hKaonRotIntegrCF.push_back( BuildIntegrCorrectedCF(iCharge,iRefSample,mIsKaon) );
            SetHistoStyle(hKaonRotIntegrCF.back());
          }
          else if(iRefSample==2) {
            hKaonOppIntegrCF.push_back( BuildIntegrCorrectedCF(iCharge,iRefSample,mIsKaon) );
            SetHistoStyle(hKaonOppIntegrCF.back());
          }
        }
        else { //isPion
          if(iRefSample==0) {
            hPionMixIntegrCF.push_back( BuildIntegrCorrectedCF(iCharge,iRefSample,mIsKaon) );
            SetHistoStyle(hPionMixIntegrCF.back());
          }
          else if(iRefSample==1) {
            hPionRotIntegrCF.push_back( BuildIntegrCorrectedCF(iCharge,iRefSample,mIsKaon) );
            SetHistoStyle(hPionRotIntegrCF.back());
          }
          else if(iRefSample==2) {
            hPionOppIntegrCF.push_back( BuildIntegrCorrectedCF(iCharge,iRefSample,mIsKaon) );
            SetHistoStyle(hPionOppIntegrCF.back());
          }
        }
      } //for(Int_t iRefSample=0; iRefSample<3; iRefSample++)
    } //for(Int_t iCharge=0; iCharge<2; iCharge++)
  }
}

//_________________
TH1F* DataProcessing::BuildIntegrCorrectedCF(Int_t charge, Int_t refSample, Bool_t isKaon) {

  if(charge<0 || charge>2) {
    std::cout << "DataProcessing::BuildIntegrCF [WARNING] - Wrong charge: " << charge
        << std::endl;
    return 0;
  }

  if(refSample<0 || refSample>2) {
    std::cout << "DataProcessing::BuildIntegrCF [WARNING] - Wrong reference sample: " << refSample
        << std::endl;
    return 0;
  }

  TH1F *hNumSum = new TH1F("hNumSum","",mQinvBins, mQinvLow, mQinvHi);
  TH1F *hDenSum = new TH1F("hDenSum","",mQinvBins, mQinvLow, mQinvHi);
  TH1F *hRatio;
  TString sName = "h";
  TString sParticle;
  TString sRefSample;

  //Define particle type
  if(isKaon)
    sParticle = "Kaon";
  else 
    sParticle = "Pion";

  //Define reference sample
  if(refSample == 0) 
    sRefSample = "Mix";
  else if(refSample == 1)
    sRefSample = "Rot";
  else if(refSample == 2)
    sRefSample = "Opp";

  sName += sParticle;
  sName += sRefSample;
  sName += "IntegrCF_";
  sName += charge;

  hRatio = new TH1F(sName.Data(),"",mQinvBins,mQinvLow,mQinvHi);
  if(isKaon) {
    if(refSample==0) {
      hNumSum->Add(hExpKaonMixIntegrCF.at(charge));
      hDenSum->Add(hMcKaonMixIntegrCF.at(charge));
    }
    else if(refSample==1) {
      hNumSum->Add(hExpKaonRotIntegrCF.at(charge));
      hDenSum->Add(hMcKaonRotIntegrCF.at(charge));
    }
    if(refSample==2) {
      hNumSum->Add(hExpKaonOppIntegrCF.at(charge));
      hDenSum->Add(hMcKaonOppIntegrCF.at(charge));
    }
  } //if(isKaon)
  else  { //isPion
    if(refSample==0) {
      hNumSum->Add(hExpPionMixIntegrCF.at(charge));
      hDenSum->Add(hMcPionMixIntegrCF.at(charge));
    }
    else if(refSample==1) {
      hNumSum->Add(hExpPionRotIntegrCF.at(charge));
      hDenSum->Add(hMcPionRotIntegrCF.at(charge));
    }
    if(refSample==2) {
      hNumSum->Add(hExpPionOppIntegrCF.at(charge));
      hDenSum->Add(hMcPionOppIntegrCF.at(charge));
    }
  } //isPion

  Correct1DCorrFctn(hRatio,hNumSum,hDenSum);
  delete hNumSum;
  delete hDenSum;

  return hRatio;
}

//_________________
void DataProcessing::ProcessMultHistos() {

  /////////////////////////////////////////
  //        Multiplicity dependence      //
  /////////////////////////////////////////
  Int_t multBinLo, multBinHi;

  for(Int_t iCharge=0; iCharge<3; iCharge++) {
    for(Int_t iRefSample=0; iRefSample<3; iRefSample++) { //Mix, Rot, Opp
      for(Int_t iMultBin=0; iMultBin<mMultVals; iMultBin++) {
        multBinLo = iMultBin;
        multBinHi = iMultBin;
        /*
           switch(iMultBin) {
           case 1:  multBinLo = 1;  multBinHi = 1;  break;
           case 2:  multBinLo = 2;  multBinHi = 2;  break;
           default: multBinLo = 0;  multBinHi = 0;  break;
           };
           */
        if(mIsKaon == false) { //Pions
          if(mUseMC) { //Mc
            if(iRefSample==0) {
              hMcPionMixMultCF.push_back( BuildMultCF(iCharge,multBinLo,multBinHi,
                                                      iRefSample,false,mIsKaon) );
              SetMcHistoStyle(hMcPionMixMultCF.back());
            }
            else if(iRefSample==1) {
              hMcPionRotMultCF.push_back( BuildMultCF(iCharge,multBinLo,multBinHi,
                                                      iRefSample,false,mIsKaon) );
            }
            else if(iRefSample==2) {
              hMcPionOppMultCF.push_back( BuildMultCF(iCharge,multBinLo,multBinHi,
                                                      iRefSample,false,mIsKaon) );
            }
          }
          else { //Exp
            if(iRefSample==0) {
              hExpPionMixMultCF.push_back( BuildMultCF(iCharge,multBinLo,multBinHi,
                                                       iRefSample,true,mIsKaon) );
              SetExpHistoStyle(hExpPionMixMultCF.back());
            }
            else if(iRefSample==1) {
              hExpPionRotMultCF.push_back( BuildMultCF(iCharge,multBinLo,multBinHi,
                                                       iRefSample,true,mIsKaon) );
            }
            else if(iRefSample==2) {
              hExpPionOppMultCF.push_back( BuildMultCF(iCharge,multBinLo,multBinHi,
                                                       iRefSample,true,mIsKaon) );
            }
          }
        }
        else { //Kaons
          if(mUseMC) { //Mc
            if(iRefSample==0) {
              hMcKaonMixMultCF.push_back( BuildMultCF(iCharge,multBinLo,multBinHi,
                                                      iRefSample,false,mIsKaon) );
              SetMcHistoStyle(hMcKaonMixMultCF.back());
            }
            else if(iRefSample==1) {
              hMcKaonRotMultCF.push_back( BuildMultCF(iCharge,multBinLo,multBinHi,
                                                      iRefSample,false,mIsKaon) );
            }
            else if(iRefSample==2) {
              hMcKaonOppMultCF.push_back( BuildMultCF(iCharge,multBinLo,multBinHi,
                                                      iRefSample,false,mIsKaon) );
            }
          }
          else { //Exp
            if(iRefSample==0) {
              hExpKaonMixMultCF.push_back( BuildMultCF(iCharge,multBinLo,multBinHi,
                                                       iRefSample,true,mIsKaon) );
              SetExpHistoStyle(hExpKaonMixMultCF.back());
            }
            else if(iRefSample==1) {
              hExpKaonRotMultCF.push_back( BuildMultCF(iCharge,multBinLo,multBinHi,
                                                       iRefSample,true,mIsKaon) );
            }
            else if(iRefSample==2) {
              hExpKaonOppMultCF.push_back( BuildMultCF(iCharge,multBinLo,multBinHi,
                                                       iRefSample,true,mIsKaon) );
            }
          }
        }
      }
    }
  }


  if (mUseMC) {
    for(Int_t iCharge=0; iCharge<3; iCharge++) {
      for(Int_t iRefSample=0; iRefSample<3; iRefSample++) {
        for(Int_t iMultBin=0; iMultBin<mMultVals; iMultBin++) {
          if(mIsKaon) {
            if(iRefSample==0) {
              hKaonMixMultCF.push_back( BuildMultCorrectedCF(iCharge,iMultBin,
                                                             iRefSample,mIsKaon) );
              SetHistoStyle(hKaonMixMultCF.back());
            }
            else if(iRefSample==1) {
              hKaonRotMultCF.push_back( BuildMultCorrectedCF(iCharge,iMultBin,
                                                             iRefSample,mIsKaon) );
              SetHistoStyle(hKaonRotMultCF.back());
            }
            else if(iRefSample==2) {
              hKaonOppMultCF.push_back( BuildMultCorrectedCF(iCharge,iMultBin,
                                                             iRefSample,mIsKaon) );
              SetHistoStyle(hKaonOppMultCF.back());
            }
          }
          else { //isPion
            if(iRefSample==0) {
              hPionMixMultCF.push_back( BuildMultCorrectedCF(iCharge,iMultBin,
                                                             iRefSample,mIsKaon) );
              SetHistoStyle(hPionMixMultCF.back());
            }
            else if(iRefSample==1) {
              hPionRotMultCF.push_back( BuildMultCorrectedCF(iCharge,iMultBin,
                                                             iRefSample,mIsKaon) );
              SetHistoStyle(hPionRotMultCF.back());
            }
            else if(iRefSample==2) {
              hPionOppMultCF.push_back( BuildMultCorrectedCF(iCharge,iMultBin,
                                                             iRefSample,mIsKaon) );
              SetHistoStyle(hPionOppMultCF.back());
            }
          }
        } //for(Int_t iMultBin=0; iMultBin<mMultVals; iMultBin++)
      } //for(Int_t iRefSample=0; iRefSample<3; iRefSample++)
    } //for(Int_t iCharge=0; iCharge<3; iCharge++)
  }
}

//_________________
void DataProcessing::ProcessKtHistos() {

  /////////////////////////////////////////
  //               Kt dependence         //
  /////////////////////////////////////////
  Int_t ktBinLo, ktBinHi;

  for(Int_t iCharge=0; iCharge<3; iCharge++) {
    for(Int_t iRefSample=0; iRefSample<3; iRefSample++) { //Mix, Rot, Opp
      for(Int_t iKtBin=0; iKtBin<mKtVals; iKtBin++) {
        switch(iKtBin) {  // 0.1 - 1.1 - 10 bins
          case 0: ktBinLo = 0; ktBinHi=2; break;
          case 1: ktBinLo = 3; ktBinHi=4; break;
          case 2: ktBinLo = 5; ktBinHi=6; break;
          case 3: ktBinLo = 7; ktBinHi=9; break;
          default: ktBinLo=0; ktBinHi=9; break;
        };

        if(mIsKaon == false) { //Pions
          if(mUseMC) { //Mc
            if(iRefSample==0) { 
              hMcPionMixKtCF.push_back( BuildKtCF(iCharge,ktBinLo,ktBinHi,
                                                  iRefSample,false,mIsKaon) );
              SetMcHistoStyle(hMcPionMixKtCF.back());
            }
            else if(iRefSample==1) {
              hMcPionRotKtCF.push_back( BuildKtCF(iCharge,ktBinLo,ktBinHi,
                                                  iRefSample,false,mIsKaon) );
            }
            else if(iRefSample==2) {
              hMcPionOppKtCF.push_back( BuildKtCF(iCharge,ktBinLo,ktBinHi,
                                                  iRefSample,false,mIsKaon) );
            }
          } //if(mUseMC)

          else { //Exp
            if(iRefSample==0) {
              hExpPionMixKtCF.push_back( BuildKtCF(iCharge,ktBinLo,ktBinHi,
                                                   iRefSample,true,mIsKaon) );
              SetExpHistoStyle(hExpPionMixKtCF.back());
            }
            else if(iRefSample==1) {
              hExpPionRotKtCF.push_back( BuildKtCF(iCharge,ktBinLo,ktBinHi,
                                                   iRefSample,true,mIsKaon) );
            }
            else if(iRefSample==2) {
              hExpPionOppKtCF.push_back( BuildKtCF(iCharge,ktBinLo,ktBinHi,
                                                   iRefSample,true,mIsKaon) );
            }
          }
        }
        else { //Kaons

          if(mUseMC) { //Mc
            if(iRefSample==0) { 
              hMcKaonMixKtCF.push_back( BuildKtCF(iCharge,ktBinLo,ktBinHi,
                                                  iRefSample,false,mIsKaon) );
              SetMcHistoStyle(hMcKaonMixKtCF.back());
            }
            else if(iRefSample==1) {
              hMcKaonRotKtCF.push_back( BuildKtCF(iCharge,ktBinLo,ktBinHi,
                                                  iRefSample,false,mIsKaon) );
            }
            else if(iRefSample==2) {
              hMcKaonOppKtCF.push_back( BuildKtCF(iCharge,ktBinLo,ktBinHi,
                                                  iRefSample,false,mIsKaon) );
            }
          } //if(mUseMC)

          else { //Exp
            if(iRefSample==0) {
              hExpKaonMixKtCF.push_back( BuildKtCF(iCharge,ktBinLo,ktBinHi,
                                                   iRefSample,true,mIsKaon) );
              SetExpHistoStyle(hExpKaonMixKtCF.back());
            }
            else if(iRefSample==1) {
              hExpKaonRotKtCF.push_back( BuildKtCF(iCharge,ktBinLo,ktBinHi,
                                                   iRefSample,true,mIsKaon) );
            }
            else if(iRefSample==2) {
              hExpKaonOppKtCF.push_back( BuildKtCF(iCharge,ktBinLo,ktBinHi,
                                                   iRefSample,true,mIsKaon) );
            }
          } //if(mUseMC==1)
        } //if(mIsKaon==1)
      } //for(Int_t iKtBin=0; iKtBin<3; iKtBin++)
    } //for(Int_t iRefSample=0; iRefSample<3; iRefSample++)
  } //for(Int_t iCharge=0; iCharge<3; iCharge++)


  if (mUseMC) {
    for(Int_t iCharge=0; iCharge<3; iCharge++) {
      for(Int_t iRefSample=0; iRefSample<3; iRefSample++) {
        for(Int_t iKtBin=0; iKtBin<mKtVals; iKtBin++) {
          if(mIsKaon) {
            if(iRefSample==0) {
              hKaonMixKtCF.push_back( BuildKtCorrectedCF(iCharge,iKtBin,
                                                         iRefSample,mIsKaon) );
              SetHistoStyle(hKaonMixKtCF.back());
            }
            else if(iRefSample==1) {
              hKaonRotKtCF.push_back( BuildKtCorrectedCF(iCharge,iKtBin,
                                                         iRefSample,mIsKaon) );
              SetHistoStyle(hKaonRotKtCF.back());
            }
            else if(iRefSample==2) {
              hKaonOppKtCF.push_back( BuildKtCorrectedCF(iCharge,iKtBin,
                                                         iRefSample,mIsKaon) );
              SetHistoStyle(hKaonOppKtCF.back());
            }
          }
          else { //isPion
            if(iRefSample==0) {
              hPionMixKtCF.push_back( BuildKtCorrectedCF(iCharge,iKtBin,
                                                         iRefSample,mIsKaon) );
              SetHistoStyle(hPionMixKtCF.back());
            }
            else if(iRefSample==1) {
              hPionRotKtCF.push_back( BuildKtCorrectedCF(iCharge,iKtBin,
                                                         iRefSample,mIsKaon) );
              SetHistoStyle(hPionRotKtCF.back());
            }
            else if(iRefSample==2) {
              hPionOppKtCF.push_back( BuildKtCorrectedCF(iCharge,iKtBin,
                                                         iRefSample,mIsKaon) );
              SetHistoStyle(hPionOppKtCF.back());
            }
          }
        } //for(Int_t iKtBin=0; iKtBin<mKtVals; iKtBin++)
      } //for(Int_t iRefSample=0; iRefSample<3; iRefSample++)
    } //for(Int_t iCharge=0; iCharge<3; iCharge++)  
  }
}

//_________________
void DataProcessing::FitHistos() {

  if (!mUseMC) {
    std::cout << "Fitting uncorrected CFs...";
    FitUncorrectedCF();
    std::cout << "\t [DONE]" << std::endl;
  }
  else {
    std::cout << "Fitting corrected CFs...";
    FitCorrectedCF();
    std::cout << "\t [DONE]" << std::endl;
  }
}

//_________________
void DataProcessing::PrintFitUncorrectedParms() {
  std::cout << "----------- Multiplicity values ----------" << std::endl;
  if (mIsKaon) {
    std::cout << "Kaons:" << std::endl;
    for(Int_t i=0; i<mMultVals; i++) {
      std::cout << Form("R: %3.2f +/- %3.2f ", mKaonMultMixRadii[2*mMultVals+i], 
                        mKaonMultMixRadiiErr[2*mMultVals+i])
          << std::endl;
    }
  }
  else {
    std::cout << "Pions:" << std::endl;
    for(Int_t i=0; i<mMultVals; i++) {
      std::cout << Form("R: %3.2f +/- %3.2f ", mPionMultMixRadii[2*mMultVals+i+1], 
                        mPionMultMixRadiiErr[2*mMultVals+i])
          << std::endl;
    }
  }
}

//_________________
void DataProcessing::PrintFitCorrectedParms() {

  std::cout << "----------- Integrated values ------------" << std::endl;
  std::cout << "Kaons:" << std::endl
      << Form("R: %3.2f +/- %3.2f ", mKaonIntegrMixRadii[0], 
              mKaonIntegrMixRadiiErr[0])
      << std::endl
      << "Pions:" << std::endl
      << Form("R: %3.2f +/- %3.2f ", mPionIntegrMixRadii[0], 
              mPionIntegrMixRadiiErr[0])
      << std::endl << std::endl;


  std::cout << "----------- Multiplicity values ----------" << std::endl;
  std::cout << "Kaons:" << std::endl;
  for(Int_t i=0; i<mMultVals; i++) {
    std::cout << Form("R: %3.2f +/- %3.2f ", mKaonMultMixRadii[2*mMultVals+i], 
                      mKaonMultMixRadiiErr[2*mMultVals+i])
        << std::endl;
  }
  std::cout << "Pions:" << std::endl;
  for(Int_t i=0; i<mMultVals; i++) {
    std::cout << Form("R: %3.2f +/- %3.2f ", mPionMultMixRadii[2*mMultVals+i+1], 
                      mPionMultMixRadiiErr[2*mMultVals+i])
        << std::endl;
  }

  std::cout << "-----------      Kt values     ----------" << std::endl;
  std::cout << "Kaons:" << std::endl;
  for(Int_t i=0; i<mKtVals; i++) {
    std::cout << Form("R: %3.2f +/- %3.2f ", mKaonKtMixRadii[2*mKtVals+i], 
                      mKaonKtMixRadiiErr[2*mKtVals+i])
        << std::endl;
  }
  std::cout << "Pions:" << std::endl;
  for(Int_t i=0; i<mKtVals; i++) {
    std::cout << Form("R: %3.2f +/- %3.2f ", mPionKtMixRadii[2*mKtVals+i], 
                      mPionKtMixRadiiErr[2*mKtVals+i])
        << std::endl;
  }

}

//_________________
void DataProcessing::FitCorrectedCF() {

  std::vector<double> mFitParams;

  ////////////////////////////////////
  //       Integrated values        //
  ////////////////////////////////////

  //Kaons
  if (mIsKaon) {
    for(unsigned int i=1; i<hKaonMixIntegrCF.size(); i++) {
      if(mFitParams.empty()) {
      }
      else {
        mFitParams.clear();
      }
      mFitParams = DoFit(hKaonMixIntegrCF.at(i),4,mSourceFunc,mNonFemtoFunc,mDrawLegend);
      mKaonIntegrMixRadii.push_back(mFitParams.at(0));
      mKaonIntegrMixRadiiErr.push_back(mFitParams.at(1));
      mKaonIntegrMixLambda.push_back(mFitParams.at(2));
      mKaonIntegrMixLambdaErr.push_back(mFitParams.at(3));
    }

    for(unsigned int i=0; i<hKaonRotIntegrCF.size(); i++) {
      mFitParams.clear();
      mFitParams = DoFit(hKaonRotIntegrCF[i],4,mSourceFunc,mNonFemtoFunc,mDrawLegend);
      mKaonIntegrRotRadii.push_back(mFitParams.at(0));
      mKaonIntegrRotRadiiErr.push_back(mFitParams.at(1));
      mKaonIntegrRotLambda.push_back(mFitParams.at(2));
      mKaonIntegrRotLambdaErr.push_back(mFitParams.at(3));
    }

    for(unsigned int i=0; i<hKaonOppIntegrCF.size(); i++) {
      mFitParams.clear();
      mFitParams = DoFit(hKaonOppIntegrCF[i],4,mSourceFunc,mNonFemtoFunc,mDrawLegend);
      mKaonIntegrOppRadii.push_back(mFitParams.at(0));
      mKaonIntegrOppRadiiErr.push_back(mFitParams.at(1));
      mKaonIntegrOppLambda.push_back(mFitParams.at(2));
      mKaonIntegrOppLambdaErr.push_back(mFitParams.at(3));
    }
  } 
  else {
    //Pions
    for(unsigned int i=1; i<hPionMixIntegrCF.size(); i++) {
      if(mFitParams.empty()) {
      }
      else {
        mFitParams.clear();
      }
      mFitParams = DoFit(hPionMixIntegrCF.at(i),3,mSourceFunc,mNonFemtoFunc,mDrawLegend);
      mPionIntegrMixRadii.push_back(mFitParams.at(0));
      mPionIntegrMixRadiiErr.push_back(mFitParams.at(1));
      mPionIntegrMixLambda.push_back(mFitParams.at(2));
      mPionIntegrMixLambdaErr.push_back(mFitParams.at(3));
    }

    for(unsigned int i=0; i<hPionRotIntegrCF.size(); i++) {
      mFitParams.clear();
      mFitParams = DoFit(hPionRotIntegrCF[i],3,mSourceFunc,mNonFemtoFunc,mDrawLegend);
      mPionIntegrRotRadii.push_back(mFitParams.at(0));
      mPionIntegrRotRadiiErr.push_back(mFitParams.at(1));
      mPionIntegrRotLambda.push_back(mFitParams.at(2));
      mPionIntegrRotLambdaErr.push_back(mFitParams.at(3));
    }

    for(unsigned int i=0; i<hPionOppIntegrCF.size(); i++) {
      mFitParams.clear();
      mFitParams = DoFit(hPionOppIntegrCF[i],3,mSourceFunc,mNonFemtoFunc,mDrawLegend);
      mPionIntegrOppRadii.push_back(mFitParams.at(0));
      mPionIntegrOppRadiiErr.push_back(mFitParams.at(1));
      mPionIntegrOppLambda.push_back(mFitParams.at(2));
      mPionIntegrOppLambdaErr.push_back(mFitParams.at(3));
    }
  }

  ////////////////////////////////////
  //       Multiplicity values      //
  ////////////////////////////////////

  if (mIsKaon) { // kaons
    for(unsigned int i=0; i<hKaonMixMultCF.size(); i++) {
      mFitParams.clear();
      mFitParams = DoFit(hKaonMixMultCF[i],4,mSourceFunc,mNonFemtoFunc,mDrawLegend);
      mKaonMultMixRadii.push_back(mFitParams.at(0));
      mKaonMultMixRadiiErr.push_back(mFitParams.at(1));
      mKaonMultMixLambda.push_back(mFitParams.at(2));
      mKaonMultMixLambdaErr.push_back(mFitParams.at(3));
    }

    for(unsigned int i=0; i<hKaonRotMultCF.size(); i++) {
      mFitParams.clear();
      mFitParams = DoFit(hKaonRotMultCF[i],4,mSourceFunc,mNonFemtoFunc,mDrawLegend);
      mKaonMultRotRadii.push_back(mFitParams.at(0));
      mKaonMultRotRadiiErr.push_back(mFitParams.at(1));
      mKaonMultRotLambda.push_back(mFitParams.at(2));
      mKaonMultRotLambdaErr.push_back(mFitParams.at(3));
    }

    for(unsigned int i=0; i<hKaonOppMultCF.size(); i++) {
      mFitParams.clear();
      mFitParams = DoFit(hKaonOppMultCF[i],4,mSourceFunc,mNonFemtoFunc,mDrawLegend);
      mKaonMultOppRadii.push_back(mFitParams.at(0));
      mKaonMultOppRadiiErr.push_back(mFitParams.at(1));
      mKaonMultOppLambda.push_back(mFitParams.at(2));
      mKaonMultOppLambdaErr.push_back(mFitParams.at(3));
    }
  } 
  else {  // pions
    for(unsigned int i=0; i<hPionMixMultCF.size(); i++) {
      mFitParams.clear();
      mFitParams = DoFit(hPionMixMultCF[i],3,mSourceFunc,mNonFemtoFunc,mDrawLegend);
      mPionMultMixRadii.push_back(mFitParams.at(0));
      mPionMultMixRadiiErr.push_back(mFitParams.at(1));
      mPionMultMixLambda.push_back(mFitParams.at(2));
      mPionMultMixLambdaErr.push_back(mFitParams.at(3));
    }

    for(unsigned int i=0; i<hPionRotMultCF.size(); i++) {
      mFitParams.clear();
      mFitParams = DoFit(hPionRotMultCF[i],3,mSourceFunc,mNonFemtoFunc,mDrawLegend);
      mPionMultRotRadii.push_back(mFitParams.at(0));
      mPionMultRotRadiiErr.push_back(mFitParams.at(1));
      mPionMultRotLambda.push_back(mFitParams.at(2));
      mPionMultRotLambdaErr.push_back(mFitParams.at(3));
    }

    for(unsigned int i=0; i<hPionOppMultCF.size(); i++) {
      mFitParams.clear();
      mFitParams = DoFit(hPionOppMultCF[i],3,mSourceFunc,mNonFemtoFunc,mDrawLegend);
      mPionMultOppRadii.push_back(mFitParams.at(0));
      mPionMultOppRadiiErr.push_back(mFitParams.at(1));
      mPionMultOppLambda.push_back(mFitParams.at(2));
      mPionMultOppLambdaErr.push_back(mFitParams.at(3));
    }
  }

  ////////////////////////////////////
  //              Kt values         //
  ////////////////////////////////////

  if (mIsKaon) { // kaons
    for(unsigned int i=0; i<hKaonMixKtCF.size(); i++) {
      mFitParams.clear();
      mFitParams = DoFit(hKaonMixKtCF[i],4,mSourceFunc,mNonFemtoFunc,mDrawLegend);
      mKaonKtMixRadii.push_back(mFitParams.at(0));
      mKaonKtMixRadiiErr.push_back(mFitParams.at(1));
      mKaonKtMixLambda.push_back(mFitParams.at(2));
      mKaonKtMixLambdaErr.push_back(mFitParams.at(3));
    }

    for(unsigned int i=0; i<hKaonRotKtCF.size(); i++) {
      mFitParams.clear();
      mFitParams = DoFit(hKaonRotKtCF[i],4,mSourceFunc,mNonFemtoFunc,mDrawLegend);
      mKaonKtRotRadii.push_back(mFitParams.at(0));
      mKaonKtRotRadiiErr.push_back(mFitParams.at(1));
      mKaonKtRotLambda.push_back(mFitParams.at(2));
      mKaonKtRotLambdaErr.push_back(mFitParams.at(3));
    }

    for(unsigned int i=0; i<hKaonOppKtCF.size(); i++) {
      mFitParams.clear();
      mFitParams = DoFit(hKaonOppKtCF[i],4,mSourceFunc,mNonFemtoFunc,mDrawLegend);
      mKaonKtOppRadii.push_back(mFitParams.at(0));
      mKaonKtOppRadiiErr.push_back(mFitParams.at(1));
      mKaonKtOppLambda.push_back(mFitParams.at(2));
      mKaonKtOppLambdaErr.push_back(mFitParams.at(3));
    }
  }
  else { // pions
    for(unsigned int i=0; i<hPionMixKtCF.size(); i++) {
      mFitParams.clear();
      mFitParams = DoFit(hPionMixKtCF[i],3,mSourceFunc,mNonFemtoFunc,mDrawLegend);
      mPionKtMixRadii.push_back(mFitParams.at(0));
      mPionKtMixRadiiErr.push_back(mFitParams.at(1));
      mPionKtMixLambda.push_back(mFitParams.at(2));
      mPionKtMixLambdaErr.push_back(mFitParams.at(3));
    }

    for(unsigned int i=0; i<hPionRotKtCF.size(); i++) {
      mFitParams.clear();
      mFitParams = DoFit(hPionRotKtCF[i],3,mSourceFunc,mNonFemtoFunc,mDrawLegend);
      mPionKtRotRadii.push_back(mFitParams.at(0));
      mPionKtRotRadiiErr.push_back(mFitParams.at(1));
      mPionKtRotLambda.push_back(mFitParams.at(2));
      mPionKtRotLambdaErr.push_back(mFitParams.at(3));
    }

    for(unsigned int i=0; i<hPionOppKtCF.size(); i++) {
      mFitParams.clear();
      mFitParams = DoFit(hPionOppKtCF[i],3,mSourceFunc,mNonFemtoFunc,mDrawLegend);
      mPionKtOppRadii.push_back(mFitParams.at(0));
      mPionKtOppRadiiErr.push_back(mFitParams.at(1));
      mPionKtOppLambda.push_back(mFitParams.at(2));
      mPionKtOppLambdaErr.push_back(mFitParams.at(3));
    }
  }

}

//_________________
void DataProcessing::FitUncorrectedCF() {
  std::vector<double> mFitParams;

  ////////////////////////////////////
  //       Multiplicity values      //
  ////////////////////////////////////

  if (mIsKaon) { // kaons
    for(unsigned int i=0; i<hExpKaonMixMultCF.size(); i++) {
      mFitParams.clear();
      mFitParams = DoFit(hExpKaonMixMultCF[i],4,mSourceFunc,mNonFemtoFunc,mDrawLegend);
      mKaonMultMixRadii.push_back(mFitParams.at(0));
      mKaonMultMixRadiiErr.push_back(mFitParams.at(1));
      mKaonMultMixLambda.push_back(mFitParams.at(2));
      mKaonMultMixLambdaErr.push_back(mFitParams.at(3));
    }

    for(unsigned int i=0; i<hExpKaonRotMultCF.size(); i++) {
      mFitParams.clear();
      mFitParams = DoFit(hExpKaonRotMultCF[i],4,mSourceFunc,mNonFemtoFunc,mDrawLegend);
      mKaonMultRotRadii.push_back(mFitParams.at(0));
      mKaonMultRotRadiiErr.push_back(mFitParams.at(1));
      mKaonMultRotLambda.push_back(mFitParams.at(2));
      mKaonMultRotLambdaErr.push_back(mFitParams.at(3));
    }

    for(unsigned int i=0; i<hExpKaonOppMultCF.size(); i++) {
      mFitParams.clear();
      mFitParams = DoFit(hExpKaonOppMultCF[i],4,mSourceFunc,mNonFemtoFunc,mDrawLegend);
      mKaonMultOppRadii.push_back(mFitParams.at(0));
      mKaonMultOppRadiiErr.push_back(mFitParams.at(1));
      mKaonMultOppLambda.push_back(mFitParams.at(2));
      mKaonMultOppLambdaErr.push_back(mFitParams.at(3));
    }
  } 
  else {  // pions
    for(unsigned int i=0; i<hExpPionMixMultCF.size(); i++) {
      mFitParams.clear();
      mFitParams = DoFit(hExpPionMixMultCF[i],3,mSourceFunc,mNonFemtoFunc,mDrawLegend);
      mPionMultMixRadii.push_back(mFitParams.at(0));
      mPionMultMixRadiiErr.push_back(mFitParams.at(1));
      mPionMultMixLambda.push_back(mFitParams.at(2));
      mPionMultMixLambdaErr.push_back(mFitParams.at(3));
    }

    for(unsigned int i=0; i<hExpPionRotMultCF.size(); i++) {
      mFitParams.clear();
      mFitParams = DoFit(hExpPionRotMultCF[i],3,mSourceFunc,mNonFemtoFunc,mDrawLegend);
      mPionMultRotRadii.push_back(mFitParams.at(0));
      mPionMultRotRadiiErr.push_back(mFitParams.at(1));
      mPionMultRotLambda.push_back(mFitParams.at(2));
      mPionMultRotLambdaErr.push_back(mFitParams.at(3));
    }

    for(unsigned int i=0; i<hExpPionOppMultCF.size(); i++) {
      mFitParams.clear();
      mFitParams = DoFit(hExpPionOppMultCF[i],3,mSourceFunc,mNonFemtoFunc,mDrawLegend);
      mPionMultOppRadii.push_back(mFitParams.at(0));
      mPionMultOppRadiiErr.push_back(mFitParams.at(1));
      mPionMultOppLambda.push_back(mFitParams.at(2));
      mPionMultOppLambdaErr.push_back(mFitParams.at(3));
    }
  }



}

//_________________
vector<double> DoFit(TH1* histo, Int_t PartType, Int_t SourceFunc, 
                     Int_t NonFemtoFunc, Bool_t DrawFitLegend, Bool_t mExcludePoints) {

  vector<double> mRetVect;

  Int_t mNbins = histo->GetXaxis()->GetNbins();
  Double_t mFitMinVal = 0.;
  Double_t mDeltaMaxFitVal = -0.005; // -0.005
  Double_t mFitMaxVal = histo->GetXaxis()->GetBinUpEdge(mNbins) + mDeltaMaxFitVal;
  Int_t mFemtoParNum = 2;       //lambda, R
  Int_t mNonFemtoParNum = 0;

  if(NonFemtoFunc == 0)
    mNonFemtoParNum = 1;
  else if(NonFemtoFunc == 1)
    mNonFemtoParNum = 2;
  else if(NonFemtoFunc >= 2 && NonFemtoFunc<=3)
    mNonFemtoParNum = 3;
  else if(NonFemtoFunc >= 4)
    mNonFemtoParNum = 2;

  Int_t mFullParNum = mFemtoParNum + mNonFemtoParNum;
  HbtFitter* mHbtFitter = new HbtFitter(PartType,SourceFunc,NonFemtoFunc);
  mHbtFitter->Set1DMaxVal(histo->GetXaxis()->GetBinUpEdge(mNbins));
  mHbtFitter->Set1DBinsNum(mNbins);
  TF1* mCorrFit = new TF1("mCorrFit",mHbtFitter,&HbtFitter::FitFunction,
                          mFitMinVal,mFitMaxVal,mFullParNum,"HbtFitter","FitFunction");
  mCorrFit->SetParameter(0, 0.5);
  mCorrFit->SetParLimits(0, 0., 1.05);
  mCorrFit->SetParameter(1, 4.);
  mCorrFit->SetParLimits(1, 0., 20.);
  mCorrFit->SetParameter(2, 1.);
  //mCorrFit->SetParLimits(2, 0.9, 1.1);
  mCorrFit->SetLineWidth(3);
  mCorrFit->SetLineColor(kRed);
  //mCorrFit->SetNpx(100);
//  histo->Fit("mCorrFit","MRQE","ep");
  histo->Fit("mCorrFit","MQE","ep", 0., 0.8);
  mCorrFit->Draw("same");

  if(SourceFunc==0) {
    mRetVect.push_back(mCorrFit->GetParameter(1)*MHC);                 //0 R
    mRetVect.push_back(mCorrFit->GetParError(1)*MHC);                  //1 dR
  }
  else if(SourceFunc==1) {
    mRetVect.push_back(mCorrFit->GetParameter(1)*MHC*INVSQRTPI);       //0 R
    mRetVect.push_back(mCorrFit->GetParError(1)*MHC*INVSQRTPI);        //1 dR
  }
  mRetVect.push_back(mCorrFit->GetParameter(0));                       //2 Lam
  mRetVect.push_back(mCorrFit->GetParError(0));                        //3 dLam
  mRetVect.push_back(mCorrFit->GetChisquare()/mCorrFit->GetNDF());     //4 chi2/ndf
  mRetVect.push_back(mCorrFit->GetParameter(2));                       //5 Norm
  mRetVect.push_back(mCorrFit->GetParError(2));                        //6 dNorm

  if(DrawFitLegend) {
    char temp1[100];
    char* temp2;
    TLegend* mLegend = new TLegend(0.4,0.5,0.9,0.9);
    mLegend->SetFillColor(kWhite);
    mLegend->SetHeader("Fit parameters:");

    mLegend->AddEntry("mCorrFit","Bowler-Sinyukov fit","l");
    sprintf(temp1,"#chi^{2}/n.d.f. = %4.3f / %2d",mCorrFit->GetChisquare(),mCorrFit->GetNDF());
    temp2 = temp1;
    mLegend->AddEntry((TObject*)0,temp2,"");
    sprintf(temp1,"N = %4.3f \\pm %4.3f",mRetVect.at(5),mRetVect.at(6));
    temp2 = temp1;
    mLegend->AddEntry((TObject*)0,temp2,"");
    sprintf(temp1,"#lambda = %4.2f \\pm %4.2f",mRetVect.at(2),mRetVect.at(3));
    temp2 = temp1;
    mLegend->AddEntry((TObject*)0,temp2,"");
    sprintf(temp1,"R = %4.2f \\pm %4.2f",mRetVect.at(0),mRetVect.at(1));
    temp2 = temp1;
    mLegend->AddEntry((TObject*)0,temp2,"");

    mLegend->Draw();
  }
  return mRetVect;
}

//_________________
vector<double> DoSeparatedFit(TH1* hExpHisto, TH1* hMcHisto, 
                              Int_t PartType, Int_t SourceFunc, 
                              Int_t NonFemtoFunc, Bool_t DrawFitLegend) {

  vector<double> mNonFemtoVect;
  vector<double> mRetVect;

  Int_t mNbins = hExpHisto->GetXaxis()->GetNbins();
  Double_t mFitMinVal = 0.;
  Double_t mDeltaMaxFitVal = -0.005; // -0.005
  Double_t mFitMaxVal = hExpHisto->GetXaxis()->GetBinUpEdge(mNbins) + mDeltaMaxFitVal;
  Int_t mFemtoParNum = 2;       //lambda, R
  Int_t mNonFemtoParNum = 0;
  if(NonFemtoFunc == 0)
    mNonFemtoParNum = 1;
  else if(NonFemtoFunc == 1)
    mNonFemtoParNum = 2;
  else if(NonFemtoFunc >= 2 && NonFemtoFunc<=3)
    mNonFemtoParNum = 3;
  else if(NonFemtoFunc >= 4)
    mNonFemtoParNum = 2;

  Int_t mFullParNum = mFemtoParNum + mNonFemtoParNum;
  HbtFitter* mHbtFitter = new HbtFitter(PartType,SourceFunc,NonFemtoFunc);
  mHbtFitter->Set1DMaxVal(hExpHisto->GetXaxis()->GetBinUpEdge(mNbins));
  mHbtFitter->Set1DBinsNum(mNbins);

  TF1* mBckgFunc = new TF1("mBckgFunc",mHbtFitter,&HbtFitter::FitBackgroundFunction,
                           mFitMinVal,mFitMaxVal,mNonFemtoParNum,
                           "HbtFitter","FitBackgroundFunction");
  mBckgFunc->SetParameter(0, 1.);
  mBckgFunc->SetLineWidth(3);
  mBckgFunc->SetLineColor(kBlue);
  mBckgFunc->SetLineStyle(9);
  hMcHisto->Fit("mBckgFunc","MRQE","ep");
  //mBckgFunc->Draw("same");   //I guess this line is not really needed

  for(Int_t i=0; i<mNonFemtoParNum; i++) {
    mNonFemtoVect.push_back(mBckgFunc->GetParameter(i));
  }

  mHbtFitter->Set1DBackgroundParameters(mNonFemtoVect);

  TF1* mSigFunc = new TF1("mSigFunc",mHbtFitter,&HbtFitter::FitSignalFunction,
                          mFitMinVal,mFitMaxVal,(mFemtoParNum+1),
                          "HbtFitter","FitSignalFunction");   //mFemtoParNum+1 = lambda,R + Normal
  mSigFunc->SetParameter(0, 0.5);     //Lambda
  mSigFunc->SetParLimits(0, 0., 1.05);
  mSigFunc->SetParameter(1, 5.);      //R
  mSigFunc->SetParLimits(1, 0., 20.); 
  mSigFunc->SetParameter(2, 1.);      //Normalization
  //mSigFunc->SetParLimits(0, 0., 1.05);
  mSigFunc->SetLineWidth(3);
  mSigFunc->SetLineColor(kRed);
  mSigFunc->SetLineStyle(1);
  //mSigFunc->SetNpx(50);
  hExpHisto->Fit("mSigFunc","MRQE","ep");
  mSigFunc->Draw("same");

  if(SourceFunc==0) {
    mRetVect.push_back(mSigFunc->GetParameter(1)*MHC);            //0 R
    mRetVect.push_back(mSigFunc->GetParError(1)*MHC);             //1 dR
  }
  else if(SourceFunc==1) {
    mRetVect.push_back(mSigFunc->GetParameter(1)*MHC*INVSQRTPI);  //0 R
    mRetVect.push_back(mSigFunc->GetParError(1)*MHC*INVSQRTPI);   //1 dR
  }
  mRetVect.push_back(mSigFunc->GetParameter(0));                  //2 Lam
  mRetVect.push_back(mSigFunc->GetParError(0));                   //3 dLam
  mRetVect.push_back(mSigFunc->GetChisquare()/mSigFunc->GetNDF());//4 chi2/ndf

  if(DrawFitLegend) {
    char temp1[100];
    char* temp2;
    TLegend* mLegend = new TLegend(0.4,0.5,0.9,0.9);
    mLegend->SetFillColor(kWhite);
    mLegend->SetHeader("Fit parameters:");

    mLegend->AddEntry("mSigFunc","Bowler-Sinyukov fit","l");
    sprintf(temp1,"#chi^{2}/n.d.f. = %4.3f/%2d ",mSigFunc->GetChisquare(),mSigFunc->GetNDF());
    temp2 = temp1;
    mLegend->AddEntry((TObject*)0,temp2,"");
    sprintf(temp1,"#lambda = %4.2f \\pm %4.2f",mRetVect.at(2),mRetVect.at(3));
    temp2 = temp1;
    mLegend->AddEntry((TObject*)0,temp2,"");
    sprintf(temp1,"R = %4.2f \\pm %4.2f",mRetVect.at(0),mRetVect.at(1));
    temp2 = temp1;
    mLegend->AddEntry((TObject*)0,temp2,"");
    mLegend->Draw();
  }
  return mRetVect;
}
