ATLAS Offline Software
Loading...
Searching...
No Matches
TrigADComboHypoTool Class Reference

#include <TrigADComboHypoTool.h>

Inheritance diagram for TrigADComboHypoTool:
Collaboration diagram for TrigADComboHypoTool:

Public Member Functions

 TrigADComboHypoTool (const std::string &type, const std::string &name, const IInterface *parent)
virtual StatusCode initialize () override
virtual StatusCode decide (Combo::LegDecisionsMap &passingLegs, const EventContext &context) const override
 retrieves the decisions associated to this decId, make their combinations and apply the algorithm
virtual HLT::Identifier decisionId () const
 retrieves this ComboHypoTool's chain's decision ID
StatusCode setLegMultiplicity (const Combo::MultiplicityReqMap &multiplicityRequiredMap)
 Sets the number of legs and the multiplicity required on each leg.
const std::vector< int > & legMultiplicity () const
 Gets the number of legs and the multiplicity required on each leg.
HLT::Identifier legDecisionId (size_t i) const
 Retrieves this ComboHypoTool's chain's decision ID for a given leg.
const std::vector< HLT::Identifier > & legDecisionIds () const
 Retrieves this ComboHypoTool's chain's decision IDs for all legs.
virtual StatusCode decideOnSingleObject (TrigCompositeUtils::Decision *, const std::vector< const TrigCompositeUtils::DecisionIDContainer * > &) const
 Alternate method called by BPhysics ComboHypoAlgs instead of the base method decide(...).

Protected Member Functions

virtual bool executeAlg (const std::vector< Combo::LegDecision > &combination, const EventContext &ctx) const
 Only a dummy implementation exists in ComboHypoToolBase.
StatusCode selectLegs (const Combo::LegDecisionsMap &IDCombMap, std::vector< std::vector< Combo::LegDecision > > &leg_decisions) const
 Creates the per-leg vectors of Decision objects starting from the initial LegDecision map, storing only those concerning this HypoTool's chain Pack the Decision objects in std::pair<DecisionID, ElementLink<Decision>> so the derived class' executeAlg function knows which leg each object is on.
void updateLegDecisionsMap (const std::vector< std::vector< Combo::LegDecision > > &passing_comb, Combo::LegDecisionsMap &passingLegs) const
 For when the tool accepts some/all combinations.
void eraseFromLegDecisionsMap (Combo::LegDecisionsMap &passingLegs) const
 For when the tool rejects all combinations.
void printDebugInformation (const Combo::LegDecisionsMap &passingLegs) const
 Print the output of the tool, after having removed failed Decision Objects.

Protected Attributes

Gaudi::Property< size_t > m_combinationsThresholdWarn
Gaudi::Property< size_t > m_combinationsThresholdBreak
Gaudi::Property< bool > m_modeOR
Gaudi::Property< bool > m_enableOverride

Private Member Functions

float getAdScore (const std::vector< const xAOD::Jet * > &input_jets, const std::vector< const xAOD::Muon * > &input_muons, const std::vector< const xAOD::Electron * > &input_electrons, const std::vector< const xAOD::Photon * > &input_photons, const std::vector< const xAOD::TauJet * > &input_taus, const std::vector< const xAOD::TrigMissingET * > &input_mets) const
float runInference (std::vector< float > &tensor) const

Private Attributes

Gaudi::Property< unsigned int > m_maxjs {this, "max_jets",{6}, "Maximum number of jets allowed in the event"}
Gaudi::Property< unsigned int > m_maxes {this, "max_electrons",{3}, "Maximum number of electrons allowed in the event"}
Gaudi::Property< unsigned int > m_maxms {this, "max_muons",{3}, "Maximum number of muons allowed in the event"}
Gaudi::Property< unsigned int > m_maxgs {this, "max_photons",{3}, "Maximum number of photons allowed in the event"}
Gaudi::Property< double > m_adScoreThres {this, "adScoreThres", {0.}, "HLT AD score threshold"}
SG::WriteHandleKey< xAOD::TrigCompositeContainerm_adScoreKey {this, "adScoreKey", "Undefined", ""}
ToolHandle< GenericMonitoringToolm_monTool {this, "monTool", "", "Monitoring tool"}
Gaudi::Property< bool > m_monFlag {this, "monFlag", false, "Monitoring flag"}
ServiceHandle< AthOnnx::IOnnxRuntimeSvcm_svc {this, "ONNXRuntimeSvc", "AthOnnx::OnnxRuntimeSvc", "TrigADComboHypoTool ONNXRuntimeSvc"}
std::unique_ptr< Ort::Session > m_session
std::vector< const char * > m_input_node_names
std::vector< const char * > m_output_node_names
std::vector< int64_t > m_input_node_dims
Gaudi::Property< std::string > m_modelFileName {this, "ModelFileName", "TrigAnomalyDetectionHypo/2025-03-10/HLT_AD_v1.onnx"}
HLT::Identifier m_decisionId
 The DecisionID of the chain, obtained from the Tool's name.
std::vector< HLT::Identifierm_legDecisionIds
 The DecisionIDs of the individual legs, derived from both m_decisionId and m_legMultiplicities.
std::vector< int > m_legMultiplicities
 The number of legs, and the required multiplicity on each leg.

Detailed Description

Definition at line 26 of file TrigADComboHypoTool.h.

Constructor & Destructor Documentation

◆ TrigADComboHypoTool()

TrigADComboHypoTool::TrigADComboHypoTool ( const std::string & type,
const std::string & name,
const IInterface * parent )

Definition at line 24 of file TrigADComboHypoTool.cxx.

24: ComboHypoToolBase(type, name, parent) {}
ComboHypoToolBase(const std::string &type, const std::string &name, const IInterface *parent)

Member Function Documentation

◆ decide()

StatusCode TrigADComboHypoTool::decide ( Combo::LegDecisionsMap & passingLegs,
const EventContext & ctx ) const
overridevirtual

retrieves the decisions associated to this decId, make their combinations and apply the algorithm

Parameters
[in]LegDecisionsMapthat lists all the passing decisions, to be updated by the tool depending on the outcome of executeAlg
[in]EventContext

Reimplemented from ComboHypoToolBase.

Definition at line 104 of file TrigADComboHypoTool.cxx.

