Skip to content

Commit 98d43b4

Browse files
committed
Add tests for ROOT::RVec
... with all possible index column types, copied from std::vector. Closes #19
1 parent 79d301f commit 98d43b4

8 files changed

Lines changed: 329 additions & 0 deletions

File tree

types/README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
* [`multiset`](multiset): `std::multiset` with all `[Split]Index{32,64}` column types
55
* [`optional`](optional): `std::optional` with different element types
66
* [`pair`](pair): `std::pair` with different element types
7+
* [`RVec`](RVec): `ROOT::RVec` with all `[Split]Index{32,64}` column types
78
* [`set`](set): `std::set` with all `[Split]Index{32,64}` column types
89
* [`string`](string): `std::string` with all `[Split]Index{32,64}` column types
910
* [`tuple`](tuple): `std::tuple` with different element types

types/RVec/README.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
# `ROOT::RVec`
2+
3+
* [`fundamental`](fundamental): `ROOT::RVec<std::int32_t>`
4+
* [`nested`](nested): `ROOT::RVec<ROOT::RVec<std::int32_t>>`
5+
6+
__Missing:__
7+
Field with the shorter alias `ROOT::RVec<T>`; ROOT always stores the fully qualified type name `ROOT::VecOps::RVec<T>`.

types/RVec/fundamental/README.md

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
# `ROOT::RVec<std::int32_t>`
2+
3+
## Fields
4+
5+
* `[Split]Index{32,64}`
6+
7+
with the corresponding column type for offset column of the collection parent field.
8+
All child fields use the default column encoding `Int32`.
9+
10+
## Entries
11+
12+
1. Single-element vectors, with ascending values
13+
2. Empty vectors
14+
3. Increasing number of elements in the vector:
15+
one element in the first field, two elements in the second field, etc.

types/RVec/fundamental/read.C

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
#include <ROOT/REntry.hxx>
2+
#include <ROOT/RNTupleReader.hxx>
3+
#include <ROOT/RVec.hxx>
4+
5+
using ROOT::Experimental::REntry;
6+
using ROOT::Experimental::RNTupleReader;
7+
8+
#include <cstdint>
9+
#include <fstream>
10+
#include <ostream>
11+
#include <string>
12+
#include <string_view>
13+
14+
using Vector = ROOT::RVec<std::int32_t>;
15+
16+
static void PrintVectorValue(const REntry &entry, std::string_view name,
17+
std::ostream &os, bool last = false) {
18+
Vector &value = *entry.GetPtr<Vector>(name);
19+
os << " \"" << name << "\": [";
20+
bool first = true;
21+
for (auto element : value) {
22+
if (first) {
23+
first = false;
24+
} else {
25+
os << ",";
26+
}
27+
os << "\n " << element;
28+
}
29+
if (!value.empty()) {
30+
os << "\n ";
31+
}
32+
os << "]";
33+
if (!last) {
34+
os << ",";
35+
}
36+
os << "\n";
37+
}
38+
39+
void read(std::string_view input = "types.RVec.fundamental.root",
40+
std::string_view output = "types.RVec.fundamental.json") {
41+
std::ofstream os(std::string{output});
42+
os << "[\n";
43+
44+
auto reader = RNTupleReader::Open("ntpl", input);
45+
auto &entry = reader->GetModel().GetDefaultEntry();
46+
bool first = true;
47+
for (auto index : *reader) {
48+
reader->LoadEntry(index);
49+
50+
if (first) {
51+
first = false;
52+
} else {
53+
os << ",\n";
54+
}
55+
os << " {\n";
56+
57+
PrintVectorValue(entry, "Index32", os);
58+
PrintVectorValue(entry, "Index64", os);
59+
PrintVectorValue(entry, "SplitIndex32", os);
60+
PrintVectorValue(entry, "SplitIndex64", os, /*last=*/true);
61+
62+
os << " }";
63+
// Newline is intentionally missing, may need to print a comma before the
64+
// next entry.
65+
}
66+
os << "\n";
67+
os << "]\n";
68+
}

