1 /*************************************************************************
2 * Copyright(c) 1998-2009, ALICE Experiment at CERN, All rights reserved. *
4 * Author: The ALICE Off-line Project. *
5 * Contributors are mentioned in the code where appropriate. *
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 **************************************************************************/
16 ///////////////////////////////////////////////////////////////////////////
17 // Dielectron Correction framework draw helper //
31 ///////////////////////////////////////////////////////////////////////////
33 #include <TSeqCollection.h>
34 #include <TObjArray.h>
39 #include <TVirtualPS.h>
42 #include <TObjString.h>
51 #include <AliCFEffGrid.h>
55 #include "AliDielectronCFdraw.h"
57 ClassImp(AliDielectronCFdraw)
59 AliDielectronCFdraw::AliDielectronCFdraw() :
70 //________________________________________________________________
71 AliDielectronCFdraw::AliDielectronCFdraw(const char*name, const char* title) :
83 //________________________________________________________________
84 AliDielectronCFdraw::AliDielectronCFdraw(AliCFContainer *cont) :
85 TNamed(cont->GetName(), cont->GetTitle()),
87 fEffGrid(new AliCFEffGrid("eff","eff",*cont)),
91 // directly set the CF container
96 //________________________________________________________________
97 AliDielectronCFdraw::AliDielectronCFdraw(const char* filename) :
104 // get CF container(s) from file 'filename'
106 SetCFContainers(filename);
109 //________________________________________________________________
110 void AliDielectronCFdraw::SetCFContainers(const TSeqCollection *arr)
113 // Merge CF Container out of several containers
120 while ( (o=next()) ){
121 AliCFContainer *cf=dynamic_cast<AliCFContainer*>(o);
123 nstep+=cf->GetNStep();
125 if (nstep==0) return;
127 fCfContainer=new AliCFContainer(GetName(), GetTitle(), nstep, 1, nbins);
129 //delete unneeded steps
130 // for (Int_t istep=0; istep<nstep; ++istep) delete fCfContainer->GetGrid(istep);
132 //add step to the new container
134 for (Int_t icf=0; icf<arr->GetEntries(); ++icf){
135 AliCFContainer *cf=dynamic_cast<AliCFContainer*>(arr->At(icf));
137 for (Int_t istepCurr=0; istepCurr<cf->GetNStep(); ++istepCurr){
138 fCfContainer->SetGrid(istep, cf->GetGrid(istepCurr));
139 fCfContainer->SetStepTitle(istep,Form("%s, Pair: %s",cf->GetTitle(),cf->GetStepTitle(istepCurr)));
143 if (fEffGrid) delete fEffGrid;
144 fEffGrid=new AliCFEffGrid("eff","eff",*fCfContainer);
147 //________________________________________________________________
148 void AliDielectronCFdraw::SetCFContainers(const char* filename)
151 // get CF containers from file
155 TList *l=f.GetListOfKeys();
158 while ( (k=static_cast<TKey*>(nextKey())) ){
159 TObject *o=k->ReadObj();
160 if (o->IsA()->InheritsFrom(TSeqCollection::Class())){
161 TSeqCollection *arr=static_cast<TSeqCollection*>(o);
162 SetCFContainers(arr);
163 } else if (o->IsA()==AliCFContainer::Class()){
164 fCfContainer=static_cast<AliCFContainer*>(o);
165 if (fEffGrid) delete fEffGrid;
166 fEffGrid=new AliCFEffGrid("eff","eff",*fCfContainer);
171 //________________________________________________________________
172 void AliDielectronCFdraw::SetRangeUser(Int_t ivar, Double_t min, Double_t max, const char* slices)
175 // Set range of cut steps defined in slices
176 // Steps may be separated by one the the characteres ,;:
178 if (ivar==-1) return;
179 TObjArray *arr=TString(slices).Tokenize(",:;");
181 if (arr->GetEntriesFast()==0){
182 // all slices in case of 0 entries
183 for (Int_t istep=0; istep<fCfContainer->GetNStep(); ++istep){
184 fCfContainer->GetGrid(istep)->SetRangeUser(ivar,min,max);
185 fCfContainer->GetAxis(ivar,istep)->SetBit(TAxis::kAxisRange,1);
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 fCfContainer->GetAxis(ivar,istep)->SetBit(TAxis::kAxisRange,1);
199 //________________________________________________________________
200 void AliDielectronCFdraw::UnsetRangeUser(Int_t ivar, const char* slices)
203 // Unset range of cut steps defined in slices
204 // Steps may be separated by one the the characteres ,;:
206 if (ivar==-1) return;
207 TObjArray *arr=TString(slices).Tokenize(",:;");
209 if (arr->GetEntriesFast()==0){
210 // all slices in case of 0 entries
211 for (Int_t istep=0; istep<fCfContainer->GetNStep(); ++istep){
212 fCfContainer->GetAxis(ivar,istep)->SetRange(0,0);
216 TObjString *ostr=0x0;
217 while ( (ostr=static_cast<TObjString*>(next())) ) {
218 Int_t istep=ostr->GetString().Atoi();
219 fCfContainer->GetAxis(ivar,istep)->SetRange(0,0);
225 //________________________________________________________________
226 void AliDielectronCFdraw::Draw(const Option_t* varnames, const char* opt, const char* slices)
229 // Draw 'variables' of 'slices'
230 // for multidimensional draw variables may be separated by a ':'
231 // slice numbers may be separated by any of ,:;
233 // variables may be called by either their name or number
236 TObjArray *arrVars=TString(varnames).Tokenize(":");
237 Int_t entries=arrVars->GetEntriesFast();
238 if (entries<1||entries>3){
239 AliError("Wrong number of variables, supported are 1 - 3 dimensions");
245 TObjString *ostr=0x0;
246 Int_t ivar[3]={-1,-1,-1};
247 for (Int_t i=entries-1; i>=0; --i){
248 ostr=static_cast<TObjString*>(next());
249 if (ostr->GetString().IsDigit()){
250 ivar[i]=ostr->GetString().Atoi();
252 ivar[i]=fCfContainer->GetVar(ostr->GetName());
256 Draw(ivar[0],ivar[1],ivar[2],opt,slices);
260 //________________________________________________________________
261 TObjArray* AliDielectronCFdraw::CollectHistosProj(const Option_t* varnames, const char* slices)
264 // Collect histos with 'variables' of 'slices'
265 // for multidimensional histograms, variables may be separated by a ':'
266 // slice numbers may be separated by any of ,:;
268 // variables may be called by either their name or number
271 TObjArray *arrVars=TString(varnames).Tokenize(":");
272 Int_t entries=arrVars->GetEntriesFast();
273 if (entries<1||entries>3){
274 AliError("Wrong number of variables, supported are 1 - 3 dimensions");
280 TObjString *ostr=0x0;
281 Int_t ivar[3]={-1,-1,-1};
282 for (Int_t i=entries-1; i>=0; --i){
283 ostr=static_cast<TObjString*>(next());
284 if (ostr->GetString().IsDigit()){
285 ivar[i]=ostr->GetString().Atoi();
287 ivar[i]=fCfContainer->GetVar(ostr->GetName());
292 return CollectHistosProj(ivar,slices);
295 //________________________________________________________________
296 void AliDielectronCFdraw::Draw(Int_t var, const char* opt, const char* slices)
299 // Draw variable var for all slices
300 // slices may be divided by and of ,;:
302 // if opt contains 'same' all histograms are drawn in the same pad
303 // otherwise the pad will be divided in sub pads and the histograms
304 // are drawn in each sub pad
307 Int_t vars[3]={var,-1,-1};
308 TObjArray *arr=CollectHistosProj(vars,slices);
313 //________________________________________________________________
314 void AliDielectronCFdraw::Draw(Int_t var0, Int_t var1, const char* opt, const char* slices)
319 Int_t vars[3]={var0,var1,-1};
320 TObjArray *arr=CollectHistosProj(vars,slices);
325 //________________________________________________________________
326 void AliDielectronCFdraw::Draw(Int_t var0, Int_t var1, Int_t var2, const char* opt, const char* slices)
331 Int_t vars[3]={var0,var1,var2};
332 TObjArray *arr=CollectHistosProj(vars,slices);
337 //________________________________________________________________
338 TObjArray* AliDielectronCFdraw::CollectHistosProj(const Int_t vars[3], const char* slices)
341 // Collect histos with up to 3 dimension of the 'slices' separated by one of "':;'"
342 // in a TObjArray and return it
343 // if a dimension is not used it must be set to -1
345 TObjArray *arr=TString(slices).Tokenize(",:;");
346 TObjArray *arrHists=0x0;
347 if (arr->GetEntriesFast()==0){
348 // all slices in case of 0 entries
349 arrHists=new TObjArray(fCfContainer->GetNStep());
350 for (Int_t istep=0; istep<fCfContainer->GetNStep(); ++istep){
351 TH1 *hproj=Project(vars,istep);
352 if (!hproj) continue;
353 hproj->SetName(Form("proj_%02d",istep));
354 hproj->SetTitle(fCfContainer->GetStepTitle(istep));
355 arrHists->Add(hproj);
358 arrHists=new TObjArray(arr->GetEntriesFast());
360 TObjString *ostr=0x0;
361 while ( (ostr=static_cast<TObjString*>(next())) ) {
362 Int_t istep=ostr->GetString().Atoi();
363 TH1 *hproj=Project(vars,istep);
364 if (!hproj) continue;
365 hproj->SetName(Form("proj_%02d",istep));
366 hproj->SetTitle(fCfContainer->GetStepTitle(istep));
367 arrHists->Add(hproj);
375 //________________________________________________________________
376 TH1* AliDielectronCFdraw::Project(const Int_t *vars, Int_t slice)
379 // Do an ndim projection
381 return fCfContainer->Project(slice,vars[0],vars[1],vars[2]);
384 //________________________________________________________________
385 TH1* AliDielectronCFdraw::Project(const Option_t* var, Int_t slice)
388 // translate variable names and do projection
390 TObjArray *arrVars=TString(var).Tokenize(":");
391 Int_t entries=arrVars->GetEntriesFast();
392 if (entries<1||entries>3){
393 AliError("Wrong number of variables, supported are 1 - 3 dimensions");
398 TObjString *ostr=0x0;
399 Int_t ivar[3]={-1,-1,-1};
400 for (Int_t i=entries-1; i>=0; --i){
401 ostr=static_cast<TObjString*>(arrVars->At(i));
402 if (ostr->GetString().IsDigit()){
403 ivar[i]=ostr->GetString().Atoi();
405 ivar[i]=fCfContainer->GetVar(ostr->GetName());
408 if (ivar[0]==-1) return 0x0;
410 return fCfContainer->Project(slice,ivar[0],ivar[1],ivar[2]);
413 //________________________________________________________________
414 void AliDielectronCFdraw::DrawEfficiency(const char* varnames, const char* numerators, Int_t denominator, const char* opt)
417 // plot efficiencies for variables. Variable may be up to 3 dim, separated by a ':'
418 // you may have several numerators, sparated by one of ',:;'
421 TObjArray *arrVars=TString(varnames).Tokenize(":");
422 Int_t entries=arrVars->GetEntriesFast();
423 if (entries<1||entries>3){
424 AliError("Wrong number of variables, supported are 1 - 3 dimensions");
430 TObjString *ostr=0x0;
431 Int_t ivar[3]={-1,-1,-1};
432 for (Int_t i=0; i<entries; ++i){
433 ostr=static_cast<TObjString*>(next());
434 if (ostr->GetString().IsDigit()){
435 ivar[i]=ostr->GetString().Atoi();
437 ivar[i]=fCfContainer->GetVar(ostr->GetName());
443 if (optStr.Contains("2")) type=1;
445 DrawEfficiency(ivar[2],ivar[1],ivar[0],numerators, denominator,opt,type);
449 //________________________________________________________________
450 void AliDielectronCFdraw::DrawEfficiency(Int_t var, const char* numerators, Int_t denominator, const char* opt, Int_t type)
453 // Draw Efficiencies for all numerators
454 // numerators may be divided by and of ,;:
456 // if opt contains 'same' all histograms are drawn in the same pad
457 // otherwise the pad will be divided in sub pads and the histograms
458 // are drawn in each sub pad
461 Int_t vars[3]={var,-1,-1};
462 TObjArray *arr=CollectHistosEff(vars,numerators,denominator,type);
469 //________________________________________________________________
470 void AliDielectronCFdraw::DrawEfficiency(Int_t var0, Int_t var1, const char* numerators, Int_t denominator, const char* opt, Int_t type)
475 Int_t vars[3]={var0,var1,-1};
476 TObjArray *arr=CollectHistosEff(vars,numerators,denominator,type);
483 //________________________________________________________________
484 void AliDielectronCFdraw::DrawEfficiency(Int_t var0, Int_t var1, Int_t var2, const char* numerators, Int_t denominator, const char* opt, Int_t type)
489 Int_t vars[3]={var0,var1,var2};
490 TObjArray *arr=CollectHistosEff(vars,numerators,denominator,type);
497 //________________________________________________________________
498 TObjArray* AliDielectronCFdraw::CollectHistosEff(const Int_t vars[3], const char* numerators, Int_t denominator, Int_t type)
501 // Collect histos with 'dim'ension of the 'slices' separated by one of "':;'"
502 // in a TObjArray and return it
504 TObjArray *arr=TString(numerators).Tokenize(",:;");
505 TObjArray *arrHists=0x0;
508 if (arr->GetEntriesFast()==0){
509 // all slices in case of 0 entries
510 arrHists=new TObjArray(fCfContainer->GetNStep());
511 fVdata.ResizeTo(arrHists->GetSize());
512 for (Int_t istep=0; istep<fCfContainer->GetNStep(); ++istep){
513 fEffGrid->CalculateEfficiency(istep,denominator);
514 TH1 *hproj=ProjectEff(vars);
515 if (!hproj) continue;
516 Float_t eff=fEffGrid->GetAverage();
518 hproj->SetName(Form("eff_%02d/%02d",istep,denominator));
519 hproj->SetTitle(Form("%s (%.3f)",fCfContainer->GetStepTitle(istep),eff));
520 arrHists->Add(hproj);
523 arrHists=new TObjArray(arr->GetEntriesFast());
525 TObjString *ostr=0x0;
526 fVdata.ResizeTo(arrHists->GetSize());
528 while ( (ostr=static_cast<TObjString*>(next())) ) {
529 Int_t istep=ostr->GetString().Atoi();
530 fEffGrid->CalculateEfficiency(istep,denominator);
531 TH1 *hproj=ProjectEff(vars);
532 if (!hproj) continue;
533 Float_t eff=fEffGrid->GetAverage();
535 hproj->SetName(Form("eff_%02d/%02d",istep,denominator));
536 hproj->SetTitle(Form("%s (%.3f)",fCfContainer->GetStepTitle(istep),eff));
537 arrHists->Add(hproj);
544 TH1 *hDen=Project(vars,denominator);
545 Double_t entriesDen=hDen->GetEffectiveEntries();
546 if (arr->GetEntriesFast()==0){
547 // all slices in case of 0 entries
548 arrHists=new TObjArray(fCfContainer->GetNStep());
549 fVdata.ResizeTo(arrHists->GetSize());
550 for (Int_t istep=0; istep<fCfContainer->GetNStep(); ++istep){
551 TH1 *hproj=Project(vars,istep);
552 if (!hproj) continue;
554 if (entriesDen>0) eff=hproj->GetEffectiveEntries()/entriesDen;
556 hproj->Divide(hproj,hDen,1,1,"B");
557 hproj->SetName(Form("eff_%02d/%02d",istep,denominator));
558 hproj->SetTitle(Form("%s (%.3f)",fCfContainer->GetStepTitle(istep),eff));
559 arrHists->Add(hproj);
562 arrHists=new TObjArray(arr->GetEntriesFast());
563 fVdata.ResizeTo(arrHists->GetSize());
565 TObjString *ostr=0x0;
567 while ( (ostr=static_cast<TObjString*>(next())) ) {
568 Int_t istep=ostr->GetString().Atoi();
569 TH1 *hproj=Project(vars,istep);
570 if (!hproj) continue;
572 if (entriesDen>0) eff=hproj->GetEffectiveEntries()/entriesDen;
574 hproj->Divide(hproj,hDen,1,1,"B");
575 hproj->SetName(Form("eff_%02d/%02d",istep,denominator));
576 hproj->SetTitle(Form("%s (%.3f)",fCfContainer->GetStepTitle(istep),eff));
577 arrHists->Add(hproj);
588 //________________________________________________________________
589 TH1* AliDielectronCFdraw::ProjectEff(const Int_t vars[3])
592 // Do an nim projection
594 return fEffGrid->Project(vars[0],vars[1],vars[2]);
597 //________________________________________________________________
598 void AliDielectronCFdraw::Draw(const TObjArray *arr, const char* opt)
601 // draw all objects in arr
605 Bool_t drawSame = optStr.Contains("same");
606 Bool_t drawSamePlus = optStr.Contains("same+");
607 Bool_t drawEff = optStr.Contains("eff");
608 Bool_t optLeg = optStr.Contains("leg");
609 Bool_t optScaleMax = optStr.Contains("max");
611 if (!drawSamePlus) optStr.ReplaceAll("same","");
613 optStr.ReplaceAll("+","");
614 optStr.ReplaceAll("eff","");
615 optStr.ReplaceAll("leg","");
616 optStr.ReplaceAll("max","");
618 if (!gPad) new TCanvas;
620 Int_t nPads = arr->GetEntriesFast();
621 if (nPads==0) return;
624 // arr->UncheckedAt(0)->Draw(optStr.Data());
628 TCanvas *c=gPad->GetCanvas();
629 if (!gVirtualPS&&!drawSamePlus&&!drawSame&&nPads>1) c->Clear();
631 if (!drawSame&&nPads>1){
633 Int_t nCols = (Int_t)TMath::Ceil( TMath::Sqrt(nPads) );
634 Int_t nRows = (Int_t)TMath::Ceil( (Double_t)nPads/(Double_t)nCols );
635 c->Divide(nCols,nRows);
636 for (Int_t i=0; i<nPads; ++i){
638 arr->UncheckedAt(i)->Draw(optStr.Data());
643 //find already existing legend to attach entries to it
644 TIter nextPrimitive(gPad->GetListOfPrimitives());
646 while ((o=nextPrimitive())) if (o->IsA()==TLegend::Class()) leg=(TLegend*)o;
649 if (optLeg&&!leg) leg=new TLegend(.2,.3,.99,.9);
651 if (leg) addColor=leg->GetNRows();
653 if (nPads<7) offset=24;
654 for (Int_t i=0; i<nPads; ++i){
655 if (i==1&&!drawSamePlus) optStr+="same";
656 TH1 *hist=static_cast<TH1*>(arr->UncheckedAt(i));
657 hist->SetLineColor(i+1+addColor);
658 hist->SetLineWidth(2);
659 hist->SetMarkerColor(i+1+addColor);
660 hist->SetMarkerStyle(offset+i+addColor);
661 hist->Draw(optStr.Data());
663 if (drawEff&&i==0&&!drawSamePlus) {
664 hist->GetYaxis()->SetRangeUser(0,2);
665 hist->SetYTitle("Rec. Signal / Gen. Signal");
668 if (leg) leg->AddEntry(hist,hist->GetTitle(),"lp");
671 leg->SetFillColor(10);
672 leg->SetY1(.9-leg->GetNRows()*.05);
673 leg->SetY1NDC(.9-leg->GetNRows()*.05);
675 if (!drawSamePlus) leg->Draw();
678 TIter nextPrimitive(gPad->GetListOfPrimitives());
682 while ((o=nextPrimitive())) if (o->InheritsFrom(TH1::Class())){
684 if (!hfirst) hfirst=h;
685 if (h->GetMaximum()>max) max=h->GetMaximum();
688 hfirst->SetMaximum(max);
694 //________________________________________________________________
695 Double_t AliDielectronCFdraw::GetAverageEfficiency(Int_t numerator, Int_t denominator, Double_t &effErr)
698 // Extract the mean efficiency of the numerator and denominator
701 //use variable 0 as default, since for the average it doesn't matter
702 TH1 *hDen=fCfContainer->Project(denominator,0);
703 Double_t entriesDen=hDen->GetEffectiveEntries();
704 TH1 *hproj=fCfContainer->Project(numerator,0);
705 if (!hproj) return -1.;
706 Double_t entriesNum=hproj->GetEffectiveEntries();
707 if (entriesDen<1||entriesNum<1) return -1;
710 if (entriesDen>0) eff=entriesNum/entriesDen;
711 effErr=TMath::Sqrt(1./entriesNum+1./entriesDen)*eff;