Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-12-16 10:13:05

0001 // SPDX-License-Identifier: Apache-2.0
0002 // Copyright (C) 2014-2024 Key4hep-Project
0003 // Adapted from:
0004 // - https://github.com/key4hep/k4FWCore/blob/cc6a28a245592a5b54667925a4b2e3809e6eba54/k4FWCore/components/UniqueIDGenSvc.h
0005 // - https://github.com/key4hep/k4FWCore/blob/cc6a28a245592a5b54667925a4b2e3809e6eba54/k4FWCore/components/UniqueIDGenSvc.cpp
0006 // Local modifications:
0007 // Copyright (C) 2025 Wouter Deconinck
0008 
0009 #pragma once
0010 
0011 #include <edm4hep/EventHeaderCollection.h>
0012 #include <edm4hep/EDM4hepVersion.h>
0013 #include <algorithms/logger.h>
0014 #include <algorithms/service.h>
0015 #include <bitset>
0016 #include <map>
0017 #include <memory>
0018 #include <string>
0019 #include <unordered_map>
0020 
0021 namespace algorithms {
0022 
0023 class UniqueIDGenSvc : public LoggedService<UniqueIDGenSvc> {
0024 public:
0025   using event_num_t = decltype(std::declval<edm4hep::EventHeader>().getEventNumber());
0026   using run_num_t   = decltype(std::declval<edm4hep::EventHeader>().getRunNumber());
0027 
0028   using seed_t = uint64_t;
0029 
0030 private:
0031   static constexpr size_t event_num_digits = std::numeric_limits<event_num_t>::digits;
0032   static constexpr size_t run_num_digits   = std::numeric_limits<run_num_t>::digits;
0033   static constexpr size_t seed_digits      = std::numeric_limits<seed_t>::digits;
0034   static constexpr size_t name_digits      = std::numeric_limits<size_t>::digits;
0035 
0036 public:
0037   virtual void init() {}
0038 
0039   // calculate a unique id from name and the event header
0040   size_t getUniqueID(const edm4hep::EventHeader& evt_header, const std::string_view& name) const {
0041     return getUniqueID(evt_header.getEventNumber(), evt_header.getRunNumber(), name);
0042   }
0043   // calculate a unique id from name and the first element of collection
0044   size_t getUniqueID(const edm4hep::EventHeaderCollection& evt_headers,
0045                      const std::string_view& name) const {
0046     return getUniqueID(evt_headers.at(0), name);
0047   }
0048   // calculate a unique id from name and the event and run numbers
0049   size_t getUniqueID(const event_num_t evt_num, const run_num_t run_num,
0050                      const std::string_view& name) const {
0051     std::bitset<seed_digits> seed_bits           = m_seed.value();
0052     std::bitset<event_num_digits> event_num_bits = evt_num;
0053 #if EDM4HEP_BUILD_VERSION >= EDM4HEP_VERSION(0, 99, 2)
0054     std::bitset<run_num_digits> run_num_bits = run_num;
0055 #else
0056     // FIXME until edm4hep 0.99.1, the run number is signed and defaults to -1
0057     std::bitset<run_num_digits> run_num_bits = static_cast<std::uint32_t>(run_num);
0058 #endif
0059     std::bitset<name_digits> name_bits = std::hash<std::string_view>{}(name);
0060 
0061     std::bitset<seed_digits + event_num_digits + run_num_digits + name_digits> combined_bits;
0062 
0063     for (size_t i = 0; i < name_digits; i++) {
0064       combined_bits[i] = name_bits[i];
0065     }
0066     for (size_t i = 0; i < run_num_digits; i++) {
0067       combined_bits[i + name_digits] = run_num_bits[i];
0068     }
0069     for (size_t i = 0; i < event_num_digits; i++) {
0070       combined_bits[i + run_num_digits + name_digits] = event_num_bits[i];
0071     }
0072     for (size_t i = 0; i < seed_digits; i++) {
0073       combined_bits[i + event_num_digits + run_num_digits + name_digits] = seed_bits[i];
0074     }
0075 
0076     auto hash =
0077         std::hash<std::bitset<seed_digits + event_num_digits + run_num_digits + name_digits>>{}(
0078             combined_bits);
0079 
0080     if (m_checkDuplicates) {
0081       auto [it, inserted] = [=, this, &name]() {
0082         std::lock_guard<std::mutex> lock(m_mutex);
0083         return m_uniqueIDs.insert({hash, {evt_num, run_num, std::string{name}}});
0084       }();
0085       if (!inserted) {
0086         const auto& [id_evt, id_run, id_name] = it->second;
0087         // TODO log to error
0088         throw std::runtime_error(fmt::format(
0089             "Duplicate ID for event number, run number and algorithm name: {}, {}, \"{}\". "
0090             "ID already assigned to: {}, {}, \"{}\"",
0091             evt_num, run_num, name, id_evt, id_run, id_name));
0092       }
0093     }
0094 
0095     return hash;
0096   };
0097 
0098 protected:
0099   ALGORITHMS_DEFINE_LOGGED_SERVICE(UniqueIDGenSvc)
0100 
0101 private:
0102   Property<size_t> m_seed{this, "seed", 1, "Random seed for the internal random engine"};
0103   Property<bool> m_checkDuplicates{
0104       this, "checkDuplicates", false,
0105       "Caches obtained ID and throws an exception if a duplicate would be returned"};
0106 
0107   mutable std::unordered_map<size_t, std::tuple<event_num_t, run_num_t, std::string>, std::identity>
0108       m_uniqueIDs;
0109   mutable std::mutex m_mutex;
0110 };
0111 
0112 } // namespace algorithms