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, ECollectType collect, TString var)
422 // Collect invariant mass spectra of step 'slice' for pair types
425 TObjArray *arr = new TObjArray();
427 for (Int_t iType = 0; iType <= AliDielectron::kEv1PMRot; iType++) {
431 case AliDielectron::kEv1PP:
432 case AliDielectron::kEv1MM:
433 if(collect==kROT || collect==kME || collect==kMEOS) continue; break;
435 case AliDielectron::kEv1PEv2P:
436 case AliDielectron::kEv1MEv2M:
437 if(collect==kROT || collect==kSE || collect==kMEOS) continue; break;
438 case AliDielectron::kEv1MEv2P:
439 case AliDielectron::kEv1PEv2M:
440 if(collect==kROT || collect==kSE) continue; break;
442 case AliDielectron::kEv1PMRot:
443 if(collect==kSE || collect==kME || collect==kMEOS) continue; break;
445 case AliDielectron::kEv2PP:
446 case AliDielectron::kEv2PM:
447 case AliDielectron::kEv2MM:
450 SetRangeUser("PairType",iType,iType,Form("%d",slice));
451 TH1 *hM=Project(var.Data(),slice);
452 hM->SetDirectory(0x0);
453 hM->SetNameTitle(Form("Minv_%d",iType),Form("M for type %d;M (GeV/c^{2})", iType));
454 arr->AddAt(hM,iType);
456 UnsetRangeUser("PairType",Form("%d",slice));
460 //________________________________________________________________
461 TH1* AliDielectronCFdraw::Project(const Int_t *vars, Int_t slice)
464 // Do an ndim projection
466 return fCfContainer->Project(slice,vars[0],vars[1],vars[2]);
469 //________________________________________________________________
470 TH1* AliDielectronCFdraw::Project(const Option_t* var, Int_t slice)
473 // translate variable names and do projection
475 TObjArray *arrVars=TString(var).Tokenize(":");
476 Int_t entries=arrVars->GetEntriesFast();
477 if (entries<1||entries>3){
478 AliError("Wrong number of variables, supported are 1 - 3 dimensions");
484 TObjString *ostr=0x0;
485 Int_t ivar[3]={-1,-1,-1};
486 for (Int_t i=entries-1; i>=0; --i){
487 ostr=static_cast<TObjString*>(next());
488 if (ostr->GetString().IsDigit()){
489 ivar[i]=ostr->GetString().Atoi();
491 ivar[i]=fCfContainer->GetVar(ostr->GetName());
494 if (ivar[0]==-1) return 0x0;
496 return fCfContainer->Project(slice,ivar[0],ivar[1],ivar[2]);
499 //________________________________________________________________
500 void AliDielectronCFdraw::DrawEfficiency(const char* varnames, const char* numerators, Int_t denominator, const char* opt)
503 // plot efficiencies for variables. Variable may be up to 3 dim, separated by a ':'
504 // you may have several numerators, sparated by one of ',:;'
507 TObjArray *arrVars=TString(varnames).Tokenize(":");
508 Int_t entries=arrVars->GetEntriesFast();
509 if (entries<1||entries>3){
510 AliError("Wrong number of variables, supported are 1 - 3 dimensions");
516 TObjString *ostr=0x0;
517 Int_t ivar[3]={-1,-1,-1};
518 for (Int_t i=entries-1; i>=0; --i){
519 ostr=static_cast<TObjString*>(next());
520 if (ostr->GetString().IsDigit()){
521 ivar[i]=ostr->GetString().Atoi();
523 ivar[i]=fCfContainer->GetVar(ostr->GetName());
529 if (optStr.Contains("2")) type=1;
531 DrawEfficiency(ivar[0],ivar[1],ivar[2],numerators, denominator,opt,type);
535 //________________________________________________________________
536 void AliDielectronCFdraw::DrawEfficiency(Int_t var, const char* numerators, Int_t denominator, const char* opt, Int_t type)
539 // Draw Efficiencies for all numerators
540 // numerators may be divided by and of ,;:
542 // if opt contains 'same' all histograms are drawn in the same pad
543 // otherwise the pad will be divided in sub pads and the histograms
544 // are drawn in each sub pad
547 Int_t vars[3]={var,-1,-1};
548 TObjArray *arr=CollectHistosEff(vars,numerators,denominator,type);
555 //________________________________________________________________
556 void AliDielectronCFdraw::DrawEfficiency(Int_t var0, Int_t var1, const char* numerators, Int_t denominator, const char* opt, Int_t type)
561 Int_t vars[3]={var0,var1,-1};
562 TObjArray *arr=CollectHistosEff(vars,numerators,denominator,type);
569 //________________________________________________________________
570 void AliDielectronCFdraw::DrawEfficiency(Int_t var0, Int_t var1, Int_t var2, const char* numerators, Int_t denominator, const char* opt, Int_t type)
575 Int_t vars[3]={var0,var1,var2};
576 TObjArray *arr=CollectHistosEff(vars,numerators,denominator,type);
583 //________________________________________________________________
584 TObjArray* AliDielectronCFdraw::CollectHistosEff(const Int_t vars[3], const char* numerators, Int_t denominator, Int_t type)
587 // Collect histos with 'dim'ension of the 'slices' separated by one of "':;'"
588 // in a TObjArray and return it
590 TObjArray *arr=TString(numerators).Tokenize(",:;");
591 TObjArray *arrHists=0x0;
594 if (arr->GetEntriesFast()==0){
595 // all slices in case of 0 entries
596 arrHists=new TObjArray(fCfContainer->GetNStep());
597 fVdata.ResizeTo(arrHists->GetSize());
598 for (Int_t istep=0; istep<fCfContainer->GetNStep(); ++istep){
599 fEffGrid->CalculateEfficiency(istep,denominator);
600 TH1 *hproj=ProjectEff(vars);
601 if (!hproj) continue;
602 Float_t eff=fEffGrid->GetAverage();
604 hproj->SetName(Form("eff_%02d/%02d",istep,denominator));
605 hproj->SetTitle(Form("%s (%.3f)",fCfContainer->GetStepTitle(istep),eff));
606 arrHists->Add(hproj);
609 arrHists=new TObjArray(arr->GetEntriesFast());
611 TObjString *ostr=0x0;
612 fVdata.ResizeTo(arrHists->GetSize());
614 while ( (ostr=static_cast<TObjString*>(next())) ) {
615 Int_t istep=ostr->GetString().Atoi();
616 fEffGrid->CalculateEfficiency(istep,denominator);
617 TH1 *hproj=ProjectEff(vars);
618 if (!hproj) continue;
619 Float_t eff=fEffGrid->GetAverage();
621 hproj->SetName(Form("eff_%02d/%02d",istep,denominator));
622 hproj->SetTitle(Form("%s (%.3f)",fCfContainer->GetStepTitle(istep),eff));
623 arrHists->Add(hproj);
630 TH1 *hDen=Project(vars,denominator);
631 Double_t entriesDen=hDen->GetEffectiveEntries();
632 if (arr->GetEntriesFast()==0){
633 // all slices in case of 0 entries
634 arrHists=new TObjArray(fCfContainer->GetNStep());
635 fVdata.ResizeTo(arrHists->GetSize());
636 for (Int_t istep=0; istep<fCfContainer->GetNStep(); ++istep){
637 TH1 *hproj=Project(vars,istep);
638 if (!hproj) continue;
640 if (entriesDen>0) eff=hproj->GetEffectiveEntries()/entriesDen;
642 hproj->Divide(hproj,hDen,1,1,"B");
643 hproj->SetName(Form("eff_%02d/%02d",istep,denominator));
644 hproj->SetTitle(Form("%s (%.3f)",fCfContainer->GetStepTitle(istep),eff));
645 arrHists->Add(hproj);
648 arrHists=new TObjArray(arr->GetEntriesFast());
649 fVdata.ResizeTo(arrHists->GetSize());
651 TObjString *ostr=0x0;
653 while ( (ostr=static_cast<TObjString*>(next())) ) {
654 Int_t istep=ostr->GetString().Atoi();
655 TH1 *hproj=Project(vars,istep);
656 if (!hproj) continue;
658 if (entriesDen>0) eff=hproj->GetEffectiveEntries()/entriesDen;
660 hproj->Divide(hproj,hDen,1,1,"B");
661 hproj->SetName(Form("eff_%02d/%02d",istep,denominator));
662 hproj->SetTitle(Form("%s (%.3f)",fCfContainer->GetStepTitle(istep),eff));
663 arrHists->Add(hproj);
674 //________________________________________________________________
675 TH1* AliDielectronCFdraw::ProjectEff(const Int_t vars[3])
678 // Do an nim projection
680 return fEffGrid->Project(vars[0],vars[1],vars[2]);
683 //________________________________________________________________
684 void AliDielectronCFdraw::Draw(const TObjArray *arr, const char* opt)
687 // draw all objects in arr
691 Bool_t drawSame = optStr.Contains("same");
692 Bool_t drawSamePlus = optStr.Contains("same+");
693 Bool_t drawEff = optStr.Contains("eff");
694 Bool_t optLeg = optStr.Contains("leg");
695 Bool_t optScaleMax = optStr.Contains("max");
697 if (!drawSamePlus) optStr.ReplaceAll("same","");
699 optStr.ReplaceAll("+","");
700 optStr.ReplaceAll("eff","");
701 optStr.ReplaceAll("leg","");
702 optStr.ReplaceAll("max","");
704 if (!gPad) new TCanvas;
706 Int_t nPads = arr->GetEntriesFast();
707 if (nPads==0) return;
710 // arr->UncheckedAt(0)->Draw(optStr.Data());
714 TCanvas *c=gPad->GetCanvas();
715 if (!gVirtualPS&&!drawSamePlus&&!drawSame&&nPads>1) c->Clear();
717 if (!drawSame&&nPads>1){
719 Int_t nCols = (Int_t)TMath::Ceil( TMath::Sqrt(nPads) );
720 Int_t nRows = (Int_t)TMath::Ceil( (Double_t)nPads/(Double_t)nCols );
721 c->Divide(nCols,nRows);
722 for (Int_t i=0; i<nPads; ++i){
724 arr->UncheckedAt(i)->Draw(optStr.Data());
729 //find already existing legend to attach entries to it
730 TIter nextPrimitive(gPad->GetListOfPrimitives());
732 while ((o=nextPrimitive())) if (o->IsA()==TLegend::Class()) leg=(TLegend*)o;
735 if (optLeg&&!leg) leg=new TLegend(.2,.3,.99,.9);
737 if (leg) addColor=leg->GetNRows();
739 if (nPads<7) offset=24;
740 for (Int_t i=0; i<nPads; ++i){
741 if (i==1&&!drawSamePlus) optStr+="same";
742 TH1 *hist=static_cast<TH1*>(arr->UncheckedAt(i));
743 hist->SetLineColor(i+1+addColor);
744 hist->SetLineWidth(2);
745 hist->SetMarkerColor(i+1+addColor);
746 hist->SetMarkerStyle(offset+i+addColor);
747 hist->Draw(optStr.Data());
749 if (drawEff&&i==0&&!drawSamePlus) {
750 hist->GetYaxis()->SetRangeUser(0,2);
751 hist->SetYTitle("Rec. Signal / Gen. Signal");
754 if (leg) leg->AddEntry(hist,hist->GetTitle(),"lp");
757 leg->SetFillColor(10);
758 leg->SetY1(.9-leg->GetNRows()*.05);
759 leg->SetY1NDC(.9-leg->GetNRows()*.05);
761 if (!drawSamePlus) leg->Draw();
764 TIter nextPrimitive(gPad->GetListOfPrimitives());
768 while ((o=nextPrimitive())) if (o->InheritsFrom(TH1::Class())){
770 if (!hfirst) hfirst=h;
771 if (h->GetMaximum()>max) max=h->GetMaximum();
774 hfirst->SetMaximum(max);
780 //________________________________________________________________
781 Double_t AliDielectronCFdraw::GetAverageEfficiency(Int_t numerator, Int_t denominator, Double_t &effErr)
784 // Extract the mean efficiency of the numerator and denominator
787 //use variable 0 as default, since for the average it doesn't matter
788 TH1 *hDen=fCfContainer->Project(denominator,0);
789 Double_t entriesDen=hDen->GetEffectiveEntries();
790 TH1 *hproj=fCfContainer->Project(numerator,0);
791 if (!hproj) return -1.;
792 Double_t entriesNum=hproj->GetEffectiveEntries();
793 if (entriesDen<1||entriesNum<1) return -1;
796 if (entriesDen>0) eff=entriesNum/entriesDen;
797 effErr=TMath::Sqrt(1./entriesNum+1./entriesDen)*eff;