Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-07-06 07:52:51

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 #pragma once
0010 
0011 #include "Acts/Definitions/TrackParametrization.hpp"
0012 #include "Acts/EventData/TransformationHelpers.hpp"
0013 #include "Acts/Geometry/DetectorElementBase.hpp"
0014 #include "Acts/Surfaces/Surface.hpp"
0015 #include "Acts/Utilities/Result.hpp"
0016 #include "ActsFatras/Digitization/DigitizationError.hpp"
0017 #include "ActsFatras/EventData/Hit.hpp"
0018 
0019 #include <array>
0020 #include <functional>
0021 #include <utility>
0022 
0023 namespace ActsFatras {
0024 
0025 /// Smearing function definition for single track parameters.
0026 ///
0027 /// The function takes the unsmeared parameter and returns the smeared value and
0028 /// a standard deviation.
0029 ///
0030 /// @tparam generator_t The type of the random generator.
0031 template <typename generator_t>
0032 using SingleParameterSmearFunction =
0033     std::function<Acts::Result<std::pair<double, double>>(double,
0034                                                           generator_t&)>;
0035 
0036 /// Uncorrelated smearing algorithm for fast digitisation of bound parameters.
0037 ///
0038 /// @tparam generator_t Random number generator type
0039 /// @tparam kSize Number of smeared parameters
0040 ///
0041 /// The smearer takes a single simulated `Hit` and generates a smeared parameter
0042 /// vector and associated covariance matrix.
0043 template <typename generator_t, std::size_t kSize>
0044 struct BoundParametersSmearer {
0045   using ParametersVector = Acts::ActsVector<kSize>;
0046   using CovarianceMatrix = Acts::ActsSquareMatrix<kSize>;
0047   using Result = Acts::Result<std::pair<ParametersVector, CovarianceMatrix>>;
0048 
0049   /// Parameter indices that will be used to create the smeared measurements.
0050   std::array<Acts::BoundIndices, kSize> indices{};
0051   std::array<SingleParameterSmearFunction<generator_t>, kSize> smearFunctions{};
0052   std::array<bool, kSize> forcePositive = {};
0053   std::size_t maxRetries = 0;
0054 
0055   static constexpr std::size_t size() { return kSize; }
0056 
0057   /// Generate smeared measured for configured parameters.
0058   ///
0059   /// @param rng Random number generator
0060   /// @param hit Simulated hit
0061   /// @param surface Local surface on which the hit is smeared
0062   /// @param geoCtx Geometry context
0063   /// @retval Smeared parameters vector and associated covariance on success
0064   /// @retval Error code for failure
0065   Result operator()(generator_t& rng, const Hit& hit,
0066                     const Acts::Surface& surface,
0067                     const Acts::GeometryContext& geoCtx) const {
0068     // We use the thickness of the detector element as tolerance, because Geant4
0069     // treats the Surfaces as volumes and thus it is not ensured, that each hit
0070     // lies exactly on the Acts::Surface
0071     const auto tolerance =
0072         surface.associatedDetectorElement() != nullptr
0073             ? surface.associatedDetectorElement()->thickness()
0074             : Acts::s_onSurfaceTolerance;
0075 
0076     // construct full bound parameters. they are probably not all needed, but it
0077     // is easier to just create them all and then select the requested ones.
0078     Acts::Result<Acts::BoundVector> boundParamsRes =
0079         Acts::transformFreeToBoundParameters(hit.position(), hit.time(),
0080                                              hit.direction(), 0, surface,
0081                                              geoCtx, tolerance);
0082 
0083     if (!boundParamsRes.ok()) {
0084       return boundParamsRes.error();
0085     }
0086 
0087     const auto& boundParams = *boundParamsRes;
0088     Acts::BoundVector smearedBoundParams = boundParams;
0089 
0090     for (std::size_t k = 0; k < maxRetries + 1; ++k) {
0091       ParametersVector par = ParametersVector::Zero();
0092       CovarianceMatrix cov = CovarianceMatrix::Zero();
0093       for (std::size_t i = 0; i < kSize; ++i) {
0094         auto res = smearFunctions[i](boundParams[indices[i]], rng);
0095         if (!res.ok()) {
0096           return Result::failure(res.error());
0097         }
0098         auto [value, stddev] = res.value();
0099         par[i] = value;
0100         if (forcePositive[i]) {
0101           par[i] = std::abs(value);
0102         }
0103         smearedBoundParams[indices[i]] = par[i];
0104         cov(i, i) = stddev * stddev;
0105       }
0106 
0107       if (!surface.insideBounds(smearedBoundParams.head<2>())) {
0108         continue;
0109       }
0110 
0111       return Result::success(std::make_pair(par, cov));
0112     }
0113 
0114     return Result::failure(DigitizationError::MaximumRetriesExceeded);
0115   }
0116 };
0117 
0118 /// Uncorrelated smearing algorithm for fast digitisation of free parameters.
0119 ///
0120 /// @tparam generator_t Random number generator type
0121 /// @tparam kSize Number of smeared parameters
0122 ///
0123 /// The smearer takes a single simulated `Hit` and generates a smeared parameter
0124 /// vector and associated covariance matrix.
0125 ///
0126 /// @note Uncorrelated smearing of the direction using each components
0127 ///   individually is not recommended
0128 template <typename generator_t, std::size_t kSize>
0129 struct FreeParametersSmearer {
0130   using ParametersVector = Acts::ActsVector<kSize>;
0131   using CovarianceMatrix = Acts::ActsSquareMatrix<kSize>;
0132   using Result = Acts::Result<std::pair<ParametersVector, CovarianceMatrix>>;
0133 
0134   /// Parameter indices that will be used to create the smeared measurements.
0135   std::array<Acts::FreeIndices, kSize> indices{};
0136   std::array<SingleParameterSmearFunction<generator_t>, kSize> smearFunctions;
0137 
0138   static constexpr std::size_t size() { return kSize; }
0139 
0140   /// Generate smeared measured for configured parameters.
0141   ///
0142   /// @param rng Random number generator
0143   /// @param hit Simulated hit
0144   /// @return Smeared free parameter set wrapped in a Result<...> object
0145   /// @retval Smeared parameters vector and associated covariance on success
0146   /// @retval Error code for failure
0147   Result operator()(generator_t& rng, const Hit& hit) const {
0148     // construct full free parameters. they are probably not all needed, but it
0149     // is easier to just create them all and then select the requested ones.
0150     Acts::FreeVector freeParams;
0151     freeParams.segment<3>(Acts::eFreePos0) = hit.position();
0152     freeParams[Acts::eFreeTime] = hit.time();
0153     freeParams.segment<3>(Acts::eFreeDir0) = hit.direction();
0154     freeParams[Acts::eFreeQOverP] = 0;
0155 
0156     ParametersVector par = ParametersVector::Zero();
0157     CovarianceMatrix cov = CovarianceMatrix::Zero();
0158     for (std::size_t i = 0; i < kSize; ++i) {
0159       auto res = smearFunctions[i](freeParams[indices[i]], rng);
0160       if (!res.ok()) {
0161         return Result::failure(res.error());
0162       }
0163       auto [value, stddev] = res.value();
0164       par[i] = value;
0165       cov(i, i) = stddev * stddev;
0166     }
0167 
0168     return Result::success(std::make_pair(par, cov));
0169   }
0170 };
0171 
0172 }  // namespace ActsFatras