ATLAS Offline Software
Loading...
Searching...
No Matches
MuJetOverlapTool.cxx
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2025 CERN for the benefit of the ATLAS collaboration
3*/
4
5// System includes
6#include <typeinfo>
7
8// Framework includes
13
14// Local includes
18
19namespace
20{
22 const double GeV = 1e3; // FIXME local unit definition!!
23}
24
25namespace ORUtils
26{
27
28 //---------------------------------------------------------------------------
29 // Constructor
30 //---------------------------------------------------------------------------
31 MuJetOverlapTool::MuJetOverlapTool(const std::string& name)
32 : BaseOverlapTool(name)
33 {
34 declareProperty("BJetLabel", m_bJetLabel = "",
35 "Input b-jet flag. Disabled by default.");
36 declareProperty("NumJetTrk", m_numJetTrk = 3,
37 "Min number of jet tracks to keep jet and remove muon");
38 declareProperty("ApplyRelPt", m_applyRelPt = false,
39 "Toggle mu/jet relative PT requirements to prioritize jet");
40 declareProperty("MuJetPtRatio", m_muJetPtRatio = 0.5,
41 "Mu/jet PT ratio threshold to remove a jet");
42 declareProperty("MuJetTrkPtRatio", m_muJetTrkPtRatio = 0.7,
43 "Mu/jetTrk PT ratio threshold to remove a jet");
44 declareProperty("JetNumTrackDecoration", m_jetNumTrkDec = "",
45 "User-defined decoration for jet numTrack");
46 declareProperty("JetSumTrackPTDecoration", m_jetSumTrkPtDec = "",
47 "User-defined decoration for jet sumTrackPT");
48 declareProperty("UseGhostAssociation", m_useGhostAssociation = true,
49 "Activate ghost-association mapping for jet removals");
50 declareProperty("InnerDR", m_innerDR = 0.2,
51 "Flat inner cone for removing jets");
52 declareProperty("OuterDR", m_outerDR = 0.4,
53 "Flat outer cone for removing muons");
54 declareProperty("UseSlidingDR", m_useSlidingDR = false,
55 "Enables sliding dR outer cone = c1 + c2/MuPt");
56 declareProperty("SlidingDRC1", m_slidingDRC1 = 0.04,
57 "The constant offset for sliding dR");
58 declareProperty("SlidingDRC2", m_slidingDRC2 = 10.*GeV,
59 "The inverse muon pt factor for sliding dR");
60 declareProperty("SlidingDRMaxCone", m_slidingDRMaxCone = 0.4,
61 "Maximum allowed size of sliding dR cone");
62 declareProperty("UseRapidity", m_useRapidity = true,
63 "Calculate delta-R using rapidity");
64 declareProperty("AllowNoPV", m_allowNoPV = false,
65 "Allow events with no primary vertex");
66 declareProperty("PVContainerName", m_PVContName = "PrimaryVertices",
67 "PV Container to use");
68 }
69
70 //---------------------------------------------------------------------------
71 // Initialize
72 //---------------------------------------------------------------------------
74 {
75 // Initialize the b-jet helper
76 if(!m_bJetLabel.empty()) {
77 ATH_MSG_DEBUG("Configuring btag-aware OR with btag label: " << m_bJetLabel);
78 resetAccessor (m_bJetAcc, *this, m_bJetLabel);
79 }
80
81 // Initialize the matcher for the 'inner' cone.
83 ATH_MSG_DEBUG("Configuring ghost association + dR matching for jet-mu OR "
84 "with inner cone size " << m_innerDR);
85 m_dRMatchCone1 = std::make_unique<MuJetGhostDRMatcher>(m_innerDR, m_useRapidity);
86 }
87 else {
88 ATH_MSG_DEBUG("Configuring mu-jet inner cone size " << m_innerDR);
89 m_dRMatchCone1 = std::make_unique<DeltaRMatcher>(m_innerDR, m_useRapidity);
90 }
92 addSubtool(*m_dRMatchCone1);
93
94 // Use sliding dR or flat dR for the 'outer' cone.
95 if(m_useSlidingDR) {
96 ATH_MSG_DEBUG("Configuring sliding outer cone for mu-jet OR with " <<
97 "constants C1 = " << m_slidingDRC1 << ", C2 = " <<
98 m_slidingDRC2 << ", MaxCone = " << m_slidingDRMaxCone);
100 std::make_unique<SlidingDeltaRMatcher>
102 }
103 else {
104 ATH_MSG_DEBUG("Configuring mu-jet outer cone size " << m_outerDR);
105 m_dRMatchCone2 = std::make_unique<DeltaRMatcher>(m_outerDR, m_useRapidity);
106 }
108 addSubtool(*m_dRMatchCone2);
109
110 // Additional config printouts
111 ATH_MSG_DEBUG("Mu-jet matching config: NumJetTrk " << m_numJetTrk <<
112 " ApplyRelPt " << m_applyRelPt <<
113 " MuJetPtRatio " << m_muJetPtRatio <<
114 " MuJetTrkPtRatio " << m_muJetTrkPtRatio);
115 if(!m_jetNumTrkDec.empty()) {
116 ATH_MSG_DEBUG("Using user-defined JetNumTrackDecoration " << m_jetNumTrkDec);
117 }
118 if(!m_jetSumTrkPtDec.empty()) {
119 ATH_MSG_DEBUG("Using user-defined JetSumTrackPTDecoration " << m_jetSumTrkPtDec);
120 }
121
122 ATH_MSG_DEBUG("AllowNoPV set to " << m_allowNoPV);
123 resetAccessor (m_accessors->m_vtxContainerAcc, *m_accessors, m_PVContName, {.addMTDependency = true});
124 if (!m_jetNumTrkDec.empty())
125 resetAccessor (m_accessors->m_jetNumTrkAcc, *m_accessors, m_jetNumTrkDec);
126 else
127 resetAccessor (m_accessors->m_jetNumTrkPt500Acc, *m_accessors, "NumTrkPt500");
128 if (!m_jetSumTrkPtDec.empty())
129 resetAccessor (m_accessors->m_jetSumTrkPtAcc, *m_accessors, m_jetSumTrkPtDec);
130 else
131 resetAccessor (m_accessors->m_jetSumTrkPt500Acc, *m_accessors, "SumPtTrkPt500");
132 return StatusCode::SUCCESS;
133 }
134
135 //---------------------------------------------------------------------------
136 // Identify overlaps
137 //---------------------------------------------------------------------------
141 columnar::EventContextId eventContext) const
142 {
143 // Check the container types
144 ATH_CHECK( checkForXAODContainer<xAOD::MuonContainer>(cont1, "First container arg is not of type MuonContainer!") );
145 ATH_CHECK( checkForXAODContainer<xAOD::JetContainer>(cont2, "Second container arg is not of type JetContainer!") );
146
147 ATH_CHECK( internalFindOverlaps(cont1, cont2, eventContext) );
148 return StatusCode::SUCCESS;
149 }
150
151 //---------------------------------------------------------------------------
152 // Identify overlaps
153 //---------------------------------------------------------------------------
157 columnar::EventContextId eventContext) const
158 {
159 ATH_MSG_DEBUG("Removing overlapping muons and jets");
160 auto& acc = *m_accessors;
161
162 // Initialize output decorations if necessary
165
166 // Retrieve the primary vertex for later reference
167 auto vtxIdx = getPrimVtxIdx(eventContext);
168 if(m_jetNumTrkDec.empty() && m_jetSumTrkPtDec.empty()) {
169 if (!vtxIdx)
170 {
171 if (!m_allowNoPV) {
172 ATH_MSG_ERROR("No primary vertex found! Cannot proceed with Mu-Jet OR.");
173 return StatusCode::FAILURE;
174 }
175 else {
176 ATH_MSG_DEBUG("No primary vertex found. Skipping the PV-dependent jet track info.");
177 }
178 }
179 }
180
181 // Remove suspicious jets that overlap with muons.
182 for(const auto muon : muons){
183 if(!isSurvivingObject(muon)) continue;
184
185 for(const auto jet : jets){
186 if(!isSurvivingObject(jet)) continue;
187
188 // Don't reject user-defined b-tagged jets
189 if(!m_bJetLabel.empty() && m_bJetAcc(jet)) continue;
190
191 if (vtxIdx) {
192 // Get the number of tracks and the sumPT of those tracks
193 int nTrk = getNumTracks(jet, vtxIdx.value());
194 float sumTrkPt = getSumTrackPt(jet, vtxIdx.value());
195
196 // Don't reject jets with high track multiplicity and
197 // high relative PT ratio
198 bool highNumTrk = nTrk >= m_numJetTrk;
199 bool highRelPt = false;
200
201 if (sumTrkPt < FLT_MIN){
202 highRelPt = (muon(acc.m_muonPtAcc)/jet(acc.m_jetPtAcc) < m_muJetPtRatio);
203 }
204 else{
205 highRelPt = (muon(acc.m_muonPtAcc)/jet(acc.m_jetPtAcc) < m_muJetPtRatio || muon(acc.m_muonPtAcc)/sumTrkPt < m_muJetTrkPtRatio);
206 }
207
208 if(highNumTrk && (!m_applyRelPt || highRelPt)) continue;
209 } // end part related to PV
210
211 if(m_dRMatchCone1->objectsMatch(muon, jet)){
212 ATH_CHECK( handleOverlap(jet, muon) );
213 }
214 }
215 }
216
217 // Remove muons from remaining overlapping jets
218 for(const auto jet : jets){
219 if(!isSurvivingObject(jet)) continue;
220
221 for(const auto muon : muons){
222 if(!isSurvivingObject(muon)) continue;
223
224 if(m_dRMatchCone2->objectsMatch(muon, jet)){
225 ATH_CHECK( handleOverlap(muon, jet) );
226 }
227 }
228 }
229
230 return StatusCode::SUCCESS;
231 }
232
233 //---------------------------------------------------------------------------
234 // Retrieve the primary vertex
235 //---------------------------------------------------------------------------
236 std::optional<std::size_t> MuJetOverlapTool::getPrimVtxIdx(columnar::EventContextId eventContext) const
237 {
238 auto& acc = *m_accessors;
239 // the old version of this code would allow for a missing PV
240 // container, but then fail later on. So the code now requires a
241 // primary vertex here.
242 auto vertices = acc.m_vtxContainerAcc(eventContext);
243 for(auto vtx : vertices) {
244 if(vtx(acc.m_vertexTypeAcc) == xAOD::VxType::PriVtx)
245 return vertices.getIndexInRange(vtx);
246 }
247 // No PV found. Printing a debug message only and leaving it to the
248 // caller to do the right thing. There is no point checking here
249 // whether we will fail or not.
250 ATH_MSG_DEBUG("No primary vertex in the " << m_PVContName << " container!");
251 return std::nullopt;
252 }
253
254 //---------------------------------------------------------------------------
255 // Get the number of tracks in a jet
256 //---------------------------------------------------------------------------
258 {
259 auto& acc = *m_accessors;
260 // Use the user decoration if configured
261 if(!m_jetNumTrkDec.empty()) {
262 return acc.m_jetNumTrkAcc(jet);
263 }
264 return acc.m_jetNumTrkPt500Acc(jet)[vtxIdx];
265 }
266
267 //---------------------------------------------------------------------------
268 // Get the sum track pt of a jet
269 //---------------------------------------------------------------------------
271 {
272 auto& acc = *m_accessors;
273 // Use the user decoration if configured
274 if(!m_jetSumTrkPtDec.empty()) {
275 return acc.m_jetSumTrkPtAcc(jet);
276 }
277 return acc.m_jetSumTrkPt500Acc(jet)[vtxIdx];
278 }
279
280} // namespace ORUtils
#define ATH_CHECK
Evaluate an expression and check for errors.
#define ATH_MSG_ERROR(x)
#define ATH_MSG_DEBUG(x)
Handle class for reading from StoreGate.
Helper class to provide constant type-safe access to aux data.
DataVector adapter that acts like it holds const pointers.
Gaudi::Details::PropertyBase & declareProperty(Gaudi::Property< T, V, H > &t)
void initializeDecorations(columnar::Particle1Range container) const
BaseOverlapTool(const std::string &name)
Create proper constructor for Athena.
StatusCode handleOverlap(const columnar::ObjectId< CI1, CM > &testParticle, const columnar::ObjectId< CI2, CM > &refParticle) const
Common helper method to handle an overlap result.
bool isSurvivingObject(columnar::Particle1Id obj) const
StatusCode checkForXAODContainer(columnar::ObjectRange< CI, CM > cont, std::string_view message) const
check whether the container is of the right type
virtual StatusCode initializeDerived() override
Initialize the tool.
int getNumTracks(columnar::Particle2Id jet, size_t vtxIdx) const
Get the number of tracks in a jet w.r.t. requested vertex.
std::unique_ptr< Accessors > m_accessors
std::string m_PVContName
PV Container to use.
bool m_useSlidingDR
Toggle sliding dR overlap removal for removing muons.
float m_innerDR
Inner dR cone within which jets get removed.
int m_numJetTrk
Minimum number of jet tracks to prioritize the jet.
std::unique_ptr< IParticleAssociator > m_dRMatchCone1
Delta-R matcher for the inner cone.
float m_muJetTrkPtRatio
PT ratio threshold for vetoing the jet. Uses sum of jet track PT.
std::optional< std::size_t > getPrimVtxIdx(columnar::EventContextId eventContext) const
Retrieve the primary vertex used to count jet tracks.
bool m_applyRelPt
Toggle PT ratio criteria TODO: rename to m_applyPtRatio.
double m_slidingDRMaxCone
MaxCone, the upper limit of the sliding cone.
float m_muJetPtRatio
PT ratio threshold for vetoing the jet.
std::unique_ptr< IParticleAssociator > m_dRMatchCone2
Delta-R matcher for the outer cone.
std::string m_bJetLabel
Input jet decoration which labels a bjet.
double m_slidingDRC2
C1, the inverse pt factor in sliding dR.
MuJetOverlapTool(const std::string &name)
Create proper constructor for Athena.
virtual StatusCode findOverlaps(columnar::Particle1Range cont1, columnar::Particle2Range cont2, columnar::EventContextId eventContext) const override
Identify overlapping muons and jets.
float getSumTrackPt(columnar::Particle2Id jet, size_t vtxIdx) const
Get the sum trk pt in a jet w.r.t. requested vertex.
columnar::Particle2Accessor< char > m_bJetAcc
BJet helper.
float m_outerDR
Outer dR cone within which muons get removed.
std::string m_jetNumTrkDec
Optional user decoration for jet numTrack of type 'int'.
std::string m_jetSumTrkPtDec
Optional user decoration for jet sumTrackPT of type 'float'.
virtual StatusCode internalFindOverlaps(columnar::Particle1Range muons, columnar::Particle2Range jets, columnar::EventContextId eventContext) const
Identify overlapping muons and jets.
bool m_useRapidity
Calculate deltaR using rapidity.
bool m_useGhostAssociation
Use ghost association in matching to remove jets.
double m_slidingDRC1
C1, the constant offset in sliding dR.
ObjectId< ContainerId::particle2 > Particle2Id
Definition ParticleDef.h:54
ObjectId< ContainerId::eventContext > EventContextId
ObjectRange< ContainerId::particle2 > Particle2Range
Definition ParticleDef.h:53
ObjectRange< ContainerId::particle1 > Particle1Range
Definition ParticleDef.h:47
@ Jet
The object is a jet.
Definition ObjectType.h:40
@ Muon
The object is a muon.
Definition ObjectType.h:48
@ PriVtx
Primary vertex.