ATLAS Offline Software
Loading...
Searching...
No Matches
PileUpMTAlg.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// PileUpMT includes
6#include "PileUpMTAlg.h"
7
8#include <CxxUtils/XXH.h>
9#include <unistd.h>
10
11#include <boost/core/demangle.hpp>
12#include <range/v3/all.hpp>
13
14#include <chrono>
15#include <format>
16
18#include "EventInfo/EventInfo.h"
19#include <tuple>
20
22#include "CLHEP/Random/RandPoisson.h"
23#include "CLHEP/Random/RandomEngine.h"
31
33namespace rv = ranges::views;
34// namespace ra = ranges::actions;
35
36inline std::string CLIDToString(const CLID& clid) {
37 return boost::core::demangle(CLIDRegistry::CLIDToTypeinfo(clid)->name());
38}
39
40PileUpMTAlg::PileUpMTAlg(const std::string& name, ISvcLocator* pSvcLocator)
41 : AthAlgorithm(name, pSvcLocator) {}
42
44
46 std::unique_ptr<const xAOD::EventInfo>& ei_,
47 std::unique_ptr<xAOD::EventAuxInfo>& ei_aux_,
48 bool pileup) const {
49 std::string key = pileup ? "EventInfo" : "HSEventInfo";
50 auto newEi = std::make_unique<xAOD::EventInfo>();
51 auto eiAux = std::make_unique<xAOD::EventAuxInfo>();
52 newEi->setStore(eiAux.get());
53 SG::ReadHandle<xAOD::EventInfo> ei_h(key, sg.name());
54 const xAOD::EventInfo* ei = ei_h.get();
55 if (ei != nullptr) {
56 *newEi = *ei;
57 } else {
58 ATH_MSG_ERROR("Couldn't find xAOD::EventInfo. " << sg.name());
59 ATH_MSG_ERROR(sg.dump());
60 return StatusCode::FAILURE;
61 }
62 // Use attribute list if EventInfo doesn't have event numbers set
63 if (newEi->eventNumber() == 0) {
64 const auto* attr_list_p = sg.tryConstRetrieve<AthenaAttributeList>("Input");
65 if (attr_list_p != nullptr) {
66 if (attr_list_p->size() <= 6) {
67 ATH_MSG_WARNING("Read Input attribute list but size <= 6");
68 } else {
69 const AthenaAttributeList& attr_list = *attr_list_p;
70 const auto runNum = attr_list["RunNumber"].data<unsigned>();
71 const auto evtNum = attr_list["EventNumber"].data<unsigned long long>();
72 const auto lbNum = attr_list["LumiBlockN"].data<unsigned>();
73 newEi->setRunNumber(runNum);
74 newEi->setLumiBlock(lbNum);
75 newEi->setEventNumber(evtNum);
76 }
77 } else {
79 "Could not read Input attribute list and EventInfo has no event "
80 "number");
81 }
82 }
83 newEi->setEvtStore(&sg);
84 ei_ = std::move(newEi);
85 ei_aux_ = std::move(eiAux);
86 return StatusCode::SUCCESS;
87}
88
90 const std::vector<std::uint32_t>& bcid,
94 int bc, const EventContext& ctx, unsigned long subevt_id,
95 std::vector<std::uint64_t>& trace) {
96 // Keep the code to add and process a subevent in one place
97 const unsigned int bc_idx = bc - m_earliestDeltaBC;
98 StoreGateSvc* sg = mbSvc->getMinbias(ctx, subevt_id);
99 std::unique_ptr<const xAOD::EventInfo> ei;
100 std::unique_ptr<xAOD::EventAuxInfo> eiAux;
101 ATH_CHECK(get_ei(*sg, ei, eiAux, true));
102 xAOD::EventInfo mb_to_modify(*ei);
103 if (m_writeTrace) {
104 trace.push_back(mb_to_modify.eventNumber());
105 }
106 mb_to_modify.setBCID(bcid[bc_idx]);
107 try {
108 addSubEvent(overlaidEvt.ptr(), &mb_to_modify, bc * m_BCSpacing, puType,
109 puCont.ptr(), m_evtInfoContKey.key(), sg);
110 } catch (const std::exception& e) {
111 ATH_MSG_ERROR("Caught exception adding subevent: " << e.what());
112 return StatusCode::FAILURE;
113 }
114 return StatusCode::SUCCESS;
115}
116
118 using namespace std::chrono;
119 ATH_MSG_DEBUG("Initializing " << name() << "...");
120 if (m_writeTrace) {
121 std::string filename = std::format("pileup_trace_skipping-{}_{:%Y-%m-%dT%H%M}.txt",
122 m_skippedHSEvents.value(),
123 system_clock::now());
124 if (!m_pileupTrace.init(filename)) {
125 ATH_MSG_ERROR("Cannot append to file " << filename);
126 return StatusCode::FAILURE;
127 }
128 }
129 ATH_CHECK(m_skipEventIdxSvc.retrieve());
130 ATH_CHECK(m_rngSvc.retrieve());
131 if (m_fracLowPt != 0) {
132 ATH_CHECK(m_lowptMBSvc.retrieve());
133 }
134 if (m_fracHighPt != 0) {
135 ATH_CHECK(m_highptMBSvc.retrieve());
136 }
137 if (m_numCavern != 0) {
138 ATH_CHECK(m_cavernMBSvc.retrieve());
139 }
140 if (m_numBeamGas != 0) {
141 ATH_CHECK(m_beamgasMBSvc.retrieve());
142 }
143 if (m_numBeamHalo != 0) {
144 ATH_CHECK(m_beamhaloMBSvc.retrieve());
145 }
146 ATH_CHECK(m_beamInt.retrieve());
147 ATH_CHECK(m_beamLumi.retrieve());
148 ATH_CHECK(m_puTools.retrieve());
149
150 m_evtInfoContKey = "PileUpEventInfo";
151 ATH_CHECK(m_evtInfoKey.initialize());
152 ATH_CHECK(m_evtInfoContKey.initialize());
153 ATH_CHECK(m_beamSpotKey.initialize());
154
155 // Trace skipped events
156 if (m_writeTrace) {
158 ISkipEventIdxSvc::EvtIter end) -> StatusCode {
159 std::string trace_buf{};
160 auto trace = std::back_inserter(trace_buf);
161 for (; it != end; ++it) {
162 std::format_to(trace, "SKIPPING Run: {} LB: {} EVT: {} HS ID: {}\n",
163 it->runNum, it->lbNum, it->evtNum, it->evtIdx);
164 }
165 m_pileupTrace.print(trace_buf);
166 return StatusCode::SUCCESS;
167 };
168 if (!m_skiptrace_written) {
169 ATH_CHECK(m_skipEventIdxSvc->registerCallback(handler));
170 m_skiptrace_written = true;
171 }
172 }
173 return StatusCode::SUCCESS;
174}
175
177 ATH_MSG_DEBUG("Finalizing " << name() << "...");
178 //
179 // Things that happen once at the end of the event loop go here
180 //
181
182 return StatusCode::SUCCESS;
183}
184
186 using PUType = xAOD::EventInfo::PileUpType;
187 std::string trace_buf{}; // Hold trace of events.
188 auto trace = std::back_inserter(trace_buf);
189 ATH_MSG_DEBUG("Executing " << name() << "...");
190 const EventContext& ctx = Gaudi::Hive::currentContext();
191 const auto& evtID = ctx.eventID();
192
193 ATH_CHECK(evtStore().retrieve());
194 setFilterPassed(false); // optional: start with algorithm not passed
195
196 // Code based on PileUpEventLoopMgr and PileUpToolsAlg (trying to extract the
197 // core merging code) Read hard scatter
198 std::unique_ptr<const xAOD::EventInfo> hsEvt = nullptr;
199 std::unique_ptr<xAOD::EventAuxInfo> hsEvtAux = nullptr;
200 ATH_CHECK(get_ei(*evtStore(), hsEvt, hsEvtAux));
201
202 // Setup overlaid event
204 ATH_CHECK(overlaidEvt.record(std::make_unique<xAOD::EventInfo>(),
205 std::make_unique<xAOD::EventAuxInfo>()));
206 *overlaidEvt = *hsEvt; // copy in hard scatter
207 overlaidEvt->setEvtStore(evtStore().get());
208 overlaidEvt->clearSubEvents();
209
210 // This was the problem. Need to fix overlaidEvt using context run and lb
211 // number
212 overlaidEvt->setRunNumber(evtID.run_number());
213 overlaidEvt->setLumiBlock(evtID.lumi_block());
214 overlaidEvt->setEventNumber(evtID.event_number());
215 overlaidEvt->setBCID(evtID.bunch_crossing_id());
216 overlaidEvt->setTimeStamp(evtID.time_stamp());
217 overlaidEvt->setTimeStampNSOffset(evtID.time_stamp_ns_offset());
218 // Set beam spot info
220 if (!beamSpotHandle.isValid()) {
221 ATH_MSG_ERROR("Beam spot information not valid");
222 return StatusCode::FAILURE;
223 }
224
225 overlaidEvt->setBeamPos(beamSpotHandle->beamPos()[Amg::x],
226 beamSpotHandle->beamPos()[Amg::y],
227 beamSpotHandle->beamPos()[Amg::z]);
228 overlaidEvt->setBeamPosSigma(beamSpotHandle->beamSigma(0),
229 beamSpotHandle->beamSigma(1),
230 beamSpotHandle->beamSigma(2));
231 overlaidEvt->setBeamPosSigmaXY(beamSpotHandle->beamSigmaXY());
232 overlaidEvt->setBeamTiltXZ(beamSpotHandle->beamTilt(0));
233 overlaidEvt->setBeamTiltYZ(beamSpotHandle->beamTilt(1));
234 overlaidEvt->setBeamStatus(beamSpotHandle->beamStatus());
235
236 // Pileup container
238 ATH_CHECK(puCont.record(std::make_unique<xAOD::EventInfoContainer>(),
239 std::make_unique<xAOD::EventInfoAuxContainer>()));
240
241 // Get crossing number
242 m_beamInt->selectT0(evtID.run_number(), evtID.event_number());
243 overlaidEvt->setBCID(m_beamInt->getCurrentT0BunchCrossing());
244
245 // Set simulation bit
246 overlaidEvt->setEventTypeBitmask(hsEvt->eventTypeBitmask() |
248
249 // Set properties
250 bool sf_updated = false;
251 float lumi_sf = m_beamLumi->scaleFactor(evtID.run_number(),
252 evtID.lumi_block(), sf_updated);
253 float cur_avg_mu = lumi_sf * m_avgMu;
254 overlaidEvt->setAverageInteractionsPerCrossing(cur_avg_mu);
255 overlaidEvt->setActualInteractionsPerCrossing(m_beamInt->normFactor(0) *
256 cur_avg_mu);
257
258 // Trace
259 if (m_writeTrace) {
260 std::format_to(trace,
261 "Idx: {} Run: {} LB: {} EVT: {} "
262 "HS ID: {}\n",
263 ctx.evt(), evtID.run_number(), evtID.lumi_block(),
264 evtID.event_number(), m_lowptMBSvc->get_hs_id(ctx));
265 auto bunch_pattern =
266 rv::closed_iota(m_earliestDeltaBC.value(), m_latestDeltaBC.value()) |
267 rv::transform(
268 [this](int bc) { return int(m_beamInt->normFactor(bc)); }) |
269#if RANGE_V3_VERSION >= 1200
270 rv::chunk_by(std::equal_to{}) |
271#else
272 rv::group_by(std::equal_to{}) |
273#endif
274 rv::transform([](const auto& rng) {
275 return std::format("{}{}", rng.size(), rng[0] == 0 ? 'E' : 'F');
276 }) |
277 ranges::to<std::vector<std::string>>;
278 // Manual join using std::ostringstream as std::format does not support ranges
279 std::string joined_pattern;
280 for (size_t i = 0; i < bunch_pattern.size(); ++i) {
281 joined_pattern += bunch_pattern[i];
282 if (i + 1 < bunch_pattern.size()) {
283 joined_pattern += " ";
284 }
285 }
286
287 std::format_to(trace,
288 "mu = {}, central BCID = {}, bunch pattern = [{}]\n",
289 cur_avg_mu, m_beamInt->getCurrentT0BunchCrossing(),
290 joined_pattern);
291 }
292 // Copy subevents
293 if (!hsEvt->subEvents().empty()) {
294 for (const SubEvent& se : hsEvt->subEvents()) {
295 addSubEvent(overlaidEvt.ptr(), se, puCont.ptr(), m_evtInfoContKey.key(),
296 evtStore().get());
297 }
298 } else {
299 // if no subevents, add original event
300 addSubEvent(overlaidEvt.ptr(), hsEvt.get(), 0, xAOD::EventInfo::Signal,
301 puCont.ptr(), m_evtInfoContKey.key(), evtStore().get());
302 }
303
304 // Initialize MinbiasSvcs
305 if (m_fracLowPt != 0) {
306 ATH_CHECK(m_lowptMBSvc->beginHardScatter(ctx));
307 }
308 if (m_fracHighPt != 0) {
309 ATH_CHECK(m_highptMBSvc->beginHardScatter(ctx));
310 }
311 if (m_numCavern != 0) {
312 ATH_CHECK(m_cavernMBSvc->beginHardScatter(ctx));
313 }
314 if (m_numBeamHalo != 0) {
315 ATH_CHECK(m_beamhaloMBSvc->beginHardScatter(ctx));
316 }
317 if (m_numBeamGas != 0) {
318 ATH_CHECK(m_beamgasMBSvc->beginHardScatter(ctx));
319 }
320
321 std::uint32_t central_bcid = overlaidEvt->bcid();
322 std::vector<std::uint32_t> bcid{};
323 bcid.reserve(m_latestDeltaBC - m_earliestDeltaBC + 1);
324
325 for (int bc = m_earliestDeltaBC; bc <= m_latestDeltaBC; ++bc) {
326 bcid.push_back(get_BCID(bc, central_bcid));
327 }
328
329 // Setup tools
330 for (auto&& tool : m_puTools) {
331 // Reset filter -- Don't know if this is necessary
332 tool->resetFilter();
333 }
334
335 // Now add the events
336 std::uint64_t low_pt_count = 0;
337 std::uint64_t high_pt_count = 0;
338 std::uint64_t cavern_count = 0;
339 std::uint64_t beam_halo_count = 0;
340 std::uint64_t beam_gas_count = 0;
341 auto now = std::chrono::high_resolution_clock::now();
342 for (int bc = m_earliestDeltaBC; bc <= m_latestDeltaBC; ++bc) {
343 if (m_beamInt->normFactor(bc) == 0.) {
344 // skip empty bunch crossings
345 continue;
346 }
347 std::vector<std::uint64_t> subevts_vec{};
348 if (m_fracLowPt != 0) {
349 if (m_writeTrace) {
350 std::format_to(trace, "\tBC {:03} : LOW PT {} ", bc,
351 m_lowptMBSvc->getNumForBunch(ctx, bc));
352 }
353 for (std::size_t i = 0; i < m_lowptMBSvc->getNumForBunch(ctx, bc); ++i) {
354 ATH_CHECK(add_subevt(bcid, overlaidEvt, puCont, m_lowptMBSvc,
355 PUType::MinimumBias, bc, ctx, low_pt_count,
356 subevts_vec));
357 ++low_pt_count;
358 }
359 }
360 if (m_fracHighPt != 0) {
361 if (m_writeTrace) {
362 std::format_to(trace, "HIGH PT {} | ",
363 m_highptMBSvc->getNumForBunch(ctx, bc));
364 }
365 for (std::size_t i = 0; i < m_highptMBSvc->getNumForBunch(ctx, bc); ++i) {
366 ATH_CHECK(add_subevt(bcid, overlaidEvt, puCont, m_highptMBSvc,
367 PUType::HighPtMinimumBias, bc, ctx, high_pt_count,
368 subevts_vec));
369 ++high_pt_count;
370 }
371 }
372 if (m_numCavern != 0) {
373 if (m_writeTrace) {
374 std::format_to(trace, "CAVERN {} | ",
375 m_cavernMBSvc->getNumForBunch(ctx, bc));
376 }
377 for (std::size_t i = 0; i < m_cavernMBSvc->getNumForBunch(ctx, bc); ++i) {
378 ATH_CHECK(add_subevt(bcid, overlaidEvt, puCont, m_cavernMBSvc,
379 PUType::Cavern, bc, ctx, cavern_count,
380 subevts_vec));
381 ++cavern_count;
382 }
383 }
384 if (m_numBeamHalo != 0) {
385 if (m_writeTrace) {
386 std::format_to(trace, "BEAM HALO {} | ",
387 m_beamhaloMBSvc->getNumForBunch(ctx, bc));
388 }
389 for (std::size_t i = 0; i < m_beamhaloMBSvc->getNumForBunch(ctx, bc);
390 ++i) {
391 ATH_CHECK(add_subevt(bcid, overlaidEvt, puCont, m_beamhaloMBSvc,
392 PUType::HaloGas, bc, ctx, beam_halo_count,
393 subevts_vec));
394 ++beam_halo_count;
395 }
396 }
397 if (m_numBeamGas != 0) {
398 if (m_writeTrace) {
399 std::format_to(trace, "BEAM GAS {} | ",
400 m_beamgasMBSvc->getNumForBunch(ctx, bc));
401 }
402 for (std::size_t i = 0; i < m_beamgasMBSvc->getNumForBunch(ctx, bc);
403 ++i) {
404 ATH_CHECK(add_subevt(bcid, overlaidEvt, puCont, m_beamgasMBSvc,
405 PUType::HaloGas, bc, ctx, beam_gas_count,
406 subevts_vec));
407 ++beam_gas_count;
408 }
409 }
410 if (m_writeTrace) {
411 std::format_to(trace, "TOTAL {} | HASH {:08X}\n", subevts_vec.size(),
412 xxh3::hash64(subevts_vec));
413 }
414 }
415 if (m_writeTrace) {
416 std::format_to(trace, "\n");
417 m_pileupTrace.print(trace_buf);
418 }
419
420 for (auto&& tool : m_puTools) {
421 try {
422 ATH_CHECK(tool->processAllSubEvents(ctx));
423 } catch (const std::exception& e) {
424 ATH_MSG_ERROR("Caught exception running " << tool.name() << ": "
425 << e.what());
426 return StatusCode::FAILURE;
427 }
428 // Propagate filter result
429 if (!tool->filterPassed()) {
430 setFilterPassed(false);
431 }
432 }
433 ATH_MSG_DEBUG(std::format("***** Took {:%OMm %OSs} to process all subevents",
434 std::chrono::high_resolution_clock::now() - now));
435 //
436 // Save hash (direct copy from PileUpEventLoopMgr)
437 PileUpHashHelper pileUpHashHelper;
438 pileUpHashHelper.addToHashSource(overlaidEvt.cptr());
439 ATH_MSG_VERBOSE("Pile-up hash source:" << pileUpHashHelper.hashSource());
440
441 // Calculate and set hash
442 uuid_t pileUpHash;
443 pileUpHashHelper.calculateHash(pileUpHash);
444 overlaidEvt->setPileUpMixtureID(
446 ATH_MSG_DEBUG("PileUpMixtureID = " << overlaidEvt->pileUpMixtureID());
447
448 setFilterPassed(true); // if got here, assume that means algorithm passed
449 if (m_fracLowPt != 0) {
450 ATH_CHECK(m_lowptMBSvc->endHardScatter(ctx));
451 }
452 if (m_fracHighPt != 0) {
453 ATH_CHECK(m_highptMBSvc->endHardScatter(ctx));
454 }
455 if (m_numCavern != 0) {
456 ATH_CHECK(m_cavernMBSvc->endHardScatter(ctx));
457 }
458 if (m_numBeamHalo != 0) {
459 ATH_CHECK(m_beamhaloMBSvc->endHardScatter(ctx));
460 }
461 if (m_numBeamGas != 0) {
462 ATH_CHECK(m_beamgasMBSvc->endHardScatter(ctx));
463 }
464 return StatusCode::SUCCESS;
465}
#define ATH_CHECK
Evaluate an expression and check for errors.
#define ATH_MSG_ERROR(x)
#define ATH_MSG_VERBOSE(x)
#define ATH_MSG_WARNING(x)
#define ATH_MSG_DEBUG(x)
uint32_t CLID
The Class ID type.
An AttributeList represents a logical row of attributes in a metadata table.
A helper class to compute a hash of pile-up events.
xAOD::EventInfo::SubEvent SubEvent
std::string CLIDToString(const CLID &clid)
xAOD::EventInfo * addSubEvent(xAOD::EventInfo *targetEv, const xAOD::EventInfo::SubEvent &subev, xAOD::EventInfoContainer *eiContainer, const std::string &eiContKey, StoreGateSvc *subev_store=nullptr)
C++ native wrapper for the C xxhash API.
AthAlgorithm(const std::string &name, ISvcLocator *pSvcLocator)
Constructor with parameters:
An AttributeList represents a logical row of attributes in a metadata table.
static const std::type_info * CLIDToTypeinfo(CLID clid)
Translate between CLID and type_info.
std::vector< EvtId >::const_iterator EvtIter
std::string hashSource() const
Get the current hash base.
void addToHashSource(const std::string &string)
Add a plain string to the stream.
void calculateHash(uuid_t &hash) const
Calculate the hash.
static xAOD::EventInfo::PileUpMixtureID uuidToPileUpMixtureId(const uuid_t &hash)
Convert uuid_t to xAOD::EventInfo::PileUpMixtureID.
Gaudi::Property< int > m_earliestDeltaBC
virtual StatusCode initialize() override
uncomment and implement methods as required
Gaudi::Property< int > m_latestDeltaBC
Gaudi::Property< bool > m_writeTrace
Gaudi::Property< float > m_avgMu
PileUpMTAlg(const std::string &name, ISvcLocator *pSvcLocator)
Gaudi::Property< float > m_numCavern
unsigned int get_BCID(int bc, unsigned int central_BCID) const
virtual StatusCode execute() override
virtual ~PileUpMTAlg()
Gaudi::Property< float > m_fracLowPt
ServiceHandle< IBeamLuminosity > m_beamLumi
ToolHandleArray< IPileUpTool > m_puTools
SG::WriteHandleKey< xAOD::EventInfoContainer > m_evtInfoContKey
ServiceHandle< IAthRNGSvc > m_rngSvc
SG::ReadCondHandleKey< InDet::BeamSpotData > m_beamSpotKey
StatusCode get_ei(StoreGateSvc &sg, std::unique_ptr< const xAOD::EventInfo > &ei, std::unique_ptr< xAOD::EventAuxInfo > &eiAux, bool pileup=false) const
ServiceHandle< IMinbiasSvc > m_beamgasMBSvc
ServiceHandle< IMinbiasSvc > m_highptMBSvc
Definition PileUpMTAlg.h:99
ServiceHandle< IMinbiasSvc > m_cavernMBSvc
Gaudi::Property< float > m_fracHighPt
SG::WriteHandleKey< xAOD::EventInfo > m_evtInfoKey
ServiceHandle< IBeamIntensity > m_beamInt
ServiceHandle< ISkipEventIdxSvc > m_skipEventIdxSvc
Gaudi::Property< int > m_skippedHSEvents
ServiceHandle< IMinbiasSvc > m_lowptMBSvc
Other useful methods provided by base class are: evtStore() : ServiceHandle to main event data storeg...
Definition PileUpMTAlg.h:97
Gaudi::Property< float > m_numBeamGas
Gaudi::Property< float > m_numBeamHalo
virtual StatusCode finalize() override
StatusCode add_subevt(const std::vector< std::uint32_t > &bcid, SG::WriteHandle< xAOD::EventInfo > &overlaidEvt, SG::WriteHandle< xAOD::EventInfoContainer > &puCont, ServiceHandle< IMinbiasSvc > &mbSvc, xAOD::EventInfo::PileUpType puType, int bc, const EventContext &ctx, unsigned long subevt_id, std::vector< std::uint64_t > &trace)
ServiceHandle< IMinbiasSvc > m_beamhaloMBSvc
Gaudi::Property< int > m_BCSpacing
const_pointer_type get() const
Dereference the pointer, but don't cache anything.
const_pointer_type cptr() const
Dereference the pointer.
StatusCode record(std::unique_ptr< T > data)
Record a const object to the store.
pointer_type ptr()
Dereference the pointer.
The Athena Transient Store API.
std::string dump() const
dump objects in store.
const T * tryConstRetrieve() const
Class describing the properties of one pileup sub-event.
void setBCID(uint32_t value)
Set the bunch crossing ID of the event.
PileUpType
Enumerator describing the types of pileup events.
@ Signal
The signal event.
@ IS_SIMULATION
true: simulation, false: data
uint64_t eventNumber() const
The current event's event number.
T * get(TKey *tobj)
get a TObject* from a TKey* (why can't a TObject be a TKey?)
Definition hcg.cxx:130
EventInfo_v1 EventInfo
Definition of the latest event info version.
std::uint64_t hash64(const void *data, std::size_t size)
Passthrough to XXH3_64bits.
Definition XXH.cxx:9
void handler(int sig)
signal handler
Definition rmain.cxx:99