types/RVec/fundamental/write.C

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
#include <ROOT/RField.hxx>
2+
#include <ROOT/RNTupleModel.hxx>
3+
#include <ROOT/RNTupleUtil.hxx>
4+
#include <ROOT/RNTupleWriteOptions.hxx>
5+
#include <ROOT/RNTupleWriter.hxx>
6+
#include <ROOT/RVec.hxx>
7+
8+
using ROOT::Experimental::EColumnType;
9+
using ROOT::Experimental::RField;
10+
using ROOT::Experimental::RNTupleModel;
11+
using ROOT::Experimental::RNTupleWriteOptions;
12+
using ROOT::Experimental::RNTupleWriter;
13+
14+
#include <cstdint>
15+
#include <memory>
16+
#include <string_view>
17+
18+
using Vector = ROOT::RVec<std::int32_t>;
19+
20+
static std::shared_ptr<Vector> MakeVectorField(RNTupleModel &model,
21+
std::string_view name,
22+
EColumnType indexType) {
23+
auto field = std::make_unique<RField<Vector>>(name);
24+
field->SetColumnRepresentatives({{indexType}});
25+
model.AddField(std::move(field));
26+
return model.GetDefaultEntry().GetPtr<Vector>(name);
27+
}
28+
29+
void write(std::string_view filename = "types.RVec.fundamental.root") {
30+
auto model = RNTupleModel::Create();
31+
32+
// Non-split index encoding
33+
auto Index32 = MakeVectorField(*model, "Index32", EColumnType::kIndex32);
34+
auto Index64 = MakeVectorField(*model, "Index64", EColumnType::kIndex64);
35+
36+
// Split index encoding
37+
auto SplitIndex32 =
38+
MakeVectorField(*model, "SplitIndex32", EColumnType::kSplitIndex32);
39+
auto SplitIndex64 =
40+
MakeVectorField(*model, "SplitIndex64", EColumnType::kSplitIndex64);
41+
42+
RNTupleWriteOptions options;
43+
options.SetCompression(0);
44+
auto writer =
45+
RNTupleWriter::Recreate(std::move(model), "ntpl", filename, options);
46+
47+
// First entry: single-element vectors, with ascending values
48+
*Index32 = {1};
49+
*Index64 = {2};
50+
*SplitIndex32 = {3};
51+
*SplitIndex64 = {4};
52+
writer->Fill();
53+
54+
// Second entry: empty vectors
55+
*Index32 = {};
56+
*Index64 = {};
57+
*SplitIndex32 = {};
58+
*SplitIndex64 = {};
59+
writer->Fill();
60+
61+
// Third entry: increasing number of elements in the vector
62+
*Index32 = {1};
63+
*Index64 = {2, 3};
64+
*SplitIndex32 = {4, 5, 6};
65+
*SplitIndex64 = {7, 8, 9, 10};
66+
writer->Fill();
67+
}

types/RVec/nested/README.md

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
# `ROOT::RVec<ROOT::RVec<std::int32_t>>`
2+
3+
## Fields
4+
5+
* `[Split]Index{32,64}`
6+
7+
with the corresponding column type for offset columns of the two collection parent fields.
8+
All child fields use the default column encoding `Int32`.
9+
10+
## Entries
11+
12+
1. Single-element vectors, with ascending values
13+
2. Empty vectors
14+
3. Increasing number of elements in the outer vector, with arbitrary lengths of the inner vectors

types/RVec/nested/read.C

Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
#include <ROOT/REntry.hxx>
2+
#include <ROOT/RNTupleReader.hxx>
3+
#include <ROOT/RVec.hxx>
4+
5+
using ROOT::Experimental::REntry;
6+
using ROOT::Experimental::RNTupleReader;
7+
8+
#include <cstdint>
9+
#include <fstream>
10+
#include <ostream>
11+
#include <string>
12+
#include <string_view>
13+
14+
using Vector = ROOT::RVec<ROOT::RVec<std::int32_t>>;
15+
16+
static void PrintNestedVectorValue(const REntry &entry, std::string_view name,
17+
std::ostream &os, bool last = false) {
18+
Vector &value = *entry.GetPtr<Vector>(name);
19+
os << " \"" << name << "\": [";
20+
bool outerFirst = true;
21+
for (auto inner : value) {
22+
if (outerFirst) {
23+
outerFirst = false;
24+
} else {
25+
os << ",";
26+
}
27+
os << "\n [";
28+
bool innerFirst = true;
29+
for (auto element : inner) {
30+
if (innerFirst) {
31+
innerFirst = false;
32+
} else {
33+
os << ",";
34+
}
35+
os << "\n " << element;
36+
}
37+
if (!inner.empty()) {
38+
os << "\n ";
39+
}
40+
os << "]";
41+
}
42+
if (!value.empty()) {
43+
os << "\n ";
44+
}
45+
os << "]";
46+
if (!last) {
47+
os << ",";
48+
}
49+
os << "\n";
50+
}
51+
52+
void read(std::string_view input = "types.RVec.nested.root",
53+
std::string_view output = "types.RVec.nested.json") {
54+
std::ofstream os(std::string{output});
55+
os << "[\n";
56+
57+
auto reader = RNTupleReader::Open("ntpl", input);
58+
auto &entry = reader->GetModel().GetDefaultEntry();
59+
bool first = true;
60+
for (auto index : *reader) {
61+
reader->LoadEntry(index);
62+
63+
if (first) {
64+
first = false;
65+
} else {
66+
os << ",\n";
67+
}
68+
os << " {\n";
69+
70+
PrintNestedVectorValue(entry, "Index32", os);
71+
PrintNestedVectorValue(entry, "Index64", os);
72+
PrintNestedVectorValue(entry, "SplitIndex32", os);
73+
PrintNestedVectorValue(entry, "SplitIndex64", os, /*last=*/true);
74+
75+
os << " }";
76+
// Newline is intentionally missing, may need to print a comma before the
77+
// next entry.
78+
}
79+
os << "\n";
80+
os << "]\n";
81+
}

