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.21 2002/04/27 07:43:08 morsch
19 Calculation of fDphi corrected (Renan Cabrera)
21 Revision 1.20 2002/03/12 01:06:23 pavlinov
22 Testin output from generator
24 Revision 1.19 2002/02/27 00:46:33 pavlinov
25 Added method FillFromParticles()
27 Revision 1.18 2002/02/21 08:48:59 morsch
28 Correction in FillFromHitFlaggedTrack. (Jennifer Klay)
30 Revision 1.17 2002/02/14 08:52:53 morsch
31 Major updates by Aleksei Pavlinov:
32 FillFromPartons, FillFromTracks, jetfinder configuration.
34 Revision 1.16 2002/02/08 11:43:05 morsch
35 SetOutputFileName(..) allows to specify an output file to which the
36 reconstructed jets are written. If not set output goes to input file.
37 Attention call Init() before processing.
39 Revision 1.15 2002/02/02 08:37:18 morsch
40 Formula for rB corrected.
42 Revision 1.14 2002/02/01 08:55:30 morsch
43 Fill map with Et and pT.
45 Revision 1.13 2002/01/31 09:37:36 morsch
46 Geometry parameters in constructor and call of SetCellSize()
48 Revision 1.12 2002/01/23 13:40:23 morsch
49 Fastidious debug print statement removed.
51 Revision 1.11 2002/01/22 17:25:47 morsch
52 Some corrections for event mixing and bg event handling.
54 Revision 1.10 2002/01/22 10:31:44 morsch
55 Some correction for bg mixing.
57 Revision 1.9 2002/01/21 16:28:42 morsch
60 Revision 1.8 2002/01/21 16:05:31 morsch
61 - different phi-bin for hadron correction
62 - provisions for background mixing.
64 Revision 1.7 2002/01/21 15:47:18 morsch
65 Bending radius correctly in cm.
67 Revision 1.6 2002/01/21 12:53:50 morsch
70 Revision 1.5 2002/01/21 12:47:47 morsch
71 Possibility to include K0long and neutrons.
73 Revision 1.4 2002/01/21 11:03:21 morsch
74 Phi propagation introduced in FillFromTracks.
76 Revision 1.3 2002/01/18 05:07:56 morsch
79 - track selection upon EMCAL information
83 //*-- Authors: Andreas Morsch (CERN)
85 //* Aleksei Pavlinov (WSU)
90 #include <TClonesArray.h>
92 #include <TBranchElement.h>
100 #include <TPaveText.h>
103 #include <TParticle.h>
104 #include <TParticlePDG.h>
105 #include <TPythia6Calls.h>
108 #include "AliEMCALJetFinder.h"
109 #include "AliEMCALFast.h"
110 #include "AliEMCALGeometry.h"
111 #include "AliEMCALHit.h"
112 #include "AliEMCALDigit.h"
113 #include "AliEMCALDigitizer.h"
114 #include "AliEMCALHadronCorrection.h"
115 #include "AliEMCALJetMicroDst.h"
118 #include "AliMagFCM.h"
119 #include "AliEMCAL.h"
120 #include "AliHeader.h"
124 // Interface to FORTRAN
128 ClassImp(AliEMCALJetFinder)
130 //____________________________________________________________________________
131 AliEMCALJetFinder::AliEMCALJetFinder()
133 // Default constructor
152 fHadronCorrector = 0;
160 SetParametersForBgSubtraction();
163 AliEMCALJetFinder::AliEMCALJetFinder(const char* name, const char *title)
167 // Title is used in method GetFileNameForParameters();
169 fJets = new TClonesArray("AliEMCALJet",10000);
171 for (Int_t i = 0; i < 30000; i++)
193 fHadronCorrector = 0;
202 SetMomentumSmearing();
205 SetHadronCorrection();
206 SetSamplingFraction();
209 SetParametersForBgSubtraction();
212 void AliEMCALJetFinder::SetParametersForBgSubtraction
213 (Int_t mode, Float_t minMove, Float_t maxMove, Float_t precBg)
215 // see file /home/pavlinov/cosmic/pythia/jetFinderParamData.inc
216 // at WSU Linux cluster - 11-feb-2002
217 // These parameters must be tuned more carefull !!!
224 //____________________________________________________________________________
225 AliEMCALJetFinder::~AliEMCALJetFinder()
236 # define jet_finder_ua1 jet_finder_ua1_
238 # define type_of_call
241 # define jet_finder_ua1 JET_FINDER_UA1
243 # define type_of_call _stdcall
246 extern "C" void type_of_call
247 jet_finder_ua1(Int_t& ncell, Int_t& ncell_tot,
248 Float_t etc[30000], Float_t etac[30000],
250 Float_t& min_move, Float_t& max_move, Int_t& mode,
251 Float_t& prec_bg, Int_t& ierror);
253 extern "C" void type_of_call hf1(Int_t& id, Float_t& x, Float_t& wgt);
256 void AliEMCALJetFinder::Init()
259 // Geometry and I/O initialization
263 // Get geometry parameters from EMCAL
267 AliEMCAL* pEMCAL = (AliEMCAL*) gAlice->GetModule("EMCAL");
268 AliEMCALGeometry* geom =
269 AliEMCALGeometry::GetInstance(pEMCAL->GetTitle(), "");
270 fNbinEta = geom->GetNZ();
271 fNbinPhi = geom->GetNPhi();
272 fPhiMin = geom->GetArm1PhiMin()*TMath::Pi()/180.;
273 fPhiMax = geom->GetArm1PhiMax()*TMath::Pi()/180.;
274 fEtaMin = geom->GetArm1EtaMin();
275 fEtaMax = geom->GetArm1EtaMax();
276 fDphi = (fPhiMax-fPhiMin)/fNbinPhi;
277 fDeta = (fEtaMax-fEtaMin)/fNbinEta;
278 fNtot = fNbinPhi*fNbinEta;
280 SetCellSize(fDeta, fDphi);
283 if (fOutFileName) fOutFile = new TFile(fOutFileName, "recreate");
286 void AliEMCALJetFinder::Find(Int_t ncell, Int_t ncell_tot, Float_t etc[30000],
287 Float_t etac[30000], Float_t phic[30000],
288 Float_t min_move, Float_t max_move, Int_t mode,
289 Float_t prec_bg, Int_t ierror)
291 // Wrapper for fortran coded jet finder
292 // Full argument list
293 jet_finder_ua1(ncell, ncell_tot, etc, etac, phic,
294 min_move, max_move, mode, prec_bg, ierror);
295 // Write result to output
296 if(fWrite) WriteJets();
300 void AliEMCALJetFinder::Find()
302 // Wrapper for fortran coded jet finder using member data for
305 Float_t min_move = fMinMove;
306 Float_t max_move = fMaxMove;
308 Float_t prec_bg = fPrecBg;
311 ResetJets(); // 4-feb-2002 by PAI
313 jet_finder_ua1(fNcell, fNtot, fEtCell, fEtaCell, fPhiCell,
314 min_move, max_move, mode, prec_bg, ierror);
316 // Write result to output
317 Int_t njet = Njets();
319 for (Int_t nj=0; nj<njet; nj++)
322 fJetT[nj] = new AliEMCALJet(JetEnergy(nj),
327 FindTracksInJetCone();
328 if(fWrite) WriteJets();
332 Int_t AliEMCALJetFinder::Njets()
334 // Get number of reconstructed jets
335 return EMCALJETS.njet;
338 Float_t AliEMCALJetFinder::JetEnergy(Int_t i)
340 // Get reconstructed jet energy
341 return EMCALJETS.etj[i];
344 Float_t AliEMCALJetFinder::JetPhiL(Int_t i)
346 // Get reconstructed jet phi from leading particle
347 return EMCALJETS.phij[0][i];
350 Float_t AliEMCALJetFinder::JetPhiW(Int_t i)
352 // Get reconstructed jet phi from weighting
353 return EMCALJETS.phij[1][i];
356 Float_t AliEMCALJetFinder::JetEtaL(Int_t i)
358 // Get reconstructed jet eta from leading particles
359 return EMCALJETS.etaj[0][i];
363 Float_t AliEMCALJetFinder::JetEtaW(Int_t i)
365 // Get reconstructed jet eta from weighting
366 return EMCALJETS.etaj[1][i];
369 void AliEMCALJetFinder::SetCellSize(Float_t eta, Float_t phi)
371 // Set grid cell size
372 EMCALCELLGEO.etaCellSize = eta;
373 EMCALCELLGEO.phiCellSize = phi;
376 void AliEMCALJetFinder::SetConeRadius(Float_t par)
378 // Set jet cone radius
379 EMCALJETPARAM.coneRad = par;
383 void AliEMCALJetFinder::SetEtSeed(Float_t par)
385 // Set et cut for seeds
386 EMCALJETPARAM.etSeed = par;
390 void AliEMCALJetFinder::SetMinJetEt(Float_t par)
392 // Set minimum jet et
393 EMCALJETPARAM.ejMin = par;
397 void AliEMCALJetFinder::SetMinCellEt(Float_t par)
399 // Set et cut per cell
400 EMCALJETPARAM.etMin = par;
404 void AliEMCALJetFinder::SetPtCut(Float_t par)
406 // Set pT cut on charged tracks
411 void AliEMCALJetFinder::Test()
414 // Test the finder call
416 const Int_t nmax = 30000;
418 Int_t ncell_tot = 100;
423 Float_t min_move = 0;
424 Float_t max_move = 0;
430 Find(ncell, ncell_tot, etc, etac, phic,
431 min_move, max_move, mode, prec_bg, ierror);
439 void AliEMCALJetFinder::AddJet(const AliEMCALJet& jet)
444 TClonesArray &lrawcl = *fJets;
445 new(lrawcl[fNjets++]) AliEMCALJet(jet);
448 void AliEMCALJetFinder::ResetJets()
457 void AliEMCALJetFinder::WriteJets()
460 // Add all jets to the list
462 const Int_t kBufferSize = 4000;
463 const char* file = 0;
465 Int_t njet = Njets();
467 for (Int_t nj = 0; nj < njet; nj++)
476 // output written to input file
478 AliEMCAL* pEMCAL = (AliEMCAL* )gAlice->GetModule("EMCAL");
479 TTree* pK = gAlice->TreeK();
480 file = (pK->GetCurrentFile())->GetName();
482 printf("Make Branch - TreeR address %p %p\n",gAlice->TreeR(), pEMCAL);
483 if (fJets && gAlice->TreeR()) {
484 pEMCAL->MakeBranchInTree(gAlice->TreeR(),
490 Int_t nev = gAlice->GetHeader()->GetEvent();
491 gAlice->TreeR()->Fill();
493 sprintf(hname,"TreeR%d", nev);
494 gAlice->TreeR()->Write(hname);
495 gAlice->TreeR()->Reset();
498 // Output written to user specified output file
500 TTree* pK = gAlice->TreeK();
501 fInFile = pK->GetCurrentFile();
505 sprintf(hname,"TreeR%d", fEvent);
506 TTree* treeJ = new TTree(hname, "EMCALJets");
507 treeJ->Branch("EMCALJets", &fJets, kBufferSize);
515 void AliEMCALJetFinder::BookLego()
518 // Book histo for discretisation
522 // Don't add histos to the current directory
523 if(fDebug) printf("\n AliEMCALJetFinder::BookLego() \n");
525 // TH2::AddDirectory(0);
526 // TH1::AddDirectory(0);
530 fLego = new TH2F("legoH","eta-phi",
531 fNbinEta, fEtaMin, fEtaMax,
532 fNbinPhi, fPhiMin, fPhiMax);
535 fLegoB = new TH2F("legoB","eta-phi for BG event",
536 fNbinEta, fEtaMin, fEtaMax,
537 fNbinPhi, fPhiMin, fPhiMax);
540 fhLegoTracks = new TH2F("hLegoTracks","eta-phi for Tracks",
541 fNbinEta, fEtaMin, fEtaMax, fNbinPhi, fPhiMin, fPhiMax);
543 fhLegoEMCAL = new TH2F("hLegoEMCAL","eta-phi for EMCAL",
544 fNbinEta, fEtaMin, fEtaMax, fNbinPhi, fPhiMin, fPhiMax);
545 // Hadron correction map
546 fhLegoHadrCorr = new TH2F("hLegoHadrCorr","eta-phi for Hadron. Correction",
547 fNbinEta, fEtaMin, fEtaMax, fNbinPhi, fPhiMin, fPhiMax);
548 // Hists. for tuning jet finder
549 fhEff = new TH2F("hEff","#epsilon vs momentum ", 100,0.,20., 50,0.5,1.);
553 for(Int_t i=1; i<=1000; i++) eTmp[i] = 0.1*i; // step 100 mev
554 for(Int_t i=1001; i<=1100; i++) eTmp[i] = eTmp[1000] + 1.0*(i-1000); // step 1GeV
556 fhCellEt = new TH1F("hCellEt","Cell E_{T} from fLego",
557 eTmp.GetSize()-1, eTmp.GetArray());
558 fhCellEMCALEt = new TH1F("hCellEMCALEt","Cell E_{T} for EMCAL itself",
559 eTmp.GetSize()-1, eTmp.GetArray());
560 fhTrackPt = new TH1F("hTrackPt","Ch.particles P_{T} ",
561 eTmp.GetSize()-1, eTmp.GetArray());
562 fhTrackPtBcut = new TH1F("hTrackPtBcut","Ch.particles P_{T} + magnetic field cut",
563 eTmp.GetSize()-1, eTmp.GetArray());
565 fhChPartMultInTpc = new TH1F("hChPartMultInTpc",
566 "Charge partilcle multiplicity in |%eta|<0.9", 2000, 0, 20000);
568 //! first canvas for drawing
569 fHistsList=AliEMCALJetMicroDst::MoveHistsToList("Hists from AliEMCALJetFinder", kTRUE);
572 void AliEMCALJetFinder::DumpLego()
575 // Dump lego histo into array
578 TAxis* Xaxis = fLego->GetXaxis();
579 TAxis* Yaxis = fLego->GetYaxis();
580 // fhCellEt->Clear();
582 for (Int_t i = 1; i <= fNbinEta; i++) {
583 for (Int_t j = 1; j <= fNbinPhi; j++) {
584 e = fLego->GetBinContent(i,j);
586 Float_t eta = Xaxis->GetBinCenter(i);
587 Float_t phi = Yaxis->GetBinCenter(j);
589 fEtaCell[fNcell] = eta;
590 fPhiCell[fNcell] = phi;
595 eH = fhLegoEMCAL->GetBinContent(i,j);
596 if(eH > 0.0) fhCellEMCALEt->Fill(eH);
603 void AliEMCALJetFinder::ResetMap()
606 // Reset eta-phi array
608 for (Int_t i=0; i<30000; i++)
617 void AliEMCALJetFinder::FillFromTracks(Int_t flag, Int_t ich)
620 // Fill Cells with track information
623 printf("\n AliEMCALJetFinder::FillFromTracks(%i,%i) ",flag,ich);
628 if (!fLego) BookLego();
630 if (flag == 0) fLego->Reset();
632 // Access particle information
633 Int_t npart = (gAlice->GetHeader())->GetNprimary();
634 Int_t ntr = (gAlice->GetHeader())->GetNtrack();
635 printf(" : #primary particles %i # tracks %i \n", npart, ntr);
640 // 1: selected for jet finding
643 if (fTrackList) delete[] fTrackList;
644 if (fPtT) delete[] fPtT;
645 if (fEtaT) delete[] fEtaT;
646 if (fPhiT) delete[] fPhiT;
647 if (fPdgT) delete[] fPdgT;
649 fTrackList = new Int_t [npart];
650 fPtT = new Float_t[npart];
651 fEtaT = new Float_t[npart];
652 fPhiT = new Float_t[npart];
653 fPdgT = new Int_t[npart];
657 Float_t chTmp=0.0; // charge of current particle
660 // this is for Pythia ??
661 for (Int_t part = 0; part < npart; part++) {
662 TParticle *MPart = gAlice->Particle(part);
663 Int_t mpart = MPart->GetPdgCode();
664 Int_t child1 = MPart->GetFirstDaughter();
665 Float_t pT = MPart->Pt();
666 Float_t p = MPart->P();
667 Float_t phi = MPart->Phi();
669 if(pT > 0.001) eta = MPart->Eta();
670 Float_t theta = MPart->Theta();
672 printf("ind %7i part %7i -> child1 %5i child2 %5i Status %5i\n",
673 part, mpart, child1, MPart->GetLastDaughter(), MPart->GetStatusCode());
677 if (part == 6 || part == 7)
679 printf("\n Simulated Jet (pt, eta, phi): %d %f %f %f\n",
680 part-5, pT, eta, phi);
685 // printf("\n Simulated Jet (pt, eta, phi): %d %d %f %f %f",
686 // part, mpart, pT, eta, phi);
689 fTrackList[part] = 0;
690 fPtT[part] = pT; // must be change after correction for resolution !!!
696 if (part < 2) continue;
698 // move to fLego->Fill because hadron correction must apply
699 // if particle hit to EMCAL - 11-feb-2002
700 // if (pT == 0 || pT < fPtCut) continue;
701 TParticlePDG* pdgP = 0;
702 // charged or neutral
703 pdgP = MPart->GetPDG();
704 chTmp = pdgP->Charge() / 3.; // 13-feb-2001!!
710 if (mpart != kNeutron &&
711 mpart != kNeutronBar &&
712 mpart != kK0Long) continue;
717 if (TMath::Abs(mpart) <= 6 ||
719 mpart == 92) continue;
721 if (TMath::Abs(eta)<=0.9) fNChTpc++;
723 if (child1 >= 0 && child1 < npart) continue;
725 if (TMath::Abs(eta) > 0.7) continue;
726 // Initial phi may be out of acceptance but track may
727 // hit two the acceptance - see variable curls
728 if (phi*180./TMath::Pi() > 120.) continue;
731 printf("\n=>nsel:%5d mpart %5d child1 %5d eta %6.2f phi %6.2f pT %6.2f ch %3.0f ",
732 part, mpart, child1, eta, phi, pT, chTmp);
735 // Momentum smearing goes here ...
739 if (fSmear && TMath::Abs(chTmp)) {
740 pw = AliEMCALFast::SmearMomentum(1,p);
741 // p changed - take into account when calculate pT,
744 if(fDebug >= 4) printf("\n Smearing : p %8.4f change to %8.4f ", p, pw);
748 // Tracking Efficiency and TPC acceptance goes here ...
750 if (fEffic && TMath::Abs(chTmp)) {
751 // eff = AliEMCALFast::Efficiency(1,p);
752 eff = 0.95; // for testing 25-feb-2002
753 if(fhEff) fhEff->Fill(p, eff);
754 if (AliEMCALFast::RandomReject(eff)) {
755 if(fDebug >= 5) printf(" reject due to unefficiency ");
760 // Correction of Hadronic Energy goes here ...
763 // phi propagation for hadronic correction
765 Bool_t curls = kFALSE; // hit two the EMCAL (no curl)
766 Float_t phiHC=0.0, dpH=0.0, dphi=0.0, eTdpH=0;
767 if(TMath::Abs(chTmp)) {
768 // hadr. correction only for charge particle
769 dphi = PropagatePhi(pT, chTmp, curls);
772 printf("\n Delta phi %f pT %f ", dphi, pT);
773 if (curls) printf("\n !! Track is curling");
775 if(!curls) fhTrackPtBcut->Fill(pT);
777 if (fHCorrection && !curls) {
778 if (!fHadronCorrector)
779 Fatal("AliEMCALJetFinder",
780 "Hadronic energy correction required but not defined !");
782 dpH = fHadronCorrector->GetEnergy(p, eta, 7);
783 eTdpH = dpH*TMath::Sin(theta);
785 if (fDebug >= 7) printf(" phi %f phiHC %f eTcorr %f\n",
786 phi, phiHC, -eTdpH); // correction is negative
787 fLego->Fill(eta, phiHC, -eTdpH);
788 fhLegoHadrCorr->Fill(eta, phiHC, eTdpH);
792 // More to do ? Just think about it !
795 if (phi*180./TMath::Pi() > 120.) continue;
797 if(TMath::Abs(chTmp) ) { // charge particle
798 if (pT > fPtCut && !curls) {
799 if (fDebug >= 8) printf("Charge : fLego->Fill(%5.2f, %5.2f, %6.2f)\n",
801 fLego->Fill(eta, phi, pT);
802 fhLegoTracks->Fill(eta, phi, pT); // 20-feb for checking
803 fTrackList[part] = 1;
806 } else if(ich==0 && fK0N) {
807 // case of n, nbar and K0L
808 if (fDebug >= 9) printf("Neutral : fLego->Fill(%5.2f, %5.2f, %6.2f)\n",
810 fLego->Fill(eta, phi, pT);
811 fTrackList[part] = 1;
819 void AliEMCALJetFinder::FillFromHits(Int_t flag)
822 // Fill Cells with hit information
826 printf("\n AliEMCALJetFinder::FillFromHits(%i)\n",flag);
830 if (!fLego) BookLego();
831 // Reset eta-phi maps if needed
832 if (flag == 0) { // default behavior
834 fhLegoTracks->Reset();
835 fhLegoEMCAL->Reset();
836 fhLegoHadrCorr->Reset();
838 // Initialize from background event if available
840 // Access hit information
841 AliEMCAL* pEMCAL = (AliEMCAL*) gAlice->GetModule("EMCAL");
843 TTree *treeH = gAlice->TreeH();
844 Int_t ntracks = (Int_t) treeH->GetEntries();
851 for (Int_t track=0; track<ntracks;track++) {
853 nbytes += treeH->GetEvent(track);
857 for(AliEMCALHit* mHit=(AliEMCALHit*) pEMCAL->FirstHit(-1);
859 mHit=(AliEMCALHit*) pEMCAL->NextHit())
861 Float_t x = mHit->X(); // x-pos of hit
862 Float_t y = mHit->Y(); // y-pos
863 Float_t z = mHit->Z(); // z-pos
864 Float_t eloss = mHit->GetEnergy(); // deposited energy
866 Float_t r = TMath::Sqrt(x*x+y*y);
867 Float_t theta = TMath::ATan2(r,z);
868 Float_t eta = -TMath::Log(TMath::Tan(theta/2.));
869 Float_t phi = TMath::ATan2(y,x);
871 if (fDebug >= 11) printf("\n Hit %f %f %f %f", x, y, z, eloss);
873 etH = fSamplingF*eloss*TMath::Sin(theta);
874 fLego->Fill(eta, phi, etH);
875 // fhLegoEMCAL->Fill(eta, phi, etH);
878 // copy content of fLego to fhLegoEMCAL (fLego and fhLegoEMCAL are identical)
879 for(Int_t i=0; i<fLego->GetSize(); i++) (*fhLegoEMCAL)[i] = (*fLego)[i];
883 void AliEMCALJetFinder::FillFromDigits(Int_t flag)
886 // Fill Cells with digit information
891 if (!fLego) BookLego();
892 if (flag == 0) fLego->Reset();
899 TClonesArray* digs = new TClonesArray("AliEMCALDigit", 10000);
900 TTree *treeD = gAlice->TreeD();
901 TBranchElement* branchDg = (TBranchElement*)
902 treeD->GetBranch("EMCAL");
904 if (!branchDg) Fatal("AliEMCALJetFinder",
905 "Reading digits requested but no digits in file !");
907 branchDg->SetAddress(&digs);
908 Int_t nent = (Int_t) branchDg->GetEntries();
912 AliEMCALDigitizer* digr = new AliEMCALDigitizer();
913 TBranchElement* branchDr = (TBranchElement*)
914 treeD->GetBranch("AliEMCALDigitizer");
915 branchDr->SetAddress(&digr);
918 nbytes += branchDg->GetEntry(0);
919 nbytes += branchDr->GetEntry(0);
921 // Get digitizer parameters
922 Float_t towerADCped = digr->GetTowerpedestal();
923 Float_t towerADCcha = digr->GetTowerchannel();
924 Float_t preshoADCped = digr->GetPreShopedestal();
925 Float_t preshoADCcha = digr->GetPreShochannel();
927 AliEMCAL* pEMCAL = (AliEMCAL*) gAlice->GetModule("EMCAL");
928 AliEMCALGeometry* geom =
929 AliEMCALGeometry::GetInstance(pEMCAL->GetTitle(), "");
932 Int_t ndig = digs->GetEntries();
933 printf("\n Number of Digits: %d %d\n", ndig, nent);
934 printf("\n Parameters: %f %f %f %f\n",
935 towerADCped, towerADCcha, preshoADCped, preshoADCcha );
936 printf("\n Geometry: %d %d\n", geom->GetNEta(), geom->GetNPhi());
943 while ((sdg = (AliEMCALDigit*)(next())))
947 if (sdg->GetId() > (geom->GetNZ() * geom->GetNPhi()))
949 pedestal = preshoADCped;
950 channel = preshoADCcha;
952 pedestal = towerADCped;
953 channel = towerADCcha;
956 Float_t eta = sdg->GetEta();
957 Float_t phi = sdg->GetPhi() * TMath::Pi()/180.;
958 Float_t amp = (Float_t) (channel*(sdg->GetAmp())-pedestal);
960 if (fDebug > 1) printf("\n Digit: eta %8.3f phi %8.3f amp %8.3f %8d",
961 eta, phi, amp, sdg->GetAmp());
963 fLego->Fill(eta, phi, fSamplingF*amp);
971 void AliEMCALJetFinder::FillFromHitFlaggedTracks(Int_t flag)
974 // Fill Cells with hit information
979 if (!fLego) BookLego();
981 if (flag == 0) fLego->Reset();
983 // Flag charged tracks passing through TPC which
984 // are associated to EMCAL Hits
985 BuildTrackFlagTable();
988 // Access particle information
989 TTree *treeK = gAlice->TreeK();
990 Int_t ntracks = (Int_t) treeK->GetEntries();
992 if (fPtT) delete[] fPtT;
993 if (fEtaT) delete[] fEtaT;
994 if (fPhiT) delete[] fPhiT;
995 if (fPdgT) delete[] fPdgT;
997 fPtT = new Float_t[ntracks];
998 fEtaT = new Float_t[ntracks];
999 fPhiT = new Float_t[ntracks];
1000 fPdgT = new Int_t[ntracks];
1005 for (Int_t track = 0; track < ntracks; track++) {
1006 TParticle *MPart = gAlice->Particle(track);
1007 Float_t pT = MPart->Pt();
1008 Float_t phi = MPart->Phi();
1009 Float_t eta = MPart->Eta();
1011 if(fTrackList[track]) {
1015 fPdgT[track] = MPart->GetPdgCode();
1017 if (track < 2) continue; //Colliding particles?
1018 if (pT == 0 || pT < fPtCut) continue;
1020 fLego->Fill(eta, phi, pT);
1026 void AliEMCALJetFinder::FillFromParticles()
1028 // 26-feb-2002 PAI - for checking all chain
1029 // Work on particles level; accept all particle (not neutrino )
1031 Double_t PX=0, PY=0, PZ=0, E=0; // checking conservation law
1035 if (!fLego) BookLego();
1038 // Access particles information
1039 Int_t npart = (gAlice->GetHeader())->GetNprimary();
1040 if (fDebug >= 2 || npart<=0) {
1041 printf(" AliEMCALJetFinder::FillFromParticles : npart %i\n", npart);
1042 if(npart<=0) return;
1046 RearrangeParticlesMemory(npart);
1048 // Go through the particles
1049 Int_t mpart, child1, child2, geantPdg;
1050 Float_t pT, phi, eta, e=0, px=0, py=0, pz=0;
1052 for (Int_t part = 0; part < npart; part++) {
1054 fTrackList[part] = 0;
1056 MPart = gAlice->Particle(part);
1057 mpart = MPart->GetPdgCode();
1058 child1 = MPart->GetFirstDaughter();
1059 child2 = MPart->GetLastDaughter();
1067 e = MPart->Energy();
1069 // see pyedit in Pythia's text
1071 // Int_t kc = pycomp_(&mpart);
1072 // TString name = GetPythiaParticleName(mpart);
1073 // printf(" mpart %6.6i;kc %6.6i -> gid %3.3i",mpart,kc,geantPdg);
1074 //printf(" (%s)\n", name.Data());
1075 if (IsThisPartonsOrDiQuark(mpart)) continue;
1076 printf("%5i: %5i(%2i) px %5.1f py %5.1f pz %6.1f e %6.1f childs %5i,%5i \n",
1077 part, mpart, geantPdg, px, py, pz, e, child1, child2);
1079 // exclude partons (21 - gluon, 92 - string)
1082 // exclude neutrinous also ??
1083 if (fDebug >= 11 && pT>0.01)
1084 printf("\n part:%5d mpart %5d eta %9.2f phi %9.2f pT %9.2f ",
1085 part, mpart, eta, phi, pT);
1090 fPdgT[part] = mpart;
1093 if (child1 >= 0 && child1 < npart) continue;
1095 // printf("%4i -> %5i(%3i) px %6.1f py %6.1f pz %7.1f e %8.2f child1 %5i %s\n",
1096 // part, mpart, geantPdg, px, py, pz, e, child1, name.Data());
1103 if (TMath::Abs(eta) <= 0.9) fNChTpc++;
1105 if (TMath::Abs(eta) > 0.7) continue;
1106 if (phi*180./TMath::Pi() > 120.) continue;
1108 if(fK0N==0 ) { // exclude neutral hadrons
1109 if (mpart == kNeutron || mpart == kNeutronBar || mpart == kK0Long) continue;
1111 fTrackList[part] = 1;
1112 fLego->Fill(eta, phi, pT);
1115 printf("\n PX %8.2f PY %8.2f PZ %8.2f E %8.2f \n",
1118 if(fhChPartMultInTpc) fhChPartMultInTpc->Fill(fNChTpc);
1121 void AliEMCALJetFinder::FillFromPartons()
1123 // function under construction - 13-feb-2002 PAI
1126 printf("\n AliEMCALJetFinder::FillFromPartons()\n");
1130 if (!fLego) BookLego();
1133 // Access particle information
1134 Int_t npart = (gAlice->GetHeader())->GetNprimary();
1135 if (fDebug >= 2 || npart<=0)
1136 printf("\n AliEMCALJetFinder::FillFromPartons : npart %i\n", npart);
1137 fNt = 0; // for FindTracksInJetCone
1140 // Go through the partons
1142 for (Int_t part = 8; part < npart; part++) {
1143 TParticle *MPart = gAlice->Particle(part);
1144 Int_t mpart = MPart->GetPdgCode();
1145 // Int_t child1 = MPart->GetFirstDaughter();
1146 Float_t pT = MPart->Pt();
1147 // Float_t p = MPart->P();
1148 Float_t phi = MPart->Phi();
1149 Float_t eta = MPart->Eta();
1150 // Float_t theta = MPart->Theta();
1151 statusCode = MPart->GetStatusCode();
1153 // accept partons (21 - gluon, 92 - string)
1154 if (!(TMath::Abs(mpart) <= 6 || mpart == 21 ||mpart == 92)) continue;
1155 if (fDebug > 1 && pT>0.01)
1156 printf("\n part:%5d mpart %5d status %5d eta %8.2f phi %8.2f pT %8.2f ",
1157 part, mpart, statusCode, eta, phi, pT);
1158 // if (fDebug >= 3) MPart->Print();
1159 // accept partons before fragmentation - p.57 in Pythia manual
1160 // if(statusCode != 1) continue;
1162 if (TMath::Abs(eta) > 0.7) continue;
1163 if (phi*180./TMath::Pi() > 120.) continue;
1165 // if (child1 >= 0 && child1 < npart) continue;
1168 fLego->Fill(eta, phi, pT);
1174 void AliEMCALJetFinder::BuildTrackFlagTable() {
1176 // Method to generate a lookup table for TreeK particles
1177 // which are linked to hits in the EMCAL
1179 // --Author: J.L. Klay
1181 // Access hit information
1182 AliEMCAL* pEMCAL = (AliEMCAL*) gAlice->GetModule("EMCAL");
1184 TTree *TK = gAlice->TreeK(); // Get the number of entries in the kine tree
1185 Int_t nKTrks = (Int_t) TK->GetEntries(); // (Number of particles created somewhere)
1187 if(fTrackList) delete[] fTrackList; //Make sure we get rid of the old one
1188 fTrackList = new Int_t[nKTrks]; //before generating a new one
1190 for (Int_t i = 0; i < nKTrks; i++) { //Initialize members to 0
1194 TTree *treeH = gAlice->TreeH();
1195 Int_t ntracks = (Int_t) treeH->GetEntries();
1201 for (Int_t track=0; track<ntracks;track++) {
1202 gAlice->ResetHits();
1203 nbytes += treeH->GetEvent(track);
1209 for(AliEMCALHit* mHit=(AliEMCALHit*) pEMCAL->FirstHit(-1);
1211 mHit=(AliEMCALHit*) pEMCAL->NextHit())
1213 Int_t iTrk = mHit->Track(); // track number
1214 Int_t idprim = mHit->GetPrimary(); // primary particle
1216 //Determine the origin point of this particle - it made a hit in the EMCAL
1217 TParticle *trkPart = gAlice->Particle(iTrk);
1218 TParticlePDG *trkPdg = trkPart->GetPDG();
1219 Int_t trkCode = trkPart->GetPdgCode();
1221 if (trkCode < 10000) { //Big Ions cause problems for
1222 trkChg = trkPdg->Charge(); //this function. Since they aren't
1223 } else { //likely to make it very far, set
1224 trkChg = 0.0; //their charge to 0 for the Flag test
1226 Float_t vxTrk = trkPart->Vx();
1227 Float_t vyTrk = trkPart->Vy();
1228 Float_t vrTrk = TMath::Sqrt(vxTrk*vxTrk+vyTrk*vyTrk);
1229 fTrackList[iTrk] = SetTrackFlag(vrTrk,trkCode,trkChg);
1231 //Loop through the ancestry of the EMCAL entrance particles
1232 Int_t ancestor = trkPart->GetFirstMother(); //Get track's Mother
1233 while (ancestor != -1) {
1234 TParticle *ancPart = gAlice->Particle(ancestor); //get particle info on ancestor
1235 TParticlePDG *ancPdg = ancPart->GetPDG();
1236 Int_t ancCode = ancPart->GetPdgCode();
1238 if (ancCode < 10000) {
1239 ancChg = ancPdg->Charge();
1243 Float_t vxAnc = ancPart->Vx();
1244 Float_t vyAnc = ancPart->Vy();
1245 Float_t vrAnc = TMath::Sqrt(vxAnc*vxAnc+vyAnc*vyAnc);
1246 fTrackList[ancestor] = SetTrackFlag(vrAnc,ancCode,ancChg);
1247 ancestor = ancPart->GetFirstMother(); //Get the next ancestor
1250 //Determine the origin point of the primary particle associated with the hit
1251 TParticle *primPart = gAlice->Particle(idprim);
1252 TParticlePDG *primPdg = primPart->GetPDG();
1253 Int_t primCode = primPart->GetPdgCode();
1255 if (primCode < 10000) {
1256 primChg = primPdg->Charge();
1260 Float_t vxPrim = primPart->Vx();
1261 Float_t vyPrim = primPart->Vy();
1262 Float_t vrPrim = TMath::Sqrt(vxPrim*vxPrim+vyPrim*vyPrim);
1263 fTrackList[idprim] = SetTrackFlag(vrPrim,primCode,primChg);
1269 Int_t AliEMCALJetFinder
1270 ::SetTrackFlag(Float_t radius, Int_t code, Double_t charge) {
1276 if (charge == 0) neutral = 1;
1278 if (TMath::Abs(code) <= 6 ||
1280 code == 92) parton = 1;
1282 //It's not a parton, it's charged and it went through the TPC
1283 if (!parton && !neutral && radius <= 84.0) flag = 1;
1290 void AliEMCALJetFinder::SaveBackgroundEvent()
1292 // Saves the eta-phi lego and the tracklist
1296 (*fLegoB) = (*fLegoB) + (*fLego);
1298 printf("\n AliEMCALJetFinder::SaveBackgroundEvent() (fLegoB) %f = %f(fLego) \n",
1299 fLegoB->Integral(), fLego->Integral());
1302 if (fPtB) delete[] fPtB;
1303 if (fEtaB) delete[] fEtaB;
1304 if (fPhiB) delete[] fPhiB;
1305 if (fPdgB) delete[] fPdgB;
1306 if (fTrackListB) delete[] fTrackListB;
1308 fPtB = new Float_t[fNtS];
1309 fEtaB = new Float_t[fNtS];
1310 fPhiB = new Float_t[fNtS];
1311 fPdgB = new Int_t [fNtS];
1312 fTrackListB = new Int_t [fNtS];
1316 for (Int_t i = 0; i < fNt; i++) {
1317 if (!fTrackList[i]) continue;
1318 fPtB [fNtB] = fPtT [i];
1319 fEtaB[fNtB] = fEtaT[i];
1320 fPhiB[fNtB] = fPhiT[i];
1321 fPdgB[fNtB] = fPdgT[i];
1323 fTrackListB[fNtB] = 1;
1327 printf(" fNtB %i => fNtS %i #particles %i \n", fNtB, fNtS, fNt);
1330 void AliEMCALJetFinder::InitFromBackground()
1334 if (fDebug) printf("\n AliEMCALJetFinder::InitFromBackground() ");
1338 (*fLego) = (*fLego) + (*fLegoB);
1340 printf("\n AliEMCALJetFinder::SaveBackgroundEvent() (fLego) %f = %f(fLegoB) \n",
1341 fLego->Integral(), fLegoB->Integral());
1343 printf(" => fLego undefined \n");
1348 void AliEMCALJetFinder::FindTracksInJetCone()
1351 // Build list of tracks inside jet cone
1354 Int_t njet = Njets();
1355 for (Int_t nj = 0; nj < njet; nj++)
1357 Float_t etaj = JetEtaW(nj);
1358 Float_t phij = JetPhiW(nj);
1359 Int_t nT = 0; // number of associated tracks
1361 // Loop over particles in current event
1362 for (Int_t part = 0; part < fNt; part++) {
1363 if (!fTrackList[part]) continue;
1364 Float_t phi = fPhiT[part];
1365 Float_t eta = fEtaT[part];
1366 Float_t dr = TMath::Sqrt((etaj-eta)*(etaj-eta) +
1367 (phij-phi)*(phij-phi));
1368 if (dr < fConeRadius) {
1369 fTrackList[part] = nj+2;
1374 // Same for background event if available
1377 for (Int_t part = 0; part < fNtB; part++) {
1378 Float_t phi = fPhiB[part];
1379 Float_t eta = fEtaB[part];
1380 Float_t dr = TMath::Sqrt((etaj-eta)*(etaj-eta) +
1381 (phij-phi)*(phij-phi));
1382 fTrackListB[part] = 1;
1384 if (dr < fConeRadius) {
1385 fTrackListB[part] = nj+2;
1389 } // Background available ?
1391 Int_t nT0 = nT + nTB;
1393 if (nT0 > 50) nT0 = 50;
1395 Float_t* ptT = new Float_t[nT0];
1396 Float_t* etaT = new Float_t[nT0];
1397 Float_t* phiT = new Float_t[nT0];
1398 Int_t* pdgT = new Int_t[nT0];
1403 for (Int_t part = 0; part < fNt; part++) {
1404 if (fTrackList[part] == nj+2) {
1406 for (j=iT-1; j>=0; j--) {
1407 if (fPtT[part] > ptT[j]) {
1412 for (j=iT-1; j>=index; j--) {
1413 ptT [j+1] = ptT [j];
1414 etaT[j+1] = etaT[j];
1415 phiT[j+1] = phiT[j];
1416 pdgT[j+1] = pdgT[j];
1418 ptT [index] = fPtT [part];
1419 etaT[index] = fEtaT[part];
1420 phiT[index] = fPhiT[part];
1421 pdgT[index] = fPdgT[part];
1423 } // particle associated
1424 if (iT > nT0) break;
1428 for (Int_t part = 0; part < fNtB; part++) {
1429 if (fTrackListB[part] == nj+2) {
1431 for (j=iT-1; j>=0; j--) {
1432 if (fPtB[part] > ptT[j]) {
1438 for (j=iT-1; j>=index; j--) {
1439 ptT [j+1] = ptT [j];
1440 etaT[j+1] = etaT[j];
1441 phiT[j+1] = phiT[j];
1442 pdgT[j+1] = pdgT[j];
1444 ptT [index] = fPtB [part];
1445 etaT[index] = fEtaB[part];
1446 phiT[index] = fPhiB[part];
1447 pdgT[index] = fPdgB[part];
1449 } // particle associated
1450 if (iT > nT0) break;
1452 } // Background available ?
1454 fJetT[nj]->SetTrackList(nT0, ptT, etaT, phiT, pdgT);
1463 Float_t AliEMCALJetFinder::PropagatePhi(Float_t pt, Float_t charge, Bool_t& curls)
1465 // Propagates phi angle to EMCAL radius
1467 static Float_t b = 0.0, rEMCAL = -1.0;
1470 b = ((AliMagFCM*) gAlice->Field())->SolenoidField();
1471 // Get EMCAL radius in cm
1472 rEMCAL = AliEMCALGeometry::GetInstance()->GetIPDistance();
1473 printf("\nMagnetic field %f rEMCAL %f ", b, rEMCAL);
1482 Float_t rB = 3335.6 * pt / b; // [cm] (case of |charge|=1)
1484 // check if particle is curling below EMCAL
1485 if (2.*rB < rEMCAL) {
1490 // if not calculate delta phi
1491 Float_t phi = TMath::ACos(1.-rEMCAL*rEMCAL/(2.*rB*rB));
1492 dPhi = TMath::ATan2(1.-TMath::Cos(phi), TMath::Sin(phi));
1493 dPhi = -TMath::Sign(dPhi, charge);
1498 void hf1(Int_t& id, Float_t& x, Float_t& wgt)
1500 // dummy for hbook calls
1504 void AliEMCALJetFinder::DrawLego(Char_t *opt)
1507 void AliEMCALJetFinder::DrawLegoEMCAL(Char_t *opt)
1508 {fhLegoEMCAL->Draw(opt);}
1510 void AliEMCALJetFinder::DrawHistsForTuning(Int_t mode)
1512 static TPaveText *varLabel=0;
1514 fC1 = new TCanvas("C1","Hists. for tunning", 0,25,600,800);
1524 fhCellEMCALEt->Draw();
1529 fhTrackPtBcut->SetLineColor(2);
1530 fhTrackPtBcut->Draw("same");
1535 varLabel = new TPaveText(0.05,0.5,0.95,0.95,"NDC");
1536 varLabel->SetTextAlign(12);
1537 varLabel->SetFillColor(19); // see TAttFill
1538 TString tmp(GetTitle());
1539 varLabel->ReadFile(GetFileNameForParameters());
1543 if(mode) { // for saving picture to the file
1544 TString stmp(GetFileNameForParameters());
1545 stmp.ReplaceAll("_Par.txt",".ps");
1546 fC1->Print(stmp.Data());
1550 void AliEMCALJetFinder::PrintParameters(Int_t mode)
1553 if(mode==0) file = stdout; // output to terminal
1555 file = fopen(GetFileNameForParameters(),"w");
1556 if(file==0) file = stdout;
1558 fprintf(file,"==== Filling lego ==== \n");
1559 fprintf(file,"Smearing %6i ", fSmear);
1560 fprintf(file,"Efficiency %6i\n", fEffic);
1561 fprintf(file,"Hadr.Correct. %6i ", fHCorrection);
1562 fprintf(file,"P_{T} Cut of ch.par. %6.2f\n", fPtCut);
1563 fprintf(file,"==== Jet finding ==== \n");
1564 fprintf(file,"Cone radius %6.2f ", fConeRadius);
1565 fprintf(file,"Seed E_{T} %6.1f\n", fEtSeed);
1566 fprintf(file,"Min E_{T} of cell %6.1f ", fMinCellEt);
1567 fprintf(file,"Min E_{T} of jet %6.1f\n", fMinJetEt);
1569 fprintf(file,"==== Bg subtraction ==== \n");
1570 fprintf(file,"BG subtraction %6i ", fMode);
1571 fprintf(file,"Min cone move %6.2f\n", fMinMove);
1572 fprintf(file,"Max cone move %6.2f ", fMaxMove);
1573 fprintf(file,"%% change for BG %6.4f\n", fPrecBg);
1575 fprintf(file,"==== No Bg subtraction ==== \n");
1576 if(file != stdout) fclose(file);
1579 void AliEMCALJetFinder::DrawLegos()
1582 fC1 = new TCanvas("C1","Hists. for tunning", 0,25,600,800);
1586 gStyle->SetOptStat(111111);
1588 Int_t nent1, nent2, nent3, nent4;
1589 Double_t int1, int2, int3, int4;
1590 nent1 = (Int_t)fLego->GetEntries();
1591 int1 = fLego->Integral();
1593 if(int1) fLego->Draw("lego");
1595 nent2 = (Int_t)fhLegoTracks->GetEntries();
1596 int2 = fhLegoTracks->Integral();
1598 if(int2) fhLegoTracks->Draw("lego");
1600 nent3 = (Int_t)fhLegoEMCAL->GetEntries();
1601 int3 = fhLegoEMCAL->Integral();
1603 if(int3) fhLegoEMCAL->Draw("lego");
1605 nent4 = (Int_t)fhLegoHadrCorr->GetEntries();
1606 int4 = fhLegoHadrCorr->Integral();
1608 if(int4) fhLegoHadrCorr->Draw("lego");
1610 // just for checking
1611 printf(" Integrals \n");
1612 printf("lego %10.3f \ntrack %10.3f \nhits %10.3f \nHCorr %10.3f\n-- %10.3f(must be 0)\n",
1613 int1, int2, int3, int4, int1 - (int2 + int3 - int4));
1616 const Char_t* AliEMCALJetFinder::GetFileNameForParameters(Char_t* dir)
1619 if(strlen(dir)) tmp = dir;
1625 void AliEMCALJetFinder::RearrangeParticlesMemory(Int_t npart)
1626 { // See FillFromTracks() - npart must be positive
1627 if (fTrackList) delete[] fTrackList;
1628 if (fPtT) delete[] fPtT;
1629 if (fEtaT) delete[] fEtaT;
1630 if (fPhiT) delete[] fPhiT;
1631 if (fPdgT) delete[] fPdgT;
1634 fTrackList = new Int_t [npart];
1635 fPtT = new Float_t[npart];
1636 fEtaT = new Float_t[npart];
1637 fPhiT = new Float_t[npart];
1638 fPdgT = new Int_t[npart];
1640 printf("AliEMCALJetFinder::RearrangeParticlesMemory : npart = %d\n", npart);
1644 Bool_t AliEMCALJetFinder::IsThisPartonsOrDiQuark(Int_t pdg)
1646 Int_t absPdg = TMath::Abs(pdg);
1647 if(absPdg<=6) return kTRUE; // quarks
1648 if(pdg == 21) return kTRUE; // gluon
1649 if(pdg == 92) return kTRUE; // string
1651 // see p.51 of Pythia Manual
1652 // Not include diquarks with c and b quark - 4-mar-2002
1653 // ud_0,sd_0,su_0; dd_1,ud_1,uu_1; sd_1,su_1,ss_1
1654 static Int_t diquark[9]={2101,3101,3201, 1103,2103,2203, 3103,3203,3303};
1655 for(Int_t i=0; i<9; i++) if(absPdg == diquark[i]) return kTRUE; // diquarks
1660 TString &AliEMCALJetFinder::GetPythiaParticleName(Int_t kf)
1661 {// see subroutine PYNAME in PYTHIA
1662 static TString sname;
1664 pyname_(&kf, name, 16);
1665 for(Int_t i=0; i<16; i++){
1666 if(name[i] == ' ') {