104 {
105
106 ATH_MSG_DEBUG("Size of passingLegs = " << passingLegs.size());
107
108 if (passingLegs.size() == 0) { // if no combinations passed, then exit
109 return StatusCode::SUCCESS;
110 }
111
112 std::vector<std::vector<Combo::LegDecision>> legDecisions;
113 ATH_CHECK(selectLegs(passingLegs, legDecisions));
114
115 // get the lists of each object
116 ATH_MSG_DEBUG("Have "<<passingLegs.size()<<" passing legs in AD");
117
118 std::vector<const xAOD::Jet*> input_jets;
119 std::map<const xAOD::Jet*, std::vector<Combo::LegDecision>> jet_decisions;
120 std::vector<const xAOD::Electron*> input_electrons;
121 std::map<const xAOD::Electron*, std::vector<Combo::LegDecision>> ele_decisions;
122 std::vector<const xAOD::Muon*> input_muons;
123 std::map<const xAOD::Muon*, std::vector<Combo::LegDecision>> muon_decisions;
124 std::vector<const xAOD::Photon*> input_photons;
125 std::map<const xAOD::Photon*, std::vector<Combo::LegDecision>> gam_decisions;
126 std::vector<const xAOD::TauJet*> input_taus;
127 std::map<const xAOD::TauJet*, std::vector<Combo::LegDecision>> taujet_decisions;
128 std::vector<const xAOD::TrigMissingET*> input_mets;
129 std::map<const xAOD::TrigMissingET*, std::vector<Combo::LegDecision>> met_decisions;
130
131 for(const auto &leg_decs : legDecisions){ // loop over each leg
132 for(const auto &dec_pair : leg_decs){ // loop over each object in a leg
133 const TrigCompositeUtils::Decision* decision(*(dec_pair.second));
134 std::vector<TrigCompositeUtils::LinkInfo<xAOD::JetContainer>> jet_feature_links = TrigCompositeUtils::findLinks<xAOD::JetContainer>(decision, TrigCompositeUtils::featureString(), TrigDefs::lastFeatureOfType);
135 std::vector<TrigCompositeUtils::LinkInfo<xAOD::ElectronContainer>> ele_feature_links = TrigCompositeUtils::findLinks<xAOD::ElectronContainer>(decision, TrigCompositeUtils::featureString(), TrigDefs::lastFeatureOfType);
136 std::vector<TrigCompositeUtils::LinkInfo<xAOD::MuonContainer>> muon_feature_links = TrigCompositeUtils::findLinks<xAOD::MuonContainer>(decision, TrigCompositeUtils::featureString(), TrigDefs::lastFeatureOfType);
137 std::vector<TrigCompositeUtils::LinkInfo<xAOD::PhotonContainer>> gam_feature_links = TrigCompositeUtils::findLinks<xAOD::PhotonContainer>(decision, TrigCompositeUtils::featureString(), TrigDefs::lastFeatureOfType);
138 std::vector<TrigCompositeUtils::LinkInfo<xAOD::TauJetContainer>> taujet_feature_links = TrigCompositeUtils::findLinks<xAOD::TauJetContainer>(decision, TrigCompositeUtils::featureString(), TrigDefs::lastFeatureOfType);
139 std::vector<TrigCompositeUtils::LinkInfo<xAOD::TrigMissingETContainer>> met_feature_links = TrigCompositeUtils::findLinks<xAOD::TrigMissingETContainer>(decision, TrigCompositeUtils::featureString(), TrigDefs::lastFeatureOfType);
140 if(jet_feature_links.size()==1){
141 const TrigCompositeUtils::LinkInfo<xAOD::JetContainer> jet_feature_link = jet_feature_links.at(0);
142 ATH_CHECK(jet_feature_link.isValid());
143 const xAOD::Jet* jet = *(jet_feature_link.link);
144 jet_decisions[jet].push_back(dec_pair);
145 }
146 if(ele_feature_links.size()==1){
147 const TrigCompositeUtils::LinkInfo<xAOD::ElectronContainer> ele_feature_link = ele_feature_links.at(0);
148 ATH_CHECK(ele_feature_link.isValid());
149 const xAOD::Electron* electron = *(ele_feature_link.link);
150 ele_decisions[electron].push_back(dec_pair);
151 }
152 if(muon_feature_links.size()==1){
153 const TrigCompositeUtils::LinkInfo<xAOD::MuonContainer> muon_feature_link = muon_feature_links.at(0);
154 ATH_CHECK(muon_feature_link.isValid());
155 const xAOD::Muon* muon = *(muon_feature_link.link);
156 muon_decisions[muon].push_back(dec_pair);
157 }
158 if(gam_feature_links.size()==1){
159 const TrigCompositeUtils::LinkInfo<xAOD::PhotonContainer> gam_feature_link = gam_feature_links.at(0);
160 ATH_CHECK(gam_feature_link.isValid());
161 const xAOD::Photon* photon = *(gam_feature_link.link);
162 gam_decisions[photon].push_back(dec_pair);
163 }
164 if(taujet_feature_links.size()==1){
165 const TrigCompositeUtils::LinkInfo<xAOD::TauJetContainer> taujet_feature_link = taujet_feature_links.at(0);
166 ATH_CHECK(taujet_feature_link.isValid());
167 const xAOD::TauJet* taujet = *(taujet_feature_link.link);
168 taujet_decisions[taujet].push_back(dec_pair);
169 }
170 if(met_feature_links.size()==1){
171 const TrigCompositeUtils::LinkInfo<xAOD::TrigMissingETContainer> met_feature_link = met_feature_links.at(0);
172 ATH_CHECK(met_feature_link.isValid());
173 const xAOD::TrigMissingET* met = *(met_feature_link.link);
174 met_decisions[met].push_back(dec_pair);
175 }
176 }
177 }
178
179 for(const auto &pair : jet_decisions){
180 input_jets.push_back(pair.first);
181 }
182 if(input_jets.size()>1){
183 std::sort(input_jets.begin(), input_jets.end(),
184 [](const auto a, const auto b){
185 return a->pt() > b->pt();
186 });
187 }
188
189 for(const auto &pair : ele_decisions){
190 input_electrons.push_back(pair.first);
191 }
192 if(input_electrons.size()>1){
193 std::sort(input_electrons.begin(), input_electrons.end(),
194 [](const auto a, const auto b){
195 return a->pt() > b->pt();
196 });
197 }
198
199 for(const auto &pair : muon_decisions){
200 input_muons.push_back(pair.first);
201 }
202 if(input_muons.size()>1){
203 std::sort(input_muons.begin(), input_muons.end(),
204 [](const auto a, const auto b){
205 return a->pt() > b->pt();
206 });
207 }
208
209 for(const auto &pair : gam_decisions){
210 input_photons.push_back(pair.first);
211 }
212 if(input_photons.size()>1){
213 std::sort(input_photons.begin(), input_photons.end(),
214 [](const auto a, const auto b){
215 return a->pt() > b->pt();
216 });
217 }
218
219 for(const auto &pair : taujet_decisions){
220 input_taus.push_back(pair.first);
221 }
222 if(input_taus.size()>1){
223 std::sort(input_taus.begin(), input_taus.end(),
224 [](const auto a, const auto b){
225 return a->pt() > b->pt();
226 });
227 }
228
229 for(const auto &pair : met_decisions){
230 input_mets.push_back(pair.first);
231 }
232
233 float outputScore = this->getAdScore(input_jets, input_muons, input_electrons, input_photons, input_taus, input_mets);
234
235 // Recording Data
236 if(!m_adScoreKey.empty()){
237 auto adScoreContainer = std::make_unique< xAOD::TrigCompositeContainer>();
238 auto adScoreContainerAux = std::make_unique< xAOD::TrigCompositeAuxContainer>();
239 adScoreContainer->setStore(adScoreContainerAux.get());
240
242 adScoreContainer->push_back(adScore);
243 adScore->setDetail( "adScore", outputScore );
244
245 SG::WriteHandle<xAOD::TrigCompositeContainer> adScoreHandle(m_adScoreKey, context);
246 ATH_CHECK( adScoreHandle.record( std::move( adScoreContainer ), std::move( adScoreContainerAux ) ) );
247 }
248
249 // Monitoring
250 if(m_monFlag){
251 auto monScore = Monitored::Scalar<float>("adScore", -1.0);
252 auto monGroup = Monitored::Group(m_monTool, monScore); // possible use in future
253 monScore = outputScore;
254 }
255
256 bool trigPass = (outputScore > m_adScoreThres);
257
258 if(!trigPass){
259 eraseFromLegDecisionsMap(passingLegs);
260 }
261
262 return StatusCode::SUCCESS;
263}
#define ATH_CHECK
Evaluate an expression and check for errors.
#define ATH_MSG_DEBUG(x)
static Double_t a
StatusCode selectLegs(const Combo::LegDecisionsMap &IDCombMap, std::vector< std::vector< Combo::LegDecision > > &leg_decisions) const
Creates the per-leg vectors of Decision objects starting from the initial LegDecision map,...
void eraseFromLegDecisionsMap(Combo::LegDecisionsMap &passingLegs) const
For when the tool rejects all combinations.
Gaudi::Property< double > m_adScoreThres
SG::WriteHandleKey< xAOD::TrigCompositeContainer > m_adScoreKey
float getAdScore(const std::vector< const xAOD::Jet * > &input_jets, const std::vector< const xAOD::Muon * > &input_muons, const std::vector< const xAOD::Electron * > &input_electrons, const std::vector< const xAOD::Photon * > &input_photons, const std::vector< const xAOD::TauJet * > &input_taus, const std::vector< const xAOD::TrigMissingET * > &input_mets) const
Gaudi::Property< bool > m_monFlag
ToolHandle< GenericMonitoringTool > m_monTool
bool setDetail(const std::string &name, const TYPE &value)
Set an TYPE detail on the object.
const std::string & featureString()
void findLinks(const Decision *start, const std::string &linkName, std::vector< LinkInfo< T > > &links, unsigned int behaviour=TrigDefs::allFeaturesOfType, std::set< const xAOD::TrigComposite * > *fullyExploredFrom=nullptr)
search back the TC links for the object of type T linked to the one of TC (recursively) Populates pro...
static const unsigned int lastFeatureOfType
Run 3 "enum". Only return the final feature along each route through the navigation.
monGroup(analysis_chain)
void sort(typename DataModel_detail::iterator< DVL > beg, typename DataModel_detail::iterator< DVL > end)
Specialization of sort for DataVector/List.
Jet_v1 Jet
Definition of the current "jet version".
TrigComposite_v1 TrigComposite
Declare the latest version of the class.
TauJet_v3 TauJet
Definition of the current "tau version".
TrigMissingET_v1 TrigMissingET
Define the most recent version of the TrigMissingET class.
Muon_v1 Muon
Reference the current persistent version:
Photon_v1 Photon
Definition of the current "egamma version".
Electron_v1 Electron
Definition of the current "egamma version".
ElementLink< T > link
Link to the feature.
Definition LinkInfo.h:55

