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-2000, 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 In order to store columnar datasets, ROOT provides the TTree, TChain,
15 TNtuple and TNtupleD classes.
16 The TTree class represents a columnar dataset. Any C++ type can be stored in the
17 columns. The TTree has allowed to store about **1 EB** of data coming from the LHC alone:
18 it is demonstrated to scale and it's battle tested. It has been optimized during the years
19 to reduce dataset sizes on disk and to deliver excellent runtime performance.
20 It allows to access only part of the columns of the datasets, too.
21 The TNtuple and TNtupleD classes are specialisations of the TTree class which can
22 only hold single precision and double precision floating-point numbers respectively;
23 The TChain is a collection of TTrees, which can be located also in different files.
24
25*/
26
27/** \class TTree
28\ingroup tree
29
30A TTree represents a columnar dataset. Any C++ type can be stored in its columns.
31
32A TTree, often called in jargon *tree*, consists of a list of independent columns or *branches*,
33represented by the TBranch class.
34Behind each branch, buffers are allocated automatically by ROOT.
35Such buffers are automatically written to disk or kept in memory until the size stored in the
36attribute fMaxVirtualSize is reached.
37Variables of one branch are written to the same buffer. A branch buffer is
38automatically compressed if the file compression attribute is set (default).
39Branches may be written to different files (see TBranch::SetFile).
40
41The ROOT user can decide to make one single branch and serialize one object into
42one single I/O buffer or to make several branches.
43Making several branches is particularly interesting in the data analysis phase,
44when it is desirable to have a high reading rate and not all columns are equally interesting
45
46\anchor creatingattreetoc
47## Create a TTree to store columnar data
48- [Construct a TTree](\ref creatingattree)
49- [Add a column of Fundamental Types and Arrays thereof](\ref addcolumnoffundamentaltypes)
50- [Add a column of a STL Collection instances](\ref addingacolumnofstl)
51- [Add a column holding an object](\ref addingacolumnofobjs)
52- [Add a column holding a TObjectArray](\ref addingacolumnofobjs)
53- [Fill the tree](\ref fillthetree)
54- [Add a column to an already existing Tree](\ref addcoltoexistingtree)
55- [An Example](\ref fullexample)
56
57\anchor creatingattree
58## Construct a TTree
59
60~~~ {.cpp}
61 TTree tree(name, title)
62~~~
63Creates a Tree with name and title.
64
65Various kinds of branches can be added to a tree:
66- Variables representing fundamental types, simple classes/structures or list of variables: for example for C or Fortran
67structures.
68- Any C++ object or collection, provided by the STL or ROOT.
69
70In the following, the details about the creation of different types of branches are given.
71
72\anchor addcolumnoffundamentaltypes
73## Add a column ("branch") holding fundamental types and arrays thereof
74This strategy works also for lists of variables, e.g. to describe simple structures.
75It is strongly recommended to persistify those as objects rather than lists of leaves.
76
77~~~ {.cpp}
78 auto branch = tree.Branch(branchname, address, leaflist, bufsize)
79~~~
80- address is the address of the first item of a structure
81- leaflist is the concatenation of all the variable names and types
82 separated by a colon character :
83 The variable name and the variable type are separated by a
84 slash (/). The variable type must be 1 character. (Characters
85 after the first are legal and will be appended to the visible
86 name of the leaf, but have no effect.) If no type is given, the
87 type of the variable is assumed to be the same as the previous
88 variable. If the first variable does not have a type, it is
89 assumed of type F by default. The list of currently supported
90 types is given below:
91 - `C` : a character string terminated by the 0 character
92 - `B` : an 8 bit signed integer (`Char_t`); Treated as a character when in an array.
93 - `b` : an 8 bit unsigned integer (`UChar_t`)
94 - `S` : a 16 bit signed integer (`Short_t`)
95 - `s` : a 16 bit unsigned integer (`UShort_t`)
96 - `I` : a 32 bit signed integer (`Int_t`)
97 - `i` : a 32 bit unsigned integer (`UInt_t`)
98 - `F` : a 32 bit floating point (`Float_t`)
99 - `f` : a 24 bit floating point with truncated mantissa (`Float16_t`)
100 - `D` : a 64 bit floating point (`Double_t`)
101 - `d` : a 24 bit truncated floating point (`Double32_t`)
102 - `L` : a 64 bit signed integer (`Long64_t`)
103 - `l` : a 64 bit unsigned integer (`ULong64_t`)
104 - `G` : a long signed integer, stored as 64 bit (`Long_t`)
105 - `g` : a long unsigned integer, stored as 64 bit (`ULong_t`)
106 - `O` : [the letter `o`, not a zero] a boolean (`bool`)
107
108 Examples:
109 - A int: "myVar/I"
110 - A float array with fixed size: "myArrfloat[42]/F"
111 - An double array with variable size, held by the `myvar` column: "myArrdouble[myvar]/D"
112 - An Double32_t array with variable size, held by the `myvar` column , with values between 0 and 16: "myArr[myvar]/d[0,10]"
113 - The `myvar` column, which holds the variable size, **MUST** be an `Int_t` (/I).
114
115- If the address points to a single numerical variable, the leaflist is optional:
116~~~ {.cpp}
117 int value;
118 tree->Branch(branchname, &value);
119~~~
120- If the address points to more than one numerical variable, we strongly recommend
121 that the variable be sorted in decreasing order of size. Any other order will
122 result in a non-portable TTree (i.e. you will not be able to read it back on a
123 platform with a different padding strategy).
124 We recommend to persistify objects rather than composite leaflists.
125- In case of the truncated floating point types (Float16_t and Double32_t) you can
126 furthermore specify the range in the style [xmin,xmax] or [xmin,xmax,nbits] after
127 the type character. For example, for storing a variable size array `myArr` of
128 `Double32_t` with values within a range of `[0, 2*pi]` and the size of which is stored
129 in an `Int_t` (/I) branch called `myArrSize`, the syntax for the `leaflist` string would
130 be: `myArr[myArrSize]/d[0,twopi]`. Of course the number of bits could be specified,
131 the standard rules of opaque typedefs annotation are valid. For example, if only
132 18 bits were sufficient, the syntax would become: `myArr[myArrSize]/d[0,twopi,18]`
133
134\anchor addingacolumnofstl
135## Adding a column holding STL collection instances (e.g. std::vector, std::list, std::unordered_map)
136
137~~~ {.cpp}
138 auto branch = tree.Branch( branchname, STLcollection, buffsize, splitlevel);
139~~~
140STLcollection is the address of a pointer to std::vector, std::list,
141std::deque, std::set or std::multiset containing pointers to objects.
142If the splitlevel is a value bigger than 100 (TTree::kSplitCollectionOfPointers)
143then the collection will be written in split mode, e.g. if it contains objects of
144any types deriving from TTrack this function will sort the objects
145based on their type and store them in separate branches in split
146mode.
147
148~~~ {.cpp}
149 branch->SetAddress(void *address)
150~~~
151In case of dynamic structures changing with each entry for example, one must
152redefine the branch address before filling the branch again.
153This is done via the TBranch::SetAddress member function.
154
155\anchor addingacolumnofobjs
156## Add a column holding objects
157
158~~~ {.cpp}
159 MyClass object;
160 auto branch = tree.Branch(branchname, &object, bufsize, splitlevel)
161~~~
162Note: The 2nd parameter must be the address of a valid object.
163 The object must not be destroyed (i.e. be deleted) until the TTree
164 is deleted or TTree::ResetBranchAddress is called.
165
166- if splitlevel=0, the object is serialized in the branch buffer.
167- if splitlevel=1 (default), this branch will automatically be split
168 into subbranches, with one subbranch for each data member or object
169 of the object itself. In case the object member is a TClonesArray,
170 the mechanism described in case C is applied to this array.
171- if splitlevel=2 ,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 it is processed as a TObject*, only one branch.
175
176Another available syntax is the following:
177
178~~~ {.cpp}
179 auto branch = tree.Branch(branchname, &p_object, bufsize, splitlevel)
180 auto branch = tree.Branch(branchname, className, &p_object, bufsize, splitlevel)
181~~~
182- p_object is a pointer to an object.
183- If className is not specified, Branch uses the type of p_object to determine the
184 type of the object.
185- If className is used to specify explicitly the object type, the className must
186 be of a type related to the one pointed to by the pointer. It should be either
187 a parent or derived class.
188
189Note: The pointer whose address is passed to TTree::Branch must not
190 be destroyed (i.e. go out of scope) until the TTree is deleted or
191 TTree::ResetBranchAddress is called.
192
193Note: The pointer p_object must be initialized before calling TTree::Branch
194- Do either:
195~~~ {.cpp}
196 MyDataClass* p_object = nullptr;
197 tree.Branch(branchname, &p_object);
198~~~
199- Or:
200~~~ {.cpp}
201 auto p_object = new MyDataClass;
202 tree.Branch(branchname, &p_object);
203~~~
204Whether the pointer is set to zero or not, the ownership of the object
205is not taken over by the TTree. I.e. even though an object will be allocated
206by TTree::Branch if the pointer p_object is zero, the object will <b>not</b>
207be deleted when the TTree is deleted.
208
209\anchor addingacolumnoftclonesarray
210## Add a column holding TClonesArray instances
211
212*It is recommended to use STL containers instead of TClonesArrays*.
213
214~~~ {.cpp}
215 // clonesarray is the address of a pointer to a TClonesArray.
216 auto branch = tree.Branch(branchname,clonesarray, bufsize, splitlevel)
217~~~
218The TClonesArray is a direct access list of objects of the same class.
219For example, if the TClonesArray is an array of TTrack objects,
220this function will create one subbranch for each data member of
221the object TTrack.
222
223\anchor fillthetree
224## Fill the Tree
225
226A TTree instance is filled with the invocation of the TTree::Fill method:
227~~~ {.cpp}
228 tree.Fill()
229~~~
230Upon its invocation, a loop on all defined branches takes place that for each branch invokes
231the TBranch::Fill method.
232
233\anchor addcoltoexistingtree
234## Add a column to an already existing Tree
235
236You may want to add a branch to an existing tree. For example,
237if one variable in the tree was computed with a certain algorithm,
238you may want to try another algorithm and compare the results.
239One solution is to add a new branch, fill it, and save the tree.
240The code below adds a simple branch to an existing tree.
241Note the kOverwrite option in the Write method, it overwrites the
242existing tree. If it is not specified, two copies of the tree headers
243are saved.
244~~~ {.cpp}
245 void tree3AddBranch() {
246 TFile f("tree3.root", "update");
247
248 Float_t new_v;
249 auto t3 = f->Get<TTree>("t3");
250 auto newBranch = t3->Branch("new_v", &new_v, "new_v/F");
251
252 Long64_t nentries = t3->GetEntries(); // read the number of entries in the t3
253
254 for (Long64_t i = 0; i < nentries; i++) {
255 new_v = gRandom->Gaus(0, 1);
256 newBranch->Fill();
257 }
258
259 t3->Write("", TObject::kOverwrite); // save only the new version of the tree
260 }
261~~~
262It is not always possible to add branches to existing datasets stored in TFiles: for example,
263these files might not be writeable, just readable. In addition, modifying in place a TTree
264causes a new TTree instance to be written and the previous one to be deleted.
265For this reasons, ROOT offers the concept of friends for TTree and TChain:
266if is good practice to rely on friend trees rather than adding a branch manually.
267
268\anchor fullexample
269## An Example
270
271Begin_Macro
272../../../tutorials/tree/tree.C
273End_Macro
274
275~~~ {.cpp}
276 // A simple example with histograms and a tree
277 //
278 // This program creates :
279 // - a one dimensional histogram
280 // - a two dimensional histogram
281 // - a profile histogram
282 // - a tree
283 //
284 // These objects are filled with some random numbers and saved on a file.
285
286 #include "TFile.h"
287 #include "TH1.h"
288 #include "TH2.h"
289 #include "TProfile.h"
290 #include "TRandom.h"
291 #include "TTree.h"
292
293 //__________________________________________________________________________
294 main(int argc, char **argv)
295 {
296 // Create a new ROOT binary machine independent file.
297 // Note that this file may contain any kind of ROOT objects, histograms,trees
298 // pictures, graphics objects, detector geometries, tracks, events, etc..
299 // This file is now becoming the current directory.
300 TFile hfile("htree.root","RECREATE","Demo ROOT file with histograms & trees");
301
302 // Create some histograms and a profile histogram
303 TH1F hpx("hpx","This is the px distribution",100,-4,4);
304 TH2F hpxpy("hpxpy","py ps px",40,-4,4,40,-4,4);
305 TProfile hprof("hprof","Profile of pz versus px",100,-4,4,0,20);
306
307 // Define some simple structures
308 typedef struct {Float_t x,y,z;} POINT;
309 typedef struct {
310 Int_t ntrack,nseg,nvertex;
311 UInt_t flag;
312 Float_t temperature;
313 } EVENTN;
314 POINT point;
315 EVENTN eventn;
316
317 // Create a ROOT Tree
318 TTree tree("T","An example of ROOT tree with a few branches");
319 tree.Branch("point",&point,"x:y:z");
320 tree.Branch("eventn",&eventn,"ntrack/I:nseg:nvertex:flag/i:temperature/F");
321 tree.Branch("hpx","TH1F",&hpx,128000,0);
322
323 Float_t px,py,pz;
324
325 // Here we start a loop on 1000 events
326 for ( Int_t i=0; i<1000; i++) {
327 gRandom->Rannor(px,py);
328 pz = px*px + py*py;
329 const auto random = gRandom->::Rndm(1);
330
331 // Fill histograms
332 hpx.Fill(px);
333 hpxpy.Fill(px,py,1);
334 hprof.Fill(px,pz,1);
335
336 // Fill structures
337 point.x = 10*(random-1);
338 point.y = 5*random;
339 point.z = 20*random;
340 eventn.ntrack = Int_t(100*random);
341 eventn.nseg = Int_t(2*eventn.ntrack);
342 eventn.nvertex = 1;
343 eventn.flag = Int_t(random+0.5);
344 eventn.temperature = 20+random;
345
346 // Fill the tree. For each event, save the 2 structures and 3 objects
347 // In this simple example, the objects hpx, hprof and hpxpy are slightly
348 // different from event to event. We expect a big compression factor!
349 tree->Fill();
350 }
351 // End of the loop
352
353 tree.Print();
354
355 // Save all objects in this file
356 hfile.Write();
357
358 // Close the file. Note that this is automatically done when you leave
359 // the application upon file destruction.
360 hfile.Close();
361
362 return 0;
363}
364~~~
365*/
366
367#include <ROOT/RConfig.hxx>
368#include "TTree.h"
369
370#include "ROOT/TIOFeatures.hxx"
371#include "TArrayC.h"
372#include "TBufferFile.h"
373#include "TBaseClass.h"
374#include "TBasket.h"
375#include "TBranchClones.h"
376#include "TBranchElement.h"
377#include "TBranchObject.h"
378#include "TBranchRef.h"
379#include "TBrowser.h"
380#include "TClass.h"
381#include "TClassEdit.h"
382#include "TClonesArray.h"
383#include "TCut.h"
384#include "TDataMember.h"
385#include "TDataType.h"
386#include "TDirectory.h"
387#include "TError.h"
388#include "TEntryList.h"
389#include "TEnv.h"
390#include "TEventList.h"
391#include "TFile.h"
392#include "TFolder.h"
393#include "TFriendElement.h"
394#include "TInterpreter.h"
395#include "TLeaf.h"
396#include "TLeafB.h"
397#include "TLeafC.h"
398#include "TLeafD.h"
399#include "TLeafElement.h"
400#include "TLeafF.h"
401#include "TLeafI.h"
402#include "TLeafL.h"
403#include "TLeafObject.h"
404#include "TLeafS.h"
405#include "TList.h"
406#include "TMath.h"
407#include "TMemFile.h"
408#include "TROOT.h"
409#include "TRealData.h"
410#include "TRegexp.h"
411#include "TRefTable.h"
412#include "TStreamerElement.h"
413#include "TStreamerInfo.h"
414#include "TStyle.h"
415#include "TSystem.h"
416#include "TTreeCloner.h"
417#include "TTreeCache.h"
418#include "TTreeCacheUnzip.h"
421#include "TVirtualIndex.h"
422#include "TVirtualPerfStats.h"
423#include "TVirtualPad.h"
424#include "TBranchSTL.h"
425#include "TSchemaRuleSet.h"
426#include "TFileMergeInfo.h"
427#include "ROOT/StringConv.hxx"
428#include "TVirtualMutex.h"
429#include "strlcpy.h"
430#include "snprintf.h"
431
432#include "TBranchIMTHelper.h"
433#include "TNotifyLink.h"
434
435#include <chrono>
436#include <cstddef>
437#include <iostream>
438#include <fstream>
439#include <sstream>
440#include <string>
441#include <cstdio>
442#include <climits>
443#include <algorithm>
444#include <set>
445
446#ifdef R__USE_IMT
448#include <thread>
449#endif
451constexpr Int_t kNEntriesResort = 100;
453
454Int_t TTree::fgBranchStyle = 1; // Use new TBranch style with TBranchElement.
455Long64_t TTree::fgMaxTreeSize = 100000000000LL;
456
458
459////////////////////////////////////////////////////////////////////////////////
460////////////////////////////////////////////////////////////////////////////////
461////////////////////////////////////////////////////////////////////////////////
463static char DataTypeToChar(EDataType datatype)
464{
465 // Return the leaflist 'char' for a given datatype.
466
467 switch(datatype) {
468 case kChar_t: return 'B';
469 case kUChar_t: return 'b';
470 case kBool_t: return 'O';
471 case kShort_t: return 'S';
472 case kUShort_t: return 's';
473 case kCounter:
474 case kInt_t: return 'I';
475 case kUInt_t: return 'i';
476 case kDouble_t: return 'D';
477 case kDouble32_t: return 'd';
478 case kFloat_t: return 'F';
479 case kFloat16_t: return 'f';
480 case kLong_t: return 'G';
481 case kULong_t: return 'g';
482 case kchar: return 0; // unsupported
483 case kLong64_t: return 'L';
484 case kULong64_t: return 'l';
485
486 case kCharStar: return 'C';
487 case kBits: return 0; //unsupported
488
489 case kOther_t:
490 case kNoType_t:
491 default:
492 return 0;
493 }
494 return 0;
495}
496
497////////////////////////////////////////////////////////////////////////////////
498/// \class TTree::TFriendLock
499/// Helper class to prevent infinite recursion in the usage of TTree Friends.
500
501////////////////////////////////////////////////////////////////////////////////
502/// Record in tree that it has been used while recursively looks through the friends.
505: fTree(tree)
506{
507 // We could also add some code to acquire an actual
508 // lock to prevent multi-thread issues
509 fMethodBit = methodbit;
510 if (fTree) {
513 } else {
514 fPrevious = false;
515 }
516}
517
518////////////////////////////////////////////////////////////////////////////////
519/// Copy constructor.
522 fTree(tfl.fTree),
523 fMethodBit(tfl.fMethodBit),
524 fPrevious(tfl.fPrevious)
525{
526}
527
528////////////////////////////////////////////////////////////////////////////////
529/// Assignment operator.
532{
533 if(this!=&tfl) {
534 fTree=tfl.fTree;
535 fMethodBit=tfl.fMethodBit;
536 fPrevious=tfl.fPrevious;
537 }
538 return *this;
539}
540
541////////////////////////////////////////////////////////////////////////////////
542/// Restore the state of tree the same as before we set the lock.
545{
546 if (fTree) {
547 if (!fPrevious) {
548 fTree->fFriendLockStatus &= ~(fMethodBit & kBitMask);
549 }
550 }
551}
552
553////////////////////////////////////////////////////////////////////////////////
554/// \class TTree::TClusterIterator
555/// Helper class to iterate over cluster of baskets.
556
557////////////////////////////////////////////////////////////////////////////////
558/// Regular constructor.
559/// TTree is not set as const, since we might modify if it is a TChain.
561TTree::TClusterIterator::TClusterIterator(TTree *tree, Long64_t firstEntry) : fTree(tree), fClusterRange(0), fStartEntry(0), fNextEntry(0), fEstimatedSize(-1)
562{
563 if (fTree->fNClusterRange) {
564 // Find the correct cluster range.
565 //
566 // Since fClusterRangeEnd contains the inclusive upper end of the range, we need to search for the
567 // range that was containing the previous entry and add 1 (because BinarySearch consider the values
568 // to be the inclusive start of the bucket).
570
571 Long64_t entryInRange;
572 Long64_t pedestal;
573 if (fClusterRange == 0) {
574 pedestal = 0;
575 entryInRange = firstEntry;
576 } else {
577 pedestal = fTree->fClusterRangeEnd[fClusterRange-1] + 1;
578 entryInRange = firstEntry - pedestal;
579 }
580 Long64_t autoflush;
582 autoflush = fTree->fAutoFlush;
583 } else {
584 autoflush = fTree->fClusterSize[fClusterRange];
585 }
586 if (autoflush <= 0) {
587 autoflush = GetEstimatedClusterSize();
588 }
589 fStartEntry = pedestal + entryInRange - entryInRange%autoflush;
590 } else if ( fTree->GetAutoFlush() <= 0 ) {
591 // Case of old files before November 9 2009 *or* small tree where AutoFlush was never set.
592 fStartEntry = firstEntry;
593 } else {
594 fStartEntry = firstEntry - firstEntry%fTree->GetAutoFlush();
595 }
596 fNextEntry = fStartEntry; // Position correctly for the first call to Next()
597}
598
599////////////////////////////////////////////////////////////////////////////////
600/// Estimate the cluster size.
601///
602/// In almost all cases, this quickly returns the size of the auto-flush
603/// in the TTree.
604///
605/// However, in the case where the cluster size was not fixed (old files and
606/// case where autoflush was explicitly set to zero), we need estimate
607/// a cluster size in relation to the size of the cache.
608///
609/// After this value is calculated once for the TClusterIterator, it is
610/// cached and reused in future calls.
613{
614 auto autoFlush = fTree->GetAutoFlush();
615 if (autoFlush > 0) return autoFlush;
616 if (fEstimatedSize > 0) return fEstimatedSize;
617
618 Long64_t zipBytes = fTree->GetZipBytes();
619 if (zipBytes == 0) {
620 fEstimatedSize = fTree->GetEntries() - 1;
621 if (fEstimatedSize <= 0)
622 fEstimatedSize = 1;
623 } else {
624 Long64_t clusterEstimate = 1;
625 Long64_t cacheSize = fTree->GetCacheSize();
626 if (cacheSize == 0) {
627 // Humm ... let's double check on the file.
628 TFile *file = fTree->GetCurrentFile();
629 if (file) {
630 TFileCacheRead *cache = fTree->GetReadCache(file);
631 if (cache) {
632 cacheSize = cache->GetBufferSize();
633 }
634 }
635 }
636 // If neither file nor tree has a cache, use the current default.
637 if (cacheSize <= 0) {
638 cacheSize = 30000000;
639 }
640 clusterEstimate = fTree->GetEntries() * cacheSize / zipBytes;
641 // If there are no entries, then just default to 1.
642 fEstimatedSize = clusterEstimate ? clusterEstimate : 1;
643 }
644 return fEstimatedSize;
645}
646
647////////////////////////////////////////////////////////////////////////////////
648/// Move on to the next cluster and return the starting entry
649/// of this next cluster
652{
653 fStartEntry = fNextEntry;
654 if (fTree->fNClusterRange || fTree->GetAutoFlush() > 0) {
655 if (fClusterRange == fTree->fNClusterRange) {
656 // We are looking at a range which size
657 // is defined by AutoFlush itself and goes to the GetEntries.
658 fNextEntry += GetEstimatedClusterSize();
659 } else {
660 if (fStartEntry > fTree->fClusterRangeEnd[fClusterRange]) {
661 ++fClusterRange;
662 }
663 if (fClusterRange == fTree->fNClusterRange) {
664 // We are looking at the last range which size
665 // is defined by AutoFlush itself and goes to the GetEntries.
666 fNextEntry += GetEstimatedClusterSize();
667 } else {
668 Long64_t clusterSize = fTree->fClusterSize[fClusterRange];
669 if (clusterSize == 0) {
670 clusterSize = GetEstimatedClusterSize();
671 }
672 fNextEntry += clusterSize;
673 if (fNextEntry > fTree->fClusterRangeEnd[fClusterRange]) {
674 // The last cluster of the range was a partial cluster,
675 // so the next cluster starts at the beginning of the
676 // next range.
677 fNextEntry = fTree->fClusterRangeEnd[fClusterRange] + 1;
678 }
679 }
680 }
681 } else {
682 // Case of old files before November 9 2009
683 fNextEntry = fStartEntry + GetEstimatedClusterSize();
684 }
685 if (fNextEntry > fTree->GetEntries()) {
686 fNextEntry = fTree->GetEntries();
687 }
688 return fStartEntry;
689}
690
691////////////////////////////////////////////////////////////////////////////////
692/// Move on to the previous cluster and return the starting entry
693/// of this previous cluster
696{
697 fNextEntry = fStartEntry;
698 if (fTree->fNClusterRange || fTree->GetAutoFlush() > 0) {
699 if (fClusterRange == 0 || fTree->fNClusterRange == 0) {
700 // We are looking at a range which size
701 // is defined by AutoFlush itself.
702 fStartEntry -= GetEstimatedClusterSize();
703 } else {
704 if (fNextEntry <= fTree->fClusterRangeEnd[fClusterRange]) {
705 --fClusterRange;
706 }
707 if (fClusterRange == 0) {
708 // We are looking at the first range.
709 fStartEntry = 0;
710 } else {
711 Long64_t clusterSize = fTree->fClusterSize[fClusterRange];
712 if (clusterSize == 0) {
713 clusterSize = GetEstimatedClusterSize();
714 }
715 fStartEntry -= clusterSize;
716 }
717 }
718 } else {
719 // Case of old files before November 9 2009 or trees that never auto-flushed.
720 fStartEntry = fNextEntry - GetEstimatedClusterSize();
721 }
722 if (fStartEntry < 0) {
723 fStartEntry = 0;
724 }
725 return fStartEntry;
726}
727
728////////////////////////////////////////////////////////////////////////////////
729////////////////////////////////////////////////////////////////////////////////
730////////////////////////////////////////////////////////////////////////////////
731
732////////////////////////////////////////////////////////////////////////////////
733/// Default constructor and I/O constructor.
734///
735/// Note: We do *not* insert ourself into the current directory.
736///
739: TNamed()
740, TAttLine()
741, TAttFill()
742, TAttMarker()
743, fEntries(0)
744, fTotBytes(0)
745, fZipBytes(0)
746, fSavedBytes(0)
747, fFlushedBytes(0)
748, fWeight(1)
750, fScanField(25)
751, fUpdate(0)
755, fMaxEntries(0)
756, fMaxEntryLoop(0)
758, fAutoSave( -300000000)
759, fAutoFlush(-30000000)
760, fEstimate(1000000)
761, fClusterRangeEnd(nullptr)
762, fClusterSize(nullptr)
763, fCacheSize(0)
764, fChainOffset(0)
765, fReadEntry(-1)
766, fTotalBuffers(0)
767, fPacketSize(100)
768, fNfill(0)
769, fDebug(0)
770, fDebugMin(0)
771, fDebugMax(9999999)
772, fMakeClass(0)
773, fFileNumber(0)
774, fNotify(nullptr)
775, fDirectory(nullptr)
776, fBranches()
777, fLeaves()
778, fAliases(nullptr)
779, fEventList(nullptr)
780, fEntryList(nullptr)
781, fIndexValues()
782, fIndex()
783, fTreeIndex(nullptr)
784, fFriends(nullptr)
785, fExternalFriends(nullptr)
786, fPerfStats(nullptr)
787, fUserInfo(nullptr)
788, fPlayer(nullptr)
789, fClones(nullptr)
790, fBranchRef(nullptr)
792, fTransientBuffer(nullptr)
793, fCacheDoAutoInit(true)
795, fCacheUserSet(false)
796, fIMTEnabled(ROOT::IsImplicitMTEnabled())
798{
799 fMaxEntries = 1000000000;
800 fMaxEntries *= 1000;
801
802 fMaxEntryLoop = 1000000000;
803 fMaxEntryLoop *= 1000;
804
805 fBranches.SetOwner(true);
806}
807
808////////////////////////////////////////////////////////////////////////////////
809/// Normal tree constructor.
810///
811/// The tree is created in the current directory.
812/// Use the various functions Branch below to add branches to this tree.
813///
814/// If the first character of title is a "/", the function assumes a folder name.
815/// In this case, it creates automatically branches following the folder hierarchy.
816/// splitlevel may be used in this case to control the split level.
818TTree::TTree(const char* name, const char* title, Int_t splitlevel /* = 99 */,
819 TDirectory* dir /* = gDirectory*/)
820: TNamed(name, title)
821, TAttLine()
822, TAttFill()
823, TAttMarker()
824, fEntries(0)
825, fTotBytes(0)
826, fZipBytes(0)
827, fSavedBytes(0)
828, fFlushedBytes(0)
829, fWeight(1)
830, fTimerInterval(0)
831, fScanField(25)
832, fUpdate(0)
833, fDefaultEntryOffsetLen(1000)
834, fNClusterRange(0)
835, fMaxClusterRange(0)
836, fMaxEntries(0)
837, fMaxEntryLoop(0)
838, fMaxVirtualSize(0)
839, fAutoSave( -300000000)
840, fAutoFlush(-30000000)
841, fEstimate(1000000)
842, fClusterRangeEnd(nullptr)
843, fClusterSize(nullptr)
844, fCacheSize(0)
845, fChainOffset(0)
846, fReadEntry(-1)
847, fTotalBuffers(0)
848, fPacketSize(100)
849, fNfill(0)
850, fDebug(0)
851, fDebugMin(0)
852, fDebugMax(9999999)
853, fMakeClass(0)
854, fFileNumber(0)
855, fNotify(nullptr)
856, fDirectory(dir)
857, fBranches()
858, fLeaves()
859, fAliases(nullptr)
860, fEventList(nullptr)
861, fEntryList(nullptr)
862, fIndexValues()
863, fIndex()
864, fTreeIndex(nullptr)
865, fFriends(nullptr)
866, fExternalFriends(nullptr)
867, fPerfStats(nullptr)
868, fUserInfo(nullptr)
869, fPlayer(nullptr)
870, fClones(nullptr)
871, fBranchRef(nullptr)
872, fFriendLockStatus(0)
873, fTransientBuffer(nullptr)
874, fCacheDoAutoInit(true)
875, fCacheDoClusterPrefetch(false)
876, fCacheUserSet(false)
877, fIMTEnabled(ROOT::IsImplicitMTEnabled())
878, fNEntriesSinceSorting(0)
879{
880 // TAttLine state.
884
885 // TAttFill state.
888
889 // TAttMarkerState.
893
894 fMaxEntries = 1000000000;
895 fMaxEntries *= 1000;
896
897 fMaxEntryLoop = 1000000000;
898 fMaxEntryLoop *= 1000;
899
900 // Insert ourself into the current directory.
901 // FIXME: This is very annoying behaviour, we should
902 // be able to choose to not do this like we
903 // can with a histogram.
904 if (fDirectory) fDirectory->Append(this);
905
906 fBranches.SetOwner(true);
907
908 // If title starts with "/" and is a valid folder name, a superbranch
909 // is created.
910 // FIXME: Why?
911 if (strlen(title) > 2) {
912 if (title[0] == '/') {
913 Branch(title+1,32000,splitlevel);
914 }
915 }
916}
917
918////////////////////////////////////////////////////////////////////////////////
919/// Destructor.
922{
923 if (auto link = dynamic_cast<TNotifyLinkBase*>(fNotify)) {
924 link->Clear();
925 }
926 if (fAllocationCount && (gDebug > 0)) {
927 Info("TTree::~TTree", "For tree %s, allocation count is %u.", GetName(), fAllocationCount.load());
928#ifdef R__TRACK_BASKET_ALLOC_TIME
929 Info("TTree::~TTree", "For tree %s, allocation time is %lluus.", GetName(), fAllocationTime.load());
930#endif
931 }
932
933 if (fDirectory) {
934 // We are in a directory, which may possibly be a file.
935 if (fDirectory->GetList()) {
936 // Remove us from the directory listing.
937 fDirectory->Remove(this);
938 }
939 //delete the file cache if it points to this Tree
940 TFile *file = fDirectory->GetFile();
941 MoveReadCache(file,nullptr);
942 }
943
944 // Remove the TTree from any list (linked to to the list of Cleanups) to avoid the unnecessary call to
945 // this RecursiveRemove while we delete our content.
947 ResetBit(kMustCleanup); // Don't redo it.
948
949 // We don't own the leaves in fLeaves, the branches do.
950 fLeaves.Clear();
951 // I'm ready to destroy any objects allocated by
952 // SetAddress() by my branches. If I have clones,
953 // tell them to zero their pointers to this shared
954 // memory.
955 if (fClones && fClones->GetEntries()) {
956 // I have clones.
957 // I am about to delete the objects created by
958 // SetAddress() which we are sharing, so tell
959 // the clones to release their pointers to them.
960 for (TObjLink* lnk = fClones->FirstLink(); lnk; lnk = lnk->Next()) {
961 TTree* clone = (TTree*) lnk->GetObject();
962 // clone->ResetBranchAddresses();
963
964 // Reset only the branch we have set the address of.
965 CopyAddresses(clone,true);
966 }
967 }
968 // Get rid of our branches, note that this will also release
969 // any memory allocated by TBranchElement::SetAddress().
971
972 // The TBranch destructor is using fDirectory to detect whether it
973 // owns the TFile that contains its data (See TBranch::~TBranch)
974 fDirectory = nullptr;
975
976 // FIXME: We must consider what to do with the reset of these if we are a clone.
977 delete fPlayer;
978 fPlayer = nullptr;
979 if (fExternalFriends) {
980 using namespace ROOT::Detail;
982 fetree->Reset();
983 fExternalFriends->Clear("nodelete");
985 }
986 if (fFriends) {
987 fFriends->Delete();
988 delete fFriends;
989 fFriends = nullptr;
990 }
991 if (fAliases) {
992 fAliases->Delete();
993 delete fAliases;
994 fAliases = nullptr;
995 }
996 if (fUserInfo) {
997 fUserInfo->Delete();
998 delete fUserInfo;
999 fUserInfo = nullptr;
1000 }
1001 if (fClones) {
1002 // Clone trees should no longer be removed from fClones when they are deleted.
1003 {
1005 gROOT->GetListOfCleanups()->Remove(fClones);
1006 }
1007 // Note: fClones does not own its content.
1008 delete fClones;
1009 fClones = nullptr;
1010 }
1011 if (fEntryList) {
1012 if (fEntryList->TestBit(kCanDelete) && fEntryList->GetDirectory()==nullptr) {
1013 // Delete the entry list if it is marked to be deleted and it is not also
1014 // owned by a directory. (Otherwise we would need to make sure that a
1015 // TDirectoryFile that has a TTree in it does a 'slow' TList::Delete.
1016 delete fEntryList;
1017 fEntryList=nullptr;
1018 }
1019 }
1020 delete fTreeIndex;
1021 fTreeIndex = nullptr;
1022 delete fBranchRef;
1023 fBranchRef = nullptr;
1024 delete [] fClusterRangeEnd;
1025 fClusterRangeEnd = nullptr;
1026 delete [] fClusterSize;
1027 fClusterSize = nullptr;
1028
1029 if (fTransientBuffer) {
1030 delete fTransientBuffer;
1031 fTransientBuffer = nullptr;
1032 }
1033}
1034
1035////////////////////////////////////////////////////////////////////////////////
1036/// Returns the transient buffer currently used by this TTree for reading/writing baskets.
1039{
1040 if (fTransientBuffer) {
1041 if (fTransientBuffer->BufferSize() < size) {
1043 }
1044 return fTransientBuffer;
1045 }
1047 return fTransientBuffer;
1048}
1049
1050////////////////////////////////////////////////////////////////////////////////
1051/// Add branch with name bname to the Tree cache.
1052/// If bname="*" all branches are added to the cache.
1053/// if subbranches is true all the branches of the subbranches are
1054/// also put to the cache.
1055///
1056/// Returns:
1057/// - 0 branch added or already included
1058/// - -1 on error
1060Int_t TTree::AddBranchToCache(const char*bname, bool subbranches)
1061{
1062 if (!GetTree()) {
1063 if (LoadTree(0)<0) {
1064 Error("AddBranchToCache","Could not load a tree");
1065 return -1;
1066 }
1067 }
1068 if (GetTree()) {
1069 if (GetTree() != this) {
1070 return GetTree()->AddBranchToCache(bname, subbranches);
1071 }
1072 } else {
1073 Error("AddBranchToCache", "No tree is available. Branch was not added to the cache");
1074 return -1;
1075 }
1076
1077 TFile *f = GetCurrentFile();
1078 if (!f) {
1079 Error("AddBranchToCache", "No file is available. Branch was not added to the cache");
1080 return -1;
1081 }
1082 TTreeCache *tc = GetReadCache(f,true);
1083 if (!tc) {
1084 Error("AddBranchToCache", "No cache is available, branch not added");
1085 return -1;
1086 }
1087 return tc->AddBranch(bname,subbranches);
1088}
1089
1090////////////////////////////////////////////////////////////////////////////////
1091/// Add branch b to the Tree cache.
1092/// if subbranches is true all the branches of the subbranches are
1093/// also put to the cache.
1094///
1095/// Returns:
1096/// - 0 branch added or already included
1097/// - -1 on error
1099Int_t TTree::AddBranchToCache(TBranch *b, bool subbranches)
1100{
1101 if (!GetTree()) {
1102 if (LoadTree(0)<0) {
1103 Error("AddBranchToCache","Could not load a tree");
1104 return -1;
1105 }
1106 }
1107 if (GetTree()) {
1108 if (GetTree() != this) {
1109 Int_t res = GetTree()->AddBranchToCache(b, subbranches);
1110 if (res<0) {
1111 Error("AddBranchToCache", "Error adding branch");
1112 }
1113 return res;
1114 }
1115 } else {
1116 Error("AddBranchToCache", "No tree is available. Branch was not added to the cache");
1117 return -1;
1118 }
1119
1120 TFile *f = GetCurrentFile();
1121 if (!f) {
1122 Error("AddBranchToCache", "No file is available. Branch was not added to the cache");
1123 return -1;
1124 }
1125 TTreeCache *tc = GetReadCache(f,true);
1126 if (!tc) {
1127 Error("AddBranchToCache", "No cache is available, branch not added");
1128 return -1;
1129 }
1130 return tc->AddBranch(b,subbranches);
1131}
1132
1133////////////////////////////////////////////////////////////////////////////////
1134/// Remove the branch with name 'bname' from the Tree cache.
1135/// If bname="*" all branches are removed from the cache.
1136/// if subbranches is true all the branches of the subbranches are
1137/// also removed from the cache.
1138///
1139/// Returns:
1140/// - 0 branch dropped or not in cache
1141/// - -1 on error
1143Int_t TTree::DropBranchFromCache(const char*bname, bool subbranches)
1144{
1145 if (!GetTree()) {
1146 if (LoadTree(0)<0) {
1147 Error("DropBranchFromCache","Could not load a tree");
1148 return -1;
1149 }
1150 }
1151 if (GetTree()) {
1152 if (GetTree() != this) {
1153 return GetTree()->DropBranchFromCache(bname, subbranches);
1154 }
1155 } else {
1156 Error("DropBranchFromCache", "No tree is available. Branch was not dropped from the cache");
1157 return -1;
1158 }
1159
1160 TFile *f = GetCurrentFile();
1161 if (!f) {
1162 Error("DropBranchFromCache", "No file is available. Branch was not dropped from the cache");
1163 return -1;
1164 }
1165 TTreeCache *tc = GetReadCache(f,true);
1166 if (!tc) {
1167 Error("DropBranchFromCache", "No cache is available, branch not dropped");
1168 return -1;
1169 }
1170 return tc->DropBranch(bname,subbranches);
1171}
1172
1173////////////////////////////////////////////////////////////////////////////////
1174/// Remove the branch b from the Tree cache.
1175/// if subbranches is true all the branches of the subbranches are
1176/// also removed from the cache.
1177///
1178/// Returns:
1179/// - 0 branch dropped or not in cache
1180/// - -1 on error
1182Int_t TTree::DropBranchFromCache(TBranch *b, bool subbranches)
1183{
1184 if (!GetTree()) {
1185 if (LoadTree(0)<0) {
1186 Error("DropBranchFromCache","Could not load a tree");
1187 return -1;
1188 }
1189 }
1190 if (GetTree()) {
1191 if (GetTree() != this) {
1192 Int_t res = GetTree()->DropBranchFromCache(b, subbranches);
1193 if (res<0) {
1194 Error("DropBranchFromCache", "Error dropping branch");
1195 }
1196 return res;
1197 }
1198 } else {
1199 Error("DropBranchFromCache", "No tree is available. Branch was not dropped from the cache");
1200 return -1;
1201 }
1202
1203 TFile *f = GetCurrentFile();
1204 if (!f) {
1205 Error("DropBranchFromCache", "No file is available. Branch was not dropped from the cache");
1206 return -1;
1207 }
1208 TTreeCache *tc = GetReadCache(f,true);
1209 if (!tc) {
1210 Error("DropBranchFromCache", "No cache is available, branch not dropped");
1211 return -1;
1212 }
1213 return tc->DropBranch(b,subbranches);
1214}
1215
1216////////////////////////////////////////////////////////////////////////////////
1217/// Add a cloned tree to our list of trees to be notified whenever we change
1218/// our branch addresses or when we are deleted.
1220void TTree::AddClone(TTree* clone)
1221{
1222 if (!fClones) {
1223 fClones = new TList();
1224 fClones->SetOwner(false);
1225 // So that the clones are automatically removed from the list when
1226 // they are deleted.
1227 {
1229 gROOT->GetListOfCleanups()->Add(fClones);
1230 }
1231 }
1232 if (!fClones->FindObject(clone)) {
1233 fClones->Add(clone);
1234 }
1235}
1236
1237// Check whether mainTree and friendTree can be friends w.r.t. the kEntriesReshuffled bit.
1238// In particular, if any has the bit set, then friendTree must have a TTreeIndex and the
1239// branches used for indexing must be present in mainTree.
1240// Return true if the trees can be friends, false otherwise.
1241bool CheckReshuffling(TTree &mainTree, TTree &friendTree)
1242{
1243 const auto isMainReshuffled = mainTree.TestBit(TTree::kEntriesReshuffled);
1244 const auto isFriendReshuffled = friendTree.TestBit(TTree::kEntriesReshuffled);
1245 const auto friendHasValidIndex = [&] {
1246 auto idx = friendTree.GetTreeIndex();
1247 return idx ? idx->IsValidFor(&mainTree) : false;
1248 }();
1249
1250 if ((isMainReshuffled || isFriendReshuffled) && !friendHasValidIndex) {
1251 const auto reshuffledTreeName = isMainReshuffled ? mainTree.GetName() : friendTree.GetName();
1252 const auto msg =
1253 "Tree '%s' has the kEntriesReshuffled bit set and cannot have friends nor can be added as a friend unless the "
1254 "main tree has a TTreeIndex on the friend tree '%s'. You can also unset the bit manually if you know what you "
1255 "are doing; note that you risk associating wrong TTree entries of the friend with those of the main TTree!";
1256 Error("AddFriend", msg, reshuffledTreeName, friendTree.GetName());
1257 return false;
1258 }
1259 return true;
1260}
1261
1262////////////////////////////////////////////////////////////////////////////////
1263/// Add a TFriendElement to the list of friends.
1264///
1265/// This function:
1266/// - opens a file if filename is specified
1267/// - reads a Tree with name treename from the file (current directory)
1268/// - adds the Tree to the list of friends
1269/// see other AddFriend functions
1270///
1271/// A TFriendElement TF describes a TTree object TF in a file.
1272/// When a TFriendElement TF is added to the list of friends of an
1273/// existing TTree T, any variable from TF can be referenced in a query
1274/// to T.
1275///
1276/// A tree keeps a list of friends. In the context of a tree (or a chain),
1277/// friendship means unrestricted access to the friends data. In this way
1278/// it is much like adding another branch to the tree without taking the risk
1279/// of damaging it. To add a friend to the list, you can use the TTree::AddFriend
1280/// method. The tree in the diagram below has two friends (friend_tree1 and
1281/// friend_tree2) and now has access to the variables a,b,c,i,j,k,l and m.
1282///
1283/// \image html ttree_friend1.png
1284///
1285/// The AddFriend method has two parameters, the first is the tree name and the
1286/// second is the name of the ROOT file where the friend tree is saved.
1287/// AddFriend automatically opens the friend file. If no file name is given,
1288/// the tree called ft1 is assumed to be in the same file as the original tree.
1289///
1290/// tree.AddFriend("ft1","friendfile1.root");
1291/// If the friend tree has the same name as the original tree, you can give it
1292/// an alias in the context of the friendship:
1293///
1294/// tree.AddFriend("tree1 = tree","friendfile1.root");
1295/// Once the tree has friends, we can use TTree::Draw as if the friend's
1296/// variables were in the original tree. To specify which tree to use in
1297/// the Draw method, use the syntax:
1298/// ~~~ {.cpp}
1299/// <treeName>.<branchname>.<varname>
1300/// ~~~
1301/// If the variablename is enough to uniquely identify the variable, you can
1302/// leave out the tree and/or branch name.
1303/// For example, these commands generate a 3-d scatter plot of variable "var"
1304/// in the TTree tree versus variable v1 in TTree ft1 versus variable v2 in
1305/// TTree ft2.
1306/// ~~~ {.cpp}
1307/// tree.AddFriend("ft1","friendfile1.root");
1308/// tree.AddFriend("ft2","friendfile2.root");
1309/// tree.Draw("var:ft1.v1:ft2.v2");
1310/// ~~~
1311/// \image html ttree_friend2.png
1312///
1313/// The picture illustrates the access of the tree and its friends with a
1314/// Draw command.
1315/// When AddFriend is called, the ROOT file is automatically opened and the
1316/// friend tree (ft1) is read into memory. The new friend (ft1) is added to
1317/// the list of friends of tree.
1318/// The number of entries in the friend must be equal or greater to the number
1319/// of entries of the original tree. If the friend tree has fewer entries a
1320/// warning is given and the missing entries are not included in the histogram.
1321/// To retrieve the list of friends from a tree use TTree::GetListOfFriends.
1322/// When the tree is written to file (TTree::Write), the friends list is saved
1323/// with it. And when the tree is retrieved, the trees on the friends list are
1324/// also retrieved and the friendship restored.
1325/// When a tree is deleted, the elements of the friend list are also deleted.
1326/// It is possible to declare a friend tree that has the same internal
1327/// structure (same branches and leaves) as the original tree, and compare the
1328/// same values by specifying the tree.
1329/// ~~~ {.cpp}
1330/// tree.Draw("var:ft1.var:ft2.var")
1331/// ~~~
1333TFriendElement *TTree::AddFriend(const char *treename, const char *filename)
1334{
1335 if (!fFriends) {
1336 fFriends = new TList();
1337 }
1338 TFriendElement *fe = new TFriendElement(this, treename, filename);
1339
1340 TTree *t = fe->GetTree();
1341 bool canAddFriend = true;
1342 if (t) {
1343 canAddFriend = CheckReshuffling(*this, *t);
1344 if (!t->GetTreeIndex() && (t->GetEntries() < fEntries)) {
1345 Warning("AddFriend", "FriendElement %s in file %s has less entries %lld than its parent Tree: %lld", treename,
1347 }
1348 } else {
1349 Error("AddFriend", "Cannot find tree '%s' in file '%s', friend not added", treename, filename);
1350 canAddFriend = false;
1351 }
1352
1353 if (canAddFriend)
1354 fFriends->Add(fe);
1355 return fe;
1356}
1357
1358////////////////////////////////////////////////////////////////////////////////
1359/// Add a TFriendElement to the list of friends.
1360///
1361/// The TFile is managed by the user (e.g. the user must delete the file).
1362/// For complete description see AddFriend(const char *, const char *).
1363/// This function:
1364/// - reads a Tree with name treename from the file
1365/// - adds the Tree to the list of friends
1367TFriendElement *TTree::AddFriend(const char *treename, TFile *file)
1368{
1369 if (!fFriends) {
1370 fFriends = new TList();
1371 }
1372 TFriendElement *fe = new TFriendElement(this, treename, file);
1373 R__ASSERT(fe);
1374 TTree *t = fe->GetTree();
1375 bool canAddFriend = true;
1376 if (t) {
1377 canAddFriend = CheckReshuffling(*this, *t);
1378 if (!t->GetTreeIndex() && (t->GetEntries() < fEntries)) {
1379 Warning("AddFriend", "FriendElement %s in file %s has less entries %lld than its parent tree: %lld", treename,
1380 file->GetName(), t->GetEntries(), fEntries);
1381 }
1382 } else {
1383 Error("AddFriend", "Cannot find tree '%s' in file '%s', friend not added", treename, file->GetName());
1384 canAddFriend = false;
1385 }
1386
1387 if (canAddFriend)
1388 fFriends->Add(fe);
1389 return fe;
1390}
1391
1392////////////////////////////////////////////////////////////////////////////////
1393/// Add a TFriendElement to the list of friends.
1394///
1395/// The TTree is managed by the user (e.g., the user must delete the file).
1396/// For a complete description see AddFriend(const char *, const char *).
1398TFriendElement *TTree::AddFriend(TTree *tree, const char *alias, bool warn)
1399{
1400 if (!tree) {
1401 return nullptr;
1402 }
1403 if (!fFriends) {
1404 fFriends = new TList();
1405 }
1406 TFriendElement *fe = new TFriendElement(this, tree, alias);
1407 R__ASSERT(fe); // this assert is for historical reasons. Don't remove it unless you understand all the consequences.
1408 TTree *t = fe->GetTree();
1409 if (warn && (t->GetEntries() < fEntries)) {
1410 Warning("AddFriend", "FriendElement '%s' in file '%s' has less entries %lld than its parent tree: %lld",
1411 tree->GetName(), fe->GetFile() ? fe->GetFile()->GetName() : "(memory resident)", t->GetEntries(),
1412 fEntries);
1413 }
1414 if (CheckReshuffling(*this, *t))
1415 fFriends->Add(fe);
1416 else
1417 tree->RemoveExternalFriend(fe);
1418 return fe;
1419}
1420
1421////////////////////////////////////////////////////////////////////////////////
1422/// AutoSave tree header every fAutoSave bytes.
1423///
1424/// When large Trees are produced, it is safe to activate the AutoSave
1425/// procedure. Some branches may have buffers holding many entries.
1426/// If fAutoSave is negative, AutoSave is automatically called by
1427/// TTree::Fill when the number of bytes generated since the previous
1428/// AutoSave is greater than -fAutoSave bytes.
1429/// If fAutoSave is positive, AutoSave is automatically called by
1430/// TTree::Fill every N entries.
1431/// This function may also be invoked by the user.
1432/// Each AutoSave generates a new key on the file.
1433/// Once the key with the tree header has been written, the previous cycle
1434/// (if any) is deleted.
1435///
1436/// Note that calling TTree::AutoSave too frequently (or similarly calling
1437/// TTree::SetAutoSave with a small value) is an expensive operation.
1438/// You should make tests for your own application to find a compromise
1439/// between speed and the quantity of information you may loose in case of
1440/// a job crash.
1441///
1442/// In case your program crashes before closing the file holding this tree,
1443/// the file will be automatically recovered when you will connect the file
1444/// in UPDATE mode.
1445/// The Tree will be recovered at the status corresponding to the last AutoSave.
1446///
1447/// if option contains "SaveSelf", gDirectory->SaveSelf() is called.
1448/// This allows another process to analyze the Tree while the Tree is being filled.
1449///
1450/// if option contains "FlushBaskets", TTree::FlushBaskets is called and all
1451/// the current basket are closed-out and written to disk individually.
1452///
1453/// By default the previous header is deleted after having written the new header.
1454/// if option contains "Overwrite", the previous Tree header is deleted
1455/// before written the new header. This option is slightly faster, but
1456/// the default option is safer in case of a problem (disk quota exceeded)
1457/// when writing the new header.
1458///
1459/// The function returns the number of bytes written to the file.
1460/// if the number of bytes is null, an error has occurred while writing
1461/// the header to the file.
1462///
1463/// ## How to write a Tree in one process and view it from another process
1464///
1465/// The following two scripts illustrate how to do this.
1466/// The script treew.C is executed by process1, treer.C by process2
1467///
1468/// script treew.C:
1469/// ~~~ {.cpp}
1470/// void treew() {
1471/// TFile f("test.root","recreate");
1472/// TNtuple *ntuple = new TNtuple("ntuple","Demo","px:py:pz:random:i");
1473/// Float_t px, py, pz;
1474/// for ( Int_t i=0; i<10000000; i++) {
1475/// gRandom->Rannor(px,py);
1476/// pz = px*px + py*py;
1477/// Float_t random = gRandom->Rndm(1);
1478/// ntuple->Fill(px,py,pz,random,i);
1479/// if (i%1000 == 1) ntuple->AutoSave("SaveSelf");
1480/// }
1481/// }
1482/// ~~~
1483/// script treer.C:
1484/// ~~~ {.cpp}
1485/// void treer() {
1486/// TFile f("test.root");
1487/// TTree *ntuple = (TTree*)f.Get("ntuple");
1488/// TCanvas c1;
1489/// Int_t first = 0;
1490/// while(1) {
1491/// if (first == 0) ntuple->Draw("px>>hpx", "","",10000000,first);
1492/// else ntuple->Draw("px>>+hpx","","",10000000,first);
1493/// first = (Int_t)ntuple->GetEntries();
1494/// c1.Update();
1495/// gSystem->Sleep(1000); //sleep 1 second
1496/// ntuple->Refresh();
1497/// }
1498/// }
1499/// ~~~
1502{
1503 if (!fDirectory || fDirectory == gROOT || !fDirectory->IsWritable()) return 0;
1504 if (gDebug > 0) {
1505 Info("AutoSave", "Tree:%s after %lld bytes written\n",GetName(),GetTotBytes());
1506 }
1507 TString opt = option;
1508 opt.ToLower();
1509
1510 if (opt.Contains("flushbaskets")) {
1511 if (gDebug > 0) Info("AutoSave", "calling FlushBaskets \n");
1513 }
1514
1516
1518 Long64_t nbytes;
1519 if (opt.Contains("overwrite")) {
1520 nbytes = fDirectory->WriteTObject(this,"","overwrite");
1521 } else {
1522 nbytes = fDirectory->WriteTObject(this); //nbytes will be 0 if Write failed (disk space exceeded)
1523 if (nbytes && key && strcmp(ClassName(), key->GetClassName()) == 0) {
1524 key->Delete();
1525 delete key;
1526 }
1527 }
1528 // save StreamerInfo
1529 TFile *file = fDirectory->GetFile();
1530 if (file) file->WriteStreamerInfo();
1531
1532 if (opt.Contains("saveself")) {
1534 //the following line is required in case GetUserInfo contains a user class
1535 //for which the StreamerInfo must be written. One could probably be a bit faster (Rene)
1536 if (file) file->WriteHeader();
1537 }
1538
1539 return nbytes;
1540}
1541
1542namespace {
1543 // This error message is repeated several times in the code. We write it once.
1544 const char* writeStlWithoutProxyMsg = "The class requested (%s) for the branch \"%s\""
1545 " is an instance of an stl collection and does not have a compiled CollectionProxy."
1546 " Please generate the dictionary for this collection (%s) to avoid to write corrupted data.";
1547}
1548
1549////////////////////////////////////////////////////////////////////////////////
1550/// Same as TTree::Branch() with added check that addobj matches className.
1551///
1552/// \see TTree::Branch() for other details.
1553///
1555TBranch* TTree::BranchImp(const char* branchname, const char* classname, TClass* ptrClass, void* addobj, Int_t bufsize, Int_t splitlevel)
1556{
1557 TClass* claim = TClass::GetClass(classname);
1558 if (!ptrClass) {
1559 if (claim && claim->GetCollectionProxy() && dynamic_cast<TEmulatedCollectionProxy*>(claim->GetCollectionProxy())) {
1560 Error("Branch", writeStlWithoutProxyMsg,
1561 claim->GetName(), branchname, claim->GetName());
1562 return nullptr;
1563 }
1564 return Branch(branchname, classname, (void*) addobj, bufsize, splitlevel);
1565 }
1566 TClass* actualClass = nullptr;
1567 void** addr = (void**) addobj;
1568 if (addr) {
1569 actualClass = ptrClass->GetActualClass(*addr);
1570 }
1571 if (ptrClass && claim) {
1572 if (!(claim->InheritsFrom(ptrClass) || ptrClass->InheritsFrom(claim))) {
1573 // Note we currently do not warn in case of splicing or over-expectation).
1574 if (claim->IsLoaded() && ptrClass->IsLoaded() && strcmp( claim->GetTypeInfo()->name(), ptrClass->GetTypeInfo()->name() ) == 0) {
1575 // The type is the same according to the C++ type_info, we must be in the case of
1576 // a template of Double32_t. This is actually a correct case.
1577 } else {
1578 Error("Branch", "The class requested (%s) for \"%s\" is different from the type of the pointer passed (%s)",
1579 claim->GetName(), branchname, ptrClass->GetName());
1580 }
1581 } else if (actualClass && (claim != actualClass) && !actualClass->InheritsFrom(claim)) {
1582 if (claim->IsLoaded() && actualClass->IsLoaded() && strcmp( claim->GetTypeInfo()->name(), actualClass->GetTypeInfo()->name() ) == 0) {
1583 // The type is the same according to the C++ type_info, we must be in the case of
1584 // a template of Double32_t. This is actually a correct case.
1585 } else {
1586 Error("Branch", "The actual class (%s) of the object provided for the definition of the branch \"%s\" does not inherit from %s",
1587 actualClass->GetName(), branchname, claim->GetName());
1588 }
1589 }
1590 }
1591 if (claim && claim->GetCollectionProxy() && dynamic_cast<TEmulatedCollectionProxy*>(claim->GetCollectionProxy())) {
1592 Error("Branch", writeStlWithoutProxyMsg,
1593 claim->GetName(), branchname, claim->GetName());
1594 return nullptr;
1595 }
1596 return Branch(branchname, classname, (void*) addobj, bufsize, splitlevel);
1597}
1598
1599////////////////////////////////////////////////////////////////////////////////
1600/// Same as TTree::Branch but automatic detection of the class name.
1601/// \see TTree::Branch for other details.
1603TBranch* TTree::BranchImp(const char* branchname, TClass* ptrClass, void* addobj, Int_t bufsize, Int_t splitlevel)
1604{
1605 if (!ptrClass) {
1606 Error("Branch", "The pointer specified for %s is not of a class known to ROOT", branchname);
1607 return nullptr;
1608 }
1609 TClass* actualClass = nullptr;
1610 void** addr = (void**) addobj;
1611 if (addr && *addr) {
1612 actualClass = ptrClass->GetActualClass(*addr);
1613 if (!actualClass) {
1614 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",
1615 branchname, ptrClass->GetName());
1616 actualClass = ptrClass;
1617 } else if ((ptrClass != actualClass) && !actualClass->InheritsFrom(ptrClass)) {
1618 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());
1619 return nullptr;
1620 }
1621 } else {
1622 actualClass = ptrClass;
1623 }
1624 if (actualClass && actualClass->GetCollectionProxy() && dynamic_cast<TEmulatedCollectionProxy*>(actualClass->GetCollectionProxy())) {
1625 Error("Branch", writeStlWithoutProxyMsg,
1626 actualClass->GetName(), branchname, actualClass->GetName());
1627 return nullptr;
1628 }
1629 return Branch(branchname, actualClass->GetName(), (void*) addobj, bufsize, splitlevel);
1630}
1631
1632////////////////////////////////////////////////////////////////////////////////
1633/// Same as TTree::Branch but automatic detection of the class name.
1634/// \see TTree::Branch for other details.
1636TBranch* TTree::BranchImpRef(const char* branchname, const char *classname, TClass* ptrClass, void *addobj, Int_t bufsize, Int_t splitlevel)
1637{
1638 TClass* claim = TClass::GetClass(classname);
1639 if (!ptrClass) {
1640 if (claim && claim->GetCollectionProxy() && dynamic_cast<TEmulatedCollectionProxy*>(claim->GetCollectionProxy())) {
1641 Error("Branch", writeStlWithoutProxyMsg,
1642 claim->GetName(), branchname, claim->GetName());
1643 return nullptr;
1644 } else if (claim == nullptr) {
1645 Error("Branch", "The pointer specified for %s is not of a class known to ROOT and %s is not a known class", branchname, classname);
1646 return nullptr;
1647 }
1648 ptrClass = claim;
1649 }
1650 TClass* actualClass = nullptr;
1651 if (!addobj) {
1652 Error("Branch", "Reference interface requires a valid object (for branch: %s)!", branchname);
1653 return nullptr;
1654 }
1655 actualClass = ptrClass->GetActualClass(addobj);
1656 if (ptrClass && claim) {
1657 if (!(claim->InheritsFrom(ptrClass) || ptrClass->InheritsFrom(claim))) {
1658 // Note we currently do not warn in case of splicing or over-expectation).
1659 if (claim->IsLoaded() && ptrClass->IsLoaded() && strcmp( claim->GetTypeInfo()->name(), ptrClass->GetTypeInfo()->name() ) == 0) {
1660 // The type is the same according to the C++ type_info, we must be in the case of
1661 // a template of Double32_t. This is actually a correct case.
1662 } else {
1663 Error("Branch", "The class requested (%s) for \"%s\" is different from the type of the object passed (%s)",
1664 claim->GetName(), branchname, ptrClass->GetName());
1665 }
1666 } else if (actualClass && (claim != actualClass) && !actualClass->InheritsFrom(claim)) {
1667 if (claim->IsLoaded() && actualClass->IsLoaded() && strcmp( claim->GetTypeInfo()->name(), actualClass->GetTypeInfo()->name() ) == 0) {
1668 // The type is the same according to the C++ type_info, we must be in the case of
1669 // a template of Double32_t. This is actually a correct case.
1670 } else {
1671 Error("Branch", "The actual class (%s) of the object provided for the definition of the branch \"%s\" does not inherit from %s",
1672 actualClass->GetName(), branchname, claim->GetName());
1673 }
1674 }
1675 }
1676 if (!actualClass) {
1677 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",
1678 branchname, ptrClass->GetName());
1679 actualClass = ptrClass;
1680 } else if ((ptrClass != actualClass) && !actualClass->InheritsFrom(ptrClass)) {
1681 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());
1682 return nullptr;
1683 }
1684 if (actualClass && actualClass->GetCollectionProxy() && dynamic_cast<TEmulatedCollectionProxy*>(actualClass->GetCollectionProxy())) {
1685 Error("Branch", writeStlWithoutProxyMsg,
1686 actualClass->GetName(), branchname, actualClass->GetName());
1687 return nullptr;
1688 }
1689 return BronchExec(branchname, actualClass->GetName(), (void*) addobj, false, bufsize, splitlevel);
1690}
1691
1692////////////////////////////////////////////////////////////////////////////////
1693/// Same as TTree::Branch but automatic detection of the class name.
1694/// \see TTree::Branch for other details.
1696TBranch* TTree::BranchImpRef(const char* branchname, TClass* ptrClass, EDataType datatype, void* addobj, Int_t bufsize, Int_t splitlevel)
1697{
1698 if (!ptrClass) {
1699 if (datatype == kOther_t || datatype == kNoType_t) {
1700 Error("Branch", "The pointer specified for %s is not of a class or type known to ROOT", branchname);
1701 } else {
1702 TString varname; varname.Form("%s/%c",branchname,DataTypeToChar(datatype));
1703 return Branch(branchname,addobj,varname.Data(),bufsize);
1704 }
1705 return nullptr;
1706 }
1707 TClass* actualClass = nullptr;
1708 if (!addobj) {
1709 Error("Branch", "Reference interface requires a valid object (for branch: %s)!", branchname);
1710 return nullptr;
1711 }
1712 actualClass = ptrClass->GetActualClass(addobj);
1713 if (!actualClass) {
1714 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",
1715 branchname, ptrClass->GetName());
1716 actualClass = ptrClass;
1717 } else if ((ptrClass != actualClass) && !actualClass->InheritsFrom(ptrClass)) {
1718 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());
1719 return nullptr;
1720 }
1721 if (actualClass && actualClass->GetCollectionProxy() && dynamic_cast<TEmulatedCollectionProxy*>(actualClass->GetCollectionProxy())) {
1722 Error("Branch", writeStlWithoutProxyMsg,
1723 actualClass->GetName(), branchname, actualClass->GetName());
1724 return nullptr;
1725 }
1726 return BronchExec(branchname, actualClass->GetName(), (void*) addobj, false, bufsize, splitlevel);
1727}
1728
1729////////////////////////////////////////////////////////////////////////////////
1730// Wrapper to turn Branch call with an std::array into the relevant leaf list
1731// call
1732TBranch *TTree::BranchImpArr(const char *branchname, EDataType datatype, std::size_t N, void *addobj, Int_t bufsize,
1733 Int_t /* splitlevel */)
1734{
1735 if (datatype == kOther_t || datatype == kNoType_t) {
1736 Error("Branch",
1737 "The inner type of the std::array passed specified for %s is not of a class or type known to ROOT",
1738 branchname);
1739 } else {
1740 TString varname;
1741 varname.Form("%s[%d]/%c", branchname, (int)N, DataTypeToChar(datatype));
1742 return Branch(branchname, addobj, varname.Data(), bufsize);
1743 }
1744 return nullptr;
1745}
1746
1747////////////////////////////////////////////////////////////////////////////////
1748/// Deprecated function. Use next function instead.
1750Int_t TTree::Branch(TList* li, Int_t bufsize /* = 32000 */ , Int_t splitlevel /* = 99 */)
1751{
1752 return Branch((TCollection*) li, bufsize, splitlevel);
1753}
1754
1755////////////////////////////////////////////////////////////////////////////////
1756/// Create one branch for each element in the collection.
1757///
1758/// Each entry in the collection becomes a top level branch if the
1759/// corresponding class is not a collection. If it is a collection, the entry
1760/// in the collection becomes in turn top level branches, etc.
1761/// The splitlevel is decreased by 1 every time a new collection is found.
1762/// For example if list is a TObjArray*
1763/// - if splitlevel = 1, one top level branch is created for each element
1764/// of the TObjArray.
1765/// - if splitlevel = 2, one top level branch is created for each array element.
1766/// if, in turn, one of the array elements is a TCollection, one top level
1767/// branch will be created for each element of this collection.
1768///
1769/// In case a collection element is a TClonesArray, the special Tree constructor
1770/// for TClonesArray is called.
1771/// The collection itself cannot be a TClonesArray.
1772///
1773/// The function returns the total number of branches created.
1774///
1775/// If name is given, all branch names will be prefixed with name_.
1776///
1777/// IMPORTANT NOTE1: This function should not be called with splitlevel < 1.
1778///
1779/// IMPORTANT NOTE2: The branches created by this function will have names
1780/// corresponding to the collection or object names. It is important
1781/// to give names to collections to avoid misleading branch names or
1782/// identical branch names. By default collections have a name equal to
1783/// the corresponding class name, e.g. the default name for a TList is "TList".
1784///
1785/// And in general, in case two or more master branches contain subbranches
1786/// with identical names, one must add a "." (dot) character at the end
1787/// of the master branch name. This will force the name of the subbranches
1788/// to be of the form `master.subbranch` instead of simply `subbranch`.
1789/// This situation happens when the top level object
1790/// has two or more members referencing the same class.
1791/// For example, if a Tree has two branches B1 and B2 corresponding
1792/// to objects of the same class MyClass, one can do:
1793/// ~~~ {.cpp}
1794/// tree.Branch("B1.","MyClass",&b1,8000,1);
1795/// tree.Branch("B2.","MyClass",&b2,8000,1);
1796/// ~~~
1797/// if MyClass has 3 members a,b,c, the two instructions above will generate
1798/// subbranches called B1.a, B1.b ,B1.c, B2.a, B2.b, B2.c
1799///
1800/// Example:
1801/// ~~~ {.cpp}
1802/// {
1803/// TTree T("T","test list");
1804/// TList *list = new TList();
1805///
1806/// TObjArray *a1 = new TObjArray();
1807/// a1->SetName("a1");
1808/// list->Add(a1);
1809/// TH1F *ha1a = new TH1F("ha1a","ha1",100,0,1);
1810/// TH1F *ha1b = new TH1F("ha1b","ha1",100,0,1);
1811/// a1->Add(ha1a);
1812/// a1->Add(ha1b);
1813/// TObjArray *b1 = new TObjArray();
1814/// b1->SetName("b1");
1815/// list->Add(b1);
1816/// TH1F *hb1a = new TH1F("hb1a","hb1",100,0,1);
1817/// TH1F *hb1b = new TH1F("hb1b","hb1",100,0,1);
1818/// b1->Add(hb1a);
1819/// b1->Add(hb1b);
1820///
1821/// TObjArray *a2 = new TObjArray();
1822/// a2->SetName("a2");
1823/// list->Add(a2);
1824/// TH1S *ha2a = new TH1S("ha2a","ha2",100,0,1);
1825/// TH1S *ha2b = new TH1S("ha2b","ha2",100,0,1);
1826/// a2->Add(ha2a);
1827/// a2->Add(ha2b);
1828///
1829/// T.Branch(list,16000,2);
1830/// T.Print();
1831/// }
1832/// ~~~
1834Int_t TTree::Branch(TCollection* li, Int_t bufsize /* = 32000 */, Int_t splitlevel /* = 99 */, const char* name /* = "" */)
1835{
1836
1837 if (!li) {
1838 return 0;
1839 }
1840 TObject* obj = nullptr;
1841 Int_t nbranches = GetListOfBranches()->GetEntries();
1842 if (li->InheritsFrom(TClonesArray::Class())) {
1843 Error("Branch", "Cannot call this constructor for a TClonesArray");
1844 return 0;
1845 }
1846 Int_t nch = strlen(name);
1847 TString branchname;
1848 TIter next(li);
1849 while ((obj = next())) {
1850 if ((splitlevel > 1) && obj->InheritsFrom(TCollection::Class()) && !obj->InheritsFrom(TClonesArray::Class())) {
1851 TCollection* col = (TCollection*) obj;
1852 if (nch) {
1853 branchname.Form("%s_%s_", name, col->GetName());
1854 } else {
1855 branchname.Form("%s_", col->GetName());
1856 }
1857 Branch(col, bufsize, splitlevel - 1, branchname);
1858 } else {
1859 if (nch && (name[nch-1] == '_')) {
1860 branchname.Form("%s%s", name, obj->GetName());
1861 } else {
1862 if (nch) {
1863 branchname.Form("%s_%s", name, obj->GetName());
1864 } else {
1865 branchname.Form("%s", obj->GetName());
1866 }
1867 }
1868 if (splitlevel > 99) {
1869 branchname += ".";
1870 }
1871 Bronch(branchname, obj->ClassName(), li->GetObjectRef(obj), bufsize, splitlevel - 1);
1872 }
1873 }
1874 return GetListOfBranches()->GetEntries() - nbranches;
1875}
1876
1877////////////////////////////////////////////////////////////////////////////////
1878/// Create one branch for each element in the folder.
1879/// Returns the total number of branches created.
1881Int_t TTree::Branch(const char* foldername, Int_t bufsize /* = 32000 */, Int_t splitlevel /* = 99 */)
1882{
1883 TObject* ob = gROOT->FindObjectAny(foldername);
1884 if (!ob) {
1885 return 0;
1886 }
1887 if (ob->IsA() != TFolder::Class()) {
1888 return 0;
1889 }
1890 Int_t nbranches = GetListOfBranches()->GetEntries();
1891 TFolder* folder = (TFolder*) ob;
1892 TIter next(folder->GetListOfFolders());
1893 TObject* obj = nullptr;
1894 char* curname = new char[1000];
1895 char occur[20];
1896 while ((obj = next())) {
1897 snprintf(curname,1000, "%s/%s", foldername, obj->GetName());
1898 if (obj->IsA() == TFolder::Class()) {
1899 Branch(curname, bufsize, splitlevel - 1);
1900 } else {
1901 void* add = (void*) folder->GetListOfFolders()->GetObjectRef(obj);
1902 for (Int_t i = 0; i < 1000; ++i) {
1903 if (curname[i] == 0) {
1904 break;
1905 }
1906 if (curname[i] == '/') {
1907 curname[i] = '.';
1908 }
1909 }
1910 Int_t noccur = folder->Occurence(obj);
1911 if (noccur > 0) {
1912 snprintf(occur,20, "_%d", noccur);
1913 strlcat(curname, occur,1000);
1914 }
1915 TBranchElement* br = (TBranchElement*) Bronch(curname, obj->ClassName(), add, bufsize, splitlevel - 1);
1916 if (br) br->SetBranchFolder();
1917 }
1918 }
1919 delete[] curname;
1920 return GetListOfBranches()->GetEntries() - nbranches;
1921}
1922
1923////////////////////////////////////////////////////////////////////////////////
1924/// Create a new TTree Branch.
1925///
1926/// This Branch constructor is provided to support non-objects in
1927/// a Tree. The variables described in leaflist may be simple
1928/// variables or structures. // See the two following
1929/// constructors for writing objects in a Tree.
1930///
1931/// By default the branch buffers are stored in the same file as the Tree.
1932/// use TBranch::SetFile to specify a different file
1933///
1934/// * address is the address of the first item of a structure.
1935/// * leaflist is the concatenation of all the variable names and types
1936/// separated by a colon character :
1937/// The variable name and the variable type are separated by a slash (/).
1938/// The variable type may be 0,1 or 2 characters. If no type is given,
1939/// the type of the variable is assumed to be the same as the previous
1940/// variable. If the first variable does not have a type, it is assumed
1941/// of type F by default. The list of currently supported types is given below:
1942/// - `C` : a character string terminated by the 0 character
1943/// - `B` : an 8 bit signed integer (`Char_t`); Treated as a character when in an array.
1944/// - `b` : an 8 bit unsigned integer (`UChar_t`)
1945/// - `S` : a 16 bit signed integer (`Short_t`)
1946/// - `s` : a 16 bit unsigned integer (`UShort_t`)
1947/// - `I` : a 32 bit signed integer (`Int_t`)
1948/// - `i` : a 32 bit unsigned integer (`UInt_t`)
1949/// - `F` : a 32 bit floating point (`Float_t`)
1950/// - `f` : a 24 bit floating point with truncated mantissa (`Float16_t`)
1951/// - `D` : a 64 bit floating point (`Double_t`)
1952/// - `d` : a 24 bit truncated floating point (`Double32_t`)
1953/// - `L` : a 64 bit signed integer (`Long64_t`)
1954/// - `l` : a 64 bit unsigned integer (`ULong64_t`)
1955/// - `G` : a long signed integer, stored as 64 bit (`Long_t`)
1956/// - `g` : a long unsigned integer, stored as 64 bit (`ULong_t`)
1957/// - `O` : [the letter `o`, not a zero] a boolean (`bool`)
1958///
1959/// Arrays of values are supported with the following syntax:
1960/// - If leaf name has the form var[nelem], where nelem is alphanumeric, then
1961/// if nelem is a leaf name, it is used as the variable size of the array,
1962/// otherwise return 0.
1963/// The leaf referred to by nelem **MUST** be an int (/I),
1964/// - If leaf name has the form var[nelem], where nelem is a non-negative integer, then
1965/// it is used as the fixed size of the array.
1966/// - If leaf name has the form of a multi-dimensional array (e.g. var[nelem][nelem2])
1967/// where nelem and nelem2 are non-negative integer) then
1968/// it is used as a 2 dimensional array of fixed size.
1969/// - In case of the truncated floating point types (Float16_t and Double32_t) you can
1970/// furthermore specify the range in the style [xmin,xmax] or [xmin,xmax,nbits] after
1971/// the type character. See `TStreamerElement::GetRange()` for further information.
1972///
1973/// Any of other form is not supported.
1974///
1975/// Note that the TTree will assume that all the item are contiguous in memory.
1976/// On some platform, this is not always true of the member of a struct or a class,
1977/// due to padding and alignment. Sorting your data member in order of decreasing
1978/// sizeof usually leads to their being contiguous in memory.
1979///
1980/// * bufsize is the buffer size in bytes for this branch
1981/// The default value is 32000 bytes and should be ok for most cases.
1982/// You can specify a larger value (e.g. 256000) if your Tree is not split
1983/// and each entry is large (Megabytes)
1984/// A small value for bufsize is optimum if you intend to access
1985/// the entries in the Tree randomly and your Tree is in split mode.
1987TBranch* TTree::Branch(const char* name, void* address, const char* leaflist, Int_t bufsize /* = 32000 */)
1988{
1989 TBranch* branch = new TBranch(this, name, address, leaflist, bufsize);
1990 if (branch->IsZombie()) {
1991 delete branch;
1992 branch = nullptr;
1993 return nullptr;
1994 }
1995 fBranches.Add(branch);
1996 return branch;
1997}
1998
1999////////////////////////////////////////////////////////////////////////////////
2000/// Create a new branch with the object of class classname at address addobj.
2001///
2002/// WARNING:
2003///
2004/// Starting with Root version 3.01, the Branch function uses the new style
2005/// branches (TBranchElement). To get the old behaviour, you can:
2006/// - call BranchOld or
2007/// - call TTree::SetBranchStyle(0)
2008///
2009/// Note that with the new style, classname does not need to derive from TObject.
2010/// It must derived from TObject if the branch style has been set to 0 (old)
2011///
2012/// Note: See the comments in TBranchElement::SetAddress() for a more
2013/// detailed discussion of the meaning of the addobj parameter in
2014/// the case of new-style branches.
2015///
2016/// Use splitlevel < 0 instead of splitlevel=0 when the class
2017/// has a custom Streamer
2018///
2019/// Note: if the split level is set to the default (99), TTree::Branch will
2020/// not issue a warning if the class can not be split.
2022TBranch* TTree::Branch(const char* name, const char* classname, void* addobj, Int_t bufsize /* = 32000 */, Int_t splitlevel /* = 99 */)
2023{
2024 if (fgBranchStyle == 1) {
2025 return Bronch(name, classname, addobj, bufsize, splitlevel);
2026 } else {
2027 if (splitlevel < 0) {
2028 splitlevel = 0;
2029 }
2030 return BranchOld(name, classname, addobj, bufsize, splitlevel);
2031 }
2032}
2033
2034////////////////////////////////////////////////////////////////////////////////
2035/// Create a new TTree BranchObject.
2036///
2037/// Build a TBranchObject for an object of class classname.
2038/// addobj is the address of a pointer to an object of class classname.
2039/// IMPORTANT: classname must derive from TObject.
2040/// The class dictionary must be available (ClassDef in class header).
2041///
2042/// This option requires access to the library where the corresponding class
2043/// is defined. Accessing one single data member in the object implies
2044/// reading the full object.
2045/// See the next Branch constructor for a more efficient storage
2046/// in case the entry consists of arrays of identical objects.
2047///
2048/// By default the branch buffers are stored in the same file as the Tree.
2049/// use TBranch::SetFile to specify a different file
2050///
2051/// IMPORTANT NOTE about branch names:
2052///
2053/// And in general, in case two or more master branches contain subbranches
2054/// with identical names, one must add a "." (dot) character at the end
2055/// of the master branch name. This will force the name of the subbranches
2056/// to be of the form `master.subbranch` instead of simply `subbranch`.
2057/// This situation happens when the top level object
2058/// has two or more members referencing the same class.
2059/// For example, if a Tree has two branches B1 and B2 corresponding
2060/// to objects of the same class MyClass, one can do:
2061/// ~~~ {.cpp}
2062/// tree.Branch("B1.","MyClass",&b1,8000,1);
2063/// tree.Branch("B2.","MyClass",&b2,8000,1);
2064/// ~~~
2065/// if MyClass has 3 members a,b,c, the two instructions above will generate
2066/// subbranches called B1.a, B1.b ,B1.c, B2.a, B2.b, B2.c
2067///
2068/// bufsize is the buffer size in bytes for this branch
2069/// The default value is 32000 bytes and should be ok for most cases.
2070/// You can specify a larger value (e.g. 256000) if your Tree is not split
2071/// and each entry is large (Megabytes)
2072/// A small value for bufsize is optimum if you intend to access
2073/// the entries in the Tree randomly and your Tree is in split mode.
2075TBranch* TTree::BranchOld(const char* name, const char* classname, void* addobj, Int_t bufsize /* = 32000 */, Int_t splitlevel /* = 1 */)
2076{
2077 TClass* cl = TClass::GetClass(classname);
2078 if (!cl) {
2079 Error("BranchOld", "Cannot find class: '%s'", classname);
2080 return nullptr;
2081 }
2082 if (!cl->IsTObject()) {
2083 if (fgBranchStyle == 0) {
2084 Fatal("BranchOld", "The requested class ('%s') does not inherit from TObject.\n"
2085 "\tfgBranchStyle is set to zero requesting by default to use BranchOld.\n"
2086 "\tIf this is intentional use Bronch instead of Branch or BranchOld.", classname);
2087 } else {
2088 Fatal("BranchOld", "The requested class ('%s') does not inherit from TObject.\n"
2089 "\tYou can not use BranchOld to store objects of this type.",classname);
2090 }
2091 return nullptr;
2092 }
2093 TBranch* branch = new TBranchObject(this, name, classname, addobj, bufsize, splitlevel);
2094 fBranches.Add(branch);
2095 if (!splitlevel) {
2096 return branch;
2097 }
2098 // We are going to fully split the class now.
2099 TObjArray* blist = branch->GetListOfBranches();
2100 const char* rdname = nullptr;
2101 const char* dname = nullptr;
2102 TString branchname;
2103 char** apointer = (char**) addobj;
2104 TObject* obj = (TObject*) *apointer;
2105 bool delobj = false;
2106 if (!obj) {
2107 obj = (TObject*) cl->New();
2108 delobj = true;
2109 }
2110 // Build the StreamerInfo if first time for the class.
2111 BuildStreamerInfo(cl, obj);
2112 // Loop on all public data members of the class and its base classes.
2113 Int_t lenName = strlen(name);
2114 Int_t isDot = 0;
2115 if (name[lenName-1] == '.') {
2116 isDot = 1;
2117 }
2118 TBranch* branch1 = nullptr;
2119 TRealData* rd = nullptr;
2120 TRealData* rdi = nullptr;
2121 TIter nexti(cl->GetListOfRealData());
2122 TIter next(cl->GetListOfRealData());
2123 // Note: This loop results in a full split because the
2124 // real data list includes all data members of
2125 // data members.
2126 while ((rd = (TRealData*) next())) {
2127 if (rd->TestBit(TRealData::kTransient)) continue;
2128
2129 // Loop over all data members creating branches for each one.
2130 TDataMember* dm = rd->GetDataMember();
2131 if (!dm->IsPersistent()) {
2132 // Do not process members with an "!" as the first character in the comment field.
2133 continue;
2134 }
2135 if (rd->IsObject()) {
2136 // We skip data members of class type.
2137 // But we do build their real data, their
2138 // streamer info, and write their streamer
2139 // info to the current directory's file.
2140 // Oh yes, and we also do this for all of
2141 // their base classes.
2143 if (clm) {
2144 BuildStreamerInfo(clm, (char*) obj + rd->GetThisOffset());
2145 }
2146 continue;
2147 }
2148 rdname = rd->GetName();
2149 dname = dm->GetName();
2150 if (cl->CanIgnoreTObjectStreamer()) {
2151 // Skip the TObject base class data members.
2152 // FIXME: This prevents a user from ever
2153 // using these names themself!
2154 if (!strcmp(dname, "fBits")) {
2155 continue;
2156 }
2157 if (!strcmp(dname, "fUniqueID")) {
2158 continue;
2159 }
2160 }
2161 TDataType* dtype = dm->GetDataType();
2162 Int_t code = 0;
2163 if (dtype) {
2164 code = dm->GetDataType()->GetType();
2165 }
2166 // Encode branch name. Use real data member name
2167 branchname = rdname;
2168 if (isDot) {
2169 if (dm->IsaPointer()) {
2170 // FIXME: This is wrong! The asterisk is not usually in the front!
2171 branchname.Form("%s%s", name, &rdname[1]);
2172 } else {
2173 branchname.Form("%s%s", name, &rdname[0]);
2174 }
2175 }
2176 // FIXME: Change this to a string stream.
2177 TString leaflist;
2178 Int_t offset = rd->GetThisOffset();
2179 char* pointer = ((char*) obj) + offset;
2180 if (dm->IsaPointer()) {
2181 // We have a pointer to an object or a pointer to an array of basic types.
2182 TClass* clobj = nullptr;
2183 if (!dm->IsBasic()) {
2184 clobj = TClass::GetClass(dm->GetTypeName());
2185 }
2186 if (clobj && clobj->InheritsFrom(TClonesArray::Class())) {
2187 // We have a pointer to a clones array.
2188 char* cpointer = (char*) pointer;
2189 char** ppointer = (char**) cpointer;
2190 TClonesArray* li = (TClonesArray*) *ppointer;
2191 if (splitlevel != 2) {
2192 if (isDot) {
2193 branch1 = new TBranchClones(branch,branchname, pointer, bufsize);
2194 } else {
2195 // FIXME: This is wrong! The asterisk is not usually in the front!
2196 branch1 = new TBranchClones(branch,&branchname.Data()[1], pointer, bufsize);
2197 }
2198 blist->Add(branch1);
2199 } else {
2200 if (isDot) {
2201 branch1 = new TBranchObject(branch, branchname, li->ClassName(), pointer, bufsize);
2202 } else {
2203 // FIXME: This is wrong! The asterisk is not usually in the front!
2204 branch1 = new TBranchObject(branch, &branchname.Data()[1], li->ClassName(), pointer, bufsize);
2205 }
2206 blist->Add(branch1);
2207 }
2208 } else if (clobj) {
2209 // We have a pointer to an object.
2210 //
2211 // It must be a TObject object.
2212 if (!clobj->IsTObject()) {
2213 continue;
2214 }
2215 branch1 = new TBranchObject(branch, dname, clobj->GetName(), pointer, bufsize, 0);
2216 if (isDot) {
2217 branch1->SetName(branchname);
2218 } else {
2219 // FIXME: This is wrong! The asterisk is not usually in the front!
2220 // Do not use the first character (*).
2221 branch1->SetName(&branchname.Data()[1]);
2222 }
2223 blist->Add(branch1);
2224 } else {
2225 // We have a pointer to an array of basic types.
2226 //
2227 // Check the comments in the text of the code for an index specification.
2228 const char* index = dm->GetArrayIndex();
2229 if (index[0]) {
2230 // We are a pointer to a varying length array of basic types.
2231 //check that index is a valid data member name
2232 //if member is part of an object (e.g. fA and index=fN)
2233 //index must be changed from fN to fA.fN
2234 TString aindex (rd->GetName());
2235 Ssiz_t rdot = aindex.Last('.');
2236 if (rdot>=0) {
2237 aindex.Remove(rdot+1);
2238 aindex.Append(index);
2239 }
2240 nexti.Reset();
2241 while ((rdi = (TRealData*) nexti())) {
2242 if (rdi->TestBit(TRealData::kTransient)) continue;
2243
2244 if (!strcmp(rdi->GetName(), index)) {
2245 break;
2246 }
2247 if (!strcmp(rdi->GetName(), aindex)) {
2248 index = rdi->GetName();
2249 break;
2250 }
2251 }
2252
2253 char vcode = DataTypeToChar((EDataType)code);
2254 // Note that we differentiate between strings and
2255 // char array by the fact that there is NO specified
2256 // size for a string (see next if (code == 1)
2257
2258 if (vcode) {
2259 leaflist.Form("%s[%s]/%c", &rdname[0], index, vcode);
2260 } else {
2261 Error("BranchOld", "Cannot create branch for rdname: %s code: %d", branchname.Data(), code);
2262 leaflist = "";
2263 }
2264 } else {
2265 // We are possibly a character string.
2266 if (code == 1) {
2267 // We are a character string.
2268 leaflist.Form("%s/%s", dname, "C");
2269 } else {
2270 // Invalid array specification.
2271 // FIXME: We need an error message here.
2272 continue;
2273 }
2274 }
2275 // There are '*' in both the branchname and leaflist, remove them.
2276 TString bname( branchname );
2277 bname.ReplaceAll("*","");
2278 leaflist.ReplaceAll("*","");
2279 // Add the branch to the tree and indicate that the address
2280 // is that of a pointer to be dereferenced before using.
2281 branch1 = new TBranch(branch, bname, *((void**) pointer), leaflist, bufsize);
2282 TLeaf* leaf = (TLeaf*) branch1->GetListOfLeaves()->At(0);
2284 leaf->SetAddress((void**) pointer);
2285 blist->Add(branch1);
2286 }
2287 } else if (dm->IsBasic()) {
2288 // We have a basic type.
2289
2290 char vcode = DataTypeToChar((EDataType)code);
2291 if (vcode) {
2292 leaflist.Form("%s/%c", rdname, vcode);
2293 } else {
2294 Error("BranchOld", "Cannot create branch for rdname: %s code: %d", branchname.Data(), code);
2295 leaflist = "";
2296 }
2297 branch1 = new TBranch(branch, branchname, pointer, leaflist, bufsize);
2298 branch1->SetTitle(rdname);
2299 blist->Add(branch1);
2300 } else {
2301 // We have a class type.
2302 // Note: This cannot happen due to the rd->IsObject() test above.
2303 // FIXME: Put an error message here just in case.
2304 }
2305 if (branch1) {
2306 branch1->SetOffset(offset);
2307 } else {
2308 Warning("BranchOld", "Cannot process member: '%s'", rdname);
2309 }
2310 }
2311 if (delobj) {
2312 delete obj;
2313 obj = nullptr;
2314 }
2315 return branch;
2316}
2317
2318////////////////////////////////////////////////////////////////////////////////
2319/// Build the optional branch supporting the TRefTable.
2320/// This branch will keep all the information to find the branches
2321/// containing referenced objects.
2322///
2323/// At each Tree::Fill, the branch numbers containing the
2324/// referenced objects are saved to the TBranchRef basket.
2325/// When the Tree header is saved (via TTree::Write), the branch
2326/// is saved keeping the information with the pointers to the branches
2327/// having referenced objects.
2330{
2331 if (!fBranchRef) {
2332 fBranchRef = new TBranchRef(this);
2333 }
2334 return fBranchRef;
2335}
2336
2337////////////////////////////////////////////////////////////////////////////////
2338/// Create a new TTree BranchElement.
2339///
2340/// ## WARNING about this new function
2341///
2342/// This function is designed to replace the internal
2343/// implementation of the old TTree::Branch (whose implementation
2344/// has been moved to BranchOld).
2345///
2346/// NOTE: The 'Bronch' method supports only one possible calls
2347/// signature (where the object type has to be specified
2348/// explicitly and the address must be the address of a pointer).
2349/// For more flexibility use 'Branch'. Use Bronch only in (rare)
2350/// cases (likely to be legacy cases) where both the new and old
2351/// implementation of Branch needs to be used at the same time.
2352///
2353/// This function is far more powerful than the old Branch
2354/// function. It supports the full C++, including STL and has
2355/// the same behaviour in split or non-split mode. classname does
2356/// not have to derive from TObject. The function is based on
2357/// the new TStreamerInfo.
2358///
2359/// Build a TBranchElement for an object of class classname.
2360///
2361/// addr is the address of a pointer to an object of class
2362/// classname. The class dictionary must be available (ClassDef
2363/// in class header).
2364///
2365/// Note: See the comments in TBranchElement::SetAddress() for a more
2366/// detailed discussion of the meaning of the addr parameter.
2367///
2368/// This option requires access to the library where the
2369/// corresponding class is defined. Accessing one single data
2370/// member in the object implies reading the full object.
2371///
2372/// By default the branch buffers are stored in the same file as the Tree.
2373/// use TBranch::SetFile to specify a different file
2374///
2375/// IMPORTANT NOTE about branch names:
2376///
2377/// And in general, in case two or more master branches contain subbranches
2378/// with identical names, one must add a "." (dot) character at the end
2379/// of the master branch name. This will force the name of the subbranches
2380/// to be of the form `master.subbranch` instead of simply `subbranch`.
2381/// This situation happens when the top level object
2382/// has two or more members referencing the same class.
2383/// For example, if a Tree has two branches B1 and B2 corresponding
2384/// to objects of the same class MyClass, one can do:
2385/// ~~~ {.cpp}
2386/// tree.Branch("B1.","MyClass",&b1,8000,1);
2387/// tree.Branch("B2.","MyClass",&b2,8000,1);
2388/// ~~~
2389/// if MyClass has 3 members a,b,c, the two instructions above will generate
2390/// subbranches called B1.a, B1.b ,B1.c, B2.a, B2.b, B2.c
2391///
2392/// bufsize is the buffer size in bytes for this branch
2393/// The default value is 32000 bytes and should be ok for most cases.
2394/// You can specify a larger value (e.g. 256000) if your Tree is not split
2395/// and each entry is large (Megabytes)
2396/// A small value for bufsize is optimum if you intend to access
2397/// the entries in the Tree randomly and your Tree is in split mode.
2398///
2399/// Use splitlevel < 0 instead of splitlevel=0 when the class
2400/// has a custom Streamer
2401///
2402/// Note: if the split level is set to the default (99), TTree::Branch will
2403/// not issue a warning if the class can not be split.
2405TBranch* TTree::Bronch(const char* name, const char* classname, void* addr, Int_t bufsize /* = 32000 */, Int_t splitlevel /* = 99 */)
2406{
2407 return BronchExec(name, classname, addr, true, bufsize, splitlevel);
2408}
2409
2410////////////////////////////////////////////////////////////////////////////////
2411/// Helper function implementing TTree::Bronch and TTree::Branch(const char *name, T &obj);
2413TBranch* TTree::BronchExec(const char* name, const char* classname, void* addr, bool isptrptr, Int_t bufsize /* = 32000 */, Int_t splitlevel /* = 99 */)
2414{
2415 TClass* cl = TClass::GetClass(classname);
2416 if (!cl) {
2417 Error("Bronch", "Cannot find class:%s", classname);
2418 return nullptr;
2419 }
2420
2421 //if splitlevel <= 0 and class has a custom Streamer, we must create
2422 //a TBranchObject. We cannot assume that TClass::ReadBuffer is consistent
2423 //with the custom Streamer. The penalty is that one cannot process
2424 //this Tree without the class library containing the class.
2425
2426 char* objptr = nullptr;
2427 if (!isptrptr) {
2428 objptr = (char*)addr;
2429 } else if (addr) {
2430 objptr = *((char**) addr);
2431 }
2432
2433 if (cl == TClonesArray::Class()) {
2434 TClonesArray* clones = (TClonesArray*) objptr;
2435 if (!clones) {
2436 Error("Bronch", "Pointer to TClonesArray is null");
2437 return nullptr;
2438 }
2439 if (!clones->GetClass()) {
2440 Error("Bronch", "TClonesArray with no class defined in branch: %s", name);
2441 return nullptr;
2442 }
2443 if (!clones->GetClass()->HasDataMemberInfo()) {
2444 Error("Bronch", "TClonesArray with no dictionary defined in branch: %s", name);
2445 return nullptr;
2446 }
2447 bool hasCustomStreamer = clones->GetClass()->HasCustomStreamerMember();
2448 if (splitlevel > 0) {
2449 if (hasCustomStreamer)
2450 Warning("Bronch", "Using split mode on a class: %s with a custom Streamer", clones->GetClass()->GetName());
2451 } else {
2452 if (hasCustomStreamer) clones->BypassStreamer(false);
2453 TBranchObject *branch = new TBranchObject(this,name,classname,addr,bufsize,0,/*compress=*/ -1,isptrptr);
2454 fBranches.Add(branch);
2455 return branch;
2456 }
2457 }
2458
2459 if (cl->GetCollectionProxy()) {
2461 //if (!collProxy) {
2462 // Error("Bronch", "%s is missing its CollectionProxy (for branch %s)", classname, name);
2463 //}
2464 TClass* inklass = collProxy->GetValueClass();
2465 if (!inklass && (collProxy->GetType() == 0)) {
2466 Error("Bronch", "%s with no class defined in branch: %s", classname, name);
2467 return nullptr;
2468 }
2469 if ((splitlevel > 0) && inklass && (inklass->GetCollectionProxy() == nullptr)) {
2471 if ((stl != ROOT::kSTLmap) && (stl != ROOT::kSTLmultimap)) {
2472 if (!inklass->HasDataMemberInfo()) {
2473 Error("Bronch", "Container with no dictionary defined in branch: %s", name);
2474 return nullptr;
2475 }
2476 if (inklass->HasCustomStreamerMember()) {
2477 Warning("Bronch", "Using split mode on a class: %s with a custom Streamer", inklass->GetName());
2478 }
2479 }
2480 }
2481 //-------------------------------------------------------------------------
2482 // If the splitting switch is enabled, the split level is big enough and
2483 // the collection contains pointers we can split it
2484 //////////////////////////////////////////////////////////////////////////
2485
2486 TBranch *branch;
2487 if( splitlevel > kSplitCollectionOfPointers && collProxy->HasPointers() )
2488 branch = new TBranchSTL( this, name, collProxy, bufsize, splitlevel );
2489 else
2490 branch = new TBranchElement(this, name, collProxy, bufsize, splitlevel);
2491 fBranches.Add(branch);
2492 if (isptrptr) {
2493 branch->SetAddress(addr);
2494 } else {
2495 branch->SetObject(addr);
2496 }
2497 return branch;
2498 }
2499
2500 bool hasCustomStreamer = false;
2501 if (!cl->HasDataMemberInfo() && !cl->GetCollectionProxy()) {
2502 Error("Bronch", "Cannot find dictionary for class: %s", classname);
2503 return nullptr;
2504 }
2505
2506 if (!cl->GetCollectionProxy() && cl->HasCustomStreamerMember()) {
2507 // Not an STL container and the linkdef file had a "-" after the class name.
2508 hasCustomStreamer = true;
2509 }
2510
2511 if (splitlevel < 0 || ((splitlevel == 0) && hasCustomStreamer && cl->IsTObject())) {
2512 TBranchObject* branch = new TBranchObject(this, name, classname, addr, bufsize, 0, /*compress=*/ ROOT::RCompressionSetting::EAlgorithm::kInherit, isptrptr);
2513 fBranches.Add(branch);
2514 return branch;
2515 }
2516
2517 if (cl == TClonesArray::Class()) {
2518 // Special case of TClonesArray.
2519 // No dummy object is created.
2520 // The streamer info is not rebuilt unoptimized.
2521 // No dummy top-level branch is created.
2522 // No splitting is attempted.
2523 TBranchElement* branch = new TBranchElement(this, name, (TClonesArray*) objptr, bufsize, splitlevel%kSplitCollectionOfPointers);
2524 fBranches.Add(branch);
2525 if (isptrptr) {
2526 branch->SetAddress(addr);
2527 } else {
2528 branch->SetObject(addr);
2529 }
2530 return branch;
2531 }
2532
2533 //
2534 // If we are not given an object to use as an i/o buffer
2535 // then create a temporary one which we will delete just
2536 // before returning.
2537 //
2538
2539 bool delobj = false;
2540
2541 if (!objptr) {
2542 objptr = (char*) cl->New();
2543 delobj = true;
2544 }
2545
2546 //
2547 // Avoid splitting unsplittable classes.
2548 //
2549
2550 if ((splitlevel > 0) && !cl->CanSplit()) {
2551 if (splitlevel != 99) {
2552 Warning("Bronch", "%s cannot be split, resetting splitlevel to 0", cl->GetName());
2553 }
2554 splitlevel = 0;
2555 }
2556
2557 //
2558 // Make sure the streamer info is built and fetch it.
2559 //
2560 // If we are splitting, then make sure the streamer info
2561 // is built unoptimized (data members are not combined).
2562 //
2563
2564 TStreamerInfo* sinfo = BuildStreamerInfo(cl, objptr, splitlevel==0);
2565 if (!sinfo) {
2566 Error("Bronch", "Cannot build the StreamerInfo for class: %s", cl->GetName());
2567 return nullptr;
2568 }
2569
2570 //
2571 // Create a dummy top level branch object.
2572 //
2573
2574 Int_t id = -1;
2575 if (splitlevel > 0) {
2576 id = -2;
2577 }
2578 TBranchElement* branch = new TBranchElement(this, name, sinfo, id, objptr, bufsize, splitlevel);
2579 fBranches.Add(branch);
2580
2581 //
2582 // Do splitting, if requested.
2583 //
2584
2585 if (splitlevel%kSplitCollectionOfPointers > 0) {
2586 branch->Unroll(name, cl, sinfo, objptr, bufsize, splitlevel);
2587 }
2588
2589 //
2590 // Setup our offsets into the user's i/o buffer.
2591 //
2592
2593 if (isptrptr) {
2594 branch->SetAddress(addr);
2595 } else {
2596 branch->SetObject(addr);
2597 }
2598
2599 if (delobj) {
2600 cl->Destructor(objptr);
2601 objptr = nullptr;
2602 }
2603
2604 return branch;
2605}
2606
2607////////////////////////////////////////////////////////////////////////////////
2608/// Browse content of the TTree.
2611{
2613 if (fUserInfo) {
2614 if (strcmp("TList",fUserInfo->GetName())==0) {
2615 fUserInfo->SetName("UserInfo");
2616 b->Add(fUserInfo);
2617 fUserInfo->SetName("TList");
2618 } else {
2619 b->Add(fUserInfo);
2620 }
2621 }
2622}
2623
2624////////////////////////////////////////////////////////////////////////////////
2625/// Build a Tree Index (default is TTreeIndex).
2626/// See a description of the parameters and functionality in
2627/// TTreeIndex::TTreeIndex().
2628///
2629/// The return value is the number of entries in the Index (< 0 indicates failure).
2630///
2631/// A TTreeIndex object pointed by fTreeIndex is created.
2632/// This object will be automatically deleted by the TTree destructor.
2633/// If an index is already existing, this is replaced by the new one without being
2634/// deleted. This behaviour prevents the deletion of a previously external index
2635/// assigned to the TTree via the TTree::SetTreeIndex() method.
2636/// \see also comments in TTree::SetTreeIndex().
2638Int_t TTree::BuildIndex(const char* majorname, const char* minorname /* = "0" */)
2639{
2640 fTreeIndex = GetPlayer()->BuildIndex(this, majorname, minorname);
2641 if (fTreeIndex->IsZombie()) {
2642 delete fTreeIndex;
2643 fTreeIndex = nullptr;
2644 return 0;
2645 }
2646 return fTreeIndex->GetN();
2647}
2648
2649////////////////////////////////////////////////////////////////////////////////
2650/// Build StreamerInfo for class cl.
2651/// pointer is an optional argument that may contain a pointer to an object of cl.
2653TStreamerInfo* TTree::BuildStreamerInfo(TClass* cl, void* pointer /* = 0 */, bool canOptimize /* = true */ )
2654{
2655 if (!cl) {
2656 return nullptr;
2657 }
2658 cl->BuildRealData(pointer);
2660
2661 // Create StreamerInfo for all base classes.
2662 TBaseClass* base = nullptr;
2663 TIter nextb(cl->GetListOfBases());
2664 while((base = (TBaseClass*) nextb())) {
2665 if (base->IsSTLContainer()) {
2666 continue;
2667 }
2668 TClass* clm = TClass::GetClass(base->GetName());
2669 BuildStreamerInfo(clm, pointer, canOptimize);
2670 }
2671 if (sinfo && fDirectory) {
2673 }
2674 return sinfo;
2675}
2676
2677////////////////////////////////////////////////////////////////////////////////
2678/// Enable the TTreeCache unless explicitly disabled for this TTree by
2679/// a prior call to `SetCacheSize(0)`.
2680/// If the environment variable `ROOT_TTREECACHE_SIZE` or the rootrc config
2681/// `TTreeCache.Size` has been set to zero, this call will over-ride them with
2682/// a value of 1.0 (i.e. use a cache size to hold 1 cluster)
2683///
2684/// Return true if there is a cache attached to the `TTree` (either pre-exisiting
2685/// or created as part of this call)
2686bool TTree::EnableCache()
2687{
2688 TFile* file = GetCurrentFile();
2689 if (!file)
2690 return false;
2691 // Check for an existing cache
2692 TTreeCache* pf = GetReadCache(file);
2693 if (pf)
2694 return true;
2695 if (fCacheUserSet && fCacheSize == 0)
2696 return false;
2697 return (0 == SetCacheSizeAux(true, -1));
2698}
2699
2700////////////////////////////////////////////////////////////////////////////////
2701/// Called by TTree::Fill() when file has reached its maximum fgMaxTreeSize.
2702/// Create a new file. If the original file is named "myfile.root",
2703/// subsequent files are named "myfile_1.root", "myfile_2.root", etc.
2704///
2705/// Returns a pointer to the new file.
2706///
2707/// Currently, the automatic change of file is restricted
2708/// to the case where the tree is in the top level directory.
2709/// The file should not contain sub-directories.
2710///
2711/// Before switching to a new file, the tree header is written
2712/// to the current file, then the current file is closed.
2713///
2714/// To process the multiple files created by ChangeFile, one must use
2715/// a TChain.
2716///
2717/// The new file name has a suffix "_N" where N is equal to fFileNumber+1.
2718/// By default a Root session starts with fFileNumber=0. One can set
2719/// fFileNumber to a different value via TTree::SetFileNumber.
2720/// In case a file named "_N" already exists, the function will try
2721/// a file named "__N", then "___N", etc.
2722///
2723/// fgMaxTreeSize can be set via the static function TTree::SetMaxTreeSize.
2724/// The default value of fgMaxTreeSize is 100 Gigabytes.
2725///
2726/// If the current file contains other objects like TH1 and TTree,
2727/// these objects are automatically moved to the new file.
2728///
2729/// \warning Be careful when writing the final Tree header to the file!
2730/// Don't do:
2731/// ~~~ {.cpp}
2732/// TFile *file = new TFile("myfile.root","recreate");
2733/// TTree *T = new TTree("T","title");
2734/// T->Fill(); // Loop
2735/// file->Write();
2736/// file->Close();
2737/// ~~~
2738/// \warning but do the following:
2739/// ~~~ {.cpp}
2740/// TFile *file = new TFile("myfile.root","recreate");
2741/// TTree *T = new TTree("T","title");
2742/// T->Fill(); // Loop
2743/// file = T->GetCurrentFile(); // To get the pointer to the current file
2744/// file->Write();
2745/// file->Close();
2746/// ~~~
2747///
2748/// \note This method is never called if the input file is a `TMemFile` or derivate.
2751{
2752 file->cd();
2753 Write();
2754 Reset();
2755 constexpr auto kBufSize = 2000;
2756 char* fname = new char[kBufSize];
2757 ++fFileNumber;
2758 char uscore[10];
2759 for (Int_t i = 0; i < 10; ++i) {
2760 uscore[i] = 0;
2761 }
2762 Int_t nus = 0;
2763 // Try to find a suitable file name that does not already exist.
2764 while (nus < 10) {
2765 uscore[nus] = '_';
2766 fname[0] = 0;
2767 strlcpy(fname, file->GetName(), kBufSize);
2768
2769 if (fFileNumber > 1) {
2770 char* cunder = strrchr(fname, '_');
2771 if (cunder) {
2772 snprintf(cunder, kBufSize - Int_t(cunder - fname), "%s%d", uscore, fFileNumber);
2773 const char* cdot = strrchr(file->GetName(), '.');
2774 if (cdot) {
2775 strlcat(fname, cdot, kBufSize);
2776 }
2777 } else {
2778 char fcount[21];
2779 snprintf(fcount,21, "%s%d", uscore, fFileNumber);
2780 strlcat(fname, fcount, kBufSize);
2781 }
2782 } else {
2783 char* cdot = strrchr(fname, '.');
2784 if (cdot) {
2785 snprintf(cdot, kBufSize - Int_t(fname-cdot), "%s%d", uscore, fFileNumber);
2786 strlcat(fname, strrchr(file->GetName(), '.'), kBufSize);
2787 } else {
2788 char fcount[21];
2789 snprintf(fcount,21, "%s%d", uscore, fFileNumber);
2790 strlcat(fname, fcount, kBufSize);
2791 }
2792 }
2793 if (gSystem->AccessPathName(fname)) {
2794 break;
2795 }
2796 ++nus;
2797 Warning("ChangeFile", "file %s already exist, trying with %d underscores", fname, nus+1);
2798 }
2799 Int_t compress = file->GetCompressionSettings();
2800 TFile* newfile = TFile::Open(fname, "recreate", "chain files", compress);
2801 if (newfile == nullptr) {
2802 Error("Fill","Failed to open new file %s, continuing as a memory tree.",fname);
2803 } else {
2804 Printf("Fill: Switching to new file: %s", fname);
2805 }
2806 // The current directory may contain histograms and trees.
2807 // These objects must be moved to the new file.
2808 TBranch* branch = nullptr;
2809 TObject* obj = nullptr;
2810 while ((obj = file->GetList()->First())) {
2811 file->Remove(obj);
2812 // Histogram: just change the directory.
2813 if (obj->InheritsFrom("TH1")) {
2814 gROOT->ProcessLine(TString::Format("((%s*)0x%zx)->SetDirectory((TDirectory*)0x%zx);", obj->ClassName(), (size_t) obj, (size_t) newfile));
2815 continue;
2816 }
2817 // Tree: must save all trees in the old file, reset them.
2818 if (obj->InheritsFrom(TTree::Class())) {
2819 TTree* t = (TTree*) obj;
2820 if (t != this) {
2821 t->AutoSave();
2822 t->Reset();
2824 }
2825 t->SetDirectory(newfile);
2826 TIter nextb(t->GetListOfBranches());
2827 while ((branch = (TBranch*)nextb())) {
2828 branch->SetFile(newfile);
2829 }
2830 if (t->GetBranchRef()) {
2831 t->GetBranchRef()->SetFile(newfile);
2832 }
2833 continue;
2834 }
2835 // Not a TH1 or a TTree, move object to new file.
2836 if (newfile) newfile->Append(obj);
2837 file->Remove(obj);
2838 }
2839 file->TObject::Delete();
2840 file = nullptr;
2841 delete[] fname;
2842 fname = nullptr;
2843 return newfile;
2844}
2845
2846////////////////////////////////////////////////////////////////////////////////
2847/// Check whether or not the address described by the last 3 parameters
2848/// matches the content of the branch. If a Data Model Evolution conversion
2849/// is involved, reset the fInfo of the branch.
2850/// The return values are:
2851//
2852/// - kMissingBranch (-5) : Missing branch
2853/// - kInternalError (-4) : Internal error (could not find the type corresponding to a data type number)
2854/// - kMissingCompiledCollectionProxy (-3) : Missing compiled collection proxy for a compiled collection
2855/// - kMismatch (-2) : Non-Class Pointer type given does not match the type expected by the branch
2856/// - kClassMismatch (-1) : Class Pointer type given does not match the type expected by the branch
2857/// - kMatch (0) : perfect match
2858/// - kMatchConversion (1) : match with (I/O) conversion
2859/// - kMatchConversionCollection (2) : match with (I/O) conversion of the content of a collection
2860/// - kMakeClass (3) : MakeClass mode so we can not check.
2861/// - kVoidPtr (4) : void* passed so no check was made.
2862/// - kNoCheck (5) : Underlying TBranch not yet available so no check was made.
2863/// In addition this can be multiplexed with the two bits:
2864/// - kNeedEnableDecomposedObj : in order for the address (type) to be 'usable' the branch needs to be in Decomposed Object (aka MakeClass) mode.
2865/// - kNeedDisableDecomposedObj : in order for the address (type) to be 'usable' the branch needs to not be in Decomposed Object (aka MakeClass) mode.
2866/// This bits can be masked out by using kDecomposedObjMask
2868Int_t TTree::CheckBranchAddressType(TBranch* branch, TClass* ptrClass, EDataType datatype, bool isptr)
2869{
2870 if (GetMakeClass()) {
2871 // If we are in MakeClass mode so we do not really use classes.
2872 return kMakeClass;
2873 }
2874
2875 // Let's determine what we need!
2876 TClass* expectedClass = nullptr;
2877 EDataType expectedType = kOther_t;
2878 if (0 != branch->GetExpectedType(expectedClass,expectedType) ) {
2879 // Something went wrong, the warning message has already been issued.
2880 return kInternalError;
2881 }
2882 bool isBranchElement = branch->InheritsFrom( TBranchElement::Class() );
2883 if (expectedClass && datatype == kOther_t && ptrClass == nullptr) {
2884 if (isBranchElement) {
2885 TBranchElement* bEl = (TBranchElement*)branch;
2886 bEl->SetTargetClass( expectedClass->GetName() );
2887 }
2888 if (expectedClass && expectedClass->GetCollectionProxy() && dynamic_cast<TEmulatedCollectionProxy*>(expectedClass->GetCollectionProxy())) {
2889 Error("SetBranchAddress", "Unable to determine the type given for the address for \"%s\". "
2890 "The class expected (%s) refers to an stl collection and do not have a compiled CollectionProxy. "
2891 "Please generate the dictionary for this class (%s)",
2892 branch->GetName(), expectedClass->GetName(), expectedClass->GetName());
2894 }
2895 if (!expectedClass->IsLoaded()) {
2896 // The originally expected class does not have a dictionary, it is then plausible that the pointer being passed is the right type
2897 // (we really don't know). So let's express that.
2898 Error("SetBranchAddress", "Unable to determine the type given for the address for \"%s\". "
2899 "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."
2900 "Please generate the dictionary for this class (%s)",
2901 branch->GetName(), expectedClass->GetName(), expectedClass->GetName());
2902 } else {
2903 Error("SetBranchAddress", "Unable to determine the type given for the address for \"%s\". "
2904 "This is probably due to a missing dictionary, the original data class for this branch is %s.", branch->GetName(), expectedClass->GetName());
2905 }
2906 return kClassMismatch;
2907 }
2908 if (expectedClass && ptrClass && (branch->GetMother() == branch)) {
2909 // Top Level branch
2910 if (!isptr) {
2911 Error("SetBranchAddress", "The address for \"%s\" should be the address of a pointer!", branch->GetName());
2912 }
2913 }
2914 if (expectedType == kFloat16_t) {
2915 expectedType = kFloat_t;
2916 }
2917 if (expectedType == kDouble32_t) {
2918 expectedType = kDouble_t;
2919 }
2920 if (datatype == kFloat16_t) {
2921 datatype = kFloat_t;
2922 }
2923 if (datatype == kDouble32_t) {
2924 datatype = kDouble_t;
2925 }
2926
2927 /////////////////////////////////////////////////////////////////////////////
2928 // Deal with the class renaming
2929 /////////////////////////////////////////////////////////////////////////////
2930
2931 if( expectedClass && ptrClass &&
2932 expectedClass != ptrClass &&
2933 isBranchElement &&
2934 ptrClass->GetSchemaRules() &&
2935 ptrClass->GetSchemaRules()->HasRuleWithSourceClass( expectedClass->GetName() ) ) {
2936 TBranchElement* bEl = (TBranchElement*)branch;
2937
2938 if ( ptrClass->GetCollectionProxy() && expectedClass->GetCollectionProxy() ) {
2939 if (gDebug > 7)
2940 Info("SetBranchAddress", "Matching STL collection (at least according to the SchemaRuleSet when "
2941 "reading a %s into a %s",expectedClass->GetName(),ptrClass->GetName());
2942
2943 bEl->SetTargetClass( ptrClass->GetName() );
2944 return kMatchConversion;
2945
2946 } else if ( !ptrClass->GetConversionStreamerInfo( expectedClass, bEl->GetClassVersion() ) &&
2947 !ptrClass->FindConversionStreamerInfo( expectedClass, bEl->GetCheckSum() ) ) {
2948 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());
2949
2950 bEl->SetTargetClass( expectedClass->GetName() );
2951 return kClassMismatch;
2952 }
2953 else {
2954
2955 bEl->SetTargetClass( ptrClass->GetName() );
2956 return kMatchConversion;
2957 }
2958
2959 } else if (expectedClass && ptrClass && !expectedClass->InheritsFrom(ptrClass)) {
2960
2961 if (expectedClass->GetCollectionProxy() && ptrClass->GetCollectionProxy() &&
2962 isBranchElement &&
2963 expectedClass->GetCollectionProxy()->GetValueClass() &&
2964 ptrClass->GetCollectionProxy()->GetValueClass() )
2965 {
2966 // In case of collection, we know how to convert them, if we know how to convert their content.
2967 // NOTE: we need to extend this to std::pair ...
2968
2969 TClass *onfileValueClass = expectedClass->GetCollectionProxy()->GetValueClass();
2970 TClass *inmemValueClass = ptrClass->GetCollectionProxy()->GetValueClass();
2971
2972 if (inmemValueClass->GetSchemaRules() &&
2973 inmemValueClass->GetSchemaRules()->HasRuleWithSourceClass(onfileValueClass->GetName() ) )
2974 {
2975 TBranchElement* bEl = (TBranchElement*)branch;
2976 bEl->SetTargetClass( ptrClass->GetName() );
2978 }
2979 }
2980
2981 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());
2982 if (isBranchElement) {
2983 TBranchElement* bEl = (TBranchElement*)branch;
2984 bEl->SetTargetClass( expectedClass->GetName() );
2985 }
2986 return kClassMismatch;
2987
2988 } else if ((expectedType != kOther_t) && (datatype != kOther_t) && (expectedType != kNoType_t) && (datatype != kNoType_t) && (expectedType != datatype)) {
2989 if (datatype != kChar_t) {
2990 // For backward compatibility we assume that (char*) was just a cast and/or a generic address
2991 Error("SetBranchAddress", "The pointer type given \"%s\" (%d) does not correspond to the type needed \"%s\" (%d) by the branch: %s",
2992 TDataType::GetTypeName(datatype), datatype, TDataType::GetTypeName(expectedType), expectedType, branch->GetName());
2993 return kMismatch;
2994 }
2995 } else if ((expectedClass && (datatype != kOther_t && datatype != kNoType_t && datatype != kInt_t)) ||
2996 (ptrClass && (expectedType != kOther_t && expectedType != kNoType_t && datatype != kInt_t)) ) {
2997 // Sometime a null pointer can look an int, avoid complaining in that case.
2998 if (expectedClass) {
2999 Error("SetBranchAddress", "The pointer type given \"%s\" (%d) does not correspond to the type needed \"%s\" by the branch: %s",
3000 TDataType::GetTypeName(datatype), datatype, expectedClass->GetName(), branch->GetName());
3001 if (isBranchElement) {
3002 TBranchElement* bEl = (TBranchElement*)branch;
3003 bEl->SetTargetClass( expectedClass->GetName() );
3004 }
3005 } else {
3006 // 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
3007 // a struct).
3008 bool found = false;
3009 if (ptrClass->IsLoaded()) {
3010 TIter next(ptrClass->GetListOfRealData());
3011 TRealData *rdm;
3012 while ((rdm = (TRealData*)next())) {
3013 if (rdm->GetThisOffset() == 0) {
3014 TDataType *dmtype = rdm->GetDataMember()->GetDataType();
3015 if (dmtype) {
3016 EDataType etype = (EDataType)dmtype->GetType();
3017 if (etype == expectedType) {
3018 found = true;
3019 }
3020 }
3021 break;
3022 }
3023 }
3024 } else {
3025 TIter next(ptrClass->GetListOfDataMembers());
3026 TDataMember *dm;
3027 while ((dm = (TDataMember*)next())) {
3028 if (dm->GetOffset() == 0) {
3029 TDataType *dmtype = dm->GetDataType();
3030 if (dmtype) {
3031 EDataType etype = (EDataType)dmtype->GetType();
3032 if (etype == expectedType) {
3033 found = true;
3034 }
3035 }
3036 break;
3037 }
3038 }
3039 }
3040 if (found) {
3041 // let's check the size.
3042 TLeaf *last = (TLeaf*)branch->GetListOfLeaves()->Last();
3043 long len = last->GetOffset() + last->GetLenType() * last->GetLen();
3044 if (len <= ptrClass->Size()) {
3045 return kMatch;
3046 }
3047 }
3048 Error("SetBranchAddress", "The pointer type given \"%s\" does not correspond to the type needed \"%s\" (%d) by the branch: %s",
3049 ptrClass->GetName(), TDataType::GetTypeName(expectedType), expectedType, branch->GetName());
3050 }
3051 return kMismatch;
3052 }
3053 if (expectedClass && expectedClass->GetCollectionProxy() && dynamic_cast<TEmulatedCollectionProxy*>(expectedClass->GetCollectionProxy())) {
3054 Error("SetBranchAddress", writeStlWithoutProxyMsg,
3055 expectedClass->GetName(), branch->GetName(), expectedClass->GetName());
3056 if (isBranchElement) {
3057 TBranchElement* bEl = (TBranchElement*)branch;
3058 bEl->SetTargetClass( expectedClass->GetName() );
3059 }
3061 }
3062 if (isBranchElement) {
3063 if (expectedClass) {
3064 TBranchElement* bEl = (TBranchElement*)branch;
3065 bEl->SetTargetClass( expectedClass->GetName() );
3066 } else if (expectedType != kNoType_t && expectedType != kOther_t) {
3068 }
3069 }
3070 return kMatch;
3071}
3072
3073////////////////////////////////////////////////////////////////////////////////
3074/// Create a clone of this tree and copy nentries.
3075///
3076/// By default copy all entries.
3077/// The compression level of the cloned tree is set to the destination
3078/// file's compression level.
3079///
3080/// NOTE: Only active branches are copied. See TTree::SetBranchStatus for more
3081/// information and usage regarding the (de)activation of branches. More
3082/// examples are provided in the tutorials listed below.
3083///
3084/// NOTE: If the TTree is a TChain, the structure of the first TTree
3085/// is used for the copy.
3086///
3087/// IMPORTANT: The cloned tree stays connected with this tree until
3088/// this tree is deleted. In particular, any changes in
3089/// branch addresses in this tree are forwarded to the
3090/// clone trees, unless a branch in a clone tree has had
3091/// its address changed, in which case that change stays in
3092/// effect. When this tree is deleted, all the addresses of
3093/// the cloned tree are reset to their default values.
3094///
3095/// If 'option' contains the word 'fast' and nentries is -1, the
3096/// cloning will be done without unzipping or unstreaming the baskets
3097/// (i.e., a direct copy of the raw bytes on disk).
3098///
3099/// When 'fast' is specified, 'option' can also contain a sorting
3100/// order for the baskets in the output file.
3101///
3102/// There are currently 3 supported sorting order:
3103///
3104/// - SortBasketsByOffset (the default)
3105/// - SortBasketsByBranch
3106/// - SortBasketsByEntry
3107///
3108/// When using SortBasketsByOffset the baskets are written in the
3109/// output file in the same order as in the original file (i.e. the
3110/// baskets are sorted by their offset in the original file; Usually
3111/// this also means that the baskets are sorted by the index/number of
3112/// the _last_ entry they contain)
3113///
3114/// When using SortBasketsByBranch all the baskets of each individual
3115/// branches are stored contiguously. This tends to optimize reading
3116/// speed when reading a small number (1->5) of branches, since all
3117/// their baskets will be clustered together instead of being spread
3118/// across the file. However it might decrease the performance when
3119/// reading more branches (or the full entry).
3120///
3121/// When using SortBasketsByEntry the baskets with the lowest starting
3122/// entry are written first. (i.e. the baskets are sorted by the
3123/// index/number of the first entry they contain). This means that on
3124/// the file the baskets will be in the order in which they will be
3125/// needed when reading the whole tree sequentially.
3126///
3127/// For examples of CloneTree, see tutorials:
3128///
3129/// - copytree.C:
3130/// A macro to copy a subset of a TTree to a new TTree.
3131/// The input file has been generated by the program in
3132/// $ROOTSYS/test/Event with: Event 1000 1 1 1
3133///
3134/// - copytree2.C:
3135/// A macro to copy a subset of a TTree to a new TTree.
3136/// One branch of the new Tree is written to a separate file.
3137/// The input file has been generated by the program in
3138/// $ROOTSYS/test/Event with: Event 1000 1 1 1
3140TTree* TTree::CloneTree(Long64_t nentries /* = -1 */, Option_t* option /* = "" */)
3141{
3142 // Options
3143 bool fastClone = false;
3144
3145 TString opt = option;
3146 opt.ToLower();
3147 if (opt.Contains("fast")) {
3148 fastClone = true;
3149 }
3150
3151 // If we are a chain, switch to the first tree.
3152 if ((fEntries > 0) && (LoadTree(0) < 0)) {
3153 // FIXME: We need an error message here.
3154 return nullptr;
3155 }
3156
3157 // Note: For a tree we get the this pointer, for
3158 // a chain we get the chain's current tree.
3159 TTree* thistree = GetTree();
3160
3161 // We will use this to override the IO features on the cloned branches.
3162 ROOT::TIOFeatures features = this->GetIOFeatures();
3163 ;
3164
3165 // Note: For a chain, the returned clone will be
3166 // a clone of the chain's first tree.
3167 TTree* newtree = (TTree*) thistree->Clone();
3168 if (!newtree) {
3169 return nullptr;
3170 }
3171
3172 // The clone should not delete any objects allocated by SetAddress().
3173 TObjArray* branches = newtree->GetListOfBranches();
3174 Int_t nb = branches->GetEntriesFast();
3175 for (Int_t i = 0; i < nb; ++i) {
3176 TBranch* br = (TBranch*) branches->UncheckedAt(i);
3178 ((TBranchElement*) br)->ResetDeleteObject();
3179 }
3180 }
3181
3182 // Add the new tree to the list of clones so that
3183 // we can later inform it of changes to branch addresses.
3184 thistree->AddClone(newtree);
3185 if (thistree != this) {
3186 // In case this object is a TChain, add the clone
3187 // also to the TChain's list of clones.
3188 AddClone(newtree);
3189 }
3190
3191 newtree->Reset();
3192
3193 TDirectory* ndir = newtree->GetDirectory();
3194 TFile* nfile = nullptr;
3195 if (ndir) {
3196 nfile = ndir->GetFile();
3197 }
3198 Int_t newcomp = -1;
3199 if (nfile) {
3200 newcomp = nfile->GetCompressionSettings();
3201 }
3202
3203 //
3204 // Delete non-active branches from the clone.
3205 //
3206 // Note: If we are a chain, this does nothing
3207 // since chains have no leaves.
3208 TObjArray* leaves = newtree->GetListOfLeaves();
3209 Int_t nleaves = leaves->GetEntriesFast();
3210 for (Int_t lndx = 0; lndx < nleaves; ++lndx) {
3211 TLeaf* leaf = (TLeaf*) leaves->UncheckedAt(lndx);
3212 if (!leaf) {
3213 continue;
3214 }
3215 TBranch* branch = leaf->GetBranch();
3216 if (branch && (newcomp > -1)) {
3217 branch->SetCompressionSettings(newcomp);
3218 }
3219 if (branch) branch->SetIOFeatures(features);
3220 if (!branch || !branch->TestBit(kDoNotProcess)) {
3221 continue;
3222 }
3223 // size might change at each iteration of the loop over the leaves.
3224 nb = branches->GetEntriesFast();
3225 for (Long64_t i = 0; i < nb; ++i) {
3226 TBranch* br = (TBranch*) branches->UncheckedAt(i);
3227 if (br == branch) {
3228 branches->RemoveAt(i);
3229 delete br;
3230 br = nullptr;
3231 branches->Compress();
3232 break;
3233 }
3234 TObjArray* lb = br->GetListOfBranches();
3235 Int_t nb1 = lb->GetEntriesFast();
3236 for (Int_t j = 0; j < nb1; ++j) {
3237 TBranch* b1 = (TBranch*) lb->UncheckedAt(j);
3238 if (!b1) {
3239 continue;
3240 }
3241 if (b1 == branch) {
3242 lb->RemoveAt(j);
3243 delete b1;
3244 b1 = nullptr;
3245 lb->Compress();
3246 break;
3247 }
3248 TObjArray* lb1 = b1->GetListOfBranches();
3249 Int_t nb2 = lb1->GetEntriesFast();
3250 for (Int_t k = 0; k < nb2; ++k) {
3251 TBranch* b2 = (TBranch*) lb1->UncheckedAt(k);
3252 if (!b2) {
3253 continue;
3254 }
3255 if (b2 == branch) {
3256 lb1->RemoveAt(k);
3257 delete b2;
3258 b2 = nullptr;
3259 lb1->Compress();
3260 break;
3261 }
3262 }
3263 }
3264 }
3265 }
3266 leaves->Compress();
3267
3268 // Copy MakeClass status.
3269 newtree->SetMakeClass(fMakeClass);
3270
3271 // Copy branch addresses.
3272 CopyAddresses(newtree);
3273
3274 //
3275 // Copy entries if requested.
3276 //
3277
3278 if (nentries != 0) {
3279 if (fastClone && (nentries < 0)) {
3280 if ( newtree->CopyEntries( this, -1, option, false ) < 0 ) {
3281 // There was a problem!
3282 Error("CloneTTree", "TTree has not been cloned\n");
3283 delete newtree;
3284 newtree = nullptr;
3285 return nullptr;
3286 }
3287 } else {
3288 newtree->CopyEntries( this, nentries, option, false );
3289 }
3290 }
3291
3292 return newtree;
3293}
3294
3295////////////////////////////////////////////////////////////////////////////////
3296/// Set branch addresses of passed tree equal to ours.
3297/// If undo is true, reset the branch addresses instead of copying them.
3298/// This ensures 'separation' of a cloned tree from its original.
3300void TTree::CopyAddresses(TTree* tree, bool undo)
3301{
3302 // Copy branch addresses starting from branches.
3303 TObjArray* branches = GetListOfBranches();
3304 Int_t nbranches = branches->GetEntriesFast();
3305 for (Int_t i = 0; i < nbranches; ++i) {
3306 TBranch* branch = (TBranch*) branches->UncheckedAt(i);
3307 if (branch->TestBit(kDoNotProcess)) {
3308 continue;
3309 }
3310 if (undo) {
3311 TBranch* br = tree->GetBranch(branch->GetName());
3312 tree->ResetBranchAddress(br);
3313 } else {
3314 char* addr = branch->GetAddress();
3315 if (!addr) {
3316 if (branch->IsA() == TBranch::Class()) {
3317 // If the branch was created using a leaflist, the branch itself may not have
3318 // an address but the leaf might already.
3319 TLeaf *firstleaf = (TLeaf*)branch->GetListOfLeaves()->At(0);
3320 if (!firstleaf || firstleaf->GetValuePointer()) {
3321 // Either there is no leaf (and thus no point in copying the address)
3322 // or the leaf has an address but we can not copy it via the branche
3323 // this will be copied via the next loop (over the leaf).
3324 continue;
3325 }
3326 }
3327 // Note: This may cause an object to be allocated.
3328 branch->SetAddress(nullptr);
3329 addr = branch->GetAddress();
3330 }
3331 TBranch* br = tree->GetBranch(branch->GetFullName());
3332 if (br) {
3333 if (br->GetMakeClass() != branch->GetMakeClass())
3334 br->SetMakeClass(branch->GetMakeClass());
3335 br->SetAddress(addr);
3336 // The copy does not own any object allocated by SetAddress().
3338 ((TBranchElement*) br)->ResetDeleteObject();
3339 }
3340 } else {
3341 Warning("CopyAddresses", "Could not find branch named '%s' in tree named '%s'", branch->GetName(), tree->GetName());
3342 }
3343 }
3344 }
3345
3346 // Copy branch addresses starting from leaves.
3347 TObjArray* tleaves = tree->GetListOfLeaves();
3348 Int_t ntleaves = tleaves->GetEntriesFast();
3349 std::set<TLeaf*> updatedLeafCount;
3350 for (Int_t i = 0; i < ntleaves; ++i) {
3351 TLeaf* tleaf = (TLeaf*) tleaves->UncheckedAt(i);
3352 TBranch* tbranch = tleaf->GetBranch();
3353 TBranch* branch = GetBranch(tbranch->GetName());
3354 if (!branch) {
3355 continue;
3356 }
3357 TLeaf* leaf = branch->GetLeaf(tleaf->GetName());
3358 if (!leaf) {
3359 continue;
3360 }
3361 if (branch->TestBit(kDoNotProcess)) {
3362 continue;
3363 }
3364 if (undo) {
3365 // Now we know whether the address has been transfered
3366 tree->ResetBranchAddress(tbranch);
3367 } else {
3368 TBranchElement *mother = dynamic_cast<TBranchElement*>(leaf->GetBranch()->GetMother());
3369 bool needAddressReset = false;
3370 if (leaf->GetLeafCount() && (leaf->TestBit(TLeaf::kNewValue) || !leaf->GetValuePointer() || (mother && mother->IsObjectOwner())) && tleaf->GetLeafCount())
3371 {
3372 // If it is an array and it was allocated by the leaf itself,
3373 // let's make sure it is large enough for the incoming data.
3374 if (leaf->GetLeafCount()->GetMaximum() < tleaf->GetLeafCount()->GetMaximum()) {
3375 leaf->GetLeafCount()->IncludeRange( tleaf->GetLeafCount() );
3376 updatedLeafCount.insert(leaf->GetLeafCount());
3377 needAddressReset = true;
3378 } else {
3379 needAddressReset = (updatedLeafCount.find(leaf->GetLeafCount()) != updatedLeafCount.end());
3380 }
3381 }
3382 if (needAddressReset && leaf->GetValuePointer()) {
3383 if (leaf->IsA() == TLeafElement::Class() && mother)
3384 mother->ResetAddress();
3385 else
3386 leaf->SetAddress(nullptr);
3387 }
3388 if (!branch->GetAddress() && !leaf->GetValuePointer()) {
3389 // We should attempts to set the address of the branch.
3390 // something like:
3391 //(TBranchElement*)branch->GetMother()->SetAddress(0)
3392 //plus a few more subtleties (see TBranchElement::GetEntry).
3393 //but for now we go the simplest route:
3394 //
3395 // Note: This may result in the allocation of an object.
3396 branch->SetupAddresses();
3397 }
3398 if (branch->GetAddress()) {
3399 tree->SetBranchAddress(branch->GetName(), (void*) branch->GetAddress());
3400 TBranch* br = tree->GetBranch(branch->GetName());
3401 if (br) {
3402 if (br->IsA() != branch->IsA()) {
3403 Error(
3404 "CopyAddresses",
3405 "Branch kind mismatch between input tree '%s' and output tree '%s' for branch '%s': '%s' vs '%s'",
3406 tree->GetName(), br->GetTree()->GetName(), br->GetName(), branch->IsA()->GetName(),
3407 br->IsA()->GetName());
3408 }
3409 // The copy does not own any object allocated by SetAddress().
3410 // FIXME: We do too much here, br may not be a top-level branch.
3412 ((TBranchElement*) br)->ResetDeleteObject();
3413 }
3414 } else {
3415 Warning("CopyAddresses", "Could not find branch named '%s' in tree named '%s'", branch->GetName(), tree->GetName());
3416 }
3417 } else {
3418 tleaf->SetAddress(leaf->GetValuePointer());
3419 }
3420 }
3421 }
3422
3423 if (undo &&
3424 ( tree->IsA()->InheritsFrom("TNtuple") || tree->IsA()->InheritsFrom("TNtupleD") )
3425 ) {
3426 tree->ResetBranchAddresses();
3427 }
3428}
3429
3430namespace {
3431
3432 enum EOnIndexError { kDrop, kKeep, kBuild };
3433
3434 bool R__HandleIndex(EOnIndexError onIndexError, TTree *newtree, TTree *oldtree)
3435 {
3436 // Return true if we should continue to handle indices, false otherwise.
3437
3438 bool withIndex = true;
3439
3440 if ( newtree->GetTreeIndex() ) {
3441 if ( oldtree->GetTree()->GetTreeIndex() == nullptr ) {
3442 switch (onIndexError) {
3443 case kDrop:
3444 delete newtree->GetTreeIndex();
3445 newtree->SetTreeIndex(nullptr);
3446 withIndex = false;
3447 break;
3448 case kKeep:
3449 // Nothing to do really.
3450 break;
3451 case kBuild:
3452 // Build the index then copy it
3453 if (oldtree->GetTree()->BuildIndex(newtree->GetTreeIndex()->GetMajorName(), newtree->GetTreeIndex()->GetMinorName())) {
3454 newtree->GetTreeIndex()->Append(oldtree->GetTree()->GetTreeIndex(), true);
3455 // Clean up
3456 delete oldtree->GetTree()->GetTreeIndex();
3457 oldtree->GetTree()->SetTreeIndex(nullptr);
3458 }
3459 break;
3460 }
3461 } else {
3462 newtree->GetTreeIndex()->Append(oldtree->GetTree()->GetTreeIndex(), true);
3463 }
3464 } else if ( oldtree->GetTree()->GetTreeIndex() != nullptr ) {
3465 // We discover the first index in the middle of the chain.
3466 switch (onIndexError) {
3467 case kDrop:
3468 // Nothing to do really.
3469 break;
3470 case kKeep: {
3472 index->SetTree(newtree);
3473 newtree->SetTreeIndex(index);
3474 break;
3475 }
3476 case kBuild:
3477 if (newtree->GetEntries() == 0) {
3478 // Start an index.
3480 index->SetTree(newtree);
3481 newtree->SetTreeIndex(index);
3482 } else {
3483 // Build the index so far.
3484 if (newtree->BuildIndex(oldtree->GetTree()->GetTreeIndex()->GetMajorName(), oldtree->GetTree()->GetTreeIndex()->GetMinorName())) {
3485 newtree->GetTreeIndex()->Append(oldtree->GetTree()->GetTreeIndex(), true);
3486 }
3487 }
3488 break;
3489 }
3490 } else if ( onIndexError == kDrop ) {
3491 // There is no index on this or on tree->GetTree(), we know we have to ignore any further
3492 // index
3493 withIndex = false;
3494 }
3495 return withIndex;
3496 }
3497}
3498
3499////////////////////////////////////////////////////////////////////////////////
3500/// Copy nentries from given tree to this tree.
3501/// This routines assumes that the branches that intended to be copied are
3502/// already connected. The typical case is that this tree was created using
3503/// tree->CloneTree(0).
3504///
3505/// By default copy all entries.
3506///
3507/// Returns number of bytes copied to this tree.
3508///
3509/// If 'option' contains the word 'fast' and nentries is -1, the cloning will be
3510/// done without unzipping or unstreaming the baskets (i.e., a direct copy of the
3511/// raw bytes on disk).
3512///
3513/// When 'fast' is specified, 'option' can also contains a sorting order for the
3514/// baskets in the output file.
3515///
3516/// There are currently 3 supported sorting order:
3517///
3518/// - SortBasketsByOffset (the default)
3519/// - SortBasketsByBranch
3520/// - SortBasketsByEntry
3521///
3522/// See TTree::CloneTree for a detailed explanation of the semantics of these 3 options.
3523///
3524/// If the tree or any of the underlying tree of the chain has an index, that index and any
3525/// index in the subsequent underlying TTree objects will be merged.
3526///
3527/// There are currently three 'options' to control this merging:
3528/// - NoIndex : all the TTreeIndex object are dropped.
3529/// - DropIndexOnError : if any of the underlying TTree object do no have a TTreeIndex,
3530/// they are all dropped.
3531/// - AsIsIndexOnError [default]: In case of missing TTreeIndex, the resulting TTree index has gaps.
3532/// - BuildIndexOnError : If any of the underlying TTree objects do not have a TTreeIndex,
3533/// all TTreeIndex are 'ignored' and the missing piece are rebuilt.
3535Long64_t TTree::CopyEntries(TTree* tree, Long64_t nentries /* = -1 */, Option_t* option /* = "" */, bool needCopyAddresses /* = false */)
3536{
3537 if (!tree) {
3538 return 0;
3539 }
3540 // Options
3541 TString opt = option;
3542 opt.ToLower();
3543 bool fastClone = opt.Contains("fast");
3544 bool withIndex = !opt.Contains("noindex");
3545 EOnIndexError onIndexError;
3546 if (opt.Contains("asisindex")) {
3547 onIndexError = kKeep;
3548 } else if (opt.Contains("buildindex")) {
3549 onIndexError = kBuild;
3550 } else if (opt.Contains("dropindex")) {
3551 onIndexError = kDrop;
3552 } else {
3553 onIndexError = kBuild;
3554 }
3555 Ssiz_t cacheSizeLoc = opt.Index("cachesize=");
3556 Long64_t cacheSize = -1;
3557 if (cacheSizeLoc != TString::kNPOS) {
3558 // If the parse faile, cacheSize stays at -1.
3559 Ssiz_t cacheSizeEnd = opt.Index(" ",cacheSizeLoc+10) - (cacheSizeLoc+10);
3560 TSubString cacheSizeStr( opt(cacheSizeLoc+10,cacheSizeEnd) );
3561 auto parseResult = ROOT::FromHumanReadableSize(cacheSizeStr,cacheSize);
3562 if (parseResult == ROOT::EFromHumanReadableSize::kParseFail) {
3563 Warning("CopyEntries","The cachesize option can not be parsed: %s. The default size will be used.",cacheSizeStr.String().Data());
3564 } else if (parseResult == ROOT::EFromHumanReadableSize::kOverflow) {
3565 double m;
3566 const char *munit = nullptr;
3567 ROOT::ToHumanReadableSize(std::numeric_limits<decltype(cacheSize)>::max(),false,&m,&munit);
3568
3569 Warning("CopyEntries","The cachesize option is too large: %s (%g%s max). The default size will be used.",cacheSizeStr.String().Data(),m,munit);
3570 }
3571 }
3572 if (gDebug > 0 && cacheSize != -1) Info("CopyEntries","Using Cache size: %lld\n",cacheSize);
3573
3574 Long64_t nbytes = 0;
3575 Long64_t treeEntries = tree->GetEntriesFast();
3576 if (nentries < 0) {
3577 nentries = treeEntries;
3578 } else if (nentries > treeEntries) {
3579 nentries = treeEntries;
3580 }
3581
3582 if (fastClone && (nentries < 0 || nentries == tree->GetEntriesFast())) {
3583 // Quickly copy the basket without decompression and streaming.
3584 Long64_t totbytes = GetTotBytes();
3585 for (Long64_t i = 0; i < nentries; i += tree->GetTree()->GetEntries()) {
3586 if (tree->LoadTree(i) < 0) {
3587 break;
3588 }
3589 if ( withIndex ) {
3590 withIndex = R__HandleIndex( onIndexError, this, tree );
3591 }
3592 if (this->GetDirectory()) {
3593 TFile* file2 = this->GetDirectory()->GetFile();
3594 if (file2 && (file2->GetEND() > TTree::GetMaxTreeSize())) {
3595 if (this->GetDirectory() == (TDirectory*) file2) {
3596 this->ChangeFile(file2);
3597 }
3598 }
3599 }
3600 TTreeCloner cloner(tree->GetTree(), this, option, TTreeCloner::kNoWarnings);
3601 if (cloner.IsValid()) {
3602 this->SetEntries(this->GetEntries() + tree->GetTree()->GetEntries());
3603 if (cacheSize != -1) cloner.SetCacheSize(cacheSize);
3604 cloner.Exec();
3605 } else {
3606 if (i == 0) {
3607 Warning("CopyEntries","%s",cloner.GetWarning());
3608 // If the first cloning does not work, something is really wrong
3609 // (since apriori the source and target are exactly the same structure!)
3610 return -1;
3611 } else {
3612 if (cloner.NeedConversion()) {
3613 TTree *localtree = tree->GetTree();
3614 Long64_t tentries = localtree->GetEntries();
3615 if (needCopyAddresses) {
3616 // Copy MakeClass status.
3617 tree->SetMakeClass(fMakeClass);
3618 // Copy branch addresses.
3619 CopyAddresses(tree);
3620 }
3621 for (Long64_t ii = 0; ii < tentries; ii++) {
3622 if (localtree->GetEntry(ii) <= 0) {
3623 break;
3624 }
3625 this->Fill();
3626 }
3627 if (needCopyAddresses)
3628 tree->ResetBranchAddresses();
3629 if (this->GetTreeIndex()) {
3630 this->GetTreeIndex()->Append(tree->GetTree()->GetTreeIndex(), true);
3631 }
3632 } else {
3633 Warning("CopyEntries","%s",cloner.GetWarning());
3634 if (tree->GetDirectory() && tree->GetDirectory()->GetFile()) {
3635 Warning("CopyEntries", "Skipped file %s\n", tree->GetDirectory()->GetFile()->GetName());
3636 } else {
3637 Warning("CopyEntries", "Skipped file number %d\n", tree->GetTreeNumber());
3638 }
3639 }
3640 }
3641 }
3642
3643 }
3644 if (this->GetTreeIndex()) {
3645 this->GetTreeIndex()->Append(nullptr,false); // Force the sorting
3646 }
3647 nbytes = GetTotBytes() - totbytes;
3648 } else {
3649 if (nentries < 0) {
3650 nentries = treeEntries;
3651 } else if (nentries > treeEntries) {
3652 nentries = treeEntries;
3653 }
3654 if (needCopyAddresses) {
3655 // Copy MakeClass status.
3656 tree->SetMakeClass(fMakeClass);
3657 // Copy branch addresses.
3658 CopyAddresses(tree);
3659 }
3660 Int_t treenumber = -1;
3661 for (Long64_t i = 0; i < nentries; i++) {
3662 if (tree->LoadTree(i) < 0) {
3663 break;
3664 }
3665 if (treenumber != tree->GetTreeNumber()) {
3666 if ( withIndex ) {
3667 withIndex = R__HandleIndex( onIndexError, this, tree );
3668 }
3669 treenumber = tree->GetTreeNumber();
3670 }
3671 if (tree->GetEntry(i) <= 0) {
3672 break;
3673 }
3674 nbytes += this->Fill();
3675 }
3676 if (needCopyAddresses)
3677 tree->ResetBranchAddresses();
3678 if (this->GetTreeIndex()) {
3679 this->GetTreeIndex()->Append(nullptr,false); // Force the sorting
3680 }
3681 }
3682 return nbytes;
3683}
3684
3685////////////////////////////////////////////////////////////////////////////////
3686/// Copy a tree with selection.
3687///
3688/// ### Important:
3689///
3690/// The returned copied tree stays connected with the original tree
3691/// until the original tree is deleted. In particular, any changes
3692/// to the branch addresses in the original tree are also made to
3693/// the copied tree. Any changes made to the branch addresses of the
3694/// copied tree are overridden anytime the original tree changes its
3695/// branch addresses. When the original tree is deleted, all the
3696/// branch addresses of the copied tree are set to zero.
3697///
3698/// For examples of CopyTree, see the tutorials:
3699///
3700/// - copytree.C:
3701/// Example macro to copy a subset of a tree to a new tree.
3702/// The input file was generated by running the program in
3703/// $ROOTSYS/test/Event in this way:
3704/// ~~~ {.cpp}
3705/// ./Event 1000 1 1 1
3706/// ~~~
3707/// - copytree2.C
3708/// Example macro to copy a subset of a tree to a new tree.
3709/// One branch of the new tree is written to a separate file.
3710/// The input file was generated by running the program in
3711/// $ROOTSYS/test/Event in this way:
3712/// ~~~ {.cpp}
3713/// ./Event 1000 1 1 1
3714/// ~~~
3715/// - copytree3.C
3716/// Example macro to copy a subset of a tree to a new tree.
3717/// Only selected entries are copied to the new tree.
3718/// NOTE that only the active branches are copied.
3720TTree* TTree::CopyTree(const char* selection, Option_t* option /* = 0 */, Long64_t nentries /* = TTree::kMaxEntries */, Long64_t firstentry /* = 0 */)
3721{
3722 GetPlayer();
3723 if (fPlayer) {
3724 return fPlayer->CopyTree(selection, option, nentries, firstentry);
3725 }
3726 return nullptr;
3727}
3728
3729////////////////////////////////////////////////////////////////////////////////
3730/// Create a basket for this tree and given branch.
3733{
3734 if (!branch) {
3735 return nullptr;
3736 }
3737 return new TBasket(branch->GetName(), GetName(), branch);
3738}
3739
3740////////////////////////////////////////////////////////////////////////////////
3741/// Delete this tree from memory or/and disk.
3742///
3743/// - if option == "all" delete Tree object from memory AND from disk
3744/// all baskets on disk are deleted. All keys with same name
3745/// are deleted.
3746/// - if option =="" only Tree object in memory is deleted.
3748void TTree::Delete(Option_t* option /* = "" */)
3749{
3750 TFile *file = GetCurrentFile();
3751
3752 // delete all baskets and header from file
3753 if (file && option && !strcmp(option,"all")) {
3754 if (!file->IsWritable()) {
3755 Error("Delete","File : %s is not writable, cannot delete Tree:%s", file->GetName(),GetName());
3756 return;
3757 }
3758
3759 //find key and import Tree header in memory
3760 TKey *key = fDirectory->GetKey(GetName());
3761 if (!key) return;
3762
3763 TDirectory *dirsav = gDirectory;
3764 file->cd();
3765
3766 //get list of leaves and loop on all the branches baskets
3767 TIter next(GetListOfLeaves());
3768 TLeaf *leaf;
3769 char header[16];
3770 Int_t ntot = 0;
3771 Int_t nbask = 0;
3772 Int_t nbytes,objlen,keylen;
3773 while ((leaf = (TLeaf*)next())) {
3774 TBranch *branch = leaf->GetBranch();
3775 Int_t nbaskets = branch->GetMaxBaskets();
3776 for (Int_t i=0;i<nbaskets;i++) {
3777 Long64_t pos = branch->GetBasketSeek(i);
3778 if (!pos) continue;
3779 TFile *branchFile = branch->GetFile();
3780 if (!branchFile) continue;
3781 branchFile->GetRecordHeader(header,pos,16,nbytes,objlen,keylen);
3782 if (nbytes <= 0) continue;
3783 branchFile->MakeFree(pos,pos+nbytes-1);
3784 ntot += nbytes;
3785 nbask++;
3786 }
3787 }
3788
3789 // delete Tree header key and all keys with the same name
3790 // A Tree may have been saved many times. Previous cycles are invalid.
3791 while (key) {
3792 ntot += key->GetNbytes();
3793 key->Delete();
3794 delete key;
3795 key = fDirectory->GetKey(GetName());
3796 }
3797 if (dirsav) dirsav->cd();
3798 if (gDebug) Info("TTree::Delete", "Deleting Tree: %s: %d baskets deleted. Total space freed = %d bytes\n",GetName(),nbask,ntot);
3799 }
3800
3801 if (fDirectory) {
3802 fDirectory->Remove(this);
3803 //delete the file cache if it points to this Tree
3804 MoveReadCache(file,nullptr);
3805 fDirectory = nullptr;
3807 }
3808
3809 // Delete object from CINT symbol table so it can not be used anymore.
3810 gCling->DeleteGlobal(this);
3811
3812 // Warning: We have intentional invalidated this object while inside a member function!
3813 delete this;
3814}
3815
3816 ///////////////////////////////////////////////////////////////////////////////
3817 /// Called by TKey and TObject::Clone to automatically add us to a directory
3818 /// when we are read from a file.
3821{
3822 if (fDirectory == dir) return;
3823 if (fDirectory) {
3824 fDirectory->Remove(this);
3825 // Delete or move the file cache if it points to this Tree
3826 TFile *file = fDirectory->GetFile();
3827 MoveReadCache(file,dir);
3828 }
3829 fDirectory = dir;
3830 TBranch* b = nullptr;
3831 TIter next(GetListOfBranches());
3832 while((b = (TBranch*) next())) {
3833 b->UpdateFile();
3834 }
3835 if (fBranchRef) {
3837 }
3838 if (fDirectory) fDirectory->Append(this);
3839}
3840
3841////////////////////////////////////////////////////////////////////////////////
3842/// Draw expression varexp for specified entries.
3843///
3844/// \return -1 in case of error or number of selected events in case of success.
3845///
3846/// This function accepts TCut objects as arguments.
3847/// Useful to use the string operator +
3848///
3849/// Example:
3850///
3851/// ~~~ {.cpp}
3852/// ntuple.Draw("x",cut1+cut2+cut3);
3853/// ~~~
3854
3856Long64_t TTree::Draw(const char* varexp, const TCut& selection, Option_t* option, Long64_t nentries, Long64_t firstentry)
3857{
3858 return TTree::Draw(varexp, selection.GetTitle(), option, nentries, firstentry);
3859}
3860
3861/////////////////////////////////////////////////////////////////////////////////////////
3862/// \brief Draw expression varexp for entries and objects that pass a (optional) selection.
3863///
3864/// \return -1 in case of error or number of selected events in case of success.
3865///
3866/// \param [in] varexp
3867/// \parblock
3868/// A string that takes one of these general forms:
3869/// - "e1" produces a 1-d histogram (TH1F) of expression "e1"
3870/// - "e1:e2" produces an unbinned 2-d scatter-plot (TGraph) of "e1"
3871/// on the y-axis versus "e2" on the x-axis
3872/// - "e1:e2:e3" produces an unbinned 3-d scatter-plot (TPolyMarker3D) of "e1"
3873/// vs "e2" vs "e3" on the z-, y-, x-axis, respectively
3874/// - "e1:e2:e3:e4" produces an unbinned 3-d scatter-plot (TPolyMarker3D) of "e1"
3875/// vs "e2" vs "e3" and "e4" mapped on the current color palette.
3876/// (to create histograms in the 2, 3, and 4 dimensional case,
3877/// see section "Saving the result of Draw to an histogram")
3878/// - "e1:e2:e3:e4:e5" with option "GL5D" produces a 5D plot using OpenGL. `gStyle->SetCanvasPreferGL(true)` is needed.
3879/// - Any number of variables no fewer than two can be used with the options "CANDLE" and "PARA"
3880/// - An arbitrary number of variables can be used with the option "GOFF"
3881///
3882/// Examples:
3883/// - "x": the simplest case, it draws a 1-Dim histogram of column x
3884/// - "sqrt(x)", "x*y/z": draw histogram with the values of the specified numerical expression across TTree events
3885/// - "y:sqrt(x)": 2-Dim histogram of y versus sqrt(x)
3886/// - "px:py:pz:2.5*E": produces a 3-d scatter-plot of px vs py ps pz
3887/// and the color number of each marker will be 2.5*E.
3888/// If the color number is negative it is set to 0.
3889/// If the color number is greater than the current number of colors
3890/// it is set to the highest color number. The default number of
3891/// colors is 50. See TStyle::SetPalette for setting a new color palette.
3892///
3893/// The expressions can use all the operations and built-in functions
3894/// supported by TFormula (see TFormula::Analyze()), including free
3895/// functions taking numerical arguments (e.g. TMath::Bessel()).
3896/// In addition, you can call member functions taking numerical
3897/// arguments. For example, these are two valid expressions:
3898/// ~~~ {.cpp}
3899/// TMath::BreitWigner(fPx,3,2)
3900/// event.GetHistogram()->GetXaxis()->GetXmax()
3901/// ~~~
3902/// \endparblock
3903/// \param [in] selection
3904/// \parblock
3905/// A string containing a selection expression.
3906/// In a selection all usual C++ mathematical and logical operators are allowed.
3907/// The value corresponding to the selection expression is used as a weight
3908/// to fill the histogram (a weight of 0 is equivalent to not filling the histogram).\n
3909/// \n
3910/// Examples:
3911/// - "x<y && sqrt(z)>3.2": returns a weight = 0 or 1
3912/// - "(x+y)*(sqrt(z)>3.2)": returns a weight = x+y if sqrt(z)>3.2, 0 otherwise\n
3913/// \n
3914/// If the selection expression returns an array, it is iterated over in sync with the
3915/// array returned by the varexp argument (as described below in "Drawing expressions using arrays and array
3916/// elements"). For example, if, for a given event, varexp evaluates to
3917/// `{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:
3918/// ~~~{.cpp}
3919/// // Muon_pt is an array: fill a histogram with the array elements > 100 in each event
3920/// tree->Draw('Muon_pt', 'Muon_pt > 100')
3921/// ~~~
3922/// \endparblock
3923/// \param [in] option
3924/// \parblock
3925/// The drawing option.
3926/// - When an histogram is produced it can be any histogram drawing option
3927/// listed in THistPainter.
3928/// - when no option is specified:
3929/// - the default histogram drawing option is used
3930/// if the expression is of the form "e1".
3931/// - if the expression is of the form "e1:e2"or "e1:e2:e3" a cloud of
3932/// unbinned 2D or 3D points is drawn respectively.
3933/// - if the expression has four fields "e1:e2:e3:e4" a cloud of unbinned 3D
3934/// points is produced with e1 vs e2 vs e3, and e4 is mapped on the current color
3935/// palette.
3936/// - If option COL is specified when varexp has three fields:
3937/// ~~~ {.cpp}
3938/// tree.Draw("e1:e2:e3","","col");
3939/// ~~~
3940/// a 2D scatter is produced with e1 vs e2, and e3 is mapped on the current
3941/// color palette. The colors for e3 are evaluated once in linear scale before
3942/// painting. Therefore changing the pad to log scale along Z as no effect
3943/// on the colors.
3944/// - if expression has more than four fields the option "PARA"or "CANDLE"
3945/// can be used.
3946/// - If option contains the string "goff", no graphics is generated.
3947/// \endparblock
3948/// \param [in] nentries The number of entries to process (default is all)
3949/// \param [in] firstentry The first entry to process (default is 0)
3950///
3951/// ### Drawing expressions using arrays and array elements
3952///
3953/// Let assumes, a leaf fMatrix, on the branch fEvent, which is a 3 by 3 array,
3954/// or a TClonesArray.
3955/// In a TTree::Draw expression you can now access fMatrix using the following
3956/// syntaxes:
3957///
3958/// | String passed | What is used for each entry of the tree
3959/// |-----------------|--------------------------------------------------------|
3960/// | `fMatrix` | the 9 elements of fMatrix |
3961/// | `fMatrix[][]` | the 9 elements of fMatrix |
3962/// | `fMatrix[2][2]` | only the elements fMatrix[2][2] |
3963/// | `fMatrix[1]` | the 3 elements fMatrix[1][0], fMatrix[1][1] and fMatrix[1][2] |
3964/// | `fMatrix[1][]` | the 3 elements fMatrix[1][0], fMatrix[1][1] and fMatrix[1][2] |
3965/// | `fMatrix[][0]` | the 3 elements fMatrix[0][0], fMatrix[1][0] and fMatrix[2][0] |
3966///
3967/// "fEvent.fMatrix...." same as "fMatrix..." (unless there is more than one leaf named fMatrix!).
3968///
3969/// In summary, if a specific index is not specified for a dimension, TTree::Draw
3970/// will loop through all the indices along this dimension. Leaving off the
3971/// last (right most) dimension of specifying then with the two characters '[]'
3972/// is equivalent. For variable size arrays (and TClonesArray) the range
3973/// of the first dimension is recalculated for each entry of the tree.
3974/// You can also specify the index as an expression of any other variables from the
3975/// tree.
3976///
3977/// TTree::Draw also now properly handling operations involving 2 or more arrays.
3978///
3979/// Let assume a second matrix fResults[5][2], here are a sample of some
3980/// of the possible combinations, the number of elements they produce and
3981/// the loop used:
3982///
3983/// | expression | element(s) | Loop |
3984/// |----------------------------------|------------|--------------------------|
3985/// | `fMatrix[2][1] - fResults[5][2]` | one | no loop |
3986/// | `fMatrix[2][] - fResults[5][2]` | three | on 2nd dim fMatrix |
3987/// | `fMatrix[2][] - fResults[5][]` | two | on both 2nd dimensions |
3988/// | `fMatrix[][2] - fResults[][1]` | three | on both 1st dimensions |
3989/// | `fMatrix[][2] - fResults[][]` | six | on both 1st and 2nd dimensions of fResults |
3990/// | `fMatrix[][2] - fResults[3][]` | two | on 1st dim of fMatrix and 2nd of fResults (at the same time) |
3991/// | `fMatrix[][] - fResults[][]` | six | on 1st dim then on 2nd dim |
3992/// | `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.|
3993///
3994///
3995/// In summary, TTree::Draw loops through all unspecified dimensions. To
3996/// figure out the range of each loop, we match each unspecified dimension
3997/// from left to right (ignoring ALL dimensions for which an index has been
3998/// specified), in the equivalent loop matched dimensions use the same index
3999/// and are restricted to the smallest range (of only the matched dimensions).
4000/// When involving variable arrays, the range can of course be different
4001/// for each entry of the tree.
4002///
4003/// So the loop equivalent to "fMatrix[][2] - fResults[3][]" is:
4004/// ~~~ {.cpp}
4005/// for (Int_t i0; i < min(3,2); i++) {
4006/// use the value of (fMatrix[i0][2] - fMatrix[3][i0])
4007/// }
4008/// ~~~
4009/// So the loop equivalent to "fMatrix[][2] - fResults[][]" is:
4010/// ~~~ {.cpp}
4011/// for (Int_t i0; i < min(3,5); i++) {
4012/// for (Int_t i1; i1 < 2; i1++) {
4013/// use the value of (fMatrix[i0][2] - fMatrix[i0][i1])
4014/// }
4015/// }
4016/// ~~~
4017/// So the loop equivalent to "fMatrix[][] - fResults[][]" is:
4018/// ~~~ {.cpp}
4019/// for (Int_t i0; i < min(3,5); i++) {
4020/// for (Int_t i1; i1 < min(3,2); i1++) {
4021/// use the value of (fMatrix[i0][i1] - fMatrix[i0][i1])
4022/// }
4023/// }
4024/// ~~~
4025/// So the loop equivalent to "fMatrix[][fResults[][]]" is:
4026/// ~~~ {.cpp}
4027/// for (Int_t i0; i0 < 3; i0++) {
4028/// for (Int_t j2; j2 < 5; j2++) {
4029/// for (Int_t j3; j3 < 2; j3++) {
4030/// i1 = fResults[j2][j3];
4031/// use the value of fMatrix[i0][i1]
4032/// }
4033/// }
4034/// ~~~
4035/// ### Retrieving the result of Draw
4036///
4037/// By default a temporary histogram called `htemp` is created. It will be:
4038///
4039/// - A TH1F* in case of a mono-dimensional distribution: `Draw("e1")`,
4040/// - A TH2F* in case of a bi-dimensional distribution: `Draw("e1:e2")`,
4041/// - A TH3F* in case of a three-dimensional distribution: `Draw("e1:e2:e3")`.
4042///
4043/// In the one dimensional case the `htemp` is filled and drawn whatever the drawing
4044/// option is.
4045///
4046/// In the two and three dimensional cases, with the default drawing option (`""`),
4047/// a cloud of points is drawn and the histogram `htemp` is not filled. For all the other
4048/// drawing options `htemp` will be filled.
4049///
4050/// In all cases `htemp` can be retrieved by calling:
4051///
4052/// ~~~ {.cpp}
4053/// auto htemp = (TH1F*)gPad->GetPrimitive("htemp"); // 1D
4054/// auto htemp = (TH2F*)gPad->GetPrimitive("htemp"); // 2D
4055/// auto htemp = (TH3F*)gPad->GetPrimitive("htemp"); // 3D
4056/// ~~~
4057///
4058/// In the two dimensional case (`Draw("e1;e2")`), with the default drawing option, the
4059/// data is filled into a TGraph named `Graph`. This TGraph can be retrieved by
4060/// calling
4061///
4062/// ~~~ {.cpp}
4063/// auto graph = (TGraph*)gPad->GetPrimitive("Graph");
4064/// ~~~
4065///
4066/// For the three and four dimensional cases, with the default drawing option, an unnamed
4067/// TPolyMarker3D is produced, and therefore cannot be retrieved.
4068///
4069/// In all cases `htemp` can be used to access the axes. For instance in the 2D case:
4070///
4071/// ~~~ {.cpp}
4072/// auto htemp = (TH2F*)gPad->GetPrimitive("htemp");
4073/// auto xaxis = htemp->GetXaxis();
4074/// ~~~
4075///
4076/// When the option `"A"` is used (with TGraph painting option) to draw a 2D
4077/// distribution:
4078/// ~~~ {.cpp}
4079/// tree.Draw("e1:e2","","A*");
4080/// ~~~
4081/// a scatter plot is produced (with stars in that case) but the axis creation is
4082/// delegated to TGraph and `htemp` is not created.
4083///
4084/// ### Saving the result of Draw to a histogram
4085///
4086/// If `varexp` contains `>>hnew` (following the variable(s) name(s)),
4087/// the new histogram called `hnew` is created and it is kept in the current
4088/// directory (and also the current pad). This works for all dimensions.
4089///
4090/// Example:
4091/// ~~~ {.cpp}
4092/// tree.Draw("sqrt(x)>>hsqrt","y>0")
4093/// ~~~
4094/// will draw `sqrt(x)` and save the histogram as "hsqrt" in the current
4095/// directory. To retrieve it do:
4096/// ~~~ {.cpp}
4097/// TH1F *hsqrt = (TH1F*)gDirectory->Get("hsqrt");
4098/// ~~~
4099/// The binning information is taken from the environment variables
4100/// ~~~ {.cpp}
4101/// Hist.Binning.?D.?
4102/// ~~~
4103/// In addition, the name of the histogram can be followed by up to 9
4104/// numbers between '(' and ')', where the numbers describe the
4105/// following:
4106///
4107/// - 1 - bins in x-direction
4108/// - 2 - lower limit in x-direction
4109/// - 3 - upper limit in x-direction
4110/// - 4-6 same for y-direction
4111/// - 7-9 same for z-direction
4112///
4113/// When a new binning is used the new value will become the default.
4114/// Values can be skipped.
4115///
4116/// Example:
4117/// ~~~ {.cpp}
4118/// tree.Draw("sqrt(x)>>hsqrt(500,10,20)")
4119/// // plot sqrt(x) between 10 and 20 using 500 bins
4120/// tree.Draw("sqrt(x):sin(y)>>hsqrt(100,10,60,50,.1,.5)")
4121/// // plot sqrt(x) against sin(y)
4122/// // 100 bins in x-direction; lower limit on x-axis is 10; upper limit is 60
4123/// // 50 bins in y-direction; lower limit on y-axis is .1; upper limit is .5
4124/// ~~~
4125/// By default, the specified histogram is reset.
4126/// To continue to append data to an existing histogram, use "+" in front
4127/// of the histogram name.
4128///
4129/// A '+' in front of the histogram name is ignored, when the name is followed by
4130/// binning information as described in the previous paragraph.
4131/// ~~~ {.cpp}
4132/// tree.Draw("sqrt(x)>>+hsqrt","y>0")
4133/// ~~~
4134/// will not reset `hsqrt`, but will continue filling. This works for 1-D, 2-D
4135/// and 3-D histograms.
4136///
4137/// ### Accessing collection objects
4138///
4139/// TTree::Draw default's handling of collections is to assume that any
4140/// request on a collection pertain to it content. For example, if fTracks
4141/// is a collection of Track objects, the following:
4142/// ~~~ {.cpp}
4143/// tree->Draw("event.fTracks.fPx");
4144/// ~~~
4145/// will plot the value of fPx for each Track objects inside the collection.
4146/// Also
4147/// ~~~ {.cpp}
4148/// tree->Draw("event.fTracks.size()");
4149/// ~~~
4150/// would plot the result of the member function Track::size() for each
4151/// Track object inside the collection.
4152/// To access information about the collection itself, TTree::Draw support
4153/// the '@' notation. If a variable which points to a collection is prefixed
4154/// or postfixed with '@', the next part of the expression will pertain to
4155/// the collection object. For example:
4156/// ~~~ {.cpp}
4157/// tree->Draw("event.@fTracks.size()");
4158/// ~~~
4159/// will plot the size of the collection referred to by `fTracks` (i.e the number
4160/// of Track objects).
4161///
4162/// ### Drawing 'objects'
4163///
4164/// When a class has a member function named AsDouble or AsString, requesting
4165/// to directly draw the object will imply a call to one of the 2 functions.
4166/// If both AsDouble and AsString are present, AsDouble will be used.
4167/// AsString can return either a char*, a std::string or a TString.s
4168/// For example, the following
4169/// ~~~ {.cpp}
4170/// tree->Draw("event.myTTimeStamp");
4171/// ~~~
4172/// will draw the same histogram as
4173/// ~~~ {.cpp}
4174/// tree->Draw("event.myTTimeStamp.AsDouble()");
4175/// ~~~
4176/// In addition, when the object is a type TString or std::string, TTree::Draw
4177/// will call respectively `TString::Data` and `std::string::c_str()`
4178///
4179/// If the object is a TBits, the histogram will contain the index of the bit
4180/// that are turned on.
4181///
4182/// ### Retrieving information about the tree itself.
4183///
4184/// You can refer to the tree (or chain) containing the data by using the
4185/// string 'This'.
4186/// You can then could any TTree methods. For example:
4187/// ~~~ {.cpp}
4188/// tree->Draw("This->GetReadEntry()");
4189/// ~~~
4190/// will display the local entry numbers be read.
4191/// ~~~ {.cpp}
4192/// tree->Draw("This->GetUserInfo()->At(0)->GetName()");
4193/// ~~~
4194/// will display the name of the first 'user info' object.
4195///
4196/// ### Special functions and variables
4197///
4198/// `Entry$`: A TTree::Draw formula can use the special variable `Entry$`
4199/// to access the entry number being read. For example to draw every
4200/// other entry use:
4201/// ~~~ {.cpp}
4202/// tree.Draw("myvar","Entry$%2==0");
4203/// ~~~
4204/// - `Entry$` : return the current entry number (`== TTree::GetReadEntry()`)
4205/// - `LocalEntry$` : return the current entry number in the current tree of a
4206/// chain (`== GetTree()->GetReadEntry()`)
4207/// - `Entries$` : return the total number of entries (== TTree::GetEntries())
4208/// - `LocalEntries$` : return the total number of entries in the current tree
4209/// of a chain (== GetTree()->TTree::GetEntries())
4210/// - `Length$` : return the total number of element of this formula for this
4211/// entry (`==TTreeFormula::GetNdata()`)
4212/// - `Iteration$` : return the current iteration over this formula for this
4213/// entry (i.e. varies from 0 to `Length$`).
4214/// - `Length$(formula )` : return the total number of element of the formula
4215/// given as a parameter.
4216/// - `Sum$(formula )` : return the sum of the value of the elements of the
4217/// formula given as a parameter. For example the mean for all the elements in
4218/// one entry can be calculated with: `Sum$(formula )/Length$(formula )`
4219/// - `Min$(formula )` : return the minimum (within one TTree entry) of the value of the
4220/// elements of the formula given as a parameter.
4221/// - `Max$(formula )` : return the maximum (within one TTree entry) of the value of the
4222/// elements of the formula given as a parameter.
4223/// - `MinIf$(formula,condition)`
4224/// - `MaxIf$(formula,condition)` : return the minimum (maximum) (within one TTree entry)
4225/// of the value of the elements of the formula given as a parameter
4226/// if they match the condition. If no element matches the condition,
4227/// the result is zero. To avoid the resulting peak at zero, use the
4228/// pattern:
4229/// ~~~ {.cpp}
4230/// tree->Draw("MinIf$(formula,condition)","condition");
4231/// ~~~
4232/// which will avoid calculation `MinIf$` for the entries that have no match
4233/// for the condition.
4234/// - `Alt$(primary,alternate)` : return the value of "primary" if it is available
4235/// for the current iteration otherwise return the value of "alternate".
4236/// For example, with arr1[3] and arr2[2]
4237/// ~~~ {.cpp}
4238/// tree->Draw("arr1+Alt$(arr2,0)");
4239/// ~~~
4240/// will draw arr1[0]+arr2[0] ; arr1[1]+arr2[1] and arr1[2]+0
4241/// Or with a variable size array arr3
4242/// ~~~ {.cpp}
4243/// tree->Draw("Alt$(arr3[0],0)+Alt$(arr3[1],0)+Alt$(arr3[2],0)");
4244/// ~~~
4245/// will draw the sum arr3 for the index 0 to min(2,actual_size_of_arr3-1)
4246/// As a comparison
4247/// ~~~ {.cpp}
4248/// tree->Draw("arr3[0]+arr3[1]+arr3[2]");
4249/// ~~~
4250/// will draw the sum arr3 for the index 0 to 2 only if the
4251/// actual_size_of_arr3 is greater or equal to 3.
4252/// Note that the array in 'primary' is flattened/linearized thus using
4253/// `Alt$` with multi-dimensional arrays of different dimensions in unlikely
4254/// to yield the expected results. To visualize a bit more what elements
4255/// would be matched by TTree::Draw, TTree::Scan can be used:
4256/// ~~~ {.cpp}
4257/// tree->Scan("arr1:Alt$(arr2,0)");
4258/// ~~~
4259/// will print on one line the value of arr1 and (arr2,0) that will be
4260/// matched by
4261/// ~~~ {.cpp}
4262/// tree->Draw("arr1-Alt$(arr2,0)");
4263/// ~~~
4264/// The ternary operator is not directly supported in TTree::Draw however, to plot the
4265/// equivalent of `var2<20 ? -99 : var1`, you can use:
4266/// ~~~ {.cpp}
4267/// tree->Draw("(var2<20)*99+(var2>=20)*var1","");
4268/// ~~~
4269///
4270/// ### Drawing a user function accessing the TTree data directly
4271///
4272/// If the formula contains a file name, TTree::MakeProxy will be used
4273/// to load and execute this file. In particular it will draw the
4274/// result of a function with the same name as the file. The function
4275/// will be executed in a context where the name of the branches can
4276/// be used as a C++ variable.
4277///
4278/// For example draw px using the file hsimple.root (generated by the
4279/// hsimple.C tutorial), we need a file named hsimple.cxx:
4280/// ~~~ {.cpp}
4281/// double hsimple() {
4282/// return px;
4283/// }
4284/// ~~~
4285/// MakeProxy can then be used indirectly via the TTree::Draw interface
4286/// as follow:
4287/// ~~~ {.cpp}
4288/// new TFile("hsimple.root")
4289/// ntuple->Draw("hsimple.cxx");
4290/// ~~~
4291/// A more complete example is available in the tutorials directory:
4292/// `h1analysisProxy.cxx`, `h1analysProxy.h` and `h1analysisProxyCut.C`
4293/// which reimplement the selector found in `h1analysis.C`
4294///
4295/// The main features of this facility are:
4296///
4297/// * on-demand loading of branches
4298/// * ability to use the 'branchname' as if it was a data member
4299/// * protection against array out-of-bound
4300/// * ability to use the branch data as object (when the user code is available)
4301///
4302/// See TTree::MakeProxy for more details.
4303///
4304/// ### Making a Profile histogram
4305///
4306/// In case of a 2-Dim expression, one can generate a TProfile histogram
4307/// instead of a TH2F histogram by specifying option=prof or option=profs
4308/// or option=profi or option=profg ; the trailing letter select the way
4309/// the bin error are computed, See TProfile2D::SetErrorOption for
4310/// details on the differences.
4311/// The option=prof is automatically selected in case of y:x>>pf
4312/// where pf is an existing TProfile histogram.
4313///
4314/// ### Making a 2D Profile histogram
4315///
4316/// In case of a 3-Dim expression, one can generate a TProfile2D histogram
4317/// instead of a TH3F histogram by specifying option=prof or option=profs.
4318/// or option=profi or option=profg ; the trailing letter select the way
4319/// the bin error are computed, See TProfile2D::SetErrorOption for
4320/// details on the differences.
4321/// The option=prof is automatically selected in case of z:y:x>>pf
4322/// where pf is an existing TProfile2D histogram.
4323///
4324/// ### Making a 5D plot using GL
4325///
4326/// If option GL5D is specified together with 5 variables, a 5D plot is drawn
4327/// using OpenGL. See $ROOTSYS/tutorials/tree/staff.C as example.
4328///
4329/// ### Making a parallel coordinates plot
4330///
4331/// In case of a 2-Dim or more expression with the option=para, one can generate
4332/// a parallel coordinates plot. With that option, the number of dimensions is
4333/// arbitrary. Giving more than 4 variables without the option=para or
4334/// option=candle or option=goff will produce an error.
4335///
4336/// ### Making a candle sticks chart
4337///
4338/// In case of a 2-Dim or more expression with the option=candle, one can generate
4339/// a candle sticks chart. With that option, the number of dimensions is
4340/// arbitrary. Giving more than 4 variables without the option=para or
4341/// option=candle or option=goff will produce an error.
4342///
4343/// ### Normalizing the output histogram to 1
4344///
4345/// When option contains "norm" the output histogram is normalized to 1.
4346///
4347/// ### Saving the result of Draw to a TEventList, a TEntryList or a TEntryListArray
4348///
4349/// TTree::Draw can be used to fill a TEventList object (list of entry numbers)
4350/// instead of histogramming one variable.
4351/// If varexp0 has the form >>elist , a TEventList object named "elist"
4352/// is created in the current directory. elist will contain the list
4353/// of entry numbers satisfying the current selection.
4354/// If option "entrylist" is used, a TEntryList object is created
4355/// If the selection contains arrays, vectors or any container class and option
4356/// "entrylistarray" is used, a TEntryListArray object is created
4357/// containing also the subentries satisfying the selection, i.e. the indices of
4358/// the branches which hold containers classes.
4359/// Example:
4360/// ~~~ {.cpp}
4361/// tree.Draw(">>yplus","y>0")
4362/// ~~~
4363/// will create a TEventList object named "yplus" in the current directory.
4364/// In an interactive session, one can type (after TTree::Draw)
4365/// ~~~ {.cpp}
4366/// yplus.Print("all")
4367/// ~~~
4368/// to print the list of entry numbers in the list.
4369/// ~~~ {.cpp}
4370/// tree.Draw(">>yplus", "y>0", "entrylist")
4371/// ~~~
4372/// will create a TEntryList object names "yplus" in the current directory
4373/// ~~~ {.cpp}
4374/// tree.Draw(">>yplus", "y>0", "entrylistarray")
4375/// ~~~
4376/// will create a TEntryListArray object names "yplus" in the current directory
4377///
4378/// By default, the specified entry list is reset.
4379/// To continue to append data to an existing list, use "+" in front
4380/// of the list name;
4381/// ~~~ {.cpp}
4382/// tree.Draw(">>+yplus","y>0")
4383/// ~~~
4384/// will not reset yplus, but will enter the selected entries at the end
4385/// of the existing list.
4386///
4387/// ### Using a TEventList, TEntryList or TEntryListArray as Input
4388///
4389/// Once a TEventList or a TEntryList object has been generated, it can be used as input
4390/// for TTree::Draw. Use TTree::SetEventList or TTree::SetEntryList to set the
4391/// current event list
4392///
4393/// Example 1:
4394/// ~~~ {.cpp}
4395/// TEventList *elist = (TEventList*)gDirectory->Get("yplus");
4396/// tree->SetEventList(elist);
4397/// tree->Draw("py");
4398/// ~~~
4399/// Example 2:
4400/// ~~~ {.cpp}
4401/// TEntryList *elist = (TEntryList*)gDirectory->Get("yplus");
4402/// tree->SetEntryList(elist);
4403/// tree->Draw("py");
4404/// ~~~
4405/// If a TEventList object is used as input, a new TEntryList object is created
4406/// inside the SetEventList function. In case of a TChain, all tree headers are loaded
4407/// for this transformation. This new object is owned by the chain and is deleted
4408/// with it, unless the user extracts it by calling GetEntryList() function.
4409/// See also comments to SetEventList() function of TTree and TChain.
4410///
4411/// If arrays are used in the selection criteria and TEntryListArray is not used,
4412/// all the entries that have at least one element of the array that satisfy the selection
4413/// are entered in the list.
4414///
4415/// Example:
4416/// ~~~ {.cpp}
4417/// tree.Draw(">>pyplus","fTracks.fPy>0");
4418/// tree->SetEventList(pyplus);
4419/// tree->Draw("fTracks.fPy");
4420/// ~~~
4421/// will draw the fPy of ALL tracks in event with at least one track with
4422/// a positive fPy.
4423///
4424/// To select only the elements that did match the original selection
4425/// use TEventList::SetReapplyCut or TEntryList::SetReapplyCut.
4426///
4427/// Example:
4428/// ~~~ {.cpp}
4429/// tree.Draw(">>pyplus","fTracks.fPy>0");
4430/// pyplus->SetReapplyCut(true);
4431/// tree->SetEventList(pyplus);
4432/// tree->Draw("fTracks.fPy");
4433/// ~~~
4434/// will draw the fPy of only the tracks that have a positive fPy.
4435///
4436/// To draw only the elements that match a selection in case of arrays,
4437/// you can also use TEntryListArray (faster in case of a more general selection).
4438///
4439/// Example:
4440/// ~~~ {.cpp}
4441/// tree.Draw(">>pyplus","fTracks.fPy>0", "entrylistarray");
4442/// tree->SetEntryList(pyplus);
4443/// tree->Draw("fTracks.fPy");
4444/// ~~~
4445/// will draw the fPy of only the tracks that have a positive fPy,
4446/// but without redoing the selection.
4447///
4448/// Note: Use tree->SetEventList(0) if you do not want use the list as input.
4449///
4450/// ### How to obtain more info from TTree::Draw
4451///
4452/// Once TTree::Draw has been called, it is possible to access useful
4453/// information still stored in the TTree object via the following functions:
4454///
4455/// - GetSelectedRows() // return the number of values accepted by the selection expression. In case where no selection was specified, returns the number of values processed.
4456/// - GetV1() // returns a pointer to the double array of V1
4457/// - GetV2() // returns a pointer to the double array of V2
4458/// - GetV3() // returns a pointer to the double array of V3
4459/// - GetV4() // returns a pointer to the double array of V4
4460/// - GetW() // returns a pointer to the double array of Weights where weight equal the result of the selection expression.
4461///
4462/// where V1,V2,V3 correspond to the expressions in
4463/// ~~~ {.cpp}
4464/// TTree::Draw("V1:V2:V3:V4",selection);
4465/// ~~~
4466/// If the expression has more than 4 component use GetVal(index)
4467///
4468/// Example:
4469/// ~~~ {.cpp}
4470/// Root > ntuple->Draw("py:px","pz>4");
4471/// Root > TGraph *gr = new TGraph(ntuple->GetSelectedRows(),
4472/// ntuple->GetV2(), ntuple->GetV1());
4473/// Root > gr->Draw("ap"); //draw graph in current pad
4474/// ~~~
4475///
4476/// A more complete complete tutorial (treegetval.C) shows how to use the
4477/// GetVal() method.
4478///
4479/// creates a TGraph object with a number of points corresponding to the
4480/// number of entries selected by the expression "pz>4", the x points of the graph
4481/// being the px values of the Tree and the y points the py values.
4482///
4483/// Important note: By default TTree::Draw creates the arrays obtained
4484/// with GetW, GetV1, GetV2, GetV3, GetV4, GetVal with a length corresponding
4485/// to the parameter fEstimate. The content will be the last `GetSelectedRows() % GetEstimate()`
4486/// values calculated.
4487/// By default fEstimate=1000000 and can be modified
4488/// via TTree::SetEstimate. To keep in memory all the results (in case
4489/// where there is only one result per entry), use
4490/// ~~~ {.cpp}
4491/// tree->SetEstimate(tree->GetEntries()+1); // same as tree->SetEstimate(-1);
4492/// ~~~
4493/// You must call SetEstimate if the expected number of selected rows
4494/// you need to look at is greater than 1000000.
4495///
4496/// You can use the option "goff" to turn off the graphics output
4497/// of TTree::Draw in the above example.
4498///
4499/// ### Automatic interface to TTree::Draw via the TTreeViewer
4500///
4501/// A complete graphical interface to this function is implemented
4502/// in the class TTreeViewer.
4503/// To start the TTreeViewer, three possibilities:
4504/// - select TTree context menu item "StartViewer"
4505/// - type the command "TTreeViewer TV(treeName)"
4506/// - execute statement "tree->StartViewer();"
4508Long64_t TTree::Draw(const char* varexp, const char* selection, Option_t* option, Long64_t nentries, Long64_t firstentry)
4509{
4510 GetPlayer();
4511 if (fPlayer)
4512 return fPlayer->DrawSelect(varexp,selection,option,nentries,firstentry);
4513 return -1;
4514}
4515
4516////////////////////////////////////////////////////////////////////////////////
4517/// Remove some baskets from memory.
4519void TTree::DropBaskets()
4520{
4521 TBranch* branch = nullptr;
4523 for (Int_t i = 0; i < nb; ++i) {
4524 branch = (TBranch*) fBranches.UncheckedAt(i);
4525 branch->DropBaskets("all");
4526 }
4527}
4528
4529////////////////////////////////////////////////////////////////////////////////
4530/// Drop branch buffers to accommodate nbytes below MaxVirtualsize.
4533{
4534 // Be careful not to remove current read/write buffers.
4535 Int_t nleaves = fLeaves.GetEntriesFast();
4536 for (Int_t i = 0; i < nleaves; ++i) {
4537 TLeaf* leaf = (TLeaf*) fLeaves.UncheckedAt(i);
4538 TBranch* branch = (TBranch*) leaf->GetBranch();
4539 Int_t nbaskets = branch->GetListOfBaskets()->GetEntries();
4540 for (Int_t j = 0; j < nbaskets - 1; ++j) {
4541 if ((j == branch->GetReadBasket()) || (j == branch->GetWriteBasket())) {
4542 continue;
4543 }
4544 TBasket* basket = (TBasket*)branch->GetListOfBaskets()->UncheckedAt(j);
4545 if (basket) {
4546 basket->DropBuffers();
4548 return;
4549 }
4550 }
4551 }
4552 }
4553}
4554
4555////////////////////////////////////////////////////////////////////////////////
4556/// Fill all branches.
4557///
4558/// This function loops on all the branches of this tree. For
4559/// each branch, it copies to the branch buffer (basket) the current
4560/// values of the leaves data types. If a leaf is a simple data type,
4561/// a simple conversion to a machine independent format has to be done.
4562///
4563/// This machine independent version of the data is copied into a
4564/// basket (each branch has its own basket). When a basket is full
4565/// (32k worth of data by default), it is then optionally compressed
4566/// and written to disk (this operation is also called committing or
4567/// 'flushing' the basket). The committed baskets are then
4568/// immediately removed from memory.
4569///
4570/// The function returns the number of bytes committed to the
4571/// individual branches.
4572///
4573/// If a write error occurs, the number of bytes returned is -1.
4574///
4575/// If no data are written, because, e.g., the branch is disabled,
4576/// the number of bytes returned is 0.
4577///
4578/// __The baskets are flushed and the Tree header saved at regular intervals__
4579///
4580/// At regular intervals, when the amount of data written so far is
4581/// greater than fAutoFlush (see SetAutoFlush) all the baskets are flushed to disk.
4582/// This makes future reading faster as it guarantees that baskets belonging to nearby
4583/// entries will be on the same disk region.
4584/// When the first call to flush the baskets happen, we also take this opportunity
4585/// to optimize the baskets buffers.
4586/// We also check if the amount of data written is greater than fAutoSave (see SetAutoSave).
4587/// In this case we also write the Tree header. This makes the Tree recoverable up to this point
4588/// in case the program writing the Tree crashes.
4589/// The decisions to FlushBaskets and Auto Save can be made based either on the number
4590/// of bytes written (fAutoFlush and fAutoSave negative) or on the number of entries
4591/// written (fAutoFlush and fAutoSave positive).
4592/// Note that the user can decide to call FlushBaskets and AutoSave in her event loop
4593/// base on the number of events written instead of the number of bytes written.
4594///
4595/// \note Calling `TTree::FlushBaskets` too often increases the IO time.
4596///
4597/// \note Calling `TTree::AutoSave` too often increases the IO time and also the
4598/// file size.
4599///
4600/// \note This method calls `TTree::ChangeFile` when the tree reaches a size
4601/// greater than `TTree::fgMaxTreeSize`. This doesn't happen if the tree is
4602/// attached to a `TMemFile` or derivate.
4605{
4606 Int_t nbytes = 0;
4607 Int_t nwrite = 0;
4608 Int_t nerror = 0;
4609 Int_t nbranches = fBranches.GetEntriesFast();
4610
4611 // Case of one single super branch. Automatically update
4612 // all the branch addresses if a new object was created.
4613 if (nbranches == 1)
4614 ((TBranch *)fBranches.UncheckedAt(0))->UpdateAddress();
4615
4616 if (fBranchRef)
4617 fBranchRef->Clear();
4618
4619#ifdef R__USE_IMT
4620 const auto useIMT = ROOT::IsImplicitMTEnabled() && fIMTEnabled;
4622 if (useIMT) {
4623 fIMTFlush = true;
4624 fIMTZipBytes.store(0);
4625 fIMTTotBytes.store(0);
4626 }
4627#endif
4628
4629 for (Int_t i = 0; i < nbranches; ++i) {
4630 // Loop over all branches, filling and accumulating bytes written and error counts.
4631 TBranch *branch = (TBranch *)fBranches.UncheckedAt(i);
4632
4633 if (branch->TestBit(kDoNotProcess))
4634 continue;
4635
4636#ifndef R__USE_IMT
4637 nwrite = branch->FillImpl(nullptr);
4638#else
4639 nwrite = branch->FillImpl(useIMT ? &imtHelper : nullptr);
4640#endif
4641 if (nwrite < 0) {
4642 if (nerror < 2) {
4643 Error("Fill", "Failed filling branch:%s.%s, nbytes=%d, entry=%lld\n"
4644 " This error is symptomatic of a Tree created as a memory-resident Tree\n"
4645 " Instead of doing:\n"
4646 " TTree *T = new TTree(...)\n"
4647 " TFile *f = new TFile(...)\n"
4648 " you should do:\n"
4649 " TFile *f = new TFile(...)\n"
4650 " TTree *T = new TTree(...)\n\n",
4651 GetName(), branch->GetName(), nwrite, fEntries + 1);
4652 } else {
4653 Error("Fill", "Failed filling branch:%s.%s, nbytes=%d, entry=%lld", GetName(), branch->GetName(), nwrite,
4654 fEntries + 1);
4655 }
4656 ++nerror;
4657 } else {
4658 nbytes += nwrite;
4659 }
4660 }
4661
4662#ifdef R__USE_IMT
4663 if (fIMTFlush) {
4664 imtHelper.Wait();
4665 fIMTFlush = false;
4666 const_cast<TTree *>(this)->AddTotBytes(fIMTTotBytes);
4667 const_cast<TTree *>(this)->AddZipBytes(fIMTZipBytes);
4668 nbytes += imtHelper.GetNbytes();
4669 nerror += imtHelper.GetNerrors();
4670 }
4671#endif
4672
4673 if (fBranchRef)
4674 fBranchRef->Fill();
4675
4676 ++fEntries;
4677
4678 if (fEntries > fMaxEntries)
4679 KeepCircular();
4680
4681 if (gDebug > 0)
4682 Info("TTree::Fill", " - A: %d %lld %lld %lld %lld %lld %lld \n", nbytes, fEntries, fAutoFlush, fAutoSave,
4684
4685 bool autoFlush = false;
4686 bool autoSave = false;
4687
4688 if (fAutoFlush != 0 || fAutoSave != 0) {
4689 // Is it time to flush or autosave baskets?
4690 if (fFlushedBytes == 0) {
4691 // If fFlushedBytes == 0, it means we never flushed or saved, so
4692 // we need to check if it's time to do it and recompute the values
4693 // of fAutoFlush and fAutoSave in terms of the number of entries.
4694 // Decision can be based initially either on the number of bytes
4695 // or the number of entries written.
4696 Long64_t zipBytes = GetZipBytes();
4697
4698 if (fAutoFlush)
4699 autoFlush = fAutoFlush < 0 ? (zipBytes > -fAutoFlush) : fEntries % fAutoFlush == 0;
4700
4701 if (fAutoSave)
4702 autoSave = fAutoSave < 0 ? (zipBytes > -fAutoSave) : fEntries % fAutoSave == 0;
4703
4704 if (autoFlush || autoSave) {
4705 // First call FlushBasket to make sure that fTotBytes is up to date.
4707 autoFlush = false; // avoid auto flushing again later
4708
4709 // When we are in one-basket-per-cluster mode, there is no need to optimize basket:
4710 // they will automatically grow to the size needed for an event cluster (with the basket
4711 // shrinking preventing them from growing too much larger than the actually-used space).
4713 OptimizeBaskets(GetTotBytes(), 1, "");
4714 if (gDebug > 0)
4715 Info("TTree::Fill", "OptimizeBaskets called at entry %lld, fZipBytes=%lld, fFlushedBytes=%lld\n",
4717 }
4719 fAutoFlush = fEntries; // Use test on entries rather than bytes
4720
4721 // subsequently in run
4722 if (fAutoSave < 0) {
4723 // Set fAutoSave to the largest integer multiple of
4724 // fAutoFlush events such that fAutoSave*fFlushedBytes
4725 // < (minus the input value of fAutoSave)
4726 Long64_t totBytes = GetTotBytes();
4727 if (zipBytes != 0) {
4728 fAutoSave = TMath::Max(fAutoFlush, fEntries * ((-fAutoSave / zipBytes) / fEntries));
4729 } else if (totBytes != 0) {
4730 fAutoSave = TMath::Max(fAutoFlush, fEntries * ((-fAutoSave / totBytes) / fEntries));
4731 } else {
4733 TTree::Class()->WriteBuffer(b, (TTree *)this);
4734 Long64_t total = b.Length();
4736 }
4737 } else if (fAutoSave > 0) {
4739 }
4740
4741 if (fAutoSave != 0 && fEntries >= fAutoSave)
4742 autoSave = true;
4743
4744 if (gDebug > 0)
4745 Info("TTree::Fill", "First AutoFlush. fAutoFlush = %lld, fAutoSave = %lld\n", fAutoFlush, fAutoSave);
4746 }
4747 } else {
4748 // Check if we need to auto flush
4749 if (fAutoFlush) {
4750 if (fNClusterRange == 0)
4751 autoFlush = fEntries > 1 && fEntries % fAutoFlush == 0;
4752 else
4753 autoFlush = (fEntries - (fClusterRangeEnd[fNClusterRange - 1] + 1)) % fAutoFlush == 0;
4754 }
4755 // Check if we need to auto save
4756 if (fAutoSave)
4757 autoSave = fEntries % fAutoSave == 0;
4758 }
4759 }
4760
4761 if (autoFlush) {
4763 if (gDebug > 0)
4764 Info("TTree::Fill", "FlushBaskets() called at entry %lld, fZipBytes=%lld, fFlushedBytes=%lld\n", fEntries,
4767 }
4768
4769 if (autoSave) {
4770 AutoSave(); // does not call FlushBasketsImpl() again
4771 if (gDebug > 0)
4772 Info("TTree::Fill", "AutoSave called at entry %lld, fZipBytes=%lld, fSavedBytes=%lld\n", fEntries,
4774 }
4775
4776 // Check that output file is still below the maximum size.
4777 // If above, close the current file and continue on a new file.
4778 // Currently, the automatic change of file is restricted
4779 // to the case where the tree is in the top level directory.
4780 if (fDirectory)
4781 if (TFile *file = fDirectory->GetFile())
4782 if (static_cast<TDirectory *>(file) == fDirectory && (file->GetEND() > fgMaxTreeSize))
4783 // Changing file clashes with the design of TMemFile and derivates, see #6523.
4784 if (!(dynamic_cast<TMemFile *>(file)))
4785 ChangeFile(file);
4786
4787 return nerror == 0 ? nbytes : -1;
4788}
4789
4790////////////////////////////////////////////////////////////////////////////////
4791/// Search in the array for a branch matching the branch name,
4792/// with the branch possibly expressed as a 'full' path name (with dots).
4794static TBranch *R__FindBranchHelper(TObjArray *list, const char *branchname) {
4795 if (list==nullptr || branchname == nullptr || branchname[0] == '\0') return nullptr;
4796
4797 Int_t nbranches = list->GetEntries();
4798
4799 UInt_t brlen = strlen(branchname);
4800
4801 for(Int_t index = 0; index < nbranches; ++index) {
4802 TBranch *where = (TBranch*)list->UncheckedAt(index);
4803
4804 const char *name = where->GetName();
4805 UInt_t len = strlen(name);
4806 if (len && name[len-1]==']') {
4807 const char *dim = strchr(name,'[');
4808 if (dim) {
4809 len = dim - name;
4810 }
4811 }
4812 if (brlen == len && strncmp(branchname,name,len)==0) {
4813 return where;
4814 }
4815 TBranch *next = nullptr;
4816 if ((brlen >= len) && (branchname[len] == '.')
4817 && strncmp(name, branchname, len) == 0) {
4818 // The prefix subbranch name match the branch name.
4819
4820 next = where->FindBranch(branchname);
4821 if (!next) {
4822 next = where->FindBranch(branchname+len+1);
4823 }
4824 if (next) return next;
4825 }
4826 const char *dot = strchr((char*)branchname,'.');
4827 if (dot) {
4828 if (len==(size_t)(dot-branchname) &&
4829 strncmp(branchname,name,dot-branchname)==0 ) {
4830 return R__FindBranchHelper(where->GetListOfBranches(),dot+1);
4831 }
4832 }
4833 }
4834 return nullptr;
4835}
4836
4837////////////////////////////////////////////////////////////////////////////////
4838/// Return the branch that correspond to the path 'branchname', which can
4839/// include the name of the tree or the omitted name of the parent branches.
4840/// In case of ambiguity, returns the first match.
4842TBranch* TTree::FindBranch(const char* branchname)
4843{
4844 // We already have been visited while recursively looking
4845 // through the friends tree, let return
4847 return nullptr;
4848 }
4849
4850 if (!branchname)
4851 return nullptr;
4852
4853 TBranch* branch = nullptr;
4854 // If the first part of the name match the TTree name, look for the right part in the
4855 // list of branches.
4856 // This will allow the branchname to be preceded by
4857 // the name of this tree.
4858 if (strncmp(fName.Data(),branchname,fName.Length())==0 && branchname[fName.Length()]=='.') {
4859 branch = R__FindBranchHelper( GetListOfBranches(), branchname + fName.Length() + 1);
4860 if (branch) return branch;
4861 }
4862 // If we did not find it, let's try to find the full name in the list of branches.
4863 branch = R__FindBranchHelper(GetListOfBranches(), branchname);
4864 if (branch) return branch;
4865
4866 // If we still did not find, let's try to find it within each branch assuming it does not the branch name.
4867 TIter next(GetListOfBranches());
4868 while ((branch = (TBranch*) next())) {
4869 TBranch* nestedbranch = branch->FindBranch(branchname);
4870 if (nestedbranch) {
4871 return nestedbranch;
4872 }
4873 }
4874
4875 // Search in list of friends.
4876 if (!fFriends) {
4877 return nullptr;
4878 }
4879 TFriendLock lock(this, kFindBranch);
4880 TIter nextf(fFriends);
4881 TFriendElement* fe = nullptr;
4882 while ((fe = (TFriendElement*) nextf())) {
4883 TTree* t = fe->GetTree();
4884 if (!t) {
4885 continue;
4886 }
4887 // If the alias is present replace it with the real name.
4888 const char *subbranch = strstr(branchname, fe->GetName());
4889 if (subbranch != branchname) {
4890 subbranch = nullptr;
4891 }
4892 if (subbranch) {
4893 subbranch += strlen(fe->GetName());
4894 if (*subbranch != '.') {
4895 subbranch = nullptr;
4896 } else {
4897 ++subbranch;
4898 }
4899 }
4900 std::ostringstream name;
4901 if (subbranch) {
4902 name << t->GetName() << "." << subbranch;
4903 } else {
4904 name << branchname;
4905 }
4906 branch = t->FindBranch(name.str().c_str());
4907 if (branch) {
4908 return branch;
4909 }
4910 }
4911 return nullptr;
4912}
4913
4914////////////////////////////////////////////////////////////////////////////////
4915/// Find leaf..
4917TLeaf* TTree::FindLeaf(const char* searchname)
4918{
4919 if (!searchname)
4920 return nullptr;
4921
4922 // We already have been visited while recursively looking
4923 // through the friends tree, let's return.
4925 return nullptr;
4926 }
4927
4928 // This will allow the branchname to be preceded by
4929 // the name of this tree.
4930 const char* subsearchname = strstr(searchname, GetName());
4931 if (subsearchname != searchname) {
4932 subsearchname = nullptr;
4933 }
4934 if (subsearchname) {
4935 subsearchname += strlen(GetName());
4936 if (*subsearchname != '.') {
4937 subsearchname = nullptr;
4938 } else {
4939 ++subsearchname;
4940 if (subsearchname[0] == 0) {
4941 subsearchname = nullptr;
4942 }
4943 }
4944 }
4945
4946 TString leafname;
4947 TString leaftitle;
4948 TString longname;
4949 TString longtitle;
4950
4951 const bool searchnameHasDot = strchr(searchname, '.') != nullptr;
4952
4953 // For leaves we allow for one level up to be prefixed to the name.
4954 TIter next(GetListOfLeaves());
4955 TLeaf* leaf = nullptr;
4956 while ((leaf = (TLeaf*) next())) {
4957 leafname = leaf->GetName();
4958 Ssiz_t dim = leafname.First('[');
4959 if (dim >= 0) leafname.Remove(dim);
4960
4961 if (leafname == searchname) {
4962 return leaf;
4963 }
4964 if (subsearchname && leafname == subsearchname) {
4965 return leaf;
4966 }
4967 // The TLeafElement contains the branch name
4968 // in its name, let's use the title.
4969 leaftitle = leaf->GetTitle();
4970 dim = leaftitle.First('[');
4971 if (dim >= 0) leaftitle.Remove(dim);
4972
4973 if (leaftitle == searchname) {
4974 return leaf;
4975 }
4976 if (subsearchname && leaftitle == subsearchname) {
4977 return leaf;
4978 }
4979 if (!searchnameHasDot)
4980 continue;
4981 TBranch* branch = leaf->GetBranch();
4982 if (branch) {
4983 longname.Form("%s.%s",branch->GetName(),leafname.Data());
4984 dim = longname.First('[');
4985 if (dim>=0) longname.Remove(dim);
4986 if (longname == searchname) {
4987 return leaf;
4988 }
4989 if (subsearchname && longname == subsearchname) {
4990 return leaf;
4991 }
4992 longtitle.Form("%s.%s",branch->GetName(),leaftitle.Data());
4993 dim = longtitle.First('[');
4994 if (dim>=0) longtitle.Remove(dim);
4995 if (longtitle == searchname) {
4996 return leaf;
4997 }
4998 if (subsearchname && longtitle == subsearchname) {
4999 return leaf;
5000 }
5001 // The following is for the case where the branch is only
5002 // a sub-branch. Since we do not see it through
5003 // TTree::GetListOfBranches, we need to see it indirectly.
5004 // This is the less sturdy part of this search ... it may
5005 // need refining ...
5006 if (strstr(searchname, ".") && !strcmp(searchname, branch->GetName())) {
5007 return leaf;
5008 }
5009 if (subsearchname && strstr(subsearchname, ".") && !strcmp(subsearchname, branch->GetName())) {
5010 return leaf;
5011 }
5012 }
5013 }
5014 // Search in list of friends.
5015 if (!fFriends) {
5016 return nullptr;
5017 }
5018 TFriendLock lock(this, kFindLeaf);
5019 TIter nextf(fFriends);
5020 TFriendElement* fe = nullptr;
5021 while ((fe = (TFriendElement*) nextf())) {
5022 TTree* t = fe->GetTree();
5023 if (!t) {
5024 continue;
5025 }
5026 // If the alias is present replace it with the real name.
5027 subsearchname = strstr(searchname, fe->GetName());
5028 if (subsearchname != searchname) {
5029 subsearchname = nullptr;
5030 }
5031 if (subsearchname) {
5032 subsearchname += strlen(fe->GetName());
5033 if (*subsearchname != '.') {
5034 subsearchname = nullptr;
5035 } else {
5036 ++subsearchname;
5037 }
5038 }
5039 if (subsearchname) {
5040 leafname.Form("%s.%s",t->GetName(),subsearchname);
5041 } else {
5042 leafname = searchname;
5043 }
5044 leaf = t->FindLeaf(leafname);
5045 if (leaf) {
5046 return leaf;
5047 }
5048 }
5049 return nullptr;
5050}
5051
5052////////////////////////////////////////////////////////////////////////////////
5053/// Fit a projected item(s) from a tree.
5054///
5055/// funcname is a TF1 function.
5056///
5057/// See TTree::Draw() for explanations of the other parameters.
5058///
5059/// By default the temporary histogram created is called htemp.
5060/// If varexp contains >>hnew , the new histogram created is called hnew
5061/// and it is kept in the current directory.
5062///
5063/// The function returns the number of selected entries.
5064///
5065/// Example:
5066/// ~~~ {.cpp}
5067/// tree.Fit(pol4,"sqrt(x)>>hsqrt","y>0")
5068/// ~~~
5069/// will fit sqrt(x) and save the histogram as "hsqrt" in the current
5070/// directory.
5071///
5072/// See also TTree::UnbinnedFit
5073///
5074/// ## Return status
5075///
5076/// The function returns the status of the histogram fit (see TH1::Fit)
5077/// If no entries were selected, the function returns -1;
5078/// (i.e. fitResult is null if the fit is OK)
5080Int_t TTree::Fit(const char* funcname, const char* varexp, const char* selection, Option_t* option, Option_t* goption, Long64_t nentries, Long64_t firstentry)
5081{
5082 GetPlayer();
5083 if (fPlayer) {
5084 return fPlayer->Fit(funcname, varexp, selection, option, goption, nentries, firstentry);
5085 }
5086 return -1;
5087}
5088
5089namespace {
5090struct BoolRAIIToggle {
5091 bool &m_val;
5092
5093 BoolRAIIToggle(bool &val) : m_val(val) { m_val = true; }
5094 ~BoolRAIIToggle() { m_val = false; }
5095};
5096}
5097
5098////////////////////////////////////////////////////////////////////////////////
5099/// Write to disk all the basket that have not yet been individually written and
5100/// create an event cluster boundary (by default).
5101///
5102/// If the caller wishes to flush the baskets but not create an event cluster,
5103/// then set create_cluster to false.
5104///
5105/// If ROOT has IMT-mode enabled, this will launch multiple TBB tasks in parallel
5106/// via TThreadExecutor to do this operation; one per basket compression. If the
5107/// caller utilizes TBB also, care must be taken to prevent deadlocks.
5108///
5109/// For example, let's say the caller holds mutex A and calls FlushBaskets; while
5110/// TBB is waiting for the ROOT compression tasks to complete, it may decide to
5111/// run another one of the user's tasks in this thread. If the second user task
5112/// tries to acquire A, then a deadlock will occur. The example call sequence
5113/// looks like this:
5114///
5115/// - User acquires mutex A
5116/// - User calls FlushBaskets.
5117/// - ROOT launches N tasks and calls wait.
5118/// - TBB schedules another user task, T2.
5119/// - T2 tries to acquire mutex A.
5120///
5121/// At this point, the thread will deadlock: the code may function with IMT-mode
5122/// disabled if the user assumed the legacy code never would run their own TBB
5123/// tasks.
5124///
5125/// SO: users of TBB who want to enable IMT-mode should carefully review their
5126/// locking patterns and make sure they hold no coarse-grained application
5127/// locks when they invoke ROOT.
5128///
5129/// Return the number of bytes written or -1 in case of write error.
5130Int_t TTree::FlushBaskets(bool create_cluster) const
5131{
5132 Int_t retval = FlushBasketsImpl();
5133 if (retval == -1) return retval;
5134
5135 if (create_cluster) const_cast<TTree *>(this)->MarkEventCluster();
5136 return retval;
5137}
5138
5139////////////////////////////////////////////////////////////////////////////////
5140/// Internal implementation of the FlushBaskets algorithm.
5141/// Unlike the public interface, this does NOT create an explicit event cluster
5142/// boundary; it is up to the (internal) caller to determine whether that should
5143/// done.
5144///
5145/// Otherwise, the comments for FlushBaskets applies.
5148{
5149 if (!fDirectory) return 0;
5150 Int_t nbytes = 0;
5151 Int_t nerror = 0;
5152 TObjArray *lb = const_cast<TTree*>(this)->GetListOfBranches();
5153 Int_t nb = lb->GetEntriesFast();
5154
5155#ifdef R__USE_IMT
5156 const auto useIMT = ROOT::IsImplicitMTEnabled() && fIMTEnabled;
5157 if (useIMT) {
5158 // ROOT-9668: here we need to check if the size of fSortedBranches is different from the
5159 // size of the list of branches before triggering the initialisation of the fSortedBranches
5160 // container to cover two cases:
5161 // 1. This is the first time we flush. fSortedBranches is empty and we need to fill it.
5162 // 2. We flushed at least once already but a branch has been be added to the tree since then
5163 if (fSortedBranches.size() != unsigned(nb)) { const_cast<TTree*>(this)->InitializeBranchLists(false); }
5164
5165 BoolRAIIToggle sentry(fIMTFlush);
5166 fIMTZipBytes.store(0);
5167 fIMTTotBytes.store(0);
5168 std::atomic<Int_t> nerrpar(0);
5169 std::atomic<Int_t> nbpar(0);
5170 std::atomic<Int_t> pos(0);
5171
5172 auto mapFunction = [&]() {
5173 // The branch to process is obtained when the task starts to run.
5174 // This way, since branches are sorted, we make sure that branches
5175 // leading to big tasks are processed first. If we assigned the
5176 // branch at task creation time, the scheduler would not necessarily
5177 // respect our sorting.
5178 Int_t j = pos.fetch_add(1);
5179
5180 auto branch = fSortedBranches[j].second;
5181 if (R__unlikely(!branch)) { return; }
5182
5183 if (R__unlikely(gDebug > 0)) {
5184 std::stringstream ss;
5185 ss << std::this_thread::get_id();
5186 Info("FlushBaskets", "[IMT] Thread %s", ss.str().c_str());
5187 Info("FlushBaskets", "[IMT] Running task for branch #%d: %s", j, branch->GetName());
5188 }
5189
5190 Int_t nbtask = branch->FlushBaskets();
5191
5192 if (nbtask < 0) { nerrpar++; }
5193 else { nbpar += nbtask; }
5194 };
5195
5197 pool.Foreach(mapFunction, nb);
5198
5199 fIMTFlush = false;
5200 const_cast<TTree*>(this)->AddTotBytes(fIMTTotBytes);
5201 const_cast<TTree*>(this)->AddZipBytes(fIMTZipBytes);
5202
5203 return nerrpar ? -1 : nbpar.load();
5204 }
5205#endif
5206 for (Int_t j = 0; j < nb; j++) {
5207 TBranch* branch = (TBranch*) lb->UncheckedAt(j);
5208 if (branch) {
5209 Int_t nwrite = branch->FlushBaskets();
5210 if (nwrite<0) {
5211 ++nerror;
5212 } else {
5213 nbytes += nwrite;
5214 }
5215 }
5216 }
5217 if (nerror) {
5218 return -1;
5219 } else {
5220 return nbytes;
5221 }
5222}
5223
5224////////////////////////////////////////////////////////////////////////////////
5225/// Returns the expanded value of the alias. Search in the friends if any.
5227const char* TTree::GetAlias(const char* aliasName) const
5228{
5229 // We already have been visited while recursively looking
5230 // through the friends tree, let's return.
5232 return nullptr;
5233 }
5234 if (fAliases) {
5235 TObject* alias = fAliases->FindObject(aliasName);
5236 if (alias) {
5237 return alias->GetTitle();
5238 }
5239 }
5240 if (!fFriends) {
5241 return nullptr;
5242 }
5243 TFriendLock lock(const_cast<TTree*>(this), kGetAlias);
5244 TIter nextf(fFriends);
5245 TFriendElement* fe = nullptr;
5246 while ((fe = (TFriendElement*) nextf())) {
5247 TTree* t = fe->GetTree();
5248 if (t) {
5249 const char* alias = t->GetAlias(aliasName);
5250 if (alias) {
5251 return alias;
5252 }
5253 const char* subAliasName = strstr(aliasName, fe->GetName());
5254 if (subAliasName && (subAliasName[strlen(fe->GetName())] == '.')) {
5255 alias = t->GetAlias(aliasName + strlen(fe->GetName()) + 1);
5256 if (alias) {
5257 return alias;
5258 }
5259 }
5260 }
5261 }
5262 return nullptr;
5263}
5264
5265namespace {
5266/// Do a breadth first search through the implied hierarchy
5267/// of branches.
5268/// To avoid scanning through the list multiple time
5269/// we also remember the 'depth-first' match.
5270TBranch *R__GetBranch(const TObjArray &branches, const char *name)
5271{
5272 TBranch *result = nullptr;
5273 Int_t nb = branches.GetEntriesFast();
5274 for (Int_t i = 0; i < nb; i++) {
5275 TBranch* b = (TBranch*)branches.UncheckedAt(i);
5276 if (!b)
5277 continue;
5278 if (!strcmp(b->GetName(), name)) {
5279 return b;
5280 }
5281 if (!strcmp(b->GetFullName(), name)) {
5282 return b;
5283 }
5284 if (!result)
5285 result = R__GetBranch(*(b->GetListOfBranches()), name);
5286 }
5287 return result;
5288}
5289}
5290
5291////////////////////////////////////////////////////////////////////////////////
5292/// Return pointer to the branch with the given name in this tree or its friends.
5293/// The search is done breadth first.
5295TBranch* TTree::GetBranch(const char* name)
5296{
5297 // We already have been visited while recursively
5298 // looking through the friends tree, let's return.
5300 return nullptr;
5301 }
5302
5303 if (!name)
5304 return nullptr;
5305
5306 // Look for an exact match in the list of top level
5307 // branches.
5309 if (result)
5310 return result;
5311
5312 // Search using branches, breadth first.
5313 result = R__GetBranch(fBranches, name);
5314 if (result)
5315 return result;
5316
5317 // Search using leaves.
5318 TObjArray* leaves = GetListOfLeaves();
5319 Int_t nleaves = leaves->GetEntriesFast();
5320 for (Int_t i = 0; i < nleaves; i++) {
5321 TLeaf* leaf = (TLeaf*) leaves->UncheckedAt(i);
5322 TBranch* branch = leaf->GetBranch();
5323 if (!strcmp(branch->GetName(), name)) {
5324 return branch;
5325 }
5326 if (!strcmp(branch->GetFullName(), name)) {
5327 return branch;
5328 }
5329 }
5330
5331 if (!fFriends) {
5332 return nullptr;
5333 }
5334
5335 // Search in list of friends.
5336 TFriendLock lock(this, kGetBranch);
5337 TIter next(fFriends);
5338 TFriendElement* fe = nullptr;
5339 while ((fe = (TFriendElement*) next())) {
5340 TTree* t = fe->GetTree();
5341 if (t) {
5342 TBranch* branch = t->GetBranch(name);
5343 if (branch) {
5344 return branch;
5345 }
5346 }
5347 }
5348
5349 // Second pass in the list of friends when
5350 // the branch name is prefixed by the tree name.
5351 next.Reset();
5352 while ((fe = (TFriendElement*) next())) {
5353 TTree* t = fe->GetTree();
5354 if (!t) {
5355 continue;
5356 }
5357 const char* subname = strstr(name, fe->GetName());
5358 if (subname != name) {
5359 continue;
5360 }
5361 Int_t l = strlen(fe->GetName());
5362 subname += l;
5363 if (*subname != '.') {
5364 continue;
5365 }
5366 subname++;
5367 TBranch* branch = t->GetBranch(subname);
5368 if (branch) {
5369 return branch;
5370 }
5371 }
5372 return nullptr;
5373}
5374
5375////////////////////////////////////////////////////////////////////////////////
5376/// Return status of branch with name branchname.
5377///
5378/// - 0 if branch is not activated
5379/// - 1 if branch is activated
5381bool TTree::GetBranchStatus(const char* branchname) const
5382{
5383 TBranch* br = const_cast<TTree*>(this)->GetBranch(branchname);
5384 if (br) {
5385 return br->TestBit(kDoNotProcess) == 0;
5386 }
5387 return false;
5388}
5389
5390////////////////////////////////////////////////////////////////////////////////
5391/// Static function returning the current branch style.
5392///
5393/// - style = 0 old Branch
5394/// - style = 1 new Bronch
5397{
5398 return fgBranchStyle;
5399}
5400
5401////////////////////////////////////////////////////////////////////////////////
5402/// Used for automatic sizing of the cache.
5403///
5404/// Estimates a suitable size for the tree cache based on AutoFlush.
5405/// A cache sizing factor is taken from the configuration. If this yields zero
5406/// and withDefault is true the historical algorithm for default size is used.
5408Long64_t TTree::GetCacheAutoSize(bool withDefault /* = false */ )
5409{
5410 auto calculateCacheSize = [this](Double_t cacheFactor)
5411 {
5412 Long64_t cacheSize = 0;
5413 if (fAutoFlush < 0) {
5414 cacheSize = Long64_t(-cacheFactor * fAutoFlush);
5415 } else if (fAutoFlush == 0) {
5416 const auto medianClusterSize = GetMedianClusterSize();
5417 if (medianClusterSize > 0)
5418 cacheSize = Long64_t(cacheFactor * 1.5 * medianClusterSize * GetZipBytes() / (fEntries + 1));
5419 else
5420 cacheSize = Long64_t(cacheFactor * 1.5 * 30000000); // use the default value of fAutoFlush
5421 } else {
5422 cacheSize = Long64_t(cacheFactor * 1.5 * fAutoFlush * GetZipBytes() / (fEntries + 1));
5423 }
5424 if (cacheSize >= (INT_MAX / 4)) {
5425 cacheSize = INT_MAX / 4;
5426 }
5427 return cacheSize;
5428 };
5429
5430 const char *stcs;
5431 Double_t cacheFactor = 0.0;
5432 if (!(stcs = gSystem->Getenv("ROOT_TTREECACHE_SIZE")) || !*stcs) {
5433 cacheFactor = gEnv->GetValue("TTreeCache.Size", 1.0);
5434 } else {
5435 cacheFactor = TString(stcs).Atof();
5436 }
5437
5438 if (cacheFactor < 0.0) {
5439 // ignore negative factors
5440 cacheFactor = 0.0;
5441 }
5442
5443 Long64_t cacheSize = calculateCacheSize(cacheFactor);
5444
5445 if (cacheSize < 0) {
5446 cacheSize = 0;
5447 }
5448
5449 if (cacheSize == 0 && withDefault) {
5450 cacheSize = calculateCacheSize(1.0);
5451 }
5452
5453 return cacheSize;
5454}
5455
5456////////////////////////////////////////////////////////////////////////////////
5457/// Return an iterator over the cluster of baskets starting at firstentry.
5458///
5459/// This iterator is not yet supported for TChain object.
5460/// ~~~ {.cpp}
5461/// TTree::TClusterIterator clusterIter = tree->GetClusterIterator(entry);
5462/// Long64_t clusterStart;
5463/// while( (clusterStart = clusterIter()) < tree->GetEntries() ) {
5464/// printf("The cluster starts at %lld and ends at %lld (inclusive)\n",clusterStart,clusterIter.GetNextEntry()-1);
5465/// }
5466/// ~~~
5469{
5470 // create cache if wanted
5471 if (fCacheDoAutoInit)
5473
5474 return TClusterIterator(this,firstentry);
5475}
5476
5477////////////////////////////////////////////////////////////////////////////////
5478/// Return pointer to the current file.
5481{
5482 if (!fDirectory || fDirectory==gROOT) {
5483 return nullptr;
5484 }
5485 return fDirectory->GetFile();
5486}
5487
5488////////////////////////////////////////////////////////////////////////////////
5489/// Return the number of entries matching the selection.
5490/// Return -1 in case of errors.
5491///
5492/// If the selection uses any arrays or containers, we return the number
5493/// of entries where at least one element match the selection.
5494/// GetEntries is implemented using the selector class TSelectorEntries,
5495/// which can be used directly (see code in TTreePlayer::GetEntries) for
5496/// additional option.
5497/// If SetEventList was used on the TTree or TChain, only that subset
5498/// of entries will be considered.
5500Long64_t TTree::GetEntries(const char *selection)
5501{
5502 GetPlayer();
5503 if (fPlayer) {
5504 return fPlayer->GetEntries(selection);
5505 }
5506 return -1;
5507}
5508
5509////////////////////////////////////////////////////////////////////////////////
5510/// Return pointer to the 1st Leaf named name in any Branch of this Tree or
5511/// any branch in the list of friend trees.
5514{
5515 if (fEntries) return fEntries;
5516 if (!fFriends) return 0;
5518 if (!fr) return 0;
5519 TTree *t = fr->GetTree();
5520 if (t==nullptr) return 0;
5521 return t->GetEntriesFriend();
5522}
5523
5524////////////////////////////////////////////////////////////////////////////////
5525/// Read all branches of entry and return total number of bytes read.
5526///
5527/// - `getall = 0` : get only active branches
5528/// - `getall = 1` : get all branches
5529///
5530/// The function returns the number of bytes read from the input buffer.
5531/// If entry does not exist the function returns 0.
5532/// If an I/O error occurs, the function returns -1.
5533///
5534/// If the Tree has friends, also read the friends entry.
5535///
5536/// To activate/deactivate one or more branches, use TBranch::SetBranchStatus
5537/// For example, if you have a Tree with several hundred branches, and you
5538/// are interested only by branches named "a" and "b", do
5539/// ~~~ {.cpp}
5540/// mytree.SetBranchStatus("*",0); //disable all branches
5541/// mytree.SetBranchStatus("a",1);
5542/// mytree.SetBranchStatus("b",1);
5543/// ~~~
5544/// when calling mytree.GetEntry(i); only branches "a" and "b" will be read.
5545///
5546/// __WARNING!!__
5547/// If your Tree has been created in split mode with a parent branch "parent.",
5548/// ~~~ {.cpp}
5549/// mytree.SetBranchStatus("parent",1);
5550/// ~~~
5551/// will not activate the sub-branches of "parent". You should do:
5552/// ~~~ {.cpp}
5553/// mytree.SetBranchStatus("parent*",1);
5554/// ~~~
5555/// Without the trailing dot in the branch creation you have no choice but to
5556/// call SetBranchStatus explicitly for each of the sub branches.
5557///
5558/// An alternative is to call directly
5559/// ~~~ {.cpp}
5560/// brancha.GetEntry(i)
5561/// branchb.GetEntry(i);
5562/// ~~~
5563/// ## IMPORTANT NOTE
5564///
5565/// By default, GetEntry reuses the space allocated by the previous object
5566/// for each branch. You can force the previous object to be automatically
5567/// deleted if you call mybranch.SetAutoDelete(true) (default is false).
5568///
5569/// Example:
5570///
5571/// Consider the example in $ROOTSYS/test/Event.h
5572/// The top level branch in the tree T is declared with:
5573/// ~~~ {.cpp}
5574/// Event *event = 0; //event must be null or point to a valid object
5575/// //it must be initialized
5576/// T.SetBranchAddress("event",&event);
5577/// ~~~
5578/// When reading the Tree, one can choose one of these 3 options:
5579///
5580/// ## OPTION 1
5581///
5582/// ~~~ {.cpp}
5583/// for (Long64_t i=0;i<nentries;i++) {
5584/// T.GetEntry(i);
5585/// // the object event has been filled at this point
5586/// }
5587/// ~~~
5588/// The default (recommended). At the first entry an object of the class
5589/// Event will be created and pointed by event. At the following entries,
5590/// event will be overwritten by the new data. All internal members that are
5591/// TObject* are automatically deleted. It is important that these members
5592/// be in a valid state when GetEntry is called. Pointers must be correctly
5593/// initialized. However these internal members will not be deleted if the
5594/// characters "->" are specified as the first characters in the comment
5595/// field of the data member declaration.
5596///
5597/// If "->" is specified, the pointer member is read via pointer->Streamer(buf).
5598/// In this case, it is assumed that the pointer is never null (case of
5599/// pointer TClonesArray *fTracks in the Event example). If "->" is not
5600/// specified, the pointer member is read via buf >> pointer. In this case
5601/// the pointer may be null. Note that the option with "->" is faster to
5602/// read or write and it also consumes less space in the file.
5603///
5604/// ## OPTION 2
5605///
5606/// The option AutoDelete is set
5607/// ~~~ {.cpp}
5608/// TBranch *branch = T.GetBranch("event");
5609/// branch->SetAddress(&event);
5610/// branch->SetAutoDelete(true);
5611/// for (Long64_t i=0;i<nentries;i++) {
5612/// T.GetEntry(i);
5613/// // the object event has been filled at this point
5614/// }
5615/// ~~~
5616/// In this case, at each iteration, the object event is deleted by GetEntry
5617/// and a new instance of Event is created and filled.
5618///
5619/// ## OPTION 3
5620///
5621/// ~~~ {.cpp}
5622/// Same as option 1, but you delete yourself the event.
5623///
5624/// for (Long64_t i=0;i<nentries;i++) {
5625/// delete event;
5626/// event = 0; // EXTREMELY IMPORTANT
5627/// T.GetEntry(i);
5628/// // the object event has been filled at this point
5629/// }
5630/// ~~~
5631/// It is strongly recommended to use the default option 1. It has the
5632/// additional advantage that functions like TTree::Draw (internally calling
5633/// TTree::GetEntry) will be functional even when the classes in the file are
5634/// not available.
5635///
5636/// Note: See the comments in TBranchElement::SetAddress() for the
5637/// object ownership policy of the underlying (user) data.
5639Int_t TTree::GetEntry(Long64_t entry, Int_t getall)
5640{
5641 // We already have been visited while recursively looking
5642 // through the friends tree, let return
5643 if (kGetEntry & fFriendLockStatus) return 0;
5644
5645 if (entry < 0 || entry >= fEntries) return 0;
5646 Int_t i;
5647 Int_t nbytes = 0;
5648 fReadEntry = entry;
5649
5650 // create cache if wanted
5651 if (fCacheDoAutoInit)
5653
5654 Int_t nbranches = fBranches.GetEntriesUnsafe();
5655 Int_t nb=0;
5656
5657 auto seqprocessing = [&]() {
5658 TBranch *branch;
5659 for (i=0;i<nbranches;i++) {
5660 branch = (TBranch*)fBranches.UncheckedAt(i);
5661 nb = branch->GetEntry(entry, getall);
5662 if (nb < 0) break;
5663 nbytes += nb;
5664 }
5665 };
5666
5667#ifdef R__USE_IMT
5669 if (fSortedBranches.empty())
5671
5672 // Count branches are processed first and sequentially
5673 for (auto branch : fSeqBranches) {
5674 nb = branch->GetEntry(entry, getall);
5675 if (nb < 0) break;
5676 nbytes += nb;
5677 }
5678 if (nb < 0) return nb;
5679
5680 // Enable this IMT use case (activate its locks)
5682
5683 Int_t errnb = 0;
5684 std::atomic<Int_t> pos(0);
5685 std::atomic<Int_t> nbpar(0);
5686
5687 auto mapFunction = [&]() {
5688 // The branch to process is obtained when the task starts to run.
5689 // This way, since branches are sorted, we make sure that branches
5690 // leading to big tasks are processed first. If we assigned the
5691 // branch at task creation time, the scheduler would not necessarily
5692 // respect our sorting.
5693 Int_t j = pos.fetch_add(1);
5694
5695 Int_t nbtask = 0;
5696 auto branch = fSortedBranches[j].second;
5697
5698 if (gDebug > 0) {
5699 std::stringstream ss;
5700 ss << std::this_thread::get_id();
5701 Info("GetEntry", "[IMT] Thread %s", ss.str().c_str());
5702 Info("GetEntry", "[IMT] Running task for branch #%d: %s", j, branch->GetName());
5703 }
5704
5705 std::chrono::time_point<std::chrono::system_clock> start, end;
5706
5707 start = std::chrono::system_clock::now();
5708 nbtask = branch->GetEntry(entry, getall);
5709 end = std::chrono::system_clock::now();
5710
5711 Long64_t tasktime = (Long64_t)std::chrono::duration_cast<std::chrono::microseconds>(end - start).count();
5712 fSortedBranches[j].first += tasktime;
5713
5714 if (nbtask < 0) errnb = nbtask;
5715 else nbpar += nbtask;
5716 };
5717
5719 pool.Foreach(mapFunction, fSortedBranches.size());
5720
5721 if (errnb < 0) {
5722 nb = errnb;
5723 }
5724 else {
5725 // Save the number of bytes read by the tasks
5726 nbytes += nbpar;
5727
5728 // Re-sort branches if necessary
5732 }
5733 }
5734 }
5735 else {
5736 seqprocessing();
5737 }
5738#else
5739 seqprocessing();
5740#endif
5741 if (nb < 0) return nb;
5742
5743 // GetEntry in list of friends
5744 if (!fFriends) return nbytes;
5745 TFriendLock lock(this,kGetEntry);
5746 TIter nextf(fFriends);
5747 TFriendElement *fe;
5748 while ((fe = (TFriendElement*)nextf())) {
5749 TTree *t = fe->GetTree();
5750 if (t) {
5752 nb = t->GetEntry(t->GetReadEntry(),getall);
5753 } else {
5754 if ( t->LoadTreeFriend(entry,this) >= 0 ) {
5755 nb = t->GetEntry(t->GetReadEntry(),getall);
5756 } else nb = 0;
5757 }
5758 if (nb < 0) return nb;
5759 nbytes += nb;
5760 }
5761 }
5762 return nbytes;
5763}
5764
5765
5766////////////////////////////////////////////////////////////////////////////////
5767/// Divides the top-level branches into two vectors: (i) branches to be
5768/// processed sequentially and (ii) branches to be processed in parallel.
5769/// Even if IMT is on, some branches might need to be processed first and in a
5770/// sequential fashion: in the parallelization of GetEntry, those are the
5771/// branches that store the size of another branch for every entry
5772/// (e.g. the size of an array branch). If such branches were processed
5773/// in parallel with the rest, there could be two threads invoking
5774/// TBranch::GetEntry on one of them at the same time, since a branch that
5775/// depends on a size (or count) branch will also invoke GetEntry on the latter.
5776/// This method can be invoked several times during the event loop if the TTree
5777/// is being written, for example when adding new branches. In these cases, the
5778/// `checkLeafCount` parameter is false.
5779/// \param[in] checkLeafCount True if we need to check whether some branches are
5780/// count leaves.
5782void TTree::InitializeBranchLists(bool checkLeafCount)
5783{
5784 Int_t nbranches = fBranches.GetEntriesFast();
5785
5786 // The special branch fBranchRef needs to be processed sequentially:
5787 // we add it once only.
5788 if (fBranchRef && fBranchRef != fSeqBranches[0]) {
5789 fSeqBranches.push_back(fBranchRef);
5790 }
5791
5792 // The branches to be processed sequentially are those that are the leaf count of another branch
5793 if (checkLeafCount) {
5794 for (Int_t i = 0; i < nbranches; i++) {
5795 TBranch* branch = (TBranch*)fBranches.UncheckedAt(i);
5796 auto leafCount = ((TLeaf*)branch->GetListOfLeaves()->At(0))->GetLeafCount();
5797 if (leafCount) {
5798 auto countBranch = leafCount->GetBranch();
5799 if (std::find(fSeqBranches.begin(), fSeqBranches.end(), countBranch) == fSeqBranches.end()) {
5800 fSeqBranches.push_back(countBranch);
5801 }
5802 }
5803 }
5804 }
5805
5806 // Any branch that is not a leaf count can be safely processed in parallel when reading
5807 // We need to reset the vector to make sure we do not re-add several times the same branch.
5808 if (!checkLeafCount) {
5809 fSortedBranches.clear();
5810 }
5811 for (Int_t i = 0; i < nbranches; i++) {
5812 Long64_t bbytes = 0;
5813 TBranch* branch = (TBranch*)fBranches.UncheckedAt(i);
5814 if (std::find(fSeqBranches.begin(), fSeqBranches.end(), branch) == fSeqBranches.end()) {
5815 bbytes = branch->GetTotBytes("*");
5816 fSortedBranches.emplace_back(bbytes, branch);
5817 }
5818 }
5819
5820 // Initially sort parallel branches by size
5821 std::sort(fSortedBranches.begin(),
5822 fSortedBranches.end(),
5823 [](std::pair<Long64_t,TBranch*> a, std::pair<Long64_t,TBranch*> b) {
5824 return a.first > b.first;
5825 });
5826
5827 for (size_t i = 0; i < fSortedBranches.size(); i++) {
5828 fSortedBranches[i].first = 0LL;
5829 }
5830}
5831
5832////////////////////////////////////////////////////////////////////////////////
5833/// Sorts top-level branches by the last average task time recorded per branch.
5836{
5837 for (size_t i = 0; i < fSortedBranches.size(); i++) {
5839 }
5840
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///Returns the entry list assigned to this tree
5856{
5857 return fEntryList;
5858}
5859
5860////////////////////////////////////////////////////////////////////////////////
5861/// Return entry number corresponding to entry.
5862///
5863/// if no TEntryList set returns entry
5864/// else returns the entry number corresponding to the list index=entry
5867{
5868 if (!fEntryList) {
5869 return entry;
5870 }
5871
5872 return fEntryList->GetEntry(entry);
5873}
5874
5875////////////////////////////////////////////////////////////////////////////////
5876/// Return entry number corresponding to major and minor number.
5877/// Note that this function returns only the entry number, not the data
5878/// To read the data corresponding to an entry number, use TTree::GetEntryWithIndex
5879/// the BuildIndex function has created a table of Long64_t* of sorted values
5880/// corresponding to val = major<<31 + minor;
5881/// The function performs binary search in this sorted table.
5882/// If it finds a pair that matches val, it returns directly the
5883/// index in the table.
5884/// If an entry corresponding to major and minor is not found, the function
5885/// returns the index of the major,minor pair immediately lower than the
5886/// requested value, ie it will return -1 if the pair is lower than
5887/// the first entry in the index.
5888///
5889/// See also GetEntryNumberWithIndex
5892{
5893 if (!fTreeIndex) {
5894 return -1;
5895 }
5896 return fTreeIndex->GetEntryNumberWithBestIndex(major, minor);
5897}
5898
5899////////////////////////////////////////////////////////////////////////////////
5900/// Return entry number corresponding to major and minor number.
5901/// Note that this function returns only the entry number, not the data
5902/// To read the data corresponding to an entry number, use TTree::GetEntryWithIndex
5903/// the BuildIndex function has created a table of Long64_t* of sorted values
5904/// corresponding to val = major<<31 + minor;
5905/// The function performs binary search in this sorted table.
5906/// If it finds a pair that matches val, it returns directly the
5907/// index in the table, otherwise it returns -1.
5908///
5909/// See also GetEntryNumberWithBestIndex
5912{
5913 if (!fTreeIndex) {
5914 return -1;
5915 }
5916 return fTreeIndex->GetEntryNumberWithIndex(major, minor);
5917}
5918
5919////////////////////////////////////////////////////////////////////////////////
5920/// Read entry corresponding to major and minor number.
5921///
5922/// The function returns the total number of bytes read.
5923/// If the Tree has friend trees, the corresponding entry with
5924/// the index values (major,minor) is read. Note that the master Tree
5925/// and its friend may have different entry serial numbers corresponding
5926/// to (major,minor).
5929{
5930 // We already have been visited while recursively looking
5931 // through the friends tree, let's return.
5933 return 0;
5934 }
5935 Long64_t serial = GetEntryNumberWithIndex(major, minor);
5936 if (serial < 0) {
5937 return -1;
5938 }
5939 // create cache if wanted
5940 if (fCacheDoAutoInit)
5942
5943 Int_t i;
5944 Int_t nbytes = 0;
5945 fReadEntry = serial;
5946 TBranch *branch;
5947 Int_t nbranches = fBranches.GetEntriesFast();
5948 Int_t nb;
5949 for (i = 0; i < nbranches; ++i) {
5950 branch = (TBranch*)fBranches.UncheckedAt(i);
5951 nb = branch->GetEntry(serial);
5952 if (nb < 0) return nb;
5953 nbytes += nb;
5954 }
5955 // GetEntry in list of friends
5956 if (!fFriends) return nbytes;
5958 TIter nextf(fFriends);
5959 TFriendElement* fe = nullptr;
5960 while ((fe = (TFriendElement*) nextf())) {
5961 TTree *t = fe->GetTree();
5962 if (t) {
5963 serial = t->GetEntryNumberWithIndex(major,minor);
5964 if (serial <0) return -nbytes;
5965 nb = t->GetEntry(serial);
5966 if (nb < 0) return nb;
5967 nbytes += nb;
5968 }
5969 }
5970 return nbytes;
5971}
5972
5973////////////////////////////////////////////////////////////////////////////////
5974/// Return a pointer to the TTree friend whose name or alias is `friendname`.
5976TTree* TTree::GetFriend(const char *friendname) const
5977{
5978
5979 // We already have been visited while recursively
5980 // looking through the friends tree, let's return.
5982 return nullptr;
5983 }
5984 if (!fFriends) {
5985 return nullptr;
5986 }
5987 TFriendLock lock(const_cast<TTree*>(this), kGetFriend);
5988 TIter nextf(fFriends);
5989 TFriendElement* fe = nullptr;
5990 while ((fe = (TFriendElement*) nextf())) {
5991 if (strcmp(friendname,fe->GetName())==0
5992 || strcmp(friendname,fe->GetTreeName())==0) {
5993 return fe->GetTree();
5994 }
5995 }
5996 // After looking at the first level,
5997 // let's see if it is a friend of friends.
5998 nextf.Reset();
5999 fe = nullptr;
6000 while ((fe = (TFriendElement*) nextf())) {
6001 TTree *res = fe->GetTree()->GetFriend(friendname);
6002 if (res) {
6003 return res;
6004 }
6005 }
6006 return nullptr;
6007}
6008
6009////////////////////////////////////////////////////////////////////////////////
6010/// If the 'tree' is a friend, this method returns its alias name.
6011///
6012/// This alias is an alternate name for the tree.
6013///
6014/// It can be used in conjunction with a branch or leaf name in a TTreeFormula,
6015/// to specify in which particular tree the branch or leaf can be found if
6016/// the friend trees have branches or leaves with the same name as the master
6017/// tree.
6018///
6019/// It can also be used in conjunction with an alias created using
6020/// TTree::SetAlias in a TTreeFormula, e.g.:
6021/// ~~~ {.cpp}
6022/// maintree->Draw("treealias.fPx - treealias.myAlias");
6023/// ~~~
6024/// where fPx is a branch of the friend tree aliased as 'treealias' and 'myAlias'
6025/// was created using TTree::SetAlias on the friend tree.
6026///
6027/// However, note that 'treealias.myAlias' will be expanded literally,
6028/// without remembering that it comes from the aliased friend and thus
6029/// the branch name might not be disambiguated properly, which means
6030/// that you may not be able to take advantage of this feature.
6031///
6033const char* TTree::GetFriendAlias(TTree* tree) const
6034{
6035 if ((tree == this) || (tree == GetTree())) {
6036 return nullptr;
6037 }
6038
6039 // We already have been visited while recursively
6040 // looking through the friends tree, let's return.
6042 return nullptr;
6043 }
6044 if (!fFriends) {
6045 return nullptr;
6046 }
6047 TFriendLock lock(const_cast<TTree*>(this), kGetFriendAlias);
6048 TIter nextf(fFriends);
6049 TFriendElement* fe = nullptr;
6050 while ((fe = (TFriendElement*) nextf())) {
6051 TTree* t = fe->GetTree();
6052 if (t == tree) {
6053 return fe->GetName();
6054 }
6055 // Case of a chain:
6056 if (t && t->GetTree() == tree) {
6057 return fe->GetName();
6058 }
6059 }
6060 // After looking at the first level,
6061 // let's see if it is a friend of friends.
6062 nextf.Reset();
6063 fe = nullptr;
6064 while ((fe = (TFriendElement*) nextf())) {
6065 const char* res = fe->GetTree()->GetFriendAlias(tree);
6066 if (res) {
6067 return res;
6068 }
6069 }
6070 return nullptr;
6071}
6072
6073////////////////////////////////////////////////////////////////////////////////
6074/// Returns the current set of IO settings
6076{
6077 return fIOFeatures;
6078}
6079
6080////////////////////////////////////////////////////////////////////////////////
6081/// Creates a new iterator that will go through all the leaves on the tree itself and its friend.
6084{
6085 return new TTreeFriendLeafIter(this, dir);
6086}
6087
6088////////////////////////////////////////////////////////////////////////////////
6089/// Return pointer to the 1st Leaf named name in any Branch of this
6090/// Tree or any branch in the list of friend trees.
6091///
6092/// The leaf name can contain the name of a friend tree with the
6093/// syntax: friend_dir_and_tree.full_leaf_name
6094/// the friend_dir_and_tree can be of the form:
6095/// ~~~ {.cpp}
6096/// TDirectoryName/TreeName
6097/// ~~~
6099TLeaf* TTree::GetLeafImpl(const char* branchname, const char *leafname)
6100{
6101 TLeaf *leaf = nullptr;
6102 if (branchname) {
6103 TBranch *branch = FindBranch(branchname);
6104 if (branch) {
6105 leaf = branch->GetLeaf(leafname);
6106 if (leaf) {
6107 return leaf;
6108 }
6109 }
6110 }
6111 TIter nextl(GetListOfLeaves());
6112 while ((leaf = (TLeaf*)nextl())) {
6113 if (strcmp(leaf->GetFullName(), leafname) != 0 && strcmp(leaf->GetName(), leafname) != 0)
6114 continue; // leafname does not match GetName() nor GetFullName(), this is not the right leaf
6115 if (branchname) {
6116 // check the branchname is also a match
6117 TBranch *br = leaf->GetBranch();
6118 // if a quick comparison with the branch full name is a match, we are done
6119 if (!strcmp(br->GetFullName(), branchname))
6120 return leaf;
6121 UInt_t nbch = strlen(branchname);
6122 const char* brname = br->GetName();
6123 TBranch *mother = br->GetMother();
6124 if (strncmp(brname,branchname,nbch)) {
6125 if (mother != br) {
6126 const char *mothername = mother->GetName();
6127 UInt_t motherlen = strlen(mothername);
6128 if (!strcmp(mothername, branchname)) {
6129 return leaf;
6130 } else if (nbch > motherlen && strncmp(mothername,branchname,motherlen)==0 && (mothername[motherlen-1]=='.' || branchname[motherlen]=='.')) {
6131 // 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.
6132 if (strncmp(brname,branchname+motherlen+1,nbch-motherlen-1)) {
6133 // No it does not
6134 continue;
6135 } // else we have match so we can proceed.
6136 } else {
6137 // no match
6138 continue;
6139 }
6140 } else {
6141 continue;
6142 }
6143 }
6144 // The start of the branch name is identical to the content
6145 // of 'aname' before the first '/'.
6146 // Let's make sure that it is not longer (we are trying
6147 // to avoid having jet2/value match the branch jet23
6148 if ((strlen(brname) > nbch) && (brname[nbch] != '.') && (brname[nbch] != '[')) {
6149 continue;
6150 }
6151 }
6152 return leaf;
6153 }
6154 if (!fFriends) return nullptr;
6155 TFriendLock lock(this,kGetLeaf);
6156 TIter next(fFriends);
6157 TFriendElement *fe;
6158 while ((fe = (TFriendElement*)next())) {
6159 TTree *t = fe->GetTree();
6160 if (t) {
6161 leaf = t->GetLeaf(branchname, leafname);
6162 if (leaf) return leaf;
6163 }
6164 }
6165
6166 //second pass in the list of friends when the leaf name
6167 //is prefixed by the tree name
6168 TString strippedArg;
6169 next.Reset();
6170 while ((fe = (TFriendElement*)next())) {
6171 TTree *t = fe->GetTree();
6172 if (!t) continue;
6173 const char *subname = strstr(leafname,fe->GetName());
6174 if (subname != leafname) continue;
6175 Int_t l = strlen(fe->GetName());
6176 subname += l;
6177 if (*subname != '.') continue;
6178 subname++;
6179 strippedArg += subname;
6180 leaf = t->GetLeaf(branchname,subname);
6181 if (leaf) return leaf;
6182 }
6183 return nullptr;
6184}
6185
6186////////////////////////////////////////////////////////////////////////////////
6187/// Return pointer to the 1st Leaf named name in any Branch of this
6188/// Tree or any branch in the list of friend trees.
6189///
6190/// The leaf name can contain the name of a friend tree with the
6191/// syntax: friend_dir_and_tree.full_leaf_name
6192/// the friend_dir_and_tree can be of the form:
6193///
6194/// TDirectoryName/TreeName
6196TLeaf* TTree::GetLeaf(const char* branchname, const char *leafname)
6197{
6198 if (leafname == nullptr) return nullptr;
6199
6200 // We already have been visited while recursively looking
6201 // through the friends tree, let return
6203 return nullptr;
6204 }
6205
6206 return GetLeafImpl(branchname,leafname);
6207}
6208
6209////////////////////////////////////////////////////////////////////////////////
6210/// Return pointer to first leaf named "name" in any branch of this
6211/// tree or its friend trees.
6212///
6213/// \param[in] name may be in the form 'branch/leaf'
6214///
6216TLeaf* TTree::GetLeaf(const char *name)
6217{
6218 // Return nullptr if name is invalid or if we have
6219 // already been visited while searching friend trees
6220 if (!name || (kGetLeaf & fFriendLockStatus))
6221 return nullptr;
6222
6223 std::string path(name);
6224 const auto sep = path.find_last_of('/');
6225 if (sep != std::string::npos)
6226 return GetLeafImpl(path.substr(0, sep).c_str(), name+sep+1);
6227
6228 return GetLeafImpl(nullptr, name);
6229}
6230
6231////////////////////////////////////////////////////////////////////////////////
6232/// Return maximum of column with name columname.
6233/// if the Tree has an associated TEventList or TEntryList, the maximum
6234/// is computed for the entries in this list.
6236Double_t TTree::GetMaximum(const char* columname)
6237{
6238 TLeaf* leaf = this->GetLeaf(columname);
6239 if (!leaf) {
6240 return 0;
6241 }
6242
6243 // create cache if wanted
6244 if (fCacheDoAutoInit)
6246
6247 TBranch* branch = leaf->GetBranch();
6248 Double_t cmax = -DBL_MAX;
6249 for (Long64_t i = 0; i < fEntries; ++i) {
6250 Long64_t entryNumber = this->GetEntryNumber(i);
6251 if (entryNumber < 0) break;
6252 branch->GetEntry(entryNumber);
6253 for (Int_t j = 0; j < leaf->GetLen(); ++j) {
6254 Double_t val = leaf->GetValue(j);
6255 if (val > cmax) {
6256 cmax = val;
6257 }
6258 }
6259 }
6260 return cmax;
6261}
6262
6263////////////////////////////////////////////////////////////////////////////////
6264/// Static function which returns the tree file size limit in bytes.
6267{
6268 return fgMaxTreeSize;
6269}
6270
6271////////////////////////////////////////////////////////////////////////////////
6272/// Return minimum of column with name columname.
6273/// if the Tree has an associated TEventList or TEntryList, the minimum
6274/// is computed for the entries in this list.
6276Double_t TTree::GetMinimum(const char* columname)
6277{
6278 TLeaf* leaf = this->GetLeaf(columname);
6279 if (!leaf) {
6280 return 0;
6281 }
6282
6283 // create cache if wanted
6284 if (fCacheDoAutoInit)
6286
6287 TBranch* branch = leaf->GetBranch();
6288 Double_t cmin = DBL_MAX;
6289 for (Long64_t i = 0; i < fEntries; ++i) {
6290 Long64_t entryNumber = this->GetEntryNumber(i);
6291 if (entryNumber < 0) break;
6292 branch->GetEntry(entryNumber);
6293 for (Int_t j = 0;j < leaf->GetLen(); ++j) {
6294 Double_t val = leaf->GetValue(j);
6295 if (val < cmin) {
6296 cmin = val;
6297 }
6298 }
6299 }
6300 return cmin;
6301}
6302
6303////////////////////////////////////////////////////////////////////////////////
6304/// Load the TTreePlayer (if not already done).
6307{
6308 if (fPlayer) {
6309 return fPlayer;
6310 }
6312 return fPlayer;
6313}
6314
6315////////////////////////////////////////////////////////////////////////////////
6316/// Find and return the TTreeCache registered with the file and which may
6317/// contain branches for us.
6320{
6321 TTreeCache *pe = dynamic_cast<TTreeCache*>(file->GetCacheRead(GetTree()));
6322 if (pe && pe->GetTree() != GetTree())
6323 pe = nullptr;
6324 return pe;
6325}
6326
6327////////////////////////////////////////////////////////////////////////////////
6328/// Find and return the TTreeCache registered with the file and which may
6329/// contain branches for us. If create is true and there is no cache
6330/// a new cache is created with default size.
6332TTreeCache *TTree::GetReadCache(TFile *file, bool create)
6333{
6334 TTreeCache *pe = GetReadCache(file);
6335 if (create && !pe) {
6336 if (fCacheDoAutoInit)
6337 SetCacheSizeAux(true, -1);
6338 pe = dynamic_cast<TTreeCache*>(file->GetCacheRead(GetTree()));
6339 if (pe && pe->GetTree() != GetTree()) pe = nullptr;
6340 }
6341 return pe;
6342}
6343
6344////////////////////////////////////////////////////////////////////////////////
6345/// Return a pointer to the list containing user objects associated to this tree.
6346///
6347/// The list is automatically created if it does not exist.
6348///
6349/// WARNING: By default the TTree destructor will delete all objects added
6350/// to this list. If you do not want these objects to be deleted,
6351/// call:
6352///
6353/// mytree->GetUserInfo()->Clear();
6354///
6355/// before deleting the tree.
6358{
6359 if (!fUserInfo) {
6360 fUserInfo = new TList();
6361 fUserInfo->SetName("UserInfo");
6362 }
6363 return fUserInfo;
6364}
6365
6366////////////////////////////////////////////////////////////////////////////////
6367/// Appends the cluster range information stored in 'fromtree' to this tree,
6368/// including the value of fAutoFlush.
6369///
6370/// This is used when doing a fast cloning (by TTreeCloner).
6371/// See also fAutoFlush and fAutoSave if needed.
6373void TTree::ImportClusterRanges(TTree *fromtree)
6374{
6375 Long64_t autoflush = fromtree->GetAutoFlush();
6376 if (fromtree->fNClusterRange == 0 && fromtree->fAutoFlush == fAutoFlush) {
6377 // nothing to do
6378 } else if (fNClusterRange || fromtree->fNClusterRange) {
6379 Int_t newsize = fNClusterRange + 1 + fromtree->fNClusterRange;
6380 if (newsize > fMaxClusterRange) {
6381 if (fMaxClusterRange) {
6383 newsize*sizeof(Long64_t),fMaxClusterRange*sizeof(Long64_t));
6385 newsize*sizeof(Long64_t),fMaxClusterRange*sizeof(Long64_t));
6386 fMaxClusterRange = newsize;
6387 } else {
6388 fMaxClusterRange = newsize;
6391 }
6392 }
6393 if (fEntries) {
6397 }
6398 for (Int_t i = 0 ; i < fromtree->fNClusterRange; ++i) {
6402 }
6403 fAutoFlush = autoflush;
6404 } else {
6405 SetAutoFlush( autoflush );
6406 }
6407 Long64_t autosave = GetAutoSave();
6408 if (autoflush > 0 && autosave > 0) {
6409 SetAutoSave( autoflush*(autosave/autoflush) );
6410 }
6411}
6412
6413////////////////////////////////////////////////////////////////////////////////
6414/// Keep a maximum of fMaxEntries in memory.
6417{
6419 Long64_t maxEntries = fMaxEntries - (fMaxEntries / 10);
6420 for (Int_t i = 0; i < nb; ++i) {
6421 TBranch* branch = (TBranch*) fBranches.UncheckedAt(i);
6422 branch->KeepCircular(maxEntries);
6423 }
6424 if (fNClusterRange) {
6425 Long64_t entriesOffset = fEntries - maxEntries;
6426 Int_t oldsize = fNClusterRange;
6427 for(Int_t i = 0, j = 0; j < oldsize; ++j) {
6428 if (fClusterRangeEnd[j] > entriesOffset) {
6429 fClusterRangeEnd[i] = fClusterRangeEnd[j] - entriesOffset;
6430 ++i;
6431 } else {
6433 }
6434 }
6435 }
6436 fEntries = maxEntries;
6437 fReadEntry = -1;
6438}
6439
6440////////////////////////////////////////////////////////////////////////////////
6441/// Read in memory all baskets from all branches up to the limit of maxmemory bytes.
6442///
6443/// If maxmemory is non null and positive SetMaxVirtualSize is called
6444/// with this value. Default for maxmemory is 2000000000 (2 Gigabytes).
6445/// The function returns the total number of baskets read into memory
6446/// if negative an error occurred while loading the branches.
6447/// This method may be called to force branch baskets in memory
6448/// when random access to branch entries is required.
6449/// If random access to only a few branches is required, you should
6450/// call directly TBranch::LoadBaskets.
6453{
6454 if (maxmemory > 0) SetMaxVirtualSize(maxmemory);
6455
6456 TIter next(GetListOfLeaves());
6457 TLeaf *leaf;
6458 Int_t nimported = 0;
6459 while ((leaf=(TLeaf*)next())) {
6460 nimported += leaf->GetBranch()->LoadBaskets();//break;
6461 }
6462 return nimported;
6463}
6464
6465////////////////////////////////////////////////////////////////////////////////
6466/// Set current entry.
6467///
6468/// Returns -2 if entry does not exist (just as TChain::LoadTree()).
6469/// Returns -6 if an error occurs in the notification callback (just as TChain::LoadTree()).
6470///
6471/// Calls fNotify->Notify() (if fNotify is not null) when starting the processing of a new tree.
6472///
6473/// \note This function is overloaded in TChain.
6475{
6476 // We have already been visited while recursively looking
6477 // through the friend trees, let's return
6479 // We need to return a negative value to avoid a circular list of friends
6480 // to think that there is always an entry somewhere in the list.
6481 return -1;
6482 }
6483
6484 // create cache if wanted
6485 if (fCacheDoAutoInit && entry >=0)
6487
6488 if (fNotify) {
6489 if (fReadEntry < 0) {
6490 fNotify->Notify();
6491 }
6492 }
6493 fReadEntry = entry;
6494
6495 bool friendHasEntry = false;
6496 if (fFriends) {
6497 // Set current entry in friends as well.
6498 //
6499 // An alternative would move this code to each of the
6500 // functions calling LoadTree (and to overload a few more).
6501 bool needUpdate = false;
6502 {
6503 // This scope is need to insure the lock is released at the right time
6504 TIter nextf(fFriends);
6505 TFriendLock lock(this, kLoadTree);
6506 TFriendElement* fe = nullptr;
6507 while ((fe = (TFriendElement*) nextf())) {
6509 // This friend element was added by the chain that owns this
6510 // tree, the chain will deal with loading the correct entry.
6511 continue;
6512 }
6513 TTree* friendTree = fe->GetTree();
6514 if (friendTree) {
6515 if (friendTree->LoadTreeFriend(entry, this) >= 0) {
6516 friendHasEntry = true;
6517 }
6518 }
6519 if (fe->IsUpdated()) {
6520 needUpdate = true;
6521 fe->ResetUpdated();
6522 }
6523 } // for each friend
6524 }
6525 if (needUpdate) {
6526 //update list of leaves in all TTreeFormula of the TTreePlayer (if any)
6527 if (fPlayer) {
6529 }
6530 //Notify user if requested
6531 if (fNotify) {
6532 if(!fNotify->Notify()) return -6;
6533 }
6534 }
6535 }
6536
6537 if ((fReadEntry >= fEntries) && !friendHasEntry) {
6538 fReadEntry = -1;
6539 return -2;
6540 }
6541 return fReadEntry;
6542}
6543
6544////////////////////////////////////////////////////////////////////////////////
6545/// Load entry on behalf of our master tree, we may use an index.
6546///
6547/// Called by LoadTree() when the masterTree looks for the entry
6548/// number in a friend tree (us) corresponding to the passed entry
6549/// number in the masterTree.
6550///
6551/// If we have no index, our entry number and the masterTree entry
6552/// number are the same.
6553///
6554/// If we *do* have an index, we must find the (major, minor) value pair
6555/// in masterTree to locate our corresponding entry.
6556///
6558Long64_t TTree::LoadTreeFriend(Long64_t entry, TTree* masterTree)
6559{
6560 if (!fTreeIndex) {
6561 return LoadTree(entry);
6562 }
6563 return LoadTree(fTreeIndex->GetEntryNumberFriend(masterTree));
6564}
6565
6566////////////////////////////////////////////////////////////////////////////////
6567/// Generate a skeleton analysis class for this tree.
6568///
6569/// The following files are produced: classname.h and classname.C.
6570/// If classname is 0, classname will be called "nameoftree".
6571///
6572/// The generated code in classname.h includes the following:
6573///
6574/// - Identification of the original tree and the input file name.
6575/// - Definition of an analysis class (data members and member functions).
6576/// - The following member functions:
6577/// - constructor (by default opening the tree file),
6578/// - GetEntry(Long64_t entry),
6579/// - Init(TTree* tree) to initialize a new TTree,
6580/// - Show(Long64_t entry) to read and dump entry.
6581///
6582/// The generated code in classname.C includes only the main
6583/// analysis function Loop.
6584///
6585/// To use this function:
6586///
6587/// - Open your tree file (eg: TFile f("myfile.root");)
6588/// - T->MakeClass("MyClass");
6589///
6590/// where T is the name of the TTree in file myfile.root,
6591/// and MyClass.h, MyClass.C the name of the files created by this function.
6592/// In a ROOT session, you can do:
6593/// ~~~ {.cpp}
6594/// root > .L MyClass.C
6595/// root > MyClass* t = new MyClass;
6596/// root > t->GetEntry(12); // Fill data members of t with entry number 12.
6597/// root > t->Show(); // Show values of entry 12.
6598/// root > t->Show(16); // Read and show values of entry 16.
6599/// root > t->Loop(); // Loop on all entries.
6600/// ~~~
6601/// NOTE: Do not use the code generated for a single TTree which is part
6602/// of a TChain to process that entire TChain. The maximum dimensions
6603/// calculated for arrays on the basis of a single TTree from the TChain
6604/// might be (will be!) too small when processing all of the TTrees in
6605/// the TChain. You must use myChain.MakeClass() to generate the code,
6606/// not myTree.MakeClass(...).
6608Int_t TTree::MakeClass(const char* classname, Option_t* option)
6609{
6610 GetPlayer();
6611 if (!fPlayer) {
6612 return 0;
6613 }
6614 return fPlayer->MakeClass(classname, option);
6615}
6616
6617////////////////////////////////////////////////////////////////////////////////
6618/// Generate a skeleton function for this tree.
6619///
6620/// The function code is written on filename.
6621/// If filename is 0, filename will be called nameoftree.C
6622///
6623/// The generated code includes the following:
6624/// - Identification of the original Tree and Input file name,
6625/// - Opening the Tree file,
6626/// - Declaration of Tree variables,
6627/// - Setting of branches addresses,
6628/// - A skeleton for the entry loop.
6629///
6630/// To use this function:
6631///
6632/// - Open your Tree file (eg: TFile f("myfile.root");)
6633/// - T->MakeCode("MyAnalysis.C");
6634///
6635/// where T is the name of the TTree in file myfile.root
6636/// and MyAnalysis.C the name of the file created by this function.
6637///
6638/// NOTE: Since the implementation of this function, a new and better
6639/// function TTree::MakeClass() has been developed.
6641Int_t TTree::MakeCode(const char* filename)
6642{
6643 Warning("MakeCode", "MakeCode is obsolete. Use MakeClass or MakeSelector instead");
6644
6645 GetPlayer();
6646 if (!fPlayer) return 0;
6647 return fPlayer->MakeCode(filename);
6648}
6649
6650////////////////////////////////////////////////////////////////////////////////
6651/// Generate a skeleton analysis class for this Tree using TBranchProxy.
6652///
6653/// TBranchProxy is the base of a class hierarchy implementing an
6654/// indirect access to the content of the branches of a TTree.
6655///
6656/// "proxyClassname" is expected to be of the form:
6657/// ~~~ {.cpp}
6658/// [path/]fileprefix
6659/// ~~~
6660/// The skeleton will then be generated in the file:
6661/// ~~~ {.cpp}
6662/// fileprefix.h
6663/// ~~~
6664/// located in the current directory or in 'path/' if it is specified.
6665/// The class generated will be named 'fileprefix'
6666///
6667/// "macrofilename" and optionally "cutfilename" are expected to point
6668/// to source files which will be included by the generated skeleton.
6669/// Method of the same name as the file(minus the extension and path)
6670/// will be called by the generated skeleton's Process method as follow:
6671/// ~~~ {.cpp}
6672/// [if (cutfilename())] htemp->Fill(macrofilename());
6673/// ~~~
6674/// "option" can be used select some of the optional features during
6675/// the code generation. The possible options are:
6676///
6677/// - nohist : indicates that the generated ProcessFill should not fill the histogram.
6678///
6679/// 'maxUnrolling' controls how deep in the class hierarchy does the
6680/// system 'unroll' classes that are not split. Unrolling a class
6681/// allows direct access to its data members (this emulates the behavior
6682/// of TTreeFormula).
6683///
6684/// The main features of this skeleton are:
6685///
6686/// * on-demand loading of branches
6687/// * ability to use the 'branchname' as if it was a data member
6688/// * protection against array out-of-bounds errors
6689/// * ability to use the branch data as an object (when the user code is available)
6690///
6691/// For example with Event.root, if
6692/// ~~~ {.cpp}
6693/// Double_t somePx = fTracks.fPx[2];
6694/// ~~~
6695/// is executed by one of the method of the skeleton,
6696/// somePx will updated with the current value of fPx of the 3rd track.
6697///
6698/// Both macrofilename and the optional cutfilename are expected to be
6699/// the name of source files which contain at least a free standing
6700/// function with the signature:
6701/// ~~~ {.cpp}
6702/// x_t macrofilename(); // i.e function with the same name as the file
6703/// ~~~
6704/// and
6705/// ~~~ {.cpp}
6706/// y_t cutfilename(); // i.e function with the same name as the file
6707/// ~~~
6708/// x_t and y_t needs to be types that can convert respectively to a double
6709/// and a bool (because the skeleton uses:
6710///
6711/// if (cutfilename()) htemp->Fill(macrofilename());
6712///
6713/// These two functions are run in a context such that the branch names are
6714/// available as local variables of the correct (read-only) type.
6715///
6716/// Note that if you use the same 'variable' twice, it is more efficient
6717/// to 'cache' the value. For example:
6718/// ~~~ {.cpp}
6719/// Int_t n = fEventNumber; // Read fEventNumber
6720/// if (n<10 || n>10) { ... }
6721/// ~~~
6722/// is more efficient than
6723/// ~~~ {.cpp}
6724/// if (fEventNumber<10 || fEventNumber>10)
6725/// ~~~
6726/// Also, optionally, the generated selector will also call methods named
6727/// macrofilename_methodname in each of 6 main selector methods if the method
6728/// macrofilename_methodname exist (Where macrofilename is stripped of its
6729/// extension).
6730///
6731/// Concretely, with the script named h1analysisProxy.C,
6732///
6733/// - The method calls the method (if it exist)
6734/// - Begin -> void h1analysisProxy_Begin(TTree*);
6735/// - SlaveBegin -> void h1analysisProxy_SlaveBegin(TTree*);
6736/// - Notify -> bool h1analysisProxy_Notify();
6737/// - Process -> bool h1analysisProxy_Process(Long64_t);
6738/// - SlaveTerminate -> void h1analysisProxy_SlaveTerminate();
6739/// - Terminate -> void h1analysisProxy_Terminate();
6740///
6741/// If a file name macrofilename.h (or .hh, .hpp, .hxx, .hPP, .hXX) exist
6742/// it is included before the declaration of the proxy class. This can
6743/// be used in particular to insure that the include files needed by
6744/// the macro file are properly loaded.
6745///
6746/// The default histogram is accessible via the variable named 'htemp'.
6747///
6748/// If the library of the classes describing the data in the branch is
6749/// loaded, the skeleton will add the needed `include` statements and
6750/// give the ability to access the object stored in the branches.
6751///
6752/// To draw px using the file hsimple.root (generated by the
6753/// hsimple.C tutorial), we need a file named hsimple.cxx:
6754/// ~~~ {.cpp}
6755/// double hsimple() {
6756/// return px;
6757/// }
6758/// ~~~
6759/// MakeProxy can then be used indirectly via the TTree::Draw interface
6760/// as follow:
6761/// ~~~ {.cpp}
6762/// new TFile("hsimple.root")
6763/// ntuple->Draw("hsimple.cxx");
6764/// ~~~
6765/// A more complete example is available in the tutorials directory:
6766/// h1analysisProxy.cxx , h1analysProxy.h and h1analysisProxyCut.C
6767/// which reimplement the selector found in h1analysis.C
6769Int_t TTree::MakeProxy(const char* proxyClassname, const char* macrofilename, const char* cutfilename, const char* option, Int_t maxUnrolling)
6770{
6771 GetPlayer();
6772 if (!fPlayer) return 0;
6773 return fPlayer->MakeProxy(proxyClassname,macrofilename,cutfilename,option,maxUnrolling);
6774}
6775
6776////////////////////////////////////////////////////////////////////////////////
6777/// Generate skeleton selector class for this tree.
6778///
6779/// The following files are produced: selector.h and selector.C.
6780/// If selector is 0, the selector will be called "nameoftree".
6781/// The option can be used to specify the branches that will have a data member.
6782/// - If option is "=legacy", a pre-ROOT6 selector will be generated (data
6783/// members and branch pointers instead of TTreeReaders).
6784/// - If option is empty, readers will be generated for each leaf.
6785/// - If option is "@", readers will be generated for the topmost branches.
6786/// - Individual branches can also be picked by their name:
6787/// - "X" generates readers for leaves of X.
6788/// - "@X" generates a reader for X as a whole.
6789/// - "@X;Y" generates a reader for X as a whole and also readers for the
6790/// leaves of Y.
6791/// - For further examples see the figure below.
6792///
6793/// \image html ttree_makeselector_option_examples.png
6794///
6795/// The generated code in selector.h includes the following:
6796/// - Identification of the original Tree and Input file name
6797/// - Definition of selector class (data and functions)
6798/// - The following class functions:
6799/// - constructor and destructor
6800/// - void Begin(TTree *tree)
6801/// - void SlaveBegin(TTree *tree)
6802/// - void Init(TTree *tree)
6803/// - bool Notify()
6804/// - bool Process(Long64_t entry)
6805/// - void Terminate()
6806/// - void SlaveTerminate()
6807///
6808/// The class selector derives from TSelector.
6809/// The generated code in selector.C includes empty functions defined above.
6810///
6811/// To use this function:
6812///
6813/// - connect your Tree file (eg: `TFile f("myfile.root");`)
6814/// - `T->MakeSelector("myselect");`
6815///
6816/// where T is the name of the Tree in file myfile.root
6817/// and myselect.h, myselect.C the name of the files created by this function.
6818/// In a ROOT session, you can do:
6819/// ~~~ {.cpp}
6820/// root > T->Process("myselect.C")
6821/// ~~~
6823Int_t TTree::MakeSelector(const char* selector, Option_t* option)
6824{
6825 TString opt(option);
6826 if(opt.EqualTo("=legacy", TString::ECaseCompare::kIgnoreCase)) {
6827 return MakeClass(selector, "selector");
6828 } else {
6829 GetPlayer();
6830 if (!fPlayer) return 0;
6831 return fPlayer->MakeReader(selector, option);
6832 }
6833}
6834
6835////////////////////////////////////////////////////////////////////////////////
6836/// Check if adding nbytes to memory we are still below MaxVirtualsize.
6838bool TTree::MemoryFull(Int_t nbytes)
6839{
6840 if ((fTotalBuffers + nbytes) < fMaxVirtualSize) {
6841 return false;
6842 }
6843 return true;
6844}
6845
6846////////////////////////////////////////////////////////////////////////////////
6847/// Static function merging the trees in the TList into a new tree.
6848///
6849/// Trees in the list can be memory or disk-resident trees.
6850/// The new tree is created in the current directory (memory if gROOT).
6852TTree* TTree::MergeTrees(TList* li, Option_t* options)
6853{
6854 if (!li) return nullptr;
6855 TIter next(li);
6856 TTree *newtree = nullptr;
6857 TObject *obj;
6858
6859 while ((obj=next())) {
6860 if (!obj->InheritsFrom(TTree::Class())) continue;
6861 TTree *tree = (TTree*)obj;
6862 Long64_t nentries = tree->GetEntries();
6863 if (nentries == 0) continue;
6864 if (!newtree) {
6865 newtree = (TTree*)tree->CloneTree(-1, options);
6866 if (!newtree) continue;
6867
6868 // Once the cloning is done, separate the trees,
6869 // to avoid as many side-effects as possible
6870 // The list of clones is guaranteed to exist since we
6871 // just cloned the tree.
6872 tree->GetListOfClones()->Remove(newtree);
6873 tree->ResetBranchAddresses();
6874 newtree->ResetBranchAddresses();
6875 continue;
6876 }
6877
6878 newtree->CopyEntries(tree, -1, options, true);
6879 }
6880 if (newtree && newtree->GetTreeIndex()) {
6881 newtree->GetTreeIndex()->Append(nullptr,false); // Force the sorting
6882 }
6883 return newtree;
6884}
6885
6886////////////////////////////////////////////////////////////////////////////////
6887/// Merge the trees in the TList into this tree.
6888///
6889/// Returns the total number of entries in the merged tree.
6892{
6893 if (!li) return 0;
6894 Long64_t storeAutoSave = fAutoSave;
6895 // Disable the autosave as the TFileMerge keeps a list of key and deleting the underlying
6896 // key would invalidate its iteration (or require costly measure to not use the deleted keys).
6897 // Also since this is part of a merging operation, the output file is not as precious as in
6898 // the general case since the input file should still be around.
6899 fAutoSave = 0;
6900 TIter next(li);
6901 TTree *tree;
6902 while ((tree = (TTree*)next())) {
6903 if (tree==this) continue;
6904 if (!tree->InheritsFrom(TTree::Class())) {
6905 Error("Add","Attempt to add object of class: %s to a %s", tree->ClassName(), ClassName());
6906 fAutoSave = storeAutoSave;
6907 return -1;
6908 }
6909
6910 Long64_t nentries = tree->GetEntries();
6911 if (nentries == 0) continue;
6912
6913 CopyEntries(tree, -1, options, true);
6914 }
6915 fAutoSave = storeAutoSave;
6916 return GetEntries();
6917}
6918
6919////////////////////////////////////////////////////////////////////////////////
6920/// Merge the trees in the TList into this tree.
6921/// If info->fIsFirst is true, first we clone this TTree info the directory
6922/// info->fOutputDirectory and then overlay the new TTree information onto
6923/// this TTree object (so that this TTree object is now the appropriate to
6924/// use for further merging).
6925///
6926/// Returns the total number of entries in the merged tree.
6929{
6930 const char *options = info ? info->fOptions.Data() : "";
6931 if (info && info->fIsFirst && info->fOutputDirectory && info->fOutputDirectory->GetFile() != GetCurrentFile()) {
6932 if (GetCurrentFile() == nullptr) {
6933 // In memory TTree, all we need to do is ... write it.
6936 fDirectory->WriteTObject(this);
6937 } else if (info->fOptions.Contains("fast")) {
6939 } else {
6941 TIOFeatures saved_features = fIOFeatures;
6942 TTree *newtree = CloneTree(-1, options);
6943 if (info->fIOFeatures)
6944 fIOFeatures = *(info->fIOFeatures);
6945 else
6946 fIOFeatures = saved_features;
6947 if (newtree) {
6948 newtree->Write();
6949 delete newtree;
6950 }
6951 // Make sure things are really written out to disk before attempting any reading.
6952 info->fOutputDirectory->GetFile()->Flush();
6953 info->fOutputDirectory->ReadTObject(this,this->GetName());
6954 }
6955 }
6956 if (!li) return 0;
6957 Long64_t storeAutoSave = fAutoSave;
6958 // Disable the autosave as the TFileMerge keeps a list of key and deleting the underlying
6959 // key would invalidate its iteration (or require costly measure to not use the deleted keys).
6960 // Also since this is part of a merging operation, the output file is not as precious as in
6961 // the general case since the input file should still be around.
6962 fAutoSave = 0;
6963 TIter next(li);
6964 TTree *tree;
6965 while ((tree = (TTree*)next())) {
6966 if (tree==this) continue;
6967 if (!tree->InheritsFrom(TTree::Class())) {
6968 Error("Add","Attempt to add object of class: %s to a %s", tree->ClassName(), ClassName());
6969 fAutoSave = storeAutoSave;
6970 return -1;
6971 }
6972
6973 CopyEntries(tree, -1, options, true);
6974 }
6975 fAutoSave = storeAutoSave;
6976 return GetEntries();
6977}
6978
6979////////////////////////////////////////////////////////////////////////////////
6980/// Move a cache from a file to the current file in dir.
6981/// if src is null no operation is done, if dir is null or there is no
6982/// current file the cache is deleted.
6985{
6986 if (!src) return;
6987 TFile *dst = (dir && dir != gROOT) ? dir->GetFile() : nullptr;
6988 if (src == dst) return;
6989
6991 if (dst) {
6992 src->SetCacheRead(nullptr,this);
6993 dst->SetCacheRead(pf, this);
6994 } else {
6995 if (pf) {
6996 pf->WaitFinishPrefetch();
6997 }
6998 src->SetCacheRead(nullptr,this);
6999 delete pf;
7000 }
7001}
7002
7003////////////////////////////////////////////////////////////////////////////////
7004/// Copy the content to a new new file, update this TTree with the new
7005/// location information and attach this TTree to the new directory.
7006///
7007/// options: Indicates a basket sorting method, see TTreeCloner::TTreeCloner for
7008/// details
7009///
7010/// If new and old directory are in the same file, the data is untouched,
7011/// this "just" does a call to SetDirectory.
7012/// Equivalent to an "in place" cloning of the TTree.
7013bool TTree::InPlaceClone(TDirectory *newdirectory, const char *options)
7014{
7015 if (!newdirectory) {
7017 SetDirectory(nullptr);
7018 return true;
7019 }
7020 if (newdirectory->GetFile() == GetCurrentFile()) {
7021 SetDirectory(newdirectory);
7022 return true;
7023 }
7024 TTreeCloner cloner(this, newdirectory, options);
7025 if (cloner.IsValid())
7026 return cloner.Exec();
7027 else
7028 return false;
7029}
7030
7031////////////////////////////////////////////////////////////////////////////////
7032/// Function called when loading a new class library.
7034bool TTree::Notify()
7035{
7036 TIter next(GetListOfLeaves());
7037 TLeaf* leaf = nullptr;
7038 while ((leaf = (TLeaf*) next())) {
7039 leaf->Notify();
7040 leaf->GetBranch()->Notify();
7041 }
7042 return true;
7043}
7044
7045////////////////////////////////////////////////////////////////////////////////
7046/// This function may be called after having filled some entries in a Tree.
7047/// Using the information in the existing branch buffers, it will reassign
7048/// new branch buffer sizes to optimize time and memory.
7049///
7050/// The function computes the best values for branch buffer sizes such that
7051/// the total buffer sizes is less than maxMemory and nearby entries written
7052/// at the same time.
7053/// In case the branch compression factor for the data written so far is less
7054/// than compMin, the compression is disabled.
7055///
7056/// if option ="d" an analysis report is printed.
7058void TTree::OptimizeBaskets(ULong64_t maxMemory, Float_t minComp, Option_t *option)
7059{
7060 //Flush existing baskets if the file is writable
7061 if (this->GetDirectory()->IsWritable()) this->FlushBasketsImpl();
7062
7063 TString opt( option );
7064 opt.ToLower();
7065 bool pDebug = opt.Contains("d");
7066 TObjArray *leaves = this->GetListOfLeaves();
7067 Int_t nleaves = leaves->GetEntries();
7068 Double_t treeSize = (Double_t)this->GetTotBytes();
7069
7070 if (nleaves == 0 || treeSize == 0) {
7071 // We're being called too early, we really have nothing to do ...
7072 return;
7073 }
7074 Double_t aveSize = treeSize/nleaves;
7075 UInt_t bmin = 512;
7076 UInt_t bmax = 256000;
7077 Double_t memFactor = 1;
7078 Int_t i, oldMemsize,newMemsize,oldBaskets,newBaskets;
7079 i = oldMemsize = newMemsize = oldBaskets = newBaskets = 0;
7080
7081 //we make two passes
7082 //one pass to compute the relative branch buffer sizes
7083 //a second pass to compute the absolute values
7084 for (Int_t pass =0;pass<2;pass++) {
7085 oldMemsize = 0; //to count size of baskets in memory with old buffer size
7086 newMemsize = 0; //to count size of baskets in memory with new buffer size
7087 oldBaskets = 0; //to count number of baskets with old buffer size
7088 newBaskets = 0; //to count number of baskets with new buffer size
7089 for (i=0;i<nleaves;i++) {
7090 TLeaf *leaf = (TLeaf*)leaves->At(i);
7091 TBranch *branch = leaf->GetBranch();
7092 Double_t totBytes = (Double_t)branch->GetTotBytes();
7093 Double_t idealFactor = totBytes/aveSize;
7094 UInt_t sizeOfOneEntry;
7095 if (branch->GetEntries() == 0) {
7096 // There is no data, so let's make a guess ...
7097 sizeOfOneEntry = aveSize;
7098 } else {
7099 sizeOfOneEntry = 1+(UInt_t)(totBytes / (Double_t)branch->GetEntries());
7100 }
7101 Int_t oldBsize = branch->GetBasketSize();
7102 oldMemsize += oldBsize;
7103 oldBaskets += 1+Int_t(totBytes/oldBsize);
7104 Int_t nb = branch->GetListOfBranches()->GetEntries();
7105 if (nb > 0) {
7106 newBaskets += 1+Int_t(totBytes/oldBsize);
7107 continue;
7108 }
7109 Double_t bsize = oldBsize*idealFactor*memFactor; //bsize can be very large !
7110 if (bsize < 0) bsize = bmax;
7111 if (bsize > bmax) bsize = bmax;
7112 UInt_t newBsize = UInt_t(bsize);
7113 if (pass) { // only on the second pass so that it doesn't interfere with scaling
7114 // If there is an entry offset, it will be stored in the same buffer as the object data; hence,
7115 // we must bump up the size of the branch to account for this extra footprint.
7116 // If fAutoFlush is not set yet, let's assume that it is 'in the process of being set' to
7117 // the value of GetEntries().
7118 Long64_t clusterSize = (fAutoFlush > 0) ? fAutoFlush : branch->GetEntries();
7119 if (branch->GetEntryOffsetLen()) {
7120 newBsize = newBsize + (clusterSize * sizeof(Int_t) * 2);
7121 }
7122 // We used ATLAS fully-split xAOD for testing, which is a rather unbalanced TTree, 10K branches,
7123 // with 8K having baskets smaller than 512 bytes. To achieve good I/O performance ATLAS uses auto-flush 100,
7124 // resulting in the smallest baskets being ~300-400 bytes, so this change increases their memory by about 8k*150B =~ 1MB,
7125 // at the same time it significantly reduces the number of total baskets because it ensures that all 100 entries can be
7126 // stored in a single basket (the old optimization tended to make baskets too small). In a toy example with fixed sized
7127 // structures we found a factor of 2 fewer baskets needed in the new scheme.
7128 // rounds up, increases basket size to ensure all entries fit into single basket as intended
7129 newBsize = newBsize - newBsize%512 + 512;
7130 }
7131 if (newBsize < sizeOfOneEntry) newBsize = sizeOfOneEntry;
7132 if (newBsize < bmin) newBsize = bmin;
7133 if (newBsize > 10000000) newBsize = bmax;
7134 if (pass) {
7135 if (pDebug) Info("OptimizeBaskets", "Changing buffer size from %6d to %6d bytes for %s\n",oldBsize,newBsize,branch->GetName());
7136 branch->SetBasketSize(newBsize);
7137 }
7138 newMemsize += newBsize;
7139 // For this number to be somewhat accurate when newBsize is 'low'
7140 // we do not include any space for meta data in the requested size (newBsize) even-though SetBasketSize will
7141 // not let it be lower than 100+TBranch::fEntryOffsetLen.
7142 newBaskets += 1+Int_t(totBytes/newBsize);
7143 if (pass == 0) continue;
7144 //Reset the compression level in case the compression factor is small
7145 Double_t comp = 1;
7146 if (branch->GetZipBytes() > 0) comp = totBytes/Double_t(branch->GetZipBytes());
7147 if (comp > 1 && comp < minComp) {
7148 if (pDebug) Info("OptimizeBaskets", "Disabling compression for branch : %s\n",branch->GetName());
7150 }
7151 }
7152 // coverity[divide_by_zero] newMemsize can not be zero as there is at least one leaf
7153 memFactor = Double_t(maxMemory)/Double_t(newMemsize);
7154 if (memFactor > 100) memFactor = 100;
7155 Double_t bmin_new = bmin*memFactor;
7156 Double_t bmax_new = bmax*memFactor;
7157 static const UInt_t hardmax = 1*1024*1024*1024; // Really, really never give more than 1Gb to a single buffer.
7158
7159 // Really, really never go lower than 8 bytes (we use this number
7160 // so that the calculation of the number of basket is consistent
7161 // but in fact SetBasketSize will not let the size go below
7162 // TBranch::fEntryOffsetLen + (100 + strlen(branch->GetName())
7163 // (The 2nd part being a slight over estimate of the key length.
7164 static const UInt_t hardmin = 8;
7165 bmin = (bmin_new > hardmax) ? hardmax : ( bmin_new < hardmin ? hardmin : (UInt_t)bmin_new );
7166 bmax = (bmax_new > hardmax) ? bmin : (UInt_t)bmax_new;
7167 }
7168 if (pDebug) {
7169 Info("OptimizeBaskets", "oldMemsize = %d, newMemsize = %d\n",oldMemsize, newMemsize);
7170 Info("OptimizeBaskets", "oldBaskets = %d, newBaskets = %d\n",oldBaskets, newBaskets);
7171 }
7172}
7173
7174////////////////////////////////////////////////////////////////////////////////
7175/// Interface to the Principal Components Analysis class.
7176///
7177/// Create an instance of TPrincipal
7178///
7179/// Fill it with the selected variables
7180///
7181/// - if option "n" is specified, the TPrincipal object is filled with
7182/// normalized variables.
7183/// - If option "p" is specified, compute the principal components
7184/// - If option "p" and "d" print results of analysis
7185/// - If option "p" and "h" generate standard histograms
7186/// - If option "p" and "c" generate code of conversion functions
7187/// - return a pointer to the TPrincipal object. It is the user responsibility
7188/// - to delete this object.
7189/// - The option default value is "np"
7190///
7191/// see TTree::Draw for explanation of the other parameters.
7192///
7193/// The created object is named "principal" and a reference to it
7194/// is added to the list of specials Root objects.
7195/// you can retrieve a pointer to the created object via:
7196/// ~~~ {.cpp}
7197/// TPrincipal *principal =
7198/// (TPrincipal*)gROOT->GetListOfSpecials()->FindObject("principal");
7199/// ~~~
7201TPrincipal* TTree::Principal(const char* varexp, const char* selection, Option_t* option, Long64_t nentries, Long64_t firstentry)
7202{
7203 GetPlayer();
7204 if (fPlayer) {
7205 return fPlayer->Principal(varexp, selection, option, nentries, firstentry);
7206 }
7207 return nullptr;
7208}
7209
7210////////////////////////////////////////////////////////////////////////////////
7211/// Print a summary of the tree contents.
7212///
7213/// - If option contains "all" friend trees are also printed.
7214/// - If option contains "toponly" only the top level branches are printed.
7215/// - If option contains "clusters" information about the cluster of baskets is printed.
7216///
7217/// Wildcarding can be used to print only a subset of the branches, e.g.,
7218/// `T.Print("Elec*")` will print all branches with name starting with "Elec".
7220void TTree::Print(Option_t* option) const
7221{
7222 // We already have been visited while recursively looking
7223 // through the friends tree, let's return.
7224 if (kPrint & fFriendLockStatus) {
7225 return;
7226 }
7227 Int_t s = 0;
7228 Int_t skey = 0;
7229 if (fDirectory) {
7230 TKey* key = fDirectory->GetKey(GetName());
7231 if (key) {
7232 skey = key->GetKeylen();
7233 s = key->GetNbytes();
7234 }
7235 }
7236 Long64_t total = skey;
7237 Long64_t zipBytes = GetZipBytes();
7238 if (zipBytes > 0) {
7239 total += GetTotBytes();
7240 }
7242 TTree::Class()->WriteBuffer(b, (TTree*) this);
7243 total += b.Length();
7244 Long64_t file = zipBytes + s;
7245 Float_t cx = 1;
7246 if (zipBytes) {
7247 cx = (GetTotBytes() + 0.00001) / zipBytes;
7248 }
7249 Printf("******************************************************************************");
7250 Printf("*Tree :%-10s: %-54s *", GetName(), GetTitle());
7251 Printf("*Entries : %8lld : Total = %15lld bytes File Size = %10lld *", fEntries, total, file);
7252 Printf("* : : Tree compression factor = %6.2f *", cx);
7253 Printf("******************************************************************************");
7254
7255 // Avoid many check of option validity
7256 if (!option)
7257 option = "";
7258
7259 if (strncmp(option,"clusters",strlen("clusters"))==0) {
7260 Printf("%-16s %-16s %-16s %8s %20s",
7261 "Cluster Range #", "Entry Start", "Last Entry", "Size", "Number of clusters");
7262 Int_t index= 0;
7263 Long64_t clusterRangeStart = 0;
7264 Long64_t totalClusters = 0;
7265 bool estimated = false;
7266 bool unknown = false;
7267 auto printer = [this, &totalClusters, &estimated, &unknown](Int_t ind, Long64_t start, Long64_t end, Long64_t recordedSize) {
7268 Long64_t nclusters = 0;
7269 if (recordedSize > 0) {
7270 nclusters = (1 + end - start) / recordedSize;
7271 Printf("%-16d %-16lld %-16lld %8lld %10lld",
7272 ind, start, end, recordedSize, nclusters);
7273 } else {
7274 // NOTE: const_cast ... DO NOT Merge for now
7275 TClusterIterator iter((TTree*)this, start);
7276 iter.Next();
7277 auto estimated_size = iter.GetNextEntry() - start;
7278 if (estimated_size > 0) {
7279 nclusters = (1 + end - start) / estimated_size;
7280 Printf("%-16d %-16lld %-16lld %8lld %10lld (estimated)",
7281 ind, start, end, recordedSize, nclusters);
7282 estimated = true;
7283 } else {
7284 Printf("%-16d %-16lld %-16lld %8lld (unknown)",
7285 ind, start, end, recordedSize);
7286 unknown = true;
7287 }
7288 }
7289 start = end + 1;
7290 totalClusters += nclusters;
7291 };
7292 if (fNClusterRange) {
7293 for( ; index < fNClusterRange; ++index) {
7294 printer(index, clusterRangeStart, fClusterRangeEnd[index], fClusterSize[index]);
7295 clusterRangeStart = fClusterRangeEnd[index] + 1;
7296 }
7297 }
7298 printer(index, clusterRangeStart, fEntries - 1, fAutoFlush);
7299 if (unknown) {
7300 Printf("Total number of clusters: (unknown)");
7301 } else {
7302 Printf("Total number of clusters: %lld %s", totalClusters, estimated ? "(estimated)" : "");
7303 }
7304 return;
7305 }
7306
7307 Int_t nl = const_cast<TTree*>(this)->GetListOfLeaves()->GetEntries();
7308 Int_t l;
7309 TBranch* br = nullptr;
7310 TLeaf* leaf = nullptr;
7311 if (strstr(option, "toponly")) {
7312 Long64_t *count = new Long64_t[nl];
7313 Int_t keep =0;
7314 for (l=0;l<nl;l++) {
7315 leaf = (TLeaf *)const_cast<TTree*>(this)->GetListOfLeaves()->At(l);
7316 br = leaf->GetBranch();
7317 if (strchr(br->GetName(),'.')) {
7318 count[l] = -1;
7319 count[keep] += br->GetZipBytes();
7320 } else {
7321 keep = l;
7322 count[keep] = br->GetZipBytes();
7323 }
7324 }
7325 for (l=0;l<nl;l++) {
7326 if (count[l] < 0) continue;
7327 leaf = (TLeaf *)const_cast<TTree*>(this)->GetListOfLeaves()->At(l);
7328 br = leaf->GetBranch();
7329 Printf("branch: %-20s %9lld\n",br->GetName(),count[l]);
7330 }
7331 delete [] count;
7332 } else {
7333 TString reg = "*";
7334 if (strlen(option) && strchr(option,'*')) reg = option;
7335 TRegexp re(reg,true);
7336 TIter next(const_cast<TTree*>(this)->GetListOfBranches());
7338 while ((br= (TBranch*)next())) {
7339 TString st = br->GetName();
7340 st.ReplaceAll("/","_");
7341 if (st.Index(re) == kNPOS) continue;
7342 br->Print(option);
7343 }
7344 }
7345
7346 //print TRefTable (if one)
7348
7349 //print friends if option "all"
7350 if (!fFriends || !strstr(option,"all")) return;
7351 TIter nextf(fFriends);
7352 TFriendLock lock(const_cast<TTree*>(this),kPrint);
7353 TFriendElement *fr;
7354 while ((fr = (TFriendElement*)nextf())) {
7355 TTree * t = fr->GetTree();
7356 if (t) t->Print(option);
7357 }
7358}
7359
7360////////////////////////////////////////////////////////////////////////////////
7361/// Print statistics about the TreeCache for this tree.
7362/// Like:
7363/// ~~~ {.cpp}
7364/// ******TreeCache statistics for file: cms2.root ******
7365/// Reading 73921562 bytes in 716 transactions
7366/// Average transaction = 103.242405 Kbytes
7367/// Number of blocks in current cache: 202, total size : 6001193
7368/// ~~~
7369/// if option = "a" the list of blocks in the cache is printed
7372{
7373 TFile *f = GetCurrentFile();
7374 if (!f) return;
7375 TTreeCache *tc = GetReadCache(f);
7376 if (tc) tc->Print(option);
7377}
7378
7379////////////////////////////////////////////////////////////////////////////////
7380/// Process this tree executing the TSelector code in the specified filename.
7381/// The return value is -1 in case of error and TSelector::GetStatus() in
7382/// in case of success.
7383///
7384/// The code in filename is loaded (interpreted or compiled, see below),
7385/// filename must contain a valid class implementation derived from TSelector,
7386/// where TSelector has the following member functions:
7387///
7388/// - `Begin()`: called every time a loop on the tree starts,
7389/// a convenient place to create your histograms.
7390/// - `SlaveBegin()`: called after Begin(), when on PROOF called only on the
7391/// slave servers.
7392/// - `Process()`: called for each event, in this function you decide what
7393/// to read and fill your histograms.
7394/// - `SlaveTerminate`: called at the end of the loop on the tree, when on PROOF
7395/// called only on the slave servers.
7396/// - `Terminate()`: called at the end of the loop on the tree,
7397/// a convenient place to draw/fit your histograms.
7398///
7399/// If filename is of the form file.C, the file will be interpreted.
7400///
7401/// If filename is of the form file.C++, the file file.C will be compiled
7402/// and dynamically loaded.
7403///
7404/// If filename is of the form file.C+, the file file.C will be compiled
7405/// and dynamically loaded. At next call, if file.C is older than file.o
7406/// and file.so, the file.C is not compiled, only file.so is loaded.
7407///
7408/// ## NOTE1
7409///
7410/// It may be more interesting to invoke directly the other Process function
7411/// accepting a TSelector* as argument.eg
7412/// ~~~ {.cpp}
7413/// MySelector *selector = (MySelector*)TSelector::GetSelector(filename);
7414/// selector->CallSomeFunction(..);
7415/// mytree.Process(selector,..);
7416/// ~~~
7417/// ## NOTE2
7418//
7419/// One should not call this function twice with the same selector file
7420/// in the same script. If this is required, proceed as indicated in NOTE1,
7421/// by getting a pointer to the corresponding TSelector,eg
7422///
7423/// ### Workaround 1
7424///
7425/// ~~~ {.cpp}
7426/// void stubs1() {
7427/// TSelector *selector = TSelector::GetSelector("h1test.C");
7428/// TFile *f1 = new TFile("stubs_nood_le1.root");
7429/// TTree *h1 = (TTree*)f1->Get("h1");
7430/// h1->Process(selector);
7431/// TFile *f2 = new TFile("stubs_nood_le1_coarse.root");
7432/// TTree *h2 = (TTree*)f2->Get("h1");
7433/// h2->Process(selector);
7434/// }
7435/// ~~~
7436/// or use ACLIC to compile the selector
7437///
7438/// ### Workaround 2
7439///
7440/// ~~~ {.cpp}
7441/// void stubs2() {
7442/// TFile *f1 = new TFile("stubs_nood_le1.root");
7443/// TTree *h1 = (TTree*)f1->Get("h1");
7444/// h1->Process("h1test.C+");
7445/// TFile *f2 = new TFile("stubs_nood_le1_coarse.root");
7446/// TTree *h2 = (TTree*)f2->Get("h1");
7447/// h2->Process("h1test.C+");
7448/// }
7449/// ~~~
7452{
7453 GetPlayer();
7454 if (fPlayer) {
7455 return fPlayer->Process(filename, option, nentries, firstentry);
7456 }
7457 return -1;
7458}
7459
7460////////////////////////////////////////////////////////////////////////////////
7461/// Process this tree executing the code in the specified selector.
7462/// The return value is -1 in case of error and TSelector::GetStatus() in
7463/// in case of success.
7464///
7465/// The TSelector class has the following member functions:
7466///
7467/// - `Begin()`: called every time a loop on the tree starts,
7468/// a convenient place to create your histograms.
7469/// - `SlaveBegin()`: called after Begin(), when on PROOF called only on the
7470/// slave servers.
7471/// - `Process()`: called for each event, in this function you decide what
7472/// to read and fill your histograms.
7473/// - `SlaveTerminate`: called at the end of the loop on the tree, when on PROOF
7474/// called only on the slave servers.
7475/// - `Terminate()`: called at the end of the loop on the tree,
7476/// a convenient place to draw/fit your histograms.
7477///
7478/// If the Tree (Chain) has an associated EventList, the loop is on the nentries
7479/// of the EventList, starting at firstentry, otherwise the loop is on the
7480/// specified Tree entries.
7483{
7484 GetPlayer();
7485 if (fPlayer) {
7486 return fPlayer->Process(selector, option, nentries, firstentry);
7487 }
7488 return -1;
7489}
7490
7491////////////////////////////////////////////////////////////////////////////////
7492/// Make a projection of a tree using selections.
7493///
7494/// Depending on the value of varexp (described in Draw) a 1-D, 2-D, etc.,
7495/// projection of the tree will be filled in histogram hname.
7496/// Note that the dimension of hname must match with the dimension of varexp.
7497///
7499Long64_t TTree::Project(const char* hname, const char* varexp, const char* selection, Option_t* option, Long64_t nentries, Long64_t firstentry)
7500{
7501 TString var;
7502 var.Form("%s>>%s", varexp, hname);
7503 TString opt("goff");
7504 if (option) {
7505 opt.Form("%sgoff", option);
7506 }
7507 Long64_t nsel = Draw(var, selection, opt, nentries, firstentry);
7508 return nsel;
7509}
7510
7511////////////////////////////////////////////////////////////////////////////////
7512/// Loop over entries and return a TSQLResult object containing entries following selection.
7514TSQLResult* TTree::Query(const char* varexp, const char* selection, Option_t* option, Long64_t nentries, Long64_t firstentry)
7515{
7516 GetPlayer();
7517 if (fPlayer) {
7518 return fPlayer->Query(varexp, selection, option, nentries, firstentry);
7519 }
7520 return nullptr;
7521}
7522
7523////////////////////////////////////////////////////////////////////////////////
7524/// Create or simply read branches from filename.
7525///
7526/// if branchDescriptor = "" (default), it is assumed that the Tree descriptor
7527/// is given in the first line of the file with a syntax like
7528/// ~~~ {.cpp}
7529/// A/D:Table[2]/F:Ntracks/I:astring/C
7530/// ~~~
7531/// otherwise branchDescriptor must be specified with the above syntax.
7532///
7533/// - If the type of the first variable is not specified, it is assumed to be "/F"
7534/// - If the type of any other variable is not specified, the type of the previous
7535/// variable is assumed. eg
7536/// - `x:y:z` (all variables are assumed of type "F")
7537/// - `x/D:y:z` (all variables are of type "D")
7538/// - `x:y/D:z` (x is type "F", y and z of type "D")
7539///
7540/// delimiter allows for the use of another delimiter besides whitespace.
7541/// This provides support for direct import of common data file formats
7542/// like csv. If delimiter != ' ' and branchDescriptor == "", then the
7543/// branch description is taken from the first line in the file, but
7544/// delimiter is used for the branch names tokenization rather than ':'.
7545/// Note however that if the values in the first line do not use the
7546/// /[type] syntax, all variables are assumed to be of type "F".
7547/// If the filename ends with extensions .csv or .CSV and a delimiter is
7548/// not specified (besides ' '), the delimiter is automatically set to ','.
7549///
7550/// Lines in the input file starting with "#" are ignored. Leading whitespace
7551/// for each column data is skipped. Empty lines are skipped.
7552///
7553/// A TBranch object is created for each variable in the expression.
7554/// The total number of rows read from the file is returned.
7555///
7556/// ## FILLING a TTree WITH MULTIPLE INPUT TEXT FILES
7557///
7558/// To fill a TTree with multiple input text files, proceed as indicated above
7559/// for the first input file and omit the second argument for subsequent calls
7560/// ~~~ {.cpp}
7561/// T.ReadFile("file1.dat","branch descriptor");
7562/// T.ReadFile("file2.dat");
7563/// ~~~
7565Long64_t TTree::ReadFile(const char* filename, const char* branchDescriptor, char delimiter)
7566{
7567 if (!filename || !*filename) {
7568 Error("ReadFile","File name not specified");
7569 return 0;
7570 }
7571
7572 std::ifstream in;
7573 in.open(filename);
7574 if (!in.good()) {
7575 Error("ReadFile","Cannot open file: %s",filename);
7576 return 0;
7577 }
7578 const char* ext = strrchr(filename, '.');
7579 if(ext && ((strcmp(ext, ".csv") == 0) || (strcmp(ext, ".CSV") == 0)) && delimiter == ' ') {
7580 delimiter = ',';
7581 }
7582 return ReadStream(in, branchDescriptor, delimiter);
7583}
7584
7585////////////////////////////////////////////////////////////////////////////////
7586/// Determine which newline this file is using.
7587/// Return '\\r' for Windows '\\r\\n' as that already terminates.
7589char TTree::GetNewlineValue(std::istream &inputStream)
7590{
7591 Long_t inPos = inputStream.tellg();
7592 char newline = '\n';
7593 while(true) {
7594 char c = 0;
7595 inputStream.get(c);
7596 if(!inputStream.good()) {
7597 Error("ReadStream","Error reading stream: no newline found.");
7598 return 0;
7599 }
7600 if(c == newline) break;
7601 if(c == '\r') {
7602 newline = '\r';
7603 break;
7604 }
7605 }
7606 inputStream.clear();
7607 inputStream.seekg(inPos);
7608 return newline;
7609}
7610
7611////////////////////////////////////////////////////////////////////////////////
7612/// Create or simply read branches from an input stream.
7613///
7614/// \see reference information for TTree::ReadFile
7616Long64_t TTree::ReadStream(std::istream& inputStream, const char *branchDescriptor, char delimiter)
7617{
7618 char newline = 0;
7619 std::stringstream ss;
7620 std::istream *inTemp;
7621 Long_t inPos = inputStream.tellg();
7622 if (!inputStream.good()) {
7623 Error("ReadStream","Error reading stream");
7624 return 0;
7625 }
7626 if (inPos == -1) {
7627 ss << std::cin.rdbuf();
7628 newline = GetNewlineValue(ss);
7629 inTemp = &ss;
7630 } else {
7631 newline = GetNewlineValue(inputStream);
7632 inTemp = &inputStream;
7633 }
7634 std::istream& in = *inTemp;
7635 Long64_t nlines = 0;
7636
7637 TBranch *branch = nullptr;
7638 Int_t nbranches = fBranches.GetEntries();
7639 if (nbranches == 0) {
7640 char *bdname = new char[4000];
7641 char *bd = new char[100000];
7642 Int_t nch = 0;
7643 if (branchDescriptor) nch = strlen(branchDescriptor);
7644 // branch Descriptor is null, read its definition from the first line in the file
7645 if (!nch) {
7646 do {
7647 in.getline(bd, 100000, newline);
7648 if (!in.good()) {
7649 delete [] bdname;
7650 delete [] bd;
7651 Error("ReadStream","Error reading stream");
7652 return 0;
7653 }
7654 char *cursor = bd;
7655 while( isspace(*cursor) && *cursor != '\n' && *cursor != '\0') {
7656 ++cursor;
7657 }
7658 if (*cursor != '#' && *cursor != '\n' && *cursor != '\0') {
7659 break;
7660 }
7661 } while (true);
7662 ++nlines;
7663 nch = strlen(bd);
7664 } else {
7665 strlcpy(bd,branchDescriptor,100000);
7666 }
7667
7668 //parse the branch descriptor and create a branch for each element
7669 //separated by ":"
7670 void *address = &bd[90000];
7671 char *bdcur = bd;
7672 TString desc="", olddesc="F";
7673 char bdelim = ':';
7674 if(delimiter != ' ') {
7675 bdelim = delimiter;
7676 if (strchr(bdcur,bdelim)==nullptr && strchr(bdcur,':') != nullptr) {
7677 // revert to the default
7678 bdelim = ':';
7679 }
7680 }
7681 while (bdcur) {
7682 char *colon = strchr(bdcur,bdelim);
7683 if (colon) *colon = 0;
7684 strlcpy(bdname,bdcur,4000);
7685 char *slash = strchr(bdname,'/');
7686 if (slash) {
7687 *slash = 0;
7688 desc = bdcur;
7689 olddesc = slash+1;
7690 } else {
7691 desc.Form("%s/%s",bdname,olddesc.Data());
7692 }
7693 char *bracket = strchr(bdname,'[');
7694 if (bracket) {
7695 *bracket = 0;
7696 }
7697 branch = new TBranch(this,bdname,address,desc.Data(),32000);
7698 if (branch->IsZombie()) {
7699 delete branch;
7700 Warning("ReadStream","Illegal branch definition: %s",bdcur);
7701 } else {
7702 fBranches.Add(branch);
7703 branch->SetAddress(nullptr);
7704 }
7705 if (!colon)break;
7706 bdcur = colon+1;
7707 }
7708 delete [] bdname;
7709 delete [] bd;
7710 }
7711
7712 nbranches = fBranches.GetEntries();
7713
7714 if (gDebug > 1) {
7715 Info("ReadStream", "Will use branches:");
7716 for (int i = 0 ; i < nbranches; ++i) {
7717 TBranch* br = (TBranch*) fBranches.At(i);
7718 Info("ReadStream", " %s: %s [%s]", br->GetName(),
7719 br->GetTitle(), br->GetListOfLeaves()->At(0)->IsA()->GetName());
7720 }
7721 if (gDebug > 3) {
7722 Info("ReadStream", "Dumping read tokens, format:");
7723 Info("ReadStream", "LLLLL:BBB:gfbe:GFBE:T");
7724 Info("ReadStream", " L: line number");
7725 Info("ReadStream", " B: branch number");
7726 Info("ReadStream", " gfbe: good / fail / bad / eof of token");
7727 Info("ReadStream", " GFBE: good / fail / bad / eof of file");
7728 Info("ReadStream", " T: Token being read");
7729 }
7730 }
7731
7732 //loop on all lines in the file
7733 Long64_t nGoodLines = 0;
7734 std::string line;
7735 const char sDelimBuf[2] = { delimiter, 0 };
7736 const char* sDelim = sDelimBuf;
7737 if (delimiter == ' ') {
7738 // ' ' really means whitespace
7739 sDelim = "[ \t]";
7740 }
7741 while(in.good()) {
7742 if (newline == '\r' && in.peek() == '\n') {
7743 // Windows, skip '\n':
7744 in.get();
7745 }
7746 std::getline(in, line, newline);
7747 ++nlines;
7748
7749 TString sLine(line);
7750 sLine = sLine.Strip(TString::kLeading); // skip leading whitespace
7751 if (sLine.IsNull()) {
7752 if (gDebug > 2) {
7753 Info("ReadStream", "Skipping empty line number %lld", nlines);
7754 }
7755 continue; // silently skip empty lines
7756 }
7757 if (sLine[0] == '#') {
7758 if (gDebug > 2) {
7759 Info("ReadStream", "Skipping comment line number %lld: '%s'",
7760 nlines, line.c_str());
7761 }
7762 continue;
7763 }
7764 if (gDebug > 2) {
7765 Info("ReadStream", "Parsing line number %lld: '%s'",
7766 nlines, line.c_str());
7767 }
7768
7769 // Loop on branches and read the branch values into their buffer
7770 branch = nullptr;
7771 TString tok; // one column's data
7772 TString leafData; // leaf data, possibly multiple tokens for e.g. /I[2]
7773 std::stringstream sToken; // string stream feeding leafData into leaves
7774 Ssiz_t pos = 0;
7775 Int_t iBranch = 0;
7776 bool goodLine = true; // whether the row can be filled into the tree
7777 Int_t remainingLeafLen = 0; // remaining columns for the current leaf
7778 while (goodLine && iBranch < nbranches
7779 && sLine.Tokenize(tok, pos, sDelim)) {
7780 tok = tok.Strip(TString::kLeading); // skip leading whitespace
7781 if (tok.IsNull() && delimiter == ' ') {
7782 // 1 2 should not be interpreted as 1,,,2 but 1, 2.
7783 // Thus continue until we have a non-empty token.
7784 continue;
7785 }
7786
7787 if (!remainingLeafLen) {
7788 // next branch!
7789 branch = (TBranch*)fBranches.At(iBranch);
7790 }
7791 TLeaf *leaf = (TLeaf*)branch->GetListOfLeaves()->At(0);
7792 if (!remainingLeafLen) {
7793 remainingLeafLen = leaf->GetLen();
7794 if (leaf->GetMaximum() > 0) {
7795 // This is a dynamic leaf length, i.e. most likely a TLeafC's
7796 // string size. This still translates into one token:
7797 remainingLeafLen = 1;
7798 }
7799
7800 leafData = tok;
7801 } else {
7802 // append token to laf data:
7803 leafData += " ";
7804 leafData += tok;
7805 }
7806 --remainingLeafLen;
7807 if (remainingLeafLen) {
7808 // need more columns for this branch:
7809 continue;
7810 }
7811 ++iBranch;
7812
7813 // initialize stringstream with token
7814 sToken.clear();
7815 sToken.seekp(0, std::ios_base::beg);
7816 sToken.str(leafData.Data());
7817 sToken.seekg(0, std::ios_base::beg);
7818 leaf->ReadValue(sToken, 0 /* 0 = "all" */);
7819 if (gDebug > 3) {
7820 Info("ReadStream", "%5lld:%3d:%d%d%d%d:%d%d%d%d:%s",
7821 nlines, iBranch,
7822 (int)sToken.good(), (int)sToken.fail(),
7823 (int)sToken.bad(), (int)sToken.eof(),
7824 (int)in.good(), (int)in.fail(),
7825 (int)in.bad(), (int)in.eof(),
7826 sToken.str().c_str());
7827 }
7828
7829 // Error handling
7830 if (sToken.bad()) {
7831 // How could that happen for a stringstream?
7832 Warning("ReadStream",
7833 "Buffer error while reading data for branch %s on line %lld",
7834 branch->GetName(), nlines);
7835 } else if (!sToken.eof()) {
7836 if (sToken.fail()) {
7837 Warning("ReadStream",
7838 "Couldn't read formatted data in \"%s\" for branch %s on line %lld; ignoring line",
7839 tok.Data(), branch->GetName(), nlines);
7840 goodLine = false;
7841 } else {
7842 std::string remainder;
7843 std::getline(sToken, remainder, newline);
7844 if (!remainder.empty()) {
7845 Warning("ReadStream",
7846 "Ignoring trailing \"%s\" while reading data for branch %s on line %lld",
7847 remainder.c_str(), branch->GetName(), nlines);
7848 }
7849 }
7850 }
7851 } // tokenizer loop
7852
7853 if (iBranch < nbranches) {
7854 Warning("ReadStream",
7855 "Read too few columns (%d < %d) in line %lld; ignoring line",
7856 iBranch, nbranches, nlines);
7857 goodLine = false;
7858 } else if (pos != kNPOS) {
7859 sLine = sLine.Strip(TString::kTrailing);
7860 if (pos < sLine.Length()) {
7861 Warning("ReadStream",
7862 "Ignoring trailing \"%s\" while reading line %lld",
7863 sLine.Data() + pos - 1 /* also print delimiter */,
7864 nlines);
7865 }
7866 }
7867
7868 //we are now ready to fill the tree
7869 if (goodLine) {
7870 Fill();
7871 ++nGoodLines;
7872 }
7873 }
7874
7875 return nGoodLines;
7876}
7877
7878////////////////////////////////////////////////////////////////////////////////
7879/// Make sure that obj (which is being deleted or will soon be) is no
7880/// longer referenced by this TTree.
7883{
7884 if (obj == fEventList) {
7885 fEventList = nullptr;
7886 }
7887 if (obj == fEntryList) {
7888 fEntryList = nullptr;
7889 }
7890 if (fUserInfo) {
7892 }
7893 if (fPlayer == obj) {
7894 fPlayer = nullptr;
7895 }
7896 if (fTreeIndex == obj) {
7897 fTreeIndex = nullptr;
7898 }
7899 if (fAliases == obj) {
7900 fAliases = nullptr;
7901 } else if (fAliases) {
7903 }
7904 if (fFriends == obj) {
7905 fFriends = nullptr;
7906 } else if (fFriends) {
7908 }
7909}
7910
7911////////////////////////////////////////////////////////////////////////////////
7912/// Refresh contents of this tree and its branches from the current status on disk.
7913///
7914/// One can call this function in case the tree file is being
7915/// updated by another process.
7917void TTree::Refresh()
7918{
7919 if (!fDirectory->GetFile()) {
7920 return;
7921 }
7923 fDirectory->Remove(this);
7924 TTree* tree; fDirectory->GetObject(GetName(),tree);
7925 if (!tree) {
7926 return;
7927 }
7928 //copy info from tree header into this Tree
7929 fEntries = 0;
7930 fNClusterRange = 0;
7931 ImportClusterRanges(tree);
7932
7933 fAutoSave = tree->fAutoSave;
7934 fEntries = tree->fEntries;
7935 fTotBytes = tree->GetTotBytes();
7936 fZipBytes = tree->GetZipBytes();
7937 fSavedBytes = tree->fSavedBytes;
7938 fTotalBuffers = tree->fTotalBuffers.load();
7939
7940 //loop on all branches and update them
7941 Int_t nleaves = fLeaves.GetEntriesFast();
7942 for (Int_t i = 0; i < nleaves; i++) {
7943 TLeaf* leaf = (TLeaf*) fLeaves.UncheckedAt(i);
7944 TBranch* branch = (TBranch*) leaf->GetBranch();
7945 branch->Refresh(tree->GetBranch(branch->GetName()));
7946 }
7947 fDirectory->Remove(tree);
7948 fDirectory->Append(this);
7949 delete tree;
7950 tree = nullptr;
7951}
7952
7953////////////////////////////////////////////////////////////////////////////////
7954/// Record a TFriendElement that we need to warn when the chain switches to
7955/// a new file (typically this is because this chain is a friend of another
7956/// TChain)
7959{
7960 if (!fExternalFriends)
7961 fExternalFriends = new TList();
7962 fExternalFriends->Add(fe);
7963}
7964
7965
7966////////////////////////////////////////////////////////////////////////////////
7967/// Removes external friend
7970{
7972}
7973
7974
7975////////////////////////////////////////////////////////////////////////////////
7976/// Remove a friend from the list of friends.
7978void TTree::RemoveFriend(TTree* oldFriend)
7979{
7980 // We already have been visited while recursively looking
7981 // through the friends tree, let return
7983 return;
7984 }
7985 if (!fFriends) {
7986 return;
7987 }
7988 TFriendLock lock(this, kRemoveFriend);
7989 TIter nextf(fFriends);
7990 TFriendElement* fe = nullptr;
7991 while ((fe = (TFriendElement*) nextf())) {
7992 TTree* friend_t = fe->GetTree();
7993 if (friend_t == oldFriend) {
7994 fFriends->Remove(fe);
7995 delete fe;
7996 fe = nullptr;
7997 }
7998 }
7999}
8000
8001////////////////////////////////////////////////////////////////////////////////
8002/// Reset baskets, buffers and entries count in all branches and leaves.
8005{
8006 fNotify = nullptr;
8007 fEntries = 0;
8008 fNClusterRange = 0;
8009 fTotBytes = 0;
8010 fZipBytes = 0;
8011 fFlushedBytes = 0;
8012 fSavedBytes = 0;
8013 fTotalBuffers = 0;
8014 fChainOffset = 0;
8015 fReadEntry = -1;
8016
8017 delete fTreeIndex;
8018 fTreeIndex = nullptr;
8019
8021 for (Int_t i = 0; i < nb; ++i) {
8022 TBranch* branch = (TBranch*) fBranches.UncheckedAt(i);
8023 branch->Reset(option);
8024 }
8025
8026 if (fBranchRef) {
8027 fBranchRef->Reset();
8028 }
8029}
8030
8031////////////////////////////////////////////////////////////////////////////////
8032/// Resets the state of this TTree after a merge (keep the customization but
8033/// forget the data).
8036{
8037 fEntries = 0;
8038 fNClusterRange = 0;
8039 fTotBytes = 0;
8040 fZipBytes = 0;
8041 fSavedBytes = 0;
8042 fFlushedBytes = 0;
8043 fTotalBuffers = 0;
8044 fChainOffset = 0;
8045 fReadEntry = -1;
8046
8047 delete fTreeIndex;
8048 fTreeIndex = nullptr;
8049
8051 for (Int_t i = 0; i < nb; ++i) {
8052 TBranch* branch = (TBranch*) fBranches.UncheckedAt(i);
8053 branch->ResetAfterMerge(info);
8054 }
8055
8056 if (fBranchRef) {
8058 }
8059}
8060
8061////////////////////////////////////////////////////////////////////////////////
8062/// Tell all of our branches to set their addresses to zero.
8063///
8064/// Note: If any of our branches own any objects, they are deleted.
8067{
8068 if (br && br->GetTree()) {
8069 br->ResetAddress();
8070 }
8071}
8072
8073////////////////////////////////////////////////////////////////////////////////
8074/// Tell all of our branches to drop their current objects and allocate new ones.
8077{
8078 TObjArray* branches = GetListOfBranches();
8079 Int_t nbranches = branches->GetEntriesFast();
8080 for (Int_t i = 0; i < nbranches; ++i) {
8081 TBranch* branch = (TBranch*) branches->UncheckedAt(i);
8082 branch->ResetAddress();
8083 }
8084}
8085
8086////////////////////////////////////////////////////////////////////////////////
8087/// Loop over tree entries and print entries passing selection. Interactive
8088/// pagination break is on by default.
8089///
8090/// - If varexp is 0 (or "") then print only first 8 columns.
8091/// - If varexp = "*" print all columns.
8092///
8093/// Otherwise a columns selection can be made using "var1:var2:var3".
8094///
8095/// \param firstentry first entry to scan
8096/// \param nentries total number of entries to scan (starting from firstentry). Defaults to all entries.
8097/// \see TTree::SetScanField to control how many lines are printed between pagination breaks (Use 0 to disable pagination)
8098/// \see TTreePlayer::Scan for more information
8100Long64_t TTree::Scan(const char* varexp, const char* selection, Option_t* option, Long64_t nentries, Long64_t firstentry)
8101{
8102 GetPlayer();
8103 if (fPlayer) {
8104 return fPlayer->Scan(varexp, selection, option, nentries, firstentry);
8105 }
8106 return -1;
8107}
8108
8109////////////////////////////////////////////////////////////////////////////////
8110/// Set a tree variable alias.
8111///
8112/// Set an alias for an expression/formula based on the tree 'variables'.
8113///
8114/// The content of 'aliasName' can be used in TTreeFormula (i.e. TTree::Draw,
8115/// TTree::Scan, TTreeViewer) and will be evaluated as the content of
8116/// 'aliasFormula'.
8117///
8118/// If the content of 'aliasFormula' only contains symbol names, periods and
8119/// array index specification (for example event.fTracks[3]), then
8120/// the content of 'aliasName' can be used as the start of symbol.
8121///
8122/// If the alias 'aliasName' already existed, it is replaced by the new
8123/// value.
8124///
8125/// When being used, the alias can be preceded by an eventual 'Friend Alias'
8126/// (see TTree::GetFriendAlias)
8127///
8128/// Return true if it was added properly.
8129///
8130/// For example:
8131/// ~~~ {.cpp}
8132/// tree->SetAlias("x1","(tdc1[1]-tdc1[0])/49");
8133/// tree->SetAlias("y1","(tdc1[3]-tdc1[2])/47");
8134/// tree->SetAlias("x2","(tdc2[1]-tdc2[0])/49");
8135/// tree->SetAlias("y2","(tdc2[3]-tdc2[2])/47");
8136/// tree->Draw("y2-y1:x2-x1");
8137///
8138/// tree->SetAlias("theGoodTrack","event.fTracks[3]");
8139/// tree->Draw("theGoodTrack.fPx"); // same as "event.fTracks[3].fPx"
8140/// ~~~
8142bool TTree::SetAlias(const char* aliasName, const char* aliasFormula)
8143{
8144 if (!aliasName || !aliasFormula) {
8145 return false;
8146 }
8147 if (!aliasName[0] || !aliasFormula[0]) {
8148 return false;
8149 }
8150 if (!fAliases) {
8151 fAliases = new TList;
8152 } else {
8153 TNamed* oldHolder = (TNamed*) fAliases->FindObject(aliasName);
8154 if (oldHolder) {
8155 oldHolder->SetTitle(aliasFormula);
8156 return true;
8157 }
8158 }
8159 TNamed* holder = new TNamed(aliasName, aliasFormula);
8160 fAliases->Add(holder);
8161 return true;
8162}
8163
8164////////////////////////////////////////////////////////////////////////////////
8165/// This function may be called at the start of a program to change
8166/// the default value for fAutoFlush.
8167///
8168/// ### CASE 1 : autof > 0
8169///
8170/// autof is the number of consecutive entries after which TTree::Fill will
8171/// flush all branch buffers to disk.
8172///
8173/// ### CASE 2 : autof < 0
8174///
8175/// When filling the Tree the branch buffers will be flushed to disk when
8176/// more than autof bytes have been written to the file. At the first FlushBaskets
8177/// TTree::Fill will replace fAutoFlush by the current value of fEntries.
8178///
8179/// Calling this function with autof<0 is interesting when it is hard to estimate
8180/// the size of one entry. This value is also independent of the Tree.
8181///
8182/// The Tree is initialized with fAutoFlush=-30000000, ie that, by default,
8183/// the first AutoFlush will be done when 30 MBytes of data are written to the file.
8184///
8185/// ### CASE 3 : autof = 0
8186///
8187/// The AutoFlush mechanism is disabled.
8188///
8189/// Flushing the buffers at regular intervals optimize the location of
8190/// consecutive entries on the disk by creating clusters of baskets.
8191///
8192/// A cluster of baskets is a set of baskets that contains all
8193/// the data for a (consecutive) set of entries and that is stored
8194/// consecutively on the disk. When reading all the branches, this
8195/// is the minimum set of baskets that the TTreeCache will read.
8197void TTree::SetAutoFlush(Long64_t autof /* = -30000000 */ )
8198{
8199 // Implementation note:
8200 //
8201 // A positive value of autoflush determines the size (in number of entries) of
8202 // a cluster of baskets.
8203 //
8204 // If the value of autoflush is changed over time (this happens in
8205 // particular when the TTree results from fast merging many trees),
8206 // we record the values of fAutoFlush in the data members:
8207 // fClusterRangeEnd and fClusterSize.
8208 // In the code we refer to a range of entries where the size of the
8209 // cluster of baskets is the same (i.e the value of AutoFlush was
8210 // constant) is called a ClusterRange.
8211 //
8212 // The 2 arrays (fClusterRangeEnd and fClusterSize) have fNClusterRange
8213 // active (used) values and have fMaxClusterRange allocated entries.
8214 //
8215 // fClusterRangeEnd contains the last entries number of a cluster range.
8216 // In particular this means that the 'next' cluster starts at fClusterRangeEnd[]+1
8217 // fClusterSize contains the size in number of entries of all the cluster
8218 // within the given range.
8219 // The last range (and the only one if fNClusterRange is zero) start at
8220 // fNClusterRange[fNClusterRange-1]+1 and ends at the end of the TTree. The
8221 // size of the cluster in this range is given by the value of fAutoFlush.
8222 //
8223 // For example printing the beginning and end of each the ranges can be done by:
8224 //
8225 // Printf("%-16s %-16s %-16s %5s",
8226 // "Cluster Range #", "Entry Start", "Last Entry", "Size");
8227 // Int_t index= 0;
8228 // Long64_t clusterRangeStart = 0;
8229 // if (fNClusterRange) {
8230 // for( ; index < fNClusterRange; ++index) {
8231 // Printf("%-16d %-16lld %-16lld %5lld",
8232 // index, clusterRangeStart, fClusterRangeEnd[index], fClusterSize[index]);
8233 // clusterRangeStart = fClusterRangeEnd[index] + 1;
8234 // }
8235 // }
8236 // Printf("%-16d %-16lld %-16lld %5lld",
8237 // index, prevEntry, fEntries - 1, fAutoFlush);
8238 //
8239
8240 // Note: We store the entry number corresponding to the end of the cluster
8241 // rather than its start in order to avoid using the array if the cluster
8242 // size never varies (If there is only one value of AutoFlush for the whole TTree).
8243
8244 if( fAutoFlush != autof) {
8245 if ((fAutoFlush > 0 || autof > 0) && fFlushedBytes) {
8246 // The mechanism was already enabled, let's record the previous
8247 // cluster if needed.
8249 }
8250 fAutoFlush = autof;
8251 }
8252}
8253
8254////////////////////////////////////////////////////////////////////////////////
8255/// Mark the previous event as being at the end of the event cluster.
8256///
8257/// So, if fEntries is set to 10 (and this is the first cluster) when MarkEventCluster
8258/// is called, then the first cluster has 9 events.
8260{
8261 if (!fEntries) return;
8262
8263 if ( (fNClusterRange+1) > fMaxClusterRange ) {
8264 if (fMaxClusterRange) {
8265 // Resize arrays to hold a larger event cluster.
8266 Int_t newsize = TMath::Max(10,Int_t(2*fMaxClusterRange));
8268 newsize*sizeof(Long64_t),fMaxClusterRange*sizeof(Long64_t));
8270 newsize*sizeof(Long64_t),fMaxClusterRange*sizeof(Long64_t));
8271 fMaxClusterRange = newsize;
8272 } else {
8273 // Cluster ranges have never been initialized; create them now.
8274 fMaxClusterRange = 2;
8277 }
8278 }
8280 // If we are auto-flushing, then the cluster size is the same as the current auto-flush setting.
8281 if (fAutoFlush > 0) {
8282 // Even if the user triggers MarkEventRange prior to fAutoFlush being present, the TClusterIterator
8283 // will appropriately go to the next event range.
8285 // Otherwise, assume there is one cluster per event range (e.g., user is manually controlling the flush).
8286 } else if (fNClusterRange == 0) {
8288 } else {
8290 }
8292}
8293
8294/// Estimate the median cluster size for the TTree.
8295/// This value provides e.g. a reasonable cache size default if other heuristics fail.
8296/// Clusters with size 0 and the very last cluster range, that might not have been committed to fClusterSize yet,
8297/// are ignored for the purposes of the calculation.
8299{
8300 std::vector<Long64_t> clusterSizesPerRange;
8301 clusterSizesPerRange.reserve(fNClusterRange);
8302
8303 // We ignore cluster sizes of 0 for the purposes of this function.
8304 // We also ignore the very last cluster range which might not have been committed to fClusterSize.
8305 std::copy_if(fClusterSize, fClusterSize + fNClusterRange, std::back_inserter(clusterSizesPerRange),
8306 [](Long64_t size) { return size != 0; });
8307
8308 std::vector<double> nClustersInRange; // we need to store doubles because of the signature of TMath::Median
8309 nClustersInRange.reserve(clusterSizesPerRange.size());
8310
8311 auto clusterRangeStart = 0ll;
8312 for (int i = 0; i < fNClusterRange; ++i) {
8313 const auto size = fClusterSize[i];
8314 R__ASSERT(size >= 0);
8315 if (fClusterSize[i] == 0)
8316 continue;
8317 const auto nClusters = (1 + fClusterRangeEnd[i] - clusterRangeStart) / fClusterSize[i];
8318 nClustersInRange.emplace_back(nClusters);
8319 clusterRangeStart = fClusterRangeEnd[i] + 1;
8320 }
8321
8322 R__ASSERT(nClustersInRange.size() == clusterSizesPerRange.size());
8323 const auto medianClusterSize =
8324 TMath::Median(nClustersInRange.size(), clusterSizesPerRange.data(), nClustersInRange.data());
8325 return medianClusterSize;
8326}
8327
8328////////////////////////////////////////////////////////////////////////////////
8329/// In case of a program crash, it will be possible to recover the data in the
8330/// tree up to the last AutoSave point.
8331/// This function may be called before filling a TTree to specify when the
8332/// branch buffers and TTree header are flushed to disk as part of
8333/// TTree::Fill().
8334/// The default is -300000000, ie the TTree will write data to disk once it
8335/// exceeds 300 MBytes.
8336/// CASE 1: If fAutoSave is positive the watermark is reached when a multiple of
8337/// fAutoSave entries have been filled.
8338/// CASE 2: If fAutoSave is negative the watermark is reached when -fAutoSave
8339/// bytes can be written to the file.
8340/// CASE 3: If fAutoSave is 0, AutoSave() will never be called automatically
8341/// as part of TTree::Fill().
8343void TTree::SetAutoSave(Long64_t autos)
8344{
8345 fAutoSave = autos;
8346}
8347
8348////////////////////////////////////////////////////////////////////////////////
8349/// Set a branch's basket size.
8350///
8351/// bname is the name of a branch.
8352///
8353/// - if bname="*", apply to all branches.
8354/// - if bname="xxx*", apply to all branches with name starting with xxx
8355///
8356/// see TRegexp for wildcarding options
8357/// buffsize = branc basket size
8359void TTree::SetBasketSize(const char* bname, Int_t buffsize)
8360{
8361 Int_t nleaves = fLeaves.GetEntriesFast();
8362 TRegexp re(bname, true);
8363 Int_t nb = 0;
8364 for (Int_t i = 0; i < nleaves; i++) {
8365 TLeaf* leaf = (TLeaf*) fLeaves.UncheckedAt(i);
8366 TBranch* branch = (TBranch*) leaf->GetBranch();
8367 TString s = branch->GetName();
8368 if (strcmp(bname, branch->GetName()) && (s.Index(re) == kNPOS)) {
8369 continue;
8370 }
8371 nb++;
8372 branch->SetBasketSize(buffsize);
8373 }
8374 if (!nb) {
8375 Error("SetBasketSize", "unknown branch -> '%s'", bname);
8376 }
8377}
8378
8379////////////////////////////////////////////////////////////////////////////////
8380/// Change branch address, dealing with clone trees properly.
8381/// See TTree::CheckBranchAddressType for the semantic of the return value.
8382///
8383/// Note: See the comments in TBranchElement::SetAddress() for the
8384/// meaning of the addr parameter and the object ownership policy.
8386Int_t TTree::SetBranchAddress(const char* bname, void* addr, TBranch** ptr)
8387{
8388 TBranch* branch = GetBranch(bname);
8389 if (!branch) {
8390 if (ptr) *ptr = nullptr;
8391 Error("SetBranchAddress", "unknown branch -> %s", bname);
8392 return kMissingBranch;
8393 }
8394 return SetBranchAddressImp(branch,addr,ptr);
8395}
8396
8397////////////////////////////////////////////////////////////////////////////////
8398/// Verify the validity of the type of addr before calling SetBranchAddress.
8399/// See TTree::CheckBranchAddressType for the semantic of the return value.
8400///
8401/// Note: See the comments in TBranchElement::SetAddress() for the
8402/// meaning of the addr parameter and the object ownership policy.
8404Int_t TTree::SetBranchAddress(const char* bname, void* addr, TClass* ptrClass, EDataType datatype, bool isptr)
8405{
8406 return SetBranchAddress(bname, addr, nullptr, ptrClass, datatype, isptr);
8407}
8408
8409////////////////////////////////////////////////////////////////////////////////
8410/// Verify the validity of the type of addr before calling SetBranchAddress.
8411/// See TTree::CheckBranchAddressType for the semantic of the return value.
8412///
8413/// Note: See the comments in TBranchElement::SetAddress() for the
8414/// meaning of the addr parameter and the object ownership policy.
8416Int_t TTree::SetBranchAddress(const char* bname, void* addr, TBranch** ptr, TClass* ptrClass, EDataType datatype, bool isptr)
8417{
8418 TBranch* branch = GetBranch(bname);
8419 if (!branch) {
8420 if (ptr) *ptr = nullptr;
8421 Error("SetBranchAddress", "unknown branch -> %s", bname);
8422 return kMissingBranch;
8423 }
8424
8425 Int_t res = CheckBranchAddressType(branch, ptrClass, datatype, isptr);
8426
8427 // This will set the value of *ptr to branch.
8428 if (res >= 0) {
8429 // The check succeeded.
8430 if ((res & kNeedEnableDecomposedObj) && !branch->GetMakeClass())
8431 branch->SetMakeClass(true);
8432 SetBranchAddressImp(branch,addr,ptr);
8433 } else {
8434 if (ptr) *ptr = nullptr;
8435 }
8436 return res;
8437}
8438
8439////////////////////////////////////////////////////////////////////////////////
8440/// Change branch address, dealing with clone trees properly.
8441/// See TTree::CheckBranchAddressType for the semantic of the return value.
8442///
8443/// Note: See the comments in TBranchElement::SetAddress() for the
8444/// meaning of the addr parameter and the object ownership policy.
8446Int_t TTree::SetBranchAddressImp(TBranch *branch, void* addr, TBranch** ptr)
8447{
8448 if (ptr) {
8449 *ptr = branch;
8450 }
8451 if (fClones) {
8452 void* oldAddr = branch->GetAddress();
8453 TIter next(fClones);
8454 TTree* clone = nullptr;
8455 const char *bname = branch->GetName();
8456 while ((clone = (TTree*) next())) {
8457 TBranch* cloneBr = clone->GetBranch(bname);
8458 if (cloneBr && (cloneBr->GetAddress() == oldAddr)) {
8459 cloneBr->SetAddress(addr);
8460 }
8461 }
8462 }
8463 branch->SetAddress(addr);
8464 return kVoidPtr;
8465}
8466
8467////////////////////////////////////////////////////////////////////////////////
8468/// Set branch status to Process or DoNotProcess.
8469///
8470/// When reading a Tree, by default, all branches are read.
8471/// One can speed up considerably the analysis phase by activating
8472/// only the branches that hold variables involved in a query.
8473///
8474/// bname is the name of a branch.
8475///
8476/// - if bname="*", apply to all branches.
8477/// - if bname="xxx*", apply to all branches with name starting with xxx
8478///
8479/// see TRegexp for wildcarding options
8480///
8481/// - status = 1 branch will be processed
8482/// - = 0 branch will not be processed
8483///
8484/// Example:
8485///
8486/// Assume a tree T with sub-branches a,b,c,d,e,f,g,etc..
8487/// when doing T.GetEntry(i) all branches are read for entry i.
8488/// to read only the branches c and e, one can do
8489/// ~~~ {.cpp}
8490/// T.SetBranchStatus("*",0); //disable all branches
8491/// T.SetBranchStatus("c",1);
8492/// T.setBranchStatus("e",1);
8493/// T.GetEntry(i);
8494/// ~~~
8495/// bname is interpreted as a wild-carded TRegexp (see TRegexp::MakeWildcard).
8496/// Thus, "a*b" or "a.*b" matches branches starting with "a" and ending with
8497/// "b", but not any other branch with an "a" followed at some point by a
8498/// "b". For this second behavior, use "*a*b*". Note that TRegExp does not
8499/// support '|', and so you cannot select, e.g. track and shower branches
8500/// with "track|shower".
8501///
8502/// __WARNING! WARNING! WARNING!__
8503///
8504/// SetBranchStatus is matching the branch based on match of the branch
8505/// 'name' and not on the branch hierarchy! In order to be able to
8506/// selectively enable a top level object that is 'split' you need to make
8507/// sure the name of the top level branch is prefixed to the sub-branches'
8508/// name (by adding a dot ('.') at the end of the Branch creation and use the
8509/// corresponding bname.
8510///
8511/// I.e If your Tree has been created in split mode with a parent branch "parent."
8512/// (note the trailing dot).
8513/// ~~~ {.cpp}
8514/// T.SetBranchStatus("parent",1);
8515/// ~~~
8516/// will not activate the sub-branches of "parent". You should do:
8517/// ~~~ {.cpp}
8518/// T.SetBranchStatus("parent*",1);
8519/// ~~~
8520/// Without the trailing dot in the branch creation you have no choice but to
8521/// call SetBranchStatus explicitly for each of the sub branches.
8522///
8523/// An alternative to this function is to read directly and only
8524/// the interesting branches. Example:
8525/// ~~~ {.cpp}
8526/// TBranch *brc = T.GetBranch("c");
8527/// TBranch *bre = T.GetBranch("e");
8528/// brc->GetEntry(i);
8529/// bre->GetEntry(i);
8530/// ~~~
8531/// If found is not 0, the number of branch(es) found matching the regular
8532/// expression is returned in *found AND the error message 'unknown branch'
8533/// is suppressed.
8535void TTree::SetBranchStatus(const char* bname, bool status, UInt_t* found)
8536{
8537 // We already have been visited while recursively looking
8538 // through the friends tree, let return
8540 return;
8541 }
8542
8543 if (!bname || !*bname) {
8544 Error("SetBranchStatus", "Input regexp is an empty string: no match against branch names will be attempted.");
8545 return;
8546 }
8547
8548 TBranch *branch, *bcount, *bson;
8549 TLeaf *leaf, *leafcount;
8550
8551 Int_t i,j;
8552 Int_t nleaves = fLeaves.GetEntriesFast();
8553 TRegexp re(bname,true);
8554 Int_t nb = 0;
8555
8556 // first pass, loop on all branches
8557 // for leafcount branches activate/deactivate in function of status
8558 for (i=0;i<nleaves;i++) {
8559 leaf = (TLeaf*)fLeaves.UncheckedAt(i);
8560 branch = (TBranch*)leaf->GetBranch();
8561 TString s = branch->GetName();
8562 if (strcmp(bname,"*")) { //Regexp gives wrong result for [] in name
8563 TString longname;
8564 longname.Form("%s.%s",GetName(),branch->GetName());
8565 if (strcmp(bname,branch->GetName())
8566 && longname != bname
8567 && s.Index(re) == kNPOS) continue;
8568 }
8569 nb++;
8570 if (status) branch->ResetBit(kDoNotProcess);
8571 else branch->SetBit(kDoNotProcess);
8572 leafcount = leaf->GetLeafCount();
8573 if (leafcount) {
8574 bcount = leafcount->GetBranch();
8575 if (status) bcount->ResetBit(kDoNotProcess);
8576 else bcount->SetBit(kDoNotProcess);
8577 }
8578 }
8579 if (nb==0 && !strchr(bname,'*')) {
8580 branch = GetBranch(bname);
8581 if (branch) {
8582 if (status) branch->ResetBit(kDoNotProcess);
8583 else branch->SetBit(kDoNotProcess);
8584 ++nb;
8585 }
8586 }
8587
8588 //search in list of friends
8589 UInt_t foundInFriend = 0;
8590 if (fFriends) {
8591 TFriendLock lock(this,kSetBranchStatus);
8592 TIter nextf(fFriends);
8593 TFriendElement *fe;
8594 TString name;
8595 while ((fe = (TFriendElement*)nextf())) {
8596 TTree *t = fe->GetTree();
8597 if (!t) continue;
8598
8599 // If the alias is present replace it with the real name.
8600 const char *subbranch = strstr(bname,fe->GetName());
8601 if (subbranch!=bname) subbranch = nullptr;
8602 if (subbranch) {
8603 subbranch += strlen(fe->GetName());
8604 if ( *subbranch != '.' ) subbranch = nullptr;
8605 else subbranch ++;
8606 }
8607 if (subbranch) {
8608 name.Form("%s.%s",t->GetName(),subbranch);
8609 } else {
8610 name = bname;
8611 }
8612 t->SetBranchStatus(name,status, &foundInFriend);
8613 }
8614 }
8615 if (!nb && !foundInFriend) {
8616 if (!found) {
8617 if (status) {
8618 if (strchr(bname,'*') != nullptr)
8619 Error("SetBranchStatus", "No branch name is matching wildcard -> %s", bname);
8620 else
8621 Error("SetBranchStatus", "unknown branch -> %s", bname);
8622 } else {
8623 if (strchr(bname,'*') != nullptr)
8624 Warning("SetBranchStatus", "No branch name is matching wildcard -> %s", bname);
8625 else
8626 Warning("SetBranchStatus", "unknown branch -> %s", bname);
8627 }
8628 }
8629 return;
8630 }
8631 if (found) *found = nb + foundInFriend;
8632
8633 // second pass, loop again on all branches
8634 // activate leafcount branches for active branches only
8635 for (i = 0; i < nleaves; i++) {
8636 leaf = (TLeaf*)fLeaves.UncheckedAt(i);
8637 branch = (TBranch*)leaf->GetBranch();
8638 if (!branch->TestBit(kDoNotProcess)) {
8639 leafcount = leaf->GetLeafCount();
8640 if (leafcount) {
8641 bcount = leafcount->GetBranch();
8642 bcount->ResetBit(kDoNotProcess);
8643 }
8644 } else {
8645 //Int_t nbranches = branch->GetListOfBranches()->GetEntriesFast();
8646 Int_t nbranches = branch->GetListOfBranches()->GetEntries();
8647 for (j=0;j<nbranches;j++) {
8648 bson = (TBranch*)branch->GetListOfBranches()->UncheckedAt(j);
8649 if (!bson) continue;
8650 if (!bson->TestBit(kDoNotProcess)) {
8651 if (bson->GetNleaves() <= 0) continue;
8652 branch->ResetBit(kDoNotProcess);
8653 break;
8654 }
8655 }
8656 }
8657 }
8658}
8659
8660////////////////////////////////////////////////////////////////////////////////
8661/// Set the current branch style. (static function)
8662///
8663/// - style = 0 old Branch
8664/// - style = 1 new Bronch
8667{
8669}
8670
8671////////////////////////////////////////////////////////////////////////////////
8672/// Set maximum size of the file cache .
8673//
8674/// - if cachesize = 0 the existing cache (if any) is deleted.
8675/// - if cachesize = -1 (default) it is set to the AutoFlush value when writing
8676/// the Tree (default is 30 MBytes).
8677///
8678/// The cacheSize might be clamped, see TFileCacheRead::SetBufferSize
8679///
8680/// Returns:
8681/// - 0 size set, cache was created if possible
8682/// - -1 on error
8685{
8686 // remember that the user has requested an explicit cache setup
8687 fCacheUserSet = true;
8688
8689 return SetCacheSizeAux(false, cacheSize);
8690}
8691
8692////////////////////////////////////////////////////////////////////////////////
8693/// Set the size of the file cache and create it if possible.
8694///
8695/// If autocache is true:
8696/// this may be an autocreated cache, possibly enlarging an existing
8697/// autocreated cache. The size is calculated. The value passed in cacheSize:
8698/// - cacheSize = 0 make cache if default cache creation is enabled
8699/// - cacheSize = -1 make a default sized cache in any case
8700///
8701/// If autocache is false:
8702/// this is a user requested cache. cacheSize is used to size the cache.
8703/// This cache should never be automatically adjusted.
8704///
8705/// The cacheSize might be clamped, see TFileCacheRead::SetBufferSize
8706///
8707/// Returns:
8708/// - 0 size set, or existing autosized cache almost large enough.
8709/// (cache was created if possible)
8710/// - -1 on error
8712Int_t TTree::SetCacheSizeAux(bool autocache /* = true */, Long64_t cacheSize /* = 0 */ )
8713{
8714 if (autocache) {
8715 // used as a once only control for automatic cache setup
8716 fCacheDoAutoInit = false;
8717 }
8718
8719 if (!autocache) {
8720 // negative size means the user requests the default
8721 if (cacheSize < 0) {
8722 cacheSize = GetCacheAutoSize(true);
8723 }
8724 } else {
8725 if (cacheSize == 0) {
8726 cacheSize = GetCacheAutoSize();
8727 } else if (cacheSize < 0) {
8728 cacheSize = GetCacheAutoSize(true);
8729 }
8730 }
8731
8732 TFile* file = GetCurrentFile();
8733 if (!file || GetTree() != this) {
8734 // if there's no file or we are not a plain tree (e.g. if we're a TChain)
8735 // do not create a cache, only record the size if one was given
8736 if (!autocache) {
8737 fCacheSize = cacheSize;
8738 }
8739 if (GetTree() != this) {
8740 return 0;
8741 }
8742 if (!autocache && cacheSize>0) {
8743 Warning("SetCacheSizeAux", "A TTreeCache could not be created because the TTree has no file");
8744 }
8745 return 0;
8746 }
8747
8748 // Check for an existing cache
8749 TTreeCache* pf = GetReadCache(file);
8750 if (pf) {
8751 if (autocache) {
8752 // reset our cache status tracking in case existing cache was added
8753 // by the user without using one of the TTree methods
8754 fCacheSize = pf->GetBufferSize();
8756
8757 if (fCacheUserSet) {
8758 // existing cache was created by the user, don't change it
8759 return 0;
8760 }
8761 } else {
8762 // update the cache to ensure it records the user has explicitly
8763 // requested it
8764 pf->SetAutoCreated(false);
8765 }
8766
8767 // if we're using an automatically calculated size and the existing
8768 // cache is already almost large enough don't resize
8769 if (autocache && Long64_t(0.80*cacheSize) < fCacheSize) {
8770 // already large enough
8771 return 0;
8772 }
8773
8774 if (cacheSize == fCacheSize) {
8775 return 0;
8776 }
8777
8778 if (cacheSize == 0) {
8779 // delete existing cache
8780 pf->WaitFinishPrefetch();
8781 file->SetCacheRead(nullptr,this);
8782 delete pf;
8783 pf = nullptr;
8784 } else {
8785 // resize
8786 Int_t res = pf->SetBufferSize(cacheSize);
8787 if (res < 0) {
8788 return -1;
8789 }
8790 cacheSize = pf->GetBufferSize(); // update after potential clamp
8791 }
8792 } else {
8793 // no existing cache
8794 if (autocache) {
8795 if (fCacheUserSet) {
8796 // value was already set manually.
8797 if (fCacheSize == 0) return 0;
8798 // Expected a cache should exist; perhaps the user moved it
8799 // Do nothing more here.
8800 if (cacheSize) {
8801 Error("SetCacheSizeAux", "Not setting up an automatically sized TTreeCache because of missing cache previously set");
8802 }
8803 return -1;
8804 }
8805 }
8806 }
8807
8808 fCacheSize = cacheSize;
8809 if (cacheSize == 0 || pf) {
8810 return 0;
8811 }
8812
8813#ifdef R__USE_IMT
8815 pf = new TTreeCacheUnzip(this, cacheSize);
8816 else
8817#endif
8818 pf = new TTreeCache(this, cacheSize);
8819
8820 pf->SetAutoCreated(autocache);
8821
8822 return 0;
8823}
8824
8825////////////////////////////////////////////////////////////////////////////////
8826///interface to TTreeCache to set the cache entry range
8827///
8828/// Returns:
8829/// - 0 entry range set
8830/// - -1 on error
8833{
8834 if (!GetTree()) {
8835 if (LoadTree(0)<0) {
8836 Error("SetCacheEntryRange","Could not load a tree");
8837 return -1;
8838 }
8839 }
8840 if (GetTree()) {
8841 if (GetTree() != this) {
8842 return GetTree()->SetCacheEntryRange(first, last);
8843 }
8844 } else {
8845 Error("SetCacheEntryRange", "No tree is available. Could not set cache entry range");
8846 return -1;
8847 }
8848
8849 TFile *f = GetCurrentFile();
8850 if (!f) {
8851 Error("SetCacheEntryRange", "No file is available. Could not set cache entry range");
8852 return -1;
8853 }
8854 TTreeCache *tc = GetReadCache(f,true);
8855 if (!tc) {
8856 Error("SetCacheEntryRange", "No cache is available. Could not set entry range");
8857 return -1;
8858 }
8859 tc->SetEntryRange(first,last);
8860 return 0;
8861}
8862
8863////////////////////////////////////////////////////////////////////////////////
8864/// Interface to TTreeCache to set the number of entries for the learning phase
8867{
8869}
8870
8871////////////////////////////////////////////////////////////////////////////////
8872/// Enable/Disable circularity for this tree.
8873///
8874/// if maxEntries > 0 a maximum of maxEntries is kept in one buffer/basket
8875/// per branch in memory.
8876/// Note that when this function is called (maxEntries>0) the Tree
8877/// must be empty or having only one basket per branch.
8878/// if maxEntries <= 0 the tree circularity is disabled.
8879///
8880/// #### NOTE 1:
8881/// Circular Trees are interesting in online real time environments
8882/// to store the results of the last maxEntries events.
8883/// #### NOTE 2:
8884/// Calling SetCircular with maxEntries <= 0 is necessary before
8885/// merging circular Trees that have been saved on files.
8886/// #### NOTE 3:
8887/// SetCircular with maxEntries <= 0 is automatically called
8888/// by TChain::Merge
8889/// #### NOTE 4:
8890/// A circular Tree can still be saved in a file. When read back,
8891/// it is still a circular Tree and can be filled again.
8893void TTree::SetCircular(Long64_t maxEntries)
8894{
8895 if (maxEntries <= 0) {
8896 // Disable circularity.
8897 fMaxEntries = 1000000000;
8898 fMaxEntries *= 1000;
8900 //in case the Tree was originally created in gROOT, the branch
8901 //compression level was set to -1. If the Tree is now associated to
8902 //a file, reset the compression level to the file compression level
8903 if (fDirectory) {
8904 TFile* bfile = fDirectory->GetFile();
8906 if (bfile) {
8907 compress = bfile->GetCompressionSettings();
8908 }
8910 for (Int_t i = 0; i < nb; i++) {
8911 TBranch* branch = (TBranch*) fBranches.UncheckedAt(i);
8912 branch->SetCompressionSettings(compress);
8913 }
8914 }
8915 } else {
8916 // Enable circularity.
8917 fMaxEntries = maxEntries;
8919 }
8920}
8921
8922////////////////////////////////////////////////////////////////////////////////
8923/// Set the debug level and the debug range.
8924///
8925/// For entries in the debug range, the functions TBranchElement::Fill
8926/// and TBranchElement::GetEntry will print the number of bytes filled
8927/// or read for each branch.
8929void TTree::SetDebug(Int_t level, Long64_t min, Long64_t max)
8930{
8931 fDebug = level;
8932 fDebugMin = min;
8933 fDebugMax = max;
8934}
8935
8936////////////////////////////////////////////////////////////////////////////////
8937/// Update the default value for the branch's fEntryOffsetLen.
8938/// If updateExisting is true, also update all the existing branches.
8939/// If newdefault is less than 10, the new default value will be 10.
8941void TTree::SetDefaultEntryOffsetLen(Int_t newdefault, bool updateExisting)
8942{
8943 if (newdefault < 10) {
8944 newdefault = 10;
8945 }
8946 fDefaultEntryOffsetLen = newdefault;
8947 if (updateExisting) {
8948 TIter next( GetListOfBranches() );
8949 TBranch *b;
8950 while ( ( b = (TBranch*)next() ) ) {
8951 b->SetEntryOffsetLen( newdefault, true );
8952 }
8953 if (fBranchRef) {
8954 fBranchRef->SetEntryOffsetLen( newdefault, true );
8955 }
8956 }
8957}
8958
8959////////////////////////////////////////////////////////////////////////////////
8960/// Change the tree's directory.
8961///
8962/// Remove reference to this tree from current directory and
8963/// add reference to new directory dir. The dir parameter can
8964/// be 0 in which case the tree does not belong to any directory.
8965///
8968{
8969 if (fDirectory == dir) {
8970 return;
8971 }
8972 if (fDirectory) {
8973 fDirectory->Remove(this);
8974
8975 // Delete or move the file cache if it points to this Tree
8976 TFile *file = fDirectory->GetFile();
8977 MoveReadCache(file,dir);
8978 }
8979 fDirectory = dir;
8980 if (fDirectory) {
8981 fDirectory->Append(this);
8982 }
8983 TFile* file = nullptr;
8984 if (fDirectory) {
8985 file = fDirectory->GetFile();
8986 }
8987 if (fBranchRef) {
8988 fBranchRef->SetFile(file);
8989 }
8990 TBranch* b = nullptr;
8991 TIter next(GetListOfBranches());
8992 while((b = (TBranch*) next())) {
8993 b->SetFile(file);
8994 }
8995}
8996
8997////////////////////////////////////////////////////////////////////////////////
8998/// Change number of entries in the tree.
8999///
9000/// If n >= 0, set number of entries in the tree = n.
9001///
9002/// If n < 0, set number of entries in the tree to match the
9003/// number of entries in each branch. (default for n is -1)
9004///
9005/// This function should be called only when one fills each branch
9006/// independently via TBranch::Fill without calling TTree::Fill.
9007/// Calling TTree::SetEntries() make sense only if the number of entries
9008/// in each branch is identical, a warning is issued otherwise.
9009/// The function returns the number of entries.
9010///
9013{
9014 // case 1 : force number of entries to n
9015 if (n >= 0) {
9016 fEntries = n;
9017 return n;
9018 }
9019
9020 // case 2; compute the number of entries from the number of entries in the branches
9021 TBranch* b(nullptr), *bMin(nullptr), *bMax(nullptr);
9022 Long64_t nMin = kMaxEntries;
9023 Long64_t nMax = 0;
9024 TIter next(GetListOfBranches());
9025 while((b = (TBranch*) next())){
9026 Long64_t n2 = b->GetEntries();
9027 if (!bMin || n2 < nMin) {
9028 nMin = n2;
9029 bMin = b;
9030 }
9031 if (!bMax || n2 > nMax) {
9032 nMax = n2;
9033 bMax = b;
9034 }
9035 }
9036 if (bMin && nMin != nMax) {
9037 Warning("SetEntries", "Tree branches have different numbers of entries, eg %s has %lld entries while %s has %lld entries.",
9038 bMin->GetName(), nMin, bMax->GetName(), nMax);
9039 }
9040 fEntries = nMax;
9041 return fEntries;
9042}
9043
9044////////////////////////////////////////////////////////////////////////////////
9045/// Set an EntryList
9047void TTree::SetEntryList(TEntryList *enlist, Option_t * /*opt*/)
9048{
9049 if (fEntryList) {
9050 //check if the previous entry list is owned by the tree
9052 delete fEntryList;
9053 }
9054 }
9055 fEventList = nullptr;
9056 if (!enlist) {
9057 fEntryList = nullptr;
9058 return;
9059 }
9060 fEntryList = enlist;
9061 fEntryList->SetTree(this);
9062
9063}
9064
9065////////////////////////////////////////////////////////////////////////////////
9066/// This function transfroms the given TEventList into a TEntryList
9067/// The new TEntryList is owned by the TTree and gets deleted when the tree
9068/// is deleted. This TEntryList can be returned by GetEntryList() function.
9070void TTree::SetEventList(TEventList *evlist)
9071{
9072 fEventList = evlist;
9073 if (fEntryList){
9075 TEntryList *tmp = fEntryList;
9076 fEntryList = nullptr; // Avoid problem with RecursiveRemove.
9077 delete tmp;
9078 } else {
9079 fEntryList = nullptr;
9080 }
9081 }
9082
9083 if (!evlist) {
9084 fEntryList = nullptr;
9085 fEventList = nullptr;
9086 return;
9087 }
9088
9089 fEventList = evlist;
9090 char enlistname[100];
9091 snprintf(enlistname,100, "%s_%s", evlist->GetName(), "entrylist");
9092 fEntryList = new TEntryList(enlistname, evlist->GetTitle());
9093 fEntryList->SetDirectory(nullptr); // We own this.
9094 Int_t nsel = evlist->GetN();
9095 fEntryList->SetTree(this);
9096 Long64_t entry;
9097 for (Int_t i=0; i<nsel; i++){
9098 entry = evlist->GetEntry(i);
9099 fEntryList->Enter(entry);
9100 }
9103}
9104
9105////////////////////////////////////////////////////////////////////////////////
9106/// Set number of entries to estimate variable limits.
9107/// If n is -1, the estimate is set to be the current maximum
9108/// for the tree (i.e. GetEntries() + 1)
9109/// If n is less than -1, the behavior is undefined.
9111void TTree::SetEstimate(Long64_t n /* = 1000000 */)
9112{
9113 if (n == 0) {
9114 n = 10000;
9115 } else if (n < 0) {
9116 n = fEntries - n;
9117 }
9118 fEstimate = n;
9119 GetPlayer();
9120 if (fPlayer) {
9122 }
9123}
9124
9125////////////////////////////////////////////////////////////////////////////////
9126/// Provide the end-user with the ability to enable/disable various experimental
9127/// IO features for this TTree.
9128///
9129/// Returns all the newly-set IO settings.
9132{
9133 // Purposely ignore all unsupported bits; TIOFeatures implementation already warned the user about the
9134 // error of their ways; this is just a safety check.
9135 UChar_t featuresRequested = features.GetFeatures() & static_cast<UChar_t>(TBasket::EIOBits::kSupported);
9136
9137 UChar_t curFeatures = fIOFeatures.GetFeatures();
9138 UChar_t newFeatures = ~curFeatures & featuresRequested;
9139 curFeatures |= newFeatures;
9140 fIOFeatures.Set(curFeatures);
9141
9142 ROOT::TIOFeatures newSettings(newFeatures);
9143 return newSettings;
9144}
9145
9146////////////////////////////////////////////////////////////////////////////////
9147/// Set fFileNumber to number.
9148/// fFileNumber is used by TTree::Fill to set the file name
9149/// for a new file to be created when the current file exceeds fgTreeMaxSize.
9150/// (see TTree::ChangeFile)
9151/// if fFileNumber=10, the new file name will have a suffix "_11",
9152/// ie, fFileNumber is incremented before setting the file name
9154void TTree::SetFileNumber(Int_t number)
9155{
9156 if (fFileNumber < 0) {
9157 Warning("SetFileNumber", "file number must be positive. Set to 0");
9158 fFileNumber = 0;
9159 return;
9160 }
9161 fFileNumber = number;
9162}
9163
9164////////////////////////////////////////////////////////////////////////////////
9165/// Set all the branches in this TTree to be in decomposed object mode
9166/// (also known as MakeClass mode).
9167///
9168/// For MakeClass mode 0, the TTree expects the address where the data is stored
9169/// to be set by either the user or the TTree to the address of a full object
9170/// through the top level branch.
9171/// For MakeClass mode 1, this address is expected to point to a numerical type
9172/// or C-style array (variable or not) of numerical type, representing the
9173/// primitive data members.
9174/// The function's primary purpose is to allow the user to access the data
9175/// directly with numerical type variable rather than having to have the original
9176/// set of classes (or a reproduction thereof).
9178void TTree::SetMakeClass(Int_t make)
9179{
9180 fMakeClass = make;
9181
9183 for (Int_t i = 0; i < nb; ++i) {
9184 TBranch* branch = (TBranch*) fBranches.UncheckedAt(i);
9185 branch->SetMakeClass(make);
9186 }
9187}
9188
9189////////////////////////////////////////////////////////////////////////////////
9190/// Set the maximum size in bytes of a Tree file (static function).
9191/// The default size is 100000000000LL, ie 100 Gigabytes.
9192///
9193/// In TTree::Fill, when the file has a size > fgMaxTreeSize,
9194/// the function closes the current file and starts writing into
9195/// a new file with a name of the style "file_1.root" if the original
9196/// requested file name was "file.root".
9198void TTree::SetMaxTreeSize(Long64_t maxsize)
9199{
9200 fgMaxTreeSize = maxsize;
9201}
9202
9203////////////////////////////////////////////////////////////////////////////////
9204/// Change the name of this tree.
9206void TTree::SetName(const char* name)
9207{
9208 if (gPad) {
9209 gPad->Modified();
9210 }
9211 // Trees are named objects in a THashList.
9212 // We must update hashlists if we change the name.
9213 TFile *file = nullptr;
9214 TTreeCache *pf = nullptr;
9215 if (fDirectory) {
9216 fDirectory->Remove(this);
9217 if ((file = GetCurrentFile())) {
9218 pf = GetReadCache(file);
9219 file->SetCacheRead(nullptr,this,TFile::kDoNotDisconnect);
9220 }
9221 }
9222 // This changes our hash value.
9223 fName = name;
9224 if (fDirectory) {
9225 fDirectory->Append(this);
9226 if (pf) {
9228 }
9229 }
9230}
9232void TTree::SetNotify(TObject *obj)
9233{
9234 if (obj && fNotify && dynamic_cast<TNotifyLinkBase *>(fNotify)) {
9235 auto *oldLink = static_cast<TNotifyLinkBase *>(fNotify);
9236 auto *newLink = dynamic_cast<TNotifyLinkBase *>(obj);
9237 if (!newLink) {
9238 Warning("TTree::SetNotify",
9239 "The tree or chain already has a fNotify registered and it is a TNotifyLink, while the new object is "
9240 "not a TNotifyLink. Setting fNotify to the new value will lead to an orphan linked list of "
9241 "TNotifyLinks and it is most likely not intended. If this is the intended goal, please call "
9242 "SetNotify(nullptr) first to silence this warning.");
9243 } else if (newLink->GetNext() != oldLink && oldLink->GetNext() != newLink) {
9244 // If newLink->GetNext() == oldLink then we are prepending the new head, as in TNotifyLink::PrependLink
9245 // If oldLink->GetNext() == newLink then we are removing the head of the list, as in TNotifyLink::RemoveLink
9246 // Otherwise newLink and oldLink are unrelated:
9247 Warning("TTree::SetNotify",
9248 "The tree or chain already has a TNotifyLink registered, and the new TNotifyLink `obj` does not link "
9249 "to it. Setting fNotify to the new value will lead to an orphan linked list of TNotifyLinks and it is "
9250 "most likely not intended. If this is the intended goal, please call SetNotify(nullptr) first to "
9251 "silence this warning.");
9252 }
9253 }
9254
9255 fNotify = obj;
9256}
9257
9258////////////////////////////////////////////////////////////////////////////////
9259/// Change the name and title of this tree.
9261void TTree::SetObject(const char* name, const char* title)
9262{
9263 if (gPad) {
9264 gPad->Modified();
9265 }
9266
9267 // Trees are named objects in a THashList.
9268 // We must update hashlists if we change the name
9269 TFile *file = nullptr;
9270 TTreeCache *pf = nullptr;
9271 if (fDirectory) {
9272 fDirectory->Remove(this);
9273 if ((file = GetCurrentFile())) {
9274 pf = GetReadCache(file);
9275 file->SetCacheRead(nullptr,this,TFile::kDoNotDisconnect);
9276 }
9277 }
9278 // This changes our hash value.
9279 fName = name;
9280 fTitle = title;
9281 if (fDirectory) {
9282 fDirectory->Append(this);
9283 if (pf) {
9285 }
9286 }
9287}
9288
9289////////////////////////////////////////////////////////////////////////////////
9290/// Enable or disable parallel unzipping of Tree buffers.
9292void TTree::SetParallelUnzip(bool opt, Float_t RelSize)
9293{
9294#ifdef R__USE_IMT
9295 if (GetTree() == nullptr) {
9297 if (!GetTree())
9298 return;
9299 }
9300 if (GetTree() != this) {
9301 GetTree()->SetParallelUnzip(opt, RelSize);
9302 return;
9303 }
9304 TFile* file = GetCurrentFile();
9305 if (!file)
9306 return;
9307
9308 TTreeCache* pf = GetReadCache(file);
9309 if (pf && !( opt ^ (nullptr != dynamic_cast<TTreeCacheUnzip*>(pf)))) {
9310 // done with opt and type are in agreement.
9311 return;
9312 }
9313 delete pf;
9314 auto cacheSize = GetCacheAutoSize(true);
9315 if (opt) {
9316 auto unzip = new TTreeCacheUnzip(this, cacheSize);
9317 unzip->SetUnzipBufferSize( Long64_t(cacheSize * RelSize) );
9318 } else {
9319 pf = new TTreeCache(this, cacheSize);
9320 }
9321#else
9322 (void)opt;
9323 (void)RelSize;
9324#endif
9325}
9326
9327////////////////////////////////////////////////////////////////////////////////
9328/// Set perf stats
9331{
9332 fPerfStats = perf;
9333}
9334
9335////////////////////////////////////////////////////////////////////////////////
9336/// The current TreeIndex is replaced by the new index.
9337/// Note that this function does not delete the previous index.
9338/// This gives the possibility to play with more than one index, e.g.,
9339/// ~~~ {.cpp}
9340/// TVirtualIndex* oldIndex = tree.GetTreeIndex();
9341/// tree.SetTreeIndex(newIndex);
9342/// tree.Draw();
9343/// tree.SetTreeIndex(oldIndex);
9344/// tree.Draw(); etc
9345/// ~~~
9348{
9349 if (fTreeIndex) {
9350 fTreeIndex->SetTree(nullptr);
9351 }
9352 fTreeIndex = index;
9353}
9354
9355////////////////////////////////////////////////////////////////////////////////
9356/// Set tree weight.
9357///
9358/// The weight is used by TTree::Draw to automatically weight each
9359/// selected entry in the resulting histogram.
9360///
9361/// For example the equivalent of:
9362/// ~~~ {.cpp}
9363/// T.Draw("x", "w")
9364/// ~~~
9365/// is:
9366/// ~~~ {.cpp}
9367/// T.SetWeight(w);
9368/// T.Draw("x");
9369/// ~~~
9370/// This function is redefined by TChain::SetWeight. In case of a
9371/// TChain, an option "global" may be specified to set the same weight
9372/// for all trees in the TChain instead of the default behaviour
9373/// using the weights of each tree in the chain (see TChain::SetWeight).
9376{
9377 fWeight = w;
9378}
9379
9380////////////////////////////////////////////////////////////////////////////////
9381/// Print values of all active leaves for entry.
9382///
9383/// - if entry==-1, print current entry (default)
9384/// - if a leaf is an array, a maximum of lenmax elements is printed.
9386void TTree::Show(Long64_t entry, Int_t lenmax)
9387{
9388 if (entry != -1) {
9389 Int_t ret = LoadTree(entry);
9390 if (ret == -2) {
9391 Error("Show()", "Cannot read entry %lld (entry does not exist)", entry);
9392 return;
9393 } else if (ret == -1) {
9394 Error("Show()", "Cannot read entry %lld (I/O error)", entry);
9395 return;
9396 }
9397 ret = GetEntry(entry);
9398 if (ret == -1) {
9399 Error("Show()", "Cannot read entry %lld (I/O error)", entry);
9400 return;
9401 } else if (ret == 0) {
9402 Error("Show()", "Cannot read entry %lld (no data read)", entry);
9403 return;
9404 }
9405 }
9406 printf("======> EVENT:%lld\n", fReadEntry);
9407 TObjArray* leaves = GetListOfLeaves();
9408 Int_t nleaves = leaves->GetEntriesFast();
9409 Int_t ltype;
9410 for (Int_t i = 0; i < nleaves; i++) {
9411 TLeaf* leaf = (TLeaf*) leaves->UncheckedAt(i);
9412 TBranch* branch = leaf->GetBranch();
9413 if (branch->TestBit(kDoNotProcess)) {
9414 continue;
9415 }
9416 Int_t len = leaf->GetLen();
9417 if (len <= 0) {
9418 continue;
9419 }
9420 len = TMath::Min(len, lenmax);
9421 if (leaf->IsA() == TLeafElement::Class()) {
9422 leaf->PrintValue(lenmax);
9423 continue;
9424 }
9425 if (branch->GetListOfBranches()->GetEntriesFast() > 0) {
9426 continue;
9427 }
9428 ltype = 10;
9429 if (leaf->IsA() == TLeafF::Class()) {
9430 ltype = 5;
9431 }
9432 if (leaf->IsA() == TLeafD::Class()) {
9433 ltype = 5;
9434 }
9435 if (leaf->IsA() == TLeafC::Class()) {
9436 len = 1;
9437 ltype = 5;
9438 };
9439 printf(" %-15s = ", leaf->GetName());
9440 for (Int_t l = 0; l < len; l++) {
9441 leaf->PrintValue(l);
9442 if (l == (len - 1)) {
9443 printf("\n");
9444 continue;
9445 }
9446 printf(", ");
9447 if ((l % ltype) == 0) {
9448 printf("\n ");
9449 }
9450 }
9451 }
9452}
9453
9454////////////////////////////////////////////////////////////////////////////////
9455/// Start the TTreeViewer on this tree.
9456///
9457/// - ww is the width of the canvas in pixels
9458/// - wh is the height of the canvas in pixels
9460void TTree::StartViewer()
9461{
9462 GetPlayer();
9463 if (fPlayer) {
9464 fPlayer->StartViewer(600, 400);
9465 }
9466}
9467
9468////////////////////////////////////////////////////////////////////////////////
9469/// Stop the cache learning phase
9470///
9471/// Returns:
9472/// - 0 learning phase stopped or not active
9473/// - -1 on error
9476{
9477 if (!GetTree()) {
9478 if (LoadTree(0)<0) {
9479 Error("StopCacheLearningPhase","Could not load a tree");
9480 return -1;
9481 }
9482 }
9483 if (GetTree()) {
9484 if (GetTree() != this) {
9485 return GetTree()->StopCacheLearningPhase();
9486 }
9487 } else {
9488 Error("StopCacheLearningPhase", "No tree is available. Could not stop cache learning phase");
9489 return -1;
9490 }
9491
9492 TFile *f = GetCurrentFile();
9493 if (!f) {
9494 Error("StopCacheLearningPhase", "No file is available. Could not stop cache learning phase");
9495 return -1;
9496 }
9497 TTreeCache *tc = GetReadCache(f,true);
9498 if (!tc) {
9499 Error("StopCacheLearningPhase", "No cache is available. Could not stop learning phase");
9500 return -1;
9501 }
9502 tc->StopLearningPhase();
9503 return 0;
9504}
9505
9506////////////////////////////////////////////////////////////////////////////////
9507/// Set the fTree member for all branches and sub branches.
9509static void TBranch__SetTree(TTree *tree, TObjArray &branches)
9510{
9511 Int_t nb = branches.GetEntriesFast();
9512 for (Int_t i = 0; i < nb; ++i) {
9513 TBranch* br = (TBranch*) branches.UncheckedAt(i);
9514 br->SetTree(tree);
9515
9516 Int_t writeBasket = br->GetWriteBasket();
9517 for (Int_t j = writeBasket; j >= 0; --j) {
9518 TBasket *bk = (TBasket*)br->GetListOfBaskets()->UncheckedAt(j);
9519 if (bk) {
9520 tree->IncrementTotalBuffers(bk->GetBufferSize());
9521 }
9522 }
9523
9525 }
9526}
9527
9528////////////////////////////////////////////////////////////////////////////////
9529/// Set the fTree member for all friend elements.
9531void TFriendElement__SetTree(TTree *tree, TList *frlist)
9532{
9533 if (frlist) {
9534 TObjLink *lnk = frlist->FirstLink();
9535 while (lnk) {
9536 TFriendElement *elem = (TFriendElement*)lnk->GetObject();
9537 elem->fParentTree = tree;
9538 lnk = lnk->Next();
9539 }
9540 }
9541}
9542
9543////////////////////////////////////////////////////////////////////////////////
9544/// Stream a class object.
9547{
9548 if (b.IsReading()) {
9549 UInt_t R__s, R__c;
9550 if (fDirectory) {
9551 fDirectory->Remove(this);
9552 //delete the file cache if it points to this Tree
9553 TFile *file = fDirectory->GetFile();
9554 MoveReadCache(file,nullptr);
9555 }
9556 fDirectory = nullptr;
9557 fCacheDoAutoInit = true;
9558 fCacheUserSet = false;
9559 Version_t R__v = b.ReadVersion(&R__s, &R__c);
9560 if (R__v > 4) {
9561 b.ReadClassBuffer(TTree::Class(), this, R__v, R__s, R__c);
9562
9563 fBranches.SetOwner(true); // True needed only for R__v < 19 and most R__v == 19
9564
9565 if (fBranchRef) fBranchRef->SetTree(this);
9568
9569 if (fTreeIndex) {
9570 fTreeIndex->SetTree(this);
9571 }
9572 if (fIndex.fN) {
9573 Warning("Streamer", "Old style index in this tree is deleted. Rebuild the index via TTree::BuildIndex");
9574 fIndex.Set(0);
9575 fIndexValues.Set(0);
9576 }
9577 if (fEstimate <= 10000) {
9578 fEstimate = 1000000;
9579 }
9580
9581 if (fNClusterRange) {
9582 // The I/O allocated just enough memory to hold the
9583 // current set of ranges.
9585 }
9586
9587 // Throughs calls to `GetCacheAutoSize` or `EnableCache` (for example
9588 // by TTreePlayer::Process, the cache size will be automatically
9589 // determined unless the user explicitly call `SetCacheSize`
9590 fCacheSize = 0;
9591 fCacheUserSet = false;
9592
9594 return;
9595 }
9596 //====process old versions before automatic schema evolution
9597 Stat_t djunk;
9598 Int_t ijunk;
9603 b >> fScanField;
9604 b >> ijunk; fMaxEntryLoop = (Long64_t)ijunk;
9605 b >> ijunk; fMaxVirtualSize = (Long64_t)ijunk;
9606 b >> djunk; fEntries = (Long64_t)djunk;
9607 b >> djunk; fTotBytes = (Long64_t)djunk;
9608 b >> djunk; fZipBytes = (Long64_t)djunk;
9609 b >> ijunk; fAutoSave = (Long64_t)ijunk;
9610 b >> ijunk; fEstimate = (Long64_t)ijunk;
9611 if (fEstimate <= 10000) fEstimate = 1000000;
9613 if (fBranchRef) fBranchRef->SetTree(this);
9617 if (R__v > 1) fIndexValues.Streamer(b);
9618 if (R__v > 2) fIndex.Streamer(b);
9619 if (R__v > 3) {
9620 TList OldInfoList;
9621 OldInfoList.Streamer(b);
9622 OldInfoList.Delete();
9623 }
9624 fNClusterRange = 0;
9627 b.CheckByteCount(R__s, R__c, TTree::IsA());
9628 //====end of old versions
9629 } else {
9630 if (fBranchRef) {
9631 fBranchRef->Clear();
9632 }
9634 if (table) TRefTable::SetRefTable(nullptr);
9635
9636 b.WriteClassBuffer(TTree::Class(), this);
9637
9638 if (table) TRefTable::SetRefTable(table);
9639 }
9640}
9641
9642////////////////////////////////////////////////////////////////////////////////
9643/// Unbinned fit of one or more variable(s) from a tree.
9644///
9645/// funcname is a TF1 function.
9646///
9647/// \see TTree::Draw for explanations of the other parameters.
9648///
9649/// Fit the variable varexp using the function funcname using the
9650/// selection cuts given by selection.
9651///
9652/// The list of fit options is given in parameter option.
9653///
9654/// - option = "Q" Quiet mode (minimum printing)
9655/// - option = "V" Verbose mode (default is between Q and V)
9656/// - option = "E" Perform better Errors estimation using Minos technique
9657/// - option = "M" More. Improve fit results
9658///
9659/// You can specify boundary limits for some or all parameters via
9660/// ~~~ {.cpp}
9661/// func->SetParLimits(p_number, parmin, parmax);
9662/// ~~~
9663/// if parmin>=parmax, the parameter is fixed
9664///
9665/// Note that you are not forced to fix the limits for all parameters.
9666/// For example, if you fit a function with 6 parameters, you can do:
9667/// ~~~ {.cpp}
9668/// func->SetParameters(0,3.1,1.e-6,0.1,-8,100);
9669/// func->SetParLimits(4,-10,-4);
9670/// func->SetParLimits(5, 1,1);
9671/// ~~~
9672/// With this setup:
9673///
9674/// - Parameters 0->3 can vary freely
9675/// - Parameter 4 has boundaries [-10,-4] with initial value -8
9676/// - Parameter 5 is fixed to 100.
9677///
9678/// For the fit to be meaningful, the function must be self-normalized.
9679///
9680/// i.e. It must have the same integral regardless of the parameter
9681/// settings. Otherwise the fit will effectively just maximize the
9682/// area.
9683///
9684/// It is mandatory to have a normalization variable
9685/// which is fixed for the fit. e.g.
9686/// ~~~ {.cpp}
9687/// TF1* f1 = new TF1("f1", "gaus(0)/sqrt(2*3.14159)/[2]", 0, 5);
9688/// f1->SetParameters(1, 3.1, 0.01);
9689/// f1->SetParLimits(0, 1, 1); // fix the normalization parameter to 1
9690/// data->UnbinnedFit("f1", "jpsimass", "jpsipt>3.0");
9691/// ~~~
9692/// 1, 2 and 3 Dimensional fits are supported. See also TTree::Fit
9693///
9694/// Return status:
9695///
9696/// - The function return the status of the fit in the following form
9697/// fitResult = migradResult + 10*minosResult + 100*hesseResult + 1000*improveResult
9698/// - The fitResult is 0 is the fit is OK.
9699/// - The fitResult is negative in case of an error not connected with the fit.
9700/// - The number of entries used in the fit can be obtained via mytree.GetSelectedRows();
9701/// - If the number of selected entries is null the function returns -1
9703Int_t TTree::UnbinnedFit(const char* funcname, const char* varexp, const char* selection, Option_t* option, Long64_t nentries, Long64_t firstentry)
9704{
9705 GetPlayer();
9706 if (fPlayer) {
9707 return fPlayer->UnbinnedFit(funcname, varexp, selection, option, nentries, firstentry);
9708 }
9709 return -1;
9710}
9711
9712////////////////////////////////////////////////////////////////////////////////
9713/// Replace current attributes by current style.
9716{
9717 if (gStyle->IsReading()) {
9726 } else {
9735 }
9736}
9737
9738////////////////////////////////////////////////////////////////////////////////
9739/// Write this object to the current directory. For more see TObject::Write
9740/// If option & kFlushBasket, call FlushBasket before writing the tree.
9742Int_t TTree::Write(const char *name, Int_t option, Int_t bufsize) const
9743{
9746 return 0;
9747 return TObject::Write(name, option, bufsize);
9748}
9749
9750////////////////////////////////////////////////////////////////////////////////
9751/// Write this object to the current directory. For more see TObject::Write
9752/// If option & kFlushBasket, call FlushBasket before writing the tree.
9754Int_t TTree::Write(const char *name, Int_t option, Int_t bufsize)
9755{
9756 return ((const TTree*)this)->Write(name, option, bufsize);
9757}
9758
9759////////////////////////////////////////////////////////////////////////////////
9760/// \class TTreeFriendLeafIter
9761///
9762/// Iterator on all the leaves in a TTree and its friend
9763
9765
9766////////////////////////////////////////////////////////////////////////////////
9767/// Create a new iterator. By default the iteration direction
9768/// is kIterForward. To go backward use kIterBackward.
9771: fTree(const_cast<TTree*>(tree))
9772, fLeafIter(nullptr)
9773, fTreeIter(nullptr)
9774, fDirection(dir)
9775{
9776}
9777
9778////////////////////////////////////////////////////////////////////////////////
9779/// Copy constructor. Does NOT copy the 'cursor' location!
9782: TIterator(iter)
9783, fTree(iter.fTree)
9784, fLeafIter(nullptr)
9785, fTreeIter(nullptr)
9786, fDirection(iter.fDirection)
9787{
9788}
9789
9790////////////////////////////////////////////////////////////////////////////////
9791/// Overridden assignment operator. Does NOT copy the 'cursor' location!
9794{
9795 if (this != &rhs && rhs.IsA() == TTreeFriendLeafIter::Class()) {
9796 const TTreeFriendLeafIter &rhs1 = (const TTreeFriendLeafIter &)rhs;
9797 fDirection = rhs1.fDirection;
9798 }
9799 return *this;
9800}
9801
9802////////////////////////////////////////////////////////////////////////////////
9803/// Overridden assignment operator. Does NOT copy the 'cursor' location!
9806{
9807 if (this != &rhs) {
9808 fDirection = rhs.fDirection;
9809 }
9810 return *this;
9811}
9812
9813////////////////////////////////////////////////////////////////////////////////
9814/// Go the next friend element
9817{
9818 if (!fTree) return nullptr;
9819
9820 TObject * next;
9821 TTree * nextTree;
9822
9823 if (!fLeafIter) {
9824 TObjArray *list = fTree->GetListOfLeaves();
9825 if (!list) return nullptr; // Can happen with an empty chain.
9827 if (!fLeafIter) return nullptr;
9828 }
9829
9830 next = fLeafIter->Next();
9831 if (!next) {
9832 if (!fTreeIter) {
9834 if (!list) return next;
9836 if (!fTreeIter) return nullptr;
9837 }
9838 TFriendElement * nextFriend = (TFriendElement*) fTreeIter->Next();
9839 ///nextTree = (TTree*)fTreeIter->Next();
9840 if (nextFriend) {
9841 nextTree = const_cast<TTree*>(nextFriend->GetTree());
9842 if (!nextTree) return Next();
9845 if (!fLeafIter) return nullptr;
9846 next = fLeafIter->Next();
9847 }
9848 }
9849 return next;
9850}
9851
9852////////////////////////////////////////////////////////////////////////////////
9853/// Returns the object option stored in the list.
9856{
9857 if (fLeafIter) return fLeafIter->GetOption();
9858 return "";
9859}
#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
unsigned char UChar_t
Definition RtypesCore.h:38
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:382
const Int_t kDoNotProcess
Definition TBranch.h:56
EDataType
Definition TDataType.h:28
@ kNoType_t
Definition TDataType.h:33
@ kFloat_t
Definition TDataType.h:31
@ kULong64_t
Definition TDataType.h:32
@ kInt_t
Definition TDataType.h:30
@ kchar
Definition TDataType.h:31
@ kLong_t
Definition TDataType.h:30
@ kDouble32_t
Definition TDataType.h:31
@ kShort_t
Definition TDataType.h:29
@ kBool_t
Definition TDataType.h:32
@ kBits
Definition TDataType.h:34
@ kULong_t
Definition TDataType.h:30
@ kLong64_t
Definition TDataType.h:32
@ kUShort_t
Definition TDataType.h:29
@ kDouble_t
Definition TDataType.h:31
@ kCharStar
Definition TDataType.h:34
@ kChar_t
Definition TDataType.h:29
@ kUChar_t
Definition TDataType.h:29
@ kCounter
Definition TDataType.h:34
@ kUInt_t
Definition TDataType.h:30
@ kFloat16_t
Definition TDataType.h:33
@ kOther_t
Definition TDataType.h:32
#define gDirectory
Definition TDirectory.h:384
R__EXTERN TEnv * gEnv
Definition TEnv.h:170
#define R__ASSERT(e)
Checks condition e and reports a fatal error if it's false.
Definition TError.h:125
void Error(const char *location, const char *msgfmt,...)
Use this function in case an error occurred.
Definition TError.cxx:185
#define N
static unsigned int total
Option_t Option_t option
Option_t Option_t SetLineWidth
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t cursor
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t Float_t Float_t Int_t Int_t UInt_t UInt_t Rectangle_t Int_t Int_t Window_t TString Int_t GCValues_t GetPrimarySelectionOwner GetDisplay GetScreen GetColormap GetNativeEvent const char const char dpyName wid window const char font_name cursor keysym reg const char only_if_exist regb h Point_t winding char text const char depth char const char Int_t count const char ColorStruct_t color const char filename
Option_t Option_t SetFillStyle
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t Float_t Float_t Int_t Int_t UInt_t UInt_t Rectangle_t Int_t Int_t Window_t TString Int_t GCValues_t GetPrimarySelectionOwner GetDisplay GetScreen GetColormap GetNativeEvent const char const char dpyName wid window const char font_name cursor keysym reg const char only_if_exist regb h Point_t winding char text const char depth char const char Int_t count const char ColorStruct_t color const char Pixmap_t Pixmap_t PictureAttributes_t attr const char char ret_data h unsigned char height h offset
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t Float_t Float_t Int_t Int_t UInt_t UInt_t Rectangle_t result
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t index
Option_t Option_t SetLineColor
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t Float_t Float_t Int_t Int_t UInt_t UInt_t Rectangle_t Int_t Int_t Window_t TString Int_t GCValues_t GetPrimarySelectionOwner GetDisplay GetScreen GetColormap GetNativeEvent const char const char dpyName wid window const char font_name cursor keysym reg const char only_if_exist regb h Point_t winding char text const char depth char const char Int_t count const char ColorStruct_t color const char Pixmap_t Pixmap_t PictureAttributes_t attr const char char ret_data h unsigned char height h Atom_t Int_t ULong_t ULong_t unsigned char prop_list Atom_t Atom_t Atom_t Time_t UChar_t len
Option_t Option_t SetFillColor
Option_t Option_t SetMarkerStyle
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t src
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void reg
Option_t Option_t style
char name[80]
Definition TGX11.cxx:110
int nentries
R__EXTERN TInterpreter * gCling
Int_t gDebug
Definition TROOT.cxx:597
R__EXTERN TVirtualMutex * gROOTMutex
Definition TROOT.h:63
#define gROOT
Definition TROOT.h:406
void Printf(const char *fmt,...)
Formats a string in a circular formatting buffer and prints the string.
Definition TString.cxx:2503
R__EXTERN TStyle * gStyle
Definition TStyle.h:436
R__EXTERN TSystem * gSystem
Definition TSystem.h:561
constexpr Int_t kNEntriesResort
Definition TTree.cxx:450
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:4793
static char DataTypeToChar(EDataType datatype)
Definition TTree.cxx:462
void TFriendElement__SetTree(TTree *tree, TList *frlist)
Set the fTree member for all friend elements.
Definition TTree.cxx:9530
bool CheckReshuffling(TTree &mainTree, TTree &friendTree)
Definition TTree.cxx:1240
static void TBranch__SetTree(TTree *tree, TObjArray &branches)
Set the fTree member for all branches and sub branches.
Definition TTree.cxx:9508
constexpr Float_t kNEntriesResortInv
Definition TTree.cxx:451
#define R__LOCKGUARD(mutex)
#define gPad
#define snprintf
Definition civetweb.c:1540
Bool_t HasRuleWithSourceClass(const TString &source) const
Return True if we have any rule whose source class is 'source'.
A helper class for managing IMT work during TTree:Fill operations.
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 Foreach(F func, unsigned nTimes, unsigned nChunks=0)
Execute a function without arguments several times in parallel, dividing the execution in nChunks.
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:19
virtual void Streamer(TBuffer &)
virtual Color_t GetFillColor() const
Return the fill area color.
Definition TAttFill.h:30
virtual Style_t GetFillStyle() const
Return the fill area style.
Definition TAttFill.h:31
Line Attributes class.
Definition TAttLine.h:18
virtual void Streamer(TBuffer &)
virtual Color_t GetLineColor() const
Return the line color.
Definition TAttLine.h:33
virtual void SetLineStyle(Style_t lstyle)
Set the line style.
Definition TAttLine.h:42
virtual Width_t GetLineWidth() const
Return the line width.
Definition TAttLine.h:35
virtual Style_t GetLineStyle() const
Return the line style.
Definition TAttLine.h:34
Marker Attributes class.
Definition TAttMarker.h:19
virtual Style_t GetMarkerStyle() const
Return the marker style.
Definition TAttMarker.h:32
virtual void SetMarkerColor(Color_t mcolor=1)
Set the marker color.
Definition TAttMarker.h:38
virtual Color_t GetMarkerColor() const
Return the marker color.
Definition TAttMarker.h:31
virtual Size_t GetMarkerSize() const
Return the marker size.
Definition TAttMarker.h:33
virtual void SetMarkerStyle(Style_t mstyle=1)
Set the marker style.
Definition TAttMarker.h:40
virtual void Streamer(TBuffer &)
virtual void SetMarkerSize(Size_t msize=1)
Set the marker size.
Definition TAttMarker.h:45
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
virtual Int_t DropBuffers()
Drop buffers of this basket if it is not the current basket.
Definition TBasket.cxx:173
Int_t GetBufferSize() const
Definition TBasket.h:122
A Branch for the case of an array of clone objects.
A Branch for the case of an object.
virtual bool IsObjectOwner() const
virtual void SetBranchFolder()
static TClass * Class()
Int_t GetClassVersion()
const char * GetClassName() const override
Return the name of the user class whose content is stored in this branch, if any.
void ResetAddress() override
Set branch address to zero and free all allocated memory.
Int_t Unroll(const char *name, TClass *cltop, TClass *cl, char *ptr, Int_t basketsize, Int_t splitlevel, Int_t btype)
Split class cl into sub-branches of this branch.
void SetAddress(void *addobj) override
Point this branch at an object.
virtual void SetTargetClass(const char *name)
Set the name of the class of the in-memory object into which the data will loaded.
void SetObject(void *objadd) override
Set object this branch is pointing to.
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
virtual TLeaf * GetLeaf(const char *name) const
Return pointer to the 1st Leaf named name in thisBranch.
Definition TBranch.cxx:2055
virtual bool GetMakeClass() const
Return whether this branch is in a mode where the object are decomposed or not (Also known as MakeCla...
Definition TBranch.cxx:2117
virtual void SetupAddresses()
If the branch address is not set, we set all addresses starting with the top level parent branch.
Definition TBranch.cxx:3294
virtual void ResetAddress()
Reset the address of the branch.
Definition TBranch.cxx:2651
virtual Long64_t GetBasketSeek(Int_t basket) const
Return address of basket in the file.
Definition TBranch.cxx:1302
virtual char * GetAddress() const
Definition TBranch.h:212
void SetCompressionSettings(Int_t settings=ROOT::RCompressionSetting::EDefaults::kUseCompiledDefault)
Set compression settings.
Definition TBranch.cxx:2805
TTree * GetTree() const
Definition TBranch.h:252
static TClass * Class()
virtual TString GetFullName() const
Return the 'full' name of the branch.
Definition TBranch.cxx:2031
Int_t GetWriteBasket() const
Definition TBranch.h:238
virtual void DropBaskets(Option_t *option="")
Loop on all branch baskets.
Definition TBranch.cxx:757
TObjArray * GetListOfBranches()
Definition TBranch.h:246
virtual void SetTree(TTree *tree)
Definition TBranch.h:287
virtual Int_t GetEntry(Long64_t entry=0, Int_t getall=0)
Read all leaves of entry and return total number of bytes read.
Definition TBranch.cxx:1706
TClass * IsA() const override
Definition TBranch.h:295
void Print(Option_t *option="") const override
Print TBranch parameters.
Definition TBranch.cxx:2341
static void ResetCount()
Static function resetting fgCount.
Definition TBranch.cxx:2674
virtual void SetObject(void *objadd)
Set object this branch is pointing to.
Definition TBranch.cxx:2936
Int_t FlushBaskets()
Flush to disk all the baskets of this branch and any of subbranches.
Definition TBranch.cxx:1136
virtual void SetAddress(void *add)
Set address of this branch.
Definition TBranch.cxx:2682
Int_t GetNleaves() const
Definition TBranch.h:249
virtual void SetFile(TFile *file=nullptr)
Set file where this branch writes/reads its buffers.
Definition TBranch.cxx:2863
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:2821
TObjArray * GetListOfBaskets()
Definition TBranch.h:245
Long64_t GetEntries() const
Definition TBranch.h:251
virtual void UpdateFile()
Refresh the value of fDirectory (i.e.
Definition TBranch.cxx:3304
Int_t GetReadBasket() const
Definition TBranch.h:236
Int_t GetMaxBaskets() const
Definition TBranch.h:248
virtual TFile * GetFile(Int_t mode=0)
Return pointer to the file where branch buffers reside, returns 0 in case branch buffers reside in th...
Definition TBranch.cxx:1853
virtual void KeepCircular(Long64_t maxEntries)
keep a maximum of fMaxEntries in memory
Definition TBranch.cxx:2283
virtual void ResetAfterMerge(TFileMergeInfo *)
Reset a Branch.
Definition TBranch.cxx:2598
virtual TBranch * FindBranch(const char *name)
Find the immediate sub-branch with passed name.
Definition TBranch.cxx:1035
virtual Int_t LoadBaskets()
Baskets associated to this branch are forced to be in memory.
Definition TBranch.cxx:2309
void SetIOFeatures(TIOFeatures &features)
Definition TBranch.h:283
Long64_t GetTotBytes(Option_t *option="") const
Return total number of bytes in the branch (excluding current buffer) if option ="*" includes all sub...
Definition TBranch.cxx:2220
virtual void SetOffset(Int_t offset=0)
Definition TBranch.h:285
virtual Int_t GetExpectedType(TClass *&clptr, EDataType &type)
Fill expectedClass and expectedType with information on the data type of the object/values contained ...
Definition TBranch.cxx:1834
virtual Int_t GetBasketSize() const
Definition TBranch.h:217
Long64_t GetZipBytes(Option_t *option="") const
Return total number of zip bytes in the branch if option ="*" includes all sub-branches of this branc...
Definition TBranch.cxx:2238
virtual void SetBasketSize(Int_t buffsize)
Set the basket size The function makes sure that the basket size is greater than fEntryOffsetlen.
Definition TBranch.cxx:2729
virtual void Refresh(TBranch *b)
Refresh this branch using new information in b This function is called by TTree::Refresh.
Definition TBranch.cxx:2508
virtual bool SetMakeClass(bool decomposeObj=true)
Set the branch in a mode where the object are decomposed (Also known as MakeClass mode).
Definition TBranch.cxx:2927
TObjArray * GetListOfLeaves()
Definition TBranch.h:247
Int_t Fill()
Definition TBranch.h:205
virtual void Reset(Option_t *option="")
Reset a Branch.
Definition TBranch.cxx:2557
TBranch * GetMother() const
Get our top-level parent branch in the tree.
Definition TBranch.cxx:2127
virtual Int_t FillImpl(ROOT::Internal::TBranchIMTHelper *)
Loop on all leaves of this branch to fill Basket buffer.
Definition TBranch.cxx:856
Int_t GetEntryOffsetLen() const
Definition TBranch.h:227
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:81
Bool_t CanSplit() const
Return true if the data member of this TClass can be saved separately.
Definition TClass.cxx:2388
ROOT::ESTLType GetCollectionType() const
Return the 'type' of the STL the TClass is representing.
Definition TClass.cxx:2955
void * New(ENewType defConstructor=kClassNew, Bool_t quiet=kFALSE) const
Return a pointer to a newly allocated object of this class.
Definition TClass.cxx:5047
Bool_t HasDataMemberInfo() const
Definition TClass.h:407
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:508
void Destructor(void *obj, Bool_t dtorOnly=kFALSE)
Explicitly call destructor for object.
Definition TClass.cxx:5469
void BuildRealData(void *pointer=nullptr, Bool_t isTransient=kFALSE)
Build a full list of persistent data members.
Definition TClass.cxx:2100
const std::type_info * GetTypeInfo() const
Definition TClass.h:496
TList * GetListOfDataMembers(Bool_t load=kTRUE)
Return list containing the TDataMembers of a class.
Definition TClass.cxx:3839
TList * GetListOfRealData() const
Definition TClass.h:453
Bool_t CanIgnoreTObjectStreamer()
Definition TClass.h:393
const ROOT::Detail::TSchemaRuleSet * GetSchemaRules() const
Return the set of the schema rules if any.
Definition TClass.cxx:2001
TList * GetListOfBases()
Return list containing the TBaseClass(es) of a class.
Definition TClass.cxx:3705
Bool_t IsLoaded() const
Return true if the shared library of this class is currently in the a process's memory.
Definition TClass.cxx:5981
Bool_t IsTObject() const
Return kTRUE is the class inherits from TObject.
Definition TClass.cxx:6007
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:4668
Bool_t InheritsFrom(const char *cl) const override
Return kTRUE if this class inherits from a class with name "classname".
Definition TClass.cxx:4943
TVirtualCollectionProxy * GetCollectionProxy() const
Return the proxy describing the collection (if any).
Definition TClass.cxx:2966
TVirtualStreamerInfo * GetConversionStreamerInfo(const char *onfile_classname, Int_t version) const
Return a Conversion StreamerInfo from the class 'classname' for version number 'version' to this clas...
Definition TClass.cxx:7155
TVirtualStreamerInfo * FindConversionStreamerInfo(const char *onfile_classname, UInt_t checksum) const
Return a Conversion StreamerInfo from the class 'classname' for the layout represented by 'checksum' ...
Definition TClass.cxx:7262
Version_t GetClassVersion() const
Definition TClass.h:420
TClass * GetActualClass(const void *object) const
Return a pointer to the real class of the object.
Definition TClass.cxx:2676
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:3037
Int_t WriteBuffer(TBuffer &b, void *pointer, const char *info="")
Function called by the Streamer functions to serialize object at p to buffer b.
Definition TClass.cxx:6848
An array of clone (identical) objects.
void BypassStreamer(Bool_t bypass=kTRUE)
When the kBypassStreamer bit is set, the automatically generated Streamer can call directly TClass::W...
TClass * GetClass() const
static TClass * Class()
Collection abstract base class.
Definition TCollection.h:65
virtual TObject ** GetObjectRef(const TObject *obj) const =0
virtual TIterator * MakeIterator(Bool_t dir=kIterForward) const =0
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.
void Append(TObject *obj, Bool_t replace=kFALSE) override
Append object 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 Bool_t cd()
Change current directory to "this" directory.
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 Int_t ReadTObject(TObject *, const char *)
Definition TDirectory.h:249
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
virtual Long64_t GetEntry(Int_t index) const
Return value of entry at index in the list.
virtual bool GetReapplyCut() const
Definition TEventList.h:57
virtual Int_t GetN() const
Definition TEventList.h:56
A cache when reading files over the network.
virtual void WaitFinishPrefetch()
virtual Int_t GetBufferSize() const
TIOFeatures * fIOFeatures
TDirectory * fOutputDirectory
A ROOT file is an on-disk file, usually with extension .root, that stores objects in a file-system-li...
Definition TFile.h:53
virtual void SetCacheRead(TFileCacheRead *cache, TObject *tree=nullptr, ECacheAction action=kDisconnect)
Set a pointer to the read cache.
Definition TFile.cxx:2365
Int_t GetCompressionSettings() const
Definition TFile.h:397
Int_t GetCompressionLevel() const
Definition TFile.h:391
virtual Long64_t GetEND() const
Definition TFile.h:231
virtual void WriteStreamerInfo()
Write the list of TStreamerInfo as a single object in this file The class Streamer description for al...
Definition TFile.cxx:3792
@ kDoNotDisconnect
Definition TFile.h:70
virtual void Flush()
Synchronize a file's in-memory and on-disk states.
Definition TFile.cxx:1141
virtual void MakeFree(Long64_t first, Long64_t last)
Mark unused bytes on the file.
Definition TFile.cxx:1484
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:4089
virtual void WriteHeader()
Write File Header.
Definition TFile.cxx:2615
Int_t GetRecordHeader(char *buf, Long64_t first, Int_t maxbytes, Int_t &nbytes, Int_t &objlen, Int_t &keylen)
Read the logical record header starting at a certain postion.
Definition TFile.cxx:1301
TFileCacheRead * GetCacheRead(const TObject *tree=nullptr) const
Return a pointer to the current read cache.
Definition TFile.cxx:1262
<div class="legacybox"><h2>Legacy Code</h2> TFolder is a legacy interface: there will be no bug fixes...
Definition TFolder.h:30
TCollection * GetListOfFolders() const
Definition TFolder.h:55
virtual Int_t Occurence(const TObject *obj) const
Return occurence number of object in the list of objects of this folder.
Definition TFolder.cxx:427
static TClass * Class()
A TFriendElement TF describes a TTree object TF in a file.
virtual const char * GetTreeName() const
Get the actual TTree name of the friend.
virtual TTree * GetTree()
Return pointer to friend TTree.
bool IsUpdated() const
virtual TFile * GetFile()
Return pointer to TFile containing this friend TTree.
TTree * fParentTree
! pointer to the parent TTree
virtual Int_t DeleteGlobal(void *obj)=0
void Reset()
Iterator abstract base class.
Definition TIterator.h:30
virtual TObject * Next()=0
virtual TClass * IsA() const
Definition TIterator.h:48
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:539
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 Double_t GetValue(Int_t i=0) const
Definition TLeaf.h:183
virtual void * GetValuePointer() const
Definition TLeaf.h:138
virtual Int_t GetLenType() const
Definition TLeaf.h:133
virtual void ReadValue(std::istream &, Char_t=' ')
Definition TLeaf.h:156
virtual Int_t GetMaximum() const
Definition TLeaf.h:134
virtual Int_t GetLen() const
Return the number of effective elements of this leaf, for the current entry.
Definition TLeaf.cxx:404
virtual TLeaf * GetLeafCount() const
If this leaf stores a variable-sized array or a multi-dimensional array whose last dimension has vari...
Definition TLeaf.h:121
TClass * IsA() const override
Definition TLeaf.h:168
virtual bool IncludeRange(TLeaf *)
Definition TLeaf.h:146
virtual void SetAddress(void *add=nullptr)
Definition TLeaf.h:185
TBranch * GetBranch() const
Definition TLeaf.h:116
@ 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 TString GetFullName() const
Return the full name (including the parent's branch names) of the leaf.
Definition TLeaf.cxx:224
virtual Int_t GetOffset() const
Definition TLeaf.h:137
virtual void PrintValue(Int_t i=0) const
Definition TLeaf.h:184
A doubly linked list.
Definition TList.h:38
void Streamer(TBuffer &) override
Stream all objects in the collection to or from the I/O buffer.
Definition TList.cxx:1189
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
TObject * First() const override
Return the first object in the list. Returns 0 when list is empty.
Definition TList.cxx:657
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
TObject * Clone(const char *newname="") const override
Make a clone of an object using the Streamer facility.
Definition TNamed.cxx:74
virtual void SetTitle(const char *title="")
Set the title of the TNamed.
Definition TNamed.cxx:164
const char * GetName() const override
Returns name of object.
Definition TNamed.h:47
void Streamer(TBuffer &) override
Stream an object of class TObject.
const char * GetTitle() const override
Returns title of object.
Definition TNamed.h:48
TString fTitle
Definition TNamed.h:33
TNamed()
Definition TNamed.h:36
TString fName
Definition TNamed.h:32
virtual void SetName(const char *name)
Set the name of the TNamed.
Definition TNamed.cxx:140
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.
TObject * Last() const override
Return the object in the last filled slot. Returns 0 if no entries.
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.
TIterator * MakeIterator(Bool_t dir=kIterForward) const override
Returns an array iterator.
virtual void Compress()
Remove empty slots from array.
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
TObject * RemoveAt(Int_t idx) override
Remove object at index idx.
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:599
virtual const char * GetName() const
Returns name of object.
Definition TObject.cxx:444
R__ALWAYS_INLINE Bool_t TestBit(UInt_t f) const
Definition TObject.h:199
@ kBitMask
Definition TObject.h:86
virtual const char * ClassName() const
Returns name of class to which the object belongs.
Definition TObject.cxx:213
virtual void Warning(const char *method, const char *msgfmt,...) const
Issue warning message.
Definition TObject.cxx:979
R__ALWAYS_INLINE Bool_t IsZombie() const
Definition TObject.h:153
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:886
@ kOnlyPrepStep
Used to request that the class specific implementation of TObject::Write just prepare the objects to ...
Definition TObject.h:106
void SetBit(UInt_t f, Bool_t set)
Set or unset the user status bits as specified in f.
Definition TObject.cxx:786
virtual Bool_t InheritsFrom(const char *classname) const
Returns kTRUE if object inherits from class "classname".
Definition TObject.cxx:530
virtual void Error(const char *method, const char *msgfmt,...) const
Issue error message.
Definition TObject.cxx:993
virtual void Fatal(const char *method, const char *msgfmt,...) const
Issue fatal error message.
Definition TObject.cxx:1021
virtual const char * GetTitle() const
Returns title of object.
Definition TObject.cxx:488
virtual TClass * IsA() const
Definition TObject.h:243
void ResetBit(UInt_t f)
Definition TObject.h:198
@ kCanDelete
if object in a list can be deleted
Definition TObject.h:62
@ kMustCleanup
if object destructor must call RecursiveRemove()
Definition TObject.h:64
virtual void Info(const char *method, const char *msgfmt,...) const
Issue info message.
Definition TObject.cxx:967
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
const char * GetName() const override
Returns name of object.
Definition TRealData.h:52
TDataMember * GetDataMember() const
Definition TRealData.h:53
Bool_t IsObject() const
Definition TRealData.h:56
Long_t GetThisOffset() const
Definition TRealData.h:55
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.
void ForceWriteInfo(TFile *file, Bool_t force=kFALSE) override
Recursively mark streamer infos for writing to a file.
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
TSubString Strip(EStripType s=kTrailing, char c=' ') const
Return a substring of self stripped at beginning and/or end.
Definition TString.cxx:1163
Double_t Atof() const
Return floating-point value contained in string.
Definition TString.cxx:2054
Ssiz_t First(char c) const
Find first occurrence of a character c.
Definition TString.cxx:538
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
Ssiz_t Last(char c) const
Find last occurrence of a character c.
Definition TString.cxx:931
TObjArray * Tokenize(const TString &delim) const
This function is used to isolate sequential tokens in a TString.
Definition TString.cxx:2264
Bool_t IsNull() const
Definition TString.h:414
TString & Remove(Ssiz_t pos)
Definition TString.h:685
TString & Append(const char *cs)
Definition TString.h:572
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:379
Color_t GetHistLineColor() const
Definition TStyle.h:233
Bool_t IsReading() const
Definition TStyle.h:296
void SetHistLineStyle(Style_t styl=0)
Definition TStyle.h:382
Style_t GetHistFillStyle() const
Definition TStyle.h:234
Color_t GetHistFillColor() const
Definition TStyle.h:232
void SetHistLineColor(Color_t color=1)
Definition TStyle.h:380
Style_t GetHistLineStyle() const
Definition TStyle.h:235
void SetHistFillStyle(Style_t styl=0)
Definition TStyle.h:381
Width_t GetHistLineWidth() const
Definition TStyle.h:236
void SetHistLineWidth(Width_t width=1)
Definition TStyle.h:383
A zero length substring is legal.
Definition TString.h:85
TString & String()
Definition TString.h:124
virtual const char * Getenv(const char *env)
Get environment variable.
Definition TSystem.cxx:1665
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:1296
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
bool IsAutoCreated() const
Definition TTreeCache.h:150
Int_t SetBufferSize(Long64_t buffersize) override
Change the underlying buffer size of the cache.
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...
TTree * GetTree() const
Definition TTreeCache.h:149
virtual void SetEntryRange(Long64_t emin, Long64_t emax)
Set the minimum and maximum entry number to be processed this information helps to optimize the numbe...
virtual Int_t DropBranch(TBranch *b, bool subbranches=false)
Remove a branch to the list of branches to be stored in the cache this function is called by TBranch:...
void SetAutoCreated(bool val)
Definition TTreeCache.h:164
virtual void StopLearningPhase()
This is the counterpart of StartLearningPhase() and can be used to stop the learning phase.
void Print(Option_t *option="") const override
Print cache statistics.
Int_t AddBranch(TBranch *b, bool subgbranches=false) override
Add a branch to the list of branches to be stored in the cache this function is called by the user vi...
Class implementing or helping the various TTree cloning method.
Definition TTreeCloner.h:31
const char * GetWarning() const
bool Exec()
Execute the cloning.
bool NeedConversion()
bool IsValid()
void SetCacheSize(Long64_t size)
Set the cache size used by the matching TFile.
Iterator on all the leaves in a TTree and its friend.
Definition TTree.h:716
TTree * fTree
tree being iterated
Definition TTree.h:719
TIterator & operator=(const TIterator &rhs) override
Overridden assignment operator. Does NOT copy the 'cursor' location!
Definition TTree.cxx:9792
TObject * Next() override
Go the next friend element.
Definition TTree.cxx:9815
TIterator * fLeafIter
current leaf sub-iterator.
Definition TTree.h:720
Option_t * GetOption() const override
Returns the object option stored in the list.
Definition TTree.cxx:9854
TIterator * fTreeIter
current tree sub-iterator.
Definition TTree.h:721
bool fDirection
iteration direction
Definition TTree.h:722
static TClass * Class()
Helper class to iterate over cluster of baskets.
Definition TTree.h:270
Long64_t GetEstimatedClusterSize()
Estimate the cluster size.
Definition TTree.cxx:611
Long64_t Previous()
Move on to the previous cluster and return the starting entry of this previous cluster.
Definition TTree.cxx:694
Long64_t Next()
Move on to the next cluster and return the starting entry of this next cluster.
Definition TTree.cxx:650
Long64_t GetNextEntry()
Definition TTree.h:307
TClusterIterator(TTree *tree, Long64_t firstEntry)
Regular constructor.
Definition TTree.cxx:560
Helper class to prevent infinite recursion in the usage of TTree Friends.
Definition TTree.h:188
TFriendLock & operator=(const TFriendLock &)
Assignment operator.
Definition TTree.cxx:530
TFriendLock(const TFriendLock &)
Copy constructor.
Definition TTree.cxx:520
UInt_t fMethodBit
Definition TTree.h:192
TTree * fTree
Definition TTree.h:191
~TFriendLock()
Restore the state of tree the same as before we set the lock.
Definition TTree.cxx:543
A TTree represents a columnar dataset.
Definition TTree.h:79
virtual Int_t Fill()
Fill all branches.
Definition TTree.cxx:4603
virtual TFriendElement * AddFriend(const char *treename, const char *filename="")
Add a TFriendElement to the list of friends.
Definition TTree.cxx:1332
TBranchRef * fBranchRef
Branch supporting the TRefTable (if any)
Definition TTree.h:136
TStreamerInfo * BuildStreamerInfo(TClass *cl, void *pointer=nullptr, bool canOptimize=true)
Build StreamerInfo for class cl.
Definition TTree.cxx:2652
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:4841
virtual void SetBranchStatus(const char *bname, bool status=true, UInt_t *found=nullptr)
Set branch status to Process or DoNotProcess.
Definition TTree.cxx:8534
bool EnableCache()
Enable the TTreeCache unless explicitly disabled for this TTree by a prior call to SetCacheSize(0).
Definition TTree.cxx:2685
virtual TBranch * GetBranch(const char *name)
Return pointer to the branch with the given name in this tree or its friends.
Definition TTree.cxx:5294
static Int_t GetBranchStyle()
Static function returning the current branch style.
Definition TTree.cxx:5395
TList * fFriends
pointer to list of friend elements
Definition TTree.h:130
bool fIMTEnabled
! true if implicit multi-threading is enabled for this tree
Definition TTree.h:142
virtual bool GetBranchStatus(const char *branchname) const
Return status of branch with name branchname.
Definition TTree.cxx:5380
UInt_t fFriendLockStatus
! Record which method is locking the friend recursion
Definition TTree.h:137
virtual TLeaf * GetLeafImpl(const char *branchname, const char *leafname)
Return pointer to the 1st Leaf named name in any Branch of this Tree or any branch in the list of fri...
Definition TTree.cxx:6098
Long64_t fTotBytes
Total number of bytes in all branches before compression.
Definition TTree.h:86
virtual Int_t FlushBaskets(bool create_cluster=true) const
Write to disk all the basket that have not yet been individually written and create an event cluster ...
Definition TTree.cxx:5129
Int_t fMaxClusterRange
! Memory allocated for the cluster range.
Definition TTree.h:96
virtual void Show(Long64_t entry=-1, Int_t lenmax=20)
Print values of all active leaves for entry.
Definition TTree.cxx:9385
TEventList * fEventList
! Pointer to event selection list (if one)
Definition TTree.h:125
virtual Long64_t GetAutoSave() const
Definition TTree.h:448
virtual Int_t StopCacheLearningPhase()
Stop the cache learning phase.
Definition TTree.cxx:9474
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:5638
std::vector< std::pair< Long64_t, TBranch * > > fSortedBranches
! Branches to be processed in parallel when IMT is on, sorted by average task time
Definition TTree.h:144
virtual void SetCircular(Long64_t maxEntries)
Enable/Disable circularity for this tree.
Definition TTree.cxx:8892
Long64_t fSavedBytes
Number of autosaved bytes.
Definition TTree.h:88
virtual Int_t AddBranchToCache(const char *bname, bool subbranches=false)
Add branch with name bname to the Tree cache.
Definition TTree.cxx:1059
Long64_t GetMedianClusterSize()
Estimate the median cluster size for the TTree.
Definition TTree.cxx:8297
virtual TClusterIterator GetClusterIterator(Long64_t firstentry)
Return an iterator over the cluster of baskets starting at firstentry.
Definition TTree.cxx:5467
virtual void ResetBranchAddress(TBranch *)
Tell all of our branches to set their addresses to zero.
Definition TTree.cxx:8065
bool fCacheUserSet
! true if the cache setting was explicitly given by user
Definition TTree.h:141
char GetNewlineValue(std::istream &inputStream)
Determine which newline this file is using.
Definition TTree.cxx:7588
TIOFeatures fIOFeatures
IO features to define for newly-written baskets and branches.
Definition TTree.h:114
virtual Long64_t GetEntryNumberWithIndex(Long64_t major, Long64_t minor=0) const
Return entry number corresponding to major and minor number.
Definition TTree.cxx:5910
Long64_t fDebugMin
! First entry number to debug
Definition TTree.h:112
virtual Long64_t SetEntries(Long64_t n=-1)
Change number of entries in the tree.
Definition TTree.cxx:9011
virtual TObjArray * GetListOfLeaves()
Definition TTree.h:529
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:2074
Long64_t GetCacheAutoSize(bool withDefault=false)
Used for automatic sizing of the cache.
Definition TTree.cxx:5407
virtual TBranch * BranchRef()
Build the optional branch supporting the TRefTable.
Definition TTree.cxx:2328
TFile * GetCurrentFile() const
Return pointer to the current file.
Definition TTree.cxx:5479
TList * fAliases
List of aliases for expressions based on the tree branches.
Definition TTree.h:124
virtual TTree * CopyTree(const char *selection, Option_t *option="", Long64_t nentries=kMaxEntries, Long64_t firstentry=0)
Copy a tree with selection.
Definition TTree.cxx:3719
virtual Int_t DropBranchFromCache(const char *bname, bool subbranches=false)
Remove the branch with name 'bname' from the Tree cache.
Definition TTree.cxx:1142
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:5079
Long64_t * fClusterRangeEnd
[fNClusterRange] Last entry of a cluster range.
Definition TTree.h:103
void Streamer(TBuffer &) override
Stream a class object.
Definition TTree.cxx:9545
std::atomic< Long64_t > fIMTZipBytes
! Zip bytes for the IMT flush baskets.
Definition TTree.h:161
void RecursiveRemove(TObject *obj) override
Make sure that obj (which is being deleted or will soon be) is no longer referenced by this TTree.
Definition TTree.cxx:7881
TVirtualTreePlayer * GetPlayer()
Load the TTreePlayer (if not already done).
Definition TTree.cxx:6305
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:6768
@ kSplitCollectionOfPointers
Definition TTree.h:266
virtual Long64_t ReadStream(std::istream &inputStream, const char *branchDescriptor="", char delimiter=' ')
Create or simply read branches from an input stream.
Definition TTree.cxx:7615
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:8928
Int_t fScanField
Number of runs before prompting in Scan.
Definition TTree.h:92
void Draw(Option_t *opt) override
Default Draw method for all objects.
Definition TTree.h:431
virtual TTree * GetFriend(const char *) const
Return a pointer to the TTree friend whose name or alias is friendname.
Definition TTree.cxx:5975
virtual void SetNotify(TObject *obj)
Sets the address of the object to be notified when the tree is loaded.
Definition TTree.cxx:9231
virtual Double_t GetMaximum(const char *columname)
Return maximum of column with name columname.
Definition TTree.cxx:6235
virtual Long64_t GetEntryNumberWithBestIndex(Long64_t major, Long64_t minor=0) const
Return entry number corresponding to major and minor number.
Definition TTree.cxx:5890
static void SetMaxTreeSize(Long64_t maxsize=100000000000LL)
Set the maximum size in bytes of a Tree file (static function).
Definition TTree.cxx:9197
void Print(Option_t *option="") const override
Print a summary of the tree contents.
Definition TTree.cxx:7219
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:9702
Int_t fNClusterRange
Number of Cluster range in addition to the one defined by 'AutoFlush'.
Definition TTree.h:95
virtual void PrintCacheStats(Option_t *option="") const
Print statistics about the TreeCache for this tree.
Definition TTree.cxx:7370
virtual Int_t BuildIndex(const char *majorname, const char *minorname="0")
Build a Tree Index (default is TTreeIndex).
Definition TTree.cxx:2637
TVirtualTreePlayer * fPlayer
! Pointer to current Tree player
Definition TTree.h:134
virtual TIterator * GetIteratorOnAllLeaves(bool dir=kIterForward)
Creates a new iterator that will go through all the leaves on the tree itself and its friend.
Definition TTree.cxx:6082
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:9177
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:7012
TObjArray fBranches
List of Branches.
Definition TTree.h:122
TDirectory * GetDirectory() const
Definition TTree.h:462
bool fCacheDoAutoInit
! true if cache auto creation or resize check is needed
Definition TTree.h:139
TTreeCache * GetReadCache(TFile *file) const
Find and return the TTreeCache registered with the file and which may contain branches for us.
Definition TTree.cxx:6318
Long64_t fEntries
Number of entries.
Definition TTree.h:84
virtual TFile * ChangeFile(TFile *file)
Called by TTree::Fill() when file has reached its maximum fgMaxTreeSize.
Definition TTree.cxx:2749
virtual TEntryList * GetEntryList()
Returns the entry list assigned to this tree.
Definition TTree.cxx:5854
virtual void SetWeight(Double_t w=1, Option_t *option="")
Set tree weight.
Definition TTree.cxx:9374
void InitializeBranchLists(bool checkLeafCount)
Divides the top-level branches into two vectors: (i) branches to be processed sequentially and (ii) b...
Definition TTree.cxx:5781
virtual Int_t SetBranchAddress(const char *bname, void *add, TBranch **ptr=nullptr)
Change branch address, dealing with clone trees properly.
Definition TTree.cxx:8385
Long64_t * fClusterSize
[fNClusterRange] Number of entries in each cluster for a given range.
Definition TTree.h:104
Long64_t fFlushedBytes
Number of auto-flushed bytes.
Definition TTree.h:89
virtual void SetPerfStats(TVirtualPerfStats *perf)
Set perf stats.
Definition TTree.cxx:9329
std::atomic< Long64_t > fIMTTotBytes
! Total bytes for the IMT flush baskets
Definition TTree.h:160
virtual void SetCacheLearnEntries(Int_t n=10)
Interface to TTreeCache to set the number of entries for the learning phase.
Definition TTree.cxx:8865
TEntryList * fEntryList
! Pointer to event selection list (if one)
Definition TTree.h:126
virtual TVirtualIndex * GetTreeIndex() const
Definition TTree.h:558
TList * fExternalFriends
! List of TFriendsElement pointing to us and need to be notified of LoadTree. Content not owned.
Definition TTree.h:131
virtual Long64_t Merge(TCollection *list, Option_t *option="")
Merge the trees in the TList into this tree.
Definition TTree.cxx:6890
virtual void SetMaxVirtualSize(Long64_t size=0)
Definition TTree.h:665
virtual void DropBaskets()
Remove some baskets from memory.
Definition TTree.cxx:4518
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:8342
Long64_t fMaxEntryLoop
Maximum number of entries to process.
Definition TTree.h:98
virtual void SetParallelUnzip(bool opt=true, Float_t RelSize=-1)
Enable or disable parallel unzipping of Tree buffers.
Definition TTree.cxx:9291
virtual void SetDirectory(TDirectory *dir)
Change the tree's directory.
Definition TTree.cxx:8966
void SortBranchesByTime()
Sorts top-level branches by the last average task time recorded per branch.
Definition TTree.cxx:5834
void Delete(Option_t *option="") override
Delete this tree from memory or/and disk.
Definition TTree.cxx:3747
virtual TBranchRef * GetBranchRef() const
Definition TTree.h:450
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:7450
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:1635
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:9069
void MoveReadCache(TFile *src, TDirectory *dir)
Move a cache from a file to the current file in dir.
Definition TTree.cxx:6983
Long64_t fAutoFlush
Auto-flush tree when fAutoFlush entries written or -fAutoFlush (compressed) bytes produced.
Definition TTree.h:101
Int_t fUpdate
Update frequency for EntryLoop.
Definition TTree.h:93
virtual void ResetAfterMerge(TFileMergeInfo *)
Resets the state of this TTree after a merge (keep the customization but forget the data).
Definition TTree.cxx:8034
virtual Long64_t GetEntries() const
Definition TTree.h:463
virtual void SetEstimate(Long64_t nentries=1000000)
Set number of entries to estimate variable limits.
Definition TTree.cxx:9110
Int_t fTimerInterval
Timer interval in milliseconds.
Definition TTree.h:91
Int_t fDebug
! Debug level
Definition TTree.h:111
Int_t SetCacheSizeAux(bool autocache=true, Long64_t cacheSize=0)
Set the size of the file cache and create it if possible.
Definition TTree.cxx:8711
virtual Long64_t AutoSave(Option_t *option="")
AutoSave tree header every fAutoSave bytes.
Definition TTree.cxx:1500
virtual Long64_t GetEntryNumber(Long64_t entry) const
Return entry number corresponding to entry.
Definition TTree.cxx:5865
virtual TTree * CloneTree(Long64_t nentries=-1, Option_t *option="")
Create a clone of this tree and copy nentries.
Definition TTree.cxx:3139
Int_t fFileNumber
! current file number (if file extensions)
Definition TTree.h:116
virtual TLeaf * GetLeaf(const char *branchname, const char *leafname)
Return pointer to the 1st Leaf named name in any Branch of this Tree or any branch in the list of fri...
Definition TTree.cxx:6195
virtual Long64_t GetZipBytes() const
Definition TTree.h:585
TObjArray fLeaves
Direct pointers to individual branch leaves.
Definition TTree.h:123
virtual void Reset(Option_t *option="")
Reset baskets, buffers and entries count in all branches and leaves.
Definition TTree.cxx:8003
virtual void KeepCircular()
Keep a maximum of fMaxEntries in memory.
Definition TTree.cxx:6415
virtual void SetDefaultEntryOffsetLen(Int_t newdefault, bool updateExisting=false)
Update the default value for the branch's fEntryOffsetLen.
Definition TTree.cxx:8940
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:3819
Long64_t fMaxVirtualSize
Maximum total size of buffers kept in memory.
Definition TTree.h:99
virtual Long64_t GetTotBytes() const
Definition TTree.h:556
virtual Int_t MakeSelector(const char *selector=nullptr, Option_t *option="")
Generate skeleton selector class for this tree.
Definition TTree.cxx:6822
virtual void SetObject(const char *name, const char *title)
Change the name and title of this tree.
Definition TTree.cxx:9260
TVirtualPerfStats * fPerfStats
! pointer to the current perf stats object
Definition TTree.h:132
Double_t fWeight
Tree weight (see TTree::SetWeight)
Definition TTree.h:90
std::vector< TBranch * > fSeqBranches
! Branches to be processed sequentially when IMT is on
Definition TTree.h:145
Long64_t fDebugMax
! Last entry number to debug
Definition TTree.h:113
Int_t fDefaultEntryOffsetLen
Initial Length of fEntryOffset table in the basket buffers.
Definition TTree.h:94
TTree()
Default constructor and I/O constructor.
Definition TTree.cxx:737
Long64_t fAutoSave
Autosave tree when fAutoSave entries written or -fAutoSave (compressed) bytes produced.
Definition TTree.h:100
TBranch * Branch(const char *name, T *obj, Int_t bufsize=32000, Int_t splitlevel=99)
Add a new branch, and infer the data type from the type of obj being passed.
Definition TTree.h:353
std::atomic< UInt_t > fAllocationCount
indicates basket should be resized to exact memory usage, but causes significant
Definition TTree.h:152
virtual Int_t GetEntryWithIndex(Int_t major, Int_t minor=0)
Read entry corresponding to major and minor number.
Definition TTree.cxx:5927
static TTree * MergeTrees(TList *list, Option_t *option="")
Static function merging the trees in the TList into a new tree.
Definition TTree.cxx:6851
bool MemoryFull(Int_t nbytes)
Check if adding nbytes to memory we are still below MaxVirtualsize.
Definition TTree.cxx:6837
virtual Long64_t GetReadEntry() const
Definition TTree.h:549
virtual TObjArray * GetListOfBranches()
Definition TTree.h:528
Long64_t fZipBytes
Total number of bytes in all branches after compression.
Definition TTree.h:87
virtual TTree * GetTree() const
Definition TTree.h:557
TBuffer * fTransientBuffer
! Pointer to the current transient buffer.
Definition TTree.h:138
virtual void SetEntryList(TEntryList *list, Option_t *opt="")
Set an EntryList.
Definition TTree.cxx:9046
bool Notify() override
Function called when loading a new class library.
Definition TTree.cxx:7033
virtual void AddZipBytes(Int_t zip)
Definition TTree.h:332
virtual Long64_t LoadTree(Long64_t entry)
Set current entry.
Definition TTree.cxx:6473
virtual Long64_t ReadFile(const char *filename, const char *branchDescriptor="", char delimiter=' ')
Create or simply read branches from filename.
Definition TTree.cxx:7564
virtual const char * GetAlias(const char *aliasName) const
Returns the expanded value of the alias. Search in the friends if any.
Definition TTree.cxx:5226
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:9130
virtual TBasket * CreateBasket(TBranch *)
Create a basket for this tree and given branch.
Definition TTree.cxx:3731
TList * fUserInfo
pointer to a list of user objects associated to this Tree
Definition TTree.h:133
virtual Double_t GetMinimum(const char *columname)
Return minimum of column with name columname.
Definition TTree.cxx:6275
virtual void RemoveFriend(TTree *)
Remove a friend from the list of friends.
Definition TTree.cxx:7977
virtual Long64_t GetEntriesFast() const
Return a number greater or equal to the total number of entries in the dataset.
Definition TTree.h:505
void Browse(TBrowser *) override
Browse content of the TTree.
Definition TTree.cxx:2609
virtual TList * GetUserInfo()
Return a pointer to the list containing user objects associated to this tree.
Definition TTree.cxx:6356
Long64_t fChainOffset
! Offset of 1st entry of this Tree in a TChain
Definition TTree.h:106
@ kOnlyFlushAtCluster
If set, the branch's buffers will grow until an event cluster boundary is hit, guaranteeing a basket ...
Definition TTree.h:256
@ kEntriesReshuffled
If set, signals that this TTree is the output of the processing of another TTree, and the entries are...
Definition TTree.h:261
@ kCircular
Definition TTree.h:252
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:5512
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:7513
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:2404
virtual void SetBasketSize(const char *bname, Int_t buffsize=16000)
Set a branch's basket size.
Definition TTree.cxx:8358
static void SetBranchStyle(Int_t style=1)
Set the current branch style.
Definition TTree.cxx:8665
~TTree() override
Destructor.
Definition TTree.cxx:920
void ImportClusterRanges(TTree *fromtree)
Appends the cluster range information stored in 'fromtree' to this tree, including the value of fAuto...
Definition TTree.cxx:6372
TClass * IsA() const override
Definition TTree.h:705
Long64_t fEstimate
Number of entries to estimate histogram limits.
Definition TTree.h:102
Int_t FlushBasketsImpl() const
Internal implementation of the FlushBaskets algorithm.
Definition TTree.cxx:5146
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:6557
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:9753
TVirtualIndex * fTreeIndex
Pointer to the tree Index (if any)
Definition TTree.h:129
void UseCurrentStyle() override
Replace current attributes by current style.
Definition TTree.cxx:9714
TObject * fNotify
Object to be notified when loading a Tree.
Definition TTree.h:120
virtual TBranch * BranchImp(const char *branchname, const char *classname, TClass *ptrClass, void *addobj, Int_t bufsize, Int_t splitlevel)
Same as TTree::Branch() with added check that addobj matches className.
Definition TTree.cxx:1554
Long64_t fCacheSize
! Maximum size of file buffers
Definition TTree.h:105
TList * fClones
! List of cloned trees which share our addresses
Definition TTree.h:135
std::atomic< Long64_t > fTotalBuffers
! Total number of bytes in branch buffers
Definition TTree.h:108
static TClass * Class()
@ kFindBranch
Definition TTree.h:212
@ kFindLeaf
Definition TTree.h:213
@ kGetEntryWithIndex
Definition TTree.h:217
@ kPrint
Definition TTree.h:222
@ kGetFriend
Definition TTree.h:218
@ kGetBranch
Definition TTree.h:215
@ kSetBranchStatus
Definition TTree.h:224
@ kLoadTree
Definition TTree.h:221
@ kGetEntry
Definition TTree.h:216
@ kGetLeaf
Definition TTree.h:220
@ kRemoveFriend
Definition TTree.h:223
@ kGetFriendAlias
Definition TTree.h:219
@ kGetAlias
Definition TTree.h:214
virtual void SetTreeIndex(TVirtualIndex *index)
The current TreeIndex is replaced by the new index.
Definition TTree.cxx:9346
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:7057
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:7498
virtual Int_t SetCacheEntryRange(Long64_t first, Long64_t last)
interface to TTreeCache to set the cache entry range
Definition TTree.cxx:8831
static Long64_t GetMaxTreeSize()
Static function which returns the tree file size limit in bytes.
Definition TTree.cxx:6265
bool fCacheDoClusterPrefetch
! true if cache is prefetching whole clusters
Definition TTree.h:140
Int_t SetBranchAddressImp(TBranch *branch, void *addr, TBranch **ptr)
Change branch address, dealing with clone trees properly.
Definition TTree.cxx:8445
virtual bool SetAlias(const char *aliasName, const char *aliasFormula)
Set a tree variable alias.
Definition TTree.cxx:8141
virtual void CopyAddresses(TTree *, bool undo=false)
Set branch addresses of passed tree equal to ours.
Definition TTree.cxx:3299
Long64_t fMaxEntries
Maximum number of entries in case of circular buffers.
Definition TTree.h:97
virtual void DropBuffers(Int_t nbytes)
Drop branch buffers to accommodate nbytes below MaxVirtualsize.
Definition TTree.cxx:4531
virtual TList * GetListOfFriends() const
Definition TTree.h:530
virtual void Refresh()
Refresh contents of this tree and its branches from the current status on disk.
Definition TTree.cxx:7916
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:8196
static Long64_t fgMaxTreeSize
Maximum size of a file containing a Tree.
Definition TTree.h:155
Long64_t fReadEntry
! Number of the entry being processed
Definition TTree.h:107
TArrayD fIndexValues
Sorted index values.
Definition TTree.h:127
void MarkEventCluster()
Mark the previous event as being at the end of the event cluster.
Definition TTree.cxx:8258
UInt_t fNEntriesSinceSorting
! Number of entries processed since the last re-sorting of branches
Definition TTree.h:143
virtual void SetFileNumber(Int_t number=0)
Set fFileNumber to number.
Definition TTree.cxx:9153
virtual TLeaf * FindLeaf(const char *name)
Find leaf..
Definition TTree.cxx:4916
virtual void StartViewer()
Start the TTreeViewer on this tree.
Definition TTree.cxx:9459
Int_t GetMakeClass() const
Definition TTree.h:535
virtual Int_t MakeCode(const char *filename=nullptr)
Generate a skeleton function for this tree.
Definition TTree.cxx:6640
bool fIMTFlush
! True if we are doing a multithreaded flush.
Definition TTree.h:159
TDirectory * fDirectory
! Pointer to directory holding this tree
Definition TTree.h:121
@ kNeedEnableDecomposedObj
Definition TTree.h:244
@ kClassMismatch
Definition TTree.h:237
@ kVoidPtr
Definition TTree.h:242
@ kMatchConversionCollection
Definition TTree.h:240
@ kMissingCompiledCollectionProxy
Definition TTree.h:235
@ kMismatch
Definition TTree.h:236
@ kMatchConversion
Definition TTree.h:239
@ kInternalError
Definition TTree.h:234
@ kMatch
Definition TTree.h:238
@ kMissingBranch
Definition TTree.h:233
@ kMakeClass
Definition TTree.h:241
static Int_t fgBranchStyle
Old/New branch style.
Definition TTree.h:154
virtual void ResetBranchAddresses()
Tell all of our branches to drop their current objects and allocate new ones.
Definition TTree.cxx:8075
Int_t fNfill
! Local for EntryLoop
Definition TTree.h:110
void SetName(const char *name) override
Change the name of this tree.
Definition TTree.cxx:9205
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:7957
TArrayI fIndex
Index of sorted values.
Definition TTree.h:128
virtual Int_t SetCacheSize(Long64_t cachesize=-1)
Set maximum size of the file cache .
Definition TTree.cxx:8683
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:1219
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:2867
TBuffer * GetTransientBuffer(Int_t size)
Returns the transient buffer currently used by this TTree for reading/writing baskets.
Definition TTree.cxx:1037
ROOT::TIOFeatures GetIOFeatures() const
Returns the current set of IO settings.
Definition TTree.cxx:6074
virtual Int_t MakeClass(const char *classname=nullptr, Option_t *option="")
Generate a skeleton analysis class for this tree.
Definition TTree.cxx:6607
virtual const char * GetFriendAlias(TTree *) const
If the 'tree' is a friend, this method returns its alias name.
Definition TTree.cxx:6032
virtual void RemoveExternalFriend(TFriendElement *)
Removes external friend.
Definition TTree.cxx:7968
Int_t fPacketSize
! Number of entries in one packet for parallel root
Definition TTree.h:109
virtual TBranch * BranchImpArr(const char *branchname, EDataType datatype, std::size_t N, void *addobj, Int_t bufsize, Int_t splitlevel)
Definition TTree.cxx:1731
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:8099
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:2412
virtual void AddTotBytes(Int_t tot)
Definition TTree.h:331
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:3534
Int_t fMakeClass
! not zero when processing code generated by MakeClass
Definition TTree.h:115
virtual Int_t LoadBaskets(Long64_t maxmemory=2000000000)
Read in memory all baskets from all branches up to the limit of maxmemory bytes.
Definition TTree.cxx:6451
static constexpr Long64_t kMaxEntries
Definition TTree.h:229
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:7200
virtual Long64_t GetAutoFlush() const
Definition TTree.h:447
Defines a common interface to inspect/change the contents of an object that represents a collection.
virtual EDataType GetType() const =0
If the value type is a fundamental data type, return its type (see enumeration EDataType).
virtual TClass * GetValueClass() const =0
If the value type is a user-defined class, return a pointer to the TClass representing the value type...
virtual Bool_t HasPointers() const =0
Return true if the content is of type 'pointer to'.
Abstract interface for Tree Index.
virtual const char * GetMajorName() const =0
virtual Long64_t GetEntryNumberWithIndex(Long64_t major, Long64_t minor) const =0
virtual Long64_t GetEntryNumberFriend(const TTree *)=0
virtual void Append(const TVirtualIndex *, bool delaySort=false)=0
virtual const char * GetMinorName() const =0
virtual void SetTree(TTree *T)=0
virtual Long64_t GetN() const =0
virtual bool IsValidFor(const TTree *parent)=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
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:387
tbb::task_arena is an alias of tbb::interface7::task_arena, which doesn't allow to forward declare tb...
Bool_t IsImplicitMTEnabled()
Returns true if the implicit multi-threading in ROOT is enabled.
Definition TROOT.cxx:570
ESTLType
Definition ESTLType.h:28
@ kSTLmap
Definition ESTLType.h:33
@ kSTLmultimap
Definition ESTLType.h:34
void CallRecursiveRemoveIfNeeded(TObject &obj)
call RecursiveRemove for obj if gROOT is valid and obj.TestBit(kMustCleanup) is true.
Definition TROOT.h:395
void ToHumanReadableSize(value_type bytes, Bool_t si, Double_t *coeff, const char **units)
Return the size expressed in 'human readable' format.
EFromHumanReadableSize FromHumanReadableSize(std::string_view str, T &value)
Convert strings like the following into byte counts 5MB, 5 MB, 5M, 3.7GB, 123b, 456kB,...
Short_t Max(Short_t a, Short_t b)
Returns the largest of a and b.
Definition TMathBase.h:250
Double_t Median(Long64_t n, const T *a, const Double_t *w=nullptr, Long64_t *work=nullptr)
Same as RMS.
Definition TMath.h:1272
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