Changes for #93172: Improve trigger chamber efficiency calculation
[u/mrichter/AliRoot.git] / PWGPP / MUON / lite / AliAnalysisTaskTrigChEff.cxx
1 /**************************************************************************
2  * Copyright(c) 1998-2007, 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 /* $Id$ */
17
18 #include "AliAnalysisTaskTrigChEff.h"
19
20 // ROOT includes
21 #include "TH1.h"
22 #include "TH2.h"
23 #include "TCanvas.h"
24 #include "TLegend.h"
25 #include "TMath.h"
26 #include "TObjString.h"
27 #include "TObjArray.h"
28 #include "TStyle.h"
29 #include "TROOT.h"
30 #include "TGraphAsymmErrors.h"
31 #include "TList.h"
32 #include "TFile.h"
33
34 // STEER includes
35 #include "AliVParticle.h"
36 #include "AliAODTrack.h"
37 #include "AliESDMuonTrack.h"
38
39 // ANALYSIS includes
40 #include "AliAnalysisManager.h"
41 #include "AliAnalysisDataSlot.h"
42 #include "AliAnalysisDataContainer.h"
43
44 // PWG3 includes
45 #include "AliVAnalysisMuon.h"
46 #include "AliMuonTrackCuts.h"
47 #include "AliMergeableCollection.h"
48
49
50 /// \cond CLASSIMP
51 ClassImp(AliAnalysisTaskTrigChEff) // Class implementation in ROOT context
52 /// \endcond
53
54
55 //________________________________________________________________________
56 AliAnalysisTaskTrigChEff::AliAnalysisTaskTrigChEff() :
57   AliVAnalysisMuon(),
58   fTrackSelKeys(0x0),
59   fCountTypeKeys(0x0),
60   fHistoTypeKeys(0x0),
61   fEffMethodKeys(0x0),
62   fUseGhosts(kFALSE),
63   fList(0x0)
64 {
65   /// Default ctor.
66 }
67
68 //________________________________________________________________________
69 AliAnalysisTaskTrigChEff::AliAnalysisTaskTrigChEff(const char *name, const AliMuonTrackCuts& cuts) :
70   AliVAnalysisMuon(name, cuts),
71   fTrackSelKeys(0x0),
72   fCountTypeKeys(0x0),
73   fHistoTypeKeys(0x0),
74   fEffMethodKeys(0x0),
75   fUseGhosts(kFALSE),
76   fList(0x0)
77 {
78   //
79   /// Constructor.
80   //
81
82   InitLocalKeys();
83   
84   DefineOutput(2, TList::Class());
85 }
86
87
88 //________________________________________________________________________
89 AliAnalysisTaskTrigChEff::~AliAnalysisTaskTrigChEff()
90 {
91   //
92   /// Destructor
93   //
94   delete fTrackSelKeys;
95   delete fCountTypeKeys;
96   delete fHistoTypeKeys;
97   delete fEffMethodKeys;
98   if ( ! AliAnalysisManager::GetAnalysisManager() || ! AliAnalysisManager::GetAnalysisManager()->IsProofMode() ) {
99     delete fList;
100   }
101 }
102
103 //___________________________________________________________________________
104 TList* AliAnalysisTaskTrigChEff::GetEffHistoList(TString physSel, TString trigClassNames, TString centrality, TString trackSelection)
105 {
106   /// Get the list of efficiency objects by merging the 
107   // results from the histogram collection
108   
109   TList* outList = new TList();
110   outList->SetOwner();
111   FillEffHistoList(physSel, trigClassNames, centrality, trackSelection, outList);
112   return outList;
113 }
114
115 //___________________________________________________________________________
116 Bool_t AliAnalysisTaskTrigChEff::FillEffHistoList(TString physSel, TString trigClassNames, TString centrality, TString trackSelection, TList* outList)
117 {
118   /// Fill the list of objects for the efficiency calculation
119   /// merging the splitted output of the fHistogramCollection
120   /// The obtained list can be converted in the efficiency map used in simulations
121   /// in a backward compatible way
122   
123   if ( ! fMergeableCollection ) return kFALSE;
124   if ( ! outList ) outList = fList;
125   TString histoName = "";
126   TString histoPattern = "";
127   TH1* histo = 0x0;
128   Bool_t isOk = kTRUE;
129   for ( Int_t icount=0; icount<kNcounts; ++icount ) {
130     histoName = GetHistoName(kHchamberEff, icount, -1, -1, -1);
131     histoPattern = Form("%s&%s", histoName.Data(), trackSelection.Data());
132     histo = (TH1*)GetSum(physSel, trigClassNames, centrality, histoPattern);
133     if ( histo ) {
134       histo->SetName(histoName.Data());
135       histo->SetTitle(histoName.Data());
136       histo->SetDirectory(0);
137       outList->Add(histo);
138     }
139     else isOk = kFALSE;
140   }
141   for ( Int_t icount=0; icount<kNcounts; ++icount ) {
142     for ( Int_t ich=0; ich<4; ++ich ) {
143       histoName = GetHistoName(kHslatEff, icount, ich, -1, -1);
144       histoPattern = Form("%s&%s", histoName.Data(), trackSelection.Data());
145       histo = (TH1*)GetSum(physSel, trigClassNames, centrality, histoPattern);
146       if ( histo ) {
147         histo->SetName(histoName.Data());
148         histo->SetTitle(histoName.Data());
149         histo->SetDirectory(0);
150         outList->Add(histo);
151       }
152       else isOk = kFALSE;
153     }
154   }
155   for ( Int_t icount=0; icount<kNcounts; ++icount ) {
156     for ( Int_t ich=0; ich<4; ++ich ) {
157       histoName = GetHistoName(kHboardEff, icount, ich, -1, -1);
158       histoPattern = Form("%s&%s", histoName.Data(), trackSelection.Data());
159       histo = (TH1*)GetSum(physSel, trigClassNames, centrality, histoPattern);
160       if ( histo ) {
161         histo->SetName(histoName.Data());
162         histo->SetTitle(histoName.Data());
163         histo->SetDirectory(0);
164         outList->Add(histo);
165       }
166       else isOk = kFALSE;
167     }
168   }
169   
170   histoName = GetHistoName(kHcheckBoard, -1, -1, -1, -1);
171   histoPattern = Form("%s&%s", histoName.Data(), trackSelection.Data());
172   histo = (TH1*)GetSum(physSel, trigClassNames, centrality, histoPattern);
173   if ( histo ) {
174     histo->SetName(histoName.Data());
175     histo->SetTitle(histoName.Data());
176     histo->SetDirectory(0);
177     outList->Add(histo);
178   }
179   else isOk = kFALSE;
180   
181   return isOk;
182 }
183
184 //___________________________________________________________________________
185 void AliAnalysisTaskTrigChEff::FinishTaskOutput()
186 {
187   //
188   /// Merge Apt, Lpt and Hpt
189   /// Fill the final efficiency object (for backward compatibility)
190   //
191
192   TString histoName = "";
193   for ( Int_t isel=0; isel<kNselections; ++isel ) {
194     for ( Int_t itrig=0; itrig<fTriggerClasses->GetEntries(); ++itrig ) {
195       for ( Int_t icent=1; icent<=fCentralityClasses->GetNbins(); ++icent ) {
196         for ( Int_t imethod=0; imethod<kNeffMethods; ++imethod ) {
197           for ( Int_t itype=0; itype<kNhistoTypes; ++itype ) {
198             for ( Int_t icount=-1; icount<kNcounts; ++icount ) {
199               for ( Int_t ich=-1; ich<4; ++ich ) {
200                 for ( Int_t imatch=kMatchApt; imatch<kMatchHpt; ++imatch ) {
201                   TH1* histo = 0x0;
202                   for ( Int_t jmatch=imatch+1; jmatch<=kMatchHpt; ++jmatch ) {
203                     histoName = GetHistoName(itype, icount, ich, jmatch, imethod);
204                     TH1* histoAdd = (TH1*)fMergeableCollection->GetObject(Form("/%s/%s/%s/",fPhysSelKeys->At(isel)->GetName(), fTriggerClasses->At(itrig)->GetName(), fCentralityClasses->GetBinLabel(icent)), histoName);
205                     if ( ! histoAdd ) continue;
206                     histoName = GetHistoName(itype, icount, ich, imatch, imethod);
207                     if ( ! histo ) histo = (TH1*)GetMergeableObject(fPhysSelKeys->At(isel)->GetName(), fTriggerClasses->At(itrig)->GetName(), fCentralityClasses->GetBinLabel(icent), histoName);
208                     AliDebug(2,Form("Adding %s (%g) to %s (%g)", histoAdd->GetName(), histoAdd->Integral(), histo->GetName(), histo->Integral()));
209                     histo->Add(histoAdd);
210                   } // loop on higher pt matching
211                 } // loop on match trigger
212               } // loop on chamber
213             } // loop on count type
214           } // loop on histo type
215         } // loop on eff method
216       } // loop on centrality
217     } // loop on trigger classes
218   } // loop on physics selection
219
220   TString physSel = fPhysSelKeys->At(kPhysSelPass)->GetName();
221   TString trigClass = "ANY";
222   TString centrality = "all";
223   TString histoPattern = Form("%s&%s",fTrackSelKeys->At(kMatchApt)->GetName(),fEffMethodKeys->At(kEffFromTrack)->GetName());
224   
225   FillEffHistoList(physSel, trigClass, centrality, histoPattern, fList);
226
227   AliVAnalysisMuon::FinishTaskOutput();
228 }
229
230
231 //___________________________________________________________________________
232 void AliAnalysisTaskTrigChEff::InitLocalKeys()
233 {
234   //
235   /// Initialyze objects
236   //
237   
238   TString trackSelNames = "MatchNoTrackSelCut MatchApt MatchLpt MatchHpt"; 
239   fTrackSelKeys = trackSelNames.Tokenize(" ");
240   
241   TString countTypeNames = "bendPlaneCount nonBendPlaneCount bothPlanesCount allTracksCount";
242   fCountTypeKeys = countTypeNames.Tokenize(" ");
243   
244   TString histoTypeKeys = "Chamber Slat Board checkRejectedBoard";
245   fHistoTypeKeys = histoTypeKeys.Tokenize(" ");
246   
247   TString effMethodKeys = "FromTrk FromTrg";
248   fEffMethodKeys = effMethodKeys.Tokenize(" ");
249 }
250
251 //___________________________________________________________________________
252 void AliAnalysisTaskTrigChEff::MyUserCreateOutputObjects()
253 {
254   //
255   /// Create prototype objects for mergeable collection
256   //
257   
258   const Char_t* yAxisTitle = "counts";
259   
260   Int_t nChamberBins = 4;
261   Float_t chamberLow = 11.-0.5, chamberHigh = (Float_t)(nChamberBins)+11.-0.5;
262   const Char_t* chamberName = "chamber";
263   
264   Int_t nSlatBins = 18;
265   Float_t slatLow = 0.-0.5, slatHigh = (Float_t)nSlatBins-0.5;
266   const Char_t* slatName = "slat";
267   
268   Int_t nBoardBins = 234;
269   Float_t boardLow = 1.-0.5, boardHigh = (Float_t)nBoardBins+1.-0.5;
270   const Char_t* boardName = "board";
271   
272   TString baseName, histoName, histoTitle;
273   
274   TH1* histo;
275   TH2F* histo2D;
276   
277   for ( Int_t imethod=0; imethod<kNeffMethods; ++imethod ) {
278     for ( Int_t itrackSel = 0; itrackSel<kNtrackSel; ++itrackSel ) {
279       for ( Int_t icount=0; icount<kNcounts; ++icount ) {
280         histoName = GetHistoName(kHchamberEff, icount, -1, itrackSel, imethod);
281         histo = new TH1F(histoName, histoName,
282                          nChamberBins, chamberLow, chamberHigh);
283         histo->GetXaxis()->SetTitle(chamberName);
284         histo->GetYaxis()->SetTitle(yAxisTitle);
285         AddObjectToCollection(histo);
286       } // loop on counts
287       
288       for ( Int_t icount=0; icount<kNcounts; ++icount ) {
289         for ( Int_t ich=0; ich<4; ++ich ) {
290           histoName = GetHistoName(kHslatEff, icount, ich, itrackSel, imethod);
291           histo = new TH1F(histoName, histoName,
292                            nSlatBins, slatLow, slatHigh);
293           histo->GetXaxis()->SetTitle(slatName);
294           histo->GetYaxis()->SetTitle(yAxisTitle);
295           AddObjectToCollection(histo);
296         } // loop on chamber
297       } // loop on counts
298       
299       for ( Int_t icount=0; icount<kNcounts; ++icount ) {
300         for ( Int_t ich=0; ich<4; ++ich ) {
301           histoName = GetHistoName(kHboardEff, icount, ich, itrackSel, imethod);
302           histo = new TH1F(histoName, histoName,
303                            nBoardBins, boardLow, boardHigh);
304           histo->GetXaxis()->SetTitle(boardName);
305           histo->GetYaxis()->SetTitle(yAxisTitle);
306           AddObjectToCollection(histo);
307         } // loop on chamber
308       } // loop on counts
309       
310       histoName = GetHistoName(kHcheckBoard, -1, -1, itrackSel, imethod);
311       histo2D = new TH2F(histoName.Data(), "Rejected tracks motivation", 
312                          5, 20.5, 25.5, nBoardBins, boardLow, boardHigh);
313       histo2D->GetXaxis()->SetBinLabel(1,"Many pads");
314       histo2D->GetXaxis()->SetBinLabel(2,"Few pads");
315       histo2D->GetXaxis()->SetBinLabel(3,"Outside geom");
316       histo2D->GetXaxis()->SetBinLabel(4,"Tracker track");
317       histo2D->GetXaxis()->SetBinLabel(5,"Masked board");
318       histo2D->GetYaxis()->SetTitle(boardName);
319       AddObjectToCollection(histo2D);
320     } // loop on track selection
321   } // loop on eff method
322
323   fMuonTrackCuts->Print("mask");
324   
325   fList = new TList();
326   fList->SetOwner();
327   PostData(2, fList);
328
329 }
330
331 //___________________________________________________________________________
332 TString AliAnalysisTaskTrigChEff::GetHistoName(Int_t itype, Int_t icount, Int_t ichamber, Int_t itrackSel, Int_t imethod)
333 {
334   /// Get histogram index
335   TString histoName = "";
336   if ( itype < kHcheckBoard && icount >= 0 ) histoName += ((TObjString*)fCountTypeKeys->At(icount))->GetString();
337   histoName += ((TObjString*)fHistoTypeKeys->At(itype))->GetString();
338   if ( ichamber >= 0 ) histoName += Form("Ch%i", 11+ichamber);
339   if ( itrackSel >= 0 ) histoName += ((TObjString*)fTrackSelKeys->At(itrackSel))->GetString();
340   if ( imethod >= 0 ) histoName += ((TObjString*)fEffMethodKeys->At(imethod))->GetString();
341   return histoName;
342 }
343
344 //________________________________________________________________________
345 void AliAnalysisTaskTrigChEff::ProcessEvent(TString physSel, const TObjArray& selectTrigClasses, TString centrality)
346 {
347   //
348   /// Fill histogram
349   //
350
351   Int_t slat = 0, board = 0;
352   UInt_t pattern = 0;
353   TString histoName = "";
354
355   TArrayI othersEfficient(4);
356
357   AliVParticle* track = 0x0;
358
359   Int_t itrackSel = -1;
360
361   Int_t nTracks = GetNTracks();
362   for ( Int_t itrack = 0; itrack < nTracks; ++itrack ) {
363     track = GetTrack(itrack);
364
365     Bool_t matchTracker = ( fAODEvent && ((AliAODTrack*)track)->IsMuonTrack() ) || ((AliESDMuonTrack*)track)->ContainTrackerData();
366     if ( ! matchTracker && ! fUseGhosts ) continue;
367
368     Int_t matchTrig = ( fAODEvent ) ? ((AliAODTrack*)track)->GetMatchTrigger() : ((AliESDMuonTrack*)track)->GetMatchTrigger();
369     itrackSel = matchTrig;
370     UInt_t selection = fMuonTrackCuts->GetSelectionMask(track);
371     Bool_t isSelected = ( ( selection & fMuonTrackCuts->GetFilterMask() ) == fMuonTrackCuts->GetFilterMask() );
372     if ( matchTrig == 1 && ( ( selection & AliMuonTrackCuts::kMuMatchApt ) == 0 ) ) isSelected = kFALSE;
373     if ( matchTrig == 2 && ( ( selection & AliMuonTrackCuts::kMuMatchLpt ) == 0 ) ) isSelected = kFALSE;
374     if ( matchTrig == 3 && ( ( selection & AliMuonTrackCuts::kMuMatchHpt ) == 0 ) ) isSelected = kFALSE;
375     if ( ! isSelected ) itrackSel = kNoSelCutApt;
376
377     for ( Int_t imethod=0; imethod<kNeffMethods; ++imethod ) {
378       if ( imethod == kEffFromTrack ) {
379         if ( track->P() < 10. ) continue;
380         pattern = ( fAODEvent ) ? ((AliAODTrack*)track)->GetMUONTrigHitsMapTrk() :  ((AliESDMuonTrack*)track)->GetHitsPatternInTrigChTrk();
381         board = AliESDMuonTrack::GetCrossedBoard(pattern);
382       }
383       else {
384         pattern = ( fAODEvent ) ? ((AliAODTrack*)track)->GetMUONTrigHitsMapTrg() :  ((AliESDMuonTrack*)track)->GetHitsPatternInTrigCh();
385         board = ( fAODEvent ) ? AliESDMuonTrack::GetCrossedBoard(pattern) : ((AliESDMuonTrack*)track)->LoCircuit();
386       }
387       
388       Int_t effFlag = AliESDMuonTrack::GetEffFlag(pattern);
389       
390       if ( effFlag < AliESDMuonTrack::kChEff ) {
391         for ( Int_t itrig=0; itrig<selectTrigClasses.GetEntries(); ++itrig ) {
392           TString trigClassName = ((TObjString*)selectTrigClasses.At(itrig))->GetString();
393           
394           histoName = GetHistoName(kHcheckBoard, -1, -1, itrackSel, imethod);
395           ((TH2F*)GetMergeableObject(physSel, trigClassName, centrality, histoName))->Fill(AliESDMuonTrack::GetSlatOrInfo(pattern), board);
396         }
397         continue; // Track not good for efficiency calculation
398       }
399       
400       othersEfficient.Reset(1);
401       for ( Int_t cath=0; cath<2; ++cath ) {
402         for ( Int_t ich=0; ich<4; ++ich ) {
403           if ( ! AliESDMuonTrack::IsChamberHit(pattern, cath, ich) ) {
404             for ( Int_t jch=0; jch<4; jch++ ) {
405               if ( jch != ich ) othersEfficient[jch] = 0;
406             } // loop on other chambers
407             break;
408           } // if chamber not efficient
409         } // loop on chambers
410       } // loop on cathodes
411       
412       Bool_t rejectTrack = kTRUE;
413       for ( Int_t ich=0; ich<4; ++ich ) {
414         if ( othersEfficient[ich] > 0 ) {
415           rejectTrack = kFALSE;
416           break;
417         }
418       }
419       
420       if ( rejectTrack ) continue;
421       
422       slat = AliESDMuonTrack::GetSlatOrInfo(pattern);
423       
424       for ( Int_t ich=0; ich<4; ++ich ) {
425         if ( ! othersEfficient[ich] )
426           continue; // Reject track if the info of the chamber under study 
427         // is necessary to create the track itself
428         
429         Int_t iChamber = 11 + ich;
430         
431         Bool_t hitsBend = AliESDMuonTrack::IsChamberHit(pattern, 0, ich);
432         Bool_t hitsNonBend = AliESDMuonTrack::IsChamberHit(pattern, 1, ich);
433         
434         Bool_t fillHisto[kNcounts] = {
435           hitsBend,
436           hitsNonBend,
437           ( hitsBend && hitsNonBend ),
438           kTRUE
439         };
440         
441         for (Int_t icount=0; icount<kNcounts; ++icount){
442           if ( ! fillHisto[icount] ) continue;
443           for ( Int_t itrig=0; itrig<selectTrigClasses.GetEntries(); ++itrig ) {
444             TString trigClassName = ((TObjString*)selectTrigClasses.At(itrig))->GetString();
445             
446             histoName = GetHistoName(kHchamberEff, icount, -1, itrackSel, imethod);
447             ((TH1*)GetMergeableObject(physSel, trigClassName, centrality, histoName))->Fill(iChamber);
448             
449             if ( effFlag < AliESDMuonTrack::kSlatEff ) continue; // Track crossed different slats
450             histoName = GetHistoName(kHslatEff, icount, ich, itrackSel, imethod);
451             ((TH1*)GetMergeableObject(physSel, trigClassName, centrality, histoName))->Fill(slat);
452             
453             if ( effFlag < AliESDMuonTrack::kBoardEff ) continue; // Track crossed different boards
454             histoName = GetHistoName(kHboardEff, icount, ich, itrackSel, imethod);
455             ((TH1*)GetMergeableObject(physSel, trigClassName, centrality, histoName))->Fill(board);
456           } // loop on trigger classes
457         } // loop on chambers
458       } // loop on count types
459     } // loop on tracks
460   } // loop on eff methods
461   
462   PostData(2, fList);
463 }
464
465
466 //________________________________________________________________________
467 void AliAnalysisTaskTrigChEff::Terminate(Option_t *)
468 {
469   //
470   /// Draw some histogram at the end.
471   //
472
473   AliVAnalysisMuon::Terminate("");
474   
475   if ( ! fMergeableCollection ) return;
476
477   Int_t xshift = 100;
478   Int_t yshift = 20;
479   Int_t igroup1 = -1;
480   Int_t igroup2 = 0;
481
482   TObjArray* physSel =  ((TObjString*)fTerminateOptions->At(0))->GetString().Tokenize(" ");
483   physSel->SetOwner();
484   TObjArray* trigClasses = ((TObjString*)fTerminateOptions->At(1))->GetString().Tokenize(" ");
485   trigClasses->SetOwner();
486   TObjArray* centrality = ((TObjString*)fTerminateOptions->At(2))->GetString().Tokenize(" ");
487   centrality->SetOwner();
488   TString furtherOpt = ((TObjString*)fTerminateOptions->At(3))->GetString();
489
490   TString currName = "";
491   TObjArray* optArr = furtherOpt.Tokenize(" ");
492   TObjArray trackSel, methodSel;
493   trackSel.SetOwner();
494   methodSel.SetOwner();
495   TString outFileOpt = "";
496   for ( Int_t iopt=0; iopt<optArr->GetEntries(); iopt++ ) {
497     currName = optArr->At(iopt)->GetName();
498     if ( currName.Contains(".root") ) outFileOpt = currName;
499     else if ( currName.Contains("Match") ) trackSel.Add(new TObjString(currName));
500     else if ( currName.Contains("From") ) methodSel.Add(new TObjString(currName));
501   }
502   delete optArr;
503   
504   if ( trackSel.GetEntries() == 0 ) trackSel.Add(new TObjString(fTrackSelKeys->At(kMatchApt)->GetName()));
505   if ( methodSel.GetEntries() == 0 ) methodSel.Add(new TObjString(fEffMethodKeys->At(kEffFromTrack)->GetName()));
506
507   furtherOpt.ToUpper();
508   
509   Int_t chosenType = ( furtherOpt.Contains("BOARD") ) ? kHboardEff : kHslatEff;
510
511   igroup1++;
512   igroup2 = 0;
513   TString histoName = "", yAxisTitle = "";
514   
515   TH1 *num = 0x0;
516   TH1 *den = 0x0;
517   TGraphAsymmErrors* effGraph = 0x0;
518   
519   ////////////////
520   // Show tests //
521   ////////////////
522   
523   for ( Int_t icount=0; icount<kNcounts-1; ++icount ) {
524     currName = Form("%s%s_can", fHistoTypeKeys->At(chosenType)->GetName(), fCountTypeKeys->At(icount)->GetName());
525     TCanvas* can = new TCanvas(currName.Data(), currName.Data(), igroup1*xshift,igroup2*yshift,600,600);
526     can->Divide(2,2);
527     TLegend* leg = new TLegend(0.6, 0.6, 0.9, 0.9);
528     leg->SetBorderSize(1);
529     for ( Int_t ich=0; ich<4; ++ich ) {
530       TGraph* refGraph = 0x0;
531       can->cd(ich+1);
532       gPad->SetRightMargin(0.03);
533       Int_t icolor = 1;
534       Int_t istyle = 0;
535       TString drawOpt = "AP";
536       for ( Int_t isel=0; isel<physSel->GetEntries(); ++isel ) {
537         for ( Int_t itrig=0; itrig<trigClasses->GetEntries(); ++itrig ) {
538           for ( Int_t icent=0; icent<centrality->GetEntries(); ++icent ) {
539             for ( Int_t imethodSel=0; imethodSel<methodSel.GetEntries(); ++imethodSel ) {
540               for ( Int_t itrackSel=0; itrackSel<trackSel.GetEntries(); ++itrackSel ) {
541                 histoName = GetHistoName(chosenType, kAllTracks, ich, -1, -1); // partial name
542                 histoName += Form("&%s&%s",trackSel.At(itrackSel)->GetName(),methodSel.At(imethodSel)->GetName());
543                 den = (TH1*)GetSum(physSel->At(isel)->GetName(), trigClasses->At(itrig)->GetName(), centrality->At(icent)->GetName(), histoName.Data());
544                 if ( ! den ) continue;
545                 histoName = GetHistoName(chosenType, icount, ich, -1, -1); // partial name
546                 histoName += Form("&%s&%s",trackSel.At(itrackSel)->GetName(),methodSel.At(imethodSel)->GetName());
547                 num = (TH1*)GetSum(physSel->At(isel)->GetName(), trigClasses->At(itrig)->GetName(), centrality->At(icent)->GetName(), histoName.Data());
548                 if ( ! num ) continue;
549                 effGraph = new TGraphAsymmErrors(num, den);
550                 currName = Form("%s_%s_%s_%s_%s", physSel->At(isel)->GetName(), trigClasses->At(itrig)->GetName(), centrality->At(icent)->GetName(), trackSel.At(itrackSel)->GetName(), methodSel.At(imethodSel)->GetName());
551                 effGraph->SetTitle(currName.Data());
552
553                 Double_t ymin = 0.;
554                 Double_t ymax = 1.1;
555                 yAxisTitle = "Efficiency";
556
557                 if ( furtherOpt.Contains("DIFF") || furtherOpt.Contains("PULL") ) {
558                   if ( ! refGraph ) {
559                     refGraph = effGraph;
560                     continue;
561                   }
562                   Double_t currX, currY, baseX, baseY, errYlow = 0., errYhigh = 0., newY = 0.;
563                   Double_t refVal = 1., errY = 0.; 
564                   for ( Int_t ipoint=0; ipoint<effGraph->GetN(); ipoint++ ) {
565                     refGraph->GetPoint(ipoint, baseX, baseY);
566                     effGraph->GetPoint(ipoint, currX, currY);
567                     Double_t errX = effGraph->GetErrorXlow(ipoint);
568                     if ( furtherOpt.Contains("DIFF") ) {
569                       refVal = ( baseY > 0. ) ? baseY : 1.;
570                       newY = ( currY - baseY ) / refVal;
571                       Double_t errYlow1 = effGraph->GetErrorYlow(ipoint);
572                       Double_t errYlow2 = refGraph->GetErrorYlow(ipoint);
573                       Double_t errYhigh1 = effGraph->GetErrorYhigh(ipoint);
574                       Double_t errYhigh2 = refGraph->GetErrorYhigh(ipoint);
575                       errYlow = TMath::Sqrt(errYlow1*errYlow1 + errYlow2*errYlow2) / refVal;
576                       errYhigh = TMath::Sqrt(errYhigh1*errYhigh1 + errYhigh2*errYhigh2) / refVal;
577                       //yAxisTitle = Form("(%s - %s) / %s", effGraph->GetTitle(), refGraph->GetTitle(), refGraph->GetTitle());
578                       yAxisTitle = "(eff - ref ) / ref";
579                       effGraph->SetTitle(Form("Rel. diff. w.r.t. %s", refGraph->GetTitle()));
580                       ymin = -0.1;
581                       ymax = 0.1;
582                     }
583                     else if ( furtherOpt.Contains("PULL") ) {
584                       errY = 0.5 * ( effGraph->GetErrorYlow(ipoint) + effGraph->GetErrorYhigh(ipoint));
585                       newY = ( errY > 0. ) ? ( currY - baseY ) / errY : 0.;
586                       errYlow = 1.;
587                       errYhigh = 1.;
588                       //yAxisTitle = Form("( %s - %s ) / err", effGraph->GetTitle(), refGraph->GetTitle());
589                       yAxisTitle = "(eff - ref ) / err";
590                       effGraph->SetTitle(Form("Pull w.r.t. %s", refGraph->GetTitle()));
591                       ymin = -4.;
592                       ymax = 4.;
593                     }
594                     effGraph->SetPoint(ipoint, currX, newY);
595                     effGraph->SetPointError(ipoint, errX, errX, errYlow, errYhigh);
596                   } // loop on points
597                 }
598                 effGraph->GetYaxis()->SetRangeUser(ymin, ymax);
599                 effGraph->GetYaxis()->SetTitle(yAxisTitle.Data());
600                 effGraph->SetLineColor(icolor);
601                 effGraph->SetMarkerColor(icolor);
602                 effGraph->SetMarkerStyle(20 + istyle);
603                 //effGraph->SetMarkerSize(0.3);
604                 icolor++;
605                 if ( icolor == 5 || icolor == 10 ) icolor++;
606                 istyle++;
607                 effGraph->Draw(drawOpt.Data());
608                 drawOpt = "P";
609                 if ( ich < 3 ) continue;
610                 leg->AddEntry(effGraph, currName.Data(), "lp");
611               } // loop on match trigger
612             } // loop on eff method
613           } // loop on centrality
614         } // loop on trigger classes
615       } // loop on physics selection
616     } // loop on chamber
617     leg->Draw("same");
618   } // loop on count type
619   //} // loop on detection element type
620
621   delete physSel;
622   delete trigClasses;
623   delete centrality;
624   
625    
626   fList = dynamic_cast<TList*>(GetOutputData(2));
627   if ( fList ) {
628   
629     ///////////////////////////
630     // Show final efficiency //
631     ///////////////////////////
632     TString baseName[3] = {"Chamber", "RPC", "Board"};
633     Int_t baseIndex[3] = {kHchamberEff, kHslatEff, kHboardEff};
634     TString effName[kNcounts-1] = {"BendPlane", "NonBendPlane", "BothPlanes"};
635     for ( Int_t itype=0; itype<3; itype++ ) {
636       for ( Int_t icount=0; icount<kNcounts-1; icount++ ){
637         TString canName = Form("efficiencyPer%s_%s",baseName[itype].Data(),effName[icount].Data());
638         TCanvas* can = new TCanvas(canName.Data(),canName.Data(),10*(1+kNcounts*itype+icount),10*(1+kNcounts*itype+icount),310,310);
639         can->SetFillColor(10); can->SetHighLightColor(10);
640         can->SetLeftMargin(0.15); can->SetBottomMargin(0.15);  
641         if ( itype > 0 )
642           can->Divide(2,2);
643         
644         for ( Int_t ich=-1; ich<4; ich++ ) {
645           histoName = GetHistoName(baseIndex[itype], icount, ich, -1, -1);
646           num = (TH1*)fList->FindObject(histoName.Data());
647           histoName = GetHistoName(baseIndex[itype], kNcounts-1, ich, -1, -1);
648           den = (TH1*)fList->FindObject(histoName.Data());
649           if ( ! num || ! den ) continue;
650           effGraph = new TGraphAsymmErrors(num, den);
651           effGraph->GetYaxis()->SetRangeUser(0., 1.1);
652           effGraph->GetYaxis()->SetTitle("Efficiency");
653           effGraph->GetXaxis()->SetTitle(baseName[itype].Data());
654           can->cd(ich+1);
655           effGraph->Draw("AP");
656           if ( itype == 0 ) break;
657         } // loop on chamber
658       } // loop on count types
659     } // loop on histo
660   }
661
662   
663   if ( ! outFileOpt.IsNull() ) {
664     TObjArray* outFileOptList = outFileOpt.Tokenize("?");
665     AliInfo(Form("Creating file %s", outFileOptList->At(0)->GetName()));
666     TList* effList = GetEffHistoList(outFileOptList->At(1)->GetName(), outFileOptList->At(2)->GetName(), outFileOptList->At(3)->GetName(), outFileOptList->At(4)->GetName());
667     effList->SetName(GetOutputSlot(2)->GetContainer()->GetName());
668     TFile* outFile = TFile::Open(outFileOptList->At(0)->GetName(), "RECREATE");
669     effList->Write(effList->GetName(),TObject::kSingleKey);
670     outFile->Close();
671     delete effList;
672     delete outFileOptList;
673   }
674 }