Fixing a bug with DCA
[u/mrichter/AliRoot.git] / CORRFW / AliCFGridSparse.cxx
1 /**************************************************************************
2  * Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
3  *                                                                        *
4  * Author: The ALICE Off-line Project.                                    *
5  * Contributors are mentioned in the code where appropriate.              *
6  *                                                                        *
7  * Permission to use, copy, modify and distribute this software and its   *
8  * documentation strictly for non-commercial purposes is hereby granted   *
9  * without fee, provided that the above copyright notice appears in all   *
10  * copies and that both the copyright notice and this permission notice   *
11  * appear in the supporting documentation. The authors make no claims     *
12  * about the suitability of this software for any purpose. It is          *
13  * provided "as is" without express or implied warranty.                  *
14  **************************************************************************/
15 //--------------------------------------------------------------------//
16 //                                                                    //
17 // AliCFGridSparse Class                                              //
18 // Class to accumulate data on an N-dimensional grid, to be used      //
19 // as input to get corrections for Reconstruction & Trigger efficiency// 
20 // Based on root THnSparse                                            //
21 // -- Author : S.Arcelli                                              //
22 // Still to be done:                                                  //
23 // --Interpolate among bins in a range                                // 
24 //--------------------------------------------------------------------//
25 //
26 //
27 #include "AliCFGridSparse.h"
28 #include "THnSparse.h"
29 #include "AliLog.h"
30 #include "TMath.h"
31 #include "TROOT.h"
32 #include "TH1D.h"
33 #include "TH2D.h"
34 #include "TH3D.h"
35 #include "TAxis.h"
36 #include "AliCFUnfolding.h"
37
38 //____________________________________________________________________
39 ClassImp(AliCFGridSparse)
40
41 //____________________________________________________________________
42 AliCFGridSparse::AliCFGridSparse() : 
43   AliCFFrame(),
44   fSumW2(kFALSE),
45   fData(0x0)
46 {
47   // default constructor
48 }
49 //____________________________________________________________________
50 AliCFGridSparse::AliCFGridSparse(const Char_t* name, const Char_t* title) : 
51   AliCFFrame(name,title),
52   fSumW2(kFALSE),
53   fData(0x0)
54 {
55   // default constructor
56 }
57 //____________________________________________________________________
58 AliCFGridSparse::AliCFGridSparse(const Char_t* name, const Char_t* title, Int_t nVarIn, const Int_t * nBinIn) :  
59   AliCFFrame(name,title),
60   fSumW2(kFALSE),
61   fData(0x0)
62 {
63   //
64   // main constructor
65   //
66
67   fData = new THnSparseF(name,title,nVarIn,nBinIn);
68 }
69
70 //____________________________________________________________________
71 AliCFGridSparse::~AliCFGridSparse()
72 {
73   //
74   // destructor
75   //
76   if (fData) delete fData;
77 }
78
79 //____________________________________________________________________
80 AliCFGridSparse::AliCFGridSparse(const AliCFGridSparse& c) :
81   AliCFFrame(c),
82   fSumW2(kFALSE),
83   fData(0x0)
84 {
85   //
86   // copy constructor
87   //
88   ((AliCFGridSparse &)c).Copy(*this);
89 }
90
91 //____________________________________________________________________
92 AliCFGridSparse& AliCFGridSparse::operator=(const AliCFGridSparse &c)
93 {
94   //
95   // assigment operator
96   //
97   if (this != &c) c.Copy(*this);
98   return *this;
99
100
101 //____________________________________________________________________
102 void AliCFGridSparse::SetBinLimits(Int_t ivar, Double_t min, Double_t max)
103 {
104   //
105   // set a uniform binning for variable ivar
106   //
107   Int_t nBins = GetNBins(ivar);
108   Double_t * array = new Double_t[nBins+1];
109   for (Int_t iEdge=0; iEdge<=nBins; iEdge++) array[iEdge] = min + iEdge * (max-min)/nBins ;
110   fData->SetBinEdges(ivar, array);
111   delete [] array ;
112
113
114 //____________________________________________________________________
115 void AliCFGridSparse::SetBinLimits(Int_t ivar, const Double_t *array)
116 {
117   //
118   // setting the arrays containing the bin limits 
119   //
120   fData->SetBinEdges(ivar, array);
121
122
123 //____________________________________________________________________
124 void AliCFGridSparse::Fill(const Double_t *var, Double_t weight)
125 {
126   //
127   // Fill the grid,
128   // given a set of values of the input variable, 
129   // with weight (by default w=1)
130   //
131   fData->Fill(var,weight);
132 }
133
134 //___________________________________________________________________
135 AliCFGridSparse* AliCFGridSparse::MakeSlice(Int_t nVars, const Int_t* vars, const Double_t* varMin, const Double_t* varMax, Bool_t useBins) const
136 {
137   //
138   // projects the grid on the nVars dimensions defined in vars.
139   // axis ranges can be defined in arrays varMin, varMax
140   // If useBins=true, varMin and varMax are taken as bin numbers
141   //
142
143   // binning for new grid
144   Int_t* bins = new Int_t[nVars];
145   for (Int_t iVar=0; iVar<nVars; iVar++) {
146     bins[iVar] = GetNBins(vars[iVar]);
147   }
148   
149   // create new grid sparse
150   AliCFGridSparse* out = new AliCFGridSparse(fName,fTitle,nVars,bins);
151
152   //set the range in the THnSparse to project
153   THnSparse* clone = ((THnSparse*)fData->Clone());
154   if (varMin && varMax) {
155     for (Int_t iAxis=0; iAxis<GetNVar(); iAxis++) {
156       SetAxisRange(clone->GetAxis(iAxis),varMin[iAxis],varMax[iAxis],useBins);
157     }
158   }
159   else AliInfo("Keeping same axis ranges");
160
161   out->SetGrid(clone->Projection(nVars,vars));
162   delete [] bins;
163   delete clone;
164   return out;
165 }
166
167
168 //____________________________________________________________________
169 Float_t AliCFGridSparse::GetBinCenter(Int_t ivar, Int_t ibin) const
170 {
171   //
172   // Returns the center of specified bin for variable axis ivar
173   // 
174   
175   return (Float_t) fData->GetAxis(ivar)->GetBinCenter(ibin);
176 }
177
178 //____________________________________________________________________
179 Float_t AliCFGridSparse::GetBinSize(Int_t ivar, Int_t ibin) const
180 {
181   //
182   // Returns the size of specified bin for variable axis ivar
183   // 
184   
185   return (Float_t) fData->GetAxis(ivar)->GetBinUpEdge(ibin) - fData->GetAxis(ivar)->GetBinLowEdge(ibin);
186 }
187
188 //____________________________________________________________________
189 Float_t AliCFGridSparse::GetEntries() const
190 {
191   //
192   // total entries (including overflows and underflows)
193   //
194
195   return fData->GetEntries();
196 }
197
198 //____________________________________________________________________
199 Float_t AliCFGridSparse::GetElement(Long_t index) const
200 {
201   //
202   // Returns content of grid element index 
203   //
204   
205   return fData->GetBinContent(index);
206 }
207 //____________________________________________________________________
208 Float_t AliCFGridSparse::GetElement(const Int_t *bin) const
209 {
210   //
211   // Get the content in a bin corresponding to a set of bin indexes
212   //
213   return fData->GetBinContent(bin);
214
215 }  
216 //____________________________________________________________________
217 Float_t AliCFGridSparse::GetElement(const Double_t *var) const
218 {
219   //
220   // Get the content in a bin corresponding to a set of input variables
221   //
222
223   Long_t index = fData->GetBin(var,kFALSE);
224   if (index<0) return 0.;
225   return fData->GetBinContent(index);
226
227
228 //____________________________________________________________________
229 Float_t AliCFGridSparse::GetElementError(Long_t index) const
230 {
231   //
232   // Returns the error on the content 
233   //
234
235   return fData->GetBinError(index);
236 }
237 //____________________________________________________________________
238 Float_t AliCFGridSparse::GetElementError(const Int_t *bin) const
239 {
240  //
241   // Get the error in a bin corresponding to a set of bin indexes
242   //
243   return fData->GetBinError(bin);
244
245 }  
246 //____________________________________________________________________
247 Float_t AliCFGridSparse::GetElementError(const Double_t *var) const
248 {
249   //
250   // Get the error in a bin corresponding to a set of input variables
251   //
252
253   Long_t index=fData->GetBin(var,kFALSE); //this is the THnSparse index (do not allocate new cells if content is empy)
254   if (index<0) return 0.;
255   return fData->GetBinError(index);
256
257
258 //____________________________________________________________________
259 void AliCFGridSparse::SetElement(Long_t index, Float_t val)
260 {
261   //
262   // Sets grid element value
263   //
264   Int_t* bin = new Int_t[GetNVar()];
265   fData->GetBinContent(index,bin); //affects the bin coordinates
266   SetElement(bin,val);
267   delete [] bin ;
268 }
269
270 //____________________________________________________________________
271 void AliCFGridSparse::SetElement(const Int_t *bin, Float_t val)
272 {
273   //
274   // Sets grid element of bin indeces bin to val
275   //
276   fData->SetBinContent(bin,val);
277 }
278 //____________________________________________________________________
279 void AliCFGridSparse::SetElement(const Double_t *var, Float_t val) 
280 {
281   //
282   // Set the content in a bin to value val corresponding to a set of input variables
283   //
284   Long_t index=fData->GetBin(var,kTRUE); //THnSparse index: allocate the cell
285   Int_t *bin = new Int_t[GetNVar()];
286   fData->GetBinContent(index,bin); //trick to access the array of bins
287   SetElement(bin,val);
288   delete [] bin;
289 }
290
291 //____________________________________________________________________
292 void AliCFGridSparse::SetElementError(Long_t index, Float_t val)
293 {
294   //
295   // Sets grid element iel error to val (linear indexing) in AliCFFrame
296   //
297   Int_t *bin = new Int_t[GetNVar()];
298   fData->GetBinContent(index,bin);
299   SetElementError(bin,val);
300   delete [] bin;
301 }
302
303 //____________________________________________________________________
304 void AliCFGridSparse::SetElementError(const Int_t *bin, Float_t val)
305 {
306   //
307   // Sets grid element error of bin indeces bin to val
308   //
309   fData->SetBinError(bin,val);
310 }
311 //____________________________________________________________________
312 void AliCFGridSparse::SetElementError(const Double_t *var, Float_t val) 
313 {
314   //
315   // Set the error in a bin to value val corresponding to a set of input variables
316   //
317   Long_t index=fData->GetBin(var); //THnSparse index
318   Int_t *bin = new Int_t[GetNVar()];
319   fData->GetBinContent(index,bin); //trick to access the array of bins
320   SetElementError(bin,val);
321   delete [] bin;
322 }
323
324 //____________________________________________________________________
325 void AliCFGridSparse::SumW2()
326 {
327   //
328   //set calculation of the squared sum of the weighted entries
329   //
330   if(!fSumW2){
331     fData->CalculateErrors(kTRUE); 
332   }
333   fSumW2=kTRUE;
334 }
335
336 //____________________________________________________________________
337 void AliCFGridSparse::Add(const AliCFGridSparse* aGrid, Double_t c)
338 {
339   //
340   //add aGrid to the current one
341   //
342
343   if (aGrid->GetNVar() != GetNVar()){
344     AliError("Different number of variables, cannot add the grids");
345     return;
346   } 
347   
348   if (!fSumW2  && aGrid->GetSumW2()) SumW2();
349   fData->Add(aGrid->GetGrid(),c);
350 }
351
352 //____________________________________________________________________
353 void AliCFGridSparse::Add(const AliCFGridSparse* aGrid1, const AliCFGridSparse* aGrid2, Double_t c1,Double_t c2)
354 {
355   //
356   //Add aGrid1 and aGrid2 and deposit the result into the current one
357   //
358
359   if (GetNVar() != aGrid1->GetNVar() || GetNVar() != aGrid2->GetNVar()) {
360     AliInfo("Different number of variables, cannot add the grids");
361     return;
362   } 
363   
364   if (!fSumW2  && (aGrid1->GetSumW2() || aGrid2->GetSumW2())) SumW2();
365
366   fData->Reset();
367   fData->Add(aGrid1->GetGrid(),c1);
368   fData->Add(aGrid2->GetGrid(),c2);
369 }
370
371 //____________________________________________________________________
372 void AliCFGridSparse::Multiply(const AliCFGridSparse* aGrid, Double_t c)
373 {
374   //
375   // Multiply aGrid to the current one
376   //
377
378   if (aGrid->GetNVar() != GetNVar()) {
379     AliError("Different number of variables, cannot multiply the grids");
380     return;
381   } 
382   
383   if(!fSumW2  && aGrid->GetSumW2()) SumW2();
384   THnSparse *h = aGrid->GetGrid();
385   fData->Multiply(h);
386   fData->Scale(c);
387 }
388
389 //____________________________________________________________________
390 void AliCFGridSparse::Multiply(const AliCFGridSparse* aGrid1, const AliCFGridSparse* aGrid2, Double_t c1,Double_t c2)
391 {
392   //
393   //Multiply aGrid1 and aGrid2 and deposit the result into the current one
394   //
395
396   if (GetNVar() != aGrid1->GetNVar() || GetNVar() != aGrid2->GetNVar()) {
397     AliError("Different number of variables, cannot multiply the grids");
398     return;
399   }
400   
401   if(!fSumW2  && (aGrid1->GetSumW2() || aGrid2->GetSumW2())) SumW2();
402
403   fData->Reset();
404   THnSparse *h1 = aGrid1->GetGrid();
405   THnSparse *h2 = aGrid2->GetGrid();
406   h2->Multiply(h1);
407   h2->Scale(c1*c2);
408   fData->Add(h2);
409 }
410
411 //____________________________________________________________________
412 void AliCFGridSparse::Divide(const AliCFGridSparse* aGrid, Double_t c)
413 {
414   //
415   // Divide aGrid to the current one
416   //
417
418   if (aGrid->GetNVar() != GetNVar()) {
419     AliError("Different number of variables, cannot divide the grids");
420     return;
421   } 
422   
423   if (!fSumW2  && aGrid->GetSumW2()) SumW2();
424
425   THnSparse *h1 = aGrid->GetGrid();
426   THnSparse *h2 = (THnSparse*)fData->Clone();
427   fData->Divide(h2,h1);
428   fData->Scale(c);
429 }
430
431 //____________________________________________________________________
432 void AliCFGridSparse::Divide(const AliCFGridSparse* aGrid1, const AliCFGridSparse* aGrid2, Double_t c1,Double_t c2, Option_t *option)
433 {
434   //
435   //Divide aGrid1 and aGrid2 and deposit the result into the current one
436   //binomial errors are supported
437   //
438
439   if (GetNVar() != aGrid1->GetNVar() || GetNVar() != aGrid2->GetNVar()) {
440     AliError("Different number of variables, cannot divide the grids");
441     return;
442   } 
443   
444   if (!fSumW2  && (aGrid1->GetSumW2() || aGrid2->GetSumW2())) SumW2();
445
446   THnSparse *h1= aGrid1->GetGrid();
447   THnSparse *h2= aGrid2->GetGrid();
448   fData->Divide(h1,h2,c1,c2,option);
449 }
450
451
452 //____________________________________________________________________
453 void AliCFGridSparse::Rebin(const Int_t* group)
454 {
455   //
456   // rebin the grid according to Rebin() as in THnSparse
457   // Please notice that the original number of bins on
458   // a given axis has to be divisible by the rebin group.
459   //
460
461   for(Int_t i=0;i<GetNVar();i++){
462     if (group[i]!=1) AliInfo(Form(" merging bins along dimension %i in groups of %i bins", i,group[i]));
463   }
464
465   THnSparse *rebinned =fData->Rebin(group);
466   fData->Reset();
467   fData = rebinned;
468 }
469 //____________________________________________________________________
470 void AliCFGridSparse::Scale(Long_t index, const Double_t *fact)
471 {
472   //
473   //scale content of a certain cell by (positive) fact (with error)
474   //
475
476   if (GetElement(index)==0 || fact[0]==0) return;
477
478   Double_t in[2], out[2];
479   in[0]=GetElement(index);
480   in[1]=GetElementError(index);
481   GetScaledValues(fact,in,out);
482   SetElement(index,out[0]);
483   if (fSumW2) SetElementError(index,out[1]);
484 }
485 //____________________________________________________________________
486 void AliCFGridSparse::Scale(const Int_t *bin, const Double_t *fact)
487 {
488   //
489   //scale content of a certain cell by (positive) fact (with error)
490   //
491   if(GetElement(bin)==0 || fact[0]==0)return;
492
493   Double_t in[2], out[2];
494   in[0]=GetElement(bin);
495   in[1]=GetElementError(bin);
496   GetScaledValues(fact,in,out);
497   SetElement(bin,out[0]);
498   if(fSumW2)SetElementError(bin,out[1]);
499   
500 }
501 //____________________________________________________________________
502 void AliCFGridSparse::Scale(const Double_t *var, const Double_t *fact) 
503 {
504   //
505   //scale content of a certain cell by (positive) fact (with error)
506   //
507   if(GetElement(var)==0 || fact[0]==0)return;
508
509   Double_t in[2], out[2];
510   in[0]=GetElement(var);
511   in[1]=GetElementError(var);
512   GetScaledValues(fact,in,out);
513   SetElement(var,out[0]);
514   if(fSumW2)SetElementError(var,out[1]);
515   
516 }
517 //____________________________________________________________________
518 void AliCFGridSparse::Scale(const Double_t* fact)
519 {
520   //
521   //scale contents of the whole grid by fact
522   //
523
524   for (Long_t iel=0; iel<GetNFilledBins(); iel++) {
525     Scale(iel,fact);
526   }
527 }
528 //____________________________________________________________________
529 Long_t AliCFGridSparse::GetEmptyBins() const {
530   //
531   // Get empty bins 
532   //
533
534   return (GetNBinsTotal() - GetNFilledBins()) ;
535
536
537 //____________________________________________________________________
538 Int_t AliCFGridSparse::CheckStats(Double_t thr) const
539 {
540   //
541   // Count the cells below a certain threshold
542   //
543   Int_t ncellsLow=0;
544   for (Int_t i=0; i<GetNBinsTotal(); i++) {
545     if (GetElement(i)<thr) ncellsLow++;
546   }
547   return ncellsLow;
548 }
549
550 //_____________________________________________________________________
551 Double_t AliCFGridSparse::GetIntegral() const 
552 {
553   //
554   // Get full Integral
555   //
556   return fData->ComputeIntegral();  
557
558
559 //____________________________________________________________________
560 Long64_t AliCFGridSparse::Merge(TCollection* list)
561 {
562   //
563   // Merge a list of AliCFGridSparse with this (needed for PROOF). 
564   // Returns the number of merged objects (including this).
565   //
566
567   if (!list)
568     return 0;
569   
570   if (list->IsEmpty())
571     return 1;
572
573   TIterator* iter = list->MakeIterator();
574   TObject* obj;
575   
576   Int_t count = 0;
577   while ((obj = iter->Next())) {
578     AliCFGridSparse* entry = dynamic_cast<AliCFGridSparse*> (obj);
579     if (entry == 0) 
580       continue;
581     this->Add(entry);
582     count++;
583   }
584
585   return count+1;
586 }
587
588 //____________________________________________________________________
589 void AliCFGridSparse::GetScaledValues(const Double_t *fact, const Double_t *in, Double_t *out) const{
590   //
591   // scale input *in and its error by (positive) fact (with error)
592   // and erite it to *out
593   //
594   out[0]=in[0]*fact[0];
595   out[1]=TMath::Sqrt(in[1]*in[1]/in[0]/in[0]
596                      +fact[1]*fact[1]/fact[0]/fact[0])*out[0];
597     
598 }
599
600 //____________________________________________________________________
601 void AliCFGridSparse::Copy(TObject& c) const
602 {
603   //
604   // copy function
605   //
606   AliCFFrame::Copy(c);
607   AliCFGridSparse& target = (AliCFGridSparse &) c;
608   target.fSumW2 = fSumW2 ;
609   if (fData) {
610     target.fData = (THnSparse*)fData->Clone();
611   }
612 }
613
614 //____________________________________________________________________
615 TH1* AliCFGridSparse::Slice(Int_t iVar1, Int_t iVar2, Int_t iVar3, const Double_t *varMin, const Double_t *varMax, Bool_t useBins) const
616 {
617   //
618   // return a slice on variables iVar1 (and optionnally iVar2 (and iVar3)) while axis ranges are defined with varMin,varMax
619   // arrays varMin and varMax contain the min and max values of each variable.
620   // therefore varMin and varMax must have their dimensions equal to GetNVar()
621   // If useBins=true, varMin and varMax are taken as bin numbers
622   // if varmin or varmax point to null, all the range is taken, including over- and underflows
623
624   THnSparse* clone = (THnSparse*)fData->Clone();
625   if (varMin != 0x0 && varMax != 0x0) {
626     for (Int_t iAxis=0; iAxis<GetNVar(); iAxis++) SetAxisRange(clone->GetAxis(iAxis),varMin[iAxis],varMax[iAxis],useBins);
627   }
628
629   TH1* projection = 0x0 ;
630   TString name,title;
631   GetProjectionName (name ,iVar1,iVar2,iVar3);
632   GetProjectionTitle(title,iVar1,iVar2,iVar3);
633
634   if (iVar3<0) {
635     if (iVar2<0) {
636       if (iVar1 >= GetNVar() || iVar1 < 0 ) {
637         AliError("Non-existent variable, return NULL");
638         return 0x0;
639       }
640       projection = (TH1D*)clone->Projection(iVar1); 
641       projection->SetTitle(Form("%s_proj-%s",GetTitle(),GetVarTitle(iVar1)));
642       for (Int_t iBin=1; iBin<=projection->GetNbinsX(); iBin++) {
643         Int_t origBin = GetAxis(iVar1)->GetFirst()+iBin-1;
644         TString binLabel = GetAxis(iVar1)->GetBinLabel(origBin) ;
645         if (binLabel.CompareTo("") != 0) projection->GetXaxis()->SetBinLabel(iBin,binLabel);
646       }
647     }
648     else {
649       if (iVar1 >= GetNVar() || iVar1 < 0 ||
650           iVar2 >= GetNVar() || iVar2 < 0 ) {
651         AliError("Non-existent variable, return NULL");
652         return 0x0;
653       }
654       projection = (TH2D*)clone->Projection(iVar2,iVar1); 
655       for (Int_t iBin=1; iBin<=projection->GetNbinsX(); iBin++) {
656         Int_t origBin = GetAxis(iVar1)->GetFirst()+iBin-1;
657         TString binLabel = GetAxis(iVar1)->GetBinLabel(origBin) ;
658         if (binLabel.CompareTo("") != 0) projection->GetXaxis()->SetBinLabel(iBin,binLabel);
659       }
660       for (Int_t iBin=1; iBin<=projection->GetNbinsY(); iBin++) {
661         Int_t origBin = GetAxis(iVar2)->GetFirst()+iBin-1;
662         TString binLabel = GetAxis(iVar2)->GetBinLabel(origBin) ;
663         if (binLabel.CompareTo("") != 0) projection->GetYaxis()->SetBinLabel(iBin,binLabel);
664       }
665     }
666   }
667   else {
668     if (iVar1 >= GetNVar() || iVar1 < 0 ||
669         iVar2 >= GetNVar() || iVar2 < 0 ||
670         iVar3 >= GetNVar() || iVar3 < 0 ) {
671       AliError("Non-existent variable, return NULL");
672       return 0x0;
673     }
674     projection = (TH3D*)clone->Projection(iVar1,iVar2,iVar3); 
675     for (Int_t iBin=1; iBin<=projection->GetNbinsX(); iBin++) {
676       Int_t origBin = GetAxis(iVar1)->GetFirst()+iBin-1;
677       TString binLabel = GetAxis(iVar1)->GetBinLabel(origBin) ;
678       if (binLabel.CompareTo("") != 0) projection->GetXaxis()->SetBinLabel(iBin,binLabel);
679     }
680     for (Int_t iBin=1; iBin<=projection->GetNbinsY(); iBin++) {
681       Int_t origBin = GetAxis(iVar2)->GetFirst()+iBin-1;
682       TString binLabel = GetAxis(iVar2)->GetBinLabel(origBin) ;
683       if (binLabel.CompareTo("") != 0) projection->GetYaxis()->SetBinLabel(iBin,binLabel);
684     }
685     for (Int_t iBin=1; iBin<=projection->GetNbinsZ(); iBin++) {
686       Int_t origBin = GetAxis(iVar3)->GetFirst()+iBin-1;
687       TString binLabel = GetAxis(iVar3)->GetBinLabel(origBin) ;
688       if (binLabel.CompareTo("") != 0) projection->GetZaxis()->SetBinLabel(iBin,binLabel);
689     }
690   }
691   
692   projection->SetName (name .Data());
693   projection->SetTitle(title.Data());
694
695   delete clone;
696   return projection ;
697 }
698
699 //____________________________________________________________________
700 void AliCFGridSparse::SetAxisRange(TAxis* axis, Double_t min, Double_t max, Bool_t useBins) const {
701   //
702   // sets axis range, and forces bit TAxis::kAxisRange
703   //
704   
705   if (useBins) axis->SetRange    ((Int_t)min,(Int_t)max);
706   else         axis->SetRangeUser(       min,       max);
707   //axis->SetBit(TAxis::kAxisRange); // uncomment when ROOT TAxis is fixed
708 }
709
710 //____________________________________________________________________
711 void AliCFGridSparse::SetRangeUser(Int_t iVar, Double_t varMin, Double_t varMax, Bool_t useBins) const {
712   //
713   // set range of axis iVar. 
714   //
715   SetAxisRange(fData->GetAxis(iVar),varMin,varMax,useBins);
716         //AliInfo(Form("AliCFGridSparse axis %d range has been modified",iVar));
717         TAxis* currAxis = fData->GetAxis(iVar);
718   TString outString = Form("%s new range: %.1f < %s < %.1f", GetName(), currAxis->GetBinLowEdge(currAxis->GetFirst()), currAxis->GetTitle(), currAxis->GetBinUpEdge(currAxis->GetLast()));
719   TString binLabel = currAxis->GetBinLabel(currAxis->GetFirst());
720   if ( ! binLabel.IsNull() ) {
721     outString += " ( ";
722     for ( Int_t ibin = currAxis->GetFirst(); ibin <= currAxis->GetLast(); ibin++ ) {
723       outString += Form("%s ", currAxis->GetBinLabel(ibin));
724     }
725     outString += ")";
726   }
727   AliWarning(outString.Data());
728
729 }
730
731 //____________________________________________________________________
732 void AliCFGridSparse::SetRangeUser(const Double_t *varMin, const Double_t *varMax, Bool_t useBins) const {
733   //
734   // set range of every axis. varMin and varMax must be of dimension GetNVar()
735   //
736   for (Int_t iAxis=0; iAxis<GetNVar() ; iAxis++) { // set new range for every axis
737     SetRangeUser(iAxis,varMin[iAxis],varMax[iAxis], useBins);
738   }
739   AliInfo("AliCFGridSparse axes ranges have been modified");
740 }
741
742 //____________________________________________________________________
743 Float_t AliCFGridSparse::GetOverFlows(Int_t ivar, Bool_t exclusive) const
744 {
745   //
746   // Returns overflows in variable ivar
747   // Set 'exclusive' to true for an exclusive check on variable ivar
748   //
749   Int_t* bin = new Int_t[GetNVar()];
750   memset(bin, 0, sizeof(Int_t) * GetNVar());
751   Float_t ovfl=0.;
752   for (Long64_t i = 0; i < fData->GetNbins(); i++) {
753     Double_t v = fData->GetBinContent(i, bin);
754     Bool_t add=kTRUE;
755     if (exclusive) {
756       for(Int_t j=0;j<GetNVar();j++){
757         if(ivar==j)continue;
758         if((bin[j]==0) || (bin[j]==GetNBins(j)+1))add=kFALSE;
759       }
760     }
761     if(bin[ivar]==GetNBins(ivar)+1 && add) ovfl+=v;
762   }
763
764   delete[] bin;
765   return ovfl;
766 }
767
768 //____________________________________________________________________
769 Float_t AliCFGridSparse::GetUnderFlows(Int_t ivar, Bool_t exclusive) const
770 {
771   //
772   // Returns exclusive overflows in variable ivar
773   // Set 'exclusive' to true for an exclusive check on variable ivar
774   //
775   Int_t* bin = new Int_t[GetNVar()];
776   memset(bin, 0, sizeof(Int_t) * GetNVar());
777   Float_t unfl=0.;
778   for (Long64_t i = 0; i < fData->GetNbins(); i++) {
779     Double_t v = fData->GetBinContent(i, bin);
780     Bool_t add=kTRUE;
781     if (exclusive) {
782       for(Int_t j=0;j<GetNVar();j++){
783         if(ivar==j)continue;
784         if((bin[j]==0) || (bin[j]==GetNBins(j)+1))add=kFALSE;
785       }
786     }
787     if(bin[ivar]==0 && add) unfl+=v;
788   }
789
790   delete[] bin;
791   return unfl;
792 }
793
794
795 //____________________________________________________________________
796 void AliCFGridSparse::Smooth() {
797   //
798   // smoothing function: TO USE WITH CARE
799   //
800
801   AliInfo("Your GridSparse is going to be smoothed");
802   AliInfo(Form("N TOTAL  BINS : %li",GetNBinsTotal()));
803   AliInfo(Form("N FILLED BINS : %li",GetNFilledBins()));
804   AliCFUnfolding::SmoothUsingNeighbours(fData);
805 }