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 return StatusCode::SUCCESS;
13}
14
16{
17
18 for (xAOD::FlowElement *pfo : container)
19 {
20 if (pfo->isCharged())
21 {
22 ATH_MSG_WARNING("NeutralPFOClusterMLCorrectionTool: Charged FlowElement found in neutral FlowElementContainer with index " + std::to_string(pfo->index()));
23 continue;
24 }
25
26 const xAOD::CaloCluster *cls = getLinkedCluster(*pfo);
27 if (cls != nullptr)
29 }
30}
31
33{
34 // Scale factor is defined as the ratio of the cluster energy stored in decoration
35 // to the energy in the EM calibration state (UNCALIBRATED). This scale factor is then applied to the PFO energy.
36 // If the EM energy is zero or if decoration is not found, no scaling is applied.
37 const SG::AuxElement::Accessor<double> clusterMLCorrectedEnergyAccessor(m_clusterMLCorrectedEnergyKey.value());
38 const double clusterEMEnergy = cls.rawE();
39 if (!clusterMLCorrectedEnergyAccessor.isAvailable(cls))
40 {
41 ATH_MSG_WARNING("NeutralPFOClusterMLCorrectionTool: No ML energy decoration '" << m_clusterMLCorrectedEnergyKey.value()
42 << "' found for cluster with index " << cls.index()
43 << ". PFO energy will not be scaled.");
44 }
45 const double clusterDecorEnergy = clusterMLCorrectedEnergyAccessor.isAvailable(cls) ? clusterMLCorrectedEnergyAccessor(cls) : clusterEMEnergy;
46 const double scaleFactor = clusterEMEnergy > FLT_MIN ? clusterDecorEnergy / clusterEMEnergy : 1.0;
47
48 ATH_MSG_DEBUG("NeutralPFOClusterMLCorrectionTool: Scaling PFO with index " << pfo.index()
49 << " energy from " << pfo.e() << " to " << (pfo.e() * scaleFactor)
50 << " using cluster index " << cls.index()
51 << " EM energy " << clusterEMEnergy
52 << " Decor energy " << clusterDecorEnergy
53 << " scale factor " << scaleFactor);
54
55 pfo.setP4(pfo.pt() * scaleFactor, pfo.eta(), pfo.phi(), pfo.m() * scaleFactor);
56}
57
59{
60 // Returns xAOD::Type::CaloCluster type link. There should be at most one such link.
61 // It can happen that no such link exists. This can happen due to negative cells subtraction.
62 // Empty link is returned if no valid cluster link is found.
63 const std::vector<ElementLink<xAOD::IParticleContainer>> &otherObjectLinks = pfo.otherObjectLinks();
64 if (otherObjectLinks.size() > 1)
65 ATH_MSG_ERROR("NeutralPFOClusterMLCorrectionTool: Multiple links found for neutral FlowElement with index " + std::to_string(pfo.index()));
66
67 bool hasValidLink = !otherObjectLinks.empty() && otherObjectLinks[0].isValid();
68 if (hasValidLink)
69 {
70 if ((**otherObjectLinks[0]).type() != xAOD::Type::CaloCluster)
71 ATH_MSG_ERROR("NeutralPFOClusterMLCorrectionTool: Link for neutral FlowElement with index " + std::to_string(pfo.index()) + " is not of type CaloCluster");
72
73 return static_cast<const xAOD::CaloCluster *>(*otherObjectLinks[0]);
74 }
75 else
76 return nullptr;
77}
#define ATH_MSG_ERROR(x)
#define ATH_MSG_WARNING(x)
#define ATH_MSG_DEBUG(x)
const xAOD::CaloCluster * getLinkedCluster(const xAOD::FlowElement &pfo) const
Gaudi::Property< std::string > m_clusterMLCorrectedEnergyKey
NeutralPFOClusterMLCorrectionTool(const std::string &type, const std::string &name, const IInterface *parent)
void scaleEnergyToAlternativeSignalState(xAOD::FlowElement &pfo, const xAOD::CaloCluster &cls) const
virtual void correctContainer(xAOD::FlowElementContainer &pfos) const override
SG::Accessor< T, ALLOC > Accessor
Definition AuxElement.h:572
size_t index() const
Return the index of this element within its container.
bool isAvailable(const ELT &e) const
Test to see if this variable exists in the store.
virtual double pt() const override
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