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
8
9
10NeutralPFOClusterMLCorrectionTool::NeutralPFOClusterMLCorrectionTool(const std::string &type, const std::string &name, const IInterface *parent)
11 : base_class(type, name, parent) {}
12
15 ATH_MSG_DEBUG("Initializing with ClusterMLCorrectedEnergyDecorationKey: " << m_clusterMLCorrectedEnergyKey.key());
16 ATH_MSG_DEBUG("Initializing with MaxAllowedChargedCorrectionFraction: " << m_max_allowed_charged_correction_fraction.value());
17 ATH_MSG_DEBUG("Initializing with MinAllowedEMEnergyMeV: " << m_min_allowed_em_energy.value());
18 return StatusCode::SUCCESS;
19}
20
21void NeutralPFOClusterMLCorrectionTool::correctContainer(xAOD::FlowElementContainer &neutral_pfos, xAOD::FlowElementContainer &/*charged_pfos*/, const EventContext& ctx) const
22{
23
25 if (!clusterMLReadHandle.isValid()) {
26 throw std::runtime_error("Invalid decoration handle: " +
28 }
29
30 for (xAOD::FlowElement *neutral_pfo : neutral_pfos)
31 { correctNeutralFlowElement(*neutral_pfo, clusterMLReadHandle); }
32}
33
34
36{
37 // The correction is applied only if link to cluster exists.
38 // If no link exists, it can be due to negative cell subtraction. In this case, no correction is applied.
39 // The corrected neutral pfo energy is calculated from ML-corrected cluster energy
40 if (neutral_pfo.isCharged())
41 {
42 throw std::runtime_error("Charged FlowElement found in neutral FlowElementContainer with index " + std::to_string(neutral_pfo.index()));
43 }
44 const xAOD::CaloCluster *cls = getLinkedCluster(neutral_pfo);
45 if (cls == nullptr)
46 { return; }
47
48 const double cluster_EM_energy = cls->rawE();
49
50 bool apply_ML_correction = (std::abs(neutral_pfo.e() - cluster_EM_energy) <= std::abs(m_max_allowed_charged_correction_fraction.value() * cluster_EM_energy));
51 apply_ML_correction = apply_ML_correction && (cluster_EM_energy > m_min_allowed_em_energy.value());
52 if (apply_ML_correction)
53 {
54 const double cluster_ML_energy = clusterMLReadHandle(*cls);
55 neutral_pfo.setP4(cluster_ML_energy / cosh(neutral_pfo.eta()), neutral_pfo.eta(), neutral_pfo.phi(), neutral_pfo.m());
56 }
57
58}
59
60
62{
63 // Returns xAOD::Type::CaloCluster type link. There should be at most one such link.
64 // It can happen that no such link exists. This can happen due to negative cells subtraction.
65 // Empty link is returned if no valid cluster link is found.
66 const std::vector<ElementLink<xAOD::IParticleContainer>> &otherObjectLinks = neutral_pfo.otherObjectLinks();
67 if (otherObjectLinks.size() > 1)
68 throw std::runtime_error("NeutralPFOClusterMLCorrectionTool: Multiple links found for neutral FlowElement with index " + std::to_string(neutral_pfo.index()));
69
70 bool hasValidLink = !otherObjectLinks.empty() && otherObjectLinks[0].isValid();
71 if (!hasValidLink)
72 { return nullptr; }
73
74 if ((**otherObjectLinks[0]).type() != xAOD::Type::CaloCluster)
75 throw std::runtime_error("NeutralPFOClusterMLCorrectionTool: Link for neutral FlowElement with index " + std::to_string(neutral_pfo.index()) + " is not of type CaloCluster");
76
77 return static_cast<const xAOD::CaloCluster *>(*otherObjectLinks[0]);
78}
#define ATH_CHECK
Evaluate an expression and check for errors.
#define ATH_MSG_DEBUG(x)
Handle class for reading a decoration on an object.
virtual void correctContainer(xAOD::FlowElementContainer &neutral_pfos, xAOD::FlowElementContainer &charged_pfos, const EventContext &ctx) const override
const xAOD::CaloCluster * getLinkedCluster(const xAOD::FlowElement &pfo) const
NeutralPFOClusterMLCorrectionTool(const std::string &type, const std::string &name, const IInterface *parent)
SG::ReadDecorHandleKey< xAOD::CaloClusterContainer > m_clusterMLCorrectedEnergyKey
void correctNeutralFlowElement(xAOD::FlowElement &pfo, const SG::ReadDecorHandle< xAOD::CaloClusterContainer, double > &clusterMLReadHandle) const
Gaudi::Property< float > m_max_allowed_charged_correction_fraction
Handle class for reading a decoration on an object.
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