Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-07-30 08:39:03

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 <algorithms/logger.h>
0013 #include <algorithms/service.h>
0014 #include <bitset>
0015 #include <map>
0016 #include <memory>
0017 #include <string>
0018 #include <unordered_map>
0019 
0020 namespace algorithms {
0021 
0022 class UniqueIDGenSvc : public LoggedService<UniqueIDGenSvc> {
0023 public:
0024   using event_num_t = decltype(std::declval<edm4hep::EventHeader>().getEventNumber());
0025   using run_num_t   = decltype(std::declval<edm4hep::EventHeader>().getRunNumber());
0026 
0027   using seed_t = uint64_t;
0028 
0029 private:
0030   static constexpr size_t event_num_digits = std::numeric_limits<event_num_t>::digits;
0031   static constexpr size_t run_num_digits   = std::numeric_limits<run_num_t>::digits;
0032   static constexpr size_t seed_digits      = std::numeric_limits<seed_t>::digits;
0033   static constexpr size_t name_digits      = std::numeric_limits<size_t>::digits;
0034 
0035 public:
0036   virtual void init() {}
0037 
0038   // calculate a unique id from name and the event header
0039   size_t getUniqueID(const edm4hep::EventHeader& evt_header, const std::string_view& name) const {
0040     return getUniqueID(evt_header.getEventNumber(), evt_header.getRunNumber(), name);
0041   }
0042   // calculate a unique id from name and the first element of collection
0043   size_t getUniqueID(const edm4hep::EventHeaderCollection& evt_headers,
0044                      const std::string_view& name) const {
0045     return getUniqueID(evt_headers.at(0), name);
0046   }
0047   // calculate a unique id from name and the event and run numbers
0048   size_t getUniqueID(const event_num_t evt_num, const run_num_t run_num,
0049                      const std::string_view& name) const {
0050     std::bitset<seed_digits> seed_bits           = m_seed.value();
0051     std::bitset<event_num_digits> event_num_bits = evt_num;
0052     std::bitset<run_num_digits> run_num_bits     = run_num;
0053     std::bitset<name_digits> name_bits           = std::hash<std::string_view>{}(name);
0054 
0055     std::bitset<seed_digits + event_num_digits + run_num_digits + name_digits> combined_bits;
0056 
0057     for (size_t i = 0; i < name_digits; i++) {
0058       combined_bits[i] = name_bits[i];
0059     }
0060     for (size_t i = 0; i < run_num_digits; i++) {
0061       combined_bits[i + name_digits] = run_num_bits[i];
0062     }
0063     for (size_t i = 0; i < event_num_digits; i++) {
0064       combined_bits[i + run_num_digits + name_digits] = event_num_bits[i];
0065     }
0066     for (size_t i = 0; i < seed_digits; i++) {
0067       combined_bits[i + event_num_digits + run_num_digits + name_digits] = seed_bits[i];
0068     }
0069 
0070     auto hash =
0071         std::hash<std::bitset<seed_digits + event_num_digits + run_num_digits + name_digits>>{}(
0072             combined_bits);
0073 
0074     if (m_checkDuplicates) {
0075       auto [it, inserted] = [=, this, &name]() {
0076         std::lock_guard<std::mutex> lock(m_mutex);
0077         return m_uniqueIDs.insert({hash, {evt_num, run_num, std::string{name}}});
0078       }();
0079       if (!inserted) {
0080         const auto& [id_evt, id_run, id_name] = it->second;
0081         // TODO log to error
0082         throw std::runtime_error(fmt::format(
0083             "Duplicate ID for event number, run number and algorithm name: {}, {}, \"{}\". "
0084             "ID already assigned to: {}, {}, \"{}\"",
0085             evt_num, run_num, name, id_evt, id_run, id_name));
0086       }
0087     }
0088 
0089     return hash;
0090   };
0091 
0092 protected:
0093   ALGORITHMS_DEFINE_LOGGED_SERVICE(UniqueIDGenSvc)
0094 
0095 private:
0096   Property<size_t> m_seed{this, "seed", 1, "Random seed for the internal random engine"};
0097   Property<bool> m_checkDuplicates{
0098       this, "checkDuplicates", false,
0099       "Caches obtained ID and throws an exception if a duplicate would be returned"};
0100 
0101   mutable std::unordered_map<size_t, std::tuple<event_num_t, run_num_t, std::string>, std::identity>
0102       m_uniqueIDs;
0103   mutable std::mutex m_mutex;
0104 };
0105 
0106 } // namespace algorithms