Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions hist/histv7util/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
ROOT_STANDARD_LIBRARY_PACKAGE(ROOTHistUtil
HEADERS
ROOT/Hist/ConversionUtils.hxx
ROOT/Hist/ConvertToTH1.hxx
SOURCES
ConversionUtils.cxx
ConvertToTH1.cxx
DEPENDENCIES
Core
Expand Down
29 changes: 29 additions & 0 deletions hist/histv7util/inc/ROOT/Hist/ConversionUtils.hxx
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
/// \file
/// \warning This is part of the %ROOT 7 prototype! It will change without notice. It might trigger earthquakes.
/// Feedback is welcome!

#ifndef ROOT_Hist_ConversionUtils
#define ROOT_Hist_ConversionUtils

class TAxis;

namespace ROOT {
namespace Experimental {

class RAxisVariant;

namespace Hist {
namespace Internal {

/// Convert a single axis object to TAxis.
///
/// \param[out] dst the target TAxis object
/// \param[in] src the input axis to convert
void ConvertAxis(TAxis &dst, const RAxisVariant &src);

} // namespace Internal
} // namespace Hist
} // namespace Experimental
} // namespace ROOT

#endif
39 changes: 39 additions & 0 deletions hist/histv7util/src/ConversionUtils.cxx
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
/// \file
/// \warning This is part of the %ROOT 7 prototype! It will change without notice. It might trigger earthquakes.
/// Feedback is welcome!

#include <ROOT/Hist/ConversionUtils.hxx>
#include <ROOT/RAxisVariant.hxx>
#include <ROOT/RCategoricalAxis.hxx>
#include <ROOT/RRegularAxis.hxx>
#include <ROOT/RVariableBinAxis.hxx>

#include <TAxis.h>

namespace ROOT {
namespace Experimental {
namespace Hist {
namespace Internal {

void ConvertAxis(TAxis &dst, const RAxisVariant &src)
{
if (auto *regular = src.GetRegularAxis()) {
dst.Set(regular->GetNNormalBins(), regular->GetLow(), regular->GetHigh());
} else if (auto *variable = src.GetVariableBinAxis()) {
dst.Set(variable->GetNNormalBins(), variable->GetBinEdges().data());
} else if (auto *categorical = src.GetCategoricalAxis()) {
const auto &categories = categorical->GetCategories();
dst.Set(categories.size(), 0, categories.size());

for (std::size_t i = 0; i < categories.size(); i++) {
dst.SetBinLabel(i + 1, categories[i].c_str());
}
} else {
throw std::logic_error("unimplemented axis type"); // GCOVR_EXCL_LINE
}
}

} // namespace Internal
} // namespace Hist
} // namespace Experimental
} // namespace ROOT
41 changes: 17 additions & 24 deletions hist/histv7util/src/ConvertToTH1.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
/// \warning This is part of the %ROOT 7 prototype! It will change without notice. It might trigger earthquakes.
/// Feedback is welcome!

#include <ROOT/Hist/ConversionUtils.hxx>
#include <ROOT/Hist/ConvertToTH1.hxx>
#include <ROOT/RBinIndex.hxx>
#include <ROOT/RHist.hxx>
Expand All @@ -27,7 +28,12 @@ std::unique_ptr<Hist> ConvertToTH1Impl(const RHistEngine<T> &engine)
throw std::invalid_argument("TH1 requires one dimension");
}

std::unique_ptr<Hist> ret;
auto ret = std::make_unique<Hist>();
ret->SetDirectory(nullptr);

ROOT::Experimental::Hist::Internal::ConvertAxis(*ret->GetXaxis(), engine.GetAxes()[0]);
ret->SetBinsLength();

Double_t *sumw2 = nullptr;
auto copyBinContent = [&ret, &engine, &sumw2](Int_t i, RBinIndex index) {
if constexpr (std::is_same_v<T, RBinWithError>) {
Expand All @@ -44,30 +50,17 @@ std::unique_ptr<Hist> ConvertToTH1Impl(const RHistEngine<T> &engine)
}
};

