Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-12-17 09:20:55

0001 // This file is part of the ACTS project.
0002 //
0003 // Copyright (C) 2016 CERN for the benefit of the ACTS project
0004 //
0005 // This Source Code Form is subject to the terms of the Mozilla Public
0006 // License, v. 2.0. If a copy of the MPL was not distributed with this
0007 // file, You can obtain one at https://mozilla.org/MPL/2.0/.
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   // First sort
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   // Then check for overlaps
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 }  // namespace
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   // Check for overlapping IOVs in the stores
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);  // Initialize counter to 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   // Get the event number & look for the alignment store
0072   const std::size_t eventNumber = context.eventNumber;
0073   // A pointer to an alignment store - if set it will be used to decorate the
0074   // geometry context consequently
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         }  // Increase the counter if first use;
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);  // Add to the IOV stores
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   // Run the garbage collection if requested
0111   if (m_cfg.garbageCollection) {
0112     std::scoped_lock lock(m_iovMutex);
0113     // First increase the counters
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     // Remove if count is greater than the interval
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;  // Remove if counter exceeds interval
0133       }
0134       return false;  // Keep it
0135     });
0136     // Do the actual removal
0137     m_iovStores.erase(rmIdx.begin(), rmIdx.end());
0138   }
0139 
0140   // Decorate the alignment context if a store is set
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 }