◆ decideOnSingleObject()

StatusCode ComboHypoToolBase::decideOnSingleObject ( TrigCompositeUtils::Decision * ,
const std::vector< const TrigCompositeUtils::DecisionIDContainer * > &  ) const
virtualinherited

Alternate method called by BPhysics ComboHypoAlgs instead of the base method decide(...).

This function should be considered a specialist use-case only. It must be over-ridden to do anything useful.

Reimplemented in TrigBmumuxComboHypoTool, and TrigMultiTrkComboHypoTool.

Definition at line 283 of file ComboHypoToolBase.cxx.

283 {
284 ATH_MSG_ERROR("Do not use ComboHypoToolBase on its own, inherit this class and override decideOnSingleObject.");
285 ATH_MSG_ERROR("NOTE: Only if you are also supplying your own decide(...) implimentation, or similar.");
286 ATH_MSG_ERROR("NOTE: Most uses cases should only need to override executeAlg(...).");
287 return StatusCode::FAILURE;
288}
#define ATH_MSG_ERROR(x)

◆ decisionId()

virtual HLT::Identifier ComboHypoToolBase::decisionId ( ) const
inlinevirtualinherited

retrieves this ComboHypoTool's chain's decision ID

Definition at line 41 of file ComboHypoToolBase.h.

