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;