EICrecon
JANA based reconstruction for the EPIC detector
Loading...
Searching...
No Matches
UniqueIDGenSvc.h
Go to the documentation of this file.
1// SPDX-License-Identifier: Apache-2.0
2// Copyright (C) 2014-2024 Key4hep-Project
3// Adapted from:
4// - https://github.com/key4hep/k4FWCore/blob/cc6a28a245592a5b54667925a4b2e3809e6eba54/k4FWCore/components/UniqueIDGenSvc.h
5// - https://github.com/key4hep/k4FWCore/blob/cc6a28a245592a5b54667925a4b2e3809e6eba54/k4FWCore/components/UniqueIDGenSvc.cpp
6// Local modifications:
7// Copyright (C) 2025 Wouter Deconinck
8
9#pragma once
10
11#include <edm4hep/EventHeaderCollection.h>
12#include <edm4hep/EDM4hepVersion.h>
13#include <algorithms/logger.h>
14#include <algorithms/service.h>
15#include <bitset>
16#include <map>
17#include <memory>
18#include <string>
19#include <unordered_map>
20
21namespace algorithms {
22
23class UniqueIDGenSvc : public LoggedService<UniqueIDGenSvc> {
24public:
25 using event_num_t = decltype(std::declval<edm4hep::EventHeader>().getEventNumber());
26 using run_num_t = decltype(std::declval<edm4hep::EventHeader>().getRunNumber());
27
28 using seed_t = uint64_t;
29
30private:
31 static constexpr size_t event_num_digits = std::numeric_limits<event_num_t>::digits;
32 static constexpr size_t run_num_digits = std::numeric_limits<run_num_t>::digits;
33 static constexpr size_t seed_digits = std::numeric_limits<seed_t>::digits;
34 static constexpr size_t name_digits = std::numeric_limits<size_t>::digits;
35
36public:
37 virtual void init() {}
38
39 // calculate a unique id from name and the event header
40 size_t getUniqueID(const edm4hep::EventHeader& evt_header, const std::string_view& name) const {
41 return getUniqueID(evt_header.getEventNumber(), evt_header.getRunNumber(), name);
42 }
43 // calculate a unique id from name and the first element of collection
44 size_t getUniqueID(const edm4hep::EventHeaderCollection& evt_headers,
45 const std::string_view& name) const {
46 return getUniqueID(evt_headers.at(0), name);
47 }
48 // calculate a unique id from name and the event and run numbers
49 size_t getUniqueID(const event_num_t evt_num, const run_num_t run_num,
50 const std::string_view& name) const {
51 std::bitset<seed_digits> seed_bits = m_seed.value();
52 std::bitset<event_num_digits> event_num_bits = evt_num;
53#if EDM4HEP_BUILD_VERSION >= EDM4HEP_VERSION(0, 99, 2)
54 std::bitset<run_num_digits> run_num_bits = run_num;
55#else
56 // FIXME until edm4hep 0.99.1, the run number is signed and defaults to -1
57 std::bitset<run_num_digits> run_num_bits = static_cast<std::uint32_t>(run_num);
58#endif
59 std::bitset<name_digits> name_bits = std::hash<std::string_view>{}(name);
60
61 std::bitset<seed_digits + event_num_digits + run_num_digits + name_digits> combined_bits;
62
63 for (size_t i = 0; i < name_digits; i++) {
64 combined_bits[i] = name_bits[i];
65 }
66 for (size_t i = 0; i < run_num_digits; i++) {
67 combined_bits[i + name_digits] = run_num_bits[i];
68 }
69 for (size_t i = 0; i < event_num_digits; i++) {
70 combined_bits[i + run_num_digits + name_digits] = event_num_bits[i];
71 }
72 for (size_t i = 0; i < seed_digits; i++) {
73 combined_bits[i + event_num_digits + run_num_digits + name_digits] = seed_bits[i];
74 }
75
76 auto hash =
77 std::hash<std::bitset<seed_digits + event_num_digits + run_num_digits + name_digits>>{}(
78 combined_bits);
79
80 if (m_checkDuplicates) {
81 auto [it, inserted] = [=, this, &name]() {
82 std::lock_guard<std::mutex> lock(m_mutex);
83 return m_uniqueIDs.insert({hash, {evt_num, run_num, std::string{name}}});
84 }();
85 if (!inserted) {
86 const auto& [id_evt, id_run, id_name] = it->second;
87 // TODO log to error
88 throw std::runtime_error(fmt::format(
89 "Duplicate ID for event number, run number and algorithm name: {}, {}, \"{}\". "
90 "ID already assigned to: {}, {}, \"{}\"",
91 evt_num, run_num, name, id_evt, id_run, id_name));
92 }
93 }
94
95 return hash;
96 };
97
98protected:
99 ALGORITHMS_DEFINE_LOGGED_SERVICE(UniqueIDGenSvc)
100
101private:
102 Property<size_t> m_seed{this, "seed", 1, "Random seed for the internal random engine"};
103 Property<bool> m_checkDuplicates{
104 this, "checkDuplicates", false,
105 "Caches obtained ID and throws an exception if a duplicate would be returned"};
106
107 mutable std::unordered_map<size_t, std::tuple<event_num_t, run_num_t, std::string>, std::identity>
108 m_uniqueIDs;
109 mutable std::mutex m_mutex;
110};
111
112} // namespace algorithms
Definition UniqueIDGenSvc.h:23
uint64_t seed_t
Definition UniqueIDGenSvc.h:28
size_t getUniqueID(const event_num_t evt_num, const run_num_t run_num, const std::string_view &name) const
Definition UniqueIDGenSvc.h:49
size_t getUniqueID(const edm4hep::EventHeaderCollection &evt_headers, const std::string_view &name) const
Definition UniqueIDGenSvc.h:44
decltype(std::declval< edm4hep::EventHeader >().getRunNumber()) run_num_t
Definition UniqueIDGenSvc.h:26
virtual void init()
Definition UniqueIDGenSvc.h:37
decltype(std::declval< edm4hep::EventHeader >().getEventNumber()) event_num_t
Definition UniqueIDGenSvc.h:25
size_t getUniqueID(const edm4hep::EventHeader &evt_header, const std::string_view &name) const
Definition UniqueIDGenSvc.h:40
Definition ActsSvc.h:11