]> git.uio.no Git - u/mrichter/AliRoot.git/blame - PWGPP/TPC/AliTPCPIDEtaTree.cxx
Correcly handle centrality bins (Diego)
[u/mrichter/AliRoot.git] / PWGPP / TPC / AliTPCPIDEtaTree.cxx
CommitLineData
88b71b9f 1#include "TChain.h"
2#include "TTree.h"
3#include "TF1.h"
4#include "TAxis.h"
5#include "TH2I.h"
6
7#include "THnSparse.h"
8
9#include "AliMCParticle.h"
10//#include "AliStack.h"
11
12#include "AliAnalysisTask.h"
13#include "AliAnalysisManager.h"
14
15#include "AliESDEvent.h"
16#include "AliMCEvent.h"
17#include "AliESDInputHandler.h"
18#include "AliInputEventHandler.h"
19
20#include "AliVVertex.h"
21#include "AliAnalysisFilter.h"
22#include "AliPID.h"
23#include "AliPIDResponse.h"
24#include "AliTPCPIDResponse.h"
25//#include "AliTPCParamSR.h"
26
27#include "AliTPCPIDEtaTree.h"
28
29/*
30This task determines the eta dependence of the TPC signal.
31For this purpose, only tracks fulfilling some standard quality cuts are taken into account.
32The obtained data can be used to derive the functional behaviour of the eta dependence.
33Such a function can be plugged into this task to correct for the eta dependence and to see
34if there is then really no eta dependence left.
35
36Class written by Benjamin Hess.
37Contact: bhess@cern.ch
38*/
39
40ClassImp(AliTPCPIDEtaTree)
41
42//________________________________________________________________________
43AliTPCPIDEtaTree::AliTPCPIDEtaTree()
caa5a9ed 44 : AliTPCPIDBase()
f310f95e 45 , fNumEtaCorrReqErrorsIssued(0)
46 , fNumMultCorrReqErrorsIssued(0)
88b71b9f 47 , fStoreMultiplicity(kFALSE)
48 , fStoreNumOfSubthresholdclusters(kFALSE)
49 , fStoreNumClustersInActiveVolume(kFALSE)
50 , fDoAdditionalQA(kFALSE)
51 , fPtpcPionCut(1.0)
52 , fPtpc(0)
53 , fPt(0)
54 , fDeDx(0)
55 , fDeDxExpected(0)
56 , fTanTheta(0)
57 //, fSinAlpha(0)
58 //, fY(0)
59 , fPhiPrime(0)
60 , fTPCsignalN(0)
61 , fTPCsignalNsubthreshold(0)
62 , fNumTPCClustersInActiveVolume(0)
63 , fPIDtype(0)
64 , fMultiplicity(0)
65 , fCorrectdEdxEtaDependence(kFALSE)
66 , fCorrectdEdxMultiplicityDependence(kFALSE)
67 , fTree(0x0)
68 , fTreePions(0x0)
69 , fOutputContainer(0x0)
70 , fhTOFqa(0x0)
71 , fhMultiplicityQA(0x0)
72{
73 // default Constructor
74}
75
76//________________________________________________________________________
77AliTPCPIDEtaTree::AliTPCPIDEtaTree(const char *name)
caa5a9ed 78 : AliTPCPIDBase(name)
f310f95e 79 , fNumEtaCorrReqErrorsIssued(0)
80 , fNumMultCorrReqErrorsIssued(0)
88b71b9f 81 , fStoreMultiplicity(kFALSE)
82 , fStoreNumOfSubthresholdclusters(kFALSE)
83 , fStoreNumClustersInActiveVolume(kFALSE)
84 , fDoAdditionalQA(kFALSE)
85 , fPtpcPionCut(1.0)
86 , fPtpc(0)
87 , fPt(0)
88 , fDeDx(0)
89 , fDeDxExpected(0)
90 , fTanTheta(0)
91 //, fSinAlpha(0)
92 //, fY(0)
93 , fPhiPrime(0)
94 , fTPCsignalN(0)
95 , fTPCsignalNsubthreshold(0)
96 , fNumTPCClustersInActiveVolume(0)
97 , fPIDtype(0)
98 , fMultiplicity(0)
99 , fCorrectdEdxEtaDependence(kFALSE)
100 , fCorrectdEdxMultiplicityDependence(kFALSE)
101 , fTree(0x0)
102 , fTreePions(0x0)
103 , fOutputContainer(0x0)
104 , fhTOFqa(0x0)
105 , fhMultiplicityQA(0x0)
106{
107 // Constructor
108
109 // Define input and output slots here
110 DefineInput(0, TChain::Class());
111 DefineOutput(1, TTree::Class());
112 DefineOutput(2, TTree::Class());
113 DefineOutput(3, TObjArray::Class());
114}
115
116
117//________________________________________________________________________
118AliTPCPIDEtaTree::~AliTPCPIDEtaTree()
119{
120 // dtor
121
122 //delete fTree;
123 //fTree = 0x0;
124
125 delete fOutputContainer;
126 fOutputContainer = 0x0;
127}
128
129
130//________________________________________________________________________
131void AliTPCPIDEtaTree::UserCreateOutputObjects()
132{
133 // Create histograms
134 // Called once
135
caa5a9ed 136 AliTPCPIDBase::UserCreateOutputObjects();
88b71b9f 137
138 if (fDoAdditionalQA) {
139 OpenFile(3);
140
141 fOutputContainer = new TObjArray(2);
142 fOutputContainer->SetName(GetName());
143 fOutputContainer->SetOwner(kTRUE);
144
145 const Int_t nBins = 6;
146 // p_vert, p_TPC, eta, nSigmaTOF, beta, multiplicity
147 Int_t bins[nBins] = { 48, 48, 9, 30, 110, 4 };
148 Double_t xmin[nBins] = { 0.3, 0.3, -0.9, -5.0, 0.0, 0. };
149 Double_t xmax[nBins] = { 2.7, 2.7, 0.9, 5.0, 1.1, 3200 };
150
151
152 fhTOFqa = new THnSparseI("hTOFqa","", nBins, bins, xmin, xmax);
153 fhTOFqa->GetAxis(0)->SetTitle("p_{Vertex} (GeV/c)");
154 fhTOFqa->GetAxis(1)->SetTitle("p_{TPC_inner} (GeV/c)");
155 fhTOFqa->GetAxis(2)->SetTitle("#eta");
156 fhTOFqa->GetAxis(3)->SetTitle("n #sigma_{p} TOF");
157 fhTOFqa->GetAxis(4)->SetTitle("#beta");
158 fhTOFqa->GetAxis(5)->SetTitle("Multiplicity");
159
160 fOutputContainer->Add(fhTOFqa);
161
162
163
164 fhMultiplicityQA = new TH2I("hMultiplicityQA", "Multiplicity check; Contributors to primary vertex per event; Total number of tracks per Event",
165 120, 0, 6000, 400, 0, 20000);
166 fOutputContainer->Add(fhMultiplicityQA);
167 }
168 else {
169 fOutputContainer = new TObjArray(1);
170 fOutputContainer->SetName(GetName());
171 fOutputContainer->SetOwner(kTRUE);
172 }
173
174 OpenFile(1);
175
176 fTree = new TTree("fTree", "Tree for analysis of #eta dependence of TPC signal");
177 fTree->Branch("pTPC", &fPtpc);
178 //fTree->Branch("pT", &fPt);
179 fTree->Branch("dEdx", &fDeDx);
180 fTree->Branch("dEdxExpected", &fDeDxExpected);
181 fTree->Branch("tanTheta", &fTanTheta);
182 //fTree->Branch("sinAlpha", &fSinAlpha);
183 //fTree->Branch("y", &fY);
184 //TODO fTree->Branch("phiPrime", &fPhiPrime);
185 fTree->Branch("tpcSignalN", &fTPCsignalN);
186
187 if (fStoreNumOfSubthresholdclusters)
188 fTree->Branch("tpcSignalNsubthreshold", &fTPCsignalNsubthreshold);
189
190 if (fStoreNumClustersInActiveVolume)
191 fTree->Branch("numTPCClustersInActiveVolume", &fNumTPCClustersInActiveVolume);
192
193 fTree->Branch("pidType", &fPIDtype);
194
195 if (fStoreMultiplicity) {
196 fTree->Branch("fMultiplicity", &fMultiplicity);
197 }
198
199 OpenFile(2);
200
201 fTreePions = new TTree("fTreePions", "Tree for analysis of #eta dependence of TPC signal - Pions");
202 fTreePions->Branch("pTPC", &fPtpc);
203 fTreePions->Branch("pT", &fPt);
204 fTreePions->Branch("dEdx", &fDeDx);
205 fTreePions->Branch("dEdxExpected", &fDeDxExpected);
206 fTreePions->Branch("tanTheta", &fTanTheta);
207 fTreePions->Branch("tpcSignalN", &fTPCsignalN);
208
209 if (fStoreNumOfSubthresholdclusters)
210 fTreePions->Branch("tpcSignalNsubthreshold", &fTPCsignalNsubthreshold);
211
212 if (fStoreMultiplicity) {
213 fTreePions->Branch("fMultiplicity", &fMultiplicity);
214 }
215
216 PostData(1, fTree);
217 PostData(2, fTreePions);
218 PostData(3, fOutputContainer);
219}
220
221
222//________________________________________________________________________
223void AliTPCPIDEtaTree::UserExec(Option_t *)
224{
225 // Main loop
226 // Called for each event
227
228 fESD = dynamic_cast<AliESDEvent*>(InputEvent());
229 if (!fESD) {
230 Printf("ERROR: fESD not available");
231 return;
232 }
233
234 fMC = dynamic_cast<AliMCEvent*>(MCEvent());
235
236 if (!fPIDResponse || !fV0KineCuts)
237 return;
238
239 if (!GetVertexIsOk(fESD))
240 return;
241
242 const AliVVertex* primaryVertex = fESD->GetPrimaryVertexTracks();
243 if (!primaryVertex)
244 return;
245 //fMultiplicity = primaryVertex->GetNContributors();
246
247
248 if(primaryVertex->GetNContributors() <= 0)
249 return;
250
12f73ffa 251 fMultiplicity = fESD->GetNumberOfESDTracks();
88b71b9f 252
253 if (fDoAdditionalQA) {
12f73ffa 254 Int_t nTotTracks = fESD->GetNumberOfESDTracks();
88b71b9f 255 fhMultiplicityQA->Fill(primaryVertex->GetNContributors(), nTotTracks);
256 }
257
258 Double_t magField = fESD->GetMagneticField();
259
260 // Fill V0 arrays with V0s
261 FillV0PIDlist();
262
263 //AliTPCParamSR par;
264 //par.Update();
265
f310f95e 266
267 Bool_t etaCorrAvail = fPIDResponse->UseTPCEtaCorrection();
268 Bool_t multCorrAvail = fPIDResponse->UseTPCMultiplicityCorrection();
269
88b71b9f 270 // Track loop to fill a Train spectrum
271 for (Int_t iTracks = 0; iTracks < fESD->GetNumberOfTracks(); iTracks++) {
272 Bool_t isPr = kFALSE;
273 Bool_t isPi = kFALSE;
274
275 AliESDtrack* track = fESD->GetTrack(iTracks);
276 if (!track) {
277 Printf("ERROR: Could not receive track %d", iTracks);
278 continue;
279 }
280
281 if (TMath::Abs(track->Eta()) > fEtaCut)
282 continue;
283
284 // Do not distinguish positively and negatively charged V0's
285 Char_t v0tagAllCharges = TMath::Abs(GetV0tag(iTracks));
286 if (v0tagAllCharges == -99) {
287 AliError(Form("Problem with V0 tag list (requested V0 track for track %d from %d (list status %d))!", iTracks, fESD->GetNumberOfTracks(),
288 fV0tags != 0x0));
289 continue;
290 }
291
292 Bool_t isV0prNotMC = (v0tagAllCharges == 16) && !fMC; // Only accept V0 protons for data, not for MC
293 Bool_t isV0piNotMC = (v0tagAllCharges == 15) && !fMC; // Only accept V0 pions for data, not for MC
294
295 Bool_t isV0NotMC = isV0prNotMC || isV0piNotMC;
296
297 // Apply track cut
298 if(!isV0NotMC && fTrackFilter && !fTrackFilter->IsSelected(track))
299 continue;
300
301 // Note: For V0's, the cut on ncl can be done via the tree (value is stored). One should not cut on geometry
302 // for V0's since they have different topology
303 if (!isV0NotMC && GetUseTPCCutMIGeo()) {
304 if (!TPCCutMIGeo(track, InputEvent()))
305 continue;
306 }
307
308
309 fPtpc = track->GetTPCmomentum();
310
311 if (fPtpc > 5.)
312 continue;
313
314 fPt = track->Pt();
315 fPhiPrime = GetPhiPrime(track->Phi(), magField, track->Charge());
316
317 Int_t label = track->GetLabel();
318
319 AliMCParticle* mcTrack = 0x0;
320
321 if (fMC) {
322 if (label < 0)
323 continue; // If MC is available, reject tracks with negative ESD label
324 mcTrack = dynamic_cast<AliMCParticle*>(fMC->GetTrack(TMath::Abs(label)));
325 if (!mcTrack) {
326 Printf("ERROR: Could not receive mcTrack with label %d for track %d", label, iTracks);
327 continue;
328 }
329
330 /*// Only accept MC primaries
331 if (!fMC->Stack()->IsPhysicalPrimary(TMath::Abs(label))) {
332 continue;
333 }*/
334 }
335
336 if (fMC) {
337 Int_t pdg = mcTrack->PdgCode();
338
339 if (TMath::Abs(pdg) == 2212) // Proton
340 isPr = kTRUE;
341 else if ((pdg == 111 || TMath::Abs(pdg) == 211) && fPtpc <= fPtpcPionCut) // Pion below desired momentum threshold
342 isPi = kTRUE;
343 else
344 continue; // Only take protons and pions
345
346 fPIDtype = kMCid;
347 /*
348 if (pdg == 111 || TMath::Abs(pdg) == 211) {//Pion
349 binMC = 3;
350 }
351 else if (TMath::Abs(pdg) == 311 || TMath::Abs(pdg) == 321) {//Kaon
352 binMC = 1;
353 }
354 else if (TMath::Abs(pdg) == 2212) {//Proton
355 binMC = 4;
356 }
357 else if (TMath::Abs(pdg) == 11) {//Electron
358 binMC = 0;
359 }
360 else if (TMath::Abs(pdg) == 13) {//Muon
361 binMC = 2;
362 }*/
363 }
364
365 fDeDx = track->GetTPCsignal();
366
367 UInt_t status = track->GetStatus();
368 Bool_t hasTOFout = status&AliESDtrack::kTOFout;
369 Bool_t hasTOFtime = status&AliESDtrack::kTIME;
370 Bool_t hasTOF = kFALSE;
371 if (hasTOFout && hasTOFtime)
372 hasTOF = kTRUE;
373 Float_t length = track->GetIntegratedLength();
374 // Length check only for primaries, not for V0's!
375 if (length < 350 && !isV0NotMC)
376 hasTOF = kFALSE;
377
378 if (!fMC) {
379 // Note: Normally, the track cuts include a cut on primaries. Therefore, if the particle is a V0, it would usually
380 // NOT be found via the primary cuts. This means that the PIDtype describes more or less disjoint sets
381 if (isV0prNotMC) {
382 // V0
383 isPr = kTRUE;
384
385 if (!hasTOF) {
386 fPIDtype = kV0idNoTOF;
387 }
388 else {
389 if (TMath::Abs(fPIDResponse->NumberOfSigmasTOF(track, AliPID::kProton)) < 3.0)
390 fPIDtype = kV0idPlusTOFaccepted;
391 else
392 fPIDtype = kV0idPlusTOFrejected;
393 }
394 }
395 else if (isV0piNotMC) {
396 // V0 pion
397 if (fPtpc > fPtpcPionCut || fDeDx > 140.) // Reject pions above desired momentum threshold and also reject too high dEdx
398 continue;
399
400 isPi = kTRUE;
401
402 if (!hasTOF) {
403 fPIDtype = kV0idNoTOF;
404 }
405 else {
406 if (TMath::Abs(fPIDResponse->NumberOfSigmasTOF(track, AliPID::kPion)) < 3.0)
407 fPIDtype = kV0idPlusTOFaccepted;
408 else
409 fPIDtype = kV0idPlusTOFrejected;
410 }
411 }
412 else {
413 // Non-V0
414 isPr = kTRUE; // If particle is accepted, it is a proton (for pions, only V0s are used)
415
416 if (fPtpc < 4.0 && //TODO was 2.7 // Do not accept non-V0s above this threshold -> High contamination!!!
417 (fDeDx >= 50. / TMath::Power(fPtpc, 1.3))) {// Pattern recognition instead of TPC cut to be ~independent of old TPC expected dEdx
418 if (fPtpc < 0.6) {
419 fPIDtype = kTPCid;
420 }
421 // fPtpc >= 0.6
422 else if (hasTOF && TMath::Abs(fPIDResponse->NumberOfSigmasTOF(track, AliPID::kProton)) < 3.0) {
423 fPIDtype = kTPCandTOFid;
424 }
425 else
426 continue; // Reject particle
427 }
428 else
429 continue; // Reject particle
430 }
431 }
432
433 if (fDoAdditionalQA) {
434 Double_t tofTime = track->GetTOFsignal();//in ps
435 Double_t tof = tofTime * 1E-3; // ns, average T0 fill subtracted, no info from T0detector
436 Double_t length2 = track->GetIntegratedLength();
437 Double_t c = TMath::C() * 1.E-9;// m/ns
438 length2 = length2 * 0.01; // in meters
439 tof = tof * c;
440 Double_t beta = length2 / tof;
441
442 Double_t nSigmaTOF = hasTOF ? fPIDResponse->NumberOfSigmasTOF(track, AliPID::kProton) : 999;
443
444 // p_vert, p_TPC, eta, nSigmaTOF, beta, multiplicity
0e60aeb1 445 Double_t entry[6] = { track->P(), fPtpc, track->Eta(), nSigmaTOF, beta, (Double_t)fMultiplicity };
88b71b9f 446 fhTOFqa->Fill(entry);
447 }
448
449 // Prepare entry for tree (some quantities have already been set)
450 // Turn eta correction off -> Important here is the pure spline value and the selection via cuts. The correction
451 // can be re-done manually, if needed. But it cannot be undone!
452
f310f95e 453 if (fCorrectdEdxEtaDependence && fNumEtaCorrReqErrorsIssued < 23 && !etaCorrAvail) {
454 AliError("TPC eta correction requested, but was not activated in PID response (most likely not available)!");
455 fNumEtaCorrReqErrorsIssued++;
456 if (fNumEtaCorrReqErrorsIssued == 23)
457 AliError("Ignoring this error from now on!");
458 }
459
460 if (fCorrectdEdxMultiplicityDependence && fNumMultCorrReqErrorsIssued < 23 && !multCorrAvail) {
461 AliError("TPC multiplicity correction requested, but was not activated in PID response (most likely not available)!");
462 fNumMultCorrReqErrorsIssued++;
463 if (fNumMultCorrReqErrorsIssued == 23)
464 AliError("Ignoring this error from now on!");
465 }
466
88b71b9f 467 if (isPr)
468 fDeDxExpected = fPIDResponse->GetTPCResponse().GetExpectedSignal(track, AliPID::kProton, AliTPCPIDResponse::kdEdxDefault,
f310f95e 469 fCorrectdEdxEtaDependence && etaCorrAvail,
470 fCorrectdEdxMultiplicityDependence && multCorrAvail);
88b71b9f 471 else if (isPi)
472 fDeDxExpected = fPIDResponse->GetTPCResponse().GetExpectedSignal(track, AliPID::kPion, AliTPCPIDResponse::kdEdxDefault,
f310f95e 473 fCorrectdEdxEtaDependence && etaCorrAvail,
474 fCorrectdEdxMultiplicityDependence && multCorrAvail);
88b71b9f 475 else
476 fDeDxExpected = -1.;
477 fTanTheta = track->GetInnerParam()->GetTgl();
478 //fSinAlpha = track->GetInnerParam()->GetSnp();
479 //fY = track->GetInnerParam()->GetY();
480 fTPCsignalN = track->GetTPCsignalN();
481
482 if (fStoreNumOfSubthresholdclusters) {
483 const AliTPCdEdxInfo *clsInfo = track->GetTPCdEdxInfo();
484
485 if (clsInfo) {
486 Double32_t signal[4] = {0}; // 0: IROC only; 1: OROC short padas; 2: OROC long pads; 3:OROC combined
487 Char_t ncl[3] = {0}; // clusters above threshold; 0: IROC; 1: OROC short; 2: OROC long
488 Char_t nrows[3] = {0}; // clusters above and below threshold; 0: IROC; 1: OROC short; 2: OROC long
489
490 clsInfo->GetTPCSignalRegionInfo(signal, ncl, nrows);
491
492 fTPCsignalNsubthreshold = nrows[0] + nrows[1] + nrows[2] - ncl[0] - ncl[1] - ncl[2];
493 }
494 else
495 fTPCsignalNsubthreshold = 200;// Set to invalid value
496 }
497
498
499 if (fStoreNumClustersInActiveVolume)
500 fNumTPCClustersInActiveVolume = track->GetLengthInActiveZone(1, 1.8, 220, magField);
501 else
502 fNumTPCClustersInActiveVolume = 200.;//Set to invalid value
503
504
505
506 /* START
507 const Double_t tanTheta = track->GetInnerParam()->GetTgl();
508
509 // Constant in formula for B in kGauss (factor 0.1 to convert B from Tesla to kGauss),
510 // pT in GeV/c (factor c*1e-9 to arrive at GeV/c) and curvature in 1/cm (factor 0.01 to get from m to cm)
511 const Double_t constant = TMath::C()* 1e-9 * 0.1 * 0.01;
512 const Double_t curvature = magField * constant / track->Pt(); // in 1./cm
513
514 //const Double_t angleIROC = TMath::ASin(TMath::Min(TMath::Abs(par.GetPadRowRadii(0, par.GetNRow(0) / 2.) * curvature) * 0.5, 1.));
515 //const Double_t angleOROC = TMath::ASin(TMath::Min(TMath::Abs(par.GetPadRowRadii(36, par.GetNRow(36) / 2.) * curvature) * 0.5, 1.));
516
517 Double_t averageddzdr = 0.;
518 Int_t nParts = 0;
519
520 for (Double_t r = 85; r < 245; r++) {
521 Double_t sinPhiLocal = TMath::Abs(r*curvature*0.5);
522
523 // Cut on |sin(phi)| as during reco
524 if (TMath::Abs(sinPhiLocal) <= 0.95) {
525 const Double_t phiLocal = TMath::ASin(sinPhiLocal);
526 const Double_t tanPhiLocal = TMath::Tan(phiLocal);
527
528 averageddzdr += tanTheta * TMath::Sqrt(1. + tanPhiLocal * tanPhiLocal);
529 nParts++;
530 }
531 }
532
533 if (nParts > 0)
534 averageddzdr /= nParts;
535 else {
536 AliError("Problems during determination of dz/dr. Skipping track!");
537 continue;
538 }
539
540
541 //printf("padRow 0 / 36: %f / %f\n", par.GetPadRowRadii(0, par.GetNRow(0) / 2.), par.GetPadRowRadii(36, par.GetNRow(36) / 2.));
542 //printf("pT: %f\nFactor/magField(kGs)/curvature^-1: %f / %f /%f\nIROC/OROC/averageOld/average: %f / %f / %f / //%f\ntanThetaGlobalFromTheta/tanTheta/dzdr: %f / %f / %f\n\n",
543 // track->Pt(), constant, magField, 1./curvature, angleIROC, angleOROC, angleAverage, averageAngle, TMath::Tan(-track->Theta() + TMath::Pi() / 2.0), tanTheta, dzdr);
544 //printf("pT: %f\nFactor/magField(kGs)/curvature^-1: %f / %f /%f\ntanThetaGlobalFromTheta/tanTheta/Averageddzdr: %f / %f / %f\n\n",
545 // track->Pt(), constant, magField, 1./curvature, TMath::Tan(-track->Theta() + TMath::Pi() / 2.0), tanTheta, averageddzdr);
546
547
548 fTanTheta = averageddzdr;
549 */
550
551 if (isPr)
552 fTree->Fill();
553 else if (isPi)
554 fTreePions->Fill();
555 } //track loop
556
557 // Post output data.
558 PostData(1, fTree);
559 PostData(2, fTreePions);
560
561 if (fDoAdditionalQA)
562 PostData(3, fOutputContainer);
563
564 // Clear the V0 PID arrays
565 ClearV0PIDlist();
566}
567
568//________________________________________________________________________
569void AliTPCPIDEtaTree::Terminate(const Option_t *)
570{
571 // Called once at the end of the query
572}