ATLAS Offline Software
Loading...
Searching...
No Matches
NeutralPFOClusterMLCorrectionTool.cxx
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2025 CERN for the benefit of the ATLAS collaboration
3*/
4
6
7NeutralPFOClusterMLCorrectionTool::NeutralPFOClusterMLCorrectionTool(const std::string &type, const std::string &name, const IInterface *parent)
8 : base_class(type, name, parent) {}
9
11 ATH_MSG_DEBUG("Initializing with ClusterMLCorrectedEnergyDecorationKey: " << m_clusterMLCorrectedEnergyKey.value());
12 ATH_MSG_DEBUG("Initializing with MaxAllowedChargedCorrectionFraction: " << m_max_allowed_charged_correction_fraction.value());
13 ATH_MSG_DEBUG("Initializing with MinAllowedEMEnergyMeV: " << m_min_allowed_em_energy.value());
14 return StatusCode::SUCCESS;
15}
16
18{
19 for (xAOD::FlowElement *neutral_pfo : neutral_pfos)
20 { correctNeutralFlowElement(*neutral_pfo); }
21}
22
23
25{
26 // The correction is applied only if link to cluster exists.
27 // If no link exists, it can be due to negative cell subtraction. In this case, no correction is applied.
28 // The corrected neutral pfo energy is calculated from ML-corrected cluster energy
29 if (neutral_pfo.isCharged())
30 {
31 throw std::runtime_error("Charged FlowElement found in neutral FlowElementContainer with index " + std::to_string(neutral_pfo.index()));
32 }
33 const xAOD::CaloCluster *cls = getLinkedCluster(neutral_pfo);
34 if (cls == nullptr)
35 { return; }
36
37 const double cluster_EM_energy = cls->rawE();
38
39 bool apply_ML_correction = (std::abs(neutral_pfo.e() - cluster_EM_energy) <= std::abs(m_max_allowed_charged_correction_fraction.value() * cluster_EM_energy));
40 apply_ML_correction = (cluster_EM_energy > m_min_allowed_em_energy.value());
41 if (apply_ML_correction)
42 {
43 const double cluster_ML_energy = getClusterMLCorrectedEnergy(*cls);
44 neutral_pfo.setP4(cluster_ML_energy / cosh(neutral_pfo.eta()), neutral_pfo.eta(), neutral_pfo.phi(), neutral_pfo.m());
45 }
46
47}
48
49
51{
52 // Returns xAOD::Type::CaloCluster type link. There should be at most one such link.
53 // It can happen that no such link exists. This can happen due to negative cells subtraction.
54 // Empty link is returned if no valid cluster link is found.
55 const std::vector<ElementLink<xAOD::IParticleContainer>> &otherObjectLinks = neutral_pfo.otherObjectLinks();
56 if (otherObjectLinks.size() > 1)
57 throw std::runtime_error("NeutralPFOClusterMLCorrectionTool: Multiple links found for neutral FlowElement with index " + std::to_string(neutral_pfo.index()));
58
59 bool hasValidLink = !otherObjectLinks.empty() && otherObjectLinks[0].isValid();
60 if (!hasValidLink)
61 { return nullptr; }
62
63 if ((**otherObjectLinks[0]).type() != xAOD::Type::CaloCluster)
64 throw std::runtime_error("NeutralPFOClusterMLCorrectionTool: Link for neutral FlowElement with index " + std::to_string(neutral_pfo.index()) + " is not of type CaloCluster");
65
66 return static_cast<const xAOD::CaloCluster *>(*otherObjectLinks[0]);
67}
68
70{
71 const SG::Accessor<double> clusterMLCorrectedEnergyAccessor(m_clusterMLCorrectedEnergyKey.value());
72 if (!clusterMLCorrectedEnergyAccessor.isAvailable(cls))
73 {
74 throw std::runtime_error("No ML energy decoration '" + m_clusterMLCorrectedEnergyKey.value()
75 + "' found for cluster with index " + std::to_string(cls.index())
76 + ". Returning EM energy.");
77 }
78 return clusterMLCorrectedEnergyAccessor(cls);
79}
#define ATH_MSG_DEBUG(x)
const xAOD::CaloCluster * getLinkedCluster(const xAOD::FlowElement &pfo) const
Gaudi::Property< std::string > m_clusterMLCorrectedEnergyKey
void correctNeutralFlowElement(xAOD::FlowElement &pfo) const
virtual void correctContainer(xAOD::FlowElementContainer &neutral_pfos, xAOD::FlowElementContainer &charged_pfos) const override
NeutralPFOClusterMLCorrectionTool(const std::string &type, const std::string &name, const IInterface *parent)
double getClusterMLCorrectedEnergy(const xAOD::CaloCluster &cls) const
Gaudi::Property< float > m_max_allowed_charged_correction_fraction
Helper class to provide type-safe access to aux data.
bool isAvailable(const ELT &e) const
Test to see if this variable exists in the store.
void setP4(float pt, float eta, float phi, float m)
virtual double m() const override
The invariant mass of the particle.
const std::vector< ElementLink< IParticleContainer > > & otherObjectLinks() const
virtual double phi() const override
The azimuthal angle ( ) of the particle.
virtual double eta() const override
The pseudorapidity ( ) of the particle.
virtual double e() const override
The total energy of the particle.
@ CaloCluster
The object is a calorimeter cluster.
Definition ObjectType.h:39
FlowElementContainer_v1 FlowElementContainer
Definition of the current "pfo container version".
CaloCluster_v1 CaloCluster
Define the latest version of the calorimeter cluster class.
FlowElement_v1 FlowElement
Definition of the current "pfo version".
Definition FlowElement.h:16