Logo ROOT  
Reference Guide
 
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/// \note In contrast to class TListIter, looping here must NOT be done using
547/// `while (iter())` or `while (iter.Next())` that would lead to an infinite loop, but rather using
548/// `while( (auto clusterStart = iter()) < tree->GetEntries() )`.
549/// \see TTree::GetClusterIterator
550
551////////////////////////////////////////////////////////////////////////////////
552/// Regular constructor.
553/// TTree is not set as const, since we might modify if it is a TChain.
555TTree::TClusterIterator::TClusterIterator(TTree *tree, Long64_t firstEntry) : fTree(tree), fClusterRange(0), fStartEntry(0), fNextEntry(0), fEstimatedSize(-1)
556{
557 if (fTree->fNClusterRange) {
558 // Find the correct cluster range.
559 //
560 // Since fClusterRangeEnd contains the inclusive upper end of the range, we need to search for the
561 // range that was containing the previous entry and add 1 (because BinarySearch consider the values
562 // to be the inclusive start of the bucket).
564
567 if (fClusterRange == 0) {
568 pedestal = 0;
570 } else {
573 }
577 } else {
579 }
580 if (autoflush <= 0) {
582 }
584 } else if ( fTree->GetAutoFlush() <= 0 ) {
585 // Case of old files before November 9 2009 *or* small tree where AutoFlush was never set.
587 } else {
589 }
590 fNextEntry = fStartEntry; // Position correctly for the first call to Next()
591}
592
593////////////////////////////////////////////////////////////////////////////////
594/// Estimate the cluster size.
595///
596/// In almost all cases, this quickly returns the size of the auto-flush
597/// in the TTree.
598///
599/// However, in the case where the cluster size was not fixed (old files and
600/// case where autoflush was explicitly set to zero), we need estimate
601/// a cluster size in relation to the size of the cache.
602///
603/// After this value is calculated once for the TClusterIterator, it is
604/// cached and reused in future calls.
607{
608 auto autoFlush = fTree->GetAutoFlush();
609 if (autoFlush > 0) return autoFlush;
610 if (fEstimatedSize > 0) return fEstimatedSize;
611
612 Long64_t zipBytes = fTree->GetZipBytes();
613 if (zipBytes == 0) {
614 fEstimatedSize = fTree->GetEntries() - 1;
615 if (fEstimatedSize <= 0)
616 fEstimatedSize = 1;
617 } else {
619 Long64_t cacheSize = fTree->GetCacheSize();
620 if (cacheSize == 0) {
621 // Humm ... let's double check on the file.
622 TFile *file = fTree->GetCurrentFile();
623 if (file) {
624 TFileCacheRead *cache = fTree->GetReadCache(file);
625 if (cache) {
626 cacheSize = cache->GetBufferSize();
627 }
628 }
629 }
630 // If neither file nor tree has a cache, use the current default.
631 if (cacheSize <= 0) {
632 cacheSize = 30000000;
633 }
634 clusterEstimate = fTree->GetEntries() * cacheSize / zipBytes;
635 // If there are no entries, then just default to 1.
636 fEstimatedSize = clusterEstimate ? clusterEstimate : 1;
637 }
638 return fEstimatedSize;
639}
640
641////////////////////////////////////////////////////////////////////////////////
642/// Move on to the next cluster and return the starting entry
643/// of this next cluster
646{
647 fStartEntry = fNextEntry;
648 if (fTree->fNClusterRange || fTree->GetAutoFlush() > 0) {
649 if (fClusterRange == fTree->fNClusterRange) {
650 // We are looking at a range which size
651 // is defined by AutoFlush itself and goes to the GetEntries.
652 fNextEntry += GetEstimatedClusterSize();
653 } else {
654 if (fStartEntry > fTree->fClusterRangeEnd[fClusterRange]) {
655 ++fClusterRange;
656 }
657 if (fClusterRange == fTree->fNClusterRange) {
658 // We are looking at the last range which size
659 // is defined by AutoFlush itself and goes to the GetEntries.
660 fNextEntry += GetEstimatedClusterSize();
661 } else {
662 Long64_t clusterSize = fTree->fClusterSize[fClusterRange];
663 if (clusterSize == 0) {
664 clusterSize = GetEstimatedClusterSize();
665 }
666 fNextEntry += clusterSize;
667 if (fNextEntry > fTree->fClusterRangeEnd[fClusterRange]) {
668 // The last cluster of the range was a partial cluster,
669 // so the next cluster starts at the beginning of the
670 // next range.
671 fNextEntry = fTree->fClusterRangeEnd[fClusterRange] + 1;
672 }
673 }
674 }
675 } else {
676 // Case of old files before November 9 2009
677 fNextEntry = fStartEntry + GetEstimatedClusterSize();
678 }
679 if (fNextEntry > fTree->GetEntries()) {
680 fNextEntry = fTree->GetEntries();
681 }
682 return fStartEntry;
683}
684
685////////////////////////////////////////////////////////////////////////////////
686/// Move on to the previous cluster and return the starting entry
687/// of this previous cluster
690{
691 fNextEntry = fStartEntry;
692 if (fTree->fNClusterRange || fTree->GetAutoFlush() > 0) {
693 if (fClusterRange == 0 || fTree->fNClusterRange == 0) {
694 // We are looking at a range which size
695 // is defined by AutoFlush itself.
696 fStartEntry -= GetEstimatedClusterSize();
697 } else {
698 if (fNextEntry <= fTree->fClusterRangeEnd[fClusterRange]) {
699 --fClusterRange;
700 }
701 if (fClusterRange == 0) {
702 // We are looking at the first range.
703 fStartEntry = 0;
704 } else {
705 Long64_t clusterSize = fTree->fClusterSize[fClusterRange];
706 if (clusterSize == 0) {
707 clusterSize = GetEstimatedClusterSize();
708 }
709 fStartEntry -= clusterSize;
710 }
711 }
712 } else {
713 // Case of old files before November 9 2009 or trees that never auto-flushed.
714 fStartEntry = fNextEntry - GetEstimatedClusterSize();
715 }
716 if (fStartEntry < 0) {
717 fStartEntry = 0;
718 }
719 return fStartEntry;
720}
721
722////////////////////////////////////////////////////////////////////////////////
723////////////////////////////////////////////////////////////////////////////////
724////////////////////////////////////////////////////////////////////////////////
725
726////////////////////////////////////////////////////////////////////////////////
727/// Default constructor and I/O constructor.
728///
729/// Note: We do *not* insert ourself into the current directory.
730///
733: TNamed()
734, TAttLine()
735, TAttFill()
736, TAttMarker()
737, fEntries(0)
738, fTotBytes(0)
739, fZipBytes(0)
740, fSavedBytes(0)
741, fFlushedBytes(0)
742, fWeight(1)
744, fScanField(25)
745, fUpdate(0)
749, fMaxEntries(0)
750, fMaxEntryLoop(0)
752, fAutoSave( -300000000)
753, fAutoFlush(-30000000)
754, fEstimate(1000000)
755, fClusterRangeEnd(nullptr)
756, fClusterSize(nullptr)
757, fCacheSize(0)
758, fChainOffset(0)
759, fReadEntry(-1)
760, fTotalBuffers(0)
761, fPacketSize(100)
762, fNfill(0)
763, fDebug(0)
764, fDebugMin(0)
765, fDebugMax(9999999)
766, fMakeClass(0)
767, fFileNumber(0)
768, fNotify(nullptr)
769, fDirectory(nullptr)
770, fBranches()
771, fLeaves()
772, fAliases(nullptr)
773, fEventList(nullptr)
774, fEntryList(nullptr)
775, fIndexValues()
776, fIndex()
777, fTreeIndex(nullptr)
778, fFriends(nullptr)
779, fExternalFriends(nullptr)
780, fPerfStats(nullptr)
781, fUserInfo(nullptr)
782, fPlayer(nullptr)
783, fClones(nullptr)
784, fBranchRef(nullptr)
786, fTransientBuffer(nullptr)
790, fIMTEnabled(ROOT::IsImplicitMTEnabled())
792{
793 fMaxEntries = 1000000000;
794 fMaxEntries *= 1000;
795
796 fMaxEntryLoop = 1000000000;
797 fMaxEntryLoop *= 1000;
798
799 fBranches.SetOwner(true);
800}
801
802////////////////////////////////////////////////////////////////////////////////
803/// Normal tree constructor.
804///
805/// The tree is created in the current directory.
806/// Use the various functions Branch below to add branches to this tree.
807///
808/// If the first character of title is a "/", the function assumes a folder name.
809/// In this case, it creates automatically branches following the folder hierarchy.
810/// splitlevel may be used in this case to control the split level.
812TTree::TTree(const char* name, const char* title, Int_t splitlevel /* = 99 */,
813 TDirectory* dir /* = gDirectory*/)
814: TNamed(name, title)
815, TAttLine()
816, TAttFill()
817, TAttMarker()
818, fEntries(0)
819, fTotBytes(0)
820, fZipBytes(0)
821, fSavedBytes(0)
822, fFlushedBytes(0)
823, fWeight(1)
824, fTimerInterval(0)
825, fScanField(25)
826, fUpdate(0)
827, fDefaultEntryOffsetLen(1000)
828, fNClusterRange(0)
829, fMaxClusterRange(0)
830, fMaxEntries(0)
831, fMaxEntryLoop(0)
832, fMaxVirtualSize(0)
833, fAutoSave( -300000000)
834, fAutoFlush(-30000000)
835, fEstimate(1000000)
836, fClusterRangeEnd(nullptr)
837, fClusterSize(nullptr)
838, fCacheSize(0)
839, fChainOffset(0)
840, fReadEntry(-1)
841, fTotalBuffers(0)
842, fPacketSize(100)
843, fNfill(0)
844, fDebug(0)
845, fDebugMin(0)
846, fDebugMax(9999999)
847, fMakeClass(0)
848, fFileNumber(0)
849, fNotify(nullptr)
850, fDirectory(dir)
851, fBranches()
852, fLeaves()
853, fAliases(nullptr)
854, fEventList(nullptr)
855, fEntryList(nullptr)
856, fIndexValues()
857, fIndex()
858, fTreeIndex(nullptr)
859, fFriends(nullptr)
860, fExternalFriends(nullptr)
861, fPerfStats(nullptr)
862, fUserInfo(nullptr)
863, fPlayer(nullptr)
864, fClones(nullptr)
865, fBranchRef(nullptr)
866, fFriendLockStatus(0)
867, fTransientBuffer(nullptr)
868, fCacheDoAutoInit(true)
869, fCacheDoClusterPrefetch(false)
870, fCacheUserSet(false)
871, fIMTEnabled(ROOT::IsImplicitMTEnabled())
872, fNEntriesSinceSorting(0)
873{
874 // TAttLine state.
878
879 // TAttFill state.
882
883 // TAttMarkerState.
887
888 fMaxEntries = 1000000000;
889 fMaxEntries *= 1000;
890
891 fMaxEntryLoop = 1000000000;
892 fMaxEntryLoop *= 1000;
893
894 // Insert ourself into the current directory.
895 // FIXME: This is very annoying behaviour, we should
896 // be able to choose to not do this like we
897 // can with a histogram.
898 if (fDirectory) fDirectory->Append(this);
899
900 fBranches.SetOwner(true);
901
902 // If title starts with "/" and is a valid folder name, a superbranch
903 // is created.
904 // FIXME: Why?
905 if (strlen(title) > 2) {
906 if (title[0] == '/') {
907 Branch(title+1,32000,splitlevel);
908 }
909 }
910}
911
912////////////////////////////////////////////////////////////////////////////////
913/// Destructor.
916{
917 if (auto link = dynamic_cast<TNotifyLinkBase*>(fNotify)) {
918 link->Clear();
919 }
920 if (fAllocationCount && (gDebug > 0)) {
921 Info("TTree::~TTree", "For tree %s, allocation count is %u.", GetName(), fAllocationCount.load());
922#ifdef R__TRACK_BASKET_ALLOC_TIME
923 Info("TTree::~TTree", "For tree %s, allocation time is %lluus.", GetName(), fAllocationTime.load());
924#endif
925 }
926
927 if (fDirectory) {
928 // We are in a directory, which may possibly be a file.
929 if (fDirectory->GetList()) {
930 // Remove us from the directory listing.
931 fDirectory->Remove(this);
932 }
933 //delete the file cache if it points to this Tree
934 TFile *file = fDirectory->GetFile();
935 MoveReadCache(file,nullptr);
936 }
937
938 // Remove the TTree from any list (linked to to the list of Cleanups) to avoid the unnecessary call to
939 // this RecursiveRemove while we delete our content.
941 ResetBit(kMustCleanup); // Don't redo it.
942
943 // We don't own the leaves in fLeaves, the branches do.
944 fLeaves.Clear();
945 // I'm ready to destroy any objects allocated by
946 // SetAddress() by my branches. If I have clones,
947 // tell them to zero their pointers to this shared
948 // memory.
949 if (fClones && fClones->GetEntries()) {
950 // I have clones.
951 // I am about to delete the objects created by
952 // SetAddress() which we are sharing, so tell
953 // the clones to release their pointers to them.
954 for (TObjLink* lnk = fClones->FirstLink(); lnk; lnk = lnk->Next()) {
955 TTree* clone = (TTree*) lnk->GetObject();
956 // clone->ResetBranchAddresses();
957
958 // Reset only the branch we have set the address of.
959 CopyAddresses(clone,true);
960 }
961 }
962 // Get rid of our branches, note that this will also release
963 // any memory allocated by TBranchElement::SetAddress().
965
966 // The TBranch destructor is using fDirectory to detect whether it
967 // owns the TFile that contains its data (See TBranch::~TBranch)
968 fDirectory = nullptr;
969
970 // FIXME: We must consider what to do with the reset of these if we are a clone.
971 delete fPlayer;
972 fPlayer = nullptr;
973 if (fExternalFriends) {
974 using namespace ROOT::Detail;
976 fetree->Reset();
977 fExternalFriends->Clear("nodelete");
979 }
980 if (fFriends) {
981 fFriends->Delete();
982 delete fFriends;
983 fFriends = nullptr;
984 }
985 if (fAliases) {
986 fAliases->Delete();
987 delete fAliases;
988 fAliases = nullptr;
989 }
990 if (fUserInfo) {
991 fUserInfo->Delete();
992 delete fUserInfo;
993 fUserInfo = nullptr;
994 }
995 if (fClones) {
996 // Clone trees should no longer be removed from fClones when they are deleted.
997 {
999 gROOT->GetListOfCleanups()->Remove(fClones);
1000 }
1001 // Note: fClones does not own its content.
1002 delete fClones;
1003 fClones = nullptr;
1004 }
1005 if (fEntryList) {
1006 if (fEntryList->TestBit(kCanDelete) && fEntryList->GetDirectory()==nullptr) {
1007 // Delete the entry list if it is marked to be deleted and it is not also
1008 // owned by a directory. (Otherwise we would need to make sure that a
1009 // TDirectoryFile that has a TTree in it does a 'slow' TList::Delete.
1010 delete fEntryList;
1011 fEntryList=nullptr;
1012 }
1013 }
1014 delete fTreeIndex;
1015 fTreeIndex = nullptr;
1016 delete fBranchRef;
1017 fBranchRef = nullptr;
1018 delete [] fClusterRangeEnd;
1019 fClusterRangeEnd = nullptr;
1020 delete [] fClusterSize;
1021 fClusterSize = nullptr;
1022
1023 if (fTransientBuffer) {
1024 delete fTransientBuffer;
1025 fTransientBuffer = nullptr;
1026 }
1027}
1028
1029////////////////////////////////////////////////////////////////////////////////
1030/// Returns the transient buffer currently used by this TTree for reading/writing baskets.
1042}
1043
1044////////////////////////////////////////////////////////////////////////////////
1045/// Add branch with name bname to the Tree cache.
1046/// If bname="*" all branches are added to the cache.
1047/// if subbranches is true all the branches of the subbranches are
1048/// also put to the cache.
1049///
1050/// Returns:
1051/// - 0 branch added or already included
1052/// - -1 on error
1054Int_t TTree::AddBranchToCache(const char*bname, bool subbranches)
1055{
1056 if (!GetTree()) {
1057 if (LoadTree(0)<0) {
1058 Error("AddBranchToCache","Could not load a tree");
1059 return -1;
1060 }
1061 }
1062 if (GetTree()) {
1063 if (GetTree() != this) {
1064 return GetTree()->AddBranchToCache(bname, subbranches);
1065 }
1066 } else {
1067 Error("AddBranchToCache", "No tree is available. Branch was not added to the cache");
1068 return -1;
1069 }
1070
1071 TFile *f = GetCurrentFile();
1072 if (!f) {
1073 Error("AddBranchToCache", "No file is available. Branch was not added to the cache");
1074 return -1;
1075 }
1076 TTreeCache *tc = GetReadCache(f,true);
1077 if (!tc) {
1078 Error("AddBranchToCache", "No cache is available, branch not added");
1079 return -1;
1080 }
1081 return tc->AddBranch(bname,subbranches);
1082}
1083
1084////////////////////////////////////////////////////////////////////////////////
1085/// Add branch b to the Tree cache.
1086/// if subbranches is true all the branches of the subbranches are
1087/// also put to the cache.
1088///
1089/// Returns:
1090/// - 0 branch added or already included
1091/// - -1 on error
1094{
1095 if (!GetTree()) {
1096 if (LoadTree(0)<0) {
1097 Error("AddBranchToCache","Could not load a tree");
1098 return -1;
1099 }
1100 }
1101 if (GetTree()) {
1102 if (GetTree() != this) {
1103 Int_t res = GetTree()->AddBranchToCache(b, subbranches);
1104 if (res<0) {
1105 Error("AddBranchToCache", "Error adding branch");
1106 }
1107 return res;
1108 }
1109 } else {
1110 Error("AddBranchToCache", "No tree is available. Branch was not added to the cache");
1111 return -1;
1112 }
1113
1114 TFile *f = GetCurrentFile();
1115 if (!f) {
1116 Error("AddBranchToCache", "No file is available. Branch was not added to the cache");
1117 return -1;
1118 }
1119 TTreeCache *tc = GetReadCache(f,true);
1120 if (!tc) {
1121 Error("AddBranchToCache", "No cache is available, branch not added");
1122 return -1;
1123 }
1124 return tc->AddBranch(b,subbranches);
1125}
1126
1127////////////////////////////////////////////////////////////////////////////////
1128/// Remove the branch with name 'bname' from the Tree cache.
1129/// If bname="*" all branches are removed from the cache.
1130/// if subbranches is true all the branches of the subbranches are
1131/// also removed from the cache.
1132///
1133/// Returns:
1134/// - 0 branch dropped or not in cache
1135/// - -1 on error
1137Int_t TTree::DropBranchFromCache(const char*bname, bool subbranches)
1138{
1139 if (!GetTree()) {
1140 if (LoadTree(0)<0) {
1141 Error("DropBranchFromCache","Could not load a tree");
1142 return -1;
1143 }
1144 }
1145 if (GetTree()) {
1146 if (GetTree() != this) {
1147 return GetTree()->DropBranchFromCache(bname, subbranches);
1148 }
1149 } else {
1150 Error("DropBranchFromCache", "No tree is available. Branch was not dropped from the cache");
1151 return -1;
1152 }
1153
1154 TFile *f = GetCurrentFile();
1155 if (!f) {
1156 Error("DropBranchFromCache", "No file is available. Branch was not dropped from the cache");
1157 return -1;
1158 }
1159 TTreeCache *tc = GetReadCache(f,true);
1160 if (!tc) {
1161 Error("DropBranchFromCache", "No cache is available, branch not dropped");
1162 return -1;
1163 }
1164 return tc->DropBranch(bname,subbranches);
1165}
1166
1167////////////////////////////////////////////////////////////////////////////////
1168/// Remove the branch b from the Tree cache.
1169/// if subbranches is true all the branches of the subbranches are
1170/// also removed from the cache.
1171///
1172/// Returns:
1173/// - 0 branch dropped or not in cache
1174/// - -1 on error
1177{
1178 if (!GetTree()) {
1179 if (LoadTree(0)<0) {
1180 Error("DropBranchFromCache","Could not load a tree");
1181 return -1;
1182 }
1183 }
1184 if (GetTree()) {
1185 if (GetTree() != this) {
1186 Int_t res = GetTree()->DropBranchFromCache(b, subbranches);
1187 if (res<0) {
1188 Error("DropBranchFromCache", "Error dropping branch");
1189 }
1190 return res;
1191 }
1192 } else {
1193 Error("DropBranchFromCache", "No tree is available. Branch was not dropped from the cache");
1194 return -1;
1195 }
1196
1197 TFile *f = GetCurrentFile();
1198 if (!f) {
1199 Error("DropBranchFromCache", "No file is available. Branch was not dropped from the cache");
1200 return -1;
1201 }
1202 TTreeCache *tc = GetReadCache(f,true);
1203 if (!tc) {
1204 Error("DropBranchFromCache", "No cache is available, branch not dropped");
1205 return -1;
1206 }
1207 return tc->DropBranch(b,subbranches);
1208}
1209
1210////////////////////////////////////////////////////////////////////////////////
1211/// Add a cloned tree to our list of trees to be notified whenever we change
1212/// our branch addresses or when we are deleted.
1214void TTree::AddClone(TTree* clone)
1215{
1216 if (!fClones) {
1217 fClones = new TList();
1218 fClones->SetOwner(false);
1219 // So that the clones are automatically removed from the list when
1220 // they are deleted.
1221 {
1223 gROOT->GetListOfCleanups()->Add(fClones);
1224 }
1225 }
1226 if (!fClones->FindObject(clone)) {
1227 fClones->Add(clone);
1228 }
1229}
1230
1231// Check whether mainTree and friendTree can be friends w.r.t. the kEntriesReshuffled bit.
1232// In particular, if any has the bit set, then friendTree must have a TTreeIndex and the
1233// branches used for indexing must be present in mainTree.
1234// Return true if the trees can be friends, false otherwise.
1236{
1239 const auto friendHasValidIndex = [&] {
1240 auto idx = friendTree.GetTreeIndex();
1241 return idx ? idx->IsValidFor(&mainTree) : false;
1242 }();
1243
1245 const auto reshuffledTreeName = isMainReshuffled ? mainTree.GetName() : friendTree.GetName();
1246 const auto msg =
1247 "Tree '%s' has the kEntriesReshuffled bit set and cannot have friends nor can be added as a friend unless the "
1248 "main tree has a TTreeIndex on the friend tree '%s'. You can also unset the bit manually if you know what you "
1249 "are doing; note that you risk associating wrong TTree entries of the friend with those of the main TTree!";
1250 Error("AddFriend", msg, reshuffledTreeName, friendTree.GetName());
1251 return false;
1252 }
1253 return true;
1254}
1255
1256////////////////////////////////////////////////////////////////////////////////
1257/// Add a TFriendElement to the list of friends.
1258///
1259/// This function:
1260/// - opens a file if filename is specified
1261/// - reads a Tree with name treename from the file (current directory)
1262/// - adds the Tree to the list of friends
1263/// see other AddFriend functions
1264///
1265/// A TFriendElement TF describes a TTree object TF in a file.
1266/// When a TFriendElement TF is added to the list of friends of an
1267/// existing TTree T, any variable from TF can be referenced in a query
1268/// to T.
1269///
1270/// A tree keeps a list of friends. In the context of a tree (or a chain),
1271/// friendship means unrestricted access to the friends data. In this way
1272/// it is much like adding another branch to the tree without taking the risk
1273/// of damaging it. To add a friend to the list, you can use the TTree::AddFriend
1274/// method. The tree in the diagram below has two friends (friend_tree1 and
1275/// friend_tree2) and now has access to the variables a,b,c,i,j,k,l and m.
1276///
1277/// \image html ttree_friend1.png
1278///
1279/// The AddFriend method has two parameters, the first is the tree name and the
1280/// second is the name of the ROOT file where the friend tree is saved.
1281/// AddFriend automatically opens the friend file. If no file name is given,
1282/// the tree called ft1 is assumed to be in the same file as the original tree.
1283///
1284/// tree.AddFriend("ft1","friendfile1.root");
1285/// If the friend tree has the same name as the original tree, you can give it
1286/// an alias in the context of the friendship:
1287///
1288/// tree.AddFriend("tree1 = tree","friendfile1.root");
1289/// Once the tree has friends, we can use TTree::Draw as if the friend's
1290/// variables were in the original tree. To specify which tree to use in
1291/// the Draw method, use the syntax:
1292/// ~~~ {.cpp}
1293/// <treeName>.<branchname>.<varname>
1294/// ~~~
1295/// If the variablename is enough to uniquely identify the variable, you can
1296/// leave out the tree and/or branch name.
1297/// For example, these commands generate a 3-d scatter plot of variable "var"
1298/// in the TTree tree versus variable v1 in TTree ft1 versus variable v2 in
1299/// TTree ft2.
1300/// ~~~ {.cpp}
1301/// tree.AddFriend("ft1","friendfile1.root");
1302/// tree.AddFriend("ft2","friendfile2.root");
1303/// tree.Draw("var:ft1.v1:ft2.v2");
1304/// ~~~
1305/// \image html ttree_friend2.png
1306///
1307/// The picture illustrates the access of the tree and its friends with a
1308/// Draw command.
1309/// When AddFriend is called, the ROOT file is automatically opened and the
1310/// friend tree (ft1) is read into memory. The new friend (ft1) is added to
1311/// the list of friends of tree.
1312/// The number of entries in the friend must be equal or greater to the number
1313/// of entries of the original tree. If the friend tree has fewer entries a
1314/// warning is given and the missing entries are not included in the histogram.
1315/// To retrieve the list of friends from a tree use TTree::GetListOfFriends.
1316/// When the tree is written to file (TTree::Write), the friends list is saved
1317/// with it. And when the tree is retrieved, the trees on the friends list are
1318/// also retrieved and the friendship restored.
1319/// When a tree is deleted, the elements of the friend list are also deleted.
1320/// It is possible to declare a friend tree that has the same internal
1321/// structure (same branches and leaves) as the original tree, and compare the
1322/// same values by specifying the tree.
1323/// ~~~ {.cpp}
1324/// tree.Draw("var:ft1.var:ft2.var")
1325/// ~~~
1327TFriendElement *TTree::AddFriend(const char *treename, const char *filename)
1328{
1329 if (!fFriends) {
1330 fFriends = new TList();
1331 }
1333
1334 TTree *t = fe->GetTree();
1335 bool canAddFriend = true;
1336 if (t) {
1337 canAddFriend = CheckReshuffling(*this, *t);
1338 if (!t->GetTreeIndex() && (t->GetEntries() < fEntries)) {
1339 Warning("AddFriend", "FriendElement %s in file %s has less entries %lld than its parent Tree: %lld", treename,
1341 }
1342 } else {
1343 Error("AddFriend", "Cannot find tree '%s' in file '%s', friend not added", treename, filename);
1344 canAddFriend = false;
1345 }
1346
1347 if (canAddFriend)
1348 fFriends->Add(fe);
1349 return fe;
1350}
1351
1352////////////////////////////////////////////////////////////////////////////////
1353/// Add a TFriendElement to the list of friends.
1354///
1355/// The TFile is managed by the user (e.g. the user must delete the file).
1356/// For complete description see AddFriend(const char *, const char *).
1357/// This function:
1358/// - reads a Tree with name treename from the file
1359/// - adds the Tree to the list of friends
1361TFriendElement *TTree::AddFriend(const char *treename, TFile *file)
1362{
1363 if (!fFriends) {
1364 fFriends = new TList();
1365 }
1366 TFriendElement *fe = new TFriendElement(this, treename, file);
1367 R__ASSERT(fe);
1368 TTree *t = fe->GetTree();
1369 bool canAddFriend = true;
1370 if (t) {
1371 canAddFriend = CheckReshuffling(*this, *t);
1372 if (!t->GetTreeIndex() && (t->GetEntries() < fEntries)) {
1373 Warning("AddFriend", "FriendElement %s in file %s has less entries %lld than its parent tree: %lld", treename,
1374 file->GetName(), t->GetEntries(), fEntries);
1375 }
1376 } else {
1377 Error("AddFriend", "Cannot find tree '%s' in file '%s', friend not added", treename, file->GetName());
1378 canAddFriend = false;
1379 }
1380
1381 if (canAddFriend)
1382 fFriends->Add(fe);
1383 return fe;
1384}
1385
1386////////////////////////////////////////////////////////////////////////////////
1387/// Add a TFriendElement to the list of friends.
1388///
1389/// The TTree is managed by the user (e.g., the user must delete the file).
1390/// For a complete description see AddFriend(const char *, const char *).
1392TFriendElement *TTree::AddFriend(TTree *tree, const char *alias, bool warn)
1393{
1394 if (!tree) {
1395 return nullptr;
1396 }
1397 if (!fFriends) {
1398 fFriends = new TList();
1399 }
1400 TFriendElement *fe = new TFriendElement(this, tree, alias);
1401 R__ASSERT(fe); // this assert is for historical reasons. Don't remove it unless you understand all the consequences.
1402 TTree *t = fe->GetTree();
1403 if (warn && (t->GetEntries() < fEntries)) {
1404 Warning("AddFriend", "FriendElement '%s' in file '%s' has less entries %lld than its parent tree: %lld",
1405 tree->GetName(), fe->GetFile() ? fe->GetFile()->GetName() : "(memory resident)", t->GetEntries(),
1406 fEntries);
1407 }
1408 if (CheckReshuffling(*this, *t))
1409 fFriends->Add(fe);
1410 else
1411 tree->RemoveExternalFriend(fe);
1412 return fe;
1413}
1414
1415////////////////////////////////////////////////////////////////////////////////
1416/// AutoSave tree header every fAutoSave bytes.
1417///
1418/// When large Trees are produced, it is safe to activate the AutoSave
1419/// procedure. Some branches may have buffers holding many entries.
1420/// If fAutoSave is negative, AutoSave is automatically called by
1421/// TTree::Fill when the number of bytes generated since the previous
1422/// AutoSave is greater than -fAutoSave bytes.
1423/// If fAutoSave is positive, AutoSave is automatically called by
1424/// TTree::Fill every N entries.
1425/// This function may also be invoked by the user.
1426/// Each AutoSave generates a new key on the file.
1427/// Once the key with the tree header has been written, the previous cycle
1428/// (if any) is deleted.
1429///
1430/// Note that calling TTree::AutoSave too frequently (or similarly calling
1431/// TTree::SetAutoSave with a small value) is an expensive operation.
1432/// You should make tests for your own application to find a compromise
1433/// between speed and the quantity of information you may loose in case of
1434/// a job crash.
1435///
1436/// In case your program crashes before closing the file holding this tree,
1437/// the file will be automatically recovered when you will connect the file
1438/// in UPDATE mode.
1439/// The Tree will be recovered at the status corresponding to the last AutoSave.
1440///
1441/// if option contains "SaveSelf", gDirectory->SaveSelf() is called.
1442/// This allows another process to analyze the Tree while the Tree is being filled.
1443///
1444/// if option contains "FlushBaskets", TTree::FlushBaskets is called and all
1445/// the current basket are closed-out and written to disk individually.
1446///
1447/// By default the previous header is deleted after having written the new header.
1448/// if option contains "Overwrite", the previous Tree header is deleted
1449/// before written the new header. This option is slightly faster, but
1450/// the default option is safer in case of a problem (disk quota exceeded)
1451/// when writing the new header.
1452///
1453/// The function returns the number of bytes written to the file.
1454/// if the number of bytes is null, an error has occurred while writing
1455/// the header to the file.
1456///
1457/// ## How to write a Tree in one process and view it from another process
1458///
1459/// The following two scripts illustrate how to do this.
1460/// The script treew.C is executed by process1, treer.C by process2
1461///
1462/// script treew.C:
1463/// ~~~ {.cpp}
1464/// void treew() {
1465/// TFile f("test.root","recreate");
1466/// TNtuple *ntuple = new TNtuple("ntuple","Demo","px:py:pz:random:i");
1467/// Float_t px, py, pz;
1468/// for ( Int_t i=0; i<10000000; i++) {
1469/// gRandom->Rannor(px,py);
1470/// pz = px*px + py*py;
1471/// Float_t random = gRandom->Rndm(1);
1472/// ntuple->Fill(px,py,pz,random,i);
1473/// if (i%1000 == 1) ntuple->AutoSave("SaveSelf");
1474/// }
1475/// }
1476/// ~~~
1477/// script treer.C:
1478/// ~~~ {.cpp}
1479/// void treer() {
1480/// TFile f("test.root");
1481/// TTree *ntuple = (TTree*)f.Get("ntuple");
1482/// TCanvas c1;
1483/// Int_t first = 0;
1484/// while(1) {
1485/// if (first == 0) ntuple->Draw("px>>hpx", "","",10000000,first);
1486/// else ntuple->Draw("px>>+hpx","","",10000000,first);
1487/// first = (Int_t)ntuple->GetEntries();
1488/// c1.Update();
1489/// gSystem->Sleep(1000); //sleep 1 second
1490/// ntuple->Refresh();
1491/// }
1492/// }
1493/// ~~~
1496{
1497 if (!fDirectory || fDirectory == gROOT || !fDirectory->IsWritable()) return 0;
1498 if (gDebug > 0) {
1499 Info("AutoSave", "Tree:%s after %lld bytes written\n",GetName(),GetTotBytes());
1500 }
1501 TString opt = option;
1502 opt.ToLower();
1503
1504 if (opt.Contains("flushbaskets")) {
1505 if (gDebug > 0) Info("AutoSave", "calling FlushBaskets \n");
1507 }
1508
1510
1511 TKey *key = (TKey*)fDirectory->GetListOfKeys()->FindObject(GetName());
1513 if (opt.Contains("overwrite")) {
1514 nbytes = fDirectory->WriteTObject(this,"","overwrite");
1515 } else {
1516 nbytes = fDirectory->WriteTObject(this); //nbytes will be 0 if Write failed (disk space exceeded)
1517 if (nbytes && key && strcmp(ClassName(), key->GetClassName()) == 0) {
1518 key->Delete();
1519 delete key;
1520 }
1521 }
1522 // save StreamerInfo
1523 TFile *file = fDirectory->GetFile();
1524 if (file) file->WriteStreamerInfo();
1525
1526 if (opt.Contains("saveself")) {
1528 //the following line is required in case GetUserInfo contains a user class
1529 //for which the StreamerInfo must be written. One could probably be a bit faster (Rene)
1530 if (file) file->WriteHeader();
1531 }
1532
1533 return nbytes;
1534}
1535
1536namespace {
1537 // This error message is repeated several times in the code. We write it once.
1538 const char* writeStlWithoutProxyMsg = "The class requested (%s) for the branch \"%s\""
1539 " is an instance of an stl collection and does not have a compiled CollectionProxy."
1540 " Please generate the dictionary for this collection (%s) to avoid to write corrupted data.";
1541}
1542
1543////////////////////////////////////////////////////////////////////////////////
1544/// Same as TTree::Branch() with added check that addobj matches className.
1545///
1546/// \see TTree::Branch()
1547///
1549TBranch* TTree::BranchImp(const char* branchname, const char* classname, TClass* ptrClass, void* addobj, Int_t bufsize, Int_t splitlevel)
1550{
1551 TClass* claim = TClass::GetClass(classname);
1552 if (!ptrClass) {
1553 if (claim && claim->GetCollectionProxy() && dynamic_cast<TEmulatedCollectionProxy*>(claim->GetCollectionProxy())) {
1555 claim->GetName(), branchname, claim->GetName());
1556 return nullptr;
1557 }
1558 return Branch(branchname, classname, (void*) addobj, bufsize, splitlevel);
1559 }
1560 TClass* actualClass = nullptr;
1561 void** addr = (void**) addobj;
1562 if (addr) {
1563 actualClass = ptrClass->GetActualClass(*addr);
1564 }
1565 if (ptrClass && claim) {
1566 if (!(claim->InheritsFrom(ptrClass) || ptrClass->InheritsFrom(claim))) {
1567 // Note we currently do not warn in case of splicing or over-expectation).
1568 if (claim->IsLoaded() && ptrClass->IsLoaded() && strcmp( claim->GetTypeInfo()->name(), ptrClass->GetTypeInfo()->name() ) == 0) {
1569 // The type is the same according to the C++ type_info, we must be in the case of
1570 // a template of Double32_t. This is actually a correct case.
1571 } else {
1572 Error("Branch", "The class requested (%s) for \"%s\" is different from the type of the pointer passed (%s)",
1573 claim->GetName(), branchname, ptrClass->GetName());
1574 }
1575 } else if (actualClass && (claim != actualClass) && !actualClass->InheritsFrom(claim)) {
1576 if (claim->IsLoaded() && actualClass->IsLoaded() && strcmp( claim->GetTypeInfo()->name(), actualClass->GetTypeInfo()->name() ) == 0) {
1577 // The type is the same according to the C++ type_info, we must be in the case of
1578 // a template of Double32_t. This is actually a correct case.
1579 } else {
1580 Error("Branch", "The actual class (%s) of the object provided for the definition of the branch \"%s\" does not inherit from %s",
1581 actualClass->GetName(), branchname, claim->GetName());
1582 }
1583 }
1584 }
1585 if (claim && claim->GetCollectionProxy() && dynamic_cast<TEmulatedCollectionProxy*>(claim->GetCollectionProxy())) {
1587 claim->GetName(), branchname, claim->GetName());
1588 return nullptr;
1589 }
1590 return Branch(branchname, classname, (void*) addobj, bufsize, splitlevel);
1591}
1592
1593////////////////////////////////////////////////////////////////////////////////
1594/// Same as TTree::Branch but automatic detection of the class name.
1595/// \see TTree::Branch
1598{
1599 if (!ptrClass) {
1600 Error("Branch", "The pointer specified for %s is not of a class known to ROOT", branchname);
1601 return nullptr;
1602 }
1603 TClass* actualClass = nullptr;
1604 void** addr = (void**) addobj;
1605 if (addr && *addr) {
1606 actualClass = ptrClass->GetActualClass(*addr);
1607 if (!actualClass) {
1608 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",
1609 branchname, ptrClass->GetName());
1611 } else if ((ptrClass != actualClass) && !actualClass->InheritsFrom(ptrClass)) {
1612 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());
1613 return nullptr;
1614 }
1615 } else {
1617 }
1618 if (actualClass && actualClass->GetCollectionProxy() && dynamic_cast<TEmulatedCollectionProxy*>(actualClass->GetCollectionProxy())) {
1620 actualClass->GetName(), branchname, actualClass->GetName());
1621 return nullptr;
1622 }
1623 return Branch(branchname, actualClass->GetName(), (void*) addobj, bufsize, splitlevel);
1624}
1625
1626////////////////////////////////////////////////////////////////////////////////
1627/// Same as TTree::Branch but automatic detection of the class name.
1628/// \see TTree::Branch
1630TBranch* TTree::BranchImpRef(const char* branchname, const char *classname, TClass* ptrClass, void *addobj, Int_t bufsize, Int_t splitlevel)
1631{
1632 TClass* claim = TClass::GetClass(classname);
1633 if (!ptrClass) {
1634 if (claim && claim->GetCollectionProxy() && dynamic_cast<TEmulatedCollectionProxy*>(claim->GetCollectionProxy())) {
1636 claim->GetName(), branchname, claim->GetName());
1637 return nullptr;
1638 } else if (claim == nullptr) {
1639 Error("Branch", "The pointer specified for %s is not of a class known to ROOT and %s is not a known class", branchname, classname);
1640 return nullptr;
1641 }
1642 ptrClass = claim;
1643 }
1644 TClass* actualClass = nullptr;
1645 if (!addobj) {
1646 Error("Branch", "Reference interface requires a valid object (for branch: %s)!", branchname);
1647 return nullptr;
1648 }
1649 actualClass = ptrClass->GetActualClass(addobj);
1650 if (ptrClass && claim) {
1651 if (!(claim->InheritsFrom(ptrClass) || ptrClass->InheritsFrom(claim))) {
1652 // Note we currently do not warn in case of splicing or over-expectation).
1653 if (claim->IsLoaded() && ptrClass->IsLoaded() && strcmp( claim->GetTypeInfo()->name(), ptrClass->GetTypeInfo()->name() ) == 0) {
1654 // The type is the same according to the C++ type_info, we must be in the case of
1655 // a template of Double32_t. This is actually a correct case.
1656 } else {
1657 Error("Branch", "The class requested (%s) for \"%s\" is different from the type of the object passed (%s)",
1658 claim->GetName(), branchname, ptrClass->GetName());
1659 }
1660 } else if (actualClass && (claim != actualClass) && !actualClass->InheritsFrom(claim)) {
1661 if (claim->IsLoaded() && actualClass->IsLoaded() && strcmp( claim->GetTypeInfo()->name(), actualClass->GetTypeInfo()->name() ) == 0) {
1662 // The type is the same according to the C++ type_info, we must be in the case of
1663 // a template of Double32_t. This is actually a correct case.
1664 } else {
1665 Error("Branch", "The actual class (%s) of the object provided for the definition of the branch \"%s\" does not inherit from %s",
1666 actualClass->GetName(), branchname, claim->GetName());
1667 }
1668 }
1669 }
1670 if (!actualClass) {
1671 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",
1672 branchname, ptrClass->GetName());
1674 } else if ((ptrClass != actualClass) && !actualClass->InheritsFrom(ptrClass)) {
1675 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());
1676 return nullptr;
1677 }
1678 if (actualClass && actualClass->GetCollectionProxy() && dynamic_cast<TEmulatedCollectionProxy*>(actualClass->GetCollectionProxy())) {
1680 actualClass->GetName(), branchname, actualClass->GetName());
1681 return nullptr;
1682 }
1683 return BronchExec(branchname, actualClass->GetName(), (void*) addobj, false, bufsize, splitlevel);
1684}
1685
1686////////////////////////////////////////////////////////////////////////////////
1687/// Same as TTree::Branch but automatic detection of the class name.
1688/// \see TTree::Branch
1691{
1692 if (!ptrClass) {
1693 if (datatype == kOther_t || datatype == kNoType_t) {
1694 Error("Branch", "The pointer specified for %s is not of a class or type known to ROOT", branchname);
1695 } else {
1697 return Branch(branchname,addobj,varname.Data(),bufsize);
1698 }
1699 return nullptr;
1700 }
1701 TClass* actualClass = nullptr;
1702 if (!addobj) {
1703 Error("Branch", "Reference interface requires a valid object (for branch: %s)!", branchname);
1704 return nullptr;
1705 }
1706 actualClass = ptrClass->GetActualClass(addobj);
1707 if (!actualClass) {
1708 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",
1709 branchname, ptrClass->GetName());
1711 } else if ((ptrClass != actualClass) && !actualClass->InheritsFrom(ptrClass)) {
1712 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());
1713 return nullptr;
1714 }
1715 if (actualClass && actualClass->GetCollectionProxy() && dynamic_cast<TEmulatedCollectionProxy*>(actualClass->GetCollectionProxy())) {
1717 actualClass->GetName(), branchname, actualClass->GetName());
1718 return nullptr;
1719 }
1720 return BronchExec(branchname, actualClass->GetName(), (void*) addobj, false, bufsize, splitlevel);
1721}
1722
1723////////////////////////////////////////////////////////////////////////////////
1724// Wrapper to turn Branch call with an std::array into the relevant leaf list
1725// call
1726TBranch *TTree::BranchImpArr(const char *branchname, EDataType datatype, std::size_t N, void *addobj, Int_t bufsize,
1727 Int_t /* splitlevel */)
1728{
1729 if (datatype == kOther_t || datatype == kNoType_t) {
1730 Error("Branch",
1731 "The inner type of the std::array passed specified for %s is not of a class or type known to ROOT",
1732 branchname);
1733 } else {
1735 varname.Form("%s[%d]/%c", branchname, (int)N, DataTypeToChar(datatype));
1736 return Branch(branchname, addobj, varname.Data(), bufsize);
1737 }
1738 return nullptr;
1739}
1740
1741////////////////////////////////////////////////////////////////////////////////
1742/// Deprecated function. Use next function instead.
1744Int_t TTree::Branch(TList* li, Int_t bufsize /* = 32000 */ , Int_t splitlevel /* = 99 */)
1745{
1746 return Branch((TCollection*) li, bufsize, splitlevel);
1747}
1748
1749////////////////////////////////////////////////////////////////////////////////
1750/// Create one branch for each element in the collection.
1751///
1752/// Each entry in the collection becomes a top level branch if the
1753/// corresponding class is not a collection. If it is a collection, the entry
1754/// in the collection becomes in turn top level branches, etc.
1755/// The splitlevel is decreased by 1 every time a new collection is found.
1756/// For example if list is a TObjArray*
1757/// - if splitlevel = 1, one top level branch is created for each element
1758/// of the TObjArray.
1759/// - if splitlevel = 2, one top level branch is created for each array element.
1760/// if, in turn, one of the array elements is a TCollection, one top level
1761/// branch will be created for each element of this collection.
1762///
1763/// In case a collection element is a TClonesArray, the special Tree constructor
1764/// for TClonesArray is called.
1765/// The collection itself cannot be a TClonesArray.
1766///
1767/// The function returns the total number of branches created.
1768///
1769/// If name is given, all branch names will be prefixed with name_.
1770///
1771/// IMPORTANT NOTE1: This function should not be called with splitlevel < 1.
1772///
1773/// IMPORTANT NOTE2: The branches created by this function will have names
1774/// corresponding to the collection or object names. It is important
1775/// to give names to collections to avoid misleading branch names or
1776/// identical branch names. By default collections have a name equal to
1777/// the corresponding class name, e.g. the default name for a TList is "TList".
1778///
1779/// And in general, in case two or more master branches contain subbranches
1780/// with identical names, one must add a "." (dot) character at the end
1781/// of the master branch name. This will force the name of the subbranches
1782/// to be of the form `master.subbranch` instead of simply `subbranch`.
1783/// This situation happens when the top level object
1784/// has two or more members referencing the same class.
1785/// Without the dot, the prefix will not be there and that might cause ambiguities.
1786/// For example, if a Tree has two branches B1 and B2 corresponding
1787/// to objects of the same class MyClass, one can do:
1788/// ~~~ {.cpp}
1789/// tree.Branch("B1.","MyClass",&b1,8000,1);
1790/// tree.Branch("B2.","MyClass",&b2,8000,1);
1791/// ~~~
1792/// if MyClass has 3 members a,b,c, the two instructions above will generate
1793/// subbranches called B1.a, B1.b ,B1.c, B2.a, B2.b, B2.c
1794/// In other words, the trailing dot of the branch name is semantically relevant
1795/// and recommended.
1796///
1797/// Example:
1798/// ~~~ {.cpp}
1799/// {
1800/// TTree T("T","test list");
1801/// TList *list = new TList();
1802///
1803/// TObjArray *a1 = new TObjArray();
1804/// a1->SetName("a1");
1805/// list->Add(a1);
1806/// TH1F *ha1a = new TH1F("ha1a","ha1",100,0,1);
1807/// TH1F *ha1b = new TH1F("ha1b","ha1",100,0,1);
1808/// a1->Add(ha1a);
1809/// a1->Add(ha1b);
1810/// TObjArray *b1 = new TObjArray();
1811/// b1->SetName("b1");
1812/// list->Add(b1);
1813/// TH1F *hb1a = new TH1F("hb1a","hb1",100,0,1);
1814/// TH1F *hb1b = new TH1F("hb1b","hb1",100,0,1);
1815/// b1->Add(hb1a);
1816/// b1->Add(hb1b);
1817///
1818/// TObjArray *a2 = new TObjArray();
1819/// a2->SetName("a2");
1820/// list->Add(a2);
1821/// TH1S *ha2a = new TH1S("ha2a","ha2",100,0,1);
1822/// TH1S *ha2b = new TH1S("ha2b","ha2",100,0,1);
1823/// a2->Add(ha2a);
1824/// a2->Add(ha2b);
1825///
1826/// T.Branch(list,16000,2);
1827/// T.Print();
1828/// }
1829/// ~~~
1831Int_t TTree::Branch(TCollection* li, Int_t bufsize /* = 32000 */, Int_t splitlevel /* = 99 */, const char* name /* = "" */)
1832{
1833
1834 if (!li) {
1835 return 0;
1836 }
1837 TObject* obj = nullptr;
1838 Int_t nbranches = GetListOfBranches()->GetEntries();
1839 if (li->InheritsFrom(TClonesArray::Class())) {
1840 Error("Branch", "Cannot call this constructor for a TClonesArray");
1841 return 0;
1842 }
1843 Int_t nch = strlen(name);
1845 TIter next(li);
1846 while ((obj = next())) {
1848 TCollection* col = (TCollection*) obj;
1849 if (nch) {
1850 branchname.Form("%s_%s_", name, col->GetName());
1851 } else {
1852 branchname.Form("%s_", col->GetName());
1853 }
1854 Branch(col, bufsize, splitlevel - 1, branchname);
1855 } else {
1856 if (nch && (name[nch-1] == '_')) {
1857 branchname.Form("%s%s", name, obj->GetName());
1858 } else {
1859 if (nch) {
1860 branchname.Form("%s_%s", name, obj->GetName());
1861 } else {
1862 branchname.Form("%s", obj->GetName());
1863 }
1864 }
1865 if (splitlevel > 99) {
1866 branchname += ".";
1867 }
1868 Bronch(branchname, obj->ClassName(), li->GetObjectRef(obj), bufsize, splitlevel - 1);
1869 }
1870 }
1871 return GetListOfBranches()->GetEntries() - nbranches;
1872}
1873
1874////////////////////////////////////////////////////////////////////////////////
1875/// Create one branch for each element in the folder.
1876/// Returns the total number of branches created.
1878Int_t TTree::Branch(const char* foldername, Int_t bufsize /* = 32000 */, Int_t splitlevel /* = 99 */)
1879{
1880 TObject* ob = gROOT->FindObjectAny(foldername);
1881 if (!ob) {
1882 return 0;
1883 }
1884 if (ob->IsA() != TFolder::Class()) {
1885 return 0;
1886 }
1887 Int_t nbranches = GetListOfBranches()->GetEntries();
1888 TFolder* folder = (TFolder*) ob;
1889 TIter next(folder->GetListOfFolders());
1890 TObject* obj = nullptr;
1891 char* curname = new char[1000];
1892 char occur[20];
1893 while ((obj = next())) {
1894 snprintf(curname,1000, "%s/%s", foldername, obj->GetName());
1895 if (obj->IsA() == TFolder::Class()) {
1897 } else {
1898 void* add = (void*) folder->GetListOfFolders()->GetObjectRef(obj);
1899 for (Int_t i = 0; i < 1000; ++i) {
1900 if (curname[i] == 0) {
1901 break;
1902 }
1903 if (curname[i] == '/') {
1904 curname[i] = '.';
1905 }
1906 }
1907 Int_t noccur = folder->Occurence(obj);
1908 if (noccur > 0) {
1909 snprintf(occur,20, "_%d", noccur);
1910 strlcat(curname, occur,1000);
1911 }
1913 if (br) br->SetBranchFolder();
1914 }
1915 }
1916 delete[] curname;
1917 return GetListOfBranches()->GetEntries() - nbranches;
1918}
1919
1920////////////////////////////////////////////////////////////////////////////////
1921/// Create a new TTree Branch.
1922///
1923/// This Branch constructor is provided to support non-objects in
1924/// a Tree. The variables described in leaflist may be simple
1925/// variables or structures. // See the two following
1926/// constructors for writing objects in a Tree.
1927///
1928/// By default the branch buffers are stored in the same file as the Tree.
1929/// use TBranch::SetFile to specify a different file
1930///
1931/// * address is the address of the first item of a structure.
1932/// * leaflist is the concatenation of all the variable names and types
1933/// separated by a colon character :
1934/// The variable name and the variable type are separated by a slash (/).
1935/// The variable type may be 0,1 or 2 characters. If no type is given,
1936/// the type of the variable is assumed to be the same as the previous
1937/// variable. If the first variable does not have a type, it is assumed
1938/// of type F by default. The list of currently supported types is given below:
1939/// - `C` : a character string terminated by the 0 character
1940/// - `B` : an 8 bit signed integer (`Char_t`); Treated as a character when in an array.
1941/// - `b` : an 8 bit unsigned integer (`UChar_t`)
1942/// - `S` : a 16 bit signed integer (`Short_t`)
1943/// - `s` : a 16 bit unsigned integer (`UShort_t`)
1944/// - `I` : a 32 bit signed integer (`Int_t`)
1945/// - `i` : a 32 bit unsigned integer (`UInt_t`)
1946/// - `F` : a 32 bit floating point (`Float_t`)
1947/// - `f` : a 24 bit floating point with truncated mantissa (`Float16_t`)
1948/// - `D` : a 64 bit floating point (`Double_t`)
1949/// - `d` : a 24 bit truncated floating point (`Double32_t`)
1950/// - `L` : a 64 bit signed integer (`Long64_t`)
1951/// - `l` : a 64 bit unsigned integer (`ULong64_t`)
1952/// - `G` : a long signed integer, stored as 64 bit (`Long_t`)
1953/// - `g` : a long unsigned integer, stored as 64 bit (`ULong_t`)
1954/// - `O` : [the letter `o`, not a zero] a boolean (`bool`)
1955///
1956/// Arrays of values are supported with the following syntax:
1957/// - If leaf name has the form var[nelem], where nelem is alphanumeric, then
1958/// if nelem is a leaf name, it is used as the variable size of the array,
1959/// otherwise return 0.
1960/// The leaf referred to by nelem **MUST** be an int (/I),
1961/// - If leaf name has the form var[nelem], where nelem is a non-negative integer, then
1962/// it is used as the fixed size of the array.
1963/// - If leaf name has the form of a multi-dimensional array (e.g. var[nelem][nelem2])
1964/// where nelem and nelem2 are non-negative integer) then
1965/// it is used as a 2 dimensional array of fixed size.
1966/// - In case of the truncated floating point types (Float16_t and Double32_t) you can
1967/// furthermore specify the range in the style [xmin,xmax] or [xmin,xmax,nbits] after
1968/// the type character. See `TStreamerElement::GetRange()` for further information.
1969///
1970/// Any of other form is not supported.
1971///
1972/// Note that the TTree will assume that all the item are contiguous in memory.
1973/// On some platform, this is not always true of the member of a struct or a class,
1974/// due to padding and alignment. Sorting your data member in order of decreasing
1975/// sizeof usually leads to their being contiguous in memory.
1976///
1977/// * bufsize is the buffer size in bytes for this branch
1978/// The default value is 32000 bytes and should be ok for most cases.
1979/// You can specify a larger value (e.g. 256000) if your Tree is not split
1980/// and each entry is large (Megabytes)
1981/// A small value for bufsize is optimum if you intend to access
1982/// the entries in the Tree randomly and your Tree is in split mode.
1984TBranch* TTree::Branch(const char* name, void* address, const char* leaflist, Int_t bufsize /* = 32000 */)
1985{
1986 TBranch* branch = new TBranch(this, name, address, leaflist, bufsize);
1987 if (branch->IsZombie()) {
1988 delete branch;
1989 branch = nullptr;
1990 return nullptr;
1991 }
1993 return branch;
1994}
1995
1996////////////////////////////////////////////////////////////////////////////////
1997/// Create a new branch with the object of class classname at address addobj.
1998///
1999/// WARNING:
2000///
2001/// Starting with Root version 3.01, the Branch function uses the new style
2002/// branches (TBranchElement). To get the old behaviour, you can:
2003/// - call BranchOld or
2004/// - call TTree::SetBranchStyle(0)
2005///
2006/// Note that with the new style, classname does not need to derive from TObject.
2007/// It must derived from TObject if the branch style has been set to 0 (old)
2008///
2009/// Note: See the comments in TBranchElement::SetAddress() for a more
2010/// detailed discussion of the meaning of the addobj parameter in
2011/// the case of new-style branches.
2012///
2013/// Use splitlevel < 0 instead of splitlevel=0 when the class
2014/// has a custom Streamer
2015///
2016/// Note: if the split level is set to the default (99), TTree::Branch will
2017/// not issue a warning if the class can not be split.
2019TBranch* TTree::Branch(const char* name, const char* classname, void* addobj, Int_t bufsize /* = 32000 */, Int_t splitlevel /* = 99 */)
2020{
2021 if (fgBranchStyle == 1) {
2022 return Bronch(name, classname, addobj, bufsize, splitlevel);
2023 } else {
2024 if (splitlevel < 0) {
2025 splitlevel = 0;
2026 }
2027 return BranchOld(name, classname, addobj, bufsize, splitlevel);
2028 }
2029}
2030
2031////////////////////////////////////////////////////////////////////////////////
2032/// Create a new TTree BranchObject.
2033///
2034/// Build a TBranchObject for an object of class classname.
2035/// addobj is the address of a pointer to an object of class classname.
2036/// IMPORTANT: classname must derive from TObject.
2037/// The class dictionary must be available (ClassDef in class header).
2038///
2039/// This option requires access to the library where the corresponding class
2040/// is defined. Accessing one single data member in the object implies
2041/// reading the full object.
2042/// See the next Branch constructor for a more efficient storage
2043/// in case the entry consists of arrays of identical objects.
2044///
2045/// By default the branch buffers are stored in the same file as the Tree.
2046/// use TBranch::SetFile to specify a different file
2047///
2048/// IMPORTANT NOTE about branch names:
2049///
2050/// And in general, in case two or more master branches contain subbranches
2051/// with identical names, one must add a "." (dot) character at the end
2052/// of the master branch name. This will force the name of the subbranches
2053/// to be of the form `master.subbranch` instead of simply `subbranch`.
2054/// This situation happens when the top level object
2055/// has two or more members referencing the same class.
2056/// For example, if a Tree has two branches B1 and B2 corresponding
2057/// to objects of the same class MyClass, one can do:
2058/// ~~~ {.cpp}
2059/// tree.Branch("B1.","MyClass",&b1,8000,1);
2060/// tree.Branch("B2.","MyClass",&b2,8000,1);
2061/// ~~~
2062/// if MyClass has 3 members a,b,c, the two instructions above will generate
2063/// subbranches called B1.a, B1.b ,B1.c, B2.a, B2.b, B2.c
2064///
2065/// bufsize is the buffer size in bytes for this branch
2066/// The default value is 32000 bytes and should be ok for most cases.
2067/// You can specify a larger value (e.g. 256000) if your Tree is not split
2068/// and each entry is large (Megabytes)
2069/// A small value for bufsize is optimum if you intend to access
2070/// the entries in the Tree randomly and your Tree is in split mode.
2072TBranch* TTree::BranchOld(const char* name, const char* classname, void* addobj, Int_t bufsize /* = 32000 */, Int_t splitlevel /* = 1 */)
2073{
2074 TClass* cl = TClass::GetClass(classname);
2075 if (!cl) {
2076 Error("BranchOld", "Cannot find class: '%s'", classname);
2077 return nullptr;
2078 }
2079 if (!cl->IsTObject()) {
2080 if (fgBranchStyle == 0) {
2081 Fatal("BranchOld", "The requested class ('%s') does not inherit from TObject.\n"
2082 "\tfgBranchStyle is set to zero requesting by default to use BranchOld.\n"
2083 "\tIf this is intentional use Bronch instead of Branch or BranchOld.", classname);
2084 } else {
2085 Fatal("BranchOld", "The requested class ('%s') does not inherit from TObject.\n"
2086 "\tYou can not use BranchOld to store objects of this type.",classname);
2087 }
2088 return nullptr;
2089 }
2090 TBranch* branch = new TBranchObject(this, name, classname, addobj, bufsize, splitlevel);
2092 if (!splitlevel) {
2093 return branch;
2094 }
2095 // We are going to fully split the class now.
2096 TObjArray* blist = branch->GetListOfBranches();
2097 const char* rdname = nullptr;
2098 const char* dname = nullptr;
2100 char** apointer = (char**) addobj;
2101 TObject* obj = (TObject*) *apointer;
2102 bool delobj = false;
2103 if (!obj) {
2104 obj = (TObject*) cl->New();
2105 delobj = true;
2106 }
2107 // Build the StreamerInfo if first time for the class.
2108 BuildStreamerInfo(cl, obj);
2109 // Loop on all public data members of the class and its base classes.
2111 Int_t isDot = 0;
2112 if (name[lenName-1] == '.') {
2113 isDot = 1;
2114 }
2115 TBranch* branch1 = nullptr;
2116 TRealData* rd = nullptr;
2117 TRealData* rdi = nullptr;
2119 TIter next(cl->GetListOfRealData());
2120 // Note: This loop results in a full split because the
2121 // real data list includes all data members of
2122 // data members.
2123 while ((rd = (TRealData*) next())) {
2124 if (rd->TestBit(TRealData::kTransient)) continue;
2125
2126 // Loop over all data members creating branches for each one.
2127 TDataMember* dm = rd->GetDataMember();
2128 if (!dm->IsPersistent()) {
2129 // Do not process members with an "!" as the first character in the comment field.
2130 continue;
2131 }
2132 if (rd->IsObject()) {
2133 // We skip data members of class type.
2134 // But we do build their real data, their
2135 // streamer info, and write their streamer
2136 // info to the current directory's file.
2137 // Oh yes, and we also do this for all of
2138 // their base classes.
2140 if (clm) {
2141 BuildStreamerInfo(clm, (char*) obj + rd->GetThisOffset());
2142 }
2143 continue;
2144 }
2145 rdname = rd->GetName();
2146 dname = dm->GetName();
2147 if (cl->CanIgnoreTObjectStreamer()) {
2148 // Skip the TObject base class data members.
2149 // FIXME: This prevents a user from ever
2150 // using these names themself!
2151 if (!strcmp(dname, "fBits")) {
2152 continue;
2153 }
2154 if (!strcmp(dname, "fUniqueID")) {
2155 continue;
2156 }
2157 }
2158 TDataType* dtype = dm->GetDataType();
2159 Int_t code = 0;
2160 if (dtype) {
2161 code = dm->GetDataType()->GetType();
2162 }
2163 // Encode branch name. Use real data member name
2165 if (isDot) {
2166 if (dm->IsaPointer()) {
2167 // FIXME: This is wrong! The asterisk is not usually in the front!
2168 branchname.Form("%s%s", name, &rdname[1]);
2169 } else {
2170 branchname.Form("%s%s", name, &rdname[0]);
2171 }
2172 }
2173 // FIXME: Change this to a string stream.
2175 Int_t offset = rd->GetThisOffset();
2176 char* pointer = ((char*) obj) + offset;
2177 if (dm->IsaPointer()) {
2178 // We have a pointer to an object or a pointer to an array of basic types.
2179 TClass* clobj = nullptr;
2180 if (!dm->IsBasic()) {
2182 }
2183 if (clobj && clobj->InheritsFrom(TClonesArray::Class())) {
2184 // We have a pointer to a clones array.
2185 char* cpointer = (char*) pointer;
2186 char** ppointer = (char**) cpointer;
2188 if (splitlevel != 2) {
2189 if (isDot) {
2191 } else {
2192 // FIXME: This is wrong! The asterisk is not usually in the front!
2193 branch1 = new TBranchClones(branch,&branchname.Data()[1], pointer, bufsize);
2194 }
2195 blist->Add(branch1);
2196 } else {
2197 if (isDot) {
2198 branch1 = new TBranchObject(branch, branchname, li->ClassName(), pointer, bufsize);
2199 } else {
2200 // FIXME: This is wrong! The asterisk is not usually in the front!
2201 branch1 = new TBranchObject(branch, &branchname.Data()[1], li->ClassName(), pointer, bufsize);
2202 }
2203 blist->Add(branch1);
2204 }
2205 } else if (clobj) {
2206 // We have a pointer to an object.
2207 //
2208 // It must be a TObject object.
2209 if (!clobj->IsTObject()) {
2210 continue;
2211 }
2212 branch1 = new TBranchObject(branch, dname, clobj->GetName(), pointer, bufsize, 0);
2213 if (isDot) {
2214 branch1->SetName(branchname);
2215 } else {
2216 // FIXME: This is wrong! The asterisk is not usually in the front!
2217 // Do not use the first character (*).
2218 branch1->SetName(&branchname.Data()[1]);
2219 }
2220 blist->Add(branch1);
2221 } else {
2222 // We have a pointer to an array of basic types.
2223 //
2224 // Check the comments in the text of the code for an index specification.
2225 const char* index = dm->GetArrayIndex();
2226 if (index[0]) {
2227 // We are a pointer to a varying length array of basic types.
2228 //check that index is a valid data member name
2229 //if member is part of an object (e.g. fA and index=fN)
2230 //index must be changed from fN to fA.fN
2231 TString aindex (rd->GetName());
2232 Ssiz_t rdot = aindex.Last('.');
2233 if (rdot>=0) {
2234 aindex.Remove(rdot+1);
2235 aindex.Append(index);
2236 }
2237 nexti.Reset();
2238 while ((rdi = (TRealData*) nexti())) {
2239 if (rdi->TestBit(TRealData::kTransient)) continue;
2240
2241 if (!strcmp(rdi->GetName(), index)) {
2242 break;
2243 }
2244 if (!strcmp(rdi->GetName(), aindex)) {
2245 index = rdi->GetName();
2246 break;
2247 }
2248 }
2249
2250 char vcode = DataTypeToChar((EDataType)code);
2251 // Note that we differentiate between strings and
2252 // char array by the fact that there is NO specified
2253 // size for a string (see next if (code == 1)
2254
2255 if (vcode) {
2256 leaflist.Form("%s[%s]/%c", &rdname[0], index, vcode);
2257 } else {
2258 Error("BranchOld", "Cannot create branch for rdname: %s code: %d", branchname.Data(), code);
2259 leaflist = "";
2260 }
2261 } else {
2262 // We are possibly a character string.
2263 if (code == 1) {
2264 // We are a character string.
2265 leaflist.Form("%s/%s", dname, "C");
2266 } else {
2267 // Invalid array specification.
2268 // FIXME: We need an error message here.
2269 continue;
2270 }
2271 }
2272 // There are '*' in both the branchname and leaflist, remove them.
2273 TString bname( branchname );
2274 bname.ReplaceAll("*","");
2275 leaflist.ReplaceAll("*","");
2276 // Add the branch to the tree and indicate that the address
2277 // is that of a pointer to be dereferenced before using.
2278 branch1 = new TBranch(branch, bname, *((void**) pointer), leaflist, bufsize);
2279 TLeaf* leaf = (TLeaf*) branch1->GetListOfLeaves()->At(0);
2281 leaf->SetAddress((void**) pointer);
2282 blist->Add(branch1);
2283 }
2284 } else if (dm->IsBasic()) {
2285 // We have a basic type.
2286
2287 char vcode = DataTypeToChar((EDataType)code);
2288 if (vcode) {
2289 leaflist.Form("%s/%c", rdname, vcode);
2290 } else {
2291 Error("BranchOld", "Cannot create branch for rdname: %s code: %d", branchname.Data(), code);
2292 leaflist = "";
2293 }
2294 branch1 = new TBranch(branch, branchname, pointer, leaflist, bufsize);
2295 branch1->SetTitle(rdname);
2296 blist->Add(branch1);
2297 } else {
2298 // We have a class type.
2299 // Note: This cannot happen due to the rd->IsObject() test above.
2300 // FIXME: Put an error message here just in case.
2301 }
2302 if (branch1) {
2303 branch1->SetOffset(offset);
2304 } else {
2305 Warning("BranchOld", "Cannot process member: '%s'", rdname);
2306 }
2307 }
2308 if (delobj) {
2309 delete obj;
2310 obj = nullptr;
2311 }
2312 return branch;
2313}
2314
2315////////////////////////////////////////////////////////////////////////////////
2316/// Build the optional branch supporting the TRefTable.
2317/// This branch will keep all the information to find the branches
2318/// containing referenced objects.
2319///
2320/// At each Tree::Fill, the branch numbers containing the
2321/// referenced objects are saved to the TBranchRef basket.
2322/// When the Tree header is saved (via TTree::Write), the branch
2323/// is saved keeping the information with the pointers to the branches
2324/// having referenced objects.
2327{
2328 if (!fBranchRef) {
2329 fBranchRef = new TBranchRef(this);
2330 }
2331 return fBranchRef;
2332}
2333
2334////////////////////////////////////////////////////////////////////////////////
2335/// Create a new TTree BranchElement.
2336///
2337/// ## WARNING about this new function
2338///
2339/// This function is designed to replace the internal
2340/// implementation of the old TTree::Branch (whose implementation
2341/// has been moved to BranchOld).
2342///
2343/// NOTE: The 'Bronch' method supports only one possible calls
2344/// signature (where the object type has to be specified
2345/// explicitly and the address must be the address of a pointer).
2346/// For more flexibility use 'Branch'. Use Bronch only in (rare)
2347/// cases (likely to be legacy cases) where both the new and old
2348/// implementation of Branch needs to be used at the same time.
2349///
2350/// This function is far more powerful than the old Branch
2351/// function. It supports the full C++, including STL and has
2352/// the same behaviour in split or non-split mode. classname does
2353/// not have to derive from TObject. The function is based on
2354/// the new TStreamerInfo.
2355///
2356/// Build a TBranchElement for an object of class classname.
2357///
2358/// addr is the address of a pointer to an object of class
2359/// classname. The class dictionary must be available (ClassDef
2360/// in class header).
2361///
2362/// Note: See the comments in TBranchElement::SetAddress() for a more
2363/// detailed discussion of the meaning of the addr parameter.
2364///
2365/// This option requires access to the library where the
2366/// corresponding class is defined. Accessing one single data
2367/// member in the object implies reading the full object.
2368///
2369/// By default the branch buffers are stored in the same file as the Tree.
2370/// use TBranch::SetFile to specify a different file
2371///
2372/// IMPORTANT NOTE about branch names:
2373///
2374/// And in general, in case two or more master branches contain subbranches
2375/// with identical names, one must add a "." (dot) character at the end
2376/// of the master branch name. This will force the name of the subbranches
2377/// to be of the form `master.subbranch` instead of simply `subbranch`.
2378/// This situation happens when the top level object
2379/// has two or more members referencing the same class.
2380/// For example, if a Tree has two branches B1 and B2 corresponding
2381/// to objects of the same class MyClass, one can do:
2382/// ~~~ {.cpp}
2383/// tree.Branch("B1.","MyClass",&b1,8000,1);
2384/// tree.Branch("B2.","MyClass",&b2,8000,1);
2385/// ~~~
2386/// if MyClass has 3 members a,b,c, the two instructions above will generate
2387/// subbranches called B1.a, B1.b ,B1.c, B2.a, B2.b, B2.c
2388///
2389/// bufsize is the buffer size in bytes for this branch
2390/// The default value is 32000 bytes and should be ok for most cases.
2391/// You can specify a larger value (e.g. 256000) if your Tree is not split
2392/// and each entry is large (Megabytes)
2393/// A small value for bufsize is optimum if you intend to access
2394/// the entries in the Tree randomly and your Tree is in split mode.
2395///
2396/// Use splitlevel < 0 instead of splitlevel=0 when the class
2397/// has a custom Streamer
2398///
2399/// Note: if the split level is set to the default (99), TTree::Branch will
2400/// not issue a warning if the class can not be split.
2402TBranch* TTree::Bronch(const char* name, const char* classname, void* addr, Int_t bufsize /* = 32000 */, Int_t splitlevel /* = 99 */)
2403{
2404 return BronchExec(name, classname, addr, true, bufsize, splitlevel);
2405}
2406
2407////////////////////////////////////////////////////////////////////////////////
2408/// Helper function implementing TTree::Bronch and TTree::Branch(const char *name, T &obj);
2410TBranch* TTree::BronchExec(const char* name, const char* classname, void* addr, bool isptrptr, Int_t bufsize /* = 32000 */, Int_t splitlevel /* = 99 */)
2411{
2412 TClass* cl = TClass::GetClass(classname);
2413 if (!cl) {
2414 Error("Bronch", "Cannot find class:%s", classname);
2415 return nullptr;
2416 }
2417
2418 //if splitlevel <= 0 and class has a custom Streamer, we must create
2419 //a TBranchObject. We cannot assume that TClass::ReadBuffer is consistent
2420 //with the custom Streamer. The penalty is that one cannot process
2421 //this Tree without the class library containing the class.
2422
2423 char* objptr = nullptr;
2424 if (!isptrptr) {
2425 objptr = (char*)addr;
2426 } else if (addr) {
2427 objptr = *((char**) addr);
2428 }
2429
2430 if (cl == TClonesArray::Class()) {
2432 if (!clones) {
2433 Error("Bronch", "Pointer to TClonesArray is null");
2434 return nullptr;
2435 }
2436 if (!clones->GetClass()) {
2437 Error("Bronch", "TClonesArray with no class defined in branch: %s", name);
2438 return nullptr;
2439 }
2440 if (!clones->GetClass()->HasDataMemberInfo()) {
2441 Error("Bronch", "TClonesArray with no dictionary defined in branch: %s", name);
2442 return nullptr;
2443 }
2444 bool hasCustomStreamer = clones->GetClass()->HasCustomStreamerMember();
2445 if (splitlevel > 0) {
2447 Warning("Bronch", "Using split mode on a class: %s with a custom Streamer", clones->GetClass()->GetName());
2448 } else {
2449 if (hasCustomStreamer) clones->BypassStreamer(false);
2450 TBranchObject *branch = new TBranchObject(this,name,classname,addr,bufsize,0,/*compress=*/ -1,isptrptr);
2452 return branch;
2453 }
2454 }
2455
2456 if (cl->GetCollectionProxy()) {
2458 //if (!collProxy) {
2459 // Error("Bronch", "%s is missing its CollectionProxy (for branch %s)", classname, name);
2460 //}
2461 TClass* inklass = collProxy->GetValueClass();
2462 if (!inklass && (collProxy->GetType() == 0)) {
2463 Error("Bronch", "%s with no class defined in branch: %s", classname, name);
2464 return nullptr;
2465 }
2466 if ((splitlevel > 0) && inklass && (inklass->GetCollectionProxy() == nullptr)) {
2468 if ((stl != ROOT::kSTLmap) && (stl != ROOT::kSTLmultimap)) {
2469 if (!inklass->HasDataMemberInfo()) {
2470 Error("Bronch", "Container with no dictionary defined in branch: %s", name);
2471 return nullptr;
2472 }
2473 if (inklass->HasCustomStreamerMember()) {
2474 Warning("Bronch", "Using split mode on a class: %s with a custom Streamer", inklass->GetName());
2475 }
2476 }
2477 }
2478 //-------------------------------------------------------------------------
2479 // If the splitting switch is enabled, the split level is big enough and
2480 // the collection contains pointers we can split it
2481 //////////////////////////////////////////////////////////////////////////
2482
2483 TBranch *branch;
2484 if( splitlevel > kSplitCollectionOfPointers && collProxy->HasPointers() )
2486 else
2489 if (isptrptr) {
2490 branch->SetAddress(addr);
2491 } else {
2492 branch->SetObject(addr);
2493 }
2494 return branch;
2495 }
2496
2497 bool hasCustomStreamer = false;
2498 if (!cl->HasDataMemberInfo() && !cl->GetCollectionProxy()) {
2499 Error("Bronch", "Cannot find dictionary for class: %s", classname);
2500 return nullptr;
2501 }
2502
2503 if (!cl->GetCollectionProxy() && cl->HasCustomStreamerMember()) {
2504 // Not an STL container and the linkdef file had a "-" after the class name.
2505 hasCustomStreamer = true;
2506 }
2507
2508 if (splitlevel < 0 || ((splitlevel == 0) && hasCustomStreamer && cl->IsTObject())) {
2511 return branch;
2512 }
2513
2514 if (cl == TClonesArray::Class()) {
2515 // Special case of TClonesArray.
2516 // No dummy object is created.
2517 // The streamer info is not rebuilt unoptimized.
2518 // No dummy top-level branch is created.
2519 // No splitting is attempted.
2522 if (isptrptr) {
2523 branch->SetAddress(addr);
2524 } else {
2525 branch->SetObject(addr);
2526 }
2527 return branch;
2528 }
2529
2530 //
2531 // If we are not given an object to use as an i/o buffer
2532 // then create a temporary one which we will delete just
2533 // before returning.
2534 //
2535
2536 bool delobj = false;
2537
2538 if (!objptr) {
2539 objptr = (char*) cl->New();
2540 delobj = true;
2541 }
2542
2543 //
2544 // Avoid splitting unsplittable classes.
2545 //
2546
2547 if ((splitlevel > 0) && !cl->CanSplit()) {
2548 if (splitlevel != 99) {
2549 Warning("Bronch", "%s cannot be split, resetting splitlevel to 0", cl->GetName());
2550 }
2551 splitlevel = 0;
2552 }
2553
2554 //
2555 // Make sure the streamer info is built and fetch it.
2556 //
2557 // If we are splitting, then make sure the streamer info
2558 // is built unoptimized (data members are not combined).
2559 //
2560
2562 if (!sinfo) {
2563 Error("Bronch", "Cannot build the StreamerInfo for class: %s", cl->GetName());
2564 return nullptr;
2565 }
2566
2567 //
2568 // Create a dummy top level branch object.
2569 //
2570
2571 Int_t id = -1;
2572 if (splitlevel > 0) {
2573 id = -2;
2574 }
2577
2578 //
2579 // Do splitting, if requested.
2580 //
2581
2583 branch->Unroll(name, cl, sinfo, objptr, bufsize, splitlevel);
2584 }
2585
2586 //
2587 // Setup our offsets into the user's i/o buffer.
2588 //
2589
2590 if (isptrptr) {
2591 branch->SetAddress(addr);
2592 } else {
2593 branch->SetObject(addr);
2594 }
2595
2596 if (delobj) {
2597 cl->Destructor(objptr);
2598 objptr = nullptr;
2599 }
2600
2601 return branch;
2602}
2603
2604////////////////////////////////////////////////////////////////////////////////
2605/// Browse content of the TTree.
2608{
2610 if (fUserInfo) {
2611 if (strcmp("TList",fUserInfo->GetName())==0) {
2612 fUserInfo->SetName("UserInfo");
2613 b->Add(fUserInfo);
2614 fUserInfo->SetName("TList");
2615 } else {
2616 b->Add(fUserInfo);
2617 }
2618 }
2619}
2620
2621////////////////////////////////////////////////////////////////////////////////
2622/// Build a Tree Index (default is TTreeIndex).
2623/// See a description of the parameters and functionality in
2624/// TTreeIndex::TTreeIndex().
2625///
2626/// The return value is the number of entries in the Index (< 0 indicates failure).
2627///
2628/// A TTreeIndex object pointed by fTreeIndex is created.
2629/// This object will be automatically deleted by the TTree destructor.
2630/// If an index is already existing, this is replaced by the new one without being
2631/// deleted. This behaviour prevents the deletion of a previously external index
2632/// assigned to the TTree via the TTree::SetTreeIndex() method.
2633/// \see TTree::SetTreeIndex()
2635Int_t TTree::BuildIndex(const char* majorname, const char* minorname /* = "0" */)
2636{
2638 if (fTreeIndex->IsZombie()) {
2639 delete fTreeIndex;
2640 fTreeIndex = nullptr;
2641 return 0;
2642 }
2643 return fTreeIndex->GetN();
2644}
2645
2646////////////////////////////////////////////////////////////////////////////////
2647/// Build StreamerInfo for class cl.
2648/// pointer is an optional argument that may contain a pointer to an object of cl.
2650TStreamerInfo* TTree::BuildStreamerInfo(TClass* cl, void* pointer /* = 0 */, bool canOptimize /* = true */ )
2651{
2652 if (!cl) {
2653 return nullptr;
2654 }
2655 cl->BuildRealData(pointer);
2657
2658 // Create StreamerInfo for all base classes.
2659 TBaseClass* base = nullptr;
2660 TIter nextb(cl->GetListOfBases());
2661 while((base = (TBaseClass*) nextb())) {
2662 if (base->IsSTLContainer()) {
2663 continue;
2664 }
2665 TClass* clm = TClass::GetClass(base->GetName());
2667 }
2668 if (sinfo && fDirectory) {
2669 sinfo->ForceWriteInfo(fDirectory->GetFile());
2670 }
2671 return sinfo;
2672}
2673
2674////////////////////////////////////////////////////////////////////////////////
2675/// Enable the TTreeCache unless explicitly disabled for this TTree by
2676/// a prior call to `SetCacheSize(0)`.
2677/// If the environment variable `ROOT_TTREECACHE_SIZE` or the rootrc config
2678/// `TTreeCache.Size` has been set to zero, this call will over-ride them with
2679/// a value of 1.0 (i.e. use a cache size to hold 1 cluster)
2680///
2681/// Return true if there is a cache attached to the `TTree` (either pre-exisiting
2682/// or created as part of this call)
2683bool TTree::EnableCache()
2684{
2685 TFile* file = GetCurrentFile();
2686 if (!file)
2687 return false;
2688 // Check for an existing cache
2689 TTreeCache* pf = GetReadCache(file);
2690 if (pf)
2691 return true;
2692 if (fCacheUserSet && fCacheSize == 0)
2693 return false;
2694 return (0 == SetCacheSizeAux(true, -1));
2695}
2696
2697////////////////////////////////////////////////////////////////////////////////
2698/// Called by TTree::Fill() when file has reached its maximum fgMaxTreeSize.
2699/// Create a new file. If the original file is named "myfile.root",
2700/// subsequent files are named "myfile_1.root", "myfile_2.root", etc.
2701///
2702/// Returns a pointer to the new file.
2703///
2704/// Currently, the automatic change of file is restricted
2705/// to the case where the tree is in the top level directory.
2706/// The file should not contain sub-directories.
2707///
2708/// Before switching to a new file, the tree header is written
2709/// to the current file, then the current file is closed.
2710///
2711/// To process the multiple files created by ChangeFile, one must use
2712/// a TChain.
2713///
2714/// The new file name has a suffix "_N" where N is equal to fFileNumber+1.
2715/// By default a Root session starts with fFileNumber=0. One can set
2716/// fFileNumber to a different value via TTree::SetFileNumber.
2717/// In case a file named "_N" already exists, the function will try
2718/// a file named "__N", then "___N", etc.
2719///
2720/// fgMaxTreeSize can be set via the static function TTree::SetMaxTreeSize.
2721/// The default value of fgMaxTreeSize is 100 Gigabytes.
2722///
2723/// If the current file contains other objects like TH1 and TTree,
2724/// these objects are automatically moved to the new file.
2725///
2726/// \warning Be careful when writing the final Tree header to the file!
2727/// Don't do:
2728/// ~~~ {.cpp}
2729/// TFile *file = new TFile("myfile.root","recreate");
2730/// TTree *T = new TTree("T","title");
2731/// T->Fill(); // Loop
2732/// file->Write();
2733/// file->Close();
2734/// ~~~
2735/// \warning but do the following:
2736/// ~~~ {.cpp}
2737/// TFile *file = new TFile("myfile.root","recreate");
2738/// TTree *T = new TTree("T","title");
2739/// T->Fill(); // Loop
2740/// file = T->GetCurrentFile(); // To get the pointer to the current file
2741/// file->Write();
2742/// file->Close();
2743/// ~~~
2744///
2745/// \note This method is never called if the input file is a `TMemFile` or derivate.
2748{
2749 // Changing file clashes with the design of TMemFile and derivates, see #6523,
2750 // as well as with TFileMerger operations, see #6640.
2751 if ((dynamic_cast<TMemFile *>(file)) || file->TestBit(TFile::kCancelTTreeChangeRequest))
2752 return file;
2753 file->cd();
2754 Write();
2755 Reset();
2756 constexpr auto kBufSize = 2000;
2757 char* fname = new char[kBufSize];
2758 ++fFileNumber;
2759 char uscore[10];
2760 for (Int_t i = 0; i < 10; ++i) {
2761 uscore[i] = 0;
2762 }
2763 Int_t nus = 0;
2764 // Try to find a suitable file name that does not already exist.
2765 while (nus < 10) {
2766 uscore[nus] = '_';
2767 fname[0] = 0;
2768 strlcpy(fname, file->GetName(), kBufSize);
2769
2770 if (fFileNumber > 1) {
2771 char* cunder = strrchr(fname, '_');
2772 if (cunder) {
2774 const char* cdot = strrchr(file->GetName(), '.');
2775 if (cdot) {
2777 }
2778 } else {
2779 char fcount[21];
2780 snprintf(fcount,21, "%s%d", uscore, fFileNumber);
2782 }
2783 } else {
2784 char* cdot = strrchr(fname, '.');
2785 if (cdot) {
2787 strlcat(fname, strrchr(file->GetName(), '.'), kBufSize);
2788 } else {
2789 char fcount[21];
2790 snprintf(fcount,21, "%s%d", uscore, fFileNumber);
2792 }
2793 }
2795 break;
2796 }
2797 ++nus;
2798 Warning("ChangeFile", "file %s already exists, trying with %d underscores", fname, nus + 1);
2799 }
2801 TFile* newfile = TFile::Open(fname, "recreate", "chain files", compress);
2802 if (newfile == nullptr) {
2803 Error("Fill","Failed to open new file %s, continuing as a memory tree.",fname);
2804 } else {
2805 Printf("Fill: Switching to new file: %s", fname);
2806 }
2807 // The current directory may contain histograms and trees.
2808 // These objects must be moved to the new file.
2809 TBranch* branch = nullptr;
2810 TObject* obj = nullptr;
2811 while ((obj = file->GetList()->First())) {
2812 file->Remove(obj);
2813 // Histogram: just change the directory.
2814 if (obj->InheritsFrom("TH1")) {
2815 gROOT->ProcessLine(TString::Format("((%s*)0x%zx)->SetDirectory((TDirectory*)0x%zx);", obj->ClassName(), (size_t) obj, (size_t) newfile));
2816 continue;
2817 }
2818 // Tree: must save all trees in the old file, reset them.
2819 if (obj->InheritsFrom(TTree::Class())) {
2820 TTree* t = (TTree*) obj;
2821 if (t != this) {
2822 t->AutoSave();
2823 t->Reset();
2825 }
2828 while ((branch = (TBranch*)nextb())) {
2829 branch->SetFile(newfile);
2830 }
2831 if (t->GetBranchRef()) {
2832 t->GetBranchRef()->SetFile(newfile);
2833 }
2834 continue;
2835 }
2836 // Not a TH1 or a TTree, move object to new file.
2837 if (newfile) newfile->Append(obj);
2838 file->Remove(obj);
2839 }
2840 file->TObject::Delete();
2841 file = nullptr;
2842 delete[] fname;
2843 fname = nullptr;
2844 return newfile;
2845}
2846
2847////////////////////////////////////////////////////////////////////////////////
2848/// Check whether or not the address described by the last 3 parameters
2849/// matches the content of the branch. If a Data Model Evolution conversion
2850/// is involved, reset the fInfo of the branch.
2851/// The return values are:
2852//
2853/// - kMissingBranch (-5) : Missing branch
2854/// - kInternalError (-4) : Internal error (could not find the type corresponding to a data type number)
2855/// - kMissingCompiledCollectionProxy (-3) : Missing compiled collection proxy for a compiled collection
2856/// - kMismatch (-2) : Non-Class Pointer type given does not match the type expected by the branch
2857/// - kClassMismatch (-1) : Class Pointer type given does not match the type expected by the branch
2858/// - kMatch (0) : perfect match
2859/// - kMatchConversion (1) : match with (I/O) conversion
2860/// - kMatchConversionCollection (2) : match with (I/O) conversion of the content of a collection
2861/// - kMakeClass (3) : MakeClass mode so we can not check.
2862/// - kVoidPtr (4) : void* passed so no check was made.
2863/// - kNoCheck (5) : Underlying TBranch not yet available so no check was made.
2864/// In addition this can be multiplexed with the two bits:
2865/// - kNeedEnableDecomposedObj : in order for the address (type) to be 'usable' the branch needs to be in Decomposed Object (aka MakeClass) mode.
2866/// - kNeedDisableDecomposedObj : in order for the address (type) to be 'usable' the branch needs to not be in Decomposed Object (aka MakeClass) mode.
2867/// This bits can be masked out by using kDecomposedObjMask
2870{
2871 if (GetMakeClass()) {
2872 // If we are in MakeClass mode so we do not really use classes.
2873 return kMakeClass;
2874 }
2875
2876 // Let's determine what we need!
2877 TClass* expectedClass = nullptr;
2879 if (0 != branch->GetExpectedType(expectedClass,expectedType) ) {
2880 // Something went wrong, the warning message has already been issued.
2881 return kInternalError;
2882 }
2883 bool isBranchElement = branch->InheritsFrom( TBranchElement::Class() );
2884 if (expectedClass && datatype == kOther_t && ptrClass == nullptr) {
2885 if (isBranchElement) {
2887 bEl->SetTargetClass( expectedClass->GetName() );
2888 }
2889 if (expectedClass && expectedClass->GetCollectionProxy() && dynamic_cast<TEmulatedCollectionProxy*>(expectedClass->GetCollectionProxy())) {
2890 Error("SetBranchAddress", "Unable to determine the type given for the address for \"%s\". "
2891 "The class expected (%s) refers to an stl collection and do not have a compiled CollectionProxy. "
2892 "Please generate the dictionary for this class (%s)",
2893 branch->GetName(), expectedClass->GetName(), expectedClass->GetName());
2895 }
2896 if (!expectedClass->IsLoaded()) {
2897 // The originally expected class does not have a dictionary, it is then plausible that the pointer being passed is the right type
2898 // (we really don't know). So let's express that.
2899 Error("SetBranchAddress", "Unable to determine the type given for the address for \"%s\". "
2900 "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."
2901 "Please generate the dictionary for this class (%s)",
2902 branch->GetName(), expectedClass->GetName(), expectedClass->GetName());
2903 } else {
2904 Error("SetBranchAddress", "Unable to determine the type given for the address for \"%s\". "
2905 "This is probably due to a missing dictionary, the original data class for this branch is %s.", branch->GetName(), expectedClass->GetName());
2906 }
2907 return kClassMismatch;
2908 }
2909 if (expectedClass && ptrClass && (branch->GetMother() == branch)) {
2910 // Top Level branch
2911 if (!isptr) {
2912 Error("SetBranchAddress", "The address for \"%s\" should be the address of a pointer!", branch->GetName());
2913 }
2914 }
2915 if (expectedType == kFloat16_t) {
2917 }
2918 if (expectedType == kDouble32_t) {
2920 }
2921 if (datatype == kFloat16_t) {
2923 }
2924 if (datatype == kDouble32_t) {
2926 }
2927
2928 /////////////////////////////////////////////////////////////////////////////
2929 // Deal with the class renaming
2930 /////////////////////////////////////////////////////////////////////////////
2931
2932 if( expectedClass && ptrClass &&
2935 ptrClass->GetSchemaRules() &&
2936 ptrClass->GetSchemaRules()->HasRuleWithSourceClass( expectedClass->GetName() ) ) {
2938
2939 if ( ptrClass->GetCollectionProxy() && expectedClass->GetCollectionProxy() ) {
2940 if (gDebug > 7)
2941 Info("SetBranchAddress", "Matching STL collection (at least according to the SchemaRuleSet when "
2942 "reading a %s into a %s",expectedClass->GetName(),ptrClass->GetName());
2943
2944 bEl->SetTargetClass( ptrClass->GetName() );
2945 return kMatchConversion;
2946
2947 } else if ( !ptrClass->GetConversionStreamerInfo( expectedClass, bEl->GetClassVersion() ) &&
2948 !ptrClass->FindConversionStreamerInfo( expectedClass, bEl->GetCheckSum() ) ) {
2949 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());
2950
2951 bEl->SetTargetClass( expectedClass->GetName() );
2952 return kClassMismatch;
2953 }
2954 else {
2955
2956 bEl->SetTargetClass( ptrClass->GetName() );
2957 return kMatchConversion;
2958 }
2959
2960 } else if (expectedClass && ptrClass && !expectedClass->InheritsFrom(ptrClass)) {
2961
2962 if (expectedClass->GetCollectionProxy() && ptrClass->GetCollectionProxy() &&
2964 expectedClass->GetCollectionProxy()->GetValueClass() &&
2965 ptrClass->GetCollectionProxy()->GetValueClass() )
2966 {
2967 // In case of collection, we know how to convert them, if we know how to convert their content.
2968 // NOTE: we need to extend this to std::pair ...
2969
2970 TClass *onfileValueClass = expectedClass->GetCollectionProxy()->GetValueClass();
2971 TClass *inmemValueClass = ptrClass->GetCollectionProxy()->GetValueClass();
2972
2973 if (inmemValueClass->GetSchemaRules() &&
2974 inmemValueClass->GetSchemaRules()->HasRuleWithSourceClass(onfileValueClass->GetName() ) )
2975 {
2977 bEl->SetTargetClass( ptrClass->GetName() );
2979 }
2980 }
2981
2982 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());
2983 if (isBranchElement) {
2985 bEl->SetTargetClass( expectedClass->GetName() );
2986 }
2987 return kClassMismatch;
2988
2989 } else if ((expectedType != kOther_t) && (datatype != kOther_t) && (expectedType != kNoType_t) && (datatype != kNoType_t) && (expectedType != datatype)) {
2990 if (datatype != kChar_t) {
2991 // For backward compatibility we assume that (char*) was just a cast and/or a generic address
2992 Error("SetBranchAddress", "The pointer type given \"%s\" (%d) does not correspond to the type needed \"%s\" (%d) by the branch: %s",
2994 return kMismatch;
2995 }
2996 } else if ((expectedClass && (datatype != kOther_t && datatype != kNoType_t && datatype != kInt_t)) ||
2998 // Sometime a null pointer can look an int, avoid complaining in that case.
2999 if (expectedClass) {
3000 Error("SetBranchAddress", "The pointer type given \"%s\" (%d) does not correspond to the type needed \"%s\" by the branch: %s",
3001 TDataType::GetTypeName(datatype), datatype, expectedClass->GetName(), branch->GetName());
3002 if (isBranchElement) {
3004 bEl->SetTargetClass( expectedClass->GetName() );
3005 }
3006 } else {
3007 // 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
3008 // a struct).
3009 bool found = false;
3010 if (ptrClass->IsLoaded()) {
3011 TIter next(ptrClass->GetListOfRealData());
3012 TRealData *rdm;
3013 while ((rdm = (TRealData*)next())) {
3014 if (rdm->GetThisOffset() == 0) {
3015 TDataType *dmtype = rdm->GetDataMember()->GetDataType();
3016 if (dmtype) {
3017 EDataType etype = (EDataType)dmtype->GetType();
3018 if (etype == expectedType) {
3019 found = true;
3020 }
3021 }
3022 break;
3023 }
3024 }
3025 } else {
3026 TIter next(ptrClass->GetListOfDataMembers());
3027 TDataMember *dm;
3028 while ((dm = (TDataMember*)next())) {
3029 if (dm->GetOffset() == 0) {
3030 TDataType *dmtype = dm->GetDataType();
3031 if (dmtype) {
3032 EDataType etype = (EDataType)dmtype->GetType();
3033 if (etype == expectedType) {
3034 found = true;
3035 }
3036 }
3037 break;
3038 }
3039 }
3040 }
3041 if (found) {
3042 // let's check the size.
3043 TLeaf *last = (TLeaf*)branch->GetListOfLeaves()->Last();
3044 long len = last->GetOffset() + last->GetLenType() * last->GetLen();
3045 if (len <= ptrClass->Size()) {
3046 return kMatch;
3047 }
3048 }
3049 Error("SetBranchAddress", "The pointer type given \"%s\" does not correspond to the type needed \"%s\" (%d) by the branch: %s",
3051 }
3052 return kMismatch;
3053 }
3054 if (expectedClass && expectedClass->GetCollectionProxy() && dynamic_cast<TEmulatedCollectionProxy*>(expectedClass->GetCollectionProxy())) {
3055 Error("SetBranchAddress", writeStlWithoutProxyMsg,
3056 expectedClass->GetName(), branch->GetName(), expectedClass->GetName());
3057 if (isBranchElement) {
3059 bEl->SetTargetClass( expectedClass->GetName() );
3060 }
3062 }
3063 if (isBranchElement) {
3064 if (expectedClass) {
3066 bEl->SetTargetClass( expectedClass->GetName() );
3067 } else if (expectedType != kNoType_t && expectedType != kOther_t) {
3069 }
3070 }
3071 return kMatch;
3072}
3073
3074////////////////////////////////////////////////////////////////////////////////
3075/// Create a clone of this tree and copy nentries.
3076///
3077/// By default copy all entries.
3078/// The compression level of the cloned tree is set to the destination
3079/// file's compression level.
3080///
3081/// NOTE: Only active branches are copied. See TTree::SetBranchStatus for more
3082/// information and usage regarding the (de)activation of branches. More
3083/// examples are provided in the tutorials listed below.
3084///
3085/// NOTE: If the TTree is a TChain, the structure of the first TTree
3086/// is used for the copy.
3087///
3088/// IMPORTANT: The cloned tree stays connected with this tree until
3089/// this tree is deleted. In particular, any changes in
3090/// branch addresses in this tree are forwarded to the
3091/// clone trees, unless a branch in a clone tree has had
3092/// its address changed, in which case that change stays in
3093/// effect. When this tree is deleted, all the addresses of
3094/// the cloned tree are reset to their default values.
3095///
3096/// If 'option' contains the word 'fast' and nentries is -1, the
3097/// cloning will be done without unzipping or unstreaming the baskets
3098/// (i.e., a direct copy of the raw bytes on disk).
3099///
3100/// When 'fast' is specified, 'option' can also contain a sorting
3101/// order for the baskets in the output file.
3102///
3103/// There are currently 3 supported sorting order:
3104///
3105/// - SortBasketsByOffset (the default)
3106/// - SortBasketsByBranch
3107/// - SortBasketsByEntry
3108///
3109/// When using SortBasketsByOffset the baskets are written in the
3110/// output file in the same order as in the original file (i.e. the
3111/// baskets are sorted by their offset in the original file; Usually
3112/// this also means that the baskets are sorted by the index/number of
3113/// the _last_ entry they contain)
3114///
3115/// When using SortBasketsByBranch all the baskets of each individual
3116/// branches are stored contiguously. This tends to optimize reading
3117/// speed when reading a small number (1->5) of branches, since all
3118/// their baskets will be clustered together instead of being spread
3119/// across the file. However it might decrease the performance when
3120/// reading more branches (or the full entry).
3121///
3122/// When using SortBasketsByEntry the baskets with the lowest starting
3123/// entry are written first. (i.e. the baskets are sorted by the
3124/// index/number of the first entry they contain). This means that on
3125/// the file the baskets will be in the order in which they will be
3126/// needed when reading the whole tree sequentially.
3127///
3128/// For examples of CloneTree, see tutorials:
3129///
3130/// - copytree.C:
3131/// A macro to copy a subset of a TTree to a new TTree.
3132/// The input file has been generated by the program in
3133/// $ROOTSYS/test/Event with: Event 1000 1 1 1
3134///
3135/// - copytree2.C:
3136/// A macro to copy a subset of a TTree to a new TTree.
3137/// One branch of the new Tree is written to a separate file.
3138/// The input file has been generated by the program in
3139/// $ROOTSYS/test/Event with: Event 1000 1 1 1
3141TTree* TTree::CloneTree(Long64_t nentries /* = -1 */, Option_t* option /* = "" */)
3142{
3143 // Options
3144 bool fastClone = false;
3145
3146 TString opt = option;
3147 opt.ToLower();
3148 if (opt.Contains("fast")) {
3149 fastClone = true;
3150 }
3151
3152 // If we are a chain, switch to the first tree.
3153 if (fEntries > 0) {
3154 const auto res = LoadTree(0);
3155 if (res < -2 || res == -1) {
3156 // -1 is not accepted, it happens when no trees were defined
3157 // -2 is the only acceptable error, when the chain has zero entries, but tree(s) were defined
3158 // Other errors (-3, ...) are not accepted
3159 Error("CloneTree", "returning nullptr since LoadTree failed with code %lld.", res);
3160 return nullptr;
3161 }
3162 }
3163
3164 // Note: For a tree we get the this pointer, for
3165 // a chain we get the chain's current tree.
3166 TTree* thistree = GetTree();
3167
3168 // We will use this to override the IO features on the cloned branches.
3170 ;
3171
3172 // Note: For a chain, the returned clone will be
3173 // a clone of the chain's first tree.
3174 TTree* newtree = (TTree*) thistree->Clone();
3175 if (!newtree) {
3176 return nullptr;
3177 }
3178
3179 // The clone should not delete any objects allocated by SetAddress().
3180 TObjArray* branches = newtree->GetListOfBranches();
3181 Int_t nb = branches->GetEntriesFast();
3182 for (Int_t i = 0; i < nb; ++i) {
3183 TBranch* br = (TBranch*) branches->UncheckedAt(i);
3184 if (br->InheritsFrom(TBranchElement::Class())) {
3185 ((TBranchElement*) br)->ResetDeleteObject();
3186 }
3187 }
3188
3189 // Add the new tree to the list of clones so that
3190 // we can later inform it of changes to branch addresses.
3191 thistree->AddClone(newtree);
3192 if (thistree != this) {
3193 // In case this object is a TChain, add the clone
3194 // also to the TChain's list of clones.
3196 }
3197
3198 newtree->Reset();
3199
3200 TDirectory* ndir = newtree->GetDirectory();
3201 TFile* nfile = nullptr;
3202 if (ndir) {
3203 nfile = ndir->GetFile();
3204 }
3205 Int_t newcomp = -1;
3206 if (nfile) {
3207 newcomp = nfile->GetCompressionSettings();
3208 }
3209
3210 //
3211 // Delete non-active branches from the clone.
3212 //
3213 // Note: If we are a chain, this does nothing
3214 // since chains have no leaves.
3215 TObjArray* leaves = newtree->GetListOfLeaves();
3216 Int_t nleaves = leaves->GetEntriesFast();
3217 for (Int_t lndx = 0; lndx < nleaves; ++lndx) {
3218 TLeaf* leaf = (TLeaf*) leaves->UncheckedAt(lndx);
3219 if (!leaf) {
3220 continue;
3221 }
3222 TBranch* branch = leaf->GetBranch();
3223 if (branch && (newcomp > -1)) {
3224 branch->SetCompressionSettings(newcomp);
3225 }
3226 if (branch) branch->SetIOFeatures(features);
3227 if (!branch || !branch->TestBit(kDoNotProcess)) {
3228 continue;
3229 }
3230 // size might change at each iteration of the loop over the leaves.
3231 nb = branches->GetEntriesFast();
3232 for (Long64_t i = 0; i < nb; ++i) {
3233 TBranch* br = (TBranch*) branches->UncheckedAt(i);
3234 if (br == branch) {
3235 branches->RemoveAt(i);
3236 delete br;
3237 br = nullptr;
3238 branches->Compress();
3239 break;
3240 }
3241 TObjArray* lb = br->GetListOfBranches();
3242 Int_t nb1 = lb->GetEntriesFast();
3243 for (Int_t j = 0; j < nb1; ++j) {
3244 TBranch* b1 = (TBranch*) lb->UncheckedAt(j);
3245 if (!b1) {
3246 continue;
3247 }
3248 if (b1 == branch) {
3249 lb->RemoveAt(j);
3250 delete b1;
3251 b1 = nullptr;
3252 lb->Compress();
3253 break;
3254 }
3256 Int_t nb2 = lb1->GetEntriesFast();
3257 for (Int_t k = 0; k < nb2; ++k) {
3258 TBranch* b2 = (TBranch*) lb1->UncheckedAt(k);
3259 if (!b2) {
3260 continue;
3261 }
3262 if (b2 == branch) {
3263 lb1->RemoveAt(k);
3264 delete b2;
3265 b2 = nullptr;
3266 lb1->Compress();
3267 break;
3268 }
3269 }
3270 }
3271 }
3272 }
3273 leaves->Compress();
3274
3275 // Copy MakeClass status.
3276 newtree->SetMakeClass(fMakeClass);
3277
3278 // Copy branch addresses.
3280
3281 //
3282 // Copy entries if requested.
3283 //
3284
3285 if (nentries != 0) {
3286 if (fastClone && (nentries < 0)) {
3287 if ( newtree->CopyEntries( this, -1, option, false ) < 0 ) {
3288 // There was a problem!
3289 Error("CloneTTree", "TTree has not been cloned\n");
3290 delete newtree;
3291 newtree = nullptr;
3292 return nullptr;
3293 }
3294 } else {
3295 newtree->CopyEntries( this, nentries, option, false );
3296 }
3297 }
3298
3299 return newtree;
3300}
3301
3302////////////////////////////////////////////////////////////////////////////////
3303/// Set branch addresses of passed tree equal to ours.
3304/// If undo is true, reset the branch addresses instead of copying them.
3305/// This ensures 'separation' of a cloned tree from its original.
3307void TTree::CopyAddresses(TTree* tree, bool undo)
3308{
3309 // Copy branch addresses starting from branches.
3311 Int_t nbranches = branches->GetEntriesFast();
3312 for (Int_t i = 0; i < nbranches; ++i) {
3313 TBranch* branch = (TBranch*) branches->UncheckedAt(i);
3314 if (branch->TestBit(kDoNotProcess)) {
3315 continue;
3316 }
3317 if (undo) {
3318 TBranch* br = tree->GetBranch(branch->GetName());
3319 tree->ResetBranchAddress(br);
3320 } else {
3321 char* addr = branch->GetAddress();
3322 if (!addr) {
3323 if (branch->IsA() == TBranch::Class()) {
3324 // If the branch was created using a leaflist, the branch itself may not have
3325 // an address but the leaf might already.
3326 TLeaf *firstleaf = (TLeaf*)branch->GetListOfLeaves()->At(0);
3327 if (!firstleaf || firstleaf->GetValuePointer()) {
3328 // Either there is no leaf (and thus no point in copying the address)
3329 // or the leaf has an address but we can not copy it via the branche
3330 // this will be copied via the next loop (over the leaf).
3331 continue;
3332 }
3333 }
3334 // Note: This may cause an object to be allocated.
3335 branch->SetAddress(nullptr);
3336 addr = branch->GetAddress();
3337 }
3338 TBranch* br = tree->GetBranch(branch->GetFullName());
3339 if (br) {
3340 if (br->GetMakeClass() != branch->GetMakeClass())
3341 br->SetMakeClass(branch->GetMakeClass());
3342 br->SetAddress(addr);
3343 // The copy does not own any object allocated by SetAddress().
3344 if (br->InheritsFrom(TBranchElement::Class())) {
3345 ((TBranchElement*) br)->ResetDeleteObject();
3346 }
3347 } else {
3348 Warning("CopyAddresses", "Could not find branch named '%s' in tree named '%s'", branch->GetName(), tree->GetName());
3349 }
3350 }
3351 }
3352
3353 // Copy branch addresses starting from leaves.
3354 TObjArray* tleaves = tree->GetListOfLeaves();
3355 Int_t ntleaves = tleaves->GetEntriesFast();
3356 std::set<TLeaf*> updatedLeafCount;
3357 for (Int_t i = 0; i < ntleaves; ++i) {
3358 TLeaf* tleaf = (TLeaf*) tleaves->UncheckedAt(i);
3359 TBranch* tbranch = tleaf->GetBranch();
3360 TBranch* branch = GetBranch(tbranch->GetName());
3361 if (!branch) {
3362 continue;
3363 }
3364 TLeaf* leaf = branch->GetLeaf(tleaf->GetName());
3365 if (!leaf) {
3366 continue;
3367 }
3368 if (branch->TestBit(kDoNotProcess)) {
3369 continue;
3370 }
3371 if (undo) {
3372 // Now we know whether the address has been transfered
3373 tree->ResetBranchAddress(tbranch);
3374 } else {
3375 TBranchElement *mother = dynamic_cast<TBranchElement*>(leaf->GetBranch()->GetMother());
3376 bool needAddressReset = false;
3377 if (leaf->GetLeafCount() && (leaf->TestBit(TLeaf::kNewValue) || !leaf->GetValuePointer() || (mother && mother->IsObjectOwner())) && tleaf->GetLeafCount())
3378 {
3379 // If it is an array and it was allocated by the leaf itself,
3380 // let's make sure it is large enough for the incoming data.
3381 if (leaf->GetLeafCount()->GetMaximum() < tleaf->GetLeafCount()->GetMaximum()) {
3382 leaf->GetLeafCount()->IncludeRange( tleaf->GetLeafCount() );
3383 updatedLeafCount.insert(leaf->GetLeafCount());
3384 needAddressReset = true;
3385 } else {
3386 needAddressReset = (updatedLeafCount.find(leaf->GetLeafCount()) != updatedLeafCount.end());
3387 }
3388 }
3389 if (needAddressReset && leaf->GetValuePointer()) {
3390 if (leaf->IsA() == TLeafElement::Class() && mother)
3391 mother->ResetAddress();
3392 else
3393 leaf->SetAddress(nullptr);
3394 }
3395 if (!branch->GetAddress() && !leaf->GetValuePointer()) {
3396 // We should attempts to set the address of the branch.
3397 // something like:
3398 //(TBranchElement*)branch->GetMother()->SetAddress(0)
3399 //plus a few more subtleties (see TBranchElement::GetEntry).
3400 //but for now we go the simplest route:
3401 //
3402 // Note: This may result in the allocation of an object.
3403 branch->SetupAddresses();
3404 }
3405 if (branch->GetAddress()) {
3406 tree->SetBranchAddress(branch->GetName(), (void*) branch->GetAddress());
3407 TBranch* br = tree->GetBranch(branch->GetName());
3408 if (br) {
3409 if (br->IsA() != branch->IsA()) {
3410 Error(
3411 "CopyAddresses",
3412 "Branch kind mismatch between input tree '%s' and output tree '%s' for branch '%s': '%s' vs '%s'",
3413 tree->GetName(), br->GetTree()->GetName(), br->GetName(), branch->IsA()->GetName(),
3414 br->IsA()->GetName());
3415 }
3416 // The copy does not own any object allocated by SetAddress().
3417 // FIXME: We do too much here, br may not be a top-level branch.
3418 if (br->InheritsFrom(TBranchElement::Class())) {
3419 ((TBranchElement*) br)->ResetDeleteObject();
3420 }
3421 } else {
3422 Warning("CopyAddresses", "Could not find branch named '%s' in tree named '%s'", branch->GetName(), tree->GetName());
3423 }
3424 } else {
3425 tleaf->SetAddress(leaf->GetValuePointer());
3426 }
3427 }
3428 }
3429
3430 if (undo &&
3431 ( tree->IsA()->InheritsFrom("TNtuple") || tree->IsA()->InheritsFrom("TNtupleD") )
3432 ) {
3433 tree->ResetBranchAddresses();
3434 }
3435}
3436
3437namespace {
3438
3439 enum EOnIndexError { kDrop, kKeep, kBuild };
3440
3441 bool R__HandleIndex(EOnIndexError onIndexError, TTree *newtree, TTree *oldtree)
3442 {
3443 // Return true if we should continue to handle indices, false otherwise.
3444
3445 bool withIndex = true;
3446
3447 if ( newtree->GetTreeIndex() ) {
3448 if ( oldtree->GetTree()->GetTreeIndex() == nullptr ) {
3449 switch (onIndexError) {
3450 case kDrop:
3451 delete newtree->GetTreeIndex();
3452 newtree->SetTreeIndex(nullptr);
3453 withIndex = false;
3454 break;
3455 case kKeep:
3456 // Nothing to do really.
3457 break;
3458 case kBuild:
3459 // Build the index then copy it
3460 if (oldtree->GetTree()->BuildIndex(newtree->GetTreeIndex()->GetMajorName(), newtree->GetTreeIndex()->GetMinorName())) {
3461 newtree->GetTreeIndex()->Append(oldtree->GetTree()->GetTreeIndex(), true);
3462 // Clean up
3463 delete oldtree->GetTree()->GetTreeIndex();
3464 oldtree->GetTree()->SetTreeIndex(nullptr);
3465 }
3466 break;
3467 }
3468 } else {
3469 newtree->GetTreeIndex()->Append(oldtree->GetTree()->GetTreeIndex(), true);
3470 }
3471 } else if ( oldtree->GetTree()->GetTreeIndex() != nullptr ) {
3472 // We discover the first index in the middle of the chain.
3473 switch (onIndexError) {
3474 case kDrop:
3475 // Nothing to do really.
3476 break;
3477 case kKeep: {
3478 TVirtualIndex *index = (TVirtualIndex*) oldtree->GetTree()->GetTreeIndex()->Clone();
3479 index->SetTree(newtree);
3480 newtree->SetTreeIndex(index);
3481 break;
3482 }
3483 case kBuild:
3484 if (newtree->GetEntries() == 0) {
3485 // Start an index.
3486 TVirtualIndex *index = (TVirtualIndex*) oldtree->GetTree()->GetTreeIndex()->Clone();
3487 index->SetTree(newtree);
3488 newtree->SetTreeIndex(index);
3489 } else {
3490 // Build the index so far.
3491 if (newtree->BuildIndex(oldtree->GetTree()->GetTreeIndex()->GetMajorName(), oldtree->GetTree()->GetTreeIndex()->GetMinorName())) {
3492 newtree->GetTreeIndex()->Append(oldtree->GetTree()->GetTreeIndex(), true);
3493 }
3494 }
3495 break;
3496 }
3497 } else if ( onIndexError == kDrop ) {
3498 // There is no index on this or on tree->GetTree(), we know we have to ignore any further
3499 // index
3500 withIndex = false;
3501 }
3502 return withIndex;
3503 }
3504}
3505
3506////////////////////////////////////////////////////////////////////////////////
3507/// Copy nentries from given tree to this tree.
3508/// This routines assumes that the branches that intended to be copied are
3509/// already connected. The typical case is that this tree was created using
3510/// tree->CloneTree(0).
3511///
3512/// By default copy all entries.
3513///
3514/// Returns number of bytes copied to this tree.
3515///
3516/// If 'option' contains the word 'fast' and nentries is -1, the cloning will be
3517/// done without unzipping or unstreaming the baskets (i.e., a direct copy of the
3518/// raw bytes on disk).
3519///
3520/// When 'fast' is specified, 'option' can also contains a sorting order for the
3521/// baskets in the output file.
3522///
3523/// There are currently 3 supported sorting order:
3524///
3525/// - SortBasketsByOffset (the default)
3526/// - SortBasketsByBranch
3527/// - SortBasketsByEntry
3528///
3529/// See TTree::CloneTree for a detailed explanation of the semantics of these 3 options.
3530///
3531/// If the tree or any of the underlying tree of the chain has an index, that index and any
3532/// index in the subsequent underlying TTree objects will be merged.
3533///
3534/// There are currently three 'options' to control this merging:
3535/// - NoIndex : all the TTreeIndex object are dropped.
3536/// - DropIndexOnError : if any of the underlying TTree object do no have a TTreeIndex,
3537/// they are all dropped.
3538/// - AsIsIndexOnError [default]: In case of missing TTreeIndex, the resulting TTree index has gaps.
3539/// - BuildIndexOnError : If any of the underlying TTree objects do not have a TTreeIndex,
3540/// all TTreeIndex are 'ignored' and the missing piece are rebuilt.
3542Long64_t TTree::CopyEntries(TTree* tree, Long64_t nentries /* = -1 */, Option_t* option /* = "" */, bool needCopyAddresses /* = false */)
3543{
3544 if (!tree) {
3545 return 0;
3546 }
3547 // Options
3548 TString opt = option;
3549 opt.ToLower();
3550 bool fastClone = opt.Contains("fast");
3551 bool withIndex = !opt.Contains("noindex");
3552 EOnIndexError onIndexError;
3553 if (opt.Contains("asisindex")) {
3555 } else if (opt.Contains("buildindex")) {
3557 } else if (opt.Contains("dropindex")) {
3559 } else {
3561 }
3562 Ssiz_t cacheSizeLoc = opt.Index("cachesize=");
3563 Long64_t cacheSize = -1;
3565 // If the parse faile, cacheSize stays at -1.
3566 Ssiz_t cacheSizeEnd = opt.Index(" ",cacheSizeLoc+10) - (cacheSizeLoc+10);
3570 Warning("CopyEntries","The cachesize option can not be parsed: %s. The default size will be used.",cacheSizeStr.String().Data());
3572 double m;
3573 const char *munit = nullptr;
3574 ROOT::ToHumanReadableSize(std::numeric_limits<decltype(cacheSize)>::max(),false,&m,&munit);
3575
3576 Warning("CopyEntries","The cachesize option is too large: %s (%g%s max). The default size will be used.",cacheSizeStr.String().Data(),m,munit);
3577 }
3578 }
3579 if (gDebug > 0 && cacheSize != -1) Info("CopyEntries","Using Cache size: %lld\n",cacheSize);
3580
3581 Long64_t nbytes = 0;
3582 Long64_t treeEntries = tree->GetEntriesFast();
3583 if (nentries < 0) {
3585 } else if (nentries > treeEntries) {
3587 }
3588
3590 // Quickly copy the basket without decompression and streaming.
3592 for (Long64_t i = 0; i < nentries; i += tree->GetTree()->GetEntries()) {
3593 if (tree->LoadTree(i) < 0) {
3594 break;
3595 }
3596 if ( withIndex ) {
3597 withIndex = R__HandleIndex( onIndexError, this, tree );
3598 }
3599 if (this->GetDirectory()) {
3600 TFile* file2 = this->GetDirectory()->GetFile();
3601 if (file2 && (file2->GetEND() > TTree::GetMaxTreeSize())) {
3602 if (this->GetDirectory() == (TDirectory*) file2) {
3603 this->ChangeFile(file2);
3604 }
3605 }
3606 }
3607 TTreeCloner cloner(tree->GetTree(), this, option, TTreeCloner::kNoWarnings);
3608 if (cloner.IsValid()) {
3609 this->SetEntries(this->GetEntries() + tree->GetTree()->GetEntries());
3610 if (cacheSize != -1) cloner.SetCacheSize(cacheSize);
3611 cloner.Exec();
3612 } else {
3613 if (i == 0) {
3614 Warning("CopyEntries","%s",cloner.GetWarning());
3615 // If the first cloning does not work, something is really wrong
3616 // (since apriori the source and target are exactly the same structure!)
3617 return -1;
3618 } else {
3619 if (cloner.NeedConversion()) {
3620 TTree *localtree = tree->GetTree();
3621 Long64_t tentries = localtree->GetEntries();
3622 if (needCopyAddresses) {
3623 // Copy MakeClass status.
3624 tree->SetMakeClass(fMakeClass);
3625 // Copy branch addresses.
3626 CopyAddresses(tree);
3627 }
3628 for (Long64_t ii = 0; ii < tentries; ii++) {
3629 if (localtree->GetEntry(ii) <= 0) {
3630 break;
3631 }
3632 this->Fill();
3633 }
3634 if (needCopyAddresses)
3635 tree->ResetBranchAddresses();
3636 if (this->GetTreeIndex()) {
3637 this->GetTreeIndex()->Append(tree->GetTree()->GetTreeIndex(), true);
3638 }
3639 } else {
3640 Warning("CopyEntries","%s",cloner.GetWarning());
3641 if (tree->GetDirectory() && tree->GetDirectory()->GetFile()) {
3642 Warning("CopyEntries", "Skipped file %s\n", tree->GetDirectory()->GetFile()->GetName());
3643 } else {
3644 Warning("CopyEntries", "Skipped file number %d\n", tree->GetTreeNumber());
3645 }
3646 }
3647 }
3648 }
3649
3650 }
3651 if (this->GetTreeIndex()) {
3652 this->GetTreeIndex()->Append(nullptr,false); // Force the sorting
3653 }
3654 nbytes = GetTotBytes() - totbytes;
3655 } else {
3656 if (nentries < 0) {
3658 } else if (nentries > treeEntries) {
3660 }
3661 if (needCopyAddresses) {
3662 // Copy MakeClass status.
3663 tree->SetMakeClass(fMakeClass);
3664 // Copy branch addresses.
3665 CopyAddresses(tree);
3666 }
3667 Int_t treenumber = -1;
3668 for (Long64_t i = 0; i < nentries; i++) {
3669 if (tree->LoadTree(i) < 0) {
3670 break;
3671 }
3672 if (treenumber != tree->GetTreeNumber()) {
3673 if ( withIndex ) {
3674 withIndex = R__HandleIndex( onIndexError, this, tree );
3675 }
3676 treenumber = tree->GetTreeNumber();
3677 }
3678 if (tree->GetEntry(i) <= 0) {
3679 break;
3680 }
3681 nbytes += this->Fill();
3682 }
3683 if (needCopyAddresses)
3684 tree->ResetBranchAddresses();
3685 if (this->GetTreeIndex()) {
3686 this->GetTreeIndex()->Append(nullptr,false); // Force the sorting
3687 }
3688 }
3689 return nbytes;
3690}
3691
3692////////////////////////////////////////////////////////////////////////////////
3693/// Copy a tree with selection.
3694///
3695/// ### Important:
3696///
3697/// The returned copied tree stays connected with the original tree
3698/// until the original tree is deleted. In particular, any changes
3699/// to the branch addresses in the original tree are also made to
3700/// the copied tree. Any changes made to the branch addresses of the
3701/// copied tree are overridden anytime the original tree changes its
3702/// branch addresses. When the original tree is deleted, all the
3703/// branch addresses of the copied tree are set to zero.
3704///
3705/// For examples of CopyTree, see the tutorials:
3706///
3707/// - copytree.C:
3708/// Example macro to copy a subset of a tree to a new tree.
3709/// The input file was generated by running the program in
3710/// $ROOTSYS/test/Event in this way:
3711/// ~~~ {.cpp}
3712/// ./Event 1000 1 1 1
3713/// ~~~
3714/// - copytree2.C
3715/// Example macro to copy a subset of a tree to a new tree.
3716/// One branch of the new tree is written to a separate file.
3717/// The input file was generated by running the program in
3718/// $ROOTSYS/test/Event in this way:
3719/// ~~~ {.cpp}
3720/// ./Event 1000 1 1 1
3721/// ~~~
3722/// - copytree3.C
3723/// Example macro to copy a subset of a tree to a new tree.
3724/// Only selected entries are copied to the new tree.
3725/// NOTE that only the active branches are copied.
3727TTree* TTree::CopyTree(const char* selection, Option_t* option /* = 0 */, Long64_t nentries /* = TTree::kMaxEntries */, Long64_t firstentry /* = 0 */)
3728{
3729 GetPlayer();
3730 if (fPlayer) {
3732 }
3733 return nullptr;
3734}
3735
3736////////////////////////////////////////////////////////////////////////////////
3737/// Create a basket for this tree and given branch.
3740{
3741 if (!branch) {
3742 return nullptr;
3743 }
3744 return new TBasket(branch->GetName(), GetName(), branch);
3745}
3746
3747////////////////////////////////////////////////////////////////////////////////
3748/// Delete this tree from memory or/and disk.
3749///
3750/// - if option == "all" delete Tree object from memory AND from disk
3751/// all baskets on disk are deleted. All keys with same name
3752/// are deleted.
3753/// - if option =="" only Tree object in memory is deleted.
3755void TTree::Delete(Option_t* option /* = "" */)
3756{
3757 TFile *file = GetCurrentFile();
3758
3759 // delete all baskets and header from file
3760 if (file && option && !strcmp(option,"all")) {
3761 if (!file->IsWritable()) {
3762 Error("Delete","File : %s is not writable, cannot delete Tree:%s", file->GetName(),GetName());
3763 return;
3764 }
3765
3766 //find key and import Tree header in memory
3767 TKey *key = fDirectory->GetKey(GetName());
3768 if (!key) return;
3769
3771 file->cd();
3772
3773 //get list of leaves and loop on all the branches baskets
3774 TIter next(GetListOfLeaves());
3775 TLeaf *leaf;
3776 char header[16];
3777 Int_t ntot = 0;
3778 Int_t nbask = 0;
3780 while ((leaf = (TLeaf*)next())) {
3781 TBranch *branch = leaf->GetBranch();
3782 Int_t nbaskets = branch->GetMaxBaskets();
3783 for (Int_t i=0;i<nbaskets;i++) {
3784 Long64_t pos = branch->GetBasketSeek(i);
3785 if (!pos) continue;
3786 TFile *branchFile = branch->GetFile();
3787 if (!branchFile) continue;
3788 branchFile->GetRecordHeader(header,pos,16,nbytes,objlen,keylen);
3789 if (nbytes <= 0) continue;
3790 branchFile->MakeFree(pos,pos+nbytes-1);
3791 ntot += nbytes;
3792 nbask++;
3793 }
3794 }
3795
3796 // delete Tree header key and all keys with the same name
3797 // A Tree may have been saved many times. Previous cycles are invalid.
3798 while (key) {
3799 ntot += key->GetNbytes();
3800 key->Delete();
3801 delete key;
3802 key = fDirectory->GetKey(GetName());
3803 }
3804 if (dirsav) dirsav->cd();
3805 if (gDebug) Info("TTree::Delete", "Deleting Tree: %s: %d baskets deleted. Total space freed = %d bytes\n",GetName(),nbask,ntot);
3806 }
3807
3808 if (fDirectory) {
3809 fDirectory->Remove(this);
3810 //delete the file cache if it points to this Tree
3811 MoveReadCache(file,nullptr);
3812 fDirectory = nullptr;
3814 }
3815
3816 // Delete object from CINT symbol table so it can not be used anymore.
3817 gCling->DeleteGlobal(this);
3818
3819 // Warning: We have intentional invalidated this object while inside a member function!
3820 delete this;
3821}
3822
3823 ///////////////////////////////////////////////////////////////////////////////
3824 /// Called by TKey and TObject::Clone to automatically add us to a directory
3825 /// when we are read from a file.
3828{
3829 if (fDirectory == dir) return;
3830 if (fDirectory) {
3831 fDirectory->Remove(this);
3832 // Delete or move the file cache if it points to this Tree
3833 TFile *file = fDirectory->GetFile();
3834 MoveReadCache(file,dir);
3835 }
3836 fDirectory = dir;
3837 TBranch* b = nullptr;
3838 TIter next(GetListOfBranches());
3839 while((b = (TBranch*) next())) {
3840 b->UpdateFile();
3841 }
3842 if (fBranchRef) {
3844 }
3845 if (fDirectory) fDirectory->Append(this);
3846}
3847
3848////////////////////////////////////////////////////////////////////////////////
3849/// Draw expression varexp for specified entries.
3850///
3851/// \return -1 in case of error or number of selected events in case of success.
3852/// If `selection` involves an array variable `x[n]`, for example `x[] > 0` or
3853/// `x > 0`, then we return the number of selected instances rather than number of events.
3854/// In the output of `tree.Scan()`, instances are shown in individual printed rows, thus
3855/// each event (tree entry) is split across the various instances (lines) of the array.
3856/// In contrast, the function `GetEntries(selection)` always returns the number of entries selected.
3857///
3858/// This function accepts TCut objects as arguments.
3859/// Useful to use the string operator +
3860///
3861/// Example:
3862///
3863/// ~~~ {.cpp}
3864/// ntuple.Draw("x",cut1+cut2+cut3);
3865/// ~~~
3866
3871}
3872
3873/////////////////////////////////////////////////////////////////////////////////////////
3874/// \brief Draw expression varexp for entries and objects that pass a (optional) selection.
3875///
3876/// \return -1 in case of error or number of selected events in case of success.
3877/// If `selection` involves an array variable `x[n]`, for example `x[] > 0` or
3878/// `x > 0`, then we return the number of selected instances rather than number of events.
3879/// In the output of `tree.Scan()`, instances are shown in individual printed rows, thus
3880/// each event (tree entry) is split across the various instances (lines) of the array.
3881/// In contrast, the function `GetEntries(selection)` always returns the number of entries selected.
3882///
3883/// \param [in] varexp
3884/// \parblock
3885/// A string that takes one of these general forms:
3886/// - "e1" produces a 1-d histogram (TH1F) of expression "e1"
3887/// - "e1:e2" produces an unbinned 2-d scatter-plot (TGraph) of "e1"
3888/// on the y-axis versus "e2" on the x-axis
3889/// - "e1:e2:e3" produces an unbinned 3-d scatter-plot (TPolyMarker3D) of "e1"
3890/// vs "e2" vs "e3" on the z-, y-, x-axis, respectively
3891/// - "e1:e2:e3:e4" produces an unbinned 3-d scatter-plot (TPolyMarker3D) of "e1"
3892/// vs "e2" vs "e3" and "e4" mapped on the current color palette.
3893/// (to create histograms in the 2, 3, and 4 dimensional case,
3894/// see section "Saving the result of Draw to an histogram")
3895/// - "e1:e2:e3:e4:e5" with option "GL5D" produces a 5D plot using OpenGL. `gStyle->SetCanvasPreferGL(true)` is needed.
3896/// - Any number of variables no fewer than two can be used with the options "CANDLE" and "PARA"
3897/// - An arbitrary number of variables can be used with the option "GOFF"
3898///
3899/// Examples:
3900/// - "x": the simplest case, it draws a 1-Dim histogram of column x
3901/// - "sqrt(x)", "x*y/z": draw histogram with the values of the specified numerical expression across TTree events
3902/// - "y:sqrt(x)": 2-Dim histogram of y versus sqrt(x)
3903/// - "px:py:pz:2.5*E": produces a 3-d scatter-plot of px vs py ps pz
3904/// and the color number of each marker will be 2.5*E.
3905/// If the color number is negative it is set to 0.
3906/// If the color number is greater than the current number of colors
3907/// it is set to the highest color number. The default number of
3908/// colors is 50. See TStyle::SetPalette for setting a new color palette.
3909///
3910/// The expressions can use all the operations and built-in functions
3911/// supported by TFormula (see TFormula::Analyze()), including free
3912/// functions taking numerical arguments (e.g. TMath::Bessel()).
3913/// In addition, you can call member functions taking numerical
3914/// arguments. For example, these are two valid expressions:
3915/// ~~~ {.cpp}
3916/// TMath::BreitWigner(fPx,3,2)
3917/// event.GetHistogram()->GetXaxis()->GetXmax()
3918/// ~~~
3919/// \endparblock
3920/// \param [in] selection
3921/// \parblock
3922/// A string containing a selection expression.
3923/// In a selection all usual C++ mathematical and logical operators are allowed.
3924/// The value corresponding to the selection expression is used as a weight
3925/// to fill the histogram (a weight of 0 is equivalent to not filling the histogram).\n
3926/// \n
3927/// Examples:
3928/// - "x<y && sqrt(z)>3.2": returns a weight = 0 or 1
3929/// - "(x+y)*(sqrt(z)>3.2)": returns a weight = x+y if sqrt(z)>3.2, 0 otherwise\n
3930/// \n
3931/// If the selection expression returns an array, it is iterated over in sync with the
3932/// array returned by the varexp argument (as described below in "Drawing expressions using arrays and array
3933/// elements"). For example, if, for a given event, varexp evaluates to
3934/// `{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:
3935/// ~~~{.cpp}
3936/// // Muon_pt is an array: fill a histogram with the array elements > 100 in each event
3937/// tree->Draw('Muon_pt', 'Muon_pt > 100')
3938/// ~~~
3939/// \endparblock
3940/// \param [in] option
3941/// \parblock
3942/// The drawing option.
3943/// - When an histogram is produced it can be any histogram drawing option
3944/// listed in THistPainter.
3945/// - when no option is specified:
3946/// - the default histogram drawing option is used
3947/// if the expression is of the form "e1".
3948/// - if the expression is of the form "e1:e2"or "e1:e2:e3" a cloud of
3949/// unbinned 2D or 3D points is drawn respectively.
3950/// - if the expression has four fields "e1:e2:e3:e4" a cloud of unbinned 3D
3951/// points is produced with e1 vs e2 vs e3, and e4 is mapped on the current color
3952/// palette.
3953/// - If option COL is specified when varexp has three fields:
3954/// ~~~ {.cpp}
3955/// tree.Draw("e1:e2:e3","","col");
3956/// ~~~
3957/// a 2D scatter is produced with e1 vs e2, and e3 is mapped on the current
3958/// color palette. The colors for e3 are evaluated once in linear scale before
3959/// painting. Therefore changing the pad to log scale along Z as no effect
3960/// on the colors.
3961/// - if expression has more than four fields the option "PARA"or "CANDLE"
3962/// can be used.
3963/// - If option contains the string "goff", no graphics is generated.
3964/// \endparblock
3965/// \param [in] nentries The number of entries to process (default is all)
3966/// \param [in] firstentry The first entry to process (default is 0)
3967///
3968/// ### Drawing expressions using arrays and array elements
3969///
3970/// Let assumes, a leaf fMatrix, on the branch fEvent, which is a 3 by 3 array,
3971/// or a TClonesArray.
3972/// In a TTree::Draw expression you can now access fMatrix using the following
3973/// syntaxes:
3974///
3975/// | String passed | What is used for each entry of the tree
3976/// |-----------------|--------------------------------------------------------|
3977/// | `fMatrix` | the 9 elements of fMatrix |
3978/// | `fMatrix[][]` | the 9 elements of fMatrix |
3979/// | `fMatrix[2][2]` | only the elements fMatrix[2][2] |
3980/// | `fMatrix[1]` | the 3 elements fMatrix[1][0], fMatrix[1][1] and fMatrix[1][2] |
3981/// | `fMatrix[1][]` | the 3 elements fMatrix[1][0], fMatrix[1][1] and fMatrix[1][2] |
3982/// | `fMatrix[][0]` | the 3 elements fMatrix[0][0], fMatrix[1][0] and fMatrix[2][0] |
3983///
3984/// "fEvent.fMatrix...." same as "fMatrix..." (unless there is more than one leaf named fMatrix!).
3985///
3986/// In summary, if a specific index is not specified for a dimension, TTree::Draw
3987/// will loop through all the indices along this dimension. Leaving off the
3988/// last (right most) dimension of specifying then with the two characters '[]'
3989/// is equivalent. For variable size arrays (and TClonesArray) the range
3990/// of the first dimension is recalculated for each entry of the tree.
3991/// You can also specify the index as an expression of any other variables from the
3992/// tree.
3993///
3994/// TTree::Draw also now properly handling operations involving 2 or more arrays.
3995///
3996/// Let assume a second matrix fResults[5][2], here are a sample of some
3997/// of the possible combinations, the number of elements they produce and
3998/// the loop used:
3999///
4000/// | expression | element(s) | Loop |
4001/// |----------------------------------|------------|--------------------------|
4002/// | `fMatrix[2][1] - fResults[5][2]` | one | no loop |
4003/// | `fMatrix[2][] - fResults[5][2]` | three | on 2nd dim fMatrix |
4004/// | `fMatrix[2][] - fResults[5][]` | two | on both 2nd dimensions |
4005/// | `fMatrix[][2] - fResults[][1]` | three | on both 1st dimensions |
4006/// | `fMatrix[][2] - fResults[][]` | six | on both 1st and 2nd dimensions of fResults |
4007/// | `fMatrix[][2] - fResults[3][]` | two | on 1st dim of fMatrix and 2nd of fResults (at the same time) |
4008/// | `fMatrix[][] - fResults[][]` | six | on 1st dim then on 2nd dim |
4009/// | `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.|
4010///
4011///
4012/// In summary, TTree::Draw loops through all unspecified dimensions. To
4013/// figure out the range of each loop, we match each unspecified dimension
4014/// from left to right (ignoring ALL dimensions for which an index has been
4015/// specified), in the equivalent loop matched dimensions use the same index
4016/// and are restricted to the smallest range (of only the matched dimensions).
4017/// When involving variable arrays, the range can of course be different
4018/// for each entry of the tree.
4019///
4020/// So the loop equivalent to "fMatrix[][2] - fResults[3][]" is:
4021/// ~~~ {.cpp}
4022/// for (Int_t i0; i < min(3,2); i++) {
4023/// use the value of (fMatrix[i0][2] - fMatrix[3][i0])
4024/// }
4025/// ~~~
4026/// So the loop equivalent to "fMatrix[][2] - fResults[][]" is:
4027/// ~~~ {.cpp}
4028/// for (Int_t i0; i < min(3,5); i++) {
4029/// for (Int_t i1; i1 < 2; i1++) {
4030/// use the value of (fMatrix[i0][2] - fMatrix[i0][i1])
4031/// }
4032/// }
4033/// ~~~
4034/// So the loop equivalent to "fMatrix[][] - fResults[][]" is:
4035/// ~~~ {.cpp}
4036/// for (Int_t i0; i < min(3,5); i++) {
4037/// for (Int_t i1; i1 < min(3,2); i1++) {
4038/// use the value of (fMatrix[i0][i1] - fMatrix[i0][i1])
4039/// }
4040/// }
4041/// ~~~
4042/// So the loop equivalent to "fMatrix[][fResults[][]]" is:
4043/// ~~~ {.cpp}
4044/// for (Int_t i0; i0 < 3; i0++) {
4045/// for (Int_t j2; j2 < 5; j2++) {
4046/// for (Int_t j3; j3 < 2; j3++) {
4047/// i1 = fResults[j2][j3];
4048/// use the value of fMatrix[i0][i1]
4049/// }
4050/// }
4051/// ~~~
4052/// ### Retrieving the result of Draw
4053///
4054/// By default a temporary histogram called `htemp` is created. It will be:
4055///
4056/// - A TH1F* in case of a mono-dimensional distribution: `Draw("e1")`,
4057/// - A TH2F* in case of a bi-dimensional distribution: `Draw("e1:e2")`,
4058/// - A TH3F* in case of a three-dimensional distribution: `Draw("e1:e2:e3")`.
4059///
4060/// In the one dimensional case the `htemp` is filled and drawn whatever the drawing
4061/// option is.
4062///
4063/// In the two and three dimensional cases, with the default drawing option (`""`),
4064/// a cloud of points is drawn and the histogram `htemp` is not filled. For all the other
4065/// drawing options `htemp` will be filled.
4066///
4067/// In all cases `htemp` can be retrieved by calling:
4068///
4069/// ~~~ {.cpp}
4070/// auto htemp = (TH1F*)gPad->GetPrimitive("htemp"); // 1D
4071/// auto htemp = (TH2F*)gPad->GetPrimitive("htemp"); // 2D
4072/// auto htemp = (TH3F*)gPad->GetPrimitive("htemp"); // 3D
4073/// ~~~
4074///
4075/// In the two dimensional case (`Draw("e1;e2")`), with the default drawing option, the
4076/// data is filled into a TGraph named `Graph`. This TGraph can be retrieved by
4077/// calling
4078///
4079/// ~~~ {.cpp}
4080/// auto graph = (TGraph*)gPad->GetPrimitive("Graph");
4081/// ~~~
4082///
4083/// For the three and four dimensional cases, with the default drawing option, an unnamed
4084/// TPolyMarker3D is produced, and therefore cannot be retrieved.
4085///
4086/// In all cases `htemp` can be used to access the axes. For instance in the 2D case:
4087///
4088/// ~~~ {.cpp}
4089/// auto htemp = (TH2F*)gPad->GetPrimitive("htemp");
4090/// auto xaxis = htemp->GetXaxis();
4091/// ~~~
4092///
4093/// When the option `"A"` is used (with TGraph painting option) to draw a 2D
4094/// distribution:
4095/// ~~~ {.cpp}
4096/// tree.Draw("e1:e2","","A*");
4097/// ~~~
4098/// a scatter plot is produced (with stars in that case) but the axis creation is
4099/// delegated to TGraph and `htemp` is not created.
4100///
4101/// ### Saving the result of Draw to a histogram
4102///
4103/// If `varexp` contains `>>hnew` (following the variable(s) name(s)),
4104/// the new histogram called `hnew` is created and it is kept in the current
4105/// directory (and also the current pad). This works for all dimensions.
4106///
4107/// Example:
4108/// ~~~ {.cpp}
4109/// tree.Draw("sqrt(x)>>hsqrt","y>0")
4110/// ~~~
4111/// will draw `sqrt(x)` and save the histogram as "hsqrt" in the current
4112/// directory. To retrieve it do:
4113/// ~~~ {.cpp}
4114/// TH1F *hsqrt = (TH1F*)gDirectory->Get("hsqrt");
4115/// ~~~
4116/// The binning information is taken from the environment variables
4117/// ~~~ {.cpp}
4118/// Hist.Binning.?D.?
4119/// ~~~
4120/// In addition, the name of the histogram can be followed by up to 9
4121/// numbers between '(' and ')', where the numbers describe the
4122/// following:
4123///
4124/// - 1 - bins in x-direction
4125/// - 2 - lower limit in x-direction
4126/// - 3 - upper limit in x-direction
4127/// - 4-6 same for y-direction
4128/// - 7-9 same for z-direction
4129///
4130/// When a new binning is used the new value will become the default.
4131/// Values can be skipped.
4132///
4133/// Example:
4134/// ~~~ {.cpp}
4135/// tree.Draw("sqrt(x)>>hsqrt(500,10,20)")
4136/// // plot sqrt(x) between 10 and 20 using 500 bins
4137/// tree.Draw("sqrt(x):sin(y)>>hsqrt(100,10,60,50,.1,.5)")
4138/// // plot sqrt(x) against sin(y)
4139/// // 100 bins in x-direction; lower limit on x-axis is 10; upper limit is 60
4140/// // 50 bins in y-direction; lower limit on y-axis is .1; upper limit is .5
4141/// ~~~
4142/// By default, the specified histogram is reset.
4143/// To continue to append data to an existing histogram, use "+" in front
4144/// of the histogram name.
4145///
4146/// A '+' in front of the histogram name is ignored, when the name is followed by
4147/// binning information as described in the previous paragraph.
4148/// ~~~ {.cpp}
4149/// tree.Draw("sqrt(x)>>+hsqrt","y>0")
4150/// ~~~
4151/// will not reset `hsqrt`, but will continue filling. This works for 1-D, 2-D
4152/// and 3-D histograms.
4153///
4154/// ### Accessing collection objects
4155///
4156/// TTree::Draw default's handling of collections is to assume that any
4157/// request on a collection pertain to it content. For example, if fTracks
4158/// is a collection of Track objects, the following:
4159/// ~~~ {.cpp}
4160/// tree->Draw("event.fTracks.fPx");
4161/// ~~~
4162/// will plot the value of fPx for each Track objects inside the collection.
4163/// Also
4164/// ~~~ {.cpp}
4165/// tree->Draw("event.fTracks.size()");
4166/// ~~~
4167/// would plot the result of the member function Track::size() for each
4168/// Track object inside the collection.
4169/// To access information about the collection itself, TTree::Draw support
4170/// the '@' notation. If a variable which points to a collection is prefixed
4171/// or postfixed with '@', the next part of the expression will pertain to
4172/// the collection object. For example:
4173/// ~~~ {.cpp}
4174/// tree->Draw("event.@fTracks.size()");
4175/// ~~~
4176/// will plot the size of the collection referred to by `fTracks` (i.e the number
4177/// of Track objects).
4178///
4179/// ### Drawing 'objects'
4180///
4181/// When a class has a member function named AsDouble or AsString, requesting
4182/// to directly draw the object will imply a call to one of the 2 functions.
4183/// If both AsDouble and AsString are present, AsDouble will be used.
4184/// AsString can return either a char*, a std::string or a TString.s
4185/// For example, the following
4186/// ~~~ {.cpp}
4187/// tree->Draw("event.myTTimeStamp");
4188/// ~~~
4189/// will draw the same histogram as
4190/// ~~~ {.cpp}
4191/// tree->Draw("event.myTTimeStamp.AsDouble()");
4192/// ~~~
4193/// In addition, when the object is a type TString or std::string, TTree::Draw
4194/// will call respectively `TString::Data` and `std::string::c_str()`
4195///
4196/// If the object is a TBits, the histogram will contain the index of the bit
4197/// that are turned on.
4198///
4199/// ### Retrieving information about the tree itself.
4200///
4201/// You can refer to the tree (or chain) containing the data by using the
4202/// string 'This'.
4203/// You can then could any TTree methods. For example:
4204/// ~~~ {.cpp}
4205/// tree->Draw("This->GetReadEntry()");
4206/// ~~~
4207/// will display the local entry numbers be read.
4208/// ~~~ {.cpp}
4209/// tree->Draw("This->GetUserInfo()->At(0)->GetName()");
4210/// ~~~
4211/// will display the name of the first 'user info' object.
4212///
4213/// ### Special functions and variables
4214///
4215/// `Entry$`: A TTree::Draw formula can use the special variable `Entry$`
4216/// to access the entry number being read. For example to draw every
4217/// other entry use:
4218/// ~~~ {.cpp}
4219/// tree.Draw("myvar","Entry$%2==0");
4220/// ~~~
4221/// - `Entry$` : return the current entry number (`== TTree::GetReadEntry()`)
4222/// - `LocalEntry$` : return the current entry number in the current tree of a
4223/// chain (`== GetTree()->GetReadEntry()`)
4224/// - `Entries$` : return the total number of entries (== TTree::GetEntries())
4225/// - `LocalEntries$` : return the total number of entries in the current tree
4226/// of a chain (== GetTree()->TTree::GetEntries())
4227/// - `Length$` : return the total number of element of this formula for this
4228/// entry (`==TTreeFormula::GetNdata()`)
4229/// - `Iteration$` : return the current iteration over this formula for this
4230/// entry (i.e. varies from 0 to `Length$`).
4231/// - `Length$(formula )` : return the total number of element of the formula
4232/// given as a parameter.
4233/// - `Sum$(formula )` : return the sum of the value of the elements of the
4234/// formula given as a parameter. For example the mean for all the elements in
4235/// one entry can be calculated with: `Sum$(formula )/Length$(formula )`
4236/// - `Min$(formula )` : return the minimum (within one TTree entry) of the value of the
4237/// elements of the formula given as a parameter.
4238/// - `Max$(formula )` : return the maximum (within one TTree entry) of the value of the
4239/// elements of the formula given as a parameter.
4240/// - `MinIf$(formula,condition)`
4241/// - `MaxIf$(formula,condition)` : return the minimum (maximum) (within one TTree entry)
4242/// of the value of the elements of the formula given as a parameter
4243/// if they match the condition. If no element matches the condition,
4244/// the result is zero. To avoid the resulting peak at zero, use the
4245/// pattern:
4246/// ~~~ {.cpp}
4247/// tree->Draw("MinIf$(formula,condition)","condition");
4248/// ~~~
4249/// which will avoid calculation `MinIf$` for the entries that have no match
4250/// for the condition.
4251/// - `Alt$(primary,alternate)` : return the value of "primary" if it is available
4252/// for the current iteration otherwise return the value of "alternate".
4253/// For example, with arr1[3] and arr2[2]
4254/// ~~~ {.cpp}
4255/// tree->Draw("arr1+Alt$(arr2,0)");
4256/// ~~~
4257/// will draw arr1[0]+arr2[0] ; arr1[1]+arr2[1] and arr1[2]+0
4258/// Or with a variable size array arr3
4259/// ~~~ {.cpp}
4260/// tree->Draw("Alt$(arr3[0],0)+Alt$(arr3[1],0)+Alt$(arr3[2],0)");
4261/// ~~~
4262/// will draw the sum arr3 for the index 0 to min(2,actual_size_of_arr3-1)
4263/// As a comparison
4264/// ~~~ {.cpp}
4265/// tree->Draw("arr3[0]+arr3[1]+arr3[2]");
4266/// ~~~
4267/// will draw the sum arr3 for the index 0 to 2 only if the
4268/// actual_size_of_arr3 is greater or equal to 3.
4269/// Note that the array in 'primary' is flattened/linearized thus using
4270/// `Alt$` with multi-dimensional arrays of different dimensions is unlikely
4271/// to yield the expected results. To visualize a bit more what elements
4272/// would be matched by TTree::Draw, TTree::Scan can be used:
4273/// ~~~ {.cpp}
4274/// tree->Scan("arr1:Alt$(arr2,0)");
4275/// ~~~
4276/// will print on one line the value of arr1 and (arr2,0) that will be
4277/// matched by
4278/// ~~~ {.cpp}
4279/// tree->Draw("arr1-Alt$(arr2,0)");
4280/// ~~~
4281/// The ternary operator is not directly supported in TTree::Draw however, to plot the
4282/// equivalent of `var2<20 ? -99 : var1`, you can use:
4283/// ~~~ {.cpp}
4284/// tree->Draw("(var2<20)*99+(var2>=20)*var1","");
4285/// ~~~
4286///
4287/// ### Drawing a user function accessing the TTree data directly
4288///
4289/// If the formula contains a file name, TTree::MakeProxy will be used
4290/// to load and execute this file. In particular it will draw the
4291/// result of a function with the same name as the file. The function
4292/// will be executed in a context where the name of the branches can
4293/// be used as a C++ variable.
4294///
4295/// For example draw px using the file hsimple.root (generated by the
4296/// hsimple.C tutorial), we need a file named hsimple.cxx:
4297/// ~~~ {.cpp}
4298/// double hsimple() {
4299/// return px;
4300/// }
4301/// ~~~
4302/// MakeProxy can then be used indirectly via the TTree::Draw interface
4303/// as follow:
4304/// ~~~ {.cpp}
4305/// new TFile("hsimple.root")
4306/// ntuple->Draw("hsimple.cxx");
4307/// ~~~
4308/// A more complete example is available in the tutorials directory:
4309/// `h1analysisProxy.cxx`, `h1analysProxy.h` and `h1analysisProxyCut.C`
4310/// which reimplement the selector found in `h1analysis.C`
4311///
4312/// The main features of this facility are:
4313///
4314/// * on-demand loading of branches
4315/// * ability to use the 'branchname' as if it was a data member
4316/// * protection against array out-of-bound
4317/// * ability to use the branch data as object (when the user code is available)
4318///
4319/// See TTree::MakeProxy for more details.
4320///
4321/// ### Making a Profile histogram
4322///
4323/// In case of a 2-Dim expression, one can generate a TProfile histogram
4324/// instead of a TH2F histogram by specifying option=prof or option=profs
4325/// or option=profi or option=profg ; the trailing letter select the way
4326/// the bin error are computed, See TProfile2D::SetErrorOption for
4327/// details on the differences.
4328/// The option=prof is automatically selected in case of y:x>>pf
4329/// where pf is an existing TProfile histogram.
4330///
4331/// ### Making a 2D Profile histogram
4332///
4333/// In case of a 3-Dim expression, one can generate a TProfile2D histogram
4334/// instead of a TH3F histogram by specifying option=prof or option=profs.
4335/// or option=profi or option=profg ; the trailing letter select the way
4336/// the bin error are computed, See TProfile2D::SetErrorOption for
4337/// details on the differences.
4338/// The option=prof is automatically selected in case of z:y:x>>pf
4339/// where pf is an existing TProfile2D histogram.
4340///
4341/// ### Making a 5D plot using GL
4342///
4343/// If option GL5D is specified together with 5 variables, a 5D plot is drawn
4344/// using OpenGL. See $ROOTSYS/tutorials/io/tree/tree502_staff.C as example.
4345///
4346/// ### Making a parallel coordinates plot
4347///
4348/// In case of a 2-Dim or more expression with the option=para, one can generate
4349/// a parallel coordinates plot. With that option, the number of dimensions is
4350/// arbitrary. Giving more than 4 variables without the option=para or
4351/// option=candle or option=goff will produce an error.
4352///
4353/// ### Making a candle sticks chart
4354///
4355/// In case of a 2-Dim or more expression with the option=candle, one can generate
4356/// a candle sticks chart. With that option, the number of dimensions is
4357/// arbitrary. Giving more than 4 variables without the option=para or
4358/// option=candle or option=goff will produce an error.
4359///
4360/// ### Normalizing the output histogram to 1
4361///
4362/// When option contains "norm" the output histogram is normalized to 1.
4363///
4364/// ### Saving the result of Draw to a TEventList, a TEntryList or a TEntryListArray
4365///
4366/// TTree::Draw can be used to fill a TEventList object (list of entry numbers)
4367/// instead of histogramming one variable.
4368/// If varexp0 has the form >>elist , a TEventList object named "elist"
4369/// is created in the current directory. elist will contain the list
4370/// of entry numbers satisfying the current selection.
4371/// If option "entrylist" is used, a TEntryList object is created
4372/// If the selection contains arrays, vectors or any container class and option
4373/// "entrylistarray" is used, a TEntryListArray object is created
4374/// containing also the subentries satisfying the selection, i.e. the indices of
4375/// the branches which hold containers classes.
4376/// Example:
4377/// ~~~ {.cpp}
4378/// tree.Draw(">>yplus","y>0")
4379/// ~~~
4380/// will create a TEventList object named "yplus" in the current directory.
4381/// In an interactive session, one can type (after TTree::Draw)
4382/// ~~~ {.cpp}
4383/// yplus.Print("all")
4384/// ~~~
4385/// to print the list of entry numbers in the list.
4386/// ~~~ {.cpp}
4387/// tree.Draw(">>yplus", "y>0", "entrylist")
4388/// ~~~
4389/// will create a TEntryList object names "yplus" in the current directory
4390/// ~~~ {.cpp}
4391/// tree.Draw(">>yplus", "y>0", "entrylistarray")
4392/// ~~~
4393/// will create a TEntryListArray object names "yplus" in the current directory
4394///
4395/// By default, the specified entry list is reset.
4396/// To continue to append data to an existing list, use "+" in front
4397/// of the list name;
4398/// ~~~ {.cpp}
4399/// tree.Draw(">>+yplus","y>0")
4400/// ~~~
4401/// will not reset yplus, but will enter the selected entries at the end
4402/// of the existing list.
4403///
4404/// ### Using a TEventList, TEntryList or TEntryListArray as Input
4405///
4406/// Once a TEventList or a TEntryList object has been generated, it can be used as input
4407/// for TTree::Draw. Use TTree::SetEventList or TTree::SetEntryList to set the
4408/// current event list
4409///
4410/// Example 1:
4411/// ~~~ {.cpp}
4412/// TEventList *elist = (TEventList*)gDirectory->Get("yplus");
4413/// tree->SetEventList(elist);
4414/// tree->Draw("py");
4415/// ~~~
4416/// Example 2:
4417/// ~~~ {.cpp}
4418/// TEntryList *elist = (TEntryList*)gDirectory->Get("yplus");
4419/// tree->SetEntryList(elist);
4420/// tree->Draw("py");
4421/// ~~~
4422/// If a TEventList object is used as input, a new TEntryList object is created
4423/// inside the SetEventList function. In case of a TChain, all tree headers are loaded
4424/// for this transformation. This new object is owned by the chain and is deleted
4425/// with it, unless the user extracts it by calling GetEntryList() function.
4426/// See also comments to SetEventList() function of TTree and TChain.
4427///
4428/// If arrays are used in the selection criteria and TEntryListArray is not used,
4429/// all the entries that have at least one element of the array that satisfy the selection
4430/// are entered in the list.
4431///
4432/// Example:
4433/// ~~~ {.cpp}
4434/// tree.Draw(">>pyplus","fTracks.fPy>0");
4435/// tree->SetEventList(pyplus);
4436/// tree->Draw("fTracks.fPy");
4437/// ~~~
4438/// will draw the fPy of ALL tracks in event with at least one track with
4439/// a positive fPy.
4440///
4441/// To select only the elements that did match the original selection
4442/// use TEventList::SetReapplyCut or TEntryList::SetReapplyCut.
4443///
4444/// Example:
4445/// ~~~ {.cpp}
4446/// tree.Draw(">>pyplus","fTracks.fPy>0");
4447/// pyplus->SetReapplyCut(true);
4448/// tree->SetEventList(pyplus);
4449/// tree->Draw("fTracks.fPy");
4450/// ~~~
4451/// will draw the fPy of only the tracks that have a positive fPy.
4452///
4453/// To draw only the elements that match a selection in case of arrays,
4454/// you can also use TEntryListArray (faster in case of a more general selection).
4455///
4456/// Example:
4457/// ~~~ {.cpp}
4458/// tree.Draw(">>pyplus","fTracks.fPy>0", "entrylistarray");
4459/// tree->SetEntryList(pyplus);
4460/// tree->Draw("fTracks.fPy");
4461/// ~~~
4462/// will draw the fPy of only the tracks that have a positive fPy,
4463/// but without redoing the selection.
4464///
4465/// Note: Use tree->SetEventList(0) if you do not want use the list as input.
4466///
4467/// ### How to obtain more info from TTree::Draw
4468///
4469/// Once TTree::Draw has been called, it is possible to access useful
4470/// information still stored in the TTree object via the following functions:
4471///
4472/// - GetSelectedRows() // return the number of values accepted by the selection expression. In case where no selection was specified, returns the number of values processed.
4473/// - GetV1() // returns a pointer to the double array of V1
4474/// - GetV2() // returns a pointer to the double array of V2
4475/// - GetV3() // returns a pointer to the double array of V3
4476/// - GetV4() // returns a pointer to the double array of V4
4477/// - GetW() // returns a pointer to the double array of Weights where weight equal the result of the selection expression.
4478///
4479/// where V1,V2,V3 correspond to the expressions in
4480/// ~~~ {.cpp}
4481/// TTree::Draw("V1:V2:V3:V4",selection);
4482/// ~~~
4483/// If the expression has more than 4 component use GetVal(index)
4484///
4485/// Example:
4486/// ~~~ {.cpp}
4487/// Root > ntuple->Draw("py:px","pz>4");
4488/// Root > TGraph *gr = new TGraph(ntuple->GetSelectedRows(),
4489/// ntuple->GetV2(), ntuple->GetV1());
4490/// Root > gr->Draw("ap"); //draw graph in current pad
4491/// ~~~
4492///
4493/// A more complete complete tutorial (treegetval.C) shows how to use the
4494/// GetVal() method.
4495///
4496/// creates a TGraph object with a number of points corresponding to the
4497/// number of entries selected by the expression "pz>4", the x points of the graph
4498/// being the px values of the Tree and the y points the py values.
4499///
4500/// Important note: By default TTree::Draw creates the arrays obtained
4501/// with GetW, GetV1, GetV2, GetV3, GetV4, GetVal with a length corresponding
4502/// to the parameter fEstimate. The content will be the last `GetSelectedRows() % GetEstimate()`
4503/// values calculated.
4504/// By default fEstimate=1000000 and can be modified
4505/// via TTree::SetEstimate. To keep in memory all the results (in case
4506/// where there is only one result per entry), use
4507/// ~~~ {.cpp}
4508/// tree->SetEstimate(tree->GetEntries()+1); // same as tree->SetEstimate(-1);
4509/// ~~~
4510/// You must call SetEstimate if the expected number of selected rows
4511/// you need to look at is greater than 1000000.
4512///
4513/// You can use the option "goff" to turn off the graphics output
4514/// of TTree::Draw in the above example.
4515///
4516/// ### Automatic interface to TTree::Draw via the TTreeViewer
4517///
4518/// A complete graphical interface to this function is implemented
4519/// in the class TTreeViewer.
4520/// To start the TTreeViewer, three possibilities:
4521/// - select TTree context menu item "StartViewer"
4522/// - type the command "TTreeViewer TV(treeName)"
4523/// - execute statement "tree->StartViewer();"
4526{
4527 GetPlayer();
4528 if (fPlayer)
4530 return -1;
4531}
4532
4533////////////////////////////////////////////////////////////////////////////////
4534/// Remove some baskets from memory.
4536void TTree::DropBaskets()
4537{
4538 TBranch* branch = nullptr;
4540 for (Int_t i = 0; i < nb; ++i) {
4542 branch->DropBaskets("all");
4543 }
4544}
4545
4546////////////////////////////////////////////////////////////////////////////////
4547/// Drop branch buffers to accommodate nbytes below MaxVirtualsize.
4550{
4551 // Be careful not to remove current read/write buffers.
4553 for (Int_t i = 0; i < nleaves; ++i) {
4555 TBranch* branch = (TBranch*) leaf->GetBranch();
4556 Int_t nbaskets = branch->GetListOfBaskets()->GetEntries();
4557 for (Int_t j = 0; j < nbaskets - 1; ++j) {
4558 if ((j == branch->GetReadBasket()) || (j == branch->GetWriteBasket())) {
4559 continue;
4560 }
4561 TBasket* basket = (TBasket*)branch->GetListOfBaskets()->UncheckedAt(j);
4562 if (basket) {
4563 basket->DropBuffers();
4565 return;
4566 }
4567 }
4568 }
4569 }
4570}
4571
4572////////////////////////////////////////////////////////////////////////////////
4573/// Fill all branches.
4574///
4575/// This function loops on all the branches of this tree. For
4576/// each branch, it copies to the branch buffer (basket) the current
4577/// values of the leaves data types. If a leaf is a simple data type,
4578/// a simple conversion to a machine independent format has to be done.
4579///
4580/// This machine independent version of the data is copied into a
4581/// basket (each branch has its own basket). When a basket is full
4582/// (32k worth of data by default), it is then optionally compressed
4583/// and written to disk (this operation is also called committing or
4584/// 'flushing' the basket). The committed baskets are then
4585/// immediately removed from memory.
4586///
4587/// The function returns the number of bytes committed to the
4588/// individual branches.
4589///
4590/// If a write error occurs, the number of bytes returned is -1.
4591///
4592/// If no data are written, because, e.g., the branch is disabled,
4593/// the number of bytes returned is 0.
4594///
4595/// __The baskets are flushed and the Tree header saved at regular intervals__
4596///
4597/// At regular intervals, when the amount of data written so far is
4598/// greater than fAutoFlush (see SetAutoFlush) all the baskets are flushed to disk.
4599/// This makes future reading faster as it guarantees that baskets belonging to nearby
4600/// entries will be on the same disk region.
4601/// When the first call to flush the baskets happen, we also take this opportunity
4602/// to optimize the baskets buffers.
4603/// We also check if the amount of data written is greater than fAutoSave (see SetAutoSave).
4604/// In this case we also write the Tree header. This makes the Tree recoverable up to this point
4605/// in case the program writing the Tree crashes.
4606/// The decisions to FlushBaskets and Auto Save can be made based either on the number
4607/// of bytes written (fAutoFlush and fAutoSave negative) or on the number of entries
4608/// written (fAutoFlush and fAutoSave positive).
4609/// Note that the user can decide to call FlushBaskets and AutoSave in her event loop
4610/// base on the number of events written instead of the number of bytes written.
4611///
4612/// \note Calling `TTree::FlushBaskets` too often increases the IO time.
4613///
4614/// \note Calling `TTree::AutoSave` too often increases the IO time and also the
4615/// file size.
4616///
4617/// \note This method calls `TTree::ChangeFile` when the tree reaches a size
4618/// greater than `TTree::fgMaxTreeSize`. This doesn't happen if the tree is
4619/// attached to a `TMemFile` or derivate.
4622{
4623 Int_t nbytes = 0;
4624 Int_t nwrite = 0;
4625 Int_t nerror = 0;
4627
4628 // Case of one single super branch. Automatically update
4629 // all the branch addresses if a new object was created.
4630 if (nbranches == 1)
4631 ((TBranch *)fBranches.UncheckedAt(0))->UpdateAddress();
4632
4633 if (fBranchRef)
4634 fBranchRef->Clear();
4635
4636#ifdef R__USE_IMT
4639 if (useIMT) {
4640 fIMTFlush = true;
4641 fIMTZipBytes.store(0);
4642 fIMTTotBytes.store(0);
4643 }
4644#endif
4645
4646 for (Int_t i = 0; i < nbranches; ++i) {
4647 // Loop over all branches, filling and accumulating bytes written and error counts.
4649
4650 if (branch->TestBit(kDoNotProcess))
4651 continue;
4652
4653#ifndef R__USE_IMT
4654 nwrite = branch->FillImpl(nullptr);
4655#else
4656 nwrite = branch->FillImpl(useIMT ? &imtHelper : nullptr);
4657#endif
4658 if (nwrite < 0) {
4659 if (nerror < 2) {
4660 Error("Fill", "Failed filling branch:%s.%s, nbytes=%d, entry=%lld\n"
4661 " This error is symptomatic of a Tree created as a memory-resident Tree\n"
4662 " Instead of doing:\n"
4663 " TTree *T = new TTree(...)\n"
4664 " TFile *f = new TFile(...)\n"
4665 " you should do:\n"
4666 " TFile *f = new TFile(...)\n"
4667 " TTree *T = new TTree(...)\n\n",
4668 GetName(), branch->GetName(), nwrite, fEntries + 1);
4669 } else {
4670 Error("Fill", "Failed filling branch:%s.%s, nbytes=%d, entry=%lld", GetName(), branch->GetName(), nwrite,
4671 fEntries + 1);
4672 }
4673 ++nerror;
4674 } else {
4675 nbytes += nwrite;
4676 }
4677 }
4678
4679#ifdef R__USE_IMT
4680 if (fIMTFlush) {
4681 imtHelper.Wait();
4682 fIMTFlush = false;
4683 const_cast<TTree *>(this)->AddTotBytes(fIMTTotBytes);
4684 const_cast<TTree *>(this)->AddZipBytes(fIMTZipBytes);
4685 nbytes += imtHelper.GetNbytes();
4686 nerror += imtHelper.GetNerrors();
4687 }
4688#endif
4689
4690 if (fBranchRef)
4691 fBranchRef->Fill();
4692
4693 ++fEntries;
4694
4695 if (fEntries > fMaxEntries)
4696 KeepCircular();
4697
4698 if (gDebug > 0)
4699 Info("TTree::Fill", " - A: %d %lld %lld %lld %lld %lld %lld \n", nbytes, fEntries, fAutoFlush, fAutoSave,
4701
4702 bool autoFlush = false;
4703 bool autoSave = false;
4704
4705 if (fAutoFlush != 0 || fAutoSave != 0) {
4706 // Is it time to flush or autosave baskets?
4707 if (fFlushedBytes == 0) {
4708 // If fFlushedBytes == 0, it means we never flushed or saved, so
4709 // we need to check if it's time to do it and recompute the values
4710 // of fAutoFlush and fAutoSave in terms of the number of entries.
4711 // Decision can be based initially either on the number of bytes
4712 // or the number of entries written.
4714
4715 if (fAutoFlush)
4717
4718 if (fAutoSave)
4719 autoSave = fAutoSave < 0 ? (zipBytes > -fAutoSave) : fEntries % fAutoSave == 0;
4720
4721 if (autoFlush || autoSave) {
4722 // First call FlushBasket to make sure that fTotBytes is up to date.
4724 autoFlush = false; // avoid auto flushing again later
4725
4726 // When we are in one-basket-per-cluster mode, there is no need to optimize basket:
4727 // they will automatically grow to the size needed for an event cluster (with the basket
4728 // shrinking preventing them from growing too much larger than the actually-used space).
4730 OptimizeBaskets(GetTotBytes(), 1, "");
4731 if (gDebug > 0)
4732 Info("TTree::Fill", "OptimizeBaskets called at entry %lld, fZipBytes=%lld, fFlushedBytes=%lld\n",
4734 }
4736 fAutoFlush = fEntries; // Use test on entries rather than bytes
4737
4738 // subsequently in run
4739 if (fAutoSave < 0) {
4740 // Set fAutoSave to the largest integer multiple of
4741 // fAutoFlush events such that fAutoSave*fFlushedBytes
4742 // < (minus the input value of fAutoSave)
4744 if (zipBytes != 0) {
4746 } else if (totBytes != 0) {
4748 } else {
4750 TTree::Class()->WriteBuffer(b, (TTree *)this);
4751 Long64_t total = b.Length();
4753 }
4754 } else if (fAutoSave > 0) {
4756 }
4757
4758 if (fAutoSave != 0 && fEntries >= fAutoSave)
4759 autoSave = true;
4760
4761 if (gDebug > 0)
4762 Info("TTree::Fill", "First AutoFlush. fAutoFlush = %lld, fAutoSave = %lld\n", fAutoFlush, fAutoSave);
4763 }
4764 } else {
4765 // Check if we need to auto flush
4766 if (fAutoFlush) {
4767 if (fNClusterRange == 0)
4768 autoFlush = fEntries > 1 && fEntries % fAutoFlush == 0;
4769 else
4771 }
4772 // Check if we need to auto save
4773 if (fAutoSave)
4774 autoSave = fEntries % fAutoSave == 0;
4775 }
4776 }
4777
4778 if (autoFlush) {
4780 if (gDebug > 0)
4781 Info("TTree::Fill", "FlushBaskets() called at entry %lld, fZipBytes=%lld, fFlushedBytes=%lld\n", fEntries,
4784 }
4785
4786 if (autoSave) {
4787 AutoSave(); // does not call FlushBasketsImpl() again
4788 if (gDebug > 0)
4789 Info("TTree::Fill", "AutoSave called at entry %lld, fZipBytes=%lld, fSavedBytes=%lld\n", fEntries,
4791 }
4792
4793 // Check that output file is still below the maximum size.
4794 // If above, close the current file and continue on a new file.
4795 // Currently, the automatic change of file is restricted
4796 // to the case where the tree is in the top level directory.
4797 if (fDirectory)
4798 if (TFile *file = fDirectory->GetFile())
4799 if (static_cast<TDirectory *>(file) == fDirectory && (file->GetEND() > fgMaxTreeSize))
4800 ChangeFile(file);
4801
4802 return nerror == 0 ? nbytes : -1;
4803}
4804
4805////////////////////////////////////////////////////////////////////////////////
4806/// Search in the array for a branch matching the branch name,
4807/// with the branch possibly expressed as a 'full' path name (with dots).
4809static TBranch *R__FindBranchHelper(TObjArray *list, const char *branchname) {
4810 if (list==nullptr || branchname == nullptr || branchname[0] == '\0') return nullptr;
4811
4812 Int_t nbranches = list->GetEntries();
4813
4815
4816 for(Int_t index = 0; index < nbranches; ++index) {
4817 TBranch *where = (TBranch*)list->UncheckedAt(index);
4818
4819 const char *name = where->GetName();
4820 UInt_t len = strlen(name);
4821 if (len && name[len-1]==']') {
4822 const char *dim = strchr(name,'[');
4823 if (dim) {
4824 len = dim - name;
4825 }
4826 }
4827 if (brlen == len && strncmp(branchname,name,len)==0) {
4828 return where;
4829 }
4830 TBranch *next = nullptr;
4831 if ((brlen >= len) && (branchname[len] == '.')
4832 && strncmp(name, branchname, len) == 0) {
4833 // The prefix subbranch name match the branch name.
4834
4835 next = where->FindBranch(branchname);
4836 if (!next) {
4837 next = where->FindBranch(branchname+len+1);
4838 }
4839 if (next) return next;
4840 }
4841 const char *dot = strchr((char*)branchname,'.');
4842 if (dot) {
4843 if (len==(size_t)(dot-branchname) &&
4844 strncmp(branchname,name,dot-branchname)==0 ) {
4845 return R__FindBranchHelper(where->GetListOfBranches(),dot+1);
4846 }
4847 }
4848 }
4849 return nullptr;
4850}
4851
4852////////////////////////////////////////////////////////////////////////////////
4853/// Return the branch that correspond to the path 'branchname', which can
4854/// include the name of the tree or the omitted name of the parent branches.
4855/// In case of ambiguity, returns the first match.
4858{
4859 // We already have been visited while recursively looking
4860 // through the friends tree, let return
4862 return nullptr;
4863 }
4864
4865 if (!branchname)
4866 return nullptr;
4867
4868 TBranch* branch = nullptr;
4869 // If the first part of the name match the TTree name, look for the right part in the
4870 // list of branches.
4871 // This will allow the branchname to be preceded by
4872 // the name of this tree.
4873 if (strncmp(fName.Data(),branchname,fName.Length())==0 && branchname[fName.Length()]=='.') {
4875 if (branch) return branch;
4876 }
4877 // If we did not find it, let's try to find the full name in the list of branches.
4879 if (branch) return branch;
4880
4881 // If we still did not find, let's try to find it within each branch assuming it does not the branch name.
4882 TIter next(GetListOfBranches());
4883 while ((branch = (TBranch*) next())) {
4884 TBranch* nestedbranch = branch->FindBranch(branchname);
4885 if (nestedbranch) {
4886 return nestedbranch;
4887 }
4888 }
4889
4890 // Search in list of friends.
4891 if (!fFriends) {
4892 return nullptr;
4893 }
4894 TFriendLock lock(this, kFindBranch);
4896 TFriendElement* fe = nullptr;
4897 while ((fe = (TFriendElement*) nextf())) {
4898 TTree* t = fe->GetTree();
4899 if (!t) {
4900 continue;
4901 }
4902 // If the alias is present replace it with the real name.
4903 const char *subbranch = strstr(branchname, fe->GetName());
4904 if (subbranch != branchname) {
4905 subbranch = nullptr;
4906 }
4907 if (subbranch) {
4908 subbranch += strlen(fe->GetName());
4909 if (*subbranch != '.') {
4910 subbranch = nullptr;
4911 } else {
4912 ++subbranch;
4913 }
4914 }
4915 std::ostringstream name;
4916 if (subbranch) {
4917 name << t->GetName() << "." << subbranch;
4918 } else {
4919 name << branchname;
4920 }
4921 branch = t->FindBranch(name.str().c_str());
4922 if (branch) {
4923 return branch;
4924 }
4925 }
4926 return nullptr;
4927}
4928
4929////////////////////////////////////////////////////////////////////////////////
4930/// Find leaf..
4932TLeaf* TTree::FindLeaf(const char* searchname)
4933{
4934 if (!searchname)
4935 return nullptr;
4936
4937 // We already have been visited while recursively looking
4938 // through the friends tree, let's return.
4940 return nullptr;
4941 }
4942
4943 // This will allow the branchname to be preceded by
4944 // the name of this tree.
4945 const char* subsearchname = strstr(searchname, GetName());
4946 if (subsearchname != searchname) {
4947 subsearchname = nullptr;
4948 }
4949 if (subsearchname) {
4951 if (*subsearchname != '.') {
4952 subsearchname = nullptr;
4953 } else {
4954 ++subsearchname;
4955 if (subsearchname[0] == 0) {
4956 subsearchname = nullptr;
4957 }
4958 }
4959 }
4960
4965
4966 const bool searchnameHasDot = strchr(searchname, '.') != nullptr;
4967
4968 // For leaves we allow for one level up to be prefixed to the name.
4969 TIter next(GetListOfLeaves());
4970 TLeaf* leaf = nullptr;
4971 while ((leaf = (TLeaf*) next())) {
4972 leafname = leaf->GetName();
4973 Ssiz_t dim = leafname.First('[');
4974 if (dim >= 0) leafname.Remove(dim);
4975
4976 if (leafname == searchname) {
4977 return leaf;
4978 }
4980 return leaf;
4981 }
4982 // The TLeafElement contains the branch name
4983 // in its name, let's use the title.
4984 leaftitle = leaf->GetTitle();
4985 dim = leaftitle.First('[');
4986 if (dim >= 0) leaftitle.Remove(dim);
4987
4988 if (leaftitle == searchname) {
4989 return leaf;
4990 }
4992 return leaf;
4993 }
4994 if (!searchnameHasDot)
4995 continue;
4996 TBranch* branch = leaf->GetBranch();
4997 if (branch) {
4998 longname.Form("%s.%s",branch->GetName(),leafname.Data());
4999 dim = longname.First('[');
5000 if (dim>=0) longname.Remove(dim);
5001 if (longname == searchname) {
5002 return leaf;
5003 }
5005 return leaf;
5006 }
5007 longtitle.Form("%s.%s",branch->GetName(),leaftitle.Data());
5008 dim = longtitle.First('[');
5009 if (dim>=0) longtitle.Remove(dim);
5010 if (longtitle == searchname) {
5011 return leaf;
5012 }
5014 return leaf;
5015 }
5016 // The following is for the case where the branch is only
5017 // a sub-branch. Since we do not see it through
5018 // TTree::GetListOfBranches, we need to see it indirectly.
5019 // This is the less sturdy part of this search ... it may
5020 // need refining ...
5021 if (strstr(searchname, ".") && !strcmp(searchname, branch->GetName())) {
5022 return leaf;
5023 }
5024 if (subsearchname && strstr(subsearchname, ".") && !strcmp(subsearchname, branch->GetName())) {
5025 return leaf;
5026 }
5027 }
5028 }
5029 // Search in list of friends.
5030 if (!fFriends) {
5031 return nullptr;
5032 }
5033 TFriendLock lock(this, kFindLeaf);
5035 TFriendElement* fe = nullptr;
5036 while ((fe = (TFriendElement*) nextf())) {
5037 TTree* t = fe->GetTree();
5038 if (!t) {
5039 continue;
5040 }
5041 // If the alias is present replace it with the real name.
5042 subsearchname = strstr(searchname, fe->GetName());
5043 if (subsearchname != searchname) {
5044 subsearchname = nullptr;
5045 }
5046 if (subsearchname) {
5047 subsearchname += strlen(fe->GetName());
5048 if (*subsearchname != '.') {
5049 subsearchname = nullptr;
5050 } else {
5051 ++subsearchname;
5052 }
5053 }
5054 if (subsearchname) {
5055 leafname.Form("%s.%s",t->GetName(),subsearchname);
5056 } else {
5058 }
5059 leaf = t->FindLeaf(leafname);
5060 if (leaf) {
5061 return leaf;
5062 }
5063 }
5064 return nullptr;
5065}
5066
5067////////////////////////////////////////////////////////////////////////////////
5068/// Fit a projected item(s) from a tree.
5069///
5070/// funcname is a TF1 function.
5071///
5072/// See TTree::Draw() for explanations of the other parameters.
5073///
5074/// By default the temporary histogram created is called htemp.
5075/// If varexp contains >>hnew , the new histogram created is called hnew
5076/// and it is kept in the current directory.
5077///
5078/// The function returns the number of selected entries.
5079///
5080/// Example:
5081/// ~~~ {.cpp}
5082/// tree.Fit(pol4,"sqrt(x)>>hsqrt","y>0")
5083/// ~~~
5084/// will fit sqrt(x) and save the histogram as "hsqrt" in the current
5085/// directory.
5086///
5087/// See also TTree::UnbinnedFit
5088///
5089/// ## Return status
5090///
5091/// The function returns the status of the histogram fit (see TH1::Fit)
5092/// If no entries were selected, the function returns -1;
5093/// (i.e. fitResult is null if the fit is OK)
5096{
5097 GetPlayer();
5098 if (fPlayer) {
5100 }
5101 return -1;
5102}
5103
5104namespace {
5105struct BoolRAIIToggle {
5106 bool &m_val;
5107
5108 BoolRAIIToggle(bool &val) : m_val(val) { m_val = true; }
5109 ~BoolRAIIToggle() { m_val = false; }
5110};
5111}
5112
5113////////////////////////////////////////////////////////////////////////////////
5114/// Write to disk all the basket that have not yet been individually written and
5115/// create an event cluster boundary (by default).
5116///
5117/// If the caller wishes to flush the baskets but not create an event cluster,
5118/// then set create_cluster to false.
5119///
5120/// If ROOT has IMT-mode enabled, this will launch multiple TBB tasks in parallel
5121/// via TThreadExecutor to do this operation; one per basket compression. If the
5122/// caller utilizes TBB also, care must be taken to prevent deadlocks.
5123///
5124/// For example, let's say the caller holds mutex A and calls FlushBaskets; while
5125/// TBB is waiting for the ROOT compression tasks to complete, it may decide to
5126/// run another one of the user's tasks in this thread. If the second user task
5127/// tries to acquire A, then a deadlock will occur. The example call sequence
5128/// looks like this:
5129///
5130/// - User acquires mutex A
5131/// - User calls FlushBaskets.
5132/// - ROOT launches N tasks and calls wait.
5133/// - TBB schedules another user task, T2.
5134/// - T2 tries to acquire mutex A.
5135///
5136/// At this point, the thread will deadlock: the code may function with IMT-mode
5137/// disabled if the user assumed the legacy code never would run their own TBB
5138/// tasks.
5139///
5140/// SO: users of TBB who want to enable IMT-mode should carefully review their
5141/// locking patterns and make sure they hold no coarse-grained application
5142/// locks when they invoke ROOT.
5143///
5144/// Return the number of bytes written or -1 in case of write error.
5146{
5148 if (retval == -1) return retval;
5149
5150 if (create_cluster) const_cast<TTree *>(this)->MarkEventCluster();
5151 return retval;
5152}
5153
5154////////////////////////////////////////////////////////////////////////////////
5155/// Internal implementation of the FlushBaskets algorithm.
5156/// Unlike the public interface, this does NOT create an explicit event cluster
5157/// boundary; it is up to the (internal) caller to determine whether that should
5158/// done.
5159///
5160/// Otherwise, the comments for FlushBaskets applies.
5163{
5164 if (!fDirectory) return 0;
5165 Int_t nbytes = 0;
5166 Int_t nerror = 0;
5167 TObjArray *lb = const_cast<TTree*>(this)->GetListOfBranches();
5168 Int_t nb = lb->GetEntriesFast();
5169
5170#ifdef R__USE_IMT
5172 if (useIMT) {
5173 // ROOT-9668: here we need to check if the size of fSortedBranches is different from the
5174 // size of the list of branches before triggering the initialisation of the fSortedBranches
5175 // container to cover two cases:
5176 // 1. This is the first time we flush. fSortedBranches is empty and we need to fill it.
5177 // 2. We flushed at least once already but a branch has been be added to the tree since then
5178 if (fSortedBranches.size() != unsigned(nb)) { const_cast<TTree*>(this)->InitializeBranchLists(false); }
5179
5180 BoolRAIIToggle sentry(fIMTFlush);
5181 fIMTZipBytes.store(0);
5182 fIMTTotBytes.store(0);
5183 std::atomic<Int_t> nerrpar(0);
5184 std::atomic<Int_t> nbpar(0);
5185 std::atomic<Int_t> pos(0);
5186
5187 auto mapFunction = [&]() {
5188 // The branch to process is obtained when the task starts to run.
5189 // This way, since branches are sorted, we make sure that branches
5190 // leading to big tasks are processed first. If we assigned the
5191 // branch at task creation time, the scheduler would not necessarily
5192 // respect our sorting.
5193 Int_t j = pos.fetch_add(1);
5194
5195 auto branch = fSortedBranches[j].second;
5196 if (R__unlikely(!branch)) { return; }
5197
5198 if (R__unlikely(gDebug > 0)) {
5199 std::stringstream ss;
5200 ss << std::this_thread::get_id();
5201 Info("FlushBaskets", "[IMT] Thread %s", ss.str().c_str());
5202 Info("FlushBaskets", "[IMT] Running task for branch #%d: %s", j, branch->GetName());
5203 }
5204
5205 Int_t nbtask = branch->FlushBaskets();
5206
5207 if (nbtask < 0) { nerrpar++; }
5208 else { nbpar += nbtask; }
5209 };
5210
5212 pool.Foreach(mapFunction, nb);
5213
5214 fIMTFlush = false;
5215 const_cast<TTree*>(this)->AddTotBytes(fIMTTotBytes);
5216 const_cast<TTree*>(this)->AddZipBytes(fIMTZipBytes);
5217
5218 return nerrpar ? -1 : nbpar.load();
5219 }
5220#endif
5221 for (Int_t j = 0; j < nb; j++) {
5222 TBranch* branch = (TBranch*) lb->UncheckedAt(j);
5223 if (branch) {
5224 Int_t nwrite = branch->FlushBaskets();
5225 if (nwrite<0) {
5226 ++nerror;
5227 } else {
5228 nbytes += nwrite;
5229 }
5230 }
5231 }
5232 if (nerror) {
5233 return -1;
5234 } else {
5235 return nbytes;
5236 }
5237}
5238
5239////////////////////////////////////////////////////////////////////////////////
5240/// Returns the expanded value of the alias. Search in the friends if any.
5242const char* TTree::GetAlias(const char* aliasName) const
5243{
5244 // We already have been visited while recursively looking
5245 // through the friends tree, let's return.
5247 return nullptr;
5248 }
5249 if (fAliases) {
5251 if (alias) {
5252 return alias->GetTitle();
5253 }
5254 }
5255 if (!fFriends) {
5256 return nullptr;
5257 }
5258 TFriendLock lock(const_cast<TTree*>(this), kGetAlias);
5260 TFriendElement* fe = nullptr;
5261 while ((fe = (TFriendElement*) nextf())) {
5262 TTree* t = fe->GetTree();
5263 if (t) {
5264 const char* alias = t->GetAlias(aliasName);
5265 if (alias) {
5266 return alias;
5267 }
5268 const char* subAliasName = strstr(aliasName, fe->GetName());
5269 if (subAliasName && (subAliasName[strlen(fe->GetName())] == '.')) {
5270 alias = t->GetAlias(aliasName + strlen(fe->GetName()) + 1);
5271 if (alias) {
5272 return alias;
5273 }
5274 }
5275 }
5276 }
5277 return nullptr;
5278}
5279
5280namespace {
5281/// Do a breadth first search through the implied hierarchy
5282/// of branches.
5283/// To avoid scanning through the list multiple time
5284/// we also remember the 'depth-first' match.
5285TBranch *R__GetBranch(const TObjArray &branches, const char *name)
5286{
5287 TBranch *result = nullptr;
5288 Int_t nb = branches.GetEntriesFast();
5289 for (Int_t i = 0; i < nb; i++) {
5290 TBranch* b = (TBranch*)branches.UncheckedAt(i);
5291 if (!b)
5292 continue;
5293 if (!strcmp(b->GetName(), name)) {
5294 return b;
5295 }
5296 if (!strcmp(b->GetFullName(), name)) {
5297 return b;
5298 }
5299 if (!result)
5300 result = R__GetBranch(*(b->GetListOfBranches()), name);
5301 }
5302 return result;
5303}
5304}
5305
5306////////////////////////////////////////////////////////////////////////////////
5307/// Return pointer to the branch with the given name in this tree or its friends.
5308/// The search is done breadth first.
5310TBranch* TTree::GetBranch(const char* name)
5311{
5312 // We already have been visited while recursively
5313 // looking through the friends tree, let's return.
5315 return nullptr;
5316 }
5317
5318 if (!name)
5319 return nullptr;
5320
5321 // Look for an exact match in the list of top level
5322 // branches.
5324 if (result)
5325 return result;
5326
5327 if (auto it = fNamesToBranches.find(name); it != fNamesToBranches.end())
5328 return it->second;
5329
5330 // Search using branches, breadth first.
5332 if (result)
5333 return result;
5334
5335 // Search using leaves.
5337 Int_t nleaves = leaves->GetEntriesFast();
5338 for (Int_t i = 0; i < nleaves; i++) {
5339 TLeaf* leaf = (TLeaf*) leaves->UncheckedAt(i);
5340 TBranch* branch = leaf->GetBranch();
5341 if (!strcmp(branch->GetName(), name)) {
5342 return branch;
5343 }
5344 if (!strcmp(branch->GetFullName(), name)) {
5345 return branch;
5346 }
5347 }
5348
5349 if (!fFriends) {
5350 return nullptr;
5351 }
5352
5353 // Search in list of friends.
5354 TFriendLock lock(this, kGetBranch);
5355 TIter next(fFriends);
5356 TFriendElement* fe = nullptr;
5357 while ((fe = (TFriendElement*) next())) {
5358 TTree* t = fe->GetTree();
5359 if (t) {
5361 if (branch) {
5362 return branch;
5363 }
5364 }
5365 }
5366
5367 // Second pass in the list of friends when
5368 // the branch name is prefixed by the tree name.
5369 next.Reset();
5370 while ((fe = (TFriendElement*) next())) {
5371 TTree* t = fe->GetTree();
5372 if (!t) {
5373 continue;
5374 }
5375 const char* subname = strstr(name, fe->GetName());
5376 if (subname != name) {
5377 continue;
5378 }
5379 Int_t l = strlen(fe->GetName());
5380 subname += l;
5381 if (*subname != '.') {
5382 continue;
5383 }
5384 subname++;
5386 if (branch) {
5387 return branch;
5388 }
5389 }
5390 return nullptr;
5391}
5392
5393////////////////////////////////////////////////////////////////////////////////
5394/// Return status of branch with name branchname.
5395///
5396/// - 0 if branch is not activated
5397/// - 1 if branch is activated
5399bool TTree::GetBranchStatus(const char* branchname) const
5400{
5401 TBranch* br = const_cast<TTree*>(this)->GetBranch(branchname);
5402 if (br) {
5403 return br->TestBit(kDoNotProcess) == 0;
5404 }
5405 return false;
5406}
5407
5408////////////////////////////////////////////////////////////////////////////////
5409/// Static function returning the current branch style.
5410///
5411/// - style = 0 old Branch
5412/// - style = 1 new Bronch
5417}
5418
5419////////////////////////////////////////////////////////////////////////////////
5420/// Used for automatic sizing of the cache.
5421///
5422/// Estimates a suitable size for the tree cache based on AutoFlush.
5423/// A cache sizing factor is taken from the configuration. If this yields zero
5424/// and withDefault is true the historical algorithm for default size is used.
5426Long64_t TTree::GetCacheAutoSize(bool withDefault /* = false */ )
5427{
5429 {
5430 Long64_t cacheSize = 0;
5431 if (fAutoFlush < 0) {
5432 cacheSize = Long64_t(-cacheFactor * fAutoFlush);
5433 } else if (fAutoFlush == 0) {
5435 if (medianClusterSize > 0)
5436 cacheSize = Long64_t(cacheFactor * 1.5 * medianClusterSize * GetZipBytes() / (fEntries + 1));
5437 else
5438 cacheSize = Long64_t(cacheFactor * 1.5 * 30000000); // use the default value of fAutoFlush
5439 } else {
5440 cacheSize = Long64_t(cacheFactor * 1.5 * fAutoFlush * GetZipBytes() / (fEntries + 1));
5441 }
5442 if (cacheSize >= (INT_MAX / 4)) {
5443 cacheSize = INT_MAX / 4;
5444 }
5445 return cacheSize;
5446 };
5447
5448 const char *stcs;
5449 Double_t cacheFactor = 0.0;
5450 if (!(stcs = gSystem->Getenv("ROOT_TTREECACHE_SIZE")) || !*stcs) {
5451 cacheFactor = gEnv->GetValue("TTreeCache.Size", 1.0);
5452 } else {
5454 }
5455
5456 if (cacheFactor < 0.0) {
5457 // ignore negative factors
5458 cacheFactor = 0.0;
5459 }
5460
5462
5463 if (cacheSize < 0) {
5464 cacheSize = 0;
5465 }
5466
5467 if (cacheSize == 0 && withDefault) {
5468 cacheSize = calculateCacheSize(1.0);
5469 }
5470
5471 return cacheSize;
5472}
5473
5474////////////////////////////////////////////////////////////////////////////////
5475/// Return an iterator over the cluster of baskets starting at firstentry.
5476///
5477/// This iterator is not yet supported for TChain object.
5478/// ~~~ {.cpp}
5479/// TTree::TClusterIterator clusterIter = tree->GetClusterIterator(entry);
5480/// Long64_t clusterStart;
5481/// while( (clusterStart = clusterIter()) < tree->GetEntries() ) {
5482/// printf("The cluster starts at %lld and ends at %lld (inclusive)\n",clusterStart,clusterIter.GetNextEntry()-1);
5483/// }
5484/// ~~~
5487{
5488 // create cache if wanted
5489 if (fCacheDoAutoInit)
5491
5492 return TClusterIterator(this,firstentry);
5493}
5494
5495////////////////////////////////////////////////////////////////////////////////
5496/// Return pointer to the current file.
5499{
5500 if (!fDirectory || fDirectory==gROOT) {
5501 return nullptr;
5502 }
5503 return fDirectory->GetFile();
5504}
5505
5506////////////////////////////////////////////////////////////////////////////////
5507/// Return the number of entries matching the selection.
5508/// Return -1 in case of errors.
5509///
5510/// If the selection uses any arrays or containers, we return the number
5511/// of entries where at least one element match the selection.
5512/// GetEntries is implemented using the selector class TSelectorEntries,
5513/// which can be used directly (see code in TTreePlayer::GetEntries) for
5514/// additional option.
5515/// If SetEventList was used on the TTree or TChain, only that subset
5516/// of entries will be considered.
5519{
5520 GetPlayer();
5521 if (fPlayer) {
5522 return fPlayer->GetEntries(selection);
5523 }
5524 return -1;
5525}
5526
5527////////////////////////////////////////////////////////////////////////////////
5528/// Return pointer to the 1st Leaf named name in any Branch of this Tree or
5529/// any branch in the list of friend trees.
5532{
5533 if (fEntries) return fEntries;
5534 if (!fFriends) return 0;
5536 if (!fr) return 0;
5537 TTree *t = fr->GetTree();
5538 if (t==nullptr) return 0;
5539 return t->GetEntriesFriend();
5540}
5541
5542////////////////////////////////////////////////////////////////////////////////
5543/// Read all branches of entry and return total number of bytes read.
5544///
5545/// - `getall = 0` : get only active branches
5546/// - `getall = 1` : get all branches
5547///
5548/// The function returns the number of bytes read from the input buffer.
5549/// If entry does not exist the function returns 0.
5550/// If an I/O error occurs, the function returns -1.
5551/// If all branches are disabled and getall == 0, it also returns 0
5552/// even if the specified entry exists in the tree, since zero bytes were read.
5553///
5554/// If the Tree has friends, also read the friends entry.
5555///
5556/// To activate/deactivate one or more branches, use TBranch::SetBranchStatus
5557/// For example, if you have a Tree with several hundred branches, and you
5558/// are interested only by branches named "a" and "b", do
5559/// ~~~ {.cpp}
5560/// mytree.SetBranchStatus("*",0); //disable all branches
5561/// mytree.SetBranchStatus("a",1);
5562/// mytree.SetBranchStatus("b",1);
5563/// ~~~
5564/// when calling mytree.GetEntry(i); only branches "a" and "b" will be read.
5565///
5566/// __WARNING!!__
5567/// If your Tree has been created in split mode with a parent branch "parent.",
5568/// ~~~ {.cpp}
5569/// mytree.SetBranchStatus("parent",1);
5570/// ~~~
5571/// will not activate the sub-branches of "parent". You should do:
5572/// ~~~ {.cpp}
5573/// mytree.SetBranchStatus("parent*",1);
5574/// ~~~
5575/// Without the trailing dot in the branch creation you have no choice but to
5576/// call SetBranchStatus explicitly for each of the sub branches.
5577///
5578/// An alternative is to call directly
5579/// ~~~ {.cpp}
5580/// brancha.GetEntry(i)
5581/// branchb.GetEntry(i);
5582/// ~~~
5583/// ## IMPORTANT NOTE
5584///
5585/// By default, GetEntry reuses the space allocated by the previous object
5586/// for each branch. You can force the previous object to be automatically
5587/// deleted if you call mybranch.SetAutoDelete(true) (default is false).
5588///
5589/// Example:
5590///
5591/// Consider the example in $ROOTSYS/test/Event.h
5592/// The top level branch in the tree T is declared with:
5593/// ~~~ {.cpp}
5594/// Event *event = 0; //event must be null or point to a valid object
5595/// //it must be initialized
5596/// T.SetBranchAddress("event",&event);
5597/// ~~~
5598/// When reading the Tree, one can choose one of these 3 options:
5599///
5600/// ## OPTION 1
5601///
5602/// ~~~ {.cpp}
5603/// for (Long64_t i=0;i<nentries;i++) {
5604/// T.GetEntry(i);
5605/// // the object event has been filled at this point
5606/// }
5607/// ~~~
5608/// The default (recommended). At the first entry an object of the class
5609/// Event will be created and pointed by event. At the following entries,
5610/// event will be overwritten by the new data. All internal members that are
5611/// TObject* are automatically deleted. It is important that these members
5612/// be in a valid state when GetEntry is called. Pointers must be correctly
5613/// initialized. However these internal members will not be deleted if the
5614/// characters "->" are specified as the first characters in the comment
5615/// field of the data member declaration.
5616///
5617/// If "->" is specified, the pointer member is read via pointer->Streamer(buf).
5618/// In this case, it is assumed that the pointer is never null (case of
5619/// pointer TClonesArray *fTracks in the Event example). If "->" is not
5620/// specified, the pointer member is read via buf >> pointer. In this case
5621/// the pointer may be null. Note that the option with "->" is faster to
5622/// read or write and it also consumes less space in the file.
5623///
5624/// ## OPTION 2
5625///
5626/// The option AutoDelete is set
5627/// ~~~ {.cpp}
5628/// TBranch *branch = T.GetBranch("event");
5629/// branch->SetAddress(&event);
5630/// branch->SetAutoDelete(true);
5631/// for (Long64_t i=0;i<nentries;i++) {
5632/// T.GetEntry(i);
5633/// // the object event has been filled at this point
5634/// }
5635/// ~~~
5636/// In this case, at each iteration, the object event is deleted by GetEntry
5637/// and a new instance of Event is created and filled.
5638///
5639/// ## OPTION 3
5640///
5641/// ~~~ {.cpp}
5642/// Same as option 1, but you delete yourself the event.
5643///
5644/// for (Long64_t i=0;i<nentries;i++) {
5645/// delete event;
5646/// event = 0; // EXTREMELY IMPORTANT
5647/// T.GetEntry(i);
5648/// // the object event has been filled at this point
5649/// }
5650/// ~~~
5651/// It is strongly recommended to use the default option 1. It has the
5652/// additional advantage that functions like TTree::Draw (internally calling
5653/// TTree::GetEntry) will be functional even when the classes in the file are
5654/// not available.
5655///
5656/// Note: See the comments in TBranchElement::SetAddress() for the
5657/// object ownership policy of the underlying (user) data.
5660{
5661 // We already have been visited while recursively looking
5662 // through the friends tree, let return
5663 if (kGetEntry & fFriendLockStatus) return 0;
5664
5665 if (entry < 0 || entry >= fEntries) return 0;
5666 Int_t i;
5667 Int_t nbytes = 0;
5668 fReadEntry = entry;
5669
5670 // create cache if wanted
5671 if (fCacheDoAutoInit)
5673
5675 Int_t nb=0;
5676
5677 auto seqprocessing = [&]() {
5678 TBranch *branch;
5679 for (i=0;i<nbranches;i++) {
5681 nb = branch->GetEntry(entry, getall);
5682 if (nb < 0) break;
5683 nbytes += nb;
5684 }
5685 };
5686
5687#ifdef R__USE_IMT
5689 if (fSortedBranches.empty())
5691
5692 // Count branches are processed first and sequentially
5693 for (auto branch : fSeqBranches) {
5694 nb = branch->GetEntry(entry, getall);
5695 if (nb < 0) break;
5696 nbytes += nb;
5697 }
5698 if (nb < 0) return nb;
5699
5700 // Enable this IMT use case (activate its locks)
5702
5703 Int_t errnb = 0;
5704 std::atomic<Int_t> pos(0);
5705 std::atomic<Int_t> nbpar(0);
5706
5707 auto mapFunction = [&]() {
5708 // The branch to process is obtained when the task starts to run.
5709 // This way, since branches are sorted, we make sure that branches
5710 // leading to big tasks are processed first. If we assigned the
5711 // branch at task creation time, the scheduler would not necessarily
5712 // respect our sorting.
5713 Int_t j = pos.fetch_add(1);
5714
5715 Int_t nbtask = 0;
5716 auto branch = fSortedBranches[j].second;
5717
5718 if (gDebug > 0) {
5719 std::stringstream ss;
5720 ss << std::this_thread::get_id();
5721 Info("GetEntry", "[IMT] Thread %s", ss.str().c_str());
5722 Info("GetEntry", "[IMT] Running task for branch #%d: %s", j, branch->GetName());
5723 }
5724
5725 std::chrono::time_point<std::chrono::system_clock> start, end;
5726
5727 start = std::chrono::system_clock::now();
5728 nbtask = branch->GetEntry(entry, getall);
5729 end = std::chrono::system_clock::now();
5730
5731 Long64_t tasktime = (Long64_t)std::chrono::duration_cast<std::chrono::microseconds>(end - start).count();
5732 fSortedBranches[j].first += tasktime;
5733
5734 if (nbtask < 0) errnb = nbtask;
5735 else nbpar += nbtask;
5736 };
5737
5739 pool.Foreach(mapFunction, fSortedBranches.size());
5740
5741 if (errnb < 0) {
5742 nb = errnb;
5743 }
5744 else {
5745 // Save the number of bytes read by the tasks
5746 nbytes += nbpar;
5747
5748 // Re-sort branches if necessary
5752 }
5753 }
5754 }
5755 else {
5756 seqprocessing();
5757 }
5758#else
5759 seqprocessing();
5760#endif
5761 if (nb < 0) return nb;
5762
5763 // GetEntry in list of friends
5764 if (!fFriends) return nbytes;
5765 TFriendLock lock(this,kGetEntry);
5768 while ((fe = (TFriendElement*)nextf())) {
5769 TTree *t = fe->GetTree();
5770 if (t) {
5771 if (fe->TestBit(TFriendElement::kFromChain)) {
5772 nb = t->GetEntry(t->GetReadEntry(),getall);
5773 } else {
5774 if ( t->LoadTreeFriend(entry,this) >= 0 ) {
5775 nb = t->GetEntry(t->GetReadEntry(),getall);
5776 } else nb = 0;
5777 }
5778 if (nb < 0) return nb;
5779 nbytes += nb;
5780 }
5781 }
5782 return nbytes;
5783}
5784
5785
5786////////////////////////////////////////////////////////////////////////////////
5787/// Divides the top-level branches into two vectors: (i) branches to be
5788/// processed sequentially and (ii) branches to be processed in parallel.
5789/// Even if IMT is on, some branches might need to be processed first and in a
5790/// sequential fashion: in the parallelization of GetEntry, those are the
5791/// branches that store the size of another branch for every entry
5792/// (e.g. the size of an array branch). If such branches were processed
5793/// in parallel with the rest, there could be two threads invoking
5794/// TBranch::GetEntry on one of them at the same time, since a branch that
5795/// depends on a size (or count) branch will also invoke GetEntry on the latter.
5796/// This method can be invoked several times during the event loop if the TTree
5797/// is being written, for example when adding new branches. In these cases, the
5798/// `checkLeafCount` parameter is false.
5799/// \param[in] checkLeafCount True if we need to check whether some branches are
5800/// count leaves.
5803{
5805
5806 // The special branch fBranchRef needs to be processed sequentially:
5807 // we add it once only.
5808 if (fBranchRef && fBranchRef != fSeqBranches[0]) {
5809 fSeqBranches.push_back(fBranchRef);
5810 }
5811
5812 // The branches to be processed sequentially are those that are the leaf count of another branch
5813 if (checkLeafCount) {
5814 for (Int_t i = 0; i < nbranches; i++) {
5816 auto leafCount = ((TLeaf*)branch->GetListOfLeaves()->At(0))->GetLeafCount();
5817 if (leafCount) {
5818 auto countBranch = leafCount->GetBranch();
5819 if (std::find(fSeqBranches.begin(), fSeqBranches.end(), countBranch) == fSeqBranches.end()) {
5820 fSeqBranches.push_back(countBranch);
5821 }
5822 }
5823 }
5824 }
5825
5826 // Any branch that is not a leaf count can be safely processed in parallel when reading
5827 // We need to reset the vector to make sure we do not re-add several times the same branch.
5828 if (!checkLeafCount) {
5829 fSortedBranches.clear();
5830 }
5831 for (Int_t i = 0; i < nbranches; i++) {
5832 Long64_t bbytes = 0;
5834 if (std::find(fSeqBranches.begin(), fSeqBranches.end(), branch) == fSeqBranches.end()) {
5835 bbytes = branch->GetTotBytes("*");
5836 fSortedBranches.emplace_back(bbytes, branch);
5837 }
5838 }
5839
5840 // Initially sort parallel branches by size
5841 std::sort(fSortedBranches.begin(),
5842 fSortedBranches.end(),
5843 [](std::pair<Long64_t,TBranch*> a, std::pair<Long64_t,TBranch*> b) {
5844 return a.first > b.first;
5845 });
5846
5847 for (size_t i = 0; i < fSortedBranches.size(); i++) {
5848 fSortedBranches[i].first = 0LL;
5849 }
5850}
5851
5852////////////////////////////////////////////////////////////////////////////////
5853/// Sorts top-level branches by the last average task time recorded per branch.
5856{
5857 for (size_t i = 0; i < fSortedBranches.size(); i++) {
5859 }
5860
5861 std::sort(fSortedBranches.begin(),
5862 fSortedBranches.end(),
5863 [](std::pair<Long64_t,TBranch*> a, std::pair<Long64_t,TBranch*> b) {
5864 return a.first > b.first;
5865 });
5866
5867 for (size_t i = 0; i < fSortedBranches.size(); i++) {
5868 fSortedBranches[i].first = 0LL;
5869 }
5870}
5871
5872////////////////////////////////////////////////////////////////////////////////
5873///Returns the entry list assigned to this tree
5876{
5877 return fEntryList;
5878}
5879
5880////////////////////////////////////////////////////////////////////////////////
5881/// Return entry number corresponding to entry.
5882///
5883/// if no TEntryList set returns entry
5884/// else returns the entry number corresponding to the list index=entry
5887{
5888 if (!fEntryList) {
5889 return entry;
5890 }
5891
5892 return fEntryList->GetEntry(entry);
5893}
5894
5895////////////////////////////////////////////////////////////////////////////////
5896/// Return entry number corresponding to major and minor number.
5897/// Note that this function returns only the entry number, not the data
5898/// To read the data corresponding to an entry number, use TTree::GetEntryWithIndex
5899/// the BuildIndex function has created a table of Long64_t* of sorted values
5900/// corresponding to val = major<<31 + minor;
5901/// The function performs binary search in this sorted table.
5902/// If it finds a pair that matches val, it returns directly the
5903/// index in the table.
5904/// If an entry corresponding to major and minor is not found, the function
5905/// returns the index of the major,minor pair immediately lower than the
5906/// requested value, ie it will return -1 if the pair is lower than
5907/// the first entry in the index.
5908///
5909/// See also GetEntryNumberWithIndex
5917}
5918
5919////////////////////////////////////////////////////////////////////////////////
5920/// Return entry number corresponding to major and minor number.
5921/// Note that this function returns only the entry number, not the data
5922/// To read the data corresponding to an entry number, use TTree::GetEntryWithIndex
5923/// the BuildIndex function has created a table of Long64_t* of sorted values
5924/// corresponding to val = major<<31 + minor;
5925/// The function performs binary search in this sorted table.
5926/// If it finds a pair that matches val, it returns directly the
5927/// index in the table, otherwise it returns -1.
5928///
5929/// See also GetEntryNumberWithBestIndex
5932{
5933 if (!fTreeIndex) {
5934 return -1;
5935 }
5937}
5938
5939////////////////////////////////////////////////////////////////////////////////
5940/// Read entry corresponding to major and minor number.
5941///
5942/// The function returns the total number of bytes read.
5943/// If the Tree has friend trees, the corresponding entry with
5944/// the index values (major,minor) is read. Note that the master Tree
5945/// and its friend may have different entry serial numbers corresponding
5946/// to (major,minor).
5949{
5950 // We already have been visited while recursively looking
5951 // through the friends tree, let's return.
5953 return 0;
5954 }
5956 if (serial < 0) {
5957 return -1;
5958 }
5959 // create cache if wanted
5960 if (fCacheDoAutoInit)
5962
5963 Int_t i;
5964 Int_t nbytes = 0;
5965 fReadEntry = serial;
5966 TBranch *branch;
5968 Int_t nb;
5969 for (i = 0; i < nbranches; ++i) {
5971 nb = branch->GetEntry(serial);
5972 if (nb < 0) return nb;
5973 nbytes += nb;
5974 }
5975 // GetEntry in list of friends
5976 if (!fFriends) return nbytes;
5979 TFriendElement* fe = nullptr;
5980 while ((fe = (TFriendElement*) nextf())) {
5981 TTree *t = fe->GetTree();
5982 if (t) {
5983 serial = t->GetEntryNumberWithIndex(major,minor);
5984 if (serial <0) return -nbytes;
5985 nb = t->GetEntry(serial);
5986 if (nb < 0) return nb;
5987 nbytes += nb;
5988 }
5989 }
5990 return nbytes;
5991}
5992
5993////////////////////////////////////////////////////////////////////////////////
5994/// Return a pointer to the TTree friend whose name or alias is `friendname`.
5996TTree* TTree::GetFriend(const char *friendname) const
5997{
5998
5999 // We already have been visited while recursively
6000 // looking through the friends tree, let's return.
6002 return nullptr;
6003 }
6004 if (!fFriends) {
6005 return nullptr;
6006 }
6007 TFriendLock lock(const_cast<TTree*>(this), kGetFriend);
6009 TFriendElement* fe = nullptr;
6010 while ((fe = (TFriendElement*) nextf())) {
6011 if (strcmp(friendname,fe->GetName())==0
6012 || strcmp(friendname,fe->GetTreeName())==0) {
6013 return fe->GetTree();
6014 }
6015 }
6016 // After looking at the first level,
6017 // let's see if it is a friend of friends.
6018 nextf.Reset();
6019 fe = nullptr;
6020 while ((fe = (TFriendElement*) nextf())) {
6021 TTree *res = fe->GetTree()->GetFriend(friendname);
6022 if (res) {
6023 return res;
6024 }
6025 }
6026 return nullptr;
6027}
6028
6029////////////////////////////////////////////////////////////////////////////////
6030/// If the 'tree' is a friend, this method returns its alias name.
6031///
6032/// This alias is an alternate name for the tree.
6033///
6034/// It can be used in conjunction with a branch or leaf name in a TTreeFormula,
6035/// to specify in which particular tree the branch or leaf can be found if
6036/// the friend trees have branches or leaves with the same name as the master
6037/// tree.
6038///
6039/// It can also be used in conjunction with an alias created using
6040/// TTree::SetAlias in a TTreeFormula, e.g.:
6041/// ~~~ {.cpp}
6042/// maintree->Draw("treealias.fPx - treealias.myAlias");
6043/// ~~~
6044/// where fPx is a branch of the friend tree aliased as 'treealias' and 'myAlias'
6045/// was created using TTree::SetAlias on the friend tree.
6046///
6047/// However, note that 'treealias.myAlias' will be expanded literally,
6048/// without remembering that it comes from the aliased friend and thus
6049/// the branch name might not be disambiguated properly, which means
6050/// that you may not be able to take advantage of this feature.
6051///
6053const char* TTree::GetFriendAlias(TTree* tree) const
6054{
6055 if ((tree == this) || (tree == GetTree())) {
6056 return nullptr;
6057 }
6058
6059 // We already have been visited while recursively
6060 // looking through the friends tree, let's return.
6062 return nullptr;
6063 }
6064 if (!fFriends) {
6065 return nullptr;
6066 }
6067 TFriendLock lock(const_cast<TTree*>(this), kGetFriendAlias);
6069 TFriendElement* fe = nullptr;
6070 while ((fe = (TFriendElement*) nextf())) {
6071 TTree* t = fe->GetTree();
6072 if (t == tree) {
6073 return fe->GetName();
6074 }
6075 // Case of a chain:
6076 if (t && t->GetTree() == tree) {
6077 return fe->GetName();
6078 }
6079 }
6080 // After looking at the first level,
6081 // let's see if it is a friend of friends.
6082 nextf.Reset();
6083 fe = nullptr;
6084 while ((fe = (TFriendElement*) nextf())) {
6085 const char* res = fe->GetTree()->GetFriendAlias(tree);
6086 if (res) {
6087 return res;
6088 }
6089 }
6090 return nullptr;
6091}
6092
6093////////////////////////////////////////////////////////////////////////////////
6094/// Returns the current set of IO settings
6096{
6097 return fIOFeatures;
6098}
6099
6100////////////////////////////////////////////////////////////////////////////////
6101/// Creates a new iterator that will go through all the leaves on the tree itself and its friend.
6104{
6105 return new TTreeFriendLeafIter(this, dir);
6106}
6107
6108////////////////////////////////////////////////////////////////////////////////
6109/// Return pointer to the 1st Leaf named name in any Branch of this
6110/// Tree or any branch in the list of friend trees.
6111///
6112/// The leaf name can contain the name of a friend tree with the
6113/// syntax: friend_dir_and_tree.full_leaf_name
6114/// the friend_dir_and_tree can be of the form:
6115/// ~~~ {.cpp}
6116/// TDirectoryName/TreeName
6117/// ~~~
6119TLeaf* TTree::GetLeafImpl(const char* branchname, const char *leafname)
6120{
6121 TLeaf *leaf = nullptr;
6122 if (branchname) {
6124 if (branch) {
6125 leaf = branch->GetLeaf(leafname);
6126 if (leaf) {
6127 return leaf;
6128 }
6129 }
6130 }
6132 while ((leaf = (TLeaf*)nextl())) {
6133 if (strcmp(leaf->GetFullName(), leafname) != 0 && strcmp(leaf->GetName(), leafname) != 0)
6134 continue; // leafname does not match GetName() nor GetFullName(), this is not the right leaf
6135 if (branchname) {
6136 // check the branchname is also a match
6137 TBranch *br = leaf->GetBranch();
6138 // if a quick comparison with the branch full name is a match, we are done
6139 if (!strcmp(br->GetFullName(), branchname))
6140 return leaf;
6142 const char* brname = br->GetName();
6143 TBranch *mother = br->GetMother();
6145 if (mother != br) {
6146 const char *mothername = mother->GetName();
6148 if (!strcmp(mothername, branchname)) {
6149 return leaf;
6150 } else if (nbch > motherlen && strncmp(mothername,branchname,motherlen)==0 && (mothername[motherlen-1]=='.' || branchname[motherlen]=='.')) {
6151 // 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.
6153 // No it does not
6154 continue;
6155 } // else we have match so we can proceed.
6156 } else {
6157 // no match
6158 continue;
6159 }
6160 } else {
6161 continue;
6162 }
6163 }
6164 // The start of the branch name is identical to the content
6165 // of 'aname' before the first '/'.
6166 // Let's make sure that it is not longer (we are trying
6167 // to avoid having jet2/value match the branch jet23
6168 if ((strlen(brname) > nbch) && (brname[nbch] != '.') && (brname[nbch] != '[')) {
6169 continue;
6170 }
6171 }
6172 return leaf;
6173 }
6174 if (!fFriends) return nullptr;
6175 TFriendLock lock(this,kGetLeaf);
6176 TIter next(fFriends);
6178 while ((fe = (TFriendElement*)next())) {
6179 TTree *t = fe->GetTree();
6180 if (t) {
6182 if (leaf) return leaf;
6183 }
6184 }
6185
6186 //second pass in the list of friends when the leaf name
6187 //is prefixed by the tree name
6189 next.Reset();
6190 while ((fe = (TFriendElement*)next())) {
6191 TTree *t = fe->GetTree();
6192 if (!t) continue;
6193 const char *subname = strstr(leafname,fe->GetName());
6194 if (subname != leafname) continue;
6195 Int_t l = strlen(fe->GetName());
6196 subname += l;
6197 if (*subname != '.') continue;
6198 subname++;
6201 if (leaf) return leaf;
6202 }
6203 return nullptr;
6204}
6205
6206////////////////////////////////////////////////////////////////////////////////
6207/// Return pointer to the 1st Leaf named name in any Branch of this
6208/// Tree or any branch in the list of friend trees.
6209///
6210/// The leaf name can contain the name of a friend tree with the
6211/// syntax: friend_dir_and_tree.full_leaf_name
6212/// the friend_dir_and_tree can be of the form:
6213///
6214/// TDirectoryName/TreeName
6216TLeaf* TTree::GetLeaf(const char* branchname, const char *leafname)
6217{
6218 if (leafname == nullptr) return nullptr;
6219
6220 // We already have been visited while recursively looking
6221 // through the friends tree, let return
6223 return nullptr;
6224 }
6225
6227}
6228
6229////////////////////////////////////////////////////////////////////////////////
6230/// Return pointer to first leaf named "name" in any branch of this
6231/// tree or its friend trees.
6232///
6233/// \param[in] name may be in the form 'branch/leaf'
6234///
6236TLeaf* TTree::GetLeaf(const char *name)
6237{
6238 // Return nullptr if name is invalid or if we have
6239 // already been visited while searching friend trees
6240 if (!name || (kGetLeaf & fFriendLockStatus))
6241 return nullptr;
6242
6243 std::string path(name);
6244 const auto sep = path.find_last_of('/');
6245 if (sep != std::string::npos)
6246 return GetLeafImpl(path.substr(0, sep).c_str(), name+sep+1);
6247
6248 return GetLeafImpl(nullptr, name);
6249}
6250
6251////////////////////////////////////////////////////////////////////////////////
6252/// Return maximum of column with name columname.
6253/// if the Tree has an associated TEventList or TEntryList, the maximum
6254/// is computed for the entries in this list.
6257{
6258 TLeaf* leaf = this->GetLeaf(columname);
6259 if (!leaf) {
6260 return 0;
6261 }
6262
6263 // create cache if wanted
6264 if (fCacheDoAutoInit)
6266
6267 TBranch* branch = leaf->GetBranch();
6269 for (Long64_t i = 0; i < fEntries; ++i) {
6271 if (entryNumber < 0) break;
6272 branch->GetEntry(entryNumber);
6273 for (Int_t j = 0; j < leaf->GetLen(); ++j) {
6274 Double_t val = leaf->GetValue(j);
6275 if (val > cmax) {
6276 cmax = val;
6277 }
6278 }
6279 }
6280 return cmax;
6281}
6282
6283////////////////////////////////////////////////////////////////////////////////
6284/// Static function which returns the tree file size limit in bytes.
6289}
6290
6291////////////////////////////////////////////////////////////////////////////////
6292/// Return minimum of column with name columname.
6293/// if the Tree has an associated TEventList or TEntryList, the minimum
6294/// is computed for the entries in this list.
6297{
6298 TLeaf* leaf = this->GetLeaf(columname);
6299 if (!leaf) {
6300 return 0;
6301 }
6302
6303 // create cache if wanted
6304 if (fCacheDoAutoInit)
6306
6307 TBranch* branch = leaf->GetBranch();
6309 for (Long64_t i = 0; i < fEntries; ++i) {
6311 if (entryNumber < 0) break;
6312 branch->GetEntry(entryNumber);
6313 for (Int_t j = 0;j < leaf->GetLen(); ++j) {
6314 Double_t val = leaf->GetValue(j);
6315 if (val < cmin) {
6316 cmin = val;
6317 }
6318 }
6319 }
6320 return cmin;
6321}
6322
6323////////////////////////////////////////////////////////////////////////////////
6324/// Load the TTreePlayer (if not already done).
6327{
6328 if (fPlayer) {
6329 return fPlayer;
6330 }
6332 return fPlayer;
6333}
6334
6335////////////////////////////////////////////////////////////////////////////////
6336/// Find and return the TTreeCache registered with the file and which may
6337/// contain branches for us.
6340{
6341 TTreeCache *pe = dynamic_cast<TTreeCache*>(file->GetCacheRead(GetTree()));
6342 if (pe && pe->GetTree() != GetTree())
6343 pe = nullptr;
6344 return pe;
6345}
6346
6347////////////////////////////////////////////////////////////////////////////////
6348/// Find and return the TTreeCache registered with the file and which may
6349/// contain branches for us. If create is true and there is no cache
6350/// a new cache is created with default size.
6352TTreeCache *TTree::GetReadCache(TFile *file, bool create)
6353{
6354 TTreeCache *pe = GetReadCache(file);
6355 if (create && !pe) {
6356 if (fCacheDoAutoInit)
6357 SetCacheSizeAux(true, -1);
6358 pe = dynamic_cast<TTreeCache*>(file->GetCacheRead(GetTree()));
6359 if (pe && pe->GetTree() != GetTree()) pe = nullptr;
6360 }
6361 return pe;
6362}
6363
6364////////////////////////////////////////////////////////////////////////////////
6365/// Return a pointer to the list containing user objects associated to this tree.
6366///
6367/// The list is automatically created if it does not exist.
6368///
6369/// WARNING: By default the TTree destructor will delete all objects added
6370/// to this list. If you do not want these objects to be deleted,
6371/// call:
6372///
6373/// mytree->GetUserInfo()->Clear();
6374///
6375/// before deleting the tree.
6378{
6379 if (!fUserInfo) {
6380 fUserInfo = new TList();
6381 fUserInfo->SetName("UserInfo");
6382 }
6383 return fUserInfo;
6384}
6385
6386////////////////////////////////////////////////////////////////////////////////
6387/// Appends the cluster range information stored in 'fromtree' to this tree,
6388/// including the value of fAutoFlush.
6389///
6390/// This is used when doing a fast cloning (by TTreeCloner).
6391/// See also fAutoFlush and fAutoSave if needed.
6394{
6395 Long64_t autoflush = fromtree->GetAutoFlush();
6396 if (fromtree->fNClusterRange == 0 && fromtree->fAutoFlush == fAutoFlush) {
6397 // nothing to do
6398 } else if (fNClusterRange || fromtree->fNClusterRange) {
6399 Int_t newsize = fNClusterRange + 1 + fromtree->fNClusterRange;
6400 if (newsize > fMaxClusterRange) {
6401 if (fMaxClusterRange) {
6403 newsize*sizeof(Long64_t),fMaxClusterRange*sizeof(Long64_t));
6405 newsize*sizeof(Long64_t),fMaxClusterRange*sizeof(Long64_t));
6407 } else {
6411 }
6412 }
6413 if (fEntries) {
6417 }
6418 for (Int_t i = 0 ; i < fromtree->fNClusterRange; ++i) {
6419 fClusterRangeEnd[fNClusterRange] = fEntries + fromtree->fClusterRangeEnd[i];
6420 fClusterSize[fNClusterRange] = fromtree->fClusterSize[i];
6422 }
6424 } else {
6426 }
6428 if (autoflush > 0 && autosave > 0) {
6430 }
6431}
6432
6433////////////////////////////////////////////////////////////////////////////////
6434/// Keep a maximum of fMaxEntries in memory.
6437{
6440 for (Int_t i = 0; i < nb; ++i) {
6442 branch->KeepCircular(maxEntries);
6443 }
6444 if (fNClusterRange) {
6447 for(Int_t i = 0, j = 0; j < oldsize; ++j) {
6450 ++i;
6451 } else {
6453 }
6454 }
6455 }
6457 fReadEntry = -1;
6458}
6459
6460////////////////////////////////////////////////////////////////////////////////
6461/// Read in memory all baskets from all branches up to the limit of maxmemory bytes.
6462///
6463/// If maxmemory is non null and positive SetMaxVirtualSize is called
6464/// with this value. Default for maxmemory is 2000000000 (2 Gigabytes).
6465/// The function returns the total number of baskets read into memory
6466/// if negative an error occurred while loading the branches.
6467/// This method may be called to force branch baskets in memory
6468/// when random access to branch entries is required.
6469/// If random access to only a few branches is required, you should
6470/// call directly TBranch::LoadBaskets.
6473{
6475
6476 TIter next(GetListOfLeaves());
6477 TLeaf *leaf;
6478 Int_t nimported = 0;
6479 while ((leaf=(TLeaf*)next())) {
6480 nimported += leaf->GetBranch()->LoadBaskets();//break;
6481 }
6482 return nimported;
6483}
6484
6485////////////////////////////////////////////////////////////////////////////////
6486/// Set current entry.
6487///
6488/// Returns -2 if entry does not exist (just as TChain::LoadTree()).
6489/// Returns -6 if an error occurs in the notification callback (just as TChain::LoadTree()).
6490///
6491/// Calls fNotify->Notify() (if fNotify is not null) when starting the processing of a new tree.
6492///
6493/// \note This function is overloaded in TChain.
6495{
6496 // We have already been visited while recursively looking
6497 // through the friend trees, let's return
6499 // We need to return a negative value to avoid a circular list of friends
6500 // to think that there is always an entry somewhere in the list.
6501 return -1;
6502 }
6503
6504 // create cache if wanted
6505 if (fCacheDoAutoInit && entry >=0)
6507
6508 if (fNotify) {
6509 if (fReadEntry < 0) {
6510 fNotify->Notify();
6511 }
6512 }
6513 fReadEntry = entry;
6514
6515 bool friendHasEntry = false;
6516 if (fFriends) {
6517 // Set current entry in friends as well.
6518 //
6519 // An alternative would move this code to each of the
6520 // functions calling LoadTree (and to overload a few more).
6521 bool needUpdate = false;
6522 {
6523 // This scope is need to insure the lock is released at the right time
6525 TFriendLock lock(this, kLoadTree);
6526 TFriendElement* fe = nullptr;
6527 while ((fe = (TFriendElement*) nextf())) {
6528 if (fe->TestBit(TFriendElement::kFromChain)) {
6529 // This friend element was added by the chain that owns this
6530 // tree, the chain will deal with loading the correct entry.
6531 continue;
6532 }
6533 TTree* friendTree = fe->GetTree();
6534 if (friendTree) {
6535 if (friendTree->LoadTreeFriend(entry, this) >= 0) {
6536 friendHasEntry = true;
6537 }
6538 }
6539 if (fe->IsUpdated()) {
6540 needUpdate = true;
6541 fe->ResetUpdated();
6542 }
6543 } // for each friend
6544 }
6545 if (needUpdate) {
6546 //update list of leaves in all TTreeFormula of the TTreePlayer (if any)
6547 if (fPlayer) {
6549 }
6550 //Notify user if requested
6551 if (fNotify) {
6552 if(!fNotify->Notify()) return -6;
6553 }
6554 }
6555 }
6556
6557 if ((fReadEntry >= fEntries) && !friendHasEntry) {
6558 fReadEntry = -1;
6559 return -2;
6560 }
6561 return fReadEntry;
6562}
6563
6564////////////////////////////////////////////////////////////////////////////////
6565/// Load entry on behalf of our master tree, we may use an index.
6566///
6567/// Called by LoadTree() when the masterTree looks for the entry
6568/// number in a friend tree (us) corresponding to the passed entry
6569/// number in the masterTree.
6570///
6571/// If we have no index, our entry number and the masterTree entry
6572/// number are the same.
6573///
6574/// If we *do* have an index, we must find the (major, minor) value pair
6575/// in masterTree to locate our corresponding entry.
6576///
6584}
6585
6586////////////////////////////////////////////////////////////////////////////////
6587/// Generate a skeleton analysis class for this tree.
6588///
6589/// The following files are produced: classname.h and classname.C.
6590/// If classname is 0, classname will be called "nameoftree".
6591///
6592/// The generated code in classname.h includes the following:
6593///
6594/// - Identification of the original tree and the input file name.
6595/// - Definition of an analysis class (data members and member functions).
6596/// - The following member functions:
6597/// - constructor (by default opening the tree file),
6598/// - GetEntry(Long64_t entry),
6599/// - Init(TTree* tree) to initialize a new TTree,
6600/// - Show(Long64_t entry) to read and dump entry.
6601///
6602/// The generated code in classname.C includes only the main
6603/// analysis function Loop.
6604///
6605/// To use this function:
6606///
6607/// - Open your tree file (eg: TFile f("myfile.root");)
6608/// - T->MakeClass("MyClass");
6609///
6610/// where T is the name of the TTree in file myfile.root,
6611/// and MyClass.h, MyClass.C the name of the files created by this function.
6612/// In a ROOT session, you can do:
6613/// ~~~ {.cpp}
6614/// root > .L MyClass.C
6615/// root > MyClass* t = new MyClass;
6616/// root > t->GetEntry(12); // Fill data members of t with entry number 12.
6617/// root > t->Show(); // Show values of entry 12.
6618/// root > t->Show(16); // Read and show values of entry 16.
6619/// root > t->Loop(); // Loop on all entries.
6620/// ~~~
6621/// NOTE: Do not use the code generated for a single TTree which is part
6622/// of a TChain to process that entire TChain. The maximum dimensions
6623/// calculated for arrays on the basis of a single TTree from the TChain
6624/// might be (will be!) too small when processing all of the TTrees in
6625/// the TChain. You must use myChain.MakeClass() to generate the code,
6626/// not myTree.MakeClass(...).
6628Int_t TTree::MakeClass(const char* classname, Option_t* option)
6629{
6630 GetPlayer();
6631 if (!fPlayer) {
6632 return 0;
6633 }
6634 return fPlayer->MakeClass(classname, option);
6635}
6636
6637////////////////////////////////////////////////////////////////////////////////
6638/// Generate a skeleton function for this tree.
6639///
6640/// The function code is written on filename.
6641/// If filename is 0, filename will be called nameoftree.C
6642///
6643/// The generated code includes the following:
6644/// - Identification of the original Tree and Input file name,
6645/// - Opening the Tree file,
6646/// - Declaration of Tree variables,
6647/// - Setting of branches addresses,
6648/// - A skeleton for the entry loop.
6649///
6650/// To use this function:
6651///
6652/// - Open your Tree file (eg: TFile f("myfile.root");)
6653/// - T->MakeCode("MyAnalysis.C");
6654///
6655/// where T is the name of the TTree in file myfile.root
6656/// and MyAnalysis.C the name of the file created by this function.
6657///
6658/// NOTE: Since the implementation of this function, a new and better
6659/// function TTree::MakeClass() has been developed.
6661Int_t TTree::MakeCode(const char* filename)
6662{
6663 Warning("MakeCode", "MakeCode is obsolete. Use MakeClass or MakeSelector instead");
6664
6665 GetPlayer();
6666 if (!fPlayer) return 0;
6667 return fPlayer->MakeCode(filename);
6668}
6669
6670////////////////////////////////////////////////////////////////////////////////
6671/// Generate a skeleton analysis class for this Tree using TBranchProxy.
6672///
6673/// TBranchProxy is the base of a class hierarchy implementing an
6674/// indirect access to the content of the branches of a TTree.
6675///
6676/// "proxyClassname" is expected to be of the form:
6677/// ~~~ {.cpp}
6678/// [path/]fileprefix
6679/// ~~~
6680/// The skeleton will then be generated in the file:
6681/// ~~~ {.cpp}
6682/// fileprefix.h
6683/// ~~~
6684/// located in the current directory or in 'path/' if it is specified.
6685/// The class generated will be named 'fileprefix'
6686///
6687/// "macrofilename" and optionally "cutfilename" are expected to point
6688/// to source files which will be included by the generated skeleton.
6689/// Method of the same name as the file(minus the extension and path)
6690/// will be called by the generated skeleton's Process method as follow:
6691/// ~~~ {.cpp}
6692/// [if (cutfilename())] htemp->Fill(macrofilename());
6693/// ~~~
6694/// "option" can be used select some of the optional features during
6695/// the code generation. The possible options are:
6696///
6697/// - nohist : indicates that the generated ProcessFill should not fill the histogram.
6698///
6699/// 'maxUnrolling' controls how deep in the class hierarchy does the
6700/// system 'unroll' classes that are not split. Unrolling a class
6701/// allows direct access to its data members (this emulates the behavior
6702/// of TTreeFormula).
6703///
6704/// The main features of this skeleton are:
6705///
6706/// * on-demand loading of branches
6707/// * ability to use the 'branchname' as if it was a data member
6708/// * protection against array out-of-bounds errors
6709/// * ability to use the branch data as an object (when the user code is available)
6710///
6711/// For example with Event.root, if
6712/// ~~~ {.cpp}
6713/// Double_t somePx = fTracks.fPx[2];
6714/// ~~~
6715/// is executed by one of the method of the skeleton,
6716/// somePx will updated with the current value of fPx of the 3rd track.
6717///
6718/// Both macrofilename and the optional cutfilename are expected to be
6719/// the name of source files which contain at least a free standing
6720/// function with the signature:
6721/// ~~~ {.cpp}
6722/// x_t macrofilename(); // i.e function with the same name as the file
6723/// ~~~
6724/// and
6725/// ~~~ {.cpp}
6726/// y_t cutfilename(); // i.e function with the same name as the file
6727/// ~~~
6728/// x_t and y_t needs to be types that can convert respectively to a double
6729/// and a bool (because the skeleton uses:
6730///
6731/// if (cutfilename()) htemp->Fill(macrofilename());
6732///
6733/// These two functions are run in a context such that the branch names are
6734/// available as local variables of the correct (read-only) type.
6735///
6736/// Note that if you use the same 'variable' twice, it is more efficient
6737/// to 'cache' the value. For example:
6738/// ~~~ {.cpp}
6739/// Int_t n = fEventNumber; // Read fEventNumber
6740/// if (n<10 || n>10) { ... }
6741/// ~~~
6742/// is more efficient than
6743/// ~~~ {.cpp}
6744/// if (fEventNumber<10 || fEventNumber>10)
6745/// ~~~
6746/// Also, optionally, the generated selector will also call methods named
6747/// macrofilename_methodname in each of 6 main selector methods if the method
6748/// macrofilename_methodname exist (Where macrofilename is stripped of its
6749/// extension).
6750///
6751/// Concretely, with the script named h1analysisProxy.C,
6752///
6753/// - The method calls the method (if it exist)
6754/// - Begin -> void h1analysisProxy_Begin(TTree*);
6755/// - SlaveBegin -> void h1analysisProxy_SlaveBegin(TTree*);
6756/// - Notify -> bool h1analysisProxy_Notify();
6757/// - Process -> bool h1analysisProxy_Process(Long64_t);
6758/// - SlaveTerminate -> void h1analysisProxy_SlaveTerminate();
6759/// - Terminate -> void h1analysisProxy_Terminate();
6760///
6761/// If a file name macrofilename.h (or .hh, .hpp, .hxx, .hPP, .hXX) exist
6762/// it is included before the declaration of the proxy class. This can
6763/// be used in particular to insure that the include files needed by
6764/// the macro file are properly loaded.
6765///
6766/// The default histogram is accessible via the variable named 'htemp'.
6767///
6768/// If the library of the classes describing the data in the branch is
6769/// loaded, the skeleton will add the needed `include` statements and
6770/// give the ability to access the object stored in the branches.
6771///
6772/// To draw px using the file hsimple.root (generated by the
6773/// hsimple.C tutorial), we need a file named hsimple.cxx:
6774/// ~~~ {.cpp}
6775/// double hsimple() {
6776/// return px;
6777/// }
6778/// ~~~
6779/// MakeProxy can then be used indirectly via the TTree::Draw interface
6780/// as follow:
6781/// ~~~ {.cpp}
6782/// new TFile("hsimple.root")
6783/// ntuple->Draw("hsimple.cxx");
6784/// ~~~
6785/// A more complete example is available in the tutorials directory:
6786/// h1analysisProxy.cxx , h1analysProxy.h and h1analysisProxyCut.C
6787/// which reimplement the selector found in h1analysis.C
6789Int_t TTree::MakeProxy(const char* proxyClassname, const char* macrofilename, const char* cutfilename, const char* option, Int_t maxUnrolling)
6790{
6791 GetPlayer();
6792 if (!fPlayer) return 0;
6794}
6795
6796////////////////////////////////////////////////////////////////////////////////
6797/// Generate skeleton selector class for this tree.
6798///
6799/// The following files are produced: selector.h and selector.C.
6800/// If selector is 0, the selector will be called "nameoftree".
6801/// The option can be used to specify the branches that will have a data member.
6802/// - If option is "=legacy", a pre-ROOT6 selector will be generated (data
6803/// members and branch pointers instead of TTreeReaders).
6804/// - If option is empty, readers will be generated for each leaf.
6805/// - If option is "@", readers will be generated for the topmost branches.
6806/// - Individual branches can also be picked by their name:
6807/// - "X" generates readers for leaves of X.
6808/// - "@X" generates a reader for X as a whole.
6809/// - "@X;Y" generates a reader for X as a whole and also readers for the
6810/// leaves of Y.
6811/// - For further examples see the figure below.
6812///
6813/// \image html ttree_makeselector_option_examples.png
6814///
6815/// The generated code in selector.h includes the following:
6816/// - Identification of the original Tree and Input file name
6817/// - Definition of selector class (data and functions)
6818/// - The following class functions:
6819/// - constructor and destructor
6820/// - void Begin(TTree *tree)
6821/// - void SlaveBegin(TTree *tree)
6822/// - void Init(TTree *tree)
6823/// - bool Notify()
6824/// - bool Process(Long64_t entry)
6825/// - void Terminate()
6826/// - void SlaveTerminate()
6827///
6828/// The class selector derives from TSelector.
6829/// The generated code in selector.C includes empty functions defined above.
6830///
6831/// To use this function:
6832///
6833/// - connect your Tree file (eg: `TFile f("myfile.root");`)
6834/// - `T->MakeSelector("myselect");`
6835///
6836/// where T is the name of the Tree in file myfile.root
6837/// and myselect.h, myselect.C the name of the files created by this function.
6838/// In a ROOT session, you can do:
6839/// ~~~ {.cpp}
6840/// root > T->Process("myselect.C")
6841/// ~~~
6843Int_t TTree::MakeSelector(const char* selector, Option_t* option)
6844{
6845 TString opt(option);
6846 if(opt.EqualTo("=legacy", TString::ECaseCompare::kIgnoreCase)) {
6847 return MakeClass(selector, "selector");
6848 } else {
6849 GetPlayer();
6850 if (!fPlayer) return 0;
6851 return fPlayer->MakeReader(selector, option);
6852 }
6853}
6854
6855////////////////////////////////////////////////////////////////////////////////
6856/// Check if adding nbytes to memory we are still below MaxVirtualsize.
6859{
6861 return false;
6862 }
6863 return true;
6864}
6865
6866////////////////////////////////////////////////////////////////////////////////
6867/// Static function merging the trees in the TList into a new tree.
6868///
6869/// Trees in the list can be memory or disk-resident trees.
6870/// The new tree is created in the current directory (memory if gROOT).
6871/// Trees with no branches will be skipped, the branch structure
6872/// will be taken from the first non-zero-branch Tree of {li}
6875{
6876 if (!li) return nullptr;
6877 TIter next(li);
6878 TTree *newtree = nullptr;
6879 TObject *obj;
6880
6881 while ((obj=next())) {
6882 if (!obj->InheritsFrom(TTree::Class())) continue;
6883 TTree *tree = (TTree*)obj;
6884 if (tree->GetListOfBranches()->IsEmpty()) {
6885 if (gDebug > 2) {
6886 tree->Warning("MergeTrees","TTree %s has no branches, skipping.", tree->GetName());
6887 }
6888 continue; // Completely ignore the empty trees.
6889 }
6890 Long64_t nentries = tree->GetEntries();
6891 if (newtree && nentries == 0)
6892 continue; // If we already have the structure and we have no entry, save time and skip
6893 if (!newtree) {
6894 newtree = (TTree*)tree->CloneTree(-1, options);
6895 if (!newtree) continue;
6896
6897 // Once the cloning is done, separate the trees,
6898 // to avoid as many side-effects as possible
6899 // The list of clones is guaranteed to exist since we
6900 // just cloned the tree.
6901 tree->GetListOfClones()->Remove(newtree);
6902 tree->ResetBranchAddresses();
6903 newtree->ResetBranchAddresses();
6904 continue;
6905 }
6906 if (nentries == 0)
6907 continue;
6908 newtree->CopyEntries(tree, -1, options, true);
6909 }
6910 if (newtree && newtree->GetTreeIndex()) {
6911 newtree->GetTreeIndex()->Append(nullptr,false); // Force the sorting
6912 }
6913 return newtree;
6914}
6915
6916////////////////////////////////////////////////////////////////////////////////
6917/// Merge the trees in the TList into this tree.
6918///
6919/// Returns the total number of entries in the merged tree.
6920/// Trees with no branches will be skipped, the branch structure
6921/// will be taken from the first non-zero-branch Tree of {this+li}
6924{
6925 if (fBranches.IsEmpty()) {
6926 if (!li || li->IsEmpty())
6927 return 0; // Nothing to do ....
6928 // Let's find the first non-empty
6929 TIter next(li);
6930 TTree *tree;
6931 while ((tree = (TTree *)next())) {
6932 if (tree == this || tree->GetListOfBranches()->IsEmpty()) {
6933 if (gDebug > 2) {
6934 Warning("Merge","TTree %s has no branches, skipping.", tree->GetName());
6935 }
6936 continue;
6937 }
6938 // We could come from a list made up of different names, the first one still wins
6939 tree->SetName(this->GetName());
6940 auto prevEntries = tree->GetEntries();
6941 auto result = tree->Merge(li, options);
6942 if (result != prevEntries) {
6943 // If there is no additional entries, the first write was enough.
6944 tree->Write();
6945 }
6946 // Make sure things are really written out to disk before attempting any reading.
6947 if (tree->GetCurrentFile()) {
6948 tree->GetCurrentFile()->Flush();
6949 // Read back the complete info in this TTree, so that caller does not
6950 // inadvertently write the empty tree.
6951 tree->GetDirectory()->ReadTObject(this, this->GetName());
6952 }
6953 return result;
6954 }
6955 return 0; // All trees have empty branches
6956 }
6957 if (!li) return 0;
6959 // Disable the autosave as the TFileMerge keeps a list of key and deleting the underlying
6960 // key would invalidate its iteration (or require costly measure to not use the deleted keys).
6961 // Also since this is part of a merging operation, the output file is not as precious as in
6962 // the general case since the input file should still be around.
6963 fAutoSave = 0;
6964 TIter next(li);
6965 TTree *tree;
6966 while ((tree = (TTree*)next())) {
6967 if (tree==this) continue;
6968 if (!tree->InheritsFrom(TTree::Class())) {
6969 Error("Add","Attempt to add object of class: %s to a %s", tree->ClassName(), ClassName());
6971 return -1;
6972 }
6973
6974 Long64_t nentries = tree->GetEntries();
6975 if (nentries == 0) continue;
6976
6977 CopyEntries(tree, -1, options, true);
6978 }
6980 return GetEntries();
6981}
6982
6983////////////////////////////////////////////////////////////////////////////////
6984/// Merge the trees in the TList into this tree.
6985/// If info->fIsFirst is true, first we clone this TTree info the directory
6986/// info->fOutputDirectory and then overlay the new TTree information onto
6987/// this TTree object (so that this TTree object is now the appropriate to
6988/// use for further merging).
6989/// Trees with no branches will be skipped, the branch structure
6990/// will be taken from the first non-zero-branch Tree of {this+li}
6991///
6992/// Returns the total number of entries in the merged tree.
6995{
6996 if (fBranches.IsEmpty()) {
6997 if (!li || li->IsEmpty())
6998 return 0; // Nothing to do ....
6999 // Let's find the first non-empty
7000 TIter next(li);
7001 TTree *tree;
7002 while ((tree = (TTree *)next())) {
7003 if (tree == this || tree->GetListOfBranches()->IsEmpty()) {
7004 if (gDebug > 2) {
7005 Warning("Merge","TTree %s has no branches, skipping.", tree->GetName());
7006 }
7007 continue;
7008 }
7009 // We could come from a list made up of different names, the first one still wins
7010 tree->SetName(this->GetName());
7011 auto prevEntries = tree->GetEntries();
7012 auto result = tree->Merge(li, info);
7013 if (result != prevEntries) {
7014 // If there is no additional entries, the first write was enough.
7015 tree->Write();
7016 }
7017 // Make sure things are really written out to disk before attempting any reading.
7018 info->fOutputDirectory->GetFile()->Flush();
7019 // Read back the complete info in this TTree, so that TFileMerge does not
7020 // inadvertently write the empty tree.
7021 info->fOutputDirectory->ReadTObject(this, this->GetName());
7022 return result;
7023 }
7024 return 0; // All trees have empty branches
7025 }
7026 const char *options = info ? info->fOptions.Data() : "";
7027 if (info && info->fIsFirst && info->fOutputDirectory && info->fOutputDirectory->GetFile() != GetCurrentFile()) {
7028 if (GetCurrentFile() == nullptr) {
7029 // In memory TTree, all we need to do is ... write it.
7030 SetDirectory(info->fOutputDirectory);
7032 fDirectory->WriteTObject(this);
7033 } else if (info->fOptions.Contains("fast")) {
7034 InPlaceClone(info->fOutputDirectory);
7035 } else {
7036 TDirectory::TContext ctxt(info->fOutputDirectory);
7038 TTree *newtree = CloneTree(-1, options);
7039 if (info->fIOFeatures)
7040 fIOFeatures = *(info->fIOFeatures);
7041 else
7043 if (newtree) {
7044 newtree->Write();
7045 delete newtree;
7046 }
7047 // Make sure things are really written out to disk before attempting any reading.
7048 info->fOutputDirectory->GetFile()->Flush();
7049 info->fOutputDirectory->ReadTObject(this,this->GetName());
7050 }
7051 }
7052 if (!li) return 0;
7054 // Disable the autosave as the TFileMerge keeps a list of key and deleting the underlying
7055 // key would invalidate its iteration (or require costly measure to not use the deleted keys).
7056 // Also since this is part of a merging operation, the output file is not as precious as in
7057 // the general case since the input file should still be around.
7058 fAutoSave = 0;
7059 TIter next(li);
7060 TTree *tree;
7061 while ((tree = (TTree*)next())) {
7062 if (tree==this) continue;
7063 if (!tree->InheritsFrom(TTree::Class())) {
7064 Error("Add","Attempt to add object of class: %s to a %s", tree->ClassName(), ClassName());
7066 return -1;
7067 }
7068
7069 CopyEntries(tree, -1, options, true);
7070 }
7072 return GetEntries();
7073}
7074
7075////////////////////////////////////////////////////////////////////////////////
7076/// Move a cache from a file to the current file in dir.
7077/// if src is null no operation is done, if dir is null or there is no
7078/// current file the cache is deleted.
7081{
7082 if (!src) return;
7083 TFile *dst = (dir && dir != gROOT) ? dir->GetFile() : nullptr;
7084 if (src == dst) return;
7085
7087 if (dst) {
7088 src->SetCacheRead(nullptr,this);
7089 dst->SetCacheRead(pf, this);
7090 } else {
7091 if (pf) {
7092 pf->WaitFinishPrefetch();
7093 }
7094 src->SetCacheRead(nullptr,this);
7095 delete pf;
7096 }
7097}
7098
7099////////////////////////////////////////////////////////////////////////////////
7100/// Copy the content to a new new file, update this TTree with the new
7101/// location information and attach this TTree to the new directory.
7102///
7103/// options: Indicates a basket sorting method, see TTreeCloner::TTreeCloner for
7104/// details
7105///
7106/// If new and old directory are in the same file, the data is untouched,
7107/// this "just" does a call to SetDirectory.
7108/// Equivalent to an "in place" cloning of the TTree.
7109bool TTree::InPlaceClone(TDirectory *newdirectory, const char *options)
7110{
7111 if (!newdirectory) {
7113 SetDirectory(nullptr);
7114 return true;
7115 }
7116 if (newdirectory->GetFile() == GetCurrentFile()) {
7118 return true;
7119 }
7120 TTreeCloner cloner(this, newdirectory, options);
7121 if (cloner.IsValid())
7122 return cloner.Exec();
7123 else
7124 return false;
7125}
7126
7127////////////////////////////////////////////////////////////////////////////////
7128/// Function called when loading a new class library.
7130bool TTree::Notify()
7131{
7132 TIter next(GetListOfLeaves());
7133 TLeaf* leaf = nullptr;
7134 while ((leaf = (TLeaf*) next())) {
7135 leaf->Notify();
7136 leaf->GetBranch()->Notify();
7137 }
7138 return true;
7139}
7140
7141////////////////////////////////////////////////////////////////////////////////
7142/// This function may be called after having filled some entries in a Tree.
7143/// Using the information in the existing branch buffers, it will reassign
7144/// new branch buffer sizes to optimize time and memory.
7145///
7146/// The function computes the best values for branch buffer sizes such that
7147/// the total buffer sizes is less than maxMemory and nearby entries written
7148/// at the same time.
7149/// In case the branch compression factor for the data written so far is less
7150/// than compMin, the compression is disabled.
7151///
7152/// if option ="d" an analysis report is printed.
7155{
7156 //Flush existing baskets if the file is writable
7157 if (this->GetDirectory()->IsWritable()) this->FlushBasketsImpl();
7158
7159 TString opt( option );
7160 opt.ToLower();
7161 bool pDebug = opt.Contains("d");
7162 TObjArray *leaves = this->GetListOfLeaves();
7163 Int_t nleaves = leaves->GetEntries();
7165
7166 if (nleaves == 0 || treeSize == 0) {
7167 // We're being called too early, we really have nothing to do ...
7168 return;
7169 }
7171 UInt_t bmin = 512;
7172 UInt_t bmax = 256000;
7173 Double_t memFactor = 1;
7176
7177 //we make two passes
7178 //one pass to compute the relative branch buffer sizes
7179 //a second pass to compute the absolute values
7180 for (Int_t pass =0;pass<2;pass++) {
7181 oldMemsize = 0; //to count size of baskets in memory with old buffer size
7182 newMemsize = 0; //to count size of baskets in memory with new buffer size
7183 oldBaskets = 0; //to count number of baskets with old buffer size
7184 newBaskets = 0; //to count number of baskets with new buffer size
7185 for (i=0;i<nleaves;i++) {
7186 TLeaf *leaf = (TLeaf*)leaves->At(i);
7187 TBranch *branch = leaf->GetBranch();
7188 Double_t totBytes = (Double_t)branch->GetTotBytes();
7191 if (branch->GetEntries() == 0) {
7192 // There is no data, so let's make a guess ...
7194 } else {
7195 sizeOfOneEntry = 1+(UInt_t)(totBytes / (Double_t)branch->GetEntries());
7196 }
7197 Int_t oldBsize = branch->GetBasketSize();
7200 Int_t nb = branch->GetListOfBranches()->GetEntries();
7201 if (nb > 0) {
7203 continue;
7204 }
7205 Double_t bsize = oldBsize*idealFactor*memFactor; //bsize can be very large !
7206 if (bsize < 0) bsize = bmax;
7207 if (bsize > bmax) bsize = bmax;
7209 if (pass) { // only on the second pass so that it doesn't interfere with scaling
7210 // If there is an entry offset, it will be stored in the same buffer as the object data; hence,
7211 // we must bump up the size of the branch to account for this extra footprint.
7212 // If fAutoFlush is not set yet, let's assume that it is 'in the process of being set' to
7213 // the value of GetEntries().
7214 Long64_t clusterSize = (fAutoFlush > 0) ? fAutoFlush : branch->GetEntries();
7215 if (branch->GetEntryOffsetLen()) {
7216 newBsize = newBsize + (clusterSize * sizeof(Int_t) * 2);
7217 }
7218 // We used ATLAS fully-split xAOD for testing, which is a rather unbalanced TTree, 10K branches,
7219 // with 8K having baskets smaller than 512 bytes. To achieve good I/O performance ATLAS uses auto-flush 100,
7220 // resulting in the smallest baskets being ~300-400 bytes, so this change increases their memory by about 8k*150B =~ 1MB,
7221 // at the same time it significantly reduces the number of total baskets because it ensures that all 100 entries can be
7222 // stored in a single basket (the old optimization tended to make baskets too small). In a toy example with fixed sized
7223 // structures we found a factor of 2 fewer baskets needed in the new scheme.
7224 // rounds up, increases basket size to ensure all entries fit into single basket as intended
7225 newBsize = newBsize - newBsize%512 + 512;
7226 }
7228 if (newBsize < bmin) newBsize = bmin;
7229 if (newBsize > 10000000) newBsize = bmax;
7230 if (pass) {
7231 if (pDebug) Info("OptimizeBaskets", "Changing buffer size from %6d to %6d bytes for %s\n",oldBsize,newBsize,branch->GetName());
7232 branch->SetBasketSize(newBsize);
7233 }
7235 // For this number to be somewhat accurate when newBsize is 'low'
7236 // we do not include any space for meta data in the requested size (newBsize) even-though SetBasketSize will
7237 // not let it be lower than 100+TBranch::fEntryOffsetLen.
7239 if (pass == 0) continue;
7240 //Reset the compression level in case the compression factor is small
7241 Double_t comp = 1;
7242 if (branch->GetZipBytes() > 0) comp = totBytes/Double_t(branch->GetZipBytes());
7243 if (comp > 1 && comp < minComp) {
7244 if (pDebug) Info("OptimizeBaskets", "Disabling compression for branch : %s\n",branch->GetName());
7246 }
7247 }
7248 // coverity[divide_by_zero] newMemsize can not be zero as there is at least one leaf
7250 if (memFactor > 100) memFactor = 100;
7253 static const UInt_t hardmax = 1*1024*1024*1024; // Really, really never give more than 1Gb to a single buffer.
7254
7255 // Really, really never go lower than 8 bytes (we use this number
7256 // so that the calculation of the number of basket is consistent
7257 // but in fact SetBasketSize will not let the size go below
7258 // TBranch::fEntryOffsetLen + (100 + strlen(branch->GetName())
7259 // (The 2nd part being a slight over estimate of the key length.
7260 static const UInt_t hardmin = 8;
7263 }
7264 if (pDebug) {
7265 Info("OptimizeBaskets", "oldMemsize = %d, newMemsize = %d\n",oldMemsize, newMemsize);
7266 Info("OptimizeBaskets", "oldBaskets = %d, newBaskets = %d\n",oldBaskets, newBaskets);
7267 }
7268}
7269
7270////////////////////////////////////////////////////////////////////////////////
7271/// Interface to the Principal Components Analysis class.
7272///
7273/// Create an instance of TPrincipal
7274///
7275/// Fill it with the selected variables
7276///
7277/// - if option "n" is specified, the TPrincipal object is filled with
7278/// normalized variables.
7279/// - If option "p" is specified, compute the principal components
7280/// - If option "p" and "d" print results of analysis
7281/// - If option "p" and "h" generate standard histograms
7282/// - If option "p" and "c" generate code of conversion functions
7283/// - return a pointer to the TPrincipal object. It is the user responsibility
7284/// - to delete this object.
7285/// - The option default value is "np"
7286///
7287/// see TTree::Draw for explanation of the other parameters.
7288///
7289/// The created object is named "principal" and a reference to it
7290/// is added to the list of specials Root objects.
7291/// you can retrieve a pointer to the created object via:
7292/// ~~~ {.cpp}
7293/// TPrincipal *principal =
7294/// (TPrincipal*)gROOT->GetListOfSpecials()->FindObject("principal");
7295/// ~~~
7298{
7299 GetPlayer();
7300 if (fPlayer) {
7302 }
7303 return nullptr;
7304}
7305
7306////////////////////////////////////////////////////////////////////////////////
7307/// Print a summary of the tree contents.
7308///
7309/// - If option contains "all" friend trees are also printed.
7310/// - If option contains "toponly" only the top level branches are printed.
7311/// - If option contains "clusters" information about the cluster of baskets is printed.
7312///
7313/// Wildcarding can be used to print only a subset of the branches, e.g.,
7314/// `T.Print("Elec*")` will print all branches with name starting with "Elec".
7316void TTree::Print(Option_t* option) const
7317{
7318 // We already have been visited while recursively looking
7319 // through the friends tree, let's return.
7320 if (kPrint & fFriendLockStatus) {
7321 return;
7322 }
7323 Int_t s = 0;
7324 Int_t skey = 0;
7325 if (fDirectory) {
7326 TKey* key = fDirectory->GetKey(GetName());
7327 if (key) {
7328 skey = key->GetKeylen();
7329 s = key->GetNbytes();
7330 }
7331 }
7334 if (zipBytes > 0) {
7335 total += GetTotBytes();
7336 }
7338 TTree::Class()->WriteBuffer(b, (TTree*) this);
7339 total += b.Length();
7340 Long64_t file = zipBytes + s;
7341 Float_t cx = 1;
7342 if (zipBytes) {
7343 cx = (GetTotBytes() + 0.00001) / zipBytes;
7344 }
7345 Printf("******************************************************************************");
7346 Printf("*Tree :%-10s: %-54s *", GetName(), GetTitle());
7347 Printf("*Entries : %8lld : Total = %15lld bytes File Size = %10lld *", fEntries, total, file);
7348 Printf("* : : Tree compression factor = %6.2f *", cx);
7349 Printf("******************************************************************************");
7350
7351 // Avoid many check of option validity
7352 if (!option)
7353 option = "";
7354
7355 if (strncmp(option,"clusters",std::char_traits<char>::length("clusters"))==0) {
7356 Printf("%-16s %-16s %-16s %8s %20s",
7357 "Cluster Range #", "Entry Start", "Last Entry", "Size", "Number of clusters");
7358 Int_t index= 0;
7361 bool estimated = false;
7362 bool unknown = false;
7364 Long64_t nclusters = 0;
7365 if (recordedSize > 0) {
7366 nclusters = TMath::Ceil(static_cast<double>(1 + end - start) / recordedSize);
7367 Printf("%-16d %-16lld %-16lld %8lld %10lld",
7368 ind, start, end, recordedSize, nclusters);
7369 } else {
7370 // NOTE: const_cast ... DO NOT Merge for now
7371 TClusterIterator iter((TTree*)this, start);
7372 iter.Next();
7373 auto estimated_size = iter.GetNextEntry() - start;
7374 if (estimated_size > 0) {
7375 nclusters = TMath::Ceil(static_cast<double>(1 + end - start) / estimated_size);
7376 Printf("%-16d %-16lld %-16lld %8lld %10lld (estimated)",
7377 ind, start, end, recordedSize, nclusters);
7378 estimated = true;
7379 } else {
7380 Printf("%-16d %-16lld %-16lld %8lld (unknown)",
7381 ind, start, end, recordedSize);
7382 unknown = true;
7383 }
7384 }
7385 start = end + 1;
7387 };
7388 if (fNClusterRange) {
7389 for( ; index < fNClusterRange; ++index) {
7392 }
7393 }
7395 if (unknown) {
7396 Printf("Total number of clusters: (unknown)");
7397 } else {
7398 Printf("Total number of clusters: %lld %s", totalClusters, estimated ? "(estimated)" : "");
7399 }
7400 return;
7401 }
7402
7403 Int_t nl = const_cast<TTree*>(this)->GetListOfLeaves()->GetEntries();
7404 Int_t l;
7405 TBranch* br = nullptr;
7406 TLeaf* leaf = nullptr;
7407 if (strstr(option, "toponly")) {
7408 Long64_t *count = new Long64_t[nl];
7409 Int_t keep =0;
7410 for (l=0;l<nl;l++) {
7411 leaf = (TLeaf *)const_cast<TTree*>(this)->GetListOfLeaves()->At(l);
7412 br = leaf->GetBranch();
7413 // branch is its own (top level) mother only for the top level branches.
7414 if (br != br->GetMother()) {
7415 count[l] = -1;
7416 count[keep] += br->GetZipBytes();
7417 } else {
7418 keep = l;
7419 count[keep] = br->GetZipBytes();
7420 }
7421 }
7422 for (l=0;l<nl;l++) {
7423 if (count[l] < 0) continue;
7424 leaf = (TLeaf *)const_cast<TTree*>(this)->GetListOfLeaves()->At(l);
7425 br = leaf->GetBranch();
7426 Printf("branch: %-20s %9lld",br->GetName(),count[l]);
7427 }
7428 delete [] count;
7429 } else {
7430 TString reg = "*";
7431 if (strlen(option) && strchr(option,'*')) reg = option;
7432 TRegexp re(reg,true);
7433 TIter next(const_cast<TTree*>(this)->GetListOfBranches());
7435 while ((br= (TBranch*)next())) {
7436 TString st = br->GetName();
7437 st.ReplaceAll("/","_");
7438 if (st.Index(re) == kNPOS) continue;
7439 br->Print(option);
7440 }
7441 }
7442
7443 //print TRefTable (if one)
7445
7446 //print friends if option "all"
7447 if (!fFriends || !strstr(option,"all")) return;
7449 TFriendLock lock(const_cast<TTree*>(this),kPrint);
7450 TFriendElement *fr;
7451 while ((fr = (TFriendElement*)nextf())) {
7452 TTree * t = fr->GetTree();
7453 if (t) t->Print(option);
7454 }
7455}
7456
7457////////////////////////////////////////////////////////////////////////////////
7458/// Print statistics about the TreeCache for this tree.
7459/// Like:
7460/// ~~~ {.cpp}
7461/// ******TreeCache statistics for file: cms2.root ******
7462/// Reading 73921562 bytes in 716 transactions
7463/// Average transaction = 103.242405 Kbytes
7464/// Number of blocks in current cache: 202, total size : 6001193
7465/// ~~~
7466/// if option = "a" the list of blocks in the cache is printed
7469{
7470 TFile *f = GetCurrentFile();
7471 if (!f) return;
7473 if (tc) tc->Print(option);
7474}
7475
7476////////////////////////////////////////////////////////////////////////////////
7477/// Process this tree executing the TSelector code in the specified filename.
7478/// The return value is -1 in case of error and TSelector::GetStatus() in
7479/// in case of success.
7480///
7481/// The code in filename is loaded (interpreted or compiled, see below),
7482/// filename must contain a valid class implementation derived from TSelector,
7483/// where TSelector has the following member functions:
7484///
7485/// - `Begin()`: called every time a loop on the tree starts,
7486/// a convenient place to create your histograms.
7487/// - `SlaveBegin()`: called after Begin(), when on PROOF called only on the
7488/// slave servers.
7489/// - `Process()`: called for each event, in this function you decide what
7490/// to read and fill your histograms.
7491/// - `SlaveTerminate`: called at the end of the loop on the tree, when on PROOF
7492/// called only on the slave servers.
7493/// - `Terminate()`: called at the end of the loop on the tree,
7494/// a convenient place to draw/fit your histograms.
7495///
7496/// If filename is of the form file.C, the file will be interpreted.
7497///
7498/// If filename is of the form file.C++, the file file.C will be compiled
7499/// and dynamically loaded.
7500///
7501/// If filename is of the form file.C+, the file file.C will be compiled
7502/// and dynamically loaded. At next call, if file.C is older than file.o
7503/// and file.so, the file.C is not compiled, only file.so is loaded.
7504///
7505/// ## NOTE1
7506///
7507/// It may be more interesting to invoke directly the other Process function
7508/// accepting a TSelector* as argument.eg
7509/// ~~~ {.cpp}
7510/// MySelector *selector = (MySelector*)TSelector::GetSelector(filename);
7511/// selector->CallSomeFunction(..);
7512/// mytree.Process(selector,..);
7513/// ~~~
7514/// ## NOTE2
7515//
7516/// One should not call this function twice with the same selector file
7517/// in the same script. If this is required, proceed as indicated in NOTE1,
7518/// by getting a pointer to the corresponding TSelector,eg
7519///
7520/// ### Workaround 1
7521///
7522/// ~~~ {.cpp}
7523/// void stubs1() {
7524/// TSelector *selector = TSelector::GetSelector("h1test.C");
7525/// TFile *f1 = new TFile("stubs_nood_le1.root");
7526/// TTree *h1 = (TTree*)f1->Get("h1");
7527/// h1->Process(selector);
7528/// TFile *f2 = new TFile("stubs_nood_le1_coarse.root");
7529/// TTree *h2 = (TTree*)f2->Get("h1");
7530/// h2->Process(selector);
7531/// }
7532/// ~~~
7533/// or use ACLIC to compile the selector
7534///
7535/// ### Workaround 2
7536///
7537/// ~~~ {.cpp}
7538/// void stubs2() {
7539/// TFile *f1 = new TFile("stubs_nood_le1.root");
7540/// TTree *h1 = (TTree*)f1->Get("h1");
7541/// h1->Process("h1test.C+");
7542/// TFile *f2 = new TFile("stubs_nood_le1_coarse.root");
7543/// TTree *h2 = (TTree*)f2->Get("h1");
7544/// h2->Process("h1test.C+");
7545/// }
7546/// ~~~
7549{
7550 GetPlayer();
7551 if (fPlayer) {
7553 }
7554 return -1;
7555}
7556
7557////////////////////////////////////////////////////////////////////////////////
7558/// Process this tree executing the code in the specified selector.
7559/// The return value is -1 in case of error and TSelector::GetStatus() in
7560/// in case of success.
7561///
7562/// The TSelector class has the following member functions:
7563///
7564/// - `Begin()`: called every time a loop on the tree starts,
7565/// a convenient place to create your histograms.
7566/// - `SlaveBegin()`: called after Begin(), when on PROOF called only on the
7567/// slave servers.
7568/// - `Process()`: called for each event, in this function you decide what
7569/// to read and fill your histograms.
7570/// - `SlaveTerminate`: called at the end of the loop on the tree, when on PROOF
7571/// called only on the slave servers.
7572/// - `Terminate()`: called at the end of the loop on the tree,
7573/// a convenient place to draw/fit your histograms.
7574///
7575/// If the Tree (Chain) has an associated EventList, the loop is on the nentries
7576/// of the EventList, starting at firstentry, otherwise the loop is on the
7577/// specified Tree entries.
7580{
7581 GetPlayer();
7582 if (fPlayer) {
7583 return fPlayer->Process(selector, option, nentries, firstentry);
7584 }
7585 return -1;
7586}
7587
7588////////////////////////////////////////////////////////////////////////////////
7589/// Make a projection of a tree using selections.
7590///
7591/// Depending on the value of varexp (described in Draw) a 1-D, 2-D, etc.,
7592/// projection of the tree will be filled in histogram hname.
7593/// Note that the dimension of hname must match with the dimension of varexp.
7594///
7597{
7598 TString var;
7599 var.Form("%s>>%s", varexp, hname);
7600 TString opt("goff");
7601 if (option) {
7602 opt.Form("%sgoff", option);
7603 }
7605 return nsel;
7606}
7607
7608////////////////////////////////////////////////////////////////////////////////
7609/// Loop over entries and return a TSQLResult object containing entries following selection.
7612{
7613 GetPlayer();
7614 if (fPlayer) {
7616 }
7617 return nullptr;
7618}
7619
7620////////////////////////////////////////////////////////////////////////////////
7621/// Create or simply read branches from filename.
7622///
7623/// if branchDescriptor = "" (default), it is assumed that the Tree descriptor
7624/// is given in the first line of the file with a syntax like
7625/// ~~~ {.cpp}
7626/// A/D:Table[2]/F:Ntracks/I:astring/C
7627/// ~~~
7628/// otherwise branchDescriptor must be specified with the above syntax.
7629///
7630/// - If the type of the first variable is not specified, it is assumed to be "/F"
7631/// - If the type of any other variable is not specified, the type of the previous
7632/// variable is assumed. eg
7633/// - `x:y:z` (all variables are assumed of type "F")
7634/// - `x/D:y:z` (all variables are of type "D")
7635/// - `x:y/D:z` (x is type "F", y and z of type "D")
7636///
7637/// delimiter allows for the use of another delimiter besides whitespace.
7638/// This provides support for direct import of common data file formats
7639/// like csv. If delimiter != ' ' and branchDescriptor == "", then the
7640/// branch description is taken from the first line in the file, but
7641/// delimiter is used for the branch names tokenization rather than ':'.
7642/// Note however that if the values in the first line do not use the
7643/// /[type] syntax, all variables are assumed to be of type "F".
7644/// If the filename ends with extensions .csv or .CSV and a delimiter is
7645/// not specified (besides ' '), the delimiter is automatically set to ','.
7646///
7647/// Lines in the input file starting with "#" are ignored. Leading whitespace
7648/// for each column data is skipped. Empty lines are skipped.
7649///
7650/// A TBranch object is created for each variable in the expression.
7651/// The total number of rows read from the file is returned.
7652///
7653/// ## FILLING a TTree WITH MULTIPLE INPUT TEXT FILES
7654///
7655/// To fill a TTree with multiple input text files, proceed as indicated above
7656/// for the first input file and omit the second argument for subsequent calls
7657/// ~~~ {.cpp}
7658/// T.ReadFile("file1.dat","branch descriptor");
7659/// T.ReadFile("file2.dat");
7660/// ~~~
7662Long64_t TTree::ReadFile(const char* filename, const char* branchDescriptor, char delimiter)
7663{
7664 if (!filename || !*filename) {
7665 Error("ReadFile","File name not specified");
7666 return 0;
7667 }
7668
7669 std::ifstream in;
7670 in.open(filename);
7671 if (!in.good()) {
7672 Error("ReadFile","Cannot open file: %s",filename);
7673 return 0;
7674 }
7675 const char* ext = strrchr(filename, '.');
7676 if(ext && ((strcmp(ext, ".csv") == 0) || (strcmp(ext, ".CSV") == 0)) && delimiter == ' ') {
7677 delimiter = ',';
7678 }
7680}
7681
7682////////////////////////////////////////////////////////////////////////////////
7683/// Determine which newline this file is using.
7684/// Return '\\r' for Windows '\\r\\n' as that already terminates.
7686char TTree::GetNewlineValue(std::istream &inputStream)
7687{
7688 Long_t inPos = inputStream.tellg();
7689 char newline = '\n';
7690 while(true) {
7691 char c = 0;
7692 inputStream.get(c);
7693 if(!inputStream.good()) {
7694 Error("ReadStream","Error reading stream: no newline found.");
7695 return 0;
7696 }
7697 if(c == newline) break;
7698 if(c == '\r') {
7699 newline = '\r';
7700 break;
7701 }
7702 }
7703 inputStream.clear();
7704 inputStream.seekg(inPos);
7705 return newline;
7706}
7707
7708////////////////////////////////////////////////////////////////////////////////
7709/// Create or simply read branches from an input stream.
7710///
7711/// \see TTree::ReadFile
7713Long64_t TTree::ReadStream(std::istream& inputStream, const char *branchDescriptor, char delimiter)
7714{
7715 char newline = 0;
7716 std::stringstream ss;
7717 std::istream *inTemp;
7718 Long_t inPos = inputStream.tellg();
7719 if (!inputStream.good()) {
7720 Error("ReadStream","Error reading stream");
7721 return 0;
7722 }
7723 if (inPos == -1) {
7724 ss << std::cin.rdbuf();
7726 inTemp = &ss;
7727 } else {
7730 }
7731 std::istream& in = *inTemp;
7732 Long64_t nlines = 0;
7733
7734 TBranch *branch = nullptr;
7736 if (nbranches == 0) {
7737 char *bdname = new char[4000];
7738 char *bd = new char[100000];
7739 Int_t nch = 0;
7741 // branch Descriptor is null, read its definition from the first line in the file
7742 if (!nch) {
7743 do {
7744 in.getline(bd, 100000, newline);
7745 if (!in.good()) {
7746 delete [] bdname;
7747 delete [] bd;
7748 Error("ReadStream","Error reading stream");
7749 return 0;
7750 }
7751 char *cursor = bd;
7752 while( isspace(*cursor) && *cursor != '\n' && *cursor != '\0') {
7753 ++cursor;
7754 }
7755 if (*cursor != '#' && *cursor != '\n' && *cursor != '\0') {
7756 break;
7757 }
7758 } while (true);
7759 ++nlines;
7760 nch = strlen(bd);
7761 } else {
7762 strlcpy(bd,branchDescriptor,100000);
7763 }
7764
7765 //parse the branch descriptor and create a branch for each element
7766 //separated by ":"
7767 void *address = &bd[90000];
7768 char *bdcur = bd;
7769 TString desc="", olddesc="F";
7770 char bdelim = ':';
7771 if(delimiter != ' ') {
7772 bdelim = delimiter;
7773 if (strchr(bdcur,bdelim)==nullptr && strchr(bdcur,':') != nullptr) {
7774 // revert to the default
7775 bdelim = ':';
7776 }
7777 }
7778 while (bdcur) {
7779 char *colon = strchr(bdcur,bdelim);
7780 if (colon) *colon = 0;
7781 strlcpy(bdname,bdcur,4000);
7782 char *slash = strchr(bdname,'/');
7783 if (slash) {
7784 *slash = 0;
7785 desc = bdcur;
7786 olddesc = slash+1;
7787 } else {
7788 desc.Form("%s/%s",bdname,olddesc.Data());
7789 }
7790 char *bracket = strchr(bdname,'[');
7791 if (bracket) {
7792 *bracket = 0;
7793 }
7794 branch = new TBranch(this,bdname,address,desc.Data(),32000);
7795 if (branch->IsZombie()) {
7796 delete branch;
7797 Warning("ReadStream","Illegal branch definition: %s",bdcur);
7798 } else {
7800 branch->SetAddress(nullptr);
7801 }
7802 if (!colon)break;
7803 bdcur = colon+1;
7804 }
7805 delete [] bdname;
7806 delete [] bd;
7807 }
7808
7810
7811 if (gDebug > 1) {
7812 Info("ReadStream", "Will use branches:");
7813 for (int i = 0 ; i < nbranches; ++i) {
7814 TBranch* br = (TBranch*) fBranches.At(i);
7815 Info("ReadStream", " %s: %s [%s]", br->GetName(),
7816 br->GetTitle(), br->GetListOfLeaves()->At(0)->IsA()->GetName());
7817 }
7818 if (gDebug > 3) {
7819 Info("ReadStream", "Dumping read tokens, format:");
7820 Info("ReadStream", "LLLLL:BBB:gfbe:GFBE:T");
7821 Info("ReadStream", " L: line number");
7822 Info("ReadStream", " B: branch number");
7823 Info("ReadStream", " gfbe: good / fail / bad / eof of token");
7824 Info("ReadStream", " GFBE: good / fail / bad / eof of file");
7825 Info("ReadStream", " T: Token being read");
7826 }
7827 }
7828
7829 //loop on all lines in the file
7830 Long64_t nGoodLines = 0;
7831 std::string line;
7832 const char sDelimBuf[2] = { delimiter, 0 };
7833 const char* sDelim = sDelimBuf;
7834 if (delimiter == ' ') {
7835 // ' ' really means whitespace
7836 sDelim = "[ \t]";
7837 }
7838 while(in.good()) {
7839 if (newline == '\r' && in.peek() == '\n') {
7840 // Windows, skip '\n':
7841 in.get();
7842 }
7843 std::getline(in, line, newline);
7844 ++nlines;
7845
7847 sLine = sLine.Strip(TString::kLeading); // skip leading whitespace
7848 if (sLine.IsNull()) {
7849 if (gDebug > 2) {
7850 Info("ReadStream", "Skipping empty line number %lld", nlines);
7851 }
7852 continue; // silently skip empty lines
7853 }
7854 if (sLine[0] == '#') {
7855 if (gDebug > 2) {
7856 Info("ReadStream", "Skipping comment line number %lld: '%s'",
7857 nlines, line.c_str());
7858 }
7859 continue;
7860 }
7861 if (gDebug > 2) {
7862 Info("ReadStream", "Parsing line number %lld: '%s'",
7863 nlines, line.c_str());
7864 }
7865
7866 // Loop on branches and read the branch values into their buffer
7867 branch = nullptr;
7868 TString tok; // one column's data
7869 TString leafData; // leaf data, possibly multiple tokens for e.g. /I[2]
7870 std::stringstream sToken; // string stream feeding leafData into leaves
7871 Ssiz_t pos = 0;
7872 Int_t iBranch = 0;
7873 bool goodLine = true; // whether the row can be filled into the tree
7874 Int_t remainingLeafLen = 0; // remaining columns for the current leaf
7875 while (goodLine && iBranch < nbranches
7876 && sLine.Tokenize(tok, pos, sDelim)) {
7877 tok = tok.Strip(TString::kLeading); // skip leading whitespace
7878 if (tok.IsNull() && delimiter == ' ') {
7879 // 1 2 should not be interpreted as 1,,,2 but 1, 2.
7880 // Thus continue until we have a non-empty token.
7881 continue;
7882 }
7883
7884 if (!remainingLeafLen) {
7885 // next branch!
7887 }
7888 TLeaf *leaf = (TLeaf*)branch->GetListOfLeaves()->At(0);
7889 if (!remainingLeafLen) {
7890 remainingLeafLen = leaf->GetLen();
7891 if (leaf->GetMaximum() > 0) {
7892 // This is a dynamic leaf length, i.e. most likely a TLeafC's
7893 // string size. This still translates into one token:
7894 remainingLeafLen = 1;
7895 }
7896
7897 leafData = tok;
7898 } else {
7899 // append token to laf data:
7900 leafData += " ";
7901 leafData += tok;
7902 }
7904 if (remainingLeafLen) {
7905 // need more columns for this branch:
7906 continue;
7907 }
7908 ++iBranch;
7909
7910 // initialize stringstream with token
7911 sToken.clear();
7912 sToken.seekp(0, std::ios_base::beg);
7913 sToken.str(leafData.Data());
7914 sToken.seekg(0, std::ios_base::beg);
7915 leaf->ReadValue(sToken, 0 /* 0 = "all" */);
7916 if (gDebug > 3) {
7917 Info("ReadStream", "%5lld:%3d:%d%d%d%d:%d%d%d%d:%s",
7918 nlines, iBranch,
7919 (int)sToken.good(), (int)sToken.fail(),
7920 (int)sToken.bad(), (int)sToken.eof(),
7921 (int)in.good(), (int)in.fail(),
7922 (int)in.bad(), (int)in.eof(),
7923 sToken.str().c_str());
7924 }
7925
7926 // Error handling
7927 if (sToken.bad()) {
7928 // How could that happen for a stringstream?
7929 Warning("ReadStream",
7930 "Buffer error while reading data for branch %s on line %lld",
7931 branch->GetName(), nlines);
7932 } else if (!sToken.eof()) {
7933 if (sToken.fail()) {
7934 Warning("ReadStream",
7935 "Couldn't read formatted data in \"%s\" for branch %s on line %lld; ignoring line",
7936 tok.Data(), branch->GetName(), nlines);
7937 goodLine = false;
7938 } else {
7939 std::string remainder;
7940 std::getline(sToken, remainder, newline);
7941 if (!remainder.empty()) {
7942 Warning("ReadStream",
7943 "Ignoring trailing \"%s\" while reading data for branch %s on line %lld",
7944 remainder.c_str(), branch->GetName(), nlines);
7945 }
7946 }
7947 }
7948 } // tokenizer loop
7949
7950 if (iBranch < nbranches) {
7951 Warning("ReadStream",
7952 "Read too few columns (%d < %d) in line %lld; ignoring line",
7954 goodLine = false;
7955 } else if (pos != kNPOS) {
7957 if (pos < sLine.Length()) {
7958 Warning("ReadStream",
7959 "Ignoring trailing \"%s\" while reading line %lld",
7960 sLine.Data() + pos - 1 /* also print delimiter */,
7961 nlines);
7962 }
7963 }
7964
7965 //we are now ready to fill the tree
7966 if (goodLine) {
7967 Fill();
7968 ++nGoodLines;
7969 }
7970 }
7971
7972 return nGoodLines;
7973}
7974
7975////////////////////////////////////////////////////////////////////////////////
7976/// Make sure that obj (which is being deleted or will soon be) is no
7977/// longer referenced by this TTree.
7980{
7981 if (obj == fEventList) {
7982 fEventList = nullptr;
7983 }
7984 if (obj == fEntryList) {
7985 fEntryList = nullptr;
7986 }
7987 if (fUserInfo) {
7989 }
7990 if (fPlayer == obj) {
7991 fPlayer = nullptr;
7992 }
7993 if (fTreeIndex == obj) {
7994 fTreeIndex = nullptr;
7995 }
7996 if (fAliases == obj) {
7997 fAliases = nullptr;
7998 } else if (fAliases) {
8000 }
8001 if (fFriends == obj) {
8002 fFriends = nullptr;
8003 } else if (fFriends) {
8005 }
8006}
8007
8008////////////////////////////////////////////////////////////////////////////////
8009/// Refresh contents of this tree and its branches from the current status on disk.
8010///
8011/// One can call this function in case the tree file is being
8012/// updated by another process.
8014void TTree::Refresh()
8015{
8016 if (!fDirectory->GetFile()) {
8017 return;
8018 }
8020 fDirectory->Remove(this);
8021 TTree* tree; fDirectory->GetObject(GetName(),tree);
8022 if (!tree) {
8023 return;
8024 }
8025 //copy info from tree header into this Tree
8026 fEntries = 0;
8027 fNClusterRange = 0;
8028 ImportClusterRanges(tree);
8029
8030 fAutoSave = tree->fAutoSave;
8031 fEntries = tree->fEntries;
8032 fTotBytes = tree->GetTotBytes();
8033 fZipBytes = tree->GetZipBytes();
8034 fSavedBytes = tree->fSavedBytes;
8035 fTotalBuffers = tree->fTotalBuffers.load();
8036
8037 //loop on all branches and update them
8039 for (Int_t i = 0; i < nleaves; i++) {
8041 TBranch* branch = (TBranch*) leaf->GetBranch();
8042 branch->Refresh(tree->GetBranch(branch->GetName()));
8043 }
8044 fDirectory->Remove(tree);
8045 fDirectory->Append(this);
8046 delete tree;
8047 tree = nullptr;
8048}
8049
8050////////////////////////////////////////////////////////////////////////////////
8051/// Record a TFriendElement that we need to warn when the chain switches to
8052/// a new file (typically this is because this chain is a friend of another
8053/// TChain)
8060}
8061
8062
8063////////////////////////////////////////////////////////////////////////////////
8064/// Removes external friend
8069}
8070
8071
8072////////////////////////////////////////////////////////////////////////////////
8073/// Remove a friend from the list of friends.
8076{
8077 // We already have been visited while recursively looking
8078 // through the friends tree, let return
8080 return;
8081 }
8082 if (!fFriends) {
8083 return;
8084 }
8085 TFriendLock lock(this, kRemoveFriend);
8087 TFriendElement* fe = nullptr;
8088 while ((fe = (TFriendElement*) nextf())) {
8089 TTree* friend_t = fe->GetTree();
8090 if (friend_t == oldFriend) {
8091 fFriends->Remove(fe);
8092 delete fe;
8093 fe = nullptr;
8094 }
8095 }
8096}
8097
8098////////////////////////////////////////////////////////////////////////////////
8099/// Reset baskets, buffers and entries count in all branches and leaves.
8102{
8103 fNotify = nullptr;
8104 fEntries = 0;
8105 fNClusterRange = 0;
8106 fTotBytes = 0;
8107 fZipBytes = 0;
8108 fFlushedBytes = 0;
8109 fSavedBytes = 0;
8110 fTotalBuffers = 0;
8111 fChainOffset = 0;
8112 fReadEntry = -1;
8113
8114 delete fTreeIndex;
8115 fTreeIndex = nullptr;
8116
8118 for (Int_t i = 0; i < nb; ++i) {
8120 branch->Reset(option);
8121 }
8122
8123 if (fBranchRef) {
8124 fBranchRef->Reset();
8125 }
8126}
8127
8128////////////////////////////////////////////////////////////////////////////////
8129/// Resets the state of this TTree after a merge (keep the customization but
8130/// forget the data).
8133{
8134 fEntries = 0;
8135 fNClusterRange = 0;
8136 fTotBytes = 0;
8137 fZipBytes = 0;
8138 fSavedBytes = 0;
8139 fFlushedBytes = 0;
8140 fTotalBuffers = 0;
8141 fChainOffset = 0;
8142 fReadEntry = -1;
8143
8144 delete fTreeIndex;
8145 fTreeIndex = nullptr;
8146
8148 for (Int_t i = 0; i < nb; ++i) {
8150 branch->ResetAfterMerge(info);
8151 }
8152
8153 if (fBranchRef) {
8155 }
8156}
8157
8158////////////////////////////////////////////////////////////////////////////////
8159/// Tell a branch to set its address to zero.
8160///
8161/// @note If the branch owns any objects, they are deleted.
8164{
8165 if (br && br->GetTree()) {
8166 br->ResetAddress();
8167 }
8168}
8169
8170////////////////////////////////////////////////////////////////////////////////
8171/// Tell all of our branches to drop their current objects and allocate new ones.
8174{
8175 // We already have been visited while recursively looking
8176 // through the friends tree, let return
8178 return;
8179 }
8181 Int_t nbranches = branches->GetEntriesFast();
8182 for (Int_t i = 0; i < nbranches; ++i) {
8183 TBranch* branch = (TBranch*) branches->UncheckedAt(i);
8184 branch->ResetAddress();
8185 }
8186 if (fFriends) {
8189 auto *frTree = frEl->GetTree();
8190 if (frTree) {
8191 frTree->ResetBranchAddresses();
8192 }
8193 }
8194 }
8195}
8196
8197////////////////////////////////////////////////////////////////////////////////
8198/// Loop over tree entries and print entries passing selection. Interactive
8199/// pagination break is on by default.
8200///
8201/// - If varexp is 0 (or "") then print only first 8 columns.
8202/// - If varexp = "*" print all columns.
8203///
8204/// Otherwise a columns selection can be made using "var1:var2:var3".
8205///
8206/// \param firstentry first entry to scan
8207/// \param nentries total number of entries to scan (starting from firstentry). Defaults to all entries.
8208/// \note see TTree::SetScanField to control how many lines are printed between pagination breaks (Use 0 to disable pagination)
8209/// \see TTreePlayer::Scan
8212{
8213 GetPlayer();
8214 if (fPlayer) {
8216 }
8217 return -1;
8218}
8219
8220////////////////////////////////////////////////////////////////////////////////
8221/// Set a tree variable alias.
8222///
8223/// Set an alias for an expression/formula based on the tree 'variables'.
8224///
8225/// The content of 'aliasName' can be used in TTreeFormula (i.e. TTree::Draw,
8226/// TTree::Scan, TTreeViewer) and will be evaluated as the content of
8227/// 'aliasFormula'.
8228///
8229/// If the content of 'aliasFormula' only contains symbol names, periods and
8230/// array index specification (for example event.fTracks[3]), then
8231/// the content of 'aliasName' can be used as the start of symbol.
8232///
8233/// If the alias 'aliasName' already existed, it is replaced by the new
8234/// value.
8235///
8236/// When being used, the alias can be preceded by an eventual 'Friend Alias'
8237/// (see TTree::GetFriendAlias)
8238///
8239/// Return true if it was added properly.
8240///
8241/// For example:
8242/// ~~~ {.cpp}
8243/// tree->SetAlias("x1","(tdc1[1]-tdc1[0])/49");
8244/// tree->SetAlias("y1","(tdc1[3]-tdc1[2])/47");
8245/// tree->SetAlias("x2","(tdc2[1]-tdc2[0])/49");
8246/// tree->SetAlias("y2","(tdc2[3]-tdc2[2])/47");
8247/// tree->Draw("y2-y1:x2-x1");
8248///
8249/// tree->SetAlias("theGoodTrack","event.fTracks[3]");
8250/// tree->Draw("theGoodTrack.fPx"); // same as "event.fTracks[3].fPx"
8251/// ~~~
8253bool TTree::SetAlias(const char* aliasName, const char* aliasFormula)
8254{
8255 if (!aliasName || !aliasFormula) {
8256 return false;
8257 }
8258 if (!aliasName[0] || !aliasFormula[0]) {
8259 return false;
8260 }
8261 if (!fAliases) {
8262 fAliases = new TList;
8263 } else {
8265 if (oldHolder) {
8266 oldHolder->SetTitle(aliasFormula);
8267 return true;
8268 }
8269 }
8272 return true;
8273}
8274
8275////////////////////////////////////////////////////////////////////////////////
8276/// This function may be called at the start of a program to change
8277/// the default value for fAutoFlush.
8278///
8279/// ### CASE 1 : autof > 0
8280///
8281/// autof is the number of consecutive entries after which TTree::Fill will
8282/// flush all branch buffers to disk.
8283///
8284/// ### CASE 2 : autof < 0
8285///
8286/// When filling the Tree the branch buffers will be flushed to disk when
8287/// more than autof bytes have been written to the file. At the first FlushBaskets
8288/// TTree::Fill will replace fAutoFlush by the current value of fEntries.
8289///
8290/// Calling this function with autof<0 is interesting when it is hard to estimate
8291/// the size of one entry. This value is also independent of the Tree.
8292///
8293/// The Tree is initialized with fAutoFlush=-30000000, ie that, by default,
8294/// the first AutoFlush will be done when 30 MBytes of data are written to the file.
8295///
8296/// ### CASE 3 : autof = 0
8297///
8298/// The AutoFlush mechanism is disabled.
8299///
8300/// Flushing the buffers at regular intervals optimize the location of
8301/// consecutive entries on the disk by creating clusters of baskets.
8302///
8303/// A cluster of baskets is a set of baskets that contains all
8304/// the data for a (consecutive) set of entries and that is stored
8305/// consecutively on the disk. When reading all the branches, this
8306/// is the minimum set of baskets that the TTreeCache will read.
8308void TTree::SetAutoFlush(Long64_t autof /* = -30000000 */ )
8309{
8310 // Implementation note:
8311 //
8312 // A positive value of autoflush determines the size (in number of entries) of
8313 // a cluster of baskets.
8314 //
8315 // If the value of autoflush is changed over time (this happens in
8316 // particular when the TTree results from fast merging many trees),
8317 // we record the values of fAutoFlush in the data members:
8318 // fClusterRangeEnd and fClusterSize.
8319 // In the code we refer to a range of entries where the size of the
8320 // cluster of baskets is the same (i.e the value of AutoFlush was
8321 // constant) is called a ClusterRange.
8322 //
8323 // The 2 arrays (fClusterRangeEnd and fClusterSize) have fNClusterRange
8324 // active (used) values and have fMaxClusterRange allocated entries.
8325 //
8326 // fClusterRangeEnd contains the last entries number of a cluster range.
8327 // In particular this means that the 'next' cluster starts at fClusterRangeEnd[]+1
8328 // fClusterSize contains the size in number of entries of all the cluster
8329 // within the given range.
8330 // The last range (and the only one if fNClusterRange is zero) start at
8331 // fNClusterRange[fNClusterRange-1]+1 and ends at the end of the TTree. The
8332 // size of the cluster in this range is given by the value of fAutoFlush.
8333 //
8334 // For example printing the beginning and end of each the ranges can be done by:
8335 //
8336 // Printf("%-16s %-16s %-16s %5s",
8337 // "Cluster Range #", "Entry Start", "Last Entry", "Size");
8338 // Int_t index= 0;
8339 // Long64_t clusterRangeStart = 0;
8340 // if (fNClusterRange) {
8341 // for( ; index < fNClusterRange; ++index) {
8342 // Printf("%-16d %-16lld %-16lld %5lld",
8343 // index, clusterRangeStart, fClusterRangeEnd[index], fClusterSize[index]);
8344 // clusterRangeStart = fClusterRangeEnd[index] + 1;
8345 // }
8346 // }
8347 // Printf("%-16d %-16lld %-16lld %5lld",
8348 // index, prevEntry, fEntries - 1, fAutoFlush);
8349 //
8350
8351 // Note: We store the entry number corresponding to the end of the cluster
8352 // rather than its start in order to avoid using the array if the cluster
8353 // size never varies (If there is only one value of AutoFlush for the whole TTree).
8354
8355 if( fAutoFlush != autof) {
8356 if ((fAutoFlush > 0 || autof > 0) && fFlushedBytes) {
8357 // The mechanism was already enabled, let's record the previous
8358 // cluster if needed.
8360 }
8361 fAutoFlush = autof;
8362 }
8363}
8364
8365////////////////////////////////////////////////////////////////////////////////
8366/// Mark the previous event as being at the end of the event cluster.
8367///
8368/// So, if fEntries is set to 10 (and this is the first cluster) when MarkEventCluster
8369/// is called, then the first cluster has 9 events.
8371{
8372 if (!fEntries) return;
8373
8374 if ( (fNClusterRange+1) > fMaxClusterRange ) {
8375 if (fMaxClusterRange) {
8376 // Resize arrays to hold a larger event cluster.
8379 newsize*sizeof(Long64_t),fMaxClusterRange*sizeof(Long64_t));
8381 newsize*sizeof(Long64_t),fMaxClusterRange*sizeof(Long64_t));
8383 } else {
8384 // Cluster ranges have never been initialized; create them now.
8385 fMaxClusterRange = 2;
8388 }
8389 }
8391 // If we are auto-flushing, then the cluster size is the same as the current auto-flush setting.
8392 if (fAutoFlush > 0) {
8393 // Even if the user triggers MarkEventRange prior to fAutoFlush being present, the TClusterIterator
8394 // will appropriately go to the next event range.
8396 // Otherwise, assume there is one cluster per event range (e.g., user is manually controlling the flush).
8397 } else if (fNClusterRange == 0) {
8399 } else {
8401 }
8403}
8404
8405/// Estimate the median cluster size for the TTree.
8406/// This value provides e.g. a reasonable cache size default if other heuristics fail.
8407/// Clusters with size 0 and the very last cluster range, that might not have been committed to fClusterSize yet,
8408/// are ignored for the purposes of the calculation.
8410{
8411 std::vector<Long64_t> clusterSizesPerRange;
8413
8414 // We ignore cluster sizes of 0 for the purposes of this function.
8415 // We also ignore the very last cluster range which might not have been committed to fClusterSize.
8416 std::copy_if(fClusterSize, fClusterSize + fNClusterRange, std::back_inserter(clusterSizesPerRange),
8417 [](Long64_t size) { return size != 0; });
8418
8419 std::vector<double> nClustersInRange; // we need to store doubles because of the signature of TMath::Median
8420 nClustersInRange.reserve(clusterSizesPerRange.size());
8421
8422 auto clusterRangeStart = 0ll;
8423 for (int i = 0; i < fNClusterRange; ++i) {
8424 const auto size = fClusterSize[i];
8425 R__ASSERT(size >= 0);
8426 if (fClusterSize[i] == 0)
8427 continue;
8428 const auto nClusters = (1 + fClusterRangeEnd[i] - clusterRangeStart) / fClusterSize[i];
8429 nClustersInRange.emplace_back(nClusters);
8431 }
8432
8434 const auto medianClusterSize =
8436 return medianClusterSize;
8437}
8438
8439////////////////////////////////////////////////////////////////////////////////
8440/// In case of a program crash, it will be possible to recover the data in the
8441/// tree up to the last AutoSave point.
8442/// This function may be called before filling a TTree to specify when the
8443/// branch buffers and TTree header are flushed to disk as part of
8444/// TTree::Fill().
8445/// The default is -300000000, ie the TTree will write data to disk once it
8446/// exceeds 300 MBytes.
8447/// CASE 1: If fAutoSave is positive the watermark is reached when a multiple of
8448/// fAutoSave entries have been filled.
8449/// CASE 2: If fAutoSave is negative the watermark is reached when -fAutoSave
8450/// bytes can be written to the file.
8451/// CASE 3: If fAutoSave is 0, AutoSave() will never be called automatically
8452/// as part of TTree::Fill().
8457}
8458
8459////////////////////////////////////////////////////////////////////////////////
8460/// Set a branch's basket size.
8461///
8462/// bname is the name of a branch.
8463///
8464/// - if bname="*", apply to all branches.
8465/// - if bname="xxx*", apply to all branches with name starting with xxx
8466///
8467/// see TRegexp for wildcarding options
8468/// buffsize = branc basket size
8470void TTree::SetBasketSize(const char* bname, Int_t buffsize)
8471{
8473 TRegexp re(bname, true);
8474 Int_t nb = 0;
8475 for (Int_t i = 0; i < nleaves; i++) {
8477 TBranch* branch = (TBranch*) leaf->GetBranch();
8478 TString s = branch->GetName();
8479 if (strcmp(bname, branch->GetName()) && (s.Index(re) == kNPOS)) {
8480 continue;
8481 }
8482 nb++;
8483 branch->SetBasketSize(buffsize);
8484 }
8485 if (!nb) {
8486 Error("SetBasketSize", "unknown branch -> '%s'", bname);
8487 }
8488}
8489
8490////////////////////////////////////////////////////////////////////////////////
8491/// Change branch address, dealing with clone trees properly.
8492/// See TTree::CheckBranchAddressType for the semantic of the return value.
8493///
8494/// Note: See the comments in TBranchElement::SetAddress() for the
8495/// meaning of the addr parameter and the object ownership policy.
8497Int_t TTree::SetBranchAddress(const char* bname, void* addr, TBranch** ptr)
8498{
8499 TBranch* branch = GetBranch(bname);
8500 if (!branch) {
8501 if (ptr) *ptr = nullptr;
8502 Error("SetBranchAddress", "unknown branch -> %s", bname);
8503 return kMissingBranch;
8504 }
8505 return SetBranchAddressImp(branch,addr,ptr);
8506}
8507
8508////////////////////////////////////////////////////////////////////////////////
8509/// Verify the validity of the type of addr before calling SetBranchAddress.
8510/// See TTree::CheckBranchAddressType for the semantic of the return value.
8511///
8512/// Note: See the comments in TBranchElement::SetAddress() for the
8513/// meaning of the addr parameter and the object ownership policy.
8515Int_t TTree::SetBranchAddress(const char* bname, void* addr, TClass* ptrClass, EDataType datatype, bool isptr)
8516{
8517 return SetBranchAddress(bname, addr, nullptr, ptrClass, datatype, isptr);
8518}
8519
8520////////////////////////////////////////////////////////////////////////////////
8521/// Verify the validity of the type of addr before calling SetBranchAddress.
8522/// See TTree::CheckBranchAddressType for the semantic of the return value.
8523///
8524/// Note: See the comments in TBranchElement::SetAddress() for the
8525/// meaning of the addr parameter and the object ownership policy.
8527Int_t TTree::SetBranchAddress(const char* bname, void* addr, TBranch** ptr, TClass* ptrClass, EDataType datatype, bool isptr)
8528{
8529 TBranch* branch = GetBranch(bname);
8530 if (!branch) {
8531 if (ptr) *ptr = nullptr;
8532 Error("SetBranchAddress", "unknown branch -> %s", bname);
8533 return kMissingBranch;
8534 }
8535
8537
8538 // This will set the value of *ptr to branch.
8539 if (res >= 0) {
8540 // The check succeeded.
8541 if ((res & kNeedEnableDecomposedObj) && !branch->GetMakeClass())
8542 branch->SetMakeClass(true);
8544 } else {
8545 if (ptr) *ptr = nullptr;
8546 }
8547 return res;
8548}
8549
8550////////////////////////////////////////////////////////////////////////////////
8551/// Change branch address, dealing with clone trees properly.
8552/// See TTree::CheckBranchAddressType for the semantic of the return value.
8553///
8554/// Note: See the comments in TBranchElement::SetAddress() for the
8555/// meaning of the addr parameter and the object ownership policy.
8558{
8559 if (ptr) {
8560 *ptr = branch;
8561 }
8562 if (fClones) {
8563 void* oldAddr = branch->GetAddress();
8564 TIter next(fClones);
8565 TTree* clone = nullptr;
8566 const char *bname = branch->GetName();
8567 while ((clone = (TTree*) next())) {
8568 TBranch* cloneBr = clone->GetBranch(bname);
8569 if (cloneBr && (cloneBr->GetAddress() == oldAddr)) {
8570 cloneBr->SetAddress(addr);
8571 }
8572 }
8573 }
8574 branch->SetAddress(addr);
8575 return kVoidPtr;
8576}
8577
8578////////////////////////////////////////////////////////////////////////////////
8579/// Set branch status to Process or DoNotProcess.
8580///
8581/// When reading a Tree, by default, all branches are read.
8582/// One can speed up considerably the analysis phase by activating
8583/// only the branches that hold variables involved in a query.
8584///
8585/// bname is the name of a branch.
8586///
8587/// - if bname="*", apply to all branches.
8588/// - if bname="xxx*", apply to all branches with name starting with xxx
8589///
8590/// see TRegexp for wildcarding options
8591///
8592/// - status = 1 branch will be processed
8593/// - = 0 branch will not be processed
8594///
8595/// Example:
8596///
8597/// Assume a tree T with sub-branches a,b,c,d,e,f,g,etc..
8598/// when doing T.GetEntry(i) all branches are read for entry i.
8599/// to read only the branches c and e, one can do
8600/// ~~~ {.cpp}
8601/// T.SetBranchStatus("*",0); //disable all branches
8602/// T.SetBranchStatus("c",1);
8603/// T.setBranchStatus("e",1);
8604/// T.GetEntry(i);
8605/// ~~~
8606/// bname is interpreted as a wild-carded TRegexp (see TRegexp::MakeWildcard).
8607/// Thus, "a*b" or "a.*b" matches branches starting with "a" and ending with
8608/// "b", but not any other branch with an "a" followed at some point by a
8609/// "b". For this second behavior, use "*a*b*". Note that TRegExp does not
8610/// support '|', and so you cannot select, e.g. track and shower branches
8611/// with "track|shower".
8612///
8613/// __WARNING! WARNING! WARNING!__
8614///
8615/// SetBranchStatus is matching the branch based on match of the branch
8616/// 'name' and not on the branch hierarchy! In order to be able to
8617/// selectively enable a top level object that is 'split' you need to make
8618/// sure the name of the top level branch is prefixed to the sub-branches'
8619/// name (by adding a dot ('.') at the end of the Branch creation and use the
8620/// corresponding bname.
8621///
8622/// I.e If your Tree has been created in split mode with a parent branch "parent."
8623/// (note the trailing dot).
8624/// ~~~ {.cpp}
8625/// T.SetBranchStatus("parent",1);
8626/// ~~~
8627/// will not activate the sub-branches of "parent". You should do:
8628/// ~~~ {.cpp}
8629/// T.SetBranchStatus("parent*",1);
8630/// ~~~
8631/// Without the trailing dot in the branch creation you have no choice but to
8632/// call SetBranchStatus explicitly for each of the sub branches.
8633///
8634/// An alternative to this function is to read directly and only
8635/// the interesting branches. Example:
8636/// ~~~ {.cpp}
8637/// TBranch *brc = T.GetBranch("c");
8638/// TBranch *bre = T.GetBranch("e");
8639/// brc->GetEntry(i);
8640/// bre->GetEntry(i);
8641/// ~~~
8642/// If found is not 0, the number of branch(es) found matching the regular
8643/// expression is returned in *found AND the error message 'unknown branch'
8644/// is suppressed.
8646void TTree::SetBranchStatus(const char* bname, bool status, UInt_t* found)
8647{
8648 // We already have been visited while recursively looking
8649 // through the friends tree, let return
8651 return;
8652 }
8653
8654 if (!bname || !*bname) {
8655 Error("SetBranchStatus", "Input regexp is an empty string: no match against branch names will be attempted.");
8656 return;
8657 }
8658
8660 TLeaf *leaf, *leafcount;
8661
8662 Int_t i,j;
8664 TRegexp re(bname,true);
8665 Int_t nb = 0;
8666
8667 // first pass, loop on all branches
8668 // for leafcount branches activate/deactivate in function of status
8669 for (i=0;i<nleaves;i++) {
8671 branch = (TBranch*)leaf->GetBranch();
8672 TString s = branch->GetName();
8673 if (strcmp(bname,"*")) { //Regexp gives wrong result for [] in name
8675 longname.Form("%s.%s",GetName(),branch->GetName());
8676 if (strcmp(bname,branch->GetName())
8677 && longname != bname
8678 && s.Index(re) == kNPOS) continue;
8679 }
8680 nb++;
8681 if (status) branch->ResetBit(kDoNotProcess);
8682 else branch->SetBit(kDoNotProcess);
8683 leafcount = leaf->GetLeafCount();
8684 if (leafcount) {
8685 bcount = leafcount->GetBranch();
8686 if (status) bcount->ResetBit(kDoNotProcess);
8687 else bcount->SetBit(kDoNotProcess);
8688 }
8689 }
8690 if (nb==0 && !strchr(bname,'*')) {
8691 branch = GetBranch(bname);
8692 if (branch) {
8693 if (status) branch->ResetBit(kDoNotProcess);
8694 else branch->SetBit(kDoNotProcess);
8695 ++nb;
8696 }
8697 }
8698
8699 //search in list of friends
8701 if (fFriends) {
8702 TFriendLock lock(this,kSetBranchStatus);
8705 TString name;
8706 while ((fe = (TFriendElement*)nextf())) {
8707 TTree *t = fe->GetTree();
8708 if (!t) continue;
8709
8710 // If the alias is present replace it with the real name.
8711 const char *subbranch = strstr(bname,fe->GetName());
8712 if (subbranch!=bname) subbranch = nullptr;
8713 if (subbranch) {
8714 subbranch += strlen(fe->GetName());
8715 if ( *subbranch != '.' ) subbranch = nullptr;
8716 else subbranch ++;
8717 }
8718 if (subbranch) {
8719 name.Form("%s.%s",t->GetName(),subbranch);
8720 } else {
8721 name = bname;
8722 }
8723 t->SetBranchStatus(name,status, &foundInFriend);
8724 }
8725 }
8726 if (!nb && !foundInFriend) {
8727 if (!found) {
8728 if (status) {
8729 if (strchr(bname,'*') != nullptr)
8730 Error("SetBranchStatus", "No branch name is matching wildcard -> %s", bname);
8731 else
8732 Error("SetBranchStatus", "unknown branch -> %s", bname);
8733 } else {
8734 if (strchr(bname,'*') != nullptr)
8735 Warning("SetBranchStatus", "No branch name is matching wildcard -> %s", bname);
8736 else
8737 Warning("SetBranchStatus", "unknown branch -> %s", bname);
8738 }
8739 }
8740 return;
8741 }
8742 if (found) *found = nb + foundInFriend;
8743
8744 // second pass, loop again on all branches
8745 // activate leafcount branches for active branches only
8746 for (i = 0; i < nleaves; i++) {
8748 branch = (TBranch*)leaf->GetBranch();
8749 if (!branch->TestBit(kDoNotProcess)) {
8750 leafcount = leaf->GetLeafCount();
8751 if (leafcount) {
8752 bcount = leafcount->GetBranch();
8753 bcount->ResetBit(kDoNotProcess);
8754 }
8755 } else {
8756 //Int_t nbranches = branch->GetListOfBranches()->GetEntriesFast();
8757 Int_t nbranches = branch->GetListOfBranches()->GetEntries();
8758 for (j=0;j<nbranches;j++) {
8759 bson = (TBranch*)branch->GetListOfBranches()->UncheckedAt(j);
8760 if (!bson) continue;
8761 if (!bson->TestBit(kDoNotProcess)) {
8762 if (bson->GetNleaves() <= 0) continue;
8763 branch->ResetBit(kDoNotProcess);
8764 break;
8765 }
8766 }
8767 }
8768 }
8769}
8770
8771////////////////////////////////////////////////////////////////////////////////
8772/// Set the current branch style. (static function)
8773///
8774/// - style = 0 old Branch
8775/// - style = 1 new Bronch
8780}
8781
8782////////////////////////////////////////////////////////////////////////////////
8783/// Set maximum size of the file cache .
8784//
8785/// - if cachesize = 0 the existing cache (if any) is deleted.
8786/// - if cachesize = -1 (default) it is set to the AutoFlush value when writing
8787/// the Tree (default is 30 MBytes).
8788///
8789/// The cacheSize might be clamped, see TFileCacheRead::SetBufferSize
8790///
8791/// Returns:
8792/// - 0 size set, cache was created if possible
8793/// - -1 on error
8796{
8797 // remember that the user has requested an explicit cache setup
8798 fCacheUserSet = true;
8799
8800 return SetCacheSizeAux(false, cacheSize);
8801}
8802
8803////////////////////////////////////////////////////////////////////////////////
8804/// Set the size of the file cache and create it if possible.
8805///
8806/// If autocache is true:
8807/// this may be an autocreated cache, possibly enlarging an existing
8808/// autocreated cache. The size is calculated. The value passed in cacheSize:
8809/// - cacheSize = 0 make cache if default cache creation is enabled
8810/// - cacheSize = -1 make a default sized cache in any case
8811///
8812/// If autocache is false:
8813/// this is a user requested cache. cacheSize is used to size the cache.
8814/// This cache should never be automatically adjusted.
8815///
8816/// The cacheSize might be clamped, see TFileCacheRead::SetBufferSize
8817///
8818/// Returns:
8819/// - 0 size set, or existing autosized cache almost large enough.
8820/// (cache was created if possible)
8821/// - -1 on error
8823Int_t TTree::SetCacheSizeAux(bool autocache /* = true */, Long64_t cacheSize /* = 0 */ )
8824{
8825 if (autocache) {
8826 // used as a once only control for automatic cache setup
8827 fCacheDoAutoInit = false;
8828 }
8829
8830 if (!autocache) {
8831 // negative size means the user requests the default
8832 if (cacheSize < 0) {
8833 cacheSize = GetCacheAutoSize(true);
8834 }
8835 } else {
8836 if (cacheSize == 0) {
8837 cacheSize = GetCacheAutoSize();
8838 } else if (cacheSize < 0) {
8839 cacheSize = GetCacheAutoSize(true);
8840 }
8841 }
8842
8843 TFile* file = GetCurrentFile();
8844 if (!file || GetTree() != this) {
8845 // if there's no file or we are not a plain tree (e.g. if we're a TChain)
8846 // do not create a cache, only record the size if one was given
8847 if (!autocache) {
8848 fCacheSize = cacheSize;
8849 }
8850 if (GetTree() != this) {
8851 return 0;
8852 }
8853 if (!autocache && cacheSize>0) {
8854 Warning("SetCacheSizeAux", "A TTreeCache could not be created because the TTree has no file");
8855 }
8856 return 0;
8857 }
8858
8859 // Check for an existing cache
8860 TTreeCache* pf = GetReadCache(file);
8861 if (pf) {
8862 if (autocache) {
8863 // reset our cache status tracking in case existing cache was added
8864 // by the user without using one of the TTree methods
8865 fCacheSize = pf->GetBufferSize();
8866 fCacheUserSet = !pf->IsAutoCreated();
8867
8868 if (fCacheUserSet) {
8869 // existing cache was created by the user, don't change it
8870 return 0;
8871 }
8872 } else {
8873 // update the cache to ensure it records the user has explicitly
8874 // requested it
8875 pf->SetAutoCreated(false);
8876 }
8877
8878 // if we're using an automatically calculated size and the existing
8879 // cache is already almost large enough don't resize
8880 if (autocache && Long64_t(0.80*cacheSize) < fCacheSize) {
8881 // already large enough
8882 return 0;
8883 }
8884
8885 if (cacheSize == fCacheSize) {
8886 return 0;
8887 }
8888
8889 if (cacheSize == 0) {
8890 // delete existing cache
8891 pf->WaitFinishPrefetch();
8892 file->SetCacheRead(nullptr,this);
8893 delete pf;
8894 pf = nullptr;
8895 } else {
8896 // resize
8897 Int_t res = pf->SetBufferSize(cacheSize);
8898 if (res < 0) {
8899 return -1;
8900 }
8901 cacheSize = pf->GetBufferSize(); // update after potential clamp
8902 }
8903 } else {
8904 // no existing cache
8905 if (autocache) {
8906 if (fCacheUserSet) {
8907 // value was already set manually.
8908 if (fCacheSize == 0) return 0;
8909 // Expected a cache should exist; perhaps the user moved it
8910 // Do nothing more here.
8911 if (cacheSize) {
8912 Error("SetCacheSizeAux", "Not setting up an automatically sized TTreeCache because of missing cache previously set");
8913 }
8914 return -1;
8915 }
8916 }
8917 }
8918
8919 fCacheSize = cacheSize;
8920 if (cacheSize == 0 || pf) {
8921 return 0;
8922 }
8923
8924#ifdef R__USE_IMT
8926 pf = new TTreeCacheUnzip(this, cacheSize);
8927 else
8928#endif
8929 pf = new TTreeCache(this, cacheSize);
8930
8931 pf->SetAutoCreated(autocache);
8932
8933 return 0;
8934}
8935
8936////////////////////////////////////////////////////////////////////////////////
8937///interface to TTreeCache to set the cache entry range
8938///
8939/// Returns:
8940/// - 0 entry range set
8941/// - -1 on error
8944{
8945 if (!GetTree()) {
8946 if (LoadTree(0)<0) {
8947 Error("SetCacheEntryRange","Could not load a tree");
8948 return -1;
8949 }
8950 }
8951 if (GetTree()) {
8952 if (GetTree() != this) {
8953 return GetTree()->SetCacheEntryRange(first, last);
8954 }
8955 } else {
8956 Error("SetCacheEntryRange", "No tree is available. Could not set cache entry range");
8957 return -1;
8958 }
8959
8960 TFile *f = GetCurrentFile();
8961 if (!f) {
8962 Error("SetCacheEntryRange", "No file is available. Could not set cache entry range");
8963 return -1;
8964 }
8965 TTreeCache *tc = GetReadCache(f,true);
8966 if (!tc) {
8967 Error("SetCacheEntryRange", "No cache is available. Could not set entry range");
8968 return -1;
8969 }
8970 tc->SetEntryRange(first,last);
8971 return 0;
8972}
8973
8974////////////////////////////////////////////////////////////////////////////////
8975/// Interface to TTreeCache to set the number of entries for the learning phase
8980}
8981
8982////////////////////////////////////////////////////////////////////////////////
8983/// Enable/Disable circularity for this tree.
8984///
8985/// if maxEntries > 0 a maximum of maxEntries is kept in one buffer/basket
8986/// per branch in memory.
8987/// Note that when this function is called (maxEntries>0) the Tree
8988/// must be empty or having only one basket per branch.
8989/// if maxEntries <= 0 the tree circularity is disabled.
8990///
8991/// #### NOTE 1:
8992/// Circular Trees are interesting in online real time environments
8993/// to store the results of the last maxEntries events.
8994/// #### NOTE 2:
8995/// Calling SetCircular with maxEntries <= 0 is necessary before
8996/// merging circular Trees that have been saved on files.
8997/// #### NOTE 3:
8998/// SetCircular with maxEntries <= 0 is automatically called
8999/// by TChain::Merge
9000/// #### NOTE 4:
9001/// A circular Tree can still be saved in a file. When read back,
9002/// it is still a circular Tree and can be filled again.
9005{
9006 if (maxEntries <= 0) {
9007 // Disable circularity.
9008 fMaxEntries = 1000000000;
9009 fMaxEntries *= 1000;
9011 //in case the Tree was originally created in gROOT, the branch
9012 //compression level was set to -1. If the Tree is now associated to
9013 //a file, reset the compression level to the file compression level
9014 if (fDirectory) {
9017 if (bfile) {
9018 compress = bfile->GetCompressionSettings();
9019 }
9021 for (Int_t i = 0; i < nb; i++) {
9023 branch->SetCompressionSettings(compress);
9024 }
9025 }
9026 } else {
9027 // Enable circularity.
9030 }
9031}
9032
9033////////////////////////////////////////////////////////////////////////////////
9034/// Set the debug level and the debug range.
9035///
9036/// For entries in the debug range, the functions TBranchElement::Fill
9037/// and TBranchElement::GetEntry will print the number of bytes filled
9038/// or read for each branch.
9040void TTree::SetDebug(Int_t level, Long64_t min, Long64_t max)
9041{
9042 fDebug = level;
9043 fDebugMin = min;
9044 fDebugMax = max;
9045}
9046
9047////////////////////////////////////////////////////////////////////////////////
9048/// Update the default value for the branch's fEntryOffsetLen.
9049/// If updateExisting is true, also update all the existing branches.
9050/// If newdefault is less than 10, the new default value will be 10.
9053{
9054 if (newdefault < 10) {
9055 newdefault = 10;
9056 }
9058 if (updateExisting) {
9059 TIter next( GetListOfBranches() );
9060 TBranch *b;
9061 while ( ( b = (TBranch*)next() ) ) {
9062 b->SetEntryOffsetLen( newdefault, true );
9063 }
9064 if (fBranchRef) {
9066 }
9067 }
9068}
9069
9070////////////////////////////////////////////////////////////////////////////////
9071/// Change the tree's directory.
9072///
9073/// Remove reference to this tree from current directory and
9074/// add reference to new directory dir. The dir parameter can
9075/// be 0 in which case the tree does not belong to any directory.
9076///
9079{
9080 if (fDirectory == dir) {
9081 return;
9082 }
9083 if (fDirectory) {
9084 fDirectory->Remove(this);
9085
9086 // Delete or move the file cache if it points to this Tree
9087 TFile *file = fDirectory->GetFile();
9088 MoveReadCache(file,dir);
9089 }
9090 fDirectory = dir;
9091 if (fDirectory) {
9092 fDirectory->Append(this);
9093 }
9094 TFile* file = nullptr;
9095 if (fDirectory) {
9096 file = fDirectory->GetFile();
9097 }
9098 if (fBranchRef) {
9099 fBranchRef->SetFile(file);
9100 }
9101 TBranch* b = nullptr;
9102 TIter next(GetListOfBranches());
9103 while((b = (TBranch*) next())) {
9104 b->SetFile(file);
9105 }
9106}
9107
9108////////////////////////////////////////////////////////////////////////////////
9109/// Change number of entries in the tree.
9110///
9111/// If n >= 0, set number of entries in the tree = n.
9112///
9113/// If n < 0, set number of entries in the tree to match the
9114/// number of entries in each branch. (default for n is -1)
9115///
9116/// This function should be called only when one fills each branch
9117/// independently via TBranch::Fill without calling TTree::Fill.
9118/// Calling TTree::SetEntries() make sense only if the number of entries
9119/// in each branch is identical, a warning is issued otherwise.
9120/// The function returns the number of entries.
9121///
9124{
9125 // case 1 : force number of entries to n
9126 if (n >= 0) {
9127 fEntries = n;
9128 return n;
9129 }
9130
9131 // case 2; compute the number of entries from the number of entries in the branches
9132 TBranch* b(nullptr), *bMin(nullptr), *bMax(nullptr);
9134 Long64_t nMax = 0;
9135 TIter next(GetListOfBranches());
9136 while((b = (TBranch*) next())){
9137 Long64_t n2 = b->GetEntries();
9138 if (!bMin || n2 < nMin) {
9139 nMin = n2;
9140 bMin = b;
9141 }
9142 if (!bMax || n2 > nMax) {
9143 nMax = n2;
9144 bMax = b;
9145 }
9146 }
9147 if (bMin && nMin != nMax) {
9148 Warning("SetEntries", "Tree branches have different numbers of entries, eg %s has %lld entries while %s has %lld entries.",
9149 bMin->GetName(), nMin, bMax->GetName(), nMax);
9150 }
9151 fEntries = nMax;
9152 return fEntries;
9153}
9154
9155////////////////////////////////////////////////////////////////////////////////
9156/// Set an EntryList
9159{
9160 if (fEntryList) {
9161 //check if the previous entry list is owned by the tree
9163 delete fEntryList;
9164 }
9165 }
9166 fEventList = nullptr;
9167 if (!enlist) {
9168 fEntryList = nullptr;
9169 return;
9170 }
9172 fEntryList->SetTree(this);
9173
9174}
9175
9176////////////////////////////////////////////////////////////////////////////////
9177/// This function transfroms the given TEventList into a TEntryList
9178/// The new TEntryList is owned by the TTree and gets deleted when the tree
9179/// is deleted. This TEntryList can be returned by GetEntryList() function.
9182{
9184 if (fEntryList){
9186 TEntryList *tmp = fEntryList;
9187 fEntryList = nullptr; // Avoid problem with RecursiveRemove.
9188 delete tmp;
9189 } else {
9190 fEntryList = nullptr;
9191 }
9192 }
9193
9194 if (!evlist) {
9195 fEntryList = nullptr;
9196 fEventList = nullptr;
9197 return;
9198 }
9199
9201 char enlistname[100];
9202 snprintf(enlistname,100, "%s_%s", evlist->GetName(), "entrylist");
9203 fEntryList = new TEntryList(enlistname, evlist->GetTitle());
9204 fEntryList->SetDirectory(nullptr); // We own this.
9205 Int_t nsel = evlist->GetN();
9206 fEntryList->SetTree(this);
9208 for (Int_t i=0; i<nsel; i++){
9209 entry = evlist->GetEntry(i);
9211 }
9212 fEntryList->SetReapplyCut(evlist->GetReapplyCut());
9214}
9215
9216////////////////////////////////////////////////////////////////////////////////
9217/// Set number of entries to estimate variable limits.
9218/// If n is -1, the estimate is set to be the current maximum
9219/// for the tree (i.e. GetEntries() + 1)
9220/// If n is less than -1, the behavior is undefined.
9222void TTree::SetEstimate(Long64_t n /* = 1000000 */)
9223{
9224 if (n == 0) {
9225 n = 10000;
9226 } else if (n < 0) {
9227 n = fEntries - n;
9228 }
9229 fEstimate = n;
9230 GetPlayer();
9231 if (fPlayer) {
9233 }
9234}
9235
9236////////////////////////////////////////////////////////////////////////////////
9237/// Provide the end-user with the ability to enable/disable various experimental
9238/// IO features for this TTree.
9239///
9240/// Returns all the newly-set IO settings.
9243{
9244 // Purposely ignore all unsupported bits; TIOFeatures implementation already warned the user about the
9245 // error of their ways; this is just a safety check.
9247
9252
9254 return newSettings;
9255}
9256
9257////////////////////////////////////////////////////////////////////////////////
9258/// Set fFileNumber to number.
9259/// fFileNumber is used by TTree::Fill to set the file name
9260/// for a new file to be created when the current file exceeds fgTreeMaxSize.
9261/// (see TTree::ChangeFile)
9262/// if fFileNumber=10, the new file name will have a suffix "_11",
9263/// ie, fFileNumber is incremented before setting the file name
9265void TTree::SetFileNumber(Int_t number)
9266{
9267 if (fFileNumber < 0) {
9268 Warning("SetFileNumber", "file number must be positive. Set to 0");
9269 fFileNumber = 0;
9270 return;
9271 }
9272 fFileNumber = number;
9273}
9274
9275////////////////////////////////////////////////////////////////////////////////
9276/// Set all the branches in this TTree to be in decomposed object mode
9277/// (also known as MakeClass mode).
9278///
9279/// For MakeClass mode 0, the TTree expects the address where the data is stored
9280/// to be set by either the user or the TTree to the address of a full object
9281/// through the top level branch.
9282/// For MakeClass mode 1, this address is expected to point to a numerical type
9283/// or C-style array (variable or not) of numerical type, representing the
9284/// primitive data members.
9285/// The function's primary purpose is to allow the user to access the data
9286/// directly with numerical type variable rather than having to have the original
9287/// set of classes (or a reproduction thereof).
9288/// In other words, SetMakeClass sets the branch(es) into a
9289/// mode that allow its reading via a set of independant variables
9290/// (see the result of running TTree::MakeClass on your TTree) by changing the
9291/// interpretation of the address passed to SetAddress from being the beginning
9292/// of the object containing the data to being the exact location where the data
9293/// should be loaded. If you have the shared library corresponding to your object,
9294/// it is better if you do
9295/// `MyClass *objp = 0; tree->SetBranchAddress("toplevel",&objp);`, whereas
9296/// if you do not have the shared library but know your branch data type, e.g.
9297/// `Int_t* ptr = new Int_t[10];`, then:
9298/// `tree->SetMakeClass(1); tree->GetBranch("x")->SetAddress(ptr)` is the way to go.
9300void TTree::SetMakeClass(Int_t make)
9301{
9302 fMakeClass = make;
9303
9305 for (Int_t i = 0; i < nb; ++i) {
9307 branch->SetMakeClass(make);
9308 }
9309}
9310
9311////////////////////////////////////////////////////////////////////////////////
9312/// Set the maximum size in bytes of a Tree file (static function).
9313/// The default size is 100000000000LL, ie 100 Gigabytes.
9314///
9315/// In TTree::Fill, when the file has a size > fgMaxTreeSize,
9316/// the function closes the current file and starts writing into
9317/// a new file with a name of the style "file_1.root" if the original
9318/// requested file name was "file.root".
9323}
9324
9325////////////////////////////////////////////////////////////////////////////////
9326/// Change the name of this tree.
9328void TTree::SetName(const char* name)
9329{
9330 if (gPad) {
9331 gPad->Modified();
9332 }
9333 // Trees are named objects in a THashList.
9334 // We must update hashlists if we change the name.
9335 TFile *file = nullptr;
9336 TTreeCache *pf = nullptr;
9337 if (fDirectory) {
9338 fDirectory->Remove(this);
9339 if ((file = GetCurrentFile())) {
9340 pf = GetReadCache(file);
9341 file->SetCacheRead(nullptr,this,TFile::kDoNotDisconnect);
9342 }
9343 }
9344 // This changes our hash value.
9345 fName = name;
9346 if (fDirectory) {
9347 fDirectory->Append(this);
9348 if (pf) {
9350 }
9351 }
9352}
9354void TTree::SetNotify(TObject *obj)
9355{
9356 if (obj && fNotify && dynamic_cast<TNotifyLinkBase *>(fNotify)) {
9357 auto *oldLink = static_cast<TNotifyLinkBase *>(fNotify);
9358 auto *newLink = dynamic_cast<TNotifyLinkBase *>(obj);
9359 if (!newLink) {
9360 Warning("TTree::SetNotify",
9361 "The tree or chain already has a fNotify registered and it is a TNotifyLink, while the new object is "
9362 "not a TNotifyLink. Setting fNotify to the new value will lead to an orphan linked list of "
9363 "TNotifyLinks and it is most likely not intended. If this is the intended goal, please call "
9364 "SetNotify(nullptr) first to silence this warning.");
9365 } else if (newLink->GetNext() != oldLink && oldLink->GetNext() != newLink) {
9366 // If newLink->GetNext() == oldLink then we are prepending the new head, as in TNotifyLink::PrependLink
9367 // If oldLink->GetNext() == newLink then we are removing the head of the list, as in TNotifyLink::RemoveLink
9368 // Otherwise newLink and oldLink are unrelated:
9369 Warning("TTree::SetNotify",
9370 "The tree or chain already has a TNotifyLink registered, and the new TNotifyLink `obj` does not link "
9371 "to it. Setting fNotify to the new value will lead to an orphan linked list of TNotifyLinks and it is "
9372 "most likely not intended. If this is the intended goal, please call SetNotify(nullptr) first to "
9373 "silence this warning.");
9374 }
9375 }
9376
9377 fNotify = obj;
9378}
9379
9380////////////////////////////////////////////////////////////////////////////////
9381/// Change the name and title of this tree.
9383void TTree::SetObject(const char* name, const char* title)
9384{
9385 if (gPad) {
9386 gPad->Modified();
9387 }
9388
9389 // Trees are named objects in a THashList.
9390 // We must update hashlists if we change the name
9391 TFile *file = nullptr;
9392 TTreeCache *pf = nullptr;
9393 if (fDirectory) {
9394 fDirectory->Remove(this);
9395 if ((file = GetCurrentFile())) {
9396 pf = GetReadCache(file);
9397 file->SetCacheRead(nullptr,this,TFile::kDoNotDisconnect);
9398 }
9399 }
9400 // This changes our hash value.
9401 fName = name;
9402 fTitle = title;
9403 if (fDirectory) {
9404 fDirectory->Append(this);
9405 if (pf) {
9407 }
9408 }
9409}
9410
9411////////////////////////////////////////////////////////////////////////////////
9412/// Enable or disable parallel unzipping of Tree buffers.
9415{
9416#ifdef R__USE_IMT
9417 if (GetTree() == nullptr) {
9419 if (!GetTree())
9420 return;
9421 }
9422 if (GetTree() != this) {
9423 GetTree()->SetParallelUnzip(opt, RelSize);
9424 return;
9425 }
9426 TFile* file = GetCurrentFile();
9427 if (!file)
9428 return;
9429
9430 TTreeCache* pf = GetReadCache(file);
9431 if (pf && !( opt ^ (nullptr != dynamic_cast<TTreeCacheUnzip*>(pf)))) {
9432 // done with opt and type are in agreement.
9433 return;
9434 }
9435 delete pf;
9436 auto cacheSize = GetCacheAutoSize(true);
9437 if (opt) {
9438 auto unzip = new TTreeCacheUnzip(this, cacheSize);
9439 unzip->SetUnzipBufferSize( Long64_t(cacheSize * RelSize) );
9440 } else {
9441 pf = new TTreeCache(this, cacheSize);
9442 }
9443#else
9444 (void)opt;
9445 (void)RelSize;
9446#endif
9447}
9448
9449////////////////////////////////////////////////////////////////////////////////
9450/// Set perf stats
9455}
9456
9457////////////////////////////////////////////////////////////////////////////////
9458/// The current TreeIndex is replaced by the new index.
9459/// Note that this function does not delete the previous index.
9460/// This gives the possibility to play with more than one index, e.g.,
9461/// ~~~ {.cpp}
9462/// TVirtualIndex* oldIndex = tree.GetTreeIndex();
9463/// tree.SetTreeIndex(newIndex);
9464/// tree.Draw();
9465/// tree.SetTreeIndex(oldIndex);
9466/// tree.Draw(); etc
9467/// ~~~
9470{
9471 if (fTreeIndex) {
9472 fTreeIndex->SetTree(nullptr);
9473 }
9474 fTreeIndex = index;
9475}
9476
9477////////////////////////////////////////////////////////////////////////////////
9478/// Set tree weight.
9479///
9480/// The weight is used by TTree::Draw to automatically weight each
9481/// selected entry in the resulting histogram.
9482///
9483/// For example the equivalent of:
9484/// ~~~ {.cpp}
9485/// T.Draw("x", "w")
9486/// ~~~
9487/// is:
9488/// ~~~ {.cpp}
9489/// T.SetWeight(w);
9490/// T.Draw("x");
9491/// ~~~
9492/// This function is redefined by TChain::SetWeight. In case of a
9493/// TChain, an option "global" may be specified to set the same weight
9494/// for all trees in the TChain instead of the default behaviour
9495/// using the weights of each tree in the chain (see TChain::SetWeight).
9498{
9499 fWeight = w;
9500}
9501
9502////////////////////////////////////////////////////////////////////////////////
9503/// Print values of all active leaves for entry.
9504///
9505/// - if entry==-1, print current entry (default)
9506/// - if a leaf is an array, a maximum of lenmax elements is printed.
9509{
9510 if (entry != -1) {
9512 if (ret == -2) {
9513 Error("Show()", "Cannot read entry %lld (entry does not exist)", entry);
9514 return;
9515 } else if (ret == -1) {
9516 Error("Show()", "Cannot read entry %lld (I/O error)", entry);
9517 return;
9518 }
9519 ret = GetEntry(entry);
9520 if (ret == -1) {
9521 Error("Show()", "Cannot read entry %lld (I/O error)", entry);
9522 return;
9523 } else if (ret == 0) {
9524 Error("Show()", "Cannot read entry %lld (no data read)", entry);
9525 return;
9526 }
9527 }
9528 printf("======> EVENT:%lld\n", fReadEntry);
9530 Int_t nleaves = leaves->GetEntriesFast();
9531 Int_t ltype;
9532 for (Int_t i = 0; i < nleaves; i++) {
9533 TLeaf* leaf = (TLeaf*) leaves->UncheckedAt(i);
9534 TBranch* branch = leaf->GetBranch();
9535 if (branch->TestBit(kDoNotProcess)) {
9536 continue;
9537 }
9538 Int_t len = leaf->GetLen();
9539 if (len <= 0) {
9540 continue;
9541 }
9543 if (leaf->IsA() == TLeafElement::Class()) {
9544 leaf->PrintValue(lenmax);
9545 continue;
9546 }
9547 if (branch->GetListOfBranches()->GetEntriesFast() > 0) {
9548 continue;
9549 }
9550 ltype = 10;
9551 if (leaf->IsA() == TLeafF::Class()) {
9552 ltype = 5;
9553 }
9554 if (leaf->IsA() == TLeafD::Class()) {
9555 ltype = 5;
9556 }
9557 if (leaf->IsA() == TLeafC::Class()) {
9558 len = 1;
9559 ltype = 5;
9560 };
9561 printf(" %-15s = ", leaf->GetName());
9562 for (Int_t l = 0; l < len; l++) {
9563 leaf->PrintValue(l);
9564 if (l == (len - 1)) {
9565 printf("\n");
9566 continue;
9567 }
9568 printf(", ");
9569 if ((l % ltype) == 0) {
9570 printf("\n ");
9571 }
9572 }
9573 }
9574}
9575
9576////////////////////////////////////////////////////////////////////////////////
9577/// Start the TTreeViewer on this tree.
9578///
9579/// - ww is the width of the canvas in pixels
9580/// - wh is the height of the canvas in pixels
9582void TTree::StartViewer()
9583{
9584 GetPlayer();
9585 if (fPlayer) {
9586 fPlayer->StartViewer(600, 400);
9587 }
9588}
9589
9590////////////////////////////////////////////////////////////////////////////////
9591/// Stop the cache learning phase
9592///
9593/// Returns:
9594/// - 0 learning phase stopped or not active
9595/// - -1 on error
9598{
9599 if (!GetTree()) {
9600 if (LoadTree(0)<0) {
9601 Error("StopCacheLearningPhase","Could not load a tree");
9602 return -1;
9603 }
9604 }
9605 if (GetTree()) {
9606 if (GetTree() != this) {
9607 return GetTree()->StopCacheLearningPhase();
9608 }
9609 } else {
9610 Error("StopCacheLearningPhase", "No tree is available. Could not stop cache learning phase");
9611 return -1;
9612 }
9613
9614 TFile *f = GetCurrentFile();
9615 if (!f) {
9616 Error("StopCacheLearningPhase", "No file is available. Could not stop cache learning phase");
9617 return -1;
9618 }
9619 TTreeCache *tc = GetReadCache(f,true);
9620 if (!tc) {
9621 Error("StopCacheLearningPhase", "No cache is available. Could not stop learning phase");
9622 return -1;
9623 }
9624 tc->StopLearningPhase();
9625 return 0;
9626}
9627
9628////////////////////////////////////////////////////////////////////////////////
9629/// Set the fTree member for all branches and sub branches.
9632{
9633 Int_t nb = branches.GetEntriesFast();
9634 for (Int_t i = 0; i < nb; ++i) {
9635 TBranch* br = (TBranch*) branches.UncheckedAt(i);
9636 br->SetTree(tree);
9637
9638 Int_t writeBasket = br->GetWriteBasket();
9639 for (Int_t j = writeBasket; j >= 0; --j) {
9640 TBasket *bk = (TBasket*)br->GetListOfBaskets()->UncheckedAt(j);
9641 if (bk) {
9642 tree->IncrementTotalBuffers(bk->GetBufferSize());
9643 }
9644 }
9645
9646 tree->RegisterBranchFullName({std::string{br->GetFullName()}, br});
9647
9648 ROOT::Internal::TreeUtils::TBranch__SetTree(tree, *br->GetListOfBranches());
9649 }
9650}
9651
9652////////////////////////////////////////////////////////////////////////////////
9653/// Set the fTree member for all friend elements.
9656{
9657 if (frlist) {
9658 TObjLink *lnk = frlist->FirstLink();
9659 while (lnk) {
9660 TFriendElement *elem = (TFriendElement*)lnk->GetObject();
9661 elem->fParentTree = tree;
9662 lnk = lnk->Next();
9663 }
9664 }
9665}
9666
9667////////////////////////////////////////////////////////////////////////////////
9668/// Stream a class object.
9671{
9672 if (b.IsReading()) {
9673 UInt_t R__s, R__c;
9674 if (fDirectory) {
9675 fDirectory->Remove(this);
9676 //delete the file cache if it points to this Tree
9677 TFile *file = fDirectory->GetFile();
9678 MoveReadCache(file,nullptr);
9679 }
9680 fDirectory = nullptr;
9681 fCacheDoAutoInit = true;
9682 fCacheUserSet = false;
9683 Version_t R__v = b.ReadVersion(&R__s, &R__c);
9684 if (R__v > 4) {
9685 b.ReadClassBuffer(TTree::Class(), this, R__v, R__s, R__c);
9686
9687 fBranches.SetOwner(true); // True needed only for R__v < 19 and most R__v == 19
9688
9689 if (fBranchRef) fBranchRef->SetTree(this);
9692
9693 if (fTreeIndex) {
9694 fTreeIndex->SetTree(this);
9695 }
9696 if (fIndex.fN) {
9697 Warning("Streamer", "Old style index in this tree is deleted. Rebuild the index via TTree::BuildIndex");
9698 fIndex.Set(0);
9699 fIndexValues.Set(0);
9700 }
9701 if (fEstimate <= 10000) {
9702 fEstimate = 1000000;
9703 }
9704
9705 if (fNClusterRange) {
9706 // The I/O allocated just enough memory to hold the
9707 // current set of ranges.
9709 }
9710
9711 // Throughs calls to `GetCacheAutoSize` or `EnableCache` (for example
9712 // by TTreePlayer::Process, the cache size will be automatically
9713 // determined unless the user explicitly call `SetCacheSize`
9714 fCacheSize = 0;
9715 fCacheUserSet = false;
9716
9718 return;
9719 }
9720 //====process old versions before automatic schema evolution
9721 Stat_t djunk;
9722 Int_t ijunk;
9727 b >> fScanField;
9730 b >> djunk; fEntries = (Long64_t)djunk;
9735 if (fEstimate <= 10000) fEstimate = 1000000;
9737 if (fBranchRef) fBranchRef->SetTree(this);
9741 if (R__v > 1) fIndexValues.Streamer(b);
9742 if (R__v > 2) fIndex.Streamer(b);
9743 if (R__v > 3) {
9745 OldInfoList.Streamer(b);
9746 OldInfoList.Delete();
9747 }
9748 fNClusterRange = 0;
9751 b.CheckByteCount(R__s, R__c, TTree::IsA());
9752 //====end of old versions
9753 } else {
9754 if (fBranchRef) {
9755 fBranchRef->Clear();
9756 }
9758 if (table) TRefTable::SetRefTable(nullptr);
9759
9760 b.WriteClassBuffer(TTree::Class(), this);
9761
9762 if (table) TRefTable::SetRefTable(table);
9763 }
9764}
9765
9766////////////////////////////////////////////////////////////////////////////////
9767/// Unbinned fit of one or more variable(s) from a tree.
9768///
9769/// funcname is a TF1 function.
9770///
9771/// \note see TTree::Draw for explanations of the other parameters.
9772///
9773/// Fit the variable varexp using the function funcname using the
9774/// selection cuts given by selection.
9775///
9776/// The list of fit options is given in parameter option.
9777///
9778/// - option = "Q" Quiet mode (minimum printing)
9779/// - option = "V" Verbose mode (default is between Q and V)
9780/// - option = "E" Perform better Errors estimation using Minos technique
9781/// - option = "M" More. Improve fit results
9782///
9783/// You can specify boundary limits for some or all parameters via
9784/// ~~~ {.cpp}
9785/// func->SetParLimits(p_number, parmin, parmax);
9786/// ~~~
9787/// if parmin>=parmax, the parameter is fixed
9788///
9789/// Note that you are not forced to fix the limits for all parameters.
9790/// For example, if you fit a function with 6 parameters, you can do:
9791/// ~~~ {.cpp}
9792/// func->SetParameters(0,3.1,1.e-6,0.1,-8,100);
9793/// func->SetParLimits(4,-10,-4);
9794/// func->SetParLimits(5, 1,1);
9795/// ~~~
9796/// With this setup:
9797///
9798/// - Parameters 0->3 can vary freely
9799/// - Parameter 4 has boundaries [-10,-4] with initial value -8
9800/// - Parameter 5 is fixed to 100.
9801///
9802/// For the fit to be meaningful, the function must be self-normalized.
9803///
9804/// i.e. It must have the same integral regardless of the parameter
9805/// settings. Otherwise the fit will effectively just maximize the
9806/// area.
9807///
9808/// It is mandatory to have a normalization variable
9809/// which is fixed for the fit. e.g.
9810/// ~~~ {.cpp}
9811/// TF1* f1 = new TF1("f1", "gaus(0)/sqrt(2*3.14159)/[2]", 0, 5);
9812/// f1->SetParameters(1, 3.1, 0.01);
9813/// f1->SetParLimits(0, 1, 1); // fix the normalization parameter to 1
9814/// data->UnbinnedFit("f1", "jpsimass", "jpsipt>3.0");
9815/// ~~~
9816/// 1, 2 and 3 Dimensional fits are supported. See also TTree::Fit
9817///
9818/// Return status:
9819///
9820/// - The function return the status of the fit in the following form
9821/// fitResult = migradResult + 10*minosResult + 100*hesseResult + 1000*improveResult
9822/// - The fitResult is 0 is the fit is OK.
9823/// - The fitResult is negative in case of an error not connected with the fit.
9824/// - The number of entries used in the fit can be obtained via mytree.GetSelectedRows();
9825/// - If the number of selected entries is null the function returns -1
9828{
9829 GetPlayer();
9830 if (fPlayer) {
9832 }
9833 return -1;
9834}
9835
9836////////////////////////////////////////////////////////////////////////////////
9837/// Replace current attributes by current style.
9860}
9861
9862////////////////////////////////////////////////////////////////////////////////
9863/// Write this object to the current directory. For more see TObject::Write
9864/// If option & kFlushBasket, call FlushBasket before writing the tree.
9866Int_t TTree::Write(const char *name, Int_t option, Int_t bufsize) const
9867{
9870 return 0;
9872}
9873
9874////////////////////////////////////////////////////////////////////////////////
9875/// Write this object to the current directory. For more see TObject::Write
9876/// If option & kFlushBasket, call FlushBasket before writing the tree.
9879{
9880 return ((const TTree*)this)->Write(name, option, bufsize);
9881}
9882
9883////////////////////////////////////////////////////////////////////////////////
9884/// \class TTreeFriendLeafIter
9885///
9886/// Iterator on all the leaves in a TTree and its friend
9887
9889
9890////////////////////////////////////////////////////////////////////////////////
9891/// Create a new iterator. By default the iteration direction
9892/// is kIterForward. To go backward use kIterBackward.
9895: fTree(const_cast<TTree*>(tree))
9896, fLeafIter(nullptr)
9897, fTreeIter(nullptr)
9898, fDirection(dir)
9899{
9900}
9901
9902////////////////////////////////////////////////////////////////////////////////
9903/// Copy constructor. Does NOT copy the 'cursor' location!
9906: TIterator(iter)
9907, fTree(iter.fTree)
9908, fLeafIter(nullptr)
9909, fTreeIter(nullptr)
9910, fDirection(iter.fDirection)
9911{
9912}
9913
9914////////////////////////////////////////////////////////////////////////////////
9915/// Overridden assignment operator. Does NOT copy the 'cursor' location!
9918{
9919 if (this != &rhs && rhs.IsA() == TTreeFriendLeafIter::Class()) {
9921 fDirection = rhs1.fDirection;
9922 }
9923 return *this;
9924}
9925
9926////////////////////////////////////////////////////////////////////////////////
9927/// Overridden assignment operator. Does NOT copy the 'cursor' location!
9930{
9931 if (this != &rhs) {
9932 fDirection = rhs.fDirection;
9933 }
9934 return *this;
9935}
9936
9937////////////////////////////////////////////////////////////////////////////////
9938/// Go the next friend element
9941{
9942 if (!fTree) return nullptr;
9943
9944 TObject * next;
9945 TTree * nextTree;
9946
9947 if (!fLeafIter) {
9948 TObjArray *list = fTree->GetListOfLeaves();
9949 if (!list) return nullptr; // Can happen with an empty chain.
9950 fLeafIter = list->MakeIterator(fDirection);
9951 if (!fLeafIter) return nullptr;
9952 }
9953
9954 next = fLeafIter->Next();
9955 if (!next) {
9956 if (!fTreeIter) {
9958 if (!list) return next;
9959 fTreeIter = list->MakeIterator(fDirection);
9960 if (!fTreeIter) return nullptr;
9961 }
9963 ///nextTree = (TTree*)fTreeIter->Next();
9964 if (nextFriend) {
9965 nextTree = const_cast<TTree*>(nextFriend->GetTree());
9966 if (!nextTree) return Next();
9968 fLeafIter = nextTree->GetListOfLeaves()->MakeIterator(fDirection);
9969 if (!fLeafIter) return nullptr;
9970 next = fLeafIter->Next();
9971 }
9972 }
9973 return next;
9974}
9975
9976////////////////////////////////////////////////////////////////////////////////
9977/// Returns the object option stored in the list.
9980{
9981 if (fLeafIter) return fLeafIter->GetOption();
9982 return "";
9983}
#define R__unlikely(expr)
Definition RConfig.hxx:594
#define SafeDelete(p)
Definition RConfig.hxx:533
#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
TVirtualProofPlayer * fPlayer
Definition TProof.h:177
Int_t gDebug
Definition TROOT.cxx:622
R__EXTERN TVirtualMutex * gROOTMutex
Definition TROOT.h:63
#define gROOT
Definition TROOT.h:414
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:4808
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:9654
bool CheckReshuffling(TTree &mainTree, TTree &friendTree)
Definition TTree.cxx:1234
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:2424
ROOT::ESTLType GetCollectionType() const
Return the 'type' of the STL the TClass is representing.
Definition TClass.cxx:2991
void * New(ENewType defConstructor=kClassNew, Bool_t quiet=kFALSE) const
Return a pointer to a newly allocated object of this class.
Definition TClass.cxx:5117
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:5539
void BuildRealData(void *pointer=nullptr, Bool_t isTransient=kFALSE)
Build a full list of persistent data members.
Definition TClass.cxx:2136
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:3763
Bool_t IsTObject() const
Return kTRUE is the class inherits from TObject.
Definition TClass.cxx:6080
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:4726
TVirtualCollectionProxy * GetCollectionProxy() const
Return the proxy describing the collection (if any).
Definition TClass.cxx:3002
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:3073
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:2387
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:3815
@ 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:4112
virtual void WriteHeader()
Write File Header.
Definition TFile.cxx:2637
@ kCancelTTreeChangeRequest
Definition TFile.h:280
TFileCacheRead * GetCacheRead(const TObject *tree=nullptr) const
Return a pointer to the current read cache.
Definition TFile.cxx:1248
<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:1678
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:1309
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:728
TTree * fTree
tree being iterated
Definition TTree.h:731
TIterator & operator=(const TIterator &rhs) override
Overridden assignment operator. Does NOT copy the 'cursor' location!
Definition TTree.cxx:9916
TObject * Next() override
Go the next friend element.
Definition TTree.cxx:9939
TIterator * fLeafIter
current leaf sub-iterator.
Definition TTree.h:732
Option_t * GetOption() const override
Returns the object option stored in the list.
Definition TTree.cxx:9978
TIterator * fTreeIter
current tree sub-iterator.
Definition TTree.h:733
bool fDirection
iteration direction
Definition TTree.h:734
static TClass * Class()
Helper class to iterate over cluster of baskets.
Definition TTree.h:282
Long64_t GetEstimatedClusterSize()
Estimate the cluster size.
Definition TTree.cxx:605
Long64_t Previous()
Move on to the previous cluster and return the starting entry of this previous cluster.
Definition TTree.cxx:688
Long64_t Next()
Move on to the next cluster and return the starting entry of this next cluster.
Definition TTree.cxx:644
Long64_t GetNextEntry()
Definition TTree.h:319
TClusterIterator(TTree *tree, Long64_t firstEntry)
Regular constructor.
Definition TTree.cxx:554
Helper class to prevent infinite recursion in the usage of TTree Friends.
Definition TTree.h:199
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:203
TTree * fTree
Definition TTree.h:202
~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:84
virtual Int_t Fill()
Fill all branches.
Definition TTree.cxx:4620
virtual TFriendElement * AddFriend(const char *treename, const char *filename="")
Add a TFriendElement to the list of friends.
Definition TTree.cxx:1326
TBranchRef * fBranchRef
Branch supporting the TRefTable (if any)
Definition TTree.h:141
TStreamerInfo * BuildStreamerInfo(TClass *cl, void *pointer=nullptr, bool canOptimize=true)
Build StreamerInfo for class cl.
Definition TTree.cxx:2649
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:4856
virtual void SetBranchStatus(const char *bname, bool status=true, UInt_t *found=nullptr)
Set branch status to Process or DoNotProcess.
Definition TTree.cxx:8645
bool EnableCache()
Enable the TTreeCache unless explicitly disabled for this TTree by a prior call to SetCacheSize(0).
Definition TTree.cxx:2682
virtual TBranch * GetBranch(const char *name)
Return pointer to the branch with the given name in this tree or its friends.
Definition TTree.cxx:5309
static Int_t GetBranchStyle()
Static function returning the current branch style.
Definition TTree.cxx:5413
TList * fFriends
pointer to list of friend elements
Definition TTree.h:135
bool fIMTEnabled
! true if implicit multi-threading is enabled for this tree
Definition TTree.h:147
virtual bool GetBranchStatus(const char *branchname) const
Return status of branch with name branchname.
Definition TTree.cxx:5398
UInt_t fFriendLockStatus
! Record which method is locking the friend recursion
Definition TTree.h:142
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:6118
Long64_t fTotBytes
Total number of bytes in all branches before compression.
Definition TTree.h:91
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:5144
Int_t fMaxClusterRange
! Memory allocated for the cluster range.
Definition TTree.h:101
virtual void Show(Long64_t entry=-1, Int_t lenmax=20)
Print values of all active leaves for entry.
Definition TTree.cxx:9507
TEventList * fEventList
! Pointer to event selection list (if one)
Definition TTree.h:130
virtual Long64_t GetAutoSave() const
Definition TTree.h:460
virtual Int_t StopCacheLearningPhase()
Stop the cache learning phase.
Definition TTree.cxx:9596
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:5658
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:149
virtual void SetCircular(Long64_t maxEntries)
Enable/Disable circularity for this tree.
Definition TTree.cxx:9003
Long64_t fSavedBytes
Number of autosaved bytes.
Definition TTree.h:93
virtual Int_t AddBranchToCache(const char *bname, bool subbranches=false)
Add branch with name bname to the Tree cache.
Definition TTree.cxx:1053
Long64_t GetMedianClusterSize()
Estimate the median cluster size for the TTree.
Definition TTree.cxx:8408
virtual TClusterIterator GetClusterIterator(Long64_t firstentry)
Return an iterator over the cluster of baskets starting at firstentry.
Definition TTree.cxx:5485
virtual void ResetBranchAddress(TBranch *)
Tell a branch to set its address to zero.
Definition TTree.cxx:8162
bool fCacheUserSet
! true if the cache setting was explicitly given by user
Definition TTree.h:146
char GetNewlineValue(std::istream &inputStream)
Determine which newline this file is using.
Definition TTree.cxx:7685
TIOFeatures fIOFeatures
IO features to define for newly-written baskets and branches.
Definition TTree.h:119
virtual Long64_t GetEntryNumberWithIndex(Long64_t major, Long64_t minor=0) const
Return entry number corresponding to major and minor number.
Definition TTree.cxx:5930
Long64_t fDebugMin
! First entry number to debug
Definition TTree.h:117
virtual Long64_t SetEntries(Long64_t n=-1)
Change number of entries in the tree.
Definition TTree.cxx:9122
virtual TObjArray * GetListOfLeaves()
Definition TTree.h:541
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:2071
Long64_t GetCacheAutoSize(bool withDefault=false)
Used for automatic sizing of the cache.
Definition TTree.cxx:5425
virtual TBranch * BranchRef()
Build the optional branch supporting the TRefTable.
Definition TTree.cxx:2325
TFile * GetCurrentFile() const
Return pointer to the current file.
Definition TTree.cxx:5497
TList * fAliases
List of aliases for expressions based on the tree branches.
Definition TTree.h:129
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:3726
virtual Int_t DropBranchFromCache(const char *bname, bool subbranches=false)
Remove the branch with name 'bname' from the Tree cache.
Definition TTree.cxx:1136
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:5094
Long64_t * fClusterRangeEnd
[fNClusterRange] Last entry of a cluster range.
Definition TTree.h:108
void Streamer(TBuffer &) override
Stream a class object.
Definition TTree.cxx:9669
std::atomic< Long64_t > fIMTZipBytes
! Zip bytes for the IMT flush baskets.
Definition TTree.h:166
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:7978
TVirtualTreePlayer * GetPlayer()
Load the TTreePlayer (if not already done).
Definition TTree.cxx:6325
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:6788
virtual Long64_t ReadStream(std::istream &inputStream, const char *branchDescriptor="", char delimiter=' ')
Create or simply read branches from an input stream.
Definition TTree.cxx:7712
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:9039
Int_t fScanField
Number of runs before prompting in Scan.
Definition TTree.h:97
void Draw(Option_t *opt) override
Default Draw method for all objects.
Definition TTree.h:443
virtual TTree * GetFriend(const char *) const
Return a pointer to the TTree friend whose name or alias is friendname.
Definition TTree.cxx:5995
virtual void SetNotify(TObject *obj)
Sets the address of the object to be notified when the tree is loaded.
Definition TTree.cxx:9353
virtual Double_t GetMaximum(const char *columname)
Return maximum of column with name columname.
Definition TTree.cxx:6255
virtual Long64_t GetEntryNumberWithBestIndex(Long64_t major, Long64_t minor=0) const
Return entry number corresponding to major and minor number.
Definition TTree.cxx:5910
static void SetMaxTreeSize(Long64_t maxsize=100000000000LL)
Set the maximum size in bytes of a Tree file (static function).
Definition TTree.cxx:9319
void Print(Option_t *option="") const override
Print a summary of the tree contents.
Definition TTree.cxx:7315
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:9826
Int_t fNClusterRange
Number of Cluster range in addition to the one defined by 'AutoFlush'.
Definition TTree.h:100
virtual void PrintCacheStats(Option_t *option="") const
Print statistics about the TreeCache for this tree.
Definition TTree.cxx:7467
virtual Int_t BuildIndex(const char *majorname, const char *minorname="0")
Build a Tree Index (default is TTreeIndex).
Definition TTree.cxx:2634
TVirtualTreePlayer * fPlayer
! Pointer to current Tree player
Definition TTree.h:139
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:6102
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:9299
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:7108
TObjArray fBranches
List of Branches.
Definition TTree.h:127
TDirectory * GetDirectory() const
Definition TTree.h:474
bool fCacheDoAutoInit
! true if cache auto creation or resize check is needed
Definition TTree.h:144
TTreeCache * GetReadCache(TFile *file) const
Find and return the TTreeCache registered with the file and which may contain branches for us.
Definition TTree.cxx:6338
Long64_t fEntries
Number of entries.
Definition TTree.h:89
virtual TFile * ChangeFile(TFile *file)
Called by TTree::Fill() when file has reached its maximum fgMaxTreeSize.
Definition TTree.cxx:2746
virtual TEntryList * GetEntryList()
Returns the entry list assigned to this tree.
Definition TTree.cxx:5874
virtual void SetWeight(Double_t w=1, Option_t *option="")
Set tree weight.
Definition TTree.cxx:9496
void InitializeBranchLists(bool checkLeafCount)
Divides the top-level branches into two vectors: (i) branches to be processed sequentially and (ii) b...
Definition TTree.cxx:5801
virtual Int_t SetBranchAddress(const char *bname, void *add, TBranch **ptr=nullptr)
Change branch address, dealing with clone trees properly.
Definition TTree.cxx:8496
Long64_t * fClusterSize
[fNClusterRange] Number of entries in each cluster for a given range.
Definition TTree.h:109
Long64_t fFlushedBytes
Number of auto-flushed bytes.
Definition TTree.h:94
virtual void SetPerfStats(TVirtualPerfStats *perf)
Set perf stats.
Definition TTree.cxx:9451
std::atomic< Long64_t > fIMTTotBytes
! Total bytes for the IMT flush baskets
Definition TTree.h:165
virtual void SetCacheLearnEntries(Int_t n=10)
Interface to TTreeCache to set the number of entries for the learning phase.
Definition TTree.cxx:8976
TEntryList * fEntryList
! Pointer to event selection list (if one)
Definition TTree.h:131
@ kSplitCollectionOfPointers
Definition TTree.h:278
virtual TVirtualIndex * GetTreeIndex() const
Definition TTree.h:570
TList * fExternalFriends
! List of TFriendsElement pointing to us and need to be notified of LoadTree. Content not owned.
Definition TTree.h:136
virtual Long64_t Merge(TCollection *list, Option_t *option="")
Merge the trees in the TList into this tree.
Definition TTree.cxx:6922
virtual void SetMaxVirtualSize(Long64_t size=0)
Definition TTree.h:677
virtual void DropBaskets()
Remove some baskets from memory.
Definition TTree.cxx:4535
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:8453
Long64_t fMaxEntryLoop
Maximum number of entries to process.
Definition TTree.h:103
virtual void SetParallelUnzip(bool opt=true, Float_t RelSize=-1)
Enable or disable parallel unzipping of Tree buffers.
Definition TTree.cxx:9413
virtual void SetDirectory(TDirectory *dir)
Change the tree's directory.
Definition TTree.cxx:9077
void SortBranchesByTime()
Sorts top-level branches by the last average task time recorded per branch.
Definition TTree.cxx:5854
void Delete(Option_t *option="") override
Delete this tree from memory or/and disk.
Definition TTree.cxx:3754
virtual TBranchRef * GetBranchRef() const
Definition TTree.h:462
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:7547
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:1629
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:9180
void MoveReadCache(TFile *src, TDirectory *dir)
Move a cache from a file to the current file in dir.
Definition TTree.cxx:7079
Long64_t fAutoFlush
Auto-flush tree when fAutoFlush entries written or -fAutoFlush (compressed) bytes produced.
Definition TTree.h:106
Int_t fUpdate
Update frequency for EntryLoop.
Definition TTree.h:98
virtual void ResetAfterMerge(TFileMergeInfo *)
Resets the state of this TTree after a merge (keep the customization but forget the data).
Definition TTree.cxx:8131
virtual Long64_t GetEntries() const
Definition TTree.h:475
virtual void SetEstimate(Long64_t nentries=1000000)
Set number of entries to estimate variable limits.
Definition TTree.cxx:9221
Int_t fTimerInterval
Timer interval in milliseconds.
Definition TTree.h:96
Int_t fDebug
! Debug level
Definition TTree.h:116
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:8822
virtual Long64_t AutoSave(Option_t *option="")
AutoSave tree header every fAutoSave bytes.
Definition TTree.cxx:1494
virtual Long64_t GetEntryNumber(Long64_t entry) const
Return entry number corresponding to entry.
Definition TTree.cxx:5885
virtual TTree * CloneTree(Long64_t nentries=-1, Option_t *option="")
Create a clone of this tree and copy nentries.
Definition TTree.cxx:3140
Int_t fFileNumber
! current file number (if file extensions)
Definition TTree.h:121
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:6215
virtual Long64_t GetZipBytes() const
Definition TTree.h:597
TObjArray fLeaves
Direct pointers to individual branch leaves.
Definition TTree.h:128
virtual void Reset(Option_t *option="")
Reset baskets, buffers and entries count in all branches and leaves.
Definition TTree.cxx:8100
virtual void KeepCircular()
Keep a maximum of fMaxEntries in memory.
Definition TTree.cxx:6435
virtual void SetDefaultEntryOffsetLen(Int_t newdefault, bool updateExisting=false)
Update the default value for the branch's fEntryOffsetLen.
Definition TTree.cxx:9051
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:3826
Long64_t fMaxVirtualSize
Maximum total size of buffers kept in memory.
Definition TTree.h:104
virtual Long64_t GetTotBytes() const
Definition TTree.h:568
virtual Int_t MakeSelector(const char *selector=nullptr, Option_t *option="")
Generate skeleton selector class for this tree.
Definition TTree.cxx:6842
virtual void SetObject(const char *name, const char *title)
Change the name and title of this tree.
Definition TTree.cxx:9382
TVirtualPerfStats * fPerfStats
! pointer to the current perf stats object
Definition TTree.h:137
Double_t fWeight
Tree weight (see TTree::SetWeight)
Definition TTree.h:95
std::vector< TBranch * > fSeqBranches
! Branches to be processed sequentially when IMT is on
Definition TTree.h:150
Long64_t fDebugMax
! Last entry number to debug
Definition TTree.h:118
Int_t fDefaultEntryOffsetLen
Initial Length of fEntryOffset table in the basket buffers.
Definition TTree.h:99
TTree()
Default constructor and I/O constructor.
Definition TTree.cxx:731
Long64_t fAutoSave
Autosave tree when fAutoSave entries written or -fAutoSave (compressed) bytes produced.
Definition TTree.h:105
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:365
std::atomic< UInt_t > fAllocationCount
indicates basket should be resized to exact memory usage, but causes significant
Definition TTree.h:157
virtual Int_t GetEntryWithIndex(Int_t major, Int_t minor=0)
Read entry corresponding to major and minor number.
Definition TTree.cxx:5947
static TTree * MergeTrees(TList *list, Option_t *option="")
Static function merging the trees in the TList into a new tree.
Definition TTree.cxx:6873
bool MemoryFull(Int_t nbytes)
Check if adding nbytes to memory we are still below MaxVirtualsize.
Definition TTree.cxx:6857
virtual Long64_t GetReadEntry() const
Definition TTree.h:561
virtual TObjArray * GetListOfBranches()
Definition TTree.h:540
Long64_t fZipBytes
Total number of bytes in all branches after compression.
Definition TTree.h:92
virtual TTree * GetTree() const
Definition TTree.h:569
TBuffer * fTransientBuffer
! Pointer to the current transient buffer.
Definition TTree.h:143
virtual void SetEntryList(TEntryList *list, Option_t *opt="")
Set an EntryList.
Definition TTree.cxx:9157
bool Notify() override
Function called when loading a new class library.
Definition TTree.cxx:7129
virtual void AddZipBytes(Int_t zip)
Definition TTree.h:344
virtual Long64_t LoadTree(Long64_t entry)
Set current entry.
Definition TTree.cxx:6493
virtual Long64_t ReadFile(const char *filename, const char *branchDescriptor="", char delimiter=' ')
Create or simply read branches from filename.
Definition TTree.cxx:7661
virtual const char * GetAlias(const char *aliasName) const
Returns the expanded value of the alias. Search in the friends if any.
Definition TTree.cxx:5241
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:9241
virtual TBasket * CreateBasket(TBranch *)
Create a basket for this tree and given branch.
Definition TTree.cxx:3738
TList * fUserInfo
pointer to a list of user objects associated to this Tree
Definition TTree.h:138
virtual Double_t GetMinimum(const char *columname)
Return minimum of column with name columname.
Definition TTree.cxx:6295
virtual void RemoveFriend(TTree *)
Remove a friend from the list of friends.
Definition TTree.cxx:8074
virtual Long64_t GetEntriesFast() const
Return a number greater or equal to the total number of entries in the dataset.
Definition TTree.h:517
void Browse(TBrowser *) override
Browse content of the TTree.
Definition TTree.cxx:2606
virtual TList * GetUserInfo()
Return a pointer to the list containing user objects associated to this tree.
Definition TTree.cxx:6376
Long64_t fChainOffset
! Offset of 1st entry of this Tree in a TChain
Definition TTree.h:111
@ kOnlyFlushAtCluster
If set, the branch's buffers will grow until an event cluster boundary is hit, guaranteeing a basket ...
Definition TTree.h:268
@ kEntriesReshuffled
If set, signals that this TTree is the output of the processing of another TTree, and the entries are...
Definition TTree.h:273
@ kCircular
Definition TTree.h:264
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:5530
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:7610
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:2401
virtual void SetBasketSize(const char *bname, Int_t buffsize=16000)
Set a branch's basket size.
Definition TTree.cxx:8469
static void SetBranchStyle(Int_t style=1)
Set the current branch style.
Definition TTree.cxx:8776
~TTree() override
Destructor.
Definition TTree.cxx:914
void ImportClusterRanges(TTree *fromtree)
Appends the cluster range information stored in 'fromtree' to this tree, including the value of fAuto...
Definition TTree.cxx:6392
TClass * IsA() const override
Definition TTree.h:717
Long64_t fEstimate
Number of entries to estimate histogram limits.
Definition TTree.h:107
Int_t FlushBasketsImpl() const
Internal implementation of the FlushBaskets algorithm.
Definition TTree.cxx:5161
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:6577
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:9877
TVirtualIndex * fTreeIndex
Pointer to the tree Index (if any)
Definition TTree.h:134
void UseCurrentStyle() override
Replace current attributes by current style.
Definition TTree.cxx:9838
TObject * fNotify
Object to be notified when loading a Tree.
Definition TTree.h:125
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:1548
Long64_t fCacheSize
! Maximum size of file buffers
Definition TTree.h:110
TList * fClones
! List of cloned trees which share our addresses
Definition TTree.h:140
std::atomic< Long64_t > fTotalBuffers
! Total number of bytes in branch buffers
Definition TTree.h:113
static TClass * Class()
@ kFindBranch
Definition TTree.h:223
@ kResetBranchAddresses
Definition TTree.h:236
@ kFindLeaf
Definition TTree.h:224
@ kGetEntryWithIndex
Definition TTree.h:228
@ kPrint
Definition TTree.h:233
@ kGetFriend
Definition TTree.h:229
@ kGetBranch
Definition TTree.h:226
@ kSetBranchStatus
Definition TTree.h:235
@ kLoadTree
Definition TTree.h:232
@ kGetEntry
Definition TTree.h:227
@ kGetLeaf
Definition TTree.h:231
@ kRemoveFriend
Definition TTree.h:234
@ kGetFriendAlias
Definition TTree.h:230
@ kGetAlias
Definition TTree.h:225
virtual void SetTreeIndex(TVirtualIndex *index)
The current TreeIndex is replaced by the new index.
Definition TTree.cxx:9468
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:7153
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:7595
virtual Int_t SetCacheEntryRange(Long64_t first, Long64_t last)
interface to TTreeCache to set the cache entry range
Definition TTree.cxx:8942
static Long64_t GetMaxTreeSize()
Static function which returns the tree file size limit in bytes.
Definition TTree.cxx:6285
bool fCacheDoClusterPrefetch
! true if cache is prefetching whole clusters
Definition TTree.h:145
Int_t SetBranchAddressImp(TBranch *branch, void *addr, TBranch **ptr)
Change branch address, dealing with clone trees properly.
Definition TTree.cxx:8556
virtual bool SetAlias(const char *aliasName, const char *aliasFormula)
Set a tree variable alias.
Definition TTree.cxx:8252
virtual void CopyAddresses(TTree *, bool undo=false)
Set branch addresses of passed tree equal to ours.
Definition TTree.cxx:3306
Long64_t fMaxEntries
Maximum number of entries in case of circular buffers.
Definition TTree.h:102
virtual void DropBuffers(Int_t nbytes)
Drop branch buffers to accommodate nbytes below MaxVirtualsize.
Definition TTree.cxx:4548
virtual TList * GetListOfFriends() const
Definition TTree.h:542
virtual void Refresh()
Refresh contents of this tree and its branches from the current status on disk.
Definition TTree.cxx:8013
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:8307
static Long64_t fgMaxTreeSize
Maximum size of a file containing a Tree.
Definition TTree.h:160
Long64_t fReadEntry
! Number of the entry being processed
Definition TTree.h:112
TArrayD fIndexValues
Sorted index values.
Definition TTree.h:132
void MarkEventCluster()
Mark the previous event as being at the end of the event cluster.
Definition TTree.cxx:8369
UInt_t fNEntriesSinceSorting
! Number of entries processed since the last re-sorting of branches
Definition TTree.h:148
virtual void SetFileNumber(Int_t number=0)
Set fFileNumber to number.
Definition TTree.cxx:9264
virtual TLeaf * FindLeaf(const char *name)
Find leaf..
Definition TTree.cxx:4931
virtual void StartViewer()
Start the TTreeViewer on this tree.
Definition TTree.cxx:9581
Int_t GetMakeClass() const
Definition TTree.h:547
virtual Int_t MakeCode(const char *filename=nullptr)
Generate a skeleton function for this tree.
Definition TTree.cxx:6660
bool fIMTFlush
! True if we are doing a multithreaded flush.
Definition TTree.h:164
TDirectory * fDirectory
! Pointer to directory holding this tree
Definition TTree.h:126
@ kNeedEnableDecomposedObj
Definition TTree.h:256
@ kClassMismatch
Definition TTree.h:249
@ kVoidPtr
Definition TTree.h:254
@ kMatchConversionCollection
Definition TTree.h:252
@ kMissingCompiledCollectionProxy
Definition TTree.h:247
@ kMismatch
Definition TTree.h:248
@ kMatchConversion
Definition TTree.h:251
@ kInternalError
Definition TTree.h:246
@ kMatch
Definition TTree.h:250
@ kMissingBranch
Definition TTree.h:245
@ kMakeClass
Definition TTree.h:253
static Int_t fgBranchStyle
Old/New branch style.
Definition TTree.h:159
virtual void ResetBranchAddresses()
Tell all of our branches to drop their current objects and allocate new ones.
Definition TTree.cxx:8172
Int_t fNfill
! Local for EntryLoop
Definition TTree.h:115
void SetName(const char *name) override
Change the name of this tree.
Definition TTree.cxx:9327
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:8054
TArrayI fIndex
Index of sorted values.
Definition TTree.h:133
virtual Int_t SetCacheSize(Long64_t cachesize=-1)
Set maximum size of the file cache .
Definition TTree.cxx:8794
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:1213
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:2868
TBuffer * GetTransientBuffer(Int_t size)
Returns the transient buffer currently used by this TTree for reading/writing baskets.
Definition TTree.cxx:1031
ROOT::TIOFeatures GetIOFeatures() const
Returns the current set of IO settings.
Definition TTree.cxx:6094
virtual Int_t MakeClass(const char *classname=nullptr, Option_t *option="")
Generate a skeleton analysis class for this tree.
Definition TTree.cxx:6627
virtual const char * GetFriendAlias(TTree *) const
If the 'tree' is a friend, this method returns its alias name.
Definition TTree.cxx:6052
virtual void RemoveExternalFriend(TFriendElement *)
Removes external friend.
Definition TTree.cxx:8065
Int_t fPacketSize
! Number of entries in one packet for parallel root
Definition TTree.h:114
virtual TBranch * BranchImpArr(const char *branchname, EDataType datatype, std::size_t N, void *addobj, Int_t bufsize, Int_t splitlevel)
Definition TTree.cxx:1725
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:8210
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:2409
virtual void AddTotBytes(Int_t tot)
Definition TTree.h:343
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:3541
Int_t fMakeClass
! not zero when processing code generated by MakeClass
Definition TTree.h:120
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:6471
static constexpr Long64_t kMaxEntries
Definition TTree.h:241
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:7296
std::unordered_map< std::string, TBranch * > fNamesToBranches
! maps names to their branches, useful when retrieving branches by name
Definition TTree.h:169
virtual Long64_t GetAutoFlush() const
Definition TTree.h:459
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:177
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
void TBranch__SetTree(TTree *tree, TObjArray &branches)
Set the fTree member for all branches and sub branches.
Definition TTree.cxx:9630
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:595
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:403
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:1354
Double_t Ceil(Double_t x)
Rounds x upward, returning the smallest integral value that is not less than x.
Definition TMath.h:674
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