Fork me on GitHub

source: git/modules/Calorimeter.cc@ d1678fd

Last change on this file since d1678fd was d1678fd, checked in by michele <michele.selvaggi@…>, 4 years ago

fix weighted time and tower position in calorimeter modules

  • Property mode set to 100644
File size: 21.3 KB
RevLine 
[01f457a]1/*
2 * Delphes: a framework for fast simulation of a generic collider experiment
3 * Copyright (C) 2012-2014 Universite catholique de Louvain (UCL), Belgium
[1fa50c2]4 *
[01f457a]5 * This program is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation, either version 3 of the License, or
8 * (at your option) any later version.
[1fa50c2]9 *
[01f457a]10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
[1fa50c2]14 *
[01f457a]15 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
17 */
18
[d7d2da3]19/** \class Calorimeter
20 *
21 * Fills calorimeter towers, performs calorimeter resolution smearing,
[d4c4d9d]22 * and creates energy flow objects (tracks, photons, and neutral hadrons).
[d7d2da3]23 *
24 * \author P. Demin - UCL, Louvain-la-Neuve
25 *
26 */
27
28#include "modules/Calorimeter.h"
29
30#include "classes/DelphesClasses.h"
31#include "classes/DelphesFactory.h"
32#include "classes/DelphesFormula.h"
33
34#include "ExRootAnalysis/ExRootClassifier.h"
[341014c]35#include "ExRootAnalysis/ExRootFilter.h"
36#include "ExRootAnalysis/ExRootResult.h"
[d7d2da3]37
38#include "TDatabasePDG.h"
[341014c]39#include "TFormula.h"
[d7d2da3]40#include "TLorentzVector.h"
[341014c]41#include "TMath.h"
42#include "TObjArray.h"
43#include "TRandom3.h"
44#include "TString.h"
[d7d2da3]45
46#include <algorithm>
47#include <iostream>
48#include <sstream>
[341014c]49#include <stdexcept>
[d7d2da3]50
51using namespace std;
52
53//------------------------------------------------------------------------------
54
55Calorimeter::Calorimeter() :
[82575a3]56 fECalResolutionFormula(0), fHCalResolutionFormula(0),
[00e8dca]57 fItParticleInputArray(0), fItTrackInputArray(0)
[d7d2da3]58{
[341014c]59
[82575a3]60 fECalResolutionFormula = new DelphesFormula;
61 fHCalResolutionFormula = new DelphesFormula;
62
[04290b1]63 fECalTowerTrackArray = new TObjArray;
64 fItECalTowerTrackArray = fECalTowerTrackArray->MakeIterator();
[00e8dca]65
[04290b1]66 fHCalTowerTrackArray = new TObjArray;
67 fItHCalTowerTrackArray = fHCalTowerTrackArray->MakeIterator();
[d7d2da3]68}
69
70//------------------------------------------------------------------------------
71
72Calorimeter::~Calorimeter()
73{
[341014c]74
[82575a3]75 if(fECalResolutionFormula) delete fECalResolutionFormula;
76 if(fHCalResolutionFormula) delete fHCalResolutionFormula;
77
[04290b1]78 if(fECalTowerTrackArray) delete fECalTowerTrackArray;
79 if(fItECalTowerTrackArray) delete fItECalTowerTrackArray;
[00e8dca]80
[04290b1]81 if(fHCalTowerTrackArray) delete fHCalTowerTrackArray;
82 if(fItHCalTowerTrackArray) delete fItHCalTowerTrackArray;
[2dab783]83}
[d7d2da3]84
85//------------------------------------------------------------------------------
86
87void Calorimeter::Init()
88{
89 ExRootConfParam param, paramEtaBins, paramPhiBins, paramFractions;
[a221d1f]90 Long_t i, j, k, size, sizeEtaBins, sizePhiBins;
[82575a3]91 Double_t ecalFraction, hcalFraction;
[d7d2da3]92 TBinMap::iterator itEtaBin;
[341014c]93 set<Double_t>::iterator itPhiBin;
94 vector<Double_t> *phiBins;
[d7d2da3]95
96 // read eta and phi bins
97 param = GetParam("EtaPhiBins");
98 size = param.GetSize();
99 fBinMap.clear();
100 fEtaBins.clear();
101 fPhiBins.clear();
[341014c]102 for(i = 0; i < size / 2; ++i)
[d7d2da3]103 {
[341014c]104 paramEtaBins = param[i * 2];
[d7d2da3]105 sizeEtaBins = paramEtaBins.GetSize();
[341014c]106 paramPhiBins = param[i * 2 + 1];
[d7d2da3]107 sizePhiBins = paramPhiBins.GetSize();
108
109 for(j = 0; j < sizeEtaBins; ++j)
110 {
111 for(k = 0; k < sizePhiBins; ++k)
112 {
113 fBinMap[paramEtaBins[j].GetDouble()].insert(paramPhiBins[k].GetDouble());
114 }
115 }
116 }
117
118 // for better performance we transform map of sets to parallel vectors:
119 // vector< double > and vector< vector< double >* >
120 for(itEtaBin = fBinMap.begin(); itEtaBin != fBinMap.end(); ++itEtaBin)
121 {
122 fEtaBins.push_back(itEtaBin->first);
[341014c]123 phiBins = new vector<double>(itEtaBin->second.size());
[d7d2da3]124 fPhiBins.push_back(phiBins);
125 phiBins->clear();
126 for(itPhiBin = itEtaBin->second.begin(); itPhiBin != itEtaBin->second.end(); ++itPhiBin)
127 {
128 phiBins->push_back(*itPhiBin);
129 }
130 }
131
132 // read energy fractions for different particles
133 param = GetParam("EnergyFraction");
134 size = param.GetSize();
135
136 // set default energy fractions values
137 fFractionMap.clear();
[82575a3]138 fFractionMap[0] = make_pair(0.0, 1.0);
[d7d2da3]139
[341014c]140 for(i = 0; i < size / 2; ++i)
[d7d2da3]141 {
[341014c]142 paramFractions = param[i * 2 + 1];
[82575a3]143
144 ecalFraction = paramFractions[0].GetDouble();
145 hcalFraction = paramFractions[1].GetDouble();
146
[341014c]147 fFractionMap[param[i * 2].GetInt()] = make_pair(ecalFraction, hcalFraction);
[d7d2da3]148 }
[8624f58]149
[3db5282]150 // read min E value for timing measurement in ECAL
[341014c]151 fTimingEnergyMin = GetDouble("TimingEnergyMin", 4.);
[3db5282]152 // For timing
153 // So far this flag needs to be false
154 // Curved extrapolation not supported
155 fElectronsFromTrack = false;
156
[4b9a2dc]157 // read min E value for towers to be saved
[38bf1ae]158 fECalEnergyMin = GetDouble("ECalEnergyMin", 0.0);
159 fHCalEnergyMin = GetDouble("HCalEnergyMin", 0.0);
[a221d1f]160
[38bf1ae]161 fECalEnergySignificanceMin = GetDouble("ECalEnergySignificanceMin", 0.0);
162 fHCalEnergySignificanceMin = GetDouble("HCalEnergySignificanceMin", 0.0);
[a221d1f]163
[8624f58]164 // switch on or off the dithering of the center of calorimeter towers
[4e09c3a]165 fSmearTowerCenter = GetBool("SmearTowerCenter", true);
[4b9a2dc]166
[d7d2da3]167 // read resolution formulas
[82575a3]168 fECalResolutionFormula->Compile(GetString("ECalResolutionFormula", "0"));
169 fHCalResolutionFormula->Compile(GetString("HCalResolutionFormula", "0"));
170
[d7d2da3]171 // import array with output from other modules
172 fParticleInputArray = ImportArray(GetString("ParticleInputArray", "ParticlePropagator/particles"));
173 fItParticleInputArray = fParticleInputArray->MakeIterator();
174
175 fTrackInputArray = ImportArray(GetString("TrackInputArray", "ParticlePropagator/tracks"));
176 fItTrackInputArray = fTrackInputArray->MakeIterator();
177
178 // create output arrays
179 fTowerOutputArray = ExportArray(GetString("TowerOutputArray", "towers"));
[82575a3]180 fPhotonOutputArray = ExportArray(GetString("PhotonOutputArray", "photons"));
[a221d1f]181
[82575a3]182 fEFlowTrackOutputArray = ExportArray(GetString("EFlowTrackOutputArray", "eflowTracks"));
183 fEFlowPhotonOutputArray = ExportArray(GetString("EFlowPhotonOutputArray", "eflowPhotons"));
184 fEFlowNeutralHadronOutputArray = ExportArray(GetString("EFlowNeutralHadronOutputArray", "eflowNeutralHadrons"));
[d7d2da3]185}
186
187//------------------------------------------------------------------------------
188
189void Calorimeter::Finish()
190{
[341014c]191 vector<vector<Double_t> *>::iterator itPhiBin;
[d7d2da3]192 if(fItParticleInputArray) delete fItParticleInputArray;
193 if(fItTrackInputArray) delete fItTrackInputArray;
194 for(itPhiBin = fPhiBins.begin(); itPhiBin != fPhiBins.end(); ++itPhiBin)
195 {
196 delete *itPhiBin;
197 }
198}
199
200//------------------------------------------------------------------------------
201
202void Calorimeter::Process()
203{
204 Candidate *particle, *track;
205 TLorentzVector position, momentum;
206 Short_t etaBin, phiBin, flags;
207 Int_t number;
208 Long64_t towerHit, towerEtaPhi, hitEtaPhi;
[82575a3]209 Double_t ecalFraction, hcalFraction;
210 Double_t ecalEnergy, hcalEnergy;
[298734e]211 Double_t ecalSigma, hcalSigma;
212 Double_t energyGuess;
[d7d2da3]213 Int_t pdgCode;
214
215 TFractionMap::iterator itFractionMap;
216
[341014c]217 vector<Double_t>::iterator itEtaBin;
218 vector<Double_t>::iterator itPhiBin;
219 vector<Double_t> *phiBins;
[d7d2da3]220
[341014c]221 vector<Long64_t>::iterator itTowerHits;
[d7d2da3]222
223 DelphesFactory *factory = GetFactory();
224 fTowerHits.clear();
[00e8dca]225 fECalTowerFractions.clear();
226 fHCalTowerFractions.clear();
227 fECalTrackFractions.clear();
228 fHCalTrackFractions.clear();
[82575a3]229
[d7d2da3]230 // loop over all particles
231 fItParticleInputArray->Reset();
232 number = -1;
[341014c]233 while((particle = static_cast<Candidate *>(fItParticleInputArray->Next())))
[d7d2da3]234 {
235 const TLorentzVector &particlePosition = particle->Position;
236 ++number;
237
238 pdgCode = TMath::Abs(particle->PID);
239
240 itFractionMap = fFractionMap.find(pdgCode);
241 if(itFractionMap == fFractionMap.end())
242 {
243 itFractionMap = fFractionMap.find(0);
244 }
245
[82575a3]246 ecalFraction = itFractionMap->second.first;
247 hcalFraction = itFractionMap->second.second;
248
[00e8dca]249 fECalTowerFractions.push_back(ecalFraction);
250 fHCalTowerFractions.push_back(hcalFraction);
[82575a3]251
252 if(ecalFraction < 1.0E-9 && hcalFraction < 1.0E-9) continue;
[d7d2da3]253
254 // find eta bin [1, fEtaBins.size - 1]
255 itEtaBin = lower_bound(fEtaBins.begin(), fEtaBins.end(), particlePosition.Eta());
256 if(itEtaBin == fEtaBins.begin() || itEtaBin == fEtaBins.end()) continue;
257 etaBin = distance(fEtaBins.begin(), itEtaBin);
258
259 // phi bins for given eta bin
260 phiBins = fPhiBins[etaBin];
261
262 // find phi bin [1, phiBins.size - 1]
263 itPhiBin = lower_bound(phiBins->begin(), phiBins->end(), particlePosition.Phi());
264 if(itPhiBin == phiBins->begin() || itPhiBin == phiBins->end()) continue;
265 phiBin = distance(phiBins->begin(), itPhiBin);
266
[73e0386]267 flags = 0;
[2dab783]268 flags |= (pdgCode == 11 || pdgCode == 22) << 1;
[d7d2da3]269
270 // make tower hit {16-bits for eta bin number, 16-bits for phi bin number, 8-bits for flags, 24-bits for particle number}
271 towerHit = (Long64_t(etaBin) << 48) | (Long64_t(phiBin) << 32) | (Long64_t(flags) << 24) | Long64_t(number);
272
273 fTowerHits.push_back(towerHit);
274 }
275
276 // loop over all tracks
277 fItTrackInputArray->Reset();
278 number = -1;
[341014c]279 while((track = static_cast<Candidate *>(fItTrackInputArray->Next())))
[d7d2da3]280 {
281 const TLorentzVector &trackPosition = track->Position;
282 ++number;
283
[73e0386]284 pdgCode = TMath::Abs(track->PID);
285
286 itFractionMap = fFractionMap.find(pdgCode);
287 if(itFractionMap == fFractionMap.end())
288 {
289 itFractionMap = fFractionMap.find(0);
290 }
291
[82575a3]292 ecalFraction = itFractionMap->second.first;
293 hcalFraction = itFractionMap->second.second;
294
[00e8dca]295 fECalTrackFractions.push_back(ecalFraction);
296 fHCalTrackFractions.push_back(hcalFraction);
[82575a3]297
[d7d2da3]298 // find eta bin [1, fEtaBins.size - 1]
299 itEtaBin = lower_bound(fEtaBins.begin(), fEtaBins.end(), trackPosition.Eta());
300 if(itEtaBin == fEtaBins.begin() || itEtaBin == fEtaBins.end()) continue;
301 etaBin = distance(fEtaBins.begin(), itEtaBin);
302
303 // phi bins for given eta bin
304 phiBins = fPhiBins[etaBin];
305
306 // find phi bin [1, phiBins.size - 1]
307 itPhiBin = lower_bound(phiBins->begin(), phiBins->end(), trackPosition.Phi());
308 if(itPhiBin == phiBins->begin() || itPhiBin == phiBins->end()) continue;
309 phiBin = distance(phiBins->begin(), itPhiBin);
310
[73e0386]311 flags = 1;
312
[d7d2da3]313 // make tower hit {16-bits for eta bin number, 16-bits for phi bin number, 8-bits for flags, 24-bits for track number}
[73e0386]314 towerHit = (Long64_t(etaBin) << 48) | (Long64_t(phiBin) << 32) | (Long64_t(flags) << 24) | Long64_t(number);
[d7d2da3]315
316 fTowerHits.push_back(towerHit);
317 }
318
319 // all hits are sorted first by eta bin number, then by phi bin number,
320 // then by flags and then by particle or track number
321 sort(fTowerHits.begin(), fTowerHits.end());
322
323 // loop over all hits
324 towerEtaPhi = 0;
325 fTower = 0;
326 for(itTowerHits = fTowerHits.begin(); itTowerHits != fTowerHits.end(); ++itTowerHits)
327 {
328 towerHit = (*itTowerHits);
329 flags = (towerHit >> 24) & 0x00000000000000FFLL;
[341014c]330 number = (towerHit)&0x0000000000FFFFFFLL;
[d7d2da3]331 hitEtaPhi = towerHit >> 32;
332
333 if(towerEtaPhi != hitEtaPhi)
334 {
335 // switch to next tower
336 towerEtaPhi = hitEtaPhi;
337
338 // finalize previous tower
339 FinalizeTower();
340
341 // create new tower
342 fTower = factory->NewCandidate();
343
344 phiBin = (towerHit >> 32) & 0x000000000000FFFFLL;
345 etaBin = (towerHit >> 48) & 0x000000000000FFFFLL;
346
347 // phi bins for given eta bin
348 phiBins = fPhiBins[etaBin];
349
350 // calculate eta and phi of the tower's center
[341014c]351 fTowerEta = 0.5 * (fEtaBins[etaBin - 1] + fEtaBins[etaBin]);
352 fTowerPhi = 0.5 * ((*phiBins)[phiBin - 1] + (*phiBins)[phiBin]);
[d7d2da3]353
354 fTowerEdges[0] = fEtaBins[etaBin - 1];
355 fTowerEdges[1] = fEtaBins[etaBin];
356 fTowerEdges[2] = (*phiBins)[phiBin - 1];
357 fTowerEdges[3] = (*phiBins)[phiBin];
358
[00e8dca]359 fECalTowerEnergy = 0.0;
360 fHCalTowerEnergy = 0.0;
361
[04290b1]362 fECalTrackEnergy = 0.0;
363 fHCalTrackEnergy = 0.0;
[341014c]364
[04290b1]365 fECalTrackSigma = 0.0;
366 fHCalTrackSigma = 0.0;
[341014c]367
[2dab783]368 fTowerTrackHits = 0;
369 fTowerPhotonHits = 0;
[a221d1f]370
[04290b1]371 fECalTowerTrackArray->Clear();
372 fHCalTowerTrackArray->Clear();
[d7d2da3]373 }
374
375 // check for track hits
[73e0386]376 if(flags & 1)
[d7d2da3]377 {
[2dab783]378 ++fTowerTrackHits;
[73e0386]379
[341014c]380 track = static_cast<Candidate *>(fTrackInputArray->At(number));
[2dab783]381 momentum = track->Momentum;
[22dc7fd]382 position = track->Position;
[82575a3]383
[00e8dca]384 ecalEnergy = momentum.E() * fECalTrackFractions[number];
385 hcalEnergy = momentum.E() * fHCalTrackFractions[number];
[a221d1f]386
[839deb7]387 if(ecalEnergy > fTimingEnergyMin && fTower)
388 {
389 if(fElectronsFromTrack)
390 {
391 fTower->ECalEnergyTimePairs.push_back(make_pair<Float_t, Float_t>(ecalEnergy, track->Position.T()));
392 }
[3db5282]393 }
[a221d1f]394
[9da65a5]395 if(fECalTrackFractions[number] > 1.0E-9 && fHCalTrackFractions[number] < 1.0E-9)
[00e8dca]396 {
[04290b1]397 fECalTrackEnergy += ecalEnergy;
[341014c]398 ecalSigma = fECalResolutionFormula->Eval(0.0, fTowerEta, 0.0, momentum.E());
399 if(ecalSigma / momentum.E() < track->TrackResolution)
400 energyGuess = ecalEnergy;
401 else
402 energyGuess = momentum.E();
[298734e]403
[341014c]404 fECalTrackSigma += (track->TrackResolution) * energyGuess * (track->TrackResolution) * energyGuess;
[04290b1]405 fECalTowerTrackArray->Add(track);
[00e8dca]406 }
[341014c]407
[9da65a5]408 else if(fECalTrackFractions[number] < 1.0E-9 && fHCalTrackFractions[number] > 1.0E-9)
[00e8dca]409 {
[04290b1]410 fHCalTrackEnergy += hcalEnergy;
[298734e]411 hcalSigma = fHCalResolutionFormula->Eval(0.0, fTowerEta, 0.0, momentum.E());
[341014c]412 if(hcalSigma / momentum.E() < track->TrackResolution)
413 energyGuess = hcalEnergy;
414 else
415 energyGuess = momentum.E();
[298734e]416
[341014c]417 fHCalTrackSigma += (track->TrackResolution) * energyGuess * (track->TrackResolution) * energyGuess;
[04290b1]418 fHCalTowerTrackArray->Add(track);
[00e8dca]419 }
[341014c]420
[9da65a5]421 else if(fECalTrackFractions[number] < 1.0E-9 && fHCalTrackFractions[number] < 1.0E-9)
422 {
423 fEFlowTrackOutputArray->Add(track);
424 }
[73e0386]425
[2dab783]426 continue;
[73e0386]427 }
[839deb7]428
[73e0386]429 // check for photon and electron hits in current tower
[2dab783]430 if(flags & 2) ++fTowerPhotonHits;
[a221d1f]431
[341014c]432 particle = static_cast<Candidate *>(fParticleInputArray->At(number));
[d7d2da3]433 momentum = particle->Momentum;
[22dc7fd]434 position = particle->Position;
[d7d2da3]435
436 // fill current tower
[00e8dca]437 ecalEnergy = momentum.E() * fECalTowerFractions[number];
438 hcalEnergy = momentum.E() * fHCalTowerFractions[number];
[82575a3]439
[00e8dca]440 fECalTowerEnergy += ecalEnergy;
441 fHCalTowerEnergy += hcalEnergy;
[82575a3]442
[839deb7]443 if(ecalEnergy > fTimingEnergyMin && fTower)
444 {
[341014c]445 if(abs(particle->PID) != 11 || !fElectronsFromTrack)
[839deb7]446 {
447 fTower->ECalEnergyTimePairs.push_back(make_pair<Float_t, Float_t>(ecalEnergy, particle->Position.T()));
[3db5282]448 }
449 }
[82575a3]450
[3079350]451 fTower->AddCandidate(particle);
[d1678fd]452 fTower->Position = position;
[d7d2da3]453 }
454
455 // finalize last tower
456 FinalizeTower();
457}
458
459//------------------------------------------------------------------------------
460
461void Calorimeter::FinalizeTower()
462{
[e2dd4c5]463 Candidate *track, *tower, *mother;
[d1678fd]464 Double_t energy, pt, eta, phi, r;
[82575a3]465 Double_t ecalEnergy, hcalEnergy;
[04290b1]466 Double_t ecalNeutralEnergy, hcalNeutralEnergy;
[341014c]467
[82575a3]468 Double_t ecalSigma, hcalSigma;
[04290b1]469 Double_t ecalNeutralSigma, hcalNeutralSigma;
[e2dd4c5]470
[04290b1]471 Double_t weightTrack, weightCalo, bestEnergyEstimate, rescaleFactor;
[341014c]472
[a98c7ef]473 TLorentzVector momentum;
474 TFractionMap::iterator itFractionMap;
[e2dd4c5]475
[839deb7]476 Float_t weight, sumWeightedTime, sumWeight;
477
[d7d2da3]478 if(!fTower) return;
479
[00e8dca]480 ecalSigma = fECalResolutionFormula->Eval(0.0, fTowerEta, 0.0, fECalTowerEnergy);
481 hcalSigma = fHCalResolutionFormula->Eval(0.0, fTowerEta, 0.0, fHCalTowerEnergy);
[4600a41]482
[00e8dca]483 ecalEnergy = LogNormal(fECalTowerEnergy, ecalSigma);
484 hcalEnergy = LogNormal(fHCalTowerEnergy, hcalSigma);
[82575a3]485
[4b9a2dc]486 ecalSigma = fECalResolutionFormula->Eval(0.0, fTowerEta, 0.0, ecalEnergy);
487 hcalSigma = fHCalResolutionFormula->Eval(0.0, fTowerEta, 0.0, hcalEnergy);
488
[341014c]489 if(ecalEnergy < fECalEnergyMin || ecalEnergy < fECalEnergySignificanceMin * ecalSigma) ecalEnergy = 0.0;
490 if(hcalEnergy < fHCalEnergyMin || hcalEnergy < fHCalEnergySignificanceMin * hcalSigma) hcalEnergy = 0.0;
[4b9a2dc]491
[82575a3]492 energy = ecalEnergy + hcalEnergy;
[839deb7]493
[4e09c3a]494 if(fSmearTowerCenter)
[a221d1f]495 {
[38bf1ae]496 eta = gRandom->Uniform(fTowerEdges[0], fTowerEdges[1]);
497 phi = gRandom->Uniform(fTowerEdges[2], fTowerEdges[3]);
[a221d1f]498 }
499 else
500 {
[38bf1ae]501 eta = fTowerEta;
502 phi = fTowerPhi;
[a221d1f]503 }
[d7d2da3]504
505 pt = energy / TMath::CosH(eta);
506
[3db5282]507 // Time calculation for tower
[839deb7]508 fTower->NTimeHits = 0;
509 sumWeightedTime = 0.0;
510 sumWeight = 0.0;
511
512 for(size_t i = 0; i < fTower->ECalEnergyTimePairs.size(); ++i)
[3db5282]513 {
[d1678fd]514 weight = TMath::Power((fTower->ECalEnergyTimePairs[i].first),2);
[839deb7]515 sumWeightedTime += weight * fTower->ECalEnergyTimePairs[i].second;
516 sumWeight += weight;
517 fTower->NTimeHits++;
[3db5282]518 }
[839deb7]519
[d1678fd]520 r = TMath::Sqrt(fTower->Position.X()*fTower->Position.X()+fTower->Position.Y()*fTower->Position.Y());
521
[839deb7]522 if(sumWeight > 0.0)
523 {
[d1678fd]524 fTower->Position.SetPtEtaPhiE(r, eta, phi, sumWeightedTime / sumWeight);
[839deb7]525 }
526 else
527 {
[d1678fd]528 fTower->Position.SetPtEtaPhiE(r, eta, phi, 999999.9);
[3db5282]529 }
530
[d7d2da3]531 fTower->Momentum.SetPtEtaPhiE(pt, eta, phi, energy);
[82575a3]532 fTower->Eem = ecalEnergy;
533 fTower->Ehad = hcalEnergy;
534
[d7d2da3]535 fTower->Edges[0] = fTowerEdges[0];
536 fTower->Edges[1] = fTowerEdges[1];
537 fTower->Edges[2] = fTowerEdges[2];
538 fTower->Edges[3] = fTowerEdges[3];
539
[38bf1ae]540 if(energy > 0.0)
[82575a3]541 {
542 if(fTowerPhotonHits > 0 && fTowerTrackHits == 0)
543 {
544 fPhotonOutputArray->Add(fTower);
545 }
[a221d1f]546
[82575a3]547 fTowerOutputArray->Add(fTower);
548 }
[341014c]549
[f6b9fec]550 // fill energy flow candidates
[04290b1]551 fECalTrackSigma = TMath::Sqrt(fECalTrackSigma);
552 fHCalTrackSigma = TMath::Sqrt(fHCalTrackSigma);
553
554 //compute neutral excesses
[341014c]555 ecalNeutralEnergy = max((ecalEnergy - fECalTrackEnergy), 0.0);
556 hcalNeutralEnergy = max((hcalEnergy - fHCalTrackEnergy), 0.0);
557
558 ecalNeutralSigma = ecalNeutralEnergy / TMath::Sqrt(fECalTrackSigma * fECalTrackSigma + ecalSigma * ecalSigma);
559 hcalNeutralSigma = hcalNeutralEnergy / TMath::Sqrt(fHCalTrackSigma * fHCalTrackSigma + hcalSigma * hcalSigma);
560
561 // if ecal neutral excess is significant, simply create neutral EflowPhoton tower and clone each track into eflowtrack
[04290b1]562 if(ecalNeutralEnergy > fECalEnergyMin && ecalNeutralSigma > fECalEnergySignificanceMin)
[00e8dca]563 {
[fd4b326]564 // create new photon tower assuming null mass
[341014c]565 tower = static_cast<Candidate *>(fTower->Clone());
566 pt = ecalNeutralEnergy / TMath::CosH(eta);
567
[04290b1]568 tower->Momentum.SetPtEtaPhiE(pt, eta, phi, ecalNeutralEnergy);
569 tower->Eem = ecalNeutralEnergy;
570 tower->Ehad = 0.0;
[efac6f9]571 tower->PID = 22;
[341014c]572
[04290b1]573 fEFlowPhotonOutputArray->Add(tower);
[341014c]574
[04290b1]575 //clone tracks
576 fItECalTowerTrackArray->Reset();
[341014c]577 while((track = static_cast<Candidate *>(fItECalTowerTrackArray->Next())))
[04290b1]578 {
579 mother = track;
[341014c]580 track = static_cast<Candidate *>(track->Clone());
[04290b1]581 track->AddCandidate(mother);
[e2dd4c5]582
[04290b1]583 fEFlowTrackOutputArray->Add(track);
584 }
[82575a3]585 }
[341014c]586
[04290b1]587 // if neutral excess is not significant, rescale eflow tracks, such that the total charged equals the best measurement given by the calorimeter and tracking
588 else if(fECalTrackEnergy > 0.0)
[00e8dca]589 {
[341014c]590 weightTrack = (fECalTrackSigma > 0.0) ? 1 / (fECalTrackSigma * fECalTrackSigma) : 0.0;
591 weightCalo = (ecalSigma > 0.0) ? 1 / (ecalSigma * ecalSigma) : 0.0;
592
593 bestEnergyEstimate = (weightTrack * fECalTrackEnergy + weightCalo * ecalEnergy) / (weightTrack + weightCalo);
594 rescaleFactor = bestEnergyEstimate / fECalTrackEnergy;
[04290b1]595
596 //rescale tracks
597 fItECalTowerTrackArray->Reset();
[341014c]598 while((track = static_cast<Candidate *>(fItECalTowerTrackArray->Next())))
599 {
[04290b1]600 mother = track;
[341014c]601 track = static_cast<Candidate *>(track->Clone());
[04290b1]602 track->AddCandidate(mother);
603
604 track->Momentum *= rescaleFactor;
605
606 fEFlowTrackOutputArray->Add(track);
607 }
[00e8dca]608 }
[e2dd4c5]609
[04290b1]610 // if hcal neutral excess is significant, simply create neutral EflowNeutralHadron tower and clone each track into eflowtrack
611 if(hcalNeutralEnergy > fHCalEnergyMin && hcalNeutralSigma > fHCalEnergySignificanceMin)
[2dab783]612 {
[d4c4d9d]613 // create new photon tower
[341014c]614 tower = static_cast<Candidate *>(fTower->Clone());
615 pt = hcalNeutralEnergy / TMath::CosH(eta);
616
[04290b1]617 tower->Momentum.SetPtEtaPhiE(pt, eta, phi, hcalNeutralEnergy);
618 tower->Ehad = hcalNeutralEnergy;
619 tower->Eem = 0.0;
[341014c]620
[04290b1]621 fEFlowNeutralHadronOutputArray->Add(tower);
[341014c]622
[04290b1]623 //clone tracks
624 fItHCalTowerTrackArray->Reset();
[341014c]625 while((track = static_cast<Candidate *>(fItHCalTowerTrackArray->Next())))
[04290b1]626 {
627 mother = track;
[341014c]628 track = static_cast<Candidate *>(track->Clone());
[04290b1]629 track->AddCandidate(mother);
[0d5f77c]630
[04290b1]631 fEFlowTrackOutputArray->Add(track);
632 }
[82575a3]633 }
[341014c]634
[04290b1]635 // if neutral excess is not significant, rescale eflow tracks, such that the total charged equals the best measurement given by the calorimeter and tracking
636 else if(fHCalTrackEnergy > 0.0)
[82575a3]637 {
[341014c]638 weightTrack = (fHCalTrackSigma > 0.0) ? 1 / (fHCalTrackSigma * fHCalTrackSigma) : 0.0;
639 weightCalo = (hcalSigma > 0.0) ? 1 / (hcalSigma * hcalSigma) : 0.0;
640
641 bestEnergyEstimate = (weightTrack * fHCalTrackEnergy + weightCalo * hcalEnergy) / (weightTrack + weightCalo);
[04290b1]642 rescaleFactor = bestEnergyEstimate / fHCalTrackEnergy;
643
644 //rescale tracks
[b6e6d36]645 fItHCalTowerTrackArray->Reset();
[341014c]646 while((track = static_cast<Candidate *>(fItHCalTowerTrackArray->Next())))
647 {
[04290b1]648 mother = track;
[341014c]649 track = static_cast<Candidate *>(track->Clone());
[04290b1]650 track->AddCandidate(mother);
651 track->Momentum *= rescaleFactor;
[fd4b326]652 track->Momentum.SetPtEtaPhiM(track->Momentum.Pt()*rescaleFactor, track->Momentum.Eta(), track->Momentum.Phi(), track->Momentum.M());
[04290b1]653
654 fEFlowTrackOutputArray->Add(track);
655 }
[d7d2da3]656 }
657}
658
659//------------------------------------------------------------------------------
[39022b6]660
[4600a41]661Double_t Calorimeter::LogNormal(Double_t mean, Double_t sigma)
662{
663 Double_t a, b;
664
665 if(mean > 0.0)
[39022b6]666 {
[341014c]667 b = TMath::Sqrt(TMath::Log((1.0 + (sigma * sigma) / (mean * mean))));
668 a = TMath::Log(mean) - 0.5 * b * b;
[4600a41]669
[341014c]670 return TMath::Exp(a + b * gRandom->Gaus(0.0, 1.0));
[39022b6]671 }
[4600a41]672 else
673 {
674 return 0.0;
675 }
676}
Note: See TracBrowser for help on using the repository browser.