ATLAS Offline Software
Loading...
Searching...
No Matches
JetHitAssociationAlg.cxx
Go to the documentation of this file.
1/*
2Copyright (C) 2002-2026 CERN for the benefit of the ATLAS collaboration
3*/
4
5//Include header file
7
8#include "JetHitPhiRanges.h"
9
13
14// RoIDescriptor for wedge selections
16
17//Include some helpful ROOT objects here.
18
19#include "CxxUtils/phihelper.h"
20#include <cmath>
21#include <optional>
22#include <algorithm> //sort, min, max
23
24
25namespace FlavorTagDiscriminants {
26
27 JetHitAssociationAlg::JetHitAssociationAlg(const std::string& name, ISvcLocator* loc)
28 : AthReentrantAlgorithm(name, loc) {}
29
30
32 ATH_MSG_DEBUG("Initializing " << name());
33
34 if(m_minJetPt > 0 || m_maxAbsJetEta >= 0) {
35 ATH_MSG_INFO("Associating hits only to jets with pt > " << m_minJetPt.value()
36 << " MeV and |eta| < "
37 << (m_maxAbsJetEta >= 0 ? m_maxAbsJetEta.value() : INFINITY));
38 }
39
40 // Initialize jet keys
41 ATH_CHECK(m_jetCollectionKey.initialize());
42 CHECK(m_hitAssociationKey.initialize());
43
44 ATH_CHECK(m_wedgeZKey.initialize(!m_wedgeZKey.empty()));
45
46 // Initialize hits position decoration keys
48 ATH_CHECK(m_hitsXRelToVertexKey.initialize());
49 ATH_CHECK(m_hitsYRelToVertexKey.initialize());
50 ATH_CHECK(m_hitsZRelToVertexKey.initialize());
51
52 if(m_useDRCone) {
53 if(m_dRHitToJet <= 0) {
54 ATH_MSG_FATAL("Invalid dR cone size!");
55 return StatusCode::FAILURE;
56 }
57 }
58 else if(m_dPhiHitToJet <= 0 || m_dEtaHitToVertex <= 0 || m_dZHitToVertex <= 0) {
59 ATH_MSG_FATAL("Invalid RoiDescriptor size!");
60 return StatusCode::FAILURE;
61 }
62
63 return StatusCode::SUCCESS;
64 }
65
66
67 StatusCode JetHitAssociationAlg::execute(const EventContext& ctx) const {
68 ATH_MSG_DEBUG("Executing " << name());
69
70 // Read out jets
72 if(!jetReadHandle.isValid()) {
73 ATH_MSG_ERROR("Failed to retrieve jet container with key " << m_jetCollectionKey.key());
74 return StatusCode::FAILURE;
75 }
76 // Avoid reading out hits if there are no jets to attach them to
77 if(jetReadHandle->empty()) return StatusCode::SUCCESS;
78
79 // Set up jet decorators
81
82 std::optional<SG::ReadDecorHandle<xAOD::IParticleContainer, float>> wedgeZ;
83 if(!m_wedgeZKey.empty()) wedgeZ.emplace(m_wedgeZKey, ctx);
84
85
86 // Read out hits (we need to keep the handles open to later build the ElementLinks)
88 if(!hitsHandle.isValid()) {
89 ATH_MSG_ERROR("Failed to retrieve hits container with key " << hitsHandle.key());
90 return StatusCode::FAILURE;
91 }
92
96
97 // The bec aux-variable is not declaared through keys to the SG, so it creates dependency errors in the
98 // schedules if we try to use a ReadDecorHandle(Key) for it.
99 static const SG::ConstAccessor<int> bec("bec");
100
101 // Filter input hits
102 std::vector<Hit> hits;
103 hits.reserve(hitsHandle->size());
104 for(const xAOD::TrackMeasurementValidation* hit : *hitsHandle) {
105 const int hit_bec = bec(*hit);
106 if(hit_bec == 0 && !m_includeBarrel) continue;
107 if(hit_bec != 0 && !m_includeEndcap) continue;
108
109 const float hx = x(*hit);
110 const float hy = y(*hit);
111 hits.push_back({hit, std::atan2(hy, hx), z(*hit), std::sqrt(hx*hx + hy*hy)});
112 }
113
114 // Sorting once per event lets each jet binary-search its phi window in
115 // getPhiRanges rather than scan every hit in the event
116 std::sort(hits.begin(), hits.end(),
117 [](const Hit& a, const Hit& b) { return a.phi < b.phi; });
118
119 // Loop over jets
120 for(const xAOD::IParticle* jet : *jetReadHandle) {
121
122 if(jet->pt() < m_minJetPt ||
123 (m_maxAbsJetEta >= 0 && std::abs(jet->eta()) > m_maxAbsJetEta)) {
124 hitAssociation(*jet) = {};
125 continue;
126 }
127
128 double zed = 0.0;
129 if(wedgeZ) {
130 zed = (*wedgeZ)(*jet);
131 if(!std::isfinite(zed)) {
132 ATH_MSG_WARNING("Wedge z-centre is not finite, dropping hits for this jet.");
133 hitAssociation(*jet) = {};
134 continue;
135 }
136 }
137
138 // Create links and decorate the jet
139 std::vector<ElementLink<xAOD::TrackMeasurementValidationContainer>> links;
140 for(const auto& [dist, hit] : getJetHits(jet, hits, zed)) {
143 hit->index(),
144 ctx
145 ));
146 }
147
148 hitAssociation(*jet) = std::move(links);
149 }
150
151 return StatusCode::SUCCESS;
152 }
153
154
155 const std::vector<std::pair<float, const xAOD::TrackMeasurementValidation*>>
157 const std::vector<Hit>& hits,
158 double zed) const {
159 const double eta = jet->eta();
160 const double phi = jet->phi();
161
162 std::vector<std::pair<float, const xAOD::TrackMeasurementValidation*>> ret;
163
164 // Both selections below imply |dphi| <= halfWidth, so only the hits in
165 // that phi window need testing. The epsilon keeps float rounding from
166 // dropping a hit on the boundary.
167 const float halfWidth =
168 (m_useDRCone ? m_dRHitToJet.value() : m_dPhiHitToJet.value()) + 1e-5f;
169
170 using HitItr = std::vector<Hit>::const_iterator;
171 const std::vector<std::pair<HitItr, HitItr>> ranges =
172 getPhiRanges(hits, phi, halfWidth);
173
174 if(m_useDRCone) {
175 for(const auto& [first, last] : ranges) {
176 for(HitItr it = first; it != last; ++it) {
177 const Hit& hit = *it;
178 const float dEta = eta - std::asinh((hit.z - zed) / hit.r);
179 const float dPhi = CxxUtils::wrapToPi(phi - hit.phi);
180
181 const float dR = std::sqrt(dEta * dEta + dPhi * dPhi);
182 if(dR > m_dRHitToJet) continue;
183
184 ret.emplace_back(dR, hit.original_hit);
185 }
186 }
187 }
188 else {
189 const RoiDescriptor roi(
192 zed, zed - m_dZHitToVertex, zed + m_dZHitToVertex
193 );
194
195 for(const auto& [first, last] : ranges) {
196 for(HitItr it = first; it != last; ++it) {
197 const Hit& hit = *it;
198 if(!RoiUtil::contains(roi, hit.z, hit.r, hit.phi)) continue;
199
200 ret.emplace_back(std::abs(CxxUtils::wrapToPi(phi - hit.phi)), hit.original_hit);
201 }
202 }
203 }
204
205 // If a maximum number of hits has been provided, sort them by distance and truncate the vector
206 if(m_maxHits > 0) {
207 std::sort(ret.begin(), ret.end(), [](const auto& h1, const auto& h2) -> bool { return h1.first < h2.first; });
208 ret.resize(std::min(static_cast<unsigned int>(m_maxHits), static_cast<unsigned int>(ret.size())));
209 }
210
211 return ret;
212 }
213
214}
Scalar eta() const
pseudorapidity method
Scalar phi() const
phi method
#define ATH_CHECK
Evaluate an expression and check for errors.
#define ATH_MSG_DEBUG(x,...)
#define ATH_MSG_ERROR(x,...)
#define ATH_MSG_WARNING(x,...)
#define ATH_MSG_INFO(x,...)
#define ATH_MSG_FATAL(x,...)
#define CHECK(...)
Evaluate an expression and check for errors.
bool hit(const Container &ids, int pdgId)
static Double_t a
Handle class for reading a decoration on an object.
Handle class for reading from StoreGate.
Handle class for adding a decoration to an object.
#define y
#define x
#define z
An algorithm that can be simultaneously executed in multiple threads.
virtual StatusCode execute(const EventContext &) const override
SG::ReadDecorHandleKey< xAOD::IParticleContainer > m_wedgeZKey
SG::ReadDecorHandleKey< xAOD::TrackMeasurementValidationContainer > m_hitsYRelToVertexKey
SG::ReadHandleKey< xAOD::TrackMeasurementValidationContainer > m_inputHitCollectionKey
SG::ReadHandleKey< xAOD::IParticleContainer > m_jetCollectionKey
JetHitAssociationAlg(const std::string &name, ISvcLocator *pSvcLocator)
SG::ReadDecorHandleKey< xAOD::TrackMeasurementValidationContainer > m_hitsXRelToVertexKey
const std::vector< std::pair< float, const xAOD::TrackMeasurementValidation * > > getJetHits(const xAOD::IParticle *jet, const std::vector< Hit > &hits, double zed) const
SG::WriteDecorHandleKey< xAOD::IParticleContainer > m_hitAssociationKey
SG::ReadDecorHandleKey< xAOD::TrackMeasurementValidationContainer > m_hitsZRelToVertexKey
Describes the Region of Ineterest geometry It has basically 9 parameters.
Helper class to provide constant type-safe access to aux data.
Handle class for reading a decoration on an object.
virtual bool isValid() override final
Can the handle be successfully dereferenced?
virtual const std::string & key() const override final
Return the StoreGate ID for the referenced object.
Handle class for adding a decoration to an object.
Class providing the definition of the 4-vector interface.
constexpr T wrapToPi(T phi)
Wrap angle in radians to [-pi, pi].
Definition phihelper.h:31
std::vector< std::pair< typename std::vector< Hit >::const_iterator, typename std::vector< Hit >::const_iterator > > getPhiRanges(const std::vector< Hit > &hits, float phi, float halfWidth)
bool contains(const IRoiDescriptor &roi, double z0, double dzdr)
see whether a segment is contained within the roi in r-z
Definition RoiUtil.cxx:42
void sort(typename DataModel_detail::iterator< DVL > beg, typename DataModel_detail::iterator< DVL > end)
Specialization of sort for DataVector/List.
TrackMeasurementValidation_v1 TrackMeasurementValidation
Reference the current persistent version:
Helper for azimuthal angle calculations.