3 // Hadronic correction task.
5 // Author: R.Reed, C.Loizides, S.Aiola
8 #include <TClonesArray.h>
13 #include "AliAnalysisManager.h"
14 #include "AliAODEvent.h"
15 #include "AliAODCaloCluster.h"
16 #include "AliESDCaloCluster.h"
17 #include "AliVTrack.h"
18 #include "AliPicoTrack.h"
19 #include "AliVEventHandler.h"
20 #include "AliEmcalParticle.h"
22 #include "AliHadCorrTask.h"
24 ClassImp(AliHadCorrTask)
26 //________________________________________________________________________
27 AliHadCorrTask::AliHadCorrTask() :
28 AliAnalysisTaskEmcal("AliHadCorrTask", kFALSE),
37 fHistNclusMatchvsCent(0),
42 fHistNMatchCent_trk(0),
46 // Default constructor.
48 for(Int_t i=0; i<8; i++) {
50 fHistEsubPchRat[i] = 0;
51 for(Int_t j=0; j<4; j++) {
52 fHistNCellsEnergy[i][j] = 0;
55 fHistMatchEvsP[i] = 0;
56 fHistMatchdRvsEP[i] = 0;
57 fHistNMatchEnergy[i] = 0;
59 for(Int_t j=0; j<9; j++) {
60 for(Int_t k=0; k<2; k++) {
61 fHistMatchEtaPhi[i][j][k] = 0;
67 //________________________________________________________________________
68 AliHadCorrTask::AliHadCorrTask(const char *name, Bool_t histo) :
69 AliAnalysisTaskEmcal(name, histo),
70 fOutCaloName("CaloClustersCorr"),
78 fHistNclusMatchvsCent(0),
83 fHistNMatchCent_trk(0),
87 // Standard constructor.
89 for(Int_t i=0; i<8; i++) {
91 fHistMatchEvsP[i] = 0;
92 fHistMatchdRvsEP[i] = 0;
93 for(Int_t j=0; j<3; j++) {
94 fHistNCellsEnergy[i][j] = 0;
98 fHistEsubPchRat[i] = 0;
99 for(Int_t j=0; j<9; j++) {
100 for(Int_t k=0; k<2; k++) {
101 fHistMatchEtaPhi[i][j][k] = 0;
106 fBranchNames="ESD:AliESDRun.,AliESDHeader.,PrimaryVertex.";
109 //________________________________________________________________________
110 AliHadCorrTask::~AliHadCorrTask()
115 //________________________________________________________________________
116 Int_t AliHadCorrTask::GetMomBin(Double_t p) const
123 else if (p>=0.5 && p<1.0)
125 else if (p>=1.0 && p<1.5)
127 else if (p>=1.5 && p<2.)
129 else if (p>=2. && p<3.)
131 else if (p>=3. && p<4.)
133 else if (p>=4. && p<5.)
135 else if (p>=5. && p<8.)
143 //________________________________________________________________________
144 Double_t AliHadCorrTask::GetEtaSigma(Int_t pbin) const
148 Double_t EtaSigma[9]={0.0097,0.0075,0.0059,0.0055,0.0053,0.005,0.005,0.0045,0.0042};
149 return 2.0*EtaSigma[pbin];
152 //________________________________________________________________________
153 Double_t AliHadCorrTask::GetPhiMean(Int_t pbin, Int_t centbin) const
158 Double_t PhiMean[9]={0.036,
167 return PhiMean[pbin];
168 } else if (centbin==1) {
169 Double_t PhiMean[9]={0.036,
178 return PhiMean[pbin];
179 } else if (centbin==2) {
180 Double_t PhiMean[9]={0.036,
189 return PhiMean[pbin];
190 } else if (centbin==3) {
191 Double_t PhiMean[9]={0.036,
200 return PhiMean[pbin];
201 } else if (centbin==4) {
202 Double_t PhiMean[9]={0.036,
211 return PhiMean[pbin]*(-1.);
212 } else if (centbin==5) {
213 Double_t PhiMean[9]={0.036,
222 return PhiMean[pbin]*(-1.);
223 } else if (centbin==6) {
224 Double_t PhiMean[9]={0.036,
233 return PhiMean[pbin]*(-1.);
234 } else if (centbin==7) {
235 Double_t PhiMean[9]={0.036,
244 return PhiMean[pbin]*(-1.);
250 //________________________________________________________________________
251 Double_t AliHadCorrTask::GetPhiSigma(Int_t pbin, Int_t centbin) const
256 Double_t PhiSigma[9]={0.0221,
265 return 2.*PhiSigma[pbin];
266 } else if (centbin==1) {
267 Double_t PhiSigma[9]={0.0217,
276 return 2.*PhiSigma[pbin];
277 } else if (centbin==2) {
278 Double_t PhiSigma[9]={0.0211,
287 return 2.*PhiSigma[pbin];
288 } else if (centbin==3) {
289 Double_t PhiSigma[9]={0.0215,
298 return 2.*PhiSigma[pbin];
299 } else if (centbin==4) {
300 Double_t PhiSigma[9]={0.0199,
309 return 2.*PhiSigma[pbin];
310 } else if (centbin==5) {
311 Double_t PhiSigma[9]={0.0200,
320 return 2.*PhiSigma[pbin];
321 } else if (centbin==6) {
322 Double_t PhiSigma[9]={0.0202,
331 return 2.*PhiSigma[pbin];
332 } else if (centbin==7) {
333 Double_t PhiSigma[9]={0.0205,
342 return 2.*PhiSigma[pbin];
348 //________________________________________________________________________
349 void AliHadCorrTask::UserCreateOutputObjects()
351 // Create my user objects.
353 AliVEventHandler* handler = AliAnalysisManager::GetAnalysisManager()->GetInputEventHandler();
355 AliError(Form("%s: Input handler not available!", GetName()));
359 if (handler->InheritsFrom("AliESDInputHandler")) {
360 fOutClusters = new TClonesArray("AliESDCaloCluster");
361 } else if (handler->InheritsFrom("AliAODInputHandler")) {
362 fOutClusters = new TClonesArray("AliAODCaloCluster");
364 AliError(Form("%s: Input handler not recognized!", GetName()));
367 fOutClusters->SetName(fOutCaloName);
373 fOutput = new TList();
378 for(Int_t icent=0; icent<8; ++icent) {
379 for(Int_t ipt=0; ipt<9; ++ipt) {
380 for(Int_t ieta=0; ieta<2; ++ieta) {
381 name = Form("fHistMatchEtaPhi_%i_%i_%i",icent,ipt,ieta);
382 fHistMatchEtaPhi[icent][ipt][ieta] = new TH2F(name, name, 200, -0.1, 0.1, 400, -0.2, 0.2);
383 fOutput->Add(fHistMatchEtaPhi[icent][ipt][ieta]);
387 for(Int_t itrk=0; itrk<4; ++itrk) {
388 name = Form("fHistNCellsEnergy_%i_%i",icent,itrk);
389 fHistNCellsEnergy[icent][itrk] = new TH2F(name, name, 1000, 0, 100, 101, -0.5, 100.5);
390 fOutput->Add(fHistNCellsEnergy[icent][itrk]);
393 name = Form("fHistEsubPch_%i",icent);
394 fHistEsubPch[icent]=new TH1F(name, name, 400, 0., 100.);
395 fOutput->Add(fHistEsubPch[icent]);
397 name = Form("fHistEsubPchRat_%i",icent);
398 fHistEsubPchRat[icent]=new TH2F(name, name, 400, 0., 200., 1000, 0., 10.);
399 fOutput->Add(fHistEsubPchRat[icent]);
402 name = Form("fHistMatchEvsP_%i",icent);
403 fHistMatchEvsP[icent] = new TH2F(name, name, 400, 0., 200., 1000, 0., 10.);
404 fOutput->Add(fHistMatchEvsP[icent]);
406 name = Form("fHistMatchdRvsEP_%i",icent);
407 fHistMatchdRvsEP[icent] = new TH2F(name, name, 1000, 0., 1., 1000, 0., 10.);
408 fOutput->Add(fHistMatchdRvsEP[icent]);
410 name = Form("fHistNMatchEnergy_%i",icent);
411 fHistNMatchEnergy[icent] = new TH2F(name, name, 1000, 0, 100, 101, -0.5, 100.5);
412 fOutput->Add(fHistNMatchEnergy[icent]);
416 fHistCentrality = new TH1F("fHistCentrality", "Centrality", 100, 0, 100);
417 fHistNclusvsCent = new TH1F("Nclusvscent", "NclusVsCent", 100, 0, 100);
418 fHistNclusMatchvsCent = new TH1F("NclusMatchvscent", "NclusMatchVsCent", 100, 0, 100);
419 fHistEbefore = new TH2F("Ebefore", "Ebefore", 100, 0, 100, 101, -0.5, 100.5);
420 fHistEafter = new TH2F("Eafter", "Eafter", 100, 0, 100, 101, -0.5, 100.5);
421 fHistEoPCent = new TH2F("EoPCent", "EoPCent", 100, 0, 100, 1000, 0, 10);
422 fHistNMatchCent = new TH2F("NMatchesCent", "NMatchesCent", 100, 0, 100, 11, -0.5, 10.5);
423 fHistNMatchCent_trk = new TH2F("NMatchesCent_trk", "NMatchesCent_trk", 100, 0, 100, 11, -0.5, 10.5);
424 fHistNoMatchEtaPhi = new TH2F("NoMatchEtaPhi", "NoMatchEtaPhi", 200, -1, 1, 90, 1, 4);
426 fOutput->Add(fHistNclusMatchvsCent);
427 fOutput->Add(fHistNclusvsCent);
428 fOutput->Add(fHistEbefore);
429 fOutput->Add(fHistEafter);
430 fOutput->Add(fHistEoPCent);
431 fOutput->Add(fHistNMatchCent);
432 fOutput->Add(fHistNMatchCent_trk);
433 fOutput->Add(fHistCentrality);
434 fOutput->Add(fHistNoMatchEtaPhi);
436 PostData(1, fOutput);
439 //________________________________________________________________________
440 void AliHadCorrTask::DoTrackClusLoop()
442 // Do the track cluster loop.
444 const Int_t Ntrks = fTracks->GetEntries();
446 // loop over all tracks
447 for (Int_t t = 0; t < Ntrks; ++t) {
448 AliEmcalParticle *emctrack = static_cast<AliEmcalParticle*>(fTracks->At(t));
452 AliVTrack *track = emctrack->GetTrack();
455 if (!AcceptTrack(track))
458 Int_t Nclus = emctrack->GetNumberOfMatchedObj();
461 // loop over matched clusters
462 for (Int_t i = 0; i < Nclus; ++i) {
463 Int_t c = emctrack->GetMatchedObjId(i);
464 AliEmcalParticle *emccluster = static_cast<AliEmcalParticle*>(fCaloClusters->At(c));
468 AliVCluster *cluster = emccluster->GetCluster();
472 Double_t etadiff = 999;
473 Double_t phidiff = 999;
474 AliPicoTrack::GetEtaPhiDiff(track, cluster, phidiff, etadiff);
476 Double_t mom = track->P();
477 Int_t mombin = GetMomBin(mom);
478 Int_t centbinch = fCentBin;
479 if (track->Charge()<0)
482 Double_t etaCut = 0.0;
483 Double_t phiCutlo = 0.0;
484 Double_t phiCuthi = 0.0;
487 phiCutlo = -fPhiMatch;
488 phiCuthi = +fPhiMatch;
490 phiCutlo = GetPhiMean(mombin, centbinch) - GetPhiSigma(mombin, fCentBin);
491 phiCuthi = GetPhiMean(mombin, centbinch) + GetPhiSigma(mombin, fCentBin);
498 etaCut = GetEtaSigma(mombin);
501 if ((phidiff < phiCuthi && phidiff > phiCutlo) && TMath::Abs(etadiff) < etaCut) {
506 fHistNMatchCent_trk->Fill(fCent, Nmatches);
508 if (Nmatches == 0 && track->Pt() > 2.0)
509 fHistNoMatchEtaPhi->Fill(track->GetTrackEtaOnEMCal(), track->GetTrackPhiOnEMCal());
513 //________________________________________________________________________
514 void AliHadCorrTask::DoMatchedTracksLoop(AliEmcalParticle *emccluster, Double_t &totalTrkP, Int_t &Nmatches)
516 // Do the loop over matched tracks for cluster emccluster.
518 AliVCluster *cluster = emccluster->GetCluster();
519 Int_t iClus = emccluster->IdInCollection();
520 Double_t energyclus = cluster->E();
522 // loop over matched tracks
523 const Int_t Ntrks = emccluster->GetNumberOfMatchedObj();
524 for (Int_t i = 0; i < Ntrks; ++i) {
525 Int_t iTrack = emccluster->GetMatchedObjId(i);
526 Double_t dR = emccluster->GetMatchedObjDistance(i);
528 AliEmcalParticle *emctrack = static_cast<AliEmcalParticle*>(fTracks->At(iTrack));
531 AliVTrack *track = emctrack->GetTrack();
534 if (!AcceptTrack(track))
537 // check if track also points to cluster
538 if (fDoTrackClus && (track->GetEMCALcluster()) != iClus)
541 Double_t etadiff = 999;
542 Double_t phidiff = 999;
543 AliPicoTrack::GetEtaPhiDiff(track, cluster, phidiff, etadiff);
545 Double_t mom = track->P();
546 Int_t mombin = GetMomBin(mom);
547 Int_t centbinch = fCentBin;
548 if (track->Charge()<0)
553 if(track->Eta() > 0) etabin=1;
554 fHistMatchEtaPhi[centbinch][mombin][etabin]->Fill(etadiff, phidiff);
557 Double_t etaCut = 0.0;
558 Double_t phiCutlo = 0.0;
559 Double_t phiCuthi = 0.0;
562 phiCutlo = -fPhiMatch;
563 phiCuthi = +fPhiMatch;
565 phiCutlo = GetPhiMean(mombin, centbinch) - GetPhiSigma(mombin, fCentBin);
566 phiCuthi = GetPhiMean(mombin, centbinch) + GetPhiSigma(mombin, fCentBin);
572 etaCut = GetEtaSigma(mombin);
575 if ((phidiff < phiCuthi && phidiff > phiCutlo) && TMath::Abs(etadiff) < etaCut) {
577 totalTrkP += track->P();
580 if (fHadCorr > 1 && mombin > -1) {
581 fHistMatchdRvsEP[fCentBin]->Fill(dR, energyclus / mom);
588 //________________________________________________________________________
589 Bool_t AliHadCorrTask::Run()
591 // Run the hadronic correction
593 // post output in event if not yet present
594 if (!(InputEvent()->FindListObject(fOutCaloName)))
595 InputEvent()->AddObject(fOutClusters);
598 fOutClusters->Delete();
601 Bool_t esdMode = kTRUE;
602 if (dynamic_cast<AliAODEvent*>(InputEvent()))
605 if (esdMode) { // optimization in case autobranch loading is off
606 AliAnalysisManager *am = AliAnalysisManager::GetAnalysisManager();
607 if (fCaloName == "CaloClusters")
608 am->LoadBranch("CaloClusters");
609 if (fTracksName == "Tracks")
610 am->LoadBranch("Tracks");
611 am->LoadBranch("Centrality");
615 fHistCentrality->Fill(fCent);
620 // loop over all clusters
621 const Int_t Nclus = fCaloClusters->GetEntries();
622 for (Int_t iClus = 0, clusCount=0; iClus < Nclus; ++iClus) {
623 AliEmcalParticle *emccluster = static_cast<AliEmcalParticle*>(fCaloClusters->At(iClus));
627 AliVCluster *cluster = emccluster->GetCluster();
630 if (!AcceptCluster(cluster))
633 Double_t energyclus = 0;
635 fHistEbefore->Fill(fCent, cluster->E());
637 // apply correction / subtraction
639 // to subtract only the closest track set fHadCor to a %
640 // to subtract all tracks within the cut set fHadCor to %+1
642 energyclus = ApplyHadCorrAllTracks(emccluster, fHadCorr - 1);
644 energyclus = ApplyHadCorrOneTrack(emccluster, fHadCorr);
650 if (energyclus > 0) { // create corrected cluster
653 AliESDCaloCluster *ec = dynamic_cast<AliESDCaloCluster*>(cluster);
656 oc = new ((*fOutClusters)[clusCount]) AliESDCaloCluster(*ec);
658 AliAODCaloCluster *ac = dynamic_cast<AliAODCaloCluster*>(cluster);
661 oc = new ((*fOutClusters)[clusCount]) AliAODCaloCluster(*ac);
663 oc->SetE(energyclus);
668 fHistEafter->Fill(fCent, energyclus);
675 //________________________________________________________________________
676 Double_t AliHadCorrTask::ApplyHadCorrOneTrack(AliEmcalParticle *emccluster, Double_t hadCorr)
678 // Apply the hadronic correction with one track only.
680 AliVCluster *cluster = emccluster->GetCluster();
681 Double_t energyclus = cluster->E();
682 Int_t iMin = emccluster->GetMatchedObjId();
686 AliEmcalParticle *emctrack = static_cast<AliEmcalParticle*>(fTracks->At(iMin));
690 // check if track also points to cluster
691 Int_t cid = emctrack->GetMatchedObjId();
692 if (fDoTrackClus && (cid!=emccluster->IdInCollection()))
695 AliVTrack *track = emctrack->GetTrack();
699 Double_t mom = track->P();
703 Double_t dRmin = emccluster->GetMatchedObjDistance();
704 Double_t dEtaMin = 1e9;
705 Double_t dPhiMin = 1e9;
706 AliPicoTrack::GetEtaPhiDiff(track, cluster, dPhiMin, dEtaMin);
708 Int_t mombin = GetMomBin(mom);
709 Int_t centbinch = fCentBin;
710 if (track->Charge()<0)
713 // plot some histograms if switched on
719 fHistMatchEtaPhi[centbinch][mombin][etabin]->Fill(dEtaMin, dPhiMin);
722 fHistMatchEvsP[fCentBin]->Fill(energyclus, energyclus / mom);
723 fHistEoPCent->Fill(fCent, energyclus / mom);
724 fHistMatchdRvsEP[fCentBin]->Fill(dRmin, energyclus / mom);
728 // define eta/phi cuts
729 Double_t etaCut = 0.0;
730 Double_t phiCutlo = 0.0;
731 Double_t phiCuthi = 0.0;
733 phiCutlo = -fPhiMatch;
734 phiCuthi = +fPhiMatch;
737 phiCutlo = GetPhiMean(mombin, centbinch) - GetPhiSigma(mombin, fCentBin);
738 phiCuthi = GetPhiMean(mombin, centbinch) + GetPhiSigma(mombin, fCentBin);
744 etaCut = GetEtaSigma(mombin);
747 // apply the correction if the track is in the eta/phi window
748 if ((dPhiMin < phiCuthi && dPhiMin > phiCutlo) && TMath::Abs(dEtaMin) < etaCut) {
749 energyclus -= hadCorr * mom;
755 //________________________________________________________________________
756 Double_t AliHadCorrTask::ApplyHadCorrAllTracks(AliEmcalParticle *emccluster, Double_t hadCorr)
758 // Apply the hadronic correction with all tracks.
760 AliVCluster *cluster = emccluster->GetCluster();
762 Double_t energyclus = cluster->E();
763 Double_t cNcells = cluster->GetNCells();
765 Double_t totalTrkP = 0.0; // count total track momentum
766 Int_t Nmatches = 0; // count total number of matches
768 // do the loop over the matched tracks and get the number of matches and the total momentum
769 DoMatchedTracksLoop(emccluster, totalTrkP, Nmatches);
771 if(fCreateHisto && Nmatches == 0) {
772 fHistNclusvsCent->Fill(fCent);
773 fHistNCellsEnergy[fCentBin][0]->Fill(energyclus, cNcells);
779 Double_t Esub = hadCorr * totalTrkP;
781 Double_t clusEexcl = fEexclCell * cNcells;
783 if (energyclus < clusEexcl)
784 clusEexcl = energyclus;
786 if (Esub > energyclus)
789 // applying Peter's proposed algorithm
790 // never subtract the full energy of the cluster
791 if ((energyclus - Esub) < clusEexcl)
792 Esub = (energyclus - clusEexcl);
794 Double_t EoP = energyclus / totalTrkP;
796 // plot some histograms if switched on
798 fHistNMatchCent->Fill(fCent, Nmatches);
799 fHistNMatchEnergy[fCentBin]->Fill(energyclus, Nmatches);
802 fHistNclusMatchvsCent->Fill(fCent);
805 fHistNCellsEnergy[fCentBin][1]->Fill(energyclus, cNcells);
806 else if(Nmatches == 2)
807 fHistNCellsEnergy[fCentBin][2]->Fill(energyclus, cNcells);
808 else if(Nmatches > 2)
809 fHistNCellsEnergy[fCentBin][3]->Fill(energyclus, cNcells);
812 fHistEoPCent->Fill(fCent, EoP);
813 fHistMatchEvsP[fCentBin]->Fill(energyclus, EoP);
817 Int_t iMin = emccluster->GetMatchedObjId();
818 AliEmcalParticle *emctrack = static_cast<AliEmcalParticle*>(fTracks->At(iMin));
819 AliVTrack *track = emctrack->GetTrack();
820 Int_t centbinchm = fCentBin;
821 if (track->Charge()<0)
824 fHistEsubPchRat[centbinchm]->Fill(totalTrkP, Esub / totalTrkP);
825 fHistEsubPch[centbinchm]->Fill(totalTrkP, Esub);
829 // apply the correction