Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-10-25 07:56:26

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   /// Type alias for parameter vector of dimension kSize
0046   using ParametersVector = Acts::ActsVector<kSize>;
0047   /// Type alias for covariance matrix of dimension kSize x kSize
0048   using CovarianceMatrix = Acts::ActsSquareMatrix<kSize>;
0049   /// Type alias for smearing result containing parameters and covariance
0050   using Result = Acts::Result<std::pair<ParametersVector, CovarianceMatrix>>;
0051 
0052   /// Parameter indices that will be used to create the smeared measurements.
0053   std::array<Acts::BoundIndices, kSize> indices{};
0054   /// Array of smearing functions for each measurement parameter
0055   std::array<SingleParameterSmearFunction<generator_t>, kSize> smearFunctions{};
0056   /// Array of flags to force positive values after smearing
0057   std::array<bool, kSize> forcePositive = {};
0058   /// Maximum number of retries for generating positive values when forced
0059   std::size_t maxRetries = 0;
0060 
0061   /// Get the number of bound parameters that will be smeared
0062   /// @return Number of bound parameters (kSize)
0063   static constexpr std::size_t size() { return kSize; }
0064 
0065   /// Generate smeared measured for configured parameters.
0066   ///
0067   /// @param rng Random number generator
0068   /// @param hit Simulated hit
0069   /// @param surface Local surface on which the hit is smeared
0070   /// @param geoCtx Geometry context
0071   /// @retval Smeared parameters vector and associated covariance on success
0072   /// @retval Error code for failure
0073   Result operator()(generator_t& rng, const Hit& hit,
0074                     const Acts::Surface& surface,
0075                     const Acts::GeometryContext& geoCtx) const {
0076     // We use the thickness of the detector element as tolerance, because Geant4
0077     // treats the Surfaces as volumes and thus it is not ensured, that each hit
0078     // lies exactly on the Acts::Surface
0079     const auto tolerance =
0080         surface.associatedDetectorElement() != nullptr
0081             ? surface.associatedDetectorElement()->thickness()
0082             : Acts::s_onSurfaceTolerance;
0083 
0084     // construct full bound parameters. they are probably not all needed, but it
0085     // is easier to just create them all and then select the requested ones.
0086     Acts::Result<Acts::BoundVector> boundParamsRes =
0087         Acts::transformFreeToBoundParameters(hit.position(), hit.time(),
0088                                              hit.direction(), 0, surface,
0089                                              geoCtx, tolerance);
0090 
0091     if (!boundParamsRes.ok()) {
0092       return boundParamsRes.error();
0093     }
0094 
0095     const auto& boundParams = *boundParamsRes;
0096     Acts::BoundVector smearedBoundParams = boundParams;
0097 
0098     for (std::size_t k = 0; k < maxRetries + 1; ++k) {
0099       ParametersVector par = ParametersVector::Zero();
0100       CovarianceMatrix cov = CovarianceMatrix::Zero();
0101       for (std::size_t i = 0; i < kSize; ++i) {
0102         auto res = smearFunctions[i](boundParams[indices[i]], rng);
0103         if (!res.ok()) {
0104           return Result::failure(res.error());
0105         }
0106         auto [value, stddev] = res.value();
0107         par[i] = value;
0108         if (forcePositive[i]) {
0109           par[i] = std::abs(value);
0110         }
0111         smearedBoundParams[indices[i]] = par[i];
0112         cov(i, i) = stddev * stddev;
0113       }
0114 
0115       if (!surface.insideBounds(smearedBoundParams.head<2>())) {
0116         continue;
0117       }
0118 
0119       return Result::success(std::make_pair(par, cov));
0120     }
0121 
0122     return Result::failure(DigitizationError::MaximumRetriesExceeded);
0123   }
0124 };
0125 
0126 /// Uncorrelated smearing algorithm for fast digitisation of free parameters.
0127 ///
0128 /// @tparam generator_t Random number generator type
0129 /// @tparam kSize Number of smeared parameters
0130 ///
0131 /// The smearer takes a single simulated `Hit` and generates a smeared parameter
0132 /// vector and associated covariance matrix.
0133 ///
0134 /// @note Uncorrelated smearing of the direction using each components
0135 ///   individually is not recommended
0136 template <typename generator_t, std::size_t kSize>
0137 struct FreeParametersSmearer {
0138   /// Type alias for parameter vector of dimension kSize
0139   using ParametersVector = Acts::ActsVector<kSize>;
0140   /// Type alias for covariance matrix of dimension kSize x kSize
0141   using CovarianceMatrix = Acts::ActsSquareMatrix<kSize>;
0142   /// Type alias for smearing result containing parameters and covariance
0143   using Result = Acts::Result<std::pair<ParametersVector, CovarianceMatrix>>;
0144 
0145   /// Parameter indices that will be used to create the smeared measurements.
0146   std::array<Acts::FreeIndices, kSize> indices{};
0147   /// Array of smearing functions for each free parameter
0148   std::array<SingleParameterSmearFunction<generator_t>, kSize> smearFunctions;
0149 
0150   /// Get the number of free parameters that will be smeared
0151   /// @return Number of free parameters (kSize)
0152   static constexpr std::size_t size() { return kSize; }
0153 
0154   /// Generate smeared measured for configured parameters.
0155   ///
0156   /// @param rng Random number generator
0157   /// @param hit Simulated hit
0158   /// @return Smeared free parameter set wrapped in a Result<...> object
0159   /// @retval Smeared parameters vector and associated covariance on success
0160   /// @retval Error code for failure
0161   Result operator()(generator_t& rng, const Hit& hit) const {
0162     // construct full free parameters. they are probably not all needed, but it
0163     // is easier to just create them all and then select the requested ones.
0164     Acts::FreeVector freeParams;
0165     freeParams.segment<3>(Acts::eFreePos0) = hit.position();
0166     freeParams[Acts::eFreeTime] = hit.time();
0167     freeParams.segment<3>(Acts::eFreeDir0) = hit.direction();
0168     freeParams[Acts::eFreeQOverP] = 0;
0169 
0170     ParametersVector par = ParametersVector::Zero();
0171     CovarianceMatrix cov = CovarianceMatrix::Zero();
0172     for (std::size_t i = 0; i < kSize; ++i) {
0173       auto res = smearFunctions[i](freeParams[indices[i]], rng);
0174       if (!res.ok()) {
0175         return Result::failure(res.error());
0176       }
0177       auto [value, stddev] = res.value();
0178       par[i] = value;
0179       cov(i, i) = stddev * stddev;
0180     }
0181 
0182     return Result::success(std::make_pair(par, cov));
0183   }
0184 };
0185 
0186 }  // namespace ActsFatras