41{ return m_decisionId; }
HLT::Identifier m_decisionId
The DecisionID of the chain, obtained from the Tool's name.

◆ eraseFromLegDecisionsMap()

void ComboHypoToolBase::eraseFromLegDecisionsMap ( Combo::LegDecisionsMap & passingLegs) const
protectedinherited

For when the tool rejects all combinations.

Remove all Decision Objects from all the legs of this HypoTool's chain.

Definition at line 253 of file ComboHypoToolBase.cxx.

253 {
254 for (auto& it : passingLegs) {
255 DecisionID id = it.first;
256 if (id == m_decisionId or (isLegId(id) and getIDFromLeg(id) == m_decisionId)) {
257 const size_t nDecisionObjects = it.second.size();
258 it.second.clear();
259 ATH_MSG_VERBOSE("-- Removed " << nDecisionObjects << " from " << id);
260 }
261 }
262}
#define ATH_MSG_VERBOSE(x)
unsigned int DecisionID
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.

◆ executeAlg()

bool ComboHypoToolBase::executeAlg ( const std::vector< Combo::LegDecision > & combination,
const EventContext & ctx ) const
protectedvirtualinherited

Only a dummy implementation exists in ComboHypoToolBase.

This should be over-ridden by a derived class. The derived class should return a boolean pass/fail for each possible combination in the event. param[in] combination A single combination of objects to be discriminated against. Vector contains the required number of objects over all legs. Use the pair.first to tell which leg a given pair.second decision object belongs to in the current combination.

Reimplemented in DebugComboHypoTool, DeltaRRoIComboHypoTool, TrigAFPDijetComboHypoTool, TrigBmumuxComboHypoTool, TrigEgammaTopoHypoTool, TrigMultiTrkComboHypoTool, TrigMuonEFIdtpInvMassHypoTool, and TrigMuonEFInvMassHypoTool.

Definition at line 278 of file ComboHypoToolBase.cxx.

278 {
279 ATH_MSG_ERROR("Do not use ComboHypoToolBase on its own, inherit this class and override executeAlg.");
280 return false;
281}

◆ getAdScore()

float TrigADComboHypoTool::getAdScore ( const std::vector< const xAOD::Jet * > & input_jets,
const std::vector< const xAOD::Muon * > & input_muons,
const std::vector< const xAOD::Electron * > & input_electrons,
const std::vector< const xAOD::Photon * > & input_photons,
const std::vector< const xAOD::TauJet * > & input_taus,
const std::vector< const xAOD::TrigMissingET * > & input_mets ) const
private

Definition at line 265 of file TrigADComboHypoTool.cxx.

271 {
272
273 ATH_MSG_DEBUG( "Counting AD input objects in the event ... "
274 << "Jets: " << input_jets.size() << ", "
275 << "Muons: " << input_muons.size() << ", "
276 << "Electrons: " << input_electrons.size() << ", "
277 << "Photons: " << input_photons.size() << ", "
278 << "TauJets: " << input_taus.size() << ", "
279 << "METs: " << input_mets.size());
280
281 // pt1 eta1 phi1 pt2 eta2 phi2 ... for 6 jets, 3 electrons, 3 muons, 3 photons, and MET
282 unsigned int metind = (m_maxjs.value()+m_maxes.value()+m_maxms.value()+m_maxgs.value())*3;
283 std::vector<float> inputTensor;
284
285 unsigned int jet_count = 0;
286 for(const auto &jet : input_jets){
287 ATH_MSG_DEBUG( std::setprecision(3) << std::fixed
288 << "jet[" << jet_count << "] = ("
289 << jet->pt()/1000 << ", "
290 << jet->eta() << ", "
291 << jet->phi() << ", "
292 << jet->m()/1000 << ")");
293 if (jet_count<m_maxjs.value()) {
294 inputTensor.insert(inputTensor.end(), {static_cast<float>(jet->pt()/1000), static_cast<float>(jet->eta()), static_cast<float>(jet->phi())});
295 jet_count++;
296 }
297 }
298 inputTensor.insert(inputTensor.end(), 3*(m_maxjs.value()-jet_count), 0.);
299
300 unsigned int ele_count = 0;
301 for(const auto &ele : input_electrons){
302 ATH_MSG_DEBUG( std::setprecision(3) << std::fixed
303 << "ele[" << ele_count << "] = ("
304 << ele->pt()/1000 << ", "
305 << ele->eta() << ", "
306 << ele->phi() << ", "
307 << ele->m()/1000 << ")");
308 if (ele_count<m_maxes.value()) {
309 inputTensor.insert(inputTensor.end(), {static_cast<float>(ele->pt()/1000), static_cast<float>(ele->eta()), static_cast<float>(ele->phi())});
310 ele_count++;
311 }
312 }
313 inputTensor.insert(inputTensor.end(), 3*(m_maxes.value()-ele_count), 0.);
314
315 unsigned int muon_count = 0;
316 for(const auto &muon : input_muons){
317 ATH_MSG_DEBUG( std::setprecision(3) << std::fixed
318 << "muon[" << muon_count << "] = ("
319 << muon->pt()/1000 << ", "
320 << muon->eta() << ", "
321 << muon->phi() << ", "
322 << muon->m()/1000 << ")");
323 if (muon_count<m_maxms.value()) {
324 inputTensor.insert(inputTensor.end(), {static_cast<float>(muon->pt()/1000), static_cast<float>(muon->eta()), static_cast<float>(muon->phi())});
325 muon_count++;
326 }
327 }
328 inputTensor.insert(inputTensor.end(), 3*(m_maxms.value()-muon_count), 0.);
329
330 unsigned int gam_count = 0;
331 for(const auto &gam : input_photons){
332 ATH_MSG_DEBUG( std::setprecision(3) << std::fixed
333 << "gam[" << gam_count << "] = ("
334 << gam->pt()/1000 << ", "
335 << gam->eta() << ", "
336 << gam->phi() << ", "
337 << gam->m()/1000 << ")");
338 if (gam_count<m_maxgs.value()) {
339 inputTensor.insert(inputTensor.end(), {static_cast<float>(gam->pt()/1000), static_cast<float>(gam->eta()), static_cast<float>(gam->phi())});
340 gam_count++;
341 }
342 }
343 inputTensor.insert(inputTensor.end(), 3*(m_maxgs.value()-gam_count), 0.);
344
345 inputTensor.insert(inputTensor.end(), {0., 0., 0.});
346 for(const auto &met : input_mets){
347 ROOT::Math::XYVectorF metv(met->ex(),met->ey());
348 float met_phi = metv.phi();
349 float met_et = metv.r();
350
351 ATH_MSG_DEBUG( std::setprecision(3) << std::fixed
352 << "MET = ("
353 << met_et/1000 << ", "
354 << met_phi << ")");
355 inputTensor[metind] = met_et/1000;
356 inputTensor[metind+2] = met_phi;
357 }
358
359 ATH_MSG_DEBUG("inputTensor size = " << inputTensor.size());
360 if(msgLvl(MSG::DEBUG)){
361 for (unsigned int i=0; i<inputTensor.size(); i++){
362 ATH_MSG_DEBUG("inputTensor[" << i << "] = " << inputTensor[i]);
363 }
364 }
365
366 float outputScore = runInference(inputTensor);
367 ATH_MSG_DEBUG("Computed TrigADScore: " << outputScore);
368
369 return outputScore;
370}
float runInference(std::vector< float > &tensor) const
Gaudi::Property< unsigned int > m_maxgs
Gaudi::Property< unsigned int > m_maxjs
Gaudi::Property< unsigned int > m_maxms
Gaudi::Property< unsigned int > m_maxes

