28f458148551659fc331e7206bdf6489d2fc5234
[u/mrichter/AliRoot.git] / PWG3 / dielectron / AliDielectronCFdraw.cxx
1 /*************************************************************************
2 * Copyright(c) 1998-2009, 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 /* $Id$ */
17
18 ///////////////////////////////////////////////////////////////////////////
19 //       Dielectron Correction framework draw helper                     //
20 //                                                                       //
21 /*
22
23
24
25
26
27
28
29
30
31 */
32 //                                                                       //
33 ///////////////////////////////////////////////////////////////////////////
34
35 #include <TSeqCollection.h>
36 #include <TObjArray.h>
37 #include <TKey.h>
38 #include <TList.h>
39 #include <TClass.h>
40 #include <TObject.h>
41 #include <TVirtualPS.h>
42 #include <TFile.h>
43 #include <TString.h>
44 #include <TObjString.h>
45 #include <TVectorD.h>
46 #include <TMath.h>
47 #include <TH1.h>
48 #include <TH2.h>
49 #include <TH3.h>
50 #include <TPad.h>
51 #include <TCanvas.h>
52 #include <TLegend.h>
53 #include <AliCFEffGrid.h>
54
55 #include <AliLog.h>
56
57 #include "AliDielectronCFdraw.h"
58
59 ClassImp(AliDielectronCFdraw)
60
61 AliDielectronCFdraw::AliDielectronCFdraw() :
62   TNamed(),
63   fCfContainer(0x0),
64   fEffGrid(0x0),
65   fVdata(0)
66 {
67   //
68   // Ctor
69   //
70 }
71
72 //________________________________________________________________
73 AliDielectronCFdraw::AliDielectronCFdraw(const char*name, const char* title) :
74   TNamed(name,title),
75   fCfContainer(0x0),
76   fEffGrid(0x0),
77   fVdata(0)
78 {
79   //
80   // Named Ctor
81   //
82   
83 }
84
85 //________________________________________________________________
86 AliDielectronCFdraw::AliDielectronCFdraw(AliCFContainer *cont) :
87   TNamed(cont->GetName(), cont->GetTitle()),
88   fCfContainer(cont),
89   fEffGrid(new AliCFEffGrid("eff","eff",*cont)),
90   fVdata(0)
91 {
92   //
93   // directly set the CF container
94   //
95
96 }
97
98 //________________________________________________________________
99 AliDielectronCFdraw::AliDielectronCFdraw(const char* filename) :
100   TNamed(),
101   fCfContainer(0x0),
102   fEffGrid(0x0),
103   fVdata(0)
104 {
105   //
106   // get CF container(s) from file 'filename'
107   //
108   SetCFContainers(filename);
109 }
110
111 //________________________________________________________________
112 void AliDielectronCFdraw::SetCFContainers(const TSeqCollection *arr)
113 {
114   //
115   // Merge CF Container out of several containers
116   //
117
118   TIter next(arr);
119   TObject *o=0x0;
120
121   Int_t nstep=0;
122   while ( (o=next()) ){
123     AliCFContainer *cf=dynamic_cast<AliCFContainer*>(o);
124     if (!cf) continue;
125     nstep+=cf->GetNStep();
126   }
127   if (nstep==0) return;
128   Int_t nbins[1]={1};
129   fCfContainer=new AliCFContainer(GetName(), GetTitle(), nstep, 1, nbins);
130
131   //delete unneeded steps
132 //   for (Int_t istep=0; istep<nstep; ++istep) delete fCfContainer->GetGrid(istep);
133
134   //add step to the new container
135   Int_t istep=0;
136   for (Int_t icf=0; icf<arr->GetEntries(); ++icf){
137     AliCFContainer *cf=dynamic_cast<AliCFContainer*>(arr->At(icf));
138     if (!cf) continue;
139     for (Int_t istepCurr=0; istepCurr<cf->GetNStep(); ++istepCurr){
140       fCfContainer->SetGrid(istep, cf->GetGrid(istepCurr));
141       fCfContainer->SetStepTitle(istep,Form("%s, Pair: %s",cf->GetTitle(),cf->GetStepTitle(istepCurr)));
142       ++istep;
143     }
144   }
145   if (fEffGrid) delete fEffGrid;
146   fEffGrid=new AliCFEffGrid("eff","eff",*fCfContainer);
147 }
148
149 //________________________________________________________________
150 void AliDielectronCFdraw::SetCFContainers(const char* filename)
151 {
152   //
153   // get CF containers from file
154   //
155
156   TFile f(filename);
157   TList *l=f.GetListOfKeys();
158   TIter nextKey(l);
159   TKey *k=0x0;
160   while ( (k=static_cast<TKey*>(nextKey())) ){
161     TObject *o=k->ReadObj();
162     if (o->IsA()->InheritsFrom(TSeqCollection::Class())){
163       TSeqCollection *arr=static_cast<TSeqCollection*>(o);
164       SetCFContainers(arr);
165     } else if (o->IsA()==AliCFContainer::Class()){
166       fCfContainer=static_cast<AliCFContainer*>(o);
167       if (fEffGrid) delete fEffGrid;
168       fEffGrid=new AliCFEffGrid("eff","eff",*fCfContainer);
169     }
170   }
171 }
172
173 //________________________________________________________________
174 void AliDielectronCFdraw::SetRangeUser(Int_t ivar, Double_t min, Double_t max, const char* slices)
175 {
176   //
177   // Set range of cut steps defined in slices
178   // Steps may be separated by one the the characteres ,;:
179   //
180   TObjArray *arr=TString(slices).Tokenize(",:;");
181
182   if (arr->GetEntriesFast()==0){
183     // all slices in case of 0 entries
184     for (Int_t istep=0; istep<fCfContainer->GetNStep(); ++istep){
185       fCfContainer->GetGrid(istep)->SetRangeUser(ivar,min,max);
186     }
187   } else {
188     TIter next(arr);
189     TObjString *ostr=0x0;
190     while ( (ostr=static_cast<TObjString*>(next())) ) {
191       Int_t istep=ostr->GetString().Atoi();
192       fCfContainer->GetGrid(istep)->SetRangeUser(ivar,min,max);
193     }
194   }
195   delete arr;
196 }
197
198 //________________________________________________________________
199 void AliDielectronCFdraw::UnsetRangeUser(Int_t ivar, const char* slices)
200 {
201   //
202   // Unset range of cut steps defined in slices
203   // Steps may be separated by one the the characteres ,;:
204   //
205   TObjArray *arr=TString(slices).Tokenize(",:;");
206   
207   if (arr->GetEntriesFast()==0){
208     // all slices in case of 0 entries
209     for (Int_t istep=0; istep<fCfContainer->GetNStep(); ++istep){
210       fCfContainer->GetAxis(ivar,istep)->SetRange(0,0);
211     }
212   } else {
213     TIter next(arr);
214     TObjString *ostr=0x0;
215     while ( (ostr=static_cast<TObjString*>(next())) ) {
216       Int_t istep=ostr->GetString().Atoi();
217       fCfContainer->GetAxis(ivar,istep)->SetRange(0,0);
218     }
219   }
220   delete arr;
221 }
222
223 //________________________________________________________________
224 void AliDielectronCFdraw::Draw(const Option_t* varnames, const char* opt, const char* slices)
225 {
226   //
227   // Draw 'variables' of 'slices'
228   // for multidimensional draw variables may be separated by a ':'
229   // slice numbers may be separated by any of ,:;
230   //
231   // variables may be called by either their name or number
232   //
233
234   TObjArray *arrVars=TString(varnames).Tokenize(":");
235   Int_t entries=arrVars->GetEntriesFast();
236   if (entries<1||entries>3){
237     AliError("Wrong number of variables, supported are 1 - 3 dimensions");
238     delete arrVars;
239     return;
240   }
241   
242   TIter next(arrVars);
243   TObjString *ostr=0x0;
244   Int_t ivar[3]={-1,-1,-1};
245   for (Int_t i=entries-1; i>=0; --i){
246     ostr=static_cast<TObjString*>(next());
247     if (ostr->GetString().IsDigit()){
248       ivar[i]=ostr->GetString().Atoi();
249     } else {
250       ivar[i]=fCfContainer->GetVar(ostr->GetName());
251     }
252   }
253
254   Draw(ivar[0],ivar[1],ivar[2],opt,slices);
255   delete arrVars;
256 }
257
258 //________________________________________________________________
259 void AliDielectronCFdraw::Draw(Int_t var, const char* opt, const char* slices)
260 {
261   //
262   // Draw variable var for all slices
263   // slices may be divided by and of ,;:
264   //
265   // if opt contains 'same' all histograms are drawn in the same pad
266   // otherwise the pad will be divided in sub pads and the histograms
267   // are drawn in each sub pad
268   //
269
270   Int_t vars[3]={var,-1,-1};
271   TObjArray *arr=CollectHistosProj(vars,slices);
272   Draw(arr,opt);
273   delete arr; 
274 }
275
276 //________________________________________________________________
277 void AliDielectronCFdraw::Draw(Int_t var0, Int_t var1, const char* opt, const char* slices)
278 {
279   //
280   // Draw 2D case
281   //
282   Int_t vars[3]={var0,var1,-1};
283   TObjArray *arr=CollectHistosProj(vars,slices);
284   Draw(arr,opt);
285   delete arr;
286 }
287
288 //________________________________________________________________
289 void AliDielectronCFdraw::Draw(Int_t var0, Int_t var1, Int_t var2, const char* opt, const char* slices)
290 {
291   //
292   // Draw 3D case
293   //
294   Int_t vars[3]={var0,var1,var2};
295   TObjArray *arr=CollectHistosProj(vars,slices);
296   Draw(arr,opt);
297   delete arr;
298 }
299
300 //________________________________________________________________
301 TObjArray* AliDielectronCFdraw::CollectHistosProj(const Int_t vars[3], const char* slices)
302 {
303   //
304   // Collect histos with up to 3 dimension of the 'slices' separated by one of "':;'"
305   // in a TObjArray and return it
306   // if a dimension is not used it must be set to -1
307   //
308   TObjArray *arr=TString(slices).Tokenize(",:;");
309   TObjArray *arrHists=0x0;
310   if (arr->GetEntriesFast()==0){
311     // all slices in case of 0 entries
312     arrHists=new TObjArray(fCfContainer->GetNStep());
313     for (Int_t istep=0; istep<fCfContainer->GetNStep(); ++istep){
314       TH1 *hproj=Project(vars,istep);
315       if (!hproj) continue;
316       hproj->SetName(Form("proj_%02d",istep));
317       hproj->SetTitle(fCfContainer->GetStepTitle(istep));
318       arrHists->Add(hproj);
319     }
320   } else {
321     arrHists=new TObjArray(arr->GetEntriesFast());
322     TIter next(arr);
323     TObjString *ostr=0x0;
324     while ( (ostr=static_cast<TObjString*>(next())) ) {
325       Int_t istep=ostr->GetString().Atoi();
326       TH1 *hproj=Project(vars,istep);
327       if (!hproj) continue;
328       hproj->SetName(Form("proj_%02d",istep));
329       hproj->SetTitle(fCfContainer->GetStepTitle(istep));
330       arrHists->Add(hproj);
331     }
332   }
333   delete arr;
334
335   return arrHists;
336 }
337
338 //________________________________________________________________
339 TH1* AliDielectronCFdraw::Project(const Int_t *vars, Int_t slice)
340 {
341   //
342   // Do an ndim projection
343   //
344   return fCfContainer->Project(slice,vars[0],vars[1],vars[2]);
345 }
346
347 //________________________________________________________________
348 TH1* AliDielectronCFdraw::Project(const Option_t* var, Int_t slice)
349 {
350   //
351   // translate variable names and do projection
352   //
353   TObjArray *arrVars=TString(var).Tokenize(":");
354   Int_t entries=arrVars->GetEntriesFast();
355   if (entries<1||entries>3){
356     AliError("Wrong number of variables, supported are 1 - 3 dimensions");
357     delete arrVars;
358     return 0x0;
359   }
360   
361   TObjString *ostr=0x0;
362   Int_t ivar[3]={-1,-1,-1};
363   for (Int_t i=entries-1; i>=0; --i){
364     ostr=static_cast<TObjString*>(arrVars->At(i));
365     if (ostr->GetString().IsDigit()){
366       ivar[i]=ostr->GetString().Atoi();
367     } else {
368       ivar[i]=fCfContainer->GetVar(ostr->GetName());
369     }
370   }
371   if (ivar[0]==-1) return 0x0;
372   delete arrVars;
373   return fCfContainer->Project(slice,ivar[0],ivar[1],ivar[2]);
374 }
375
376 //________________________________________________________________
377 void AliDielectronCFdraw::DrawEfficiency(const char* varnames, const char* numerators, Int_t denominator, const char* opt)
378 {
379   //
380   // plot efficiencies for variables. Variable may be up to 3 dim, separated by a ':'
381   // you may have several numerators, sparated by one of ',:;'
382   //
383   
384   TObjArray *arrVars=TString(varnames).Tokenize(":");
385   Int_t entries=arrVars->GetEntriesFast();
386   if (entries<1||entries>3){
387     AliError("Wrong number of variables, supported are 1 - 3 dimensions");
388     delete arrVars;
389     return;
390   }
391   
392   TIter next(arrVars);
393   TObjString *ostr=0x0;
394   Int_t ivar[3]={-1,-1,-1};
395   for (Int_t i=0; i<entries; ++i){
396     ostr=static_cast<TObjString*>(next());
397     if (ostr->GetString().IsDigit()){
398       ivar[i]=ostr->GetString().Atoi();
399     } else {
400       ivar[i]=fCfContainer->GetVar(ostr->GetName());
401     }
402   }
403
404   Int_t type=0;
405   TString optStr(opt);
406   if (optStr.Contains("2")) type=1;
407   
408   DrawEfficiency(ivar[2],ivar[1],ivar[0],numerators, denominator,opt,type);
409   delete arrVars;
410 }
411
412 //________________________________________________________________
413 void AliDielectronCFdraw::DrawEfficiency(Int_t var, const char* numerators, Int_t denominator, const char* opt, Int_t type)
414 {
415   //
416   // Draw Efficiencies for all numerators
417   // numerators may be divided by and of ,;:
418   //
419   // if opt contains 'same' all histograms are drawn in the same pad
420   // otherwise the pad will be divided in sub pads and the histograms
421   // are drawn in each sub pad
422   //
423   
424   Int_t vars[3]={var,-1,-1};
425   TObjArray *arr=CollectHistosEff(vars,numerators,denominator,type);
426   TString drawOpt=opt;
427   drawOpt+="eff";
428   Draw(arr,drawOpt);
429   delete arr;
430 }
431
432 //________________________________________________________________
433 void AliDielectronCFdraw::DrawEfficiency(Int_t var0, Int_t var1, const char* numerators, Int_t denominator, const char* opt, Int_t type)
434 {
435   //
436   // Draw 2D case
437   //
438   Int_t vars[3]={var0,var1,-1};
439   TObjArray *arr=CollectHistosEff(vars,numerators,denominator,type);
440   TString drawOpt=opt;
441   drawOpt+="eff";
442   Draw(arr,drawOpt);
443   delete arr;
444 }
445
446 //________________________________________________________________
447 void AliDielectronCFdraw::DrawEfficiency(Int_t var0, Int_t var1, Int_t var2, const char* numerators, Int_t denominator, const char* opt, Int_t type)
448 {
449   //
450   // Draw 3D case
451   //
452   Int_t vars[3]={var0,var1,var2};
453   TObjArray *arr=CollectHistosEff(vars,numerators,denominator,type);
454   TString drawOpt=opt;
455   drawOpt+="eff";
456   Draw(arr,drawOpt);
457   delete arr;
458 }
459
460 //________________________________________________________________
461 TObjArray* AliDielectronCFdraw::CollectHistosEff(const  Int_t vars[3], const char* numerators, Int_t denominator, Int_t type)
462 {
463   //
464   // Collect histos with 'dim'ension of the 'slices' separated by one of "':;'"
465   // in a TObjArray and return it
466   //
467   TObjArray *arr=TString(numerators).Tokenize(",:;");
468   TObjArray *arrHists=0x0;
469
470   if (type==0){
471     if (arr->GetEntriesFast()==0){
472     // all slices in case of 0 entries
473       arrHists=new TObjArray(fCfContainer->GetNStep());
474       fVdata.ResizeTo(arrHists->GetSize());
475       for (Int_t istep=0; istep<fCfContainer->GetNStep(); ++istep){
476         fEffGrid->CalculateEfficiency(istep,denominator);
477         TH1 *hproj=ProjectEff(vars);
478         if (!hproj) continue;
479         Float_t eff=fEffGrid->GetAverage();
480         fVdata(istep)=eff;
481         hproj->SetName(Form("eff_%02d/%02d",istep,denominator));
482         hproj->SetTitle(Form("%s (%.3f)",fCfContainer->GetStepTitle(istep),eff));
483         arrHists->Add(hproj);
484       }
485     } else {
486       arrHists=new TObjArray(arr->GetEntriesFast());
487       TIter next(arr);
488       TObjString *ostr=0x0;
489       fVdata.ResizeTo(arrHists->GetSize());
490       Int_t count=0;
491       while ( (ostr=static_cast<TObjString*>(next())) ) {
492         Int_t istep=ostr->GetString().Atoi();
493         fEffGrid->CalculateEfficiency(istep,denominator);
494         TH1 *hproj=ProjectEff(vars);
495         if (!hproj) continue;
496         Float_t eff=fEffGrid->GetAverage();
497         fVdata(count++)=eff;
498         hproj->SetName(Form("eff_%02d/%02d",istep,denominator));
499         hproj->SetTitle(Form("%s (%.3f)",fCfContainer->GetStepTitle(istep),eff));
500         arrHists->Add(hproj);
501       }
502     }
503   }
504
505   //second approach
506   if (type==1){
507     TH1 *hDen=Project(vars,denominator);
508     Double_t entriesDen=hDen->GetEffectiveEntries();
509     if (arr->GetEntriesFast()==0){
510     // all slices in case of 0 entries
511       arrHists=new TObjArray(fCfContainer->GetNStep());
512       fVdata.ResizeTo(arrHists->GetSize());
513       for (Int_t istep=0; istep<fCfContainer->GetNStep(); ++istep){
514         TH1 *hproj=Project(vars,istep);
515         if (!hproj) continue;
516         Float_t eff=0;
517         if (entriesDen>0) eff=hproj->GetEffectiveEntries()/entriesDen;
518         fVdata(istep)=eff;
519         hproj->Divide(hproj,hDen,1,1,"B");
520         hproj->SetName(Form("eff_%02d/%02d",istep,denominator));
521         hproj->SetTitle(Form("%s (%.3f)",fCfContainer->GetStepTitle(istep),eff));
522         arrHists->Add(hproj);
523       }
524     } else {
525       arrHists=new TObjArray(arr->GetEntriesFast());
526       fVdata.ResizeTo(arrHists->GetSize());
527       TIter next(arr);
528       TObjString *ostr=0x0;
529       Int_t count=0;
530       while ( (ostr=static_cast<TObjString*>(next())) ) {
531         Int_t istep=ostr->GetString().Atoi();
532         TH1 *hproj=Project(vars,istep);
533         if (!hproj) continue;
534         Float_t eff=0;
535         if (entriesDen>0) eff=hproj->GetEffectiveEntries()/entriesDen;
536         fVdata(count++)=eff;
537         hproj->Divide(hproj,hDen,1,1,"B");
538         hproj->SetName(Form("eff_%02d/%02d",istep,denominator));
539         hproj->SetTitle(Form("%s (%.3f)",fCfContainer->GetStepTitle(istep),eff));
540         arrHists->Add(hproj);
541       }
542     }
543     delete hDen;
544   }
545   
546
547   delete arr;
548   return arrHists;
549 }
550
551 //________________________________________________________________
552 TH1* AliDielectronCFdraw::ProjectEff(const Int_t vars[3])
553 {
554   //
555   // Do an nim projection
556   //
557   return fEffGrid->Project(vars[0],vars[1],vars[2]);
558 }
559
560 //________________________________________________________________
561 void AliDielectronCFdraw::Draw(const TObjArray *arr, const char* opt)
562 {
563   //
564   // draw all objects in arr
565   //
566   TString optStr(opt);
567   optStr.ToLower();
568   Bool_t drawSame     = optStr.Contains("same");
569   Bool_t drawSamePlus = optStr.Contains("same+");
570   Bool_t drawEff      = optStr.Contains("eff");
571   Bool_t optLeg       = optStr.Contains("leg");
572   Bool_t optScaleMax  = optStr.Contains("max");
573   
574   if (!drawSamePlus) optStr.ReplaceAll("same","");
575   
576   optStr.ReplaceAll("+","");
577   optStr.ReplaceAll("eff","");
578   optStr.ReplaceAll("leg","");
579   optStr.ReplaceAll("max","");
580   
581   if (!gPad) new TCanvas;
582   
583   Int_t nPads = arr->GetEntriesFast();
584   if (nPads==0) return;
585   
586 //   if (nPads==1){
587 //     arr->UncheckedAt(0)->Draw(optStr.Data());
588 //     return;
589 //   }
590   
591   TCanvas *c=gPad->GetCanvas();
592   if (!gVirtualPS&&!drawSamePlus&&!drawSame&&nPads>1) c->Clear();
593   
594   if (!drawSame&&nPads>1){
595     //optimised division
596     Int_t nCols = (Int_t)TMath::Ceil( TMath::Sqrt(nPads) );
597     Int_t nRows = (Int_t)TMath::Ceil( (Double_t)nPads/(Double_t)nCols );
598     c->Divide(nCols,nRows);
599     for (Int_t i=0; i<nPads; ++i){
600       c->cd(i+1);
601       arr->UncheckedAt(i)->Draw(optStr.Data());
602     }
603   } else {
604     TLegend *leg=0;
605     if (drawSamePlus){
606       //find already existing legend to attach entries to it
607       TIter nextPrimitive(gPad->GetListOfPrimitives());
608       TObject *o=0x0;
609       while ((o=nextPrimitive())) if (o->IsA()==TLegend::Class()) leg=(TLegend*)o;
610     }
611     
612     if (optLeg&&!leg) leg=new TLegend(.2,.3,.99,.9);
613     Int_t addColor=0;
614     if (leg) addColor=leg->GetNRows();
615     Int_t offset=20;
616     if (nPads<7) offset=24;
617     for (Int_t i=0; i<nPads; ++i){
618       if (i==1&&!drawSamePlus) optStr+="same";
619       TH1 *hist=static_cast<TH1*>(arr->UncheckedAt(i));
620       hist->SetLineColor(i+1+addColor);
621       hist->SetLineWidth(2);
622       hist->SetMarkerColor(i+1+addColor);
623       hist->SetMarkerStyle(offset+i+addColor);
624       hist->Draw(optStr.Data());
625       
626       if (drawEff&&i==0&&!drawSamePlus) {
627         hist->GetYaxis()->SetRangeUser(0,2);
628         hist->SetYTitle("Rec. Signal / Gen. Signal");
629       }
630       
631       if (leg) leg->AddEntry(hist,hist->GetTitle(),"lp");
632     }
633     if (leg){
634       leg->SetFillColor(10);
635       leg->SetY1(.9-leg->GetNRows()*.05);
636       leg->SetY1NDC(.9-leg->GetNRows()*.05);
637       leg->SetMargin(.1);
638       if (!drawSamePlus) leg->Draw();
639     }
640     if (optScaleMax){
641       TIter nextPrimitive(gPad->GetListOfPrimitives());
642       TObject *o=0x0;
643       TH1 *hfirst=0x0;
644       Float_t max=0;
645       while ((o=nextPrimitive())) if (o->InheritsFrom(TH1::Class())){
646         TH1 *h=(TH1*)o;
647         if (!hfirst) hfirst=h;
648         if (h->GetMaximum()>max) max=h->GetMaximum();
649       }
650       max*=1.1;
651       hfirst->SetMaximum(max);
652     }
653   }
654   
655 }
656
657 //________________________________________________________________
658 Double_t AliDielectronCFdraw::GetAverageEfficiency(Int_t numerator, Int_t denominator, Double_t &effErr)
659 {
660   //
661   // Extract the mean efficiency of the numerator and denominator
662   //
663
664   //use variable 0 as default, since for the average it doesn't matter
665   TH1 *hDen=fCfContainer->Project(denominator,0);
666   Double_t entriesDen=hDen->GetEffectiveEntries();
667   TH1 *hproj=fCfContainer->Project(numerator,0);
668   if (!hproj) return -1.;
669   Double_t entriesNum=hproj->GetEffectiveEntries();
670   if (entriesDen<1||entriesNum<1) return -1;
671   
672   Double_t eff=-1.;
673   if (entriesDen>0) eff=entriesNum/entriesDen;
674   effErr=TMath::Sqrt(1./entriesNum+1./entriesDen)*eff;
675   delete hDen;
676   delete hproj;
677   return eff;
678 }