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"
21 #include "AliEMCALGeometry.h"
23 #include "AliHadCorrTask.h"
25 ClassImp(AliHadCorrTask)
27 //________________________________________________________________________
28 AliHadCorrTask::AliHadCorrTask() :
29 AliAnalysisTaskEmcal("AliHadCorrTask", kFALSE),
39 fHistNclusMatchvsCent(0),
44 fHistNClusMatchCent(0)
46 // Default constructor.
48 for(Int_t i=0; i<8; i++) {
50 fHistEsubPchRat[i] = 0;
53 fHistMatchEvsP[i] = 0;
54 fHistMatchdRvsEP[i] = 0;
55 fHistNMatchEnergy[i] = 0;
57 for(Int_t j=0; j<4; j++)
58 fHistNCellsEnergy[i][j] = 0;
61 for(Int_t j=0; j<9; j++) {
62 for(Int_t k=0; k<2; k++)
63 fHistMatchEtaPhi[i][j][k] = 0;
68 //________________________________________________________________________
69 AliHadCorrTask::AliHadCorrTask(const char *name, Bool_t histo) :
70 AliAnalysisTaskEmcal(name, histo),
71 fOutCaloName("CaloClustersCorr"),
80 fHistNclusMatchvsCent(0),
85 fHistNClusMatchCent(0)
87 // Standard constructor.
89 for(Int_t i=0; i<8; i++) {
91 fHistEsubPchRat[i] = 0;
94 fHistMatchEvsP[i] = 0;
95 fHistMatchdRvsEP[i] = 0;
96 fHistNMatchEnergy[i] = 0;
98 for(Int_t j=0; j<4; j++)
99 fHistNCellsEnergy[i][j] = 0;
102 for(Int_t j=0; j<9; j++) {
103 for(Int_t k=0; k<2; k++)
104 fHistMatchEtaPhi[i][j][k] = 0;
108 SetMakeGeneralHistograms(histo);
110 fBranchNames="ESD:AliESDRun.,AliESDHeader.,PrimaryVertex.";
113 //________________________________________________________________________
114 AliHadCorrTask::~AliHadCorrTask()
119 //________________________________________________________________________
120 Int_t AliHadCorrTask::GetMomBin(Double_t p) const
127 else if (p>=0.5 && p<1.0)
129 else if (p>=1.0 && p<1.5)
131 else if (p>=1.5 && p<2.)
133 else if (p>=2. && p<3.)
135 else if (p>=3. && p<4.)
137 else if (p>=4. && p<5.)
139 else if (p>=5. && p<8.)
147 //________________________________________________________________________
148 Double_t AliHadCorrTask::GetEtaSigma(Int_t pbin) const
152 Double_t EtaSigma[9]={0.0097,0.0075,0.0059,0.0055,0.0053,0.005,0.005,0.0045,0.0042};
153 return 2.0*EtaSigma[pbin];
156 //________________________________________________________________________
157 Double_t AliHadCorrTask::GetPhiMean(Int_t pbin, Int_t centbin) const
162 Double_t PhiMean[9]={0.036,
171 return PhiMean[pbin];
172 } else if (centbin==1) {
173 Double_t PhiMean[9]={0.036,
182 return PhiMean[pbin];
183 } else if (centbin==2) {
184 Double_t PhiMean[9]={0.036,
193 return PhiMean[pbin];
194 } else if (centbin==3) {
195 Double_t PhiMean[9]={0.036,
204 return PhiMean[pbin];
205 } else if (centbin==4) {
206 Double_t PhiMean[9]={0.036,
215 return PhiMean[pbin]*(-1.);
216 } else if (centbin==5) {
217 Double_t PhiMean[9]={0.036,
226 return PhiMean[pbin]*(-1.);
227 } else if (centbin==6) {
228 Double_t PhiMean[9]={0.036,
237 return PhiMean[pbin]*(-1.);
238 } else if (centbin==7) {
239 Double_t PhiMean[9]={0.036,
248 return PhiMean[pbin]*(-1.);
254 //________________________________________________________________________
255 Double_t AliHadCorrTask::GetPhiSigma(Int_t pbin, Int_t centbin) const
260 Double_t PhiSigma[9]={0.0221,
269 return 2.*PhiSigma[pbin];
270 } else if (centbin==1) {
271 Double_t PhiSigma[9]={0.0217,
280 return 2.*PhiSigma[pbin];
281 } else if (centbin==2) {
282 Double_t PhiSigma[9]={0.0211,
291 return 2.*PhiSigma[pbin];
292 } else if (centbin==3) {
293 Double_t PhiSigma[9]={0.0215,
302 return 2.*PhiSigma[pbin];
303 } else if (centbin==4) {
304 Double_t PhiSigma[9]={0.0199,
313 return 2.*PhiSigma[pbin];
314 } else if (centbin==5) {
315 Double_t PhiSigma[9]={0.0200,
324 return 2.*PhiSigma[pbin];
325 } else if (centbin==6) {
326 Double_t PhiSigma[9]={0.0202,
335 return 2.*PhiSigma[pbin];
336 } else if (centbin==7) {
337 Double_t PhiSigma[9]={0.0205,
346 return 2.*PhiSigma[pbin];
352 //________________________________________________________________________
353 void AliHadCorrTask::UserCreateOutputObjects()
355 // Create my user objects.
360 AliAnalysisTaskEmcal::UserCreateOutputObjects();
364 for(Int_t icent=0; icent<8; ++icent) {
365 for(Int_t ipt=0; ipt<9; ++ipt) {
366 for(Int_t ieta=0; ieta<2; ++ieta) {
367 name = Form("fHistMatchEtaPhi_%i_%i_%i",icent,ipt,ieta);
368 fHistMatchEtaPhi[icent][ipt][ieta] = new TH2F(name, name, 200, -0.1, 0.1, 400, -0.2, 0.2);
369 fOutput->Add(fHistMatchEtaPhi[icent][ipt][ieta]);
373 name = Form("fHistEsubPch_%i",icent);
374 fHistEsubPch[icent]=new TH1F(name, name, 400, 0., 100.);
375 fOutput->Add(fHistEsubPch[icent]);
377 name = Form("fHistEsubPchRat_%i",icent);
378 fHistEsubPchRat[icent]=new TH2F(name, name, 400, 0., 200., 1000, 0., 10.);
379 fOutput->Add(fHistEsubPchRat[icent]);
382 for(Int_t itrk=0; itrk<4; ++itrk) {
383 name = Form("fHistNCellsEnergy_%i_%i",icent,itrk);
384 fHistNCellsEnergy[icent][itrk] = new TH2F(name, name, 1000, 0, 100, 101, -0.5, 100.5);
385 fOutput->Add(fHistNCellsEnergy[icent][itrk]);
388 name = Form("fHistMatchEvsP_%i",icent);
389 fHistMatchEvsP[icent] = new TH2F(name, name, 400, 0., 200., 1000, 0., 10.);
390 fOutput->Add(fHistMatchEvsP[icent]);
392 name = Form("fHistMatchdRvsEP_%i",icent);
393 fHistMatchdRvsEP[icent] = new TH2F(name, name, 1000, 0., 1., 1000, 0., 10.);
394 fOutput->Add(fHistMatchdRvsEP[icent]);
396 name = Form("fHistNMatchEnergy_%i",icent);
397 fHistNMatchEnergy[icent] = new TH2F(name, name, 1000, 0, 100, 101, -0.5, 100.5);
398 fOutput->Add(fHistNMatchEnergy[icent]);
402 fHistNclusvsCent = new TH1F("Nclusvscent", "NclusVsCent", 100, 0, 100);
403 fHistNclusMatchvsCent = new TH1F("NclusMatchvscent", "NclusMatchVsCent", 100, 0, 100);
404 fHistEbefore = new TH1F("Ebefore", "Ebefore", 100, 0, 100);
405 fHistEafter = new TH1F("Eafter", "Eafter", 100, 0, 100);
406 fHistEoPCent = new TH2F("EoPCent", "EoPCent", 100, 0, 100, 1000, 0, 10);
407 fHistNMatchCent = new TH2F("NMatchesCent", "NMatchesCent", 100, 0, 100, 11, -0.5, 10.5);
408 fHistNClusMatchCent = new TH2F("NClusMatchesCent", "NClusMatchesCent", 100, 0, 100, 11, -0.5, 10.5);
410 fOutput->Add(fHistNclusMatchvsCent);
411 fOutput->Add(fHistNclusvsCent);
412 fOutput->Add(fHistEbefore);
413 fOutput->Add(fHistEafter);
414 fOutput->Add(fHistEoPCent);
415 fOutput->Add(fHistNMatchCent);
416 fOutput->Add(fHistNClusMatchCent);
418 PostData(1, fOutput);
421 //________________________________________________________________________
422 void AliHadCorrTask::ExecOnce()
424 // Do base class initializations and if it fails -> bail out
426 AliAnalysisTaskEmcal::ExecOnce();
430 // Init the analysis.
432 AliAnalysisTaskEmcal::ExecOnce();
437 if (dynamic_cast<AliAODEvent*>(InputEvent()))
440 if (fEsdMode) { // optimization in case autobranch loading is off
441 AliAnalysisManager *am = AliAnalysisManager::GetAnalysisManager();
442 if (fCaloName == "CaloClusters")
443 am->LoadBranch("CaloClusters");
444 if (fTracksName == "Tracks")
445 am->LoadBranch("Tracks");
446 am->LoadBranch("Centrality.");
450 fOutClusters = new TClonesArray("AliESDCaloCluster");
452 fOutClusters = new TClonesArray("AliAODCaloCluster");
454 fOutClusters->SetName(fOutCaloName);
456 // post output in event if not yet present
457 if (!(InputEvent()->FindListObject(fOutCaloName))) {
458 InputEvent()->AddObject(fOutClusters);
461 fInitialized = kFALSE;
462 AliFatal(Form("%s: Container with same name %s already present. Aborting", GetName(), fOutCaloName.Data()));
463 fInitialized = kFALSE;
468 //________________________________________________________________________
469 void AliHadCorrTask::DoTrackLoop()
471 const Int_t Ntracks = fTracks->GetEntries();
472 for (Int_t iTrk = 0; iTrk < Ntracks; ++iTrk) {
473 Int_t NmatchClus = 0;
475 AliEmcalParticle *emctrack = static_cast<AliEmcalParticle*>(fTracks->At(iTrk));
478 if (!emctrack->IsEMCAL())
481 AliVTrack *track = emctrack->GetTrack();
484 if (!AcceptTrack(track))
487 if (track->GetTrackEtaOnEMCal() < fGeom->GetArm1EtaMin() + fEtaMatch ||
488 track->GetTrackEtaOnEMCal() > fGeom->GetArm1EtaMax() - fEtaMatch ||
489 track->GetTrackPhiOnEMCal() < fGeom->GetArm1PhiMin() * TMath::DegToRad() + fPhiMatch ||
490 track->GetTrackPhiOnEMCal() > fGeom->GetArm1PhiMax() * TMath::DegToRad() - fPhiMatch)
493 Int_t Nclus = emctrack->GetNumberOfMatchedObj();
495 for (Int_t iClus = 0; iClus < Nclus; ++iClus) {
496 AliEmcalParticle *emccluster = static_cast<AliEmcalParticle*>(fCaloClusters->At(iClus));
500 AliVCluster *cluster = emccluster->GetCluster();
503 if (!AcceptCluster(cluster))
506 Double_t etadiff = 999;
507 Double_t phidiff = 999;
508 AliPicoTrack::GetEtaPhiDiff(track, cluster, phidiff, etadiff);
510 if (TMath::Abs(phidiff) < fPhiMatch && TMath::Abs(etadiff) < fEtaMatch)
513 fHistNClusMatchCent->Fill(fCent, NmatchClus);
517 //________________________________________________________________________
518 void AliHadCorrTask::DoMatchedTracksLoop(AliEmcalParticle *emccluster, Double_t &totalTrkP, Int_t &Nmatches)
520 // Do the loop over matched tracks for cluster emccluster.
522 AliVCluster *cluster = emccluster->GetCluster();
523 Int_t iClus = emccluster->IdInCollection();
524 Double_t energyclus = cluster->E();
526 // loop over matched tracks
527 const Int_t Ntrks = emccluster->GetNumberOfMatchedObj();
528 for (Int_t i = 0; i < Ntrks; ++i) {
529 Int_t iTrack = emccluster->GetMatchedObjId(i);
530 Double_t dR = emccluster->GetMatchedObjDistance(i);
532 AliEmcalParticle *emctrack = static_cast<AliEmcalParticle*>(fTracks->At(iTrack));
535 AliVTrack *track = emctrack->GetTrack();
538 if (!AcceptTrack(track))
541 // check if track also points to cluster
542 if (fDoTrackClus && (track->GetEMCALcluster()) != iClus)
545 Double_t etadiff = 999;
546 Double_t phidiff = 999;
547 AliPicoTrack::GetEtaPhiDiff(track, cluster, phidiff, etadiff);
549 Double_t mom = track->P();
550 Int_t mombin = GetMomBin(mom);
551 Int_t centbinch = fCentBin;
552 if (track->Charge()<0)
557 if(track->Eta() > 0) etabin=1;
558 fHistMatchEtaPhi[centbinch][mombin][etabin]->Fill(etadiff, phidiff);
561 Double_t etaCut = 0.0;
562 Double_t phiCutlo = 0.0;
563 Double_t phiCuthi = 0.0;
566 phiCutlo = -fPhiMatch;
567 phiCuthi = +fPhiMatch;
569 phiCutlo = GetPhiMean(mombin, centbinch) - GetPhiSigma(mombin, fCentBin);
570 phiCuthi = GetPhiMean(mombin, centbinch) + GetPhiSigma(mombin, fCentBin);
576 etaCut = GetEtaSigma(mombin);
579 if ((phidiff < phiCuthi && phidiff > phiCutlo) && TMath::Abs(etadiff) < etaCut) {
581 totalTrkP += track->P();
584 if (fHadCorr > 1 && mombin > -1) {
585 fHistMatchdRvsEP[fCentBin]->Fill(dR, energyclus / mom);
592 //________________________________________________________________________
593 Bool_t AliHadCorrTask::Run()
595 // Run the hadronic correction
601 fOutClusters->Delete();
603 // loop over all clusters
604 const Int_t Nclus = fCaloClusters->GetEntries();
605 for (Int_t iClus = 0, clusCount=0; iClus < Nclus; ++iClus) {
606 AliEmcalParticle *emccluster = static_cast<AliEmcalParticle*>(fCaloClusters->At(iClus));
610 AliVCluster *cluster = emccluster->GetCluster();
613 if (!AcceptCluster(cluster))
616 Double_t energyclus = 0;
618 fHistEbefore->Fill(fCent, cluster->E());
620 // apply correction / subtraction
622 // to subtract only the closest track set fHadCor to a %
623 // to subtract all tracks within the cut set fHadCor to %+1
625 energyclus = ApplyHadCorrAllTracks(emccluster, fHadCorr - 1);
627 energyclus = ApplyHadCorrOneTrack(emccluster, fHadCorr);
633 if (energyclus > 0) { // create corrected cluster
636 AliESDCaloCluster *ec = dynamic_cast<AliESDCaloCluster*>(cluster);
639 oc = new ((*fOutClusters)[clusCount]) AliESDCaloCluster(*ec);
641 AliAODCaloCluster *ac = dynamic_cast<AliAODCaloCluster*>(cluster);
644 oc = new ((*fOutClusters)[clusCount]) AliAODCaloCluster(*ac);
646 oc->SetE(energyclus);
651 fHistEafter->Fill(fCent, energyclus);
658 //________________________________________________________________________
659 Double_t AliHadCorrTask::ApplyHadCorrOneTrack(AliEmcalParticle *emccluster, Double_t hadCorr)
661 // Apply the hadronic correction with one track only.
663 AliVCluster *cluster = emccluster->GetCluster();
664 Double_t energyclus = cluster->E();
665 Int_t iMin = emccluster->GetMatchedObjId();
669 AliEmcalParticle *emctrack = static_cast<AliEmcalParticle*>(fTracks->At(iMin));
673 // check if track also points to cluster
674 Int_t cid = emctrack->GetMatchedObjId();
675 if (fDoTrackClus && (cid!=emccluster->IdInCollection()))
678 AliVTrack *track = emctrack->GetTrack();
682 Double_t mom = track->P();
686 Double_t dRmin = emccluster->GetMatchedObjDistance();
687 Double_t dEtaMin = 1e9;
688 Double_t dPhiMin = 1e9;
689 AliPicoTrack::GetEtaPhiDiff(track, cluster, dPhiMin, dEtaMin);
691 Int_t mombin = GetMomBin(mom);
692 Int_t centbinch = fCentBin;
693 if (track->Charge()<0)
696 // plot some histograms if switched on
702 fHistMatchEtaPhi[centbinch][mombin][etabin]->Fill(dEtaMin, dPhiMin);
705 fHistMatchEvsP[fCentBin]->Fill(energyclus, energyclus / mom);
706 fHistEoPCent->Fill(fCent, energyclus / mom);
707 fHistMatchdRvsEP[fCentBin]->Fill(dRmin, energyclus / mom);
711 // define eta/phi cuts
712 Double_t etaCut = 0.0;
713 Double_t phiCutlo = 0.0;
714 Double_t phiCuthi = 0.0;
716 phiCutlo = -fPhiMatch;
717 phiCuthi = +fPhiMatch;
720 phiCutlo = GetPhiMean(mombin, centbinch) - GetPhiSigma(mombin, fCentBin);
721 phiCuthi = GetPhiMean(mombin, centbinch) + GetPhiSigma(mombin, fCentBin);
727 etaCut = GetEtaSigma(mombin);
730 // apply the correction if the track is in the eta/phi window
731 if ((dPhiMin < phiCuthi && dPhiMin > phiCutlo) && TMath::Abs(dEtaMin) < etaCut) {
732 energyclus -= hadCorr * mom;
738 //________________________________________________________________________
739 Double_t AliHadCorrTask::ApplyHadCorrAllTracks(AliEmcalParticle *emccluster, Double_t hadCorr)
741 // Apply the hadronic correction with all tracks.
743 AliVCluster *cluster = emccluster->GetCluster();
745 Double_t energyclus = cluster->E();
746 Double_t cNcells = cluster->GetNCells();
748 Double_t totalTrkP = 0.0; // count total track momentum
749 Int_t Nmatches = 0; // count total number of matches
751 // do the loop over the matched tracks and get the number of matches and the total momentum
752 DoMatchedTracksLoop(emccluster, totalTrkP, Nmatches);
754 Double_t Esub = hadCorr * totalTrkP;
756 if (Esub > energyclus)
759 // applying Peter's proposed algorithm
760 // never subtract the full energy of the cluster
761 Double_t clusEexcl = fEexclCell * cNcells;
762 if (energyclus < clusEexcl)
763 clusEexcl = energyclus;
764 if ((energyclus - Esub) < clusEexcl)
765 Esub = (energyclus - clusEexcl);
769 EoP = energyclus / totalTrkP;
771 // plot some histograms if switched on
773 fHistNclusvsCent->Fill(fCent);
774 fHistNMatchCent->Fill(fCent, Nmatches);
775 fHistNMatchEnergy[fCentBin]->Fill(energyclus, Nmatches);
778 fHistNclusMatchvsCent->Fill(fCent);
781 fHistNCellsEnergy[fCentBin][Nmatches]->Fill(energyclus, cNcells);
783 fHistNCellsEnergy[fCentBin][3]->Fill(energyclus, cNcells);
786 fHistEoPCent->Fill(fCent, EoP);
787 fHistMatchEvsP[fCentBin]->Fill(energyclus, EoP);
790 if (Nmatches == 1 && totalTrkP > 0) {
791 Int_t iMin = emccluster->GetMatchedObjId();
792 AliEmcalParticle *emctrack = static_cast<AliEmcalParticle*>(fTracks->At(iMin));
793 AliVTrack *track = emctrack->GetTrack();
794 Int_t centbinchm = fCentBin;
795 if (track->Charge()<0)
798 fHistEsubPchRat[centbinchm]->Fill(totalTrkP, Esub / totalTrkP);
799 fHistEsubPch[centbinchm]->Fill(totalTrkP, Esub);
803 // apply the correction