Fork me on GitHub

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

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

new energy flow that compiles

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