const auto &axes = engine.GetAxes();
RBinIndexRange range;
if (auto *regular = axes[0].GetRegularAxis()) {
const std::size_t nNormalBins = regular->GetNNormalBins();
ret.reset(new Hist("", "", nNormalBins, regular->GetLow(), regular->GetHigh()));

// Convert the flow bins, if enabled.
if (regular->HasFlowBins()) {
copyBinContent(0, RBinIndex::Underflow());
copyBinContent(nNormalBins + 1, RBinIndex::Overflow());
// Copy the bin contents, accounting for TH1 numbering conventions.
const auto &axis = engine.GetAxes()[0];
for (auto index : axis.GetFullRange()) {
if (index.IsUnderflow()) {
copyBinContent(0, index);
} else if (index.IsOverflow()) {
copyBinContent(axis.GetNNormalBins() + 1, index);
} else {
assert(index.IsNormal());
copyBinContent(index.GetIndex() + 1, index);
}

// Get the range of normal bins for the loop below.
range = regular->GetNormalRange();
} else {
throw std::logic_error("unimplemented axis type"); // GCOVR_EXCL_LINE
}

assert(ret);
ret->SetDirectory(nullptr);

// Convert the normal bins, accounting for TH1 numbering conventions.
for (auto index : range) {
copyBinContent(index.GetIndex() + 1, index);
}

return ret;
Expand Down
1 change: 1 addition & 0 deletions hist/histv7util/test/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
ROOT_ADD_GTEST(hist_conversion_utils hist_conversion_utils.cxx LIBRARIES ROOTHist ROOTHistUtil)
ROOT_ADD_GTEST(hist_convert_TH1 hist_convert_TH1.cxx LIBRARIES ROOTHist ROOTHistUtil)
62 changes: 62 additions & 0 deletions hist/histv7util/test/hist_conversion_utils.cxx
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
#include "histutil_test.hxx"

#include <TAxis.h>

#include <string>
#include <vector>

using ROOT::Experimental::Hist::Internal::ConvertAxis;

TEST(ConvertAxis, RegularAxis)
{
static constexpr std::size_t Bins = 20;
const RAxisVariant src{RRegularAxis(Bins, {0, Bins})};

TAxis dst;
ConvertAxis(dst, src);

EXPECT_FALSE(dst.IsVariableBinSize());
EXPECT_EQ(dst.GetNbins(), Bins);
EXPECT_EQ(dst.GetXmin(), 0.0);
EXPECT_EQ(dst.GetXmax(), Bins);
EXPECT_EQ(dst.GetXbins()->size(), 0);
}

TEST(ConvertAxis, VariableBinAxis)
{
static constexpr std::size_t Bins = 20;
std::vector<double> bins;
for (std::size_t i = 0; i < Bins; i++) {
bins.push_back(i);
}
bins.push_back(Bins);
const RAxisVariant src{RVariableBinAxis(bins)};

TAxis dst;
ConvertAxis(dst, src);

EXPECT_TRUE(dst.IsVariableBinSize());
EXPECT_EQ(dst.GetNbins(), Bins);
EXPECT_EQ(dst.GetXmin(), 0.0);
EXPECT_EQ(dst.GetXmax(), Bins);

ASSERT_EQ(dst.GetXbins()->size(), Bins + 1);
for (std::size_t i = 0; i <= Bins; i++) {
EXPECT_EQ(dst.GetXbins()->At(i), bins[i]);
}
}

TEST(ConvertAxis, CategoricalAxis)
{
const std::vector<std::string> categories = {"a", "b", "c"};
const RAxisVariant src{RCategoricalAxis(categories)};

TAxis dst;
ConvertAxis(dst, src);

EXPECT_FALSE(dst.IsVariableBinSize());
EXPECT_EQ(dst.GetNbins(), categories.size());
for (std::size_t i = 0; i < categories.size(); i++) {
EXPECT_EQ(dst.GetBinLabel(i + 1), categories[i]);
}
}
7 changes: 0 additions & 7 deletions hist/histv7util/test/hist_convert_TH1.cxx
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
#include "histutil_test.hxx"

#include <TAxis.h>
#include <TH1.h>

#include <array>
Expand Down Expand Up @@ -30,12 +29,6 @@ TEST(ConvertToTH1I, RHistEngine)
ASSERT_EQ(th1i->GetNbinsY(), 1);
ASSERT_EQ(th1i->GetNbinsZ(), 1);

const auto *xAxis = th1i->GetXaxis();
EXPECT_FALSE(xAxis->IsVariableBinSize());
EXPECT_EQ(xAxis->GetNbins(), Bins);
EXPECT_EQ(xAxis->GetXmin(), 0.0);
EXPECT_EQ(xAxis->GetXmax(), Bins);

for (std::size_t i = 0; i < Bins + 2; i++) {
// Bin 7 was filled twice.
if (i == 7 + 1) {
Expand Down
8 changes: 8 additions & 0 deletions hist/histv7util/test/histutil_test.hxx
Original file line number Diff line number Diff line change
@@ -1,18 +1,26 @@
#ifndef histutil_test
#define histutil_test

#include <ROOT/Hist/ConversionUtils.hxx>
#include <ROOT/Hist/ConvertToTH1.hxx>
#include <ROOT/RAxisVariant.hxx>
#include <ROOT/RBinWithError.hxx>
#include <ROOT/RCategoricalAxis.hxx>
#include <ROOT/RHist.hxx>
#include <ROOT/RHistEngine.hxx>
#include <ROOT/RRegularAxis.hxx>
#include <ROOT/RVariableBinAxis.hxx>
#include <ROOT/RWeight.hxx>

using namespace ROOT::Experimental::Hist;
using ROOT::Experimental::RAxisVariant;
using ROOT::Experimental::RBinIndex;
using ROOT::Experimental::RBinWithError;
using ROOT::Experimental::RCategoricalAxis;
using ROOT::Experimental::RHist;
using ROOT::Experimental::RHistEngine;
using ROOT::Experimental::RRegularAxis;
using ROOT::Experimental::RVariableBinAxis;
using ROOT::Experimental::RWeight;

#include <gtest/gtest.h>
Expand Down
Loading