From 871eae4503d0bd87059bc020e77fd0e28fc76e18 Mon Sep 17 00:00:00 2001 From: Benjamin Michael Wynne <b.m.wynne@ed.ac.uk> Date: Fri, 14 Dec 2018 16:35:09 +0000 Subject: [PATCH] HLT navigation dump --- .../xAODTrigger/Root/TrigComposite_v1.cxx | 31 +++ .../xAODTrigger/versions/TrigComposite_v1.h | 3 + .../TrigUpgradeTest/share/checkAOD.py | 23 ++ .../TrigValidation/TrigValAlgs/CMakeLists.txt | 7 +- .../TrigValAlgs/TrigValAlgs/TrigEDMChecker.h | 18 +- .../TrigValAlgs/src/TrigEDMChecker.cxx | 197 +++++++++++++++++- 6 files changed, 271 insertions(+), 8 deletions(-) create mode 100644 Trigger/TrigValidation/TrigUpgradeTest/share/checkAOD.py diff --git a/Event/xAOD/xAODTrigger/Root/TrigComposite_v1.cxx b/Event/xAOD/xAODTrigger/Root/TrigComposite_v1.cxx index 1d691a39956..aea7b853e1e 100644 --- a/Event/xAOD/xAODTrigger/Root/TrigComposite_v1.cxx +++ b/Event/xAOD/xAODTrigger/Root/TrigComposite_v1.cxx @@ -472,6 +472,37 @@ namespace xAOD { return acc( *this ); } + void TrigComposite_v1::typelessSetObjectLink( const std::string& name, const uint32_t key, const uint32_t clid, const uint16_t beginIndex, const uint16_t endIndex ) { + + // Loop over collections + if ( endIndex - beginIndex > 1 ) { + + const std::string mangledName = name + s_collectionSuffix; + for ( unsigned int index = beginIndex; index < endIndex; ++index ) { + + // Check uniqueness + if ( std::find( linkColNamesNC().begin(), linkColNamesNC().end(), mangledName ) == linkColNamesNC().end() ) { + + this->linkColNamesNC().push_back( mangledName ); + this->linkColKeysNC().push_back( key ); + this->linkColIndicesNC().push_back( index ); + this->linkColClidsNC().push_back( clid ); + } + } + } + else { + + // Check uniqueness + if ( std::find( linkColNamesNC().begin(), linkColNamesNC().end(), name ) == linkColNamesNC().end() ) { + + this->linkColNamesNC().push_back( name ); + this->linkColKeysNC().push_back( key ); + this->linkColIndicesNC().push_back( beginIndex ); + this->linkColClidsNC().push_back( clid ); + } + } + } + // ///////////////////////////////////////////////////////////////////////////// diff --git a/Event/xAOD/xAODTrigger/xAODTrigger/versions/TrigComposite_v1.h b/Event/xAOD/xAODTrigger/xAODTrigger/versions/TrigComposite_v1.h index dd7ca44018b..0f55daf1f17 100644 --- a/Event/xAOD/xAODTrigger/xAODTrigger/versions/TrigComposite_v1.h +++ b/Event/xAOD/xAODTrigger/xAODTrigger/versions/TrigComposite_v1.h @@ -206,6 +206,9 @@ namespace xAOD { /// Raw access to the persistent link CLIDs const std::vector< uint32_t >& linkColClids() const; + /// Add a link without type + void typelessSetObjectLink( const std::string& name, const uint32_t key, const uint32_t clid, const uint16_t beginIndex, const uint16_t endIndex = 0 ); + /// @} /// For use in validation, when copying element links from one object to another diff --git a/Trigger/TrigValidation/TrigUpgradeTest/share/checkAOD.py b/Trigger/TrigValidation/TrigUpgradeTest/share/checkAOD.py new file mode 100644 index 00000000000..15996631172 --- /dev/null +++ b/Trigger/TrigValidation/TrigUpgradeTest/share/checkAOD.py @@ -0,0 +1,23 @@ +include("AthenaPoolDataModelTest/esdtoesd_base.py") + +svcMgr.EventSelector.InputCollections = [ "/eos/atlas/atlascerngroupdisk/data-art/grid-output/21.0/Athena/x86_64-slc6-gcc62-opt/2018-12-08T2201/TrigAnalysisTest/test_physics_pp_v7_rdotoesdaod_grid/AOD.pool.root" ] +#svcMgr.EventSelector.InputCollections = [ "myESD.pool.root" ] +from TrigValAlgs.TrigValAlgsConf import TrigEDMChecker +MessageSvc.defaultLimit = 9999999 +MessageSvc.useColors = True +checker = TrigEDMChecker() +checker.OutputLevel = DEBUG +checker.doDumpAll = False +checker.doDumpStoreGate = False +checker.doDumpNavigation = True +checker.doDumpTrigCompsiteNavigation = True + +checker.Decisions = "exportTest" +checker.dumpTrigCompositeContainers = [ "exportTest" ] + + +from AthenaCommon.AppMgr import topSequence +topSequence += checker + +theApp.EvtMax = 10 +svcMgr.EventSelector.SkipEvents = 9 diff --git a/Trigger/TrigValidation/TrigValAlgs/CMakeLists.txt b/Trigger/TrigValidation/TrigValAlgs/CMakeLists.txt index db647d60d28..9553cb8672b 100644 --- a/Trigger/TrigValidation/TrigValAlgs/CMakeLists.txt +++ b/Trigger/TrigValidation/TrigValAlgs/CMakeLists.txt @@ -8,6 +8,7 @@ atlas_subdir( TrigValAlgs ) # Declare the package's dependencies: atlas_depends_on_subdirs( PUBLIC Control/AthenaBaseComps + Control/AthAnalysisBaseComps GaudiKernel TestPolicy Trigger/TrigAnalysis/TrigDecisionTool @@ -45,9 +46,13 @@ atlas_depends_on_subdirs( PUBLIC Reconstruction/Particle Reconstruction/tauEvent Tracking/TrkEvent/VxSecVertex + Trigger/TrigNavigation + Trigger/TrigNavStructure + Trigger/TrigConfiguration/TrigConfHLTData Trigger/TrigConfiguration/TrigConfigSvc Trigger/TrigEvent/TrigDecisionEvent Trigger/TrigEvent/TrigMissingEtEvent + Trigger/TrigSteer/DecisionHandling Trigger/TrigTruthEvent/TrigInDetTruthEvent Trigger/TrigT1/TrigT1Interfaces ) @@ -60,7 +65,7 @@ atlas_add_component( TrigValAlgs src/*.cxx src/components/*.cxx INCLUDE_DIRS ${XERCESC_INCLUDE_DIRS} ${CLHEP_INCLUDE_DIRS} - LINK_LIBRARIES ${XERCESC_LIBRARIES} ${CLHEP_LIBRARIES} AthenaBaseComps GaudiKernel TrigDecisionToolLib TrigCaloEvent TrigInDetEvent TrigMuonEvent TrigNavToolsLib TrigNavigationLib TrigParticle TrigSteeringEvent AthenaKernel CxxUtils EventInfo xAODEventInfo xAODBTagging xAODEgamma xAODJet xAODMuon xAODTau xAODTracking xAODTrigBphys xAODTrigCalo xAODTrigEgamma xAODTrigMinBias xAODTrigMissingET xAODTrigMuon xAODCore xAODTrigger AnalysisTriggerEvent MuonCombinedToolInterfaces Particle tauEvent VxSecVertex TrigConfigSvcLib TrigConfHLTData TrigRoiConversionLib TrigDecisionEvent TrigMissingEtEvent TrigInDetTruthEvent TrigT1Interfaces ) + LINK_LIBRARIES ${XERCESC_LIBRARIES} ${CLHEP_LIBRARIES} AthenaBaseComps AthAnalysisBaseCompsLib GaudiKernel TrigDecisionToolLib TrigCaloEvent TrigInDetEvent TrigMuonEvent TrigNavToolsLib TrigNavigationLib TrigParticle TrigSteeringEvent AthenaKernel CxxUtils EventInfo xAODEventInfo xAODBTagging xAODEgamma xAODJet xAODMuon xAODTau xAODTracking xAODTrigBphys xAODTrigCalo xAODTrigEgamma xAODTrigMinBias xAODTrigMissingET xAODTrigMuon xAODCore xAODTrigger AnalysisTriggerEvent MuonCombinedToolInterfaces Particle tauEvent VxSecVertex TrigConfigSvcLib TrigConfHLTData TrigRoiConversionLib TrigDecisionEvent TrigMissingEtEvent TrigInDetTruthEvent TrigT1Interfaces DecisionHandlingLib ) # Install files from the package: atlas_install_headers( TrigValAlgs ) diff --git a/Trigger/TrigValidation/TrigValAlgs/TrigValAlgs/TrigEDMChecker.h b/Trigger/TrigValidation/TrigValAlgs/TrigValAlgs/TrigEDMChecker.h index d6197e72c42..eb2298c6124 100755 --- a/Trigger/TrigValidation/TrigValAlgs/TrigValAlgs/TrigEDMChecker.h +++ b/Trigger/TrigValidation/TrigValAlgs/TrigValAlgs/TrigEDMChecker.h @@ -9,12 +9,20 @@ #include "GaudiKernel/ObjectVector.h" #include "CLHEP/Units/SystemOfUnits.h" -#include "AthenaBaseComps/AthAlgorithm.h" +#include "AthAnalysisBaseComps/AthAnalysisAlgorithm.h" #include "xAODTrigger/TrigCompositeContainer.h" #include "AthenaKernel/IClassIDSvc.h" +#include "StoreGate/ReadHandleKey.h" +#include "StoreGate/WriteHandleKey.h" +#include "xAODTrigger/TrigNavigation.h" +#include "DecisionHandling/TrigCompositeUtils.h" +#include "TrigNavigation/Navigation.h" +#include "GaudiKernel/ToolHandle.h" + + #include <string> // forward declarations of muon track classes used in TrigMuonEFInfo @@ -28,7 +36,7 @@ namespace Rec { class IMuonPrintingTool; } -class TrigEDMChecker : public AthAlgorithm { +class TrigEDMChecker : public AthAnalysisAlgorithm { public: @@ -173,6 +181,9 @@ class TrigEDMChecker : public AthAlgorithm { bool m_doDumpAllTrigComposite; std::vector<std::string> m_dumpTrigCompositeContainers; + bool m_doDumpNavigation; + StatusCode dumpNavigation(); + /** * @brief Dump information on TrigComposite collections * @@ -201,6 +212,9 @@ class TrigEDMChecker : public AthAlgorithm { ServiceHandle< ::IClassIDSvc > m_clidSvc; + SG::ReadHandleKey< xAOD::TrigNavigation > m_navigationHandleKey{ this, "TrigNavigation", "TrigNavigation", "" }; + SG::WriteHandleKey<TrigCompositeUtils::DecisionContainer> m_decisionsKey{ this, "Decisions", "RoIDecisions", "Decisions created from TEs" }; + ToolHandle< HLT::Navigation > m_navigationTool{ this, "NavigationTool", "HLT::Navigation/Navigation", "" }; }; #endif // TRIG_EDM_CHECKER_H diff --git a/Trigger/TrigValidation/TrigValAlgs/src/TrigEDMChecker.cxx b/Trigger/TrigValidation/TrigValAlgs/src/TrigEDMChecker.cxx index abebc076bba..e9d474636d1 100644 --- a/Trigger/TrigValidation/TrigValAlgs/src/TrigEDMChecker.cxx +++ b/Trigger/TrigValidation/TrigValAlgs/src/TrigEDMChecker.cxx @@ -13,6 +13,10 @@ #include "xAODTrigger/TrigPassBitsContainer.h" #include "xAODTrigger/TrigPassBits.h" +#include "xAODTrigger/TriggerMenuContainer.h" +#include "TrigNavStructure/TriggerElement.h" +#include "TrigConfHLTData/HLTUtils.h" + #include "AthContainers/debug.h" #include "xAODJet/JetContainer.h" #include "xAODJet/JetConstituentVector.h" @@ -98,6 +102,7 @@ #include <iostream> #include <fstream> +#include <queue> static int trackWarningNum; static int vertexWarningNum; @@ -105,7 +110,7 @@ static int maxRepWarnings; TrigEDMChecker::TrigEDMChecker(const std::string& name, ISvcLocator* pSvcLocator) - : AthAlgorithm(name, pSvcLocator), + : AthAnalysisAlgorithm(name, pSvcLocator), m_muonPrinter("Rec::MuonPrintingTool/MuonPrintingTool"), m_clidSvc( "ClassIDSvc", name ) { @@ -155,6 +160,7 @@ TrigEDMChecker::TrigEDMChecker(const std::string& name, ISvcLocator* pSvcLocator declareProperty("doDumpAllTrigComposite", m_doDumpAllTrigComposite = false ); declareProperty("dumpTrigCompositeContainers", m_dumpTrigCompositeContainers, "List of TC to dump" ); declareProperty("doDumpTrigCompsiteNavigation", m_doDumpTrigCompsiteNavigation = false ); + declareProperty("doDumpNavigation", m_doDumpNavigation = false ); declareProperty( "ClassIDSvc", m_clidSvc, "Service providing CLID info" ); } @@ -164,6 +170,10 @@ TrigEDMChecker::~TrigEDMChecker() {} StatusCode TrigEDMChecker::initialize() { + ATH_CHECK( m_navigationHandleKey.initialize() ); + ATH_CHECK( m_decisionsKey.initialize() ); + ATH_CHECK( m_navigationTool.retrieve() ); + ATH_MSG_DEBUG("Initializing TrigEDMChecker"); ATH_MSG_INFO("REGTEST Initializing..."); @@ -518,6 +528,15 @@ StatusCode TrigEDMChecker::execute() { ATH_MSG_DEBUG(evtStore()->dump()); } + if (m_doDumpAll || m_doDumpNavigation) { + StatusCode sc = dumpNavigation(); + if ( sc.isFailure() ) { + ATH_MSG_ERROR("The method dumpNavigation() failed"); + } + } + + ATH_CHECK( dumpTrigComposite() ); + if (m_doDumpAll || m_doDumpTrigCompsiteNavigation) { std::string trigCompositeSteering; ATH_CHECK(TrigCompositeNavigationToDot(trigCompositeSteering)); @@ -532,8 +551,9 @@ StatusCode TrigEDMChecker::execute() { ofile << trigCompositeSteering; } - ATH_CHECK( dumpTrigComposite() ); - + + + return StatusCode::SUCCESS; } @@ -4053,10 +4073,16 @@ StatusCode TrigEDMChecker::checkTrigCompositeElementLink(const xAOD::TrigComposi StatusCode TrigEDMChecker::TrigCompositeNavigationToDot(std::string& returnValue) { - std::vector<std::string> keys; + // This constexpr is evaluated at compile time const CLID TrigCompositeCLID = static_cast<CLID>( ClassID_traits< xAOD::TrigCompositeContainer >::ID() ); - evtStore()->keys(TrigCompositeCLID, keys); + std::vector<std::string> keys; + if ( m_doDumpAll ) { + evtStore()->keys(TrigCompositeCLID, keys); + } + else { + std::vector<std::string> keys = m_dumpTrigCompositeContainers; + } std::string typeNameTC; ATH_CHECK(m_clidSvc->getTypeNameOfID(TrigCompositeCLID, typeNameTC)); ATH_MSG_DEBUG("Got " << keys.size() << " keys for " << typeNameTC); @@ -4132,3 +4158,164 @@ StatusCode TrigEDMChecker::TrigCompositeNavigationToDot(std::string& returnValue returnValue.assign( ss.str() ); return StatusCode::SUCCESS; } + +StatusCode TrigEDMChecker::dumpNavigation() +{ + // Get object from store + const xAOD::TrigNavigation * navigationHandle = nullptr; + ATH_CHECK( evtStore()->retrieve( navigationHandle, m_navigationHandleKey.key() ) ); + // Proper version doesn't work - conversion issue? + //SG::ReadHandle< xAOD::TrigNavigation > navigationHandle = SG::ReadHandle< xAOD::TrigNavigation >( m_navigationHandleKey ); + //if ( !navigationHandle.isValid() ) ATH_MSG_FATAL( "Could not retrieve navigation" ); + + // Get serialised navigation info + const std::vector< unsigned int > serialisedNavigation = navigationHandle->serialized(); + ATH_MSG_INFO( "Serialised navigation size: " << serialisedNavigation.size() ); + + // Convert the input + HLT::Navigation* testNav = m_navigationTool.get(); + testNav->deserialize( serialisedNavigation ); + + // Make a map of TE name hashes + const xAOD::TriggerMenuContainer * testMenu = nullptr; + ATH_CHECK( inputMetaStore()->retrieve( testMenu, "TriggerMenu" ) ); + std::map< int, std::string > hash2string; + for ( auto const& sequence : testMenu->front()->sequenceInputTEs() ) { + for ( auto const& name : sequence ) { + int hash = TrigConf::HLTUtils::string2hash( name ); + hash2string[ hash ] = name; + } + } + + // Map TE names to chain names + unsigned int chainCounter = 0; + std::map< int, std::string > hash2chain; + for ( auto const& chain : testMenu->front()->chainSignatureOutputTEs() ) { + + // Find the chain name + std::string chainName = testMenu->front()->chainNames()[ chainCounter ]; + ++chainCounter; + + // Find all associated TEs + for ( auto const& signature : chain ) { + for ( auto const& name : signature ) { + int hash = TrigConf::HLTUtils::string2hash( name ); + hash2string[ hash ] = name; // for decoding + hash2chain[ hash ] = chainName; + } + } + } + + // Define a map of TE features, to the TEs that use them. Needs a custom sort lambda + auto cmpLambda = []( const HLT::TriggerElement::FeatureAccessHelper &lhs, const HLT::TriggerElement::FeatureAccessHelper &rhs) { + + // Compare indices if CLID matches + if ( lhs.getCLID() == rhs.getCLID() ) return ( lhs.getIndex() < rhs.getIndex() ); + + // Compare CLIDs + else return ( lhs.getCLID() < rhs.getCLID() ); + }; + std::map< HLT::TriggerElement::FeatureAccessHelper, std::vector< HLT::TriggerElement* >, decltype(cmpLambda) > feature2element(cmpLambda); + + // Retrieve all TE features and add them to the map + std::vector< HLT::TriggerElement* > allTEs; + testNav->getAll( allTEs, false ); + for ( auto element : allTEs ) { + + // Add TE features to the big map + for ( auto helper : element->getFeatureAccessHelpers() ) { + feature2element[ helper ].push_back( element ); + } + } + + // Debug - output all TEs and their ancestors + // No duplication - only print terminal nodes + for ( auto element : allTEs ) { + if ( testNav->isTerminalNode( element ) ) { + ATH_MSG_INFO( "+++++++++++ " << hash2string[ element->getId() ] << " is terminal node" ); + ATH_MSG_INFO( "ptr: " << element ); + std::queue< HLT::TriggerElement* > allAncestors; + allAncestors.push( element ); + while ( allAncestors.size() ) { + + HLT::TriggerElement * thisElement = allAncestors.front(); + allAncestors.pop(); + auto theseAncestors = thisElement->getRelated( HLT::TriggerElement::Relation::seededByRelation ); + + // Dump TE + ATH_MSG_INFO( "te: " << thisElement->getId() << " " << hash2string[ thisElement->getId() ] ); + ATH_MSG_INFO( " chain: " << hash2chain[ thisElement->getId() ] ); + for ( auto helper : thisElement->getFeatureAccessHelpers() ) { + ATH_MSG_INFO( " feat: " << helper ); + } + ATH_MSG_INFO( theseAncestors.size() << " ancestors" ); + + // Examine ancestors + for ( auto ancestor : theseAncestors ) { + allAncestors.push( ancestor ); + } + } + } + } + + // Make the decision container + SG::WriteHandle< TrigCompositeUtils::DecisionContainer > outputNavigation = TrigCompositeUtils::createAndStore( m_decisionsKey, getContext() ); + auto decisionOutput = outputNavigation.ptr(); + + // Find unique chains associated with a feature + std::map< HLT::TriggerElement const*, std::vector< int > > element2decisions; + for ( auto pair : feature2element ) { + + // Get the feature info + std::string featureName = testNav->label( pair.first.getCLID(), pair.first.getIndex().subTypeIndex() ); + auto sgKey = evtStore()->stringToKey( featureName, pair.first.getCLID() ); + + // Store RoIs with appropriate label ? + std::string storeFeatureName = "feature"; +/* if ( pair.first.getCLID() == ClassID_traits< TrigRoiDescriptor >::ID() ) { + storeFeatureName = "roi"; + }*/ + + // Make a decision object for the feature + auto decision = TrigCompositeUtils::newDecisionIn( decisionOutput ); + decision->typelessSetObjectLink( storeFeatureName, sgKey, pair.first.getCLID(), pair.first.getIndex().objectsBegin(), pair.first.getIndex().objectsEnd() ); + + // Examine associated TEs, look for chains + std::set< std::string > passedChains; + for ( HLT::TriggerElement const* element : pair.second ) { + + // TODO - find out what chains actually passed! + passedChains.insert( hash2chain[ element->getId() ] ); + + // Index the TE + int decisionNumber = decisionOutput->size() - 1; + element2decisions[ element ].push_back( decisionNumber ); + } + + // Store unique chains in the decision + for ( auto& chain : passedChains ) { + TrigCompositeUtils::addDecisionID( TrigConf::HLTUtils::string2hash( chain ), decision ); + } + } + + // Store decision ancestry (had to go through once before to ensure indices populated) + unsigned int decisionCounter = 0; + for ( auto pair : feature2element ) { + + // Get current decision + auto decision = decisionOutput->at( decisionCounter ); + ++decisionCounter; + + // Find ancestor TEs + for ( auto element : pair.second ) { + auto theseAncestors = element->getRelated( HLT::TriggerElement::Relation::seededByRelation ); + for ( auto ancestor : theseAncestors ) { + for ( int decisionIndex : element2decisions[ ancestor ] ) { + TrigCompositeUtils::linkToPrevious( decision, m_decisionsKey.key(), decisionIndex ); + } + } + } + } + + return StatusCode::SUCCESS; +} -- GitLab