Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-05-30 08:18:21

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 
0120 /// @brief Multi-dimensional profile histogram using boost::histogram
0121 ///
0122 /// This class wraps boost::histogram to provide a ROOT-independent profile
0123 /// histogram implementation with compile-time dimensionality. For each bin,
0124 /// it tracks the mean and variance of sample values.
0125 ///
0126 /// @tparam Dim Number of dimensions
0127 template <std::size_t Dim>
0128 class ProfileHistogram {
0129  public:
0130   /// Construct multi-dimensional profile histogram from axes
0131   ///
0132   /// @param name Histogram name (for identification and output)
0133   /// @param title Histogram title (for plotting)
0134   /// @param axes Array of axes with binning and metadata
0135   /// @param sampleAxisTitle Title for the sampled axis (profiled quantity)
0136   /// @param sampleRange Samples are discarded when outside range
0137   ProfileHistogram(std::string name, std::string title,
0138                    const std::array<AxisVariant, Dim>& axes,
0139                    std::string sampleAxisTitle,
0140                    Range1D<double> sampleRange = {})
0141       : m_name(std::move(name)),
0142         m_title(std::move(title)),
0143         m_sampleAxisTitle(std::move(sampleAxisTitle)),
0144         m_sampleRange(sampleRange),
0145         m_hist(boost::histogram::make_profile(axes.begin(), axes.end())) {}
0146 
0147   /// Fill profile with values and sample
0148   ///
0149   /// @param values Bin coordinate values (one per axis)
0150   /// @param sample Sample value (profiled quantity)
0151   void fill(const std::array<double, Dim>& values, double sample) {
0152     if (!m_sampleRange.contains(sample)) {
0153       return;
0154     }
0155 
0156     std::apply(
0157         [&](auto... v) { m_hist(v..., boost::histogram::sample(sample)); },
0158         std::tuple_cat(values));
0159   }
0160 
0161   /// Get histogram name
0162   /// @return The histogram name
0163   const std::string& name() const { return m_name; }
0164 
0165   /// Get histogram title
0166   /// @return The histogram title
0167   const std::string& title() const { return m_title; }
0168 
0169   /// Get number of dimensions (compile-time constant)
0170   /// @return The number of dimensions
0171   static constexpr std::size_t rank() { return Dim; }
0172 
0173   /// Get title of the sample axis
0174   /// @return The sample axis title
0175   const std::string& sampleAxisTitle() const { return m_sampleAxisTitle; }
0176 
0177   /// Direct access to boost::histogram (for converters and tests)
0178   /// @return The underlying boost profile histogram
0179   const BoostProfileHist& histogram() const { return m_hist; }
0180 
0181  private:
0182   std::string m_name;
0183   std::string m_title;
0184   std::string m_sampleAxisTitle;
0185   Range1D<double> m_sampleRange;
0186 
0187   BoostProfileHist m_hist;
0188 };
0189 
0190 /// Type aliases for common dimensions
0191 using ProfileHistogram1 = ProfileHistogram<1>;
0192 
0193 /// @brief Multi-dimensional efficiency histogram using boost::histogram
0194 ///
0195 /// This class tracks pass/total counts for efficiency calculation.
0196 /// It internally uses two multi-dimensional histograms: one for accepted
0197 /// events, one for total events.
0198 ///
0199 /// @tparam Dim Number of dimensions
0200 template <std::size_t Dim>
0201 class Efficiency {
0202  public:
0203   /// Construct multi-dimensional efficiency histogram
0204   ///
0205   /// @param name Histogram name
0206   /// @param title Histogram title
0207   /// @param axes Array of axes with binning and metadata
0208   Efficiency(std::string name, std::string title,
0209              const std::array<AxisVariant, Dim>& axes)
0210       : m_name(std::move(name)),
0211         m_title(std::move(title)),
0212         m_accepted(boost::histogram::make_histogram(axes.begin(), axes.end())),
0213         m_total(boost::histogram::make_histogram(axes.begin(), axes.end())) {}
0214 
0215   /// Fill efficiency histogram
0216   ///
0217   /// @param values Values to fill (one per axis)
0218   /// @param accepted Whether the event passed selection
0219   void fill(const std::array<double, Dim>& values, bool accepted) {
0220     std::apply(
0221         [&](auto... v) {
0222           m_total(v...);
0223           if (accepted) {
0224             m_accepted(v...);
0225           }
0226         },
0227         std::tuple_cat(values));
0228   }
0229 
0230   /// Get histogram name
0231   /// @return The histogram name
0232   const std::string& name() const { return m_name; }
0233 
0234   /// Get histogram title
0235   /// @return The histogram title
0236   const std::string& title() const { return m_title; }
0237 
0238   /// Get number of dimensions (compile-time constant)
0239   /// @return The histogram dimension
0240   static constexpr std::size_t rank() { return Dim; }
0241 
0242   /// Access to accepted histogram (for converters and tests)
0243   /// @return The accepted histogram
0244   const BoostHist& acceptedHistogram() const { return m_accepted; }
0245 
0246   /// Access to total histogram (for converters and tests)
0247   /// @return The total histogram
0248   const BoostHist& totalHistogram() const { return m_total; }
0249 
0250  private:
0251   std::string m_name;
0252   std::string m_title;
0253 
0254   BoostHist m_accepted;
0255   BoostHist m_total;
0256 };
0257 
0258 /// Type aliases for common dimensions
0259 using Efficiency1 = Efficiency<1>;
0260 /// 2D efficiency histogram
0261 using Efficiency2 = Efficiency<2>;
0262 
0263 /// Project a 2D histogram onto the X axis (axis 0)
0264 ///
0265 /// @param hist2d The 2D histogram to project
0266 /// @return A 1D histogram containing the projection
0267 Histogram1 projectionX(const Histogram2& hist2d);
0268 
0269 /// Project a 2D histogram onto the Y axis (axis 1)
0270 ///
0271 /// @param hist2d The 2D histogram to project
0272 /// @return A 1D histogram containing the projection
0273 Histogram1 projectionY(const Histogram2& hist2d);
0274 
0275 /// Extract bin edges from an AxisVariant
0276 ///
0277 /// Works with all axis types (regular, variable, log) in the variant by
0278 /// accessing the generic axis interface.
0279 ///
0280 /// @param axis The axis variant to extract edges from
0281 /// @return Vector of bin edges (size = nBins + 1)
0282 std::vector<double> extractBinEdges(const AxisVariant& axis);
0283 
0284 }  // namespace Acts::Experimental