Logo ROOT  
Reference Guide
 
Loading...
Searching...
No Matches
TTree.cxx
Go to the documentation of this file.
1// @(#)root/tree:$Id$
2// Author: Rene Brun 12/01/96
3
4/*************************************************************************
5 * Copyright (C) 1995-2000, Rene Brun and Fons Rademakers. *
6 * All rights reserved. *
7 * *
8 * For the licensing terms see $ROOTSYS/LICENSE. *
9 * For the list of contributors see $ROOTSYS/README/CREDITS. *
10 *************************************************************************/
11/**
12 \defgroup tree Tree Library
13
14 In order to store columnar datasets, ROOT provides the TTree, TChain,
15 TNtuple and TNtupleD classes.
16 The TTree class represents a columnar dataset. Any C++ type can be stored in the
17 columns. The TTree has allowed to store about **1 EB** of data coming from the LHC alone:
18 it is demonstrated to scale and it's battle tested. It has been optimized during the years
19 to reduce dataset sizes on disk and to deliver excellent runtime performance.
20 It allows to access only part of the columns of the datasets, too.
21 The TNtuple and TNtupleD classes are specialisations of the TTree class which can
22 only hold single precision and double precision floating-point numbers respectively;
23 The TChain is a collection of TTrees, which can be located also in different files.
24
25*/
26
27/** \class TTree
28\ingroup tree
29
30A TTree represents a columnar dataset. Any C++ type can be stored in its columns.
31
32A TTree, often called in jargon *tree*, consists of a list of independent columns or *branches*,
33represented by the TBranch class.
34Behind each branch, buffers are allocated automatically by ROOT.
35Such buffers are automatically written to disk or kept in memory until the size stored in the
36attribute fMaxVirtualSize is reached.
37Variables of one branch are written to the same buffer. A branch buffer is
38automatically compressed if the file compression attribute is set (default).
39Branches may be written to different files (see TBranch::SetFile).
40
41The ROOT user can decide to make one single branch and serialize one object into
42one single I/O buffer or to make several branches.
43Making several branches is particularly interesting in the data analysis phase,
44when it is desirable to have a high reading rate and not all columns are equally interesting
45
46\anchor creatingattreetoc
47## Create a TTree to store columnar data
48- [Construct a TTree](\ref creatingattree)
49- [Add a column of Fundamental Types and Arrays thereof](\ref addcolumnoffundamentaltypes)
50- [Add a column of a STL Collection instances](\ref addingacolumnofstl)
51- [Add a column holding an object](\ref addingacolumnofobjs)
52- [Add a column holding a TObjectArray](\ref addingacolumnofobjs)
53- [Fill the tree](\ref fillthetree)
54- [Add a column to an already existing Tree](\ref addcoltoexistingtree)
55- [An Example](\ref fullexample)
56
57\anchor creatingattree
58## Construct a TTree
59
60~~~ {.cpp}
61 TTree tree(name, title)
62~~~
63Creates a Tree with name and title.
64
65Various kinds of branches can be added to a tree:
66- Variables representing fundamental types, simple classes/structures or list of variables: for example for C or Fortran
67structures.
68- Any C++ object or collection, provided by the STL or ROOT.
69
70In the following, the details about the creation of different types of branches are given.
71
72\anchor addcolumnoffundamentaltypes
73## Add a column ("branch") holding fundamental types and arrays thereof
74This strategy works also for lists of variables, e.g. to describe simple structures.
75It is strongly recommended to persistify those as objects rather than lists of leaves.
76
77~~~ {.cpp}
78 auto branch = tree.Branch(branchname, address, leaflist, bufsize)
79~~~
80- address is the address of the first item of a structure
81- leaflist is the concatenation of all the variable names and types
82 separated by a colon character :
83 The variable name and the variable type are separated by a
84 slash (/). The variable type must be 1 character. (Characters
85 after the first are legal and will be appended to the visible
86 name of the leaf, but have no effect.) If no type is given, the
87 type of the variable is assumed to be the same as the previous
88 variable. If the first variable does not have a type, it is
89 assumed of type F by default. The list of currently supported
90 types is given below:
91 - `C` : a character string terminated by the 0 character
92 - `B` : an 8 bit signed integer (`Char_t`); Treated as a character when in an array.
93 - `b` : an 8 bit unsigned integer (`UChar_t`)
94 - `S` : a 16 bit signed integer (`Short_t`)
95 - `s` : a 16 bit unsigned integer (`UShort_t`)
96 - `I` : a 32 bit signed integer (`Int_t`)
97 - `i` : a 32 bit unsigned integer (`UInt_t`)
98 - `F` : a 32 bit floating point (`Float_t`)
99 - `f` : a 24 bit floating point with truncated mantissa (`Float16_t`)
100 - `D` : a 64 bit floating point (`Double_t`)
101 - `d` : a 24 bit truncated floating point (`Double32_t`)
102 - `L` : a 64 bit signed integer (`Long64_t`)
103 - `l` : a 64 bit unsigned integer (`ULong64_t`)
104 - `G` : a long signed integer, stored as 64 bit (`Long_t`)
105 - `g` : a long unsigned integer, stored as 64 bit (`ULong_t`)
106 - `O` : [the letter `o`, not a zero] a boolean (`Bool_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 - The `myvar` column, which holds the variable size, **MUST** be an `Int_t` (/I).
114
115- If the address points to a single numerical variable, the leaflist is optional:
116~~~ {.cpp}
117 int value;
118 tree->Branch(branchname, &value);
119~~~
120- If the address points to more than one numerical variable, we strongly recommend
121 that the variable be sorted in decreasing order of size. Any other order will
122 result in a non-portable TTree (i.e. you will not be able to read it back on a
123 platform with a different padding strategy).
124 We recommend to persistify objects rather than composite leaflists.
125- In case of the truncated floating point types (Float16_t and Double32_t) you can
126 furthermore specify the range in the style [xmin,xmax] or [xmin,xmax,nbits] after
127 the type character. For example, for storing a variable size array `myArr` of
128 `Double32_t` with values within a range of `[0, 2*pi]` and the size of which is stored
129 in an `Int_t` (/I) branch called `myArrSize`, the syntax for the `leaflist` string would
130 be: `myArr[myArrSize]/d[0,twopi]`. Of course the number of bits could be specified,
131 the standard rules of opaque typedefs annotation are valid. For example, if only
132 18 bits were sufficient, the syntax would become: `myArr[myArrSize]/d[0,twopi,18]`
133
134\anchor addingacolumnofstl
135## Adding a column holding STL collection instances (e.g. std::vector, std::list, std::unordered_map)
136
137~~~ {.cpp}
138 auto branch = tree.Branch( branchname, STLcollection, buffsize, splitlevel);
139~~~
140STLcollection is the address of a pointer to std::vector, std::list,
141std::deque, std::set or std::multiset containing pointers to objects.
142If the splitlevel is a value bigger than 100 (TTree::kSplitCollectionOfPointers)
143then the collection will be written in split mode, e.g. if it contains objects of
144any types deriving from TTrack this function will sort the objects
145based on their type and store them in separate branches in split
146mode.
147
148~~~ {.cpp}
149 branch->SetAddress(void *address)
150~~~
151In case of dynamic structures changing with each entry for example, one must
152redefine the branch address before filling the branch again.
153This is done via the TBranch::SetAddress member function.
154
155\anchor addingacolumnofobjs
156## Add a column holding objects
157
158~~~ {.cpp}
159 MyClass object;
160 auto branch = tree.Branch(branchname, &object, bufsize, splitlevel)
161~~~
162Note: The 2nd parameter must be the address of a valid object.
163 The object must not be destroyed (i.e. be deleted) until the TTree
164 is deleted or TTree::ResetBranchAddress is called.
165
166- if splitlevel=0, the object is serialized in the branch buffer.
167- if splitlevel=1 (default), this branch will automatically be split
168 into subbranches, with one subbranch for each data member or object
169 of the object itself. In case the object member is a TClonesArray,
170 the mechanism described in case C is applied to this array.
171- if splitlevel=2 ,this branch will automatically be split
172 into subbranches, with one subbranch for each data member or object
173 of the object itself. In case the object member is a TClonesArray,
174 it is processed as a TObject*, only one branch.
175
176Another available syntax is the following:
177
178~~~ {.cpp}
179 auto branch = tree.Branch(branchname, &p_object, bufsize, splitlevel)
180 auto branch = tree.Branch(branchname, className, &p_object, bufsize, splitlevel)
181~~~
182- p_object is a pointer to an object.
183- If className is not specified, Branch uses the type of p_object to determine the
184 type of the object.
185- If className is used to specify explicitly the object type, the className must
186 be of a type related to the one pointed to by the pointer. It should be either
187 a parent or derived class.
188
189Note: The pointer whose address is passed to TTree::Branch must not
190 be destroyed (i.e. go out of scope) until the TTree is deleted or
191 TTree::ResetBranchAddress is called.
192
193Note: The pointer p_object must be initialized before calling TTree::Branch
194- Do either:
195~~~ {.cpp}
196 MyDataClass* p_object = nullptr;
197 tree.Branch(branchname, &p_object);
198~~~
199- Or:
200~~~ {.cpp}
201 auto p_object = new MyDataClass;
202 tree.Branch(branchname, &p_object);
203~~~
204Whether the pointer is set to zero or not, the ownership of the object
205is not taken over by the TTree. I.e. even though an object will be allocated
206by TTree::Branch if the pointer p_object is zero, the object will <b>not</b>
207be deleted when the TTree is deleted.
208
209\anchor addingacolumnoftclonesarray
210## Add a column holding TClonesArray instances
211
212*It is recommended to use STL containers instead of TClonesArrays*.
213
214~~~ {.cpp}
215 // clonesarray is the address of a pointer to a TClonesArray.
216 auto branch = tree.Branch(branchname,clonesarray, bufsize, splitlevel)
217~~~
218The TClonesArray is a direct access list of objects of the same class.
219For example, if the TClonesArray is an array of TTrack objects,
220this function will create one subbranch for each data member of
221the object TTrack.
222
223\anchor fillthetree
224## Fill the Tree
225
226A TTree instance is filled with the invocation of the TTree::Fill method:
227~~~ {.cpp}
228 tree.Fill()
229~~~
230Upon its invocation, a loop on all defined branches takes place that for each branch invokes
231the TBranch::Fill method.
232
233\anchor addcoltoexistingtree
234## Add a column to an already existing Tree
235
236You may want to add a branch to an existing tree. For example,
237if one variable in the tree was computed with a certain algorithm,
238you may want to try another algorithm and compare the results.
239One solution is to add a new branch, fill it, and save the tree.
240The code below adds a simple branch to an existing tree.
241Note the kOverwrite option in the Write method, it overwrites the
242existing tree. If it is not specified, two copies of the tree headers
243are saved.
244~~~ {.cpp}
245 void tree3AddBranch() {
246 TFile f("tree3.root", "update");
247
248 Float_t new_v;
249 auto t3 = f->Get<TTree>("t3");
250 auto newBranch = t3->Branch("new_v", &new_v, "new_v/F");
251
252 Long64_t nentries = t3->GetEntries(); // read the number of entries in the t3
253
254 for (Long64_t i = 0; i < nentries; i++) {
255 new_v = gRandom->Gaus(0, 1);
256 newBranch->Fill();
257 }
258
259 t3->Write("", TObject::kOverwrite); // save only the new version of the tree
260 }
261~~~
262It is not always possible to add branches to existing datasets stored in TFiles: for example,
263these files might not be writeable, just readable. In addition, modifying in place a TTree
264causes a new TTree instance to be written and the previous one to be deleted.
265For this reasons, ROOT offers the concept of friends for TTree and TChain:
266if is good practice to rely on friend trees rather than adding a branch manually.
267
268\anchor fullexample
269## An Example
270
271Begin_Macro
272../../../tutorials/tree/tree.C
273End_Macro
274
275~~~ {.cpp}
276 // A simple example with histograms and a tree
277 //
278 // This program creates :
279 // - a one dimensional histogram
280 // - a two dimensional histogram
281 // - a profile histogram
282 // - a tree
283 //
284 // These objects are filled with some random numbers and saved on a file.
285
286 #include "TFile.h"
287 #include "TH1.h"
288 #include "TH2.h"
289 #include "TProfile.h"
290 #include "TRandom.h"
291 #include "TTree.h"
292
293 //__________________________________________________________________________
294 main(int argc, char **argv)
295 {
296 // Create a new ROOT binary machine independent file.
297 // Note that this file may contain any kind of ROOT objects, histograms,trees
298 // pictures, graphics objects, detector geometries, tracks, events, etc..
299 // This file is now becoming the current directory.
300 TFile hfile("htree.root","RECREATE","Demo ROOT file with histograms & trees");
301
302 // Create some histograms and a profile histogram
303 TH1F hpx("hpx","This is the px distribution",100,-4,4);
304 TH2F hpxpy("hpxpy","py ps px",40,-4,4,40,-4,4);
305 TProfile hprof("hprof","Profile of pz versus px",100,-4,4,0,20);
306
307 // Define some simple structures
308 typedef struct {Float_t x,y,z;} POINT;
309 typedef struct {
310 Int_t ntrack,nseg,nvertex;
311 UInt_t flag;
312 Float_t temperature;
313 } EVENTN;
314 POINT point;
315 EVENTN eventn;
316
317 // Create a ROOT Tree
318 TTree tree("T","An example of ROOT tree with a few branches");
319 tree.Branch("point",&point,"x:y:z");
320 tree.Branch("eventn",&eventn,"ntrack/I:nseg:nvertex:flag/i:temperature/F");
321 tree.Branch("hpx","TH1F",&hpx,128000,0);
322
323 Float_t px,py,pz;
324
325 // Here we start a loop on 1000 events
326 for ( Int_t i=0; i<1000; i++) {
327 gRandom->Rannor(px,py);
328 pz = px*px + py*py;
329 const auto random = gRandom->::Rndm(1);
330
331 // Fill histograms
332 hpx.Fill(px);
333 hpxpy.Fill(px,py,1);
334 hprof.Fill(px,pz,1);
335
336 // Fill structures
337 point.x = 10*(random-1);
338 point.y = 5*random;
339 point.z = 20*random;
340 eventn.ntrack = Int_t(100*random);
341 eventn.nseg = Int_t(2*eventn.ntrack);
342 eventn.nvertex = 1;
343 eventn.flag = Int_t(random+0.5);
344 eventn.temperature = 20+random;
345
346 // Fill the tree. For each event, save the 2 structures and 3 objects
347 // In this simple example, the objects hpx, hprof and hpxpy are slightly
348 // different from event to event. We expect a big compression factor!
349 tree->Fill();
350 }
351 // End of the loop
352
353 tree.Print();
354
355 // Save all objects in this file
356 hfile.Write();
357
358 // Close the file. Note that this is automatically done when you leave
359 // the application upon file destruction.
360 hfile.Close();
361
362 return 0;
363}
364~~~
365*/
366
367#include <ROOT/RConfig.hxx>
368#include "TTree.h"
369
370#include "ROOT/TIOFeatures.hxx"
371#include "TArrayC.h"
372#include "TBufferFile.h"
373#include "TBaseClass.h"
374#include "TBasket.h"
375#include "TBranchClones.h"
376#include "TBranchElement.h"
377#include "TBranchObject.h"
378#include "TBranchRef.h"
379#include "TBrowser.h"
380#include "TClass.h"
381#include "TClassEdit.h"
382#include "TClonesArray.h"
383#include "TCut.h"
384#include "TDataMember.h"
385#include "TDataType.h"
386#include "TDirectory.h"
387#include "TError.h"
388#include "TEntryList.h"
389#include "TEnv.h"
390#include "TEventList.h"
391#include "TFile.h"
392#include "TFolder.h"
393#include "TFriendElement.h"
394#include "TInterpreter.h"
395#include "TLeaf.h"
396#include "TLeafB.h"
397#include "TLeafC.h"
398#include "TLeafD.h"
399#include "TLeafElement.h"
400#include "TLeafF.h"
401#include "TLeafI.h"
402#include "TLeafL.h"
403#include "TLeafObject.h"
404#include "TLeafS.h"
405#include "TList.h"
406#include "TMath.h"
407#include "TMemFile.h"
408#include "TROOT.h"
409#include "TRealData.h"
410#include "TRegexp.h"
411#include "TRefTable.h"
412#include "TStreamerElement.h"
413#include "TStreamerInfo.h"
414#include "TStyle.h"
415#include "TSystem.h"
416#include "TTreeCloner.h"
417#include "TTreeCache.h"
418#include "TTreeCacheUnzip.h"
421#include "TVirtualIndex.h"
422#include "TVirtualPerfStats.h"
423#include "TVirtualPad.h"
424#include "TBranchSTL.h"
425#include "TSchemaRuleSet.h"
426#include "TFileMergeInfo.h"
427#include "ROOT/StringConv.hxx"
428#include "TVirtualMutex.h"
429#include "strlcpy.h"
430#include "snprintf.h"
431
432#include "TBranchIMTHelper.h"
433#include "TNotifyLink.h"
434
435#include <chrono>
436#include <cstddef>
437#include <iostream>
438#include <fstream>
439#include <sstream>
440#include <string>
441#include <cstdio>
442#include <climits>
443#include <algorithm>
444#include <set>
445
446#ifdef R__USE_IMT
448#include <thread>
449#endif
451constexpr Int_t kNEntriesResort = 100;
453
454Int_t TTree::fgBranchStyle = 1; // Use new TBranch style with TBranchElement.
455Long64_t TTree::fgMaxTreeSize = 100000000000LL;
456
458
459////////////////////////////////////////////////////////////////////////////////
460////////////////////////////////////////////////////////////////////////////////
461////////////////////////////////////////////////////////////////////////////////
463static char DataTypeToChar(EDataType datatype)
464{
465 // Return the leaflist 'char' for a given datatype.
466
467 switch(datatype) {
468 case kChar_t: return 'B';
469 case kUChar_t: return 'b';
470 case kBool_t: return 'O';
471 case kShort_t: return 'S';
472 case kUShort_t: return 's';
473 case kCounter:
474 case kInt_t: return 'I';
475 case kUInt_t: return 'i';
476 case kDouble_t: return 'D';
477 case kDouble32_t: return 'd';
478 case kFloat_t: return 'F';
479 case kFloat16_t: return 'f';
480 case kLong_t: return 'G';
481 case kULong_t: return 'g';
482 case kchar: return 0; // unsupported
483 case kLong64_t: return 'L';
484 case kULong64_t: return 'l';
485
486 case kCharStar: return 'C';
487 case kBits: return 0; //unsupported
488
489 case kOther_t:
490 case kNoType_t:
491 default:
492 return 0;
493 }
494 return 0;
495}
496
497////////////////////////////////////////////////////////////////////////////////
498/// \class TTree::TFriendLock
499/// Helper class to prevent infinite recursion in the usage of TTree Friends.
500
501////////////////////////////////////////////////////////////////////////////////
502/// Record in tree that it has been used while recursively looks through the friends.
505: fTree(tree)
506{
507 // We could also add some code to acquire an actual
508 // lock to prevent multi-thread issues
509 fMethodBit = methodbit;
510 if (fTree) {
513 } else {
514 fPrevious = 0;
515 }
516}
517
518////////////////////////////////////////////////////////////////////////////////
519/// Copy constructor.
522 fTree(tfl.fTree),
523 fMethodBit(tfl.fMethodBit),
524 fPrevious(tfl.fPrevious)
525{
526}
527
528////////////////////////////////////////////////////////////////////////////////
529/// Assignment operator.
532{
533 if(this!=&tfl) {
534 fTree=tfl.fTree;
535 fMethodBit=tfl.fMethodBit;
536 fPrevious=tfl.fPrevious;
537 }
538 return *this;
539}
540
541////////////////////////////////////////////////////////////////////////////////
542/// Restore the state of tree the same as before we set the lock.
545{
546 if (fTree) {
547 if (!fPrevious) {
548 fTree->fFriendLockStatus &= ~(fMethodBit & kBitMask);
549 }
550 }
551}
552
553////////////////////////////////////////////////////////////////////////////////
554/// \class TTree::TClusterIterator
555/// Helper class to iterate over cluster of baskets.
556
557////////////////////////////////////////////////////////////////////////////////
558/// Regular constructor.
559/// TTree is not set as const, since we might modify if it is a TChain.
561TTree::TClusterIterator::TClusterIterator(TTree *tree, Long64_t firstEntry) : fTree(tree), fClusterRange(0), fStartEntry(0), fNextEntry(0), fEstimatedSize(-1)
562{
563 if (fTree->fNClusterRange) {
564 // Find the correct cluster range.
565 //
566 // Since fClusterRangeEnd contains the inclusive upper end of the range, we need to search for the
567 // range that was containing the previous entry and add 1 (because BinarySearch consider the values
568 // to be the inclusive start of the bucket).
570
571 Long64_t entryInRange;
572 Long64_t pedestal;
573 if (fClusterRange == 0) {
574 pedestal = 0;
575 entryInRange = firstEntry;
576 } else {
577 pedestal = fTree->fClusterRangeEnd[fClusterRange-1] + 1;
578 entryInRange = firstEntry - pedestal;
579 }
580 Long64_t autoflush;
582 autoflush = fTree->fAutoFlush;
583 } else {
584 autoflush = fTree->fClusterSize[fClusterRange];
585 }
586 if (autoflush <= 0) {
587 autoflush = GetEstimatedClusterSize();
588 }
589 fStartEntry = pedestal + entryInRange - entryInRange%autoflush;
590 } else if ( fTree->GetAutoFlush() <= 0 ) {
591 // Case of old files before November 9 2009 *or* small tree where AutoFlush was never set.
592 fStartEntry = firstEntry;
593 } else {
594 fStartEntry = firstEntry - firstEntry%fTree->GetAutoFlush();
595 }
596 fNextEntry = fStartEntry; // Position correctly for the first call to Next()
597}
598
599////////////////////////////////////////////////////////////////////////////////
600/// Estimate the cluster size.
601///
602/// In almost all cases, this quickly returns the size of the auto-flush
603/// in the TTree.
604///
605/// However, in the case where the cluster size was not fixed (old files and
606/// case where autoflush was explicitly set to zero), we need estimate
607/// a cluster size in relation to the size of the cache.
608///
609/// After this value is calculated once for the TClusterIterator, it is
610/// cached and reused in future calls.
613{
614 auto autoFlush = fTree->GetAutoFlush();
615 if (autoFlush > 0) return autoFlush;
616 if (fEstimatedSize > 0) return fEstimatedSize;
617
618 Long64_t zipBytes = fTree->GetZipBytes();
619 if (zipBytes == 0) {
620 fEstimatedSize = fTree->GetEntries() - 1;
621 if (fEstimatedSize <= 0)
622 fEstimatedSize = 1;
623 } else {
624 Long64_t clusterEstimate = 1;
625 Long64_t cacheSize = fTree->GetCacheSize();
626 if (cacheSize == 0) {
627 // Humm ... let's double check on the file.
628 TFile *file = fTree->GetCurrentFile();
629 if (file) {
630 TFileCacheRead *cache = fTree->GetReadCache(file);
631 if (cache) {
632 cacheSize = cache->GetBufferSize();
633 }
634 }
635 }
636 // If neither file nor tree has a cache, use the current default.
637 if (cacheSize <= 0) {
638 cacheSize = 30000000;
639 }
640 clusterEstimate = fTree->GetEntries() * cacheSize / zipBytes;
641 // If there are no entries, then just default to 1.
642 fEstimatedSize = clusterEstimate ? clusterEstimate : 1;
643 }
644 return fEstimatedSize;
645}
646
647////////////////////////////////////////////////////////////////////////////////
648/// Move on to the next cluster and return the starting entry
649/// of this next cluster
652{
653 fStartEntry = fNextEntry;
654 if (fTree->fNClusterRange || fTree->GetAutoFlush() > 0) {
655 if (fClusterRange == fTree->fNClusterRange) {
656 // We are looking at a range which size
657 // is defined by AutoFlush itself and goes to the GetEntries.
658 fNextEntry += GetEstimatedClusterSize();
659 } else {
660 if (fStartEntry > fTree->fClusterRangeEnd[fClusterRange]) {
661 ++fClusterRange;
662 }
663 if (fClusterRange == fTree->fNClusterRange) {
664 // We are looking at the last range which size
665 // is defined by AutoFlush itself and goes to the GetEntries.
666 fNextEntry += GetEstimatedClusterSize();
667 } else {
668 Long64_t clusterSize = fTree->fClusterSize[fClusterRange];
669 if (clusterSize == 0) {
670 clusterSize = GetEstimatedClusterSize();
671 }
672 fNextEntry += clusterSize;
673 if (fNextEntry > fTree->fClusterRangeEnd[fClusterRange]) {
674 // The last cluster of the range was a partial cluster,
675 // so the next cluster starts at the beginning of the
676 // next range.
677 fNextEntry = fTree->fClusterRangeEnd[fClusterRange] + 1;
678 }
679 }
680 }
681 } else {
682 // Case of old files before November 9 2009
683 fNextEntry = fStartEntry + GetEstimatedClusterSize();
684 }
685 if (fNextEntry > fTree->GetEntries()) {
686 fNextEntry = fTree->GetEntries();
687 }
688 return fStartEntry;
689}
690
691////////////////////////////////////////////////////////////////////////////////
692/// Move on to the previous cluster and return the starting entry
693/// of this previous cluster
696{
697 fNextEntry = fStartEntry;
698 if (fTree->fNClusterRange || fTree->GetAutoFlush() > 0) {
699 if (fClusterRange == 0 || fTree->fNClusterRange == 0) {
700 // We are looking at a range which size
701 // is defined by AutoFlush itself.
702 fStartEntry -= GetEstimatedClusterSize();
703 } else {
704 if (fNextEntry <= fTree->fClusterRangeEnd[fClusterRange]) {
705 --fClusterRange;
706 }
707 if (fClusterRange == 0) {
708 // We are looking at the first range.
709 fStartEntry = 0;
710 } else {
711 Long64_t clusterSize = fTree->fClusterSize[fClusterRange];
712 if (clusterSize == 0) {
713 clusterSize = GetEstimatedClusterSize();
714 }
715 fStartEntry -= clusterSize;
716 }
717 }
718 } else {
719 // Case of old files before November 9 2009 or trees that never auto-flushed.
720 fStartEntry = fNextEntry - GetEstimatedClusterSize();
721 }
722 if (fStartEntry < 0) {
723 fStartEntry = 0;
724 }
725 return fStartEntry;
726}
727
728////////////////////////////////////////////////////////////////////////////////
729////////////////////////////////////////////////////////////////////////////////
730////////////////////////////////////////////////////////////////////////////////
731
732////////////////////////////////////////////////////////////////////////////////
733/// Default constructor and I/O constructor.
734///
735/// Note: We do *not* insert ourself into the current directory.
736///
739: TNamed()
740, TAttLine()
741, TAttFill()
742, TAttMarker()
743, fEntries(0)
744, fTotBytes(0)
745, fZipBytes(0)
746, fSavedBytes(0)
747, fFlushedBytes(0)
748, fWeight(1)
750, fScanField(25)
751, fUpdate(0)
755, fMaxEntries(0)
756, fMaxEntryLoop(0)
758, fAutoSave( -300000000)
759, fAutoFlush(-30000000)
760, fEstimate(1000000)
762, fClusterSize(0)
763, fCacheSize(0)
764, fChainOffset(0)
765, fReadEntry(-1)
766, fTotalBuffers(0)
767, fPacketSize(100)
768, fNfill(0)
769, fDebug(0)
770, fDebugMin(0)
771, fDebugMax(9999999)
772, fMakeClass(0)
773, fFileNumber(0)
774, fNotify(0)
775, fDirectory(0)
776, fBranches()
777, fLeaves()
778, fAliases(0)
779, fEventList(0)
780, fEntryList(0)
781, fIndexValues()
782, fIndex()
783, fTreeIndex(0)
784, fFriends(0)
786, fPerfStats(0)
787, fUserInfo(0)
788, fPlayer(0)
789, fClones(0)
790, fBranchRef(0)
796, fIMTEnabled(ROOT::IsImplicitMTEnabled())
798{
799 fMaxEntries = 1000000000;
800 fMaxEntries *= 1000;
801
802 fMaxEntryLoop = 1000000000;
803 fMaxEntryLoop *= 1000;
804
806}
807
808////////////////////////////////////////////////////////////////////////////////
809/// Normal tree constructor.
810///
811/// The tree is created in the current directory.
812/// Use the various functions Branch below to add branches to this tree.
813///
814/// If the first character of title is a "/", the function assumes a folder name.
815/// In this case, it creates automatically branches following the folder hierarchy.
816/// splitlevel may be used in this case to control the split level.
818TTree::TTree(const char* name, const char* title, Int_t splitlevel /* = 99 */,
819 TDirectory* dir /* = gDirectory*/)
820: TNamed(name, title)
821, TAttLine()
822, TAttFill()
823, TAttMarker()
824, fEntries(0)
825, fTotBytes(0)
826, fZipBytes(0)
827, fSavedBytes(0)
828, fFlushedBytes(0)
829, fWeight(1)
830, fTimerInterval(0)
831, fScanField(25)
832, fUpdate(0)
833, fDefaultEntryOffsetLen(1000)
834, fNClusterRange(0)
835, fMaxClusterRange(0)
836, fMaxEntries(0)
837, fMaxEntryLoop(0)
838, fMaxVirtualSize(0)
839, fAutoSave( -300000000)
840, fAutoFlush(-30000000)
841, fEstimate(1000000)
842, fClusterRangeEnd(0)
843, fClusterSize(0)
844, fCacheSize(0)
845, fChainOffset(0)
846, fReadEntry(-1)
847, fTotalBuffers(0)
848, fPacketSize(100)
849, fNfill(0)
850, fDebug(0)
851, fDebugMin(0)
852, fDebugMax(9999999)
853, fMakeClass(0)
854, fFileNumber(0)
855, fNotify(0)
856, fDirectory(dir)
857, fBranches()
858, fLeaves()
859, fAliases(0)
860, fEventList(0)
861, fEntryList(0)
862, fIndexValues()
863, fIndex()
864, fTreeIndex(0)
865, fFriends(0)
866, fExternalFriends(0)
867, fPerfStats(0)
868, fUserInfo(0)
869, fPlayer(0)
870, fClones(0)
871, fBranchRef(0)
872, fFriendLockStatus(0)
873, fTransientBuffer(0)
874, fCacheDoAutoInit(kTRUE)
875, fCacheDoClusterPrefetch(kFALSE)
876, fCacheUserSet(kFALSE)
877, fIMTEnabled(ROOT::IsImplicitMTEnabled())
878, fNEntriesSinceSorting(0)
879{
880 // TAttLine state.
884
885 // TAttFill state.
888
889 // TAttMarkerState.
893
894 fMaxEntries = 1000000000;
895 fMaxEntries *= 1000;
896
897 fMaxEntryLoop = 1000000000;
898 fMaxEntryLoop *= 1000;
899
900 // Insert ourself into the current directory.
901 // FIXME: This is very annoying behaviour, we should
902 // be able to choose to not do this like we
903 // can with a histogram.
904 if (fDirectory) fDirectory->Append(this);
905
907
908 // If title starts with "/" and is a valid folder name, a superbranch
909 // is created.
910 // FIXME: Why?
911 if (strlen(title) > 2) {
912 if (title[0] == '/') {
913 Branch(title+1,32000,splitlevel);
914 }
915 }
916}
917
918////////////////////////////////////////////////////////////////////////////////
919/// Destructor.
922{
923 if (auto link = dynamic_cast<TNotifyLinkBase*>(fNotify)) {
924 link->Clear();
925 }
926 if (fAllocationCount && (gDebug > 0)) {
927 Info("TTree::~TTree", "For tree %s, allocation count is %u.", GetName(), fAllocationCount.load());
928#ifdef R__TRACK_BASKET_ALLOC_TIME
929 Info("TTree::~TTree", "For tree %s, allocation time is %lluus.", GetName(), fAllocationTime.load());
930#endif
931 }
932
933 if (fDirectory) {
934 // We are in a directory, which may possibly be a file.
935 if (fDirectory->GetList()) {
936 // Remove us from the directory listing.
937 fDirectory->Remove(this);
938 }
939 //delete the file cache if it points to this Tree
942 }
943
944 // Remove the TTree from any list (linked to to the list of Cleanups) to avoid the unnecessary call to
945 // this RecursiveRemove while we delete our content.
947 ResetBit(kMustCleanup); // Don't redo it.
948
949 // We don't own the leaves in fLeaves, the branches do.
950 fLeaves.Clear();
951 // I'm ready to destroy any objects allocated by
952 // SetAddress() by my branches. If I have clones,
953 // tell them to zero their pointers to this shared
954 // memory.
955 if (fClones && fClones->GetEntries()) {
956 // I have clones.
957 // I am about to delete the objects created by
958 // SetAddress() which we are sharing, so tell
959 // the clones to release their pointers to them.
960 for (TObjLink* lnk = fClones->FirstLink(); lnk; lnk = lnk->Next()) {
961 TTree* clone = (TTree*) lnk->GetObject();
962 // clone->ResetBranchAddresses();
963
964 // Reset only the branch we have set the address of.
965 CopyAddresses(clone,kTRUE);
966 }
967 }
968 // Get rid of our branches, note that this will also release
969 // any memory allocated by TBranchElement::SetAddress().
971
972 // The TBranch destructor is using fDirectory to detect whether it
973 // owns the TFile that contains its data (See TBranch::~TBranch)
974 fDirectory = nullptr;
975
976 // FIXME: We must consider what to do with the reset of these if we are a clone.
977 delete fPlayer;
978 fPlayer = 0;
979 if (fExternalFriends) {
980 using namespace ROOT::Detail;
982 fetree->Reset();
983 fExternalFriends->Clear("nodelete");
985 }
986 if (fFriends) {
987 fFriends->Delete();
988 delete fFriends;
989 fFriends = 0;
990 }
991 if (fAliases) {
992 fAliases->Delete();
993 delete fAliases;
994 fAliases = 0;
995 }
996 if (fUserInfo) {
997 fUserInfo->Delete();
998 delete fUserInfo;
999 fUserInfo = 0;
1000 }
1001 if (fClones) {
1002 // Clone trees should no longer be removed from fClones when they are deleted.
1003 {
1005 gROOT->GetListOfCleanups()->Remove(fClones);
1006 }
1007 // Note: fClones does not own its content.
1008 delete fClones;
1009 fClones = 0;
1010 }
1011 if (fEntryList) {
1013 // Delete the entry list if it is marked to be deleted and it is not also
1014 // owned by a directory. (Otherwise we would need to make sure that a
1015 // TDirectoryFile that has a TTree in it does a 'slow' TList::Delete.
1016 delete fEntryList;
1017 fEntryList=0;
1018 }
1019 }
1020 delete fTreeIndex;
1021 fTreeIndex = 0;
1022 delete fBranchRef;
1023 fBranchRef = 0;
1024 delete [] fClusterRangeEnd;
1025 fClusterRangeEnd = 0;
1026 delete [] fClusterSize;
1027 fClusterSize = 0;
1028
1029 if (fTransientBuffer) {
1030 delete fTransientBuffer;
1031 fTransientBuffer = 0;
1032 }
1033}
1034
1035////////////////////////////////////////////////////////////////////////////////
1036/// Returns the transient buffer currently used by this TTree for reading/writing baskets.
1039{
1040 if (fTransientBuffer) {
1041 if (fTransientBuffer->BufferSize() < size) {
1043 }
1044 return fTransientBuffer;
1045 }
1047 return fTransientBuffer;
1048}
1049
1050////////////////////////////////////////////////////////////////////////////////
1051/// Add branch with name bname to the Tree cache.
1052/// If bname="*" all branches are added to the cache.
1053/// if subbranches is true all the branches of the subbranches are
1054/// also put to the cache.
1055///
1056/// Returns:
1057/// - 0 branch added or already included
1058/// - -1 on error
1060Int_t TTree::AddBranchToCache(const char*bname, Bool_t subbranches)
1061{
1062 if (!GetTree()) {
1063 if (LoadTree(0)<0) {
1064 Error("AddBranchToCache","Could not load a tree");
1065 return -1;
1066 }
1067 }
1068 if (GetTree()) {
1069 if (GetTree() != this) {
1070 return GetTree()->AddBranchToCache(bname, subbranches);
1071 }
1072 } else {
1073 Error("AddBranchToCache", "No tree is available. Branch was not added to the cache");
1074 return -1;
1075 }
1076
1077 TFile *f = GetCurrentFile();
1078 if (!f) {
1079 Error("AddBranchToCache", "No file is available. Branch was not added to the cache");
1080 return -1;
1081 }
1083 if (!tc) {
1084 Error("AddBranchToCache", "No cache is available, branch not added");
1085 return -1;
1086 }
1087 return tc->AddBranch(bname,subbranches);
1088}
1089
1090////////////////////////////////////////////////////////////////////////////////
1091/// Add branch b to the Tree cache.
1092/// if subbranches is true all the branches of the subbranches are
1093/// also put to the cache.
1094///
1095/// Returns:
1096/// - 0 branch added or already included
1097/// - -1 on error
1100{
1101 if (!GetTree()) {
1102 if (LoadTree(0)<0) {
1103 Error("AddBranchToCache","Could not load a tree");
1104 return -1;
1105 }
1106 }
1107 if (GetTree()) {
1108 if (GetTree() != this) {
1109 Int_t res = GetTree()->AddBranchToCache(b, subbranches);
1110 if (res<0) {
1111 Error("AddBranchToCache", "Error adding branch");
1112 }
1113 return res;
1114 }
1115 } else {
1116 Error("AddBranchToCache", "No tree is available. Branch was not added to the cache");
1117 return -1;
1118 }
1119
1120 TFile *f = GetCurrentFile();
1121 if (!f) {
1122 Error("AddBranchToCache", "No file is available. Branch was not added to the cache");
1123 return -1;
1124 }
1126 if (!tc) {
1127 Error("AddBranchToCache", "No cache is available, branch not added");
1128 return -1;
1129 }
1130 return tc->AddBranch(b,subbranches);
1131}
1132
1133////////////////////////////////////////////////////////////////////////////////
1134/// Remove the branch with name 'bname' from the Tree cache.
1135/// If bname="*" all branches are removed from the cache.
1136/// if subbranches is true all the branches of the subbranches are
1137/// also removed from the cache.
1138///
1139/// Returns:
1140/// - 0 branch dropped or not in cache
1141/// - -1 on error
1143Int_t TTree::DropBranchFromCache(const char*bname, Bool_t subbranches)
1144{
1145 if (!GetTree()) {
1146 if (LoadTree(0)<0) {
1147 Error("DropBranchFromCache","Could not load a tree");
1148 return -1;
1149 }
1150 }
1151 if (GetTree()) {
1152 if (GetTree() != this) {
1153 return GetTree()->DropBranchFromCache(bname, subbranches);
1154 }
1155 } else {
1156 Error("DropBranchFromCache", "No tree is available. Branch was not dropped from the cache");
1157 return -1;
1158 }
1159
1160 TFile *f = GetCurrentFile();
1161 if (!f) {
1162 Error("DropBranchFromCache", "No file is available. Branch was not dropped from the cache");
1163 return -1;
1164 }
1166 if (!tc) {
1167 Error("DropBranchFromCache", "No cache is available, branch not dropped");
1168 return -1;
1169 }
1170 return tc->DropBranch(bname,subbranches);
1171}
1172
1173////////////////////////////////////////////////////////////////////////////////
1174/// Remove the branch b from the Tree cache.
1175/// if subbranches is true all the branches of the subbranches are
1176/// also removed from the cache.
1177///
1178/// Returns:
1179/// - 0 branch dropped or not in cache
1180/// - -1 on error
1183{
1184 if (!GetTree()) {
1185 if (LoadTree(0)<0) {
1186 Error("DropBranchFromCache","Could not load a tree");
1187 return -1;
1188 }
1189 }
1190 if (GetTree()) {
1191 if (GetTree() != this) {
1192 Int_t res = GetTree()->DropBranchFromCache(b, subbranches);
1193 if (res<0) {
1194 Error("DropBranchFromCache", "Error dropping branch");
1195 }
1196 return res;
1197 }
1198 } else {
1199 Error("DropBranchFromCache", "No tree is available. Branch was not dropped from the cache");
1200 return -1;
1201 }
1202
1203 TFile *f = GetCurrentFile();
1204 if (!f) {
1205 Error("DropBranchFromCache", "No file is available. Branch was not dropped from the cache");
1206 return -1;
1207 }
1209 if (!tc) {
1210 Error("DropBranchFromCache", "No cache is available, branch not dropped");
1211 return -1;
1212 }
1213 return tc->DropBranch(b,subbranches);
1214}
1215
1216////////////////////////////////////////////////////////////////////////////////
1217/// Add a cloned tree to our list of trees to be notified whenever we change
1218/// our branch addresses or when we are deleted.
1220void TTree::AddClone(TTree* clone)
1221{
1222 if (!fClones) {
1223 fClones = new TList();
1224 fClones->SetOwner(false);
1225 // So that the clones are automatically removed from the list when
1226 // they are deleted.
1227 {
1229 gROOT->GetListOfCleanups()->Add(fClones);
1230 }
1231 }
1232 if (!fClones->FindObject(clone)) {
1233 fClones->Add(clone);
1234 }
1235}
1236
1237// Check whether mainTree and friendTree can be friends w.r.t. the kEntriesReshuffled bit.
1238// In particular, if any has the bit set, then friendTree must have a TTreeIndex and the
1239// branches used for indexing must be present in mainTree.
1240// Return true if the trees can be friends, false otherwise.
1241bool CheckReshuffling(TTree &mainTree, TTree &friendTree)
1242{
1243 const auto isMainReshuffled = mainTree.TestBit(TTree::kEntriesReshuffled);
1244 const auto isFriendReshuffled = friendTree.TestBit(TTree::kEntriesReshuffled);
1245 const auto friendHasValidIndex = [&] {
1246 auto idx = friendTree.GetTreeIndex();
1247 return idx ? idx->IsValidFor(&mainTree) : kFALSE;
1248 }();
1249
1250 if ((isMainReshuffled || isFriendReshuffled) && !friendHasValidIndex) {
1251 const auto reshuffledTreeName = isMainReshuffled ? mainTree.GetName() : friendTree.GetName();
1252 const auto msg = "Tree '%s' has the kEntriesReshuffled bit set, and cannot be used as friend nor can be added as "
1253 "a friend unless the main tree has a TTreeIndex on the friend tree '%s'. You can also unset the "
1254 "bit manually if you know what you are doing.";
1255 Error("AddFriend", msg, reshuffledTreeName, friendTree.GetName());
1256 return false;
1257 }
1258 return true;
1259}
1260
1261////////////////////////////////////////////////////////////////////////////////
1262/// Add a TFriendElement to the list of friends.
1263///
1264/// This function:
1265/// - opens a file if filename is specified
1266/// - reads a Tree with name treename from the file (current directory)
1267/// - adds the Tree to the list of friends
1268/// see other AddFriend functions
1269///
1270/// A TFriendElement TF describes a TTree object TF in a file.
1271/// When a TFriendElement TF is added to the list of friends of an
1272/// existing TTree T, any variable from TF can be referenced in a query
1273/// to T.
1274///
1275/// A tree keeps a list of friends. In the context of a tree (or a chain),
1276/// friendship means unrestricted access to the friends data. In this way
1277/// it is much like adding another branch to the tree without taking the risk
1278/// of damaging it. To add a friend to the list, you can use the TTree::AddFriend
1279/// method. The tree in the diagram below has two friends (friend_tree1 and
1280/// friend_tree2) and now has access to the variables a,b,c,i,j,k,l and m.
1281///
1282/// \image html ttree_friend1.png
1283///
1284/// The AddFriend method has two parameters, the first is the tree name and the
1285/// second is the name of the ROOT file where the friend tree is saved.
1286/// AddFriend automatically opens the friend file. If no file name is given,
1287/// the tree called ft1 is assumed to be in the same file as the original tree.
1288///
1289/// tree.AddFriend("ft1","friendfile1.root");
1290/// If the friend tree has the same name as the original tree, you can give it
1291/// an alias in the context of the friendship:
1292///
1293/// tree.AddFriend("tree1 = tree","friendfile1.root");
1294/// Once the tree has friends, we can use TTree::Draw as if the friend's
1295/// variables were in the original tree. To specify which tree to use in
1296/// the Draw method, use the syntax:
1297/// ~~~ {.cpp}
1298/// <treeName>.<branchname>.<varname>
1299/// ~~~
1300/// If the variablename is enough to uniquely identify the variable, you can
1301/// leave out the tree and/or branch name.
1302/// For example, these commands generate a 3-d scatter plot of variable "var"
1303/// in the TTree tree versus variable v1 in TTree ft1 versus variable v2 in
1304/// TTree ft2.
1305/// ~~~ {.cpp}
1306/// tree.AddFriend("ft1","friendfile1.root");
1307/// tree.AddFriend("ft2","friendfile2.root");
1308/// tree.Draw("var:ft1.v1:ft2.v2");
1309/// ~~~
1310/// \image html ttree_friend2.png
1311///
1312/// The picture illustrates the access of the tree and its friends with a
1313/// Draw command.
1314/// When AddFriend is called, the ROOT file is automatically opened and the
1315/// friend tree (ft1) is read into memory. The new friend (ft1) is added to
1316/// the list of friends of tree.
1317/// The number of entries in the friend must be equal or greater to the number
1318/// of entries of the original tree. If the friend tree has fewer entries a
1319/// warning is given and the missing entries are not included in the histogram.
1320/// To retrieve the list of friends from a tree use TTree::GetListOfFriends.
1321/// When the tree is written to file (TTree::Write), the friends list is saved
1322/// with it. And when the tree is retrieved, the trees on the friends list are
1323/// also retrieved and the friendship restored.
1324/// When a tree is deleted, the elements of the friend list are also deleted.
1325/// It is possible to declare a friend tree that has the same internal
1326/// structure (same branches and leaves) as the original tree, and compare the
1327/// same values by specifying the tree.
1328/// ~~~ {.cpp}
1329/// tree.Draw("var:ft1.var:ft2.var")
1330/// ~~~
1332TFriendElement *TTree::AddFriend(const char *treename, const char *filename)
1333{
1334 if (!fFriends) {
1335 fFriends = new TList();
1336 }
1337 TFriendElement *fe = new TFriendElement(this, treename, filename);
1338
1339 TTree *t = fe->GetTree();
1340 bool canAddFriend = true;
1341 if (t) {
1342 canAddFriend = CheckReshuffling(*this, *t);
1343 if (!t->GetTreeIndex() && (t->GetEntries() < fEntries)) {
1344 Warning("AddFriend", "FriendElement %s in file %s has less entries %lld than its parent Tree: %lld", treename,
1346 }
1347 } else {
1348 Error("AddFriend", "Cannot find tree '%s' in file '%s', friend not added", treename, filename);
1349 canAddFriend = false;
1350 }
1351
1352 if (canAddFriend)
1353 fFriends->Add(fe);
1354 return fe;
1355}
1356
1357////////////////////////////////////////////////////////////////////////////////
1358/// Add a TFriendElement to the list of friends.
1359///
1360/// The TFile is managed by the user (e.g. the user must delete the file).
1361/// For complete description see AddFriend(const char *, const char *).
1362/// This function:
1363/// - reads a Tree with name treename from the file
1364/// - adds the Tree to the list of friends
1366TFriendElement *TTree::AddFriend(const char *treename, TFile *file)
1367{
1368 if (!fFriends) {
1369 fFriends = new TList();
1370 }
1371 TFriendElement *fe = new TFriendElement(this, treename, file);
1372 R__ASSERT(fe);
1373 TTree *t = fe->GetTree();
1374 bool canAddFriend = true;
1375 if (t) {
1376 canAddFriend = CheckReshuffling(*this, *t);
1377 if (!t->GetTreeIndex() && (t->GetEntries() < fEntries)) {
1378 Warning("AddFriend", "FriendElement %s in file %s has less entries %lld than its parent tree: %lld", treename,
1379 file->GetName(), t->GetEntries(), fEntries);
1380 }
1381 } else {
1382 Error("AddFriend", "Cannot find tree '%s' in file '%s', friend not added", treename, file->GetName());
1383 canAddFriend = false;
1384 }
1385
1386 if (canAddFriend)
1387 fFriends->Add(fe);
1388 return fe;
1389}
1390
1391////////////////////////////////////////////////////////////////////////////////
1392/// Add a TFriendElement to the list of friends.
1393///
1394/// The TTree is managed by the user (e.g., the user must delete the file).
1395/// For a complete description see AddFriend(const char *, const char *).
1397TFriendElement *TTree::AddFriend(TTree *tree, const char *alias, Bool_t warn)
1398{
1399 if (!tree) {
1400 return 0;
1401 }
1402 if (!fFriends) {
1403 fFriends = new TList();
1404 }
1405 TFriendElement *fe = new TFriendElement(this, tree, alias);
1406 R__ASSERT(fe); // this assert is for historical reasons. Don't remove it unless you understand all the consequences.
1407 TTree *t = fe->GetTree();
1408 if (warn && (t->GetEntries() < fEntries)) {
1409 Warning("AddFriend", "FriendElement '%s' in file '%s' has less entries %lld than its parent tree: %lld",
1410 tree->GetName(), fe->GetFile() ? fe->GetFile()->GetName() : "(memory resident)", t->GetEntries(),
1411 fEntries);
1412 }
1413 if (CheckReshuffling(*this, *t))
1414 fFriends->Add(fe);
1415 else
1416 tree->RemoveExternalFriend(fe);
1417 return fe;
1418}
1419
1420////////////////////////////////////////////////////////////////////////////////
1421/// AutoSave tree header every fAutoSave bytes.
1422///
1423/// When large Trees are produced, it is safe to activate the AutoSave
1424/// procedure. Some branches may have buffers holding many entries.
1425/// If fAutoSave is negative, AutoSave is automatically called by
1426/// TTree::Fill when the number of bytes generated since the previous
1427/// AutoSave is greater than -fAutoSave bytes.
1428/// If fAutoSave is positive, AutoSave is automatically called by
1429/// TTree::Fill every N entries.
1430/// This function may also be invoked by the user.
1431/// Each AutoSave generates a new key on the file.
1432/// Once the key with the tree header has been written, the previous cycle
1433/// (if any) is deleted.
1434///
1435/// Note that calling TTree::AutoSave too frequently (or similarly calling
1436/// TTree::SetAutoSave with a small value) is an expensive operation.
1437/// You should make tests for your own application to find a compromise
1438/// between speed and the quantity of information you may loose in case of
1439/// a job crash.
1440///
1441/// In case your program crashes before closing the file holding this tree,
1442/// the file will be automatically recovered when you will connect the file
1443/// in UPDATE mode.
1444/// The Tree will be recovered at the status corresponding to the last AutoSave.
1445///
1446/// if option contains "SaveSelf", gDirectory->SaveSelf() is called.
1447/// This allows another process to analyze the Tree while the Tree is being filled.
1448///
1449/// if option contains "FlushBaskets", TTree::FlushBaskets is called and all
1450/// the current basket are closed-out and written to disk individually.
1451///
1452/// By default the previous header is deleted after having written the new header.
1453/// if option contains "Overwrite", the previous Tree header is deleted
1454/// before written the new header. This option is slightly faster, but
1455/// the default option is safer in case of a problem (disk quota exceeded)
1456/// when writing the new header.
1457///
1458/// The function returns the number of bytes written to the file.
1459/// if the number of bytes is null, an error has occurred while writing
1460/// the header to the file.
1461///
1462/// ## How to write a Tree in one process and view it from another process
1463///
1464/// The following two scripts illustrate how to do this.
1465/// The script treew.C is executed by process1, treer.C by process2
1466///
1467/// script treew.C:
1468/// ~~~ {.cpp}
1469/// void treew() {
1470/// TFile f("test.root","recreate");
1471/// TNtuple *ntuple = new TNtuple("ntuple","Demo","px:py:pz:random:i");
1472/// Float_t px, py, pz;
1473/// for ( Int_t i=0; i<10000000; i++) {
1474/// gRandom->Rannor(px,py);
1475/// pz = px*px + py*py;
1476/// Float_t random = gRandom->Rndm(1);
1477/// ntuple->Fill(px,py,pz,random,i);
1478/// if (i%1000 == 1) ntuple->AutoSave("SaveSelf");
1479/// }
1480/// }
1481/// ~~~
1482/// script treer.C:
1483/// ~~~ {.cpp}
1484/// void treer() {
1485/// TFile f("test.root");
1486/// TTree *ntuple = (TTree*)f.Get("ntuple");
1487/// TCanvas c1;
1488/// Int_t first = 0;
1489/// while(1) {
1490/// if (first == 0) ntuple->Draw("px>>hpx", "","",10000000,first);
1491/// else ntuple->Draw("px>>+hpx","","",10000000,first);
1492/// first = (Int_t)ntuple->GetEntries();
1493/// c1.Update();
1494/// gSystem->Sleep(1000); //sleep 1 second
1495/// ntuple->Refresh();
1496/// }
1497/// }
1498/// ~~~
1501{
1502 if (!fDirectory || fDirectory == gROOT || !fDirectory->IsWritable()) return 0;
1503 if (gDebug > 0) {
1504 Info("AutoSave", "Tree:%s after %lld bytes written\n",GetName(),GetTotBytes());
1505 }
1506 TString opt = option;
1507 opt.ToLower();
1508
1509 if (opt.Contains("flushbaskets")) {
1510 if (gDebug > 0) Info("AutoSave", "calling FlushBaskets \n");
1512 }
1513
1515
1517 Long64_t nbytes;
1518 if (opt.Contains("overwrite")) {
1519 nbytes = fDirectory->WriteTObject(this,"","overwrite");
1520 } else {
1521 nbytes = fDirectory->WriteTObject(this); //nbytes will be 0 if Write failed (disk space exceeded)
1522 if (nbytes && key && strcmp(ClassName(), key->GetClassName()) == 0) {
1523 key->Delete();
1524 delete key;
1525 }
1526 }
1527 // save StreamerInfo
1529 if (file) file->WriteStreamerInfo();
1530
1531 if (opt.Contains("saveself")) {
1533 //the following line is required in case GetUserInfo contains a user class
1534 //for which the StreamerInfo must be written. One could probably be a bit faster (Rene)
1535 if (file) file->WriteHeader();
1536 }
1537
1538 return nbytes;
1539}
1540
1541namespace {
1542 // This error message is repeated several times in the code. We write it once.
1543 const char* writeStlWithoutProxyMsg = "The class requested (%s) for the branch \"%s\""
1544 " is an instance of an stl collection and does not have a compiled CollectionProxy."
1545 " Please generate the dictionary for this collection (%s) to avoid to write corrupted data.";
1546}
1547
1548////////////////////////////////////////////////////////////////////////////////
1549/// Same as TTree::Branch() with added check that addobj matches className.
1550///
1551/// \see TTree::Branch() for other details.
1552///
1554TBranch* TTree::BranchImp(const char* branchname, const char* classname, TClass* ptrClass, void* addobj, Int_t bufsize, Int_t splitlevel)
1555{
1556 TClass* claim = TClass::GetClass(classname);
1557 if (!ptrClass) {
1558 if (claim && claim->GetCollectionProxy() && dynamic_cast<TEmulatedCollectionProxy*>(claim->GetCollectionProxy())) {
1559 Error("Branch", writeStlWithoutProxyMsg,
1560 claim->GetName(), branchname, claim->GetName());
1561 return 0;
1562 }
1563 return Branch(branchname, classname, (void*) addobj, bufsize, splitlevel);
1564 }
1565 TClass* actualClass = 0;
1566 void** addr = (void**) addobj;
1567 if (addr) {
1568 actualClass = ptrClass->GetActualClass(*addr);
1569 }
1570 if (ptrClass && claim) {
1571 if (!(claim->InheritsFrom(ptrClass) || ptrClass->InheritsFrom(claim))) {
1572 // Note we currently do not warn in case of splicing or over-expectation).
1573 if (claim->IsLoaded() && ptrClass->IsLoaded() && strcmp( claim->GetTypeInfo()->name(), ptrClass->GetTypeInfo()->name() ) == 0) {
1574 // The type is the same according to the C++ type_info, we must be in the case of
1575 // a template of Double32_t. This is actually a correct case.
1576 } else {
1577 Error("Branch", "The class requested (%s) for \"%s\" is different from the type of the pointer passed (%s)",
1578 claim->GetName(), branchname, ptrClass->GetName());
1579 }
1580 } else if (actualClass && (claim != actualClass) && !actualClass->InheritsFrom(claim)) {
1581 if (claim->IsLoaded() && actualClass->IsLoaded() && strcmp( claim->GetTypeInfo()->name(), actualClass->GetTypeInfo()->name() ) == 0) {
1582 // The type is the same according to the C++ type_info, we must be in the case of
1583 // a template of Double32_t. This is actually a correct case.
1584 } else {
1585 Error("Branch", "The actual class (%s) of the object provided for the definition of the branch \"%s\" does not inherit from %s",
1586 actualClass->GetName(), branchname, claim->GetName());
1587 }
1588 }
1589 }
1590 if (claim && claim->GetCollectionProxy() && dynamic_cast<TEmulatedCollectionProxy*>(claim->GetCollectionProxy())) {
1591 Error("Branch", writeStlWithoutProxyMsg,
1592 claim->GetName(), branchname, claim->GetName());
1593 return 0;
1594 }
1595 return Branch(branchname, classname, (void*) addobj, bufsize, splitlevel);
1596}
1597
1598////////////////////////////////////////////////////////////////////////////////
1599/// Same as TTree::Branch but automatic detection of the class name.
1600/// \see TTree::Branch for other details.
1602TBranch* TTree::BranchImp(const char* branchname, TClass* ptrClass, void* addobj, Int_t bufsize, Int_t splitlevel)
1603{
1604 if (!ptrClass) {
1605 Error("Branch", "The pointer specified for %s is not of a class known to ROOT", branchname);
1606 return 0;
1607 }
1608 TClass* actualClass = 0;
1609 void** addr = (void**) addobj;
1610 if (addr && *addr) {
1611 actualClass = ptrClass->GetActualClass(*addr);
1612 if (!actualClass) {
1613 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",
1614 branchname, ptrClass->GetName());
1615 actualClass = ptrClass;
1616 } else if ((ptrClass != actualClass) && !actualClass->InheritsFrom(ptrClass)) {
1617 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());
1618 return 0;
1619 }
1620 } else {
1621 actualClass = ptrClass;
1622 }
1623 if (actualClass && actualClass->GetCollectionProxy() && dynamic_cast<TEmulatedCollectionProxy*>(actualClass->GetCollectionProxy())) {
1624 Error("Branch", writeStlWithoutProxyMsg,
1625 actualClass->GetName(), branchname, actualClass->GetName());
1626 return 0;
1627 }
1628 return Branch(branchname, actualClass->GetName(), (void*) addobj, bufsize, splitlevel);
1629}
1630
1631////////////////////////////////////////////////////////////////////////////////
1632/// Same as TTree::Branch but automatic detection of the class name.
1633/// \see TTree::Branch for other details.
1635TBranch* TTree::BranchImpRef(const char* branchname, const char *classname, TClass* ptrClass, void *addobj, Int_t bufsize, Int_t splitlevel)
1636{
1637 TClass* claim = TClass::GetClass(classname);
1638 if (!ptrClass) {
1639 if (claim && claim->GetCollectionProxy() && dynamic_cast<TEmulatedCollectionProxy*>(claim->GetCollectionProxy())) {
1640 Error("Branch", writeStlWithoutProxyMsg,
1641 claim->GetName(), branchname, claim->GetName());
1642 return 0;
1643 } else if (claim == 0) {
1644 Error("Branch", "The pointer specified for %s is not of a class known to ROOT and %s is not a known class", branchname, classname);
1645 return 0;
1646 }
1647 ptrClass = claim;
1648 }
1649 TClass* actualClass = 0;
1650 if (!addobj) {
1651 Error("Branch", "Reference interface requires a valid object (for branch: %s)!", branchname);
1652 return 0;
1653 }
1654 actualClass = ptrClass->GetActualClass(addobj);
1655 if (ptrClass && claim) {
1656 if (!(claim->InheritsFrom(ptrClass) || ptrClass->InheritsFrom(claim))) {
1657 // Note we currently do not warn in case of splicing or over-expectation).
1658 if (claim->IsLoaded() && ptrClass->IsLoaded() && strcmp( claim->GetTypeInfo()->name(), ptrClass->GetTypeInfo()->name() ) == 0) {
1659 // The type is the same according to the C++ type_info, we must be in the case of
1660 // a template of Double32_t. This is actually a correct case.
1661 } else {
1662 Error("Branch", "The class requested (%s) for \"%s\" is different from the type of the object passed (%s)",
1663 claim->GetName(), branchname, ptrClass->GetName());
1664 }
1665 } else if (actualClass && (claim != actualClass) && !actualClass->InheritsFrom(claim)) {
1666 if (claim->IsLoaded() && actualClass->IsLoaded() && strcmp( claim->GetTypeInfo()->name(), actualClass->GetTypeInfo()->name() ) == 0) {
1667 // The type is the same according to the C++ type_info, we must be in the case of
1668 // a template of Double32_t. This is actually a correct case.
1669 } else {
1670 Error("Branch", "The actual class (%s) of the object provided for the definition of the branch \"%s\" does not inherit from %s",
1671 actualClass->GetName(), branchname, claim->GetName());
1672 }
1673 }
1674 }
1675 if (!actualClass) {
1676 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",
1677 branchname, ptrClass->GetName());
1678 actualClass = ptrClass;
1679 } else if ((ptrClass != actualClass) && !actualClass->InheritsFrom(ptrClass)) {
1680 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());
1681 return 0;
1682 }
1683 if (actualClass && actualClass->GetCollectionProxy() && dynamic_cast<TEmulatedCollectionProxy*>(actualClass->GetCollectionProxy())) {
1684 Error("Branch", writeStlWithoutProxyMsg,
1685 actualClass->GetName(), branchname, actualClass->GetName());
1686 return 0;
1687 }
1688 return BronchExec(branchname, actualClass->GetName(), (void*) addobj, kFALSE, bufsize, splitlevel);
1689}
1690
1691////////////////////////////////////////////////////////////////////////////////
1692/// Same as TTree::Branch but automatic detection of the class name.
1693/// \see TTree::Branch for other details.
1695TBranch* TTree::BranchImpRef(const char* branchname, TClass* ptrClass, EDataType datatype, void* addobj, Int_t bufsize, Int_t splitlevel)
1696{
1697 if (!ptrClass) {
1698 if (datatype == kOther_t || datatype == kNoType_t) {
1699 Error("Branch", "The pointer specified for %s is not of a class or type known to ROOT", branchname);
1700 } else {
1701 TString varname; varname.Form("%s/%c",branchname,DataTypeToChar(datatype));
1702 return Branch(branchname,addobj,varname.Data(),bufsize);
1703 }
1704 return 0;
1705 }
1706 TClass* actualClass = 0;
1707 if (!addobj) {
1708 Error("Branch", "Reference interface requires a valid object (for branch: %s)!", branchname);
1709 return 0;
1710 }
1711 actualClass = ptrClass->GetActualClass(addobj);
1712 if (!actualClass) {
1713 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",
1714 branchname, ptrClass->GetName());
1715 actualClass = ptrClass;
1716 } else if ((ptrClass != actualClass) && !actualClass->InheritsFrom(ptrClass)) {
1717 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());
1718 return 0;
1719 }
1720 if (actualClass && actualClass->GetCollectionProxy() && dynamic_cast<TEmulatedCollectionProxy*>(actualClass->GetCollectionProxy())) {
1721 Error("Branch", writeStlWithoutProxyMsg,
1722 actualClass->GetName(), branchname, actualClass->GetName());
1723 return 0;
1724 }
1725 return BronchExec(branchname, actualClass->GetName(), (void*) addobj, kFALSE, bufsize, splitlevel);
1726}
1727
1728////////////////////////////////////////////////////////////////////////////////
1729// Wrapper to turn Branch call with an std::array into the relevant leaf list
1730// call
1731TBranch *TTree::BranchImpArr(const char *branchname, EDataType datatype, std::size_t N, void *addobj, Int_t bufsize,
1732 Int_t /* splitlevel */)
1733{
1734 if (datatype == kOther_t || datatype == kNoType_t) {
1735 Error("Branch",
1736 "The inner type of the std::array passed specified for %s is not of a class or type known to ROOT",
1737 branchname);
1738 } else {
1739 TString varname;
1740 varname.Form("%s[%d]/%c", branchname, (int)N, DataTypeToChar(datatype));
1741 return Branch(branchname, addobj, varname.Data(), bufsize);
1742 }
1743 return nullptr;
1744}
1745
1746////////////////////////////////////////////////////////////////////////////////
1747/// Deprecated function. Use next function instead.
1749Int_t TTree::Branch(TList* li, Int_t bufsize /* = 32000 */ , Int_t splitlevel /* = 99 */)
1750{
1751 return Branch((TCollection*) li, bufsize, splitlevel);
1752}
1753
1754////////////////////////////////////////////////////////////////////////////////
1755/// Create one branch for each element in the collection.
1756///
1757/// Each entry in the collection becomes a top level branch if the
1758/// corresponding class is not a collection. If it is a collection, the entry
1759/// in the collection becomes in turn top level branches, etc.
1760/// The splitlevel is decreased by 1 every time a new collection is found.
1761/// For example if list is a TObjArray*
1762/// - if splitlevel = 1, one top level branch is created for each element
1763/// of the TObjArray.
1764/// - if splitlevel = 2, one top level branch is created for each array element.
1765/// if, in turn, one of the array elements is a TCollection, one top level
1766/// branch will be created for each element of this collection.
1767///
1768/// In case a collection element is a TClonesArray, the special Tree constructor
1769/// for TClonesArray is called.
1770/// The collection itself cannot be a TClonesArray.
1771///
1772/// The function returns the total number of branches created.
1773///
1774/// If name is given, all branch names will be prefixed with name_.
1775///
1776/// IMPORTANT NOTE1: This function should not be called with splitlevel < 1.
1777///
1778/// IMPORTANT NOTE2: The branches created by this function will have names
1779/// corresponding to the collection or object names. It is important
1780/// to give names to collections to avoid misleading branch names or
1781/// identical branch names. By default collections have a name equal to
1782/// the corresponding class name, e.g. the default name for a TList is "TList".
1783///
1784/// And in general, in case two or more master branches contain subbranches
1785/// with identical names, one must add a "." (dot) character at the end
1786/// of the master branch name. This will force the name of the subbranches
1787/// to be of the form `master.subbranch` instead of simply `subbranch`.
1788/// This situation happens when the top level object
1789/// has two or more members referencing the same class.
1790/// For example, if a Tree has two branches B1 and B2 corresponding
1791/// to objects of the same class MyClass, one can do:
1792/// ~~~ {.cpp}
1793/// tree.Branch("B1.","MyClass",&b1,8000,1);
1794/// tree.Branch("B2.","MyClass",&b2,8000,1);
1795/// ~~~
1796/// if MyClass has 3 members a,b,c, the two instructions above will generate
1797/// subbranches called B1.a, B1.b ,B1.c, B2.a, B2.b, B2.c
1798///
1799/// Example:
1800/// ~~~ {.cpp}
1801/// {
1802/// TTree T("T","test list");
1803/// TList *list = new TList();
1804///
1805/// TObjArray *a1 = new TObjArray();
1806/// a1->SetName("a1");
1807/// list->Add(a1);
1808/// TH1F *ha1a = new TH1F("ha1a","ha1",100,0,1);
1809/// TH1F *ha1b = new TH1F("ha1b","ha1",100,0,1);
1810/// a1->Add(ha1a);
1811/// a1->Add(ha1b);
1812/// TObjArray *b1 = new TObjArray();
1813/// b1->SetName("b1");
1814/// list->Add(b1);
1815/// TH1F *hb1a = new TH1F("hb1a","hb1",100,0,1);
1816/// TH1F *hb1b = new TH1F("hb1b","hb1",100,0,1);
1817/// b1->Add(hb1a);
1818/// b1->Add(hb1b);
1819///
1820/// TObjArray *a2 = new TObjArray();
1821/// a2->SetName("a2");
1822/// list->Add(a2);
1823/// TH1S *ha2a = new TH1S("ha2a","ha2",100,0,1);
1824/// TH1S *ha2b = new TH1S("ha2b","ha2",100,0,1);
1825/// a2->Add(ha2a);
1826/// a2->Add(ha2b);
1827///
1828/// T.Branch(list,16000,2);
1829/// T.Print();
1830/// }
1831/// ~~~
1833Int_t TTree::Branch(TCollection* li, Int_t bufsize /* = 32000 */, Int_t splitlevel /* = 99 */, const char* name /* = "" */)
1834{
1835
1836 if (!li) {
1837 return 0;
1838 }
1839 TObject* obj = 0;
1840 Int_t nbranches = GetListOfBranches()->GetEntries();
1841 if (li->InheritsFrom(TClonesArray::Class())) {
1842 Error("Branch", "Cannot call this constructor for a TClonesArray");
1843 return 0;
1844 }
1845 Int_t nch = strlen(name);
1846 TString branchname;
1847 TIter next(li);
1848 while ((obj = next())) {
1849 if ((splitlevel > 1) && obj->InheritsFrom(TCollection::Class()) && !obj->InheritsFrom(TClonesArray::Class())) {
1850 TCollection* col = (TCollection*) obj;
1851 if (nch) {
1852 branchname.Form("%s_%s_", name, col->GetName());
1853 } else {
1854 branchname.Form("%s_", col->GetName());
1855 }
1856 Branch(col, bufsize, splitlevel - 1, branchname);
1857 } else {
1858 if (nch && (name[nch-1] == '_')) {
1859 branchname.Form("%s%s", name, obj->GetName());
1860 } else {
1861 if (nch) {
1862 branchname.Form("%s_%s", name, obj->GetName());
1863 } else {
1864 branchname.Form("%s", obj->GetName());
1865 }
1866 }
1867 if (splitlevel > 99) {
1868 branchname += ".";
1869 }
1870 Bronch(branchname, obj->ClassName(), li->GetObjectRef(obj), bufsize, splitlevel - 1);
1871 }
1872 }
1873 return GetListOfBranches()->GetEntries() - nbranches;
1874}
1875
1876////////////////////////////////////////////////////////////////////////////////
1877/// Create one branch for each element in the folder.
1878/// Returns the total number of branches created.
1880Int_t TTree::Branch(const char* foldername, Int_t bufsize /* = 32000 */, Int_t splitlevel /* = 99 */)
1881{
1882 TObject* ob = gROOT->FindObjectAny(foldername);
1883 if (!ob) {
1884 return 0;
1885 }
1886 if (ob->IsA() != TFolder::Class()) {
1887 return 0;
1888 }
1889 Int_t nbranches = GetListOfBranches()->GetEntries();
1890 TFolder* folder = (TFolder*) ob;
1891 TIter next(folder->GetListOfFolders());
1892 TObject* obj = 0;
1893 char* curname = new char[1000];
1894 char occur[20];
1895 while ((obj = next())) {
1896 snprintf(curname,1000, "%s/%s", foldername, obj->GetName());
1897 if (obj->IsA() == TFolder::Class()) {
1898 Branch(curname, bufsize, splitlevel - 1);
1899 } else {
1900 void* add = (void*) folder->GetListOfFolders()->GetObjectRef(obj);
1901 for (Int_t i = 0; i < 1000; ++i) {
1902 if (curname[i] == 0) {
1903 break;
1904 }
1905 if (curname[i] == '/') {
1906 curname[i] = '.';
1907 }
1908 }
1909 Int_t noccur = folder->Occurence(obj);
1910 if (noccur > 0) {
1911 snprintf(occur,20, "_%d", noccur);
1912 strlcat(curname, occur,1000);
1913 }
1914 TBranchElement* br = (TBranchElement*) Bronch(curname, obj->ClassName(), add, bufsize, splitlevel - 1);
1915 if (br) br->SetBranchFolder();
1916 }
1917 }
1918 delete[] curname;
1919 return GetListOfBranches()->GetEntries() - nbranches;
1920}
1921
1922////////////////////////////////////////////////////////////////////////////////
1923/// Create a new TTree Branch.
1924///
1925/// This Branch constructor is provided to support non-objects in
1926/// a Tree. The variables described in leaflist may be simple
1927/// variables or structures. // See the two following
1928/// constructors for writing objects in a Tree.
1929///
1930/// By default the branch buffers are stored in the same file as the Tree.
1931/// use TBranch::SetFile to specify a different file
1932///
1933/// * address is the address of the first item of a structure.
1934/// * leaflist is the concatenation of all the variable names and types
1935/// separated by a colon character :
1936/// The variable name and the variable type are separated by a slash (/).
1937/// The variable type may be 0,1 or 2 characters. If no type is given,
1938/// the type of the variable is assumed to be the same as the previous
1939/// variable. If the first variable does not have a type, it is assumed
1940/// of type F by default. The list of currently supported types is given below:
1941/// - `C` : a character string terminated by the 0 character
1942/// - `B` : an 8 bit signed integer (`Char_t`); Treated as a character when in an array.
1943/// - `b` : an 8 bit unsigned integer (`UChar_t`)
1944/// - `S` : a 16 bit signed integer (`Short_t`)
1945/// - `s` : a 16 bit unsigned integer (`UShort_t`)
1946/// - `I` : a 32 bit signed integer (`Int_t`)
1947/// - `i` : a 32 bit unsigned integer (`UInt_t`)
1948/// - `F` : a 32 bit floating point (`Float_t`)
1949/// - `f` : a 24 bit floating point with truncated mantissa (`Float16_t`)
1950/// - `D` : a 64 bit floating point (`Double_t`)
1951/// - `d` : a 24 bit truncated floating point (`Double32_t`)
1952/// - `L` : a 64 bit signed integer (`Long64_t`)
1953/// - `l` : a 64 bit unsigned integer (`ULong64_t`)
1954/// - `G` : a long signed integer, stored as 64 bit (`Long_t`)
1955/// - `g` : a long unsigned integer, stored as 64 bit (`ULong_t`)
1956/// - `O` : [the letter `o`, not a zero] a boolean (`Bool_t`)
1957///
1958/// Arrays of values are supported with the following syntax:
1959/// - If leaf name has the form var[nelem], where nelem is alphanumeric, then
1960/// if nelem is a leaf name, it is used as the variable size of the array,
1961/// otherwise return 0.
1962/// The leaf referred to by nelem **MUST** be an int (/I),
1963/// - If leaf name has the form var[nelem], where nelem is a non-negative integer, then
1964/// it is used as the fixed size of the array.
1965/// - If leaf name has the form of a multi-dimensional array (e.g. var[nelem][nelem2])
1966/// where nelem and nelem2 are non-negative integer) then
1967/// it is used as a 2 dimensional array of fixed size.
1968/// - In case of the truncated floating point types (Float16_t and Double32_t) you can
1969/// furthermore specify the range in the style [xmin,xmax] or [xmin,xmax,nbits] after
1970/// the type character. See `TStreamerElement::GetRange()` for further information.
1971///
1972/// Any of other form is not supported.
1973///
1974/// Note that the TTree will assume that all the item are contiguous in memory.
1975/// On some platform, this is not always true of the member of a struct or a class,
1976/// due to padding and alignment. Sorting your data member in order of decreasing
1977/// sizeof usually leads to their being contiguous in memory.
1978///
1979/// * bufsize is the buffer size in bytes for this branch
1980/// The default value is 32000 bytes and should be ok for most cases.
1981/// You can specify a larger value (e.g. 256000) if your Tree is not split
1982/// and each entry is large (Megabytes)
1983/// A small value for bufsize is optimum if you intend to access
1984/// the entries in the Tree randomly and your Tree is in split mode.
1986TBranch* TTree::Branch(const char* name, void* address, const char* leaflist, Int_t bufsize /* = 32000 */)
1987{
1988 TBranch* branch = new TBranch(this, name, address, leaflist, bufsize);
1989 if (branch->IsZombie()) {
1990 delete branch;
1991 branch = 0;
1992 return 0;
1993 }
1994 fBranches.Add(branch);
1995 return branch;
1996}
1997
1998////////////////////////////////////////////////////////////////////////////////
1999/// Create a new branch with the object of class classname at address addobj.
2000///
2001/// WARNING:
2002///
2003/// Starting with Root version 3.01, the Branch function uses the new style
2004/// branches (TBranchElement). To get the old behaviour, you can:
2005/// - call BranchOld or
2006/// - call TTree::SetBranchStyle(0)
2007///
2008/// Note that with the new style, classname does not need to derive from TObject.
2009/// It must derived from TObject if the branch style has been set to 0 (old)
2010///
2011/// Note: See the comments in TBranchElement::SetAddress() for a more
2012/// detailed discussion of the meaning of the addobj parameter in
2013/// the case of new-style branches.
2014///
2015/// Use splitlevel < 0 instead of splitlevel=0 when the class
2016/// has a custom Streamer
2017///
2018/// Note: if the split level is set to the default (99), TTree::Branch will
2019/// not issue a warning if the class can not be split.
2021TBranch* TTree::Branch(const char* name, const char* classname, void* addobj, Int_t bufsize /* = 32000 */, Int_t splitlevel /* = 99 */)
2022{
2023 if (fgBranchStyle == 1) {
2024 return Bronch(name, classname, addobj, bufsize, splitlevel);
2025 } else {
2026 if (splitlevel < 0) {
2027 splitlevel = 0;
2028 }
2029 return BranchOld(name, classname, addobj, bufsize, splitlevel);
2030 }
2031}
2032
2033////////////////////////////////////////////////////////////////////////////////
2034/// Create a new TTree BranchObject.
2035///
2036/// Build a TBranchObject for an object of class classname.
2037/// addobj is the address of a pointer to an object of class classname.
2038/// IMPORTANT: classname must derive from TObject.
2039/// The class dictionary must be available (ClassDef in class header).
2040///
2041/// This option requires access to the library where the corresponding class
2042/// is defined. Accessing one single data member in the object implies
2043/// reading the full object.
2044/// See the next Branch constructor for a more efficient storage
2045/// in case the entry consists of arrays of identical objects.
2046///
2047/// By default the branch buffers are stored in the same file as the Tree.
2048/// use TBranch::SetFile to specify a different file
2049///
2050/// IMPORTANT NOTE about branch names:
2051///
2052/// And in general, in case two or more master branches contain subbranches
2053/// with identical names, one must add a "." (dot) character at the end
2054/// of the master branch name. This will force the name of the subbranches
2055/// to be of the form `master.subbranch` instead of simply `subbranch`.
2056/// This situation happens when the top level object
2057/// has two or more members referencing the same class.
2058/// For example, if a Tree has two branches B1 and B2 corresponding
2059/// to objects of the same class MyClass, one can do:
2060/// ~~~ {.cpp}
2061/// tree.Branch("B1.","MyClass",&b1,8000,1);
2062/// tree.Branch("B2.","MyClass",&b2,8000,1);
2063/// ~~~
2064/// if MyClass has 3 members a,b,c, the two instructions above will generate
2065/// subbranches called B1.a, B1.b ,B1.c, B2.a, B2.b, B2.c
2066///
2067/// bufsize is the buffer size in bytes for this branch
2068/// The default value is 32000 bytes and should be ok for most cases.
2069/// You can specify a larger value (e.g. 256000) if your Tree is not split
2070/// and each entry is large (Megabytes)
2071/// A small value for bufsize is optimum if you intend to access
2072/// the entries in the Tree randomly and your Tree is in split mode.
2074TBranch* TTree::BranchOld(const char* name, const char* classname, void* addobj, Int_t bufsize /* = 32000 */, Int_t splitlevel /* = 1 */)
2075{
2076 TClass* cl = TClass::GetClass(classname);
2077 if (!cl) {
2078 Error("BranchOld", "Cannot find class: '%s'", classname);
2079 return 0;
2080 }
2081 if (!cl->IsTObject()) {
2082 if (fgBranchStyle == 0) {
2083 Fatal("BranchOld", "The requested class ('%s') does not inherit from TObject.\n"
2084 "\tfgBranchStyle is set to zero requesting by default to use BranchOld.\n"
2085 "\tIf this is intentional use Bronch instead of Branch or BranchOld.", classname);
2086 } else {
2087 Fatal("BranchOld", "The requested class ('%s') does not inherit from TObject.\n"
2088 "\tYou can not use BranchOld to store objects of this type.",classname);
2089 }
2090 return 0;
2091 }
2092 TBranch* branch = new TBranchObject(this, name, classname, addobj, bufsize, splitlevel);
2093 fBranches.Add(branch);
2094 if (!splitlevel) {
2095 return branch;
2096 }
2097 // We are going to fully split the class now.
2098 TObjArray* blist = branch->GetListOfBranches();
2099 const char* rdname = 0;
2100 const char* dname = 0;
2101 TString branchname;
2102 char** apointer = (char**) addobj;
2103 TObject* obj = (TObject*) *apointer;
2104 Bool_t delobj = kFALSE;
2105 if (!obj) {
2106 obj = (TObject*) cl->New();
2107 delobj = kTRUE;
2108 }
2109 // Build the StreamerInfo if first time for the class.
2110 BuildStreamerInfo(cl, obj);
2111 // Loop on all public data members of the class and its base classes.
2112 Int_t lenName = strlen(name);
2113 Int_t isDot = 0;
2114 if (name[lenName-1] == '.') {
2115 isDot = 1;
2116 }
2117 TBranch* branch1 = 0;
2118 TRealData* rd = 0;
2119 TRealData* rdi = 0;
2120 TIter nexti(cl->GetListOfRealData());
2121 TIter next(cl->GetListOfRealData());
2122 // Note: This loop results in a full split because the
2123 // real data list includes all data members of
2124 // data members.
2125 while ((rd = (TRealData*) next())) {
2126 if (rd->TestBit(TRealData::kTransient)) continue;
2127
2128 // Loop over all data members creating branches for each one.
2129 TDataMember* dm = rd->GetDataMember();
2130 if (!dm->IsPersistent()) {
2131 // Do not process members with an "!" as the first character in the comment field.
2132 continue;
2133 }
2134 if (rd->IsObject()) {
2135 // We skip data members of class type.
2136 // But we do build their real data, their
2137 // streamer info, and write their streamer
2138 // info to the current directory's file.
2139 // Oh yes, and we also do this for all of
2140 // their base classes.
2142 if (clm) {
2143 BuildStreamerInfo(clm, (char*) obj + rd->GetThisOffset());
2144 }
2145 continue;
2146 }
2147 rdname = rd->GetName();
2148 dname = dm->GetName();
2149 if (cl->CanIgnoreTObjectStreamer()) {
2150 // Skip the TObject base class data members.
2151 // FIXME: This prevents a user from ever
2152 // using these names themself!
2153 if (!strcmp(dname, "fBits")) {
2154 continue;
2155 }
2156 if (!strcmp(dname, "fUniqueID")) {
2157 continue;
2158 }
2159 }
2160 TDataType* dtype = dm->GetDataType();
2161 Int_t code = 0;
2162 if (dtype) {
2163 code = dm->GetDataType()->GetType();
2164 }
2165 // Encode branch name. Use real data member name
2166 branchname = rdname;
2167 if (isDot) {
2168 if (dm->IsaPointer()) {
2169 // FIXME: This is wrong! The asterisk is not usually in the front!
2170 branchname.Form("%s%s", name, &rdname[1]);
2171 } else {
2172 branchname.Form("%s%s", name, &rdname[0]);
2173 }
2174 }
2175 // FIXME: Change this to a string stream.
2176 TString leaflist;
2177 Int_t offset = rd->GetThisOffset();
2178 char* pointer = ((char*) obj) + offset;
2179 if (dm->IsaPointer()) {
2180 // We have a pointer to an object or a pointer to an array of basic types.
2181 TClass* clobj = 0;
2182 if (!dm->IsBasic()) {
2183 clobj = TClass::GetClass(dm->GetTypeName());
2184 }
2185 if (clobj && clobj->InheritsFrom(TClonesArray::Class())) {
2186 // We have a pointer to a clones array.
2187 char* cpointer = (char*) pointer;
2188 char** ppointer = (char**) cpointer;
2189 TClonesArray* li = (TClonesArray*) *ppointer;
2190 if (splitlevel != 2) {
2191 if (isDot) {
2192 branch1 = new TBranchClones(branch,branchname, pointer, bufsize);
2193 } else {
2194 // FIXME: This is wrong! The asterisk is not usually in the front!
2195 branch1 = new TBranchClones(branch,&branchname.Data()[1], pointer, bufsize);
2196 }
2197 blist->Add(branch1);
2198 } else {
2199 if (isDot) {
2200 branch1 = new TBranchObject(branch, branchname, li->ClassName(), pointer, bufsize);
2201 } else {
2202 // FIXME: This is wrong! The asterisk is not usually in the front!
2203 branch1 = new TBranchObject(branch, &branchname.Data()[1], li->ClassName(), pointer, bufsize);
2204 }
2205 blist->Add(branch1);
2206 }
2207 } else if (clobj) {
2208 // We have a pointer to an object.
2209 //
2210 // It must be a TObject object.
2211 if (!clobj->IsTObject()) {
2212 continue;
2213 }
2214 branch1 = new TBranchObject(branch, dname, clobj->GetName(), pointer, bufsize, 0);
2215 if (isDot) {
2216 branch1->SetName(branchname);
2217 } else {
2218 // FIXME: This is wrong! The asterisk is not usually in the front!
2219 // Do not use the first character (*).
2220 branch1->SetName(&branchname.Data()[1]);
2221 }
2222 blist->Add(branch1);
2223 } else {
2224 // We have a pointer to an array of basic types.
2225 //
2226 // Check the comments in the text of the code for an index specification.
2227 const char* index = dm->GetArrayIndex();
2228 if (index[0]) {
2229 // We are a pointer to a varying length array of basic types.
2230 //check that index is a valid data member name
2231 //if member is part of an object (e.g. fA and index=fN)
2232 //index must be changed from fN to fA.fN
2233 TString aindex (rd->GetName());
2234 Ssiz_t rdot = aindex.Last('.');
2235 if (rdot>=0) {
2236 aindex.Remove(rdot+1);
2237 aindex.Append(index);
2238 }
2239 nexti.Reset();
2240 while ((rdi = (TRealData*) nexti())) {
2241 if (rdi->TestBit(TRealData::kTransient)) continue;
2242
2243 if (!strcmp(rdi->GetName(), index)) {
2244 break;
2245 }
2246 if (!strcmp(rdi->GetName(), aindex)) {
2247 index = rdi->GetName();
2248 break;
2249 }
2250 }
2251
2252 char vcode = DataTypeToChar((EDataType)code);
2253 // Note that we differentiate between strings and
2254 // char array by the fact that there is NO specified
2255 // size for a string (see next if (code == 1)
2256
2257 if (vcode) {
2258 leaflist.Form("%s[%s]/%c", &rdname[0], index, vcode);
2259 } else {
2260 Error("BranchOld", "Cannot create branch for rdname: %s code: %d", branchname.Data(), code);
2261 leaflist = "";
2262 }
2263 } else {
2264 // We are possibly a character string.
2265 if (code == 1) {
2266 // We are a character string.
2267 leaflist.Form("%s/%s", dname, "C");
2268 } else {
2269 // Invalid array specification.
2270 // FIXME: We need an error message here.
2271 continue;
2272 }
2273 }
2274 // There are '*' in both the branchname and leaflist, remove them.
2275 TString bname( branchname );
2276 bname.ReplaceAll("*","");
2277 leaflist.ReplaceAll("*","");
2278 // Add the branch to the tree and indicate that the address
2279 // is that of a pointer to be dereferenced before using.
2280 branch1 = new TBranch(branch, bname, *((void**) pointer), leaflist, bufsize);
2281 TLeaf* leaf = (TLeaf*) branch1->GetListOfLeaves()->At(0);
2283 leaf->SetAddress((void**) pointer);
2284 blist->Add(branch1);
2285 }
2286 } else if (dm->IsBasic()) {
2287 // We have a basic type.
2288
2289 char vcode = DataTypeToChar((EDataType)code);
2290 if (vcode) {
2291 leaflist.Form("%s/%c", rdname, vcode);
2292 } else {
2293 Error("BranchOld", "Cannot create branch for rdname: %s code: %d", branchname.Data(), code);
2294 leaflist = "";
2295 }
2296 branch1 = new TBranch(branch, branchname, pointer, leaflist, bufsize);
2297 branch1->SetTitle(rdname);
2298 blist->Add(branch1);
2299 } else {
2300 // We have a class type.
2301 // Note: This cannot happen due to the rd->IsObject() test above.
2302 // FIXME: Put an error message here just in case.
2303 }
2304 if (branch1) {
2305 branch1->SetOffset(offset);
2306 } else {
2307 Warning("BranchOld", "Cannot process member: '%s'", rdname);
2308 }
2309 }
2310 if (delobj) {
2311 delete obj;
2312 obj = 0;
2313 }
2314 return branch;
2315}
2316
2317////////////////////////////////////////////////////////////////////////////////
2318/// Build the optional branch supporting the TRefTable.
2319/// This branch will keep all the information to find the branches
2320/// containing referenced objects.
2321///
2322/// At each Tree::Fill, the branch numbers containing the
2323/// referenced objects are saved to the TBranchRef basket.
2324/// When the Tree header is saved (via TTree::Write), the branch
2325/// is saved keeping the information with the pointers to the branches
2326/// having referenced objects.
2329{
2330 if (!fBranchRef) {
2331 fBranchRef = new TBranchRef(this);
2332 }
2333 return fBranchRef;
2334}
2335
2336////////////////////////////////////////////////////////////////////////////////
2337/// Create a new TTree BranchElement.
2338///
2339/// ## WARNING about this new function
2340///
2341/// This function is designed to replace the internal
2342/// implementation of the old TTree::Branch (whose implementation
2343/// has been moved to BranchOld).
2344///
2345/// NOTE: The 'Bronch' method supports only one possible calls
2346/// signature (where the object type has to be specified
2347/// explicitly and the address must be the address of a pointer).
2348/// For more flexibility use 'Branch'. Use Bronch only in (rare)
2349/// cases (likely to be legacy cases) where both the new and old
2350/// implementation of Branch needs to be used at the same time.
2351///
2352/// This function is far more powerful than the old Branch
2353/// function. It supports the full C++, including STL and has
2354/// the same behaviour in split or non-split mode. classname does
2355/// not have to derive from TObject. The function is based on
2356/// the new TStreamerInfo.
2357///
2358/// Build a TBranchElement for an object of class classname.
2359///
2360/// addr is the address of a pointer to an object of class
2361/// classname. The class dictionary must be available (ClassDef
2362/// in class header).
2363///
2364/// Note: See the comments in TBranchElement::SetAddress() for a more
2365/// detailed discussion of the meaning of the addr parameter.
2366///
2367/// This option requires access to the library where the
2368/// corresponding class is defined. Accessing one single data
2369/// member in the object implies reading the full object.
2370///
2371/// By default the branch buffers are stored in the same file as the Tree.
2372/// use TBranch::SetFile to specify a different file
2373///
2374/// IMPORTANT NOTE about branch names:
2375///
2376/// And in general, in case two or more master branches contain subbranches
2377/// with identical names, one must add a "." (dot) character at the end
2378/// of the master branch name. This will force the name of the subbranches
2379/// to be of the form `master.subbranch` instead of simply `subbranch`.
2380/// This situation happens when the top level object
2381/// has two or more members referencing the same class.
2382/// For example, if a Tree has two branches B1 and B2 corresponding
2383/// to objects of the same class MyClass, one can do:
2384/// ~~~ {.cpp}
2385/// tree.Branch("B1.","MyClass",&b1,8000,1);
2386/// tree.Branch("B2.","MyClass",&b2,8000,1);
2387/// ~~~
2388/// if MyClass has 3 members a,b,c, the two instructions above will generate
2389/// subbranches called B1.a, B1.b ,B1.c, B2.a, B2.b, B2.c
2390///
2391/// bufsize is the buffer size in bytes for this branch
2392/// The default value is 32000 bytes and should be ok for most cases.
2393/// You can specify a larger value (e.g. 256000) if your Tree is not split
2394/// and each entry is large (Megabytes)
2395/// A small value for bufsize is optimum if you intend to access
2396/// the entries in the Tree randomly and your Tree is in split mode.
2397///
2398/// Use splitlevel < 0 instead of splitlevel=0 when the class
2399/// has a custom Streamer
2400///
2401/// Note: if the split level is set to the default (99), TTree::Branch will
2402/// not issue a warning if the class can not be split.
2404TBranch* TTree::Bronch(const char* name, const char* classname, void* addr, Int_t bufsize /* = 32000 */, Int_t splitlevel /* = 99 */)
2405{
2406 return BronchExec(name, classname, addr, kTRUE, bufsize, splitlevel);
2407}
2408
2409////////////////////////////////////////////////////////////////////////////////
2410/// Helper function implementing TTree::Bronch and TTree::Branch(const char *name, T &obj);
2412TBranch* TTree::BronchExec(const char* name, const char* classname, void* addr, Bool_t isptrptr, Int_t bufsize /* = 32000 */, Int_t splitlevel /* = 99 */)
2413{
2414 TClass* cl = TClass::GetClass(classname);
2415 if (!cl) {
2416 Error("Bronch", "Cannot find class:%s", classname);
2417 return 0;
2418 }
2419
2420 //if splitlevel <= 0 and class has a custom Streamer, we must create
2421 //a TBranchObject. We cannot assume that TClass::ReadBuffer is consistent
2422 //with the custom Streamer. The penalty is that one cannot process
2423 //this Tree without the class library containing the class.
2424
2425 char* objptr = 0;
2426 if (!isptrptr) {
2427 objptr = (char*)addr;
2428 } else if (addr) {
2429 objptr = *((char**) addr);
2430 }
2431
2432 if (cl == TClonesArray::Class()) {
2433 TClonesArray* clones = (TClonesArray*) objptr;
2434 if (!clones) {
2435 Error("Bronch", "Pointer to TClonesArray is null");
2436 return 0;
2437 }
2438 if (!clones->GetClass()) {
2439 Error("Bronch", "TClonesArray with no class defined in branch: %s", name);
2440 return 0;
2441 }
2442 if (!clones->GetClass()->HasDataMemberInfo()) {
2443 Error("Bronch", "TClonesArray with no dictionary defined in branch: %s", name);
2444 return 0;
2445 }
2446 bool hasCustomStreamer = clones->GetClass()->TestBit(TClass::kHasCustomStreamerMember);
2447 if (splitlevel > 0) {
2448 if (hasCustomStreamer)
2449 Warning("Bronch", "Using split mode on a class: %s with a custom Streamer", clones->GetClass()->GetName());
2450 } else {
2451 if (hasCustomStreamer) clones->BypassStreamer(kFALSE);
2452 TBranchObject *branch = new TBranchObject(this,name,classname,addr,bufsize,0,/*compress=*/ -1,isptrptr);
2453 fBranches.Add(branch);
2454 return branch;
2455 }
2456 }
2457
2458 if (cl->GetCollectionProxy()) {
2460 //if (!collProxy) {
2461 // Error("Bronch", "%s is missing its CollectionProxy (for branch %s)", classname, name);
2462 //}
2463 TClass* inklass = collProxy->GetValueClass();
2464 if (!inklass && (collProxy->GetType() == 0)) {
2465 Error("Bronch", "%s with no class defined in branch: %s", classname, name);
2466 return 0;
2467 }
2468 if ((splitlevel > 0) && inklass && (inklass->GetCollectionProxy() == 0)) {
2470 if ((stl != ROOT::kSTLmap) && (stl != ROOT::kSTLmultimap)) {
2471 if (!inklass->HasDataMemberInfo()) {
2472 Error("Bronch", "Container with no dictionary defined in branch: %s", name);
2473 return 0;
2474 }
2476 Warning("Bronch", "Using split mode on a class: %s with a custom Streamer", inklass->GetName());
2477 }
2478 }
2479 }
2480 //-------------------------------------------------------------------------
2481 // If the splitting switch is enabled, the split level is big enough and
2482 // the collection contains pointers we can split it
2483 //////////////////////////////////////////////////////////////////////////
2484
2485 TBranch *branch;
2486 if( splitlevel > kSplitCollectionOfPointers && collProxy->HasPointers() )
2487 branch = new TBranchSTL( this, name, collProxy, bufsize, splitlevel );
2488 else
2489 branch = new TBranchElement(this, name, collProxy, bufsize, splitlevel);
2490 fBranches.Add(branch);
2491 if (isptrptr) {
2492 branch->SetAddress(addr);
2493 } else {
2494 branch->SetObject(addr);
2495 }
2496 return branch;
2497 }
2498
2499 Bool_t hasCustomStreamer = kFALSE;
2500 if (!cl->HasDataMemberInfo() && !cl->GetCollectionProxy()) {
2501 Error("Bronch", "Cannot find dictionary for class: %s", classname);
2502 return 0;
2503 }
2504
2506 // Not an STL container and the linkdef file had a "-" after the class name.
2507 hasCustomStreamer = kTRUE;
2508 }
2509
2510 if (splitlevel < 0 || ((splitlevel == 0) && hasCustomStreamer && cl->IsTObject())) {
2511 TBranchObject* branch = new TBranchObject(this, name, classname, addr, bufsize, 0, /*compress=*/ ROOT::RCompressionSetting::EAlgorithm::kInherit, isptrptr);
2512 fBranches.Add(branch);
2513 return branch;
2514 }
2515
2516 if (cl == TClonesArray::Class()) {
2517 // Special case of TClonesArray.
2518 // No dummy object is created.
2519 // The streamer info is not rebuilt unoptimized.
2520 // No dummy top-level branch is created.
2521 // No splitting is attempted.
2522 TBranchElement* branch = new TBranchElement(this, name, (TClonesArray*) objptr, bufsize, splitlevel%kSplitCollectionOfPointers);
2523 fBranches.Add(branch);
2524 if (isptrptr) {
2525 branch->SetAddress(addr);
2526 } else {
2527 branch->SetObject(addr);
2528 }
2529 return branch;
2530 }
2531
2532 //
2533 // If we are not given an object to use as an i/o buffer
2534 // then create a temporary one which we will delete just
2535 // before returning.
2536 //
2537
2538 Bool_t delobj = kFALSE;
2539
2540 if (!objptr) {
2541 objptr = (char*) cl->New();
2542 delobj = kTRUE;
2543 }
2544
2545 //
2546 // Avoid splitting unsplittable classes.
2547 //
2548
2549 if ((splitlevel > 0) && !cl->CanSplit()) {
2550 if (splitlevel != 99) {
2551 Warning("Bronch", "%s cannot be split, resetting splitlevel to 0", cl->GetName());
2552 }
2553 splitlevel = 0;
2554 }
2555
2556 //
2557 // Make sure the streamer info is built and fetch it.
2558 //
2559 // If we are splitting, then make sure the streamer info
2560 // is built unoptimized (data members are not combined).
2561 //
2562
2563 TStreamerInfo* sinfo = BuildStreamerInfo(cl, objptr, splitlevel==0);
2564 if (!sinfo) {
2565 Error("Bronch", "Cannot build the StreamerInfo for class: %s", cl->GetName());
2566 return 0;
2567 }
2568
2569 //
2570 // Create a dummy top level branch object.
2571 //
2572
2573 Int_t id = -1;
2574 if (splitlevel > 0) {
2575 id = -2;
2576 }
2577 TBranchElement* branch = new TBranchElement(this, name, sinfo, id, objptr, bufsize, splitlevel);
2578 fBranches.Add(branch);
2579
2580 //
2581 // Do splitting, if requested.
2582 //
2583
2584 if (splitlevel%kSplitCollectionOfPointers > 0) {
2585 branch->Unroll(name, cl, sinfo, objptr, bufsize, splitlevel);
2586 }
2587
2588 //
2589 // Setup our offsets into the user's i/o buffer.
2590 //
2591
2592 if (isptrptr) {
2593 branch->SetAddress(addr);
2594 } else {
2595 branch->SetObject(addr);
2596 }
2597
2598 if (delobj) {
2599 cl->Destructor(objptr);
2600 objptr = 0;
2601 }
2602
2603 return branch;
2604}
2605
2606////////////////////////////////////////////////////////////////////////////////
2607/// Browse content of the TTree.
2610{
2612 if (fUserInfo) {
2613 if (strcmp("TList",fUserInfo->GetName())==0) {
2614 fUserInfo->SetName("UserInfo");
2615 b->Add(fUserInfo);
2616 fUserInfo->SetName("TList");
2617 } else {
2618 b->Add(fUserInfo);
2619 }
2620 }
2621}
2622
2623////////////////////////////////////////////////////////////////////////////////
2624/// Build a Tree Index (default is TTreeIndex).
2625/// See a description of the parameters and functionality in
2626/// TTreeIndex::TTreeIndex().
2627///
2628/// The return value is the number of entries in the Index (< 0 indicates failure).
2629///
2630/// A TTreeIndex object pointed by fTreeIndex is created.
2631/// This object will be automatically deleted by the TTree destructor.
2632/// If an index is already existing, this is replaced by the new one without being
2633/// deleted. This behaviour prevents the deletion of a previously external index
2634/// assigned to the TTree via the TTree::SetTreeIndex() method.
2635/// \see also comments in TTree::SetTreeIndex().
2637Int_t TTree::BuildIndex(const char* majorname, const char* minorname /* = "0" */)
2638{
2639 fTreeIndex = GetPlayer()->BuildIndex(this, majorname, minorname);
2640 if (fTreeIndex->IsZombie()) {
2641 delete fTreeIndex;
2642 fTreeIndex = 0;
2643 return 0;
2644 }
2645 return fTreeIndex->GetN();
2646}
2647
2648////////////////////////////////////////////////////////////////////////////////
2649/// Build StreamerInfo for class cl.
2650/// pointer is an optional argument that may contain a pointer to an object of cl.
2652TStreamerInfo* TTree::BuildStreamerInfo(TClass* cl, void* pointer /* = 0 */, Bool_t canOptimize /* = kTRUE */ )
2653{
2654 if (!cl) {
2655 return 0;
2656 }
2657 cl->BuildRealData(pointer);
2659
2660 // Create StreamerInfo for all base classes.
2661 TBaseClass* base = 0;
2662 TIter nextb(cl->GetListOfBases());
2663 while((base = (TBaseClass*) nextb())) {
2664 if (base->IsSTLContainer()) {
2665 continue;
2666 }
2667 TClass* clm = TClass::GetClass(base->GetName());
2668 BuildStreamerInfo(clm, pointer, canOptimize);
2669 }
2670 if (sinfo && fDirectory) {
2672 }
2673 return sinfo;
2674}
2675
2676////////////////////////////////////////////////////////////////////////////////
2677/// Enable the TTreeCache unless explicitly disabled for this TTree by
2678/// a prior call to `SetCacheSize(0)`.
2679/// If the environment variable `ROOT_TTREECACHE_SIZE` or the rootrc config
2680/// `TTreeCache.Size` has been set to zero, this call will over-ride them with
2681/// a value of 1.0 (i.e. use a cache size to hold 1 cluster)
2682///
2683/// Return true if there is a cache attached to the `TTree` (either pre-exisiting
2684/// or created as part of this call)
2686{
2688 if (!file)
2689 return kFALSE;
2690 // Check for an existing cache
2692 if (pf)
2693 return kTRUE;
2694 if (fCacheUserSet && fCacheSize == 0)
2695 return kFALSE;
2696 return (0 == SetCacheSizeAux(kTRUE, -1));
2697}
2698
2699////////////////////////////////////////////////////////////////////////////////
2700/// Called by TTree::Fill() when file has reached its maximum fgMaxTreeSize.
2701/// Create a new file. If the original file is named "myfile.root",
2702/// subsequent files are named "myfile_1.root", "myfile_2.root", etc.
2703///
2704/// Returns a pointer to the new file.
2705///
2706/// Currently, the automatic change of file is restricted
2707/// to the case where the tree is in the top level directory.
2708/// The file should not contain sub-directories.
2709///
2710/// Before switching to a new file, the tree header is written
2711/// to the current file, then the current file is closed.
2712///
2713/// To process the multiple files created by ChangeFile, one must use
2714/// a TChain.
2715///
2716/// The new file name has a suffix "_N" where N is equal to fFileNumber+1.
2717/// By default a Root session starts with fFileNumber=0. One can set
2718/// fFileNumber to a different value via TTree::SetFileNumber.
2719/// In case a file named "_N" already exists, the function will try
2720/// a file named "__N", then "___N", etc.
2721///
2722/// fgMaxTreeSize can be set via the static function TTree::SetMaxTreeSize.
2723/// The default value of fgMaxTreeSize is 100 Gigabytes.
2724///
2725/// If the current file contains other objects like TH1 and TTree,
2726/// these objects are automatically moved to the new file.
2727///
2728/// \warning Be careful when writing the final Tree header to the file!
2729/// Don't do:
2730/// ~~~ {.cpp}
2731/// TFile *file = new TFile("myfile.root","recreate");
2732/// TTree *T = new TTree("T","title");
2733/// T->Fill(); // Loop
2734/// file->Write();
2735/// file->Close();
2736/// ~~~
2737/// \warning but do the following:
2738/// ~~~ {.cpp}
2739/// TFile *file = new TFile("myfile.root","recreate");
2740/// TTree *T = new TTree("T","title");
2741/// T->Fill(); // Loop
2742/// file = T->GetCurrentFile(); // To get the pointer to the current file
2743/// file->Write();
2744/// file->Close();
2745/// ~~~
2746///
2747/// \note This method is never called if the input file is a `TMemFile` or derivate.
2750{
2751 file->cd();
2752 Write();
2753 Reset();
2754 constexpr auto kBufSize = 2000;
2755 char* fname = new char[kBufSize];
2756 ++fFileNumber;
2757 char uscore[10];
2758 for (Int_t i = 0; i < 10; ++i) {
2759 uscore[i] = 0;
2760 }
2761 Int_t nus = 0;
2762 // Try to find a suitable file name that does not already exist.
2763 while (nus < 10) {
2764 uscore[nus] = '_';
2765 fname[0] = 0;
2766 strlcpy(fname, file->GetName(), kBufSize);
2767
2768 if (fFileNumber > 1) {
2769 char* cunder = strrchr(fname, '_');
2770 if (cunder) {
2771 snprintf(cunder, kBufSize - Int_t(cunder - fname), "%s%d", uscore, fFileNumber);
2772 const char* cdot = strrchr(file->GetName(), '.');
2773 if (cdot) {
2774 strlcat(fname, cdot, kBufSize);
2775 }
2776 } else {
2777 char fcount[21];
2778 snprintf(fcount,21, "%s%d", uscore, fFileNumber);
2779 strlcat(fname, fcount, kBufSize);
2780 }
2781 } else {
2782 char* cdot = strrchr(fname, '.');
2783 if (cdot) {
2784 snprintf(cdot, kBufSize - Int_t(fname-cdot), "%s%d", uscore, fFileNumber);
2785 strlcat(fname, strrchr(file->GetName(), '.'), kBufSize);
2786 } else {
2787 char fcount[21];
2788 snprintf(fcount,21, "%s%d", uscore, fFileNumber);
2789 strlcat(fname, fcount, kBufSize);
2790 }
2791 }
2792 if (gSystem->AccessPathName(fname)) {
2793 break;
2794 }
2795 ++nus;
2796 Warning("ChangeFile", "file %s already exist, trying with %d underscores", fname, nus+1);
2797 }
2798 Int_t compress = file->GetCompressionSettings();
2799 TFile* newfile = TFile::Open(fname, "recreate", "chain files", compress);
2800 if (newfile == 0) {
2801 Error("Fill","Failed to open new file %s, continuing as a memory tree.",fname);
2802 } else {
2803 Printf("Fill: Switching to new file: %s", fname);
2804 }
2805 // The current directory may contain histograms and trees.
2806 // These objects must be moved to the new file.
2807 TBranch* branch = 0;
2808 TObject* obj = 0;
2809 while ((obj = file->GetList()->First())) {
2810 file->Remove(obj);
2811 // Histogram: just change the directory.
2812 if (obj->InheritsFrom("TH1")) {
2813 gROOT->ProcessLine(TString::Format("((%s*)0x%zx)->SetDirectory((TDirectory*)0x%zx);", obj->ClassName(), (size_t) obj, (size_t) newfile));
2814 continue;
2815 }
2816 // Tree: must save all trees in the old file, reset them.
2817 if (obj->InheritsFrom(TTree::Class())) {
2818 TTree* t = (TTree*) obj;
2819 if (t != this) {
2820 t->AutoSave();
2821 t->Reset();
2823 }
2824 t->SetDirectory(newfile);
2825 TIter nextb(t->GetListOfBranches());
2826 while ((branch = (TBranch*)nextb())) {
2827 branch->SetFile(newfile);
2828 }
2829 if (t->GetBranchRef()) {
2830 t->GetBranchRef()->SetFile(newfile);
2831 }
2832 continue;
2833 }
2834 // Not a TH1 or a TTree, move object to new file.
2835 if (newfile) newfile->Append(obj);
2836 file->Remove(obj);
2837 }
2838 file->TObject::Delete();
2839 file = 0;
2840 delete[] fname;
2841 fname = 0;
2842 return newfile;
2843}
2844
2845////////////////////////////////////////////////////////////////////////////////
2846/// Check whether or not the address described by the last 3 parameters
2847/// matches the content of the branch. If a Data Model Evolution conversion
2848/// is involved, reset the fInfo of the branch.
2849/// The return values are:
2850//
2851/// - kMissingBranch (-5) : Missing branch
2852/// - kInternalError (-4) : Internal error (could not find the type corresponding to a data type number)
2853/// - kMissingCompiledCollectionProxy (-3) : Missing compiled collection proxy for a compiled collection
2854/// - kMismatch (-2) : Non-Class Pointer type given does not match the type expected by the branch
2855/// - kClassMismatch (-1) : Class Pointer type given does not match the type expected by the branch
2856/// - kMatch (0) : perfect match
2857/// - kMatchConversion (1) : match with (I/O) conversion
2858/// - kMatchConversionCollection (2) : match with (I/O) conversion of the content of a collection
2859/// - kMakeClass (3) : MakeClass mode so we can not check.
2860/// - kVoidPtr (4) : void* passed so no check was made.
2861/// - kNoCheck (5) : Underlying TBranch not yet available so no check was made.
2862/// In addition this can be multiplexed with the two bits:
2863/// - kNeedEnableDecomposedObj : in order for the address (type) to be 'usable' the branch needs to be in Decomposed Object (aka MakeClass) mode.
2864/// - kNeedDisableDecomposedObj : in order for the address (type) to be 'usable' the branch needs to not be in Decomposed Object (aka MakeClass) mode.
2865/// This bits can be masked out by using kDecomposedObjMask
2867Int_t TTree::CheckBranchAddressType(TBranch* branch, TClass* ptrClass, EDataType datatype, Bool_t isptr)
2868{
2869 if (GetMakeClass()) {
2870 // If we are in MakeClass mode so we do not really use classes.
2871 return kMakeClass;
2872 }
2873
2874 // Let's determine what we need!
2875 TClass* expectedClass = 0;
2876 EDataType expectedType = kOther_t;
2877 if (0 != branch->GetExpectedType(expectedClass,expectedType) ) {
2878 // Something went wrong, the warning message has already been issued.
2879 return kInternalError;
2880 }
2881 bool isBranchElement = branch->InheritsFrom( TBranchElement::Class() );
2882 if (expectedClass && datatype == kOther_t && ptrClass == 0) {
2883 if (isBranchElement) {
2884 TBranchElement* bEl = (TBranchElement*)branch;
2885 bEl->SetTargetClass( expectedClass->GetName() );
2886 }
2887 if (expectedClass && expectedClass->GetCollectionProxy() && dynamic_cast<TEmulatedCollectionProxy*>(expectedClass->GetCollectionProxy())) {
2888 Error("SetBranchAddress", "Unable to determine the type given for the address for \"%s\". "
2889 "The class expected (%s) refers to an stl collection and do not have a compiled CollectionProxy. "
2890 "Please generate the dictionary for this class (%s)",
2891 branch->GetName(), expectedClass->GetName(), expectedClass->GetName());
2893 }
2894 if (!expectedClass->IsLoaded()) {
2895 // The originally expected class does not have a dictionary, it is then plausible that the pointer being passed is the right type
2896 // (we really don't know). So let's express that.
2897 Error("SetBranchAddress", "Unable to determine the type given for the address for \"%s\". "
2898 "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."
2899 "Please generate the dictionary for this class (%s)",
2900 branch->GetName(), expectedClass->GetName(), expectedClass->GetName());
2901 } else {
2902 Error("SetBranchAddress", "Unable to determine the type given for the address for \"%s\". "
2903 "This is probably due to a missing dictionary, the original data class for this branch is %s.", branch->GetName(), expectedClass->GetName());
2904 }
2905 return kClassMismatch;
2906 }
2907 if (expectedClass && ptrClass && (branch->GetMother() == branch)) {
2908 // Top Level branch
2909 if (!isptr) {
2910 Error("SetBranchAddress", "The address for \"%s\" should be the address of a pointer!", branch->GetName());
2911 }
2912 }
2913 if (expectedType == kFloat16_t) {
2914 expectedType = kFloat_t;
2915 }
2916 if (expectedType == kDouble32_t) {
2917 expectedType = kDouble_t;
2918 }
2919 if (datatype == kFloat16_t) {
2920 datatype = kFloat_t;
2921 }
2922 if (datatype == kDouble32_t) {
2923 datatype = kDouble_t;
2924 }
2925
2926 /////////////////////////////////////////////////////////////////////////////
2927 // Deal with the class renaming
2928 /////////////////////////////////////////////////////////////////////////////
2929
2930 if( expectedClass && ptrClass &&
2931 expectedClass != ptrClass &&
2932 isBranchElement &&
2933 ptrClass->GetSchemaRules() &&
2934 ptrClass->GetSchemaRules()->HasRuleWithSourceClass( expectedClass->GetName() ) ) {
2935 TBranchElement* bEl = (TBranchElement*)branch;
2936
2937 if ( ptrClass->GetCollectionProxy() && expectedClass->GetCollectionProxy() ) {
2938 if (gDebug > 7)
2939 Info("SetBranchAddress", "Matching STL collection (at least according to the SchemaRuleSet when "
2940 "reading a %s into a %s",expectedClass->GetName(),ptrClass->GetName());
2941
2942 bEl->SetTargetClass( ptrClass->GetName() );
2943 return kMatchConversion;
2944
2945 } else if ( !ptrClass->GetConversionStreamerInfo( expectedClass, bEl->GetClassVersion() ) &&
2946 !ptrClass->FindConversionStreamerInfo( expectedClass, bEl->GetCheckSum() ) ) {
2947 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());
2948
2949 bEl->SetTargetClass( expectedClass->GetName() );
2950 return kClassMismatch;
2951 }
2952 else {
2953
2954 bEl->SetTargetClass( ptrClass->GetName() );
2955 return kMatchConversion;
2956 }
2957
2958 } else if (expectedClass && ptrClass && !expectedClass->InheritsFrom(ptrClass)) {
2959
2960 if (expectedClass->GetCollectionProxy() && ptrClass->GetCollectionProxy() &&
2961 isBranchElement &&
2962 expectedClass->GetCollectionProxy()->GetValueClass() &&
2963 ptrClass->GetCollectionProxy()->GetValueClass() )
2964 {
2965 // In case of collection, we know how to convert them, if we know how to convert their content.
2966 // NOTE: we need to extend this to std::pair ...
2967
2968 TClass *onfileValueClass = expectedClass->GetCollectionProxy()->GetValueClass();
2969 TClass *inmemValueClass = ptrClass->GetCollectionProxy()->GetValueClass();
2970
2971 if (inmemValueClass->GetSchemaRules() &&
2972 inmemValueClass->GetSchemaRules()->HasRuleWithSourceClass(onfileValueClass->GetName() ) )
2973 {
2974 TBranchElement* bEl = (TBranchElement*)branch;
2975 bEl->SetTargetClass( ptrClass->GetName() );
2977 }
2978 }
2979
2980 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());
2981 if (isBranchElement) {
2982 TBranchElement* bEl = (TBranchElement*)branch;
2983 bEl->SetTargetClass( expectedClass->GetName() );
2984 }
2985 return kClassMismatch;
2986
2987 } else if ((expectedType != kOther_t) && (datatype != kOther_t) && (expectedType != kNoType_t) && (datatype != kNoType_t) && (expectedType != datatype)) {
2988 if (datatype != kChar_t) {
2989 // For backward compatibility we assume that (char*) was just a cast and/or a generic address
2990 Error("SetBranchAddress", "The pointer type given \"%s\" (%d) does not correspond to the type needed \"%s\" (%d) by the branch: %s",
2991 TDataType::GetTypeName(datatype), datatype, TDataType::GetTypeName(expectedType), expectedType, branch->GetName());
2992 return kMismatch;
2993 }
2994 } else if ((expectedClass && (datatype != kOther_t && datatype != kNoType_t && datatype != kInt_t)) ||
2995 (ptrClass && (expectedType != kOther_t && expectedType != kNoType_t && datatype != kInt_t)) ) {
2996 // Sometime a null pointer can look an int, avoid complaining in that case.
2997 if (expectedClass) {
2998 Error("SetBranchAddress", "The pointer type given \"%s\" (%d) does not correspond to the type needed \"%s\" by the branch: %s",
2999 TDataType::GetTypeName(datatype), datatype, expectedClass->GetName(), branch->GetName());
3000 if (isBranchElement) {
3001 TBranchElement* bEl = (TBranchElement*)branch;
3002 bEl->SetTargetClass( expectedClass->GetName() );
3003 }
3004 } else {
3005 // 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
3006 // a struct).
3007 bool found = false;
3008 if (ptrClass->IsLoaded()) {
3009 TIter next(ptrClass->GetListOfRealData());
3010 TRealData *rdm;
3011 while ((rdm = (TRealData*)next())) {
3012 if (rdm->GetThisOffset() == 0) {
3013 TDataType *dmtype = rdm->GetDataMember()->GetDataType();
3014 if (dmtype) {
3015 EDataType etype = (EDataType)dmtype->GetType();
3016 if (etype == expectedType) {
3017 found = true;
3018 }
3019 }
3020 break;
3021 }
3022 }
3023 } else {
3024 TIter next(ptrClass->GetListOfDataMembers());
3025 TDataMember *dm;
3026 while ((dm = (TDataMember*)next())) {
3027 if (dm->GetOffset() == 0) {
3028 TDataType *dmtype = dm->GetDataType();
3029 if (dmtype) {
3030 EDataType etype = (EDataType)dmtype->GetType();
3031 if (etype == expectedType) {
3032 found = true;
3033 }
3034 }
3035 break;
3036 }
3037 }
3038 }
3039 if (found) {
3040 // let's check the size.
3041 TLeaf *last = (TLeaf*)branch->GetListOfLeaves()->Last();
3042 long len = last->GetOffset() + last->GetLenType() * last->GetLen();
3043 if (len <= ptrClass->Size()) {
3044 return kMatch;
3045 }
3046 }
3047 Error("SetBranchAddress", "The pointer type given \"%s\" does not correspond to the type needed \"%s\" (%d) by the branch: %s",
3048 ptrClass->GetName(), TDataType::GetTypeName(expectedType), expectedType, branch->GetName());
3049 }
3050 return kMismatch;
3051 }
3052 if (expectedClass && expectedClass->GetCollectionProxy() && dynamic_cast<TEmulatedCollectionProxy*>(expectedClass->GetCollectionProxy())) {
3053 Error("SetBranchAddress", writeStlWithoutProxyMsg,
3054 expectedClass->GetName(), branch->GetName(), expectedClass->GetName());
3055 if (isBranchElement) {
3056 TBranchElement* bEl = (TBranchElement*)branch;
3057 bEl->SetTargetClass( expectedClass->GetName() );
3058 }
3060 }
3061 if (isBranchElement) {
3062 if (expectedClass) {
3063 TBranchElement* bEl = (TBranchElement*)branch;
3064 bEl->SetTargetClass( expectedClass->GetName() );
3065 } else if (expectedType != kNoType_t && expectedType != kOther_t) {
3067 }
3068 }
3069 return kMatch;
3070}
3071
3072////////////////////////////////////////////////////////////////////////////////
3073/// Create a clone of this tree and copy nentries.
3074///
3075/// By default copy all entries.
3076/// The compression level of the cloned tree is set to the destination
3077/// file's compression level.
3078///
3079/// NOTE: Only active branches are copied.
3080/// NOTE: If the TTree is a TChain, the structure of the first TTree
3081/// is used for the copy.
3082///
3083/// IMPORTANT: The cloned tree stays connected with this tree until
3084/// this tree is deleted. In particular, any changes in
3085/// branch addresses in this tree are forwarded to the
3086/// clone trees, unless a branch in a clone tree has had
3087/// its address changed, in which case that change stays in
3088/// effect. When this tree is deleted, all the addresses of
3089/// the cloned tree are reset to their default values.
3090///
3091/// If 'option' contains the word 'fast' and nentries is -1, the
3092/// cloning will be done without unzipping or unstreaming the baskets
3093/// (i.e., a direct copy of the raw bytes on disk).
3094///
3095/// When 'fast' is specified, 'option' can also contain a sorting
3096/// order for the baskets in the output file.
3097///
3098/// There are currently 3 supported sorting order:
3099///
3100/// - SortBasketsByOffset (the default)
3101/// - SortBasketsByBranch
3102/// - SortBasketsByEntry
3103///
3104/// When using SortBasketsByOffset the baskets are written in the
3105/// output file in the same order as in the original file (i.e. the
3106/// baskets are sorted by their offset in the original file; Usually
3107/// this also means that the baskets are sorted by the index/number of
3108/// the _last_ entry they contain)
3109///
3110/// When using SortBasketsByBranch all the baskets of each individual
3111/// branches are stored contiguously. This tends to optimize reading
3112/// speed when reading a small number (1->5) of branches, since all
3113/// their baskets will be clustered together instead of being spread
3114/// across the file. However it might decrease the performance when
3115/// reading more branches (or the full entry).
3116///
3117/// When using SortBasketsByEntry the baskets with the lowest starting
3118/// entry are written first. (i.e. the baskets are sorted by the
3119/// index/number of the first entry they contain). This means that on
3120/// the file the baskets will be in the order in which they will be
3121/// needed when reading the whole tree sequentially.
3122///
3123/// For examples of CloneTree, see tutorials:
3124///
3125/// - copytree.C:
3126/// A macro to copy a subset of a TTree to a new TTree.
3127/// The input file has been generated by the program in
3128/// $ROOTSYS/test/Event with: Event 1000 1 1 1
3129///
3130/// - copytree2.C:
3131/// A macro to copy a subset of a TTree to a new TTree.
3132/// One branch of the new Tree is written to a separate file.
3133/// The input file has been generated by the program in
3134/// $ROOTSYS/test/Event with: Event 1000 1 1 1
3136TTree* TTree::CloneTree(Long64_t nentries /* = -1 */, Option_t* option /* = "" */)
3137{
3138 // Options
3139 Bool_t fastClone = kFALSE;
3140
3141 TString opt = option;
3142 opt.ToLower();
3143 if (opt.Contains("fast")) {
3144 fastClone = kTRUE;
3145 }
3146
3147 // If we are a chain, switch to the first tree.
3148 if ((fEntries > 0) && (LoadTree(0) < 0)) {
3149 // FIXME: We need an error message here.
3150 return 0;
3151 }
3152
3153 // Note: For a tree we get the this pointer, for
3154 // a chain we get the chain's current tree.
3155 TTree* thistree = GetTree();
3156
3157 // We will use this to override the IO features on the cloned branches.
3158 ROOT::TIOFeatures features = this->GetIOFeatures();
3159 ;
3160
3161 // Note: For a chain, the returned clone will be
3162 // a clone of the chain's first tree.
3163 TTree* newtree = (TTree*) thistree->Clone();
3164 if (!newtree) {
3165 return 0;
3166 }
3167
3168 // The clone should not delete any objects allocated by SetAddress().
3169 TObjArray* branches = newtree->GetListOfBranches();
3170 Int_t nb = branches->GetEntriesFast();
3171 for (Int_t i = 0; i < nb; ++i) {
3172 TBranch* br = (TBranch*) branches->UncheckedAt(i);
3174 ((TBranchElement*) br)->ResetDeleteObject();
3175 }
3176 }
3177
3178 // Add the new tree to the list of clones so that
3179 // we can later inform it of changes to branch addresses.
3180 thistree->AddClone(newtree);
3181 if (thistree != this) {
3182 // In case this object is a TChain, add the clone
3183 // also to the TChain's list of clones.
3184 AddClone(newtree);
3185 }
3186
3187 newtree->Reset();
3188
3189 TDirectory* ndir = newtree->GetDirectory();
3190 TFile* nfile = 0;
3191 if (ndir) {
3192 nfile = ndir->GetFile();
3193 }
3194 Int_t newcomp = -1;
3195 if (nfile) {
3196 newcomp = nfile->GetCompressionSettings();
3197 }
3198
3199 //
3200 // Delete non-active branches from the clone.
3201 //
3202 // Note: If we are a chain, this does nothing
3203 // since chains have no leaves.
3204 TObjArray* leaves = newtree->GetListOfLeaves();
3205 Int_t nleaves = leaves->GetEntriesFast();
3206 for (Int_t lndx = 0; lndx < nleaves; ++lndx) {
3207 TLeaf* leaf = (TLeaf*) leaves->UncheckedAt(lndx);
3208 if (!leaf) {
3209 continue;
3210 }
3211 TBranch* branch = leaf->GetBranch();
3212 if (branch && (newcomp > -1)) {
3213 branch->SetCompressionSettings(newcomp);
3214 }
3215 if (branch) branch->SetIOFeatures(features);
3216 if (!branch || !branch->TestBit(kDoNotProcess)) {
3217 continue;
3218 }
3219 // size might change at each iteration of the loop over the leaves.
3220 nb = branches->GetEntriesFast();
3221 for (Long64_t i = 0; i < nb; ++i) {
3222 TBranch* br = (TBranch*) branches->UncheckedAt(i);
3223 if (br == branch) {
3224 branches->RemoveAt(i);
3225 delete br;
3226 br = 0;
3227 branches->Compress();
3228 break;
3229 }
3230 TObjArray* lb = br->GetListOfBranches();
3231 Int_t nb1 = lb->GetEntriesFast();
3232 for (Int_t j = 0; j < nb1; ++j) {
3233 TBranch* b1 = (TBranch*) lb->UncheckedAt(j);
3234 if (!b1) {
3235 continue;
3236 }
3237 if (b1 == branch) {
3238 lb->RemoveAt(j);
3239 delete b1;
3240 b1 = 0;
3241 lb->Compress();
3242 break;
3243 }
3244 TObjArray* lb1 = b1->GetListOfBranches();
3245 Int_t nb2 = lb1->GetEntriesFast();
3246 for (Int_t k = 0; k < nb2; ++k) {
3247 TBranch* b2 = (TBranch*) lb1->UncheckedAt(k);
3248 if (!b2) {
3249 continue;
3250 }
3251 if (b2 == branch) {
3252 lb1->RemoveAt(k);
3253 delete b2;
3254 b2 = 0;
3255 lb1->Compress();
3256 break;
3257 }
3258 }
3259 }
3260 }
3261 }
3262 leaves->Compress();
3263
3264 // Copy MakeClass status.
3265 newtree->SetMakeClass(fMakeClass);
3266
3267 // Copy branch addresses.
3268 CopyAddresses(newtree);
3269
3270 //
3271 // Copy entries if requested.
3272 //
3273
3274 if (nentries != 0) {
3275 if (fastClone && (nentries < 0)) {
3276 if ( newtree->CopyEntries( this, -1, option, kFALSE ) < 0 ) {
3277 // There was a problem!
3278 Error("CloneTTree", "TTree has not been cloned\n");
3279 delete newtree;
3280 newtree = 0;
3281 return 0;
3282 }
3283 } else {
3284 newtree->CopyEntries( this, nentries, option, kFALSE );
3285 }
3286 }
3287
3288 return newtree;
3289}
3290
3291////////////////////////////////////////////////////////////////////////////////
3292/// Set branch addresses of passed tree equal to ours.
3293/// If undo is true, reset the branch addresses instead of copying them.
3294/// This ensures 'separation' of a cloned tree from its original.
3297{
3298 // Copy branch addresses starting from branches.
3299 TObjArray* branches = GetListOfBranches();
3300 Int_t nbranches = branches->GetEntriesFast();
3301 for (Int_t i = 0; i < nbranches; ++i) {
3302 TBranch* branch = (TBranch*) branches->UncheckedAt(i);
3303 if (branch->TestBit(kDoNotProcess)) {
3304 continue;
3305 }
3306 if (undo) {
3307 TBranch* br = tree->GetBranch(branch->GetName());
3308 tree->ResetBranchAddress(br);
3309 } else {
3310 char* addr = branch->GetAddress();
3311 if (!addr) {
3312 if (branch->IsA() == TBranch::Class()) {
3313 // If the branch was created using a leaflist, the branch itself may not have
3314 // an address but the leaf might already.
3315 TLeaf *firstleaf = (TLeaf*)branch->GetListOfLeaves()->At(0);
3316 if (!firstleaf || firstleaf->GetValuePointer()) {
3317 // Either there is no leaf (and thus no point in copying the address)
3318 // or the leaf has an address but we can not copy it via the branche
3319 // this will be copied via the next loop (over the leaf).
3320 continue;
3321 }
3322 }
3323 // Note: This may cause an object to be allocated.
3324 branch->SetAddress(0);
3325 addr = branch->GetAddress();
3326 }
3327 TBranch* br = tree->GetBranch(branch->GetFullName());
3328 if (br) {
3329 if (br->GetMakeClass() != branch->GetMakeClass())
3330 br->SetMakeClass(branch->GetMakeClass());
3331 br->SetAddress(addr);
3332 // The copy does not own any object allocated by SetAddress().
3334 ((TBranchElement*) br)->ResetDeleteObject();
3335 }
3336 } else {
3337 Warning("CopyAddresses", "Could not find branch named '%s' in tree named '%s'", branch->GetName(), tree->GetName());
3338 }
3339 }
3340 }
3341
3342 // Copy branch addresses starting from leaves.
3343 TObjArray* tleaves = tree->GetListOfLeaves();
3344 Int_t ntleaves = tleaves->GetEntriesFast();
3345 std::set<TLeaf*> updatedLeafCount;
3346 for (Int_t i = 0; i < ntleaves; ++i) {
3347 TLeaf* tleaf = (TLeaf*) tleaves->UncheckedAt(i);
3348 TBranch* tbranch = tleaf->GetBranch();
3349 TBranch* branch = GetBranch(tbranch->GetName());
3350 if (!branch) {
3351 continue;
3352 }
3353 TLeaf* leaf = branch->GetLeaf(tleaf->GetName());
3354 if (!leaf) {
3355 continue;
3356 }
3357 if (branch->TestBit(kDoNotProcess)) {
3358 continue;
3359 }
3360 if (undo) {
3361 // Now we know whether the address has been transfered
3362 tree->ResetBranchAddress(tbranch);
3363 } else {
3364 TBranchElement *mother = dynamic_cast<TBranchElement*>(leaf->GetBranch()->GetMother());
3365 bool needAddressReset = false;
3366 if (leaf->GetLeafCount() && (leaf->TestBit(TLeaf::kNewValue) || !leaf->GetValuePointer() || (mother && mother->IsObjectOwner())) && tleaf->GetLeafCount())
3367 {
3368 // If it is an array and it was allocated by the leaf itself,
3369 // let's make sure it is large enough for the incoming data.
3370 if (leaf->GetLeafCount()->GetMaximum() < tleaf->GetLeafCount()->GetMaximum()) {
3371 leaf->GetLeafCount()->IncludeRange( tleaf->GetLeafCount() );
3372 updatedLeafCount.insert(leaf->GetLeafCount());
3373 needAddressReset = true;
3374 } else {
3375 needAddressReset = (updatedLeafCount.find(leaf->GetLeafCount()) != updatedLeafCount.end());
3376 }
3377 }
3378 if (needAddressReset && leaf->GetValuePointer()) {
3379 if (leaf->IsA() == TLeafElement::Class() && mother)
3380 mother->ResetAddress();
3381 else
3382 leaf->SetAddress(nullptr);
3383 }
3384 if (!branch->GetAddress() && !leaf->GetValuePointer()) {
3385 // We should attempts to set the address of the branch.
3386 // something like:
3387 //(TBranchElement*)branch->GetMother()->SetAddress(0)
3388 //plus a few more subtleties (see TBranchElement::GetEntry).
3389 //but for now we go the simplest route:
3390 //
3391 // Note: This may result in the allocation of an object.
3392 branch->SetupAddresses();
3393 }
3394 if (branch->GetAddress()) {
3395 tree->SetBranchAddress(branch->GetName(), (void*) branch->GetAddress());
3396 TBranch* br = tree->GetBranch(branch->GetName());
3397 if (br) {
3398 if (br->IsA() != branch->IsA()) {
3399 Error(
3400 "CopyAddresses",
3401 "Branch kind mismatch between input tree '%s' and output tree '%s' for branch '%s': '%s' vs '%s'",
3402 tree->GetName(), br->GetTree()->GetName(), br->GetName(), branch->IsA()->GetName(),
3403 br->IsA()->GetName());
3404 }
3405 // The copy does not own any object allocated by SetAddress().
3406 // FIXME: We do too much here, br may not be a top-level branch.
3408 ((TBranchElement*) br)->ResetDeleteObject();
3409 }
3410 } else {
3411 Warning("CopyAddresses", "Could not find branch named '%s' in tree named '%s'", branch->GetName(), tree->GetName());
3412 }
3413 } else {
3414 tleaf->SetAddress(leaf->GetValuePointer());
3415 }
3416 }
3417 }
3418
3419 if (undo &&
3420 ( tree->IsA()->InheritsFrom("TNtuple") || tree->IsA()->InheritsFrom("TNtupleD") )
3421 ) {
3422 tree->ResetBranchAddresses();
3423 }
3424}
3425
3426namespace {
3427
3428 enum EOnIndexError { kDrop, kKeep, kBuild };
3429
3430 static Bool_t R__HandleIndex(EOnIndexError onIndexError, TTree *newtree, TTree *oldtree)
3431 {
3432 // Return true if we should continue to handle indices, false otherwise.
3433
3434 Bool_t withIndex = kTRUE;
3435
3436 if ( newtree->GetTreeIndex() ) {
3437 if ( oldtree->GetTree()->GetTreeIndex() == 0 ) {
3438 switch (onIndexError) {
3439 case kDrop:
3440 delete newtree->GetTreeIndex();
3441 newtree->SetTreeIndex(0);
3442 withIndex = kFALSE;
3443 break;
3444 case kKeep:
3445 // Nothing to do really.
3446 break;
3447 case kBuild:
3448 // Build the index then copy it
3449 if (oldtree->GetTree()->BuildIndex(newtree->GetTreeIndex()->GetMajorName(), newtree->GetTreeIndex()->GetMinorName())) {
3450 newtree->GetTreeIndex()->Append(oldtree->GetTree()->GetTreeIndex(), kTRUE);
3451 // Clean up
3452 delete oldtree->GetTree()->GetTreeIndex();
3453 oldtree->GetTree()->SetTreeIndex(0);
3454 }
3455 break;
3456 }
3457 } else {
3458 newtree->GetTreeIndex()->Append(oldtree->GetTree()->GetTreeIndex(), kTRUE);
3459 }
3460 } else if ( oldtree->GetTree()->GetTreeIndex() != 0 ) {
3461 // We discover the first index in the middle of the chain.
3462 switch (onIndexError) {
3463 case kDrop:
3464 // Nothing to do really.
3465 break;
3466 case kKeep: {
3468 index->SetTree(newtree);
3469 newtree->SetTreeIndex(index);
3470 break;
3471 }
3472 case kBuild:
3473 if (newtree->GetEntries() == 0) {
3474 // Start an index.
3476 index->SetTree(newtree);
3477 newtree->SetTreeIndex(index);
3478 } else {
3479 // Build the index so far.
3480 if (newtree->BuildIndex(oldtree->GetTree()->GetTreeIndex()->GetMajorName(), oldtree->GetTree()->GetTreeIndex()->GetMinorName())) {
3481 newtree->GetTreeIndex()->Append(oldtree->GetTree()->GetTreeIndex(), kTRUE);
3482 }
3483 }
3484 break;
3485 }
3486 } else if ( onIndexError == kDrop ) {
3487 // There is no index on this or on tree->GetTree(), we know we have to ignore any further
3488 // index
3489 withIndex = kFALSE;
3490 }
3491 return withIndex;
3492 }
3493}
3494
3495////////////////////////////////////////////////////////////////////////////////
3496/// Copy nentries from given tree to this tree.
3497/// This routines assumes that the branches that intended to be copied are
3498/// already connected. The typical case is that this tree was created using
3499/// tree->CloneTree(0).
3500///
3501/// By default copy all entries.
3502///
3503/// Returns number of bytes copied to this tree.
3504///
3505/// If 'option' contains the word 'fast' and nentries is -1, the cloning will be
3506/// done without unzipping or unstreaming the baskets (i.e., a direct copy of the
3507/// raw bytes on disk).
3508///
3509/// When 'fast' is specified, 'option' can also contains a sorting order for the
3510/// baskets in the output file.
3511///
3512/// There are currently 3 supported sorting order:
3513///
3514/// - SortBasketsByOffset (the default)
3515/// - SortBasketsByBranch
3516/// - SortBasketsByEntry
3517///
3518/// See TTree::CloneTree for a detailed explanation of the semantics of these 3 options.
3519///
3520/// If the tree or any of the underlying tree of the chain has an index, that index and any
3521/// index in the subsequent underlying TTree objects will be merged.
3522///
3523/// There are currently three 'options' to control this merging:
3524/// - NoIndex : all the TTreeIndex object are dropped.
3525/// - DropIndexOnError : if any of the underlying TTree object do no have a TTreeIndex,
3526/// they are all dropped.
3527/// - AsIsIndexOnError [default]: In case of missing TTreeIndex, the resulting TTree index has gaps.
3528/// - BuildIndexOnError : If any of the underlying TTree objects do not have a TTreeIndex,
3529/// all TTreeIndex are 'ignored' and the missing piece are rebuilt.
3531Long64_t TTree::CopyEntries(TTree* tree, Long64_t nentries /* = -1 */, Option_t* option /* = "" */, Bool_t needCopyAddresses /* = false */)
3532{
3533 if (!tree) {
3534 return 0;
3535 }
3536 // Options
3537 TString opt = option;
3538 opt.ToLower();
3539 Bool_t fastClone = opt.Contains("fast");
3540 Bool_t withIndex = !opt.Contains("noindex");
3541 EOnIndexError onIndexError;
3542 if (opt.Contains("asisindex")) {
3543 onIndexError = kKeep;
3544 } else if (opt.Contains("buildindex")) {
3545 onIndexError = kBuild;
3546 } else if (opt.Contains("dropindex")) {
3547 onIndexError = kDrop;
3548 } else {
3549 onIndexError = kBuild;
3550 }
3551 Ssiz_t cacheSizeLoc = opt.Index("cachesize=");
3552 Int_t cacheSize = -1;
3553 if (cacheSizeLoc != TString::kNPOS) {
3554 // If the parse faile, cacheSize stays at -1.
3555 Ssiz_t cacheSizeEnd = opt.Index(" ",cacheSizeLoc+10) - (cacheSizeLoc+10);
3556 TSubString cacheSizeStr( opt(cacheSizeLoc+10,cacheSizeEnd) );
3557 auto parseResult = ROOT::FromHumanReadableSize(cacheSizeStr,cacheSize);
3558 if (parseResult == ROOT::EFromHumanReadableSize::kParseFail) {
3559 Warning("CopyEntries","The cachesize option can not be parsed: %s. The default size will be used.",cacheSizeStr.String().Data());
3560 } else if (parseResult == ROOT::EFromHumanReadableSize::kOverflow) {
3561 double m;
3562 const char *munit = nullptr;
3563 ROOT::ToHumanReadableSize(std::numeric_limits<decltype(cacheSize)>::max(),false,&m,&munit);
3564
3565 Warning("CopyEntries","The cachesize option is too large: %s (%g%s max). The default size will be used.",cacheSizeStr.String().Data(),m,munit);
3566 }
3567 }
3568 if (gDebug > 0 && cacheSize != -1) Info("CopyEntries","Using Cache size: %d\n",cacheSize);
3569
3570 Long64_t nbytes = 0;
3571 Long64_t treeEntries = tree->GetEntriesFast();
3572 if (nentries < 0) {
3573 nentries = treeEntries;
3574 } else if (nentries > treeEntries) {
3575 nentries = treeEntries;
3576 }
3577
3578 if (fastClone && (nentries < 0 || nentries == tree->GetEntriesFast())) {
3579 // Quickly copy the basket without decompression and streaming.
3580 Long64_t totbytes = GetTotBytes();
3581 for (Long64_t i = 0; i < nentries; i += tree->GetTree()->GetEntries()) {
3582 if (tree->LoadTree(i) < 0) {
3583 break;
3584 }
3585 if ( withIndex ) {
3586 withIndex = R__HandleIndex( onIndexError, this, tree );
3587 }
3588 if (this->GetDirectory()) {
3589 TFile* file2 = this->GetDirectory()->GetFile();
3590 if (file2 && (file2->GetEND() > TTree::GetMaxTreeSize())) {
3591 if (this->GetDirectory() == (TDirectory*) file2) {
3592 this->ChangeFile(file2);
3593 }
3594 }
3595 }
3596 TTreeCloner cloner(tree->GetTree(), this, option, TTreeCloner::kNoWarnings);
3597 if (cloner.IsValid()) {
3598 this->SetEntries(this->GetEntries() + tree->GetTree()->GetEntries());
3599 if (cacheSize != -1) cloner.SetCacheSize(cacheSize);
3600 cloner.Exec();
3601 } else {
3602 if (i == 0) {
3603 Warning("CopyEntries","%s",cloner.GetWarning());
3604 // If the first cloning does not work, something is really wrong
3605 // (since apriori the source and target are exactly the same structure!)
3606 return -1;
3607 } else {
3608 if (cloner.NeedConversion()) {
3609 TTree *localtree = tree->GetTree();
3610 Long64_t tentries = localtree->GetEntries();
3611 if (needCopyAddresses) {
3612 // Copy MakeClass status.
3613 tree->SetMakeClass(fMakeClass);
3614 // Copy branch addresses.
3616 }
3617 for (Long64_t ii = 0; ii < tentries; ii++) {
3618 if (localtree->GetEntry(ii) <= 0) {
3619 break;
3620 }
3621 this->Fill();
3622 }
3623 if (needCopyAddresses)
3624 tree->ResetBranchAddresses();
3625 if (this->GetTreeIndex()) {
3626 this->GetTreeIndex()->Append(tree->GetTree()->GetTreeIndex(), kTRUE);
3627 }
3628 } else {
3629 Warning("CopyEntries","%s",cloner.GetWarning());
3630 if (tree->GetDirectory() && tree->GetDirectory()->GetFile()) {
3631 Warning("CopyEntries", "Skipped file %s\n", tree->GetDirectory()->GetFile()->GetName());
3632 } else {
3633 Warning("CopyEntries", "Skipped file number %d\n", tree->GetTreeNumber());
3634 }
3635 }
3636 }
3637 }
3638
3639 }
3640 if (this->GetTreeIndex()) {
3641 this->GetTreeIndex()->Append(0,kFALSE); // Force the sorting
3642 }
3643 nbytes = GetTotBytes() - totbytes;
3644 } else {
3645 if (nentries < 0) {
3646 nentries = treeEntries;
3647 } else if (nentries > treeEntries) {
3648 nentries = treeEntries;
3649 }
3650 if (needCopyAddresses) {
3651 // Copy MakeClass status.
3652 tree->SetMakeClass(fMakeClass);
3653 // Copy branch addresses.
3655 }
3656 Int_t treenumber = -1;
3657 for (Long64_t i = 0; i < nentries; i++) {
3658 if (tree->LoadTree(i) < 0) {
3659 break;
3660 }
3661 if (treenumber != tree->GetTreeNumber()) {
3662 if ( withIndex ) {
3663 withIndex = R__HandleIndex( onIndexError, this, tree );
3664 }
3665 treenumber = tree->GetTreeNumber();
3666 }
3667 if (tree->GetEntry(i) <= 0) {
3668 break;
3669 }
3670 nbytes += this->Fill();
3671 }
3672 if (needCopyAddresses)
3673 tree->ResetBranchAddresses();
3674 if (this->GetTreeIndex()) {
3675 this->GetTreeIndex()->Append(0,kFALSE); // Force the sorting
3676 }
3677 }
3678 return nbytes;
3679}
3680
3681////////////////////////////////////////////////////////////////////////////////
3682/// Copy a tree with selection.
3683///
3684/// ### Important:
3685///
3686/// The returned copied tree stays connected with the original tree
3687/// until the original tree is deleted. In particular, any changes
3688/// to the branch addresses in the original tree are also made to
3689/// the copied tree. Any changes made to the branch addresses of the
3690/// copied tree are overridden anytime the original tree changes its
3691/// branch addresses. When the original tree is deleted, all the
3692/// branch addresses of the copied tree are set to zero.
3693///
3694/// For examples of CopyTree, see the tutorials:
3695///
3696/// - copytree.C:
3697/// Example macro to copy a subset of a tree to a new tree.
3698/// The input file was generated by running the program in
3699/// $ROOTSYS/test/Event in this way:
3700/// ~~~ {.cpp}
3701/// ./Event 1000 1 1 1
3702/// ~~~
3703/// - copytree2.C
3704/// Example macro to copy a subset of a tree to a new tree.
3705/// One branch of the new tree is written to a separate file.
3706/// The input file was generated by running the program in
3707/// $ROOTSYS/test/Event in this way:
3708/// ~~~ {.cpp}
3709/// ./Event 1000 1 1 1
3710/// ~~~
3711/// - copytree3.C
3712/// Example macro to copy a subset of a tree to a new tree.
3713/// Only selected entries are copied to the new tree.
3714/// NOTE that only the active branches are copied.
3716TTree* TTree::CopyTree(const char* selection, Option_t* option /* = 0 */, Long64_t nentries /* = TTree::kMaxEntries */, Long64_t firstentry /* = 0 */)
3717{
3718 GetPlayer();
3719 if (fPlayer) {
3720 return fPlayer->CopyTree(selection, option, nentries, firstentry);
3721 }
3722 return 0;
3723}
3724
3725////////////////////////////////////////////////////////////////////////////////
3726/// Create a basket for this tree and given branch.
3729{
3730 if (!branch) {
3731 return 0;
3732 }
3733 return new TBasket(branch->GetName(), GetName(), branch);
3734}
3735
3736////////////////////////////////////////////////////////////////////////////////
3737/// Delete this tree from memory or/and disk.
3738///
3739/// - if option == "all" delete Tree object from memory AND from disk
3740/// all baskets on disk are deleted. All keys with same name
3741/// are deleted.
3742/// - if option =="" only Tree object in memory is deleted.
3744void TTree::Delete(Option_t* option /* = "" */)
3745{
3747
3748 // delete all baskets and header from file
3749 if (file && option && !strcmp(option,"all")) {
3750 if (!file->IsWritable()) {
3751 Error("Delete","File : %s is not writable, cannot delete Tree:%s", file->GetName(),GetName());
3752 return;
3753 }
3754
3755 //find key and import Tree header in memory
3756 TKey *key = fDirectory->GetKey(GetName());
3757 if (!key) return;
3758
3759 TDirectory *dirsav = gDirectory;
3760 file->cd();
3761
3762 //get list of leaves and loop on all the branches baskets
3763 TIter next(GetListOfLeaves());
3764 TLeaf *leaf;
3765 char header[16];
3766 Int_t ntot = 0;
3767 Int_t nbask = 0;
3768 Int_t nbytes,objlen,keylen;
3769 while ((leaf = (TLeaf*)next())) {
3770 TBranch *branch = leaf->GetBranch();
3771 Int_t nbaskets = branch->GetMaxBaskets();
3772 for (Int_t i=0;i<nbaskets;i++) {
3773 Long64_t pos = branch->GetBasketSeek(i);
3774 if (!pos) continue;
3775 TFile *branchFile = branch->GetFile();
3776 if (!branchFile) continue;
3777 branchFile->GetRecordHeader(header,pos,16,nbytes,objlen,keylen);
3778 if (nbytes <= 0) continue;
3779 branchFile->MakeFree(pos,pos+nbytes-1);
3780 ntot += nbytes;
3781 nbask++;
3782 }
3783 }
3784
3785 // delete Tree header key and all keys with the same name
3786 // A Tree may have been saved many times. Previous cycles are invalid.
3787 while (key) {
3788 ntot += key->GetNbytes();
3789 key->Delete();
3790 delete key;
3791 key = fDirectory->GetKey(GetName());
3792 }
3793 if (dirsav) dirsav->cd();
3794 if (gDebug) Info("TTree::Delete", "Deleting Tree: %s: %d baskets deleted. Total space freed = %d bytes\n",GetName(),nbask,ntot);
3795 }
3796
3797 if (fDirectory) {
3798 fDirectory->Remove(this);
3799 //delete the file cache if it points to this Tree
3801 fDirectory = nullptr;
3803 }
3804
3805 // Delete object from CINT symbol table so it can not be used anymore.
3806 gCling->DeleteGlobal(this);
3807
3808 // Warning: We have intentional invalidated this object while inside a member function!
3809 delete this;
3810}
3811
3812 ///////////////////////////////////////////////////////////////////////////////
3813 /// Called by TKey and TObject::Clone to automatically add us to a directory
3814 /// when we are read from a file.
3817{
3818 if (fDirectory == dir) return;
3819 if (fDirectory) {
3820 fDirectory->Remove(this);
3821 // Delete or move the file cache if it points to this Tree
3823 MoveReadCache(file,dir);
3824 }
3825 fDirectory = dir;
3826 TBranch* b = 0;
3827 TIter next(GetListOfBranches());
3828 while((b = (TBranch*) next())) {
3829 b->UpdateFile();
3830 }
3831 if (fBranchRef) {
3833 }
3834 if (fDirectory) fDirectory->Append(this);
3835}
3836
3837////////////////////////////////////////////////////////////////////////////////
3838/// Draw expression varexp for specified entries.
3839///
3840/// \return -1 in case of error or number of selected events in case of success.
3841///
3842/// This function accepts TCut objects as arguments.
3843/// Useful to use the string operator +
3844///
3845/// Example:
3846///
3847/// ~~~ {.cpp}
3848/// ntuple.Draw("x",cut1+cut2+cut3);
3849/// ~~~
3850
3852Long64_t TTree::Draw(const char* varexp, const TCut& selection, Option_t* option, Long64_t nentries, Long64_t firstentry)
3853{
3854 return TTree::Draw(varexp, selection.GetTitle(), option, nentries, firstentry);
3855}
3856
3857/////////////////////////////////////////////////////////////////////////////////////////
3858/// \brief Draw expression varexp for entries and objects that pass a (optional) selection.
3859///
3860/// \return -1 in case of error or number of selected events in case of success.
3861///
3862/// \param [in] varexp
3863/// \parblock
3864/// A string that takes one of these general forms:
3865/// - "e1" produces a 1-d histogram (TH1F) of expression "e1"
3866/// - "e1:e2" produces an unbinned 2-d scatter-plot (TGraph) of "e1"
3867/// on the y-axis versus "e2" on the x-axis
3868/// - "e1:e2:e3" produces an unbinned 3-d scatter-plot (TPolyMarker3D) of "e1"
3869/// vs "e2" vs "e3" on the z-, y-, x-axis, respectively
3870/// - "e1:e2:e3:e4" produces an unbinned 3-d scatter-plot (TPolyMarker3D) of "e1"
3871/// vs "e2" vs "e3" and "e4" mapped on the current color palette.
3872/// (to create histograms in the 2, 3, and 4 dimensional case,
3873/// see section "Saving the result of Draw to an histogram")
3874/// - "e1:e2:e3:e4:e5" with option "GL5D" produces a 5D plot using OpenGL. `gStyle->SetCanvasPreferGL(true)` is needed.
3875/// - Any number of variables no fewer than two can be used with the options "CANDLE" and "PARA"
3876/// - An arbitrary number of variables can be used with the option "GOFF"
3877///
3878/// Examples:
3879/// - "x": the simplest case, it draws a 1-Dim histogram of column x
3880/// - "sqrt(x)", "x*y/z": draw histogram with the values of the specified numerical expression across TTree events
3881/// - "y:sqrt(x)": 2-Dim histogram of y versus sqrt(x)
3882/// - "px:py:pz:2.5*E": produces a 3-d scatter-plot of px vs py ps pz
3883/// and the color number of each marker will be 2.5*E.
3884/// If the color number is negative it is set to 0.
3885/// If the color number is greater than the current number of colors
3886/// it is set to the highest color number. The default number of
3887/// colors is 50. See TStyle::SetPalette for setting a new color palette.
3888///
3889/// The expressions can use all the operations and built-in functions
3890/// supported by TFormula (see TFormula::Analyze()), including free
3891/// functions taking numerical arguments (e.g. TMath::Bessel()).
3892/// In addition, you can call member functions taking numerical
3893/// arguments. For example, these are two valid expressions:
3894/// ~~~ {.cpp}
3895/// TMath::BreitWigner(fPx,3,2)
3896/// event.GetHistogram()->GetXaxis()->GetXmax()
3897/// ~~~
3898/// \endparblock
3899/// \param [in] selection
3900/// \parblock
3901/// A string containing a selection expression.
3902/// In a selection all usual C++ mathematical and logical operators are allowed.
3903/// The value corresponding to the selection expression is used as a weight
3904/// to fill the histogram (a weight of 0 is equivalent to not filling the histogram).\n
3905/// \n
3906/// Examples:
3907/// - "x<y && sqrt(z)>3.2": returns a weight = 0 or 1
3908/// - "(x+y)*(sqrt(z)>3.2)": returns a weight = x+y if sqrt(z)>3.2, 0 otherwise\n
3909/// \n
3910/// If the selection expression returns an array, it is iterated over in sync with the
3911/// array returned by the varexp argument (as described below in "Drawing expressions using arrays and array
3912/// elements"). For example, if, for a given event, varexp evaluates to
3913/// `{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:
3914/// ~~~{.cpp}
3915/// // Muon_pt is an array: fill a histogram with the array elements > 100 in each event
3916/// tree->Draw('Muon_pt', 'Muon_pt > 100')
3917/// ~~~
3918/// \endparblock
3919/// \param [in] option
3920/// \parblock
3921/// The drawing option.
3922/// - When an histogram is produced it can be any histogram drawing option
3923/// listed in THistPainter.
3924/// - when no option is specified:
3925/// - the default histogram drawing option is used
3926/// if the expression is of the form "e1".
3927/// - if the expression is of the form "e1:e2"or "e1:e2:e3" a cloud of
3928/// unbinned 2D or 3D points is drawn respectively.
3929/// - if the expression has four fields "e1:e2:e3:e4" a cloud of unbinned 3D
3930/// points is produced with e1 vs e2 vs e3, and e4 is mapped on the current color
3931/// palette.
3932/// - If option COL is specified when varexp has three fields:
3933/// ~~~ {.cpp}
3934/// tree.Draw("e1:e2:e3","","col");
3935/// ~~~
3936/// a 2D scatter is produced with e1 vs e2, and e3 is mapped on the current
3937/// color palette. The colors for e3 are evaluated once in linear scale before
3938/// painting. Therefore changing the pad to log scale along Z as no effect
3939/// on the colors.
3940/// - if expression has more than four fields the option "PARA"or "CANDLE"
3941/// can be used.
3942/// - If option contains the string "goff", no graphics is generated.
3943/// \endparblock
3944/// \param [in] nentries The number of entries to process (default is all)
3945/// \param [in] firstentry The first entry to process (default is 0)
3946///
3947/// ### Drawing expressions using arrays and array elements
3948///
3949/// Let assumes, a leaf fMatrix, on the branch fEvent, which is a 3 by 3 array,
3950/// or a TClonesArray.
3951/// In a TTree::Draw expression you can now access fMatrix using the following
3952/// syntaxes:
3953///
3954/// | String passed | What is used for each entry of the tree
3955/// |-----------------|--------------------------------------------------------|
3956/// | `fMatrix` | the 9 elements of fMatrix |
3957/// | `fMatrix[][]` | the 9 elements of fMatrix |
3958/// | `fMatrix[2][2]` | only the elements fMatrix[2][2] |
3959/// | `fMatrix[1]` | the 3 elements fMatrix[1][0], fMatrix[1][1] and fMatrix[1][2] |
3960/// | `fMatrix[1][]` | the 3 elements fMatrix[1][0], fMatrix[1][1] and fMatrix[1][2] |
3961/// | `fMatrix[][0]` | the 3 elements fMatrix[0][0], fMatrix[1][0] and fMatrix[2][0] |
3962///
3963/// "fEvent.fMatrix...." same as "fMatrix..." (unless there is more than one leaf named fMatrix!).
3964///
3965/// In summary, if a specific index is not specified for a dimension, TTree::Draw
3966/// will loop through all the indices along this dimension. Leaving off the
3967/// last (right most) dimension of specifying then with the two characters '[]'
3968/// is equivalent. For variable size arrays (and TClonesArray) the range
3969/// of the first dimension is recalculated for each entry of the tree.
3970/// You can also specify the index as an expression of any other variables from the
3971/// tree.
3972///
3973/// TTree::Draw also now properly handling operations involving 2 or more arrays.
3974///
3975/// Let assume a second matrix fResults[5][2], here are a sample of some
3976/// of the possible combinations, the number of elements they produce and
3977/// the loop used:
3978///
3979/// | expression | element(s) | Loop |
3980/// |----------------------------------|------------|--------------------------|
3981/// | `fMatrix[2][1] - fResults[5][2]` | one | no loop |
3982/// | `fMatrix[2][] - fResults[5][2]` | three | on 2nd dim fMatrix |
3983/// | `fMatrix[2][] - fResults[5][]` | two | on both 2nd dimensions |
3984/// | `fMatrix[][2] - fResults[][1]` | three | on both 1st dimensions |
3985/// | `fMatrix[][2] - fResults[][]` | six | on both 1st and 2nd dimensions of fResults |
3986/// | `fMatrix[][2] - fResults[3][]` | two | on 1st dim of fMatrix and 2nd of fResults (at the same time) |
3987/// | `fMatrix[][] - fResults[][]` | six | on 1st dim then on 2nd dim |
3988/// | `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.|
3989///
3990///
3991/// In summary, TTree::Draw loops through all unspecified dimensions. To
3992/// figure out the range of each loop, we match each unspecified dimension
3993/// from left to right (ignoring ALL dimensions for which an index has been
3994/// specified), in the equivalent loop matched dimensions use the same index
3995/// and are restricted to the smallest range (of only the matched dimensions).
3996/// When involving variable arrays, the range can of course be different
3997/// for each entry of the tree.
3998///
3999/// So the loop equivalent to "fMatrix[][2] - fResults[3][]" is:
4000/// ~~~ {.cpp}
4001/// for (Int_t i0; i < min(3,2); i++) {
4002/// use the value of (fMatrix[i0][2] - fMatrix[3][i0])
4003/// }
4004/// ~~~
4005/// So the loop equivalent to "fMatrix[][2] - fResults[][]" is:
4006/// ~~~ {.cpp}
4007/// for (Int_t i0; i < min(3,5); i++) {
4008/// for (Int_t i1; i1 < 2; i1++) {
4009/// use the value of (fMatrix[i0][2] - fMatrix[i0][i1])
4010/// }
4011/// }
4012/// ~~~
4013/// So the loop equivalent to "fMatrix[][] - fResults[][]" is:
4014/// ~~~ {.cpp}
4015/// for (Int_t i0; i < min(3,5); i++) {
4016/// for (Int_t i1; i1 < min(3,2); i1++) {
4017/// use the value of (fMatrix[i0][i1] - fMatrix[i0][i1])
4018/// }
4019/// }
4020/// ~~~
4021/// So the loop equivalent to "fMatrix[][fResults[][]]" is:
4022/// ~~~ {.cpp}
4023/// for (Int_t i0; i0 < 3; i0++) {
4024/// for (Int_t j2; j2 < 5; j2++) {
4025/// for (Int_t j3; j3 < 2; j3++) {
4026/// i1 = fResults[j2][j3];
4027/// use the value of fMatrix[i0][i1]
4028/// }
4029/// }
4030/// ~~~
4031/// ### Retrieving the result of Draw
4032///
4033/// By default a temporary histogram called `htemp` is created. It will be:
4034///
4035/// - A TH1F* in case of a mono-dimensional distribution: `Draw("e1")`,
4036/// - A TH2F* in case of a bi-dimensional distribution: `Draw("e1:e2")`,
4037/// - A TH3F* in case of a three-dimensional distribution: `Draw("e1:e2:e3")`.
4038///
4039/// In the one dimensional case the `htemp` is filled and drawn whatever the drawing
4040/// option is.
4041///
4042/// In the two and three dimensional cases, with the default drawing option (`""`),
4043/// a cloud of points is drawn and the histogram `htemp` is not filled. For all the other
4044/// drawing options `htemp` will be filled.
4045///
4046/// In all cases `htemp` can be retrieved by calling:
4047///
4048/// ~~~ {.cpp}
4049/// auto htemp = (TH1F*)gPad->GetPrimitive("htemp"); // 1D
4050/// auto htemp = (TH2F*)gPad->GetPrimitive("htemp"); // 2D
4051/// auto htemp = (TH3F*)gPad->GetPrimitive("htemp"); // 3D
4052/// ~~~
4053///
4054/// In the two dimensional case (`Draw("e1;e2")`), with the default drawing option, the
4055/// data is filled into a TGraph named `Graph`. This TGraph can be retrieved by
4056/// calling
4057///
4058/// ~~~ {.cpp}
4059/// auto graph = (TGraph*)gPad->GetPrimitive("Graph");
4060/// ~~~
4061///
4062/// For the three and four dimensional cases, with the default drawing option, an unnamed
4063/// TPolyMarker3D is produced, and therefore cannot be retrieved.
4064///
4065/// In all cases `htemp` can be used to access the axes. For instance in the 2D case:
4066///
4067/// ~~~ {.cpp}
4068/// auto htemp = (TH2F*)gPad->GetPrimitive("htemp");
4069/// auto xaxis = htemp->GetXaxis();
4070/// ~~~
4071///
4072/// When the option `"A"` is used (with TGraph painting option) to draw a 2D
4073/// distribution:
4074/// ~~~ {.cpp}
4075/// tree.Draw("e1:e2","","A*");
4076/// ~~~
4077/// a scatter plot is produced (with stars in that case) but the axis creation is
4078/// delegated to TGraph and `htemp` is not created.
4079///
4080/// ### Saving the result of Draw to a histogram
4081///
4082/// If `varexp` contains `>>hnew` (following the variable(s) name(s)),
4083/// the new histogram called `hnew` is created and it is kept in the current
4084/// directory (and also the current pad). This works for all dimensions.
4085///
4086/// Example:
4087/// ~~~ {.cpp}
4088/// tree.Draw("sqrt(x)>>hsqrt","y>0")
4089/// ~~~
4090/// will draw `sqrt(x)` and save the histogram as "hsqrt" in the current
4091/// directory. To retrieve it do:
4092/// ~~~ {.cpp}
4093/// TH1F *hsqrt = (TH1F*)gDirectory->Get("hsqrt");
4094/// ~~~
4095/// The binning information is taken from the environment variables
4096/// ~~~ {.cpp}
4097/// Hist.Binning.?D.?
4098/// ~~~
4099/// In addition, the name of the histogram can be followed by up to 9
4100/// numbers between '(' and ')', where the numbers describe the
4101/// following:
4102///
4103/// - 1 - bins in x-direction
4104/// - 2 - lower limit in x-direction
4105/// - 3 - upper limit in x-direction
4106/// - 4-6 same for y-direction
4107/// - 7-9 same for z-direction
4108///
4109/// When a new binning is used the new value will become the default.
4110/// Values can be skipped.
4111///
4112/// Example:
4113/// ~~~ {.cpp}
4114/// tree.Draw("sqrt(x)>>hsqrt(500,10,20)")
4115/// // plot sqrt(x) between 10 and 20 using 500 bins
4116/// tree.Draw("sqrt(x):sin(y)>>hsqrt(100,10,60,50,.1,.5)")
4117/// // plot sqrt(x) against sin(y)
4118/// // 100 bins in x-direction; lower limit on x-axis is 10; upper limit is 60
4119/// // 50 bins in y-direction; lower limit on y-axis is .1; upper limit is .5
4120/// ~~~
4121/// By default, the specified histogram is reset.
4122/// To continue to append data to an existing histogram, use "+" in front
4123/// of the histogram name.
4124///
4125/// A '+' in front of the histogram name is ignored, when the name is followed by
4126/// binning information as described in the previous paragraph.
4127/// ~~~ {.cpp}
4128/// tree.Draw("sqrt(x)>>+hsqrt","y>0")
4129/// ~~~
4130/// will not reset `hsqrt`, but will continue filling. This works for 1-D, 2-D
4131/// and 3-D histograms.
4132///
4133/// ### Accessing collection objects
4134///
4135/// TTree::Draw default's handling of collections is to assume that any
4136/// request on a collection pertain to it content. For example, if fTracks
4137/// is a collection of Track objects, the following:
4138/// ~~~ {.cpp}
4139/// tree->Draw("event.fTracks.fPx");
4140/// ~~~
4141/// will plot the value of fPx for each Track objects inside the collection.
4142/// Also
4143/// ~~~ {.cpp}
4144/// tree->Draw("event.fTracks.size()");
4145/// ~~~
4146/// would plot the result of the member function Track::size() for each
4147/// Track object inside the collection.
4148/// To access information about the collection itself, TTree::Draw support
4149/// the '@' notation. If a variable which points to a collection is prefixed
4150/// or postfixed with '@', the next part of the expression will pertain to
4151/// the collection object. For example:
4152/// ~~~ {.cpp}
4153/// tree->Draw("event.@fTracks.size()");
4154/// ~~~
4155/// will plot the size of the collection referred to by `fTracks` (i.e the number
4156/// of Track objects).
4157///
4158/// ### Drawing 'objects'
4159///
4160/// When a class has a member function named AsDouble or AsString, requesting
4161/// to directly draw the object will imply a call to one of the 2 functions.
4162/// If both AsDouble and AsString are present, AsDouble will be used.
4163/// AsString can return either a char*, a std::string or a TString.s
4164/// For example, the following
4165/// ~~~ {.cpp}
4166/// tree->Draw("event.myTTimeStamp");
4167/// ~~~
4168/// will draw the same histogram as
4169/// ~~~ {.cpp}
4170/// tree->Draw("event.myTTimeStamp.AsDouble()");
4171/// ~~~
4172/// In addition, when the object is a type TString or std::string, TTree::Draw
4173/// will call respectively `TString::Data` and `std::string::c_str()`
4174///
4175/// If the object is a TBits, the histogram will contain the index of the bit
4176/// that are turned on.
4177///
4178/// ### Retrieving information about the tree itself.
4179///
4180/// You can refer to the tree (or chain) containing the data by using the
4181/// string 'This'.
4182/// You can then could any TTree methods. For example:
4183/// ~~~ {.cpp}
4184/// tree->Draw("This->GetReadEntry()");
4185/// ~~~
4186/// will display the local entry numbers be read.
4187/// ~~~ {.cpp}
4188/// tree->Draw("This->GetUserInfo()->At(0)->GetName()");
4189/// ~~~
4190/// will display the name of the first 'user info' object.
4191///
4192/// ### Special functions and variables
4193///
4194/// `Entry$`: A TTree::Draw formula can use the special variable `Entry$`
4195/// to access the entry number being read. For example to draw every
4196/// other entry use:
4197/// ~~~ {.cpp}
4198/// tree.Draw("myvar","Entry$%2==0");
4199/// ~~~
4200/// - `Entry$` : return the current entry number (`== TTree::GetReadEntry()`)
4201/// - `LocalEntry$` : return the current entry number in the current tree of a
4202/// chain (`== GetTree()->GetReadEntry()`)
4203/// - `Entries$` : return the total number of entries (== TTree::GetEntries())
4204/// - `LocalEntries$` : return the total number of entries in the current tree
4205/// of a chain (== GetTree()->TTree::GetEntries())
4206/// - `Length$` : return the total number of element of this formula for this
4207/// entry (`==TTreeFormula::GetNdata()`)
4208/// - `Iteration$` : return the current iteration over this formula for this
4209/// entry (i.e. varies from 0 to `Length$`).
4210/// - `Length$(formula )` : return the total number of element of the formula
4211/// given as a parameter.
4212/// - `Sum$(formula )` : return the sum of the value of the elements of the
4213/// formula given as a parameter. For example the mean for all the elements in
4214/// one entry can be calculated with: `Sum$(formula )/Length$(formula )`
4215/// - `Min$(formula )` : return the minimum (within one TTree entry) of the value of the
4216/// elements of the formula given as a parameter.
4217/// - `Max$(formula )` : return the maximum (within one TTree entry) of the value of the
4218/// elements of the formula given as a parameter.
4219/// - `MinIf$(formula,condition)`
4220/// - `MaxIf$(formula,condition)` : return the minimum (maximum) (within one TTree entry)
4221/// of the value of the elements of the formula given as a parameter
4222/// if they match the condition. If no element matches the condition,
4223/// the result is zero. To avoid the resulting peak at zero, use the
4224/// pattern:
4225/// ~~~ {.cpp}
4226/// tree->Draw("MinIf$(formula,condition)","condition");
4227/// ~~~
4228/// which will avoid calculation `MinIf$` for the entries that have no match
4229/// for the condition.
4230/// - `Alt$(primary,alternate)` : return the value of "primary" if it is available
4231/// for the current iteration otherwise return the value of "alternate".
4232/// For example, with arr1[3] and arr2[2]
4233/// ~~~ {.cpp}
4234/// tree->Draw("arr1+Alt$(arr2,0)");
4235/// ~~~
4236/// will draw arr1[0]+arr2[0] ; arr1[1]+arr2[1] and arr1[2]+0
4237/// Or with a variable size array arr3
4238/// ~~~ {.cpp}
4239/// tree->Draw("Alt$(arr3[0],0)+Alt$(arr3[1],0)+Alt$(arr3[2],0)");
4240/// ~~~
4241/// will draw the sum arr3 for the index 0 to min(2,actual_size_of_arr3-1)
4242/// As a comparison
4243/// ~~~ {.cpp}
4244/// tree->Draw("arr3[0]+arr3[1]+arr3[2]");
4245/// ~~~
4246/// will draw the sum arr3 for the index 0 to 2 only if the
4247/// actual_size_of_arr3 is greater or equal to 3.
4248/// Note that the array in 'primary' is flattened/linearized thus using
4249/// `Alt$` with multi-dimensional arrays of different dimensions in unlikely
4250/// to yield the expected results. To visualize a bit more what elements
4251/// would be matched by TTree::Draw, TTree::Scan can be used:
4252/// ~~~ {.cpp}
4253/// tree->Scan("arr1:Alt$(arr2,0)");
4254/// ~~~
4255/// will print on one line the value of arr1 and (arr2,0) that will be
4256/// matched by
4257/// ~~~ {.cpp}
4258/// tree->Draw("arr1-Alt$(arr2,0)");
4259/// ~~~
4260/// The ternary operator is not directly supported in TTree::Draw however, to plot the
4261/// equivalent of `var2<20 ? -99 : var1`, you can use:
4262/// ~~~ {.cpp}
4263/// tree->Draw("(var2<20)*99+(var2>=20)*var1","");
4264/// ~~~
4265///
4266/// ### Drawing a user function accessing the TTree data directly
4267///
4268/// If the formula contains a file name, TTree::MakeProxy will be used
4269/// to load and execute this file. In particular it will draw the
4270/// result of a function with the same name as the file. The function
4271/// will be executed in a context where the name of the branches can
4272/// be used as a C++ variable.
4273///
4274/// For example draw px using the file hsimple.root (generated by the
4275/// hsimple.C tutorial), we need a file named hsimple.cxx:
4276/// ~~~ {.cpp}
4277/// double hsimple() {
4278/// return px;
4279/// }
4280/// ~~~
4281/// MakeProxy can then be used indirectly via the TTree::Draw interface
4282/// as follow:
4283/// ~~~ {.cpp}
4284/// new TFile("hsimple.root")
4285/// ntuple->Draw("hsimple.cxx");
4286/// ~~~
4287/// A more complete example is available in the tutorials directory:
4288/// `h1analysisProxy.cxx`, `h1analysProxy.h` and `h1analysisProxyCut.C`
4289/// which reimplement the selector found in `h1analysis.C`
4290///
4291/// The main features of this facility are:
4292///
4293/// * on-demand loading of branches
4294/// * ability to use the 'branchname' as if it was a data member
4295/// * protection against array out-of-bound
4296/// * ability to use the branch data as object (when the user code is available)
4297///
4298/// See TTree::MakeProxy for more details.
4299///
4300/// ### Making a Profile histogram
4301///
4302/// In case of a 2-Dim expression, one can generate a TProfile histogram
4303/// instead of a TH2F histogram by specifying option=prof or option=profs
4304/// or option=profi or option=profg ; the trailing letter select the way
4305/// the bin error are computed, See TProfile2D::SetErrorOption for
4306/// details on the differences.
4307/// The option=prof is automatically selected in case of y:x>>pf
4308/// where pf is an existing TProfile histogram.
4309///
4310/// ### Making a 2D Profile histogram
4311///
4312/// In case of a 3-Dim expression, one can generate a TProfile2D histogram
4313/// instead of a TH3F histogram by specifying option=prof or option=profs.
4314/// or option=profi or option=profg ; the trailing letter select the way
4315/// the bin error are computed, See TProfile2D::SetErrorOption for
4316/// details on the differences.
4317/// The option=prof is automatically selected in case of z:y:x>>pf
4318/// where pf is an existing TProfile2D histogram.
4319///
4320/// ### Making a 5D plot using GL
4321///
4322/// If option GL5D is specified together with 5 variables, a 5D plot is drawn
4323/// using OpenGL. See $ROOTSYS/tutorials/tree/staff.C as example.
4324///
4325/// ### Making a parallel coordinates plot
4326///
4327/// In case of a 2-Dim or more expression with the option=para, one can generate
4328/// a parallel coordinates plot. With that option, the number of dimensions is
4329/// arbitrary. Giving more than 4 variables without the option=para or
4330/// option=candle or option=goff will produce an error.
4331///
4332/// ### Making a candle sticks chart
4333///
4334/// In case of a 2-Dim or more expression with the option=candle, one can generate
4335/// a candle sticks chart. With that option, the number of dimensions is
4336/// arbitrary. Giving more than 4 variables without the option=para or
4337/// option=candle or option=goff will produce an error.
4338///
4339/// ### Normalizing the output histogram to 1
4340///
4341/// When option contains "norm" the output histogram is normalized to 1.
4342///
4343/// ### Saving the result of Draw to a TEventList, a TEntryList or a TEntryListArray
4344///
4345/// TTree::Draw can be used to fill a TEventList object (list of entry numbers)
4346/// instead of histogramming one variable.
4347/// If varexp0 has the form >>elist , a TEventList object named "elist"
4348/// is created in the current directory. elist will contain the list
4349/// of entry numbers satisfying the current selection.
4350/// If option "entrylist" is used, a TEntryList object is created
4351/// If the selection contains arrays, vectors or any container class and option
4352/// "entrylistarray" is used, a TEntryListArray object is created
4353/// containing also the subentries satisfying the selection, i.e. the indices of
4354/// the branches which hold containers classes.
4355/// Example:
4356/// ~~~ {.cpp}
4357/// tree.Draw(">>yplus","y>0")
4358/// ~~~
4359/// will create a TEventList object named "yplus" in the current directory.
4360/// In an interactive session, one can type (after TTree::Draw)
4361/// ~~~ {.cpp}
4362/// yplus.Print("all")
4363/// ~~~
4364/// to print the list of entry numbers in the list.
4365/// ~~~ {.cpp}
4366/// tree.Draw(">>yplus", "y>0", "entrylist")
4367/// ~~~
4368/// will create a TEntryList object names "yplus" in the current directory
4369/// ~~~ {.cpp}
4370/// tree.Draw(">>yplus", "y>0", "entrylistarray")
4371/// ~~~
4372/// will create a TEntryListArray object names "yplus" in the current directory
4373///
4374/// By default, the specified entry list is reset.
4375/// To continue to append data to an existing list, use "+" in front
4376/// of the list name;
4377/// ~~~ {.cpp}
4378/// tree.Draw(">>+yplus","y>0")
4379/// ~~~
4380/// will not reset yplus, but will enter the selected entries at the end
4381/// of the existing list.
4382///
4383/// ### Using a TEventList, TEntryList or TEntryListArray as Input
4384///
4385/// Once a TEventList or a TEntryList object has been generated, it can be used as input
4386/// for TTree::Draw. Use TTree::SetEventList or TTree::SetEntryList to set the
4387/// current event list
4388///
4389/// Example 1:
4390/// ~~~ {.cpp}
4391/// TEventList *elist = (TEventList*)gDirectory->Get("yplus");
4392/// tree->SetEventList(elist);
4393/// tree->Draw("py");
4394/// ~~~
4395/// Example 2:
4396/// ~~~ {.cpp}
4397/// TEntryList *elist = (TEntryList*)gDirectory->Get("yplus");
4398/// tree->SetEntryList(elist);
4399/// tree->Draw("py");
4400/// ~~~
4401/// If a TEventList object is used as input, a new TEntryList object is created
4402/// inside the SetEventList function. In case of a TChain, all tree headers are loaded
4403/// for this transformation. This new object is owned by the chain and is deleted
4404/// with it, unless the user extracts it by calling GetEntryList() function.
4405/// See also comments to SetEventList() function of TTree and TChain.
4406///
4407/// If arrays are used in the selection criteria and TEntryListArray is not used,
4408/// all the entries that have at least one element of the array that satisfy the selection
4409/// are entered in the list.
4410///
4411/// Example:
4412/// ~~~ {.cpp}
4413/// tree.Draw(">>pyplus","fTracks.fPy>0");
4414/// tree->SetEventList(pyplus);
4415/// tree->Draw("fTracks.fPy");
4416/// ~~~
4417/// will draw the fPy of ALL tracks in event with at least one track with
4418/// a positive fPy.
4419///
4420/// To select only the elements that did match the original selection
4421/// use TEventList::SetReapplyCut or TEntryList::SetReapplyCut.
4422///
4423/// Example:
4424/// ~~~ {.cpp}
4425/// tree.Draw(">>pyplus","fTracks.fPy>0");
4426/// pyplus->SetReapplyCut(kTRUE);
4427/// tree->SetEventList(pyplus);
4428/// tree->Draw("fTracks.fPy");
4429/// ~~~
4430/// will draw the fPy of only the tracks that have a positive fPy.
4431///
4432/// To draw only the elements that match a selection in case of arrays,
4433/// you can also use TEntryListArray (faster in case of a more general selection).
4434///
4435/// Example:
4436/// ~~~ {.cpp}
4437/// tree.Draw(">>pyplus","fTracks.fPy>0", "entrylistarray");
4438/// tree->SetEntryList(pyplus);
4439/// tree->Draw("fTracks.fPy");
4440/// ~~~
4441/// will draw the fPy of only the tracks that have a positive fPy,
4442/// but without redoing the selection.
4443///
4444/// Note: Use tree->SetEventList(0) if you do not want use the list as input.
4445///
4446/// ### How to obtain more info from TTree::Draw
4447///
4448/// Once TTree::Draw has been called, it is possible to access useful
4449/// information still stored in the TTree object via the following functions:
4450///
4451/// - GetSelectedRows() // return the number of values accepted by the selection expression. In case where no selection was specified, returns the number of values processed.
4452/// - GetV1() // returns a pointer to the double array of V1
4453/// - GetV2() // returns a pointer to the double array of V2
4454/// - GetV3() // returns a pointer to the double array of V3
4455/// - GetV4() // returns a pointer to the double array of V4
4456/// - GetW() // returns a pointer to the double array of Weights where weight equal the result of the selection expression.
4457///
4458/// where V1,V2,V3 correspond to the expressions in
4459/// ~~~ {.cpp}
4460/// TTree::Draw("V1:V2:V3:V4",selection);
4461/// ~~~
4462/// If the expression has more than 4 component use GetVal(index)
4463///
4464/// Example:
4465/// ~~~ {.cpp}
4466/// Root > ntuple->Draw("py:px","pz>4");
4467/// Root > TGraph *gr = new TGraph(ntuple->GetSelectedRows(),
4468/// ntuple->GetV2(), ntuple->GetV1());
4469/// Root > gr->Draw("ap"); //draw graph in current pad
4470/// ~~~
4471///
4472/// A more complete complete tutorial (treegetval.C) shows how to use the
4473/// GetVal() method.
4474///
4475/// creates a TGraph object with a number of points corresponding to the
4476/// number of entries selected by the expression "pz>4", the x points of the graph
4477/// being the px values of the Tree and the y points the py values.
4478///
4479/// Important note: By default TTree::Draw creates the arrays obtained
4480/// with GetW, GetV1, GetV2, GetV3, GetV4, GetVal with a length corresponding
4481/// to the parameter fEstimate. The content will be the last `GetSelectedRows() % GetEstimate()`
4482/// values calculated.
4483/// By default fEstimate=1000000 and can be modified
4484/// via TTree::SetEstimate. To keep in memory all the results (in case
4485/// where there is only one result per entry), use
4486/// ~~~ {.cpp}
4487/// tree->SetEstimate(tree->GetEntries()+1); // same as tree->SetEstimate(-1);
4488/// ~~~
4489/// You must call SetEstimate if the expected number of selected rows
4490/// you need to look at is greater than 1000000.
4491///
4492/// You can use the option "goff" to turn off the graphics output
4493/// of TTree::Draw in the above example.
4494///
4495/// ### Automatic interface to TTree::Draw via the TTreeViewer
4496///
4497/// A complete graphical interface to this function is implemented
4498/// in the class TTreeViewer.
4499/// To start the TTreeViewer, three possibilities:
4500/// - select TTree context menu item "StartViewer"
4501/// - type the command "TTreeViewer TV(treeName)"
4502/// - execute statement "tree->StartViewer();"
4504Long64_t TTree::Draw(const char* varexp, const char* selection, Option_t* option, Long64_t nentries, Long64_t firstentry)
4505{
4506 GetPlayer();
4507 if (fPlayer)
4508 return fPlayer->DrawSelect(varexp,selection,option,nentries,firstentry);
4509 return -1;
4510}
4511
4512////////////////////////////////////////////////////////////////////////////////
4513/// Remove some baskets from memory.
4515void TTree::DropBaskets()
4516{
4517 TBranch* branch = 0;
4519 for (Int_t i = 0; i < nb; ++i) {
4520 branch = (TBranch*) fBranches.UncheckedAt(i);
4521 branch->DropBaskets("all");
4522 }
4523}
4524
4525////////////////////////////////////////////////////////////////////////////////
4526/// Drop branch buffers to accommodate nbytes below MaxVirtualsize.
4529{
4530 // Be careful not to remove current read/write buffers.
4531 Int_t nleaves = fLeaves.GetEntriesFast();
4532 for (Int_t i = 0; i < nleaves; ++i) {
4533 TLeaf* leaf = (TLeaf*) fLeaves.UncheckedAt(i);
4534 TBranch* branch = (TBranch*) leaf->GetBranch();
4535 Int_t nbaskets = branch->GetListOfBaskets()->GetEntries();
4536 for (Int_t j = 0; j < nbaskets - 1; ++j) {
4537 if ((j == branch->GetReadBasket()) || (j == branch->GetWriteBasket())) {
4538 continue;
4539 }
4540 TBasket* basket = (TBasket*)branch->GetListOfBaskets()->UncheckedAt(j);
4541 if (basket) {
4542 basket->DropBuffers();
4544 return;
4545 }
4546 }
4547 }
4548 }
4549}
4550
4551////////////////////////////////////////////////////////////////////////////////
4552/// Fill all branches.
4553///
4554/// This function loops on all the branches of this tree. For
4555/// each branch, it copies to the branch buffer (basket) the current
4556/// values of the leaves data types. If a leaf is a simple data type,
4557/// a simple conversion to a machine independent format has to be done.
4558///
4559/// This machine independent version of the data is copied into a
4560/// basket (each branch has its own basket). When a basket is full
4561/// (32k worth of data by default), it is then optionally compressed
4562/// and written to disk (this operation is also called committing or
4563/// 'flushing' the basket). The committed baskets are then
4564/// immediately removed from memory.
4565///
4566/// The function returns the number of bytes committed to the
4567/// individual branches.
4568///
4569/// If a write error occurs, the number of bytes returned is -1.
4570///
4571/// If no data are written, because, e.g., the branch is disabled,
4572/// the number of bytes returned is 0.
4573///
4574/// __The baskets are flushed and the Tree header saved at regular intervals__
4575///
4576/// At regular intervals, when the amount of data written so far is
4577/// greater than fAutoFlush (see SetAutoFlush) all the baskets are flushed to disk.
4578/// This makes future reading faster as it guarantees that baskets belonging to nearby
4579/// entries will be on the same disk region.
4580/// When the first call to flush the baskets happen, we also take this opportunity
4581/// to optimize the baskets buffers.
4582/// We also check if the amount of data written is greater than fAutoSave (see SetAutoSave).
4583/// In this case we also write the Tree header. This makes the Tree recoverable up to this point
4584/// in case the program writing the Tree crashes.
4585/// The decisions to FlushBaskets and Auto Save can be made based either on the number
4586/// of bytes written (fAutoFlush and fAutoSave negative) or on the number of entries
4587/// written (fAutoFlush and fAutoSave positive).
4588/// Note that the user can decide to call FlushBaskets and AutoSave in her event loop
4589/// base on the number of events written instead of the number of bytes written.
4590///
4591/// \note Calling `TTree::FlushBaskets` too often increases the IO time.
4592///
4593/// \note Calling `TTree::AutoSave` too often increases the IO time and also the
4594/// file size.
4595///
4596/// \note This method calls `TTree::ChangeFile` when the tree reaches a size
4597/// greater than `TTree::fgMaxTreeSize`. This doesn't happen if the tree is
4598/// attached to a `TMemFile` or derivate.
4601{
4602 Int_t nbytes = 0;
4603 Int_t nwrite = 0;
4604 Int_t nerror = 0;
4605 Int_t nbranches = fBranches.GetEntriesFast();
4606
4607 // Case of one single super branch. Automatically update
4608 // all the branch addresses if a new object was created.
4609 if (nbranches == 1)
4610 ((TBranch *)fBranches.UncheckedAt(0))->UpdateAddress();
4611
4612 if (fBranchRef)
4613 fBranchRef->Clear();
4614
4615#ifdef R__USE_IMT
4616 const auto useIMT = ROOT::IsImplicitMTEnabled() && fIMTEnabled;
4618 if (useIMT) {
4619 fIMTFlush = true;
4620 fIMTZipBytes.store(0);
4621 fIMTTotBytes.store(0);
4622 }
4623#endif
4624
4625 for (Int_t i = 0; i < nbranches; ++i) {
4626 // Loop over all branches, filling and accumulating bytes written and error counts.
4627 TBranch *branch = (TBranch *)fBranches.UncheckedAt(i);
4628
4629 if (branch->TestBit(kDoNotProcess))
4630 continue;
4631
4632#ifndef R__USE_IMT
4633 nwrite = branch->FillImpl(nullptr);
4634#else
4635 nwrite = branch->FillImpl(useIMT ? &imtHelper : nullptr);
4636#endif
4637 if (nwrite < 0) {
4638 if (nerror < 2) {
4639 Error("Fill", "Failed filling branch:%s.%s, nbytes=%d, entry=%lld\n"
4640 " This error is symptomatic of a Tree created as a memory-resident Tree\n"
4641 " Instead of doing:\n"
4642 " TTree *T = new TTree(...)\n"
4643 " TFile *f = new TFile(...)\n"
4644 " you should do:\n"
4645 " TFile *f = new TFile(...)\n"
4646 " TTree *T = new TTree(...)\n\n",
4647 GetName(), branch->GetName(), nwrite, fEntries + 1);
4648 } else {
4649 Error("Fill", "Failed filling branch:%s.%s, nbytes=%d, entry=%lld", GetName(), branch->GetName(), nwrite,
4650 fEntries + 1);
4651 }
4652 ++nerror;
4653 } else {
4654 nbytes += nwrite;
4655 }
4656 }
4657
4658#ifdef R__USE_IMT
4659 if (fIMTFlush) {
4660 imtHelper.Wait();
4661 fIMTFlush = false;
4662 const_cast<TTree *>(this)->AddTotBytes(fIMTTotBytes);
4663 const_cast<TTree *>(this)->AddZipBytes(fIMTZipBytes);
4664 nbytes += imtHelper.GetNbytes();
4665 nerror += imtHelper.GetNerrors();
4666 }
4667#endif
4668
4669 if (fBranchRef)
4670 fBranchRef->Fill();
4671
4672 ++fEntries;
4673
4674 if (fEntries > fMaxEntries)
4675 KeepCircular();
4676
4677 if (gDebug > 0)
4678 Info("TTree::Fill", " - A: %d %lld %lld %lld %lld %lld %lld \n", nbytes, fEntries, fAutoFlush, fAutoSave,
4680
4681 bool autoFlush = false;
4682 bool autoSave = false;
4683
4684 if (fAutoFlush != 0 || fAutoSave != 0) {
4685 // Is it time to flush or autosave baskets?
4686 if (fFlushedBytes == 0) {
4687 // If fFlushedBytes == 0, it means we never flushed or saved, so
4688 // we need to check if it's time to do it and recompute the values
4689 // of fAutoFlush and fAutoSave in terms of the number of entries.
4690 // Decision can be based initially either on the number of bytes
4691 // or the number of entries written.
4692 Long64_t zipBytes = GetZipBytes();
4693
4694 if (fAutoFlush)
4695 autoFlush = fAutoFlush < 0 ? (zipBytes > -fAutoFlush) : fEntries % fAutoFlush == 0;
4696
4697 if (fAutoSave)
4698 autoSave = fAutoSave < 0 ? (zipBytes > -fAutoSave) : fEntries % fAutoSave == 0;
4699
4700 if (autoFlush || autoSave) {
4701 // First call FlushBasket to make sure that fTotBytes is up to date.
4703 autoFlush = false; // avoid auto flushing again later
4704
4705 // When we are in one-basket-per-cluster mode, there is no need to optimize basket:
4706 // they will automatically grow to the size needed for an event cluster (with the basket
4707 // shrinking preventing them from growing too much larger than the actually-used space).
4709 OptimizeBaskets(GetTotBytes(), 1, "");
4710 if (gDebug > 0)
4711 Info("TTree::Fill", "OptimizeBaskets called at entry %lld, fZipBytes=%lld, fFlushedBytes=%lld\n",
4713 }
4715 fAutoFlush = fEntries; // Use test on entries rather than bytes
4716
4717 // subsequently in run
4718 if (fAutoSave < 0) {
4719 // Set fAutoSave to the largest integer multiple of
4720 // fAutoFlush events such that fAutoSave*fFlushedBytes
4721 // < (minus the input value of fAutoSave)
4722 Long64_t totBytes = GetTotBytes();
4723 if (zipBytes != 0) {
4724 fAutoSave = TMath::Max(fAutoFlush, fEntries * ((-fAutoSave / zipBytes) / fEntries));
4725 } else if (totBytes != 0) {
4726 fAutoSave = TMath::Max(fAutoFlush, fEntries * ((-fAutoSave / totBytes) / fEntries));
4727 } else {
4729 TTree::Class()->WriteBuffer(b, (TTree *)this);
4730 Long64_t total = b.Length();
4732 }
4733 } else if (fAutoSave > 0) {
4735 }
4736
4737 if (fAutoSave != 0 && fEntries >= fAutoSave)
4738 autoSave = true;
4739
4740 if (gDebug > 0)
4741 Info("TTree::Fill", "First AutoFlush. fAutoFlush = %lld, fAutoSave = %lld\n", fAutoFlush, fAutoSave);
4742 }
4743 } else {
4744 // Check if we need to auto flush
4745 if (fAutoFlush) {
4746 if (fNClusterRange == 0)
4747 autoFlush = fEntries > 1 && fEntries % fAutoFlush == 0;
4748 else
4749 autoFlush = (fEntries - (fClusterRangeEnd[fNClusterRange - 1] + 1)) % fAutoFlush == 0;
4750 }
4751 // Check if we need to auto save
4752 if (fAutoSave)
4753 autoSave = fEntries % fAutoSave == 0;
4754 }
4755 }
4756
4757 if (autoFlush) {
4759 if (gDebug > 0)
4760 Info("TTree::Fill", "FlushBaskets() called at entry %lld, fZipBytes=%lld, fFlushedBytes=%lld\n", fEntries,
4763 }
4764
4765 if (autoSave) {
4766 AutoSave(); // does not call FlushBasketsImpl() again
4767 if (gDebug > 0)
4768 Info("TTree::Fill", "AutoSave called at entry %lld, fZipBytes=%lld, fSavedBytes=%lld\n", fEntries,
4770 }
4771
4772 // Check that output file is still below the maximum size.
4773 // If above, close the current file and continue on a new file.
4774 // Currently, the automatic change of file is restricted
4775 // to the case where the tree is in the top level directory.
4776 if (fDirectory)
4777 if (TFile *file = fDirectory->GetFile())
4778 if (static_cast<TDirectory *>(file) == fDirectory && (file->GetEND() > fgMaxTreeSize))
4779 // Changing file clashes with the design of TMemFile and derivates, see #6523.
4780 if (!(dynamic_cast<TMemFile *>(file)))
4782
4783 return nerror == 0 ? nbytes : -1;
4784}
4785
4786////////////////////////////////////////////////////////////////////////////////
4787/// Search in the array for a branch matching the branch name,
4788/// with the branch possibly expressed as a 'full' path name (with dots).
4790static TBranch *R__FindBranchHelper(TObjArray *list, const char *branchname) {
4791 if (list==0 || branchname == 0 || branchname[0] == '\0') return 0;
4792
4793 Int_t nbranches = list->GetEntries();
4794
4795 UInt_t brlen = strlen(branchname);
4796
4797 for(Int_t index = 0; index < nbranches; ++index) {
4798 TBranch *where = (TBranch*)list->UncheckedAt(index);
4799
4800 const char *name = where->GetName();
4801 UInt_t len = strlen(name);
4802 if (len && name[len-1]==']') {
4803 const char *dim = strchr(name,'[');
4804 if (dim) {
4805 len = dim - name;
4806 }
4807 }
4808 if (brlen == len && strncmp(branchname,name,len)==0) {
4809 return where;
4810 }
4811 TBranch *next = 0;
4812 if ((brlen >= len) && (branchname[len] == '.')
4813 && strncmp(name, branchname, len) == 0) {
4814 // The prefix subbranch name match the branch name.
4815
4816 next = where->FindBranch(branchname);
4817 if (!next) {
4818 next = where->FindBranch(branchname+len+1);
4819 }
4820 if (next) return next;
4821 }
4822 const char *dot = strchr((char*)branchname,'.');
4823 if (dot) {
4824 if (len==(size_t)(dot-branchname) &&
4825 strncmp(branchname,name,dot-branchname)==0 ) {
4826 return R__FindBranchHelper(where->GetListOfBranches(),dot+1);
4827 }
4828 }
4829 }
4830 return 0;
4831}
4832
4833////////////////////////////////////////////////////////////////////////////////
4834/// Return the branch that correspond to the path 'branchname', which can
4835/// include the name of the tree or the omitted name of the parent branches.
4836/// In case of ambiguity, returns the first match.
4838TBranch* TTree::FindBranch(const char* branchname)
4839{
4840 // We already have been visited while recursively looking
4841 // through the friends tree, let return
4843 return nullptr;
4844 }
4845
4846 if (!branchname)
4847 return nullptr;
4848
4849 TBranch* branch = nullptr;
4850 // If the first part of the name match the TTree name, look for the right part in the
4851 // list of branches.
4852 // This will allow the branchname to be preceded by
4853 // the name of this tree.
4854 if (strncmp(fName.Data(),branchname,fName.Length())==0 && branchname[fName.Length()]=='.') {
4855 branch = R__FindBranchHelper( GetListOfBranches(), branchname + fName.Length() + 1);
4856 if (branch) return branch;
4857 }
4858 // If we did not find it, let's try to find the full name in the list of branches.
4859 branch = R__FindBranchHelper(GetListOfBranches(), branchname);
4860 if (branch) return branch;
4861
4862 // If we still did not find, let's try to find it within each branch assuming it does not the branch name.
4863 TIter next(GetListOfBranches());
4864 while ((branch = (TBranch*) next())) {
4865 TBranch* nestedbranch = branch->FindBranch(branchname);
4866 if (nestedbranch) {
4867 return nestedbranch;
4868 }
4869 }
4870
4871 // Search in list of friends.
4872 if (!fFriends) {
4873 return nullptr;
4874 }
4875 TFriendLock lock(this, kFindBranch);
4876 TIter nextf(fFriends);
4877 TFriendElement* fe = nullptr;
4878 while ((fe = (TFriendElement*) nextf())) {
4879 TTree* t = fe->GetTree();
4880 if (!t) {
4881 continue;
4882 }
4883 // If the alias is present replace it with the real name.
4884 const char *subbranch = strstr(branchname, fe->GetName());
4885 if (subbranch != branchname) {
4886 subbranch = nullptr;
4887 }
4888 if (subbranch) {
4889 subbranch += strlen(fe->GetName());
4890 if (*subbranch != '.') {
4891 subbranch = nullptr;
4892 } else {
4893 ++subbranch;
4894 }
4895 }
4896 std::ostringstream name;
4897 if (subbranch) {
4898 name << t->GetName() << "." << subbranch;
4899 } else {
4900 name << branchname;
4901 }
4902 branch = t->FindBranch(name.str().c_str());
4903 if (branch) {
4904 return branch;
4905 }
4906 }
4907 return nullptr;
4908}
4909
4910////////////////////////////////////////////////////////////////////////////////
4911/// Find leaf..
4913TLeaf* TTree::FindLeaf(const char* searchname)
4914{
4915 if (!searchname)
4916 return nullptr;
4917
4918 // We already have been visited while recursively looking
4919 // through the friends tree, let's return.
4921 return nullptr;
4922 }
4923
4924 // This will allow the branchname to be preceded by
4925 // the name of this tree.
4926 const char* subsearchname = strstr(searchname, GetName());
4927 if (subsearchname != searchname) {
4928 subsearchname = nullptr;
4929 }
4930 if (subsearchname) {
4931 subsearchname += strlen(GetName());
4932 if (*subsearchname != '.') {
4933 subsearchname = nullptr;
4934 } else {
4935 ++subsearchname;
4936 if (subsearchname[0] == 0) {
4937 subsearchname = nullptr;
4938 }
4939 }
4940 }
4941
4942 TString leafname;
4943 TString leaftitle;
4944 TString longname;
4945 TString longtitle;
4946
4947 const bool searchnameHasDot = strchr(searchname, '.') != nullptr;
4948
4949 // For leaves we allow for one level up to be prefixed to the name.
4950 TIter next(GetListOfLeaves());
4951 TLeaf* leaf = nullptr;
4952 while ((leaf = (TLeaf*) next())) {
4953 leafname = leaf->GetName();
4954 Ssiz_t dim = leafname.First('[');
4955 if (dim >= 0) leafname.Remove(dim);
4956
4957 if (leafname == searchname) {
4958 return leaf;
4959 }
4960 if (subsearchname && leafname == subsearchname) {
4961 return leaf;
4962 }
4963 // The TLeafElement contains the branch name
4964 // in its name, let's use the title.
4965 leaftitle = leaf->GetTitle();
4966 dim = leaftitle.First('[');
4967 if (dim >= 0) leaftitle.Remove(dim);
4968
4969 if (leaftitle == searchname) {
4970 return leaf;
4971 }
4972 if (subsearchname && leaftitle == subsearchname) {
4973 return leaf;
4974 }
4975 if (!searchnameHasDot)
4976 continue;
4977 TBranch* branch = leaf->GetBranch();
4978 if (branch) {
4979 longname.Form("%s.%s",branch->GetName(),leafname.Data());
4980 dim = longname.First('[');
4981 if (dim>=0) longname.Remove(dim);
4982 if (longname == searchname) {
4983 return leaf;
4984 }
4985 if (subsearchname && longname == subsearchname) {
4986 return leaf;
4987 }
4988 longtitle.Form("%s.%s",branch->GetName(),leaftitle.Data());
4989 dim = longtitle.First('[');
4990 if (dim>=0) longtitle.Remove(dim);
4991 if (longtitle == searchname) {
4992 return leaf;
4993 }
4994 if (subsearchname && longtitle == subsearchname) {
4995 return leaf;
4996 }
4997 // The following is for the case where the branch is only
4998 // a sub-branch. Since we do not see it through
4999 // TTree::GetListOfBranches, we need to see it indirectly.
5000 // This is the less sturdy part of this search ... it may
5001 // need refining ...
5002 if (strstr(searchname, ".") && !strcmp(searchname, branch->GetName())) {
5003 return leaf;
5004 }
5005 if (subsearchname && strstr(subsearchname, ".") && !strcmp(subsearchname, branch->GetName())) {
5006 return leaf;
5007 }
5008 }
5009 }
5010 // Search in list of friends.
5011 if (!fFriends) {
5012 return nullptr;
5013 }
5014 TFriendLock lock(this, kFindLeaf);
5015 TIter nextf(fFriends);
5016 TFriendElement* fe = nullptr;
5017 while ((fe = (TFriendElement*) nextf())) {
5018 TTree* t = fe->GetTree();
5019 if (!t) {
5020 continue;
5021 }
5022 // If the alias is present replace it with the real name.
5023 subsearchname = strstr(searchname, fe->GetName());
5024 if (subsearchname != searchname) {
5025 subsearchname = nullptr;
5026 }
5027 if (subsearchname) {
5028 subsearchname += strlen(fe->GetName());
5029 if (*subsearchname != '.') {
5030 subsearchname = nullptr;
5031 } else {
5032 ++subsearchname;
5033 }
5034 }
5035 if (subsearchname) {
5036 leafname.Form("%s.%s",t->GetName(),subsearchname);
5037 } else {
5038 leafname = searchname;
5039 }
5040 leaf = t->FindLeaf(leafname);
5041 if (leaf) {
5042 return leaf;
5043 }
5044 }
5045 return nullptr;
5046}
5047
5048////////////////////////////////////////////////////////////////////////////////
5049/// Fit a projected item(s) from a tree.
5050///
5051/// funcname is a TF1 function.
5052///
5053/// See TTree::Draw() for explanations of the other parameters.
5054///
5055/// By default the temporary histogram created is called htemp.
5056/// If varexp contains >>hnew , the new histogram created is called hnew
5057/// and it is kept in the current directory.
5058///
5059/// The function returns the number of selected entries.
5060///
5061/// Example:
5062/// ~~~ {.cpp}
5063/// tree.Fit(pol4,"sqrt(x)>>hsqrt","y>0")
5064/// ~~~
5065/// will fit sqrt(x) and save the histogram as "hsqrt" in the current
5066/// directory.
5067///
5068/// See also TTree::UnbinnedFit
5069///
5070/// ## Return status
5071///
5072/// The function returns the status of the histogram fit (see TH1::Fit)
5073/// If no entries were selected, the function returns -1;
5074/// (i.e. fitResult is null if the fit is OK)
5076Int_t TTree::Fit(const char* funcname, const char* varexp, const char* selection, Option_t* option, Option_t* goption, Long64_t nentries, Long64_t firstentry)
5077{
5078 GetPlayer();
5079 if (fPlayer) {
5080 return fPlayer->Fit(funcname, varexp, selection, option, goption, nentries, firstentry);
5081 }
5082 return -1;
5083}
5084
5085namespace {
5086struct BoolRAIIToggle {
5087 Bool_t &m_val;
5088
5089 BoolRAIIToggle(Bool_t &val) : m_val(val) { m_val = true; }
5090 ~BoolRAIIToggle() { m_val = false; }
5091};
5092}
5093
5094////////////////////////////////////////////////////////////////////////////////
5095/// Write to disk all the basket that have not yet been individually written and
5096/// create an event cluster boundary (by default).
5097///
5098/// If the caller wishes to flush the baskets but not create an event cluster,
5099/// then set create_cluster to false.
5100///
5101/// If ROOT has IMT-mode enabled, this will launch multiple TBB tasks in parallel
5102/// via TThreadExecutor to do this operation; one per basket compression. If the
5103/// caller utilizes TBB also, care must be taken to prevent deadlocks.
5104///
5105/// For example, let's say the caller holds mutex A and calls FlushBaskets; while
5106/// TBB is waiting for the ROOT compression tasks to complete, it may decide to
5107/// run another one of the user's tasks in this thread. If the second user task
5108/// tries to acquire A, then a deadlock will occur. The example call sequence
5109/// looks like this:
5110///
5111/// - User acquires mutex A
5112/// - User calls FlushBaskets.
5113/// - ROOT launches N tasks and calls wait.
5114/// - TBB schedules another user task, T2.
5115/// - T2 tries to acquire mutex A.
5116///
5117/// At this point, the thread will deadlock: the code may function with IMT-mode
5118/// disabled if the user assumed the legacy code never would run their own TBB
5119/// tasks.
5120///
5121/// SO: users of TBB who want to enable IMT-mode should carefully review their
5122/// locking patterns and make sure they hold no coarse-grained application
5123/// locks when they invoke ROOT.
5124///
5125/// Return the number of bytes written or -1 in case of write error.
5126Int_t TTree::FlushBaskets(Bool_t create_cluster) const
5127{
5128 Int_t retval = FlushBasketsImpl();
5129 if (retval == -1) return retval;
5130
5131 if (create_cluster) const_cast<TTree *>(this)->MarkEventCluster();
5132 return retval;
5133}
5134
5135////////////////////////////////////////////////////////////////////////////////
5136/// Internal implementation of the FlushBaskets algorithm.
5137/// Unlike the public interface, this does NOT create an explicit event cluster
5138/// boundary; it is up to the (internal) caller to determine whether that should
5139/// done.
5140///
5141/// Otherwise, the comments for FlushBaskets applies.
5144{
5145 if (!fDirectory) return 0;
5146 Int_t nbytes = 0;
5147 Int_t nerror = 0;
5148 TObjArray *lb = const_cast<TTree*>(this)->GetListOfBranches();
5149 Int_t nb = lb->GetEntriesFast();
5150
5151#ifdef R__USE_IMT
5152 const auto useIMT = ROOT::IsImplicitMTEnabled() && fIMTEnabled;
5153 if (useIMT) {
5154 // ROOT-9668: here we need to check if the size of fSortedBranches is different from the
5155 // size of the list of branches before triggering the initialisation of the fSortedBranches
5156 // container to cover two cases:
5157 // 1. This is the first time we flush. fSortedBranches is empty and we need to fill it.
5158 // 2. We flushed at least once already but a branch has been be added to the tree since then
5159 if (fSortedBranches.size() != unsigned(nb)) { const_cast<TTree*>(this)->InitializeBranchLists(false); }
5160
5161 BoolRAIIToggle sentry(fIMTFlush);
5162 fIMTZipBytes.store(0);
5163 fIMTTotBytes.store(0);
5164 std::atomic<Int_t> nerrpar(0);
5165 std::atomic<Int_t> nbpar(0);
5166 std::atomic<Int_t> pos(0);
5167
5168 auto mapFunction = [&]() {
5169 // The branch to process is obtained when the task starts to run.
5170 // This way, since branches are sorted, we make sure that branches
5171 // leading to big tasks are processed first. If we assigned the
5172 // branch at task creation time, the scheduler would not necessarily
5173 // respect our sorting.
5174 Int_t j = pos.fetch_add(1);
5175
5176 auto branch = fSortedBranches[j].second;
5177 if (R__unlikely(!branch)) { return; }
5178
5179 if (R__unlikely(gDebug > 0)) {
5180 std::stringstream ss;
5181 ss << std::this_thread::get_id();
5182 Info("FlushBaskets", "[IMT] Thread %s", ss.str().c_str());
5183 Info("FlushBaskets", "[IMT] Running task for branch #%d: %s", j, branch->GetName());
5184 }
5185
5186 Int_t nbtask = branch->FlushBaskets();
5187
5188 if (nbtask < 0) { nerrpar++; }
5189 else { nbpar += nbtask; }
5190 };
5191
5193 pool.Foreach(mapFunction, nb);
5194
5195 fIMTFlush = false;
5196 const_cast<TTree*>(this)->AddTotBytes(fIMTTotBytes);
5197 const_cast<TTree*>(this)->AddZipBytes(fIMTZipBytes);
5198
5199 return nerrpar ? -1 : nbpar.load();
5200 }
5201#endif
5202 for (Int_t j = 0; j < nb; j++) {
5203 TBranch* branch = (TBranch*) lb->UncheckedAt(j);
5204 if (branch) {
5205 Int_t nwrite = branch->FlushBaskets();
5206 if (nwrite<0) {
5207 ++nerror;
5208 } else {
5209 nbytes += nwrite;
5210 }
5211 }
5212 }
5213 if (nerror) {
5214 return -1;
5215 } else {
5216 return nbytes;
5217 }
5218}
5219
5220////////////////////////////////////////////////////////////////////////////////
5221/// Returns the expanded value of the alias. Search in the friends if any.
5223const char* TTree::GetAlias(const char* aliasName) const
5224{
5225 // We already have been visited while recursively looking
5226 // through the friends tree, let's return.
5228 return nullptr;
5229 }
5230 if (fAliases) {
5231 TObject* alias = fAliases->FindObject(aliasName);
5232 if (alias) {
5233 return alias->GetTitle();
5234 }
5235 }
5236 if (!fFriends) {
5237 return nullptr;
5238 }
5239 TFriendLock lock(const_cast<TTree*>(this), kGetAlias);
5240 TIter nextf(fFriends);
5241 TFriendElement* fe = nullptr;
5242 while ((fe = (TFriendElement*) nextf())) {
5243 TTree* t = fe->GetTree();
5244 if (t) {
5245 const char* alias = t->GetAlias(aliasName);
5246 if (alias) {
5247 return alias;
5248 }
5249 const char* subAliasName = strstr(aliasName, fe->GetName());
5250 if (subAliasName && (subAliasName[strlen(fe->GetName())] == '.')) {
5251 alias = t->GetAlias(aliasName + strlen(fe->GetName()) + 1);
5252 if (alias) {
5253 return alias;
5254 }
5255 }
5256 }
5257 }
5258 return nullptr;
5259}
5260
5261namespace {
5262/// Do a breadth first search through the implied hierarchy
5263/// of branches.
5264/// To avoid scanning through the list multiple time
5265/// we also remember the 'depth-first' match.
5266TBranch *R__GetBranch(const TObjArray &branches, const char *name)
5267{
5268 TBranch *result = nullptr;
5269 Int_t nb = branches.GetEntriesFast();
5270 for (Int_t i = 0; i < nb; i++) {
5271 TBranch* b = (TBranch*)branches.UncheckedAt(i);
5272 if (!b)
5273 continue;
5274 if (!strcmp(b->GetName(), name)) {
5275 return b;
5276 }
5277 if (!strcmp(b->GetFullName(), name)) {
5278 return b;
5279 }
5280 if (!result)
5281 result = R__GetBranch(*(b->GetListOfBranches()), name);
5282 }
5283 return result;
5284}
5285}
5286
5287////////////////////////////////////////////////////////////////////////////////
5288/// Return pointer to the branch with the given name in this tree or its friends.
5289/// The search is done breadth first.
5291TBranch* TTree::GetBranch(const char* name)
5292{
5293 // We already have been visited while recursively
5294 // looking through the friends tree, let's return.
5296 return nullptr;
5297 }
5298
5299 if (!name)
5300 return nullptr;
5301
5302 // Look for an exact match in the list of top level
5303 // branches.
5305 if (result)
5306 return result;
5307
5308 // Search using branches, breadth first.
5309 result = R__GetBranch(fBranches, name);
5310 if (result)
5311 return result;
5312
5313 // Search using leaves.
5314 TObjArray* leaves = GetListOfLeaves();
5315 Int_t nleaves = leaves->GetEntriesFast();
5316 for (Int_t i = 0; i < nleaves; i++) {
5317 TLeaf* leaf = (TLeaf*) leaves->UncheckedAt(i);
5318 TBranch* branch = leaf->GetBranch();
5319 if (!strcmp(branch->GetName(), name)) {