Logo ROOT  
Reference Guide
 
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Modules Pages
Loading...
Searching...
No Matches
TTree.cxx
Go to the documentation of this file.
1// @(#)root/tree:$Id$
2// Author: Rene Brun 12/01/96
3
4/*************************************************************************
5 * Copyright (C) 1995-2024, Rene Brun and Fons Rademakers. *
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/**
12 \defgroup tree Tree Library
13
14 RNTuple is the modern way of storing columnar datasets: please consider to use it
15 before starting new projects based on TTree and related classes.
16
17 In order to store columnar datasets, ROOT historically provides the TTree, TChain,
18 TNtuple and TNtupleD classes.
19 The TTree class represents a columnar dataset. Any C++ type can be stored in the
20 columns. The TTree has allowed to store about **1 EB** of data coming from the LHC alone:
21 it is demonstrated to scale and it's battle tested. It has been optimized during the years
22 to reduce dataset sizes on disk and to deliver excellent runtime performance.
23 It allows to access only part of the columns of the datasets, too.
24 The TNtuple and TNtupleD classes are specialisations of the TTree class which can
25 only hold single precision and double precision floating-point numbers respectively;
26 The TChain is a collection of TTrees, which can be located also in different files.
27
28*/
29
30/** \class TTree
31\ingroup tree
32
33A TTree represents a columnar dataset. Any C++ type can be stored in its columns. The modern
34version of TTree is RNTuple: please consider using it before opting for TTree.
35
36A TTree, often called in jargon *tree*, consists of a list of independent columns or *branches*,
37represented by the TBranch class.
38Behind each branch, buffers are allocated automatically by ROOT.
39Such buffers are automatically written to disk or kept in memory until the size stored in the
40attribute fMaxVirtualSize is reached.
41Variables of one branch are written to the same buffer. A branch buffer is
42automatically compressed if the file compression attribute is set (default).
43Branches may be written to different files (see TBranch::SetFile).
44
45The ROOT user can decide to make one single branch and serialize one object into
46one single I/O buffer or to make several branches.
47Making several branches is particularly interesting in the data analysis phase,
48when it is desirable to have a high reading rate and not all columns are equally interesting
49
50\anchor creatingattreetoc
51## Create a TTree to store columnar data
52- [Construct a TTree](\ref creatingattree)
53- [Add a column of Fundamental Types and Arrays thereof](\ref addcolumnoffundamentaltypes)
54- [Add a column of a STL Collection instances](\ref addingacolumnofstl)
55- [Add a column holding an object](\ref addingacolumnofobjs)
56- [Add a column holding a TObjectArray](\ref addingacolumnofobjs)
57- [Fill the tree](\ref fillthetree)
58- [Add a column to an already existing Tree](\ref addcoltoexistingtree)
59- [An Example](\ref fullexample)
60
61\anchor creatingattree
62## Construct a TTree
63
64~~~ {.cpp}
65 TTree tree(name, title)
66~~~
67Creates a Tree with name and title.
68
69Various kinds of branches can be added to a tree:
70- Variables representing fundamental types, simple classes/structures or list of variables: for example for C or Fortran
71structures.
72- Any C++ object or collection, provided by the STL or ROOT.
73
74In the following, the details about the creation of different types of branches are given.
75
76\anchor addcolumnoffundamentaltypes
77## Add a column ("branch") holding fundamental types and arrays thereof
78This strategy works also for lists of variables, e.g. to describe simple structures.
79It is strongly recommended to persistify those as objects rather than lists of leaves.
80
81~~~ {.cpp}
82 auto branch = tree.Branch(branchname, address, leaflist, bufsize)
83~~~
84- `address` is the address of the first item of a structure
85- `leaflist` is the concatenation of all the variable names and types
86 separated by a colon character :
87 The variable name and the variable type are separated by a
88 slash (/). The variable type must be 1 character. (Characters
89 after the first are legal and will be appended to the visible
90 name of the leaf, but have no effect.) If no type is given, the
91 type of the variable is assumed to be the same as the previous
92 variable. If the first variable does not have a type, it is
93 assumed of type F by default. The list of currently supported
94 types is given below:
95 - `C` : a character string terminated by the 0 character
96 - `B` : an 8 bit signed integer (`Char_t`); Treated as a character when in an array.
97 - `b` : an 8 bit unsigned integer (`UChar_t`)
98 - `S` : a 16 bit signed integer (`Short_t`)
99 - `s` : a 16 bit unsigned integer (`UShort_t`)
100 - `I` : a 32 bit signed integer (`Int_t`)
101 - `i` : a 32 bit unsigned integer (`UInt_t`)
102 - `F` : a 32 bit floating point (`Float_t`)
103 - `f` : a 21 bit floating point with truncated mantissa (`Float16_t`): 1 for the sign, 8 for the exponent and 12 for the mantissa.
104 - `D` : a 64 bit floating point (`Double_t`)
105 - `d` : a 32 bit truncated floating point (`Double32_t`): 1 for the sign, 8 for the exponent and 23 for the mantissa.
106 - `L` : a 64 bit signed integer (`Long64_t`)
107 - `l` : a 64 bit unsigned integer (`ULong64_t`)
108 - `G` : a long signed integer, stored as 64 bit (`Long_t`)
109 - `g` : a long unsigned integer, stored as 64 bit (`ULong_t`)
110 - `O` : [the letter `o`, not a zero] a boolean (`bool`)
111
112 Examples:
113 - A int: "myVar/I"
114 - A float array with fixed size: "myArrfloat[42]/F"
115 - An double array with variable size, held by the `myvar` column: "myArrdouble[myvar]/D"
116 - An Double32_t array with variable size, held by the `myvar` column , with values between 0 and 16: "myArr[myvar]/d[0,10]"
117 - The `myvar` column, which holds the variable size, **MUST** be an `Int_t` (/I).
118
119- If the address points to a single numerical variable, the leaflist is optional:
120~~~ {.cpp}
121 int value;
122 tree->Branch(branchname, &value);
123~~~
124- If the address points to more than one numerical variable, we strongly recommend
125 that the variable be sorted in decreasing order of size. Any other order will
126 result in a non-portable TTree (i.e. you will not be able to read it back on a
127 platform with a different padding strategy).
128 We recommend to persistify objects rather than composite leaflists.
129- In case of the truncated floating point types (`Float16_t` and `Double32_t`) you can
130 also specify the range in the style `[xmin,xmax]` or `[xmin,xmax,nbits]` after
131 the type character. For example, for storing a variable size array `myArr` of
132 `Double32_t` with values within a range of `[0, 2*pi]` and the size of which is stored
133 in an `Int_t` (/I) branch called `myArrSize`, the syntax for the `leaflist` string would
134 be: `myArr[myArrSize]/d[0,twopi]`. Of course the number of bits could be specified,
135 the standard rules of opaque typedefs annotation are valid. For example, if only
136 18 bits were sufficient, the syntax would become: `myArr[myArrSize]/d[0,twopi,18]`
137
138\anchor addingacolumnofstl
139## Adding a column holding STL collection instances (e.g. std::vector or std::list)
140
141~~~ {.cpp}
142 auto branch = tree.Branch( branchname, STLcollection, buffsize, splitlevel);
143~~~
144`STLcollection` is the address of a pointer to a container of the standard
145library such as `std::vector`, `std::list`, containing pointers, fundamental types
146or objects.
147If the splitlevel is a value bigger than 100 (`TTree::kSplitCollectionOfPointers`)
148then the collection will be written in split mode, i.e. transparently storing
149individual data members as arrays, therewith potentially increasing compression ratio.
150
151### Note
152In case of dynamic structures changing with each entry, see e.g.
153~~~ {.cpp}
154 branch->SetAddress(void *address)
155~~~
156one must redefine the branch address before filling the branch
157again. This is done via the `TBranch::SetAddress` member function.
158
159\anchor addingacolumnofobjs
160## Add a column holding objects
161
162~~~ {.cpp}
163 MyClass object;
164 auto branch = tree.Branch(branchname, &object, bufsize, splitlevel)
165~~~
166Note: The 2nd parameter must be the address of a valid object.
167 The object must not be destroyed (i.e. be deleted) until the TTree
168 is deleted or TTree::ResetBranchAddress is called.
169
170- if splitlevel=0, the object is serialized in the branch buffer.
171- if splitlevel=1 (default), this branch will automatically be split
172 into subbranches, with one subbranch for each data member or object
173 of the object itself. In case the object member is a TClonesArray,
174 the mechanism described in case C is applied to this array.
175- if splitlevel=2 ,this branch will automatically be split
176 into subbranches, with one subbranch for each data member or object
177 of the object itself. In case the object member is a TClonesArray,
178 it is processed as a TObject*, only one branch.
179
180Another available syntax is the following:
181
182~~~ {.cpp}
183 auto branch_a = tree.Branch(branchname, &p_object, bufsize, splitlevel)
184 auto branch_b = tree.Branch(branchname, className, &p_object, bufsize, splitlevel)
185~~~
186- `p_object` is a pointer to an object.
187- If `className` is not specified, the `Branch` method uses the type of `p_object`
188 to determine the type of the object.
189- If `className` is used to specify explicitly the object type, the `className`
190 must be of a type related to the one pointed to by the pointer. It should be
191 either a parent or derived class.
192
193Note: The pointer whose address is passed to `TTree::Branch` must not
194 be destroyed (i.e. go out of scope) until the TTree is deleted or
195 TTree::ResetBranchAddress is called.
196
197Note: The pointer `p_object` can be initialized before calling `TTree::Branch`
198~~~ {.cpp}
199 auto p_object = new MyDataClass;
200 tree.Branch(branchname, &p_object);
201~~~
202or not
203~~~ {.cpp}
204 MyDataClass* p_object = nullptr;
205 tree.Branch(branchname, &p_object);
206~~~
207In either case, the ownership of the object is not taken over by the `TTree`.
208Even though in the first case an object is be allocated by `TTree::Branch`,
209the object will <b>not</b> be deleted when the `TTree` is deleted.
210
211\anchor addingacolumnoftclonesarray
212## Add a column holding TClonesArray instances
213
214*The usage of `TClonesArray` should be abandoned in favour of `std::vector`,
215for which `TTree` has been heavily optimised, as well as `RNTuple`.*
216
217~~~ {.cpp}
218 // clonesarray is the address of a pointer to a TClonesArray.
219 auto branch = tree.Branch(branchname,clonesarray, bufsize, splitlevel)
220~~~
221The TClonesArray is a direct access list of objects of the same class.
222For example, if the TClonesArray is an array of TTrack objects,
223this function will create one subbranch for each data member of
224the object TTrack.
225
226\anchor fillthetree
227## Fill the Tree
228
229A TTree instance is filled with the invocation of the TTree::Fill method:
230~~~ {.cpp}
231 tree.Fill()
232~~~
233Upon its invocation, a loop on all defined branches takes place that for each branch invokes
234the TBranch::Fill method.
235
236\anchor addcoltoexistingtree
237## Add a column to an already existing Tree
238
239You may want to add a branch to an existing tree. For example,
240if one variable in the tree was computed with a certain algorithm,
241you may want to try another algorithm and compare the results.
242One solution is to add a new branch, fill it, and save the tree.
243The code below adds a simple branch to an existing tree.
244Note the `kOverwrite` option in the `Write` method: it overwrites the
245existing tree. If it is not specified, two copies of the tree headers
246are saved.
247~~~ {.cpp}
248 void addBranchToTree() {
249 TFile f("tree.root", "update");
250
251 Float_t new_v;
252 auto mytree = f->Get<TTree>("mytree");
253 auto newBranch = mytree->Branch("new_v", &new_v, "new_v/F");
254
255 auto nentries = mytree->GetEntries(); // read the number of entries in the mytree
256
257 for (Long64_t i = 0; i < nentries; i++) {
258 new_v = gRandom->Gaus(0, 1);
259 newBranch->Fill();
260 }
261
262 mytree->Write("", TObject::kOverwrite); // save only the new version of the tree
263 }
264~~~
265It is not always possible to add branches to existing datasets stored in TFiles: for example,
266these files might not be writeable, just readable. In addition, modifying in place a TTree
267causes a new TTree instance to be written and the previous one to be deleted.
268For this reasons, ROOT offers the concept of friends for TTree and TChain.
269
270\anchor fullexample
271## A Complete Example
272
273~~~ {.cpp}
274// A simple example creating a tree
275// Compile it with: `g++ myTreeExample.cpp -o myTreeExample `root-config --cflags --libs`
276
277#include "TFile.h"
278#include "TH1D.h"
279#include "TRandom3.h"
280#include "TTree.h"
281
282int main()
283{
284 // Create a new ROOT binary machine independent file.
285 // Note that this file may contain any kind of ROOT objects, histograms,trees
286 // pictures, graphics objects, detector geometries, tracks, events, etc..
287 TFile hfile("htree.root", "RECREATE", "Demo ROOT file with trees");
288
289 // Define a histogram and some simple structures
290 TH1D hpx("hpx", "This is the px distribution", 100, -4, 4);
291
292 typedef struct {
293 Float_t x, y, z;
294 } Point;
295
296 typedef struct {
297 Int_t ntrack, nseg, nvertex;
298 UInt_t flag;
299 Float_t temperature;
300 } Event;
301 Point point;
302 Event event;
303
304 // Create a ROOT Tree
305 TTree tree("T", "An example of ROOT tree with a few branches");
306 tree.Branch("point", &point, "x:y:z");
307 tree.Branch("event", &event, "ntrack/I:nseg:nvertex:flag/i:temperature/F");
308 tree.Branch("hpx", &hpx);
309
310 float px, py;
311
312 TRandom3 myGenerator;
313
314 // Here we start a loop on 1000 events
315 for (Int_t i = 0; i < 1000; i++) {
316 myGenerator.Rannor(px, py);
317 const auto random = myGenerator.Rndm(1);
318
319 // Fill histogram
320 hpx.Fill(px);
321
322 // Fill structures
323 point.x = 10 * (random - 1);
324 point.y = 5 * random;
325 point.z = 20 * random;
326 event.ntrack = int(100 * random);
327 event.nseg = int(2 * event.ntrack);
328 event.nvertex = 1;
329 event.flag = int(random + 0.5);
330 event.temperature = 20 + random;
331
332 // Fill the tree. For each event, save the 2 structures and object.
333 // In this simple example, the objects hpx, hprof and hpxpy are only slightly
334 // different from event to event. We expect a big compression factor!
335 tree.Fill();
336 }
337
338 // Save all objects in this file
339 hfile.Write();
340
341 // Close the file. Note that this is automatically done when you leave
342 // the application upon file destruction.
343 hfile.Close();
344
345 return 0;
346}
347~~~
348## TTree Diagram
349
350The following diagram shows the organisation of the federation of classes related to TTree.
351
352Begin_Macro
353../../../tutorials/legacy/tree/tree.C
354End_Macro
355*/
356
357#include <ROOT/RConfig.hxx>
358#include "TTree.h"
359
360#include "ROOT/TIOFeatures.hxx"
361#include "TArrayC.h"
362#include "TBufferFile.h"
363#include "TBaseClass.h"
364#include "TBasket.h"
365#include "TBranchClones.h"
366#include "TBranchElement.h"
367#include "TBranchObject.h"
368#include "TBranchRef.h"
369#include "TBrowser.h"
370#include "TClass.h"
371#include "TClassEdit.h"
372#include "TClonesArray.h"
373#include "TCut.h"
374#include "TDataMember.h"
375#include "TDataType.h"
376#include "TDirectory.h"
377#include "TError.h"
378#include "TEntryList.h"
379#include "TEnv.h"
380#include "TEventList.h"
381#include "TFile.h"
382#include "TFolder.h"
383#include "TFriendElement.h"
384#include "TInterpreter.h"
385#include "TLeaf.h"
386#include "TLeafB.h"
387#include "TLeafC.h"
388#include "TLeafD.h"
389#include "TLeafElement.h"
390#include "TLeafF.h"
391#include "TLeafI.h"
392#include "TLeafL.h"
393#include "TLeafObject.h"
394#include "TLeafS.h"
395#include "TList.h"
396#include "TMath.h"
397#include "TMemFile.h"
398#include "TROOT.h"
399#include "TRealData.h"
400#include "TRegexp.h"
401#include "TRefTable.h"
402#include "TStreamerElement.h"
403#include "TStreamerInfo.h"
404#include "TStyle.h"
405#include "TSystem.h"
406#include "TTreeCloner.h"
407#include "TTreeCache.h"
408#include "TTreeCacheUnzip.h"
411#include "TVirtualIndex.h"
412#include "TVirtualPerfStats.h"
413#include "TVirtualPad.h"
414#include "TBranchSTL.h"
415#include "TSchemaRuleSet.h"
416#include "TFileMergeInfo.h"
417#include "ROOT/StringConv.hxx"
418#include "TVirtualMutex.h"
419#include "strlcpy.h"
420#include "snprintf.h"
421
422#include "TBranchIMTHelper.h"
423#include "TNotifyLink.h"
424
425#include <chrono>
426#include <cstddef>
427#include <iostream>
428#include <fstream>
429#include <sstream>
430#include <string>
431#include <cstdio>
432#include <climits>
433#include <algorithm>
434#include <set>
435
436#ifdef R__USE_IMT
438#include <thread>
439#endif
441constexpr Int_t kNEntriesResort = 100;
443
444Int_t TTree::fgBranchStyle = 1; // Use new TBranch style with TBranchElement.
445Long64_t TTree::fgMaxTreeSize = 100000000000LL;
446
448
449////////////////////////////////////////////////////////////////////////////////
450////////////////////////////////////////////////////////////////////////////////
451////////////////////////////////////////////////////////////////////////////////
454{
455 // Return the leaflist 'char' for a given datatype.
456
457 switch(datatype) {
458 case kChar_t: return 'B';
459 case kUChar_t: return 'b';
460 case kBool_t: return 'O';
461 case kShort_t: return 'S';
462 case kUShort_t: return 's';
463 case kCounter:
464 case kInt_t: return 'I';
465 case kUInt_t: return 'i';
466 case kDouble_t: return 'D';
467 case kDouble32_t: return 'd';
468 case kFloat_t: return 'F';
469 case kFloat16_t: return 'f';
470 case kLong_t: return 'G';
471 case kULong_t: return 'g';
472 case kchar: return 0; // unsupported
473 case kLong64_t: return 'L';
474 case kULong64_t: return 'l';
475
476 case kCharStar: return 'C';
477 case kBits: return 0; //unsupported
478
479 case kOther_t:
480 case kNoType_t:
481 default:
482 return 0;
483 }
484 return 0;
485}
486
487////////////////////////////////////////////////////////////////////////////////
488/// \class TTree::TFriendLock
489/// Helper class to prevent infinite recursion in the usage of TTree Friends.
490
491////////////////////////////////////////////////////////////////////////////////
492/// Record in tree that it has been used while recursively looks through the friends.
495: fTree(tree)
496{
497 // We could also add some code to acquire an actual
498 // lock to prevent multi-thread issues
500 if (fTree) {
503 } else {
504 fPrevious = false;
505 }
506}
507
508////////////////////////////////////////////////////////////////////////////////
509/// Copy constructor.
512 fTree(tfl.fTree),
513 fMethodBit(tfl.fMethodBit),
514 fPrevious(tfl.fPrevious)
515{
516}
517
518////////////////////////////////////////////////////////////////////////////////
519/// Assignment operator.
522{
523 if(this!=&tfl) {
524 fTree=tfl.fTree;
525 fMethodBit=tfl.fMethodBit;
526 fPrevious=tfl.fPrevious;
527 }
528 return *this;
529}
530
531////////////////////////////////////////////////////////////////////////////////
532/// Restore the state of tree the same as before we set the lock.
535{
536 if (fTree) {
537 if (!fPrevious) {
538 fTree->fFriendLockStatus &= ~(fMethodBit & kBitMask);
539 }
540 }
541}
542
543////////////////////////////////////////////////////////////////////////////////
544/// \class TTree::TClusterIterator
545/// Helper class to iterate over cluster of baskets.
546
547////////////////////////////////////////////////////////////////////////////////
548/// Regular constructor.
549/// TTree is not set as const, since we might modify if it is a TChain.
551TTree::TClusterIterator::TClusterIterator(TTree *tree, Long64_t firstEntry) : fTree(tree), fClusterRange(0), fStartEntry(0), fNextEntry(0), fEstimatedSize(-1)
552{
553 if (fTree->fNClusterRange) {
554 // Find the correct cluster range.
555 //
556 // Since fClusterRangeEnd contains the inclusive upper end of the range, we need to search for the
557 // range that was containing the previous entry and add 1 (because BinarySearch consider the values
558 // to be the inclusive start of the bucket).
560
563 if (fClusterRange == 0) {
564 pedestal = 0;
566 } else {
569 }
573 } else {
575 }
576 if (autoflush <= 0) {
578 }
580 } else if ( fTree->GetAutoFlush() <= 0 ) {
581 // Case of old files before November 9 2009 *or* small tree where AutoFlush was never set.
583 } else {
585 }
586 fNextEntry = fStartEntry; // Position correctly for the first call to Next()
587}
588
589////////////////////////////////////////////////////////////////////////////////
590/// Estimate the cluster size.
591///
592/// In almost all cases, this quickly returns the size of the auto-flush
593/// in the TTree.
594///
595/// However, in the case where the cluster size was not fixed (old files and
596/// case where autoflush was explicitly set to zero), we need estimate
597/// a cluster size in relation to the size of the cache.
598///
599/// After this value is calculated once for the TClusterIterator, it is
600/// cached and reused in future calls.
603{
604 auto autoFlush = fTree->GetAutoFlush();
605 if (autoFlush > 0) return autoFlush;
606 if (fEstimatedSize > 0) return fEstimatedSize;
607
608 Long64_t zipBytes = fTree->GetZipBytes();
609 if (zipBytes == 0) {
610 fEstimatedSize = fTree->GetEntries() - 1;
611 if (fEstimatedSize <= 0)
612 fEstimatedSize = 1;
613 } else {
615 Long64_t cacheSize = fTree->GetCacheSize();
616 if (cacheSize == 0) {
617 // Humm ... let's double check on the file.
618 TFile *file = fTree->GetCurrentFile();
619 if (file) {
620 TFileCacheRead *cache = fTree->GetReadCache(file);
621 if (cache) {
622 cacheSize = cache->GetBufferSize();
623 }
624 }
625 }
626 // If neither file nor tree has a cache, use the current default.
627 if (cacheSize <= 0) {
628 cacheSize = 30000000;
629 }
630 clusterEstimate = fTree->GetEntries() * cacheSize / zipBytes;
631 // If there are no entries, then just default to 1.
632 fEstimatedSize = clusterEstimate ? clusterEstimate : 1;
633 }
634 return fEstimatedSize;
635}
636
637////////////////////////////////////////////////////////////////////////////////
638/// Move on to the next cluster and return the starting entry
639/// of this next cluster
642{
643 fStartEntry = fNextEntry;
644 if (fTree->fNClusterRange || fTree->GetAutoFlush() > 0) {
645 if (fClusterRange == fTree->fNClusterRange) {
646 // We are looking at a range which size
647 // is defined by AutoFlush itself and goes to the GetEntries.
648 fNextEntry += GetEstimatedClusterSize();
649 } else {
650 if (fStartEntry > fTree->fClusterRangeEnd[fClusterRange]) {
651 ++fClusterRange;
652 }
653 if (fClusterRange == fTree->fNClusterRange) {
654 // We are looking at the last range which size
655 // is defined by AutoFlush itself and goes to the GetEntries.
656 fNextEntry += GetEstimatedClusterSize();
657 } else {
658 Long64_t clusterSize = fTree->fClusterSize[fClusterRange];
659 if (clusterSize == 0) {
660 clusterSize = GetEstimatedClusterSize();
661 }
662 fNextEntry += clusterSize;
663 if (fNextEntry > fTree->fClusterRangeEnd[fClusterRange]) {
664 // The last cluster of the range was a partial cluster,
665 // so the next cluster starts at the beginning of the
666 // next range.
667 fNextEntry = fTree->fClusterRangeEnd[fClusterRange] + 1;
668 }
669 }
670 }
671 } else {
672 // Case of old files before November 9 2009
673 fNextEntry = fStartEntry + GetEstimatedClusterSize();
674 }
675 if (fNextEntry > fTree->GetEntries()) {
676 fNextEntry = fTree->GetEntries();
677 }
678 return fStartEntry;
679}
680
681////////////////////////////////////////////////////////////////////////////////
682/// Move on to the previous cluster and return the starting entry
683/// of this previous cluster
686{
687 fNextEntry = fStartEntry;
688 if (fTree->fNClusterRange || fTree->GetAutoFlush() > 0) {
689 if (fClusterRange == 0 || fTree->fNClusterRange == 0) {
690 // We are looking at a range which size
691 // is defined by AutoFlush itself.
692 fStartEntry -= GetEstimatedClusterSize();
693 } else {
694 if (fNextEntry <= fTree->fClusterRangeEnd[fClusterRange]) {
695 --fClusterRange;
696 }
697 if (fClusterRange == 0) {
698 // We are looking at the first range.
699 fStartEntry = 0;
700 } else {
701 Long64_t clusterSize = fTree->fClusterSize[fClusterRange];
702 if (clusterSize == 0) {
703 clusterSize = GetEstimatedClusterSize();
704 }
705 fStartEntry -= clusterSize;
706 }
707 }
708 } else {
709 // Case of old files before November 9 2009 or trees that never auto-flushed.
710 fStartEntry = fNextEntry - GetEstimatedClusterSize();
711 }
712 if (fStartEntry < 0) {
713 fStartEntry = 0;
714 }
715 return fStartEntry;
716}
717
718////////////////////////////////////////////////////////////////////////////////
719////////////////////////////////////////////////////////////////////////////////
720////////////////////////////////////////////////////////////////////////////////
721
722////////////////////////////////////////////////////////////////////////////////
723/// Default constructor and I/O constructor.
724///
725/// Note: We do *not* insert ourself into the current directory.
726///
729: TNamed()
730, TAttLine()
731, TAttFill()
732, TAttMarker()
733, fEntries(0)
734, fTotBytes(0)
735, fZipBytes(0)
736, fSavedBytes(0)
737, fFlushedBytes(0)
738, fWeight(1)
740, fScanField(25)
741, fUpdate(0)
745, fMaxEntries(0)
746, fMaxEntryLoop(0)
748, fAutoSave( -300000000)
749, fAutoFlush(-30000000)
750, fEstimate(1000000)
751, fClusterRangeEnd(nullptr)
752, fClusterSize(nullptr)
753, fCacheSize(0)
754, fChainOffset(0)
755, fReadEntry(-1)
756, fTotalBuffers(0)
757, fPacketSize(100)
758, fNfill(0)
759, fDebug(0)
760, fDebugMin(0)
761, fDebugMax(9999999)
762, fMakeClass(0)
763, fFileNumber(0)
764, fNotify(nullptr)
765, fDirectory(nullptr)
766, fBranches()
767, fLeaves()
768, fAliases(nullptr)
769, fEventList(nullptr)
770, fEntryList(nullptr)
771, fIndexValues()
772, fIndex()
773, fTreeIndex(nullptr)
774, fFriends(nullptr)
775, fExternalFriends(nullptr)
776, fPerfStats(nullptr)
777, fUserInfo(nullptr)
778, fPlayer(nullptr)
779, fClones(nullptr)
780, fBranchRef(nullptr)
782, fTransientBuffer(nullptr)
786, fIMTEnabled(ROOT::IsImplicitMTEnabled())
788{
789 fMaxEntries = 1000000000;
790 fMaxEntries *= 1000;
791
792 fMaxEntryLoop = 1000000000;
793 fMaxEntryLoop *= 1000;
794
795 fBranches.SetOwner(true);
796}
797
798////////////////////////////////////////////////////////////////////////////////
799/// Normal tree constructor.
800///
801/// The tree is created in the current directory.
802/// Use the various functions Branch below to add branches to this tree.
803///
804/// If the first character of title is a "/", the function assumes a folder name.
805/// In this case, it creates automatically branches following the folder hierarchy.
806/// splitlevel may be used in this case to control the split level.
808TTree::TTree(const char* name, const char* title, Int_t splitlevel /* = 99 */,
809 TDirectory* dir /* = gDirectory*/)
810: TNamed(name, title)
811, TAttLine()
812, TAttFill()
813, TAttMarker()
814, fEntries(0)
815, fTotBytes(0)
816, fZipBytes(0)
817, fSavedBytes(0)
818, fFlushedBytes(0)
819, fWeight(1)
820, fTimerInterval(0)
821, fScanField(25)
822, fUpdate(0)
823, fDefaultEntryOffsetLen(1000)
824, fNClusterRange(0)
825, fMaxClusterRange(0)
826, fMaxEntries(0)
827, fMaxEntryLoop(0)
828, fMaxVirtualSize(0)
829, fAutoSave( -300000000)
830, fAutoFlush(-30000000)
831, fEstimate(1000000)
832, fClusterRangeEnd(nullptr)
833, fClusterSize(nullptr)
834, fCacheSize(0)
835, fChainOffset(0)
836, fReadEntry(-1)
837, fTotalBuffers(0)
838, fPacketSize(100)
839, fNfill(0)
840, fDebug(0)
841, fDebugMin(0)
842, fDebugMax(9999999)
843, fMakeClass(0)
844, fFileNumber(0)
845, fNotify(nullptr)
846, fDirectory(dir)
847, fBranches()
848, fLeaves()
849, fAliases(nullptr)
850, fEventList(nullptr)
851, fEntryList(nullptr)
852, fIndexValues()
853, fIndex()
854, fTreeIndex(nullptr)
855, fFriends(nullptr)
856, fExternalFriends(nullptr)
857, fPerfStats(nullptr)
858, fUserInfo(nullptr)
859, fPlayer(nullptr)
860, fClones(nullptr)
861, fBranchRef(nullptr)
862, fFriendLockStatus(0)
863, fTransientBuffer(nullptr)
864, fCacheDoAutoInit(true)
865, fCacheDoClusterPrefetch(false)
866, fCacheUserSet(false)
867, fIMTEnabled(ROOT::IsImplicitMTEnabled())
868, fNEntriesSinceSorting(0)
869{
870 // TAttLine state.
874
875 // TAttFill state.
878
879 // TAttMarkerState.
883
884 fMaxEntries = 1000000000;
885 fMaxEntries *= 1000;
886
887 fMaxEntryLoop = 1000000000;
888 fMaxEntryLoop *= 1000;
889
890 // Insert ourself into the current directory.
891 // FIXME: This is very annoying behaviour, we should
892 // be able to choose to not do this like we
893 // can with a histogram.
894 if (fDirectory) fDirectory->Append(this);
895
896 fBranches.SetOwner(true);
897
898 // If title starts with "/" and is a valid folder name, a superbranch
899 // is created.
900 // FIXME: Why?
901 if (strlen(title) > 2) {
902 if (title[0] == '/') {
903 Branch(title+1,32000,splitlevel);
904 }
905 }
906}
907
908////////////////////////////////////////////////////////////////////////////////
909/// Destructor.
912{
913 if (auto link = dynamic_cast<TNotifyLinkBase*>(fNotify)) {
914 link->Clear();
915 }
916 if (fAllocationCount && (gDebug > 0)) {
917 Info("TTree::~TTree", "For tree %s, allocation count is %u.", GetName(), fAllocationCount.load());
918#ifdef R__TRACK_BASKET_ALLOC_TIME
919 Info("TTree::~TTree", "For tree %s, allocation time is %lluus.", GetName(), fAllocationTime.load());
920#endif
921 }
922
923 if (fDirectory) {
924 // We are in a directory, which may possibly be a file.
925 if (fDirectory->GetList()) {
926 // Remove us from the directory listing.
927 fDirectory->Remove(this);
928 }
929 //delete the file cache if it points to this Tree
930 TFile *file = fDirectory->GetFile();
931 MoveReadCache(file,nullptr);
932 }
933
934 // Remove the TTree from any list (linked to to the list of Cleanups) to avoid the unnecessary call to
935 // this RecursiveRemove while we delete our content.
937 ResetBit(kMustCleanup); // Don't redo it.
938
939 // We don't own the leaves in fLeaves, the branches do.
940 fLeaves.Clear();
941 // I'm ready to destroy any objects allocated by
942 // SetAddress() by my branches. If I have clones,
943 // tell them to zero their pointers to this shared
944 // memory.
945 if (fClones && fClones->GetEntries()) {
946 // I have clones.
947 // I am about to delete the objects created by
948 // SetAddress() which we are sharing, so tell
949 // the clones to release their pointers to them.
950 for (TObjLink* lnk = fClones->FirstLink(); lnk; lnk = lnk->Next()) {
951 TTree* clone = (TTree*) lnk->GetObject();
952 // clone->ResetBranchAddresses();
953
954 // Reset only the branch we have set the address of.
955 CopyAddresses(clone,true);
956 }
957 }
958 // Get rid of our branches, note that this will also release
959 // any memory allocated by TBranchElement::SetAddress().
961
962 // The TBranch destructor is using fDirectory to detect whether it
963 // owns the TFile that contains its data (See TBranch::~TBranch)
964 fDirectory = nullptr;
965
966 // FIXME: We must consider what to do with the reset of these if we are a clone.
967 delete fPlayer;
968 fPlayer = nullptr;
969 if (fExternalFriends) {
970 using namespace ROOT::Detail;
972 fetree->Reset();
973 fExternalFriends->Clear("nodelete");
975 }
976 if (fFriends) {
977 fFriends->Delete();
978 delete fFriends;
979 fFriends = nullptr;
980 }
981 if (fAliases) {
982 fAliases->Delete();
983 delete fAliases;
984 fAliases = nullptr;
985 }
986 if (fUserInfo) {
987 fUserInfo->Delete();
988 delete fUserInfo;
989 fUserInfo = nullptr;
990 }
991 if (fClones) {
992 // Clone trees should no longer be removed from fClones when they are deleted.
993 {
995 gROOT->GetListOfCleanups()->Remove(fClones);
996 }
997 // Note: fClones does not own its content.
998 delete fClones;
999 fClones = nullptr;
1000 }
1001 if (fEntryList) {
1002 if (fEntryList->TestBit(kCanDelete) && fEntryList->GetDirectory()==nullptr) {
1003 // Delete the entry list if it is marked to be deleted and it is not also
1004 // owned by a directory. (Otherwise we would need to make sure that a
1005 // TDirectoryFile that has a TTree in it does a 'slow' TList::Delete.
1006 delete fEntryList;
1007 fEntryList=nullptr;
1008 }
1009 }
1010 delete fTreeIndex;
1011 fTreeIndex = nullptr;
1012 delete fBranchRef;
1013 fBranchRef = nullptr;
1014 delete [] fClusterRangeEnd;
1015 fClusterRangeEnd = nullptr;
1016 delete [] fClusterSize;
1017 fClusterSize = nullptr;
1018
1019 if (fTransientBuffer) {
1020 delete fTransientBuffer;
1021 fTransientBuffer = nullptr;
1022 }
1023}
1024
1025////////////////////////////////////////////////////////////////////////////////
1026/// Returns the transient buffer currently used by this TTree for reading/writing baskets.
1038}
1039
1040////////////////////////////////////////////////////////////////////////////////
1041/// Add branch with name bname to the Tree cache.
1042/// If bname="*" all branches are added to the cache.
1043/// if subbranches is true all the branches of the subbranches are
1044/// also put to the cache.
1045///
1046/// Returns:
1047/// - 0 branch added or already included
1048/// - -1 on error
1050Int_t TTree::AddBranchToCache(const char*bname, bool subbranches)
1051{
1052 if (!GetTree()) {
1053 if (LoadTree(0)<0) {
1054 Error("AddBranchToCache","Could not load a tree");
1055 return -1;
1056 }
1057 }
1058 if (GetTree()) {
1059 if (GetTree() != this) {
1060 return GetTree()->AddBranchToCache(bname, subbranches);
1061 }
1062 } else {
1063 Error("AddBranchToCache", "No tree is available. Branch was not added to the cache");
1064 return -1;
1065 }
1066
1067 TFile *f = GetCurrentFile();
1068 if (!f) {
1069 Error("AddBranchToCache", "No file is available. Branch was not added to the cache");
1070 return -1;
1071 }
1072 TTreeCache *tc = GetReadCache(f,true);
1073 if (!tc) {
1074 Error("AddBranchToCache", "No cache is available, branch not added");
1075 return -1;
1076 }
1077 return tc->AddBranch(bname,subbranches);
1078}
1079
1080////////////////////////////////////////////////////////////////////////////////
1081/// Add branch b to the Tree cache.
1082/// if subbranches is true all the branches of the subbranches are
1083/// also put to the cache.
1084///
1085/// Returns:
1086/// - 0 branch added or already included
1087/// - -1 on error
1090{
1091 if (!GetTree()) {
1092 if (LoadTree(0)<0) {
1093 Error("AddBranchToCache","Could not load a tree");
1094 return -1;
1095 }
1096 }
1097 if (GetTree()) {
1098 if (GetTree() != this) {
1099 Int_t res = GetTree()->AddBranchToCache(b, subbranches);
1100 if (res<0) {
1101 Error("AddBranchToCache", "Error adding branch");
1102 }
1103 return res;
1104 }
1105 } else {
1106 Error("AddBranchToCache", "No tree is available. Branch was not added to the cache");
1107 return -1;
1108 }
1109
1110 TFile *f = GetCurrentFile();
1111 if (!f) {
1112 Error("AddBranchToCache", "No file is available. Branch was not added to the cache");
1113 return -1;
1114 }
1115 TTreeCache *tc = GetReadCache(f,true);
1116 if (!tc) {
1117 Error("AddBranchToCache", "No cache is available, branch not added");
1118 return -1;
1119 }
1120 return tc->AddBranch(b,subbranches);
1121}
1122
1123////////////////////////////////////////////////////////////////////////////////
1124/// Remove the branch with name 'bname' from the Tree cache.
1125/// If bname="*" all branches are removed from the cache.
1126/// if subbranches is true all the branches of the subbranches are
1127/// also removed from the cache.
1128///
1129/// Returns:
1130/// - 0 branch dropped or not in cache
1131/// - -1 on error
1133Int_t TTree::DropBranchFromCache(const char*bname, bool subbranches)
1134{
1135 if (!GetTree()) {
1136 if (LoadTree(0)<0) {
1137 Error("DropBranchFromCache","Could not load a tree");
1138 return -1;
1139 }
1140 }
1141 if (GetTree()) {
1142 if (GetTree() != this) {
1143 return GetTree()->DropBranchFromCache(bname, subbranches);
1144 }
1145 } else {
1146 Error("DropBranchFromCache", "No tree is available. Branch was not dropped from the cache");
1147 return -1;
1148 }
1149
1150 TFile *f = GetCurrentFile();
1151 if (!f) {
1152 Error("DropBranchFromCache", "No file is available. Branch was not dropped from the cache");
1153 return -1;
1154 }
1155 TTreeCache *tc = GetReadCache(f,true);
1156 if (!tc) {
1157 Error("DropBranchFromCache", "No cache is available, branch not dropped");
1158 return -1;
1159 }
1160 return tc->DropBranch(bname,subbranches);
1161}
1162
1163////////////////////////////////////////////////////////////////////////////////
1164/// Remove the branch b from the Tree cache.
1165/// if subbranches is true all the branches of the subbranches are
1166/// also removed from the cache.
1167///
1168/// Returns:
1169/// - 0 branch dropped or not in cache
1170/// - -1 on error
1173{
1174 if (!GetTree()) {
1175 if (LoadTree(0)<0) {
1176 Error("DropBranchFromCache","Could not load a tree");
1177 return -1;
1178 }
1179 }
1180 if (GetTree()) {
1181 if (GetTree() != this) {
1182 Int_t res = GetTree()->DropBranchFromCache(b, subbranches);
1183 if (res<0) {
1184 Error("DropBranchFromCache", "Error dropping branch");
1185 }
1186 return res;
1187 }
1188 } else {
1189 Error("DropBranchFromCache", "No tree is available. Branch was not dropped from the cache");
1190 return -1;
1191 }
1192
1193 TFile *f = GetCurrentFile();
1194 if (!f) {
1195 Error("DropBranchFromCache", "No file is available. Branch was not dropped from the cache");
1196 return -1;
1197 }
1198 TTreeCache *tc = GetReadCache(f,true);
1199 if (!tc) {
1200 Error("DropBranchFromCache", "No cache is available, branch not dropped");
1201 return -1;
1202 }
1203 return tc->DropBranch(b,subbranches);
1204}
1205
1206////////////////////////////////////////////////////////////////////////////////
1207/// Add a cloned tree to our list of trees to be notified whenever we change
1208/// our branch addresses or when we are deleted.
1210void TTree::AddClone(TTree* clone)
1211{
1212 if (!fClones) {
1213 fClones = new TList();
1214 fClones->SetOwner(false);
1215 // So that the clones are automatically removed from the list when
1216 // they are deleted.
1217 {
1219 gROOT->GetListOfCleanups()->Add(fClones);
1220 }
1221 }
1222 if (!fClones->FindObject(clone)) {
1223 fClones->Add(clone);
1224 }
1225}
1226
1227// Check whether mainTree and friendTree can be friends w.r.t. the kEntriesReshuffled bit.
1228// In particular, if any has the bit set, then friendTree must have a TTreeIndex and the
1229// branches used for indexing must be present in mainTree.
1230// Return true if the trees can be friends, false otherwise.
1232{
1235 const auto friendHasValidIndex = [&] {
1236 auto idx = friendTree.GetTreeIndex();
1237 return idx ? idx->IsValidFor(&mainTree) : false;
1238 }();
1239
1241 const auto reshuffledTreeName = isMainReshuffled ? mainTree.GetName() : friendTree.GetName();
1242 const auto msg =
1243 "Tree '%s' has the kEntriesReshuffled bit set and cannot have friends nor can be added as a friend unless the "
1244 "main tree has a TTreeIndex on the friend tree '%s'. You can also unset the bit manually if you know what you "
1245 "are doing; note that you risk associating wrong TTree entries of the friend with those of the main TTree!";
1246 Error("AddFriend", msg, reshuffledTreeName, friendTree.GetName());
1247 return false;
1248 }
1249 return true;
1250}
1251
1252////////////////////////////////////////////////////////////////////////////////
1253/// Add a TFriendElement to the list of friends.
1254///
1255/// This function:
1256/// - opens a file if filename is specified
1257/// - reads a Tree with name treename from the file (current directory)
1258/// - adds the Tree to the list of friends
1259/// see other AddFriend functions
1260///
1261/// A TFriendElement TF describes a TTree object TF in a file.
1262/// When a TFriendElement TF is added to the list of friends of an
1263/// existing TTree T, any variable from TF can be referenced in a query
1264/// to T.
1265///
1266/// A tree keeps a list of friends. In the context of a tree (or a chain),
1267/// friendship means unrestricted access to the friends data. In this way
1268/// it is much like adding another branch to the tree without taking the risk
1269/// of damaging it. To add a friend to the list, you can use the TTree::AddFriend
1270/// method. The tree in the diagram below has two friends (friend_tree1 and
1271/// friend_tree2) and now has access to the variables a,b,c,i,j,k,l and m.
1272///
1273/// \image html ttree_friend1.png
1274///
1275/// The AddFriend method has two parameters, the first is the tree name and the
1276/// second is the name of the ROOT file where the friend tree is saved.
1277/// AddFriend automatically opens the friend file. If no file name is given,
1278/// the tree called ft1 is assumed to be in the same file as the original tree.
1279///
1280/// tree.AddFriend("ft1","friendfile1.root");
1281/// If the friend tree has the same name as the original tree, you can give it
1282/// an alias in the context of the friendship:
1283///
1284/// tree.AddFriend("tree1 = tree","friendfile1.root");
1285/// Once the tree has friends, we can use TTree::Draw as if the friend's
1286/// variables were in the original tree. To specify which tree to use in
1287/// the Draw method, use the syntax:
1288/// ~~~ {.cpp}
1289/// <treeName>.<branchname>.<varname>
1290/// ~~~
1291/// If the variablename is enough to uniquely identify the variable, you can
1292/// leave out the tree and/or branch name.
1293/// For example, these commands generate a 3-d scatter plot of variable "var"
1294/// in the TTree tree versus variable v1 in TTree ft1 versus variable v2 in
1295/// TTree ft2.
1296/// ~~~ {.cpp}
1297/// tree.AddFriend("ft1","friendfile1.root");
1298/// tree.AddFriend("ft2","friendfile2.root");
1299/// tree.Draw("var:ft1.v1:ft2.v2");
1300/// ~~~
1301/// \image html ttree_friend2.png
1302///
1303/// The picture illustrates the access of the tree and its friends with a
1304/// Draw command.
1305/// When AddFriend is called, the ROOT file is automatically opened and the
1306/// friend tree (ft1) is read into memory. The new friend (ft1) is added to
1307/// the list of friends of tree.
1308/// The number of entries in the friend must be equal or greater to the number
1309/// of entries of the original tree. If the friend tree has fewer entries a
1310/// warning is given and the missing entries are not included in the histogram.
1311/// To retrieve the list of friends from a tree use TTree::GetListOfFriends.
1312/// When the tree is written to file (TTree::Write), the friends list is saved
1313/// with it. And when the tree is retrieved, the trees on the friends list are
1314/// also retrieved and the friendship restored.
1315/// When a tree is deleted, the elements of the friend list are also deleted.
1316/// It is possible to declare a friend tree that has the same internal
1317/// structure (same branches and leaves) as the original tree, and compare the
1318/// same values by specifying the tree.
1319/// ~~~ {.cpp}
1320/// tree.Draw("var:ft1.var:ft2.var")
1321/// ~~~
1323TFriendElement *TTree::AddFriend(const char *treename, const char *filename)
1324{
1325 if (!fFriends) {
1326 fFriends = new TList();
1327 }
1329
1330 TTree *t = fe->GetTree();
1331 bool canAddFriend = true;
1332 if (t) {
1333 canAddFriend = CheckReshuffling(*this, *t);
1334 if (!t->GetTreeIndex() && (t->GetEntries() < fEntries)) {
1335 Warning("AddFriend", "FriendElement %s in file %s has less entries %lld than its parent Tree: %lld", treename,
1337 }
1338 } else {
1339 Error("AddFriend", "Cannot find tree '%s' in file '%s', friend not added", treename, filename);
1340 canAddFriend = false;
1341 }
1342
1343 if (canAddFriend)
1344 fFriends->Add(fe);
1345 return fe;
1346}
1347
1348////////////////////////////////////////////////////////////////////////////////
1349/// Add a TFriendElement to the list of friends.
1350///
1351/// The TFile is managed by the user (e.g. the user must delete the file).
1352/// For complete description see AddFriend(const char *, const char *).
1353/// This function:
1354/// - reads a Tree with name treename from the file
1355/// - adds the Tree to the list of friends
1357TFriendElement *TTree::AddFriend(const char *treename, TFile *file)
1358{
1359 if (!fFriends) {
1360 fFriends = new TList();
1361 }
1362 TFriendElement *fe = new TFriendElement(this, treename, file);
1363 R__ASSERT(fe);
1364 TTree *t = fe->GetTree();
1365 bool canAddFriend = true;
1366 if (t) {
1367 canAddFriend = CheckReshuffling(*this, *t);
1368 if (!t->GetTreeIndex() && (t->GetEntries() < fEntries)) {
1369 Warning("AddFriend", "FriendElement %s in file %s has less entries %lld than its parent tree: %lld", treename,
1370 file->GetName(), t->GetEntries(), fEntries);
1371 }
1372 } else {
1373 Error("AddFriend", "Cannot find tree '%s' in file '%s', friend not added", treename, file->GetName());
1374 canAddFriend = false;
1375 }
1376
1377 if (canAddFriend)
1378 fFriends->Add(fe);
1379 return fe;
1380}
1381
1382////////////////////////////////////////////////////////////////////////////////
1383/// Add a TFriendElement to the list of friends.
1384///
1385/// The TTree is managed by the user (e.g., the user must delete the file).
1386/// For a complete description see AddFriend(const char *, const char *).
1388TFriendElement *TTree::AddFriend(TTree *tree, const char *alias, bool warn)
1389{
1390 if (!tree) {
1391 return nullptr;
1392 }
1393 if (!fFriends) {
1394 fFriends = new TList();
1395 }
1396 TFriendElement *fe = new TFriendElement(this, tree, alias);
1397 R__ASSERT(fe); // this assert is for historical reasons. Don't remove it unless you understand all the consequences.
1398 TTree *t = fe->GetTree();
1399 if (warn && (t->GetEntries() < fEntries)) {
1400 Warning("AddFriend", "FriendElement '%s' in file '%s' has less entries %lld than its parent tree: %lld",
1401 tree->GetName(), fe->GetFile() ? fe->GetFile()->GetName() : "(memory resident)", t->GetEntries(),
1402 fEntries);
1403 }
1404 if (CheckReshuffling(*this, *t))
1405 fFriends->Add(fe);
1406 else
1407 tree->RemoveExternalFriend(fe);
1408 return fe;
1409}
1410
1411////////////////////////////////////////////////////////////////////////////////
1412/// AutoSave tree header every fAutoSave bytes.
1413///
1414/// When large Trees are produced, it is safe to activate the AutoSave
1415/// procedure. Some branches may have buffers holding many entries.
1416/// If fAutoSave is negative, AutoSave is automatically called by
1417/// TTree::Fill when the number of bytes generated since the previous
1418/// AutoSave is greater than -fAutoSave bytes.
1419/// If fAutoSave is positive, AutoSave is automatically called by
1420/// TTree::Fill every N entries.
1421/// This function may also be invoked by the user.
1422/// Each AutoSave generates a new key on the file.
1423/// Once the key with the tree header has been written, the previous cycle
1424/// (if any) is deleted.
1425///
1426/// Note that calling TTree::AutoSave too frequently (or similarly calling
1427/// TTree::SetAutoSave with a small value) is an expensive operation.
1428/// You should make tests for your own application to find a compromise
1429/// between speed and the quantity of information you may loose in case of
1430/// a job crash.
1431///
1432/// In case your program crashes before closing the file holding this tree,
1433/// the file will be automatically recovered when you will connect the file
1434/// in UPDATE mode.
1435/// The Tree will be recovered at the status corresponding to the last AutoSave.
1436///
1437/// if option contains "SaveSelf", gDirectory->SaveSelf() is called.
1438/// This allows another process to analyze the Tree while the Tree is being filled.
1439///
1440/// if option contains "FlushBaskets", TTree::FlushBaskets is called and all
1441/// the current basket are closed-out and written to disk individually.
1442///
1443/// By default the previous header is deleted after having written the new header.
1444/// if option contains "Overwrite", the previous Tree header is deleted
1445/// before written the new header. This option is slightly faster, but
1446/// the default option is safer in case of a problem (disk quota exceeded)
1447/// when writing the new header.
1448///
1449/// The function returns the number of bytes written to the file.
1450/// if the number of bytes is null, an error has occurred while writing
1451/// the header to the file.
1452///
1453/// ## How to write a Tree in one process and view it from another process
1454///
1455/// The following two scripts illustrate how to do this.
1456/// The script treew.C is executed by process1, treer.C by process2
1457///
1458/// script treew.C:
1459/// ~~~ {.cpp}
1460/// void treew() {
1461/// TFile f("test.root","recreate");
1462/// TNtuple *ntuple = new TNtuple("ntuple","Demo","px:py:pz:random:i");
1463/// Float_t px, py, pz;
1464/// for ( Int_t i=0; i<10000000; i++) {
1465/// gRandom->Rannor(px,py);
1466/// pz = px*px + py*py;
1467/// Float_t random = gRandom->Rndm(1);
1468/// ntuple->Fill(px,py,pz,random,i);
1469/// if (i%1000 == 1) ntuple->AutoSave("SaveSelf");
1470/// }
1471/// }
1472/// ~~~
1473/// script treer.C:
1474/// ~~~ {.cpp}
1475/// void treer() {
1476/// TFile f("test.root");
1477/// TTree *ntuple = (TTree*)f.Get("ntuple");
1478/// TCanvas c1;
1479/// Int_t first = 0;
1480/// while(1) {
1481/// if (first == 0) ntuple->Draw("px>>hpx", "","",10000000,first);
1482/// else ntuple->Draw("px>>+hpx","","",10000000,first);
1483/// first = (Int_t)ntuple->GetEntries();
1484/// c1.Update();
1485/// gSystem->Sleep(1000); //sleep 1 second
1486/// ntuple->Refresh();
1487/// }
1488/// }
1489/// ~~~
1492{
1493 if (!fDirectory || fDirectory == gROOT || !fDirectory->IsWritable()) return 0;
1494 if (gDebug > 0) {
1495 Info("AutoSave", "Tree:%s after %lld bytes written\n",GetName(),GetTotBytes());
1496 }
1497 TString opt = option;
1498 opt.ToLower();
1499
1500 if (opt.Contains("flushbaskets")) {
1501 if (gDebug > 0) Info("AutoSave", "calling FlushBaskets \n");
1503 }
1504
1506
1507 TKey *key = (TKey*)fDirectory->GetListOfKeys()->FindObject(GetName());
1509 if (opt.Contains("overwrite")) {
1510 nbytes = fDirectory->WriteTObject(this,"","overwrite");
1511 } else {
1512 nbytes = fDirectory->WriteTObject(this); //nbytes will be 0 if Write failed (disk space exceeded)
1513 if (nbytes && key && strcmp(ClassName(), key->GetClassName()) == 0) {
1514 key->Delete();
1515 delete key;
1516 }
1517 }
1518 // save StreamerInfo
1519 TFile *file = fDirectory->GetFile();
1520 if (file) file->WriteStreamerInfo();
1521
1522 if (opt.Contains("saveself")) {
1524 //the following line is required in case GetUserInfo contains a user class
1525 //for which the StreamerInfo must be written. One could probably be a bit faster (Rene)
1526 if (file) file->WriteHeader();
1527 }
1528
1529 return nbytes;
1530}
1531
1532namespace {
1533 // This error message is repeated several times in the code. We write it once.
1534 const char* writeStlWithoutProxyMsg = "The class requested (%s) for the branch \"%s\""
1535 " is an instance of an stl collection and does not have a compiled CollectionProxy."
1536 " Please generate the dictionary for this collection (%s) to avoid to write corrupted data.";
1537}
1538
1539////////////////////////////////////////////////////////////////////////////////
1540/// Same as TTree::Branch() with added check that addobj matches className.
1541///
1542/// \see TTree::Branch()
1543///
1545TBranch* TTree::BranchImp(const char* branchname, const char* classname, TClass* ptrClass, void* addobj, Int_t bufsize, Int_t splitlevel)
1546{
1547 TClass* claim = TClass::GetClass(classname);
1548 if (!ptrClass) {
1549 if (claim && claim->GetCollectionProxy() && dynamic_cast<TEmulatedCollectionProxy*>(claim->GetCollectionProxy())) {
1551 claim->GetName(), branchname, claim->GetName());
1552 return nullptr;
1553 }
1554 return Branch(branchname, classname, (void*) addobj, bufsize, splitlevel);
1555 }
1556 TClass* actualClass = nullptr;
1557 void** addr = (void**) addobj;
1558 if (addr) {
1559 actualClass = ptrClass->GetActualClass(*addr);
1560 }
1561 if (ptrClass && claim) {
1562 if (!(claim->InheritsFrom(ptrClass) || ptrClass->InheritsFrom(claim))) {
1563 // Note we currently do not warn in case of splicing or over-expectation).
1564 if (claim->IsLoaded() && ptrClass->IsLoaded() && strcmp( claim->GetTypeInfo()->name(), ptrClass->GetTypeInfo()->name() ) == 0) {
1565 // The type is the same according to the C++ type_info, we must be in the case of
1566 // a template of Double32_t. This is actually a correct case.
1567 } else {
1568 Error("Branch", "The class requested (%s) for \"%s\" is different from the type of the pointer passed (%s)",
1569 claim->GetName(), branchname, ptrClass->GetName());
1570 }
1571 } else if (actualClass && (claim != actualClass) && !actualClass->InheritsFrom(claim)) {
1572 if (claim->IsLoaded() && actualClass->IsLoaded() && strcmp( claim->GetTypeInfo()->name(), actualClass->GetTypeInfo()->name() ) == 0) {
1573 // The type is the same according to the C++ type_info, we must be in the case of
1574 // a template of Double32_t. This is actually a correct case.
1575 } else {
1576 Error("Branch", "The actual class (%s) of the object provided for the definition of the branch \"%s\" does not inherit from %s",
1577 actualClass->GetName(), branchname, claim->GetName());
1578 }
1579 }
1580 }
1581 if (claim && claim->GetCollectionProxy() && dynamic_cast<TEmulatedCollectionProxy*>(claim->GetCollectionProxy())) {
1583 claim->GetName(), branchname, claim->GetName());
1584 return nullptr;
1585 }
1586 return Branch(branchname, classname, (void*) addobj, bufsize, splitlevel);
1587}
1588
1589////////////////////////////////////////////////////////////////////////////////
1590/// Same as TTree::Branch but automatic detection of the class name.
1591/// \see TTree::Branch
1594{
1595 if (!ptrClass) {
1596 Error("Branch", "The pointer specified for %s is not of a class known to ROOT", branchname);
1597 return nullptr;
1598 }
1599 TClass* actualClass = nullptr;
1600 void** addr = (void**) addobj;
1601 if (addr && *addr) {
1602 actualClass = ptrClass->GetActualClass(*addr);
1603 if (!actualClass) {
1604 Warning("Branch", "The actual TClass corresponding to the object provided for the definition of the branch \"%s\" is missing.\n\tThe object will be truncated down to its %s part",
1605 branchname, ptrClass->GetName());
1607 } else if ((ptrClass != actualClass) && !actualClass->InheritsFrom(ptrClass)) {
1608 Error("Branch", "The actual class (%s) of the object provided for the definition of the branch \"%s\" does not inherit from %s", actualClass->GetName(), branchname, ptrClass->GetName());
1609 return nullptr;
1610 }
1611 } else {
1613 }
1614 if (actualClass && actualClass->GetCollectionProxy() && dynamic_cast<TEmulatedCollectionProxy*>(actualClass->GetCollectionProxy())) {
1616 actualClass->GetName(), branchname, actualClass->GetName());
1617 return nullptr;
1618 }
1619 return Branch(branchname, actualClass->GetName(), (void*) addobj, bufsize, splitlevel);
1620}
1621
1622////////////////////////////////////////////////////////////////////////////////
1623/// Same as TTree::Branch but automatic detection of the class name.
1624/// \see TTree::Branch
1626TBranch* TTree::BranchImpRef(const char* branchname, const char *classname, TClass* ptrClass, void *addobj, Int_t bufsize, Int_t splitlevel)
1627{
1628 TClass* claim = TClass::GetClass(classname);
1629 if (!ptrClass) {
1630 if (claim && claim->GetCollectionProxy() && dynamic_cast<TEmulatedCollectionProxy*>(claim->GetCollectionProxy())) {
1632 claim->GetName(), branchname, claim->GetName());
1633 return nullptr;
1634 } else if (claim == nullptr) {
1635 Error("Branch", "The pointer specified for %s is not of a class known to ROOT and %s is not a known class", branchname, classname);
1636 return nullptr;
1637 }
1638 ptrClass = claim;
1639 }
1640 TClass* actualClass = nullptr;
1641 if (!addobj) {
1642 Error("Branch", "Reference interface requires a valid object (for branch: %s)!", branchname);
1643 return nullptr;
1644 }
1645 actualClass = ptrClass->GetActualClass(addobj);
1646 if (ptrClass && claim) {
1647 if (!(claim->InheritsFrom(ptrClass) || ptrClass->InheritsFrom(claim))) {
1648 // Note we currently do not warn in case of splicing or over-expectation).
1649 if (claim->IsLoaded() && ptrClass->IsLoaded() && strcmp( claim->GetTypeInfo()->name(), ptrClass->GetTypeInfo()->name() ) == 0) {
1650 // The type is the same according to the C++ type_info, we must be in the case of
1651 // a template of Double32_t. This is actually a correct case.
1652 } else {
1653 Error("Branch", "The class requested (%s) for \"%s\" is different from the type of the object passed (%s)",
1654 claim->GetName(), branchname, ptrClass->GetName());
1655 }
1656 } else if (actualClass && (claim != actualClass) && !actualClass->InheritsFrom(claim)) {
1657 if (claim->IsLoaded() && actualClass->IsLoaded() && strcmp( claim->GetTypeInfo()->name(), actualClass->GetTypeInfo()->name() ) == 0) {
1658 // The type is the same according to the C++ type_info, we must be in the case of
1659 // a template of Double32_t. This is actually a correct case.
1660 } else {
1661 Error("Branch", "The actual class (%s) of the object provided for the definition of the branch \"%s\" does not inherit from %s",
1662 actualClass->GetName(), branchname, claim->GetName());
1663 }
1664 }
1665 }
1666 if (!actualClass) {
1667 Warning("Branch", "The actual TClass corresponding to the object provided for the definition of the branch \"%s\" is missing.\n\tThe object will be truncated down to its %s part",
1668 branchname, ptrClass->GetName());
1670 } else if ((ptrClass != actualClass) && !actualClass->InheritsFrom(ptrClass)) {
1671 Error("Branch", "The actual class (%s) of the object provided for the definition of the branch \"%s\" does not inherit from %s", actualClass->GetName(), branchname, ptrClass->GetName());
1672 return nullptr;
1673 }
1674 if (actualClass && actualClass->GetCollectionProxy() && dynamic_cast<TEmulatedCollectionProxy*>(actualClass->GetCollectionProxy())) {
1676 actualClass->GetName(), branchname, actualClass->GetName());
1677 return nullptr;
1678 }
1679 return BronchExec(branchname, actualClass->GetName(), (void*) addobj, false, bufsize, splitlevel);
1680}
1681
1682////////////////////////////////////////////////////////////////////////////////
1683/// Same as TTree::Branch but automatic detection of the class name.
1684/// \see TTree::Branch
1687{
1688 if (!ptrClass) {
1689 if (datatype == kOther_t || datatype == kNoType_t) {
1690 Error("Branch", "The pointer specified for %s is not of a class or type known to ROOT", branchname);
1691 } else {
1693 return Branch(branchname,addobj,varname.Data(),bufsize);
1694 }
1695 return nullptr;
1696 }
1697 TClass* actualClass = nullptr;
1698 if (!addobj) {
1699 Error("Branch", "Reference interface requires a valid object (for branch: %s)!", branchname);
1700 return nullptr;
1701 }
1702 actualClass = ptrClass->GetActualClass(addobj);
1703 if (!actualClass) {
1704 Warning("Branch", "The actual TClass corresponding to the object provided for the definition of the branch \"%s\" is missing.\n\tThe object will be truncated down to its %s part",
1705 branchname, ptrClass->GetName());
1707 } else if ((ptrClass != actualClass) && !actualClass->InheritsFrom(ptrClass)) {
1708 Error("Branch", "The actual class (%s) of the object provided for the definition of the branch \"%s\" does not inherit from %s", actualClass->GetName(), branchname, ptrClass->GetName());
1709 return nullptr;
1710 }
1711 if (actualClass && actualClass->GetCollectionProxy() && dynamic_cast<TEmulatedCollectionProxy*>(actualClass->GetCollectionProxy())) {
1713 actualClass->GetName(), branchname, actualClass->GetName());
1714 return nullptr;
1715 }
1716 return BronchExec(branchname, actualClass->GetName(), (void*) addobj, false, bufsize, splitlevel);
1717}
1718
1719////////////////////////////////////////////////////////////////////////////////
1720// Wrapper to turn Branch call with an std::array into the relevant leaf list
1721// call
1722TBranch *TTree::BranchImpArr(const char *branchname, EDataType datatype, std::size_t N, void *addobj, Int_t bufsize,
1723 Int_t /* splitlevel */)
1724{
1725 if (datatype == kOther_t || datatype == kNoType_t) {
1726 Error("Branch",
1727 "The inner type of the std::array passed specified for %s is not of a class or type known to ROOT",
1728 branchname);
1729 } else {
1731 varname.Form("%s[%d]/%c", branchname, (int)N, DataTypeToChar(datatype));
1732 return Branch(branchname, addobj, varname.Data(), bufsize);
1733 }
1734 return nullptr;
1735}
1736
1737////////////////////////////////////////////////////////////////////////////////
1738/// Deprecated function. Use next function instead.
1740Int_t TTree::Branch(TList* li, Int_t bufsize /* = 32000 */ , Int_t splitlevel /* = 99 */)
1741{
1742 return Branch((TCollection*) li, bufsize, splitlevel);
1743}
1744
1745////////////////////////////////////////////////////////////////////////////////
1746/// Create one branch for each element in the collection.
1747///
1748/// Each entry in the collection becomes a top level branch if the
1749/// corresponding class is not a collection. If it is a collection, the entry
1750/// in the collection becomes in turn top level branches, etc.
1751/// The splitlevel is decreased by 1 every time a new collection is found.
1752/// For example if list is a TObjArray*
1753/// - if splitlevel = 1, one top level branch is created for each element
1754/// of the TObjArray.
1755/// - if splitlevel = 2, one top level branch is created for each array element.
1756/// if, in turn, one of the array elements is a TCollection, one top level
1757/// branch will be created for each element of this collection.
1758///
1759/// In case a collection element is a TClonesArray, the special Tree constructor
1760/// for TClonesArray is called.
1761/// The collection itself cannot be a TClonesArray.
1762///
1763/// The function returns the total number of branches created.
1764///
1765/// If name is given, all branch names will be prefixed with name_.
1766///
1767/// IMPORTANT NOTE1: This function should not be called with splitlevel < 1.
1768///
1769/// IMPORTANT NOTE2: The branches created by this function will have names
1770/// corresponding to the collection or object names. It is important
1771/// to give names to collections to avoid misleading branch names or
1772/// identical branch names. By default collections have a name equal to
1773/// the corresponding class name, e.g. the default name for a TList is "TList".
1774///
1775/// And in general, in case two or more master branches contain subbranches
1776/// with identical names, one must add a "." (dot) character at the end
1777/// of the master branch name. This will force the name of the subbranches
1778/// to be of the form `master.subbranch` instead of simply `subbranch`.
1779/// This situation happens when the top level object
1780/// has two or more members referencing the same class.
1781/// Without the dot, the prefix will not be there and that might cause ambiguities.
1782/// For example, if a Tree has two branches B1 and B2 corresponding
1783/// to objects of the same class MyClass, one can do:
1784/// ~~~ {.cpp}
1785/// tree.Branch("B1.","MyClass",&b1,8000,1);
1786/// tree.Branch("B2.","MyClass",&b2,8000,1);
1787/// ~~~
1788/// if MyClass has 3 members a,b,c, the two instructions above will generate
1789/// subbranches called B1.a, B1.b ,B1.c, B2.a, B2.b, B2.c
1790/// In other words, the trailing dot of the branch name is semantically relevant
1791/// and recommended.
1792///
1793/// Example:
1794/// ~~~ {.cpp}
1795/// {
1796/// TTree T("T","test list");
1797/// TList *list = new TList();
1798///
1799/// TObjArray *a1 = new TObjArray();
1800/// a1->SetName("a1");
1801/// list->Add(a1);
1802/// TH1F *ha1a = new TH1F("ha1a","ha1",100,0,1);
1803/// TH1F *ha1b = new TH1F("ha1b","ha1",100,0,1);
1804/// a1->Add(ha1a);
1805/// a1->Add(ha1b);
1806/// TObjArray *b1 = new TObjArray();
1807/// b1->SetName("b1");
1808/// list->Add(b1);
1809/// TH1F *hb1a = new TH1F("hb1a","hb1",100,0,1);
1810/// TH1F *hb1b = new TH1F("hb1b","hb1",100,0,1);
1811/// b1->Add(hb1a);
1812/// b1->Add(hb1b);
1813///
1814/// TObjArray *a2 = new TObjArray();
1815/// a2->SetName("a2");
1816/// list->Add(a2);
1817/// TH1S *ha2a = new TH1S("ha2a","ha2",100,0,1);
1818/// TH1S *ha2b = new TH1S("ha2b","ha2",100,0,1);
1819/// a2->Add(ha2a);
1820/// a2->Add(ha2b);
1821///
1822/// T.Branch(list,16000,2);
1823/// T.Print();
1824/// }
1825/// ~~~
1827Int_t TTree::Branch(TCollection* li, Int_t bufsize /* = 32000 */, Int_t splitlevel /* = 99 */, const char* name /* = "" */)
1828{
1829
1830 if (!li) {
1831 return 0;
1832 }
1833 TObject* obj = nullptr;
1834 Int_t nbranches = GetListOfBranches()->GetEntries();
1835 if (li->InheritsFrom(TClonesArray::Class())) {
1836 Error("Branch", "Cannot call this constructor for a TClonesArray");
1837 return 0;
1838 }
1839 Int_t nch = strlen(name);
1841 TIter next(li);
1842 while ((obj = next())) {
1844 TCollection* col = (TCollection*) obj;
1845 if (nch) {
1846 branchname.Form("%s_%s_", name, col->GetName());
1847 } else {
1848 branchname.Form("%s_", col->GetName());
1849 }
1850 Branch(col, bufsize, splitlevel - 1, branchname);
1851 } else {
1852 if (nch && (name[nch-1] == '_')) {
1853 branchname.Form("%s%s", name, obj->GetName());
1854 } else {
1855 if (nch) {
1856 branchname.Form("%s_%s", name, obj->GetName());
1857 } else {
1858 branchname.Form("%s", obj->GetName());
1859 }
1860 }
1861 if (splitlevel > 99) {
1862 branchname += ".";
1863 }
1864 Bronch(branchname, obj->ClassName(), li->GetObjectRef(obj), bufsize, splitlevel - 1);
1865 }
1866 }
1867 return GetListOfBranches()->GetEntries() - nbranches;
1868}
1869
1870////////////////////////////////////////////////////////////////////////////////
1871/// Create one branch for each element in the folder.
1872/// Returns the total number of branches created.
1874Int_t TTree::Branch(const char* foldername, Int_t bufsize /* = 32000 */, Int_t splitlevel /* = 99 */)
1875{
1876 TObject* ob = gROOT->FindObjectAny(foldername);
1877 if (!ob) {
1878 return 0;
1879 }
1880 if (ob->IsA() != TFolder::Class()) {
1881 return 0;
1882 }
1883 Int_t nbranches = GetListOfBranches()->GetEntries();
1884 TFolder* folder = (TFolder*) ob;
1885 TIter next(folder->GetListOfFolders());
1886 TObject* obj = nullptr;
1887 char* curname = new char[1000];
1888 char occur[20];
1889 while ((obj = next())) {
1890 snprintf(curname,1000, "%s/%s", foldername, obj->GetName());
1891 if (obj->IsA() == TFolder::Class()) {
1893 } else {
1894 void* add = (void*) folder->GetListOfFolders()->GetObjectRef(obj);
1895 for (Int_t i = 0; i < 1000; ++i) {
1896 if (curname[i] == 0) {
1897 break;
1898 }
1899 if (curname[i] == '/') {
1900 curname[i] = '.';
1901 }
1902 }
1903 Int_t noccur = folder->Occurence(obj);
1904 if (noccur > 0) {
1905 snprintf(occur,20, "_%d", noccur);
1906 strlcat(curname, occur,1000);
1907 }
1909 if (br) br->SetBranchFolder();
1910 }
1911 }
1912 delete[] curname;
1913 return GetListOfBranches()->GetEntries() - nbranches;
1914}
1915
1916////////////////////////////////////////////////////////////////////////////////
1917/// Create a new TTree Branch.
1918///
1919/// This Branch constructor is provided to support non-objects in
1920/// a Tree. The variables described in leaflist may be simple
1921/// variables or structures. // See the two following
1922/// constructors for writing objects in a Tree.
1923///
1924/// By default the branch buffers are stored in the same file as the Tree.
1925/// use TBranch::SetFile to specify a different file
1926///
1927/// * address is the address of the first item of a structure.
1928/// * leaflist is the concatenation of all the variable names and types
1929/// separated by a colon character :
1930/// The variable name and the variable type are separated by a slash (/).
1931/// The variable type may be 0,1 or 2 characters. If no type is given,
1932/// the type of the variable is assumed to be the same as the previous
1933/// variable. If the first variable does not have a type, it is assumed
1934/// of type F by default. The list of currently supported types is given below:
1935/// - `C` : a character string terminated by the 0 character
1936/// - `B` : an 8 bit signed integer (`Char_t`); Treated as a character when in an array.
1937/// - `b` : an 8 bit unsigned integer (`UChar_t`)
1938/// - `S` : a 16 bit signed integer (`Short_t`)
1939/// - `s` : a 16 bit unsigned integer (`UShort_t`)
1940/// - `I` : a 32 bit signed integer (`Int_t`)
1941/// - `i` : a 32 bit unsigned integer (`UInt_t`)
1942/// - `F` : a 32 bit floating point (`Float_t`)
1943/// - `f` : a 24 bit floating point with truncated mantissa (`Float16_t`)
1944/// - `D` : a 64 bit floating point (`Double_t`)
1945/// - `d` : a 24 bit truncated floating point (`Double32_t`)
1946/// - `L` : a 64 bit signed integer (`Long64_t`)
1947/// - `l` : a 64 bit unsigned integer (`ULong64_t`)
1948/// - `G` : a long signed integer, stored as 64 bit (`Long_t`)
1949/// - `g` : a long unsigned integer, stored as 64 bit (`ULong_t`)
1950/// - `O` : [the letter `o`, not a zero] a boolean (`bool`)
1951///
1952/// Arrays of values are supported with the following syntax:
1953/// - If leaf name has the form var[nelem], where nelem is alphanumeric, then
1954/// if nelem is a leaf name, it is used as the variable size of the array,
1955/// otherwise return 0.
1956/// The leaf referred to by nelem **MUST** be an int (/I),
1957/// - If leaf name has the form var[nelem], where nelem is a non-negative integer, then
1958/// it is used as the fixed size of the array.
1959/// - If leaf name has the form of a multi-dimensional array (e.g. var[nelem][nelem2])
1960/// where nelem and nelem2 are non-negative integer) then
1961/// it is used as a 2 dimensional array of fixed size.
1962/// - In case of the truncated floating point types (Float16_t and Double32_t) you can
1963/// furthermore specify the range in the style [xmin,xmax] or [xmin,xmax,nbits] after
1964/// the type character. See `TStreamerElement::GetRange()` for further information.
1965///
1966/// Any of other form is not supported.
1967///
1968/// Note that the TTree will assume that all the item are contiguous in memory.
1969/// On some platform, this is not always true of the member of a struct or a class,
1970/// due to padding and alignment. Sorting your data member in order of decreasing
1971/// sizeof usually leads to their being contiguous in memory.
1972///
1973/// * bufsize is the buffer size in bytes for this branch
1974/// The default value is 32000 bytes and should be ok for most cases.
1975/// You can specify a larger value (e.g. 256000) if your Tree is not split
1976/// and each entry is large (Megabytes)
1977/// A small value for bufsize is optimum if you intend to access
1978/// the entries in the Tree randomly and your Tree is in split mode.
1980TBranch* TTree::Branch(const char* name, void* address, const char* leaflist, Int_t bufsize /* = 32000 */)
1981{
1982 TBranch* branch = new TBranch(this, name, address, leaflist, bufsize);
1983 if (branch->IsZombie()) {
1984 delete branch;
1985 branch = nullptr;
1986 return nullptr;
1987 }
1989 return branch;
1990}
1991
1992////////////////////////////////////////////////////////////////////////////////
1993/// Create a new branch with the object of class classname at address addobj.
1994///
1995/// WARNING:
1996///
1997/// Starting with Root version 3.01, the Branch function uses the new style
1998/// branches (TBranchElement). To get the old behaviour, you can:
1999/// - call BranchOld or
2000/// - call TTree::SetBranchStyle(0)
2001///
2002/// Note that with the new style, classname does not need to derive from TObject.
2003/// It must derived from TObject if the branch style has been set to 0 (old)
2004///
2005/// Note: See the comments in TBranchElement::SetAddress() for a more
2006/// detailed discussion of the meaning of the addobj parameter in
2007/// the case of new-style branches.
2008///
2009/// Use splitlevel < 0 instead of splitlevel=0 when the class
2010/// has a custom Streamer
2011///
2012/// Note: if the split level is set to the default (99), TTree::Branch will
2013/// not issue a warning if the class can not be split.
2015TBranch* TTree::Branch(const char* name, const char* classname, void* addobj, Int_t bufsize /* = 32000 */, Int_t splitlevel /* = 99 */)
2016{
2017 if (fgBranchStyle == 1) {
2018 return Bronch(name, classname, addobj, bufsize, splitlevel);
2019 } else {
2020 if (splitlevel < 0) {
2021 splitlevel = 0;
2022 }
2023 return BranchOld(name, classname, addobj, bufsize, splitlevel);
2024 }
2025}
2026
2027////////////////////////////////////////////////////////////////////////////////
2028/// Create a new TTree BranchObject.
2029///
2030/// Build a TBranchObject for an object of class classname.
2031/// addobj is the address of a pointer to an object of class classname.
2032/// IMPORTANT: classname must derive from TObject.
2033/// The class dictionary must be available (ClassDef in class header).
2034///
2035/// This option requires access to the library where the corresponding class
2036/// is defined. Accessing one single data member in the object implies
2037/// reading the full object.
2038/// See the next Branch constructor for a more efficient storage
2039/// in case the entry consists of arrays of identical objects.
2040///
2041/// By default the branch buffers are stored in the same file as the Tree.
2042/// use TBranch::SetFile to specify a different file
2043///
2044/// IMPORTANT NOTE about branch names:
2045///
2046/// And in general, in case two or more master branches contain subbranches
2047/// with identical names, one must add a "." (dot) character at the end
2048/// of the master branch name. This will force the name of the subbranches
2049/// to be of the form `master.subbranch` instead of simply `subbranch`.
2050/// This situation happens when the top level object
2051/// has two or more members referencing the same class.
2052/// For example, if a Tree has two branches B1 and B2 corresponding
2053/// to objects of the same class MyClass, one can do:
2054/// ~~~ {.cpp}
2055/// tree.Branch("B1.","MyClass",&b1,8000,1);
2056/// tree.Branch("B2.","MyClass",&b2,8000,1);
2057/// ~~~
2058/// if MyClass has 3 members a,b,c, the two instructions above will generate
2059/// subbranches called B1.a, B1.b ,B1.c, B2.a, B2.b, B2.c
2060///
2061/// bufsize is the buffer size in bytes for this branch
2062/// The default value is 32000 bytes and should be ok for most cases.
2063/// You can specify a larger value (e.g. 256000) if your Tree is not split
2064/// and each entry is large (Megabytes)
2065/// A small value for bufsize is optimum if you intend to access
2066/// the entries in the Tree randomly and your Tree is in split mode.
2068TBranch* TTree::BranchOld(const char* name, const char* classname, void* addobj, Int_t bufsize /* = 32000 */, Int_t splitlevel /* = 1 */)
2069{
2070 TClass* cl = TClass::GetClass(classname);
2071 if (!cl) {
2072 Error("BranchOld", "Cannot find class: '%s'", classname);
2073 return nullptr;
2074 }
2075 if (!cl->IsTObject()) {
2076 if (fgBranchStyle == 0) {
2077 Fatal("BranchOld", "The requested class ('%s') does not inherit from TObject.\n"
2078 "\tfgBranchStyle is set to zero requesting by default to use BranchOld.\n"
2079 "\tIf this is intentional use Bronch instead of Branch or BranchOld.", classname);
2080 } else {
2081 Fatal("BranchOld", "The requested class ('%s') does not inherit from TObject.\n"
2082 "\tYou can not use BranchOld to store objects of this type.",classname);
2083 }
2084 return nullptr;
2085 }
2086 TBranch* branch = new TBranchObject(this, name, classname, addobj, bufsize, splitlevel);
2088 if (!splitlevel) {
2089 return branch;
2090 }
2091 // We are going to fully split the class now.
2092 TObjArray* blist = branch->GetListOfBranches();
2093 const char* rdname = nullptr;
2094 const char* dname = nullptr;
2096 char** apointer = (char**) addobj;
2097 TObject* obj = (TObject*) *apointer;
2098 bool delobj = false;
2099 if (!obj) {
2100 obj = (TObject*) cl->New();
2101 delobj = true;
2102 }
2103 // Build the StreamerInfo if first time for the class.
2104 BuildStreamerInfo(cl, obj);
2105 // Loop on all public data members of the class and its base classes.
2107 Int_t isDot = 0;
2108 if (name[lenName-1] == '.') {
2109 isDot = 1;
2110 }
2111 TBranch* branch1 = nullptr;
2112 TRealData* rd = nullptr;
2113 TRealData* rdi = nullptr;
2115 TIter next(cl->GetListOfRealData());
2116 // Note: This loop results in a full split because the
2117 // real data list includes all data members of
2118 // data members.
2119 while ((rd = (TRealData*) next())) {
2120 if (rd->TestBit(TRealData::kTransient)) continue;
2121
2122 // Loop over all data members creating branches for each one.
2123 TDataMember* dm = rd->GetDataMember();
2124 if (!dm->IsPersistent()) {
2125 // Do not process members with an "!" as the first character in the comment field.
2126 continue;
2127 }
2128 if (rd->IsObject()) {
2129 // We skip data members of class type.
2130 // But we do build their real data, their
2131 // streamer info, and write their streamer
2132 // info to the current directory's file.
2133 // Oh yes, and we also do this for all of
2134 // their base classes.
2136 if (clm) {
2137 BuildStreamerInfo(clm, (char*) obj + rd->GetThisOffset());
2138 }
2139 continue;
2140 }
2141 rdname = rd->GetName();
2142 dname = dm->GetName();
2143 if (cl->CanIgnoreTObjectStreamer()) {
2144 // Skip the TObject base class data members.
2145 // FIXME: This prevents a user from ever
2146 // using these names themself!
2147 if (!strcmp(dname, "fBits")) {
2148 continue;
2149 }
2150 if (!strcmp(dname, "fUniqueID")) {
2151 continue;
2152 }
2153 }
2154 TDataType* dtype = dm->GetDataType();
2155 Int_t code = 0;
2156 if (dtype) {
2157 code = dm->GetDataType()->GetType();
2158 }
2159 // Encode branch name. Use real data member name
2161 if (isDot) {
2162 if (dm->IsaPointer()) {
2163 // FIXME: This is wrong! The asterisk is not usually in the front!
2164 branchname.Form("%s%s", name, &rdname[1]);
2165 } else {
2166 branchname.Form("%s%s", name, &rdname[0]);
2167 }
2168 }
2169 // FIXME: Change this to a string stream.
2171 Int_t offset = rd->GetThisOffset();
2172 char* pointer = ((char*) obj) + offset;
2173 if (dm->IsaPointer()) {
2174 // We have a pointer to an object or a pointer to an array of basic types.
2175 TClass* clobj = nullptr;
2176 if (!dm->IsBasic()) {
2178 }
2179 if (clobj && clobj->InheritsFrom(TClonesArray::Class())) {
2180 // We have a pointer to a clones array.
2181 char* cpointer = (char*) pointer;
2182 char** ppointer = (char**) cpointer;
2184 if (splitlevel != 2) {
2185 if (isDot) {
2187 } else {
2188 // FIXME: This is wrong! The asterisk is not usually in the front!
2189 branch1 = new TBranchClones(branch,&branchname.Data()[1], pointer, bufsize);
2190 }
2191 blist->Add(branch1);
2192 } else {
2193 if (isDot) {
2194 branch1 = new TBranchObject(branch, branchname, li->ClassName(), pointer, bufsize);
2195 } else {
2196 // FIXME: This is wrong! The asterisk is not usually in the front!
2197 branch1 = new TBranchObject(branch, &branchname.Data()[1], li->ClassName(), pointer, bufsize);
2198 }
2199 blist->Add(branch1);
2200 }
2201 } else if (clobj) {
2202 // We have a pointer to an object.
2203 //
2204 // It must be a TObject object.
2205 if (!clobj->IsTObject()) {
2206 continue;
2207 }
2208 branch1 = new TBranchObject(branch, dname, clobj->GetName(), pointer, bufsize, 0);
2209 if (isDot) {
2210 branch1->SetName(branchname);
2211 } else {
2212 // FIXME: This is wrong! The asterisk is not usually in the front!
2213 // Do not use the first character (*).
2214 branch1->SetName(&branchname.Data()[1]);
2215 }
2216 blist->Add(branch1);
2217 } else {
2218 // We have a pointer to an array of basic types.
2219 //
2220 // Check the comments in the text of the code for an index specification.
2221 const char* index = dm->GetArrayIndex();
2222 if (index[0]) {
2223 // We are a pointer to a varying length array of basic types.
2224 //check that index is a valid data member name
2225 //if member is part of an object (e.g. fA and index=fN)
2226 //index must be changed from fN to fA.fN
2227 TString aindex (rd->GetName());
2228 Ssiz_t rdot = aindex.Last('.');
2229 if (rdot>=0) {
2230 aindex.Remove(rdot+1);
2231 aindex.Append(index);
2232 }
2233 nexti.Reset();
2234 while ((rdi = (TRealData*) nexti())) {
2235 if (rdi->TestBit(TRealData::kTransient)) continue;
2236
2237 if (!strcmp(rdi->GetName(), index)) {
2238 break;
2239 }
2240 if (!strcmp(rdi->GetName(), aindex)) {
2241 index = rdi->GetName();
2242 break;
2243 }
2244 }
2245
2246 char vcode = DataTypeToChar((EDataType)code);
2247 // Note that we differentiate between strings and
2248 // char array by the fact that there is NO specified
2249 // size for a string (see next if (code == 1)
2250
2251 if (vcode) {
2252 leaflist.Form("%s[%s]/%c", &rdname[0], index, vcode);
2253 } else {
2254 Error("BranchOld", "Cannot create branch for rdname: %s code: %d", branchname.Data(), code);
2255 leaflist = "";
2256 }
2257 } else {
2258 // We are possibly a character string.
2259 if (code == 1) {
2260 // We are a character string.
2261 leaflist.Form("%s/%s", dname, "C");
2262 } else {
2263 // Invalid array specification.
2264 // FIXME: We need an error message here.
2265 continue;
2266 }
2267 }
2268 // There are '*' in both the branchname and leaflist, remove them.
2269 TString bname( branchname );
2270 bname.ReplaceAll("*","");
2271 leaflist.ReplaceAll("*","");
2272 // Add the branch to the tree and indicate that the address
2273 // is that of a pointer to be dereferenced before using.
2274 branch1 = new TBranch(branch, bname, *((void**) pointer), leaflist, bufsize);
2275 TLeaf* leaf = (TLeaf*) branch1->GetListOfLeaves()->At(0);
2277 leaf->SetAddress((void**) pointer);
2278 blist->Add(branch1);
2279 }
2280 } else if (dm->IsBasic()) {
2281 // We have a basic type.
2282
2283 char vcode = DataTypeToChar((EDataType)code);
2284 if (vcode) {
2285 leaflist.Form("%s/%c", rdname, vcode);
2286 } else {
2287 Error("BranchOld", "Cannot create branch for rdname: %s code: %d", branchname.Data(), code);
2288 leaflist = "";
2289 }
2290 branch1 = new TBranch(branch, branchname, pointer, leaflist, bufsize);
2291 branch1->SetTitle(rdname);
2292 blist->Add(branch1);
2293 } else {
2294 // We have a class type.
2295 // Note: This cannot happen due to the rd->IsObject() test above.
2296 // FIXME: Put an error message here just in case.
2297 }
2298 if (branch1) {
2299 branch1->SetOffset(offset);
2300 } else {
2301 Warning("BranchOld", "Cannot process member: '%s'", rdname);
2302 }
2303 }
2304 if (delobj) {
2305 delete obj;
2306 obj = nullptr;
2307 }
2308 return branch;
2309}
2310
2311////////////////////////////////////////////////////////////////////////////////
2312/// Build the optional branch supporting the TRefTable.
2313/// This branch will keep all the information to find the branches
2314/// containing referenced objects.
2315///
2316/// At each Tree::Fill, the branch numbers containing the
2317/// referenced objects are saved to the TBranchRef basket.
2318/// When the Tree header is saved (via TTree::Write), the branch
2319/// is saved keeping the information with the pointers to the branches
2320/// having referenced objects.
2323{
2324 if (!fBranchRef) {
2325 fBranchRef = new TBranchRef(this);
2326 }
2327 return fBranchRef;
2328}
2329
2330////////////////////////////////////////////////////////////////////////////////
2331/// Create a new TTree BranchElement.
2332///
2333/// ## WARNING about this new function
2334///
2335/// This function is designed to replace the internal
2336/// implementation of the old TTree::Branch (whose implementation
2337/// has been moved to BranchOld).
2338///
2339/// NOTE: The 'Bronch' method supports only one possible calls
2340/// signature (where the object type has to be specified
2341/// explicitly and the address must be the address of a pointer).
2342/// For more flexibility use 'Branch'. Use Bronch only in (rare)
2343/// cases (likely to be legacy cases) where both the new and old
2344/// implementation of Branch needs to be used at the same time.
2345///
2346/// This function is far more powerful than the old Branch
2347/// function. It supports the full C++, including STL and has
2348/// the same behaviour in split or non-split mode. classname does
2349/// not have to derive from TObject. The function is based on
2350/// the new TStreamerInfo.
2351///
2352/// Build a TBranchElement for an object of class classname.
2353///
2354/// addr is the address of a pointer to an object of class
2355/// classname. The class dictionary must be available (ClassDef
2356/// in class header).
2357///
2358/// Note: See the comments in TBranchElement::SetAddress() for a more
2359/// detailed discussion of the meaning of the addr parameter.
2360///
2361/// This option requires access to the library where the
2362/// corresponding class is defined. Accessing one single data
2363/// member in the object implies reading the full object.
2364///
2365/// By default the branch buffers are stored in the same file as the Tree.
2366/// use TBranch::SetFile to specify a different file
2367///
2368/// IMPORTANT NOTE about branch names:
2369///
2370/// And in general, in case two or more master branches contain subbranches
2371/// with identical names, one must add a "." (dot) character at the end
2372/// of the master branch name. This will force the name of the subbranches
2373/// to be of the form `master.subbranch` instead of simply `subbranch`.
2374/// This situation happens when the top level object
2375/// has two or more members referencing the same class.
2376/// For example, if a Tree has two branches B1 and B2 corresponding
2377/// to objects of the same class MyClass, one can do:
2378/// ~~~ {.cpp}
2379/// tree.Branch("B1.","MyClass",&b1,8000,1);
2380/// tree.Branch("B2.","MyClass",&b2,8000,1);
2381/// ~~~
2382/// if MyClass has 3 members a,b,c, the two instructions above will generate
2383/// subbranches called B1.a, B1.b ,B1.c, B2.a, B2.b, B2.c
2384///
2385/// bufsize is the buffer size in bytes for this branch
2386/// The default value is 32000 bytes and should be ok for most cases.
2387/// You can specify a larger value (e.g. 256000) if your Tree is not split
2388/// and each entry is large (Megabytes)
2389/// A small value for bufsize is optimum if you intend to access
2390/// the entries in the Tree randomly and your Tree is in split mode.
2391///
2392/// Use splitlevel < 0 instead of splitlevel=0 when the class
2393/// has a custom Streamer
2394///
2395/// Note: if the split level is set to the default (99), TTree::Branch will
2396/// not issue a warning if the class can not be split.
2398TBranch* TTree::Bronch(const char* name, const char* classname, void* addr, Int_t bufsize /* = 32000 */, Int_t splitlevel /* = 99 */)
2399{
2400 return BronchExec(name, classname, addr, true, bufsize, splitlevel);
2401}
2402
2403////////////////////////////////////////////////////////////////////////////////
2404/// Helper function implementing TTree::Bronch and TTree::Branch(const char *name, T &obj);
2406TBranch* TTree::BronchExec(const char* name, const char* classname, void* addr, bool isptrptr, Int_t bufsize /* = 32000 */, Int_t splitlevel /* = 99 */)
2407{
2408 TClass* cl = TClass::GetClass(classname);
2409 if (!cl) {
2410 Error("Bronch", "Cannot find class:%s", classname);
2411 return nullptr;
2412 }
2413
2414 //if splitlevel <= 0 and class has a custom Streamer, we must create
2415 //a TBranchObject. We cannot assume that TClass::ReadBuffer is consistent
2416 //with the custom Streamer. The penalty is that one cannot process
2417 //this Tree without the class library containing the class.
2418
2419 char* objptr = nullptr;
2420 if (!isptrptr) {
2421 objptr = (char*)addr;
2422 } else if (addr) {
2423 objptr = *((char**) addr);
2424 }
2425
2426 if (cl == TClonesArray::Class()) {
2428 if (!clones) {
2429 Error("Bronch", "Pointer to TClonesArray is null");
2430 return nullptr;
2431 }
2432 if (!clones->GetClass()) {
2433 Error("Bronch", "TClonesArray with no class defined in branch: %s", name);
2434 return nullptr;
2435 }
2436 if (!clones->GetClass()->HasDataMemberInfo()) {
2437 Error("Bronch", "TClonesArray with no dictionary defined in branch: %s", name);
2438 return nullptr;
2439 }
2440 bool hasCustomStreamer = clones->GetClass()->HasCustomStreamerMember();
2441 if (splitlevel > 0) {
2443 Warning("Bronch", "Using split mode on a class: %s with a custom Streamer", clones->GetClass()->GetName());
2444 } else {
2445 if (hasCustomStreamer) clones->BypassStreamer(false);
2446 TBranchObject *branch = new TBranchObject(this,name,classname,addr,bufsize,0,/*compress=*/ -1,isptrptr);
2448 return branch;
2449 }
2450 }
2451
2452 if (cl->GetCollectionProxy()) {
2454 //if (!collProxy) {
2455 // Error("Bronch", "%s is missing its CollectionProxy (for branch %s)", classname, name);
2456 //}
2457 TClass* inklass = collProxy->GetValueClass();
2458 if (!inklass && (collProxy->GetType() == 0)) {
2459 Error("Bronch", "%s with no class defined in branch: %s", classname, name);
2460 return nullptr;
2461 }
2462 if ((splitlevel > 0) && inklass && (inklass->GetCollectionProxy() == nullptr)) {
2464 if ((stl != ROOT::kSTLmap) && (stl != ROOT::kSTLmultimap)) {
2465 if (!inklass->HasDataMemberInfo()) {
2466 Error("Bronch", "Container with no dictionary defined in branch: %s", name);
2467 return nullptr;
2468 }
2469 if (inklass->HasCustomStreamerMember()) {
2470 Warning("Bronch", "Using split mode on a class: %s with a custom Streamer", inklass->GetName());
2471 }
2472 }
2473 }
2474 //-------------------------------------------------------------------------
2475 // If the splitting switch is enabled, the split level is big enough and
2476 // the collection contains pointers we can split it
2477 //////////////////////////////////////////////////////////////////////////
2478
2479 TBranch *branch;
2480 if( splitlevel > kSplitCollectionOfPointers && collProxy->HasPointers() )
2482 else
2485 if (isptrptr) {
2486 branch->SetAddress(addr);
2487 } else {
2488 branch->SetObject(addr);
2489 }
2490 return branch;
2491 }
2492
2493 bool hasCustomStreamer = false;
2494 if (!cl->HasDataMemberInfo() && !cl->GetCollectionProxy()) {
2495 Error("Bronch", "Cannot find dictionary for class: %s", classname);
2496 return nullptr;
2497 }
2498
2499 if (!cl->GetCollectionProxy() && cl->HasCustomStreamerMember()) {
2500 // Not an STL container and the linkdef file had a "-" after the class name.
2501 hasCustomStreamer = true;
2502 }
2503
2504 if (splitlevel < 0 || ((splitlevel == 0) && hasCustomStreamer && cl->IsTObject())) {
2507 return branch;
2508 }
2509
2510 if (cl == TClonesArray::Class()) {
2511 // Special case of TClonesArray.
2512 // No dummy object is created.
2513 // The streamer info is not rebuilt unoptimized.
2514 // No dummy top-level branch is created.
2515 // No splitting is attempted.
2518 if (isptrptr) {
2519 branch->SetAddress(addr);
2520 } else {
2521 branch->SetObject(addr);
2522 }
2523 return branch;
2524 }
2525
2526 //
2527 // If we are not given an object to use as an i/o buffer
2528 // then create a temporary one which we will delete just
2529 // before returning.
2530 //
2531
2532 bool delobj = false;
2533
2534 if (!objptr) {
2535 objptr = (char*) cl->New();
2536 delobj = true;
2537 }
2538
2539 //
2540 // Avoid splitting unsplittable classes.
2541 //
2542
2543 if ((splitlevel > 0) && !cl->CanSplit()) {
2544 if (splitlevel != 99) {
2545 Warning("Bronch", "%s cannot be split, resetting splitlevel to 0", cl->GetName());
2546 }
2547 splitlevel = 0;
2548 }
2549
2550 //
2551 // Make sure the streamer info is built and fetch it.
2552 //
2553 // If we are splitting, then make sure the streamer info
2554 // is built unoptimized (data members are not combined).
2555 //
2556
2558 if (!sinfo) {
2559 Error("Bronch", "Cannot build the StreamerInfo for class: %s", cl->GetName());
2560 return nullptr;
2561 }
2562
2563 //
2564 // Create a dummy top level branch object.
2565 //
2566
2567 Int_t id = -1;
2568 if (splitlevel > 0) {
2569 id = -2;
2570 }
2573
2574 //
2575 // Do splitting, if requested.
2576 //
2577
2579 branch->Unroll(name, cl, sinfo, objptr, bufsize, splitlevel);
2580 }
2581
2582 //
2583 // Setup our offsets into the user's i/o buffer.
2584 //
2585
2586 if (isptrptr) {
2587 branch->SetAddress(addr);
2588 } else {
2589 branch->SetObject(addr);
2590 }
2591
2592 if (delobj) {
2593 cl->Destructor(objptr);
2594 objptr = nullptr;
2595 }
2596
2597 return branch;
2598}
2599
2600////////////////////////////////////////////////////////////////////////////////
2601/// Browse content of the TTree.
2604{
2606 if (fUserInfo) {
2607 if (strcmp("TList",fUserInfo->GetName())==0) {
2608 fUserInfo->SetName("UserInfo");
2609 b->Add(fUserInfo);
2610 fUserInfo->SetName("TList");
2611 } else {
2612 b->Add(fUserInfo);
2613 }
2614 }
2615}
2616
2617////////////////////////////////////////////////////////////////////////////////
2618/// Build a Tree Index (default is TTreeIndex).
2619/// See a description of the parameters and functionality in
2620/// TTreeIndex::TTreeIndex().
2621///
2622/// The return value is the number of entries in the Index (< 0 indicates failure).
2623///
2624/// A TTreeIndex object pointed by fTreeIndex is created.
2625/// This object will be automatically deleted by the TTree destructor.
2626/// If an index is already existing, this is replaced by the new one without being
2627/// deleted. This behaviour prevents the deletion of a previously external index
2628/// assigned to the TTree via the TTree::SetTreeIndex() method.
2629/// \see TTree::SetTreeIndex()
2631Int_t TTree::BuildIndex(const char* majorname, const char* minorname /* = "0" */)
2632{
2634 if (fTreeIndex->IsZombie()) {
2635 delete fTreeIndex;
2636 fTreeIndex = nullptr;
2637 return 0;
2638 }
2639 return fTreeIndex->GetN();
2640}
2641
2642////////////////////////////////////////////////////////////////////////////////
2643/// Build StreamerInfo for class cl.
2644/// pointer is an optional argument that may contain a pointer to an object of cl.
2646TStreamerInfo* TTree::BuildStreamerInfo(TClass* cl, void* pointer /* = 0 */, bool canOptimize /* = true */ )
2647{
2648 if (!cl) {
2649 return nullptr;
2650 }
2651 cl->BuildRealData(pointer);
2653
2654 // Create StreamerInfo for all base classes.
2655 TBaseClass* base = nullptr;
2656 TIter nextb(cl->GetListOfBases());
2657 while((base = (TBaseClass*) nextb())) {
2658 if (base->IsSTLContainer()) {
2659 continue;
2660 }
2661 TClass* clm = TClass::GetClass(base->GetName());
2663 }
2664 if (sinfo && fDirectory) {
2665 sinfo->ForceWriteInfo(fDirectory->GetFile());
2666 }
2667 return sinfo;
2668}
2669
2670////////////////////////////////////////////////////////////////////////////////
2671/// Enable the TTreeCache unless explicitly disabled for this TTree by
2672/// a prior call to `SetCacheSize(0)`.
2673/// If the environment variable `ROOT_TTREECACHE_SIZE` or the rootrc config
2674/// `TTreeCache.Size` has been set to zero, this call will over-ride them with
2675/// a value of 1.0 (i.e. use a cache size to hold 1 cluster)
2676///
2677/// Return true if there is a cache attached to the `TTree` (either pre-exisiting
2678/// or created as part of this call)
2679bool TTree::EnableCache()
2680{
2681 TFile* file = GetCurrentFile();
2682 if (!file)
2683 return false;
2684 // Check for an existing cache
2685 TTreeCache* pf = GetReadCache(file);
2686 if (pf)
2687 return true;
2688 if (fCacheUserSet && fCacheSize == 0)
2689 return false;
2690 return (0 == SetCacheSizeAux(true, -1));
2691}
2692
2693////////////////////////////////////////////////////////////////////////////////
2694/// Called by TTree::Fill() when file has reached its maximum fgMaxTreeSize.
2695/// Create a new file. If the original file is named "myfile.root",
2696/// subsequent files are named "myfile_1.root", "myfile_2.root", etc.
2697///
2698/// Returns a pointer to the new file.
2699///
2700/// Currently, the automatic change of file is restricted
2701/// to the case where the tree is in the top level directory.
2702/// The file should not contain sub-directories.
2703///
2704/// Before switching to a new file, the tree header is written
2705/// to the current file, then the current file is closed.
2706///
2707/// To process the multiple files created by ChangeFile, one must use
2708/// a TChain.
2709///
2710/// The new file name has a suffix "_N" where N is equal to fFileNumber+1.
2711/// By default a Root session starts with fFileNumber=0. One can set
2712/// fFileNumber to a different value via TTree::SetFileNumber.
2713/// In case a file named "_N" already exists, the function will try
2714/// a file named "__N", then "___N", etc.
2715///
2716/// fgMaxTreeSize can be set via the static function TTree::SetMaxTreeSize.
2717/// The default value of fgMaxTreeSize is 100 Gigabytes.
2718///
2719/// If the current file contains other objects like TH1 and TTree,
2720/// these objects are automatically moved to the new file.
2721///
2722/// \warning Be careful when writing the final Tree header to the file!
2723/// Don't do:
2724/// ~~~ {.cpp}
2725/// TFile *file = new TFile("myfile.root","recreate");
2726/// TTree *T = new TTree("T","title");
2727/// T->Fill(); // Loop
2728/// file->Write();
2729/// file->Close();
2730/// ~~~
2731/// \warning but do the following:
2732/// ~~~ {.cpp}
2733/// TFile *file = new TFile("myfile.root","recreate");
2734/// TTree *T = new TTree("T","title");
2735/// T->Fill(); // Loop
2736/// file = T->GetCurrentFile(); // To get the pointer to the current file
2737/// file->Write();
2738/// file->Close();
2739/// ~~~
2740///
2741/// \note This method is never called if the input file is a `TMemFile` or derivate.
2744{
2745 // Changing file clashes with the design of TMemFile and derivates, see #6523,
2746 // as well as with TFileMerger operations, see #6640.
2747 if ((dynamic_cast<TMemFile *>(file)) || file->TestBit(TFile::kCancelTTreeChangeRequest))
2748 return file;
2749 file->cd();
2750 Write();
2751 Reset();
2752 constexpr auto kBufSize = 2000;
2753 char* fname = new char[kBufSize];
2754 ++fFileNumber;
2755 char uscore[10];
2756 for (Int_t i = 0; i < 10; ++i) {
2757 uscore[i] = 0;
2758 }
2759 Int_t nus = 0;
2760 // Try to find a suitable file name that does not already exist.
2761 while (nus < 10) {
2762 uscore[nus] = '_';
2763 fname[0] = 0;
2764 strlcpy(fname, file->GetName(), kBufSize);
2765
2766 if (fFileNumber > 1) {
2767 char* cunder = strrchr(fname, '_');
2768 if (cunder) {
2770 const char* cdot = strrchr(file->GetName(), '.');
2771 if (cdot) {
2773 }
2774 } else {
2775 char fcount[21];
2776 snprintf(fcount,21, "%s%d", uscore, fFileNumber);
2778 }
2779 } else {
2780 char* cdot = strrchr(fname, '.');
2781 if (cdot) {
2783 strlcat(fname, strrchr(file->GetName(), '.'), kBufSize);
2784 } else {
2785 char fcount[21];
2786 snprintf(fcount,21, "%s%d", uscore, fFileNumber);
2788 }
2789 }
2791 break;
2792 }
2793 ++nus;
2794 Warning("ChangeFile", "file %s already exists, trying with %d underscores", fname, nus + 1);
2795 }
2797 TFile* newfile = TFile::Open(fname, "recreate", "chain files", compress);
2798 if (newfile == nullptr) {
2799 Error("Fill","Failed to open new file %s, continuing as a memory tree.",fname);
2800 } else {
2801 Printf("Fill: Switching to new file: %s", fname);
2802 }
2803 // The current directory may contain histograms and trees.
2804 // These objects must be moved to the new file.
2805 TBranch* branch = nullptr;
2806 TObject* obj = nullptr;
2807 while ((obj = file->GetList()->First())) {
2808 file->Remove(obj);
2809 // Histogram: just change the directory.
2810 if (obj->InheritsFrom("TH1")) {
2811 gROOT->ProcessLine(TString::Format("((%s*)0x%zx)->SetDirectory((TDirectory*)0x%zx);", obj->ClassName(), (size_t) obj, (size_t) newfile));
2812 continue;
2813 }
2814 // Tree: must save all trees in the old file, reset them.
2815 if (obj->InheritsFrom(TTree::Class())) {
2816 TTree* t = (TTree*) obj;
2817 if (t != this) {
2818 t->AutoSave();
2819 t->Reset();
2821 }
2824 while ((branch = (TBranch*)nextb())) {
2825 branch->SetFile(newfile);
2826 }
2827 if (t->GetBranchRef()) {
2828 t->GetBranchRef()->SetFile(newfile);
2829 }
2830 continue;
2831 }
2832 // Not a TH1 or a TTree, move object to new file.
2833 if (newfile) newfile->Append(obj);
2834 file->Remove(obj);
2835 }
2836 file->TObject::Delete();
2837 file = nullptr;
2838 delete[] fname;
2839 fname = nullptr;
2840 return newfile;
2841}
2842
2843////////////////////////////////////////////////////////////////////////////////
2844/// Check whether or not the address described by the last 3 parameters
2845/// matches the content of the branch. If a Data Model Evolution conversion
2846/// is involved, reset the fInfo of the branch.
2847/// The return values are:
2848//
2849/// - kMissingBranch (-5) : Missing branch
2850/// - kInternalError (-4) : Internal error (could not find the type corresponding to a data type number)
2851/// - kMissingCompiledCollectionProxy (-3) : Missing compiled collection proxy for a compiled collection
2852/// - kMismatch (-2) : Non-Class Pointer type given does not match the type expected by the branch
2853/// - kClassMismatch (-1) : Class Pointer type given does not match the type expected by the branch
2854/// - kMatch (0) : perfect match
2855/// - kMatchConversion (1) : match with (I/O) conversion
2856/// - kMatchConversionCollection (2) : match with (I/O) conversion of the content of a collection
2857/// - kMakeClass (3) : MakeClass mode so we can not check.
2858/// - kVoidPtr (4) : void* passed so no check was made.
2859/// - kNoCheck (5) : Underlying TBranch not yet available so no check was made.
2860/// In addition this can be multiplexed with the two bits:
2861/// - kNeedEnableDecomposedObj : in order for the address (type) to be 'usable' the branch needs to be in Decomposed Object (aka MakeClass) mode.
2862/// - kNeedDisableDecomposedObj : in order for the address (type) to be 'usable' the branch needs to not be in Decomposed Object (aka MakeClass) mode.
2863/// This bits can be masked out by using kDecomposedObjMask
2866{
2867 if (GetMakeClass()) {
2868 // If we are in MakeClass mode so we do not really use classes.
2869 return kMakeClass;
2870 }
2871
2872 // Let's determine what we need!
2873 TClass* expectedClass = nullptr;
2875 if (0 != branch->GetExpectedType(expectedClass,expectedType) ) {
2876 // Something went wrong, the warning message has already been issued.
2877 return kInternalError;
2878 }
2879 bool isBranchElement = branch->InheritsFrom( TBranchElement::Class() );
2880 if (expectedClass && datatype == kOther_t && ptrClass == nullptr) {
2881 if (isBranchElement) {
2883 bEl->SetTargetClass( expectedClass->GetName() );
2884 }
2885 if (expectedClass && expectedClass->GetCollectionProxy() && dynamic_cast<TEmulatedCollectionProxy*>(expectedClass->GetCollectionProxy())) {
2886 Error("SetBranchAddress", "Unable to determine the type given for the address for \"%s\". "
2887 "The class expected (%s) refers to an stl collection and do not have a compiled CollectionProxy. "
2888 "Please generate the dictionary for this class (%s)",
2889 branch->GetName(), expectedClass->GetName(), expectedClass->GetName());
2891 }
2892 if (!expectedClass->IsLoaded()) {
2893 // The originally expected class does not have a dictionary, it is then plausible that the pointer being passed is the right type
2894 // (we really don't know). So let's express that.
2895 Error("SetBranchAddress", "Unable to determine the type given for the address for \"%s\". "
2896 "The class expected (%s) does not have a dictionary and needs to be emulated for I/O purposes but is being passed a compiled object."
2897 "Please generate the dictionary for this class (%s)",
2898 branch->GetName(), expectedClass->GetName(), expectedClass->GetName());
2899 } else {
2900 Error("SetBranchAddress", "Unable to determine the type given for the address for \"%s\". "
2901 "This is probably due to a missing dictionary, the original data class for this branch is %s.", branch->GetName(), expectedClass->GetName());
2902 }
2903 return kClassMismatch;
2904 }
2905 if (expectedClass && ptrClass && (branch->GetMother() == branch)) {
2906 // Top Level branch
2907 if (!isptr) {
2908 Error("SetBranchAddress", "The address for \"%s\" should be the address of a pointer!", branch->GetName());
2909 }
2910 }
2911 if (expectedType == kFloat16_t) {
2913 }
2914 if (expectedType == kDouble32_t) {
2916 }
2917 if (datatype == kFloat16_t) {
2919 }
2920 if (datatype == kDouble32_t) {
2922 }
2923
2924 /////////////////////////////////////////////////////////////////////////////
2925 // Deal with the class renaming
2926 /////////////////////////////////////////////////////////////////////////////
2927
2928 if( expectedClass && ptrClass &&
2931 ptrClass->GetSchemaRules() &&
2932 ptrClass->GetSchemaRules()->HasRuleWithSourceClass( expectedClass->GetName() ) ) {
2934
2935 if ( ptrClass->GetCollectionProxy() && expectedClass->GetCollectionProxy() ) {
2936 if (gDebug > 7)
2937 Info("SetBranchAddress", "Matching STL collection (at least according to the SchemaRuleSet when "
2938 "reading a %s into a %s",expectedClass->GetName(),ptrClass->GetName());
2939
2940 bEl->SetTargetClass( ptrClass->GetName() );
2941 return kMatchConversion;
2942
2943 } else if ( !ptrClass->GetConversionStreamerInfo( expectedClass, bEl->GetClassVersion() ) &&
2944 !ptrClass->FindConversionStreamerInfo( expectedClass, bEl->GetCheckSum() ) ) {
2945 Error("SetBranchAddress", "The pointer type given \"%s\" does not correspond to the type needed \"%s\" by the branch: %s", ptrClass->GetName(), bEl->GetClassName(), branch->GetName());
2946
2947 bEl->SetTargetClass( expectedClass->GetName() );
2948 return kClassMismatch;
2949 }
2950 else {
2951
2952 bEl->SetTargetClass( ptrClass->GetName() );
2953 return kMatchConversion;
2954 }
2955
2956 } else if (expectedClass && ptrClass && !expectedClass->InheritsFrom(ptrClass)) {
2957
2958 if (expectedClass->GetCollectionProxy() && ptrClass->GetCollectionProxy() &&
2960 expectedClass->GetCollectionProxy()->GetValueClass() &&
2961 ptrClass->GetCollectionProxy()->GetValueClass() )
2962 {
2963 // In case of collection, we know how to convert them, if we know how to convert their content.
2964 // NOTE: we need to extend this to std::pair ...
2965
2966 TClass *onfileValueClass = expectedClass->GetCollectionProxy()->GetValueClass();
2967 TClass *inmemValueClass = ptrClass->GetCollectionProxy()->GetValueClass();
2968
2969 if (inmemValueClass->GetSchemaRules() &&
2970 inmemValueClass->GetSchemaRules()->HasRuleWithSourceClass(onfileValueClass->GetName() ) )
2971 {
2973 bEl->SetTargetClass( ptrClass->GetName() );
2975 }
2976 }
2977
2978 Error("SetBranchAddress", "The pointer type given (%s) does not correspond to the class needed (%s) by the branch: %s", ptrClass->GetName(), expectedClass->GetName(), branch->GetName());
2979 if (isBranchElement) {
2981 bEl->SetTargetClass( expectedClass->GetName() );
2982 }
2983 return kClassMismatch;
2984
2985 } else if ((expectedType != kOther_t) && (datatype != kOther_t) && (expectedType != kNoType_t) && (datatype != kNoType_t) && (expectedType != datatype)) {
2986 if (datatype != kChar_t) {
2987 // For backward compatibility we assume that (char*) was just a cast and/or a generic address
2988 Error("SetBranchAddress", "The pointer type given \"%s\" (%d) does not correspond to the type needed \"%s\" (%d) by the branch: %s",
2990 return kMismatch;
2991 }
2992 } else if ((expectedClass && (datatype != kOther_t && datatype != kNoType_t && datatype != kInt_t)) ||
2994 // Sometime a null pointer can look an int, avoid complaining in that case.
2995 if (expectedClass) {
2996 Error("SetBranchAddress", "The pointer type given \"%s\" (%d) does not correspond to the type needed \"%s\" by the branch: %s",
2997 TDataType::GetTypeName(datatype), datatype, expectedClass->GetName(), branch->GetName());
2998 if (isBranchElement) {
3000 bEl->SetTargetClass( expectedClass->GetName() );
3001 }
3002 } else {
3003 // In this case, it is okay if the first data member is of the right type (to support the case where we are being passed
3004 // a struct).
3005 bool found = false;
3006 if (ptrClass->IsLoaded()) {
3007 TIter next(ptrClass->GetListOfRealData());
3008 TRealData *rdm;
3009 while ((rdm = (TRealData*)next())) {
3010 if (rdm->GetThisOffset() == 0) {
3011 TDataType *dmtype = rdm->GetDataMember()->GetDataType();
3012 if (dmtype) {
3013 EDataType etype = (EDataType)dmtype->GetType();
3014 if (etype == expectedType) {
3015 found = true;
3016 }
3017 }
3018 break;
3019 }
3020 }
3021 } else {
3022 TIter next(ptrClass->GetListOfDataMembers());
3023 TDataMember *dm;
3024 while ((dm = (TDataMember*)next())) {
3025 if (dm->GetOffset() == 0) {
3026 TDataType *dmtype = dm->GetDataType();
3027 if (dmtype) {
3028 EDataType etype = (EDataType)dmtype->GetType();
3029 if (etype == expectedType) {
3030 found = true;
3031 }
3032 }
3033 break;
3034 }
3035 }
3036 }
3037 if (found) {
3038 // let's check the size.
3039 TLeaf *last = (TLeaf*)branch->GetListOfLeaves()->Last();
3040 long len = last->GetOffset() + last->GetLenType() * last->GetLen();
3041 if (len <= ptrClass->Size()) {
3042 return kMatch;
3043 }
3044 }
3045 Error("SetBranchAddress", "The pointer type given \"%s\" does not correspond to the type needed \"%s\" (%d) by the branch: %s",
3047 }
3048 return kMismatch;
3049 }
3050 if (expectedClass && expectedClass->GetCollectionProxy() && dynamic_cast<TEmulatedCollectionProxy*>(expectedClass->GetCollectionProxy())) {
3051 Error("SetBranchAddress", writeStlWithoutProxyMsg,
3052 expectedClass->GetName(), branch->GetName(), expectedClass->GetName());
3053 if (isBranchElement) {
3055 bEl->SetTargetClass( expectedClass->GetName() );
3056 }
3058 }
3059 if (isBranchElement) {
3060 if (expectedClass) {
3062 bEl->SetTargetClass( expectedClass->GetName() );
3063 } else if (expectedType != kNoType_t && expectedType != kOther_t) {
3065 }
3066 }
3067 return kMatch;
3068}
3069
3070////////////////////////////////////////////////////////////////////////////////
3071/// Create a clone of this tree and copy nentries.
3072///
3073/// By default copy all entries.
3074/// The compression level of the cloned tree is set to the destination
3075/// file's compression level.
3076///
3077/// NOTE: Only active branches are copied. See TTree::SetBranchStatus for more
3078/// information and usage regarding the (de)activation of branches. More
3079/// examples are provided in the tutorials listed below.
3080///
3081/// NOTE: If the TTree is a TChain, the structure of the first TTree
3082/// is used for the copy.
3083///
3084/// IMPORTANT: The cloned tree stays connected with this tree until
3085/// this tree is deleted. In particular, any changes in
3086/// branch addresses in this tree are forwarded to the
3087/// clone trees, unless a branch in a clone tree has had
3088/// its address changed, in which case that change stays in
3089/// effect. When this tree is deleted, all the addresses of
3090/// the cloned tree are reset to their default values.
3091///
3092/// If 'option' contains the word 'fast' and nentries is -1, the
3093/// cloning will be done without unzipping or unstreaming the baskets
3094/// (i.e., a direct copy of the raw bytes on disk).
3095///
3096/// When 'fast' is specified, 'option' can also contain a sorting
3097/// order for the baskets in the output file.
3098///
3099/// There are currently 3 supported sorting order:
3100///
3101/// - SortBasketsByOffset (the default)
3102/// - SortBasketsByBranch
3103/// - SortBasketsByEntry
3104///
3105/// When using SortBasketsByOffset the baskets are written in the
3106/// output file in the same order as in the original file (i.e. the
3107/// baskets are sorted by their offset in the original file; Usually
3108/// this also means that the baskets are sorted by the index/number of
3109/// the _last_ entry they contain)
3110///
3111/// When using SortBasketsByBranch all the baskets of each individual
3112/// branches are stored contiguously. This tends to optimize reading
3113/// speed when reading a small number (1->5) of branches, since all
3114/// their baskets will be clustered together instead of being spread
3115/// across the file. However it might decrease the performance when
3116/// reading more branches (or the full entry).
3117///
3118/// When using SortBasketsByEntry the baskets with the lowest starting
3119/// entry are written first. (i.e. the baskets are sorted by the
3120/// index/number of the first entry they contain). This means that on
3121/// the file the baskets will be in the order in which they will be
3122/// needed when reading the whole tree sequentially.
3123///
3124/// For examples of CloneTree, see tutorials:
3125///
3126/// - copytree.C:
3127/// A macro to copy a subset of a TTree to a new TTree.
3128/// The input file has been generated by the program in
3129/// $ROOTSYS/test/Event with: Event 1000 1 1 1
3130///
3131/// - copytree2.C:
3132/// A macro to copy a subset of a TTree to a new TTree.
3133/// One branch of the new Tree is written to a separate file.
3134/// The input file has been generated by the program in
3135/// $ROOTSYS/test/Event with: Event 1000 1 1 1
3137TTree* TTree::CloneTree(Long64_t nentries /* = -1 */, Option_t* option /* = "" */)
3138{
3139 // Options
3140 bool fastClone = false;
3141
3142 TString opt = option;
3143 opt.ToLower();
3144 if (opt.Contains("fast")) {
3145 fastClone = true;
3146 }
3147
3148 // If we are a chain, switch to the first tree.
3149 if (fEntries > 0) {
3150 const auto res = LoadTree(0);
3151 if (res < -2 || res == -1) {
3152 // -1 is not accepted, it happens when no trees were defined
3153 // -2 is the only acceptable error, when the chain has zero entries, but tree(s) were defined
3154 // Other errors (-3, ...) are not accepted
3155 Error("CloneTree", "returning nullptr since LoadTree failed with code %lld.", res);
3156 return nullptr;
3157 }
3158 }
3159
3160 // Note: For a tree we get the this pointer, for
3161 // a chain we get the chain's current tree.
3162 TTree* thistree = GetTree();
3163
3164 // We will use this to override the IO features on the cloned branches.
3166 ;
3167
3168 // Note: For a chain, the returned clone will be
3169 // a clone of the chain's first tree.
3170 TTree* newtree = (TTree*) thistree->Clone();
3171 if (!newtree) {
3172 return nullptr;
3173 }
3174
3175 // The clone should not delete any objects allocated by SetAddress().
3176 TObjArray* branches = newtree->GetListOfBranches();
3177 Int_t nb = branches->GetEntriesFast();
3178 for (Int_t i = 0; i < nb; ++i) {
3179 TBranch* br = (TBranch*) branches->UncheckedAt(i);
3180 if (br->InheritsFrom(TBranchElement::Class())) {
3181 ((TBranchElement*) br)->ResetDeleteObject();
3182 }
3183 }
3184
3185 // Add the new tree to the list of clones so that
3186 // we can later inform it of changes to branch addresses.
3187 thistree->AddClone(newtree);
3188 if (thistree != this) {
3189 // In case this object is a TChain, add the clone
3190 // also to the TChain's list of clones.
3192 }
3193
3194 newtree->Reset();
3195
3196 TDirectory* ndir = newtree->GetDirectory();
3197 TFile* nfile = nullptr;
3198 if (ndir) {
3199 nfile = ndir->GetFile();
3200 }
3201 Int_t newcomp = -1;
3202 if (nfile) {
3203 newcomp = nfile->GetCompressionSettings();
3204 }
3205
3206 //
3207 // Delete non-active branches from the clone.
3208 //
3209 // Note: If we are a chain, this does nothing
3210 // since chains have no leaves.
3211 TObjArray* leaves = newtree->GetListOfLeaves();
3212 Int_t nleaves = leaves->GetEntriesFast();
3213 for (Int_t lndx = 0; lndx < nleaves; ++lndx) {
3214 TLeaf* leaf = (TLeaf*) leaves->UncheckedAt(lndx);
3215 if (!leaf) {
3216 continue;
3217 }
3218 TBranch* branch = leaf->GetBranch();
3219 if (branch && (newcomp > -1)) {
3220 branch->SetCompressionSettings(newcomp);
3221 }
3222 if (branch) branch->SetIOFeatures(features);
3223 if (!branch || !branch->TestBit(kDoNotProcess)) {
3224 continue;
3225 }
3226 // size might change at each iteration of the loop over the leaves.
3227 nb = branches->GetEntriesFast();
3228 for (Long64_t i = 0; i < nb; ++i) {
3229 TBranch* br = (TBranch*) branches->UncheckedAt(i);
3230 if (br == branch) {
3231 branches->RemoveAt(i);
3232 delete br;
3233 br = nullptr;
3234 branches->Compress();
3235 break;
3236 }
3237 TObjArray* lb = br->GetListOfBranches();
3238 Int_t nb1 = lb->GetEntriesFast();
3239 for (Int_t j = 0; j < nb1; ++j) {
3240 TBranch* b1 = (TBranch*) lb->UncheckedAt(j);
3241 if (!b1) {
3242 continue;
3243 }
3244 if (b1 == branch) {
3245 lb->RemoveAt(j);
3246 delete b1;
3247 b1 = nullptr;
3248 lb->Compress();
3249 break;
3250 }
3252 Int_t nb2 = lb1->GetEntriesFast();
3253 for (Int_t k = 0; k < nb2; ++k) {
3254 TBranch* b2 = (TBranch*) lb1->UncheckedAt(k);
3255 if (!b2) {
3256 continue;
3257 }
3258 if (b2 == branch) {
3259 lb1->RemoveAt(k);
3260 delete b2;
3261 b2 = nullptr;
3262 lb1->Compress();
3263 break;
3264 }
3265 }
3266 }
3267 }
3268 }
3269 leaves->Compress();
3270
3271 // Copy MakeClass status.
3272 newtree->SetMakeClass(fMakeClass);
3273
3274 // Copy branch addresses.
3276
3277 //
3278 // Copy entries if requested.
3279 //
3280
3281 if (nentries != 0) {
3282 if (fastClone && (nentries < 0)) {
3283 if ( newtree->CopyEntries( this, -1, option, false ) < 0 ) {
3284 // There was a problem!
3285 Error("CloneTTree", "TTree has not been cloned\n");
3286 delete newtree;
3287 newtree = nullptr;
3288 return nullptr;
3289 }
3290 } else {
3291 newtree->CopyEntries( this, nentries, option, false );
3292 }
3293 }
3294
3295 return newtree;
3296}
3297
3298////////////////////////////////////////////////////////////////////////////////
3299/// Set branch addresses of passed tree equal to ours.
3300/// If undo is true, reset the branch addresses instead of copying them.
3301/// This ensures 'separation' of a cloned tree from its original.
3303void TTree::CopyAddresses(TTree* tree, bool undo)
3304{
3305 // Copy branch addresses starting from branches.
3307 Int_t nbranches = branches->GetEntriesFast();
3308 for (Int_t i = 0; i < nbranches; ++i) {
3309 TBranch* branch = (TBranch*) branches->UncheckedAt(i);
3310 if (branch->TestBit(kDoNotProcess)) {
3311 continue;
3312 }
3313 if (undo) {
3314 TBranch* br = tree->GetBranch(branch->GetName());
3315 tree->ResetBranchAddress(br);
3316 } else {
3317 char* addr = branch->GetAddress();
3318 if (!addr) {
3319 if (branch->IsA() == TBranch::Class()) {
3320 // If the branch was created using a leaflist, the branch itself may not have
3321 // an address but the leaf might already.
3322 TLeaf *firstleaf = (TLeaf*)branch->GetListOfLeaves()->At(0);
3323 if (!firstleaf || firstleaf->GetValuePointer()) {
3324 // Either there is no leaf (and thus no point in copying the address)
3325 // or the leaf has an address but we can not copy it via the branche
3326 // this will be copied via the next loop (over the leaf).
3327 continue;
3328 }
3329 }
3330 // Note: This may cause an object to be allocated.
3331 branch->SetAddress(nullptr);
3332 addr = branch->GetAddress();
3333 }
3334 TBranch* br = tree->GetBranch(branch->GetFullName());
3335 if (br) {
3336 if (br->GetMakeClass() != branch->GetMakeClass())
3337 br->SetMakeClass(branch->GetMakeClass());
3338 br->SetAddress(addr);
3339 // The copy does not own any object allocated by SetAddress().
3340 if (br->InheritsFrom(TBranchElement::Class())) {
3341 ((TBranchElement*) br)->ResetDeleteObject();
3342 }
3343 } else {
3344 Warning("CopyAddresses", "Could not find branch named '%s' in tree named '%s'", branch->GetName(), tree->GetName());
3345 }
3346 }
3347 }
3348
3349 // Copy branch addresses starting from leaves.
3350 TObjArray* tleaves = tree->GetListOfLeaves();
3351 Int_t ntleaves = tleaves->GetEntriesFast();
3352 std::set<TLeaf*> updatedLeafCount;
3353 for (Int_t i = 0; i < ntleaves; ++i) {
3354 TLeaf* tleaf = (TLeaf*) tleaves->UncheckedAt(i);
3355 TBranch* tbranch = tleaf->GetBranch();
3356 TBranch* branch = GetBranch(tbranch->GetName());
3357 if (!branch) {
3358 continue;
3359 }
3360 TLeaf* leaf = branch->GetLeaf(tleaf->GetName());
3361 if (!leaf) {
3362 continue;
3363 }
3364 if (branch->TestBit(kDoNotProcess)) {
3365 continue;
3366 }
3367 if (undo) {
3368 // Now we know whether the address has been transfered
3369 tree->ResetBranchAddress(tbranch);
3370 } else {
3371 TBranchElement *mother = dynamic_cast<TBranchElement*>(leaf->GetBranch()->GetMother());
3372 bool needAddressReset = false;
3373 if (leaf->GetLeafCount() && (leaf->TestBit(TLeaf::kNewValue) || !leaf->GetValuePointer() || (mother && mother->IsObjectOwner())) && tleaf->GetLeafCount())
3374 {
3375 // If it is an array and it was allocated by the leaf itself,
3376 // let's make sure it is large enough for the incoming data.
3377 if (leaf->GetLeafCount()->GetMaximum() < tleaf->GetLeafCount()->GetMaximum()) {
3378 leaf->GetLeafCount()->IncludeRange( tleaf->GetLeafCount() );
3379 updatedLeafCount.insert(leaf->GetLeafCount());
3380 needAddressReset = true;
3381 } else {
3382 needAddressReset = (updatedLeafCount.find(leaf->GetLeafCount()) != updatedLeafCount.end());
3383 }
3384 }
3385 if (needAddressReset && leaf->GetValuePointer()) {
3386 if (leaf->IsA() == TLeafElement::Class() && mother)
3387 mother->ResetAddress();
3388 else
3389 leaf->SetAddress(nullptr);
3390 }
3391 if (!branch->GetAddress() && !leaf->GetValuePointer()) {
3392 // We should attempts to set the address of the branch.
3393 // something like:
3394 //(TBranchElement*)branch->GetMother()->SetAddress(0)
3395 //plus a few more subtleties (see TBranchElement::GetEntry).
3396 //but for now we go the simplest route:
3397 //
3398 // Note: This may result in the allocation of an object.
3399 branch->SetupAddresses();
3400 }
3401 if (branch->GetAddress()) {
3402 tree->SetBranchAddress(branch->GetName(), (void*) branch->GetAddress());
3403 TBranch* br = tree->GetBranch(branch->GetName());
3404 if (br) {
3405 if (br->IsA() != branch->IsA()) {
3406 Error(
3407 "CopyAddresses",
3408 "Branch kind mismatch between input tree '%s' and output tree '%s' for branch '%s': '%s' vs '%s'",
3409 tree->GetName(), br->GetTree()->GetName(), br->GetName(), branch->IsA()->GetName(),
3410 br->IsA()->GetName());
3411 }
3412 // The copy does not own any object allocated by SetAddress().
3413 // FIXME: We do too much here, br may not be a top-level branch.
3414 if (br->InheritsFrom(TBranchElement::Class())) {
3415 ((TBranchElement*) br)->ResetDeleteObject();
3416 }
3417 } else {
3418 Warning("CopyAddresses", "Could not find branch named '%s' in tree named '%s'", branch->GetName(), tree->GetName());
3419 }
3420 } else {
3421 tleaf->SetAddress(leaf->GetValuePointer());
3422 }
3423 }
3424 }
3425
3426 if (undo &&
3427 ( tree->IsA()->InheritsFrom("TNtuple") || tree->IsA()->InheritsFrom("TNtupleD") )
3428 ) {
3429 tree->ResetBranchAddresses();
3430 }
3431}
3432
3433namespace {
3434
3435 enum EOnIndexError { kDrop, kKeep, kBuild };
3436
3437 bool R__HandleIndex(EOnIndexError onIndexError, TTree *newtree, TTree *oldtree)
3438 {
3439 // Return true if we should continue to handle indices, false otherwise.
3440
3441 bool withIndex = true;
3442
3443 if ( newtree->GetTreeIndex() ) {
3444 if ( oldtree->GetTree()->GetTreeIndex() == nullptr ) {
3445 switch (onIndexError) {
3446 case kDrop:
3447 delete newtree->GetTreeIndex();
3448 newtree->SetTreeIndex(nullptr);
3449 withIndex = false;
3450 break;
3451 case kKeep:
3452 // Nothing to do really.
3453 break;
3454 case kBuild:
3455 // Build the index then copy it
3456 if (oldtree->GetTree()->BuildIndex(newtree->GetTreeIndex()->GetMajorName(), newtree->GetTreeIndex()->GetMinorName())) {
3457 newtree->GetTreeIndex()->Append(oldtree->GetTree()->GetTreeIndex(), true);
3458 // Clean up
3459 delete oldtree->GetTree()->GetTreeIndex();
3460 oldtree->GetTree()->SetTreeIndex(nullptr);
3461 }
3462 break;
3463 }
3464 } else {
3465 newtree->GetTreeIndex()->Append(oldtree->GetTree()->GetTreeIndex(), true);
3466 }
3467 } else if ( oldtree->GetTree()->GetTreeIndex() != nullptr ) {
3468 // We discover the first index in the middle of the chain.
3469 switch (onIndexError) {
3470 case kDrop:
3471 // Nothing to do really.
3472 break;
3473 case kKeep: {
3474 TVirtualIndex *index = (TVirtualIndex*) oldtree->GetTree()->GetTreeIndex()->Clone();
3475 index->SetTree(newtree);
3476 newtree->SetTreeIndex(index);
3477 break;
3478 }
3479 case kBuild:
3480 if (newtree->GetEntries() == 0) {
3481 // Start an index.
3482 TVirtualIndex *index = (TVirtualIndex*) oldtree->GetTree()->GetTreeIndex()->Clone();
3483 index->SetTree(newtree);
3484 newtree->SetTreeIndex(index);
3485 } else {
3486 // Build the index so far.
3487 if (newtree->BuildIndex(oldtree->GetTree()->GetTreeIndex()->GetMajorName(), oldtree->GetTree()->GetTreeIndex()->GetMinorName())) {
3488 newtree->GetTreeIndex()->Append(oldtree->GetTree()->GetTreeIndex(), true);
3489 }
3490 }
3491 break;
3492 }
3493 } else if ( onIndexError == kDrop ) {
3494 // There is no index on this or on tree->GetTree(), we know we have to ignore any further
3495 // index
3496 withIndex = false;
3497 }
3498 return withIndex;
3499 }
3500}
3501
3502////////////////////////////////////////////////////////////////////////////////
3503/// Copy nentries from given tree to this tree.
3504/// This routines assumes that the branches that intended to be copied are
3505/// already connected. The typical case is that this tree was created using
3506/// tree->CloneTree(0).
3507///
3508/// By default copy all entries.
3509///
3510/// Returns number of bytes copied to this tree.
3511///
3512/// If 'option' contains the word 'fast' and nentries is -1, the cloning will be
3513/// done without unzipping or unstreaming the baskets (i.e., a direct copy of the
3514/// raw bytes on disk).
3515///
3516/// When 'fast' is specified, 'option' can also contains a sorting order for the
3517/// baskets in the output file.
3518///
3519/// There are currently 3 supported sorting order:
3520///
3521/// - SortBasketsByOffset (the default)
3522/// - SortBasketsByBranch
3523/// - SortBasketsByEntry
3524///
3525/// See TTree::CloneTree for a detailed explanation of the semantics of these 3 options.
3526///
3527/// If the tree or any of the underlying tree of the chain has an index, that index and any
3528/// index in the subsequent underlying TTree objects will be merged.
3529///
3530/// There are currently three 'options' to control this merging:
3531/// - NoIndex : all the TTreeIndex object are dropped.
3532/// - DropIndexOnError : if any of the underlying TTree object do no have a TTreeIndex,
3533/// they are all dropped.
3534/// - AsIsIndexOnError [default]: In case of missing TTreeIndex, the resulting TTree index has gaps.
3535/// - BuildIndexOnError : If any of the underlying TTree objects do not have a TTreeIndex,
3536/// all TTreeIndex are 'ignored' and the missing piece are rebuilt.
3538Long64_t TTree::CopyEntries(TTree* tree, Long64_t nentries /* = -1 */, Option_t* option /* = "" */, bool needCopyAddresses /* = false */)
3539{
3540 if (!tree) {
3541 return 0;
3542 }
3543 // Options
3544 TString opt = option;
3545 opt.ToLower();
3546 bool fastClone = opt.Contains("fast");
3547 bool withIndex = !opt.Contains("noindex");
3548 EOnIndexError onIndexError;
3549 if (opt.Contains("asisindex")) {
3551 } else if (opt.Contains("buildindex")) {
3553 } else if (opt.Contains("dropindex")) {
3555 } else {
3557 }
3558 Ssiz_t cacheSizeLoc = opt.Index("cachesize=");
3559 Long64_t cacheSize = -1;
3561 // If the parse faile, cacheSize stays at -1.
3562 Ssiz_t cacheSizeEnd = opt.Index(" ",cacheSizeLoc+10) - (cacheSizeLoc+10);
3566 Warning("CopyEntries","The cachesize option can not be parsed: %s. The default size will be used.",cacheSizeStr.String().Data());
3568 double m;
3569 const char *munit = nullptr;
3570 ROOT::ToHumanReadableSize(std::numeric_limits<decltype(cacheSize)>::max(),false,&m,&munit);
3571
3572 Warning("CopyEntries","The cachesize option is too large: %s (%g%s max). The default size will be used.",cacheSizeStr.String().Data(),m,munit);
3573 }
3574 }
3575 if (gDebug > 0 && cacheSize != -1) Info("CopyEntries","Using Cache size: %lld\n",cacheSize);
3576
3577 Long64_t nbytes = 0;
3578 Long64_t treeEntries = tree->GetEntriesFast();
3579 if (nentries < 0) {
3581 } else if (nentries > treeEntries) {
3583 }
3584
3586 // Quickly copy the basket without decompression and streaming.
3588 for (Long64_t i = 0; i < nentries; i += tree->GetTree()->GetEntries()) {
3589 if (tree->LoadTree(i) < 0) {
3590 break;
3591 }
3592 if ( withIndex ) {
3593 withIndex = R__HandleIndex( onIndexError, this, tree );
3594 }
3595 if (this->GetDirectory()) {
3596 TFile* file2 = this->GetDirectory()->GetFile();
3597 if (file2 && (file2->GetEND() > TTree::GetMaxTreeSize())) {
3598 if (this->GetDirectory() == (TDirectory*) file2) {
3599 this->ChangeFile(file2);
3600 }
3601 }
3602 }
3603 TTreeCloner cloner(tree->GetTree(), this, option, TTreeCloner::kNoWarnings);
3604 if (cloner.IsValid()) {
3605 this->SetEntries(this->GetEntries() + tree->GetTree()->GetEntries());
3606 if (cacheSize != -1) cloner.SetCacheSize(cacheSize);
3607 cloner.Exec();
3608 } else {
3609 if (i == 0) {
3610 Warning("CopyEntries","%s",cloner.GetWarning());
3611 // If the first cloning does not work, something is really wrong
3612 // (since apriori the source and target are exactly the same structure!)
3613 return -1;
3614 } else {
3615 if (cloner.NeedConversion()) {
3616 TTree *localtree = tree->GetTree();
3617 Long64_t tentries = localtree->GetEntries();
3618 if (needCopyAddresses) {
3619 // Copy MakeClass status.
3620 tree->SetMakeClass(fMakeClass);
3621 // Copy branch addresses.
3622 CopyAddresses(tree);
3623 }
3624 for (Long64_t ii = 0; ii < tentries; ii++) {
3625 if (localtree->GetEntry(ii) <= 0) {
3626 break;
3627 }
3628 this->Fill();
3629 }
3630 if (needCopyAddresses)
3631 tree->ResetBranchAddresses();
3632 if (this->GetTreeIndex()) {
3633 this->GetTreeIndex()->Append(tree->GetTree()->GetTreeIndex(), true);
3634 }
3635 } else {
3636 Warning("CopyEntries","%s",cloner.GetWarning());
3637 if (tree->GetDirectory() && tree->GetDirectory()->GetFile()) {
3638 Warning("CopyEntries", "Skipped file %s\n", tree->GetDirectory()->GetFile()->GetName());
3639 } else {
3640 Warning("CopyEntries", "Skipped file number %d\n", tree->GetTreeNumber());
3641 }
3642 }
3643 }
3644 }
3645
3646 }
3647 if (this->GetTreeIndex()) {
3648 this->GetTreeIndex()->Append(nullptr,false); // Force the sorting
3649 }
3650 nbytes = GetTotBytes() - totbytes;
3651 } else {
3652 if (nentries < 0) {
3654 } else if (nentries > treeEntries) {
3656 }
3657 if (needCopyAddresses) {
3658 // Copy MakeClass status.
3659 tree->SetMakeClass(fMakeClass);
3660 // Copy branch addresses.
3661 CopyAddresses(tree);
3662 }
3663 Int_t treenumber = -1;
3664 for (Long64_t i = 0; i < nentries; i++) {
3665 if (tree->LoadTree(i) < 0) {
3666 break;
3667 }
3668 if (treenumber != tree->GetTreeNumber()) {
3669 if ( withIndex ) {
3670 withIndex = R__HandleIndex( onIndexError, this, tree );
3671 }
3672 treenumber = tree->GetTreeNumber();
3673 }
3674 if (tree->GetEntry(i) <= 0) {
3675 break;
3676 }
3677 nbytes += this->Fill();
3678 }
3679 if (needCopyAddresses)
3680 tree->ResetBranchAddresses();
3681 if (this->GetTreeIndex()) {
3682 this->GetTreeIndex()->Append(nullptr,false); // Force the sorting
3683 }
3684 }
3685 return nbytes;
3686}
3687
3688////////////////////////////////////////////////////////////////////////////////
3689/// Copy a tree with selection.
3690///
3691/// ### Important:
3692///
3693/// The returned copied tree stays connected with the original tree
3694/// until the original tree is deleted. In particular, any changes
3695/// to the branch addresses in the original tree are also made to
3696/// the copied tree. Any changes made to the branch addresses of the
3697/// copied tree are overridden anytime the original tree changes its
3698/// branch addresses. When the original tree is deleted, all the
3699/// branch addresses of the copied tree are set to zero.
3700///
3701/// For examples of CopyTree, see the tutorials:
3702///
3703/// - copytree.C:
3704/// Example macro to copy a subset of a tree to a new tree.
3705/// The input file was generated by running the program in
3706/// $ROOTSYS/test/Event in this way:
3707/// ~~~ {.cpp}
3708/// ./Event 1000 1 1 1
3709/// ~~~
3710/// - copytree2.C
3711/// Example macro to copy a subset of a tree to a new tree.
3712/// One branch of the new tree is written to a separate file.
3713/// The input file was generated by running the program in
3714/// $ROOTSYS/test/Event in this way:
3715/// ~~~ {.cpp}
3716/// ./Event 1000 1 1 1
3717/// ~~~
3718/// - copytree3.C
3719/// Example macro to copy a subset of a tree to a new tree.
3720/// Only selected entries are copied to the new tree.
3721/// NOTE that only the active branches are copied.
3723TTree* TTree::CopyTree(const char* selection, Option_t* option /* = 0 */, Long64_t nentries /* = TTree::kMaxEntries */, Long64_t firstentry /* = 0 */)
3724{
3725 GetPlayer();
3726 if (fPlayer) {
3728 }
3729 return nullptr;
3730}
3731
3732////////////////////////////////////////////////////////////////////////////////
3733/// Create a basket for this tree and given branch.
3736{
3737 if (!branch) {
3738 return nullptr;
3739 }
3740 return new TBasket(branch->GetName(), GetName(), branch);
3741}
3742
3743////////////////////////////////////////////////////////////////////////////////
3744/// Delete this tree from memory or/and disk.
3745///
3746/// - if option == "all" delete Tree object from memory AND from disk
3747/// all baskets on disk are deleted. All keys with same name
3748/// are deleted.
3749/// - if option =="" only Tree object in memory is deleted.
3751void TTree::Delete(Option_t* option /* = "" */)
3752{
3753 TFile *file = GetCurrentFile();
3754
3755 // delete all baskets and header from file
3756 if (file && option && !strcmp(option,"all")) {
3757 if (!file->IsWritable()) {
3758 Error("Delete","File : %s is not writable, cannot delete Tree:%s", file->GetName(),GetName());
3759 return;
3760 }
3761
3762 //find key and import Tree header in memory
3763 TKey *key = fDirectory->GetKey(GetName());
3764 if (!key) return;
3765
3767 file->cd();
3768
3769 //get list of leaves and loop on all the branches baskets
3770 TIter next(GetListOfLeaves());
3771 TLeaf *leaf;
3772 char header[16];
3773 Int_t ntot = 0;
3774 Int_t nbask = 0;
3776 while ((leaf = (TLeaf*)next())) {
3777 TBranch *branch = leaf->GetBranch();
3778 Int_t nbaskets = branch->GetMaxBaskets();
3779 for (Int_t i=0;i<nbaskets;i++) {
3780 Long64_t pos = branch->GetBasketSeek(i);
3781 if (!pos) continue;
3782 TFile *branchFile = branch->GetFile();
3783 if (!branchFile) continue;
3784 branchFile->GetRecordHeader(header,pos,16,nbytes,objlen,keylen);
3785 if (nbytes <= 0) continue;
3786 branchFile->MakeFree(pos,pos+nbytes-1);
3787 ntot += nbytes;
3788 nbask++;
3789 }
3790 }
3791
3792 // delete Tree header key and all keys with the same name
3793 // A Tree may have been saved many times. Previous cycles are invalid.
3794 while (key) {
3795 ntot += key->GetNbytes();
3796 key->Delete();
3797 delete key;
3798 key = fDirectory->GetKey(GetName());
3799 }
3800 if (dirsav) dirsav->cd();
3801 if (gDebug) Info("TTree::Delete", "Deleting Tree: %s: %d baskets deleted. Total space freed = %d bytes\n",GetName(),nbask,ntot);
3802 }
3803
3804 if (fDirectory) {
3805 fDirectory->Remove(this);
3806 //delete the file cache if it points to this Tree
3807 MoveReadCache(file,nullptr);
3808 fDirectory = nullptr;
3810 }
3811
3812 // Delete object from CINT symbol table so it can not be used anymore.
3813 gCling->DeleteGlobal(this);
3814
3815 // Warning: We have intentional invalidated this object while inside a member function!
3816 delete this;
3817}
3818
3819 ///////////////////////////////////////////////////////////////////////////////
3820 /// Called by TKey and TObject::Clone to automatically add us to a directory
3821 /// when we are read from a file.
3824{
3825 if (fDirectory == dir) return;
3826 if (fDirectory) {
3827 fDirectory->Remove(this);
3828 // Delete or move the file cache if it points to this Tree
3829 TFile *file = fDirectory->GetFile();
3830 MoveReadCache(file,dir);
3831 }
3832 fDirectory = dir;
3833 TBranch* b = nullptr;
3834 TIter next(GetListOfBranches());
3835 while((b = (TBranch*) next())) {
3836 b->UpdateFile();
3837 }
3838 if (fBranchRef) {
3840 }
3841 if (fDirectory) fDirectory->Append(this);
3842}
3843
3844////////////////////////////////////////////////////////////////////////////////
3845/// Draw expression varexp for specified entries.
3846///
3847/// \return -1 in case of error or number of selected events in case of success.
3848///
3849/// This function accepts TCut objects as arguments.
3850/// Useful to use the string operator +
3851///
3852/// Example:
3853///
3854/// ~~~ {.cpp}
3855/// ntuple.Draw("x",cut1+cut2+cut3);
3856/// ~~~
3857
3862}
3863
3864/////////////////////////////////////////////////////////////////////////////////////////
3865/// \brief Draw expression varexp for entries and objects that pass a (optional) selection.
3866///
3867/// \return -1 in case of error or number of selected events in case of success.
3868///
3869/// \param [in] varexp
3870/// \parblock
3871/// A string that takes one of these general forms:
3872/// - "e1" produces a 1-d histogram (TH1F) of expression "e1"
3873/// - "e1:e2" produces an unbinned 2-d scatter-plot (TGraph) of "e1"
3874/// on the y-axis versus "e2" on the x-axis
3875/// - "e1:e2:e3" produces an unbinned 3-d scatter-plot (TPolyMarker3D) of "e1"
3876/// vs "e2" vs "e3" on the z-, y-, x-axis, respectively
3877/// - "e1:e2:e3:e4" produces an unbinned 3-d scatter-plot (TPolyMarker3D) of "e1"
3878/// vs "e2" vs "e3" and "e4" mapped on the current color palette.
3879/// (to create histograms in the 2, 3, and 4 dimensional case,
3880/// see section "Saving the result of Draw to an histogram")
3881/// - "e1:e2:e3:e4:e5" with option "GL5D" produces a 5D plot using OpenGL. `gStyle->SetCanvasPreferGL(true)` is needed.
3882/// - Any number of variables no fewer than two can be used with the options "CANDLE" and "PARA"
3883/// - An arbitrary number of variables can be used with the option "GOFF"
3884///
3885/// Examples:
3886/// - "x": the simplest case, it draws a 1-Dim histogram of column x
3887/// - "sqrt(x)", "x*y/z": draw histogram with the values of the specified numerical expression across TTree events
3888/// - "y:sqrt(x)": 2-Dim histogram of y versus sqrt(x)
3889/// - "px:py:pz:2.5*E": produces a 3-d scatter-plot of px vs py ps pz
3890/// and the color number of each marker will be 2.5*E.
3891/// If the color number is negative it is set to 0.
3892/// If the color number is greater than the current number of colors
3893/// it is set to the highest color number. The default number of
3894/// colors is 50. See TStyle::SetPalette for setting a new color palette.
3895///
3896/// The expressions can use all the operations and built-in functions
3897/// supported by TFormula (see TFormula::Analyze()), including free
3898/// functions taking numerical arguments (e.g. TMath::Bessel()).
3899/// In addition, you can call member functions taking numerical
3900/// arguments. For example, these are two valid expressions:
3901/// ~~~ {.cpp}
3902/// TMath::BreitWigner(fPx,3,2)
3903/// event.GetHistogram()->GetXaxis()->GetXmax()
3904/// ~~~
3905/// \endparblock
3906/// \param [in] selection
3907/// \parblock
3908/// A string containing a selection expression.
3909/// In a selection all usual C++ mathematical and logical operators are allowed.
3910/// The value corresponding to the selection expression is used as a weight
3911/// to fill the histogram (a weight of 0 is equivalent to not filling the histogram).\n
3912/// \n
3913/// Examples:
3914/// - "x<y && sqrt(z)>3.2": returns a weight = 0 or 1
3915/// - "(x+y)*(sqrt(z)>3.2)": returns a weight = x+y if sqrt(z)>3.2, 0 otherwise\n
3916/// \n
3917/// If the selection expression returns an array, it is iterated over in sync with the
3918/// array returned by the varexp argument (as described below in "Drawing expressions using arrays and array
3919/// elements"). For example, if, for a given event, varexp evaluates to
3920/// `{1., 2., 3.}` and selection evaluates to `{0, 1, 0}`, the resulting histogram is filled with the value 2. For example, for each event here we perform a simple object selection:
3921/// ~~~{.cpp}
3922/// // Muon_pt is an array: fill a histogram with the array elements > 100 in each event
3923/// tree->Draw('Muon_pt', 'Muon_pt > 100')
3924/// ~~~
3925/// \endparblock
3926/// \param [in] option
3927/// \parblock
3928/// The drawing option.
3929/// - When an histogram is produced it can be any histogram drawing option
3930/// listed in THistPainter.
3931/// - when no option is specified:
3932/// - the default histogram drawing option is used
3933/// if the expression is of the form "e1".
3934/// - if the expression is of the form "e1:e2"or "e1:e2:e3" a cloud of
3935/// unbinned 2D or 3D points is drawn respectively.
3936/// - if the expression has four fields "e1:e2:e3:e4" a cloud of unbinned 3D
3937/// points is produced with e1 vs e2 vs e3, and e4 is mapped on the current color
3938/// palette.
3939/// - If option COL is specified when varexp has three fields:
3940/// ~~~ {.cpp}
3941/// tree.Draw("e1:e2:e3","","col");
3942/// ~~~
3943/// a 2D scatter is produced with e1 vs e2, and e3 is mapped on the current
3944/// color palette. The colors for e3 are evaluated once in linear scale before
3945/// painting. Therefore changing the pad to log scale along Z as no effect
3946/// on the colors.
3947/// - if expression has more than four fields the option "PARA"or "CANDLE"
3948/// can be used.
3949/// - If option contains the string "goff", no graphics is generated.
3950/// \endparblock
3951/// \param [in] nentries The number of entries to process (default is all)
3952/// \param [in] firstentry The first entry to process (default is 0)
3953///
3954/// ### Drawing expressions using arrays and array elements
3955///
3956/// Let assumes, a leaf fMatrix, on the branch fEvent, which is a 3 by 3 array,
3957/// or a TClonesArray.
3958/// In a TTree::Draw expression you can now access fMatrix using the following
3959/// syntaxes:
3960///
3961/// | String passed | What is used for each entry of the tree
3962/// |-----------------|--------------------------------------------------------|
3963/// | `fMatrix` | the 9 elements of fMatrix |
3964/// | `fMatrix[][]` | the 9 elements of fMatrix |
3965/// | `fMatrix[2][2]` | only the elements fMatrix[2][2] |
3966/// | `fMatrix[1]` | the 3 elements fMatrix[1][0], fMatrix[1][1] and fMatrix[1][2] |
3967/// | `fMatrix[1][]` | the 3 elements fMatrix[1][0], fMatrix[1][1] and fMatrix[1][2] |
3968/// | `fMatrix[][0]` | the 3 elements fMatrix[0][0], fMatrix[1][0] and fMatrix[2][0] |
3969///
3970/// "fEvent.fMatrix...." same as "fMatrix..." (unless there is more than one leaf named fMatrix!).
3971///
3972/// In summary, if a specific index is not specified for a dimension, TTree::Draw
3973/// will loop through all the indices along this dimension. Leaving off the
3974/// last (right most) dimension of specifying then with the two characters '[]'
3975/// is equivalent. For variable size arrays (and TClonesArray) the range
3976/// of the first dimension is recalculated for each entry of the tree.
3977/// You can also specify the index as an expression of any other variables from the
3978/// tree.
3979///
3980/// TTree::Draw also now properly handling operations involving 2 or more arrays.
3981///
3982/// Let assume a second matrix fResults[5][2], here are a sample of some
3983/// of the possible combinations, the number of elements they produce and
3984/// the loop used:
3985///
3986/// | expression | element(s) | Loop |
3987/// |----------------------------------|------------|--------------------------|
3988/// | `fMatrix[2][1] - fResults[5][2]` | one | no loop |
3989/// | `fMatrix[2][] - fResults[5][2]` | three | on 2nd dim fMatrix |
3990/// | `fMatrix[2][] - fResults[5][]` | two | on both 2nd dimensions |
3991/// | `fMatrix[][2] - fResults[][1]` | three | on both 1st dimensions |
3992/// | `fMatrix[][2] - fResults[][]` | six | on both 1st and 2nd dimensions of fResults |
3993/// | `fMatrix[][2] - fResults[3][]` | two | on 1st dim of fMatrix and 2nd of fResults (at the same time) |
3994/// | `fMatrix[][] - fResults[][]` | six | on 1st dim then on 2nd dim |
3995/// | `fMatrix[][fResult[][]]` | 30 | on 1st dim of fMatrix then on both dimensions of fResults. The value if fResults[j][k] is used as the second index of fMatrix.|
3996///
3997///
3998/// In summary, TTree::Draw loops through all unspecified dimensions. To
3999/// figure out the range of each loop, we match each unspecified dimension
4000/// from left to right (ignoring ALL dimensions for which an index has been
4001/// specified), in the equivalent loop matched dimensions use the same index
4002/// and are restricted to the smallest range (of only the matched dimensions).
4003/// When involving variable arrays, the range can of course be different
4004/// for each entry of the tree.
4005///
4006/// So the loop equivalent to "fMatrix[][2] - fResults[3][]" is:
4007/// ~~~ {.cpp}
4008/// for (Int_t i0; i < min(3,2); i++) {
4009/// use the value of (fMatrix[i0][2] - fMatrix[3][i0])
4010/// }
4011/// ~~~
4012/// So the loop equivalent to "fMatrix[][2] - fResults[][]" is:
4013/// ~~~ {.cpp}
4014/// for (Int_t i0; i < min(3,5); i++) {
4015/// for (Int_t i1; i1 < 2; i1++) {
4016/// use the value of (fMatrix[i0][2] - fMatrix[i0][i1])
4017/// }
4018/// }
4019/// ~~~
4020/// So the loop equivalent to "fMatrix[][] - fResults[][]" is:
4021/// ~~~ {.cpp}
4022/// for (Int_t i0; i < min(3,5); i++) {
4023/// for (Int_t i1; i1 < min(3,2); i1++) {
4024/// use the value of (fMatrix[i0][i1] - fMatrix[i0][i1])
4025/// }
4026/// }
4027/// ~~~
4028/// So the loop equivalent to "fMatrix[][fResults[][]]" is:
4029/// ~~~ {.cpp}
4030/// for (Int_t i0; i0 < 3; i0++) {
4031/// for (Int_t j2; j2 < 5; j2++) {
4032/// for (Int_t j3; j3 < 2; j3++) {
4033/// i1 = fResults[j2][j3];
4034/// use the value of fMatrix[i0][i1]
4035/// }
4036/// }
4037/// ~~~
4038/// ### Retrieving the result of Draw
4039///
4040/// By default a temporary histogram called `htemp` is created. It will be:
4041///
4042/// - A TH1F* in case of a mono-dimensional distribution: `Draw("e1")`,
4043/// - A TH2F* in case of a bi-dimensional distribution: `Draw("e1:e2")`,
4044/// - A TH3F* in case of a three-dimensional distribution: `Draw("e1:e2:e3")`.
4045///
4046/// In the one dimensional case the `htemp` is filled and drawn whatever the drawing
4047/// option is.
4048///
4049/// In the two and three dimensional cases, with the default drawing option (`""`),
4050/// a cloud of points is drawn and the histogram `htemp` is not filled. For all the other
4051/// drawing options `htemp` will be filled.
4052///
4053/// In all cases `htemp` can be retrieved by calling:
4054///
4055/// ~~~ {.cpp}
4056/// auto htemp = (TH1F*)gPad->GetPrimitive("htemp"); // 1D
4057/// auto htemp = (TH2F*)gPad->GetPrimitive("htemp"); // 2D
4058/// auto htemp = (TH3F*)gPad->GetPrimitive("htemp"); // 3D
4059/// ~~~
4060///
4061/// In the two dimensional case (`Draw("e1;e2")`), with the default drawing option, the
4062/// data is filled into a TGraph named `Graph`. This TGraph can be retrieved by
4063/// calling
4064///
4065/// ~~~ {.cpp}
4066/// auto graph = (TGraph*)gPad->GetPrimitive("Graph");
4067/// ~~~
4068///
4069/// For the three and four dimensional cases, with the default drawing option, an unnamed
4070/// TPolyMarker3D is produced, and therefore cannot be retrieved.
4071///
4072/// In all cases `htemp` can be used to access the axes. For instance in the 2D case:
4073///
4074/// ~~~ {.cpp}
4075/// auto htemp = (TH2F*)gPad->GetPrimitive("htemp");
4076/// auto xaxis = htemp->GetXaxis();
4077/// ~~~
4078///
4079/// When the option `"A"` is used (with TGraph painting option) to draw a 2D
4080/// distribution:
4081/// ~~~ {.cpp}
4082/// tree.Draw("e1:e2","","A*");
4083/// ~~~
4084/// a scatter plot is produced (with stars in that case) but the axis creation is
4085/// delegated to TGraph and `htemp` is not created.
4086///
4087/// ### Saving the result of Draw to a histogram
4088///
4089/// If `varexp` contains `>>hnew` (following the variable(s) name(s)),
4090/// the new histogram called `hnew` is created and it is kept in the current
4091/// directory (and also the current pad). This works for all dimensions.
4092///
4093/// Example:
4094/// ~~~ {.cpp}
4095/// tree.Draw("sqrt(x)>>hsqrt","y>0")
4096/// ~~~
4097/// will draw `sqrt(x)` and save the histogram as "hsqrt" in the current
4098/// directory. To retrieve it do:
4099/// ~~~ {.cpp}
4100/// TH1F *hsqrt = (TH1F*)gDirectory->Get("hsqrt");
4101/// ~~~
4102/// The binning information is taken from the environment variables
4103/// ~~~ {.cpp}
4104/// Hist.Binning.?D.?
4105/// ~~~
4106/// In addition, the name of the histogram can be followed by up to 9
4107/// numbers between '(' and ')', where the numbers describe the
4108/// following:
4109///
4110/// - 1 - bins in x-direction
4111/// - 2 - lower limit in x-direction
4112/// - 3 - upper limit in x-direction
4113/// - 4-6 same for y-direction
4114/// - 7-9 same for z-direction
4115///
4116/// When a new binning is used the new value will become the default.
4117/// Values can be skipped.
4118///
4119/// Example:
4120/// ~~~ {.cpp}
4121/// tree.Draw("sqrt(x)>>hsqrt(500,10,20)")
4122/// // plot sqrt(x) between 10 and 20 using 500 bins
4123/// tree.Draw("sqrt(x):sin(y)>>hsqrt(100,10,60,50,.1,.5)")
4124/// // plot sqrt(x) against sin(y)
4125/// // 100 bins in x-direction; lower limit on x-axis is 10; upper limit is 60
4126/// // 50 bins in y-direction; lower limit on y-axis is .1; upper limit is .5
4127/// ~~~
4128/// By default, the specified histogram is reset.
4129/// To continue to append data to an existing histogram, use "+" in front
4130/// of the histogram name.
4131///
4132/// A '+' in front of the histogram name is ignored, when the name is followed by
4133/// binning information as described in the previous paragraph.
4134/// ~~~ {.cpp}
4135/// tree.Draw("sqrt(x)>>+hsqrt","y>0")
4136/// ~~~
4137/// will not reset `hsqrt`, but will continue filling. This works for 1-D, 2-D
4138/// and 3-D histograms.
4139///
4140/// ### Accessing collection objects
4141///
4142/// TTree::Draw default's handling of collections is to assume that any
4143/// request on a collection pertain to it content. For example, if fTracks
4144/// is a collection of Track objects, the following:
4145/// ~~~ {.cpp}
4146/// tree->Draw("event.fTracks.fPx");
4147/// ~~~
4148/// will plot the value of fPx for each Track objects inside the collection.
4149/// Also
4150/// ~~~ {.cpp}
4151/// tree->Draw("event.fTracks.size()");
4152/// ~~~
4153/// would plot the result of the member function Track::size() for each
4154/// Track object inside the collection.
4155/// To access information about the collection itself, TTree::Draw support
4156/// the '@' notation. If a variable which points to a collection is prefixed
4157/// or postfixed with '@', the next part of the expression will pertain to
4158/// the collection object. For example:
4159/// ~~~ {.cpp}
4160/// tree->Draw("event.@fTracks.size()");
4161/// ~~~
4162/// will plot the size of the collection referred to by `fTracks` (i.e the number
4163/// of Track objects).
4164///
4165/// ### Drawing 'objects'
4166///
4167/// When a class has a member function named AsDouble or AsString, requesting
4168/// to directly draw the object will imply a call to one of the 2 functions.
4169/// If both AsDouble and AsString are present, AsDouble will be used.
4170/// AsString can return either a char*, a std::string or a TString.s
4171/// For example, the following
4172/// ~~~ {.cpp}
4173/// tree->Draw("event.myTTimeStamp");
4174/// ~~~
4175/// will draw the same histogram as
4176/// ~~~ {.cpp}
4177/// tree->Draw("event.myTTimeStamp.AsDouble()");
4178/// ~~~
4179/// In addition, when the object is a type TString or std::string, TTree::Draw
4180/// will call respectively `TString::Data` and `std::string::c_str()`
4181///
4182/// If the object is a TBits, the histogram will contain the index of the bit
4183/// that are turned on.
4184///
4185/// ### Retrieving information about the tree itself.
4186///
4187/// You can refer to the tree (or chain) containing the data by using the
4188/// string 'This'.
4189/// You can then could any TTree methods. For example:
4190/// ~~~ {.cpp}
4191/// tree->Draw("This->GetReadEntry()");
4192/// ~~~
4193/// will display the local entry numbers be read.
4194/// ~~~ {.cpp}
4195/// tree->Draw("This->GetUserInfo()->At(0)->GetName()");
4196/// ~~~
4197/// will display the name of the first 'user info' object.
4198///
4199/// ### Special functions and variables
4200///
4201/// `Entry$`: A TTree::Draw formula can use the special variable `Entry$`
4202/// to access the entry number being read. For example to draw every
4203/// other entry use:
4204/// ~~~ {.cpp}
4205/// tree.Draw("myvar","Entry$%2==0");
4206/// ~~~
4207/// - `Entry$` : return the current entry number (`== TTree::GetReadEntry()`)
4208/// - `LocalEntry$` : return the current entry number in the current tree of a
4209/// chain (`== GetTree()->GetReadEntry()`)
4210/// - `Entries$` : return the total number of entries (== TTree::GetEntries())
4211/// - `LocalEntries$` : return the total number of entries in the current tree
4212/// of a chain (== GetTree()->TTree::GetEntries())
4213/// - `Length$` : return the total number of element of this formula for this
4214/// entry (`==TTreeFormula::GetNdata()`)
4215/// - `Iteration$` : return the current iteration over this formula for this
4216/// entry (i.e. varies from 0 to `Length$`).
4217/// - `Length$(formula )` : return the total number of element of the formula
4218/// given as a parameter.
4219/// - `Sum$(formula )` : return the sum of the value of the elements of the
4220/// formula given as a parameter. For example the mean for all the elements in
4221/// one entry can be calculated with: `Sum$(formula )/Length$(formula )`
4222/// - `Min$(formula )` : return the minimum (within one TTree entry) of the value of the
4223/// elements of the formula given as a parameter.
4224/// - `Max$(formula )` : return the maximum (within one TTree entry) of the value of the
4225/// elements of the formula given as a parameter.
4226/// - `MinIf$(formula,condition)`
4227/// - `MaxIf$(formula,condition)` : return the minimum (maximum) (within one TTree entry)
4228/// of the value of the elements of the formula given as a parameter
4229/// if they match the condition. If no element matches the condition,
4230/// the result is zero. To avoid the resulting peak at zero, use the
4231/// pattern:
4232/// ~~~ {.cpp}
4233/// tree->Draw("MinIf$(formula,condition)","condition");
4234/// ~~~
4235/// which will avoid calculation `MinIf$` for the entries that have no match
4236/// for the condition.
4237/// - `Alt$(primary,alternate)` : return the value of "primary" if it is available
4238/// for the current iteration otherwise return the value of "alternate".
4239/// For example, with arr1[3] and arr2[2]
4240/// ~~~ {.cpp}
4241/// tree->Draw("arr1+Alt$(arr2,0)");
4242/// ~~~
4243/// will draw arr1[0]+arr2[0] ; arr1[1]+arr2[1] and arr1[2]+0
4244/// Or with a variable size array arr3
4245/// ~~~ {.cpp}
4246/// tree->Draw("Alt$(arr3[0],0)+Alt$(arr3[1],0)+Alt$(arr3[2],0)");
4247/// ~~~
4248/// will draw the sum arr3 for the index 0 to min(2,actual_size_of_arr3-1)
4249/// As a comparison
4250/// ~~~ {.cpp}
4251/// tree->Draw("arr3[0]+arr3[1]+arr3[2]");
4252/// ~~~
4253/// will draw the sum arr3 for the index 0 to 2 only if the
4254/// actual_size_of_arr3 is greater or equal to 3.
4255/// Note that the array in 'primary' is flattened/linearized thus using
4256/// `Alt$` with multi-dimensional arrays of different dimensions in unlikely
4257/// to yield the expected results. To visualize a bit more what elements
4258/// would be matched by TTree::Draw, TTree::Scan can be used:
4259/// ~~~ {.cpp}
4260/// tree->Scan("arr1:Alt$(arr2,0)");
4261/// ~~~
4262/// will print on one line the value of arr1 and (arr2,0) that will be
4263/// matched by
4264/// ~~~ {.cpp}
4265/// tree->Draw("arr1-Alt$(arr2,0)");
4266/// ~~~
4267/// The ternary operator is not directly supported in TTree::Draw however, to plot the
4268/// equivalent of `var2<20 ? -99 : var1`, you can use:
4269/// ~~~ {.cpp}
4270/// tree->Draw("(var2<20)*99+(var2>=20)*var1","");
4271/// ~~~
4272///
4273/// ### Drawing a user function accessing the TTree data directly
4274///
4275/// If the formula contains a file name, TTree::MakeProxy will be used
4276/// to load and execute this file. In particular it will draw the
4277/// result of a function with the same name as the file. The function
4278/// will be executed in a context where the name of the branches can
4279/// be used as a C++ variable.
4280///
4281/// For example draw px using the file hsimple.root (generated by the
4282/// hsimple.C tutorial), we need a file named hsimple.cxx:
4283/// ~~~ {.cpp}
4284/// double hsimple() {
4285/// return px;
4286/// }
4287/// ~~~
4288/// MakeProxy can then be used indirectly via the TTree::Draw interface
4289/// as follow:
4290/// ~~~ {.cpp}
4291/// new TFile("hsimple.root")
4292/// ntuple->Draw("hsimple.cxx");
4293/// ~~~
4294/// A more complete example is available in the tutorials directory:
4295/// `h1analysisProxy.cxx`, `h1analysProxy.h` and `h1analysisProxyCut.C`
4296/// which reimplement the selector found in `h1analysis.C`
4297///
4298/// The main features of this facility are:
4299///
4300/// * on-demand loading of branches
4301/// * ability to use the 'branchname' as if it was a data member
4302/// * protection against array out-of-bound
4303/// * ability to use the branch data as object (when the user code is available)
4304///
4305/// See TTree::MakeProxy for more details.
4306///
4307/// ### Making a Profile histogram
4308///
4309/// In case of a 2-Dim expression, one can generate a TProfile histogram
4310/// instead of a TH2F histogram by specifying option=prof or option=profs
4311/// or option=profi or option=profg ; the trailing letter select the way
4312/// the bin error are computed, See TProfile2D::SetErrorOption for
4313/// details on the differences.
4314/// The option=prof is automatically selected in case of y:x>>pf
4315/// where pf is an existing TProfile histogram.
4316///
4317/// ### Making a 2D Profile histogram
4318///
4319/// In case of a 3-Dim expression, one can generate a TProfile2D histogram
4320/// instead of a TH3F histogram by specifying option=prof or option=profs.
4321/// or option=profi or option=profg ; the trailing letter select the way
4322/// the bin error are computed, See TProfile2D::SetErrorOption for
4323/// details on the differences.
4324/// The option=prof is automatically selected in case of z:y:x>>pf
4325/// where pf is an existing TProfile2D histogram.
4326///
4327/// ### Making a 5D plot using GL
4328///
4329/// If option GL5D is specified together with 5 variables, a 5D plot is drawn
4330/// using OpenGL. See $ROOTSYS/tutorials/io/tree/tree502_staff.C as example.
4331///
4332/// ### Making a parallel coordinates plot
4333///
4334/// In case of a 2-Dim or more expression with the option=para, one can generate
4335/// a parallel coordinates plot. With that option, the number of dimensions is
4336/// arbitrary. Giving more than 4 variables without the option=para or
4337/// option=candle or option=goff will produce an error.
4338///
4339/// ### Making a candle sticks chart
4340///
4341/// In case of a 2-Dim or more expression with the option=candle, one can generate
4342/// a candle sticks chart. With that option, the number of dimensions is
4343/// arbitrary. Giving more than 4 variables without the option=para or
4344/// option=candle or option=goff will produce an error.
4345///
4346/// ### Normalizing the output histogram to 1
4347///
4348/// When option contains "norm" the output histogram is normalized to 1.
4349///
4350/// ### Saving the result of Draw to a TEventList, a TEntryList or a TEntryListArray
4351///
4352/// TTree::Draw can be used to fill a TEventList object (list of entry numbers)
4353/// instead of histogramming one variable.
4354/// If varexp0 has the form >>elist , a TEventList object named "elist"
4355/// is created in the current directory. elist will contain the list
4356/// of entry numbers satisfying the current selection.
4357/// If option "entrylist" is used, a TEntryList object is created
4358/// If the selection contains arrays, vectors or any container class and option
4359/// "entrylistarray" is used, a TEntryListArray object is created
4360/// containing also the subentries satisfying the selection, i.e. the indices of
4361/// the branches which hold containers classes.
4362/// Example:
4363/// ~~~ {.cpp}
4364/// tree.Draw(">>yplus","y>0")
4365/// ~~~
4366/// will create a TEventList object named "yplus" in the current directory.
4367/// In an interactive session, one can type (after TTree::Draw)
4368/// ~~~ {.cpp}
4369/// yplus.Print("all")
4370/// ~~~
4371/// to print the list of entry numbers in the list.
4372/// ~~~ {.cpp}
4373/// tree.Draw(">>yplus", "y>0", "entrylist")
4374/// ~~~
4375/// will create a TEntryList object names "yplus" in the current directory
4376/// ~~~ {.cpp}
4377/// tree.Draw(">>yplus", "y>0", "entrylistarray")
4378/// ~~~
4379/// will create a TEntryListArray object names "yplus" in the current directory
4380///
4381/// By default, the specified entry list is reset.
4382/// To continue to append data to an existing list, use "+" in front
4383/// of the list name;
4384/// ~~~ {.cpp}
4385/// tree.Draw(">>+yplus","y>0")
4386/// ~~~
4387/// will not reset yplus, but will enter the selected entries at the end
4388/// of the existing list.
4389///
4390/// ### Using a TEventList, TEntryList or TEntryListArray as Input
4391///
4392/// Once a TEventList or a TEntryList object has been generated, it can be used as input
4393/// for TTree::Draw. Use TTree::SetEventList or TTree::SetEntryList to set the
4394/// current event list
4395///
4396/// Example 1:
4397/// ~~~ {.cpp}
4398/// TEventList *elist = (TEventList*)gDirectory->Get("yplus");
4399/// tree->SetEventList(elist);
4400/// tree->Draw("py");
4401/// ~~~
4402/// Example 2:
4403/// ~~~ {.cpp}
4404/// TEntryList *elist = (TEntryList*)gDirectory->Get("yplus");
4405/// tree->SetEntryList(elist);
4406/// tree->Draw("py");
4407/// ~~~
4408/// If a TEventList object is used as input, a new TEntryList object is created
4409/// inside the SetEventList function. In case of a TChain, all tree headers are loaded
4410/// for this transformation. This new object is owned by the chain and is deleted
4411/// with it, unless the user extracts it by calling GetEntryList() function.
4412/// See also comments to SetEventList() function of TTree and TChain.
4413///
4414/// If arrays are used in the selection criteria and TEntryListArray is not used,
4415/// all the entries that have at least one element of the array that satisfy the selection
4416/// are entered in the list.
4417///
4418/// Example:
4419/// ~~~ {.cpp}
4420/// tree.Draw(">>pyplus","fTracks.fPy>0");
4421/// tree->SetEventList(pyplus);
4422/// tree->Draw("fTracks.fPy");
4423/// ~~~
4424/// will draw the fPy of ALL tracks in event with at least one track with
4425/// a positive fPy.
4426///
4427/// To select only the elements that did match the original selection
4428/// use TEventList::SetReapplyCut or TEntryList::SetReapplyCut.
4429///
4430/// Example:
4431/// ~~~ {.cpp}
4432/// tree.Draw(">>pyplus","fTracks.fPy>0");
4433/// pyplus->SetReapplyCut(true);
4434/// tree->SetEventList(pyplus);
4435/// tree->Draw("fTracks.fPy");
4436/// ~~~
4437/// will draw the fPy of only the tracks that have a positive fPy.
4438///
4439/// To draw only the elements that match a selection in case of arrays,
4440/// you can also use TEntryListArray (faster in case of a more general selection).
4441///
4442/// Example:
4443/// ~~~ {.cpp}
4444/// tree.Draw(">>pyplus","fTracks.fPy>0", "entrylistarray");
4445/// tree->SetEntryList(pyplus);
4446/// tree->Draw("fTracks.fPy");
4447/// ~~~
4448/// will draw the fPy of only the tracks that have a positive fPy,
4449/// but without redoing the selection.
4450///
4451/// Note: Use tree->SetEventList(0) if you do not want use the list as input.
4452///
4453/// ### How to obtain more info from TTree::Draw
4454///
4455/// Once TTree::Draw has been called, it is possible to access useful
4456/// information still stored in the TTree object via the following functions:
4457///
4458/// - GetSelectedRows() // return the number of values accepted by the selection expression. In case where no selection was specified, returns the number of values processed.
4459/// - GetV1() // returns a pointer to the double array of V1
4460/// - GetV2() // returns a pointer to the double array of V2
4461/// - GetV3() // returns a pointer to the double array of V3
4462/// - GetV4() // returns a pointer to the double array of V4
4463/// - GetW() // returns a pointer to the double array of Weights where weight equal the result of the selection expression.
4464///
4465/// where V1,V2,V3 correspond to the expressions in
4466/// ~~~ {.cpp}
4467/// TTree::Draw("V1:V2:V3:V4",selection);
4468/// ~~~
4469/// If the expression has more than 4 component use GetVal(index)
4470///
4471/// Example:
4472/// ~~~ {.cpp}
4473/// Root > ntuple->Draw("py:px","pz>4");
4474/// Root > TGraph *gr = new TGraph(ntuple->GetSelectedRows(),
4475/// ntuple->GetV2(), ntuple->GetV1());
4476/// Root > gr->Draw("ap"); //draw graph in current pad
4477/// ~~~
4478///
4479/// A more complete complete tutorial (treegetval.C) shows how to use the
4480/// GetVal() method.
4481///
4482/// creates a TGraph object with a number of points corresponding to the
4483/// number of entries selected by the expression "pz>4", the x points of the graph
4484/// being the px values of the Tree and the y points the py values.
4485///
4486/// Important note: By default TTree::Draw creates the arrays obtained
4487/// with GetW, GetV1, GetV2, GetV3, GetV4, GetVal with a length corresponding
4488/// to the parameter fEstimate. The content will be the last `GetSelectedRows() % GetEstimate()`
4489/// values calculated.
4490/// By default fEstimate=1000000 and can be modified
4491/// via TTree::SetEstimate. To keep in memory all the results (in case
4492/// where there is only one result per entry), use
4493/// ~~~ {.cpp}
4494/// tree->SetEstimate(tree->GetEntries()+1); // same as tree->SetEstimate(-1);
4495/// ~~~
4496/// You must call SetEstimate if the expected number of selected rows
4497/// you need to look at is greater than 1000000.
4498///
4499/// You can use the option "goff" to turn off the graphics output
4500/// of TTree::Draw in the above example.
4501///
4502/// ### Automatic interface to TTree::Draw via the TTreeViewer
4503///
4504/// A complete graphical interface to this function is implemented
4505/// in the class TTreeViewer.
4506/// To start the TTreeViewer, three possibilities:
4507/// - select TTree context menu item "StartViewer"
4508/// - type the command "TTreeViewer TV(treeName)"
4509/// - execute statement "tree->StartViewer();"
4512{
4513 GetPlayer();
4514 if (fPlayer)
4516 return -1;
4517}
4518
4519////////////////////////////////////////////////////////////////////////////////
4520/// Remove some baskets from memory.
4522void TTree::DropBaskets()
4523{
4524 TBranch* branch = nullptr;
4526 for (Int_t i = 0; i < nb; ++i) {
4528 branch->DropBaskets("all");
4529 }
4530}
4531
4532////////////////////////////////////////////////////////////////////////////////
4533/// Drop branch buffers to accommodate nbytes below MaxVirtualsize.
4536{
4537 // Be careful not to remove current read/write buffers.
4539 for (Int_t i = 0; i < nleaves; ++i) {
4541 TBranch* branch = (TBranch*) leaf->GetBranch();
4542 Int_t nbaskets = branch->GetListOfBaskets()->GetEntries();
4543 for (Int_t j = 0; j < nbaskets - 1; ++j) {
4544 if ((j == branch->GetReadBasket()) || (j == branch->GetWriteBasket())) {
4545 continue;
4546 }
4547 TBasket* basket = (TBasket*)branch->GetListOfBaskets()->UncheckedAt(j);
4548 if (basket) {
4549 basket->DropBuffers();
4551 return;
4552 }
4553 }
4554 }
4555 }
4556}
4557
4558////////////////////////////////////////////////////////////////////////////////
4559/// Fill all branches.
4560///
4561/// This function loops on all the branches of this tree. For
4562/// each branch, it copies to the branch buffer (basket) the current
4563/// values of the leaves data types. If a leaf is a simple data type,
4564/// a simple conversion to a machine independent format has to be done.
4565///
4566/// This machine independent version of the data is copied into a
4567/// basket (each branch has its own basket). When a basket is full
4568/// (32k worth of data by default), it is then optionally compressed
4569/// and written to disk (this operation is also called committing or
4570/// 'flushing' the basket). The committed baskets are then
4571/// immediately removed from memory.
4572///
4573/// The function returns the number of bytes committed to the
4574/// individual branches.
4575///
4576/// If a write error occurs, the number of bytes returned is -1.
4577///
4578/// If no data are written, because, e.g., the branch is disabled,
4579/// the number of bytes returned is 0.
4580///
4581/// __The baskets are flushed and the Tree header saved at regular intervals__
4582///
4583/// At regular intervals, when the amount of data written so far is
4584/// greater than fAutoFlush (see SetAutoFlush) all the baskets are flushed to disk.
4585/// This makes future reading faster as it guarantees that baskets belonging to nearby
4586/// entries will be on the same disk region.
4587/// When the first call to flush the baskets happen, we also take this opportunity
4588/// to optimize the baskets buffers.
4589/// We also check if the amount of data written is greater than fAutoSave (see SetAutoSave).
4590/// In this case we also write the Tree header. This makes the Tree recoverable up to this point
4591/// in case the program writing the Tree crashes.
4592/// The decisions to FlushBaskets and Auto Save can be made based either on the number
4593/// of bytes written (fAutoFlush and fAutoSave negative) or on the number of entries
4594/// written (fAutoFlush and fAutoSave positive).
4595/// Note that the user can decide to call FlushBaskets and AutoSave in her event loop
4596/// base on the number of events written instead of the number of bytes written.
4597///
4598/// \note Calling `TTree::FlushBaskets` too often increases the IO time.
4599///
4600/// \note Calling `TTree::AutoSave` too often increases the IO time and also the
4601/// file size.
4602///
4603/// \note This method calls `TTree::ChangeFile` when the tree reaches a size
4604/// greater than `TTree::fgMaxTreeSize`. This doesn't happen if the tree is
4605/// attached to a `TMemFile` or derivate.
4608{
4609 Int_t nbytes = 0;
4610 Int_t nwrite = 0;
4611 Int_t nerror = 0;
4613
4614 // Case of one single super branch. Automatically update
4615 // all the branch addresses if a new object was created.
4616 if (nbranches == 1)
4617 ((TBranch *)fBranches.UncheckedAt(0))->UpdateAddress();
4618
4619 if (fBranchRef)
4620 fBranchRef->Clear();
4621
4622#ifdef R__USE_IMT
4625 if (useIMT) {
4626 fIMTFlush = true;
4627 fIMTZipBytes.store(0);
4628 fIMTTotBytes.store(0);
4629 }
4630#endif
4631
4632 for (Int_t i = 0; i < nbranches; ++i) {
4633 // Loop over all branches, filling and accumulating bytes written and error counts.
4635
4636 if (branch->TestBit(kDoNotProcess))
4637 continue;
4638
4639#ifndef R__USE_IMT
4640 nwrite = branch->FillImpl(nullptr);
4641#else
4642 nwrite = branch->FillImpl(useIMT ? &imtHelper : nullptr);
4643#endif
4644 if (nwrite < 0) {
4645 if (nerror < 2) {
4646 Error("Fill", "Failed filling branch:%s.%s, nbytes=%d, entry=%lld\n"
4647 " This error is symptomatic of a Tree created as a memory-resident Tree\n"
4648 " Instead of doing:\n"
4649 " TTree *T = new TTree(...)\n"
4650 " TFile *f = new TFile(...)\n"
4651 " you should do:\n"
4652 " TFile *f = new TFile(...)\n"
4653 " TTree *T = new TTree(...)\n\n",
4654 GetName(), branch->GetName(), nwrite, fEntries + 1);
4655 } else {
4656 Error("Fill", "Failed filling branch:%s.%s, nbytes=%d, entry=%lld", GetName(), branch->GetName(), nwrite,
4657 fEntries + 1);
4658 }
4659 ++nerror;
4660 } else {
4661 nbytes += nwrite;
4662 }
4663 }
4664
4665#ifdef R__USE_IMT
4666 if (fIMTFlush) {
4667 imtHelper.Wait();
4668 fIMTFlush = false;
4669 const_cast<TTree *>(this)->AddTotBytes(fIMTTotBytes);
4670 const_cast<TTree *>(this)->AddZipBytes(fIMTZipBytes);
4671 nbytes += imtHelper.GetNbytes();
4672 nerror += imtHelper.GetNerrors();
4673 }
4674#endif
4675
4676 if (fBranchRef)
4677 fBranchRef->Fill();
4678
4679 ++fEntries;
4680
4681 if (fEntries > fMaxEntries)
4682 KeepCircular();
4683
4684 if (gDebug > 0)
4685 Info("TTree::Fill", " - A: %d %lld %lld %lld %lld %lld %lld \n", nbytes, fEntries, fAutoFlush, fAutoSave,
4687
4688 bool autoFlush = false;
4689 bool autoSave = false;
4690
4691 if (fAutoFlush != 0 || fAutoSave != 0) {
4692 // Is it time to flush or autosave baskets?
4693 if (fFlushedBytes == 0) {
4694 // If fFlushedBytes == 0, it means we never flushed or saved, so
4695 // we need to check if it's time to do it and recompute the values
4696 // of fAutoFlush and fAutoSave in terms of the number of entries.
4697 // Decision can be based initially either on the number of bytes
4698 // or the number of entries written.
4700
4701 if (fAutoFlush)
4703
4704 if (fAutoSave)
4705 autoSave = fAutoSave < 0 ? (zipBytes > -fAutoSave) : fEntries % fAutoSave == 0;
4706
4707 if (autoFlush || autoSave) {
4708 // First call FlushBasket to make sure that fTotBytes is up to date.
4710 autoFlush = false; // avoid auto flushing again later
4711
4712 // When we are in one-basket-per-cluster mode, there is no need to optimize basket:
4713 // they will automatically grow to the size needed for an event cluster (with the basket
4714 // shrinking preventing them from growing too much larger than the actually-used space).
4716 OptimizeBaskets(GetTotBytes(), 1, "");
4717 if (gDebug > 0)
4718 Info("TTree::Fill", "OptimizeBaskets called at entry %lld, fZipBytes=%lld, fFlushedBytes=%lld\n",
4720 }
4722 fAutoFlush = fEntries; // Use test on entries rather than bytes
4723
4724 // subsequently in run
4725 if (fAutoSave < 0) {
4726 // Set fAutoSave to the largest integer multiple of
4727 // fAutoFlush events such that fAutoSave*fFlushedBytes
4728 // < (minus the input value of fAutoSave)
4730 if (zipBytes != 0) {
4732 } else if (totBytes != 0) {
4734 } else {
4736 TTree::Class()->WriteBuffer(b, (TTree *)this);
4737 Long64_t total = b.Length();
4739 }
4740 } else if (fAutoSave > 0) {
4742 }
4743
4744 if (fAutoSave != 0 && fEntries >= fAutoSave)
4745 autoSave = true;
4746
4747 if (gDebug > 0)
4748 Info("TTree::Fill", "First AutoFlush. fAutoFlush = %lld, fAutoSave = %lld\n", fAutoFlush, fAutoSave);
4749 }
4750 } else {
4751 // Check if we need to auto flush
4752 if (fAutoFlush) {
4753 if (fNClusterRange == 0)
4754 autoFlush = fEntries > 1 && fEntries % fAutoFlush == 0;
4755 else
4757 }
4758 // Check if we need to auto save
4759 if (fAutoSave)
4760 autoSave = fEntries % fAutoSave == 0;
4761 }
4762 }
4763
4764 if (autoFlush) {
4766 if (gDebug > 0)
4767 Info("TTree::Fill", "FlushBaskets() called at entry %lld, fZipBytes=%lld, fFlushedBytes=%lld\n", fEntries,
4770 }
4771
4772 if (autoSave) {
4773 AutoSave(); // does not call FlushBasketsImpl() again
4774 if (gDebug > 0)
4775 Info("TTree::Fill", "AutoSave called at entry %lld, fZipBytes=%lld, fSavedBytes=%lld\n", fEntries,
4777 }
4778
4779 // Check that output file is still below the maximum size.
4780 // If above, close the current file and continue on a new file.
4781 // Currently, the automatic change of file is restricted
4782 // to the case where the tree is in the top level directory.
4783 if (fDirectory)
4784 if (TFile *file = fDirectory->GetFile())
4785 if (static_cast<TDirectory *>(file) == fDirectory && (file->GetEND() > fgMaxTreeSize))
4786 ChangeFile(file);
4787
4788 return nerror == 0 ? nbytes : -1;
4789}
4790
4791////////////////////////////////////////////////////////////////////////////////
4792/// Search in the array for a branch matching the branch name,
4793/// with the branch possibly expressed as a 'full' path name (with dots).
4795static TBranch *R__FindBranchHelper(TObjArray *list, const char *branchname) {
4796 if (list==nullptr || branchname == nullptr || branchname[0] == '\0') return nullptr;
4797
4798 Int_t nbranches = list->GetEntries();
4799
4801
4802 for(Int_t index = 0; index < nbranches; ++index) {
4803 TBranch *where = (TBranch*)list->UncheckedAt(index);
4804
4805 const char *name = where->GetName();
4806 UInt_t len = strlen(name);
4807 if (len && name[len-1]==']') {
4808 const char *dim = strchr(name,'[');
4809 if (dim) {
4810 len = dim - name;
4811 }
4812 }
4813 if (brlen == len && strncmp(branchname,name,len)==0) {
4814 return where;
4815 }
4816 TBranch *next = nullptr;
4817 if ((brlen >= len) && (branchname[len] == '.')
4818 && strncmp(name, branchname, len) == 0) {
4819 // The prefix subbranch name match the branch name.
4820
4821 next = where->FindBranch(branchname);
4822 if (!next) {
4823 next = where->FindBranch(branchname+len+1);
4824 }
4825 if (next) return next;
4826 }
4827 const char *dot = strchr((char*)branchname,'.');
4828 if (dot) {
4829 if (len==(size_t)(dot-branchname) &&
4830 strncmp(branchname,name,dot-branchname)==0 ) {
4831 return R__FindBranchHelper(where->GetListOfBranches(),dot+1);
4832 }
4833 }
4834 }
4835 return nullptr;
4836}
4837
4838////////////////////////////////////////////////////////////////////////////////
4839/// Return the branch that correspond to the path 'branchname', which can
4840/// include the name of the tree or the omitted name of the parent branches.
4841/// In case of ambiguity, returns the first match.
4844{
4845 // We already have been visited while recursively looking
4846 // through the friends tree, let return
4848 return nullptr;
4849 }
4850
4851 if (!branchname)
4852 return nullptr;
4853
4854 TBranch* branch = nullptr;
4855 // If the first part of the name match the TTree name, look for the right part in the
4856 // list of branches.
4857 // This will allow the branchname to be preceded by
4858 // the name of this tree.
4859 if (strncmp(fName.Data(),branchname,fName.Length())==0 && branchname[fName.Length()]=='.') {
4861 if (branch) return branch;
4862 }
4863 // If we did not find it, let's try to find the full name in the list of branches.
4865 if (branch) return branch;
4866
4867 // If we still did not find, let's try to find it within each branch assuming it does not the branch name.
4868 TIter next(GetListOfBranches());
4869 while ((branch = (TBranch*) next())) {
4870 TBranch* nestedbranch = branch->FindBranch(branchname);
4871 if (nestedbranch) {
4872 return nestedbranch;
4873 }
4874 }
4875
4876 // Search in list of friends.
4877 if (!fFriends) {
4878 return nullptr;
4879 }
4880 TFriendLock lock(this, kFindBranch);
4882 TFriendElement* fe = nullptr;
4883 while ((fe = (TFriendElement*) nextf())) {
4884 TTree* t = fe->GetTree();
4885 if (!t) {
4886 continue;
4887 }
4888 // If the alias is present replace it with the real name.
4889 const char *subbranch = strstr(branchname, fe->GetName());
4890 if (subbranch != branchname) {
4891 subbranch = nullptr;
4892 }
4893 if (subbranch) {
4894 subbranch += strlen(fe->GetName());
4895 if (*subbranch != '.') {
4896 subbranch = nullptr;
4897 } else {
4898 ++subbranch;
4899 }
4900 }
4901 std::ostringstream name;
4902 if (subbranch) {
4903 name << t->GetName() << "." << subbranch;
4904 } else {
4905 name << branchname;
4906 }
4907 branch = t->FindBranch(name.str().c_str());
4908 if (branch) {
4909 return branch;
4910 }
4911 }
4912 return nullptr;
4913}
4914
4915////////////////////////////////////////////////////////////////////////////////
4916/// Find leaf..
4918TLeaf* TTree::FindLeaf(const char* searchname)
4919{
4920 if (!searchname)
4921 return nullptr;
4922
4923 // We already have been visited while recursively looking
4924 // through the friends tree, let's return.
4926 return nullptr;
4927 }
4928
4929 // This will allow the branchname to be preceded by
4930 // the name of this tree.
4931 const char* subsearchname = strstr(searchname, GetName());
4932 if (subsearchname != searchname) {
4933 subsearchname = nullptr;
4934 }
4935 if (subsearchname) {
4937 if (*subsearchname != '.') {
4938 subsearchname = nullptr;
4939 } else {
4940 ++subsearchname;
4941 if (subsearchname[0] == 0) {
4942 subsearchname = nullptr;
4943 }
4944 }
4945 }
4946
4951
4952 const bool searchnameHasDot = strchr(searchname, '.') != nullptr;
4953
4954 // For leaves we allow for one level up to be prefixed to the name.
4955 TIter next(GetListOfLeaves());
4956 TLeaf* leaf = nullptr;
4957 while ((leaf = (TLeaf*) next())) {
4958 leafname = leaf->GetName();
4959 Ssiz_t dim = leafname.First('[');
4960 if (dim >= 0) leafname.Remove(dim);
4961
4962 if (leafname == searchname) {
4963 return leaf;
4964 }
4966 return leaf;
4967 }
4968 // The TLeafElement contains the branch name
4969 // in its name, let's use the title.
4970 leaftitle = leaf->GetTitle();
4971 dim = leaftitle.First('[');
4972 if (dim >= 0) leaftitle.Remove(dim);
4973
4974 if (leaftitle == searchname) {
4975 return leaf;
4976 }
4978 return leaf;
4979 }
4980 if (!searchnameHasDot)
4981 continue;
4982 TBranch* branch = leaf->GetBranch();
4983 if (branch) {
4984 longname.Form("%s.%s",branch->GetName(),leafname.Data());
4985 dim = longname.First('[');
4986 if (dim>=0) longname.Remove(dim);
4987 if (longname == searchname) {
4988 return leaf;
4989 }
4991 return leaf;
4992 }
4993 longtitle.Form("%s.%s",branch->GetName(),leaftitle.Data());
4994 dim = longtitle.First('[');
4995 if (dim>=0) longtitle.Remove(dim);
4996 if (longtitle == searchname) {
4997 return leaf;
4998 }
5000 return leaf;
5001 }
5002 // The following is for the case where the branch is only
5003 // a sub-branch. Since we do not see it through
5004 // TTree::GetListOfBranches, we need to see it indirectly.
5005 // This is the less sturdy part of this search ... it may
5006 // need refining ...
5007 if (strstr(searchname, ".") && !strcmp(searchname, branch->GetName())) {
5008 return leaf;
5009 }
5010 if (subsearchname && strstr(subsearchname, ".") && !strcmp(subsearchname, branch->GetName())) {
5011 return leaf;
5012 }
5013 }
5014 }
5015 // Search in list of friends.
5016 if (!fFriends) {
5017 return nullptr;
5018 }
5019 TFriendLock lock(this, kFindLeaf);
5021 TFriendElement* fe = nullptr;
5022 while ((fe = (TFriendElement*) nextf())) {
5023 TTree* t = fe->GetTree();
5024 if (!t) {
5025 continue;
5026 }
5027 // If the alias is present replace it with the real name.
5028 subsearchname = strstr(searchname, fe->GetName());
5029 if (subsearchname != searchname) {
5030 subsearchname = nullptr;
5031 }
5032 if (subsearchname) {
5033 subsearchname += strlen(fe->GetName());
5034 if (*subsearchname != '.') {
5035 subsearchname = nullptr;
5036 } else {
5037 ++subsearchname;
5038 }
5039 }
5040 if (subsearchname) {
5041 leafname.Form("%s.%s",t->GetName(),subsearchname);
5042 } else {
5044 }
5045 leaf = t->FindLeaf(leafname);
5046 if (leaf) {
5047 return leaf;
5048 }
5049 }
5050 return nullptr;
5051}
5052
5053////////////////////////////////////////////////////////////////////////////////
5054/// Fit a projected item(s) from a tree.
5055///
5056/// funcname is a TF1 function.
5057///
5058/// See TTree::Draw() for explanations of the other parameters.
5059///
5060/// By default the temporary histogram created is called htemp.
5061/// If varexp contains >>hnew , the new histogram created is called hnew
5062/// and it is kept in the current directory.
5063///
5064/// The function returns the number of selected entries.
5065///
5066/// Example:
5067/// ~~~ {.cpp}
5068/// tree.Fit(pol4,"sqrt(x)>>hsqrt","y>0")
5069/// ~~~
5070/// will fit sqrt(x) and save the histogram as "hsqrt" in the current
5071/// directory.
5072///
5073/// See also TTree::UnbinnedFit
5074///
5075/// ## Return status
5076///
5077/// The function returns the status of the histogram fit (see TH1::Fit)
5078/// If no entries were selected, the function returns -1;
5079/// (i.e. fitResult is null if the fit is OK)
5082{
5083 GetPlayer();
5084 if (fPlayer) {
5086 }
5087 return -1;
5088}
5089
5090namespace {
5091struct BoolRAIIToggle {
5092 bool &m_val;
5093
5094 BoolRAIIToggle(bool &val) : m_val(val) { m_val = true; }
5095 ~BoolRAIIToggle() { m_val = false; }
5096};
5097}
5098
5099////////////////////////////////////////////////////////////////////////////////
5100/// Write to disk all the basket that have not yet been individually written and
5101/// create an event cluster boundary (by default).
5102///
5103/// If the caller wishes to flush the baskets but not create an event cluster,
5104/// then set create_cluster to false.
5105///
5106/// If ROOT has IMT-mode enabled, this will launch multiple TBB tasks in parallel
5107/// via TThreadExecutor to do this operation; one per basket compression. If the
5108/// caller utilizes TBB also, care must be taken to prevent deadlocks.
5109///
5110/// For example, let's say the caller holds mutex A and calls FlushBaskets; while
5111/// TBB is waiting for the ROOT compression tasks to complete, it may decide to
5112/// run another one of the user's tasks in this thread. If the second user task
5113/// tries to acquire A, then a deadlock will occur. The example call sequence
5114/// looks like this:
5115///
5116/// - User acquires mutex A
5117/// - User calls FlushBaskets.
5118/// - ROOT launches N tasks and calls wait.
5119/// - TBB schedules another user task, T2.
5120/// - T2 tries to acquire mutex A.
5121///
5122/// At this point, the thread will deadlock: the code may function with IMT-mode
5123/// disabled if the user assumed the legacy code never would run their own TBB
5124/// tasks.
5125///
5126/// SO: users of TBB who want to enable IMT-mode should carefully review their
5127/// locking patterns and make sure they hold no coarse-grained application
5128/// locks when they invoke ROOT.
5129///
5130/// Return the number of bytes written or -1 in case of write error.
5132{
5134 if (retval == -1) return retval;
5135
5136 if (create_cluster) const_cast<TTree *>(this)->MarkEventCluster();
5137 return retval;
5138}
5139
5140////////////////////////////////////////////////////////////////////////////////
5141/// Internal implementation of the FlushBaskets algorithm.
5142/// Unlike the public interface, this does NOT create an explicit event cluster
5143/// boundary; it is up to the (internal) caller to determine whether that should
5144/// done.
5145///
5146/// Otherwise, the comments for FlushBaskets applies.
5149{
5150 if (!fDirectory) return 0;
5151 Int_t nbytes = 0;
5152 Int_t nerror = 0;
5153 TObjArray *lb = const_cast<TTree*>(this)->GetListOfBranches();
5154 Int_t nb = lb->GetEntriesFast();
5155
5156#ifdef R__USE_IMT
5158 if (useIMT) {
5159 // ROOT-9668: here we need to check if the size of fSortedBranches is different from the
5160 // size of the list of branches before triggering the initialisation of the fSortedBranches
5161 // container to cover two cases:
5162 // 1. This is the first time we flush. fSortedBranches is empty and we need to fill it.
5163 // 2. We flushed at least once already but a branch has been be added to the tree since then
5164 if (fSortedBranches.size() != unsigned(nb)) { const_cast<TTree*>(this)->InitializeBranchLists(false); }
5165
5166 BoolRAIIToggle sentry(fIMTFlush);
5167 fIMTZipBytes.store(0);
5168 fIMTTotBytes.store(0);
5169 std::atomic<Int_t> nerrpar(0);
5170 std::atomic<Int_t> nbpar(0);
5171 std::atomic<Int_t> pos(0);
5172
5173 auto mapFunction = [&]() {
5174 // The branch to process is obtained when the task starts to run.
5175 // This way, since branches are sorted, we make sure that branches
5176 // leading to big tasks are processed first. If we assigned the
5177 // branch at task creation time, the scheduler would not necessarily
5178 // respect our sorting.
5179 Int_t j = pos.fetch_add(1);
5180
5181 auto branch = fSortedBranches[j].second;
5182 if (R__unlikely(!branch)) { return; }
5183
5184 if (R__unlikely(gDebug > 0)) {
5185 std::stringstream ss;
5186 ss << std::this_thread::get_id();
5187 Info("FlushBaskets", "[IMT] Thread %s", ss.str().c_str());
5188 Info("FlushBaskets", "[IMT] Running task for branch #%d: %s", j, branch->GetName());
5189 }
5190
5191 Int_t nbtask = branch->FlushBaskets();
5192
5193 if (nbtask < 0) { nerrpar++; }
5194 else { nbpar += nbtask; }
5195 };
5196
5198 pool.Foreach(mapFunction, nb);
5199
5200 fIMTFlush = false;
5201 const_cast<TTree*>(this)->AddTotBytes(fIMTTotBytes);
5202 const_cast<TTree*>(this)->AddZipBytes(fIMTZipBytes);
5203
5204 return nerrpar ? -1 : nbpar.load();
5205 }
5206#endif
5207 for (Int_t j = 0; j < nb; j++) {
5208 TBranch* branch = (TBranch*) lb->UncheckedAt(j);
5209 if (branch) {
5210 Int_t nwrite = branch->FlushBaskets();
5211 if (nwrite<0) {
5212 ++nerror;
5213 } else {
5214 nbytes += nwrite;
5215 }
5216 }
5217 }
5218 if (nerror) {
5219 return -1;
5220 } else {
5221 return nbytes;
5222 }
5223}
5224
5225////////////////////////////////////////////////////////////////////////////////
5226/// Returns the expanded value of the alias. Search in the friends if any.
5228const char* TTree::GetAlias(const char* aliasName) const
5229{
5230 // We already have been visited while recursively looking
5231 // through the friends tree, let's return.
5233 return nullptr;
5234 }
5235 if (fAliases) {
5237 if (alias) {
5238 return alias->GetTitle();
5239 }
5240 }
5241 if (!fFriends) {
5242 return nullptr;
5243 }
5244 TFriendLock lock(const_cast<TTree*>(this), kGetAlias);
5246 TFriendElement* fe = nullptr;
5247 while ((fe = (TFriendElement*) nextf())) {
5248 TTree* t = fe->GetTree();
5249 if (t) {
5250 const char* alias = t->GetAlias(aliasName);
5251 if (alias) {
5252 return alias;
5253 }
5254 const char* subAliasName = strstr(aliasName, fe->GetName());
5255 if (subAliasName && (subAliasName[strlen(fe->GetName())] == '.')) {
5256 alias = t->GetAlias(aliasName + strlen(fe->GetName()) + 1);
5257 if (alias) {
5258 return alias;
5259 }
5260 }
5261 }
5262 }
5263 return nullptr;
5264}
5265
5266namespace {
5267/// Do a breadth first search through the implied hierarchy
5268/// of branches.
5269/// To avoid scanning through the list multiple time
5270/// we also remember the 'depth-first' match.
5271TBranch *R__GetBranch(const TObjArray &branches, const char *name)
5272{
5273 TBranch *result = nullptr;
5274 Int_t nb = branches.GetEntriesFast();
5275 for (Int_t i = 0; i < nb; i++) {
5276 TBranch* b = (TBranch*)branches.UncheckedAt(i);
5277 if (!b)
5278 continue;
5279 if (!strcmp(b->GetName(), name)) {
5280 return b;
5281 }
5282 if (!strcmp(b->GetFullName(), name)) {
5283 return b;
5284 }
5285 if (!result)
5286 result = R__GetBranch(*(b->GetListOfBranches()), name);
5287 }
5288 return result;
5289}
5290}
5291
5292////////////////////////////////////////////////////////////////////////////////
5293/// Return pointer to the branch with the given name in this tree or its friends.
5294/// The search is done breadth first.
5296TBranch* TTree::GetBranch(const char* name)
5297{
5298 // We already have been visited while recursively
5299 // looking through the friends tree, let's return.
5301 return nullptr;
5302 }
5303
5304 if (!name)
5305 return nullptr;
5306
5307 // Look for an exact match in the list of top level
5308 // branches.
5310 if (result)
5311 return result;
5312
5313 // Search using branches, breadth first.
5315 if (result)
5316 return result;
5317
5318 // Search using leaves.
5320 Int_t nleaves = leaves->GetEntriesFast();
5321 for (Int_t i = 0; i < nleaves; i++) {
5322 TLeaf* leaf = (TLeaf*) leaves->UncheckedAt(i);
5323 TBranch* branch = leaf->GetBranch();
5324 if (!strcmp(branch->GetName(), name)) {
5325 return branch;
5326 }
5327 if (!strcmp(branch->GetFullName(), name)) {
5328 return branch;
5329 }
5330 }
5331
5332 if (!fFriends) {
5333 return nullptr;
5334 }
5335
5336 // Search in list of friends.
5337 TFriendLock lock(this, kGetBranch);
5338 TIter next(fFriends);
5339 TFriendElement* fe = nullptr;
5340 while ((fe = (TFriendElement*) next())) {
5341 TTree* t = fe->GetTree();
5342 if (t) {
5344 if (branch) {
5345 return branch;
5346 }
5347 }
5348 }
5349
5350 // Second pass in the list of friends when
5351 // the branch name is prefixed by the tree name.
5352 next.Reset();
5353 while ((fe = (TFriendElement*) next())) {
5354 TTree* t = fe->GetTree();
5355 if (!t) {
5356 continue;
5357 }
5358 const char* subname = strstr(name, fe->GetName());
5359 if (subname != name) {
5360 continue;
5361 }
5362 Int_t l = strlen(fe->GetName());
5363 subname += l;
5364 if (*subname != '.') {
5365 continue;
5366 }
5367 subname++;
5369 if (branch) {
5370 return branch;
5371 }
5372 }
5373 return nullptr;
5374}
5375
5376////////////////////////////////////////////////////////////////////////////////
5377/// Return status of branch with name branchname.
5378///
5379/// - 0 if branch is not activated
5380/// - 1 if branch is activated
5382bool TTree::GetBranchStatus(const char* branchname) const
5383{
5384 TBranch* br = const_cast<TTree*>(this)->GetBranch(branchname);
5385 if (br) {
5386 return br->TestBit(kDoNotProcess) == 0;
5387 }
5388 return false;
5389}
5390
5391////////////////////////////////////////////////////////////////////////////////
5392/// Static function returning the current branch style.
5393///
5394/// - style = 0 old Branch
5395/// - style = 1 new Bronch
5400}
5401
5402////////////////////////////////////////////////////////////////////////////////
5403/// Used for automatic sizing of the cache.
5404///
5405/// Estimates a suitable size for the tree cache based on AutoFlush.
5406/// A cache sizing factor is taken from the configuration. If this yields zero
5407/// and withDefault is true the historical algorithm for default size is used.
5409Long64_t TTree::GetCacheAutoSize(bool withDefault /* = false */ )
5410{
5412 {
5413 Long64_t cacheSize = 0;
5414 if (fAutoFlush < 0) {
5415 cacheSize = Long64_t(-cacheFactor * fAutoFlush);
5416 } else if (fAutoFlush == 0) {
5418 if (medianClusterSize > 0)
5419 cacheSize = Long64_t(cacheFactor * 1.5 * medianClusterSize * GetZipBytes() / (fEntries + 1));
5420 else
5421 cacheSize = Long64_t(cacheFactor * 1.5 * 30000000); // use the default value of fAutoFlush
5422 } else {
5423 cacheSize = Long64_t(cacheFactor * 1.5 * fAutoFlush * GetZipBytes() / (fEntries + 1));
5424 }
5425 if (cacheSize >= (INT_MAX / 4)) {
5426 cacheSize = INT_MAX / 4;
5427 }
5428 return cacheSize;
5429 };
5430
5431 const char *stcs;
5432 Double_t cacheFactor = 0.0;
5433 if (!(stcs = gSystem->Getenv("ROOT_TTREECACHE_SIZE")) || !*stcs) {
5434 cacheFactor = gEnv->GetValue("TTreeCache.Size", 1.0);
5435 } else {
5437 }
5438
5439 if (cacheFactor < 0.0) {
5440 // ignore negative factors
5441 cacheFactor = 0.0;
5442 }
5443
5445
5446 if (cacheSize < 0) {
5447 cacheSize = 0;
5448 }
5449
5450 if (cacheSize == 0 && withDefault) {
5451 cacheSize = calculateCacheSize(1.0);
5452 }
5453
5454 return cacheSize;
5455}
5456
5457////////////////////////////////////////////////////////////////////////////////
5458/// Return an iterator over the cluster of baskets starting at firstentry.
5459///
5460/// This iterator is not yet supported for TChain object.
5461/// ~~~ {.cpp}
5462/// TTree::TClusterIterator clusterIter = tree->GetClusterIterator(entry);
5463/// Long64_t clusterStart;
5464/// while( (clusterStart = clusterIter()) < tree->GetEntries() ) {
5465/// printf("The cluster starts at %lld and ends at %lld (inclusive)\n",clusterStart,clusterIter.GetNextEntry()-1);
5466/// }
5467/// ~~~
5470{
5471 // create cache if wanted
5472 if (fCacheDoAutoInit)
5474
5475 return TClusterIterator(this,firstentry);
5476}
5477
5478////////////////////////////////////////////////////////////////////////////////
5479/// Return pointer to the current file.
5482{
5483 if (!fDirectory || fDirectory==gROOT) {
5484 return nullptr;
5485 }
5486 return fDirectory->GetFile();
5487}
5488
5489////////////////////////////////////////////////////////////////////////////////
5490/// Return the number of entries matching the selection.
5491/// Return -1 in case of errors.
5492///
5493/// If the selection uses any arrays or containers, we return the number
5494/// of entries where at least one element match the selection.
5495/// GetEntries is implemented using the selector class TSelectorEntries,
5496/// which can be used directly (see code in TTreePlayer::GetEntries) for
5497/// additional option.
5498/// If SetEventList was used on the TTree or TChain, only that subset
5499/// of entries will be considered.
5502{
5503 GetPlayer();
5504 if (fPlayer) {
5505 return fPlayer->GetEntries(selection);
5506 }
5507 return -1;
5508}
5509
5510////////////////////////////////////////////////////////////////////////////////
5511/// Return pointer to the 1st Leaf named name in any Branch of this Tree or
5512/// any branch in the list of friend trees.
5515{
5516 if (fEntries) return fEntries;
5517 if (!fFriends) return 0;
5519 if (!fr) return 0;
5520 TTree *t = fr->GetTree();
5521 if (t==nullptr) return 0;
5522 return t->GetEntriesFriend();
5523}
5524
5525////////////////////////////////////////////////////////////////////////////////
5526/// Read all branches of entry and return total number of bytes read.
5527///
5528/// - `getall = 0` : get only active branches
5529/// - `getall = 1` : get all branches
5530///
5531/// The function returns the number of bytes read from the input buffer.
5532/// If entry does not exist the function returns 0.
5533/// If an I/O error occurs, the function returns -1.
5534/// If all branches are disabled and getall == 0, it also returns 0
5535/// even if the specified entry exists in the tree, since zero bytes were read.
5536///
5537/// If the Tree has friends, also read the friends entry.
5538///
5539/// To activate/deactivate one or more branches, use TBranch::SetBranchStatus
5540/// For example, if you have a Tree with several hundred branches, and you
5541/// are interested only by branches named "a" and "b", do
5542/// ~~~ {.cpp}
5543/// mytree.SetBranchStatus("*",0); //disable all branches
5544/// mytree.SetBranchStatus("a",1);
5545/// mytree.SetBranchStatus("b",1);
5546/// ~~~
5547/// when calling mytree.GetEntry(i); only branches "a" and "b" will be read.
5548///
5549/// __WARNING!!__
5550/// If your Tree has been created in split mode with a parent branch "parent.",
5551/// ~~~ {.cpp}
5552/// mytree.SetBranchStatus("parent",1);
5553/// ~~~
5554/// will not activate the sub-branches of "parent". You should do:
5555/// ~~~ {.cpp}
5556/// mytree.SetBranchStatus("parent*",1);
5557/// ~~~
5558/// Without the trailing dot in the branch creation you have no choice but to
5559/// call SetBranchStatus explicitly for each of the sub branches.
5560///
5561/// An alternative is to call directly
5562/// ~~~ {.cpp}
5563/// brancha.GetEntry(i)
5564/// branchb.GetEntry(i);
5565/// ~~~
5566/// ## IMPORTANT NOTE
5567///
5568/// By default, GetEntry reuses the space allocated by the previous object
5569/// for each branch. You can force the previous object to be automatically
5570/// deleted if you call mybranch.SetAutoDelete(true) (default is false).
5571///
5572/// Example:
5573///
5574/// Consider the example in $ROOTSYS/test/Event.h
5575/// The top level branch in the tree T is declared with:
5576/// ~~~ {.cpp}
5577/// Event *event = 0; //event must be null or point to a valid object
5578/// //it must be initialized
5579/// T.SetBranchAddress("event",&event);
5580/// ~~~
5581/// When reading the Tree, one can choose one of these 3 options:
5582///
5583/// ## OPTION 1
5584///
5585/// ~~~ {.cpp}
5586/// for (Long64_t i=0;i<nentries;i++) {
5587/// T.GetEntry(i);
5588/// // the object event has been filled at this point
5589/// }
5590/// ~~~
5591/// The default (recommended). At the first entry an object of the class
5592/// Event will be created and pointed by event. At the following entries,
5593/// event will be overwritten by the new data. All internal members that are
5594/// TObject* are automatically deleted. It is important that these members
5595/// be in a valid state when GetEntry is called. Pointers must be correctly
5596/// initialized. However these internal members will not be deleted if the
5597/// characters "->" are specified as the first characters in the comment
5598/// field of the data member declaration.
5599///
5600/// If "->" is specified, the pointer member is read via pointer->Streamer(buf).
5601/// In this case, it is assumed that the pointer is never null (case of
5602/// pointer TClonesArray *fTracks in the Event example). If "->" is not
5603/// specified, the pointer member is read via buf >> pointer. In this case
5604/// the pointer may be null. Note that the option with "->" is faster to
5605/// read or write and it also consumes less space in the file.
5606///
5607/// ## OPTION 2
5608///
5609/// The option AutoDelete is set
5610/// ~~~ {.cpp}
5611/// TBranch *branch = T.GetBranch("event");
5612/// branch->SetAddress(&event);
5613/// branch->SetAutoDelete(true);
5614/// for (Long64_t i=0;i<nentries;i++) {
5615/// T.GetEntry(i);
5616/// // the object event has been filled at this point
5617/// }
5618/// ~~~
5619/// In this case, at each iteration, the object event is deleted by GetEntry
5620/// and a new instance of Event is created and filled.
5621///
5622/// ## OPTION 3
5623///
5624/// ~~~ {.cpp}
5625/// Same as option 1, but you delete yourself the event.
5626///
5627/// for (Long64_t i=0;i<nentries;i++) {
5628/// delete event;
5629/// event = 0; // EXTREMELY IMPORTANT
5630/// T.GetEntry(i);
5631/// // the object event has been filled at this point
5632/// }
5633/// ~~~
5634/// It is strongly recommended to use the default option 1. It has the
5635/// additional advantage that functions like TTree::Draw (internally calling
5636/// TTree::GetEntry) will be functional even when the classes in the file are
5637/// not available.
5638///
5639/// Note: See the comments in TBranchElement::SetAddress() for the
5640/// object ownership policy of the underlying (user) data.
5643{
5644 // We already have been visited while recursively looking
5645 // through the friends tree, let return
5646 if (kGetEntry & fFriendLockStatus) return 0;
5647
5648 if (entry < 0 || entry >= fEntries) return 0;
5649 Int_t i;
5650 Int_t nbytes = 0;
5651 fReadEntry = entry;
5652
5653 // create cache if wanted
5654 if (fCacheDoAutoInit)
5656
5658 Int_t nb=0;
5659
5660 auto seqprocessing = [&]() {
5661 TBranch *branch;
5662 for (i=0;i<nbranches;i++) {
5664 nb = branch->GetEntry(entry, getall);
5665 if (nb < 0) break;
5666 nbytes += nb;
5667 }
5668 };
5669
5670#ifdef R__USE_IMT
5672 if (fSortedBranches.empty())
5674
5675 // Count branches are processed first and sequentially
5676 for (auto branch : fSeqBranches) {
5677 nb = branch->GetEntry(entry, getall);
5678 if (nb < 0) break;
5679 nbytes += nb;
5680 }
5681 if (nb < 0) return nb;
5682
5683 // Enable this IMT use case (activate its locks)
5685
5686 Int_t errnb = 0;
5687 std::atomic<Int_t> pos(0);
5688 std::atomic<Int_t> nbpar(0);
5689
5690 auto mapFunction = [&]() {
5691 // The branch to process is obtained when the task starts to run.
5692 // This way, since branches are sorted, we make sure that branches
5693 // leading to big tasks are processed first. If we assigned the
5694 // branch at task creation time, the scheduler would not necessarily
5695 // respect our sorting.
5696 Int_t j = pos.fetch_add(1);
5697
5698 Int_t nbtask = 0;
5699 auto branch = fSortedBranches[j].second;
5700
5701 if (gDebug > 0) {
5702 std::stringstream ss;
5703 ss << std::this_thread::get_id();
5704 Info("GetEntry", "[IMT] Thread %s", ss.str().c_str());
5705 Info("GetEntry", "[IMT] Running task for branch #%d: %s", j, branch->GetName());
5706 }
5707
5708 std::chrono::time_point<std::chrono::system_clock> start, end;
5709
5710 start = std::chrono::system_clock::now();
5711 nbtask = branch->GetEntry(entry, getall);
5712 end = std::chrono::system_clock::now();
5713
5714 Long64_t tasktime = (Long64_t)std::chrono::duration_cast<std::chrono::microseconds>(end - start).count();
5715 fSortedBranches[j].first += tasktime;
5716
5717 if (nbtask < 0) errnb = nbtask;
5718 else nbpar += nbtask;
5719 };
5720
5722 pool.Foreach(mapFunction, fSortedBranches.size());
5723
5724 if (errnb < 0) {
5725 nb = errnb;
5726 }
5727 else {
5728 // Save the number of bytes read by the tasks
5729 nbytes += nbpar;
5730
5731 // Re-sort branches if necessary
5735 }
5736 }
5737 }
5738 else {
5739 seqprocessing();
5740 }
5741#else
5742 seqprocessing();
5743#endif
5744 if (nb < 0) return nb;
5745
5746 // GetEntry in list of friends
5747 if (!fFriends) return nbytes;
5748 TFriendLock lock(this,kGetEntry);
5751 while ((fe = (TFriendElement*)nextf())) {
5752 TTree *t = fe->GetTree();
5753 if (t) {
5754 if (fe->TestBit(TFriendElement::kFromChain)) {
5755 nb = t->GetEntry(t->GetReadEntry(),getall);
5756 } else {
5757 if ( t->LoadTreeFriend(entry,this) >= 0 ) {
5758 nb = t->GetEntry(t->GetReadEntry(),getall);
5759 } else nb = 0;
5760 }
5761 if (nb < 0) return nb;
5762 nbytes += nb;
5763 }
5764 }
5765 return nbytes;
5766}
5767
5768
5769////////////////////////////////////////////////////////////////////////////////
5770/// Divides the top-level branches into two vectors: (i) branches to be
5771/// processed sequentially and (ii) branches to be processed in parallel.
5772/// Even if IMT is on, some branches might need to be processed first and in a
5773/// sequential fashion: in the parallelization of GetEntry, those are the
5774/// branches that store the size of another branch for every entry
5775/// (e.g. the size of an array branch). If such branches were processed
5776/// in parallel with the rest, there could be two threads invoking
5777/// TBranch::GetEntry on one of them at the same time, since a branch that
5778/// depends on a size (or count) branch will also invoke GetEntry on the latter.
5779/// This method can be invoked several times during the event loop if the TTree
5780/// is being written, for example when adding new branches. In these cases, the
5781/// `checkLeafCount` parameter is false.
5782/// \param[in] checkLeafCount True if we need to check whether some branches are
5783/// count leaves.
5786{
5788
5789 // The special branch fBranchRef needs to be processed sequentially:
5790 // we add it once only.
5791 if (fBranchRef && fBranchRef != fSeqBranches[0]) {
5792 fSeqBranches.push_back(fBranchRef);
5793 }
5794
5795 // The branches to be processed sequentially are those that are the leaf count of another branch
5796 if (checkLeafCount) {
5797 for (Int_t i = 0; i < nbranches; i++) {
5799 auto leafCount = ((TLeaf*)branch->GetListOfLeaves()->At(0))->GetLeafCount();
5800 if (leafCount) {
5801 auto countBranch = leafCount->GetBranch();
5802 if (std::find(fSeqBranches.begin(), fSeqBranches.end(), countBranch) == fSeqBranches.end()) {
5803 fSeqBranches.push_back(countBranch);
5804 }
5805 }
5806 }
5807 }
5808
5809 // Any branch that is not a leaf count can be safely processed in parallel when reading
5810 // We need to reset the vector to make sure we do not re-add several times the same branch.
5811 if (!checkLeafCount) {
5812 fSortedBranches.clear();
5813 }
5814 for (Int_t i = 0; i < nbranches; i++) {
5815 Long64_t bbytes = 0;
5817 if (std::find(fSeqBranches.begin(), fSeqBranches.end(), branch) == fSeqBranches.end()) {
5818 bbytes = branch->GetTotBytes("*");
5819 fSortedBranches.emplace_back(bbytes, branch);
5820 }
5821 }
5822
5823 // Initially sort parallel branches by size
5824 std::sort(fSortedBranches.begin(),
5825 fSortedBranches.end(),
5826 [](std::pair<Long64_t,TBranch*> a, std::pair<Long64_t,TBranch*> b) {
5827 return a.first > b.first;
5828 });
5829
5830 for (size_t i = 0; i < fSortedBranches.size(); i++) {
5831 fSortedBranches[i].first = 0LL;
5832 }
5833}
5834
5835////////////////////////////////////////////////////////////////////////////////
5836/// Sorts top-level branches by the last average task time recorded per branch.
5839{
5840 for (size_t i = 0; i < fSortedBranches.size(); i++) {
5842 }
5843
5844 std::sort(fSortedBranches.begin(),
5845 fSortedBranches.end(),
5846 [](std::pair<Long64_t,TBranch*> a, std::pair<Long64_t,TBranch*> b) {
5847 return a.first > b.first;
5848 });
5849
5850 for (size_t i = 0; i < fSortedBranches.size(); i++) {
5851 fSortedBranches[i].first = 0LL;
5852 }
5853}
5854
5855////////////////////////////////////////////////////////////////////////////////
5856///Returns the entry list assigned to this tree
5859{
5860 return fEntryList;
5861}
5862
5863////////////////////////////////////////////////////////////////////////////////
5864/// Return entry number corresponding to entry.
5865///
5866/// if no TEntryList set returns entry
5867/// else returns the entry number corresponding to the list index=entry
5870{
5871 if (!fEntryList) {
5872 return entry;
5873 }
5874
5875 return fEntryList->GetEntry(entry);
5876}
5877
5878////////////////////////////////////////////////////////////////////////////////
5879/// Return entry number corresponding to major and minor number.
5880/// Note that this function returns only the entry number, not the data
5881/// To read the data corresponding to an entry number, use TTree::GetEntryWithIndex
5882/// the BuildIndex function has created a table of Long64_t* of sorted values
5883/// corresponding to val = major<<31 + minor;
5884/// The function performs binary search in this sorted table.
5885/// If it finds a pair that matches val, it returns directly the
5886/// index in the table.
5887/// If an entry corresponding to major and minor is not found, the function
5888/// returns the index of the major,minor pair immediately lower than the
5889/// requested value, ie it will return -1 if the pair is lower than
5890/// the first entry in the index.
5891///
5892/// See also GetEntryNumberWithIndex
5900}
5901
5902////////////////////////////////////////////////////////////////////////////////
5903/// Return entry number corresponding to major and minor number.
5904/// Note that this function returns only the entry number, not the data
5905/// To read the data corresponding to an entry number, use TTree::GetEntryWithIndex
5906/// the BuildIndex function has created a table of Long64_t* of sorted values
5907/// corresponding to val = major<<31 + minor;
5908/// The function performs binary search in this sorted table.
5909/// If it finds a pair that matches val, it returns directly the
5910/// index in the table, otherwise it returns -1.
5911///
5912/// See also GetEntryNumberWithBestIndex
5915{
5916 if (!fTreeIndex) {
5917 return -1;
5918 }
5920}
5921
5922////////////////////////////////////////////////////////////////////////////////
5923/// Read entry corresponding to major and minor number.
5924///
5925/// The function returns the total number of bytes read.
5926/// If the Tree has friend trees, the corresponding entry with
5927/// the index values (major,minor) is read. Note that the master Tree
5928/// and its friend may have different entry serial numbers corresponding
5929/// to (major,minor).
5932{
5933 // We already have been visited while recursively looking
5934 // through the friends tree, let's return.
5936 return 0;
5937 }
5939 if (serial < 0) {
5940 return -1;
5941 }
5942 // create cache if wanted
5943 if (fCacheDoAutoInit)
5945
5946 Int_t i;
5947 Int_t nbytes = 0;
5948 fReadEntry = serial;
5949 TBranch *branch;
5951 Int_t nb;
5952 for (i = 0; i < nbranches; ++i) {
5954 nb = branch->GetEntry(serial);
5955 if (nb < 0) return nb;
5956 nbytes += nb;
5957 }
5958 // GetEntry in list of friends
5959 if (!fFriends) return nbytes;
5962 TFriendElement* fe = nullptr;
5963 while ((fe = (TFriendElement*) nextf())) {
5964 TTree *t = fe->GetTree();
5965 if (t) {
5966 serial = t->GetEntryNumberWithIndex(major,minor);
5967 if (serial <0) return -nbytes;
5968 nb = t->GetEntry(serial);
5969 if (nb < 0) return nb;
5970 nbytes += nb;
5971 }
5972 }
5973 return nbytes;
5974}
5975
5976////////////////////////////////////////////////////////////////////////////////
5977/// Return a pointer to the TTree friend whose name or alias is `friendname`.
5979TTree* TTree::GetFriend(const char *friendname) const
5980{
5981
5982 // We already have been visited while recursively
5983 // looking through the friends tree, let's return.
5985 return nullptr;
5986 }
5987 if (!fFriends) {
5988 return nullptr;
5989 }
5990 TFriendLock lock(const_cast<TTree*>(this), kGetFriend);
5992 TFriendElement* fe = nullptr;
5993 while ((fe = (TFriendElement*) nextf())) {
5994 if (strcmp(friendname,fe->GetName())==0
5995 || strcmp(friendname,fe->GetTreeName())==0) {
5996 return fe->GetTree();
5997 }
5998 }
5999 // After looking at the first level,
6000 // let's see if it is a friend of friends.
6001 nextf.Reset();
6002 fe = nullptr;
6003 while ((fe = (TFriendElement*) nextf())) {
6004 TTree *res = fe->GetTree()->GetFriend(friendname);
6005 if (res) {
6006 return res;
6007 }
6008 }
6009 return nullptr;
6010}
6011
6012////////////////////////////////////////////////////////////////////////////////
6013/// If the 'tree' is a friend, this method returns its alias name.
6014///
6015/// This alias is an alternate name for the tree.
6016///
6017/// It can be used in conjunction with a branch or leaf name in a TTreeFormula,
6018/// to specify in which particular tree the branch or leaf can be found if
6019/// the friend trees have branches or leaves with the same name as the master
6020/// tree.
6021///
6022/// It can also be used in conjunction with an alias created using
6023/// TTree::SetAlias in a TTreeFormula, e.g.:
6024/// ~~~ {.cpp}
6025/// maintree->Draw("treealias.fPx - treealias.myAlias");
6026/// ~~~
6027/// where fPx is a branch of the friend tree aliased as 'treealias' and 'myAlias'
6028/// was created using TTree::SetAlias on the friend tree.
6029///
6030/// However, note that 'treealias.myAlias' will be expanded literally,
6031/// without remembering that it comes from the aliased friend and thus
6032/// the branch name might not be disambiguated properly, which means
6033/// that you may not be able to take advantage of this feature.
6034///
6036const char* TTree::GetFriendAlias(TTree* tree) const
6037{
6038 if ((tree == this) || (tree == GetTree())) {
6039 return nullptr;
6040 }
6041
6042 // We already have been visited while recursively
6043 // looking through the friends tree, let's return.
6045 return nullptr;
6046 }
6047 if (!fFriends) {
6048 return nullptr;
6049 }
6050 TFriendLock lock(const_cast<TTree*>(this), kGetFriendAlias);
6052 TFriendElement* fe = nullptr;
6053 while ((fe = (TFriendElement*) nextf())) {
6054 TTree* t = fe->GetTree();
6055 if (t == tree) {
6056 return fe->GetName();
6057 }
6058 // Case of a chain:
6059 if (t && t->GetTree() == tree) {
6060 return fe->GetName();
6061 }
6062 }
6063 // After looking at the first level,
6064 // let's see if it is a friend of friends.
6065 nextf.Reset();
6066 fe = nullptr;
6067 while ((fe = (TFriendElement*) nextf())) {
6068 const char* res = fe->GetTree()->GetFriendAlias(tree);
6069 if (res) {
6070 return res;
6071 }
6072 }
6073 return nullptr;
6074}
6075
6076////////////////////////////////////////////////////////////////////////////////
6077/// Returns the current set of IO settings
6079{
6080 return fIOFeatures;
6081}
6082
6083////////////////////////////////////////////////////////////////////////////////
6084/// Creates a new iterator that will go through all the leaves on the tree itself and its friend.
6087{
6088 return new TTreeFriendLeafIter(this, dir);
6089}
6090
6091////////////////////////////////////////////////////////////////////////////////
6092/// Return pointer to the 1st Leaf named name in any Branch of this
6093/// Tree or any branch in the list of friend trees.
6094///
6095/// The leaf name can contain the name of a friend tree with the
6096/// syntax: friend_dir_and_tree.full_leaf_name
6097/// the friend_dir_and_tree can be of the form:
6098/// ~~~ {.cpp}
6099/// TDirectoryName/TreeName
6100/// ~~~
6102TLeaf* TTree::GetLeafImpl(const char* branchname, const char *leafname)
6103{
6104 TLeaf *leaf = nullptr;
6105 if (branchname) {
6107 if (branch) {
6108 leaf = branch->GetLeaf(leafname);
6109 if (leaf) {
6110 return leaf;
6111 }
6112 }
6113 }
6115 while ((leaf = (TLeaf*)nextl())) {
6116 if (strcmp(leaf->GetFullName(), leafname) != 0 && strcmp(leaf->GetName(), leafname) != 0)
6117 continue; // leafname does not match GetName() nor GetFullName(), this is not the right leaf
6118 if (branchname) {
6119 // check the branchname is also a match
6120 TBranch *br = leaf->GetBranch();
6121 // if a quick comparison with the branch full name is a match, we are done
6122 if (!strcmp(br->GetFullName(), branchname))
6123 return leaf;
6125 const char* brname = br->GetName();
6126 TBranch *mother = br->GetMother();
6128 if (mother != br) {
6129 const char *mothername = mother->GetName();
6131 if (!strcmp(mothername, branchname)) {
6132 return leaf;
6133 } else if (nbch > motherlen && strncmp(mothername,branchname,motherlen)==0 && (mothername[motherlen-1]=='.' || branchname[motherlen]=='.')) {
6134 // The left part of the requested name match the name of the mother, let's see if the right part match the name of the branch.
6136 // No it does not
6137 continue;
6138 } // else we have match so we can proceed.
6139 } else {
6140 // no match
6141 continue;
6142 }
6143 } else {
6144 continue;
6145 }
6146 }
6147 // The start of the branch name is identical to the content
6148 // of 'aname' before the first '/'.
6149 // Let's make sure that it is not longer (we are trying
6150 // to avoid having jet2/value match the branch jet23
6151 if ((strlen(brname) > nbch) && (brname[nbch] != '.') && (brname[nbch] != '[')) {
6152 continue;
6153 }
6154 }
6155 return leaf;
6156 }
6157 if (!fFriends) return nullptr;
6158 TFriendLock lock(this,kGetLeaf);
6159 TIter next(fFriends);
6161 while ((fe = (TFriendElement*)next())) {
6162 TTree *t = fe->GetTree();
6163 if (t) {
6165 if (leaf) return leaf;
6166 }
6167 }
6168
6169 //second pass in the list of friends when the leaf name
6170 //is prefixed by the tree name
6172 next.Reset();
6173 while ((fe = (TFriendElement*)next())) {
6174 TTree *t = fe->GetTree();
6175 if (!t) continue;
6176 const char *subname = strstr(leafname,fe->GetName());
6177 if (subname != leafname) continue;
6178 Int_t l = strlen(fe->GetName());
6179 subname += l;
6180 if (*subname != '.') continue;
6181 subname++;
6184 if (leaf) return leaf;
6185 }
6186 return nullptr;
6187}
6188
6189////////////////////////////////////////////////////////////////////////////////
6190/// Return pointer to the 1st Leaf named name in any Branch of this
6191/// Tree or any branch in the list of friend trees.
6192///
6193/// The leaf name can contain the name of a friend tree with the
6194/// syntax: friend_dir_and_tree.full_leaf_name
6195/// the friend_dir_and_tree can be of the form:
6196///
6197/// TDirectoryName/TreeName
6199TLeaf* TTree::GetLeaf(const char* branchname, const char *leafname)
6200{
6201 if (leafname == nullptr) return nullptr;
6202
6203 // We already have been visited while recursively looking
6204 // through the friends tree, let return
6206 return nullptr;
6207 }
6208
6210}
6211
6212////////////////////////////////////////////////////////////////////////////////
6213/// Return pointer to first leaf named "name" in any branch of this
6214/// tree or its friend trees.
6215///
6216/// \param[in] name may be in the form 'branch/leaf'
6217///
6219TLeaf* TTree::GetLeaf(const char *name)
6220{
6221 // Return nullptr if name is invalid or if we have
6222 // already been visited while searching friend trees
6223 if (!name || (kGetLeaf & fFriendLockStatus))
6224 return nullptr;
6225
6226 std::string path(name);
6227 const auto sep = path.find_last_of('/');
6228 if (sep != std::string::npos)
6229 return GetLeafImpl(path.substr(0, sep).c_str(), name+sep+1);
6230
6231 return GetLeafImpl(nullptr, name);
6232}
6233
6234////////////////////////////////////////////////////////////////////////////////
6235/// Return maximum of column with name columname.
6236/// if the Tree has an associated TEventList or TEntryList, the maximum
6237/// is computed for the entries in this list.
6240{
6241 TLeaf* leaf = this->GetLeaf(columname);
6242 if (!leaf) {
6243 return 0;
6244 }
6245
6246 // create cache if wanted
6247 if (fCacheDoAutoInit)
6249
6250 TBranch* branch = leaf->GetBranch();
6252 for (Long64_t i = 0; i < fEntries; ++i) {
6254 if (entryNumber < 0) break;
6255 branch->GetEntry(entryNumber);
6256 for (Int_t j = 0; j < leaf->GetLen(); ++j) {
6257 Double_t val = leaf->GetValue(j);
6258 if (val > cmax) {
6259 cmax = val;
6260 }
6261 }
6262 }
6263 return cmax;
6264}
6265
6266////////////////////////////////////////////////////////////////////////////////
6267/// Static function which returns the tree file size limit in bytes.
6272}
6273
6274////////////////////////////////////////////////////////////////////////////////
6275/// Return minimum of column with name columname.
6276/// if the Tree has an associated TEventList or TEntryList, the minimum
6277/// is computed for the entries in this list.
6280{
6281 TLeaf* leaf = this->GetLeaf(columname);
6282 if (!leaf) {
6283 return 0;
6284 }
6285
6286 // create cache if wanted
6287 if (fCacheDoAutoInit)
6289
6290 TBranch* branch = leaf->GetBranch();
6292 for (Long64_t i = 0; i < fEntries; ++i) {
6294 if (entryNumber < 0) break;
6295 branch->GetEntry(entryNumber);
6296 for (Int_t j = 0;j < leaf->GetLen(); ++j) {
6297 Double_t val = leaf->GetValue(j);
6298 if (val < cmin) {
6299 cmin = val;
6300 }
6301 }
6302 }
6303 return cmin;
6304}
6305
6306////////////////////////////////////////////////////////////////////////////////
6307/// Load the TTreePlayer (if not already done).
6310{
6311 if (fPlayer) {
6312 return fPlayer;
6313 }
6315 return fPlayer;
6316}
6317
6318////////////////////////////////////////////////////////////////////////////////
6319/// Find and return the TTreeCache registered with the file and which may
6320/// contain branches for us.
6323{
6324 TTreeCache *pe = dynamic_cast<TTreeCache*>(file->GetCacheRead(GetTree()));
6325 if (pe && pe->GetTree() != GetTree())
6326 pe = nullptr;
6327 return pe;
6328}
6329
6330////////////////////////////////////////////////////////////////////////////////
6331/// Find and return the TTreeCache registered with the file and which may
6332/// contain branches for us. If create is true and there is no cache
6333/// a new cache is created with default size.
6335TTreeCache *TTree::GetReadCache(TFile *file, bool create)
6336{
6337 TTreeCache *pe = GetReadCache(file);
6338 if (create && !pe) {
6339 if (fCacheDoAutoInit)
6340 SetCacheSizeAux(true, -1);
6341 pe = dynamic_cast<TTreeCache*>(file->GetCacheRead(GetTree()));
6342 if (pe && pe->GetTree() != GetTree()) pe = nullptr;
6343 }
6344 return pe;
6345}
6346
6347////////////////////////////////////////////////////////////////////////////////
6348/// Return a pointer to the list containing user objects associated to this tree.
6349///
6350/// The list is automatically created if it does not exist.
6351///
6352/// WARNING: By default the TTree destructor will delete all objects added
6353/// to this list. If you do not want these objects to be deleted,
6354/// call:
6355///
6356/// mytree->GetUserInfo()->Clear();
6357///
6358/// before deleting the tree.
6361{
6362 if (!fUserInfo) {
6363 fUserInfo = new TList();
6364 fUserInfo->SetName("UserInfo");
6365 }
6366 return fUserInfo;
6367}
6368
6369////////////////////////////////////////////////////////////////////////////////
6370/// Appends the cluster range information stored in 'fromtree' to this tree,
6371/// including the value of fAutoFlush.
6372///
6373/// This is used when doing a fast cloning (by TTreeCloner).
6374/// See also fAutoFlush and fAutoSave if needed.
6377{
6378 Long64_t autoflush = fromtree->GetAutoFlush();
6379 if (fromtree->fNClusterRange == 0 && fromtree->fAutoFlush == fAutoFlush) {
6380 // nothing to do
6381 } else if (fNClusterRange || fromtree->fNClusterRange) {
6382 Int_t newsize = fNClusterRange + 1 + fromtree->fNClusterRange;
6383 if (newsize > fMaxClusterRange) {
6384 if (fMaxClusterRange) {
6386 newsize*sizeof(Long64_t),fMaxClusterRange*sizeof(Long64_t));
6388 newsize*sizeof(Long64_t),fMaxClusterRange*sizeof(Long64_t));
6390 } else {
6394 }
6395 }
6396 if (fEntries) {
6400 }
6401 for (Int_t i = 0 ; i < fromtree->fNClusterRange; ++i) {
6402 fClusterRangeEnd[fNClusterRange] = fEntries + fromtree->fClusterRangeEnd[i];
6403 fClusterSize[fNClusterRange] = fromtree->fClusterSize[i];
6405 }
6407 } else {
6409 }
6411 if (autoflush > 0 && autosave > 0) {
6413 }
6414}
6415
6416////////////////////////////////////////////////////////////////////////////////
6417/// Keep a maximum of fMaxEntries in memory.
6420{
6423 for (Int_t i = 0; i < nb; ++i) {
6425 branch->KeepCircular(maxEntries);
6426 }
6427 if (fNClusterRange) {
6430 for(Int_t i = 0, j = 0; j < oldsize; ++j) {
6433 ++i;
6434 } else {
6436 }
6437 }
6438 }
6440 fReadEntry = -1;
6441}
6442
6443////////////////////////////////////////////////////////////////////////////////
6444/// Read in memory all baskets from all branches up to the limit of maxmemory bytes.
6445///
6446/// If maxmemory is non null and positive SetMaxVirtualSize is called
6447/// with this value. Default for maxmemory is 2000000000 (2 Gigabytes).
6448/// The function returns the total number of baskets read into memory
6449/// if negative an error occurred while loading the branches.
6450/// This method may be called to force branch baskets in memory
6451/// when random access to branch entries is required.
6452/// If random access to only a few branches is required, you should
6453/// call directly TBranch::LoadBaskets.
6456{
6458
6459 TIter next(GetListOfLeaves());
6460 TLeaf *leaf;
6461 Int_t nimported = 0;
6462 while ((leaf=(TLeaf*)next())) {
6463 nimported += leaf->GetBranch()->LoadBaskets();//break;
6464 }
6465 return nimported;
6466}
6467
6468////////////////////////////////////////////////////////////////////////////////
6469/// Set current entry.
6470///
6471/// Returns -2 if entry does not exist (just as TChain::LoadTree()).
6472/// Returns -6 if an error occurs in the notification callback (just as TChain::LoadTree()).
6473///
6474/// Calls fNotify->Notify() (if fNotify is not null) when starting the processing of a new tree.
6475///
6476/// \note This function is overloaded in TChain.
6478{
6479 // We have already been visited while recursively looking
6480 // through the friend trees, let's return
6482 // We need to return a negative value to avoid a circular list of friends
6483 // to think that there is always an entry somewhere in the list.
6484 return -1;
6485 }
6486
6487 // create cache if wanted
6488 if (fCacheDoAutoInit && entry >=0)
6490
6491 if (fNotify) {
6492 if (fReadEntry < 0) {
6493 fNotify->Notify();
6494 }
6495 }
6496 fReadEntry = entry;
6497
6498 bool friendHasEntry = false;
6499 if (fFriends) {
6500 // Set current entry in friends as well.
6501 //
6502 // An alternative would move this code to each of the
6503 // functions calling LoadTree (and to overload a few more).
6504 bool needUpdate = false;
6505 {
6506 // This scope is need to insure the lock is released at the right time
6508 TFriendLock lock(this, kLoadTree);
6509 TFriendElement* fe = nullptr;
6510 while ((fe = (TFriendElement*) nextf())) {
6511 if (fe->TestBit(TFriendElement::kFromChain)) {
6512 // This friend element was added by the chain that owns this
6513 // tree, the chain will deal with loading the correct entry.
6514 continue;
6515 }
6516 TTree* friendTree = fe->GetTree();
6517 if (friendTree) {
6518 if (friendTree->LoadTreeFriend(entry, this) >= 0) {
6519 friendHasEntry = true;
6520 }
6521 }
6522 if (fe->IsUpdated()) {
6523 needUpdate = true;
6524 fe->ResetUpdated();
6525 }
6526 } // for each friend
6527 }
6528 if (needUpdate) {
6529 //update list of leaves in all TTreeFormula of the TTreePlayer (if any)
6530 if (fPlayer) {
6532 }
6533 //Notify user if requested
6534 if (fNotify) {
6535 if(!fNotify->Notify()) return -6;
6536 }
6537 }
6538 }
6539
6540 if ((fReadEntry >= fEntries) && !friendHasEntry) {
6541 fReadEntry = -1;
6542 return -2;
6543 }
6544 return fReadEntry;
6545}
6546
6547////////////////////////////////////////////////////////////////////////////////
6548/// Load entry on behalf of our master tree, we may use an index.
6549///
6550/// Called by LoadTree() when the masterTree looks for the entry
6551/// number in a friend tree (us) corresponding to the passed entry
6552/// number in the masterTree.
6553///
6554/// If we have no index, our entry number and the masterTree entry
6555/// number are the same.
6556///
6557/// If we *do* have an index, we must find the (major, minor) value pair
6558/// in masterTree to locate our corresponding entry.
6559///
6567}
6568
6569////////////////////////////////////////////////////////////////////////////////
6570/// Generate a skeleton analysis class for this tree.
6571///
6572/// The following files are produced: classname.h and classname.C.
6573/// If classname is 0, classname will be called "nameoftree".
6574///
6575/// The generated code in classname.h includes the following:
6576///
6577/// - Identification of the original tree and the input file name.
6578/// - Definition of an analysis class (data members and member functions).
6579/// - The following member functions:
6580/// - constructor (by default opening the tree file),
6581/// - GetEntry(Long64_t entry),
6582/// - Init(TTree* tree) to initialize a new TTree,
6583/// - Show(Long64_t entry) to read and dump entry.
6584///
6585/// The generated code in classname.C includes only the main
6586/// analysis function Loop.
6587///
6588/// To use this function:
6589///
6590/// - Open your tree file (eg: TFile f("myfile.root");)
6591/// - T->MakeClass("MyClass");
6592///
6593/// where T is the name of the TTree in file myfile.root,
6594/// and MyClass.h, MyClass.C the name of the files created by this function.
6595/// In a ROOT session, you can do:
6596/// ~~~ {.cpp}
6597/// root > .L MyClass.C
6598/// root > MyClass* t = new MyClass;
6599/// root > t->GetEntry(12); // Fill data members of t with entry number 12.
6600/// root > t->Show(); // Show values of entry 12.
6601/// root > t->Show(16); // Read and show values of entry 16.
6602/// root > t->Loop(); // Loop on all entries.
6603/// ~~~
6604/// NOTE: Do not use the code generated for a single TTree which is part
6605/// of a TChain to process that entire TChain. The maximum dimensions
6606/// calculated for arrays on the basis of a single TTree from the TChain
6607/// might be (will be!) too small when processing all of the TTrees in
6608/// the TChain. You must use myChain.MakeClass() to generate the code,
6609/// not myTree.MakeClass(...).
6611Int_t TTree::MakeClass(const char* classname, Option_t* option)
6612{
6613 GetPlayer();
6614 if (!fPlayer) {
6615 return 0;
6616 }
6617 return fPlayer->MakeClass(classname, option);
6618}
6619
6620////////////////////////////////////////////////////////////////////////////////
6621/// Generate a skeleton function for this tree.
6622///
6623/// The function code is written on filename.
6624/// If filename is 0, filename will be called nameoftree.C
6625///
6626/// The generated code includes the following:
6627/// - Identification of the original Tree and Input file name,
6628/// - Opening the Tree file,
6629/// - Declaration of Tree variables,
6630/// - Setting of branches addresses,
6631/// - A skeleton for the entry loop.
6632///
6633/// To use this function:
6634///
6635/// - Open your Tree file (eg: TFile f("myfile.root");)
6636/// - T->MakeCode("MyAnalysis.C");
6637///
6638/// where T is the name of the TTree in file myfile.root
6639/// and MyAnalysis.C the name of the file created by this function.
6640///
6641/// NOTE: Since the implementation of this function, a new and better
6642/// function TTree::MakeClass() has been developed.
6644Int_t TTree::MakeCode(const char* filename)
6645{
6646 Warning("MakeCode", "MakeCode is obsolete. Use MakeClass or MakeSelector instead");
6647
6648 GetPlayer();
6649 if (!fPlayer) return 0;
6650 return fPlayer->MakeCode(filename);
6651}
6652
6653////////////////////////////////////////////////////////////////////////////////
6654/// Generate a skeleton analysis class for this Tree using TBranchProxy.
6655///
6656/// TBranchProxy is the base of a class hierarchy implementing an
6657/// indirect access to the content of the branches of a TTree.
6658///
6659/// "proxyClassname" is expected to be of the form:
6660/// ~~~ {.cpp}
6661/// [path/]fileprefix
6662/// ~~~
6663/// The skeleton will then be generated in the file:
6664/// ~~~ {.cpp}
6665/// fileprefix.h
6666/// ~~~
6667/// located in the current directory or in 'path/' if it is specified.
6668/// The class generated will be named 'fileprefix'
6669///
6670/// "macrofilename" and optionally "cutfilename" are expected to point
6671/// to source files which will be included by the generated skeleton.
6672/// Method of the same name as the file(minus the extension and path)
6673/// will be called by the generated skeleton's Process method as follow:
6674/// ~~~ {.cpp}
6675/// [if (cutfilename())] htemp->Fill(macrofilename());
6676/// ~~~
6677/// "option" can be used select some of the optional features during
6678/// the code generation. The possible options are:
6679///
6680/// - nohist : indicates that the generated ProcessFill should not fill the histogram.
6681///
6682/// 'maxUnrolling' controls how deep in the class hierarchy does the
6683/// system 'unroll' classes that are not split. Unrolling a class
6684/// allows direct access to its data members (this emulates the behavior
6685/// of TTreeFormula).
6686///
6687/// The main features of this skeleton are:
6688///
6689/// * on-demand loading of branches
6690/// * ability to use the 'branchname' as if it was a data member
6691/// * protection against array out-of-bounds errors
6692/// * ability to use the branch data as an object (when the user code is available)
6693///
6694/// For example with Event.root, if
6695/// ~~~ {.cpp}
6696/// Double_t somePx = fTracks.fPx[2];
6697/// ~~~
6698/// is executed by one of the method of the skeleton,
6699/// somePx will updated with the current value of fPx of the 3rd track.
6700///
6701/// Both macrofilename and the optional cutfilename are expected to be
6702/// the name of source files which contain at least a free standing
6703/// function with the signature:
6704/// ~~~ {.cpp}
6705/// x_t macrofilename(); // i.e function with the same name as the file
6706/// ~~~
6707/// and
6708/// ~~~ {.cpp}
6709/// y_t cutfilename(); // i.e function with the same name as the file
6710/// ~~~
6711/// x_t and y_t needs to be types that can convert respectively to a double
6712/// and a bool (because the skeleton uses:
6713///
6714/// if (cutfilename()) htemp->Fill(macrofilename());
6715///
6716/// These two functions are run in a context such that the branch names are
6717/// available as local variables of the correct (read-only) type.
6718///
6719/// Note that if you use the same 'variable' twice, it is more efficient
6720/// to 'cache' the value. For example:
6721/// ~~~ {.cpp}
6722/// Int_t n = fEventNumber; // Read fEventNumber
6723/// if (n<10 || n>10) { ... }
6724/// ~~~
6725/// is more efficient than
6726/// ~~~ {.cpp}
6727/// if (fEventNumber<10 || fEventNumber>10)
6728/// ~~~
6729/// Also, optionally, the generated selector will also call methods named
6730/// macrofilename_methodname in each of 6 main selector methods if the method
6731/// macrofilename_methodname exist (Where macrofilename is stripped of its
6732/// extension).
6733///
6734/// Concretely, with the script named h1analysisProxy.C,
6735///
6736/// - The method calls the method (if it exist)
6737/// - Begin -> void h1analysisProxy_Begin(TTree*);
6738/// - SlaveBegin -> void h1analysisProxy_SlaveBegin(TTree*);
6739/// - Notify -> bool h1analysisProxy_Notify();
6740/// - Process -> bool h1analysisProxy_Process(Long64_t);
6741/// - SlaveTerminate -> void h1analysisProxy_SlaveTerminate();
6742/// - Terminate -> void h1analysisProxy_Terminate();
6743///
6744/// If a file name macrofilename.h (or .hh, .hpp, .hxx, .hPP, .hXX) exist
6745/// it is included before the declaration of the proxy class. This can
6746/// be used in particular to insure that the include files needed by
6747/// the macro file are properly loaded.
6748///
6749/// The default histogram is accessible via the variable named 'htemp'.
6750///
6751/// If the library of the classes describing the data in the branch is
6752/// loaded, the skeleton will add the needed `include` statements and
6753/// give the ability to access the object stored in the branches.
6754///
6755/// To draw px using the file hsimple.root (generated by the
6756/// hsimple.C tutorial), we need a file named hsimple.cxx:
6757/// ~~~ {.cpp}
6758/// double hsimple() {
6759/// return px;
6760/// }
6761/// ~~~
6762/// MakeProxy can then be used indirectly via the TTree::Draw interface
6763/// as follow:
6764/// ~~~ {.cpp}
6765/// new TFile("hsimple.root")
6766/// ntuple->Draw("hsimple.cxx");
6767/// ~~~
6768/// A more complete example is available in the tutorials directory:
6769/// h1analysisProxy.cxx , h1analysProxy.h and h1analysisProxyCut.C
6770/// which reimplement the selector found in h1analysis.C
6772Int_t TTree::MakeProxy(const char* proxyClassname, const char* macrofilename, const char* cutfilename, const char* option, Int_t maxUnrolling)
6773{
6774 GetPlayer();
6775 if (!fPlayer) return 0;
6777}
6778
6779////////////////////////////////////////////////////////////////////////////////
6780/// Generate skeleton selector class for this tree.
6781///
6782/// The following files are produced: selector.h and selector.C.
6783/// If selector is 0, the selector will be called "nameoftree".
6784/// The option can be used to specify the branches that will have a data member.
6785/// - If option is "=legacy", a pre-ROOT6 selector will be generated (data
6786/// members and branch pointers instead of TTreeReaders).
6787/// - If option is empty, readers will be generated for each leaf.
6788/// - If option is "@", readers will be generated for the topmost branches.
6789/// - Individual branches can also be picked by their name:
6790/// - "X" generates readers for leaves of X.
6791/// - "@X" generates a reader for X as a whole.
6792/// - "@X;Y" generates a reader for X as a whole and also readers for the
6793/// leaves of Y.
6794/// - For further examples see the figure below.
6795///
6796/// \image html ttree_makeselector_option_examples.png
6797///
6798/// The generated code in selector.h includes the following:
6799/// - Identification of the original Tree and Input file name
6800/// - Definition of selector class (data and functions)
6801/// - The following class functions:
6802/// - constructor and destructor
6803/// - void Begin(TTree *tree)
6804/// - void SlaveBegin(TTree *tree)
6805/// - void Init(TTree *tree)
6806/// - bool Notify()
6807/// - bool Process(Long64_t entry)
6808/// - void Terminate()
6809/// - void SlaveTerminate()
6810///
6811/// The class selector derives from TSelector.
6812/// The generated code in selector.C includes empty functions defined above.
6813///
6814/// To use this function:
6815///
6816/// - connect your Tree file (eg: `TFile f("myfile.root");`)
6817/// - `T->MakeSelector("myselect");`
6818///
6819/// where T is the name of the Tree in file myfile.root
6820/// and myselect.h, myselect.C the name of the files created by this function.
6821/// In a ROOT session, you can do:
6822/// ~~~ {.cpp}
6823/// root > T->Process("myselect.C")
6824/// ~~~
6826Int_t TTree::MakeSelector(const char* selector, Option_t* option)
6827{
6828 TString opt(option);
6829 if(opt.EqualTo("=legacy", TString::ECaseCompare::kIgnoreCase)) {
6830 return MakeClass(selector, "selector");
6831 } else {
6832 GetPlayer();
6833 if (!fPlayer) return 0;
6834 return fPlayer->MakeReader(selector, option);
6835 }
6836}
6837
6838////////////////////////////////////////////////////////////////////////////////
6839/// Check if adding nbytes to memory we are still below MaxVirtualsize.
6842{
6844 return false;
6845 }
6846 return true;
6847}
6848
6849////////////////////////////////////////////////////////////////////////////////
6850/// Static function merging the trees in the TList into a new tree.
6851///
6852/// Trees in the list can be memory or disk-resident trees.
6853/// The new tree is created in the current directory (memory if gROOT).
6854/// Trees with no branches will be skipped, the branch structure
6855/// will be taken from the first non-zero-branch Tree of {li}
6858{
6859 if (!li) return nullptr;
6860 TIter next(li);
6861 TTree *newtree = nullptr;
6862 TObject *obj;
6863
6864 while ((obj=next())) {
6865 if (!obj->InheritsFrom(TTree::Class())) continue;
6866 TTree *tree = (TTree*)obj;
6867 if (tree->GetListOfBranches()->IsEmpty()) {
6868 if (gDebug > 2) {
6869 tree->Warning("MergeTrees","TTree %s has no branches, skipping.", tree->GetName());
6870 }
6871 continue; // Completely ignore the empty trees.
6872 }
6873 Long64_t nentries = tree->GetEntries();
6874 if (newtree && nentries == 0)
6875 continue; // If we already have the structure and we have no entry, save time and skip
6876 if (!newtree) {
6877 newtree = (TTree*)tree->CloneTree(-1, options);
6878 if (!newtree) continue;
6879
6880 // Once the cloning is done, separate the trees,
6881 // to avoid as many side-effects as possible
6882 // The list of clones is guaranteed to exist since we
6883 // just cloned the tree.
6884 tree->GetListOfClones()->Remove(newtree);
6885 tree->ResetBranchAddresses();
6886 newtree->ResetBranchAddresses();
6887 continue;
6888 }
6889 if (nentries == 0)
6890 continue;
6891 newtree->CopyEntries(tree, -1, options, true);
6892 }
6893 if (newtree && newtree->GetTreeIndex()) {
6894 newtree->GetTreeIndex()->Append(nullptr,false); // Force the sorting
6895 }
6896 return newtree;
6897}
6898
6899////////////////////////////////////////////////////////////////////////////////
6900/// Merge the trees in the TList into this tree.
6901///
6902/// Returns the total number of entries in the merged tree.
6903/// Trees with no branches will be skipped, the branch structure
6904/// will be taken from the first non-zero-branch Tree of {this+li}
6907{
6908 if (fBranches.IsEmpty()) {
6909 if (!li || li->IsEmpty())
6910 return 0; // Nothing to do ....
6911 // Let's find the first non-empty
6912 TIter next(li);
6913 TTree *tree;
6914 while ((tree = (TTree *)next())) {
6915 if (tree == this || tree->GetListOfBranches()->IsEmpty()) {
6916 if (gDebug > 2) {
6917 Warning("Merge","TTree %s has no branches, skipping.", tree->GetName());
6918 }
6919 continue;
6920 }
6921 // We could come from a list made up of different names, the first one still wins
6922 tree->SetName(this->GetName());
6923 auto prevEntries = tree->GetEntries();
6924 auto result = tree->Merge(li, options);
6925 if (result != prevEntries) {
6926 // If there is no additional entries, the first write was enough.
6927 tree->Write();
6928 }
6929 // Make sure things are really written out to disk before attempting any reading.
6930 if (tree->GetCurrentFile()) {
6931 tree->GetCurrentFile()->Flush();
6932 // Read back the complete info in this TTree, so that caller does not
6933 // inadvertently write the empty tree.
6934 tree->GetDirectory()->ReadTObject(this, this->GetName());
6935 }
6936 return result;
6937 }
6938 return 0; // All trees have empty branches
6939 }
6940 if (!li) return 0;
6942 // Disable the autosave as the TFileMerge keeps a list of key and deleting the underlying
6943 // key would invalidate its iteration (or require costly measure to not use the deleted keys).
6944 // Also since this is part of a merging operation, the output file is not as precious as in
6945 // the general case since the input file should still be around.
6946 fAutoSave = 0;
6947 TIter next(li);
6948 TTree *tree;
6949 while ((tree = (TTree*)next())) {
6950 if (tree==this) continue;
6951 if (!tree->InheritsFrom(TTree::Class())) {
6952 Error("Add","Attempt to add object of class: %s to a %s", tree->ClassName(), ClassName());
6954 return -1;
6955 }
6956
6957 Long64_t nentries = tree->GetEntries();
6958 if (nentries == 0) continue;
6959
6960 CopyEntries(tree, -1, options, true);
6961 }
6963 return GetEntries();
6964}
6965
6966////////////////////////////////////////////////////////////////////////////////
6967/// Merge the trees in the TList into this tree.
6968/// If info->fIsFirst is true, first we clone this TTree info the directory
6969/// info->fOutputDirectory and then overlay the new TTree information onto
6970/// this TTree object (so that this TTree object is now the appropriate to
6971/// use for further merging).
6972/// Trees with no branches will be skipped, the branch structure
6973/// will be taken from the first non-zero-branch Tree of {this+li}
6974///
6975/// Returns the total number of entries in the merged tree.
6978{
6979 if (fBranches.IsEmpty()) {
6980 if (!li || li->IsEmpty())
6981 return 0; // Nothing to do ....
6982 // Let's find the first non-empty
6983 TIter next(li);
6984 TTree *tree;
6985 while ((tree = (TTree *)next())) {
6986 if (tree == this || tree->GetListOfBranches()->IsEmpty()) {
6987 if (gDebug > 2) {
6988 Warning("Merge","TTree %s has no branches, skipping.", tree->GetName());
6989 }
6990 continue;
6991 }
6992 // We could come from a list made up of different names, the first one still wins
6993 tree->SetName(this->GetName());
6994 auto prevEntries = tree->GetEntries();
6995 auto result = tree->Merge(li, info);
6996 if (result != prevEntries) {
6997 // If there is no additional entries, the first write was enough.
6998 tree->Write();
6999 }
7000 // Make sure things are really written out to disk before attempting any reading.
7001 info->fOutputDirectory->GetFile()->Flush();
7002 // Read back the complete info in this TTree, so that TFileMerge does not
7003 // inadvertently write the empty tree.
7004 info->fOutputDirectory->ReadTObject(this, this->GetName());
7005 return result;
7006 }
7007 return 0; // All trees have empty branches
7008 }
7009 const char *options = info ? info->fOptions.Data() : "";
7010 if (info && info->fIsFirst && info->fOutputDirectory && info->fOutputDirectory->GetFile() != GetCurrentFile()) {
7011 if (GetCurrentFile() == nullptr) {
7012 // In memory TTree, all we need to do is ... write it.
7013 SetDirectory(info->fOutputDirectory);
7015 fDirectory->WriteTObject(this);
7016 } else if (info->fOptions.Contains("fast")) {
7017 InPlaceClone(info->fOutputDirectory);
7018 } else {
7019 TDirectory::TContext ctxt(info->fOutputDirectory);
7021 TTree *newtree = CloneTree(-1, options);
7022 if (info->fIOFeatures)
7023 fIOFeatures = *(info->fIOFeatures);
7024 else
7026 if (newtree) {
7027 newtree->Write();
7028 delete newtree;
7029 }
7030 // Make sure things are really written out to disk before attempting any reading.
7031 info->fOutputDirectory->GetFile()->Flush();
7032 info->fOutputDirectory->ReadTObject(this,this->GetName());
7033 }
7034 }
7035 if (!li) return 0;
7037 // Disable the autosave as the TFileMerge keeps a list of key and deleting the underlying
7038 // key would invalidate its iteration (or require costly measure to not use the deleted keys).
7039 // Also since this is part of a merging operation, the output file is not as precious as in
7040 // the general case since the input file should still be around.
7041 fAutoSave = 0;
7042 TIter next(li);
7043 TTree *tree;
7044 while ((tree = (TTree*)next())) {
7045 if (tree==this) continue;
7046 if (!tree->InheritsFrom(TTree::Class())) {
7047 Error("Add","Attempt to add object of class: %s to a %s", tree->ClassName(), ClassName());
7049 return -1;
7050 }
7051
7052 CopyEntries(tree, -1, options, true);
7053 }
7055 return GetEntries();
7056}
7057
7058////////////////////////////////////////////////////////////////////////////////
7059/// Move a cache from a file to the current file in dir.
7060/// if src is null no operation is done, if dir is null or there is no
7061/// current file the cache is deleted.
7064{
7065 if (!src) return;
7066 TFile *dst = (dir && dir != gROOT) ? dir->GetFile() : nullptr;
7067 if (src == dst) return;
7068
7070 if (dst) {
7071 src->SetCacheRead(nullptr,this);
7072 dst->SetCacheRead(pf, this);
7073 } else {
7074 if (pf) {
7075 pf->WaitFinishPrefetch();
7076 }
7077 src->SetCacheRead(nullptr,this);
7078 delete pf;
7079 }
7080}
7081
7082////////////////////////////////////////////////////////////////////////////////
7083/// Copy the content to a new new file, update this TTree with the new
7084/// location information and attach this TTree to the new directory.
7085///
7086/// options: Indicates a basket sorting method, see TTreeCloner::TTreeCloner for
7087/// details
7088///
7089/// If new and old directory are in the same file, the data is untouched,
7090/// this "just" does a call to SetDirectory.
7091/// Equivalent to an "in place" cloning of the TTree.
7092bool TTree::InPlaceClone(TDirectory *newdirectory, const char *options)
7093{
7094 if (!newdirectory) {
7096 SetDirectory(nullptr);
7097 return true;
7098 }
7099 if (newdirectory->GetFile() == GetCurrentFile()) {
7101 return true;
7102 }
7103 TTreeCloner cloner(this, newdirectory, options);
7104 if (cloner.IsValid())
7105 return cloner.Exec();
7106 else
7107 return false;
7108}
7109
7110////////////////////////////////////////////////////////////////////////////////
7111/// Function called when loading a new class library.
7113bool TTree::Notify()
7114{
7115 TIter next(GetListOfLeaves());
7116 TLeaf* leaf = nullptr;
7117 while ((leaf = (TLeaf*) next())) {
7118 leaf->Notify();
7119 leaf->GetBranch()->Notify();
7120 }
7121 return true;
7122}
7123
7124////////////////////////////////////////////////////////////////////////////////
7125/// This function may be called after having filled some entries in a Tree.
7126/// Using the information in the existing branch buffers, it will reassign
7127/// new branch buffer sizes to optimize time and memory.
7128///
7129/// The function computes the best values for branch buffer sizes such that
7130/// the total buffer sizes is less than maxMemory and nearby entries written
7131/// at the same time.
7132/// In case the branch compression factor for the data written so far is less
7133/// than compMin, the compression is disabled.
7134///
7135/// if option ="d" an analysis report is printed.
7138{
7139 //Flush existing baskets if the file is writable
7140 if (this->GetDirectory()->IsWritable()) this->FlushBasketsImpl();
7141
7142 TString opt( option );
7143 opt.ToLower();
7144 bool pDebug = opt.Contains("d");
7145 TObjArray *leaves = this->GetListOfLeaves();
7146 Int_t nleaves = leaves->GetEntries();
7148
7149 if (nleaves == 0 || treeSize == 0) {
7150 // We're being called too early, we really have nothing to do ...
7151 return;
7152 }
7154 UInt_t bmin = 512;
7155 UInt_t bmax = 256000;
7156 Double_t memFactor = 1;
7159
7160 //we make two passes
7161 //one pass to compute the relative branch buffer sizes
7162 //a second pass to compute the absolute values
7163 for (Int_t pass =0;pass<2;pass++) {
7164 oldMemsize = 0; //to count size of baskets in memory with old buffer size
7165 newMemsize = 0; //to count size of baskets in memory with new buffer size
7166 oldBaskets = 0; //to count number of baskets with old buffer size
7167 newBaskets = 0; //to count number of baskets with new buffer size
7168 for (i=0;i<nleaves;i++) {
7169 TLeaf *leaf = (TLeaf*)leaves->At(i);
7170 TBranch *branch = leaf->GetBranch();
7171 Double_t totBytes = (Double_t)branch->GetTotBytes();
7174 if (branch->GetEntries() == 0) {
7175 // There is no data, so let's make a guess ...
7177 } else {
7178 sizeOfOneEntry = 1+(UInt_t)(totBytes / (Double_t)branch->GetEntries());
7179 }
7180 Int_t oldBsize = branch->GetBasketSize();
7183 Int_t nb = branch->GetListOfBranches()->GetEntries();
7184 if (nb > 0) {
7186 continue;
7187 }
7188 Double_t bsize = oldBsize*idealFactor*memFactor; //bsize can be very large !
7189 if (bsize < 0) bsize = bmax;
7190 if (bsize > bmax) bsize = bmax;
7192 if (pass) { // only on the second pass so that it doesn't interfere with scaling
7193 // If there is an entry offset, it will be stored in the same buffer as the object data; hence,
7194 // we must bump up the size of the branch to account for this extra footprint.
7195 // If fAutoFlush is not set yet, let's assume that it is 'in the process of being set' to
7196 // the value of GetEntries().
7197 Long64_t clusterSize = (fAutoFlush > 0) ? fAutoFlush : branch->GetEntries();
7198 if (branch->GetEntryOffsetLen()) {
7199 newBsize = newBsize + (clusterSize * sizeof(Int_t) * 2);
7200 }
7201 // We used ATLAS fully-split xAOD for testing, which is a rather unbalanced TTree, 10K branches,
7202 // with 8K having baskets smaller than 512 bytes. To achieve good I/O performance ATLAS uses auto-flush 100,
7203 // resulting in the smallest baskets being ~300-400 bytes, so this change increases their memory by about 8k*150B =~ 1MB,
7204 // at the same time it significantly reduces the number of total baskets because it ensures that all 100 entries can be
7205 // stored in a single basket (the old optimization tended to make baskets too small). In a toy example with fixed sized
7206 // structures we found a factor of 2 fewer baskets needed in the new scheme.
7207 // rounds up, increases basket size to ensure all entries fit into single basket as intended
7208 newBsize = newBsize - newBsize%512 + 512;
7209 }
7211 if (newBsize < bmin) newBsize = bmin;
7212 if (newBsize > 10000000) newBsize = bmax;
7213 if (pass) {
7214 if (pDebug) Info("OptimizeBaskets", "Changing buffer size from %6d to %6d bytes for %s\n",oldBsize,newBsize,branch->GetName());
7215 branch->SetBasketSize(newBsize);
7216 }
7218 // For this number to be somewhat accurate when newBsize is 'low'
7219 // we do not include any space for meta data in the requested size (newBsize) even-though SetBasketSize will
7220 // not let it be lower than 100+TBranch::fEntryOffsetLen.
7222 if (pass == 0) continue;
7223 //Reset the compression level in case the compression factor is small
7224 Double_t comp = 1;
7225 if (branch->GetZipBytes() > 0) comp = totBytes/Double_t(branch->GetZipBytes());
7226 if (comp > 1 && comp < minComp) {
7227 if (pDebug) Info("OptimizeBaskets", "Disabling compression for branch : %s\n",branch->GetName());
7229 }
7230 }
7231 // coverity[divide_by_zero] newMemsize can not be zero as there is at least one leaf
7233 if (memFactor > 100) memFactor = 100;
7236 static const UInt_t hardmax = 1*1024*1024*1024; // Really, really never give more than 1Gb to a single buffer.
7237
7238 // Really, really never go lower than 8 bytes (we use this number
7239 // so that the calculation of the number of basket is consistent
7240 // but in fact SetBasketSize will not let the size go below
7241 // TBranch::fEntryOffsetLen + (100 + strlen(branch->GetName())
7242 // (The 2nd part being a slight over estimate of the key length.
7243 static const UInt_t hardmin = 8;
7246 }
7247 if (pDebug) {
7248 Info("OptimizeBaskets", "oldMemsize = %d, newMemsize = %d\n",oldMemsize, newMemsize);
7249 Info("OptimizeBaskets", "oldBaskets = %d, newBaskets = %d\n",oldBaskets, newBaskets);
7250 }
7251}
7252
7253////////////////////////////////////////////////////////////////////////////////
7254/// Interface to the Principal Components Analysis class.
7255///
7256/// Create an instance of TPrincipal
7257///
7258/// Fill it with the selected variables
7259///
7260/// - if option "n" is specified, the TPrincipal object is filled with
7261/// normalized variables.
7262/// - If option "p" is specified, compute the principal components
7263/// - If option "p" and "d" print results of analysis
7264/// - If option "p" and "h" generate standard histograms
7265/// - If option "p" and "c" generate code of conversion functions
7266/// - return a pointer to the TPrincipal object. It is the user responsibility
7267/// - to delete this object.
7268/// - The option default value is "np"
7269///
7270/// see TTree::Draw for explanation of the other parameters.
7271///
7272/// The created object is named "principal" and a reference to it
7273/// is added to the list of specials Root objects.
7274/// you can retrieve a pointer to the created object via:
7275/// ~~~ {.cpp}
7276/// TPrincipal *principal =
7277/// (TPrincipal*)gROOT->GetListOfSpecials()->FindObject("principal");
7278/// ~~~
7281{
7282 GetPlayer();
7283 if (fPlayer) {
7285 }
7286 return nullptr;
7287}
7288
7289////////////////////////////////////////////////////////////////////////////////
7290/// Print a summary of the tree contents.
7291///
7292/// - If option contains "all" friend trees are also printed.
7293/// - If option contains "toponly" only the top level branches are printed.
7294/// - If option contains "clusters" information about the cluster of baskets is printed.
7295///
7296/// Wildcarding can be used to print only a subset of the branches, e.g.,
7297/// `T.Print("Elec*")` will print all branches with name starting with "Elec".
7299void TTree::Print(Option_t* option) const
7300{
7301 // We already have been visited while recursively looking
7302 // through the friends tree, let's return.
7303 if (kPrint & fFriendLockStatus) {
7304 return;
7305 }
7306 Int_t s = 0;
7307 Int_t skey = 0;
7308 if (fDirectory) {
7309 TKey* key = fDirectory->GetKey(GetName());
7310 if (key) {
7311 skey = key->GetKeylen();
7312 s = key->GetNbytes();
7313 }
7314 }
7317 if (zipBytes > 0) {
7318 total += GetTotBytes();
7319 }
7321 TTree::Class()->WriteBuffer(b, (TTree*) this);
7322 total += b.Length();
7323 Long64_t file = zipBytes + s;
7324 Float_t cx = 1;
7325 if (zipBytes) {
7326 cx = (GetTotBytes() + 0.00001) / zipBytes;
7327 }
7328 Printf("******************************************************************************");
7329 Printf("*Tree :%-10s: %-54s *", GetName(), GetTitle());
7330 Printf("*Entries : %8lld : Total = %15lld bytes File Size = %10lld *", fEntries, total, file);
7331 Printf("* : : Tree compression factor = %6.2f *", cx);
7332 Printf("******************************************************************************");
7333
7334 // Avoid many check of option validity
7335 if (!option)
7336 option = "";
7337
7338 if (strncmp(option,"clusters",std::char_traits<char>::length("clusters"))==0) {
7339 Printf("%-16s %-16s %-16s %8s %20s",
7340 "Cluster Range #", "Entry Start", "Last Entry", "Size", "Number of clusters");
7341 Int_t index= 0;
7344 bool estimated = false;
7345 bool unknown = false;
7347 Long64_t nclusters = 0;
7348 if (recordedSize > 0) {
7349 nclusters = TMath::Ceil(static_cast<double>(1 + end - start) / recordedSize);
7350 Printf("%-16d %-16lld %-16lld %8lld %10lld",
7351 ind, start, end, recordedSize, nclusters);
7352 } else {
7353 // NOTE: const_cast ... DO NOT Merge for now
7354 TClusterIterator iter((TTree*)this, start);
7355 iter.Next();
7356 auto estimated_size = iter.GetNextEntry() - start;
7357 if (estimated_size > 0) {
7358 nclusters = TMath::Ceil(static_cast<double>(1 + end - start) / estimated_size);
7359 Printf("%-16d %-16lld %-16lld %8lld %10lld (estimated)",
7360 ind, start, end, recordedSize, nclusters);
7361 estimated = true;
7362 } else {
7363 Printf("%-16d %-16lld %-16lld %8lld (unknown)",
7364 ind, start, end, recordedSize);
7365 unknown = true;
7366 }
7367 }
7368 start = end + 1;
7370 };
7371 if (fNClusterRange) {
7372 for( ; index < fNClusterRange; ++index) {
7375 }
7376 }
7378 if (unknown) {
7379 Printf("Total number of clusters: (unknown)");
7380 } else {
7381 Printf("Total number of clusters: %lld %s", totalClusters, estimated ? "(estimated)" : "");
7382 }
7383 return;
7384 }
7385
7386 Int_t nl = const_cast<TTree*>(this)->GetListOfLeaves()->GetEntries();
7387 Int_t l;
7388 TBranch* br = nullptr;
7389 TLeaf* leaf = nullptr;
7390 if (strstr(option, "toponly")) {
7391 Long64_t *count = new Long64_t[nl];
7392 Int_t keep =0;
7393 for (l=0;l<nl;l++) {
7394 leaf = (TLeaf *)const_cast<TTree*>(this)->GetListOfLeaves()->At(l);
7395 br = leaf->GetBranch();
7396 // branch is its own (top level) mother only for the top level branches.
7397 if (br != br->GetMother()) {
7398 count[l] = -1;
7399 count[keep] += br->GetZipBytes();
7400 } else {
7401 keep = l;
7402 count[keep] = br->GetZipBytes();
7403 }
7404 }
7405 for (l=0;l<nl;l++) {
7406 if (count[l] < 0) continue;
7407 leaf = (TLeaf *)const_cast<TTree*>(this)->GetListOfLeaves()->At(l);
7408 br = leaf->GetBranch();
7409 Printf("branch: %-20s %9lld",br->GetName(),count[l]);
7410 }
7411 delete [] count;
7412 } else {
7413 TString reg = "*";
7414 if (strlen(option) && strchr(option,'*')) reg = option;
7415 TRegexp re(reg,true);
7416 TIter next(const_cast<TTree*>(this)->GetListOfBranches());
7418 while ((br= (TBranch*)next())) {
7419 TString st = br->GetName();
7420 st.ReplaceAll("/","_");
7421 if (st.Index(re) == kNPOS) continue;
7422 br->Print(option);
7423 }
7424 }
7425
7426 //print TRefTable (if one)
7428
7429 //print friends if option "all"
7430 if (!fFriends || !strstr(option,"all")) return;
7432 TFriendLock lock(const_cast<TTree*>(this),kPrint);
7433 TFriendElement *fr;
7434 while ((fr = (TFriendElement*)nextf())) {
7435 TTree * t = fr->GetTree();
7436 if (t) t->Print(option);
7437 }
7438}
7439
7440////////////////////////////////////////////////////////////////////////////////
7441/// Print statistics about the TreeCache for this tree.
7442/// Like:
7443/// ~~~ {.cpp}
7444/// ******TreeCache statistics for file: cms2.root ******
7445/// Reading 73921562 bytes in 716 transactions
7446/// Average transaction = 103.242405 Kbytes
7447/// Number of blocks in current cache: 202, total size : 6001193
7448/// ~~~
7449/// if option = "a" the list of blocks in the cache is printed
7452{
7453 TFile *f = GetCurrentFile();
7454 if (!f) return;
7456 if (tc) tc->Print(option);
7457}
7458
7459////////////////////////////////////////////////////////////////////////////////
7460/// Process this tree executing the TSelector code in the specified filename.
7461/// The return value is -1 in case of error and TSelector::GetStatus() in
7462/// in case of success.
7463///
7464/// The code in filename is loaded (interpreted or compiled, see below),
7465/// filename must contain a valid class implementation derived from TSelector,
7466/// where TSelector has the following member functions:
7467///
7468/// - `Begin()`: called every time a loop on the tree starts,
7469/// a convenient place to create your histograms.
7470/// - `SlaveBegin()`: called after Begin(), when on PROOF called only on the
7471/// slave servers.
7472/// - `Process()`: called for each event, in this function you decide what
7473/// to read and fill your histograms.
7474/// - `SlaveTerminate`: called at the end of the loop on the tree, when on PROOF
7475/// called only on the slave servers.
7476/// - `Terminate()`: called at the end of the loop on the tree,
7477/// a convenient place to draw/fit your histograms.
7478///
7479/// If filename is of the form file.C, the file will be interpreted.
7480///
7481/// If filename is of the form file.C++, the file file.C will be compiled
7482/// and dynamically loaded.
7483///
7484/// If filename is of the form file.C+, the file file.C will be compiled
7485/// and dynamically loaded. At next call, if file.C is older than file.o
7486/// and file.so, the file.C is not compiled, only file.so is loaded.
7487///
7488/// ## NOTE1
7489///
7490/// It may be more interesting to invoke directly the other Process function
7491/// accepting a TSelector* as argument.eg
7492/// ~~~ {.cpp}
7493/// MySelector *selector = (MySelector*)TSelector::GetSelector(filename);
7494/// selector->CallSomeFunction(..);
7495/// mytree.Process(selector,..);
7496/// ~~~
7497/// ## NOTE2
7498//
7499/// One should not call this function twice with the same selector file
7500/// in the same script. If this is required, proceed as indicated in NOTE1,
7501/// by getting a pointer to the corresponding TSelector,eg
7502///
7503/// ### Workaround 1
7504///
7505/// ~~~ {.cpp}
7506/// void stubs1() {
7507/// TSelector *selector = TSelector::GetSelector("h1test.C");
7508/// TFile *f1 = new TFile("stubs_nood_le1.root");
7509/// TTree *h1 = (TTree*)f1->Get("h1");
7510/// h1->Process(selector);
7511/// TFile *f2 = new TFile("stubs_nood_le1_coarse.root");
7512/// TTree *h2 = (TTree*)f2->Get("h1");
7513/// h2->Process(selector);
7514/// }
7515/// ~~~
7516/// or use ACLIC to compile the selector
7517///
7518/// ### Workaround 2
7519///
7520/// ~~~ {.cpp}
7521/// void stubs2() {
7522/// TFile *f1 = new TFile("stubs_nood_le1.root");
7523/// TTree *h1 = (TTree*)f1->Get("h1");
7524/// h1->Process("h1test.C+");
7525/// TFile *f2 = new TFile("stubs_nood_le1_coarse.root");
7526/// TTree *h2 = (TTree*)f2->Get("h1");
7527/// h2->Process("h1test.C+");
7528/// }
7529/// ~~~
7532{
7533 GetPlayer();
7534 if (fPlayer) {
7536 }
7537 return -1;
7538}
7539
7540////////////////////////////////////////////////////////////////////////////////
7541/// Process this tree executing the code in the specified selector.
7542/// The return value is -1 in case of error and TSelector::GetStatus() in
7543/// in case of success.
7544///
7545/// The TSelector class has the following member functions:
7546///
7547/// - `Begin()`: called every time a loop on the tree starts,
7548/// a convenient place to create your histograms.
7549/// - `SlaveBegin()`: called after Begin(), when on PROOF called only on the
7550/// slave servers.
7551/// - `Process()`: called for each event, in this function you decide what
7552/// to read and fill your histograms.
7553/// - `SlaveTerminate`: called at the end of the loop on the tree, when on PROOF
7554/// called only on the slave servers.
7555/// - `Terminate()`: called at the end of the loop on the tree,
7556/// a convenient place to draw/fit your histograms.
7557///
7558/// If the Tree (Chain) has an associated EventList, the loop is on the nentries
7559/// of the EventList, starting at firstentry, otherwise the loop is on the
7560/// specified Tree entries.
7563{
7564 GetPlayer();
7565 if (fPlayer) {
7566 return fPlayer->Process(selector, option, nentries, firstentry);
7567 }
7568 return -1;
7569}
7570
7571////////////////////////////////////////////////////////////////////////////////
7572/// Make a projection of a tree using selections.
7573///
7574/// Depending on the value of varexp (described in Draw) a 1-D, 2-D, etc.,
7575/// projection of the tree will be filled in histogram hname.
7576/// Note that the dimension of hname must match with the dimension of varexp.
7577///
7580{
7581 TString var;
7582 var.Form("%s>>%s", varexp, hname);
7583 TString opt("goff");
7584 if (option) {
7585 opt.Form("%sgoff", option);
7586 }
7588 return nsel;
7589}
7590
7591////////////////////////////////////////////////////////////////////////////////
7592/// Loop over entries and return a TSQLResult object containing entries following selection.
7595{
7596 GetPlayer();
7597 if (fPlayer) {
7599 }
7600 return nullptr;
7601}
7602
7603////////////////////////////////////////////////////////////////////////////////
7604/// Create or simply read branches from filename.
7605///
7606/// if branchDescriptor = "" (default), it is assumed that the Tree descriptor
7607/// is given in the first line of the file with a syntax like
7608/// ~~~ {.cpp}
7609/// A/D:Table[2]/F:Ntracks/I:astring/C
7610/// ~~~
7611/// otherwise branchDescriptor must be specified with the above syntax.
7612///
7613/// - If the type of the first variable is not specified, it is assumed to be "/F"
7614/// - If the type of any other variable is not specified, the type of the previous
7615/// variable is assumed. eg
7616/// - `x:y:z` (all variables are assumed of type "F")
7617/// - `x/D:y:z` (all variables are of type "D")
7618/// - `x:y/D:z` (x is type "F", y and z of type "D")
7619///
7620/// delimiter allows for the use of another delimiter besides whitespace.
7621/// This provides support for direct import of common data file formats
7622/// like csv. If delimiter != ' ' and branchDescriptor == "", then the
7623/// branch description is taken from the first line in the file, but
7624/// delimiter is used for the branch names tokenization rather than ':'.
7625/// Note however that if the values in the first line do not use the
7626/// /[type] syntax, all variables are assumed to be of type "F".
7627/// If the filename ends with extensions .csv or .CSV and a delimiter is
7628/// not specified (besides ' '), the delimiter is automatically set to ','.
7629///
7630/// Lines in the input file starting with "#" are ignored. Leading whitespace
7631/// for each column data is skipped. Empty lines are skipped.
7632///
7633/// A TBranch object is created for each variable in the expression.
7634/// The total number of rows read from the file is returned.
7635///
7636/// ## FILLING a TTree WITH MULTIPLE INPUT TEXT FILES
7637///
7638/// To fill a TTree with multiple input text files, proceed as indicated above
7639/// for the first input file and omit the second argument for subsequent calls
7640/// ~~~ {.cpp}
7641/// T.ReadFile("file1.dat","branch descriptor");
7642/// T.ReadFile("file2.dat");
7643/// ~~~
7645Long64_t TTree::ReadFile(const char* filename, const char* branchDescriptor, char delimiter)
7646{
7647 if (!filename || !*filename) {
7648 Error("ReadFile","File name not specified");
7649 return 0;
7650 }
7651
7652 std::ifstream in;
7653 in.open(filename);
7654 if (!in.good()) {
7655 Error("ReadFile","Cannot open file: %s",filename);
7656 return 0;
7657 }
7658 const char* ext = strrchr(filename, '.');
7659 if(ext && ((strcmp(ext, ".csv") == 0) || (strcmp(ext, ".CSV") == 0)) && delimiter == ' ') {
7660 delimiter = ',';
7661 }
7663}
7664
7665////////////////////////////////////////////////////////////////////////////////
7666/// Determine which newline this file is using.
7667/// Return '\r' for Windows '\r\n' as that already terminates.
7669char TTree::GetNewlineValue(std::istream &inputStream)
7670{
7671 Long_t inPos = inputStream.tellg();
7672 char newline = '\n';
7673 while(true) {
7674 char c = 0;
7675 inputStream.get(c);
7676 if(!inputStream.good()) {
7677 Error("ReadStream","Error reading stream: no newline found.");
7678 return 0;
7679 }
7680 if(c == newline) break;
7681 if(c == '\r') {
7682 newline = '\r';
7683 break;
7684 }
7685 }
7686 inputStream.clear();
7687 inputStream.seekg(inPos);
7688 return newline;
7689}
7690
7691////////////////////////////////////////////////////////////////////////////////
7692/// Create or simply read branches from an input stream.
7693///
7694/// \see TTree::ReadFile
7696Long64_t TTree::ReadStream(std::istream& inputStream, const char *branchDescriptor, char delimiter)
7697{
7698 char newline = 0;
7699 std::stringstream ss;
7700 std::istream *inTemp;
7701 Long_t inPos = inputStream.tellg();
7702 if (!inputStream.good()) {
7703 Error("ReadStream","Error reading stream");
7704 return 0;
7705 }
7706 if (inPos == -1) {
7707 ss << std::cin.rdbuf();
7709 inTemp = &ss;
7710 } else {
7713 }
7714 std::istream& in = *inTemp;
7715 Long64_t nlines = 0;
7716
7717 TBranch *branch = nullptr;
7719 if (nbranches == 0) {
7720 char *bdname = new char[4000];
7721 char *bd = new char[100000];
7722 Int_t nch = 0;
7724 // branch Descriptor is null, read its definition from the first line in the file
7725 if (!nch) {
7726 do {
7727 in.getline(bd, 100000, newline);
7728 if (!in.good()) {
7729 delete [] bdname;
7730 delete [] bd;
7731 Error("ReadStream","Error reading stream");
7732 return 0;
7733 }
7734 char *cursor = bd;
7735 while( isspace(*cursor) && *cursor != '\n' && *cursor != '\0') {
7736 ++cursor;
7737 }
7738 if (*cursor != '#' && *cursor != '\n' && *cursor != '\0') {
7739 break;
7740 }
7741 } while (true);
7742 ++nlines;
7743 nch = strlen(bd);
7744 } else {
7745 strlcpy(bd,branchDescriptor,100000);
7746 }
7747
7748 //parse the branch descriptor and create a branch for each element
7749 //separated by ":"
7750 void *address = &bd[90000];
7751 char *bdcur = bd;
7752 TString desc="", olddesc="F";
7753 char bdelim = ':';
7754 if(delimiter != ' ') {
7755 bdelim = delimiter;
7756 if (strchr(bdcur,bdelim)==nullptr && strchr(bdcur,':') != nullptr) {
7757 // revert to the default
7758 bdelim = ':';
7759 }
7760 }
7761 while (bdcur) {
7762 char *colon = strchr(bdcur,bdelim);
7763 if (colon) *colon = 0;
7764 strlcpy(bdname,bdcur,4000);
7765 char *slash = strchr(bdname,'/');
7766 if (slash) {
7767 *slash = 0;
7768 desc = bdcur;
7769 olddesc = slash+1;
7770 } else {
7771 desc.Form("%s/%s",bdname,olddesc.Data());
7772 }
7773 char *bracket = strchr(bdname,'[');
7774 if (bracket) {
7775 *bracket = 0;
7776 }
7777 branch = new TBranch(this,bdname,address,desc.Data(),32000);
7778 if (branch->IsZombie()) {
7779 delete branch;
7780 Warning("ReadStream","Illegal branch definition: %s",bdcur);
7781 } else {
7783 branch->SetAddress(nullptr);
7784 }
7785 if (!colon)break;
7786 bdcur = colon+1;
7787 }
7788 delete [] bdname;
7789 delete [] bd;
7790 }
7791
7793
7794 if (gDebug > 1) {
7795 Info("ReadStream", "Will use branches:");
7796 for (int i = 0 ; i < nbranches; ++i) {
7797 TBranch* br = (TBranch*) fBranches.At(i);
7798 Info("ReadStream", " %s: %s [%s]", br->GetName(),
7799 br->GetTitle(), br->GetListOfLeaves()->At(0)->IsA()->GetName());
7800 }
7801 if (gDebug > 3) {
7802 Info("ReadStream", "Dumping read tokens, format:");
7803 Info("ReadStream", "LLLLL:BBB:gfbe:GFBE:T");
7804 Info("ReadStream", " L: line number");
7805 Info("ReadStream", " B: branch number");
7806 Info("ReadStream", " gfbe: good / fail / bad / eof of token");
7807 Info("ReadStream", " GFBE: good / fail / bad / eof of file");
7808 Info("ReadStream", " T: Token being read");
7809 }
7810 }
7811
7812 //loop on all lines in the file
7813 Long64_t nGoodLines = 0;
7814 std::string line;
7815 const char sDelimBuf[2] = { delimiter, 0 };
7816 const char* sDelim = sDelimBuf;
7817 if (delimiter == ' ') {
7818 // ' ' really means whitespace
7819 sDelim = "[ \t]";
7820 }
7821 while(in.good()) {
7822 if (newline == '\r' && in.peek() == '\n') {
7823 // Windows, skip '\n':
7824 in.get();
7825 }
7826 std::getline(in, line, newline);
7827 ++nlines;
7828
7830 sLine = sLine.Strip(TString::kLeading); // skip leading whitespace
7831 if (sLine.IsNull()) {
7832 if (gDebug > 2) {
7833 Info("ReadStream", "Skipping empty line number %lld", nlines);
7834 }
7835 continue; // silently skip empty lines
7836 }
7837 if (sLine[0] == '#') {
7838 if (gDebug > 2) {
7839 Info("ReadStream", "Skipping comment line number %lld: '%s'",
7840 nlines, line.c_str());
7841 }
7842 continue;
7843 }
7844 if (gDebug > 2) {
7845 Info("ReadStream", "Parsing line number %lld: '%s'",
7846 nlines, line.c_str());
7847 }
7848
7849 // Loop on branches and read the branch values into their buffer
7850 branch = nullptr;
7851 TString tok; // one column's data
7852 TString leafData; // leaf data, possibly multiple tokens for e.g. /I[2]
7853 std::stringstream sToken; // string stream feeding leafData into leaves
7854 Ssiz_t pos = 0;
7855 Int_t iBranch = 0;
7856 bool goodLine = true; // whether the row can be filled into the tree
7857 Int_t remainingLeafLen = 0; // remaining columns for the current leaf
7858 while (goodLine && iBranch < nbranches
7859 && sLine.Tokenize(tok, pos, sDelim)) {
7860 tok = tok.Strip(TString::kLeading); // skip leading whitespace
7861 if (tok.IsNull() && delimiter == ' ') {
7862 // 1 2 should not be interpreted as 1,,,2 but 1, 2.
7863 // Thus continue until we have a non-empty token.
7864 continue;
7865 }
7866
7867 if (!remainingLeafLen) {
7868 // next branch!
7870 }
7871 TLeaf *leaf = (TLeaf*)branch->GetListOfLeaves()->At(0);
7872 if (!remainingLeafLen) {
7873 remainingLeafLen = leaf->GetLen();
7874 if (leaf->GetMaximum() > 0) {
7875 // This is a dynamic leaf length, i.e. most likely a TLeafC's
7876 // string size. This still translates into one token:
7877 remainingLeafLen = 1;
7878 }
7879
7880 leafData = tok;
7881 } else {
7882 // append token to laf data:
7883 leafData += " ";
7884 leafData += tok;
7885 }
7887 if (remainingLeafLen) {
7888 // need more columns for this branch:
7889 continue;
7890 }
7891 ++iBranch;
7892
7893 // initialize stringstream with token
7894 sToken.clear();
7895 sToken.seekp(0, std::ios_base::beg);
7896 sToken.str(leafData.Data());
7897 sToken.seekg(0, std::ios_base::beg);
7898 leaf->ReadValue(sToken, 0 /* 0 = "all" */);
7899 if (gDebug > 3) {
7900 Info("ReadStream", "%5lld:%3d:%d%d%d%d:%d%d%d%d:%s",
7901 nlines, iBranch,
7902 (int)sToken.good(), (int)sToken.fail(),
7903 (int)sToken.bad(), (int)sToken.eof(),
7904 (int)in.good(), (int)in.fail(),
7905 (int)in.bad(), (int)in.eof(),
7906 sToken.str().c_str());
7907 }
7908
7909 // Error handling
7910 if (sToken.bad()) {
7911 // How could that happen for a stringstream?
7912 Warning("ReadStream",
7913 "Buffer error while reading data for branch %s on line %lld",
7914 branch->GetName(), nlines);
7915 } else if (!sToken.eof()) {
7916 if (sToken.fail()) {
7917 Warning("ReadStream",
7918 "Couldn't read formatted data in \"%s\" for branch %s on line %lld; ignoring line",
7919 tok.Data(), branch->GetName(), nlines);
7920 goodLine = false;
7921 } else {
7922 std::string remainder;
7923 std::getline(sToken, remainder, newline);
7924 if (!remainder.empty()) {
7925 Warning("ReadStream",
7926 "Ignoring trailing \"%s\" while reading data for branch %s on line %lld",
7927 remainder.c_str(), branch->GetName(), nlines);
7928 }
7929 }
7930 }
7931 } // tokenizer loop
7932
7933 if (iBranch < nbranches) {
7934 Warning("ReadStream",
7935 "Read too few columns (%d < %d) in line %lld; ignoring line",
7937 goodLine = false;
7938 } else if (pos != kNPOS) {
7940 if (pos < sLine.Length()) {
7941 Warning("ReadStream",
7942 "Ignoring trailing \"%s\" while reading line %lld",
7943 sLine.Data() + pos - 1 /* also print delimiter */,
7944 nlines);
7945 }
7946 }
7947
7948 //we are now ready to fill the tree
7949 if (goodLine) {
7950 Fill();
7951 ++nGoodLines;
7952 }
7953 }
7954
7955 return nGoodLines;
7956}
7957
7958////////////////////////////////////////////////////////////////////////////////
7959/// Make sure that obj (which is being deleted or will soon be) is no
7960/// longer referenced by this TTree.
7963{
7964 if (obj == fEventList) {
7965 fEventList = nullptr;
7966 }
7967 if (obj == fEntryList) {
7968 fEntryList = nullptr;
7969 }
7970 if (fUserInfo) {
7972 }
7973 if (fPlayer == obj) {
7974 fPlayer = nullptr;
7975 }
7976 if (fTreeIndex == obj) {
7977 fTreeIndex = nullptr;
7978 }
7979 if (fAliases == obj) {
7980 fAliases = nullptr;
7981 } else if (fAliases) {
7983 }
7984 if (fFriends == obj) {
7985 fFriends = nullptr;
7986 } else if (fFriends) {
7988 }
7989}
7990
7991////////////////////////////////////////////////////////////////////////////////
7992/// Refresh contents of this tree and its branches from the current status on disk.
7993///
7994/// One can call this function in case the tree file is being
7995/// updated by another process.
7997void TTree::Refresh()
7998{
7999 if (!fDirectory->GetFile()) {
8000 return;
8001 }
8003 fDirectory->Remove(this);
8004 TTree* tree; fDirectory->GetObject(GetName(),tree);
8005 if (!tree) {
8006 return;
8007 }
8008 //copy info from tree header into this Tree
8009 fEntries = 0;
8010 fNClusterRange = 0;
8011 ImportClusterRanges(tree);
8012
8013 fAutoSave = tree->fAutoSave;
8014 fEntries = tree->fEntries;
8015 fTotBytes = tree->GetTotBytes();
8016 fZipBytes = tree->GetZipBytes();
8017 fSavedBytes = tree->fSavedBytes;
8018 fTotalBuffers = tree->fTotalBuffers.load();
8019
8020 //loop on all branches and update them
8022 for (Int_t i = 0; i < nleaves; i++) {
8024 TBranch* branch = (TBranch*) leaf->GetBranch();
8025 branch->Refresh(tree->GetBranch(branch->GetName()));
8026 }
8027 fDirectory->Remove(tree);
8028 fDirectory->Append(this);
8029 delete tree;
8030 tree = nullptr;
8031}
8032
8033////////////////////////////////////////////////////////////////////////////////
8034/// Record a TFriendElement that we need to warn when the chain switches to
8035/// a new file (typically this is because this chain is a friend of another
8036/// TChain)
8043}
8044
8045
8046////////////////////////////////////////////////////////////////////////////////
8047/// Removes external friend
8052}
8053
8054
8055////////////////////////////////////////////////////////////////////////////////
8056/// Remove a friend from the list of friends.
8059{
8060 // We already have been visited while recursively looking
8061 // through the friends tree, let return
8063 return;
8064 }
8065 if (!fFriends) {
8066 return;
8067 }
8068 TFriendLock lock(this, kRemoveFriend);
8070 TFriendElement* fe = nullptr;
8071 while ((fe = (TFriendElement*) nextf())) {
8072 TTree* friend_t = fe->GetTree();
8073 if (friend_t == oldFriend) {
8074 fFriends->Remove(fe);
8075 delete fe;
8076 fe = nullptr;
8077 }
8078 }
8079}
8080
8081////////////////////////////////////////////////////////////////////////////////
8082/// Reset baskets, buffers and entries count in all branches and leaves.
8085{
8086 fNotify = nullptr;
8087 fEntries = 0;
8088 fNClusterRange = 0;
8089 fTotBytes = 0;
8090 fZipBytes = 0;
8091 fFlushedBytes = 0;
8092 fSavedBytes = 0;
8093 fTotalBuffers = 0;
8094 fChainOffset = 0;
8095 fReadEntry = -1;
8096
8097 delete fTreeIndex;
8098 fTreeIndex = nullptr;
8099
8101 for (Int_t i = 0; i < nb; ++i) {
8103 branch->Reset(option);
8104 }
8105
8106 if (fBranchRef) {
8107 fBranchRef->Reset();
8108 }
8109}
8110
8111////////////////////////////////////////////////////////////////////////////////
8112/// Resets the state of this TTree after a merge (keep the customization but
8113/// forget the data).
8116{
8117 fEntries = 0;
8118 fNClusterRange = 0;
8119 fTotBytes = 0;
8120 fZipBytes = 0;
8121 fSavedBytes = 0;
8122 fFlushedBytes = 0;
8123 fTotalBuffers = 0;
8124 fChainOffset = 0;
8125 fReadEntry = -1;
8126
8127 delete fTreeIndex;
8128 fTreeIndex = nullptr;
8129
8131 for (Int_t i = 0; i < nb; ++i) {
8133 branch->ResetAfterMerge(info);
8134 }
8135
8136 if (fBranchRef) {
8138 }
8139}
8140
8141////////////////////////////////////////////////////////////////////////////////
8142/// Tell a branch to set its address to zero.
8143///
8144/// @note If the branch owns any objects, they are deleted.
8147{
8148 if (br && br->GetTree()) {
8149 br->ResetAddress();
8150 }
8151}
8152
8153////////////////////////////////////////////////////////////////////////////////
8154/// Tell all of our branches to drop their current objects and allocate new ones.
8157{
8158 // We already have been visited while recursively looking
8159 // through the friends tree, let return
8161 return;
8162 }
8164 Int_t nbranches = branches->GetEntriesFast();
8165 for (Int_t i = 0; i < nbranches; ++i) {
8166 TBranch* branch = (TBranch*) branches->UncheckedAt(i);
8167 branch->ResetAddress();
8168 }
8169 if (fFriends) {
8172 auto *frTree = frEl->GetTree();
8173 if (frTree) {
8174 frTree->ResetBranchAddresses();
8175 }
8176 }
8177 }
8178}
8179
8180////////////////////////////////////////////////////////////////////////////////
8181/// Loop over tree entries and print entries passing selection. Interactive
8182/// pagination break is on by default.
8183///
8184/// - If varexp is 0 (or "") then print only first 8 columns.
8185/// - If varexp = "*" print all columns.
8186///
8187/// Otherwise a columns selection can be made using "var1:var2:var3".
8188///
8189/// \param firstentry first entry to scan
8190/// \param nentries total number of entries to scan (starting from firstentry). Defaults to all entries.
8191/// \note see TTree::SetScanField to control how many lines are printed between pagination breaks (Use 0 to disable pagination)
8192/// \see TTreePlayer::Scan
8195{
8196 GetPlayer();
8197 if (fPlayer) {
8199 }
8200 return -1;
8201}
8202
8203////////////////////////////////////////////////////////////////////////////////
8204/// Set a tree variable alias.
8205///
8206/// Set an alias for an expression/formula based on the tree 'variables'.
8207///
8208/// The content of 'aliasName' can be used in TTreeFormula (i.e. TTree::Draw,
8209/// TTree::Scan, TTreeViewer) and will be evaluated as the content of
8210/// 'aliasFormula'.
8211///
8212/// If the content of 'aliasFormula' only contains symbol names, periods and
8213/// array index specification (for example event.fTracks[3]), then
8214/// the content of 'aliasName' can be used as the start of symbol.
8215///
8216/// If the alias 'aliasName' already existed, it is replaced by the new
8217/// value.
8218///
8219/// When being used, the alias can be preceded by an eventual 'Friend Alias'
8220/// (see TTree::GetFriendAlias)
8221///
8222/// Return true if it was added properly.
8223///
8224/// For example:
8225/// ~~~ {.cpp}
8226/// tree->SetAlias("x1","(tdc1[1]-tdc1[0])/49");
8227/// tree->SetAlias("y1","(tdc1[3]-tdc1[2])/47");
8228/// tree->SetAlias("x2","(tdc2[1]-tdc2[0])/49");
8229/// tree->SetAlias("y2","(tdc2[3]-tdc2[2])/47");
8230/// tree->Draw("y2-y1:x2-x1");
8231///
8232/// tree->SetAlias("theGoodTrack","event.fTracks[3]");
8233/// tree->Draw("theGoodTrack.fPx"); // same as "event.fTracks[3].fPx"
8234/// ~~~
8236bool TTree::SetAlias(const char* aliasName, const char* aliasFormula)
8237{
8238 if (!aliasName || !aliasFormula) {
8239 return false;
8240 }
8241 if (!aliasName[0] || !aliasFormula[0]) {
8242 return false;
8243 }
8244 if (!fAliases) {
8245 fAliases = new TList;
8246 } else {
8248 if (oldHolder) {
8249 oldHolder->SetTitle(aliasFormula);
8250 return true;
8251 }
8252 }
8255 return true;
8256}
8257
8258////////////////////////////////////////////////////////////////////////////////
8259/// This function may be called at the start of a program to change
8260/// the default value for fAutoFlush.
8261///
8262/// ### CASE 1 : autof > 0
8263///
8264/// autof is the number of consecutive entries after which TTree::Fill will
8265/// flush all branch buffers to disk.
8266///
8267/// ### CASE 2 : autof < 0
8268///
8269/// When filling the Tree the branch buffers will be flushed to disk when
8270/// more than autof bytes have been written to the file. At the first FlushBaskets
8271/// TTree::Fill will replace fAutoFlush by the current value of fEntries.
8272///
8273/// Calling this function with autof<0 is interesting when it is hard to estimate
8274/// the size of one entry. This value is also independent of the Tree.
8275///
8276/// The Tree is initialized with fAutoFlush=-30000000, ie that, by default,
8277/// the first AutoFlush will be done when 30 MBytes of data are written to the file.
8278///
8279/// ### CASE 3 : autof = 0
8280///
8281/// The AutoFlush mechanism is disabled.
8282///
8283/// Flushing the buffers at regular intervals optimize the location of
8284/// consecutive entries on the disk by creating clusters of baskets.
8285///
8286/// A cluster of baskets is a set of baskets that contains all
8287/// the data for a (consecutive) set of entries and that is stored
8288/// consecutively on the disk. When reading all the branches, this
8289/// is the minimum set of baskets that the TTreeCache will read.
8291void TTree::SetAutoFlush(Long64_t autof /* = -30000000 */ )
8292{
8293 // Implementation note:
8294 //
8295 // A positive value of autoflush determines the size (in number of entries) of
8296 // a cluster of baskets.
8297 //
8298 // If the value of autoflush is changed over time (this happens in
8299 // particular when the TTree results from fast merging many trees),
8300 // we record the values of fAutoFlush in the data members:
8301 // fClusterRangeEnd and fClusterSize.
8302 // In the code we refer to a range of entries where the size of the
8303 // cluster of baskets is the same (i.e the value of AutoFlush was
8304 // constant) is called a ClusterRange.
8305 //
8306 // The 2 arrays (fClusterRangeEnd and fClusterSize) have fNClusterRange
8307 // active (used) values and have fMaxClusterRange allocated entries.
8308 //
8309 // fClusterRangeEnd contains the last entries number of a cluster range.
8310 // In particular this means that the 'next' cluster starts at fClusterRangeEnd[]+1
8311 // fClusterSize contains the size in number of entries of all the cluster
8312 // within the given range.
8313 // The last range (and the only one if fNClusterRange is zero) start at
8314 // fNClusterRange[fNClusterRange-1]+1 and ends at the end of the TTree. The
8315 // size of the cluster in this range is given by the value of fAutoFlush.
8316 //
8317 // For example printing the beginning and end of each the ranges can be done by:
8318 //
8319 // Printf("%-16s %-16s %-16s %5s",
8320 // "Cluster Range #", "Entry Start", "Last Entry", "Size");
8321 // Int_t index= 0;
8322 // Long64_t clusterRangeStart = 0;
8323 // if (fNClusterRange) {
8324 // for( ; index < fNClusterRange; ++index) {
8325 // Printf("%-16d %-16lld %-16lld %5lld",
8326 // index, clusterRangeStart, fClusterRangeEnd[index], fClusterSize[index]);
8327 // clusterRangeStart = fClusterRangeEnd[index] + 1;
8328 // }
8329 // }
8330 // Printf("%-16d %-16lld %-16lld %5lld",
8331 // index, prevEntry, fEntries - 1, fAutoFlush);
8332 //
8333
8334 // Note: We store the entry number corresponding to the end of the cluster
8335 // rather than its start in order to avoid using the array if the cluster
8336 // size never varies (If there is only one value of AutoFlush for the whole TTree).
8337
8338 if( fAutoFlush != autof) {
8339 if ((fAutoFlush > 0 || autof > 0) && fFlushedBytes) {
8340 // The mechanism was already enabled, let's record the previous
8341 // cluster if needed.
8343 }
8344 fAutoFlush = autof;
8345 }
8346}
8347
8348////////////////////////////////////////////////////////////////////////////////
8349/// Mark the previous event as being at the end of the event cluster.
8350///
8351/// So, if fEntries is set to 10 (and this is the first cluster) when MarkEventCluster
8352/// is called, then the first cluster has 9 events.
8354{
8355 if (!fEntries) return;
8356
8357 if ( (fNClusterRange+1) > fMaxClusterRange ) {
8358 if (fMaxClusterRange) {
8359 // Resize arrays to hold a larger event cluster.
8362 newsize*sizeof(Long64_t),fMaxClusterRange*sizeof(Long64_t));
8364 newsize*sizeof(Long64_t),fMaxClusterRange*sizeof(Long64_t));
8366 } else {
8367 // Cluster ranges have never been initialized; create them now.
8368 fMaxClusterRange = 2;
8371 }
8372 }
8374 // If we are auto-flushing, then the cluster size is the same as the current auto-flush setting.
8375 if (fAutoFlush > 0) {
8376 // Even if the user triggers MarkEventRange prior to fAutoFlush being present, the TClusterIterator
8377 // will appropriately go to the next event range.
8379 // Otherwise, assume there is one cluster per event range (e.g., user is manually controlling the flush).
8380 } else if (fNClusterRange == 0) {
8382 } else {
8384 }
8386}
8387
8388/// Estimate the median cluster size for the TTree.
8389/// This value provides e.g. a reasonable cache size default if other heuristics fail.
8390/// Clusters with size 0 and the very last cluster range, that might not have been committed to fClusterSize yet,
8391/// are ignored for the purposes of the calculation.
8393{
8394 std::vector<Long64_t> clusterSizesPerRange;
8396
8397 // We ignore cluster sizes of 0 for the purposes of this function.
8398 // We also ignore the very last cluster range which might not have been committed to fClusterSize.
8399 std::copy_if(fClusterSize, fClusterSize + fNClusterRange, std::back_inserter(clusterSizesPerRange),
8400 [](Long64_t size) { return size != 0; });
8401
8402 std::vector<double> nClustersInRange; // we need to store doubles because of the signature of TMath::Median
8403 nClustersInRange.reserve(clusterSizesPerRange.size());
8404
8405 auto clusterRangeStart = 0ll;
8406 for (int i = 0; i < fNClusterRange; ++i) {
8407 const auto size = fClusterSize[i];
8408 R__ASSERT(size >= 0);
8409 if (fClusterSize[i] == 0)
8410 continue;
8411 const auto nClusters = (1 + fClusterRangeEnd[i] - clusterRangeStart) / fClusterSize[i];
8412 nClustersInRange.emplace_back(nClusters);
8414 }
8415
8417 const auto medianClusterSize =
8419 return medianClusterSize;
8420}
8421
8422////////////////////////////////////////////////////////////////////////////////
8423/// In case of a program crash, it will be possible to recover the data in the
8424/// tree up to the last AutoSave point.
8425/// This function may be called before filling a TTree to specify when the
8426/// branch buffers and TTree header are flushed to disk as part of
8427/// TTree::Fill().
8428/// The default is -300000000, ie the TTree will write data to disk once it
8429/// exceeds 300 MBytes.
8430/// CASE 1: If fAutoSave is positive the watermark is reached when a multiple of
8431/// fAutoSave entries have been filled.
8432/// CASE 2: If fAutoSave is negative the watermark is reached when -fAutoSave
8433/// bytes can be written to the file.
8434/// CASE 3: If fAutoSave is 0, AutoSave() will never be called automatically
8435/// as part of TTree::Fill().
8440}
8441
8442////////////////////////////////////////////////////////////////////////////////
8443/// Set a branch's basket size.
8444///
8445/// bname is the name of a branch.
8446///
8447/// - if bname="*", apply to all branches.
8448/// - if bname="xxx*", apply to all branches with name starting with xxx
8449///
8450/// see TRegexp for wildcarding options
8451/// buffsize = branc basket size
8453void TTree::SetBasketSize(const char* bname, Int_t buffsize)
8454{
8456 TRegexp re(bname, true);
8457 Int_t nb = 0;
8458 for (Int_t i = 0; i < nleaves; i++) {
8460 TBranch* branch = (TBranch*) leaf->GetBranch();
8461 TString s = branch->GetName();
8462 if (strcmp(bname, branch->GetName()) && (s.Index(re) == kNPOS)) {
8463 continue;
8464 }
8465 nb++;
8466 branch->SetBasketSize(buffsize);
8467 }
8468 if (!nb) {
8469 Error("SetBasketSize", "unknown branch -> '%s'", bname);
8470 }
8471}
8472
8473////////////////////////////////////////////////////////////////////////////////
8474/// Change branch address, dealing with clone trees properly.
8475/// See TTree::CheckBranchAddressType for the semantic of the return value.
8476///
8477/// Note: See the comments in TBranchElement::SetAddress() for the
8478/// meaning of the addr parameter and the object ownership policy.
8480Int_t TTree::SetBranchAddress(const char* bname, void* addr, TBranch** ptr)
8481{
8482 TBranch* branch = GetBranch(bname);
8483 if (!branch) {
8484 if (ptr) *ptr = nullptr;
8485 Error("SetBranchAddress", "unknown branch -> %s", bname);
8486 return kMissingBranch;
8487 }
8488 return SetBranchAddressImp(branch,addr,ptr);
8489}
8490
8491////////////////////////////////////////////////////////////////////////////////
8492/// Verify the validity of the type of addr before calling SetBranchAddress.
8493/// See TTree::CheckBranchAddressType for the semantic of the return value.
8494///
8495/// Note: See the comments in TBranchElement::SetAddress() for the
8496/// meaning of the addr parameter and the object ownership policy.
8498Int_t TTree::SetBranchAddress(const char* bname, void* addr, TClass* ptrClass, EDataType datatype, bool isptr)
8499{
8500 return SetBranchAddress(bname, addr, nullptr, ptrClass, datatype, isptr);
8501}
8502
8503////////////////////////////////////////////////////////////////////////////////
8504/// Verify the validity of the type of addr before calling SetBranchAddress.
8505/// See TTree::CheckBranchAddressType for the semantic of the return value.
8506///
8507/// Note: See the comments in TBranchElement::SetAddress() for the
8508/// meaning of the addr parameter and the object ownership policy.
8510Int_t TTree::SetBranchAddress(const char* bname, void* addr, TBranch** ptr, TClass* ptrClass, EDataType datatype, bool isptr)
8511{
8512 TBranch* branch = GetBranch(bname);
8513 if (!branch) {
8514 if (ptr) *ptr = nullptr;
8515 Error("SetBranchAddress", "unknown branch -> %s", bname);
8516 return kMissingBranch;
8517 }
8518
8520
8521 // This will set the value of *ptr to branch.
8522 if (res >= 0) {
8523 // The check succeeded.
8524 if ((res & kNeedEnableDecomposedObj) && !branch->GetMakeClass())
8525 branch->SetMakeClass(true);
8527 } else {
8528 if (ptr) *ptr = nullptr;
8529 }
8530 return res;
8531}
8532
8533////////////////////////////////////////////////////////////////////////////////
8534/// Change branch address, dealing with clone trees properly.
8535/// See TTree::CheckBranchAddressType for the semantic of the return value.
8536///
8537/// Note: See the comments in TBranchElement::SetAddress() for the
8538/// meaning of the addr parameter and the object ownership policy.
8541{
8542 if (ptr) {
8543 *ptr = branch;
8544 }
8545 if (fClones) {
8546 void* oldAddr = branch->GetAddress();
8547 TIter next(fClones);
8548 TTree* clone = nullptr;
8549 const char *bname = branch->GetName();
8550 while ((clone = (TTree*) next())) {
8551 TBranch* cloneBr = clone->GetBranch(bname);
8552 if (cloneBr && (cloneBr->GetAddress() == oldAddr)) {
8553 cloneBr->SetAddress(addr);
8554 }
8555 }
8556 }
8557 branch->SetAddress(addr);
8558 return kVoidPtr;
8559}
8560
8561////////////////////////////////////////////////////////////////////////////////
8562/// Set branch status to Process or DoNotProcess.
8563///
8564/// When reading a Tree, by default, all branches are read.
8565/// One can speed up considerably the analysis phase by activating
8566/// only the branches that hold variables involved in a query.
8567///
8568/// bname is the name of a branch.
8569///
8570/// - if bname="*", apply to all branches.
8571/// - if bname="xxx*", apply to all branches with name starting with xxx
8572///
8573/// see TRegexp for wildcarding options
8574///
8575/// - status = 1 branch will be processed
8576/// - = 0 branch will not be processed
8577///
8578/// Example:
8579///
8580/// Assume a tree T with sub-branches a,b,c,d,e,f,g,etc..
8581/// when doing T.GetEntry(i) all branches are read for entry i.
8582/// to read only the branches c and e, one can do
8583/// ~~~ {.cpp}
8584/// T.SetBranchStatus("*",0); //disable all branches
8585/// T.SetBranchStatus("c",1);
8586/// T.setBranchStatus("e",1);
8587/// T.GetEntry(i);
8588/// ~~~
8589/// bname is interpreted as a wild-carded TRegexp (see TRegexp::MakeWildcard).
8590/// Thus, "a*b" or "a.*b" matches branches starting with "a" and ending with
8591/// "b", but not any other branch with an "a" followed at some point by a
8592/// "b". For this second behavior, use "*a*b*". Note that TRegExp does not
8593/// support '|', and so you cannot select, e.g. track and shower branches
8594/// with "track|shower".
8595///
8596/// __WARNING! WARNING! WARNING!__
8597///
8598/// SetBranchStatus is matching the branch based on match of the branch
8599/// 'name' and not on the branch hierarchy! In order to be able to
8600/// selectively enable a top level object that is 'split' you need to make
8601/// sure the name of the top level branch is prefixed to the sub-branches'
8602/// name (by adding a dot ('.') at the end of the Branch creation and use the
8603/// corresponding bname.
8604///
8605/// I.e If your Tree has been created in split mode with a parent branch "parent."
8606/// (note the trailing dot).
8607/// ~~~ {.cpp}
8608/// T.SetBranchStatus("parent",1);
8609/// ~~~
8610/// will not activate the sub-branches of "parent". You should do:
8611/// ~~~ {.cpp}
8612/// T.SetBranchStatus("parent*",1);
8613/// ~~~
8614/// Without the trailing dot in the branch creation you have no choice but to
8615/// call SetBranchStatus explicitly for each of the sub branches.
8616///
8617/// An alternative to this function is to read directly and only
8618/// the interesting branches. Example:
8619/// ~~~ {.cpp}
8620/// TBranch *brc = T.GetBranch("c");
8621/// TBranch *bre = T.GetBranch("e");
8622/// brc->GetEntry(i);
8623/// bre->GetEntry(i);
8624/// ~~~
8625/// If found is not 0, the number of branch(es) found matching the regular
8626/// expression is returned in *found AND the error message 'unknown branch'
8627/// is suppressed.
8629void TTree::SetBranchStatus(const char* bname, bool status, UInt_t* found)
8630{
8631 // We already have been visited while recursively looking
8632 // through the friends tree, let return
8634 return;
8635 }
8636
8637 if (!bname || !*bname) {
8638 Error("SetBranchStatus", "Input regexp is an empty string: no match against branch names will be attempted.");
8639 return;
8640 }
8641
8643 TLeaf *leaf, *leafcount;
8644
8645 Int_t i,j;
8647 TRegexp re(bname,true);
8648 Int_t nb = 0;
8649
8650 // first pass, loop on all branches
8651 // for leafcount branches activate/deactivate in function of status
8652 for (i=0;i<nleaves;i++) {
8654 branch = (TBranch*)leaf->GetBranch();
8655 TString s = branch->GetName();
8656 if (strcmp(bname,"*")) { //Regexp gives wrong result for [] in name
8658 longname.Form("%s.%s",GetName(),branch->GetName());
8659 if (strcmp(bname,branch->GetName())
8660 && longname != bname
8661 && s.Index(re) == kNPOS) continue;
8662 }
8663 nb++;
8664 if (status) branch->ResetBit(kDoNotProcess);
8665 else branch->SetBit(kDoNotProcess);
8666 leafcount = leaf->GetLeafCount();
8667 if (leafcount) {
8668 bcount = leafcount->GetBranch();
8669 if (status) bcount->ResetBit(kDoNotProcess);
8670 else bcount->SetBit(kDoNotProcess);
8671 }
8672 }
8673 if (nb==0 && !strchr(bname,'*')) {
8674 branch = GetBranch(bname);
8675 if (branch) {
8676 if (status) branch->ResetBit(kDoNotProcess);
8677 else branch->SetBit(kDoNotProcess);
8678 ++nb;
8679 }
8680 }
8681
8682 //search in list of friends
8684 if (fFriends) {
8685 TFriendLock lock(this,kSetBranchStatus);
8688 TString name;
8689 while ((fe = (TFriendElement*)nextf())) {
8690 TTree *t = fe->GetTree();
8691 if (!t) continue;
8692
8693 // If the alias is present replace it with the real name.
8694 const char *subbranch = strstr(bname,fe->GetName());
8695 if (subbranch!=bname) subbranch = nullptr;
8696 if (subbranch) {
8697 subbranch += strlen(fe->GetName());
8698 if ( *subbranch != '.' ) subbranch = nullptr;
8699 else subbranch ++;
8700 }
8701 if (subbranch) {
8702 name.Form("%s.%s",t->GetName(),subbranch);
8703 } else {
8704 name = bname;
8705 }
8706 t->SetBranchStatus(name,status, &foundInFriend);
8707 }
8708 }
8709 if (!nb && !foundInFriend) {
8710 if (!found) {
8711 if (status) {
8712 if (strchr(bname,'*') != nullptr)
8713 Error("SetBranchStatus", "No branch name is matching wildcard -> %s", bname);
8714 else
8715 Error("SetBranchStatus", "unknown branch -> %s", bname);
8716 } else {
8717 if (strchr(bname,'*') != nullptr)
8718 Warning("SetBranchStatus", "No branch name is matching wildcard -> %s", bname);
8719 else
8720 Warning("SetBranchStatus", "unknown branch -> %s", bname);
8721 }
8722 }
8723 return;
8724 }
8725 if (found) *found = nb + foundInFriend;
8726
8727 // second pass, loop again on all branches
8728 // activate leafcount branches for active branches only
8729 for (i = 0; i < nleaves; i++) {
8731 branch = (TBranch*)leaf->GetBranch();
8732 if (!branch->TestBit(kDoNotProcess)) {
8733 leafcount = leaf->GetLeafCount();
8734 if (leafcount) {
8735 bcount = leafcount->GetBranch();
8736 bcount->ResetBit(kDoNotProcess);
8737 }
8738 } else {
8739 //Int_t nbranches = branch->GetListOfBranches()->GetEntriesFast();
8740 Int_t nbranches = branch->GetListOfBranches()->GetEntries();
8741 for (j=0;j<nbranches;j++) {
8742 bson = (TBranch*)branch->GetListOfBranches()->UncheckedAt(j);
8743 if (!bson) continue;
8744 if (!bson->TestBit(kDoNotProcess)) {
8745 if (bson->GetNleaves() <= 0) continue;
8746 branch->ResetBit(kDoNotProcess);
8747 break;
8748 }
8749 }
8750 }
8751 }
8752}
8753
8754////////////////////////////////////////////////////////////////////////////////
8755/// Set the current branch style. (static function)
8756///
8757/// - style = 0 old Branch
8758/// - style = 1 new Bronch
8763}
8764
8765////////////////////////////////////////////////////////////////////////////////
8766/// Set maximum size of the file cache .
8767//
8768/// - if cachesize = 0 the existing cache (if any) is deleted.
8769/// - if cachesize = -1 (default) it is set to the AutoFlush value when writing
8770/// the Tree (default is 30 MBytes).
8771///
8772/// The cacheSize might be clamped, see TFileCacheRead::SetBufferSize
8773///
8774/// Returns:
8775/// - 0 size set, cache was created if possible
8776/// - -1 on error
8779{
8780 // remember that the user has requested an explicit cache setup
8781 fCacheUserSet = true;
8782
8783 return SetCacheSizeAux(false, cacheSize);
8784}
8785
8786////////////////////////////////////////////////////////////////////////////////
8787/// Set the size of the file cache and create it if possible.
8788///
8789/// If autocache is true:
8790/// this may be an autocreated cache, possibly enlarging an existing
8791/// autocreated cache. The size is calculated. The value passed in cacheSize:
8792/// - cacheSize = 0 make cache if default cache creation is enabled
8793/// - cacheSize = -1 make a default sized cache in any case
8794///
8795/// If autocache is false:
8796/// this is a user requested cache. cacheSize is used to size the cache.
8797/// This cache should never be automatically adjusted.
8798///
8799/// The cacheSize might be clamped, see TFileCacheRead::SetBufferSize
8800///
8801/// Returns:
8802/// - 0 size set, or existing autosized cache almost large enough.
8803/// (cache was created if possible)
8804/// - -1 on error
8806Int_t TTree::SetCacheSizeAux(bool autocache /* = true */, Long64_t cacheSize /* = 0 */ )
8807{
8808 if (autocache) {
8809 // used as a once only control for automatic cache setup
8810 fCacheDoAutoInit = false;
8811 }
8812
8813 if (!autocache) {
8814 // negative size means the user requests the default
8815 if (cacheSize < 0) {
8816 cacheSize = GetCacheAutoSize(true);
8817 }
8818 } else {
8819 if (cacheSize == 0) {
8820 cacheSize = GetCacheAutoSize();
8821 } else if (cacheSize < 0) {
8822 cacheSize = GetCacheAutoSize(true);
8823 }
8824 }
8825
8826 TFile* file = GetCurrentFile();
8827 if (!file || GetTree() != this) {
8828 // if there's no file or we are not a plain tree (e.g. if we're a TChain)
8829 // do not create a cache, only record the size if one was given
8830 if (!autocache) {
8831 fCacheSize = cacheSize;
8832 }
8833 if (GetTree() != this) {
8834 return 0;
8835 }
8836 if (!autocache && cacheSize>0) {
8837 Warning("SetCacheSizeAux", "A TTreeCache could not be created because the TTree has no file");
8838 }
8839 return 0;
8840 }
8841
8842 // Check for an existing cache
8843 TTreeCache* pf = GetReadCache(file);
8844 if (pf) {
8845 if (autocache) {
8846 // reset our cache status tracking in case existing cache was added
8847 // by the user without using one of the TTree methods
8848 fCacheSize = pf->GetBufferSize();
8849 fCacheUserSet = !pf->IsAutoCreated();
8850
8851 if (fCacheUserSet) {
8852 // existing cache was created by the user, don't change it
8853 return 0;
8854 }
8855 } else {
8856 // update the cache to ensure it records the user has explicitly
8857 // requested it
8858 pf->SetAutoCreated(false);
8859 }
8860
8861 // if we're using an automatically calculated size and the existing
8862 // cache is already almost large enough don't resize
8863 if (autocache && Long64_t(0.80*cacheSize) < fCacheSize) {
8864 // already large enough
8865 return 0;
8866 }
8867
8868 if (cacheSize == fCacheSize) {
8869 return 0;
8870 }
8871
8872 if (cacheSize == 0) {
8873 // delete existing cache
8874 pf->WaitFinishPrefetch();
8875 file->SetCacheRead(nullptr,this);
8876 delete pf;
8877 pf = nullptr;
8878 } else {
8879 // resize
8880 Int_t res = pf->SetBufferSize(cacheSize);
8881 if (res < 0) {
8882 return -1;
8883 }
8884 cacheSize = pf->GetBufferSize(); // update after potential clamp
8885 }
8886 } else {
8887 // no existing cache
8888 if (autocache) {
8889 if (fCacheUserSet) {
8890 // value was already set manually.
8891 if (fCacheSize == 0) return 0;
8892 // Expected a cache should exist; perhaps the user moved it
8893 // Do nothing more here.
8894 if (cacheSize) {
8895 Error("SetCacheSizeAux", "Not setting up an automatically sized TTreeCache because of missing cache previously set");
8896 }
8897 return -1;
8898 }
8899 }
8900 }
8901
8902 fCacheSize = cacheSize;
8903 if (cacheSize == 0 || pf) {
8904 return 0;
8905 }
8906
8907#ifdef R__USE_IMT
8909 pf = new TTreeCacheUnzip(this, cacheSize);
8910 else
8911#endif
8912 pf = new TTreeCache(this, cacheSize);
8913
8914 pf->SetAutoCreated(autocache);
8915
8916 return 0;
8917}
8918
8919////////////////////////////////////////////////////////////////////////////////
8920///interface to TTreeCache to set the cache entry range
8921///
8922/// Returns:
8923/// - 0 entry range set
8924/// - -1 on error
8927{
8928 if (!GetTree()) {
8929 if (LoadTree(0)<0) {
8930 Error("SetCacheEntryRange","Could not load a tree");
8931 return -1;
8932 }
8933 }
8934 if (GetTree()) {
8935 if (GetTree() != this) {
8936 return GetTree()->SetCacheEntryRange(first, last);
8937 }
8938 } else {
8939 Error("SetCacheEntryRange", "No tree is available. Could not set cache entry range");
8940 return -1;
8941 }
8942
8943 TFile *f = GetCurrentFile();
8944 if (!f) {
8945 Error("SetCacheEntryRange", "No file is available. Could not set cache entry range");
8946 return -1;
8947 }
8948 TTreeCache *tc = GetReadCache(f,true);
8949 if (!tc) {
8950 Error("SetCacheEntryRange", "No cache is available. Could not set entry range");
8951 return -1;
8952 }
8953 tc->SetEntryRange(first,last);
8954 return 0;
8955}
8956
8957////////////////////////////////////////////////////////////////////////////////
8958/// Interface to TTreeCache to set the number of entries for the learning phase
8963}
8964
8965////////////////////////////////////////////////////////////////////////////////
8966/// Enable/Disable circularity for this tree.
8967///
8968/// if maxEntries > 0 a maximum of maxEntries is kept in one buffer/basket
8969/// per branch in memory.
8970/// Note that when this function is called (maxEntries>0) the Tree
8971/// must be empty or having only one basket per branch.
8972/// if maxEntries <= 0 the tree circularity is disabled.
8973///
8974/// #### NOTE 1:
8975/// Circular Trees are interesting in online real time environments
8976/// to store the results of the last maxEntries events.
8977/// #### NOTE 2:
8978/// Calling SetCircular with maxEntries <= 0 is necessary before
8979/// merging circular Trees that have been saved on files.
8980/// #### NOTE 3:
8981/// SetCircular with maxEntries <= 0 is automatically called
8982/// by TChain::Merge
8983/// #### NOTE 4:
8984/// A circular Tree can still be saved in a file. When read back,
8985/// it is still a circular Tree and can be filled again.
8988{
8989 if (maxEntries <= 0) {
8990 // Disable circularity.
8991 fMaxEntries = 1000000000;
8992 fMaxEntries *= 1000;
8994 //in case the Tree was originally created in gROOT, the branch
8995 //compression level was set to -1. If the Tree is now associated to
8996 //a file, reset the compression level to the file compression level
8997 if (fDirectory) {
9000 if (bfile) {
9001 compress = bfile->GetCompressionSettings();
9002 }
9004 for (Int_t i = 0; i < nb; i++) {
9006 branch->SetCompressionSettings(compress);
9007 }
9008 }
9009 } else {
9010 // Enable circularity.
9013 }
9014}
9015
9016////////////////////////////////////////////////////////////////////////////////
9017/// Set the debug level and the debug range.
9018///
9019/// For entries in the debug range, the functions TBranchElement::Fill
9020/// and TBranchElement::GetEntry will print the number of bytes filled
9021/// or read for each branch.
9023void TTree::SetDebug(Int_t level, Long64_t min, Long64_t max)
9024{
9025 fDebug = level;
9026 fDebugMin = min;
9027 fDebugMax = max;
9028}
9029
9030////////////////////////////////////////////////////////////////////////////////
9031/// Update the default value for the branch's fEntryOffsetLen.
9032/// If updateExisting is true, also update all the existing branches.
9033/// If newdefault is less than 10, the new default value will be 10.
9036{
9037 if (newdefault < 10) {
9038 newdefault = 10;
9039 }
9041 if (updateExisting) {
9042 TIter next( GetListOfBranches() );
9043 TBranch *b;
9044 while ( ( b = (TBranch*)next() ) ) {
9045 b->SetEntryOffsetLen( newdefault, true );
9046 }
9047 if (fBranchRef) {
9049 }
9050 }
9051}
9052
9053////////////////////////////////////////////////////////////////////////////////
9054/// Change the tree's directory.
9055///
9056/// Remove reference to this tree from current directory and
9057/// add reference to new directory dir. The dir parameter can
9058/// be 0 in which case the tree does not belong to any directory.
9059///
9062{
9063 if (fDirectory == dir) {
9064 return;
9065 }
9066 if (fDirectory) {
9067 fDirectory->Remove(this);
9068
9069 // Delete or move the file cache if it points to this Tree
9070 TFile *file = fDirectory->GetFile();
9071 MoveReadCache(file,dir);
9072 }
9073 fDirectory = dir;
9074 if (fDirectory) {
9075 fDirectory->Append(this);
9076 }
9077 TFile* file = nullptr;
9078 if (fDirectory) {
9079 file = fDirectory->GetFile();
9080 }
9081 if (fBranchRef) {
9082 fBranchRef->SetFile(file);
9083 }
9084 TBranch* b = nullptr;
9085 TIter next(GetListOfBranches());
9086 while((b = (TBranch*) next())) {
9087 b->SetFile(file);
9088 }
9089}
9090
9091////////////////////////////////////////////////////////////////////////////////
9092/// Change number of entries in the tree.
9093///
9094/// If n >= 0, set number of entries in the tree = n.
9095///
9096/// If n < 0, set number of entries in the tree to match the
9097/// number of entries in each branch. (default for n is -1)
9098///
9099/// This function should be called only when one fills each branch
9100/// independently via TBranch::Fill without calling TTree::Fill.
9101/// Calling TTree::SetEntries() make sense only if the number of entries
9102/// in each branch is identical, a warning is issued otherwise.
9103/// The function returns the number of entries.
9104///
9107{
9108 // case 1 : force number of entries to n
9109 if (n >= 0) {
9110 fEntries = n;
9111 return n;
9112 }
9113
9114 // case 2; compute the number of entries from the number of entries in the branches
9115 TBranch* b(nullptr), *bMin(nullptr), *bMax(nullptr);
9117 Long64_t nMax = 0;
9118 TIter next(GetListOfBranches());
9119 while((b = (TBranch*) next())){
9120 Long64_t n2 = b->GetEntries();
9121 if (!bMin || n2 < nMin) {
9122 nMin = n2;
9123 bMin = b;
9124 }
9125 if (!bMax || n2 > nMax) {
9126 nMax = n2;
9127 bMax = b;
9128 }
9129 }
9130 if (bMin && nMin != nMax) {
9131 Warning("SetEntries", "Tree branches have different numbers of entries, eg %s has %lld entries while %s has %lld entries.",
9132 bMin->GetName(), nMin, bMax->GetName(), nMax);
9133 }
9134 fEntries = nMax;
9135 return fEntries;
9136}
9137
9138////////////////////////////////////////////////////////////////////////////////
9139/// Set an EntryList
9142{
9143 if (fEntryList) {
9144 //check if the previous entry list is owned by the tree
9146 delete fEntryList;
9147 }
9148 }
9149 fEventList = nullptr;
9150 if (!enlist) {
9151 fEntryList = nullptr;
9152 return;
9153 }
9155 fEntryList->SetTree(this);
9156
9157}
9158
9159////////////////////////////////////////////////////////////////////////////////
9160/// This function transfroms the given TEventList into a TEntryList
9161/// The new TEntryList is owned by the TTree and gets deleted when the tree
9162/// is deleted. This TEntryList can be returned by GetEntryList() function.
9165{
9167 if (fEntryList){
9169 TEntryList *tmp = fEntryList;
9170 fEntryList = nullptr; // Avoid problem with RecursiveRemove.
9171 delete tmp;
9172 } else {
9173 fEntryList = nullptr;
9174 }
9175 }
9176
9177 if (!evlist) {
9178 fEntryList = nullptr;
9179 fEventList = nullptr;
9180 return;
9181 }
9182
9184 char enlistname[100];
9185 snprintf(enlistname,100, "%s_%s", evlist->GetName(), "entrylist");
9186 fEntryList = new TEntryList(enlistname, evlist->GetTitle());
9187 fEntryList->SetDirectory(nullptr); // We own this.
9188 Int_t nsel = evlist->GetN();
9189 fEntryList->SetTree(this);
9191 for (Int_t i=0; i<nsel; i++){
9192 entry = evlist->GetEntry(i);
9194 }
9195 fEntryList->SetReapplyCut(evlist->GetReapplyCut());
9197}
9198
9199////////////////////////////////////////////////////////////////////////////////
9200/// Set number of entries to estimate variable limits.
9201/// If n is -1, the estimate is set to be the current maximum
9202/// for the tree (i.e. GetEntries() + 1)
9203/// If n is less than -1, the behavior is undefined.
9205void TTree::SetEstimate(Long64_t n /* = 1000000 */)
9206{
9207 if (n == 0) {
9208 n = 10000;
9209 } else if (n < 0) {
9210 n = fEntries - n;
9211 }
9212 fEstimate = n;
9213 GetPlayer();
9214 if (fPlayer) {
9216 }
9217}
9218
9219////////////////////////////////////////////////////////////////////////////////
9220/// Provide the end-user with the ability to enable/disable various experimental
9221/// IO features for this TTree.
9222///
9223/// Returns all the newly-set IO settings.
9226{
9227 // Purposely ignore all unsupported bits; TIOFeatures implementation already warned the user about the
9228 // error of their ways; this is just a safety check.
9230
9235
9237 return newSettings;
9238}
9239
9240////////////////////////////////////////////////////////////////////////////////
9241/// Set fFileNumber to number.
9242/// fFileNumber is used by TTree::Fill to set the file name
9243/// for a new file to be created when the current file exceeds fgTreeMaxSize.
9244/// (see TTree::ChangeFile)
9245/// if fFileNumber=10, the new file name will have a suffix "_11",
9246/// ie, fFileNumber is incremented before setting the file name
9248void TTree::SetFileNumber(Int_t number)
9249{
9250 if (fFileNumber < 0) {
9251 Warning("SetFileNumber", "file number must be positive. Set to 0");
9252 fFileNumber = 0;
9253 return;
9254 }
9255 fFileNumber = number;
9256}
9257
9258////////////////////////////////////////////////////////////////////////////////
9259/// Set all the branches in this TTree to be in decomposed object mode
9260/// (also known as MakeClass mode).
9261///
9262/// For MakeClass mode 0, the TTree expects the address where the data is stored
9263/// to be set by either the user or the TTree to the address of a full object
9264/// through the top level branch.
9265/// For MakeClass mode 1, this address is expected to point to a numerical type
9266/// or C-style array (variable or not) of numerical type, representing the
9267/// primitive data members.
9268/// The function's primary purpose is to allow the user to access the data
9269/// directly with numerical type variable rather than having to have the original
9270/// set of classes (or a reproduction thereof).
9271/// In other words, SetMakeClass sets the branch(es) into a
9272/// mode that allow its reading via a set of independant variables
9273/// (see the result of running TTree::MakeClass on your TTree) by changing the
9274/// interpretation of the address passed to SetAddress from being the beginning
9275/// of the object containing the data to being the exact location where the data
9276/// should be loaded. If you have the shared library corresponding to your object,
9277/// it is better if you do
9278/// `MyClass *objp = 0; tree->SetBranchAddress("toplevel",&objp);`, whereas
9279/// if you do not have the shared library but know your branch data type, e.g.
9280/// `Int_t* ptr = new Int_t[10];`, then:
9281/// `tree->SetMakeClass(1); tree->GetBranch("x")->SetAddress(ptr)` is the way to go.
9283void TTree::SetMakeClass(Int_t make)
9284{
9285 fMakeClass = make;
9286
9288 for (Int_t i = 0; i < nb; ++i) {
9290 branch->SetMakeClass(make);
9291 }
9292}
9293
9294////////////////////////////////////////////////////////////////////////////////
9295/// Set the maximum size in bytes of a Tree file (static function).
9296/// The default size is 100000000000LL, ie 100 Gigabytes.
9297///
9298/// In TTree::Fill, when the file has a size > fgMaxTreeSize,
9299/// the function closes the current file and starts writing into
9300/// a new file with a name of the style "file_1.root" if the original
9301/// requested file name was "file.root".
9306}
9307
9308////////////////////////////////////////////////////////////////////////////////
9309/// Change the name of this tree.
9311void TTree::SetName(const char* name)
9312{
9313 if (gPad) {
9314 gPad->Modified();
9315 }
9316 // Trees are named objects in a THashList.
9317 // We must update hashlists if we change the name.
9318 TFile *file = nullptr;
9319 TTreeCache *pf = nullptr;
9320 if (fDirectory) {
9321 fDirectory->Remove(this);
9322 if ((file = GetCurrentFile())) {
9323 pf = GetReadCache(file);
9324 file->SetCacheRead(nullptr,this,TFile::kDoNotDisconnect);
9325 }
9326 }
9327 // This changes our hash value.
9328 fName = name;
9329 if (fDirectory) {
9330 fDirectory->Append(this);
9331 if (pf) {
9333 }
9334 }
9335}
9337void TTree::SetNotify(TObject *obj)
9338{
9339 if (obj && fNotify && dynamic_cast<TNotifyLinkBase *>(fNotify)) {
9340 auto *oldLink = static_cast<TNotifyLinkBase *>(fNotify);
9341 auto *newLink = dynamic_cast<TNotifyLinkBase *>(obj);
9342 if (!newLink) {
9343 Warning("TTree::SetNotify",
9344 "The tree or chain already has a fNotify registered and it is a TNotifyLink, while the new object is "
9345 "not a TNotifyLink. Setting fNotify to the new value will lead to an orphan linked list of "
9346 "TNotifyLinks and it is most likely not intended. If this is the intended goal, please call "
9347 "SetNotify(nullptr) first to silence this warning.");
9348 } else if (newLink->GetNext() != oldLink && oldLink->GetNext() != newLink) {
9349 // If newLink->GetNext() == oldLink then we are prepending the new head, as in TNotifyLink::PrependLink
9350 // If oldLink->GetNext() == newLink then we are removing the head of the list, as in TNotifyLink::RemoveLink
9351 // Otherwise newLink and oldLink are unrelated:
9352 Warning("TTree::SetNotify",
9353 "The tree or chain already has a TNotifyLink registered, and the new TNotifyLink `obj` does not link "
9354 "to it. Setting fNotify to the new value will lead to an orphan linked list of TNotifyLinks and it is "
9355 "most likely not intended. If this is the intended goal, please call SetNotify(nullptr) first to "
9356 "silence this warning.");
9357 }
9358 }
9359
9360 fNotify = obj;
9361}
9362
9363////////////////////////////////////////////////////////////////////////////////
9364/// Change the name and title of this tree.
9366void TTree::SetObject(const char* name, const char* title)
9367{
9368 if (gPad) {
9369 gPad->Modified();
9370 }
9371
9372 // Trees are named objects in a THashList.
9373 // We must update hashlists if we change the name
9374 TFile *file = nullptr;
9375 TTreeCache *pf = nullptr;
9376 if (fDirectory) {
9377 fDirectory->Remove(this);
9378 if ((file = GetCurrentFile())) {
9379 pf = GetReadCache(file);
9380 file->SetCacheRead(nullptr,this,TFile::kDoNotDisconnect);
9381 }
9382 }
9383 // This changes our hash value.
9384 fName = name;
9385 fTitle = title;
9386 if (fDirectory) {
9387 fDirectory->Append(this);
9388 if (pf) {
9390 }
9391 }
9392}
9393
9394////////////////////////////////////////////////////////////////////////////////
9395/// Enable or disable parallel unzipping of Tree buffers.
9398{
9399#ifdef R__USE_IMT
9400 if (GetTree() == nullptr) {
9402 if (!GetTree())
9403 return;
9404 }
9405 if (GetTree() != this) {
9406 GetTree()->SetParallelUnzip(opt, RelSize);
9407 return;
9408 }
9409 TFile* file = GetCurrentFile();
9410 if (!file)
9411 return;
9412
9413 TTreeCache* pf = GetReadCache(file);
9414 if (pf && !( opt ^ (nullptr != dynamic_cast<TTreeCacheUnzip*>(pf)))) {
9415 // done with opt and type are in agreement.
9416 return;
9417 }
9418 delete pf;
9419 auto cacheSize = GetCacheAutoSize(true);
9420 if (opt) {
9421 auto unzip = new TTreeCacheUnzip(this, cacheSize);
9422 unzip->SetUnzipBufferSize( Long64_t(cacheSize * RelSize) );
9423 } else {
9424 pf = new TTreeCache(this, cacheSize);
9425 }
9426#else
9427 (void)opt;
9428 (void)RelSize;
9429#endif
9430}
9431
9432////////////////////////////////////////////////////////////////////////////////
9433/// Set perf stats
9438}
9439
9440////////////////////////////////////////////////////////////////////////////////
9441/// The current TreeIndex is replaced by the new index.
9442/// Note that this function does not delete the previous index.
9443/// This gives the possibility to play with more than one index, e.g.,
9444/// ~~~ {.cpp}
9445/// TVirtualIndex* oldIndex = tree.GetTreeIndex();
9446/// tree.SetTreeIndex(newIndex);
9447/// tree.Draw();
9448/// tree.SetTreeIndex(oldIndex);
9449/// tree.Draw(); etc
9450/// ~~~
9453{
9454 if (fTreeIndex) {
9455 fTreeIndex->SetTree(nullptr);
9456 }
9457 fTreeIndex = index;
9458}
9459
9460////////////////////////////////////////////////////////////////////////////////
9461/// Set tree weight.
9462///
9463/// The weight is used by TTree::Draw to automatically weight each
9464/// selected entry in the resulting histogram.
9465///
9466/// For example the equivalent of:
9467/// ~~~ {.cpp}
9468/// T.Draw("x", "w")
9469/// ~~~
9470/// is:
9471/// ~~~ {.cpp}
9472/// T.SetWeight(w);
9473/// T.Draw("x");
9474/// ~~~
9475/// This function is redefined by TChain::SetWeight. In case of a
9476/// TChain, an option "global" may be specified to set the same weight
9477/// for all trees in the TChain instead of the default behaviour
9478/// using the weights of each tree in the chain (see TChain::SetWeight).
9481{
9482 fWeight = w;
9483}
9484
9485////////////////////////////////////////////////////////////////////////////////
9486/// Print values of all active leaves for entry.
9487///
9488/// - if entry==-1, print current entry (default)
9489/// - if a leaf is an array, a maximum of lenmax elements is printed.
9492{
9493 if (entry != -1) {
9495 if (ret == -2) {
9496 Error("Show()", "Cannot read entry %lld (entry does not exist)", entry);
9497 return;
9498 } else if (ret == -1) {
9499 Error("Show()", "Cannot read entry %lld (I/O error)", entry);
9500 return;
9501 }
9502 ret = GetEntry(entry);
9503 if (ret == -1) {
9504 Error("Show()", "Cannot read entry %lld (I/O error)", entry);
9505 return;
9506 } else if (ret == 0) {
9507 Error("Show()", "Cannot read entry %lld (no data read)", entry);
9508 return;
9509 }
9510 }
9511 printf("======> EVENT:%lld\n", fReadEntry);
9513 Int_t nleaves = leaves->GetEntriesFast();
9514 Int_t ltype;
9515 for (Int_t i = 0; i < nleaves; i++) {
9516 TLeaf* leaf = (TLeaf*) leaves->UncheckedAt(i);
9517 TBranch* branch = leaf->GetBranch();
9518 if (branch->TestBit(kDoNotProcess)) {
9519 continue;
9520 }
9521 Int_t len = leaf->GetLen();
9522 if (len <= 0) {
9523 continue;
9524 }
9526 if (leaf->IsA() == TLeafElement::Class()) {
9527 leaf->PrintValue(lenmax);
9528 continue;
9529 }
9530 if (branch->GetListOfBranches()->GetEntriesFast() > 0) {
9531 continue;
9532 }
9533 ltype = 10;
9534 if (leaf->IsA() == TLeafF::Class()) {
9535 ltype = 5;
9536 }
9537 if (leaf->IsA() == TLeafD::Class()) {
9538 ltype = 5;
9539 }
9540 if (leaf->IsA() == TLeafC::Class()) {
9541 len = 1;
9542 ltype = 5;
9543 };
9544 printf(" %-15s = ", leaf->GetName());
9545 for (Int_t l = 0; l < len; l++) {
9546 leaf->PrintValue(l);
9547 if (l == (len - 1)) {
9548 printf("\n");
9549 continue;
9550 }
9551 printf(", ");
9552 if ((l % ltype) == 0) {
9553 printf("\n ");
9554 }
9555 }
9556 }
9557}
9558
9559////////////////////////////////////////////////////////////////////////////////
9560/// Start the TTreeViewer on this tree.
9561///
9562/// - ww is the width of the canvas in pixels
9563/// - wh is the height of the canvas in pixels
9565void TTree::StartViewer()
9566{
9567 GetPlayer();
9568 if (fPlayer) {
9569 fPlayer->StartViewer(600, 400);
9570 }
9571}
9572
9573////////////////////////////////////////////////////////////////////////////////
9574/// Stop the cache learning phase
9575///
9576/// Returns:
9577/// - 0 learning phase stopped or not active
9578/// - -1 on error
9581{
9582 if (!GetTree()) {
9583 if (LoadTree(0)<0) {
9584 Error("StopCacheLearningPhase","Could not load a tree");
9585 return -1;
9586 }
9587 }
9588 if (GetTree()) {
9589 if (GetTree() != this) {
9590 return GetTree()->StopCacheLearningPhase();
9591 }
9592 } else {
9593 Error("StopCacheLearningPhase", "No tree is available. Could not stop cache learning phase");
9594 return -1;
9595 }
9596
9597 TFile *f = GetCurrentFile();
9598 if (!f) {
9599 Error("StopCacheLearningPhase", "No file is available. Could not stop cache learning phase");
9600 return -1;
9601 }
9602 TTreeCache *tc = GetReadCache(f,true);
9603 if (!tc) {
9604 Error("StopCacheLearningPhase", "No cache is available. Could not stop learning phase");
9605 return -1;
9606 }
9607 tc->StopLearningPhase();
9608 return 0;
9609}
9610
9611////////////////////////////////////////////////////////////////////////////////
9612/// Set the fTree member for all branches and sub branches.
9614static void TBranch__SetTree(TTree *tree, TObjArray &branches)
9615{
9616 Int_t nb = branches.GetEntriesFast();
9617 for (Int_t i = 0; i < nb; ++i) {
9618 TBranch* br = (TBranch*) branches.UncheckedAt(i);
9619 br->SetTree(tree);
9620
9621 Int_t writeBasket = br->GetWriteBasket();
9622 for (Int_t j = writeBasket; j >= 0; --j) {
9623 TBasket *bk = (TBasket*)br->GetListOfBaskets()->UncheckedAt(j);
9624 if (bk) {
9625 tree->IncrementTotalBuffers(bk->GetBufferSize());
9626 }
9627 }
9628
9629 TBranch__SetTree(tree,*br->GetListOfBranches());
9630 }
9631}
9632
9633////////////////////////////////////////////////////////////////////////////////
9634/// Set the fTree member for all friend elements.
9637{
9638 if (frlist) {
9639 TObjLink *lnk = frlist->FirstLink();
9640 while (lnk) {
9641 TFriendElement *elem = (TFriendElement*)lnk->GetObject();
9642 elem->fParentTree = tree;
9643 lnk = lnk->Next();
9644 }
9645 }
9646}
9647
9648////////////////////////////////////////////////////////////////////////////////
9649/// Stream a class object.
9652{
9653 if (b.IsReading()) {
9654 UInt_t R__s, R__c;
9655 if (fDirectory) {
9656 fDirectory->Remove(this);
9657 //delete the file cache if it points to this Tree
9658 TFile *file = fDirectory->GetFile();
9659 MoveReadCache(file,nullptr);
9660 }
9661 fDirectory = nullptr;
9662 fCacheDoAutoInit = true;
9663 fCacheUserSet = false;
9664 Version_t R__v = b.ReadVersion(&R__s, &R__c);
9665 if (R__v > 4) {
9666 b.ReadClassBuffer(TTree::Class(), this, R__v, R__s, R__c);
9667
9668 fBranches.SetOwner(true); // True needed only for R__v < 19 and most R__v == 19
9669
9670 if (fBranchRef) fBranchRef->SetTree(this);
9673
9674 if (fTreeIndex) {
9675 fTreeIndex->SetTree(this);
9676 }
9677 if (fIndex.fN) {
9678 Warning("Streamer", "Old style index in this tree is deleted. Rebuild the index via TTree::BuildIndex");
9679 fIndex.Set(0);
9680 fIndexValues.Set(0);
9681 }
9682 if (fEstimate <= 10000) {
9683 fEstimate = 1000000;
9684 }
9685
9686 if (fNClusterRange) {
9687 // The I/O allocated just enough memory to hold the
9688 // current set of ranges.
9690 }
9691
9692 // Throughs calls to `GetCacheAutoSize` or `EnableCache` (for example
9693 // by TTreePlayer::Process, the cache size will be automatically
9694 // determined unless the user explicitly call `SetCacheSize`
9695 fCacheSize = 0;
9696 fCacheUserSet = false;
9697
9699 return;
9700 }
9701 //====process old versions before automatic schema evolution
9702 Stat_t djunk;
9703 Int_t ijunk;
9708 b >> fScanField;
9711 b >> djunk; fEntries = (Long64_t)djunk;
9716 if (fEstimate <= 10000) fEstimate = 1000000;
9718 if (fBranchRef) fBranchRef->SetTree(this);
9722 if (R__v > 1) fIndexValues.Streamer(b);
9723 if (R__v > 2) fIndex.Streamer(b);
9724 if (R__v > 3) {
9726 OldInfoList.Streamer(b);
9727 OldInfoList.Delete();
9728 }
9729 fNClusterRange = 0;
9732 b.CheckByteCount(R__s, R__c, TTree::IsA());
9733 //====end of old versions
9734 } else {
9735 if (fBranchRef) {
9736 fBranchRef->Clear();
9737 }
9739 if (table) TRefTable::SetRefTable(nullptr);
9740
9741 b.WriteClassBuffer(TTree::Class(), this);
9742
9743 if (table) TRefTable::SetRefTable(table);
9744 }
9745}
9746
9747////////////////////////////////////////////////////////////////////////////////
9748/// Unbinned fit of one or more variable(s) from a tree.
9749///
9750/// funcname is a TF1 function.
9751///
9752/// \note see TTree::Draw for explanations of the other parameters.
9753///
9754/// Fit the variable varexp using the function funcname using the
9755/// selection cuts given by selection.
9756///
9757/// The list of fit options is given in parameter option.
9758///
9759/// - option = "Q" Quiet mode (minimum printing)
9760/// - option = "V" Verbose mode (default is between Q and V)
9761/// - option = "E" Perform better Errors estimation using Minos technique
9762/// - option = "M" More. Improve fit results
9763///
9764/// You can specify boundary limits for some or all parameters via
9765/// ~~~ {.cpp}
9766/// func->SetParLimits(p_number, parmin, parmax);
9767/// ~~~
9768/// if parmin>=parmax, the parameter is fixed
9769///
9770/// Note that you are not forced to fix the limits for all parameters.
9771/// For example, if you fit a function with 6 parameters, you can do:
9772/// ~~~ {.cpp}
9773/// func->SetParameters(0,3.1,1.e-6,0.1,-8,100);
9774/// func->SetParLimits(4,-10,-4);
9775/// func->SetParLimits(5, 1,1);
9776/// ~~~
9777/// With this setup:
9778///
9779/// - Parameters 0->3 can vary freely
9780/// - Parameter 4 has boundaries [-10,-4] with initial value -8
9781/// - Parameter 5 is fixed to 100.
9782///
9783/// For the fit to be meaningful, the function must be self-normalized.
9784///
9785/// i.e. It must have the same integral regardless of the parameter
9786/// settings. Otherwise the fit will effectively just maximize the
9787/// area.
9788///
9789/// It is mandatory to have a normalization variable
9790/// which is fixed for the fit. e.g.
9791/// ~~~ {.cpp}
9792/// TF1* f1 = new TF1("f1", "gaus(0)/sqrt(2*3.14159)/[2]", 0, 5);
9793/// f1->SetParameters(1, 3.1, 0.01);
9794/// f1->SetParLimits(0, 1, 1); // fix the normalization parameter to 1
9795/// data->UnbinnedFit("f1", "jpsimass", "jpsipt>3.0");
9796/// ~~~
9797/// 1, 2 and 3 Dimensional fits are supported. See also TTree::Fit
9798///
9799/// Return status:
9800///
9801/// - The function return the status of the fit in the following form
9802/// fitResult = migradResult + 10*minosResult + 100*hesseResult + 1000*improveResult
9803/// - The fitResult is 0 is the fit is OK.
9804/// - The fitResult is negative in case of an error not connected with the fit.
9805/// - The number of entries used in the fit can be obtained via mytree.GetSelectedRows();
9806/// - If the number of selected entries is null the function returns -1
9809{
9810 GetPlayer();
9811 if (fPlayer) {
9813 }
9814 return -1;
9815}
9816
9817////////////////////////////////////////////////////////////////////////////////
9818/// Replace current attributes by current style.
9841}
9842
9843////////////////////////////////////////////////////////////////////////////////
9844/// Write this object to the current directory. For more see TObject::Write
9845/// If option & kFlushBasket, call FlushBasket before writing the tree.
9847Int_t TTree::Write(const char *name, Int_t option, Int_t bufsize) const
9848{
9851 return 0;
9853}
9854
9855////////////////////////////////////////////////////////////////////////////////
9856/// Write this object to the current directory. For more see TObject::Write
9857/// If option & kFlushBasket, call FlushBasket before writing the tree.
9860{
9861 return ((const TTree*)this)->Write(name, option, bufsize);
9862}
9863
9864////////////////////////////////////////////////////////////////////////////////
9865/// \class TTreeFriendLeafIter
9866///
9867/// Iterator on all the leaves in a TTree and its friend
9868
9870
9871////////////////////////////////////////////////////////////////////////////////
9872/// Create a new iterator. By default the iteration direction
9873/// is kIterForward. To go backward use kIterBackward.
9876: fTree(const_cast<TTree*>(tree))
9877, fLeafIter(nullptr)
9878, fTreeIter(nullptr)
9879, fDirection(dir)
9880{
9881}
9882
9883////////////////////////////////////////////////////////////////////////////////
9884/// Copy constructor. Does NOT copy the 'cursor' location!
9887: TIterator(iter)
9888, fTree(iter.fTree)
9889, fLeafIter(nullptr)
9890, fTreeIter(nullptr)
9891, fDirection(iter.fDirection)
9892{
9893}
9894
9895////////////////////////////////////////////////////////////////////////////////
9896/// Overridden assignment operator. Does NOT copy the 'cursor' location!
9899{
9900 if (this != &rhs && rhs.IsA() == TTreeFriendLeafIter::Class()) {
9902 fDirection = rhs1.fDirection;
9903 }
9904 return *this;
9905}
9906
9907////////////////////////////////////////////////////////////////////////////////
9908/// Overridden assignment operator. Does NOT copy the 'cursor' location!
9911{
9912 if (this != &rhs) {
9913 fDirection = rhs.fDirection;
9914 }
9915 return *this;
9916}
9917
9918////////////////////////////////////////////////////////////////////////////////
9919/// Go the next friend element
9922{
9923 if (!fTree) return nullptr;
9924
9925 TObject * next;
9926 TTree * nextTree;
9927
9928 if (!fLeafIter) {
9929 TObjArray *list = fTree->GetListOfLeaves();
9930 if (!list) return nullptr; // Can happen with an empty chain.
9931 fLeafIter = list->MakeIterator(fDirection);
9932 if (!fLeafIter) return nullptr;
9933 }
9934
9935 next = fLeafIter->Next();
9936 if (!next) {
9937 if (!fTreeIter) {
9939 if (!list) return next;
9940 fTreeIter = list->MakeIterator(fDirection);
9941 if (!fTreeIter) return nullptr;
9942 }
9944 ///nextTree = (TTree*)fTreeIter->Next();
9945 if (nextFriend) {
9946 nextTree = const_cast<TTree*>(nextFriend->GetTree());
9947 if (!nextTree) return Next();
9949 fLeafIter = nextTree->GetListOfLeaves()->MakeIterator(fDirection);
9950 if (!fLeafIter) return nullptr;
9951 next = fLeafIter->Next();
9952 }
9953 }
9954 return next;
9955}
9956
9957////////////////////////////////////////////////////////////////////////////////
9958/// Returns the object option stored in the list.
9961{
9962 if (fLeafIter) return fLeafIter->GetOption();
9963 return "";
9964}
#define R__unlikely(expr)
Definition RConfig.hxx:602
#define SafeDelete(p)
Definition RConfig.hxx:541
#define b(i)
Definition RSha256.hxx:100
#define f(i)
Definition RSha256.hxx:104
#define c(i)
Definition RSha256.hxx:101
#define a(i)
Definition RSha256.hxx:99
size_t size(const MatrixT &matrix)
retrieve the size of a square matrix
int Int_t
Definition RtypesCore.h:45
short Version_t
Definition RtypesCore.h:65
long Long_t
Definition RtypesCore.h:54
unsigned int UInt_t
Definition RtypesCore.h:46
float Float_t
Definition RtypesCore.h:57
double Double_t
Definition RtypesCore.h:59
constexpr Ssiz_t kNPOS
Definition RtypesCore.h:117
long long Long64_t
Definition RtypesCore.h:69
unsigned long long ULong64_t
Definition RtypesCore.h:70
const char Option_t
Definition RtypesCore.h:66
#define ClassImp(name)
Definition Rtypes.h:374
const Int_t kDoNotProcess
Definition TBranch.h:56
ROOT::Detail::TRangeCast< T, true > TRangeDynCast
TRangeDynCast is an adapter class that allows the typed iteration through a TCollection.
EDataType
Definition TDataType.h:28
@ kNoType_t
Definition TDataType.h:33
@ kFloat_t
Definition TDataType.h:31
@ kULong64_t
Definition TDataType.h:32
@ kInt_t
Definition TDataType.h:30
@ kchar
Definition TDataType.h:31
@ kLong_t
Definition TDataType.h:30
@ kDouble32_t
Definition TDataType.h:31
@ kShort_t
Definition TDataType.h:29
@ kBool_t
Definition TDataType.h:32
@ kBits
Definition TDataType.h:34
@ kULong_t
Definition TDataType.h:30
@ kLong64_t
Definition TDataType.h:32
@ kUShort_t
Definition TDataType.h:29
@ kDouble_t
Definition TDataType.h:31
@ kCharStar
Definition TDataType.h:34
@ kChar_t
Definition TDataType.h:29
@ kUChar_t
Definition TDataType.h:29
@ kCounter
Definition TDataType.h:34
@ kUInt_t
Definition TDataType.h:30
@ kFloat16_t
Definition TDataType.h:33
@ kOther_t
Definition TDataType.h:32
#define gDirectory
Definition TDirectory.h:384
R__EXTERN TEnv * gEnv
Definition TEnv.h:170
#define R__ASSERT(e)
Checks condition e and reports a fatal error if it's false.
Definition TError.h:125
void Error(const char *location, const char *msgfmt,...)
Use this function in case an error occurred.
Definition TError.cxx:185
#define N
static unsigned int total
Option_t Option_t option
Option_t Option_t SetLineWidth
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t cursor
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t Float_t Float_t Int_t Int_t UInt_t UInt_t Rectangle_t Int_t Int_t Window_t TString Int_t GCValues_t GetPrimarySelectionOwner GetDisplay GetScreen GetColormap GetNativeEvent const char const char dpyName wid window const char font_name cursor keysym reg const char only_if_exist regb h Point_t winding char text const char depth char const char Int_t count const char ColorStruct_t color const char filename
Option_t Option_t SetFillStyle
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t Float_t Float_t Int_t Int_t UInt_t UInt_t Rectangle_t Int_t Int_t Window_t TString Int_t GCValues_t GetPrimarySelectionOwner GetDisplay GetScreen GetColormap GetNativeEvent const char const char dpyName wid window const char font_name cursor keysym reg const char only_if_exist regb h Point_t winding char text const char depth char const char Int_t count const char ColorStruct_t color const char Pixmap_t Pixmap_t PictureAttributes_t attr const char char ret_data h unsigned char height h offset
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t Float_t Float_t Int_t Int_t UInt_t UInt_t Rectangle_t result
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t index
Option_t Option_t SetLineColor
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t Float_t Float_t Int_t Int_t UInt_t UInt_t Rectangle_t Int_t Int_t Window_t TString Int_t GCValues_t GetPrimarySelectionOwner GetDisplay GetScreen GetColormap GetNativeEvent const char const char dpyName wid window const char font_name cursor keysym reg const char only_if_exist regb h Point_t winding char text const char depth char const char Int_t count const char ColorStruct_t color const char Pixmap_t Pixmap_t PictureAttributes_t attr const char char ret_data h unsigned char height h Atom_t Int_t ULong_t ULong_t unsigned char prop_list Atom_t Atom_t Atom_t Time_t UChar_t len
Option_t Option_t SetFillColor
Option_t Option_t SetMarkerStyle
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t src
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void reg
Option_t Option_t style
char name[80]
Definition TGX11.cxx:110
int nentries
R__EXTERN TInterpreter * gCling
Int_t gDebug
Definition TROOT.cxx:597
R__EXTERN TVirtualMutex * gROOTMutex
Definition TROOT.h:63
#define gROOT
Definition TROOT.h:406
void Printf(const char *fmt,...)
Formats a string in a circular formatting buffer and prints the string.
Definition TString.cxx:2503
R__EXTERN TStyle * gStyle
Definition TStyle.h:442
R__EXTERN TSystem * gSystem
Definition TSystem.h:572
constexpr Int_t kNEntriesResort
Definition TTree.cxx:440
static TBranch * R__FindBranchHelper(TObjArray *list, const char *branchname)
Search in the array for a branch matching the branch name, with the branch possibly expressed as a 'f...
Definition TTree.cxx:4794
static char DataTypeToChar(EDataType datatype)
Definition TTree.cxx:452
void TFriendElement__SetTree(TTree *tree, TList *frlist)
Set the fTree member for all friend elements.
Definition TTree.cxx:9635
bool CheckReshuffling(TTree &mainTree, TTree &friendTree)
Definition TTree.cxx:1230
static void TBranch__SetTree(TTree *tree, TObjArray &branches)
Set the fTree member for all branches and sub branches.
Definition TTree.cxx:9613
constexpr Float_t kNEntriesResortInv
Definition TTree.cxx:441
#define R__LOCKGUARD(mutex)
#define gPad
#define snprintf
Definition civetweb.c:1540
A helper class for managing IMT work during TTree:Fill operations.
const_iterator end() const
TIOFeatures provides the end-user with the ability to change the IO behavior of data written via a TT...
UChar_t GetFeatures() const
bool Set(EIOFeatures bits)
Set a specific IO feature.
This class provides a simple interface to execute the same task multiple times in parallel threads,...
void Streamer(TBuffer &) override
Stream a TArrayD object.
Definition TArrayD.cxx:149
void Set(Int_t n) override
Set size of this array to n doubles.
Definition TArrayD.cxx:106
void Set(Int_t n) override
Set size of this array to n ints.
Definition TArrayI.cxx:105
void Streamer(TBuffer &) override
Stream a TArrayI object.
Definition TArrayI.cxx:148
Int_t fN
Definition TArray.h:38
Fill Area Attributes class.
Definition TAttFill.h:20
virtual void Streamer(TBuffer &)
virtual Color_t GetFillColor() const
Return the fill area color.
Definition TAttFill.h:31
virtual Style_t GetFillStyle() const
Return the fill area style.
Definition TAttFill.h:32
Line Attributes class.
Definition TAttLine.h:20
virtual void Streamer(TBuffer &)
virtual Color_t GetLineColor() const
Return the line color.
Definition TAttLine.h:35
virtual void SetLineStyle(Style_t lstyle)
Set the line style.
Definition TAttLine.h:44
virtual Width_t GetLineWidth() const
Return the line width.
Definition TAttLine.h:37
virtual Style_t GetLineStyle() const
Return the line style.
Definition TAttLine.h:36
Marker Attributes class.
Definition TAttMarker.h:20
virtual Style_t GetMarkerStyle() const
Return the marker style.
Definition TAttMarker.h:33
virtual void SetMarkerColor(Color_t mcolor=1)
Set the marker color.
Definition TAttMarker.h:39
virtual Color_t GetMarkerColor() const
Return the marker color.
Definition TAttMarker.h:32
virtual Size_t GetMarkerSize() const
Return the marker size.
Definition TAttMarker.h:34
virtual void SetMarkerStyle(Style_t mstyle=1)
Set the marker style.
Definition TAttMarker.h:41
virtual void Streamer(TBuffer &)
virtual void SetMarkerSize(Size_t msize=1)
Set the marker size.
Definition TAttMarker.h:46
Each class (see TClass) has a linked list of its base class(es).
Definition TBaseClass.h:33
ROOT::ESTLType IsSTLContainer()
Return which type (if any) of STL container the data member is.
Manages buffers for branches of a Tree.
Definition TBasket.h:34
A Branch for the case of an array of clone objects.
A Branch for the case of an object.
static TClass * Class()
A Branch for the case of an object.
A branch containing and managing a TRefTable for TRef autoloading.
Definition TBranchRef.h:34
void Reset(Option_t *option="") override
void Print(Option_t *option="") const override
Print the TRefTable branch.
void Clear(Option_t *option="") override
Clear entries in the TRefTable.
void ResetAfterMerge(TFileMergeInfo *) override
Reset a Branch after a Merge operation (drop data but keep customizations) TRefTable is cleared.
A Branch handling STL collection of pointers (vectors, lists, queues, sets and multisets) while stori...
Definition TBranchSTL.h:22
A TTree is a list of TBranches.
Definition TBranch.h:93
static TClass * Class()
TObjArray * GetListOfBranches()
Definition TBranch.h:246
virtual void SetTree(TTree *tree)
Definition TBranch.h:287
static void ResetCount()
Static function resetting fgCount.
Definition TBranch.cxx:2674
virtual void SetFile(TFile *file=nullptr)
Set file where this branch writes/reads its buffers.
Definition TBranch.cxx:2876
virtual void SetEntryOffsetLen(Int_t len, bool updateSubBranches=false)
Update the default value for the branch's fEntryOffsetLen if and only if it was already non zero (and...
Definition TBranch.cxx:2834
virtual void UpdateFile()
Refresh the value of fDirectory (i.e.
Definition TBranch.cxx:3317
Int_t Fill()
Definition TBranch.h:205
Using a TBrowser one can browse all ROOT objects.
Definition TBrowser.h:37
The concrete implementation of TBuffer for writing/reading to/from a ROOT file or socket.
Definition TBufferFile.h:47
Buffer base class used for serializing objects.
Definition TBuffer.h:43
void Expand(Int_t newsize, Bool_t copy=kTRUE)
Expand (or shrink) the I/O buffer to newsize bytes.
Definition TBuffer.cxx:223
Int_t BufferSize() const
Definition TBuffer.h:98
@ kWrite
Definition TBuffer.h:73
@ kRead
Definition TBuffer.h:73
TClass instances represent classes, structs and namespaces in the ROOT type system.
Definition TClass.h:84
Bool_t CanSplit() const
Return true if the data member of this TClass can be saved separately.
Definition TClass.cxx:2420
ROOT::ESTLType GetCollectionType() const
Return the 'type' of the STL the TClass is representing.
Definition TClass.cxx:2987
void * New(ENewType defConstructor=kClassNew, Bool_t quiet=kFALSE) const
Return a pointer to a newly allocated object of this class.
Definition TClass.cxx:5100
Bool_t HasDataMemberInfo() const
Definition TClass.h:413
Bool_t HasCustomStreamerMember() const
The class has a Streamer method and it is implemented by the user or an older (not StreamerInfo based...
Definition TClass.h:515
void Destructor(void *obj, Bool_t dtorOnly=kFALSE)
Explicitly call destructor for object.
Definition TClass.cxx:5522
void BuildRealData(void *pointer=nullptr, Bool_t isTransient=kFALSE)
Build a full list of persistent data members.
Definition TClass.cxx:2132
TList * GetListOfRealData() const
Definition TClass.h:460
Bool_t CanIgnoreTObjectStreamer()
Definition TClass.h:399
TList * GetListOfBases()
Return list containing the TBaseClass(es) of a class.
Definition TClass.cxx:3746
Bool_t IsTObject() const
Return kTRUE is the class inherits from TObject.
Definition TClass.cxx:6060
TVirtualStreamerInfo * GetStreamerInfo(Int_t version=0, Bool_t isTransient=kFALSE) const
returns a pointer to the TVirtualStreamerInfo object for version If the object does not exist,...
Definition TClass.cxx:4709
TVirtualCollectionProxy * GetCollectionProxy() const
Return the proxy describing the collection (if any).
Definition TClass.cxx:2998
Version_t GetClassVersion() const
Definition TClass.h:427
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:3069
An array of clone (identical) objects.
static TClass * Class()
Collection abstract base class.
Definition TCollection.h:65
static TClass * Class()
void SetName(const char *name)
const char * GetName() const override
Return name of this collection.
virtual Int_t GetEntries() const
virtual void SetOwner(Bool_t enable=kTRUE)
Set whether this collection is the owner (enable==true) of its content.
void Browse(TBrowser *b) override
Browse this collection (called by TBrowser).
A specialized string object used for TTree selections.
Definition TCut.h:25
All ROOT classes may have RTTI (run time type identification) support added.
Definition TDataMember.h:31
Bool_t IsPersistent() const
Definition TDataMember.h:91
Bool_t IsBasic() const
Return true if data member is a basic type, e.g. char, int, long...
Bool_t IsaPointer() const
Return true if data member is a pointer.
TDataType * GetDataType() const
Definition TDataMember.h:76
Longptr_t GetOffset() const
Get offset from "this".
const char * GetTypeName() const
Get the decayed type name of this data member, removing const and volatile qualifiers,...
const char * GetArrayIndex() const
If the data member is pointer and has a valid array size in its comments GetArrayIndex returns a stri...
const char * GetFullTypeName() const
Get the concrete type name of this data member, including const and volatile qualifiers.
Basic data type descriptor (datatype information is obtained from CINT).
Definition TDataType.h:44
Int_t GetType() const
Definition TDataType.h:68
TString GetTypeName()
Get basic type of typedef, e,g.: "class TDirectory*" -> "TDirectory".
Bool_t cd() override
Change current directory to "this" directory.
Bool_t IsWritable() const override
TDirectory::TContext keeps track and restore the current directory.
Definition TDirectory.h:89
Describe directory structure in memory.
Definition TDirectory.h:45
virtual TList * GetList() const
Definition TDirectory.h:222
virtual void Append(TObject *obj, Bool_t replace=kFALSE)
Append object to this directory.
virtual Int_t WriteTObject(const TObject *obj, const char *name=nullptr, Option_t *="", Int_t=0)
Write an object with proper type checking.
virtual TFile * GetFile() const
Definition TDirectory.h:220
virtual Int_t ReadKeys(Bool_t=kTRUE)
Definition TDirectory.h:248
virtual Bool_t IsWritable() const
Definition TDirectory.h:237
virtual TKey * GetKey(const char *, Short_t=9999) const
Definition TDirectory.h:221
virtual void SaveSelf(Bool_t=kFALSE)
Definition TDirectory.h:255
virtual TList * GetListOfKeys() const
Definition TDirectory.h:223
void GetObject(const char *namecycle, T *&ptr)
Get an object with proper type checking.
Definition TDirectory.h:212
virtual TObject * Remove(TObject *)
Remove an object from the in-memory list.
Streamer around an arbitrary STL like container, which implements basic container functionality.
A List of entry numbers in a TTree or TChain.
Definition TEntryList.h:26
virtual bool Enter(Long64_t entry, TTree *tree=nullptr)
Add entry #entry to the list.
virtual void SetTree(const TTree *tree)
If a list for a tree with such name and filename exists, sets it as the current sublist If not,...
virtual TDirectory * GetDirectory() const
Definition TEntryList.h:77
virtual void SetReapplyCut(bool apply=false)
Definition TEntryList.h:108
virtual void SetDirectory(TDirectory *dir)
Add reference to directory dir. dir can be 0.
virtual Long64_t GetEntry(Long64_t index)
Return the number of the entry #index of this TEntryList in the TTree or TChain See also Next().
virtual Int_t GetValue(const char *name, Int_t dflt) const
Returns the integer value for a resource.
Definition TEnv.cxx:491
<div class="legacybox"><h2>Legacy Code</h2> TEventList is a legacy interface: there will be no bug fi...
Definition TEventList.h:31
A cache when reading files over the network.
virtual Int_t GetBufferSize() const
A ROOT file is an on-disk file, usually with extension .root, that stores objects in a file-system-li...
Definition TFile.h:131
virtual void SetCacheRead(TFileCacheRead *cache, TObject *tree=nullptr, ECacheAction action=kDisconnect)
Set a pointer to the read cache.
Definition TFile.cxx:2406
Int_t GetCompressionSettings() const
Definition TFile.h:484
Int_t GetCompressionLevel() const
Definition TFile.h:478
virtual void WriteStreamerInfo()
Write the list of TStreamerInfo as a single object in this file The class Streamer description for al...
Definition TFile.cxx:3833
@ kDoNotDisconnect
Definition TFile.h:149
static TFile * Open(const char *name, Option_t *option="", const char *ftitle="", Int_t compress=ROOT::RCompressionSetting::EDefaults::kUseCompiledDefault, Int_t netopt=0)
Create / open a file.
Definition TFile.cxx:4130
virtual void WriteHeader()
Write File Header.
Definition TFile.cxx:2656
@ kCancelTTreeChangeRequest
Definition TFile.h:280
TFileCacheRead * GetCacheRead(const TObject *tree=nullptr) const
Return a pointer to the current read cache.
Definition TFile.cxx:1267
<div class="legacybox"><h2>Legacy Code</h2> TFolder is a legacy interface: there will be no bug fixes...
Definition TFolder.h:30
static TClass * Class()
A TFriendElement TF describes a TTree object TF in a file.
virtual TTree * GetTree()
Return pointer to friend TTree.
virtual Int_t DeleteGlobal(void *obj)=0
void Reset()
Iterator abstract base class.
Definition TIterator.h:30
virtual TObject * Next()=0
virtual Option_t * GetOption() const
Definition TIterator.h:40
Book space in a file, create I/O buffers, to fill them, (un)compress them.
Definition TKey.h:28
void Delete(Option_t *option="") override
Delete an object from the file.
Definition TKey.cxx:538
Int_t GetKeylen() const
Definition TKey.h:84
Int_t GetNbytes() const
Definition TKey.h:86
virtual const char * GetClassName() const
Definition TKey.h:75
static TClass * Class()
static TClass * Class()
static TClass * Class()
static TClass * Class()
A TLeaf describes individual elements of a TBranch See TBranch structure in TTree.
Definition TLeaf.h:57
virtual Int_t GetLenType() const
Definition TLeaf.h:133
virtual Int_t GetLen() const
Return the number of effective elements of this leaf, for the current entry.
Definition TLeaf.cxx:404
@ kNewValue
Set if we own the value buffer and so must delete it ourselves.
Definition TLeaf.h:96
@ kIndirectAddress
Data member is a pointer to an array of basic types.
Definition TLeaf.h:95
virtual Int_t GetOffset() const
Definition TLeaf.h:137
A doubly linked list.
Definition TList.h:38
void Clear(Option_t *option="") override
Remove all objects from the list.
Definition TList.cxx:400
TObject * FindObject(const char *name) const override
Find an object in this list using its name.
Definition TList.cxx:576
void RecursiveRemove(TObject *obj) override
Remove object from this collection and recursively remove the object from all other objects (and coll...
Definition TList.cxx:762
void Add(TObject *obj) override
Definition TList.h:81
TObject * Remove(TObject *obj) override
Remove object from the list.
Definition TList.cxx:820
virtual TObjLink * FirstLink() const
Definition TList.h:102
void Delete(Option_t *option="") override
Remove all objects from the list AND delete all heap based objects.
Definition TList.cxx:468
TObject * At(Int_t idx) const override
Returns the object at position idx. Returns 0 if idx is out of range.
Definition TList.cxx:355
A TMemFile is like a normal TFile except that it reads and writes only from memory.
Definition TMemFile.h:19
The TNamed class is the base class for all named ROOT classes.
Definition TNamed.h:29
const char * GetName() const override
Returns name of object.
Definition TNamed.h:49
void Streamer(TBuffer &) override
Stream an object of class TObject.
const char * GetTitle() const override
Returns title of object.
Definition TNamed.h:50
TString fTitle
Definition TNamed.h:33
TNamed()
Definition TNamed.h:38
TString fName
Definition TNamed.h:32
See TNotifyLink.
Definition TNotifyLink.h:47
An array of TObjects.
Definition TObjArray.h:31
Int_t GetEntriesFast() const
Definition TObjArray.h:58
Int_t GetEntriesUnsafe() const
Return the number of objects in array (i.e.
void Clear(Option_t *option="") override
Remove all objects from the array.
void Streamer(TBuffer &) override
Stream all objects in the array to or from the I/O buffer.
Int_t GetEntries() const override
Return the number of objects in array (i.e.
void Delete(Option_t *option="") override
Remove all objects from the array AND delete all heap based objects.
TObject * At(Int_t idx) const override
Definition TObjArray.h:164
TObject * UncheckedAt(Int_t i) const
Definition TObjArray.h:84
Bool_t IsEmpty() const override
Definition TObjArray.h:65
TObject * FindObject(const char *name) const override
Find an object in this collection using its name.
void Add(TObject *obj) override
Definition TObjArray.h:68
Mother of all ROOT objects.
Definition TObject.h:41
virtual Bool_t Notify()
This method must be overridden to handle object notification (the base implementation is no-op).
Definition TObject.cxx:612
virtual const char * GetName() const
Returns name of object.
Definition TObject.cxx:457
R__ALWAYS_INLINE Bool_t TestBit(UInt_t f) const
Definition TObject.h:205
@ kBitMask
Definition TObject.h:92
virtual const char * ClassName() const
Returns name of class to which the object belongs.
Definition TObject.cxx:226
virtual void Warning(const char *method, const char *msgfmt,...) const
Issue warning message.
Definition TObject.cxx:1057
R__ALWAYS_INLINE Bool_t IsZombie() const
Definition TObject.h:159
virtual Int_t Write(const char *name=nullptr, Int_t option=0, Int_t bufsize=0)
Write this object to the current directory.
Definition TObject.cxx:964
@ kOnlyPrepStep
Used to request that the class specific implementation of TObject::Write just prepare the objects to ...
Definition TObject.h:112
void SetBit(UInt_t f, Bool_t set)
Set or unset the user status bits as specified in f.
Definition TObject.cxx:864
virtual Bool_t InheritsFrom(const char *classname) const
Returns kTRUE if object inherits from class "classname".
Definition TObject.cxx:543
virtual void Error(const char *method, const char *msgfmt,...) const
Issue error message.
Definition TObject.cxx:1071
virtual void Fatal(const char *method, const char *msgfmt,...) const
Issue fatal error message.
Definition TObject.cxx:1099
virtual TClass * IsA() const
Definition TObject.h:249
void ResetBit(UInt_t f)
Definition TObject.h:204
@ kCanDelete
if object in a list can be deleted
Definition TObject.h:68
@ kMustCleanup
if object destructor must call RecursiveRemove()
Definition TObject.h:70
Principal Components Analysis (PCA)
Definition TPrincipal.h:21
The TRealData class manages the effective list of all data members for a given class.
Definition TRealData.h:30
A TRefTable maintains the association between a referenced object and the parent object supporting th...
Definition TRefTable.h:35
static void SetRefTable(TRefTable *table)
Static function setting the current TRefTable.
static TRefTable * GetRefTable()
Static function returning the current TRefTable.
Regular expression class.
Definition TRegexp.h:31
A TSelector object is used by the TTree::Draw, TTree::Scan, TTree::Process to navigate in a TTree and...
Definition TSelector.h:31
static void * ReAlloc(void *vp, size_t size, size_t oldsize)
Reallocate (i.e.
Definition TStorage.cxx:183
Describes a persistent version of a class.
Basic string class.
Definition TString.h:139
Ssiz_t Length() const
Definition TString.h:417
void ToLower()
Change string to lower-case.
Definition TString.cxx:1182
static constexpr Ssiz_t kNPOS
Definition TString.h:278
Double_t Atof() const
Return floating-point value contained in string.
Definition TString.cxx:2054
const char * Data() const
Definition TString.h:376
Bool_t EqualTo(const char *cs, ECaseCompare cmp=kExact) const
Definition TString.h:645
TString & ReplaceAll(const TString &s1, const TString &s2)
Definition TString.h:704
@ kLeading
Definition TString.h:276
@ kTrailing
Definition TString.h:276
@ kIgnoreCase
Definition TString.h:277
static TString Format(const char *fmt,...)
Static method which formats a string using a printf style format descriptor and return a TString.
Definition TString.cxx:2378
void Form(const char *fmt,...)
Formats a string using a printf style format descriptor.
Definition TString.cxx:2356
Bool_t Contains(const char *pat, ECaseCompare cmp=kExact) const
Definition TString.h:632
Ssiz_t Index(const char *pat, Ssiz_t i=0, ECaseCompare cmp=kExact) const
Definition TString.h:651
void SetHistFillColor(Color_t color=1)
Definition TStyle.h:383
Color_t GetHistLineColor() const
Definition TStyle.h:235
Bool_t IsReading() const
Definition TStyle.h:300
void SetHistLineStyle(Style_t styl=0)
Definition TStyle.h:386
Style_t GetHistFillStyle() const
Definition TStyle.h:236
Color_t GetHistFillColor() const
Definition TStyle.h:234
void SetHistLineColor(Color_t color=1)
Definition TStyle.h:384
Style_t GetHistLineStyle() const
Definition TStyle.h:237
void SetHistFillStyle(Style_t styl=0)
Definition TStyle.h:385
Width_t GetHistLineWidth() const
Definition TStyle.h:238
void SetHistLineWidth(Width_t width=1)
Definition TStyle.h:387
A zero length substring is legal.
Definition TString.h:85
virtual const char * Getenv(const char *env)
Get environment variable.
Definition TSystem.cxx:1676
virtual Bool_t AccessPathName(const char *path, EAccessMode mode=kFileExists)
Returns FALSE if one can access a file using the specified access mode.
Definition TSystem.cxx:1307
A TTreeCache which exploits parallelized decompression of its own content.
static bool IsParallelUnzip()
Static function that tells wether the multithreading unzipping is activated.
A cache to speed-up the reading of ROOT datasets.
Definition TTreeCache.h:32
static void SetLearnEntries(Int_t n=10)
Static function to set the number of entries to be used in learning mode The default value for n is 1...
Class implementing or helping the various TTree cloning method.
Definition TTreeCloner.h:31
Iterator on all the leaves in a TTree and its friend.
Definition TTree.h:717
TTree * fTree
tree being iterated
Definition TTree.h:720
TIterator & operator=(const TIterator &rhs) override
Overridden assignment operator. Does NOT copy the 'cursor' location!
Definition TTree.cxx:9897
TObject * Next() override
Go the next friend element.
Definition TTree.cxx:9920
TIterator * fLeafIter
current leaf sub-iterator.
Definition TTree.h:721
Option_t * GetOption() const override
Returns the object option stored in the list.
Definition TTree.cxx:9959
TIterator * fTreeIter
current tree sub-iterator.
Definition TTree.h:722
bool fDirection
iteration direction
Definition TTree.h:723
static TClass * Class()
Helper class to iterate over cluster of baskets.
Definition TTree.h:271
Long64_t GetEstimatedClusterSize()
Estimate the cluster size.
Definition TTree.cxx:601
Long64_t Previous()
Move on to the previous cluster and return the starting entry of this previous cluster.
Definition TTree.cxx:684
Long64_t Next()
Move on to the next cluster and return the starting entry of this next cluster.
Definition TTree.cxx:640
Long64_t GetNextEntry()
Definition TTree.h:308
TClusterIterator(TTree *tree, Long64_t firstEntry)
Regular constructor.
Definition TTree.cxx:550
Helper class to prevent infinite recursion in the usage of TTree Friends.
Definition TTree.h:188
TFriendLock & operator=(const TFriendLock &)
Assignment operator.
Definition TTree.cxx:520
TFriendLock(const TFriendLock &)
Copy constructor.
Definition TTree.cxx:510
UInt_t fMethodBit
Definition TTree.h:192
TTree * fTree
Definition TTree.h:191
~TFriendLock()
Restore the state of tree the same as before we set the lock.
Definition TTree.cxx:533
A TTree represents a columnar dataset.
Definition TTree.h:79
virtual Int_t Fill()
Fill all branches.
Definition TTree.cxx:4606
virtual TFriendElement * AddFriend(const char *treename, const char *filename="")
Add a TFriendElement to the list of friends.
Definition TTree.cxx:1322
TBranchRef * fBranchRef
Branch supporting the TRefTable (if any)
Definition TTree.h:136
TStreamerInfo * BuildStreamerInfo(TClass *cl, void *pointer=nullptr, bool canOptimize=true)
Build StreamerInfo for class cl.
Definition TTree.cxx:2645
virtual TBranch * FindBranch(const char *name)
Return the branch that correspond to the path 'branchname', which can include the name of the tree or...
Definition TTree.cxx:4842
virtual void SetBranchStatus(const char *bname, bool status=true, UInt_t *found=nullptr)
Set branch status to Process or DoNotProcess.
Definition TTree.cxx:8628
bool EnableCache()
Enable the TTreeCache unless explicitly disabled for this TTree by a prior call to SetCacheSize(0).
Definition TTree.cxx:2678
virtual TBranch * GetBranch(const char *name)
Return pointer to the branch with the given name in this tree or its friends.
Definition TTree.cxx:5295
static Int_t GetBranchStyle()
Static function returning the current branch style.
Definition TTree.cxx:5396
TList * fFriends
pointer to list of friend elements
Definition TTree.h:130
bool fIMTEnabled
! true if implicit multi-threading is enabled for this tree
Definition TTree.h:142
virtual bool GetBranchStatus(const char *branchname) const
Return status of branch with name branchname.
Definition TTree.cxx:5381
UInt_t fFriendLockStatus
! Record which method is locking the friend recursion
Definition TTree.h:137
virtual TLeaf * GetLeafImpl(const char *branchname, const char *leafname)
Return pointer to the 1st Leaf named name in any Branch of this Tree or any branch in the list of fri...
Definition TTree.cxx:6101
Long64_t fTotBytes
Total number of bytes in all branches before compression.
Definition TTree.h:86
virtual Int_t FlushBaskets(bool create_cluster=true) const
Write to disk all the basket that have not yet been individually written and create an event cluster ...
Definition TTree.cxx:5130
Int_t fMaxClusterRange
! Memory allocated for the cluster range.
Definition TTree.h:96
virtual void Show(Long64_t entry=-1, Int_t lenmax=20)
Print values of all active leaves for entry.
Definition TTree.cxx:9490
TEventList * fEventList
! Pointer to event selection list (if one)
Definition TTree.h:125
virtual Long64_t GetAutoSave() const
Definition TTree.h:449
virtual Int_t StopCacheLearningPhase()
Stop the cache learning phase.
Definition TTree.cxx:9579
virtual Int_t GetEntry(Long64_t entry, Int_t getall=0)
Read all branches of entry and return total number of bytes read.
Definition TTree.cxx:5641
std::vector< std::pair< Long64_t, TBranch * > > fSortedBranches
! Branches to be processed in parallel when IMT is on, sorted by average task time
Definition TTree.h:144
virtual void SetCircular(Long64_t maxEntries)
Enable/Disable circularity for this tree.
Definition TTree.cxx:8986
Long64_t fSavedBytes
Number of autosaved bytes.
Definition TTree.h:88
virtual Int_t AddBranchToCache(const char *bname, bool subbranches=false)
Add branch with name bname to the Tree cache.
Definition TTree.cxx:1049
Long64_t GetMedianClusterSize()
Estimate the median cluster size for the TTree.
Definition TTree.cxx:8391
virtual TClusterIterator GetClusterIterator(Long64_t firstentry)
Return an iterator over the cluster of baskets starting at firstentry.
Definition TTree.cxx:5468
virtual void ResetBranchAddress(TBranch *)
Tell a branch to set its address to zero.
Definition TTree.cxx:8145
bool fCacheUserSet
! true if the cache setting was explicitly given by user
Definition TTree.h:141
char GetNewlineValue(std::istream &inputStream)
Determine which newline this file is using.
Definition TTree.cxx:7668
TIOFeatures fIOFeatures
IO features to define for newly-written baskets and branches.
Definition TTree.h:114
virtual Long64_t GetEntryNumberWithIndex(Long64_t major, Long64_t minor=0) const
Return entry number corresponding to major and minor number.
Definition TTree.cxx:5913
Long64_t fDebugMin
! First entry number to debug
Definition TTree.h:112
virtual Long64_t SetEntries(Long64_t n=-1)
Change number of entries in the tree.
Definition TTree.cxx:9105
virtual TObjArray * GetListOfLeaves()
Definition TTree.h:530
virtual TBranch * BranchOld(const char *name, const char *classname, void *addobj, Int_t bufsize=32000, Int_t splitlevel=1)
Create a new TTree BranchObject.
Definition TTree.cxx:2067
Long64_t GetCacheAutoSize(bool withDefault=false)
Used for automatic sizing of the cache.
Definition TTree.cxx:5408
virtual TBranch * BranchRef()
Build the optional branch supporting the TRefTable.
Definition TTree.cxx:2321
TFile * GetCurrentFile() const
Return pointer to the current file.
Definition TTree.cxx:5480
TList * fAliases
List of aliases for expressions based on the tree branches.
Definition TTree.h:124
virtual TTree * CopyTree(const char *selection, Option_t *option="", Long64_t nentries=kMaxEntries, Long64_t firstentry=0)
Copy a tree with selection.
Definition TTree.cxx:3722
virtual Int_t DropBranchFromCache(const char *bname, bool subbranches=false)
Remove the branch with name 'bname' from the Tree cache.
Definition TTree.cxx:1132
virtual Int_t Fit(const char *funcname, const char *varexp, const char *selection="", Option_t *option="", Option_t *goption="", Long64_t nentries=kMaxEntries, Long64_t firstentry=0)
Fit a projected item(s) from a tree.
Definition TTree.cxx:5080
Long64_t * fClusterRangeEnd
[fNClusterRange] Last entry of a cluster range.
Definition TTree.h:103
void Streamer(TBuffer &) override
Stream a class object.
Definition TTree.cxx:9650
std::atomic< Long64_t > fIMTZipBytes
! Zip bytes for the IMT flush baskets.
Definition TTree.h:161
void RecursiveRemove(TObject *obj) override
Make sure that obj (which is being deleted or will soon be) is no longer referenced by this TTree.
Definition TTree.cxx:7961
TVirtualTreePlayer * GetPlayer()
Load the TTreePlayer (if not already done).
Definition TTree.cxx:6308
virtual Int_t MakeProxy(const char *classname, const char *macrofilename=nullptr, const char *cutfilename=nullptr, const char *option=nullptr, Int_t maxUnrolling=3)
Generate a skeleton analysis class for this Tree using TBranchProxy.
Definition TTree.cxx:6771
virtual Long64_t ReadStream(std::istream &inputStream, const char *branchDescriptor="", char delimiter=' ')
Create or simply read branches from an input stream.
Definition TTree.cxx:7695
virtual void SetDebug(Int_t level=1, Long64_t min=0, Long64_t max=9999999)
Set the debug level and the debug range.
Definition TTree.cxx:9022
Int_t fScanField
Number of runs before prompting in Scan.
Definition TTree.h:92
void Draw(Option_t *opt) override
Default Draw method for all objects.
Definition TTree.h:432
virtual TTree * GetFriend(const char *) const
Return a pointer to the TTree friend whose name or alias is friendname.
Definition TTree.cxx:5978
virtual void SetNotify(TObject *obj)
Sets the address of the object to be notified when the tree is loaded.
Definition TTree.cxx:9336
virtual Double_t GetMaximum(const char *columname)
Return maximum of column with name columname.
Definition TTree.cxx:6238
virtual Long64_t GetEntryNumberWithBestIndex(Long64_t major, Long64_t minor=0) const
Return entry number corresponding to major and minor number.
Definition TTree.cxx:5893
static void SetMaxTreeSize(Long64_t maxsize=100000000000LL)
Set the maximum size in bytes of a Tree file (static function).
Definition TTree.cxx:9302
void Print(Option_t *option="") const override
Print a summary of the tree contents.
Definition TTree.cxx:7298
virtual Int_t UnbinnedFit(const char *funcname, const char *varexp, const char *selection="", Option_t *option="", Long64_t nentries=kMaxEntries, Long64_t firstentry=0)
Unbinned fit of one or more variable(s) from a tree.
Definition TTree.cxx:9807
Int_t fNClusterRange
Number of Cluster range in addition to the one defined by 'AutoFlush'.
Definition TTree.h:95
virtual void PrintCacheStats(Option_t *option="") const
Print statistics about the TreeCache for this tree.
Definition TTree.cxx:7450
virtual Int_t BuildIndex(const char *majorname, const char *minorname="0")
Build a Tree Index (default is TTreeIndex).
Definition TTree.cxx:2630
TVirtualTreePlayer * fPlayer
! Pointer to current Tree player
Definition TTree.h:134
virtual TIterator * GetIteratorOnAllLeaves(bool dir=kIterForward)
Creates a new iterator that will go through all the leaves on the tree itself and its friend.
Definition TTree.cxx:6085
virtual void SetMakeClass(Int_t make)
Set all the branches in this TTree to be in decomposed object mode (also known as MakeClass mode).
Definition TTree.cxx:9282
virtual bool InPlaceClone(TDirectory *newdirectory, const char *options="")
Copy the content to a new new file, update this TTree with the new location information and attach th...
Definition TTree.cxx:7091
TObjArray fBranches
List of Branches.
Definition TTree.h:122
TDirectory * GetDirectory() const
Definition TTree.h:463
bool fCacheDoAutoInit
! true if cache auto creation or resize check is needed
Definition TTree.h:139
TTreeCache * GetReadCache(TFile *file) const
Find and return the TTreeCache registered with the file and which may contain branches for us.
Definition TTree.cxx:6321
Long64_t fEntries
Number of entries.
Definition TTree.h:84
virtual TFile * ChangeFile(TFile *file)
Called by TTree::Fill() when file has reached its maximum fgMaxTreeSize.
Definition TTree.cxx:2742
virtual TEntryList * GetEntryList()
Returns the entry list assigned to this tree.
Definition TTree.cxx:5857
virtual void SetWeight(Double_t w=1, Option_t *option="")
Set tree weight.
Definition TTree.cxx:9479
void InitializeBranchLists(bool checkLeafCount)
Divides the top-level branches into two vectors: (i) branches to be processed sequentially and (ii) b...
Definition TTree.cxx:5784
virtual Int_t SetBranchAddress(const char *bname, void *add, TBranch **ptr=nullptr)
Change branch address, dealing with clone trees properly.
Definition TTree.cxx:8479
Long64_t * fClusterSize
[fNClusterRange] Number of entries in each cluster for a given range.
Definition TTree.h:104
Long64_t fFlushedBytes
Number of auto-flushed bytes.
Definition TTree.h:89
virtual void SetPerfStats(TVirtualPerfStats *perf)
Set perf stats.
Definition TTree.cxx:9434
std::atomic< Long64_t > fIMTTotBytes
! Total bytes for the IMT flush baskets
Definition TTree.h:160
virtual void SetCacheLearnEntries(Int_t n=10)
Interface to TTreeCache to set the number of entries for the learning phase.
Definition TTree.cxx:8959
TEntryList * fEntryList
! Pointer to event selection list (if one)
Definition TTree.h:126
@ kSplitCollectionOfPointers
Definition TTree.h:267
virtual TVirtualIndex * GetTreeIndex() const
Definition TTree.h:559
TList * fExternalFriends
! List of TFriendsElement pointing to us and need to be notified of LoadTree. Content not owned.
Definition TTree.h:131
virtual Long64_t Merge(TCollection *list, Option_t *option="")
Merge the trees in the TList into this tree.
Definition TTree.cxx:6905
virtual void SetMaxVirtualSize(Long64_t size=0)
Definition TTree.h:666
virtual void DropBaskets()
Remove some baskets from memory.
Definition TTree.cxx:4521
virtual void SetAutoSave(Long64_t autos=-300000000)
In case of a program crash, it will be possible to recover the data in the tree up to the last AutoSa...
Definition TTree.cxx:8436
Long64_t fMaxEntryLoop
Maximum number of entries to process.
Definition TTree.h:98
virtual void SetParallelUnzip(bool opt=true, Float_t RelSize=-1)
Enable or disable parallel unzipping of Tree buffers.
Definition TTree.cxx:9396
virtual void SetDirectory(TDirectory *dir)
Change the tree's directory.
Definition TTree.cxx:9060
void SortBranchesByTime()
Sorts top-level branches by the last average task time recorded per branch.
Definition TTree.cxx:5837
void Delete(Option_t *option="") override
Delete this tree from memory or/and disk.
Definition TTree.cxx:3750
virtual TBranchRef * GetBranchRef() const
Definition TTree.h:451
virtual Long64_t Process(const char *filename, Option_t *option="", Long64_t nentries=kMaxEntries, Long64_t firstentry=0)
Process this tree executing the TSelector code in the specified filename.
Definition TTree.cxx:7530
virtual TBranch * BranchImpRef(const char *branchname, const char *classname, TClass *ptrClass, void *addobj, Int_t bufsize, Int_t splitlevel)
Same as TTree::Branch but automatic detection of the class name.
Definition TTree.cxx:1625
virtual void SetEventList(TEventList *list)
This function transfroms the given TEventList into a TEntryList The new TEntryList is owned by the TT...
Definition TTree.cxx:9163
void MoveReadCache(TFile *src, TDirectory *dir)
Move a cache from a file to the current file in dir.
Definition TTree.cxx:7062
Long64_t fAutoFlush
Auto-flush tree when fAutoFlush entries written or -fAutoFlush (compressed) bytes produced.
Definition TTree.h:101
Int_t fUpdate
Update frequency for EntryLoop.
Definition TTree.h:93
virtual void ResetAfterMerge(TFileMergeInfo *)
Resets the state of this TTree after a merge (keep the customization but forget the data).
Definition TTree.cxx:8114
virtual Long64_t GetEntries() const
Definition TTree.h:464
virtual void SetEstimate(Long64_t nentries=1000000)
Set number of entries to estimate variable limits.
Definition TTree.cxx:9204
Int_t fTimerInterval
Timer interval in milliseconds.
Definition TTree.h:91
Int_t fDebug
! Debug level
Definition TTree.h:111
Int_t SetCacheSizeAux(bool autocache=true, Long64_t cacheSize=0)
Set the size of the file cache and create it if possible.
Definition TTree.cxx:8805
virtual Long64_t AutoSave(Option_t *option="")
AutoSave tree header every fAutoSave bytes.
Definition TTree.cxx:1490
virtual Long64_t GetEntryNumber(Long64_t entry) const
Return entry number corresponding to entry.
Definition TTree.cxx:5868
virtual TTree * CloneTree(Long64_t nentries=-1, Option_t *option="")
Create a clone of this tree and copy nentries.
Definition TTree.cxx:3136
Int_t fFileNumber
! current file number (if file extensions)
Definition TTree.h:116
virtual TLeaf * GetLeaf(const char *branchname, const char *leafname)
Return pointer to the 1st Leaf named name in any Branch of this Tree or any branch in the list of fri...
Definition TTree.cxx:6198
virtual Long64_t GetZipBytes() const
Definition TTree.h:586
TObjArray fLeaves
Direct pointers to individual branch leaves.
Definition TTree.h:123
virtual void Reset(Option_t *option="")
Reset baskets, buffers and entries count in all branches and leaves.
Definition TTree.cxx:8083
virtual void KeepCircular()
Keep a maximum of fMaxEntries in memory.
Definition TTree.cxx:6418
virtual void SetDefaultEntryOffsetLen(Int_t newdefault, bool updateExisting=false)
Update the default value for the branch's fEntryOffsetLen.
Definition TTree.cxx:9034
virtual void DirectoryAutoAdd(TDirectory *)
Called by TKey and TObject::Clone to automatically add us to a directory when we are read from a file...
Definition TTree.cxx:3822
Long64_t fMaxVirtualSize
Maximum total size of buffers kept in memory.
Definition TTree.h:99
virtual Long64_t GetTotBytes() const
Definition TTree.h:557
virtual Int_t MakeSelector(const char *selector=nullptr, Option_t *option="")
Generate skeleton selector class for this tree.
Definition TTree.cxx:6825
virtual void SetObject(const char *name, const char *title)
Change the name and title of this tree.
Definition TTree.cxx:9365
TVirtualPerfStats * fPerfStats
! pointer to the current perf stats object
Definition TTree.h:132
Double_t fWeight
Tree weight (see TTree::SetWeight)
Definition TTree.h:90
std::vector< TBranch * > fSeqBranches
! Branches to be processed sequentially when IMT is on
Definition TTree.h:145
Long64_t fDebugMax
! Last entry number to debug
Definition TTree.h:113
Int_t fDefaultEntryOffsetLen
Initial Length of fEntryOffset table in the basket buffers.
Definition TTree.h:94
TTree()
Default constructor and I/O constructor.
Definition TTree.cxx:727
Long64_t fAutoSave
Autosave tree when fAutoSave entries written or -fAutoSave (compressed) bytes produced.
Definition TTree.h:100
TBranch * Branch(const char *name, T *obj, Int_t bufsize=32000, Int_t splitlevel=99)
Add a new branch, and infer the data type from the type of obj being passed.
Definition TTree.h:354
std::atomic< UInt_t > fAllocationCount
indicates basket should be resized to exact memory usage, but causes significant
Definition TTree.h:152
virtual Int_t GetEntryWithIndex(Int_t major, Int_t minor=0)
Read entry corresponding to major and minor number.
Definition TTree.cxx:5930
static TTree * MergeTrees(TList *list, Option_t *option="")
Static function merging the trees in the TList into a new tree.
Definition TTree.cxx:6856
bool MemoryFull(Int_t nbytes)
Check if adding nbytes to memory we are still below MaxVirtualsize.
Definition TTree.cxx:6840
virtual Long64_t GetReadEntry() const
Definition TTree.h:550
virtual TObjArray * GetListOfBranches()
Definition TTree.h:529
Long64_t fZipBytes
Total number of bytes in all branches after compression.
Definition TTree.h:87
virtual TTree * GetTree() const
Definition TTree.h:558
TBuffer * fTransientBuffer
! Pointer to the current transient buffer.
Definition TTree.h:138
virtual void SetEntryList(TEntryList *list, Option_t *opt="")
Set an EntryList.
Definition TTree.cxx:9140
bool Notify() override
Function called when loading a new class library.
Definition TTree.cxx:7112
virtual void AddZipBytes(Int_t zip)
Definition TTree.h:333
virtual Long64_t LoadTree(Long64_t entry)
Set current entry.
Definition TTree.cxx:6476
virtual Long64_t ReadFile(const char *filename, const char *branchDescriptor="", char delimiter=' ')
Create or simply read branches from filename.
Definition TTree.cxx:7644
virtual const char * GetAlias(const char *aliasName) const
Returns the expanded value of the alias. Search in the friends if any.
Definition TTree.cxx:5227
ROOT::TIOFeatures SetIOFeatures(const ROOT::TIOFeatures &)
Provide the end-user with the ability to enable/disable various experimental IO features for this TTr...
Definition TTree.cxx:9224
virtual TBasket * CreateBasket(TBranch *)
Create a basket for this tree and given branch.
Definition TTree.cxx:3734
TList * fUserInfo
pointer to a list of user objects associated to this Tree
Definition TTree.h:133
virtual Double_t GetMinimum(const char *columname)
Return minimum of column with name columname.
Definition TTree.cxx:6278
virtual void RemoveFriend(TTree *)
Remove a friend from the list of friends.
Definition TTree.cxx:8057
virtual Long64_t GetEntriesFast() const
Return a number greater or equal to the total number of entries in the dataset.
Definition TTree.h:506
void Browse(TBrowser *) override
Browse content of the TTree.
Definition TTree.cxx:2602
virtual TList * GetUserInfo()
Return a pointer to the list containing user objects associated to this tree.
Definition TTree.cxx:6359
Long64_t fChainOffset
! Offset of 1st entry of this Tree in a TChain
Definition TTree.h:106
@ kOnlyFlushAtCluster
If set, the branch's buffers will grow until an event cluster boundary is hit, guaranteeing a basket ...
Definition TTree.h:257
@ kEntriesReshuffled
If set, signals that this TTree is the output of the processing of another TTree, and the entries are...
Definition TTree.h:262
@ kCircular
Definition TTree.h:253
virtual Long64_t GetEntriesFriend() const
Return pointer to the 1st Leaf named name in any Branch of this Tree or any branch in the list of fri...
Definition TTree.cxx:5513
virtual TSQLResult * Query(const char *varexp="", const char *selection="", Option_t *option="", Long64_t nentries=kMaxEntries, Long64_t firstentry=0)
Loop over entries and return a TSQLResult object containing entries following selection.
Definition TTree.cxx:7593
virtual TBranch * Bronch(const char *name, const char *classname, void *addobj, Int_t bufsize=32000, Int_t splitlevel=99)
Create a new TTree BranchElement.
Definition TTree.cxx:2397
virtual void SetBasketSize(const char *bname, Int_t buffsize=16000)
Set a branch's basket size.
Definition TTree.cxx:8452
static void SetBranchStyle(Int_t style=1)
Set the current branch style.
Definition TTree.cxx:8759
~TTree() override
Destructor.
Definition TTree.cxx:910
void ImportClusterRanges(TTree *fromtree)
Appends the cluster range information stored in 'fromtree' to this tree, including the value of fAuto...
Definition TTree.cxx:6375
TClass * IsA() const override
Definition TTree.h:706
Long64_t fEstimate
Number of entries to estimate histogram limits.
Definition TTree.h:102
Int_t FlushBasketsImpl() const
Internal implementation of the FlushBaskets algorithm.
Definition TTree.cxx:5147
virtual Long64_t LoadTreeFriend(Long64_t entry, TTree *T)
Load entry on behalf of our master tree, we may use an index.
Definition TTree.cxx:6560
Int_t Write(const char *name=nullptr, Int_t option=0, Int_t bufsize=0) override
Write this object to the current directory.
Definition TTree.cxx:9858
TVirtualIndex * fTreeIndex
Pointer to the tree Index (if any)
Definition TTree.h:129
void UseCurrentStyle() override
Replace current attributes by current style.
Definition TTree.cxx:9819
TObject * fNotify
Object to be notified when loading a Tree.
Definition TTree.h:120
virtual TBranch * BranchImp(const char *branchname, const char *classname, TClass *ptrClass, void *addobj, Int_t bufsize, Int_t splitlevel)
Same as TTree::Branch() with added check that addobj matches className.
Definition TTree.cxx:1544
Long64_t fCacheSize
! Maximum size of file buffers
Definition TTree.h:105
TList * fClones
! List of cloned trees which share our addresses
Definition TTree.h:135
std::atomic< Long64_t > fTotalBuffers
! Total number of bytes in branch buffers
Definition TTree.h:108
static TClass * Class()
@ kFindBranch
Definition TTree.h:212
@ kResetBranchAddresses
Definition TTree.h:225
@ kFindLeaf
Definition TTree.h:213
@ kGetEntryWithIndex
Definition TTree.h:217
@ kPrint
Definition TTree.h:222
@ kGetFriend
Definition TTree.h:218
@ kGetBranch
Definition TTree.h:215
@ kSetBranchStatus
Definition TTree.h:224
@ kLoadTree
Definition TTree.h:221
@ kGetEntry
Definition TTree.h:216
@ kGetLeaf
Definition TTree.h:220
@ kRemoveFriend
Definition TTree.h:223
@ kGetFriendAlias
Definition TTree.h:219
@ kGetAlias
Definition TTree.h:214
virtual void SetTreeIndex(TVirtualIndex *index)
The current TreeIndex is replaced by the new index.
Definition TTree.cxx:9451
virtual void OptimizeBaskets(ULong64_t maxMemory=10000000, Float_t minComp=1.1, Option_t *option="")
This function may be called after having filled some entries in a Tree.
Definition TTree.cxx:7136
virtual Long64_t Project(const char *hname, const char *varexp, const char *selection="", Option_t *option="", Long64_t nentries=kMaxEntries, Long64_t firstentry=0)
Make a projection of a tree using selections.
Definition TTree.cxx:7578
virtual Int_t SetCacheEntryRange(Long64_t first, Long64_t last)
interface to TTreeCache to set the cache entry range
Definition TTree.cxx:8925
static Long64_t GetMaxTreeSize()
Static function which returns the tree file size limit in bytes.
Definition TTree.cxx:6268
bool fCacheDoClusterPrefetch
! true if cache is prefetching whole clusters
Definition TTree.h:140
Int_t SetBranchAddressImp(TBranch *branch, void *addr, TBranch **ptr)
Change branch address, dealing with clone trees properly.
Definition TTree.cxx:8539
virtual bool SetAlias(const char *aliasName, const char *aliasFormula)
Set a tree variable alias.
Definition TTree.cxx:8235
virtual void CopyAddresses(TTree *, bool undo=false)
Set branch addresses of passed tree equal to ours.
Definition TTree.cxx:3302
Long64_t fMaxEntries
Maximum number of entries in case of circular buffers.
Definition TTree.h:97
virtual void DropBuffers(Int_t nbytes)
Drop branch buffers to accommodate nbytes below MaxVirtualsize.
Definition TTree.cxx:4534
virtual TList * GetListOfFriends() const
Definition TTree.h:531
virtual void Refresh()
Refresh contents of this tree and its branches from the current status on disk.
Definition TTree.cxx:7996
virtual void SetAutoFlush(Long64_t autof=-30000000)
This function may be called at the start of a program to change the default value for fAutoFlush.
Definition TTree.cxx:8290
static Long64_t fgMaxTreeSize
Maximum size of a file containing a Tree.
Definition TTree.h:155
Long64_t fReadEntry
! Number of the entry being processed
Definition TTree.h:107
TArrayD fIndexValues
Sorted index values.
Definition TTree.h:127
void MarkEventCluster()
Mark the previous event as being at the end of the event cluster.
Definition TTree.cxx:8352
UInt_t fNEntriesSinceSorting
! Number of entries processed since the last re-sorting of branches
Definition TTree.h:143
virtual void SetFileNumber(Int_t number=0)
Set fFileNumber to number.
Definition TTree.cxx:9247
virtual TLeaf * FindLeaf(const char *name)
Find leaf..
Definition TTree.cxx:4917
virtual void StartViewer()
Start the TTreeViewer on this tree.
Definition TTree.cxx:9564
Int_t GetMakeClass() const
Definition TTree.h:536
virtual Int_t MakeCode(const char *filename=nullptr)
Generate a skeleton function for this tree.
Definition TTree.cxx:6643
bool fIMTFlush
! True if we are doing a multithreaded flush.
Definition TTree.h:159
TDirectory * fDirectory
! Pointer to directory holding this tree
Definition TTree.h:121
@ kNeedEnableDecomposedObj
Definition TTree.h:245
@ kClassMismatch
Definition TTree.h:238
@ kVoidPtr
Definition TTree.h:243
@ kMatchConversionCollection
Definition TTree.h:241
@ kMissingCompiledCollectionProxy
Definition TTree.h:236
@ kMismatch
Definition TTree.h:237
@ kMatchConversion
Definition TTree.h:240
@ kInternalError
Definition TTree.h:235
@ kMatch
Definition TTree.h:239
@ kMissingBranch
Definition TTree.h:234
@ kMakeClass
Definition TTree.h:242
static Int_t fgBranchStyle
Old/New branch style.
Definition TTree.h:154
virtual void ResetBranchAddresses()
Tell all of our branches to drop their current objects and allocate new ones.
Definition TTree.cxx:8155
Int_t fNfill
! Local for EntryLoop
Definition TTree.h:110
void SetName(const char *name) override
Change the name of this tree.
Definition TTree.cxx:9310
virtual void RegisterExternalFriend(TFriendElement *)
Record a TFriendElement that we need to warn when the chain switches to a new file (typically this is...
Definition TTree.cxx:8037
TArrayI fIndex
Index of sorted values.
Definition TTree.h:128
virtual Int_t SetCacheSize(Long64_t cachesize=-1)
Set maximum size of the file cache .
Definition TTree.cxx:8777
void AddClone(TTree *)
Add a cloned tree to our list of trees to be notified whenever we change our branch addresses or when...
Definition TTree.cxx:1209
virtual Int_t CheckBranchAddressType(TBranch *branch, TClass *ptrClass, EDataType datatype, bool ptr)
Check whether or not the address described by the last 3 parameters matches the content of the branch...
Definition TTree.cxx:2864
TBuffer * GetTransientBuffer(Int_t size)
Returns the transient buffer currently used by this TTree for reading/writing baskets.
Definition TTree.cxx:1027
ROOT::TIOFeatures GetIOFeatures() const
Returns the current set of IO settings.
Definition TTree.cxx:6077
virtual Int_t MakeClass(const char *classname=nullptr, Option_t *option="")
Generate a skeleton analysis class for this tree.
Definition TTree.cxx:6610
virtual const char * GetFriendAlias(TTree *) const
If the 'tree' is a friend, this method returns its alias name.
Definition TTree.cxx:6035
virtual void RemoveExternalFriend(TFriendElement *)
Removes external friend.
Definition TTree.cxx:8048
Int_t fPacketSize
! Number of entries in one packet for parallel root
Definition TTree.h:109
virtual TBranch * BranchImpArr(const char *branchname, EDataType datatype, std::size_t N, void *addobj, Int_t bufsize, Int_t splitlevel)
Definition TTree.cxx:1721
virtual Long64_t Scan(const char *varexp="", const char *selection="", Option_t *option="", Long64_t nentries=kMaxEntries, Long64_t firstentry=0)
Loop over tree entries and print entries passing selection.
Definition TTree.cxx:8193
virtual TBranch * BronchExec(const char *name, const char *classname, void *addobj, bool isptrptr, Int_t bufsize, Int_t splitlevel)
Helper function implementing TTree::Bronch and TTree::Branch(const char *name, T &obj);.
Definition TTree.cxx:2405
virtual void AddTotBytes(Int_t tot)
Definition TTree.h:332
virtual Long64_t CopyEntries(TTree *tree, Long64_t nentries=-1, Option_t *option="", bool needCopyAddresses=false)
Copy nentries from given tree to this tree.
Definition TTree.cxx:3537
Int_t fMakeClass
! not zero when processing code generated by MakeClass
Definition TTree.h:115
virtual Int_t LoadBaskets(Long64_t maxmemory=2000000000)
Read in memory all baskets from all branches up to the limit of maxmemory bytes.
Definition TTree.cxx:6454
static constexpr Long64_t kMaxEntries
Definition TTree.h:230
TPrincipal * Principal(const char *varexp="", const char *selection="", Option_t *option="np", Long64_t nentries=kMaxEntries, Long64_t firstentry=0)
Interface to the Principal Components Analysis class.
Definition TTree.cxx:7279
virtual Long64_t GetAutoFlush() const
Definition TTree.h:448
Defines a common interface to inspect/change the contents of an object that represents a collection.
Abstract interface for Tree Index.
virtual Long64_t GetEntryNumberWithIndex(Long64_t major, Long64_t minor) const =0
virtual Long64_t GetEntryNumberFriend(const TTree *)=0
virtual void SetTree(TTree *T)=0
virtual Long64_t GetN() const =0
virtual Long64_t GetEntryNumberWithBestIndex(Long64_t major, Long64_t minor) const =0
Provides the interface for the PROOF internal performance measurement and event tracing.
Abstract base class defining the interface for the plugins that implement Draw, Scan,...
virtual Long64_t Scan(const char *varexp, const char *selection, Option_t *option, Long64_t nentries, Long64_t firstentry)=0
virtual void UpdateFormulaLeaves()=0
virtual Long64_t DrawSelect(const char *varexp, const char *selection, Option_t *option, Long64_t nentries, Long64_t firstentry)=0
virtual Int_t MakeCode(const char *filename)=0
virtual Int_t UnbinnedFit(const char *formula, const char *varexp, const char *selection, Option_t *option, Long64_t nentries, Long64_t firstentry)=0
virtual Long64_t GetEntries(const char *)=0
virtual Int_t MakeProxy(const char *classname, const char *macrofilename=nullptr, const char *cutfilename=nullptr, const char *option=nullptr, Int_t maxUnrolling=3)=0
virtual TSQLResult * Query(const char *varexp, const char *selection, Option_t *option, Long64_t nentries, Long64_t firstentry)=0
virtual TPrincipal * Principal(const char *varexp="", const char *selection="", Option_t *option="np", Long64_t nentries=kMaxEntries, Long64_t firstentry=0)=0
virtual void StartViewer(Int_t ww, Int_t wh)=0
virtual Int_t MakeReader(const char *classname, Option_t *option)=0
virtual TVirtualIndex * BuildIndex(const TTree *T, const char *majorname, const char *minorname)=0
virtual TTree * CopyTree(const char *selection, Option_t *option="", Long64_t nentries=kMaxEntries, Long64_t firstentry=0)=0
virtual Long64_t Process(const char *filename, Option_t *option="", Long64_t nentries=kMaxEntries, Long64_t firstentry=0)=0
virtual void SetEstimate(Long64_t n)=0
static TVirtualTreePlayer * TreePlayer(TTree *obj)
Static function returning a pointer to a Tree player.
virtual Int_t MakeClass(const char *classname, const char *option)=0
virtual Int_t Fit(const char *formula, const char *varexp, const char *selection, Option_t *option, Option_t *goption, Long64_t nentries, Long64_t firstentry)=0
TLine * line
std::ostream & Info()
Definition hadd.cxx:171
const Int_t n
Definition legend1.C:16
Special implementation of ROOT::RRangeCast for TCollection, including a check that the cast target ty...
Definition TObject.h:393
tbb::task_arena is an alias of tbb::interface7::task_arena, which doesn't allow to forward declare tb...
Bool_t IsImplicitMTEnabled()
Returns true if the implicit multi-threading in ROOT is enabled.
Definition TROOT.cxx:570
ESTLType
Definition ESTLType.h:28
@ kSTLmap
Definition ESTLType.h:33
@ kSTLmultimap
Definition ESTLType.h:34
void CallRecursiveRemoveIfNeeded(TObject &obj)
call RecursiveRemove for obj if gROOT is valid and obj.TestBit(kMustCleanup) is true.
Definition TROOT.h:395
void ToHumanReadableSize(value_type bytes, Bool_t si, Double_t *coeff, const char **units)
Return the size expressed in 'human readable' format.
EFromHumanReadableSize FromHumanReadableSize(std::string_view str, T &value)
Convert strings like the following into byte counts 5MB, 5 MB, 5M, 3.7GB, 123b, 456kB,...
Short_t Max(Short_t a, Short_t b)
Returns the largest of a and b.
Definition TMathBase.h:250
Double_t Median(Long64_t n, const T *a, const Double_t *w=nullptr, Long64_t *work=nullptr)
Same as RMS.
Definition TMath.h:1352
Double_t Ceil(Double_t x)
Rounds x upward, returning the smallest integral value that is not less than x.
Definition TMath.h:672
Short_t Min(Short_t a, Short_t b)
Returns the smallest of a and b.
Definition TMathBase.h:198
Long64_t BinarySearch(Long64_t n, const T *array, T value)
Binary search in an array of n values to locate value.
Definition TMathBase.h:347
TCanvas * slash()
Definition slash.C:1
@ kUseGlobal
Use the global compression algorithm.
Definition Compression.h:93
@ kInherit
Some objects use this value to denote that the compression algorithm should be inherited from the par...
Definition Compression.h:91
@ kUseCompiledDefault
Use the compile-time default setting.
Definition Compression.h:53
th1 Draw()
TMarker m
Definition textangle.C:8
TLine l
Definition textangle.C:4