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