Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-03-28 07:45:31

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/RangeXD.hpp"
0012 
0013 #include <array>
0014 #include <string>
0015 #include <tuple>
0016 
0017 #include <boost/histogram.hpp>
0018 
0019 namespace Acts::Experimental {
0020 
0021 /// Variable-width histogram axis with string metadata
0022 using BoostVariableAxis = boost::histogram::axis::variable<double, std::string>;
0023 /// Regular-width histogram axis with string metadata
0024 using BoostRegularAxis =
0025     boost::histogram::axis::regular<double, boost::histogram::use_default,
0026                                     std::string>;
0027 /// Logarithmic-scale histogram axis with string metadata
0028 using BoostLogAxis = boost::histogram::axis::regular<
0029     double, boost::histogram::axis::transform::log, std::string>;
0030 
0031 /// @brief Boost axis variant supporting variable, regular, and log-scale axes with metadata
0032 /// @note It seems not to be possible to combine compile-time fixed number of
0033 ///       axes with `boost::histogram::axis::variant`. Therefore we use
0034 ///       `std::vector<AxisVariant>` internally.
0035 using AxisVariant =
0036     boost::histogram::axis::variant<BoostVariableAxis, BoostRegularAxis,
0037                                     BoostLogAxis>;
0038 
0039 /// @brief Underlying Boost type for histograms
0040 using BoostHist = decltype(boost::histogram::make_histogram(
0041     std::declval<std::vector<AxisVariant>>()));
0042 
0043 /// @brief Underlying Boost type for ProfileHistogram
0044 using BoostProfileHist = decltype(boost::histogram::make_profile(
0045     std::declval<std::vector<AxisVariant>>()));
0046 
0047 /// @brief Multi-dimensional histogram wrapper using boost::histogram for data collection
0048 ///
0049 /// This class wraps boost::histogram to provide a ROOT-independent histogram
0050 /// implementation with compile-time dimensionality.
0051 ///
0052 /// @tparam Dim Number of dimensions
0053 template <std::size_t Dim>
0054 class Histogram {
0055  public:
0056   /// Construct multi-dimensional histogram from axes
0057   ///
0058   /// @param name Histogram name (for identification and output)
0059   /// @param title Histogram title (for plotting)
0060   /// @param axes Array of axes with binning and metadata
0061   Histogram(std::string name, std::string title,
0062             const std::array<AxisVariant, Dim>& axes)
0063       : m_name(std::move(name)),
0064         m_title(std::move(title)),
0065         m_hist(boost::histogram::make_histogram(axes.begin(), axes.end())) {}
0066 
0067   /// Copy constructor
0068   /// @param other The other histogram to copy from
0069   Histogram(const Histogram& other) = default;
0070 
0071   /// Move constructor
0072   /// @param other The other histogram to move from
0073   Histogram(Histogram&& other) noexcept = default;
0074 
0075   /// Copy assignment operator
0076   /// @param other The other histogram to copy from
0077   /// @return The copied histogram
0078   Histogram& operator=(const Histogram& other) = default;
0079 
0080   /// Move assignment operator
0081   /// @param other The other histogram to move from
0082   /// @return The moved histogram
0083   Histogram& operator=(Histogram&& other) noexcept = default;
0084 
0085   /// Fill histogram with values
0086   ///
0087   /// @param values Values to fill (one per axis)
0088   void fill(const std::array<double, Dim>& values) {
0089     std::apply([this](auto... v) { m_hist(v...); }, std::tuple_cat(values));
0090   }
0091 
0092   /// Get histogram name
0093   /// @return The histogram name
0094   const std::string& name() const { return m_name; }
0095 
0096   /// Get histogram title
0097   /// @return The histogram title
0098   const std::string& title() const { return m_title; }
0099 
0100   /// Get number of dimensions (compile-time constant)
0101   /// @return The number of dimensions
0102   static constexpr std::size_t rank() { return Dim; }
0103 
0104   /// Direct access to boost::histogram (for converters and tests)
0105   /// @return The underlying boost histogram
0106   const BoostHist& histogram() const { return m_hist; }
0107 
0108  private:
0109   std::string m_name;
0110   std::string m_title;
0111 
0112   BoostHist m_hist;
0113 };
0114 
0115 /// Type aliases for common dimensions
0116 using Histogram1 = Histogram<1>;
0117 /// 2D histogram
0118 using Histogram2 = Histogram<2>;
0119 /// 3D histogram
0120 using Histogram3 = Histogram<3>;
0121 
0122 /// @brief Multi-dimensional profile histogram using boost::histogram
0123 ///
0124 /// This class wraps boost::histogram to provide a ROOT-independent profile
0125 /// histogram implementation with compile-time dimensionality. For each bin,
0126 /// it tracks the mean and variance of sample values.
0127 ///
0128 /// @tparam Dim Number of dimensions
0129 template <std::size_t Dim>
0130 class ProfileHistogram {
0131  public:
0132   /// Construct multi-dimensional profile histogram from axes
0133   ///
0134   /// @param name Histogram name (for identification and output)
0135   /// @param title Histogram title (for plotting)
0136   /// @param axes Array of axes with binning and metadata
0137   /// @param sampleAxisTitle Title for the sampled axis (profiled quantity)
0138   /// @param sampleRange Samples are discarded when outside range
0139   ProfileHistogram(std::string name, std::string title,
0140                    const std::array<AxisVariant, Dim>& axes,
0141                    std::string sampleAxisTitle,
0142                    Range1D<double> sampleRange = {})
0143       : m_name(std::move(name)),
0144         m_title(std::move(title)),
0145         m_sampleAxisTitle(std::move(sampleAxisTitle)),
0146         m_sampleRange(sampleRange),
0147         m_hist(boost::histogram::make_profile(axes.begin(), axes.end())) {}
0148 
0149   /// Fill profile with values and sample
0150   ///
0151   /// @param values Bin coordinate values (one per axis)
0152   /// @param sample Sample value (profiled quantity)
0153   void fill(const std::array<double, Dim>& values, double sample) {
0154     if (!m_sampleRange.contains(sample)) {
0155       return;
0156     }
0157 
0158     std::apply(
0159         [&](auto... v) { m_hist(v..., boost::histogram::sample(sample)); },
0160         std::tuple_cat(values));
0161   }
0162 
0163   /// Get histogram name
0164   /// @return The histogram name
0165   const std::string& name() const { return m_name; }
0166 
0167   /// Get histogram title
0168   /// @return The histogram title
0169   const std::string& title() const { return m_title; }
0170 
0171   /// Get number of dimensions (compile-time constant)
0172   /// @return The number of dimensions
0173   static constexpr std::size_t rank() { return Dim; }
0174 
0175   /// Get title of the sample axis
0176   /// @return The sample axis title
0177   const std::string& sampleAxisTitle() const { return m_sampleAxisTitle; }
0178 
0179   /// Direct access to boost::histogram (for converters and tests)
0180   /// @return The underlying boost profile histogram
0181   const BoostProfileHist& histogram() const { return m_hist; }
0182 
0183  private:
0184   std::string m_name;
0185   std::string m_title;
0186   std::string m_sampleAxisTitle;
0187   Range1D<double> m_sampleRange;
0188 
0189   BoostProfileHist m_hist;
0190 };
0191 
0192 /// Type aliases for common dimensions
0193 using ProfileHistogram1 = ProfileHistogram<1>;
0194 
0195 /// @brief Multi-dimensional efficiency histogram using boost::histogram
0196 ///
0197 /// This class tracks pass/total counts for efficiency calculation.
0198 /// It internally uses two multi-dimensional histograms: one for accepted
0199 /// events, one for total events.
0200 ///
0201 /// @tparam Dim Number of dimensions
0202 template <std::size_t Dim>
0203 class Efficiency {
0204  public:
0205   /// Construct multi-dimensional efficiency histogram
0206   ///
0207   /// @param name Histogram name
0208   /// @param title Histogram title
0209   /// @param axes Array of axes with binning and metadata
0210   Efficiency(std::string name, std::string title,
0211              const std::array<AxisVariant, Dim>& axes)
0212       : m_name(std::move(name)),
0213         m_title(std::move(title)),
0214         m_accepted(boost::histogram::make_histogram(axes.begin(), axes.end())),
0215         m_total(boost::histogram::make_histogram(axes.begin(), axes.end())) {}
0216 
0217   /// Fill efficiency histogram
0218   ///
0219   /// @param values Values to fill (one per axis)
0220   /// @param accepted Whether the event passed selection
0221   void fill(const std::array<double, Dim>& values, bool accepted) {
0222     std::apply(
0223         [&](auto... v) {
0224           m_total(v...);
0225           if (accepted) {
0226             m_accepted(v...);
0227           }
0228         },
0229         std::tuple_cat(values));
0230   }
0231 
0232   /// Get histogram name
0233   /// @return The histogram name
0234   const std::string& name() const { return m_name; }
0235 
0236   /// Get histogram title
0237   /// @return The histogram title
0238   const std::string& title() const { return m_title; }
0239 
0240   /// Get number of dimensions (compile-time constant)
0241   /// @return The histogram dimension
0242   static constexpr std::size_t rank() { return Dim; }
0243 
0244   /// Access to accepted histogram (for converters and tests)
0245   /// @return The accepted histogram
0246   const BoostHist& acceptedHistogram() const { return m_accepted; }
0247 
0248   /// Access to total histogram (for converters and tests)
0249   /// @return The total histogram
0250   const BoostHist& totalHistogram() const { return m_total; }
0251 
0252  private:
0253   std::string m_name;
0254   std::string m_title;
0255 
0256   BoostHist m_accepted;
0257   BoostHist m_total;
0258 };
0259 
0260 /// Type aliases for common dimensions
0261 using Efficiency1 = Efficiency<1>;
0262 /// 2D efficiency histogram
0263 using Efficiency2 = Efficiency<2>;
0264 
0265 /// Project a 2D histogram onto the X axis (axis 0)
0266 ///
0267 /// @param hist2d The 2D histogram to project
0268 /// @return A 1D histogram containing the projection
0269 Histogram1 projectionX(const Histogram2& hist2d);
0270 
0271 /// Project a 2D histogram onto the Y axis (axis 1)
0272 ///
0273 /// @param hist2d The 2D histogram to project
0274 /// @return A 1D histogram containing the projection
0275 Histogram1 projectionY(const Histogram2& hist2d);
0276 
0277 /// Extract bin edges from an AxisVariant
0278 ///
0279 /// Works with all axis types (regular, variable, log) in the variant by
0280 /// accessing the generic axis interface.
0281 ///
0282 /// @param axis The axis variant to extract edges from
0283 /// @return Vector of bin edges (size = nBins + 1)
0284 std::vector<double> extractBinEdges(const AxisVariant& axis);
0285 
0286 }  // namespace Acts::Experimental