diff --git a/HLT/Trigger/TrigControl/TrigExamples/TrigExPartialEB/share/MTCalibPeb.py b/HLT/Trigger/TrigControl/TrigExamples/TrigExPartialEB/share/MTCalibPeb.py index dd5a507f2dc25c45d3844601e4fca370bf978f4d..5ce18abe2e3458cd434ffccd8f04a57bbf1e7e3b 100644 --- a/HLT/Trigger/TrigControl/TrigExamples/TrigExPartialEB/share/MTCalibPeb.py +++ b/HLT/Trigger/TrigControl/TrigExamples/TrigExPartialEB/share/MTCalibPeb.py @@ -55,9 +55,25 @@ hypo.HypoOutputDecisions = "MTCalibPebDecisions" hypoTool1 = MTCalibPebHypoTool("HLT_MTCalibPeb1") hypoTool1.RandomAcceptRate = 0.75 +hypoTool1.BurnTimePerCycleMillisec = 100 +hypoTool1.NumBurnCycles = 3 hypoTool2 = MTCalibPebHypoTool("HLT_MTCalibPeb2") hypoTool2.RandomAcceptRate = 0.25 +hypoTool2.BurnTimePerCycleMillisec = 200 +hypoTool2.NumBurnCycles = 10 +hypoTool2.TimeBetweenROBReqMillisec = 100 +hypoTool2.ROBAccessDict = { + "01 :ADD: Preload ": [ 0x42002a, 0x42002b ], # robs for 1st preload + "02 :ADD: Preload ": [ 0x42002e, 0x42002f ], # robs for 2nd preload + "03 :GET: Retrieve ": [ 0x42002e, 0x420060 ], # robs for 1st retrieval + "04 :ADD: Preload ": [ 0x420060 ], # robs for 3rd preload + "05 :ADD: Preload ": [ 0x420064 ], # robs for 4th preload + "06 :ADD: Preload ": [ 0x42002e, 0x420060 ], # robs for 5th preload + "07 :GET: Retrieve ": [ 0x420060 ], # robs for 2nd retrieval + "08 :GET: Retrieve ": [ 0x420064 ], # robs for 3rd retrieval + "09 :COL: Ev.Build ": [ 0x0 ] # event building +} # This is just an example with a few ROBs (LAr in this case) for testing the ROBDataProvider hypo.HypoTools = [hypoTool1, hypoTool2] @@ -77,6 +93,10 @@ stmaker.ChainDecisions = "HLTFinalDecisions" stmaker.ChainToStream = {} stmaker.ChainToStream["HLT_MTCalibPeb1"] = "DataScouting_05_Jets" stmaker.ChainToStream["HLT_MTCalibPeb2"] = "Main" +stmaker.StreamSubDets = {} +stmaker.StreamSubDets["Main"] = [0x41, 0x42] +stmaker.StreamRobs = {} +stmaker.StreamRobs["Main"] = [0x42002e, 0x420060, 0x420064] # Tool adding HLT bits to HLT result bitsmaker = TriggerBitsMakerTool() diff --git a/HLT/Trigger/TrigControl/TrigExamples/TrigExPartialEB/src/MTCalibPebHypoAlg.cxx b/HLT/Trigger/TrigControl/TrigExamples/TrigExPartialEB/src/MTCalibPebHypoAlg.cxx index b752081e438684b3a5989abd57b45d15152b9e40..9d8a72ff20bed2c2c18768c200f7a797f2b52c16 100644 --- a/HLT/Trigger/TrigControl/TrigExamples/TrigExPartialEB/src/MTCalibPebHypoAlg.cxx +++ b/HLT/Trigger/TrigControl/TrigExamples/TrigExPartialEB/src/MTCalibPebHypoAlg.cxx @@ -28,6 +28,7 @@ MTCalibPebHypoAlg::~MTCalibPebHypoAlg() {} // ============================================================================= StatusCode MTCalibPebHypoAlg::initialize() { ATH_MSG_INFO("Initialising " << name()); + ATH_CHECK(m_hypoTools.retrieve()); return StatusCode::SUCCESS; } @@ -36,6 +37,7 @@ StatusCode MTCalibPebHypoAlg::initialize() { // ============================================================================= StatusCode MTCalibPebHypoAlg::finalize() { ATH_MSG_INFO("Finalising " << name()); + ATH_CHECK(m_hypoTools.release()); return StatusCode::SUCCESS; } @@ -50,12 +52,11 @@ StatusCode MTCalibPebHypoAlg::execute_r(const EventContext& eventContext) const auto aux = std::make_unique<DecisionAuxContainer>(); decisions->setStore(aux.get()); - // Prepare input for hypo tools - std::vector<MTCalibPebHypoTool::Input> toolInput; - // Create new decision Decision* newd = newDecisionIn(decisions.get()); // DecisionContainer decisions owns the pointer - toolInput.emplace_back(newd); + + // Prepare input for hypo tools + MTCalibPebHypoTool::Input toolInput(newd, eventContext); // Call the hypo tools for (const auto& tool: m_hypoTools) { diff --git a/HLT/Trigger/TrigControl/TrigExamples/TrigExPartialEB/src/MTCalibPebHypoTool.cxx b/HLT/Trigger/TrigControl/TrigExamples/TrigExPartialEB/src/MTCalibPebHypoTool.cxx index ecb5371e2935cce1bb6e680defa9bb7576be6c78..8f2dee375d82cc47f4222d4bf9117eaa1927c67b 100644 --- a/HLT/Trigger/TrigControl/TrigExamples/TrigExPartialEB/src/MTCalibPebHypoTool.cxx +++ b/HLT/Trigger/TrigControl/TrigExamples/TrigExPartialEB/src/MTCalibPebHypoTool.cxx @@ -2,15 +2,54 @@ Copyright (C) 2002-2018 CERN for the benefit of the ATLAS collaboration */ +// Trigger includes #include "MTCalibPebHypoTool.h" + +// Athena includes +#include "AthenaKernel/Timeout.h" + +// System includes #include <random> +#include <thread> +#include <sstream> // Local implementation-specific helper methods namespace { + /// Returns a reference to static thread-local random number generator + std::mt19937& threadLocalGenerator() { + static thread_local std::random_device rd; // used only to ensure different seeds for mt19937 + static thread_local std::mt19937 generator(rd()); + return generator; + } + /// Basic random real number generation + template<typename T> T randomRealNumber(const T min, const T max) { + std::uniform_real_distribution<T> distribution(min, max); + return distribution(threadLocalGenerator()); + } + /// Basic random integer generation + template<typename T> T randomInteger(const T min, const T max) { + std::uniform_int_distribution<T> distribution(min, max); + return distribution(threadLocalGenerator()); + } + /// Random bool with a given true rate bool randomAccept(const double acceptRate) { - static thread_local std::mt19937 generator; - std::uniform_real_distribution<double> distribution(0.0, 1.0); - return (distribution(generator) < acceptRate); + return (randomRealNumber(0.0, 1.0) < acceptRate); + } + /// ROBFragments vector print helper + std::ostream& operator<<(std::ostream& str, const IROBDataProviderSvc::VROBFRAG& robFragments) { + for (const IROBDataProviderSvc::ROBF* robf : robFragments) { + str << "---> ROB ID = 0x" << std::hex << robf->rob_source_id() << std::dec << std::endl + << " ROD ID = 0x" << std::hex << robf->rod_source_id() << std::dec << std::endl + << " ROD Level-1 ID = " << robf->rod_lvl1_id() << std::endl; + } + return str; + } + /// ROB ID vector print helper + std::string robIdVecToString(const std::vector<uint32_t>& robIdVec) { + std::ostringstream str; + for (const uint32_t robId : robIdVec) + str << "0x" << std::hex << robId << std::dec << " "; + return str.str(); } } @@ -19,6 +58,7 @@ namespace { // ============================================================================= MTCalibPebHypoTool::MTCalibPebHypoTool(const std::string& type, const std::string& name, const IInterface* parent) : AthAlgTool(type,name,parent), + m_robDataProviderSvc("ROBDataProviderSvc", name), m_decisionId (HLT::Identifier::fromToolName(name)) {} // ============================================================================= @@ -31,21 +71,86 @@ MTCalibPebHypoTool::~MTCalibPebHypoTool() {} // ============================================================================= StatusCode MTCalibPebHypoTool::initialize() { ATH_MSG_INFO("Initialising " << name()); + ATH_CHECK(m_robDataProviderSvc.retrieve()); return StatusCode::SUCCESS; } // ============================================================================= -StatusCode MTCalibPebHypoTool::decide(const std::vector<MTCalibPebHypoTool::Input>& inputs) const { +// Implementation of AthAlgTool::finalize +// ============================================================================= +StatusCode MTCalibPebHypoTool::finalize() { + ATH_MSG_INFO("Finalising " << name()); + ATH_CHECK(m_robDataProviderSvc.release()); + return StatusCode::SUCCESS; +} - bool accept = randomAccept(m_acceptRate); - for (auto& in : inputs) { - if (accept) { - ATH_MSG_DEBUG("Decision " << m_decisionId << " is accept"); - TrigCompositeUtils::addDecisionID(m_decisionId, in.decision); +// ============================================================================= +StatusCode MTCalibPebHypoTool::decide(const MTCalibPebHypoTool::Input& input) const { + + // --------------------------------------------------------------------------- + // Burn CPU time + // --------------------------------------------------------------------------- + for (unsigned int iCycle = 0; iCycle < m_numBurnCycles; ++iCycle) { + if (Athena::Timeout::instance(input.eventContext).reached()) { + if (m_failOnTimeout) { + ATH_MSG_ERROR("Timeout reached in CPU time burning cycle # " << iCycle+1 << " and FailOnTimeout is true"); + return StatusCode::FAILURE; + } + ATH_MSG_INFO("Timeout reached in CPU time burning cycle # " << iCycle+1); + break; + } + unsigned int burnTime = m_burnTimeRandomly + ? randomInteger<unsigned int>(0, m_burnTimePerCycleMillisec) + : m_burnTimePerCycleMillisec.value(); + ATH_MSG_VERBOSE("CPU time burning cycle # " << iCycle+1 << ", burn time [ms] = " << burnTime); + std::this_thread::sleep_for(std::chrono::milliseconds(burnTime)); + } + + // --------------------------------------------------------------------------- + // Prefetch or retrieve ROBs + // --------------------------------------------------------------------------- + for (const auto& p : m_robAccessDict) { + // Check for timeout + if (Athena::Timeout::instance(input.eventContext).reached()) { + ATH_MSG_INFO("Timeout reached in ROB retrieval loop"); + break; + } + const std::string& instruction = p.first; + const std::vector<uint32_t>& robs = p.second; + if (instruction.find(":ADD:")!=std::string::npos) { + // Prefetch ROBs + ATH_MSG_DEBUG("Preloading ROBs: " << robIdVecToString(robs)); + m_robDataProviderSvc->addROBData(input.eventContext, robs, name()+"-ADD"); } - else { - ATH_MSG_DEBUG("Decision " << m_decisionId << " is reject"); + if (instruction.find(":GET:")!=std::string::npos) { + // Retrieve ROBs + ATH_MSG_DEBUG("Retrieving ROBs: " << robIdVecToString(robs)); + // VROBFRAG = std::vector<const eformat::ROBFragment<const uint32_t*>* > + IROBDataProviderSvc::VROBFRAG robFragments; + m_robDataProviderSvc->getROBData(input.eventContext, robs, robFragments, name()+"-GET"); + ATH_MSG_DEBUG("Number of ROBs retrieved: " << robFragments.size()); + if (!robFragments.empty()) + ATH_MSG_DEBUG("List of ROBs found: " << std::endl << robFragments); } + if (instruction.find(":COL:")!=std::string::npos) { + // Event building + ATH_MSG_DEBUG("Requesting full event ROBs"); + int nrobs = m_robDataProviderSvc->collectCompleteEventData(input.eventContext, name()+"-COL"); + ATH_MSG_DEBUG("Number of ROBs retrieved: " << nrobs); + } + std::this_thread::sleep_for(std::chrono::milliseconds(m_timeBetweenRobReqMillisec)); + } + + // --------------------------------------------------------------------------- + // Random accept decision + // --------------------------------------------------------------------------- + bool accept = randomAccept(m_acceptRate); + if (accept) { + ATH_MSG_DEBUG("Decision " << m_decisionId << " is accept"); + TrigCompositeUtils::addDecisionID(m_decisionId, input.decision); + } + else { + ATH_MSG_DEBUG("Decision " << m_decisionId << " is reject"); } return StatusCode::SUCCESS; diff --git a/HLT/Trigger/TrigControl/TrigExamples/TrigExPartialEB/src/MTCalibPebHypoTool.h b/HLT/Trigger/TrigControl/TrigExamples/TrigExPartialEB/src/MTCalibPebHypoTool.h index 2fa92ae597464e897bc082e5c19ecff6e3c5a337..a511a354cd568f4143eb8b3904b7fee0c4a32ad8 100644 --- a/HLT/Trigger/TrigControl/TrigExamples/TrigExPartialEB/src/MTCalibPebHypoTool.h +++ b/HLT/Trigger/TrigControl/TrigExamples/TrigExPartialEB/src/MTCalibPebHypoTool.h @@ -6,18 +6,19 @@ #define TRIGEXPARTIALEB_MTCALIBPEBHYPOTOOL_H // Trigger includes +#include "ByteStreamCnvSvcBase/IROBDataProviderSvc.h" #include "DecisionHandling/HLTIdentifier.h" #include "DecisionHandling/TrigCompositeUtils.h" // Athena includes #include "AthenaBaseComps/AthAlgTool.h" +// Gaudi includes +#include "Gaudi/Parsers/Factory.h" // needed to declare less common Property types + // TDAQ includes #include "eformat/StreamTag.h" -// System includes -#include <random> - /** @class MTCalibPebHypoTool * @brief Base class for tools used by MTCalibPebHypoAlg **/ @@ -30,26 +31,55 @@ public: // ------------------------- AthAlgTool methods ------------------------------ virtual StatusCode initialize() override; + virtual StatusCode finalize() override; // ------------------------- Public types ------------------------------------ struct Input { - Input(TrigCompositeUtils::Decision* d) - : decision(d) {} + Input(TrigCompositeUtils::Decision* d, const EventContext& ctx) + : decision(d), eventContext(ctx) {} TrigCompositeUtils::Decision* decision; + const EventContext& eventContext; }; // ------------------------- Specific methods of this class ------------------ /// Decides whether to accept the event - StatusCode decide(const std::vector<Input>& inputs) const; + StatusCode decide(const Input& input) const; private: // ------------------------- Properties -------------------------------------- Gaudi::Property<double> m_acceptRate { - this, - "RandomAcceptRate", - -1, + this, "RandomAcceptRate", -1, "Rate of random accepts, <=0 is never, >=1 is always" }; + Gaudi::Property<unsigned int> m_burnTimePerCycleMillisec { + this, "BurnTimePerCycleMillisec", 0, + "Burn time per cycle in milliseconds" + }; + Gaudi::Property<unsigned int> m_numBurnCycles { + this, "NumBurnCycles", 0, + "Number of time burning cycles" + }; + Gaudi::Property<bool> m_burnTimeRandomly { + this, "BurnTimeRandomly", true, + "If true, burn time per cycle is a random value from uniform distribution between 0 and the given value" + }; + Gaudi::Property<bool> m_failOnTimeout { + this, "FailOnTimeout", true, + "If true, the execution will return StatusCode::FAILURE when Athena timeout is detected" + }; + Gaudi::Property<std::map<std::string,std::vector<uint32_t> > > m_robAccessDict { + this, "ROBAccessDict", {}, + "List of prefetch/retrieve operations with given ROB IDs." + "The string key has to contain :ADD: (prefetch), :GET: (retrieve), or :COL: (full event building)." + "The value is a vector of corresponding ROB IDs." + }; + Gaudi::Property<unsigned int> m_timeBetweenRobReqMillisec { + this, "TimeBetweenROBReqMillisec", 0, + "Delay in milliseconds between subsequent ROB request operations from ROBAccessDict" + }; + + // ------------------------- Service or tool handles ------------------------- + ServiceHandle<IROBDataProviderSvc> m_robDataProviderSvc; // ------------------------- Other private members --------------------------- /// The decision id of the tool instance diff --git a/Trigger/TrigSteer/TrigOutputHandling/src/StreamTagMakerTool.cxx b/Trigger/TrigSteer/TrigOutputHandling/src/StreamTagMakerTool.cxx index 9227980a99949bb92189aab4bd34aa3ed0e80955..65b2f51448895e8a70ccdb6485434b333305b323 100644 --- a/Trigger/TrigSteer/TrigOutputHandling/src/StreamTagMakerTool.cxx +++ b/Trigger/TrigSteer/TrigOutputHandling/src/StreamTagMakerTool.cxx @@ -10,14 +10,28 @@ StreamTagMakerTool::StreamTagMakerTool( const std::string& type, const std::stri StreamTagMakerTool::~StreamTagMakerTool() {} -StatusCode StreamTagMakerTool::initialize() { - // decode mapping +StatusCode StreamTagMakerTool::initialize() { ATH_CHECK( m_finalChainDecisions.initialize() ); + // decode mapping - temporary solution for testing for ( auto& chainAndStream: m_chainToStreamProperty ) { - struct { std::string chain, stream; } conf { chainAndStream.first, chainAndStream.second }; + struct { std::string chain, stream; } conf { chainAndStream.first, chainAndStream.second }; ATH_MSG_DEBUG( "Chain " << conf.chain << " accepts events to stream " << conf.stream ); - m_mapping[ HLT::Identifier( conf.chain ) ] = eformat::helper::StreamTag( conf.stream, "physics", true ); - + // find subdets + std::set<eformat::SubDetector> dets; + const auto itSubDetMap = m_streamSubDets.value().find(conf.stream); + if (itSubDetMap != m_streamSubDets.value().cend()) { + for (const uint32_t detid : itSubDetMap->second) + dets.insert(static_cast<eformat::SubDetector>(detid & 0xFF)); // cast from uint32_t + } + // find robs + std::set<uint32_t> robs; + const auto itRobsMap = m_streamRobs.value().find(conf.stream); + if (itRobsMap != m_streamRobs.value().cend()) { + for (const uint32_t robid : itRobsMap->second) + robs.insert(robid); + } + // create the stream tag + m_mapping[ HLT::Identifier( conf.chain ) ] = eformat::helper::StreamTag( conf.stream, "physics", true, robs, dets ); } return StatusCode::SUCCESS; @@ -29,14 +43,14 @@ StatusCode StreamTagMakerTool::finalize() { StatusCode StreamTagMakerTool::fill( HLT::HLTResultMT& resultToFill ) const { - // obtain chain decisions, + // obtain chain decisions, auto chainsHandle = SG::makeHandle( m_finalChainDecisions ); // for each accepted chain lookup the map of chainID -> ST for ( TrigCompositeUtils::DecisionID chain: TrigCompositeUtils::decisionIDs( chainsHandle->at( 0 )) ) { auto mappingIter = m_mapping.find( chain ); // each chain has to have stream - if( mappingIter == m_mapping.end() ) { + if( mappingIter == m_mapping.end() ) { ATH_MSG_ERROR("Each chain has to have stream associated whereas the " << HLT::Identifier( chain ) << " does not" ); return StatusCode::FAILURE; } @@ -44,5 +58,5 @@ StatusCode StreamTagMakerTool::fill( HLT::HLTResultMT& resultToFill ) const { } ATH_MSG_DEBUG("Number of streams for event " << resultToFill.getStreamTags().size() ); - return StatusCode::SUCCESS; + return StatusCode::SUCCESS; } diff --git a/Trigger/TrigSteer/TrigOutputHandling/src/StreamTagMakerTool.h b/Trigger/TrigSteer/TrigOutputHandling/src/StreamTagMakerTool.h index d3e42b474bb1753f983b6d3719429c587550173c..3debf49a80cdb107ce3a2a05787137b081a7d303 100644 --- a/Trigger/TrigSteer/TrigOutputHandling/src/StreamTagMakerTool.h +++ b/Trigger/TrigSteer/TrigOutputHandling/src/StreamTagMakerTool.h @@ -10,6 +10,7 @@ #include "AthenaBaseComps/AthAlgTool.h" #include "TrigOutputHandling/HLTResultMTMakerTool.h" #include "DecisionHandling/TrigCompositeUtils.h" +#include "Gaudi/Parsers/Factory.h" // needed to declare less common Property types #include "eformat/StreamTag.h" /** @@ -29,7 +30,9 @@ public: private: SG::ReadHandleKey<TrigCompositeUtils::DecisionContainer> m_finalChainDecisions { this, "ChainDecisions", "UNDEFINED", "Container with final chain decisions" }; - Gaudi::Property<std::map<std::string, std::string>> m_chainToStreamProperty { this, "ChainToStream", {}, "Mapping from the chain name to string name, (temporary solution, will be replaced)"}; + Gaudi::Property<std::map<std::string, std::string>> m_chainToStreamProperty { this, "ChainToStream", {}, "Mapping from the chain name to string name (temporary solution, will be replaced)"}; + Gaudi::Property<std::map<std::string, std::vector<uint32_t>>> m_streamSubDets { this, "StreamSubDets", {}, "Mapping from the stream name to subdetector IDs (temporary solution, will be replaced)"}; + Gaudi::Property<std::map<std::string, std::vector<uint32_t>>> m_streamRobs { this, "StreamRobs", {}, "Mapping from the stream name to ROB IDs (temporary solution, will be replaced)"}; typedef std::map< TrigCompositeUtils::DecisionID, eformat::helper::StreamTag> ChainToStreamMap; ChainToStreamMap m_mapping;