46 {
47 const EventContext& ctx = Gaudi::Hive::currentContext();
48
49
50
51
52
53
54
55
56
57
58
59
62 E_FSR = 0.;
63 E_expected = 0.;
64
65 E_em_meas = 0.;
66 E_em_exp = 0.;
67 E_tile_meas = 0.;
68 E_tile_exp = 0.;
69 E_HEC_meas = 0.;
70 E_HEC_exp = 0.;
71 E_dead_exp = 0.;
72
73 bool storeCells = false;
74 if (crossedCells != nullptr && sigmaNoise_cell != nullptr && E_exp_cell != nullptr) {
75 storeCells = true;
76 crossedCells->clear();
77 sigmaNoise_cell->clear();
78 E_exp_cell->clear();
79 }
80
81
82
83
84
85
86
87
88
89
90
91 if (!trk) return;
94
95
96
97
98 double mopIoni = meanIoni;
99
100 double scale_Ionization = 0.9;
101 if (std::abs(deltaE) > 0 && std::abs(meanIoni) > 0) scale_Ionization = mopIoni / deltaE;
102 double error_ratio = 0.3;
103 if (std::abs(meanIoni) > 0 && sigmaIoni > 0) error_ratio = 3.59524 * std::abs(sigmaIoni / meanIoni);
104
105 ATH_MSG_DEBUG(
" Inputs deltaE " << deltaE <<
" meanIoni " << meanIoni <<
" sigmaIoni " << sigmaIoni <<
" scale_Ionization "
106 << scale_Ionization << " error_ratio " << error_ratio);
107 if (deltaE == 0 || meanIoni == 0 || sigmaIoni < 0)
108 ATH_MSG_WARNING(
" Strange Inputs deltaE " << deltaE <<
" meanIoni " << meanIoni <<
" sigmaIoni " << sigmaIoni);
109
110
111
113
115 if (indetTrackParticles.isValid()) {
116
117 for (const auto *it : *indetTrackParticles) {
118 if ((*it).track() == trk) {
120 break;
121 }
122 }
123 if (tp)
ATH_MSG_DEBUG(
" ID xAOD::TrackParticle found " << tp);
124 } else {
126 }
127
128
129
131 if (!tp && muonTrackParticles.isValid()) {
132 for (const auto *it : *muonTrackParticles) {
133 if ((*it).track() == trk) {
135 break;
136 }
137 }
138 if (tp)
ATH_MSG_DEBUG(
" Muon xAOD::TrackParticle found " << tp);
139 } else if (!tp) {
141 }
142
143 std::unique_ptr<const xAOD::TrackParticle> tpholder;
144 if (!tp) {
146
148 if (tp)
ATH_MSG_DEBUG(
" xAOD::TrackParticle created from scratch " << tp);
149 }
150
151 if (!tp) return;
152
153 std::unique_ptr<const Rec::ParticleCellAssociation>
association =
155
156 if (!association) { return; }
158
159 std::vector<std::pair<const CaloCell*, Rec::ParticleCellIntersection*> > cellIntersections =
association->cellIntersections();
160
161 const Trk::CaloExtension& caloExtension =
association->caloExtension();
162
164 ATH_MSG_DEBUG(
"calculateMuonEnergies() - No caloEntryLayerIntersection found");
165 return;
166 }
167
168 ATH_MSG_DEBUG(
" nr of cell intersections " << cellIntersections.size());
169 if (cellIntersections.size() < 3)
ATH_MSG_DEBUG(
" Strange nr of calorimeter cell intersections " << cellIntersections.size());
170
172
173 double Eloss = 0.;
174 double scaleTG = 1.0;
178 " No muonEntryLayerIntersection found and therefore the expected Eloss is not calculated properly for momentum "
180 }
181 ATH_MSG_DEBUG(
" No muonEntryLayerIntersection found and therefore the expected Eloss is not calculated properly ");
182 } else {
183 Eloss =
194 scaleTG = mopIoni / Eloss;
195 }
196 }
197
201
205
206 double scale_em_expected = 0.97;
207 double scale_tile_expected = 1.17;
208 double scale_HEC_expected = 1.11;
209
210
211
212 double EE_emB = 0.;
213 double EE_emE = 0.;
214 double EE_HEC = 0.;
215 double EE_tile = 0.;
216
217
218
219
220
221
222
223
224
225
226 for (
int i = CaloSampling::PreSamplerB;
i < CaloSampling::CaloSample::Unknown;
i++) {
231 double eLoss = 0.;
233 eLoss = eLossPair->second;
234 ATH_MSG_DEBUG(
" sample " << i <<
" eLoss " << scale_Ionization * eLoss);
235 if (i <= 3) {
236 EE_emB += scale_em_expected * scale_Ionization * eLoss;
237 } else if (i <= 7) {
238 EE_emE += scale_em_expected * scale_Ionization * eLoss;
239 } else if (i <= 11) {
240 EE_HEC += scale_HEC_expected * scale_Ionization * eLoss;
241 } else if (i <= 20) {
242 EE_tile += scale_tile_expected * scale_Ionization * eLoss;
243 }
244 }
245 }
247 double Eloss =
250 << EE_emB << " EE_emE " << EE_emE << " EE_tile " << EE_tile << " EE_HEC " << EE_HEC << " total Eloss "
251 << Eloss);
252 }
253
254
255
256 if (scaleTG != 1.0) return;
257
258
259
260
262 const CaloNoise* caloNoise = *caloNoiseHdl;
263
264 double E_em = 0.;
265 double E_em_expected = 0.;
266 double E_em_exptot = 0.;
267 double E_em_expall = 0.;
268 double E_em_threshold = 0.;
269 int nlay_em = 0;
270 double sigma_Noise_em = 0.;
271
272 double E_HEC = 0.;
273 double E_HEC_expected = 0.;
274 double E_HEC_threshold = 0.;
275 double E_HEC_exptot = 0.;
276 double E_HEC_expall = 0.;
277 int nlay_HEC = 0;
278 double sigma_Noise_HEC = 0.;
279
280 double E_tile = 0.;
281 double E_tile_expected = 0.;
282 double E_tile_threshold = 0.;
283 double E_tile_exptot = 0.;
284 double E_tile_expall = 0.;
285 int nlay_tile = 0;
286 double sigma_Noise_tile = 0.;
287
288 E_expected = 0.;
291
292 for (auto it : cellIntersections) {
293 const CaloCell* curr_cell =
it.first;
294 const Amg::Vector3D cell_vec(curr_cell->
x(),curr_cell->
y(), curr_cell->
z());
295 const double cell_perp = cell_vec.perp();
297 bool badCell = curr_cell->
badcell();
298 double cellEn = curr_cell->
energy();
299 Identifier
id = curr_cell->
ID();
300
301 double f_exp = (
it.second)->pathLength();
302 double E_exp = (
it.second)->expectedEnergyLoss();
303
304 if (f_exp > 1.) f_exp = 1.;
305
306
307
309
310
311 double dtheta = cell_vec.theta() - thetaPos;
312 double dphi = cell_vec.deltaPhi(extension_pos);
313 double celldr = curr_cell->
caloDDE()->
dr();
314 double celldz = curr_cell->
caloDDE()->
dz();
315 double celldtheta = celldr / (cell_perp ? cell_perp : 1. );
317
318 ATH_MSG_DEBUG(
" cell sampling " << cellSampling <<
" energy " << cellEn <<
" position R "
319 << cell_perp << " z "
320 << curr_cell->
z() <<
" f_exp " << f_exp <<
" E_exp " << E_exp <<
" dtheta " << dtheta
321 << " dphi " << dphi << " cell dtheta " << celldtheta << " cell dr " << celldr << " cell dz "
322 << celldz << " cell dphi " << celldphi);
323
324
325
326
327
328
329
330
331
332 if (cellSampling == CaloSampling::PreSamplerB || cellSampling == CaloSampling::PreSamplerE) {
334 if (storeCells) {
335 crossedCells->push_back(id);
336 sigmaNoise_cell->push_back(sigma_Noise);
337 E_exp_cell->push_back(scale_Ionization * f_exp * E_exp *
338 scale_em_expected);
339 }
340 }
341 }
343 E_em_exptot += scale_Ionization * f_exp * E_exp * scale_em_expected;
344 if (f_exp > 0) E_em_expall += scale_Ionization * E_exp * scale_em_expected;
346
347 E_em += cellEn;
348 E_em_expected += scale_Ionization * f_exp * E_exp * scale_em_expected;
349 ATH_MSG_VERBOSE(
" EM cell " << cellEn <<
" sigma_Noise " << sigma_Noise <<
" f_exp " << f_exp <<
" E_exp " << E_exp);
350 if (storeCells) {
351 crossedCells->push_back(id);
352 sigmaNoise_cell->push_back(sigma_Noise);
353 E_exp_cell->push_back(scale_Ionization * f_exp * E_exp * scale_em_expected);
354 }
355 }
356 if (f_exp > 0 && !badCell) nlay_em++;
357 if (f_exp > 0 && !badCell) sigma_Noise_em += sigma_Noise;
359 E_tile_exptot += scale_Ionization * f_exp * E_exp * scale_tile_expected;
360 if (f_exp > 0) E_tile_expall += scale_Ionization * E_exp * scale_tile_expected;
362
363 E_tile += cellEn;
364 E_tile_expected += scale_Ionization * f_exp * E_exp * scale_tile_expected;
365 ATH_MSG_VERBOSE(
" Tile cell " << cellEn <<
" sigma_Noise " << sigma_Noise <<
" f_exp " << f_exp <<
" E_exp " << E_exp);
366 if (storeCells) {
367 crossedCells->push_back(id);
368 sigmaNoise_cell->push_back(sigma_Noise);
369 E_exp_cell->push_back(scale_Ionization * f_exp * E_exp * scale_tile_expected);
370 }
371 }
372 if (f_exp > 0 && !badCell) nlay_tile++;
373 if (f_exp > 0 && !badCell) sigma_Noise_tile += sigma_Noise;
375 E_HEC_exptot += scale_Ionization * f_exp * E_exp * scale_HEC_expected;
376 if (f_exp > 0) E_HEC_expall += scale_Ionization * E_exp * scale_HEC_expected;
377
379
380 E_HEC += cellEn;
381 E_HEC_expected += scale_Ionization * f_exp * E_exp * scale_HEC_expected;
382 ATH_MSG_VERBOSE(
" HEC cell " << cellEn <<
" sigma_Noise " << sigma_Noise <<
" f_exp " << f_exp <<
" E_exp " << E_exp);
383 if (storeCells) {
384 crossedCells->push_back(id);
385 sigmaNoise_cell->push_back(sigma_Noise);
386 E_exp_cell->push_back(scale_Ionization * f_exp * E_exp * scale_HEC_expected);
387 }
388 }
389 if (f_exp > 0 && !badCell) nlay_HEC++;
390 if (f_exp > 0 && !badCell) sigma_Noise_HEC += sigma_Noise;
391 }
392 E_expected += scale_Ionization * f_exp * E_exp;
393 }
394 ATH_MSG_DEBUG(
" After cuts measured Energies em " << E_em <<
" tile " << E_tile <<
" HEC " << E_HEC);
395 ATH_MSG_DEBUG(
" After cuts expected Energies em " << E_em_expected <<
" tile " << E_tile_expected <<
" HEC " << E_HEC_expected);
396 ATH_MSG_DEBUG(
" No cuts with length expected Energies em " << E_em_exptot <<
" tile " << E_tile_exptot <<
" HEC " << E_HEC_exptot);
397 ATH_MSG_DEBUG(
" No cuts NO length expected Energies em " << E_em_expall <<
" tile " << E_tile_expall <<
" HEC " << E_HEC_expall);
398
399
400
401
402 double scaleError_tile = 0.20 + 0.80 * E_tile / (10000. + E_tile);
403 double scaleError_HEC = 0.20 + 0.80 * E_HEC / (10000. + E_HEC);
404 double sigma_em = std::sqrt(500. * E_em);
405 double sigma_tile = scaleError_tile * std::sqrt(1000. * E_tile);
406 double sigma_HEC = scaleError_HEC * std::sqrt(1000. * E_HEC);
407
408
409
413 ATH_MSG_DEBUG(
" e.m. to Muon scale measured Energies em " << E_em <<
" tile " << E_tile <<
" HEC " << E_HEC);
414
415
416
420
421
422
423 if (nlay_em > 0) sigma_Noise_em /= nlay_em;
424 if (nlay_tile > 0) sigma_Noise_tile /= nlay_tile;
425 if (nlay_HEC > 0) sigma_Noise_HEC /= nlay_HEC;
426 ATH_MSG_DEBUG(
" Average Noise em " << sigma_Noise_em <<
" nlay " << nlay_em <<
" tile " << sigma_Noise_tile <<
" nlay "
427 << nlay_tile << " HEC " << sigma_Noise_HEC << " nlay " << nlay_HEC);
428
429
430
434
435 ATH_MSG_DEBUG(
" Threshold correction to Energies em " << E_em_threshold <<
" tile " << E_tile_threshold <<
" HEC "
436 << E_HEC_threshold);
437
438 ATH_MSG_DEBUG(
" total Energies em " << E_em + E_em_threshold <<
" tile " << E_tile + E_tile_threshold <<
" HEC "
439 << E_HEC + E_HEC_threshold);
440
441
442
443
444 E_expected = scale_Ionization * Eloss;
445
446
447
448 double E_dead = E_expected - E_em_expected - E_tile_expected - E_HEC_expected + 0.12 * E_tile_expected + 0.27 * E_HEC_expected;
449
450
451
452
453 E_FSR = 0.;
454 double E_measured = 0.;
455 double E_measured_expected = E_em_expected + E_tile_expected + E_HEC_expected;
457
458 E_FSR = E_em;
459
460 E = E_em_expected + E_tile + E_tile_threshold + E_HEC + E_HEC_threshold + E_dead;
461 double sigma_expdead = error_ratio * (E_em_expected + E_dead);
462 sigma = std::sqrt(sigma_tile * sigma_tile + sigma_HEC * sigma_HEC + sigma_expdead * sigma_expdead);
463 E_measured = E_tile + E_tile_threshold + E_HEC + E_HEC_threshold;
464 } else {
465
466 E = E_em + E_em_threshold + E_tile + E_tile_threshold + E_HEC + E_HEC_threshold + E_dead;
467 double sigma_threshold = error_ratio * E_dead;
468 sigma = std::sqrt(sigma_em * sigma_em + sigma_tile * sigma_tile + sigma_HEC * sigma_HEC + sigma_threshold * sigma_threshold);
469 E_measured = E_em + E_em_threshold + E_tile + E_tile_threshold + E_HEC + E_HEC_threshold;
470 }
471
472
473
476
477 ATH_MSG_DEBUG(
" Total energy " << E <<
" sigma " << sigma <<
" E calo measured in cells " << E_measured
478 << " E calo expected in cells " << E_measured_expected << " E_expected meanIoni from TG "
479 << E_expected);
480
481 if (E_em + E_tile + E_HEC < 0.1 * E && E_em + E_tile + E_HEC > 1000.) {
482 ATH_MSG_DEBUG(
" Real Measured Calorimeter energy " << E_em + E_tile + E_HEC <<
" is much lower than total " << E
483 << " expected energy too large " << E_expected
484 << " put measured energy to zero ");
487 }
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503 double EE_dead = E_expected - EE_emB - EE_emE - EE_tile - EE_HEC + 0.12 * EE_tile + 0.27 * EE_HEC;
504
505
506
507 E_em_meas = E_em + E_em_threshold + EE_emB + EE_emE - E_em_expected;
508 E_em_exp = EE_emB + EE_emE;
509 E_tile_meas = E_tile + E_tile_threshold + EE_tile - E_tile_expected;
510 E_tile_exp = EE_tile;
511 E_HEC_meas = E_HEC + E_HEC_threshold + EE_HEC - E_HEC_expected;
512 E_HEC_exp = EE_HEC;
513 E_dead_exp = EE_dead;
514
515 }
Scalar theta() const
theta method
#define ATH_MSG_VERBOSE(x)
#define ATH_MSG_WARNING(x)
double energy() const
get energy (data member)
const CaloDetDescrElement * caloDDE() const
get pointer to CaloDetDescrElement (data member)
float y() const
get y (through CaloDetDescrElement)
virtual bool badcell() const
check is cell is dead
CaloGain::CaloGain gain() const
get gain (data member )
float z() const
get z (through CaloDetDescrElement)
float x() const
get x (through CaloDetDescrElement)
Identifier ID() const
get ID (from cached data member) non-virtual and inline for fast access
CaloCell_ID::SUBCALO getSubCalo() const
cell subcalo
float dphi() const
cell dphi
CaloCell_ID::CaloSample getSampling() const
cell sampling
float getEffectiveSigma(const Identifier id, const int gain, const float energy) const
const TrackParameters * caloEntryLayerIntersection() const
access to intersection with the calorimeter entry layer return nullptr if the intersection failed
const TrackParameters * muonEntryLayerIntersection() const
access to intersection with the muon entry layer return nullptr if the intersection failed
const Amg::Vector3D & momentum() const
Access method for the momentum.
const Amg::Vector3D & position() const
Access method for the position.
const Perigee * perigeeParameters() const
return Perigee.
Eigen::Matrix< double, 3, 1 > Vector3D
void entryExitLayerMap(const Trk::CaloExtension &extension, EntryExitLayerMap &result, const LayersToSelect *selection=nullptr)
std::map< CaloSampling::CaloSample, double > ScalarLayerMap
void eLossLayerMap(const Trk::CaloExtension &extension, ScalarLayerMap &result)
std::map< CaloSampling::CaloSample, std::pair< Amg::Vector3D, Amg::Vector3D > > EntryExitLayerMap
TrackParticle_v1 TrackParticle
Reference the current persistent version: