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