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.23 2002/06/27 09:24:26 morsch
19 Uncomment the TH1::AddDirectory statement.
21 Revision 1.22 2002/05/22 13:48:43 morsch
22 Pdg code added to track list.
24 Revision 1.21 2002/04/27 07:43:08 morsch
25 Calculation of fDphi corrected (Renan Cabrera)
27 Revision 1.20 2002/03/12 01:06:23 pavlinov
28 Testin output from generator
30 Revision 1.19 2002/02/27 00:46:33 pavlinov
31 Added method FillFromParticles()
33 Revision 1.18 2002/02/21 08:48:59 morsch
34 Correction in FillFromHitFlaggedTrack. (Jennifer Klay)
36 Revision 1.17 2002/02/14 08:52:53 morsch
37 Major updates by Aleksei Pavlinov:
38 FillFromPartons, FillFromTracks, jetfinder configuration.
40 Revision 1.16 2002/02/08 11:43:05 morsch
41 SetOutputFileName(..) allows to specify an output file to which the
42 reconstructed jets are written. If not set output goes to input file.
43 Attention call Init() before processing.
45 Revision 1.15 2002/02/02 08:37:18 morsch
46 Formula for rB corrected.
48 Revision 1.14 2002/02/01 08:55:30 morsch
49 Fill map with Et and pT.
51 Revision 1.13 2002/01/31 09:37:36 morsch
52 Geometry parameters in constructor and call of SetCellSize()
54 Revision 1.12 2002/01/23 13:40:23 morsch
55 Fastidious debug print statement removed.
57 Revision 1.11 2002/01/22 17:25:47 morsch
58 Some corrections for event mixing and bg event handling.
60 Revision 1.10 2002/01/22 10:31:44 morsch
61 Some correction for bg mixing.
63 Revision 1.9 2002/01/21 16:28:42 morsch
66 Revision 1.8 2002/01/21 16:05:31 morsch
67 - different phi-bin for hadron correction
68 - provisions for background mixing.
70 Revision 1.7 2002/01/21 15:47:18 morsch
71 Bending radius correctly in cm.
73 Revision 1.6 2002/01/21 12:53:50 morsch
76 Revision 1.5 2002/01/21 12:47:47 morsch
77 Possibility to include K0long and neutrons.
79 Revision 1.4 2002/01/21 11:03:21 morsch
80 Phi propagation introduced in FillFromTracks.
82 Revision 1.3 2002/01/18 05:07:56 morsch
85 - track selection upon EMCAL information
89 //*-- Authors: Andreas Morsch (CERN)
91 //* Aleksei Pavlinov (WSU)
96 #include <TClonesArray.h>
98 #include <TBranchElement.h>
106 #include <TPaveText.h>
109 #include <TParticle.h>
110 #include <TParticlePDG.h>
111 #include <TPythia6Calls.h>
114 #include "AliEMCALJetFinder.h"
115 #include "AliEMCALFast.h"
116 #include "AliEMCALGeometry.h"
117 #include "AliEMCALHit.h"
118 #include "AliEMCALDigit.h"
119 #include "AliEMCALDigitizer.h"
120 #include "AliEMCALHadronCorrection.h"
121 #include "AliEMCALJetMicroDst.h"
124 #include "AliMagFCM.h"
125 #include "AliEMCAL.h"
126 #include "AliHeader.h"
130 // Interface to FORTRAN
134 ClassImp(AliEMCALJetFinder)
136 //____________________________________________________________________________
137 AliEMCALJetFinder::AliEMCALJetFinder()
139 // Default constructor
158 fHadronCorrector = 0;
166 SetParametersForBgSubtraction();
169 AliEMCALJetFinder::AliEMCALJetFinder(const char* name, const char *title)
173 // Title is used in method GetFileNameForParameters();
175 fJets = new TClonesArray("AliEMCALJet",10000);
177 for (Int_t i = 0; i < 30000; i++)
199 fHadronCorrector = 0;
208 SetMomentumSmearing();
211 SetHadronCorrection();
212 SetSamplingFraction();
215 SetParametersForBgSubtraction();
218 void AliEMCALJetFinder::SetParametersForBgSubtraction
219 (Int_t mode, Float_t minMove, Float_t maxMove, Float_t precBg)
221 // see file /home/pavlinov/cosmic/pythia/jetFinderParamData.inc
222 // at WSU Linux cluster - 11-feb-2002
223 // These parameters must be tuned more carefull !!!
230 //____________________________________________________________________________
231 AliEMCALJetFinder::~AliEMCALJetFinder()
242 # define jet_finder_ua1 jet_finder_ua1_
244 # define type_of_call
247 # define jet_finder_ua1 JET_FINDER_UA1
249 # define type_of_call _stdcall
252 extern "C" void type_of_call
253 jet_finder_ua1(Int_t& ncell, Int_t& ncell_tot,
254 Float_t etc[30000], Float_t etac[30000],
256 Float_t& min_move, Float_t& max_move, Int_t& mode,
257 Float_t& prec_bg, Int_t& ierror);
259 extern "C" void type_of_call hf1(Int_t& id, Float_t& x, Float_t& wgt);
262 void AliEMCALJetFinder::Init()
265 // Geometry and I/O initialization
269 // Get geometry parameters from EMCAL
273 AliEMCAL* pEMCAL = (AliEMCAL*) gAlice->GetModule("EMCAL");
274 AliEMCALGeometry* geom =
275 AliEMCALGeometry::GetInstance(pEMCAL->GetTitle(), "");
276 fNbinEta = geom->GetNZ();
277 fNbinPhi = geom->GetNPhi();
278 fPhiMin = geom->GetArm1PhiMin()*TMath::Pi()/180.;
279 fPhiMax = geom->GetArm1PhiMax()*TMath::Pi()/180.;
280 fEtaMin = geom->GetArm1EtaMin();
281 fEtaMax = geom->GetArm1EtaMax();
282 fDphi = (fPhiMax-fPhiMin)/fNbinPhi;
283 fDeta = (fEtaMax-fEtaMin)/fNbinEta;
284 fNtot = fNbinPhi*fNbinEta;
286 SetCellSize(fDeta, fDphi);
289 if (fOutFileName) fOutFile = new TFile(fOutFileName, "recreate");
292 void AliEMCALJetFinder::Find(Int_t ncell, Int_t ncell_tot, Float_t etc[30000],
293 Float_t etac[30000], Float_t phic[30000],
294 Float_t min_move, Float_t max_move, Int_t mode,
295 Float_t prec_bg, Int_t ierror)
297 // Wrapper for fortran coded jet finder
298 // Full argument list
299 jet_finder_ua1(ncell, ncell_tot, etc, etac, phic,
300 min_move, max_move, mode, prec_bg, ierror);
301 // Write result to output
302 if(fWrite) WriteJets();
306 void AliEMCALJetFinder::Find()
308 // Wrapper for fortran coded jet finder using member data for
311 Float_t min_move = fMinMove;
312 Float_t max_move = fMaxMove;
314 Float_t prec_bg = fPrecBg;
317 ResetJets(); // 4-feb-2002 by PAI
319 jet_finder_ua1(fNcell, fNtot, fEtCell, fEtaCell, fPhiCell,
320 min_move, max_move, mode, prec_bg, ierror);
322 // Write result to output
323 Int_t njet = Njets();
325 for (Int_t nj=0; nj<njet; nj++)
328 fJetT[nj] = new AliEMCALJet(JetEnergy(nj),
333 FindTracksInJetCone();
334 if(fWrite) WriteJets();
338 Int_t AliEMCALJetFinder::Njets()
340 // Get number of reconstructed jets
341 return EMCALJETS.njet;
344 Float_t AliEMCALJetFinder::JetEnergy(Int_t i)
346 // Get reconstructed jet energy
347 return EMCALJETS.etj[i];
350 Float_t AliEMCALJetFinder::JetPhiL(Int_t i)
352 // Get reconstructed jet phi from leading particle
353 return EMCALJETS.phij[0][i];
356 Float_t AliEMCALJetFinder::JetPhiW(Int_t i)
358 // Get reconstructed jet phi from weighting
359 return EMCALJETS.phij[1][i];
362 Float_t AliEMCALJetFinder::JetEtaL(Int_t i)
364 // Get reconstructed jet eta from leading particles
365 return EMCALJETS.etaj[0][i];
369 Float_t AliEMCALJetFinder::JetEtaW(Int_t i)
371 // Get reconstructed jet eta from weighting
372 return EMCALJETS.etaj[1][i];
375 void AliEMCALJetFinder::SetCellSize(Float_t eta, Float_t phi)
377 // Set grid cell size
378 EMCALCELLGEO.etaCellSize = eta;
379 EMCALCELLGEO.phiCellSize = phi;
382 void AliEMCALJetFinder::SetConeRadius(Float_t par)
384 // Set jet cone radius
385 EMCALJETPARAM.coneRad = par;
389 void AliEMCALJetFinder::SetEtSeed(Float_t par)
391 // Set et cut for seeds
392 EMCALJETPARAM.etSeed = par;
396 void AliEMCALJetFinder::SetMinJetEt(Float_t par)
398 // Set minimum jet et
399 EMCALJETPARAM.ejMin = par;
403 void AliEMCALJetFinder::SetMinCellEt(Float_t par)
405 // Set et cut per cell
406 EMCALJETPARAM.etMin = par;
410 void AliEMCALJetFinder::SetPtCut(Float_t par)
412 // Set pT cut on charged tracks
417 void AliEMCALJetFinder::Test()
420 // Test the finder call
422 const Int_t nmax = 30000;
424 Int_t ncell_tot = 100;
429 Float_t min_move = 0;
430 Float_t max_move = 0;
436 Find(ncell, ncell_tot, etc, etac, phic,
437 min_move, max_move, mode, prec_bg, ierror);
445 void AliEMCALJetFinder::AddJet(const AliEMCALJet& jet)
450 TClonesArray &lrawcl = *fJets;
451 new(lrawcl[fNjets++]) AliEMCALJet(jet);
454 void AliEMCALJetFinder::ResetJets()
463 void AliEMCALJetFinder::WriteJets()
466 // Add all jets to the list
468 const Int_t kBufferSize = 4000;
469 const char* file = 0;
471 Int_t njet = Njets();
473 for (Int_t nj = 0; nj < njet; nj++)
482 // output written to input file
484 AliEMCAL* pEMCAL = (AliEMCAL* )gAlice->GetModule("EMCAL");
485 TTree* pK = gAlice->TreeK();
486 file = (pK->GetCurrentFile())->GetName();
488 printf("Make Branch - TreeR address %p %p\n",gAlice->TreeR(), pEMCAL);
489 if (fJets && gAlice->TreeR()) {
490 pEMCAL->MakeBranchInTree(gAlice->TreeR(),
496 Int_t nev = gAlice->GetHeader()->GetEvent();
497 gAlice->TreeR()->Fill();
499 sprintf(hname,"TreeR%d", nev);
500 gAlice->TreeR()->Write(hname);
501 gAlice->TreeR()->Reset();
504 // Output written to user specified output file
506 TTree* pK = gAlice->TreeK();
507 fInFile = pK->GetCurrentFile();
511 sprintf(hname,"TreeR%d", fEvent);
512 TTree* treeJ = new TTree(hname, "EMCALJets");
513 treeJ->Branch("EMCALJets", &fJets, kBufferSize);
521 void AliEMCALJetFinder::BookLego()
524 // Book histo for discretisation
528 // Don't add histos to the current directory
529 if(fDebug) printf("\n AliEMCALJetFinder::BookLego() \n");
531 TH2::AddDirectory(0);
532 TH1::AddDirectory(0);
536 fLego = new TH2F("legoH","eta-phi",
537 fNbinEta, fEtaMin, fEtaMax,
538 fNbinPhi, fPhiMin, fPhiMax);
541 fLegoB = new TH2F("legoB","eta-phi for BG event",
542 fNbinEta, fEtaMin, fEtaMax,
543 fNbinPhi, fPhiMin, fPhiMax);
546 fhLegoTracks = new TH2F("hLegoTracks","eta-phi for Tracks",
547 fNbinEta, fEtaMin, fEtaMax, fNbinPhi, fPhiMin, fPhiMax);
549 fhLegoEMCAL = new TH2F("hLegoEMCAL","eta-phi for EMCAL",
550 fNbinEta, fEtaMin, fEtaMax, fNbinPhi, fPhiMin, fPhiMax);
551 // Hadron correction map
552 fhLegoHadrCorr = new TH2F("hLegoHadrCorr","eta-phi for Hadron. Correction",
553 fNbinEta, fEtaMin, fEtaMax, fNbinPhi, fPhiMin, fPhiMax);
554 // Hists. for tuning jet finder
555 fhEff = new TH2F("hEff","#epsilon vs momentum ", 100,0.,20., 50,0.5,1.);
559 for(Int_t i=1; i<=1000; i++) eTmp[i] = 0.1*i; // step 100 mev
560 for(Int_t i=1001; i<=1100; i++) eTmp[i] = eTmp[1000] + 1.0*(i-1000); // step 1GeV
562 fhCellEt = new TH1F("hCellEt","Cell E_{T} from fLego",
563 eTmp.GetSize()-1, eTmp.GetArray());
564 fhCellEMCALEt = new TH1F("hCellEMCALEt","Cell E_{T} for EMCAL itself",
565 eTmp.GetSize()-1, eTmp.GetArray());
566 fhTrackPt = new TH1F("hTrackPt","Ch.particles P_{T} ",
567 eTmp.GetSize()-1, eTmp.GetArray());
568 fhTrackPtBcut = new TH1F("hTrackPtBcut","Ch.particles P_{T} + magnetic field cut",
569 eTmp.GetSize()-1, eTmp.GetArray());
571 fhChPartMultInTpc = new TH1F("hChPartMultInTpc",
572 "Charge partilcle multiplicity in |%eta|<0.9", 2000, 0, 20000);
574 //! first canvas for drawing
575 fHistsList=AliEMCALJetMicroDst::MoveHistsToList("Hists from AliEMCALJetFinder", kTRUE);
578 void AliEMCALJetFinder::DumpLego()
581 // Dump lego histo into array
584 TAxis* Xaxis = fLego->GetXaxis();
585 TAxis* Yaxis = fLego->GetYaxis();
586 // fhCellEt->Clear();
588 for (Int_t i = 1; i <= fNbinEta; i++) {
589 for (Int_t j = 1; j <= fNbinPhi; j++) {
590 e = fLego->GetBinContent(i,j);
592 Float_t eta = Xaxis->GetBinCenter(i);
593 Float_t phi = Yaxis->GetBinCenter(j);
595 fEtaCell[fNcell] = eta;
596 fPhiCell[fNcell] = phi;
601 eH = fhLegoEMCAL->GetBinContent(i,j);
602 if(eH > 0.0) fhCellEMCALEt->Fill(eH);
609 void AliEMCALJetFinder::ResetMap()
612 // Reset eta-phi array
614 for (Int_t i=0; i<30000; i++)
623 void AliEMCALJetFinder::FillFromTracks(Int_t flag, Int_t ich)
626 // Fill Cells with track information
629 printf("\n AliEMCALJetFinder::FillFromTracks(%i,%i) ",flag,ich);
634 if (!fLego) BookLego();
636 if (flag == 0) fLego->Reset();
638 // Access particle information
639 Int_t npart = (gAlice->GetHeader())->GetNprimary();
640 Int_t ntr = (gAlice->GetHeader())->GetNtrack();
641 printf(" : #primary particles %i # tracks %i \n", npart, ntr);
646 // 1: selected for jet finding
649 if (fTrackList) delete[] fTrackList;
650 if (fPtT) delete[] fPtT;
651 if (fEtaT) delete[] fEtaT;
652 if (fPhiT) delete[] fPhiT;
653 if (fPdgT) delete[] fPdgT;
655 fTrackList = new Int_t [npart];
656 fPtT = new Float_t[npart];
657 fEtaT = new Float_t[npart];
658 fPhiT = new Float_t[npart];
659 fPdgT = new Int_t[npart];
663 Float_t chTmp=0.0; // charge of current particle
666 // this is for Pythia ??
667 for (Int_t part = 0; part < npart; part++) {
668 TParticle *MPart = gAlice->Particle(part);
669 Int_t mpart = MPart->GetPdgCode();
670 Int_t child1 = MPart->GetFirstDaughter();
671 Float_t pT = MPart->Pt();
672 Float_t p = MPart->P();
673 Float_t phi = MPart->Phi();
675 if(pT > 0.001) eta = MPart->Eta();
676 Float_t theta = MPart->Theta();
678 printf("ind %7i part %7i -> child1 %5i child2 %5i Status %5i\n",
679 part, mpart, child1, MPart->GetLastDaughter(), MPart->GetStatusCode());
683 if (part == 6 || part == 7)
685 printf("\n Simulated Jet (pt, eta, phi): %d %f %f %f\n",
686 part-5, pT, eta, phi);
691 // printf("\n Simulated Jet (pt, eta, phi): %d %d %f %f %f",
692 // part, mpart, pT, eta, phi);
695 fTrackList[part] = 0;
696 fPtT[part] = pT; // must be change after correction for resolution !!!
702 if (part < 2) continue;
704 // move to fLego->Fill because hadron correction must apply
705 // if particle hit to EMCAL - 11-feb-2002
706 // if (pT == 0 || pT < fPtCut) continue;
707 TParticlePDG* pdgP = 0;
708 // charged or neutral
709 pdgP = MPart->GetPDG();
710 chTmp = pdgP->Charge() / 3.; // 13-feb-2001!!
716 if (mpart != kNeutron &&
717 mpart != kNeutronBar &&
718 mpart != kK0Long) continue;
723 if (TMath::Abs(mpart) <= 6 ||
725 mpart == 92) continue;
727 if (TMath::Abs(eta)<=0.9) fNChTpc++;
729 if (child1 >= 0 && child1 < npart) continue;
731 if (TMath::Abs(eta) > 0.7) continue;
732 // Initial phi may be out of acceptance but track may
733 // hit two the acceptance - see variable curls
734 if (phi*180./TMath::Pi() > 120.) continue;
737 printf("\n=>nsel:%5d mpart %5d child1 %5d eta %6.2f phi %6.2f pT %6.2f ch %3.0f ",
738 part, mpart, child1, eta, phi, pT, chTmp);
741 // Momentum smearing goes here ...
745 if (fSmear && TMath::Abs(chTmp)) {
746 pw = AliEMCALFast::SmearMomentum(1,p);
747 // p changed - take into account when calculate pT,
750 if(fDebug >= 4) printf("\n Smearing : p %8.4f change to %8.4f ", p, pw);
754 // Tracking Efficiency and TPC acceptance goes here ...
756 if (fEffic && TMath::Abs(chTmp)) {
757 // eff = AliEMCALFast::Efficiency(1,p);
758 eff = 0.95; // for testing 25-feb-2002
759 if(fhEff) fhEff->Fill(p, eff);
760 if (AliEMCALFast::RandomReject(eff)) {
761 if(fDebug >= 5) printf(" reject due to unefficiency ");
766 // Correction of Hadronic Energy goes here ...
769 // phi propagation for hadronic correction
771 Bool_t curls = kFALSE; // hit two the EMCAL (no curl)
772 Float_t phiHC=0.0, dpH=0.0, dphi=0.0, eTdpH=0;
773 if(TMath::Abs(chTmp)) {
774 // hadr. correction only for charge particle
775 dphi = PropagatePhi(pT, chTmp, curls);
778 printf("\n Delta phi %f pT %f ", dphi, pT);
779 if (curls) printf("\n !! Track is curling");
781 if(!curls) fhTrackPtBcut->Fill(pT);
783 if (fHCorrection && !curls) {
784 if (!fHadronCorrector)
785 Fatal("AliEMCALJetFinder",
786 "Hadronic energy correction required but not defined !");
788 dpH = fHadronCorrector->GetEnergy(p, eta, 7);
789 eTdpH = dpH*TMath::Sin(theta);
791 if (fDebug >= 7) printf(" phi %f phiHC %f eTcorr %f\n",
792 phi, phiHC, -eTdpH); // correction is negative
793 fLego->Fill(eta, phiHC, -eTdpH);
794 fhLegoHadrCorr->Fill(eta, phiHC, eTdpH);
798 // More to do ? Just think about it !
801 if (phi*180./TMath::Pi() > 120.) continue;
803 if(TMath::Abs(chTmp) ) { // charge particle
804 if (pT > fPtCut && !curls) {
805 if (fDebug >= 8) printf("Charge : fLego->Fill(%5.2f, %5.2f, %6.2f)\n",
807 fLego->Fill(eta, phi, pT);
808 fhLegoTracks->Fill(eta, phi, pT); // 20-feb for checking
809 fTrackList[part] = 1;
812 } else if(ich==0 && fK0N) {
813 // case of n, nbar and K0L
814 if (fDebug >= 9) printf("Neutral : fLego->Fill(%5.2f, %5.2f, %6.2f)\n",
816 fLego->Fill(eta, phi, pT);
817 fTrackList[part] = 1;
825 void AliEMCALJetFinder::FillFromHits(Int_t flag)
828 // Fill Cells with hit information
832 printf("\n AliEMCALJetFinder::FillFromHits(%i)\n",flag);
836 if (!fLego) BookLego();
837 // Reset eta-phi maps if needed
838 if (flag == 0) { // default behavior
840 fhLegoTracks->Reset();
841 fhLegoEMCAL->Reset();
842 fhLegoHadrCorr->Reset();
844 // Initialize from background event if available
846 // Access hit information
847 AliEMCAL* pEMCAL = (AliEMCAL*) gAlice->GetModule("EMCAL");
849 TTree *treeH = gAlice->TreeH();
850 Int_t ntracks = (Int_t) treeH->GetEntries();
857 for (Int_t track=0; track<ntracks;track++) {
859 nbytes += treeH->GetEvent(track);
863 for(AliEMCALHit* mHit=(AliEMCALHit*) pEMCAL->FirstHit(-1);
865 mHit=(AliEMCALHit*) pEMCAL->NextHit())
867 Float_t x = mHit->X(); // x-pos of hit
868 Float_t y = mHit->Y(); // y-pos
869 Float_t z = mHit->Z(); // z-pos
870 Float_t eloss = mHit->GetEnergy(); // deposited energy
872 Float_t r = TMath::Sqrt(x*x+y*y);
873 Float_t theta = TMath::ATan2(r,z);
874 Float_t eta = -TMath::Log(TMath::Tan(theta/2.));
875 Float_t phi = TMath::ATan2(y,x);
877 if (fDebug >= 11) printf("\n Hit %f %f %f %f", x, y, z, eloss);
879 etH = fSamplingF*eloss*TMath::Sin(theta);
880 fLego->Fill(eta, phi, etH);
881 // fhLegoEMCAL->Fill(eta, phi, etH);
884 // copy content of fLego to fhLegoEMCAL (fLego and fhLegoEMCAL are identical)
885 for(Int_t i=0; i<fLego->GetSize(); i++) (*fhLegoEMCAL)[i] = (*fLego)[i];
889 void AliEMCALJetFinder::FillFromDigits(Int_t flag)
892 // Fill Cells with digit information
897 if (!fLego) BookLego();
898 if (flag == 0) fLego->Reset();
905 TClonesArray* digs = new TClonesArray("AliEMCALDigit", 10000);
906 TTree *treeD = gAlice->TreeD();
907 TBranchElement* branchDg = (TBranchElement*)
908 treeD->GetBranch("EMCAL");
910 if (!branchDg) Fatal("AliEMCALJetFinder",
911 "Reading digits requested but no digits in file !");
913 branchDg->SetAddress(&digs);
914 Int_t nent = (Int_t) branchDg->GetEntries();
918 AliEMCALDigitizer* digr = new AliEMCALDigitizer();
919 TBranchElement* branchDr = (TBranchElement*)
920 treeD->GetBranch("AliEMCALDigitizer");
921 branchDr->SetAddress(&digr);
924 nbytes += branchDg->GetEntry(0);
925 nbytes += branchDr->GetEntry(0);
927 // Get digitizer parameters
928 Float_t towerADCped = digr->GetTowerpedestal();
929 Float_t towerADCcha = digr->GetTowerchannel();
930 Float_t preshoADCped = digr->GetPreShopedestal();
931 Float_t preshoADCcha = digr->GetPreShochannel();
933 AliEMCAL* pEMCAL = (AliEMCAL*) gAlice->GetModule("EMCAL");
934 AliEMCALGeometry* geom =
935 AliEMCALGeometry::GetInstance(pEMCAL->GetTitle(), "");
938 Int_t ndig = digs->GetEntries();
939 printf("\n Number of Digits: %d %d\n", ndig, nent);
940 printf("\n Parameters: %f %f %f %f\n",
941 towerADCped, towerADCcha, preshoADCped, preshoADCcha );
942 printf("\n Geometry: %d %d\n", geom->GetNEta(), geom->GetNPhi());
949 while ((sdg = (AliEMCALDigit*)(next())))
953 if (sdg->GetId() > (geom->GetNZ() * geom->GetNPhi()))
955 pedestal = preshoADCped;
956 channel = preshoADCcha;
958 pedestal = towerADCped;
959 channel = towerADCcha;
962 Float_t eta = sdg->GetEta();
963 Float_t phi = sdg->GetPhi() * TMath::Pi()/180.;
964 Float_t amp = (Float_t) (channel*(sdg->GetAmp())-pedestal);
966 if (fDebug > 1) printf("\n Digit: eta %8.3f phi %8.3f amp %8.3f %8d",
967 eta, phi, amp, sdg->GetAmp());
969 fLego->Fill(eta, phi, fSamplingF*amp);
977 void AliEMCALJetFinder::FillFromHitFlaggedTracks(Int_t flag)
980 // Fill Cells with hit information
985 if (!fLego) BookLego();
987 if (flag == 0) fLego->Reset();
989 // Flag charged tracks passing through TPC which
990 // are associated to EMCAL Hits
991 BuildTrackFlagTable();
994 // Access particle information
995 TTree *treeK = gAlice->TreeK();
996 Int_t ntracks = (Int_t) treeK->GetEntries();
998 if (fPtT) delete[] fPtT;
999 if (fEtaT) delete[] fEtaT;
1000 if (fPhiT) delete[] fPhiT;
1001 if (fPdgT) delete[] fPdgT;
1003 fPtT = new Float_t[ntracks];
1004 fEtaT = new Float_t[ntracks];
1005 fPhiT = new Float_t[ntracks];
1006 fPdgT = new Int_t[ntracks];
1011 for (Int_t track = 0; track < ntracks; track++) {
1012 TParticle *MPart = gAlice->Particle(track);
1013 Float_t pT = MPart->Pt();
1014 Float_t phi = MPart->Phi();
1015 Float_t eta = MPart->Eta();
1017 if(fTrackList[track]) {
1021 fPdgT[track] = MPart->GetPdgCode();
1023 if (track < 2) continue; //Colliding particles?
1024 if (pT == 0 || pT < fPtCut) continue;
1026 fLego->Fill(eta, phi, pT);
1032 void AliEMCALJetFinder::FillFromParticles()
1034 // 26-feb-2002 PAI - for checking all chain
1035 // Work on particles level; accept all particle (not neutrino )
1037 Double_t PX=0, PY=0, PZ=0, E=0; // checking conservation law
1041 if (!fLego) BookLego();
1044 // Access particles information
1045 Int_t npart = (gAlice->GetHeader())->GetNprimary();
1046 if (fDebug >= 2 || npart<=0) {
1047 printf(" AliEMCALJetFinder::FillFromParticles : npart %i\n", npart);
1048 if(npart<=0) return;
1052 RearrangeParticlesMemory(npart);
1054 // Go through the particles
1055 Int_t mpart, child1, child2, geantPdg;
1056 Float_t pT, phi, eta, e=0, px=0, py=0, pz=0;
1058 for (Int_t part = 0; part < npart; part++) {
1060 fTrackList[part] = 0;
1062 MPart = gAlice->Particle(part);
1063 mpart = MPart->GetPdgCode();
1064 child1 = MPart->GetFirstDaughter();
1065 child2 = MPart->GetLastDaughter();
1073 e = MPart->Energy();
1075 // see pyedit in Pythia's text
1077 // Int_t kc = pycomp_(&mpart);
1078 // TString name = GetPythiaParticleName(mpart);
1079 // printf(" mpart %6.6i;kc %6.6i -> gid %3.3i",mpart,kc,geantPdg);
1080 //printf(" (%s)\n", name.Data());
1081 if (IsThisPartonsOrDiQuark(mpart)) continue;
1082 printf("%5i: %5i(%2i) px %5.1f py %5.1f pz %6.1f e %6.1f childs %5i,%5i \n",
1083 part, mpart, geantPdg, px, py, pz, e, child1, child2);
1085 // exclude partons (21 - gluon, 92 - string)
1088 // exclude neutrinous also ??
1089 if (fDebug >= 11 && pT>0.01)
1090 printf("\n part:%5d mpart %5d eta %9.2f phi %9.2f pT %9.2f ",
1091 part, mpart, eta, phi, pT);
1096 fPdgT[part] = mpart;
1099 if (child1 >= 0 && child1 < npart) continue;
1101 // printf("%4i -> %5i(%3i) px %6.1f py %6.1f pz %7.1f e %8.2f child1 %5i %s\n",
1102 // part, mpart, geantPdg, px, py, pz, e, child1, name.Data());
1109 if (TMath::Abs(eta) <= 0.9) fNChTpc++;
1111 if (TMath::Abs(eta) > 0.7) continue;
1112 if (phi*180./TMath::Pi() > 120.) continue;
1114 if(fK0N==0 ) { // exclude neutral hadrons
1115 if (mpart == kNeutron || mpart == kNeutronBar || mpart == kK0Long) continue;
1117 fTrackList[part] = 1;
1118 fLego->Fill(eta, phi, pT);
1121 printf("\n PX %8.2f PY %8.2f PZ %8.2f E %8.2f \n",
1124 if(fhChPartMultInTpc) fhChPartMultInTpc->Fill(fNChTpc);
1127 void AliEMCALJetFinder::FillFromPartons()
1129 // function under construction - 13-feb-2002 PAI
1132 printf("\n AliEMCALJetFinder::FillFromPartons()\n");
1136 if (!fLego) BookLego();
1139 // Access particle information
1140 Int_t npart = (gAlice->GetHeader())->GetNprimary();
1141 if (fDebug >= 2 || npart<=0)
1142 printf("\n AliEMCALJetFinder::FillFromPartons : npart %i\n", npart);
1143 fNt = 0; // for FindTracksInJetCone
1146 // Go through the partons
1148 for (Int_t part = 8; part < npart; part++) {
1149 TParticle *MPart = gAlice->Particle(part);
1150 Int_t mpart = MPart->GetPdgCode();
1151 // Int_t child1 = MPart->GetFirstDaughter();
1152 Float_t pT = MPart->Pt();
1153 // Float_t p = MPart->P();
1154 Float_t phi = MPart->Phi();
1155 Float_t eta = MPart->Eta();
1156 // Float_t theta = MPart->Theta();
1157 statusCode = MPart->GetStatusCode();
1159 // accept partons (21 - gluon, 92 - string)
1160 if (!(TMath::Abs(mpart) <= 6 || mpart == 21 ||mpart == 92)) continue;
1161 if (fDebug > 1 && pT>0.01)
1162 printf("\n part:%5d mpart %5d status %5d eta %8.2f phi %8.2f pT %8.2f ",
1163 part, mpart, statusCode, eta, phi, pT);
1164 // if (fDebug >= 3) MPart->Print();
1165 // accept partons before fragmentation - p.57 in Pythia manual
1166 // if(statusCode != 1) continue;
1168 if (TMath::Abs(eta) > 0.7) continue;
1169 if (phi*180./TMath::Pi() > 120.) continue;
1171 // if (child1 >= 0 && child1 < npart) continue;
1174 fLego->Fill(eta, phi, pT);
1180 void AliEMCALJetFinder::BuildTrackFlagTable() {
1182 // Method to generate a lookup table for TreeK particles
1183 // which are linked to hits in the EMCAL
1185 // --Author: J.L. Klay
1187 // Access hit information
1188 AliEMCAL* pEMCAL = (AliEMCAL*) gAlice->GetModule("EMCAL");
1190 TTree *TK = gAlice->TreeK(); // Get the number of entries in the kine tree
1191 Int_t nKTrks = (Int_t) TK->GetEntries(); // (Number of particles created somewhere)
1193 if(fTrackList) delete[] fTrackList; //Make sure we get rid of the old one
1194 fTrackList = new Int_t[nKTrks]; //before generating a new one
1196 for (Int_t i = 0; i < nKTrks; i++) { //Initialize members to 0
1200 TTree *treeH = gAlice->TreeH();
1201 Int_t ntracks = (Int_t) treeH->GetEntries();
1207 for (Int_t track=0; track<ntracks;track++) {
1208 gAlice->ResetHits();
1209 nbytes += treeH->GetEvent(track);
1215 for(AliEMCALHit* mHit=(AliEMCALHit*) pEMCAL->FirstHit(-1);
1217 mHit=(AliEMCALHit*) pEMCAL->NextHit())
1219 Int_t iTrk = mHit->Track(); // track number
1220 Int_t idprim = mHit->GetPrimary(); // primary particle
1222 //Determine the origin point of this particle - it made a hit in the EMCAL
1223 TParticle *trkPart = gAlice->Particle(iTrk);
1224 TParticlePDG *trkPdg = trkPart->GetPDG();
1225 Int_t trkCode = trkPart->GetPdgCode();
1227 if (trkCode < 10000) { //Big Ions cause problems for
1228 trkChg = trkPdg->Charge(); //this function. Since they aren't
1229 } else { //likely to make it very far, set
1230 trkChg = 0.0; //their charge to 0 for the Flag test
1232 Float_t vxTrk = trkPart->Vx();
1233 Float_t vyTrk = trkPart->Vy();
1234 Float_t vrTrk = TMath::Sqrt(vxTrk*vxTrk+vyTrk*vyTrk);
1235 fTrackList[iTrk] = SetTrackFlag(vrTrk,trkCode,trkChg);
1237 //Loop through the ancestry of the EMCAL entrance particles
1238 Int_t ancestor = trkPart->GetFirstMother(); //Get track's Mother
1239 while (ancestor != -1) {
1240 TParticle *ancPart = gAlice->Particle(ancestor); //get particle info on ancestor
1241 TParticlePDG *ancPdg = ancPart->GetPDG();
1242 Int_t ancCode = ancPart->GetPdgCode();
1244 if (ancCode < 10000) {
1245 ancChg = ancPdg->Charge();
1249 Float_t vxAnc = ancPart->Vx();
1250 Float_t vyAnc = ancPart->Vy();
1251 Float_t vrAnc = TMath::Sqrt(vxAnc*vxAnc+vyAnc*vyAnc);
1252 fTrackList[ancestor] = SetTrackFlag(vrAnc,ancCode,ancChg);
1253 ancestor = ancPart->GetFirstMother(); //Get the next ancestor
1256 //Determine the origin point of the primary particle associated with the hit
1257 TParticle *primPart = gAlice->Particle(idprim);
1258 TParticlePDG *primPdg = primPart->GetPDG();
1259 Int_t primCode = primPart->GetPdgCode();
1261 if (primCode < 10000) {
1262 primChg = primPdg->Charge();
1266 Float_t vxPrim = primPart->Vx();
1267 Float_t vyPrim = primPart->Vy();
1268 Float_t vrPrim = TMath::Sqrt(vxPrim*vxPrim+vyPrim*vyPrim);
1269 fTrackList[idprim] = SetTrackFlag(vrPrim,primCode,primChg);
1275 Int_t AliEMCALJetFinder
1276 ::SetTrackFlag(Float_t radius, Int_t code, Double_t charge) {
1282 if (charge == 0) neutral = 1;
1284 if (TMath::Abs(code) <= 6 ||
1286 code == 92) parton = 1;
1288 //It's not a parton, it's charged and it went through the TPC
1289 if (!parton && !neutral && radius <= 84.0) flag = 1;
1296 void AliEMCALJetFinder::SaveBackgroundEvent()
1298 // Saves the eta-phi lego and the tracklist
1302 (*fLegoB) = (*fLegoB) + (*fLego);
1304 printf("\n AliEMCALJetFinder::SaveBackgroundEvent() (fLegoB) %f = %f(fLego) \n",
1305 fLegoB->Integral(), fLego->Integral());
1308 if (fPtB) delete[] fPtB;
1309 if (fEtaB) delete[] fEtaB;
1310 if (fPhiB) delete[] fPhiB;
1311 if (fPdgB) delete[] fPdgB;
1312 if (fTrackListB) delete[] fTrackListB;
1314 fPtB = new Float_t[fNtS];
1315 fEtaB = new Float_t[fNtS];
1316 fPhiB = new Float_t[fNtS];
1317 fPdgB = new Int_t [fNtS];
1318 fTrackListB = new Int_t [fNtS];
1322 for (Int_t i = 0; i < fNt; i++) {
1323 if (!fTrackList[i]) continue;
1324 fPtB [fNtB] = fPtT [i];
1325 fEtaB[fNtB] = fEtaT[i];
1326 fPhiB[fNtB] = fPhiT[i];
1327 fPdgB[fNtB] = fPdgT[i];
1329 fTrackListB[fNtB] = 1;
1333 printf(" fNtB %i => fNtS %i #particles %i \n", fNtB, fNtS, fNt);
1336 void AliEMCALJetFinder::InitFromBackground()
1340 if (fDebug) printf("\n AliEMCALJetFinder::InitFromBackground() ");
1344 (*fLego) = (*fLego) + (*fLegoB);
1346 printf("\n AliEMCALJetFinder::SaveBackgroundEvent() (fLego) %f = %f(fLegoB) \n",
1347 fLego->Integral(), fLegoB->Integral());
1349 printf(" => fLego undefined \n");
1354 void AliEMCALJetFinder::FindTracksInJetCone()
1357 // Build list of tracks inside jet cone
1360 Int_t njet = Njets();
1361 for (Int_t nj = 0; nj < njet; nj++)
1363 Float_t etaj = JetEtaW(nj);
1364 Float_t phij = JetPhiW(nj);
1365 Int_t nT = 0; // number of associated tracks
1367 // Loop over particles in current event
1368 for (Int_t part = 0; part < fNt; part++) {
1369 if (!fTrackList[part]) continue;
1370 Float_t phi = fPhiT[part];
1371 Float_t eta = fEtaT[part];
1372 Float_t dr = TMath::Sqrt((etaj-eta)*(etaj-eta) +
1373 (phij-phi)*(phij-phi));
1374 if (dr < fConeRadius) {
1375 fTrackList[part] = nj+2;
1380 // Same for background event if available
1383 for (Int_t part = 0; part < fNtB; part++) {
1384 Float_t phi = fPhiB[part];
1385 Float_t eta = fEtaB[part];
1386 Float_t dr = TMath::Sqrt((etaj-eta)*(etaj-eta) +
1387 (phij-phi)*(phij-phi));
1388 fTrackListB[part] = 1;
1390 if (dr < fConeRadius) {
1391 fTrackListB[part] = nj+2;
1395 } // Background available ?
1397 Int_t nT0 = nT + nTB;
1399 if (nT0 > 50) nT0 = 50;
1401 Float_t* ptT = new Float_t[nT0];
1402 Float_t* etaT = new Float_t[nT0];
1403 Float_t* phiT = new Float_t[nT0];
1404 Int_t* pdgT = new Int_t[nT0];
1409 for (Int_t part = 0; part < fNt; part++) {
1410 if (fTrackList[part] == nj+2) {
1412 for (j=iT-1; j>=0; j--) {
1413 if (fPtT[part] > ptT[j]) {
1418 for (j=iT-1; j>=index; j--) {
1419 ptT [j+1] = ptT [j];
1420 etaT[j+1] = etaT[j];
1421 phiT[j+1] = phiT[j];
1422 pdgT[j+1] = pdgT[j];
1424 ptT [index] = fPtT [part];
1425 etaT[index] = fEtaT[part];
1426 phiT[index] = fPhiT[part];
1427 pdgT[index] = fPdgT[part];
1429 } // particle associated
1430 if (iT > nT0) break;
1434 for (Int_t part = 0; part < fNtB; part++) {
1435 if (fTrackListB[part] == nj+2) {
1437 for (j=iT-1; j>=0; j--) {
1438 if (fPtB[part] > ptT[j]) {
1444 for (j=iT-1; j>=index; j--) {
1445 ptT [j+1] = ptT [j];
1446 etaT[j+1] = etaT[j];
1447 phiT[j+1] = phiT[j];
1448 pdgT[j+1] = pdgT[j];
1450 ptT [index] = fPtB [part];
1451 etaT[index] = fEtaB[part];
1452 phiT[index] = fPhiB[part];
1453 pdgT[index] = fPdgB[part];
1455 } // particle associated
1456 if (iT > nT0) break;
1458 } // Background available ?
1460 fJetT[nj]->SetTrackList(nT0, ptT, etaT, phiT, pdgT);
1469 Float_t AliEMCALJetFinder::PropagatePhi(Float_t pt, Float_t charge, Bool_t& curls)
1471 // Propagates phi angle to EMCAL radius
1473 static Float_t b = 0.0, rEMCAL = -1.0;
1476 b = gAlice->Field())->SolenoidField();
1477 // Get EMCAL radius in cm
1478 rEMCAL = AliEMCALGeometry::GetInstance()->GetIPDistance();
1479 printf("\nMagnetic field %f rEMCAL %f ", b, rEMCAL);
1488 Float_t rB = 3335.6 * pt / b; // [cm] (case of |charge|=1)
1490 // check if particle is curling below EMCAL
1491 if (2.*rB < rEMCAL) {
1496 // if not calculate delta phi
1497 Float_t phi = TMath::ACos(1.-rEMCAL*rEMCAL/(2.*rB*rB));
1498 dPhi = TMath::ATan2(1.-TMath::Cos(phi), TMath::Sin(phi));
1499 dPhi = -TMath::Sign(dPhi, charge);
1504 void hf1(Int_t& id, Float_t& x, Float_t& wgt)
1506 // dummy for hbook calls
1510 void AliEMCALJetFinder::DrawLego(Char_t *opt)
1513 void AliEMCALJetFinder::DrawLegoEMCAL(Char_t *opt)
1514 {fhLegoEMCAL->Draw(opt);}
1516 void AliEMCALJetFinder::DrawHistsForTuning(Int_t mode)
1518 static TPaveText *varLabel=0;
1520 fC1 = new TCanvas("C1","Hists. for tunning", 0,25,600,800);
1530 fhCellEMCALEt->Draw();
1535 fhTrackPtBcut->SetLineColor(2);
1536 fhTrackPtBcut->Draw("same");
1541 varLabel = new TPaveText(0.05,0.5,0.95,0.95,"NDC");
1542 varLabel->SetTextAlign(12);
1543 varLabel->SetFillColor(19); // see TAttFill
1544 TString tmp(GetTitle());
1545 varLabel->ReadFile(GetFileNameForParameters());
1549 if(mode) { // for saving picture to the file
1550 TString stmp(GetFileNameForParameters());
1551 stmp.ReplaceAll("_Par.txt",".ps");
1552 fC1->Print(stmp.Data());
1556 void AliEMCALJetFinder::PrintParameters(Int_t mode)
1559 if(mode==0) file = stdout; // output to terminal
1561 file = fopen(GetFileNameForParameters(),"w");
1562 if(file==0) file = stdout;
1564 fprintf(file,"==== Filling lego ==== \n");
1565 fprintf(file,"Smearing %6i ", fSmear);
1566 fprintf(file,"Efficiency %6i\n", fEffic);
1567 fprintf(file,"Hadr.Correct. %6i ", fHCorrection);
1568 fprintf(file,"P_{T} Cut of ch.par. %6.2f\n", fPtCut);
1569 fprintf(file,"==== Jet finding ==== \n");
1570 fprintf(file,"Cone radius %6.2f ", fConeRadius);
1571 fprintf(file,"Seed E_{T} %6.1f\n", fEtSeed);
1572 fprintf(file,"Min E_{T} of cell %6.1f ", fMinCellEt);
1573 fprintf(file,"Min E_{T} of jet %6.1f\n", fMinJetEt);
1575 fprintf(file,"==== Bg subtraction ==== \n");
1576 fprintf(file,"BG subtraction %6i ", fMode);
1577 fprintf(file,"Min cone move %6.2f\n", fMinMove);
1578 fprintf(file,"Max cone move %6.2f ", fMaxMove);
1579 fprintf(file,"%% change for BG %6.4f\n", fPrecBg);
1581 fprintf(file,"==== No Bg subtraction ==== \n");
1582 if(file != stdout) fclose(file);
1585 void AliEMCALJetFinder::DrawLegos()
1588 fC1 = new TCanvas("C1","Hists. for tunning", 0,25,600,800);
1592 gStyle->SetOptStat(111111);
1594 Int_t nent1, nent2, nent3, nent4;
1595 Double_t int1, int2, int3, int4;
1596 nent1 = (Int_t)fLego->GetEntries();
1597 int1 = fLego->Integral();
1599 if(int1) fLego->Draw("lego");
1601 nent2 = (Int_t)fhLegoTracks->GetEntries();
1602 int2 = fhLegoTracks->Integral();
1604 if(int2) fhLegoTracks->Draw("lego");
1606 nent3 = (Int_t)fhLegoEMCAL->GetEntries();
1607 int3 = fhLegoEMCAL->Integral();
1609 if(int3) fhLegoEMCAL->Draw("lego");
1611 nent4 = (Int_t)fhLegoHadrCorr->GetEntries();
1612 int4 = fhLegoHadrCorr->Integral();
1614 if(int4) fhLegoHadrCorr->Draw("lego");
1616 // just for checking
1617 printf(" Integrals \n");
1618 printf("lego %10.3f \ntrack %10.3f \nhits %10.3f \nHCorr %10.3f\n-- %10.3f(must be 0)\n",
1619 int1, int2, int3, int4, int1 - (int2 + int3 - int4));
1622 const Char_t* AliEMCALJetFinder::GetFileNameForParameters(Char_t* dir)
1625 if(strlen(dir)) tmp = dir;
1631 void AliEMCALJetFinder::RearrangeParticlesMemory(Int_t npart)
1632 { // See FillFromTracks() - npart must be positive
1633 if (fTrackList) delete[] fTrackList;
1634 if (fPtT) delete[] fPtT;
1635 if (fEtaT) delete[] fEtaT;
1636 if (fPhiT) delete[] fPhiT;
1637 if (fPdgT) delete[] fPdgT;
1640 fTrackList = new Int_t [npart];
1641 fPtT = new Float_t[npart];
1642 fEtaT = new Float_t[npart];
1643 fPhiT = new Float_t[npart];
1644 fPdgT = new Int_t[npart];
1646 printf("AliEMCALJetFinder::RearrangeParticlesMemory : npart = %d\n", npart);
1650 Bool_t AliEMCALJetFinder::IsThisPartonsOrDiQuark(Int_t pdg)
1652 Int_t absPdg = TMath::Abs(pdg);
1653 if(absPdg<=6) return kTRUE; // quarks
1654 if(pdg == 21) return kTRUE; // gluon
1655 if(pdg == 92) return kTRUE; // string
1657 // see p.51 of Pythia Manual
1658 // Not include diquarks with c and b quark - 4-mar-2002
1659 // ud_0,sd_0,su_0; dd_1,ud_1,uu_1; sd_1,su_1,ss_1
1660 static Int_t diquark[9]={2101,3101,3201, 1103,2103,2203, 3103,3203,3303};
1661 for(Int_t i=0; i<9; i++) if(absPdg == diquark[i]) return kTRUE; // diquarks
1666 TString &AliEMCALJetFinder::GetPythiaParticleName(Int_t kf)
1667 {// see subroutine PYNAME in PYTHIA
1668 static TString sname;
1670 pyname_(&kf, name, 16);
1671 for(Int_t i=0; i<16; i++){
1672 if(name[i] == ' ') {