Fork me on GitHub

source: git/modules/Calorimeter.cc@ 2dab783

ImprovedOutputFile Timing dual_readout llp
Last change on this file since 2dab783 was 2dab783, checked in by pavel <pavel@…>, 11 years ago

new energy flow

  • Property mode set to 100644
File size: 14.1 KB
Line 
1
2/** \class Calorimeter
3 *
4 * Fills calorimeter towers, performs calorimeter resolution smearing,
5 * preselects towers hit by photons and creates energy flow objects.
6 *
7 * $Date$
8 * $Revision$
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),
44 fItParticleInputArray(0), fItTrackInputArray(0),
45 fTowerTrackArray(0), fItTowerTrackArray(0)
46{
47 fECalResolutionFormula = new DelphesFormula;
48 fHCalResolutionFormula = new DelphesFormula;
49
50 fTowerTrackArray = new TObjArray;
51 fItTowerTrackArray = fTowerTrackArray->MakeIterator();
52}
53
54//------------------------------------------------------------------------------
55
56Calorimeter::~Calorimeter()
57{
58 if(fECalResolutionFormula) delete fECalResolutionFormula;
59 if(fHCalResolutionFormula) delete fHCalResolutionFormula;
60
61 if(fTowerTrackArray) delete fTowerTrackArray;
62 if(fItTowerTrackArray) delete fItTowerTrackArray;
63}
64
65//------------------------------------------------------------------------------
66
67void Calorimeter::Init()
68{
69 ExRootConfParam param, paramEtaBins, paramPhiBins, paramFractions;
70 Long_t i, j, k, size, sizeEtaBins, sizePhiBins, sizeFractions;
71 Double_t ecalFraction, hcalFraction;
72 TBinMap::iterator itEtaBin;
73 set< Double_t >::iterator itPhiBin;
74 vector< Double_t > *phiBins;
75
76 // read eta and phi bins
77 param = GetParam("EtaPhiBins");
78 size = param.GetSize();
79 fBinMap.clear();
80 fEtaBins.clear();
81 fPhiBins.clear();
82 for(i = 0; i < size/2; ++i)
83 {
84 paramEtaBins = param[i*2];
85 sizeEtaBins = paramEtaBins.GetSize();
86 paramPhiBins = param[i*2 + 1];
87 sizePhiBins = paramPhiBins.GetSize();
88
89 for(j = 0; j < sizeEtaBins; ++j)
90 {
91 for(k = 0; k < sizePhiBins; ++k)
92 {
93 fBinMap[paramEtaBins[j].GetDouble()].insert(paramPhiBins[k].GetDouble());
94 }
95 }
96 }
97
98 // for better performance we transform map of sets to parallel vectors:
99 // vector< double > and vector< vector< double >* >
100 for(itEtaBin = fBinMap.begin(); itEtaBin != fBinMap.end(); ++itEtaBin)
101 {
102 fEtaBins.push_back(itEtaBin->first);
103 phiBins = new vector< double >(itEtaBin->second.size());
104 fPhiBins.push_back(phiBins);
105 phiBins->clear();
106 for(itPhiBin = itEtaBin->second.begin(); itPhiBin != itEtaBin->second.end(); ++itPhiBin)
107 {
108 phiBins->push_back(*itPhiBin);
109 }
110 }
111
112 // read energy fractions for different particles
113 param = GetParam("EnergyFraction");
114 size = param.GetSize();
115
116 // set default energy fractions values
117 fFractionMap.clear();
118 fFractionMap[0] = make_pair(0.0, 1.0);
119
120 for(i = 0; i < size/2; ++i)
121 {
122 paramFractions = param[i*2 + 1];
123 sizeFractions = paramFractions.GetSize();
124
125 ecalFraction = paramFractions[0].GetDouble();
126 hcalFraction = paramFractions[1].GetDouble();
127
128 fFractionMap[param[i*2].GetInt()] = make_pair(ecalFraction, hcalFraction);
129 }
130/*
131 TFractionMap::iterator itFractionMap;
132 for(itFractionMap = fFractionMap.begin(); itFractionMap != fFractionMap.end(); ++itFractionMap)
133 {
134 cout << itFractionMap->first << " " << itFractionMap->second.first << " " << itFractionMap->second.second << endl;
135 }
136*/
137 // read resolution formulas
138 fECalResolutionFormula->Compile(GetString("ECalResolutionFormula", "0"));
139 fHCalResolutionFormula->Compile(GetString("HCalResolutionFormula", "0"));
140
141 // import array with output from other modules
142 fParticleInputArray = ImportArray(GetString("ParticleInputArray", "ParticlePropagator/particles"));
143 fItParticleInputArray = fParticleInputArray->MakeIterator();
144
145 fTrackInputArray = ImportArray(GetString("TrackInputArray", "ParticlePropagator/tracks"));
146 fItTrackInputArray = fTrackInputArray->MakeIterator();
147
148 // create output arrays
149 fTowerOutputArray = ExportArray(GetString("TowerOutputArray", "towers"));
150 fPhotonOutputArray = ExportArray(GetString("PhotonOutputArray", "photons"));
151
152 fEFlowTrackOutputArray = ExportArray(GetString("EFlowTrackOutputArray", "eflowTracks"));
153 fEFlowTowerOutputArray = ExportArray(GetString("EFlowTowerOutputArray", "eflowTowers"));
154}
155
156//------------------------------------------------------------------------------
157
158void Calorimeter::Finish()
159{
160 vector< vector< Double_t >* >::iterator itPhiBin;
161 if(fItParticleInputArray) delete fItParticleInputArray;
162 if(fItTrackInputArray) delete fItTrackInputArray;
163 for(itPhiBin = fPhiBins.begin(); itPhiBin != fPhiBins.end(); ++itPhiBin)
164 {
165 delete *itPhiBin;
166 }
167}
168
169//------------------------------------------------------------------------------
170
171void Calorimeter::Process()
172{
173 Candidate *particle, *track;
174 TLorentzVector position, momentum;
175 Short_t etaBin, phiBin, flags;
176 Int_t number;
177 Long64_t towerHit, towerEtaPhi, hitEtaPhi;
178 Double_t ecalFraction, hcalFraction;
179 Double_t ecalEnergy, hcalEnergy;
180 Int_t pdgCode;
181
182 TFractionMap::iterator itFractionMap;
183
184 vector< Double_t >::iterator itEtaBin;
185 vector< Double_t >::iterator itPhiBin;
186 vector< Double_t > *phiBins;
187
188 vector< Long64_t >::iterator itTowerHits;
189
190 DelphesFactory *factory = GetFactory();
191 fTowerHits.clear();
192 fTowerECalFractions.clear();
193 fTowerHCalFractions.clear();
194 fTrackECalFractions.clear();
195 fTrackHCalFractions.clear();
196
197 // loop over all particles
198 fItParticleInputArray->Reset();
199 number = -1;
200 while((particle = static_cast<Candidate*>(fItParticleInputArray->Next())))
201 {
202 const TLorentzVector &particlePosition = particle->Position;
203 ++number;
204
205 pdgCode = TMath::Abs(particle->PID);
206
207 itFractionMap = fFractionMap.find(pdgCode);
208 if(itFractionMap == fFractionMap.end())
209 {
210 itFractionMap = fFractionMap.find(0);
211 }
212
213 ecalFraction = itFractionMap->second.first;
214 hcalFraction = itFractionMap->second.second;
215
216 fTowerECalFractions.push_back(ecalFraction);
217 fTowerHCalFractions.push_back(hcalFraction);
218
219 if(ecalFraction < 1.0E-9 && hcalFraction < 1.0E-9) continue;
220
221 // find eta bin [1, fEtaBins.size - 1]
222 itEtaBin = lower_bound(fEtaBins.begin(), fEtaBins.end(), particlePosition.Eta());
223 if(itEtaBin == fEtaBins.begin() || itEtaBin == fEtaBins.end()) continue;
224 etaBin = distance(fEtaBins.begin(), itEtaBin);
225
226 // phi bins for given eta bin
227 phiBins = fPhiBins[etaBin];
228
229 // find phi bin [1, phiBins.size - 1]
230 itPhiBin = lower_bound(phiBins->begin(), phiBins->end(), particlePosition.Phi());
231 if(itPhiBin == phiBins->begin() || itPhiBin == phiBins->end()) continue;
232 phiBin = distance(phiBins->begin(), itPhiBin);
233
234 flags = 0;
235 flags |= (pdgCode == 11 || pdgCode == 22) << 1;
236
237 // make tower hit {16-bits for eta bin number, 16-bits for phi bin number, 8-bits for flags, 24-bits for particle number}
238 towerHit = (Long64_t(etaBin) << 48) | (Long64_t(phiBin) << 32) | (Long64_t(flags) << 24) | Long64_t(number);
239
240 fTowerHits.push_back(towerHit);
241 }
242
243 // loop over all tracks
244 fItTrackInputArray->Reset();
245 number = -1;
246 while((track = static_cast<Candidate*>(fItTrackInputArray->Next())))
247 {
248 const TLorentzVector &trackPosition = track->Position;
249 ++number;
250
251 pdgCode = TMath::Abs(track->PID);
252
253 itFractionMap = fFractionMap.find(pdgCode);
254 if(itFractionMap == fFractionMap.end())
255 {
256 itFractionMap = fFractionMap.find(0);
257 }
258
259 ecalFraction = itFractionMap->second.first;
260 hcalFraction = itFractionMap->second.second;
261
262 fTrackECalFractions.push_back(ecalFraction);
263 fTrackHCalFractions.push_back(hcalFraction);
264
265 if(ecalFraction < 1.0E-9 && hcalFraction < 1.0E-9) continue;
266
267 // find eta bin [1, fEtaBins.size - 1]
268 itEtaBin = lower_bound(fEtaBins.begin(), fEtaBins.end(), trackPosition.Eta());
269 if(itEtaBin == fEtaBins.begin() || itEtaBin == fEtaBins.end()) continue;
270 etaBin = distance(fEtaBins.begin(), itEtaBin);
271
272 // phi bins for given eta bin
273 phiBins = fPhiBins[etaBin];
274
275 // find phi bin [1, phiBins.size - 1]
276 itPhiBin = lower_bound(phiBins->begin(), phiBins->end(), trackPosition.Phi());
277 if(itPhiBin == phiBins->begin() || itPhiBin == phiBins->end()) continue;
278 phiBin = distance(phiBins->begin(), itPhiBin);
279
280 flags = 1;
281
282 // make tower hit {16-bits for eta bin number, 16-bits for phi bin number, 8-bits for flags, 24-bits for track number}
283 towerHit = (Long64_t(etaBin) << 48) | (Long64_t(phiBin) << 32) | (Long64_t(flags) << 24) | Long64_t(number);
284
285 fTowerHits.push_back(towerHit);
286 }
287
288 // all hits are sorted first by eta bin number, then by phi bin number,
289 // then by flags and then by particle or track number
290 sort(fTowerHits.begin(), fTowerHits.end());
291
292 // loop over all hits
293 towerEtaPhi = 0;
294 fTower = 0;
295 for(itTowerHits = fTowerHits.begin(); itTowerHits != fTowerHits.end(); ++itTowerHits)
296 {
297 towerHit = (*itTowerHits);
298 flags = (towerHit >> 24) & 0x00000000000000FFLL;
299 number = (towerHit) & 0x0000000000FFFFFFLL;
300 hitEtaPhi = towerHit >> 32;
301
302 if(towerEtaPhi != hitEtaPhi)
303 {
304 // switch to next tower
305 towerEtaPhi = hitEtaPhi;
306
307 // finalize previous tower
308 FinalizeTower();
309
310 // create new tower
311 fTower = factory->NewCandidate();
312
313 phiBin = (towerHit >> 32) & 0x000000000000FFFFLL;
314 etaBin = (towerHit >> 48) & 0x000000000000FFFFLL;
315
316 // phi bins for given eta bin
317 phiBins = fPhiBins[etaBin];
318
319 // calculate eta and phi of the tower's center
320 fTowerEta = 0.5*(fEtaBins[etaBin - 1] + fEtaBins[etaBin]);
321 fTowerPhi = 0.5*((*phiBins)[phiBin - 1] + (*phiBins)[phiBin]);
322
323 fTowerEdges[0] = fEtaBins[etaBin - 1];
324 fTowerEdges[1] = fEtaBins[etaBin];
325 fTowerEdges[2] = (*phiBins)[phiBin - 1];
326 fTowerEdges[3] = (*phiBins)[phiBin];
327
328 fTowerECalEnergy = 0.0;
329 fTowerHCalEnergy = 0.0;
330
331 fTrackECalEnergy = 0.0;
332 fTrackHCalEnergy = 0.0;
333
334 fTowerTrackHits = 0;
335 fTowerPhotonHits = 0;
336
337 fTowerTrackArray->Clear();
338 }
339
340 // check for track hits
341 if(flags & 1)
342 {
343 ++fTowerTrackHits;
344
345 track = static_cast<Candidate*>(fTrackInputArray->At(number));
346 momentum = track->Momentum;
347
348 ecalEnergy = momentum.E() * fTrackECalFractions[number];
349 hcalEnergy = momentum.E() * fTrackHCalFractions[number];
350
351 fTrackECalEnergy += ecalEnergy;
352 fTrackHCalEnergy += hcalEnergy;
353
354 fTowerTrackArray->Add(track);
355
356 continue;
357 }
358
359 // check for photon and electron hits in current tower
360 if(flags & 2) ++fTowerPhotonHits;
361
362 particle = static_cast<Candidate*>(fParticleInputArray->At(number));
363 momentum = particle->Momentum;
364
365 // fill current tower
366 ecalEnergy = momentum.E() * fTowerECalFractions[number];
367 hcalEnergy = momentum.E() * fTowerHCalFractions[number];
368
369 fTowerECalEnergy += ecalEnergy;
370 fTowerHCalEnergy += hcalEnergy;
371
372 fTower->AddCandidate(particle);
373 }
374
375 // finalize last tower
376 FinalizeTower();
377}
378
379//------------------------------------------------------------------------------
380
381void Calorimeter::FinalizeTower()
382{
383 Candidate *track, *tower;
384 Double_t energy, pt, eta, phi;
385 Double_t ecalEnergy, hcalEnergy;
386
387 if(!fTower) return;
388
389// ecalEnergy = gRandom->Gaus(fTowerECalEnergy, fECalResolutionFormula->Eval(0.0, fTowerEta, 0.0, fTowerECalEnergy));
390// if(ecalEnergy < 0.0) ecalEnergy = 0.0;
391
392 ecalEnergy = LogNormal(fTowerECalEnergy, fECalResolutionFormula->Eval(0.0, fTowerEta, 0.0, fTowerECalEnergy));
393
394// hcalEnergy = gRandom->Gaus(fTowerHCalEnergy, fHCalResolutionFormula->Eval(0.0, fTowerEta, 0.0, fTowerHCalEnergy));
395// if(hcalEnergy < 0.0) hcalEnergy = 0.0;
396
397 hcalEnergy = LogNormal(fTowerHCalEnergy, fHCalResolutionFormula->Eval(0.0, fTowerEta, 0.0, fTowerHCalEnergy));
398
399 energy = ecalEnergy + hcalEnergy;
400
401// eta = fTowerEta;
402// phi = fTowerPhi;
403
404 eta = gRandom->Uniform(fTowerEdges[0], fTowerEdges[1]);
405 phi = gRandom->Uniform(fTowerEdges[2], fTowerEdges[3]);
406
407 pt = energy / TMath::CosH(eta);
408
409 fTower->Position.SetPtEtaPhiE(1.0, eta, phi, 0.0);
410 fTower->Momentum.SetPtEtaPhiE(pt, eta, phi, energy);
411 fTower->Eem = ecalEnergy;
412 fTower->Ehad = hcalEnergy;
413
414 fTower->Edges[0] = fTowerEdges[0];
415 fTower->Edges[1] = fTowerEdges[1];
416 fTower->Edges[2] = fTowerEdges[2];
417 fTower->Edges[3] = fTowerEdges[3];
418
419 // fill calorimeter towers and photon candidates
420 if(energy > 0.0)
421 {
422 if(fTowerPhotonHits > 0 && fTowerTrackHits == 0)
423 {
424 fPhotonOutputArray->Add(fTower);
425 }
426
427 fTowerOutputArray->Add(fTower);
428 }
429
430 // fill energy flow candidates
431
432 // save all the tracks as energy flow tracks
433 fItTowerTrackArray->Reset();
434 while((track = static_cast<Candidate*>(fItTowerTrackArray->Next())))
435 {
436 fEFlowTrackOutputArray->Add(track);
437 }
438
439 ecalEnergy -= fTrackECalEnergy;
440 if(ecalEnergy < 0.0) ecalEnergy = 0.0;
441
442 hcalEnergy -= fTrackHCalEnergy;
443 if(hcalEnergy < 0.0) hcalEnergy = 0.0;
444
445 energy = ecalEnergy + hcalEnergy;
446
447 // save ECAL and/or HCAL energy excess as an energy flow tower
448 if(energy > 0.0)
449 {
450 // create new tower
451 tower = static_cast<Candidate*>(fTower->Clone());
452
453 pt = energy / TMath::CosH(eta);
454
455 tower->Position.SetPtEtaPhiE(1.0, eta, phi, 0.0);
456 tower->Momentum.SetPtEtaPhiE(pt, eta, phi, energy);
457 tower->Eem = ecalEnergy;
458 tower->Ehad = hcalEnergy;
459
460 tower->Edges[0] = fTowerEdges[0];
461 tower->Edges[1] = fTowerEdges[1];
462 tower->Edges[2] = fTowerEdges[2];
463 tower->Edges[3] = fTowerEdges[3];
464
465 fEFlowTowerOutputArray->Add(tower);
466 }
467}
468
469//------------------------------------------------------------------------------
470
471Double_t Calorimeter::LogNormal(Double_t mean, Double_t sigma)
472{
473 Double_t a, b;
474
475 if(mean > 0.0)
476 {
477 b = TMath::Sqrt(TMath::Log((1.0 + (sigma*sigma)/(mean*mean))));
478 a = TMath::Log(mean) - 0.5*b*b;
479
480 return TMath::Exp(a + b*gRandom->Gaus(0, 1));
481 }
482 else
483 {
484 return 0.0;
485 }
486}
Note: See TracBrowser for help on using the repository browser.