Commit ba3ac77e authored by Tim Martin's avatar Tim Martin
Browse files

Enabling Trigger Feature Access

     * TrigComposite (a.k.a. Decision) objects, when asked for an ElementLink, can now introspect if they've been decorated with re-mapped information.
     * Re-mapping of element links happens online at the end of processing, when EDM objects inside EventViews are copied out into EDM containers in the global event context.
     * Feature access code is reworked slightly to return LinkInfo objects rather than ElementLink objects. This is better as you can easily then also check which ROI your feature was in, etc.
     * The list of hard-coded chains was updated based on full_menu.py
     * HLTEDMCreator was updated to be given the HypoAlg output collection to remap rather than the InputMaker output. This was a bug before, features are attached by the hypo.
     * The way that `HLTEDMCreator` knows what collections need their element links updating was reworked - but reamins a bit clunky.
     * `HLTEDMCreator` indentation was standadised
     * Printing of feature properties was added to `TrigEDMChecker::dumpTDT`
parent 535b7237
......@@ -214,13 +214,39 @@ namespace xAOD {
AUXSTORE_OBJECT_GETTER( TrigComposite_v1, std::vector< std::string >,
linkColNames )
AUXSTORE_OBJECT_GETTER( TrigComposite_v1, std::vector< uint32_t >,
linkColKeys )
AUXSTORE_OBJECT_GETTER( TrigComposite_v1, std::vector< uint16_t >,
linkColIndices )
AUXSTORE_OBJECT_GETTER( TrigComposite_v1, std::vector< uint32_t >,
linkColClids )
const std::vector< uint32_t >& TrigComposite_v1::linkColKeys() const {
if (isRemapped()) {
static const Accessor< std::vector< uint32_t > > acc_remap( "remap_linkColKeys" );
return acc_remap( *this );
}
static const Accessor< std::vector< uint32_t > > acc_builtin( "linkColKeys" );
return acc_builtin( *this );
}
const std::vector< uint16_t >& TrigComposite_v1::linkColIndices() const {
if (isRemapped()) {
static const Accessor< std::vector< uint16_t > > acc_remap( "remap_linkColIndices" );
return acc_remap( *this );
}
static const Accessor< std::vector< uint16_t > > acc_builtin( "linkColIndices" );
return acc_builtin( *this );
}
const std::vector< uint32_t >& TrigComposite_v1::linkColKeysNoRemap() const {
static const Accessor< std::vector< uint32_t > > acc( "linkColKeys" );
return acc( *this );
}
const std::vector< uint16_t >& TrigComposite_v1::linkColIndicesNoRemap() const {
static const Accessor< std::vector< uint16_t > > acc( "linkColIndices" );
return acc( *this );
}
////////
std::vector< std::string >& TrigComposite_v1::linkColNamesNC() {
static const Accessor< std::vector< std::string > > acc( "linkColNames" );
......@@ -314,18 +340,28 @@ namespace xAOD {
}
}
bool TrigComposite_v1::isRemapped() const {
static const Accessor< std::vector< uint32_t > > key_remap( "remap_linkColKeys" );
static const Accessor< std::vector< uint16_t > > index_remap( "remap_linkColIndices" );
return (key_remap.isAvailable( *this ) && index_remap.isAvailable( *this ) );
}
//
/////////////////////////////////////////////////////////////////////////////
std::ostream& operator<<(std::ostream& os, const xAOD::TrigComposite_v1& tc) {
os << "TrigComposite_v1 name:'" << tc.name() << "'" << std::endl;
os << " N Lnks:" << tc.linkColNames().size();
const bool isRemapped = tc.isRemapped();
os << " N Links:" << tc.linkColNames().size() << ", isRemapped:" << (isRemapped ? "YES" : "NO");
for (size_t i=0; i<tc.linkColNames().size(); ++i){
if (!i) os << std::endl;
os << " Link Name:" << tc.linkColNames()[i];
os << ", Key:" << tc.linkColKeys()[i];
if (isRemapped) os << ", OldKey:" << tc.linkColKeysNoRemap()[i];
os << ", Index:" << tc.linkColIndices()[i];
if (isRemapped) os << ", OldIndex:" << tc.linkColIndicesNoRemap()[i];
os << ", CLID:" << tc.linkColClids()[i];
if (i != tc.linkColNames().size() - 1) os << std::endl;
}
......
......@@ -166,13 +166,22 @@ namespace xAOD {
/// Raw access to the persistent link names
const std::vector< std::string >& linkColNames() const;
/// Raw access to the persistent link labels
/// Raw access to the persistent link labels. Will use remapped data, if available.
const std::vector< uint32_t >& linkColKeys() const;
/// Raw access to the persistent link indices
/// Raw access to the persistent link indices. Will use remapped data, if available.
const std::vector< uint16_t >& linkColIndices() const;
/// Raw access to the persistent link CLIDs
const std::vector< uint32_t >& linkColClids() const;
/// Information on if linkColKeys() and linkColIndices() are able to access remapped link data
/// Remapping happens at the end of HLT execution when EDM objects are copied out of their per-EventView
/// containers and into the global Trigger EDM containers.
bool isRemapped() const;
/// Raw access to the persistent link labels. Will not attempt to access remapped link data.
const std::vector< uint32_t >& linkColKeysNoRemap() const;
/// Raw access to the persistent link indices. Will not attempt to access remapped link data.
const std::vector< uint16_t >& linkColIndicesNoRemap() const;
/// @}
......
......@@ -119,9 +119,16 @@ namespace xAOD {
for( size_t i = 0; i < names.size(); ++i ) {
if( names[ i ] != name ) continue;
checkTypes< CONTAINER >(linkColClids()[ i ], name);
// Construct the link:
return ElementLink< CONTAINER >( linkColKeys()[ i ],
linkColIndices()[ i ] );
// Construct the link. Try to remap, if remap collections are available:
ElementLink< CONTAINER > linkTryRemap( linkColKeys()[ i ],
linkColIndices()[ i ] );
if (linkTryRemap.isValid()) {
return linkTryRemap;
}
// Try again, without remapping
return ElementLink< CONTAINER >( linkColKeysNoRemap()[ i ],
linkColIndicesNoRemap()[ i ] );
}
// We didn't find the link. :-(
......@@ -145,13 +152,19 @@ namespace xAOD {
// Check that it is of the right type:
checkTypes< DataVector< OBJECT > >(linkColClids()[ i ], name);
// Create a temporary ElementLink:
ElementLink< DataVector< OBJECT > > link( linkColKeys()[ i ],
linkColIndices()[ i ] );
if( ! link.isValid() ) {
return 0;
ElementLink< DataVector< OBJECT > > linkTryRemap( linkColKeys()[ i ],
linkColIndices()[ i ] );
if( linkTryRemap.isValid() ) {
return *linkTryRemap;
}
// This time forbid remapping
ElementLink< DataVector< OBJECT > > link( linkColKeysNoRemap()[ i ],
linkColIndicesNoRemap()[ i ] );
if( link.isValid() ) {
return *link;
}
// Get the pointer:
return *link;
}
// There was an internal error. :-(
......
......@@ -121,10 +121,12 @@ namespace Trig {
* @param[in] eventStore Event store pointer. To migrate to readHandles with the rest of the TDT soon
* @param[in] condition Condition requirement. Only physics currently supported.
* @param[in] oneFeaturePerLeg If true, only collects the final feature from each object which passed the event for the Chain Group.
* @return ElementLinkVector with one entry per located feature for the ChainGroup's chain(s)
* @return Vector of LinkInfo, where each entry wraps an ElementLink to the feature, and the Decision object it came from.
**/
template<class CONTAINER>
const ElementLinkVector<CONTAINER> features(EventPtr_t eventStore, unsigned int condition = TrigDefs::Physics, const bool oneFeaturePerLeg = true) const;
const std::vector< TrigCompositeUtils::LinkInfo<CONTAINER> > features(EventPtr_t eventStore,
unsigned int condition = TrigDefs::Physics,
const bool oneFeaturePerLeg = true) const;
//
const std::vector< std::string >& patterns() const {return m_patterns;}
......
template<class CONTAINER>
const ElementLinkVector<CONTAINER> Trig::ChainGroup::features(EventPtr_t eventStore, unsigned int condition, const bool oneFeaturePerLeg) const {
// Proper adherence to the condition bits in Run 3 is to follow.
bool errState = false;
if ( !(condition & TrigDefs::Physics) ) {
ATH_MSG_ERROR("Only TrigDefs::Physics is currently supported for Run 3 feature retrieval");
errState = true;
}
if ( condition & TrigDefs::allowResurrectedDecision ) {
ATH_MSG_ERROR("TrigDefs::allowResurrectedDecision is not yet supported for feature retrieval for Run 3");
errState = true;
}
// TODO when we decide what happens to CacheGlobalMemory - this needs to be updated to use a ReadHandle
const TrigCompositeUtils::DecisionContainer* navigationSummaryContainer = nullptr;
if (eventStore->retrieve(navigationSummaryContainer, "HLTSummary").isFailure() || navigationSummaryContainer == nullptr) {
ATH_MSG_ERROR("Unable to read Run 3 trigger navigation. Cannot retrieve features.");
errState = true;
}
// We just support Physics decision for now
const TrigCompositeUtils::Decision* terminusNode = nullptr;
if (!errState) {
for (const TrigCompositeUtils::Decision* decision : *navigationSummaryContainer) {
if (decision->name() == "HLTPassRaw") {
terminusNode = decision;
break;
}
}
if (terminusNode == nullptr) {
ATH_MSG_ERROR("Unable to locate HLTPassRaw element of HLTSummary");
errState = true;
}
}
if (errState) {
return ElementLinkVector<CONTAINER>();
}
// For each chain, collect Navigation information
std::vector< ElementLinkVector<TrigCompositeUtils::DecisionContainer> > allLinearNavigationPaths;
// Loop over HLT chains
std::set<const TrigConf::HLTChain*>::const_iterator chIt;
for (chIt=conf_chain_begin(); chIt != conf_chain_end(); ++chIt) {
const HLT::Chain* fchain = cgm()->chain(**chIt);
if (fchain) {
TrigCompositeUtils::recursiveGetDecisions(terminusNode, allLinearNavigationPaths, fchain->getChainHashId());
}
}
return TrigCompositeUtils::getFeaturesOfType<CONTAINER>(allLinearNavigationPaths, oneFeaturePerLeg);
}
template<class CONTAINER>
const std::vector< TrigCompositeUtils::LinkInfo<CONTAINER> > Trig::ChainGroup::features(EventPtr_t eventStore,
unsigned int condition, const bool oneFeaturePerLeg) const {
// Proper adherence to the condition bits in Run 3 is to follow.
bool errState = false;
if ( !(condition & TrigDefs::Physics) ) {
ATH_MSG_ERROR("Only TrigDefs::Physics is currently supported for Run 3 feature retrieval");
errState = true;
}
if ( condition & TrigDefs::allowResurrectedDecision ) {
ATH_MSG_ERROR("TrigDefs::allowResurrectedDecision is not yet supported for feature retrieval for Run 3");
errState = true;
}
// TODO when we decide what happens to CacheGlobalMemory - this needs to be updated to use a ReadHandle
const TrigCompositeUtils::DecisionContainer* navigationSummaryContainer = nullptr;
if (eventStore->retrieve(navigationSummaryContainer, "HLTSummary").isFailure() || navigationSummaryContainer == nullptr) {
ATH_MSG_ERROR("Unable to read Run 3 trigger navigation. Cannot retrieve features.");
errState = true;
}
// We just support Physics decision for now
const TrigCompositeUtils::Decision* terminusNode = nullptr;
if (!errState) {
for (const TrigCompositeUtils::Decision* decision : *navigationSummaryContainer) {
if (decision->name() == "HLTPassRaw") {
terminusNode = decision;
break;
}
}
if (terminusNode == nullptr) {
ATH_MSG_ERROR("Unable to locate HLTPassRaw element of HLTSummary");
errState = true;
}
}
if (errState) {
ATH_MSG_ERROR("Encountered one or more errors in Trig::ChainGroup::features. Returning empty vector.");
return std::vector< TrigCompositeUtils::LinkInfo<CONTAINER> >();
}
// For each chain, collect Navigation information
std::vector< ElementLinkVector<TrigCompositeUtils::DecisionContainer> > allLinearNavigationPaths;
// Loop over HLT chains
std::set<const TrigConf::HLTChain*>::const_iterator chIt;
for (chIt=conf_chain_begin(); chIt != conf_chain_end(); ++chIt) {
const HLT::Chain* fchain = cgm()->chain(**chIt);
if (fchain) {
TrigCompositeUtils::recursiveGetDecisions(terminusNode, allLinearNavigationPaths, fchain->getChainHashId());
ATH_MSG_DEBUG("Added all navigation paths for chain " << fchain->getChainName() << ", total paths:" << allLinearNavigationPaths.size());
} else {
ATH_MSG_ERROR("Cannot access configuration for one of the ChainGroup's chains");
}
}
if (allLinearNavigationPaths.size() == 0) {
ATH_MSG_WARNING("No navigation paths found for this chain group of " << names().size() << " chains.");
}
return TrigCompositeUtils::getFeaturesOfType<CONTAINER>(allLinearNavigationPaths, oneFeaturePerLeg);
}
......@@ -107,17 +107,27 @@ namespace Trig {
/**
* @brief Runs 3+. Returns all features related to given chain group
* @param[in] group Chain group to return features for.
* @param[in] condition Condition bits which the chain group must satisfy.
* @param[in] oneFeaturePerLeg If true, only collects the final feature from each object which passed the event for the Chain Group.
* @return Vector of LinkInfo, where each entry wraps an ElementLink to the feature, and the Decision object it came from.
**/
template<class CONTAINER>
const ElementLinkVector<CONTAINER> features(const Trig::ChainGroup* group,
unsigned int condition = TrigDefs::Physics) const;
const std::vector< TrigCompositeUtils::LinkInfo<CONTAINER> > features(const Trig::ChainGroup* group,
const unsigned int condition = TrigDefs::Physics,
const bool oneFeaturePerLeg = true) const;
/**
* @brief Runs 3+. Returns features related to given chain
* @param[in] group Chain group to return features for.
* @param[in] condition Condition bits which the chain group must satisfy.
* @param[in] oneFeaturePerLeg If true, only collects the final feature from each object which passed the event for the Chain Group.
* @return Vector of LinkInfo, where each entry wraps an ElementLink to the feature, and the Decision object it came from.
**/
template<class CONTAINER>
const ElementLinkVector<CONTAINER> features(const std::string& chainName = "HLT_.*",
unsigned int condition = TrigDefs::Physics) const;
const std::vector< TrigCompositeUtils::LinkInfo<CONTAINER> > features(const std::string& chainName = "HLT_.*",
const unsigned int condition = TrigDefs::Physics,
const bool oneFeaturePerLeg = true) const;
/**
* @brief gives back feature matching (by seeding relation)
......
#if defined(ASGTOOL_ATHENA) && !defined(XAOD_ANALYSIS)
template<class T>
const Trig::Feature<T> Trig::DecisionAccess::ancestor(const HLT::TriggerElement* te, std::string label) const {
Trig::Feature<T> f;
std::vector<Trig::Feature<T> > data;
FeatureAccessImpl::collect<T>(te, data, label, TrigDefs::alsoDeactivateTEs, "", const_cast<HLT::TrigNavStructure*>(cgm()->navigation()));
BOOST_FOREACH( Feature<T>& f, data ) {
if ( f.owned() ) {
cgm()->deleteAtTheEndOfEvent( const_cast<T*>( f.cptr() ) );
}
}
if (data.size() == 1)
f = data[0];
return f;
}
template<class T>
const std::vector<Trig::Feature<T> > Trig::DecisionAccess::ancestors(const HLT::TriggerElement* te, std::string label, unsigned int condition, const std::string& teName) const {
std::vector<Trig::Feature<T> > data;
FeatureAccessImpl::collect<T>(te, data, label, condition, teName, const_cast<HLT::TrigNavStructure*>(cgm()->navigation()));
BOOST_FOREACH( Feature<T>& f, data ) {
if ( f.owned() ) {
cgm()->deleteAtTheEndOfEvent(const_cast<T*>( f.cptr() ));
}
}
return data;
}
#else
template<class T>
const Trig::Feature<T> Trig::DecisionAccess::ancestor(const HLT::TriggerElement* /*te*/, std::string /*label*/) const {
ATH_MSG_WARNING("DecisionAccess::ancestor not implemented in Standalone mode, since it needs compile-time type information. Returning empty Feature");
return Trig::Feature<T>();
}
template<class T>
const std::vector<Trig::Feature<T> > Trig::DecisionAccess::ancestors(const HLT::TriggerElement* /*te*/, std::string /*label*/, unsigned int /*condition*/, const std::string& /*teName*/) const {
ATH_MSG_WARNING("DecisionAccess::ancestor not implemented in Standalone mode, since it needs compile-time type information. Returning empty vector");
return std::vector<Trig::Feature<T> >();
}
#endif // ASGTOOL_ATHENA
template<class CONTAINER>
const ElementLinkVector<CONTAINER> Trig::DecisionAccess::features(const Trig::ChainGroup* group,
unsigned int condition) const {
return group->features<CONTAINER>(cgm()->store(), condition, /*one feature per leg*/ true);
}
template<class CONTAINER>
const ElementLinkVector<CONTAINER> Trig::DecisionAccess::features(const std::string& chainName,
unsigned int condition) const {
const Trig::ChainGroup *g = cgm()->createChainGroup(Trig::convertStringToVector(chainName));
return features<CONTAINER>(g,condition);
}
\ No newline at end of file
#if defined(ASGTOOL_ATHENA) && !defined(XAOD_ANALYSIS)
template<class T>
const Trig::Feature<T> Trig::DecisionAccess::ancestor(const HLT::TriggerElement* te, std::string label) const {
Trig::Feature<T> f;
std::vector<Trig::Feature<T> > data;
FeatureAccessImpl::collect<T>(te, data, label, TrigDefs::alsoDeactivateTEs, "", const_cast<HLT::TrigNavStructure*>(cgm()->navigation()));
BOOST_FOREACH( Feature<T>& f, data ) {
if ( f.owned() ) {
cgm()->deleteAtTheEndOfEvent( const_cast<T*>( f.cptr() ) );
}
}
if (data.size() == 1)
f = data[0];
return f;
}
template<class T>
const std::vector<Trig::Feature<T> > Trig::DecisionAccess::ancestors(const HLT::TriggerElement* te, std::string label, unsigned int condition, const std::string& teName) const {
std::vector<Trig::Feature<T> > data;
FeatureAccessImpl::collect<T>(te, data, label, condition, teName, const_cast<HLT::TrigNavStructure*>(cgm()->navigation()));
BOOST_FOREACH( Feature<T>& f, data ) {
if ( f.owned() ) {
cgm()->deleteAtTheEndOfEvent(const_cast<T*>( f.cptr() ));
}
}
return data;
}
#else
template<class T>
const Trig::Feature<T> Trig::DecisionAccess::ancestor(const HLT::TriggerElement* /*te*/, std::string /*label*/) const {
ATH_MSG_WARNING("DecisionAccess::ancestor not implemented in Standalone mode, since it needs compile-time type information. Returning empty Feature");
return Trig::Feature<T>();
}
template<class T>
const std::vector<Trig::Feature<T> > Trig::DecisionAccess::ancestors(const HLT::TriggerElement* /*te*/, std::string /*label*/, unsigned int /*condition*/, const std::string& /*teName*/) const {
ATH_MSG_WARNING("DecisionAccess::ancestor not implemented in Standalone mode, since it needs compile-time type information. Returning empty vector");
return std::vector<Trig::Feature<T> >();
}
#endif // ASGTOOL_ATHENA
template<class CONTAINER>
const std::vector< TrigCompositeUtils::LinkInfo<CONTAINER> > Trig::DecisionAccess::features(const Trig::ChainGroup* group,
const unsigned int condition,
const bool oneFeaturePerLeg) const {
return group->features<CONTAINER>(cgm()->store(), condition, oneFeaturePerLeg);
}
template<class CONTAINER>
const std::vector< TrigCompositeUtils::LinkInfo<CONTAINER> > Trig::DecisionAccess::features(const std::string& chainName,
const unsigned int condition,
const bool oneFeaturePerLeg) const {
const Trig::ChainGroup *g = cgm()->createChainGroup(Trig::convertStringToVector(chainName));
return features<CONTAINER>(g,condition,oneFeaturePerLeg);
}
......@@ -146,6 +146,35 @@ HLTConfigSvc::initialize() {
dummyChains["HLT_e3_etcut"] = "L1_EM3";
dummyChains["HLT_e5_etcut"] = "L1_EM3";
dummyChains["HLT_e7_etcut"] = "L1_EM7";
// for menu test
dummyChains["HLT_2mu4_bBmumu_L12MU4"] = "L1_2MU4";
dummyChains["HLT_2mu4_bJpsimumu_L12MU4"] = "L1_2MU4";
dummyChains["HLT_2mu4_bUpsimumu_L12MU4"] = "L1_2MU4";
dummyChains["HLT_2mu6"] = "L1_2MU6";
dummyChains["HLT_2mu6Comb"] = "L1_2MU6";
dummyChains["HLT_2mu6_bJpsimumu_L12MU6"] = "L1_2MU6";
dummyChains["HLT_3j200"] = "L1_J50";
dummyChains["HLT_5j70_0eta240"] = "L1_J50";
dummyChains["HLT_e3_etcut1step"] = "L1_EM3";
dummyChains["HLT_e3_etcut_mu6"] = "L1_EM8I_MU10";
dummyChains["HLT_g5_etcut"] = "L1_EM3";
dummyChains["HLT_j0_vbenfSEP30etSEP34mass35SEP50fbet20"] = "L1_RD0_FILLED";
dummyChains["HLT_j225_gsc420_boffperf_split20"] = "L1_J100";
dummyChains["HLT_j260_320eta490"] = "L1_J100";
dummyChains["HLT_j420"] = "L1_J100";
dummyChains["HLT_j45"] = "L1_J20";
dummyChains["HLT_j460_a10_lcw_subjes"] = "L1_J100";
dummyChains["HLT_j460_a10r"] = "L1_J100";
dummyChains["HLT_j85"] = "L1_J20";
dummyChains["HLT_mu20_ivar"] = "L1_MU20";
dummyChains["HLT_mu6"] = "L1_MU6";
dummyChains["HLT_mu6Comb"] = "L1_MU6";
dummyChains["HLT_mu6fast"] = "L1_MU6";
dummyChains["HLT_mu6msonly"] = "L1_MU6";
dummyChains["HLT_mu6nol1"] = "L1_MU6";
dummyChains["HLT_xe30_L1XE10"] = "L1_XE20";
dummyChains["HLT_xe65_L1XE50"] = "L1_XE20";
m_HLTFrame.setMergedHLT( m_setMergedHLT );
for (const auto& mapPair : dummyChains) {
const std::string& chainName = mapPair.first;
......
......@@ -225,15 +225,6 @@ namespace TrigCompositeUtils {
**/
void recursiveGetDecisionsInternal( const Decision* start, const size_t location, std::vector<ElementLinkVector<DecisionContainer>>& linkVector, const DecisionID id = 0);
/**
* @brief Extract features from the supplied linkVector (obtained through recursiveGetDecisions).
* @param[in] linkVector Vector of paths through the navigation which are to be considered.
* @param[oneFeaturePerLeg] oneFeaturePerLeg If True, stops at the first feature (of the correct type) found per path through the navigation.
* @return Typed vector of element links to all features found on the supplied linkVector.
**/
template<class CONTAINER>
ElementLinkVector<CONTAINER> getFeaturesOfType( const std::vector<ElementLinkVector<DecisionContainer>>& linkVector, const bool oneFeaturePerLeg = true );
/**
* @brief Helper to keep the TC & object it has linked together (for convenience)
**/
......@@ -256,6 +247,15 @@ namespace TrigCompositeUtils {
ElementLink<T> link;
};
/**
* @brief Extract features from the supplied linkVector (obtained through recursiveGetDecisions).
* @param[in] linkVector Vector of paths through the navigation which are to be considered.
* @param[oneFeaturePerLeg] oneFeaturePerLeg If True, stops at the first feature (of the correct type) found per path through the navigation.
* @return Typed vector of LinkInfo. Each LinkInfo wraps an ElementLink to a feature and a pointer to the feature's Decision object in the navigation.
**/
template<class CONTAINER>
const std::vector< LinkInfo<CONTAINER> > getFeaturesOfType( const std::vector<ElementLinkVector<DecisionContainer>>& linkVector, const bool oneFeaturePerLeg = true );
/**
* @brief search back the TC links for the object of type T linked to the one of TC (recursively)
* @arg start the TC from where the link back is to be looked for
......
......@@ -60,20 +60,20 @@ namespace TrigCompositeUtils {
}
template<class CONTAINER>
ElementLinkVector<CONTAINER> getFeaturesOfType(const std::vector<ElementLinkVector<DecisionContainer>>& linkVector, const bool oneFeaturePerLeg) {
ElementLinkVector<CONTAINER> features;
const std::vector< LinkInfo<CONTAINER> > getFeaturesOfType(const std::vector<ElementLinkVector<DecisionContainer>>& linkVector, const bool oneFeaturePerLeg) {
std::vector< LinkInfo<CONTAINER> > features;
// For each unique path through the navigation for a given chain
for (const ElementLinkVector<DecisionContainer>& decisionPath : linkVector) {
// For each step along this path, starting at the terminus and working back towards L1
for (const ElementLink<DecisionContainer>& decisionLink : decisionPath) {
const Decision* decision = (*decisionLink);
if (decision->hasObjectLink("feature", ClassID_traits< CONTAINER >::ID())) {
if (decision->hasObjectLink(featureString(), ClassID_traits< CONTAINER >::ID())) {
// This try block protects against ExcCLIDMismatch throws from
// features which do not derive from IParticle, when an IParticle interface is requested.
try {
const ElementLink<CONTAINER> featureLink = decision->objectLink<CONTAINER>("feature");
features.push_back( featureLink );
const ElementLink<CONTAINER> featureLink = decision->objectLink<CONTAINER>( featureString() );
features.push_back( LinkInfo<CONTAINER>(decision, featureLink) );
if (oneFeaturePerLeg) {
break;
}
......
......@@ -169,12 +169,9 @@ namespace TrigCompositeUtils {
void recursiveGetDecisionsInternal(const Decision* start, const size_t location, std::vector<ElementLinkVector<DecisionContainer>>& linkVector, const DecisionID id) {
// Does this Decision satisfy the chain requirement?
// Don't check this for HLTPassRaw or HLTRerun. These inital nodes have empty sets
if (start->name() != "HLTPassRaw" && start->name() != "HLTRerun") {
DecisionIDContainer idSet = {id};
if (id != 0 && !isAnyIDPassing(start, idSet)) {
return; // Stop propagating down this leg. It does not concern the chain with DecisionID = id
}
DecisionIDContainer idSet = {id};
if (id != 0 && !isAnyIDPassing(start, idSet)) {
return; // Stop propagating down this leg. It does not concern the chain with DecisionID = id
}
// This Decision object is part of this linear path through the Navigation
......@@ -211,7 +208,7 @@ namespace TrigCompositeUtils {
}
void recursiveGetDecisions(const Decision* start, std::vector<ElementLinkVector<DecisionContainer>>& linkVector, const DecisionID id) {
// Note: we do not require recursiveGetDecisions to be an empty vector. We can append to it.
// Note: we do not require linkVector to be an empty vector. We can append to it.
linkVector.push_back( ElementLinkVector<DecisionContainer>() ); // Our starting point
const size_t startingElement = linkVector.size() - 1;
recursiveGetDecisionsInternal(start, startingElement, linkVector, id);
......
......@@ -28,7 +28,7 @@ using TrigCompositeUtils::DecisionContainer;
void printPaths(const std::vector<ElementLinkVector<DecisionContainer>>& paths, const std::string& name);