◆ initialize()

StatusCode TrigADComboHypoTool::initialize ( )
overridevirtual

Definition at line 26 of file TrigADComboHypoTool.cxx.

26 {
27
28 if (!m_monTool.empty()) ATH_CHECK(m_monTool.retrieve());
29
31 if (m_adScoreKey.key() == "Undefined") {
32 ATH_MSG_ERROR("AD score key name is undefined" );
33 return StatusCode::FAILURE;
34 }
35
36 ATH_CHECK( m_svc.retrieve() );
37 std::string model_file_name = PathResolverFindCalibFile(m_modelFileName);
38
39 if (m_modelFileName.empty() || model_file_name.empty()) {
40 ATH_MSG_ERROR("Could not find the requested ONNX model file: " << m_modelFileName);
41 ATH_MSG_ERROR("Please make sure it exists in the ATLAS calibration area (https://atlas-groupdata.web.cern.ch/atlas-groupdata/), and provide a model file name relative to the root of the calibration area.");
42
43 return StatusCode::FAILURE;
44 }
45
46 // initialise session
47 Ort::SessionOptions session_options;
48 Ort::AllocatorWithDefaultOptions allocator;
49 session_options.SetIntraOpNumThreads(1);
50 session_options.SetGraphOptimizationLevel(ORT_ENABLE_BASIC);
51
52 m_session = std::make_unique<Ort::Session>(m_svc->env(), model_file_name.c_str(), session_options);
53
54 ATH_MSG_INFO("Created ONNX runtime session with model " << model_file_name);
55
56 size_t num_input_nodes = m_session->GetInputCount();
57 m_input_node_names.resize(num_input_nodes);
58
59 for (std::size_t i = 0; i < num_input_nodes; i++) {
60 char* input_name = m_session->GetInputNameAllocated(i, allocator).release();
61 ATH_MSG_DEBUG("Input " << i << " : " << " name= " << input_name);
62 m_input_node_names[i] = input_name;
63
64 Ort::TypeInfo type_info = m_session->GetInputTypeInfo(i);
65 auto tensor_info = type_info.GetTensorTypeAndShapeInfo();
66 ONNXTensorElementDataType type = tensor_info.GetElementType();
67 ATH_MSG_DEBUG("Input " << i << " : " << " type= " << type);
68
69 m_input_node_dims = tensor_info.GetShape();
70 ATH_MSG_DEBUG("Input " << i << " : num_dims= " << m_input_node_dims.size());
71 for (std::size_t j = 0; j < m_input_node_dims.size(); j++) {
72 if (m_input_node_dims[j] < 0) m_input_node_dims[j] = 1;
73 ATH_MSG_DEBUG("Input " << i << " : dim " << j << "= " << m_input_node_dims[j]);
74 }
75 }
76
77 std::vector<int64_t> output_node_dims;
78 size_t num_output_nodes = m_session->GetOutputCount();
79 ATH_MSG_DEBUG("Have output nodes " << num_output_nodes);
80 m_output_node_names.resize(num_output_nodes);
81
82 for (std::size_t i = 0; i < num_output_nodes; i++) {
83 char* output_name = m_session->GetOutputNameAllocated(i, allocator).release();
84 ATH_MSG_DEBUG("Output " << i << " : " << " name= " << output_name);
85 m_output_node_names[i] = output_name;
86
87 Ort::TypeInfo type_info = m_session->GetOutputTypeInfo(i);
88 auto tensor_info = type_info.GetTensorTypeAndShapeInfo();
89 ONNXTensorElementDataType type = tensor_info.GetElementType();
90 ATH_MSG_DEBUG("Output " << i << " : " << " type= " << type);
91
92 output_node_dims = tensor_info.GetShape();
93 ATH_MSG_DEBUG("Output " << i << " : num_dims= " << output_node_dims.size());
94 for (std::size_t j = 0; j < output_node_dims.size(); j++) {
95 if (output_node_dims[j] < 0) output_node_dims[j] = 1;
96 ATH_MSG_DEBUG("Output" << i << " : dim " << j << "= " << output_node_dims[j]);
97 }
98 }
99
100
101 return StatusCode::SUCCESS;
102}
#define ATH_MSG_INFO(x)
std::string PathResolverFindCalibFile(const std::string &logical_file_name)
ServiceHandle< AthOnnx::IOnnxRuntimeSvc > m_svc
Gaudi::Property< std::string > m_modelFileName
std::vector< const char * > m_output_node_names
std::unique_ptr< Ort::Session > m_session
std::vector< const char * > m_input_node_names
std::vector< int64_t > m_input_node_dims

◆ legDecisionId()

HLT::Identifier ComboHypoToolBase::legDecisionId ( size_t i) const
inlineinherited

Retrieves this ComboHypoTool's chain's decision ID for a given leg.

