Skip to content

Commit 889466a

Browse files
committed
[TDF] Add the TTrivialDS and its unit tests
The TTrivialDS is a very simple TDataSource, de facto a generator. It is useful as example and for testing the behaviour of the TDF in combination with external data sources.
1 parent 72258d5 commit 889466a

File tree

3 files changed

+146
-0
lines changed

3 files changed

+146
-0
lines changed
Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
#ifndef ROOT_TTRIVIALTDS
2+
#define ROOT_TTRIVIALTDS
3+
4+
#include "ROOT/TDataFrame.hxx"
5+
#include "ROOT/TDataSource.hxx"
6+
#include "ROOT/TSeq.hxx"
7+
8+
namespace ROOT {
9+
namespace Experimental {
10+
namespace TDF {
11+
12+
class TTrivialDS final : public ROOT::Experimental::TDF::TDataSource {
13+
private:
14+
unsigned int fNSlots = 0U;
15+
ULong64_t fSize = 0ULL;
16+
std::vector<std::pair<ULong64_t, ULong64_t>> fEntryRanges;
17+
std::vector<std::string> fColNames{"col0"};
18+
std::vector<ULong64_t> fCounter;
19+
std::vector<ULong64_t *> fCounterAddr;
20+
std::vector<void *> GetColumnReadersImpl(std::string_view name, const std::type_info &)
21+
{
22+
std::vector<void *> ret;
23+
for (auto i : ROOT::TSeqU(fNSlots)) {
24+
fCounterAddr[i] = &fCounter[i];
25+
ret.emplace_back((void *)(&fCounterAddr[i]));
26+
}
27+
return ret;
28+
}
29+
30+
public:
31+
TTrivialDS(ULong64_t size) : fSize(size) {}
32+
33+
~TTrivialDS() {}
34+
35+
const std::vector<std::string> &GetColumnNames() const { return fColNames; }
36+
37+
bool HasColumn(std::string_view colName) const { return colName == fColNames[0]; }
38+
39+
std::string GetTypeName(std::string_view) const { return "ULong64_t"; }
40+
41+
const std::vector<std::pair<ULong64_t, ULong64_t>> &GetEntryRanges() const
42+
{
43+
if (fEntryRanges.empty()) {
44+
throw std::runtime_error("No ranges are available. Did you set the number of slots?");
45+
}
46+
return fEntryRanges;
47+
}
48+
void SetEntry(ULong64_t entry, unsigned int slot) { fCounter[slot] = entry; }
49+
50+
void SetNSlots(unsigned int nSlots)
51+
{
52+
if (0U != fNSlots) {
53+
return;
54+
}
55+
56+
fNSlots = nSlots;
57+
fCounter.resize(fNSlots);
58+
fCounterAddr.resize(fNSlots);
59+
60+
auto chunckSize = fSize / fNSlots;
61+
auto start = 0UL;
62+
auto end = 0UL;
63+
for (auto i : ROOT::TSeqUL(fNSlots)) {
64+
start = end;
65+
end += chunckSize;
66+
fEntryRanges.emplace_back(start, end);
67+
}
68+
// TODO: redistribute reminder to all slots
69+
fEntryRanges.back().second += fSize % fNSlots;
70+
};
71+
};
72+
}
73+
}
74+
}
75+
76+
#endif

tree/treeplayer/test/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,3 +7,4 @@ ROOT_ADD_GTEST(dataframe_regression dataframe/dataframe_regression.cxx LIBRARIES
77
ROOT_ADD_GTEST(dataframe_interface dataframe/dataframe_interface.cxx LIBRARIES TreePlayer)
88
ROOT_ADD_GTEST(dataframe_utils dataframe/dataframe_utils.cxx LIBRARIES TreePlayer)
99
ROOT_ADD_GTEST(dataframe_nodes dataframe/dataframe_nodes.cxx LIBRARIES TreePlayer)
10+
ROOT_ADD_GTEST(datasource_trivial dataframe/datasource_trivial.cxx LIBRARIES TreePlayer)
Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
#include "ROOT/TTrivialDS.hxx"
2+
3+
#include "gtest/gtest.h"
4+
5+
using namespace ROOT::Experimental;
6+
using namespace ROOT::Experimental::TDF;
7+
8+
TEST(TTrivialDS, ColTypeNames)
9+
{
10+
TTrivialDS tds(32);
11+
tds.SetNSlots(1);
12+
13+
auto colName = tds.GetColumnNames()[0]; // We know it's one.
14+
EXPECT_STREQ("col0", colName.c_str());
15+
EXPECT_STREQ("ULong64_t", tds.GetTypeName("col0").c_str());
16+
17+
EXPECT_TRUE(tds.HasColumn("col0"));
18+
EXPECT_FALSE(tds.HasColumn("col1"));
19+
}
20+
21+
TEST(TTrivialDS, EntryRanges)
22+
{
23+
TTrivialDS tds(32);
24+
const auto nSlots = 4U;
25+
tds.SetNSlots(nSlots);
26+
27+
auto ranges = tds.GetEntryRanges();
28+
29+
EXPECT_EQ(4U, ranges.size());
30+
EXPECT_EQ(0U, ranges[0].first);
31+
EXPECT_EQ(8U, ranges[0].second);
32+
EXPECT_EQ(8U, ranges[1].first);
33+
EXPECT_EQ(16U, ranges[1].second);
34+
EXPECT_EQ(16U, ranges[2].first);
35+
EXPECT_EQ(24U, ranges[2].second);
36+
EXPECT_EQ(24U, ranges[3].first);
37+
EXPECT_EQ(32U, ranges[3].second);
38+
}
39+
40+
TEST(TTrivialDS, ColumnReaders)
41+
{
42+
TTrivialDS tds(32);
43+
const auto nSlots = 4U;
44+
tds.SetNSlots(nSlots);
45+
auto vals = tds.GetColumnReaders<ULong64_t>("col0");
46+
auto ranges = tds.GetEntryRanges();
47+
auto slot = 0U;
48+
for (auto &&range : ranges) {
49+
for (auto i : ROOT::TSeq<ULong64_t>(range.first, range.second)) {
50+
tds.SetEntry(i, slot);
51+
auto val = **vals[slot];
52+
EXPECT_EQ(i, val);
53+
}
54+
slot++;
55+
}
56+
}
57+
58+
TEST(TTrivialDS, FromATDF)
59+
{
60+
std::unique_ptr<TDataSource> tds(new TTrivialDS(32));
61+
TDataFrame tdf(std::move(tds));
62+
auto max = tdf.Max<ULong64_t>("col0");
63+
auto min = tdf.Min<ULong64_t>("col0");
64+
auto c = tdf.Count();
65+
66+
EXPECT_EQ(32U, *c);
67+
EXPECT_DOUBLE_EQ(31., *max);
68+
EXPECT_DOUBLE_EQ(0., *min);
69+
}

0 commit comments

Comments
 (0)