Logo ROOT   6.16/01
Reference Guide
TTreeReaderGenerator.cxx
Go to the documentation of this file.
1// @(#)root/treeplayer:$Id$
2// Author: Akos Hajdu 22/06/2015
3
4/*************************************************************************
5 * Copyright (C) 1995-2015, Rene Brun and Fons Rademakers and al. *
6 * All rights reserved. *
7 * *
8 * For the licensing terms see $ROOTSYS/LICENSE. *
9 * For the list of contributors see $ROOTSYS/README/CREDITS. *
10 *************************************************************************/
11
13#include <algorithm>
14#include <stdio.h>
15#include <fstream>
16
17#include "TBranchElement.h"
18#include "TChain.h"
19#include "TClass.h"
20#include "TClassEdit.h"
21#include "TClonesArray.h"
22#include "TError.h"
23#include "TFile.h"
24#include "TLeaf.h"
25#include "TLeafC.h"
26#include "TLeafObject.h"
27#include "TROOT.h"
28#include "TStreamerElement.h"
29#include "TStreamerInfo.h"
30#include "TTree.h"
33
34namespace ROOT {
35namespace Internal {
36
37 ////////////////////////////////////////////////////////////////////////////////
38 /// Constructor. Analyzes the tree and writes selector.
39
41 TTreeGeneratorBase(tree, option), fClassname(classname),
42 fIncludeAllLeaves(kFALSE), fIncludeAllTopmost(kFALSE)
43 {
47 }
48
49 ////////////////////////////////////////////////////////////////////////////////
50 /// Add a reader to the generated code.
51
54 {
55 if(BranchNeedsReader(branchName, parent, isLeaf)) {
56 // Ignore unknown types
57 if (dataType.EqualTo("")) {
58 Warning("TTreeReaderGenerator::AddReader", "Ignored branch %s because type is unsupported.", branchName.Data());
59 return;
60 }
61 // Loop through existing readers to check duplicate branch names
62 TIter next(&fListOfReaders);
63 TTreeReaderDescriptor *descriptor;
64 while ( ( descriptor = (TTreeReaderDescriptor*)next() ) ) {
65 if (descriptor->fBranchName.EqualTo(branchName)) {
66 Warning("AddReader", "Ignored branch %s because a branch with the same name already exists. "
67 "TTreeReader requires an unique name for the branches. You may need to "
68 "put a dot at the end of the name of top-level branches.", branchName.Data());
69 return;
70 }
71 }
72 name.ReplaceAll('.', '_'); // Replace dots with underscore
73 // Remove array dimensions from name
74 while (name.Index('[') >= 0 && name.Index(']') >= 0 && name.Index(']') > name.Index('[')) {
75 name.Remove(name.Index('['), name.Index(']') - name.Index('[') + 1);
76 }
78 }
79 }
80
81 ////////////////////////////////////////////////////////////////////////////////
82 /// Analyse sub-branches of 'branch' recursively and extract readers.
83
85 {
86 if (info==0) info = branch->GetInfo();
87
89
90 return AnalyzeBranches(desc, branches, info);
91 }
92
93 ////////////////////////////////////////////////////////////////////////////////
94 /// Analyse sub-branches 'branches' recursively and extract readers.
95
97 {
98 UInt_t lookedAt = 0; // Number of sub-branches analyzed
99 ELocation outer_isclones = kOut; // Is the parent branch a container
100 TString containerName; // Container name
101 TString subBranchPrefix; // Prefix of sub-branch (if the elements and sub-branches do not match).
102 Bool_t skipped = false; // Should the branch be skipped
103
104 // Check for containers (TClonesArray or STL)
105 {
106 TIter peek = branches;
107 TBranchElement *branch = (TBranchElement*)peek();
108 if (desc && desc->IsClones()) {
109 outer_isclones = kClones;
110 containerName = "TClonesArray";
111 } else if (desc && desc->IsSTL()) {
112 outer_isclones = kSTL;
113 containerName = desc->fContainerName;
114 } else if (!desc && branch && branch->GetBranchCount() == branch->GetMother()) {
115 if ( ((TBranchElement*)(branch->GetMother()))->GetType()==3) {
116 outer_isclones = kClones;
117 containerName = "TClonesArray";
118 } else {
119 outer_isclones = kSTL;
120 containerName = branch->GetMother()->GetClassName();
121 }
122 }
123 // FIXME: this is wrong because 'branch' is the first sub-branch and even though
124 // it can be a collection, it does not mean that the other sub-branches are
125 // collections as well.
126 /* else if (branch->GetType() == 3) {
127 outer_isclones = kClones;
128 containerName = "TClonesArray";
129 } else if (branch->GetType() == 4) {
130 outer_isclones = kSTL;
131 containerName = branch->GetMother()->GetSubBranch(branch)->GetClassName();
132 }*/
133 if (desc) {
134 subBranchPrefix = desc->fSubBranchPrefix;
135 } else {
136 TBranchElement *mom = (TBranchElement*)branch->GetMother();
137 subBranchPrefix = mom->GetName();
138 if (subBranchPrefix[subBranchPrefix.Length()-1]=='.') {
139 subBranchPrefix.Remove(subBranchPrefix.Length()-1);
140 } else if (mom->GetType()!=3 && mom->GetType() != 4) {
141 subBranchPrefix = "";
142 }
143 }
144 }
145
146 // Loop through elements (i.e., sub-branches). The problem is that the elements
147 // and sub-branches do not always match. For example suppose that class A contains
148 // members x and y, and there is a class B inheriting from A and containing an extra
149 // member z. It is possible that B has two elements: A and z but three sub-branches
150 // x, y and z. Therefore, the branch iterator is treated differently.
151 TIter elements( info->GetElements() );
152 for( TStreamerElement *element = (TStreamerElement*)elements();
153 element;
154 element = (TStreamerElement*)elements() )
155 {
156 Bool_t isBase = false; // Does the element correspond to a base class
157 Bool_t usedBranch = kTRUE; // Does the branch correspond to the element (i.e., they match)
158 Bool_t isLeaf = true; // Is the branch a leaf (i.e. no sub-branches)
159 TIter peek = branches; // Iterator for sub-branches
160 // Always start with the first available sub-branch and if it does not match the element,
161 // try the next ones
162 TBranchElement *branch = (TBranchElement*)peek();
163 // There is a problem if there are more elements than branches
164 if (branch==0) {
165 if (desc) {
166 Error("AnalyzeBranches","Ran out of branches when looking in branch %s, class %s",
167 desc->fBranchName.Data(), info->GetName());
168 } else {
169 Error("AnalyzeBranches","Ran out of branches when looking in class %s, element %s",
170 info->GetName(), element->GetName());
171 }
172 return lookedAt;
173 }
174
175 if (info->GetClass()->GetCollectionProxy() && strcmp(element->GetName(),"This")==0) {
176 continue; // Skip the artifical streamer element.
177 }
178
179 if (element->GetType() == -1) {
180 continue; // This is an ignored TObject base class.
181 }
182
183 // Get branch name
184 TString branchname = branch->GetName();
185 TString branchEndName;
186 {
187 TLeaf *leaf = (TLeaf*)branch->GetListOfLeaves()->At(0);
188 if (leaf && outer_isclones == kOut
189 && !(branch->GetType() == 3 || branch->GetType() == 4)) branchEndName = leaf->GetName();
190 else branchEndName = branch->GetName();
191 Int_t pos;
192 pos = branchEndName.Index(".");
193 if (pos!=-1) {
194 if (subBranchPrefix.Length() && branchEndName.BeginsWith(subBranchPrefix)) {
195 branchEndName.Remove(0, subBranchPrefix.Length() + 1);
196 }
197 }
198 }
199
200 TString dataType; // Data type of reader
201 TTreeReaderDescriptor::ReaderType readerType = TTreeReaderDescriptor::ReaderType::kValue;
202 Bool_t ispointer = false;
203 ELocation isclones = outer_isclones; // Is the actual sub-branch a collection (inherit from parent branch)
204 // Get data type
205 switch(element->GetType()) {
206 // Built-in types
207 case TVirtualStreamerInfo::kBool: { dataType = "Bool_t"; readerType = TTreeReaderDescriptor::ReaderType::kValue; break; }
208 case TVirtualStreamerInfo::kChar: { dataType = "Char_t"; readerType = TTreeReaderDescriptor::ReaderType::kValue; break; }
209 case TVirtualStreamerInfo::kShort: { dataType = "Short_t"; readerType = TTreeReaderDescriptor::ReaderType::kValue; break; }
210 case TVirtualStreamerInfo::kInt: { dataType = "Int_t"; readerType = TTreeReaderDescriptor::ReaderType::kValue; break; }
211 case TVirtualStreamerInfo::kLong: { dataType = "Long_t"; readerType = TTreeReaderDescriptor::ReaderType::kValue; break; }
212 case TVirtualStreamerInfo::kLong64: { dataType = "Long64_t"; readerType = TTreeReaderDescriptor::ReaderType::kValue; break; }
213 case TVirtualStreamerInfo::kFloat: { dataType = "Float_t"; readerType = TTreeReaderDescriptor::ReaderType::kValue; break; }
214 case TVirtualStreamerInfo::kFloat16: { dataType = "Float16_t"; readerType = TTreeReaderDescriptor::ReaderType::kValue; break; }
215 case TVirtualStreamerInfo::kDouble: { dataType = "Double_t"; readerType = TTreeReaderDescriptor::ReaderType::kValue; break; }
216 case TVirtualStreamerInfo::kDouble32:{ dataType = "Double32_t"; readerType = TTreeReaderDescriptor::ReaderType::kValue; break; }
217 case TVirtualStreamerInfo::kUChar: { dataType = "UChar_t"; readerType = TTreeReaderDescriptor::ReaderType::kValue; break; }
218 case TVirtualStreamerInfo::kUShort: { dataType = "unsigned short"; readerType = TTreeReaderDescriptor::ReaderType::kValue; break; }
219 case TVirtualStreamerInfo::kUInt: { dataType = "unsigned int"; readerType = TTreeReaderDescriptor::ReaderType::kValue; break; }
220 case TVirtualStreamerInfo::kULong: { dataType = "ULong_t"; readerType = TTreeReaderDescriptor::ReaderType::kValue; break; }
221 case TVirtualStreamerInfo::kULong64: { dataType = "ULong64_t"; readerType = TTreeReaderDescriptor::ReaderType::kValue; break; }
222 case TVirtualStreamerInfo::kBits: { dataType = "unsigned int"; readerType = TTreeReaderDescriptor::ReaderType::kValue; break; }
223 // Character arrays
224 case TVirtualStreamerInfo::kCharStar: { dataType = "Char_t"; readerType = TTreeReaderDescriptor::ReaderType::kArray; break; }
225 // Array of built-in types [8]
226 case TVirtualStreamerInfo::kOffsetL + TVirtualStreamerInfo::kBool: { dataType = "Bool_t"; readerType = TTreeReaderDescriptor::ReaderType::kArray; break; }
227 case TVirtualStreamerInfo::kOffsetL + TVirtualStreamerInfo::kChar: { dataType = "Char_t"; readerType = TTreeReaderDescriptor::ReaderType::kArray; break; }
228 case TVirtualStreamerInfo::kOffsetL + TVirtualStreamerInfo::kShort: { dataType = "Short_t"; readerType = TTreeReaderDescriptor::ReaderType::kArray; break; }
229 case TVirtualStreamerInfo::kOffsetL + TVirtualStreamerInfo::kInt: { dataType = "Int_t"; readerType = TTreeReaderDescriptor::ReaderType::kArray; break; }
230 case TVirtualStreamerInfo::kOffsetL + TVirtualStreamerInfo::kLong: { dataType = "Long_t"; readerType = TTreeReaderDescriptor::ReaderType::kArray; break; }
231 case TVirtualStreamerInfo::kOffsetL + TVirtualStreamerInfo::kLong64: { dataType = "Long64_t"; readerType = TTreeReaderDescriptor::ReaderType::kArray; break; }
232 case TVirtualStreamerInfo::kOffsetL + TVirtualStreamerInfo::kFloat: { dataType = "Float_t"; readerType = TTreeReaderDescriptor::ReaderType::kArray; break; }
233 case TVirtualStreamerInfo::kOffsetL + TVirtualStreamerInfo::kFloat16: { dataType = "Float16_t"; readerType = TTreeReaderDescriptor::ReaderType::kArray; break; }
234 case TVirtualStreamerInfo::kOffsetL + TVirtualStreamerInfo::kDouble: { dataType = "Double_t"; readerType = TTreeReaderDescriptor::ReaderType::kArray; break; }
235 case TVirtualStreamerInfo::kOffsetL + TVirtualStreamerInfo::kDouble32:{ dataType = "Double32_t"; readerType = TTreeReaderDescriptor::ReaderType::kArray; break; }
236 case TVirtualStreamerInfo::kOffsetL + TVirtualStreamerInfo::kUChar: { dataType = "UChar_t"; readerType = TTreeReaderDescriptor::ReaderType::kArray; break; }
237 case TVirtualStreamerInfo::kOffsetL + TVirtualStreamerInfo::kUShort: { dataType = "unsigned short"; readerType = TTreeReaderDescriptor::ReaderType::kArray; break; }
238 case TVirtualStreamerInfo::kOffsetL + TVirtualStreamerInfo::kUInt: { dataType = "unsigned int"; readerType = TTreeReaderDescriptor::ReaderType::kArray; break; }
239 case TVirtualStreamerInfo::kOffsetL + TVirtualStreamerInfo::kULong: { dataType = "ULong_t"; readerType = TTreeReaderDescriptor::ReaderType::kArray; break; }
240 case TVirtualStreamerInfo::kOffsetL + TVirtualStreamerInfo::kULong64: { dataType = "ULong64_t"; readerType = TTreeReaderDescriptor::ReaderType::kArray; break; }
241 case TVirtualStreamerInfo::kOffsetL + TVirtualStreamerInfo::kBits: { dataType = "unsigned int"; readerType = TTreeReaderDescriptor::ReaderType::kArray; break; }
242 // Array of built-in types [n]
243 case TVirtualStreamerInfo::kOffsetP + TVirtualStreamerInfo::kBool: { dataType = "Bool_t"; readerType = TTreeReaderDescriptor::ReaderType::kArray; break; }
244 case TVirtualStreamerInfo::kOffsetP + TVirtualStreamerInfo::kChar: { dataType = "Char_t"; readerType = TTreeReaderDescriptor::ReaderType::kArray; break; }
245 case TVirtualStreamerInfo::kOffsetP + TVirtualStreamerInfo::kShort: { dataType = "Short_t"; readerType = TTreeReaderDescriptor::ReaderType::kArray; break; }
246 case TVirtualStreamerInfo::kOffsetP + TVirtualStreamerInfo::kInt: { dataType = "Int_t"; readerType = TTreeReaderDescriptor::ReaderType::kArray; break; }
247 case TVirtualStreamerInfo::kOffsetP + TVirtualStreamerInfo::kLong: { dataType = "Long_t"; readerType = TTreeReaderDescriptor::ReaderType::kArray; break; }
248 case TVirtualStreamerInfo::kOffsetP + TVirtualStreamerInfo::kLong64: { dataType = "Long64_t"; readerType = TTreeReaderDescriptor::ReaderType::kArray; break; }
249 case TVirtualStreamerInfo::kOffsetP + TVirtualStreamerInfo::kFloat: { dataType = "Float_t"; readerType = TTreeReaderDescriptor::ReaderType::kArray; break; }
250 case TVirtualStreamerInfo::kOffsetP + TVirtualStreamerInfo::kFloat16: { dataType = "Float16_t"; readerType = TTreeReaderDescriptor::ReaderType::kArray; break; }
251 case TVirtualStreamerInfo::kOffsetP + TVirtualStreamerInfo::kDouble: { dataType = "Double_t"; readerType = TTreeReaderDescriptor::ReaderType::kArray; break; }
252 case TVirtualStreamerInfo::kOffsetP + TVirtualStreamerInfo::kDouble32:{ dataType = "Double32_t"; readerType = TTreeReaderDescriptor::ReaderType::kArray; break; }
253 case TVirtualStreamerInfo::kOffsetP + TVirtualStreamerInfo::kUChar: { dataType = "UChar_t"; readerType = TTreeReaderDescriptor::ReaderType::kArray; break; }
254 case TVirtualStreamerInfo::kOffsetP + TVirtualStreamerInfo::kUShort: { dataType = "unsigned short"; readerType = TTreeReaderDescriptor::ReaderType::kArray; break; }
255 case TVirtualStreamerInfo::kOffsetP + TVirtualStreamerInfo::kUInt: { dataType = "unsigned int"; readerType = TTreeReaderDescriptor::ReaderType::kArray; break; }
256 case TVirtualStreamerInfo::kOffsetP + TVirtualStreamerInfo::kULong: { dataType = "ULong_t"; readerType = TTreeReaderDescriptor::ReaderType::kArray; break; }
257 case TVirtualStreamerInfo::kOffsetP + TVirtualStreamerInfo::kULong64: { dataType = "ULong64_t"; readerType = TTreeReaderDescriptor::ReaderType::kArray; break; }
258 case TVirtualStreamerInfo::kOffsetP + TVirtualStreamerInfo::kBits: { dataType = "unsigned int"; readerType = TTreeReaderDescriptor::ReaderType::kArray; break; }
259 // array counter [n]
260 case TVirtualStreamerInfo::kCounter: { dataType = "Int_t"; readerType = TTreeReaderDescriptor::ReaderType::kArray; break; }
261 // other stuff (containers, classes, ...)
270 // set as pointers and fall through to the next switches
271 ispointer = true;
273 // This means an array of objects, but then fall through
274 readerType = TTreeReaderDescriptor::ReaderType::kArray;
282 TClass *cl = element->GetClassPointer();
283 R__ASSERT(cl);
284 dataType = cl->GetName();
285 // Check for containers
286 if (cl == TClonesArray::Class()) { // TClonesArray
287 isclones = kClones;
288 containerName = "TClonesArray";
289 if (outer_isclones != kOut) { // If the parent is already a collection
290 isclones = outer_isclones;
291 dataType = "TClonesArray";
292 } else {
293 readerType = TTreeReaderDescriptor::ReaderType::kArray;
294 dataType = GetContainedClassName(branch, element, ispointer);
295 }
296 } else if (cl->GetCollectionProxy()) { // STL collection
297 isclones = kSTL;
298 containerName = cl->GetName();
299 if (outer_isclones != kOut || containerName.EqualTo("vector<bool>")) {
300 // If the parent is already a collection we can only add this collection as a whole
301 // Also TTreeReaderArray does currently not support vectors of bool so
302 // that need to be added as a whole.
303 // Also getting the inner type of vector would return "unsigned" so the full
304 // name has to be compared
305 isclones = outer_isclones;
306 dataType = cl->GetName();
307 } else {
308 readerType = TTreeReaderDescriptor::ReaderType::kArray;
309 TClass *valueClass = cl->GetCollectionProxy()->GetValueClass();
310 if (valueClass) { // Get class inside container
311 dataType = valueClass->GetName();
312 }
313 else { // Get built-in type inside container
314 TDataType *valueClassBuiltIn = TDataType::GetDataType(cl->GetCollectionProxy()->GetType());
315 if (valueClassBuiltIn) dataType = valueClassBuiltIn->GetName();
316 else Error("AnalyzeBranches", "Could not get type from collection %s in branch %s", cl->GetName(), branch->GetName());
317 }
318 }
319 }
320
321 // Analyze the actual element
322 // Possible cases:
323 // - Base class
324 // - Element and branch matches
325 // - Non-split: do nothing
326 // - Split: recurse with sub-sub-branches
327 // - Element and branch does not match: recurse with same branches
328 // - Not base class
329 // - Element and branch matches
330 // - Non-split: do nothing
331 // - Split: recurse with sub-sub-branches
332 // - Element and branch does not match: recurse with same branches
333 TBranch *parent = branch->GetMother()->GetSubBranch(branch);
334 TVirtualStreamerInfo *objInfo = 0;
335 if (branch->GetListOfBranches()->GetEntries()) {
336 objInfo = ((TBranchElement*)branch->GetListOfBranches()->At(0))->GetInfo();
337 } else {
338 objInfo = branch->GetInfo();
339 }
340 if (element->IsBase()) { // Base class
341 isBase = true;
342 if (cl == TObject::Class() && info->GetClass()->CanIgnoreTObjectStreamer())
343 {
344 continue; // Ignore TObject
345 }
346
347 TBranchDescriptor *bdesc = 0;
348
349 if (branchEndName == element->GetName()) { // The element and the branch matches
350 if (branch->GetListOfBranches()->GetEntries() == 0) { // The branch contains a non-split base class
351 // FIXME: nothing to do in such cases, because readers cannot access
352 // non-split members and a reader for the whole branch will be added
353 } else { // The branch contains a split base class
354 Int_t pos = branchname.Last('.');
355 if (pos != -1) {
356 branchname.Remove(pos);
357 }
358 TString local_prefix = desc ? desc->fSubBranchPrefix : TString(parent->GetName());
359 bdesc = new TBranchDescriptor(cl->GetName(), objInfo, branchname.Data(), local_prefix.Data(),
360 isclones, containerName, desc);
361 // Recurse: analyze sub-branches of the sub-branch
362 lookedAt += AnalyzeBranches(bdesc, branch, objInfo);
363 isLeaf = false;
364
365 }
366 } else { // The element and the branch does not match, we need to loop over the next branches
367 Int_t pos = branchname.Last('.');
368 if (pos != -1) {
369 branchname.Remove(pos);
370 }
371 TString local_prefix = desc ? desc->fSubBranchPrefix : TString(parent->GetName());
372 objInfo = GetBaseClass(element);
373 if (objInfo == 0) {
374 continue; // There is no data in this base class
375 }
376 cl = objInfo->GetClass();
377 bdesc = new TBranchDescriptor(cl->GetName(), objInfo, branchname.Data(), local_prefix.Data(),
378 isclones, containerName, desc);
379 usedBranch = kFALSE;
380 // Recurse: analyze the sub-elements with the same branches
381 lookedAt += AnalyzeBranches(bdesc, branches, objInfo);
382 }
383 delete bdesc;
384 } else { // Not base class
385 TBranchDescriptor *bdesc = 0;
386 if (branchEndName == element->GetName()) { // The element and the branch matches
387 if (branch->GetListOfBranches()->GetEntries() == 0) { // The branch contains a non-split class
388 // FIXME: nothing to do in such cases, because readers cannot access
389 // non-split members and a reader for the whole branch will be added
390 } else { // The branch contains a split class
391 if (isclones != kOut) {
392 // We have to guess the version number!
393 cl = TClass::GetClass(dataType);
394 objInfo = GetStreamerInfo(branch, branch->GetListOfBranches(), cl);
395 }
396 bdesc = new TBranchDescriptor(cl->GetName(), objInfo, branch->GetName(), branch->GetName(),
397 isclones, containerName, desc);
398 // Recurse: analyze sub-branches of the sub-branch
399 lookedAt += AnalyzeBranches(bdesc, branch, objInfo);
400 isLeaf = false;
401 }
402 } else { // The element and the branch does not match, we need to loop over the next branches
403 TString local_prefix = desc ? desc->fSubBranchPrefix : TString(parent->GetName());
404 if (local_prefix.Length()) local_prefix += ".";
405 local_prefix += element->GetName();
406 objInfo = branch->GetInfo();
407 Int_t pos = branchname.Last('.');
408 if (pos != -1) {
409 branchname.Remove(pos);
410 }
411 if (isclones != kOut) {
412 // We have to guess the version number!
413 cl = TClass::GetClass(dataType);
414 objInfo = GetStreamerInfo(branch, branches, cl);
415 }
416 bdesc = new TBranchDescriptor(cl->GetName(), objInfo, branchname.Data(), local_prefix.Data(),
417 isclones, containerName, desc);
418 usedBranch = kFALSE;
419 skipped = kTRUE;
420 // Recurse: analyze the sub-elements with the same branches
421 lookedAt += AnalyzeBranches(bdesc, branches, objInfo);
422 }
423 delete bdesc;
424 }
425
426 break;
427 }
428 default:
429 Error("AnalyzeBranch", "Unsupported type for %s (%d).", branch->GetName(), element->GetType());
430 }
431
432 if (!isBase && !skipped) { // Add reader for the whole branch
433 if (outer_isclones != kOut && readerType == TTreeReaderDescriptor::ReaderType::kArray) {
434 Error("AnalyzeBranch", "Arrays inside collections are not supported yet (branch: %s).", branch->GetName());
435 } else {
436 if (outer_isclones != kOut || isclones != kOut) {
437 readerType = TTreeReaderDescriptor::ReaderType::kArray;
438 }
439 AddReader(readerType, dataType, branch->GetName(), branch->GetName(), desc, isLeaf);
440 }
441 }
442
443 // If the branch was used, jump to the next
444 if (usedBranch) {
445 branches.Next();
446 ++lookedAt;
447 }
448 }
449
450 return lookedAt;
451 }
452
453 ////////////////////////////////////////////////////////////////////////////////
454 /// Analyze branch and add the variables found. The number of analyzed
455 /// sub-branches is returned.
456
458 {
459 UInt_t extraLookedAt = 0;
460 TString prefix;
461
462 TString branchName = branch->GetName();
463
464 TObjArray *leaves = branch->GetListOfLeaves();
465 Int_t nleaves = leaves ? leaves->GetEntriesFast() : 0;
466
467 // Loop through leaves and analyze them
468 for(int l=0;l<nleaves;l++) {
469 TLeaf *leaf = (TLeaf*)leaves->UncheckedAt(l);
470 extraLookedAt += AnalyzeOldLeaf(leaf, nleaves);
471 }
472
473 return extraLookedAt;
474 }
475
476 ////////////////////////////////////////////////////////////////////////////////
477 /// Analyze the leaf and add the variables found.
478
480 {
481 if (leaf->IsA()==TLeafObject::Class()) {
482 Error("AnalyzeOldLeaf","TLeafObject not supported yet");
483 return 0;
484 }
485
486 TString leafTypeName = leaf->GetTypeName();
487 Int_t pos = leafTypeName.Last('_');
488 //if (pos != -1) leafTypeName.Remove(pos); // FIXME: this is not required since it makes Float_t -> Float
489
490 // Analyze dimensions
491 UInt_t dim = 0;
492 std::vector<Int_t> maxDim;
493
494 TString dimensions;
495 TString temp = leaf->GetName();
496 pos = temp.Index("[");
497 if (pos != -1) {
498 if (pos) temp.Remove(0, pos);
499 dimensions.Append(temp);
500 }
501 temp = leaf->GetTitle();
502 pos = temp.Index("[");
503 if (pos != -1) {
504 if (pos) temp.Remove(0, pos);
505 dimensions.Append(temp);
506 }
507
508 Int_t dimlen = dimensions.Length();
509
510 if (dimlen) {
511 const char *current = dimensions.Data();
512
513 Int_t index;
514 Int_t scanindex ;
515 while (current) {
516 current++;
517 if (current[0] == ']') {
518 maxDim.push_back(-1); // maxDim[dim] = -1; // Loop over all elements;
519 } else {
520 scanindex = sscanf(current,"%d",&index);
521 if (scanindex) {
522 maxDim.push_back(index); // maxDim[dim] = index;
523 } else {
524 maxDim.push_back(-2); // maxDim[dim] = -2; // Index is calculated via a variable.
525 }
526 }
527 dim ++;
528 current = (char*)strstr( current, "[" );
529 }
530 }
531
532 if (dim == 0 && leaf->IsA() == TLeafC::Class()) {
533 dim = 1; // For C style strings
534 }
535
536 TTreeReaderDescriptor::ReaderType type = TTreeReaderDescriptor::ReaderType::kValue;
537 TString dataType;
538 switch (dim) {
539 case 0: {
540 type = TTreeReaderDescriptor::ReaderType::kValue;
541 dataType = leafTypeName;
542 break;
543 }
544 case 1: {
545 type = TTreeReaderDescriptor::ReaderType::kArray;
546 dataType = leafTypeName;
547 break;
548 }
549 default: {
550 // TODO: transform this
551 /*type = "TArrayProxy<";
552 for(Int_t ind = dim - 2; ind > 0; --ind) {
553 type += "TMultiArrayType<";
554 }
555 type += "TArrayType<";
556 type += leaf->GetTypeName();
557 type += ",";
558 type += maxDim[dim-1];
559 type += "> ";
560 for(Int_t ind = dim - 2; ind > 0; --ind) {
561 type += ",";
562 type += maxDim[ind];
563 type += "> ";
564 }
565 type += ">";*/
566 break;
567 }
568 }
569
570 // If there are multiple leaves (leaflist) the name of the branch is
571 // <branch_name>.<leaf_name>
572 // (Otherwise the brach name does not change)
573 TString branchName = leaf->GetBranch()->GetName();
574 if (nleaves > 1) {
575 branchName.Form("%s.%s", leaf->GetBranch()->GetName(), leaf->GetName());
576 }
577
578 AddReader(type, dataType, leaf->GetName(), branchName, 0, kTRUE);
579
580 return 0;
581 }
582
583 ////////////////////////////////////////////////////////////////////////////////
584 /// Check whether a branch should have a corresponding reader added, depending
585 /// on the options provided by the user.
586
588 {
589 if (isLeaf) { // Branch is a leaf
590 // Include if all leaves should be included or it is contained in any of the lists.
591 if (fIncludeAllLeaves) return kTRUE;
592 if (std::find(fIncludeLeaves.begin(), fIncludeLeaves.end(), branchName) != fIncludeLeaves.end()) return kTRUE;
593 if (std::find(fIncludeStruct.begin(), fIncludeStruct.end(), branchName) != fIncludeStruct.end()) return kTRUE;
594 if (!parent) { // Branch is topmost (top-level leaf)
595 if (fIncludeAllTopmost) return kTRUE;
596 } else { // Branch is not topmost
597 while (parent) { // Check if any parent is in the list of "include as leaves"
598 if (std::find(fIncludeLeaves.begin(), fIncludeLeaves.end(), parent->fBranchName) != fIncludeLeaves.end()) {
599 return kTRUE;
600 }
601 parent = parent->fParent;
602 }
603 }
604 } else { // Branch is not a leaf (has sub-branches)
605 if (std::find(fIncludeStruct.begin(), fIncludeStruct.end(), branchName) != fIncludeStruct.end()) return kTRUE;
606 if (!parent) { // Branch is topmost
607 if (fIncludeAllTopmost) return kTRUE;
608 }
609 }
610 return false;
611 }
612
613 ////////////////////////////////////////////////////////////////////////////////
614 /// Parse the user options.
615
617 if (fOptionStr.EqualTo("")) { // Empty -> include all leaves
619 } else if (fOptionStr.EqualTo("@")) { // "@" -> include all topmost
621 } else { // Otherwise split at ";" to get names
622 TObjArray *tokens = fOptionStr.Tokenize(TString(";"));
623 for (Int_t i = 0; i < tokens->GetEntries(); ++i) {
624 TString token = ((TObjString*)tokens->At(i))->GetString();
625 if ( token.Length() == 0 || (token.Length() == 1 && token[0] == '@') ) {
626 Warning("ParseOptions", "Ignored empty branch name in option string.");
627 } else if (token[0] == '@') { // "@X" means include X as a whole
628 token = TString(token.Data()+1);
629 fIncludeStruct.push_back(token);
630 } else { // "X" means include leaves of X
631 fIncludeLeaves.push_back(token);
632 }
633 if (!fTree->GetBranch(token)) { // Display a warning for non-existing branch names
634 Warning("ParseOptions", "Tree %s does not contain a branch named %s.", fTree->GetName(), token.Data());
635 }
636 }
637 delete tokens;
638 }
639 }
640
641 ////////////////////////////////////////////////////////////////////////////////
642 /// Analyze tree and extract readers.
643
645 {
646 TIter next(tree->GetListOfBranches());
647 TBranch *branch;
648
649 // Loop through branches
650 while ( (branch = (TBranch*)next()) ) {
651 TVirtualStreamerInfo *info = 0;
652 // Get the name and the class of the branch
653 const char *branchName = branch->GetName();
654 const char *branchClassName = branch->GetClassName();
655 TClass *cl = TClass::GetClass(branchClassName);
656
657 // Add headers for user classes
658 if (branchClassName && strlen(branchClassName)) {
659 AddHeader(cl);
660 }
661
662 TString type = "unknown"; // Type of branch
663 ELocation isclones = kOut; // Type of container
664 TString containerName = ""; // Name of container
665 TBranchDescriptor *desc = 0;
666 // Check whether the branch is a container
667 if (cl) {
668 // Check if it is a TClonesArray
669 if (cl == TClonesArray::Class()) {
670 isclones = kClones;
671 containerName = "TClonesArray";
672 if (branch->IsA()==TBranchElement::Class()) {
673 // Get the class inside the TClonesArray
674 const char *cname = ((TBranchElement*)branch)->GetClonesName();
675 TClass *ncl = TClass::GetClass(cname);
676 if (ncl) {
677 cl = ncl;
678 info = GetStreamerInfo(branch, branch->GetListOfBranches(), cl);
679 } else {
680 Error("AnalyzeTree",
681 "Introspection of TClonesArray in older file not implemented yet.");
682 }
683 } else {
684 TClonesArray **ptr = (TClonesArray**)branch->GetAddress();
685 TClonesArray *clones = 0;
686 if (ptr==0) {
687 clones = new TClonesArray;
688 branch->SetAddress(&clones);
689 ptr = &clones;
690 }
691 branch->GetEntry(0);
692 TClass *ncl = *ptr ? (*ptr)->GetClass() : 0;
693 if (ncl) {
694 cl = ncl;
695 } else {
696 Error("AnalyzeTree",
697 "Introspection of TClonesArray for %s failed.",branch->GetName());
698 }
699 }
700 // Check if it is an STL container
701 } else if (cl->GetCollectionProxy()) {
702 isclones = kSTL;
703 containerName = cl->GetName();
704 // Get the type inside container
705 if (cl->GetCollectionProxy()->GetValueClass()) { // Class inside container
706 cl = cl->GetCollectionProxy()->GetValueClass();
707 } else { // RAW type (or missing class) inside container
708 // TODO: CheckForMissingClass?
709 // TTreeReaderArray does currently not support vectors of bool so that need to
710 // be added as a TTreeReaderValue<vector<bool>>. Also getting the inner type of
711 // vector would return "unsigned" so the full name has to be compared.
712 if (containerName.EqualTo("vector<bool>")) {
713 AddReader(TTreeReaderDescriptor::ReaderType::kValue,
714 containerName,
715 branch->GetName(), branch->GetName(), 0, kTRUE);
716 } else { // Otherwise we can generate a TTreeReaderArray with the inner type
717 AddReader(TTreeReaderDescriptor::ReaderType::kArray,
719 branch->GetName(), branch->GetName(), 0, kTRUE);
720 }
721 continue; // Nothing else to with this branch in these cases
722 }
723 }
724
725 // Check class inside container and create a descriptor or add a reader
726 if (cl) {
727 if (cl->TestBit(TClass::kIsEmulation) || branchName[strlen(branchName)-1] == '.' || branch->GetSplitLevel()) {
728 TBranchElement *be = dynamic_cast<TBranchElement*>(branch);
729 TVirtualStreamerInfo *beinfo = (be && isclones == kOut)
730 ? be->GetInfo() : cl->GetStreamerInfo(); // the 2nd hand need to be fixed
731 // Create descriptor
732 desc = new TBranchDescriptor(cl->GetName(), beinfo, branchName, branchName, isclones, containerName);
733 info = beinfo;
734 } else {
735 // Add a reader for non-split classes
736 AddReader(isclones == kOut ?
737 TTreeReaderDescriptor::ReaderType::kValue
738 : TTreeReaderDescriptor::ReaderType::kArray,
739 cl->GetName(), branchName, branchName, 0, kTRUE);
740 // TODO: can't we just put a continue here?
741 }
742 }
743 }
744
745 // Analyze sub-branches (if exist) and add readers
746 if (branch->GetListOfBranches()->GetEntries() == 0) { // Branch is non-splitted
747 if (cl) { // Non-split object
748 if (desc) { // If there is a descriptor add reader (otherwise
749 // it was already added).
750 AddReader(isclones == kOut ?
751 TTreeReaderDescriptor::ReaderType::kValue
752 : TTreeReaderDescriptor::ReaderType::kArray,
753 desc->GetName(), desc->fBranchName, desc->fBranchName, 0, kTRUE);
754 }
755 } else { // Top-level RAW type
756 AnalyzeOldBranch(branch); // Analyze branch and extract readers
757 }
758 } else { // Branch is splitted
759 TIter subnext( branch->GetListOfBranches() );
760 if (desc) {
761 // Analyze sub-branches and extract readers
762 TBranchElement *branchElem = dynamic_cast<TBranchElement*>(branch);
763 if (branchElem) {
764 AnalyzeBranches(desc, branchElem, info);
765 } else {
766 Error("AnalyzeTree", "Cannot analyze branch %s because it is not a TBranchElement.", branchName);
767 }
768 // Also add a reader for the whole branch
769 AddReader(isclones == kOut ?
770 TTreeReaderDescriptor::ReaderType::kValue
771 : TTreeReaderDescriptor::ReaderType::kArray,
772 desc->GetName(), desc->fBranchName, desc->fBranchName, 0, kFALSE);
773 }
774 }
775 delete desc;
776 }
777 }
778
779 ////////////////////////////////////////////////////////////////////////////////
780 /// Generate code for selector class.
781
783 {
784 // If no name is given, set to default (name of the tree)
786
787 TString treefile;
788 if (fTree->GetDirectory() && fTree->GetDirectory()->GetFile()) {
789 treefile = fTree->GetDirectory()->GetFile()->GetName();
790 } else {
791 treefile = "Memory Directory";
792 }
793 // In the case of a chain, the GetDirectory information usually does
794 // pertain to the Chain itself but to the currently loaded tree.
795 // So we can not rely on it.
797 Bool_t isHbook = fTree->InheritsFrom("THbookTree");
798 if (isHbook)
799 treefile = fTree->GetTitle();
800
801 //======================Generate classname.h=====================
802 TString thead;
803 thead.Form("%s.h", fClassname.Data());
804 std::ofstream ofs (thead, std::ofstream::out);
805 if (!ofs) {
806 Error("WriteSelector","cannot open output file %s", thead.Data());
807 return;
808 }
809 // Print header
810 TDatime td;
811 ofs <<
812R"CODE(//////////////////////////////////////////////////////////
813// This class has been automatically generated on
814// )CODE" << td.AsString() << R"CODE( by ROOT version )CODE" << gROOT->GetVersion() << std::endl;
815 if (!ischain) {
816 ofs << "// from TTree " << fTree->GetName() << "/" << fTree->GetTitle() << std::endl
817 << "// found on file: " << treefile << std::endl;
818 } else {
819 ofs << "// from TChain " << fTree->GetName() << "/" << fTree->GetTitle() << std::endl;
820 }
821 ofs <<
822R"CODE(//////////////////////////////////////////////////////////
823
824#ifndef )CODE" << fClassname << R"CODE(_h
825#define )CODE" << fClassname << R"CODE(_h
826
827#include <TROOT.h>
828#include <TChain.h>
829#include <TFile.h>
830)CODE";
831 if (isHbook) ofs << "#include <THbookFile.h>" << std::endl;
832 ofs <<
833R"CODE(#include <TSelector.h>
834#include <TTreeReader.h>
835#include <TTreeReaderValue.h>
836#include <TTreeReaderArray.h>
837
838// Headers needed by this particular selector
839)CODE";
840
841 TIter next(&fListOfHeaders);
842 TObject *header;
843 while ( (header = next()) ) {
844 ofs << header->GetTitle() << std::endl;
845 }
846 ofs << std::endl << std::endl;
847
848 // Generate class declaration with TTreeReaderValues and Arrays
849 ofs <<
850R"CODE(class )CODE" << fClassname << R"CODE( : public TSelector {
851public :
852 TTreeReader fReader; //!the tree reader
853 TTree *fChain = 0; //!pointer to the analyzed TTree or TChain
854
855 // Readers to access the data (delete the ones you do not need).
856)CODE";
857 next = &fListOfReaders;
858 TTreeReaderDescriptor *descriptor;
859 while ( ( descriptor = (TTreeReaderDescriptor*)next() ) ) {
860 ofs << " TTreeReader" << (descriptor->fType == TTreeReaderDescriptor::ReaderType::kValue ? "Value" : "Array")
861 << "<" << descriptor->fDataType
862 << "> " << descriptor->fName
863 << " = {fReader, \"" << descriptor->fBranchName << "\"};" << std::endl;
864 }
865 // Generate class member functions prototypes
866 ofs <<
867R"CODE(
868
869 )CODE" << fClassname << R"CODE((TTree * /*tree*/ =0) { }
870 virtual ~)CODE" << fClassname << R"CODE(() { }
871 virtual Int_t Version() const { return 2; }
872 virtual void Begin(TTree *tree);
873 virtual void SlaveBegin(TTree *tree);
874 virtual void Init(TTree *tree);
875 virtual Bool_t Notify();
876 virtual Bool_t Process(Long64_t entry);
877 virtual Int_t GetEntry(Long64_t entry, Int_t getall = 0) { return fChain ? fChain->GetTree()->GetEntry(entry, getall) : 0; }
878 virtual void SetOption(const char *option) { fOption = option; }
879 virtual void SetObject(TObject *obj) { fObject = obj; }
880 virtual void SetInputList(TList *input) { fInput = input; }
881 virtual TList *GetOutputList() const { return fOutput; }
882 virtual void SlaveTerminate();
883 virtual void Terminate();
884
885 ClassDef()CODE" << fClassname << R"CODE(,0);
886
887};
888
889#endif
890
891#ifdef )CODE" << fClassname << R"CODE(_cxx
892void )CODE" << fClassname << R"CODE(::Init(TTree *tree)
893{
894 // The Init() function is called when the selector needs to initialize
895 // a new tree or chain. Typically here the reader is initialized.
896 // It is normally not necessary to make changes to the generated
897 // code, but the routine can be extended by the user if needed.
898 // Init() will be called many times when running on PROOF
899 // (once per file to be processed).
900
901 fReader.SetTree(tree);
902}
903
904Bool_t )CODE" << fClassname << R"CODE(::Notify()
905{
906 // The Notify() function is called when a new file is opened. This
907 // can be either for a new TTree in a TChain or when when a new TTree
908 // is started when using PROOF. It is normally not necessary to make changes
909 // to the generated code, but the routine can be extended by the
910 // user if needed. The return value is currently not used.
911
912 return kTRUE;
913}
914
915
916#endif // #ifdef )CODE" << fClassname << R"CODE(_cxx
917)CODE";
918 ofs.close();
919
920 //======================Generate classname.C=====================
921 TString tcimp;
922 tcimp.Form("%s.C", fClassname.Data());
923 std::ofstream ofsc (tcimp, std::ofstream::out);
924 if (!ofsc) {
925 Error("WriteSelector","cannot open output file %s", tcimp.Data());
926 return;
927 }
928
929 ofsc <<
930R"CODE(#define )CODE" << fClassname << R"CODE(_cxx
931// The class definition in )CODE" << fClassname << R"CODE(.h has been generated automatically
932// by the ROOT utility TTree::MakeSelector(). This class is derived
933// from the ROOT class TSelector. For more information on the TSelector
934// framework see $ROOTSYS/README/README.SELECTOR or the ROOT User Manual.
935
936
937// The following methods are defined in this file:
938// Begin(): called every time a loop on the tree starts,
939// a convenient place to create your histograms.
940// SlaveBegin(): called after Begin(), when on PROOF called only on the
941// slave servers.
942// Process(): called for each event, in this function you decide what
943// to read and fill your histograms.
944// SlaveTerminate: called at the end of the loop on the tree, when on PROOF
945// called only on the slave servers.
946// Terminate(): called at the end of the loop on the tree,
947// a convenient place to draw/fit your histograms.
948//
949// To use this file, try the following session on your Tree T:
950//
951// root> T->Process(")CODE" << fClassname << R"CODE(.C")
952// root> T->Process(")CODE" << fClassname << R"CODE(.C","some options")
953// root> T->Process(")CODE" << fClassname << R"CODE(.C+")
954//
955
956
957#include ")CODE" << thead << R"CODE("
958#include <TH2.h>
959#include <TStyle.h>
960
961void )CODE" << fClassname << R"CODE(::Begin(TTree * /*tree*/)
962{
963 // The Begin() function is called at the start of the query.
964 // When running with PROOF Begin() is only called on the client.
965 // The tree argument is deprecated (on PROOF 0 is passed).
966
967 TString option = GetOption();
968}
969
970void )CODE" << fClassname << R"CODE(::SlaveBegin(TTree * /*tree*/)
971{
972 // The SlaveBegin() function is called after the Begin() function.
973 // When running with PROOF SlaveBegin() is called on each slave server.
974 // The tree argument is deprecated (on PROOF 0 is passed).
975
976 TString option = GetOption();
977
978}
979
980Bool_t )CODE" << fClassname << R"CODE(::Process(Long64_t entry)
981{
982 // The Process() function is called for each entry in the tree (or possibly
983 // keyed object in the case of PROOF) to be processed. The entry argument
984 // specifies which entry in the currently loaded tree is to be processed.
985 // When processing keyed objects with PROOF, the object is already loaded
986 // and is available via the fObject pointer.
987 //
988 // This function should contain the \"body\" of the analysis. It can contain
989 // simple or elaborate selection criteria, run algorithms on the data
990 // of the event and typically fill histograms.
991 //
992 // The processing can be stopped by calling Abort().
993 //
994 // Use fStatus to set the return value of TTree::Process().
995 //
996 // The return value is currently not used.
997
998 fReader.SetLocalEntry(entry);
999
1000 return kTRUE;
1001}
1002
1003void )CODE" << fClassname << R"CODE(::SlaveTerminate()
1004{
1005 // The SlaveTerminate() function is called after all entries or objects
1006 // have been processed. When running with PROOF SlaveTerminate() is called
1007 // on each slave server.
1008
1009}
1010
1011void )CODE" << fClassname << R"CODE(::Terminate()
1012{
1013 // The Terminate() function is the last function to be called during
1014 // a query. It always runs on the client, it can be used to present
1015 // the results graphically or save the results to file.
1016
1017})CODE";
1018 ofsc.close();
1019 }
1020
1021} // namespace Internal
1022} // namespace ROOT
void Class()
Definition: Class.C:29
int Int_t
Definition: RtypesCore.h:41
unsigned int UInt_t
Definition: RtypesCore.h:42
const Bool_t kFALSE
Definition: RtypesCore.h:88
bool Bool_t
Definition: RtypesCore.h:59
const Bool_t kTRUE
Definition: RtypesCore.h:87
const char Option_t
Definition: RtypesCore.h:62
#define R__ASSERT(e)
Definition: TError.h:96
void Error(const char *location, const char *msgfmt,...)
void Warning(const char *location, const char *msgfmt,...)
int type
Definition: TGX11.cxx:120
#define gROOT
Definition: TROOT.h:410
void AddHeader(TClass *cl)
Add a header inclusion request.
TVirtualStreamerInfo * GetStreamerInfo(TBranch *branch, TIter current, TClass *cl)
Return the correct TStreamerInfo of class 'cl' in the list of branches (current) [Assuming these bran...
TVirtualStreamerInfo * GetBaseClass(TStreamerElement *element)
Check if element is a base class and if yes, return the base class.
TString GetContainedClassName(TBranchElement *branch, TStreamerElement *element, Bool_t ispointer)
Get name of class inside a container.
void AnalyzeTree(TTree *tree)
Analyze tree and extract readers.
UInt_t AnalyzeBranches(TBranchDescriptor *desc, TBranchElement *branch, TVirtualStreamerInfo *info)
Analyse sub-branches of 'branch' recursively and extract readers.
void ParseOptions()
Parse the user options.
TTreeReaderGenerator(TTree *tree, const char *classname, Option_t *option)
Constructor. Analyzes the tree and writes selector.
void AddReader(TTreeReaderDescriptor::ReaderType type, TString dataType, TString name, TString branchName, TBranchDescriptor *parent=0, Bool_t isLeaf=kTRUE)
Add a reader to the generated code.
Bool_t BranchNeedsReader(TString branchName, TBranchDescriptor *parent, Bool_t isLeaf)
Check whether a branch should have a corresponding reader added, depending on the options provided by...
UInt_t AnalyzeOldLeaf(TLeaf *leaf, Int_t nleaves)
Analyze the leaf and add the variables found.
UInt_t AnalyzeOldBranch(TBranch *branch)
Analyze branch and add the variables found.
void WriteSelector()
Generate code for selector class.
A Branch for the case of an object.
TBranchElement * GetBranchCount() const
TStreamerInfo * GetInfo() const
Get streamer info for the branch class.
Int_t GetType() const
A TTree is a list of TBranches.
Definition: TBranch.h:64
virtual const char * GetClassName() const
Return the name of the user class whose content is stored in this branch, if any.
Definition: TBranch.cxx:1282
virtual char * GetAddress() const
Definition: TBranch.h:171
TObjArray * GetListOfBranches()
Definition: TBranch.h:203
Int_t GetSplitLevel() const
Definition: TBranch.h:207
virtual Int_t GetEntry(Long64_t entry=0, Int_t getall=0)
Read all leaves of entry and return total number of bytes read.
Definition: TBranch.cxx:1317
TBranch * GetSubBranch(const TBranch *br) const
Find the parent branch of child.
Definition: TBranch.cxx:1746
virtual void SetAddress(void *add)
Set address of this branch.
Definition: TBranch.cxx:2265
TObjArray * GetListOfLeaves()
Definition: TBranch.h:204
TBranch * GetMother() const
Get our top-level parent branch in the tree.
Definition: TBranch.cxx:1725
The ROOT global object gROOT contains a list of all defined classes.
Definition: TClass.h:75
TVirtualStreamerInfo * GetStreamerInfo(Int_t version=0) const
returns a pointer to the TVirtualStreamerInfo object for version If the object does not exist,...
Definition: TClass.cxx:4452
Bool_t CanIgnoreTObjectStreamer()
Definition: TClass.h:365
TVirtualCollectionProxy * GetCollectionProxy() const
Return the proxy describing the collection (if any).
Definition: TClass.cxx:2814
@ kIsEmulation
Definition: TClass.h:95
static TClass * GetClass(const char *name, Bool_t load=kTRUE, Bool_t silent=kFALSE)
Static method returning pointer to TClass of the specified class name.
Definition: TClass.cxx:2885
An array of clone (identical) objects.
Definition: TClonesArray.h:32
TClass * GetClass() const
Definition: TClonesArray.h:56
Basic data type descriptor (datatype information is obtained from CINT).
Definition: TDataType.h:44
static TDataType * GetDataType(EDataType type)
Given a EDataType type, get the TDataType* that represents it.
Definition: TDataType.cxx:440
This class stores the date and time with a precision of one second in an unsigned 32 bit word (950130...
Definition: TDatime.h:37
const char * AsString() const
Return the date & time as a string (ctime() format).
Definition: TDatime.cxx:101
virtual TFile * GetFile() const
Definition: TDirectory.h:147
A TLeaf describes individual elements of a TBranch See TBranch structure in TTree.
Definition: TLeaf.h:32
virtual const char * GetTypeName() const
Definition: TLeaf.h:93
TBranch * GetBranch() const
Definition: TLeaf.h:75
virtual void Add(TObject *obj)
Definition: TList.h:87
virtual const char * GetTitle() const
Returns title of object.
Definition: TNamed.h:48
virtual const char * GetName() const
Returns name of object.
Definition: TNamed.h:47
An array of TObjects.
Definition: TObjArray.h:37
Int_t GetEntriesFast() const
Definition: TObjArray.h:64
Int_t GetEntries() const
Return the number of objects in array (i.e.
Definition: TObjArray.cxx:522
TObject * UncheckedAt(Int_t i) const
Definition: TObjArray.h:89
TObject * At(Int_t idx) const
Definition: TObjArray.h:165
Collectable string class.
Definition: TObjString.h:28
Mother of all ROOT objects.
Definition: TObject.h:37
R__ALWAYS_INLINE Bool_t TestBit(UInt_t f) const
Definition: TObject.h:172
virtual Bool_t InheritsFrom(const char *classname) const
Returns kTRUE if object inherits from class "classname".
Definition: TObject.cxx:443
virtual const char * GetTitle() const
Returns title of object.
Definition: TObject.cxx:401
Basic string class.
Definition: TString.h:131
Ssiz_t Length() const
Definition: TString.h:405
const char * Data() const
Definition: TString.h:364
Bool_t EqualTo(const char *cs, ECaseCompare cmp=kExact) const
Definition: TString.h:628
Ssiz_t Last(char c) const
Find last occurrence of a character c.
Definition: TString.cxx:876
TObjArray * Tokenize(const TString &delim) const
This function is used to isolate sequential tokens in a TString.
Definition: TString.cxx:2172
Bool_t BeginsWith(const char *s, ECaseCompare cmp=kExact) const
Definition: TString.h:610
TString & Remove(Ssiz_t pos)
Definition: TString.h:668
TString & Append(const char *cs)
Definition: TString.h:559
void Form(const char *fmt,...)
Formats a string using a printf style format descriptor.
Definition: TString.cxx:2264
Ssiz_t Index(const char *pat, Ssiz_t i=0, ECaseCompare cmp=kExact) const
Definition: TString.h:634
A TTree object has a header with a name and a title.
Definition: TTree.h:71
virtual TBranch * GetBranch(const char *name)
Return pointer to the branch with the given name in this tree or its friends.
Definition: TTree.cxx:5051
TDirectory * GetDirectory() const
Definition: TTree.h:401
virtual EDataType GetType() const =0
virtual TClass * GetValueClass() const =0
Abstract Interface class describing Streamer information for one class.
virtual TObjArray * GetElements() const =0
virtual TClass * GetClass() const =0
Namespace for new ROOT classes and functions.
Definition: StringConv.hxx:21
Definition: tree.py:1
auto * l
Definition: textangle.C:4