Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-31 09:16:52

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/ContextualDetector/ExternalAlignmentDecorator.hpp"
0010 
0011 #include "Acts/Geometry/GeometryContext.hpp"
0012 #include "Acts/Geometry/TrackingGeometry.hpp"
0013 #include "ActsExamples/ContextualDetector/ExternallyAlignedDetectorElement.hpp"
0014 #include "ActsExamples/Framework/AlgorithmContext.hpp"
0015 #include "ActsExamples/Framework/RandomNumbers.hpp"
0016 
0017 #include <cassert>
0018 #include <ostream>
0019 #include <thread>
0020 #include <utility>
0021 
0022 namespace ActsExamples {
0023 
0024 ExternalAlignmentDecorator::ExternalAlignmentDecorator(
0025     const Config& cfg, std::unique_ptr<const Acts::Logger> logger)
0026     : m_cfg(cfg), m_logger(std::move(logger)) {
0027   if (m_cfg.trackingGeometry != nullptr) {
0028     // parse and populate
0029     parseGeometry(*m_cfg.trackingGeometry.get());
0030   }
0031 }
0032 
0033 ProcessCode ExternalAlignmentDecorator::decorate(AlgorithmContext& context) {
0034   // Iov map access needs to be synchronized
0035   std::lock_guard lock{m_iovMutex};
0036 
0037   // In which iov batch are we?
0038   unsigned int iov = context.eventNumber / m_cfg.iovSize;
0039   ACTS_VERBOSE("IOV handling in thread " << std::this_thread::get_id() << ".");
0040   ACTS_VERBOSE("IOV resolved to " << iov << " - from event "
0041                                   << context.eventNumber << ".");
0042 
0043   m_eventsSeen++;
0044 
0045   if (m_cfg.randomNumberSvc != nullptr) {
0046     if (auto it = m_activeIovs.find(iov); it != m_activeIovs.end()) {
0047       // Iov is already present, update last accessed
0048       it->second->lastAccessed = m_eventsSeen;
0049       context.geoContext =
0050           ExternallyAlignedDetectorElement::ContextType{it->second};
0051     } else {
0052       // Iov is not present yet, create it
0053       auto alignmentStore =
0054           std::make_unique<ExternallyAlignedDetectorElement::AlignmentStore>();
0055       alignmentStore->lastAccessed = m_eventsSeen;
0056 
0057       ACTS_VERBOSE("New IOV " << iov << " detected at event "
0058                               << context.eventNumber
0059                               << ", emulate new alignment.");
0060 
0061       // Create an algorithm local random number generator
0062       RandomEngine rng = m_cfg.randomNumberSvc->spawnGenerator(context);
0063 
0064       alignmentStore->transforms = m_nominalStore;  // copy nominal alignment
0065       for (auto& tForm : alignmentStore->transforms) {
0066         // Multiply alignment in place
0067         applyTransform(tForm, m_cfg, rng, iov);
0068       }
0069 
0070       auto [insertIterator, inserted] =
0071           m_activeIovs.emplace(iov, std::move(alignmentStore));
0072       assert(inserted && "Expected IOV to be created in map, but wasn't");
0073 
0074       // make context from iov pointer, address should be stable
0075       context.geoContext =
0076           ExternallyAlignedDetectorElement::ContextType{insertIterator->second};
0077     }
0078   }
0079 
0080   // Garbage collection
0081   if (m_cfg.doGarbageCollection) {
0082     for (auto it = m_activeIovs.begin(); it != m_activeIovs.end();) {
0083       auto& status = it->second;
0084       if (m_eventsSeen - status->lastAccessed > m_cfg.flushSize) {
0085         ACTS_DEBUG("IOV " << iov << " has not been accessed in the last "
0086                           << m_cfg.flushSize << " events, clearing");
0087         it = m_activeIovs.erase(it);
0088       } else {
0089         it++;
0090       }
0091     }
0092   }
0093 
0094   return ProcessCode::SUCCESS;
0095 }
0096 
0097 void ExternalAlignmentDecorator::parseGeometry(
0098     const Acts::TrackingGeometry& tGeometry) {
0099   // Double-visit - first count
0100   std::size_t nTransforms = 0;
0101   tGeometry.visitSurfaces([&nTransforms](const auto*) { ++nTransforms; });
0102 
0103   Acts::GeometryContext nominalCtx{
0104       ExternallyAlignedDetectorElement::ContextType{}};
0105 
0106   // Collect the surfacas into the nominal store
0107   std::vector<Acts::Transform3> aStore(nTransforms,
0108                                        Acts::Transform3::Identity());
0109 
0110   auto fillTransforms = [&aStore, &nominalCtx](const auto* surface) -> void {
0111     if (surface == nullptr) {
0112       throw std::invalid_argument("Surface is nullptr.");
0113     }
0114     auto alignableElement =
0115         dynamic_cast<const ExternallyAlignedDetectorElement*>(
0116             surface->associatedDetectorElement());
0117     if (alignableElement == nullptr) {
0118       throw std::invalid_argument("Surface is not alignable");
0119     }
0120     aStore[alignableElement->identifier()] = surface->transform(nominalCtx);
0121   };
0122 
0123   tGeometry.visitSurfaces(fillTransforms);
0124   m_nominalStore = std::move(aStore);
0125 }
0126 
0127 }  // namespace ActsExamples