15#include <unordered_set>
25 ANA_MSG_SOURCE (msgRejected,
"TrigCompositeUtils.getRejectedDecisionNodes")
30 auto data = std::make_unique<DecisionContainer>() ;
31 auto aux = std::make_unique<DecisionAuxContainer>() ;
33 handle.
record( std::move(
data ), std::move(
aux ) ).ignore();
38 auto data = std::make_unique<DecisionContainer>() ;
39 auto aux = std::make_unique<DecisionAuxContainer>() ;
41 handle.
record( std::move(
data ), std::move(
aux ) ).ignore();
47 if ( ! name.empty() ) {
61 if ( decisions.size() == 0 or decisions.back() !=
id)
62 decisions.push_back(
id );
67 destination.insert( decisions.begin(), decisions.end() );
89 collateIDs.insert( src.begin(), src.end() );
90 std::vector<DecisionID>& vdest =
decisionIDs( dest );
93 vdest.reserve(collateIDs.size());
95 vdest.insert( vdest.end(), collateIDs.begin(), collateIDs.end() );
106 return decisions.empty();
111 if ( required.find(
id ) != required.end() ) {
119 return idSet.find(
id ) != idSet.end();
122#if !defined(XAOD_STANDALONE) && !defined(XAOD_ANALYSIS)
126 throw std::runtime_error(
"TrigCompositeUtils::convertToElementLink Using convertToElementLink(d) requires that the Decision d is already in a container");
134 throw std::runtime_error(
"TrigCompositeUtils::convertToElementLink Using convertToElementLink(d) requires that the Decision d is already in a container");
136 return ElementLink<DecisionContainer>(*container,
d->index());
142 if (!seed.isValid()) {
143 throw std::runtime_error(
"TrigCompositeUtils::linkToPrevious Invalid Decision Link key or index provided");
145 d->addObjectCollectionLink(
seedString(), seed);
154 return d->hasObjectCollectionLinks(
seedString() );
163 return dest->copyAllLinksFrom(src);
172 throw std::runtime_error(
"TrigCompositeUtils::createLegName chainIdentifier '"+name+
"' does not start with 'HLT_'");
175 throw std::runtime_error(
"TrigCompositeUtils::createLegName Leg counters above 999 are invalid.");
181 const std::string& name = legIdentifier.
name();
183 return legIdentifier;
187 throw std::runtime_error(
"TrigCompositeUtils::getIDFromLeg legIdentifier '"+name+
"' does not start with 'HLT_' or 'leg' ");
200 std::from_chars(name.data()+3, name.data()+6,
id);
202 throw std::runtime_error(
"TrigCompositeUtils::getIndexFromLeg legIdentifier '"+name+
"' does not start with 'HLT_' or 'leg' ");
212 std::from_chars(name.data()+3, name.data()+6,
id);
213 return {name.substr(7),
id};
215 throw std::runtime_error(
"TrigCompositeUtils::getIDFromLeg legIdentifier '"+name+
"' does not start with 'HLT_' or 'leg' ");
224 return name.starts_with(
"leg");
232 return name.starts_with(
"HLT_");
237 if ( filter( start ) )
return start;
240 const std::vector<ElementLink<DecisionContainer>> seeds =
getLinkToPrevious(start);
271 const auto it = std::find_if(
container.begin(),
container.end(), [&nodeName](
const Decision* d){return d->name()==nodeName;});
272 if (it==
container.end()) {
return nullptr;}
277 const EventContext& ctx,
278 const std::string& summaryCollectionKey,
280 const std::set<std::string>& keysToIgnore) {
285 static const std::unordered_set<std::string> knownDistributedSummaryStores{
292 static const std::unordered_set<std::string> knownCompactSummaryStores{
"HLTNav_Summary_OnlineSlimmed",
293 "HLTNav_Summary_ESDSlimmed",
294 "HLTNav_Summary_AODSlimmed",
295 "HLTNav_Summary_DAODSlimmed",
296 "HLTNav_R2ToR3Summary"
299 std::vector<std::string> keys;
301 if (knownDistributedSummaryStores.contains(summaryCollectionKey) or summaryCollectionKey.empty()) {
305#ifndef XAOD_STANDALONE
310 throw std::runtime_error(
"Cannot obtain rejected HLT features in AnalysisBase when reading from uncompactified navigation containers, run trigger navigation slimming first if you really need this.");
313 }
else if (knownCompactSummaryStores.contains(summaryCollectionKey)) {
315 keys.push_back(summaryCollectionKey);
319 using namespace msgRejected;
320 ANA_MSG_WARNING(
"getRejectedDecisionNodes has not been told about final collection " << summaryCollectionKey <<
" please update this function. Assuming that it is already compact.");
322 keys.push_back(summaryCollectionKey);
326 std::vector<const Decision*> output;
330 if (!containerRHKey.
initialize().isSuccess()) {
331 throw std::runtime_error(
"Cannot initialize ReadHandleKey for DecisionContainer");
335 for (
const std::string& key : keys) {
337 if ( ! (key.starts_with(
"HLTNav_") || key.starts_with(
"_HLTNav_")) ) {
340 if (keysToIgnore.contains(key)) {
345 containerRHKey = key;
347 if (!containerRH.isValid()) {
348 throw std::runtime_error(
"Unable to retrieve " + key +
" from event store.");
351 for (
const Decision* d : *containerRH) {
356 if (mySeeds.empty()) {
360 if (!allSeedsValid) {
361 using namespace msgRejected;
362 ANA_MSG_WARNING(
"A Decision object in " << key <<
" has invalid seeds. "
363 <<
"The trigger navigation information is incomplete. Skipping this Decision object.");
368 decisionIDs(*mySeeds[0], activeChainsIntoThisDecision);
369 if (mySeeds.size() > 1) {
370 for (
size_t i = 1; i < mySeeds.size(); ++i) {
375 std::set_intersection(activeChainsIntoThisDecision.begin(), activeChainsIntoThisDecision.end(),
376 moreActiveChains.begin(), moreActiveChains.end(),
387 chainsToCheck = activeChainsIntoThisDecision;
395 for (
const DecisionID checkID : chainsToCheck) {
396 if (not activeChainsPassedByThisDecision.contains(checkID) &&
397 activeChainsIntoThisDecision.contains(checkID)) {
410 std::set<const Decision*>& fullyExploredFrom,
412 const bool enforceDecisionOnNode) {
422#if TRIGCOMPUTILS_ENABLE_EARLY_EXIT == 1
424 if (fullyExploredFrom.count(
node) == 1) {
434 const Decision* seedDecision = *(seed);
441 fullyExploredFrom.insert(
node);
449 const bool enforceDecisionOnStartNode) {
451 std::set<const Decision*> fullyExploredFrom;
460 const bool keepOnlyFinalFeatures,
461 const bool removeEmptySteps,
462 const std::vector<std::string>& nodesToDrop)
464 std::set<NavGraphNode*> fullyExploredFrom;
473 std::set<NavGraphNode*>& fullyExploredFrom,
474 const bool keepOnlyFinalFeatures,
475 const bool removeEmptySteps,
476 const std::vector<std::string>& nodesToDrop)
481 bool keep = modeKeep;
487 const Decision*
const myFirstParent = (
node->seeds().size() ?
node->seeds().at(0)->
node() :
nullptr);
488 const Decision*
const myFirstChild = (
node->children().size() ?
node->children().at(0)->
node() :
nullptr);
492 if (keepOnlyFinalFeatures) {
508 if (!specialBphysCase && !specialR2toR3Case) {
522 for (
const std::string& toDrop : nodesToDrop) {
523 if (me->
name() == toDrop) {
571#if TRIGCOMPUTILS_ENABLE_EARLY_EXIT == 1
585 bool allowEarlyExit =
true;
586 if (keepOnlyFinalFeatures) {
587 allowEarlyExit = (modeKeep ==
false);
589 if (allowEarlyExit && fullyExploredFrom.count(seed) == 1) {
599 fullyExploredFrom.insert(
node);
604 const std::string& linkName,
605 std::vector<sgkey_t>& keyVec,
606 std::vector<CLID>& clidVec,
607 std::vector<Decision::index_type>& indexVec,
608 std::vector<const Decision*>& sourceVec,
609 const unsigned int behaviour,
610 std::set<const Decision*>* fullyExploredFrom)
612 using namespace msgFindLink;
615 if (keyVec.size() != clidVec.size() or clidVec.size() != indexVec.size()) {
616 ANA_MSG_WARNING(
"In typelessFindLinks, keyVec, clidVec, indexVec must all be the same size. Instead have:"
617 << keyVec.size() <<
", " << clidVec.size() <<
", " << indexVec.size());
630#if TRIGCOMPUTILS_ENABLE_EARLY_EXIT == 1
631 if (fullyExploredFrom !=
nullptr) {
634 if (fullyExploredFrom->count(*seed) == 1) {
639 found |=
typelessFindLinks(*seed, linkName, keyVec, clidVec, indexVec, sourceVec, behaviour, fullyExploredFrom);
642 if (fullyExploredFrom !=
nullptr) {
643 fullyExploredFrom->insert(start);
650 const std::string& linkName,
651 std::vector<sgkey_t>& keyVec,
652 std::vector<CLID>& clidVec,
653 std::vector<Decision::index_type>& indexVec,
654 std::vector<const Decision*>& sourceVec,
655 const unsigned int behaviour,
656 std::set<const Decision*>* fullyExploredFrom)
658 using namespace msgFindLink;
661 if (keyVec.size() != clidVec.size() or clidVec.size() != indexVec.size()) {
662 ANA_MSG_WARNING(
"In typelessFindLinks, keyVec, clidVec, indexVec must all be the same size. Instead have:"
663 << keyVec.size() <<
", " << clidVec.size() <<
", " << indexVec.size());
667 const Decision* start_decisionObject = start->node();
677#if TRIGCOMPUTILS_ENABLE_EARLY_EXIT == 1
678 if (fullyExploredFrom !=
nullptr) {
681 const Decision* seed_decisionObject = seed->node();
682 if (fullyExploredFrom->count(seed_decisionObject) == 1) {
687 found |=
typelessFindLinks(seed, linkName, keyVec, clidVec, indexVec, sourceVec, behaviour, fullyExploredFrom);
690 if (fullyExploredFrom !=
nullptr) {
691 fullyExploredFrom->insert(start_decisionObject);
698 const std::string& linkName,
699 std::vector<sgkey_t>& keyVec,
700 std::vector<CLID>& clidVec,
701 std::vector<Decision::index_type>& indexVec,
702 std::vector<const Decision*>& sourceVec)
705 std::vector<sgkey_t> tmpKeyVec;
706 std::vector<CLID> tmpClidVec;
707 std::vector<Decision::index_type> tmpIndexVec;
708 if (start->hasObjectCollectionLinks(linkName)) {
709 found = start->typelessGetObjectCollectionLinks(linkName, tmpKeyVec, tmpClidVec, tmpIndexVec);
711 if (start->hasObjectLink(linkName)) {
715 found |= start->typelessGetObjectLink(linkName, tmpKey, tmpClid, tmpIndex);
716 tmpKeyVec.push_back(tmpKey);
717 tmpClidVec.push_back(tmpClid);
718 tmpIndexVec.push_back(tmpIndex);
721 for (
size_t tmpi = 0; tmpi < tmpKeyVec.size(); ++tmpi) {
722 bool alreadyAdded =
false;
723 const sgkey_t tmpKey = tmpKeyVec.at(tmpi);
724 const CLID tmpClid = tmpClidVec.at(tmpi);
726 for (
size_t veci = 0; veci < keyVec.size(); ++veci) {
728 and clidVec.at(veci) == tmpClid
729 and indexVec.at(veci) == tmpIndex)
736 keyVec.push_back( tmpKey );
737 clidVec.push_back( tmpClid );
738 indexVec.push_back( tmpIndex );
739 sourceVec.push_back( start );
748 const std::string& linkName,
753 const bool suppressMultipleLinksWarning)
755 using namespace msgFindLink;
762 std::vector<sgkey_t> keyVec;
763 std::vector<CLID> clidVec;
764 std::vector<Decision::index_type> indexVec;
765 std::vector<const Decision*> sourceVec;
766 std::set<const xAOD::TrigComposite*> fullyExploredFrom;
773 if (keyVec.size() > 1 && !suppressMultipleLinksWarning) {
774 ANA_MSG_WARNING (keyVec.size() <<
" typeless links found for " << linkName
775 <<
" returning the first link, consider using findLinks.");
778 clid = clidVec.at(0);
779 index = indexVec.at(0);
780 source = sourceVec.at(0);
786 const std::string& linkName,
791 const bool suppressMultipleLinksWarning)
793 using namespace msgFindLink;
797 std::vector<sgkey_t> keyVec;
798 std::vector<uint32_t> clidVec;
799 std::vector<Decision::index_type> indexVec;
800 std::vector<const Decision*> sourceVec;
801 std::set<const Decision*> fullyExploredFrom;
812 if (keyVec.size() > 1 && !suppressMultipleLinksWarning) {
813 ANA_MSG_WARNING (keyVec.size() <<
" typeless links found for " << linkName
814 <<
" returning the first link, consider using findLinks.");
817 clid = clidVec.at(0);
818 index = indexVec.at(0);
819 source = sourceVec.at(0);
825 const std::string& chainName,
827 const std::vector<std::size_t>& legMultiplicities,
831 combinations.reserve(legMultiplicities.size());
832 if (legMultiplicities.size() == 1)
833 combinations.addLeg(legMultiplicities.at(0), features);
835 for (std::size_t legIdx = 0; legIdx < legMultiplicities.size(); ++legIdx)
838 if (legMultiplicities[legIdx] == 0)
841 std::vector<LinkInfo<xAOD::IParticleContainer>> legFeatures;
843 if (info.decisions->contains(legID.
numeric()))
844 legFeatures.push_back(info);
846 combinations.addLeg(legMultiplicities.at(legIdx), std::move(legFeatures));
853 const std::string& chainName,
855 const std::vector<std::size_t>& legMultiplicities,
862 const std::string& chainName,
871 const std::string& chainName,
882 ret += printerFnc(
tc );
886 ret +=
" -> " +
dump( *seedEL, printerFnc );
Base class for elements of a container that can have aux data.
uint32_t CLID
The Class ID type.
char data[hepevt_bytes_allocation_ATLAS]
xAOD::TrigComposite Decision
xAOD::TrigCompositeContainer DecisionContainer
static const SG::AuxElement::ConstAccessor< std::vector< TrigCompositeUtils::DecisionID > > readOnlyAccessor("decisions")
static const SG::AuxElement::Accessor< std::vector< TrigCompositeUtils::DecisionID > > readWriteAccessor("decisions")
value_type push_back(value_type pElem)
Add an element to the end of the collection.
ElementLink implementation for ROOT usage.
TrigCompositeUtils::DecisionID numeric() const
numeric ID
std::string name() const
reports human redable name
SG::ConstAccessor< T, ALLOC > ConstAccessor
SG::Accessor< T, ALLOC > Accessor
Property holding a SG store/key/clid from which a ReadHandle is made.
StatusCode initialize(bool used=true)
If this object is used as a property, then this should be called during the initialize phase.
StatusCode record(std::unique_ptr< T > data)
Record a const object to the store.
bool operator()(const Decision *) const
checks if the arg Decision object has link collection of name specified at construction
bool operator()(const Decision *) const
checks if the arg TC has link of name specified at construction
Transient utility class to represent a node in a graph (m_decisionObject), and a vector of edges (m_f...
Structure to hold a transient Directed Acyclic Graph (DAG) structure.
void addNode(const Decision *node, const Decision *comingFrom=nullptr)
Add a new NavGraphNode which shadows the xAOD Decision object "node" from the full navigation graph.
const std::vector< NavGraphNode * > & finalNodes() const
Get all final nodes.
HLT chain configuration information.
const std::vector< size_t > & leg_multiplicities() const
node(node *n=0, const std::string &d="", TObject *t=0)
bool hasObjectLink(const std::string &name, const CLID clid=CLID_NULL) const
Check if a link to an object with a given name and type exists. CLID_NULL to not check type.
const OBJECT * object(const std::string &name) const
Get a bare pointer with the requested name.
bool hasObjectCollectionLinks(const std::string &collectionName, const CLID clid=CLID_NULL) const
Check if links exist to a collection of objects with given name and type. CLID_NULL to not check type...
const std::string & name() const
Get a human-readable name for the object.
std::vector< std::string > intersection(std::vector< std::string > &v1, std::vector< std::string > &v2)
constexpr bool sgkeyEqual(const sgkey_t a, const sgkey_t b)
Compare two sgkeys for equality.
SG::ReadCondHandle< T > makeHandle(const SG::ReadCondHandleKey< T > &key, const EventContext &ctx=Gaudi::Hive::currentContext())
bool isChainId(const HLT::Identifier &chainIdentifier)
Recognise whether the HLT identifier corresponds to a whole chain.
HLT::Identifier createLegName(const HLT::Identifier &chainIdentifier, size_t counter)
Generate the HLT::Identifier which corresponds to a specific leg of a given chain.
const std::string & inputMakerNodeName()
xAOD::TrigComposite Decision
Combinations buildCombinations(const std::string &chainName, const std::vector< LinkInfo< xAOD::IParticleContainer > > &features, const std::vector< std::size_t > &legMultiplicities, const std::function< bool(const std::vector< LinkInfo< xAOD::IParticleContainer > > &)> &filter)
Produce the combinations for a set of features.
const Decision * find(const Decision *start, const std::function< bool(const Decision *)> &filter)
traverses Decision object links for another Decision object fulfilling the prerequisite specified by ...
const Decision * getNodeByName(const DecisionContainer &container, const std::string &nodeName)
Returns the navigation node with a given name from a collection or nullptr if missing.
void insertDecisionIDs(const Decision *src, Decision *dest)
Appends the decision IDs of src to the dest decision object.
Decision * newDecisionIn(DecisionContainer *dc, const std::string &name)
Helper method to create a Decision object, place it in the container and return a pointer to it.
const std::vector< ElementLink< DecisionContainer > > getLinkToPrevious(const Decision *d)
returns links to previous decision object 'seed'
const std::string & featureString()
int32_t getIndexFromLeg(const HLT::Identifier &legIdentifier)
Extract the numeric index of a leg identifier.
const Decision * getExpressTerminusNode(const DecisionContainer &container)
Returns the express-accept navigation node from a collection or nullptr if missing.
void recursiveGetDecisions(const Decision *start, NavGraph &navGraph, const DecisionIDContainer &ids, const bool enforceDecisionOnStartNode)
Search back in time from "node" and locate all paths back through Decision objects for a given chain.
HLT::Identifier getIDFromLeg(const HLT::Identifier &legIdentifier)
Generate the HLT::Identifier which corresponds to the chain name from the leg name.
std::vector< const Decision * > getRejectedDecisionNodes(const asg::EventStoreType *eventStore, const EventContext &ctx, const std::string &summaryCollectionKey, const DecisionIDContainer &ids, const std::set< std::string > &keysToIgnore)
Query all DecisionCollections in the event store, locate all Decision nodes in the graph where an obj...
bool copyLinks(const Decision *src, Decision *dest)
copy all links from src to dest TC objects
bool hasLinkToPrevious(const Decision *d)
checks if there is at least one 'seed' link to previous object
bool passed(DecisionID id, const DecisionIDContainer &idSet)
checks if required decision ID is in the set of IDs in the container
void recursiveFlagForThinningInternal(NavGraphNode *node, bool modeKeep, std::set< NavGraphNode * > &fullyExploredFrom, const bool keepOnlyFinalFeatures, const bool removeEmptySteps, const std::vector< std::string > &nodesToDrop)
Used by recursiveFlagForThinning.
const std::string & comboHypoAlgNodeName()
std::set< DecisionID > DecisionIDContainer
std::function< bool(const std::vector< LinkInfo< xAOD::IParticleContainer > > &)> getFilter(FilterType filter)
Get a lambda corresponding to the specified FilterType enum.
const Decision * getTerminusNode(SG::ReadHandle< DecisionContainer > &container)
void recursiveFlagForThinning(NavGraph &graph, const bool keepOnlyFinalFeatures, const bool removeEmptySteps, const std::vector< std::string > &nodesToDrop)
Used by trigger navigation thinning.
SG::WriteHandle< DecisionContainer > createAndStore(const SG::WriteHandleKey< DecisionContainer > &key, const EventContext &ctx)
Creates and right away records the DecisionContainer with the key.
void recursiveGetDecisionsInternal(const Decision *node, const Decision *comingFrom, NavGraph &navGraph, std::set< const Decision * > &fullyExploredFrom, const DecisionIDContainer &ids, const bool enforceDecisionOnNode)
Used by recursiveGetDecisions.
const std::string & hypoAlgNodeName()
void linkToPrevious(Decision *d, const std::string &previousCollectionKey, size_t previousIndex)
Links to the previous object, location of previous 'seed' decision supplied by hand.
bool allFailed(const Decision *d)
return true if there is no positive decision stored
void uniqueDecisionIDs(Decision *dest)
Make unique list of decision IDs of dest Decision object.
bool typelessFindLinksCommonLinkCollection(const Decision *start, const std::string &linkName, std::vector< sgkey_t > &keyVec, std::vector< CLID > &clidVec, std::vector< Decision::index_type > &indexVec, std::vector< const Decision * > &sourceVec)
Common functionality shared by both typelessFindLinks interfaces Returns true if at least one link wa...
std::pair< std::string, int32_t > getNameAndIndexFromLeg(const std::string &name)
Extract the name and numeric index of a leg identifier.
const std::string & seedString()
const std::string & summaryPassNodeName()
bool typelessFindLinks(const Decision *start, const std::string &linkName, std::vector< sgkey_t > &keyVec, std::vector< CLID > &clidVec, std::vector< Decision::index_type > &indexVec, std::vector< const Decision * > &sourceVec, const unsigned int behaviour, std::set< const Decision * > *fullyExploredFrom)
search back the TC links for the object of type T linked to the one of TC (recursively) Returns the l...
const std::string & summaryPassExpressNodeName()
xAOD::TrigCompositeContainer DecisionContainer
void addDecisionID(DecisionID id, Decision *d)
Appends the decision (given as ID) to the decision object.
const std::string & hltSeedingNodeName()
void decisionIDs(const Decision *d, DecisionIDContainer &destination)
Extracts DecisionIDs stored in the Decision object.
bool isAnyIDPassing(const Decision *d, const DecisionIDContainer &required)
Checks if any of the DecisionIDs passed in arg required is availble in Decision object.
ElementLink< DecisionContainer > decisionToElementLink(const Decision *d, const EventContext &ctx)
Takes a raw pointer to a Decision and returns an ElementLink to the Decision.
bool isLegId(const HLT::Identifier &legIdentifier)
Recognise whether the chain ID is a leg ID.
bool typelessFindLink(const Decision *start, const std::string &linkName, sgkey_t &key, CLID &clid, Decision::index_type &index, const Decision *&source, const bool suppressMultipleLinksWarning)
Perform a recursive search for ElementLinks of any time and name 'linkName', starting from Decision o...
static const unsigned int lastFeatureOfType
Run 3 "enum". Only return the final feature along each route through the navigation.
StoreGateSvc EventStoreType
the type returned by AsgTool::evtStore
Helper to keep a Decision object, ElementLink and ActiveState (with respect to some requested ChainGr...