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.19 2002/02/27 00:46:33 pavlinov
19 Added method FillFromParticles()
21 Revision 1.18 2002/02/21 08:48:59 morsch
22 Correction in FillFromHitFlaggedTrack. (Jennifer Klay)
24 Revision 1.17 2002/02/14 08:52:53 morsch
25 Major updates by Aleksei Pavlinov:
26 FillFromPartons, FillFromTracks, jetfinder configuration.
28 Revision 1.16 2002/02/08 11:43:05 morsch
29 SetOutputFileName(..) allows to specify an output file to which the
30 reconstructed jets are written. If not set output goes to input file.
31 Attention call Init() before processing.
33 Revision 1.15 2002/02/02 08:37:18 morsch
34 Formula for rB corrected.
36 Revision 1.14 2002/02/01 08:55:30 morsch
37 Fill map with Et and pT.
39 Revision 1.13 2002/01/31 09:37:36 morsch
40 Geometry parameters in constructor and call of SetCellSize()
42 Revision 1.12 2002/01/23 13:40:23 morsch
43 Fastidious debug print statement removed.
45 Revision 1.11 2002/01/22 17:25:47 morsch
46 Some corrections for event mixing and bg event handling.
48 Revision 1.10 2002/01/22 10:31:44 morsch
49 Some correction for bg mixing.
51 Revision 1.9 2002/01/21 16:28:42 morsch
54 Revision 1.8 2002/01/21 16:05:31 morsch
55 - different phi-bin for hadron correction
56 - provisions for background mixing.
58 Revision 1.7 2002/01/21 15:47:18 morsch
59 Bending radius correctly in cm.
61 Revision 1.6 2002/01/21 12:53:50 morsch
64 Revision 1.5 2002/01/21 12:47:47 morsch
65 Possibility to include K0long and neutrons.
67 Revision 1.4 2002/01/21 11:03:21 morsch
68 Phi propagation introduced in FillFromTracks.
70 Revision 1.3 2002/01/18 05:07:56 morsch
73 - track selection upon EMCAL information
77 //*-- Authors: Andreas Morsch (CERN)
79 //* Aleksei Pavlinov (WSU)
84 #include <TClonesArray.h>
86 #include <TBranchElement.h>
94 #include <TPaveText.h>
97 #include <TParticle.h>
98 #include <TParticlePDG.h>
99 #include <TPythia6Calls.h>
102 #include "AliEMCALJetFinder.h"
103 #include "AliEMCALFast.h"
104 #include "AliEMCALGeometry.h"
105 #include "AliEMCALHit.h"
106 #include "AliEMCALDigit.h"
107 #include "AliEMCALDigitizer.h"
108 #include "AliEMCALHadronCorrection.h"
109 #include "AliEMCALJetMicroDst.h"
112 #include "AliMagFCM.h"
113 #include "AliEMCAL.h"
114 #include "AliHeader.h"
117 // Interface to FORTRAN
121 ClassImp(AliEMCALJetFinder)
123 //____________________________________________________________________________
124 AliEMCALJetFinder::AliEMCALJetFinder()
126 // Default constructor
143 fHadronCorrector = 0;
151 SetParametersForBgSubtraction();
154 AliEMCALJetFinder::AliEMCALJetFinder(const char* name, const char *title)
158 // Title is used in method GetFileNameForParameters();
160 fJets = new TClonesArray("AliEMCALJet",10000);
162 for (Int_t i = 0; i < 30000; i++)
182 fHadronCorrector = 0;
191 SetMomentumSmearing();
194 SetHadronCorrection();
195 SetSamplingFraction();
198 SetParametersForBgSubtraction();
201 void AliEMCALJetFinder::SetParametersForBgSubtraction
202 (Int_t mode, Float_t minMove, Float_t maxMove, Float_t precBg)
204 // see file /home/pavlinov/cosmic/pythia/jetFinderParamData.inc
205 // at WSU Linux cluster - 11-feb-2002
206 // These parameters must be tuned more carefull !!!
213 //____________________________________________________________________________
214 AliEMCALJetFinder::~AliEMCALJetFinder()
225 # define jet_finder_ua1 jet_finder_ua1_
226 # define sgpdge sgpdge_
228 # define type_of_call
231 # define jet_finder_ua1 J
233 # define type_of_call _stdcall
236 extern "C" void type_of_call
237 jet_finder_ua1(Int_t& ncell, Int_t& ncell_tot,
238 Float_t etc[30000], Float_t etac[30000],
240 Float_t& min_move, Float_t& max_move, Int_t& mode,
241 Float_t& prec_bg, Int_t& ierror);
243 extern "C" void type_of_call hf1(Int_t& id, Float_t& x, Float_t& wgt);
245 extern "C" void type_of_call sgpdge(Int_t &i, Int_t &pdggea);
246 // int pycomp_(int* kf); see $ROOTSYS/include/TPythia6Calls.h
248 void AliEMCALJetFinder::Init()
251 // Geometry and I/O initialization
255 // Get geometry parameters from EMCAL
259 AliEMCAL* pEMCAL = (AliEMCAL*) gAlice->GetModule("EMCAL");
260 AliEMCALGeometry* geom =
261 AliEMCALGeometry::GetInstance(pEMCAL->GetTitle(), "");
262 fNbinEta = geom->GetNZ();
263 fNbinPhi = geom->GetNPhi();
264 fPhiMin = geom->GetArm1PhiMin()*TMath::Pi()/180.;
265 fPhiMax = geom->GetArm1PhiMax()*TMath::Pi()/180.;
266 fEtaMin = geom->GetArm1EtaMin();
267 fEtaMax = geom->GetArm1EtaMax();
268 fDphi = (fPhiMax-fPhiMin)/fNbinEta;
269 fDeta = (fEtaMax-fEtaMin)/fNbinEta;
270 fNtot = fNbinPhi*fNbinEta;
272 SetCellSize(fDeta, fDphi);
275 if (fOutFileName) fOutFile = new TFile(fOutFileName, "recreate");
278 void AliEMCALJetFinder::Find(Int_t ncell, Int_t ncell_tot, Float_t etc[30000],
279 Float_t etac[30000], Float_t phic[30000],
280 Float_t min_move, Float_t max_move, Int_t mode,
281 Float_t prec_bg, Int_t ierror)
283 // Wrapper for fortran coded jet finder
284 // Full argument list
285 jet_finder_ua1(ncell, ncell_tot, etc, etac, phic,
286 min_move, max_move, mode, prec_bg, ierror);
287 // Write result to output
288 if(fWrite) WriteJets();
292 void AliEMCALJetFinder::Find()
294 // Wrapper for fortran coded jet finder using member data for
297 Float_t min_move = fMinMove;
298 Float_t max_move = fMaxMove;
300 Float_t prec_bg = fPrecBg;
303 ResetJets(); // 4-feb-2002 by PAI
305 jet_finder_ua1(fNcell, fNtot, fEtCell, fEtaCell, fPhiCell,
306 min_move, max_move, mode, prec_bg, ierror);
308 // Write result to output
309 Int_t njet = Njets();
311 for (Int_t nj=0; nj<njet; nj++)
314 fJetT[nj] = new AliEMCALJet(JetEnergy(nj),
319 FindTracksInJetCone();
320 if(fWrite) WriteJets();
324 Int_t AliEMCALJetFinder::Njets()
326 // Get number of reconstructed jets
327 return EMCALJETS.njet;
330 Float_t AliEMCALJetFinder::JetEnergy(Int_t i)
332 // Get reconstructed jet energy
333 return EMCALJETS.etj[i];
336 Float_t AliEMCALJetFinder::JetPhiL(Int_t i)
338 // Get reconstructed jet phi from leading particle
339 return EMCALJETS.phij[0][i];
342 Float_t AliEMCALJetFinder::JetPhiW(Int_t i)
344 // Get reconstructed jet phi from weighting
345 return EMCALJETS.phij[1][i];
348 Float_t AliEMCALJetFinder::JetEtaL(Int_t i)
350 // Get reconstructed jet eta from leading particles
351 return EMCALJETS.etaj[0][i];
355 Float_t AliEMCALJetFinder::JetEtaW(Int_t i)
357 // Get reconstructed jet eta from weighting
358 return EMCALJETS.etaj[1][i];
361 void AliEMCALJetFinder::SetCellSize(Float_t eta, Float_t phi)
363 // Set grid cell size
364 EMCALCELLGEO.etaCellSize = eta;
365 EMCALCELLGEO.phiCellSize = phi;
368 void AliEMCALJetFinder::SetConeRadius(Float_t par)
370 // Set jet cone radius
371 EMCALJETPARAM.coneRad = par;
375 void AliEMCALJetFinder::SetEtSeed(Float_t par)
377 // Set et cut for seeds
378 EMCALJETPARAM.etSeed = par;
382 void AliEMCALJetFinder::SetMinJetEt(Float_t par)
384 // Set minimum jet et
385 EMCALJETPARAM.ejMin = par;
389 void AliEMCALJetFinder::SetMinCellEt(Float_t par)
391 // Set et cut per cell
392 EMCALJETPARAM.etMin = par;
396 void AliEMCALJetFinder::SetPtCut(Float_t par)
398 // Set pT cut on charged tracks
403 void AliEMCALJetFinder::Test()
406 // Test the finder call
408 const Int_t nmax = 30000;
410 Int_t ncell_tot = 100;
415 Float_t min_move = 0;
416 Float_t max_move = 0;
422 Find(ncell, ncell_tot, etc, etac, phic,
423 min_move, max_move, mode, prec_bg, ierror);
431 void AliEMCALJetFinder::AddJet(const AliEMCALJet& jet)
436 TClonesArray &lrawcl = *fJets;
437 new(lrawcl[fNjets++]) AliEMCALJet(jet);
440 void AliEMCALJetFinder::ResetJets()
449 void AliEMCALJetFinder::WriteJets()
452 // Add all jets to the list
454 const Int_t kBufferSize = 4000;
455 const char* file = 0;
457 Int_t njet = Njets();
459 for (Int_t nj = 0; nj < njet; nj++)
468 // output written to input file
470 AliEMCAL* pEMCAL = (AliEMCAL* )gAlice->GetModule("EMCAL");
471 TTree* pK = gAlice->TreeK();
472 file = (pK->GetCurrentFile())->GetName();
474 printf("Make Branch - TreeR address %p %p\n",gAlice->TreeR(), pEMCAL);
475 if (fJets && gAlice->TreeR()) {
476 pEMCAL->MakeBranchInTree(gAlice->TreeR(),
482 Int_t nev = gAlice->GetHeader()->GetEvent();
483 gAlice->TreeR()->Fill();
485 sprintf(hname,"TreeR%d", nev);
486 gAlice->TreeR()->Write(hname);
487 gAlice->TreeR()->Reset();
490 // Output written to user specified output file
492 TTree* pK = gAlice->TreeK();
493 fInFile = pK->GetCurrentFile();
497 sprintf(hname,"TreeR%d", fEvent);
498 TTree* treeJ = new TTree(hname, "EMCALJets");
499 treeJ->Branch("EMCALJets", &fJets, kBufferSize);
507 void AliEMCALJetFinder::BookLego()
510 // Book histo for discretisation
514 // Don't add histos to the current directory
515 if(fDebug) printf("\n AliEMCALJetFinder::BookLego() \n");
517 // TH2::AddDirectory(0);
518 // TH1::AddDirectory(0);
522 fLego = new TH2F("legoH","eta-phi",
523 fNbinEta, fEtaMin, fEtaMax,
524 fNbinPhi, fPhiMin, fPhiMax);
527 fLegoB = new TH2F("legoB","eta-phi for BG event",
528 fNbinEta, fEtaMin, fEtaMax,
529 fNbinPhi, fPhiMin, fPhiMax);
532 fhLegoTracks = new TH2F("hLegoTracks","eta-phi for Tracks",
533 fNbinEta, fEtaMin, fEtaMax, fNbinPhi, fPhiMin, fPhiMax);
535 fhLegoEMCAL = new TH2F("hLegoEMCAL","eta-phi for EMCAL",
536 fNbinEta, fEtaMin, fEtaMax, fNbinPhi, fPhiMin, fPhiMax);
537 // Hadron correction map
538 fhLegoHadrCorr = new TH2F("hLegoHadrCorr","eta-phi for Hadron. Correction",
539 fNbinEta, fEtaMin, fEtaMax, fNbinPhi, fPhiMin, fPhiMax);
540 // Hists. for tuning jet finder
541 fhEff = new TH2F("hEff","#epsilon vs momentum ", 100,0.,20., 50,0.5,1.);
545 for(Int_t i=1; i<=1000; i++) eTmp[i] = 0.1*i; // step 100 mev
546 for(Int_t i=1001; i<=1100; i++) eTmp[i] = eTmp[1000] + 1.0*(i-1000); // step 1GeV
548 fhCellEt = new TH1F("hCellEt","Cell E_{T} from fLego",
549 eTmp.GetSize()-1, eTmp.GetArray());
550 fhCellEMCALEt = new TH1F("hCellEMCALEt","Cell E_{T} for EMCAL itself",
551 eTmp.GetSize()-1, eTmp.GetArray());
552 fhTrackPt = new TH1F("hTrackPt","Ch.particles P_{T} ",
553 eTmp.GetSize()-1, eTmp.GetArray());
554 fhTrackPtBcut = new TH1F("hTrackPtBcut","Ch.particles P_{T} + magnetic field cut",
555 eTmp.GetSize()-1, eTmp.GetArray());
557 fhChPartMultInTpc = new TH1F("hChPartMultInTpc",
558 "Charge partilcle multiplicity in |%eta|<0.9", 2000, 0, 20000);
560 //! first canvas for drawing
561 fHistsList=AliEMCALJetMicroDst::MoveHistsToList("Hists from AliEMCALJetFinder", kTRUE);
564 void AliEMCALJetFinder::DumpLego()
567 // Dump lego histo into array
570 TAxis* Xaxis = fLego->GetXaxis();
571 TAxis* Yaxis = fLego->GetYaxis();
572 // fhCellEt->Clear();
574 for (Int_t i = 1; i <= fNbinEta; i++) {
575 for (Int_t j = 1; j <= fNbinPhi; j++) {
576 e = fLego->GetBinContent(i,j);
578 Float_t eta = Xaxis->GetBinCenter(i);
579 Float_t phi = Yaxis->GetBinCenter(j);
581 fEtaCell[fNcell] = eta;
582 fPhiCell[fNcell] = phi;
587 eH = fhLegoEMCAL->GetBinContent(i,j);
588 if(eH > 0.0) fhCellEMCALEt->Fill(eH);
595 void AliEMCALJetFinder::ResetMap()
598 // Reset eta-phi array
600 for (Int_t i=0; i<30000; i++)
609 void AliEMCALJetFinder::FillFromTracks(Int_t flag, Int_t ich)
612 // Fill Cells with track information
615 printf("\n AliEMCALJetFinder::FillFromTracks(%i,%i) ",flag,ich);
620 if (!fLego) BookLego();
622 if (flag == 0) fLego->Reset();
624 // Access particle information
625 Int_t npart = (gAlice->GetHeader())->GetNprimary();
626 Int_t ntr = (gAlice->GetHeader())->GetNtrack();
627 printf(" : #primary particles %i # tracks %i \n", npart, ntr);
632 // 1: selected for jet finding
635 if (fTrackList) delete[] fTrackList;
636 if (fPtT) delete[] fPtT;
637 if (fEtaT) delete[] fEtaT;
638 if (fPhiT) delete[] fPhiT;
640 fTrackList = new Int_t [npart];
641 fPtT = new Float_t[npart];
642 fEtaT = new Float_t[npart];
643 fPhiT = new Float_t[npart];
647 Float_t chTmp=0.0; // charge of current particle
650 // this is for Pythia ??
651 for (Int_t part = 0; part < npart; part++) {
652 TParticle *MPart = gAlice->Particle(part);
653 Int_t mpart = MPart->GetPdgCode();
654 Int_t child1 = MPart->GetFirstDaughter();
655 Float_t pT = MPart->Pt();
656 Float_t p = MPart->P();
657 Float_t phi = MPart->Phi();
659 if(pT > 0.001) eta = MPart->Eta();
660 Float_t theta = MPart->Theta();
662 printf("ind %7i part %7i -> child1 %5i child2 %5i Status %5i\n",
663 part, mpart, child1, MPart->GetLastDaughter(), MPart->GetStatusCode());
667 if (part == 6 || part == 7)
669 printf("\n Simulated Jet (pt, eta, phi): %d %f %f %f\n",
670 part-5, pT, eta, phi);
675 // printf("\n Simulated Jet (pt, eta, phi): %d %d %f %f %f",
676 // part, mpart, pT, eta, phi);
679 fTrackList[part] = 0;
680 fPtT[part] = pT; // must be change after correction for resolution !!!
684 if (part < 2) continue;
686 // move to fLego->Fill because hadron correction must apply
687 // if particle hit to EMCAL - 11-feb-2002
688 // if (pT == 0 || pT < fPtCut) continue;
689 TParticlePDG* pdgP = 0;
690 // charged or neutral
691 pdgP = MPart->GetPDG();
692 chTmp = pdgP->Charge() / 3.; // 13-feb-2001!!
698 if (mpart != kNeutron &&
699 mpart != kNeutronBar &&
700 mpart != kK0Long) continue;
705 if (TMath::Abs(mpart) <= 6 ||
707 mpart == 92) continue;
709 if (TMath::Abs(eta)<=0.9) fNChTpc++;
711 if (child1 >= 0 && child1 < npart) continue;
713 if (TMath::Abs(eta) > 0.7) continue;
714 // Initial phi may be out of acceptance but track may
715 // hit two the acceptance - see variable curls
716 if (phi*180./TMath::Pi() > 120.) continue;
719 printf("\n=>nsel:%5d mpart %5d child1 %5d eta %6.2f phi %6.2f pT %6.2f ch %3.0f ",
720 part, mpart, child1, eta, phi, pT, chTmp);
723 // Momentum smearing goes here ...
727 if (fSmear && TMath::Abs(chTmp)) {
728 pw = AliEMCALFast::SmearMomentum(1,p);
729 // p changed - take into account when calculate pT,
732 if(fDebug >= 4) printf("\n Smearing : p %8.4f change to %8.4f ", p, pw);
736 // Tracking Efficiency and TPC acceptance goes here ...
738 if (fEffic && TMath::Abs(chTmp)) {
739 // eff = AliEMCALFast::Efficiency(1,p);
740 eff = 0.95; // for testing 25-feb-2002
741 if(fhEff) fhEff->Fill(p, eff);
742 if (AliEMCALFast::RandomReject(eff)) {
743 if(fDebug >= 5) printf(" reject due to unefficiency ");
748 // Correction of Hadronic Energy goes here ...
751 // phi propagation for hadronic correction
753 Bool_t curls = kFALSE; // hit two the EMCAL (no curl)
754 Float_t phiHC=0.0, dpH=0.0, dphi=0.0, eTdpH=0;
755 if(TMath::Abs(chTmp)) {
756 // hadr. correction only for charge particle
757 dphi = PropagatePhi(pT, chTmp, curls);
760 printf("\n Delta phi %f pT %f ", dphi, pT);
761 if (curls) printf("\n !! Track is curling");
763 if(!curls) fhTrackPtBcut->Fill(pT);
765 if (fHCorrection && !curls) {
766 if (!fHadronCorrector)
767 Fatal("AliEMCALJetFinder",
768 "Hadronic energy correction required but not defined !");
770 dpH = fHadronCorrector->GetEnergy(p, eta, 7);
771 eTdpH = dpH*TMath::Sin(theta);
773 if (fDebug >= 7) printf(" phi %f phiHC %f eTcorr %f\n",
774 phi, phiHC, -eTdpH); // correction is negative
775 fLego->Fill(eta, phiHC, -eTdpH);
776 fhLegoHadrCorr->Fill(eta, phiHC, eTdpH);
780 // More to do ? Just think about it !
783 if (phi*180./TMath::Pi() > 120.) continue;
785 if(TMath::Abs(chTmp) ) { // charge particle
786 if (pT > fPtCut && !curls) {
787 if (fDebug >= 8) printf("Charge : fLego->Fill(%5.2f, %5.2f, %6.2f)\n",
789 fLego->Fill(eta, phi, pT);
790 fhLegoTracks->Fill(eta, phi, pT); // 20-feb for checking
791 fTrackList[part] = 1;
794 } else if(ich==0 && fK0N) {
795 // case of n, nbar and K0L
796 if (fDebug >= 9) printf("Neutral : fLego->Fill(%5.2f, %5.2f, %6.2f)\n",
798 fLego->Fill(eta, phi, pT);
799 fTrackList[part] = 1;
807 void AliEMCALJetFinder::FillFromHits(Int_t flag)
810 // Fill Cells with hit information
814 printf("\n AliEMCALJetFinder::FillFromHits(%i)\n",flag);
818 if (!fLego) BookLego();
819 // Reset eta-phi maps if needed
820 if (flag == 0) { // default behavior
822 fhLegoTracks->Reset();
823 fhLegoEMCAL->Reset();
824 fhLegoHadrCorr->Reset();
826 // Initialize from background event if available
828 // Access hit information
829 AliEMCAL* pEMCAL = (AliEMCAL*) gAlice->GetModule("EMCAL");
831 TTree *treeH = gAlice->TreeH();
832 Int_t ntracks = (Int_t) treeH->GetEntries();
839 for (Int_t track=0; track<ntracks;track++) {
841 nbytes += treeH->GetEvent(track);
845 for(AliEMCALHit* mHit=(AliEMCALHit*) pEMCAL->FirstHit(-1);
847 mHit=(AliEMCALHit*) pEMCAL->NextHit())
849 Float_t x = mHit->X(); // x-pos of hit
850 Float_t y = mHit->Y(); // y-pos
851 Float_t z = mHit->Z(); // z-pos
852 Float_t eloss = mHit->GetEnergy(); // deposited energy
854 Float_t r = TMath::Sqrt(x*x+y*y);
855 Float_t theta = TMath::ATan2(r,z);
856 Float_t eta = -TMath::Log(TMath::Tan(theta/2.));
857 Float_t phi = TMath::ATan2(y,x);
859 if (fDebug >= 11) printf("\n Hit %f %f %f %f", x, y, z, eloss);
861 etH = fSamplingF*eloss*TMath::Sin(theta);
862 fLego->Fill(eta, phi, etH);
863 // fhLegoEMCAL->Fill(eta, phi, etH);
866 // copy content of fLego to fhLegoEMCAL (fLego and fhLegoEMCAL are identical)
867 for(Int_t i=0; i<fLego->GetSize(); i++) (*fhLegoEMCAL)[i] = (*fLego)[i];
871 void AliEMCALJetFinder::FillFromDigits(Int_t flag)
874 // Fill Cells with digit information
879 if (!fLego) BookLego();
880 if (flag == 0) fLego->Reset();
887 TClonesArray* digs = new TClonesArray("AliEMCALDigit", 10000);
888 TTree *treeD = gAlice->TreeD();
889 TBranchElement* branchDg = (TBranchElement*)
890 treeD->GetBranch("EMCAL");
892 if (!branchDg) Fatal("AliEMCALJetFinder",
893 "Reading digits requested but no digits in file !");
895 branchDg->SetAddress(&digs);
896 Int_t nent = (Int_t) branchDg->GetEntries();
900 AliEMCALDigitizer* digr = new AliEMCALDigitizer();
901 TBranchElement* branchDr = (TBranchElement*)
902 treeD->GetBranch("AliEMCALDigitizer");
903 branchDr->SetAddress(&digr);
906 nbytes += branchDg->GetEntry(0);
907 nbytes += branchDr->GetEntry(0);
909 // Get digitizer parameters
910 Float_t towerADCped = digr->GetTowerpedestal();
911 Float_t towerADCcha = digr->GetTowerchannel();
912 Float_t preshoADCped = digr->GetPreShopedestal();
913 Float_t preshoADCcha = digr->GetPreShochannel();
915 AliEMCAL* pEMCAL = (AliEMCAL*) gAlice->GetModule("EMCAL");
916 AliEMCALGeometry* geom =
917 AliEMCALGeometry::GetInstance(pEMCAL->GetTitle(), "");
920 Int_t ndig = digs->GetEntries();
921 printf("\n Number of Digits: %d %d\n", ndig, nent);
922 printf("\n Parameters: %f %f %f %f\n",
923 towerADCped, towerADCcha, preshoADCped, preshoADCcha );
924 printf("\n Geometry: %d %d\n", geom->GetNEta(), geom->GetNPhi());
931 while ((sdg = (AliEMCALDigit*)(next())))
935 if (sdg->GetId() > (geom->GetNZ() * geom->GetNPhi()))
937 pedestal = preshoADCped;
938 channel = preshoADCcha;
940 pedestal = towerADCped;
941 channel = towerADCcha;
944 Float_t eta = sdg->GetEta();
945 Float_t phi = sdg->GetPhi() * TMath::Pi()/180.;
946 Float_t amp = (Float_t) (channel*(sdg->GetAmp())-pedestal);
948 if (fDebug > 1) printf("\n Digit: eta %8.3f phi %8.3f amp %8.3f %8d",
949 eta, phi, amp, sdg->GetAmp());
951 fLego->Fill(eta, phi, fSamplingF*amp);
959 void AliEMCALJetFinder::FillFromHitFlaggedTracks(Int_t flag)
962 // Fill Cells with hit information
967 if (!fLego) BookLego();
969 if (flag == 0) fLego->Reset();
971 // Flag charged tracks passing through TPC which
972 // are associated to EMCAL Hits
973 BuildTrackFlagTable();
976 // Access particle information
977 TTree *treeK = gAlice->TreeK();
978 Int_t ntracks = (Int_t) treeK->GetEntries();
980 if (fPtT) delete[] fPtT;
981 if (fEtaT) delete[] fEtaT;
982 if (fPhiT) delete[] fPhiT;
984 fPtT = new Float_t[ntracks];
985 fEtaT = new Float_t[ntracks];
986 fPhiT = new Float_t[ntracks];
991 for (Int_t track = 0; track < ntracks; track++) {
992 TParticle *MPart = gAlice->Particle(track);
993 Float_t pT = MPart->Pt();
994 Float_t phi = MPart->Phi();
995 Float_t eta = MPart->Eta();
997 if(fTrackList[track]) {
1002 if (track < 2) continue; //Colliding particles?
1003 if (pT == 0 || pT < fPtCut) continue;
1005 fLego->Fill(eta, phi, pT);
1011 void AliEMCALJetFinder::FillFromParticles()
1013 // 26-feb-2002 PAI - for checking all chain
1014 // Work on particles level; accept all particle (not neutrino )
1016 Double_t PX=0, PY=0, PZ=0, E=0; // checking conservation law
1020 if (!fLego) BookLego();
1023 // Access particles information
1024 Int_t npart = (gAlice->GetHeader())->GetNprimary();
1025 if (fDebug >= 2 || npart<=0) {
1026 printf(" AliEMCALJetFinder::FillFromParticles : npart %i\n", npart);
1027 if(npart<=0) return;
1031 RearrangeParticlesMemory(npart);
1033 // Go through the particles
1034 Int_t mpart, child1, child2, geantPdg;
1035 Float_t pT, phi, eta, e=0, px=0, py=0, pz=0;
1037 for (Int_t part = 0; part < npart; part++) {
1039 fTrackList[part] = 0;
1041 MPart = gAlice->Particle(part);
1042 mpart = MPart->GetPdgCode();
1043 child1 = MPart->GetFirstDaughter();
1044 child2 = MPart->GetLastDaughter();
1052 e = MPart->Energy();
1054 // see pyedit in Pythia's text
1055 sgpdge(mpart, geantPdg);
1056 Int_t kc = pycomp_(&mpart);
1057 TString name = GetPythiaParticleName(mpart);
1058 // printf(" mpart %6.6i;kc %6.6i -> gid %3.3i",mpart,kc,geantPdg);
1059 //printf(" (%s)\n", name.Data());
1060 printf("%5i: %5i(%2i) px %5.1f py %5.1f pz %6.1f e %6.1f childs %5i,%5i %s\n",
1061 part, mpart, geantPdg, px, py, pz, e, child1, child2, name.Data());
1063 // exclude partons (21 - gluon, 92 - string)
1064 if (IsThisPartonsOrDiQuark(mpart)) continue;
1065 // exclude neutrinous also ??
1066 if (fDebug >= 11 && pT>0.01)
1067 printf("\n part:%5d mpart %5d eta %9.2f phi %9.2f pT %9.2f ",
1068 part, mpart, eta, phi, pT);
1075 if (child1 >= 0 && child1 < npart) continue;
1077 // printf("%4i -> %5i(%3i) px %6.1f py %6.1f pz %7.1f e %8.2f child1 %5i %s\n",
1078 // part, mpart, geantPdg, px, py, pz, e, child1, name.Data());
1085 if (TMath::Abs(eta) <= 0.9) fNChTpc++;
1087 if (TMath::Abs(eta) > 0.7) continue;
1088 if (phi*180./TMath::Pi() > 120.) continue;
1090 if(fK0N==0 ) { // exclude neutral hadrons
1091 if (mpart == kNeutron || mpart == kNeutronBar || mpart == kK0Long) continue;
1093 fTrackList[part] = 1;
1094 fLego->Fill(eta, phi, pT);
1097 printf("\n PX %8.2f PY %8.2f PZ %8.2f E %8.2f \n",
1100 if(fhChPartMultInTpc) fhChPartMultInTpc->Fill(fNChTpc);
1103 void AliEMCALJetFinder::FillFromPartons()
1105 // function under construction - 13-feb-2002 PAI
1108 printf("\n AliEMCALJetFinder::FillFromPartons()\n");
1112 if (!fLego) BookLego();
1115 // Access particle information
1116 Int_t npart = (gAlice->GetHeader())->GetNprimary();
1117 if (fDebug >= 2 || npart<=0)
1118 printf("\n AliEMCALJetFinder::FillFromPartons : npart %i\n", npart);
1119 fNt = 0; // for FindTracksInJetCone
1122 // Go through the partons
1124 for (Int_t part = 8; part < npart; part++) {
1125 TParticle *MPart = gAlice->Particle(part);
1126 Int_t mpart = MPart->GetPdgCode();
1127 // Int_t child1 = MPart->GetFirstDaughter();
1128 Float_t pT = MPart->Pt();
1129 // Float_t p = MPart->P();
1130 Float_t phi = MPart->Phi();
1131 Float_t eta = MPart->Eta();
1132 // Float_t theta = MPart->Theta();
1133 statusCode = MPart->GetStatusCode();
1135 // accept partons (21 - gluon, 92 - string)
1136 if (!(TMath::Abs(mpart) <= 6 || mpart == 21 ||mpart == 92)) continue;
1137 if (fDebug > 1 && pT>0.01)
1138 printf("\n part:%5d mpart %5d status %5d eta %8.2f phi %8.2f pT %8.2f ",
1139 part, mpart, statusCode, eta, phi, pT);
1140 // if (fDebug >= 3) MPart->Print();
1141 // accept partons before fragmentation - p.57 in Pythia manual
1142 // if(statusCode != 1) continue;
1144 if (TMath::Abs(eta) > 0.7) continue;
1145 if (phi*180./TMath::Pi() > 120.) continue;
1147 // if (child1 >= 0 && child1 < npart) continue;
1150 fLego->Fill(eta, phi, pT);
1156 void AliEMCALJetFinder::BuildTrackFlagTable() {
1158 // Method to generate a lookup table for TreeK particles
1159 // which are linked to hits in the EMCAL
1161 // --Author: J.L. Klay
1163 // Access hit information
1164 AliEMCAL* pEMCAL = (AliEMCAL*) gAlice->GetModule("EMCAL");
1166 TTree *TK = gAlice->TreeK(); // Get the number of entries in the kine tree
1167 Int_t nKTrks = (Int_t) TK->GetEntries(); // (Number of particles created somewhere)
1169 if(fTrackList) delete[] fTrackList; //Make sure we get rid of the old one
1170 fTrackList = new Int_t[nKTrks]; //before generating a new one
1172 for (Int_t i = 0; i < nKTrks; i++) { //Initialize members to 0
1176 TTree *treeH = gAlice->TreeH();
1177 Int_t ntracks = (Int_t) treeH->GetEntries();
1183 for (Int_t track=0; track<ntracks;track++) {
1184 gAlice->ResetHits();
1185 nbytes += treeH->GetEvent(track);
1191 for(AliEMCALHit* mHit=(AliEMCALHit*) pEMCAL->FirstHit(-1);
1193 mHit=(AliEMCALHit*) pEMCAL->NextHit())
1195 Int_t iTrk = mHit->Track(); // track number
1196 Int_t idprim = mHit->GetPrimary(); // primary particle
1198 //Determine the origin point of this particle - it made a hit in the EMCAL
1199 TParticle *trkPart = gAlice->Particle(iTrk);
1200 TParticlePDG *trkPdg = trkPart->GetPDG();
1201 Int_t trkCode = trkPart->GetPdgCode();
1203 if (trkCode < 10000) { //Big Ions cause problems for
1204 trkChg = trkPdg->Charge(); //this function. Since they aren't
1205 } else { //likely to make it very far, set
1206 trkChg = 0.0; //their charge to 0 for the Flag test
1208 Float_t vxTrk = trkPart->Vx();
1209 Float_t vyTrk = trkPart->Vy();
1210 Float_t vrTrk = TMath::Sqrt(vxTrk*vxTrk+vyTrk*vyTrk);
1211 fTrackList[iTrk] = SetTrackFlag(vrTrk,trkCode,trkChg);
1213 //Loop through the ancestry of the EMCAL entrance particles
1214 Int_t ancestor = trkPart->GetFirstMother(); //Get track's Mother
1215 while (ancestor != -1) {
1216 TParticle *ancPart = gAlice->Particle(ancestor); //get particle info on ancestor
1217 TParticlePDG *ancPdg = ancPart->GetPDG();
1218 Int_t ancCode = ancPart->GetPdgCode();
1220 if (ancCode < 10000) {
1221 ancChg = ancPdg->Charge();
1225 Float_t vxAnc = ancPart->Vx();
1226 Float_t vyAnc = ancPart->Vy();
1227 Float_t vrAnc = TMath::Sqrt(vxAnc*vxAnc+vyAnc*vyAnc);
1228 fTrackList[ancestor] = SetTrackFlag(vrAnc,ancCode,ancChg);
1229 ancestor = ancPart->GetFirstMother(); //Get the next ancestor
1232 //Determine the origin point of the primary particle associated with the hit
1233 TParticle *primPart = gAlice->Particle(idprim);
1234 TParticlePDG *primPdg = primPart->GetPDG();
1235 Int_t primCode = primPart->GetPdgCode();
1237 if (primCode < 10000) {
1238 primChg = primPdg->Charge();
1242 Float_t vxPrim = primPart->Vx();
1243 Float_t vyPrim = primPart->Vy();
1244 Float_t vrPrim = TMath::Sqrt(vxPrim*vxPrim+vyPrim*vyPrim);
1245 fTrackList[idprim] = SetTrackFlag(vrPrim,primCode,primChg);
1251 Int_t AliEMCALJetFinder
1252 ::SetTrackFlag(Float_t radius, Int_t code, Double_t charge) {
1258 if (charge == 0) neutral = 1;
1260 if (TMath::Abs(code) <= 6 ||
1262 code == 92) parton = 1;
1264 //It's not a parton, it's charged and it went through the TPC
1265 if (!parton && !neutral && radius <= 84.0) flag = 1;
1272 void AliEMCALJetFinder::SaveBackgroundEvent()
1274 // Saves the eta-phi lego and the tracklist
1278 (*fLegoB) = (*fLegoB) + (*fLego);
1280 printf("\n AliEMCALJetFinder::SaveBackgroundEvent() (fLegoB) %f = %f(fLego) \n",
1281 fLegoB->Integral(), fLego->Integral());
1284 if (fPtB) delete[] fPtB;
1285 if (fEtaB) delete[] fEtaB;
1286 if (fPhiB) delete[] fPhiB;
1287 if (fTrackListB) delete[] fTrackListB;
1289 fPtB = new Float_t[fNtS];
1290 fEtaB = new Float_t[fNtS];
1291 fPhiB = new Float_t[fNtS];
1292 fTrackListB = new Int_t [fNtS];
1296 for (Int_t i = 0; i < fNt; i++) {
1297 if (!fTrackList[i]) continue;
1298 fPtB [fNtB] = fPtT [i];
1299 fEtaB[fNtB] = fEtaT[i];
1300 fPhiB[fNtB] = fPhiT[i];
1301 fTrackListB[fNtB] = 1;
1305 printf(" fNtB %i => fNtS %i #particles %i \n", fNtB, fNtS, fNt);
1308 void AliEMCALJetFinder::InitFromBackground()
1312 if (fDebug) printf("\n AliEMCALJetFinder::InitFromBackground() ");
1316 (*fLego) = (*fLego) + (*fLegoB);
1318 printf("\n AliEMCALJetFinder::SaveBackgroundEvent() (fLego) %f = %f(fLegoB) \n",
1319 fLego->Integral(), fLegoB->Integral());
1321 printf(" => fLego undefined \n");
1326 void AliEMCALJetFinder::FindTracksInJetCone()
1329 // Build list of tracks inside jet cone
1332 Int_t njet = Njets();
1333 for (Int_t nj = 0; nj < njet; nj++)
1335 Float_t etaj = JetEtaW(nj);
1336 Float_t phij = JetPhiW(nj);
1337 Int_t nT = 0; // number of associated tracks
1339 // Loop over particles in current event
1340 for (Int_t part = 0; part < fNt; part++) {
1341 if (!fTrackList[part]) continue;
1342 Float_t phi = fPhiT[part];
1343 Float_t eta = fEtaT[part];
1344 Float_t dr = TMath::Sqrt((etaj-eta)*(etaj-eta) +
1345 (phij-phi)*(phij-phi));
1346 if (dr < fConeRadius) {
1347 fTrackList[part] = nj+2;
1352 // Same for background event if available
1355 for (Int_t part = 0; part < fNtB; part++) {
1356 Float_t phi = fPhiB[part];
1357 Float_t eta = fEtaB[part];
1358 Float_t dr = TMath::Sqrt((etaj-eta)*(etaj-eta) +
1359 (phij-phi)*(phij-phi));
1360 fTrackListB[part] = 1;
1362 if (dr < fConeRadius) {
1363 fTrackListB[part] = nj+2;
1367 } // Background available ?
1369 Int_t nT0 = nT + nTB;
1371 if (nT0 > 50) nT0 = 50;
1373 Float_t* ptT = new Float_t[nT0];
1374 Float_t* etaT = new Float_t[nT0];
1375 Float_t* phiT = new Float_t[nT0];
1379 for (Int_t part = 0; part < fNt; part++) {
1380 if (fTrackList[part] == nj+2) {
1382 for (j=iT-1; j>=0; j--) {
1383 if (fPtT[part] > ptT[j]) {
1388 for (j=iT-1; j>=index; j--) {
1389 ptT [j+1] = ptT [j];
1390 etaT[j+1] = etaT[j];
1391 phiT[j+1] = phiT[j];
1393 ptT [index] = fPtT [part];
1394 etaT[index] = fEtaT[part];
1395 phiT[index] = fPhiT[part];
1397 } // particle associated
1398 if (iT > nT0) break;
1402 for (Int_t part = 0; part < fNtB; part++) {
1403 if (fTrackListB[part] == nj+2) {
1405 for (j=iT-1; j>=0; j--) {
1406 if (fPtB[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];
1417 ptT [index] = fPtB [part];
1418 etaT[index] = fEtaB[part];
1419 phiT[index] = fPhiB[part];
1421 } // particle associated
1422 if (iT > nT0) break;
1424 } // Background available ?
1426 fJetT[nj]->SetTrackList(nT0, ptT, etaT, phiT);
1433 Float_t AliEMCALJetFinder::PropagatePhi(Float_t pt, Float_t charge, Bool_t& curls)
1435 // Propagates phi angle to EMCAL radius
1437 static Float_t b = 0.0, rEMCAL = -1.0;
1440 b = ((AliMagFCM*) gAlice->Field())->SolenoidField();
1441 // Get EMCAL radius in cm
1442 rEMCAL = AliEMCALGeometry::GetInstance()->GetIPDistance();
1443 printf("\nMagnetic field %f rEMCAL %f ", b, rEMCAL);
1452 Float_t rB = 3335.6 * pt / b; // [cm] (case of |charge|=1)
1454 // check if particle is curling below EMCAL
1455 if (2.*rB < rEMCAL) {
1460 // if not calculate delta phi
1461 Float_t phi = TMath::ACos(1.-rEMCAL*rEMCAL/(2.*rB*rB));
1462 dPhi = TMath::ATan2(1.-TMath::Cos(phi), TMath::Sin(phi));
1463 dPhi = -TMath::Sign(dPhi, charge);
1468 void hf1(Int_t& id, Float_t& x, Float_t& wgt)
1470 // dummy for hbook calls
1474 void AliEMCALJetFinder::DrawLego(Char_t *opt)
1477 void AliEMCALJetFinder::DrawLegoEMCAL(Char_t *opt)
1478 {fhLegoEMCAL->Draw(opt);}
1480 void AliEMCALJetFinder::DrawHistsForTuning(Int_t mode)
1482 static TPaveText *varLabel=0;
1484 fC1 = new TCanvas("C1","Hists. for tunning", 0,25,600,800);
1494 fhCellEMCALEt->Draw();
1499 fhTrackPtBcut->SetLineColor(2);
1500 fhTrackPtBcut->Draw("same");
1505 varLabel = new TPaveText(0.05,0.5,0.95,0.95,"NDC");
1506 varLabel->SetTextAlign(12);
1507 varLabel->SetFillColor(19); // see TAttFill
1508 TString tmp(GetTitle());
1509 varLabel->ReadFile(GetFileNameForParameters());
1513 if(mode) { // for saving picture to the file
1514 TString stmp(GetFileNameForParameters());
1515 stmp.ReplaceAll("_Par.txt",".ps");
1516 fC1->Print(stmp.Data());
1520 void AliEMCALJetFinder::PrintParameters(Int_t mode)
1523 if(mode==0) file = stdout; // output to terminal
1525 file = fopen(GetFileNameForParameters(),"w");
1526 if(file==0) file = stdout;
1528 fprintf(file,"==== Filling lego ==== \n");
1529 fprintf(file,"Smearing %6i ", fSmear);
1530 fprintf(file,"Efficiency %6i\n", fEffic);
1531 fprintf(file,"Hadr.Correct. %6i ", fHCorrection);
1532 fprintf(file,"P_{T} Cut of ch.par. %6.2f\n", fPtCut);
1533 fprintf(file,"==== Jet finding ==== \n");
1534 fprintf(file,"Cone radius %6.2f ", fConeRadius);
1535 fprintf(file,"Seed E_{T} %6.1f\n", fEtSeed);
1536 fprintf(file,"Min E_{T} of cell %6.1f ", fMinCellEt);
1537 fprintf(file,"Min E_{T} of jet %6.1f\n", fMinJetEt);
1539 fprintf(file,"==== Bg subtraction ==== \n");
1540 fprintf(file,"BG subtraction %6i ", fMode);
1541 fprintf(file,"Min cone move %6.2f\n", fMinMove);
1542 fprintf(file,"Max cone move %6.2f ", fMaxMove);
1543 fprintf(file,"%% change for BG %6.4f\n", fPrecBg);
1545 fprintf(file,"==== No Bg subtraction ==== \n");
1546 if(file != stdout) fclose(file);
1549 void AliEMCALJetFinder::DrawLegos()
1552 fC1 = new TCanvas("C1","Hists. for tunning", 0,25,600,800);
1556 gStyle->SetOptStat(111111);
1558 Int_t nent1, nent2, nent3, nent4;
1559 Double_t int1, int2, int3, int4;
1560 nent1 = (Int_t)fLego->GetEntries();
1561 int1 = fLego->Integral();
1563 if(int1) fLego->Draw("lego");
1565 nent2 = (Int_t)fhLegoTracks->GetEntries();
1566 int2 = fhLegoTracks->Integral();
1568 if(int2) fhLegoTracks->Draw("lego");
1570 nent3 = (Int_t)fhLegoEMCAL->GetEntries();
1571 int3 = fhLegoEMCAL->Integral();
1573 if(int3) fhLegoEMCAL->Draw("lego");
1575 nent4 = (Int_t)fhLegoHadrCorr->GetEntries();
1576 int4 = fhLegoHadrCorr->Integral();
1578 if(int4) fhLegoHadrCorr->Draw("lego");
1580 // just for checking
1581 printf(" Integrals \n");
1582 printf("lego %10.3f \ntrack %10.3f \nhits %10.3f \nHCorr %10.3f\n-- %10.3f(must be 0)\n",
1583 int1, int2, int3, int4, int1 - (int2 + int3 - int4));
1586 const Char_t* AliEMCALJetFinder::GetFileNameForParameters(Char_t* dir)
1589 if(strlen(dir)) tmp = dir;
1595 void AliEMCALJetFinder::RearrangeParticlesMemory(Int_t npart)
1596 { // See FillFromTracks() - npart must be positive
1597 if (fTrackList) delete[] fTrackList;
1598 if (fPtT) delete[] fPtT;
1599 if (fEtaT) delete[] fEtaT;
1600 if (fPhiT) delete[] fPhiT;
1603 fTrackList = new Int_t [npart];
1604 fPtT = new Float_t[npart];
1605 fEtaT = new Float_t[npart];
1606 fPhiT = new Float_t[npart];
1608 printf("AliEMCALJetFinder::RearrangeParticlesMemory : npart = %d\n", npart);
1612 Bool_t AliEMCALJetFinder::IsThisPartonsOrDiQuark(Int_t pdg)
1614 Int_t absPdg = TMath::Abs(pdg);
1615 if(absPdg<=6) return kTRUE; // quarks
1616 if(pdg == 21) return kTRUE; // gluon
1617 if(pdg == 92) return kTRUE; // string
1619 // see p.51 of Pythia Manual
1620 // Not include diquarks with c and b quark - 4-mar-2002
1621 // ud_0,sd_0,su_0; dd_1,ud_1,uu_1; sd_1,su_1,ss_1
1622 static Int_t diquark[9]={2101,3101,3201, 1103,2103,2203, 3103,3203,3303};
1623 for(Int_t i=0; i<9; i++) if(absPdg == diquark[i]) return kTRUE; // diquarks
1628 TString &AliEMCALJetFinder::GetPythiaParticleName(Int_t kf)
1629 {// see subroutine PYNAME in PYTHIA
1630 static TString sname;
1632 pyname_(&kf, name, 16);
1633 for(Int_t i=0; i<16; i++){
1634 if(name[i] == ' ') {