Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-09-15 08:18:41

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/Utilities/AxisDefinitions.hpp"
0012 
0013 #include <iosfwd>
0014 #include <memory>
0015 #include <optional>
0016 #include <vector>
0017 
0018 namespace Acts {
0019 
0020 /// Common base class for all Axis instances. This allows generice handling
0021 /// such as for inspection.
0022 class IAxis {
0023  public:
0024   IAxis() = default;
0025 
0026   /// Constructs a new axis with the given direction
0027   /// @param direction the optional direction of the axis
0028   explicit IAxis(std::optional<AxisDirection> direction)
0029       : m_direction(direction) {}
0030 
0031   virtual ~IAxis() = default;
0032 
0033   /// Returns whether the axis is equidistant
0034   /// @return bool is equidistant
0035   virtual bool isEquidistant() const = 0;
0036 
0037   /// Returns whether the axis is variable
0038   /// @return bool is variable
0039   virtual bool isVariable() const = 0;
0040 
0041   /// Returns the type of the axis
0042   /// @return @c AxisType of this axis
0043   virtual AxisType getType() const = 0;
0044 
0045   /// Returns the boundary type set in the template param
0046   /// @return @c AxisBoundaryType of this axis
0047   virtual AxisBoundaryType getBoundaryType() const = 0;
0048 
0049   /// Returns the direction of the axis
0050   /// @return @c AxisDirection of this axis
0051   std::optional<AxisDirection> getDirection() const { return m_direction; }
0052 
0053   /// Returns a vector of bin edges
0054   /// @return Vector which contains the bin edges
0055   virtual std::vector<double> getBinEdges() const = 0;
0056 
0057   /// Get minimum of binning range
0058   /// @return minimum of binning range
0059   virtual double getMin() const = 0;
0060 
0061   /// Get maximum of binning range
0062   /// @return maximum of binning range
0063   virtual double getMax() const = 0;
0064 
0065   /// Get total number of bins
0066   /// @return total number of bins (excluding under-/overflow bins)
0067   virtual std::size_t getNBins() const = 0;
0068 
0069   /// Get corresponding bin index for given coordinate
0070   /// @param  [in] x input coordinate
0071   /// @return index of bin containing the given value
0072   /// @note Bin indices start at @c 1. The underflow bin has the index @c 0
0073   ///       while the index <tt>nBins + 1</tt> indicates the overflow bin .
0074   virtual std::size_t getBin(double x) const = 0;
0075 
0076   /// Check whether value is inside axis limits
0077   /// @param x The value to check
0078   /// @return @c true if the value is within the axis range, otherwise @c false
0079   /// @post If @c true is returned, the bin containing the given value is a
0080   ///       valid bin, i.e. it is neither the underflow nor the overflow bin.
0081   virtual bool isInside(double x) const = 0;
0082 
0083   /// Get bin width
0084   /// @param bin index of bin
0085   /// @return width of given bin
0086   virtual double getBinWidth(std::size_t bin) const = 0;
0087 
0088   /// Get lower bound of bin
0089   /// @param bin index of bin
0090   /// @return lower bin boundary
0091   /// @note Bin intervals have a closed lower bound, i.e. the lower boundary
0092   ///       belongs to the bin with the given bin index.
0093   virtual double getBinLowerBound(std::size_t bin) const = 0;
0094 
0095   /// Get upper bound of bin
0096   /// @param bin index of bin
0097   /// @return upper bin boundary
0098   /// @note Bin intervals have an open upper bound, i.e. the upper boundary
0099   ///       does @b not belong to the bin with the given bin index.
0100   virtual double getBinUpperBound(std::size_t bin) const = 0;
0101 
0102   /// Get bin center
0103   /// @param bin index of bin
0104   /// @return bin center position
0105   virtual double getBinCenter(std::size_t bin) const = 0;
0106 
0107   /// Centralized axis factory for equidistant binning
0108   /// @param aBoundaryType the axis boundary type
0109   /// @param min the minimum edge of the axis
0110   /// @param max the maximum edge of the axis
0111   /// @param nbins the number of bins
0112   /// @param direction the optional direction of the axis
0113   /// @throws std::invalid_argument if min >= max or nbins == 0
0114   /// @return a unique pointer to the axis
0115   static std::unique_ptr<IAxis> createEquidistant(
0116       AxisBoundaryType aBoundaryType, double min, double max, std::size_t nbins,
0117       std::optional<AxisDirection> direction = std::nullopt);
0118 
0119   /// Centralized axis factory for variable binning
0120   /// @param aBoundaryType the axis boundary type
0121   /// @param edges are the bin edges
0122   /// @param direction the optional direction of the axis
0123   /// @throws std::invalid_argument if edges is empty or not strictly increasing
0124   /// @return a unique pointer to the axis
0125   static std::unique_ptr<IAxis> createVariable(
0126       AxisBoundaryType aBoundaryType, const std::vector<double>& edges,
0127       std::optional<AxisDirection> direction = std::nullopt);
0128 
0129   /// Helper function that dispatches from the @c IAxis base class
0130   /// to a concrete axis type. It will call the provided @p callable
0131   /// with a const reference to the concrete axis type.
0132   /// @tparam callable_t the callable type
0133   /// @param callable the callable object
0134   /// @return the value returned by the callable
0135   template <typename callable_t>
0136   decltype(auto) visit(const callable_t& callable) const {
0137     auto switchOnType =
0138         [this, &callable]<AxisBoundaryType bdt>(AxisBoundaryTypeTag<bdt>) {
0139           switch (getType()) {
0140             using enum AxisType;
0141             case Equidistant:
0142               return callable(
0143                   dynamic_cast<const Axis<AxisType::Equidistant, bdt>&>(*this));
0144             case Variable:
0145               return callable(
0146                   dynamic_cast<const Axis<AxisType::Variable, bdt>&>(*this));
0147             default:
0148               throw std::logic_error("Unknown axis type");
0149           }
0150         };
0151 
0152     switch (getBoundaryType()) {
0153       using enum AxisBoundaryType;
0154       case Open:
0155         return switchOnType(AxisOpen);
0156       case Bound:
0157         return switchOnType(AxisBound);
0158       case Closed:
0159         return switchOnType(AxisClosed);
0160       default:
0161         throw std::logic_error("Unknown axis type");
0162     }
0163   }
0164 
0165   /// Check if two axes are equal
0166   /// @param lhs first axis
0167   /// @param rhs second axis
0168   /// @return true if the axes are equal
0169   friend bool operator==(const IAxis& lhs, const IAxis& rhs) {
0170     return lhs.getType() == rhs.getType() &&
0171            lhs.getBoundaryType() == rhs.getBoundaryType() &&
0172            lhs.getMin() == rhs.getMin() && lhs.getMax() == rhs.getMax() &&
0173            lhs.getNBins() == rhs.getNBins() &&
0174            lhs.getBinEdges() == rhs.getBinEdges();
0175   }
0176 
0177   /// Output stream operator
0178   /// @param os output stream
0179   /// @param axis the axis to be printed
0180   /// @return the output stream
0181   friend std::ostream& operator<<(std::ostream& os, const IAxis& axis) {
0182     axis.toStream(os);
0183     return os;
0184   }
0185 
0186  protected:
0187   /// Dispatch to the correct stream operator
0188   /// @param os output stream
0189   virtual void toStream(std::ostream& os) const = 0;
0190 
0191  private:
0192   std::optional<AxisDirection> m_direction;
0193 };
0194 
0195 template <typename T>
0196 concept AxisConcept = std::derived_from<T, IAxis>;
0197 
0198 }  // namespace Acts