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.5 2002/01/21 12:47:47 morsch
20 Possibility to include K0long and neutrons.
22 Revision 1.4 2002/01/21 11:03:21 morsch
23 Phi propagation introduced in FillFromTracks.
25 Revision 1.3 2002/01/18 05:07:56 morsch
28 - track selection upon EMCAL information
32 //*-- Authors: Andreas Morsch (CERN)
34 //* Aleksei Pavlinov (WSU)
37 #include <TClonesArray.h>
39 #include <TBranchElement.h>
43 #include <TParticle.h>
44 #include <TParticlePDG.h>
47 #include "AliEMCALJetFinder.h"
48 #include "AliEMCALFast.h"
49 #include "AliEMCALGeometry.h"
50 #include "AliEMCALHit.h"
51 #include "AliEMCALDigit.h"
52 #include "AliEMCALDigitizer.h"
53 #include "AliEMCALHadronCorrection.h"
57 #include "AliMagFCM.h"
59 #include "AliHeader.h"
62 ClassImp(AliEMCALJetFinder)
64 //____________________________________________________________________________
65 AliEMCALJetFinder::AliEMCALJetFinder()
67 // Default constructor
78 AliEMCALJetFinder::AliEMCALJetFinder(const char* name, const char *title)
82 fJets = new TClonesArray("AliEMCALJet",10000);
84 for (Int_t i = 0; i < 30000; i++)
99 SetMomentumSmearing();
102 SetHadronCorrection();
103 SetSamplingFraction();
110 //____________________________________________________________________________
111 AliEMCALJetFinder::~AliEMCALJetFinder()
125 # define jet_finder_ua1 jet_finder_ua1_
127 # define type_of_call
130 # define jet_finder_ua1 J
132 # define type_of_call _stdcall
135 extern "C" void type_of_call
136 jet_finder_ua1(Int_t& ncell, Int_t& ncell_tot,
137 Float_t etc[30000], Float_t etac[30000],
139 Float_t& min_move, Float_t& max_move, Int_t& mode,
140 Float_t& prec_bg, Int_t& ierror);
142 extern "C" void type_of_call hf1(Int_t& id, Float_t& x, Float_t& wgt);
148 void AliEMCALJetFinder::Find(Int_t ncell, Int_t ncell_tot, Float_t etc[30000],
149 Float_t etac[30000], Float_t phic[30000],
150 Float_t min_move, Float_t max_move, Int_t mode,
151 Float_t prec_bg, Int_t ierror)
153 // Wrapper for fortran coded jet finder
154 // Full argument list
155 jet_finder_ua1(ncell, ncell_tot, etc, etac, phic,
156 min_move, max_move, mode, prec_bg, ierror);
157 // Write result to output
161 void AliEMCALJetFinder::Find()
163 // Wrapper for fortran coded jet finder using member data for
166 Float_t min_move = 0;
167 Float_t max_move = 0;
169 Float_t prec_bg = 0.;
172 jet_finder_ua1(fNcell, fNtot, fEtCell, fEtaCell, fPhiCell,
173 min_move, max_move, mode, prec_bg, ierror);
174 // Write result to output
175 Int_t njet = Njets();
177 for (Int_t nj=0; nj<njet; nj++)
181 fJetT[nj] = new AliEMCALJet(JetEnergy(nj),
185 FindTracksInJetCone();
190 Int_t AliEMCALJetFinder::Njets()
192 // Get number of reconstructed jets
193 return EMCALJETS.njet;
196 Float_t AliEMCALJetFinder::JetEnergy(Int_t i)
198 // Get reconstructed jet energy
199 return EMCALJETS.etj[i];
202 Float_t AliEMCALJetFinder::JetPhiL(Int_t i)
204 // Get reconstructed jet phi from leading particle
205 return EMCALJETS.phij[0][i];
208 Float_t AliEMCALJetFinder::JetPhiW(Int_t i)
210 // Get reconstructed jet phi from weighting
211 return EMCALJETS.phij[1][i];
214 Float_t AliEMCALJetFinder::JetEtaL(Int_t i)
216 // Get reconstructed jet eta from leading particles
217 return EMCALJETS.etaj[0][i];
221 Float_t AliEMCALJetFinder::JetEtaW(Int_t i)
223 // Get reconstructed jet eta from weighting
224 return EMCALJETS.etaj[1][i];
227 void AliEMCALJetFinder::SetCellSize(Float_t eta, Float_t phi)
229 // Set grid cell size
230 EMCALCELLGEO.etaCellSize = eta;
231 EMCALCELLGEO.phiCellSize = phi;
236 void AliEMCALJetFinder::SetConeRadius(Float_t par)
238 // Set jet cone radius
239 EMCALJETPARAM.coneRad = par;
243 void AliEMCALJetFinder::SetEtSeed(Float_t par)
245 // Set et cut for seeds
246 EMCALJETPARAM.etSeed = par;
250 void AliEMCALJetFinder::SetMinJetEt(Float_t par)
252 // Set minimum jet et
253 EMCALJETPARAM.ejMin = par;
257 void AliEMCALJetFinder::SetMinCellEt(Float_t par)
259 // Set et cut per cell
260 EMCALJETPARAM.etMin = par;
264 void AliEMCALJetFinder::SetPtCut(Float_t par)
266 // Set pT cut on charged tracks
271 void AliEMCALJetFinder::Test()
274 // Test the finder call
276 const Int_t nmax = 30000;
278 Int_t ncell_tot = 100;
283 Float_t min_move = 0;
284 Float_t max_move = 0;
290 Find(ncell, ncell_tot, etc, etac, phic,
291 min_move, max_move, mode, prec_bg, ierror);
299 void AliEMCALJetFinder::AddJet(const AliEMCALJet& jet)
304 TClonesArray &lrawcl = *fJets;
305 new(lrawcl[fNjets++]) AliEMCALJet(jet);
308 void AliEMCALJetFinder::ResetJets()
317 void AliEMCALJetFinder::WriteJets()
320 // Add all jets to the list
322 const Int_t kBufferSize = 4000;
323 TTree *pK = gAlice->TreeK();
324 const char* file = (pK->GetCurrentFile())->GetName();
326 AliEMCAL* pEMCAL = (AliEMCAL* )gAlice->GetModule("EMCAL");
329 printf("Make Branch - TreeR address %p %p\n",gAlice->TreeR(), pEMCAL);
331 if (fJets && gAlice->TreeR()) {
332 pEMCAL->MakeBranchInTree(gAlice->TreeR(),
338 Int_t njet = Njets();
339 for (Int_t nj = 0; nj < njet; nj++)
345 Int_t nev = gAlice->GetHeader()->GetEvent();
346 gAlice->TreeR()->Fill();
348 sprintf(hname,"TreeR%d", nev);
349 gAlice->TreeR()->Write(hname);
350 gAlice->TreeR()->Reset();
354 void AliEMCALJetFinder::BookLego()
357 // Book histo for discretisation
360 // Get geometry parameters from
361 AliEMCAL* pEMCAL = (AliEMCAL*) gAlice->GetModule("EMCAL");
362 AliEMCALGeometry* geom =
363 AliEMCALGeometry::GetInstance(pEMCAL->GetTitle(), "");
364 fNbinEta = geom->GetNZ();
365 fNbinPhi = geom->GetNPhi();
366 const Float_t phiMin = geom->GetArm1PhiMin()*TMath::Pi()/180.;
367 const Float_t phiMax = geom->GetArm1PhiMax()*TMath::Pi()/180.;
368 fDphi = (phiMax-phiMin)/fNbinEta;
369 fDeta = 1.4/fNbinEta;
370 fNtot = fNbinPhi*fNbinEta;
373 fLego = new TH2F("legoH","eta-phi",
375 fNbinPhi, phiMin, phiMax);
378 void AliEMCALJetFinder::DumpLego()
381 // Dump lego histo into array
384 for (Int_t i = 1; i < fNbinEta; i++) {
385 for (Int_t j = 1; j < fNbinPhi; j++) {
386 Float_t e = fLego->GetBinContent(i,j);
387 TAxis* Xaxis = fLego->GetXaxis();
388 TAxis* Yaxis = fLego->GetYaxis();
389 Float_t eta = Xaxis->GetBinCenter(i);
390 Float_t phi = Yaxis->GetBinCenter(j);
392 fEtaCell[fNcell] = eta;
393 fPhiCell[fNcell] = phi;
400 void AliEMCALJetFinder::ResetMap()
403 // Reset eta-phi array
405 for (Int_t i=0; i<30000; i++)
414 void AliEMCALJetFinder::FillFromTracks(Int_t flag, Int_t ich)
417 // Fill Cells with track information
422 if (!fLego) BookLego();
424 if (flag == 0) fLego->Reset();
426 // Access particle information
427 Int_t npart = (gAlice->GetHeader())->GetNprimary();
431 // 1: selected for jet finding
434 if (fTrackList) delete[] fTrackList;
435 if (fPtT) delete[] fPtT;
436 if (fEtaT) delete[] fEtaT;
437 if (fPhiT) delete[] fPhiT;
439 fTrackList = new Int_t [npart];
440 fPtT = new Float_t[npart];
441 fEtaT = new Float_t[npart];
442 fPhiT = new Float_t[npart];
444 for (Int_t part = 2; part < npart; part++) {
445 TParticle *MPart = gAlice->Particle(part);
446 Int_t mpart = MPart->GetPdgCode();
447 Int_t child1 = MPart->GetFirstDaughter();
448 Float_t pT = MPart->Pt();
449 Float_t p = MPart->P();
450 Float_t phi = MPart->Phi();
451 Float_t eta = MPart->Eta();
454 if (part == 6 || part == 7)
456 printf("\n Simulated Jet (pt, eta, phi): %d %f %f %f",
457 part-5, pT, eta, phi);
462 // printf("\n Simulated Jet (pt, eta, phi): %d %d %f %f %f",
463 // part, mpart, pT, eta, phi);
467 fTrackList[part] = 0;
472 if (part < 2) continue;
473 if (pT == 0 || pT < fPtCut) continue;
474 TParticlePDG* pdgP = 0;
475 // charged or neutral
477 pdgP = MPart->GetPDG();
478 if (pdgP->Charge() == 0) {
482 if (mpart != kNeutron &&
483 mpart != kNeutronBar &&
484 mpart != kK0Long) continue;
489 if (TMath::Abs(mpart) <= 6 ||
491 mpart == 92) continue;
493 if (TMath::Abs(eta) > 0.7) continue;
494 if (phi*180./TMath::Pi() > 120.) continue;
496 if (child1 >= 0 && child1 < npart) continue;
499 printf("\n sel:%5d %5d %5d %8.2f %8.2f %8.2f",
500 part, mpart, child1, eta, phi, pT);
505 Bool_t curls = kFALSE;
506 Float_t dphi = PropagatePhi(pT, pdgP->Charge(), curls);
510 // Momentum smearing goes here ...
513 p = AliEMCALFast::SmearMomentum(1,p);
516 // Tracking Efficiency and TPC acceptance goes here ...
518 Float_t eff = AliEMCALFast::Efficiency(1,p);
519 if (AliEMCALFast::RandomReject(eff)) continue;
522 // Correction of Hadronic Energy goes here ...
525 if (!fHadronCorrector)
526 Fatal("AliEMCALJetFinder",
527 "Hadronic energy correction required but not defined !");
528 Float_t dpH = fHadronCorrector->GetEnergy(p, eta, 7);
532 // More to do ? Just think about it !
534 fTrackList[part] = 1;
536 fLego->Fill(eta, phi, p);
541 void AliEMCALJetFinder::FillFromHits(Int_t flag)
544 // Fill Cells with hit information
549 if (!fLego) BookLego();
550 if (flag == 0) fLego->Reset();
553 // Access hit information
554 AliEMCAL* pEMCAL = (AliEMCAL*) gAlice->GetModule("EMCAL");
556 TTree *treeH = gAlice->TreeH();
557 Int_t ntracks = (Int_t) treeH->GetEntries();
564 for (Int_t track=0; track<ntracks;track++) {
566 nbytes += treeH->GetEvent(track);
570 for(AliEMCALHit* mHit=(AliEMCALHit*) pEMCAL->FirstHit(-1);
572 mHit=(AliEMCALHit*) pEMCAL->NextHit())
574 Float_t x = mHit->X(); // x-pos of hit
575 Float_t y = mHit->Y(); // y-pos
576 Float_t z = mHit->Z(); // z-pos
577 Float_t eloss = mHit->GetEnergy(); // deposited energy
579 Float_t r = TMath::Sqrt(x*x+y*y);
580 Float_t theta = TMath::ATan2(r,z);
581 Float_t eta = -TMath::Log(TMath::Tan(theta/2.));
582 Float_t phi = TMath::ATan2(y,x);
583 fLego->Fill(eta, phi, fSamplingF*eloss);
589 void AliEMCALJetFinder::FillFromDigits(Int_t flag)
592 // Fill Cells with digit information
597 if (!fLego) BookLego();
598 if (flag == 0) fLego->Reset();
605 TClonesArray* digs = new TClonesArray("AliEMCALDigit", 10000);
606 TTree *treeD = gAlice->TreeD();
607 TBranchElement* branchDg = (TBranchElement*)
608 treeD->GetBranch("EMCAL");
610 if (!branchDg) Fatal("AliEMCALJetFinder",
611 "Reading digits requested but no digits in file !");
613 branchDg->SetAddress(&digs);
614 Int_t nent = (Int_t) branchDg->GetEntries();
618 AliEMCALDigitizer* digr = new AliEMCALDigitizer();
619 TBranchElement* branchDr = (TBranchElement*)
620 treeD->GetBranch("AliEMCALDigitizer");
621 branchDr->SetAddress(&digr);
624 nbytes += branchDg->GetEntry(0);
625 nbytes += branchDr->GetEntry(0);
627 // Get digitizer parameters
628 Float_t towerADCped = digr->GetTowerpedestal();
629 Float_t towerADCcha = digr->GetTowerchannel();
630 Float_t preshoADCped = digr->GetPreShopedestal();
631 Float_t preshoADCcha = digr->GetPreShochannel();
633 AliEMCAL* pEMCAL = (AliEMCAL*) gAlice->GetModule("EMCAL");
634 AliEMCALGeometry* geom =
635 AliEMCALGeometry::GetInstance(pEMCAL->GetTitle(), "");
638 Int_t ndig = digs->GetEntries();
639 printf("\n Number of Digits: %d %d\n", ndig, nent);
640 printf("\n Parameters: %f %f %f %f\n",
641 towerADCped, towerADCcha, preshoADCped, preshoADCcha );
642 printf("\n Geometry: %d %d\n", geom->GetNEta(), geom->GetNPhi());
649 while ((sdg = (AliEMCALDigit*)(next())))
653 if (sdg->GetId() > (geom->GetNZ() * geom->GetNPhi()))
655 pedestal = preshoADCped;
656 channel = preshoADCcha;
658 pedestal = towerADCped;
659 channel = towerADCcha;
662 Float_t eta = sdg->GetEta();
663 Float_t phi = sdg->GetPhi() * TMath::Pi()/180.;
664 Float_t amp = (Float_t) (channel*(sdg->GetAmp())-pedestal);
666 if (fDebug > 1) printf("\n Digit: eta %8.3f phi %8.3f amp %8.3f %8d",
667 eta, phi, amp, sdg->GetAmp());
669 fLego->Fill(eta, phi, fSamplingF*amp);
677 void AliEMCALJetFinder::FillFromHitFlaggedTracks(Int_t flag)
680 // Fill Cells with hit information
685 if (!fLego) BookLego();
687 if (flag == 0) fLego->Reset();
689 //Flag charged tracks passing through TPC which
690 //are associated to EMCAL Hits
691 BuildTrackFlagTable();
694 // Access particle information
695 TTree *treeH = gAlice->TreeH();
696 Int_t ntracks = (Int_t) treeH->GetEntries();
698 if (fPtT) delete[] fPtT;
699 if (fEtaT) delete[] fEtaT;
700 if (fPhiT) delete[] fPhiT;
702 fPtT = new Float_t[ntracks];
703 fEtaT = new Float_t[ntracks];
704 fPhiT = new Float_t[ntracks];
707 for (Int_t track = 0; track < ntracks; track++) {
708 TParticle *MPart = gAlice->Particle(track);
709 Float_t pT = MPart->Pt();
710 Float_t phi = MPart->Phi();
711 Float_t eta = MPart->Eta();
713 if(fTrackList[track]) {
718 if (track < 2) continue; //Colliding particles?
719 if (pT == 0 || pT < fPtCut) continue;
720 fLego->Fill(eta, phi, pT);
726 void AliEMCALJetFinder::BuildTrackFlagTable() {
728 // Method to generate a lookup table for TreeK particles
729 // which are linked to hits in the EMCAL
731 // --Author: J.L. Klay
733 printf("\n Building track flag table.\n");
736 // Access hit information
737 AliEMCAL* pEMCAL = (AliEMCAL*) gAlice->GetModule("EMCAL");
739 TTree *TK = gAlice->TreeK(); // Get the number of entries in the kine tree
740 Int_t nKTrks = (Int_t) TK->GetEntries(); // (Number of particles created somewhere)
742 if(fTrackList) delete[] fTrackList; //Make sure we get rid of the old one
743 fTrackList = new Int_t[nKTrks]; //before generating a new one
745 for (Int_t i = 0; i < nKTrks; i++) { //Initialize members to 0
749 TTree *treeH = gAlice->TreeH();
750 Int_t ntracks = (Int_t) treeH->GetEntries();
756 for (Int_t track=0; track<ntracks;track++) {
758 nbytes += treeH->GetEvent(track);
764 for(AliEMCALHit* mHit=(AliEMCALHit*) pEMCAL->FirstHit(-1);
766 mHit=(AliEMCALHit*) pEMCAL->NextHit())
768 Int_t iTrk = mHit->Track(); // track number
769 Int_t idprim = mHit->GetPrimary(); // primary particle
771 //Determine the origin point of this particle - it made a hit in the EMCAL
772 TParticle *trkPart = gAlice->Particle(iTrk);
773 TParticlePDG *trkPdg = trkPart->GetPDG();
774 Int_t trkCode = trkPart->GetPdgCode();
776 if (trkCode < 10000) { //Big Ions cause problems for
777 trkChg = trkPdg->Charge(); //this function. Since they aren't
778 } else { //likely to make it very far, set
779 trkChg = 0.0; //their charge to 0 for the Flag test
781 Float_t vxTrk = trkPart->Vx();
782 Float_t vyTrk = trkPart->Vy();
783 Float_t vrTrk = TMath::Sqrt(vxTrk*vxTrk+vyTrk*vyTrk);
784 fTrackList[iTrk] = SetTrackFlag(vrTrk,trkCode,trkChg);
786 //Loop through the ancestry of the EMCAL entrance particles
787 Int_t ancestor = trkPart->GetFirstMother(); //Get track's Mother
788 while (ancestor != -1) {
789 TParticle *ancPart = gAlice->Particle(ancestor); //get particle info on ancestor
790 TParticlePDG *ancPdg = ancPart->GetPDG();
791 Int_t ancCode = ancPart->GetPdgCode();
793 if (ancCode < 10000) {
794 ancChg = ancPdg->Charge();
798 Float_t vxAnc = ancPart->Vx();
799 Float_t vyAnc = ancPart->Vy();
800 Float_t vrAnc = TMath::Sqrt(vxAnc*vxAnc+vyAnc*vyAnc);
801 fTrackList[ancestor] = SetTrackFlag(vrAnc,ancCode,ancChg);
802 ancestor = ancPart->GetFirstMother(); //Get the next ancestor
805 //Determine the origin point of the primary particle associated with the hit
806 TParticle *primPart = gAlice->Particle(idprim);
807 TParticlePDG *primPdg = primPart->GetPDG();
808 Int_t primCode = primPart->GetPdgCode();
810 if (primCode < 10000) {
811 primChg = primPdg->Charge();
815 Float_t vxPrim = primPart->Vx();
816 Float_t vyPrim = primPart->Vy();
817 Float_t vrPrim = TMath::Sqrt(vxPrim*vxPrim+vyPrim*vyPrim);
818 fTrackList[idprim] = SetTrackFlag(vrPrim,primCode,primChg);
824 Int_t AliEMCALJetFinder
825 ::SetTrackFlag(Float_t radius, Int_t code, Double_t charge) {
831 if (charge == 0) neutral = 1;
833 if (TMath::Abs(code) <= 6 ||
835 code == 92) parton = 1;
837 //It's not a parton, it's charged and it went through the TPC
838 if (!parton && !neutral && radius <= 84.0) flag = 1;
843 void AliEMCALJetFinder::FindTracksInJetCone()
846 // Build list of tracks inside jet cone
849 Int_t njet = Njets();
850 for (Int_t nj = 0; nj < njet; nj++)
852 Float_t etaj = JetEtaW(nj);
853 Float_t phij = JetPhiW(nj);
854 Int_t nT = 0; // number of associated tracks
856 // Loop over particles
857 for (Int_t part = 0; part < fNt; part++) {
858 if (!fTrackList[part]) continue;
859 Float_t phi = fPhiT[part];
860 Float_t eta = fEtaT[part];
861 Float_t dr = TMath::Sqrt((etaj-eta)*(etaj-eta) +
862 (phij-phi)*(phij-phi));
863 if (dr < fConeRadius) {
864 fTrackList[part] = nj+2;
869 if (nT > 50) nT = 50;
871 Float_t* ptT = new Float_t[nT];
872 Float_t* etaT = new Float_t[nT];
873 Float_t* phiT = new Float_t[nT];
877 for (Int_t part = 0; part < fNt; part++) {
878 if (fTrackList[part] == nj+2) {
880 for (j=iT-1; j>=0; j--) {
881 if (fPtT[part] > ptT[j]) {
886 for (j=iT-1; j>=index; j--) {
891 ptT [index] = fPtT [part];
892 etaT[index] = fEtaT[part];
893 phiT[index] = fPhiT[part];
895 } // particle associated
898 fJetT[nj]->SetTrackList(nT, ptT, etaT, phiT);
905 Float_t AliEMCALJetFinder::PropagatePhi(Float_t pt, Float_t charge, Bool_t& curls)
907 // Propagates phi angle to EMCAL radius
911 Float_t b = ((AliMagFCM*) gAlice->Field())->SolenoidField();
913 Float_t rEMCAL = AliEMCALGeometry::GetInstance()->GetIPDistance();
917 Float_t rB = 3.3356 * pt / b;
920 // check if particle is curling below EMCAL
921 if (2.*rB < rEMCAL) {
926 // if not calculate delta phi
927 Float_t phi = TMath::ACos(1.-rEMCAL*rEMCAL/(2.*rB*rB));
928 dPhi = TMath::ATan2(1.-TMath::Cos(phi), TMath::Sin(phi));
929 dPhi = TMath::Sign(dPhi, charge);
936 void hf1(Int_t& id, Float_t& x, Float_t& wgt)
938 // dummy for hbook calls