1 /**************************************************************************
2 * Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
4 * Author: The ALICE Off-line Project. *
5 * Contributors are mentioned in the code where appropriate. *
7 * Permission to use, copy, modify and distribute this software and its *
8 * documentation strictly for non-commercial purposes is hereby granted *
9 * without fee, provided that the above copyright notice appears in all *
10 * copies and that both the copyright notice and this permission notice *
11 * appear in the supporting documentation. The authors make no claims *
12 * about the suitability of this software for any purpose. It is *
13 * provided "as is" without express or implied warranty. *
14 **************************************************************************/
18 Revision 1.3 2002/01/18 05:07:56 morsch
21 - track selection upon EMCAL information
25 //*-- Author: Andreas Morsch (CERN)
28 #include <TClonesArray.h>
30 #include <TBranchElement.h>
34 #include <TParticle.h>
35 #include <TParticlePDG.h>
38 #include "AliEMCALJetFinder.h"
39 #include "AliEMCALFast.h"
40 #include "AliEMCALGeometry.h"
41 #include "AliEMCALHit.h"
42 #include "AliEMCALDigit.h"
43 #include "AliEMCALDigitizer.h"
44 #include "AliEMCALHadronCorrection.h"
48 #include "AliMagFCM.h"
50 #include "AliHeader.h"
52 ClassImp(AliEMCALJetFinder)
54 //____________________________________________________________________________
55 AliEMCALJetFinder::AliEMCALJetFinder()
57 // Default constructor
68 AliEMCALJetFinder::AliEMCALJetFinder(const char* name, const char *title)
72 fJets = new TClonesArray("AliEMCALJet",10000);
74 for (Int_t i = 0; i < 30000; i++)
88 SetMomentumSmearing();
91 SetHadronCorrection();
92 SetSamplingFraction();
98 //____________________________________________________________________________
99 AliEMCALJetFinder::~AliEMCALJetFinder()
113 # define jet_finder_ua1 jet_finder_ua1_
115 # define type_of_call
118 # define jet_finder_ua1 J
120 # define type_of_call _stdcall
123 extern "C" void type_of_call
124 jet_finder_ua1(Int_t& ncell, Int_t& ncell_tot,
125 Float_t etc[30000], Float_t etac[30000],
127 Float_t& min_move, Float_t& max_move, Int_t& mode,
128 Float_t& prec_bg, Int_t& ierror);
130 extern "C" void type_of_call hf1(Int_t& id, Float_t& x, Float_t& wgt);
136 void AliEMCALJetFinder::Find(Int_t ncell, Int_t ncell_tot, Float_t etc[30000],
137 Float_t etac[30000], Float_t phic[30000],
138 Float_t min_move, Float_t max_move, Int_t mode,
139 Float_t prec_bg, Int_t ierror)
141 // Wrapper for fortran coded jet finder
142 // Full argument list
143 jet_finder_ua1(ncell, ncell_tot, etc, etac, phic,
144 min_move, max_move, mode, prec_bg, ierror);
145 // Write result to output
149 void AliEMCALJetFinder::Find()
151 // Wrapper for fortran coded jet finder using member data for
154 Float_t min_move = 0;
155 Float_t max_move = 0;
157 Float_t prec_bg = 0.;
160 jet_finder_ua1(fNcell, fNtot, fEtCell, fEtaCell, fPhiCell,
161 min_move, max_move, mode, prec_bg, ierror);
162 // Write result to output
163 Int_t njet = Njets();
165 for (Int_t nj=0; nj<njet; nj++)
169 fJetT[nj] = new AliEMCALJet(JetEnergy(nj),
173 FindTracksInJetCone();
178 Int_t AliEMCALJetFinder::Njets()
180 // Get number of reconstructed jets
181 return EMCALJETS.njet;
184 Float_t AliEMCALJetFinder::JetEnergy(Int_t i)
186 // Get reconstructed jet energy
187 return EMCALJETS.etj[i];
190 Float_t AliEMCALJetFinder::JetPhiL(Int_t i)
192 // Get reconstructed jet phi from leading particle
193 return EMCALJETS.phij[0][i];
196 Float_t AliEMCALJetFinder::JetPhiW(Int_t i)
198 // Get reconstructed jet phi from weighting
199 return EMCALJETS.phij[1][i];
202 Float_t AliEMCALJetFinder::JetEtaL(Int_t i)
204 // Get reconstructed jet eta from leading particles
205 return EMCALJETS.etaj[0][i];
209 Float_t AliEMCALJetFinder::JetEtaW(Int_t i)
211 // Get reconstructed jet eta from weighting
212 return EMCALJETS.etaj[1][i];
215 void AliEMCALJetFinder::SetCellSize(Float_t eta, Float_t phi)
217 // Set grid cell size
218 EMCALCELLGEO.etaCellSize = eta;
219 EMCALCELLGEO.phiCellSize = phi;
224 void AliEMCALJetFinder::SetConeRadius(Float_t par)
226 // Set jet cone radius
227 EMCALJETPARAM.coneRad = par;
231 void AliEMCALJetFinder::SetEtSeed(Float_t par)
233 // Set et cut for seeds
234 EMCALJETPARAM.etSeed = par;
238 void AliEMCALJetFinder::SetMinJetEt(Float_t par)
240 // Set minimum jet et
241 EMCALJETPARAM.ejMin = par;
245 void AliEMCALJetFinder::SetMinCellEt(Float_t par)
247 // Set et cut per cell
248 EMCALJETPARAM.etMin = par;
252 void AliEMCALJetFinder::SetPtCut(Float_t par)
254 // Set pT cut on charged tracks
259 void AliEMCALJetFinder::Test()
262 // Test the finder call
264 const Int_t nmax = 30000;
266 Int_t ncell_tot = 100;
271 Float_t min_move = 0;
272 Float_t max_move = 0;
278 Find(ncell, ncell_tot, etc, etac, phic,
279 min_move, max_move, mode, prec_bg, ierror);
287 void AliEMCALJetFinder::AddJet(const AliEMCALJet& jet)
292 TClonesArray &lrawcl = *fJets;
293 new(lrawcl[fNjets++]) AliEMCALJet(jet);
296 void AliEMCALJetFinder::ResetJets()
305 void AliEMCALJetFinder::WriteJets()
308 // Add all jets to the list
310 const Int_t kBufferSize = 4000;
311 TTree *pK = gAlice->TreeK();
312 const char* file = (pK->GetCurrentFile())->GetName();
314 AliEMCAL* pEMCAL = (AliEMCAL* )gAlice->GetModule("EMCAL");
317 printf("Make Branch - TreeR address %p %p\n",gAlice->TreeR(), pEMCAL);
319 if (fJets && gAlice->TreeR()) {
320 pEMCAL->MakeBranchInTree(gAlice->TreeR(),
326 Int_t njet = Njets();
327 for (Int_t nj = 0; nj < njet; nj++)
333 Int_t nev = gAlice->GetHeader()->GetEvent();
334 gAlice->TreeR()->Fill();
336 sprintf(hname,"TreeR%d", nev);
337 gAlice->TreeR()->Write(hname);
338 gAlice->TreeR()->Reset();
342 void AliEMCALJetFinder::BookLego()
345 // Book histo for discretisation
348 // Get geometry parameters from
349 AliEMCAL* pEMCAL = (AliEMCAL*) gAlice->GetModule("EMCAL");
350 AliEMCALGeometry* geom =
351 AliEMCALGeometry::GetInstance(pEMCAL->GetTitle(), "");
352 fNbinEta = geom->GetNZ();
353 fNbinPhi = geom->GetNPhi();
354 const Float_t phiMin = geom->GetArm1PhiMin()*TMath::Pi()/180.;
355 const Float_t phiMax = geom->GetArm1PhiMax()*TMath::Pi()/180.;
356 fDphi = (phiMax-phiMin)/fNbinEta;
357 fDeta = 1.4/fNbinEta;
358 fNtot = fNbinPhi*fNbinEta;
361 fLego = new TH2F("legoH","eta-phi",
363 fNbinPhi, phiMin, phiMax);
366 void AliEMCALJetFinder::DumpLego()
369 // Dump lego histo into array
372 for (Int_t i = 1; i < fNbinEta; i++) {
373 for (Int_t j = 1; j < fNbinPhi; j++) {
374 Float_t e = fLego->GetBinContent(i,j);
375 TAxis* Xaxis = fLego->GetXaxis();
376 TAxis* Yaxis = fLego->GetYaxis();
377 Float_t eta = Xaxis->GetBinCenter(i);
378 Float_t phi = Yaxis->GetBinCenter(j);
380 fEtaCell[fNcell] = eta;
381 fPhiCell[fNcell] = phi;
388 void AliEMCALJetFinder::ResetMap()
391 // Reset eta-phi array
393 for (Int_t i=0; i<30000; i++)
402 void AliEMCALJetFinder::FillFromTracks(Int_t flag, Int_t ich)
405 // Fill Cells with track information
410 if (!fLego) BookLego();
412 if (flag == 0) fLego->Reset();
414 // Access particle information
415 Int_t npart = (gAlice->GetHeader())->GetNprimary();
419 // 1: selected for jet finding
422 if (fTrackList) delete[] fTrackList;
423 if (fPtT) delete[] fPtT;
424 if (fEtaT) delete[] fEtaT;
425 if (fPhiT) delete[] fPhiT;
427 fTrackList = new Int_t [npart];
428 fPtT = new Float_t[npart];
429 fEtaT = new Float_t[npart];
430 fPhiT = new Float_t[npart];
432 for (Int_t part = 2; part < npart; part++) {
433 TParticle *MPart = gAlice->Particle(part);
434 Int_t mpart = MPart->GetPdgCode();
435 Int_t child1 = MPart->GetFirstDaughter();
436 Float_t pT = MPart->Pt();
437 Float_t p = MPart->P();
438 Float_t phi = MPart->Phi();
439 Float_t eta = MPart->Eta();
442 if (part == 6 || part == 7)
444 printf("\n Simulated Jet (pt, eta, phi): %d %f %f %f",
445 part-5, pT, eta, phi);
450 // printf("\n Simulated Jet (pt, eta, phi): %d %d %f %f %f",
451 // part, mpart, pT, eta, phi);
455 fTrackList[part] = 0;
460 if (part < 2) continue;
461 if (pT == 0 || pT < fPtCut) continue;
462 TParticlePDG* pdgP = 0;
463 // charged or neutral
465 pdgP = MPart->GetPDG();
466 if (pdgP->Charge() == 0) continue;
469 if (TMath::Abs(mpart) <= 6 ||
471 mpart == 92) continue;
473 if (TMath::Abs(eta) > 0.7) continue;
474 if (phi*180./TMath::Pi() > 120.) continue;
476 if (child1 >= 0 && child1 < npart) continue;
479 printf("\n sel:%5d %5d %5d %8.2f %8.2f %8.2f",
480 part, mpart, child1, eta, phi, pT);
485 Bool_t curls = kFALSE;
486 Float_t dphi = PropagatePhi(pT, pdgP->Charge(), curls);
490 // Momentum smearing goes here ...
493 p = AliEMCALFast::SmearMomentum(1,p);
496 // Tracking Efficiency and TPC acceptance goes here ...
498 Float_t eff = AliEMCALFast::Efficiency(1,p);
499 if (AliEMCALFast::RandomReject(eff)) continue;
502 // Correction of Hadronic Energy goes here ...
505 if (!fHadronCorrector)
506 Fatal("AliEMCALJetFinder",
507 "Hadronic energy correction required but not defined !");
508 Float_t dpH = fHadronCorrector->GetEnergy(p, eta, 7);
512 // More to do ? Just think about it !
514 fTrackList[part] = 1;
516 fLego->Fill(eta, phi, p);
521 void AliEMCALJetFinder::FillFromHits(Int_t flag)
524 // Fill Cells with hit information
529 if (!fLego) BookLego();
530 if (flag == 0) fLego->Reset();
533 // Access hit information
534 AliEMCAL* pEMCAL = (AliEMCAL*) gAlice->GetModule("EMCAL");
536 TTree *treeH = gAlice->TreeH();
537 Int_t ntracks = (Int_t) treeH->GetEntries();
544 for (Int_t track=0; track<ntracks;track++) {
546 nbytes += treeH->GetEvent(track);
550 for(AliEMCALHit* mHit=(AliEMCALHit*) pEMCAL->FirstHit(-1);
552 mHit=(AliEMCALHit*) pEMCAL->NextHit())
554 Float_t x = mHit->X(); // x-pos of hit
555 Float_t y = mHit->Y(); // y-pos
556 Float_t z = mHit->Z(); // z-pos
557 Float_t eloss = mHit->GetEnergy(); // deposited energy
559 Float_t r = TMath::Sqrt(x*x+y*y);
560 Float_t theta = TMath::ATan2(r,z);
561 Float_t eta = -TMath::Log(TMath::Tan(theta/2.));
562 Float_t phi = TMath::ATan2(y,x);
563 fLego->Fill(eta, phi, fSamplingF*eloss);
569 void AliEMCALJetFinder::FillFromDigits(Int_t flag)
572 // Fill Cells with digit information
577 if (!fLego) BookLego();
578 if (flag == 0) fLego->Reset();
585 TClonesArray* digs = new TClonesArray("AliEMCALDigit", 10000);
586 TTree *treeD = gAlice->TreeD();
587 TBranchElement* branchDg = (TBranchElement*)
588 treeD->GetBranch("EMCAL");
590 if (!branchDg) Fatal("AliEMCALJetFinder",
591 "Reading digits requested but no digits in file !");
593 branchDg->SetAddress(&digs);
594 Int_t nent = (Int_t) branchDg->GetEntries();
598 AliEMCALDigitizer* digr = new AliEMCALDigitizer();
599 TBranchElement* branchDr = (TBranchElement*)
600 treeD->GetBranch("AliEMCALDigitizer");
601 branchDr->SetAddress(&digr);
604 nbytes += branchDg->GetEntry(0);
605 nbytes += branchDr->GetEntry(0);
607 // Get digitizer parameters
608 Float_t towerADCped = digr->GetTowerpedestal();
609 Float_t towerADCcha = digr->GetTowerchannel();
610 Float_t preshoADCped = digr->GetPreShopedestal();
611 Float_t preshoADCcha = digr->GetPreShochannel();
613 AliEMCAL* pEMCAL = (AliEMCAL*) gAlice->GetModule("EMCAL");
614 AliEMCALGeometry* geom =
615 AliEMCALGeometry::GetInstance(pEMCAL->GetTitle(), "");
618 Int_t ndig = digs->GetEntries();
619 printf("\n Number of Digits: %d %d\n", ndig, nent);
620 printf("\n Parameters: %f %f %f %f\n",
621 towerADCped, towerADCcha, preshoADCped, preshoADCcha );
622 printf("\n Geometry: %d %d\n", geom->GetNEta(), geom->GetNPhi());
629 while ((sdg = (AliEMCALDigit*)(next())))
633 if (sdg->GetId() > (geom->GetNZ() * geom->GetNPhi()))
635 pedestal = preshoADCped;
636 channel = preshoADCcha;
638 pedestal = towerADCped;
639 channel = towerADCcha;
642 Float_t eta = sdg->GetEta();
643 Float_t phi = sdg->GetPhi() * TMath::Pi()/180.;
644 Float_t amp = (Float_t) (channel*(sdg->GetAmp())-pedestal);
646 if (fDebug > 1) printf("\n Digit: eta %8.3f phi %8.3f amp %8.3f %8d",
647 eta, phi, amp, sdg->GetAmp());
649 fLego->Fill(eta, phi, fSamplingF*amp);
657 void AliEMCALJetFinder::FillFromHitFlaggedTracks(Int_t flag)
660 // Fill Cells with hit information
665 if (!fLego) BookLego();
667 if (flag == 0) fLego->Reset();
669 //Flag charged tracks passing through TPC which
670 //are associated to EMCAL Hits
671 BuildTrackFlagTable();
674 // Access particle information
675 TTree *treeH = gAlice->TreeH();
676 Int_t ntracks = (Int_t) treeH->GetEntries();
678 if (fPtT) delete[] fPtT;
679 if (fEtaT) delete[] fEtaT;
680 if (fPhiT) delete[] fPhiT;
682 fPtT = new Float_t[ntracks];
683 fEtaT = new Float_t[ntracks];
684 fPhiT = new Float_t[ntracks];
687 for (Int_t track = 0; track < ntracks; track++) {
688 TParticle *MPart = gAlice->Particle(track);
689 Float_t pT = MPart->Pt();
690 Float_t phi = MPart->Phi();
691 Float_t eta = MPart->Eta();
693 if(fTrackList[track]) {
698 if (track < 2) continue; //Colliding particles?
699 if (pT == 0 || pT < fPtCut) continue;
700 fLego->Fill(eta, phi, pT);
706 void AliEMCALJetFinder::BuildTrackFlagTable() {
708 // Method to generate a lookup table for TreeK particles
709 // which are linked to hits in the EMCAL
711 // --Author: J.L. Klay
713 printf("\n Building track flag table.\n");
716 // Access hit information
717 AliEMCAL* pEMCAL = (AliEMCAL*) gAlice->GetModule("EMCAL");
719 TTree *TK = gAlice->TreeK(); // Get the number of entries in the kine tree
720 Int_t nKTrks = (Int_t) TK->GetEntries(); // (Number of particles created somewhere)
722 if(fTrackList) delete[] fTrackList; //Make sure we get rid of the old one
723 fTrackList = new Int_t[nKTrks]; //before generating a new one
725 for (Int_t i = 0; i < nKTrks; i++) { //Initialize members to 0
729 TTree *treeH = gAlice->TreeH();
730 Int_t ntracks = (Int_t) treeH->GetEntries();
736 for (Int_t track=0; track<ntracks;track++) {
738 nbytes += treeH->GetEvent(track);
744 for(AliEMCALHit* mHit=(AliEMCALHit*) pEMCAL->FirstHit(-1);
746 mHit=(AliEMCALHit*) pEMCAL->NextHit())
748 Int_t iTrk = mHit->Track(); // track number
749 Int_t idprim = mHit->GetPrimary(); // primary particle
751 //Determine the origin point of this particle - it made a hit in the EMCAL
752 TParticle *trkPart = gAlice->Particle(iTrk);
753 TParticlePDG *trkPdg = trkPart->GetPDG();
754 Int_t trkCode = trkPart->GetPdgCode();
756 if (trkCode < 10000) { //Big Ions cause problems for
757 trkChg = trkPdg->Charge(); //this function. Since they aren't
758 } else { //likely to make it very far, set
759 trkChg = 0.0; //their charge to 0 for the Flag test
761 Float_t vxTrk = trkPart->Vx();
762 Float_t vyTrk = trkPart->Vy();
763 Float_t vrTrk = TMath::Sqrt(vxTrk*vxTrk+vyTrk*vyTrk);
764 fTrackList[iTrk] = SetTrackFlag(vrTrk,trkCode,trkChg);
766 //Loop through the ancestry of the EMCAL entrance particles
767 Int_t ancestor = trkPart->GetFirstMother(); //Get track's Mother
768 while (ancestor != -1) {
769 TParticle *ancPart = gAlice->Particle(ancestor); //get particle info on ancestor
770 TParticlePDG *ancPdg = ancPart->GetPDG();
771 Int_t ancCode = ancPart->GetPdgCode();
773 if (ancCode < 10000) {
774 ancChg = ancPdg->Charge();
778 Float_t vxAnc = ancPart->Vx();
779 Float_t vyAnc = ancPart->Vy();
780 Float_t vrAnc = TMath::Sqrt(vxAnc*vxAnc+vyAnc*vyAnc);
781 fTrackList[ancestor] = SetTrackFlag(vrAnc,ancCode,ancChg);
782 ancestor = ancPart->GetFirstMother(); //Get the next ancestor
785 //Determine the origin point of the primary particle associated with the hit
786 TParticle *primPart = gAlice->Particle(idprim);
787 TParticlePDG *primPdg = primPart->GetPDG();
788 Int_t primCode = primPart->GetPdgCode();
790 if (primCode < 10000) {
791 primChg = primPdg->Charge();
795 Float_t vxPrim = primPart->Vx();
796 Float_t vyPrim = primPart->Vy();
797 Float_t vrPrim = TMath::Sqrt(vxPrim*vxPrim+vyPrim*vyPrim);
798 fTrackList[idprim] = SetTrackFlag(vrPrim,primCode,primChg);
804 Int_t AliEMCALJetFinder
805 ::SetTrackFlag(Float_t radius, Int_t code, Double_t charge) {
811 if (charge == 0) neutral = 1;
813 if (TMath::Abs(code) <= 6 ||
815 code == 92) parton = 1;
817 //It's not a parton, it's charged and it went through the TPC
818 if (!parton && !neutral && radius <= 84.0) flag = 1;
823 void AliEMCALJetFinder::FindTracksInJetCone()
826 // Build list of tracks inside jet cone
829 Int_t njet = Njets();
830 for (Int_t nj = 0; nj < njet; nj++)
832 Float_t etaj = JetEtaW(nj);
833 Float_t phij = JetPhiW(nj);
834 Int_t nT = 0; // number of associated tracks
836 // Loop over particles
837 for (Int_t part = 0; part < fNt; part++) {
838 if (!fTrackList[part]) continue;
839 Float_t phi = fPhiT[part];
840 Float_t eta = fEtaT[part];
841 Float_t dr = TMath::Sqrt((etaj-eta)*(etaj-eta) +
842 (phij-phi)*(phij-phi));
843 if (dr < fConeRadius) {
844 fTrackList[part] = nj+2;
849 if (nT > 50) nT = 50;
851 Float_t* ptT = new Float_t[nT];
852 Float_t* etaT = new Float_t[nT];
853 Float_t* phiT = new Float_t[nT];
857 for (Int_t part = 0; part < fNt; part++) {
858 if (fTrackList[part] == nj+2) {
860 for (j=iT-1; j>=0; j--) {
861 if (fPtT[part] > ptT[j]) {
866 for (j=iT-1; j>=index; j--) {
871 ptT [index] = fPtT [part];
872 etaT[index] = fEtaT[part];
873 phiT[index] = fPhiT[part];
875 } // particle associated
878 fJetT[nj]->SetTrackList(nT, ptT, etaT, phiT);
885 Float_t AliEMCALJetFinder::PropagatePhi(Float_t pt, Float_t charge, Bool_t& curls)
887 // Propagates phi angle to EMCAL radius
891 Float_t b = ((AliMagFCM*) gAlice->Field())->SolenoidField();
893 Float_t rEMCAL = AliEMCALGeometry::GetInstance()->GetIPDistance();
897 Float_t rB = 3.3356 * pt / b;
900 // check if particle is curling below EMCAL
901 if (2.*rB < rEMCAL) {
906 // if not calculate delta phi
907 Float_t phi = TMath::ACos(1.-rEMCAL*rEMCAL/(2.*rB*rB));
908 dPhi = TMath::ATan2(1.-TMath::Cos(phi), TMath::Sin(phi));
909 dPhi = TMath::Sign(dPhi, charge);
916 void hf1(Int_t& id, Float_t& x, Float_t& wgt)
918 // dummy for hbook calls