Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-08-16 09:21:12

0001 /// \file
0002 /// \warning This is part of the %ROOT 7 prototype! It will change without notice. It might trigger earthquakes.
0003 /// Feedback is welcome!
0004 
0005 #ifndef ROOT_RAxisVariant
0006 #define ROOT_RAxisVariant
0007 
0008 #include "RCategoricalAxis.hxx"
0009 #include "RRegularAxis.hxx"
0010 #include "RVariableBinAxis.hxx"
0011 
0012 #include <cstdint>
0013 #include <stdexcept>
0014 #include <utility>
0015 #include <variant>
0016 
0017 class TBuffer;
0018 
0019 namespace ROOT {
0020 namespace Experimental {
0021 
0022 /**
0023 A variant of all supported axis types.
0024 
0025 This class provides easy access to the contained axis object and dispatching methods for common accessors.
0026 
0027 \warning This is part of the %ROOT 7 prototype! It will change without notice. It might trigger earthquakes.
0028 Feedback is welcome!
0029 */
0030 class RAxisVariant final {
0031 public:
0032    using VariantType = std::variant<RRegularAxis, RVariableBinAxis, RCategoricalAxis>;
0033 
0034 private:
0035    VariantType fVariant;
0036 
0037 public:
0038    RAxisVariant(VariantType axis) : fVariant(std::move(axis)) {}
0039    RAxisVariant(RRegularAxis axis) : fVariant(std::move(axis)) {}
0040    RAxisVariant(RVariableBinAxis axis) : fVariant(std::move(axis)) {}
0041    RAxisVariant(RCategoricalAxis axis) : fVariant(std::move(axis)) {}
0042 
0043    const VariantType &GetVariant() const { return fVariant; }
0044 
0045    /// \return the RRegularAxis or nullptr, if this variant stores a different axis type
0046    const RRegularAxis *GetRegularAxis() const { return std::get_if<RRegularAxis>(&fVariant); }
0047    /// \return the RVariableBinAxis or nullptr, if this variant stores a different axis type
0048    const RVariableBinAxis *GetVariableBinAxis() const { return std::get_if<RVariableBinAxis>(&fVariant); }
0049    /// \return the RCategoricalAxis or nullptr, if this variant stores a different axis type
0050    const RCategoricalAxis *GetCategoricalAxis() const { return std::get_if<RCategoricalAxis>(&fVariant); }
0051 
0052    std::uint64_t GetNNormalBins() const
0053    {
0054       if (auto *regular = GetRegularAxis()) {
0055          return regular->GetNNormalBins();
0056       } else if (auto *variable = GetVariableBinAxis()) {
0057          return variable->GetNNormalBins();
0058       } else if (auto *categorical = GetCategoricalAxis()) {
0059          return categorical->GetNNormalBins();
0060       } else {
0061          throw std::logic_error("unimplemented axis type"); // GCOVR_EXCL_LINE
0062       }
0063    }
0064 
0065    std::uint64_t GetTotalNBins() const
0066    {
0067       if (auto *regular = GetRegularAxis()) {
0068          return regular->GetTotalNBins();
0069       } else if (auto *variable = GetVariableBinAxis()) {
0070          return variable->GetTotalNBins();
0071       } else if (auto *categorical = GetCategoricalAxis()) {
0072          return categorical->GetTotalNBins();
0073       } else {
0074          throw std::logic_error("unimplemented axis type"); // GCOVR_EXCL_LINE
0075       }
0076    }
0077 
0078    /// Get the range of all normal bins.
0079    ///
0080    /// \return the bin index range from the first to the last normal bin, inclusive
0081    RBinIndexRange GetNormalRange() const
0082    {
0083       if (auto *regular = GetRegularAxis()) {
0084          return regular->GetNormalRange();
0085       } else if (auto *variable = GetVariableBinAxis()) {
0086          return variable->GetNormalRange();
0087       } else if (auto *categorical = GetCategoricalAxis()) {
0088          return categorical->GetNormalRange();
0089       } else {
0090          throw std::logic_error("unimplemented axis type"); // GCOVR_EXCL_LINE
0091       }
0092    }
0093 
0094    /// Get a range of normal bins.
0095    ///
0096    /// \param[in] begin the begin of the bin index range (inclusive), must be normal
0097    /// \param[in] end the end of the bin index range (exclusive), must be normal and >= begin
0098    /// \return a bin index range \f$[begin, end)\f$
0099    RBinIndexRange GetNormalRange(RBinIndex begin, RBinIndex end) const
0100    {
0101       if (auto *regular = GetRegularAxis()) {
0102          return regular->GetNormalRange(begin, end);
0103       } else if (auto *variable = GetVariableBinAxis()) {
0104          return variable->GetNormalRange(begin, end);
0105       } else if (auto *categorical = GetCategoricalAxis()) {
0106          return categorical->GetNormalRange(begin, end);
0107       } else {
0108          throw std::logic_error("unimplemented axis type"); // GCOVR_EXCL_LINE
0109       }
0110    }
0111 
0112    /// Get the full range of all bins.
0113    ///
0114    /// This includes underflow and overflow bins, if enabled.
0115    ///
0116    /// \return the bin index range of all bins
0117    RBinIndexRange GetFullRange() const
0118    {
0119       if (auto *regular = GetRegularAxis()) {
0120          return regular->GetFullRange();
0121       } else if (auto *variable = GetVariableBinAxis()) {
0122          return variable->GetFullRange();
0123       } else if (auto *categorical = GetCategoricalAxis()) {
0124          return categorical->GetFullRange();
0125       } else {
0126          throw std::logic_error("unimplemented axis type"); // GCOVR_EXCL_LINE
0127       }
0128    }
0129 
0130    /// Slice this axis according to the specification.
0131    ///
0132    /// Axes throw exceptions if the slicing cannot be performed. For example, the rebin operation must divide the
0133    /// number of normal bins for RRegularAxis and RVariableBinAxis, while RCategoricalAxis cannot be sliced at all.
0134    ///
0135    /// \param[in] sliceSpec the slice specification
0136    /// \return the sliced axis
0137    RAxisVariant Slice(const RSliceSpec &sliceSpec) const
0138    {
0139       if (auto *regular = GetRegularAxis()) {
0140          return regular->Slice(sliceSpec);
0141       } else if (auto *variable = GetVariableBinAxis()) {
0142          return variable->Slice(sliceSpec);
0143       } else if (auto *categorical = GetCategoricalAxis()) {
0144          return categorical->Slice(sliceSpec);
0145       } else {
0146          throw std::logic_error("unimplemented axis type"); // GCOVR_EXCL_LINE
0147       }
0148    }
0149 
0150    friend bool operator==(const RAxisVariant &lhs, const RAxisVariant &rhs) { return lhs.fVariant == rhs.fVariant; }
0151 
0152    /// %ROOT Streamer function to throw when trying to store an object of this class.
0153    void Streamer(TBuffer &) { throw std::runtime_error("unable to store RAxisVariant"); }
0154 };
0155 
0156 } // namespace Experimental
0157 } // namespace ROOT
0158 
0159 #endif