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