Project
Loading...
Searching...
No Matches
testTreeStream.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#define BOOST_TEST_MODULE Test TreeStream
13#define BOOST_TEST_MAIN
14#define BOOST_TEST_DYN_LINK
15
16#include <TFile.h>
17#include <TRandom.h>
18#include <TVectorD.h>
19#include <boost/test/unit_test.hpp>
20#include <iostream>
25#include <string>
26
27using namespace o2::utils;
28
29bool UnitTestSparse(Double_t scale, Int_t testEntries);
30
31BOOST_AUTO_TEST_CASE(TreeStream_test)
32{
33 // Example test function to show functionality of TreeStreamRedirector
34
35 // create the redirector associated with file (testredirector.root)
36
37 LOG(info) << "Testing TreeStream creation";
38 std::string outFName("testTreeStream.root");
39 int nit = 50;
40 {
41 TreeStreamRedirector tstStream(outFName.data(), "recreate");
42 // write tree named TrackTree of int counter, float and TrackParCov (using pointer)
43 // and another similar tree but using reference of TrackParCov
44 std::array<float, o2::track::kNParams> par{};
45 for (int i = 0; i < nit; i++) {
46 par[o2::track::kQ2Pt] = 0.5 + float(i) / nit;
47 float x = 10. + float(i) / nit * 200.;
48 o2::track::TrackPar trc(0., 0., par);
49 trc.propagateParamTo(x, 0.5);
50 tstStream << "TrackTree"
51 << "id=" << i << "x=" << x << "track=" << &trc << "\n";
52
53 tstStream << "TrackTreeR"
54 << "id=" << i << "x=" << x << "track=" << trc << "\n";
55 }
56
57 // test for c-arrays
58 int iArray[6] = {1, 2, 3, 4, 5, 6};
59 float fArray[6] = {1.1f, 2.2f, 3.3f, 4.4f, 5.5f, 6.6f};
60 for (int i{0}; i < nit; ++i) {
61 for (int j{0}; j < 6; ++j) {
62 iArray[j] += i;
63 fArray[j] += (float)i;
64 }
65 tstStream << "ArrayTree"
66 << "id=" << i
67 << "iArray[6]=" << iArray
68 << "fArray[6]=" << fArray
69 << "\n";
70 }
71
72 // on destruction of tstTreem the trees will be stored, but we can also force it by
73 tstStream.Close();
74 }
75 //
76 LOG(info) << "Testing reading back tree made by the TreeStream ";
77 // read back tracks and arrays
78 {
79 TFile inpf(outFName.data());
80 BOOST_CHECK(!inpf.IsZombie());
81 auto tree = (TTree*)inpf.GetObjectChecked("TrackTree", "TTree");
83 int nent = tree->GetEntries();
84 BOOST_CHECK(nent == nit);
85 int id;
86 float x;
87 o2::track::TrackPar* trc = nullptr;
88 BOOST_CHECK(!tree->SetBranchAddress("id", &id));
89 BOOST_CHECK(!tree->SetBranchAddress("x", &x));
90 BOOST_CHECK(!tree->SetBranchAddress("track", &trc));
91
92 for (int i = 0; i < nent; i++) {
93 tree->GetEntry(i);
94 BOOST_CHECK(id == i);
95 LOG(info) << "id: " << id << " X: " << x << " Track> ";
96 trc->printParam();
97 BOOST_CHECK(std::abs(x - trc->getX()) < 1e-4);
98 }
99
100 // check arrays
101 tree = (TTree*)inpf.GetObjectChecked("ArrayTree", "TTree");
103 nent = tree->GetEntries();
104 BOOST_CHECK(nent == nit);
105 int iArray[6];
106 float fArray[6];
107 BOOST_CHECK(!tree->SetBranchAddress("id", &id));
108 BOOST_CHECK(!tree->SetBranchAddress("iArray", iArray));
109 BOOST_CHECK(!tree->SetBranchAddress("fArray", fArray));
110 for (int i = 0; i < nit; i++) {
111 BOOST_CHECK(tree->GetEntry(i) > 0);
112 BOOST_CHECK(id == i);
113 for (int j = 0; j < 6; j++) {
114 BOOST_CHECK(iArray[j] == (1 + j + i * (i + 1) / 2));
115 }
116 for (int j = 0; j < 6; j++) {
117 BOOST_CHECK_CLOSE(fArray[j], (1.f + j + i * (i + 1) / 2.f + 0.1 * (j + 1)), 1e-5);
118 }
119 }
120 }
121
122 LOG(info) << "Testing loading tree via RootChain";
123 //
124 auto chain = RootChain::load("TrackTree", outFName);
125 BOOST_CHECK(chain->GetEntries());
126 chain->Print();
127
128 // we can also write the stream to external file open in write mode:
129 {
130 TFile inpf(outFName.data(), "update");
131 TreeStream strm("TreeNamed");
132 for (int i = 0; i < nit; i++) {
133 TNamed nm(Form("obj%d", i), "");
134 strm << "idx=" << i << "named=" << &nm << "\n";
135 }
136 strm.Close(); // flush the tree
137 }
138
139 // run Marian's old unit test
140 LOG(info) << "Doing UnitTestSparse";
141 nit = 1000;
142 BOOST_CHECK(UnitTestSparse(0.5, nit));
143 BOOST_CHECK(UnitTestSparse(0.1, nit));
144}
145
146//_________________________________________________
147bool UnitTestSparse(Double_t scale, Int_t testEntries)
148{
149 // Unit test for the TreeStreamRedirector
150 // 1.) Test TTreeRedirector
151 // a.) Fill tree with random vectors
152 // b.) Fill downscaled version of vectors
153 // c.) The same skipping first entry
154 // 2.) Check results wtitten to terminale
155 // a.) Disk consumption
156 // skip data should be scale time smaller than full
157 // zerro replaced ata should be compresed time smaller than full
158 // b.) Test invariants
159 // Input parameter scale => downscaling of sprse element
160
161 std::string outFName("testTreeStreamSparse.root");
162 if (scale <= 0) {
163 scale = 1;
164 }
165 if (scale > 1) {
166 scale = 1;
167 }
168 TreeStreamRedirector* pcstream = new TreeStreamRedirector(outFName.data(), "recreate");
169 for (Int_t ientry = 0; ientry < testEntries; ientry++) {
170 TVectorD vecRandom(200);
171 TVectorD vecZerro(200); // zerro vector
172 for (Int_t j = 0; j < 200; j++) {
173 vecRandom[j] = j + ientry + 0.1 * gRandom->Rndm();
174 }
175 Bool_t isSelected = (gRandom->Rndm() < scale);
176 TVectorD* pvecFull = &vecRandom;
177 TVectorD* pvecSparse = isSelected ? &vecRandom : nullptr;
178 TVectorD* pvecSparse0 = isSelected ? &vecRandom : nullptr;
179 TVectorD* pvecSparse1 = isSelected ? &vecRandom : &vecZerro;
180
181 if (ientry == 0) {
182 pvecSparse0 = nullptr;
183 pvecSparse = &vecRandom;
184 }
185 (*pcstream) << "Full" << // stored all vectors
186 "ientry=" << ientry << "vec.=" << pvecFull << "\n";
187 (*pcstream) << "SparseSkip" << // fraction of vectors stored
188 "ientry=" << ientry << "vec.=" << pvecSparse << "\n";
189 (*pcstream) << "SparseSkip0" << // fraction with -pointer
190 "ientry=" << ientry << "vec.=" << pvecSparse0 << "\n";
191 (*pcstream) << "SparseZerro" << // all vectors filled, franction filled with 0
192 "ientry=" << ientry << "vec.=" << pvecSparse1 << "\n";
193 }
194 delete pcstream;
195 //
196 // 2.) check results
197 //
198
199 TFile* f = TFile::Open(outFName.data());
200 if (!f) {
201 printf("Failed to open file: %s\n", outFName.data());
202 return false;
203 }
204 TTree* treeFull = (TTree*)f->Get("Full");
205 TTree* treeSparseSkip = (TTree*)f->Get("SparseSkip");
206 TTree* treeSparseSkip0 = (TTree*)f->Get("SparseSkip0");
207 TTree* treeSparseZerro = (TTree*)f->Get("SparseZerro");
208 // a.) data volume
209 //
210 Double_t ratio = (1. / scale) * treeSparseSkip->GetZipBytes() / Double_t(treeFull->GetZipBytes());
211 Double_t ratio0 = (1. / scale) * treeSparseSkip0->GetZipBytes() / Double_t(treeFull->GetZipBytes());
212 Double_t ratio1 = (1. / scale) * treeSparseZerro->GetZipBytes() / Double_t(treeFull->GetZipBytes());
213 printf("#UnitTest:\tTestSparse(%f)\tRatioSkip\t%f\n", scale, ratio);
214 printf("#UnitTest:\tTestSparse(%f)\tRatioSkip0\t%f\n", scale, ratio0);
215 printf("#UnitTest:\tTestSparse(%f)\tRatioZerro\t%f\n", scale, ratio1);
216 // b.) Integrity
217 Int_t outlyersSparseSkip = treeSparseSkip->Draw("1", "(vec.fElements-ientry-Iteration$-0.5)>0.5", "goff");
218 Int_t outlyersSparseSkip0 = treeSparseSkip0->Draw("1", "(vec.fElements-ientry-Iteration$-0.5)>0.5", "goff");
219 printf("#UnitTest:\tTestSparse(%f)\tOutlyersSkip\t%d\n", scale, outlyersSparseSkip != 0);
220 printf("#UnitTest:\tTestSparse(%f)\tOutlyersSkip0\t%d\n", scale, outlyersSparseSkip0 != 0);
221 // c.) Number of entries
222 //
223 Int_t entries = treeFull->GetEntries();
224 Int_t entries0 = treeSparseSkip0->GetEntries();
225 Bool_t isOKStat = (entries == entries0);
226 printf("#UnitTest:\tTestSparse(%f)\tEntries\t%d\n", scale, isOKStat);
227 //
228 // d.)Reading test
229 TVectorD* pvecRead = nullptr;
230 treeSparseSkip0->SetBranchAddress("vec.", &pvecRead);
231 Bool_t readOK = kTRUE;
232 for (Int_t ientry = 0; ientry < testEntries; ientry++) {
233 if (!pvecRead) {
234 continue;
235 }
236 if (pvecRead->GetNrows() == 0) {
237 continue;
238 }
239 if (TMath::Abs((*pvecRead)[0] - ientry) > 0.5) {
240 readOK = kFALSE;
241 }
242 }
243 printf("#UnitTest:\tTestSparse(%f)\tReadOK\t%d\n", scale, readOK);
244 //
245 // e.)Global test
246 Bool_t isOK = (outlyersSparseSkip0 == 0) && isOKStat && readOK;
247 printf("#UnitTest:\tTestSparse(%f)\tisOk\t%d\n", scale, isOK);
248
249 return isOK;
250}
Base track model for the Barrel, params only, w/o covariance.
int32_t i
GPUChain * chain
uint32_t j
Definition RawData.h:0
static std::unique_ptr< TChain > load(const std::string trName, const std::string inpFile)
Definition RootChain.cxx:21
GLint GLenum GLint x
Definition glcorearb.h:403
GLdouble f
Definition glcorearb.h:310
GLuint id
Definition glcorearb.h:650
BOOST_AUTO_TEST_CASE(TreeStream_test)
bool UnitTestSparse(Double_t scale, Int_t testEntries)
LOG(info)<< "Compressed in "<< sw.CpuTime()<< " s"
BOOST_CHECK(tree)
std::unique_ptr< TTree > tree((TTree *) flIn.Get(std::string(o2::base::NameConf::CTFTREENAME).c_str()))