Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 09:11:40

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/TrackFinding/SpacePointMaker.hpp"
0010 
0011 #include "Acts/Definitions/Algebra.hpp"
0012 #include "Acts/EventData/SourceLink.hpp"
0013 #include "Acts/SpacePointFormation/SpacePointBuilderConfig.hpp"
0014 #include "Acts/SpacePointFormation/SpacePointBuilderOptions.hpp"
0015 #include "ActsExamples/EventData/GeometryContainers.hpp"
0016 #include "ActsExamples/EventData/IndexSourceLink.hpp"
0017 #include "ActsExamples/EventData/Measurement.hpp"
0018 #include "ActsExamples/EventData/SimSpacePoint.hpp"
0019 #include "ActsExamples/Framework/AlgorithmContext.hpp"
0020 #include "ActsExamples/Utilities/GroupBy.hpp"
0021 
0022 #include <algorithm>
0023 #include <functional>
0024 #include <iterator>
0025 #include <ostream>
0026 #include <stdexcept>
0027 #include <utility>
0028 
0029 ActsExamples::SpacePointMaker::SpacePointMaker(Config cfg,
0030                                                Acts::Logging::Level lvl)
0031     : IAlgorithm("SpacePointMaker", lvl), m_cfg(std::move(cfg)) {
0032   if (m_cfg.inputMeasurements.empty()) {
0033     throw std::invalid_argument("Missing measurement input collection");
0034   }
0035   if (m_cfg.outputSpacePoints.empty()) {
0036     throw std::invalid_argument("Missing space point output collection");
0037   }
0038   if (!m_cfg.trackingGeometry) {
0039     throw std::invalid_argument("Missing tracking geometry");
0040   }
0041   if (m_cfg.geometrySelection.empty()) {
0042     throw std::invalid_argument("Missing space point maker geometry selection");
0043   }
0044 
0045   m_inputMeasurements.initialize(m_cfg.inputMeasurements);
0046   m_outputSpacePoints.initialize(m_cfg.outputSpacePoints);
0047 
0048   // ensure geometry selection contains only valid inputs
0049   for (const auto& geoId : m_cfg.geometrySelection) {
0050     if ((geoId.approach() != 0u) || (geoId.boundary() != 0u) ||
0051         (geoId.sensitive() != 0u)) {
0052       throw std::invalid_argument(
0053           "Invalid geometry selection: only volume and layer are allowed to be "
0054           "set");
0055     }
0056   }
0057   // remove geometry selection duplicates
0058   //
0059   // the geometry selections must be mutually exclusive, i.e. if we have a
0060   // selection that contains both a volume and a layer within that same volume,
0061   // we would create the space points for the layer twice.
0062   auto isDuplicate = [](Acts::GeometryIdentifier ref,
0063                         Acts::GeometryIdentifier cmp) {
0064     // code assumes ref < cmp and that only volume and layer can be non-zero
0065     // root node always contains everything
0066     if (ref.volume() == 0) {
0067       return true;
0068     }
0069     // unequal volumes always means separate hierarchies
0070     if (ref.volume() != cmp.volume()) {
0071       return false;
0072     }
0073     // within the same volume hierarchy only consider layers
0074     return (ref.layer() == cmp.layer());
0075   };
0076   // sort geometry selection so the unique filtering works
0077   std::ranges::sort(m_cfg.geometrySelection,
0078                     std::less<Acts::GeometryIdentifier>{});
0079   auto geoSelBeg = m_cfg.geometrySelection.begin();
0080   auto geoSelEnd = m_cfg.geometrySelection.end();
0081   auto geoSelLastUnique = std::unique(geoSelBeg, geoSelEnd, isDuplicate);
0082   if (geoSelLastUnique != geoSelEnd) {
0083     ACTS_WARNING("Removed " << std::distance(geoSelLastUnique, geoSelEnd)
0084                             << " geometry selection duplicates");
0085     m_cfg.geometrySelection.erase(geoSelLastUnique, geoSelEnd);
0086   }
0087   ACTS_INFO("Space point geometry selection:");
0088   for (const auto& geoId : m_cfg.geometrySelection) {
0089     ACTS_INFO("  " << geoId);
0090   }
0091   auto spBuilderConfig = Acts::SpacePointBuilderConfig();
0092   spBuilderConfig.trackingGeometry = m_cfg.trackingGeometry;
0093 
0094   m_slSurfaceAccessor.emplace(
0095       IndexSourceLink::SurfaceAccessor{*m_cfg.trackingGeometry});
0096   spBuilderConfig.slSurfaceAccessor
0097       .connect<&IndexSourceLink::SurfaceAccessor::operator()>(
0098           &m_slSurfaceAccessor.value());
0099 
0100   auto spConstructor =
0101       [](const Acts::Vector3& pos, std::optional<double> t,
0102          const Acts::Vector2& cov, std::optional<double> varT,
0103          boost::container::static_vector<Acts::SourceLink, 2> slinks)
0104       -> SimSpacePoint {
0105     return SimSpacePoint(pos, t, cov[0], cov[1], varT, std::move(slinks));
0106   };
0107 
0108   m_spacePointBuilder = Acts::SpacePointBuilder<SimSpacePoint>(
0109       spBuilderConfig, spConstructor,
0110       Acts::getDefaultLogger("SpacePointBuilder", lvl));
0111 }
0112 
0113 ActsExamples::ProcessCode ActsExamples::SpacePointMaker::execute(
0114     const AlgorithmContext& ctx) const {
0115   const auto& measurements = m_inputMeasurements(ctx);
0116 
0117   // TODO Support strip measurements
0118   Acts::SpacePointBuilderOptions spOpt;
0119 
0120   spOpt.paramCovAccessor = [&measurements](Acts::SourceLink slink) {
0121     const auto islink = slink.get<IndexSourceLink>();
0122     const ConstVariableBoundMeasurementProxy meas =
0123         measurements.getMeasurement(islink.index());
0124 
0125     return std::make_pair(meas.fullParameters(), meas.fullCovariance());
0126   };
0127 
0128   SimSpacePointContainer spacePoints;
0129   for (Acts::GeometryIdentifier geoId : m_cfg.geometrySelection) {
0130     // select volume/layer depending on what is set in the geometry id
0131     auto range =
0132         selectLowestNonZeroGeometryObject(measurements.orderedIndices(), geoId);
0133     // groupByModule only works with geometry containers, not with an
0134     // arbitrary range. do the equivalent grouping manually
0135     auto groupedByModule = makeGroupBy(range, detail::GeometryIdGetter());
0136 
0137     for (const auto& [moduleGeoId, moduleSourceLinks] : groupedByModule) {
0138       for (const auto& sourceLink : moduleSourceLinks) {
0139         m_spacePointBuilder.buildSpacePoint(
0140             ctx.geoContext, {Acts::SourceLink{sourceLink}}, spOpt,
0141             std::back_inserter(spacePoints));
0142       }
0143     }
0144   }
0145 
0146   spacePoints.shrink_to_fit();
0147 
0148   ACTS_DEBUG("Created " << spacePoints.size() << " space points");
0149   m_outputSpacePoints(ctx, std::move(spacePoints));
0150 
0151   return ActsExamples::ProcessCode::SUCCESS;
0152 }