]> git.uio.no Git - u/mrichter/AliRoot.git/blob - PWG3/muon/AliAnalysisTaskMuonQA.cxx
Use rapidity instead of pseudo-rapidity (better quantity when comparing with theory...
[u/mrichter/AliRoot.git] / PWG3 / muon / AliAnalysisTaskMuonQA.cxx
1 /**************************************************************************
2  * Copyright(c) 1998-1999, 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 #include <Riostream.h>
17
18 // ROOT includes
19 #include "TH1F.h"
20 #include "TH2F.h"
21 #include "TCanvas.h"
22 #include "TROOT.h"
23 #include "TString.h"
24 #include "TObjArray.h"
25 #include "TMath.h"
26 #include "TFile.h"
27 #include "TRegexp.h"
28 #include "TMap.h"
29 #include "TList.h"
30 #include "TObjString.h"
31
32 // STEER includes
33 #include "AliESDEvent.h"
34 #include "AliESDMuonTrack.h"
35 #include "AliESDMuonCluster.h"
36 #include "AliESDInputHandler.h"
37
38 // ANALYSIS includes
39 #include "AliAnalysisTaskSE.h"
40 #include "AliAnalysisDataSlot.h"
41 #include "AliAnalysisManager.h"
42 #include "AliAnalysisTaskMuonQA.h"
43 #include "AliCounterCollection.h"
44
45 ClassImp(AliAnalysisTaskMuonQA)
46
47 const Int_t AliAnalysisTaskMuonQA::nCh = 10;
48
49 const Int_t AliAnalysisTaskMuonQA::nDE = 1100;
50
51 const Float_t AliAnalysisTaskMuonQA::dMax[5] = {176.6, 229.0, 308.84, 418.2,  522.0}; // cm
52
53 //________________________________________________________________________
54 AliAnalysisTaskMuonQA::AliAnalysisTaskMuonQA() :
55   AliAnalysisTaskSE(), 
56   fList(0x0),
57   fListExpert(0x0),
58   fListNorm(0x0),
59   fTrackCounters(0x0),
60   fEventCounters(0x0),
61   fSelectCharge(0),
62   fSelectPhysics(kFALSE),
63   fSelectTrigger(kFALSE),
64   fTriggerMask(0),
65   fTriggerClass(0x0),
66   fSelectTriggerClass(0x0)
67 {
68 // Dummy constructor
69 }
70
71 //________________________________________________________________________
72 AliAnalysisTaskMuonQA::AliAnalysisTaskMuonQA(const char *name) :
73   AliAnalysisTaskSE(name), 
74   fList(0x0),
75   fListExpert(0x0),
76   fListNorm(0x0),
77   fTrackCounters(0x0),
78   fEventCounters(0x0),
79   fSelectCharge(0),
80   fSelectPhysics(kFALSE),
81   fSelectTrigger(kFALSE),
82   fTriggerMask(0),
83   fTriggerClass(0x0),
84   fSelectTriggerClass(0x0)
85 {
86   /// Constructor
87   
88   // Output slot #1 writes into a TObjArray container
89   DefineOutput(1,TObjArray::Class());
90   // Output slot #2 writes into a TObjArray container
91   DefineOutput(2,TObjArray::Class());
92   // Output slot #3 writes track counters
93   DefineOutput(3,AliCounterCollection::Class());
94   // Output slot #4 writes event counters
95   DefineOutput(4,AliCounterCollection::Class());
96   // Output slot #5 writes normalized histograms
97   DefineOutput(5,TObjArray::Class());
98 }
99
100 //________________________________________________________________________
101 AliAnalysisTaskMuonQA::~AliAnalysisTaskMuonQA()
102 {
103   /// Destructor
104   delete fList;
105   delete fListExpert;
106   delete fListNorm;
107   delete fTrackCounters;
108   delete fEventCounters;
109   delete fTriggerClass;
110   delete fSelectTriggerClass;
111 }
112
113 //___________________________________________________________________________
114 void AliAnalysisTaskMuonQA::UserCreateOutputObjects()
115 {
116   /// Create histograms and counters
117   
118   // set the list of trigger classes with corresponding short names
119   fTriggerClass = new TMap(20);
120   fTriggerClass->SetOwnerKeyValue();
121   fTriggerClass->Add(new TObjString(" CBEAMB"), new TObjString("CBEAMB"));
122   fTriggerClass->Add(new TObjString(" CINT1B-ABCE-NOPF-ALL "), new TObjString("CINT1B"));
123   fTriggerClass->Add(new TObjString(" CMUS1B-ABCE-NOPF-MUON "), new TObjString("CMUS1B"));
124   fTriggerClass->Add(new TObjString(" CINT1B-ABCE-NOPF-ALL  CMUS1B-ABCE-NOPF-MUON "), new TObjString("CINT1B+CMUS1B"));
125   fTriggerClass->Add(new TObjString(" CINT1[AC]-"), new TObjString("CINT1AC"));
126   fTriggerClass->Add(new TObjString(" CINT1-E-"), new TObjString("CINT1E"));
127   fTriggerClass->Add(new TObjString(" CMUS1[AC]-"), new TObjString("CMUS1AC"));
128   fTriggerClass->Add(new TObjString(" CMUS1-E-"), new TObjString("CMUS1E"));
129   fTriggerClass->Add(new TObjString(" CINT1-B-"), new TObjString("CINT1B"));
130   fTriggerClass->Add(new TObjString(" CMUS1-B-"), new TObjString("CMUS1B"));
131   fTriggerClass->Add(new TObjString(" CINT1-AC-"), new TObjString("CINT1AC"));
132   fTriggerClass->Add(new TObjString(" CMUS1-AC-"), new TObjString("CMUS1AC"));
133   fTriggerClass->Add(new TObjString(" CSH1-B-"), new TObjString("CSH1B"));
134   
135   // set the corresponding list of trigger key words for counters
136   TString triggerKeys = "CBEAMB/CINT1B/CMUS1B/CINT1B+CMUS1B/CINT1AC/CINT1E/CMUS1AC/CMUS1E/CSH1B/other/any";
137   
138   // set the list of trigger classes that can be selected to fill histograms (in case the physics selection is not used)
139   fSelectTriggerClass = new TList();
140   fSelectTriggerClass->SetOwner();
141   fSelectTriggerClass->AddLast(new TObjString(" CINT1B-ABCE-NOPF-ALL ")); fSelectTriggerClass->Last()->SetUniqueID(AliVEvent::kMB);
142   fSelectTriggerClass->AddLast(new TObjString(" CMUS1B-ABCE-NOPF-MUON ")); fSelectTriggerClass->Last()->SetUniqueID(AliVEvent::kMUON);
143   fSelectTriggerClass->AddLast(new TObjString(" CINT1-B-")); fSelectTriggerClass->Last()->SetUniqueID(AliVEvent::kMB);
144   fSelectTriggerClass->AddLast(new TObjString(" CMUS1-B-")); fSelectTriggerClass->Last()->SetUniqueID(AliVEvent::kMUON);
145   fSelectTriggerClass->AddLast(new TObjString(" CSH1-B-")); fSelectTriggerClass->Last()->SetUniqueID(AliVEvent::kHighMult);
146   
147   // create histograms
148   fList = new TObjArray(2000);
149   fList->SetOwner();
150   fListExpert = new TObjArray(2000);
151   fListExpert->SetOwner();
152   
153   // track info
154   TH1F* hNTracks = new TH1F("hNTracks", "number of tracks;n_{tracks}", 20, 0., 20.);
155   fList->AddAtAndExpand(hNTracks, kNTracks);
156   
157   TH1F* hMatchTrig = new TH1F("hMatchTrig", "number of tracks matched with trigger;n_{tracks}", 20, 0., 20.);
158   fList->AddAtAndExpand(hMatchTrig, kMatchTrig);
159   
160   TH1F* hSign = new TH1F("hSign", "track sign;sign", 3, -1.5, 1.5);
161   fList->AddAtAndExpand(hSign, kSign);
162   
163   TH1F* hDCA = new TH1F("hDCA", "DCA distribution;DCA (cm)", 500, 0., 500.);
164   fList->AddAtAndExpand(hDCA, kDCA);
165   
166   TH1F* hP = new TH1F("hP", "momentum distribution;p (GeV/c)", 300, 0., 300.);
167   fList->AddAtAndExpand(hP, kP);
168   
169   TH1F* hPMuPlus = new TH1F("hPMuPlus", "momentum distribution of #mu^{+};p (GeV/c)", 300, 0., 300.);
170   fList->AddAtAndExpand(hPMuPlus, kPMuPlus);
171   
172   TH1F* hPMuMinus = new TH1F("hPMuMinus", "momentum distribution of #mu^{-};p (GeV/c)", 300, 0., 300.);
173   fList->AddAtAndExpand(hPMuMinus, kPMuMinus);
174   
175   TH1F* hPt = new TH1F("hPt", "transverse momentum distribution;p_{t} (GeV/c)", 300, 0., 30);
176   fList->AddAtAndExpand(hPt, kPt);
177   
178   TH1F* hPtMuPlus = new TH1F("hPtMuPlus", "transverse momentum distribution of #mu^{+};p_{t} (GeV/c)", 300, 0., 30);
179   fList->AddAtAndExpand(hPtMuPlus, kPtMuPlus);
180   
181   TH1F* hPtMuMinus = new TH1F("hPtMuMinus", "transverse momentum distribution of #mu^{-};p_{t} (GeV/c)", 300, 0., 30);
182   fList->AddAtAndExpand(hPtMuMinus, kPtMuMinus);
183   
184   TH1F* hRapidity = new TH1F("hRapidity", "rapidity distribution;rapidity", 200, -4.5, -2.);
185   fList->AddAtAndExpand(hRapidity, kRapidity);
186   
187   TH1F* hThetaX = new TH1F("hThetaX", "#theta_{X} distribution;#theta_{X} (degree)", 360, -180., 180);
188   fList->AddAtAndExpand(hThetaX, kThetaX);
189   
190   TH1F* hThetaY = new TH1F("hThetaY", "#theta_{Y} distribution;#theta_{Y} (degree)", 360, -180., 180);
191   fList->AddAtAndExpand(hThetaY, kThetaY);
192   
193   TH1F* hChi2 = new TH1F("hChi2", "normalized #chi^{2} distribution;#chi^{2} / ndf", 500, 0., 50.);
194   fList->AddAtAndExpand(hChi2, kChi2);
195   
196   TH1F* hProbChi2 = new TH1F("hProbChi2", "distribution of probability of #chi^{2};prob(#chi^{2})", 100, 0., 1.);
197   fList->AddAtAndExpand(hProbChi2, kProbChi2);
198   
199   // cluster info
200   TH1F* hNClustersPerTrack = new TH1F("hNClustersPerTrack", "number of associated clusters per track;n_{clusters}", 20, 0., 20.);
201   fList->AddAtAndExpand(hNClustersPerTrack, kNClustersPerTrack);
202   
203   TH1F* hNChamberHitPerTrack = new TH1F("hNChamberHitPerTrack", "number of chambers hit per track;n_{chamber hit}", 15, 0., 15.);
204   fList->AddAtAndExpand(hNChamberHitPerTrack, kNChamberHitPerTrack);
205   
206   TH1F* hNClustersPerCh = new TH1F("hNClustersPerCh", "averaged number of clusters per chamber per track;chamber ID;<n_{clusters}>", nCh, -0.5, nCh-0.5);
207   hNClustersPerCh->Sumw2();
208   hNClustersPerCh->SetOption("P");
209   hNClustersPerCh->SetMarkerStyle(kFullDotMedium);
210   hNClustersPerCh->SetMarkerColor(kBlue);
211   fListExpert->AddAtAndExpand(hNClustersPerCh, kNClustersPerCh);
212   
213   TH1F* hNClustersPerDE = new TH1F("hNClustersPerDE", "averaged number of clusters per DE per track;DetElem ID;<n_{clusters}>", nDE+1, -0.5, nDE+0.5);
214   hNClustersPerDE->Sumw2();
215   hNClustersPerDE->SetOption("P");
216   hNClustersPerDE->SetMarkerStyle(kFullDotMedium);
217   hNClustersPerDE->SetMarkerColor(kBlue);
218   fListExpert->AddAtAndExpand(hNClustersPerDE, kNClustersPerDE);
219   
220   for (Int_t i = 0; i < nCh; i++) {
221     Float_t rMax = 0.5*dMax[i/2];
222     TH2F* hClusterHitMapInCh = new TH2F(Form("hClusterHitMapInCh%d",i+1), Form("cluster position distribution in chamber %d;X (cm);Y (cm)",i+1),
223                                        100, -rMax, rMax, 100, -rMax, rMax);
224     fListExpert->AddAtAndExpand(hClusterHitMapInCh, kClusterHitMapInCh+i);
225     
226     TH1F* hClusterChargeInCh = new TH1F(Form("hClusterChargeInCh%d",i+1), Form("cluster charge distribution in chamber %d;charge (fC)",i+1), 100, 0., 1000.);
227     fListExpert->AddAtAndExpand(hClusterChargeInCh, kClusterChargeInCh+i);
228     
229     TH1F* hClusterSizeInCh = new TH1F(Form("hClusterSizeInCh%d",i+1), Form("cluster size distribution in chamber %d;size (n_{pads})",i+1), 200, 0., 200.);
230     fListExpert->AddAtAndExpand(hClusterSizeInCh, kClusterSizeInCh+i);
231   }
232   
233   TH2F* hClusterChargePerDE = new TH2F("hClusterChargePerDE", "cluster charge distribution per DE;DetElem ID;charge (fC)", nDE+1, -0.5, nDE+0.5, 100, 0., 1000.);
234   fListExpert->AddAtAndExpand(hClusterChargePerDE, kClusterChargePerDE);
235   
236   TH2F* hClusterSizePerDE = new TH2F("hClusterSizePerDE", "cluster size distribution per DE;DetElem ID;size (n_{pads})", nDE+1, -0.5, nDE+0.5, 200, 0., 200.);
237   fListExpert->AddAtAndExpand(hClusterSizePerDE, kClusterSizePerDE);
238   
239   // initialize track counters
240   fTrackCounters = new AliCounterCollection("trackCounters");
241   fTrackCounters->AddRubric("track", "trackeronly/triggeronly/matched");
242   fTrackCounters->AddRubric("trigger", triggerKeys.Data());
243   fTrackCounters->AddRubric("run", 1000000);
244   fTrackCounters->AddRubric("selected", "yes/no");
245   fTrackCounters->AddRubric("triggerRO", "good/bad");
246   fTrackCounters->AddRubric("charge", "pos/neg/any");
247   fTrackCounters->AddRubric("pt", "low/high/any");
248   fTrackCounters->Init();
249   
250   // initialize event counters
251   fEventCounters = new AliCounterCollection("eventCounters");
252   fEventCounters->AddRubric("event", "muon/any");
253   fEventCounters->AddRubric("trigger", triggerKeys.Data());
254   fEventCounters->AddRubric("run", 1000000);
255   fEventCounters->AddRubric("selected", "yes/no");
256   fEventCounters->AddRubric("triggerRO", "good/bad");
257   fEventCounters->Init();
258   
259   // Post data at least once per task to ensure data synchronisation (required for merging)
260   PostData(1, fList);
261   PostData(2, fListExpert);
262   PostData(3, fTrackCounters);
263   PostData(4, fEventCounters);
264 }
265
266 //________________________________________________________________________
267 void AliAnalysisTaskMuonQA::UserExec(Option_t *)
268 {
269   /// Called for each event
270   
271   AliESDEvent* fESD = dynamic_cast<AliESDEvent*>(InputEvent());
272   if (!fESD) {
273     Printf("ERROR: fESD not available");
274     return;
275   }
276   
277   // check physics selection
278   UInt_t triggerWord = (fInputHandler) ? fInputHandler->IsEventSelected() : 0;
279   Bool_t isPhysicsSelected = (triggerWord != 0);
280   TString selected = isPhysicsSelected ? "selected:yes" : "selected:no";
281   
282   // check trigger selection 
283   TString FiredTriggerClasses = fESD->GetFiredTriggerClasses();
284   if (!fSelectPhysics) triggerWord = BuildTriggerWord(FiredTriggerClasses);
285   Bool_t isTriggerSelected = ((triggerWord & fTriggerMask) != 0);
286   
287   // first loop over tracks to check for trigger readout problem
288   Int_t nTracks = (Int_t) fESD->GetNumberOfMuonTracks();
289   Int_t nTriggerTracks = 0;
290   for (Int_t iTrack = 0; iTrack < nTracks; ++iTrack)
291     if (fESD->GetMuonTrack(iTrack)->ContainTriggerData()) nTriggerTracks++;
292   TString triggerRO = (nTriggerTracks < 10) ? "triggerRO:good" : "triggerRO:bad";
293   
294   // --- fill event counters ---
295   
296   // build the list of trigger cases
297   TList* triggerCases = BuildListOfTriggerCases(FiredTriggerClasses);
298   
299   // loop over trigger cases
300   TObjString* triggerKey = 0x0;
301   TIter nextTriggerCase(triggerCases);
302   while ((triggerKey = static_cast<TObjString*>(nextTriggerCase()))) {
303     
304     // any event
305     fEventCounters->Count(Form("event:any/%s/run:%d/%s/%s", triggerKey->GetName(), fCurrentRunNumber, selected.Data(), triggerRO.Data()));
306     
307     // muon event
308     if (nTracks > 0) fEventCounters->Count(Form("event:muon/%s/run:%d/%s/%s", triggerKey->GetName(), fCurrentRunNumber, selected.Data(), triggerRO.Data()));
309       
310   }
311   
312   // second loop over tracks to fill histograms and track counters
313   Int_t nSelectedTrackerTracks = 0;
314   Int_t nSelectedTrackMatchTrig = 0;
315   Int_t nPVTracks = fESD->GetPrimaryVertex()->GetNContributors();
316   for (Int_t iTrack = 0; iTrack < nTracks; ++iTrack) {
317     
318     // get the ESD track
319     AliESDMuonTrack* esdTrack = fESD->GetMuonTrack(iTrack);
320     
321     // --- fill track counters ---
322     
323     // define the key words
324     TString trackKey = "track:";
325     TString chargeKey = "charge:";
326     Bool_t lowPt = kFALSE;
327     Bool_t highPt = kFALSE;
328     if (esdTrack->ContainTrackerData()) {
329       
330       if (esdTrack->ContainTriggerData()) trackKey += "matched";
331       else  trackKey += "trackeronly";
332       
333       Short_t trackCharge = esdTrack->Charge();
334       if (trackCharge < 0) chargeKey += "neg";
335       else chargeKey += "pos";
336       
337       Double_t thetaTrackAbsEnd = TMath::ATan(esdTrack->GetRAtAbsorberEnd()/505.) * TMath::RadToDeg();
338       Double_t trackPt = esdTrack->Pt();
339       if (trackPt > 1. && nPVTracks>0 && thetaTrackAbsEnd>2. ) lowPt = kTRUE;
340       if (trackPt > 2. && nPVTracks>0 && thetaTrackAbsEnd>2. ) highPt = kTRUE;
341       
342     } else {
343       
344       trackKey += "triggeronly";
345       chargeKey = "";
346       
347     }
348     
349     // loop over trigger cases and fill counters
350     nextTriggerCase.Reset();
351     while ((triggerKey = static_cast<TObjString*>(nextTriggerCase()))) {
352       
353       // any charge / any pt
354       fTrackCounters->Count(Form("%s/%s/run:%d/%s/%s/charge:any/pt:any", trackKey.Data(), triggerKey->GetName(), fCurrentRunNumber, selected.Data(), triggerRO.Data()));
355       
356       // any charge / specific pt
357       if (lowPt) fTrackCounters->Count(Form("%s/%s/run:%d/%s/%s/charge:any/pt:low", trackKey.Data(), triggerKey->GetName(), fCurrentRunNumber, selected.Data(), triggerRO.Data()));
358       if (highPt) fTrackCounters->Count(Form("%s/%s/run:%d/%s/%s/charge:any/pt:high", trackKey.Data(), triggerKey->GetName(), fCurrentRunNumber, selected.Data(), triggerRO.Data()));
359       
360       if (!chargeKey.IsNull()) {
361         
362         // specific charge / any pt
363         fTrackCounters->Count(Form("%s/%s/run:%d/%s/%s/%s/pt:any", trackKey.Data(), triggerKey->GetName(), fCurrentRunNumber, selected.Data(), triggerRO.Data(), chargeKey.Data()));
364         
365         // specific charge / specific pt
366         if (lowPt) fTrackCounters->Count(Form("%s/%s/run:%d/%s/%s/%s/pt:low", trackKey.Data(), triggerKey->GetName(), fCurrentRunNumber, selected.Data(), triggerRO.Data(), chargeKey.Data()));
367         if (highPt) fTrackCounters->Count(Form("%s/%s/run:%d/%s/%s/%s/pt:high", trackKey.Data(), triggerKey->GetName(), fCurrentRunNumber, selected.Data(), triggerRO.Data(), chargeKey.Data()));
368         
369       }
370       
371     }
372     
373     // --- apply selections and fill histograms with selected tracks ---
374     
375     // remove "ghost"
376     if (!esdTrack->ContainTrackerData()) continue;
377     
378     // select on "physics" before filling histograms
379     if (fSelectPhysics && !isPhysicsSelected) continue;
380     
381     // select on trigger before filling histograms
382     if (fSelectTrigger && !isTriggerSelected) continue;
383     
384     // select on track charge
385     if (fSelectCharge*esdTrack->Charge() < 0) continue;
386     
387     nSelectedTrackerTracks++;
388     if (esdTrack->ContainTriggerData()) nSelectedTrackMatchTrig++;
389     
390     Double_t trackP = esdTrack->P();
391     Double_t trackPt = esdTrack->Pt();
392     Short_t trackCharge = esdTrack->Charge();
393     ((TH1F*)fList->UncheckedAt(kP))->Fill(trackP);
394     ((TH1F*)fList->UncheckedAt(kPt))->Fill(trackPt);
395     if (trackCharge < 0) {
396       ((TH1F*)fList->UncheckedAt(kPMuMinus))->Fill(trackP);
397       ((TH1F*)fList->UncheckedAt(kPtMuMinus))->Fill(trackPt);
398     } else {
399       ((TH1F*)fList->UncheckedAt(kPMuPlus))->Fill(trackP);
400       ((TH1F*)fList->UncheckedAt(kPtMuPlus))->Fill(trackPt);
401     }
402     ((TH1F*)fList->UncheckedAt(kRapidity))->Fill(esdTrack->Y());
403     Int_t ndf = 2 * esdTrack->GetNHit() - 5;
404     ((TH1F*)fList->UncheckedAt(kChi2))->Fill(esdTrack->GetChi2()/ndf);
405     ((TH1F*)fList->UncheckedAt(kProbChi2))->Fill(TMath::Prob(esdTrack->GetChi2(),ndf));
406     ((TH1F*)fList->UncheckedAt(kThetaX))->Fill(ChangeThetaRange(esdTrack->GetThetaXUncorrected()));
407     ((TH1F*)fList->UncheckedAt(kThetaY))->Fill(ChangeThetaRange(esdTrack->GetThetaYUncorrected()));
408     ((TH1F*)fList->UncheckedAt(kNClustersPerTrack))->Fill(esdTrack->GetNHit());
409     ((TH1F*)fList->UncheckedAt(kSign))->Fill(trackCharge);
410     ((TH1F*)fList->UncheckedAt(kDCA))->Fill(esdTrack->GetDCA());
411     
412     Int_t nChamberHit = 0;
413     for (Int_t ich=0; ich<10; ich++) if (esdTrack->IsInMuonClusterMap(ich)) nChamberHit++;
414     ((TH1F*)fList->UncheckedAt(kNChamberHitPerTrack))->Fill(nChamberHit);
415     
416     // what follows concern clusters
417     if(!esdTrack->ClustersStored()) continue;
418     
419     AliESDMuonCluster *esdCluster = (AliESDMuonCluster*) esdTrack->GetClusters().First();
420     while (esdCluster) {
421       
422       Int_t chId = esdCluster->GetChamberId();
423       Int_t deId = esdCluster->GetDetElemId();
424       
425       ((TH1F*)fListExpert->UncheckedAt(kNClustersPerCh))->Fill(chId);
426       ((TH1F*)fListExpert->UncheckedAt(kNClustersPerDE))->Fill(deId);
427       
428       ((TH1F*)fListExpert->UncheckedAt(kClusterHitMapInCh+chId))->Fill(esdCluster->GetX(), esdCluster->GetY());
429       
430       ((TH1F*)fListExpert->UncheckedAt(kClusterChargeInCh+chId))->Fill(esdCluster->GetCharge());
431       ((TH1F*)fListExpert->UncheckedAt(kClusterChargePerDE))->Fill(deId, esdCluster->GetCharge());
432       
433       if (esdCluster->PadsStored()) { // discard clusters with pad not stored in ESD
434         ((TH1F*)fListExpert->UncheckedAt(kClusterSizeInCh+chId))->Fill(esdCluster->GetNPads());
435         ((TH1F*)fListExpert->UncheckedAt(kClusterSizePerDE))->Fill(deId, esdCluster->GetNPads());
436       }
437       
438       esdCluster = (AliESDMuonCluster*) esdTrack->GetClusters().After(esdCluster);
439     }
440     
441   }
442   
443   if ((!fSelectPhysics || isPhysicsSelected) && (!fSelectTrigger || isTriggerSelected)) {
444     ((TH1F*)fList->UncheckedAt(kNTracks))->Fill(nSelectedTrackerTracks);
445     ((TH1F*)fList->UncheckedAt(kMatchTrig))->Fill(nSelectedTrackMatchTrig);
446   }
447   
448   // clean memory
449   delete triggerCases;
450   
451   // Post final data. It will be written to a file with option "RECREATE"
452   PostData(1, fList);
453   PostData(2, fListExpert);
454   PostData(3, fTrackCounters);
455   PostData(4, fEventCounters);
456 }
457
458 //________________________________________________________________________
459 void AliAnalysisTaskMuonQA::Terminate(Option_t *)
460 {
461   /// Normalize histograms
462   /// Draw result to the screen
463   /// Print statistics
464   
465   // global statistic
466   fTrackCounters = static_cast<AliCounterCollection*>(GetOutputData(3));
467   fEventCounters = static_cast<AliCounterCollection*>(GetOutputData(4));
468   if (fTrackCounters && fEventCounters) {
469     if (!gROOT->IsBatch()) {
470       cout<<"whole statistics without selection:"<<endl;
471       fEventCounters->Print("trigger/event");
472       fTrackCounters->Print("trigger/track");
473       cout<<"whole statistics of selected events:"<<endl;
474       fEventCounters->Print("trigger/event","selected:yes");
475       fTrackCounters->Print("trigger/track","selected:yes");
476       new TCanvas();
477       fEventCounters->Draw("event","trigger","");
478       new TCanvas();
479       fTrackCounters->Draw("track","trigger","");
480       new TCanvas();
481       fEventCounters->Draw("event","trigger","selected:yes");
482       new TCanvas();
483       fTrackCounters->Draw("track","trigger","selected:yes");
484     }
485   }
486   
487   // recover output histograms
488   fList = static_cast<TObjArray*>(GetOutputData(1));
489   fListExpert = static_cast<TObjArray*>(GetOutputData(2));
490   if (!fList || !fListExpert) return;
491   
492   // create summary plots
493   fListNorm = new TObjArray(1000);
494   fListNorm->SetOwner();
495   
496   // mean/dispersion of cluster charge per chamber/DE
497   TH1F* hClusterChargePerChMean = new TH1F("hClusterChargePerChMean", "cluster mean charge per chamber;chamber ID;<charge> (fC)", nCh, -0.5, nCh-0.5);
498   hClusterChargePerChMean->SetOption("P");
499   hClusterChargePerChMean->SetMarkerStyle(kFullDotMedium);
500   hClusterChargePerChMean->SetMarkerColor(kBlue);
501   fListNorm->AddAtAndExpand(hClusterChargePerChMean, kClusterChargePerChMean);
502   
503   TH1F* hClusterChargePerChSigma = new TH1F("hClusterChargePerChSigma", "cluster charge dispersion per chamber;chamber ID;#sigma_{charge} (fC)", nCh, -0.5, nCh-0.5);
504   hClusterChargePerChSigma->SetOption("P");
505   hClusterChargePerChSigma->SetMarkerStyle(kFullDotMedium);
506   hClusterChargePerChSigma->SetMarkerColor(kBlue);
507   fListNorm->AddAtAndExpand(hClusterChargePerChSigma, kClusterChargePerChSigma);
508   
509   TH1F* hClusterChargePerDEMean = new TH1F("hClusterChargePerDEMean", "cluster mean charge per DE;DetElem ID;<charge> (fC)", nDE+1, -0.5, nDE+0.5);
510   hClusterChargePerDEMean->SetOption("P");
511   hClusterChargePerDEMean->SetMarkerStyle(kFullDotMedium);
512   hClusterChargePerDEMean->SetMarkerColor(kBlue);
513   fListNorm->AddAtAndExpand(hClusterChargePerDEMean, kClusterChargePerDEMean);
514   
515   TH1F* hClusterChargePerDESigma = new TH1F("hClusterChargePerDESigma", "cluster charge dispersion per DE;DetElem ID;#sigma_{charge} (fC)", nDE+1, -0.5, nDE+0.5);
516   hClusterChargePerDESigma->SetOption("P");
517   hClusterChargePerDESigma->SetMarkerStyle(kFullDotMedium);
518   hClusterChargePerDESigma->SetMarkerColor(kBlue);
519   fListNorm->AddAtAndExpand(hClusterChargePerDESigma, kClusterChargePerDESigma);
520   
521   // mean/dispersion of cluster size per chamber/DE
522   TH1F* hClusterSizePerChMean = new TH1F("hClusterSizePerChMean", "cluster mean size per chamber;chamber ID;<size> (n_{pads})", nCh, -0.5, nCh-0.5);
523   hClusterSizePerChMean->SetOption("P");
524   hClusterSizePerChMean->SetMarkerStyle(kFullDotMedium);
525   hClusterSizePerChMean->SetMarkerColor(kBlue);
526   fListNorm->AddAtAndExpand(hClusterSizePerChMean, kClusterSizePerChMean);
527   
528   TH1F* hClusterSizePerChSigma = new TH1F("hClusterSizePerChSigma", "cluster size dispersion per chamber;chamber ID;#sigma_{size} (n_{pads})", nCh, -0.5, nCh-0.5);
529   hClusterSizePerChSigma->SetOption("P");
530   hClusterSizePerChSigma->SetMarkerStyle(kFullDotMedium);
531   hClusterSizePerChSigma->SetMarkerColor(kBlue);
532   fListNorm->AddAtAndExpand(hClusterSizePerChSigma, kClusterSizePerChSigma);
533   
534   TH1F* hClusterSizePerDEMean = new TH1F("hClusterSizePerDEMean", "cluster mean size per DE;DetElem ID;<size> (n_{pads})", nDE+1, -0.5, nDE+0.5);
535   hClusterSizePerDEMean->SetOption("P");
536   hClusterSizePerDEMean->SetMarkerStyle(kFullDotMedium);
537   hClusterSizePerDEMean->SetMarkerColor(kBlue);
538   fListNorm->AddAtAndExpand(hClusterSizePerDEMean, kClusterSizePerDEMean);
539   
540   TH1F* hClusterSizePerDESigma = new TH1F("hClusterSizePerDESigma", "cluster size dispersion per DE;DetElem ID;#sigma_{size} (n_{pads})", nDE+1, -0.5, nDE+0.5);
541   hClusterSizePerDESigma->SetOption("P");
542   hClusterSizePerDESigma->SetMarkerStyle(kFullDotMedium);
543   hClusterSizePerDESigma->SetMarkerColor(kBlue);
544   fListNorm->AddAtAndExpand(hClusterSizePerDESigma, kClusterSizePerDESigma);
545   
546   // normalize histograms
547   Float_t nTracks = ((TH1F*)fList->UncheckedAt(kNClustersPerTrack))->GetEntries();
548   if (nTracks > 0.) {
549     ((TH1F*)fListExpert->UncheckedAt(kNClustersPerCh))->Scale(1./nTracks);
550     ((TH1F*)fListExpert->UncheckedAt(kNClustersPerDE))->Scale(1./nTracks);
551     fListNorm->AddAtAndExpand(((TH1F*)fListExpert->UncheckedAt(kNClustersPerCh))->Clone(), kNClustersPerChPerTrack);
552     fListNorm->AddAtAndExpand(((TH1F*)fListExpert->UncheckedAt(kNClustersPerDE))->Clone(), kNClustersPerDEPerTrack);
553   }
554   
555   // fill summary plots per chamber
556   for (Int_t iCh = 0; iCh < nCh; iCh++) {
557     
558     TH1* hClusterChargeInCh = ((TH1F*)fListExpert->UncheckedAt(kClusterChargeInCh+iCh));
559     hClusterChargePerChMean->SetBinContent(iCh+1, hClusterChargeInCh->GetMean());
560     hClusterChargePerChMean->SetBinError(iCh+1, hClusterChargeInCh->GetMeanError());
561     hClusterChargePerChSigma->SetBinContent(iCh+1, hClusterChargeInCh->GetRMS());
562     hClusterChargePerChSigma->SetBinError(iCh+1, hClusterChargeInCh->GetRMSError());
563     
564     TH1* hClusterSizeInCh = ((TH1F*)fListExpert->UncheckedAt(kClusterSizeInCh+iCh));
565     hClusterSizePerChMean->SetBinContent(iCh+1, hClusterSizeInCh->GetMean());
566     hClusterSizePerChMean->SetBinError(iCh+1, hClusterSizeInCh->GetMeanError());
567     hClusterSizePerChSigma->SetBinContent(iCh+1, hClusterSizeInCh->GetRMS());
568     hClusterSizePerChSigma->SetBinError(iCh+1, hClusterSizeInCh->GetRMSError());
569     
570   }
571   
572   // fill summary plots per DE
573   TH2F* hClusterChargePerDE = ((TH2F*)fListExpert->UncheckedAt(kClusterChargePerDE));
574   TH2F* hClusterSizePerDE = ((TH2F*)fListExpert->UncheckedAt(kClusterSizePerDE));
575   for (Int_t iDE = 1; iDE < nDE+1; iDE++) {
576     
577     TH1D *tmp = hClusterChargePerDE->ProjectionY("tmp",iDE,iDE,"e");
578     if (tmp->GetEntries() > 10.) {
579       hClusterChargePerDEMean->SetBinContent(iDE, tmp->GetMean());
580       hClusterChargePerDEMean->SetBinError(iDE, tmp->GetMeanError());
581       hClusterChargePerDESigma->SetBinContent(iDE, tmp->GetRMS());
582       hClusterChargePerDESigma->SetBinError(iDE, tmp->GetRMSError());
583     }
584     delete tmp;
585     
586     tmp = hClusterSizePerDE->ProjectionY("tmp",iDE,iDE,"e");
587     if (tmp->GetEntries() > 10.) {
588       hClusterSizePerDEMean->SetBinContent(iDE, tmp->GetMean());
589       hClusterSizePerDEMean->SetBinError(iDE, tmp->GetMeanError());
590       hClusterSizePerDESigma->SetBinContent(iDE, tmp->GetRMS());
591       hClusterSizePerDESigma->SetBinError(iDE, tmp->GetRMSError());
592     }
593     delete tmp;
594     
595   }
596   
597   // Post summary data.
598   PostData(5, fListNorm);
599 }
600
601 //________________________________________________________________________
602 Double_t AliAnalysisTaskMuonQA::ChangeThetaRange(Double_t theta)
603 {
604   /// set theta range from -180 to +180 degrees
605   if(theta < -2.5) return (theta / TMath::Pi() + 1.) * 180.;
606   else if(theta > 2.5) return (theta / TMath::Pi() - 1.) * 180.;
607   else return theta / TMath::Pi() * 180.;
608 }
609
610 //________________________________________________________________________
611 UInt_t AliAnalysisTaskMuonQA::BuildTriggerWord(TString& FiredTriggerClasses)
612 {
613   /// build the trigger word from the fired trigger classes and the list of selectable trigger
614   
615   UInt_t word = 0;
616   
617   TObjString* trigClasseName = 0x0;
618   TIter nextTrigger(fSelectTriggerClass);
619   while ((trigClasseName = static_cast<TObjString*>(nextTrigger()))) {
620     
621     TRegexp GenericTriggerClasseName(trigClasseName->String());
622     if (FiredTriggerClasses.Contains(GenericTriggerClasseName)) word |= trigClasseName->GetUniqueID();
623     
624   }
625   
626   return word;
627 }
628
629 //________________________________________________________________________
630 TList* AliAnalysisTaskMuonQA::BuildListOfTriggerCases(TString& FiredTriggerClasses)
631 {
632   /// build the list of trigger for the counters from the fired trigger classes and the list of trigger classes
633   /// returned TList must be deleted by user
634   
635   TList* list = new TList();
636   list->SetOwner();
637   
638   // add case any
639   list->AddLast(new TObjString("trigger:any"));
640   
641   TObjString* trigClasseName = 0x0;
642   TIter nextTrigger(fTriggerClass);
643   while ((trigClasseName = static_cast<TObjString*>(nextTrigger()))) {
644     
645     TRegexp GenericTriggerClasseName(trigClasseName->String());
646     if (FiredTriggerClasses.Contains(GenericTriggerClasseName)) {
647       
648       // add specific trigger case
649       TObjString* trigShortName = static_cast<TObjString*>(fTriggerClass->GetValue(trigClasseName));
650       list->AddLast(new TObjString(Form("trigger:%s",trigShortName->GetName())));
651       
652     }
653     
654   }
655   
656   // add case other if no specific trigger was found
657   if (list->GetSize() == 1) list->AddLast(new TObjString("trigger:other"));
658   
659   return list;
660 }
661