ATLAS Offline Software
Loading...
Searching...
No Matches
R3MatchingTool.cxx
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2026 CERN for the benefit of the ATLAS collaboration
3*/
4
11#include "xAODEgamma/Egamma.h"
12#include <numeric>
13#include <algorithm>
14
15
16namespace Trig
17{
18
19 R3MatchingTool::R3MatchingTool(const std::string &name) : asg::AsgTool(name)
20 {
21 m_trigDecTool.setTypeAndName("Trig::TrigDecisionTool/TrigDecisionTool");
22 declareProperty("TrigDecisionTool", m_trigDecTool, "The trigger decision tool");
23 }
24
26
28 {
29 ATH_CHECK(m_trigDecTool.retrieve());
30 ATH_CHECK(m_scoreTool.retrieve());
31 return StatusCode::SUCCESS;
32 }
33
35 const std::vector<const xAOD::IParticle *> &recoObjects,
36 std::string_view chain,
37 double matchThreshold,
38 bool rerun) const
39 {
40 if (recoObjects.size() == 0)
41 // If there are no reco objects, the matching is trivially true
42 return true;
43 // Make the LinkInfo type less verbose
45 using VecLinkInfo_t = std::vector<IPartLinkInfo_t>;
46 // TODO - detect if we're looking at run 3 data.
47 // If we are, then setting rerun to true should give a warning as it no
48 // longer makes sense for run 3
49
50 // In what follows, the same comparisons between reco and trigger objects will done
51 // fairly frequently. As these include DR checks we want to minimise how often we do these
52 // Therefore we keep track of any comparisons that we've already done
53 // There is one map per input reco object, and then each map entry is the keyed on information
54 // extracted from the element link
55 std::vector<std::map<std::pair<uint32_t, uint32_t>, bool>> cachedComparisons(recoObjects.size());
56
57 // Note that the user can supply a regex pattern which matches multiple chains
58 // We should return true if any individual chain matches
59 const Trig::ChainGroup *chainGroup = m_trigDecTool->getChainGroup(chain);
60 for (const std::string &chainName : chainGroup->getListOfTriggers())
61 {
62 const chainInfo_t &chainInfo = getChainInfo(chainName);
64 {
65 ATH_MSG_DEBUG("Chain " << chainName << " did not pass");
66 continue;
67 }
68 ATH_MSG_DEBUG("Chain " << chainName << " passed");
69 // Note: regarding R2-to-R3 converted trigger navigation. We do not pass
70 // TrigDefs::allowResurrectedDecision to the R3 feature request - the R3
71 // navigation has no concept of rerun. The physics objects of
72 // analysis-flagged R2 rerun chains have been copied to the R3 structure as
73 // if they had passed in the initial pass. The rerun status of R2 trigger
74 // chains remains available from the TrigDecisionTool.
75 Trig::FeatureRequestDescriptor frd(chainName);
76 VecLinkInfo_t features = m_trigDecTool->features<xAOD::IParticleContainer>(frd);
77
78 // Note: regarding R2-to-R3 converted trigger navigation. If
79 // IncludeSubfeatures is enabled, also retrieve the subfeature links:
80 // lower-pT objects from within a single R2 RoI, which the standard
81 // DAOD-based trigger matching procedure used prior to this migration did
82 // not consider.
84 frd.setLinkName("subfeature");
85 VecLinkInfo_t subfeatures = m_trigDecTool->features<xAOD::IParticleContainer>(frd);
86 features.insert(features.end(), subfeatures.begin(), subfeatures.end());
87 ATH_MSG_DEBUG("Added " << subfeatures.size() << " subfeatures for chain " << chainName);
88 }
89
90
91 // See if we have any that have invalid links. This is a sign that the
92 // input file does not contain the required information and should be seen
93 // as reason for a job failure
94 for (IPartLinkInfo_t &linkInfo : features)
95 {
96 if (!linkInfo.isValid())
97 {
98 ATH_MSG_ERROR("Chain " << chainName << " has invalid link info!");
99 throw std::runtime_error("Bad link info");
100 }
101 }
102 // Now we have to build up combinations
103 // TODO - right now we use a filter that passes everything that isn't pointer-equal.
104 // This will probably need to be fixed to something else later - at least the unique RoI filter
106 chainName,
107 features,
108 chainInfo.first,
110 // Warn once per call if one of the chain groups is too small to match anything
111 if (combinations.size() < recoObjects.size())
112 {
114 "Chain " << chainName << " (matching pattern " << chain << ") has too few objects ("
115 << combinations.size() << ") to match the number of provided reco objects (" << recoObjects.size() << ")");
116 continue;
117 }
118 // Now we iterate through the available combinations
119 for (const VecLinkInfo_t &combination : combinations)
120 {
121 // Prepare the index vector
122 std::vector<std::size_t> onlineIndices(combination.size());
123 std::iota(onlineIndices.begin(), onlineIndices.end(), 0);
124 do
125 {
126 bool match = true;
127 for (std::size_t recoIdx = 0; recoIdx < recoObjects.size(); ++recoIdx)
128 {
129 std::size_t onlineIdx = onlineIndices[recoIdx];
130 if (!matchObjects(
131 recoObjects[recoIdx],
132 combination[onlineIdx].link,
133 chainInfo.second[onlineIdx],
134 cachedComparisons[recoIdx],
135 matchThreshold))
136 {
137 match = false;
138 break;
139 }
140 }
141 if (match)
142 return true;
143 } while (std::next_permutation(onlineIndices.begin(), onlineIndices.end()));
144 }
145 }
146
147 // If we reach here we've tried all combinations from all chains in the group and none of them matched
148 return false;
149 }
150
152 const xAOD::IParticle &recoObject,
153 std::string_view chain,
154 double matchThreshold,
155 bool rerun) const
156 {
157 std::vector<const xAOD::IParticle *> tmpVec{&recoObject};
158 return match(tmpVec, chain, matchThreshold, rerun);
159 }
160
162 const xAOD::IParticle *reco,
164 xAODType::ObjectType onlineType,
165 std::map<std::pair<uint32_t, uint32_t>, bool> &cache,
166 double scoreThreshold) const
167 {
168 if (!onlineLink.isValid())
169 {
170 ATH_MSG_WARNING("Invalid element link!");
171 return false;
172 }
173 std::pair<uint32_t, uint32_t> linkIndices(onlineLink.persKey(), onlineLink.persIndex());
174 auto cacheItr = cache.find(linkIndices);
175 if (cacheItr == cache.end())
176 {
177 const xAOD::IParticle *online = *onlineLink;
178 ATH_MSG_DEBUG("Match online " << onlineType << " to offline " << reco->type());
179 bool match = onlineType == reco->type();
180 if (onlineType == xAOD::Type::CaloCluster && (reco->type() == xAOD::Type::Electron || reco->type() == xAOD::Type::Photon))
181 {
182 // Calo cluster is a special case - some of the egamma chains can return these (the etcut chains)
183 // In these cases we need to match this against the caloCluster object contained in electrons or photons
184 const xAOD::Egamma *egamma = dynamic_cast<const xAOD::Egamma *>(reco);
185 if (!egamma)
186 // this should never happen
187 throw std::runtime_error("Failed to cast to egamma object");
188 const xAOD::IParticle *cluster = egamma->caloCluster();
189 if (cluster)
190 reco = cluster;
191 else
192 ATH_MSG_WARNING("Cannot retrieve egamma object's primary calorimeter cluster, will match to the egamma object");
193 match = true;
194 }
195 if (reco->type() == xAOD::Type::TruthParticle) match=true;
196 if (match)
197 match = m_scoreTool->score(*online, *reco) < scoreThreshold;
198 cacheItr = cache.insert(std::make_pair(linkIndices, match)).first;
199 }
200 return cacheItr->second;
201 }
202
203 const R3MatchingTool::chainInfo_t &R3MatchingTool::getChainInfo(const std::string &chain) const
204 {
205 std::lock_guard<std::mutex> guard(m_chainInfoMutex);
206 auto cacheItr = m_chainInfoCache.find(chain);
207 if (cacheItr == m_chainInfoCache.end())
208 {
209 chainInfo_t info;
210 for (const ChainNameParser::LegInfo &legInfo : ChainNameParser::HLTChainInfo(chain))
211 {
212 const xAODType::ObjectType type = legInfo.type();
213 if (type == xAODType::Other)
214 {
215 // Use 0 to signal that a leg expects no IParticle features
216 info.first.push_back(0);
217 }
218 else
219 {
220 info.first.push_back(legInfo.multiplicity);
221 for (std::size_t idx = 0; idx < legInfo.multiplicity; ++idx)
222 info.second.push_back(type);
223 }
224 }
225 cacheItr = m_chainInfoCache.insert(std::make_pair(chain, std::move(info))).first;
226 }
227 return cacheItr->second;
228 }
229
230} // namespace Trig
#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,...)
Gaudi::Details::PropertyBase & declareProperty(Gaudi::Property< T, V, H > &t)
Helper class that provides access to information about individual legs.
stored_index_type persIndex() const
Return the index of the link.
sgkey_t persKey() const
Return the SG key that we reference, as a hash.
std::vector< std::string > getListOfTriggers() const
FeatureRequestDescriptor & setLinkName(const std::string &navElementLinkKey)
Set the Link Name Key.
ToolHandle< Trig::IMatchScoringTool > m_scoreTool
virtual StatusCode initialize() override
Dummy implementation of the initialisation function.
bool matchObjects(const xAOD::IParticle *reco, const ElementLink< xAOD::IParticleContainer > &onlineLink, xAODType::ObjectType onlineType, std::map< std::pair< uint32_t, uint32_t >, bool > &cache, double drThreshold) const
ToolHandle< TrigDecisionTool > m_trigDecTool
const chainInfo_t & getChainInfo(const std::string &chain) const
R3MatchingTool(const std::string &name)
virtual bool match(const std::vector< const xAOD::IParticle * > &recoObjects, std::string_view chain, double matchThreshold, bool rerun) const override
multi-object trigger matching
Gaudi::Property< bool > m_includeSubfeatures
std::pair< multInfo_t, typeInfo_t > chainInfo_t
AsgTool(const std::string &name)
Constructor specifying the tool instance's name.
Definition AsgTool.cxx:58
elec/gamma data class.
Definition egamma.h:59
Class providing the definition of the 4-vector interface.
Combinations buildCombinations(const std::string &chainName, const std::vector< LinkInfo< xAOD::IParticleContainer > > &features, const std::vector< std::size_t > &legMultiplicities, const IPartCombItr::FilterFunc_t &filter)
Produce the combinations for a set of features.
@ UniqueObjects
Do not allow any repeated objects.
The common trigger namespace for trigger analysis tools.
ObjectType
Type of objects that have a representation in the xAOD EDM.
Definition ObjectType.h:32
@ Photon
The object is a photon.
Definition ObjectType.h:47
@ Other
An object not falling into any of the other categories.
Definition ObjectType.h:34
@ CaloCluster
The object is a calorimeter cluster.
Definition ObjectType.h:39
@ TruthParticle
The object is a truth particle.
Definition ObjectType.h:67
@ Electron
The object is an electron.
Definition ObjectType.h:46
Egamma_v1 Egamma
Definition of the current "egamma version".
Definition Egamma.h:17
DataVector< IParticle > IParticleContainer
Simple convenience declaration of IParticleContainer.
Struct containing information on each leg of a chain.
Helper to keep a Decision object, ElementLink and ActiveState (with respect to some requested ChainGr...
Definition LinkInfo.h:22