Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-11-04 09:21:32

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 /// @note This file is foreseen for the `Geometry` module to replace `Extent`
0012 
0013 #include "Acts/Definitions/Algebra.hpp"
0014 #include "Acts/Utilities/AxisDefinitions.hpp"
0015 #include "Acts/Utilities/Enumerate.hpp"
0016 #include "Acts/Utilities/Helpers.hpp"
0017 #include "Acts/Utilities/RangeXD.hpp"
0018 
0019 #include <array>
0020 #include <bitset>
0021 #include <optional>
0022 #include <ostream>
0023 #include <string>
0024 #include <vector>
0025 
0026 namespace Acts {
0027 
0028 /// @brief Type alias for envelope values in different directions
0029 /// @details Stores the envelope values for both positive and negative directions
0030 using Envelope = std::array<double, 2>;
0031 
0032 /// Zero envelope constant for no extension
0033 constexpr Envelope zeroEnvelope = {0, 0};
0034 
0035 /// This struct models a multi-dimensional enveloper along the axis directions
0036 struct ExtentEnvelope {
0037   /// Access a single envelope configuration
0038   /// @param aDir the axis definition
0039   /// @return the envelope
0040   Envelope& operator[](AxisDirection aDir) {
0041     return m_values.at(toUnderlying(aDir));
0042   }
0043 
0044   /// Access a single envelope configuration
0045   /// @param aDir the axis direction
0046   /// @return the envelope
0047   const Envelope& operator[](AxisDirection aDir) const {
0048     return m_values.at(toUnderlying(aDir));
0049   }
0050 
0051   /// Constructor from a single envelope that is assigned to all values
0052   /// @param envelope the envelope to be assigned
0053   explicit ExtentEnvelope(const Envelope& envelope = zeroEnvelope) {
0054     for (auto& val : m_values) {
0055       val = envelope;
0056     }
0057   }
0058 
0059   /// Static factory for a zero envelope
0060   /// @return the zero envelope
0061   constexpr static ExtentEnvelope Zero() {
0062     return ExtentEnvelope{{
0063         zeroEnvelope,
0064         zeroEnvelope,
0065         zeroEnvelope,
0066         zeroEnvelope,
0067         zeroEnvelope,
0068         zeroEnvelope,
0069         zeroEnvelope,
0070         zeroEnvelope,
0071         zeroEnvelope,
0072     }};
0073   }
0074 
0075   /// Helper struct for designated initializer construction
0076   struct Arguments {
0077     /// Envelope for x-coordinate direction
0078     Envelope x = zeroEnvelope;
0079     /// Envelope for y-coordinate direction
0080     Envelope y = zeroEnvelope;
0081     /// Envelope for z-coordinate direction
0082     Envelope z = zeroEnvelope;
0083     /// Envelope for radial coordinate direction
0084     Envelope r = zeroEnvelope;
0085     /// Envelope for azimuthal angle direction
0086     Envelope phi = zeroEnvelope;
0087     /// Envelope for r*phi coordinate direction
0088     Envelope rPhi = zeroEnvelope;
0089     /// Envelope for polar angle direction
0090     Envelope theta = zeroEnvelope;
0091     /// Envelope for pseudorapidity direction
0092     Envelope eta = zeroEnvelope;
0093     /// Envelope for magnitude direction
0094     Envelope mag = zeroEnvelope;
0095   };
0096 
0097   /// Constructor using a helper struct for designated initializaion
0098   /// @param args the arguments
0099   constexpr explicit ExtentEnvelope(Arguments&& args) {
0100     using enum AxisDirection;
0101     m_values[toUnderlying(AxisX)] = args.x;
0102     m_values[toUnderlying(AxisY)] = args.y;
0103     m_values[toUnderlying(AxisZ)] = args.z;
0104     m_values[toUnderlying(AxisR)] = args.r;
0105     m_values[toUnderlying(AxisPhi)] = args.phi;
0106     m_values[toUnderlying(AxisTheta)] = args.theta;
0107     m_values[toUnderlying(AxisEta)] = args.eta;
0108     m_values[toUnderlying(AxisMag)] = args.mag;
0109   }
0110 
0111   /// Comparison operator between envelope sets
0112   /// @param lhs the left hand side
0113   /// @param rhs the right hand side
0114   /// @return true if the envelopes are equal
0115   friend bool operator==(const ExtentEnvelope& lhs, const ExtentEnvelope& rhs) {
0116     return lhs.m_values == rhs.m_values;
0117   }
0118 
0119  private:
0120   std::array<Envelope, numAxisDirections()> m_values{};
0121 };
0122 
0123 /// A class representing the geometric extent of an object in its possible
0124 /// dimensions, these can be all dimensions that are described as AxisDirections
0125 ///
0126 /// The extent object can have an optional envelope in all of those values
0127 /// @note that the consistency of the different envelopes is not checked
0128 ///
0129 class Extent {
0130  public:
0131   /// Constructor with (optional) @param envelope
0132   explicit Extent(const ExtentEnvelope& envelope = ExtentEnvelope::Zero());
0133 
0134   /// Define a comparison operator
0135   /// @param e The extent to compare with
0136   /// @return True if the extents are equal, false otherwise
0137   bool operator==(const Extent& e) const;
0138 
0139   /// Extend with a position vertex
0140   ///
0141   /// @param vtx the vertex to be used for extending
0142   /// @param aDirs the axis directions
0143   /// @param applyEnv boolean to steer if envelope should be applied
0144   /// @param fillHistograms is a boolean flag to steer whether the values
0145   ///        to fill this extent should be stored
0146   void extend(const Vector3& vtx,
0147               const std::vector<AxisDirection>& aDirs = allAxisDirections(),
0148               bool applyEnv = true, bool fillHistograms = false);
0149 
0150   /// Extend with a set of vectors by iterators
0151   ///
0152   /// @param start the start iterator of the loop
0153   /// @param end the end iterator of the loop
0154   /// @param aDirs the axis directions
0155   /// @param applyEnv boolean to steer if envelope should be applied
0156   /// @param fillHistograms is a boolean flag to steer whether the values
0157   ///        to fill this extent should be stored
0158   template <typename vector_iterator_t>
0159   void extend(const vector_iterator_t& start, const vector_iterator_t& end,
0160               const std::vector<AxisDirection>& aDirs = allAxisDirections(),
0161               bool applyEnv = true, bool fillHistograms = false) {
0162     for (vector_iterator_t vIt = start; vIt < end; ++vIt) {
0163       extend(*vIt, aDirs, applyEnv, fillHistograms);
0164     }
0165   }
0166 
0167   /// Extend with another geometric extent, usually pushes the
0168   /// current range to the boundaries of the rhs extent,
0169   /// unless the current extent is already bigger.
0170   ///
0171   /// @note the extent can also simply set an envelope
0172   /// which then is applied to the current one
0173   ///
0174   /// @param rhs is the other source Extent
0175   /// @param aDirs the axis directions
0176   /// @param applyEnv boolean to steer if envelope should be applied
0177   ///        on the constraint values, if only an envelope is given
0178   ///        but the value not constraint, then it is always applied
0179   ///
0180   /// @note that the histogram values can not be filled in this call
0181   void extend(const Extent& rhs,
0182               const std::vector<AxisDirection>& aDirs = allAxisDirections(),
0183               bool applyEnv = true);
0184 
0185   /// Constrain an extent by another one, this is
0186   /// - values that are already constrained are not touched
0187   /// - values not constrained by @param rhs are not touched
0188   /// - values that are constrained by the external one, but not
0189   /// by the current one, are touched
0190   ///
0191   /// @param envelope an envelope applied to the constrained value
0192   void addConstrain(const Extent& rhs,
0193                     const ExtentEnvelope& envelope = ExtentEnvelope::Zero());
0194 
0195   /// Set a range for a dedicated binning value
0196   ///
0197   /// @param aDir the axis direction
0198   /// @param min the minimum parameter
0199   /// @param max the maximum parameter
0200   void set(AxisDirection aDir, double min, double max);
0201 
0202   /// Set a min value for a dedicated binning value
0203   ///
0204   /// @param aDir the axis direction
0205   /// @param min the minimum parameter
0206   void setMin(AxisDirection aDir, double min);
0207 
0208   /// Set a max value for a dedicated binning value
0209   ///
0210   /// @param aDir the axis direction
0211   /// @param max the maximum parameter
0212   void setMax(AxisDirection aDir, double max);
0213 
0214   /// (re-)Set the envelope
0215   ///
0216   /// @param envelope new envelope to be set
0217   void setEnvelope(const ExtentEnvelope& envelope = ExtentEnvelope::Zero());
0218 
0219   /// Return the individual 1-dimensional range
0220   ///
0221   /// @param aDir is the axis direction to be returned
0222   ///
0223   /// @return a one dimensional arrange
0224   auto range(AxisDirection aDir) { return m_range[toUnderlying(aDir)]; }
0225 
0226   /// Return the individual 1-dimensional range
0227   ///
0228   /// @param aDir is the axis direction to be returned
0229   ///
0230   /// @return a one dimensional arrange
0231   Range1D<double> range(AxisDirection aDir) const;
0232 
0233   /// Return the N-dimension range
0234   /// @return Reference to the complete multi-dimensional range
0235   const RangeXD<numAxisDirections(), double>& range() const;
0236 
0237   /// Return an D-dimensional sub range according to the
0238   /// the given binvalues
0239   /// @tparam kSUBDIM the number of sub dimensions
0240   /// @param axisDirections the axis directions
0241   /// @return the sub range
0242   template <unsigned int kSUBDIM>
0243   RangeXD<kSUBDIM, double> range(
0244       const std::array<AxisDirection, kSUBDIM>& axisDirections) const {
0245     RangeXD<kSUBDIM, double> rRange;
0246     for (auto [i, v] : enumerate(axisDirections)) {
0247       rRange[i] = range(v);
0248     }
0249     return rRange;
0250   }
0251 
0252   /// Return the envelope - non-const access
0253   /// @return Reference to the envelope for modification
0254   ExtentEnvelope& envelope();
0255 
0256   /// Return the envelope - const access
0257   /// @return Const reference to the envelope
0258   const ExtentEnvelope& envelope() const;
0259 
0260   /// Return the histogram store
0261   ///
0262   /// The histogram store can be used for automated binning detection
0263   const std::array<std::vector<double>, numAxisDirections()>& valueHistograms()
0264       const;
0265 
0266   /// Access the minimum parameter
0267   ///
0268   /// @param aDir the axis direction
0269   /// @return Minimum value along the specified axis direction
0270   double min(AxisDirection aDir) const {
0271     return m_range[toUnderlying(aDir)].min();
0272   }
0273 
0274   /// Access the maximum parameter
0275   ///
0276   /// @param aDir the axis direction
0277   /// @return Maximum value along the specified axis direction
0278   double max(AxisDirection aDir) const {
0279     return m_range[toUnderlying(aDir)].max();
0280   }
0281 
0282   /// Access the midpoint
0283   ///
0284   /// @param aDir the axis direction
0285   /// @return Midpoint value along the specified axis direction
0286   double medium(AxisDirection aDir) const {
0287     return 0.5 * (m_range[toUnderlying(aDir)].min() +
0288                   m_range[toUnderlying(aDir)].max());
0289   }
0290 
0291   /// Access the parameter interval (i.e. the range span)
0292   ///
0293   /// @param aDir the axis direction
0294   /// @return Interval size along the specified axis direction
0295   double interval(AxisDirection aDir) const {
0296     return m_range[toUnderlying(aDir)].size();
0297   }
0298 
0299   /// Contains check
0300   ///
0301   /// @param rhs the extent that is check if it is contained
0302   /// @param aDir is the axis direction, if set to nullopt
0303   ///               the check on all is done
0304   ///
0305   /// @return true if the rhs is contained
0306   bool contains(const Extent& rhs,
0307                 std::optional<AxisDirection> aDir = std::nullopt) const;
0308 
0309   /// Contains check for a single point
0310   ///
0311   /// @param vtx the point that is check if it is contained
0312   ///
0313   /// @return true if the rhs is contained
0314   bool contains(const Vector3& vtx) const;
0315 
0316   /// Intersection checks
0317   ///
0318   /// @param rhs the extent that is check for intersection
0319   /// @param aDir is the axis direction, if set to nulloptr
0320   ///               the check on all is done
0321   ///
0322   /// @return true if the rhs intersects
0323   bool intersects(const Extent& rhs,
0324                   std::optional<AxisDirection> aDir = std::nullopt) const;
0325 
0326   /// Check if this object constrains a given direction
0327   ///
0328   /// @param aDir is the axis direction
0329   /// @return True if the specified axis direction is constrained, false otherwise
0330   bool constrains(AxisDirection aDir) const;
0331 
0332   /// Check if this object constrains any direction
0333   /// @return True if any axis direction is constrained, false otherwise
0334   bool constrains() const;
0335 
0336   /// Convert to output stream for screen output
0337   ///
0338   /// @param indent indentation for the screen display
0339   /// @return String representation of the extent
0340   std::string toString(const std::string& indent = "") const;
0341 
0342  private:
0343   /// A bitset that remembers the constraint values
0344   std::bitset<numAxisDirections()> m_constrains{0};
0345   /// The actual range store
0346   RangeXD<numAxisDirections(), double> m_range;
0347   /// A potential envelope
0348   ExtentEnvelope m_envelope = ExtentEnvelope::Zero();
0349   /// (Optional) Value histograms for bin detection
0350   std::array<std::vector<double>, numAxisDirections()> m_valueHistograms;
0351 };
0352 
0353 inline Range1D<double> Acts::Extent::range(AxisDirection aDir) const {
0354   return m_range[toUnderlying(aDir)];
0355 }
0356 
0357 inline const RangeXD<numAxisDirections(), double>& Extent::range() const {
0358   return m_range;
0359 }
0360 
0361 inline ExtentEnvelope& Extent::envelope() {
0362   return m_envelope;
0363 }
0364 
0365 inline const ExtentEnvelope& Extent::envelope() const {
0366   return m_envelope;
0367 }
0368 
0369 /// Return the value histograms
0370 /// @return Reference to the value histograms array
0371 inline const std::array<std::vector<double>, numAxisDirections()>&
0372 Extent::valueHistograms() const {
0373   return m_valueHistograms;
0374 }
0375 
0376 /// Overload of << operator for std::ostream for debug output
0377 /// @param sl Output stream
0378 /// @param rhs Extent to output
0379 /// @return Reference to output stream
0380 std::ostream& operator<<(std::ostream& sl, const Extent& rhs);
0381 
0382 }  // namespace Acts