ATLAS Offline Software
IParticleRetrievalTool.cxx
Go to the documentation of this file.
1 /*
2  Copyright (C) 2002-2024 CERN for the benefit of the ATLAS collaboration
3 */
4 
5 // Package includes
7 #include "CxxUtils/starts_with.h"
8 #include <ostream>
9 
10 // Anonymous namespace contains helper functions
11 namespace {
13  using CLIDTuple_t =
14  std::tuple<HLT::class_id_type, xAOD::Type::ObjectType, std::string>;
15 
16  template <std::size_t FROM, std::size_t TO>
17  bool CLIDLookUp(
20  {
21  static const std::vector<CLIDTuple_t> CLIDVector {
22  {1178459224, xAOD::Type::Muon, "xAOD::MuonContainer"},
23  {1087532415, xAOD::Type::Electron, "xAOD::ElectronContainer"},
24  {1219821989, xAOD::Type::CaloCluster, "xAOD::CaloClusterContainer"},
25  {1105575213, xAOD::Type::Photon, "xAOD::PhotonContainer"},
26  {1177172564, xAOD::Type::Tau, "xAOD::TauJetContainer"}
27  };
28  auto itr = std::find_if(CLIDVector.begin(), CLIDVector.end(),
29  [from] (const CLIDTuple_t& tup) {
30  return std::get<FROM>(tup) == from;
31  });
32  if (itr == CLIDVector.end() )
33  return false;
34  else {
35  to = std::get<TO>(*itr);
36  return true;
37  }
38  }
39  bool CLIDToObjectType(xAOD::Type::ObjectType& type, HLT::class_id_type clid)
40  {
41  return CLIDLookUp<0, 1>(type, clid);
42  }
43  bool ObjectTypeToCLID(HLT::class_id_type& clid, xAOD::Type::ObjectType type)
44  {
45  return CLIDLookUp<1, 0>(clid, type);
46  }
47  bool CLIDToContainerType(std::string& name, HLT::class_id_type clid)
48  {
49  return CLIDLookUp<0, 2>(name, clid);
50  }
51 
52 } //> end anonymous namespace
53 
54 namespace Trig {
56  asg::AsgTool(name)
57  {
58  declareProperty("TrigDecisionTool", m_tdt,
59  "The trigger decision tool to use.");
60  declareProperty("WarnOnNavigationError", m_warnOnNavigationFailure = true,
61  "Only spit a warning on a navigation error, don't cause a job failure.");
62 
63  }
64 
66 
68  {
69  ATH_MSG_INFO("Initializing " << name() );
70  ATH_CHECK( m_tdt.retrieve() );
71  return StatusCode::SUCCESS;
72  }
73 
75  std::vector<std::vector<const xAOD::IParticle*>>& combinations,
76  const std::string& chain,
77  bool rerun) const
78  {
79  // Make sure what we're getting is cleared.
80  combinations.clear();
81  // Start by getting the chain group
82  const ChainGroup* cg = m_tdt->getChainGroup(chain);
83  // Make sure that this group actually contains triggers. If it doesn't then
84  // this is very wrong and the job shouldn't be allowed to continue
85  if (cg->getListOfTriggers().size() == 0) {
86  ATH_MSG_ERROR("Chain group " << chain
87  << " is empty! This means that no matching chains were found!");
88  return StatusCode::FAILURE;
89  }
90  unsigned int condition = TrigDefs::Physics;
91  if (rerun)
92  condition |= TrigDefs::allowResurrectedDecision;
93  if (!cg->isPassed(condition) ) {
94  ATH_MSG_DEBUG("Chain: " << chain << " was not passed!");
95  return StatusCode::SUCCESS;
96  }
97 
98  FeatureContainer features = cg->features(condition);
99  for (const Combination& combo : features.getCombinations() ) {
100  // The assumption here is that each combination represents a *single* way
101  // in which the trigger could have been passed. This should be true for
102  // the types of trigger that this tool expects to examine. It won't be
103  // true for (e.g.) jet triggers.
104  std::vector<const xAOD::IParticle*> currentCombination;
105  bool navFailure = false;
106  for (const HLT::TriggerElement* te : combo.tes() ) {
107  if (!retrieveParticles(currentCombination, te, navFailure).isSuccess() ) {
108  // Interpret a failure this way so that we can report the chain name
109  ATH_MSG_ERROR("Failed to retrieve particles for chain " << chain );
110  return StatusCode::FAILURE;
111  }
112  // If the navigation failed for this combination ignore it completely
113  if (navFailure)
114  break;
115  }
116  if (navFailure)
117  ATH_MSG_WARNING("Skipping combination for chain " << chain
118  << " due to navigation failure");
119  else
120  combinations.push_back(currentCombination);
121  }
122  return StatusCode::SUCCESS;
123  }
124 
126  std::vector<const xAOD::IParticle*>& combination,
127  const HLT::TriggerElement* te,
128  bool& navFailure) const
129  {
130  ATH_MSG_DEBUG( "Processing TE " << Trig::getTEName(*te) );
131  // Keep track of whether or not we found a particle here.
132  const xAOD::IParticle* part = nullptr;
133  for (const auto& feature : te->getFeatureAccessHelpers() ) {
135  if (!CLIDToObjectType(type, feature.getCLID() ) )
136  // Skip any features that don't hold 'final' state particles
137  continue;
139  // If this is an egamma type we have to check if we are meant to be
140  // looking for a CaloCluster instead!
142  if (egType == xAOD::Type::Other) {
143  std::string message =
144  "Unable to determine the correct type for TE " + Trig::getTEName(*te);
145  navFailure = true;
148  return StatusCode::SUCCESS;
149  }
150  else {
152  return StatusCode::FAILURE;
153  }
154  }
155  else if (egType == xAOD::Type::CaloCluster) {
156  HLT::class_id_type clid = 0;
157  ObjectTypeToCLID(clid, egType);
158  // This will be where we store the TE containing the calo cluster
159  // feature
160  const HLT::TriggerElement* sourceTE = nullptr;
161  const HLT::TrigNavStructure* navigation =
162  m_tdt->ExperimentalAndExpertMethods().getNavigation();
164  navigation->getFeatureRecursively(te, clid, "", sourceTE);
165  if (!sourceTE) {
166  std::ostringstream os;
167  os << "Unable to retrieve feature of type " << egType
168  << " from TE " << Trig::getTEName(*te);
169  navFailure = true;
171  ATH_MSG_WARNING( os.str() );
172  return StatusCode::SUCCESS;
173  }
174  else {
175  ATH_MSG_ERROR( os.str() );
176  return StatusCode::FAILURE;
177  }
178  }
179  ATH_CHECK( retrieveFeatureParticle(part, egFeature, sourceTE, navFailure) );
180  if (navFailure)
181  return StatusCode::SUCCESS;
182  // If it's a calo-cluster like TE then stop here, otherwise we'll
183  // encounter the other EG type again and fail...
184  break;
185  }
186  else if (egType != type) {
187  // This is the wrong feature to be looking at
188  continue;
189  }
190  // Otherwise we continue as before
191  }
192  // If we found a particle from another feature access helper then this is
193  // a problem. Our assumption is that there is only one particle per leg!
194  if (part) {
195  std::string message = "TE" + Trig::getTEName(*te) + "has multiple " +
196  "'final' particles attached to it! This breaks this tool's asumptions!";
197  navFailure = true;
200  return StatusCode::SUCCESS;
201  }
202  else {
204  return StatusCode::FAILURE;
205  }
206  }
207  ATH_CHECK( retrieveFeatureParticle(part, feature, te, navFailure) );
208  if (navFailure)
209  return StatusCode::SUCCESS;
210  } //> end loop over features
211 
212  // If we found a particle then we can stop going through this branch of the
213  // tree
214  if (part) {
215  combination.push_back(part);
216  return StatusCode::SUCCESS;
217  }
218 
219  // Otherwise look at each of the next TEs separately
220  for (const HLT::TriggerElement* nextTE :
222  ATH_CHECK( retrieveParticles(combination, nextTE, navFailure) );
223 
224  return StatusCode::SUCCESS;
225  }
226 
228  const HLT::TriggerElement* te) const
229  {
230  // We need to check the TE name for this
231  std::string teName = Trig::getTEName(*te);
232  if (teName.find("etcut") != std::string::npos &&
233  teName.find("trkcut") == std::string::npos)
235  else if (CxxUtils::starts_with (teName, "EF_e"))
236  return xAOD::Type::Electron;
237  else if (CxxUtils::starts_with (teName, "EF_g"))
238  return xAOD::Type::Photon;
239  else
240  return xAOD::Type::Other;
241  }
242 
244  const xAOD::IParticle*& particle,
246  const HLT::TriggerElement* te,
247  bool& navFailure) const
248  {
249  // Get the right container type name
250  std::string containerType;
251  if (!CLIDToContainerType(containerType, feature.getCLID() ) ) {
252  ATH_MSG_ERROR("Unrecognised CLID " << feature.getCLID() << " received!");
253  // This isn't a navigation error - this is a failure in the tool's
254  // internal logic!
255  return StatusCode::FAILURE;
256  }
257  // Build a vector of typeless features so that we can use the central
258  // functions.
259  const HLT::TrigNavStructure* navigation =
260  m_tdt->ExperimentalAndExpertMethods().getNavigation();
261 
262 
264  auto typelessHolder = navigation->getHolder(feature);
265 
266  if (!typelessHolder) {
267  std::string message = "Typeless holder for feature not present!";
268  navFailure = true;
271  return StatusCode::SUCCESS;
272  }
273  else {
275  return StatusCode::FAILURE;
276  }
277  }
278  const xAOD::IParticleContainer* cont(nullptr);
279  // Get the name used in the event store
280  std::string key = HLTNavDetails::formatSGkey(
281  "HLT", containerType, typelessHolder->label() );
282  // Now things are *much* more familiar
283  if (!evtStore()->contains<xAOD::IParticleContainer>(key) ) {
284  std::string message = "Store does not contain " + key + "!";
285  navFailure = true;
288  return StatusCode::SUCCESS;
289  }
290  else {
292  return StatusCode::FAILURE;
293  }
294  }
295  ATH_CHECK( evtStore()->retrieve(cont, key) );
297  if (cont->size() < idx.objectsEnd() ) {
298  std::ostringstream os;
299  os << "Featured object end " << idx.objectsEnd()
300  << " is *after* the end of container " << key;
301  navFailure = true;
303  ATH_MSG_WARNING( os.str() );
304  return StatusCode::SUCCESS;
305  }
306  else {
307  ATH_MSG_ERROR( os.str() );
308  return StatusCode::FAILURE;
309  }
310  }
311  std::vector<const xAOD::IParticle*> particleFeatures;
312  particleFeatures.reserve(idx.objectsEnd() - idx.objectsBegin() );
313  auto begin = cont->begin();
314  auto end = cont->begin();
315  std::advance(begin, idx.objectsBegin() );
316  std::advance(end, idx.objectsEnd() );
317  particleFeatures.insert(particleFeatures.end(), begin, end);
318 
319  // Make sure the answer is what we expect
320  std::ostringstream os;
321  switch (particleFeatures.size() ) {
322  case 0:
323  os << "No particles retrieved from feature "
324  << navigation->label(feature.getCLID(), feature.getIndex().subTypeIndex() )
325  << " from TE " << Trig::getTEName(*te);
326  navFailure = true;
328  ATH_MSG_WARNING(os.str() );
329  return StatusCode::SUCCESS;
330  }
331  else {
332  ATH_MSG_ERROR(os.str() );
333  return StatusCode::FAILURE;
334  }
335  case 1:
336  // Set the output.
337  particle = particleFeatures.at(0);
338  break;
339  default:
340  // Some TEs can end up reporting multiple outputs within the same RoI.
341  // AFAIK this only happens within EGamma TEs but I don't know that for
342  // sure. In any case this shouldn't matter too much for the matching
343  // given that they will be nearby each other. Just return the highest pT
344  // object.
345  particle = *(std::max_element(
346  particleFeatures.begin(), particleFeatures.end(),
347  [] (const xAOD::IParticle* lhs, const xAOD::IParticle* rhs)
348  { return lhs->pt() < rhs->pt(); }) );
349  }
350  return StatusCode::SUCCESS;
351  }
352 
353 } //> end namespace Trig
python.PyKernel.retrieve
def retrieve(aClass, aKey=None)
Definition: PyKernel.py:110
LArG4FSStartPointFilter.part
part
Definition: LArG4FSStartPointFilter.py:21
Trig::IParticleRetrievalTool::getEGammaTEType
xAOD::Type::ObjectType getEGammaTEType(const HLT::TriggerElement *te) const
Get the type of particle that should be retrieved from this TE.
Definition: IParticleRetrievalTool.cxx:227
HLT::TriggerElement::ObjectIndex
Helper class for conversion from/to int stored in TE and pair of ints used in Navigation Object point...
Definition: TrigNavStructure/TrigNavStructure/TriggerElement.h:75
Trig::getTEName
std::string getTEName(const HLT::TriggerElement &te)
converts TEid to TE name (this may not always work, it depends on the availability of config)
Definition: TDTUtilities.cxx:61
Trig::IParticleRetrievalTool::m_tdt
ToolHandle< Trig::TrigDecisionTool > m_tdt
The TrigDecisionTool that will be used to get the navigation.
Definition: IParticleRetrievalTool.h:88
Trk::ParticleSwitcher::particle
constexpr ParticleHypothesis particle[PARTICLEHYPOTHESES]
the array of masses
Definition: ParticleHypothesis.h:76
xAOD::Electron
Electron_v1 Electron
Definition of the current "egamma version".
Definition: Event/xAOD/xAODEgamma/xAODEgamma/Electron.h:17
CxxUtils::starts_with
bool starts_with(const char *s, const char *prefix)
Test whether one null-terminated byte string starts with another.
Trig::IParticleRetrievalTool::m_warnOnNavigationFailure
bool m_warnOnNavigationFailure
Be forgiving about the navigation not matching our expectations.
Definition: IParticleRetrievalTool.h:91
runLayerRecalibration.chain
chain
Definition: runLayerRecalibration.py:175
ATH_MSG_INFO
#define ATH_MSG_INFO(x)
Definition: AthMsgStreamMacros.h:31
IParticleRetrievalTool.h
HLT::TrigNavStructure::label
std::string label(class_id_type clid, const index_or_label_type &sti_or_label) const
Definition: TrigNavStructure.cxx:775
Trig
The common trigger namespace for trigger analysis tools.
Definition: CaloTowerVecMon.h:44
ObjectType
ObjectType
Definition: BaseObject.h:11
AthCommonDataStore< AthCommonMsg< AlgTool > >::declareProperty
Gaudi::Details::PropertyBase & declareProperty(Gaudi::Property< T > &t)
Definition: AthCommonDataStore.h:145
PlotCalibFromCool.begin
begin
Definition: PlotCalibFromCool.py:94
asg
Definition: DataHandleTestTool.h:28
HLT::TriggerElement::FeatureAccessHelper::getCLID
class_id_type getCLID() const
Class ID of object.
Definition: TrigNavStructure/TrigNavStructure/TriggerElement.h:208
navigation2dot.teName
def teName(teid)
Definition: navigation2dot.py:59
LArG4GenerateShowerLib.condition
condition
Definition: LArG4GenerateShowerLib.py:19
Trig::IParticleRetrievalTool::IParticleRetrievalTool
IParticleRetrievalTool(const std::string &name)
Standard constructor.
Definition: IParticleRetrievalTool.cxx:55
HLTNavDetails::formatSGkey
std::string formatSGkey(const std::string &prefix, const std::string &containername, const std::string &label)
declaration of formatting function.
Definition: Holder.cxx:122
xAOD::IParticle
Class providing the definition of the 4-vector interface.
Definition: Event/xAOD/xAODBase/xAODBase/IParticle.h:40
HLT::TrigNavStructure
Definition: TrigNavStructure.h:40
ReweightUtils.message
message
Definition: ReweightUtils.py:15
xAOD::CaloCluster
CaloCluster_v1 CaloCluster
Define the latest version of the calorimeter cluster class.
Definition: Event/xAOD/xAODCaloEvent/xAODCaloEvent/CaloCluster.h:19
mergePhysValFiles.end
end
Definition: DataQuality/DataQualityUtils/scripts/mergePhysValFiles.py:93
Trig::ChainGroup::features
const FeatureContainer features(unsigned int condition=TrigDefs::Physics) const
returns all features related to given chain group of HLT chains or L1 items Note: This does not yet w...
Definition: Trigger/TrigAnalysis/TrigDecisionTool/Root/ChainGroup.cxx:726
Trig::IParticleRetrievalTool::~IParticleRetrievalTool
~IParticleRetrievalTool() override
Default destructor.
Definition: IParticleRetrievalTool.cxx:65
Trig::FeatureContainer
Definition: FeatureContainer.h:54
AthCommonDataStore< AthCommonMsg< AlgTool > >::evtStore
ServiceHandle< StoreGateSvc > & evtStore()
The standard StoreGateSvc (event store) Returns (kind of) a pointer to the StoreGateSvc.
Definition: AthCommonDataStore.h:85
HLT::TriggerElement::ObjectIndex::subTypeIndex
sub_index_type subTypeIndex() const
to get collection index
Definition: TrigNavStructure/Root/TriggerElement.cxx:247
ATH_MSG_ERROR
#define ATH_MSG_ERROR(x)
Definition: AthMsgStreamMacros.h:33
HLT::TrigNavStructure::getDirectPredecessors
static const std::vector< TriggerElement * > & getDirectPredecessors(const TriggerElement *te)
returns list of direct predecessors (nodes seeding me)
Definition: TrigNavStructure.cxx:120
EL::StatusCode
::StatusCode StatusCode
StatusCode definition for legacy code.
Definition: PhysicsAnalysis/D3PDTools/EventLoop/EventLoop/StatusCode.h:22
ATH_MSG_DEBUG
#define ATH_MSG_DEBUG(x)
Definition: AthMsgStreamMacros.h:29
Trig::Combination
Definition: Trigger/TrigAnalysis/TrigDecisionTool/TrigDecisionTool/Combination.h:55
HLT::TriggerElement
TriggerElement is the basic ingreedient of the interface between HLT algorithms and the navigation It...
Definition: TrigNavStructure/TrigNavStructure/TriggerElement.h:27
ATH_CHECK
#define ATH_CHECK
Definition: AthCheckMacros.h:40
HLT::class_id_type
uint32_t class_id_type
Definition: Trigger/TrigEvent/TrigNavStructure/Root/Types.h:11
Trig::IParticleRetrievalTool::retrieveFeatureParticle
StatusCode retrieveFeatureParticle(const xAOD::IParticle *&particle, const HLT::TriggerElement::FeatureAccessHelper &feature, const HLT::TriggerElement *te, bool &navFailure) const
Retrieve an IParticle from a feature.
Definition: IParticleRetrievalTool.cxx:243
DataVector
Derived DataVector<T>.
Definition: DataVector.h:581
ReadFromCoolCompare.os
os
Definition: ReadFromCoolCompare.py:231
starts_with.h
C++20-like starts_with/ends_with for strings.
Trig::ChainGroup
Definition: Trigger/TrigAnalysis/TrigDecisionTool/TrigDecisionTool/ChainGroup.h:51
Trig::ChainGroup::isPassed
bool isPassed(unsigned int condition=TrigDefs::Physics) const
tells if chain group passed
Definition: Trigger/TrigAnalysis/TrigDecisionTool/Root/ChainGroup.cxx:208
name
std::string name
Definition: Control/AthContainers/Root/debug.cxx:192
CxxUtils::to
CONT to(RANGE &&r)
Definition: ranges.h:32
HLT::TrigNavStructure::getFeatureRecursively
TriggerElement::FeatureAccessHelper getFeatureRecursively(const TriggerElement *startTE, class_id_type clid, const index_or_label_type &index_or_label, const TriggerElement *&sourceTE) const
recursive search for features the function is similar to the above butif th features is not found at ...
Definition: TrigNavStructure.cxx:797
xAOD::Photon
Photon_v1 Photon
Definition of the current "egamma version".
Definition: Event/xAOD/xAODEgamma/xAODEgamma/Photon.h:17
python.combo.combinations
def combinations(items, n)
Definition: combo.py:85
Muon
struct TBPatternUnitContext Muon
HLT::TriggerElement::FeatureAccessHelper::getIndex
const ObjectIndex & getIndex() const
index in the external ojects array
Definition: TrigNavStructure/TrigNavStructure/TriggerElement.h:209
HLT::TriggerElement::FeatureAccessHelper
the FeatureAccessHelper is a class used to keep track of features attached to this TE.
Definition: TrigNavStructure/TrigNavStructure/TriggerElement.h:192
ATH_MSG_WARNING
#define ATH_MSG_WARNING(x)
Definition: AthMsgStreamMacros.h:32
python.CaloScaleNoiseConfig.type
type
Definition: CaloScaleNoiseConfig.py:78
LArNewCalib_DelayDump_OFC_Cali.idx
idx
Definition: LArNewCalib_DelayDump_OFC_Cali.py:69
xAODType::Tau
@ Tau
The object is a tau (jet)
Definition: ObjectType.h:49
HLT::TriggerElement::getFeatureAccessHelpers
const std::vector< FeatureAccessHelper > & getFeatureAccessHelpers() const
returns all features which ara attached to this TE
Definition: TrigNavStructure/TrigNavStructure/TriggerElement.h:238
Trig::FeatureContainer::getCombinations
const std::vector< Trig::Combination > & getCombinations() const
gives back reference to combinations collected through append
Definition: FeatureContainer.h:135
Trig::ChainGroup::getListOfTriggers
std::vector< std::string > getListOfTriggers() const
Definition: Trigger/TrigAnalysis/TrigDecisionTool/Root/ChainGroup.cxx:467
DataVector::size
size_type size() const noexcept
Returns the number of elements in the collection.
Trig::IParticleRetrievalTool::retrieveParticles
StatusCode retrieveParticles(std::vector< std::vector< const xAOD::IParticle * >> &combinations, const std::string &chain, bool rerun=false) const override
Retrieve the particles that caused this trigger to fire.
Definition: IParticleRetrievalTool.cxx:74
Trig::IParticleRetrievalTool::initialize
StatusCode initialize() override
Initialise the tool.
Definition: IParticleRetrievalTool.cxx:67
HLT::TrigNavStructure::getHolder
const BaseHolder * getHolder(const TriggerElement::FeatureAccessHelper &fea) const
Definition: TrigNavStructure.cxx:923
DataVector::begin
const_iterator begin() const noexcept
Return a const_iterator pointing at the beginning of the collection.
mapkey::key
key
Definition: TElectronEfficiencyCorrectionTool.cxx:37