1 //_________________________________________________________________________
2 // Utility Class for transverse energy studies
3 // Base class for ESD analysis
4 // - reconstruction output
7 //*-- Authors: Oystein Djuvsland (Bergen), David Silvermyr (ORNL)
8 //_________________________________________________________________________
10 #include "AliAnalysisEtReconstructed.h"
11 #include "AliAnalysisEtCuts.h"
12 #include "AliESDtrack.h"
13 #include "AliEMCALTrack.h"
14 #include "AliESDCaloCluster.h"
16 #include "TGeoGlobalMagField.h"
18 #include "AliVEvent.h"
19 #include "AliESDEvent.h"
20 #include "AliESDtrackCuts.h"
21 #include "AliVParticle.h"
22 #include "TDatabasePDG.h"
24 #include "AliESDpid.h"
27 #include "AliAnalysisHadEtCorrections.h"
29 #include "AliCentrality.h"
36 ClassImp(AliAnalysisEtReconstructed);
39 AliAnalysisEtReconstructed::AliAnalysisEtReconstructed() :
44 ,fHistChargedPionEnergyDeposit(0)
45 ,fHistProtonEnergyDeposit(0)
46 ,fHistAntiProtonEnergyDeposit(0)
47 ,fHistChargedKaonEnergyDeposit(0)
48 ,fHistMuonEnergyDeposit(0)
49 ,fHistRemovedEnergy(0)
56 AliAnalysisEtReconstructed::~AliAnalysisEtReconstructed()
59 delete fHistChargedPionEnergyDeposit; /** Energy deposited in calorimeter by charged pions */
60 delete fHistProtonEnergyDeposit; /** Energy deposited in calorimeter by protons */
61 delete fHistAntiProtonEnergyDeposit; /** Energy deposited in calorimeter by anti-protons */
62 delete fHistChargedKaonEnergyDeposit; /** Energy deposited in calorimeter by charged kaons */
63 delete fHistMuonEnergyDeposit; /** Energy deposited in calorimeter by muons */
65 delete fHistRemovedEnergy; // removed energy
69 Int_t AliAnalysisEtReconstructed::AnalyseEvent(AliVEvent* ev)
75 AliFatal("ERROR: Event does not exist");
79 AliESDEvent *event = dynamic_cast<AliESDEvent*>(ev);
81 AliFatal("ERROR: ESD Event does not exist");
88 cent = fCentrality->GetCentralityClass10("V0M");
89 fCentClass = fCentrality->GetCentralityClass10("V0M");
92 Double_t protonMass = fgProtonMass;
97 TObjArray* list = fEsdtrackCutsTPC->GetAcceptedTracks(event);
99 Int_t nGoodTracks = list->GetEntries();
100 // printf("nGoodTracks %d nCaloClusters %d\n", nGoodTracks, event->GetNumberOfCaloClusters());
102 for (Int_t iTrack = 0; iTrack < nGoodTracks; iTrack++)
104 AliESDtrack *track = dynamic_cast<AliESDtrack*> (list->At(iTrack));
107 AliError(Form("ERROR: Could not get track %d", iTrack));
114 Float_t nSigmaPion,nSigmaProton,nSigmaKaon,nSigmaElectron;
115 nSigmaPion = TMath::Abs(pID.NumberOfSigmasTPC(track,AliPID::kPion));
116 nSigmaProton = TMath::Abs(pID.NumberOfSigmasTPC(track,AliPID::kProton));
117 nSigmaKaon = TMath::Abs(pID.NumberOfSigmasTPC(track,AliPID::kKaon));
118 nSigmaElectron = TMath::Abs(pID.NumberOfSigmasTPC(track,AliPID::kElectron));
120 bool isPion = (nSigmaPion<3.0 && nSigmaProton>2.0 && nSigmaKaon>2.0);
121 bool isElectron = (nSigmaElectron<2.0 && nSigmaPion>4.0 && nSigmaProton>3.0 && nSigmaKaon>3.0);
122 bool isKaon = (nSigmaPion>3.0 && nSigmaProton>2.0 && nSigmaKaon<2.0);
123 bool isProton = (nSigmaPion>3.0 && nSigmaProton<2.0 && nSigmaKaon>2.0);
126 Int_t nItsClusters = dynamic_cast<AliESDtrack*>(track)->GetNcls(0);
127 Int_t nTPCClusters = dynamic_cast<AliESDtrack*>(track)->GetNcls(1);
129 Float_t massPart = 0;
131 const Double_t *pidWeights = track->PID();
133 Double_t maxpidweight = 0;
137 for (Int_t p =0; p < AliPID::kSPECIES; p++)
139 if (pidWeights[p] > maxpidweight)
141 maxpidweight = pidWeights[p];
145 if (maxpid == AliPID::kProton)
147 //by definition of ET
148 massPart = -protonMass*track->Charge();
153 Double_t et = track->E() * TMath::Sin(track->Theta()) + massPart;
155 fSparseTracks[0] = maxpid;
156 fSparseTracks[1] = track->Charge();
157 fSparseTracks[2] = track->M();
158 fSparseTracks[3] = et;
159 fSparseTracks[4] = track->Pt();
160 fSparseTracks[5] = track->Eta();
161 fSparseTracks[6] = cent;
162 fSparseHistTracks->Fill(fSparseTracks);
164 //printf("Rec track: iTrack %03d eta %4.3f phi %4.3f nITSCl %d nTPCCl %d\n", iTrack, track->Eta(), track->Phi(), nItsClusters, nTPCClusters); // tmp/debug printout
166 if (TMath::Abs(track->Eta()) < fCuts->GetCommonEtaCut() && CheckGoodVertex(track) && nItsClusters > fCuts->GetReconstructedNItsClustersCut() && nTPCClusters > fCuts->GetReconstructedNTpcClustersCut() )
169 fChargedMultiplicity++;
172 if (maxpid == AliPID::kProton)
176 if (maxpid == AliPID::kPion)
180 if (maxpid == AliPID::kKaon)
182 fChargedKaonEt += et;
184 if (maxpid == AliPID::kMuon)
188 if (maxpid == AliPID::kElectron)
194 if (TMath::Abs(track->Eta()) < fEtaCutAcc && track->Phi() < fPhiCutAccMax && track->Phi() > fPhiCutAccMin)
196 fTotChargedEtAcc += track->E()*TMath::Sin(track->Theta()) + massPart;
199 if (maxpid == AliPID::kProton)
203 if (maxpid == AliPID::kPion)
207 if (maxpid == AliPID::kKaon)
209 fChargedKaonEtAcc += et;
211 if (maxpid == AliPID::kMuon)
215 if (maxpid == AliPID::kElectron)
217 fElectronEtAcc += et;
224 if (TrackHitsCalorimeter(track, event->GetMagneticField()))
226 Double_t phi = track->Phi();
227 Double_t pt = track->Pt();
228 // printf("Rec track hit: iTrack %03d phi %4.3f pt %4.3f\n", iTrack, phi, pt); // tmp/debug printout
229 if (track->Charge() > 0) fHistPhivsPtPos->Fill(phi, pt);
230 else fHistPhivsPtNeg->Fill(phi, pt);
234 for (Int_t iCluster = 0; iCluster < event->GetNumberOfCaloClusters(); iCluster++)
236 AliESDCaloCluster* cluster = event->GetCaloCluster(iCluster);
239 AliError(Form("ERROR: Could not get cluster %d", iCluster));
242 if (cluster->GetType() != fClusterType) continue;
244 //if(cluster->GetTracksMatched() > 0)
245 // printf("Rec Cluster: iCluster %03d E %4.3f type %.qd NCells %d, nmatched: %d, distance to closest: %f\n", iCluster, cluster->E(), (int)(cluster->GetType()), cluster->GetNCells(), cluster->GetNTracksMatched(), cluster->GetEmcCpvDistance()); // tmp/debug printout
248 if (cluster->E() < fClusterEnergyCut) continue;
252 cluster->GetPosition(pos);
255 Double_t distance = cluster->GetEmcCpvDistance();
256 Int_t trackMatchedIndex = cluster->GetTrackMatchedIndex();
257 if ( cluster->IsEMCAL() ) {
258 distance = CalcTrackClusterDistance(pos, &trackMatchedIndex, event);
262 fSparseClusters[0] = 0;
263 fSparseClusters[1] = 0;
264 fSparseClusters[2] = 0;
265 fSparseClusters[6] = 0;
266 fSparseClusters[7] = 0;
267 fSparseClusters[8] = 0;
268 fSparseClusters[9] = cent;
269 fSparseClusters[10] = 0;
272 if (cluster->GetNTracksMatched() > 0 && trackMatchedIndex > -1)
274 AliVTrack *tmptrack = event->GetTrack(trackMatchedIndex);
277 AliError("Error: track does not exist");
280 const Double_t *pidWeights = tmptrack->PID();
282 Double_t maxpidweight = 0;
284 Double_t massPart = 0;
287 for (Int_t p =0; p < AliPID::kSPECIES; p++)
289 if (pidWeights[p] > maxpidweight)
291 maxpidweight = pidWeights[p];
295 if (maxpid == AliPID::kProton)
297 //by definition of ET
298 massPart = -protonMass*tmptrack->Charge();
302 fSparseClusters[0] = maxpid;
303 fSparseClusters[1] = tmptrack->Charge();
304 fSparseClusters[2] = tmptrack->M();
305 fSparseClusters[6] = tmptrack->E() * TMath::Sin(tmptrack->Theta()) + massPart;;
306 fSparseClusters[7] = tmptrack->Pt();
307 fSparseClusters[8] = tmptrack->Eta();
312 if(fMakeSparse){fSparseClusters[10] = distance;}
314 fHistTMDeltaR->Fill(distance);
315 fHistTMDxDz->Fill(cluster->GetTrackDx(), cluster->GetTrackDz());
317 // Float_t clusteret = cluster->E() * TMath::Sin(cp.Theta());
319 Bool_t matched = false;
321 if (cluster->IsEMCAL()) matched = distance < fTrackDistanceCut;
322 else matched = (TMath::Abs(cluster->GetTrackDx()) < fTrackDxCut && TMath::Abs(cluster->GetTrackDz()) < fTrackDzCut);
326 if (cluster->GetNTracksMatched() > 0 && trackMatchedIndex>=0)
328 AliVTrack *track = event->GetTrack(trackMatchedIndex);
330 AliError("Error: track does not exist");
333 const Double_t *pidWeights = track->PID();
335 Double_t maxpidweight = 0;
340 for (Int_t p =0; p < AliPID::kSPECIES; p++)
342 if (pidWeights[p] > maxpidweight)
344 maxpidweight = pidWeights[p];
348 if (fCuts->GetHistMakeTreeDeposit() && fTreeDeposit)
350 fEnergyDeposited = cluster->E();
351 fEnergyTPC = track->E();
352 fCharge = track->Charge();
353 fParticlePid = maxpid;
354 fPidProb = maxpidweight;
355 AliESDtrack *esdTrack = dynamic_cast<AliESDtrack*>(track);
357 AliError("Error: track does not exist");
360 if (esdTrack) fTrackPassedCut = fEsdtrackCutsTPC->AcceptTrack(esdTrack);
361 fTreeDeposit->Fill();
365 if (maxpidweight > fPidCut)
367 Float_t dist = TMath::Sqrt(pos[0]*pos[0] + pos[1]*pos[1]);
369 Float_t theta = TMath::ATan(pos[2]/dist)+TMath::Pi()/2;
371 Float_t et = cluster->E() * TMath::Sin(theta);
372 if (maxpid == AliPID::kProton)
375 if (track->Charge() == 1)
378 fHistProtonEnergyDeposit->Fill(cluster->E(), track->E());
380 else if (track->Charge() == -1)
383 fHistAntiProtonEnergyDeposit->Fill(cluster->E(), track->E());
386 else if (maxpid == AliPID::kPion)
389 fHistChargedPionEnergyDeposit->Fill(cluster->E(), track->E());
391 else if (maxpid == AliPID::kKaon)
394 fHistChargedKaonEnergyDeposit->Fill(cluster->E(), track->E());
396 else if (maxpid == AliPID::kMuon)
398 fHistMuonEnergyDeposit->Fill(cluster->E(), track->E());
409 fSparseClusters[0] = AliPID::kPhoton;
410 fSparseClusters[1] = 0;
413 if (cluster->E() > fSingleCellEnergyCut && cluster->GetNCells() == fCuts->GetCommonSingleCell()) continue;
414 if (cluster->E() < fClusterEnergyCut) continue;
415 cluster->GetPosition(pos);
417 // TODO: replace with TVector3, too lazy now...
419 float dist = TMath::Sqrt(pos[0]*pos[0] + pos[1]*pos[1]);
421 float theta = TMath::ATan(pos[2]/dist)+TMath::Pi()/2;
422 // float eta = TMath::Log(TMath::Abs( TMath::Tan( 0.5 * theta ) ) );
423 fTotNeutralEt += cluster->E() * TMath::Sin(theta);
424 fNeutralMultiplicity++;
427 cluster->GetPosition(pos);
429 // TODO: replace with TVector3
431 float dist = TMath::Sqrt(pos[0]*pos[0] + pos[1]*pos[1]);
432 float theta = TMath::ATan(pos[2]/dist)+TMath::Pi()/2;
433 float eta = TMath::Log(TMath::Abs( TMath::Tan( 0.5 * theta ) ) );
435 fSparseClusters[3] = cluster->E() * TMath::Sin(theta);
436 fSparseClusters[4] = cluster->E();
437 fSparseClusters[5] = eta;
439 fSparseHistClusters->Fill(fSparseClusters);
444 Double_t removedEnergy = GetChargedContribution(fNeutralMultiplicity) + GetNeutralContribution(fNeutralMultiplicity) - GetGammaContribution(fNeutralMultiplicity);
445 fHistRemovedEnergy->Fill(removedEnergy);
446 // std::cout << "fTotNeutralEt: " << fTotNeutralEt << ", Contribution from non-removed charged: " << GetChargedContribution(fNeutralMultiplicity) << ", neutral: " << GetNeutralContribution(fNeutralMultiplicity) << ", gammas: " << GetGammaContribution(fNeutralMultiplicity) << ", multiplicity: " << fNeutralMultiplicity<< std::endl;
447 fTotNeutralEt = fGeomCorrection * fEMinCorrection * fTotNeutralEt - removedEnergy;
448 fTotNeutralEtAcc = fTotNeutralEt/fGeomCorrection;
449 fTotEt = fTotChargedEt + fTotNeutralEt;
450 fTotEtAcc = fTotChargedEtAcc + fTotNeutralEtAcc;
452 fSparseEt[0] = fTotEt;
453 fSparseEt[1] = fTotNeutralEt;
454 fSparseEt[2] = fTotChargedEtAcc;
455 fSparseEt[3] = fMultiplicity;
456 fSparseEt[4] = fNeutralMultiplicity;
457 fSparseEt[5] = fChargedMultiplicity;
460 // Fill the histograms...
466 bool AliAnalysisEtReconstructed::CheckGoodVertex(AliVParticle* track)
472 AliError("ERROR: no track");
475 AliESDtrack *esdTrack = dynamic_cast<AliESDtrack*>(track);
477 AliError("ERROR: no track");
480 esdTrack->GetImpactParametersTPC(bxy,bz);
483 bool status = (TMath::Abs(track->Xv()) < fCuts->GetReconstructedVertexXCut()) &&
484 (TMath::Abs(track->Yv()) < fCuts->GetReconstructedVertexYCut()) &&
485 (TMath::Abs(track->Zv()) < fCuts->GetReconstructedVertexZCut()) &&
486 (TMath::Abs(bxy) < fCuts->GetReconstructedIPxyCut()) &&
487 (TMath::Abs(bz) < fCuts->GetReconstructedIPzCut());
492 void AliAnalysisEtReconstructed::Init()
494 AliAnalysisEt::Init();
495 fPidCut = fCuts->GetReconstructedPidCut();
496 TGeoGlobalMagField::Instance()->SetField(new AliMagF("Maps","Maps", 1., 1., AliMagF::k5kG));
498 cout<<"Warning! You have not set corrections. Your code will crash. You have to set the corrections."<<endl;
502 bool AliAnalysisEtReconstructed::TrackHitsCalorimeter(AliVParticle* track, Double_t magField)
503 { // propagate track to detector radius
506 cout<<"Warning: track empty"<<endl;
509 AliESDtrack *esdTrack= dynamic_cast<AliESDtrack*>(track);
511 AliError("ERROR: no ESD track");
514 // Printf("Propagating track: eta: %f, phi: %f, pt: %f", esdTrack->Eta(), esdTrack->Phi(), esdTrack->Pt());
516 Bool_t prop = esdTrack->PropagateTo(fDetectorRadius, magField);
518 // if (prop) Printf("Track propagated, eta: %f, phi: %f, pt: %f", esdTrack->Eta(), esdTrack->Phi(), esdTrack->Pt());
520 TMath::Abs(esdTrack->Eta()) < fEtaCutAcc &&
521 esdTrack->Phi() > fPhiCutAccMin*TMath::Pi()/180. &&
522 esdTrack->Phi() < fPhiCutAccMax*TMath::Pi()/180.;
525 void AliAnalysisEtReconstructed::FillOutputList(TList* list)
526 { // add some extra histograms to the ones from base class
527 AliAnalysisEt::FillOutputList(list);
529 list->Add(fHistChargedPionEnergyDeposit);
530 list->Add(fHistProtonEnergyDeposit);
531 list->Add(fHistAntiProtonEnergyDeposit);
532 list->Add(fHistChargedKaonEnergyDeposit);
533 list->Add(fHistMuonEnergyDeposit);
535 list->Add(fHistRemovedEnergy);
538 void AliAnalysisEtReconstructed::CreateHistograms()
539 { // add some extra histograms to the ones from base class
540 AliAnalysisEt::CreateHistograms();
542 Int_t nbinsEt = 1000;
546 // possibly change histogram limits
548 nbinsEt = fCuts->GetHistNbinsParticleEt();
549 minEt = fCuts->GetHistMinParticleEt();
550 maxEt = fCuts->GetHistMaxParticleEt();
554 histname = "fHistChargedPionEnergyDeposit" + fHistogramNameSuffix;
555 fHistChargedPionEnergyDeposit = new TH2F(histname.Data(), "Energy deposited by #pi^{+/-}", nbinsEt, minEt, maxEt, nbinsEt, minEt, maxEt);
556 fHistChargedPionEnergyDeposit->SetXTitle("Energy deposited in calorimeter");
557 fHistChargedPionEnergyDeposit->SetYTitle("Energy of track");
559 histname = "fHistProtonEnergyDeposit" + fHistogramNameSuffix;
560 fHistProtonEnergyDeposit = new TH2F(histname.Data(), "Energy deposited by protons", nbinsEt, minEt, maxEt, nbinsEt, minEt, maxEt);
561 fHistProtonEnergyDeposit->SetXTitle("Energy deposited in calorimeter");
562 fHistProtonEnergyDeposit->SetYTitle("Energy of track");
564 histname = "fHistAntiProtonEnergyDeposit" + fHistogramNameSuffix;
565 fHistAntiProtonEnergyDeposit = new TH2F(histname.Data(), "Energy deposited by anti-protons", nbinsEt, minEt, maxEt, nbinsEt, minEt, maxEt);
566 fHistAntiProtonEnergyDeposit->SetXTitle("Energy deposited in calorimeter");
567 fHistAntiProtonEnergyDeposit->SetYTitle("Energy of track");
569 histname = "fHistChargedKaonEnergyDeposit" + fHistogramNameSuffix;
570 fHistChargedKaonEnergyDeposit = new TH2F(histname.Data(), "Energy deposited by K^{+/-}", nbinsEt, minEt, maxEt, nbinsEt, minEt, maxEt);
571 fHistChargedKaonEnergyDeposit->SetXTitle("Energy deposited in calorimeter");
572 fHistChargedKaonEnergyDeposit->SetYTitle("Energy of track");
574 histname = "fHistMuonEnergyDeposit" + fHistogramNameSuffix;
575 fHistMuonEnergyDeposit = new TH2F(histname.Data(), "Energy deposited by #mu^{+/-}", nbinsEt, minEt, maxEt, nbinsEt, minEt, maxEt);
576 fHistMuonEnergyDeposit->SetXTitle("Energy deposited in calorimeter");
577 fHistMuonEnergyDeposit->SetYTitle("Energy of track");
579 histname = "fHistRemovedEnergy" + fHistogramNameSuffix;
580 fHistRemovedEnergy = new TH1F(histname.Data(), histname.Data(), 1000, 0, 20);
581 //fHistMuonEnergyDeposit->SetXTitle("Energy deposited in calorimeter");
582 //fHistMuonEnergyDeposit->SetYTitle("Energy of track");
589 AliAnalysisEtReconstructed::CalcTrackClusterDistance(const Float_t clsPos[3],
591 const AliESDEvent *event)
592 { // calculate distance between cluster and closest track
594 Double_t trkPos[3] = {0,0,0};
596 Int_t bestTrkMatchId = -1;
597 Double_t distance = 9999; // init to a big number
600 Double_t distX = 0, distY = 0, distZ = 0;
602 for (Int_t iTrack = 0; iTrack < event->GetNumberOfTracks(); iTrack++) {
603 AliESDtrack *track = event->GetTrack(iTrack);
605 AliError(Form("ERROR: Could not get track %d", iTrack));
609 // check for approx. eta and phi range before we propagate..
612 AliEMCALTrack *emctrack = new AliEMCALTrack(*track);
613 if (!emctrack->PropagateToGlobal(clsPos[0],clsPos[1],clsPos[2],0.,0.) ) {
616 emctrack->GetXYZ(trkPos);
619 distX = clsPos[0]-trkPos[0];
620 distY = clsPos[1]-trkPos[1];
621 distZ = clsPos[2]-trkPos[2];
622 dist = TMath::Sqrt(distX*distX + distY*distY + distZ*distZ);
624 if (dist < distance) {
626 bestTrkMatchId = iTrack;
630 // printf("CalcTrackClusterDistance: bestTrkMatch %d origTrkMatch %d distance %f\n", bestTrkMatchId, *trkMatchId, distance);
631 *trkMatchId = bestTrkMatchId;