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"
56 #include "AliDielectron.h"
58 ClassImp(AliDielectronCFdraw)
60 AliDielectronCFdraw::AliDielectronCFdraw() :
71 //________________________________________________________________
72 AliDielectronCFdraw::AliDielectronCFdraw(const char*name, const char* title) :
84 //________________________________________________________________
85 AliDielectronCFdraw::AliDielectronCFdraw(AliCFContainer *cont) :
86 TNamed(cont->GetName(), cont->GetTitle()),
88 fEffGrid(new AliCFEffGrid("eff","eff",*cont)),
92 // directly set the CF container
97 //________________________________________________________________
98 AliDielectronCFdraw::AliDielectronCFdraw(const char* filename) :
105 // get CF container(s) from file 'filename'
107 SetCFContainers(filename);
110 //________________________________________________________________
111 AliDielectronCFdraw::~AliDielectronCFdraw()
120 //________________________________________________________________
121 void AliDielectronCFdraw::SetCFContainers(const TSeqCollection *arr)
124 // Merge CF Container out of several containers
127 delete fCfContainer; fCfContainer=0x0;
128 delete fEffGrid; fEffGrid=0x0;
133 while ( (o=next()) ){
134 AliCFContainer *cf=dynamic_cast<AliCFContainer*>(o);
136 nstep+=cf->GetNStep();
138 if (nstep==0) return;
140 fCfContainer=new AliCFContainer(GetName(), GetTitle(), nstep, 1, nbins);
142 //delete unneeded steps
143 // for (Int_t istep=0; istep<nstep; ++istep) delete fCfContainer->GetGrid(istep);
145 //add step to the new container
147 for (Int_t icf=0; icf<arr->GetEntries(); ++icf){
148 AliCFContainer *cf=dynamic_cast<AliCFContainer*>(arr->At(icf));
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)));
156 if (fEffGrid) delete fEffGrid;
157 fEffGrid=new AliCFEffGrid("eff","eff",*fCfContainer);
160 //________________________________________________________________
161 void AliDielectronCFdraw::SetCFContainers(const char* filename)
164 // get CF containers from file
168 TList *l=f.GetListOfKeys();
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);
184 //________________________________________________________________
185 void AliDielectronCFdraw::SetRangeUser(Int_t ivar, Double_t min, Double_t max, const char* slices)
188 // Set range of cut steps defined in slices
189 // Steps may be separated by one the the characteres ,;:
191 if (ivar==-1) return;
192 TObjArray *arr=TString(slices).Tokenize(",:;");
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);
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);
212 //________________________________________________________________
213 void AliDielectronCFdraw::SetRangeUser(const char* varname, Double_t min, Double_t max, const char* slices)
216 // Set range from variable name
218 Int_t ivar=fCfContainer->GetVar(varname);
220 AliFatal(Form("Variable '%s' not found",varname));
223 SetRangeUser(ivar,min,max,slices);
226 //________________________________________________________________
227 void AliDielectronCFdraw::UnsetRangeUser(const char* varname, const char* slices)
230 // Unset range from variable name
232 Int_t ivar=fCfContainer->GetVar(varname);
234 AliFatal(Form("Variable '%s' not found",varname));
237 UnsetRangeUser(ivar,slices);
240 //________________________________________________________________
241 void AliDielectronCFdraw::UnsetRangeUser(Int_t ivar, const char* slices)
244 // Unset range of cut steps defined in slices
245 // Steps may be separated by one the the characteres ,;:
247 if (ivar==-1) return;
248 TObjArray *arr=TString(slices).Tokenize(",:;");
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);
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);
268 //________________________________________________________________
269 void AliDielectronCFdraw::Draw(const Option_t* varnames, const char* opt, const char* slices)
272 // Draw 'variables' of 'slices'
273 // for multidimensional draw variables may be separated by a ':'
274 // slice numbers may be separated by any of ,:;
276 // variables may be called by either their name or number
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");
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();
295 ivar[i]=fCfContainer->GetVar(ostr->GetName());
299 Draw(ivar[0],ivar[1],ivar[2],opt,slices);
303 //________________________________________________________________
304 TObjArray* AliDielectronCFdraw::CollectHistosProj(const Option_t* varnames, const char* slices)
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 ,:;
311 // variables may be called by either their name or number
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");
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();
330 ivar[i]=fCfContainer->GetVar(ostr->GetName());
335 return CollectHistosProj(ivar,slices);
338 //________________________________________________________________
339 void AliDielectronCFdraw::Draw(Int_t var, const char* opt, const char* slices)
342 // Draw variable var for all slices
343 // slices may be divided by and of ,;:
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
350 Int_t vars[3]={var,-1,-1};
351 TObjArray *arr=CollectHistosProj(vars,slices);
356 //________________________________________________________________
357 void AliDielectronCFdraw::Draw(Int_t var0, Int_t var1, const char* opt, const char* slices)
362 Int_t vars[3]={var0,var1,-1};
363 TObjArray *arr=CollectHistosProj(vars,slices);
368 //________________________________________________________________
369 void AliDielectronCFdraw::Draw(Int_t var0, Int_t var1, Int_t var2, const char* opt, const char* slices)
374 Int_t vars[3]={var0,var1,var2};
375 TObjArray *arr=CollectHistosProj(vars,slices);
380 //________________________________________________________________
381 TObjArray* AliDielectronCFdraw::CollectHistosProj(const Int_t vars[3], const char* slices)
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
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);
401 arrHists=new TObjArray(arr->GetEntriesFast());
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);
418 //________________________________________________________________
419 TObjArray* AliDielectronCFdraw::CollectMinvProj(Int_t slice)
422 // Collect invariant mass spectra of slice 'slice' for all pair types
425 TObjArray *arr = new TObjArray();
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);
435 //________________________________________________________________
436 TH1* AliDielectronCFdraw::Project(const Int_t *vars, Int_t slice)
439 // Do an ndim projection
441 return fCfContainer->Project(slice,vars[0],vars[1],vars[2]);
444 //________________________________________________________________
445 TH1* AliDielectronCFdraw::Project(const Option_t* var, Int_t slice)
448 // translate variable names and do projection
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");
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();
466 ivar[i]=fCfContainer->GetVar(ostr->GetName());
469 if (ivar[0]==-1) return 0x0;
471 return fCfContainer->Project(slice,ivar[0],ivar[1],ivar[2]);
474 //________________________________________________________________
475 void AliDielectronCFdraw::DrawEfficiency(const char* varnames, const char* numerators, Int_t denominator, const char* opt)
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 ',:;'
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");
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();
498 ivar[i]=fCfContainer->GetVar(ostr->GetName());
504 if (optStr.Contains("2")) type=1;
506 DrawEfficiency(ivar[0],ivar[1],ivar[2],numerators, denominator,opt,type);
510 //________________________________________________________________
511 void AliDielectronCFdraw::DrawEfficiency(Int_t var, const char* numerators, Int_t denominator, const char* opt, Int_t type)
514 // Draw Efficiencies for all numerators
515 // numerators may be divided by and of ,;:
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
522 Int_t vars[3]={var,-1,-1};
523 TObjArray *arr=CollectHistosEff(vars,numerators,denominator,type);
530 //________________________________________________________________
531 void AliDielectronCFdraw::DrawEfficiency(Int_t var0, Int_t var1, const char* numerators, Int_t denominator, const char* opt, Int_t type)
536 Int_t vars[3]={var0,var1,-1};
537 TObjArray *arr=CollectHistosEff(vars,numerators,denominator,type);
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)
550 Int_t vars[3]={var0,var1,var2};
551 TObjArray *arr=CollectHistosEff(vars,numerators,denominator,type);
558 //________________________________________________________________
559 TObjArray* AliDielectronCFdraw::CollectHistosEff(const Int_t vars[3], const char* numerators, Int_t denominator, Int_t type)
562 // Collect histos with 'dim'ension of the 'slices' separated by one of "':;'"
563 // in a TObjArray and return it
565 TObjArray *arr=TString(numerators).Tokenize(",:;");
566 TObjArray *arrHists=0x0;
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();
579 hproj->SetName(Form("eff_%02d/%02d",istep,denominator));
580 hproj->SetTitle(Form("%s (%.3f)",fCfContainer->GetStepTitle(istep),eff));
581 arrHists->Add(hproj);
584 arrHists=new TObjArray(arr->GetEntriesFast());
586 TObjString *ostr=0x0;
587 fVdata.ResizeTo(arrHists->GetSize());
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();
596 hproj->SetName(Form("eff_%02d/%02d",istep,denominator));
597 hproj->SetTitle(Form("%s (%.3f)",fCfContainer->GetStepTitle(istep),eff));
598 arrHists->Add(hproj);
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;
615 if (entriesDen>0) eff=hproj->GetEffectiveEntries()/entriesDen;
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);
623 arrHists=new TObjArray(arr->GetEntriesFast());
624 fVdata.ResizeTo(arrHists->GetSize());
626 TObjString *ostr=0x0;
628 while ( (ostr=static_cast<TObjString*>(next())) ) {
629 Int_t istep=ostr->GetString().Atoi();
630 TH1 *hproj=Project(vars,istep);
631 if (!hproj) continue;
633 if (entriesDen>0) eff=hproj->GetEffectiveEntries()/entriesDen;
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);
649 //________________________________________________________________
650 TH1* AliDielectronCFdraw::ProjectEff(const Int_t vars[3])
653 // Do an nim projection
655 return fEffGrid->Project(vars[0],vars[1],vars[2]);
658 //________________________________________________________________
659 void AliDielectronCFdraw::Draw(const TObjArray *arr, const char* opt)
662 // draw all objects in arr
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");
672 if (!drawSamePlus) optStr.ReplaceAll("same","");
674 optStr.ReplaceAll("+","");
675 optStr.ReplaceAll("eff","");
676 optStr.ReplaceAll("leg","");
677 optStr.ReplaceAll("max","");
679 if (!gPad) new TCanvas;
681 Int_t nPads = arr->GetEntriesFast();
682 if (nPads==0) return;
685 // arr->UncheckedAt(0)->Draw(optStr.Data());
689 TCanvas *c=gPad->GetCanvas();
690 if (!gVirtualPS&&!drawSamePlus&&!drawSame&&nPads>1) c->Clear();
692 if (!drawSame&&nPads>1){
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){
699 arr->UncheckedAt(i)->Draw(optStr.Data());
704 //find already existing legend to attach entries to it
705 TIter nextPrimitive(gPad->GetListOfPrimitives());
707 while ((o=nextPrimitive())) if (o->IsA()==TLegend::Class()) leg=(TLegend*)o;
710 if (optLeg&&!leg) leg=new TLegend(.2,.3,.99,.9);
712 if (leg) addColor=leg->GetNRows();
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());
724 if (drawEff&&i==0&&!drawSamePlus) {
725 hist->GetYaxis()->SetRangeUser(0,2);
726 hist->SetYTitle("Rec. Signal / Gen. Signal");
729 if (leg) leg->AddEntry(hist,hist->GetTitle(),"lp");
732 leg->SetFillColor(10);
733 leg->SetY1(.9-leg->GetNRows()*.05);
734 leg->SetY1NDC(.9-leg->GetNRows()*.05);
736 if (!drawSamePlus) leg->Draw();
739 TIter nextPrimitive(gPad->GetListOfPrimitives());
743 while ((o=nextPrimitive())) if (o->InheritsFrom(TH1::Class())){
745 if (!hfirst) hfirst=h;
746 if (h->GetMaximum()>max) max=h->GetMaximum();
749 hfirst->SetMaximum(max);
755 //________________________________________________________________
756 Double_t AliDielectronCFdraw::GetAverageEfficiency(Int_t numerator, Int_t denominator, Double_t &effErr)
759 // Extract the mean efficiency of the numerator and denominator
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;
771 if (entriesDen>0) eff=entriesNum/entriesDen;
772 effErr=TMath::Sqrt(1./entriesNum+1./entriesDen)*eff;