diff --git a/Trigger/TrigSteer/DecisionHandling/CMakeLists.txt b/Trigger/TrigSteer/DecisionHandling/CMakeLists.txt index 6defffecb79bf2253253723dddf2c804c6ef6477..dc1ea78ccad2882d4def4149f3f34689e96fe6eb 100644 --- a/Trigger/TrigSteer/DecisionHandling/CMakeLists.txt +++ b/Trigger/TrigSteer/DecisionHandling/CMakeLists.txt @@ -9,7 +9,7 @@ atlas_add_library( DecisionHandlingLib src/DumpDecisions.cxx src/HypoBase.cxx src/InputMakerBase.cxx - src/ITestHypoTool.cxx + src/ITestHypoTool.cxx PUBLIC_HEADERS DecisionHandling LINK_LIBRARIES AthenaBaseComps AthenaMonitoringKernelLib GaudiKernel StoreGateLib TrigCompositeUtilsLib TrigCostMonitorMTLib TrigSteeringEvent TrigTimeAlgsLib PRIVATE_LINK_LIBRARIES AthContainers AthViews xAODTrigger ) @@ -22,10 +22,11 @@ atlas_add_component( DecisionHandling src/TriggerSummaryAlg.cxx src/RoRSeqFilter.cxx src/ViewCreator*.cxx - src/TestRecoAlg.cxx - src/TestInputMaker.cxx - src/TestHypoTool.cxx - src/TestHypoAlg.cxx + src/TestRecoAlg.cxx + src/TestInputMaker.cxx + src/TestHypoTool.cxx + src/TestHypoAlg.cxx + src/PassFilter.cxx LINK_LIBRARIES DecisionHandlingLib xAODTrigCalo AthViews xAODTracking xAODJet ) atlas_install_python_modules( python/*.py POST_BUILD_CMD ${ATLAS_FLAKE8} ) diff --git a/Trigger/TrigSteer/DecisionHandling/python/DecisionHandlingConfig.py b/Trigger/TrigSteer/DecisionHandling/python/DecisionHandlingConfig.py index 8fa029189db31349f76bb2bf19064ee65fd8d70e..fe55b17b79d69986da8bb5e64ecbd09e41418d63 100644 --- a/Trigger/TrigSteer/DecisionHandling/python/DecisionHandlingConfig.py +++ b/Trigger/TrigSteer/DecisionHandling/python/DecisionHandlingConfig.py @@ -3,6 +3,8 @@ # def setupFilterMonitoring( filterAlg ): + if not hasattr(filterAlg, "Input"): + return from AthenaMonitoringKernel.GenericMonitoringTool import GenericMonitoringTool monTool = GenericMonitoringTool('MonTool') diff --git a/Trigger/TrigSteer/DecisionHandling/src/PassFilter.cxx b/Trigger/TrigSteer/DecisionHandling/src/PassFilter.cxx new file mode 100644 index 0000000000000000000000000000000000000000..6b89d26bb40a1f1098e4e45b655753197a4576a2 --- /dev/null +++ b/Trigger/TrigSteer/DecisionHandling/src/PassFilter.cxx @@ -0,0 +1,30 @@ +/* + Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration +*/ + +#include "PassFilter.h" + +PassFilter::PassFilter(const std::string& name, ISvcLocator* pSvcLocator) : + AthReentrantAlgorithm(name, pSvcLocator) +{ +} + +PassFilter::~PassFilter() +{ +} + +StatusCode PassFilter::initialize() +{ + return StatusCode::SUCCESS; +} + +StatusCode PassFilter::finalize() +{ + return StatusCode::SUCCESS; +} + +StatusCode PassFilter::execute(const EventContext&) const +{ + return StatusCode::SUCCESS; +} + diff --git a/Trigger/TrigSteer/DecisionHandling/src/PassFilter.h b/Trigger/TrigSteer/DecisionHandling/src/PassFilter.h new file mode 100644 index 0000000000000000000000000000000000000000..f6ea5c2f29a2877bdda08079203b8c41b12aae03 --- /dev/null +++ b/Trigger/TrigSteer/DecisionHandling/src/PassFilter.h @@ -0,0 +1,30 @@ +/* + Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration +*/ +#ifndef DECISIONHANDLING_PASSFILTER_H +#define DECISIONHANDLING_PASSFILTER_H + +// Framework includes +#include "AthenaBaseComps/AthReentrantAlgorithm.h" + +// STL includes +#include <string> + +/** + * @class PassFilter + * @brief Filter algorithm that always pass, needed to fill gaps in HLT CF + **/ +class PassFilter : public AthReentrantAlgorithm { +public: + PassFilter(const std::string& name, ISvcLocator* pSvcLocator); + virtual ~PassFilter() override; + + virtual StatusCode initialize() override; + virtual StatusCode execute(const EventContext& context) const override; + virtual StatusCode finalize() override; + +private: + +}; + +#endif // DECISIONHANDLING_PASSFILTER_H diff --git a/Trigger/TrigSteer/DecisionHandling/src/RoRSeqFilter.cxx b/Trigger/TrigSteer/DecisionHandling/src/RoRSeqFilter.cxx index 359c1146d84abecdd6e94cbf0dcc38799e19c6d9..2876e30e74e221bb24cf7f241c15dcabcfb64f6a 100644 --- a/Trigger/TrigSteer/DecisionHandling/src/RoRSeqFilter.cxx +++ b/Trigger/TrigSteer/DecisionHandling/src/RoRSeqFilter.cxx @@ -27,25 +27,58 @@ StatusCode RoRSeqFilter::initialize() CHECK( not m_inputKeys.empty() ); CHECK( not m_outputKeys.empty() ); - if ( m_mergeInputs ) { - CHECK( m_inputKeys.size() > 1 ); - CHECK( m_outputKeys.size() == 1 ); - } else { - CHECK( m_inputKeys.size() == m_outputKeys.size() ); - } CHECK( m_inputKeys.initialize() ); CHECK( m_outputKeys.initialize() ); renounceArray(m_inputKeys); + // default IO mappnig nth input -> nth output + if ( m_ioMappingProperty.empty()) { + CHECK( m_inputKeys.size() == m_outputKeys.size() ); + for ( unsigned i = 0; i < m_inputKeys.size(); ++i ) { + m_ioMapping.push_back( {i} ); + } + ATH_MSG_DEBUG( "Default I/O collections mapping nth input -> nth output" ); + } else { + m_ioMapping = m_ioMappingProperty; + ATH_MSG_DEBUG( "Custom I/O mapping used by the filter" ); + } + + for ( size_t i = 0; i < m_ioMapping.size(); ++i ) { + for ( unsigned inIndex: m_ioMapping[i] ) { + ATH_MSG_INFO("Input collection: " << m_inputKeys[inIndex] ); + } + ATH_MSG_INFO(" Routed to output collection " << m_outputKeys[i] ); + } + + // crosscheck mapping (also the default one) + CHECK( m_ioMapping.size() == m_outputKeys.size() ); // all outputs will be filled + std::set<int> inIndices; + for ( auto i: m_ioMapping ) { + CHECK( not i.empty() ); // all outputs are connected to at least one input + inIndices.insert( i.begin(), i.end() ); + } + CHECK( inIndices.size() == m_inputKeys.size() ); // all inputs are routed + for ( size_t i = 0; i < m_ioMapping.size(); ++i ) { + auto iset = std::set( m_ioMapping[i].begin(), m_ioMapping[i].end() ); + for ( size_t j = i+1; j < m_ioMapping.size(); ++j ) { + for ( auto el: m_ioMapping[j] ) { + if ( iset.count( el ) != 0 ) { + ATH_MSG_ERROR( "The input index " << el << " directed to two outputs " << m_ioMapping[i] << " " << m_ioMapping[j] ); + return StatusCode::FAILURE; + } + } + } + } + if (msgLvl(MSG::DEBUG)){ ATH_MSG_DEBUG("Will consume implicit ReadDH:" ); for (auto& input: m_inputKeys){ ATH_MSG_DEBUG(" - "<<input.key()); } ATH_MSG_DEBUG("Will produce WriteDH: "); - for (auto& output: m_outputKeys){ + for (auto& output: m_outputKeys){ ATH_MSG_DEBUG(" - "<<output.key()); } } @@ -55,12 +88,16 @@ StatusCode RoRSeqFilter::initialize() for ( const std::string& el: m_chainsProperty ) m_chains.insert( HLT::Identifier( el ).numeric() ); + m_chainsPerInput.resize( m_chainsPerInputProperty.size() ); + for ( size_t i = 0; i < m_chainsPerInputProperty.size(); ++i ) { + for ( const std::string& el: m_chainsPerInputProperty[i] ) + m_chainsPerInput[i].insert( HLT::Identifier( el ).numeric() ); + } + if (msgLvl(MSG::DEBUG)){ ATH_MSG_DEBUG( "Configured to require these chains: "); for ( const HLT::Identifier& id: m_chains ) ATH_MSG_DEBUG( " - " << id ); - - ATH_MSG_DEBUG( "mergeInputs is " << m_mergeInputs); } if ( not m_monTool.name().empty() ) { @@ -71,28 +108,28 @@ StatusCode RoRSeqFilter::initialize() } -StatusCode RoRSeqFilter::execute(const EventContext& ctx) const { +StatusCode RoRSeqFilter::execute( const EventContext& ctx ) const { ATH_MSG_DEBUG ( "Executing " << name() << "..." ); - auto inputHandles = m_inputKeys.makeHandles(ctx); - auto outputHandles = m_outputKeys.makeHandles(ctx); + auto inputHandles = m_inputKeys.makeHandles( ctx ); + auto outputHandles = m_outputKeys.makeHandles( ctx ); - std::vector<std::string> inputNames({"exec", "anyvalid"}); + std::vector<std::string> inputNames( {"exec", "anyvalid"} ); std::vector<bool> inputStats({true, false}); // position 0 for number of execs, always true, bool at position 1 is set later inputNames.reserve(inputHandles.size() + 2); inputStats.reserve(inputHandles.size() + 2); bool validInputs = false; for ( auto& inputHandle: inputHandles ) { - inputNames.push_back(inputHandle.name()); + inputNames.push_back( inputHandle.name() ); if( inputHandle.isValid() ) {// this is because input is implicit validInputs = true; - inputStats.push_back(true); + inputStats.push_back( true ); } else { - inputStats.push_back(false); + inputStats.push_back( false ); } } inputStats[1] = validInputs; // position 1 for number of execes with any collection valid - auto inputName = Monitored::Collection<std::vector<std::string>>("name", inputNames ); - auto inputStat = Monitored::Collection<std::vector<bool>>("stat", inputStats ); + auto inputName = Monitored::Collection<std::vector<std::string>>( "name", inputNames ); + auto inputStat = Monitored::Collection<std::vector<bool>>( "stat", inputStats ); Monitored::Group( m_monTool, inputStat, inputName ); if (!validInputs) { @@ -101,46 +138,43 @@ StatusCode RoRSeqFilter::execute(const EventContext& ctx) const { return StatusCode::SUCCESS; } - ATH_MSG_DEBUG( "Running on "<< inputHandles.size() <<" input keys"); + ATH_MSG_DEBUG ( "Running on "<< inputHandles.size() <<" input keys" ); size_t passCounter = 0; - size_t outputIndex = 0; - if ( m_mergeInputs ) { - - ATH_MSG_DEBUG( "Recording " << m_outputKeys[ 0 ].key() ); - createAndStore(outputHandles[0]); - DecisionContainer* output = outputHandles[0].ptr(); - for ( auto& inputHandle: inputHandles) { - if( inputHandle.isValid() ) { - passCounter += copyPassing( *inputHandle, *output ); - } - } - outputIndex++; - - } else { // Not merging inputs - - for ( auto& inputHandle: inputHandles ) { - if( not inputHandle.isValid() ) { - ATH_MSG_DEBUG( "InputHandle "<< inputHandle.key() <<" not present" ); - } else if ( inputHandle->empty() ) { - ATH_MSG_DEBUG( "InputHandle "<< inputHandle.key() <<" contains all rejected decisions, skipping" ); + for ( size_t outputIndex = 0; outputIndex < m_ioMapping.size(); ++outputIndex ) { + bool anyPresent = false; + for ( unsigned inputIndex : m_ioMapping[outputIndex] ) { + if( not inputHandles[inputIndex].isValid() ) { + ATH_MSG_DEBUG( "InputHandle "<< inputHandles[inputIndex].key() <<" not present" ); + } else if ( inputHandles[inputIndex]->empty() ) { + ATH_MSG_DEBUG( "InputHandle "<< inputHandles[inputIndex].key() <<" contains all rejected decisions, skipping" ); } else { - ATH_MSG_DEBUG( "Checking inputHandle: "<< inputHandle.key() <<" has " << inputHandle->size() <<" elements"); - createAndStore(outputHandles[outputIndex]); - DecisionContainer* output = outputHandles[outputIndex].ptr(); - passCounter += copyPassing( *inputHandle, *output ); - ATH_MSG_DEBUG( "Recorded output key " << m_outputKeys[ outputIndex ].key() <<" of size "<<output->size() <<" at index "<< outputIndex); + anyPresent = true; + } + } + if ( anyPresent ) { + createAndStore(outputHandles[outputIndex]); + DecisionContainer* output = outputHandles[outputIndex].ptr(); + for ( auto inputIndex : m_ioMapping[outputIndex] ) { + if ( inputHandles[inputIndex].isValid() and not inputHandles[inputIndex]->empty() ) { + ATH_MSG_DEBUG( "Checking inputHandle: "<< inputHandles[inputIndex].key() <<" has " << inputHandles[inputIndex]->size() <<" elements"); + if ( not m_chainsPerInput.empty() ) { + passCounter += copyPassing( *inputHandles[inputIndex], *output, m_chainsPerInput[inputIndex] ); + } else { + passCounter += copyPassing( *inputHandles[inputIndex], *output, m_chains ); + } + ATH_MSG_DEBUG( "Recorded output key " << m_outputKeys[ outputIndex ].key() <<" of size "<<output->size() <<" at index "<< outputIndex); + } } - outputIndex++; // Keep the mapping of inputKey<->outputKey correct } } setFilterPassed( passCounter != 0, ctx ); - ATH_MSG_DEBUG( "Filter " << ( filterPassed(ctx) ? "passed" : "rejected") <<"; creating "<< outputIndex<<" valid outDecisions DH:"); - if (msgLvl(MSG::DEBUG)){ - for (auto& output: outputHandles){ - if( output.isValid() ) ATH_MSG_DEBUG(" "<<output.key()); + ATH_MSG_DEBUG( "Filter " << ( filterPassed(ctx) ? "passed" : "rejected" ) ); + if ( msgLvl( MSG::DEBUG ) ){ + for ( auto& output: outputHandles ) { + if( output.isValid() ) ATH_MSG_DEBUG( " "<<output.key() ); } } @@ -148,8 +182,8 @@ StatusCode RoRSeqFilter::execute(const EventContext& ctx) const { return StatusCode::SUCCESS; } -size_t RoRSeqFilter::copyPassing( const DecisionContainer& input, - DecisionContainer& output ) const { +size_t RoRSeqFilter::copyPassing( const DecisionContainer& input, + DecisionContainer& output, const std::set<HLT::Identifier>& topass ) const { size_t passCounter = 0; for (size_t i = 0; i < input.size(); ++i) { const Decision* inputDecision = input.at(i); @@ -160,7 +194,7 @@ size_t RoRSeqFilter::copyPassing( const DecisionContainer& input, ATH_MSG_DEBUG("Number of positive decisions for this input is " << objDecisions.size() <<". Now Filtering...." ); DecisionIDContainer intersection; - std::set_intersection( m_chains.begin(), m_chains.end(), + std::set_intersection( topass.begin(), topass.end(), objDecisions.begin(), objDecisions.end(), std::inserter(intersection, intersection.end()) ); @@ -175,9 +209,9 @@ size_t RoRSeqFilter::copyPassing( const DecisionContainer& input, passCounter ++; ATH_MSG_DEBUG("Input satisfied at least one filtering chain. Chain(s) passing:"); if (msgLvl(MSG::DEBUG)){ - for ( DecisionID id : intersection ) { - ATH_MSG_DEBUG( " -- " << HLT::Identifier( id ) ); - } + for ( DecisionID id : intersection ) { + ATH_MSG_DEBUG( " -- " << HLT::Identifier( id ) ); + } } } else { diff --git a/Trigger/TrigSteer/DecisionHandling/src/RoRSeqFilter.h b/Trigger/TrigSteer/DecisionHandling/src/RoRSeqFilter.h index ac24edb149317fb1dd4986f82cfd09575b60de35..6fc374e0b55e2de76cea35403811d2bca7f87b73 100644 --- a/Trigger/TrigSteer/DecisionHandling/src/RoRSeqFilter.h +++ b/Trigger/TrigSteer/DecisionHandling/src/RoRSeqFilter.h @@ -7,6 +7,7 @@ #include <string> #include <set> +#include "Gaudi/Parsers/Factory.h" #include "AthenaBaseComps/AthReentrantAlgorithm.h" #include "AthContainers/ConstDataVector.h" #include "TrigCompositeUtils/TrigCompositeUtils.h" @@ -66,9 +67,18 @@ class RoRSeqFilter SG::WriteHandleKeyArray<TrigCompositeUtils::DecisionContainer> m_outputKeys{ this, "Output", {}, "Output" }; Gaudi::Property<std::vector<std::string> > m_chainsProperty{ this, "Chains", {}, "Chains of which this filter is concerned" }; - Gaudi::Property<bool> m_mergeInputs{ this, "MergeInputs", false, "Produce one output" }; std::set<HLT::Identifier> m_chains; + Gaudi::Property<std::vector <std::vector<std::string>> > m_chainsPerInputProperty{ this, "ChainsPerInput", {}, "Chains of which this filter is concerned" }; + std::vector<std::set<HLT::Identifier>> m_chainsPerInput; + + /** + * It can be used to define a custom routing from input to output collections + * Example: [[0,1,3], [2]] means that inputs 0, 1, and 3 are directed to output 0, and input under the index 2 to aoutput 1 + * When not set the default is used. I.e. nth input -> nth output + **/ + Gaudi::Property< std::vector<std::vector<unsigned>> > m_ioMappingProperty { this, "IOMapping", {}, "Maps which inputs should be routed to which output" }; + std::vector<std::vector<unsigned>> m_ioMapping; /** * @brief Applies generic filter to input container, keeping only the decision objects with at least @@ -82,7 +92,7 @@ class RoRSeqFilter * parent and stored in the output collection. It will form the starting point for the next Step. **/ size_t copyPassing( const TrigCompositeUtils::DecisionContainer& input, - TrigCompositeUtils::DecisionContainer& output) const; + TrigCompositeUtils::DecisionContainer& output, const std::set<HLT::Identifier>& topass) const; ToolHandle<GenericMonitoringTool> m_monTool{ this, "MonTool", "", "Filter I/O monitoring" }; }; diff --git a/Trigger/TrigSteer/DecisionHandling/src/components/DecisionHandling_entries.cxx b/Trigger/TrigSteer/DecisionHandling/src/components/DecisionHandling_entries.cxx index 7f12647651da6dbe4a0ace81a4295b0195cc39a6..33eb0f68a38b197fe1a1a8610cbbf1ffeacbb0d4 100644 --- a/Trigger/TrigSteer/DecisionHandling/src/components/DecisionHandling_entries.cxx +++ b/Trigger/TrigSteer/DecisionHandling/src/components/DecisionHandling_entries.cxx @@ -1,5 +1,6 @@ #include "../DumpDecisions.h" #include "../RoRSeqFilter.h" +#include "../PassFilter.h" #include "../TriggerSummaryAlg.h" #include "DecisionHandling/ComboHypo.h" #include "../InputMakerForRoI.h" @@ -28,6 +29,7 @@ DECLARE_COMPONENT( HLTTest::TestRecoAlg ) DECLARE_COMPONENT( DumpDecisions ) DECLARE_COMPONENT( RoRSeqFilter ) +DECLARE_COMPONENT( PassFilter ) DECLARE_COMPONENT( TriggerSummaryAlg ) DECLARE_COMPONENT( ComboHypo ) DECLARE_COMPONENT( InputMakerForRoI ) diff --git a/Trigger/TriggerCommon/TriggerJobOpts/python/TriggerConfig.py b/Trigger/TriggerCommon/TriggerJobOpts/python/TriggerConfig.py index a5e8ece08353a46ee245556130dd796216dd2d16..f0e7b9ccf2c3bdf21c3cf8dce1b3d5788b5d678b 100644 --- a/Trigger/TriggerCommon/TriggerJobOpts/python/TriggerConfig.py +++ b/Trigger/TriggerCommon/TriggerJobOpts/python/TriggerConfig.py @@ -50,7 +50,7 @@ def collectHypos( steps ): def __decisionsFromHypo( hypo ): """ return all chains served by this hypo and the key of produced decision object """ from TrigCompositeUtils.TrigCompositeUtils import isLegId - __log.debug("Hypo type is combo {}".format( __isCombo( hypo ) ) ) + __log.debug("Hypo type {} is combo {}".format( hypo.getName(), __isCombo( hypo ) ) ) if __isCombo( hypo ): return [key for key in list(hypo.MultiplicitiesMap.keys()) if not isLegId(key)], hypo.HypoOutputDecisions[0] else: # regular hypos @@ -130,9 +130,9 @@ def collectFilterDecisionObjects(filters, inputs = True, outputs = True): decisionObjects = set() for step, stepFilters in six.iteritems (filters): for filt in stepFilters: - if inputs: + if inputs and hasattr( filt, "Input" ): decisionObjects.update( filt.Input ) - if outputs: + if outputs and hasattr( filt, "Output" ): decisionObjects.update( filt.Output ) __log.info("Collecting %i decision objects from filters", len(decisionObjects)) return decisionObjects diff --git a/Trigger/TriggerCommon/TriggerMenuMT/python/HLTMenuConfig/Electron/generateElectron.py b/Trigger/TriggerCommon/TriggerMenuMT/python/HLTMenuConfig/Electron/generateElectron.py index c73e14378ddbd87127fbb7befd0b201fbd3e37cb..553fbbb9de38512dbbdf12b145a75a9c8620c9e3 100644 --- a/Trigger/TriggerCommon/TriggerMenuMT/python/HLTMenuConfig/Electron/generateElectron.py +++ b/Trigger/TriggerCommon/TriggerMenuMT/python/HLTMenuConfig/Electron/generateElectron.py @@ -2,7 +2,7 @@ from TriggerMenuMT.HLTMenuConfig.Electron.ElectronRecoSequences import l2CaloRecoCfg, l2CaloHypoCfg from TriggerMenuMT.HLTMenuConfig.Menu.MenuComponents import CAMenuSequence, \ - ChainStep, Chain, createStepView + ChainStep, Chain, createStepView, EmptyMenuSequence from TrigEgammaHypo.TrigEgammaFastCaloHypoTool import TrigEgammaFastCaloHypoToolFromDict from AthenaConfiguration.ComponentAccumulator import ComponentAccumulator @@ -87,7 +87,7 @@ def generateChains( flags, chainDict ): # # # EF ID # # # offline egamma - - chain = Chain( chainDict['chainName'], L1Thresholds=l1Thresholds, ChainSteps=[fastCaloStep, fastInDetStep] ) + emptyStep = ChainStep(name="EmptyElStep", Sequences=[EmptyMenuSequence("EmptyElStep")], chainDicts=[chainDict]) + chain = Chain( chainDict['chainName'], L1Thresholds=l1Thresholds, ChainSteps=[fastCaloStep, fastInDetStep, emptyStep] ) return chain diff --git a/Trigger/TriggerCommon/TriggerMenuMT/python/HLTMenuConfig/Jet/generateJet.py b/Trigger/TriggerCommon/TriggerMenuMT/python/HLTMenuConfig/Jet/generateJet.py index 5683afb49b17b36d8451e2f8a26dc083556eecfd..87f6f0587975394a6b92c814524aa5347dfdb15e 100644 --- a/Trigger/TriggerCommon/TriggerMenuMT/python/HLTMenuConfig/Jet/generateJet.py +++ b/Trigger/TriggerCommon/TriggerMenuMT/python/HLTMenuConfig/Jet/generateJet.py @@ -83,7 +83,7 @@ def generateChains( flags, chainDict ): hypo = CompFactory.TrigJetHypoAlgMT("TrigJetHypoAlgMT_a4tcem_subjesIS") jetsfullname = HLT_AntiKt4EMTopo_subjesIS.fullname() hypo.Jets = jetsfullname - acc.addEventAlgo(hypo) + acc.addEventAlgo(hypo, sequenceName=stepView.getName() ) jetSequence = CAMenuSequence( Sequence = inEventReco.sequence(), Maker = inEventReco.inputMaker(), diff --git a/Trigger/TriggerCommon/TriggerMenuMT/python/HLTMenuConfig/Menu/HLTCFConfig_newJO.py b/Trigger/TriggerCommon/TriggerMenuMT/python/HLTMenuConfig/Menu/HLTCFConfig_newJO.py index f7e351239c6c37f8f7207e1213f81bf306ca5789..7fe9fd952164c11cbc348883fea90a38e48d2ce9 100644 --- a/Trigger/TriggerCommon/TriggerMenuMT/python/HLTMenuConfig/Menu/HLTCFConfig_newJO.py +++ b/Trigger/TriggerCommon/TriggerMenuMT/python/HLTMenuConfig/Menu/HLTCFConfig_newJO.py @@ -1,17 +1,21 @@ # Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration from functools import lru_cache -from AthenaCommon.CFElements import findAllAlgorithms, parOR, seqAND +from AthenaCommon.CFElements import findAllAlgorithms, parOR, seqAND, isSequence from AthenaCommon.Logging import logging from AthenaConfiguration.ComponentAccumulator import ComponentAccumulator from AthenaConfiguration.ComponentFactory import CompFactory from TriggerMenuMT.HLTMenuConfig.Menu.ChainDictTools import splitChainInDict from TriggerMenuMT.HLTMenuConfig.Menu.MenuComponents import (isComboHypoAlg, - isHypoBase, - isInputMakerBase) + isFilterAlg, + isHypoAlg, + isInputMakerBase, + EmptyMenuSequence) from TriggerMenuMT.HLTMenuConfig.Menu.MenuComponentsNaming import CFNaming from TriggerMenuMT.HLTMenuConfig.Menu.TriggerConfigHLT import TriggerConfigHLT -log = logging.getLogger( __name__ ) +log = logging.getLogger( __name__.split(".")[-1] ) + + def printStepsMatrix(matrix): print('----- Steps matrix ------') # noqa: ATL901 @@ -22,6 +26,89 @@ def printStepsMatrix(matrix): print('---- {}: {}'.format(chainName, namesInCell)) # noqa: ATL901 print('-------------------------') # noqa: ATL901 +def resetDF(acc): + """ + Find all algorithms involved in HLT decision DF and reset properites to empty (lists), unset + """ + for alg in acc.getEventAlgos(): + if isHypoAlg(alg): + log.verbose("Resetting IO for %s Hypo", alg.name ) + alg.HypoInputDecisions = "" + alg.HypoOutputDecisions = "" + if isInputMakerBase(alg): + log.verbose("Resetting IO for %s Input Maker", alg.name ) + alg.InputMakerInputDecisions = [] + alg.InputMakerOutputDecisions = "" + if isFilterAlg(alg): + log.verbose("Resetting IO for %s Filter", alg.name ) + alg.Input = [] + alg.Output = [] + if isComboHypoAlg(alg): + log.verbose("Resetting IO for %s Combo Hypo", alg.name ) + alg.MultiplicitiesMap = {} + alg.HypoInputDecisions = [] + alg.HypoOutputDecisions = [] + +def setHypoOutputs(acc): + for alg in acc.getEventAlgos(): + if isHypoAlg(alg): + alg.HypoOutputDecisions = CFNaming.hypoAlgOutName(alg.name) + +def setIMOutputs(acc): + for alg in acc.getEventAlgos(): + if isInputMakerBase(alg): + alg.InputMakerOutputDecisions = CFNaming.inputMakerOutName(alg.name) + +def traverse(acc, startCollectionName, functor): + """ + Function to traverse DF collections path starting from an arbitrary one + For each checked algorithm visited the functor is called with the collection name through which traversing arrived to it, and the algorithm itself. + Examples are available in the test at the end of the file. + + Note that this traversal has nothing to do with sequences. It only follows DF dependencies. + """ + outputs = {} + # assemble all HLT decision DF algorithms in dictionary keyed by the output that they provide + for alg in acc.getEventAlgos(): # TODO improve CA implementation to obtain all algorithms when no specific sequence is required + if isHypoAlg(alg): + outputs[alg.HypoOutputDecisions] = alg + if isComboHypoAlg(alg): + for d in alg.HypoOutputDecisions: + outputs[d] = alg + if isInputMakerBase(alg): + outputs[alg.InputMakerOutputDecisions] = alg + if isFilterAlg(alg): + for d in alg.Output: + outputs[d] = alg + + # for a given collection and algorithm returns list of inputs that lead to it + # all implementations except for ComboHypo and Filter are trivial + def __jumpToInputs(outputName, alg): + if isHypoAlg(alg): + return [alg.HypoInputDecisions] + if isInputMakerBase(alg): + return alg.InputMakerInputDecisions + if isFilterAlg(alg): + idx = alg.Output.index(outputName) + if len(alg.IOMapping) == 0: # trivial filter configuration, n-th input -> n-th output + return [alg.Input[idx]] + else: + return [alg.Input[i] for i in alg.IOMapping[idx]] + if isComboHypoAlg(alg): + idx = alg.HypoOutputDecisions.index(outputName) + return [alg.HypoInputDecisions[idx]] + + # recursive traversal implementation + def __dive(outColl, alg): + functor(outColl, alg) + inputs = __jumpToInputs(outColl, alg) + for inputColl in inputs: + if inputColl in outputs: + __dive(inputColl, outputs[inputColl]) + + if startCollectionName in outputs: + __dive(startCollectionName, outputs[startCollectionName]) + def generateDecisionTree(chains): acc = ComponentAccumulator() @@ -33,119 +120,104 @@ def generateDecisionTree(chains): """ Returns sequence containing all filters for a step """ - name = 'Step{}_{}'.format(stepNumber, CFNaming.FILTER_POSTFIX) + name = 'Step{}{}'.format(stepNumber, CFNaming.FILTER_POSTFIX) if stepNumber > 1: getRecosStepSeq( stepNumber -1 ) # make sure steps sequencers are correctly made: Step1_filter, Step1_recos, Step2_filters, Step2_recos ... seq = parOR( name ) acc.addSequence( seq, parentName = mainSequenceName ) - return seq + return acc.getSequence(seq.name) @lru_cache(None) def getRecosStepSeq( stepNumber ): """ + Returns sequence containing all reconstruction algorithms """ - getFiltersStepSeq( stepNumber ) # make sure there is filters step before recos + getFiltersStepSeq( stepNumber ) # make sure there is always filters step before reco name = 'Step{}{}'.format(stepNumber, CFNaming.RECO_POSTFIX) seq = parOR( name ) acc.addSequence( seq, parentName = mainSequenceName ) - return seq + return acc.getSequence(seq.name) @lru_cache(None) def getSingleMenuSeq( stepNumber, stepName ): """ """ - name = "Menu{}{}".format(stepNumber, stepName) + name = "Menu{}_{}".format(stepNumber, stepName) seq = seqAND( name ) allRecoSeqName = getRecosStepSeq( stepNumber ).name acc.addSequence(seq, parentName = allRecoSeqName ) - return seq + return acc.getSequence(seq.name) @lru_cache(None) def getComboSequences( stepNumber, stepName ): """ + Produces sequnece encompassing reconstruction sequences needed in combined chains """ singleMenuSeqName = getSingleMenuSeq( stepNumber, stepName ).name - stepComboName = "Combo{}{}".format(stepNumber,stepName) + stepComboName = "Combo{}_{}".format(stepNumber,stepName) acc.addSequence( seqAND(stepComboName), parentName=singleMenuSeqName ) - stepComboRecoName ="ComboReco{}{}".format(stepNumber, stepName) + stepComboRecoName ="ComboReco{}_{}".format(stepNumber, stepName) acc.addSequence( parOR(stepComboRecoName), parentName=stepComboName ) return acc.getSequence(stepComboName), acc.getSequence(stepComboRecoName) + def isEmpty( step ): + return all([isinstance(seq, EmptyMenuSequence) for seq in step.sequences]) + @lru_cache(None) - def getFilterAlg( stepNumber, stepName ): + def getFilterAlg( stepNumber, stepName, isEmpty ): """ Returns, if need be created, filter for a given step """ + filtersStep = getFiltersStepSeq(stepNumber) + singleMenuSeq = getSingleMenuSeq(stepNumber, step.name) + if isEmpty: + filterAlg = CompFactory.PassFilter(CFNaming.filterName("Pass")) + else: + filterAlg = CompFactory.RoRSeqFilter(CFNaming.filterName(stepName)) + acc.addEventAlgo(filterAlg, sequenceName=filtersStep.name) + acc.addEventAlgo(filterAlg, sequenceName=singleMenuSeq.name) - filtersStep = getFiltersStepSeq( stepNumber ) - singleMenuSeq = getSingleMenuSeq( stepNumber, stepName ) - - filterName = CFNaming.filterName( stepName ) - filterAlg = CompFactory.RoRSeqFilter( filterName ) - - acc.addEventAlgo( filterAlg, sequenceName=filtersStep.name ) - acc.addEventAlgo( filterAlg, sequenceName=singleMenuSeq.name ) + log.debug('Creted filter {}'.format(filterAlg.name)) + return acc.getEventAlgo(filterAlg.name) - log.debug('Creted filter {}'.format(filterName)) - return filterAlg - @lru_cache(None) - def findInputMaker( stepCounter, stepName ): - seq = getSingleMenuSeq( stepCounter, stepName ) - algs = findAllAlgorithms( seq ) - for alg in algs: - if isInputMakerBase(alg): - return alg - raise Exception("No input maker in seq "+seq.name) + def __findAllOf( stepCounter, stepName, predicate): + """ + Find all algorithms fulfilling predicate, for sequnces that do not look like menu None is placed in the result instead + """ + _, comboRecoSeq = getComboSequences( stepCounter, stepName ) + result = [] + for recoSeq in comboRecoSeq.Members: + if isSequence( recoSeq ): + algs = findAllAlgorithms( recoSeq ) + for alg in algs: + if predicate(alg): + result.append(alg) + break + else: + result.append(None) + return result @lru_cache(None) def findAllInputMakers( stepCounter, stepName ): - seq = getSingleMenuSeq( stepCounter, stepName ) - algs = findAllAlgorithms( seq ) - result = [] - for alg in algs: - if isInputMakerBase(alg): - result.append(alg) + return __findAllOf( stepCounter, stepName, isInputMakerBase ) - if result: - return result - else: - raise Exception("No input maker in seq "+seq.name) @lru_cache(None) def findComboHypoAlg( stepCounter, stepName ): seq = getSingleMenuSeq( stepCounter, stepName ) algs = findAllAlgorithms( seq ) for alg in algs: - if isComboHypoAlg(alg): + if isComboHypoAlg( alg ): return alg - raise Exception("No combo hypo alg in seq "+seq.name) - - @lru_cache(None) - def findHypoAlg( stepCounter, stepName ): - seq = getSingleMenuSeq( stepCounter, stepName ) - algs = findAllAlgorithms( seq ) - for alg in algs: - if isHypoBase(alg): - return alg - raise Exception("No hypo alg in seq "+seq.name) - + return None @lru_cache(None) def findAllHypoAlgs( stepCounter, stepName ): - seq = getSingleMenuSeq( stepCounter, stepName ) - algs = findAllAlgorithms( seq ) - result = [] - for alg in algs: - if isHypoBase(alg): - result.append(alg) - - if result: - return result - else: - raise Exception("No hypo alg in seq "+seq.name) + r = __findAllOf( stepCounter, stepName, isHypoAlg ) + return r def addAndAssureUniqness( prop, toadd, context="" ): @@ -161,12 +233,15 @@ def generateDecisionTree(chains): """ Central function setting strnig like proeprties (collection keys). Assures that valid names are not overwritten. """ - if prop == "" or prop == toadd: + if prop == "" or prop == [] or prop == toadd: return toadd if prop != toadd: raise Exception("{}, when setting property found conflicting values, existing {} and new {}".format(context, prop, toadd)) def clearUnderscores(s): + """ + Humanizes collection name by removing multiple underscroers and stripping trailing ones + """ p = s while True: n = p.replace("__", "_") @@ -174,96 +249,138 @@ def generateDecisionTree(chains): return p.rstrip("_") p = n - @lru_cache(None) - def prevStepOutput( chain, stepCounter ): + def prevStepComboHypoOutput(stepCounter, chain): """ - Returns list of decision collections that are outputs of previous step as well as the hypo alg name that outpus it + Returns list of decision collections that are outputs of previous step ComboHypo + For the outputs of HypoAlgs use stepHypoOutput """ - prevHypoAlgName = "" if stepCounter == 1: # L1 seed - out = chain.L1decisions + return chain.L1decisions, "" else: prevCounter = stepCounter-1 prevName = chain.steps[prevCounter-1].name # counting steps from 1, for indexing need one less - prevHypoAlg = findComboHypoAlg( prevCounter, prevName ) - out = prevHypoAlg.HypoOutputDecisions - prevHypoAlgName = prevHypoAlg.name + prevCombo = findComboHypoAlg(prevCounter, prevName) + if not prevCombo: + return prevStepComboHypoOutput(stepCounter - 1, chain) + return prevCombo.HypoOutputDecisions, prevCombo.name + + @lru_cache(None) + def stepHypoOutput( stepCounter, chain ): + """ + Return hypo outputs, if missing traverse sequences back to find one + """ + hypos = findAllHypoAlgs( stepCounter, chain.steps[stepCounter-1].name ) + if any( [h is None for h in hypos] ): + prevHypos = stepHypoOutput( stepCounter-1, chain ) + return [ _1 if _1 else _2 for (_1, _2) in zip(hypos, prevHypos) ] # select leter hypo if set + return hypos - return [out] if isinstance( out, str) else out, prevHypoAlgName # normalise to list - # CF construction logic - # create all sequences and filter algs, merge CAs from signatures (decision CF) + # CF construction + # creates all sequences and filter algs, merge CAs from signatures for chain in chains: for stepCounter, step in enumerate( chain.steps, 1 ): - getFilterAlg( stepCounter, step.name ) - getSingleMenuSeq( stepCounter, step.name ).name + getSingleMenuSeq( stepCounter, step.name ) + getFilterAlg(stepCounter, step.name, isEmpty(step)) # add sequences that allows reconstructions to be run in parallel, followed (in sequence) by the combo hypo comboSeq, comboRecoSeq = getComboSequences( stepCounter, step.name ) - for sequence in step.sequences: - acc.merge( sequence.ca, sequenceName=comboRecoSeq.name) - comboHypo = CompFactory.ComboHypo( "CH"+step.name, CheckMultiplicityMap = len(step.sequences) != 1 ) - acc.addEventAlgo( comboHypo, sequenceName=comboSeq.name ) - pass - - # cleanup settings made by Chain & related objects (can be removed in the future) - for chain in chains: - for stepCounter, step in enumerate( chain.steps, 1 ): - filterAlg = getFilterAlg( stepCounter, step.name ) - filterAlg.Input = [] - filterAlg.Output = [] - - imAlgs = findAllInputMakers( stepCounter, step.name ) - for imAlg in imAlgs: - imAlg.InputMakerInputDecisions = [] - imAlg.InputMakerOutputDecisions = "" - hypoAlgs = findAllHypoAlgs( stepCounter, step.name ) - for hypoAlg in hypoAlgs: - hypoAlg.HypoInputDecisions = "" - hypoAlg.HypoOutputDecisions = "" - - comboHypoAlg = findComboHypoAlg( stepCounter, step.name ) - comboHypoAlg.MultiplicitiesMap = {} - comboHypoAlg.HypoInputDecisions = [] - comboHypoAlg.HypoOutputDecisions = [] + needCombo = False + for sequence in step.sequences: + if not isinstance(sequence,EmptyMenuSequence): # empty sequence + acc.merge( sequence.ca, sequenceName=comboRecoSeq.name) + needCombo = True + else: # empty sequence + acc.addEventAlgo( CompFactory.PassFilter("Pass"), sequenceName=comboRecoSeq.name) + if needCombo: + comboHypo = CompFactory.ComboHypo( "CH"+step.name, CheckMultiplicityMap = len(step.sequences) != 1 ) + acc.addEventAlgo( comboHypo, sequenceName=comboSeq.name ) + pass + acc.printConfig() + resetDF(acc) + setHypoOutputs(acc) + setIMOutputs(acc) + log.debug("Configured Hypo Alg and IM Outputs") - # connect all outputs (decision DF) and add chains to filter on + # continue DF setting using chains info for chain in chains: for stepCounter, step in enumerate( chain.steps, 1 ): - # Filters linking - filterAlg = getFilterAlg( stepCounter, step.name ) + if isEmpty(step): + continue + + def __commonWihtOtherOuptut( newInputColl, filterAlg, comboHypo ): + """ + For a new input collection that is meant to be added to the filter algorithm check + if any hypo leading to it has the same input as any other input to that filter + """ + if len(filterAlg.Output) == 0: # there can not be any commonality if there is no output + return None + colls = [] + def __collectFilterInputs( outColl, alg ): + if isFilterAlg(alg): + idx = alg.Output.index(outColl) + colls.append(alg.Input[idx]) + colls = [] + traverse( acc, newInputColl, __collectFilterInputs) + newInputHistory = set(colls) + for existingOutput in filterAlg.Output: + colls = [] + traverse( acc, existingOutput, __collectFilterInputs) + if len(set(colls).intersection(newInputHistory)) != 0: + return existingOutput + return None + + + prevComboOut, prevComboName = prevStepComboHypoOutput(stepCounter, chain) def __setup(sequenceCounter, chainDict): - ''' - Local function to setup filter/input makers/hypo algs IO - ''' - # set chain to filter on - filterAlg.Chains = addAndAssureUniqness( filterAlg.Chains, chainDict["chainName"], "{} filter alg chains".format( filterAlg.name ) ) + """ + Local function to setup filter/input makers/hypo algs IO + It is meant to be used for simple inclusive chains (im this case the sequenceCounter == 0) + For comined chains when the there is more than one sequence per step this function is called as many times as many sequences there is + """ + filterAlg = getFilterAlg(stepCounter, step.name, isEmpty(step)) + + comboOut = prevComboOut[sequenceCounter] + if comboOut not in filterAlg.Input: # input is not yet connected to filter + commonWihtOutput = __commonWihtOtherOuptut( comboOut, filterAlg, comboHypo ) + if commonWihtOutput: # this input has commonalities with other input, appropriate output is returned + filterOut = commonWihtOutput + filterAlg.IOMapping[ filterAlg.Output.index(commonWihtOutput) ].append( len(filterAlg.Input) ) + else: # entirely new input + filterAlg.IOMapping.append( [len(filterAlg.Input)] ) + filterOut = clearUnderscores(CFNaming.filterOutName( filterAlg.name, comboOut ).replace(prevComboName, "")) + filterAlg.Output = addAndAssureUniqness(filterAlg.Output, filterOut, "{} output".format(filterAlg.name)) + filterAlg.Input.append( comboOut ) + filterAlg.ChainsPerInput.append([]) + else: # that input is connected to the filter, so it was already wired correctly to the output, we need to find out to which output it was connected + inputIndex = filterAlg.Input.index(comboOut) + for outIndex, inputIndices in enumerate(filterAlg.IOMapping): + if inputIndex in inputIndices: + filterOut = filterAlg.Output[outIndex] - filterIn, prevHypoName = prevStepOutput( chain, stepCounter) - filterAlg.Input = addAndAssureUniqness( filterAlg.Input, filterIn, "{} input".format( filterAlg.name ) ) - filterOut = [ clearUnderscores(CFNaming.filterOutName( filterAlg.name, s ).replace(prevHypoName, "")) for s in filterIn ] - filterAlg.Output = addAndAssureUniqness( filterAlg.Output, filterOut, "{} output".format( filterAlg.name ) ) + # set chain to filter on + filterAlg.ChainsPerInput[filterAlg.Input.index(comboOut)] = addAndAssureUniqness( filterAlg.ChainsPerInput[filterAlg.Input.index(comboOut)], chainDict["chainName"], + "{} filtered cahins".format(filterAlg.name)) + filterAlg.Chains = addAndAssureUniqness( filterAlg.Chains, chainDict["chainName"], + "{} filtered cahins".format(filterAlg.name)) - im = findAllInputMakers( stepCounter, step.name )[sequenceCounter] - im.InputMakerInputDecisions = addAndAssureUniqness( im.InputMakerInputDecisions, filterOut[sequenceCounter], "{} input".format( im.name ) ) - imOut = CFNaming.inputMakerOutName( im.name ) - im.InputMakerOutputDecisions = assureUnsetOrTheSame( im.InputMakerOutputDecisions, imOut, "{} IM output".format( im.name ) ) + imAlg = findAllInputMakers( stepCounter, step.name )[sequenceCounter] + if imAlg: + imAlg.InputMakerInputDecisions = addAndAssureUniqness( imAlg.InputMakerInputDecisions, filterOut, "{} input".format( imAlg.name ) ) - # Hypo linking + # IM -> Hypo linking hypoAlg = findAllHypoAlgs( stepCounter, step.name )[sequenceCounter] - hypoAlg.HypoInputDecisions = assureUnsetOrTheSame( hypoAlg.HypoInputDecisions, im.InputMakerOutputDecisions, - "{} hypo input".format( hypoAlg.name ) ) - hypoOut = CFNaming.hypoAlgOutName( hypoAlg.name ) - hypoAlg.HypoOutputDecisions = assureUnsetOrTheSame( hypoAlg.HypoOutputDecisions, hypoOut, - "{} hypo output".format( hypoAlg.name ) ) - - hypoAlg.HypoTools.append( step.sequences[sequenceCounter]._hypoToolConf.confAndCreate( chainDict ) ) + if hypoAlg: + hypoAlg.HypoInputDecisions = assureUnsetOrTheSame( hypoAlg.HypoInputDecisions, imAlg.InputMakerOutputDecisions, + "{} hypo input".format( hypoAlg.name ) ) + # chain selection is setup here + hypoAlg.HypoTools.append( step.sequences[sequenceCounter]._hypoToolConf.confAndCreate( chainDict ) ) pass chainDictLegs = splitChainInDict( chain.name ) - # possible cases: A) number of seqeunces == number of chain parts, e5_mu10 or just e3 type of chain + # possible cases: A) number of seqeunces == number of chain parts, e5_mu10 or just e3 type of chain # ([0, 1], [0, 1]) is the set of indices indices = zip( range( len( step.sequences ) ), range( len( chainDictLegs ) ) )# case A # B) number of sequences == 1 && number of chain parts > 1 for single signature assymetric combined chains e5_e3 type chain @@ -273,46 +390,140 @@ def generateDecisionTree(chains): for seqCounter, chainDictCounter in indices: chainLegDict = chainDictLegs[chainDictCounter] __setup( seqCounter, chainLegDict ) - comboHypoAlg = findComboHypoAlg( stepCounter, step.name ) + + comboHypoAlg = findComboHypoAlg( stepCounter, step.name ) + if comboHypoAlg: + comboHypoAlg.MultiplicitiesMap[chain.name] = step.multiplicity - elementaryHypos = findAllHypoAlgs( stepCounter, step.name ) - for hypo in elementaryHypos: - if hypo == comboHypoAlg: - continue - comboHypoAlg.HypoInputDecisions = addAndAssureUniqness( comboHypoAlg.HypoInputDecisions, hypo.HypoOutputDecisions, - "{} comboHypo input".format( comboHypoAlg.name ) ) - comboOut = CFNaming.comboHypoOutputName( comboHypoAlg.name, hypo.name ) - comboHypoAlg.HypoOutputDecisions = addAndAssureUniqness( comboHypoAlg.HypoOutputDecisions, comboOut, - "{} comboHypo output".format( comboHypoAlg.name ) ) - # Combo Hypo Tools - for comboToolConf in step.comboToolConfs: - comboHypoAlg.ComboHypoTools.append( comboToolConf.confAndCreate( TriggerConfigHLT.getChainDictFromChainName( chain.name ) ) ) + elementaryHyposOutputs = stepHypoOutput( stepCounter, chain ) + for hypo in elementaryHyposOutputs: + if hypo: + comboHypoAlg.HypoInputDecisions = addAndAssureUniqness( comboHypoAlg.HypoInputDecisions, hypo.HypoOutputDecisions, + "{} comboHypo input".format( comboHypoAlg.name ) ) + comboOut = CFNaming.comboHypoOutputName( comboHypoAlg.name, hypo.name ) + comboHypoAlg.HypoOutputDecisions = addAndAssureUniqness( comboHypoAlg.HypoOutputDecisions, comboOut, + "{} comboHypo output".format( comboHypoAlg.name ) ) + # if chan requires special combo tools (TODO understand why not only one tool?) + for comboToolConf in step.comboToolConfs: + comboHypoAlg.ComboHypoTools.append( comboToolConf.confAndCreate( TriggerConfigHLT.getChainDictFromChainName( chain.name ) ) ) for chain in chains: - log.info( "CF algorithms for chain {}".format( chain.name ) ) + log.info( "CF algorithms for chain {}".format(chain.name)) for stepCounter, step in enumerate( chain.steps, 1 ): - filterAlg = getFilterAlg( stepCounter, step.name ) - log.info(" FilterAlg {} Inputs {} Outputs {} Chains {}".format( filterAlg.name, filterAlg.Input, filterAlg.Output, filterAlg.Chains ) ) - - imAlg = findInputMaker( stepCounter, step.name ) - log.info(" InputMaker {} Inputs {} Outputs {}".format( imAlg.name, imAlg.InputMakerInputDecisions, imAlg.InputMakerOutputDecisions ) ) - if step.isCombo: - hypoAlgs = findAllHypoAlgs( stepCounter, step.name ) - for hypoAlg in hypoAlgs: - if isComboHypoAlg(hypoAlg): - continue - log.info(" HypoAlg {} Inputs {} Outputs {} Tools {}".format( hypoAlg.name, hypoAlg.HypoInputDecisions, hypoAlg.HypoOutputDecisions, [t.name for t in hypoAlg.HypoTools] ) ) - combo = findComboHypoAlg( stepCounter, step.name ) - log.info(" ComboHypoAlg {} Inputs {} Outputs {} Multiplicities {}".format( combo.name, combo.HypoInputDecisions, combo.HypoOutputDecisions, combo.MultiplicitiesMap ) ) + filterAlg = getFilterAlg( stepCounter, step.name, isEmpty(step)) + if filterAlg and hasattr(filterAlg, "Input"): + log.info("{} FilterAlg: {} input: {} output: {} IO mapping: {}".format(stepCounter, filterAlg.name, ", ".join(filterAlg.Input), ", ".join(filterAlg.Output), filterAlg.IOMapping)) + for inIndex, input in enumerate(filterAlg.Input): + log.info("{} filered chains from input: {} : {}".format( stepCounter, input, ", ".join(filterAlg.ChainsPerInput[inIndex]) )) + assert len(filterAlg.IOMapping) == len(filterAlg.Output), "Not all output will be filled in filter" - else: - hypoAlg = findHypoAlg( stepCounter, step.name ) - log.info(" HypoAlg {} Inputs {} Outputs {} Tools {}".format( hypoAlg.name, hypoAlg.HypoInputDecisions, hypoAlg.HypoOutputDecisions, [t.name for t in hypoAlg.HypoTools] ) ) + imAlgs = findAllInputMakers( stepCounter, step.name ) + for imAlg in imAlgs: + if imAlg: + log.info("{} InputMaker: {} input: {} output: {}".format(stepCounter, imAlg.name, ", ".join(imAlg.InputMakerInputDecisions), imAlg.InputMakerOutputDecisions)) + hypoAlgs = findAllHypoAlgs(stepCounter, step.name) + for hypoAlg in hypoAlgs: + if hypoAlg: + log.info("{} HypoAlg: {} input: {} output: {}".format(stepCounter, hypoAlg.name, hypoAlg.HypoInputDecisions, hypoAlg.HypoOutputDecisions)) + log.info("{} hypo tools: {}".format(stepCounter, ",".join([t.name for t in hypoAlg.HypoTools]))) + combo = findComboHypoAlg(stepCounter, step.name) + if combo: + log.info("{} ComboHypoAlg: {} input: {} output: {}".format(stepCounter, combo.name, ". ".join(combo.HypoInputDecisions), ", ".join(combo.HypoOutputDecisions))) + log.info("{} multiplicities: {}".format(stepCounter, combo.MultiplicitiesMap)) + assert len(combo.HypoInputDecisions) == len(combo.HypoInputDecisions), "Missconfiguraiton of {} ComboHypo input/output counts differ".format(combo.name) + log.info("-"*50) + log.info("") return acc - -def createControlFlowNewJO(HLTNode, CFseq_list): - """ Creates Control Flow Tree starting from the CFSequences in newJO""" - return +if __name__ == "__main__": + # Test of DF collections traversal + # build hypothetical structure of DF to test back traversing + # make it ressemble the combined chain with one arm that is hollow/empty + # naming convention: H* - hypo, IM* - InputMaker, CH* - combo hypo, F* - filter + # last digit is step + # small letter a/b branch of the selection + acc = ComponentAccumulator() + # step 1 + acc.addEventAlgo(CompFactory.RoRSeqFilter("Fmerged1", Input=["Fa1_I","Fb1_I"], Output=["Fa1merged_O", "Fb1merged_O"])) + acc.addEventAlgo(CompFactory.RoRSeqFilter("Fa1", Input=["Fa1_I"], Output=["Fa1_O"])) + acc.addEventAlgo(CompFactory.RoRSeqFilter("Fb1", Input=["Fb1_I"], Output=["FOb1"])) + acc.addEventAlgo(CompFactory.EventViewCreatorAlgorithm("IMa1", InputMakerInputDecisions=["Fa1_O", "Fa1merged_O"], InputMakerOutputDecisions="IMa1_O")) + acc.addEventAlgo(CompFactory.EventViewCreatorAlgorithm("IMb1", InputMakerInputDecisions=["FOb1", "Fb1merged_O"], InputMakerOutputDecisions="IMb1_O")) + acc.addEventAlgo(CompFactory.HLTTest.TestHypoAlg("Ha1", HypoInputDecisions="IMa1_O", HypoOutputDecisions="Ha1_O")) + acc.addEventAlgo(CompFactory.HLTTest.TestHypoAlg("Hb1", HypoInputDecisions="IMb1_O", HypoOutputDecisions="Hb1_O")) + acc.addEventAlgo(CompFactory.ComboHypo("CHmerged1", HypoInputDecisions=["Ha1_O","Hb1_O"], HypoOutputDecisions=["CHa1merged_O", "CHb1merged_O"])) + acc.addEventAlgo(CompFactory.ComboHypo("CHa1", HypoInputDecisions=["Ha1_O"], HypoOutputDecisions=["CHa1_O"])) + acc.addEventAlgo(CompFactory.ComboHypo("CHb1", HypoInputDecisions=["Hb1_O"], HypoOutputDecisions=["CHb1_O"])) + + # step 2 with alternative merged sequences, when one is empty + acc.addEventAlgo(CompFactory.RoRSeqFilter("Fmerged2", Input=["CHa1merged_O","CHb1merged_O"], Output=["Fa2merged_O", "Fb2merged_O"])) #FOb2maerged dangling/unused + acc.addEventAlgo(CompFactory.RoRSeqFilter("Faltmerged2", Input=["CHa1merged_O"], Output=["Fa2altmerged_O"])) # + acc.addEventAlgo(CompFactory.RoRSeqFilter("Fa2", Input=["CHa1_O"], Output=["Fa2_O"])) + acc.addEventAlgo(CompFactory.RoRSeqFilter("Fb2", Input=["CHb1_O"], Output=["Fb2_O"])) + acc.addEventAlgo(CompFactory.EventViewCreatorAlgorithm("IMa2", InputMakerInputDecisions=["Fa2_O", "Fa2merged_O", "Fa2altmerged_O"], InputMakerOutputDecisions="IMa2_O")) + acc.addEventAlgo(CompFactory.EventViewCreatorAlgorithm("IMb2", InputMakerInputDecisions=["Fb2_O", "Fb2merged_O"], InputMakerOutputDecisions="IMb2_O")) + acc.addEventAlgo(CompFactory.HLTTest.TestHypoAlg("Ha2", HypoInputDecisions="IMa2_O", HypoOutputDecisions="Ha2_O")) + acc.addEventAlgo(CompFactory.HLTTest.TestHypoAlg("Hb2", HypoInputDecisions="IMb2_O", HypoOutputDecisions="Hb2_O")) + acc.addEventAlgo(CompFactory.ComboHypo("CHmerged2", HypoInputDecisions=["Ha2_O","Hb2_O"], HypoOutputDecisions=["CHa2merged_O", "CHb2merged_O"])) # assymetry here, see Hb1_O + acc.addEventAlgo(CompFactory.ComboHypo("CHaltmerged2", HypoInputDecisions=["Ha2_O","Hb1_O"], HypoOutputDecisions=["CHa2altmerged_O", "CHb2altmerged_O"])) # assymetry here, see Hb1_O + acc.addEventAlgo(CompFactory.ComboHypo("CHa2", HypoInputDecisions=["Ha2_O"], HypoOutputDecisions=["CHa2_O"])) + acc.addEventAlgo(CompFactory.ComboHypo("CHb2", HypoInputDecisions=["Hb2_O"], HypoOutputDecisions=["CHb2_O"])) + + # step 3 (wiht missing branch b) + acc.addEventAlgo(CompFactory.RoRSeqFilter("Fmerged3", Input=["CHa2merged_O","CHb2merged_O", "CHa2altmerged_O", "CHb2altmerged_O"], Output=["Fa3merged_O", "Fb3merged_O"], IOMapping=[[0,2],[1,3]])) + acc.addEventAlgo(CompFactory.RoRSeqFilter("Fa3", Input=["CHa2_O"], Output=["Fa3_O"])) + acc.addEventAlgo(CompFactory.RoRSeqFilter("Fb3", Input=["CHb2_O", "CHb1_O"], Output=["Fb3_O"], IOMapping=[[0,1]])) # reach to step 1, one output + acc.addEventAlgo(CompFactory.EventViewCreatorAlgorithm("IMa3", InputMakerInputDecisions=["Fa3_O", "Fa3merged_O"], InputMakerOutputDecisions="IMa3_O")) + acc.addEventAlgo(CompFactory.EventViewCreatorAlgorithm("IMb3", InputMakerInputDecisions=["Fb3_O", "Fb3merged_O"], InputMakerOutputDecisions="IMb3_O")) + acc.addEventAlgo(CompFactory.HLTTest.TestHypoAlg("Ha3", HypoInputDecisions="IMa3_O", HypoOutputDecisions="Ha3_O")) + acc.addEventAlgo(CompFactory.HLTTest.TestHypoAlg("Hb3", HypoInputDecisions="IMb3_O", HypoOutputDecisions="Hb3_O")) + acc.addEventAlgo(CompFactory.ComboHypo("CHmerged3", HypoInputDecisions=["Ha3_O","Hb3_O"], HypoOutputDecisions=["CHOa3merged", "CHOb3merged"])) + acc.addEventAlgo(CompFactory.ComboHypo("CHa3", HypoInputDecisions=["Ha3_O"], HypoOutputDecisions=["CHa3_O"])) + acc.addEventAlgo(CompFactory.ComboHypo("CHb3", HypoInputDecisions=["Hb3_O"], HypoOutputDecisions=["CHb3_O"])) + + acc.printConfig() + acc.wasMerged() + + # test traversing and collection of info (example hypo) + colls = [] + def hypoInOut(outCol, alg): + if isHypoAlg(alg): + colls.append(alg.HypoInputDecisions) + colls.append(alg.HypoOutputDecisions) + + traverse(acc, "CHa2_O", hypoInOut) # start from ComboHypo output + log.info(colls) + assert set(colls) == set(['Ha2_O', 'IMa2_O', 'Ha1_O', 'IMa1_O']), "Traversing could not find hypo outpus & outputs for branch 'a'" + + colls = [] + traverse(acc, "Fb3_O", hypoInOut) # start from ComboHypo output + log.info(colls) + assert set(colls) == set(['Hb1_O', 'IMb1_O', 'Hb2_O', 'IMb2_O']), "Traversing cound not find hypo output & input for branch 'b'" + + colls = [] + traverse(acc, "CHa2altmerged_O", hypoInOut) # start from ComboHypo output + log.info(colls) + assert 'Ha1_O' in colls + assert 'Hb2_0' not in colls, "This is another arm of selection 'b'" + + colls = [] + traverse(acc, "CHb2altmerged_O", hypoInOut) # start from ComboHypo output from where 2nd setep hypo is not reachable + log.info(colls) + assert 'Hb1_O' in colls + assert 'Hb2_0' not in colls, "Due to empty step, this shoudl nto be reachable" + + + colls = [] + def collectFilterInputs( outColl, alg ): + if isFilterAlg(alg): + idx = alg.Output.index(outColl) + colls.append(alg.Input[idx]) + + traverse(acc, "CHa2_O", collectFilterInputs) + assert set(colls) == set(["CHa1_O", "CHa1merged_O", "Fa1_I"]) + colls = [] + traverse(acc, "CHb2merged_O", collectFilterInputs) + assert set(colls) == set(["CHb1_O", "CHb1merged_O", "Fb1_I"]) + log.info("All ok") diff --git a/Trigger/TriggerCommon/TriggerMenuMT/python/HLTMenuConfig/Menu/HLTMenuJSON.py b/Trigger/TriggerCommon/TriggerMenuMT/python/HLTMenuConfig/Menu/HLTMenuJSON.py index 3ec6987198d595e9bef54649e388d4ab08f986d4..6a5e441f9072220368940c15b72da42b0f48ff56 100644 --- a/Trigger/TriggerCommon/TriggerMenuMT/python/HLTMenuConfig/Menu/HLTMenuJSON.py +++ b/Trigger/TriggerCommon/TriggerMenuMT/python/HLTMenuConfig/Menu/HLTMenuJSON.py @@ -44,7 +44,7 @@ def __getChainSequencers(stepsData, chainName): endOfChain = False for sequencer in step: sequencerFilter = getSequenceChildren( sequencer )[0] # Always the first child in the step - if any(chainName in chainNameFromLegName(fChain) for fChain in sequencerFilter.Chains): + if hasattr(sequencerFilter, "Chains") and any(chainName in chainNameFromLegName(fChain) for fChain in sequencerFilter.Chains): if mySequencer is not None: __log.error( "Multiple Filters found (corresponding Sequencers %s, %s) for %s in Step %i!", mySequencer.getName(), sequencer.getName(), chainName, counter) @@ -52,12 +52,12 @@ def __getChainSequencers(stepsData, chainName): if mySequencer is None: endOfChain = True if counter == 1 and 'noalg' not in chainName: - __log.warn("No Filter found for %s in Step 1", chainName) + __log.info("No Filter found for %s in Step 1", chainName) else: if endOfChain is True: __log.error( "Found another Step, (Step %i) for chain %s " "which looked like it had already finished after %i Steps!", - counter, chainName, sequencers.len()) + counter, chainName, len(sequencers)) sequencers.append(mySequencer.getName()) return sequencers diff --git a/Trigger/TriggerCommon/TriggerMenuMT/python/HLTMenuConfig/Menu/LS2_v1_newJO.py b/Trigger/TriggerCommon/TriggerMenuMT/python/HLTMenuConfig/Menu/LS2_v1_newJO.py index 955836c64b6ade964589996b286a5786b1e9e928..b7b9f78ae77f567e8e13c49c2459a94aed9a8fc3 100644 --- a/Trigger/TriggerCommon/TriggerMenuMT/python/HLTMenuConfig/Menu/LS2_v1_newJO.py +++ b/Trigger/TriggerCommon/TriggerMenuMT/python/HLTMenuConfig/Menu/LS2_v1_newJO.py @@ -52,7 +52,6 @@ def setupMenu(flags): flags.Trigger.menu.electron = [ ChainProp(name='HLT_e3_etcut_L1EM3', groups=SingleElectronGroup), ChainProp(name='HLT_2e3_etcut_L12EM3', groups=MultiElectronGroup), -# this chain does not work yet ChainProp(name='HLT_e5_etcut_e3_etcut_L12EM3', groups=MultiElectronGroup), ChainProp(name='HLT_e5_etcut_L1EM3', groups=SingleElectronGroup), ChainProp(name='HLT_e7_etcut_L1EM7', groups=SingleElectronGroup) @@ -60,7 +59,7 @@ def setupMenu(flags): flags.Trigger.menu.photon = [ ChainProp(name='HLT_g10_etcut_L1EM7', groups=SinglePhotonGroup), - ChainProp(name='HLT_g15_etcut_L1EM12', groups=SinglePhotonGroup), + ChainProp(name='HLT_g11_etcut_L1EM7', groups=SinglePhotonGroup), ] flags.Trigger.menu.jet = [ @@ -71,7 +70,7 @@ def setupMenu(flags): flags.Trigger.menu.combined = [ ChainProp(name='HLT_e7_etcut_mu10_L1EM7_MU10', groups=CombinedGroup), - ChainProp(name='HLT_e7_etcut_mu12_L1EM7_MU10', groups=CombinedGroup) + ChainProp(name='HLT_e7_etcut_mu10_msonly_L1EM7_MU10', groups=CombinedGroup) ] if __name__ == "__main__": diff --git a/Trigger/TriggerCommon/TriggerMenuMT/python/HLTMenuConfig/Menu/MenuComponents.py b/Trigger/TriggerCommon/TriggerMenuMT/python/HLTMenuConfig/Menu/MenuComponents.py index 49e3c9685e2667a03ea34f226adce304d761f062..ad668929c63354652d1a70b3ac902763abbe5099 100644 --- a/Trigger/TriggerCommon/TriggerMenuMT/python/HLTMenuConfig/Menu/MenuComponents.py +++ b/Trigger/TriggerCommon/TriggerMenuMT/python/HLTMenuConfig/Menu/MenuComponents.py @@ -306,7 +306,8 @@ def isFilterAlg(alg): def isComboHypoAlg(alg): return ('MultiplicitiesMap' in alg.__class__.__dict__) - +def isHypoAlg(alg): + return isHypoBase(alg) and not isComboHypoAlg(alg) ########################################################## @@ -515,6 +516,7 @@ class CAMenuSequence(MenuSequence): return self._hypo + class Chain(object): """Basic class to define the trigger menu """ __slots__ ='name','steps','nSteps','alignmentGroups','vseeds','L1decisions' diff --git a/Trigger/TriggerCommon/TriggerMenuMT/python/HLTMenuConfig/Menu/TriggerConfigHLT.py b/Trigger/TriggerCommon/TriggerMenuMT/python/HLTMenuConfig/Menu/TriggerConfigHLT.py index f38ec5923883904704c02bea0145d6539de4b8fd..d55b693e617f915e2a4e6caa6097bc645bd2e7da 100644 --- a/Trigger/TriggerCommon/TriggerMenuMT/python/HLTMenuConfig/Menu/TriggerConfigHLT.py +++ b/Trigger/TriggerCommon/TriggerMenuMT/python/HLTMenuConfig/Menu/TriggerConfigHLT.py @@ -44,6 +44,10 @@ class TriggerConfigHLT(object): def dicts(cls): return cls.__allChainDicts + @classmethod + def configs(cls): + return cls.__allChainConfigs + @classmethod def dictsList(cls): diff --git a/Trigger/TriggerCommon/TriggerMenuMT/python/HLTMenuConfig/Muon/generateMuon.py b/Trigger/TriggerCommon/TriggerMenuMT/python/HLTMenuConfig/Muon/generateMuon.py index 1db8754f0591af5659981532677918d5b9ab171f..35f432cec8d601ea752c803afdb3c24b70bcdbcb 100644 --- a/Trigger/TriggerCommon/TriggerMenuMT/python/HLTMenuConfig/Muon/generateMuon.py +++ b/Trigger/TriggerCommon/TriggerMenuMT/python/HLTMenuConfig/Muon/generateMuon.py @@ -1,6 +1,6 @@ # Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration -from TriggerMenuMT.HLTMenuConfig.Menu.MenuComponents import CAMenuSequence, ChainStep, Chain, createStepView +from TriggerMenuMT.HLTMenuConfig.Menu.MenuComponents import CAMenuSequence, ChainStep, Chain, createStepView, EmptyMenuSequence from AthenaConfiguration.ComponentAccumulator import ComponentAccumulator from TrigL2MuonSA.TrigL2MuonSAConfig_newJO import l2MuFastAlgCfg, l2MuFastHypoCfg @@ -56,7 +56,7 @@ def MuCombViewDataVerifier(): result.addEventAlgo(alg) return result -#Not the ideal place to keep the track cnv alg configuration. Temproarily adding it here +#Not the ideal place to keep the track cnv alg configuration. Temproarily adding it here #until a better location can be found def MuonTrackCollectionCnvToolCfg(flags, name = "MuonTrackCollectionCnvTool", **kwargs): TrackCollectionCnvTool = CompFactory.xAODMaker.TrackCollectionCnvTool @@ -121,7 +121,7 @@ def efMuMSHypoCfg(flags, name="UNSPECIFIED", inputMuons="UNSPECIFIED"): def generateChains( flags, chainDict ): chainDict = splitChainDict(chainDict)[0] - + # Step 1 (L2MuonSA) stepName = 'L2MuonSA' stepReco, stepView = createStepView(stepName) @@ -138,50 +138,50 @@ def generateChains( flags, chainDict ): # decoding - # Get RPC BS decoder + # Get RPC BS decoder from MuonConfig.MuonBytestreamDecodeConfig import RpcBytestreamDecodeCfg rpcAcc = RpcBytestreamDecodeCfg( flags, forTrigger=True ) rpcAcc.getEventAlgo("RpcRawDataProvider").RoIs = reco.name+"RoIs" reco.mergeReco( rpcAcc ) # Get RPC BS->RDO convertor - from MuonConfig.MuonRdoDecodeConfig import RpcRDODecodeCfg + from MuonConfig.MuonRdoDecodeConfig import RpcRDODecodeCfg rpcAcc = RpcRDODecodeCfg( flags, forTrigger=True ) rpcAcc.getEventAlgo("RpcRdoToRpcPrepData").RoIs = reco.name+"RoIs" reco.mergeReco( rpcAcc ) - # Get TGC BS decoder + # Get TGC BS decoder from MuonConfig.MuonBytestreamDecodeConfig import TgcBytestreamDecodeCfg tgcAcc = TgcBytestreamDecodeCfg( flags, forTrigger=True ) tgcAcc.getEventAlgo("TgcRawDataProvider").RoIs = reco.name+"RoIs" reco.mergeReco( tgcAcc ) # Get TGC BS->RDO convertor - from MuonConfig.MuonRdoDecodeConfig import TgcRDODecodeCfg + from MuonConfig.MuonRdoDecodeConfig import TgcRDODecodeCfg tgcAcc = TgcRDODecodeCfg( flags, forTrigger=True ) tgcAcc.getEventAlgo("TgcRdoToTgcPrepData").RoIs = reco.name+"RoIs" reco.mergeReco( tgcAcc ) - # Get MDT BS decoder + # Get MDT BS decoder from MuonConfig.MuonBytestreamDecodeConfig import MdtBytestreamDecodeCfg mdtAcc = MdtBytestreamDecodeCfg( flags, forTrigger=True ) mdtAcc.getEventAlgo("MdtRawDataProvider").RoIs = reco.name+"RoIs" reco.mergeReco( mdtAcc ) # Get MDT BS->RDO convertor - from MuonConfig.MuonRdoDecodeConfig import MdtRDODecodeCfg + from MuonConfig.MuonRdoDecodeConfig import MdtRDODecodeCfg mdtAcc = MdtRDODecodeCfg( flags, forTrigger=True ) mdtAcc.getEventAlgo("MdtRdoToMdtPrepData").RoIs = reco.name+"RoIs" reco.mergeReco( mdtAcc ) - # Get CSC BS decoder + # Get CSC BS decoder from MuonConfig.MuonBytestreamDecodeConfig import CscBytestreamDecodeCfg cscAcc = CscBytestreamDecodeCfg( flags, forTrigger=True ) cscAcc.getEventAlgo("CscRawDataProvider").RoIs = reco.name+"RoIs" reco.mergeReco( cscAcc ) # Get CSC BS->RDO convertor - from MuonConfig.MuonRdoDecodeConfig import CscRDODecodeCfg + from MuonConfig.MuonRdoDecodeConfig import CscRDODecodeCfg cscAcc = CscRDODecodeCfg( flags, forTrigger=True ) cscAcc.getEventAlgo("CscRdoToCscPrepData").RoIs = reco.name+"RoIs" reco.mergeReco( cscAcc ) @@ -198,7 +198,7 @@ def generateChains( flags, chainDict ): l2MuFastAlgAcc = ComponentAccumulator() l2MuFastAlgAcc.addEventAlgo(alg) - + reco.mergeReco( l2MuFastAlgAcc ) reco.merge( algAcc ) # l2muFastReco = l2MuFastRecoCfg(flags) @@ -219,7 +219,7 @@ def generateChains( flags, chainDict ): l2muFastStep = ChainStep( name=stepName, Sequences=[l2muFastSequence], chainDicts=[chainDict] ) - if 'msonly' not in chainDict['chainName']: + if 'msonly' not in chainDict['chainName']: #only run in combined muon chains ### Set muon step2 - L2muComb ### stepL2CBName = 'L2MuonCB' @@ -227,7 +227,7 @@ def generateChains( flags, chainDict ): accL2CB = ComponentAccumulator() accL2CB.addSequence(stepL2CBView) - + # Set EventViews for L2MuonCB step recoL2CB = l2MuCombRecoCfg(flags) #external data loading to view @@ -237,7 +237,7 @@ def generateChains( flags, chainDict ): #ID tracking accID = TrigInDetConfig( flags, roisKey=recoL2CB.inputMaker().InViewRoIs, signatureName="Muon" ) recoL2CB.mergeReco(accID) - + accL2CB.merge(recoL2CB, sequenceName = stepL2CBReco.getName()) l2muCombHypo = l2MuCombHypoCfg( flags, @@ -253,9 +253,9 @@ def generateChains( flags, chainDict ): CA = accL2CB ) l2muCombStep = ChainStep( name=stepL2CBName, Sequences=[l2muCombSequence], chainDicts=[chainDict] ) - - if 'msonly' in chainDict['chainName']: + + if 'msonly' in chainDict['chainName'] or True: #only runningn in MS-only chains for now #EF MS only stepEFMSName = 'EFMSMuon' @@ -268,31 +268,31 @@ def generateChains( flags, chainDict ): muonflags.Muon.MuonTrigger=True muonflags.Muon.SAMuonTrigger=True muonflags.lock() - + accMS = ComponentAccumulator() accMS.addSequence(stepEFMSView) from TriggerMenuMT.HLTMenuConfig.Menu.MenuComponents import InViewReco recoMS = InViewReco("EFMuMSReco") recoMS.inputMaker().RequireParentView = True - + #Probably this block will eventually need to move somewhere more central from BeamPipeGeoModel.BeamPipeGMConfig import BeamPipeGeometryCfg - accMS.merge( BeamPipeGeometryCfg(flags) ) - + accMS.merge( BeamPipeGeometryCfg(flags) ) + from PixelGeoModel.PixelGeoModelConfig import PixelGeometryCfg accMS.merge(PixelGeometryCfg(flags)) - + from SCT_GeoModel.SCT_GeoModelConfig import SCT_GeometryCfg accMS.merge(SCT_GeometryCfg(flags)) - + from TRT_GeoModel.TRT_GeoModelConfig import TRT_GeometryCfg accMS.merge(TRT_GeometryCfg(flags)) - + from TrkConfig.AtlasTrackingGeometrySvcConfig import TrackingGeometrySvcCfg accMS.merge(TrackingGeometrySvcCfg(flags)) ################### - + EFMuonViewDataVerifier = EFMuonViewDataVerifierCfg() recoMS.mergeReco(EFMuonViewDataVerifier) @@ -325,7 +325,7 @@ def generateChains( flags, chainDict ): efmuMSSequence = CAMenuSequence( Sequence = recoMS.sequence(), Maker = recoMS.inputMaker(), - Hypo = efmuMSHypo, + Hypo = efmuMSHypo, HypoToolGen = TrigMuonEFMSonlyHypoToolFromDict, CA = accMS ) @@ -334,12 +334,13 @@ def generateChains( flags, chainDict ): l1Thresholds=[] for part in chainDict['chainParts']: l1Thresholds.append(part['L1threshold']) - + log.debug('dictionary is: %s\n', pprint.pformat(chainDict)) - if 'msonly' in chainDict['chainName']: - chain = Chain( name=chainDict['chainName'], L1Thresholds=l1Thresholds, ChainSteps=[ l2muFastStep, efmuMSStep ] ) + if 'msonly' in chainDict['chainName']: + emptyStep = ChainStep(name="EmptyNoL2MuComb", Sequences=[EmptyMenuSequence("EmptyNoL2MuComb")], chainDicts=[chainDict]) + chain = Chain( name=chainDict['chainName'], L1Thresholds=l1Thresholds, ChainSteps=[ l2muFastStep, emptyStep, efmuMSStep ] ) else: - chain = Chain( name=chainDict['chainName'], L1Thresholds=l1Thresholds, ChainSteps=[ l2muFastStep, l2muCombStep ] ) + chain = Chain( name=chainDict['chainName'], L1Thresholds=l1Thresholds, ChainSteps=[ l2muFastStep, l2muCombStep, efmuMSStep ] ) return chain