GamR  0.0.0
GammaROOT
Loading...
Searching...
No Matches
ExpDefn.tt
Go to the documentation of this file.
1/* STD */
2#include <cstring>
3#include <fstream>
4#include <iostream>
5#include <sstream>
6#include <stdexcept>
7#include <streambuf>
8
9/* ROOT */
10#include <ROOT/TSeq.hxx>
11#include <TNamed.h>
12
13/* GAMR */
14#include <utils/RTTI.hh>
15#include <utils/Tuples.hh>
16
17namespace GamR {
18 namespace Tree {
19
20 // ------------------------------------------------------------
21 template <class... ADefns>
22 struct TExpDefn<ADefns...>::FillDetDefns {
25 FillDetDefns(TExpDefn *parent) : p(parent), idxDetGroup(0){};
26 template <typename DetDefn>
27 void operator()(std::vector<DetDefn> &defnvec)
28 {
29 std::stringstream ss;
30 ss.str("");
31 ss.clear();
32 const auto &itGroup = p->fDetGroups.at(idxDetGroup);
33
34 ss << p->fINIReader.Get("array", itGroup, "");
35 if (ss.str().empty()) {
36 throw std::runtime_error("Couldn't find any active detectors for group: " + itGroup);
37 }
38
39 std::string detname;
40 while (ss >> detname) {
41 // Read deets about this detector
42 int id = p->fINIReader.GetInteger(detname, "id", 0);
43 int atleast = p->fINIReader.GetInteger(detname, "require", 1);
44 std::string eff = p->fINIReader.Get(detname, "efficiency", "1");
45 std::string cal = p->fINIReader.Get(detname, "calibration", "");
46 std::string poll = p->fINIReader.Get(detname, "pollgate", "");
47 std::string branches = p->fINIReader.Get(detname, "branches", "");
48 int pollfreq = p->fINIReader.GetInteger(detname, "pollfreq", 50000);
49
50 if (cal.empty()) {
51 throw std::runtime_error(detname + " needs a calibration.");
52 }
53 if (branches.empty()) {
54 throw std::runtime_error(detname + " needs rawtree branches for its datums.");
55 }
56 // Now lets emplace a detector definition into the tuples vector
57 defnvec.emplace_back(itGroup, id, detname, pollfreq);
58 // Take that last definition and fill it up.
59 auto &defn = defnvec.back();
60 defn.SetPtrs(p->fBranchMap, branches);
61 defn.SetCalFuncs(cal);
62 defn.SetPollGates(poll);
63 defn.SetEffFunc(eff);
64 defn.SetRequired(atleast);
65 }
66 ++idxDetGroup;
67 // All done, move on to the next group i.e. tuple element.
68 }
69 };
70
71 // ------------------------------------------------------------
72 template <class... ADefns>
73 Int_t TExpDefn<ADefns...>::Load(std::vector<std::string> rootfn, std::string inifn, Bool_t quiet)
74 {
75 // --- TExpDefn: Make pointers in fBranchMap to fRawChain
76 fRawChain = new TChain("RawTree");
77
78 for (auto filename : rootfn) {
79 if (!fRawChain->AddFile(filename.c_str())) {
80 throw std::runtime_error("file invalid: " + filename);
81 }
82 if (!quiet) {
83 std::cout << "Added file " + filename + " to chain" << std::endl;
84 }
85 }
86
87 // --- --- TExpDefn: Get the branches from fRawChain
88 TObjArray *branchlist = fRawChain->GetListOfBranches();
89 if (!quiet) {
90 std::cout << "Got list of branches, size: " << fRawChain->GetNbranches() << std::endl;
91 }
92
93 // --- --- TExpDefn: Start making pointers
94 for (const auto &branch : *branchlist) {
95 std::string brname = branch->GetName();
96 fBranchMap[brname] = std::malloc(8 * sizeof(Char_t));
97 // Abritary equivalent of new. We reinterpret this pointer
98 // into the correct type when we call SetPtrs in the
99 // DetDefn.
100
101 // We're allocating 64 bits (8 bytes), if a branch holds
102 // something larger than this, I have no idea what will
103 // happen.
104
105 // TODO: Using branch ->GetName() at CLING actually returns
106 // a string that has a code corresponding to the branch data
107 // type!
108 //
109 // We could use this to malloc the correct amount of space.
110 // Then again, why are we chasing bits on a desktop
111 // computer? Cache misses?
112
113 // Point the tree at the branch map, and continue loop.
114 fRawChain->SetBranchAddress(brname.c_str(), fBranchMap[brname]);
115 if (!quiet) {
116 std::cout << "[" << brname << "] ";
117 }
118 }
119 if (!quiet) {
120 std::cout << std::endl;
121 }
122
123 // --- INI: Load up the config file
124 std::ifstream t(inifn);
125 fINI.assign((std::istreambuf_iterator<char>(t)), std::istreambuf_iterator<char>());
126 // fINI.insert(0, "# Applied to RawChain in: "+rootfn+"\n"); NOT SURE WHAT
127 // THIS IS MEANT TO BE DOING TJG
128
129 fINIReader = INIReader(inifn);
130 if (fINIReader.ParseError() < 0) {
131 throw std::runtime_error("Can't load " + inifn);
132 }
133
134 // --- INI: Under array, get groups
135 std::stringstream ss;
136 ss.str("");
137 ss.clear();
138 ss << fINIReader.Get("array", "groups", "");
139 if (ss.str().empty()) {
140 throw std::runtime_error("Couldn't find any detector groups");
141 } else if (!quiet) {
142 std::cout << "Active groups: " << ss.str() << std::endl;
143 }
144
145 // --- TExpDefn: Save the groups
146 std::string group;
147 while (ss >> group) {
148 fDetGroups.push_back(group);
149 }
150
151 // --- TExpDefn: Should have the same number of groups as there are types,
152 // technically okay with less.
153 if (fDetGroups.size() != sizeof...(ADefns)) {
154 throw std::runtime_error("Experiment Definition expects " + std::to_string(sizeof...(ADefns)) + " groups.");
155 }
156
157 // --- fill this objects tuple! (templates and io amazedawg!)
159 if (!quiet) {
160 std::cout << "Experiment defined successfully." << std::endl;
161 }
162 return 0;
163 } // Load
164
165 // ------------------------------------------------------------ TJG 03/2020 - attempt to update to raw arbitrary non-root tree file
166 template <class... ADefns>
167 Int_t TExpDefn<ADefns...>::LoadRaw(std::vector<std::string> branchlist, std::string inifn, Bool_t quiet)
168 {
169 // --- --- TExpDefn: Start making pointers
170 for (const auto &branch : branchlist) {
171 fBranchMap[branch] = std::malloc(8 * sizeof(Char_t));
172 if (!quiet) {
173 std::cout << "[" << branch << "] ";
174 }
175 }
176 if (!quiet) {
177 std::cout << std::endl;
178 }
179
180 // --- INI: Load up the config file
181 std::ifstream t(inifn);
182 fINI.assign((std::istreambuf_iterator<char>(t)), std::istreambuf_iterator<char>());
183 // fINI.insert(0, "# Applied to RawChain in: "+rootfn+"\n"); NOT SURE WHAT
184 // THIS IS MEANT TO BE DOING TJG
185
186 fINIReader = INIReader(inifn);
187 if (fINIReader.ParseError() < 0) {
188 throw std::runtime_error("Can't load " + inifn);
189 }
190
191 // --- INI: Under array, get groups
192 std::stringstream ss;
193 ss.str("");
194 ss.clear();
195 ss << fINIReader.Get("array", "groups", "");
196 if (ss.str().empty()) {
197 throw std::runtime_error("Couldn't find any detector groups");
198 } else if (!quiet) {
199 std::cout << "Active groups: " << ss.str() << std::endl;
200 }
201
202 // --- TExpDefn: Save the groups
203 std::string group;
204 while (ss >> group) {
205 fDetGroups.push_back(group);
206 }
207
208 // --- TExpDefn: Should have the same number of groups as there are types,
209 // technically okay with less.
210 if (fDetGroups.size() != sizeof...(ADefns)) {
211 throw std::runtime_error("Experiment Definition expects " + std::to_string(sizeof...(ADefns)) + " groups.");
212 }
213
214 // --- fill this objects tuple! (templates and io amazedawg!)
216 if (!quiet) {
217 std::cout << "Experiment defined successfully." << std::endl;
218 }
219 return 0;
220 } // LoadRaw
221
222 template <class ...ADefns>
223 void TExpDefn<ADefns...>::ResetBranches(std::vector<std::string> branchnames) {
224 for (auto &name : branchnames) {
225 if (fBranchMap.find(name) != fBranchMap.end()) {
226 std::memset(fBranchMap[name], 0, 8*sizeof(Char_t));
227 }
228 }
229 }
230
231 // ------------------------------------------------------------
232 template <class... ADefns>
233 template <typename EventType>
234 ULong64_t TExpDefn<ADefns...>::Convert(std::string outfn, ULong64_t eventoffset, ULong64_t nevents, Bool_t quiet,
235 Int_t compression, ULong64_t splitmb, Bool_t overwrite)
236 {
237 /* Converts an xyz2root tree to EventType tree */
238
239 // --- TExpDefn: Open up the output file.
240 if (overwrite) {
241 fOutFile = new TFile(outfn.c_str(), "RECREATE");
242 } else {
243 fOutFile = new TFile(outfn.c_str(), "NEW");
244 }
245 if (fOutFile->IsZombie() || !fOutFile->IsOpen()) {
246 /* overwrite? */
247 while (true) {
248 std::cout << "Outfile already exists, overwrite y/n? ";
249 char overwrite[256]; // seriously C style - don't use this an example.
250 if (std::fgets(overwrite, sizeof overwrite, stdin) == NULL || overwrite[0] == '\n') {
251 continue;
252 } else if (overwrite[1] == '\n') { /* invalid if more than a single character entered */
253 if (overwrite[0] == 'y') {
254 fOutFile = new TFile(outfn.c_str(), "RECREATE");
255 break;
256 } else if (overwrite[0] == 'n') {
257 std::cout << "Outfile invalid, quitting" << std::endl;
258 return -1;
259 }
260 }
261 } /* end input loop */
262 }
263
264 // --- TExpDefn: Set output file settings
265 fOutFile->SetCompressionSettings(compression); // lzma01 (101 = gzip01)
266
267 // Write the INI File -- not allowed sub directories TTree::ChangeFile()
268 // documentation
269 // fOutFile -> mkdir("config");
270 // fOutFile -> cd("config");
271 TNamed defn("TreeDefn", fINI.c_str());
272 defn.Write();
273 // fOutFile -> cd("/");
274
275 // --- TExpDefn: Create the output tree
276 fOutTree = new TTree("EventTree", outfn.c_str());
277 fOutTree->SetMaxTreeSize(splitmb * 1000000LL); // 2GB max size
278 EventType::Class()->IgnoreTObjectStreamer(); // Saves space
279 EventType *ptrEvent = new EventType();
280
281 fOutTree->Branch("Events", DEMANGLE_TYPEID_NAME(*ptrEvent), &ptrEvent, 10000000, 99);
282
283 // Speed it up before going for it
284 // fOutTree -> SetImplicitMT(kTRUE);
285 // fOutTree -> SetCacheLearnEntries(10);
286 // fOutTree -> SetMaxVirtualSize(200000000);
287 // does nothing
288
289 // --- Convert: Loop over fRawChain, Populate ptrEvent, and fOutTree->Fill()
290 auto nRawEntries = static_cast<ULong64_t>(fRawChain->GetEntries());
291 if (nevents && nevents < nRawEntries) {
292 nRawEntries = nevents;
293 };
294
295 auto timestart = std::chrono::system_clock::now();
296 // See https://root.cern.ch/doc/master/imt001__parBranchProcessing_8C.html
297 for (ULong64_t ixEventNum : ROOT::TSeqUL(nRawEntries)) {
298 //------------------------
299 // Get local entry
300 ULong64_t ixLocalNum = fRawChain->LoadTree(ixEventNum);
301
302 // -----------------------
303 // Print back the progress
304 if (!quiet && ixEventNum % 10000 == 0) { // verbose = 1
305 auto now = std::chrono::system_clock::now();
306 std::chrono::duration<double> sec = now - timestart;
307 auto speed = ixEventNum / sec.count();
308 auto remain = static_cast<ULong64_t>((nRawEntries - ixEventNum) / speed);
309 auto hours = remain / 3600;
310 auto minutes = remain / 60 % 60;
311 auto seconds = remain % 60;
312 Float_t percent = 100.0f * ixEventNum / nRawEntries;
313 printf("\rConverted Events: %lld/%lld [%.1f%%] Time Remaining: "
314 "%02llu:%02llu:%02llu [%.0f k/s]",
315 ixEventNum, nRawEntries, percent, hours, minutes, seconds, speed / 1000);
316 fflush(stdout);
317 }
318
319 // ------------------------
320 // This populates fDetDefns
321 fRawChain->GetTree()->GetEntry(ixLocalNum);
322
323 // ---------------
324 // Setup the Event
325 ptrEvent->Reset();
326 ptrEvent->SetEventNum(ixEventNum + eventoffset);
327
328 // --------------
329 // Fill the Event
330 ptrEvent->FillEvent(fDetDefns);
331 fOutTree->Fill();
332
333 } /* end loop over fRawChain */
334
335 // --- Convert: Finishing
336 std::cout << std::endl;
337 fOutFile->Write("", TObject::kOverwrite);
338 // As per TTree::ChangeFile() documentatino
339 fOutTree->GetCurrentFile()->Write("", TObject::kOverwrite);
340
341 if (!quiet) {
342 fOutTree->Print();
343 fOutTree->Show(0);
344 }
345
346 fRawChain->ResetBranchAddresses();
347 fOutTree->ResetBranchAddresses();
348
349 delete ptrEvent;
350 return nRawEntries;
351 }
352
353 } // namespace Tree
354} // namespace GamR
void ss(std::vector< int > indexes, TCanvas *canvas, Option_t *option)
#define DEMANGLE_TYPEID_NAME(x)
Definition RTTI.hh:6
Int_t Load(std::vector< std::string > rootfn, std::string inifn, Bool_t quiet=kFALSE)
Definition ExpDefn.tt:73
std::map< std::string, void * > fBranchMap
Definition ExpDefn.hh:35
std::vector< std::string > fDetGroups
Definition ExpDefn.hh:36
ULong64_t Convert(std::string outfn, ULong64_t eventoffset, ULong64_t nevents=0, Bool_t quiet=kFALSE, Int_t compression=201, ULong64_t splitmb=2000, Bool_t overwrite=kFALSE)
Definition ExpDefn.tt:234
void ResetBranches(std::vector< std::string >)
Definition ExpDefn.tt:223
std::string fINI
Definition ExpDefn.hh:38
std::tuple< std::vector< ADefns >... > fDetDefns
Definition ExpDefn.hh:34
Int_t LoadRaw(std::vector< std::string > branchlist, std::string inifn, Bool_t quiet)
Definition ExpDefn.tt:167
INIReader fINIReader
Definition ExpDefn.hh:37
void for_each_in_tuple(std::tuple< Ts... > &t, F f)
Applies function on each element of tuple.
Definition Tuples.hh:67
Definition Gain.cc:19
FillDetDefns(TExpDefn *parent)
Definition ExpDefn.tt:25
void operator()(std::vector< DetDefn > &defnvec)
Definition ExpDefn.tt:27