Only populated for chains with more than one leg. For chains with one leg, use decisionId()

Definition at line 60 of file ComboHypoToolBase.h.

60{ return m_legDecisionIds.at(i); }
std::vector< HLT::Identifier > m_legDecisionIds
The DecisionIDs of the individual legs, derived from both m_decisionId and m_legMultiplicities.

◆ legDecisionIds()

const std::vector< HLT::Identifier > & ComboHypoToolBase::legDecisionIds ( ) const
inlineinherited

Retrieves this ComboHypoTool's chain's decision IDs for all legs.

Only populated for chains with more than one leg. For chains with one leg, use decisionId()

Definition at line 66 of file ComboHypoToolBase.h.

66{ return m_legDecisionIds; }

◆ legMultiplicity()

const std::vector< int > & ComboHypoToolBase::legMultiplicity ( ) const
inlineinherited

Gets the number of legs and the multiplicity required on each leg.

Definition at line 54 of file ComboHypoToolBase.h.

54{ return m_legMultiplicities; }
std::vector< int > m_legMultiplicities
The number of legs, and the required multiplicity on each leg.

◆ printDebugInformation()

void ComboHypoToolBase::printDebugInformation ( const Combo::LegDecisionsMap & passingLegs) const
protectedinherited

Print the output of the tool, after having removed failed Decision Objects.

Restricted to the ComboHypoTool's chain's legs.

Definition at line 264 of file ComboHypoToolBase.cxx.

264 {
265 ATH_MSG_DEBUG("ComboHypoToolBase: End of " << m_decisionId << ", passing elements are: ");
266 for (const auto& [id, ELV] : passingLegs) {
267 // Only print for this chain
268 if (id == m_decisionId or (isLegId(id) and m_decisionId == getIDFromLeg(id))) {
269 ATH_MSG_DEBUG("-- " << HLT::Identifier(id) << " with " << ELV.size() << " elements");
270 for (const auto& EL : ELV) {
271 ATH_MSG_DEBUG("-- -- container:" << EL.dataID() << ", index:" << EL.index());
272 }
273 }
274 }
275}
ElementLink< CVec > EL

◆ runInference()

float TrigADComboHypoTool::runInference ( std::vector< float > & tensor) const
private

Definition at line 372 of file TrigADComboHypoTool.cxx.

372 {
373
374 ATH_MSG_DEBUG("in TrigADComboHypoTool::runInference()");
375
376 auto memory_info = Ort::MemoryInfo::CreateCpu(OrtArenaAllocator, OrtMemTypeDefault);
377 int input_tensor_size = (m_maxjs.value()+m_maxes.value()+m_maxms.value()+m_maxgs.value()+1)*3;
378 Ort::Value input_tensor = Ort::Value::CreateTensor<float>(memory_info, tensor.data(), input_tensor_size, m_input_node_dims.data(), m_input_node_dims.size());
379
380 // Ort::Session::Run is non-const.
381 // However, the onnx authors claim that it is safe to call from multiple threads:
382 // https://github.com/Microsoft/onnxruntime/issues/114
383 Ort::Session* session ATLAS_THREAD_SAFE = m_session.get();
384 auto output_tensors = session->Run(Ort::RunOptions{nullptr}, m_input_node_names.data(), &input_tensor, m_input_node_names.size(), m_output_node_names.data(), m_output_node_names.size());
385
386 float *output_score_array = output_tensors.front().GetTensorMutableData<float>();
387 unsigned int output_size = output_tensors.front().GetTensorTypeAndShapeInfo().GetElementCount();
388
389 float output_score = 0.;
390 if(output_size!=1){
391 ATH_MSG_ERROR("Invalid output tensor size: " << output_size);
392 }else{
393 output_score = output_score_array[0];
394 }
395
396 return output_score;
397}
#define ATLAS_THREAD_SAFE

◆ selectLegs()

StatusCode ComboHypoToolBase::selectLegs ( const Combo::LegDecisionsMap & IDCombMap,
std::vector< std::vector< Combo::LegDecision > > & leg_decisions ) const
protectedinherited

Creates the per-leg vectors of Decision objects starting from the initial LegDecision map, storing only those concerning this HypoTool's chain Pack the Decision objects in std::pair<DecisionID, ElementLink<Decision>> so the derived class' executeAlg function knows which leg each object is on.

Definition at line 172 of file ComboHypoToolBase.cxx.

173{
174 /*
175 legDecisions: nested vector like:
176 [(leg0, el0), (leg0, el1), (leg0, el2), (leg0, el3)], <-- All leg0 objects are in legDecisions[0][X]
177 [(leg1, mu0), (leg1, mu1)] <-- All leg1 objects are in legDecisions[1][X]
178 We keep the legID in the std::pair inside the inner vector as these pairs will be flattened into a single vector
179 when individual combinations of objects are passed to executeAlg, pair.first then contains the leg, with pair.second containing the Decision Object.
180 */
181
182 // Extract from IDCombMap the features for this chain. Wrap the features up in a pair along with their leg ID
183 for (size_t legIndex = 0; legIndex < m_legMultiplicities.size(); ++ legIndex) {
184
185 // If the chain has more than one leg, then we have per-leg IDs. Otherwise we just use the chain's ID
186 const HLT::Identifier& legIdentifier = (m_legMultiplicities.size() > 1 ? m_legDecisionIds.at(legIndex) : m_decisionId);
187
188 // Combo::LegDecision is a pair of <DecisionID, ElementLink<Decision>>
189 std::vector<Combo::LegDecision> decisionObjectsOnLeg;
190
191 // Find physics objects on this leg. May be zero.
192 const Combo::LegDecisionsMap::const_iterator it = IDCombMap.find(legIdentifier.numeric());
193
194 if (it != IDCombMap.end()) {
195 for (const ElementLink<DecisionContainer>& el : it->second) {
196 decisionObjectsOnLeg.emplace_back(legIdentifier, el);
197 }
198 }
199
200 legDecisions.push_back(std::move(decisionObjectsOnLeg));
201 }
202
203 if (msgLvl(MSG::DEBUG)) {
204 ATH_MSG_DEBUG("Getting " << legDecisions.size() << " legs to combine, for ID: " << decisionId());
205 size_t count = 0;
206 for (const auto& leg : legDecisions) {
207 ATH_MSG_DEBUG("Leg " << count++ << " --");
208 for (const auto& dEL : leg) {
209 ATH_MSG_DEBUG("-- " << HLT::Identifier(dEL.first) << " container:" << dEL.second.dataID() << ", index:" << dEL.second.index());
210 }
211 }
212 }
213 return StatusCode::SUCCESS;
214}
virtual HLT::Identifier decisionId() const
retrieves this ComboHypoTool's chain's decision ID
TrigCompositeUtils::DecisionID numeric() const
numeric ID
int count(std::string s, const std::string &regx)
count how many occurances of a regx are in a string
Definition hcg.cxx:146

