3 // Emcal jet finder task.
5 // Authors: C.Loizides, S.Aiola
8 #include "AliEmcalJetTask.h"
11 #include <TClonesArray.h>
13 #include <TLorentzVector.h>
16 #include "AliAnalysisManager.h"
17 #include "AliCentrality.h"
18 #include "AliEMCALGeometry.h"
19 #include "AliESDEvent.h"
20 #include "AliEmcalJet.h"
21 #include "AliEmcalParticle.h"
22 #include "AliFJWrapper.h"
23 #include "AliMCEvent.h"
24 #include "AliVCluster.h"
25 #include "AliVEvent.h"
26 #include "AliVParticle.h"
28 ClassImp(AliEmcalJetTask)
30 //________________________________________________________________________
31 AliEmcalJetTask::AliEmcalJetTask() :
32 AliAnalysisTaskSE("AliEmcalJetTask"),
33 fTracksName("Tracks"),
34 fCaloName("CaloClusters"),
38 fMCConstSel(kAllJets),
44 fPhiMax(TMath::TwoPi()),
63 // Default constructor.
66 //________________________________________________________________________
67 AliEmcalJetTask::AliEmcalJetTask(const char *name) :
68 AliAnalysisTaskSE(name),
69 fTracksName("Tracks"),
70 fCaloName("CaloClusters"),
72 fJetType(kAKT|kFullJet|kRX1Jet),
74 fMCConstSel(kAllJets),
80 fPhiMax(TMath::TwoPi()),
99 // Standard constructor.
101 fBranchNames="ESD:AliESDRun.,AliESDHeader.,PrimaryVertex.";
104 //________________________________________________________________________
105 AliEmcalJetTask::~AliEmcalJetTask()
110 //________________________________________________________________________
111 void AliEmcalJetTask::UserCreateOutputObjects()
113 // Create user objects.
115 fJets = new TClonesArray("AliEmcalJet");
116 fJets->SetName(fJetsName);
119 //________________________________________________________________________
120 void AliEmcalJetTask::UserExec(Option_t *)
122 // Main loop, called for each event.
133 //________________________________________________________________________
134 void AliEmcalJetTask::Terminate(Option_t *)
136 // Called once at the end of the analysis.
139 //________________________________________________________________________
140 void AliEmcalJetTask::FindJets()
144 if (!fTracks && !fClus)
148 fastjet::JetAlgorithm jalgo(fastjet::kt_algorithm);
149 if ((fJetType & kAKT) != 0) {
151 jalgo = fastjet::antikt_algorithm;
152 AliDebug(1,"Using AKT algorithm");
155 AliDebug(1,"Using KT algorithm");
158 if ((fJetType & kR020Jet) != 0)
160 else if ((fJetType & kR030Jet) != 0)
162 else if ((fJetType & kR040Jet) != 0)
166 AliFJWrapper fjw(name, name);
167 fjw.SetAreaType(fastjet::active_area_explicit_ghosts);
168 fjw.SetGhostArea(fGhostArea);
170 fjw.SetAlgorithm(jalgo);
174 // get primary vertex
175 Double_t vertex[3] = {0, 0, 0};
176 fEvent->GetPrimaryVertex()->GetXYZ(vertex);
178 AliDebug(2,Form("Jet type = %d", fJetType));
180 if ((fIsMcPart || ((fJetType & kFullJet) != 0) || ((fJetType & kChargedJet) != 0)) && fTracks) {
181 const Int_t Ntracks = fTracks->GetEntries();
182 for (Int_t iTracks = 0; iTracks < Ntracks; ++iTracks) {
183 AliVParticle *t = static_cast<AliVParticle*>(fTracks->At(iTracks));
187 if (((fJetType & kChargedJet) != 0) && (t->Charge() == 0)) {
188 AliDebug(2,Form("Skipping track %d because it is neutral.", iTracks));
191 if (((fJetType & kNeutralJet) != 0) && (t->Charge() != 0)) {
192 AliDebug(2,Form("Skipping track %d because it is charged.", iTracks));
196 if (fIsMcPart || t->GetLabel() != 0) {
197 if (fMCConstSel == kNone) {
198 AliDebug(2,Form("Skipping track %d because bit mask is 0.", iTracks));
201 if (fMCConstSel != kAllJets) {
202 if (t->TestBits(fMCConstSel) != (Int_t)fMCConstSel) {
203 AliDebug(2,Form("Skipping track %d because it does not match the bit mask (%d, %d)", iTracks, fMCConstSel, t->TestBits(TObject::kBitMask)));
207 AliDebug(2,Form("Track %d matches the bit mask (%d, %d)", iTracks, fMCConstSel, t->TestBits(TObject::kBitMask)));
212 if (fConstSel == kNone) {
213 AliDebug(2,Form("Skipping track %d because bit mask is 0.", iTracks));
216 if (fConstSel != kAllJets) {
217 if (t->TestBits(fConstSel) != (Int_t)fConstSel) {
218 AliDebug(2,Form("Skipping track %d because it does not match the bit mask (%d, %d)", iTracks, fConstSel, t->TestBits(TObject::kBitMask)));
222 AliDebug(2,Form("Track %d matches the bit mask (%d, %d)", iTracks, fConstSel, t->TestBits(TObject::kBitMask)));
226 if (t->Pt() < fMinJetTrackPt)
228 Double_t eta = t->Eta();
229 Double_t phi = t->Phi();
230 if ((eta<fEtaMin) || (eta>fEtaMax) ||
231 (phi<fPhiMin) || (phi>fPhiMax))
234 // offset of 100 for consistency with cluster ids
235 AliDebug(2,Form("Track %d accepted (label = %d, pt = %f)", iTracks, t->GetLabel(), t->Pt()));
236 fjw.AddInputVector(t->Px(), t->Py(), t->Pz(), t->P(), iTracks + 100);
240 if ((((fJetType & kFullJet) != 0) || ((fJetType & kNeutralJet) != 0)) && fClus) {
241 const Int_t Nclus = fClus->GetEntries();
242 for (Int_t iClus = 0; iClus < Nclus; ++iClus) {
244 Double_t cEta=0,cPhi=0,cPt=0;
245 Double_t cPx=0,cPy=0,cPz=0;
247 AliEmcalParticle *ep = static_cast<AliEmcalParticle*>(fClus->At(iClus));
251 c = ep->GetCluster();
255 if (c->GetLabel() > 0) {
256 if (fMCConstSel == kNone) {
257 AliDebug(2,Form("Skipping cluster %d because bit mask is 0.", iClus));
260 if (fMCConstSel != kAllJets) {
261 if (ep->TestBits(fMCConstSel) != (Int_t)fMCConstSel) {
262 AliDebug(2,Form("Skipping cluster %d because it does not match the bit mask (%d, %d)", iClus, fMCConstSel, ep->TestBits(TObject::kBitMask)));
266 AliDebug(2,Form("Cluster %d matches the bit mask (%d, %d)", iClus, fMCConstSel, ep->TestBits(TObject::kBitMask)));
271 if (fConstSel == kNone) {
272 AliDebug(2,Form("Skipping cluster %d because bit mask is 0.", iClus));
275 if (fConstSel != kAllJets) {
276 if (ep->TestBits(fConstSel) != (Int_t)fConstSel) {
277 AliDebug(2,Form("Skipping cluster %d because it does not match the bit mask (%d, %d)", iClus, fConstSel, ep->TestBits(TObject::kBitMask)));
281 AliDebug(2,Form("Cluster %d matches the bit mask (%d, %d)", iClus, fConstSel, ep->TestBits(TObject::kBitMask)));
293 c = static_cast<AliVCluster*>(fClus->At(iClus));
297 if (c->GetLabel() > 0) {
298 if (fMCConstSel == kNone) {
299 AliDebug(2,Form("Skipping cluster %d because bit mask is 0.", iClus));
302 if (fMCConstSel != kAllJets) {
303 if (c->TestBits(fMCConstSel) != (Int_t)fMCConstSel) {
304 AliDebug(2,Form("Skipping cluster %d because it does not match the bit mask (%d, %d)", iClus, fMCConstSel, c->TestBits(TObject::kBitMask)));
308 AliDebug(2,Form("Cluster %d matches the bit mask (%d, %d)", iClus, fMCConstSel, c->TestBits(TObject::kBitMask)));
313 if (fConstSel == kNone) {
314 AliDebug(2,Form("Skipping cluster %d because bit mask is 0.", iClus));
317 if (fConstSel != kAllJets) {
318 if (c->TestBits(fConstSel) != (Int_t)fConstSel) {
319 AliDebug(2,Form("Skipping cluster %d because it does not match the bit mask (%d, %d)", iClus, fConstSel, c->TestBits(TObject::kBitMask)));
323 AliDebug(2,Form("Cluster %d matches the bit mask (%d, %d)", iClus, fConstSel, c->TestBits(TObject::kBitMask)));
329 c->GetMomentum(nP, vertex);
339 if (cPt < fMinJetClusPt)
341 if ((cEta<fEtaMin) || (cEta>fEtaMax) ||
342 (cPhi<fPhiMin) || (cPhi>fPhiMax))
344 // offset of 100 to skip ghost particles uid = -1
345 AliDebug(2,Form("Cluster %d accepted (label = %d)", iClus, c->GetLabel()));
346 fjw.AddInputVector(cPx, cPy, cPz, TMath::Sqrt(cPx*cPx+cPy*cPy+cPz*cPz), -iClus - 100);
354 AliEMCALGeometry *geom = AliEMCALGeometry::GetInstance();
356 AliFatal(Form("%s: Can not create geometry", GetName()));
360 // loop over fastjet jets
361 std::vector<fastjet::PseudoJet> jets_incl = fjw.GetInclusiveJets();
362 // sort jets according to jet pt
363 static Int_t indexes[9999] = {-1};
364 GetSortedArray(indexes, jets_incl);
366 AliDebug(1,Form("%d jets found", (Int_t)jets_incl.size()));
367 for (UInt_t ijet=0, jetCount=0; ijet<jets_incl.size(); ++ijet) {
368 Int_t ij = indexes[ijet];
369 AliDebug(3,Form("Jet pt = %f, area = %f", jets_incl[ij].perp(), fjw.GetJetArea(ij)));
371 if (jets_incl[ij].perp()<fMinJetPt)
373 if (fjw.GetJetArea(ij)<fMinJetArea)
375 if ((jets_incl[ij].eta()<fJetEtaMin) || (jets_incl[ij].eta()>fJetEtaMax) ||
376 (jets_incl[ij].phi()<fJetPhiMin) || (jets_incl[ij].phi()>fJetPhiMax))
379 AliEmcalJet *jet = new ((*fJets)[jetCount])
380 AliEmcalJet(jets_incl[ij].perp(), jets_incl[ij].eta(), jets_incl[ij].phi(), jets_incl[ij].m());
382 // loop over constituents
383 std::vector<fastjet::PseudoJet> constituents(fjw.GetJetConstituents(ij));
384 jet->SetNumberOfTracks(constituents.size());
385 jet->SetNumberOfClusters(constituents.size());
389 Double_t neutralE = 0;
400 for(UInt_t ic = 0; ic < constituents.size(); ++ic) {
401 Int_t uid = constituents[ic].user_index();
402 AliDebug(3,Form("Processing constituent %d", uid));
403 if ((uid == -1) /*&& (constituents[ic].kt2() < 1e-25)*/) { //ghost particle
405 Double_t gphi = constituents[ic].phi();
407 gphi += TMath::TwoPi();
408 gphi *= TMath::RadToDeg();
409 Double_t geta = constituents[ic].eta();
410 if ((gphi > geom->GetArm1PhiMin()) && (gphi < geom->GetArm1PhiMax()) &&
411 (geta > geom->GetArm1EtaMin()) && (geta < geom->GetArm1EtaMax()))
413 } else if ((uid > 0) && fTracks) { // track constituent
414 Int_t tid = uid - 100;
415 AliVParticle *t = static_cast<AliVParticle*>(fTracks->At(tid));
417 AliError(Form("Could not find track %d",tid));
420 if (jetCount < fMarkConst) {
421 AliDebug(2,Form("Marking track %d with bit map %d", tid, fJetType));
424 Double_t cEta = t->Eta();
425 Double_t cPhi = t->Phi();
426 Double_t cPt = t->Pt();
427 Double_t cP = t->P();
428 if (t->Charge() == 0) {
438 if (fIsMcPart || t->GetLabel() != 0) // check if MC particle
442 cPhi += TMath::TwoPi();
443 cPhi *= TMath::RadToDeg();
444 if ((cPhi > geom->GetArm1PhiMin()) && (cPhi < geom->GetArm1PhiMax()) &&
445 (cEta > geom->GetArm1EtaMin()) && (cEta < geom->GetArm1EtaMax())) {
450 jet->AddTrackAt(tid, nt);
452 } else if (fClus) { // cluster constituent
453 Int_t cid = -uid - 100;
455 Double_t cEta=0,cPhi=0,cPt=0,cP=0;
457 AliEmcalParticle *ep = static_cast<AliEmcalParticle*>(fClus->At(cid));
460 c = ep->GetCluster();
463 if (jetCount < fMarkConst)
464 ep->SetBit(fJetType);
470 c = static_cast<AliVCluster*>(fClus->At(cid));
473 if (jetCount < fMarkConst)
476 c->GetMomentum(nP, vertex);
487 if (c->GetLabel() > 0) // MC particle
491 cPhi += TMath::TwoPi();
492 cPhi *= TMath::RadToDeg();
493 if ((cPhi > geom->GetArm1PhiMin()) && (cPhi < geom->GetArm1PhiMax()) &&
494 (cEta > geom->GetArm1EtaMin()) && (cEta < geom->GetArm1EtaMax())) {
499 jet->AddClusterAt(cid, nc);
503 AliError(Form("%s: No logical way to end up here.", GetName()));
506 } /* end of constituent loop */
508 jet->SetNumberOfTracks(nt);
509 jet->SetNumberOfClusters(nc);
510 jet->SortConstituents();
511 jet->SetMaxNeutralPt(maxNe);
512 jet->SetMaxChargedPt(maxCh);
513 jet->SetNEF(neutralE / jet->E());
514 fastjet::PseudoJet area(fjw.GetJetAreaVector(ij));
515 jet->SetArea(area.perp());
516 jet->SetAreaEta(area.eta());
517 jet->SetAreaPhi(area.phi());
518 jet->SetNumberOfCharged(ncharged);
519 jet->SetNumberOfNeutrals(nneutral);
522 jet->SetPtEmc(emcpt);
525 jet->SetAreaEmc(fjw.GetJetArea(ij) * gemc / gall);
528 if ((jet->Phi() > geom->GetArm1PhiMin() * TMath::DegToRad()) &&
529 (jet->Phi() < geom->GetArm1PhiMax() * TMath::DegToRad()) &&
530 (jet->Eta() > geom->GetArm1EtaMin()) &&
531 (jet->Eta() < geom->GetArm1EtaMax()))
532 jet->SetAxisInEmcal(kTRUE);
534 AliDebug(2,Form("Added jet n. %d, pt = %f, area = %f, constituents = %d", jetCount, jet->Pt(), jet->Area(), (Int_t)constituents.size()));
540 //________________________________________________________________________
541 Bool_t AliEmcalJetTask::GetSortedArray(Int_t indexes[], std::vector<fastjet::PseudoJet> array) const
543 // Get the leading jets.
545 static Float_t pt[9999] = {0};
547 const Int_t n = (Int_t)array.size();
552 for (Int_t i = 0; i < n; i++)
553 pt[i] = array[i].perp();
555 TMath::Sort(n, pt, indexes);
560 //________________________________________________________________________
561 Bool_t AliEmcalJetTask::DoInit()
563 // Init. Return true if successful.
565 // get input collections
566 AliAnalysisManager *am = AliAnalysisManager::GetAnalysisManager();
569 fEvent = InputEvent();
571 AliError(Form("%s: Could not retrieve event! Returning", GetName()));
575 // add jets to event if not yet there
577 if (!(fEvent->FindListObject(fJetsName)))
578 fEvent->AddObject(fJets);
580 AliError(Form("%s: Object with name %s already in event! Returning", GetName(), fJetsName.Data()));
584 if (fTracksName == "Tracks")
585 am->LoadBranch("Tracks");
586 if (!fTracks && !fTracksName.IsNull()) {
587 fTracks = dynamic_cast<TClonesArray*>(fEvent->FindListObject(fTracksName));
589 AliError(Form("%s: Pointer to tracks %s == 0", GetName(), fTracksName.Data()));
594 TClass cls(fTracks->GetClass()->GetName());
595 if (cls.InheritsFrom("AliMCParticle") || cls.InheritsFrom("AliAODMCParticle"))
599 if (fCaloName == "CaloClusters")
600 am->LoadBranch("CaloClusters");
601 if (!fClus && !fCaloName.IsNull()) {
602 fClus = dynamic_cast<TClonesArray*>(fEvent->FindListObject(fCaloName));
604 AliError(Form("%s: Pointer to clus %s == 0", GetName(), fCaloName.Data()));
609 TClass cls(fClus->GetClass()->GetName());
610 if (cls.InheritsFrom("AliEmcalParticle"))