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;
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"),
79 fHistNclusMatchvsCent(0),
84 fHistNClusMatchCent(0)
86 // Standard constructor.
88 for(Int_t i=0; i<8; i++) {
90 fHistMatchEvsP[i] = 0;
91 fHistMatchdRvsEP[i] = 0;
92 for(Int_t j=0; j<3; j++) {
93 fHistNCellsEnergy[i][j] = 0;
97 fHistEsubPchRat[i] = 0;
98 for(Int_t j=0; j<9; j++) {
99 for(Int_t k=0; k<2; k++) {
100 fHistMatchEtaPhi[i][j][k] = 0;
105 SetMakeGeneralHistograms(histo);
107 fBranchNames="ESD:AliESDRun.,AliESDHeader.,PrimaryVertex.";
110 //________________________________________________________________________
111 AliHadCorrTask::~AliHadCorrTask()
116 //________________________________________________________________________
117 Int_t AliHadCorrTask::GetMomBin(Double_t p) const
124 else if (p>=0.5 && p<1.0)
126 else if (p>=1.0 && p<1.5)
128 else if (p>=1.5 && p<2.)
130 else if (p>=2. && p<3.)
132 else if (p>=3. && p<4.)
134 else if (p>=4. && p<5.)
136 else if (p>=5. && p<8.)
144 //________________________________________________________________________
145 Double_t AliHadCorrTask::GetEtaSigma(Int_t pbin) const
149 Double_t EtaSigma[9]={0.0097,0.0075,0.0059,0.0055,0.0053,0.005,0.005,0.0045,0.0042};
150 return 2.0*EtaSigma[pbin];
153 //________________________________________________________________________
154 Double_t AliHadCorrTask::GetPhiMean(Int_t pbin, Int_t centbin) const
159 Double_t PhiMean[9]={0.036,
168 return PhiMean[pbin];
169 } else if (centbin==1) {
170 Double_t PhiMean[9]={0.036,
179 return PhiMean[pbin];
180 } else if (centbin==2) {
181 Double_t PhiMean[9]={0.036,
190 return PhiMean[pbin];
191 } else if (centbin==3) {
192 Double_t PhiMean[9]={0.036,
201 return PhiMean[pbin];
202 } else if (centbin==4) {
203 Double_t PhiMean[9]={0.036,
212 return PhiMean[pbin]*(-1.);
213 } else if (centbin==5) {
214 Double_t PhiMean[9]={0.036,
223 return PhiMean[pbin]*(-1.);
224 } else if (centbin==6) {
225 Double_t PhiMean[9]={0.036,
234 return PhiMean[pbin]*(-1.);
235 } else if (centbin==7) {
236 Double_t PhiMean[9]={0.036,
245 return PhiMean[pbin]*(-1.);
251 //________________________________________________________________________
252 Double_t AliHadCorrTask::GetPhiSigma(Int_t pbin, Int_t centbin) const
257 Double_t PhiSigma[9]={0.0221,
266 return 2.*PhiSigma[pbin];
267 } else if (centbin==1) {
268 Double_t PhiSigma[9]={0.0217,
277 return 2.*PhiSigma[pbin];
278 } else if (centbin==2) {
279 Double_t PhiSigma[9]={0.0211,
288 return 2.*PhiSigma[pbin];
289 } else if (centbin==3) {
290 Double_t PhiSigma[9]={0.0215,
299 return 2.*PhiSigma[pbin];
300 } else if (centbin==4) {
301 Double_t PhiSigma[9]={0.0199,
310 return 2.*PhiSigma[pbin];
311 } else if (centbin==5) {
312 Double_t PhiSigma[9]={0.0200,
321 return 2.*PhiSigma[pbin];
322 } else if (centbin==6) {
323 Double_t PhiSigma[9]={0.0202,
332 return 2.*PhiSigma[pbin];
333 } else if (centbin==7) {
334 Double_t PhiSigma[9]={0.0205,
343 return 2.*PhiSigma[pbin];
349 //________________________________________________________________________
350 void AliHadCorrTask::UserCreateOutputObjects()
352 // Create my user objects.
357 AliAnalysisTaskEmcal::UserCreateOutputObjects();
361 for(Int_t icent=0; icent<8; ++icent) {
362 for(Int_t ipt=0; ipt<9; ++ipt) {
363 for(Int_t ieta=0; ieta<2; ++ieta) {
364 name = Form("fHistMatchEtaPhi_%i_%i_%i",icent,ipt,ieta);
365 fHistMatchEtaPhi[icent][ipt][ieta] = new TH2F(name, name, 200, -0.1, 0.1, 400, -0.2, 0.2);
366 fOutput->Add(fHistMatchEtaPhi[icent][ipt][ieta]);
370 name = Form("fHistEsubPch_%i",icent);
371 fHistEsubPch[icent]=new TH1F(name, name, 400, 0., 100.);
372 fOutput->Add(fHistEsubPch[icent]);
374 name = Form("fHistEsubPchRat_%i",icent);
375 fHistEsubPchRat[icent]=new TH2F(name, name, 400, 0., 200., 1000, 0., 10.);
376 fOutput->Add(fHistEsubPchRat[icent]);
379 for(Int_t itrk=0; itrk<4; ++itrk) {
380 name = Form("fHistNCellsEnergy_%i_%i",icent,itrk);
381 fHistNCellsEnergy[icent][itrk] = new TH2F(name, name, 1000, 0, 100, 101, -0.5, 100.5);
382 fOutput->Add(fHistNCellsEnergy[icent][itrk]);
385 name = Form("fHistMatchEvsP_%i",icent);
386 fHistMatchEvsP[icent] = new TH2F(name, name, 400, 0., 200., 1000, 0., 10.);
387 fOutput->Add(fHistMatchEvsP[icent]);
389 name = Form("fHistMatchdRvsEP_%i",icent);
390 fHistMatchdRvsEP[icent] = new TH2F(name, name, 1000, 0., 1., 1000, 0., 10.);
391 fOutput->Add(fHistMatchdRvsEP[icent]);
393 name = Form("fHistNMatchEnergy_%i",icent);
394 fHistNMatchEnergy[icent] = new TH2F(name, name, 1000, 0, 100, 101, -0.5, 100.5);
395 fOutput->Add(fHistNMatchEnergy[icent]);
399 fHistNclusvsCent = new TH1F("Nclusvscent", "NclusVsCent", 100, 0, 100);
400 fHistNclusMatchvsCent = new TH1F("NclusMatchvscent", "NclusMatchVsCent", 100, 0, 100);
401 fHistEbefore = new TH1F("Ebefore", "Ebefore", 100, 0, 100);
402 fHistEafter = new TH1F("Eafter", "Eafter", 100, 0, 100);
403 fHistEoPCent = new TH2F("EoPCent", "EoPCent", 100, 0, 100, 1000, 0, 10);
404 fHistNMatchCent = new TH2F("NMatchesCent", "NMatchesCent", 100, 0, 100, 11, -0.5, 10.5);
405 fHistNClusMatchCent = new TH2F("NClusMatchesCent", "NClusMatchesCent", 100, 0, 100, 11, -0.5, 10.5);
407 fOutput->Add(fHistNclusMatchvsCent);
408 fOutput->Add(fHistNclusvsCent);
409 fOutput->Add(fHistEbefore);
410 fOutput->Add(fHistEafter);
411 fOutput->Add(fHistEoPCent);
412 fOutput->Add(fHistNMatchCent);
413 fOutput->Add(fHistNClusMatchCent);
415 PostData(1, fOutput);
418 //________________________________________________________________________
419 void AliHadCorrTask::ExecOnce()
421 // Init the analysis.
423 if (dynamic_cast<AliAODEvent*>(InputEvent()))
426 if (fEsdMode) { // optimization in case autobranch loading is off
427 AliAnalysisManager *am = AliAnalysisManager::GetAnalysisManager();
428 if (fCaloName == "CaloClusters")
429 am->LoadBranch("CaloClusters");
430 if (fTracksName == "Tracks")
431 am->LoadBranch("Tracks");
432 am->LoadBranch("Centrality.");
436 fOutClusters = new TClonesArray("AliESDCaloCluster");
438 fOutClusters = new TClonesArray("AliAODCaloCluster");
440 fOutClusters->SetName(fOutCaloName);
442 // post output in event if not yet present
443 if (!(InputEvent()->FindListObject(fOutCaloName))) {
444 InputEvent()->AddObject(fOutClusters);
447 AliFatal(Form("%s: Container with same name %s already present. Aborting", GetName(), fOutCaloName.Data()));
451 AliAnalysisTaskEmcal::ExecOnce();
454 //________________________________________________________________________
455 void AliHadCorrTask::DoTrackLoop()
457 const Int_t Ntracks = fTracks->GetEntries();
458 for (Int_t iTrk = 0; iTrk < Ntracks; ++iTrk) {
459 Int_t NmatchClus = 0;
461 AliEmcalParticle *emctrack = static_cast<AliEmcalParticle*>(fTracks->At(iTrk));
464 if (!emctrack->IsEMCAL())
467 AliVTrack *track = emctrack->GetTrack();
470 if (!AcceptTrack(track))
473 if (track->GetTrackEtaOnEMCal() < fGeom->GetArm1EtaMin() + fEtaMatch ||
474 track->GetTrackEtaOnEMCal() > fGeom->GetArm1EtaMax() - fEtaMatch ||
475 track->GetTrackPhiOnEMCal() < fGeom->GetArm1PhiMin() * TMath::DegToRad() + fPhiMatch ||
476 track->GetTrackPhiOnEMCal() > fGeom->GetArm1PhiMax() * TMath::DegToRad() - fPhiMatch)
479 Int_t Nclus = emctrack->GetNumberOfMatchedObj();
481 for (Int_t iClus = 0; iClus < Nclus; ++iClus) {
482 AliEmcalParticle *emccluster = static_cast<AliEmcalParticle*>(fCaloClusters->At(iClus));
486 AliVCluster *cluster = emccluster->GetCluster();
489 if (!AcceptCluster(cluster))
492 Double_t etadiff = 999;
493 Double_t phidiff = 999;
494 AliPicoTrack::GetEtaPhiDiff(track, cluster, phidiff, etadiff);
496 if (TMath::Abs(phidiff) < fPhiMatch && TMath::Abs(etadiff) < fEtaMatch)
499 fHistNClusMatchCent->Fill(fCent, NmatchClus);
503 //________________________________________________________________________
504 void AliHadCorrTask::DoMatchedTracksLoop(AliEmcalParticle *emccluster, Double_t &totalTrkP, Int_t &Nmatches)
506 // Do the loop over matched tracks for cluster emccluster.
508 AliVCluster *cluster = emccluster->GetCluster();
509 Int_t iClus = emccluster->IdInCollection();
510 Double_t energyclus = cluster->E();
512 // loop over matched tracks
513 const Int_t Ntrks = emccluster->GetNumberOfMatchedObj();
514 for (Int_t i = 0; i < Ntrks; ++i) {
515 Int_t iTrack = emccluster->GetMatchedObjId(i);
516 Double_t dR = emccluster->GetMatchedObjDistance(i);
518 AliEmcalParticle *emctrack = static_cast<AliEmcalParticle*>(fTracks->At(iTrack));
521 AliVTrack *track = emctrack->GetTrack();
524 if (!AcceptTrack(track))
527 // check if track also points to cluster
528 if (fDoTrackClus && (track->GetEMCALcluster()) != iClus)
531 Double_t etadiff = 999;
532 Double_t phidiff = 999;
533 AliPicoTrack::GetEtaPhiDiff(track, cluster, phidiff, etadiff);
535 Double_t mom = track->P();
536 Int_t mombin = GetMomBin(mom);
537 Int_t centbinch = fCentBin;
538 if (track->Charge()<0)
543 if(track->Eta() > 0) etabin=1;
544 fHistMatchEtaPhi[centbinch][mombin][etabin]->Fill(etadiff, phidiff);
547 Double_t etaCut = 0.0;
548 Double_t phiCutlo = 0.0;
549 Double_t phiCuthi = 0.0;
552 phiCutlo = -fPhiMatch;
553 phiCuthi = +fPhiMatch;
555 phiCutlo = GetPhiMean(mombin, centbinch) - GetPhiSigma(mombin, fCentBin);
556 phiCuthi = GetPhiMean(mombin, centbinch) + GetPhiSigma(mombin, fCentBin);
562 etaCut = GetEtaSigma(mombin);
565 if ((phidiff < phiCuthi && phidiff > phiCutlo) && TMath::Abs(etadiff) < etaCut) {
567 totalTrkP += track->P();
570 if (fHadCorr > 1 && mombin > -1) {
571 fHistMatchdRvsEP[fCentBin]->Fill(dR, energyclus / mom);
578 //________________________________________________________________________
579 Bool_t AliHadCorrTask::Run()
581 // Run the hadronic correction
587 fOutClusters->Delete();
589 // loop over all clusters
590 const Int_t Nclus = fCaloClusters->GetEntries();
591 for (Int_t iClus = 0, clusCount=0; iClus < Nclus; ++iClus) {
592 AliEmcalParticle *emccluster = static_cast<AliEmcalParticle*>(fCaloClusters->At(iClus));
596 AliVCluster *cluster = emccluster->GetCluster();
599 if (!AcceptCluster(cluster))
602 Double_t energyclus = 0;
604 fHistEbefore->Fill(fCent, cluster->E());
606 // apply correction / subtraction
608 // to subtract only the closest track set fHadCor to a %
609 // to subtract all tracks within the cut set fHadCor to %+1
611 energyclus = ApplyHadCorrAllTracks(emccluster, fHadCorr - 1);
613 energyclus = ApplyHadCorrOneTrack(emccluster, fHadCorr);
619 if (energyclus > 0) { // create corrected cluster
622 AliESDCaloCluster *ec = dynamic_cast<AliESDCaloCluster*>(cluster);
625 oc = new ((*fOutClusters)[clusCount]) AliESDCaloCluster(*ec);
627 AliAODCaloCluster *ac = dynamic_cast<AliAODCaloCluster*>(cluster);
630 oc = new ((*fOutClusters)[clusCount]) AliAODCaloCluster(*ac);
632 oc->SetE(energyclus);
637 fHistEafter->Fill(fCent, energyclus);
644 //________________________________________________________________________
645 Double_t AliHadCorrTask::ApplyHadCorrOneTrack(AliEmcalParticle *emccluster, Double_t hadCorr)
647 // Apply the hadronic correction with one track only.
649 AliVCluster *cluster = emccluster->GetCluster();
650 Double_t energyclus = cluster->E();
651 Int_t iMin = emccluster->GetMatchedObjId();
655 AliEmcalParticle *emctrack = static_cast<AliEmcalParticle*>(fTracks->At(iMin));
659 // check if track also points to cluster
660 Int_t cid = emctrack->GetMatchedObjId();
661 if (fDoTrackClus && (cid!=emccluster->IdInCollection()))
664 AliVTrack *track = emctrack->GetTrack();
668 Double_t mom = track->P();
672 Double_t dRmin = emccluster->GetMatchedObjDistance();
673 Double_t dEtaMin = 1e9;
674 Double_t dPhiMin = 1e9;
675 AliPicoTrack::GetEtaPhiDiff(track, cluster, dPhiMin, dEtaMin);
677 Int_t mombin = GetMomBin(mom);
678 Int_t centbinch = fCentBin;
679 if (track->Charge()<0)
682 // plot some histograms if switched on
688 fHistMatchEtaPhi[centbinch][mombin][etabin]->Fill(dEtaMin, dPhiMin);
691 fHistMatchEvsP[fCentBin]->Fill(energyclus, energyclus / mom);
692 fHistEoPCent->Fill(fCent, energyclus / mom);
693 fHistMatchdRvsEP[fCentBin]->Fill(dRmin, energyclus / mom);
697 // define eta/phi cuts
698 Double_t etaCut = 0.0;
699 Double_t phiCutlo = 0.0;
700 Double_t phiCuthi = 0.0;
702 phiCutlo = -fPhiMatch;
703 phiCuthi = +fPhiMatch;
706 phiCutlo = GetPhiMean(mombin, centbinch) - GetPhiSigma(mombin, fCentBin);
707 phiCuthi = GetPhiMean(mombin, centbinch) + GetPhiSigma(mombin, fCentBin);
713 etaCut = GetEtaSigma(mombin);
716 // apply the correction if the track is in the eta/phi window
717 if ((dPhiMin < phiCuthi && dPhiMin > phiCutlo) && TMath::Abs(dEtaMin) < etaCut) {
718 energyclus -= hadCorr * mom;
724 //________________________________________________________________________
725 Double_t AliHadCorrTask::ApplyHadCorrAllTracks(AliEmcalParticle *emccluster, Double_t hadCorr)
727 // Apply the hadronic correction with all tracks.
729 AliVCluster *cluster = emccluster->GetCluster();
731 Double_t energyclus = cluster->E();
732 Double_t cNcells = cluster->GetNCells();
734 Double_t totalTrkP = 0.0; // count total track momentum
735 Int_t Nmatches = 0; // count total number of matches
737 // do the loop over the matched tracks and get the number of matches and the total momentum
738 DoMatchedTracksLoop(emccluster, totalTrkP, Nmatches);
740 Double_t Esub = hadCorr * totalTrkP;
742 if (Esub > energyclus)
745 // applying Peter's proposed algorithm
746 // never subtract the full energy of the cluster
747 Double_t clusEexcl = fEexclCell * cNcells;
748 if (energyclus < clusEexcl)
749 clusEexcl = energyclus;
750 if ((energyclus - Esub) < clusEexcl)
751 Esub = (energyclus - clusEexcl);
755 EoP = energyclus / totalTrkP;
757 // plot some histograms if switched on
759 fHistNclusvsCent->Fill(fCent);
760 fHistNMatchCent->Fill(fCent, Nmatches);
761 fHistNMatchEnergy[fCentBin]->Fill(energyclus, Nmatches);
764 fHistNclusMatchvsCent->Fill(fCent);
767 fHistNCellsEnergy[fCentBin][Nmatches]->Fill(energyclus, cNcells);
769 fHistNCellsEnergy[fCentBin][3]->Fill(energyclus, cNcells);
772 fHistEoPCent->Fill(fCent, EoP);
773 fHistMatchEvsP[fCentBin]->Fill(energyclus, EoP);
776 if (Nmatches == 1 && totalTrkP > 0) {
777 Int_t iMin = emccluster->GetMatchedObjId();
778 AliEmcalParticle *emctrack = static_cast<AliEmcalParticle*>(fTracks->At(iMin));
779 AliVTrack *track = emctrack->GetTrack();
780 Int_t centbinchm = fCentBin;
781 if (track->Charge()<0)
784 fHistEsubPchRat[centbinchm]->Fill(totalTrkP, Esub / totalTrkP);
785 fHistEsubPch[centbinchm]->Fill(totalTrkP, Esub);
789 // apply the correction