2 /**************************************************************************
3 * Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
5 * Author: The ALICE Off-line Project. *
6 * Contributors are mentioned in the code where appropriate. *
8 * Permission to use, copy, modify and distribute this software and its *
9 * documentation strictly for non-commercial purposes is hereby granted *
10 * without fee, provided that the above copyright notice appears in all *
11 * copies and that both the copyright notice and this permission notice *
12 * appear in the supporting documentation. The authors make no claims *
13 * about the suitability of this software for any purpose. It is *
14 * provided "as is" without express or implied warranty. *
15 **************************************************************************/
19 Revision 1.4 2002/01/21 11:03:21 morsch
20 Phi propagation introduced in FillFromTracks.
22 Revision 1.3 2002/01/18 05:07:56 morsch
25 - track selection upon EMCAL information
29 //*-- Author: Andreas Morsch (CERN)
32 #include <TClonesArray.h>
34 #include <TBranchElement.h>
38 #include <TParticle.h>
39 #include <TParticlePDG.h>
42 #include "AliEMCALJetFinder.h"
43 #include "AliEMCALFast.h"
44 #include "AliEMCALGeometry.h"
45 #include "AliEMCALHit.h"
46 #include "AliEMCALDigit.h"
47 #include "AliEMCALDigitizer.h"
48 #include "AliEMCALHadronCorrection.h"
52 #include "AliMagFCM.h"
54 #include "AliHeader.h"
57 ClassImp(AliEMCALJetFinder)
59 //____________________________________________________________________________
60 AliEMCALJetFinder::AliEMCALJetFinder()
62 // Default constructor
73 AliEMCALJetFinder::AliEMCALJetFinder(const char* name, const char *title)
77 fJets = new TClonesArray("AliEMCALJet",10000);
79 for (Int_t i = 0; i < 30000; i++)
93 SetMomentumSmearing();
96 SetHadronCorrection();
97 SetSamplingFraction();
104 //____________________________________________________________________________
105 AliEMCALJetFinder::~AliEMCALJetFinder()
119 # define jet_finder_ua1 jet_finder_ua1_
121 # define type_of_call
124 # define jet_finder_ua1 J
126 # define type_of_call _stdcall
129 extern "C" void type_of_call
130 jet_finder_ua1(Int_t& ncell, Int_t& ncell_tot,
131 Float_t etc[30000], Float_t etac[30000],
133 Float_t& min_move, Float_t& max_move, Int_t& mode,
134 Float_t& prec_bg, Int_t& ierror);
136 extern "C" void type_of_call hf1(Int_t& id, Float_t& x, Float_t& wgt);
142 void AliEMCALJetFinder::Find(Int_t ncell, Int_t ncell_tot, Float_t etc[30000],
143 Float_t etac[30000], Float_t phic[30000],
144 Float_t min_move, Float_t max_move, Int_t mode,
145 Float_t prec_bg, Int_t ierror)
147 // Wrapper for fortran coded jet finder
148 // Full argument list
149 jet_finder_ua1(ncell, ncell_tot, etc, etac, phic,
150 min_move, max_move, mode, prec_bg, ierror);
151 // Write result to output
155 void AliEMCALJetFinder::Find()
157 // Wrapper for fortran coded jet finder using member data for
160 Float_t min_move = 0;
161 Float_t max_move = 0;
163 Float_t prec_bg = 0.;
166 jet_finder_ua1(fNcell, fNtot, fEtCell, fEtaCell, fPhiCell,
167 min_move, max_move, mode, prec_bg, ierror);
168 // Write result to output
169 Int_t njet = Njets();
171 for (Int_t nj=0; nj<njet; nj++)
175 fJetT[nj] = new AliEMCALJet(JetEnergy(nj),
179 FindTracksInJetCone();
184 Int_t AliEMCALJetFinder::Njets()
186 // Get number of reconstructed jets
187 return EMCALJETS.njet;
190 Float_t AliEMCALJetFinder::JetEnergy(Int_t i)
192 // Get reconstructed jet energy
193 return EMCALJETS.etj[i];
196 Float_t AliEMCALJetFinder::JetPhiL(Int_t i)
198 // Get reconstructed jet phi from leading particle
199 return EMCALJETS.phij[0][i];
202 Float_t AliEMCALJetFinder::JetPhiW(Int_t i)
204 // Get reconstructed jet phi from weighting
205 return EMCALJETS.phij[1][i];
208 Float_t AliEMCALJetFinder::JetEtaL(Int_t i)
210 // Get reconstructed jet eta from leading particles
211 return EMCALJETS.etaj[0][i];
215 Float_t AliEMCALJetFinder::JetEtaW(Int_t i)
217 // Get reconstructed jet eta from weighting
218 return EMCALJETS.etaj[1][i];
221 void AliEMCALJetFinder::SetCellSize(Float_t eta, Float_t phi)
223 // Set grid cell size
224 EMCALCELLGEO.etaCellSize = eta;
225 EMCALCELLGEO.phiCellSize = phi;
230 void AliEMCALJetFinder::SetConeRadius(Float_t par)
232 // Set jet cone radius
233 EMCALJETPARAM.coneRad = par;
237 void AliEMCALJetFinder::SetEtSeed(Float_t par)
239 // Set et cut for seeds
240 EMCALJETPARAM.etSeed = par;
244 void AliEMCALJetFinder::SetMinJetEt(Float_t par)
246 // Set minimum jet et
247 EMCALJETPARAM.ejMin = par;
251 void AliEMCALJetFinder::SetMinCellEt(Float_t par)
253 // Set et cut per cell
254 EMCALJETPARAM.etMin = par;
258 void AliEMCALJetFinder::SetPtCut(Float_t par)
260 // Set pT cut on charged tracks
265 void AliEMCALJetFinder::Test()
268 // Test the finder call
270 const Int_t nmax = 30000;
272 Int_t ncell_tot = 100;
277 Float_t min_move = 0;
278 Float_t max_move = 0;
284 Find(ncell, ncell_tot, etc, etac, phic,
285 min_move, max_move, mode, prec_bg, ierror);
293 void AliEMCALJetFinder::AddJet(const AliEMCALJet& jet)
298 TClonesArray &lrawcl = *fJets;
299 new(lrawcl[fNjets++]) AliEMCALJet(jet);
302 void AliEMCALJetFinder::ResetJets()
311 void AliEMCALJetFinder::WriteJets()
314 // Add all jets to the list
316 const Int_t kBufferSize = 4000;
317 TTree *pK = gAlice->TreeK();
318 const char* file = (pK->GetCurrentFile())->GetName();
320 AliEMCAL* pEMCAL = (AliEMCAL* )gAlice->GetModule("EMCAL");
323 printf("Make Branch - TreeR address %p %p\n",gAlice->TreeR(), pEMCAL);
325 if (fJets && gAlice->TreeR()) {
326 pEMCAL->MakeBranchInTree(gAlice->TreeR(),
332 Int_t njet = Njets();
333 for (Int_t nj = 0; nj < njet; nj++)
339 Int_t nev = gAlice->GetHeader()->GetEvent();
340 gAlice->TreeR()->Fill();
342 sprintf(hname,"TreeR%d", nev);
343 gAlice->TreeR()->Write(hname);
344 gAlice->TreeR()->Reset();
348 void AliEMCALJetFinder::BookLego()
351 // Book histo for discretisation
354 // Get geometry parameters from
355 AliEMCAL* pEMCAL = (AliEMCAL*) gAlice->GetModule("EMCAL");
356 AliEMCALGeometry* geom =
357 AliEMCALGeometry::GetInstance(pEMCAL->GetTitle(), "");
358 fNbinEta = geom->GetNZ();
359 fNbinPhi = geom->GetNPhi();
360 const Float_t phiMin = geom->GetArm1PhiMin()*TMath::Pi()/180.;
361 const Float_t phiMax = geom->GetArm1PhiMax()*TMath::Pi()/180.;
362 fDphi = (phiMax-phiMin)/fNbinEta;
363 fDeta = 1.4/fNbinEta;
364 fNtot = fNbinPhi*fNbinEta;
367 fLego = new TH2F("legoH","eta-phi",
369 fNbinPhi, phiMin, phiMax);
372 void AliEMCALJetFinder::DumpLego()
375 // Dump lego histo into array
378 for (Int_t i = 1; i < fNbinEta; i++) {
379 for (Int_t j = 1; j < fNbinPhi; j++) {
380 Float_t e = fLego->GetBinContent(i,j);
381 TAxis* Xaxis = fLego->GetXaxis();
382 TAxis* Yaxis = fLego->GetYaxis();
383 Float_t eta = Xaxis->GetBinCenter(i);
384 Float_t phi = Yaxis->GetBinCenter(j);
386 fEtaCell[fNcell] = eta;
387 fPhiCell[fNcell] = phi;
394 void AliEMCALJetFinder::ResetMap()
397 // Reset eta-phi array
399 for (Int_t i=0; i<30000; i++)
408 void AliEMCALJetFinder::FillFromTracks(Int_t flag, Int_t ich)
411 // Fill Cells with track information
416 if (!fLego) BookLego();
418 if (flag == 0) fLego->Reset();
420 // Access particle information
421 Int_t npart = (gAlice->GetHeader())->GetNprimary();
425 // 1: selected for jet finding
428 if (fTrackList) delete[] fTrackList;
429 if (fPtT) delete[] fPtT;
430 if (fEtaT) delete[] fEtaT;
431 if (fPhiT) delete[] fPhiT;
433 fTrackList = new Int_t [npart];
434 fPtT = new Float_t[npart];
435 fEtaT = new Float_t[npart];
436 fPhiT = new Float_t[npart];
438 for (Int_t part = 2; part < npart; part++) {
439 TParticle *MPart = gAlice->Particle(part);
440 Int_t mpart = MPart->GetPdgCode();
441 Int_t child1 = MPart->GetFirstDaughter();
442 Float_t pT = MPart->Pt();
443 Float_t p = MPart->P();
444 Float_t phi = MPart->Phi();
445 Float_t eta = MPart->Eta();
448 if (part == 6 || part == 7)
450 printf("\n Simulated Jet (pt, eta, phi): %d %f %f %f",
451 part-5, pT, eta, phi);
456 // printf("\n Simulated Jet (pt, eta, phi): %d %d %f %f %f",
457 // part, mpart, pT, eta, phi);
461 fTrackList[part] = 0;
466 if (part < 2) continue;
467 if (pT == 0 || pT < fPtCut) continue;
468 TParticlePDG* pdgP = 0;
469 // charged or neutral
471 pdgP = MPart->GetPDG();
472 if (pdgP->Charge() == 0) {
476 if (mpart != kNeutron &&
477 mpart != kNeutronBar &&
478 mpart != kK0Long) continue;
483 if (TMath::Abs(mpart) <= 6 ||
485 mpart == 92) continue;
487 if (TMath::Abs(eta) > 0.7) continue;
488 if (phi*180./TMath::Pi() > 120.) continue;
490 if (child1 >= 0 && child1 < npart) continue;
493 printf("\n sel:%5d %5d %5d %8.2f %8.2f %8.2f",
494 part, mpart, child1, eta, phi, pT);
499 Bool_t curls = kFALSE;
500 Float_t dphi = PropagatePhi(pT, pdgP->Charge(), curls);
504 // Momentum smearing goes here ...
507 p = AliEMCALFast::SmearMomentum(1,p);
510 // Tracking Efficiency and TPC acceptance goes here ...
512 Float_t eff = AliEMCALFast::Efficiency(1,p);
513 if (AliEMCALFast::RandomReject(eff)) continue;
516 // Correction of Hadronic Energy goes here ...
519 if (!fHadronCorrector)
520 Fatal("AliEMCALJetFinder",
521 "Hadronic energy correction required but not defined !");
522 Float_t dpH = fHadronCorrector->GetEnergy(p, eta, 7);
526 // More to do ? Just think about it !
528 fTrackList[part] = 1;
530 fLego->Fill(eta, phi, p);
535 void AliEMCALJetFinder::FillFromHits(Int_t flag)
538 // Fill Cells with hit information
543 if (!fLego) BookLego();
544 if (flag == 0) fLego->Reset();
547 // Access hit information
548 AliEMCAL* pEMCAL = (AliEMCAL*) gAlice->GetModule("EMCAL");
550 TTree *treeH = gAlice->TreeH();
551 Int_t ntracks = (Int_t) treeH->GetEntries();
558 for (Int_t track=0; track<ntracks;track++) {
560 nbytes += treeH->GetEvent(track);
564 for(AliEMCALHit* mHit=(AliEMCALHit*) pEMCAL->FirstHit(-1);
566 mHit=(AliEMCALHit*) pEMCAL->NextHit())
568 Float_t x = mHit->X(); // x-pos of hit
569 Float_t y = mHit->Y(); // y-pos
570 Float_t z = mHit->Z(); // z-pos
571 Float_t eloss = mHit->GetEnergy(); // deposited energy
573 Float_t r = TMath::Sqrt(x*x+y*y);
574 Float_t theta = TMath::ATan2(r,z);
575 Float_t eta = -TMath::Log(TMath::Tan(theta/2.));
576 Float_t phi = TMath::ATan2(y,x);
577 fLego->Fill(eta, phi, fSamplingF*eloss);
583 void AliEMCALJetFinder::FillFromDigits(Int_t flag)
586 // Fill Cells with digit information
591 if (!fLego) BookLego();
592 if (flag == 0) fLego->Reset();
599 TClonesArray* digs = new TClonesArray("AliEMCALDigit", 10000);
600 TTree *treeD = gAlice->TreeD();
601 TBranchElement* branchDg = (TBranchElement*)
602 treeD->GetBranch("EMCAL");
604 if (!branchDg) Fatal("AliEMCALJetFinder",
605 "Reading digits requested but no digits in file !");
607 branchDg->SetAddress(&digs);
608 Int_t nent = (Int_t) branchDg->GetEntries();
612 AliEMCALDigitizer* digr = new AliEMCALDigitizer();
613 TBranchElement* branchDr = (TBranchElement*)
614 treeD->GetBranch("AliEMCALDigitizer");
615 branchDr->SetAddress(&digr);
618 nbytes += branchDg->GetEntry(0);
619 nbytes += branchDr->GetEntry(0);
621 // Get digitizer parameters
622 Float_t towerADCped = digr->GetTowerpedestal();
623 Float_t towerADCcha = digr->GetTowerchannel();
624 Float_t preshoADCped = digr->GetPreShopedestal();
625 Float_t preshoADCcha = digr->GetPreShochannel();
627 AliEMCAL* pEMCAL = (AliEMCAL*) gAlice->GetModule("EMCAL");
628 AliEMCALGeometry* geom =
629 AliEMCALGeometry::GetInstance(pEMCAL->GetTitle(), "");
632 Int_t ndig = digs->GetEntries();
633 printf("\n Number of Digits: %d %d\n", ndig, nent);
634 printf("\n Parameters: %f %f %f %f\n",
635 towerADCped, towerADCcha, preshoADCped, preshoADCcha );
636 printf("\n Geometry: %d %d\n", geom->GetNEta(), geom->GetNPhi());
643 while ((sdg = (AliEMCALDigit*)(next())))
647 if (sdg->GetId() > (geom->GetNZ() * geom->GetNPhi()))
649 pedestal = preshoADCped;
650 channel = preshoADCcha;
652 pedestal = towerADCped;
653 channel = towerADCcha;
656 Float_t eta = sdg->GetEta();
657 Float_t phi = sdg->GetPhi() * TMath::Pi()/180.;
658 Float_t amp = (Float_t) (channel*(sdg->GetAmp())-pedestal);
660 if (fDebug > 1) printf("\n Digit: eta %8.3f phi %8.3f amp %8.3f %8d",
661 eta, phi, amp, sdg->GetAmp());
663 fLego->Fill(eta, phi, fSamplingF*amp);
671 void AliEMCALJetFinder::FillFromHitFlaggedTracks(Int_t flag)
674 // Fill Cells with hit information
679 if (!fLego) BookLego();
681 if (flag == 0) fLego->Reset();
683 //Flag charged tracks passing through TPC which
684 //are associated to EMCAL Hits
685 BuildTrackFlagTable();
688 // Access particle information
689 TTree *treeH = gAlice->TreeH();
690 Int_t ntracks = (Int_t) treeH->GetEntries();
692 if (fPtT) delete[] fPtT;
693 if (fEtaT) delete[] fEtaT;
694 if (fPhiT) delete[] fPhiT;
696 fPtT = new Float_t[ntracks];
697 fEtaT = new Float_t[ntracks];
698 fPhiT = new Float_t[ntracks];
701 for (Int_t track = 0; track < ntracks; track++) {
702 TParticle *MPart = gAlice->Particle(track);
703 Float_t pT = MPart->Pt();
704 Float_t phi = MPart->Phi();
705 Float_t eta = MPart->Eta();
707 if(fTrackList[track]) {
712 if (track < 2) continue; //Colliding particles?
713 if (pT == 0 || pT < fPtCut) continue;
714 fLego->Fill(eta, phi, pT);
720 void AliEMCALJetFinder::BuildTrackFlagTable() {
722 // Method to generate a lookup table for TreeK particles
723 // which are linked to hits in the EMCAL
725 // --Author: J.L. Klay
727 printf("\n Building track flag table.\n");
730 // Access hit information
731 AliEMCAL* pEMCAL = (AliEMCAL*) gAlice->GetModule("EMCAL");
733 TTree *TK = gAlice->TreeK(); // Get the number of entries in the kine tree
734 Int_t nKTrks = (Int_t) TK->GetEntries(); // (Number of particles created somewhere)
736 if(fTrackList) delete[] fTrackList; //Make sure we get rid of the old one
737 fTrackList = new Int_t[nKTrks]; //before generating a new one
739 for (Int_t i = 0; i < nKTrks; i++) { //Initialize members to 0
743 TTree *treeH = gAlice->TreeH();
744 Int_t ntracks = (Int_t) treeH->GetEntries();
750 for (Int_t track=0; track<ntracks;track++) {
752 nbytes += treeH->GetEvent(track);
758 for(AliEMCALHit* mHit=(AliEMCALHit*) pEMCAL->FirstHit(-1);
760 mHit=(AliEMCALHit*) pEMCAL->NextHit())
762 Int_t iTrk = mHit->Track(); // track number
763 Int_t idprim = mHit->GetPrimary(); // primary particle
765 //Determine the origin point of this particle - it made a hit in the EMCAL
766 TParticle *trkPart = gAlice->Particle(iTrk);
767 TParticlePDG *trkPdg = trkPart->GetPDG();
768 Int_t trkCode = trkPart->GetPdgCode();
770 if (trkCode < 10000) { //Big Ions cause problems for
771 trkChg = trkPdg->Charge(); //this function. Since they aren't
772 } else { //likely to make it very far, set
773 trkChg = 0.0; //their charge to 0 for the Flag test
775 Float_t vxTrk = trkPart->Vx();
776 Float_t vyTrk = trkPart->Vy();
777 Float_t vrTrk = TMath::Sqrt(vxTrk*vxTrk+vyTrk*vyTrk);
778 fTrackList[iTrk] = SetTrackFlag(vrTrk,trkCode,trkChg);
780 //Loop through the ancestry of the EMCAL entrance particles
781 Int_t ancestor = trkPart->GetFirstMother(); //Get track's Mother
782 while (ancestor != -1) {
783 TParticle *ancPart = gAlice->Particle(ancestor); //get particle info on ancestor
784 TParticlePDG *ancPdg = ancPart->GetPDG();
785 Int_t ancCode = ancPart->GetPdgCode();
787 if (ancCode < 10000) {
788 ancChg = ancPdg->Charge();
792 Float_t vxAnc = ancPart->Vx();
793 Float_t vyAnc = ancPart->Vy();
794 Float_t vrAnc = TMath::Sqrt(vxAnc*vxAnc+vyAnc*vyAnc);
795 fTrackList[ancestor] = SetTrackFlag(vrAnc,ancCode,ancChg);
796 ancestor = ancPart->GetFirstMother(); //Get the next ancestor
799 //Determine the origin point of the primary particle associated with the hit
800 TParticle *primPart = gAlice->Particle(idprim);
801 TParticlePDG *primPdg = primPart->GetPDG();
802 Int_t primCode = primPart->GetPdgCode();
804 if (primCode < 10000) {
805 primChg = primPdg->Charge();
809 Float_t vxPrim = primPart->Vx();
810 Float_t vyPrim = primPart->Vy();
811 Float_t vrPrim = TMath::Sqrt(vxPrim*vxPrim+vyPrim*vyPrim);
812 fTrackList[idprim] = SetTrackFlag(vrPrim,primCode,primChg);
818 Int_t AliEMCALJetFinder
819 ::SetTrackFlag(Float_t radius, Int_t code, Double_t charge) {
825 if (charge == 0) neutral = 1;
827 if (TMath::Abs(code) <= 6 ||
829 code == 92) parton = 1;
831 //It's not a parton, it's charged and it went through the TPC
832 if (!parton && !neutral && radius <= 84.0) flag = 1;
837 void AliEMCALJetFinder::FindTracksInJetCone()
840 // Build list of tracks inside jet cone
843 Int_t njet = Njets();
844 for (Int_t nj = 0; nj < njet; nj++)
846 Float_t etaj = JetEtaW(nj);
847 Float_t phij = JetPhiW(nj);
848 Int_t nT = 0; // number of associated tracks
850 // Loop over particles
851 for (Int_t part = 0; part < fNt; part++) {
852 if (!fTrackList[part]) continue;
853 Float_t phi = fPhiT[part];
854 Float_t eta = fEtaT[part];
855 Float_t dr = TMath::Sqrt((etaj-eta)*(etaj-eta) +
856 (phij-phi)*(phij-phi));
857 if (dr < fConeRadius) {
858 fTrackList[part] = nj+2;
863 if (nT > 50) nT = 50;
865 Float_t* ptT = new Float_t[nT];
866 Float_t* etaT = new Float_t[nT];
867 Float_t* phiT = new Float_t[nT];
871 for (Int_t part = 0; part < fNt; part++) {
872 if (fTrackList[part] == nj+2) {
874 for (j=iT-1; j>=0; j--) {
875 if (fPtT[part] > ptT[j]) {
880 for (j=iT-1; j>=index; j--) {
885 ptT [index] = fPtT [part];
886 etaT[index] = fEtaT[part];
887 phiT[index] = fPhiT[part];
889 } // particle associated
892 fJetT[nj]->SetTrackList(nT, ptT, etaT, phiT);
899 Float_t AliEMCALJetFinder::PropagatePhi(Float_t pt, Float_t charge, Bool_t& curls)
901 // Propagates phi angle to EMCAL radius
905 Float_t b = ((AliMagFCM*) gAlice->Field())->SolenoidField();
907 Float_t rEMCAL = AliEMCALGeometry::GetInstance()->GetIPDistance();
911 Float_t rB = 3.3356 * pt / b;
914 // check if particle is curling below EMCAL
915 if (2.*rB < rEMCAL) {
920 // if not calculate delta phi
921 Float_t phi = TMath::ACos(1.-rEMCAL*rEMCAL/(2.*rB*rB));
922 dPhi = TMath::ATan2(1.-TMath::Cos(phi), TMath::Sin(phi));
923 dPhi = TMath::Sign(dPhi, charge);
930 void hf1(Int_t& id, Float_t& x, Float_t& wgt)
932 // dummy for hbook calls