ATLAS Offline Software
Loading...
Searching...
No Matches
MTCalibPebHypoTool.cxx
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2025 CERN for the benefit of the ATLAS collaboration
3*/
4
5// Trigger includes
7#include "TrigPartialEventBuilding/PEBInfoWriterToolBase.h" // Defines the PEBInfo keys expected by StreamTagMakerTool
8
9// Athena includes
12
13// System includes
14#include <random>
15#include <thread>
16#include <sstream>
17
18// Local implementation-specific helper methods
19namespace {
20 using rng_t = std::mt19937_64;
21 using seed_t = rng_t::result_type;
23 seed_t eventSeed(const EventIDBase& eventID, const std::string& name) {
24 uint64_t evtNum = eventID.event_number();
25 uint64_t runNum = eventID.run_number();
26 uint64_t nameHash = std::hash<std::string>{}(name);
27 uint64_t seed = evtNum ^ (runNum << 10) ^ nameHash;
28 return static_cast<seed_t>(seed);
29 }
31 rng_t& threadLocalGenerator() {
32 static thread_local std::random_device rd; // used only to ensure different seeds for mt19937
33 static thread_local rng_t generator(rd());
34 return generator;
35 }
37 template<typename T> T randomRealNumber(const T min, const T max) {
38 std::uniform_real_distribution<T> distribution(min, max);
39 return distribution(threadLocalGenerator());
40 }
42 template<typename T> T randomInteger(const T min, const T max) {
43 std::uniform_int_distribution<T> distribution(min, max);
44 return distribution(threadLocalGenerator());
45 }
47 bool randomAccept(const double acceptRate) {
48 return (randomRealNumber(0.0, 1.0) < acceptRate);
49 }
52 std::string format(const IROBDataProviderSvc::VROBFRAG& robFragments) {
53 std::ostringstream ss;
54 for (const IROBDataProviderSvc::ROBF* robf : robFragments) {
55 ss << "---> ROB ID = 0x" << std::hex << robf->rob_source_id() << std::dec << std::endl
56 << " ROD ID = 0x" << std::hex << robf->rod_source_id() << std::dec << std::endl
57 << " ROD Level-1 ID = " << robf->rod_lvl1_id() << std::endl;
58 }
59 return ss.str();
60 }
62 template<typename Container>
63 const std::string idsToString(const Container& ids) {
64 std::ostringstream str;
65 for (const uint32_t id : ids)
66 str << "0x" << std::hex << id << std::dec << " ";
67 return str.str();
68 }
70 StatusCode appendPEBInfo(TrigCompositeUtils::Decision* decision,
71 std::set<uint32_t> robIDsToAdd,
72 std::set<uint32_t> subDetIDsToAdd) {
73 // Merge with previous ROBs
74 std::vector<uint32_t> previousRobs;
75 if (decision->getDetail(PEBInfoWriterToolBase::robListKey(), previousRobs)) {
76 robIDsToAdd.insert(previousRobs.begin(), previousRobs.end());
77 }
78
79 // Merge with previous SubDets
80 std::vector<uint32_t> previousSubDets;
81 if (decision->getDetail(PEBInfoWriterToolBase::subDetListKey(), previousSubDets)) {
82 subDetIDsToAdd.insert(previousSubDets.begin(), previousSubDets.end());
83 }
84
85 // Attach the PEB Info to the decision
86 std::vector<uint32_t> robVec(robIDsToAdd.begin(), robIDsToAdd.end());
87 if (not decision->setDetail(PEBInfoWriterToolBase::robListKey(), robVec)) {
88 return StatusCode::FAILURE;
89 }
90 std::vector<uint32_t> subDetVec(subDetIDsToAdd.begin(), subDetIDsToAdd.end());
91 if (not decision->setDetail(PEBInfoWriterToolBase::subDetListKey(), subDetVec)) {
92 return StatusCode::FAILURE;
93 }
94 return StatusCode::SUCCESS;
95 }
97 void fillRandomData(xAOD::TrigCompositeContainer& data, unsigned int maxElements) {
98 unsigned int nObjects = randomInteger<unsigned int>(0, maxElements);
99 for (unsigned int iObj=0; iObj<nObjects; ++iObj) {
101 data.push_back(object);
102 object->setName(std::string("object_")+std::to_string(iObj));
103 unsigned int nAuxDataVec = randomInteger<unsigned int>(0, maxElements);
104 for (unsigned int iAuxDataVec=0; iAuxDataVec<nAuxDataVec; ++iAuxDataVec) {
105 xAOD::TrigComposite::Accessor<std::vector<float>> floatVec(std::string("floatVec_")+std::to_string(iAuxDataVec));
106 unsigned int nValues = randomInteger<unsigned int>(0, maxElements);
107 std::vector<float> values;
108 for (unsigned int iValue=0; iValue<nValues; ++iValue) values.push_back( randomRealNumber<float>(0,1) );
109 floatVec(*object) = std::move(values);
110 }
111 }
112 }
113}
114
115// =============================================================================
116// Standard constructor
117// =============================================================================
118MTCalibPebHypoTool::MTCalibPebHypoTool(const std::string& type, const std::string& name, const IInterface* parent)
119: AthAlgTool(type,name,parent),
120 m_decisionId (HLT::Identifier::fromToolName(name)) {}
121
122// =============================================================================
123// Standard destructor
124// =============================================================================
126
127// =============================================================================
128// Implementation of AthAlgTool::initialize
129// =============================================================================
131 ATH_MSG_INFO("Initialising " << name());
133 if (m_doCrunch) ATH_CHECK(m_cpuCrunchSvc.retrieve());
134
135 // Copy keys from map<string,uint> to WriteHandleKeyArray
136 for (const auto& [name, number] : m_createRandomData) {
137 m_randomDataWHK.push_back(name);
138 }
139 ATH_CHECK(m_randomDataWHK.initialize());
140
141 // Parse and print the ROB request dictionary
142 for (const auto& [instrString,robVec] : m_robAccessDictProp.value()) {
143 m_robAccessDict.emplace_back(ROBRequestInstruction(instrString),robVec);
144 if (m_robAccessDict.back().first.type==ROBRequestInstruction::Type::INVALID) {
145 ATH_MSG_ERROR("Invalid instruction " << instrString);
146 return StatusCode::FAILURE;
147 }
148 }
149 if (msgLvl(MSG::DEBUG)) {
150 if (!m_robAccessDict.empty()) {
151 ATH_MSG_DEBUG(name() << " will execute the following ROB request instructions:");
152 for (const auto& [instr,robVec] : m_robAccessDict) {
153 ATH_MSG_DEBUG("---> Instruction : " << instr.toString());
154 ATH_MSG_DEBUG(" ROB list : " << idsToString(robVec));
155 }
156 }
157 ATH_MSG_DEBUG(name() << " PEBROBList = [" << idsToString(m_pebRobList) << "]");
158 ATH_MSG_DEBUG(name() << " PEBSubDetList = [" << idsToString(m_pebSubDetList) << "]");
159 }
160
161 return StatusCode::SUCCESS;
162}
163
164// =============================================================================
165// Implementation of AthAlgTool::finalize
166// =============================================================================
168 ATH_MSG_INFO("Finalising " << name());
170 ATH_CHECK(m_randomDataWHK.initialize());
171 return StatusCode::SUCCESS;
172}
173
174// =============================================================================
176 // Re-seed the static thread-local RNG
177 if (not m_useRandomSeed.value()) {
178 const seed_t seed = eventSeed(input.eventContext.eventID(), name());
179 ATH_MSG_DEBUG("Using seed " << seed << " for event " << input.eventContext.eventID());
180 threadLocalGenerator().seed(seed);
181 }
182
183 // ---------------------------------------------------------------------------
184 // Burn CPU time
185 // ---------------------------------------------------------------------------
186 for (unsigned int iCycle = 0; iCycle < m_numBurnCycles; ++iCycle) {
187 if (Athena::Timeout::instance(input.eventContext).reached()) {
188 ATH_MSG_ERROR("Timeout reached in CPU time burning cycle # " << iCycle+1);
190 }
191 unsigned int burnTime = m_burnTimeRandomly
192 ? randomInteger<unsigned int>(0, m_burnTimePerCycleMillisec)
194 ATH_MSG_VERBOSE("CPU time burning cycle # " << iCycle+1 << ", burn time [ms] = " << burnTime);
195 if (m_doCrunch) m_cpuCrunchSvc->crunch_for(std::chrono::milliseconds(burnTime));
196 else std::this_thread::sleep_for(std::chrono::milliseconds(burnTime));
197 }
198
199 // ---------------------------------------------------------------------------
200 // Prefetch or retrieve ROBs
201 // ---------------------------------------------------------------------------
202 for (const auto& [instr,robVec] : m_robAccessDict) {
203 // Check for timeout
204 if (Athena::Timeout::instance(input.eventContext).reached()) {
205 ATH_MSG_ERROR("Timeout reached in ROB retrieval loop");
207 }
208
209 // Select a random sample of ROBs from the list, if needed
210 ATH_MSG_DEBUG("Processing instruction " << instr.toString());
211 std::vector<uint32_t> robs;
212 if (instr.isRandom && instr.nRandom < robVec.size()) {
213 std::sample(robVec.begin(),robVec.end(),
214 std::back_inserter(robs),
215 instr.nRandom,
216 threadLocalGenerator());
217 }
218 else robs = robVec;
219
220 // Execute the ROB requests
221 using ReqType = ROBRequestInstruction::Type;
222 if (instr.type == ReqType::ADD || instr.type == ReqType::ADDGET) {
223 // Prefetch ROBs
224 ATH_MSG_DEBUG("Preloading ROBs: " << idsToString(robs));
225 m_robDataProviderSvc->addROBData(input.eventContext, robs, name()+"-ADD");
226 }
227 if (instr.type == ReqType::GET || instr.type == ReqType::ADDGET) {
228 // Retrieve ROBs
229 ATH_MSG_DEBUG("Retrieving ROBs: " << idsToString(robs));
230 // VROBFRAG is a typedef for std::vector<const eformat::ROBFragment<const uint32_t*>*>
232 m_robDataProviderSvc->getROBData(input.eventContext, robs, robFragments, name()+"-GET");
233 ATH_MSG_DEBUG("Number of ROBs retrieved: " << robFragments.size());
234 if (!robFragments.empty()) {
235 ATH_MSG_DEBUG("List of ROBs found: " << std::endl << format(robFragments));
236 }
237 if (m_checkDataConsistency.value()) {
238 for (const IROBDataProviderSvc::ROBF* rob : robFragments) {
239 try {
240 if (!rob->check_rob() || !rob->check_rod()) {
241 ATH_MSG_ERROR("Data consistency check failed");
242 }
243 }
244 catch (const std::exception& ex) {
245 ATH_MSG_ERROR("Data consistency check failed: " << ex.what());
246 }
247 ATH_MSG_DEBUG("Data consistency check passed for ROB 0x" << std::hex << rob->rob_source_id() << std::dec);
248 }
249 }
250 }
251 if (instr.type == ReqType::COL) {
252 // Event building
253 ATH_MSG_DEBUG("Requesting full event ROBs");
254 int nrobs = m_robDataProviderSvc->collectCompleteEventData(input.eventContext, name()+"-COL");
255 ATH_MSG_DEBUG("Number of ROBs retrieved: " << nrobs);
256 }
257 if (instr.type == ReqType::INVALID) {
258 ATH_MSG_ERROR("Invalid ROB request instruction " << instr.toString());
259 return StatusCode::FAILURE;
260 }
261
262 // Sleep between ROB requests
263 std::this_thread::sleep_for(std::chrono::milliseconds(m_timeBetweenRobReqMillisec));
264 }
265
266 // ---------------------------------------------------------------------------
267 // Produce random data
268 // ---------------------------------------------------------------------------
269 {
270 using DataCont = xAOD::TrigCompositeContainer;
271 using AuxCont = xAOD::TrigCompositeAuxContainer;
272 for (const SG::WriteHandleKey<DataCont>& handleKey : m_randomDataWHK) {
273 // Create data and aux container
274 std::unique_ptr<DataCont> data = std::make_unique<DataCont>();
275 std::unique_ptr<AuxCont> aux = std::make_unique<AuxCont>();
276 data->setStore(aux.get());
277 // Record the container in event store
278 SG::WriteHandle<DataCont> handle(handleKey,input.eventContext);
279 ATH_CHECK( handle.record(std::move(data),std::move(aux)) );
280 ATH_MSG_DEBUG("Recorded TrigCompositeContainer " << handleKey.key() << " in event store");
281 // Fill the container with random data
282 unsigned int maxElements = m_createRandomData.value().at(handleKey.key());
283 fillRandomData(*handle,maxElements);
284 }
285 }
286
287 // ---------------------------------------------------------------------------
288 // Random accept decision with PEB information
289 // ---------------------------------------------------------------------------
290 bool accept = randomAccept(m_acceptRate);
291 if(!accept) {
292 ATH_MSG_DEBUG("Decision " << m_decisionId << " is reject");
293 return StatusCode::SUCCESS;
294 }
295
296 ATH_MSG_DEBUG("Decision " << m_decisionId << " is accept");
298
299 if (m_pebRobList.empty() && m_pebSubDetList.empty()) {
300 ATH_MSG_VERBOSE("Not configured to write any PEBInfo, nothing will be attached to the decision");
301 }
302 else {
303 ATH_MSG_DEBUG("Attaching ROBs=[" << idsToString(m_pebRobList) << "] and SubDets=["
304 << idsToString(m_pebSubDetList) << "] to the decision object");
305 ATH_CHECK(appendPEBInfo(input.decision,m_pebRobList,m_pebSubDetList));
306 }
307
308 return StatusCode::SUCCESS;
309}
310
311// =============================================================================
313 // Work around a bug in clang 9.
314#if __clang_major__ == 9
315 std::string str (strv.begin(), strv.end());
316#else
317 const std::string_view& str = strv;
318#endif
319 if (str.find(":ADD:")!=std::string_view::npos) type = ROBRequestInstruction::ADD;
320 else if (str.find(":GET:")!=std::string_view::npos) type = ROBRequestInstruction::GET;
321 else if (str.find(":ADDGET:")!=std::string_view::npos) type = ROBRequestInstruction::ADDGET;
322 else if (str.find(":COL:")!=std::string_view::npos) type = ROBRequestInstruction::COL;
323 if (size_t pos=str.find(":RND"); pos!=std::string_view::npos) {
324 size_t firstDigit=pos+4;
325 size_t lastDigit=str.find_first_of(":",firstDigit);
326 size_t num = std::stoul(str.substr(firstDigit,lastDigit).data());
327 isRandom = true;
328 nRandom = num;
329 }
330}
331
332// =============================================================================
334 std::string s;
335 s += "type=";
336 if (type==INVALID) s+="INVALID";
337 else if (type==ADD) s+="ADD";
338 else if (type==GET) s+="GET";
339 else if (type==ADDGET) s+="ADDGET";
340 else if (type==COL) s+="COL";
341 s += ", isRandom=";
342 s += isRandom ? "true" : "false";
343 s += ", nRandom=";
344 s += std::to_string(nRandom);
345 return s;
346}
#define ATH_CHECK
Evaluate an expression and check for errors.
#define ATH_MSG_ERROR(x)
#define ATH_MSG_INFO(x)
#define ATH_MSG_VERBOSE(x)
#define ATH_MSG_DEBUG(x)
char data[hepevt_bytes_allocation_ATLAS]
Definition HepEvt.cxx:11
static Double_t ss
Timeout singleton.
#define min(a, b)
Definition cfImp.cxx:40
#define max(a, b)
Definition cfImp.cxx:41
AthAlgTool(const std::string &type, const std::string &name, const IInterface *parent)
Constructor with parameters:
bool msgLvl(const MSG::Level lvl) const
static Timeout & instance()
Get reference to Timeout singleton.
Definition Timeout.h:64
OFFLINE_FRAGMENTS_NAMESPACE::ROBFragment ROBF
std::vector< const ROBF * > VROBFRAG
storage of the time histories of all the cells
virtual ~MTCalibPebHypoTool()
Standard destructor.
virtual StatusCode finalize() override
Gaudi::Property< double > m_acceptRate
ServiceHandle< ICPUCrunchSvc > m_cpuCrunchSvc
Gaudi::Property< unsigned int > m_timeBetweenRobReqMillisec
Gaudi::Property< std::map< std::string, std::vector< uint32_t > > > m_robAccessDictProp
Gaudi::Property< unsigned int > m_numBurnCycles
std::vector< std::pair< ROBRequestInstruction, std::vector< uint32_t > > > m_robAccessDict
Ordered map of ROB request instructions filled from ROBAccessDict property at initialisation.
Gaudi::Property< std::set< uint32_t > > m_pebSubDetList
Gaudi::Property< std::set< uint32_t > > m_pebRobList
Gaudi::Property< bool > m_useRandomSeed
StatusCode decide(const Input &input) const
Decides whether to accept the event.
SG::WriteHandleKeyArray< xAOD::TrigCompositeContainer > m_randomDataWHK
WriteHandleKey array for collections specified in the CreateRandomData property.
virtual StatusCode initialize() override
ServiceHandle< IROBDataProviderSvc > m_robDataProviderSvc
MTCalibPebHypoTool(const std::string &type, const std::string &name, const IInterface *parent)
Standard constructor.
HLT::Identifier m_decisionId
The decision id of the tool instance.
Gaudi::Property< unsigned int > m_burnTimePerCycleMillisec
Gaudi::Property< bool > m_burnTimeRandomly
Gaudi::Property< bool > m_doCrunch
Gaudi::Property< bool > m_checkDataConsistency
Gaudi::Property< std::map< std::string, unsigned int > > m_createRandomData
static std::string robListKey()
Returns the key used to record/retrieve the ROB list.
static std::string subDetListKey()
Returns the key used to record/retrieve the SubDet list.
SG::Accessor< T, ALLOC > Accessor
Definition AuxElement.h:572
Property holding a SG store/key/clid from which a WriteHandle is made.
StatusCode record(std::unique_ptr< T > data)
Record a const object to the store.
bool setDetail(const std::string &name, const TYPE &value)
Set an TYPE detail on the object.
bool getDetail(const std::string &name, TYPE &value) const
Get an TYPE detail from the object.
@ TIMEOUT
Timeout during event processing.
It used to be useful piece of code for replacing actual SG with other store of similar functionality ...
void addDecisionID(DecisionID id, Decision *d)
Appends the decision (given as ID) to the decision object.
generator
Configure Herwig7 These are the commands corresponding to what would go into the regular Herwig infil...
TrigCompositeContainer_v1 TrigCompositeContainer
Declare the latest version of the container.
TrigComposite_v1 TrigComposite
Declare the latest version of the class.
TrigCompositeAuxContainer_v2 TrigCompositeAuxContainer
Declare the latest version of the container.
ROB request instruction description.
const std::string toString() const
String form for debug print-outs.
bool isRandom
Flag switching requests of a random sub-sample of the ROB list.
ROBRequestInstruction(std::string_view str)
Constructor from string key in the ROBAccessDict property.
enum MTCalibPebHypoTool::ROBRequestInstruction::Type type
std::string number(const double &d, const std::string &s)
Definition utils.cxx:186