]> git.uio.no Git - u/mrichter/AliRoot.git/blob - PWGPP/TPC/AliTPCPIDEtaTree.cxx
Merge branch 'feature-movesplit'
[u/mrichter/AliRoot.git] / PWGPP / TPC / AliTPCPIDEtaTree.cxx
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 /*
30 This task determines the eta dependence of the TPC signal.
31 For this purpose, only tracks fulfilling some standard quality cuts are taken into account.
32 The obtained data can be used to derive the functional behaviour of the eta dependence.
33 Such a function can be plugged into this task to correct for the eta dependence and to see
34 if there is then really no eta dependence left.
35
36 Class written by Benjamin Hess.
37 Contact: bhess@cern.ch
38 */
39
40 ClassImp(AliTPCPIDEtaTree)
41
42 //________________________________________________________________________
43 AliTPCPIDEtaTree::AliTPCPIDEtaTree()
44   : AliTPCPIDBase()
45   , fNumEtaCorrReqErrorsIssued(0)
46   , fNumMultCorrReqErrorsIssued(0)
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 //________________________________________________________________________
77 AliTPCPIDEtaTree::AliTPCPIDEtaTree(const char *name)
78   : AliTPCPIDBase(name)
79   , fNumEtaCorrReqErrorsIssued(0)
80   , fNumMultCorrReqErrorsIssued(0)
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 //________________________________________________________________________
118 AliTPCPIDEtaTree::~AliTPCPIDEtaTree()
119 {
120   // dtor
121   
122   //delete fTree;
123   //fTree = 0x0;
124   
125   delete fOutputContainer;
126   fOutputContainer = 0x0;
127 }
128
129
130 //________________________________________________________________________
131 void AliTPCPIDEtaTree::UserCreateOutputObjects()
132 {
133   // Create histograms
134   // Called once
135   
136   AliTPCPIDBase::UserCreateOutputObjects();
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 //________________________________________________________________________
223 void 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   
251   fMultiplicity = fESD->GetNumberOfESDTracks(); 
252     
253   if (fDoAdditionalQA) {
254     Int_t nTotTracks = fESD->GetNumberOfESDTracks();
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   
266   
267   Bool_t etaCorrAvail = fPIDResponse->UseTPCEtaCorrection();
268   Bool_t multCorrAvail = fPIDResponse->UseTPCMultiplicityCorrection();
269   
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
445       Double_t entry[6] = { track->P(), fPtpc, track->Eta(), nSigmaTOF, beta, (Double_t)fMultiplicity };
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     
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     
467     if (isPr)
468       fDeDxExpected = fPIDResponse->GetTPCResponse().GetExpectedSignal(track, AliPID::kProton, AliTPCPIDResponse::kdEdxDefault, 
469                                                                        fCorrectdEdxEtaDependence && etaCorrAvail,
470                                                                        fCorrectdEdxMultiplicityDependence && multCorrAvail);
471     else if (isPi)
472       fDeDxExpected = fPIDResponse->GetTPCResponse().GetExpectedSignal(track, AliPID::kPion, AliTPCPIDResponse::kdEdxDefault, 
473                                                                        fCorrectdEdxEtaDependence && etaCorrAvail,
474                                                                        fCorrectdEdxMultiplicityDependence && multCorrAvail);
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 //________________________________________________________________________
569 void AliTPCPIDEtaTree::Terminate(const Option_t *)
570 {
571   // Called once at the end of the query
572 }