11 #include "GaudiKernel/SystemOfUnits.h"
26 declareInterface<IMuonCaloEnergyTool>(
this);
39 return StatusCode::SUCCESS;
43 double&
sigma,
double& E_FSR,
double& E_expected,
double& E_em_meas,
double& E_em_exp,
44 double& E_tile_meas,
double& E_tile_exp,
double& E_HEC_meas,
double& E_HEC_exp,
45 double& E_dead_exp, std::vector<Identifier>* crossedCells,
46 std::vector<double>* sigmaNoise_cell, std::vector<double>* E_exp_cell)
const {
47 const EventContext& ctx = Gaudi::Hive::currentContext();
73 bool storeCells =
false;
74 if (crossedCells !=
nullptr && sigmaNoise_cell !=
nullptr && E_exp_cell !=
nullptr) {
76 crossedCells->clear();
77 sigmaNoise_cell->clear();
98 double mopIoni = meanIoni;
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);
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);
115 if (indetTrackParticles.
isValid()) {
117 for (
const auto *
it : *indetTrackParticles) {
118 if ((*it).track() == trk) {
131 if (!
tp && muonTrackParticles.
isValid()) {
132 for (
const auto *
it : *muonTrackParticles) {
133 if ((*it).track() == trk) {
143 std::unique_ptr<const xAOD::TrackParticle> tpholder;
153 std::unique_ptr<const Rec::ParticleCellAssociation>
association =
159 std::vector<std::pair<const CaloCell*, Rec::ParticleCellIntersection*> > cellIntersections =
association->cellIntersections();
164 ATH_MSG_DEBUG(
"calculateMuonEnergies() - No caloEntryLayerIntersection found");
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());
174 double scaleTG = 1.0;
178 " No muonEntryLayerIntersection found and therefore the expected Eloss is not calculated properly for momentum "
181 ATH_MSG_DEBUG(
" No muonEntryLayerIntersection found and therefore the expected Eloss is not calculated properly ");
194 scaleTG = mopIoni / Eloss;
206 double scale_em_expected = 0.97;
207 double scale_tile_expected = 1.17;
208 double scale_HEC_expected = 1.11;
233 eLoss = eLossPair->second;
234 ATH_MSG_DEBUG(
" sample " <<
i <<
" eLoss " << scale_Ionization * eLoss);
236 EE_emB += scale_em_expected * scale_Ionization * eLoss;
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;
250 << EE_emB <<
" EE_emE " << EE_emE <<
" EE_tile " << EE_tile <<
" EE_HEC " << EE_HEC <<
" total Eloss "
256 if (scaleTG != 1.0)
return;
262 const CaloNoise* caloNoise = *caloNoiseHdl;
265 double E_em_expected = 0.;
266 double E_em_exptot = 0.;
267 double E_em_expall = 0.;
268 double E_em_threshold = 0.;
270 double sigma_Noise_em = 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.;
278 double sigma_Noise_HEC = 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.;
286 double sigma_Noise_tile = 0.;
292 for (
auto it : cellIntersections) {
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();
301 double f_exp = (
it.second)->pathLength();
302 double E_exp = (
it.second)->expectedEnergyLoss();
304 if (f_exp > 1.) f_exp = 1.;
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. );
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);
335 crossedCells->push_back(
id);
336 sigmaNoise_cell->push_back(sigma_Noise);
337 E_exp_cell->push_back(scale_Ionization * f_exp * E_exp *
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;
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);
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);
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;
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);
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);
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;
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);
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);
389 if (f_exp > 0 && !badCell) nlay_HEC++;
390 if (f_exp > 0 && !badCell) sigma_Noise_HEC += sigma_Noise;
392 E_expected += scale_Ionization * f_exp * E_exp;
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);
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);
413 ATH_MSG_DEBUG(
" e.m. to Muon scale measured Energies em " << E_em <<
" tile " << E_tile <<
" HEC " << E_HEC);
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);
435 ATH_MSG_DEBUG(
" Threshold correction to Energies em " << E_em_threshold <<
" tile " << E_tile_threshold <<
" HEC "
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);
444 E_expected = scale_Ionization * Eloss;
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;
454 double E_measured = 0.;
455 double E_measured_expected = E_em_expected + E_tile_expected + E_HEC_expected;
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;
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;
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 "
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 ");
503 double EE_dead = E_expected - EE_emB - EE_emE - EE_tile - EE_HEC + 0.12 * EE_tile + 0.27 * EE_HEC;
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;
513 E_dead_exp = EE_dead;
523 static constexpr
double corr[60] = {0.00368146, 0.0419526, 0.0419322, 0.0392922, 0.030304, 0.0262424, 0.0156346, 0.00590235, 0.00772249,
524 -0.0141775, -0.0152247, -0.0174432, -0.0319056, -0.0670813, -0.128678, -0.0982326, -0.0256406, -0.200244,
525 -0.178975, -0.120156, -0.124606, -0.0961311, -0.0163201, 0.00357829, 0.0292199, 0.0110466, -0.0375598,
526 0.0417912, 0.0386369, -0.0689454, -0.21496, -0.126157, -0.210573, -0.215757, -0.202019, -0.164546,
527 -0.168607, -0.128602, -0.124629, -0.0882631, -0.100869, -0.0460344, -0.0709039, -0.0163041, -0.0521138,
528 -0.0125259, -0.0378681, 0.00396062, -0.0636308, -0.032199, -0.0588335, -0.0470752, -0.0450315, -0.0301302,
529 -0.087378, -0.0115615, -0.0152037, 0, 0, 0};
533 static constexpr
double cor21[20] = {0.999793, 1.00017, 0.990946, 0.995358, 1.01377, 1.02676, 1.03111, 1.01483, 0.995585, 1.00465,
534 1.05224, 1.05238, 1.03208, 1.02373, 1.02305, 1.03975, 1.06547, 1.0364, 1.0361, 1.0361};
536 int i21 = std::abs(eta * 20. / 3.);
537 if (i21 > 19) i21 = 19;
551 static constexpr
double par[6] = {1.01431e+00, -2.26317e+01, 1.80901e+02, -2.33105e+01, 1.82930e+02, 1.11356e-02};
553 double E = E_expected;
555 if (
E == 0)
return 0.;
557 double x = sigma_Noise /
E;
567 ATH_MSG_DEBUG(
" ThresholdCorrection E " <<
E <<
" E_observed not used " << E_observed <<
" sigma_Noise " << sigma_Noise
568 <<
" x = sigma_Noise/E " <<
x <<
" fraction " << fraction <<
" E correction "
569 << (1 - fraction) *
E);
571 return (1. - fraction) *
E;