|
|
|||
File indexing completed on 2026-09-17 09:29:18
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_RHist 0006 #define ROOT_RHist 0007 0008 #include "RAxisVariant.hxx" 0009 #include "RBinIndex.hxx" 0010 #include "RBinIndexMultiDimRange.hxx" 0011 #include "RCategoricalAxis.hxx" 0012 #include "RHistEngine.hxx" 0013 #include "RHistStats.hxx" 0014 #include "RRegularAxis.hxx" 0015 #include "RWeight.hxx" 0016 0017 #include <array> 0018 #include <cstddef> 0019 #include <cstdint> 0020 #include <stdexcept> 0021 #include <tuple> 0022 #include <utility> 0023 #include <variant> 0024 #include <vector> 0025 0026 class TBuffer; 0027 0028 namespace ROOT { 0029 namespace Experimental { 0030 0031 // forward declaration for friend declaration 0032 template <typename BinContentType> 0033 class RHistFillContext; 0034 0035 /** 0036 A histogram for aggregation of data along multiple dimensions. 0037 0038 Every call to \ref Fill(const A &... args) "Fill" increments the bin content and is reflected in global statistics: 0039 \code 0040 ROOT::Experimental::RHist<int> hist(10, {5, 15}); 0041 hist.Fill(8.5); 0042 // hist.GetBinContent(ROOT::Experimental::RBinIndex(3)) will return 1 0043 \endcode 0044 0045 The class is templated on the bin content type. For counting, as in the example above, it may be an integral type such 0046 as `int` or `long`. Narrower types such as `unsigned char` or `short` are supported, but may overflow due to their 0047 limited range and must be used with care. For weighted filling, the bin content type must not be an integral type, but 0048 a floating-point type such as `float` or `double`, or the special type RBinWithError. Note that `float` has a limited 0049 significand precision of 24 bits. 0050 0051 An object can have arbitrary dimensionality determined at run-time. The axis configuration is passed as a vector of 0052 RAxisVariant: 0053 \code 0054 std::vector<ROOT::Experimental::RAxisVariant> axes; 0055 axes.push_back(ROOT::Experimental::RRegularAxis(10, {5, 15})); 0056 axes.push_back(ROOT::Experimental::RVariableBinAxis({1, 10, 100, 1000})); 0057 ROOT::Experimental::RHist<int> hist(axes); 0058 // hist.GetNDimensions() will return 2 0059 \endcode 0060 0061 \warning This is part of the %ROOT 7 prototype! It will change without notice. It might trigger earthquakes. 0062 Feedback is welcome! 0063 */ 0064 template <typename BinContentType> 0065 class RHist final { 0066 // For conversion, all other template instantiations must be a friend. 0067 template <typename U> 0068 friend class RHist; 0069 0070 friend class RHistFillContext<BinContentType>; 0071 0072 /// The histogram engine including the bin contents. 0073 RHistEngine<BinContentType> fEngine; 0074 /// The global histogram statistics. 0075 RHistStats fStats; 0076 0077 /// Private constructor based off an engine. 0078 RHist(RHistEngine<BinContentType> engine) : fEngine(std::move(engine)), fStats(fEngine.GetNDimensions()) {} 0079 0080 public: 0081 /// Construct a histogram. 0082 /// 0083 /// \param[in] axes the axis objects, must have size > 0 0084 explicit RHist(std::vector<RAxisVariant> axes) : fEngine(std::move(axes)), fStats(fEngine.GetNDimensions()) 0085 { 0086 // The axes parameter was moved, use from the engine. 0087 const auto &engineAxes = fEngine.GetAxes(); 0088 for (std::size_t i = 0; i < engineAxes.size(); i++) { 0089 if (engineAxes[i].GetCategoricalAxis() != nullptr) { 0090 fStats.DisableDimension(i); 0091 } 0092 } 0093 } 0094 0095 /// Construct a histogram. 0096 /// 0097 /// Note that there is no perfect forwarding of the axis objects. If that is needed, use the 0098 /// \ref RHist(std::vector<RAxisVariant> axes) "overload accepting a std::vector". 0099 /// 0100 /// \param[in] axes the axis objects, must have size > 0 0101 explicit RHist(std::initializer_list<RAxisVariant> axes) : RHist(std::vector(axes)) {} 0102 0103 /// Construct a histogram. 0104 /// 0105 /// Note that there is no perfect forwarding of the axis objects. If that is needed, use the 0106 /// \ref RHist(std::vector<RAxisVariant> axes) "overload accepting a std::vector". 0107 /// 0108 /// \param[in] axis1 the first axis object 0109 /// \param[in] axes the remaining axis objects 0110 template <typename... Axes> 0111 explicit RHist(const RAxisVariant &axis1, const Axes &...axes) : RHist(std::vector<RAxisVariant>{axis1, axes...}) 0112 { 0113 } 0114 0115 /// Construct a one-dimensional histogram with a regular axis. 0116 /// 0117 /// \param[in] nNormalBins the number of normal bins, must be > 0 0118 /// \param[in] interval the axis interval (lower end inclusive, upper end exclusive) 0119 /// \par See also 0120 /// the \ref RRegularAxis::RRegularAxis(std::uint64_t nNormalBins, std::pair<double, double> interval, bool 0121 /// enableFlowBins) "constructor of RRegularAxis" 0122 RHist(std::uint64_t nNormalBins, std::pair<double, double> interval) 0123 : RHist(std::vector<RAxisVariant>{RRegularAxis(nNormalBins, interval)}) 0124 { 0125 } 0126 0127 /// The copy constructor is deleted. 0128 /// 0129 /// Copying all bin contents can be an expensive operation, depending on the number of bins. If required, users can 0130 /// explicitly call Clone(). 0131 RHist(const RHist &) = delete; 0132 /// Efficiently move construct a histogram. 0133 /// 0134 /// After this operation, the moved-from object is invalid. 0135 RHist(RHist &&) = default; 0136 0137 /// The copy assignment operator is deleted. 0138 /// 0139 /// Copying all bin contents can be an expensive operation, depending on the number of bins. If required, users can 0140 /// explicitly call Clone(). 0141 RHist &operator=(const RHist &) = delete; 0142 /// Efficiently move a histogram. 0143 /// 0144 /// After this operation, the moved-from object is invalid. 0145 RHist &operator=(RHist &&) = default; 0146 0147 ~RHist() = default; 0148 0149 /// \name Accessors 0150 /// \{ 0151 0152 const RHistEngine<BinContentType> &GetEngine() const { return fEngine; } 0153 const RHistStats &GetStats() const { return fStats; } 0154 0155 const std::vector<RAxisVariant> &GetAxes() const { return fEngine.GetAxes(); } 0156 std::size_t GetNDimensions() const { return fEngine.GetNDimensions(); } 0157 std::uint64_t GetTotalNBins() const { return fEngine.GetTotalNBins(); } 0158 0159 std::uint64_t GetNEntries() const { return fStats.GetNEntries(); } 0160 0161 /// \} 0162 /// \name Computations 0163 /// \{ 0164 0165 /// \copydoc RHistStats::ComputeNEffectiveEntries() 0166 double ComputeNEffectiveEntries() const { return fStats.ComputeNEffectiveEntries(); } 0167 /// \copydoc RHistStats::ComputeMean() 0168 double ComputeMean(std::size_t dim = 0) const { return fStats.ComputeMean(dim); } 0169 /// \copydoc RHistStats::ComputeStdDev() 0170 double ComputeStdDev(std::size_t dim = 0) const { return fStats.ComputeStdDev(dim); } 0171 0172 /// \} 0173 /// \name Accessors 0174 /// \{ 0175 0176 /// Get the content of a single bin. 0177 /// 0178 /// \code 0179 /// ROOT::Experimental::RHist<int> hist({/* two dimensions */}); 0180 /// std::array<ROOT::Experimental::RBinIndex, 2> indices = {3, 5}; 0181 /// int content = hist.GetBinContent(indices); 0182 /// \endcode 0183 /// 0184 /// \note Compared to TH1 conventions, the first normal bin has index 0 and underflow and overflow bins are special 0185 /// values. See also the class documentation of RBinIndex. 0186 /// 0187 /// Throws an exception if the number of indices does not match the axis configuration or the bin is not found. 0188 /// 0189 /// \param[in] indices the array of indices for each axis 0190 /// \return the bin content 0191 /// \par See also 0192 /// the \ref GetBinContent(const A &... args) const "variadic function template overload" accepting arguments 0193 /// directly 0194 template <std::size_t N> 0195 const BinContentType &GetBinContent(const std::array<RBinIndex, N> &indices) const 0196 { 0197 return fEngine.GetBinContent(indices); 0198 } 0199 0200 /// Get the content of a single bin. 0201 /// 0202 /// \code 0203 /// ROOT::Experimental::RHist<int> hist({/* two dimensions */}); 0204 /// std::vector<ROOT::Experimental::RBinIndex> indices = {3, 5}; 0205 /// int content = hist.GetBinContent(indices); 0206 /// \endcode 0207 /// 0208 /// \note Compared to TH1 conventions, the first normal bin has index 0 and underflow and overflow bins are special 0209 /// values. See also the class documentation of RBinIndex. 0210 /// 0211 /// Throws an exception if the number of indices does not match the axis configuration or the bin is not found. 0212 /// 0213 /// \param[in] indices the array of indices for each axis 0214 /// \return the bin content 0215 /// \par See also 0216 /// the \ref GetBinContent(const A &... args) const "variadic function template overload" accepting arguments 0217 /// directly 0218 const BinContentType &GetBinContent(const std::vector<RBinIndex> &indices) const 0219 { 0220 return fEngine.GetBinContent(indices); 0221 } 0222 0223 /// Get the content of a single bin. 0224 /// 0225 /// \code 0226 /// ROOT::Experimental::RHist<int> hist({/* two dimensions */}); 0227 /// int content = hist.GetBinContent(ROOT::Experimental::RBinIndex(3), ROOT::Experimental::RBinIndex(5)); 0228 /// // ... or construct the RBinIndex arguments implicitly from integers: 0229 /// content = hist.GetBinContent(3, 5); 0230 /// \endcode 0231 /// 0232 /// \note Compared to TH1 conventions, the first normal bin has index 0 and underflow and overflow bins are special 0233 /// values. See also the class documentation of RBinIndex. 0234 /// 0235 /// Throws an exception if the number of arguments does not match the axis configuration or the bin is not found. 0236 /// 0237 /// \param[in] args the arguments for each axis 0238 /// \return the bin content 0239 /// \par See also 0240 /// the function overloads accepting \ref GetBinContent(const std::array<RBinIndex, N> &indices) const "`std::array`" 0241 /// or \ref GetBinContent(const std::vector<RBinIndex> &indices) const "`std::vector`" 0242 template <typename... A> 0243 const BinContentType &GetBinContent(const A &...args) const 0244 { 0245 return fEngine.GetBinContent(args...); 0246 } 0247 0248 /// Get the multidimensional range of all bins. 0249 /// 0250 /// \return the multidimensional range 0251 RBinIndexMultiDimRange GetFullMultiDimRange() const { return fEngine.GetFullMultiDimRange(); } 0252 0253 /// Set the content of a single bin. 0254 /// 0255 /// \code 0256 /// ROOT::Experimental::RHist<int> hist({/* two dimensions */}); 0257 /// std::array<ROOT::Experimental::RBinIndex, 2> indices = {3, 5}; 0258 /// int value = /* ... */; 0259 /// hist.SetBinContent(indices, value); 0260 /// \endcode 0261 /// 0262 /// \note Compared to TH1 conventions, the first normal bin has index 0 and underflow and overflow bins are special 0263 /// values. See also the class documentation of RBinIndex. 0264 /// 0265 /// Throws an exception if the number of indices does not match the axis configuration or the bin is not found. 0266 /// 0267 /// \warning Setting the bin content will taint the global histogram statistics. Attempting to access its values, for 0268 /// example calling GetNEntries(), will throw exceptions. 0269 /// 0270 /// \param[in] indices the array of indices for each axis 0271 /// \param[in] value the new value of the bin content 0272 /// \par See also 0273 /// the \ref SetBinContent(const A &... args) "variadic function template overload" accepting arguments directly 0274 template <std::size_t N, typename V> 0275 void SetBinContent(const std::array<RBinIndex, N> &indices, const V &value) 0276 { 0277 fEngine.SetBinContent(indices, value); 0278 fStats.Taint(); 0279 } 0280 0281 /// Set the content of a single bin. 0282 /// 0283 /// \code 0284 /// ROOT::Experimental::RHist<int> hist({/* two dimensions */}); 0285 /// int value = /* ... */; 0286 /// hist.SetBinContent(ROOT::Experimental::RBinIndex(3), ROOT::Experimental::RBinIndex(5), value); 0287 /// // ... or construct the RBinIndex arguments implicitly from integers: 0288 /// hist.SetBinContent(3, 5, value); 0289 /// \endcode 0290 /// 0291 /// \note Compared to TH1 conventions, the first normal bin has index 0 and underflow and overflow bins are special 0292 /// values. See also the class documentation of RBinIndex. 0293 /// 0294 /// Throws an exception if the number of arguments does not match the axis configuration or the bin is not found. 0295 /// 0296 /// \warning Setting the bin content will taint the global histogram statistics. Attempting to access its values, for 0297 /// example calling GetNEntries(), will throw exceptions. 0298 /// 0299 /// \param[in] args the arguments for each axis and the new value of the bin content 0300 /// \par See also 0301 /// the \ref SetBinContent(const std::array<RBinIndex, N> &indices, const V &value) "function overload" accepting 0302 /// `std::array` 0303 template <typename... A> 0304 void SetBinContent(const A &...args) 0305 { 0306 fEngine.SetBinContent(args...); 0307 fStats.Taint(); 0308 } 0309 0310 /// \} 0311 /// \name Filling 0312 /// \{ 0313 0314 /// Fill an entry into the histogram. 0315 /// 0316 /// \code 0317 /// ROOT::Experimental::RHist<int> hist({/* two dimensions */}); 0318 /// auto args = std::make_tuple(8.5, 10.5); 0319 /// hist.Fill(args); 0320 /// \endcode 0321 /// 0322 /// If one of the arguments is outside the corresponding axis and flow bins are disabled, the entry will be silently 0323 /// discarded. 0324 /// 0325 /// Throws an exception if the number of arguments does not match the axis configuration, or if an argument cannot be 0326 /// converted for the axis type at run-time. 0327 /// 0328 /// \param[in] args the arguments for each axis 0329 /// \par See also 0330 /// the \ref Fill(const A &... args) "variadic function template overload" accepting arguments directly and the 0331 /// \ref Fill(const std::tuple<A...> &args, RWeight weight) "overload for weighted filling" 0332 template <typename... A> 0333 void Fill(const std::tuple<A...> &args) 0334 { 0335 fEngine.Fill(args); 0336 fStats.Fill(args); 0337 } 0338 0339 /// Fill an entry into the histogram with a weight. 0340 /// 0341 /// This overload is not available for integral bin content types (see \ref RHistEngine::SupportsWeightedFilling). 0342 /// 0343 /// \code 0344 /// ROOT::Experimental::RHist<float> hist({/* two dimensions */}); 0345 /// auto args = std::make_tuple(8.5, 10.5); 0346 /// hist.Fill(args, ROOT::Experimental::RWeight(0.8)); 0347 /// \endcode 0348 /// 0349 /// If one of the arguments is outside the corresponding axis and flow bins are disabled, the entry will be silently 0350 /// discarded. 0351 /// 0352 /// Throws an exception if the number of arguments does not match the axis configuration, or if an argument cannot be 0353 /// converted for the axis type at run-time. 0354 /// 0355 /// \param[in] args the arguments for each axis 0356 /// \param[in] weight the weight for this entry 0357 /// \par See also 0358 /// the \ref Fill(const A &... args) "variadic function template overload" accepting arguments directly and the 0359 /// \ref Fill(const std::tuple<A...> &args) "overload for unweighted filling" 0360 template <typename... A> 0361 void Fill(const std::tuple<A...> &args, RWeight weight) 0362 { 0363 fEngine.Fill(args, weight); 0364 fStats.Fill(args, weight); 0365 } 0366 0367 /// Fill an entry into the histogram. 0368 /// 0369 /// \code 0370 /// ROOT::Experimental::RHist<int> hist({/* two dimensions */}); 0371 /// hist.Fill(8.5, 10.5); 0372 /// \endcode 0373 /// 0374 /// For weighted filling, pass an RWeight as the last argument: 0375 /// \code 0376 /// ROOT::Experimental::RHist<float> hist({/* two dimensions */}); 0377 /// hist.Fill(8.5, 10.5, ROOT::Experimental::RWeight(0.8)); 0378 /// \endcode 0379 /// This is not available for integral bin content types (see \ref RHistEngine::SupportsWeightedFilling). 0380 /// 0381 /// If one of the arguments is outside the corresponding axis and flow bins are disabled, the entry will be silently 0382 /// discarded. 0383 /// 0384 /// Throws an exception if the number of arguments does not match the axis configuration, or if an argument cannot be 0385 /// converted for the axis type at run-time. 0386 /// 0387 /// \param[in] args the arguments for each axis 0388 /// \par See also 0389 /// the function overloads accepting `std::tuple` \ref Fill(const std::tuple<A...> &args) "for unweighted filling" 0390 /// and \ref Fill(const std::tuple<A...> &args, RWeight) "for weighted filling" 0391 template <typename... A> 0392 void Fill(const A &...args) 0393 { 0394 static_assert(sizeof...(A) >= 1, "need at least one argument to Fill"); 0395 if constexpr (sizeof...(A) >= 1) { 0396 fEngine.Fill(args...); 0397 fStats.Fill(args...); 0398 } 0399 } 0400 0401 /// \} 0402 /// \name Operations 0403 /// \{ 0404 0405 /// Add all bin contents and statistics of another histogram. 0406 /// 0407 /// Throws an exception if the axes configurations are not identical. 0408 /// 0409 /// \param[in] other another histogram 0410 void Add(const RHist &other) 0411 { 0412 fEngine.Add(other.fEngine); 0413 fStats.Add(other.fStats); 0414 } 0415 0416 /// Add all bin contents and statistics of another histogram using atomic instructions. 0417 /// 0418 /// Throws an exception if the axes configurations are not identical. 0419 /// 0420 /// \param[in] other another histogram that must not be modified during the operation 0421 void AddAtomic(const RHist &other) 0422 { 0423 fEngine.AddAtomic(other.fEngine); 0424 fStats.AddAtomic(other.fStats); 0425 } 0426 0427 /// Clear all bin contents and statistics. 0428 void Clear() 0429 { 0430 fEngine.Clear(); 0431 fStats.Clear(); 0432 } 0433 0434 /// Clone this histogram. 0435 /// 0436 /// Copying all bin contents can be an expensive operation, depending on the number of bins. 0437 /// 0438 /// \return the cloned object 0439 RHist Clone() const 0440 { 0441 RHist h(fEngine.Clone()); 0442 h.fStats = fStats; 0443 return h; 0444 } 0445 0446 /// Convert this histogram to a different bin content type. 0447 /// 0448 /// There is no bounds checking to make sure that the converted values can be represented. Note that it is not 0449 /// possible to convert to RBinWithError since the information about individual weights has been lost since filling. 0450 /// 0451 /// Converting all bin contents can be an expensive operation, depending on the number of bins. 0452 /// 0453 /// \return the converted object 0454 template <typename U> 0455 RHist<U> Convert() const 0456 { 0457 RHist<U> h(fEngine.template Convert<U>()); 0458 h.fStats = fStats; 0459 return h; 0460 } 0461 0462 /// Scale all histogram bin contents and statistics. 0463 /// 0464 /// This method is not available for integral bin content types. 0465 /// 0466 /// \param[in] factor the scale factor 0467 void Scale(double factor) 0468 { 0469 fEngine.Scale(factor); 0470 fStats.Scale(factor); 0471 } 0472 0473 /// Slice this histogram with an RSliceSpec per dimension. 0474 /// 0475 /// With a range, only the specified bins are retained. All other bin contents are transferred to the underflow and 0476 /// overflow bins: 0477 /// \code 0478 /// ROOT::Experimental::RHist<int> hist(/* one dimension */); 0479 /// // Fill the histogram with a number of entries... 0480 /// auto sliced = hist.Slice({hist.GetAxes()[0].GetNormalRange(1, 5)}); 0481 /// // The returned histogram will have 4 normal bins, an underflow and an overflow bin. 0482 /// \endcode 0483 /// 0484 /// Slicing can also perform operations per dimension, see RSliceSpec. RSliceSpec::ROperationRebin allows to rebin 0485 /// the histogram axis, grouping a number of normal bins into a new one: 0486 /// \code 0487 /// ROOT::Experimental::RHist<int> hist(/* one dimension */); 0488 /// // Fill the histogram with a number of entries... 0489 /// auto rebinned = hist.Slice(ROOT::Experimental::RSliceSpec::ROperationRebin(2)); 0490 /// // The returned histogram has groups of two normal bins merged. 0491 /// \endcode 0492 /// 0493 /// RSliceSpec::ROperationSum sums the bin contents along that axis, which allows to project to a lower-dimensional 0494 /// histogram: 0495 /// \code 0496 /// ROOT::Experimental::RHist<int> hist({/* two dimensions */}); 0497 /// // Fill the histogram with a number of entries... 0498 /// auto projected = hist.Slice(ROOT::Experimental::RSliceSpec{}, ROOT::Experimental::RSliceSpec::ROperationSum{}); 0499 /// // The returned histogram has one dimension, with bin contents summed along the second axis. 0500 /// \endcode 0501 /// Note that it is not allowed to sum along all histogram axes because the return value would be a scalar. 0502 /// 0503 /// Ranges and operations can be combined. In that case, the range is applied before the operation. 0504 /// 0505 /// \warning Combining a range and the sum operation drops bin contents, which will taint the global histogram 0506 /// statistics. Attempting to access its values, for example calling GetNEntries(), will throw exceptions. 0507 /// 0508 /// \param[in] sliceSpecs the slice specifications for each axis 0509 /// \return the sliced histogram 0510 /// \par See also 0511 /// the \ref Slice(const A &... args) const "variadic function template overload" accepting arguments directly 0512 RHist Slice(const std::vector<RSliceSpec> &sliceSpecs) const 0513 { 0514 bool dropped = false; 0515 RHist sliced(fEngine.SliceImpl(sliceSpecs, dropped)); 0516 assert(sliced.fStats.GetNDimensions() == sliced.GetNDimensions()); 0517 if (dropped || fStats.IsTainted()) { 0518 sliced.fStats.Taint(); 0519 } else { 0520 sliced.fStats.fNEntries = fStats.fNEntries; 0521 sliced.fStats.fSumW = fStats.fSumW; 0522 sliced.fStats.fSumW2 = fStats.fSumW2; 0523 std::size_t slicedDim = 0; 0524 for (std::size_t i = 0; i < sliceSpecs.size(); i++) { 0525 // A sum operation makes the dimension disappear. 0526 if (sliceSpecs[i].GetOperationSum() == nullptr) { 0527 sliced.fStats.fDimensionStats[slicedDim] = fStats.fDimensionStats[i]; 0528 slicedDim++; 0529 } 0530 } 0531 assert(slicedDim == sliced.GetNDimensions()); 0532 } 0533 return sliced; 0534 } 0535 0536 /// Slice this histogram with an RSliceSpec per dimension. 0537 /// 0538 /// With a range, only the specified bins are retained. All other bin contents are transferred to the underflow and 0539 /// overflow bins: 0540 /// \code 0541 /// ROOT::Experimental::RHist<int> hist(/* one dimension */); 0542 /// // Fill the histogram with a number of entries... 0543 /// auto sliced = hist.Slice(hist.GetAxes()[0].GetNormalRange(1, 5)); 0544 /// // The returned histogram will have 4 normal bins, an underflow and an overflow bin. 0545 /// \endcode 0546 /// 0547 /// Slicing can also perform operations per dimension, see RSliceSpec. RSliceSpec::ROperationRebin allows to rebin 0548 /// the histogram axis, grouping a number of normal bins into a new one: 0549 /// \code 0550 /// ROOT::Experimental::RHist<int> hist(/* one dimension */); 0551 /// // Fill the histogram with a number of entries... 0552 /// auto rebinned = hist.Slice(ROOT::Experimental::RSliceSpec::ROperationRebin(2)); 0553 /// // The returned histogram has groups of two normal bins merged. 0554 /// \endcode 0555 /// 0556 /// RSliceSpec::ROperationSum sums the bin contents along that axis, which allows to project to a lower-dimensional 0557 /// histogram: 0558 /// \code 0559 /// ROOT::Experimental::RHist<int> hist({/* two dimensions */}); 0560 /// // Fill the histogram with a number of entries... 0561 /// auto projected = hist.Slice(ROOT::Experimental::RSliceSpec{}, ROOT::Experimental::RSliceSpec::ROperationSum{}); 0562 /// // The returned histogram has one dimension, with bin contents summed along the second axis. 0563 /// \endcode 0564 /// Note that it is not allowed to sum along all histogram axes because the return value would be a scalar. 0565 /// 0566 /// Ranges and operations can be combined. In that case, the range is applied before the operation. 0567 /// 0568 /// \warning Combining a range and the sum operation drops bin contents, which will taint the global histogram 0569 /// statistics. Attempting to access its values, for example calling GetNEntries(), will throw exceptions. 0570 /// 0571 /// \param[in] args the arguments for each axis 0572 /// \return the sliced histogram 0573 /// \par See also 0574 /// the \ref Slice(const std::vector<RSliceSpec> &sliceSpecs) const "function overload" accepting `std::vector` 0575 template <typename... A> 0576 RHist Slice(const A &...args) const 0577 { 0578 std::vector<RSliceSpec> sliceSpecs{args...}; 0579 return Slice(sliceSpecs); 0580 } 0581 0582 /// \} 0583 0584 /// %ROOT Streamer function to throw when trying to store an object of this class. 0585 void Streamer(TBuffer &) { throw std::runtime_error("unable to store RHist"); } 0586 }; 0587 0588 } // namespace Experimental 0589 } // namespace ROOT 0590 0591 #endif
| [ Source navigation ] | [ Diff markup ] | [ Identifier search ] | [ general search ] |
|
This page was automatically generated by the 2.3.7 LXR engine. The LXR team |
|