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"
35 ClassImp(AliAnalysisEtReconstructed);
38 AliAnalysisEtReconstructed::AliAnalysisEtReconstructed() :
44 ,fHistChargedPionEnergyDeposit(0)
45 ,fHistProtonEnergyDeposit(0)
46 ,fHistAntiProtonEnergyDeposit(0)
47 ,fHistChargedKaonEnergyDeposit(0)
48 ,fHistMuonEnergyDeposit(0)
53 AliAnalysisEtReconstructed::~AliAnalysisEtReconstructed()
58 Int_t AliAnalysisEtReconstructed::AnalyseEvent(AliVEvent* ev)
59 { // analyse ESD event
62 AliFatal("ERROR: Event does not exist");
65 AliESDEvent *event = dynamic_cast<AliESDEvent*>(ev);
67 Double_t protonMass = fgProtonMass;
72 TObjArray* list = fEsdtrackCutsTPC->GetAcceptedTracks(event);
74 Int_t nGoodTracks = list->GetEntries();
75 // printf("nGoodTracks %d nCaloClusters %d\n", nGoodTracks, event->GetNumberOfCaloClusters());
77 for (Int_t iTrack = 0; iTrack < nGoodTracks; iTrack++)
79 AliESDtrack *track = dynamic_cast<AliESDtrack*> (list->At(iTrack));
82 AliError(Form("ERROR: Could not get track %d", iTrack));
89 Float_t nSigmaPion,nSigmaProton,nSigmaKaon,nSigmaElectron;
90 nSigmaPion = TMath::Abs(pID.NumberOfSigmasTPC(track,AliPID::kPion));
91 nSigmaProton = TMath::Abs(pID.NumberOfSigmasTPC(track,AliPID::kProton));
92 nSigmaKaon = TMath::Abs(pID.NumberOfSigmasTPC(track,AliPID::kKaon));
93 nSigmaElectron = TMath::Abs(pID.NumberOfSigmasTPC(track,AliPID::kElectron));
95 bool isPion = (nSigmaPion<3.0 && nSigmaProton>2.0 && nSigmaKaon>2.0);
96 bool isElectron = (nSigmaElectron<2.0 && nSigmaPion>4.0 && nSigmaProton>3.0 && nSigmaKaon>3.0);
97 bool isKaon = (nSigmaPion>3.0 && nSigmaProton>2.0 && nSigmaKaon<2.0);
98 bool isProton = (nSigmaPion>3.0 && nSigmaProton<2.0 && nSigmaKaon>2.0);
101 Int_t nItsClusters = dynamic_cast<AliESDtrack*>(track)->GetNcls(0);
102 Int_t nTPCClusters = dynamic_cast<AliESDtrack*>(track)->GetNcls(1);
104 Float_t massPart = 0;
106 const Double_t *pidWeights = track->PID();
108 Double_t maxpidweight = 0;
112 for (Int_t p =0; p < AliPID::kSPECIES; p++)
114 if (pidWeights[p] > maxpidweight)
116 maxpidweight = pidWeights[p];
120 if (maxpid == AliPID::kProton)
122 //by definition of ET
123 massPart = -protonMass*track->Charge();
128 Double_t et = track->E() * TMath::Sin(track->Theta()) + massPart;
129 //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
131 if (TMath::Abs(track->Eta()) < fCuts->GetCommonEtaCut() && CheckGoodVertex(track) && nItsClusters > fCuts->GetReconstructedNItsClustersCut() && nTPCClusters > fCuts->GetReconstructedNTpcClustersCut() )
134 fChargedMultiplicity++;
137 if (maxpid == AliPID::kProton)
141 if (maxpid == AliPID::kPion)
145 if (maxpid == AliPID::kKaon)
147 fChargedKaonEt += et;
149 if (maxpid == AliPID::kMuon)
153 if (maxpid == AliPID::kElectron)
159 if (TMath::Abs(track->Eta()) < fEtaCutAcc && track->Phi() < fPhiCutAccMax && track->Phi() > fPhiCutAccMin)
161 fTotChargedEtAcc += track->E()*TMath::Sin(track->Theta()) + massPart;
164 if (maxpid == AliPID::kProton)
168 if (maxpid == AliPID::kPion)
172 if (maxpid == AliPID::kKaon)
174 fChargedKaonEtAcc += et;
176 if (maxpid == AliPID::kMuon)
180 if (maxpid == AliPID::kElectron)
182 fElectronEtAcc += et;
189 if (TrackHitsCalorimeter(track, event->GetMagneticField()))
191 Double_t phi = track->Phi();
192 Double_t pt = track->Pt();
193 // printf("Rec track hit: iTrack %03d phi %4.3f pt %4.3f\n", iTrack, phi, pt); // tmp/debug printout
194 if (track->Charge() > 0) fHistPhivsPtPos->Fill(phi, pt);
195 else fHistPhivsPtNeg->Fill(phi, pt);
199 for (Int_t iCluster = 0; iCluster < event->GetNumberOfCaloClusters(); iCluster++)
201 AliESDCaloCluster* cluster = event->GetCaloCluster(iCluster);
204 AliError(Form("ERROR: Could not get cluster %d", iCluster));
208 if (cluster->GetType() != fClusterType) continue;
209 //if(cluster->GetTracksMatched() > 0)
210 // printf("Rec Cluster: iCluster %03d E %4.3f type %d NCells %d, nmatched: %d, distance to closest: %f\n", iCluster, cluster->E(), (int)(cluster->GetType()), cluster->GetNCells(), cluster->GetNTracksMatched(), cluster->GetEmcCpvDistance()); // tmp/debug printout
213 if (cluster->E() < fClusterEnergyCut) continue;
216 cluster->GetPosition(pos);
218 Double_t distance = cluster->GetEmcCpvDistance();
219 Int_t trackMatchedIndex = cluster->GetTrackMatchedIndex();
220 if ( cluster->IsEMCAL() ) {
221 distance = CalcTrackClusterDistance(pos, &trackMatchedIndex, event);
224 fHistTMDeltaR->Fill(distance);
225 if (distance < fTrackDistanceCut)
227 if (cluster->GetNTracksMatched() == 1 && trackMatchedIndex>0)
229 AliVTrack *track = event->GetTrack(trackMatchedIndex);
230 const Double_t *pidWeights = track->PID();
232 Double_t maxpidweight = 0;
237 for (Int_t p =0; p < AliPID::kSPECIES; p++)
239 if (pidWeights[p] > maxpidweight)
241 maxpidweight = pidWeights[p];
245 if(fCuts->GetHistMakeTreeDeposit() && fTreeDeposit)
247 fEnergyDeposited = cluster->E();
248 fEnergyTPC = track->E();
249 fCharge = track->Charge();
250 fParticlePid = maxpid;
251 fPidProb = maxpidweight;
253 AliError("Error: track does not exist");
256 AliESDtrack *esdTrack = dynamic_cast<AliESDtrack*>(track);
258 AliError("Error: track does not exist");
261 if(esdTrack) fTrackPassedCut = fEsdtrackCutsTPC->AcceptTrack(esdTrack);
262 fTreeDeposit->Fill();
267 if(maxpidweight > fPidCut)
269 Float_t dist = TMath::Sqrt(pos[0]*pos[0] + pos[1]*pos[1]);
271 Float_t theta = TMath::ATan(pos[2]/dist)+TMath::Pi()/2;
273 Float_t et = cluster->E() * TMath::Sin(theta);
274 if(maxpid == AliPID::kProton)
277 if(track->Charge() == 1)
280 fHistProtonEnergyDeposit->Fill(cluster->E(), track->E());
282 else if(track->Charge() == -1)
285 fHistAntiProtonEnergyDeposit->Fill(cluster->E(), track->E());
288 else if(maxpid == AliPID::kPion)
291 fHistChargedPionEnergyDeposit->Fill(cluster->E(), track->E());
293 else if(maxpid == AliPID::kKaon)
296 fHistChargedKaonEnergyDeposit->Fill(cluster->E(), track->E());
298 else if(maxpid == AliPID::kMuon)
300 fHistMuonEnergyDeposit->Fill(cluster->E(), track->E());
309 if (cluster->E() > fSingleCellEnergyCut && cluster->GetNCells() == fCuts->GetCommonSingleCell()) continue;
311 cluster->GetPosition(pos);
313 // TODO: replace with TVector3, too lazy now...
315 float dist = TMath::Sqrt(pos[0]*pos[0] + pos[1]*pos[1]);
317 float theta = TMath::ATan(pos[2]/dist)+TMath::Pi()/2;
318 // float eta = TMath::Log(TMath::Abs( TMath::Tan( 0.5 * theta ) ) );
319 fTotNeutralEt += cluster->E() * TMath::Sin(theta);
320 fNeutralMultiplicity++;
325 fTotNeutralEtAcc = fTotNeutralEt;
326 fTotEt = fTotChargedEt + fTotNeutralEt;
327 fTotEtAcc = fTotChargedEtAcc + fTotNeutralEtAcc;
329 // Fill the histograms...
335 bool AliAnalysisEtReconstructed::CheckGoodVertex(AliVParticle* track)
340 if(track) dynamic_cast<AliESDtrack*>(track)->GetImpactParametersTPC(bxy,bz);
342 bool status = (TMath::Abs(track->Xv()) < fCuts->GetReconstructedVertexXCut()) &&
343 (TMath::Abs(track->Yv()) < fCuts->GetReconstructedVertexYCut()) &&
344 (TMath::Abs(track->Zv()) < fCuts->GetReconstructedVertexZCut()) &&
345 (TMath::Abs(bxy) < fCuts->GetReconstructedIPxyCut()) &&
346 (TMath::Abs(bz) < fCuts->GetReconstructedIPzCut());
351 void AliAnalysisEtReconstructed::Init()
353 AliAnalysisEt::Init();
354 fPidCut = fCuts->GetReconstructedPidCut();
355 TGeoGlobalMagField::Instance()->SetField(new AliMagF("Maps","Maps", 1., 1., AliMagF::k5kG));
357 cout<<"Warning! You have not set corrections. Your code will crash. You have to set the corrections."<<endl;
361 bool AliAnalysisEtReconstructed::TrackHitsCalorimeter(AliVParticle* track, Double_t magField)
362 { // propagate track to detector radius
365 cout<<"Warning: track empty"<<endl;
368 AliESDtrack *esdTrack= dynamic_cast<AliESDtrack*>(track);
369 // Printf("Propagating track: eta: %f, phi: %f, pt: %f", esdTrack->Eta(), esdTrack->Phi(), esdTrack->Pt());
371 Bool_t prop = esdTrack->PropagateTo(fDetectorRadius, magField);
373 // if (prop) Printf("Track propagated, eta: %f, phi: %f, pt: %f", esdTrack->Eta(), esdTrack->Phi(), esdTrack->Pt());
375 TMath::Abs(esdTrack->Eta()) < fEtaCutAcc &&
376 esdTrack->Phi() > fPhiCutAccMin*TMath::Pi()/180. &&
377 esdTrack->Phi() < fPhiCutAccMax*TMath::Pi()/180.;
380 void AliAnalysisEtReconstructed::FillOutputList(TList* list)
381 { // add some extra histograms to the ones from base class
382 AliAnalysisEt::FillOutputList(list);
384 list->Add(fHistChargedPionEnergyDeposit);
385 list->Add(fHistProtonEnergyDeposit);
386 list->Add(fHistAntiProtonEnergyDeposit);
387 list->Add(fHistChargedKaonEnergyDeposit);
388 list->Add(fHistMuonEnergyDeposit);
391 void AliAnalysisEtReconstructed::CreateHistograms()
392 { // add some extra histograms to the ones from base class
393 AliAnalysisEt::CreateHistograms();
395 Int_t nbinsEt = 1000;
399 // possibly change histogram limits
401 nbinsEt = fCuts->GetHistNbinsParticleEt();
402 minEt = fCuts->GetHistMinParticleEt();
403 maxEt = fCuts->GetHistMaxParticleEt();
407 histname = "fHistChargedPionEnergyDeposit" + fHistogramNameSuffix;
408 fHistChargedPionEnergyDeposit = new TH2F(histname.Data(), "Energy deposited by #pi^{+/-}", nbinsEt, minEt, maxEt, nbinsEt, minEt, maxEt);
409 fHistChargedPionEnergyDeposit->SetXTitle("Energy deposited in calorimeter");
410 fHistChargedPionEnergyDeposit->SetYTitle("Energy of track");
412 histname = "fHistProtonEnergyDeposit" + fHistogramNameSuffix;
413 fHistProtonEnergyDeposit = new TH2F(histname.Data(), "Energy deposited by protons", nbinsEt, minEt, maxEt, nbinsEt, minEt, maxEt);
414 fHistProtonEnergyDeposit->SetXTitle("Energy deposited in calorimeter");
415 fHistProtonEnergyDeposit->SetYTitle("Energy of track");
417 histname = "fHistAntiProtonEnergyDeposit" + fHistogramNameSuffix;
418 fHistAntiProtonEnergyDeposit = new TH2F(histname.Data(), "Energy deposited by anti-protons", nbinsEt, minEt, maxEt, nbinsEt, minEt, maxEt);
419 fHistAntiProtonEnergyDeposit->SetXTitle("Energy deposited in calorimeter");
420 fHistAntiProtonEnergyDeposit->SetYTitle("Energy of track");
422 histname = "fHistChargedKaonEnergyDeposit" + fHistogramNameSuffix;
423 fHistChargedKaonEnergyDeposit = new TH2F(histname.Data(), "Energy deposited by K^{+/-}", nbinsEt, minEt, maxEt, nbinsEt, minEt, maxEt);
424 fHistChargedKaonEnergyDeposit->SetXTitle("Energy deposited in calorimeter");
425 fHistChargedKaonEnergyDeposit->SetYTitle("Energy of track");
427 histname = "fHistMuonEnergyDeposit" + fHistogramNameSuffix;
428 fHistMuonEnergyDeposit = new TH2F(histname.Data(), "Energy deposited by #mu^{+/-}", nbinsEt, minEt, maxEt, nbinsEt, minEt, maxEt);
429 fHistMuonEnergyDeposit->SetXTitle("Energy deposited in calorimeter");
430 fHistMuonEnergyDeposit->SetYTitle("Energy of track");
436 AliAnalysisEtReconstructed::CalcTrackClusterDistance(const Float_t clsPos[3],
438 const AliESDEvent *event)
439 { // calculate distance between cluster and closest track
441 Double_t trkPos[3] = {0,0,0};
443 Int_t bestTrkMatchId = -1;
444 Double_t distance = 9999; // init to a big number
447 Double_t distX = 0, distY = 0, distZ = 0;
449 for (Int_t iTrack = 0; iTrack < event->GetNumberOfTracks(); iTrack++) {
450 AliESDtrack *track = event->GetTrack(iTrack);
452 AliError(Form("ERROR: Could not get track %d", iTrack));
456 // check for approx. eta and phi range before we propagate..
459 AliEMCALTrack *emctrack = new AliEMCALTrack(*track);
460 if (!emctrack->PropagateToGlobal(clsPos[0],clsPos[1],clsPos[2],0.,0.) ) {
463 emctrack->GetXYZ(trkPos);
466 distX = clsPos[0]-trkPos[0];
467 distY = clsPos[1]-trkPos[1];
468 distZ = clsPos[2]-trkPos[2];
469 dist = TMath::Sqrt(distX*distX + distY*distY + distZ*distZ);
471 if (dist < distance) {
473 bestTrkMatchId = iTrack;
477 // printf("CalcTrackClusterDistance: bestTrkMatch %d origTrkMatch %d distance %f\n", bestTrkMatchId, *trkMatchId, distance);
478 *trkMatchId = bestTrkMatchId;