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.26 2002/10/14 14:55:35 hristov
19 Merging the VirtualMC branch to the main development branch (HEAD)
21 Revision 1.20.4.3 2002/10/10 15:07:49 hristov
22 Updating VirtualMC to v3-09-02
24 Revision 1.25 2002/09/13 10:24:57 morsch
27 Revision 1.24 2002/09/13 10:21:13 morsch
30 Revision 1.23 2002/06/27 09:24:26 morsch
31 Uncomment the TH1::AddDirectory statement.
33 Revision 1.22 2002/05/22 13:48:43 morsch
34 Pdg code added to track list.
36 Revision 1.21 2002/04/27 07:43:08 morsch
37 Calculation of fDphi corrected (Renan Cabrera)
39 Revision 1.20 2002/03/12 01:06:23 pavlinov
40 Testin output from generator
42 Revision 1.19 2002/02/27 00:46:33 pavlinov
43 Added method FillFromParticles()
45 Revision 1.18 2002/02/21 08:48:59 morsch
46 Correction in FillFromHitFlaggedTrack. (Jennifer Klay)
48 Revision 1.17 2002/02/14 08:52:53 morsch
49 Major updates by Aleksei Pavlinov:
50 FillFromPartons, FillFromTracks, jetfinder configuration.
52 Revision 1.16 2002/02/08 11:43:05 morsch
53 SetOutputFileName(..) allows to specify an output file to which the
54 reconstructed jets are written. If not set output goes to input file.
55 Attention call Init() before processing.
57 Revision 1.15 2002/02/02 08:37:18 morsch
58 Formula for rB corrected.
60 Revision 1.14 2002/02/01 08:55:30 morsch
61 Fill map with Et and pT.
63 Revision 1.13 2002/01/31 09:37:36 morsch
64 Geometry parameters in constructor and call of SetCellSize()
66 Revision 1.12 2002/01/23 13:40:23 morsch
67 Fastidious debug print statement removed.
69 Revision 1.11 2002/01/22 17:25:47 morsch
70 Some corrections for event mixing and bg event handling.
72 Revision 1.10 2002/01/22 10:31:44 morsch
73 Some correction for bg mixing.
75 Revision 1.9 2002/01/21 16:28:42 morsch
78 Revision 1.8 2002/01/21 16:05:31 morsch
79 - different phi-bin for hadron correction
80 - provisions for background mixing.
82 Revision 1.7 2002/01/21 15:47:18 morsch
83 Bending radius correctly in cm.
85 Revision 1.6 2002/01/21 12:53:50 morsch
88 Revision 1.5 2002/01/21 12:47:47 morsch
89 Possibility to include K0long and neutrons.
91 Revision 1.4 2002/01/21 11:03:21 morsch
92 Phi propagation introduced in FillFromTracks.
94 Revision 1.3 2002/01/18 05:07:56 morsch
97 - track selection upon EMCAL information
101 //*-- Authors: Andreas Morsch (CERN)
103 //* Aleksei Pavlinov (WSU)
108 #include <TClonesArray.h>
110 #include <TBranchElement.h>
118 #include <TPaveText.h>
121 #include <TParticle.h>
122 #include <TParticlePDG.h>
123 #include <TPythia6Calls.h>
126 #include "AliEMCALJetFinder.h"
127 #include "AliEMCALFast.h"
128 #include "AliEMCALGeometry.h"
129 #include "AliEMCALHit.h"
130 #include "AliEMCALDigit.h"
131 #include "AliEMCALDigitizer.h"
132 #include "AliEMCALHadronCorrection.h"
133 #include "AliEMCALJetMicroDst.h"
136 #include "AliMagFCM.h"
137 #include "AliEMCAL.h"
138 #include "AliHeader.h"
142 // Interface to FORTRAN
146 ClassImp(AliEMCALJetFinder)
148 //____________________________________________________________________________
149 AliEMCALJetFinder::AliEMCALJetFinder()
151 // Default constructor
170 fHadronCorrector = 0;
178 SetParametersForBgSubtraction();
181 AliEMCALJetFinder::AliEMCALJetFinder(const char* name, const char *title)
185 // Title is used in method GetFileNameForParameters();
187 fJets = new TClonesArray("AliEMCALJet",10000);
189 for (Int_t i = 0; i < 30000; i++)
211 fHadronCorrector = 0;
220 SetMomentumSmearing();
223 SetHadronCorrection();
224 SetSamplingFraction();
227 SetParametersForBgSubtraction();
230 void AliEMCALJetFinder::SetParametersForBgSubtraction
231 (Int_t mode, Float_t minMove, Float_t maxMove, Float_t precBg)
233 // see file /home/pavlinov/cosmic/pythia/jetFinderParamData.inc
234 // at WSU Linux cluster - 11-feb-2002
235 // These parameters must be tuned more carefull !!!
242 //____________________________________________________________________________
243 AliEMCALJetFinder::~AliEMCALJetFinder()
254 # define jet_finder_ua1 jet_finder_ua1_
256 # define type_of_call
259 # define jet_finder_ua1 JET_FINDER_UA1
261 # define type_of_call _stdcall
264 extern "C" void type_of_call
265 jet_finder_ua1(Int_t& ncell, Int_t& ncell_tot,
266 Float_t etc[30000], Float_t etac[30000],
268 Float_t& min_move, Float_t& max_move, Int_t& mode,
269 Float_t& prec_bg, Int_t& ierror);
271 extern "C" void type_of_call hf1(Int_t& id, Float_t& x, Float_t& wgt);
274 void AliEMCALJetFinder::Init()
277 // Geometry and I/O initialization
281 // Get geometry parameters from EMCAL
285 AliEMCAL* pEMCAL = (AliEMCAL*) gAlice->GetModule("EMCAL");
286 AliEMCALGeometry* geom =
287 AliEMCALGeometry::GetInstance(pEMCAL->GetTitle(), "");
288 fNbinEta = geom->GetNZ();
289 fNbinPhi = geom->GetNPhi();
290 fPhiMin = geom->GetArm1PhiMin()*TMath::Pi()/180.;
291 fPhiMax = geom->GetArm1PhiMax()*TMath::Pi()/180.;
292 fEtaMin = geom->GetArm1EtaMin();
293 fEtaMax = geom->GetArm1EtaMax();
294 fDphi = (fPhiMax-fPhiMin)/fNbinPhi;
295 fDeta = (fEtaMax-fEtaMin)/fNbinEta;
296 fNtot = fNbinPhi*fNbinEta;
298 SetCellSize(fDeta, fDphi);
301 if (fOutFileName) fOutFile = new TFile(fOutFileName, "recreate");
304 void AliEMCALJetFinder::Find(Int_t ncell, Int_t ncell_tot, Float_t etc[30000],
305 Float_t etac[30000], Float_t phic[30000],
306 Float_t min_move, Float_t max_move, Int_t mode,
307 Float_t prec_bg, Int_t ierror)
309 // Wrapper for fortran coded jet finder
310 // Full argument list
311 jet_finder_ua1(ncell, ncell_tot, etc, etac, phic,
312 min_move, max_move, mode, prec_bg, ierror);
313 // Write result to output
314 if(fWrite) WriteJets();
318 void AliEMCALJetFinder::Find()
320 // Wrapper for fortran coded jet finder using member data for
323 Float_t min_move = fMinMove;
324 Float_t max_move = fMaxMove;
326 Float_t prec_bg = fPrecBg;
329 ResetJets(); // 4-feb-2002 by PAI
331 jet_finder_ua1(fNcell, fNtot, fEtCell, fEtaCell, fPhiCell,
332 min_move, max_move, mode, prec_bg, ierror);
334 // Write result to output
335 Int_t njet = Njets();
337 for (Int_t nj=0; nj<njet; nj++)
340 fJetT[nj] = new AliEMCALJet(JetEnergy(nj),
345 FindTracksInJetCone();
346 if(fWrite) WriteJets();
350 Int_t AliEMCALJetFinder::Njets()
352 // Get number of reconstructed jets
353 return EMCALJETS.njet;
356 Float_t AliEMCALJetFinder::JetEnergy(Int_t i)
358 // Get reconstructed jet energy
359 return EMCALJETS.etj[i];
362 Float_t AliEMCALJetFinder::JetPhiL(Int_t i)
364 // Get reconstructed jet phi from leading particle
365 return EMCALJETS.phij[0][i];
368 Float_t AliEMCALJetFinder::JetPhiW(Int_t i)
370 // Get reconstructed jet phi from weighting
371 return EMCALJETS.phij[1][i];
374 Float_t AliEMCALJetFinder::JetEtaL(Int_t i)
376 // Get reconstructed jet eta from leading particles
377 return EMCALJETS.etaj[0][i];
381 Float_t AliEMCALJetFinder::JetEtaW(Int_t i)
383 // Get reconstructed jet eta from weighting
384 return EMCALJETS.etaj[1][i];
387 void AliEMCALJetFinder::SetCellSize(Float_t eta, Float_t phi)
389 // Set grid cell size
390 EMCALCELLGEO.etaCellSize = eta;
391 EMCALCELLGEO.phiCellSize = phi;
394 void AliEMCALJetFinder::SetConeRadius(Float_t par)
396 // Set jet cone radius
397 EMCALJETPARAM.coneRad = par;
401 void AliEMCALJetFinder::SetEtSeed(Float_t par)
403 // Set et cut for seeds
404 EMCALJETPARAM.etSeed = par;
408 void AliEMCALJetFinder::SetMinJetEt(Float_t par)
410 // Set minimum jet et
411 EMCALJETPARAM.ejMin = par;
415 void AliEMCALJetFinder::SetMinCellEt(Float_t par)
417 // Set et cut per cell
418 EMCALJETPARAM.etMin = par;
422 void AliEMCALJetFinder::SetPtCut(Float_t par)
424 // Set pT cut on charged tracks
429 void AliEMCALJetFinder::Test()
432 // Test the finder call
434 const Int_t nmax = 30000;
436 Int_t ncell_tot = 100;
441 Float_t min_move = 0;
442 Float_t max_move = 0;
448 Find(ncell, ncell_tot, etc, etac, phic,
449 min_move, max_move, mode, prec_bg, ierror);
457 void AliEMCALJetFinder::AddJet(const AliEMCALJet& jet)
462 TClonesArray &lrawcl = *fJets;
463 new(lrawcl[fNjets++]) AliEMCALJet(jet);
466 void AliEMCALJetFinder::ResetJets()
475 void AliEMCALJetFinder::WriteJets()
478 // Add all jets to the list
480 const Int_t kBufferSize = 4000;
481 const char* file = 0;
483 Int_t njet = Njets();
485 for (Int_t nj = 0; nj < njet; nj++)
494 // output written to input file
496 AliEMCAL* pEMCAL = (AliEMCAL* )gAlice->GetModule("EMCAL");
497 TTree* pK = gAlice->TreeK();
498 file = (pK->GetCurrentFile())->GetName();
500 printf("Make Branch - TreeR address %p %p\n",gAlice->TreeR(), pEMCAL);
501 if (fJets && gAlice->TreeR()) {
502 pEMCAL->MakeBranchInTree(gAlice->TreeR(),
508 Int_t nev = gAlice->GetHeader()->GetEvent();
509 gAlice->TreeR()->Fill();
511 sprintf(hname,"TreeR%d", nev);
512 gAlice->TreeR()->Write(hname);
513 gAlice->TreeR()->Reset();
516 // Output written to user specified output file
518 TTree* pK = gAlice->TreeK();
519 fInFile = pK->GetCurrentFile();
523 sprintf(hname,"TreeR%d", fEvent);
524 TTree* treeJ = new TTree(hname, "EMCALJets");
525 treeJ->Branch("EMCALJets", &fJets, kBufferSize);
533 void AliEMCALJetFinder::BookLego()
536 // Book histo for discretisation
540 // Don't add histos to the current directory
541 if(fDebug) printf("\n AliEMCALJetFinder::BookLego() \n");
543 TH2::AddDirectory(0);
544 TH1::AddDirectory(0);
548 fLego = new TH2F("legoH","eta-phi",
549 fNbinEta, fEtaMin, fEtaMax,
550 fNbinPhi, fPhiMin, fPhiMax);
553 fLegoB = new TH2F("legoB","eta-phi for BG event",
554 fNbinEta, fEtaMin, fEtaMax,
555 fNbinPhi, fPhiMin, fPhiMax);
558 fhLegoTracks = new TH2F("hLegoTracks","eta-phi for Tracks",
559 fNbinEta, fEtaMin, fEtaMax, fNbinPhi, fPhiMin, fPhiMax);
561 fhLegoEMCAL = new TH2F("hLegoEMCAL","eta-phi for EMCAL",
562 fNbinEta, fEtaMin, fEtaMax, fNbinPhi, fPhiMin, fPhiMax);
563 // Hadron correction map
564 fhLegoHadrCorr = new TH2F("hLegoHadrCorr","eta-phi for Hadron. Correction",
565 fNbinEta, fEtaMin, fEtaMax, fNbinPhi, fPhiMin, fPhiMax);
566 // Hists. for tuning jet finder
567 fhEff = new TH2F("hEff","#epsilon vs momentum ", 100,0.,20., 50,0.5,1.);
571 for(Int_t i=1; i<=1000; i++) eTmp[i] = 0.1*i; // step 100 mev
572 for(Int_t i=1001; i<=1100; i++) eTmp[i] = eTmp[1000] + 1.0*(i-1000); // step 1GeV
574 fhCellEt = new TH1F("hCellEt","Cell E_{T} from fLego",
575 eTmp.GetSize()-1, eTmp.GetArray());
576 fhCellEMCALEt = new TH1F("hCellEMCALEt","Cell E_{T} for EMCAL itself",
577 eTmp.GetSize()-1, eTmp.GetArray());
578 fhTrackPt = new TH1F("hTrackPt","Ch.particles P_{T} ",
579 eTmp.GetSize()-1, eTmp.GetArray());
580 fhTrackPtBcut = new TH1F("hTrackPtBcut","Ch.particles P_{T} + magnetic field cut",
581 eTmp.GetSize()-1, eTmp.GetArray());
583 fhChPartMultInTpc = new TH1F("hChPartMultInTpc",
584 "Charge partilcle multiplicity in |%eta|<0.9", 2000, 0, 20000);
586 //! first canvas for drawing
587 fHistsList=AliEMCALJetMicroDst::MoveHistsToList("Hists from AliEMCALJetFinder", kTRUE);
590 void AliEMCALJetFinder::DumpLego()
593 // Dump lego histo into array
596 TAxis* Xaxis = fLego->GetXaxis();
597 TAxis* Yaxis = fLego->GetYaxis();
598 // fhCellEt->Clear();
600 for (Int_t i = 1; i <= fNbinEta; i++) {
601 for (Int_t j = 1; j <= fNbinPhi; j++) {
602 e = fLego->GetBinContent(i,j);
604 Float_t eta = Xaxis->GetBinCenter(i);
605 Float_t phi = Yaxis->GetBinCenter(j);
607 fEtaCell[fNcell] = eta;
608 fPhiCell[fNcell] = phi;
613 eH = fhLegoEMCAL->GetBinContent(i,j);
614 if(eH > 0.0) fhCellEMCALEt->Fill(eH);
621 void AliEMCALJetFinder::ResetMap()
624 // Reset eta-phi array
626 for (Int_t i=0; i<30000; i++)
635 void AliEMCALJetFinder::FillFromTracks(Int_t flag, Int_t ich)
638 // Fill Cells with track information
641 printf("\n AliEMCALJetFinder::FillFromTracks(%i,%i) ",flag,ich);
646 if (!fLego) BookLego();
648 if (flag == 0) fLego->Reset();
650 // Access particle information
651 Int_t npart = (gAlice->GetHeader())->GetNprimary();
652 Int_t ntr = (gAlice->GetHeader())->GetNtrack();
653 printf(" : #primary particles %i # tracks %i \n", npart, ntr);
658 // 1: selected for jet finding
661 if (fTrackList) delete[] fTrackList;
662 if (fPtT) delete[] fPtT;
663 if (fEtaT) delete[] fEtaT;
664 if (fPhiT) delete[] fPhiT;
665 if (fPdgT) delete[] fPdgT;
667 fTrackList = new Int_t [npart];
668 fPtT = new Float_t[npart];
669 fEtaT = new Float_t[npart];
670 fPhiT = new Float_t[npart];
671 fPdgT = new Int_t[npart];
675 Float_t chTmp=0.0; // charge of current particle
678 // this is for Pythia ??
679 for (Int_t part = 0; part < npart; part++) {
680 TParticle *MPart = gAlice->Particle(part);
681 Int_t mpart = MPart->GetPdgCode();
682 Int_t child1 = MPart->GetFirstDaughter();
683 Float_t pT = MPart->Pt();
684 Float_t p = MPart->P();
685 Float_t phi = MPart->Phi();
687 if(pT > 0.001) eta = MPart->Eta();
688 Float_t theta = MPart->Theta();
690 printf("ind %7i part %7i -> child1 %5i child2 %5i Status %5i\n",
691 part, mpart, child1, MPart->GetLastDaughter(), MPart->GetStatusCode());
695 if (part == 6 || part == 7)
697 printf("\n Simulated Jet (pt, eta, phi): %d %f %f %f\n",
698 part-5, pT, eta, phi);
703 // printf("\n Simulated Jet (pt, eta, phi): %d %d %f %f %f",
704 // part, mpart, pT, eta, phi);
707 fTrackList[part] = 0;
708 fPtT[part] = pT; // must be change after correction for resolution !!!
714 if (part < 2) continue;
716 // move to fLego->Fill because hadron correction must apply
717 // if particle hit to EMCAL - 11-feb-2002
718 // if (pT == 0 || pT < fPtCut) continue;
719 TParticlePDG* pdgP = 0;
720 // charged or neutral
721 pdgP = MPart->GetPDG();
722 chTmp = pdgP->Charge() / 3.; // 13-feb-2001!!
728 if (mpart != kNeutron &&
729 mpart != kNeutronBar &&
730 mpart != kK0Long) continue;
735 if (TMath::Abs(mpart) <= 6 ||
737 mpart == 92) continue;
739 if (TMath::Abs(eta)<=0.9) fNChTpc++;
741 if (child1 >= 0 && child1 < npart) continue;
743 if (TMath::Abs(eta) > 0.7) continue;
744 // Initial phi may be out of acceptance but track may
745 // hit two the acceptance - see variable curls
746 if (phi*180./TMath::Pi() > 120.) continue;
749 printf("\n=>nsel:%5d mpart %5d child1 %5d eta %6.2f phi %6.2f pT %6.2f ch %3.0f ",
750 part, mpart, child1, eta, phi, pT, chTmp);
753 // Momentum smearing goes here ...
757 if (fSmear && TMath::Abs(chTmp)) {
758 pw = AliEMCALFast::SmearMomentum(1,p);
759 // p changed - take into account when calculate pT,
762 if(fDebug >= 4) printf("\n Smearing : p %8.4f change to %8.4f ", p, pw);
766 // Tracking Efficiency and TPC acceptance goes here ...
768 if (fEffic && TMath::Abs(chTmp)) {
769 // eff = AliEMCALFast::Efficiency(1,p);
770 eff = 0.95; // for testing 25-feb-2002
771 if(fhEff) fhEff->Fill(p, eff);
772 if (AliEMCALFast::RandomReject(eff)) {
773 if(fDebug >= 5) printf(" reject due to unefficiency ");
778 // Correction of Hadronic Energy goes here ...
781 // phi propagation for hadronic correction
783 Bool_t curls = kFALSE; // hit two the EMCAL (no curl)
784 Float_t phiHC=0.0, dpH=0.0, dphi=0.0, eTdpH=0;
785 if(TMath::Abs(chTmp)) {
786 // hadr. correction only for charge particle
787 dphi = PropagatePhi(pT, chTmp, curls);
790 printf("\n Delta phi %f pT %f ", dphi, pT);
791 if (curls) printf("\n !! Track is curling");
793 if(!curls) fhTrackPtBcut->Fill(pT);
795 if (fHCorrection && !curls) {
796 if (!fHadronCorrector)
797 Fatal("AliEMCALJetFinder",
798 "Hadronic energy correction required but not defined !");
800 dpH = fHadronCorrector->GetEnergy(p, eta, 7);
801 eTdpH = dpH*TMath::Sin(theta);
803 if (fDebug >= 7) printf(" phi %f phiHC %f eTcorr %f\n",
804 phi, phiHC, -eTdpH); // correction is negative
805 fLego->Fill(eta, phiHC, -eTdpH);
806 fhLegoHadrCorr->Fill(eta, phiHC, eTdpH);
810 // More to do ? Just think about it !
813 if (phi*180./TMath::Pi() > 120.) continue;
815 if(TMath::Abs(chTmp) ) { // charge particle
816 if (pT > fPtCut && !curls) {
817 if (fDebug >= 8) printf("Charge : fLego->Fill(%5.2f, %5.2f, %6.2f)\n",
819 fLego->Fill(eta, phi, pT);
820 fhLegoTracks->Fill(eta, phi, pT); // 20-feb for checking
821 fTrackList[part] = 1;
824 } else if(ich==0 && fK0N) {
825 // case of n, nbar and K0L
826 if (fDebug >= 9) printf("Neutral : fLego->Fill(%5.2f, %5.2f, %6.2f)\n",
828 fLego->Fill(eta, phi, pT);
829 fTrackList[part] = 1;
837 void AliEMCALJetFinder::FillFromHits(Int_t flag)
840 // Fill Cells with hit information
844 printf("\n AliEMCALJetFinder::FillFromHits(%i)\n",flag);
848 if (!fLego) BookLego();
849 // Reset eta-phi maps if needed
850 if (flag == 0) { // default behavior
852 fhLegoTracks->Reset();
853 fhLegoEMCAL->Reset();
854 fhLegoHadrCorr->Reset();
856 // Initialize from background event if available
858 // Access hit information
859 AliEMCAL* pEMCAL = (AliEMCAL*) gAlice->GetModule("EMCAL");
861 TTree *treeH = gAlice->TreeH();
862 Int_t ntracks = (Int_t) treeH->GetEntries();
869 for (Int_t track=0; track<ntracks;track++) {
871 nbytes += treeH->GetEvent(track);
875 for(AliEMCALHit* mHit=(AliEMCALHit*) pEMCAL->FirstHit(-1);
877 mHit=(AliEMCALHit*) pEMCAL->NextHit())
879 Float_t x = mHit->X(); // x-pos of hit
880 Float_t y = mHit->Y(); // y-pos
881 Float_t z = mHit->Z(); // z-pos
882 Float_t eloss = mHit->GetEnergy(); // deposited energy
884 Float_t r = TMath::Sqrt(x*x+y*y);
885 Float_t theta = TMath::ATan2(r,z);
886 Float_t eta = -TMath::Log(TMath::Tan(theta/2.));
887 Float_t phi = TMath::ATan2(y,x);
889 if (fDebug >= 11) printf("\n Hit %f %f %f %f", x, y, z, eloss);
891 etH = fSamplingF*eloss*TMath::Sin(theta);
892 fLego->Fill(eta, phi, etH);
893 // fhLegoEMCAL->Fill(eta, phi, etH);
896 // copy content of fLego to fhLegoEMCAL (fLego and fhLegoEMCAL are identical)
897 for(Int_t i=0; i<fLego->GetSize(); i++) (*fhLegoEMCAL)[i] = (*fLego)[i];
901 void AliEMCALJetFinder::FillFromDigits(Int_t flag)
904 // Fill Cells with digit information
909 if (!fLego) BookLego();
910 if (flag == 0) fLego->Reset();
917 TClonesArray* digs = new TClonesArray("AliEMCALDigit", 10000);
918 TTree *treeD = gAlice->TreeD();
919 TBranchElement* branchDg = (TBranchElement*)
920 treeD->GetBranch("EMCAL");
922 if (!branchDg) Fatal("AliEMCALJetFinder",
923 "Reading digits requested but no digits in file !");
925 branchDg->SetAddress(&digs);
926 Int_t nent = (Int_t) branchDg->GetEntries();
930 AliEMCALDigitizer* digr = new AliEMCALDigitizer();
931 TBranchElement* branchDr = (TBranchElement*)
932 treeD->GetBranch("AliEMCALDigitizer");
933 branchDr->SetAddress(&digr);
936 nbytes += branchDg->GetEntry(0);
937 nbytes += branchDr->GetEntry(0);
939 // Get digitizer parameters
940 Float_t towerADCped = digr->GetTowerpedestal();
941 Float_t towerADCcha = digr->GetTowerchannel();
942 Float_t preshoADCped = digr->GetPreShopedestal();
943 Float_t preshoADCcha = digr->GetPreShochannel();
945 AliEMCAL* pEMCAL = (AliEMCAL*) gAlice->GetModule("EMCAL");
946 AliEMCALGeometry* geom =
947 AliEMCALGeometry::GetInstance(pEMCAL->GetTitle(), "");
950 Int_t ndig = digs->GetEntries();
951 printf("\n Number of Digits: %d %d\n", ndig, nent);
952 printf("\n Parameters: %f %f %f %f\n",
953 towerADCped, towerADCcha, preshoADCped, preshoADCcha );
954 printf("\n Geometry: %d %d\n", geom->GetNEta(), geom->GetNPhi());
961 while ((sdg = (AliEMCALDigit*)(next())))
965 if (sdg->GetId() > (geom->GetNZ() * geom->GetNPhi()))
967 pedestal = preshoADCped;
968 channel = preshoADCcha;
970 pedestal = towerADCped;
971 channel = towerADCcha;
974 Float_t eta = sdg->GetEta();
975 Float_t phi = sdg->GetPhi() * TMath::Pi()/180.;
976 Float_t amp = (Float_t) (channel*(sdg->GetAmp())-pedestal);
978 if (fDebug > 1) printf("\n Digit: eta %8.3f phi %8.3f amp %8.3f %8d",
979 eta, phi, amp, sdg->GetAmp());
981 fLego->Fill(eta, phi, fSamplingF*amp);
989 void AliEMCALJetFinder::FillFromHitFlaggedTracks(Int_t flag)
992 // Fill Cells with hit information
997 if (!fLego) BookLego();
999 if (flag == 0) fLego->Reset();
1001 // Flag charged tracks passing through TPC which
1002 // are associated to EMCAL Hits
1003 BuildTrackFlagTable();
1006 // Access particle information
1007 TTree *treeK = gAlice->TreeK();
1008 Int_t ntracks = (Int_t) treeK->GetEntries();
1010 if (fPtT) delete[] fPtT;
1011 if (fEtaT) delete[] fEtaT;
1012 if (fPhiT) delete[] fPhiT;
1013 if (fPdgT) delete[] fPdgT;
1015 fPtT = new Float_t[ntracks];
1016 fEtaT = new Float_t[ntracks];
1017 fPhiT = new Float_t[ntracks];
1018 fPdgT = new Int_t[ntracks];
1023 for (Int_t track = 0; track < ntracks; track++) {
1024 TParticle *MPart = gAlice->Particle(track);
1025 Float_t pT = MPart->Pt();
1026 Float_t phi = MPart->Phi();
1027 Float_t eta = MPart->Eta();
1029 if(fTrackList[track]) {
1033 fPdgT[track] = MPart->GetPdgCode();
1035 if (track < 2) continue; //Colliding particles?
1036 if (pT == 0 || pT < fPtCut) continue;
1038 fLego->Fill(eta, phi, pT);
1044 void AliEMCALJetFinder::FillFromParticles()
1046 // 26-feb-2002 PAI - for checking all chain
1047 // Work on particles level; accept all particle (not neutrino )
1049 Double_t PX=0, PY=0, PZ=0, E=0; // checking conservation law
1053 if (!fLego) BookLego();
1056 // Access particles information
1057 Int_t npart = (gAlice->GetHeader())->GetNprimary();
1058 if (fDebug >= 2 || npart<=0) {
1059 printf(" AliEMCALJetFinder::FillFromParticles : npart %i\n", npart);
1060 if(npart<=0) return;
1064 RearrangeParticlesMemory(npart);
1066 // Go through the particles
1067 Int_t mpart, child1, child2, geantPdg;
1068 Float_t pT, phi, eta, e=0, px=0, py=0, pz=0;
1070 for (Int_t part = 0; part < npart; part++) {
1072 fTrackList[part] = 0;
1074 MPart = gAlice->Particle(part);
1075 mpart = MPart->GetPdgCode();
1076 child1 = MPart->GetFirstDaughter();
1077 child2 = MPart->GetLastDaughter();
1085 e = MPart->Energy();
1087 // see pyedit in Pythia's text
1089 if (IsThisPartonsOrDiQuark(mpart)) continue;
1090 printf("%5i: %5i(%2i) px %5.1f py %5.1f pz %6.1f e %6.1f childs %5i,%5i \n",
1091 part, mpart, geantPdg, px, py, pz, e, child1, child2);
1093 // exclude partons (21 - gluon, 92 - string)
1096 // exclude neutrinous also ??
1097 if (fDebug >= 11 && pT>0.01)
1098 printf("\n part:%5d mpart %5d eta %9.2f phi %9.2f pT %9.2f ",
1099 part, mpart, eta, phi, pT);
1104 fPdgT[part] = mpart;
1107 if (child1 >= 0 && child1 < npart) continue;
1109 // printf("%4i -> %5i(%3i) px %6.1f py %6.1f pz %7.1f e %8.2f child1 %5i %s\n",
1110 // part, mpart, geantPdg, px, py, pz, e, child1, name.Data());
1117 if (TMath::Abs(eta) <= 0.9) fNChTpc++;
1119 if (TMath::Abs(eta) > 0.7) continue;
1120 if (phi*180./TMath::Pi() > 120.) continue;
1122 if(fK0N==0 ) { // exclude neutral hadrons
1123 if (mpart == kNeutron || mpart == kNeutronBar || mpart == kK0Long) continue;
1125 fTrackList[part] = 1;
1126 fLego->Fill(eta, phi, pT);
1129 printf("\n PX %8.2f PY %8.2f PZ %8.2f E %8.2f \n",
1132 if(fhChPartMultInTpc) fhChPartMultInTpc->Fill(fNChTpc);
1135 void AliEMCALJetFinder::FillFromPartons()
1137 // function under construction - 13-feb-2002 PAI
1140 printf("\n AliEMCALJetFinder::FillFromPartons()\n");
1144 if (!fLego) BookLego();
1147 // Access particle information
1148 Int_t npart = (gAlice->GetHeader())->GetNprimary();
1149 if (fDebug >= 2 || npart<=0)
1150 printf("\n AliEMCALJetFinder::FillFromPartons : npart %i\n", npart);
1151 fNt = 0; // for FindTracksInJetCone
1154 // Go through the partons
1156 for (Int_t part = 8; part < npart; part++) {
1157 TParticle *MPart = gAlice->Particle(part);
1158 Int_t mpart = MPart->GetPdgCode();
1159 // Int_t child1 = MPart->GetFirstDaughter();
1160 Float_t pT = MPart->Pt();
1161 // Float_t p = MPart->P();
1162 Float_t phi = MPart->Phi();
1163 Float_t eta = MPart->Eta();
1164 // Float_t theta = MPart->Theta();
1165 statusCode = MPart->GetStatusCode();
1167 // accept partons (21 - gluon, 92 - string)
1168 if (!(TMath::Abs(mpart) <= 6 || mpart == 21 ||mpart == 92)) continue;
1169 if (fDebug > 1 && pT>0.01)
1170 printf("\n part:%5d mpart %5d status %5d eta %8.2f phi %8.2f pT %8.2f ",
1171 part, mpart, statusCode, eta, phi, pT);
1172 // if (fDebug >= 3) MPart->Print();
1173 // accept partons before fragmentation - p.57 in Pythia manual
1174 // if(statusCode != 1) continue;
1176 if (TMath::Abs(eta) > 0.7) continue;
1177 if (phi*180./TMath::Pi() > 120.) continue;
1179 // if (child1 >= 0 && child1 < npart) continue;
1182 fLego->Fill(eta, phi, pT);
1188 void AliEMCALJetFinder::BuildTrackFlagTable() {
1190 // Method to generate a lookup table for TreeK particles
1191 // which are linked to hits in the EMCAL
1193 // --Author: J.L. Klay
1195 // Access hit information
1196 AliEMCAL* pEMCAL = (AliEMCAL*) gAlice->GetModule("EMCAL");
1198 TTree *TK = gAlice->TreeK(); // Get the number of entries in the kine tree
1199 Int_t nKTrks = (Int_t) TK->GetEntries(); // (Number of particles created somewhere)
1201 if(fTrackList) delete[] fTrackList; //Make sure we get rid of the old one
1202 fTrackList = new Int_t[nKTrks]; //before generating a new one
1204 for (Int_t i = 0; i < nKTrks; i++) { //Initialize members to 0
1208 TTree *treeH = gAlice->TreeH();
1209 Int_t ntracks = (Int_t) treeH->GetEntries();
1215 for (Int_t track=0; track<ntracks;track++) {
1216 gAlice->ResetHits();
1217 nbytes += treeH->GetEvent(track);
1223 for(AliEMCALHit* mHit=(AliEMCALHit*) pEMCAL->FirstHit(-1);
1225 mHit=(AliEMCALHit*) pEMCAL->NextHit())
1227 Int_t iTrk = mHit->Track(); // track number
1228 Int_t idprim = mHit->GetPrimary(); // primary particle
1230 //Determine the origin point of this particle - it made a hit in the EMCAL
1231 TParticle *trkPart = gAlice->Particle(iTrk);
1232 TParticlePDG *trkPdg = trkPart->GetPDG();
1233 Int_t trkCode = trkPart->GetPdgCode();
1235 if (trkCode < 10000) { //Big Ions cause problems for
1236 trkChg = trkPdg->Charge(); //this function. Since they aren't
1237 } else { //likely to make it very far, set
1238 trkChg = 0.0; //their charge to 0 for the Flag test
1240 Float_t vxTrk = trkPart->Vx();
1241 Float_t vyTrk = trkPart->Vy();
1242 Float_t vrTrk = TMath::Sqrt(vxTrk*vxTrk+vyTrk*vyTrk);
1243 fTrackList[iTrk] = SetTrackFlag(vrTrk,trkCode,trkChg);
1245 //Loop through the ancestry of the EMCAL entrance particles
1246 Int_t ancestor = trkPart->GetFirstMother(); //Get track's Mother
1247 while (ancestor != -1) {
1248 TParticle *ancPart = gAlice->Particle(ancestor); //get particle info on ancestor
1249 TParticlePDG *ancPdg = ancPart->GetPDG();
1250 Int_t ancCode = ancPart->GetPdgCode();
1252 if (ancCode < 10000) {
1253 ancChg = ancPdg->Charge();
1257 Float_t vxAnc = ancPart->Vx();
1258 Float_t vyAnc = ancPart->Vy();
1259 Float_t vrAnc = TMath::Sqrt(vxAnc*vxAnc+vyAnc*vyAnc);
1260 fTrackList[ancestor] = SetTrackFlag(vrAnc,ancCode,ancChg);
1261 ancestor = ancPart->GetFirstMother(); //Get the next ancestor
1264 //Determine the origin point of the primary particle associated with the hit
1265 TParticle *primPart = gAlice->Particle(idprim);
1266 TParticlePDG *primPdg = primPart->GetPDG();
1267 Int_t primCode = primPart->GetPdgCode();
1269 if (primCode < 10000) {
1270 primChg = primPdg->Charge();
1274 Float_t vxPrim = primPart->Vx();
1275 Float_t vyPrim = primPart->Vy();
1276 Float_t vrPrim = TMath::Sqrt(vxPrim*vxPrim+vyPrim*vyPrim);
1277 fTrackList[idprim] = SetTrackFlag(vrPrim,primCode,primChg);
1283 Int_t AliEMCALJetFinder
1284 ::SetTrackFlag(Float_t radius, Int_t code, Double_t charge) {
1290 if (charge == 0) neutral = 1;
1292 if (TMath::Abs(code) <= 6 ||
1294 code == 92) parton = 1;
1296 //It's not a parton, it's charged and it went through the TPC
1297 if (!parton && !neutral && radius <= 84.0) flag = 1;
1304 void AliEMCALJetFinder::SaveBackgroundEvent()
1306 // Saves the eta-phi lego and the tracklist
1310 (*fLegoB) = (*fLegoB) + (*fLego);
1312 printf("\n AliEMCALJetFinder::SaveBackgroundEvent() (fLegoB) %f = %f(fLego) \n",
1313 fLegoB->Integral(), fLego->Integral());
1316 if (fPtB) delete[] fPtB;
1317 if (fEtaB) delete[] fEtaB;
1318 if (fPhiB) delete[] fPhiB;
1319 if (fPdgB) delete[] fPdgB;
1320 if (fTrackListB) delete[] fTrackListB;
1322 fPtB = new Float_t[fNtS];
1323 fEtaB = new Float_t[fNtS];
1324 fPhiB = new Float_t[fNtS];
1325 fPdgB = new Int_t [fNtS];
1326 fTrackListB = new Int_t [fNtS];
1330 for (Int_t i = 0; i < fNt; i++) {
1331 if (!fTrackList[i]) continue;
1332 fPtB [fNtB] = fPtT [i];
1333 fEtaB[fNtB] = fEtaT[i];
1334 fPhiB[fNtB] = fPhiT[i];
1335 fPdgB[fNtB] = fPdgT[i];
1337 fTrackListB[fNtB] = 1;
1341 printf(" fNtB %i => fNtS %i #particles %i \n", fNtB, fNtS, fNt);
1344 void AliEMCALJetFinder::InitFromBackground()
1348 if (fDebug) printf("\n AliEMCALJetFinder::InitFromBackground() ");
1352 (*fLego) = (*fLego) + (*fLegoB);
1354 printf("\n AliEMCALJetFinder::SaveBackgroundEvent() (fLego) %f = %f(fLegoB) \n",
1355 fLego->Integral(), fLegoB->Integral());
1357 printf(" => fLego undefined \n");
1362 void AliEMCALJetFinder::FindTracksInJetCone()
1365 // Build list of tracks inside jet cone
1368 Int_t njet = Njets();
1369 for (Int_t nj = 0; nj < njet; nj++)
1371 Float_t etaj = JetEtaW(nj);
1372 Float_t phij = JetPhiW(nj);
1373 Int_t nT = 0; // number of associated tracks
1375 // Loop over particles in current event
1376 for (Int_t part = 0; part < fNt; part++) {
1377 if (!fTrackList[part]) continue;
1378 Float_t phi = fPhiT[part];
1379 Float_t eta = fEtaT[part];
1380 Float_t dr = TMath::Sqrt((etaj-eta)*(etaj-eta) +
1381 (phij-phi)*(phij-phi));
1382 if (dr < fConeRadius) {
1383 fTrackList[part] = nj+2;
1388 // Same for background event if available
1391 for (Int_t part = 0; part < fNtB; part++) {
1392 Float_t phi = fPhiB[part];
1393 Float_t eta = fEtaB[part];
1394 Float_t dr = TMath::Sqrt((etaj-eta)*(etaj-eta) +
1395 (phij-phi)*(phij-phi));
1396 fTrackListB[part] = 1;
1398 if (dr < fConeRadius) {
1399 fTrackListB[part] = nj+2;
1403 } // Background available ?
1405 Int_t nT0 = nT + nTB;
1407 if (nT0 > 50) nT0 = 50;
1409 Float_t* ptT = new Float_t[nT0];
1410 Float_t* etaT = new Float_t[nT0];
1411 Float_t* phiT = new Float_t[nT0];
1412 Int_t* pdgT = new Int_t[nT0];
1417 for (Int_t part = 0; part < fNt; part++) {
1418 if (fTrackList[part] == nj+2) {
1420 for (j=iT-1; j>=0; j--) {
1421 if (fPtT[part] > ptT[j]) {
1426 for (j=iT-1; j>=index; j--) {
1427 ptT [j+1] = ptT [j];
1428 etaT[j+1] = etaT[j];
1429 phiT[j+1] = phiT[j];
1430 pdgT[j+1] = pdgT[j];
1432 ptT [index] = fPtT [part];
1433 etaT[index] = fEtaT[part];
1434 phiT[index] = fPhiT[part];
1435 pdgT[index] = fPdgT[part];
1437 } // particle associated
1438 if (iT > nT0) break;
1442 for (Int_t part = 0; part < fNtB; part++) {
1443 if (fTrackListB[part] == nj+2) {
1445 for (j=iT-1; j>=0; j--) {
1446 if (fPtB[part] > ptT[j]) {
1452 for (j=iT-1; j>=index; j--) {
1453 ptT [j+1] = ptT [j];
1454 etaT[j+1] = etaT[j];
1455 phiT[j+1] = phiT[j];
1456 pdgT[j+1] = pdgT[j];
1458 ptT [index] = fPtB [part];
1459 etaT[index] = fEtaB[part];
1460 phiT[index] = fPhiB[part];
1461 pdgT[index] = fPdgB[part];
1463 } // particle associated
1464 if (iT > nT0) break;
1466 } // Background available ?
1468 fJetT[nj]->SetTrackList(nT0, ptT, etaT, phiT, pdgT);
1477 Float_t AliEMCALJetFinder::PropagatePhi(Float_t pt, Float_t charge, Bool_t& curls)
1479 // Propagates phi angle to EMCAL radius
1481 static Float_t b = 0.0, rEMCAL = -1.0;
1484 b = gAlice->Field()->SolenoidField();
1485 // Get EMCAL radius in cm
1486 rEMCAL = AliEMCALGeometry::GetInstance()->GetIPDistance();
1487 printf("\nMagnetic field %f rEMCAL %f ", b, rEMCAL);
1496 Float_t rB = 3335.6 * pt / b; // [cm] (case of |charge|=1)
1498 // check if particle is curling below EMCAL
1499 if (2.*rB < rEMCAL) {
1504 // if not calculate delta phi
1505 Float_t phi = TMath::ACos(1.-rEMCAL*rEMCAL/(2.*rB*rB));
1506 dPhi = TMath::ATan2(1.-TMath::Cos(phi), TMath::Sin(phi));
1507 dPhi = -TMath::Sign(dPhi, charge);
1512 void hf1(Int_t& id, Float_t& x, Float_t& wgt)
1514 // dummy for hbook calls
1518 void AliEMCALJetFinder::DrawLego(Char_t *opt)
1521 void AliEMCALJetFinder::DrawLegoEMCAL(Char_t *opt)
1522 {fhLegoEMCAL->Draw(opt);}
1524 void AliEMCALJetFinder::DrawHistsForTuning(Int_t mode)
1526 static TPaveText *varLabel=0;
1528 fC1 = new TCanvas("C1","Hists. for tunning", 0,25,600,800);
1538 fhCellEMCALEt->Draw();
1543 fhTrackPtBcut->SetLineColor(2);
1544 fhTrackPtBcut->Draw("same");
1549 varLabel = new TPaveText(0.05,0.5,0.95,0.95,"NDC");
1550 varLabel->SetTextAlign(12);
1551 varLabel->SetFillColor(19); // see TAttFill
1552 TString tmp(GetTitle());
1553 varLabel->ReadFile(GetFileNameForParameters());
1557 if(mode) { // for saving picture to the file
1558 TString stmp(GetFileNameForParameters());
1559 stmp.ReplaceAll("_Par.txt",".ps");
1560 fC1->Print(stmp.Data());
1564 void AliEMCALJetFinder::PrintParameters(Int_t mode)
1567 if(mode==0) file = stdout; // output to terminal
1569 file = fopen(GetFileNameForParameters(),"w");
1570 if(file==0) file = stdout;
1572 fprintf(file,"==== Filling lego ==== \n");
1573 fprintf(file,"Smearing %6i ", fSmear);
1574 fprintf(file,"Efficiency %6i\n", fEffic);
1575 fprintf(file,"Hadr.Correct. %6i ", fHCorrection);
1576 fprintf(file,"P_{T} Cut of ch.par. %6.2f\n", fPtCut);
1577 fprintf(file,"==== Jet finding ==== \n");
1578 fprintf(file,"Cone radius %6.2f ", fConeRadius);
1579 fprintf(file,"Seed E_{T} %6.1f\n", fEtSeed);
1580 fprintf(file,"Min E_{T} of cell %6.1f ", fMinCellEt);
1581 fprintf(file,"Min E_{T} of jet %6.1f\n", fMinJetEt);
1583 fprintf(file,"==== Bg subtraction ==== \n");
1584 fprintf(file,"BG subtraction %6i ", fMode);
1585 fprintf(file,"Min cone move %6.2f\n", fMinMove);
1586 fprintf(file,"Max cone move %6.2f ", fMaxMove);
1587 fprintf(file,"%% change for BG %6.4f\n", fPrecBg);
1589 fprintf(file,"==== No Bg subtraction ==== \n");
1590 if(file != stdout) fclose(file);
1593 void AliEMCALJetFinder::DrawLegos()
1596 fC1 = new TCanvas("C1","Hists. for tunning", 0,25,600,800);
1600 gStyle->SetOptStat(111111);
1602 Int_t nent1, nent2, nent3, nent4;
1603 Double_t int1, int2, int3, int4;
1604 nent1 = (Int_t)fLego->GetEntries();
1605 int1 = fLego->Integral();
1607 if(int1) fLego->Draw("lego");
1609 nent2 = (Int_t)fhLegoTracks->GetEntries();
1610 int2 = fhLegoTracks->Integral();
1612 if(int2) fhLegoTracks->Draw("lego");
1614 nent3 = (Int_t)fhLegoEMCAL->GetEntries();
1615 int3 = fhLegoEMCAL->Integral();
1617 if(int3) fhLegoEMCAL->Draw("lego");
1619 nent4 = (Int_t)fhLegoHadrCorr->GetEntries();
1620 int4 = fhLegoHadrCorr->Integral();
1622 if(int4) fhLegoHadrCorr->Draw("lego");
1624 // just for checking
1625 printf(" Integrals \n");
1626 printf("lego %10.3f \ntrack %10.3f \nhits %10.3f \nHCorr %10.3f\n-- %10.3f(must be 0)\n",
1627 int1, int2, int3, int4, int1 - (int2 + int3 - int4));
1630 const Char_t* AliEMCALJetFinder::GetFileNameForParameters(Char_t* dir)
1633 if(strlen(dir)) tmp = dir;
1639 void AliEMCALJetFinder::RearrangeParticlesMemory(Int_t npart)
1640 { // See FillFromTracks() - npart must be positive
1641 if (fTrackList) delete[] fTrackList;
1642 if (fPtT) delete[] fPtT;
1643 if (fEtaT) delete[] fEtaT;
1644 if (fPhiT) delete[] fPhiT;
1645 if (fPdgT) delete[] fPdgT;
1648 fTrackList = new Int_t [npart];
1649 fPtT = new Float_t[npart];
1650 fEtaT = new Float_t[npart];
1651 fPhiT = new Float_t[npart];
1652 fPdgT = new Int_t[npart];
1654 printf("AliEMCALJetFinder::RearrangeParticlesMemory : npart = %d\n", npart);
1658 Bool_t AliEMCALJetFinder::IsThisPartonsOrDiQuark(Int_t pdg)
1660 Int_t absPdg = TMath::Abs(pdg);
1661 if(absPdg<=6) return kTRUE; // quarks
1662 if(pdg == 21) return kTRUE; // gluon
1663 if(pdg == 92) return kTRUE; // string
1665 // see p.51 of Pythia Manual
1666 // Not include diquarks with c and b quark - 4-mar-2002
1667 // ud_0,sd_0,su_0; dd_1,ud_1,uu_1; sd_1,su_1,ss_1
1668 static Int_t diquark[9]={2101,3101,3201, 1103,2103,2203, 3103,3203,3303};
1669 for(Int_t i=0; i<9; i++) if(absPdg == diquark[i]) return kTRUE; // diquarks