diff --git a/HLT/Trigger/TrigControl/TrigExamples/TrigExPartialEB/share/MTCalibPeb.py b/HLT/Trigger/TrigControl/TrigExamples/TrigExPartialEB/share/MTCalibPeb.py index 39a5cc62d8f2acb1fa1e562f301c6f26eb16947b..cffdd5f7c3f608a1e46c88a227f3ee3e01eb0687 100644 --- a/HLT/Trigger/TrigControl/TrigExamples/TrigExPartialEB/share/MTCalibPeb.py +++ b/HLT/Trigger/TrigControl/TrigExamples/TrigExPartialEB/share/MTCalibPeb.py @@ -78,16 +78,17 @@ hypoTool2.RandomAcceptRate = 0.25 hypoTool2.BurnTimePerCycleMillisec = 20 hypoTool2.NumBurnCycles = 10 hypoTool2.TimeBetweenROBReqMillisec = 50 +exampleROBList = [0x420024, 0x420025, 0x420026, 0x420027, 0x420034, 0x420035, 0x420036, 0x420037, + 0x42005c, 0x42005d, 0x42005e, 0x42005f, 0x42006c, 0x42006d, 0x42006e, 0x42006f] # ROS-LAR-EMBC-02 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 + "01 :ADD: Preload ": [ 0x420024, 0x420025 ], # robs for 1st preload + "02 :ADD: Preload ": [ 0x420026, 0x420027 ], # robs for 2nd preload + "03 :GET: Retrieve ": [ 0x420025, 0x420026 ], # robs for 1st retrieval (prefetched) + "04 :GET: Retrieve ": [ 0x420034 ], # robs for 2nd retrieval (not prefetched) + "05 :ADD: Preload ": exampleROBList, # robs for 3rd preload (the full list) + "05 :GET:RND5: Retrieve ": exampleROBList, # robs for 3rd retrieval (5 random from the list) + "06 :GET:RND10: Retrieve ": exampleROBList, # robs for 4th retrieval (10 random from the list) + "07 :COL: Ev.Build ": [] # event building } # This is just an example with a few ROBs (LAr in this case) for testing the ROBDataProvider # Chain 3 - medium rate, produces random data, writes PEB info for data scouting @@ -115,7 +116,7 @@ from TrigOutputHandling.TrigOutputHandlingConfig import TriggerEDMSerialiserTool serialiser = TriggerEDMSerialiserToolCfg("Serialiser") serialiser.addCollectionListToMainResult([ "xAOD::TrigCompositeContainer_v1#"+hypo.HypoOutputDecisions, - "xAOD::TrigCompositeAuxContainer_v2#"+hypo.HypoOutputDecisions+"Aux.decisions", + "xAOD::TrigCompositeAuxContainer_v2#"+hypo.HypoOutputDecisions+"Aux.", ]) # Data scouting example resultList = [serialiser.fullResultID(), 1] diff --git a/HLT/Trigger/TrigControl/TrigExamples/TrigExPartialEB/src/MTCalibPebHypoTool.cxx b/HLT/Trigger/TrigControl/TrigExamples/TrigExPartialEB/src/MTCalibPebHypoTool.cxx index 3786018d926326782991b2141c119921b7e676f6..f814488953e9a009ff886dbb8976732014d6f005 100644 --- a/HLT/Trigger/TrigControl/TrigExamples/TrigExPartialEB/src/MTCalibPebHypoTool.cxx +++ b/HLT/Trigger/TrigControl/TrigExamples/TrigExPartialEB/src/MTCalibPebHypoTool.cxx @@ -49,7 +49,7 @@ namespace { } /// Print helper for a container with ROB/SubDet IDs template<typename Container> - std::string idsToString(const Container& ids) { + const std::string idsToString(const Container& ids) { std::ostringstream str; for (const uint32_t id : ids) str << "0x" << std::hex << id << std::dec << " "; @@ -128,6 +128,22 @@ StatusCode MTCalibPebHypoTool::initialize() { [](const auto& p){return p.first;}); ATH_CHECK(m_randomDataWHK.initialize()); + // Parse and print the ROB request dictionary + for (const auto& [instrString,robVec] : m_robAccessDictProp.value()) { + m_robAccessDict.emplace_back(ROBRequestInstruction(instrString),robVec); + if (m_robAccessDict.back().first.type==ROBRequestInstruction::Type::INVALID) { + ATH_MSG_ERROR("Invalid instruction " << instrString); + return StatusCode::FAILURE; + } + } + if (msgLvl(MSG::DEBUG) && !m_robAccessDict.empty()) { + ATH_MSG_DEBUG(name() << " will execute the following ROB request instructions:"); + for (const auto& [instr,robVec] : m_robAccessDict) { + ATH_MSG_DEBUG("---> Instruction : " << instr.toString()); + ATH_MSG_DEBUG(" ROB list : " << idsToString(robVec)); + } + } + return StatusCode::SUCCESS; } @@ -162,35 +178,57 @@ StatusCode MTCalibPebHypoTool::decide(const MTCalibPebHypoTool::Input& input) co // --------------------------------------------------------------------------- // Prefetch or retrieve ROBs // --------------------------------------------------------------------------- - for (const auto& p : m_robAccessDict) { + for (const auto& [instr,robVec] : m_robAccessDict) { // Check for timeout if (Athena::Timeout::instance(input.eventContext).reached()) { ATH_MSG_ERROR("Timeout reached in ROB retrieval loop"); return Athena::Status::TIMEOUT; } - 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: " << idsToString(robs)); - m_robDataProviderSvc->addROBData(input.eventContext, robs, name()+"-ADD"); - } - if (instruction.find(":GET:")!=std::string::npos) { - // Retrieve ROBs - ATH_MSG_DEBUG("Retrieving ROBs: " << idsToString(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); + + // Select a random sample of ROBs from the list, if needed + ATH_MSG_DEBUG("Processing instruction " << instr.toString()); + std::vector<uint32_t> robs; + if (instr.isRandom && instr.nRandom < robVec.size()) { + std::sample(robVec.begin(),robVec.end(), + std::back_inserter(robs), + instr.nRandom, + threadLocalGenerator()); } - 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); + else robs = robVec; + + // Execute the ROB requests + switch (instr.type) { + case ROBRequestInstruction::Type::ADD: { + // Prefetch ROBs + ATH_MSG_DEBUG("Preloading ROBs: " << idsToString(robs)); + m_robDataProviderSvc->addROBData(input.eventContext, robs, name()+"-ADD"); + break; + } + case ROBRequestInstruction::Type::GET: { + // Retrieve ROBs + ATH_MSG_DEBUG("Retrieving ROBs: " << idsToString(robs)); + // VROBFRAG is a typedef for 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); + break; + } + case ROBRequestInstruction::Type::COL: { + // 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); + break; + } + default: { + ATH_MSG_ERROR("Invalid ROB request instruction " << instr.toString()); + return StatusCode::FAILURE; + } } + + // Sleep between ROB requests std::this_thread::sleep_for(std::chrono::milliseconds(m_timeBetweenRobReqMillisec)); } @@ -238,3 +276,32 @@ StatusCode MTCalibPebHypoTool::decide(const MTCalibPebHypoTool::Input& input) co return StatusCode::SUCCESS; } + +// ============================================================================= +MTCalibPebHypoTool::ROBRequestInstruction::ROBRequestInstruction(std::string_view str) { + if (str.find(":ADD:")!=std::string_view::npos) type = ROBRequestInstruction::ADD; + else if (str.find(":GET:")!=std::string_view::npos) type = ROBRequestInstruction::GET; + else if (str.find(":COL:")!=std::string_view::npos) type = ROBRequestInstruction::COL; + if (size_t pos=str.find(":RND"); pos!=std::string_view::npos) { + size_t firstDigit=pos+4; + size_t lastDigit=str.find_first_of(":",firstDigit); + size_t num = std::stoul(str.substr(firstDigit,lastDigit).data()); + isRandom = true; + nRandom = num; + } +} + +// ============================================================================= +const std::string MTCalibPebHypoTool::ROBRequestInstruction::toString() const { + std::string s; + s += "type="; + if (type==INVALID) s+="INVALID"; + else if (type==ADD) s+="ADD"; + else if (type==GET) s+="GET"; + else if (type==COL) s+="COL"; + s += ", isRandom="; + s += isRandom ? "true" : "false"; + s += ", nRandom="; + s += std::to_string(nRandom); + return s; +} \ No newline at end of file diff --git a/HLT/Trigger/TrigControl/TrigExamples/TrigExPartialEB/src/MTCalibPebHypoTool.h b/HLT/Trigger/TrigControl/TrigExamples/TrigExPartialEB/src/MTCalibPebHypoTool.h index 667d44cd73772847948bcf4ff2fdeecd43e1f186..8640bbdb5ec1e69871d451c53aef1d13ece13cd2 100644 --- a/HLT/Trigger/TrigControl/TrigExamples/TrigExPartialEB/src/MTCalibPebHypoTool.h +++ b/HLT/Trigger/TrigControl/TrigExamples/TrigExPartialEB/src/MTCalibPebHypoTool.h @@ -43,6 +43,21 @@ public: StatusCode decide(const Input& input) const; private: + // ------------------------- Types ------------------------------------------- + /// ROB request instruction description + struct ROBRequestInstruction { + /// Constructor from string key in the ROBAccessDict property + ROBRequestInstruction(std::string_view str); + /// String form for debug print-outs + const std::string toString() const; + /// Type of instruction + enum Type {INVALID, ADD, GET, COL} type = INVALID; + /// Flag switching requests of a random sub-sample of the ROB list + bool isRandom = false; + /// Size of random request + size_t nRandom = 0; + }; + // ------------------------- Properties -------------------------------------- Gaudi::Property<double> m_acceptRate { this, "RandomAcceptRate", -1, @@ -60,11 +75,14 @@ private: this, "BurnTimeRandomly", true, "If true, burn time per cycle is a random value from uniform distribution between 0 and the given value" }; - Gaudi::Property<std::map<std::string,std::vector<uint32_t> > > m_robAccessDict { + Gaudi::Property<std::map<std::string,std::vector<uint32_t> > > m_robAccessDictProp { 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." + "Dictionary of prefetch/retrieve operations with given ROB IDs. The value is a vector of ROB IDs. " + "The string key has to contain :ADD: (prefetch), :GET: (retrieve), or :COL: (full event building). :ADD: and :GET: " + "may be also appended with :RNDX: where X is an integer. In this case, random X ROBs will be prefetched/retrieved " + "from the provided list, e.g. :GET:RND10: retrieves 10 random ROBs from the list. Otherwise the full list is used. " + "Note std::map is sorted by std::less<std::string>, so starting the key with a number may be needed to enforce " + "ordering, e.g. '01 :ADD:RND10:'." }; Gaudi::Property<unsigned int> m_timeBetweenRobReqMillisec { this, "TimeBetweenROBReqMillisec", 0, @@ -93,6 +111,8 @@ private: HLT::Identifier m_decisionId; /// WriteHandleKey array for collections specified in the CreateRandomData property SG::WriteHandleKeyArray<xAOD::TrigCompositeContainer> m_randomDataWHK; + /// Ordered map of ROB request instructions filled from ROBAccessDict property at initialisation + std::vector<std::pair<ROBRequestInstruction,std::vector<uint32_t>>> m_robAccessDict; }; #endif // TRIGEXPARTIALEB_MTCALIBPEBHYPOTOOL_H