ATLAS Offline Software
Loading...
Searching...
No Matches
TrigJetHypoTool.cxx
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2026 CERN for the benefit of the ATLAS collaboration
3*/
4
5// ********************************************************************
6//
7// NAME: TrigJetHypoTool.cxx
8// PACKAGE: Trigger/TrigHypothesis/TrigHLTJetHypo
9//
10//
11// ********************************************************************
12
13#include "TrigJetHypoTool.h"
14
15#include "GaudiKernel/StatusCode.h"
16
20#include "./xAODJetCollector.h"
21
23
25
26#include <sstream>
27#include <chrono>
28#include <algorithm> //transform
29#include <numeric> //accumulate
30#include <stdexcept>
31
32
39
40
42 const std::string& name,
43 const IInterface* parent) :
44 AthAlgTool(type, name, parent),
45 m_decisionID(HLT::Identifier::fromToolName(name))
46{
47}
48
49
52
54
55 if (!(m_endLabelIndex > 0)){
56 ATH_MSG_ERROR("endLabelIndex must be > 0, is " + std::to_string(m_endLabelIndex));
57 return StatusCode::FAILURE;
58 }
59
60 if (m_endLabelIndex == 1u) {
61
62 // This is a single-leg jet chain.
63 m_decisionIDs.push_back(m_decisionID);
64
65 } else {
66
67 // This is a multi-leg chain with (m_endLabelIndex - m_startLabelIndex) jet legs contained within
68
69 if(not isLegId(m_decisionID)){
70 ATH_MSG_ERROR(name() << " is being configured to do jet selection for a multi-leg chain, from leg " << m_startLabelIndex <<
71 " to " << m_endLabelIndex << ", the HypoTool's name must therefore start with legXXX_ rather than HLT_");
72 return StatusCode::FAILURE;
73 }
74
75 HLT::Identifier noLegNameDecisionID = getIDFromLeg(m_decisionID);
76 for (std::size_t i = m_startLabelIndex; i != m_endLabelIndex; ++i){
77 m_decisionIDs.push_back(createLegName(noLegNameDecisionID, i));
78 ATH_MSG_DEBUG("Adding jet-leg " << m_decisionIDs.size()-1 << " for " << noLegNameDecisionID << ", this is leg " << i << " in the chain:" << m_decisionIDs.back());
79 }
80
81 }
82
83 if (m_visitDebug){
84 DebugInfoCollector collector(name() + "_init");
85 CHECK(m_helper->getDescription(collector));
86 auto s = collector.toString();
87
88 for(const auto& l : lineSplitter(s)){
89 ATH_MSG_INFO(l);
90 }
91 }
92
93 if (!m_monTool.empty()) ATH_CHECK(m_monTool.retrieve());
94 return StatusCode::SUCCESS;
95}
96
97
99 return StatusCode::SUCCESS;
100}
101
102
103StatusCode
105 const TrigCompositeUtils::DecisionIDContainer& previousDecisionIDs,
106 std::vector<JetDecision>& jetHypoInputs) const {
107
108 // need only check against the decision ID corresponding to the name
109 // of this hypo. Leg indices are irrelevant at this point.
111 previousDecisionIDs)) {
112 return StatusCode::SUCCESS;
113 }
114
115 std::unique_ptr<ITrigJetHypoInfoCollector> infocollector(nullptr);
116 std::unique_ptr<ITrigJetHypoInfoCollector> jetdumper(nullptr);
117 if(m_visitDebug){
118 auto collectorName = name() + "_" + std::to_string(m_id++);
119 infocollector.reset(new DebugInfoCollector(collectorName));
120 auto jetdumperName =
121 name()+"_passingjets_" + std::to_string(m_id++);
122 jetdumper.reset(new DebugInfoCollector(jetdumperName));
123 }
124
125
126 HypoJetVector hypoJets(jets->size());
127
128 std::transform(jets -> begin(),
129 jets -> end(),
130 hypoJets.begin(),
132
133 /* apply cleaning and hypothesis alg */
134 ATH_MSG_DEBUG("hypo helper start... "
135 << " no of jets ... "
136 << jets->size()
137 << "...");
138
139 // steady_clock::time_point t = steady_clock::now();
140 // monitoring -- timing plots (filled for every call)
141 auto mon_NInputs = Monitored::Scalar("NJetsIn",jets->size());
142 auto mon_NOutputs = Monitored::Scalar("NJetsOut",-1);
143 auto tHypo = Monitored::Timer<std::chrono::milliseconds>("TIME_jetHypo");
144 auto monitor_group_multTime = Monitored::Group( m_monTool, tHypo, mon_NOutputs, mon_NInputs);
145
146 xAODJetCollector jetCollector;
147 bool pass;
148 try{
149 pass = m_helper->pass(hypoJets, jetCollector, infocollector);
150 } catch(std::exception& e){
151 ATH_MSG_ERROR("Exception raised by the TrigJetHypoToolHelper: "
152 << e.what());
153 return StatusCode::FAILURE;
154 }
155 tHypo.stop();
156
157 if (!pass) {
158
159 if (infocollector){
160
161 std::string msg =
162 "hypo testing done: no of input jets " + std::to_string(jets->size())
163 + " no of participating jets " + std::to_string(jetCollector.size())
164 + " pass: false ";
165
166 infocollector->collect("TrigJetHypoTool", msg);
167 }
168
169 return StatusCode::SUCCESS;
170 }
171
172 CHECK(checkPassingJets(jetCollector, infocollector));
173 CHECK(reportPassingJets(jetCollector, jetHypoInputs));
174
175 // accumulateTime(steady_clock::now() - t);
176
177
178 if (infocollector){
179
180 std::string msg =
181 "hypo testing done: no of input jets " + std::to_string(jets->size())
182 + " no of particlating jets " + std::to_string(jetCollector.size())
183 + " pass: true";
184
185
186 infocollector->collect("TrigJetHypoTool", msg);
187 infocollector->write();
188
189 std::stringstream ss;
190 ss << jetCollector.hypoJets();
191 jetdumper->collect("passed", ss.str());
192 }
193
194 //monitoring -- filled in passing events
195 HypoJetVector hjv = jetCollector.hypoJets();
196
197 mon_NOutputs = hjv.size();
198 for(const auto& j : hjv) {
199 auto mon_jetEt = Monitored::Scalar("Et", j->et()*0.001);
200 auto mon_jetEta = Monitored::Scalar("Eta", j->eta());
201 auto mon_jetPhi = Monitored::Scalar("Phi", j->phi());
202 auto mon_jetMass = Monitored::Scalar("Mass", j->m()*0.001);
203 float this_z = 999;
204 float this_negLogSigma2 = 999;
205 j->getAttribute("dipz20231122_z", this_z);
206 j->getAttribute("dipz20231122_negLogSigma2", this_negLogSigma2);
207 auto mon_dipz_z = Monitored::Scalar( "dipz_z", this_z);
208 auto mon_dipz_negLogSigma2 = Monitored::Scalar( "dipz_negLogSigma2", this_negLogSigma2);
209 float this_GN2X_phbb{999.}, this_GN2X_phcc{999.}, this_GN2X_pqcd{999.}, this_GN2X_ptop{999.};
210 j->getAttribute("GN2Xv01_phbb", this_GN2X_phbb);
211 j->getAttribute("GN2Xv01_phcc", this_GN2X_phcc);
212 j->getAttribute("GN2Xv01_ptop", this_GN2X_ptop);
213 j->getAttribute("GN2Xv01_pqcd", this_GN2X_pqcd);
214 auto mon_GN2X_phbb = Monitored::Scalar("GN2Xv01_phbb", this_GN2X_phbb);
215 auto mon_GN2X_phcc = Monitored::Scalar("GN2Xv01_phcc", this_GN2X_phcc);
216 auto mon_GN2X_ptop = Monitored::Scalar("GN2Xv01_ptop", this_GN2X_ptop);
217 auto mon_GN2X_pqcd = Monitored::Scalar("GN2Xv01_pqcd", this_GN2X_pqcd);
218 float this_GN2X_discriminant{999.};
219 if (this_GN2X_phbb > 0.){
220 float top_frac{0.25};
221 float denom = this_GN2X_pqcd*(1. - top_frac) + this_GN2X_ptop * top_frac;
222 if (denom > 0.){
223 this_GN2X_discriminant = log(this_GN2X_phbb/denom);
224 }
225 }
226 auto mon_GN2X_discriminant = Monitored::Scalar("GN2Xv01_discriminant", this_GN2X_discriminant);
227
228 float this_GN2XTrig_phbb{999.}, this_GN2XTrig_pqcd{999.}, this_GN2XTrig_ptop{999.};
229 j->getAttribute("GN2XTrig_phbb", this_GN2XTrig_phbb);
230 j->getAttribute("GN2XTrig_ptop", this_GN2XTrig_ptop);
231 j->getAttribute("GN2XTrig_pqcd", this_GN2XTrig_pqcd);
232 auto mon_GN2XTrig_phbb = Monitored::Scalar("GN2XTrig_phbb", this_GN2XTrig_phbb);
233 auto mon_GN2XTrig_ptop = Monitored::Scalar("GN2XTrig_ptop", this_GN2XTrig_ptop);
234 auto mon_GN2XTrig_pqcd = Monitored::Scalar("GN2XTrig_pqcd", this_GN2XTrig_pqcd);
235 float this_GN2XTrig_discriminant{999.};
236 if (this_GN2XTrig_phbb > 0.){
237 float top_frac{0.25};
238 float denom = this_GN2XTrig_pqcd*(1. - top_frac) + this_GN2XTrig_ptop * top_frac;
239 if (denom > 0.){
240 this_GN2XTrig_discriminant = log(this_GN2XTrig_phbb/denom);
241 }
242 }
243 auto mon_GN2XTrig_discriminant = Monitored::Scalar("GN2XTrig_discriminant", this_GN2XTrig_discriminant);
244
245 auto monitor_group_passingjets = Monitored::Group( m_monTool, mon_jetEt, mon_jetEta, mon_jetPhi , mon_dipz_z, mon_dipz_negLogSigma2, mon_jetMass, mon_GN2X_phbb, mon_GN2X_phcc, mon_GN2X_ptop, mon_GN2X_pqcd, mon_GN2X_discriminant, mon_GN2XTrig_phbb, mon_GN2XTrig_ptop, mon_GN2XTrig_pqcd, mon_GN2XTrig_discriminant);
246
247 }
248 //monitor the passing jets for each leg (there should only be one per chain!)
249 auto legInds = jetCollector.legInds();
250 for (const auto& label : legInds) {
251 const auto & theseJets = jetCollector.hypoJets(label);
252 auto monitor_nJt = Monitored::Scalar( "NJets", theseJets.size());
253 auto htsum = Monitored::Scalar("HT", std::accumulate(theseJets.begin(), theseJets.end(),0.0,
254 [](double sum, const HypoJetVector::value_type jptr){return sum + jptr->et()*0.001;} ));
255 auto monitor_group_passinght = Monitored::Group(m_monTool, monitor_nJt,htsum);
256 }
257
258 return StatusCode::SUCCESS;
259}
260
261
262const std::vector<HLT::Identifier>& TrigJetHypoTool::getIDs() const{
263 return m_decisionIDs;
264}
265
266
267const HLT::Identifier& TrigJetHypoTool::getID(std::size_t i) const{
268 return m_decisionIDs.at(i-m_startLabelIndex);
269}
270
271
272StatusCode
274 const std::unique_ptr<ITrigJetHypoInfoCollector>& infocollector) const {
275
276 if (jetCollector.empty()) {
277 ATH_MSG_ERROR("HypoTool passed the event for " <<
278 m_chainName << " ev " << m_id <<
279 ", but did not specify which jets participated");
280 return StatusCode::FAILURE;
281 }
282
283 auto legIndices = jetCollector.legInds();
284 if (!(legIndices.size() == (m_endLabelIndex - m_startLabelIndex))) {
285 ATH_MSG_ERROR("inconsistent number of leg indices");
286 return StatusCode::FAILURE;
287 }
288
289 ATH_MSG_DEBUG("check passing jets? does it work?");
290 ATH_MSG_DEBUG("There are some indices: " << legIndices.size());
291 for(size_t i = 0; i < legIndices.size(); i ++){
292 ATH_MSG_DEBUG(" -- leg " << i << " has index " << legIndices.at(i));
293 }
294
295 // jet hypo inputs:
296 // pairs of const xAOD::Jet* (first) and mutable Decision* (second)
297
298 auto participating_jets = jetCollector.xAODJets();
299 if (infocollector) {
300 infocollector->
301 collect(name(),
302 "no of xAODJets " + std::to_string(participating_jets.size()));
303
304 auto legInds = jetCollector.legInds();
305 std::stringstream ss;
306
307 for(const auto& label : legInds){
308 auto jets = jetCollector.xAODJets(label);
309 ss << label << " [\n";
310 for(const auto& j : jets){
312 }
313 ss << "]\n";
314 }
315 infocollector->collect(name(), ss.str());
316 }
317
318 return StatusCode::SUCCESS;
319}
320
321StatusCode
323 const std::vector<JetDecision>& jetHypoInputs) const {
324
325 auto legIndices = jetCollector.legInds();
326 for(const auto& legInd : legIndices){
327 auto participating_jets = jetCollector.xAODJets(legInd);
328 CHECK(reportLeg(participating_jets, jetHypoInputs, legInd));
329 }
330
331 return StatusCode::SUCCESS;
332}
333
334
335
336
337StatusCode
338TrigJetHypoTool::reportLeg(const std::vector<const xAOD::Jet*>& jets,
339 const std::vector<JetDecision>& jetHypoInputs,
340 int legInd) const {
341
342 // check if input jet is a participating jet. If so , add
343 // its Decision object.
344 for (auto& pair : jetHypoInputs) {
345 if (!inputJetParticipates(jets, pair)){continue;}
346
347 TrigCompositeUtils::DecisionIDContainer passingIDs; // set<uint32_t>
348
349 // Add the Leg DecisionID.
350 // Required by any downstream Steps which need to consume jets which
351 // are satisfying this leg's jet cuts and by the following ComboHypo
352 // Note that if the chain is single-leg, then the ID will be the chain-ID
353 // rathe than a leg-specific ID
354 passingIDs.insert(getID(legInd).numeric());
355
356 // Copy these passingIDs into the Decision Object
357 // This call also performs de-duplication
359 }
360
361 return StatusCode::SUCCESS;
362}
363
364
365bool
366TrigJetHypoTool::inputJetParticipates(const std::vector<const xAOD::Jet*>& jets,
367 const JetDecision& pair) const {
368
369 return std::find(jets.begin(), jets.end(), pair.first) != jets.end();
370}
#define ATH_CHECK
Evaluate an expression and check for errors.
#define ATH_MSG_ERROR(x)
#define ATH_MSG_INFO(x)
#define ATH_MSG_DEBUG(x)
#define CHECK(...)
Evaluate an expression and check for errors.
std::vector< pHypoJet > HypoJetVector
Definition HypoJetDefs.h:27
static Double_t ss
Header file to be included by clients of the Monitored infrastructure.
HLT::Identifier createLegName(const HLT::Identifier &chainIdentifier, size_t counter)
Generate the HLT::Identifier which corresponds to a specific leg of a given chain.
HLT::Identifier getIDFromLeg(const HLT::Identifier &legIdentifier)
Generate the HLT::Identifier which corresponds to the chain name from the leg name.
bool isLegId(const HLT::Identifier &legIdentifier)
Recognise whether the chain ID is a leg ID.
AthAlgTool(const std::string &type, const std::string &name, const IInterface *parent)
Constructor with parameters:
MsgStream & msg() const
virtual std::string toString() const override
Group of local monitoring quantities and retain correlation when filling histograms
Declare a monitored scalar variable.
A monitored timer.
StatusCode checkPassingJets(const xAODJetCollector &, const std::unique_ptr< ITrigJetHypoInfoCollector > &) const
std::vector< HLT::Identifier > m_decisionIDs
StatusCode finalize()
std::atomic< size_t > m_id
TrigJetHypoTool(const std::string &type, const std::string &name, const IInterface *parent)
StatusCode reportLeg(const std::vector< const xAOD::Jet * > &jets, const std::vector< JetDecision > &jetHypoInputs, int legInd) const
std::pair< const xAOD::Jet *, TrigCompositeUtils::Decision * > JetDecision
ToolHandle< ITrigJetHypoToolHelper > m_helper
Gaudi::Property< std::size_t > m_endLabelIndex
Gaudi::Property< bool > m_visitDebug
const std::vector< HLT::Identifier > & getIDs() const
Gaudi::Property< std::string > m_chainName
ToolHandle< GenericMonitoringTool > m_monTool
const HLT::Identifier & getID(std::size_t) const
StatusCode initialize()
Gaudi::Property< std::size_t > m_startLabelIndex
HLT::Identifier m_decisionID
StatusCode decide(const xAOD::JetContainer *jets, const TrigCompositeUtils::DecisionIDContainer &previousDecisionIDs, std::vector< JetDecision > &jetHypoInputs) const
bool inputJetParticipates(const std::vector< const xAOD::Jet * > &jets, const JetDecision &pair) const
StatusCode reportPassingJets(const xAODJetCollector &, const std::vector< JetDecision > &jetHypoInputs) const
STL class.
std::vector< const xAOD::Jet * > xAODJets() const
std::size_t size() const
HypoJetVector hypoJets() const
std::vector< int > legInds() const
std::string label(const std::string &format, int i)
Definition label.h:19
std::vector< std::string > lineSplitter(const std::string &s, char delimiter)
It used to be useful piece of code for replacing actual SG with other store of similar functionality ...
HLT::Identifier createLegName(const HLT::Identifier &chainIdentifier, size_t counter)
Generate the HLT::Identifier which corresponds to a specific leg of a given chain.
unsigned int DecisionID
void insertDecisionIDs(const Decision *src, Decision *dest)
Appends the decision IDs of src to the dest decision object.
HLT::Identifier getIDFromLeg(const HLT::Identifier &legIdentifier)
Generate the HLT::Identifier which corresponds to the chain name from the leg name.
bool passed(DecisionID id, const DecisionIDContainer &idSet)
checks if required decision ID is in the set of IDs in the container
std::set< DecisionID > DecisionIDContainer
bool isLegId(const HLT::Identifier &legIdentifier)
Recognise whether the chain ID is a leg ID.
JetContainer_v1 JetContainer
Definition of the current "jet container version".