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