◆ setLegMultiplicity()

StatusCode ComboHypoToolBase::setLegMultiplicity ( const Combo::MultiplicityReqMap & multiplicityRequiredMap)
inherited

Sets the number of legs and the multiplicity required on each leg.

This should be called when the Tool is retrieved by its parent ComboHypo alg. This also sets the leg Decision IDs at the same time param[in] multiplicityRequiredMap: Mapping of chains to required multiplicity per leg.

Definition at line 16 of file ComboHypoToolBase.cxx.

16 {
17 const std::string nameOfToolsChain = m_decisionId.name();
18 const Combo::MultiplicityReqMap::const_iterator it = multiplicityRequiredMap.find(nameOfToolsChain);
19
20 if (it == multiplicityRequiredMap.end()) {
21 ATH_MSG_ERROR("ComboHypoTool for " << m_decisionId << " could not find its required multiplcity data in the map supplied by its parent alg.");
22 return StatusCode::FAILURE;
23 }
24
25 m_legMultiplicities = it->second;
26 if (m_legMultiplicities.size() == 0) {
27 ATH_MSG_ERROR("ComboHypoTool for " << m_decisionId << " was listed in the supplied multiplicityRequiredMap, but data was not supplied for any legs.");
28 return StatusCode::FAILURE;
29 }
30
31 m_legDecisionIds.clear();
32 for (size_t i = 0; i < m_legMultiplicities.size(); ++i) {
33 if(m_legMultiplicities.at(i) < 0) {
34 ATH_MSG_ERROR("ComboHypoTool for " << m_decisionId << " has been configured with an impossible multiplicity requirement of " << m_legMultiplicities.at(i) << " on leg " << i);
35 return StatusCode::FAILURE;
36 }
37 ATH_MSG_DEBUG("ComboHypoTool for " << m_decisionId << " will require multiplicity " << m_legMultiplicities.at(i) << " on leg " << i);
38 if (m_legMultiplicities.size() > 1) { // We only have per-leg IDs when there is more than one leg
40 } else { // For one leg, just repete the chain's ID
42 }
43 }
44
45 return StatusCode::SUCCESS;
46}
HLT::Identifier createLegName(const HLT::Identifier &chainIdentifier, size_t counter)
Generate the HLT::Identifier which corresponds to a specific leg of a given chain.

◆ updateLegDecisionsMap()

void ComboHypoToolBase::updateLegDecisionsMap ( const std::vector< std::vector< Combo::LegDecision > > & passing_comb,
Combo::LegDecisionsMap & passingLegs ) const
protectedinherited

For when the tool accepts some/all combinations.

Remove Decision Objects from legs of this HypoTool's chain which participated in NONE of combinations which were flagged as accepting the event.

Definition at line 216 of file ComboHypoToolBase.cxx.

216 {
217 if (msgLvl(MSG::DEBUG)) {
218 size_t count = 0;
219 for (const std::vector<Combo::LegDecision>& comb : passingComb) {
220 ATH_MSG_DEBUG("-- Passing combination " << count++ << " of " << passingComb.size());
221 for (const auto& [id, EL] : comb) {
222 ATH_MSG_DEBUG("-- -- " << HLT::Identifier(id) << " container:" << EL.dataID() << ", index:" << EL.index());
223 }
224 }
225 }
226
227 // remove combinations that didn't pass from the final map passingLegs
228 for (auto& it : passingLegs) {
229 DecisionID legId = it.first;
230 if (not(legId == m_decisionId or (isLegId(legId) and getIDFromLeg(legId) == m_decisionId))) {
231 continue; // Some other chain, ignore it to get faster execution.
232 }
233 std::vector<ElementLink<DecisionContainer>> updatedDecisionObjectsOnLeg;
234 bool update = false;
235 // Loop over all passing combinations, and all Decision Objects in each passing combination. Find Decision Objects on this leg.
236 for (const std::vector<Combo::LegDecision>& comb : passingComb) {
237 for (const auto& [id, EL] : comb) {
238 // Check that this Decision Object is on the correct leg, and that we haven't collated it already from another combination.
239 if (id == legId and std::find(updatedDecisionObjectsOnLeg.begin(), updatedDecisionObjectsOnLeg.end(), EL) == updatedDecisionObjectsOnLeg.end()) {
240 ATH_MSG_VERBOSE("Keeping on leg " << HLT::Identifier(id) << " the Decision Object container:" << EL.dataID() << ", index:" << EL.index());
241 updatedDecisionObjectsOnLeg.push_back(EL);
242 update = true;
243 }
244 }
245 }
246 // only update those concerning this tool ID
247 if (update){
248 it.second = std::move(updatedDecisionObjectsOnLeg);
249 }
250 }
251}

Member Data Documentation

◆ m_adScoreKey

SG::WriteHandleKey<xAOD::TrigCompositeContainer> TrigADComboHypoTool::m_adScoreKey {this, "adScoreKey", "Undefined", ""}
private

Definition at line 42 of file TrigADComboHypoTool.h.

42{this, "adScoreKey", "Undefined", ""};

◆ m_adScoreThres

Gaudi::Property<double> TrigADComboHypoTool::m_adScoreThres {this, "adScoreThres", {0.}, "HLT AD score threshold"}
private

Definition at line 40 of file TrigADComboHypoTool.h.

40{this, "adScoreThres", {0.}, "HLT AD score threshold"};

◆ m_combinationsThresholdBreak

