]> git.uio.no Git - u/mrichter/AliRoot.git/blob - PWGDQ/dielectron/AliDielectronCFdraw.cxx
ALIROOT-5488 Remove build/include from the include directories
[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 #include "AliDielectronVarManager.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 AliDielectronCFdraw::~AliDielectronCFdraw()
113 {
114   //
115   // dtor
116   //
117   delete fCfContainer;
118   delete fEffGrid;
119 }
120
121 //________________________________________________________________
122 void AliDielectronCFdraw::SetCFContainers(const TSeqCollection *arr)
123 {
124   //
125   // Merge CF Container out of several containers
126   //
127
128   delete fCfContainer; fCfContainer=0x0;
129   delete fEffGrid; fEffGrid=0x0;
130   TIter next(arr);
131   TObject *o=0x0;
132
133   Int_t nstep=0;
134   while ( (o=next()) ){
135     AliCFContainer *cf=dynamic_cast<AliCFContainer*>(o);
136     if (!cf) continue;
137     nstep+=cf->GetNStep();
138   }
139   if (nstep==0) return;
140   Int_t nbins[1]={1};
141   fCfContainer=new AliCFContainer(GetName(), GetTitle(), nstep, 1, nbins);
142
143   //delete unneeded steps
144 //   for (Int_t istep=0; istep<nstep; ++istep) delete fCfContainer->GetGrid(istep);
145
146   //add step to the new container
147   Int_t istep=0;
148   for (Int_t icf=0; icf<arr->GetEntries(); ++icf){
149     AliCFContainer *cf=dynamic_cast<AliCFContainer*>(arr->At(icf));
150     if (!cf) continue;
151     for (Int_t istepCurr=0; istepCurr<cf->GetNStep(); ++istepCurr){
152       fCfContainer->SetGrid(istep, cf->GetGrid(istepCurr));
153       fCfContainer->SetStepTitle(istep,Form("%s, Pair: %s",cf->GetTitle(),cf->GetStepTitle(istepCurr)));
154       ++istep;
155     }
156   }
157   if (fEffGrid) delete fEffGrid;
158   fEffGrid=new AliCFEffGrid("eff","eff",*fCfContainer);
159 }
160
161 //________________________________________________________________
162 void AliDielectronCFdraw::SetCFContainers(const char* filename)
163 {
164   //
165   // get CF containers from file
166   //
167
168   TFile f(filename);
169   TList *l=f.GetListOfKeys();
170   TIter nextKey(l);
171   TKey *k=0x0;
172   while ( (k=static_cast<TKey*>(nextKey())) ){
173     TObject *o=k->ReadObj();
174     if (o->IsA()->InheritsFrom(TSeqCollection::Class())){
175       TSeqCollection *arr=static_cast<TSeqCollection*>(o);
176       SetCFContainers(arr);
177     } else if (o->IsA()==AliCFContainer::Class()){
178       fCfContainer=static_cast<AliCFContainer*>(o);
179       if (fEffGrid) delete fEffGrid;
180       fEffGrid=new AliCFEffGrid("eff","eff",*fCfContainer);
181     }
182   }
183 }
184
185 //________________________________________________________________
186 void AliDielectronCFdraw::SetRangeUser(Int_t ivar, Double_t min, Double_t max, const char* slices)
187 {
188   //
189   // Set range of cut steps defined in slices
190   // Steps may be separated by one the the characteres ,;:
191   //
192   if (ivar==-1) return;
193   TObjArray *arr=TString(slices).Tokenize(",:;");
194
195   //Changes in root TAxis r48279
196   //it doesn't work any longer to give the same min and max in SetRangeUser
197   //the lines below fix this
198
199   TAxis *a = fCfContainer->GetAxis(ivar,0);
200   if (a) {
201     const Int_t bin=a->FindBin(min);
202     const Double_t binw=a->GetBinWidth(bin);
203     if (TMath::Abs(max-min)<binw*0.001){
204       max+=binw*0.001;
205     }
206   }
207
208   if (arr->GetEntriesFast()==0){
209     // all slices in case of 0 entries
210     for (Int_t istep=0; istep<fCfContainer->GetNStep(); ++istep){
211       fCfContainer->GetGrid(istep)->SetRangeUser(ivar,min,max);
212       fCfContainer->GetAxis(ivar,istep)->SetBit(TAxis::kAxisRange,1);
213     }
214   } else {
215     TIter next(arr);
216     TObjString *ostr=0x0;
217     while ( (ostr=static_cast<TObjString*>(next())) ) {
218       Int_t istep=ostr->GetString().Atoi();
219       fCfContainer->GetGrid(istep)->SetRangeUser(ivar,min,max);
220       fCfContainer->GetAxis(ivar,istep)->SetBit(TAxis::kAxisRange,1);
221     }
222   }
223   delete arr;
224 }
225
226 //________________________________________________________________
227 void AliDielectronCFdraw::SetRangeUser(AliDielectronVarManager::ValueTypes type, Double_t min, Double_t max, const char* slices, Bool_t leg)
228 {
229   //
230   // Set range of cut steps defined in slices
231   // Steps may be separated by one the the characteres ,;:
232   //
233   SetRangeUser(Form("%s%s",(leg?"Leg1_":""),AliDielectronVarManager::GetValueName(type)), min, max, slices);
234   if(leg) SetRangeUser(Form("%s%s","Leg2_",AliDielectronVarManager::GetValueName(type)), min, max, slices);
235
236 }
237
238 //________________________________________________________________
239 void AliDielectronCFdraw::SetRangeUser(const char* varname, Double_t min, Double_t max, const char* slices)
240 {
241   //
242   // Set range from variable name
243   //
244   Int_t ivar=fCfContainer->GetVar(varname);
245   if (ivar==-1){
246     AliFatal(Form("Variable '%s' not found",varname));
247     return;
248   }
249   SetRangeUser(ivar,min,max,slices);
250 }
251
252 //________________________________________________________________
253 void AliDielectronCFdraw::UnsetRangeUser(const char* varname, const char* slices)
254 {
255   //
256   // Unset range from variable name
257   //
258   Int_t ivar=fCfContainer->GetVar(varname);
259   if (ivar==-1){
260     AliFatal(Form("Variable '%s' not found",varname));
261     return;
262   }
263   UnsetRangeUser(ivar,slices);
264 }
265
266 //________________________________________________________________
267 void AliDielectronCFdraw::UnsetRangeUser(AliDielectronVarManager::ValueTypes type, const char* slices, Bool_t leg)
268 {
269   //
270   // Unset range of cut steps defined in slices
271   // Steps may be separated by one the the characteres ,;:
272   //
273   UnsetRangeUser(Form("%s%s",(leg?"Leg1_":""),AliDielectronVarManager::GetValueName(type)), slices);
274   UnsetRangeUser(Form("%s%s",(leg?"Leg2_":""),AliDielectronVarManager::GetValueName(type)), slices);
275 }
276
277 //________________________________________________________________
278 void AliDielectronCFdraw::UnsetRangeUser(Int_t ivar, const char* slices)
279 {
280   //
281   // Unset range of cut steps defined in slices
282   // Steps may be separated by one the the characteres ,;:
283   //
284   if (ivar==-1) return;
285   TObjArray *arr=TString(slices).Tokenize(",:;");
286   
287   if (arr->GetEntriesFast()==0){
288     // all slices in case of 0 entries
289     for (Int_t istep=0; istep<fCfContainer->GetNStep(); ++istep){
290       fCfContainer->GetAxis(ivar,istep)->SetRange(0,0);
291       fCfContainer->GetAxis(ivar,istep)->SetBit(TAxis::kAxisRange,0);
292     }
293   } else {
294     TIter next(arr);
295     TObjString *ostr=0x0;
296     while ( (ostr=static_cast<TObjString*>(next())) ) {
297       Int_t istep=ostr->GetString().Atoi();
298       fCfContainer->GetAxis(ivar,istep)->SetRange(0,0);
299       fCfContainer->GetAxis(ivar,istep)->SetBit(TAxis::kAxisRange,0);
300     }
301   }
302   delete arr;
303 }
304
305 //________________________________________________________________
306 void AliDielectronCFdraw::Draw(const Option_t* varnames, const char* opt, const char* slices)
307 {
308   //
309   // Draw 'variables' of 'slices'
310   // for multidimensional draw variables may be separated by a ':'
311   // slice numbers may be separated by any of ,:;
312   //
313   // variables may be called by either their name or number
314   //
315
316   TObjArray *arrVars=TString(varnames).Tokenize(":");
317   Int_t entries=arrVars->GetEntriesFast();
318   if (entries<1||entries>3){
319     AliError("Wrong number of variables, supported are 1 - 3 dimensions");
320     delete arrVars;
321     return;
322   }
323   
324   TIter next(arrVars);
325   TObjString *ostr=0x0;
326   Int_t ivar[3]={-1,-1,-1};
327   for (Int_t i=entries-1; i>=0; --i){
328     ostr=static_cast<TObjString*>(next());
329     if (ostr->GetString().IsDigit()){
330       ivar[i]=ostr->GetString().Atoi();
331     } else {
332       ivar[i]=fCfContainer->GetVar(ostr->GetName());
333     }
334   }
335
336   Draw(ivar[0],ivar[1],ivar[2],opt,slices);
337   delete arrVars;
338 }
339
340 //________________________________________________________________
341 TString AliDielectronCFdraw::FindSteps(const char* search)
342 {
343   //
344   // find steps/slices containg search string
345   // search strings may be separated by any of ,:;
346   //
347   TObjArray *arr=TString(search).Tokenize(",:;");
348   TIter next(arr);
349   TObjString *ostr=0x0;
350
351   TString slices="";
352   Int_t nfnd=0;
353   // loop over all steps
354   for (Int_t istep=0; istep<fCfContainer->GetNStep(); ++istep){
355     TString steptit = fCfContainer->GetStepTitle(istep);
356     Bool_t bfnd=kFALSE;
357     next.Reset();
358     // loop over all search strings
359     while ( (ostr=static_cast<TObjString*>(next())) ) {
360       if( steptit.Contains(ostr->GetName()) ) bfnd=kTRUE;
361       else {
362         bfnd=kFALSE;
363         break;
364       }
365     }
366     // append found slices string
367     if(bfnd) {
368       if(nfnd)
369         slices.Append(Form(":%d",istep));
370       else
371         slices.Append(Form("%d", istep));
372       nfnd++;
373     }
374   }
375   delete arr;
376
377   if(!nfnd) AliWarning(" No step searched for found. returning all steps!");
378   return slices;
379 }
380 //________________________________________________________________
381 Int_t AliDielectronCFdraw::FindStep(const char* search)
382 {
383   //
384   // find first step/slice containg search string
385   // search strings may be separated by any of ,:;
386   //
387   TObjArray *arr=TString(search).Tokenize(",:;");
388   TIter next(arr);
389   TObjString *ostr=0x0;
390
391   // loop over all steps
392   for (Int_t istep=0; istep<fCfContainer->GetNStep(); ++istep){
393     TString steptit = fCfContainer->GetStepTitle(istep);
394     Bool_t bfnd=kFALSE;
395     next.Reset();
396     // loop over all search strings
397     while ( (ostr=static_cast<TObjString*>(next())) ) {
398       if( steptit.Contains(ostr->GetName()) ) bfnd=kTRUE;
399       else {
400         bfnd=kFALSE;
401         break;
402       }
403     }
404     // return found slice/step
405     if(bfnd) {
406       delete arr;
407       return istep;
408     }
409   }
410
411   AliError(" No step searched for found. returning -1!");
412   delete arr;
413   return -1;
414
415 }
416 //________________________________________________________________
417 TObjArray* AliDielectronCFdraw::CollectHistosProj(const Option_t* varnames, const char* slices)
418 {
419   //
420   // Collect histos with 'variables' of 'slices'
421   // for multidimensional histograms, variables may be separated by a ':'
422   // slice numbers may be separated by any of ,:;
423   //
424   // variables may be called by either their name or number
425   //
426   
427   TObjArray *arrVars=TString(varnames).Tokenize(":");
428   Int_t entries=arrVars->GetEntriesFast();
429   if (entries<1||entries>3){
430     AliError("Wrong number of variables, supported are 1 - 3 dimensions");
431     delete arrVars;
432     return 0x0;
433   }
434   
435   TIter next(arrVars);
436   TObjString *ostr=0x0;
437   Int_t ivar[3]={-1,-1,-1};
438   for (Int_t i=entries-1; i>=0; --i){
439     ostr=static_cast<TObjString*>(next());
440     if (ostr->GetString().IsDigit()){
441       ivar[i]=ostr->GetString().Atoi();
442     } else {
443       ivar[i]=fCfContainer->GetVar(ostr->GetName());
444     }
445   }
446   delete arrVars;
447   
448   return CollectHistosProj(ivar,slices);
449 }
450
451 //________________________________________________________________
452 void AliDielectronCFdraw::Draw(Int_t var, const char* opt, const char* slices)
453 {
454   //
455   // Draw variable var for all slices
456   // slices may be divided by and of ,;:
457   //
458   // if opt contains 'same' all histograms are drawn in the same pad
459   // otherwise the pad will be divided in sub pads and the histograms
460   // are drawn in each sub pad
461   //
462
463   Int_t vars[3]={var,-1,-1};
464   TObjArray *arr=CollectHistosProj(vars,slices);
465   Draw(arr,opt);
466   delete arr; 
467 }
468
469 //________________________________________________________________
470 void AliDielectronCFdraw::Draw(Int_t var0, Int_t var1, const char* opt, const char* slices)
471 {
472   //
473   // Draw 2D case
474   //
475   Int_t vars[3]={var0,var1,-1};
476   TObjArray *arr=CollectHistosProj(vars,slices);
477   Draw(arr,opt);
478   delete arr;
479 }
480
481 //________________________________________________________________
482 void AliDielectronCFdraw::Draw(Int_t var0, Int_t var1, Int_t var2, const char* opt, const char* slices)
483 {
484   //
485   // Draw 3D case
486   //
487   Int_t vars[3]={var0,var1,var2};
488   TObjArray *arr=CollectHistosProj(vars,slices);
489   Draw(arr,opt);
490   delete arr;
491 }
492
493 //________________________________________________________________
494 TObjArray* AliDielectronCFdraw::CollectHistosProj(const Int_t vars[3], const char* slices)
495 {
496   //
497   // Collect histos with up to 3 dimension of the 'slices' separated by one of "':;'"
498   // in a TObjArray and return it
499   // if a dimension is not used it must be set to -1
500   //
501   TObjArray *arr=TString(slices).Tokenize(",:;");
502   TObjArray *arrHists=0x0;
503   if (arr->GetEntriesFast()==0){
504     // all slices in case of 0 entries
505     arrHists=new TObjArray(fCfContainer->GetNStep());
506     for (Int_t istep=0; istep<fCfContainer->GetNStep(); ++istep){
507       TH1 *hproj=Project(vars,istep);
508       if (!hproj) continue;
509       hproj->SetName(Form("proj_%02d",istep));
510       hproj->SetTitle(fCfContainer->GetStepTitle(istep));
511       arrHists->Add(hproj);
512     }
513   } else {
514     arrHists=new TObjArray(arr->GetEntriesFast());
515     TIter next(arr);
516     TObjString *ostr=0x0;
517     while ( (ostr=static_cast<TObjString*>(next())) ) {
518       Int_t istep=ostr->GetString().Atoi();
519       TH1 *hproj=Project(vars,istep);
520       if (!hproj) continue;
521       hproj->SetName(Form("proj_%02d",istep));
522       hproj->SetTitle(fCfContainer->GetStepTitle(istep));
523       arrHists->Add(hproj);
524     }
525   }
526   delete arr;
527
528   return arrHists;
529 }
530
531 //________________________________________________________________
532 TObjArray* AliDielectronCFdraw::CollectMinvProj(Int_t slice, ECollectType collect, TString var)
533 {
534   //
535   // Collect invariant mass spectra of step 'slice' for pair types
536   //
537
538   TObjArray *arr = new TObjArray();
539   arr->SetOwner();
540   for (Int_t iType = 0; iType <= AliDielectron::kEv1PMRot; iType++) {
541
542     switch (iType) {
543       // same events
544       case AliDielectron::kEv1PP:
545       case AliDielectron::kEv1MM:
546         if(collect==kROT || collect==kME || collect==kMEOS) continue; break;
547         // mixed events
548       case AliDielectron::kEv1PEv2P:
549       case AliDielectron::kEv1MEv2M:
550         if(collect==kROT || collect==kSE || collect==kMEOS) continue; break;
551       case AliDielectron::kEv1MEv2P:
552       case AliDielectron::kEv1PEv2M:
553         if(collect==kROT || collect==kSE) continue; break;
554         // rotations
555       case AliDielectron::kEv1PMRot:
556         if(collect==kSE || collect==kME || collect==kMEOS) continue; break;
557         // unused
558       case AliDielectron::kEv2PP:
559       case AliDielectron::kEv2PM:
560       case AliDielectron::kEv2MM:
561         continue; break;
562     }
563     SetRangeUser("PairType",iType,iType,Form("%d",slice));
564     TH1 *hM=Project(var.Data(),slice);
565     hM->SetDirectory(0x0);
566     hM->SetNameTitle(Form("Minv_%d",iType),Form("M for type %d;M (GeV/c^{2})", iType));
567     arr->AddAt(hM,iType);
568   }
569   UnsetRangeUser("PairType",Form("%d",slice));
570   return arr;
571 }
572
573 //________________________________________________________________
574 TH1* AliDielectronCFdraw::Project(const Int_t *vars, Int_t slice)
575 {
576   //
577   // Do an ndim projection
578   //
579   return fCfContainer->Project(slice,vars[0],vars[1],vars[2]);
580 }
581
582 //________________________________________________________________
583 TH1* AliDielectronCFdraw::Project(const Option_t* var, Int_t slice)
584 {
585   //
586   // translate variable names and do projection
587   //
588   TObjArray *arrVars=TString(var).Tokenize(":");
589   Int_t entries=arrVars->GetEntriesFast();
590   if (entries<1||entries>3){
591     AliError("Wrong number of variables, supported are 1 - 3 dimensions");
592     delete arrVars;
593     return 0x0;
594   }
595
596   TIter next(arrVars);
597   TObjString *ostr=0x0;
598   Int_t ivar[3]={-1,-1,-1};
599   for (Int_t i=entries-1; i>=0; --i){
600     ostr=static_cast<TObjString*>(next());
601     if (ostr->GetString().IsDigit()){
602       ivar[i]=ostr->GetString().Atoi();
603     } else {
604       ivar[i]=fCfContainer->GetVar(ostr->GetName());
605     }
606   }
607   if (ivar[0]==-1) return 0x0;
608   delete arrVars;
609   return fCfContainer->Project(slice,ivar[0],ivar[1],ivar[2]);
610 }
611
612 //________________________________________________________________
613 void AliDielectronCFdraw::DrawEfficiency(const char* varnames, const char* numerators, Int_t denominator, const char* opt)
614 {
615   //
616   // plot efficiencies for variables. Variable may be up to 3 dim, separated by a ':'
617   // you may have several numerators, sparated by one of ',:;'
618   //
619   
620   TObjArray *arrVars=TString(varnames).Tokenize(":");
621   Int_t entries=arrVars->GetEntriesFast();
622   if (entries<1||entries>3){
623     AliError("Wrong number of variables, supported are 1 - 3 dimensions");
624     delete arrVars;
625     return;
626   }
627   
628   TIter next(arrVars);
629   TObjString *ostr=0x0;
630   Int_t ivar[3]={-1,-1,-1};
631   for (Int_t i=entries-1; i>=0; --i){
632     ostr=static_cast<TObjString*>(next());
633     if (ostr->GetString().IsDigit()){
634       ivar[i]=ostr->GetString().Atoi();
635     } else {
636       ivar[i]=fCfContainer->GetVar(ostr->GetName());
637     }
638   }
639
640   Int_t type=0;
641   TString optStr(opt);
642   if (optStr.Contains("2")) type=1;
643   
644   DrawEfficiency(ivar[0],ivar[1],ivar[2],numerators, denominator,opt,type);
645   delete arrVars;
646 }
647
648 //________________________________________________________________
649 void AliDielectronCFdraw::DrawEfficiency(Int_t var, const char* numerators, Int_t denominator, const char* opt, Int_t type)
650 {
651   //
652   // Draw Efficiencies for all numerators
653   // numerators may be divided by and of ,;:
654   //
655   // if opt contains 'same' all histograms are drawn in the same pad
656   // otherwise the pad will be divided in sub pads and the histograms
657   // are drawn in each sub pad
658   //
659   
660   Int_t vars[3]={var,-1,-1};
661   TObjArray *arr=CollectHistosEff(vars,numerators,denominator,type);
662   TString drawOpt=opt;
663   drawOpt+="eff";
664   Draw(arr,drawOpt);
665   delete arr;
666 }
667
668 //________________________________________________________________
669 void AliDielectronCFdraw::DrawEfficiency(Int_t var0, Int_t var1, const char* numerators, Int_t denominator, const char* opt, Int_t type)
670 {
671   //
672   // Draw 2D case
673   //
674   Int_t vars[3]={var0,var1,-1};
675   TObjArray *arr=CollectHistosEff(vars,numerators,denominator,type);
676   TString drawOpt=opt;
677   drawOpt+="eff";
678   Draw(arr,drawOpt);
679   delete arr;
680 }
681
682 //________________________________________________________________
683 void AliDielectronCFdraw::DrawEfficiency(Int_t var0, Int_t var1, Int_t var2, const char* numerators, Int_t denominator, const char* opt, Int_t type)
684 {
685   //
686   // Draw 3D case
687   //
688   Int_t vars[3]={var0,var1,var2};
689   TObjArray *arr=CollectHistosEff(vars,numerators,denominator,type);
690   TString drawOpt=opt;
691   drawOpt+="eff";
692   Draw(arr,drawOpt);
693   delete arr;
694 }
695
696 //________________________________________________________________
697 TObjArray* AliDielectronCFdraw::CollectHistosEff(const  Int_t vars[3], const char* numerators, Int_t denominator, Int_t type)
698 {
699   //
700   // Collect histos with 'dim'ension of the 'slices' separated by one of "':;'"
701   // in a TObjArray and return it
702   //
703   TObjArray *arr=TString(numerators).Tokenize(",:;");
704   TObjArray *arrHists=0x0;
705
706   if (type==0){
707     if (arr->GetEntriesFast()==0){
708     // all slices in case of 0 entries
709       arrHists=new TObjArray(fCfContainer->GetNStep());
710       fVdata.ResizeTo(arrHists->GetSize());
711       for (Int_t istep=0; istep<fCfContainer->GetNStep(); ++istep){
712         fEffGrid->CalculateEfficiency(istep,denominator);
713         TH1 *hproj=ProjectEff(vars);
714         if (!hproj) continue;
715         Float_t eff=fEffGrid->GetAverage();
716         fVdata(istep)=eff;
717         hproj->SetName(Form("eff_%02d/%02d",istep,denominator));
718         hproj->SetTitle(Form("%s (%.3f)",fCfContainer->GetStepTitle(istep),eff));
719         arrHists->Add(hproj);
720       }
721     } else {
722       arrHists=new TObjArray(arr->GetEntriesFast());
723       TIter next(arr);
724       TObjString *ostr=0x0;
725       fVdata.ResizeTo(arrHists->GetSize());
726       Int_t count=0;
727       while ( (ostr=static_cast<TObjString*>(next())) ) {
728         Int_t istep=ostr->GetString().Atoi();
729         fEffGrid->CalculateEfficiency(istep,denominator);
730         TH1 *hproj=ProjectEff(vars);
731         if (!hproj) continue;
732         Float_t eff=fEffGrid->GetAverage();
733         fVdata(count++)=eff;
734         hproj->SetName(Form("eff_%02d/%02d",istep,denominator));
735         hproj->SetTitle(Form("%s (%.3f)",fCfContainer->GetStepTitle(istep),eff));
736         arrHists->Add(hproj);
737       }
738     }
739   }
740
741   //second approach
742   if (type==1){
743     TH1 *hDen=Project(vars,denominator);
744     Double_t entriesDen=hDen->GetEffectiveEntries();
745     if (arr->GetEntriesFast()==0){
746     // all slices in case of 0 entries
747       arrHists=new TObjArray(fCfContainer->GetNStep());
748       fVdata.ResizeTo(arrHists->GetSize());
749       for (Int_t istep=0; istep<fCfContainer->GetNStep(); ++istep){
750         TH1 *hproj=Project(vars,istep);
751         if (!hproj) continue;
752         Float_t eff=0;
753         if (entriesDen>0) eff=hproj->GetEffectiveEntries()/entriesDen;
754         fVdata(istep)=eff;
755         hproj->Divide(hproj,hDen,1,1,"B");
756         hproj->SetName(Form("eff_%02d/%02d",istep,denominator));
757         hproj->SetTitle(Form("%s (%.3f)",fCfContainer->GetStepTitle(istep),eff));
758         arrHists->Add(hproj);
759       }
760     } else {
761       arrHists=new TObjArray(arr->GetEntriesFast());
762       fVdata.ResizeTo(arrHists->GetSize());
763       TIter next(arr);
764       TObjString *ostr=0x0;
765       Int_t count=0;
766       while ( (ostr=static_cast<TObjString*>(next())) ) {
767         Int_t istep=ostr->GetString().Atoi();
768         TH1 *hproj=Project(vars,istep);
769         if (!hproj) continue;
770         Float_t eff=0;
771         if (entriesDen>0) eff=hproj->GetEffectiveEntries()/entriesDen;
772         fVdata(count++)=eff;
773         hproj->Divide(hproj,hDen,1,1,"B");
774         hproj->SetName(Form("eff_%02d/%02d",istep,denominator));
775         hproj->SetTitle(Form("%s (%.3f)",fCfContainer->GetStepTitle(istep),eff));
776         arrHists->Add(hproj);
777       }
778     }
779     delete hDen;
780   }
781   
782
783   delete arr;
784   return arrHists;
785 }
786
787 //________________________________________________________________
788 TH1* AliDielectronCFdraw::ProjectEff(const Int_t vars[3])
789 {
790   //
791   // Do an nim projection
792   //
793   return fEffGrid->Project(vars[0],vars[1],vars[2]);
794 }
795
796 //________________________________________________________________
797 void AliDielectronCFdraw::Draw(const TObjArray *arr, const char* opt)
798 {
799   //
800   // draw all objects in arr
801   //
802   TString optStr(opt);
803   optStr.ToLower();
804   Bool_t drawSame     = optStr.Contains("same");
805   Bool_t drawSamePlus = optStr.Contains("same+");
806   Bool_t drawEff      = optStr.Contains("eff");
807   Bool_t optLeg       = optStr.Contains("leg");
808   Bool_t optScaleMax  = optStr.Contains("max");
809   
810   if (!drawSamePlus) optStr.ReplaceAll("same","");
811   
812   optStr.ReplaceAll("+","");
813   optStr.ReplaceAll("eff","");
814   optStr.ReplaceAll("leg","");
815   optStr.ReplaceAll("max","");
816   
817   if (!gPad) new TCanvas;
818   
819   Int_t nPads = arr->GetEntriesFast();
820   if (nPads==0) return;
821   
822 //   if (nPads==1){
823 //     arr->UncheckedAt(0)->Draw(optStr.Data());
824 //     return;
825 //   }
826   
827   TCanvas *c=gPad->GetCanvas();
828   if (!gVirtualPS&&!drawSamePlus&&!drawSame&&nPads>1) c->Clear();
829   
830   if (!drawSame&&nPads>1){
831     //optimised division
832     Int_t nCols = (Int_t)TMath::Ceil( TMath::Sqrt(nPads) );
833     Int_t nRows = (Int_t)TMath::Ceil( (Double_t)nPads/(Double_t)nCols );
834     c->Divide(nCols,nRows);
835     for (Int_t i=0; i<nPads; ++i){
836       c->cd(i+1);
837       arr->UncheckedAt(i)->Draw(optStr.Data());
838     }
839   } else {
840     TLegend *leg=0;
841     if (drawSamePlus){
842       //find already existing legend to attach entries to it
843       TIter nextPrimitive(gPad->GetListOfPrimitives());
844       TObject *o=0x0;
845       while ((o=nextPrimitive())) if (o->IsA()==TLegend::Class()) leg=(TLegend*)o;
846     }
847     
848     if (optLeg&&!leg) leg=new TLegend(.2,.3,.99,.9);
849     Int_t addColor=0;
850     if (leg) addColor=leg->GetNRows();
851     Int_t offset=20;
852     if (nPads<7) offset=24;
853     for (Int_t i=0; i<nPads; ++i){
854       if (i==1&&!drawSamePlus) optStr+="same";
855       TH1 *hist=static_cast<TH1*>(arr->UncheckedAt(i));
856       hist->SetLineColor(i+1+addColor);
857       hist->SetLineWidth(2);
858       hist->SetMarkerColor(i+1+addColor);
859       hist->SetMarkerStyle(offset+i+addColor);
860       hist->Draw(optStr.Data());
861       
862       if (drawEff&&i==0&&!drawSamePlus) {
863         hist->GetYaxis()->SetRangeUser(0,2);
864         hist->SetYTitle("Rec. Signal / Gen. Signal");
865       }
866       
867       if (leg) leg->AddEntry(hist,hist->GetTitle(),"lp");
868     }
869     if (leg){
870       leg->SetFillColor(10);
871       leg->SetY1(.9-leg->GetNRows()*.05);
872       leg->SetY1NDC(.9-leg->GetNRows()*.05);
873       leg->SetMargin(.1);
874       if (!drawSamePlus) leg->Draw();
875     }
876     if (optScaleMax){
877       TIter nextPrimitive(gPad->GetListOfPrimitives());
878       TObject *o=0x0;
879       TH1 *hfirst=0x0;
880       Float_t max=0;
881       while ((o=nextPrimitive())) if (o->InheritsFrom(TH1::Class())){
882         TH1 *h=(TH1*)o;
883         if (!hfirst) hfirst=h;
884         if (h->GetMaximum()>max) max=h->GetMaximum();
885       }
886       max*=1.1;
887       hfirst->SetMaximum(max);
888     }
889   }
890   
891 }
892
893 //________________________________________________________________
894 Double_t AliDielectronCFdraw::GetAverageEfficiency(Int_t numerator, Int_t denominator, Double_t &effErr)
895 {
896   //
897   // Extract the mean efficiency of the numerator and denominator
898   //
899
900   //use variable 0 as default, since for the average it doesn't matter
901   TH1 *hDen=fCfContainer->Project(denominator,0);
902   Double_t entriesDen=hDen->GetEffectiveEntries();
903   TH1 *hproj=fCfContainer->Project(numerator,0);
904   if (!hproj) return -1.;
905   Double_t entriesNum=hproj->GetEffectiveEntries();
906   if (entriesDen<1||entriesNum<1) return -1;
907   
908   Double_t eff=-1.;
909   if (entriesDen>0) eff=entriesNum/entriesDen;
910   effErr=TMath::Sqrt(1./entriesNum+1./entriesDen)*eff;
911   delete hDen;
912   delete hproj;
913   return eff;
914 }