Project
Loading...
Searching...
No Matches
test_TreeToTable.cxx
Go to the documentation of this file.
1// Copyright 2019-2020 CERN and copyright holders of ALICE O2.
2// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders.
3// All rights not expressly granted are reserved.
4//
5// This software is distributed under the terms of the GNU General Public
6// License v3 (GPL Version 3), copied verbatim in the file "COPYING".
7//
8// In applying this license CERN does not waive the privileges and immunities
9// granted to it by virtue of its status as an Intergovernmental Organization
10// or submit itself to any jurisdiction.
11
12#include <catch_amalgamated.hpp>
13
16#include "Framework/Logger.h"
18
19#include <TTree.h>
20#include <TRandom.h>
21#include <arrow/table.h>
22#include <array>
23
24using namespace o2::framework;
25
26TEST_CASE("TreeToTableConversion")
27{
29 Int_t ndp = 17;
30
31 TFile f1("tree2table.root", "RECREATE");
32 TTree t1("t1", "a simple Tree with simple variables");
33 Bool_t ok, ts[5] = {false};
34 Float_t px, py, pz;
35 Double_t random;
36 Int_t ev;
37 uint8_t b;
38 const Int_t nelem = 9;
39 Double_t ij[nelem] = {0};
40 float xyzw[96];
41 memset(xyzw, 1, 96 * 4);
42 TString leaflist = Form("ij[%i]/D", nelem);
43
44 Int_t ncols = 10;
45 t1.Branch("ok", &ok, "ok/O");
46 t1.Branch("px", &px, "px/F");
47 t1.Branch("py", &py, "py/F");
48 t1.Branch("pz", &pz, "pz/F");
49 t1.Branch("random", &random, "random/D");
50 t1.Branch("ev", &ev, "ev/I");
51 t1.Branch("ij", ij, leaflist.Data());
52 t1.Branch("tests", ts, "tests[5]/O");
53 t1.Branch("xyzw", xyzw, "xyzw[96]/F");
54 t1.Branch("small", &b, "small/b");
55
56 // fill the tree
57 int ntruein[2] = {0};
58 for (int i = 0; i < ndp; i++) {
59 ok = (i % 2) == 0;
60 if (ok) {
61 ntruein[0]++;
62 }
63 gRandom->Rannor(px, py);
64 pz = px * px + py * py;
65 random = gRandom->Rndm();
66 ev = i + 1;
67 b = i % 3;
68 for (Int_t jj = 0; jj < nelem; jj++) {
69 ij[jj] = i + 100 * jj;
70 }
71 for (Int_t jj = 0; jj < 5; jj++) {
72 ts[jj] = (((i + jj) % 2) == 0);
73 if (ts[jj]) {
74 ntruein[1]++;
75 }
76 }
77
78 t1.Fill();
79 }
80 t1.Write();
81
82 // Create an arrow table from this.
83 TreeToTable tr2ta;
84 tr2ta.addAllColumns(&t1);
85 tr2ta.fill(&t1);
86 auto table = tr2ta.finalize();
87 f1.Close();
88
89 // test result
90 REQUIRE(table->Validate().ok() == true);
91 REQUIRE(table->num_rows() == ndp);
92 REQUIRE(table->num_columns() == ncols);
93
94 REQUIRE(table->column(0)->type()->id() == arrow::Type::BOOL);
95 REQUIRE(table->column(1)->type()->id() == arrow::Type::FLOAT);
96 REQUIRE(table->column(2)->type()->id() == arrow::Type::FLOAT);
97 REQUIRE(table->column(3)->type()->id() == arrow::Type::FLOAT);
98 REQUIRE(table->column(4)->type()->id() == arrow::Type::DOUBLE);
99 REQUIRE(table->column(5)->type()->id() == arrow::Type::INT32);
100 REQUIRE(table->column(6)->type()->id() == arrow::Type::FIXED_SIZE_LIST);
101 REQUIRE(table->column(7)->type()->id() == arrow::Type::FIXED_SIZE_LIST);
102 REQUIRE(table->column(8)->type()->id() == arrow::Type::FIXED_SIZE_LIST);
103 REQUIRE(table->column(9)->type()->id() == arrow::Type::UINT8);
104
105 REQUIRE(table->column(0)->type()->Equals(arrow::boolean()));
106 REQUIRE(table->column(1)->type()->Equals(arrow::float32()));
107 REQUIRE(table->column(2)->type()->Equals(arrow::float32()));
108 REQUIRE(table->column(3)->type()->Equals(arrow::float32()));
109 REQUIRE(table->column(4)->type()->Equals(arrow::float64()));
110 REQUIRE(table->column(5)->type()->Equals(arrow::int32()));
111 REQUIRE(table->column(6)->type()->Equals(arrow::fixed_size_list(arrow::float64(), nelem)));
112 REQUIRE(table->column(7)->type()->Equals(arrow::fixed_size_list(arrow::boolean(), 5)));
113 REQUIRE(table->column(8)->type()->Equals(arrow::fixed_size_list(arrow::float32(), 96)));
114 REQUIRE(table->column(9)->type()->Equals(arrow::uint8()));
115
116 // count number of rows with ok==true
117 int ntrueout = 0;
118 auto chunks = table->column(0);
119 REQUIRE(!(chunks.get() == nullptr));
120
121 auto oks = std::dynamic_pointer_cast<arrow::BooleanArray>(chunks->chunk(0));
122 REQUIRE(!(oks.get() == nullptr));
123
124 for (int ii = 0; ii < table->num_rows(); ii++) {
125 ntrueout += oks->Value(ii) ? 1 : 0;
126 }
127 REQUIRE(ntruein[0] == ntrueout);
128
129 // count number of ts with ts==true
130 chunks = table->column(7);
131 REQUIRE(!(chunks.get() == nullptr));
132
133 auto chunkToUse = std::static_pointer_cast<arrow::FixedSizeListArray>(chunks->chunk(0))->values();
134 REQUIRE(!(chunkToUse.get() == nullptr));
135
136 auto tests = std::dynamic_pointer_cast<arrow::BooleanArray>(chunkToUse);
137 ntrueout = 0;
138 for (int ii = 0; ii < table->num_rows() * 5; ii++) {
139 ntrueout += tests->Value(ii) ? 1 : 0;
140 }
141 REQUIRE(ntruein[1] == ntrueout);
142
143 // save table as tree
144 TFile* f2 = TFile::Open("table2tree.root", "RECREATE");
145 TableToTree ta2tr(table, f2, "mytree");
146 ta2tr.addAllBranches();
147
148 auto t2 = ta2tr.process();
149 auto br = (TBranch*)t2->GetBranch("ok");
150 REQUIRE(t2->GetEntries() == ndp);
151 REQUIRE(br->GetEntries() == ndp);
152 br = (TBranch*)t2->GetBranch("tests");
153 REQUIRE(br->GetEntries() == ndp);
154
155 f2->Close();
156}
157
158namespace o2::aod
159{
160namespace cols
161{
162DECLARE_SOA_COLUMN(Ivec, ivec, std::vector<int>);
163DECLARE_SOA_COLUMN(Fvec, fvec, std::vector<float>);
164DECLARE_SOA_COLUMN(Dvec, dvec, std::vector<double>);
165DECLARE_SOA_COLUMN(UIvec, uivec, std::vector<uint8_t>);
166} // namespace cols
167
168DECLARE_SOA_TABLE(Vectors, "AOD", "VECS", o2::soa::Index<>, cols::Ivec, cols::Fvec, cols::Dvec, cols::UIvec);
169} // namespace o2::aod
170
171TEST_CASE("VariableLists")
172{
174 auto writer = b.cursor<o2::aod::Vectors>();
175 std::vector<int> iv;
176 std::vector<float> fv;
177 std::vector<double> dv;
178 std::vector<uint8_t> ui;
179
180 std::array<int, 3> empty = {3, 7, 10};
181 auto count = 0;
182 for (auto i = 1; i < 1000; ++i) {
183 iv.clear();
184 fv.clear();
185 dv.clear();
186 ui.clear();
187 if (count < empty.size() && i != empty[count]) {
188 for (auto j = 0; j < i % 10 + 1; ++j) {
189 iv.push_back(j + 2);
190 fv.push_back((j + 2) * 0.2134f);
191 dv.push_back((j + 4) * 0.192873819237);
192 ui.push_back(j);
193 }
194 } else {
195 count++;
196 }
197 writer(0, iv, fv, dv, ui);
198 }
199 auto table = b.finalize();
200
201 auto* f = TFile::Open("variable_lists.root", "RECREATE");
202 TableToTree ta2tr(table, f, "lists");
203 ta2tr.addAllBranches();
204 auto tree = ta2tr.process();
205 f->Close();
206
207 auto* f2 = TFile::Open("variable_lists.root", "READ");
208 auto* treeptr = static_cast<TTree*>(f2->Get("lists;1"));
209 TreeToTable tr2ta;
210 tr2ta.addAllColumns(treeptr);
211 tr2ta.fill(treeptr);
212 auto ta = tr2ta.finalize();
213 o2::aod::Vectors v{ta};
214 int i = 1;
215 count = 0;
216 for (auto& row : v) {
217 auto ivr = row.ivec();
218 auto fvr = row.fvec();
219 auto dvr = row.dvec();
220 auto uvr = row.uivec();
221 if (count < empty.size() && i != empty[count]) {
222 for (auto j = 0; j < i % 10 + 1; ++j) {
223 REQUIRE(ivr[j] == j + 2);
224 REQUIRE(fvr[j] == (j + 2) * 0.2134f);
225 REQUIRE(dvr[j] == (j + 4) * 0.192873819237);
226 REQUIRE(uvr[j] == j);
227 }
228 } else {
229 REQUIRE(ivr.size() == 0);
230 REQUIRE(fvr.size() == 0);
231 REQUIRE(dvr.size() == 0);
232 REQUIRE(uvr.size() == 0);
233 count++;
234 }
235 ++i;
236 }
237}
#define DECLARE_SOA_TABLE(_Name_, _Origin_, _Desc_,...)
Definition ASoA.h:3052
#define DECLARE_SOA_COLUMN(_Name_, _Getter_, _Type_)
Definition ASoA.h:2314
int32_t i
uint32_t j
Definition RawData.h:0
uint32_t cols
std::shared_ptr< TTree > process()
void addAllColumns(TTree *tree, std::vector< std::string > &&names={})
std::shared_ptr< arrow::Table > finalize()
GLint GLsizei count
Definition glcorearb.h:399
const GLdouble * v
Definition glcorearb.h:832
GLdouble f
Definition glcorearb.h:310
GLboolean GLboolean GLboolean b
Definition glcorearb.h:1233
GLuint GLfloat GLfloat GLfloat GLfloat GLfloat GLfloat GLfloat GLfloat GLfloat t1
Definition glcorearb.h:5034
Defining PrimaryVertex explicitly as messageable.
Definition TFIDInfo.h:20
TEST_CASE("test_prepareArguments")
void empty(int)
std::unique_ptr< TTree > tree((TTree *) flIn.Get(std::string(o2::base::NameConf::CTFTREENAME).c_str()))
std::vector< int > row