Project
Loading...
Searching...
No Matches
GeneratorFromFile.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
16#include <fairlogger/Logger.h>
18#include <TBranch.h>
19#include <TClonesArray.h>
20#include <TFile.h>
21#include <TMCProcess.h>
22#include <TParticle.h>
23#include <TTree.h>
24#include <sstream>
25#include <filesystem>
26#include <TGrid.h>
27#include <TSystem.h>
28
29namespace o2
30{
31namespace eventgen
32{
34{
35 mEventFile = TFile::Open(name);
36 if (mEventFile == nullptr) {
37 LOG(fatal) << "EventFile " << name << " not found \n";
38 return;
39 }
40 // the kinematics will be stored inside a Tree "TreeK" with branch "Particles"
41 // different events are stored inside TDirectories
42
43 // we need to probe for the number of events
44 TObject* object = nullptr;
45 do {
46 std::stringstream eventstringstr;
47 eventstringstr << "Event" << mEventsAvailable;
48 // std::cout << "probing for " << eventstring << "\n";
49 object = mEventFile->Get(eventstringstr.str().c_str());
50 // std::cout << "got " << object << "\n";
51 if (object != nullptr) {
52 mEventsAvailable++;
53 }
54 } while (object != nullptr);
55 LOG(info) << "Found " << mEventsAvailable << " events in this file \n";
56}
57
59{
60 if (start < mEventsAvailable) {
61 mEventCounter = start;
62 } else {
63 LOG(error) << "start event bigger than available events\n";
64 }
65}
66
68{
69 // avoid compute if the particle is not known in the PDG database
70 if (!p.GetPDG()) {
71 LOG(warn) << "Particle with pdg " << p.GetPdgCode() << " not known in DB (not fixing mass)";
72 // still returning true here ... primary will be flagged as non-trackable by primary event generator
73 return true;
74 }
75
76 const auto nominalmass = p.GetMass();
77 auto mom2 = p.Px() * p.Px() + p.Py() * p.Py() + p.Pz() * p.Pz();
78 auto calculatedmass = p.Energy() * p.Energy() - mom2;
79 calculatedmass = (calculatedmass >= 0.) ? std::sqrt(calculatedmass) : -std::sqrt(-calculatedmass);
80 const double tol = 1.E-4;
81 auto difference = std::abs(nominalmass - calculatedmass);
82 if (std::abs(nominalmass - calculatedmass) > tol) {
83 const auto asgmass = p.GetCalcMass();
84 bool fix = mFixOffShell && std::abs(nominalmass - asgmass) < tol;
85 LOG(warn) << "Particle " << p.GetPdgCode() << " has off-shell mass: M_PDG= " << nominalmass << " (assigned= " << asgmass
86 << ") calculated= " << calculatedmass << " -> diff= " << difference << " | " << (fix ? "fixing" : "skipping");
87 if (fix) {
88 double e = std::sqrt(nominalmass * nominalmass + mom2);
89 p.SetMomentum(p.Px(), p.Py(), p.Pz(), e);
90 p.SetCalcMass(nominalmass);
91 } else {
92 return false;
93 }
94 }
95 return true;
96}
97
99{
100 if (mEventCounter < mEventsAvailable) {
101 int particlecounter = 0;
102
103 // get the tree and the branch
104 std::stringstream treestringstr;
105 treestringstr << "Event" << mEventCounter << "/TreeK";
106 TTree* tree = (TTree*)mEventFile->Get(treestringstr.str().c_str());
107 if (tree == nullptr) {
108 return kFALSE;
109 }
110
111 auto branch = tree->GetBranch("Particles");
112 TParticle* particle = nullptr;
113 branch->SetAddress(&particle);
114 LOG(info) << "Reading " << branch->GetEntries() << " particles from Kinematics file";
115
116 // read the whole kinematics initially
117 std::vector<TParticle> particles;
118 for (int i = 0; i < branch->GetEntries(); ++i) {
119 branch->GetEntry(i);
120 particles.push_back(*particle);
121 }
122
123 // filter the particles from Kinematics.root originally put by a generator
124 // and which are trackable
125 auto isFirstTrackableDescendant = [](TParticle const& p) {
126 const int kTransportBit = BIT(14);
127 // The particle should have not set kDone bit and its status should not exceed 1
128 if ((p.GetUniqueID() > 0 && p.GetUniqueID() != kPNoProcess) || !p.TestBit(kTransportBit)) {
129 return false;
130 }
131 return true;
132 };
133
134 for (int i = 0; i < branch->GetEntries(); ++i) {
135 auto& p = particles[i];
136 if (!isFirstTrackableDescendant(p)) {
137 continue;
138 }
139
140 bool wanttracking = true; // RS as far as I understand, if it reached this point, it is trackable
141 if (wanttracking || !mSkipNonTrackable) {
142 if (!rejectOrFixKinematics(p)) {
143 continue;
144 }
145 auto pdgid = p.GetPdgCode();
146 auto px = p.Px();
147 auto py = p.Py();
148 auto pz = p.Pz();
149 auto vx = p.Vx();
150 auto vy = p.Vy();
151 auto vz = p.Vz();
152 auto parent = -1;
153 auto e = p.Energy();
154 auto tof = p.T();
155 auto weight = p.GetWeight();
156 LOG(debug) << "Putting primary " << pdgid << " " << p.GetStatusCode() << " " << p.GetUniqueID();
157 primGen->AddTrack(pdgid, px, py, pz, vx, vy, vz, parent, wanttracking, e, tof, weight);
158 particlecounter++;
159 }
160 }
161 mEventCounter++;
162
163 LOG(info) << "Event generator put " << particlecounter << " on stack";
164 return kTRUE;
165 } else {
166 LOG(error) << "GeneratorFromFile: Ran out of events\n";
167 }
168 return kFALSE;
169}
170
171// based on O2 kinematics
172
174{
175 // this generator should leave all dimensions the same as in the incoming kinematics file
176 setMomentumUnit(1.);
177 setEnergyUnit(1.);
178 setPositionUnit(1.);
179 setTimeUnit(1.);
180
181 if (strncmp(name, "alien:/", 7) == 0 && !gGrid) {
182 TGrid::Connect("alien:");
183 if (!gGrid) {
184 LOG(fatal) << "Could not connect to alien, did you check the alien token?";
185 return;
186 }
187 }
188 mEventFile = TFile::Open(name);
189 if (mEventFile == nullptr) {
190 LOG(fatal) << "EventFile " << name << " not found";
191 return;
192 }
193 // the kinematics will be stored inside a branch MCTrack
194 // different events are stored inside different entries
195 auto tree = (TTree*)mEventFile->Get("o2sim");
196 if (tree) {
197 mEventBranch = tree->GetBranch("MCTrack");
198 if (mEventBranch) {
199 mEventsAvailable = mEventBranch->GetEntries();
200 LOG(info) << "Found " << mEventsAvailable << " events in this file";
201 }
202 mMCHeaderBranch = tree->GetBranch("MCEventHeader.");
203 if (mMCHeaderBranch) {
204 LOG(info) << "Found " << mMCHeaderBranch->GetEntries() << " event-headers";
205 } else {
206 LOG(warn) << "No MCEventHeader branch found in kinematics input file";
207 }
208 return;
209 }
210 LOG(error) << "Problem reading events from file " << name;
211}
212
214{
215 mConfig = std::make_unique<O2KineGenConfig>(pars);
216}
217
219{
220
221 // read and set params
222
223 LOG(info) << "Init \'FromO2Kine\' generator";
224 mSkipNonTrackable = mConfig->skipNonTrackable;
225 mContinueMode = mConfig->continueMode;
226 mRoundRobin = mConfig->roundRobin;
227 mRandomize = mConfig->randomize;
228 mRngSeed = mConfig->rngseed;
229 mRandomPhi = mConfig->randomphi;
230 if (mRandomize) {
231 gRandom->SetSeed(mRngSeed);
232 }
233
234 return true;
235}
236
238{
239 if (start < mEventsAvailable) {
240 mEventCounter = start;
241 } else {
242 LOG(error) << "start event bigger than available events\n";
243 }
244}
245
247{
248 // NOTE: This should be usable with kinematics files without secondaries
249 // It might need some adjustment to make it work with secondaries or to continue
250 // from a kinematics snapshot
251
252 // Randomize the order of events in the input file
253 if (mRandomize) {
254 mEventCounter = gRandom->Integer(mEventsAvailable);
255 LOG(info) << "GeneratorFromO2Kine - Picking event " << mEventCounter;
256 }
257
258 double dPhi = 0.;
259 // Phi rotation
260 if (mRandomPhi) {
261 dPhi = gRandom->Uniform(2 * TMath::Pi());
262 LOG(info) << "Rotating phi by " << dPhi;
263 }
264
265 if (mEventCounter < mEventsAvailable) {
266 int particlecounter = 0;
267
268 std::vector<o2::MCTrack>* tracks = nullptr;
269 mEventBranch->SetAddress(&tracks);
270 mEventBranch->GetEntry(mEventCounter);
271
272 if (mMCHeaderBranch) {
273 o2::dataformats::MCEventHeader* mcheader = nullptr;
274 mMCHeaderBranch->SetAddress(&mcheader);
275 mMCHeaderBranch->GetEntry(mEventCounter);
276 mOrigMCEventHeader.reset(mcheader);
277 }
278
279 for (auto& t : *tracks) {
280
281 // in case we do not want to continue, take only primaries
282 if (!mContinueMode && !t.isPrimary()) {
283 continue;
284 }
285
286 auto pdg = t.GetPdgCode();
287 auto px = t.Px();
288 auto py = t.Py();
289 if (mRandomPhi) {
290 // transformation applied through rotation matrix
291 auto cos = TMath::Cos(dPhi);
292 auto sin = TMath::Sin(dPhi);
293 auto newPx = px * cos - py * sin;
294 auto newPy = px * sin + py * cos;
295 px = newPx;
296 py = newPy;
297 }
298 auto pz = t.Pz();
299 auto vx = t.Vx();
300 auto vy = t.Vy();
301 auto vz = t.Vz();
302 auto m1 = t.getMotherTrackId();
303 auto m2 = t.getSecondMotherTrackId();
304 auto d1 = t.getFirstDaughterTrackId();
305 auto d2 = t.getLastDaughterTrackId();
306 auto e = t.GetEnergy();
307 auto vt = t.T() * 1e-9; // MCTrack stores in ns ... generators and engines use seconds
308 auto weight = t.getWeight();
309 auto wanttracking = t.getToBeDone();
310
311 if (mContinueMode) { // in case we want to continue, do only inhibited tracks
312 wanttracking &= t.getInhibited();
313 }
314
315 LOG(debug) << "Putting primary " << pdg;
316
317 mParticles.push_back(TParticle(pdg, t.getStatusCode().fullEncoding, m1, m2, d1, d2, px, py, pz, e, vx, vy, vz, vt));
318 mParticles.back().SetUniqueID((unsigned int)t.getProcess()); // we should propagate the process ID
319 mParticles.back().SetBit(ParticleStatus::kToBeDone, wanttracking);
320 mParticles.back().SetWeight(weight);
321
322 particlecounter++;
323 }
324 mEventCounter++;
325 if (mRoundRobin) {
326 LOG(info) << "Resetting event counter to 0; Reusing events from file";
327 mEventCounter = mEventCounter % mEventsAvailable;
328 }
329
330 if (tracks) {
331 delete tracks;
332 }
333
334 LOG(info) << "Event generator put " << particlecounter << " on stack";
335 return true;
336 } else {
337 LOG(error) << "GeneratorFromO2Kine: Ran out of events\n";
338 }
339 return false;
340}
341
343{
346 // we forward the original header information if any
347 if (mOrigMCEventHeader.get()) {
348 eventHeader->copyInfoFrom(*mOrigMCEventHeader.get());
349 }
350 // we forward also the original basic vertex information contained in FairMCEventHeader
351 static_cast<FairMCEventHeader&>(*eventHeader) = static_cast<FairMCEventHeader&>(*mOrigMCEventHeader.get());
352
353 // put additional information about input file and event number of the current event
354 eventHeader->putInfo<std::string>("forwarding-generator", "generatorFromO2Kine");
355 eventHeader->putInfo<std::string>("forwarding-generator_inputFile", mEventFile->GetName());
356 eventHeader->putInfo<int>("forwarding-generator_inputEventNumber", mEventCounter - 1);
357}
358
359namespace
360{
361// some helper to execute a command and capture it's output in a vector
362std::vector<std::string> executeCommand(const std::string& command)
363{
364 std::vector<std::string> result;
365 std::unique_ptr<FILE, int (*)(FILE*)> pipe(popen(command.c_str(), "r"), pclose);
366 if (!pipe) {
367 throw std::runtime_error("Failed to open pipe");
368 }
369
370 char buffer[1024];
371 while (fgets(buffer, sizeof(buffer), pipe.get()) != nullptr) {
372 std::string line(buffer);
373 // Remove trailing newline character, if any
374 if (!line.empty() && line.back() == '\n') {
375 line.pop_back();
376 }
377 result.push_back(line);
378 }
379 return result;
380}
381} // namespace
382
386
388{
389 // this simply passes tracks trough. Leave units intact.
390 setTimeUnit(1.);
391 setPositionUnit(1.);
392 setEnergyUnit(1.);
393
394 // initialize the event pool
395 if (mConfig.rngseed > 0) {
396 mRandomEngine.seed(mConfig.rngseed);
397 } else {
398 std::random_device rd;
399 mRandomEngine.seed(rd());
400 }
401 TString expPath(mConfig.eventPoolPath);
402 gSystem->ExpandPathName(expPath);
403 mPoolFilesAvailable = setupFileUniverse(expPath.Data());
404
405 if (mPoolFilesAvailable.size() == 0) {
406 LOG(error) << "No file found that can be used with EventPool generator";
407 return false;
408 }
409 LOG(info) << "Found " << mPoolFilesAvailable.size() << " available event pool files";
410
411 // now choose the actual file
412 std::uniform_int_distribution<int> distribution(0, mPoolFilesAvailable.size() - 1);
413 auto chosenIndex = distribution(mRandomEngine);
414 mFileChosen = mPoolFilesAvailable[chosenIndex];
415 LOG(info) << "EventPool is using file " << mFileChosen;
416
417 // we bring up the internal mO2KineGenerator
418 auto kine_config = O2KineGenConfig{
420 .continueMode = false,
421 .roundRobin = false,
422 .randomize = mConfig.randomize,
423 .rngseed = mConfig.rngseed,
424 .randomphi = mConfig.randomphi,
425 .fileName = mFileChosen};
426 mO2KineGenerator.reset(new GeneratorFromO2Kine(kine_config));
427 return mO2KineGenerator->Init();
428}
429
430namespace
431{
432namespace fs = std::filesystem;
433// checks a single file name
434bool checkFileName(std::string const& pathStr)
435{
436 // LOG(info) << "Checking filename " << pathStr;
437 try {
438 // Remove optional protocol prefix "alien://"
439 const std::string protocol = "alien://";
440 std::string finalPathStr(pathStr);
441 if (pathStr.starts_with(protocol)) {
442 finalPathStr = pathStr.substr(protocol.size());
443 }
444 fs::path path(finalPathStr);
445
446 // Check if the filename is "evtpool.root"
448 } catch (const fs::filesystem_error& e) {
449 // Invalid path syntax will throw an exception
450 std::cerr << "Filesystem error: " << e.what() << '\n';
451 return false;
452 } catch (...) {
453 // Catch-all for other potential exceptions
454 std::cerr << "An unknown error occurred while checking the path.\n";
455 return false;
456 }
457}
458
459// checks a whole universe of file names
460bool checkFileUniverse(std::vector<std::string> const& universe)
461{
462 if (universe.size() == 0) {
463 return false;
464 }
465 for (auto& fn : universe) {
466 if (!checkFileName(fn)) {
467 return false;
468 }
469 }
470 // TODO: also check for a common path structure with maximally 00X as only difference
471
472 return true;
473}
474
475std::vector<std::string> readLines(const std::string& filePath)
476{
477 std::vector<std::string> lines;
478
479 // Check if the file is a valid text file
480 fs::path path(filePath);
481
482 // Open the file
483 std::ifstream file(filePath);
484 if (!file.is_open()) {
485 throw std::ios_base::failure("Failed to open the file.");
486 }
487
488 // Read up to n lines
489 std::string line;
490 while (std::getline(file, line)) {
491 lines.push_back(line);
492 }
493 return lines;
494}
495
496// Function to find all files named eventpool_filename under a given path
497std::vector<std::string> getLocalFileList(const fs::path& rootPath)
498{
499 std::vector<std::string> result;
500
501 // Ensure the root path exists and is a directory
502 if (!fs::exists(rootPath) || !fs::is_directory(rootPath)) {
503 throw std::invalid_argument("The provided path is not a valid directory.");
504 }
505
506 // Iterate over the directory and subdirectories
507 for (const auto& entry : fs::recursive_directory_iterator(rootPath)) {
508 if (entry.is_regular_file() && entry.path().filename() == GeneratorFromEventPool::eventpool_filename) {
509 result.push_back(entry.path().string());
510 }
511 }
512 return result;
513}
514
515} // end anonymous namespace
516
519std::vector<std::string> GeneratorFromEventPool::setupFileUniverse(std::string const& path) const
520{
521 // the path could refer to a local or alien filesystem; find out first
522 bool onAliEn = strncmp(path.c_str(), std::string(alien_protocol_prefix).c_str(), alien_protocol_prefix.size()) == 0;
523 std::vector<std::string> result;
524
525 if (onAliEn) {
526 // AliEn case
527 // we support: (a) an actual evtgen file and (b) a path containing multiple eventfiles
528
529 auto alienStatTypeCommand = std::string("alien.py stat ") + mConfig.eventPoolPath + std::string(" 2>/dev/null | grep Type ");
530 auto typeString = executeCommand(alienStatTypeCommand);
531 if (typeString.size() == 0) {
532 return result;
533 } else if (typeString.size() == 1 && typeString.front() == std::string("Type: f")) {
534 // this is a file:
535 // 1) list of files ==> select one of the lines and use it
536 // 2) evtpool.root ==> use as it is
537 if (!checkFileName(path)) {
538 // Assume it is a text file containing a list of pools
539 auto tmpPath = (std::filesystem::temp_directory_path() / ("list_" + std::to_string(getpid()) + ".txt")).string();
540 auto res = TFile::Cp(Form("%s?filetype=raw", path.c_str()), tmpPath.c_str());
541 if (!res) {
542 LOG(fatal) << "Failed to copy file from AliEn: " << path;
543 } else {
544 auto files = readLines(tmpPath);
545 if (checkFileUniverse(files)) {
546 result = files;
547 } else {
548 LOG(fatal) << "The list of files in " << path << " is not valid";
549 }
550 std::filesystem::remove(tmpPath);
551 }
552 return result;
553 }
554 result.push_back(mConfig.eventPoolPath);
555 return result;
556 } else if (typeString.size() == 1 && typeString.front() == std::string("Type: d")) {
557 // this is a directory
558 // construct command to find actual event files
559 std::string alienSearchCommand = std::string("alien.py find ") +
560 mConfig.eventPoolPath + "/ " + std::string(eventpool_filename);
561
562 auto universe_vector = executeCommand(alienSearchCommand);
563 // check vector
564 if (!checkFileUniverse(universe_vector)) {
565 return result;
566 }
567 for (auto& f : universe_vector) {
568 f = std::string(alien_protocol_prefix) + f;
569 }
570
571 return universe_vector;
572 } else {
573 LOG(error) << "Unsupported file type";
574 return result;
575 }
576 } else {
577 // local file case
578 // check if the path is a regular file
579 auto is_actual_file = std::filesystem::is_regular_file(path);
580 if (is_actual_file) {
581 // The files must match a criteria of being canonical paths ending with evtpool.root
582 if (checkFileName(path)) {
583 TFile rootfile(path.c_str(), "OPEN");
584 if (!rootfile.IsZombie()) {
585 result.push_back(path);
586 return result;
587 }
588 } else {
589 // otherwise assume it is a text file containing a list of files themselves
590 auto files = readLines(path);
591 if (checkFileUniverse(files)) {
592 result = files;
593 return result;
594 }
595 }
596 } else {
597 // check if the path is just a path
598 // In this case we need to search something and check
599 auto is_dir = std::filesystem::is_directory(path);
600 if (!is_dir) {
601 return result;
602 }
603 auto files = getLocalFileList(path);
604 if (checkFileUniverse(files)) {
605 result = files;
606 return result;
607 }
608 }
609 }
610 return result;
611}
612
613} // namespace eventgen
614} // end namespace o2
615
std::ostringstream debug
int32_t i
configStandalone Light OpenGL display display_light Apply smoothing to points Enable Z buffer Highlight links Highlight seeds Highlight sector tracks Highlight final tracks Show individual Show related Highlight grid Show only individual collision Color clusters belonging to track objects Set line Enable drawing TPC data Enable drawing TOF data Enable drawing magnetic field Set field line step count Invert colors configStandalone Heavy OpenGL display display_heavy Show tracks with ITS contribution Show tracks with TOF contribution Enable propagation of loopers Show clusters at nominal x of pad row for early transformed data Split CE tracks when they cross the central Mark clusters Mark adjacent clusters Hide rejected tracks Apply filter on tracks to be displayed Separate increase X h configStandalone Camera window renderer OpenGL display display_camera Orient the camera such that the y axis is always upwards Full Screen MultiSample Anti Downsampling Anti Enable Vertical Sync Target frame or if the backend cannot limit to the refresh Use OpenGL indirect draws to reduce number of draw calls Display h configStandalone Vulkan display display_vulkan Have uniform buffers in host accessible device memory h configStandalone Internal display display_internal Number of updates the Qt GUI may send ahead of the last one the display has before it waits for the display Opacity of the console background Number of console lines the history is shortened to this when it reaches twice the size Time in seconds an info message fades out after setInfoTime h OpenGL display display Font size Do not use Freetype for font Renderer for event Frontend to use for event ROOT macros used as track filter Console script file
Timeframe settings Average distance in cm of events merged into Randomize distance around average distance of merged events Simulate correct bunch interactions instead of placing only the average number of events A value[n] sets TFlen for[n] collisions in Number of bunches per trainsort Number of bunch trains Instantaneous interaction rate Do not simulate border Total number of collisions to be placed in the interior of all time Do not select random but walk over array of events in stride steps h Event generator settings h configStandalone Use CPU for GPU Force usage of the specified GPU device no CPU fallback Continue processing after an error First event to Number of events to Number of iterations to Number of iterations to Number of initial iterations excluded from const char e
ClassImp(o2::eventgen::GeneratorFromEventPool)
char error[CURL_ERROR_SIZE]
std::vector< o2::its::TrackITS > tracks
Definition of the MCTrack class.
@ kToBeDone
uint32_t res
Definition RawData.h:0
virtual void AddTrack(Int_t pdgid, Double_t px, Double_t py, Double_t pz, Double_t vx, Double_t vy, Double_t vz, Int_t parent=-1, Bool_t wanttracking=true, Double_t e=-9e9, Double_t tof=0., Double_t weight=0., TMCProcess proc=kPPrimary)
void copyInfoFrom(MCEventHeader const &other)
inits info fields from another Event header
void putInfo(std::string const &key, T const &value)
static constexpr std::string_view eventpool_filename
static constexpr std::string_view alien_protocol_prefix
std::vector< std::string > setupFileUniverse(std::string const &path) const
bool ReadEvent(FairPrimaryGenerator *primGen) override
void updateHeader(o2::dataformats::MCEventHeader *eventHeader) override
void setPositionUnit(double val)
Definition Generator.h:89
void setEnergyUnit(double val)
Definition Generator.h:87
void setTimeUnit(double val)
Definition Generator.h:91
std::vector< TParticle > mParticles
Definition Generator.h:161
void setMomentumUnit(double val)
Definition Generator.h:85
GLuint64EXT * result
Definition glcorearb.h:5662
GLuint const GLchar * name
Definition glcorearb.h:781
GLdouble f
Definition glcorearb.h:310
GLuint GLuint GLfloat weight
Definition glcorearb.h:5477
GLsizei const GLchar *const * path
Definition glcorearb.h:3591
GLuint start
Definition glcorearb.h:469
int32_t const char int32_t line
a couple of static helper functions to create timestamp values for CCDB queries or override obsolete ...
std::string to_string(gsl::span< T, Size > span)
Definition common.h:52
LOG(info)<< "Compressed in "<< sw.CpuTime()<< " s"
std::unique_ptr< TTree > tree((TTree *) flIn.Get(std::string(o2::base::NameConf::CTFTREENAME).c_str()))
std::random_device rd