added warning in SetElement (comment from P. Rosnet)
[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
37 //____________________________________________________________________
38 ClassImp(AliCFGridSparse)
39
40 //____________________________________________________________________
41 AliCFGridSparse::AliCFGridSparse() : 
42   AliCFVGrid(),
43   fData(0x0)
44 {
45   // default constructor
46 }
47 //____________________________________________________________________
48 AliCFGridSparse::AliCFGridSparse(const Char_t* name, const Char_t* title) : 
49   AliCFVGrid(name,title),
50   fData(0x0)
51 {
52   // default constructor
53 }
54 //____________________________________________________________________
55 AliCFGridSparse::AliCFGridSparse(const Char_t* name, const Char_t* title, const Int_t nVarIn, const Int_t * nBinIn, const Double_t *binLimitsIn) :  
56   AliCFVGrid(name,title,nVarIn,nBinIn,binLimitsIn),
57   fData(0x0)
58 {
59   //
60   // main constructor
61   //
62
63   fData=new THnSparseF(name,title,fNVar,fNVarBins);
64   
65   if(binLimitsIn){
66     for(Int_t ivar=0;ivar<fNVar;ivar++){    
67       Int_t nbins=fNVarBins[ivar]+1;
68       Double_t *array= new Double_t[nbins];
69       for(Int_t i=0;i<nbins;i++){
70         array[i]=fVarBinLimits[fOffset[ivar]+i];
71       } 
72       fData->SetBinEdges(ivar, array);
73       delete array;
74     }
75   }
76 }
77 //____________________________________________________________________
78 AliCFGridSparse::AliCFGridSparse(const AliCFGridSparse& c) : 
79   AliCFVGrid(c),
80   fData(c.fData)
81 {
82   //
83   // copy constructor
84   //
85   ((AliCFGridSparse &)c).Copy(*this);
86 }
87
88 //____________________________________________________________________
89 AliCFGridSparse::~AliCFGridSparse()
90 {
91   //
92   // destructor
93   //
94   if(fData) delete fData;
95 }
96
97 //____________________________________________________________________
98 AliCFGridSparse &AliCFGridSparse::operator=(const AliCFGridSparse &c)
99 {
100   //
101   // assigment operator
102   //
103   if (this != &c)
104     ((AliCFGridSparse &) c).Copy(*this);
105   return *this;
106
107
108 //____________________________________________________________________
109 void AliCFGridSparse::SetBinLimits(Int_t ivar, Double_t *array)
110 {
111   //
112   // setting the arrays containing the bin limits 
113   //
114   fData->SetBinEdges(ivar, array);
115   //then fill the appropriate array in ALICFFrame, to be able to use 
116   //the getter, in case....
117   Int_t nbins=fNVarBins[ivar]+1;
118   for(Int_t i=0;i<nbins;i++){
119     fVarBinLimits[fOffset[ivar]+i] =array[i];
120   } 
121
122
123 //____________________________________________________________________
124 void AliCFGridSparse::Fill(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 TH1D *AliCFGridSparse::Project(Int_t ivar) const
136 {
137   //
138   // Make a 1D projection along variable ivar 
139   //
140
141   TH1D *hist=fData->Projection(ivar);
142   return hist;
143 }
144 //___________________________________________________________________
145 TH2D *AliCFGridSparse::Project(Int_t ivar1, Int_t ivar2) const
146 {
147   //
148   // Make a 2D projection along variables ivar1 & ivar2 
149   //
150
151   TH2D *hist=fData->Projection(ivar2,ivar1); //notice inverted axis (THnSparse uses TH3 2d-projection convention...)
152   return hist;
153
154 }
155 //___________________________________________________________________
156 TH3D *AliCFGridSparse::Project(Int_t ivar1, Int_t ivar2, Int_t ivar3) const
157 {
158   //
159   // Make a 3D projection along variables ivar1 & ivar2 & ivar3 
160   //
161
162   TH3D *hist=fData->Projection(ivar1,ivar2,ivar3); 
163   return hist;
164
165 }
166
167 //___________________________________________________________________
168 AliCFGridSparse* AliCFGridSparse::Project(Int_t nVars, Int_t* vars, Double_t* varMin, Double_t* varMax) const
169 {
170   //
171   // projects the grid on the nVars dimensions defined in vars.
172   // axis ranges can be defined in arrays varMin, varMax
173   //
174
175   // binning for new grid
176   Int_t* bins = new Int_t[nVars];
177   for (Int_t iVar=0; iVar<nVars; iVar++) {
178     bins[iVar] = fNVarBins[vars[iVar]];
179   }
180   
181   // create new grid sparse
182   AliCFGridSparse* out = new AliCFGridSparse(fName,fTitle,nVars,bins);
183
184   //set the range in the THnSparse to project
185   THnSparse* clone = ((THnSparse*)fData->Clone());
186   if (varMin && varMax) {
187     for (Int_t iAxis=0; iAxis<fNVar; iAxis++) {
188       clone->GetAxis(iAxis)->SetRangeUser(varMin[iAxis],varMax[iAxis]);
189     }
190   }
191   else AliInfo("Keeping same axis ranges");
192
193   out->SetGrid(clone->Projection(nVars,vars));
194   return out;
195 }
196
197 //____________________________________________________________________
198 Float_t AliCFGridSparse::GetOverFlows(Int_t ivar) const
199 {
200   //
201   // Returns exclusive overflows in variable ivar
202   //
203   Int_t* bin = new Int_t[fNVar];
204   memset(bin, 0, sizeof(Int_t) * fNVar);
205   Float_t ovfl=0.;
206   for (Long64_t i = 0; i < fData->GetNbins(); ++i) {
207     Double_t v = fData->GetBinContent(i, bin);
208     Bool_t add=kTRUE;
209     for(Int_t j=0;j<fNVar;j++){
210       if(ivar==j)continue;
211       if((bin[j]==0) || (bin[j]==fNVarBins[j]+1))add=kFALSE;
212     }
213     if(bin[ivar]==fNVarBins[ivar]+1 && add) ovfl+=v;
214   }
215
216   delete[] bin;
217   return ovfl;
218 }
219
220 //____________________________________________________________________
221 Float_t AliCFGridSparse::GetUnderFlows(Int_t ivar) const
222 {
223   //
224   // Returns exclusive overflows in variable ivar
225   //
226   Int_t* bin = new Int_t[fNVar];
227   memset(bin, 0, sizeof(Int_t) * fNVar);
228   Float_t unfl=0.;
229   for (Long64_t i = 0; i < fData->GetNbins(); ++i) {
230     Double_t v = fData->GetBinContent(i, bin);
231     Bool_t add=kTRUE;
232     for(Int_t j=0;j<fNVar;j++){
233       if(ivar==j)continue;
234       if((bin[j]==0) || (bin[j]==fNVarBins[j]+1))add=kFALSE;
235     }
236     if(bin[ivar]==0 && add) unfl+=v;
237   }
238
239   delete[] bin;
240   return unfl;
241 }
242
243
244 //____________________________________________________________________
245 Float_t AliCFGridSparse::GetEntries() const
246 {
247   //
248   // total entries (including overflows and underflows)
249   //
250
251   return fData->GetEntries();
252 }
253
254 //____________________________________________________________________
255 Float_t AliCFGridSparse::GetElement(Int_t index) const
256 {
257   //
258   // Returns content of grid element index according to the
259   // linear indexing in AliCFFrame
260   //
261   Int_t *bin = new Int_t[fNVar];
262   GetBinIndex(index, bin);
263   for(Int_t i=0;i<fNVar;i++)fIndex[i]=bin[i]+1; //consistency with AliCFGrid
264   Float_t val=GetElement(fIndex);
265   delete [] bin;
266   return val; 
267   
268 }
269 //____________________________________________________________________
270 Float_t AliCFGridSparse::GetElement(Int_t *bin) const
271 {
272   //
273   // Get the content in a bin corresponding to a set of bin indexes
274   //
275   return fData->GetBinContent(bin);
276
277 }  
278 //____________________________________________________________________
279 Float_t AliCFGridSparse::GetElement(Double_t *var) const
280 {
281   //
282   // Get the content in a bin corresponding to a set of input variables
283   //
284
285   Long_t index=fData->GetBin(var,kFALSE); //this is the THnSparse index (do not allocate new cells if content is empty)
286   if(index<0){
287     return 0.;
288   }else{
289     return fData->GetBinContent(index);
290   }
291
292
293 //____________________________________________________________________
294 Float_t AliCFGridSparse::GetElementError(Int_t index) const
295 {
296   //
297   // Returns the error on the content of a bin according to a linear
298   // indexing in AliCFFrame
299   //
300
301   Int_t *bin = new Int_t[fNVar];
302   GetBinIndex(index, bin);
303   for(Int_t i=0;i<fNVar;i++)fIndex[i]=bin[i]+1; //consistency with AliCFGrid
304   Float_t val=GetElementError(fIndex);
305   delete [] bin;
306   return val;
307
308 }
309 //____________________________________________________________________
310 Float_t AliCFGridSparse::GetElementError(Int_t *bin) const
311 {
312  //
313   // Get the error in a bin corresponding to a set of bin indexes
314   //
315   return fData->GetBinError(bin);
316
317 }  
318 //____________________________________________________________________
319 Float_t AliCFGridSparse::GetElementError(Double_t *var) const
320 {
321   //
322   // Get the error in a bin corresponding to a set of input variables
323   //
324
325   Long_t index=fData->GetBin(var,kFALSE); //this is the THnSparse index (do not allocate new cells if content is empy)
326   if(index<0){
327     return 0.;
328   }else{
329     return fData->GetBinError(index);
330   }
331
332
333
334 //____________________________________________________________________
335 void AliCFGridSparse::SetElement(Int_t index, Float_t val)
336 {
337   //
338   // Sets grid element iel to val (linear indexing) in AliCFFrame
339   //
340   Int_t *bin = new Int_t[fNVar];
341   GetBinIndex(index, bin);
342   for(Int_t i=0;i<fNVar;i++)fIndex[i]=bin[i]+1;
343   SetElement(fIndex,val);
344   delete [] bin;
345 }
346 //____________________________________________________________________
347 void AliCFGridSparse::SetElement(Int_t *bin, Float_t val)
348 {
349   //
350   // Sets grid element of bin indeces bin to val
351   //
352   
353   AliWarning("Important: bins should be numbered from 1 to NBins");
354   fData->SetBinContent(bin,val);
355 }
356 //____________________________________________________________________
357 void AliCFGridSparse::SetElement(Double_t *var, Float_t val) 
358 {
359   //
360   // Set the content in a bin to value val corresponding to a set of input variables
361   //
362   Long_t index=fData->GetBin(var); //THnSparse index: allocate the cell
363   Int_t *bin = new Int_t[fNVar];
364   fData->GetBinContent(index,bin); //trick to access the array of bins
365   fData->SetBinContent(bin,val);
366   delete [] bin;
367
368 }
369
370 //____________________________________________________________________
371 void AliCFGridSparse::SetElementError(Int_t index, Float_t val)
372 {
373   //
374   // Sets grid element iel error to val (linear indexing) in AliCFFrame
375   //
376   Int_t *bin = new Int_t[fNVar];
377   GetBinIndex(index, bin);
378   for(Int_t i=0;i<fNVar;i++)fIndex[i]=bin[i]+1;
379   SetElementError(fIndex,val);
380   delete [] bin;
381 }
382 //____________________________________________________________________
383 void AliCFGridSparse::SetElementError(Int_t *bin, Float_t val)
384 {
385   //
386   // Sets grid element error of bin indeces bin to val
387   //
388   fData->SetBinError(bin,val);
389 }
390 //____________________________________________________________________
391 void AliCFGridSparse::SetElementError(Double_t *var, Float_t val) 
392 {
393   //
394   // Set the error in a bin to value val corresponding to a set of input variables
395   //
396   Long_t index=fData->GetBin(var); //THnSparse index
397   Int_t *bin = new Int_t[fNVar];
398   fData->GetBinContent(index,bin); //trick to access the array of bins
399   fData->SetBinError(bin,val);
400   delete [] bin;
401 }
402
403 //____________________________________________________________________
404 void AliCFGridSparse::SumW2()
405 {
406   //
407   //set calculation of the squared sum of the weighted entries
408   //
409   if(!fSumW2){
410     fData->CalculateErrors(kTRUE); 
411   }
412
413   fSumW2=kTRUE;
414 }
415
416 //____________________________________________________________________
417 void AliCFGridSparse::Add(AliCFVGrid* aGrid, Double_t c)
418 {
419   //
420   //add aGrid to the current one
421   //
422
423
424   if(aGrid->GetNVar()!=fNVar){
425     AliInfo("Different number of variables, cannot add the grids");
426     return;
427   } 
428   if(aGrid->GetNDim()!=fNDim){
429     AliInfo("Different number of dimensions, cannot add the grids!");
430     return;
431   } 
432   
433   if(!fSumW2  && aGrid->GetSumW2())SumW2();
434
435
436   fData->Add(((AliCFGridSparse*)aGrid)->GetGrid(),c);
437
438 }
439
440 //____________________________________________________________________
441 void AliCFGridSparse::Add(AliCFVGrid* aGrid1, AliCFVGrid* aGrid2, Double_t c1,Double_t c2)
442 {
443   //
444   //Add aGrid1 and aGrid2 and deposit the result into the current one
445   //
446
447   if(fNVar!=aGrid1->GetNVar()|| fNVar!=aGrid2->GetNVar()){
448     AliInfo("Different number of variables, cannot add the grids");
449     return;
450   } 
451   if(fNDim!=aGrid1->GetNDim()|| fNDim!=aGrid2->GetNDim()){
452     AliInfo("Different number of dimensions, cannot add the grids!");
453     return;
454   } 
455   
456   if(!fSumW2  && (aGrid1->GetSumW2() || aGrid2->GetSumW2()))SumW2();
457
458
459   fData->Reset();
460   fData->Add(((AliCFGridSparse*)aGrid1)->GetGrid(),c1);
461   fData->Add(((AliCFGridSparse*)aGrid2)->GetGrid(),c2);
462
463 }
464
465 //____________________________________________________________________
466 void AliCFGridSparse::Multiply(AliCFVGrid* aGrid, Double_t c)
467 {
468   //
469   // Multiply aGrid to the current one
470   //
471
472
473   if(aGrid->GetNVar()!=fNVar){
474     AliInfo("Different number of variables, cannot multiply the grids");
475     return;
476   } 
477   if(aGrid->GetNDim()!=fNDim){
478     AliInfo("Different number of dimensions, cannot multiply the grids!");
479     return;
480   } 
481   
482   if(!fSumW2  && aGrid->GetSumW2())SumW2();
483
484   THnSparse *h= ((AliCFGridSparse*)aGrid)->GetGrid();
485
486   fData->Multiply(h);
487   fData->Scale(c);
488
489 }
490
491 //____________________________________________________________________
492 void AliCFGridSparse::Multiply(AliCFVGrid* aGrid1, AliCFVGrid* aGrid2, Double_t c1,Double_t c2)
493 {
494   //
495   //Multiply aGrid1 and aGrid2 and deposit the result into the current one
496   //
497
498   if(fNVar!=aGrid1->GetNVar()|| fNVar!=aGrid2->GetNVar()){
499     AliInfo("Different number of variables, cannot multiply the grids");
500     return;
501   } 
502   if(fNDim!=aGrid1->GetNDim()|| fNDim!=aGrid2->GetNDim()){
503     AliInfo("Different number of dimensions, cannot multiply the grids!");
504     return;
505   } 
506   
507   if(!fSumW2  && (aGrid1->GetSumW2() || aGrid2->GetSumW2()))SumW2();
508
509
510   fData->Reset();
511   THnSparse *h1= ((AliCFGridSparse*)aGrid1)->GetGrid();
512   THnSparse *h2= ((AliCFGridSparse*)aGrid2)->GetGrid();
513   h2->Multiply(h1);
514   h2->Scale(c1*c2);
515   fData->Add(h2);
516 }
517
518
519
520 //____________________________________________________________________
521 void AliCFGridSparse::Divide(AliCFVGrid* aGrid, Double_t c)
522 {
523   //
524   // Divide aGrid to the current one
525   //
526
527
528   if(aGrid->GetNVar()!=fNVar){
529     AliInfo("Different number of variables, cannot divide the grids");
530     return;
531   } 
532   if(aGrid->GetNDim()!=fNDim){
533     AliInfo("Different number of dimensions, cannot divide the grids!");
534     return;
535   } 
536   
537   if(!fSumW2  && aGrid->GetSumW2())SumW2();
538
539   THnSparse *h= ((AliCFGridSparse*)aGrid)->GetGrid();
540
541   fData->Divide(h);
542   fData->Scale(c);
543
544 }
545
546 //____________________________________________________________________
547 void AliCFGridSparse::Divide(AliCFVGrid* aGrid1, AliCFVGrid* aGrid2, Double_t c1,Double_t c2, Option_t *option)
548 {
549   //
550   //Divide aGrid1 and aGrid2 and deposit the result into the current one
551   //bynomial errors are supported
552   //
553
554   if(fNVar!=aGrid1->GetNVar()|| fNVar!=aGrid2->GetNVar()){
555     AliInfo("Different number of variables, cannot divide the grids");
556     return;
557   } 
558   if(fNDim!=aGrid1->GetNDim()|| fNDim!=aGrid2->GetNDim()){
559     AliInfo("Different number of dimensions, cannot divide the grids!");
560     return;
561   } 
562   
563   if(!fSumW2  && (aGrid1->GetSumW2() || aGrid2->GetSumW2()))SumW2();
564
565
566   THnSparse *h1= ((AliCFGridSparse*)aGrid1)->GetGrid();
567   THnSparse *h2= ((AliCFGridSparse*)aGrid2)->GetGrid();
568   fData->Divide(h1,h2,c1,c2,option);
569 }
570
571
572 //____________________________________________________________________
573 void AliCFGridSparse::Rebin(const Int_t* group)
574 {
575   //
576   // rebin the grid according to Rebin() as in THnSparse
577   // Please notice that the original number of bins on
578   // a given axis has to be divisible by the rebin group.
579   //
580
581   for(Int_t i=0;i<fNVar;i++){
582     if(group[i]!=1)AliInfo(Form(" merging bins along dimension %i in groups of %i bins", i,group[i]));
583   }
584
585   THnSparse *rebinned =fData->Rebin(group);
586   fData->Reset();
587   fData = rebinned;
588
589   //redefine the needed stuff
590
591   Int_t ndimTot=1;
592   Int_t nbinTot=0;
593
594   //number of bins in each dimension, auxiliary variables
595
596   for(Int_t ivar=0;ivar<fNVar;ivar++){
597     Int_t nbins = fData->GetAxis(ivar)->GetNbins();
598     fNVarBins[ivar]=nbins;
599     ndimTot*=fNVarBins[ivar];
600     nbinTot+=(fNVarBins[ivar]+1);
601     Int_t offset=0;
602     for(Int_t i =0;i<ivar;i++)offset+=(fNVarBins[i]+1);      
603     fOffset[ivar]=offset;
604     Int_t prod=1;
605     for(Int_t i=0;i<ivar;i++)prod*=fNVarBins[i];
606     fProduct[ivar]=prod;
607   }
608
609   fNDim=ndimTot;
610
611   //now the array of bin limits
612
613   delete fVarBinLimits;
614   fNVarBinLimits=nbinTot;
615   fVarBinLimits=new Double_t[fNVarBinLimits];
616
617   for(Int_t ivar=0;ivar<fNVar;ivar++){
618     Double_t low = fData->GetAxis(ivar)->GetXmin();
619     Double_t high = fData->GetAxis(ivar)->GetXmax();    
620     const TArrayD *xbins = fData->GetAxis(ivar)->GetXbins();
621     if (xbins->fN == 0){
622       for(Int_t ibin=0;ibin<=fNVarBins[ivar];ibin++){
623         fVarBinLimits[ibin+fOffset[ivar]] = low + ibin*(high-low)/((Double_t) fNVarBins[ivar]);
624       }
625     }
626     else{
627       
628       for(Int_t ibin=0;ibin<=fNVarBins[ivar];ibin++) {
629         fVarBinLimits[ibin+fOffset[ivar]] = xbins->At(ibin);
630       }
631     }
632   }   
633   
634 }
635 //____________________________________________________________________
636 void AliCFGridSparse::Copy(TObject& c) const
637 {
638   //
639   // copy function
640   //
641   AliCFGridSparse& target = (AliCFGridSparse &) c;
642
643   if(fData)target.fData = fData;
644 }
645
646 //____________________________________________________________________
647 TH1D* AliCFGridSparse::Slice(Int_t iVar, Double_t *varMin, Double_t *varMax) const
648 {
649   //
650   // return a slice (1D-projection) on variable iVar while axis ranges are defined with varMin,varMax
651   // arrays varMin and varMax contain the min and max values of each variable.
652   // therefore varMin and varMax must have their dimensions equal to fNVar
653   //
654   
655   THnSparse* clone = (THnSparse*)fData->Clone();
656   for (Int_t iAxis=0; iAxis<fNVar; iAxis++) {
657     clone->GetAxis(iAxis)->SetRangeUser(varMin[iAxis],varMax[iAxis]);
658   }
659   return clone->Projection(iVar);
660 }
661
662 //____________________________________________________________________
663 TH2D* AliCFGridSparse::Slice(Int_t iVar1, Int_t iVar2, Double_t *varMin, Double_t *varMax) const
664 {
665   //
666   // return a slice (2D-projection) on variables iVar1 and iVar2 while axis ranges are defined with varMin,varMax
667   // arrays varMin and varMax contain the min and max values of each variable.
668   // therefore varMin and varMax must have their dimensions equal to fNVar
669   //
670   
671   THnSparse* clone = (THnSparse*)fData->Clone();
672   for (Int_t iAxis=0; iAxis<fNVar; iAxis++) {
673     clone->GetAxis(iAxis)->SetRangeUser(varMin[iAxis],varMax[iAxis]);
674   }
675   return clone->Projection(iVar1,iVar2);
676 }
677
678 //____________________________________________________________________
679 TH3D* AliCFGridSparse::Slice(Int_t iVar1, Int_t iVar2, Int_t iVar3, Double_t *varMin, Double_t *varMax) const
680 {
681   //
682   // return a slice (3D-projection) on variables iVar1, iVar2 and iVar3 while axis ranges are defined with varMin,varMax
683   // arrays varMin and varMax contain the min and max values of each variable.
684   // therefore varMin and varMax must have their dimensions equal to fNVar
685   //
686
687   THnSparse* clone = (THnSparse*)fData->Clone();
688   for (Int_t iAxis=0; iAxis<fNVar; iAxis++) {
689     clone->GetAxis(iAxis)->SetRangeUser(varMin[iAxis],varMax[iAxis]);
690   }
691   return clone->Projection(iVar1,iVar2,iVar3);
692 }
693
694 //____________________________________________________________________
695 void AliCFGridSparse::SetRangeUser(Int_t iVar, Double_t varMin, Double_t varMax) {
696   //
697   // set range of axis iVar. 
698   //
699   fData->GetAxis(iVar)->SetRangeUser(varMin,varMax);
700   AliWarning(Form("THnSparse axis %d range has been modified",iVar));
701 }
702
703 //____________________________________________________________________
704 void AliCFGridSparse::SetRangeUser(Double_t *varMin, Double_t *varMax) {
705   //
706   // set range of every axis. varMin and varMax must be of dimension fNVar
707   //
708   for (Int_t iAxis=0; iAxis<fNVar ; iAxis++) { // set new range for every axis
709     SetRangeUser(iAxis,varMin[iAxis],varMax[iAxis]);
710   }
711   AliWarning("THnSparse axes ranges have been modified");
712 }
713
714 //____________________________________________________________________
715 void AliCFGridSparse::UseAxisRange(Bool_t b) const {
716   for (Int_t iAxis=0; iAxis<fNVar; iAxis++) fData->GetAxis(iAxis)->SetBit(TAxis::kAxisRange,b);
717 }