added warning in SetElement (comment from P. Rosnet)
[u/mrichter/AliRoot.git] / CORRFW / AliCFGridSparse.cxx
index 33a0e5270a90e1862c91a996a7dec573121ac507..695be2c86f40dfe0198a355dfbc1b90ef4bbd71e 100755 (executable)
@@ -40,7 +40,6 @@ ClassImp(AliCFGridSparse)
 //____________________________________________________________________
 AliCFGridSparse::AliCFGridSparse() : 
   AliCFVGrid(),
-  fExcludeOffEntries(kTRUE),
   fData(0x0)
 {
   // default constructor
@@ -48,7 +47,6 @@ AliCFGridSparse::AliCFGridSparse() :
 //____________________________________________________________________
 AliCFGridSparse::AliCFGridSparse(const Char_t* name, const Char_t* title) : 
   AliCFVGrid(name,title),
-  fExcludeOffEntries(kTRUE),
   fData(0x0)
 {
   // default constructor
@@ -56,7 +54,6 @@ AliCFGridSparse::AliCFGridSparse(const Char_t* name, const Char_t* title) :
 //____________________________________________________________________
 AliCFGridSparse::AliCFGridSparse(const Char_t* name, const Char_t* title, const Int_t nVarIn, const Int_t * nBinIn, const Double_t *binLimitsIn) :  
   AliCFVGrid(name,title,nVarIn,nBinIn,binLimitsIn),
-  fExcludeOffEntries(kTRUE),
   fData(0x0)
 {
   //
@@ -80,7 +77,6 @@ AliCFGridSparse::AliCFGridSparse(const Char_t* name, const Char_t* title, const
 //____________________________________________________________________
 AliCFGridSparse::AliCFGridSparse(const AliCFGridSparse& c) : 
   AliCFVGrid(c),
-  fExcludeOffEntries(c.fExcludeOffEntries),
   fData(c.fData)
 {
   //
@@ -142,21 +138,8 @@ TH1D *AliCFGridSparse::Project(Int_t ivar) const
   // Make a 1D projection along variable ivar 
   //
 
-  //exclude overflows by default (used in projections)
-  if(fExcludeOffEntries){
-    for(Int_t i=0;i<fNVar;i++){
-      fData->GetAxis(i)->SetBit(TAxis::kAxisRange);
-    }
-  }
   TH1D *hist=fData->Projection(ivar);
-  Float_t sum=0;
-  for(Int_t i=1;i<=fNVarBins[ivar]; i++){
-    sum+=hist->GetBinContent(i);
-  }
-
-  hist->SetEntries(sum+GetOverFlows(ivar)+GetUnderFlows(ivar));
   return hist;
-
 }
 //___________________________________________________________________
 TH2D *AliCFGridSparse::Project(Int_t ivar1, Int_t ivar2) const
@@ -165,22 +148,7 @@ TH2D *AliCFGridSparse::Project(Int_t ivar1, Int_t ivar2) const
   // Make a 2D projection along variables ivar1 & ivar2 
   //
 
-  //exclude overflows by default (used in projections)
-  if(fExcludeOffEntries){
-    for(Int_t i=0;i<fNVar;i++){
-      fData->GetAxis(i)->SetBit(TAxis::kAxisRange);
-    }
-  }
-  TH2D *hist=fData->Projection(ivar2,ivar1); //notice inverted axis (THnSparse uses TH3 2d-projction convention...)
-
-  Float_t sum=0;
-  for(Int_t i=1;i<=fNVarBins[ivar1]; i++){
-    for(Int_t j=1;j<=fNVarBins[ivar2]; j++){
-    sum+=hist->GetBinContent(i,j);
-    }
-  }
-
-  hist->SetEntries(sum+GetOverFlows(ivar1)+GetUnderFlows(ivar1)+GetOverFlows(ivar2)+GetUnderFlows(ivar2));
+  TH2D *hist=fData->Projection(ivar2,ivar1); //notice inverted axis (THnSparse uses TH3 2d-projection convention...)
   return hist;
 
 }
@@ -190,37 +158,50 @@ TH3D *AliCFGridSparse::Project(Int_t ivar1, Int_t ivar2, Int_t ivar3) const
   //
   // Make a 3D projection along variables ivar1 & ivar2 & ivar3 
   //
-  //exclude overflows by default (used in projections)
-  if(fExcludeOffEntries){
-    for(Int_t i=0;i<fNVar;i++){
-      fData->GetAxis(i)->SetBit(TAxis::kAxisRange);
-    }
-  }
 
   TH3D *hist=fData->Projection(ivar1,ivar2,ivar3); 
+  return hist;
 
-  Float_t sum=0;
-  for(Int_t i=1;i<=fNVarBins[ivar1]; i++){
-    for(Int_t j=1;j<=fNVarBins[ivar2]; j++){
-      for(Int_t k=1;k<=fNVarBins[ivar3]; k++){
-       sum+=hist->GetBinContent(i,j,k);
-      }
+}
+
+//___________________________________________________________________
+AliCFGridSparse* AliCFGridSparse::Project(Int_t nVars, Int_t* vars, Double_t* varMin, Double_t* varMax) const
+{
+  //
+  // projects the grid on the nVars dimensions defined in vars.
+  // axis ranges can be defined in arrays varMin, varMax
+  //
+
+  // binning for new grid
+  Int_t* bins = new Int_t[nVars];
+  for (Int_t iVar=0; iVar<nVars; iVar++) {
+    bins[iVar] = fNVarBins[vars[iVar]];
+  }
+  
+  // create new grid sparse
+  AliCFGridSparse* out = new AliCFGridSparse(fName,fTitle,nVars,bins);
+
+  //set the range in the THnSparse to project
+  THnSparse* clone = ((THnSparse*)fData->Clone());
+  if (varMin && varMax) {
+    for (Int_t iAxis=0; iAxis<fNVar; iAxis++) {
+      clone->GetAxis(iAxis)->SetRangeUser(varMin[iAxis],varMax[iAxis]);
     }
   }
+  else AliInfo("Keeping same axis ranges");
 
-  hist->SetEntries(sum+GetOverFlows(ivar1)+GetUnderFlows(ivar1)+GetOverFlows(ivar2)+GetUnderFlows(ivar2)+GetOverFlows(ivar3)+GetUnderFlows(ivar3));
-  return hist;
-
+  out->SetGrid(clone->Projection(nVars,vars));
+  return out;
 }
 
 //____________________________________________________________________
 Float_t AliCFGridSparse::GetOverFlows(Int_t ivar) const
 {
   //
-  // Returns overflows in variable ivar
+  // Returns exclusive overflows in variable ivar
   //
-  Int_t* bin = new Int_t[fNDim];
-  memset(bin, 0, sizeof(Int_t) * fNDim);
+  Int_t* bin = new Int_t[fNVar];
+  memset(bin, 0, sizeof(Int_t) * fNVar);
   Float_t ovfl=0.;
   for (Long64_t i = 0; i < fData->GetNbins(); ++i) {
     Double_t v = fData->GetBinContent(i, bin);
@@ -240,10 +221,10 @@ Float_t AliCFGridSparse::GetOverFlows(Int_t ivar) const
 Float_t AliCFGridSparse::GetUnderFlows(Int_t ivar) const
 {
   //
-  // Returns overflows in variable ivar
+  // Returns exclusive overflows in variable ivar
   //
-  Int_t* bin = new Int_t[fNDim];
-  memset(bin, 0, sizeof(Int_t) * fNDim);
+  Int_t* bin = new Int_t[fNVar];
+  memset(bin, 0, sizeof(Int_t) * fNVar);
   Float_t unfl=0.;
   for (Long64_t i = 0; i < fData->GetNbins(); ++i) {
     Double_t v = fData->GetBinContent(i, bin);
@@ -368,6 +349,8 @@ void AliCFGridSparse::SetElement(Int_t *bin, Float_t val)
   //
   // Sets grid element of bin indeces bin to val
   //
+  
+  AliWarning("Important: bins should be numbered from 1 to NBins");
   fData->SetBinContent(bin,val);
 }
 //____________________________________________________________________
@@ -586,6 +569,69 @@ void AliCFGridSparse::Divide(AliCFVGrid* aGrid1, AliCFVGrid* aGrid2, Double_t c1
 }
 
 
+//____________________________________________________________________
+void AliCFGridSparse::Rebin(const Int_t* group)
+{
+  //
+  // rebin the grid according to Rebin() as in THnSparse
+  // Please notice that the original number of bins on
+  // a given axis has to be divisible by the rebin group.
+  //
+
+  for(Int_t i=0;i<fNVar;i++){
+    if(group[i]!=1)AliInfo(Form(" merging bins along dimension %i in groups of %i bins", i,group[i]));
+  }
+
+  THnSparse *rebinned =fData->Rebin(group);
+  fData->Reset();
+  fData = rebinned;
+
+  //redefine the needed stuff
+
+  Int_t ndimTot=1;
+  Int_t nbinTot=0;
+
+  //number of bins in each dimension, auxiliary variables
+
+  for(Int_t ivar=0;ivar<fNVar;ivar++){
+    Int_t nbins = fData->GetAxis(ivar)->GetNbins();
+    fNVarBins[ivar]=nbins;
+    ndimTot*=fNVarBins[ivar];
+    nbinTot+=(fNVarBins[ivar]+1);
+    Int_t offset=0;
+    for(Int_t i =0;i<ivar;i++)offset+=(fNVarBins[i]+1);      
+    fOffset[ivar]=offset;
+    Int_t prod=1;
+    for(Int_t i=0;i<ivar;i++)prod*=fNVarBins[i];
+    fProduct[ivar]=prod;
+  }
+
+  fNDim=ndimTot;
+
+  //now the array of bin limits
+
+  delete fVarBinLimits;
+  fNVarBinLimits=nbinTot;
+  fVarBinLimits=new Double_t[fNVarBinLimits];
+
+  for(Int_t ivar=0;ivar<fNVar;ivar++){
+    Double_t low = fData->GetAxis(ivar)->GetXmin();
+    Double_t high = fData->GetAxis(ivar)->GetXmax();    
+    const TArrayD *xbins = fData->GetAxis(ivar)->GetXbins();
+    if (xbins->fN == 0){
+      for(Int_t ibin=0;ibin<=fNVarBins[ivar];ibin++){
+       fVarBinLimits[ibin+fOffset[ivar]] = low + ibin*(high-low)/((Double_t) fNVarBins[ivar]);
+      }
+    }
+    else{
+      
+      for(Int_t ibin=0;ibin<=fNVarBins[ivar];ibin++) {
+       fVarBinLimits[ibin+fOffset[ivar]] = xbins->At(ibin);
+      }
+    }
+  }   
+  
+}
 //____________________________________________________________________
 void AliCFGridSparse::Copy(TObject& c) const
 {
@@ -597,3 +643,75 @@ void AliCFGridSparse::Copy(TObject& c) const
   if(fData)target.fData = fData;
 }
 
+//____________________________________________________________________
+TH1D* AliCFGridSparse::Slice(Int_t iVar, Double_t *varMin, Double_t *varMax) const
+{
+  //
+  // return a slice (1D-projection) on variable iVar while axis ranges are defined with varMin,varMax
+  // arrays varMin and varMax contain the min and max values of each variable.
+  // therefore varMin and varMax must have their dimensions equal to fNVar
+  //
+  
+  THnSparse* clone = (THnSparse*)fData->Clone();
+  for (Int_t iAxis=0; iAxis<fNVar; iAxis++) {
+    clone->GetAxis(iAxis)->SetRangeUser(varMin[iAxis],varMax[iAxis]);
+  }
+  return clone->Projection(iVar);
+}
+
+//____________________________________________________________________
+TH2D* AliCFGridSparse::Slice(Int_t iVar1, Int_t iVar2, Double_t *varMin, Double_t *varMax) const
+{
+  //
+  // return a slice (2D-projection) on variables iVar1 and iVar2 while axis ranges are defined with varMin,varMax
+  // arrays varMin and varMax contain the min and max values of each variable.
+  // therefore varMin and varMax must have their dimensions equal to fNVar
+  //
+  
+  THnSparse* clone = (THnSparse*)fData->Clone();
+  for (Int_t iAxis=0; iAxis<fNVar; iAxis++) {
+    clone->GetAxis(iAxis)->SetRangeUser(varMin[iAxis],varMax[iAxis]);
+  }
+  return clone->Projection(iVar1,iVar2);
+}
+
+//____________________________________________________________________
+TH3D* AliCFGridSparse::Slice(Int_t iVar1, Int_t iVar2, Int_t iVar3, Double_t *varMin, Double_t *varMax) const
+{
+  //
+  // return a slice (3D-projection) on variables iVar1, iVar2 and iVar3 while axis ranges are defined with varMin,varMax
+  // arrays varMin and varMax contain the min and max values of each variable.
+  // therefore varMin and varMax must have their dimensions equal to fNVar
+  //
+
+  THnSparse* clone = (THnSparse*)fData->Clone();
+  for (Int_t iAxis=0; iAxis<fNVar; iAxis++) {
+    clone->GetAxis(iAxis)->SetRangeUser(varMin[iAxis],varMax[iAxis]);
+  }
+  return clone->Projection(iVar1,iVar2,iVar3);
+}
+
+//____________________________________________________________________
+void AliCFGridSparse::SetRangeUser(Int_t iVar, Double_t varMin, Double_t varMax) {
+  //
+  // set range of axis iVar. 
+  //
+  fData->GetAxis(iVar)->SetRangeUser(varMin,varMax);
+  AliWarning(Form("THnSparse axis %d range has been modified",iVar));
+}
+
+//____________________________________________________________________
+void AliCFGridSparse::SetRangeUser(Double_t *varMin, Double_t *varMax) {
+  //
+  // set range of every axis. varMin and varMax must be of dimension fNVar
+  //
+  for (Int_t iAxis=0; iAxis<fNVar ; iAxis++) { // set new range for every axis
+    SetRangeUser(iAxis,varMin[iAxis],varMax[iAxis]);
+  }
+  AliWarning("THnSparse axes ranges have been modified");
+}
+
+//____________________________________________________________________
+void AliCFGridSparse::UseAxisRange(Bool_t b) const {
+  for (Int_t iAxis=0; iAxis<fNVar; iAxis++) fData->GetAxis(iAxis)->SetBit(TAxis::kAxisRange,b);
+}