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`)
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_t`)
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
114- If the address points to a single numerical variable, the leaflist is optional:
115~~~ {.cpp}
116 int value;
117 tree->Branch(branchname, &value);
118~~~
119- If the address points to more than one numerical variable, we strongly recommend
120 that the variable be sorted in decreasing order of size. Any other order will
121 result in a non-portable TTree (i.e. you will not be able to read it back on a
122 platform with a different padding strategy).
123 We recommend to persistify objects rather than composite leaflists.
124- In case of the truncated floating point types (Float16_t and Double32_t) you can
125 furthermore specify the range in the style [xmin,xmax] or [xmin,xmax,nbits] after
126 the type character. For example, for storing a variable size array `myArr` of
127 `Double32_t` with values within a range of `[0, 2*pi]` and the size of which is
128 stored in a branch called `myArrSize`, the syntax for the `leaflist` string would
129 be: `myArr[myArrSize]/d[0,twopi]`. Of course the number of bits could be specified,
130 the standard rules of opaque typedefs annotation are valid. For example, if only
131 18 bits were sufficient, the syntax would become: `myArr[myArrSize]/d[0,twopi,18]`
132
133\anchor addingacolumnofstl
134## Adding a column holding STL collection instances (e.g. std::vector, std::list, std::unordered_map)
135
136~~~ {.cpp}
137 auto branch = tree.Branch( branchname, STLcollection, buffsize, splitlevel);
138~~~
139STLcollection is the address of a pointer to std::vector, std::list,
140std::deque, std::set or std::multiset containing pointers to objects.
141If the splitlevel is a value bigger than 100 (TTree::kSplitCollectionOfPointers)
142then the collection will be written in split mode, e.g. if it contains objects of
143any types deriving from TTrack this function will sort the objects
144based on their type and store them in separate branches in split
145mode.
146
147~~~ {.cpp}
148 branch->SetAddress(void *address)
149~~~
150In case of dynamic structures changing with each entry for example, one must
151redefine the branch address before filling the branch again.
152This is done via the TBranch::SetAddress member function.
153
154\anchor addingacolumnofobjs
155## Add a column holding objects
156
157~~~ {.cpp}
158 MyClass object;
159 auto branch = tree.Branch(branchname, &object, bufsize, splitlevel)
160~~~
161Note: The 2nd parameter must be the address of a valid object.
162 The object must not be destroyed (i.e. be deleted) until the TTree
163 is deleted or TTree::ResetBranchAddress is called.
164
165- if splitlevel=0, the object is serialized in the branch buffer.
166- if splitlevel=1 (default), this branch will automatically be split
167 into subbranches, with one subbranch for each data member or object
168 of the object itself. In case the object member is a TClonesArray,
169 the mechanism described in case C is applied to this array.
170- if splitlevel=2 ,this branch will automatically be split
171 into subbranches, with one subbranch for each data member or object
172 of the object itself. In case the object member is a TClonesArray,
173 it is processed as a TObject*, only one branch.
174
175Another available syntax is the following:
176
177~~~ {.cpp}
178 auto branch = tree.Branch(branchname, &p_object, bufsize, splitlevel)
179 auto branch = tree.Branch(branchname, className, &p_object, bufsize, splitlevel)
180~~~
181- p_object is a pointer to an object.
182- If className is not specified, Branch uses the type of p_object to determine the
183 type of the object.
184- If className is used to specify explicitly the object type, the className must
185 be of a type related to the one pointed to by the pointer. It should be either
186 a parent or derived class.
187
188Note: The pointer whose address is passed to TTree::Branch must not
189 be destroyed (i.e. go out of scope) until the TTree is deleted or
190 TTree::ResetBranchAddress is called.
191
192Note: The pointer p_object must be initialized before calling TTree::Branch
193- Do either:
194~~~ {.cpp}
195 MyDataClass* p_object = nullptr;
196 tree.Branch(branchname, &p_object);
197~~~
198- Or:
199~~~ {.cpp}
200 auto p_object = new MyDataClass;
201 tree.Branch(branchname, &p_object);
202~~~
203Whether the pointer is set to zero or not, the ownership of the object
204is not taken over by the TTree. I.e. even though an object will be allocated
205by TTree::Branch if the pointer p_object is zero, the object will <b>not</b>
206be deleted when the TTree is deleted.
207
208\anchor addingacolumnoftclonesarray
209## Add a column holding TClonesArray instances
210
211*It is recommended to use STL containers instead of TClonesArrays*.
212
213~~~ {.cpp}
214 // clonesarray is the address of a pointer to a TClonesArray.
215 auto branch = tree.Branch(branchname,clonesarray, bufsize, splitlevel)
216~~~
217The TClonesArray is a direct access list of objects of the same class.
218For example, if the TClonesArray is an array of TTrack objects,
219this function will create one subbranch for each data member of
220the object TTrack.
221
222\anchor fillthetree
223## Fill the Tree
224
225A TTree instance is filled with the invocation of the TTree::Fill method:
226~~~ {.cpp}
227 tree.Fill()
228~~~
229Upon its invocation, a loop on all defined branches takes place that for each branch invokes
230the TBranch::Fill method.
231
232\anchor addcoltoexistingtree
233## Add a column to an already existing Tree
234
235You may want to add a branch to an existing tree. For example,
236if one variable in the tree was computed with a certain algorithm,
237you may want to try another algorithm and compare the results.
238One solution is to add a new branch, fill it, and save the tree.
239The code below adds a simple branch to an existing tree.
240Note the kOverwrite option in the Write method, it overwrites the
241existing tree. If it is not specified, two copies of the tree headers
242are saved.
243~~~ {.cpp}
244 void tree3AddBranch() {
245 TFile f("tree3.root", "update");
246
247 Float_t new_v;
248 auto t3 = f->Get<TTree>("t3");
249 auto newBranch = t3->Branch("new_v", &new_v, "new_v/F");
250
251 Long64_t nentries = t3->GetEntries(); // read the number of entries in the t3
252
253 for (Long64_t i = 0; i < nentries; i++) {
254 new_v = gRandom->Gaus(0, 1);
255 newBranch->Fill();
256 }
257
258 t3->Write("", TObject::kOverwrite); // save only the new version of the tree
259 }
260~~~
261It is not always possible to add branches to existing datasets stored in TFiles: for example,
262these files might not be writeable, just readable. In addition, modifying in place a TTree
263causes a new TTree instance to be written and the previous one to be deleted.
264For this reasons, ROOT offers the concept of friends for TTree and TChain:
265if is good practice to rely on friend trees rather than adding a branch manually.
266
267\anchor fullexample
268## An Example
269
270Begin_Macro
271../../../tutorials/tree/tree.C
272End_Macro
273
274~~~ {.cpp}
275 // A simple example with histograms and a tree
276 //
277 // This program creates :
278 // - a one dimensional histogram
279 // - a two dimensional histogram
280 // - a profile histogram
281 // - a tree
282 //
283 // These objects are filled with some random numbers and saved on a file.
284
285 #include "TFile.h"
286 #include "TH1.h"
287 #include "TH2.h"
288 #include "TProfile.h"
289 #include "TRandom.h"
290 #include "TTree.h"
291
292 //__________________________________________________________________________
293 main(int argc, char **argv)
294 {
295 // Create a new ROOT binary machine independent file.
296 // Note that this file may contain any kind of ROOT objects, histograms,trees
297 // pictures, graphics objects, detector geometries, tracks, events, etc..
298 // This file is now becoming the current directory.
299 TFile hfile("htree.root","RECREATE","Demo ROOT file with histograms & trees");
300
301 // Create some histograms and a profile histogram
302 TH1F hpx("hpx","This is the px distribution",100,-4,4);
303 TH2F hpxpy("hpxpy","py ps px",40,-4,4,40,-4,4);
304 TProfile hprof("hprof","Profile of pz versus px",100,-4,4,0,20);
305
306 // Define some simple structures
307 typedef struct {Float_t x,y,z;} POINT;
308 typedef struct {
309 Int_t ntrack,nseg,nvertex;
310 UInt_t flag;
311 Float_t temperature;
312 } EVENTN;
313 POINT point;
314 EVENTN eventn;
315
316 // Create a ROOT Tree
317 TTree tree("T","An example of ROOT tree with a few branches");
318 tree.Branch("point",&point,"x:y:z");
319 tree.Branch("eventn",&eventn,"ntrack/I:nseg:nvertex:flag/i:temperature/F");
320 tree.Branch("hpx","TH1F",&hpx,128000,0);
321
322 Float_t px,py,pz;
323
324 // Here we start a loop on 1000 events
325 for ( Int_t i=0; i<1000; i++) {
326 gRandom->Rannor(px,py);
327 pz = px*px + py*py;
328 const auto random = gRandom->::Rndm(1);
329
330 // Fill histograms
331 hpx.Fill(px);
332 hpxpy.Fill(px,py,1);
333 hprof.Fill(px,pz,1);
334
335 // Fill structures
336 point.x = 10*(random-1);
337 point.y = 5*random;
338 point.z = 20*random;
339 eventn.ntrack = Int_t(100*random);
340 eventn.nseg = Int_t(2*eventn.ntrack);
341 eventn.nvertex = 1;
342 eventn.flag = Int_t(random+0.5);
343 eventn.temperature = 20+random;
344
345 // Fill the tree. For each event, save the 2 structures and 3 objects
346 // In this simple example, the objects hpx, hprof and hpxpy are slightly
347 // different from event to event. We expect a big compression factor!
348 tree->Fill();
349 }
350 // End of the loop
351
352 tree.Print();
353
354 // Save all objects in this file
355 hfile.Write();
356
357 // Close the file. Note that this is automatically done when you leave
358 // the application upon file destruction.
359 hfile.Close();
360
361 return 0;
362}
363~~~
364*/
365
366#include <ROOT/RConfig.hxx>
367#include "TTree.h"
368
369#include "ROOT/TIOFeatures.hxx"
370#include "TArrayC.h"
371#include "TBufferFile.h"
372#include "TBaseClass.h"
373#include "TBasket.h"
374#include "TBranchClones.h"
375#include "TBranchElement.h"
376#include "TBranchObject.h"
377#include "TBranchRef.h"
378#include "TBrowser.h"
379#include "TClass.h"
380#include "TClassEdit.h"
381#include "TClonesArray.h"
382#include "TCut.h"
383#include "TDataMember.h"
384#include "TDataType.h"
385#include "TDirectory.h"
386#include "TError.h"
387#include "TEntryList.h"
388#include "TEnv.h"
389#include "TEventList.h"
390#include "TFile.h"
391#include "TFolder.h"
392#include "TFriendElement.h"
393#include "TInterpreter.h"
394#include "TLeaf.h"
395#include "TLeafB.h"
396#include "TLeafC.h"
397#include "TLeafD.h"
398#include "TLeafElement.h"
399#include "TLeafF.h"
400#include "TLeafI.h"
401#include "TLeafL.h"
402#include "TLeafObject.h"
403#include "TLeafS.h"
404#include "TList.h"
405#include "TMath.h"
406#include "TMemFile.h"
407#include "TROOT.h"
408#include "TRealData.h"
409#include "TRegexp.h"
410#include "TRefTable.h"
411#include "TStreamerElement.h"
412#include "TStreamerInfo.h"
413#include "TStyle.h"
414#include "TSystem.h"
415#include "TTreeCloner.h"
416#include "TTreeCache.h"
417#include "TTreeCacheUnzip.h"
420#include "TVirtualIndex.h"
421#include "TVirtualPerfStats.h"
422#include "TVirtualPad.h"
423#include "TBranchSTL.h"
424#include "TSchemaRuleSet.h"
425#include "TFileMergeInfo.h"
426#include "ROOT/StringConv.hxx"
427#include "TVirtualMutex.h"
428#include "strlcpy.h"
429#include "snprintf.h"
430
431#include "TBranchIMTHelper.h"
432#include "TNotifyLink.h"
433
434#include <chrono>
435#include <cstddef>
436#include <iostream>
437#include <fstream>
438#include <sstream>
439#include <string>
440#include <cstdio>
441#include <climits>
442#include <algorithm>
443#include <set>
444
445#ifdef R__USE_IMT
447#include <thread>
448#endif
450constexpr Int_t kNEntriesResort = 100;
452
453Int_t TTree::fgBranchStyle = 1; // Use new TBranch style with TBranchElement.
454Long64_t TTree::fgMaxTreeSize = 100000000000LL;
455
457
458////////////////////////////////////////////////////////////////////////////////
459////////////////////////////////////////////////////////////////////////////////
460////////////////////////////////////////////////////////////////////////////////
462static char DataTypeToChar(EDataType datatype)
463{
464 // Return the leaflist 'char' for a given datatype.
465
466 switch(datatype) {
467 case kChar_t: return 'B';
468 case kUChar_t: return 'b';
469 case kBool_t: return 'O';
470 case kShort_t: return 'S';
471 case kUShort_t: return 's';
472 case kCounter:
473 case kInt_t: return 'I';
474 case kUInt_t: return 'i';
475 case kDouble_t: return 'D';
476 case kDouble32_t: return 'd';
477 case kFloat_t: return 'F';
478 case kFloat16_t: return 'f';
479 case kLong_t: return 'G';
480 case kULong_t: return 'g';
481 case kchar: return 0; // unsupported
482 case kLong64_t: return 'L';
483 case kULong64_t: return 'l';
484
485 case kCharStar: return 'C';
486 case kBits: return 0; //unsupported
487
488 case kOther_t:
489 case kNoType_t:
490 default:
491 return 0;
492 }
493 return 0;
494}
495
496////////////////////////////////////////////////////////////////////////////////
497/// \class TTree::TFriendLock
498/// Helper class to prevent infinite recursion in the usage of TTree Friends.
499
500////////////////////////////////////////////////////////////////////////////////
501/// Record in tree that it has been used while recursively looks through the friends.
504: fTree(tree)
505{
506 // We could also add some code to acquire an actual
507 // lock to prevent multi-thread issues
508 fMethodBit = methodbit;
509 if (fTree) {
512 } else {
513 fPrevious = 0;
514 }
515}
516
517////////////////////////////////////////////////////////////////////////////////
518/// Copy constructor.
521 fTree(tfl.fTree),
522 fMethodBit(tfl.fMethodBit),
523 fPrevious(tfl.fPrevious)
524{
525}
526
527////////////////////////////////////////////////////////////////////////////////
528/// Assignment operator.
531{
532 if(this!=&tfl) {
533 fTree=tfl.fTree;
534 fMethodBit=tfl.fMethodBit;
535 fPrevious=tfl.fPrevious;
536 }
537 return *this;
538}
539
540////////////////////////////////////////////////////////////////////////////////
541/// Restore the state of tree the same as before we set the lock.
544{
545 if (fTree) {
546 if (!fPrevious) {
547 fTree->fFriendLockStatus &= ~(fMethodBit & kBitMask);
548 }
549 }
550}
551
552////////////////////////////////////////////////////////////////////////////////
553/// \class TTree::TClusterIterator
554/// Helper class to iterate over cluster of baskets.
555
556////////////////////////////////////////////////////////////////////////////////
557/// Regular constructor.
558/// TTree is not set as const, since we might modify if it is a TChain.
560TTree::TClusterIterator::TClusterIterator(TTree *tree, Long64_t firstEntry) : fTree(tree), fClusterRange(0), fStartEntry(0), fNextEntry(0), fEstimatedSize(-1)
561{
562 if (fTree->fNClusterRange) {
563 // Find the correct cluster range.
564 //
565 // Since fClusterRangeEnd contains the inclusive upper end of the range, we need to search for the
566 // range that was containing the previous entry and add 1 (because BinarySearch consider the values
567 // to be the inclusive start of the bucket).
569
570 Long64_t entryInRange;
571 Long64_t pedestal;
572 if (fClusterRange == 0) {
573 pedestal = 0;
574 entryInRange = firstEntry;
575 } else {
576 pedestal = fTree->fClusterRangeEnd[fClusterRange-1] + 1;
577 entryInRange = firstEntry - pedestal;
578 }
579 Long64_t autoflush;
581 autoflush = fTree->fAutoFlush;
582 } else {
583 autoflush = fTree->fClusterSize[fClusterRange];
584 }
585 if (autoflush <= 0) {
586 autoflush = GetEstimatedClusterSize();
587 }
588 fStartEntry = pedestal + entryInRange - entryInRange%autoflush;
589 } else if ( fTree->GetAutoFlush() <= 0 ) {
590 // Case of old files before November 9 2009 *or* small tree where AutoFlush was never set.
591 fStartEntry = firstEntry;
592 } else {
593 fStartEntry = firstEntry - firstEntry%fTree->GetAutoFlush();
594 }
595 fNextEntry = fStartEntry; // Position correctly for the first call to Next()
596}
597
598////////////////////////////////////////////////////////////////////////////////
599/// Estimate the cluster size.
600///
601/// In almost all cases, this quickly returns the size of the auto-flush
602/// in the TTree.
603///
604/// However, in the case where the cluster size was not fixed (old files and
605/// case where autoflush was explicitly set to zero), we need estimate
606/// a cluster size in relation to the size of the cache.
607///
608/// After this value is calculated once for the TClusterIterator, it is
609/// cached and reused in future calls.
612{
613 auto autoFlush = fTree->GetAutoFlush();
614 if (autoFlush > 0) return autoFlush;
615 if (fEstimatedSize > 0) return fEstimatedSize;
616
617 Long64_t zipBytes = fTree->GetZipBytes();
618 if (zipBytes == 0) {
619 fEstimatedSize = fTree->GetEntries() - 1;
620 if (fEstimatedSize <= 0)
621 fEstimatedSize = 1;
622 } else {
623 Long64_t clusterEstimate = 1;
624 Long64_t cacheSize = fTree->GetCacheSize();
625 if (cacheSize == 0) {
626 // Humm ... let's double check on the file.
627 TFile *file = fTree->GetCurrentFile();
628 if (file) {
629 TFileCacheRead *cache = fTree->GetReadCache(file);
630 if (cache) {
631 cacheSize = cache->GetBufferSize();
632 }
633 }
634 }
635 // If neither file nor tree has a cache, use the current default.
636 if (cacheSize <= 0) {
637 cacheSize = 30000000;
638 }
639 clusterEstimate = fTree->GetEntries() * cacheSize / zipBytes;
640 // If there are no entries, then just default to 1.
641 fEstimatedSize = clusterEstimate ? clusterEstimate : 1;
642 }
643 return fEstimatedSize;
644}
645
646////////////////////////////////////////////////////////////////////////////////
647/// Move on to the next cluster and return the starting entry
648/// of this next cluster
651{
652 fStartEntry = fNextEntry;
653 if (fTree->fNClusterRange || fTree->GetAutoFlush() > 0) {
654 if (fClusterRange == fTree->fNClusterRange) {
655 // We are looking at a range which size
656 // is defined by AutoFlush itself and goes to the GetEntries.
657 fNextEntry += GetEstimatedClusterSize();
658 } else {
659 if (fStartEntry > fTree->fClusterRangeEnd[fClusterRange]) {
660 ++fClusterRange;
661 }
662 if (fClusterRange == fTree->fNClusterRange) {
663 // We are looking at the last range which size
664 // is defined by AutoFlush itself and goes to the GetEntries.
665 fNextEntry += GetEstimatedClusterSize();
666 } else {
667 Long64_t clusterSize = fTree->fClusterSize[fClusterRange];
668 if (clusterSize == 0) {
669 clusterSize = GetEstimatedClusterSize();
670 }
671 fNextEntry += clusterSize;
672 if (fNextEntry > fTree->fClusterRangeEnd[fClusterRange]) {
673 // The last cluster of the range was a partial cluster,
674 // so the next cluster starts at the beginning of the
675 // next range.
676 fNextEntry = fTree->fClusterRangeEnd[fClusterRange] + 1;
677 }
678 }
679 }
680 } else {
681 // Case of old files before November 9 2009
682 fNextEntry = fStartEntry + GetEstimatedClusterSize();
683 }
684 if (fNextEntry > fTree->GetEntries()) {
685 fNextEntry = fTree->GetEntries();
686 }
687 return fStartEntry;
688}
689
690////////////////////////////////////////////////////////////////////////////////
691/// Move on to the previous cluster and return the starting entry
692/// of this previous cluster
695{
696 fNextEntry = fStartEntry;
697 if (fTree->fNClusterRange || fTree->GetAutoFlush() > 0) {
698 if (fClusterRange == 0 || fTree->fNClusterRange == 0) {
699 // We are looking at a range which size
700 // is defined by AutoFlush itself.
701 fStartEntry -= GetEstimatedClusterSize();
702 } else {
703 if (fNextEntry <= fTree->fClusterRangeEnd[fClusterRange]) {
704 --fClusterRange;
705 }
706 if (fClusterRange == 0) {
707 // We are looking at the first range.
708 fStartEntry = 0;
709 } else {
710 Long64_t clusterSize = fTree->fClusterSize[fClusterRange];
711 if (clusterSize == 0) {
712 clusterSize = GetEstimatedClusterSize();
713 }
714 fStartEntry -= clusterSize;
715 }
716 }
717 } else {
718 // Case of old files before November 9 2009 or trees that never auto-flushed.
719 fStartEntry = fNextEntry - GetEstimatedClusterSize();
720 }
721 if (fStartEntry < 0) {
722 fStartEntry = 0;
723 }
724 return fStartEntry;
725}
726
727////////////////////////////////////////////////////////////////////////////////
728////////////////////////////////////////////////////////////////////////////////
729////////////////////////////////////////////////////////////////////////////////
730
731////////////////////////////////////////////////////////////////////////////////
732/// Default constructor and I/O constructor.
733///
734/// Note: We do *not* insert ourself into the current directory.
735///
738: TNamed()
739, TAttLine()
740, TAttFill()
741, TAttMarker()
742, fEntries(0)
743, fTotBytes(0)
744, fZipBytes(0)
745, fSavedBytes(0)
746, fFlushedBytes(0)
747, fWeight(1)
749, fScanField(25)
750, fUpdate(0)
754, fMaxEntries(0)
755, fMaxEntryLoop(0)
757, fAutoSave( -300000000)
758, fAutoFlush(-30000000)
759, fEstimate(1000000)
761, fClusterSize(0)
762, fCacheSize(0)
763, fChainOffset(0)
764, fReadEntry(-1)
765, fTotalBuffers(0)
766, fPacketSize(100)
767, fNfill(0)
768, fDebug(0)
769, fDebugMin(0)
770, fDebugMax(9999999)
771, fMakeClass(0)
772, fFileNumber(0)
773, fNotify(0)
774, fDirectory(0)
775, fBranches()
776, fLeaves()
777, fAliases(0)
778, fEventList(0)
779, fEntryList(0)
780, fIndexValues()
781, fIndex()
782, fTreeIndex(0)
783, fFriends(0)
785, fPerfStats(0)
786, fUserInfo(0)
787, fPlayer(0)
788, fClones(0)
789, fBranchRef(0)
795, fIMTEnabled(ROOT::IsImplicitMTEnabled())
797{
798 fMaxEntries = 1000000000;
799 fMaxEntries *= 1000;
800
801 fMaxEntryLoop = 1000000000;
802 fMaxEntryLoop *= 1000;
803
805}
806
807////////////////////////////////////////////////////////////////////////////////
808/// Normal tree constructor.
809///
810/// The tree is created in the current directory.
811/// Use the various functions Branch below to add branches to this tree.
812///
813/// If the first character of title is a "/", the function assumes a folder name.
814/// In this case, it creates automatically branches following the folder hierarchy.
815/// splitlevel may be used in this case to control the split level.
817TTree::TTree(const char* name, const char* title, Int_t splitlevel /* = 99 */,
818 TDirectory* dir /* = gDirectory*/)
819: TNamed(name, title)
820, TAttLine()
821, TAttFill()
822, TAttMarker()
823, fEntries(0)
824, fTotBytes(0)
825, fZipBytes(0)
826, fSavedBytes(0)
827, fFlushedBytes(0)
828, fWeight(1)
829, fTimerInterval(0)
830, fScanField(25)
831, fUpdate(0)
832, fDefaultEntryOffsetLen(1000)
833, fNClusterRange(0)
834, fMaxClusterRange(0)
835, fMaxEntries(0)
836, fMaxEntryLoop(0)
837, fMaxVirtualSize(0)
838, fAutoSave( -300000000)
839, fAutoFlush(-30000000)
840, fEstimate(1000000)
841, fClusterRangeEnd(0)
842, fClusterSize(0)
843, fCacheSize(0)
844, fChainOffset(0)
845, fReadEntry(-1)
846, fTotalBuffers(0)
847, fPacketSize(100)
848, fNfill(0)
849, fDebug(0)
850, fDebugMin(0)
851, fDebugMax(9999999)
852, fMakeClass(0)
853, fFileNumber(0)
854, fNotify(0)
855, fDirectory(dir)
856, fBranches()
857, fLeaves()
858, fAliases(0)
859, fEventList(0)
860, fEntryList(0)
861, fIndexValues()
862, fIndex()
863, fTreeIndex(0)
864, fFriends(0)
865, fExternalFriends(0)
866, fPerfStats(0)
867, fUserInfo(0)
868, fPlayer(0)
869, fClones(0)
870, fBranchRef(0)
871, fFriendLockStatus(0)
872, fTransientBuffer(0)
873, fCacheDoAutoInit(kTRUE)
874, fCacheDoClusterPrefetch(kFALSE)
875, fCacheUserSet(kFALSE)
876, fIMTEnabled(ROOT::IsImplicitMTEnabled())
877, fNEntriesSinceSorting(0)
878{
879 // TAttLine state.
883
884 // TAttFill state.
887
888 // TAttMarkerState.
892
893 fMaxEntries = 1000000000;
894 fMaxEntries *= 1000;
895
896 fMaxEntryLoop = 1000000000;
897 fMaxEntryLoop *= 1000;
898
899 // Insert ourself into the current directory.
900 // FIXME: This is very annoying behaviour, we should
901 // be able to choose to not do this like we
902 // can with a histogram.
903 if (fDirectory) fDirectory->Append(this);
904
906
907 // If title starts with "/" and is a valid folder name, a superbranch
908 // is created.
909 // FIXME: Why?
910 if (strlen(title) > 2) {
911 if (title[0] == '/') {
912 Branch(title+1,32000,splitlevel);
913 }
914 }
915}
916
917////////////////////////////////////////////////////////////////////////////////
918/// Destructor.
921{
922 if (auto link = dynamic_cast<TNotifyLinkBase*>(fNotify)) {
923 link->Clear();
924 }
925 if (fAllocationCount && (gDebug > 0)) {
926 Info("TTree::~TTree", "For tree %s, allocation count is %u.", GetName(), fAllocationCount.load());
927#ifdef R__TRACK_BASKET_ALLOC_TIME
928 Info("TTree::~TTree", "For tree %s, allocation time is %lluus.", GetName(), fAllocationTime.load());
929#endif
930 }
931
932 if (fDirectory) {
933 // We are in a directory, which may possibly be a file.
934 if (fDirectory->GetList()) {
935 // Remove us from the directory listing.
936 fDirectory->Remove(this);
937 }
938 //delete the file cache if it points to this Tree
941 }
942
943 // Remove the TTree from any list (linked to to the list of Cleanups) to avoid the unnecessary call to
944 // this RecursiveRemove while we delete our content.
946 ResetBit(kMustCleanup); // Don't redo it.
947
948 // We don't own the leaves in fLeaves, the branches do.
949 fLeaves.Clear();
950 // I'm ready to destroy any objects allocated by
951 // SetAddress() by my branches. If I have clones,
952 // tell them to zero their pointers to this shared
953 // memory.
954 if (fClones && fClones->GetEntries()) {
955 // I have clones.
956 // I am about to delete the objects created by
957 // SetAddress() which we are sharing, so tell
958 // the clones to release their pointers to them.
959 for (TObjLink* lnk = fClones->FirstLink(); lnk; lnk = lnk->Next()) {
960 TTree* clone = (TTree*) lnk->GetObject();
961 // clone->ResetBranchAddresses();
962
963 // Reset only the branch we have set the address of.
964 CopyAddresses(clone,kTRUE);
965 }
966 }
967 // Get rid of our branches, note that this will also release
968 // any memory allocated by TBranchElement::SetAddress().
970
971 // The TBranch destructor is using fDirectory to detect whether it
972 // owns the TFile that contains its data (See TBranch::~TBranch)
973 fDirectory = nullptr;
974
975 // FIXME: We must consider what to do with the reset of these if we are a clone.
976 delete fPlayer;
977 fPlayer = 0;
978 if (fExternalFriends) {
979 using namespace ROOT::Detail;
981 fetree->Reset();
982 fExternalFriends->Clear("nodelete");
984 }
985 if (fFriends) {
986 fFriends->Delete();
987 delete fFriends;
988 fFriends = 0;
989 }
990 if (fAliases) {
991 fAliases->Delete();
992 delete fAliases;
993 fAliases = 0;
994 }
995 if (fUserInfo) {
996 fUserInfo->Delete();
997 delete fUserInfo;
998 fUserInfo = 0;
999 }
1000 if (fClones) {
1001 // Clone trees should no longer be removed from fClones when they are deleted.
1002 {
1004 gROOT->GetListOfCleanups()->Remove(fClones);
1005 }
1006 // Note: fClones does not own its content.
1007 delete fClones;
1008 fClones = 0;
1009 }
1010 if (fEntryList) {
1012 // Delete the entry list if it is marked to be deleted and it is not also
1013 // owned by a directory. (Otherwise we would need to make sure that a
1014 // TDirectoryFile that has a TTree in it does a 'slow' TList::Delete.
1015 delete fEntryList;
1016 fEntryList=0;
1017 }
1018 }
1019 delete fTreeIndex;
1020 fTreeIndex = 0;
1021 delete fBranchRef;
1022 fBranchRef = 0;
1023 delete [] fClusterRangeEnd;
1024 fClusterRangeEnd = 0;
1025 delete [] fClusterSize;
1026 fClusterSize = 0;
1027
1028 if (fTransientBuffer) {
1029 delete fTransientBuffer;
1030 fTransientBuffer = 0;
1031 }
1032}
1033
1034////////////////////////////////////////////////////////////////////////////////
1035/// Returns the transient buffer currently used by this TTree for reading/writing baskets.
1038{
1039 if (fTransientBuffer) {
1040 if (fTransientBuffer->BufferSize() < size) {
1042 }
1043 return fTransientBuffer;
1044 }
1046 return fTransientBuffer;
1047}
1048
1049////////////////////////////////////////////////////////////////////////////////
1050/// Add branch with name bname to the Tree cache.
1051/// If bname="*" all branches are added to the cache.
1052/// if subbranches is true all the branches of the subbranches are
1053/// also put to the cache.
1054///
1055/// Returns:
1056/// - 0 branch added or already included
1057/// - -1 on error
1059Int_t TTree::AddBranchToCache(const char*bname, Bool_t subbranches)
1060{
1061 if (!GetTree()) {
1062 if (LoadTree(0)<0) {
1063 Error("AddBranchToCache","Could not load a tree");
1064 return -1;
1065 }
1066 }
1067 if (GetTree()) {
1068 if (GetTree() != this) {
1069 return GetTree()->AddBranchToCache(bname, subbranches);
1070 }
1071 } else {
1072 Error("AddBranchToCache", "No tree is available. Branch was not added to the cache");
1073 return -1;
1074 }
1075
1076 TFile *f = GetCurrentFile();
1077 if (!f) {
1078 Error("AddBranchToCache", "No file is available. Branch was not added to the cache");
1079 return -1;
1080 }
1082 if (!tc) {
1083 Error("AddBranchToCache", "No cache is available, branch not added");
1084 return -1;
1085 }
1086 return tc->AddBranch(bname,subbranches);
1087}
1088
1089////////////////////////////////////////////////////////////////////////////////
1090/// Add branch b to the Tree cache.
1091/// if subbranches is true all the branches of the subbranches are
1092/// also put to the cache.
1093///
1094/// Returns:
1095/// - 0 branch added or already included
1096/// - -1 on error
1099{
1100 if (!GetTree()) {
1101 if (LoadTree(0)<0) {
1102 Error("AddBranchToCache","Could not load a tree");
1103 return -1;
1104 }
1105 }
1106 if (GetTree()) {
1107 if (GetTree() != this) {
1108 Int_t res = GetTree()->AddBranchToCache(b, subbranches);
1109 if (res<0) {
1110 Error("AddBranchToCache", "Error adding branch");
1111 }
1112 return res;
1113 }
1114 } else {
1115 Error("AddBranchToCache", "No tree is available. Branch was not added to the cache");
1116 return -1;
1117 }
1118
1119 TFile *f = GetCurrentFile();
1120 if (!f) {
1121 Error("AddBranchToCache", "No file is available. Branch was not added to the cache");
1122 return -1;
1123 }
1125 if (!tc) {
1126 Error("AddBranchToCache", "No cache is available, branch not added");
1127 return -1;
1128 }
1129 return tc->AddBranch(b,subbranches);
1130}
1131
1132////////////////////////////////////////////////////////////////////////////////
1133/// Remove the branch with name 'bname' from the Tree cache.
1134/// If bname="*" all branches are removed from the cache.
1135/// if subbranches is true all the branches of the subbranches are
1136/// also removed from the cache.
1137///
1138/// Returns:
1139/// - 0 branch dropped or not in cache
1140/// - -1 on error
1142Int_t TTree::DropBranchFromCache(const char*bname, Bool_t subbranches)
1143{
1144 if (!GetTree()) {
1145 if (LoadTree(0)<0) {
1146 Error("DropBranchFromCache","Could not load a tree");
1147 return -1;
1148 }
1149 }
1150 if (GetTree()) {
1151 if (GetTree() != this) {
1152 return GetTree()->DropBranchFromCache(bname, subbranches);
1153 }
1154 } else {
1155 Error("DropBranchFromCache", "No tree is available. Branch was not dropped from the cache");
1156 return -1;
1157 }
1158
1159 TFile *f = GetCurrentFile();
1160 if (!f) {
1161 Error("DropBranchFromCache", "No file is available. Branch was not dropped from the cache");
1162 return -1;
1163 }
1165 if (!tc) {
1166 Error("DropBranchFromCache", "No cache is available, branch not dropped");
1167 return -1;
1168 }
1169 return tc->DropBranch(bname,subbranches);
1170}
1171
1172////////////////////////////////////////////////////////////////////////////////
1173/// Remove the branch b from the Tree cache.
1174/// if subbranches is true all the branches of the subbranches are
1175/// also removed from the cache.
1176///
1177/// Returns:
1178/// - 0 branch dropped or not in cache
1179/// - -1 on error
1182{
1183 if (!GetTree()) {
1184 if (LoadTree(0)<0) {
1185 Error("DropBranchFromCache","Could not load a tree");
1186 return -1;
1187 }
1188 }
1189 if (GetTree()) {
1190 if (GetTree() != this) {
1191 Int_t res = GetTree()->DropBranchFromCache(b, subbranches);
1192 if (res<0) {
1193 Error("DropBranchFromCache", "Error dropping branch");
1194 }
1195 return res;
1196 }
1197 } else {
1198 Error("DropBranchFromCache", "No tree is available. Branch was not dropped from the cache");
1199 return -1;
1200 }
1201
1202 TFile *f = GetCurrentFile();
1203 if (!f) {
1204 Error("DropBranchFromCache", "No file is available. Branch was not dropped from the cache");
1205 return -1;
1206 }
1208 if (!tc) {
1209 Error("DropBranchFromCache", "No cache is available, branch not dropped");
1210 return -1;
1211 }
1212 return tc->DropBranch(b,subbranches);
1213}
1214
1215////////////////////////////////////////////////////////////////////////////////
1216/// Add a cloned tree to our list of trees to be notified whenever we change
1217/// our branch addresses or when we are deleted.
1219void TTree::AddClone(TTree* clone)
1220{
1221 if (!fClones) {
1222 fClones = new TList();
1223 fClones->SetOwner(false);
1224 // So that the clones are automatically removed from the list when
1225 // they are deleted.
1226 {
1228 gROOT->GetListOfCleanups()->Add(fClones);
1229 }
1230 }
1231 if (!fClones->FindObject(clone)) {
1232 fClones->Add(clone);
1233 }
1234}
1235
1236// Check whether mainTree and friendTree can be friends w.r.t. the kEntriesReshuffled bit.
1237// In particular, if any has the bit set, then friendTree must have a TTreeIndex and the
1238// branches used for indexing must be present in mainTree.
1239// Return true if the trees can be friends, false otherwise.
1240bool CheckReshuffling(TTree &mainTree, TTree &friendTree)
1241{
1242 const auto isMainReshuffled = mainTree.TestBit(TTree::kEntriesReshuffled);
1243 const auto isFriendReshuffled = friendTree.TestBit(TTree::kEntriesReshuffled);
1244 const auto friendHasValidIndex = [&] {
1245 auto idx = friendTree.GetTreeIndex();
1246 return idx ? idx->IsValidFor(&mainTree) : kFALSE;
1247 }();
1248
1249 if ((isMainReshuffled || isFriendReshuffled) && !friendHasValidIndex) {
1250 const auto reshuffledTreeName = isMainReshuffled ? mainTree.GetName() : friendTree.GetName();
1251 const auto msg = "Tree '%s' has the kEntriesReshuffled bit set, and cannot be used as friend nor can be added as "
1252 "a friend unless the main tree has a TTreeIndex on the friend tree '%s'. You can also unset the "
1253 "bit manually if you know what you are doing.";
1254 Error("AddFriend", msg, reshuffledTreeName, friendTree.GetName());
1255 return false;
1256 }
1257 return true;
1258}
1259
1260////////////////////////////////////////////////////////////////////////////////
1261/// Add a TFriendElement to the list of friends.
1262///
1263/// This function:
1264/// - opens a file if filename is specified
1265/// - reads a Tree with name treename from the file (current directory)
1266/// - adds the Tree to the list of friends
1267/// see other AddFriend functions
1268///
1269/// A TFriendElement TF describes a TTree object TF in a file.
1270/// When a TFriendElement TF is added to the list of friends of an
1271/// existing TTree T, any variable from TF can be referenced in a query
1272/// to T.
1273///
1274/// A tree keeps a list of friends. In the context of a tree (or a chain),
1275/// friendship means unrestricted access to the friends data. In this way
1276/// it is much like adding another branch to the tree without taking the risk
1277/// of damaging it. To add a friend to the list, you can use the TTree::AddFriend
1278/// method. The tree in the diagram below has two friends (friend_tree1 and
1279/// friend_tree2) and now has access to the variables a,b,c,i,j,k,l and m.
1280///
1281/// \image html ttree_friend1.png
1282///
1283/// The AddFriend method has two parameters, the first is the tree name and the
1284/// second is the name of the ROOT file where the friend tree is saved.
1285/// AddFriend automatically opens the friend file. If no file name is given,
1286/// the tree called ft1 is assumed to be in the same file as the original tree.
1287///
1288/// tree.AddFriend("ft1","friendfile1.root");
1289/// If the friend tree has the same name as the original tree, you can give it
1290/// an alias in the context of the friendship:
1291///
1292/// tree.AddFriend("tree1 = tree","friendfile1.root");
1293/// Once the tree has friends, we can use TTree::Draw as if the friend's
1294/// variables were in the original tree. To specify which tree to use in
1295/// the Draw method, use the syntax:
1296/// ~~~ {.cpp}
1297/// <treeName>.<branchname>.<varname>
1298/// ~~~
1299/// If the variablename is enough to uniquely identify the variable, you can
1300/// leave out the tree and/or branch name.
1301/// For example, these commands generate a 3-d scatter plot of variable "var"
1302/// in the TTree tree versus variable v1 in TTree ft1 versus variable v2 in
1303/// TTree ft2.
1304/// ~~~ {.cpp}
1305/// tree.AddFriend("ft1","friendfile1.root");
1306/// tree.AddFriend("ft2","friendfile2.root");
1307/// tree.Draw("var:ft1.v1:ft2.v2");
1308/// ~~~
1309/// \image html ttree_friend2.png
1310///
1311/// The picture illustrates the access of the tree and its friends with a
1312/// Draw command.
1313/// When AddFriend is called, the ROOT file is automatically opened and the
1314/// friend tree (ft1) is read into memory. The new friend (ft1) is added to
1315/// the list of friends of tree.
1316/// The number of entries in the friend must be equal or greater to the number
1317/// of entries of the original tree. If the friend tree has fewer entries a
1318/// warning is given and the missing entries are not included in the histogram.
1319/// To retrieve the list of friends from a tree use TTree::GetListOfFriends.
1320/// When the tree is written to file (TTree::Write), the friends list is saved
1321/// with it. And when the tree is retrieved, the trees on the friends list are
1322/// also retrieved and the friendship restored.
1323/// When a tree is deleted, the elements of the friend list are also deleted.
1324/// It is possible to declare a friend tree that has the same internal
1325/// structure (same branches and leaves) as the original tree, and compare the
1326/// same values by specifying the tree.
1327/// ~~~ {.cpp}
1328/// tree.Draw("var:ft1.var:ft2.var")
1329/// ~~~
1331TFriendElement *TTree::AddFriend(const char *treename, const char *filename)
1332{
1333 if (!fFriends) {
1334 fFriends = new TList();
1335 }
1336 TFriendElement *fe = new TFriendElement(this, treename, filename);
1337
1338 TTree *t = fe->GetTree();
1339 bool canAddFriend = true;
1340 if (t) {
1341 canAddFriend = CheckReshuffling(*this, *t);
1342 if (!t->GetTreeIndex() && (t->GetEntries() < fEntries)) {
1343 Warning("AddFriend", "FriendElement %s in file %s has less entries %lld than its parent Tree: %lld", treename,
1345 }
1346 } else {
1347 Error("AddFriend", "Cannot find tree '%s' in file '%s', friend not added", treename, filename);
1348 canAddFriend = false;
1349 }
1350
1351 if (canAddFriend)
1352 fFriends->Add(fe);
1353 return fe;
1354}
1355
1356////////////////////////////////////////////////////////////////////////////////
1357/// Add a TFriendElement to the list of friends.
1358///
1359/// The TFile is managed by the user (e.g. the user must delete the file).
1360/// For complete description see AddFriend(const char *, const char *).
1361/// This function:
1362/// - reads a Tree with name treename from the file
1363/// - adds the Tree to the list of friends
1365TFriendElement *TTree::AddFriend(const char *treename, TFile *file)
1366{
1367 if (!fFriends) {
1368 fFriends = new TList();
1369 }
1370 TFriendElement *fe = new TFriendElement(this, treename, file);
1371 R__ASSERT(fe);
1372 TTree *t = fe->GetTree();
1373 bool canAddFriend = true;
1374 if (t) {
1375 canAddFriend = CheckReshuffling(*this, *t);
1376 if (!t->GetTreeIndex() && (t->GetEntries() < fEntries)) {
1377 Warning("AddFriend", "FriendElement %s in file %s has less entries %lld than its parent tree: %lld", treename,
1378 file->GetName(), t->GetEntries(), fEntries);
1379 }
1380 } else {
1381 Error("AddFriend", "Cannot find tree '%s' in file '%s', friend not added", treename, file->GetName());
1382 canAddFriend = false;
1383 }
1384
1385 if (canAddFriend)
1386 fFriends->Add(fe);
1387 return fe;
1388}
1389
1390////////////////////////////////////////////////////////////////////////////////
1391/// Add a TFriendElement to the list of friends.
1392///
1393/// The TTree is managed by the user (e.g., the user must delete the file).
1394/// For a complete description see AddFriend(const char *, const char *).
1396TFriendElement *TTree::AddFriend(TTree *tree, const char *alias, Bool_t warn)
1397{
1398 if (!tree) {
1399 return 0;
1400 }
1401 if (!fFriends) {
1402 fFriends = new TList();
1403 }
1404 TFriendElement *fe = new TFriendElement(this, tree, alias);
1405 R__ASSERT(fe); // this assert is for historical reasons. Don't remove it unless you understand all the consequences.
1406 TTree *t = fe->GetTree();
1407 if (warn && (t->GetEntries() < fEntries)) {
1408 Warning("AddFriend", "FriendElement '%s' in file '%s' has less entries %lld than its parent tree: %lld",
1409 tree->GetName(), fe->GetFile() ? fe->GetFile()->GetName() : "(memory resident)", t->GetEntries(),
1410 fEntries);
1411 }
1412 if (CheckReshuffling(*this, *t))
1413 fFriends->Add(fe);
1414 else
1415 tree->RemoveExternalFriend(fe);
1416 return fe;
1417}
1418
1419////////////////////////////////////////////////////////////////////////////////
1420/// AutoSave tree header every fAutoSave bytes.
1421///
1422/// When large Trees are produced, it is safe to activate the AutoSave
1423/// procedure. Some branches may have buffers holding many entries.
1424/// If fAutoSave is negative, AutoSave is automatically called by
1425/// TTree::Fill when the number of bytes generated since the previous
1426/// AutoSave is greater than -fAutoSave bytes.
1427/// If fAutoSave is positive, AutoSave is automatically called by
1428/// TTree::Fill every N entries.
1429/// This function may also be invoked by the user.
1430/// Each AutoSave generates a new key on the file.
1431/// Once the key with the tree header has been written, the previous cycle
1432/// (if any) is deleted.
1433///
1434/// Note that calling TTree::AutoSave too frequently (or similarly calling
1435/// TTree::SetAutoSave with a small value) is an expensive operation.
1436/// You should make tests for your own application to find a compromise
1437/// between speed and the quantity of information you may loose in case of
1438/// a job crash.
1439///
1440/// In case your program crashes before closing the file holding this tree,
1441/// the file will be automatically recovered when you will connect the file
1442/// in UPDATE mode.
1443/// The Tree will be recovered at the status corresponding to the last AutoSave.
1444///
1445/// if option contains "SaveSelf", gDirectory->SaveSelf() is called.
1446/// This allows another process to analyze the Tree while the Tree is being filled.
1447///
1448/// if option contains "FlushBaskets", TTree::FlushBaskets is called and all
1449/// the current basket are closed-out and written to disk individually.
1450///
1451/// By default the previous header is deleted after having written the new header.
1452/// if option contains "Overwrite", the previous Tree header is deleted
1453/// before written the new header. This option is slightly faster, but
1454/// the default option is safer in case of a problem (disk quota exceeded)
1455/// when writing the new header.
1456///
1457/// The function returns the number of bytes written to the file.
1458/// if the number of bytes is null, an error has occurred while writing
1459/// the header to the file.
1460///
1461/// ## How to write a Tree in one process and view it from another process
1462///
1463/// The following two scripts illustrate how to do this.
1464/// The script treew.C is executed by process1, treer.C by process2
1465///
1466/// script treew.C:
1467/// ~~~ {.cpp}
1468/// void treew() {
1469/// TFile f("test.root","recreate");
1470/// TNtuple *ntuple = new TNtuple("ntuple","Demo","px:py:pz:random:i");
1471/// Float_t px, py, pz;
1472/// for ( Int_t i=0; i<10000000; i++) {
1473/// gRandom->Rannor(px,py);
1474/// pz = px*px + py*py;
1475/// Float_t random = gRandom->Rndm(1);
1476/// ntuple->Fill(px,py,pz,random,i);
1477/// if (i%1000 == 1) ntuple->AutoSave("SaveSelf");
1478/// }
1479/// }
1480/// ~~~
1481/// script treer.C:
1482/// ~~~ {.cpp}
1483/// void treer() {
1484/// TFile f("test.root");
1485/// TTree *ntuple = (TTree*)f.Get("ntuple");
1486/// TCanvas c1;
1487/// Int_t first = 0;
1488/// while(1) {
1489/// if (first == 0) ntuple->Draw("px>>hpx", "","",10000000,first);
1490/// else ntuple->Draw("px>>+hpx","","",10000000,first);
1491/// first = (Int_t)ntuple->GetEntries();
1492/// c1.Update();
1493/// gSystem->Sleep(1000); //sleep 1 second
1494/// ntuple->Refresh();
1495/// }
1496/// }
1497/// ~~~
1500{
1501 if (!fDirectory || fDirectory == gROOT || !fDirectory->IsWritable()) return 0;
1502 if (gDebug > 0) {
1503 Info("AutoSave", "Tree:%s after %lld bytes written\n",GetName(),GetTotBytes());
1504 }
1505 TString opt = option;
1506 opt.ToLower();
1507
1508 if (opt.Contains("flushbaskets")) {
1509 if (gDebug > 0) Info("AutoSave", "calling FlushBaskets \n");
1511 }
1512
1514
1516 Long64_t nbytes;
1517 if (opt.Contains("overwrite")) {
1518 nbytes = fDirectory->WriteTObject(this,"","overwrite");
1519 } else {
1520 nbytes = fDirectory->WriteTObject(this); //nbytes will be 0 if Write failed (disk space exceeded)
1521 if (nbytes && key && strcmp(ClassName(), key->GetClassName()) == 0) {
1522 key->Delete();
1523 delete key;
1524 }
1525 }
1526 // save StreamerInfo
1528 if (file) file->WriteStreamerInfo();
1529
1530 if (opt.Contains("saveself")) {
1532 //the following line is required in case GetUserInfo contains a user class
1533 //for which the StreamerInfo must be written. One could probably be a bit faster (Rene)
1534 if (file) file->WriteHeader();
1535 }
1536
1537 return nbytes;
1538}
1539
1540namespace {
1541 // This error message is repeated several times in the code. We write it once.
1542 const char* writeStlWithoutProxyMsg = "The class requested (%s) for the branch \"%s\""
1543 " is an instance of an stl collection and does not have a compiled CollectionProxy."
1544 " Please generate the dictionary for this collection (%s) to avoid to write corrupted data.";
1545}
1546
1547////////////////////////////////////////////////////////////////////////////////
1548/// Same as TTree::Branch() with added check that addobj matches className.
1549///
1550/// \see TTree::Branch() for other details.
1551///
1553TBranch* TTree::BranchImp(const char* branchname, const char* classname, TClass* ptrClass, void* addobj, Int_t bufsize, Int_t splitlevel)
1554{
1555 TClass* claim = TClass::GetClass(classname);
1556 if (!ptrClass) {
1557 if (claim && claim->GetCollectionProxy() && dynamic_cast<TEmulatedCollectionProxy*>(claim->GetCollectionProxy())) {
1558 Error("Branch", writeStlWithoutProxyMsg,
1559 claim->GetName(), branchname, claim->GetName());
1560 return 0;
1561 }
1562 return Branch(branchname, classname, (void*) addobj, bufsize, splitlevel);
1563 }
1564 TClass* actualClass = 0;
1565 void** addr = (void**) addobj;
1566 if (addr) {
1567 actualClass = ptrClass->GetActualClass(*addr);
1568 }
1569 if (ptrClass && claim) {
1570 if (!(claim->InheritsFrom(ptrClass) || ptrClass->InheritsFrom(claim))) {
1571 // Note we currently do not warn in case of splicing or over-expectation).
1572 if (claim->IsLoaded() && ptrClass->IsLoaded() && strcmp( claim->GetTypeInfo()->name(), ptrClass->GetTypeInfo()->name() ) == 0) {
1573 // The type is the same according to the C++ type_info, we must be in the case of
1574 // a template of Double32_t. This is actually a correct case.
1575 } else {
1576 Error("Branch", "The class requested (%s) for \"%s\" is different from the type of the pointer passed (%s)",
1577 claim->GetName(), branchname, ptrClass->GetName());
1578 }
1579 } else if (actualClass && (claim != actualClass) && !actualClass->InheritsFrom(claim)) {
1580 if (claim->IsLoaded() && actualClass->IsLoaded() && strcmp( claim->GetTypeInfo()->name(), actualClass->GetTypeInfo()->name() ) == 0) {
1581 // The type is the same according to the C++ type_info, we must be in the case of
1582 // a template of Double32_t. This is actually a correct case.
1583 } else {
1584 Error("Branch", "The actual class (%s) of the object provided for the definition of the branch \"%s\" does not inherit from %s",
1585 actualClass->GetName(), branchname, claim->GetName());
1586 }
1587 }
1588 }
1589 if (claim && claim->GetCollectionProxy() && dynamic_cast<TEmulatedCollectionProxy*>(claim->GetCollectionProxy())) {
1590 Error("Branch", writeStlWithoutProxyMsg,
1591 claim->GetName(), branchname, claim->GetName());
1592 return 0;
1593 }
1594 return Branch(branchname, classname, (void*) addobj, bufsize, splitlevel);
1595}
1596
1597////////////////////////////////////////////////////////////////////////////////
1598/// Same as TTree::Branch but automatic detection of the class name.
1599/// \see TTree::Branch for other details.
1601TBranch* TTree::BranchImp(const char* branchname, TClass* ptrClass, void* addobj, Int_t bufsize, Int_t splitlevel)
1602{
1603 if (!ptrClass) {
1604 Error("Branch", "The pointer specified for %s is not of a class known to ROOT", branchname);
1605 return 0;
1606 }
1607 TClass* actualClass = 0;
1608 void** addr = (void**) addobj;
1609 if (addr && *addr) {
1610 actualClass = ptrClass->GetActualClass(*addr);
1611 if (!actualClass) {
1612 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",
1613 branchname, ptrClass->GetName());
1614 actualClass = ptrClass;
1615 } else if ((ptrClass != actualClass) && !actualClass->InheritsFrom(ptrClass)) {
1616 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());
1617 return 0;
1618 }
1619 } else {
1620 actualClass = ptrClass;
1621 }
1622 if (actualClass && actualClass->GetCollectionProxy() && dynamic_cast<TEmulatedCollectionProxy*>(actualClass->GetCollectionProxy())) {
1623 Error("Branch", writeStlWithoutProxyMsg,
1624 actualClass->GetName(), branchname, actualClass->GetName());
1625 return 0;
1626 }
1627 return Branch(branchname, actualClass->GetName(), (void*) addobj, bufsize, splitlevel);
1628}
1629
1630////////////////////////////////////////////////////////////////////////////////
1631/// Same as TTree::Branch but automatic detection of the class name.
1632/// \see TTree::Branch for other details.
1634TBranch* TTree::BranchImpRef(const char* branchname, const char *classname, TClass* ptrClass, void *addobj, Int_t bufsize, Int_t splitlevel)
1635{
1636 TClass* claim = TClass::GetClass(classname);
1637 if (!ptrClass) {
1638 if (claim && claim->GetCollectionProxy() && dynamic_cast<TEmulatedCollectionProxy*>(claim->GetCollectionProxy())) {
1639 Error("Branch", writeStlWithoutProxyMsg,
1640 claim->GetName(), branchname, claim->GetName());
1641 return 0;
1642 } else if (claim == 0) {
1643 Error("Branch", "The pointer specified for %s is not of a class known to ROOT and %s is not a known class", branchname, classname);
1644 return 0;
1645 }
1646 ptrClass = claim;
1647 }
1648 TClass* actualClass = 0;
1649 if (!addobj) {
1650 Error("Branch", "Reference interface requires a valid object (for branch: %s)!", branchname);
1651 return 0;
1652 }
1653 actualClass = ptrClass->GetActualClass(addobj);
1654 if (ptrClass && claim) {
1655 if (!(claim->InheritsFrom(ptrClass) || ptrClass->InheritsFrom(claim))) {
1656 // Note we currently do not warn in case of splicing or over-expectation).
1657 if (claim->IsLoaded() && ptrClass->IsLoaded() && strcmp( claim->GetTypeInfo()->name(), ptrClass->GetTypeInfo()->name() ) == 0) {
1658 // The type is the same according to the C++ type_info, we must be in the case of
1659 // a template of Double32_t. This is actually a correct case.
1660 } else {
1661 Error("Branch", "The class requested (%s) for \"%s\" is different from the type of the object passed (%s)",
1662 claim->GetName(), branchname, ptrClass->GetName());
1663 }
1664 } else if (actualClass && (claim != actualClass) && !actualClass->InheritsFrom(claim)) {
1665 if (claim->IsLoaded() && actualClass->IsLoaded() && strcmp( claim->GetTypeInfo()->name(), actualClass->GetTypeInfo()->name() ) == 0) {
1666 // The type is the same according to the C++ type_info, we must be in the case of
1667 // a template of Double32_t. This is actually a correct case.
1668 } else {
1669 Error("Branch", "The actual class (%s) of the object provided for the definition of the branch \"%s\" does not inherit from %s",
1670 actualClass->GetName(), branchname, claim->GetName());
1671 }
1672 }
1673 }
1674 if (!actualClass) {
1675 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",
1676 branchname, ptrClass->GetName());
1677 actualClass = ptrClass;
1678 } else if ((ptrClass != actualClass) && !actualClass->InheritsFrom(ptrClass)) {
1679 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());
1680 return 0;
1681 }
1682 if (actualClass && actualClass->GetCollectionProxy() && dynamic_cast<TEmulatedCollectionProxy*>(actualClass->GetCollectionProxy())) {
1683 Error("Branch", writeStlWithoutProxyMsg,
1684 actualClass->GetName(), branchname, actualClass->GetName());
1685 return 0;
1686 }
1687 return BronchExec(branchname, actualClass->GetName(), (void*) addobj, kFALSE, bufsize, splitlevel);
1688}
1689
1690////////////////////////////////////////////////////////////////////////////////
1691/// Same as TTree::Branch but automatic detection of the class name.
1692/// \see TTree::Branch for other details.
1694TBranch* TTree::BranchImpRef(const char* branchname, TClass* ptrClass, EDataType datatype, void* addobj, Int_t bufsize, Int_t splitlevel)
1695{
1696 if (!ptrClass) {
1697 if (datatype == kOther_t || datatype == kNoType_t) {
1698 Error("Branch", "The pointer specified for %s is not of a class or type known to ROOT", branchname);
1699 } else {
1700 TString varname; varname.Form("%s/%c",branchname,DataTypeToChar(datatype));
1701 return Branch(branchname,addobj,varname.Data(),bufsize);
1702 }
1703 return 0;
1704 }
1705 TClass* actualClass = 0;
1706 if (!addobj) {
1707 Error("Branch", "Reference interface requires a valid object (for branch: %s)!", branchname);
1708 return 0;
1709 }
1710 actualClass = ptrClass->GetActualClass(addobj);
1711 if (!actualClass) {
1712 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",
1713 branchname, ptrClass->GetName());
1714 actualClass = ptrClass;
1715 } else if ((ptrClass != actualClass) && !actualClass->InheritsFrom(ptrClass)) {
1716 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());
1717 return 0;
1718 }
1719 if (actualClass && actualClass->GetCollectionProxy() && dynamic_cast<TEmulatedCollectionProxy*>(actualClass->GetCollectionProxy())) {
1720 Error("Branch", writeStlWithoutProxyMsg,
1721 actualClass->GetName(), branchname, actualClass->GetName());
1722 return 0;
1723 }
1724 return BronchExec(branchname, actualClass->GetName(), (void*) addobj, kFALSE, bufsize, splitlevel);
1725}
1726
1727////////////////////////////////////////////////////////////////////////////////
1728// Wrapper to turn Branch call with an std::array into the relevant leaf list
1729// call
1730TBranch *TTree::BranchImpArr(const char *branchname, EDataType datatype, std::size_t N, void *addobj, Int_t bufsize,
1731 Int_t /* splitlevel */)
1732{
1733 if (datatype == kOther_t || datatype == kNoType_t) {
1734 Error("Branch",
1735 "The inner type of the std::array passed specified for %s is not of a class or type known to ROOT",
1736 branchname);
1737 } else {
1738 TString varname;
1739 varname.Form("%s[%d]/%c", branchname, (int)N, DataTypeToChar(datatype));
1740 return Branch(branchname, addobj, varname.Data(), bufsize);
1741 }
1742 return nullptr;
1743}
1744
1745////////////////////////////////////////////////////////////////////////////////
1746/// Deprecated function. Use next function instead.
1748Int_t TTree::Branch(TList* li, Int_t bufsize /* = 32000 */ , Int_t splitlevel /* = 99 */)
1749{
1750 return Branch((TCollection*) li, bufsize, splitlevel);
1751}
1752
1753////////////////////////////////////////////////////////////////////////////////
1754/// Create one branch for each element in the collection.
1755///
1756/// Each entry in the collection becomes a top level branch if the
1757/// corresponding class is not a collection. If it is a collection, the entry
1758/// in the collection becomes in turn top level branches, etc.
1759/// The splitlevel is decreased by 1 every time a new collection is found.
1760/// For example if list is a TObjArray*
1761/// - if splitlevel = 1, one top level branch is created for each element
1762/// of the TObjArray.
1763/// - if splitlevel = 2, one top level branch is created for each array element.
1764/// if, in turn, one of the array elements is a TCollection, one top level
1765/// branch will be created for each element of this collection.
1766///
1767/// In case a collection element is a TClonesArray, the special Tree constructor
1768/// for TClonesArray is called.
1769/// The collection itself cannot be a TClonesArray.
1770///
1771/// The function returns the total number of branches created.
1772///
1773/// If name is given, all branch names will be prefixed with name_.
1774///
1775/// IMPORTANT NOTE1: This function should not be called with splitlevel < 1.
1776///
1777/// IMPORTANT NOTE2: The branches created by this function will have names
1778/// corresponding to the collection or object names. It is important
1779/// to give names to collections to avoid misleading branch names or
1780/// identical branch names. By default collections have a name equal to
1781/// the corresponding class name, e.g. the default name for a TList is "TList".
1782///
1783/// And in general, in case two or more master branches contain subbranches
1784/// with identical names, one must add a "." (dot) character at the end
1785/// of the master branch name. This will force the name of the subbranches
1786/// to be of the form `master.subbranch` instead of simply `subbranch`.
1787/// This situation happens when the top level object
1788/// has two or more members referencing the same class.
1789/// For example, if a Tree has two branches B1 and B2 corresponding
1790/// to objects of the same class MyClass, one can do:
1791/// ~~~ {.cpp}
1792/// tree.Branch("B1.","MyClass",&b1,8000,1);
1793/// tree.Branch("B2.","MyClass",&b2,8000,1);
1794/// ~~~
1795/// if MyClass has 3 members a,b,c, the two instructions above will generate
1796/// subbranches called B1.a, B1.b ,B1.c, B2.a, B2.b, B2.c
1797///
1798/// Example:
1799/// ~~~ {.cpp}
1800/// {
1801/// TTree T("T","test list");
1802/// TList *list = new TList();
1803///
1804/// TObjArray *a1 = new TObjArray();
1805/// a1->SetName("a1");
1806/// list->Add(a1);
1807/// TH1F *ha1a = new TH1F("ha1a","ha1",100,0,1);
1808/// TH1F *ha1b = new TH1F("ha1b","ha1",100,0,1);
1809/// a1->Add(ha1a);
1810/// a1->Add(ha1b);
1811/// TObjArray *b1 = new TObjArray();
1812/// b1->SetName("b1");
1813/// list->Add(b1);
1814/// TH1F *hb1a = new TH1F("hb1a","hb1",100,0,1);
1815/// TH1F *hb1b = new TH1F("hb1b","hb1",100,0,1);
1816/// b1->Add(hb1a);
1817/// b1->Add(hb1b);
1818///
1819/// TObjArray *a2 = new TObjArray();
1820/// a2->SetName("a2");
1821/// list->Add(a2);
1822/// TH1S *ha2a = new TH1S("ha2a","ha2",100,0,1);
1823/// TH1S *ha2b = new TH1S("ha2b","ha2",100,0,1);
1824/// a2->Add(ha2a);
1825/// a2->Add(ha2b);
1826///
1827/// T.Branch(list,16000,2);
1828/// T.Print();
1829/// }
1830/// ~~~
1832Int_t TTree::Branch(TCollection* li, Int_t bufsize /* = 32000 */, Int_t splitlevel /* = 99 */, const char* name /* = "" */)
1833{
1834
1835 if (!li) {
1836 return 0;
1837 }
1838 TObject* obj = 0;
1839 Int_t nbranches = GetListOfBranches()->GetEntries();
1840 if (li->InheritsFrom(TClonesArray::Class())) {
1841 Error("Branch", "Cannot call this constructor for a TClonesArray");
1842 return 0;
1843 }
1844 Int_t nch = strlen(name);
1845 TString branchname;
1846 TIter next(li);
1847 while ((obj = next())) {
1848 if ((splitlevel > 1) && obj->InheritsFrom(TCollection::Class()) && !obj->InheritsFrom(TClonesArray::Class())) {
1849 TCollection* col = (TCollection*) obj;
1850 if (nch) {
1851 branchname.Form("%s_%s_", name, col->GetName());
1852 } else {
1853 branchname.Form("%s_", col->GetName());
1854 }
1855 Branch(col, bufsize, splitlevel - 1, branchname);
1856 } else {
1857 if (nch && (name[nch-1] == '_')) {
1858 branchname.Form("%s%s", name, obj->GetName());
1859 } else {
1860 if (nch) {
1861 branchname.Form("%s_%s", name, obj->GetName());
1862 } else {
1863 branchname.Form("%s", obj->GetName());
1864 }
1865 }
1866 if (splitlevel > 99) {
1867 branchname += ".";
1868 }
1869 Bronch(branchname, obj->ClassName(), li->GetObjectRef(obj), bufsize, splitlevel - 1);
1870 }
1871 }
1872 return GetListOfBranches()->GetEntries() - nbranches;
1873}
1874
1875////////////////////////////////////////////////////////////////////////////////
1876/// Create one branch for each element in the folder.
1877/// Returns the total number of branches created.
1879Int_t TTree::Branch(const char* foldername, Int_t bufsize /* = 32000 */, Int_t splitlevel /* = 99 */)
1880{
1881 TObject* ob = gROOT->FindObjectAny(foldername);
1882 if (!ob) {
1883 return 0;
1884 }
1885 if (ob->IsA() != TFolder::Class()) {
1886 return 0;
1887 }
1888 Int_t nbranches = GetListOfBranches()->GetEntries();
1889 TFolder* folder = (TFolder*) ob;
1890 TIter next(folder->GetListOfFolders());
1891 TObject* obj = 0;
1892 char* curname = new char[1000];
1893 char occur[20];
1894 while ((obj = next())) {
1895 snprintf(curname,1000, "%s/%s", foldername, obj->GetName());
1896 if (obj->IsA() == TFolder::Class()) {
1897 Branch(curname, bufsize, splitlevel - 1);
1898 } else {
1899 void* add = (void*) folder->GetListOfFolders()->GetObjectRef(obj);
1900 for (Int_t i = 0; i < 1000; ++i) {
1901 if (curname[i] == 0) {
1902 break;
1903 }
1904 if (curname[i] == '/') {
1905 curname[i] = '.';
1906 }
1907 }
1908 Int_t noccur = folder->Occurence(obj);
1909 if (noccur > 0) {
1910 snprintf(occur,20, "_%d", noccur);
1911 strlcat(curname, occur,1000);
1912 }
1913 TBranchElement* br = (TBranchElement*) Bronch(curname, obj->ClassName(), add, bufsize, splitlevel - 1);
1914 if (br) br->SetBranchFolder();
1915 }
1916 }
1917 delete[] curname;
1918 return GetListOfBranches()->GetEntries() - nbranches;
1919}
1920
1921////////////////////////////////////////////////////////////////////////////////
1922/// Create a new TTree Branch.
1923///
1924/// This Branch constructor is provided to support non-objects in
1925/// a Tree. The variables described in leaflist may be simple
1926/// variables or structures. // See the two following
1927/// constructors for writing objects in a Tree.
1928///
1929/// By default the branch buffers are stored in the same file as the Tree.
1930/// use TBranch::SetFile to specify a different file
1931///
1932/// * address is the address of the first item of a structure.
1933/// * leaflist is the concatenation of all the variable names and types
1934/// separated by a colon character :
1935/// The variable name and the variable type are separated by a slash (/).
1936/// The variable type may be 0,1 or 2 characters. If no type is given,
1937/// the type of the variable is assumed to be the same as the previous
1938/// variable. If the first variable does not have a type, it is assumed
1939/// of type F by default. The list of currently supported types is given below:
1940/// - `C` : a character string terminated by the 0 character
1941/// - `B` : an 8 bit signed integer (`Char_t`)
1942/// - `b` : an 8 bit unsigned integer (`UChar_t`)
1943/// - `S` : a 16 bit signed integer (`Short_t`)
1944/// - `s` : a 16 bit unsigned integer (`UShort_t`)
1945/// - `I` : a 32 bit signed integer (`Int_t`)
1946/// - `i` : a 32 bit unsigned integer (`UInt_t`)
1947/// - `F` : a 32 bit floating point (`Float_t`)
1948/// - `f` : a 24 bit floating point with truncated mantissa (`Float16_t`)
1949/// - `D` : a 64 bit floating point (`Double_t`)
1950/// - `d` : a 24 bit truncated floating point (`Double32_t`)
1951/// - `L` : a 64 bit signed integer (`Long64_t`)
1952/// - `l` : a 64 bit unsigned integer (`ULong64_t`)
1953/// - `G` : a long signed integer, stored as 64 bit (`Long_t`)
1954/// - `g` : a long unsigned integer, stored as 64 bit (`ULong_t`)
1955/// - `O` : [the letter `o`, not a zero] a boolean (`Bool_t`)
1956///
1957/// Arrays of values are supported with the following syntax:
1958/// - If leaf name has the form var[nelem], where nelem is alphanumeric, then
1959/// if nelem is a leaf name, it is used as the variable size of the array,
1960/// otherwise return 0.
1961/// - If leaf name has the form var[nelem], where nelem is a non-negative integer, then
1962/// it is used as the fixed size of the array.
1963/// - If leaf name has the form of a multi-dimensional array (e.g. var[nelem][nelem2])
1964/// where nelem and nelem2 are non-negative integer) then
1965/// it is used as a 2 dimensional array of fixed size.
1966/// - In case of the truncated floating point types (Float16_t and Double32_t) you can
1967/// furthermore specify the range in the style [xmin,xmax] or [xmin,xmax,nbits] after
1968/// the type character. See `TStreamerElement::GetRange()` for further information.
1969///
1970/// Any of other form is not supported.
1971///
1972/// Note that the TTree will assume that all the item are contiguous in memory.
1973/// On some platform, this is not always true of the member of a struct or a class,
1974/// due to padding and alignment. Sorting your data member in order of decreasing
1975/// sizeof usually leads to their being contiguous in memory.
1976///
1977/// * bufsize is the buffer size in bytes for this branch
1978/// The default value is 32000 bytes and should be ok for most cases.
1979/// You can specify a larger value (e.g. 256000) if your Tree is not split
1980/// and each entry is large (Megabytes)
1981/// A small value for bufsize is optimum if you intend to access
1982/// the entries in the Tree randomly and your Tree is in split mode.
1984TBranch* TTree::Branch(const char* name, void* address, const char* leaflist, Int_t bufsize /* = 32000 */)
1985{
1986 TBranch* branch = new TBranch(this, name, address, leaflist, bufsize);
1987 if (branch->IsZombie()) {
1988 delete branch;
1989 branch = 0;
1990 return 0;
1991 }
1992 fBranches.Add(branch);
1993 return branch;
1994}
1995
1996////////////////////////////////////////////////////////////////////////////////
1997/// Create a new branch with the object of class classname at address addobj.
1998///
1999/// WARNING:
2000///
2001/// Starting with Root version 3.01, the Branch function uses the new style
2002/// branches (TBranchElement). To get the old behaviour, you can:
2003/// - call BranchOld or
2004/// - call TTree::SetBranchStyle(0)
2005///
2006/// Note that with the new style, classname does not need to derive from TObject.
2007/// It must derived from TObject if the branch style has been set to 0 (old)
2008///
2009/// Note: See the comments in TBranchElement::SetAddress() for a more
2010/// detailed discussion of the meaning of the addobj parameter in
2011/// the case of new-style branches.
2012///
2013/// Use splitlevel < 0 instead of splitlevel=0 when the class
2014/// has a custom Streamer
2015///
2016/// Note: if the split level is set to the default (99), TTree::Branch will
2017/// not issue a warning if the class can not be split.
2019TBranch* TTree::Branch(const char* name, const char* classname, void* addobj, Int_t bufsize /* = 32000 */, Int_t splitlevel /* = 99 */)
2020{
2021 if (fgBranchStyle == 1) {
2022 return Bronch(name, classname, addobj, bufsize, splitlevel);
2023 } else {
2024 if (splitlevel < 0) {
2025 splitlevel = 0;
2026 }
2027 return BranchOld(name, classname, addobj, bufsize, splitlevel);
2028 }
2029}
2030
2031////////////////////////////////////////////////////////////////////////////////
2032/// Create a new TTree BranchObject.
2033///
2034/// Build a TBranchObject for an object of class classname.
2035/// addobj is the address of a pointer to an object of class classname.
2036/// IMPORTANT: classname must derive from TObject.
2037/// The class dictionary must be available (ClassDef in class header).
2038///
2039/// This option requires access to the library where the corresponding class
2040/// is defined. Accessing one single data member in the object implies
2041/// reading the full object.
2042/// See the next Branch constructor for a more efficient storage
2043/// in case the entry consists of arrays of identical objects.
2044///
2045/// By default the branch buffers are stored in the same file as the Tree.
2046/// use TBranch::SetFile to specify a different file
2047///
2048/// IMPORTANT NOTE about branch names:
2049///
2050/// And in general, in case two or more master branches contain subbranches
2051/// with identical names, one must add a "." (dot) character at the end
2052/// of the master branch name. This will force the name of the subbranches
2053/// to be of the form `master.subbranch` instead of simply `subbranch`.
2054/// This situation happens when the top level object
2055/// has two or more members referencing the same class.
2056/// For example, if a Tree has two branches B1 and B2 corresponding
2057/// to objects of the same class MyClass, one can do:
2058/// ~~~ {.cpp}
2059/// tree.Branch("B1.","MyClass",&b1,8000,1);
2060/// tree.Branch("B2.","MyClass",&b2,8000,1);
2061/// ~~~
2062/// if MyClass has 3 members a,b,c, the two instructions above will generate
2063/// subbranches called B1.a, B1.b ,B1.c, B2.a, B2.b, B2.c
2064///
2065/// bufsize is the buffer size in bytes for this branch
2066/// The default value is 32000 bytes and should be ok for most cases.
2067/// You can specify a larger value (e.g. 256000) if your Tree is not split
2068/// and each entry is large (Megabytes)
2069/// A small value for bufsize is optimum if you intend to access
2070/// the entries in the Tree randomly and your Tree is in split mode.
2072TBranch* TTree::BranchOld(const char* name, const char* classname, void* addobj, Int_t bufsize /* = 32000 */, Int_t splitlevel /* = 1 */)
2073{
2074 TClass* cl = TClass::GetClass(classname);
2075 if (!cl) {
2076 Error("BranchOld", "Cannot find class: '%s'", classname);
2077 return 0;
2078 }
2079 if (!cl->IsTObject()) {
2080 if (fgBranchStyle == 0) {
2081 Fatal("BranchOld", "The requested class ('%s') does not inherit from TObject.\n"
2082 "\tfgBranchStyle is set to zero requesting by default to use BranchOld.\n"
2083 "\tIf this is intentional use Bronch instead of Branch or BranchOld.", classname);
2084 } else {
2085 Fatal("BranchOld", "The requested class ('%s') does not inherit from TObject.\n"
2086 "\tYou can not use BranchOld to store objects of this type.",classname);
2087 }
2088 return 0;
2089 }
2090 TBranch* branch = new TBranchObject(this, name, classname, addobj, bufsize, splitlevel);
2091 fBranches.Add(branch);
2092 if (!splitlevel) {
2093 return branch;
2094 }
2095 // We are going to fully split the class now.
2096 TObjArray* blist = branch->GetListOfBranches();
2097 const char* rdname = 0;
2098 const char* dname = 0;
2099 TString branchname;
2100 char** apointer = (char**) addobj;
2101 TObject* obj = (TObject*) *apointer;
2102 Bool_t delobj = kFALSE;
2103 if (!obj) {
2104 obj = (TObject*) cl->New();
2105 delobj = kTRUE;
2106 }
2107 // Build the StreamerInfo if first time for the class.
2108 BuildStreamerInfo(cl, obj);
2109 // Loop on all public data members of the class and its base classes.
2110 Int_t lenName = strlen(name);
2111 Int_t isDot = 0;
2112 if (name[lenName-1] == '.') {
2113 isDot = 1;
2114 }
2115 TBranch* branch1 = 0;
2116 TRealData* rd = 0;
2117 TRealData* rdi = 0;
2118 TIter nexti(cl->GetListOfRealData());
2119 TIter next(cl->GetListOfRealData());
2120 // Note: This loop results in a full split because the
2121 // real data list includes all data members of
2122 // data members.
2123 while ((rd = (TRealData*) next())) {
2124 if (rd->TestBit(TRealData::kTransient)) continue;
2125
2126 // Loop over all data members creating branches for each one.
2127 TDataMember* dm = rd->GetDataMember();
2128 if (!dm->IsPersistent()) {
2129 // Do not process members with an "!" as the first character in the comment field.
2130 continue;
2131 }
2132 if (rd->IsObject()) {
2133 // We skip data members of class type.
2134 // But we do build their real data, their
2135 // streamer info, and write their streamer
2136 // info to the current directory's file.
2137 // Oh yes, and we also do this for all of
2138 // their base classes.
2140 if (clm) {
2141 BuildStreamerInfo(clm, (char*) obj + rd->GetThisOffset());
2142 }
2143 continue;
2144 }
2145 rdname = rd->GetName();
2146 dname = dm->GetName();
2147 if (cl->CanIgnoreTObjectStreamer()) {
2148 // Skip the TObject base class data members.
2149 // FIXME: This prevents a user from ever
2150 // using these names themself!
2151 if (!strcmp(dname, "fBits")) {
2152 continue;
2153 }
2154 if (!strcmp(dname, "fUniqueID")) {
2155 continue;
2156 }
2157 }
2158 TDataType* dtype = dm->GetDataType();
2159 Int_t code = 0;
2160 if (dtype) {
2161 code = dm->GetDataType()->GetType();
2162 }
2163 // Encode branch name. Use real data member name
2164 branchname = rdname;
2165 if (isDot) {
2166 if (dm->IsaPointer()) {
2167 // FIXME: This is wrong! The asterisk is not usually in the front!
2168 branchname.Form("%s%s", name, &rdname[1]);
2169 } else {
2170 branchname.Form("%s%s", name, &rdname[0]);
2171 }
2172 }
2173 // FIXME: Change this to a string stream.
2174 TString leaflist;
2175 Int_t offset = rd->GetThisOffset();
2176 char* pointer = ((char*) obj) + offset;
2177 if (dm->IsaPointer()) {
2178 // We have a pointer to an object or a pointer to an array of basic types.
2179 TClass* clobj = 0;
2180 if (!dm->IsBasic()) {
2181 clobj = TClass::GetClass(dm->GetTypeName());
2182 }
2183 if (clobj && clobj->InheritsFrom(TClonesArray::Class())) {
2184 // We have a pointer to a clones array.
2185 char* cpointer = (char*) pointer;
2186 char** ppointer = (char**) cpointer;
2187 TClonesArray* li = (TClonesArray*) *ppointer;
2188 if (splitlevel != 2) {
2189 if (isDot) {
2190 branch1 = new TBranchClones(branch,branchname, pointer, bufsize);
2191 } else {
2192 // FIXME: This is wrong! The asterisk is not usually in the front!
2193 branch1 = new TBranchClones(branch,&branchname.Data()[1], pointer, bufsize);
2194 }
2195 blist->Add(branch1);
2196 } else {
2197 if (isDot) {
2198 branch1 = new TBranchObject(branch, branchname, li->ClassName(), pointer, bufsize);
2199 } else {
2200 // FIXME: This is wrong! The asterisk is not usually in the front!
2201 branch1 = new TBranchObject(branch, &branchname.Data()[1], li->ClassName(), pointer, bufsize);
2202 }
2203 blist->Add(branch1);
2204 }
2205 } else if (clobj) {
2206 // We have a pointer to an object.
2207 //
2208 // It must be a TObject object.
2209 if (!clobj->IsTObject()) {
2210 continue;
2211 }
2212 branch1 = new TBranchObject(branch, dname, clobj->GetName(), pointer, bufsize, 0);
2213 if (isDot) {
2214 branch1->SetName(branchname);
2215 } else {
2216 // FIXME: This is wrong! The asterisk is not usually in the front!
2217 // Do not use the first character (*).
2218 branch1->SetName(&branchname.Data()[1]);
2219 }
2220 blist->Add(branch1);
2221 } else {
2222 // We have a pointer to an array of basic types.
2223 //
2224 // Check the comments in the text of the code for an index specification.
2225 const char* index = dm->GetArrayIndex();
2226 if (index[0]) {
2227 // We are a pointer to a varying length array of basic types.
2228 //check that index is a valid data member name
2229 //if member is part of an object (e.g. fA and index=fN)
2230 //index must be changed from fN to fA.fN
2231 TString aindex (rd->GetName());
2232 Ssiz_t rdot = aindex.Last('.');
2233 if (rdot>=0) {
2234 aindex.Remove(rdot+1);
2235 aindex.Append(index);
2236 }
2237 nexti.Reset();
2238 while ((rdi = (TRealData*) nexti())) {
2239 if (rdi->TestBit(TRealData::kTransient)) continue;
2240
2241 if (!strcmp(rdi->GetName(), index)) {
2242 break;
2243 }
2244 if (!strcmp(rdi->GetName(), aindex)) {
2245 index = rdi->GetName();
2246 break;
2247 }
2248 }
2249
2250 char vcode = DataTypeToChar((EDataType)code);
2251 // Note that we differentiate between strings and
2252 // char array by the fact that there is NO specified
2253 // size for a string (see next if (code == 1)
2254
2255 if (vcode) {
2256 leaflist.Form("%s[%s]/%c", &rdname[0], index, vcode);
2257 } else {
2258 Error("BranchOld", "Cannot create branch for rdname: %s code: %d", branchname.Data(), code);
2259 leaflist = "";
2260 }
2261 } else {
2262 // We are possibly a character string.
2263 if (code == 1) {
2264 // We are a character string.
2265 leaflist.Form("%s/%s", dname, "C");
2266 } else {
2267 // Invalid array specification.
2268 // FIXME: We need an error message here.
2269 continue;
2270 }
2271 }
2272 // There are '*' in both the branchname and leaflist, remove them.
2273 TString bname( branchname );
2274 bname.ReplaceAll("*","");
2275 leaflist.ReplaceAll("*","");
2276 // Add the branch to the tree and indicate that the address
2277 // is that of a pointer to be dereferenced before using.
2278 branch1 = new TBranch(branch, bname, *((void**) pointer), leaflist, bufsize);
2279 TLeaf* leaf = (TLeaf*) branch1->GetListOfLeaves()->At(0);
2281 leaf->SetAddress((void**) pointer);
2282 blist->Add(branch1);
2283 }
2284 } else if (dm->IsBasic()) {
2285 // We have a basic type.
2286
2287 char vcode = DataTypeToChar((EDataType)code);
2288 if (vcode) {
2289 leaflist.Form("%s/%c", rdname, vcode);
2290 } else {
2291 Error("BranchOld", "Cannot create branch for rdname: %s code: %d", branchname.Data(), code);
2292 leaflist = "";
2293 }
2294 branch1 = new TBranch(branch, branchname, pointer, leaflist, bufsize);
2295 branch1->SetTitle(rdname);
2296 blist->Add(branch1);
2297 } else {
2298 // We have a class type.
2299 // Note: This cannot happen due to the rd->IsObject() test above.
2300 // FIXME: Put an error message here just in case.
2301 }
2302 if (branch1) {
2303 branch1->SetOffset(offset);
2304 } else {
2305 Warning("BranchOld", "Cannot process member: '%s'", rdname);
2306 }
2307 }
2308 if (delobj) {
2309 delete obj;
2310 obj = 0;
2311 }
2312 return branch;
2313}
2314
2315////////////////////////////////////////////////////////////////////////////////
2316/// Build the optional branch supporting the TRefTable.
2317/// This branch will keep all the information to find the branches
2318/// containing referenced objects.
2319///
2320/// At each Tree::Fill, the branch numbers containing the
2321/// referenced objects are saved to the TBranchRef basket.
2322/// When the Tree header is saved (via TTree::Write), the branch
2323/// is saved keeping the information with the pointers to the branches
2324/// having referenced objects.
2327{
2328 if (!fBranchRef) {
2329 fBranchRef = new TBranchRef(this);
2330 }
2331 return fBranchRef;
2332}
2333
2334////////////////////////////////////////////////////////////////////////////////
2335/// Create a new TTree BranchElement.
2336///
2337/// ## WARNING about this new function
2338///
2339/// This function is designed to replace the internal
2340/// implementation of the old TTree::Branch (whose implementation
2341/// has been moved to BranchOld).
2342///
2343/// NOTE: The 'Bronch' method supports only one possible calls
2344/// signature (where the object type has to be specified
2345/// explicitly and the address must be the address of a pointer).
2346/// For more flexibility use 'Branch'. Use Bronch only in (rare)
2347/// cases (likely to be legacy cases) where both the new and old
2348/// implementation of Branch needs to be used at the same time.
2349///
2350/// This function is far more powerful than the old Branch
2351/// function. It supports the full C++, including STL and has
2352/// the same behaviour in split or non-split mode. classname does
2353/// not have to derive from TObject. The function is based on
2354/// the new TStreamerInfo.
2355///
2356/// Build a TBranchElement for an object of class classname.
2357///
2358/// addr is the address of a pointer to an object of class
2359/// classname. The class dictionary must be available (ClassDef
2360/// in class header).
2361///
2362/// Note: See the comments in TBranchElement::SetAddress() for a more
2363/// detailed discussion of the meaning of the addr parameter.
2364///
2365/// This option requires access to the library where the
2366/// corresponding class is defined. Accessing one single data
2367/// member in the object implies reading the full object.
2368///
2369/// By default the branch buffers are stored in the same file as the Tree.
2370/// use TBranch::SetFile to specify a different file
2371///
2372/// IMPORTANT NOTE about branch names:
2373///
2374/// And in general, in case two or more master branches contain subbranches
2375/// with identical names, one must add a "." (dot) character at the end
2376/// of the master branch name. This will force the name of the subbranches
2377/// to be of the form `master.subbranch` instead of simply `subbranch`.
2378/// This situation happens when the top level object
2379/// has two or more members referencing the same class.
2380/// For example, if a Tree has two branches B1 and B2 corresponding
2381/// to objects of the same class MyClass, one can do:
2382/// ~~~ {.cpp}
2383/// tree.Branch("B1.","MyClass",&b1,8000,1);
2384/// tree.Branch("B2.","MyClass",&b2,8000,1);
2385/// ~~~
2386/// if MyClass has 3 members a,b,c, the two instructions above will generate
2387/// subbranches called B1.a, B1.b ,B1.c, B2.a, B2.b, B2.c
2388///
2389/// bufsize is the buffer size in bytes for this branch
2390/// The default value is 32000 bytes and should be ok for most cases.
2391/// You can specify a larger value (e.g. 256000) if your Tree is not split
2392/// and each entry is large (Megabytes)
2393/// A small value for bufsize is optimum if you intend to access
2394/// the entries in the Tree randomly and your Tree is in split mode.
2395///
2396/// Use splitlevel < 0 instead of splitlevel=0 when the class
2397/// has a custom Streamer
2398///
2399/// Note: if the split level is set to the default (99), TTree::Branch will
2400/// not issue a warning if the class can not be split.
2402TBranch* TTree::Bronch(const char* name, const char* classname, void* addr, Int_t bufsize /* = 32000 */, Int_t splitlevel /* = 99 */)
2403{
2404 return BronchExec(name, classname, addr, kTRUE, bufsize, splitlevel);
2405}
2406
2407////////////////////////////////////////////////////////////////////////////////
2408/// Helper function implementing TTree::Bronch and TTree::Branch(const char *name, T &obj);
2410TBranch* TTree::BronchExec(const char* name, const char* classname, void* addr, Bool_t isptrptr, Int_t bufsize /* = 32000 */, Int_t splitlevel /* = 99 */)
2411{
2412 TClass* cl = TClass::GetClass(classname);
2413 if (!cl) {
2414 Error("Bronch", "Cannot find class:%s", classname);
2415 return 0;
2416 }
2417
2418 //if splitlevel <= 0 and class has a custom Streamer, we must create
2419 //a TBranchObject. We cannot assume that TClass::ReadBuffer is consistent
2420 //with the custom Streamer. The penalty is that one cannot process
2421 //this Tree without the class library containing the class.
2422
2423 char* objptr = 0;
2424 if (!isptrptr) {
2425 objptr = (char*)addr;
2426 } else if (addr) {
2427 objptr = *((char**) addr);
2428 }
2429
2430 if (cl == TClonesArray::Class()) {
2431 TClonesArray* clones = (TClonesArray*) objptr;
2432 if (!clones) {
2433 Error("Bronch", "Pointer to TClonesArray is null");
2434 return 0;
2435 }
2436 if (!clones->GetClass()) {
2437 Error("Bronch", "TClonesArray with no class defined in branch: %s", name);
2438 return 0;
2439 }
2440 if (!clones->GetClass()->HasDataMemberInfo()) {
2441 Error("Bronch", "TClonesArray with no dictionary defined in branch: %s", name);
2442 return 0;
2443 }
2444 bool hasCustomStreamer = clones->GetClass()->TestBit(TClass::kHasCustomStreamerMember);
2445 if (splitlevel > 0) {
2446 if (hasCustomStreamer)
2447 Warning("Bronch", "Using split mode on a class: %s with a custom Streamer", clones->GetClass()->GetName());
2448 } else {
2449 if (hasCustomStreamer) clones->BypassStreamer(kFALSE);
2450 TBranchObject *branch = new TBranchObject(this,name,classname,addr,bufsize,0,/*compress=*/ -1,isptrptr);
2451 fBranches.Add(branch);
2452 return branch;
2453 }
2454 }
2455
2456 if (cl->GetCollectionProxy()) {
2458 //if (!collProxy) {
2459 // Error("Bronch", "%s is missing its CollectionProxy (for branch %s)", classname, name);
2460 //}
2461 TClass* inklass = collProxy->GetValueClass();
2462 if (!inklass && (collProxy->GetType() == 0)) {
2463 Error("Bronch", "%s with no class defined in branch: %s", classname, name);
2464 return 0;
2465 }
2466 if ((splitlevel > 0) && inklass && (inklass->GetCollectionProxy() == 0)) {
2468 if ((stl != ROOT::kSTLmap) && (stl != ROOT::kSTLmultimap)) {
2469 if (!inklass->HasDataMemberInfo()) {
2470 Error("Bronch", "Container with no dictionary defined in branch: %s", name);
2471 return 0;
2472 }
2474 Warning("Bronch", "Using split mode on a class: %s with a custom Streamer", inklass->GetName());
2475 }
2476 }
2477 }
2478 //-------------------------------------------------------------------------
2479 // If the splitting switch is enabled, the split level is big enough and
2480 // the collection contains pointers we can split it
2481 //////////////////////////////////////////////////////////////////////////
2482
2483 TBranch *branch;
2484 if( splitlevel > kSplitCollectionOfPointers && collProxy->HasPointers() )
2485 branch = new TBranchSTL( this, name, collProxy, bufsize, splitlevel );
2486 else
2487 branch = new TBranchElement(this, name, collProxy, bufsize, splitlevel);
2488 fBranches.Add(branch);
2489 if (isptrptr) {
2490 branch->SetAddress(addr);
2491 } else {
2492 branch->SetObject(addr);
2493 }
2494 return branch;
2495 }
2496
2497 Bool_t hasCustomStreamer = kFALSE;
2498 if (!cl->HasDataMemberInfo() && !cl->GetCollectionProxy()) {
2499 Error("Bronch", "Cannot find dictionary for class: %s", classname);
2500 return 0;
2501 }
2502
2504 // Not an STL container and the linkdef file had a "-" after the class name.
2505 hasCustomStreamer = kTRUE;
2506 }
2507
2508 if (splitlevel < 0 || ((splitlevel == 0) && hasCustomStreamer && cl->IsTObject())) {
2509 TBranchObject* branch = new TBranchObject(this, name, classname, addr, bufsize, 0, /*compress=*/ ROOT::RCompressionSetting::EAlgorithm::kInherit, isptrptr);
2510 fBranches.Add(branch);
2511 return branch;
2512 }
2513
2514 if (cl == TClonesArray::Class()) {
2515 // Special case of TClonesArray.
2516 // No dummy object is created.
2517 // The streamer info is not rebuilt unoptimized.
2518 // No dummy top-level branch is created.
2519 // No splitting is attempted.
2520 TBranchElement* branch = new TBranchElement(this, name, (TClonesArray*) objptr, bufsize, splitlevel%kSplitCollectionOfPointers);
2521 fBranches.Add(branch);
2522 if (isptrptr) {
2523 branch->SetAddress(addr);
2524 } else {
2525 branch->SetObject(addr);
2526 }
2527 return branch;
2528 }
2529
2530 //
2531 // If we are not given an object to use as an i/o buffer
2532 // then create a temporary one which we will delete just
2533 // before returning.
2534 //
2535
2536 Bool_t delobj = kFALSE;
2537
2538 if (!objptr) {
2539 objptr = (char*) cl->New();
2540 delobj = kTRUE;
2541 }
2542
2543 //
2544 // Avoid splitting unsplittable classes.
2545 //
2546
2547 if ((splitlevel > 0) && !cl->CanSplit()) {
2548 if (splitlevel != 99) {
2549 Warning("Bronch", "%s cannot be split, resetting splitlevel to 0", cl->GetName());
2550 }
2551 splitlevel = 0;
2552 }
2553
2554 //
2555 // Make sure the streamer info is built and fetch it.
2556 //
2557 // If we are splitting, then make sure the streamer info
2558 // is built unoptimized (data members are not combined).
2559 //
2560
2561 TStreamerInfo* sinfo = BuildStreamerInfo(cl, objptr, splitlevel==0);
2562 if (!sinfo) {
2563 Error("Bronch", "Cannot build the StreamerInfo for class: %s", cl->GetName());
2564 return 0;
2565 }
2566
2567 //
2568 // Create a dummy top level branch object.
2569 //
2570
2571 Int_t id = -1;
2572 if (splitlevel > 0) {
2573 id = -2;
2574 }
2575 TBranchElement* branch = new TBranchElement(this, name, sinfo, id, objptr, bufsize, splitlevel);
2576 fBranches.Add(branch);
2577
2578 //
2579 // Do splitting, if requested.
2580 //
2581
2582 if (splitlevel%kSplitCollectionOfPointers > 0) {
2583 branch->Unroll(name, cl, sinfo, objptr, bufsize, splitlevel);
2584 }
2585
2586 //
2587 // Setup our offsets into the user's i/o buffer.
2588 //
2589
2590 if (isptrptr) {
2591 branch->SetAddress(addr);
2592 } else {
2593 branch->SetObject(addr);
2594 }
2595
2596 if (delobj) {
2597 cl->Destructor(objptr);
2598 objptr = 0;
2599 }
2600
2601 return branch;
2602}
2603
2604////////////////////////////////////////////////////////////////////////////////
2605/// Browse content of the TTree.
2608{
2610 if (fUserInfo) {
2611 if (strcmp("TList",fUserInfo->GetName())==0) {
2612 fUserInfo->SetName("UserInfo");
2613 b->Add(fUserInfo);
2614 fUserInfo->SetName("TList");
2615 } else {
2616 b->Add(fUserInfo);
2617 }
2618 }
2619}
2620
2621////////////////////////////////////////////////////////////////////////////////
2622/// Build a Tree Index (default is TTreeIndex).
2623/// See a description of the parameters and functionality in
2624/// TTreeIndex::TTreeIndex().
2625///
2626/// The return value is the number of entries in the Index (< 0 indicates failure).
2627///
2628/// A TTreeIndex object pointed by fTreeIndex is created.
2629/// This object will be automatically deleted by the TTree destructor.
2630/// If an index is already existing, this is replaced by the new one without being
2631/// deleted. This behaviour prevents the deletion of a previously external index
2632/// assigned to the TTree via the TTree::SetTreeIndex() method.
2633/// \see also comments in TTree::SetTreeIndex().
2635Int_t TTree::BuildIndex(const char* majorname, const char* minorname /* = "0" */)
2636{
2637 fTreeIndex = GetPlayer()->BuildIndex(this, majorname, minorname);
2638 if (fTreeIndex->IsZombie()) {
2639 delete fTreeIndex;
2640 fTreeIndex = 0;
2641 return 0;
2642 }
2643 return fTreeIndex->GetN();
2644}
2645
2646////////////////////////////////////////////////////////////////////////////////
2647/// Build StreamerInfo for class cl.
2648/// pointer is an optional argument that may contain a pointer to an object of cl.
2650TStreamerInfo* TTree::BuildStreamerInfo(TClass* cl, void* pointer /* = 0 */, Bool_t canOptimize /* = kTRUE */ )
2651{
2652 if (!cl) {
2653 return 0;
2654 }
2655 cl->BuildRealData(pointer);
2657
2658 // Create StreamerInfo for all base classes.
2659 TBaseClass* base = 0;
2660 TIter nextb(cl->GetListOfBases());
2661 while((base = (TBaseClass*) nextb())) {
2662 if (base->IsSTLContainer()) {
2663 continue;
2664 }
2665 TClass* clm = TClass::GetClass(base->GetName());
2666 BuildStreamerInfo(clm, pointer, canOptimize);
2667 }
2668 if (sinfo && fDirectory) {
2670 }
2671 return sinfo;
2672}
2673
2674////////////////////////////////////////////////////////////////////////////////
2675/// Enable the TTreeCache unless explicitly disabled for this TTree by
2676/// a prior call to `SetCacheSize(0)`.
2677/// If the environment variable `ROOT_TTREECACHE_SIZE` or the rootrc config
2678/// `TTreeCache.Size` has been set to zero, this call will over-ride them with
2679/// a value of 1.0 (i.e. use a cache size to hold 1 cluster)
2680///
2681/// Return true if there is a cache attached to the `TTree` (either pre-exisiting
2682/// or created as part of this call)
2684{
2686 if (!file)
2687 return kFALSE;
2688 // Check for an existing cache
2690 if (pf)
2691 return kTRUE;
2692 if (fCacheUserSet && fCacheSize == 0)
2693 return kFALSE;
2694 return (0 == SetCacheSizeAux(kTRUE, -1));
2695}
2696
2697////////////////////////////////////////////////////////////////////////////////
2698/// Called by TTree::Fill() when file has reached its maximum fgMaxTreeSize.
2699/// Create a new file. If the original file is named "myfile.root",
2700/// subsequent files are named "myfile_1.root", "myfile_2.root", etc.
2701///
2702/// Returns a pointer to the new file.
2703///
2704/// Currently, the automatic change of file is restricted
2705/// to the case where the tree is in the top level directory.
2706/// The file should not contain sub-directories.
2707///
2708/// Before switching to a new file, the tree header is written
2709/// to the current file, then the current file is closed.
2710///
2711/// To process the multiple files created by ChangeFile, one must use
2712/// a TChain.
2713///
2714/// The new file name has a suffix "_N" where N is equal to fFileNumber+1.
2715/// By default a Root session starts with fFileNumber=0. One can set
2716/// fFileNumber to a different value via TTree::SetFileNumber.
2717/// In case a file named "_N" already exists, the function will try
2718/// a file named "__N", then "___N", etc.
2719///
2720/// fgMaxTreeSize can be set via the static function TTree::SetMaxTreeSize.
2721/// The default value of fgMaxTreeSize is 100 Gigabytes.
2722///
2723/// If the current file contains other objects like TH1 and TTree,
2724/// these objects are automatically moved to the new file.
2725///
2726/// \warning Be careful when writing the final Tree header to the file!
2727/// Don't do:
2728/// ~~~ {.cpp}
2729/// TFile *file = new TFile("myfile.root","recreate");
2730/// TTree *T = new TTree("T","title");
2731/// T->Fill(); // Loop
2732/// file->Write();
2733/// file->Close();
2734/// ~~~
2735/// \warning but do the following:
2736/// ~~~ {.cpp}
2737/// TFile *file = new TFile("myfile.root","recreate");
2738/// TTree *T = new TTree("T","title");
2739/// T->Fill(); // Loop
2740/// file = T->GetCurrentFile(); // To get the pointer to the current file
2741/// file->Write();
2742/// file->Close();
2743/// ~~~
2744///
2745/// \note This method is never called if the input file is a `TMemFile` or derivate.
2748{
2749 file->cd();
2750 Write();
2751 Reset();
2752 constexpr auto kBufSize = 2000;
2753 char* fname = new char[kBufSize];
2754 ++fFileNumber;
2755 char uscore[10];
2756 for (Int_t i = 0; i < 10; ++i) {
2757 uscore[i] = 0;
2758 }
2759 Int_t nus = 0;
2760 // Try to find a suitable file name that does not already exist.
2761 while (nus < 10) {
2762 uscore[nus] = '_';
2763 fname[0] = 0;
2764 strlcpy(fname, file->GetName(), kBufSize);
2765
2766 if (fFileNumber > 1) {
2767 char* cunder = strrchr(fname, '_');
2768 if (cunder) {
2769 snprintf(cunder, kBufSize - Int_t(cunder - fname), "%s%d", uscore, fFileNumber);
2770 const char* cdot = strrchr(file->GetName(), '.');
2771 if (cdot) {
2772 strlcat(fname, cdot, kBufSize);
2773 }
2774 } else {
2775 char fcount[21];
2776 snprintf(fcount,21, "%s%d", uscore, fFileNumber);
2777 strlcat(fname, fcount, kBufSize);
2778 }
2779 } else {
2780 char* cdot = strrchr(fname, '.');
2781 if (cdot) {
2782 snprintf(cdot, kBufSize - Int_t(fname-cdot), "%s%d", uscore, fFileNumber);
2783 strlcat(fname, strrchr(file->GetName(), '.'), kBufSize);
2784 } else {
2785 char fcount[21];
2786 snprintf(fcount,21, "%s%d", uscore, fFileNumber);
2787 strlcat(fname, fcount, kBufSize);
2788 }
2789 }
2790 if (gSystem->AccessPathName(fname)) {
2791 break;
2792 }
2793 ++nus;
2794 Warning("ChangeFile", "file %s already exist, trying with %d underscores", fname, nus+1);
2795 }
2796 Int_t compress = file->GetCompressionSettings();
2797 TFile* newfile = TFile::Open(fname, "recreate", "chain files", compress);
2798 if (newfile == 0) {
2799 Error("Fill","Failed to open new file %s, continuing as a memory tree.",fname);
2800 } else {
2801 Printf("Fill: Switching to new file: %s", fname);
2802 }
2803 // The current directory may contain histograms and trees.
2804 // These objects must be moved to the new file.
2805 TBranch* branch = 0;
2806 TObject* obj = 0;
2807 while ((obj = file->GetList()->First())) {
2808 file->Remove(obj);
2809 // Histogram: just change the directory.
2810 if (obj->InheritsFrom("TH1")) {
2811 gROOT->ProcessLine(TString::Format("((%s*)0x%zx)->SetDirectory((TDirectory*)0x%zx);", obj->ClassName(), (size_t) obj, (size_t) newfile));
2812 continue;
2813 }
2814 // Tree: must save all trees in the old file, reset them.
2815 if (obj->InheritsFrom(TTree::Class())) {
2816 TTree* t = (TTree*) obj;
2817 if (t != this) {
2818 t->AutoSave();
2819 t->Reset();
2821 }
2822 t->SetDirectory(newfile);
2823 TIter nextb(t->GetListOfBranches());
2824 while ((branch = (TBranch*)nextb())) {
2825 branch->SetFile(newfile);
2826 }
2827 if (t->GetBranchRef()) {
2828 t->GetBranchRef()->SetFile(newfile);
2829 }
2830 continue;
2831 }
2832 // Not a TH1 or a TTree, move object to new file.
2833 if (newfile) newfile->Append(obj);
2834 file->Remove(obj);
2835 }
2836 file->TObject::Delete();
2837 file = 0;
2838 delete[] fname;
2839 fname = 0;
2840 return newfile;
2841}
2842
2843////////////////////////////////////////////////////////////////////////////////
2844/// Check whether or not the address described by the last 3 parameters
2845/// matches the content of the branch. If a Data Model Evolution conversion
2846/// is involved, reset the fInfo of the branch.
2847/// The return values are:
2848//
2849/// - kMissingBranch (-5) : Missing branch
2850/// - kInternalError (-4) : Internal error (could not find the type corresponding to a data type number)
2851/// - kMissingCompiledCollectionProxy (-3) : Missing compiled collection proxy for a compiled collection
2852/// - kMismatch (-2) : Non-Class Pointer type given does not match the type expected by the branch
2853/// - kClassMismatch (-1) : Class Pointer type given does not match the type expected by the branch
2854/// - kMatch (0) : perfect match
2855/// - kMatchConversion (1) : match with (I/O) conversion
2856/// - kMatchConversionCollection (2) : match with (I/O) conversion of the content of a collection
2857/// - kMakeClass (3) : MakeClass mode so we can not check.
2858/// - kVoidPtr (4) : void* passed so no check was made.
2859/// - kNoCheck (5) : Underlying TBranch not yet available so no check was made.
2860/// In addition this can be multiplexed with the two bits:
2861/// - kNeedEnableDecomposedObj : in order for the address (type) to be 'usable' the branch needs to be in Decomposed Object (aka MakeClass) mode.
2862/// - kNeedDisableDecomposedObj : in order for the address (type) to be 'usable' the branch needs to not be in Decomposed Object (aka MakeClass) mode.
2863/// This bits can be masked out by using kDecomposedObjMask
2865Int_t TTree::CheckBranchAddressType(TBranch* branch, TClass* ptrClass, EDataType datatype, Bool_t isptr)
2866{
2867 if (GetMakeClass()) {
2868 // If we are in MakeClass mode so we do not really use classes.
2869 return kMakeClass;
2870 }
2871
2872 // Let's determine what we need!
2873 TClass* expectedClass = 0;
2874 EDataType expectedType = kOther_t;
2875 if (0 != branch->GetExpectedType(expectedClass,expectedType) ) {
2876 // Something went wrong, the warning message has already been issued.
2877 return kInternalError;
2878 }
2879 bool isBranchElement = branch->InheritsFrom( TBranchElement::Class() );
2880 if (expectedClass && datatype == kOther_t && ptrClass == 0) {
2881 if (isBranchElement) {
2882 TBranchElement* bEl = (TBranchElement*)branch;
2883 bEl->SetTargetClass( expectedClass->GetName() );
2884 }
2885 if (expectedClass && expectedClass->GetCollectionProxy() && dynamic_cast<TEmulatedCollectionProxy*>(expectedClass->GetCollectionProxy())) {
2886 Error("SetBranchAddress", "Unable to determine the type given for the address for \"%s\". "
2887 "The class expected (%s) refers to an stl collection and do not have a compiled CollectionProxy. "
2888 "Please generate the dictionary for this class (%s)",
2889 branch->GetName(), expectedClass->GetName(), expectedClass->GetName());
2891 }
2892 if (!expectedClass->IsLoaded()) {
2893 // The originally expected class does not have a dictionary, it is then plausible that the pointer being passed is the right type
2894 // (we really don't know). So let's express that.
2895 Error("SetBranchAddress", "Unable to determine the type given for the address for \"%s\". "
2896 "The class expected (%s) does not have a dictionary and needs to be emulated for I/O purposes but is being passed a compiled object."
2897 "Please generate the dictionary for this class (%s)",
2898 branch->GetName(), expectedClass->GetName(), expectedClass->GetName());
2899 } else {
2900 Error("SetBranchAddress", "Unable to determine the type given for the address for \"%s\". "
2901 "This is probably due to a missing dictionary, the original data class for this branch is %s.", branch->GetName(), expectedClass->GetName());
2902 }
2903 return kClassMismatch;
2904 }
2905 if (expectedClass && ptrClass && (branch->GetMother() == branch)) {
2906 // Top Level branch
2907 if (!isptr) {
2908 Error("SetBranchAddress", "The address for \"%s\" should be the address of a pointer!", branch->GetName());
2909 }
2910 }
2911 if (expectedType == kFloat16_t) {
2912 expectedType = kFloat_t;
2913 }
2914 if (expectedType == kDouble32_t) {
2915 expectedType = kDouble_t;
2916 }
2917 if (datatype == kFloat16_t) {
2918 datatype = kFloat_t;
2919 }
2920 if (datatype == kDouble32_t) {
2921 datatype = kDouble_t;
2922 }
2923
2924 /////////////////////////////////////////////////////////////////////////////
2925 // Deal with the class renaming
2926 /////////////////////////////////////////////////////////////////////////////
2927
2928 if( expectedClass && ptrClass &&
2929 expectedClass != ptrClass &&
2930 isBranchElement &&
2931 ptrClass->GetSchemaRules() &&
2932 ptrClass->GetSchemaRules()->HasRuleWithSourceClass( expectedClass->GetName() ) ) {
2933 TBranchElement* bEl = (TBranchElement*)branch;
2934
2935 if ( ptrClass->GetCollectionProxy() && expectedClass->GetCollectionProxy() ) {
2936 if (gDebug > 7)
2937 Info("SetBranchAddress", "Matching STL collection (at least according to the SchemaRuleSet when "
2938 "reading a %s into a %s",expectedClass->GetName(),ptrClass->GetName());
2939
2940 bEl->SetTargetClass( ptrClass->GetName() );
2941 return kMatchConversion;
2942
2943 } else if ( !ptrClass->GetConversionStreamerInfo( expectedClass, bEl->GetClassVersion() ) &&
2944 !ptrClass->FindConversionStreamerInfo( expectedClass, bEl->GetCheckSum() ) ) {
2945 Error("SetBranchAddress", "The pointer type given \"%s\" does not correspond to the type needed \"%s\" by the branch: %s", ptrClass->GetName(), bEl->GetClassName(), branch->GetName());
2946
2947 bEl->SetTargetClass( expectedClass->GetName() );
2948 return kClassMismatch;
2949 }
2950 else {
2951
2952 bEl->SetTargetClass( ptrClass->GetName() );
2953 return kMatchConversion;
2954 }
2955
2956 } else if (expectedClass && ptrClass && !expectedClass->InheritsFrom(ptrClass)) {
2957
2958 if (expectedClass->GetCollectionProxy() && ptrClass->GetCollectionProxy() &&
2959 isBranchElement &&
2960 expectedClass->GetCollectionProxy()->GetValueClass() &&
2961 ptrClass->GetCollectionProxy()->GetValueClass() )
2962 {
2963 // In case of collection, we know how to convert them, if we know how to convert their content.
2964 // NOTE: we need to extend this to std::pair ...
2965
2966 TClass *onfileValueClass = expectedClass->GetCollectionProxy()->GetValueClass();
2967 TClass *inmemValueClass = ptrClass->GetCollectionProxy()->GetValueClass();
2968
2969 if (inmemValueClass->GetSchemaRules() &&
2970 inmemValueClass->GetSchemaRules()->HasRuleWithSourceClass(onfileValueClass->GetName() ) )
2971 {
2972 TBranchElement* bEl = (TBranchElement*)branch;
2973 bEl->SetTargetClass( ptrClass->GetName() );
2975 }
2976 }
2977
2978 Error("SetBranchAddress", "The pointer type given (%s) does not correspond to the class needed (%s) by the branch: %s", ptrClass->GetName(), expectedClass->GetName(), branch->GetName());
2979 if (isBranchElement) {
2980 TBranchElement* bEl = (TBranchElement*)branch;
2981 bEl->SetTargetClass( expectedClass->GetName() );
2982 }
2983 return kClassMismatch;
2984
2985 } else if ((expectedType != kOther_t) && (datatype != kOther_t) && (expectedType != kNoType_t) && (datatype != kNoType_t) && (expectedType != datatype)) {
2986 if (datatype != kChar_t) {
2987 // For backward compatibility we assume that (char*) was just a cast and/or a generic address
2988 Error("SetBranchAddress", "The pointer type given \"%s\" (%d) does not correspond to the type needed \"%s\" (%d) by the branch: %s",
2989 TDataType::GetTypeName(datatype), datatype, TDataType::GetTypeName(expectedType), expectedType, branch->GetName());
2990 return kMismatch;
2991 }
2992 } else if ((expectedClass && (datatype != kOther_t && datatype != kNoType_t && datatype != kInt_t)) ||
2993 (ptrClass && (expectedType != kOther_t && expectedType != kNoType_t && datatype != kInt_t)) ) {
2994 // Sometime a null pointer can look an int, avoid complaining in that case.
2995 if (expectedClass) {
2996 Error("SetBranchAddress", "The pointer type given \"%s\" (%d) does not correspond to the type needed \"%s\" by the branch: %s",
2997 TDataType::GetTypeName(datatype), datatype, expectedClass->GetName(), branch->GetName());
2998 if (isBranchElement) {
2999 TBranchElement* bEl = (TBranchElement*)branch;
3000 bEl->SetTargetClass( expectedClass->GetName() );
3001 }
3002 } else {
3003 // In this case, it is okay if the first data member is of the right type (to support the case where we are being passed
3004 // a struct).
3005 bool found = false;
3006 if (ptrClass->IsLoaded()) {
3007 TIter next(ptrClass->GetListOfRealData());
3008 TRealData *rdm;
3009 while ((rdm = (TRealData*)next())) {
3010 if (rdm->GetThisOffset() == 0) {
3011 TDataType *dmtype = rdm->GetDataMember()->GetDataType();
3012 if (dmtype) {
3013 EDataType etype = (EDataType)dmtype->GetType();
3014 if (etype == expectedType) {
3015 found = true;
3016 }
3017 }
3018 break;
3019 }
3020 }
3021 } else {
3022 TIter next(ptrClass->GetListOfDataMembers());
3023 TDataMember *dm;
3024 while ((dm = (TDataMember*)next())) {
3025 if (dm->GetOffset() == 0) {
3026 TDataType *dmtype = dm->GetDataType();
3027 if (dmtype) {
3028 EDataType etype = (EDataType)dmtype->GetType();
3029 if (etype == expectedType) {
3030 found = true;
3031 }
3032 }
3033 break;
3034 }
3035 }
3036 }
3037 if (found) {
3038 // let's check the size.
3039 TLeaf *last = (TLeaf*)branch->GetListOfLeaves()->Last();
3040 long len = last->GetOffset() + last->GetLenType() * last->GetLen();
3041 if (len <= ptrClass->Size()) {
3042 return kMatch;
3043 }
3044 }
3045 Error("SetBranchAddress", "The pointer type given \"%s\" does not correspond to the type needed \"%s\" (%d) by the branch: %s",
3046 ptrClass->GetName(), TDataType::GetTypeName(expectedType), expectedType, branch->GetName());
3047 }
3048 return kMismatch;
3049 }
3050 if (expectedClass && expectedClass->GetCollectionProxy() && dynamic_cast<TEmulatedCollectionProxy*>(expectedClass->GetCollectionProxy())) {
3051 Error("SetBranchAddress", writeStlWithoutProxyMsg,
3052 expectedClass->GetName(), branch->GetName(), expectedClass->GetName());
3053 if (isBranchElement) {
3054 TBranchElement* bEl = (TBranchElement*)branch;
3055 bEl->SetTargetClass( expectedClass->GetName() );
3056 }
3058 }
3059 if (isBranchElement) {
3060 if (expectedClass) {
3061 TBranchElement* bEl = (TBranchElement*)branch;
3062 bEl->SetTargetClass( expectedClass->GetName() );
3063 } else if (expectedType != kNoType_t && expectedType != kOther_t) {
3065 }
3066 }
3067 return kMatch;
3068}
3069
3070////////////////////////////////////////////////////////////////////////////////
3071/// Create a clone of this tree and copy nentries.
3072///
3073/// By default copy all entries.
3074/// The compression level of the cloned tree is set to the destination
3075/// file's compression level.
3076///
3077/// NOTE: Only active branches are copied.
3078/// NOTE: If the TTree is a TChain, the structure of the first TTree
3079/// is used for the copy.
3080///
3081/// IMPORTANT: The cloned tree stays connected with this tree until
3082/// this tree is deleted. In particular, any changes in
3083/// branch addresses in this tree are forwarded to the
3084/// clone trees, unless a branch in a clone tree has had
3085/// its address changed, in which case that change stays in
3086/// effect. When this tree is deleted, all the addresses of
3087/// the cloned tree are reset to their default values.
3088///
3089/// If 'option' contains the word 'fast' and nentries is -1, the
3090/// cloning will be done without unzipping or unstreaming the baskets
3091/// (i.e., a direct copy of the raw bytes on disk).
3092///
3093/// When 'fast' is specified, 'option' can also contain a sorting
3094/// order for the baskets in the output file.
3095///
3096/// There are currently 3 supported sorting order:
3097///
3098/// - SortBasketsByOffset (the default)
3099/// - SortBasketsByBranch
3100/// - SortBasketsByEntry
3101///
3102/// When using SortBasketsByOffset the baskets are written in the
3103/// output file in the same order as in the original file (i.e. the
3104/// baskets are sorted by their offset in the original file; Usually
3105/// this also means that the baskets are sorted by the index/number of
3106/// the _last_ entry they contain)
3107///
3108/// When using SortBasketsByBranch all the baskets of each individual
3109/// branches are stored contiguously. This tends to optimize reading
3110/// speed when reading a small number (1->5) of branches, since all
3111/// their baskets will be clustered together instead of being spread
3112/// across the file. However it might decrease the performance when
3113/// reading more branches (or the full entry).
3114///
3115/// When using SortBasketsByEntry the baskets with the lowest starting
3116/// entry are written first. (i.e. the baskets are sorted by the
3117/// index/number of the first entry they contain). This means that on
3118/// the file the baskets will be in the order in which they will be
3119/// needed when reading the whole tree sequentially.
3120///
3121/// For examples of CloneTree, see tutorials:
3122///
3123/// - copytree.C:
3124/// A macro to copy a subset of a TTree to a new TTree.
3125/// The input file has been generated by the program in
3126/// $ROOTSYS/test/Event with: Event 1000 1 1 1
3127///
3128/// - copytree2.C:
3129/// A macro to copy a subset of a TTree to a new TTree.
3130/// One branch of the new Tree is written to a separate file.
3131/// The input file has been generated by the program in
3132/// $ROOTSYS/test/Event with: Event 1000 1 1 1
3134TTree* TTree::CloneTree(Long64_t nentries /* = -1 */, Option_t* option /* = "" */)
3135{
3136 // Options
3137 Bool_t fastClone = kFALSE;
3138
3139 TString opt = option;
3140 opt.ToLower();
3141 if (opt.Contains("fast")) {
3142 fastClone = kTRUE;
3143 }
3144
3145 // If we are a chain, switch to the first tree.
3146 if ((fEntries > 0) && (LoadTree(0) < 0)) {
3147 // FIXME: We need an error message here.
3148 return 0;
3149 }
3150
3151 // Note: For a tree we get the this pointer, for
3152 // a chain we get the chain's current tree.
3153 TTree* thistree = GetTree();
3154
3155 // We will use this to override the IO features on the cloned branches.
3156 ROOT::TIOFeatures features = this->GetIOFeatures();
3157 ;
3158
3159 // Note: For a chain, the returned clone will be
3160 // a clone of the chain's first tree.
3161 TTree* newtree = (TTree*) thistree->Clone();
3162 if (!newtree) {
3163 return 0;
3164 }
3165
3166 // The clone should not delete any objects allocated by SetAddress().
3167 TObjArray* branches = newtree->GetListOfBranches();
3168 Int_t nb = branches->GetEntriesFast();
3169 for (Int_t i = 0; i < nb; ++i) {
3170 TBranch* br = (TBranch*) branches->UncheckedAt(i);
3172 ((TBranchElement*) br)->ResetDeleteObject();
3173 }
3174 }
3175
3176 // Add the new tree to the list of clones so that
3177 // we can later inform it of changes to branch addresses.
3178 thistree->AddClone(newtree);
3179 if (thistree != this) {
3180 // In case this object is a TChain, add the clone
3181 // also to the TChain's list of clones.
3182 AddClone(newtree);
3183 }
3184
3185 newtree->Reset();
3186
3187 TDirectory* ndir = newtree->GetDirectory();
3188 TFile* nfile = 0;
3189 if (ndir) {
3190 nfile = ndir->GetFile();
3191 }
3192 Int_t newcomp = -1;
3193 if (nfile) {
3194 newcomp = nfile->GetCompressionSettings();
3195 }
3196
3197 //
3198 // Delete non-active branches from the clone.
3199 //
3200 // Note: If we are a chain, this does nothing
3201 // since chains have no leaves.
3202 TObjArray* leaves = newtree->GetListOfLeaves();
3203 Int_t nleaves = leaves->GetEntriesFast();
3204 for (Int_t lndx = 0; lndx < nleaves; ++lndx) {
3205 TLeaf* leaf = (TLeaf*) leaves->UncheckedAt(lndx);
3206 if (!leaf) {
3207 continue;
3208 }
3209 TBranch* branch = leaf->GetBranch();
3210 if (branch && (newcomp > -1)) {
3211 branch->SetCompressionSettings(newcomp);
3212 }
3213 if (branch) branch->SetIOFeatures(features);
3214 if (!branch || !branch->TestBit(kDoNotProcess)) {
3215 continue;
3216 }
3217 // size might change at each iteration of the loop over the leaves.
3218 nb = branches->GetEntriesFast();
3219 for (Long64_t i = 0; i < nb; ++i) {
3220 TBranch* br = (TBranch*) branches->UncheckedAt(i);
3221 if (br == branch) {
3222 branches->RemoveAt(i);
3223 delete br;
3224 br = 0;
3225 branches->Compress();
3226 break;
3227 }
3228 TObjArray* lb = br->GetListOfBranches();
3229 Int_t nb1 = lb->GetEntriesFast();
3230 for (Int_t j = 0; j < nb1; ++j) {
3231 TBranch* b1 = (TBranch*) lb->UncheckedAt(j);
3232 if (!b1) {
3233 continue;
3234 }
3235 if (b1 == branch) {
3236 lb->RemoveAt(j);
3237 delete b1;
3238 b1 = 0;
3239 lb->Compress();
3240 break;
3241 }
3242 TObjArray* lb1 = b1->GetListOfBranches();
3243 Int_t nb2 = lb1->GetEntriesFast();
3244 for (Int_t k = 0; k < nb2; ++k) {
3245 TBranch* b2 = (TBranch*) lb1->UncheckedAt(k);
3246 if (!b2) {
3247 continue;
3248 }
3249 if (b2 == branch) {
3250 lb1->RemoveAt(k);
3251 delete b2;
3252 b2 = 0;
3253 lb1->Compress();
3254 break;
3255 }
3256 }
3257 }
3258 }
3259 }
3260 leaves->Compress();
3261
3262 // Copy MakeClass status.
3263 newtree->SetMakeClass(fMakeClass);
3264
3265 // Copy branch addresses.
3266 CopyAddresses(newtree);
3267
3268 //
3269 // Copy entries if requested.
3270 //
3271
3272 if (nentries != 0) {
3273 if (fastClone && (nentries < 0)) {
3274 if ( newtree->CopyEntries( this, -1, option, kFALSE ) < 0 ) {
3275 // There was a problem!
3276 Error("CloneTTree", "TTree has not been cloned\n");
3277 delete newtree;
3278 newtree = 0;
3279 return 0;
3280 }
3281 } else {
3282 newtree->CopyEntries( this, nentries, option, kFALSE );
3283 }
3284 }
3285
3286 return newtree;
3287}
3288
3289////////////////////////////////////////////////////////////////////////////////
3290/// Set branch addresses of passed tree equal to ours.
3291/// If undo is true, reset the branch addresses instead of copying them.
3292/// This ensures 'separation' of a cloned tree from its original.
3295{
3296 // Copy branch addresses starting from branches.
3297 TObjArray* branches = GetListOfBranches();
3298 Int_t nbranches = branches->GetEntriesFast();
3299 for (Int_t i = 0; i < nbranches; ++i) {
3300 TBranch* branch = (TBranch*) branches->UncheckedAt(i);
3301 if (branch->TestBit(kDoNotProcess)) {
3302 continue;
3303 }
3304 if (undo) {
3305 TBranch* br = tree->GetBranch(branch->GetName());
3306 tree->ResetBranchAddress(br);
3307 } else {
3308 char* addr = branch->GetAddress();
3309 if (!addr) {
3310 if (branch->IsA() == TBranch::Class()) {
3311 // If the branch was created using a leaflist, the branch itself may not have
3312 // an address but the leaf might already.
3313 TLeaf *firstleaf = (TLeaf*)branch->GetListOfLeaves()->At(0);
3314 if (!firstleaf || firstleaf->GetValuePointer()) {
3315 // Either there is no leaf (and thus no point in copying the address)
3316 // or the leaf has an address but we can not copy it via the branche
3317 // this will be copied via the next loop (over the leaf).
3318 continue;
3319 }
3320 }
3321 // Note: This may cause an object to be allocated.
3322 branch->SetAddress(0);
3323 addr = branch->GetAddress();
3324 }
3325 TBranch* br = tree->GetBranch(branch->GetFullName());
3326 if (br) {
3327 if (br->GetMakeClass() != branch->GetMakeClass())
3328 br->SetMakeClass(branch->GetMakeClass());
3329 br->SetAddress(addr);
3330 // The copy does not own any object allocated by SetAddress().
3332 ((TBranchElement*) br)->ResetDeleteObject();
3333 }
3334 } else {
3335 Warning("CopyAddresses", "Could not find branch named '%s' in tree named '%s'", branch->GetName(), tree->GetName());
3336 }
3337 }
3338 }
3339
3340 // Copy branch addresses starting from leaves.
3341 TObjArray* tleaves = tree->GetListOfLeaves();
3342 Int_t ntleaves = tleaves->GetEntriesFast();
3343 std::set<TLeaf*> updatedLeafCount;
3344 for (Int_t i = 0; i < ntleaves; ++i) {
3345 TLeaf* tleaf = (TLeaf*) tleaves->UncheckedAt(i);
3346 TBranch* tbranch = tleaf->GetBranch();
3347 TBranch* branch = GetBranch(tbranch->GetName());
3348 if (!branch) {
3349 continue;
3350 }
3351 TLeaf* leaf = branch->GetLeaf(tleaf->GetName());
3352 if (!leaf) {
3353 continue;
3354 }
3355 if (branch->TestBit(kDoNotProcess)) {
3356 continue;
3357 }
3358 if (undo) {
3359 // Now we know whether the address has been transfered
3360 tree->ResetBranchAddress(tbranch);
3361 } else {
3362 TBranchElement *mother = dynamic_cast<TBranchElement*>(leaf->GetBranch()->GetMother());
3363 bool needAddressReset = false;
3364 if (leaf->GetLeafCount() && (leaf->TestBit(TLeaf::kNewValue) || !leaf->GetValuePointer() || (mother && mother->IsObjectOwner())) && tleaf->GetLeafCount())
3365 {
3366 // If it is an array and it was allocated by the leaf itself,
3367 // let's make sure it is large enough for the incoming data.
3368 if (leaf->GetLeafCount()->GetMaximum() < tleaf->GetLeafCount()->GetMaximum()) {
3369 leaf->GetLeafCount()->IncludeRange( tleaf->GetLeafCount() );
3370 updatedLeafCount.insert(leaf->GetLeafCount());
3371 needAddressReset = true;
3372 } else {
3373 needAddressReset = (updatedLeafCount.find(leaf->GetLeafCount()) != updatedLeafCount.end());
3374 }
3375 }
3376 if (needAddressReset && leaf->GetValuePointer()) {
3377 if (leaf->IsA() == TLeafElement::Class() && mother)
3378 mother->ResetAddress();
3379 else
3380 leaf->SetAddress(nullptr);
3381 }
3382 if (!branch->GetAddress() && !leaf->GetValuePointer()) {
3383 // We should attempts to set the address of the branch.
3384 // something like:
3385 //(TBranchElement*)branch->GetMother()->SetAddress(0)
3386 //plus a few more subtleties (see TBranchElement::GetEntry).
3387 //but for now we go the simplest route:
3388 //
3389 // Note: This may result in the allocation of an object.
3390 branch->SetupAddresses();
3391 }
3392 if (branch->GetAddress()) {
3393 tree->SetBranchAddress(branch->GetName(), (void*) branch->GetAddress());
3394 TBranch* br = tree->GetBranch(branch->GetName());
3395 if (br) {
3396 if (br->IsA() != branch->IsA()) {
3397 Error(
3398 "CopyAddresses",
3399 "Branch kind mismatch between input tree '%s' and output tree '%s' for branch '%s': '%s' vs '%s'",
3400 tree->GetName(), br->GetTree()->GetName(), br->GetName(), branch->IsA()->GetName(),
3401 br->IsA()->GetName());
3402 }
3403 // The copy does not own any object allocated by SetAddress().
3404 // FIXME: We do too much here, br may not be a top-level branch.
3406 ((TBranchElement*) br)->ResetDeleteObject();
3407 }
3408 } else {
3409 Warning("CopyAddresses", "Could not find branch named '%s' in tree named '%s'", branch->GetName(), tree->GetName());
3410 }
3411 } else {
3412 tleaf->SetAddress(leaf->GetValuePointer());
3413 }
3414 }
3415 }
3416
3417 if (undo &&
3418 ( tree->IsA()->InheritsFrom("TNtuple") || tree->IsA()->InheritsFrom("TNtupleD") )
3419 ) {
3420 tree->ResetBranchAddresses();
3421 }
3422}
3423
3424namespace {
3425
3426 enum EOnIndexError { kDrop, kKeep, kBuild };
3427
3428 static Bool_t R__HandleIndex(EOnIndexError onIndexError, TTree *newtree, TTree *oldtree)
3429 {
3430 // Return true if we should continue to handle indices, false otherwise.
3431
3432 Bool_t withIndex = kTRUE;
3433
3434 if ( newtree->GetTreeIndex() ) {
3435 if ( oldtree->GetTree()->GetTreeIndex() == 0 ) {
3436 switch (onIndexError) {
3437 case kDrop:
3438 delete newtree->GetTreeIndex();
3439 newtree->SetTreeIndex(0);
3440 withIndex = kFALSE;
3441 break;
3442 case kKeep:
3443 // Nothing to do really.
3444 break;
3445 case kBuild:
3446 // Build the index then copy it
3447 if (oldtree->GetTree()->BuildIndex(newtree->GetTreeIndex()->GetMajorName(), newtree->GetTreeIndex()->GetMinorName())) {
3448 newtree->GetTreeIndex()->Append(oldtree->GetTree()->GetTreeIndex(), kTRUE);
3449 // Clean up
3450 delete oldtree->GetTree()->GetTreeIndex();
3451 oldtree->GetTree()->SetTreeIndex(0);
3452 }
3453 break;
3454 }
3455 } else {
3456 newtree->GetTreeIndex()->Append(oldtree->GetTree()->GetTreeIndex(), kTRUE);
3457 }
3458 } else if ( oldtree->GetTree()->GetTreeIndex() != 0 ) {
3459 // We discover the first index in the middle of the chain.
3460 switch (onIndexError) {
3461 case kDrop:
3462 // Nothing to do really.
3463 break;
3464 case kKeep: {
3466 index->SetTree(newtree);
3467 newtree->SetTreeIndex(index);
3468 break;
3469 }
3470 case kBuild:
3471 if (newtree->GetEntries() == 0) {
3472 // Start an index.
3474 index->SetTree(newtree);
3475 newtree->SetTreeIndex(index);
3476 } else {
3477 // Build the index so far.
3478 if (newtree->BuildIndex(oldtree->GetTree()->GetTreeIndex()->GetMajorName(), oldtree->GetTree()->GetTreeIndex()->GetMinorName())) {
3479 newtree->GetTreeIndex()->Append(oldtree->GetTree()->GetTreeIndex(), kTRUE);
3480 }
3481 }
3482 break;
3483 }
3484 } else if ( onIndexError == kDrop ) {
3485 // There is no index on this or on tree->GetTree(), we know we have to ignore any further
3486 // index
3487 withIndex = kFALSE;
3488 }
3489 return withIndex;
3490 }
3491}
3492
3493////////////////////////////////////////////////////////////////////////////////
3494/// Copy nentries from given tree to this tree.
3495/// This routines assumes that the branches that intended to be copied are
3496/// already connected. The typical case is that this tree was created using
3497/// tree->CloneTree(0).
3498///
3499/// By default copy all entries.
3500///
3501/// Returns number of bytes copied to this tree.
3502///
3503/// If 'option' contains the word 'fast' and nentries is -1, the cloning will be
3504/// done without unzipping or unstreaming the baskets (i.e., a direct copy of the
3505/// raw bytes on disk).
3506///
3507/// When 'fast' is specified, 'option' can also contains a sorting order for the
3508/// baskets in the output file.
3509///
3510/// There are currently 3 supported sorting order:
3511///
3512/// - SortBasketsByOffset (the default)
3513/// - SortBasketsByBranch
3514/// - SortBasketsByEntry
3515///
3516/// See TTree::CloneTree for a detailed explanation of the semantics of these 3 options.
3517///
3518/// If the tree or any of the underlying tree of the chain has an index, that index and any
3519/// index in the subsequent underlying TTree objects will be merged.
3520///
3521/// There are currently three 'options' to control this merging:
3522/// - NoIndex : all the TTreeIndex object are dropped.
3523/// - DropIndexOnError : if any of the underlying TTree object do no have a TTreeIndex,
3524/// they are all dropped.
3525/// - AsIsIndexOnError [default]: In case of missing TTreeIndex, the resulting TTree index has gaps.
3526/// - BuildIndexOnError : If any of the underlying TTree objects do not have a TTreeIndex,
3527/// all TTreeIndex are 'ignored' and the missing piece are rebuilt.
3529Long64_t TTree::CopyEntries(TTree* tree, Long64_t nentries /* = -1 */, Option_t* option /* = "" */, Bool_t needCopyAddresses /* = false */)
3530{
3531 if (!tree) {
3532 return 0;
3533 }
3534 // Options
3535 TString opt = option;
3536 opt.ToLower();
3537 Bool_t fastClone = opt.Contains("fast");
3538 Bool_t withIndex = !opt.Contains("noindex");
3539 EOnIndexError onIndexError;
3540 if (opt.Contains("asisindex")) {
3541 onIndexError = kKeep;
3542 } else if (opt.Contains("buildindex")) {
3543 onIndexError = kBuild;
3544 } else if (opt.Contains("dropindex")) {
3545 onIndexError = kDrop;
3546 } else {
3547 onIndexError = kBuild;
3548 }
3549 Ssiz_t cacheSizeLoc = opt.Index("cachesize=");
3550 Int_t cacheSize = -1;
3551 if (cacheSizeLoc != TString::kNPOS) {
3552 // If the parse faile, cacheSize stays at -1.
3553 Ssiz_t cacheSizeEnd = opt.Index(" ",cacheSizeLoc+10) - (cacheSizeLoc+10);
3554 TSubString cacheSizeStr( opt(cacheSizeLoc+10,cacheSizeEnd) );
3555 auto parseResult = ROOT::FromHumanReadableSize(cacheSizeStr,cacheSize);
3556 if (parseResult == ROOT::EFromHumanReadableSize::kParseFail) {
3557 Warning("CopyEntries","The cachesize option can not be parsed: %s. The default size will be used.",cacheSizeStr.String().Data());
3558 } else if (parseResult == ROOT::EFromHumanReadableSize::kOverflow) {
3559 double m;
3560 const char *munit = nullptr;
3561 ROOT::ToHumanReadableSize(std::numeric_limits<decltype(cacheSize)>::max(),false,&m,&munit);
3562
3563 Warning("CopyEntries","The cachesize option is too large: %s (%g%s max). The default size will be used.",cacheSizeStr.String().Data(),m,munit);
3564 }
3565 }
3566 if (gDebug > 0 && cacheSize != -1) Info("CopyEntries","Using Cache size: %d\n",cacheSize);
3567
3568 Long64_t nbytes = 0;
3569 Long64_t treeEntries = tree->GetEntriesFast();
3570 if (nentries < 0) {
3571 nentries = treeEntries;
3572 } else if (nentries > treeEntries) {
3573 nentries = treeEntries;
3574 }
3575
3576 if (fastClone && (nentries < 0 || nentries == tree->GetEntriesFast())) {
3577 // Quickly copy the basket without decompression and streaming.
3578 Long64_t totbytes = GetTotBytes();
3579 for (Long64_t i = 0; i < nentries; i += tree->GetTree()->GetEntries()) {
3580 if (tree->LoadTree(i) < 0) {
3581 break;
3582 }
3583 if ( withIndex ) {
3584 withIndex = R__HandleIndex( onIndexError, this, tree );
3585 }
3586 if (this->GetDirectory()) {
3587 TFile* file2 = this->GetDirectory()->GetFile();
3588 if (file2 && (file2->GetEND() > TTree::GetMaxTreeSize())) {
3589 if (this->GetDirectory() == (TDirectory*) file2) {
3590 this->ChangeFile(file2);
3591 }
3592 }
3593 }
3594 TTreeCloner cloner(tree->GetTree(), this, option, TTreeCloner::kNoWarnings);
3595 if (cloner.IsValid()) {
3596 this->SetEntries(this->GetEntries() + tree->GetTree()->GetEntries());
3597 if (cacheSize != -1) cloner.SetCacheSize(cacheSize);
3598 cloner.Exec();
3599 } else {
3600 if (i == 0) {
3601 Warning("CopyEntries","%s",cloner.GetWarning());
3602 // If the first cloning does not work, something is really wrong
3603 // (since apriori the source and target are exactly the same structure!)
3604 return -1;
3605 } else {
3606 if (cloner.NeedConversion()) {
3607 TTree *localtree = tree->GetTree();
3608 Long64_t tentries = localtree->GetEntries();
3609 if (needCopyAddresses) {
3610 // Copy MakeClass status.
3611 tree->SetMakeClass(fMakeClass);
3612 // Copy branch addresses.
3614 }
3615 for (Long64_t ii = 0; ii < tentries; ii++) {
3616 if (localtree->GetEntry(ii) <= 0) {
3617 break;
3618 }
3619 this->Fill();
3620 }
3621 if (needCopyAddresses)
3622 tree->ResetBranchAddresses();
3623 if (this->GetTreeIndex()) {
3624 this->GetTreeIndex()->Append(tree->GetTree()->GetTreeIndex(), kTRUE);
3625 }
3626 } else {
3627 Warning("CopyEntries","%s",cloner.GetWarning());
3628 if (tree->GetDirectory() && tree->GetDirectory()->GetFile()) {
3629 Warning("CopyEntries", "Skipped file %s\n", tree->GetDirectory()->GetFile()->GetName());
3630 } else {
3631 Warning("CopyEntries", "Skipped file number %d\n", tree->GetTreeNumber());
3632 }
3633 }
3634 }
3635 }
3636
3637 }
3638 if (this->GetTreeIndex()) {
3639 this->GetTreeIndex()->Append(0,kFALSE); // Force the sorting
3640 }
3641 nbytes = GetTotBytes() - totbytes;
3642 } else {
3643 if (nentries < 0) {
3644 nentries = treeEntries;
3645 } else if (nentries > treeEntries) {
3646 nentries = treeEntries;
3647 }
3648 if (needCopyAddresses) {
3649 // Copy MakeClass status.
3650 tree->SetMakeClass(fMakeClass);
3651 // Copy branch addresses.
3653 }
3654 Int_t treenumber = -1;
3655 for (Long64_t i = 0; i < nentries; i++) {
3656 if (tree->LoadTree(i) < 0) {
3657 break;
3658 }
3659 if (treenumber != tree->GetTreeNumber()) {
3660 if ( withIndex ) {
3661 withIndex = R__HandleIndex( onIndexError, this, tree );
3662 }
3663 treenumber = tree->GetTreeNumber();
3664 }
3665 if (tree->GetEntry(i) <= 0) {
3666 break;
3667 }
3668 nbytes += this->Fill();
3669 }
3670 if (needCopyAddresses)
3671 tree->ResetBranchAddresses();
3672 if (this->GetTreeIndex()) {
3673 this->GetTreeIndex()->Append(0,kFALSE); // Force the sorting
3674 }
3675 }
3676 return nbytes;
3677}
3678
3679////////////////////////////////////////////////////////////////////////////////
3680/// Copy a tree with selection.
3681///
3682/// ### Important:
3683///
3684/// The returned copied tree stays connected with the original tree
3685/// until the original tree is deleted. In particular, any changes
3686/// to the branch addresses in the original tree are also made to
3687/// the copied tree. Any changes made to the branch addresses of the
3688/// copied tree are overridden anytime the original tree changes its
3689/// branch addresses. When the original tree is deleted, all the
3690/// branch addresses of the copied tree are set to zero.
3691///
3692/// For examples of CopyTree, see the tutorials:
3693///
3694/// - copytree.C:
3695/// Example macro to copy a subset of a tree to a new tree.
3696/// The input file was generated by running the program in
3697/// $ROOTSYS/test/Event in this way:
3698/// ~~~ {.cpp}
3699/// ./Event 1000 1 1 1
3700/// ~~~
3701/// - copytree2.C
3702/// Example macro to copy a subset of a tree to a new tree.
3703/// One branch of the new tree is written to a separate file.
3704/// The input file was generated by running the program in
3705/// $ROOTSYS/test/Event in this way:
3706/// ~~~ {.cpp}
3707/// ./Event 1000 1 1 1
3708/// ~~~
3709/// - copytree3.C
3710/// Example macro to copy a subset of a tree to a new tree.
3711/// Only selected entries are copied to the new tree.
3712/// NOTE that only the active branches are copied.
3714TTree* TTree::CopyTree(const char* selection, Option_t* option /* = 0 */, Long64_t nentries /* = TTree::kMaxEntries */, Long64_t firstentry /* = 0 */)
3715{
3716 GetPlayer();
3717 if (fPlayer) {
3718 return fPlayer->CopyTree(selection, option, nentries, firstentry);
3719 }
3720 return 0;
3721}
3722
3723////////////////////////////////////////////////////////////////////////////////
3724/// Create a basket for this tree and given branch.
3727{
3728 if (!branch) {
3729 return 0;
3730 }
3731 return new TBasket(branch->GetName(), GetName(), branch);
3732}
3733
3734////////////////////////////////////////////////////////////////////////////////
3735/// Delete this tree from memory or/and disk.
3736///
3737/// - if option == "all" delete Tree object from memory AND from disk
3738/// all baskets on disk are deleted. All keys with same name
3739/// are deleted.
3740/// - if option =="" only Tree object in memory is deleted.
3742void TTree::Delete(Option_t* option /* = "" */)
3743{
3745
3746 // delete all baskets and header from file
3747 if (file && option && !strcmp(option,"all")) {
3748 if (!file->IsWritable()) {
3749 Error("Delete","File : %s is not writable, cannot delete Tree:%s", file->GetName(),GetName());
3750 return;
3751 }
3752
3753 //find key and import Tree header in memory
3754 TKey *key = fDirectory->GetKey(GetName());
3755 if (!key) return;
3756
3757 TDirectory *dirsav = gDirectory;
3758 file->cd();
3759
3760 //get list of leaves and loop on all the branches baskets
3761 TIter next(GetListOfLeaves());
3762 TLeaf *leaf;
3763 char header[16];
3764 Int_t ntot = 0;
3765 Int_t nbask = 0;
3766 Int_t nbytes,objlen,keylen;
3767 while ((leaf = (TLeaf*)next())) {
3768 TBranch *branch = leaf->GetBranch();
3769 Int_t nbaskets = branch->GetMaxBaskets();
3770 for (Int_t i=0;i<nbaskets;i++) {
3771 Long64_t pos = branch->GetBasketSeek(i);
3772 if (!pos) continue;
3773 TFile *branchFile = branch->GetFile();
3774 if (!branchFile) continue;
3775 branchFile->GetRecordHeader(header,pos,16,nbytes,objlen,keylen);
3776 if (nbytes <= 0) continue;
3777 branchFile->MakeFree(pos,pos+nbytes-1);
3778 ntot += nbytes;
3779 nbask++;
3780 }
3781 }
3782
3783 // delete Tree header key and all keys with the same name
3784 // A Tree may have been saved many times. Previous cycles are invalid.
3785 while (key) {
3786 ntot += key->GetNbytes();
3787 key->Delete();
3788 delete key;
3789 key = fDirectory->GetKey(GetName());
3790 }
3791 if (dirsav) dirsav->cd();
3792 if (gDebug) Info("TTree::Delete", "Deleting Tree: %s: %d baskets deleted. Total space freed = %d bytes\n",GetName(),nbask,ntot);
3793 }
3794
3795 if (fDirectory) {
3796 fDirectory->Remove(this);
3797 //delete the file cache if it points to this Tree
3799 fDirectory = nullptr;
3801 }
3802
3803 // Delete object from CINT symbol table so it can not be used anymore.
3804 gCling->DeleteGlobal(this);
3805
3806 // Warning: We have intentional invalidated this object while inside a member function!
3807 delete this;
3808}
3809
3810 ///////////////////////////////////////////////////////////////////////////////
3811 /// Called by TKey and TObject::Clone to automatically add us to a directory
3812 /// when we are read from a file.
3815{
3816 if (fDirectory == dir) return;
3817 if (fDirectory) {
3818 fDirectory->Remove(this);
3819 // Delete or move the file cache if it points to this Tree
3821 MoveReadCache(file,dir);
3822 }
3823 fDirectory = dir;
3824 TBranch* b = 0;
3825 TIter next(GetListOfBranches());
3826 while((b = (TBranch*) next())) {
3827 b->UpdateFile();
3828 }
3829 if (fBranchRef) {
3831 }
3832 if (fDirectory) fDirectory->Append(this);
3833}
3834
3835////////////////////////////////////////////////////////////////////////////////
3836/// Draw expression varexp for specified entries.
3837///
3838/// \return -1 in case of error or number of selected events in case of success.
3839///
3840/// This function accepts TCut objects as arguments.
3841/// Useful to use the string operator +
3842///
3843/// Example:
3844///
3845/// ~~~ {.cpp}
3846/// ntuple.Draw("x",cut1+cut2+cut3);
3847/// ~~~
3848
3850Long64_t TTree::Draw(const char* varexp, const TCut& selection, Option_t* option, Long64_t nentries, Long64_t firstentry)
3851{
3852 return TTree::Draw(varexp, selection.GetTitle(), option, nentries, firstentry);
3853}
3854
3855/////////////////////////////////////////////////////////////////////////////////////////
3856/// \brief Draw expression varexp for entries and objects that pass a (optional) selection.
3857///
3858/// \return -1 in case of error or number of selected events in case of success.
3859///
3860/// \param [in] varexp
3861/// \parblock
3862/// A string that takes one of these general forms:
3863/// - "e1" produces a 1-d histogram (TH1F) of expression "e1"
3864/// - "e1:e2" produces an unbinned 2-d scatter-plot (TGraph) of "e1"
3865/// on the y-axis versus "e2" on the x-axis
3866/// - "e1:e2:e3" produces an unbinned 3-d scatter-plot (TPolyMarker3D) of "e1"
3867/// vs "e2" vs "e3" on the z-, y-, x-axis, respectively
3868/// - "e1:e2:e3:e4" produces an unbinned 3-d scatter-plot (TPolyMarker3D) of "e1"
3869/// vs "e2" vs "e3" and "e4" mapped on the current color palette.
3870/// (to create histograms in the 2, 3, and 4 dimensional case,
3871/// see section "Saving the result of Draw to an histogram")
3872///
3873/// Examples:
3874/// - "x": the simplest case, it draws a 1-Dim histogram of column x
3875/// - "sqrt(x)", "x*y/z": draw histogram with the values of the specified numerical expression across TTree events
3876/// - "y:sqrt(x)": 2-Dim histogram of y versus sqrt(x)
3877/// - "px:py:pz:2.5*E": produces a 3-d scatter-plot of px vs py ps pz
3878/// and the color number of each marker will be 2.5*E.
3879/// If the color number is negative it is set to 0.
3880/// If the color number is greater than the current number of colors
3881/// it is set to the highest color number. The default number of
3882/// colors is 50. See TStyle::SetPalette for setting a new color palette.
3883///
3884/// The expressions can use all the operations and built-in functions
3885/// supported by TFormula (see TFormula::Analyze()), including free
3886/// functions taking numerical arguments (e.g. TMath::Bessel()).
3887/// In addition, you can call member functions taking numerical
3888/// arguments. For example, these are two valid expressions:
3889/// ~~~ {.cpp}
3890/// TMath::BreitWigner(fPx,3,2)
3891/// event.GetHistogram()->GetXaxis()->GetXmax()
3892/// ~~~
3893/// \endparblock
3894/// \param [in] selection
3895/// \parblock
3896/// A string containing a selection expression.
3897/// In a selection all usual C++ mathematical and logical operators are allowed.
3898/// The value corresponding to the selection expression is used as a weight
3899/// to fill the histogram (a weight of 0 is equivalent to not filling the histogram).\n
3900/// \n
3901/// Examples:
3902/// - "x<y && sqrt(z)>3.2": returns a weight = 0 or 1
3903/// - "(x+y)*(sqrt(z)>3.2)": returns a weight = x+y if sqrt(z)>3.2, 0 otherwise\n
3904/// \n
3905/// If the selection expression returns an array, it is iterated over in sync with the
3906/// array returned by the varexp argument (as described below in "Drawing expressions using arrays and array
3907/// elements"). For example, if, for a given event, varexp evaluates to
3908/// `{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:
3909/// ~~~{.cpp}
3910/// // Muon_pt is an array: fill a histogram with the array elements > 100 in each event
3911/// tree->Draw('Muon_pt', 'Muon_pt > 100')
3912/// ~~~
3913/// \endparblock
3914/// \param [in] option
3915/// \parblock
3916/// The drawing option.
3917/// - When an histogram is produced it can be any histogram drawing option
3918/// listed in THistPainter.
3919/// - when no option is specified:
3920/// - the default histogram drawing option is used
3921/// if the expression is of the form "e1".
3922/// - if the expression is of the form "e1:e2"or "e1:e2:e3" a cloud of
3923/// unbinned 2D or 3D points is drawn respectively.
3924/// - if the expression has four fields "e1:e2:e3:e4" a cloud of unbinned 3D
3925/// points is produced with e1 vs e2 vs e3, and e4 is mapped on the current color
3926/// palette.
3927/// - If option COL is specified when varexp has three fields:
3928/// ~~~ {.cpp}
3929/// tree.Draw("e1:e2:e3","","col");
3930/// ~~~
3931/// a 2D scatter is produced with e1 vs e2, and e3 is mapped on the current
3932/// color palette. The colors for e3 are evaluated once in linear scale before
3933/// painting. Therefore changing the pad to log scale along Z as no effect
3934/// on the colors.
3935/// - if expression has more than four fields the option "PARA"or "CANDLE"
3936/// can be used.
3937/// - If option contains the string "goff", no graphics is generated.
3938/// \endparblock
3939/// \param [in] nentries The number of entries to process (default is all)
3940/// \param [in] firstentry The first entry to process (default is 0)
3941///
3942/// ### Drawing expressions using arrays and array elements
3943///
3944/// Let assumes, a leaf fMatrix, on the branch fEvent, which is a 3 by 3 array,
3945/// or a TClonesArray.
3946/// In a TTree::Draw expression you can now access fMatrix using the following
3947/// syntaxes:
3948///
3949/// | String passed | What is used for each entry of the tree
3950/// |-----------------|--------------------------------------------------------|
3951/// | `fMatrix` | the 9 elements of fMatrix |
3952/// | `fMatrix[][]` | the 9 elements of fMatrix |
3953/// | `fMatrix[2][2]` | only the elements fMatrix[2][2] |
3954/// | `fMatrix[1]` | the 3 elements fMatrix[1][0], fMatrix[1][1] and fMatrix[1][2] |
3955/// | `fMatrix[1][]` | the 3 elements fMatrix[1][0], fMatrix[1][1] and fMatrix[1][2] |
3956/// | `fMatrix[][0]` | the 3 elements fMatrix[0][0], fMatrix[1][0] and fMatrix[2][0] |
3957///
3958/// "fEvent.fMatrix...." same as "fMatrix..." (unless there is more than one leaf named fMatrix!).
3959///
3960/// In summary, if a specific index is not specified for a dimension, TTree::Draw
3961/// will loop through all the indices along this dimension. Leaving off the
3962/// last (right most) dimension of specifying then with the two characters '[]'
3963/// is equivalent. For variable size arrays (and TClonesArray) the range
3964/// of the first dimension is recalculated for each entry of the tree.
3965/// You can also specify the index as an expression of any other variables from the
3966/// tree.
3967///
3968/// TTree::Draw also now properly handling operations involving 2 or more arrays.
3969///
3970/// Let assume a second matrix fResults[5][2], here are a sample of some
3971/// of the possible combinations, the number of elements they produce and
3972/// the loop used:
3973///
3974/// | expression | element(s) | Loop |
3975/// |----------------------------------|------------|--------------------------|
3976/// | `fMatrix[2][1] - fResults[5][2]` | one | no loop |
3977/// | `fMatrix[2][] - fResults[5][2]` | three | on 2nd dim fMatrix |
3978/// | `fMatrix[2][] - fResults[5][]` | two | on both 2nd dimensions |
3979/// | `fMatrix[][2] - fResults[][1]` | three | on both 1st dimensions |
3980/// | `fMatrix[][2] - fResults[][]` | six | on both 1st and 2nd dimensions of fResults |
3981/// | `fMatrix[][2] - fResults[3][]` | two | on 1st dim of fMatrix and 2nd of fResults (at the same time) |
3982/// | `fMatrix[][] - fResults[][]` | six | on 1st dim then on 2nd dim |
3983/// | `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.|
3984///
3985///
3986/// In summary, TTree::Draw loops through all unspecified dimensions. To
3987/// figure out the range of each loop, we match each unspecified dimension
3988/// from left to right (ignoring ALL dimensions for which an index has been
3989/// specified), in the equivalent loop matched dimensions use the same index
3990/// and are restricted to the smallest range (of only the matched dimensions).
3991/// When involving variable arrays, the range can of course be different
3992/// for each entry of the tree.
3993///
3994/// So the loop equivalent to "fMatrix[][2] - fResults[3][]" is:
3995/// ~~~ {.cpp}
3996/// for (Int_t i0; i < min(3,2); i++) {
3997/// use the value of (fMatrix[i0][2] - fMatrix[3][i0])
3998/// }
3999/// ~~~
4000/// So the loop equivalent to "fMatrix[][2] - fResults[][]" is:
4001/// ~~~ {.cpp}
4002/// for (Int_t i0; i < min(3,5); i++) {
4003/// for (Int_t i1; i1 < 2; i1++) {
4004/// use the value of (fMatrix[i0][2] - fMatrix[i0][i1])
4005/// }
4006/// }
4007/// ~~~
4008/// So the loop equivalent to "fMatrix[][] - fResults[][]" is:
4009/// ~~~ {.cpp}
4010/// for (Int_t i0; i < min(3,5); i++) {
4011/// for (Int_t i1; i1 < min(3,2); i1++) {
4012/// use the value of (fMatrix[i0][i1] - fMatrix[i0][i1])
4013/// }
4014/// }
4015/// ~~~
4016/// So the loop equivalent to "fMatrix[][fResults[][]]" is:
4017/// ~~~ {.cpp}
4018/// for (Int_t i0; i0 < 3; i0++) {
4019/// for (Int_t j2; j2 < 5; j2++) {
4020/// for (Int_t j3; j3 < 2; j3++) {
4021/// i1 = fResults[j2][j3];
4022/// use the value of fMatrix[i0][i1]
4023/// }
4024/// }
4025/// ~~~
4026/// ### Retrieving the result of Draw
4027///
4028/// By default a temporary histogram called `htemp` is created. It will be:
4029///
4030/// - A TH1F* in case of a mono-dimensional distribution: `Draw("e1")`,
4031/// - A TH2F* in case of a bi-dimensional distribution: `Draw("e1:e2")`,
4032/// - A TH3F* in case of a three-dimensional distribution: `Draw("e1:e2:e3")`.
4033///
4034/// In the one dimensional case the `htemp` is filled and drawn whatever the drawing
4035/// option is.
4036///
4037/// In the two and three dimensional cases, with the default drawing option (`""`),
4038/// a cloud of points is drawn and the histogram `htemp` is not filled. For all the other
4039/// drawing options `htemp` will be filled.
4040///
4041/// In all cases `htemp` can be retrieved by calling:
4042///
4043/// ~~~ {.cpp}
4044/// auto htemp = (TH1F*)gPad->GetPrimitive("htemp"); // 1D
4045/// auto htemp = (TH2F*)gPad->GetPrimitive("htemp"); // 2D
4046/// auto htemp = (TH3F*)gPad->GetPrimitive("htemp"); // 3D
4047/// ~~~
4048///
4049/// In the two dimensional case (`Draw("e1;e2")`), with the default drawing option, the
4050/// data is filled into a TGraph named `Graph`. This TGraph can be retrieved by
4051/// calling
4052///
4053/// ~~~ {.cpp}
4054/// auto graph = (TGraph*)gPad->GetPrimitive("Graph");
4055/// ~~~
4056///
4057/// For the three and four dimensional cases, with the default drawing option, an unnamed
4058/// TPolyMarker3D is produced, and therefore cannot be retrieved.
4059///
4060/// In all cases `htemp` can be used to access the axes. For instance in the 2D case:
4061///
4062/// ~~~ {.cpp}
4063/// auto htemp = (TH2F*)gPad->GetPrimitive("htemp");
4064/// auto xaxis = htemp->GetXaxis();
4065/// ~~~
4066///
4067/// When the option `"A"` is used (with TGraph painting option) to draw a 2D
4068/// distribution:
4069/// ~~~ {.cpp}
4070/// tree.Draw("e1:e2","","A*");
4071/// ~~~
4072/// a scatter plot is produced (with stars in that case) but the axis creation is
4073/// delegated to TGraph and `htemp` is not created.
4074///
4075/// ### Saving the result of Draw to a histogram
4076///
4077/// If `varexp` contains `>>hnew` (following the variable(s) name(s)),
4078/// the new histogram called `hnew` is created and it is kept in the current
4079/// directory (and also the current pad). This works for all dimensions.
4080///
4081/// Example:
4082/// ~~~ {.cpp}
4083/// tree.Draw("sqrt(x)>>hsqrt","y>0")
4084/// ~~~
4085/// will draw `sqrt(x)` and save the histogram as "hsqrt" in the current
4086/// directory. To retrieve it do:
4087/// ~~~ {.cpp}
4088/// TH1F *hsqrt = (TH1F*)gDirectory->Get("hsqrt");
4089/// ~~~
4090/// The binning information is taken from the environment variables
4091/// ~~~ {.cpp}
4092/// Hist.Binning.?D.?
4093/// ~~~
4094/// In addition, the name of the histogram can be followed by up to 9
4095/// numbers between '(' and ')', where the numbers describe the
4096/// following:
4097///
4098/// - 1 - bins in x-direction
4099/// - 2 - lower limit in x-direction
4100/// - 3 - upper limit in x-direction
4101/// - 4-6 same for y-direction
4102/// - 7-9 same for z-direction
4103///
4104/// When a new binning is used the new value will become the default.
4105/// Values can be skipped.
4106///
4107/// Example:
4108/// ~~~ {.cpp}
4109/// tree.Draw("sqrt(x)>>hsqrt(500,10,20)")
4110/// // plot sqrt(x) between 10 and 20 using 500 bins
4111/// tree.Draw("sqrt(x):sin(y)>>hsqrt(100,10,60,50,.1,.5)")
4112/// // plot sqrt(x) against sin(y)
4113/// // 100 bins in x-direction; lower limit on x-axis is 10; upper limit is 60
4114/// // 50 bins in y-direction; lower limit on y-axis is .1; upper limit is .5
4115/// ~~~
4116/// By default, the specified histogram is reset.
4117/// To continue to append data to an existing histogram, use "+" in front
4118/// of the histogram name.
4119///
4120/// A '+' in front of the histogram name is ignored, when the name is followed by
4121/// binning information as described in the previous paragraph.
4122/// ~~~ {.cpp}
4123/// tree.Draw("sqrt(x)>>+hsqrt","y>0")
4124/// ~~~
4125/// will not reset `hsqrt`, but will continue filling. This works for 1-D, 2-D
4126/// and 3-D histograms.
4127///
4128/// ### Accessing collection objects
4129///
4130/// TTree::Draw default's handling of collections is to assume that any
4131/// request on a collection pertain to it content. For example, if fTracks
4132/// is a collection of Track objects, the following:
4133/// ~~~ {.cpp}
4134/// tree->Draw("event.fTracks.fPx");
4135/// ~~~
4136/// will plot the value of fPx for each Track objects inside the collection.
4137/// Also
4138/// ~~~ {.cpp}
4139/// tree->Draw("event.fTracks.size()");
4140/// ~~~
4141/// would plot the result of the member function Track::size() for each
4142/// Track object inside the collection.
4143/// To access information about the collection itself, TTree::Draw support
4144/// the '@' notation. If a variable which points to a collection is prefixed
4145/// or postfixed with '@', the next part of the expression will pertain to
4146/// the collection object. For example:
4147/// ~~~ {.cpp}
4148/// tree->Draw("event.@fTracks.size()");
4149/// ~~~
4150/// will plot the size of the collection referred to by `fTracks` (i.e the number
4151/// of Track objects).
4152///
4153/// ### Drawing 'objects'
4154///
4155/// When a class has a member function named AsDouble or AsString, requesting
4156/// to directly draw the object will imply a call to one of the 2 functions.
4157/// If both AsDouble and AsString are present, AsDouble will be used.
4158/// AsString can return either a char*, a std::string or a TString.s
4159/// For example, the following
4160/// ~~~ {.cpp}
4161/// tree->Draw("event.myTTimeStamp");
4162/// ~~~
4163/// will draw the same histogram as
4164/// ~~~ {.cpp}
4165/// tree->Draw("event.myTTimeStamp.AsDouble()");
4166/// ~~~
4167/// In addition, when the object is a type TString or std::string, TTree::Draw
4168/// will call respectively `TString::Data` and `std::string::c_str()`
4169///
4170/// If the object is a TBits, the histogram will contain the index of the bit
4171/// that are turned on.
4172///
4173/// ### Retrieving information about the tree itself.
4174///
4175/// You can refer to the tree (or chain) containing the data by using the
4176/// string 'This'.
4177/// You can then could any TTree methods. For example:
4178/// ~~~ {.cpp}
4179/// tree->Draw("This->GetReadEntry()");
4180/// ~~~
4181/// will display the local entry numbers be read.
4182/// ~~~ {.cpp}
4183/// tree->Draw("This->GetUserInfo()->At(0)->GetName()");
4184/// ~~~
4185/// will display the name of the first 'user info' object.
4186///
4187/// ### Special functions and variables
4188///
4189/// `Entry$`: A TTree::Draw formula can use the special variable `Entry$`
4190/// to access the entry number being read. For example to draw every
4191/// other entry use:
4192/// ~~~ {.cpp}
4193/// tree.Draw("myvar","Entry$%2==0");
4194/// ~~~
4195/// - `Entry$` : return the current entry number (`== TTree::GetReadEntry()`)
4196/// - `LocalEntry$` : return the current entry number in the current tree of a
4197/// chain (`== GetTree()->GetReadEntry()`)
4198/// - `Entries$` : return the total number of entries (== TTree::GetEntries())
4199/// - `LocalEntries$` : return the total number of entries in the current tree
4200/// of a chain (== GetTree()->TTree::GetEntries())
4201/// - `Length$` : return the total number of element of this formula for this
4202/// entry (`==TTreeFormula::GetNdata()`)
4203/// - `Iteration$` : return the current iteration over this formula for this
4204/// entry (i.e. varies from 0 to `Length$`).
4205/// - `Length$(formula )` : return the total number of element of the formula
4206/// given as a parameter.
4207/// - `Sum$(formula )` : return the sum of the value of the elements of the
4208/// formula given as a parameter. For example the mean for all the elements in
4209/// one entry can be calculated with: `Sum$(formula )/Length$(formula )`
4210/// - `Min$(formula )` : return the minimum (within one TTree entry) of the value of the
4211/// elements of the formula given as a parameter.
4212/// - `Max$(formula )` : return the maximum (within one TTree entry) of the value of the
4213/// elements of the formula given as a parameter.
4214/// - `MinIf$(formula,condition)`
4215/// - `MaxIf$(formula,condition)` : return the minimum (maximum) (within one TTree entry)
4216/// of the value of the elements of the formula given as a parameter
4217/// if they match the condition. If no element matches the condition,
4218/// the result is zero. To avoid the resulting peak at zero, use the
4219/// pattern:
4220/// ~~~ {.cpp}
4221/// tree->Draw("MinIf$(formula,condition)","condition");
4222/// ~~~
4223/// which will avoid calculation `MinIf$` for the entries that have no match
4224/// for the condition.
4225/// - `Alt$(primary,alternate)` : return the value of "primary" if it is available
4226/// for the current iteration otherwise return the value of "alternate".
4227/// For example, with arr1[3] and arr2[2]
4228/// ~~~ {.cpp}
4229/// tree->Draw("arr1+Alt$(arr2,0)");
4230/// ~~~
4231/// will draw arr1[0]+arr2[0] ; arr1[1]+arr2[1] and arr1[2]+0
4232/// Or with a variable size array arr3
4233/// ~~~ {.cpp}
4234/// tree->Draw("Alt$(arr3[0],0)+Alt$(arr3[1],0)+Alt$(arr3[2],0)");
4235/// ~~~
4236/// will draw the sum arr3 for the index 0 to min(2,actual_size_of_arr3-1)
4237/// As a comparison
4238/// ~~~ {.cpp}
4239/// tree->Draw("arr3[0]+arr3[1]+arr3[2]");
4240/// ~~~
4241/// will draw the sum arr3 for the index 0 to 2 only if the
4242/// actual_size_of_arr3 is greater or equal to 3.
4243/// Note that the array in 'primary' is flattened/linearized thus using
4244/// `Alt$` with multi-dimensional arrays of different dimensions in unlikely
4245/// to yield the expected results. To visualize a bit more what elements
4246/// would be matched by TTree::Draw, TTree::Scan can be used:
4247/// ~~~ {.cpp}
4248/// tree->Scan("arr1:Alt$(arr2,0)");
4249/// ~~~
4250/// will print on one line the value of arr1 and (arr2,0) that will be
4251/// matched by
4252/// ~~~ {.cpp}
4253/// tree->Draw("arr1-Alt$(arr2,0)");
4254/// ~~~
4255/// The ternary operator is not directly supported in TTree::Draw however, to plot the
4256/// equivalent of `var2<20 ? -99 : var1`, you can use:
4257/// ~~~ {.cpp}
4258/// tree->Draw("(var2<20)*99+(var2>=20)*var1","");
4259/// ~~~
4260///
4261/// ### Drawing a user function accessing the TTree data directly
4262///
4263/// If the formula contains a file name, TTree::MakeProxy will be used
4264/// to load and execute this file. In particular it will draw the
4265/// result of a function with the same name as the file. The function
4266/// will be executed in a context where the name of the branches can
4267/// be used as a C++ variable.
4268///
4269/// For example draw px using the file hsimple.root (generated by the
4270/// hsimple.C tutorial), we need a file named hsimple.cxx:
4271/// ~~~ {.cpp}
4272/// double hsimple() {
4273/// return px;
4274/// }
4275/// ~~~
4276/// MakeProxy can then be used indirectly via the TTree::Draw interface
4277/// as follow:
4278/// ~~~ {.cpp}
4279/// new TFile("hsimple.root")
4280/// ntuple->Draw("hsimple.cxx");
4281/// ~~~
4282/// A more complete example is available in the tutorials directory:
4283/// `h1analysisProxy.cxx`, `h1analysProxy.h` and `h1analysisProxyCut.C`
4284/// which reimplement the selector found in `h1analysis.C`
4285///
4286/// The main features of this facility are:
4287///
4288/// * on-demand loading of branches
4289/// * ability to use the 'branchname' as if it was a data member
4290/// * protection against array out-of-bound
4291/// * ability to use the branch data as object (when the user code is available)
4292///
4293/// See TTree::MakeProxy for more details.
4294///
4295/// ### Making a Profile histogram
4296///
4297/// In case of a 2-Dim expression, one can generate a TProfile histogram
4298/// instead of a TH2F histogram by specifying option=prof or option=profs
4299/// or option=profi or option=profg ; the trailing letter select the way
4300/// the bin error are computed, See TProfile2D::SetErrorOption for
4301/// details on the differences.
4302/// The option=prof is automatically selected in case of y:x>>pf
4303/// where pf is an existing TProfile histogram.
4304///
4305/// ### Making a 2D Profile histogram
4306///
4307/// In case of a 3-Dim expression, one can generate a TProfile2D histogram
4308/// instead of a TH3F histogram by specifying option=prof or option=profs.
4309/// or option=profi or option=profg ; the trailing letter select the way
4310/// the bin error are computed, See TProfile2D::SetErrorOption for
4311/// details on the differences.
4312/// The option=prof is automatically selected in case of z:y:x>>pf
4313/// where pf is an existing TProfile2D histogram.
4314///
4315/// ### Making a 5D plot using GL
4316///
4317/// If option GL5D is specified together with 5 variables, a 5D plot is drawn
4318/// using OpenGL. See $ROOTSYS/tutorials/tree/staff.C as example.
4319///
4320/// ### Making a parallel coordinates plot
4321///
4322/// In case of a 2-Dim or more expression with the option=para, one can generate
4323/// a parallel coordinates plot. With that option, the number of dimensions is
4324/// arbitrary. Giving more than 4 variables without the option=para or
4325/// option=candle or option=goff will produce an error.
4326///
4327/// ### Making a candle sticks chart
4328///
4329/// In case of a 2-Dim or more expression with the option=candle, one can generate
4330/// a candle sticks chart. With that option, the number of dimensions is
4331/// arbitrary. Giving more than 4 variables without the option=para or
4332/// option=candle or option=goff will produce an error.
4333///
4334/// ### Normalizing the output histogram to 1
4335///
4336/// When option contains "norm" the output histogram is normalized to 1.
4337///
4338/// ### Saving the result of Draw to a TEventList, a TEntryList or a TEntryListArray
4339///
4340/// TTree::Draw can be used to fill a TEventList object (list of entry numbers)
4341/// instead of histogramming one variable.
4342/// If varexp0 has the form >>elist , a TEventList object named "elist"
4343/// is created in the current directory. elist will contain the list
4344/// of entry numbers satisfying the current selection.
4345/// If option "entrylist" is used, a TEntryList object is created
4346/// If the selection contains arrays, vectors or any container class and option
4347/// "entrylistarray" is used, a TEntryListArray object is created
4348/// containing also the subentries satisfying the selection, i.e. the indices of
4349/// the branches which hold containers classes.
4350/// Example:
4351/// ~~~ {.cpp}
4352/// tree.Draw(">>yplus","y>0")
4353/// ~~~
4354/// will create a TEventList object named "yplus" in the current directory.
4355/// In an interactive session, one can type (after TTree::Draw)
4356/// ~~~ {.cpp}
4357/// yplus.Print("all")
4358/// ~~~
4359/// to print the list of entry numbers in the list.
4360/// ~~~ {.cpp}
4361/// tree.Draw(">>yplus", "y>0", "entrylist")
4362/// ~~~
4363/// will create a TEntryList object names "yplus" in the current directory
4364/// ~~~ {.cpp}
4365/// tree.Draw(">>yplus", "y>0", "entrylistarray")
4366/// ~~~
4367/// will create a TEntryListArray object names "yplus" in the current directory
4368///
4369/// By default, the specified entry list is reset.
4370/// To continue to append data to an existing list, use "+" in front
4371/// of the list name;
4372/// ~~~ {.cpp}
4373/// tree.Draw(">>+yplus","y>0")
4374/// ~~~
4375/// will not reset yplus, but will enter the selected entries at the end
4376/// of the existing list.
4377///
4378/// ### Using a TEventList, TEntryList or TEntryListArray as Input
4379///
4380/// Once a TEventList or a TEntryList object has been generated, it can be used as input
4381/// for TTree::Draw. Use TTree::SetEventList or TTree::SetEntryList to set the
4382/// current event list
4383///
4384/// Example 1:
4385/// ~~~ {.cpp}
4386/// TEventList *elist = (TEventList*)gDirectory->Get("yplus");
4387/// tree->SetEventList(elist);
4388/// tree->Draw("py");
4389/// ~~~
4390/// Example 2:
4391/// ~~~ {.cpp}
4392/// TEntryList *elist = (TEntryList*)gDirectory->Get("yplus");
4393/// tree->SetEntryList(elist);
4394/// tree->Draw("py");
4395/// ~~~
4396/// If a TEventList object is used as input, a new TEntryList object is created
4397/// inside the SetEventList function. In case of a TChain, all tree headers are loaded
4398/// for this transformation. This new object is owned by the chain and is deleted
4399/// with it, unless the user extracts it by calling GetEntryList() function.
4400/// See also comments to SetEventList() function of TTree and TChain.
4401///
4402/// If arrays are used in the selection criteria and TEntryListArray is not used,
4403/// all the entries that have at least one element of the array that satisfy the selection
4404/// are entered in the list.
4405///
4406/// Example:
4407/// ~~~ {.cpp}
4408/// tree.Draw(">>pyplus","fTracks.fPy>0");
4409/// tree->SetEventList(pyplus);
4410/// tree->Draw("fTracks.fPy");
4411/// ~~~
4412/// will draw the fPy of ALL tracks in event with at least one track with
4413/// a positive fPy.
4414///
4415/// To select only the elements that did match the original selection
4416/// use TEventList::SetReapplyCut or TEntryList::SetReapplyCut.
4417///
4418/// Example:
4419/// ~~~ {.cpp}
4420/// tree.Draw(">>pyplus","fTracks.fPy>0");
4421/// pyplus->SetReapplyCut(kTRUE);
4422/// tree->SetEventList(pyplus);
4423/// tree->Draw("fTracks.fPy");
4424/// ~~~
4425/// will draw the fPy of only the tracks that have a positive fPy.
4426///
4427/// To draw only the elements that match a selection in case of arrays,
4428/// you can also use TEntryListArray (faster in case of a more general selection).
4429///
4430/// Example:
4431/// ~~~ {.cpp}
4432/// tree.Draw(">>pyplus","fTracks.fPy>0", "entrylistarray");
4433/// tree->SetEntryList(pyplus);
4434/// tree->Draw("fTracks.fPy");
4435/// ~~~
4436/// will draw the fPy of only the tracks that have a positive fPy,
4437/// but without redoing the selection.
4438///
4439/// Note: Use tree->SetEventList(0) if you do not want use the list as input.
4440///
4441/// ### How to obtain more info from TTree::Draw
4442///
4443/// Once TTree::Draw has been called, it is possible to access useful
4444/// information still stored in the TTree object via the following functions:
4445///
4446/// - GetSelectedRows() // return the number of values accepted by the selection expression. In case where no selection was specified, returns the number of values processed.
4447/// - GetV1() // returns a pointer to the double array of V1
4448/// - GetV2() // returns a pointer to the double array of V2
4449/// - GetV3() // returns a pointer to the double array of V3
4450/// - GetV4() // returns a pointer to the double array of V4
4451/// - GetW() // returns a pointer to the double array of Weights where weight equal the result of the selection expression.
4452///
4453/// where V1,V2,V3 correspond to the expressions in
4454/// ~~~ {.cpp}
4455/// TTree::Draw("V1:V2:V3:V4",selection);
4456/// ~~~
4457/// If the expression has more than 4 component use GetVal(index)
4458///
4459/// Example:
4460/// ~~~ {.cpp}
4461/// Root > ntuple->Draw("py:px","pz>4");
4462/// Root > TGraph *gr = new TGraph(ntuple->GetSelectedRows(),
4463/// ntuple->GetV2(), ntuple->GetV1());
4464/// Root > gr->Draw("ap"); //draw graph in current pad
4465/// ~~~
4466///
4467/// A more complete complete tutorial (treegetval.C) shows how to use the
4468/// GetVal() method.
4469///
4470/// creates a TGraph object with a number of points corresponding to the
4471/// number of entries selected by the expression "pz>4", the x points of the graph
4472/// being the px values of the Tree and the y points the py values.
4473///
4474/// Important note: By default TTree::Draw creates the arrays obtained
4475/// with GetW, GetV1, GetV2, GetV3, GetV4, GetVal with a length corresponding
4476/// to the parameter fEstimate. The content will be the last `GetSelectedRows() % GetEstimate()`
4477/// values calculated.
4478/// By default fEstimate=1000000 and can be modified
4479/// via TTree::SetEstimate. To keep in memory all the results (in case
4480/// where there is only one result per entry), use
4481/// ~~~ {.cpp}
4482/// tree->SetEstimate(tree->GetEntries()+1); // same as tree->SetEstimate(-1);
4483/// ~~~
4484/// You must call SetEstimate if the expected number of selected rows
4485/// you need to look at is greater than 1000000.
4486///
4487/// You can use the option "goff" to turn off the graphics output
4488/// of TTree::Draw in the above example.
4489///
4490/// ### Automatic interface to TTree::Draw via the TTreeViewer
4491///
4492/// A complete graphical interface to this function is implemented
4493/// in the class TTreeViewer.
4494/// To start the TTreeViewer, three possibilities:
4495/// - select TTree context menu item "StartViewer"
4496/// - type the command "TTreeViewer TV(treeName)"
4497/// - execute statement "tree->StartViewer();"
4499Long64_t TTree::Draw(const char* varexp, const char* selection, Option_t* option, Long64_t nentries, Long64_t firstentry)
4500{
4501 GetPlayer();
4502 if (fPlayer)
4503 return fPlayer->DrawSelect(varexp,selection,option,nentries,firstentry);
4504 return -1;
4505}
4506
4507////////////////////////////////////////////////////////////////////////////////
4508/// Remove some baskets from memory.
4510void TTree::DropBaskets()
4511{
4512 TBranch* branch = 0;
4514 for (Int_t i = 0; i < nb; ++i) {
4515 branch = (TBranch*) fBranches.UncheckedAt(i);
4516 branch->DropBaskets("all");
4517 }
4518}
4519
4520////////////////////////////////////////////////////////////////////////////////
4521/// Drop branch buffers to accommodate nbytes below MaxVirtualsize.
4524{
4525 // Be careful not to remove current read/write buffers.
4526 Int_t nleaves = fLeaves.GetEntriesFast();
4527 for (Int_t i = 0; i < nleaves; ++i) {
4528 TLeaf* leaf = (TLeaf*) fLeaves.UncheckedAt(i);
4529 TBranch* branch = (TBranch*) leaf->GetBranch();
4530 Int_t nbaskets = branch->GetListOfBaskets()->GetEntries();
4531 for (Int_t j = 0; j < nbaskets - 1; ++j) {
4532 if ((j == branch->GetReadBasket()) || (j == branch->GetWriteBasket())) {
4533 continue;
4534 }
4535 TBasket* basket = (TBasket*)branch->GetListOfBaskets()->UncheckedAt(j);
4536 if (basket) {
4537 basket->DropBuffers();
4539 return;
4540 }
4541 }
4542 }
4543 }
4544}
4545
4546////////////////////////////////////////////////////////////////////////////////
4547/// Fill all branches.
4548///
4549/// This function loops on all the branches of this tree. For
4550/// each branch, it copies to the branch buffer (basket) the current
4551/// values of the leaves data types. If a leaf is a simple data type,
4552/// a simple conversion to a machine independent format has to be done.
4553///
4554/// This machine independent version of the data is copied into a
4555/// basket (each branch has its own basket). When a basket is full
4556/// (32k worth of data by default), it is then optionally compressed
4557/// and written to disk (this operation is also called committing or
4558/// 'flushing' the basket). The committed baskets are then
4559/// immediately removed from memory.
4560///
4561/// The function returns the number of bytes committed to the
4562/// individual branches.
4563///
4564/// If a write error occurs, the number of bytes returned is -1.
4565///
4566/// If no data are written, because, e.g., the branch is disabled,
4567/// the number of bytes returned is 0.
4568///
4569/// __The baskets are flushed and the Tree header saved at regular intervals__
4570///
4571/// At regular intervals, when the amount of data written so far is
4572/// greater than fAutoFlush (see SetAutoFlush) all the baskets are flushed to disk.
4573/// This makes future reading faster as it guarantees that baskets belonging to nearby
4574/// entries will be on the same disk region.
4575/// When the first call to flush the baskets happen, we also take this opportunity
4576/// to optimize the baskets buffers.
4577/// We also check if the amount of data written is greater than fAutoSave (see SetAutoSave).
4578/// In this case we also write the Tree header. This makes the Tree recoverable up to this point
4579/// in case the program writing the Tree crashes.
4580/// The decisions to FlushBaskets and Auto Save can be made based either on the number
4581/// of bytes written (fAutoFlush and fAutoSave negative) or on the number of entries
4582/// written (fAutoFlush and fAutoSave positive).
4583/// Note that the user can decide to call FlushBaskets and AutoSave in her event loop
4584/// base on the number of events written instead of the number of bytes written.
4585///
4586/// \note Calling `TTree::FlushBaskets` too often increases the IO time.
4587///
4588/// \note Calling `TTree::AutoSave` too often increases the IO time and also the
4589/// file size.
4590///
4591/// \note This method calls `TTree::ChangeFile` when the tree reaches a size
4592/// greater than `TTree::fgMaxTreeSize`. This doesn't happen if the tree is
4593/// attached to a `TMemFile` or derivate.
4596{
4597 Int_t nbytes = 0;
4598 Int_t nwrite = 0;
4599 Int_t nerror = 0;
4600 Int_t nbranches = fBranches.GetEntriesFast();
4601
4602 // Case of one single super branch. Automatically update
4603 // all the branch addresses if a new object was created.
4604 if (nbranches == 1)
4605 ((TBranch *)fBranches.UncheckedAt(0))->UpdateAddress();
4606
4607 if (fBranchRef)
4608 fBranchRef->Clear();
4609
4610#ifdef R__USE_IMT
4611 const auto useIMT = ROOT::IsImplicitMTEnabled() && fIMTEnabled;
4613 if (useIMT) {
4614 fIMTFlush = true;
4615 fIMTZipBytes.store(0);
4616 fIMTTotBytes.store(0);
4617 }
4618#endif
4619
4620 for (Int_t i = 0; i < nbranches; ++i) {
4621 // Loop over all branches, filling and accumulating bytes written and error counts.
4622 TBranch *branch = (TBranch *)fBranches.UncheckedAt(i);
4623
4624 if (branch->TestBit(kDoNotProcess))
4625 continue;
4626
4627#ifndef R__USE_IMT
4628 nwrite = branch->FillImpl(nullptr);
4629#else
4630 nwrite = branch->FillImpl(useIMT ? &imtHelper : nullptr);
4631#endif
4632 if (nwrite < 0) {
4633 if (nerror < 2) {
4634 Error("Fill", "Failed filling branch:%s.%s, nbytes=%d, entry=%lld\n"
4635 " This error is symptomatic of a Tree created as a memory-resident Tree\n"
4636 " Instead of doing:\n"
4637 " TTree *T = new TTree(...)\n"
4638 " TFile *f = new TFile(...)\n"
4639 " you should do:\n"
4640 " TFile *f = new TFile(...)\n"
4641 " TTree *T = new TTree(...)\n\n",
4642 GetName(), branch->GetName(), nwrite, fEntries + 1);
4643 } else {
4644 Error("Fill", "Failed filling branch:%s.%s, nbytes=%d, entry=%lld", GetName(), branch->GetName(), nwrite,
4645 fEntries + 1);
4646 }
4647 ++nerror;
4648 } else {
4649 nbytes += nwrite;
4650 }
4651 }
4652
4653#ifdef R__USE_IMT
4654 if (fIMTFlush) {
4655 imtHelper.Wait();
4656 fIMTFlush = false;
4657 const_cast<TTree *>(this)->AddTotBytes(fIMTTotBytes);
4658 const_cast<TTree *>(this)->AddZipBytes(fIMTZipBytes);
4659 nbytes += imtHelper.GetNbytes();
4660 nerror += imtHelper.GetNerrors();
4661 }
4662#endif
4663
4664 if (fBranchRef)
4665 fBranchRef->Fill();
4666
4667 ++fEntries;
4668
4669 if (fEntries > fMaxEntries)
4670 KeepCircular();
4671
4672 if (gDebug > 0)
4673 Info("TTree::Fill", " - A: %d %lld %lld %lld %lld %lld %lld \n", nbytes, fEntries, fAutoFlush, fAutoSave,
4675
4676 bool autoFlush = false;
4677 bool autoSave = false;
4678
4679 if (fAutoFlush != 0 || fAutoSave != 0) {
4680 // Is it time to flush or autosave baskets?
4681 if (fFlushedBytes == 0) {
4682 // If fFlushedBytes == 0, it means we never flushed or saved, so
4683 // we need to check if it's time to do it and recompute the values
4684 // of fAutoFlush and fAutoSave in terms of the number of entries.
4685 // Decision can be based initially either on the number of bytes
4686 // or the number of entries written.
4687 Long64_t zipBytes = GetZipBytes();
4688
4689 if (fAutoFlush)
4690 autoFlush = fAutoFlush < 0 ? (zipBytes > -fAutoFlush) : fEntries % fAutoFlush == 0;
4691
4692 if (fAutoSave)
4693 autoSave = fAutoSave < 0 ? (zipBytes > -fAutoSave) : fEntries % fAutoSave == 0;
4694
4695 if (autoFlush || autoSave) {
4696 // First call FlushBasket to make sure that fTotBytes is up to date.
4698 autoFlush = false; // avoid auto flushing again later
4699
4700 // When we are in one-basket-per-cluster mode, there is no need to optimize basket:
4701 // they will automatically grow to the size needed for an event cluster (with the basket
4702 // shrinking preventing them from growing too much larger than the actually-used space).
4704 OptimizeBaskets(GetTotBytes(), 1, "");
4705 if (gDebug > 0)
4706 Info("TTree::Fill", "OptimizeBaskets called at entry %lld, fZipBytes=%lld, fFlushedBytes=%lld\n",
4708 }
4710 fAutoFlush = fEntries; // Use test on entries rather than bytes
4711
4712 // subsequently in run
4713 if (fAutoSave < 0) {
4714 // Set fAutoSave to the largest integer multiple of
4715 // fAutoFlush events such that fAutoSave*fFlushedBytes
4716 // < (minus the input value of fAutoSave)
4717 Long64_t totBytes = GetTotBytes();
4718 if (zipBytes != 0) {
4719 fAutoSave = TMath::Max(fAutoFlush, fEntries * ((-fAutoSave / zipBytes) / fEntries));
4720 } else if (totBytes != 0) {
4721 fAutoSave = TMath::Max(fAutoFlush, fEntries * ((-fAutoSave / totBytes) / fEntries));
4722 } else {
4724 TTree::Class()->WriteBuffer(b, (TTree *)this);
4725 Long64_t total = b.Length();
4727 }
4728 } else if (fAutoSave > 0) {
4730 }
4731
4732 if (fAutoSave != 0 && fEntries >= fAutoSave)
4733 autoSave = true;
4734
4735 if (gDebug > 0)
4736 Info("TTree::Fill", "First AutoFlush. fAutoFlush = %lld, fAutoSave = %lld\n", fAutoFlush, fAutoSave);
4737 }
4738 } else {
4739 // Check if we need to auto flush
4740 if (fAutoFlush) {
4741 if (fNClusterRange == 0)
4742 autoFlush = fEntries > 1 && fEntries % fAutoFlush == 0;
4743 else
4744 autoFlush = (fEntries - (fClusterRangeEnd[fNClusterRange - 1] + 1)) % fAutoFlush == 0;
4745 }
4746 // Check if we need to auto save
4747 if (fAutoSave)
4748 autoSave = fEntries % fAutoSave == 0;
4749 }
4750 }
4751
4752 if (autoFlush) {
4754 if (gDebug > 0)
4755 Info("TTree::Fill", "FlushBaskets() called at entry %lld, fZipBytes=%lld, fFlushedBytes=%lld\n", fEntries,
4758 }
4759
4760 if (autoSave) {
4761 AutoSave(); // does not call FlushBasketsImpl() again
4762 if (gDebug > 0)
4763 Info("TTree::Fill", "AutoSave called at entry %lld, fZipBytes=%lld, fSavedBytes=%lld\n", fEntries,
4765 }
4766
4767 // Check that output file is still below the maximum size.
4768 // If above, close the current file and continue on a new file.
4769 // Currently, the automatic change of file is restricted
4770 // to the case where the tree is in the top level directory.
4771 if (fDirectory)
4772 if (TFile *file = fDirectory->GetFile())
4773 if (static_cast<TDirectory *>(file) == fDirectory && (file->GetEND() > fgMaxTreeSize))
4774 // Changing file clashes with the design of TMemFile and derivates, see #6523.
4775 if (!(dynamic_cast<TMemFile *>(file)))
4777
4778 return nerror == 0 ? nbytes : -1;
4779}
4780
4781////////////////////////////////////////////////////////////////////////////////
4782/// Search in the array for a branch matching the branch name,
4783/// with the branch possibly expressed as a 'full' path name (with dots).
4785static TBranch *R__FindBranchHelper(TObjArray *list, const char *branchname) {
4786 if (list==0 || branchname == 0 || branchname[0] == '\0') return 0;
4787
4788 Int_t nbranches = list->GetEntries();
4789
4790 UInt_t brlen = strlen(branchname);
4791
4792 for(Int_t index = 0; index < nbranches; ++index) {
4793 TBranch *where = (TBranch*)list->UncheckedAt(index);
4794
4795 const char *name = where->GetName();
4796 UInt_t len = strlen(name);
4797 if (len && name[len-1]==']') {
4798 const char *dim = strchr(name,'[');
4799 if (dim) {
4800 len = dim - name;
4801 }
4802 }
4803 if (brlen == len && strncmp(branchname,name,len)==0) {
4804 return where;
4805 }
4806 TBranch *next = 0;
4807 if ((brlen >= len) && (branchname[len] == '.')
4808 && strncmp(name, branchname, len) == 0) {
4809 // The prefix subbranch name match the branch name.
4810
4811 next = where->FindBranch(branchname);
4812 if (!next) {
4813 next = where->FindBranch(branchname+len+1);
4814 }
4815 if (next) return next;
4816 }
4817 const char *dot = strchr((char*)branchname,'.');
4818 if (dot) {
4819 if (len==(size_t)(dot-branchname) &&
4820 strncmp(branchname,name,dot-branchname)==0 ) {
4821 return R__FindBranchHelper(where->GetListOfBranches(),dot+1);
4822 }
4823 }
4824 }
4825 return 0;
4826}
4827
4828////////////////////////////////////////////////////////////////////////////////
4829/// Return the branch that correspond to the path 'branchname', which can
4830/// include the name of the tree or the omitted name of the parent branches.
4831/// In case of ambiguity, returns the first match.
4833TBranch* TTree::FindBranch(const char* branchname)
4834{
4835 // We already have been visited while recursively looking
4836 // through the friends tree, let return
4838 return nullptr;
4839 }
4840
4841 if (!branchname)
4842 return nullptr;
4843
4844 TBranch* branch = nullptr;
4845 // If the first part of the name match the TTree name, look for the right part in the
4846 // list of branches.
4847 // This will allow the branchname to be preceded by
4848 // the name of this tree.
4849 if (strncmp(fName.Data(),branchname,fName.Length())==0 && branchname[fName.Length()]=='.') {
4850 branch = R__FindBranchHelper( GetListOfBranches(), branchname + fName.Length() + 1);
4851 if (branch) return branch;
4852 }
4853 // If we did not find it, let's try to find the full name in the list of branches.
4854 branch = R__FindBranchHelper(GetListOfBranches(), branchname);
4855 if (branch) return branch;
4856
4857 // If we still did not find, let's try to find it within each branch assuming it does not the branch name.
4858 TIter next(GetListOfBranches());
4859 while ((branch = (TBranch*) next())) {
4860 TBranch* nestedbranch = branch->FindBranch(branchname);
4861 if (nestedbranch) {
4862 return nestedbranch;
4863 }
4864 }
4865
4866 // Search in list of friends.
4867 if (!fFriends) {
4868 return nullptr;
4869 }
4870 TFriendLock lock(this, kFindBranch);
4871 TIter nextf(fFriends);
4872 TFriendElement* fe = nullptr;
4873 while ((fe = (TFriendElement*) nextf())) {
4874 TTree* t = fe->GetTree();
4875 if (!t) {
4876 continue;
4877 }
4878 // If the alias is present replace it with the real name.
4879 const char *subbranch = strstr(branchname, fe->GetName());
4880 if (subbranch != branchname) {
4881 subbranch = nullptr;
4882 }
4883 if (subbranch) {
4884 subbranch += strlen(fe->GetName());
4885 if (*subbranch != '.') {
4886 subbranch = nullptr;
4887 } else {
4888 ++subbranch;
4889 }
4890 }
4891 std::ostringstream name;
4892 if (subbranch) {
4893 name << t->GetName() << "." << subbranch;
4894 } else {
4895 name << branchname;
4896 }
4897 branch = t->FindBranch(name.str().c_str());
4898 if (branch) {
4899 return branch;
4900 }
4901 }
4902 return nullptr;
4903}
4904
4905////////////////////////////////////////////////////////////////////////////////
4906/// Find leaf..
4908TLeaf* TTree::FindLeaf(const char* searchname)
4909{
4910 if (!searchname)
4911 return nullptr;
4912
4913 // We already have been visited while recursively looking
4914 // through the friends tree, let's return.
4916 return nullptr;
4917 }
4918
4919 // This will allow the branchname to be preceded by
4920 // the name of this tree.
4921 const char* subsearchname = strstr(searchname, GetName());
4922 if (subsearchname != searchname) {
4923 subsearchname = nullptr;
4924 }
4925 if (subsearchname) {
4926 subsearchname += strlen(GetName());
4927 if (*subsearchname != '.') {
4928 subsearchname = nullptr;
4929 } else {
4930 ++subsearchname;
4931 if (subsearchname[0] == 0) {
4932 subsearchname = nullptr;
4933 }
4934 }
4935 }
4936
4937 TString leafname;
4938 TString leaftitle;
4939 TString longname;
4940 TString longtitle;
4941
4942 const bool searchnameHasDot = strchr(searchname, '.') != nullptr;
4943
4944 // For leaves we allow for one level up to be prefixed to the name.
4945 TIter next(GetListOfLeaves());
4946 TLeaf* leaf = nullptr;
4947 while ((leaf = (TLeaf*) next())) {
4948 leafname = leaf->GetName();
4949 Ssiz_t dim = leafname.First('[');
4950 if (dim >= 0) leafname.Remove(dim);
4951
4952 if (leafname == searchname) {
4953 return leaf;
4954 }
4955 if (subsearchname && leafname == subsearchname) {
4956 return leaf;
4957 }
4958 // The TLeafElement contains the branch name
4959 // in its name, let's use the title.
4960 leaftitle = leaf->GetTitle();
4961 dim = leaftitle.First('[');
4962 if (dim >= 0) leaftitle.Remove(dim);
4963
4964 if (leaftitle == searchname) {
4965 return leaf;
4966 }
4967 if (subsearchname && leaftitle == subsearchname) {
4968 return leaf;
4969 }
4970 if (!searchnameHasDot)
4971 continue;
4972 TBranch* branch = leaf->GetBranch();
4973 if (branch) {
4974 longname.Form("%s.%s",branch->GetName(),leafname.Data());
4975 dim = longname.First('[');
4976 if (dim>=0) longname.Remove(dim);
4977 if (longname == searchname) {
4978 return leaf;
4979 }
4980 if (subsearchname && longname == subsearchname) {
4981 return leaf;
4982 }
4983 longtitle.Form("%s.%s",branch->GetName(),leaftitle.Data());
4984 dim = longtitle.First('[');
4985 if (dim>=0) longtitle.Remove(dim);
4986 if (longtitle == searchname) {
4987 return leaf;
4988 }
4989 if (subsearchname && longtitle == subsearchname) {
4990 return leaf;
4991 }
4992 // The following is for the case where the branch is only
4993 // a sub-branch. Since we do not see it through
4994 // TTree::GetListOfBranches, we need to see it indirectly.
4995 // This is the less sturdy part of this search ... it may
4996 // need refining ...
4997 if (strstr(searchname, ".") && !strcmp(searchname, branch->GetName())) {
4998 return leaf;
4999 }
5000 if (subsearchname && strstr(subsearchname, ".") && !strcmp(subsearchname, branch->GetName())) {
5001 return leaf;
5002 }
5003 }
5004 }
5005 // Search in list of friends.
5006 if (!fFriends) {
5007 return nullptr;
5008 }
5009 TFriendLock lock(this, kFindLeaf);
5010 TIter nextf(fFriends);
5011 TFriendElement* fe = nullptr;
5012 while ((fe = (TFriendElement*) nextf())) {
5013 TTree* t = fe->GetTree();
5014 if (!t) {
5015 continue;
5016 }
5017 // If the alias is present replace it with the real name.
5018 subsearchname = strstr(searchname, fe->GetName());
5019 if (subsearchname != searchname) {
5020 subsearchname = nullptr;
5021 }
5022 if (subsearchname) {
5023 subsearchname += strlen(fe->GetName());
5024 if (*subsearchname != '.') {
5025 subsearchname = nullptr;
5026 } else {
5027 ++subsearchname;
5028 }
5029 }
5030 if (subsearchname) {
5031 leafname.Form("%s.%s",t->GetName(),subsearchname);
5032 } else {
5033 leafname = searchname;
5034 }
5035 leaf = t->FindLeaf(leafname);
5036 if (leaf) {
5037 return leaf;
5038 }
5039 }
5040 return nullptr;
5041}
5042
5043////////////////////////////////////////////////////////////////////////////////
5044/// Fit a projected item(s) from a tree.
5045///
5046/// funcname is a TF1 function.
5047///
5048/// See TTree::Draw() for explanations of the other parameters.
5049///
5050/// By default the temporary histogram created is called htemp.
5051/// If varexp contains >>hnew , the new histogram created is called hnew
5052/// and it is kept in the current directory.
5053///
5054/// The function returns the number of selected entries.
5055///
5056/// Example:
5057/// ~~~ {.cpp}
5058/// tree.Fit(pol4,"sqrt(x)>>hsqrt","y>0")
5059/// ~~~
5060/// will fit sqrt(x) and save the histogram as "hsqrt" in the current
5061/// directory.
5062///
5063/// See also TTree::UnbinnedFit
5064///
5065/// ## Return status
5066///
5067/// The function returns the status of the histogram fit (see TH1::Fit)
5068/// If no entries were selected, the function returns -1;
5069/// (i.e. fitResult is null if the fit is OK)
5071Int_t TTree::Fit(const char* funcname, const char* varexp, const char* selection, Option_t* option, Option_t* goption, Long64_t nentries, Long64_t firstentry)
5072{
5073 GetPlayer();
5074 if (fPlayer) {
5075 return fPlayer->Fit(funcname, varexp, selection, option, goption, nentries, firstentry);
5076 }
5077 return -1;
5078}
5079
5080namespace {
5081struct BoolRAIIToggle {
5082 Bool_t &m_val;
5083
5084 BoolRAIIToggle(Bool_t &val) : m_val(val) { m_val = true; }
5085 ~BoolRAIIToggle() { m_val = false; }
5086};
5087}
5088
5089////////////////////////////////////////////////////////////////////////////////
5090/// Write to disk all the basket that have not yet been individually written and
5091/// create an event cluster boundary (by default).
5092///
5093/// If the caller wishes to flush the baskets but not create an event cluster,
5094/// then set create_cluster to false.
5095///
5096/// If ROOT has IMT-mode enabled, this will launch multiple TBB tasks in parallel
5097/// via TThreadExecutor to do this operation; one per basket compression. If the
5098/// caller utilizes TBB also, care must be taken to prevent deadlocks.
5099///
5100/// For example, let's say the caller holds mutex A and calls FlushBaskets; while
5101/// TBB is waiting for the ROOT compression tasks to complete, it may decide to
5102/// run another one of the user's tasks in this thread. If the second user task
5103/// tries to acquire A, then a deadlock will occur. The example call sequence
5104/// looks like this:
5105///
5106/// - User acquires mutex A
5107/// - User calls FlushBaskets.
5108/// - ROOT launches N tasks and calls wait.
5109/// - TBB schedules another user task, T2.
5110/// - T2 tries to acquire mutex A.
5111///
5112/// At this point, the thread will deadlock: the code may function with IMT-mode
5113/// disabled if the user assumed the legacy code never would run their own TBB
5114/// tasks.
5115///
5116/// SO: users of TBB who want to enable IMT-mode should carefully review their
5117/// locking patterns and make sure they hold no coarse-grained application
5118/// locks when they invoke ROOT.
5119///
5120/// Return the number of bytes written or -1 in case of write error.
5121Int_t TTree::FlushBaskets(Bool_t create_cluster) const
5122{
5123 Int_t retval = FlushBasketsImpl();
5124 if (retval == -1) return retval;
5125
5126 if (create_cluster) const_cast<TTree *>(this)->MarkEventCluster();
5127 return retval;
5128}
5129
5130////////////////////////////////////////////////////////////////////////////////
5131/// Internal implementation of the FlushBaskets algorithm.
5132/// Unlike the public interface, this does NOT create an explicit event cluster
5133/// boundary; it is up to the (internal) caller to determine whether that should
5134/// done.
5135///
5136/// Otherwise, the comments for FlushBaskets applies.
5139{
5140 if (!fDirectory) return 0;
5141 Int_t nbytes = 0;
5142 Int_t nerror = 0;
5143 TObjArray *lb = const_cast<TTree*>(this)->GetListOfBranches();
5144 Int_t nb = lb->GetEntriesFast();
5145
5146#ifdef R__USE_IMT
5147 const auto useIMT = ROOT::IsImplicitMTEnabled() && fIMTEnabled;
5148 if (useIMT) {
5149 // ROOT-9668: here we need to check if the size of fSortedBranches is different from the
5150 // size of the list of branches before triggering the initialisation of the fSortedBranches
5151 // container to cover two cases:
5152 // 1. This is the first time we flush. fSortedBranches is empty and we need to fill it.
5153 // 2. We flushed at least once already but a branch has been be added to the tree since then
5154 if (fSortedBranches.size() != unsigned(nb)) { const_cast<TTree*>(this)->InitializeBranchLists(false); }
5155
5156 BoolRAIIToggle sentry(fIMTFlush);
5157 fIMTZipBytes.store(0);
5158 fIMTTotBytes.store(0);
5159 std::atomic<Int_t> nerrpar(0);
5160 std::atomic<Int_t> nbpar(0);
5161 std::atomic<Int_t> pos(0);
5162
5163 auto mapFunction = [&]() {
5164 // The branch to process is obtained when the task starts to run.
5165 // This way, since branches are sorted, we make sure that branches
5166 // leading to big tasks are processed first. If we assigned the
5167 // branch at task creation time, the scheduler would not necessarily
5168 // respect our sorting.
5169 Int_t j = pos.fetch_add(1);
5170
5171 auto branch = fSortedBranches[j].second;
5172 if (R__unlikely(!branch)) { return; }
5173
5174 if (R__unlikely(gDebug > 0)) {
5175 std::stringstream ss;
5176 ss << std::this_thread::get_id();
5177 Info("FlushBaskets", "[IMT] Thread %s", ss.str().c_str());
5178 Info("FlushBaskets", "[IMT] Running task for branch #%d: %s", j, branch->GetName());
5179 }
5180
5181 Int_t nbtask = branch->FlushBaskets();
5182
5183 if (nbtask < 0) { nerrpar++; }
5184 else { nbpar += nbtask; }
5185 };
5186
5188 pool.Foreach(mapFunction, nb);
5189
5190 fIMTFlush = false;
5191 const_cast<TTree*>(this)->AddTotBytes(fIMTTotBytes);
5192 const_cast<TTree*>(this)->AddZipBytes(fIMTZipBytes);
5193
5194 return nerrpar ? -1 : nbpar.load();
5195 }
5196#endif
5197 for (Int_t j = 0; j < nb; j++) {
5198 TBranch* branch = (TBranch*) lb->UncheckedAt(j);
5199 if (branch) {
5200 Int_t nwrite = branch->FlushBaskets();
5201 if (nwrite<0) {
5202 ++nerror;
5203 } else {
5204 nbytes += nwrite;
5205 }
5206 }
5207 }
5208 if (nerror) {
5209 return -1;
5210 } else {
5211 return nbytes;
5212 }
5213}
5214
5215////////////////////////////////////////////////////////////////////////////////
5216/// Returns the expanded value of the alias. Search in the friends if any.
5218const char* TTree::GetAlias(const char* aliasName) const
5219{
5220 // We already have been visited while recursively looking
5221 // through the friends tree, let's return.
5223 return nullptr;
5224 }
5225 if (fAliases) {
5226 TObject* alias = fAliases->FindObject(aliasName);
5227 if (alias) {
5228 return alias->GetTitle();
5229 }
5230 }
5231 if (!fFriends) {
5232 return nullptr;
5233 }
5234 TFriendLock lock(const_cast<TTree*>(this), kGetAlias);
5235 TIter nextf(fFriends);
5236 TFriendElement* fe = nullptr;
5237 while ((fe = (TFriendElement*) nextf())) {
5238 TTree* t = fe->GetTree();
5239 if (t) {
5240 const char* alias = t->GetAlias(aliasName);
5241 if (alias) {
5242 return alias;
5243 }
5244 const char* subAliasName = strstr(aliasName, fe->GetName());
5245 if (subAliasName && (subAliasName[strlen(fe->GetName())] == '.')) {
5246 alias = t->GetAlias(aliasName + strlen(fe->GetName()) + 1);
5247 if (alias) {
5248 return alias;
5249 }
5250 }
5251 }
5252 }
5253 return nullptr;
5254}
5255
5256namespace {
5257/// Do a breadth first search through the implied hierarchy
5258/// of branches.
5259/// To avoid scanning through the list multiple time
5260/// we also remember the 'depth-first' match.
5261TBranch *R__GetBranch(const TObjArray &branches, const char *name)
5262{
5263 TBranch *result = nullptr;
5264 Int_t nb = branches.GetEntriesFast();
5265 for (Int_t i = 0; i < nb; i++) {
5266 TBranch* b = (TBranch*)branches.UncheckedAt(i);
5267 if (!b)
5268 continue;
5269 if (!strcmp(b->GetName(), name)) {
5270 return b;
5271 }
5272 if (!strcmp(b->GetFullName(), name)) {
5273 return b;
5274 }
5275 if (!result)
5276 result = R__GetBranch(*(b->GetListOfBranches()), name);
5277 }
5278 return result;
5279}
5280}
5281
5282////////////////////////////////////////////////////////////////////////////////
5283/// Return pointer to the branch with the given name in this tree or its friends.
5284/// The search is done breadth first.
5286TBranch* TTree::GetBranch(const char* name)
5287{
5288 // We already have been visited while recursively
5289 // looking through the friends tree, let's return.
5291 return nullptr;
5292 }
5293
5294 if (!name)
5295 return nullptr;
5296
5297 // Look for an exact match in the list of top level
5298 // branches.
5300 if (result)
5301 return result;
5302
5303 // Search using branches, breadth first.
5304 result = R__GetBranch(fBranches, name);
5305 if (result)
5306 return result;
5307
5308 // Search using leaves.
5309 TObjArray* leaves = GetListOfLeaves();
5310 Int_t nleaves = leaves->GetEntriesFast();
5311 for (Int_t i = 0; i < nleaves; i++) {
5312 TLeaf* leaf = (TLeaf*) leaves->UncheckedAt(i);
5313 TBranch* branch = leaf->GetBranch();
5314 if (!strcmp(branch->GetName(), name)) {
5315 return branch;
5316 }
5317 if (!strcmp(branch->GetFullName(), name)) {
5318 return branch;
5319 }
5320 }
5321
5322 if (!fFriends) {
5323 return nullptr;
5324 }
5325
5326 // Search in list of friends.
5327 TFriendLock lock(this, kGetBranch);
5328 TIter next(fFriends);
5329 TFriendElement* fe = nullptr;
5330 while ((fe = (TFriendElement*) next())) {
5331 TTree* t = fe->GetTree();
5332 if (t) {
5333 TBranch* branch = t->GetBranch(name);
5334 if (branch) {
5335 return branch;
5336 }
5337 }
5338 }
5339
5340 // Second pass in the list of friends when
5341 // the branch name is prefixed by the tree name.
5342 next.Reset();
5343 while ((fe = (TFriendElement*) next())) {
5344 TTree* t = fe->GetTree();
5345 if (!t) {
5346 continue;
5347 }
5348 const char* subname = strstr(name, fe->GetName());
5349 if (subname != name) {
5350 continue;
5351 }
5352 Int_t l = strlen(fe->GetName());
5353 subname += l;
5354 if (*subname != '.') {
5355 continue;
5356 }
5357 subname++;
5358 TBranch* branch = t->GetBranch(subname);
5359 if (branch) {
5360 return branch;
5361 }
5362 }
5363 return nullptr;
5364}
5365
5366////////////////////////////////////////////////////////////////////////////////
5367/// Return status of branch with name branchname.
5368///
5369/// - 0 if branch is not activated
5370/// - 1 if branch is activated
5372Bool_t TTree::GetBranchStatus(const char* branchname) const
5373{
5374 TBranch* br = const_cast<TTree*>(this)->GetBranch(branchname);
5375 if (br) {
5376 return br->TestBit(kDoNotProcess) == 0;
5377 }
5378 return 0;
5379}
5380
5381////////////////////////////////////////////////////////////////////////////////
5382/// Static function returning the current branch style.
5383///
5384/// - style = 0 old Branch
5385/// - style = 1 new Bronch
5388{
5389 return fgBranchStyle;
5390}
5391
5392////////////////////////////////////////////////////////////////////////////////
5393/// Used for automatic sizing of the cache.
5394///
5395/// Estimates a suitable size for the tree cache based on AutoFlush.
5396/// A cache sizing factor is taken from the configuration. If this yields zero
5397/// and withDefault is true the historical algorithm for default size is used.
5399Long64_t TTree::GetCacheAutoSize(Bool_t withDefault /* = kFALSE */ )
5400{
5401 auto calculateCacheSize = [this](Double_t cacheFactor)
5402 {
5403 Long64_t cacheSize = 0;
5404 if (fAutoFlush < 0) {
5405 cacheSize = Long64_t(-cacheFactor * fAutoFlush);
5406 } else if (fAutoFlush == 0) {
5407 const auto medianClusterSize = GetMedianClusterSize();
5408 if (medianClusterSize > 0)
5409 cacheSize = Long64_t(cacheFactor * 1.5 * medianClusterSize * GetZipBytes() / (fEntries + 1));
5410 else
5411 cacheSize = Long64_t(cacheFactor * 1.5 * 30000000); // use the default value of fAutoFlush
5412 } else {
5413 cacheSize = Long64_t(cacheFactor * 1.5 * fAutoFlush * GetZipBytes() / (fEntries + 1));
5414 }
5415 if (cacheSize >= (INT_MAX / 4)) {
5416 cacheSize = INT_MAX / 4;
5417 }
5418 return cacheSize;
5419 };
5420
5421 const char *stcs;
5422 Double_t cacheFactor = 0.0;
5423 if (!(stcs = gSystem->Getenv("ROOT_TTREECACHE_SIZE")) || !*stcs) {
5424 cacheFactor = gEnv->GetValue("TTreeCache.Size", 1.0);
5425 } else {
5426 cacheFactor = TString(stcs).Atof();
5427 }
5428
5429 if (cacheFactor < 0.0) {
5430 // ignore negative factors
5431 cacheFactor = 0.0;
5432 }
5433
5434 Long64_t cacheSize = calculateCacheSize(cacheFactor);
5435
5436 if (cacheSize < 0) {
5437 cacheSize = 0;
5438 }
5439
5440 if (cacheSize == 0 && withDefault) {
5441 cacheSize = calculateCacheSize(1.0);
5442 }
5443
5444 return cacheSize;
5445}
5446
5447////////////////////////////////////////////////////////////////////////////////
5448/// Return an iterator over the cluster of baskets starting at firstentry.
5449///
5450/// This iterator is not yet supported for TChain object.
5451/// ~~~ {.cpp}
5452/// TTree::TClusterIterator clusterIter = tree->GetClusterIterator(entry);
5453/// Long64_t clusterStart;
5454/// while( (clusterStart = clusterIter()) < tree->GetEntries() ) {
5455/// printf("The cluster starts at %lld and ends at %lld (inclusive)\n",clusterStart,clusterIter.GetNextEntry()-1);
5456/// }
5457/// ~~~
5460{
5461 // create cache if wanted
5462 if (fCacheDoAutoInit)
5464
5465 return TClusterIterator(this,firstentry);
5466}
5467
5468////////////////////////////////////////////////////////////////////////////////
5469/// Return pointer to the current file.
5472{
5473 if (!fDirectory || fDirectory==gROOT) {
5474 return 0;
5475 }
5476 return fDirectory->GetFile();
5477}
5478
5479////////////////////////////////////////////////////////////////////////////////
5480/// Return the number of entries matching the selection.
5481/// Return -1 in case of errors.
5482///
5483/// If the selection uses any arrays or containers, we return the number
5484/// of entries where at least one element match the selection.
5485/// GetEntries is implemented using the selector class TSelectorEntries,
5486/// which can be used directly (see code in TTreePlayer::GetEntries) for
5487/// additional option.
5488/// If SetEventList was used on the TTree or TChain, only that subset
5489/// of entries will be considered.
5491Long64_t TTree::GetEntries(const char *selection)
5492{
5493 GetPlayer();
5494 if (fPlayer) {
5495 return fPlayer->GetEntries(selection);
5496 }
5497 return -1;
5498}
5499
5500////////////////////////////////////////////////////////////////////////////////
5501/// Return pointer to the 1st Leaf named name in any Branch of this Tree or
5502/// any branch in the list of friend trees.
5505{
5506 if (fEntries) return fEntries;
5507 if (!fFriends) return 0;
5509 if (!fr) return 0;
5510 TTree *t = fr->GetTree();
5511 if (t==0) return 0;
5512 return t->GetEntriesFriend();
5513}
5514
5515////////////////////////////////////////////////////////////////////////////////
5516/// Read all branches of entry and return total number of bytes read.
5517///
5518/// - `getall = 0` : get only active branches
5519/// - `getall = 1` : get all branches
5520///
5521/// The function returns the number of bytes read from the input buffer.
5522/// If entry does not exist the function returns 0.
5523/// If an I/O error occurs, the function returns -1.
5524///
5525/// If the Tree has friends, also read the friends entry.
5526///
5527/// To activate/deactivate one or more branches, use TBranch::SetBranchStatus
5528/// For example, if you have a Tree with several hundred branches, and you
5529/// are interested only by branches named "a" and "b", do
5530/// ~~~ {.cpp}
5531/// mytree.SetBranchStatus("*",0); //disable all branches
5532/// mytree.SetBranchStatus("a",1);
5533/// mytree.SetBranchStatus("b",1);
5534/// ~~~
5535/// when calling mytree.GetEntry(i); only branches "a" and "b" will be read.
5536///
5537/// __WARNING!!__
5538/// If your Tree has been created in split mode with a parent branch "parent.",
5539/// ~~~ {.cpp}
5540/// mytree.SetBranchStatus("parent",1);
5541/// ~~~
5542/// will not activate the sub-branches of "parent". You should do:
5543/// ~~~ {.cpp}
5544/// mytree.SetBranchStatus("parent*",1);
5545/// ~~~
5546/// Without the trailing dot in the branch creation you have no choice but to
5547/// call SetBranchStatus explicitly for each of the sub branches.
5548///
5549/// An alternative is to call directly
5550/// ~~~ {.cpp}
5551/// brancha.GetEntry(i)
5552/// branchb.GetEntry(i);
5553/// ~~~
5554/// ## IMPORTANT NOTE
5555///
5556/// By default, GetEntry reuses the space allocated by the previous object
5557/// for each branch. You can force the previous object to be automatically
5558/// deleted if you call mybranch.SetAutoDelete(kTRUE) (default is kFALSE).
5559///
5560/// Example:
5561///
5562/// Consider the example in $ROOTSYS/test/Event.h
5563/// The top level branch in the tree T is declared with:
5564/// ~~~ {.cpp}
5565/// Event *event = 0; //event must be null or point to a valid object
5566/// //it must be initialized
5567/// T.SetBranchAddress("event",&event);
5568/// ~~~
5569/// When reading the Tree, one can choose one of these 3 options:
5570///
5571/// ## OPTION 1
5572///
5573/// ~~~ {.cpp}
5574/// for (Long64_t i=0;i<nentries;i++) {
5575/// T.GetEntry(i);
5576/// // the object event has been filled at this point
5577/// }
5578/// ~~~
5579/// The default (recommended). At the first entry an object of the class
5580/// Event will be created and pointed by event. At the following entries,
5581/// event will be overwritten by the new data. All internal members that are
5582/// TObject* are automatically deleted. It is important that these members
5583/// be in a valid state when GetEntry is called. Pointers must be correctly
5584/// initialized. However these internal members will not be deleted if the
5585/// characters "->" are specified as the first characters in the comment
5586/// field of the data member declaration.
5587///
5588/// If "->" is specified, the pointer member is read via pointer->Streamer(buf).
5589/// In this case, it is assumed that the pointer is never null (case of
5590/// pointer TClonesArray *fTracks in the Event example). If "->" is not
5591/// specified, the pointer member is read via buf >> pointer. In this case
5592/// the pointer may be null. Note that the option with "->" is faster to
5593/// read or write and it also consumes less space in the file.
5594///
5595/// ## OPTION 2
5596///
5597/// The option AutoDelete is set
5598/// ~~~ {.cpp}
5599/// TBranch *branch = T.GetBranch("event");
5600/// branch->SetAddress(&event);
5601/// branch->SetAutoDelete(kTRUE);
5602/// for (Long64_t i=0;i<nentries;i++) {
5603/// T.GetEntry(i);
5604/// // the object event has been filled at this point
5605/// }
5606/// ~~~
5607/// In this case, at each iteration, the object event is deleted by GetEntry
5608/// and a new instance of Event is created and filled.
5609///
5610/// ## OPTION 3
5611///
5612/// ~~~ {.cpp}
5613/// Same as option 1, but you delete yourself the event.
5614///
5615/// for (Long64_t i=0;i<nentries;i++) {
5616/// delete event;
5617/// event = 0; // EXTREMELY IMPORTANT
5618/// T.GetEntry(i);
5619/// // the object event has been filled at this point
5620/// }
5621/// ~~~
5622/// It is strongly recommended to use the default option 1. It has the
5623/// additional advantage that functions like TTree::Draw (internally calling
5624/// TTree::GetEntry) will be functional even when the classes in the file are
5625/// not available.
5626///
5627/// Note: See the comments in TBranchElement::SetAddress() for the
5628/// object ownership policy of the underlying (user) data.
5630Int_t TTree::GetEntry(Long64_t entry, Int_t getall)
5631{
5632 // We already have been visited while recursively looking
5633 // through the friends tree, let return
5634 if (kGetEntry & fFriendLockStatus) return 0;
5635
5636 if (entry < 0 || entry >= fEntries) return 0;
5637 Int_t i;
5638 Int_t nbytes = 0;
5639 fReadEntry = entry;
5640
5641 // create cache if wanted
5642 if (fCacheDoAutoInit)
5644
5645 Int_t nbranches = fBranches.GetEntriesUnsafe();
5646 Int_t nb=0;
5647
5648 auto seqprocessing = [&]() {
5649 TBranch *branch;
5650 for (i=0;i<nbranches;i++) {
5651 branch = (TBranch*)fBranches.UncheckedAt(i);
5652 nb = branch->GetEntry(entry, getall);
5653 if (nb < 0) break;
5654 nbytes += nb;
5655 }
5656 };
5657
5658#ifdef R__USE_IMT
5660 if (fSortedBranches.empty())
5662
5663 // Count branches are processed first and sequentially
5664 for (auto branch : fSeqBranches) {
5665 nb = branch->GetEntry(entry, getall);
5666 if (nb < 0) break;
5667 nbytes += nb;
5668 }
5669 if (nb < 0) return nb;
5670
5671 // Enable this IMT use case (activate its locks)
5673
5674 Int_t errnb = 0;
5675 std::atomic<Int_t> pos(0);
5676 std::atomic<Int_t> nbpar(0);
5677
5678 auto mapFunction = [&]() {
5679 // The branch to process is obtained when the task starts to run.
5680 // This way, since branches are sorted, we make sure that branches
5681 // leading to big tasks are processed first. If we assigned the
5682 // branch at task creation time, the scheduler would not necessarily
5683 // respect our sorting.
5684 Int_t j = pos.fetch_add(1);
5685
5686 Int_t nbtask = 0;
5687 auto branch = fSortedBranches[j].second;
5688
5689 if (gDebug > 0) {
5690 std::stringstream ss;
5691 ss << std::this_thread::get_id();
5692 Info("GetEntry", "[IMT] Thread %s", ss.str().c_str());
5693 Info("GetEntry", "[IMT] Running task for branch #%d: %s", j, branch->GetName());
5694 }
5695
5696 std::chrono::time_point<std::chrono::system_clock> start, end;
5697
5698 start = std::chrono::system_clock::now();
5699 nbtask = branch->GetEntry(entry, getall);
5700 end = std::chrono::system_clock::now();
5701
5702 Long64_t tasktime = (Long64_t)std::chrono::duration_cast<std::chrono::microseconds>(end - start).count();
5703 fSortedBranches[j].first += tasktime;
5704
5705 if (nbtask < 0) errnb = nbtask;
5706 else nbpar += nbtask;
5707 };
5708
5710 pool.Foreach(mapFunction, fSortedBranches.size());
5711
5712 if (errnb < 0) {
5713 nb = errnb;
5714 }
5715 else {
5716 // Save the number of bytes read by the tasks
5717 nbytes += nbpar;
5718
5719 // Re-sort branches if necessary
5723 }
5724 }
5725 }
5726 else {
5727 seqprocessing();
5728 }
5729#else
5730 seqprocessing();
5731#endif
5732 if (nb < 0) return nb;
5733
5734 // GetEntry in list of friends
5735 if (!fFriends) return nbytes;
5736 TFriendLock lock(this,kGetEntry);
5737 TIter nextf(fFriends);
5738 TFriendElement *fe;
5739 while ((fe = (TFriendElement*)nextf())) {
5740 TTree *t = fe->GetTree();
5741 if (t) {
5743 nb = t->GetEntry(t->GetReadEntry(),getall);
5744 } else {
5745 if ( t->LoadTreeFriend(entry,this) >= 0 ) {
5746 nb = t->GetEntry(t->GetReadEntry(),getall);
5747 } else nb = 0;
5748 }
5749 if (nb < 0) return nb;
5750 nbytes += nb;
5751 }
5752 }
5753 return nbytes;
5754}
5755
5756
5757////////////////////////////////////////////////////////////////////////////////
5758/// Divides the top-level branches into two vectors: (i) branches to be
5759/// processed sequentially and (ii) branches to be processed in parallel.
5760/// Even if IMT is on, some branches might need to be processed first and in a
5761/// sequential fashion: in the parallelization of GetEntry, those are the
5762/// branches that store the size of another branch for every entry
5763/// (e.g. the size of an array branch). If such branches were processed
5764/// in parallel with the rest, there could be two threads invoking
5765/// TBranch::GetEntry on one of them at the same time, since a branch that
5766/// depends on a size (or count) branch will also invoke GetEntry on the latter.
5767/// This method can be invoked several times during the event loop if the TTree
5768/// is being written, for example when adding new branches. In these cases, the
5769/// `checkLeafCount` parameter is false.
5770/// \param[in] checkLeafCount True if we need to check whether some branches are
5771/// count leaves.
5773void TTree::InitializeBranchLists(bool checkLeafCount)
5774{
5775 Int_t nbranches = fBranches.GetEntriesFast();
5776
5777 // The special branch fBranchRef needs to be processed sequentially:
5778 // we add it once only.
5779 if (fBranchRef && fBranchRef != fSeqBranches[0]) {
5780 fSeqBranches.push_back(fBranchRef);
5781 }
5782
5783 // The branches to be processed sequentially are those that are the leaf count of another branch
5784 if (checkLeafCount) {
5785 for (Int_t i = 0; i < nbranches; i++) {
5786 TBranch* branch = (TBranch*)fBranches.UncheckedAt(i);
5787 auto leafCount = ((TLeaf*)branch->GetListOfLeaves()->At(0))->GetLeafCount();
5788 if (leafCount) {
5789 auto countBranch = leafCount->GetBranch();
5790 if (std::find(fSeqBranches.begin(), fSeqBranches.end(), countBranch) == fSeqBranches.end()) {
5791 fSeqBranches.push_back(countBranch);
5792 }
5793 }
5794 }
5795 }
5796
5797 // Any branch that is not a leaf count can be safely processed in parallel when reading
5798 // We need to reset the vector to make sure we do not re-add several times the same branch.
5799 if (!checkLeafCount) {
5800 fSortedBranches.clear();
5801 }
5802 for (Int_t i = 0; i < nbranches; i++) {
5803 Long64_t bbytes = 0;
5804 TBranch* branch = (TBranch*)fBranches.UncheckedAt(i);
5805 if (std::find(fSeqBranches.begin(), fSeqBranches.end(), branch) == fSeqBranches.end()) {
5806 bbytes = branch->GetTotBytes("*");
5807 fSortedBranches.emplace_back(bbytes, branch);
5808 }
5809 }
5810
5811 // Initially sort parallel branches by size
5812 std::sort(fSortedBranches.begin(),
5813 fSortedBranches.end(),
5814 [](std::pair<Long64_t,TBranch*> a, std::pair<Long64_t,TBranch*> b) {
5815 return a.first > b.first;
5816 });
5817
5818 for (size_t i = 0; i < fSortedBranches.size(); i++) {
5819 fSortedBranches[i].first = 0LL;
5820 }
5821}
5822
5823////////////////////////////////////////////////////////////////////////////////
5824/// Sorts top-level branches by the last average task time recorded per branch.
5827{
5828 for (size_t i = 0; i < fSortedBranches.size(); i++) {
5830 }
5831
5832 std::sort(fSortedBranches.begin(),
5833 fSortedBranches.end(),
5834 [](std::pair<Long64_t,TBranch*> a, std::pair<Long64_t,TBranch*> b) {
5835 return a.first > b.first;
5836 });
5837
5838 for (size_t i = 0; i < fSortedBranches.size(); i++) {
5839 fSortedBranches[i].first = 0LL;
5840 }
5841}
5842
5843////////////////////////////////////////////////////////////////////////////////
5844///Returns the entry list assigned to this tree
5847{
5848 return fEntryList;
5849}
5850
5851////////////////////////////////////////////////////////////////////////////////
5852/// Return entry number corresponding to entry.
5853///
5854/// if no TEntryList set returns entry
5855/// else returns the entry number corresponding to the list index=entry
5858{
5859 if (!fEntryList) {
5860 return entry;
5861 }
5862
5863 return fEntryList->GetEntry(entry);
5864}
5865
5866////////////////////////////////////////////////////////////////////////////////
5867/// Return entry number corresponding to major and minor number.
5868/// Note that this function returns only the entry number, not the data
5869/// To read the data corresponding to an entry number, use TTree::GetEntryWithIndex
5870/// the BuildIndex function has created a table of Long64_t* of sorted values
5871/// corresponding to val = major<<31 + minor;
5872/// The function performs binary search in this sorted table.
5873/// If it finds a pair that matches val, it returns directly the
5874/// index in the table.
5875/// If an entry corresponding to major and minor is not found, the function
5876/// returns the index of the major,minor pair immediately lower than the
5877/// requested value, ie it will return -1 if the pair is lower than
5878/// the first entry in the index.
5879///
5880/// See also GetEntryNumberWithIndex
5883{
5884 if (!fTreeIndex) {
5885 return -1;
5886 }
5887 return fTreeIndex->GetEntryNumberWithBestIndex(major, minor);
5888}
5889
5890////////////////////////////////////////////////////////////////////////////////
5891/// Return entry number corresponding to major and minor number.
5892/// Note that this function returns only the entry number, not the data
5893/// To read the data corresponding to an entry number, use TTree::GetEntryWithIndex
5894/// the BuildIndex function has created a table of Long64_t* of sorted values
5895/// corresponding to val = major<<31 + minor;
5896/// The function performs binary search in this sorted table.
5897/// If it finds a pair that matches val, it returns directly the
5898/// index in the table, otherwise it returns -1.
5899///
5900/// See also GetEntryNumberWithBestIndex
5903{
5904 if (!fTreeIndex) {
5905 return -1;
5906 }
5907 return fTreeIndex->GetEntryNumberWithIndex(major, minor);
5908}
5909
5910////////////////////////////////////////////////////////////////////////////////
5911/// Read entry corresponding to major and minor number.
5912///
5913/// The function returns the total number of bytes read.
5914/// If the Tree has friend trees, the corresponding entry with
5915/// the index values (major,minor) is read. Note that the master Tree
5916/// and its friend may have different entry serial numbers corresponding
5917/// to (major,minor).
5920{
5921 // We already have been visited while recursively looking
5922 // through the friends tree, let's return.
5924 return 0;
5925 }
5926 Long64_t serial = GetEntryNumberWithIndex(major, minor);
5927 if (serial < 0) {
5928 return -1;
5929 }
5930 // create cache if wanted
5931 if (fCacheDoAutoInit)
5933
5934 Int_t i;
5935 Int_t nbytes = 0;
5936 fReadEntry = serial;
5937 TBranch *branch;
5938 Int_t nbranches = fBranches.GetEntriesFast();
5939 Int_t nb;
5940 for (i = 0; i < nbranches; ++i) {
5941 branch = (TBranch*)fBranches.UncheckedAt(i);
5942 nb = branch->GetEntry(serial);
5943 if (nb < 0) return nb;
5944 nbytes += nb;
5945 }
5946 // GetEntry in list of friends
5947 if (!fFriends) return nbytes;
5949 TIter nextf(fFriends);
5950 TFriendElement* fe = 0;
5951 while ((fe = (TFriendElement*) nextf())) {
5952 TTree *t = fe->GetTree();
5953 if (t) {
5954 serial = t->GetEntryNumberWithIndex(major,minor);
5955 if (serial <0) return -nbytes;
5956 nb = t->GetEntry(serial);
5957 if (nb < 0) return nb;
5958 nbytes += nb;
5959 }
5960 }
5961 return nbytes;
5962}
5963
5964////////////////////////////////////////////////////////////////////////////////
5965/// Return a pointer to the TTree friend whose name or alias is `friendname`.
5967TTree* TTree::GetFriend(const char *friendname) const
5968{
5969
5970 // We already have been visited while recursively
5971 // looking through the friends tree, let's return.
5973 return 0;
5974 }
5975 if (!fFriends) {
5976 return 0;
5977 }
5978 TFriendLock lock(const_cast<TTree*>(this), kGetFriend);
5979 TIter nextf(fFriends);
5980 TFriendElement* fe = 0;
5981 while ((fe = (TFriendElement*) nextf())) {
5982 if (strcmp(friendname,fe->GetName())==0
5983 || strcmp(friendname,fe->GetTreeName())==0) {
5984 return fe->GetTree();
5985 }
5986 }
5987 // After looking at the first level,
5988 // let's see if it is a friend of friends.
5989 nextf.Reset();
5990 fe = 0;
5991 while ((fe = (TFriendElement*) nextf())) {
5992 TTree *res = fe->GetTree()->GetFriend(friendname);
5993 if (res) {
5994 return res;
5995 }
5996 }
5997 return 0;
5998}
5999
6000////////////////////////////////////////////////////////////////////////////////
6001/// If the 'tree' is a friend, this method returns its alias name.
6002///
6003/// This alias is an alternate name for the tree.
6004///
6005/// It can be used in conjunction with a branch or leaf name in a TTreeFormula,
6006/// to specify in which particular tree the branch or leaf can be found if
6007/// the friend trees have branches or leaves with the same name as the master
6008/// tree.
6009///
6010/// It can also be used in conjunction with an alias created using
6011/// TTree::SetAlias in a TTreeFormula, e.g.:
6012/// ~~~ {.cpp}
6013/// maintree->Draw("treealias.fPx - treealias.myAlias");
6014/// ~~~
6015/// where fPx is a branch of the friend tree aliased as 'treealias' and 'myAlias'
6016/// was created using TTree::SetAlias on the friend tree.
6017///
6018/// However, note that 'treealias.myAlias' will be expanded literally,
6019/// without remembering that it comes from the aliased friend and thus
6020/// the branch name might not be disambiguated properly, which means
6021/// that you may not be able to take advantage of this feature.
6022///
6024const char* TTree::GetFriendAlias(TTree* tree) const
6025{
6026 if ((tree == this) || (tree == GetTree())) {
6027 return 0;
6028 }
6029
6030 // We already have been visited while recursively
6031 // looking through the friends tree, let's return.
6033 return 0;
6034 }
6035 if (!fFriends) {
6036 return 0;
6037 }
6038 TFriendLock lock(const_cast<TTree*>(this), kGetFriendAlias);
6039 TIter nextf(fFriends);
6040 TFriendElement* fe = 0;
6041 while ((fe = (TFriendElement*) nextf())) {
6042 TTree* t = fe->GetTree();
6043 if (t == tree) {
6044 return fe->GetName();
6045 }
6046 // Case of a chain:
6047 if (t && t->GetTree() == tree) {
6048 return fe->GetName();
6049 }
6050 }
6051 // After looking at the first level,
6052 // let's see if it is a friend of friends.
6053 nextf.Reset();
6054 fe = 0;
6055 while ((fe = (TFriendElement*) nextf())) {
6056 const char* res = fe->GetTree()->GetFriendAlias(tree);
6057 if (res) {
6058 return res;
6059 }
6060 }
6061 return 0;
6062}
6063
6064////////////////////////////////////////////////////////////////////////////////
6065/// Returns the current set of IO settings
6067{
6068 return fIOFeatures;
6069}
6070
6071////////////////////////////////////////////////////////////////////////////////
6072/// Creates a new iterator that will go through all the leaves on the tree itself and its friend.
6075{
6076 return new TTreeFriendLeafIter(this, dir);
6077}
6078
6079////////////////////////////////////////////////////////////////////////////////
6080/// Return pointer to the 1st Leaf named name in any Branch of this
6081/// Tree or any branch in the list of friend trees.
6082///
6083/// The leaf name can contain the name of a friend tree with the
6084/// syntax: friend_dir_and_tree.full_leaf_name
6085/// the friend_dir_and_tree can be of the form:
6086/// ~~~ {.cpp}
6087/// TDirectoryName/TreeName
6088/// ~~~
6090TLeaf* TTree::GetLeafImpl(const char* branchname, const char *leafname)
6091{
6092 TLeaf *leaf = nullptr;
6093 if (branchname) {
6094 TBranch *branch = FindBranch(branchname);
6095 if (branch) {
6096 leaf = branch->GetLeaf(leafname);
6097 if (leaf) {
6098 return leaf;
6099 }
6100 }
6101 }
6102 TIter nextl(GetListOfLeaves());
6103 while ((leaf = (TLeaf*)nextl())) {
6104 if (strcmp(leaf->GetFullName(), leafname) != 0 && strcmp(leaf->GetName(), leafname) != 0)
6105 continue; // leafname does not match GetName() nor GetFullName(), this is not the right leaf
6106 if (branchname) {
6107 // check the branchname is also a match
6108 TBranch *br = leaf->GetBranch();
6109 // if a quick comparison with the branch full name is a match, we are done
6110 if (!strcmp(br->GetFullName(), branchname))
6111 return leaf;
6112 UInt_t nbch = strlen(branchname);
6113 const char* brname = br->GetName();
6114 TBranch *mother = br->GetMother();
6115 if (strncmp(brname,branchname,nbch)) {
6116 if (mother != br) {
6117 const char *mothername = mother->GetName();
6118 UInt_t motherlen = strlen(mothername);
6119 if (!strcmp(mothername, branchname)) {
6120 return leaf;
6121 } else if (nbch > motherlen && strncmp(mothername,branchname,motherlen)==0 && (mothername[motherlen-1]=='.' || branchname[motherlen]=='.')) {
6122 // 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.
6123 if (strncmp(brname,branchname+motherlen+1,nbch-motherlen-1)) {
6124 // No it does not
6125 continue;
6126 } // else we have match so we can proceed.
6127 } else {
6128 // no match
6129 continue;
6130 }
6131 } else {
6132 continue;
6133 }
6134 }
6135 // The start of the branch name is identical to the content
6136 // of 'aname' before the first '/'.
6137 // Let's make sure that it is not longer (we are trying
6138 // to avoid having jet2/value match the branch jet23
6139 if ((strlen(brname) > nbch) && (brname[nbch] != '.') && (brname[nbch] != '[')) {
6140 continue;
6141 }
6142 }
6143 return leaf;
6144 }
6145 if (!fFriends) return nullptr;
6146 TFriendLock lock(this,kGetLeaf);
6147 TIter next(fFriends);
6148 TFriendElement *fe;
6149 while ((fe = (TFriendElement*)next())) {
6150 TTree *t = fe->GetTree();
6151 if (t) {
6152 leaf = t->GetLeaf(branchname, leafname);
6153 if (leaf) return leaf;
6154 }
6155 }
6156
6157 //second pass in the list of friends when the leaf name
6158 //is prefixed by the tree name
6159 TString strippedArg;
6160 next.Reset();
6161 while ((fe = (TFriendElement*)next())) {
6162 TTree *t = fe->GetTree();
6163 if (!t) continue;
6164 const char *subname = strstr(leafname,fe->GetName());
6165 if (subname != leafname) continue;
6166 Int_t l = strlen(fe->GetName());
6167 subname += l;
6168 if (*subname != '.') continue;
6169 subname++;
6170 strippedArg += subname;
6171 leaf = t->GetLeaf(branchname,subname);
6172 if (leaf) return leaf;
6173 }
6174 return nullptr;
6175}
6176
6177////////////////////////////////////////////////////////////////////////////////
6178/// Return pointer to the 1st Leaf named name in any Branch of this
6179/// Tree or any branch in the list of friend trees.
6180///
6181/// The leaf name can contain the name of a friend tree with the
6182/// syntax: friend_dir_and_tree.full_leaf_name
6183/// the friend_dir_and_tree can be of the form:
6184///
6185/// TDirectoryName/TreeName
6187TLeaf* TTree::GetLeaf(const char* branchname, const char *leafname)
6188{
6189 if (leafname == 0) return 0;
6190
6191 // We already have been visited while recursively looking
6192 // through the friends tree, let return
6194 return 0;
6195 }
6196
6197 return GetLeafImpl(branchname,leafname);
6198}
6199
6200////////////////////////////////////////////////////////////////////////////////
6201/// Return pointer to first leaf named "name" in any branch of this
6202/// tree or its friend trees.
6203///
6204/// \param[in] name may be in the form 'branch/leaf'
6205///
6207TLeaf* TTree::GetLeaf(const char *name)
6208{
6209 // Return nullptr if name is invalid or if we have
6210 // already been visited while searching friend trees
6211 if (!name || (kGetLeaf & fFriendLockStatus))
6212 return nullptr;
6213
6214 std::string path(name);
6215 const auto sep = path.find_last_of("/");
6216 if (sep != std::string::npos)
6217 return GetLeafImpl(path.substr(0, sep).c_str(), name+sep+1);
6218
6219 return GetLeafImpl(nullptr, name);
6220}
6221
6222////////////////////////////////////////////////////////////////////////////////
6223/// Return maximum of column with name columname.
6224/// if the Tree has an associated TEventList or TEntryList, the maximum
6225/// is computed for the entries in this list.
6227Double_t TTree::GetMaximum(const char* columname)
6228{
6229 TLeaf* leaf = this->GetLeaf(columname);
6230 if (!leaf) {
6231 return 0;
6232 }
6233
6234 // create cache if wanted
6235 if (fCacheDoAutoInit)
6237
6238 TBranch* branch = leaf->GetBranch();
6239 Double_t cmax = -DBL_MAX;
6240 for (Long64_t i = 0; i < fEntries; ++i) {
6241 Long64_t entryNumber = this->GetEntryNumber(i);
6242 if (entryNumber < 0) break;
6243 branch->GetEntry(entryNumber);
6244 for (Int_t j = 0; j < leaf->GetLen(); ++j) {
6245 Double_t val = leaf->GetValue(j);
6246 if (val > cmax) {
6247 cmax = val;
6248 }
6249 }
6250 }
6251 return cmax;
6252}
6253
6254////////////////////////////////////////////////////////////////////////////////
6255/// Static function which returns the tree file size limit in bytes.
6258{
6259 return fgMaxTreeSize;
6260}
6261
6262////////////////////////////////////////////////////////////////////////////////
6263/// Return minimum of column with name columname.
6264/// if the Tree has an associated TEventList or TEntryList, the minimum
6265/// is computed for the entries in this list.
6267Double_t TTree::GetMinimum(const char* columname)
6268{
6269 TLeaf* leaf = this->GetLeaf(columname);
6270 if (!leaf) {
6271 return 0;
6272 }
6273
6274 // create cache if wanted
6275 if (fCacheDoAutoInit)
6277
6278 TBranch* branch = leaf->GetBranch();
6279 Double_t cmin = DBL_MAX;
6280 for (Long64_t i = 0; i < fEntries; ++i) {
6281 Long64_t entryNumber = this->GetEntryNumber(i);
6282 if (entryNumber < 0) break;
6283 branch->GetEntry(entryNumber);
6284 for (Int_t j = 0;j < leaf->GetLen(); ++j) {
6285 Double_t val = leaf->GetValue(j);
6286 if (val < cmin) {
6287 cmin = val;
6288 }
6289 }
6290 }
6291 return cmin;
6292}
6293
6294////////////////////////////////////////////////////////////////////////////////
6295/// Load the TTreePlayer (if not already done).
6298{
6299 if (fPlayer) {
6300 return fPlayer;
6301 }
6303 return fPlayer;
6304}
6305
6306////////////////////////////////////////////////////////////////////////////////
6307/// Find and return the TTreeCache registered with the file and which may
6308/// contain branches for us.
6311{
6312 TTreeCache *pe = dynamic_cast<TTreeCache*>(file->GetCacheRead(GetTree()));
6313 if (pe && pe->GetTree() != GetTree())
6314 pe = nullptr;
6315 return pe;
6316}
6317
6318////////////////////////////////////////////////////////////////////////////////
6319/// Find and return the TTreeCache registered with the file and which may
6320/// contain branches for us. If create is true and there is no cache
6321/// a new cache is created with default size.
6324{
6326 if (create && !pe) {
6327 if (fCacheDoAutoInit)
6329 pe = dynamic_cast<TTreeCache*>(file->GetCacheRead(GetTree()));
6330 if (pe && pe->GetTree() != GetTree()) pe = 0;
6331 }
6332 return pe;
6333}
6334
6335////////////////////////////////////////////////////////////////////////////////
6336/// Return a pointer to the list containing user objects associated to this tree.
6337///
6338/// The list is automatically created if it does not exist.
6339///
6340/// WARNING: By default the TTree destructor will delete all objects added
6341/// to this list. If you do not want these objects to be deleted,
6342/// call:
6343///
6344/// mytree->GetUserInfo()->Clear();
6345///
6346/// before deleting the tree.
6349{
6350 if (!fUserInfo) {
6351 fUserInfo = new TList();
6352 fUserInfo->SetName("UserInfo");
6353 }
6354 return fUserInfo;
6355}
6356
6357////////////////////////////////////////////////////////////////////////////////
6358/// Appends the cluster range information stored in 'fromtree' to this tree,
6359/// including the value of fAutoFlush.
6360///
6361/// This is used when doing a fast cloning (by TTreeCloner).
6362/// See also fAutoFlush and fAutoSave if needed.
6364void TTree::ImportClusterRanges(TTree *fromtree)
6365{
6366 Long64_t autoflush = fromtree->GetAutoFlush();
6367 if (fromtree->fNClusterRange == 0 && fromtree->fAutoFlush == fAutoFlush) {
6368 // nothing to do
6369 } else if (fNClusterRange || fromtree->fNClusterRange) {
6370 Int_t newsize = fNClusterRange + 1 + fromtree->fNClusterRange;
6371 if (newsize > fMaxClusterRange) {
6372 if (fMaxClusterRange) {
6374 newsize*sizeof(Long64_t),fMaxClusterRange*sizeof(Long64_t));
6376 newsize*sizeof(Long64_t),fMaxClusterRange*sizeof(Long64_t));
6377 fMaxClusterRange = newsize;
6378 } else {
6379 fMaxClusterRange = newsize;
6382 }
6383 }
6384 if (fEntries) {
6388 }
6389 for (Int_t i = 0 ; i < fromtree->fNClusterRange; ++i) {
6393 }
6394 fAutoFlush = autoflush;
6395 } else {
6396 SetAutoFlush( autoflush );
6397 }
6398 Long64_t autosave = GetAutoSave();
6399 if (autoflush > 0 && autosave > 0) {
6400 SetAutoSave( autoflush*(autosave/autoflush) );
6401 }
6402}
6403
6404////////////////////////////////////////////////////////////////////////////////
6405/// Keep a maximum of fMaxEntries in memory.
6408{
6410 Long64_t maxEntries = fMaxEntries - (fMaxEntries / 10);
6411 for (Int_t i = 0; i < nb; ++i) {
6412 TBranch* branch = (TBranch*) fBranches.UncheckedAt(i);
6413 branch->KeepCircular(maxEntries);
6414 }
6415 if (fNClusterRange) {
6416 Long64_t entriesOffset = fEntries - maxEntries;
6417 Int_t oldsize = fNClusterRange;
6418 for(Int_t i = 0, j = 0; j < oldsize; ++j) {
6419 if (fClusterRangeEnd[j] > entriesOffset) {
6420 fClusterRangeEnd[i] = fClusterRangeEnd[j] - entriesOffset;
6421 ++i;
6422 } else {
6424 }
6425 }
6426 }
6427 fEntries = maxEntries;
6428 fReadEntry = -1;
6429}
6430
6431////////////////////////////////////////////////////////////////////////////////
6432/// Read in memory all baskets from all branches up to the limit of maxmemory bytes.
6433///
6434/// If maxmemory is non null and positive SetMaxVirtualSize is called
6435/// with this value. Default for maxmemory is 2000000000 (2 Gigabytes).
6436/// The function returns the total number of baskets read into memory
6437/// if negative an error occurred while loading the branches.
6438/// This method may be called to force branch baskets in memory
6439/// when random access to branch entries is required.
6440/// If random access to only a few branches is required, you should
6441/// call directly TBranch::LoadBaskets.
6444{
6445 if (maxmemory > 0) SetMaxVirtualSize(maxmemory);
6446
6447 TIter next(GetListOfLeaves());
6448 TLeaf *leaf;
6449 Int_t nimported = 0;
6450 while ((leaf=(TLeaf*)next())) {
6451 nimported += leaf->GetBranch()->LoadBaskets();//break;
6452 }
6453 return nimported;
6454}
6455
6456////////////////////////////////////////////////////////////////////////////////
6457/// Set current entry.
6458///
6459/// Returns -2 if entry does not exist (just as TChain::LoadTree()).
6460/// Returns -6 if an error occurs in the notification callback (just as TChain::LoadTree()).
6461///
6462/// Note: This function is overloaded in TChain.
6463///
6466{
6467 // We have already been visited while recursively looking
6468 // through the friend trees, let's return
6470 // We need to return a negative value to avoid a circular list of friends
6471 // to think that there is always an entry somewhere in the list.
6472 return -1;
6473 }
6474
6475 // create cache if wanted
6476 if (fCacheDoAutoInit && entry >=0)
6478
6479 if (fNotify) {
6480 if (fReadEntry < 0) {
6481 fNotify->Notify();
6482 }
6483 }
6484 fReadEntry = entry;
6485
6486 Bool_t friendHasEntry = kFALSE;
6487 if (fFriends) {
6488 // Set current entry in friends as well.
6489 //
6490 // An alternative would move this code to each of the
6491 // functions calling LoadTree (and to overload a few more).
6492 Bool_t needUpdate = kFALSE;
6493 {
6494 // This scope is need to insure the lock is released at the right time
6495 TIter nextf(fFriends);
6496 TFriendLock lock(this, kLoadTree);
6497 TFriendElement* fe = 0;
6498 while ((fe = (TFriendElement*) nextf())) {
6500 // This friend element was added by the chain that owns this
6501 // tree, the chain will deal with loading the correct entry.
6502 continue;
6503 }
6504 TTree* friendTree = fe->GetTree();
6505 if (friendTree) {
6506 if (friendTree->LoadTreeFriend(entry, this) >= 0) {
6507 friendHasEntry = kTRUE;
6508 }
6509 }
6510 if (fe->IsUpdated()) {
6511 needUpdate = kTRUE;
6512 fe->ResetUpdated();
6513 }
6514 } // for each friend
6515 }
6516 if (needUpdate) {
6517 //update list of leaves in all TTreeFormula of the TTreePlayer (if any)
6518 if (fPlayer) {
6520 }
6521 //Notify user if requested
6522 if (fNotify) {
6523 if(!fNotify->Notify()) return -6;
6524 }
6525 }
6526 }
6527
6528 if ((fReadEntry >= fEntries) && !friendHasEntry) {
6529 fReadEntry = -1;
6530 return -2;
6531 }
6532 return fReadEntry;
6533}
6534
6535////////////////////////////////////////////////////////////////////////////////
6536/// Load entry on behalf of our master tree, we may use an index.
6537///
6538/// Called by LoadTree() when the masterTree looks for the entry
6539/// number in a friend tree (us) corresponding to the passed entry
6540/// number in the masterTree.
6541///
6542/// If we have no index, our entry number and the masterTree entry
6543/// number are the same.
6544///
6545/// If we *do* have an index, we must find the (major, minor) value pair
6546/// in masterTree to locate our corresponding entry.
6547///
6549Long64_t TTree::LoadTreeFriend(Long64_t entry, TTree* masterTree)
6550{
6551 if (!fTreeIndex) {
6552 return LoadTree(entry);
6553 }
6554 return LoadTree(fTreeIndex->GetEntryNumberFriend(masterTree));
6555}
6556
6557////////////////////////////////////////////////////////////////////////////////
6558/// Generate a skeleton analysis class for this tree.
6559///
6560/// The following files are produced: classname.h and classname.C.
6561/// If classname is 0, classname will be called "nameoftree".
6562///
6563/// The generated code in classname.h includes the following:
6564///
6565/// - Identification of the original tree and the input file name.
6566/// - Definition of an analysis class (data members and member functions).
6567/// - The following member functions:
6568/// - constructor (by default opening the tree file),
6569/// - GetEntry(Long64_t entry),
6570/// - Init(TTree* tree) to initialize a new TTree,
6571/// - Show(Long64_t entry) to read and dump entry.
6572///
6573/// The generated code in classname.C includes only the main
6574/// analysis function Loop.
6575///
6576/// To use this function:
6577///
6578/// - Open your tree file (eg: TFile f("myfile.root");)
6579/// - T->MakeClass("MyClass");
6580///
6581/// where T is the name of the TTree in file myfile.root,
6582/// and MyClass.h, MyClass.C the name of the files created by this function.
6583/// In a ROOT session, you can do:
6584/// ~~~ {.cpp}
6585/// root > .L MyClass.C
6586/// root > MyClass* t = new MyClass;
6587/// root > t->GetEntry(12); // Fill data members of t with entry number 12.
6588/// root > t->Show(); // Show values of entry 12.
6589/// root > t->Show(16); // Read and show values of entry 16.
6590/// root > t->Loop(); // Loop on all entries.
6591/// ~~~
6592/// NOTE: Do not use the code generated for a single TTree which is part
6593/// of a TChain to process that entire TChain. The maximum dimensions
6594/// calculated for arrays on the basis of a single TTree from the TChain
6595/// might be (will be!) too small when processing all of the TTrees in
6596/// the TChain. You must use myChain.MakeClass() to generate the code,
6597/// not myTree.MakeClass(...).
6599Int_t TTree::MakeClass(const char* classname, Option_t* option)
6600{
6601 GetPlayer();
6602 if (!fPlayer) {
6603 return 0;
6604 }
6605 return fPlayer->MakeClass(classname, option);
6606}
6607
6608////////////////////////////////////////////////////////////////////////////////
6609/// Generate a skeleton function for this tree.
6610///
6611/// The function code is written on filename.
6612/// If filename is 0, filename will be called nameoftree.C
6613///
6614/// The generated code includes the following:
6615/// - Identification of the original Tree and Input file name,
6616/// - Opening the Tree file,
6617/// - Declaration of Tree variables,
6618/// - Setting of branches addresses,
6619/// - A skeleton for the entry loop.
6620///
6621/// To use this function:
6622///
6623/// - Open your Tree file (eg: TFile f("myfile.root");)
6624/// - T->MakeCode("MyAnalysis.C");
6625///
6626/// where T is the name of the TTree in file myfile.root
6627/// and MyAnalysis.C the name of the file created by this function.
6628///
6629/// NOTE: Since the implementation of this function, a new and better
6630/// function TTree::MakeClass() has been developed.
6632Int_t TTree::MakeCode(const char* filename)
6633{
6634 Warning("MakeCode", "MakeCode is obsolete. Use MakeClass or MakeSelector instead");
6635
6636 GetPlayer();
6637 if (!fPlayer) return 0;
6638 return fPlayer->MakeCode(filename);
6639}
6640
6641////////////////////////////////////////////////////////////////////////////////
6642/// Generate a skeleton analysis class for this Tree using TBranchProxy.
6643///
6644/// TBranchProxy is the base of a class hierarchy implementing an
6645/// indirect access to the content of the branches of a TTree.
6646///
6647/// "proxyClassname" is expected to be of the form:
6648/// ~~~ {.cpp}
6649/// [path/]fileprefix
6650/// ~~~
6651/// The skeleton will then be generated in the file:
6652/// ~~~ {.cpp}
6653/// fileprefix.h
6654/// ~~~
6655/// located in the current directory or in 'path/' if it is specified.
6656/// The class generated will be named 'fileprefix'
6657///
6658/// "macrofilename" and optionally "cutfilename" are expected to point
6659/// to source files which will be included by the generated skeleton.
6660/// Method of the same name as the file(minus the extension and path)
6661/// will be called by the generated skeleton's Process method as follow:
6662/// ~~~ {.cpp}
6663/// [if (cutfilename())] htemp->Fill(macrofilename());
6664/// ~~~
6665/// "option" can be used select some of the optional features during
6666/// the code generation. The possible options are:
6667///
6668/// - nohist : indicates that the generated ProcessFill should not fill the histogram.
6669///
6670/// 'maxUnrolling' controls how deep in the class hierarchy does the
6671/// system 'unroll' classes that are not split. Unrolling a class
6672/// allows direct access to its data members (this emulates the behavior
6673/// of TTreeFormula).
6674///
6675/// The main features of this skeleton are:
6676///
6677/// * on-demand loading of branches
6678/// * ability to use the 'branchname' as if it was a data member
6679/// * protection against array out-of-bounds errors
6680/// * ability to use the branch data as an object (when the user code is available)
6681///
6682/// For example with Event.root, if
6683/// ~~~ {.cpp}
6684/// Double_t somePx = fTracks.fPx[2];
6685/// ~~~
6686/// is executed by one of the method of the skeleton,
6687/// somePx will updated with the current value of fPx of the 3rd track.
6688///
6689/// Both macrofilename and the optional cutfilename are expected to be
6690/// the name of source files which contain at least a free standing
6691/// function with the signature:
6692/// ~~~ {.cpp}
6693/// x_t macrofilename(); // i.e function with the same name as the file
6694/// ~~~
6695/// and
6696/// ~~~ {.cpp}
6697/// y_t cutfilename(); // i.e function with the same name as the file
6698/// ~~~
6699/// x_t and y_t needs to be types that can convert respectively to a double
6700/// and a bool (because the skeleton uses:
6701///
6702/// if (cutfilename()) htemp->Fill(macrofilename());
6703///
6704/// These two functions are run in a context such that the branch names are
6705/// available as local variables of the correct (read-only) type.
6706///
6707/// Note that if you use the same 'variable' twice, it is more efficient
6708/// to 'cache' the value. For example:
6709/// ~~~ {.cpp}
6710/// Int_t n = fEventNumber; // Read fEventNumber
6711/// if (n<10 || n>10) { ... }
6712/// ~~~
6713/// is more efficient than
6714/// ~~~ {.cpp}
6715/// if (fEventNumber<10 || fEventNumber>10)
6716/// ~~~
6717/// Also, optionally, the generated selector will also call methods named
6718/// macrofilename_methodname in each of 6 main selector methods if the method
6719/// macrofilename_methodname exist (Where macrofilename is stripped of its
6720/// extension).
6721///
6722/// Concretely, with the script named h1analysisProxy.C,
6723///
6724/// - The method calls the method (if it exist)
6725/// - Begin -> void h1analysisProxy_Begin(TTree*);
6726/// - SlaveBegin -> void h1analysisProxy_SlaveBegin(TTree*);
6727/// - Notify -> Bool_t h1analysisProxy_Notify();
6728/// - Process -> Bool_t h1analysisProxy_Process(Long64_t);
6729/// - SlaveTerminate -> void h1analysisProxy_SlaveTerminate();
6730/// - Terminate -> void h1analysisProxy_Terminate();
6731///
6732/// If a file name macrofilename.h (or .hh, .hpp, .hxx, .hPP, .hXX) exist
6733/// it is included before the declaration of the proxy class. This can
6734/// be used in particular to insure that the include files needed by
6735/// the macro file are properly loaded.
6736///
6737/// The default histogram is accessible via the variable named 'htemp'.
6738///
6739/// If the library of the classes describing the data in the branch is
6740/// loaded, the skeleton will add the needed `include` statements and
6741/// give the ability to access the object stored in the branches.
6742///
6743/// To draw px using the file hsimple.root (generated by the
6744/// hsimple.C tutorial), we need a file named hsimple.cxx:
6745/// ~~~ {.cpp}
6746/// double hsimple() {
6747/// return px;
6748/// }
6749/// ~~~
6750/// MakeProxy can then be used indirectly via the TTree::Draw interface
6751/// as follow:
6752/// ~~~ {.cpp}
6753/// new TFile("hsimple.root")
6754/// ntuple->Draw("hsimple.cxx");
6755/// ~~~
6756/// A more complete example is available in the tutorials directory:
6757/// h1analysisProxy.cxx , h1analysProxy.h and h1analysisProxyCut.C
6758/// which reimplement the selector found in h1analysis.C
6760Int_t TTree::MakeProxy(const char* proxyClassname, const char* macrofilename, const char* cutfilename, const char* option, Int_t maxUnrolling)
6761{
6762 GetPlayer();
6763 if (!fPlayer) return 0;
6764 return fPlayer->MakeProxy(proxyClassname,macrofilename,cutfilename,option,maxUnrolling);
6765}
6766
6767////////////////////////////////////////////////////////////////////////////////
6768/// Generate skeleton selector class for this tree.
6769///
6770/// The following files are produced: selector.h and selector.C.
6771/// If selector is 0, the selector will be called "nameoftree".
6772/// The option can be used to specify the branches that will have a data member.
6773/// - If option is "=legacy", a pre-ROOT6 selector will be generated (data
6774/// members and branch pointers instead of TTreeReaders).
6775/// - If option is empty, readers will be generated for each leaf.
6776/// - If option is "@", readers will be generated for the topmost branches.
6777/// - Individual branches can also be picked by their name:
6778/// - "X" generates readers for leaves of X.
6779/// - "@X" generates a reader for X as a whole.
6780/// - "@X;Y" generates a reader for X as a whole and also readers for the
6781/// leaves of Y.
6782/// - For further examples see the figure below.
6783///
6784/// \image html ttree_makeselector_option_examples.png
6785///
6786/// The generated code in selector.h includes the following:
6787/// - Identification of the original Tree and Input file name
6788/// - Definition of selector class (data and functions)
6789/// - The following class functions:
6790/// - constructor and destructor
6791/// - void Begin(TTree *tree)
6792/// - void SlaveBegin(TTree *tree)
6793/// - void Init(TTree *tree)
6794/// - Bool_t Notify()
6795/// - Bool_t Process(Long64_t entry)
6796/// - void Terminate()
6797/// - void SlaveTerminate()
6798///
6799/// The class selector derives from TSelector.
6800/// The generated code in selector.C includes empty functions defined above.
6801///
6802/// To use this function:
6803///
6804/// - connect your Tree file (eg: `TFile f("myfile.root");`)
6805/// - `T->MakeSelector("myselect");`
6806///
6807/// where T is the name of the Tree in file myfile.root
6808/// and myselect.h, myselect.C the name of the files created by this function.
6809/// In a ROOT session, you can do:
6810/// ~~~ {.cpp}
6811/// root > T->Process("myselect.C")
6812/// ~~~
6814Int_t TTree::MakeSelector(const char* selector, Option_t* option)
6815{
6816 TString opt(option);
6817 if(opt.EqualTo("=legacy", TString::ECaseCompare::kIgnoreCase)) {
6818 return MakeClass(selector, "selector");
6819 } else {
6820 GetPlayer();
6821 if (!fPlayer) return 0;
6822 return fPlayer->MakeReader(selector, option);
6823 }
6824}
6825
6826////////////////////////////////////////////////////////////////////////////////
6827/// Check if adding nbytes to memory we are still below MaxVirtualsize.
6830{
6831 if ((fTotalBuffers + nbytes) < fMaxVirtualSize) {
6832 return kFALSE;
6833 }
6834 return kTRUE;
6835}
6836
6837////////////////////////////////////////////////////////////////////////////////
6838/// Static function merging the trees in the TList into a new tree.
6839///
6840/// Trees in the list can be memory or disk-resident trees.
6841/// The new tree is created in the current directory (memory if gROOT).
6843TTree* TTree::MergeTrees(TList* li, Option_t* options)
6844{
6845 if (!li) return 0;
6846 TIter next(li);
6847 TTree *newtree = 0;
6848 TObject *obj;
6849
6850 while ((obj=next())) {
6851 if (!obj->InheritsFrom(TTree::Class())) continue;
6852 TTree *tree = (TTree*)obj;
6853 Long64_t nentries = tree->GetEntries();
6854 if (nentries == 0) continue;
6855 if (!newtree) {
6856 newtree = (TTree*)tree->CloneTree(-1, options);
6857 if (!newtree) continue;
6858
6859 // Once the cloning is done, separate the trees,
6860 // to avoid as many side-effects as possible
6861 // The list of clones is guaranteed to exist since we
6862 // just cloned the tree.
6863 tree->GetListOfClones()->Remove(newtree);
6864 tree->ResetBranchAddresses();
6865 newtree->ResetBranchAddresses();
6866 continue;
6867 }
6868
6869 newtree->CopyEntries(tree, -1, options, kTRUE);
6870 }
6871 if (newtree && newtree->GetTreeIndex()) {
6872 newtree->GetTreeIndex()->Append(0,kFALSE); // Force the sorting
6873 }
6874 return newtree;
6875}
6876
6877////////////////////////////////////////////////////////////////////////////////
6878/// Merge the trees in the TList into this tree.
6879///
6880/// Returns the total number of entries in the merged tree.
6883{
6884 if (!li) return 0;
6885 Long64_t storeAutoSave = fAutoSave;
6886 // Disable the autosave as the TFileMerge keeps a list of key and deleting the underlying
6887 // key would invalidate its iteration (or require costly measure to not use the deleted keys).
6888 // Also since this is part of a merging operation, the output file is not as precious as in
6889 // the general case since the input file should still be around.
6890 fAutoSave = 0;
6891 TIter next(li);
6892 TTree *tree;
6893 while ((tree = (TTree*)next())) {
6894 if (tree==this) continue;
6895 if (!tree->InheritsFrom(TTree::Class())) {
6896 Error("Add","Attempt to add object of class: %s to a %s", tree->ClassName(), ClassName());
6897 fAutoSave = storeAutoSave;
6898 return -1;
6899 }
6900
6901 Long64_t nentries = tree->GetEntries();
6902 if (nentries == 0) continue;
6903
6904 CopyEntries(tree, -1, options, kTRUE);
6905 }
6906 fAutoSave = storeAutoSave;
6907 return GetEntries();
6908}
6909
6910////////////////////////////////////////////////////////////////////////////////
6911/// Merge the trees in the TList into this tree.
6912/// If info->fIsFirst is true, first we clone this TTree info the directory
6913/// info->fOutputDirectory and then overlay the new TTree information onto
6914/// this TTree object (so that this TTree object is now the appropriate to
6915/// use for further merging).
6916///
6917/// Returns the total number of entries in the merged tree.
6920{
6921 const char *options = info ? info->fOptions.Data() : "";
6922 if (info && info->fIsFirst && info->fOutputDirectory && info->fOutputDirectory->GetFile() != GetCurrentFile()) {
6923 if (GetCurrentFile() == nullptr) {
6924 // In memory TTree, all we need to do is ... write it.
6927 fDirectory->WriteTObject(this);
6928 } else if (info->fOptions.Contains("fast")) {
6930 } else {
6932 TIOFeatures saved_features = fIOFeatures;
6933 TTree *newtree = CloneTree(-1, options);
6934 if (info->fIOFeatures)
6935 fIOFeatures = *(info->fIOFeatures);
6936 else
6937 fIOFeatures = saved_features;
6938 if (newtree) {
6939 newtree->Write();
6940 delete newtree;
6941 }
6942 // Make sure things are really written out to disk before attempting any reading.
6943 info->fOutputDirectory->GetFile()->Flush();
6944 info->fOutputDirectory->ReadTObject(this,this->GetName());
6945 }
6946 }
6947 if (!li) return 0;
6948 Long64_t storeAutoSave = fAutoSave;
6949 // Disable the autosave as the TFileMerge keeps a list of key and deleting the underlying
6950 // key would invalidate its iteration (or require costly measure to not use the deleted keys).
6951 // Also since this is part of a merging operation, the output file is not as precious as in
6952 // the general case since the input file should still be around.
6953 fAutoSave = 0;
6954 TIter next(li);
6955 TTree *tree;
6956 while ((tree = (TTree*)next())) {
6957 if (tree==this) continue;
6958 if (!tree->InheritsFrom(TTree::Class())) {
6959 Error("Add","Attempt to add object of class: %s to a %s", tree->ClassName(), ClassName());
6960 fAutoSave = storeAutoSave;
6961 return -1;
6962 }
6963
6964 CopyEntries(tree, -1, options, kTRUE);
6965 }
6966 fAutoSave = storeAutoSave;
6967 return GetEntries();
6968}
6969
6970////////////////////////////////////////////////////////////////////////////////
6971/// Move a cache from a file to the current file in dir.
6972/// if src is null no operation is done, if dir is null or there is no
6973/// current file the cache is deleted.
6976{
6977 if (!src) return;
6978 TFile *dst = (dir && dir != gROOT) ? dir->GetFile() : 0;
6979 if (src == dst) return;
6980
6982 if (dst) {
6983 src->SetCacheRead(0,this);
6984 dst->SetCacheRead(pf, this);
6985 } else {
6986 if (pf) {
6987 pf->WaitFinishPrefetch();
6988 }
6989 src->SetCacheRead(0,this);
6990 delete pf;
6991 }
6992}
6993
6994////////////////////////////////////////////////////////////////////////////////
6995/// Copy the content to a new new file, update this TTree with the new
6996/// location information and attach this TTree to the new directory.
6997///
6998/// options: Indicates a basket sorting method, see TTreeCloner::TTreeCloner for
6999/// details
7000///
7001/// If new and old directory are in the same file, the data is untouched,
7002/// this "just" does a call to SetDirectory.
7003/// Equivalent to an "in place" cloning of the TTree.
7004Bool_t TTree::InPlaceClone(TDirectory *newdirectory, const char *options)
7005{
7006 if (!newdirectory) {
7008 SetDirectory(nullptr);
7009 return true;
7010 }
7011 if (newdirectory->GetFile() == GetCurrentFile()) {
7012 SetDirectory(newdirectory);
7013 return true;
7014 }
7015 TTreeCloner cloner(this, newdirectory, options);
7016 if (cloner.IsValid())
7017 return cloner.Exec();
7018 else
7019 return false;
7020}
7021
7022////////////////////////////////////////////////////////////////////////////////
7023/// Function called when loading a new class library.
7026{
7027 TIter next(GetListOfLeaves());
7028 TLeaf* leaf = 0;
7029 while ((leaf = (TLeaf*) next())) {
7030 leaf->Notify();
7031 leaf->GetBranch()->Notify();
7032 }
7033 return kTRUE;
7034}
7035
7036////////////////////////////////////////////////////////////////////////////////
7037/// This function may be called after having filled some entries in a Tree.
7038/// Using the information in the existing branch buffers, it will reassign
7039/// new branch buffer sizes to optimize time and memory.
7040///
7041/// The function computes the best values for branch buffer sizes such that
7042/// the total buffer sizes is less than maxMemory and nearby entries written
7043/// at the same time.
7044/// In case the branch compression factor for the data written so far is less
7045/// than compMin, the compression is disabled.
7046///
7047/// if option ="d" an analysis report is printed.
7049void TTree::OptimizeBaskets(ULong64_t maxMemory, Float_t minComp, Option_t *option)
7050{
7051 //Flush existing baskets if the file is writable
7052 if (this->GetDirectory()->IsWritable()) this->FlushBasketsImpl();
7053
7054 TString opt( option );
7055 opt.ToLower();
7056 Bool_t pDebug = opt.Contains("d");
7057 TObjArray *leaves = this->GetListOfLeaves();
7058 Int_t nleaves = leaves->GetEntries();
7059 Double_t treeSize = (Double_t)this->GetTotBytes();
7060
7061 if (nleaves == 0 || treeSize == 0) {
7062 // We're being called too early, we really have nothing to do ...
7063 return;
7064 }
7065 Double_t aveSize = treeSize/nleaves;
7066 UInt_t bmin = 512;
7067 UInt_t bmax = 256000;
7068 Double_t memFactor = 1;
7069 Int_t i, oldMemsize,newMemsize,oldBaskets,newBaskets;
7070 i = oldMemsize = newMemsize = oldBaskets = newBaskets = 0;
7071
7072 //we make two passes
7073 //one pass to compute the relative branch buffer sizes
7074 //a second pass to compute the absolute values
7075 for (Int_t pass =0;pass<2;pass++) {
7076 oldMemsize = 0; //to count size of baskets in memory with old buffer size
7077 newMemsize = 0; //to count size of baskets in memory with new buffer size
7078 oldBaskets = 0; //to count number of baskets with old buffer size
7079 newBaskets = 0; //to count number of baskets with new buffer size
7080 for (i=0;i<nleaves;i++) {
7081 TLeaf *leaf = (TLeaf*)leaves->At(i);
7082 TBranch *branch = leaf->GetBranch();
7083 Double_t totBytes = (Double_t)branch->GetTotBytes();
7084 Double_t idealFactor = totBytes/aveSize;
7085 UInt_t sizeOfOneEntry;
7086 if (branch->GetEntries() == 0) {
7087 // There is no data, so let's make a guess ...
7088 sizeOfOneEntry = aveSize;
7089 } else {
7090 sizeOfOneEntry = 1+(UInt_t)(totBytes / (Double_t)branch->GetEntries());
7091 }
7092 Int_t oldBsize = branch->GetBasketSize();
7093 oldMemsize += oldBsize;
7094 oldBaskets += 1+Int_t(totBytes/oldBsize);
7095 Int_t nb = branch->GetListOfBranches()->GetEntries();
7096 if (nb > 0) {
7097 newBaskets += 1+Int_t(totBytes/oldBsize);
7098 continue;
7099 }
7100 Double_t bsize = oldBsize*idealFactor*memFactor; //bsize can be very large !
7101 if (bsize < 0) bsize = bmax;
7102 if (bsize > bmax) bsize = bmax;
7103 UInt_t newBsize = UInt_t(bsize);
7104 if (pass) { // only on the second pass so that it doesn't interfere with scaling
7105 // If there is an entry offset, it will be stored in the same buffer as the object data; hence,
7106 // we must bump up the size of the branch to account for this extra footprint.
7107 // If fAutoFlush is not set yet, let's assume that it is 'in the process of being set' to
7108 // the value of GetEntries().
7109 Long64_t clusterSize = (fAutoFlush > 0) ? fAutoFlush : branch->GetEntries();
7110 if (branch->GetEntryOffsetLen()) {
7111 newBsize = newBsize + (clusterSize * sizeof(Int_t) * 2);
7112 }
7113 // We used ATLAS fully-split xAOD for testing, which is a rather unbalanced TTree, 10K branches,
7114 // with 8K having baskets smaller than 512 bytes. To achieve good I/O performance ATLAS uses auto-flush 100,
7115 // resulting in the smallest baskets being ~300-400 bytes, so this change increases their memory by about 8k*150B =~ 1MB,
7116 // at the same time it significantly reduces the number of total baskets because it ensures that all 100 entries can be
7117 // stored in a single basket (the old optimization tended to make baskets too small). In a toy example with fixed sized
7118 // structures we found a factor of 2 fewer baskets needed in the new scheme.
7119 // rounds up, increases basket size to ensure all entries fit into single basket as intended
7120 newBsize = newBsize - newBsize%512 + 512;
7121 }
7122 if (newBsize < sizeOfOneEntry) newBsize = sizeOfOneEntry;
7123 if (newBsize < bmin) newBsize = bmin;
7124 if (newBsize > 10000000) newBsize = bmax;
7125 if (pass) {
7126 if (pDebug) Info("OptimizeBaskets", "Changing buffer size from %6d to %6d bytes for %s\n",oldBsize,newBsize,branch->GetName());
7127 branch->SetBasketSize(newBsize);
7128 }
7129 newMemsize += newBsize;
7130 // For this number to be somewhat accurate when newBsize is 'low'
7131 // we do not include any space for meta data in the requested size (newBsize) even-though SetBasketSize will
7132 // not let it be lower than 100+TBranch::fEntryOffsetLen.
7133 newBaskets += 1+Int_t(totBytes/newBsize);
7134 if (pass == 0) continue;
7135 //Reset the compression level in case the compression factor is small
7136 Double_t comp = 1;
7137 if (branch->GetZipBytes() > 0) comp = totBytes/Double_t(branch->GetZipBytes());
7138 if (comp > 1 && comp < minComp) {
7139 if (pDebug) Info("OptimizeBaskets", "Disabling compression for branch : %s\n",branch->GetName());
7141 }
7142 }
7143 // coverity[divide_by_zero] newMemsize can not be zero as there is at least one leaf
7144 memFactor = Double_t(maxMemory)/Double_t(newMemsize);
7145 if (memFactor > 100) memFactor = 100;
7146 Double_t bmin_new = bmin*memFactor;
7147 Double_t bmax_new = bmax*memFactor;
7148 static const UInt_t hardmax = 1*1024*1024*1024; // Really, really never give more than 1Gb to a single buffer.
7149
7150 // Really, really never go lower than 8 bytes (we use this number
7151 // so that the calculation of the number of basket is consistent
7152 // but in fact SetBasketSize will not let the size go below
7153 // TBranch::fEntryOffsetLen + (100 + strlen(branch->GetName())
7154 // (The 2nd part being a slight over estimate of the key length.
7155 static const UInt_t hardmin = 8;
7156 bmin = (bmin_new > hardmax) ? hardmax : ( bmin_new < hardmin ? hardmin : (UInt_t)bmin_new );
7157 bmax = (bmax_new > hardmax) ? bmin : (UInt_t)bmax_new;
7158 }
7159 if (pDebug) {
7160 Info("OptimizeBaskets", "oldMemsize = %d, newMemsize = %d\n",oldMemsize, newMemsize);
7161 Info("OptimizeBaskets", "oldBaskets = %d, newBaskets = %d\n",oldBaskets, newBaskets);
7162 }
7163}
7164
7165////////////////////////////////////////////////////////////////////////////////
7166/// Interface to the Principal Components Analysis class.
7167///
7168/// Create an instance of TPrincipal
7169///
7170/// Fill it with the selected variables
7171///
7172/// - if option "n" is specified, the TPrincipal object is filled with
7173/// normalized variables.
7174/// - If option "p" is specified, compute the principal components
7175/// - If option "p" and "d" print results of analysis
7176/// - If option "p" and "h" generate standard histograms
7177/// - If option "p" and "c" generate code of conversion functions
7178/// - return a pointer to the TPrincipal object. It is the user responsibility
7179/// - to delete this object.
7180/// - The option default value is "np"
7181///
7182/// see TTree::Draw for explanation of the other parameters.
7183///
7184/// The created object is named "principal" and a reference to it
7185/// is added to the list of specials Root objects.
7186/// you can retrieve a pointer to the created object via:
7187/// ~~~ {.cpp}
7188/// TPrincipal *principal =
7189/// (TPrincipal*)gROOT->GetListOfSpecials()->FindObject("principal");
7190/// ~~~
7192TPrincipal* TTree::Principal(const char* varexp, const char* selection, Option_t* option, Long64_t nentries, Long64_t firstentry)
7193{
7194 GetPlayer();
7195 if (fPlayer) {
7196 return fPlayer->Principal(varexp, selection, option, nentries, firstentry);
7197 }
7198 return 0;
7199}
7200
7201////////////////////////////////////////////////////////////////////////////////
7202/// Print a summary of the tree contents.
7203///
7204/// - If option contains "all" friend trees are also printed.
7205/// - If option contains "toponly" only the top level branches are printed.
7206/// - If option contains "clusters" information about the cluster of baskets is printed.
7207///
7208/// Wildcarding can be used to print only a subset of the branches, e.g.,
7209/// `T.Print("Elec*")` will print all branches with name starting with "Elec".
7211void TTree::Print(Option_t* option) const
7212{
7213 // We already have been visited while recursively looking
7214 // through the friends tree, let's return.
7215 if (kPrint & fFriendLockStatus) {
7216 return;
7217 }
7218 Int_t s = 0;
7219 Int_t skey = 0;
7220 if (fDirectory) {
7221 TKey* key = fDirectory->GetKey(GetName());
7222 if (key) {
7223 skey = key->GetKeylen();
7224 s = key->GetNbytes();
7225 }
7226 }
7227 Long64_t total = skey;
7228 Long64_t zipBytes = GetZipBytes();
7229 if (zipBytes > 0) {
7230 total += GetTotBytes();
7231 }
7233 TTree::Class()->WriteBuffer(b, (TTree*) this);
7234 total += b.Length();
7235 Long64_t file = zipBytes + s;
7236 Float_t cx = 1;
7237 if (zipBytes) {
7238 cx = (GetTotBytes() + 0.00001) / zipBytes;
7239 }
7240 Printf("******************************************************************************");
7241 Printf("*Tree :%-10s: %-54s *", GetName(), GetTitle());
7242 Printf("*Entries : %8lld : Total = %15lld bytes File Size = %10lld *", fEntries, total, file);
7243 Printf("* : : Tree compression factor = %6.2f *", cx);
7244 Printf("******************************************************************************");
7245
7246 // Avoid many check of option validity
7247 if (!option)
7248 option = "";
7249
7250 if (strncmp(option,"clusters",strlen("clusters"))==0) {
7251 Printf("%-16s %-16s %-16s %8s %20s",
7252 "Cluster Range #", "Entry Start", "Last Entry", "Size", "Number of clusters");
7253 Int_t index= 0;
7254 Long64_t clusterRangeStart = 0;
7255 Long64_t totalClusters = 0;
7256 bool estimated = false;
7257 bool unknown = false;
7258 auto printer = [this, &totalClusters, &estimated, &unknown](Int_t ind, Long64_t start, Long64_t end, Long64_t recordedSize) {
7259 Long64_t nclusters = 0;
7260 if (recordedSize > 0) {
7261 nclusters = (1 + end - start) / recordedSize;
7262 Printf("%-16d %-16lld %-16lld %8lld %10lld",
7263 ind, start, end, recordedSize, nclusters);
7264 } else {
7265 // NOTE: const_cast ... DO NOT Merge for now
7266 TClusterIterator iter((TTree*)this, start);
7267 iter.Next();
7268 auto estimated_size = iter.GetNextEntry() - start;
7269 if (estimated_size > 0) {
7270 nclusters = (1 + end - start) / estimated_size;
7271 Printf("%-16d %-16lld %-16lld %8lld %10lld (estimated)",
7272 ind, start, end, recordedSize, nclusters);
7273 estimated = true;
7274 } else {
7275 Printf("%-16d %-16lld %-16lld %8lld (unknown)",
7276 ind, start, end, recordedSize);
7277 unknown = true;
7278 }
7279 }
7280 start = end + 1;
7281 totalClusters += nclusters;
7282 };
7283 if (fNClusterRange) {
7284 for( ; index < fNClusterRange; ++index) {
7285 printer(index, clusterRangeStart, fClusterRangeEnd[index], fClusterSize[index]);
7286 clusterRangeStart = fClusterRangeEnd[index] + 1;
7287 }
7288 }
7289 printer(index, clusterRangeStart, fEntries - 1, fAutoFlush);
7290 if (unknown) {
7291 Printf("Total number of clusters: (unknown)");
7292 } else {
7293 Printf("Total number of clusters: %lld %s", totalClusters, estimated ? "(estimated)" : "");
7294 }
7295 return;
7296 }
7297
7298 Int_t nl = const_cast<TTree*>(this)->GetListOfLeaves()->GetEntries();
7299 Int_t l;
7300 TBranch* br = nullptr;
7301 TLeaf* leaf = nullptr;
7302 if (strstr(option, "toponly")) {
7303 Long64_t *count = new Long64_t[nl];
7304 Int_t keep =0;
7305 for (l=0;l<nl;l++) {
7306 leaf = (TLeaf *)const_cast<TTree*>(this)->GetListOfLeaves()->At(l);
7307 br = leaf->GetBranch();
7308 if (strchr(br->GetName(),'.')) {
7309 count[l] = -1;
7310 count[keep] += br->GetZipBytes();
7311 } else {
7312 keep = l;
7313 count[keep] = br->GetZipBytes();
7314 }
7315 }
7316 for (l=0;l<nl;l++) {
7317 if (count[l] < 0) continue;
7318 leaf = (TLeaf *)const_cast<TTree*>(this)->GetListOfLeaves()->At(l);
7319 br = leaf->GetBranch();
7320 Printf("branch: %-20s %9lld\n",br->GetName(),count[l]);
7321 }
7322 delete [] count;
7323 } else {
7324 TString reg = "*";
7325 if (strlen(option) && strchr(option,'*')) reg = option;
7326 TRegexp re(reg,kTRUE);
7327 TIter next(const_cast<TTree*>(this)->GetListOfBranches());
7329 while ((br= (TBranch*)next())) {
7330 TString st = br->GetName();
7331 st.ReplaceAll("/","_");
7332 if (st.Index(re) == kNPOS) continue;
7333 br->Print(option);
7334 }
7335 }
7336
7337 //print TRefTable (if one)
7339
7340 //print friends if option "all"
7341 if (!fFriends || !strstr(option,"all")) return;
7342 TIter nextf(fFriends);
7343 TFriendLock lock(const_cast<TTree*>(this),kPrint);
7344 TFriendElement *fr;
7345 while ((fr = (TFriendElement*)nextf())) {
7346 TTree * t = fr->GetTree();
7347 if (t) t->Print(option);
7348 }
7349}
7350
7351////////////////////////////////////////////////////////////////////////////////
7352/// Print statistics about the TreeCache for this tree.
7353/// Like:
7354/// ~~~ {.cpp}
7355/// ******TreeCache statistics for file: cms2.root ******
7356/// Reading 73921562 bytes in 716 transactions
7357/// Average transaction = 103.242405 Kbytes
7358/// Number of blocks in current cache: 202, total size : 6001193
7359/// ~~~
7360/// if option = "a" the list of blocks in the cache is printed
7363{
7364 TFile *f = GetCurrentFile();
7365 if (!f) return;
7366 TTreeCache *tc = GetReadCache(f);
7367 if (tc) tc->Print(option);
7368}
7369
7370////////////////////////////////////////////////////////////////////////////////
7371/// Process this tree executing the TSelector code in the specified filename.
7372/// The return value is -1 in case of error and TSelector::GetStatus() in
7373/// in case of success.
7374///
7375/// The code in filename is loaded (interpreted or compiled, see below),
7376/// filename must contain a valid class implementation derived from TSelector,
7377/// where TSelector has the following member functions:
7378///
7379/// - `Begin()`: called every time a loop on the tree starts,
7380/// a convenient place to create your histograms.
7381/// - `SlaveBegin()`: called after Begin(), when on PROOF called only on the
7382/// slave servers.
7383/// - `Process()`: called for each event, in this function you decide what
7384/// to read and fill your histograms.
7385/// - `SlaveTerminate`: called at the end of the loop on the tree, when on PROOF
7386/// called only on the slave servers.
7387/// - `Terminate()`: called at the end of the loop on the tree,
7388/// a convenient place to draw/fit your histograms.
7389///
7390/// If filename is of the form file.C, the file will be interpreted.
7391///
7392/// If filename is of the form file.C++, the file file.C will be compiled
7393/// and dynamically loaded.
7394///
7395/// If filename is of the form file.C+, the file file.C will be compiled
7396/// and dynamically loaded. At next call, if file.C is older than file.o
7397/// and file.so, the file.C is not compiled, only file.so is loaded.
7398///
7399/// ## NOTE1
7400///
7401/// It may be more interesting to invoke directly the other Process function
7402/// accepting a TSelector* as argument.eg
7403/// ~~~ {.cpp}
7404/// MySelector *selector = (MySelector*)TSelector::GetSelector(filename);
7405/// selector->CallSomeFunction(..);
7406/// mytree.Process(selector,..);
7407/// ~~~
7408/// ## NOTE2
7409//
7410/// One should not call this function twice with the same selector file
7411/// in the same script. If this is required, proceed as indicated in NOTE1,
7412/// by getting a pointer to the corresponding TSelector,eg
7413///
7414/// ### Workaround 1
7415///
7416/// ~~~ {.cpp}
7417/// void stubs1() {
7418/// TSelector *selector = TSelector::GetSelector("h1test.C");
7419/// TFile *f1 = new TFile("stubs_nood_le1.root");
7420/// TTree *h1 = (TTree*)f1->Get("h1");
7421/// h1->Process(selector);
7422/// TFile *f2 = new TFile("stubs_nood_le1_coarse.root");
7423/// TTree *h2 = (TTree*)f2->Get("h1");
7424/// h2->Process(selector);
7425/// }
7426/// ~~~
7427/// or use ACLIC to compile the selector
7428///
7429/// ### Workaround 2
7430///
7431/// ~~~ {.cpp}
7432/// void stubs2() {
7433/// TFile *f1 = new TFile("stubs_nood_le1.root");
7434/// TTree *h1 = (TTree*)f1->Get("h1");
7435/// h1->Process("h1test.C+");
7436/// TFile *f2 = new TFile("stubs_nood_le1_coarse.root");
7437/// TTree *h2 = (TTree*)f2->Get("h1");
7438/// h2->Process("h1test.C+");
7439/// }
7440/// ~~~
7443{
7444 GetPlayer();
7445 if (fPlayer) {
7446 return fPlayer->Process(filename, option, nentries, firstentry);
7447 }
7448 return -1;
7449}
7450
7451////////////////////////////////////////////////////////////////////////////////
7452/// Process this tree executing the code in the specified selector.
7453/// The return value is -1 in case of error and TSelector::GetStatus() in
7454/// in case of success.
7455///
7456/// The TSelector class has the following member functions:
7457///
7458/// - `Begin()`: called every time a loop on the tree starts,
7459/// a convenient place to create your histograms.
7460/// - `SlaveBegin()`: called after Begin(), when on PROOF called only on the
7461/// slave servers.
7462/// - `Process()`: called for each event, in this function you decide what
7463/// to read and fill your histograms.
7464/// - `SlaveTerminate`: called at the end of the loop on the tree, when on PROOF
7465/// called only on the slave servers.
7466/// - `Terminate()`: called at the end of the loop on the tree,
7467/// a convenient place to draw/fit your histograms.
7468///
7469/// If the Tree (Chain) has an associated EventList, the loop is on the nentries
7470/// of the EventList, starting at firstentry, otherwise the loop is on the
7471/// specified Tree entries.
7474{
7475 GetPlayer();
7476 if (fPlayer) {
7477 return fPlayer->Process(selector, option, nentries, firstentry);
7478 }
7479 return -1;
7480}
7481
7482////////////////////////////////////////////////////////////////////////////////
7483/// Make a projection of a tree using selections.
7484///
7485/// Depending on the value of varexp (described in Draw) a 1-D, 2-D, etc.,
7486/// projection of the tree will be filled in histogram hname.
7487/// Note that the dimension of hname must match with the dimension of varexp.
7488///
7490Long64_t TTree::Project(const char* hname, const char* varexp, const char* selection, Option_t* option, Long64_t nentries, Long64_t firstentry)
7491{
7492 TString var;
7493 var.Form("%s>>%s", varexp, hname);
7494 TString opt("goff");
7495 if (option) {
7496 opt.Form("%sgoff", option);
7497 }
7498 Long64_t nsel = Draw(var, selection, opt, nentries, firstentry);
7499 return nsel;
7500}
7501
7502////////////////////////////////////////////////////////////////////////////////
7503/// Loop over entries and return a TSQLResult object containing entries following selection.
7505TSQLResult* TTree::Query(const char* varexp, const char* selection, Option_t* option, Long64_t nentries, Long64_t firstentry)
7506{
7507 GetPlayer();
7508 if (fPlayer) {
7509 return fPlayer->Query(varexp, selection, option, nentries, firstentry);
7510 }
7511 return 0;
7512}
7513
7514////////////////////////////////////////////////////////////////////////////////
7515/// Create or simply read branches from filename.
7516///
7517/// if branchDescriptor = "" (default), it is assumed that the Tree descriptor
7518/// is given in the first line of the file with a syntax like
7519/// ~~~ {.cpp}
7520/// A/D:Table[2]/F:Ntracks/I:astring/C
7521/// ~~~
7522/// otherwise branchDescriptor must be specified with the above syntax.
7523///
7524/// - If the type of the first variable is not specified, it is assumed to be "/F"
7525/// - If the type of any other variable is not specified, the type of the previous
7526/// variable is assumed. eg
7527/// - `x:y:z` (all variables are assumed of type "F")
7528/// - `x/D:y:z` (all variables are of type "D")
7529/// - `x:y/D:z` (x is type "F", y and z of type "D")
7530///
7531/// delimiter allows for the use of another delimiter besides whitespace.
7532/// This provides support for direct import of common data file formats
7533/// like csv. If delimiter != ' ' and branchDescriptor == "", then the
7534/// branch description is taken from the first line in the file, but
7535/// delimiter is used for the branch names tokenization rather than ':'.
7536/// Note however that if the values in the first line do not use the
7537/// /[type] syntax, all variables are assumed to be of type "F".
7538/// If the filename ends with extensions .csv or .CSV and a delimiter is
7539/// not specified (besides ' '), the delimiter is automatically set to ','.
7540///
7541/// Lines in the input file starting with "#" are ignored. Leading whitespace
7542/// for each column data is skipped. Empty lines are skipped.
7543///
7544/// A TBranch object is created for each variable in the expression.
7545/// The total number of rows read from the file is returned.
7546///
7547/// ## FILLING a TTree WITH MULTIPLE INPUT TEXT FILES
7548///
7549/// To fill a TTree with multiple input text files, proceed as indicated above
7550/// for the first input file and omit the second argument for subsequent calls
7551/// ~~~ {.cpp}
7552/// T.ReadFile("file1.dat","branch descriptor");
7553/// T.ReadFile("file2.dat");
7554/// ~~~
7556Long64_t TTree::ReadFile(const char* filename, const char* branchDescriptor, char delimiter)
7557{
7558 if (!filename || !*filename) {
7559 Error("ReadFile","File name not specified");
7560 return 0;
7561 }
7562
7563 std::ifstream in;
7564 in.open(filename);
7565 if (!in.good()) {
7566 Error("ReadFile","Cannot open file: %s",filename);
7567 return 0;
7568 }
7569 const char* ext = strrchr(filename, '.');
7570 if(ext && ((strcmp(ext, ".csv") == 0) || (strcmp(ext, ".CSV") == 0)) && delimiter == ' ') {
7571 delimiter = ',';
7572 }
7573 return ReadStream(in, branchDescriptor, delimiter);
7574}
7575
7576////////////////////////////////////////////////////////////////////////////////
7577/// Determine which newline this file is using.
7578/// Return '\\r' for Windows '\\r\\n' as that already terminates.
7580char TTree::GetNewlineValue(std::istream &inputStream)
7581{
7582 Long_t inPos = inputStream.tellg();
7583 char newline = '\n';
7584 while(1) {
7585 char c = 0;
7586 inputStream.get(c);
7587 if(!inputStream.good()) {
7588 Error("ReadStream","Error reading stream: no newline found.");
7589 return 0;
7590 }
7591 if(c == newline) break;
7592 if(c == '\r') {
7593 newline = '\r';
7594 break;
7595 }
7596 }
7597 inputStream.clear();
7598 inputStream.seekg(inPos);
7599 return newline;
7600}
7601
7602////////////////////////////////////////////////////////////////////////////////
7603/// Create or simply read branches from an input stream.
7604///
7605/// \see reference information for TTree::ReadFile
7607Long64_t TTree::ReadStream(std::istream& inputStream, const char *branchDescriptor, char delimiter)
7608{
7609 char newline = 0;
7610 std::stringstream ss;
7611 std::istream *inTemp;
7612 Long_t inPos = inputStream.tellg();
7613 if (!inputStream.good()) {
7614 Error("ReadStream","Error reading stream");
7615 return 0;
7616 }
7617 if (inPos == -1) {
7618 ss << std::cin.rdbuf();
7619 newline = GetNewlineValue(ss);
7620 inTemp = &ss;
7621 } else {
7622 newline = GetNewlineValue(inputStream);
7623 inTemp = &inputStream;
7624 }
7625 std::istream& in = *inTemp;
7626 Long64_t nlines = 0;
7627
7628 TBranch *branch = 0;
7629 Int_t nbranches = fBranches.GetEntries();
7630 if (nbranches == 0) {
7631 char *bdname = new char[4000];
7632 char *bd = new char[100000];
7633 Int_t nch = 0;
7634 if (branchDescriptor) nch = strlen(branchDescriptor);
7635 // branch Descriptor is null, read its definition from the first line in the file
7636 if (!nch) {
7637 do {
7638 in.getline(bd, 100000, newline);
7639 if (!in.good()) {
7640 delete [] bdname;
7641 delete [] bd;
7642 Error("ReadStream","Error reading stream");
7643 return 0;
7644 }
7645 char *cursor = bd;
7646 while( isspace(*cursor) && *cursor != '\n' && *cursor != '\0') {
7647 ++cursor;
7648 }
7649 if (*cursor != '#' && *cursor != '\n' && *cursor != '\0') {
7650 break;
7651 }
7652 } while (true);
7653 ++nlines;
7654 nch = strlen(bd);
7655 } else {
7656 strlcpy(bd,branchDescriptor,100000);
7657 }
7658
7659 //parse the branch descriptor and create a branch for each element
7660 //separated by ":"
7661 void *address = &bd[90000];
7662 char *bdcur = bd;
7663 TString desc="", olddesc="F";
7664 char bdelim = ':';
7665 if(delimiter != ' ') {
7666 bdelim = delimiter;
7667 if (strchr(bdcur,bdelim)==0 && strchr(bdcur,':') != 0) {
7668 // revert to the default
7669 bdelim = ':';
7670 }
7671 }
7672 while (bdcur) {
7673 char *colon = strchr(bdcur,bdelim);
7674 if (colon) *colon = 0;
7675 strlcpy(bdname,bdcur,4000);
7676 char *slash = strchr(bdname,'/');
7677 if (slash) {
7678 *slash = 0;
7679 desc = bdcur;
7680 olddesc = slash+1;
7681 } else {
7682 desc.Form("%s/%s",bdname,olddesc.Data());
7683 }
7684 char *bracket = strchr(bdname,'[');
7685 if (bracket) {
7686 *bracket = 0;
7687 }
7688 branch = new TBranch(this,bdname,address,desc.Data(),32000);
7689 if (branch->IsZombie()) {
7690 delete branch;
7691 Warning("ReadStream","Illegal branch definition: %s",bdcur);
7692 } else {
7693 fBranches.Add(branch);
7694 branch->SetAddress(0);
7695 }
7696 if (!colon)break;
7697 bdcur = colon+1;
7698 }
7699 delete [] bdname;
7700 delete [] bd;
7701 }
7702
7703 nbranches = fBranches.GetEntries();
7704
7705 if (gDebug > 1) {
7706 Info("ReadStream", "Will use branches:");
7707 for (int i = 0 ; i < nbranches; ++i) {
7708 TBranch* br = (TBranch*) fBranches.At(i);
7709 Info("ReadStream", " %s: %s [%s]", br->GetName(),
7710 br->GetTitle(), br->GetListOfLeaves()->At(0)->IsA()->GetName());
7711 }
7712 if (gDebug > 3) {
7713 Info("ReadStream", "Dumping read tokens, format:");
7714 Info("ReadStream", "LLLLL:BBB:gfbe:GFBE:T");
7715 Info("ReadStream", " L: line number");
7716 Info("ReadStream", " B: branch number");
7717 Info("ReadStream", " gfbe: good / fail / bad / eof of token");
7718 Info("ReadStream", " GFBE: good / fail / bad / eof of file");
7719 Info("ReadStream", " T: Token being read");
7720 }
7721 }
7722
7723 //loop on all lines in the file
7724 Long64_t nGoodLines = 0;
7725 std::string line;
7726 const char sDelimBuf[2] = { delimiter, 0 };
7727 const char* sDelim = sDelimBuf;
7728 if (delimiter == ' ') {
7729 // ' ' really means whitespace
7730 sDelim = "[ \t]";
7731 }
7732 while(in.good()) {
7733 if (newline == '\r' && in.peek() == '\n') {
7734 // Windows, skip '\n':
7735 in.get();
7736 }
7737 std::getline(in, line, newline);
7738 ++nlines;
7739
7740 TString sLine(line);
7741 sLine = sLine.Strip(TString::kLeading); // skip leading whitespace
7742 if (sLine.IsNull()) {
7743 if (gDebug > 2) {
7744 Info("ReadStream", "Skipping empty line number %lld", nlines);
7745 }
7746 continue; // silently skip empty lines
7747 }
7748 if (sLine[0] == '#') {
7749 if (gDebug > 2) {
7750 Info("ReadStream", "Skipping comment line number %lld: '%s'",
7751 nlines, line.c_str());
7752 }
7753 continue;
7754 }
7755 if (gDebug > 2) {
7756 Info("ReadStream", "Parsing line number %lld: '%s'",
7757 nlines, line.c_str());
7758 }
7759
7760 // Loop on branches and read the branch values into their buffer
7761 branch = 0;
7762 TString tok; // one column's data
7763 TString leafData; // leaf data, possibly multiple tokens for e.g. /I[2]
7764 std::stringstream sToken; // string stream feeding leafData into leaves
7765 Ssiz_t pos = 0;
7766 Int_t iBranch = 0;
7767 Bool_t goodLine = kTRUE; // whether the row can be filled into the tree
7768 Int_t remainingLeafLen = 0; // remaining columns for the current leaf
7769 while (goodLine && iBranch < nbranches
7770 && sLine.Tokenize(tok, pos, sDelim)) {
7771 tok = tok.Strip(TString::kLeading); // skip leading whitespace
7772 if (tok.IsNull() && delimiter == ' ') {
7773 // 1 2 should not be interpreted as 1,,,2 but 1, 2.
7774 // Thus continue until we have a non-empty token.
7775 continue;
7776 }
7777
7778 if (!remainingLeafLen) {
7779 // next branch!
7780 branch = (TBranch*)fBranches.At(iBranch);
7781 }
7782 TLeaf *leaf = (TLeaf*)branch->GetListOfLeaves()->At(0);
7783 if (!remainingLeafLen) {
7784 remainingLeafLen = leaf->GetLen();
7785 if (leaf->GetMaximum() > 0) {
7786 // This is a dynamic leaf length, i.e. most likely a TLeafC's
7787 // string size. This still translates into one token:
7788 remainingLeafLen = 1;
7789 }
7790
7791 leafData = tok;
7792 } else {
7793 // append token to laf data:
7794 leafData += " ";
7795 leafData += tok;
7796 }
7797 --remainingLeafLen;
7798 if (remainingLeafLen) {
7799 // need more columns for this branch:
7800 continue;
7801 }
7802 ++iBranch;
7803
7804 // initialize stringstream with token
7805 sToken.clear();
7806 sToken.seekp(0, std::ios_base::beg);
7807 sToken.str(leafData.Data());
7808 sToken.seekg(0, std::ios_base::beg);
7809 leaf->ReadValue(sToken, 0 /* 0 = "all" */);
7810 if (gDebug > 3) {
7811 Info("ReadStream", "%5lld:%3d:%d%d%d%d:%d%d%d%d:%s",
7812 nlines, iBranch,
7813 (int)sToken.good(), (int)sToken.fail(),
7814 (int)sToken.bad(), (int)sToken.eof(),
7815 (int)in.good(), (int)in.fail(),
7816 (int)in.bad(), (int)in.eof(),
7817 sToken.str().c_str());
7818 }
7819
7820 // Error handling
7821 if (sToken.bad()) {
7822 // How could that happen for a stringstream?
7823 Warning("ReadStream",
7824 "Buffer error while reading data for branch %s on line %lld",
7825 branch->GetName(), nlines);
7826 } else if (!sToken.eof()) {
7827 if (sToken.fail()) {
7828 Warning("ReadStream",
7829 "Couldn't read formatted data in \"%s\" for branch %s on line %lld; ignoring line",
7830 tok.Data(), branch->GetName(), nlines);
7831 goodLine = kFALSE;
7832 } else {
7833 std::string remainder;
7834 std::getline(sToken, remainder, newline);
7835 if (!remainder.empty()) {
7836 Warning("ReadStream",
7837 "Ignoring trailing \"%s\" while reading data for branch %s on line %lld",
7838 remainder.c_str(), branch->GetName(), nlines);
7839 }
7840 }
7841 }
7842 } // tokenizer loop
7843
7844 if (iBranch < nbranches) {
7845 Warning("ReadStream",
7846 "Read too few columns (%d < %d) in line %lld; ignoring line",
7847 iBranch, nbranches, nlines);
7848 goodLine = kFALSE;
7849 } else if (pos != kNPOS) {
7850 sLine = sLine.Strip(TString::kTrailing);
7851 if (pos < sLine.Length()) {
7852 Warning("ReadStream",
7853 "Ignoring trailing \"%s\" while reading line %lld",
7854 sLine.Data() + pos - 1 /* also print delimiter */,
7855 nlines);
7856 }
7857 }
7858
7859 //we are now ready to fill the tree
7860 if (goodLine) {
7861 Fill();
7862 ++nGoodLines;
7863 }
7864 }
7865
7866 return nGoodLines;
7867}
7868
7869////////////////////////////////////////////////////////////////////////////////
7870/// Make sure that obj (which is being deleted or will soon be) is no
7871/// longer referenced by this TTree.
7874{
7875 if (obj == fEventList) {
7876 fEventList = nullptr;
7877 }
7878 if (obj == fEntryList) {
7879 fEntryList = nullptr;
7880 }
7881 if (fUserInfo) {
7883 }
7884 if (fPlayer == obj) {
7885 fPlayer = nullptr;
7886 }
7887 if (fTreeIndex == obj) {
7888 fTreeIndex = nullptr;
7889 }
7890 if (fAliases == obj) {
7891 fAliases = nullptr;
7892 } else if (fAliases) {
7894 }
7895 if (fFriends == obj) {
7896 fFriends = nullptr;
7897 } else if (fFriends) {
7899 }
7900}
7901
7902////////////////////////////////////////////////////////////////////////////////
7903/// Refresh contents of this tree and its branches from the current status on disk.
7904///
7905/// One can call this function in case the tree file is being
7906/// updated by another process.
7908void TTree::Refresh()
7909{
7910 if (!fDirectory->GetFile()) {
7911 return;
7912 }
7914 fDirectory->Remove(this);
7916 if (!tree) {
7917 return;
7918 }
7919 //copy info from tree header into this Tree
7920 fEntries = 0;
7921 fNClusterRange = 0;
7923
7924 fAutoSave = tree->fAutoSave;
7925 fEntries = tree->fEntries;
7926 fTotBytes = tree->GetTotBytes();
7927 fZipBytes = tree->GetZipBytes();
7928 fSavedBytes = tree->fSavedBytes;
7929 fTotalBuffers = tree->fTotalBuffers.load();
7930
7931 //loop on all branches and update them
7932 Int_t nleaves = fLeaves.GetEntriesFast();
7933 for (Int_t i = 0; i < nleaves; i++) {
7934 TLeaf* leaf = (TLeaf*) fLeaves.UncheckedAt(i);
7935 TBranch* branch = (TBranch*) leaf->GetBranch();
7936 branch->Refresh(tree->GetBranch(branch->GetName()));
7937 }
7939 fDirectory->Append(this);
7940 delete tree;
7941 tree = 0;
7942}
7943
7944////////////////////////////////////////////////////////////////////////////////
7945/// Record a TFriendElement that we need to warn when the chain switches to
7946/// a new file (typically this is because this chain is a friend of another
7947/// TChain)
7950{
7951 if (!fExternalFriends)
7952 fExternalFriends = new TList();
7953 fExternalFriends->Add(fe);
7954}
7955
7956
7957////////////////////////////////////////////////////////////////////////////////
7958/// Removes external friend
7961{
7963}
7964
7965
7966////////////////////////////////////////////////////////////////////////////////
7967/// Remove a friend from the list of friends.
7969void TTree::RemoveFriend(TTree* oldFriend)
7970{
7971 // We already have been visited while recursively looking
7972 // through the friends tree, let return
7974 return;
7975 }
7976 if (!fFriends) {
7977 return;
7978 }
7979 TFriendLock lock(this, kRemoveFriend);
7980 TIter nextf(fFriends);
7981 TFriendElement* fe = 0;
7982 while ((fe = (TFriendElement*) nextf())) {
7983 TTree* friend_t = fe->GetTree();
7984 if (friend_t == oldFriend) {
7985 fFriends->Remove(fe);
7986 delete fe;
7987 fe = 0;
7988 }
7989 }
7990}
7991
7992////////////////////////////////////////////////////////////////////////////////
7993/// Reset baskets, buffers and entries count in all branches and leaves.
7996{
7997 fNotify = 0;
7998 fEntries = 0;
7999 fNClusterRange = 0;
8000 fTotBytes = 0;
8001 fZipBytes = 0;
8002 fFlushedBytes = 0;
8003 fSavedBytes = 0;
8004 fTotalBuffers = 0;
8005 fChainOffset = 0;
8006 fReadEntry = -1;
8007
8008 delete fTreeIndex;
8009 fTreeIndex = 0;
8010
8012 for (Int_t i = 0; i < nb; ++i) {
8013 TBranch* branch = (TBranch*) fBranches.UncheckedAt(i);
8014 branch->Reset(option);
8015 }
8016
8017 if (fBranchRef) {
8018 fBranchRef->Reset();
8019 }
8020}
8021
8022////////////////////////////////////////////////////////////////////////////////
8023/// Resets the state of this TTree after a merge (keep the customization but
8024/// forget the data).
8027{
8028 fEntries = 0;
8029 fNClusterRange = 0;
8030 fTotBytes = 0;
8031 fZipBytes = 0;
8032 fSavedBytes = 0;
8033 fFlushedBytes = 0;
8034 fTotalBuffers = 0;
8035 fChainOffset = 0;
8036 fReadEntry = -1;
8037
8038 delete fTreeIndex;
8039 fTreeIndex = 0;
8040
8042 for (Int_t i = 0; i < nb; ++i) {
8043 TBranch* branch = (TBranch*) fBranches.UncheckedAt(i);
8044 branch->ResetAfterMerge(info);
8045 }
8046
8047 if (fBranchRef) {
8049 }
8050}
8051
8052////////////////////////////////////////////////////////////////////////////////
8053/// Tell all of our branches to set their addresses to zero.
8054///
8055/// Note: If any of our branches own any objects, they are deleted.
8058{
8059 if (br && br->GetTree()) {
8060 br->ResetAddress();
8061 }
8062}
8063
8064////////////////////////////////////////////////////////////////////////////////
8065/// Tell all of our branches to drop their current objects and allocate new ones.
8068{
8069 TObjArray* branches = GetListOfBranches();
8070 Int_t nbranches = branches->GetEntriesFast();
8071 for (Int_t i = 0; i < nbranches; ++i) {
8072 TBranch* branch = (TBranch*) branches->UncheckedAt(i);
8073 branch->ResetAddress();
8074 }
8075}
8076
8077////////////////////////////////////////////////////////////////////////////////
8078/// Loop over tree entries and print entries passing selection.
8079///
8080/// - If varexp is 0 (or "") then print only first 8 columns.
8081/// - If varexp = "*" print all columns.
8082///
8083/// Otherwise a columns selection can be made using "var1:var2:var3".
8084/// \see TTreePlayer::Scan for more information
8086Long64_t TTree::Scan(const char* varexp, const char* selection, Option_t* option, Long64_t nentries, Long64_t firstentry)
8087{
8088 GetPlayer();
8089 if (fPlayer) {
8090 return fPlayer->Scan(varexp, selection, option, nentries, firstentry);
8091 }
8092 return -1;
8093}
8094
8095////////////////////////////////////////////////////////////////////////////////
8096/// Set a tree variable alias.
8097///
8098/// Set an alias for an expression/formula based on the tree 'variables'.
8099///
8100/// The content of 'aliasName' can be used in TTreeFormula (i.e. TTree::Draw,
8101/// TTree::Scan, TTreeViewer) and will be evaluated as the content of
8102/// 'aliasFormula'.
8103///
8104/// If the content of 'aliasFormula' only contains symbol names, periods and
8105/// array index specification (for example event.fTracks[3]), then
8106/// the content of 'aliasName' can be used as the start of symbol.
8107///
8108/// If the alias 'aliasName' already existed, it is replaced by the new
8109/// value.
8110///
8111/// When being used, the alias can be preceded by an eventual 'Friend Alias'
8112/// (see TTree::GetFriendAlias)
8113///
8114/// Return true if it was added properly.
8115///
8116/// For example:
8117/// ~~~ {.cpp}
8118/// tree->SetAlias("x1","(tdc1[1]-tdc1[0])/49");
8119/// tree->SetAlias("y1","(tdc1[3]-tdc1[2])/47");
8120/// tree->SetAlias("x2","(tdc2[1]-tdc2[0])/49");
8121/// tree->SetAlias("y2","(tdc2[3]-tdc2[2])/47");
8122/// tree->Draw("y2-y1:x2-x1");
8123///
8124/// tree->SetAlias("theGoodTrack","event.fTracks[3]");
8125/// tree->Draw("theGoodTrack.fPx"); // same as "event.fTracks[3].fPx"
8126/// ~~~
8128Bool_t TTree::SetAlias(const char* aliasName, const char* aliasFormula)
8129{
8130 if (!aliasName || !aliasFormula) {
8131 return kFALSE;
8132 }
8133 if (!aliasName[0] || !aliasFormula[0]) {
8134 return kFALSE;
8135 }
8136 if (!fAliases) {
8137 fAliases = new TList;
8138 } else {
8139 TNamed* oldHolder = (TNamed*) fAliases->FindObject(aliasName);
8140 if (oldHolder) {
8141 oldHolder->SetTitle(aliasFormula);
8142 return kTRUE;
8143 }
8144 }
8145 TNamed* holder = new TNamed(aliasName, aliasFormula);
8146 fAliases->Add(holder);
8147 return kTRUE;
8148}
8149
8150////////////////////////////////////////////////////////////////////////////////
8151/// This function may be called at the start of a program to change
8152/// the default value for fAutoFlush.
8153///
8154/// ### CASE 1 : autof > 0
8155///
8156/// autof is the number of consecutive entries after which TTree::Fill will
8157/// flush all branch buffers to disk.
8158///
8159/// ### CASE 2 : autof < 0
8160///
8161/// When filling the Tree the branch buffers will be flushed to disk when
8162/// more than autof bytes have been written to the file. At the first FlushBaskets
8163/// TTree::Fill will replace fAutoFlush by the current value of fEntries.
8164///
8165/// Calling this function with autof<0 is interesting when it is hard to estimate
8166/// the size of one entry. This value is also independent of the Tree.
8167///
8168/// The Tree is initialized with fAutoFlush=-30000000, ie that, by default,
8169/// the first AutoFlush will be done when 30 MBytes of data are written to the file.
8170///
8171/// ### CASE 3 : autof = 0
8172///
8173/// The AutoFlush mechanism is disabled.
8174///
8175/// Flushing the buffers at regular intervals optimize the location of
8176/// consecutive entries on the disk by creating clusters of baskets.
8177///
8178/// A cluster of baskets is a set of baskets that contains all
8179/// the data for a (consecutive) set of entries and that is stored
8180/// consecutively on the disk. When reading all the branches, this
8181/// is the minimum set of baskets that the TTreeCache will read.
8183void TTree::SetAutoFlush(Long64_t autof /* = -30000000 */ )
8184{
8185 // Implementation note:
8186 //
8187 // A positive value of autoflush determines the size (in number of entries) of
8188 // a cluster of baskets.
8189 //
8190 // If the value of autoflush is changed over time (this happens in
8191 // particular when the TTree results from fast merging many trees),
8192 // we record the values of fAutoFlush in the data members:
8193 // fClusterRangeEnd and fClusterSize.
8194 // In the code we refer to a range of entries where the size of the
8195 // cluster of baskets is the same (i.e the value of AutoFlush was
8196 // constant) is called a ClusterRange.
8197 //
8198 // The 2 arrays (fClusterRangeEnd and fClusterSize) have fNClusterRange
8199 // active (used) values and have fMaxClusterRange allocated entries.
8200 //
8201 // fClusterRangeEnd contains the last entries number of a cluster range.
8202 // In particular this means that the 'next' cluster starts at fClusterRangeEnd[]+1
8203 // fClusterSize contains the size in number of entries of all the cluster
8204 // within the given range.
8205 // The last range (and the only one if fNClusterRange is zero) start at
8206 // fNClusterRange[fNClusterRange-1]+1 and ends at the end of the TTree. The
8207 // size of the cluster in this range is given by the value of fAutoFlush.
8208 //
8209 // For example printing the beginning and end of each the ranges can be done by:
8210 //
8211 // Printf("%-16s %-16s %-16s %5s",
8212 // "Cluster Range #", "Entry Start", "Last Entry", "Size");
8213 // Int_t index= 0;
8214 // Long64_t clusterRangeStart = 0;
8215 // if (fNClusterRange) {
8216 // for( ; index < fNClusterRange; ++index) {
8217 // Printf("%-16d %-16lld %-16lld %5lld",
8218 // index, clusterRangeStart, fClusterRangeEnd[index], fClusterSize[index]);
8219 // clusterRangeStart = fClusterRangeEnd[index] + 1;
8220 // }
8221 // }
8222 // Printf("%-16d %-16lld %-16lld %5lld",
8223 // index, prevEntry, fEntries - 1, fAutoFlush);
8224 //
8225
8226 // Note: We store the entry number corresponding to the end of the cluster
8227 // rather than its start in order to avoid using the array if the cluster
8228 // size never varies (If there is only one value of AutoFlush for the whole TTree).
8229
8230 if( fAutoFlush != autof) {
8231 if ((fAutoFlush > 0 || autof > 0) && fFlushedBytes) {
8232 // The mechanism was already enabled, let's record the previous
8233 // cluster if needed.
8235 }
8236 fAutoFlush = autof;
8237 }
8238}
8239
8240////////////////////////////////////////////////////////////////////////////////
8241/// Mark the previous event as being at the end of the event cluster.
8242///
8243/// So, if fEntries is set to 10 (and this is the first cluster) when MarkEventCluster
8244/// is called, then the first cluster has 9 events.
8246{
8247 if (!fEntries) return;
8248
8249 if ( (fNClusterRange+1) > fMaxClusterRange ) {
8250 if (fMaxClusterRange) {
8251 // Resize arrays to hold a larger event cluster.
8252 Int_t newsize = TMath::Max(10,Int_t(2*fMaxClusterRange));
8254 newsize*sizeof(Long64_t),fMaxClusterRange*sizeof(Long64_t));
8256 newsize*sizeof(Long64_t),fMaxClusterRange*sizeof(Long64_t));
8257 fMaxClusterRange = newsize;
8258 } else {
8259 // Cluster ranges have never been initialized; create them now.
8260 fMaxClusterRange = 2;
8263 }
8264 }
8266 // If we are auto-flushing, then the cluster size is the same as the current auto-flush setting.
8267 if (fAutoFlush > 0) {
8268 // Even if the user triggers MarkEventRange prior to fAutoFlush being present, the TClusterIterator
8269 // will appropriately go to the next event range.
8271 // Otherwise, assume there is one cluster per event range (e.g., user is manually controlling the flush).
8272 } else if (fNClusterRange == 0) {
8274 } else {
8276 }
8278}
8279
8280/// Estimate the median cluster size for the TTree.
8281/// This value provides e.g. a reasonable cache size default if other heuristics fail.
8282/// Clusters with size 0 and the very last cluster range, that might not have been committed to fClusterSize yet,
8283/// are ignored for the purposes of the calculation.
8285{
8286 std::vector<Long64_t> clusterSizesPerRange;
8287 clusterSizesPerRange.reserve(fNClusterRange);
8288
8289 // We ignore cluster sizes of 0 for the purposes of this function.
8290 // We also ignore the very last cluster range which might not have been committed to fClusterSize.
8291 std::copy_if(fClusterSize, fClusterSize + fNClusterRange, std::back_inserter(clusterSizesPerRange),
8292 [](Long64_t size) { return size != 0; });
8293
8294 std::vector<double> nClustersInRange; // we need to store doubles because of the signature of TMath::Median
8295 nClustersInRange.reserve(clusterSizesPerRange.size());
8296
8297 auto clusterRangeStart = 0ll;
8298 for (int i = 0; i < fNClusterRange; ++i) {
8299 const auto size = fClusterSize[i];
8300 R__ASSERT(size >= 0);
8301 if (fClusterSize[i] == 0)
8302 continue;
8303 const auto nClusters = (1 + fClusterRangeEnd[i] - clusterRangeStart) / fClusterSize[i];
8304 nClustersInRange.emplace_back(nClusters);
8305 clusterRangeStart = fClusterRangeEnd[i] + 1;
8306 }
8307
8308 R__ASSERT(nClustersInRange.size() == clusterSizesPerRange.size());
8309 const auto medianClusterSize =
8310 TMath::Median(nClustersInRange.size(), clusterSizesPerRange.data(), nClustersInRange.data());
8311 return medianClusterSize;
8312}
8313
8314////////////////////////////////////////////////////////////////////////////////
8315/// In case of a program crash, it will be possible to recover the data in the
8316/// tree up to the last AutoSave point.
8317/// This function may be called before filling a TTree to specify when the
8318/// branch buffers and TTree header are flushed to disk as part of
8319/// TTree::Fill().
8320/// The default is -300000000, ie the TTree will write data to disk once it
8321/// exceeds 300 MBytes.
8322/// CASE 1: If fAutoSave is positive the watermark is reached when a multiple of
8323/// fAutoSave entries have been filled.
8324/// CASE 2: If fAutoSave is negative the watermark is reached when -fAutoSave
8325/// bytes can be written to the file.
8326/// CASE 3: If fAutoSave is 0, AutoSave() will never be called automatically
8327/// as part of TTree::Fill().
8329void TTree::SetAutoSave(Long64_t autos)
8330{
8331 fAutoSave = autos;
8332}
8333
8334////////////////////////////////////////////////////////////////////////////////
8335/// Set a branch's basket size.
8336///
8337/// bname is the name of a branch.
8338///
8339/// - if bname="*", apply to all branches.
8340/// - if bname="xxx*", apply to all branches with name starting with xxx
8341///
8342/// see TRegexp for wildcarding options
8343/// buffsize = branc basket size
8345void TTree::SetBasketSize(const char* bname, Int_t buffsize)
8346{
8347 Int_t nleaves = fLeaves.GetEntriesFast();
8348 TRegexp re(bname, kTRUE);
8349 Int_t nb = 0;
8350 for (Int_t i = 0; i < nleaves; i++) {
8351 TLeaf* leaf = (TLeaf*) fLeaves.UncheckedAt(i);
8352 TBranch* branch = (TBranch*) leaf->GetBranch();
8353 TString s = branch->GetName();
8354 if (strcmp(bname, branch->GetName()) && (s.Index(re) == kNPOS)) {
8355 continue;
8356 }
8357 nb++;
8358 branch->SetBasketSize(buffsize);
8359 }
8360 if (!nb) {
8361 Error("SetBasketSize", "unknown branch -> '%s'", bname);
8362 }
8363}
8364
8365////////////////////////////////////////////////////////////////////////////////
8366/// Change branch address, dealing with clone trees properly.
8367/// See TTree::CheckBranchAddressType for the semantic of the return value.
8368///
8369/// Note: See the comments in TBranchElement::SetAddress() for the
8370/// meaning of the addr parameter and the object ownership policy.
8372Int_t TTree::SetBranchAddress(const char* bname, void* addr, TBranch** ptr)
8373{
8374 TBranch* branch = GetBranch(bname);
8375 if (!branch) {
8376 if (ptr) *ptr = 0;
8377 Error("SetBranchAddress", "unknown branch -> %s", bname);
8378 return kMissingBranch;
8379 }
8380 return SetBranchAddressImp(branch,addr,ptr);
8381}
8382
8383////////////////////////////////////////////////////////////////////////////////
8384/// Verify the validity of the type of addr before calling SetBranchAddress.
8385/// See TTree::CheckBranchAddressType for the semantic of the return value.
8386///
8387/// Note: See the comments in TBranchElement::SetAddress() for the
8388/// meaning of the addr parameter and the object ownership policy.
8390Int_t TTree::SetBranchAddress(const char* bname, void* addr, TClass* ptrClass, EDataType datatype, Bool_t isptr)
8391{
8392 return SetBranchAddress(bname, addr, 0, ptrClass, datatype, isptr);
8393}
8394
8395////////////////////////////////////////////////////////////////////////////////
8396/// Verify the validity of the type of addr before calling SetBranchAddress.
8397/// See TTree::CheckBranchAddressType for the semantic of the return value.
8398///
8399/// Note: See the comments in TBranchElement::SetAddress() for the
8400/// meaning of the addr parameter and the object ownership policy.
8402Int_t TTree::SetBranchAddress(const char* bname, void* addr, TBranch** ptr, TClass* ptrClass, EDataType datatype, Bool_t isptr)
8403{
8404 TBranch* branch = GetBranch(bname);
8405 if (!branch) {
8406 if (ptr) *ptr = 0;
8407 Error("SetBranchAddress", "unknown branch -> %s", bname);
8408 return kMissingBranch;
8409 }
8410
8411 Int_t res = CheckBranchAddressType(branch, ptrClass, datatype, isptr);
8412
8413 // This will set the value of *ptr to branch.
8414 if (res >= 0) {
8415 // The check succeeded.
8416 if ((res & kNeedEnableDecomposedObj) && !branch->GetMakeClass())
8417 branch->SetMakeClass(kTRUE);
8418 SetBranchAddressImp(branch,addr,ptr);
8419 } else {
8420 if (ptr) *ptr = 0;
8421 }
8422 return res;
8423}
8424
8425////////////////////////////////////////////////////////////////////////////////
8426/// Change branch address, dealing with clone trees properly.
8427/// See TTree::CheckBranchAddressType for the semantic of the return value.
8428///
8429/// Note: See the comments in TBranchElement::SetAddress() for the
8430/// meaning of the addr parameter and the object ownership policy.
8432Int_t TTree::SetBranchAddressImp(TBranch *branch, void* addr, TBranch** ptr)
8433{
8434 if (ptr) {
8435 *ptr = branch;
8436 }
8437 if (fClones) {
8438 void* oldAddr = branch->GetAddress();
8439 TIter next(fClones);
8440 TTree* clone = 0;
8441 const char *bname = branch->GetName();
8442 while ((clone = (TTree*) next())) {
8443 TBranch* cloneBr = clone->GetBranch(bname);
8444 if (cloneBr && (cloneBr->GetAddress() == oldAddr)) {
8445 cloneBr->SetAddress(addr);
8446 }
8447 }
8448 }
8449 branch->SetAddress(addr);
8450 return kVoidPtr;
8451}
8452
8453////////////////////////////////////////////////////////////////////////////////
8454/// Set branch status to Process or DoNotProcess.
8455///
8456/// When reading a Tree, by default, all branches are read.
8457/// One can speed up considerably the analysis phase by activating
8458/// only the branches that hold variables involved in a query.
8459///
8460/// bname is the name of a branch.
8461///
8462/// - if bname="*", apply to all branches.
8463/// - if bname="xxx*", apply to all branches with name starting with xxx
8464///
8465/// see TRegexp for wildcarding options
8466///
8467/// - status = 1 branch will be processed
8468/// - = 0 branch will not be processed
8469///
8470/// Example:
8471///
8472/// Assume a tree T with sub-branches a,b,c,d,e,f,g,etc..
8473/// when doing T.GetEntry(i) all branches are read for entry i.
8474/// to read only the branches c and e, one can do
8475/// ~~~ {.cpp}
8476/// T.SetBranchStatus("*",0); //disable all branches
8477/// T.SetBranchStatus("c",1);
8478/// T.setBranchStatus("e",1);
8479/// T.GetEntry(i);
8480/// ~~~
8481/// bname is interpreted as a wild-carded TRegexp (see TRegexp::MakeWildcard).
8482/// Thus, "a*b" or "a.*b" matches branches starting with "a" and ending with
8483/// "b", but not any other branch with an "a" followed at some point by a
8484/// "b". For this second behavior, use "*a*b*". Note that TRegExp does not
8485/// support '|', and so you cannot select, e.g. track and shower branches
8486/// with "track|shower".
8487///
8488/// __WARNING! WARNING! WARNING!__
8489///
8490/// SetBranchStatus is matching the branch based on match of the branch
8491/// 'name' and not on the branch hierarchy! In order to be able to
8492/// selectively enable a top level object that is 'split' you need to make
8493/// sure the name of the top level branch is prefixed to the sub-branches'
8494/// name (by adding a dot ('.') at the end of the Branch creation and use the
8495/// corresponding bname.
8496///
8497/// I.e If your Tree has been created in split mode with a parent branch "parent."
8498/// (note the trailing dot).
8499/// ~~~ {.cpp}
8500/// T.SetBranchStatus("parent",1);
8501/// ~~~
8502/// will not activate the sub-branches of "parent". You should do:
8503/// ~~~ {.cpp}
8504/// T.SetBranchStatus("parent*",1);
8505/// ~~~
8506/// Without the trailing dot in the branch creation you have no choice but to
8507/// call SetBranchStatus explicitly for each of the sub branches.
8508///
8509/// An alternative to this function is to read directly and only
8510/// the interesting branches. Example:
8511/// ~~~ {.cpp}
8512/// TBranch *brc = T.GetBranch("c");
8513/// TBranch *bre = T.GetBranch("e");
8514/// brc->GetEntry(i);
8515/// bre->GetEntry(i);
8516/// ~~~
8517/// If found is not 0, the number of branch(es) found matching the regular
8518/// expression is returned in *found AND the error message 'unknown branch'
8519/// is suppressed.
8521void TTree::SetBranchStatus(const char* bname, Bool_t status, UInt_t* found)
8522{
8523 // We already have been visited while recursively looking
8524 // through the friends tree, let return
8526 return;
8527 }
8528
8529 if (!bname || !*bname) {
8530 Error("SetBranchStatus", "Input regexp is an empty string: no match against branch names will be attempted.");
8531 return;
8532 }
8533
8534 TBranch *branch, *bcount, *bson;
8535 TLeaf *leaf, *leafcount;
8536
8537 Int_t i,j;
8538 Int_t nleaves = fLeaves.GetEntriesFast();
8539 TRegexp re(bname,kTRUE);
8540 Int_t nb = 0;
8541
8542 // first pass, loop on all branches
8543 // for leafcount branches activate/deactivate in function of status
8544 for (i=0;i<nleaves;i++) {
8545 leaf = (TLeaf*)fLeaves.UncheckedAt(i);
8546 branch = (TBranch*)leaf->GetBranch();
8547 TString s = branch->GetName();
8548 if (strcmp(bname,"*")) { //Regexp gives wrong result for [] in name
8549 TString longname;
8550 longname.Form("%s.%s",GetName(),branch->GetName());
8551 if (strcmp(bname,branch->GetName())
8552 && longname != bname
8553 && s.Index(re) == kNPOS) continue;
8554 }
8555 nb++;
8556 if (status) branch->ResetBit(kDoNotProcess);
8557 else branch->SetBit(kDoNotProcess);
8558 leafcount = leaf->GetLeafCount();
8559 if (leafcount) {
8560 bcount = leafcount->GetBranch();
8561 if (status) bcount->ResetBit(kDoNotProcess);
8562 else bcount->SetBit(kDoNotProcess);
8563 }
8564 }
8565 if (nb==0 && !strchr(bname,'*')) {
8566 branch = GetBranch(bname);
8567 if (branch) {
8568 if (status) branch->ResetBit(kDoNotProcess);
8569 else branch->SetBit(kDoNotProcess);
8570 ++nb;
8571 }
8572 }
8573
8574 //search in list of friends
8575 UInt_t foundInFriend = 0;
8576 if (fFriends) {
8577 TFriendLock lock(this,kSetBranchStatus);
8578 TIter nextf(fFriends);
8579 TFriendElement *fe;
8580 TString name;
8581 while ((fe = (TFriendElement*)nextf())) {
8582 TTree *t = fe->GetTree();
8583 if (!t) continue;
8584
8585 // If the alias is present replace it with the real name.
8586 const char *subbranch = strstr(bname,fe->GetName());
8587 if (subbranch!=bname) subbranch = nullptr;
8588 if (subbranch) {
8589 subbranch += strlen(fe->GetName());
8590 if ( *subbranch != '.' ) subbranch = nullptr;
8591 else subbranch ++;
8592 }
8593 if (subbranch) {
8594 name.Form("%s.%s",t->GetName(),subbranch);
8595 } else {
8596 name = bname;
8597 }
8598 t->SetBranchStatus(name,status, &foundInFriend);
8599 }
8600 }
8601 if (!nb && !foundInFriend) {
8602 if (!found) {
8603 if (status) {
8604 if (strchr(bname,'*') != 0)
8605 Error("SetBranchStatus", "No branch name is matching wildcard -> %s", bname);
8606 else
8607 Error("SetBranchStatus", "unknown branch -> %s", bname);
8608 } else {
8609 if (strchr(bname,'*') != 0)
8610 Warning("SetBranchStatus", "No branch name is matching wildcard -> %s", bname);
8611 else
8612 Warning("SetBranchStatus", "unknown branch -> %s", bname);
8613 }
8614 }
8615 return;
8616 }
8617 if (found) *found = nb + foundInFriend;
8618
8619 // second pass, loop again on all branches
8620 // activate leafcount branches for active branches only
8621 for (i = 0; i < nleaves; i++) {
8622 leaf = (TLeaf*)fLeaves.UncheckedAt(i);
8623 branch = (TBranch*)leaf->GetBranch();
8624 if (!branch->TestBit(kDoNotProcess)) {
8625 leafcount = leaf->GetLeafCount();
8626 if (leafcount) {
8627 bcount = leafcount->GetBranch();
8628 bcount->ResetBit(kDoNotProcess);
8629 }
8630 } else {
8631 //Int_t nbranches = branch->GetListOfBranches()->GetEntriesFast();
8632 Int_t nbranches = branch->GetListOfBranches()->GetEntries();
8633 for (j=0;j<nbranches;j++) {
8634 bson = (TBranch*)branch->GetListOfBranches()->UncheckedAt(j);
8635 if (!bson) continue;
8636 if (!bson->TestBit(kDoNotProcess)) {
8637 if (bson->GetNleaves() <= 0) continue;
8638 branch->ResetBit(kDoNotProcess);
8639 break;
8640 }
8641 }
8642 }
8643 }
8644}
8645
8646////////////////////////////////////////////////////////////////////////////////
8647/// Set the current branch style. (static function)
8648///
8649/// - style = 0 old Branch
8650/// - style = 1 new Bronch
8653{
8655}
8656
8657////////////////////////////////////////////////////////////////////////////////
8658/// Set maximum size of the file cache .
8659//
8660/// - if cachesize = 0 the existing cache (if any) is deleted.
8661/// - if cachesize = -1 (default) it is set to the AutoFlush value when writing
8662/// the Tree (default is 30 MBytes).
8663///
8664/// Returns:
8665/// - 0 size set, cache was created if possible
8666/// - -1 on error
8669{
8670 // remember that the user has requested an explicit cache setup
8672
8673 return SetCacheSizeAux(kFALSE, cacheSize);
8674}
8675
8676////////////////////////////////////////////////////////////////////////////////
8677/// Set the size of the file cache and create it if possible.
8678///
8679/// If autocache is true:
8680/// this may be an autocreated cache, possibly enlarging an existing
8681/// autocreated cache. The size is calculated. The value passed in cacheSize:
8682/// - cacheSize = 0 make cache if default cache creation is enabled
8683/// - cacheSize = -1 make a default sized cache in any case
8684///
8685/// If autocache is false:
8686/// this is a user requested cache. cacheSize is used to size the cache.
8687/// This cache should never be automatically adjusted.
8688///
8689/// Returns:
8690/// - 0 size set, or existing autosized cache almost large enough.
8691/// (cache was created if possible)
8692/// - -1 on error
8694Int_t TTree::SetCacheSizeAux(Bool_t autocache /* = kTRUE */, Long64_t cacheSize /* = 0 */ )
8695{
8696 if (autocache) {
8697 // used as a once only control for automatic cache setup
8699 }
8700
8701 if (!autocache) {
8702 // negative size means the user requests the default
8703 if (cacheSize < 0) {
8704 cacheSize = GetCacheAutoSize(kTRUE);
8705 }
8706 } else {
8707 if (cacheSize == 0) {
8708 cacheSize = GetCacheAutoSize();
8709 } else if (cacheSize < 0) {
8710 cacheSize = GetCacheAutoSize(kTRUE);
8711 }
8712 }
8713
8715 if (!file || GetTree() != this) {
8716 // if there's no file or we are not a plain tree (e.g. if we're a TChain)
8717 // do not create a cache, only record the size if one was given
8718 if (!autocache) {
8719 fCacheSize = cacheSize;
8720 }
8721 if (GetTree() != this) {
8722 return 0;
8723 }
8724 if (!autocache && cacheSize>0) {
8725 Warning("SetCacheSizeAux", "A TTreeCache could not be created because the TTree has no file");
8726 }
8727 return 0;
8728 }
8729
8730 // Check for an existing cache
8732 if (pf) {
8733 if (autocache) {
8734 // reset our cache status tracking in case existing cache was added
8735 // by the user without using one of the TTree methods
8736 fCacheSize = pf->GetBufferSize();
8738
8739 if (fCacheUserSet) {
8740 // existing cache was created by the user, don't change it
8741 return 0;
8742 }
8743 } else {
8744 // update the cache to ensure it records the user has explicitly
8745 // requested it
8747 }
8748
8749 // if we're using an automatically calculated size and the existing
8750 // cache is already almost large enough don't resize
8751 if (autocache && Long64_t(0.80*cacheSize) < fCacheSize) {
8752 // already large enough
8753 return 0;
8754 }
8755
8756 if (cacheSize == fCacheSize) {
8757 return 0;
8758 }
8759
8760 if (cacheSize == 0) {
8761 // delete existing cache
8762 pf->WaitFinishPrefetch();
8763 file->SetCacheRead(0,this);
8764 delete pf;
8765 pf = 0;
8766 } else {
8767 // resize
8768 Int_t res = pf->SetBufferSize(cacheSize);
8769 if (res < 0) {
8770 return -1;
8771 }
8772 }
8773 } else {
8774 // no existing cache
8775 if (autocache) {
8776 if (fCacheUserSet) {
8777 // value was already set manually.
8778 if (fCacheSize == 0) return 0;
8779 // Expected a cache should exist; perhaps the user moved it
8780 // Do nothing more here.
8781 if (cacheSize) {
8782 Error("SetCacheSizeAux", "Not setting up an automatically sized TTreeCache because of missing cache previously set");
8783 }
8784 return -1;
8785 }
8786 }
8787 }
8788
8789 fCacheSize = cacheSize;
8790 if (cacheSize == 0 || pf) {
8791 return 0;
8792 }
8793
8794#ifdef R__USE_IMT
8795 if(TTreeCacheUnzip::IsParallelUnzip() && file->GetCompressionLevel() > 0)
8796 pf = new TTreeCacheUnzip(this, cacheSize);
8797 else
8798#endif
8799 pf = new TTreeCache(this, cacheSize);
8800
8801 pf->SetAutoCreated(autocache);
8802
8803 return 0;
8804}
8805
8806////////////////////////////////////////////////////////////////////////////////
8807///interface to TTreeCache to set the cache entry range
8808///
8809/// Returns:
8810/// - 0 entry range set
8811/// - -1 on error
8814{
8815 if (!GetTree()) {
8816 if (LoadTree(0)<0) {
8817 Error("SetCacheEntryRange","Could not load a tree");
8818 return -1;
8819 }
8820 }
8821 if (GetTree()) {
8822 if (GetTree() != this) {
8823 return GetTree()->SetCacheEntryRange(first, last);
8824 }
8825 } else {
8826 Error("SetCacheEntryRange", "No tree is available. Could not set cache entry range");
8827 return -1;
8828 }
8829
8830 TFile *f = GetCurrentFile();
8831 if (!f) {
8832 Error("SetCacheEntryRange", "No file is available. Could not set cache entry range");
8833 return -1;
8834 }
8836 if (!tc) {
8837 Error("SetCacheEntryRange", "No cache is available. Could not set entry range");
8838 return -1;
8839 }
8840 tc->SetEntryRange(first,last);
8841 return 0;
8842}
8843
8844////////////////////////////////////////////////////////////////////////////////
8845/// Interface to TTreeCache to set the number of entries for the learning phase
8848{
8850}
8851
8852////////////////////////////////////////////////////////////////////////////////
8853/// Enable/Disable circularity for this tree.
8854///
8855/// if maxEntries > 0 a maximum of maxEntries is kept in one buffer/basket
8856/// per branch in memory.
8857/// Note that when this function is called (maxEntries>0) the Tree
8858/// must be empty or having only one basket per branch.
8859/// if maxEntries <= 0 the tree circularity is disabled.
8860///
8861/// #### NOTE 1:
8862/// Circular Trees are interesting in online real time environments
8863/// to store the results of the last maxEntries events.
8864/// #### NOTE 2:
8865/// Calling SetCircular with maxEntries <= 0 is necessary before
8866/// merging circular Trees that have been saved on files.
8867/// #### NOTE 3:
8868/// SetCircular with maxEntries <= 0 is automatically called
8869/// by TChain::Merge
8870/// #### NOTE 4:
8871/// A circular Tree can still be saved in a file. When read back,
8872/// it is still a circular Tree and can be filled again.
8874void TTree::SetCircular(Long64_t maxEntries)
8875{
8876 if (maxEntries <= 0) {
8877 // Disable circularity.
8878 fMaxEntries = 1000000000;
8879 fMaxEntries *= 1000;
8881 //in case the Tree was originally created in gROOT, the branch
8882 //compression level was set to -1. If the Tree is now associated to
8883 //a file, reset the compression level to the file compression level
8884 if (fDirectory) {
8885 TFile* bfile = fDirectory->GetFile();
8887 if (bfile) {
8888 compress = bfile->GetCompressionSettings();
8889 }
8891 for (Int_t i = 0; i < nb; i++) {
8892 TBranch* branch = (TBranch*) fBranches.UncheckedAt(i);
8893 branch->SetCompressionSettings(compress);
8894 }
8895 }
8896 } else {
8897 // Enable circularity.
8898 fMaxEntries = maxEntries;
8900 }
8901}
8902
8903////////////////////////////////////////////////////////////////////////////////
8904/// Set the debug level and the debug range.
8905///
8906/// For entries in the debug range, the functions TBranchElement::Fill
8907/// and TBranchElement::GetEntry will print the number of bytes filled
8908/// or read for each branch.
8910void TTree::SetDebug(Int_t level, Long64_t min, Long64_t max)
8911{
8912 fDebug = level;
8913 fDebugMin = min;
8914 fDebugMax = max;
8915}
8916
8917////////////////////////////////////////////////////////////////////////////////
8918/// Update the default value for the branch's fEntryOffsetLen.
8919/// If updateExisting is true, also update all the existing branches.
8920/// If newdefault is less than 10, the new default value will be 10.
8922void TTree::SetDefaultEntryOffsetLen(Int_t newdefault, Bool_t updateExisting)
8923{
8924 if (newdefault < 10) {
8925 newdefault = 10;
8926 }
8927 fDefaultEntryOffsetLen = newdefault;
8928 if (updateExisting) {
8929 TIter next( GetListOfBranches() );
8930 TBranch *b;
8931 while ( ( b = (TBranch*)next() ) ) {
8932 b->SetEntryOffsetLen( newdefault, kTRUE );
8933 }
8934 if (fBranchRef) {
8935 fBranchRef->SetEntryOffsetLen( newdefault, kTRUE );
8936 }
8937 }
8938}
8939
8940////////////////////////////////////////////////////////////////////////////////
8941/// Change the tree's directory.
8942///
8943/// Remove reference to this tree from current directory and
8944/// add reference to new directory dir. The dir parameter can
8945/// be 0 in which case the tree does not belong to any directory.
8946///
8949{
8950 if (fDirectory == dir) {
8951 return;
8952 }
8953 if (fDirectory) {
8954 fDirectory->Remove(this);
8955
8956 // Delete or move the file cache if it points to this Tree
8958 MoveReadCache(file,dir);
8959 }
8960 fDirectory = dir;
8961 if (fDirectory) {
8962 fDirectory->Append(this);
8963 }
8964 TFile* file = 0;
8965 if (fDirectory) {
8966 file = fDirectory->GetFile();
8967 }
8968 if (fBranchRef) {
8970 }
8971 TBranch* b = 0;
8972 TIter next(GetListOfBranches());
8973 while((b = (TBranch*) next())) {
8974 b->SetFile(file);
8975 }
8976}
8977
8978////////////////////////////////////////////////////////////////////////////////
8979/// Change number of entries in the tree.
8980///
8981/// If n >= 0, set number of entries in the tree = n.
8982///
8983/// If n < 0, set number of entries in the tree to match the
8984/// number of entries in each branch. (default for n is -1)
8985///
8986/// This function should be called only when one fills each branch
8987/// independently via TBranch::Fill without calling TTree::Fill.
8988/// Calling TTree::SetEntries() make sense only if the number of entries
8989/// in each branch is identical, a warning is issued otherwise.
8990/// The function returns the number of entries.
8991///
8994{
8995 // case 1 : force number of entries to n
8996 if (n >= 0) {
8997 fEntries = n;
8998 return n;
8999 }
9000
9001 // case 2; compute the number of entries from the number of entries in the branches
9002 TBranch* b(nullptr), *bMin(nullptr), *bMax(nullptr);
9003 Long64_t nMin = kMaxEntries;
9004 Long64_t nMax = 0;
9005 TIter next(GetListOfBranches());
9006 while((b = (TBranch*) next())){
9007 Long64_t n2 = b->GetEntries();
9008 if (!bMin || n2 < nMin) {
9009 nMin = n2;
9010 bMin = b;
9011 }
9012 if (!bMax || n2 > nMax) {
9013 nMax = n2;
9014 bMax = b;
9015 }
9016 }
9017 if (bMin && nMin != nMax) {
9018 Warning("SetEntries", "Tree branches have different numbers of entries, eg %s has %lld entries while %s has %lld entries.",
9019 bMin->GetName(), nMin, bMax->GetName(), nMax);
9020 }
9021 fEntries = nMax;
9022 return fEntries;
9023}
9024
9025////////////////////////////////////////////////////////////////////////////////
9026/// Set an EntryList
9028void TTree::SetEntryList(TEntryList *enlist, Option_t * /*opt*/)
9029{
9030 if (fEntryList) {
9031 //check if the previous entry list is owned by the tree
9033 delete fEntryList;
9034 }
9035 }
9036 fEventList = 0;
9037 if (!enlist) {
9038 fEntryList = 0;
9039 return;
9040 }
9041 fEntryList = enlist;
9042 fEntryList->SetTree(this);
9043
9044}
9045
9046////////////////////////////////////////////////////////////////////////////////
9047/// This function transfroms the given TEventList into a TEntryList
9048/// The new TEntryList is owned by the TTree and gets deleted when the tree
9049/// is deleted. This TEntryList can be returned by GetEntryList() function.
9051void TTree::SetEventList(TEventList *evlist)
9052{
9053 fEventList = evlist;
9054 if (fEntryList){
9056 TEntryList *tmp = fEntryList;
9057 fEntryList = 0; // Avoid problem with RecursiveRemove.
9058 delete tmp;
9059 } else {
9060 fEntryList = 0;
9061 }
9062 }
9063
9064 if (!evlist) {
9065 fEntryList = 0;
9066 fEventList = 0;
9067 return;
9068 }
9069
9070 fEventList = evlist;
9071 char enlistname[100];
9072 snprintf(enlistname,100, "%s_%s", evlist->GetName(), "entrylist");
9073 fEntryList = new TEntryList(enlistname, evlist->GetTitle());
9074 fEntryList->SetDirectory(0); // We own this.
9075 Int_t nsel = evlist->GetN();
9076 fEntryList->SetTree(this);
9077 Long64_t entry;
9078 for (Int_t i=0; i<nsel; i++){
9079 entry = evlist->GetEntry(i);
9080 fEntryList->Enter(entry);
9081 }
9084}
9085
9086////////////////////////////////////////////////////////////////////////////////
9087/// Set number of entries to estimate variable limits.
9088/// If n is -1, the estimate is set to be the current maximum
9089/// for the tree (i.e. GetEntries() + 1)
9090/// If n is less than -1, the behavior is undefined.
9092void TTree::SetEstimate(Long64_t n /* = 1000000 */)
9093{
9094 if (n == 0) {
9095 n = 10000;
9096 } else if (n < 0) {
9097 n = fEntries - n;
9098 }
9099 fEstimate = n;
9100 GetPlayer();
9101 if (fPlayer) {
9103 }
9104}
9105
9106////////////////////////////////////////////////////////////////////////////////
9107/// Provide the end-user with the ability to enable/disable various experimental
9108/// IO features for this TTree.
9109///
9110/// Returns all the newly-set IO settings.
9113{
9114 // Purposely ignore all unsupported bits; TIOFeatures implementation already warned the user about the
9115 // error of their ways; this is just a safety check.
9116 UChar_t featuresRequested = features.GetFeatures() & static_cast<UChar_t>(TBasket::EIOBits::kSupported);
9117
9118 UChar_t curFeatures = fIOFeatures.GetFeatures();
9119 UChar_t newFeatures = ~curFeatures & featuresRequested;
9120 curFeatures |= newFeatures;
9121 fIOFeatures.Set(curFeatures);
9122
9123 ROOT::TIOFeatures newSettings(newFeatures);
9124 return newSettings;
9125}
9126
9127////////////////////////////////////////////////////////////////////////////////
9128/// Set fFileNumber to number.
9129/// fFileNumber is used by TTree::Fill to set the file name
9130/// for a new file to be created when the current file exceeds fgTreeMaxSize.
9131/// (see TTree::ChangeFile)
9132/// if fFileNumber=10, the new file name will have a suffix "_11",
9133/// ie, fFileNumber is incremented before setting the file name
9135void TTree::SetFileNumber(Int_t number)
9136{
9137 if (fFileNumber < 0) {
9138 Warning("SetFileNumber", "file number must be positive. Set to 0");
9139 fFileNumber = 0;
9140 return;
9141 }
9142 fFileNumber = number;
9143}
9144
9145////////////////////////////////////////////////////////////////////////////////
9146/// Set all the branches in this TTree to be in decomposed object mode
9147/// (also known as MakeClass mode).
9148///
9149/// For MakeClass mode 0, the TTree expects the address where the data is stored
9150/// to be set by either the user or the TTree to the address of a full object
9151/// through the top level branch.
9152/// For MakeClass mode 1, this address is expected to point to a numerical type
9153/// or C-style array (variable or not) of numerical type, representing the
9154/// primitive data members.
9155/// The function's primary purpose is to allow the user to access the data
9156/// directly with numerical type variable rather than having to have the original
9157/// set of classes (or a reproduction thereof).
9159void TTree::SetMakeClass(Int_t make)
9160{
9161 fMakeClass = make;
9162
9164 for (Int_t i = 0; i < nb; ++i) {
9165 TBranch* branch = (TBranch*) fBranches.UncheckedAt(i);
9166 branch->SetMakeClass(make);
9167 }
9168}
9169
9170////////////////////////////////////////////////////////////////////////////////
9171/// Set the maximum size in bytes of a Tree file (static function).
9172/// The default size is 100000000000LL, ie 100 Gigabytes.
9173///
9174/// In TTree::Fill, when the file has a size > fgMaxTreeSize,
9175/// the function closes the current file and starts writing into
9176/// a new file with a name of the style "file_1.root" if the original
9177/// requested file name was "file.root".
9179void TTree::SetMaxTreeSize(Long64_t maxsize)
9180{
9181 fgMaxTreeSize = maxsize;
9182}
9183
9184////////////////////////////////////////////////////////////////////////////////
9185/// Change the name of this tree.
9187void TTree::SetName(const char* name)
9188{
9189 if (gPad) {
9190 gPad->Modified();
9191 }
9192 // Trees are named objects in a THashList.
9193 // We must update hashlists if we change the name.
9194 TFile *file = 0;
9195 TTreeCache *pf = 0;
9196 if (fDirectory) {
9197 fDirectory->Remove(this);
9198 if ((file = GetCurrentFile())) {
9199 pf = GetReadCache(file);
9200 file->SetCacheRead(0,this,TFile::kDoNotDisconnect);
9201 }
9202 }
9203 // This changes our hash value.
9204 fName = name;
9205 if (fDirectory) {
9206 fDirectory->Append(this);
9207 if (pf) {
9208 file->SetCacheRead(pf,this,TFile::kDoNotDisconnect);
9209 }
9210 }
9211}
9212
9213////////////////////////////////////////////////////////////////////////////////
9214/// Change the name and title of this tree.
9216void TTree::SetObject(const char* name, const char* title)
9217{
9218 if (gPad) {
9219 gPad->Modified();
9220 }
9221
9222 // Trees are named objects in a THashList.
9223 // We must update hashlists if we change the name
9224 TFile *file = 0;
9225 TTreeCache *pf = 0;
9226 if (fDirectory) {
9227 fDirectory->Remove(this);
9228 if ((file = GetCurrentFile())) {
9229 pf = GetReadCache(file);
9230 file->SetCacheRead(0,this,TFile::kDoNotDisconnect);
9231 }
9232 }
9233 // This changes our hash value.
9234 fName = name;
9235 fTitle = title;
9236 if (fDirectory) {
9237 fDirectory->Append(this);
9238 if (pf) {
9239 file->SetCacheRead(pf,this,TFile::kDoNotDisconnect);
9240 }
9241 }
9242}
9243
9244////////////////////////////////////////////////////////////////////////////////
9245/// Enable or disable parallel unzipping of Tree buffers.
9247void TTree::SetParallelUnzip(Bool_t opt, Float_t RelSize)
9248{
9249#ifdef R__USE_IMT
9250 if (GetTree() == 0) {
9252 if (!GetTree())
9253 return;
9254 }
9255 if (GetTree() != this) {
9256 GetTree()->SetParallelUnzip(opt, RelSize);
9257 return;
9258 }
9260 if (!file)
9261 return;
9262
9264 if (pf && !( opt ^ (nullptr != dynamic_cast<TTreeCacheUnzip*>(pf)))) {
9265 // done with opt and type are in agreement.
9266 return;
9267 }
9268 delete pf;
9269 auto cacheSize = GetCacheAutoSize(kTRUE);
9270 if (opt) {
9271 auto unzip = new TTreeCacheUnzip(this, cacheSize);
9272 unzip->SetUnzipBufferSize( Long64_t(cacheSize * RelSize) );
9273 } else {
9274 pf = new TTreeCache(this, cacheSize);
9275 }
9276#else
9277 (void)opt;
9278 (void)RelSize;
9279#endif
9280}
9281
9282////////////////////////////////////////////////////////////////////////////////
9283/// Set perf stats
9286{
9287 fPerfStats = perf;
9288}
9289
9290////////////////////////////////////////////////////////////////////////////////
9291/// The current TreeIndex is replaced by the new index.
9292/// Note that this function does not delete the previous index.
9293/// This gives the possibility to play with more than one index, e.g.,
9294/// ~~~ {.cpp}
9295/// TVirtualIndex* oldIndex = tree.GetTreeIndex();
9296/// tree.SetTreeIndex(newIndex);
9297/// tree.Draw();
9298/// tree.SetTreeIndex(oldIndex);
9299/// tree.Draw(); etc
9300/// ~~~
9303{
9304 if (fTreeIndex) {
9305 fTreeIndex->SetTree(0);
9306 }
9307 fTreeIndex = index;
9308}
9309
9310////////////////////////////////////////////////////////////////////////////////
9311/// Set tree weight.
9312///
9313/// The weight is used by TTree::Draw to automatically weight each
9314/// selected entry in the resulting histogram.
9315///
9316/// For example the equivalent of:
9317/// ~~~ {.cpp}
9318/// T.Draw("x", "w")
9319/// ~~~
9320/// is:
9321/// ~~~ {.cpp}
9322/// T.SetWeight(w);
9323/// T.Draw("x");
9324/// ~~~
9325/// This function is redefined by TChain::SetWeight. In case of a
9326/// TChain, an option "global" may be specified to set the same weight
9327/// for all trees in the TChain instead of the default behaviour
9328/// using the weights of each tree in the chain (see TChain::SetWeight).
9331{
9332 fWeight = w;
9333}
9334
9335////////////////////////////////////////////////////////////////////////////////
9336/// Print values of all active leaves for entry.
9337///
9338/// - if entry==-1, print current entry (default)
9339/// - if a leaf is an array, a maximum of lenmax elements is printed.
9341void TTree::Show(Long64_t entry, Int_t lenmax)
9342{
9343 if (entry != -1) {
9344 Int_t ret = LoadTree(entry);
9345 if (ret == -2) {
9346 Error("Show()", "Cannot read entry %lld (entry does not exist)", entry);
9347 return;
9348 } else if (ret == -1) {
9349 Error("Show()", "Cannot read entry %lld (I/O error)", entry);
9350 return;
9351 }
9352 ret = GetEntry(entry);
9353 if (ret == -1) {
9354 Error("Show()", "Cannot read entry %lld (I/O error)", entry);
9355 return;
9356 } else if (ret == 0) {
9357 Error("Show()", "Cannot read entry %lld (no data read)", entry);
9358 return;
9359 }
9360 }
9361 printf("======> EVENT:%lld\n", fReadEntry);
9362 TObjArray* leaves = GetListOfLeaves();
9363 Int_t nleaves = leaves->GetEntriesFast();
9364 Int_t ltype;
9365 for (Int_t i = 0; i < nleaves; i++) {
9366 TLeaf* leaf = (TLeaf*) leaves->UncheckedAt(i);
9367 TBranch* branch = leaf->GetBranch();
9368 if (branch->TestBit(kDoNotProcess)) {
9369 continue;
9370 }
9371 Int_t len = leaf->GetLen();
9372 if (len <= 0) {
9373 continue;
9374 }
9375 len = TMath::Min(len, lenmax);
9376 if (leaf->IsA() == TLeafElement::Class()) {
9377 leaf->PrintValue(lenmax);
9378 continue;
9379 }
9380 if (branch->GetListOfBranches()->GetEntriesFast() > 0) {
9381 continue;
9382 }
9383 ltype = 10;
9384 if (leaf->IsA() == TLeafF::Class()) {
9385 ltype = 5;
9386 }
9387 if (leaf->IsA() == TLeafD::Class()) {
9388 ltype = 5;
9389 }
9390 if (leaf->IsA() == TLeafC::Class()) {
9391 len = 1;
9392 ltype = 5;
9393 };
9394 printf(" %-15s = ", leaf->GetName());
9395 for (Int_t l = 0; l < len; l++) {
9396 leaf->PrintValue(l);
9397 if (l == (len - 1)) {
9398 printf("\n");
9399 continue;
9400 }
9401 printf(", ");
9402 if ((l % ltype) == 0) {
9403 printf("\n ");
9404 }
9405 }
9406 }
9407}
9408
9409////////////////////////////////////////////////////////////////////////////////
9410/// Start the TTreeViewer on this tree.
9411///
9412/// - ww is the width of the canvas in pixels
9413/// - wh is the height of the canvas in pixels
9415void TTree::StartViewer()
9416{
9417 GetPlayer();
9418 if (fPlayer) {
9419 fPlayer->StartViewer(600, 400);
9420 }
9421}
9422
9423////////////////////////////////////////////////////////////////////////////////
9424/// Stop the cache learning phase
9425///
9426/// Returns:
9427/// - 0 learning phase stopped or not active
9428/// - -1 on error
9431{
9432 if (!GetTree()) {
9433 if (LoadTree(0)<0) {
9434 Error("StopCacheLearningPhase","Could not load a tree");
9435 return -1;
9436 }
9437 }
9438 if (GetTree()) {
9439 if (GetTree() != this) {
9440 return GetTree()->StopCacheLearningPhase();
9441 }
9442 } else {
9443 Error("StopCacheLearningPhase", "No tree is available. Could not stop cache learning phase");
9444 return -1;
9445 }
9446
9447 TFile *f = GetCurrentFile();
9448 if (!f) {
9449 Error("StopCacheLearningPhase", "No file is available. Could not stop cache learning phase");
9450 return -1;
9451 }
9453 if (!tc) {
9454 Error("StopCacheLearningPhase", "No cache is available. Could not stop learning phase");
9455 return -1;
9456 }
9457 tc->StopLearningPhase();
9458 return 0;
9459}
9460
9461////////////////////////////////////////////////////////////////////////////////
9462/// Set the fTree member for all branches and sub branches.
9464static void TBranch__SetTree(TTree *tree, TObjArray &branches)
9465{
9466 Int_t nb = branches.GetEntriesFast();
9467 for (Int_t i = 0; i < nb; ++i) {
9468 TBranch* br = (TBranch*) branches.UncheckedAt(i);
9469 br->SetTree(tree);
9470
9471 Int_t writeBasket = br->GetWriteBasket();
9472 for (Int_t j = writeBasket; j >= 0; --j) {
9473 TBasket *bk = (TBasket*)br->GetListOfBaskets()->UncheckedAt(j);
9474 if (bk) {
9475 tree->IncrementTotalBuffers(bk->GetBufferSize());
9476 }
9477 }
9478
9480 }
9481}
9482
9483////////////////////////////////////////////////////////////////////////////////
9484/// Set the fTree member for all friend elements.
9487{
9488 if (frlist) {
9489 TObjLink *lnk = frlist->FirstLink();
9490 while (lnk) {
9491 TFriendElement *elem = (TFriendElement*)lnk->GetObject();
9492 elem->fParentTree = tree;
9493 lnk = lnk->Next();
9494 }
9495 }
9496}
9497
9498////////////////////////////////////////////////////////////////////////////////
9499/// Stream a class object.
9502{
9503 if (b.IsReading()) {
9504 UInt_t R__s, R__c;
9505 if (fDirectory) {
9506 fDirectory->Remove(this);
9507 //delete the file cache if it points to this Tree
9510 }
9511 fDirectory = 0;
9514 Version_t R__v = b.ReadVersion(&R__s, &R__c);
9515 if (R__v > 4) {
9516 b.ReadClassBuffer(TTree::Class(), this, R__v, R__s, R__c);
9517
9518 fBranches.SetOwner(kTRUE); // True needed only for R__v < 19 and most R__v == 19
9519
9520 if (fBranchRef) fBranchRef->SetTree(this);
9523
9524 if (fTreeIndex) {
9525 fTreeIndex->SetTree(this);
9526 }
9527 if (fIndex.fN) {
9528 Warning("Streamer", "Old style index in this tree is deleted. Rebuild the index via TTree::BuildIndex");
9529 fIndex.Set(0);
9530 fIndexValues.Set(0);
9531 }
9532 if (fEstimate <= 10000) {
9533 fEstimate = 1000000;
9534 }
9535
9536 if (fNClusterRange) {
9537 // The I/O allocated just enough memory to hold the
9538 // current set of ranges.
9540 }
9541
9542 // Throughs calls to `GetCacheAutoSize` or `EnableCache` (for example
9543 // by TTreePlayer::Process, the cache size will be automatically
9544 // determined unless the user explicitly call `SetCacheSize`
9545 fCacheSize = 0;
9547
9549 return;
9550 }
9551 //====process old versions before automatic schema evolution
9552 Stat_t djunk;
9553 Int_t ijunk;
9558 b >> fScanField;
9559 b >> ijunk; fMaxEntryLoop = (Long64_t)ijunk;
9560 b >> ijunk; fMaxVirtualSize = (Long64_t)ijunk;
9561 b >> djunk; fEntries = (Long64_t)djunk;
9562 b >> djunk; fTotBytes = (Long64_t)djunk;
9563 b >> djunk; fZipBytes = (Long64_t)djunk;
9564 b >> ijunk; fAutoSave = (Long64_t)ijunk;
9565 b >> ijunk; fEstimate = (Long64_t)ijunk;
9566 if (fEstimate <= 10000) fEstimate = 1000000;
9568 if (fBranchRef) fBranchRef->SetTree(this);
9572 if (R__v > 1) fIndexValues.Streamer(b);
9573 if (R__v > 2) fIndex.Streamer(b);
9574 if (R__v > 3) {
9575 TList OldInfoList;
9576 OldInfoList.Streamer(b);
9577 OldInfoList.Delete();
9578 }
9579 fNClusterRange = 0;
9582 b.CheckByteCount(R__s, R__c, TTree::IsA());
9583 //====end of old versions
9584 } else {
9585 if (fBranchRef) {
9586 fBranchRef->Clear();
9587 }
9589 if (table) TRefTable::SetRefTable(0);
9590
9591 b.WriteClassBuffer(TTree::Class(), this);
9592
9593 if (table) TRefTable::SetRefTable(table);
9594 }
9595}
9596
9597////////////////////////////////////////////////////////////////////////////////
9598/// Unbinned fit of one or more variable(s) from a tree.
9599///
9600/// funcname is a TF1 function.
9601///
9602/// \see TTree::Draw for explanations of the other parameters.
9603///
9604/// Fit the variable varexp using the function funcname using the
9605/// selection cuts given by selection.
9606///
9607/// The list of fit options is given in parameter option.
9608///
9609/// - option = "Q" Quiet mode (minimum printing)
9610/// - option = "V" Verbose mode (default is between Q and V)
9611/// - option = "E" Perform better Errors estimation using Minos technique
9612/// - option = "M" More. Improve fit results
9613///
9614/// You can specify boundary limits for some or all parameters via
9615/// ~~~ {.cpp}
9616/// func->SetParLimits(p_number, parmin, parmax);
9617/// ~~~
9618/// if parmin>=parmax, the parameter is fixed
9619///
9620/// Note that you are not forced to fix the limits for all parameters.
9621/// For example, if you fit a function with 6 parameters, you can do:
9622/// ~~~ {.cpp}
9623/// func->SetParameters(0,3.1,1.e-6,0.1,-8,100);
9624/// func->SetParLimits(4,-10,-4);
9625/// func->SetParLimits(5, 1,1);
9626/// ~~~
9627/// With this setup:
9628///
9629/// - Parameters 0->3 can vary freely
9630/// - Parameter 4 has boundaries [-10,-4] with initial value -8
9631/// - Parameter 5 is fixed to 100.
9632///
9633/// For the fit to be meaningful, the function must be self-normalized.
9634///
9635/// i.e. It must have the same integral regardless of the parameter
9636/// settings. Otherwise the fit will effectively just maximize the
9637/// area.
9638///
9639/// It is mandatory to have a normalization variable
9640/// which is fixed for the fit. e.g.
9641/// ~~~ {.cpp}
9642/// TF1* f1 = new TF1("f1", "gaus(0)/sqrt(2*3.14159)/[2]", 0, 5);
9643/// f1->SetParameters(1, 3.1, 0.01);
9644/// f1->SetParLimits(0, 1, 1); // fix the normalization parameter to 1
9645/// data->UnbinnedFit("f1", "jpsimass", "jpsipt>3.0");
9646/// ~~~
9647/// 1, 2 and 3 Dimensional fits are supported. See also TTree::Fit
9648///
9649/// Return status:
9650///
9651/// - The function return the status of the fit in the following form
9652/// fitResult = migradResult + 10*minosResult + 100*hesseResult + 1000*improveResult
9653/// - The fitResult is 0 is the fit is OK.
9654/// - The fitResult is negative in case of an error not connected with the fit.
9655/// - The number of entries used in the fit can be obtained via mytree.GetSelectedRows();
9656/// - If the number of selected entries is null the function returns -1
9658Int_t TTree::UnbinnedFit(const char* funcname, const char* varexp, const char* selection, Option_t* option, Long64_t nentries, Long64_t firstentry)
9659{
9660 GetPlayer();
9661 if (fPlayer) {
9662 return fPlayer->UnbinnedFit(funcname, varexp, selection, option, nentries, firstentry);
9663 }
9664 return -1;
9665}
9666
9667////////////////////////////////////////////////////////////////////////////////
9668/// Replace current attributes by current style.
9671{
9672 if (gStyle->IsReading()) {
9681 } else {
9690 }
9691}
9692
9693////////////////////////////////////////////////////////////////////////////////
9694/// Write this object to the current directory. For more see TObject::Write
9695/// If option & kFlushBasket, call FlushBasket before writing the tree.
9697Int_t TTree::Write(const char *name, Int_t option, Int_t bufsize) const
9698{
9701 return 0;
9702 return TObject::Write(name, option, bufsize);
9703}
9704
9705////////////////////////////////////////////////////////////////////////////////
9706/// Write this object to the current directory. For more see TObject::Write
9707/// If option & kFlushBasket, call FlushBasket before writing the tree.
9709Int_t TTree::Write(const char *name, Int_t option, Int_t bufsize)
9710{
9711 return ((const TTree*)this)->Write(name, option, bufsize);
9712}
9713
9714////////////////////////////////////////////////////////////////////////////////
9715/// \class TTreeFriendLeafIter
9716///
9717/// Iterator on all the leaves in a TTree and its friend
9718
9720
9721////////////////////////////////////////////////////////////////////////////////
9722/// Create a new iterator. By default the iteration direction
9723/// is kIterForward. To go backward use kIterBackward.
9726: fTree(const_cast<TTree*>(tree))
9727, fLeafIter(0)
9728, fTreeIter(0)
9729, fDirection(dir)
9730{
9731}
9732
9733////////////////////////////////////////////////////////////////////////////////
9734/// Copy constructor. Does NOT copy the 'cursor' location!
9737: TIterator(iter)
9738, fTree(iter.fTree)
9739, fLeafIter(0)
9740, fTreeIter(0)
9741, fDirection(iter.fDirection)
9742{
9743}
9744
9745////////////////////////////////////////////////////////////////////////////////
9746/// Overridden assignment operator. Does NOT copy the 'cursor' location!
9749{
9750 if (this != &rhs && rhs.IsA() == TTreeFriendLeafIter::Class()) {
9751 const TTreeFriendLeafIter &rhs1 = (const TTreeFriendLeafIter &)rhs;
9752 fDirection = rhs1.fDirection;
9753 }
9754 return *this;
9755}
9756
9757////////////////////////////////////////////////////////////////////////////////
9758/// Overridden assignment operator. Does NOT copy the 'cursor' location!
9761{
9762 if (this != &rhs) {
9763 fDirection = rhs.fDirection;
9764 }
9765 return *this;
9766}
9767
9768////////////////////////////////////////////////////////////////////////////////
9769/// Go the next friend element
9772{
9773 if (!fTree) return 0;
9774
9775 TObject * next;
9776 TTree * nextTree;
9777
9778 if (!fLeafIter) {
9779 TObjArray *list = fTree->GetListOfLeaves();
9780 if (!list) return 0; // Can happen with an empty chain.
9782 if (!fLeafIter) return 0;
9783 }
9784
9785 next = fLeafIter->Next();
9786 if (!next) {
9787 if (!fTreeIter) {
9789 if (!list) return next;
9791 if (!fTreeIter) return 0;
9792 }
9793 TFriendElement * nextFriend = (TFriendElement*) fTreeIter->Next();
9794 ///nextTree = (TTree*)fTreeIter->Next();
9795 if (nextFriend) {
9796 nextTree = const_cast<TTree*>(nextFriend->GetTree());
9797 if (!nextTree) return Next();
9800 if (!fLeafIter) return 0;
9801 next = fLeafIter->Next();
9802 }
9803 }
9804 return next;
9805}
9806
9807////////////////////////////////////////////////////////////////////////////////
9808/// Returns the object option stored in the list.
9811{
9812 if (fLeafIter) return fLeafIter->GetOption();
9813 return "";
9814}
#define R__unlikely(expr)
Definition RConfig.hxx:601
#define SafeDelete(p)
Definition RConfig.hxx:540
#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
bool Bool_t
Definition RtypesCore.h:63
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
constexpr Bool_t kFALSE
Definition RtypesCore.h:101
double Double_t
Definition RtypesCore.h:59
constexpr Ssiz_t kNPOS
Definition RtypesCore.h:124
long long Long64_t
Definition RtypesCore.h:80
unsigned long long ULong64_t
Definition RtypesCore.h:81
constexpr Bool_t kTRUE
Definition RtypesCore.h:100
const char Option_t
Definition RtypesCore.h:66
#define ClassImp(name)
Definition Rtypes.h:377
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:386
R__EXTERN TEnv * gEnv
Definition TEnv.h:170
#define R__ASSERT(e)
Definition TError.h:117
void Error(const char *location, const char *msgfmt,...)
Use this function in case an error occurred.
Definition TError.cxx:197
#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:585
R__EXTERN TVirtualMutex * gROOTMutex
Definition TROOT.h:63
#define gROOT
Definition TROOT.h:405
void Printf(const char *fmt,...)
Formats a string in a circular formatting buffer and prints the string.
Definition TString.cxx:2481
R__EXTERN TStyle * gStyle
Definition TStyle.h:414
R__EXTERN TSystem * gSystem
Definition TSystem.h:560
constexpr Int_t kNEntriesResort
Definition TTree.cxx:449
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:4784
static char DataTypeToChar(EDataType datatype)
Definition TTree.cxx:461
void TFriendElement__SetTree(TTree *tree, TList *frlist)
Set the fTree member for all friend elements.
Definition TTree.cxx:9485
bool CheckReshuffling(TTree &mainTree, TTree &friendTree)
Definition TTree.cxx:1239
static void TBranch__SetTree(TTree *tree, TObjArray &branches)
Set the fTree member for all branches and sub branches.
Definition TTree.cxx:9463
constexpr Float_t kNEntriesResortInv
Definition TTree.cxx:450
#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 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.
virtual Bool_t IsObjectOwner() const
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:89
virtual TLeaf * GetLeaf(const char *name) const
Return pointer to the 1st Leaf named name in thisBranch.
Definition TBranch.cxx:2001
virtual void SetupAddresses()
If the branch address is not set, we set all addresses starting with the top level parent branch.
Definition TBranch.cxx:3240
virtual void ResetAddress()
Reset the address of the branch.
Definition TBranch.cxx:2597
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:208
void SetCompressionSettings(Int_t settings=ROOT::RCompressionSetting::EDefaults::kUseCompiledDefault)
Set compression settings.
Definition TBranch.cxx:2751
TTree * GetTree() const
Definition TBranch.h:248
static TClass * Class()
virtual TString GetFullName() const
Return the 'full' name of the branch.
Definition TBranch.cxx:1977
Int_t GetWriteBasket() const
Definition TBranch.h:234
virtual void DropBaskets(Option_t *option="")
Loop on all branch baskets.
Definition TBranch.cxx:757
TObjArray * GetListOfBranches()
Definition TBranch.h:242
virtual void SetTree(TTree *tree)
Definition TBranch.h:283
virtual void SetEntryOffsetLen(Int_t len, Bool_t updateSubBranches=kFALSE)
Update the default value for the branch's fEntryOffsetLen if and only if it was already non zero (and...
Definition TBranch.cxx:2767
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:1652
TClass * IsA() const override
Definition TBranch.h:291
void Print(Option_t *option="") const override
Print TBranch parameters.
Definition TBranch.cxx:2287
static void ResetCount()
Static function resetting fgCount.
Definition TBranch.cxx:2620
virtual void SetObject(void *objadd)
Set object this branch is pointing to.
Definition TBranch.cxx:2882
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:2628
Int_t GetNleaves() const
Definition TBranch.h:245
virtual void SetFile(TFile *file=nullptr)
Set file where this branch writes/reads its buffers.
Definition TBranch.cxx:2809
TObjArray * GetListOfBaskets()
Definition TBranch.h:241
Long64_t GetEntries() const
Definition TBranch.h:247
virtual void UpdateFile()
Refresh the value of fDirectory (i.e.
Definition TBranch.cxx:3250
Int_t GetReadBasket() const
Definition TBranch.h:232
Int_t GetMaxBaskets() const
Definition TBranch.h:244
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:1799
virtual void KeepCircular(Long64_t maxEntries)
keep a maximum of fMaxEntries in memory
Definition TBranch.cxx:2229
virtual void ResetAfterMerge(TFileMergeInfo *)
Reset a Branch.
Definition TBranch.cxx:2544
virtual Bool_t GetMakeClass() const
Return whether this branch is in a mode where the object are decomposed or not (Also known as MakeCla...
Definition TBranch.cxx:2063
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:2255
void SetIOFeatures(TIOFeatures &features)
Definition TBranch.h:279
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:2166
virtual Bool_t SetMakeClass(Bool_t decomposeObj=kTRUE)
Set the branch in a mode where the object are decomposed (Also known as MakeClass mode).
Definition TBranch.cxx:2873
virtual void SetOffset(Int_t offset=0)
Definition TBranch.h:281
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:1780
virtual Int_t GetBasketSize() const
Definition TBranch.h:213
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:2184
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:2675
virtual void Refresh(TBranch *b)
Refresh this branch using new information in b This function is called by TTree::Refresh.
Definition TBranch.cxx:2454
TObjArray * GetListOfLeaves()
Definition TBranch.h:243
Int_t Fill()
Definition TBranch.h:201
virtual void Reset(Option_t *option="")
Reset a Branch.
Definition TBranch.cxx:2503
TBranch * GetMother() const
Get our top-level parent branch in the tree.
Definition TBranch.cxx:2073
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:223
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:2319
ROOT::ESTLType GetCollectionType() const
Return the 'type' of the STL the TClass is representing.
Definition TClass.cxx:2886
void * New(ENewType defConstructor=kClassNew, Bool_t quiet=kFALSE) const
Return a pointer to a newly allocated object of this class.
Definition TClass.cxx:4978
Bool_t HasDataMemberInfo() const
Definition TClass.h:405
void Destructor(void *obj, Bool_t dtorOnly=kFALSE)
Explicitly call destructor for object.
Definition TClass.cxx:5400
void BuildRealData(void *pointer=nullptr, Bool_t isTransient=kFALSE)
Build a full list of persistent data members.
Definition TClass.cxx:2031
const std::type_info * GetTypeInfo() const
Definition TClass.h:494
TList * GetListOfDataMembers(Bool_t load=kTRUE)
Return list containing the TDataMembers of a class.
Definition TClass.cxx:3770
TList * GetListOfRealData() const
Definition TClass.h:451
Bool_t CanIgnoreTObjectStreamer()
Definition TClass.h:391
const ROOT::Detail::TSchemaRuleSet * GetSchemaRules() const
Return the set of the schema rules if any.
Definition TClass.cxx:1932
TList * GetListOfBases()
Return list containing the TBaseClass(es) of a class.
Definition TClass.cxx:3636
Bool_t IsLoaded() const
Return true if the shared library of this class is currently in the a process's memory.
Definition TClass.cxx:5912
Bool_t IsTObject() const
Return kTRUE is the class inherits from TObject.
Definition TClass.cxx:5938
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:4599
Bool_t InheritsFrom(const char *cl) const override
Return kTRUE if this class inherits from a class with name "classname".
Definition TClass.cxx:4874
TVirtualCollectionProxy * GetCollectionProxy() const
Return the proxy describing the collection (if any).
Definition TClass.cxx:2897
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:7086
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:7193
Version_t GetClassVersion() const
Definition TClass.h:418
TClass * GetActualClass(const void *object) const
Return a pointer to the real class of the object.
Definition TClass.cxx:2607
@ kHasCustomStreamerMember
Definition TClass.h:106
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:2968
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:6779
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 type of data member, e,g.: "class TDirectory*" -> "TDirectory".
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 full type description of data member, e,g.: "class TDirectory*".
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".
void Append(TObject *obj, Bool_t replace=kFALSE) override
Append object to this directory.
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 void SetReapplyCut(Bool_t apply=kFALSE)
Definition TEntryList.h:108
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 Bool_t Enter(Long64_t entry, TTree *tree=nullptr)
Add entry #entry to the list.
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
A TEventList object is a list of selected events (entries) in a TTree.
Definition TEventList.h:31
virtual Long64_t GetEntry(Int_t index) const
Return value of entry at index in the list.
virtual Int_t GetN() const
Definition TEventList.h:56
virtual Bool_t GetReapplyCut() const
Definition TEventList.h:57
A cache when reading files over the network.
virtual void WaitFinishPrefetch()
virtual Int_t GetBufferSize() const
TIOFeatures * fIOFeatures
TDirectory * fOutputDirectory
A ROOT file is a suite of consecutive data records (TKey instances) with a well defined format.
Definition TFile.h:51
virtual void SetCacheRead(TFileCacheRead *cache, TObject *tree=nullptr, ECacheAction action=kDisconnect)
Set a pointer to the read cache.
Definition TFile.cxx:2329
Int_t GetCompressionSettings() const
Definition TFile.h:398
virtual Long64_t GetEND() const
Definition TFile.h:222
@ kDoNotDisconnect
Definition TFile.h:68
virtual void Flush()
Synchronize a file's in-memory and on-disk states.
Definition TFile.cxx:1105
virtual void MakeFree(Long64_t first, Long64_t last)
Mark unused bytes on the file.
Definition TFile.cxx:1448
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:4053
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:1265
<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.
virtual TFile * GetFile()
Return pointer to TFile containing this friend TTree.
Bool_t IsUpdated() const
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:538
Int_t GetKeylen() const
Definition TKey.h:84
Int_t GetNbytes() const
Definition TKey.h:86
virtual const char * GetClassName() const
Definition TKey.h:75
static TClass * Class()
static TClass * Class()
static TClass * Class()
static TClass * Class()
A TLeaf describes individual elements of a TBranch See TBranch structure in TTree.
Definition TLeaf.h:57
virtual 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
virtual Bool_t IncludeRange(TLeaf *)
Definition TLeaf.h:146
TClass * IsA() const override
Definition TLeaf.h:168
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:1191
void Clear(Option_t *option="") override
Remove all objects from the list.
Definition TList.cxx:402
TObject * FindObject(const char *name) const override
Find an object in this list using its name.
Definition TList.cxx:578
void RecursiveRemove(TObject *obj) override
Remove object from this collection and recursively remove the object from all other objects (and coll...
Definition TList.cxx:764
void Add(TObject *obj) override
Definition TList.h:81
TObject * Remove(TObject *obj) override
Remove object from the list.
Definition TList.cxx:822
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:470
TObject * At(Int_t idx) const override
Returns the object at position idx. Returns 0 if idx is out of range.
Definition TList.cxx:357
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
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.
Definition TObject.cxx:588
virtual const char * GetName() const
Returns name of object.
Definition TObject.cxx:439
R__ALWAYS_INLINE Bool_t TestBit(UInt_t f) const
Definition TObject.h:201
@ kBitMask
Definition TObject.h:86
virtual const char * ClassName() const
Returns name of class to which the object belongs.
Definition TObject.cxx:207
virtual void Warning(const char *method, const char *msgfmt,...) const
Issue warning message.
Definition TObject.cxx:956
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:874
@ 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:774
virtual Bool_t InheritsFrom(const char *classname) const
Returns kTRUE if object inherits from class "classname".
Definition TObject.cxx:525
virtual void Error(const char *method, const char *msgfmt,...) const
Issue error message.
Definition TObject.cxx:970
virtual void Fatal(const char *method, const char *msgfmt,...) const
Issue fatal error message.
Definition TObject.cxx:998
virtual const char * GetTitle() const
Returns title of object.
Definition TObject.cxx:483
virtual TClass * IsA() const
Definition TObject.h:245
void ResetBit(UInt_t f)
Definition TObject.h:200
@ 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:944
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)
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:421
void ToLower()
Change string to lower-case.
Definition TString.cxx:1170
static constexpr Ssiz_t kNPOS
Definition TString.h:280
TSubString Strip(EStripType s=kTrailing, char c=' ') const
Return a substring of self stripped at beginning and/or end.
Definition TString.cxx:1151
Double_t Atof() const
Return floating-point value contained in string.
Definition TString.cxx:2032
Ssiz_t First(char c) const
Find first occurrence of a character c.
Definition TString.cxx:531
const char * Data() const
Definition TString.h:380
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:278
@ kTrailing
Definition TString.h:278
@ kIgnoreCase
Definition TString.h:279
Ssiz_t Last(char c) const
Find last occurrence of a character c.
Definition TString.cxx:924
TObjArray * Tokenize(const TString &delim) const
This function is used to isolate sequential tokens in a TString.
Definition TString.cxx:2242
Bool_t IsNull() const
Definition TString.h:418
TString & Remove(Ssiz_t pos)
Definition TString.h:685
TString & Append(const char *cs)
Definition TString.h:576
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:2356
void Form(const char *fmt,...)
Formats a string using a printf style format descriptor.
Definition TString.cxx:2334
Bool_t Contains(const char *pat, ECaseCompare cmp=kExact) const
Definition TString.h:636
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:363
Color_t GetHistLineColor() const
Definition TStyle.h:225
Bool_t IsReading() const
Definition TStyle.h:283
void SetHistLineStyle(Style_t styl=0)
Definition TStyle.h:366
Style_t GetHistFillStyle() const
Definition TStyle.h:226
Color_t GetHistFillColor() const
Definition TStyle.h:224
void SetHistLineColor(Color_t color=1)
Definition TStyle.h:364
Style_t GetHistLineStyle() const
Definition TStyle.h:227
void SetHistFillStyle(Style_t styl=0)
Definition TStyle.h:365
Width_t GetHistLineWidth() const
Definition TStyle.h:228
void SetHistLineWidth(Width_t width=1)
Definition TStyle.h:367
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:1666
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:1299
A TTreeCache which exploits parallelized decompression of its own content.
static Bool_t IsParallelUnzip()
Static function that tells wether the multithreading unzipping is activated.
A cache to speed-up the reading of ROOT datasets.
Definition TTreeCache.h:32
static void SetLearnEntries(Int_t n=10)
Static function to set the number of entries to be used in learning mode The default value for n is 1...
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...
Bool_t IsAutoCreated() const
Definition TTreeCache.h:150
void SetAutoCreated(Bool_t val)
Definition TTreeCache.h:164
virtual Int_t DropBranch(TBranch *b, Bool_t subbranches=kFALSE)
Remove a branch to the list of branches to be stored in the cache this function is called by TBranch:...
Int_t SetBufferSize(Int_t buffersize) override
Change the underlying buffer size of the cache.
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_t subgbranches=kFALSE) 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
Bool_t Exec()
Execute the cloning.
Bool_t IsValid()
const char * GetWarning() const
void SetCacheSize(Int_t size)
Set the TFile cache size to be used.
Bool_t NeedConversion()
Iterator on all the leaves in a TTree and its friend.
Definition TTree.h:665
TTree * fTree
tree being iterated
Definition TTree.h:668
TIterator & operator=(const TIterator &rhs) override
Overridden assignment operator. Does NOT copy the 'cursor' location!
Definition TTree.cxx:9747
TObject * Next() override
Go the next friend element.
Definition TTree.cxx:9770
TIterator * fLeafIter
current leaf sub-iterator.
Definition TTree.h:669
Option_t * GetOption() const override
Returns the object option stored in the list.
Definition TTree.cxx:9809
TIterator * fTreeIter
current tree sub-iterator.
Definition TTree.h:670
Bool_t fDirection
iteration direction
Definition TTree.h:671
static TClass * Class()
Helper class to iterate over cluster of baskets.
Definition TTree.h:267
Long64_t GetEstimatedClusterSize()
Estimate the cluster size.
Definition TTree.cxx:610
Long64_t Previous()
Move on to the previous cluster and return the starting entry of this previous cluster.
Definition TTree.cxx:693
Long64_t Next()
Move on to the next cluster and return the starting entry of this next cluster.
Definition TTree.cxx:649
Long64_t GetNextEntry()
Definition TTree.h:304
TClusterIterator(TTree *tree, Long64_t firstEntry)
Regular constructor.
Definition TTree.cxx:559
Helper class to prevent infinite recursion in the usage of TTree Friends.
Definition TTree.h:185
TFriendLock & operator=(const TFriendLock &)
Assignment operator.
Definition TTree.cxx:529
TFriendLock(const TFriendLock &)
Copy constructor.
Definition TTree.cxx:519
UInt_t fMethodBit
Definition TTree.h:189
TTree * fTree
Definition TTree.h:188
~TFriendLock()
Restore the state of tree the same as before we set the lock.
Definition TTree.cxx:542
Bool_t fPrevious
Definition TTree.h:190
A TTree represents a columnar dataset.
Definition TTree.h:79
virtual Int_t Fill()
Fill all branches.
Definition TTree.cxx:4594
virtual TFriendElement * AddFriend(const char *treename, const char *filename="")
Add a TFriendElement to the list of friends.
Definition TTree.cxx:1330
TBranchRef * fBranchRef
Branch supporting the TRefTable (if any)
Definition TTree.h:133
virtual Int_t AddBranchToCache(const char *bname, Bool_t subbranches=kFALSE)
Add branch with name bname to the Tree cache.
Definition TTree.cxx:1058
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:4832
virtual TBranch * GetBranch(const char *name)
Return pointer to the branch with the given name in this tree or its friends.
Definition TTree.cxx:5285
static Int_t GetBranchStyle()
Static function returning the current branch style.
Definition TTree.cxx:5386
TList * fFriends
pointer to list of friend elements
Definition TTree.h:127
UInt_t fFriendLockStatus
! Record which method is locking the friend recursion
Definition TTree.h:134
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:6089
Long64_t fTotBytes
Total number of bytes in all branches before compression.
Definition TTree.h:86
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:9340
TEventList * fEventList
! Pointer to event selection list (if one)
Definition TTree.h:122
virtual Long64_t GetAutoSave() const
Definition TTree.h:445
Long64_t GetCacheAutoSize(Bool_t withDefault=kFALSE)
Used for automatic sizing of the cache.
Definition TTree.cxx:5398
virtual Int_t StopCacheLearningPhase()
Stop the cache learning phase.
Definition TTree.cxx:9429
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:5629
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:141
virtual void SetCircular(Long64_t maxEntries)
Enable/Disable circularity for this tree.
Definition TTree.cxx:8873
Long64_t fSavedBytes
Number of autosaved bytes.
Definition TTree.h:88
Long64_t GetMedianClusterSize()
Estimate the median cluster size for the TTree.
Definition TTree.cxx:8283
virtual TClusterIterator GetClusterIterator(Long64_t firstentry)
Return an iterator over the cluster of baskets starting at firstentry.
Definition TTree.cxx:5458
virtual void ResetBranchAddress(TBranch *)
Tell all of our branches to set their addresses to zero.
Definition TTree.cxx:8056
char GetNewlineValue(std::istream &inputStream)
Determine which newline this file is using.
Definition TTree.cxx:7579
virtual Int_t CheckBranchAddressType(TBranch *branch, TClass *ptrClass, EDataType datatype, Bool_t ptr)
Check whether or not the address described by the last 3 parameters matches the content of the branch...
Definition TTree.cxx:2864
TIOFeatures fIOFeatures
IO features to define for newly-written baskets and branches.
Definition TTree.h:114
Bool_t Notify() override
Function called when loading a new class library.
Definition TTree.cxx:7024
virtual Long64_t GetEntryNumberWithIndex(Long64_t major, Long64_t minor=0) const
Return entry number corresponding to major and minor number.
Definition TTree.cxx:5901
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:8992
virtual TObjArray * GetListOfLeaves()
Definition TTree.h:486
Bool_t fCacheDoClusterPrefetch
! true if cache is prefetching whole clusters
Definition TTree.h:137
virtual TBranch * BranchOld(const char *name, const char *classname, void *addobj, Int_t bufsize=32000, Int_t splitlevel=1)
Create a new TTree BranchObject.
Definition TTree.cxx:2071
virtual TBranch * BranchRef()
Build the optional branch supporting the TRefTable.
Definition TTree.cxx:2325
virtual Bool_t 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:7003
TFile * GetCurrentFile() const
Return pointer to the current file.
Definition TTree.cxx:5470
TList * fAliases
List of aliases for expressions based on the tree branches.
Definition TTree.h:121
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:3713
virtual Int_t FlushBaskets(Bool_t 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:5120
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:5070
Int_t SetCacheSizeAux(Bool_t autocache=kTRUE, Long64_t cacheSize=0)
Set the size of the file cache and create it if possible.
Definition TTree.cxx:8693
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:9500
std::atomic< Long64_t > fIMTZipBytes
! Zip bytes for the IMT flush baskets.
Definition TTree.h:158
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:7872
TVirtualTreePlayer * GetPlayer()
Load the TTreePlayer (if not already done).
Definition TTree.cxx:6296
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:6759
virtual Long64_t ReadStream(std::istream &inputStream, const char *branchDescriptor="", char delimiter=' ')
Create or simply read branches from an input stream.
Definition TTree.cxx:7606
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:8909
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:428
virtual ~TTree()
Destructor.
Definition TTree.cxx:919
virtual TTree * GetFriend(const char *) const
Return a pointer to the TTree friend whose name or alias is friendname.
Definition TTree.cxx:5966
virtual Long64_t CopyEntries(TTree *tree, Long64_t nentries=-1, Option_t *option="", Bool_t needCopyAddresses=false)
Copy nentries from given tree to this tree.
Definition TTree.cxx:3528
virtual Double_t GetMaximum(const char *columname)
Return maximum of column with name columname.
Definition TTree.cxx:6226
virtual Long64_t GetEntryNumberWithBestIndex(Long64_t major, Long64_t minor=0) const
Return entry number corresponding to major and minor number.
Definition TTree.cxx:5881
static void SetMaxTreeSize(Long64_t maxsize=100000000000LL)
Set the maximum size in bytes of a Tree file (static function).
Definition TTree.cxx:9178
void Print(Option_t *option="") const override
Print a summary of the tree contents.
Definition TTree.cxx:7210
virtual TBranch * BronchExec(const char *name, const char *classname, void *addobj, Bool_t isptrptr, Int_t bufsize, Int_t splitlevel)
Helper function implementing TTree::Bronch and TTree::Branch(const char *name, T &obj);.
Definition TTree.cxx:2409
virtual 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:9657
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:7361
virtual Int_t BuildIndex(const char *majorname, const char *minorname="0")
Build a Tree Index (default is TTreeIndex).
Definition TTree.cxx:2634
TVirtualTreePlayer * fPlayer
! Pointer to current Tree player
Definition TTree.h:131
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:9158
TObjArray fBranches
List of Branches.
Definition TTree.h:119
TDirectory * GetDirectory() const
Definition TTree.h:459
TTreeCache * GetReadCache(TFile *file) const
Find and return the TTreeCache registered with the file and which may contain branches for us.
Definition TTree.cxx:6309
Bool_t fCacheUserSet
! true if the cache setting was explicitly given by user
Definition TTree.h:138
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:2746
virtual Bool_t GetBranchStatus(const char *branchname) const
Return status of branch with name branchname.
Definition TTree.cxx:5371
virtual TEntryList * GetEntryList()
Returns the entry list assigned to this tree.
Definition TTree.cxx:5845
TStreamerInfo * BuildStreamerInfo(TClass *cl, void *pointer=nullptr, Bool_t canOptimize=kTRUE)
Build StreamerInfo for class cl.
Definition TTree.cxx:2649
virtual void SetWeight(Double_t w=1, Option_t *option="")
Set tree weight.
Definition TTree.cxx:9329
void InitializeBranchLists(bool checkLeafCount)
Divides the top-level branches into two vectors: (i) branches to be processed sequentially and (ii) b...
Definition TTree.cxx:5772
virtual Int_t SetBranchAddress(const char *bname, void *add, TBranch **ptr=nullptr)
Change branch address, dealing with clone trees properly.
Definition TTree.cxx:8371
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:9284
std::atomic< Long64_t > fIMTTotBytes
! Total bytes for the IMT flush baskets
Definition TTree.h:157
virtual void SetCacheLearnEntries(Int_t n=10)
Interface to TTreeCache to set the number of entries for the learning phase.
Definition TTree.cxx:8846
TEntryList * fEntryList
! Pointer to event selection list (if one)
Definition TTree.h:123
virtual TVirtualIndex * GetTreeIndex() const
Definition TTree.h:515
TList * fExternalFriends
! List of TFriendsElement pointing to us and need to be notified of LoadTree. Content not owned.
Definition TTree.h:128
virtual Long64_t Merge(TCollection *list, Option_t *option="")
Merge the trees in the TList into this tree.
Definition TTree.cxx:6881
virtual void SetMaxVirtualSize(Long64_t size=0)
Definition TTree.h:622
virtual void DropBaskets()
Remove some baskets from memory.
Definition TTree.cxx:4509
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:8328
Long64_t fMaxEntryLoop
Maximum number of entries to process.
Definition TTree.h:98
virtual void SetDirectory(TDirectory *dir)
Change the tree's directory.
Definition TTree.cxx:8947
void SortBranchesByTime()
Sorts top-level branches by the last average task time recorded per branch.
Definition TTree.cxx:5825
void Delete(Option_t *option="") override
Delete this tree from memory or/and disk.
Definition TTree.cxx:3741
virtual TBranchRef * GetBranchRef() const
Definition TTree.h:447
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:7441
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:1633
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:9050
void MoveReadCache(TFile *src, TDirectory *dir)
Move a cache from a file to the current file in dir.
Definition TTree.cxx:6974
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:8025
virtual void CopyAddresses(TTree *, Bool_t undo=kFALSE)
Set branch addresses of passed tree equal to ours.
Definition TTree.cxx:3293
virtual Long64_t GetEntries() const
Definition TTree.h:460
virtual void SetEstimate(Long64_t nentries=1000000)
Set number of entries to estimate variable limits.
Definition TTree.cxx:9091
virtual TIterator * GetIteratorOnAllLeaves(Bool_t dir=kIterForward)
Creates a new iterator that will go through all the leaves on the tree itself and its friend.
Definition TTree.cxx:6073
Int_t fTimerInterval
Timer interval in milliseconds.
Definition TTree.h:91
Int_t fDebug
! Debug level
Definition TTree.h:111
virtual Long64_t AutoSave(Option_t *option="")
AutoSave tree header every fAutoSave bytes.
Definition TTree.cxx:1498
virtual Long64_t GetEntryNumber(Long64_t entry) const
Return entry number corresponding to entry.
Definition TTree.cxx:5856
virtual TTree * CloneTree(Long64_t nentries=-1, Option_t *option="")
Create a clone of this tree and copy nentries.
Definition TTree.cxx:3133
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:6186
virtual Long64_t GetZipBytes() const
Definition TTree.h:542
TObjArray fLeaves
Direct pointers to individual branch leaves.
Definition TTree.h:120
virtual void Reset(Option_t *option="")
Reset baskets, buffers and entries count in all branches and leaves.
Definition TTree.cxx:7994
virtual void KeepCircular()
Keep a maximum of fMaxEntries in memory.
Definition TTree.cxx:6406
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:3813
virtual Bool_t SetAlias(const char *aliasName, const char *aliasFormula)
Set a tree variable alias.
Definition TTree.cxx:8127
Long64_t fMaxVirtualSize
Maximum total size of buffers kept in memory.
Definition TTree.h:99
virtual Long64_t GetTotBytes() const
Definition TTree.h:513
virtual Int_t MakeSelector(const char *selector=nullptr, Option_t *option="")
Generate skeleton selector class for this tree.
Definition TTree.cxx:6813
virtual void SetObject(const char *name, const char *title)
Change the name and title of this tree.
Definition TTree.cxx:9215
TVirtualPerfStats * fPerfStats
! pointer to the current perf stats object
Definition TTree.h:129
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:142
Bool_t EnableCache()
Enable the TTreeCache unless explicitly disabled for this TTree by a prior call to SetCacheSize(0).
Definition TTree.cxx:2682
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:736
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:350
@ kSplitCollectionOfPointers
Definition TTree.h:263
virtual void SetDefaultEntryOffsetLen(Int_t newdefault, Bool_t updateExisting=kFALSE)
Update the default value for the branch's fEntryOffsetLen.
Definition TTree.cxx:8921
std::atomic< UInt_t > fAllocationCount
indicates basket should be resized to exact memory usage, but causes significant
Definition TTree.h:149
virtual Int_t GetEntryWithIndex(Int_t major, Int_t minor=0)
Read entry corresponding to major and minor number.
Definition TTree.cxx:5918
static TTree * MergeTrees(TList *list, Option_t *option="")
Static function merging the trees in the TList into a new tree.
Definition TTree.cxx:6842
virtual void SetBranchStatus(const char *bname, Bool_t status=1, UInt_t *found=nullptr)
Set branch status to Process or DoNotProcess.
Definition TTree.cxx:8520
virtual Long64_t GetReadEntry() const
Definition TTree.h:506
virtual TObjArray * GetListOfBranches()
Definition TTree.h:485
virtual void SetParallelUnzip(Bool_t opt=kTRUE, Float_t RelSize=-1)
Enable or disable parallel unzipping of Tree buffers.
Definition TTree.cxx:9246
Long64_t fZipBytes
Total number of bytes in all branches after compression.
Definition TTree.h:87
virtual TTree * GetTree() const
Definition TTree.h:514
TBuffer * fTransientBuffer
! Pointer to the current transient buffer.
Definition TTree.h:135
Bool_t fIMTEnabled
! true if implicit multi-threading is enabled for this tree
Definition TTree.h:139
virtual void SetEntryList(TEntryList *list, Option_t *opt="")
Set an EntryList.
Definition TTree.cxx:9027
virtual Int_t DropBranchFromCache(const char *bname, Bool_t subbranches=kFALSE)
Remove the branch with name 'bname' from the Tree cache.
Definition TTree.cxx:1141
virtual void AddZipBytes(Int_t zip)
Definition TTree.h:329
virtual Long64_t LoadTree(Long64_t entry)
Set current entry.
Definition TTree.cxx:6464
virtual Long64_t ReadFile(const char *filename, const char *branchDescriptor="", char delimiter=' ')
Create or simply read branches from filename.
Definition TTree.cxx:7555
virtual const char * GetAlias(const char *aliasName) const
Returns the expanded value of the alias. Search in the friends if any.
Definition TTree.cxx:5217
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:9111
virtual TBasket * CreateBasket(TBranch *)
Create a basket for this tree and given branch.
Definition TTree.cxx:3725
TList * fUserInfo
pointer to a list of user objects associated to this Tree
Definition TTree.h:130
virtual Double_t GetMinimum(const char *columname)
Return minimum of column with name columname.
Definition TTree.cxx:6266
virtual void RemoveFriend(TTree *)
Remove a friend from the list of friends.
Definition TTree.cxx:7968
virtual Long64_t GetEntriesFast() const
Definition TTree.h:462
void Browse(TBrowser *) override
Browse content of the TTree.
Definition TTree.cxx:2606
virtual TList * GetUserInfo()
Return a pointer to the list containing user objects associated to this tree.
Definition TTree.cxx:6347
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:253
@ kEntriesReshuffled
If set, signals that this TTree is the output of the processing of another TTree, and the entries are...
Definition TTree.h:258
@ kCircular
Definition TTree.h:249
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:5503
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:7504
virtual TBranch * Bronch(const char *name, const char *classname, void *addobj, Int_t bufsize=32000, Int_t splitlevel=99)
Create a new TTree BranchElement.
Definition TTree.cxx:2401
virtual void SetBasketSize(const char *bname, Int_t buffsize=16000)
Set a branch's basket size.
Definition TTree.cxx:8344
static void SetBranchStyle(Int_t style=1)
Set the current branch style.
Definition TTree.cxx:8651
void ImportClusterRanges(TTree *fromtree)
Appends the cluster range information stored in 'fromtree' to this tree, including the value of fAuto...
Definition TTree.cxx:6363
TClass * IsA() const override
Definition TTree.h:654
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:5137
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:6548
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:9708
TVirtualIndex * fTreeIndex
Pointer to the tree Index (if any)
Definition TTree.h:126
void UseCurrentStyle() override
Replace current attributes by current style.
Definition TTree.cxx:9669
TObject * fNotify
! Object to be notified when loading a Tree
Definition TTree.h:117
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:1552
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:132
std::atomic< Long64_t > fTotalBuffers
! Total number of bytes in branch buffers
Definition TTree.h:108
Bool_t fCacheDoAutoInit
! true if cache auto creation or resize check is needed
Definition TTree.h:136
static TClass * Class()
@ kFindBranch
Definition TTree.h:209
@ kFindLeaf
Definition TTree.h:210
@ kGetEntryWithIndex
Definition TTree.h:214
@ kPrint
Definition TTree.h:219
@ kGetFriend
Definition TTree.h:215
@ kGetBranch
Definition TTree.h:212
@ kSetBranchStatus
Definition TTree.h:221
@ kLoadTree
Definition TTree.h:218
@ kGetEntry
Definition TTree.h:213
@ kGetLeaf
Definition TTree.h:217
@ kRemoveFriend
Definition TTree.h:220
@ kGetFriendAlias
Definition TTree.h:216
@ kGetAlias
Definition TTree.h:211
virtual void SetTreeIndex(TVirtualIndex *index)
The current TreeIndex is replaced by the new index.
Definition TTree.cxx:9301
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:7048
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:7489
virtual Int_t SetCacheEntryRange(Long64_t first, Long64_t last)
interface to TTreeCache to set the cache entry range
Definition TTree.cxx:8812
static Long64_t GetMaxTreeSize()
Static function which returns the tree file size limit in bytes.
Definition TTree.cxx:6256
Int_t SetBranchAddressImp(TBranch *branch, void *addr, TBranch **ptr)
Change branch address, dealing with clone trees properly.
Definition TTree.cxx:8431
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:4522
virtual TList * GetListOfFriends() const
Definition TTree.h:487
virtual void Refresh()
Refresh contents of this tree and its branches from the current status on disk.
Definition TTree.cxx:7907
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:8182
static Long64_t fgMaxTreeSize
Maximum size of a file containing a Tree.
Definition TTree.h:152
Long64_t fReadEntry
! Number of the entry being processed
Definition TTree.h:107
TArrayD fIndexValues
Sorted index values.
Definition TTree.h:124
void MarkEventCluster()
Mark the previous event as being at the end of the event cluster.
Definition TTree.cxx:8244
UInt_t fNEntriesSinceSorting
! Number of entries processed since the last re-sorting of branches
Definition TTree.h:140
virtual void SetFileNumber(Int_t number=0)
Set fFileNumber to number.
Definition TTree.cxx:9134
virtual TLeaf * FindLeaf(const char *name)
Find leaf..
Definition TTree.cxx:4907
virtual void StartViewer()
Start the TTreeViewer on this tree.
Definition TTree.cxx:9414
Int_t GetMakeClass() const
Definition TTree.h:492
virtual Int_t MakeCode(const char *filename=nullptr)
Generate a skeleton function for this tree.
Definition TTree.cxx:6631
TDirectory * fDirectory
! Pointer to directory holding this tree
Definition TTree.h:118
@ kNeedEnableDecomposedObj
Definition TTree.h:241
@ kClassMismatch
Definition TTree.h:234
@ kVoidPtr
Definition TTree.h:239
@ kMatchConversionCollection
Definition TTree.h:237
@ kMissingCompiledCollectionProxy
Definition TTree.h:232
@ kMismatch
Definition TTree.h:233
@ kMatchConversion
Definition TTree.h:236
@ kInternalError
Definition TTree.h:231
@ kMatch
Definition TTree.h:235
@ kMissingBranch
Definition TTree.h:230
@ kMakeClass
Definition TTree.h:238
static Int_t fgBranchStyle
Old/New branch style.
Definition TTree.h:151
virtual void ResetBranchAddresses()
Tell all of our branches to drop their current objects and allocate new ones.
Definition TTree.cxx:8066
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:9186
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:7948
TArrayI fIndex
Index of sorted values.
Definition TTree.h:125
virtual Int_t SetCacheSize(Long64_t cachesize=-1)
Set maximum size of the file cache .
Definition TTree.cxx:8667
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:1218
TBuffer * GetTransientBuffer(Int_t size)
Returns the transient buffer currently used by this TTree for reading/writing baskets.
Definition TTree.cxx:1036
ROOT::TIOFeatures GetIOFeatures() const
Returns the current set of IO settings.
Definition TTree.cxx:6065
virtual Int_t MakeClass(const char *classname=nullptr, Option_t *option="")
Generate a skeleton analysis class for this tree.
Definition TTree.cxx:6598
virtual const char * GetFriendAlias(TTree *) const
If the 'tree' is a friend, this method returns its alias name.
Definition TTree.cxx:6023
virtual void RemoveExternalFriend(TFriendElement *)
Removes external friend.
Definition TTree.cxx:7959
Bool_t MemoryFull(Int_t nbytes)
Check if adding nbytes to memory we are still below MaxVirtualsize.
Definition TTree.cxx:6828
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:1729
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:8085
Bool_t fIMTFlush
! True if we are doing a multithreaded flush.
Definition TTree.h:156
virtual void AddTotBytes(Int_t tot)
Definition TTree.h:328
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:6442
static constexpr Long64_t kMaxEntries
Definition TTree.h:226
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:7191
virtual Long64_t GetAutoFlush() const
Definition TTree.h:444
virtual EDataType GetType() const =0
virtual TClass * GetValueClass() const =0
virtual Bool_t HasPointers() const =0
Abstract interface for Tree Index.
virtual void Append(const TVirtualIndex *, Bool_t delaySort=kFALSE)=0
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 const char * GetMinorName() const =0
virtual void SetTree(TTree *T)=0
virtual Long64_t GetN() const =0
virtual Long64_t GetEntryNumberWithBestIndex(Long64_t major, Long64_t minor) const =0
virtual Bool_t IsValidFor(const TTree *parent)=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:389
This file contains a specialised ROOT message handler to test for diagnostic in unit tests.
Bool_t IsImplicitMTEnabled()
Returns true if the implicit multi-threading in ROOT is enabled.
Definition TROOT.cxx:558
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:394
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
Short_t Min(Short_t a, Short_t b)
Returns the smallest of a and b.
Definition TMathBase.h:198
Double_t Median(Long64_t n, const T *a, const Double_t *w=0, Long64_t *work=0)
Same as RMS.
Definition TMath.h:1270
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
Definition file.py:1
Definition first.py:1
Definition tree.py:1
TCanvas * slash()
Definition slash.C:1
@ kUseGlobal
Use the global compression algorithm.
Definition Compression.h:88
@ kInherit
Some objects use this value to denote that the compression algorithm should be inherited from the par...
Definition Compression.h:86
@ kUseCompiledDefault
Use the compile-time default setting.
Definition Compression.h:50
th1 Draw()
TMarker m
Definition textangle.C:8
TLine l
Definition textangle.C:4