types/RVec/nested/write.C

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
#include <ROOT/RField.hxx>
2+
#include <ROOT/RNTupleModel.hxx>
3+
#include <ROOT/RNTupleUtil.hxx>
4+
#include <ROOT/RNTupleWriteOptions.hxx>
5+
#include <ROOT/RNTupleWriter.hxx>
6+
#include <ROOT/RVec.hxx>
7+
8+
using ROOT::Experimental::EColumnType;
9+
using ROOT::Experimental::RField;
10+
using ROOT::Experimental::RNTupleModel;
11+
using ROOT::Experimental::RNTupleWriteOptions;
12+
using ROOT::Experimental::RNTupleWriter;
13+
14+
#include <cstdint>
15+
#include <memory>
16+
#include <string_view>
17+
18+
using Inner = ROOT::RVec<std::int32_t>;
19+
using Vector = ROOT::RVec<Inner>;
20+
21+
static std::shared_ptr<Vector> MakeVectorField(RNTupleModel &model,
22+
std::string_view name,
23+
EColumnType indexType) {
24+
auto field = std::make_unique<RField<Vector>>(name);
25+
field->SetColumnRepresentatives({{indexType}});
26+
field->GetSubFields()[0]->SetColumnRepresentatives({{indexType}});
27+
model.AddField(std::move(field));
28+
return model.GetDefaultEntry().GetPtr<Vector>(name);
29+
}
30+
31+
void write(std::string_view filename = "types.RVec.nested.root") {
32+
auto model = RNTupleModel::Create();
33+
34+
// Non-split index encoding
35+
auto Index32 = MakeVectorField(*model, "Index32", EColumnType::kIndex32);
36+
auto Index64 = MakeVectorField(*model, "Index64", EColumnType::kIndex64);
37+
38+
// Split index encoding
39+
auto SplitIndex32 =
40+
MakeVectorField(*model, "SplitIndex32", EColumnType::kSplitIndex32);
41+
auto SplitIndex64 =
42+
MakeVectorField(*model, "SplitIndex64", EColumnType::kSplitIndex64);
43+
44+
RNTupleWriteOptions options;
45+
options.SetCompression(0);
46+
auto writer =
47+
RNTupleWriter::Recreate(std::move(model), "ntpl", filename, options);
48+
49+
// First entry: single-element vectors, with ascending values
50+
*Index32 = {{1}};
51+
*Index64 = {{2}};
52+
*SplitIndex32 = {{3}};
53+
*SplitIndex64 = {{4}};
54+
writer->Fill();
55+
56+
// Second entry: empty vectors
57+
*Index32 = {};
58+
*Index64 = {};
59+
*SplitIndex32 = {};
60+
*SplitIndex64 = {};
61+
writer->Fill();
62+
63+
// Third entry: increasing number of elements in the outer vector
64+
*Index32 = {{1}};
65+
*Index64 = {{}, {2, 3}};
66+
*SplitIndex32 = {{4}, {}, {5, 6}};
67+
*SplitIndex64 = {{}, {7, 8, 9}, {}, {10}};
68+
writer->Fill();
69+
70+
// Work around bug in 6.34 for destroying RVec's, later fixed by commit
71+
// https://github.com/root-project/root/commit/996cac359d for 6.36.
72+
Index32->clear();
73+
Index64->clear();
74+
SplitIndex32->clear();
75+
SplitIndex64->clear();
76+
}

0 commit comments

Comments
 (0)