Gaudi::Property<size_t> ComboHypoToolBase::m_combinationsThresholdBreak
protectedinherited
Initial value:
{this, "CombinationsThresholdBreak", 10000,
"Events processing this many combinations will generate a second WARNING message, and the loop over combinations will be terminated at this point."}

Definition at line 109 of file ComboHypoToolBase.h.

109 {this, "CombinationsThresholdBreak", 10000,
110 "Events processing this many combinations will generate a second WARNING message, and the loop over combinations will be terminated at this point."};

◆ m_combinationsThresholdWarn

Gaudi::Property<size_t> ComboHypoToolBase::m_combinationsThresholdWarn
protectedinherited
Initial value:
{this, "CombinationsThresholdWarn", 1000,
"Events processing this many combinations will generate a WARNING message."}

Definition at line 106 of file ComboHypoToolBase.h.

106 {this, "CombinationsThresholdWarn", 1000,
107 "Events processing this many combinations will generate a WARNING message."};

◆ m_decisionId

HLT::Identifier ComboHypoToolBase::m_decisionId
privateinherited

The DecisionID of the chain, obtained from the Tool's name.

Definition at line 122 of file ComboHypoToolBase.h.

◆ m_enableOverride

Gaudi::Property<bool> ComboHypoToolBase::m_enableOverride
protectedinherited
Initial value:
{this, "EnableOverride", false,
"Stops processing combinations as soon as a valid combination is found in OR mode, or as soon as an invalid combination is found in AND mode. This is to save CPU."}

Definition at line 115 of file ComboHypoToolBase.h.

115 {this, "EnableOverride", false,
116 "Stops processing combinations as soon as a valid combination is found in OR mode, or as soon as an invalid combination is found in AND mode. This is to save CPU."};

◆ m_input_node_dims

std::vector<int64_t> TrigADComboHypoTool::m_input_node_dims
private

Definition at line 64 of file TrigADComboHypoTool.h.

◆ m_input_node_names

std::vector<const char *> TrigADComboHypoTool::m_input_node_names
private

Definition at line 60 of file TrigADComboHypoTool.h.

◆ m_legDecisionIds

std::vector<HLT::Identifier> ComboHypoToolBase::m_legDecisionIds
privateinherited

The DecisionIDs of the individual legs, derived from both m_decisionId and m_legMultiplicities.

Definition at line 123 of file ComboHypoToolBase.h.

◆ m_legMultiplicities

std::vector<int> ComboHypoToolBase::m_legMultiplicities
privateinherited

The number of legs, and the required multiplicity on each leg.

Definition at line 124 of file ComboHypoToolBase.h.

◆ m_maxes

Gaudi::Property<unsigned int> TrigADComboHypoTool::m_maxes {this, "max_electrons",{3}, "Maximum number of electrons allowed in the event"}
private

Definition at line 36 of file TrigADComboHypoTool.h.

36{this, "max_electrons",{3}, "Maximum number of electrons allowed in the event"};

◆ m_maxgs

Gaudi::Property<unsigned int> TrigADComboHypoTool::m_maxgs {this, "max_photons",{3}, "Maximum number of photons allowed in the event"}
private

Definition at line 38 of file TrigADComboHypoTool.h.

38{this, "max_photons",{3}, "Maximum number of photons allowed in the event"};

◆ m_maxjs

Gaudi::Property<unsigned int> TrigADComboHypoTool::m_maxjs {this, "max_jets",{6}, "Maximum number of jets allowed in the event"}
private

Definition at line 35 of file TrigADComboHypoTool.h.

35{this, "max_jets",{6}, "Maximum number of jets allowed in the event"};

◆ m_maxms

Gaudi::Property<unsigned int> TrigADComboHypoTool::m_maxms {this, "max_muons",{3}, "Maximum number of muons allowed in the event"}
private

Definition at line 37 of file TrigADComboHypoTool.h.

37{this, "max_muons",{3}, "Maximum number of muons allowed in the event"};

◆ m_modelFileName

Gaudi::Property<std::string> TrigADComboHypoTool::m_modelFileName {this, "ModelFileName", "TrigAnomalyDetectionHypo/2025-03-10/HLT_AD_v1.onnx"}
private

Definition at line 67 of file TrigADComboHypoTool.h.

67{this, "ModelFileName", "TrigAnomalyDetectionHypo/2025-03-10/HLT_AD_v1.onnx"}; // main area v1 (2025.03.10)

◆ m_modeOR

Gaudi::Property<bool> ComboHypoToolBase::m_modeOR
protectedinherited
Initial value:
{this, "ModeOR", true,
"Accepts based on the logical OR over all calls to executeAlg. If this flag is set to false then the logical AND is required instead."}

Definition at line 112 of file ComboHypoToolBase.h.

112 {this, "ModeOR", true,
113 "Accepts based on the logical OR over all calls to executeAlg. If this flag is set to false then the logical AND is required instead."};

◆ m_monFlag

Gaudi::Property<bool> TrigADComboHypoTool::m_monFlag {this, "monFlag", false, "Monitoring flag"}
private

Definition at line 44 of file TrigADComboHypoTool.h.

44{this, "monFlag", false, "Monitoring flag"};

◆ m_monTool

ToolHandle<GenericMonitoringTool> TrigADComboHypoTool::m_monTool {this, "monTool", "", "Monitoring tool"}
private

Definition at line 43 of file TrigADComboHypoTool.h.

43{this, "monTool", "", "Monitoring tool"};

◆ m_output_node_names

std::vector<const char *> TrigADComboHypoTool::m_output_node_names
private

Definition at line 62 of file TrigADComboHypoTool.h.

◆ m_session

std::unique_ptr<Ort::Session> TrigADComboHypoTool::m_session
private

Definition at line 58 of file TrigADComboHypoTool.h.

◆ m_svc

ServiceHandle<AthOnnx::IOnnxRuntimeSvc> TrigADComboHypoTool::m_svc {this, "ONNXRuntimeSvc", "AthOnnx::OnnxRuntimeSvc", "TrigADComboHypoTool ONNXRuntimeSvc"}
private

Definition at line 56 of file TrigADComboHypoTool.h.

56{this, "ONNXRuntimeSvc", "AthOnnx::OnnxRuntimeSvc", "TrigADComboHypoTool ONNXRuntimeSvc"};

The documentation for this class was generated from the following files: