Fork me on GitHub

source: svn/trunk/modules/Calorimeter.cc@ 1234

Last change on this file since 1234 was 1233, checked in by Pavel Demin, 11 years ago

new energy flow

  • Property svn:keywords set to Id Revision Date
File size: 16.0 KB
RevLine 
[608]1
[814]2/** \class Calorimeter
3 *
[894]4 * Fills calorimeter towers, performs calorimeter resolution smearing,
5 * preselects towers hit by photons and creates energy flow objects.
[814]6 *
7 * $Date: 2013-07-22 15:41:43 +0000 (Mon, 22 Jul 2013) $
8 * $Revision: 1233 $
9 *
10 *
11 * \author P. Demin - UCL, Louvain-la-Neuve
12 *
13 */
14
[608]15#include "modules/Calorimeter.h"
16
[687]17#include "classes/DelphesClasses.h"
18#include "classes/DelphesFactory.h"
[766]19#include "classes/DelphesFormula.h"
[608]20
[703]21#include "ExRootAnalysis/ExRootResult.h"
22#include "ExRootAnalysis/ExRootFilter.h"
23#include "ExRootAnalysis/ExRootClassifier.h"
24
[608]25#include "TMath.h"
26#include "TString.h"
[629]27#include "TFormula.h"
[703]28#include "TRandom3.h"
29#include "TObjArray.h"
30#include "TDatabasePDG.h"
31#include "TLorentzVector.h"
[608]32
[935]33#include <algorithm>
[703]34#include <stdexcept>
[608]35#include <iostream>
[703]36#include <sstream>
[608]37
38using namespace std;
39
40//------------------------------------------------------------------------------
41
42Calorimeter::Calorimeter() :
[886]43 fECalResolutionFormula(0), fHCalResolutionFormula(0),
44 fItParticleInputArray(0), fItTrackInputArray(0),
[1233]45 fTowerECalArray(0), fItTowerECalArray(0),
46 fTowerHCalArray(0), fItTowerHCalArray(0),
47 fTowerECalTrackArray(0), fItTowerECalTrackArray(0),
48 fTowerHCalTrackArray(0), fItTowerHCalTrackArray(0)
[608]49{
[766]50 fECalResolutionFormula = new DelphesFormula;
51 fHCalResolutionFormula = new DelphesFormula;
[1233]52
53 fTowerECalArray = new TObjArray;
54 fItTowerECalArray = fTowerECalArray->MakeIterator();
55 fTowerHCalArray = new TObjArray;
56 fItTowerHCalArray = fTowerHCalArray->MakeIterator();
57
58 fTowerECalTrackArray = new TObjArray;
59 fItTowerECalTrackArray = fTowerECalTrackArray->MakeIterator();
60 fTowerHCalTrackArray = new TObjArray;
61 fItTowerHCalTrackArray = fTowerHCalTrackArray->MakeIterator();
[608]62}
63
64//------------------------------------------------------------------------------
65
66Calorimeter::~Calorimeter()
67{
[766]68 if(fECalResolutionFormula) delete fECalResolutionFormula;
69 if(fHCalResolutionFormula) delete fHCalResolutionFormula;
[608]70
[1233]71 if(fTowerECalArray) delete fTowerECalArray;
72 if(fItTowerECalArray) delete fItTowerECalArray;
73 if(fTowerHCalArray) delete fTowerHCalArray;
74 if(fItTowerHCalArray) delete fItTowerHCalArray;
75
76 if(fTowerECalTrackArray) delete fTowerECalTrackArray;
77 if(fItTowerECalTrackArray) delete fItTowerECalTrackArray;
78 if(fTowerHCalTrackArray) delete fTowerHCalTrackArray;
79 if(fItTowerHCalTrackArray) delete fItTowerHCalTrackArray;}
80
[608]81//------------------------------------------------------------------------------
82
83void Calorimeter::Init()
84{
[704]85 ExRootConfParam param, paramEtaBins, paramPhiBins, paramFractions;
86 Long_t i, j, k, size, sizeEtaBins, sizePhiBins, sizeFractions;
[608]87 Double_t ecalFraction, hcalFraction;
[622]88 TBinMap::iterator itEtaBin;
[659]89 set< Double_t >::iterator itPhiBin;
90 vector< Double_t > *phiBins;
[608]91
[613]92 // read eta and phi bins
[646]93 param = GetParam("EtaPhiBins");
[608]94 size = param.GetSize();
[622]95 fBinMap.clear();
[663]96 fEtaBins.clear();
97 fPhiBins.clear();
[613]98 for(i = 0; i < size/2; ++i)
[608]99 {
[646]100 paramEtaBins = param[i*2];
101 sizeEtaBins = paramEtaBins.GetSize();
[613]102 paramPhiBins = param[i*2 + 1];
103 sizePhiBins = paramPhiBins.GetSize();
[646]104
105 for(j = 0; j < sizeEtaBins; ++j)
[613]106 {
[646]107 for(k = 0; k < sizePhiBins; ++k)
108 {
[659]109 fBinMap[paramEtaBins[j].GetDouble()].insert(paramPhiBins[k].GetDouble());
[646]110 }
[613]111 }
[608]112 }
113
[661]114 // for better performance we transform map of sets to parallel vectors:
[659]115 // vector< double > and vector< vector< double >* >
[622]116 for(itEtaBin = fBinMap.begin(); itEtaBin != fBinMap.end(); ++itEtaBin)
[813]117 {
[659]118 fEtaBins.push_back(itEtaBin->first);
119 phiBins = new vector< double >(itEtaBin->second.size());
120 fPhiBins.push_back(phiBins);
[666]121 phiBins->clear();
[659]122 for(itPhiBin = itEtaBin->second.begin(); itPhiBin != itEtaBin->second.end(); ++itPhiBin)
[622]123 {
[659]124 phiBins->push_back(*itPhiBin);
[622]125 }
126 }
[935]127
[608]128 // read energy fractions for different particles
129 param = GetParam("EnergyFraction");
130 size = param.GetSize();
[935]131
[608]132 // set default energy fractions values
133 fFractionMap.clear();
134 fFractionMap[0] = make_pair(0.0, 1.0);
[935]135
[608]136 for(i = 0; i < size/2; ++i)
137 {
[703]138 paramFractions = param[i*2 + 1];
[608]139 sizeFractions = paramFractions.GetSize();
[935]140
[608]141 ecalFraction = paramFractions[0].GetDouble();
142 hcalFraction = paramFractions[1].GetDouble();
143
[703]144 fFractionMap[param[i*2].GetInt()] = make_pair(ecalFraction, hcalFraction);
[608]145 }
[629]146/*
[626]147 TFractionMap::iterator itFractionMap;
148 for(itFractionMap = fFractionMap.begin(); itFractionMap != fFractionMap.end(); ++itFractionMap)
149 {
150 cout << itFractionMap->first << " " << itFractionMap->second.first << " " << itFractionMap->second.second << endl;
151 }
[629]152*/
[935]153 // read resolution formulas
[766]154 fECalResolutionFormula->Compile(GetString("ECalResolutionFormula", "0"));
155 fHCalResolutionFormula->Compile(GetString("HCalResolutionFormula", "0"));
156
[608]157 // import array with output from other modules
[886]158 fParticleInputArray = ImportArray(GetString("ParticleInputArray", "ParticlePropagator/particles"));
159 fItParticleInputArray = fParticleInputArray->MakeIterator();
[608]160
[886]161 fTrackInputArray = ImportArray(GetString("TrackInputArray", "ParticlePropagator/tracks"));
162 fItTrackInputArray = fTrackInputArray->MakeIterator();
163
[766]164 // create output arrays
[629]165 fTowerOutputArray = ExportArray(GetString("TowerOutputArray", "towers"));
166 fPhotonOutputArray = ExportArray(GetString("PhotonOutputArray", "photons"));
[938]167
168 fEFlowTrackOutputArray = ExportArray(GetString("EFlowTrackOutputArray", "eflowTracks"));
169 fEFlowTowerOutputArray = ExportArray(GetString("EFlowTowerOutputArray", "eflowTowers"));
[608]170}
171
172//------------------------------------------------------------------------------
173
174void Calorimeter::Finish()
175{
[660]176 vector< vector< Double_t>* >::iterator itPhiBin;
[886]177 if(fItParticleInputArray) delete fItParticleInputArray;
[938]178 if(fItTrackInputArray) delete fItTrackInputArray;
[660]179 for(itPhiBin = fPhiBins.begin(); itPhiBin != fPhiBins.end(); ++itPhiBin)
180 {
181 delete *itPhiBin;
182 }
[608]183}
184
185//------------------------------------------------------------------------------
186
187void Calorimeter::Process()
188{
[886]189 Candidate *particle, *track;
[680]190 TLorentzVector position, momentum;
[1002]191 Short_t etaBin, phiBin, flags;
192 Int_t number;
[745]193 Long64_t towerHit, towerEtaPhi, hitEtaPhi;
[730]194 Double_t ecalFraction, hcalFraction;
[735]195 Double_t ecalEnergy, hcalEnergy;
[608]196 Int_t pdgCode;
197
198 TFractionMap::iterator itFractionMap;
199
[659]200 vector< Double_t >::iterator itEtaBin;
201 vector< Double_t >::iterator itPhiBin;
202 vector< Double_t > *phiBins;
[622]203
[745]204 vector< Long64_t >::iterator itTowerHits;
[935]205
[687]206 DelphesFactory *factory = GetFactory();
[661]207 fTowerHits.clear();
[663]208 fECalFractions.clear();
209 fHCalFractions.clear();
[730]210
[608]211 // loop over all particles
[886]212 fItParticleInputArray->Reset();
[666]213 number = -1;
[886]214 while((particle = static_cast<Candidate*>(fItParticleInputArray->Next())))
[608]215 {
[886]216 const TLorentzVector &particlePosition = particle->Position;
[666]217 ++number;
[608]218
[886]219 pdgCode = TMath::Abs(particle->PID);
[626]220
221 itFractionMap = fFractionMap.find(pdgCode);
222 if(itFractionMap == fFractionMap.end())
223 {
224 itFractionMap = fFractionMap.find(0);
225 }
226
227 ecalFraction = itFractionMap->second.first;
228 hcalFraction = itFractionMap->second.second;
[666]229
230 fECalFractions.push_back(ecalFraction);
231 fHCalFractions.push_back(hcalFraction);
[935]232
[626]233 if(ecalFraction < 1.0E-9 && hcalFraction < 1.0E-9) continue;
[935]234
[730]235 // find eta bin [1, fEtaBins.size - 1]
[886]236 itEtaBin = lower_bound(fEtaBins.begin(), fEtaBins.end(), particlePosition.Eta());
[659]237 if(itEtaBin == fEtaBins.begin() || itEtaBin == fEtaBins.end()) continue;
[730]238 etaBin = distance(fEtaBins.begin(), itEtaBin);
[935]239
[730]240 // phi bins for given eta bin
[659]241 phiBins = fPhiBins[etaBin];
[730]242
243 // find phi bin [1, phiBins.size - 1]
[886]244 itPhiBin = lower_bound(phiBins->begin(), phiBins->end(), particlePosition.Phi());
[659]245 if(itPhiBin == phiBins->begin() || itPhiBin == phiBins->end()) continue;
[666]246 phiBin = distance(phiBins->begin(), itPhiBin);
[608]247
[1233]248 flags = 0;
249 flags |= (ecalFraction >= 1.0E-9) << 1;
250 flags |= (hcalFraction >= 1.0E-9) << 2;
251 flags |= (pdgCode == 11 || pdgCode == 22) << 3;
[745]252
[1004]253 // make tower hit {16-bits for eta bin number, 16-bits for phi bin number, 8-bits for flags, 24-bits for particle number}
254 towerHit = (Long64_t(etaBin) << 48) | (Long64_t(phiBin) << 32) | (Long64_t(flags) << 24) | Long64_t(number);
[935]255
[661]256 fTowerHits.push_back(towerHit);
257 }
258
[886]259 // loop over all tracks
260 fItTrackInputArray->Reset();
261 number = -1;
262 while((track = static_cast<Candidate*>(fItTrackInputArray->Next())))
263 {
264 const TLorentzVector &trackPosition = track->Position;
265 ++number;
266
[1233]267 pdgCode = TMath::Abs(track->PID);
268
269 itFractionMap = fFractionMap.find(pdgCode);
270 if(itFractionMap == fFractionMap.end())
271 {
272 itFractionMap = fFractionMap.find(0);
273 }
274
275 ecalFraction = itFractionMap->second.first;
276 hcalFraction = itFractionMap->second.second;
277
[886]278 // find eta bin [1, fEtaBins.size - 1]
279 itEtaBin = lower_bound(fEtaBins.begin(), fEtaBins.end(), trackPosition.Eta());
280 if(itEtaBin == fEtaBins.begin() || itEtaBin == fEtaBins.end()) continue;
281 etaBin = distance(fEtaBins.begin(), itEtaBin);
[935]282
[886]283 // phi bins for given eta bin
284 phiBins = fPhiBins[etaBin];
285
286 // find phi bin [1, phiBins.size - 1]
287 itPhiBin = lower_bound(phiBins->begin(), phiBins->end(), trackPosition.Phi());
288 if(itPhiBin == phiBins->begin() || itPhiBin == phiBins->end()) continue;
289 phiBin = distance(phiBins->begin(), itPhiBin);
290
[1233]291 flags = 1;
292 flags |= (ecalFraction >= 1.0E-9) << 1;
293 flags |= (hcalFraction >= 1.0E-9) << 2;
294
[1004]295 // make tower hit {16-bits for eta bin number, 16-bits for phi bin number, 8-bits for flags, 24-bits for track number}
[1233]296 towerHit = (Long64_t(etaBin) << 48) | (Long64_t(phiBin) << 32) | (Long64_t(flags) << 24) | Long64_t(number);
[935]297
[886]298 fTowerHits.push_back(towerHit);
299 }
300
[894]301 // all hits are sorted first by eta bin number, then by phi bin number,
302 // then by flags and then by particle or track number
[661]303 sort(fTowerHits.begin(), fTowerHits.end());
304
[730]305 // loop over all hits
[661]306 towerEtaPhi = 0;
[732]307 fTower = 0;
[661]308 for(itTowerHits = fTowerHits.begin(); itTowerHits != fTowerHits.end(); ++itTowerHits)
309 {
310 towerHit = (*itTowerHits);
[1004]311 flags = (towerHit >> 24) & 0x00000000000000FFLL;
312 number = (towerHit) & 0x0000000000FFFFFFLL;
313 hitEtaPhi = towerHit >> 32;
[730]314
[661]315 if(towerEtaPhi != hitEtaPhi)
[608]316 {
[730]317 // switch to next tower
[661]318 towerEtaPhi = hitEtaPhi;
[730]319
[661]320 // finalize previous tower
[730]321 FinalizeTower();
[661]322
323 // create new tower
[730]324 fTower = factory->NewCandidate();
[661]325
[1004]326 phiBin = (towerHit >> 32) & 0x000000000000FFFFLL;
327 etaBin = (towerHit >> 48) & 0x000000000000FFFFLL;
[730]328
329 // phi bins for given eta bin
[661]330 phiBins = fPhiBins[etaBin];
[608]331
[730]332 // calculate eta and phi of the tower's center
[731]333 fTowerEta = 0.5*(fEtaBins[etaBin - 1] + fEtaBins[etaBin]);
334 fTowerPhi = 0.5*((*phiBins)[phiBin - 1] + (*phiBins)[phiBin]);
[626]335
[898]336 fTowerEdges[0] = fEtaBins[etaBin - 1];
337 fTowerEdges[1] = fEtaBins[etaBin];
338 fTowerEdges[2] = (*phiBins)[phiBin - 1];
339 fTowerEdges[3] = (*phiBins)[phiBin];
340
[735]341 fTowerECalEnergy = 0.0;
342 fTowerHCalEnergy = 0.0;
343
[1233]344 fTowerPhotonHits = 0;
[935]345
[886]346 fTowerAllHits = 0;
[1233]347 fTowerECalHits = 0;
348 fTowerHCalHits = 0;
[935]349
[1233]350 fTowerTrackAllHits = 0;
351 fTowerECalTrackHits = 0;
352 fTowerHCalTrackHits = 0;
353
354 fTowerECalTrackArray->Clear();
355 fTowerHCalTrackArray->Clear();
356 fTowerECalArray->Clear();
357 fTowerHCalArray->Clear();
[661]358 }
359
[886]360 // check for track hits
[1233]361 if(flags & 1)
[886]362 {
363 track = static_cast<Candidate*>(fTrackInputArray->At(number));
[1233]364
365 ++fTowerTrackAllHits;
[886]366 fTowerTrackArray->Add(track);
[1233]367 if(flags & 2)
368 {
369 ++fTowerECalTrackHits;
370 fTowerECalTrackArray->Add(track);
371 }
372 if(flags & 4)
373 {
374 ++fTowerHCalTrackHits;
375 fTowerHCalTrackArray->Add(track);
376 }
[886]377 continue;
378 }
379
[1233]380 ++fTowerAllHits;
381
382 // check for ECAL hits in current tower
383 if(flags & 2)
384 {
385 ++fTowerECalHits;
386 fTowerECalArray->Add(particle);
387 }
388
389 // check for HCAL hits in current tower
390 if(flags & 4)
391 {
392 ++fTowerHCalHits;
393 fTowerHCalArray->Add(particle);
394 }
395
396 // check for photon and electron hits in current tower
397 if(flags & 8) ++fTowerPhotonHits;
398
[886]399 particle = static_cast<Candidate*>(fParticleInputArray->At(number));
[888]400 momentum = particle->Momentum;
[886]401
[735]402 // fill current tower
403 ecalEnergy = momentum.E() * fECalFractions[number];
404 hcalEnergy = momentum.E() * fHCalFractions[number];
[931]405
[735]406 fTowerECalEnergy += ecalEnergy;
407 fTowerHCalEnergy += hcalEnergy;
[695]408
[935]409 fTower->AddCandidate(particle);
[608]410 }
411
[661]412 // finalize last tower
[730]413 FinalizeTower();
414}
415
416//------------------------------------------------------------------------------
[931]417
[730]418void Calorimeter::FinalizeTower()
419{
[934]420 Candidate *particle, *track, *tower;
[1078]421 Double_t energy, pt, eta, phi;
[735]422 Double_t ecalEnergy, hcalEnergy;
[1233]423 TIterator *iterator;
[1145]424
[734]425 if(!fTower) return;
[733]426
[1142]427// ecalEnergy = gRandom->Gaus(fTowerECalEnergy, fECalResolutionFormula->Eval(0.0, fTowerEta, 0.0, fTowerECalEnergy));
[1145]428// if(ecalEnergy < 0.0) ecalEnergy = 0.0;
[733]429
[1145]430 ecalEnergy = LogNormal(fTowerECalEnergy, fECalResolutionFormula->Eval(0.0, fTowerEta, 0.0, fTowerECalEnergy));
[733]431
[1145]432// hcalEnergy = gRandom->Gaus(fTowerHCalEnergy, fHCalResolutionFormula->Eval(0.0, fTowerEta, 0.0, fTowerHCalEnergy));
433// if(hcalEnergy < 0.0) hcalEnergy = 0.0;
434
435 hcalEnergy = LogNormal(fTowerHCalEnergy, fHCalResolutionFormula->Eval(0.0, fTowerEta, 0.0, fTowerHCalEnergy));
436
[735]437 energy = ecalEnergy + hcalEnergy;
[629]438
[1145]439// eta = fTowerEta;
440// phi = fTowerPhi;
[1078]441
442 eta = gRandom->Uniform(fTowerEdges[0], fTowerEdges[1]);
443 phi = gRandom->Uniform(fTowerEdges[2], fTowerEdges[3]);
444
[1086]445 pt = energy / TMath::CosH(eta);
446
[1078]447 fTower->Position.SetPtEtaPhiE(1.0, eta, phi, 0.0);
448 fTower->Momentum.SetPtEtaPhiE(pt, eta, phi, energy);
[735]449 fTower->Eem = ecalEnergy;
450 fTower->Ehad = hcalEnergy;
[734]451
[898]452 fTower->Edges[0] = fTowerEdges[0];
453 fTower->Edges[1] = fTowerEdges[1];
454 fTower->Edges[2] = fTowerEdges[2];
455 fTower->Edges[3] = fTowerEdges[3];
[886]456
[931]457 // fill calorimeter towers and photon candidates
458 if(energy > 0.0)
459 {
[1233]460 if(fTowerPhotonHits > 0 && fTowerTrackAllHits == 0)
[935]461 {
[931]462 fPhotonOutputArray->Add(fTower);
463 }
464
465 fTowerOutputArray->Add(fTower);
466 }
[935]467
[931]468 // fill energy flow candidates
[1233]469 if(fTowerTrackAllHits == fTowerAllHits)
[735]470 {
[886]471 fItTowerTrackArray->Reset();
472 while((track = static_cast<Candidate*>(fItTowerTrackArray->Next())))
473 {
[938]474 fEFlowTrackOutputArray->Add(track);
[886]475 }
476 }
[1233]477 else if(fTowerTrackAllHits > 0 &&
478 fTowerECalHits + fTowerHCalHits == fTowerAllHits &&
479 (fTowerECalHits == fTowerECalTrackHits || fTowerHCalHits == fTowerHCalTrackHits))
[931]480 {
[1233]481 if(fTowerECalHits == fTowerECalTrackHits)
[931]482 {
[1233]483 fItTowerECalTrackArray->Reset();
484 while((track = static_cast<Candidate*>(fItTowerECalTrackArray->Next())))
485 {
486 fEFlowTrackOutputArray->Add(track);
487 }
488 energy = hcalEnergy;
489 iterator = fItTowerHCalArray;
[931]490 }
[735]491
[1233]492 if(fTowerHCalHits == fTowerHCalTrackHits)
[931]493 {
[1233]494 fItTowerHCalTrackArray->Reset();
495 while((track = static_cast<Candidate*>(fItTowerHCalTrackArray->Next())))
496 {
497 fEFlowTrackOutputArray->Add(track);
498 }
499 energy = ecalEnergy;
500 iterator = fItTowerECalArray;
501 }
502
503 if(energy > 0.0 && iterator)
504 {
[931]505 DelphesFactory *factory = GetFactory();
[935]506
[931]507 // create new tower
508 tower = factory->NewCandidate();
[735]509
[1233]510 iterator->Reset();
511 while((particle = static_cast<Candidate*>(iterator->Next())))
[934]512 {
513 tower->AddCandidate(particle);
514 }
[935]515
[1233]516 pt = energy / TMath::CosH(eta);
[1084]517
[1078]518 tower->Position.SetPtEtaPhiE(1.0, eta, phi, 0.0);
[1233]519 tower->Momentum.SetPtEtaPhiE(pt, eta, phi, energy);
520 tower->Eem = energy;
[931]521 tower->Ehad = 0.0;
522
523 tower->Edges[0] = fTowerEdges[0];
524 tower->Edges[1] = fTowerEdges[1];
525 tower->Edges[2] = fTowerEdges[2];
526 tower->Edges[3] = fTowerEdges[3];
527
[938]528 fEFlowTowerOutputArray->Add(tower);
[931]529 }
530 }
531 else if(energy > 0.0)
532 {
[938]533 fEFlowTowerOutputArray->Add(fTower);
[931]534 }
[608]535}
536
537//------------------------------------------------------------------------------
[1142]538
[1145]539Double_t Calorimeter::LogNormal(Double_t mean, Double_t sigma)
540{
541 Double_t a, b;
542
543 if(mean > 0.0)
[1142]544 {
[1145]545 b = TMath::Sqrt(TMath::Log((1.0 + (sigma*sigma)/(mean*mean))));
546 a = TMath::Log(mean) - 0.5*b*b;
547
548 return TMath::Exp(a + b*gRandom->Gaus(0, 1));
[1142]549 }
[1145]550 else
551 {
552 return 0.0;
553 }
554}
Note: See TracBrowser for help on using the repository browser.