File indexing completed on 2025-12-17 09:20:55
0001
0002
0003
0004
0005
0006
0007
0008
0009 #include "ActsExamples/DetectorCommons/AlignmentDecorator.hpp"
0010
0011 #include "ActsExamples/DetectorCommons/AlignmentContext.hpp"
0012
0013 #include <ranges>
0014 #include <stdexcept>
0015
0016 namespace {
0017
0018 template <typename IovCollection>
0019 void checkOverlappingIOVs(IovCollection& iovStores) {
0020
0021 std::ranges::sort(iovStores, [](const auto& a, const auto& b) {
0022 return std::get<0>(a)[0] < std::get<0>(b)[0];
0023 });
0024
0025 for (std::size_t i = 1; i < iovStores.size(); ++i) {
0026 const auto& prevIov = std::get<0>(iovStores[i - 1]);
0027 const auto& currIov = std::get<0>(iovStores[i]);
0028 if (currIov[0] < prevIov[1]) {
0029 throw std::runtime_error(
0030 "Overlapping IOVs detected: " + std::to_string(prevIov[0]) + "-" +
0031 std::to_string(prevIov[1]) + " and " + std::to_string(currIov[0]) +
0032 "-" + std::to_string(currIov[1]));
0033 }
0034 }
0035 }
0036
0037 bool eventWithinIOV(const std::array<std::size_t, 2>& iov,
0038 std::size_t eventNumber) {
0039 return eventNumber >= iov[0] && eventNumber <= iov[1];
0040 }
0041
0042 }
0043
0044 ActsExamples::AlignmentDecorator::AlignmentDecorator(
0045 const ActsExamples::AlignmentDecorator::Config& config,
0046 Acts::Logging::Level level)
0047 : m_cfg(config),
0048 m_logger(Acts::getDefaultLogger("AlignmentDecorator", level)) {
0049
0050 if (!m_cfg.iovStores.empty() && m_cfg.iovGenerators.empty()) {
0051 ACTS_VERBOSE("Configuring AlignmentDecorator with IOV stores.");
0052 checkOverlappingIOVs(m_cfg.iovStores);
0053 m_iovStores.reserve(m_cfg.iovStores.size());
0054 std::ranges::for_each(m_cfg.iovStores, [&](const auto& iovStore) {
0055 const auto& [iov, store] = iovStore;
0056 m_iovStores.emplace_back(iov, store, 0);
0057 });
0058 } else if (!m_cfg.iovGenerators.empty()) {
0059 ACTS_VERBOSE("Configuring AlignmentDecorator with IOV generators.");
0060 m_iovGenerators = m_cfg.iovGenerators;
0061 checkOverlappingIOVs(m_cfg.iovGenerators);
0062 } else {
0063 throw std::runtime_error(
0064 "Both IOV stores and generators cannot be either empty nor "
0065 "configured.");
0066 }
0067 }
0068
0069 ActsExamples::ProcessCode ActsExamples::AlignmentDecorator::decorate(
0070 AlgorithmContext& context) {
0071
0072 const std::size_t eventNumber = context.eventNumber;
0073
0074
0075 IAlignmentStore* alignmentStore = nullptr;
0076 if (!m_iovStores.empty()) {
0077 ACTS_VERBOSE("Looking for alignment store for event " << eventNumber
0078 << " in IOV stores.");
0079 std::scoped_lock lock(m_iovMutex);
0080 std::ranges::for_each(m_iovStores, [&](auto& iovStore) {
0081 auto& [iov, store, counter] = iovStore;
0082 if (eventWithinIOV(iov, eventNumber)) {
0083 alignmentStore = store.get();
0084 if (counter == 0u) {
0085 ++counter;
0086 }
0087 }
0088 });
0089 }
0090
0091 if (!m_iovGenerators.empty() && alignmentStore == nullptr) {
0092 ACTS_VERBOSE("No alignment store found for event "
0093 << eventNumber << ", checking generators.");
0094 std::ranges::for_each(m_iovGenerators, [&](auto& iovGenerator) {
0095 const auto& [iov, generator] = iovGenerator;
0096 if (eventWithinIOV(iov, eventNumber)) {
0097 auto alignmentStorePtr = m_cfg.nominalStore->clone();
0098 std::scoped_lock lock(m_iovMutex);
0099 alignmentStorePtr->visitStore(generator);
0100 m_iovStores.emplace_back(iov, alignmentStorePtr,
0101 1);
0102 alignmentStore = alignmentStorePtr.get();
0103 ACTS_DEBUG("Generated alignment store for event "
0104 << eventNumber << " with IOV [" << iov[0] << ", " << iov[1]
0105 << "]");
0106 }
0107 });
0108 }
0109
0110
0111 if (m_cfg.garbageCollection) {
0112 std::scoped_lock lock(m_iovMutex);
0113
0114 for (auto& [iov, store, counter] : m_iovStores) {
0115 if (!eventWithinIOV(iov, eventNumber) && counter > 0) {
0116 ++counter;
0117 ACTS_VERBOSE("Garbage collection: keeping alignment store for IOV ["
0118 << iov[0] << ", " << iov[1]
0119 << "] events passed since last in use: " << counter);
0120 }
0121 }
0122
0123 auto rmIdx = std::ranges::remove_if(m_iovStores, [this](
0124 const auto& iovStore) {
0125 const auto& [iov, store, counter] = iovStore;
0126 if (counter > m_cfg.gcInterval) {
0127 ACTS_DEBUG("Garbage collection: removing alignment store for IOV [" +
0128 std::to_string(iov[0]) + ", " + std::to_string(iov[1]) +
0129 "] with counter " + std::to_string(counter - 1) +
0130 " reaching/exceeding interval " +
0131 std::to_string(m_cfg.gcInterval));
0132 return true;
0133 }
0134 return false;
0135 });
0136
0137 m_iovStores.erase(rmIdx.begin(), rmIdx.end());
0138 }
0139
0140
0141 if (alignmentStore != nullptr) {
0142 ACTS_DEBUG("Decorating AlgorithmContext with alignment store for event "
0143 << eventNumber);
0144 AlignmentContext alignmentContext{alignmentStore};
0145 context.geoContext = Acts::GeometryContext(alignmentContext);
0146 } else {
0147 ACTS_VERBOSE("No alignment store found for event "
0148 << eventNumber << ", skipping decoration.");
0149 }
0150
0151 return ActsExamples::ProcessCode::SUCCESS;
0152 }