#ifndef FemtoUtils_h
#define FemtoUtils_h

#include <TH1.h>
#include <TH3.h>

//_________________
void NormalizeQinv(TH1 *h) {

  Int_t mNbins = h->GetNbinsX();
  Int_t mHNbins = mNbins/2;

  Double_t scale = h->Integral(1, mNbins);
  scale -= h->Integral(1, mHNbins);
  h->Scale(1./scale);
}

//_________________
void Normalize1DCorrFctn(TH1 *h) {

  Int_t mNbins = h->GetNbinsX();
  Int_t mHNbins = mNbins/2;

  Double_t scale = h->Integral(1, mNbins);
  scale -= h->Integral(1, mHNbins);
  h->Scale((Float_t)(mNbins-mHNbins)/scale);
}

//_________________
void NormalizeQosl(TH3 *h) {

  Bool_t mIsSymmetric = false;
  Int_t mNbinsX = h->GetNbinsX();
  Int_t mNbinsY = h->GetNbinsY();
  Int_t mNbinsZ = h->GetNbinsZ();

  if( (h->GetXaxis()->GetBinLowEdge(1) < 0.) &&
      (h->GetYaxis()->GetBinLowEdge(1) < 0.) &&
      (h->GetZaxis()->GetBinLowEdge(1) < 0.) ) {
    mIsSymmetric = true;
  }

  Double_t scale = 0.;

  for(Int_t iBinX=1; iBinX<mNbinsX; iBinX++) {
    for(Int_t iBinY=1; iBinY<mNbinsY; iBinY++) {
      for(Int_t iBinZ=1; iBinZ<mNbinsZ; iBinZ++) {
	scale += h->GetBinContent(iBinX, iBinY, iBinZ);
      } //for(Int_t iBinZ=1; iBinZ<mNbinsZ; iBinZ++)
    } //for(Int_t iBinY=1; iBinY<mNbinsY; iBinY++)
  } //for(Int_t iBinX=1; iBinX<mNbinsX; iBinX++)
  
  if(mIsSymmetric) {

    Int_t mQNbinsX = mNbinsX/4;
    Int_t mQNbinsY = mNbinsY/4;
    Int_t mQNbinsZ = mNbinsZ/4;

    for(Int_t iBinX=mQNbinsX; iBinX<(mNbinsX-mQNbinsX); iBinX++) {
      for(Int_t iBinY=mQNbinsY; iBinY<(mNbinsY-mQNbinsY); iBinY++) {
	for(Int_t iBinZ=mQNbinsZ; iBinZ<(mNbinsZ-mQNbinsZ); iBinZ++) {
	  scale -= h->GetBinContent(iBinX, iBinY, iBinZ);
	} //for(Int_t iBinZ=mQNbinsZ; iBinZ<(mNbinsZ-mQNbinsZ); iBinZ++)
      } //for(Int_t iBinY=mQNbinsY; iBinY<(mNbinsY-mQNbinsY); iBinY++)
    } //for(Int_t iBinX=mQNbinsX; iBinX<(mNbinsX-mQNbinsX); iBinX++)
  }
  else {

    Int_t mHNbinsX = mNbinsX/2;
    Int_t mHNbinsY = mNbinsY/2;
    Int_t mHNbinsZ = mNbinsZ/2;
    for(Int_t iBinX=1; iBinX<mHNbinsX; iBinX++) {
      for(Int_t iBinY=1; iBinY<mHNbinsY; iBinY++) {
	for(Int_t iBinZ=1; iBinZ<mHNbinsZ; iBinZ++) {
	  scale -= h->GetBinContent(iBinX, iBinY, iBinZ);
	} //for(Int_t iBinZ=1; iBinZ<mNbinsZ; iBinZ++)
      } //for(Int_t iBinY=1; iBinY<mNbinsY; iBinY++)
    } //for(Int_t iBinX=1; iBinX<mNbinsX; iBinX++)    
  }

  h->Scale(1./scale);
}

//_________________
void Make1DCorrFctn(TH1* hCorr, TH1* hNum, TH1* hDen) {

  hNum->Sumw2();
  hDen->Sumw2();
  NormalizeQinv(hNum);
  NormalizeQinv(hDen);
  hCorr->Divide(hNum,hDen);
}

//_________________
void Correct1DCorrFctn(TH1* hCorr, TH1* hNum, TH1* hDen) {
  
  Normalize1DCorrFctn(hNum);
  Normalize1DCorrFctn(hDen);
  hCorr->Divide(hNum,hDen);
}

//_________________
void Make3DCorrFctn(TH3* hCorr, TH3* hNum, TH3* hDen) {

  hNum->Sumw2();
  hDen->Sumw2();
  NormalizeQosl(hNum);
  NormalizeQosl(hDen);
  hCorr->Divide(hNum, hDen);
}
#endif
