source: HiSusy/trunk/Delphes-3.0.0/modules/Calorimeter.cc @ 1

Last change on this file since 1 was 1, checked in by zerwas, 11 years ago

first import of structure, PYTHIA8 and DELPHES

File size: 10.4 KB
Line 
1
2/** \class Calorimeter
3 *
4 *  Fills calorimeter towers, performs calorimeter resolution smearing
5 *  and preselects towers hit by electrons, photons and neutral particles.
6 *
7 *  $Date: 2012-11-19 14:05:19 +0100 (Mon, 19 Nov 2012) $
8 *  $Revision: 829 $
9 *
10 *
11 *  \author P. Demin - UCL, Louvain-la-Neuve
12 *
13 */
14
15#include "modules/Calorimeter.h"
16
17#include "classes/DelphesClasses.h"
18#include "classes/DelphesFactory.h"
19#include "classes/DelphesFormula.h"
20
21#include "ExRootAnalysis/ExRootResult.h"
22#include "ExRootAnalysis/ExRootFilter.h"
23#include "ExRootAnalysis/ExRootClassifier.h"
24
25#include "TMath.h"
26#include "TString.h"
27#include "TFormula.h"
28#include "TRandom3.h"
29#include "TObjArray.h"
30#include "TDatabasePDG.h"
31#include "TLorentzVector.h"
32
33#include <algorithm> 
34#include <stdexcept>
35#include <iostream>
36#include <sstream>
37
38using namespace std;
39
40//------------------------------------------------------------------------------
41
42Calorimeter::Calorimeter() :
43  fECalResolutionFormula(0), fHCalResolutionFormula(0), fItInputArray(0)
44{
45  fECalResolutionFormula = new DelphesFormula;
46  fHCalResolutionFormula = new DelphesFormula;
47}
48
49//------------------------------------------------------------------------------
50
51Calorimeter::~Calorimeter()
52{
53  if(fECalResolutionFormula) delete fECalResolutionFormula;
54  if(fHCalResolutionFormula) delete fHCalResolutionFormula;
55}
56
57//------------------------------------------------------------------------------
58
59void Calorimeter::Init()
60{
61  ExRootConfParam param, paramEtaBins, paramPhiBins, paramFractions;
62  Long_t i, j, k, size, sizeEtaBins, sizePhiBins, sizeFractions;
63  Double_t ecalFraction, hcalFraction;
64  TBinMap::iterator itEtaBin;
65  set< Double_t >::iterator itPhiBin;
66  vector< Double_t > *phiBins;
67
68  // read eta and phi bins
69  param = GetParam("EtaPhiBins");
70  size = param.GetSize();
71  fBinMap.clear();
72  fEtaBins.clear();
73  fPhiBins.clear();
74  for(i = 0; i < size/2; ++i)
75  {
76    paramEtaBins = param[i*2];
77    sizeEtaBins = paramEtaBins.GetSize();
78    paramPhiBins = param[i*2 + 1];
79    sizePhiBins = paramPhiBins.GetSize();
80
81    for(j = 0; j < sizeEtaBins; ++j)
82    {
83      for(k = 0; k < sizePhiBins; ++k)
84      {
85        fBinMap[paramEtaBins[j].GetDouble()].insert(paramPhiBins[k].GetDouble());
86      }
87    }
88  }
89
90  // for better performance we transform map of sets to parallel vectors:
91  // vector< double > and vector< vector< double >* >
92  for(itEtaBin = fBinMap.begin(); itEtaBin != fBinMap.end(); ++itEtaBin)
93  {
94    fEtaBins.push_back(itEtaBin->first);
95    phiBins = new vector< double >(itEtaBin->second.size());
96    fPhiBins.push_back(phiBins);
97    phiBins->clear();
98    for(itPhiBin = itEtaBin->second.begin(); itPhiBin != itEtaBin->second.end(); ++itPhiBin)
99    {
100      phiBins->push_back(*itPhiBin);
101    }
102  }
103 
104  // read energy fractions for different particles
105  param = GetParam("EnergyFraction");
106  size = param.GetSize();
107 
108  // set default energy fractions values
109  fFractionMap.clear();
110  fFractionMap[0] = make_pair(0.0, 1.0);
111 
112  for(i = 0; i < size/2; ++i)
113  {
114    paramFractions = param[i*2 + 1];
115    sizeFractions = paramFractions.GetSize();
116 
117    ecalFraction = paramFractions[0].GetDouble();
118    hcalFraction = paramFractions[1].GetDouble();
119
120    fFractionMap[param[i*2].GetInt()] = make_pair(ecalFraction, hcalFraction);
121  }
122/*
123  TFractionMap::iterator itFractionMap;
124  for(itFractionMap = fFractionMap.begin(); itFractionMap != fFractionMap.end(); ++itFractionMap)
125  {
126    cout << itFractionMap->first << "   " << itFractionMap->second.first  << "   " << itFractionMap->second.second << endl;
127  }
128*/
129  // read resolution formulas 
130  fECalResolutionFormula->Compile(GetString("ECalResolutionFormula", "0"));
131  fHCalResolutionFormula->Compile(GetString("HCalResolutionFormula", "0"));
132
133  // import array with output from other modules
134  fInputArray = ImportArray(GetString("InputArray", "ParticlePropagator/particles"));
135  fItInputArray = fInputArray->MakeIterator();
136
137  // create output arrays
138  fTowerOutputArray = ExportArray(GetString("TowerOutputArray", "towers"));
139  fNeutralOutputArray = ExportArray(GetString("NeutralOutputArray", "neutrals"));
140  fPhotonOutputArray = ExportArray(GetString("PhotonOutputArray", "photons"));
141}
142
143//------------------------------------------------------------------------------
144
145void Calorimeter::Finish()
146{
147  vector< vector< Double_t>* >::iterator itPhiBin;
148  if(fItInputArray) delete fItInputArray;
149  for(itPhiBin = fPhiBins.begin(); itPhiBin != fPhiBins.end(); ++itPhiBin)
150  {
151    delete *itPhiBin;
152  }
153
154}
155
156//------------------------------------------------------------------------------
157
158void Calorimeter::Process()
159{
160  Candidate *candidate;
161  TLorentzVector position, momentum;
162  Short_t etaBin, phiBin, number, flags;
163  Long64_t towerHit, towerEtaPhi, hitEtaPhi;
164  Double_t ecalFraction, hcalFraction;
165  Double_t ecalEnergy, hcalEnergy;
166  Int_t pdgCode;
167
168  TFractionMap::iterator itFractionMap;
169
170  vector< Double_t >::iterator itEtaBin;
171  vector< Double_t >::iterator itPhiBin;
172  vector< Double_t > *phiBins;
173
174  vector< Long64_t >::iterator itTowerHits;
175 
176  DelphesFactory *factory = GetFactory();
177  fTowerHits.clear();
178  fECalFractions.clear();
179  fHCalFractions.clear();
180
181  // loop over all particles
182  fItInputArray->Reset();
183  number = -1;
184  while((candidate = static_cast<Candidate*>(fItInputArray->Next())))
185  {
186    const TLorentzVector &candidatePosition = candidate->Position;
187    ++number;
188
189    pdgCode = TMath::Abs(candidate->PID);
190
191    itFractionMap = fFractionMap.find(pdgCode);
192    if(itFractionMap == fFractionMap.end())
193    {
194      itFractionMap = fFractionMap.find(0);
195    }
196
197    ecalFraction = itFractionMap->second.first;
198    hcalFraction = itFractionMap->second.second;
199
200    fECalFractions.push_back(ecalFraction);
201    fHCalFractions.push_back(hcalFraction);
202   
203    if(ecalFraction < 1.0E-9 && hcalFraction < 1.0E-9) continue;
204   
205    // find eta bin [1, fEtaBins.size - 1]
206    itEtaBin = lower_bound(fEtaBins.begin(), fEtaBins.end(), candidatePosition.Eta());
207    if(itEtaBin == fEtaBins.begin() || itEtaBin == fEtaBins.end()) continue;
208    etaBin = distance(fEtaBins.begin(), itEtaBin);
209   
210    // phi bins for given eta bin
211    phiBins = fPhiBins[etaBin];
212
213    // find phi bin [1, phiBins.size - 1]
214    itPhiBin = lower_bound(phiBins->begin(), phiBins->end(), candidatePosition.Phi());
215    if(itPhiBin == phiBins->begin() || itPhiBin == phiBins->end()) continue;
216    phiBin = distance(phiBins->begin(), itPhiBin);
217
218    flags = (candidate->Charge == 0);
219    flags |= (pdgCode == 22) << 1;
220
221    // make tower hit {16-bits for eta bin number, 16-bits for phi bin number, 16-bits for candidate number, 16-bits for flags}
222    towerHit = (Long64_t(etaBin) << 48) | (Long64_t(phiBin) << 32) | Long64_t(number) << 16 | Long64_t(flags);
223   
224    fTowerHits.push_back(towerHit);
225  }
226
227  // all hits are sorted first by eta bin number, then by phi bin number and then by candidate number
228  sort(fTowerHits.begin(), fTowerHits.end());
229
230  // loop over all hits
231  towerEtaPhi = 0;
232  fTower = 0;
233  for(itTowerHits = fTowerHits.begin(); itTowerHits != fTowerHits.end(); ++itTowerHits)
234  {
235    towerHit = (*itTowerHits);
236    flags = (towerHit) & 0x000000000000FFFFLL;
237    number = (towerHit >> 16) & 0x000000000000FFFFLL;
238    hitEtaPhi = towerHit >> 32;
239    candidate = static_cast<Candidate*>(fInputArray->At(number));
240    momentum = candidate->Momentum;
241
242    if(towerEtaPhi != hitEtaPhi)
243    {
244      // switch to next tower
245      towerEtaPhi = hitEtaPhi;
246
247      // finalize previous tower
248      FinalizeTower();
249
250      // create new tower
251      fTower = factory->NewCandidate();
252
253      phiBin = (towerHit >> 32) & 0x000000000000FFFFLL;   
254      etaBin = (towerHit >> 48) & 0x000000000000FFFFLL;
255
256      // phi bins for given eta bin
257      phiBins = fPhiBins[etaBin];
258
259      // calculate eta and phi of the tower's center
260      fTowerEta = 0.5*(fEtaBins[etaBin - 1] + fEtaBins[etaBin]);
261      fTowerPhi = 0.5*((*phiBins)[phiBin - 1] + (*phiBins)[phiBin]);
262
263      fTowerECalEnergy = 0.0;
264      fTowerHCalEnergy = 0.0;
265
266      fTowerECalNeutralEnergy = 0.0;
267      fTowerHCalNeutralEnergy = 0.0;
268           
269      fTowerHasNeutralHit = kFALSE;
270      fTowerHasPhotonHit = kFALSE;
271    }
272
273    // fill current tower
274    ecalEnergy = momentum.E() * fECalFractions[number];
275    hcalEnergy = momentum.E() * fHCalFractions[number];
276   
277    fTowerECalEnergy += ecalEnergy;
278    fTowerHCalEnergy += hcalEnergy;
279
280    fTower->AddCandidate(candidate);   
281
282    // check for neutral hits in current tower
283    if(flags & 1)
284    {
285      fTowerHasNeutralHit = kTRUE;
286
287      fTowerECalNeutralEnergy += ecalEnergy;
288      fTowerHCalNeutralEnergy += hcalEnergy;
289    }
290   
291    // check for photon hits in current tower
292    if(flags & 2)
293    {
294      fTowerHasPhotonHit = kTRUE;
295    }
296  }
297
298  // finalize last tower
299  FinalizeTower();
300}
301
302//------------------------------------------------------------------------------
303void Calorimeter::FinalizeTower()
304{
305  Candidate *tower;
306  Double_t energy, pt;
307  Double_t ecalNeutralFraction, hcalNeutralFraction;
308  Double_t ecalEnergy, hcalEnergy;
309
310  if(!fTower) return;
311
312  ecalEnergy = gRandom->Gaus(fTowerECalEnergy, fECalResolutionFormula->Eval(0.0, fTowerEta, 0.0, fTowerECalEnergy));
313  if(ecalEnergy < 0.0) ecalEnergy = 0.0;
314
315  hcalEnergy = gRandom->Gaus(fTowerHCalEnergy, fHCalResolutionFormula->Eval(0.0, fTowerEta, 0.0, fTowerHCalEnergy));
316  if(hcalEnergy < 0.0) hcalEnergy = 0.0;
317
318  energy = ecalEnergy + hcalEnergy;
319
320  if(energy <= 0.0) return;
321
322  pt = energy / TMath::CosH(fTowerEta);
323 
324  fTower->Position.SetPtEtaPhiE(1.0, fTowerEta, fTowerPhi, 0.0);
325  fTower->Momentum.SetPtEtaPhiE(pt, fTowerEta, fTowerPhi, energy);
326  fTower->Eem = ecalEnergy;
327  fTower->Ehad = hcalEnergy;
328
329  fTowerOutputArray->Add(fTower);
330  if(fTowerHasPhotonHit) fPhotonOutputArray->Add(fTower);
331  if(fTowerHasNeutralHit)
332  {
333    tower = static_cast<Candidate*>(fTower->Clone());
334
335    ecalNeutralFraction = (fTowerECalEnergy > 0.0) ? fTowerECalNeutralEnergy / fTowerECalEnergy : 0.0;
336    hcalNeutralFraction = (fTowerHCalEnergy > 0.0) ? fTowerHCalNeutralEnergy / fTowerHCalEnergy : 0.0;
337
338    ecalEnergy *= ecalNeutralFraction;
339    hcalEnergy *= hcalNeutralFraction;
340
341    energy = ecalEnergy + hcalEnergy;
342    pt = energy / TMath::CosH(fTowerEta);
343
344    tower->Position.SetPtEtaPhiE(1.0, fTowerEta, fTowerPhi, 0.0);
345    tower->Momentum.SetPtEtaPhiE(pt, fTowerEta, fTowerPhi, energy);
346    tower->Eem = ecalEnergy;
347    tower->Ehad = hcalEnergy;
348    tower->Mother = fTower;
349
350    fNeutralOutputArray->Add(tower);
351  }
352}
353
354//------------------------------------------------------------------------------
Note: See TracBrowser for help on using the repository browser.