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///
5351/// If the selection uses any arrays or containers, we return the number
5352/// of entries where at least one element match the selection.
5353/// GetEntries is implemented using the selector class TSelectorEntries,
5354/// which can be used directly (see code in TTreePlayer::GetEntries) for
5355/// additional option.
5356/// If SetEventList was used on the TTree or TChain, only that subset
5357/// of entries will be considered.
5359Long64_t TTree::GetEntries(const char *selection)
5360{
5361 GetPlayer();
5362 if (fPlayer) {
5363 return fPlayer->GetEntries(selection);
5364 }
5365 return -1;
5366}
5367
5368////////////////////////////////////////////////////////////////////////////////
5369/// Return pointer to the 1st Leaf named name in any Branch of this Tree or
5370/// any branch in the list of friend trees.
5373{
5374 if (fEntries) return fEntries;
5375 if (!fFriends) return 0;
5377 if (!fr) return 0;
5378 TTree *t = fr->GetTree();
5379 if (t==0) return 0;
5380 return t->GetEntriesFriend();
5381}
5382
5383////////////////////////////////////////////////////////////////////////////////
5384/// Read all branches of entry and return total number of bytes read.
5385///
5386/// - `getall = 0` : get only active branches
5387/// - `getall = 1` : get all branches
5388///
5389/// The function returns the number of bytes read from the input buffer.
5390/// If entry does not exist the function returns 0.
5391/// If an I/O error occurs, the function returns -1.
5392///
5393/// If the Tree has friends, also read the friends entry.
5394///
5395/// To activate/deactivate one or more branches, use TBranch::SetBranchStatus
5396/// For example, if you have a Tree with several hundred branches, and you
5397/// are interested only by branches named "a" and "b", do
5398/// ~~~ {.cpp}
5399/// mytree.SetBranchStatus("*",0); //disable all branches
5400/// mytree.SetBranchStatus("a",1);
5401/// mytree.SetBranchStatus("b",1);
5402/// ~~~
5403/// when calling mytree.GetEntry(i); only branches "a" and "b" will be read.
5404///
5405/// __WARNING!!__
5406/// If your Tree has been created in split mode with a parent branch "parent.",
5407/// ~~~ {.cpp}
5408/// mytree.SetBranchStatus("parent",1);
5409/// ~~~
5410/// will not activate the sub-branches of "parent". You should do:
5411/// ~~~ {.cpp}
5412/// mytree.SetBranchStatus("parent*",1);
5413/// ~~~
5414/// Without the trailing dot in the branch creation you have no choice but to
5415/// call SetBranchStatus explicitly for each of the sub branches.
5416///
5417/// An alternative is to call directly
5418/// ~~~ {.cpp}
5419/// brancha.GetEntry(i)
5420/// branchb.GetEntry(i);
5421/// ~~~
5422/// ## IMPORTANT NOTE
5423///
5424/// By default, GetEntry reuses the space allocated by the previous object
5425/// for each branch. You can force the previous object to be automatically
5426/// deleted if you call mybranch.SetAutoDelete(kTRUE) (default is kFALSE).
5427///
5428/// Example:
5429///
5430/// Consider the example in $ROOTSYS/test/Event.h
5431/// The top level branch in the tree T is declared with:
5432/// ~~~ {.cpp}
5433/// Event *event = 0; //event must be null or point to a valid object
5434/// //it must be initialized
5435/// T.SetBranchAddress("event",&event);
5436/// ~~~
5437/// When reading the Tree, one can choose one of these 3 options:
5438///
5439/// ## OPTION 1
5440///
5441/// ~~~ {.cpp}
5442/// for (Long64_t i=0;i<nentries;i++) {
5443/// T.GetEntry(i);
5444/// // the object event has been filled at this point
5445/// }
5446/// ~~~
5447/// The default (recommended). At the first entry an object of the class
5448/// Event will be created and pointed by event. At the following entries,
5449/// event will be overwritten by the new data. All internal members that are
5450/// TObject* are automatically deleted. It is important that these members
5451/// be in a valid state when GetEntry is called. Pointers must be correctly
5452/// initialized. However these internal members will not be deleted if the
5453/// characters "->" are specified as the first characters in the comment
5454/// field of the data member declaration.
5455///
5456/// If "->" is specified, the pointer member is read via pointer->Streamer(buf).
5457/// In this case, it is assumed that the pointer is never null (case of
5458/// pointer TClonesArray *fTracks in the Event example). If "->" is not
5459/// specified, the pointer member is read via buf >> pointer. In this case
5460/// the pointer may be null. Note that the option with "->" is faster to
5461/// read or write and it also consumes less space in the file.
5462///
5463/// ## OPTION 2
5464///
5465/// The option AutoDelete is set
5466/// ~~~ {.cpp}
5467/// TBranch *branch = T.GetBranch("event");
5468/// branch->SetAddress(&event);
5469/// branch->SetAutoDelete(kTRUE);
5470/// for (Long64_t i=0;i<nentries;i++) {
5471/// T.GetEntry(i);
5472/// // the object event has been filled at this point
5473/// }
5474/// ~~~
5475/// In this case, at each iteration, the object event is deleted by GetEntry
5476/// and a new instance of Event is created and filled.
5477///
5478/// ## OPTION 3
5479///
5480/// ~~~ {.cpp}
5481/// Same as option 1, but you delete yourself the event.
5482///
5483/// for (Long64_t i=0;i<nentries;i++) {
5484/// delete event;
5485/// event = 0; // EXTREMELY IMPORTANT
5486/// T.GetEntry(i);
5487/// // the object event has been filled at this point
5488/// }
5489/// ~~~
5490/// It is strongly recommended to use the default option 1. It has the
5491/// additional advantage that functions like TTree::Draw (internally calling
5492/// TTree::GetEntry) will be functional even when the classes in the file are
5493/// not available.
5494///
5495/// Note: See the comments in TBranchElement::SetAddress() for the
5496/// object ownership policy of the underlying (user) data.
5498Int_t TTree::GetEntry(Long64_t entry, Int_t getall)
5499{
5500
5501 // We already have been visited while recursively looking
5502 // through the friends tree, let return
5503 if (kGetEntry & fFriendLockStatus) return 0;
5504
5505 if (entry < 0 || entry >= fEntries) return 0;
5506 Int_t i;
5507 Int_t nbytes = 0;
5508 fReadEntry = entry;
5509
5510 // create cache if wanted
5511 if (fCacheDoAutoInit)
5513
5514 Int_t nbranches = fBranches.GetEntriesUnsafe();
5515 Int_t nb=0;
5516
5517 auto seqprocessing = [&]() {
5518 TBranch *branch;
5519 for (i=0;i<nbranches;i++) {
5520 branch = (TBranch*)fBranches.UncheckedAt(i);
5521 nb = branch->GetEntry(entry, getall);
5522 if (nb < 0) break;
5523 nbytes += nb;
5524 }
5525 };
5526
5527#ifdef R__USE_IMT
5529 if (fSortedBranches.empty())
5531
5532 // Count branches are processed first and sequentially
5533 for (auto branch : fSeqBranches) {
5534 nb = branch->GetEntry(entry, getall);
5535 if (nb < 0) break;
5536 nbytes += nb;
5537 }
5538 if (nb < 0) return nb;
5539
5540 // Enable this IMT use case (activate its locks)
5542
5543 Int_t errnb = 0;
5544 std::atomic<Int_t> pos(0);
5545 std::atomic<Int_t> nbpar(0);
5546
5547 auto mapFunction = [&]() {
5548 // The branch to process is obtained when the task starts to run.
5549 // This way, since branches are sorted, we make sure that branches
5550 // leading to big tasks are processed first. If we assigned the
5551 // branch at task creation time, the scheduler would not necessarily
5552 // respect our sorting.
5553 Int_t j = pos.fetch_add(1);
5554
5555 Int_t nbtask = 0;
5556 auto branch = fSortedBranches[j].second;
5557
5558 if (gDebug > 0) {
5559 std::stringstream ss;
5560 ss << std::this_thread::get_id();
5561 Info("GetEntry", "[IMT] Thread %s", ss.str().c_str());
5562 Info("GetEntry", "[IMT] Running task for branch #%d: %s", j, branch->GetName());
5563 }
5564
5565 std::chrono::time_point<std::chrono::system_clock> start, end;
5566
5567 start = std::chrono::system_clock::now();
5568 nbtask = branch->GetEntry(entry, getall);
5569 end = std::chrono::system_clock::now();
5570
5571 Long64_t tasktime = (Long64_t)std::chrono::duration_cast<std::chrono::microseconds>(end - start).count();
5572 fSortedBranches[j].first += tasktime;
5573
5574 if (nbtask < 0) errnb = nbtask;
5575 else nbpar += nbtask;
5576 };
5577
5579 pool.Foreach(mapFunction, fSortedBranches.size());
5580
5581 if (errnb < 0) {
5582 nb = errnb;
5583 }
5584 else {
5585 // Save the number of bytes read by the tasks
5586 nbytes += nbpar;
5587
5588 // Re-sort branches if necessary
5592 }
5593 }
5594 }
5595 else {
5596 seqprocessing();
5597 }
5598#else
5599 seqprocessing();
5600#endif
5601 if (nb < 0) return nb;
5602
5603 // GetEntry in list of friends
5604 if (!fFriends) return nbytes;
5605 TFriendLock lock(this,kGetEntry);
5606 TIter nextf(fFriends);
5607 TFriendElement *fe;
5608 while ((fe = (TFriendElement*)nextf())) {
5609 TTree *t = fe->GetTree();
5610 if (t) {
5612 nb = t->GetEntry(t->GetReadEntry(),getall);
5613 } else {
5614 if ( t->LoadTreeFriend(entry,this) >= 0 ) {
5615 nb = t->GetEntry(t->GetReadEntry(),getall);
5616 } else nb = 0;
5617 }
5618 if (nb < 0) return nb;
5619 nbytes += nb;
5620 }
5621 }
5622 return nbytes;
5623}
5624
5625
5626////////////////////////////////////////////////////////////////////////////////
5627/// Divides the top-level branches into two vectors: (i) branches to be
5628/// processed sequentially and (ii) branches to be processed in parallel.
5629/// Even if IMT is on, some branches might need to be processed first and in a
5630/// sequential fashion: in the parallelization of GetEntry, those are the
5631/// branches that store the size of another branch for every entry
5632/// (e.g. the size of an array branch). If such branches were processed
5633/// in parallel with the rest, there could be two threads invoking
5634/// TBranch::GetEntry on one of them at the same time, since a branch that
5635/// depends on a size (or count) branch will also invoke GetEntry on the latter.
5636/// This method can be invoked several times during the event loop if the TTree
5637/// is being written, for example when adding new branches. In these cases, the
5638/// `checkLeafCount` parameter is false.
5639/// \param[in] checkLeafCount True if we need to check whether some branches are
5640/// count leaves.
5642void TTree::InitializeBranchLists(bool checkLeafCount)
5643{
5644 Int_t nbranches = fBranches.GetEntriesFast();
5645
5646 // The special branch fBranchRef needs to be processed sequentially:
5647 // we add it once only.
5648 if (fBranchRef && fBranchRef != fSeqBranches[0]) {
5649 fSeqBranches.push_back(fBranchRef);
5650 }
5651
5652 // The branches to be processed sequentially are those that are the leaf count of another branch
5653 if (checkLeafCount) {
5654 for (Int_t i = 0; i < nbranches; i++) {
5655 TBranch* branch = (TBranch*)fBranches.UncheckedAt(i);
5656 auto leafCount = ((TLeaf*)branch->GetListOfLeaves()->At(0))->GetLeafCount();
5657 if (leafCount) {
5658 auto countBranch = leafCount->GetBranch();
5659 if (std::find(fSeqBranches.begin(), fSeqBranches.end(), countBranch) == fSeqBranches.end()) {
5660 fSeqBranches.push_back(countBranch);
5661 }
5662 }
5663 }
5664 }
5665
5666 // Any branch that is not a leaf count can be safely processed in parallel when reading
5667 // We need to reset the vector to make sure we do not re-add several times the same branch.
5668 if (!checkLeafCount) {
5669 fSortedBranches.clear();
5670 }
5671 for (Int_t i = 0; i < nbranches; i++) {
5672 Long64_t bbytes = 0;
5673 TBranch* branch = (TBranch*)fBranches.UncheckedAt(i);
5674 if (std::find(fSeqBranches.begin(), fSeqBranches.end(), branch) == fSeqBranches.end()) {
5675 bbytes = branch->GetTotBytes("*");
5676 fSortedBranches.emplace_back(bbytes, branch);
5677 }
5678 }
5679
5680 // Initially sort parallel branches by size
5681 std::sort(fSortedBranches.begin(),
5682 fSortedBranches.end(),
5683 [](std::pair<Long64_t,TBranch*> a, std::pair<Long64_t,TBranch*> b) {
5684 return a.first > b.first;
5685 });
5686
5687 for (size_t i = 0; i < fSortedBranches.size(); i++) {
5688 fSortedBranches[i].first = 0LL;
5689 }
5690}
5691
5692////////////////////////////////////////////////////////////////////////////////
5693/// Sorts top-level branches by the last average task time recorded per branch.
5696{
5697 for (size_t i = 0; i < fSortedBranches.size(); i++) {
5699 }
5700
5701 std::sort(fSortedBranches.begin(),
5702 fSortedBranches.end(),
5703 [](std::pair<Long64_t,TBranch*> a, std::pair<Long64_t,TBranch*> b) {
5704 return a.first > b.first;
5705 });
5706
5707 for (size_t i = 0; i < fSortedBranches.size(); i++) {
5708 fSortedBranches[i].first = 0LL;
5709 }
5710}
5711
5712////////////////////////////////////////////////////////////////////////////////
5713///Returns the entry list assigned to this tree
5716{
5717 return fEntryList;
5718}
5719
5720////////////////////////////////////////////////////////////////////////////////
5721/// Return entry number corresponding to entry.
5722///
5723/// if no TEntryList set returns entry
5724/// else returns the entry number corresponding to the list index=entry
5727{
5728 if (!fEntryList) {
5729 return entry;
5730 }
5731
5732 return fEntryList->GetEntry(entry);
5733}
5734
5735////////////////////////////////////////////////////////////////////////////////
5736/// Return entry number corresponding to major and minor number.
5737/// Note that this function returns only the entry number, not the data
5738/// To read the data corresponding to an entry number, use TTree::GetEntryWithIndex
5739/// the BuildIndex function has created a table of Long64_t* of sorted values
5740/// corresponding to val = major<<31 + minor;
5741/// The function performs binary search in this sorted table.
5742/// If it finds a pair that matches val, it returns directly the
5743/// index in the table.
5744/// If an entry corresponding to major and minor is not found, the function
5745/// returns the index of the major,minor pair immediately lower than the
5746/// requested value, ie it will return -1 if the pair is lower than
5747/// the first entry in the index.
5748///
5749/// See also GetEntryNumberWithIndex
5752{
5753 if (!fTreeIndex) {
5754 return -1;
5755 }
5756 return fTreeIndex->GetEntryNumberWithBestIndex(major, minor);
5757}
5758
5759////////////////////////////////////////////////////////////////////////////////
5760/// Return entry number corresponding to major and minor number.
5761/// Note that this function returns only the entry number, not the data
5762/// To read the data corresponding to an entry number, use TTree::GetEntryWithIndex
5763/// the BuildIndex function has created a table of Long64_t* of sorted values
5764/// corresponding to val = major<<31 + minor;
5765/// The function performs binary search in this sorted table.
5766/// If it finds a pair that matches val, it returns directly the
5767/// index in the table, otherwise it returns -1.
5768///
5769/// See also GetEntryNumberWithBestIndex
5772{
5773 if (!fTreeIndex) {
5774 return -1;
5775 }
5776 return fTreeIndex->GetEntryNumberWithIndex(major, minor);
5777}
5778
5779////////////////////////////////////////////////////////////////////////////////
5780/// Read entry corresponding to major and minor number.
5781///
5782/// The function returns the total number of bytes read.
5783/// If the Tree has friend trees, the corresponding entry with
5784/// the index values (major,minor) is read. Note that the master Tree
5785/// and its friend may have different entry serial numbers corresponding
5786/// to (major,minor).
5789{
5790 // We already have been visited while recursively looking
5791 // through the friends tree, let's return.
5793 return 0;
5794 }
5795 Long64_t serial = GetEntryNumberWithIndex(major, minor);
5796 if (serial < 0) {
5797 return -1;
5798 }
5799 // create cache if wanted
5800 if (fCacheDoAutoInit)
5802
5803 Int_t i;
5804 Int_t nbytes = 0;
5805 fReadEntry = serial;
5806 TBranch *branch;
5807 Int_t nbranches = fBranches.GetEntriesFast();
5808 Int_t nb;
5809 for (i = 0; i < nbranches; ++i) {
5810 branch = (TBranch*)fBranches.UncheckedAt(i);
5811 nb = branch->GetEntry(serial);
5812 if (nb < 0) return nb;
5813 nbytes += nb;
5814 }
5815 // GetEntry in list of friends
5816 if (!fFriends) return nbytes;
5818 TIter nextf(fFriends);
5819 TFriendElement* fe = 0;
5820 while ((fe = (TFriendElement*) nextf())) {
5821 TTree *t = fe->GetTree();
5822 if (t) {
5823 serial = t->GetEntryNumberWithIndex(major,minor);
5824 if (serial <0) return -nbytes;
5825 nb = t->GetEntry(serial);
5826 if (nb < 0) return nb;
5827 nbytes += nb;
5828 }
5829 }
5830 return nbytes;
5831}
5832
5833////////////////////////////////////////////////////////////////////////////////
5834/// Return a pointer to the TTree friend whose name or alias is 'friendname.
5836TTree* TTree::GetFriend(const char *friendname) const
5837{
5838
5839 // We already have been visited while recursively
5840 // looking through the friends tree, let's return.
5842 return 0;
5843 }
5844 if (!fFriends) {
5845 return 0;
5846 }
5847 TFriendLock lock(const_cast<TTree*>(this), kGetFriend);
5848 TIter nextf(fFriends);
5849 TFriendElement* fe = 0;
5850 while ((fe = (TFriendElement*) nextf())) {
5851 if (strcmp(friendname,fe->GetName())==0
5852 || strcmp(friendname,fe->GetTreeName())==0) {
5853 return fe->GetTree();
5854 }
5855 }
5856 // After looking at the first level,
5857 // let's see if it is a friend of friends.
5858 nextf.Reset();
5859 fe = 0;
5860 while ((fe = (TFriendElement*) nextf())) {
5861 TTree *res = fe->GetTree()->GetFriend(friendname);
5862 if (res) {
5863 return res;
5864 }
5865 }
5866 return 0;
5867}
5868
5869////////////////////////////////////////////////////////////////////////////////
5870/// If the 'tree' is a friend, this method returns its alias name.
5871///
5872/// This alias is an alternate name for the tree.
5873///
5874/// It can be used in conjunction with a branch or leaf name in a TTreeFormula,
5875/// to specify in which particular tree the branch or leaf can be found if
5876/// the friend trees have branches or leaves with the same name as the master
5877/// tree.
5878///
5879/// It can also be used in conjunction with an alias created using
5880/// TTree::SetAlias in a TTreeFormula, e.g.:
5881/// ~~~ {.cpp}
5882/// maintree->Draw("treealias.fPx - treealias.myAlias");
5883/// ~~~
5884/// where fPx is a branch of the friend tree aliased as 'treealias' and 'myAlias'
5885/// was created using TTree::SetAlias on the friend tree.
5886///
5887/// However, note that 'treealias.myAlias' will be expanded literally,
5888/// without remembering that it comes from the aliased friend and thus
5889/// the branch name might not be disambiguated properly, which means
5890/// that you may not be able to take advantage of this feature.
5891///
5893const char* TTree::GetFriendAlias(TTree* tree) const
5894{
5895 if ((tree == this) || (tree == GetTree())) {
5896 return 0;
5897 }
5898
5899 // We already have been visited while recursively
5900 // looking through the friends tree, let's return.
5902 return 0;
5903 }
5904 if (!fFriends) {
5905 return 0;
5906 }
5907 TFriendLock lock(const_cast<TTree*>(this), kGetFriendAlias);
5908 TIter nextf(fFriends);
5909 TFriendElement* fe = 0;
5910 while ((fe = (TFriendElement*) nextf())) {
5911 TTree* t = fe->GetTree();
5912 if (t == tree) {
5913 return fe->GetName();
5914 }
5915 // Case of a chain:
5916 if (t && t->GetTree() == tree) {
5917 return fe->GetName();
5918 }
5919 }
5920 // After looking at the first level,
5921 // let's see if it is a friend of friends.
5922 nextf.Reset();
5923 fe = 0;
5924 while ((fe = (TFriendElement*) nextf())) {
5925 const char* res = fe->GetTree()->GetFriendAlias(tree);
5926 if (res) {
5927 return res;
5928 }
5929 }
5930 return 0;
5931}
5932
5933////////////////////////////////////////////////////////////////////////////////
5934/// Returns the current set of IO settings
5936{
5937 return fIOFeatures;
5938}
5939
5940////////////////////////////////////////////////////////////////////////////////
5941/// Creates a new iterator that will go through all the leaves on the tree itself and its friend.
5944{
5945 return new TTreeFriendLeafIter(this, dir);
5946}
5947
5948////////////////////////////////////////////////////////////////////////////////
5949/// Return pointer to the 1st Leaf named name in any Branch of this
5950/// Tree or any branch in the list of friend trees.
5951///
5952/// The leaf name can contain the name of a friend tree with the
5953/// syntax: friend_dir_and_tree.full_leaf_name
5954/// the friend_dir_and_tree can be of the form:
5955/// ~~~ {.cpp}
5956/// TDirectoryName/TreeName
5957/// ~~~
5959TLeaf* TTree::GetLeafImpl(const char* branchname, const char *leafname)
5960{
5961 TLeaf *leaf = 0;
5962 if (branchname) {
5963 TBranch *branch = FindBranch(branchname);
5964 if (branch) {
5965 leaf = branch->GetLeaf(leafname);
5966 if (leaf) {
5967 return leaf;
5968 }
5969 }
5970 }
5971 TIter nextl(GetListOfLeaves());
5972 while ((leaf = (TLeaf*)nextl())) {
5973 if (!strcmp(leaf->GetFullName(),leafname))
5974 return leaf;
5975 if (strcmp(leaf->GetName(),leafname))
5976 continue;
5977 if (branchname) {
5978 UInt_t nbch = strlen(branchname);
5979 TBranch *br = leaf->GetBranch();
5980 const char* brname = br->GetName();
5981 TBranch *mother = br->GetMother();
5982 if (strncmp(brname,branchname,nbch)) {
5983 if (mother != br) {
5984 const char *mothername = mother->GetName();
5985 UInt_t motherlen = strlen(mothername);
5986 if (nbch > motherlen && strncmp(mothername,branchname,motherlen)==0 && (mothername[motherlen-1]=='.' || branchname[motherlen]=='.')) {
5987 // The left part of the requested name match the name of the mother, let's see if the right part match the name of the branch.
5988 if (strncmp(brname,branchname+motherlen+1,nbch-motherlen-1)) {
5989 // No it does not
5990 continue;
5991 } // else we have match so we can proceed.
5992 } else {
5993 // no match
5994 continue;
5995 }
5996 } else {
5997 continue;
5998 }
5999 }
6000 // The start of the branch name is identical to the content
6001 // of 'aname' before the first '/'.
6002 // Let's make sure that it is not longer (we are trying
6003 // to avoid having jet2/value match the branch jet23
6004 if ((strlen(brname) > nbch) && (brname[nbch] != '.') && (brname[nbch] != '[')) {
6005 continue;
6006 }
6007 }
6008 return leaf;
6009 }
6010 if (!fFriends) return 0;
6011 TFriendLock lock(this,kGetLeaf);
6012 TIter next(fFriends);
6013 TFriendElement *fe;
6014 while ((fe = (TFriendElement*)next())) {
6015 TTree *t = fe->GetTree();
6016 if (t) {
6017 leaf = t->GetLeaf(leafname);
6018 if (leaf) return leaf;
6019 }
6020 }
6021
6022 //second pass in the list of friends when the leaf name
6023 //is prefixed by the tree name
6024 TString strippedArg;
6025 next.Reset();
6026 while ((fe = (TFriendElement*)next())) {
6027 TTree *t = fe->GetTree();
6028 if (t==0) continue;
6029 char *subname = (char*)strstr(leafname,fe->GetName());
6030 if (subname != leafname) continue;
6031 Int_t l = strlen(fe->GetName());
6032 subname += l;
6033 if (*subname != '.') continue;
6034 subname++;
6035 strippedArg += subname;
6036 leaf = t->GetLeaf(branchname,subname);
6037 if (leaf) return leaf;
6038 }
6039 return 0;
6040}
6041
6042////////////////////////////////////////////////////////////////////////////////
6043/// Return pointer to the 1st Leaf named name in any Branch of this
6044/// Tree or any branch in the list of friend trees.
6045///
6046/// The leaf name can contain the name of a friend tree with the
6047/// syntax: friend_dir_and_tree.full_leaf_name
6048/// the friend_dir_and_tree can be of the form:
6049///
6050/// TDirectoryName/TreeName
6052TLeaf* TTree::GetLeaf(const char* branchname, const char *leafname)
6053{
6054 if (leafname == 0) return 0;
6055
6056 // We already have been visited while recursively looking
6057 // through the friends tree, let return
6059 return 0;
6060 }
6061
6062 return GetLeafImpl(branchname,leafname);
6063}
6064
6065////////////////////////////////////////////////////////////////////////////////
6066/// Return pointer to first leaf named \param[name] in any branch of this
6067/// tree or its friend trees.
6068///
6069/// \param[name] may be in the form 'branch/leaf'
6070///
6072TLeaf* TTree::GetLeaf(const char *name)
6073{
6074 // Return nullptr if name is invalid or if we have
6075 // already been visited while searching friend trees
6076 if (!name || (kGetLeaf & fFriendLockStatus))
6077 return nullptr;
6078
6079 std::string path(name);
6080 const auto sep = path.find_last_of("/");
6081 if (sep != std::string::npos)
6082 return GetLeafImpl(path.substr(0, sep).c_str(), name+sep+1);
6083
6084 return GetLeafImpl(nullptr, name);
6085}
6086
6087////////////////////////////////////////////////////////////////////////////////
6088/// Return maximum of column with name columname.
6089/// if the Tree has an associated TEventList or TEntryList, the maximum
6090/// is computed for the entries in this list.
6092Double_t TTree::GetMaximum(const char* columname)
6093{
6094 TLeaf* leaf = this->GetLeaf(columname);
6095 if (!leaf) {
6096 return 0;
6097 }
6098
6099 // create cache if wanted
6100 if (fCacheDoAutoInit)
6102
6103 TBranch* branch = leaf->GetBranch();
6104 Double_t cmax = -DBL_MAX;
6105 for (Long64_t i = 0; i < fEntries; ++i) {
6106 Long64_t entryNumber = this->GetEntryNumber(i);
6107 if (entryNumber < 0) break;
6108 branch->GetEntry(entryNumber);
6109 for (Int_t j = 0; j < leaf->GetLen(); ++j) {
6110 Double_t val = leaf->GetValue(j);
6111 if (val > cmax) {
6112 cmax = val;
6113 }
6114 }
6115 }
6116 return cmax;
6117}
6118
6119////////////////////////////////////////////////////////////////////////////////
6120/// Static function which returns the tree file size limit in bytes.
6123{
6124 return fgMaxTreeSize;
6125}
6126
6127////////////////////////////////////////////////////////////////////////////////
6128/// Return minimum of column with name columname.
6129/// if the Tree has an associated TEventList or TEntryList, the minimum
6130/// is computed for the entries in this list.
6132Double_t TTree::GetMinimum(const char* columname)
6133{
6134 TLeaf* leaf = this->GetLeaf(columname);
6135 if (!leaf) {
6136 return 0;
6137 }
6138
6139 // create cache if wanted
6140 if (fCacheDoAutoInit)
6142
6143 TBranch* branch = leaf->GetBranch();
6144 Double_t cmin = DBL_MAX;
6145 for (Long64_t i = 0; i < fEntries; ++i) {
6146 Long64_t entryNumber = this->GetEntryNumber(i);
6147 if (entryNumber < 0) break;
6148 branch->GetEntry(entryNumber);
6149 for (Int_t j = 0;j < leaf->GetLen(); ++j) {
6150 Double_t val = leaf->GetValue(j);
6151 if (val < cmin) {
6152 cmin = val;
6153 }
6154 }
6155 }
6156 return cmin;
6157}
6158
6159////////////////////////////////////////////////////////////////////////////////
6160/// Load the TTreePlayer (if not already done).
6163{
6164 if (fPlayer) {
6165 return fPlayer;
6166 }
6168 return fPlayer;
6169}
6170
6171////////////////////////////////////////////////////////////////////////////////
6172/// Find and return the TTreeCache registered with the file and which may
6173/// contain branches for us.
6176{
6177 TTreeCache *pe = dynamic_cast<TTreeCache*>(file->GetCacheRead(this));
6178 if (pe && pe->GetTree() != this)
6179 pe = nullptr;
6180 return pe;
6181}
6182
6183////////////////////////////////////////////////////////////////////////////////
6184/// Find and return the TTreeCache registered with the file and which may
6185/// contain branches for us. If create is true and there is no cache
6186/// a new cache is created with default size.
6189{
6191 if (create && !pe) {
6192 if (fCacheDoAutoInit)
6194 pe = dynamic_cast<TTreeCache*>(file->GetCacheRead(this));
6195 if (pe && pe->GetTree() != this) pe = 0;
6196 }
6197 return pe;
6198}
6199
6200////////////////////////////////////////////////////////////////////////////////
6201/// Return a pointer to the list containing user objects associated to this tree.
6202///
6203/// The list is automatically created if it does not exist.
6204///
6205/// WARNING: By default the TTree destructor will delete all objects added
6206/// to this list. If you do not want these objects to be deleted,
6207/// call:
6208///
6209/// mytree->GetUserInfo()->Clear();
6210///
6211/// before deleting the tree.
6214{
6215 if (!fUserInfo) {
6216 fUserInfo = new TList();
6217 fUserInfo->SetName("UserInfo");
6218 }
6219 return fUserInfo;
6220}
6221
6222////////////////////////////////////////////////////////////////////////////////
6223/// Appends the cluster range information stored in 'fromtree' to this tree,
6224/// including the value of fAutoFlush.
6225///
6226/// This is used when doing a fast cloning (by TTreeCloner).
6227/// See also fAutoFlush and fAutoSave if needed.
6229void TTree::ImportClusterRanges(TTree *fromtree)
6230{
6231 Long64_t autoflush = fromtree->GetAutoFlush();
6232 if (fromtree->fNClusterRange == 0 && fromtree->fAutoFlush == fAutoFlush) {
6233 // nothing to do
6234 } else if (fNClusterRange || fromtree->fNClusterRange) {
6235 Int_t newsize = fNClusterRange + 1 + fromtree->fNClusterRange;
6236 if (newsize > fMaxClusterRange) {
6237 if (fMaxClusterRange) {
6239 newsize*sizeof(Long64_t),fMaxClusterRange*sizeof(Long64_t));
6241 newsize*sizeof(Long64_t),fMaxClusterRange*sizeof(Long64_t));
6242 fMaxClusterRange = newsize;
6243 } else {
6244 fMaxClusterRange = newsize;
6247 }
6248 }
6249 if (fEntries) {
6253 }
6254 for (Int_t i = 0 ; i < fromtree->fNClusterRange; ++i) {
6258 }
6259 fAutoFlush = autoflush;
6260 } else {
6261 SetAutoFlush( autoflush );
6262 }
6263 Long64_t autosave = GetAutoSave();
6264 if (autoflush > 0 && autosave > 0) {
6265 SetAutoSave( autoflush*(autosave/autoflush) );
6266 }
6267}
6268
6269////////////////////////////////////////////////////////////////////////////////
6270/// Keep a maximum of fMaxEntries in memory.
6273{
6275 Long64_t maxEntries = fMaxEntries - (fMaxEntries / 10);
6276 for (Int_t i = 0; i < nb; ++i) {
6277 TBranch* branch = (TBranch*) fBranches.UncheckedAt(i);
6278 branch->KeepCircular(maxEntries);
6279 }
6280 if (fNClusterRange) {
6281 Long64_t entriesOffset = fEntries - maxEntries;
6282 Int_t oldsize = fNClusterRange;
6283 for(Int_t i = 0, j = 0; j < oldsize; ++j) {
6284 if (fClusterRangeEnd[j] > entriesOffset) {
6285 fClusterRangeEnd[i] = fClusterRangeEnd[j] - entriesOffset;
6286 ++i;
6287 } else {
6289 }
6290 }
6291 }
6292 fEntries = maxEntries;
6293 fReadEntry = -1;
6294}
6295
6296////////////////////////////////////////////////////////////////////////////////
6297/// Read in memory all baskets from all branches up to the limit of maxmemory bytes.
6298///
6299/// If maxmemory is non null and positive SetMaxVirtualSize is called
6300/// with this value. Default for maxmemory is 2000000000 (2 Gigabytes).
6301/// The function returns the total number of baskets read into memory
6302/// if negative an error occurred while loading the branches.
6303/// This method may be called to force branch baskets in memory
6304/// when random access to branch entries is required.
6305/// If random access to only a few branches is required, you should
6306/// call directly TBranch::LoadBaskets.
6309{
6310 if (maxmemory > 0) SetMaxVirtualSize(maxmemory);
6311
6312 TIter next(GetListOfLeaves());
6313 TLeaf *leaf;
6314 Int_t nimported = 0;
6315 while ((leaf=(TLeaf*)next())) {
6316 nimported += leaf->GetBranch()->LoadBaskets();//break;
6317 }
6318 return nimported;
6319}
6320
6321////////////////////////////////////////////////////////////////////////////////
6322/// Set current entry.
6323///
6324/// Returns -2 if entry does not exist (just as TChain::LoadTree()).
6325/// Returns -6 if an error occours in the notification callback (just as TChain::LoadTree()).
6326///
6327/// Note: This function is overloaded in TChain.
6328///
6331{
6332 // We already have been visited while recursively looking
6333 // through the friends tree, let return
6335 // We need to return a negative value to avoid a circular list of friend
6336 // to think that there is always an entry somewhere in the list.
6337 return -1;
6338 }
6339
6340 // create cache if wanted
6341 if (fCacheDoAutoInit && entry >=0)
6343
6344 if (fNotify) {
6345 if (fReadEntry < 0) {
6346 fNotify->Notify();
6347 }
6348 }
6349 fReadEntry = entry;
6350
6351 Bool_t friendHasEntry = kFALSE;
6352 if (fFriends) {
6353 // Set current entry in friends as well.
6354 //
6355 // An alternative would move this code to each of the
6356 // functions calling LoadTree (and to overload a few more).
6357 Bool_t needUpdate = kFALSE;
6358 {
6359 // This scope is need to insure the lock is released at the right time
6360 TIter nextf(fFriends);
6361 TFriendLock lock(this, kLoadTree);
6362 TFriendElement* fe = 0;
6363 while ((fe = (TFriendElement*) nextf())) {
6365 // This friend element was added by the chain that owns this
6366 // tree, the chain will deal with loading the correct entry.
6367 continue;
6368 }
6369 TTree* friendTree = fe->GetTree();
6370 if (friendTree == 0) {
6371 // Somehow we failed to retrieve the friend TTree.
6372 } else if (friendTree->IsA() == TTree::Class()) {
6373 // Friend is actually a tree.
6374 if (friendTree->LoadTreeFriend(entry, this) >= 0) {
6375 friendHasEntry = kTRUE;
6376 }
6377 } else {
6378 // Friend is actually a chain.
6379 // FIXME: This logic should be in the TChain override.
6380 Int_t oldNumber = friendTree->GetTreeNumber();
6381 if (friendTree->LoadTreeFriend(entry, this) >= 0) {
6382 friendHasEntry = kTRUE;
6383 }
6384 Int_t newNumber = friendTree->GetTreeNumber();
6385 if (oldNumber != newNumber) {
6386 // We can not just compare the tree pointers because they could be reused.
6387 // So we compare the tree number instead.
6388 needUpdate = kTRUE;
6389 }
6390 }
6391 } // for each friend
6392 }
6393 if (needUpdate) {
6394 //update list of leaves in all TTreeFormula of the TTreePlayer (if any)
6395 if (fPlayer) {
6397 }
6398 //Notify user if requested
6399 if (fNotify) {
6400 if(!fNotify->Notify()) return -6;
6401 }
6402 }
6403 }
6404
6405 if ((fReadEntry >= fEntries) && !friendHasEntry) {
6406 fReadEntry = -1;
6407 return -2;
6408 }
6409 return fReadEntry;
6410}
6411
6412////////////////////////////////////////////////////////////////////////////////
6413/// Load entry on behalf of our master tree, we may use an index.
6414///
6415/// Called by LoadTree() when the masterTree looks for the entry
6416/// number in a friend tree (us) corresponding to the passed entry
6417/// number in the masterTree.
6418///
6419/// If we have no index, our entry number and the masterTree entry
6420/// number are the same.
6421///
6422/// If we *do* have an index, we must find the (major, minor) value pair
6423/// in masterTree to locate our corresponding entry.
6424///
6426Long64_t TTree::LoadTreeFriend(Long64_t entry, TTree* masterTree)
6427{
6428 if (!fTreeIndex) {
6429 return LoadTree(entry);
6430 }
6431 return LoadTree(fTreeIndex->GetEntryNumberFriend(masterTree));
6432}
6433
6434////////////////////////////////////////////////////////////////////////////////
6435/// Generate a skeleton analysis class for this tree.
6436///
6437/// The following files are produced: classname.h and classname.C.
6438/// If classname is 0, classname will be called "nameoftree".
6439///
6440/// The generated code in classname.h includes the following:
6441///
6442/// - Identification of the original tree and the input file name.
6443/// - Definition of an analysis class (data members and member functions).
6444/// - The following member functions:
6445/// - constructor (by default opening the tree file),
6446/// - GetEntry(Long64_t entry),
6447/// - Init(TTree* tree) to initialize a new TTree,
6448/// - Show(Long64_t entry) to read and dump entry.
6449///
6450/// The generated code in classname.C includes only the main
6451/// analysis function Loop.
6452///
6453/// To use this function:
6454///
6455/// - Open your tree file (eg: TFile f("myfile.root");)
6456/// - T->MakeClass("MyClass");
6457///
6458/// where T is the name of the TTree in file myfile.root,
6459/// and MyClass.h, MyClass.C the name of the files created by this function.
6460/// In a ROOT session, you can do:
6461/// ~~~ {.cpp}
6462/// root > .L MyClass.C
6463/// root > MyClass* t = new MyClass;
6464/// root > t->GetEntry(12); // Fill data members of t with entry number 12.
6465/// root > t->Show(); // Show values of entry 12.
6466/// root > t->Show(16); // Read and show values of entry 16.
6467/// root > t->Loop(); // Loop on all entries.
6468/// ~~~
6469/// NOTE: Do not use the code generated for a single TTree which is part
6470/// of a TChain to process that entire TChain. The maximum dimensions
6471/// calculated for arrays on the basis of a single TTree from the TChain
6472/// might be (will be!) too small when processing all of the TTrees in
6473/// the TChain. You must use myChain.MakeClass() to generate the code,
6474/// not myTree.MakeClass(...).
6476Int_t TTree::MakeClass(const char* classname, Option_t* option)
6477{
6478 GetPlayer();
6479 if (!fPlayer) {
6480 return 0;
6481 }
6482 return fPlayer->MakeClass(classname, option);
6483}
6484
6485////////////////////////////////////////////////////////////////////////////////
6486/// Generate a skeleton function for this tree.
6487///
6488/// The function code is written on filename.
6489/// If filename is 0, filename will be called nameoftree.C
6490///
6491/// The generated code includes the following:
6492/// - Identification of the original Tree and Input file name,
6493/// - Opening the Tree file,
6494/// - Declaration of Tree variables,
6495/// - Setting of branches addresses,
6496/// - A skeleton for the entry loop.
6497///
6498/// To use this function:
6499///
6500/// - Open your Tree file (eg: TFile f("myfile.root");)
6501/// - T->MakeCode("MyAnalysis.C");
6502///
6503/// where T is the name of the TTree in file myfile.root
6504/// and MyAnalysis.C the name of the file created by this function.
6505///
6506/// NOTE: Since the implementation of this function, a new and better
6507/// function TTree::MakeClass() has been developed.
6509Int_t TTree::MakeCode(const char* filename)
6510{
6511 Warning("MakeCode", "MakeCode is obsolete. Use MakeClass or MakeSelector instead");
6512
6513 GetPlayer();
6514 if (!fPlayer) return 0;
6515 return fPlayer->MakeCode(filename);
6516}
6517
6518////////////////////////////////////////////////////////////////////////////////
6519/// Generate a skeleton analysis class for this Tree using TBranchProxy.
6520///
6521/// TBranchProxy is the base of a class hierarchy implementing an
6522/// indirect access to the content of the branches of a TTree.
6523///
6524/// "proxyClassname" is expected to be of the form:
6525/// ~~~ {.cpp}
6526/// [path/]fileprefix
6527/// ~~~
6528/// The skeleton will then be generated in the file:
6529/// ~~~ {.cpp}
6530/// fileprefix.h
6531/// ~~~
6532/// located in the current directory or in 'path/' if it is specified.
6533/// The class generated will be named 'fileprefix'
6534///
6535/// "macrofilename" and optionally "cutfilename" are expected to point
6536/// to source files which will be included by the generated skeleton.
6537/// Method of the same name as the file(minus the extension and path)
6538/// will be called by the generated skeleton's Process method as follow:
6539/// ~~~ {.cpp}
6540/// [if (cutfilename())] htemp->Fill(macrofilename());
6541/// ~~~
6542/// "option" can be used select some of the optional features during
6543/// the code generation. The possible options are:
6544///
6545/// - nohist : indicates that the generated ProcessFill should not fill the histogram.
6546///
6547/// 'maxUnrolling' controls how deep in the class hierarchy does the
6548/// system 'unroll' classes that are not split. Unrolling a class
6549/// allows direct access to its data members (this emulates the behavior
6550/// of TTreeFormula).
6551///
6552/// The main features of this skeleton are:
6553///
6554/// * on-demand loading of branches
6555/// * ability to use the 'branchname' as if it was a data member
6556/// * protection against array out-of-bounds errors
6557/// * ability to use the branch data as an object (when the user code is available)
6558///
6559/// For example with Event.root, if
6560/// ~~~ {.cpp}
6561/// Double_t somePx = fTracks.fPx[2];
6562/// ~~~
6563/// is executed by one of the method of the skeleton,
6564/// somePx will updated with the current value of fPx of the 3rd track.
6565///
6566/// Both macrofilename and the optional cutfilename are expected to be
6567/// the name of source files which contain at least a free standing
6568/// function with the signature:
6569/// ~~~ {.cpp}
6570/// x_t macrofilename(); // i.e function with the same name as the file
6571/// ~~~
6572/// and
6573/// ~~~ {.cpp}
6574/// y_t cutfilename(); // i.e function with the same name as the file
6575/// ~~~
6576/// x_t and y_t needs to be types that can convert respectively to a double
6577/// and a bool (because the skeleton uses:
6578///
6579/// if (cutfilename()) htemp->Fill(macrofilename());
6580///
6581/// These two functions are run in a context such that the branch names are
6582/// available as local variables of the correct (read-only) type.
6583///
6584/// Note that if you use the same 'variable' twice, it is more efficient
6585/// to 'cache' the value. For example:
6586/// ~~~ {.cpp}
6587/// Int_t n = fEventNumber; // Read fEventNumber
6588/// if (n<10 || n>10) { ... }
6589/// ~~~
6590/// is more efficient than
6591/// ~~~ {.cpp}
6592/// if (fEventNumber<10 || fEventNumber>10)
6593/// ~~~
6594/// Also, optionally, the generated selector will also call methods named
6595/// macrofilename_methodname in each of 6 main selector methods if the method
6596/// macrofilename_methodname exist (Where macrofilename is stripped of its
6597/// extension).
6598///
6599/// Concretely, with the script named h1analysisProxy.C,
6600///
6601/// - The method calls the method (if it exist)
6602/// - Begin -> void h1analysisProxy_Begin(TTree*);
6603/// - SlaveBegin -> void h1analysisProxy_SlaveBegin(TTree*);
6604/// - Notify -> Bool_t h1analysisProxy_Notify();
6605/// - Process -> Bool_t h1analysisProxy_Process(Long64_t);
6606/// - SlaveTerminate -> void h1analysisProxy_SlaveTerminate();
6607/// - Terminate -> void h1analysisProxy_Terminate();
6608///
6609/// If a file name macrofilename.h (or .hh, .hpp, .hxx, .hPP, .hXX) exist
6610/// it is included before the declaration of the proxy class. This can
6611/// be used in particular to insure that the include files needed by
6612/// the macro file are properly loaded.
6613///
6614/// The default histogram is accessible via the variable named 'htemp'.
6615///
6616/// If the library of the classes describing the data in the branch is
6617/// loaded, the skeleton will add the needed `include` statements and
6618/// give the ability to access the object stored in the branches.
6619///
6620/// To draw px using the file hsimple.root (generated by the
6621/// hsimple.C tutorial), we need a file named hsimple.cxx:
6622/// ~~~ {.cpp}
6623/// double hsimple() {
6624/// return px;
6625/// }
6626/// ~~~
6627/// MakeProxy can then be used indirectly via the TTree::Draw interface
6628/// as follow:
6629/// ~~~ {.cpp}
6630/// new TFile("hsimple.root")
6631/// ntuple->Draw("hsimple.cxx");
6632/// ~~~
6633/// A more complete example is available in the tutorials directory:
6634/// h1analysisProxy.cxx , h1analysProxy.h and h1analysisProxyCut.C
6635/// which reimplement the selector found in h1analysis.C
6637Int_t TTree::MakeProxy(const char* proxyClassname, const char* macrofilename, const char* cutfilename, const char* option, Int_t maxUnrolling)
6638{
6639 GetPlayer();
6640 if (!fPlayer) return 0;
6641 return fPlayer->MakeProxy(proxyClassname,macrofilename,cutfilename,option,maxUnrolling);
6642}
6643
6644////////////////////////////////////////////////////////////////////////////////
6645/// Generate skeleton selector class for this tree.
6646///
6647/// The following files are produced: selector.h and selector.C.
6648/// If selector is 0, the selector will be called "nameoftree".
6649/// The option can be used to specify the branches that will have a data member.
6650/// - If option is "=legacy", a pre-ROOT6 selector will be generated (data
6651/// members and branch pointers instead of TTreeReaders).
6652/// - If option is empty, readers will be generated for each leaf.
6653/// - If option is "@", readers will be generated for the topmost branches.
6654/// - Individual branches can also be picked by their name:
6655/// - "X" generates readers for leaves of X.
6656/// - "@X" generates a reader for X as a whole.
6657/// - "@X;Y" generates a reader for X as a whole and also readers for the
6658/// leaves of Y.
6659/// - For further examples see the figure below.
6660///
6661/// \image html ttree_makeselector_option_examples.png
6662///
6663/// The generated code in selector.h includes the following:
6664/// - Identification of the original Tree and Input file name
6665/// - Definition of selector class (data and functions)
6666/// - The following class functions:
6667/// - constructor and destructor
6668/// - void Begin(TTree *tree)
6669/// - void SlaveBegin(TTree *tree)
6670/// - void Init(TTree *tree)
6671/// - Bool_t Notify()
6672/// - Bool_t Process(Long64_t entry)
6673/// - void Terminate()
6674/// - void SlaveTerminate()
6675///
6676/// The class selector derives from TSelector.
6677/// The generated code in selector.C includes empty functions defined above.
6678///
6679/// To use this function:
6680///
6681/// - connect your Tree file (eg: `TFile f("myfile.root");`)
6682/// - `T->MakeSelector("myselect");`
6683///
6684/// where T is the name of the Tree in file myfile.root
6685/// and myselect.h, myselect.C the name of the files created by this function.
6686/// In a ROOT session, you can do:
6687/// ~~~ {.cpp}
6688/// root > T->Process("myselect.C")
6689/// ~~~
6691Int_t TTree::MakeSelector(const char* selector, Option_t* option)
6692{
6693 TString opt(option);
6694 if(opt.EqualTo("=legacy", TString::ECaseCompare::kIgnoreCase)) {
6695 return MakeClass(selector, "selector");
6696 } else {
6697 GetPlayer();
6698 if (!fPlayer) return 0;
6699 return fPlayer->MakeReader(selector, option);
6700 }
6701}
6702
6703////////////////////////////////////////////////////////////////////////////////
6704/// Check if adding nbytes to memory we are still below MaxVirtualsize.
6707{
6708 if ((fTotalBuffers + nbytes) < fMaxVirtualSize) {
6709 return kFALSE;
6710 }
6711 return kTRUE;
6712}
6713
6714////////////////////////////////////////////////////////////////////////////////
6715/// Static function merging the trees in the TList into a new tree.
6716///
6717/// Trees in the list can be memory or disk-resident trees.
6718/// The new tree is created in the current directory (memory if gROOT).
6720TTree* TTree::MergeTrees(TList* li, Option_t* options)
6721{
6722 if (!li) return 0;
6723 TIter next(li);
6724 TTree *newtree = 0;
6725 TObject *obj;
6726
6727 while ((obj=next())) {
6728 if (!obj->InheritsFrom(TTree::Class())) continue;
6729 TTree *tree = (TTree*)obj;
6730 Long64_t nentries = tree->GetEntries();
6731 if (nentries == 0) continue;
6732 if (!newtree) {
6733 newtree = (TTree*)tree->CloneTree();
6734 if (!newtree) continue;
6735
6736 // Once the cloning is done, separate the trees,
6737 // to avoid as many side-effects as possible
6738 // The list of clones is guaranteed to exist since we
6739 // just cloned the tree.
6740 tree->GetListOfClones()->Remove(newtree);
6741 tree->ResetBranchAddresses();
6742 newtree->ResetBranchAddresses();
6743 continue;
6744 }
6745
6746 newtree->CopyAddresses(tree);
6747
6748 newtree->CopyEntries(tree,-1,options);
6749
6750 tree->ResetBranchAddresses(); // Disconnect from new tree.
6751 }
6752 if (newtree && newtree->GetTreeIndex()) {
6753 newtree->GetTreeIndex()->Append(0,kFALSE); // Force the sorting
6754 }
6755 return newtree;
6756}
6757
6758////////////////////////////////////////////////////////////////////////////////
6759/// Merge the trees in the TList into this tree.
6760///
6761/// Returns the total number of entries in the merged tree.
6764{
6765 if (!li) return 0;
6766 Long64_t storeAutoSave = fAutoSave;
6767 // Disable the autosave as the TFileMerge keeps a list of key and deleting the underlying
6768 // key would invalidate its iteration (or require costly measure to not use the deleted keys).
6769 // Also since this is part of a merging operation, the output file is not as precious as in
6770 // the general case since the input file should still be around.
6771 fAutoSave = 0;
6772 TIter next(li);
6773 TTree *tree;
6774 while ((tree = (TTree*)next())) {
6775 if (tree==this) continue;
6776 if (!tree->InheritsFrom(TTree::Class())) {
6777 Error("Add","Attempt to add object of class: %s to a %s", tree->ClassName(), ClassName());
6778 fAutoSave = storeAutoSave;
6779 return -1;
6780 }
6781
6782 Long64_t nentries = tree->GetEntries();
6783 if (nentries == 0) continue;
6784
6786
6787 CopyEntries(tree,-1,options);
6788
6789 tree->ResetBranchAddresses();
6790 }
6791 fAutoSave = storeAutoSave;
6792 return GetEntries();
6793}
6794
6795////////////////////////////////////////////////////////////////////////////////
6796/// Merge the trees in the TList into this tree.
6797/// If info->fIsFirst is true, first we clone this TTree info the directory
6798/// info->fOutputDirectory and then overlay the new TTree information onto
6799/// this TTree object (so that this TTree object is now the appropriate to
6800/// use for further merging).
6801///
6802/// Returns the total number of entries in the merged tree.
6805{
6806 const char *options = info ? info->fOptions.Data() : "";
6807 if (info && info->fIsFirst && info->fOutputDirectory && info->fOutputDirectory->GetFile() != GetCurrentFile()) {
6809 TIOFeatures saved_features = fIOFeatures;
6810 if (info->fIOFeatures) {
6811 fIOFeatures = *(info->fIOFeatures);
6812 }
6813 TTree *newtree = CloneTree(-1, options);
6814 fIOFeatures = saved_features;
6815 if (newtree) {
6816 newtree->Write();
6817 delete newtree;
6818 }
6819 // Make sure things are really written out to disk before attempting any reading.
6820 info->fOutputDirectory->GetFile()->Flush();
6821 info->fOutputDirectory->ReadTObject(this,this->GetName());
6822 }
6823 if (!li) return 0;
6824 Long64_t storeAutoSave = fAutoSave;
6825 // Disable the autosave as the TFileMerge keeps a list of key and deleting the underlying
6826 // key would invalidate its iteration (or require costly measure to not use the deleted keys).
6827 // Also since this is part of a merging operation, the output file is not as precious as in
6828 // the general case since the input file should still be around.
6829 fAutoSave = 0;
6830 TIter next(li);
6831 TTree *tree;
6832 while ((tree = (TTree*)next())) {
6833 if (tree==this) continue;
6834 if (!tree->InheritsFrom(TTree::Class())) {
6835 Error("Add","Attempt to add object of class: %s to a %s", tree->ClassName(), ClassName());
6836 fAutoSave = storeAutoSave;
6837 return -1;
6838 }
6839 // Copy MakeClass status.
6840 tree->SetMakeClass(fMakeClass);
6841
6842 // Copy branch addresses.
6844
6845 CopyEntries(tree,-1,options);
6846
6847 tree->ResetBranchAddresses();
6848 }
6849 fAutoSave = storeAutoSave;
6850 return GetEntries();
6851}
6852
6853////////////////////////////////////////////////////////////////////////////////
6854/// Move a cache from a file to the current file in dir.
6855/// if src is null no operation is done, if dir is null or there is no
6856/// current file the cache is deleted.
6858void TTree::MoveReadCache(TFile *src, TDirectory *dir)
6859{
6860 if (!src) return;
6861 TFile *dst = (dir && dir != gROOT) ? dir->GetFile() : 0;
6862 if (src == dst) return;
6863
6864 TTreeCache *pf = GetReadCache(src);
6865 if (dst) {
6866 src->SetCacheRead(0,this);
6867 dst->SetCacheRead(pf, this);
6868 } else {
6869 if (pf) {
6870 pf->WaitFinishPrefetch();
6871 }
6872 src->SetCacheRead(0,this);
6873 delete pf;
6874 }
6875}
6876
6877////////////////////////////////////////////////////////////////////////////////
6878/// Function called when loading a new class library.
6881{
6882 TIter next(GetListOfLeaves());
6883 TLeaf* leaf = 0;
6884 while ((leaf = (TLeaf*) next())) {
6885 leaf->Notify();
6886 leaf->GetBranch()->Notify();
6887 }
6888 return kTRUE;
6889}
6890
6891////////////////////////////////////////////////////////////////////////////////
6892/// This function may be called after having filled some entries in a Tree.
6893/// Using the information in the existing branch buffers, it will reassign
6894/// new branch buffer sizes to optimize time and memory.
6895///
6896/// The function computes the best values for branch buffer sizes such that
6897/// the total buffer sizes is less than maxMemory and nearby entries written
6898/// at the same time.
6899/// In case the branch compression factor for the data written so far is less
6900/// than compMin, the compression is disabled.
6901///
6902/// if option ="d" an analysis report is printed.
6904void TTree::OptimizeBaskets(ULong64_t maxMemory, Float_t minComp, Option_t *option)
6905{
6906 //Flush existing baskets if the file is writable
6907 if (this->GetDirectory()->IsWritable()) this->FlushBasketsImpl();
6908
6909 TString opt( option );
6910 opt.ToLower();
6911 Bool_t pDebug = opt.Contains("d");
6912 TObjArray *leaves = this->GetListOfLeaves();
6913 Int_t nleaves = leaves->GetEntries();
6914 Double_t treeSize = (Double_t)this->GetTotBytes();
6915
6916 if (nleaves == 0 || treeSize == 0) {
6917 // We're being called too early, we really have nothing to do ...
6918 return;
6919 }
6920 Double_t aveSize = treeSize/nleaves;
6921 UInt_t bmin = 512;
6922 UInt_t bmax = 256000;
6923 Double_t memFactor = 1;
6924 Int_t i, oldMemsize,newMemsize,oldBaskets,newBaskets;
6925 i = oldMemsize = newMemsize = oldBaskets = newBaskets = 0;
6926
6927 //we make two passes
6928 //one pass to compute the relative branch buffer sizes
6929 //a second pass to compute the absolute values
6930 for (Int_t pass =0;pass<2;pass++) {
6931 oldMemsize = 0; //to count size of baskets in memory with old buffer size
6932 newMemsize = 0; //to count size of baskets in memory with new buffer size
6933 oldBaskets = 0; //to count number of baskets with old buffer size
6934 newBaskets = 0; //to count number of baskets with new buffer size
6935 for (i=0;i<nleaves;i++) {
6936 TLeaf *leaf = (TLeaf*)leaves->At(i);
6937 TBranch *branch = leaf->GetBranch();
6938 Double_t totBytes = (Double_t)branch->GetTotBytes();
6939 Double_t idealFactor = totBytes/aveSize;
6940 UInt_t sizeOfOneEntry;
6941 if (branch->GetEntries() == 0) {
6942 // There is no data, so let's make a guess ...
6943 sizeOfOneEntry = aveSize;
6944 } else {
6945 sizeOfOneEntry = 1+(UInt_t)(totBytes / (Double_t)branch->GetEntries());
6946 }
6947 Int_t oldBsize = branch->GetBasketSize();
6948 oldMemsize += oldBsize;
6949 oldBaskets += 1+Int_t(totBytes/oldBsize);
6950 Int_t nb = branch->GetListOfBranches()->GetEntries();
6951 if (nb > 0) {
6952 newBaskets += 1+Int_t(totBytes/oldBsize);
6953 continue;
6954 }
6955 Double_t bsize = oldBsize*idealFactor*memFactor; //bsize can be very large !
6956 if (bsize < 0) bsize = bmax;
6957 if (bsize > bmax) bsize = bmax;
6958 UInt_t newBsize = UInt_t(bsize);
6959 if (pass) { // only on the second pass so that it doesn't interfere with scaling
6960 // If there is an entry offset, it will be stored in the same buffer as the object data; hence,
6961 // we must bump up the size of the branch to account for this extra footprint.
6962 // If fAutoFlush is not set yet, let's assume that it is 'in the process of being set' to
6963 // the value of GetEntries().
6964 Long64_t clusterSize = (fAutoFlush > 0) ? fAutoFlush : branch->GetEntries();
6965 if (branch->GetEntryOffsetLen()) {
6966 newBsize = newBsize + (clusterSize * sizeof(Int_t) * 2);
6967 }
6968 // We used ATLAS fully-split xAOD for testing, which is a rather unbalanced TTree, 10K branches,
6969 // with 8K having baskets smaller than 512 bytes. To achieve good I/O performance ATLAS uses auto-flush 100,
6970 // resulting in the smallest baskets being ~300-400 bytes, so this change increases their memory by about 8k*150B =~ 1MB,
6971 // at the same time it significantly reduces the number of total baskets because it ensures that all 100 entries can be
6972 // stored in a single basket (the old optimization tended to make baskets too small). In a toy example with fixed sized
6973 // structures we found a factor of 2 fewer baskets needed in the new scheme.
6974 // rounds up, increases basket size to ensure all entries fit into single basket as intended
6975 newBsize = newBsize - newBsize%512 + 512;
6976 }
6977 if (newBsize < sizeOfOneEntry) newBsize = sizeOfOneEntry;
6978 if (newBsize < bmin) newBsize = bmin;
6979 if (newBsize > 10000000) newBsize = bmax;
6980 if (pass) {
6981 if (pDebug) Info("OptimizeBaskets", "Changing buffer size from %6d to %6d bytes for %s\n",oldBsize,newBsize,branch->GetName());
6982 branch->SetBasketSize(newBsize);
6983 }
6984 newMemsize += newBsize;
6985 // For this number to be somewhat accurate when newBsize is 'low'
6986 // we do not include any space for meta data in the requested size (newBsize) even-though SetBasketSize will
6987 // not let it be lower than 100+TBranch::fEntryOffsetLen.
6988 newBaskets += 1+Int_t(totBytes/newBsize);
6989 if (pass == 0) continue;
6990 //Reset the compression level in case the compression factor is small
6991 Double_t comp = 1;
6992 if (branch->GetZipBytes() > 0) comp = totBytes/Double_t(branch->GetZipBytes());
6993 if (comp > 1 && comp < minComp) {
6994 if (pDebug) Info("OptimizeBaskets", "Disabling compression for branch : %s\n",branch->GetName());
6996 }
6997 }
6998 // coverity[divide_by_zero] newMemsize can not be zero as there is at least one leaf
6999 memFactor = Double_t(maxMemory)/Double_t(newMemsize);
7000 if (memFactor > 100) memFactor = 100;
7001 Double_t bmin_new = bmin*memFactor;
7002 Double_t bmax_new = bmax*memFactor;
7003 static const UInt_t hardmax = 1*1024*1024*1024; // Really, really never give more than 1Gb to a single buffer.
7004
7005 // Really, really never go lower than 8 bytes (we use this number
7006 // so that the calculation of the number of basket is consistent
7007 // but in fact SetBasketSize will not let the size go below
7008 // TBranch::fEntryOffsetLen + (100 + strlen(branch->GetName())
7009 // (The 2nd part being a slight over estimate of the key length.
7010 static const UInt_t hardmin = 8;
7011 bmin = (bmin_new > hardmax) ? hardmax : ( bmin_new < hardmin ? hardmin : (UInt_t)bmin_new );
7012 bmax = (bmax_new > hardmax) ? bmin : (UInt_t)bmax_new;
7013 }
7014 if (pDebug) {
7015 Info("OptimizeBaskets", "oldMemsize = %d, newMemsize = %d\n",oldMemsize, newMemsize);
7016 Info("OptimizeBaskets", "oldBaskets = %d, newBaskets = %d\n",oldBaskets, newBaskets);
7017 }
7018}
7019
7020////////////////////////////////////////////////////////////////////////////////
7021/// Interface to the Principal Components Analysis class.
7022///
7023/// Create an instance of TPrincipal
7024///
7025/// Fill it with the selected variables
7026///
7027/// - if option "n" is specified, the TPrincipal object is filled with
7028/// normalized variables.
7029/// - If option "p" is specified, compute the principal components
7030/// - If option "p" and "d" print results of analysis
7031/// - If option "p" and "h" generate standard histograms
7032/// - If option "p" and "c" generate code of conversion functions
7033/// - return a pointer to the TPrincipal object. It is the user responsibility
7034/// - to delete this object.
7035/// - The option default value is "np"
7036///
7037/// see TTree::Draw for explanation of the other parameters.
7038///
7039/// The created object is named "principal" and a reference to it
7040/// is added to the list of specials Root objects.
7041/// you can retrieve a pointer to the created object via:
7042/// ~~~ {.cpp}
7043/// TPrincipal *principal =
7044/// (TPrincipal*)gROOT->GetListOfSpecials()->FindObject("principal");
7045/// ~~~
7047TPrincipal* TTree::Principal(const char* varexp, const char* selection, Option_t* option, Long64_t nentries, Long64_t firstentry)
7048{
7049 GetPlayer();
7050 if (fPlayer) {
7051 return fPlayer->Principal(varexp, selection, option, nentries, firstentry);
7052 }
7053 return 0;
7054}
7055
7056////////////////////////////////////////////////////////////////////////////////
7057/// Print a summary of the tree contents.
7058///
7059/// - If option contains "all" friend trees are also printed.
7060/// - If option contains "toponly" only the top level branches are printed.
7061/// - If option contains "clusters" information about the cluster of baskets is printed.
7062///
7063/// Wildcarding can be used to print only a subset of the branches, e.g.,
7064/// `T.Print("Elec*")` will print all branches with name starting with "Elec".
7066void TTree::Print(Option_t* option) const
7067{
7068 // We already have been visited while recursively looking
7069 // through the friends tree, let's return.
7070 if (kPrint & fFriendLockStatus) {
7071 return;
7072 }
7073 Int_t s = 0;
7074 Int_t skey = 0;
7075 if (fDirectory) {
7076 TKey* key = fDirectory->GetKey(GetName());
7077 if (key) {
7078 skey = key->GetKeylen();
7079 s = key->GetNbytes();
7080 }
7081 }
7082 Long64_t total = skey;
7083 Long64_t zipBytes = GetZipBytes();
7084 if (zipBytes > 0) {
7085 total += GetTotBytes();
7086 }
7088 TTree::Class()->WriteBuffer(b, (TTree*) this);
7089 total += b.Length();
7090 Long64_t file = zipBytes + s;
7091 Float_t cx = 1;
7092 if (zipBytes) {
7093 cx = (GetTotBytes() + 0.00001) / zipBytes;
7094 }
7095 Printf("******************************************************************************");
7096 Printf("*Tree :%-10s: %-54s *", GetName(), GetTitle());
7097 Printf("*Entries : %8lld : Total = %15lld bytes File Size = %10lld *", fEntries, total, file);
7098 Printf("* : : Tree compression factor = %6.2f *", cx);
7099 Printf("******************************************************************************");
7100
7101 // Avoid many check of option validity
7102 if (option == nullptr)
7103 option = "";
7104
7105 if (strncmp(option,"clusters",strlen("clusters"))==0) {
7106 Printf("%-16s %-16s %-16s %5s",
7107 "Cluster Range #", "Entry Start", "Last Entry", "Size");
7108 Int_t index= 0;
7109 Long64_t clusterRangeStart = 0;
7110 if (fNClusterRange) {
7111 for( ; index < fNClusterRange; ++index) {
7112 Printf("%-16d %-16lld %-16lld %5lld",
7113 index, clusterRangeStart, fClusterRangeEnd[index], fClusterSize[index]);
7114 clusterRangeStart = fClusterRangeEnd[index] + 1;
7115 }
7116 }
7117 Printf("%-16d %-16lld %-16lld %5lld",
7118 index, clusterRangeStart, fEntries - 1, fAutoFlush);
7119 return;
7120 }
7121
7122 Int_t nl = const_cast<TTree*>(this)->GetListOfLeaves()->GetEntries();
7123 Int_t l;
7124 TBranch* br = 0;
7125 TLeaf* leaf = 0;
7126 if (strstr(option, "toponly")) {
7127 Long64_t *count = new Long64_t[nl];
7128 Int_t keep =0;
7129 for (l=0;l<nl;l++) {
7130 leaf = (TLeaf *)const_cast<TTree*>(this)->GetListOfLeaves()->At(l);
7131 br = leaf->GetBranch();
7132 if (strchr(br->GetName(),'.')) {
7133 count[l] = -1;
7134 count[keep] += br->GetZipBytes();
7135 } else {
7136 keep = l;
7137 count[keep] = br->GetZipBytes();
7138 }
7139 }
7140 for (l=0;l<nl;l++) {
7141 if (count[l] < 0) continue;
7142 leaf = (TLeaf *)const_cast<TTree*>(this)->GetListOfLeaves()->At(l);
7143 br = leaf->GetBranch();
7144 Printf("branch: %-20s %9lld\n",br->GetName(),count[l]);
7145 }
7146 delete [] count;
7147 } else {
7148 TString reg = "*";
7149 if (strlen(option) && strchr(option,'*')) reg = option;
7150 TRegexp re(reg,kTRUE);
7151 TIter next(const_cast<TTree*>(this)->GetListOfBranches());
7153 while ((br= (TBranch*)next())) {
7154 TString st = br->GetName();
7155 st.ReplaceAll("/","_");
7156 if (st.Index(re) == kNPOS) continue;
7157 br->Print(option);
7158 }
7159 }
7160
7161 //print TRefTable (if one)
7162 if (fBranchRef) fBranchRef->Print(option);
7163
7164 //print friends if option "all"
7165 if (!fFriends || !strstr(option,"all")) return;
7166 TIter nextf(fFriends);
7167 TFriendLock lock(const_cast<TTree*>(this),kPrint);
7168 TFriendElement *fr;
7169 while ((fr = (TFriendElement*)nextf())) {
7170 TTree * t = fr->GetTree();
7171 if (t) t->Print(option);
7172 }
7173}
7174
7175////////////////////////////////////////////////////////////////////////////////
7176/// Print statistics about the TreeCache for this tree.
7177/// Like:
7178/// ~~~ {.cpp}
7179/// ******TreeCache statistics for file: cms2.root ******
7180/// Reading 73921562 bytes in 716 transactions
7181/// Average transaction = 103.242405 Kbytes
7182/// Number of blocks in current cache: 202, total size : 6001193
7183/// ~~~
7184/// if option = "a" the list of blocks in the cache is printed
7186void TTree::PrintCacheStats(Option_t* option) const
7187{
7188 TFile *f = GetCurrentFile();
7189 if (!f) return;
7190 TTreeCache *tc = GetReadCache(f);
7191 if (tc) tc->Print(option);
7192}
7193
7194////////////////////////////////////////////////////////////////////////////////
7195/// Process this tree executing the TSelector code in the specified filename.
7196/// The return value is -1 in case of error and TSelector::GetStatus() in
7197/// in case of success.
7198///
7199/// The code in filename is loaded (interpreted or compiled, see below),
7200/// filename must contain a valid class implementation derived from TSelector,
7201/// where TSelector has the following member functions:
7202///
7203/// - `Begin()`: called every time a loop on the tree starts,
7204/// a convenient place to create your histograms.
7205/// - `SlaveBegin()`: called after Begin(), when on PROOF called only on the
7206/// slave servers.
7207/// - `Process()`: called for each event, in this function you decide what
7208/// to read and fill your histograms.
7209/// - `SlaveTerminate`: called at the end of the loop on the tree, when on PROOF
7210/// called only on the slave servers.
7211/// - `Terminate()`: called at the end of the loop on the tree,
7212/// a convenient place to draw/fit your histograms.
7213///
7214/// If filename is of the form file.C, the file will be interpreted.
7215///
7216/// If filename is of the form file.C++, the file file.C will be compiled
7217/// and dynamically loaded.
7218///
7219/// If filename is of the form file.C+, the file file.C will be compiled
7220/// and dynamically loaded. At next call, if file.C is older than file.o
7221/// and file.so, the file.C is not compiled, only file.so is loaded.
7222///
7223/// ## NOTE1
7224///
7225/// It may be more interesting to invoke directly the other Process function
7226/// accepting a TSelector* as argument.eg
7227/// ~~~ {.cpp}
7228/// MySelector *selector = (MySelector*)TSelector::GetSelector(filename);
7229/// selector->CallSomeFunction(..);
7230/// mytree.Process(selector,..);
7231/// ~~~
7232/// ## NOTE2
7233//
7234/// One should not call this function twice with the same selector file
7235/// in the same script. If this is required, proceed as indicated in NOTE1,
7236/// by getting a pointer to the corresponding TSelector,eg
7237///
7238/// ### Workaround 1
7239///
7240/// ~~~ {.cpp}
7241/// void stubs1() {
7242/// TSelector *selector = TSelector::GetSelector("h1test.C");
7243/// TFile *f1 = new TFile("stubs_nood_le1.root");
7244/// TTree *h1 = (TTree*)f1->Get("h1");
7245/// h1->Process(selector);
7246/// TFile *f2 = new TFile("stubs_nood_le1_coarse.root");
7247/// TTree *h2 = (TTree*)f2->Get("h1");
7248/// h2->Process(selector);
7249/// }
7250/// ~~~
7251/// or use ACLIC to compile the selector
7252///
7253/// ### Workaround 2
7254///
7255/// ~~~ {.cpp}
7256/// void stubs2() {
7257/// TFile *f1 = new TFile("stubs_nood_le1.root");
7258/// TTree *h1 = (TTree*)f1->Get("h1");
7259/// h1->Process("h1test.C+");
7260/// TFile *f2 = new TFile("stubs_nood_le1_coarse.root");
7261/// TTree *h2 = (TTree*)f2->Get("h1");
7262/// h2->Process("h1test.C+");
7263/// }
7264/// ~~~
7266Long64_t TTree::Process(const char* filename, Option_t* option, Long64_t nentries, Long64_t firstentry)
7267{
7268 GetPlayer();
7269 if (fPlayer) {
7270 return fPlayer->Process(filename, option, nentries, firstentry);
7271 }
7272 return -1;
7273}
7274
7275////////////////////////////////////////////////////////////////////////////////
7276/// Process this tree executing the code in the specified selector.
7277/// The return value is -1 in case of error and TSelector::GetStatus() in
7278/// in case of success.
7279///
7280/// The TSelector class has the following member functions:
7281///
7282/// - `Begin()`: called every time a loop on the tree starts,
7283/// a convenient place to create your histograms.
7284/// - `SlaveBegin()`: called after Begin(), when on PROOF called only on the
7285/// slave servers.
7286/// - `Process()`: called for each event, in this function you decide what
7287/// to read and fill your histograms.
7288/// - `SlaveTerminate`: called at the end of the loop on the tree, when on PROOF
7289/// called only on the slave servers.
7290/// - `Terminate()`: called at the end of the loop on the tree,
7291/// a convenient place to draw/fit your histograms.
7292///
7293/// If the Tree (Chain) has an associated EventList, the loop is on the nentries
7294/// of the EventList, starting at firstentry, otherwise the loop is on the
7295/// specified Tree entries.
7297Long64_t TTree::Process(TSelector* selector, Option_t* option, Long64_t nentries, Long64_t firstentry)
7298{
7299 GetPlayer();
7300 if (fPlayer) {
7301 return fPlayer->Process(selector, option, nentries, firstentry);
7302 }
7303 return -1;
7304}
7305
7306////////////////////////////////////////////////////////////////////////////////
7307/// Make a projection of a tree using selections.
7308///
7309/// Depending on the value of varexp (described in Draw) a 1-D, 2-D, etc.,
7310/// projection of the tree will be filled in histogram hname.
7311/// Note that the dimension of hname must match with the dimension of varexp.
7312///
7314Long64_t TTree::Project(const char* hname, const char* varexp, const char* selection, Option_t* option, Long64_t nentries, Long64_t firstentry)
7315{
7316 TString var;
7317 var.Form("%s>>%s", varexp, hname);
7318 TString opt("goff");
7319 if (option) {
7320 opt.Form("%sgoff", option);
7321 }
7322 Long64_t nsel = Draw(var, selection, opt, nentries, firstentry);
7323 return nsel;
7324}
7325
7326////////////////////////////////////////////////////////////////////////////////
7327/// Loop over entries and return a TSQLResult object containing entries following selection.
7329TSQLResult* TTree::Query(const char* varexp, const char* selection, Option_t* option, Long64_t nentries, Long64_t firstentry)
7330{
7331 GetPlayer();
7332 if (fPlayer) {
7333 return fPlayer->Query(varexp, selection, option, nentries, firstentry);
7334 }
7335 return 0;
7336}
7337
7338////////////////////////////////////////////////////////////////////////////////
7339/// Create or simply read branches from filename.
7340///
7341/// if branchDescriptor = "" (default), it is assumed that the Tree descriptor
7342/// is given in the first line of the file with a syntax like
7343/// ~~~ {.cpp}
7344/// A/D:Table[2]/F:Ntracks/I:astring/C
7345/// ~~~
7346/// otherwise branchDescriptor must be specified with the above syntax.
7347///
7348/// - If the type of the first variable is not specified, it is assumed to be "/F"
7349/// - If the type of any other variable is not specified, the type of the previous
7350/// variable is assumed. eg
7351/// - `x:y:z` (all variables are assumed of type "F"
7352/// - `x/D:y:z` (all variables are of type "D"
7353/// - `x:y/D:z` (x is type "F", y and z of type "D"
7354///
7355/// delimiter allows for the use of another delimiter besides whitespace.
7356/// This provides support for direct import of common data file formats
7357/// like csv. If delimiter != ' ' and branchDescriptor == "", then the
7358/// branch description is taken from the first line in the file, but
7359/// delimiter is used for the branch names tokenization rather than ':'.
7360/// Note however that if the values in the first line do not use the
7361/// /[type] syntax, all variables are assumed to be of type "F".
7362/// If the filename ends with extensions .csv or .CSV and a delimiter is
7363/// not specified (besides ' '), the delimiter is automatically set to ','.
7364///
7365/// Lines in the input file starting with "#" are ignored. Leading whitespace
7366/// for each column data is skipped. Empty lines are skipped.
7367///
7368/// A TBranch object is created for each variable in the expression.
7369/// The total number of rows read from the file is returned.
7370///
7371/// ## FILLING a TTree WITH MULTIPLE INPUT TEXT FILES
7372///
7373/// To fill a TTree with multiple input text files, proceed as indicated above
7374/// for the first input file and omit the second argument for subsequent calls
7375/// ~~~ {.cpp}
7376/// T.ReadFile("file1.dat","branch descriptor");
7377/// T.ReadFile("file2.dat");
7378/// ~~~
7380Long64_t TTree::ReadFile(const char* filename, const char* branchDescriptor, char delimiter)
7381{
7382 std::ifstream in;
7383 in.open(filename);
7384 if (!in.good()) {
7385 Error("ReadFile","Cannot open file: %s",filename);
7386 return 0;
7387 }
7388 const char* ext = strrchr(filename, '.');
7389 if(ext != NULL && ((strcmp(ext, ".csv") == 0) || (strcmp(ext, ".CSV") == 0)) && delimiter == ' ') {
7390 delimiter = ',';
7391 }
7392 return ReadStream(in, branchDescriptor, delimiter);
7393}
7394
7395////////////////////////////////////////////////////////////////////////////////
7396/// Determine which newline this file is using.
7397/// Return '\\r' for Windows '\\r\\n' as that already terminates.
7399char TTree::GetNewlineValue(std::istream &inputStream)
7400{
7401 Long_t inPos = inputStream.tellg();
7402 char newline = '\n';
7403 while(1) {
7404 char c = 0;
7405 inputStream.get(c);
7406 if(!inputStream.good()) {
7407 Error("ReadStream","Error reading stream: no newline found.");
7408 return 0;
7409 }
7410 if(c == newline) break;
7411 if(c == '\r') {
7412 newline = '\r';
7413 break;
7414 }
7415 }
7416 inputStream.clear();
7417 inputStream.seekg(inPos);
7418 return newline;
7419}
7420
7421////////////////////////////////////////////////////////////////////////////////
7422/// Create or simply read branches from an input stream.
7423///
7424/// See reference information for TTree::ReadFile
7426Long64_t TTree::ReadStream(std::istream& inputStream, const char *branchDescriptor, char delimiter)
7427{
7428 char newline = 0;
7429 std::stringstream ss;
7430 std::istream *inTemp;
7431 Long_t inPos = inputStream.tellg();
7432 if (!inputStream.good()) {
7433 Error("ReadStream","Error reading stream");
7434 return 0;
7435 }
7436 if (inPos == -1) {
7437 ss << std::cin.rdbuf();
7438 newline = GetNewlineValue(ss);
7439 inTemp = &ss;
7440 } else {
7441 newline = GetNewlineValue(inputStream);
7442 inTemp = &inputStream;
7443 }
7444 std::istream& in = *inTemp;
7445 Long64_t nlines = 0;
7446
7447 TBranch *branch = 0;
7448 Int_t nbranches = fBranches.GetEntries();
7449 if (nbranches == 0) {
7450 char *bdname = new char[4000];
7451 char *bd = new char[100000];
7452 Int_t nch = 0;
7453 if (branchDescriptor) nch = strlen(branchDescriptor);
7454 // branch Descriptor is null, read its definition from the first line in the file
7455 if (!nch) {
7456 do {
7457 in.getline(bd, 100000, newline);
7458 if (!in.good()) {
7459 delete [] bdname;
7460 delete [] bd;
7461 Error("ReadStream","Error reading stream");
7462 return 0;
7463 }
7464 char *cursor = bd;
7465 while( isspace(*cursor) && *cursor != '\n' && *cursor != '\0') {
7466 ++cursor;
7467 }
7468 if (*cursor != '#' && *cursor != '\n' && *cursor != '\0') {
7469 break;
7470 }
7471 } while (true);
7472 ++nlines;
7473 nch = strlen(bd);
7474 } else {
7475 strlcpy(bd,branchDescriptor,100000);
7476 }
7477
7478 //parse the branch descriptor and create a branch for each element
7479 //separated by ":"
7480 void *address = &bd[90000];
7481 char *bdcur = bd;
7482 TString desc="", olddesc="F";
7483 char bdelim = ':';
7484 if(delimiter != ' ') {
7485 bdelim = delimiter;
7486 if (strchr(bdcur,bdelim)==0 && strchr(bdcur,':') != 0) {
7487 // revert to the default
7488 bdelim = ':';
7489 }
7490 }
7491 while (bdcur) {
7492 char *colon = strchr(bdcur,bdelim);
7493 if (colon) *colon = 0;
7494 strlcpy(bdname,bdcur,4000);
7495 char *slash = strchr(bdname,'/');
7496 if (slash) {
7497 *slash = 0;
7498 desc = bdcur;
7499 olddesc = slash+1;
7500 } else {
7501 desc.Form("%s/%s",bdname,olddesc.Data());
7502 }
7503 char *bracket = strchr(bdname,'[');
7504 if (bracket) {
7505 *bracket = 0;
7506 }
7507 branch = new TBranch(this,bdname,address,desc.Data(),32000);
7508 if (branch->IsZombie()) {
7509 delete branch;
7510 Warning("ReadStream","Illegal branch definition: %s",bdcur);
7511 } else {
7512 fBranches.Add(branch);
7513 branch->SetAddress(0);
7514 }
7515 if (!colon)break;
7516 bdcur = colon+1;
7517 }
7518 delete [] bdname;
7519 delete [] bd;
7520 }
7521
7522 nbranches = fBranches.GetEntries();
7523
7524 if (gDebug > 1) {
7525 Info("ReadStream", "Will use branches:");
7526 for (int i = 0 ; i < nbranches; ++i) {
7527 TBranch* br = (TBranch*) fBranches.At(i);
7528 Info("ReadStream", " %s: %s [%s]", br->GetName(),
7529 br->GetTitle(), br->GetListOfLeaves()->At(0)->IsA()->GetName());
7530 }
7531 if (gDebug > 3) {
7532 Info("ReadStream", "Dumping read tokens, format:");
7533 Info("ReadStream", "LLLLL:BBB:gfbe:GFBE:T");
7534 Info("ReadStream", " L: line number");
7535 Info("ReadStream", " B: branch number");
7536 Info("ReadStream", " gfbe: good / fail / bad / eof of token");
7537 Info("ReadStream", " GFBE: good / fail / bad / eof of file");
7538 Info("ReadStream", " T: Token being read");
7539 }
7540 }
7541
7542 //loop on all lines in the file
7543 Long64_t nGoodLines = 0;
7544 std::string line;
7545 const char sDelimBuf[2] = { delimiter, 0 };
7546 const char* sDelim = sDelimBuf;
7547 if (delimiter == ' ') {
7548 // ' ' really means whitespace
7549 sDelim = "[ \t]";
7550 }
7551 while(in.good()) {
7552 if (newline == '\r' && in.peek() == '\n') {
7553 // Windows, skip '\n':
7554 in.get();
7555 }
7556 std::getline(in, line, newline);
7557 ++nlines;
7558
7559 TString sLine(line);
7560 sLine = sLine.Strip(TString::kLeading); // skip leading whitespace
7561 if (sLine.IsNull()) {
7562 if (gDebug > 2) {
7563 Info("ReadStream", "Skipping empty line number %lld", nlines);
7564 }
7565 continue; // silently skip empty lines
7566 }
7567 if (sLine[0] == '#') {
7568 if (gDebug > 2) {
7569 Info("ReadStream", "Skipping comment line number %lld: '%s'",
7570 nlines, line.c_str());
7571 }
7572 continue;
7573 }
7574 if (gDebug > 2) {
7575 Info("ReadStream", "Parsing line number %lld: '%s'",
7576 nlines, line.c_str());
7577 }
7578
7579 // Loop on branches and read the branch values into their buffer
7580 branch = 0;
7581 TString tok; // one column's data
7582 TString leafData; // leaf data, possibly multiple tokens for e.g. /I[2]
7583 std::stringstream sToken; // string stream feeding leafData into leaves
7584 Ssiz_t pos = 0;
7585 Int_t iBranch = 0;
7586 Bool_t goodLine = kTRUE; // whether the row can be filled into the tree
7587 Int_t remainingLeafLen = 0; // remaining columns for the current leaf
7588 while (goodLine && iBranch < nbranches
7589 && sLine.Tokenize(tok, pos, sDelim)) {
7590 tok = tok.Strip(TString::kLeading); // skip leading whitespace
7591 if (tok.IsNull() && delimiter == ' ') {
7592 // 1 2 should not be interpreted as 1,,,2 but 1, 2.
7593 // Thus continue until we have a non-empty token.
7594 continue;
7595 }
7596
7597 if (!remainingLeafLen) {
7598 // next branch!
7599 branch = (TBranch*)fBranches.At(iBranch);
7600 }
7601 TLeaf *leaf = (TLeaf*)branch->GetListOfLeaves()->At(0);
7602 if (!remainingLeafLen) {
7603 remainingLeafLen = leaf->GetLen();
7604 if (leaf->GetMaximum() > 0) {
7605 // This is a dynamic leaf length, i.e. most likely a TLeafC's
7606 // string size. This still translates into one token:
7607 remainingLeafLen = 1;
7608 }
7609
7610 leafData = tok;
7611 } else {
7612 // append token to laf data:
7613 leafData += " ";
7614 leafData += tok;
7615 }
7616 --remainingLeafLen;
7617 if (remainingLeafLen) {
7618 // need more columns for this branch:
7619 continue;
7620 }
7621 ++iBranch;
7622
7623 // initialize stringstream with token
7624 sToken.clear();
7625 sToken.seekp(0, std::ios_base::beg);
7626 sToken.str(leafData.Data());
7627 sToken.seekg(0, std::ios_base::beg);
7628 leaf->ReadValue(sToken, 0 /* 0 = "all" */);
7629 if (gDebug > 3) {
7630 Info("ReadStream", "%5lld:%3d:%d%d%d%d:%d%d%d%d:%s",
7631 nlines, iBranch,
7632 (int)sToken.good(), (int)sToken.fail(),
7633 (int)sToken.bad(), (int)sToken.eof(),
7634 (int)in.good(), (int)in.fail(),
7635 (int)in.bad(), (int)in.eof(),
7636 sToken.str().c_str());
7637 }
7638
7639 // Error handling
7640 if (sToken.bad()) {
7641 // How could that happen for a stringstream?
7642 Warning("ReadStream",
7643 "Buffer error while reading data for branch %s on line %lld",
7644 branch->GetName(), nlines);
7645 } else if (!sToken.eof()) {
7646 if (sToken.fail()) {
7647 Warning("ReadStream",
7648 "Couldn't read formatted data in \"%s\" for branch %s on line %lld; ignoring line",
7649 tok.Data(), branch->GetName(), nlines);
7650 goodLine = kFALSE;
7651 } else {
7652 std::string remainder;
7653 std::getline(sToken, remainder, newline);
7654 if (!remainder.empty()) {
7655 Warning("ReadStream",
7656 "Ignoring trailing \"%s\" while reading data for branch %s on line %lld",
7657 remainder.c_str(), branch->GetName(), nlines);
7658 }
7659 }
7660 }
7661 } // tokenizer loop
7662
7663 if (iBranch < nbranches) {
7664 Warning("ReadStream",
7665 "Read too few columns (%d < %d) in line %lld; ignoring line",
7666 iBranch, nbranches, nlines);
7667 goodLine = kFALSE;
7668 } else if (pos != kNPOS) {
7669 sLine = sLine.Strip(TString::kTrailing);
7670 if (pos < sLine.Length()) {
7671 Warning("ReadStream",
7672 "Ignoring trailing \"%s\" while reading line %lld",
7673 sLine.Data() + pos - 1 /* also print delimiter */,
7674 nlines);
7675 }
7676 }
7677
7678 //we are now ready to fill the tree
7679 if (goodLine) {
7680 Fill();
7681 ++nGoodLines;
7682 }
7683 }
7684
7685 return nGoodLines;
7686}
7687
7688////////////////////////////////////////////////////////////////////////////////
7689/// Make sure that obj (which is being deleted or will soon be) is no
7690/// longer referenced by this TTree.
7693{
7694 if (obj == fEventList) {
7695 fEventList = 0;
7696 }
7697 if (obj == fEntryList) {
7698 fEntryList = 0;
7699 }
7700 if (fUserInfo) {
7702 }
7703 if (fPlayer == obj) {
7704 fPlayer = 0;
7705 }
7706 if (fTreeIndex == obj) {
7707 fTreeIndex = 0;
7708 }
7709 if (fAliases) {
7711 }
7712 if (fFriends) {
7714 }
7715}
7716
7717////////////////////////////////////////////////////////////////////////////////
7718/// Refresh contents of this tree and its branches from the current status on disk.
7719///
7720/// One can call this function in case the tree file is being
7721/// updated by another process.
7723void TTree::Refresh()
7724{
7725 if (!fDirectory->GetFile()) {
7726 return;
7727 }
7729 fDirectory->Remove(this);
7731 if (!tree) {
7732 return;
7733 }
7734 //copy info from tree header into this Tree
7735 fEntries = 0;
7736 fNClusterRange = 0;
7738
7739 fAutoSave = tree->fAutoSave;
7740 fEntries = tree->fEntries;
7741 fTotBytes = tree->GetTotBytes();
7742 fZipBytes = tree->GetZipBytes();
7743 fSavedBytes = tree->fSavedBytes;
7744 fTotalBuffers = tree->fTotalBuffers.load();
7745
7746 //loop on all branches and update them
7747 Int_t nleaves = fLeaves.GetEntriesFast();
7748 for (Int_t i = 0; i < nleaves; i++) {
7749 TLeaf* leaf = (TLeaf*) fLeaves.UncheckedAt(i);
7750 TBranch* branch = (TBranch*) leaf->GetBranch();
7751 branch->Refresh(tree->GetBranch(branch->GetName()));
7752 }
7754 fDirectory->Append(this);
7755 delete tree;
7756 tree = 0;
7757}
7758
7759////////////////////////////////////////////////////////////////////////////////
7760/// Remove a friend from the list of friends.
7762void TTree::RemoveFriend(TTree* oldFriend)
7763{
7764 // We already have been visited while recursively looking
7765 // through the friends tree, let return
7767 return;
7768 }
7769 if (!fFriends) {
7770 return;
7771 }
7772 TFriendLock lock(this, kRemoveFriend);
7773 TIter nextf(fFriends);
7774 TFriendElement* fe = 0;
7775 while ((fe = (TFriendElement*) nextf())) {
7776 TTree* friend_t = fe->GetTree();
7777 if (friend_t == oldFriend) {
7778 fFriends->Remove(fe);
7779 delete fe;
7780 fe = 0;
7781 }
7782 }
7783}
7784
7785////////////////////////////////////////////////////////////////////////////////
7786/// Reset baskets, buffers and entries count in all branches and leaves.
7788void TTree::Reset(Option_t* option)
7789{
7790 fNotify = 0;
7791 fEntries = 0;
7792 fNClusterRange = 0;
7793 fTotBytes = 0;
7794 fZipBytes = 0;
7795 fFlushedBytes = 0;
7796 fSavedBytes = 0;
7797 fTotalBuffers = 0;
7798 fChainOffset = 0;
7799 fReadEntry = -1;
7800
7801 delete fTreeIndex;
7802 fTreeIndex = 0;
7803
7805 for (Int_t i = 0; i < nb; ++i) {
7806 TBranch* branch = (TBranch*) fBranches.UncheckedAt(i);
7807 branch->Reset(option);
7808 }
7809
7810 if (fBranchRef) {
7811 fBranchRef->Reset();
7812 }
7813}
7814
7815////////////////////////////////////////////////////////////////////////////////
7816/// Resets the state of this TTree after a merge (keep the customization but
7817/// forget the data).
7820{
7821 fEntries = 0;
7822 fNClusterRange = 0;
7823 fTotBytes = 0;
7824 fZipBytes = 0;
7825 fSavedBytes = 0;
7826 fFlushedBytes = 0;
7827 fTotalBuffers = 0;
7828 fChainOffset = 0;
7829 fReadEntry = -1;
7830
7831 delete fTreeIndex;
7832 fTreeIndex = 0;
7833
7835 for (Int_t i = 0; i < nb; ++i) {
7836 TBranch* branch = (TBranch*) fBranches.UncheckedAt(i);
7837 branch->ResetAfterMerge(info);
7838 }
7839
7840 if (fBranchRef) {
7842 }
7843}
7844
7845////////////////////////////////////////////////////////////////////////////////
7846/// Tell all of our branches to set their addresses to zero.
7847///
7848/// Note: If any of our branches own any objects, they are deleted.
7851{
7852 if (br && br->GetTree()) {
7853 br->ResetAddress();
7854 }
7855}
7856
7857////////////////////////////////////////////////////////////////////////////////
7858/// Tell all of our branches to drop their current objects and allocate new ones.
7861{
7862 TObjArray* branches = GetListOfBranches();
7863 Int_t nbranches = branches->GetEntriesFast();
7864 for (Int_t i = 0; i < nbranches; ++i) {
7865 TBranch* branch = (TBranch*) branches->UncheckedAt(i);
7866 branch->ResetAddress();
7867 }
7868}
7869
7870////////////////////////////////////////////////////////////////////////////////
7871/// Loop over tree entries and print entries passing selection.
7872///
7873/// - If varexp is 0 (or "") then print only first 8 columns.
7874/// - If varexp = "*" print all columns.
7875///
7876/// Otherwise a columns selection can be made using "var1:var2:var3".
7877/// See TTreePlayer::Scan for more information
7879Long64_t TTree::Scan(const char* varexp, const char* selection, Option_t* option, Long64_t nentries, Long64_t firstentry)
7880{
7881 GetPlayer();
7882 if (fPlayer) {
7883 return fPlayer->Scan(varexp, selection, option, nentries, firstentry);
7884 }
7885 return -1;
7886}
7887
7888////////////////////////////////////////////////////////////////////////////////
7889/// Set a tree variable alias.
7890///
7891/// Set an alias for an expression/formula based on the tree 'variables'.
7892///
7893/// The content of 'aliasName' can be used in TTreeFormula (i.e. TTree::Draw,
7894/// TTree::Scan, TTreeViewer) and will be evaluated as the content of
7895/// 'aliasFormula'.
7896///
7897/// If the content of 'aliasFormula' only contains symbol names, periods and
7898/// array index specification (for example event.fTracks[3]), then
7899/// the content of 'aliasName' can be used as the start of symbol.
7900///
7901/// If the alias 'aliasName' already existed, it is replaced by the new
7902/// value.
7903///
7904/// When being used, the alias can be preceded by an eventual 'Friend Alias'
7905/// (see TTree::GetFriendAlias)
7906///
7907/// Return true if it was added properly.
7908///
7909/// For example:
7910/// ~~~ {.cpp}
7911/// tree->SetAlias("x1","(tdc1[1]-tdc1[0])/49");
7912/// tree->SetAlias("y1","(tdc1[3]-tdc1[2])/47");
7913/// tree->SetAlias("x2","(tdc2[1]-tdc2[0])/49");
7914/// tree->SetAlias("y2","(tdc2[3]-tdc2[2])/47");
7915/// tree->Draw("y2-y1:x2-x1");
7916///
7917/// tree->SetAlias("theGoodTrack","event.fTracks[3]");
7918/// tree->Draw("theGoodTrack.fPx"); // same as "event.fTracks[3].fPx"
7919/// ~~~
7921Bool_t TTree::SetAlias(const char* aliasName, const char* aliasFormula)
7922{
7923 if (!aliasName || !aliasFormula) {
7924 return kFALSE;
7925 }
7926 if (!aliasName[0] || !aliasFormula[0]) {
7927 return kFALSE;
7928 }
7929 if (!fAliases) {
7930 fAliases = new TList;
7931 } else {
7932 TNamed* oldHolder = (TNamed*) fAliases->FindObject(aliasName);
7933 if (oldHolder) {
7934 oldHolder->SetTitle(aliasFormula);
7935 return kTRUE;
7936 }
7937 }
7938 TNamed* holder = new TNamed(aliasName, aliasFormula);
7939 fAliases->Add(holder);
7940 return kTRUE;
7941}
7942
7943////////////////////////////////////////////////////////////////////////////////
7944/// This function may be called at the start of a program to change
7945/// the default value for fAutoFlush.
7946///
7947/// ### CASE 1 : autof > 0
7948///
7949/// autof is the number of consecutive entries after which TTree::Fill will
7950/// flush all branch buffers to disk.
7951///
7952/// ### CASE 2 : autof < 0
7953///
7954/// When filling the Tree the branch buffers will be flushed to disk when
7955/// more than autof bytes have been written to the file. At the first FlushBaskets
7956/// TTree::Fill will replace fAutoFlush by the current value of fEntries.
7957///
7958/// Calling this function with autof<0 is interesting when it is hard to estimate
7959/// the size of one entry. This value is also independent of the Tree.
7960///
7961/// The Tree is initialized with fAutoFlush=-30000000, ie that, by default,
7962/// the first AutoFlush will be done when 30 MBytes of data are written to the file.
7963///
7964/// ### CASE 3 : autof = 0
7965///
7966/// The AutoFlush mechanism is disabled.
7967///
7968/// Flushing the buffers at regular intervals optimize the location of
7969/// consecutive entries on the disk by creating clusters of baskets.
7970///
7971/// A cluster of baskets is a set of baskets that contains all
7972/// the data for a (consecutive) set of entries and that is stored
7973/// consecutively on the disk. When reading all the branches, this
7974/// is the minimum set of baskets that the TTreeCache will read.
7976void TTree::SetAutoFlush(Long64_t autof /* = -30000000 */ )
7977{
7978 // Implementation note:
7979 //
7980 // A positive value of autoflush determines the size (in number of entries) of
7981 // a cluster of baskets.
7982 //
7983 // If the value of autoflush is changed over time (this happens in
7984 // particular when the TTree results from fast merging many trees),
7985 // we record the values of fAutoFlush in the data members:
7986 // fClusterRangeEnd and fClusterSize.
7987 // In the code we refer to a range of entries where the size of the
7988 // cluster of baskets is the same (i.e the value of AutoFlush was
7989 // constant) is called a ClusterRange.
7990 //
7991 // The 2 arrays (fClusterRangeEnd and fClusterSize) have fNClusterRange
7992 // active (used) values and have fMaxClusterRange allocated entries.
7993 //
7994 // fClusterRangeEnd contains the last entries number of a cluster range.
7995 // In particular this means that the 'next' cluster starts at fClusterRangeEnd[]+1
7996 // fClusterSize contains the size in number of entries of all the cluster
7997 // within the given range.
7998 // The last range (and the only one if fNClusterRange is zero) start at
7999 // fNClusterRange[fNClusterRange-1]+1 and ends at the end of the TTree. The
8000 // size of the cluster in this range is given by the value of fAutoFlush.
8001 //
8002 // For example printing the beginning and end of each the ranges can be done by:
8003 //
8004 // Printf("%-16s %-16s %-16s %5s",
8005 // "Cluster Range #", "Entry Start", "Last Entry", "Size");
8006 // Int_t index= 0;
8007 // Long64_t clusterRangeStart = 0;
8008 // if (fNClusterRange) {
8009 // for( ; index < fNClusterRange; ++index) {
8010 // Printf("%-16d %-16lld %-16lld %5lld",
8011 // index, clusterRangeStart, fClusterRangeEnd[index], fClusterSize[index]);
8012 // clusterRangeStart = fClusterRangeEnd[index] + 1;
8013 // }
8014 // }
8015 // Printf("%-16d %-16lld %-16lld %5lld",
8016 // index, prevEntry, fEntries - 1, fAutoFlush);
8017 //
8018
8019 // Note: We store the entry number corresponding to the end of the cluster
8020 // rather than its start in order to avoid using the array if the cluster
8021 // size never varies (If there is only one value of AutoFlush for the whole TTree).
8022
8023 if( fAutoFlush != autof) {
8024 if ((fAutoFlush > 0 || autof > 0) && fFlushedBytes) {
8025 // The mechanism was already enabled, let's record the previous
8026 // cluster if needed.
8028 }
8029 fAutoFlush = autof;
8030 }
8031}
8032
8033////////////////////////////////////////////////////////////////////////////////
8034/// Mark the previous event as being at the end of the event cluster.
8035///
8036/// So, if fEntries is set to 10 (and this is the first cluster) when MarkEventCluster
8037/// is called, then the first cluster has 9 events.
8039{
8040 if (!fEntries) return;
8041
8042 if ( (fNClusterRange+1) > fMaxClusterRange ) {
8043 if (fMaxClusterRange) {
8044 // Resize arrays to hold a larger event cluster.
8045 Int_t newsize = TMath::Max(10,Int_t(2*fMaxClusterRange));
8047 newsize*sizeof(Long64_t),fMaxClusterRange*sizeof(Long64_t));
8049 newsize*sizeof(Long64_t),fMaxClusterRange*sizeof(Long64_t));
8050 fMaxClusterRange = newsize;
8051 } else {
8052 // Cluster ranges have never been initialized; create them now.
8053 fMaxClusterRange = 2;
8056 }
8057 }
8059 // If we are auto-flushing, then the cluster size is the same as the current auto-flush setting.
8060 if (fAutoFlush > 0) {
8061 // Even if the user triggers MarkEventRange prior to fAutoFlush being present, the TClusterIterator
8062 // will appropriately go to the next event range.
8064 // Otherwise, assume there is one cluster per event range (e.g., user is manually controlling the flush).
8065 } else if (fNClusterRange == 0) {
8067 } else {
8069 }
8071}
8072
8073////////////////////////////////////////////////////////////////////////////////
8074/// This function may be called at the start of a program to change
8075/// the default value for fAutoSave (and for SetAutoSave) is -300000000, ie 300 MBytes.
8076/// When filling the Tree the branch buffers as well as the Tree header
8077/// will be flushed to disk when the watermark is reached.
8078/// If fAutoSave is positive the watermark is reached when a multiple of fAutoSave
8079/// entries have been written.
8080/// If fAutoSave is negative the watermark is reached when -fAutoSave bytes
8081/// have been written to the file.
8082/// In case of a program crash, it will be possible to recover the data in the Tree
8083/// up to the last AutoSave point.
8085void TTree::SetAutoSave(Long64_t autos)
8086{
8087 fAutoSave = autos;
8088}
8089
8090////////////////////////////////////////////////////////////////////////////////
8091/// Set a branch's basket size.
8092///
8093/// bname is the name of a branch.
8094///
8095/// - if bname="*", apply to all branches.
8096/// - if bname="xxx*", apply to all branches with name starting with xxx
8097///
8098/// see TRegexp for wildcarding options
8099/// buffsize = branc basket size
8101void TTree::SetBasketSize(const char* bname, Int_t buffsize)
8102{
8103 Int_t nleaves = fLeaves.GetEntriesFast();
8104 TRegexp re(bname, kTRUE);
8105 Int_t nb = 0;
8106 for (Int_t i = 0; i < nleaves; i++) {
8107 TLeaf* leaf = (TLeaf*) fLeaves.UncheckedAt(i);
8108 TBranch* branch = (TBranch*) leaf->GetBranch();
8109 TString s = branch->GetName();
8110 if (strcmp(bname, branch->GetName()) && (s.Index(re) == kNPOS)) {
8111 continue;
8112 }
8113 nb++;
8114 branch->SetBasketSize(buffsize);
8115 }
8116 if (!nb) {
8117 Error("SetBasketSize", "unknown branch -> '%s'", bname);
8118 }
8119}
8120
8121////////////////////////////////////////////////////////////////////////////////
8122/// Change branch address, dealing with clone trees properly.
8123/// See TTree::CheckBranchAddressType for the semantic of the return value.
8124///
8125/// Note: See the comments in TBranchElement::SetAddress() for the
8126/// meaning of the addr parameter and the object ownership policy.
8128Int_t TTree::SetBranchAddress(const char* bname, void* addr, TBranch** ptr)
8129{
8130 TBranch* branch = GetBranch(bname);
8131 if (!branch) {
8132 if (ptr) *ptr = 0;
8133 Error("SetBranchAddress", "unknown branch -> %s", bname);
8134 return kMissingBranch;
8135 }
8136 return SetBranchAddressImp(branch,addr,ptr);
8137}
8138
8139////////////////////////////////////////////////////////////////////////////////
8140/// Verify the validity of the type of addr before calling SetBranchAddress.
8141/// See TTree::CheckBranchAddressType for the semantic of the return value.
8142///
8143/// Note: See the comments in TBranchElement::SetAddress() for the
8144/// meaning of the addr parameter and the object ownership policy.
8146Int_t TTree::SetBranchAddress(const char* bname, void* addr, TClass* ptrClass, EDataType datatype, Bool_t isptr)
8147{
8148 return SetBranchAddress(bname, addr, 0, ptrClass, datatype, isptr);
8149}
8150
8151////////////////////////////////////////////////////////////////////////////////
8152/// Verify the validity of the type of addr before calling SetBranchAddress.
8153/// See TTree::CheckBranchAddressType for the semantic of the return value.
8154///
8155/// Note: See the comments in TBranchElement::SetAddress() for the
8156/// meaning of the addr parameter and the object ownership policy.
8158Int_t TTree::SetBranchAddress(const char* bname, void* addr, TBranch** ptr, TClass* ptrClass, EDataType datatype, Bool_t isptr)
8159{
8160 TBranch* branch = GetBranch(bname);
8161 if (!branch) {
8162 if (ptr) *ptr = 0;
8163 Error("SetBranchAddress", "unknown branch -> %s", bname);
8164 return kMissingBranch;
8165 }
8166
8167 Int_t res = CheckBranchAddressType(branch, ptrClass, datatype, isptr);
8168
8169 // This will set the value of *ptr to branch.
8170 if (res >= 0) {
8171 // The check succeeded.
8172 if ((res & kNeedEnableDecomposedObj) && !branch->GetMakeClass())
8173 branch->SetMakeClass(kTRUE);
8174 SetBranchAddressImp(branch,addr,ptr);
8175 } else {
8176 if (ptr) *ptr = 0;
8177 }
8178 return res;
8179}
8180
8181////////////////////////////////////////////////////////////////////////////////
8182/// Change branch address, dealing with clone trees properly.
8183/// See TTree::CheckBranchAddressType for the semantic of the return value.
8184///
8185/// Note: See the comments in TBranchElement::SetAddress() for the
8186/// meaning of the addr parameter and the object ownership policy.
8188Int_t TTree::SetBranchAddressImp(TBranch *branch, void* addr, TBranch** ptr)
8189{
8190 if (ptr) {
8191 *ptr = branch;
8192 }
8193 if (fClones) {
8194 void* oldAddr = branch->GetAddress();
8195 TIter next(fClones);
8196 TTree* clone = 0;
8197 const char *bname = branch->GetName();
8198 while ((clone = (TTree*) next())) {
8199 TBranch* cloneBr = clone->GetBranch(bname);
8200 if (cloneBr && (cloneBr->GetAddress() == oldAddr)) {
8201 cloneBr->SetAddress(addr);
8202 }
8203 }
8204 }
8205 branch->SetAddress(addr);
8206 return kVoidPtr;
8207}
8208
8209////////////////////////////////////////////////////////////////////////////////
8210/// Set branch status to Process or DoNotProcess.
8211///
8212/// When reading a Tree, by default, all branches are read.
8213/// One can speed up considerably the analysis phase by activating
8214/// only the branches that hold variables involved in a query.
8215///
8216/// bname is the name of a branch.
8217///
8218/// - if bname="*", apply to all branches.
8219/// - if bname="xxx*", apply to all branches with name starting with xxx
8220///
8221/// see TRegexp for wildcarding options
8222///
8223/// - status = 1 branch will be processed
8224/// - = 0 branch will not be processed
8225///
8226/// Example:
8227///
8228/// Assume a tree T with sub-branches a,b,c,d,e,f,g,etc..
8229/// when doing T.GetEntry(i) all branches are read for entry i.
8230/// to read only the branches c and e, one can do
8231/// ~~~ {.cpp}
8232/// T.SetBranchStatus("*",0); //disable all branches
8233/// T.SetBranchStatus("c",1);
8234/// T.setBranchStatus("e",1);
8235/// T.GetEntry(i);
8236/// ~~~
8237/// bname is interpreted as a wildcarded TRegexp (see TRegexp::MakeWildcard).
8238/// Thus, "a*b" or "a.*b" matches branches starting with "a" and ending with
8239/// "b", but not any other branch with an "a" followed at some point by a
8240/// "b". For this second behavior, use "*a*b*". Note that TRegExp does not
8241/// support '|', and so you cannot select, e.g. track and shower branches
8242/// with "track|shower".
8243///
8244/// __WARNING! WARNING! WARNING!__
8245///
8246/// SetBranchStatus is matching the branch based on match of the branch
8247/// 'name' and not on the branch hierarchy! In order to be able to
8248/// selectively enable a top level object that is 'split' you need to make
8249/// sure the name of the top level branch is prefixed to the sub-branches'
8250/// name (by adding a dot ('.') at the end of the Branch creation and use the
8251/// corresponding bname.
8252///
8253/// I.e If your Tree has been created in split mode with a parent branch "parent."
8254/// (note the trailing dot).
8255/// ~~~ {.cpp}
8256/// T.SetBranchStatus("parent",1);
8257/// ~~~
8258/// will not activate the sub-branches of "parent". You should do:
8259/// ~~~ {.cpp}
8260/// T.SetBranchStatus("parent*",1);
8261/// ~~~
8262/// Without the trailing dot in the branch creation you have no choice but to
8263/// call SetBranchStatus explicitly for each of the sub branches.
8264///
8265/// An alternative to this function is to read directly and only
8266/// the interesting branches. Example:
8267/// ~~~ {.cpp}
8268/// TBranch *brc = T.GetBranch("c");
8269/// TBranch *bre = T.GetBranch("e");
8270/// brc->GetEntry(i);
8271/// bre->GetEntry(i);
8272/// ~~~
8273/// If found is not 0, the number of branch(es) found matching the regular
8274/// expression is returned in *found AND the error message 'unknown branch'
8275/// is suppressed.
8277void TTree::SetBranchStatus(const char* bname, Bool_t status, UInt_t* found)
8278{
8279 // We already have been visited while recursively looking
8280 // through the friends tree, let return
8282 return;
8283 }
8284
8285 if (0 == strcmp(bname, "")) {
8286 Error("SetBranchStatus", "Input regexp is an empty string: no match against branch names will be attempted.");
8287 return;
8288 }
8289
8290 TBranch *branch, *bcount, *bson;
8291 TLeaf *leaf, *leafcount;
8292
8293 Int_t i,j;
8294 Int_t nleaves = fLeaves.GetEntriesFast();
8295 TRegexp re(bname,kTRUE);
8296 Int_t nb = 0;
8297
8298 // first pass, loop on all branches
8299 // for leafcount branches activate/deactivate in function of status
8300 for (i=0;i<nleaves;i++) {
8301 leaf = (TLeaf*)fLeaves.UncheckedAt(i);
8302 branch = (TBranch*)leaf->GetBranch();
8303 TString s = branch->GetName();
8304 if (strcmp(bname,"*")) { //Regexp gives wrong result for [] in name
8305 TString longname;
8306 longname.Form("%s.%s",GetName(),branch->GetName());
8307 if (strcmp(bname,branch->GetName())
8308 && longname != bname
8309 && s.Index(re) == kNPOS) continue;
8310 }
8311 nb++;
8312 if (status) branch->ResetBit(kDoNotProcess);
8313 else branch->SetBit(kDoNotProcess);
8314 leafcount = leaf->GetLeafCount();
8315 if (leafcount) {
8316 bcount = leafcount->GetBranch();
8317 if (status) bcount->ResetBit(kDoNotProcess);
8318 else bcount->SetBit(kDoNotProcess);
8319 }
8320 }
8321 if (nb==0 && strchr(bname,'*')==0) {
8322 branch = GetBranch(bname);
8323 if (branch) {
8324 if (status) branch->ResetBit(kDoNotProcess);
8325 else branch->SetBit(kDoNotProcess);
8326 ++nb;
8327 }
8328 }
8329
8330 //search in list of friends
8331 UInt_t foundInFriend = 0;
8332 if (fFriends) {
8333 TFriendLock lock(this,kSetBranchStatus);
8334 TIter nextf(fFriends);
8335 TFriendElement *fe;
8336 TString name;
8337 while ((fe = (TFriendElement*)nextf())) {
8338 TTree *t = fe->GetTree();
8339 if (t==0) continue;
8340
8341 // If the alias is present replace it with the real name.
8342 char *subbranch = (char*)strstr(bname,fe->GetName());
8343 if (subbranch!=bname) subbranch = 0;
8344 if (subbranch) {
8345 subbranch += strlen(fe->GetName());
8346 if ( *subbranch != '.' ) subbranch = 0;
8347 else subbranch ++;
8348 }
8349 if (subbranch) {
8350 name.Form("%s.%s",t->GetName(),subbranch);
8351 } else {
8352 name = bname;
8353 }
8354 t->SetBranchStatus(name,status, &foundInFriend);
8355 }
8356 }
8357 if (!nb && !foundInFriend) {
8358 if (found==0) {
8359 if (status) {
8360 if (strchr(bname,'*') != 0)
8361 Error("SetBranchStatus", "No branch name is matching wildcard -> %s", bname);
8362 else
8363 Error("SetBranchStatus", "unknown branch -> %s", bname);
8364 } else {
8365 if (strchr(bname,'*') != 0)
8366 Warning("SetBranchStatus", "No branch name is matching wildcard -> %s", bname);
8367 else
8368 Warning("SetBranchStatus", "unknown branch -> %s", bname);
8369 }
8370 }
8371 return;
8372 }
8373 if (found) *found = nb + foundInFriend;
8374
8375 // second pass, loop again on all branches
8376 // activate leafcount branches for active branches only
8377 for (i = 0; i < nleaves; i++) {
8378 leaf = (TLeaf*)fLeaves.UncheckedAt(i);
8379 branch = (TBranch*)leaf->GetBranch();
8380 if (!branch->TestBit(kDoNotProcess)) {
8381 leafcount = leaf->GetLeafCount();
8382 if (leafcount) {
8383 bcount = leafcount->GetBranch();
8384 bcount->ResetBit(kDoNotProcess);
8385 }
8386 } else {
8387 //Int_t nbranches = branch->GetListOfBranches()->GetEntriesFast();
8388 Int_t nbranches = branch->GetListOfBranches()->GetEntries();
8389 for (j=0;j<nbranches;j++) {
8390 bson = (TBranch*)branch->GetListOfBranches()->UncheckedAt(j);
8391 if (!bson) continue;
8392 if (!bson->TestBit(kDoNotProcess)) {
8393 if (bson->GetNleaves() <= 0) continue;
8394 branch->ResetBit(kDoNotProcess);
8395 break;
8396 }
8397 }
8398 }
8399 }
8400}
8401
8402////////////////////////////////////////////////////////////////////////////////
8403/// Set the current branch style. (static function)
8404///
8405/// - style = 0 old Branch
8406/// - style = 1 new Bronch
8409{
8411}
8412
8413////////////////////////////////////////////////////////////////////////////////
8414/// Set maximum size of the file cache .
8415//
8416/// - if cachesize = 0 the existing cache (if any) is deleted.
8417/// - if cachesize = -1 (default) it is set to the AutoFlush value when writing
8418/// the Tree (default is 30 MBytes).
8419///
8420/// Returns:
8421/// - 0 size set, cache was created if possible
8422/// - -1 on error
8425{
8426 // remember that the user has requested an explicit cache setup
8428
8429 return SetCacheSizeAux(kFALSE, cacheSize);
8430}
8431
8432////////////////////////////////////////////////////////////////////////////////
8433/// Set the size of the file cache and create it if possible.
8434///
8435/// If autocache is true:
8436/// this may be an autocreated cache, possibly enlarging an existing
8437/// autocreated cache. The size is calculated. The value passed in cacheSize:
8438/// - cacheSize = 0 make cache if default cache creation is enabled
8439/// - cacheSize = -1 make a default sized cache in any case
8440///
8441/// If autocache is false:
8442/// this is a user requested cache. cacheSize is used to size the cache.
8443/// This cache should never be automatically adjusted.
8444///
8445/// Returns:
8446/// - 0 size set, or existing autosized cache almost large enough.
8447/// (cache was created if possible)
8448/// - -1 on error
8450Int_t TTree::SetCacheSizeAux(Bool_t autocache /* = kTRUE */, Long64_t cacheSize /* = 0 */ )
8451{
8452 if (autocache) {
8453 // used as a once only control for automatic cache setup
8455 }
8456
8457 if (!autocache) {
8458 // negative size means the user requests the default
8459 if (cacheSize < 0) {
8460 cacheSize = GetCacheAutoSize(kTRUE);
8461 }
8462 } else {
8463 if (cacheSize == 0) {
8464 cacheSize = GetCacheAutoSize();
8465 } else if (cacheSize < 0) {
8466 cacheSize = GetCacheAutoSize(kTRUE);
8467 }
8468 }
8469
8471 if (!file || GetTree() != this) {
8472 // if there's no file or we are not a plain tree (e.g. if we're a TChain)
8473 // do not create a cache, only record the size if one was given
8474 if (!autocache) {
8475 fCacheSize = cacheSize;
8476 }
8477 if (GetTree() != this) {
8478 return 0;
8479 }
8480 if (!autocache && cacheSize>0) {
8481 Warning("SetCacheSizeAux", "A TTreeCache could not be created because the TTree has no file");
8482 }
8483 return 0;
8484 }
8485
8486 // Check for an existing cache
8488 if (pf) {
8489 if (autocache) {
8490 // reset our cache status tracking in case existing cache was added
8491 // by the user without using one of the TTree methods
8492 fCacheSize = pf->GetBufferSize();
8494
8495 if (fCacheUserSet) {
8496 // existing cache was created by the user, don't change it
8497 return 0;
8498 }
8499 } else {
8500 // update the cache to ensure it records the user has explicitly
8501 // requested it
8503 }
8504
8505 // if we're using an automatically calculated size and the existing
8506 // cache is already almost large enough don't resize
8507 if (autocache && Long64_t(0.80*cacheSize) < fCacheSize) {
8508 // already large enough
8509 return 0;
8510 }
8511
8512 if (cacheSize == fCacheSize) {
8513 return 0;
8514 }
8515
8516 if (cacheSize == 0) {
8517 // delete existing cache
8518 pf->WaitFinishPrefetch();
8519 file->SetCacheRead(0,this);
8520 delete pf;
8521 pf = 0;
8522 } else {
8523 // resize
8524 Int_t res = pf->SetBufferSize(cacheSize);
8525 if (res < 0) {
8526 return -1;
8527 }
8528 }
8529 } else {
8530 // no existing cache
8531 if (autocache) {
8532 if (fCacheUserSet) {
8533 // value was already set manually.
8534 if (fCacheSize == 0) return 0;
8535 // Expected a cache should exist; perhaps the user moved it
8536 // Do nothing more here.
8537 if (cacheSize) {
8538 Error("SetCacheSizeAux", "Not setting up an automatically sized TTreeCache because of missing cache previously set");
8539 }
8540 return -1;
8541 }
8542 }
8543 }
8544
8545 fCacheSize = cacheSize;
8546 if (cacheSize == 0 || pf) {
8547 return 0;
8548 }
8549
8550#ifdef R__USE_IMT
8551 if(TTreeCacheUnzip::IsParallelUnzip() && file->GetCompressionLevel() > 0)
8552 pf = new TTreeCacheUnzip(this, cacheSize);
8553 else
8554#endif
8555 pf = new TTreeCache(this, cacheSize);
8556
8557 pf->SetAutoCreated(autocache);
8558
8559 return 0;
8560}
8561
8562////////////////////////////////////////////////////////////////////////////////
8563///interface to TTreeCache to set the cache entry range
8564///
8565/// Returns:
8566/// - 0 entry range set
8567/// - -1 on error
8570{
8571 if (!GetTree()) {
8572 if (LoadTree(0)<0) {
8573 Error("SetCacheEntryRange","Could not load a tree");
8574 return -1;
8575 }
8576 }
8577 if (GetTree()) {
8578 if (GetTree() != this) {
8579 return GetTree()->SetCacheEntryRange(first, last);
8580 }
8581 } else {
8582 Error("SetCacheEntryRange", "No tree is available. Could not set cache entry range");
8583 return -1;
8584 }
8585
8586 TFile *f = GetCurrentFile();
8587 if (!f) {
8588 Error("SetCacheEntryRange", "No file is available. Could not set cache entry range");
8589 return -1;
8590 }
8592 if (!tc) {
8593 Error("SetCacheEntryRange", "No cache is available. Could not set entry range");
8594 return -1;
8595 }
8596 tc->SetEntryRange(first,last);
8597 return 0;
8598}
8599
8600////////////////////////////////////////////////////////////////////////////////
8601/// Interface to TTreeCache to set the number of entries for the learning phase
8604{
8606}
8607
8608////////////////////////////////////////////////////////////////////////////////
8609/// Enable/Disable circularity for this tree.
8610///
8611/// if maxEntries > 0 a maximum of maxEntries is kept in one buffer/basket
8612/// per branch in memory.
8613/// Note that when this function is called (maxEntries>0) the Tree
8614/// must be empty or having only one basket per branch.
8615/// if maxEntries <= 0 the tree circularity is disabled.
8616///
8617/// #### NOTE 1:
8618/// Circular Trees are interesting in online real time environments
8619/// to store the results of the last maxEntries events.
8620/// #### NOTE 2:
8621/// Calling SetCircular with maxEntries <= 0 is necessary before
8622/// merging circular Trees that have been saved on files.
8623/// #### NOTE 3:
8624/// SetCircular with maxEntries <= 0 is automatically called
8625/// by TChain::Merge
8626/// #### NOTE 4:
8627/// A circular Tree can still be saved in a file. When read back,
8628/// it is still a circular Tree and can be filled again.
8630void TTree::SetCircular(Long64_t maxEntries)
8631{
8632 if (maxEntries <= 0) {
8633 // Disable circularity.
8634 fMaxEntries = 1000000000;
8635 fMaxEntries *= 1000;
8637 //in case the Tree was originally created in gROOT, the branch
8638 //compression level was set to -1. If the Tree is now associated to
8639 //a file, reset the compression level to the file compression level
8640 if (fDirectory) {
8641 TFile* bfile = fDirectory->GetFile();
8643 if (bfile) {
8644 compress = bfile->GetCompressionSettings();
8645 }
8647 for (Int_t i = 0; i < nb; i++) {
8648 TBranch* branch = (TBranch*) fBranches.UncheckedAt(i);
8649 branch->SetCompressionSettings(compress);
8650 }
8651 }
8652 } else {
8653 // Enable circularity.
8654 fMaxEntries = maxEntries;
8656 }
8657}
8658
8659////////////////////////////////////////////////////////////////////////////////
8660/// Set the debug level and the debug range.
8661///
8662/// For entries in the debug range, the functions TBranchElement::Fill
8663/// and TBranchElement::GetEntry will print the number of bytes filled
8664/// or read for each branch.
8666void TTree::SetDebug(Int_t level, Long64_t min, Long64_t max)
8667{
8668 fDebug = level;
8669 fDebugMin = min;
8670 fDebugMax = max;
8671}
8672
8673////////////////////////////////////////////////////////////////////////////////
8674/// Update the default value for the branch's fEntryOffsetLen.
8675/// If updateExisting is true, also update all the existing branches.
8676/// If newdefault is less than 10, the new default value will be 10.
8678void TTree::SetDefaultEntryOffsetLen(Int_t newdefault, Bool_t updateExisting)
8679{
8680 if (newdefault < 10) {
8681 newdefault = 10;
8682 }
8683 fDefaultEntryOffsetLen = newdefault;
8684 if (updateExisting) {
8685 TIter next( GetListOfBranches() );
8686 TBranch *b;
8687 while ( ( b = (TBranch*)next() ) ) {
8688 b->SetEntryOffsetLen( newdefault, kTRUE );
8689 }
8690 if (fBranchRef) {
8691 fBranchRef->SetEntryOffsetLen( newdefault, kTRUE );
8692 }
8693 }
8694}
8695
8696////////////////////////////////////////////////////////////////////////////////
8697/// Change the tree's directory.
8698///
8699/// Remove reference to this tree from current directory and
8700/// add reference to new directory dir. The dir parameter can
8701/// be 0 in which case the tree does not belong to any directory.
8702///
8705{
8706 if (fDirectory == dir) {
8707 return;
8708 }
8709 if (fDirectory) {
8710 fDirectory->Remove(this);
8711
8712 // Delete or move the file cache if it points to this Tree
8714 MoveReadCache(file,dir);
8715 }
8716 fDirectory = dir;
8717 if (fDirectory) {
8718 fDirectory->Append(this);
8719 }
8720 TFile* file = 0;
8721 if (fDirectory) {
8722 file = fDirectory->GetFile();
8723 }
8724 if (fBranchRef) {
8726 }
8727 TBranch* b = 0;
8728 TIter next(GetListOfBranches());
8729 while((b = (TBranch*) next())) {
8730 b->SetFile(file);
8731 }
8732}
8733
8734////////////////////////////////////////////////////////////////////////////////
8735/// Change number of entries in the tree.
8736///
8737/// If n >= 0, set number of entries in the tree = n.
8738///
8739/// If n < 0, set number of entries in the tree to match the
8740/// number of entries in each branch. (default for n is -1)
8741///
8742/// This function should be called only when one fills each branch
8743/// independently via TBranch::Fill without calling TTree::Fill.
8744/// Calling TTree::SetEntries() make sense only if the number of entries
8745/// in each branch is identical, a warning is issued otherwise.
8746/// The function returns the number of entries.
8747///
8750{
8751 // case 1 : force number of entries to n
8752 if (n >= 0) {
8753 fEntries = n;
8754 return n;
8755 }
8756
8757 // case 2; compute the number of entries from the number of entries in the branches
8758 TBranch* b(nullptr), *bMin(nullptr), *bMax(nullptr);
8759 Long64_t nMin = kMaxEntries;
8760 Long64_t nMax = 0;
8761 TIter next(GetListOfBranches());
8762 while((b = (TBranch*) next())){
8763 Long64_t n2 = b->GetEntries();
8764 if (!bMin || n2 < nMin) {
8765 nMin = n2;
8766 bMin = b;
8767 }
8768 if (!bMax || n2 > nMax) {
8769 nMax = n2;
8770 bMax = b;
8771 }
8772 }
8773 if (bMin && nMin != nMax) {
8774 Warning("SetEntries", "Tree branches have different numbers of entries, eg %s has %lld entries while %s has %lld entries.",
8775 bMin->GetName(), nMin, bMax->GetName(), nMax);
8776 }
8777 fEntries = nMax;
8778 return fEntries;
8779}
8780
8781////////////////////////////////////////////////////////////////////////////////
8782/// Set an EntryList
8784void TTree::SetEntryList(TEntryList *enlist, Option_t * /*opt*/)
8785{
8786 if (fEntryList) {
8787 //check if the previous entry list is owned by the tree
8789 delete fEntryList;
8790 }
8791 }
8792 fEventList = 0;
8793 if (!enlist) {
8794 fEntryList = 0;
8795 return;
8796 }
8797 fEntryList = enlist;
8798 fEntryList->SetTree(this);
8799
8800}
8801
8802////////////////////////////////////////////////////////////////////////////////
8803/// This function transfroms the given TEventList into a TEntryList
8804/// The new TEntryList is owned by the TTree and gets deleted when the tree
8805/// is deleted. This TEntryList can be returned by GetEntryList() function.
8807void TTree::SetEventList(TEventList *evlist)
8808{
8809 fEventList = evlist;
8810 if (fEntryList){
8812 TEntryList *tmp = fEntryList;
8813 fEntryList = 0; // Avoid problem with RecursiveRemove.
8814 delete tmp;
8815 } else {
8816 fEntryList = 0;
8817 }
8818 }
8819
8820 if (!evlist) {
8821 fEntryList = 0;
8822 fEventList = 0;
8823 return;
8824 }
8825
8826 fEventList = evlist;
8827 char enlistname[100];
8828 snprintf(enlistname,100, "%s_%s", evlist->GetName(), "entrylist");
8829 fEntryList = new TEntryList(enlistname, evlist->GetTitle());
8830 fEntryList->SetDirectory(0); // We own this.
8831 Int_t nsel = evlist->GetN();
8832 fEntryList->SetTree(this);
8833 Long64_t entry;
8834 for (Int_t i=0; i<nsel; i++){
8835 entry = evlist->GetEntry(i);
8836 fEntryList->Enter(entry);
8837 }
8840}
8841
8842////////////////////////////////////////////////////////////////////////////////
8843/// Set number of entries to estimate variable limits.
8844/// If n is -1, the estimate is set to be the current maximum
8845/// for the tree (i.e. GetEntries() + 1)
8846/// If n is less than -1, the behavior is undefined.
8848void TTree::SetEstimate(Long64_t n /* = 1000000 */)
8849{
8850 if (n == 0) {
8851 n = 10000;
8852 } else if (n < 0) {
8853 n = fEntries - n;
8854 }
8855 fEstimate = n;
8856 GetPlayer();
8857 if (fPlayer) {
8859 }
8860}
8861
8862////////////////////////////////////////////////////////////////////////////////
8863/// Provide the end-user with the ability to enable/disable various experimental
8864/// IO features for this TTree.
8865///
8866/// Returns all the newly-set IO settings.
8869{
8870 // Purposely ignore all unsupported bits; TIOFeatures implementation already warned the user about the
8871 // error of their ways; this is just a safety check.
8872 UChar_t featuresRequested = features.GetFeatures() & static_cast<UChar_t>(TBasket::EIOBits::kSupported);
8873
8874 UChar_t curFeatures = fIOFeatures.GetFeatures();
8875 UChar_t newFeatures = ~curFeatures & featuresRequested;
8876 curFeatures |= newFeatures;
8877 fIOFeatures.Set(curFeatures);
8878
8879 ROOT::TIOFeatures newSettings(newFeatures);
8880 return newSettings;
8881}
8882
8883////////////////////////////////////////////////////////////////////////////////
8884/// Set fFileNumber to number.
8885/// fFileNumber is used by TTree::Fill to set the file name
8886/// for a new file to be created when the current file exceeds fgTreeMaxSize.
8887/// (see TTree::ChangeFile)
8888/// if fFileNumber=10, the new file name will have a suffix "_11",
8889/// ie, fFileNumber is incremented before setting the file name
8891void TTree::SetFileNumber(Int_t number)
8892{
8893 if (fFileNumber < 0) {
8894 Warning("SetFileNumber", "file number must be positive. Set to 0");
8895 fFileNumber = 0;
8896 return;
8897 }
8898 fFileNumber = number;
8899}
8900
8901////////////////////////////////////////////////////////////////////////////////
8902/// Set all the branches in this TTree to be in decomposed object mode
8903/// (also known as MakeClass mode).
8904///
8905/// For MakeClass mode 0, the TTree expects the address where the data is stored
8906/// to be set by either the user or the TTree to the address of a full object
8907/// through the top level branch.
8908/// For MakeClass mode 1, this address is expected to point to a numerical type
8909/// or C-style array (variable or not) of numerical type, representing the
8910/// primitive data members.
8911/// The function's primary purpose is to allow the user to access the data
8912/// directly with numerical type variable rather than having to have the original
8913/// set of classes (or a reproduction thereof).
8916{
8917 fMakeClass = make;
8918
8920 for (Int_t i = 0; i < nb; ++i) {
8921 TBranch* branch = (TBranch*) fBranches.UncheckedAt(i);
8922 branch->SetMakeClass(make);
8923 }
8924}
8925
8926////////////////////////////////////////////////////////////////////////////////
8927/// Set the maximum size in bytes of a Tree file (static function).
8928/// The default size is 100000000000LL, ie 100 Gigabytes.
8929///
8930/// In TTree::Fill, when the file has a size > fgMaxTreeSize,
8931/// the function closes the current file and starts writing into
8932/// a new file with a name of the style "file_1.root" if the original
8933/// requested file name was "file.root".
8935void TTree::SetMaxTreeSize(Long64_t maxsize)
8936{
8937 fgMaxTreeSize = maxsize;
8938}
8939
8940////////////////////////////////////////////////////////////////////////////////
8941/// Change the name of this tree.
8943void TTree::SetName(const char* name)
8944{
8945 if (gPad) {
8946 gPad->Modified();
8947 }
8948 // Trees are named objects in a THashList.
8949 // We must update hashlists if we change the name.
8950 TFile *file = 0;
8951 TTreeCache *pf = 0;
8952 if (fDirectory) {
8953 fDirectory->Remove(this);
8954 if ((file = GetCurrentFile())) {
8955 pf = GetReadCache(file);
8956 file->SetCacheRead(0,this,TFile::kDoNotDisconnect);
8957 }
8958 }
8959 // This changes our hash value.
8960 fName = name;
8961 if (fDirectory) {
8962 fDirectory->Append(this);
8963 if (pf) {
8964 file->SetCacheRead(pf,this,TFile::kDoNotDisconnect);
8965 }
8966 }
8967}
8968
8969////////////////////////////////////////////////////////////////////////////////
8970/// Change the name and title of this tree.
8972void TTree::SetObject(const char* name, const char* title)
8973{
8974 if (gPad) {
8975 gPad->Modified();
8976 }
8977
8978 // Trees are named objects in a THashList.
8979 // We must update hashlists if we change the name
8980 TFile *file = 0;
8981 TTreeCache *pf = 0;
8982 if (fDirectory) {
8983 fDirectory->Remove(this);
8984 if ((file = GetCurrentFile())) {
8985 pf = GetReadCache(file);
8986 file->SetCacheRead(0,this,TFile::kDoNotDisconnect);
8987 }
8988 }
8989 // This changes our hash value.
8990 fName = name;
8991 fTitle = title;
8992 if (fDirectory) {
8993 fDirectory->Append(this);
8994 if (pf) {
8995 file->SetCacheRead(pf,this,TFile::kDoNotDisconnect);
8996 }
8997 }
8998}
8999
9000////////////////////////////////////////////////////////////////////////////////
9001/// Enable or disable parallel unzipping of Tree buffers.
9003void TTree::SetParallelUnzip(Bool_t opt, Float_t RelSize)
9004{
9005#ifdef R__USE_IMT
9006 if (GetTree() == 0) {
9008 if (!GetTree())
9009 return;
9010 }
9011 if (GetTree() != this) {
9012 GetTree()->SetParallelUnzip(opt, RelSize);
9013 return;
9014 }
9016 if (!file)
9017 return;
9018
9020 if (pf && !( opt ^ (nullptr != dynamic_cast<TTreeCacheUnzip*>(pf)))) {
9021 // done with opt and type are in agreement.
9022 return;
9023 }
9024 delete pf;
9025 auto cacheSize = GetCacheAutoSize(kTRUE);
9026 if (opt) {
9027 auto unzip = new TTreeCacheUnzip(this, cacheSize);
9028 unzip->SetUnzipBufferSize( Long64_t(cacheSize * RelSize) );
9029 } else {
9030 pf = new TTreeCache(this, cacheSize);
9031 }
9032#else
9033 (void)opt;
9034 (void)RelSize;
9035#endif
9036}
9037
9038////////////////////////////////////////////////////////////////////////////////
9039/// Set perf stats
9042{
9043 fPerfStats = perf;
9044}
9045
9046////////////////////////////////////////////////////////////////////////////////
9047/// The current TreeIndex is replaced by the new index.
9048/// Note that this function does not delete the previous index.
9049/// This gives the possibility to play with more than one index, e.g.,
9050/// ~~~ {.cpp}
9051/// TVirtualIndex* oldIndex = tree.GetTreeIndex();
9052/// tree.SetTreeIndex(newIndex);
9053/// tree.Draw();
9054/// tree.SetTreeIndex(oldIndex);
9055/// tree.Draw(); etc
9056/// ~~~
9059{
9060 if (fTreeIndex) {
9061 fTreeIndex->SetTree(0);
9062 }
9063 fTreeIndex = index;
9064}
9065
9066////////////////////////////////////////////////////////////////////////////////
9067/// Set tree weight.
9068///
9069/// The weight is used by TTree::Draw to automatically weight each
9070/// selected entry in the resulting histogram.
9071///
9072/// For example the equivalent of:
9073/// ~~~ {.cpp}
9074/// T.Draw("x", "w")
9075/// ~~~
9076/// is:
9077/// ~~~ {.cpp}
9078/// T.SetWeight(w);
9079/// T.Draw("x");
9080/// ~~~
9081/// This function is redefined by TChain::SetWeight. In case of a
9082/// TChain, an option "global" may be specified to set the same weight
9083/// for all trees in the TChain instead of the default behaviour
9084/// using the weights of each tree in the chain (see TChain::SetWeight).
9087{
9088 fWeight = w;
9089}
9090
9091////////////////////////////////////////////////////////////////////////////////
9092/// Print values of all active leaves for entry.
9093///
9094/// - if entry==-1, print current entry (default)
9095/// - if a leaf is an array, a maximum of lenmax elements is printed.
9097void TTree::Show(Long64_t entry, Int_t lenmax)
9098{
9099 if (entry != -1) {
9100 Int_t ret = LoadTree(entry);
9101 if (ret == -2) {
9102 Error("Show()", "Cannot read entry %lld (entry does not exist)", entry);
9103 return;
9104 } else if (ret == -1) {
9105 Error("Show()", "Cannot read entry %lld (I/O error)", entry);
9106 return;
9107 }
9108 ret = GetEntry(entry);
9109 if (ret == -1) {
9110 Error("Show()", "Cannot read entry %lld (I/O error)", entry);
9111 return;
9112 } else if (ret == 0) {
9113 Error("Show()", "Cannot read entry %lld (no data read)", entry);
9114 return;
9115 }
9116 }
9117 printf("======> EVENT:%lld\n", fReadEntry);
9118 TObjArray* leaves = GetListOfLeaves();
9119 Int_t nleaves = leaves->GetEntriesFast();
9120 Int_t ltype;
9121 for (Int_t i = 0; i < nleaves; i++) {
9122 TLeaf* leaf = (TLeaf*) leaves->UncheckedAt(i);
9123 TBranch* branch = leaf->GetBranch();
9124 if (branch->TestBit(kDoNotProcess)) {
9125 continue;
9126 }
9127 Int_t len = leaf->GetLen();
9128 if (len <= 0) {
9129 continue;
9130 }
9131 len = TMath::Min(len, lenmax);
9132 if (leaf->IsA() == TLeafElement::Class()) {
9133 leaf->PrintValue(lenmax);
9134 continue;
9135 }
9136 if (branch->GetListOfBranches()->GetEntriesFast() > 0) {
9137 continue;
9138 }
9139 ltype = 10;
9140 if (leaf->IsA() == TLeafF::Class()) {
9141 ltype = 5;
9142 }
9143 if (leaf->IsA() == TLeafD::Class()) {
9144 ltype = 5;
9145 }
9146 if (leaf->IsA() == TLeafC::Class()) {
9147 len = 1;
9148 ltype = 5;
9149 };
9150 printf(" %-15s = ", leaf->GetName());
9151 for (Int_t l = 0; l < len; l++) {
9152 leaf->PrintValue(l);
9153 if (l == (len - 1)) {
9154 printf("\n");
9155 continue;
9156 }
9157 printf(", ");
9158 if ((l % ltype) == 0) {
9159 printf("\n ");
9160 }
9161 }
9162 }
9163}
9164
9165////////////////////////////////////////////////////////////////////////////////
9166/// Start the TTreeViewer on this tree.
9167///
9168/// - ww is the width of the canvas in pixels
9169/// - wh is the height of the canvas in pixels
9171void TTree::StartViewer()
9172{
9173 GetPlayer();
9174 if (fPlayer) {
9175 fPlayer->StartViewer(600, 400);
9176 }
9177}
9178
9179////////////////////////////////////////////////////////////////////////////////
9180/// Stop the cache learning phase
9181///
9182/// Returns:
9183/// - 0 learning phase stopped or not active
9184/// - -1 on error
9187{
9188 if (!GetTree()) {
9189 if (LoadTree(0)<0) {
9190 Error("StopCacheLearningPhase","Could not load a tree");
9191 return -1;
9192 }
9193 }
9194 if (GetTree()) {
9195 if (GetTree() != this) {
9196 return GetTree()->StopCacheLearningPhase();
9197 }
9198 } else {
9199 Error("StopCacheLearningPhase", "No tree is available. Could not stop cache learning phase");
9200 return -1;
9201 }
9202
9203 TFile *f = GetCurrentFile();
9204 if (!f) {
9205 Error("StopCacheLearningPhase", "No file is available. Could not stop cache learning phase");
9206 return -1;
9207 }
9209 if (!tc) {
9210 Error("StopCacheLearningPhase", "No cache is available. Could not stop learning phase");
9211 return -1;
9212 }
9213 tc->StopLearningPhase();
9214 return 0;
9215}
9216
9217////////////////////////////////////////////////////////////////////////////////
9218/// Set the fTree member for all branches and sub branches.
9220static void TBranch__SetTree(TTree *tree, TObjArray &branches)
9221{
9222 Int_t nb = branches.GetEntriesFast();
9223 for (Int_t i = 0; i < nb; ++i) {
9224 TBranch* br = (TBranch*) branches.UncheckedAt(i);
9225 br->SetTree(tree);
9226
9227 Int_t nBaskets = br->GetListOfBaskets()->GetEntries();
9228 Int_t writeBasket = br->GetWriteBasket();
9229 for (Int_t j=writeBasket,n=0;j>=0 && n<nBaskets;--j) {
9230 TBasket *bk = (TBasket*)br->GetListOfBaskets()->UncheckedAt(j);
9231 if (bk) {
9232 tree->IncrementTotalBuffers(bk->GetBufferSize());
9233 ++n;
9234 }
9235 }
9236
9238 }
9239}
9240
9241////////////////////////////////////////////////////////////////////////////////
9242/// Set the fTree member for all friend elements.
9245{
9246 if (frlist) {
9247 TObjLink *lnk = frlist->FirstLink();
9248 while (lnk) {
9249 TFriendElement *elem = (TFriendElement*)lnk->GetObject();
9250 elem->fParentTree = tree;
9251 lnk = lnk->Next();
9252 }
9253 }
9254}
9255
9256////////////////////////////////////////////////////////////////////////////////
9257/// Stream a class object.
9258
9259void TTree::Streamer(TBuffer& b)
9260{
9261 if (b.IsReading()) {
9262 UInt_t R__s, R__c;
9263 if (fDirectory) {
9264 fDirectory->Remove(this);
9265 //delete the file cache if it points to this Tree
9268 }
9269 fDirectory = 0;
9272 Version_t R__v = b.ReadVersion(&R__s, &R__c);
9273 if (R__v > 4) {
9274 b.ReadClassBuffer(TTree::Class(), this, R__v, R__s, R__c);
9275
9276 fBranches.SetOwner(kTRUE); // True needed only for R__v < 19 and most R__v == 19
9277
9278 if (fBranchRef) fBranchRef->SetTree(this);
9281
9282 if (fTreeIndex) {
9283 fTreeIndex->SetTree(this);
9284 }
9285 if (fIndex.fN) {
9286 Warning("Streamer", "Old style index in this tree is deleted. Rebuild the index via TTree::BuildIndex");
9287 fIndex.Set(0);
9288 fIndexValues.Set(0);
9289 }
9290 if (fEstimate <= 10000) {
9291 fEstimate = 1000000;
9292 }
9293
9294 if (fNClusterRange) {
9295 // The I/O allocated just enough memory to hold the
9296 // current set of ranges.
9298 }
9299 if (GetCacheAutoSize() != 0) {
9300 // a cache will be automatically created.
9301 // No need for TTreePlayer::Process to enable the cache
9302 fCacheSize = 0;
9303 } else if (fAutoFlush < 0) {
9304 // If there is no autoflush set, let's keep the cache completely
9305 // disable by default for now.
9307 } else if (fAutoFlush != 0) {
9308 // Estimate the cluster size.
9309 // This will allow TTree::Process to enable the cache.
9310 Long64_t zipBytes = GetZipBytes();
9311 Long64_t totBytes = GetTotBytes();
9312 if (zipBytes != 0) {
9313 fCacheSize = fAutoFlush*(zipBytes/fEntries);
9314 } else if (totBytes != 0) {
9315 fCacheSize = fAutoFlush*(totBytes/fEntries);
9316 } else {
9317 fCacheSize = 30000000;
9318 }
9319 if (fCacheSize >= (INT_MAX / 4)) {
9320 fCacheSize = INT_MAX / 4;
9321 } else if (fCacheSize == 0) {
9322 fCacheSize = 30000000;
9323 }
9324 } else {
9325 fCacheSize = 0;
9326 }
9328 return;
9329 }
9330 //====process old versions before automatic schema evolution
9331 Stat_t djunk;
9332 Int_t ijunk;
9333 TNamed::Streamer(b);
9334 TAttLine::Streamer(b);
9335 TAttFill::Streamer(b);
9336 TAttMarker::Streamer(b);
9337 b >> fScanField;
9338 b >> ijunk; fMaxEntryLoop = (Long64_t)ijunk;
9339 b >> ijunk; fMaxVirtualSize = (Long64_t)ijunk;
9340 b >> djunk; fEntries = (Long64_t)djunk;
9341 b >> djunk; fTotBytes = (Long64_t)djunk;
9342 b >> djunk; fZipBytes = (Long64_t)djunk;
9343 b >> ijunk; fAutoSave = (Long64_t)ijunk;
9344 b >> ijunk; fEstimate = (Long64_t)ijunk;
9345 if (fEstimate <= 10000) fEstimate = 1000000;
9346 fBranches.Streamer(b);
9347 if (fBranchRef) fBranchRef->SetTree(this);
9349 fLeaves.Streamer(b);
9351 if (R__v > 1) fIndexValues.Streamer(b);
9352 if (R__v > 2) fIndex.Streamer(b);
9353 if (R__v > 3) {
9354 TList OldInfoList;
9355 OldInfoList.Streamer(b);
9356 OldInfoList.Delete();
9357 }
9358 fNClusterRange = 0;
9361 b.CheckByteCount(R__s, R__c, TTree::IsA());
9362 //====end of old versions
9363 } else {
9364 if (fBranchRef) {
9365 fBranchRef->Clear();
9366 }
9368 if (table) TRefTable::SetRefTable(0);
9369
9370 b.WriteClassBuffer(TTree::Class(), this);
9371
9372 if (table) TRefTable::SetRefTable(table);
9373 }
9374}
9375
9376////////////////////////////////////////////////////////////////////////////////
9377/// Unbinned fit of one or more variable(s) from a tree.
9378///
9379/// funcname is a TF1 function.
9380///
9381/// See TTree::Draw for explanations of the other parameters.
9382///
9383/// Fit the variable varexp using the function funcname using the
9384/// selection cuts given by selection.
9385///
9386/// The list of fit options is given in parameter option.
9387///
9388/// - option = "Q" Quiet mode (minimum printing)
9389/// - option = "V" Verbose mode (default is between Q and V)
9390/// - option = "E" Perform better Errors estimation using Minos technique
9391/// - option = "M" More. Improve fit results
9392///
9393/// You can specify boundary limits for some or all parameters via
9394/// ~~~ {.cpp}
9395/// func->SetParLimits(p_number, parmin, parmax);
9396/// ~~~
9397/// if parmin>=parmax, the parameter is fixed
9398///
9399/// Note that you are not forced to fix the limits for all parameters.
9400/// For example, if you fit a function with 6 parameters, you can do:
9401/// ~~~ {.cpp}
9402/// func->SetParameters(0,3.1,1.e-6,0.1,-8,100);
9403/// func->SetParLimits(4,-10,-4);
9404/// func->SetParLimits(5, 1,1);
9405/// ~~~
9406/// With this setup:
9407///
9408/// - Parameters 0->3 can vary freely
9409/// - Parameter 4 has boundaries [-10,-4] with initial value -8
9410/// - Parameter 5 is fixed to 100.
9411///
9412/// For the fit to be meaningful, the function must be self-normalized.
9413///
9414/// i.e. It must have the same integral regardless of the parameter
9415/// settings. Otherwise the fit will effectively just maximize the
9416/// area.
9417///
9418/// It is mandatory to have a normalization variable
9419/// which is fixed for the fit. e.g.
9420/// ~~~ {.cpp}
9421/// TF1* f1 = new TF1("f1", "gaus(0)/sqrt(2*3.14159)/[2]", 0, 5);
9422/// f1->SetParameters(1, 3.1, 0.01);
9423/// f1->SetParLimits(0, 1, 1); // fix the normalization parameter to 1
9424/// data->UnbinnedFit("f1", "jpsimass", "jpsipt>3.0");
9425/// ~~~
9426/// 1, 2 and 3 Dimensional fits are supported. See also TTree::Fit
9427///
9428/// Return status:
9429///
9430/// - The function return the status of the fit in the following form
9431/// fitResult = migradResult + 10*minosResult + 100*hesseResult + 1000*improveResult
9432/// - The fitResult is 0 is the fit is OK.
9433/// - The fitResult is negative in case of an error not connected with the fit.
9434/// - The number of entries used in the fit can be obtained via mytree.GetSelectedRows();
9435/// - If the number of selected entries is null the function returns -1
9437Int_t TTree::UnbinnedFit(const char* funcname, const char* varexp, const char* selection, Option_t* option, Long64_t nentries, Long64_t firstentry)
9438{
9439 GetPlayer();
9440 if (fPlayer) {
9441 return fPlayer->UnbinnedFit(funcname, varexp, selection, option, nentries, firstentry);
9442 }
9443 return -1;
9444}
9445
9446////////////////////////////////////////////////////////////////////////////////
9447/// Replace current attributes by current style.
9450{
9451 if (gStyle->IsReading()) {
9460 } else {
9469 }
9470}
9471
9472////////////////////////////////////////////////////////////////////////////////
9473/// Write this object to the current directory. For more see TObject::Write
9474/// If option & kFlushBasket, call FlushBasket before writing the tree.
9476Int_t TTree::Write(const char *name, Int_t option, Int_t bufsize) const
9477{
9479 return TObject::Write(name, option, bufsize);
9480}
9481
9482////////////////////////////////////////////////////////////////////////////////
9483/// Write this object to the current directory. For more see TObject::Write
9484/// If option & kFlushBasket, call FlushBasket before writing the tree.
9486Int_t TTree::Write(const char *name, Int_t option, Int_t bufsize)
9487{
9488 return ((const TTree*)this)->Write(name, option, bufsize);
9489}
9490
9491////////////////////////////////////////////////////////////////////////////////
9492/// \class TTreeFriendLeafIter
9493///
9494/// Iterator on all the leaves in a TTree and its friend
9495
9497
9498////////////////////////////////////////////////////////////////////////////////
9499/// Create a new iterator. By default the iteration direction
9500/// is kIterForward. To go backward use kIterBackward.
9503: fTree(const_cast<TTree*>(tree))
9504, fLeafIter(0)
9505, fTreeIter(0)
9506, fDirection(dir)
9507{
9508}
9509
9510////////////////////////////////////////////////////////////////////////////////
9511/// Copy constructor. Does NOT copy the 'cursor' location!
9514: TIterator(iter)
9515, fTree(iter.fTree)
9516, fLeafIter(0)
9517, fTreeIter(0)
9518, fDirection(iter.fDirection)
9519{
9520}
9521
9522////////////////////////////////////////////////////////////////////////////////
9523/// Overridden assignment operator. Does NOT copy the 'cursor' location!
9526{
9527 if (this != &rhs && rhs.IsA() == TTreeFriendLeafIter::Class()) {
9528 const TTreeFriendLeafIter &rhs1 = (const TTreeFriendLeafIter &)rhs;
9529 fDirection = rhs1.fDirection;
9530 }
9531 return *this;
9532}
9533
9534////////////////////////////////////////////////////////////////////////////////
9535/// Overridden assignment operator. Does NOT copy the 'cursor' location!
9538{
9539 if (this != &rhs) {
9540 fDirection = rhs.fDirection;
9541 }
9542 return *this;
9543}
9544
9545////////////////////////////////////////////////////////////////////////////////
9546/// Go the next friend element
9549{
9550 if (!fTree) return 0;
9551
9552 TObject * next;
9553 TTree * nextTree;
9554
9555 if (!fLeafIter) {
9556 TObjArray *list = fTree->GetListOfLeaves();
9557 if (!list) return 0; // Can happen with an empty chain.
9559 if (!fLeafIter) return 0;
9560 }
9561
9562 next = fLeafIter->Next();
9563 if (!next) {
9564 if (!fTreeIter) {
9566 if (!list) return next;
9568 if (!fTreeIter) return 0;
9569 }
9570 TFriendElement * nextFriend = (TFriendElement*) fTreeIter->Next();
9571 ///nextTree = (TTree*)fTreeIter->Next();
9572 if (nextFriend) {
9573 nextTree = const_cast<TTree*>(nextFriend->GetTree());
9574 if (!nextTree) return Next();
9577 if (!fLeafIter) return 0;
9578 next = fLeafIter->Next();
9579 }
9580 }
9581 return next;
9582}
9583
9584////////////////////////////////////////////////////////////////////////////////
9585/// Returns the object option stored in the list.
9588{
9589 if (fLeafIter) return fLeafIter->GetOption();
9590 return "";
9591}
void Class()
Definition: Class.C:29
#define R__unlikely(expr)
Definition: RConfig.hxx:611
#define SafeDelete(p)
Definition: RConfig.hxx:550
#define b(i)
Definition: RSha256.hxx:100
#define f(i)
Definition: RSha256.hxx:104
#define c(i)
Definition: RSha256.hxx:101
const Ssiz_t kNPOS
Definition: RtypesCore.h:111
int Int_t
Definition: RtypesCore.h:41
short Version_t
Definition: RtypesCore.h:61
unsigned char UChar_t
Definition: RtypesCore.h:34
int Ssiz_t
Definition: RtypesCore.h:63
unsigned int UInt_t
Definition: RtypesCore.h:42
const Bool_t kFALSE
Definition: RtypesCore.h:88
long Long_t
Definition: RtypesCore.h:50
bool Bool_t
Definition: RtypesCore.h:59
double Double_t
Definition: RtypesCore.h:55
double Stat_t
Definition: RtypesCore.h:73
long long Long64_t
Definition: RtypesCore.h:69
unsigned long long ULong64_t
Definition: RtypesCore.h:70
float Float_t
Definition: RtypesCore.h:53
const Bool_t kTRUE
Definition: RtypesCore.h:87
const char Option_t
Definition: RtypesCore.h:62
#define ClassImp(name)
Definition: Rtypes.h:365
R__EXTERN Int_t gDebug
Definition: Rtypes.h:91
const Int_t kDoNotProcess
Definition: TBranch.h:58
EDataType
Definition: TDataType.h:28
@ kNoType_t
Definition: TDataType.h:33
@ kFloat_t
Definition: TDataType.h:31
@ kULong64_t
Definition: TDataType.h:32
@ kInt_t
Definition: TDataType.h:30
@ kchar
Definition: TDataType.h:31
@ kLong_t
Definition: TDataType.h:30
@ kDouble32_t
Definition: TDataType.h:31
@ kShort_t
Definition: TDataType.h:29
@ kBool_t
Definition: TDataType.h:32
@ kBits
Definition: TDataType.h:34
@ kULong_t
Definition: TDataType.h:30
@ kLong64_t
Definition: TDataType.h:32
@ kUShort_t
Definition: TDataType.h:29
@ kDouble_t
Definition: TDataType.h:31
@ kCharStar
Definition: TDataType.h:34
@ kChar_t
Definition: TDataType.h:29
@ kUChar_t
Definition: TDataType.h:29
@ kCounter
Definition: TDataType.h:34
@ kUInt_t
Definition: TDataType.h:30
@ kFloat16_t
Definition: TDataType.h:33
@ kOther_t
Definition: TDataType.h:32
#define gDirectory
Definition: TDirectory.h:223
R__EXTERN TEnv * gEnv
Definition: TEnv.h:171
#define R__ASSERT(e)
Definition: TError.h:96
void Error(const char *location, const char *msgfmt,...)
#define N
static unsigned int total
char name[80]
Definition: TGX11.cxx:109
int nentries
Definition: THbookFile.cxx:89
R__EXTERN TInterpreter * gCling
Definition: TInterpreter.h:556
R__EXTERN TVirtualMutex * gROOTMutex
Definition: TROOT.h:59
#define gROOT
Definition: TROOT.h:415
void Printf(const char *fmt,...)
R__EXTERN TStyle * gStyle
Definition: TStyle.h:407
typedef void((*Func_t)())
R__EXTERN TSystem * gSystem
Definition: TSystem.h:560
constexpr Int_t kNEntriesResort
Definition: TTree.cxx:436
static TBranch * R__FindBranchHelper(TObjArray *list, const char *branchname)
Search in the array for a branch matching the branch name, with the branch possibly expressed as a 'f...
Definition: TTree.cxx:4675
static char DataTypeToChar(EDataType datatype)
Definition: TTree.cxx:448
void TFriendElement__SetTree(TTree *tree, TList *frlist)
Set the fTree member for all friend elements.
Definition: TTree.cxx:9243
bool CheckReshuffling(TTree &mainTree, TTree &friendTree)
Definition: TTree.cxx:1209
static void TBranch__SetTree(TTree *tree, TObjArray &branches)
Set the fTree member for all branches and sub branches.
Definition: TTree.cxx:9219
constexpr Float_t kNEntriesResortInv
Definition: TTree.cxx:437
#define R__LOCKGUARD(mutex)
#define gPad
Definition: TVirtualPad.h:286
#define snprintf
Definition: civetweb.c:1540
Bool_t HasRuleWithSourceClass(const TString &source) const
Return True if we have any rule whose source class is 'source'.
TIOFeatures provides the end-user with the ability to change the IO behavior of data written via a TT...
Definition: TIOFeatures.hxx:62
UChar_t GetFeatures() const
bool Set(EIOFeatures bits)
Set a specific IO feature.
This class provides a simple interface to execute the same task multiple times in parallel,...
void Foreach(F func, unsigned nTimes, unsigned nChunks=0)
Execute func (with no arguments) nTimes in parallel.
void Set(Int_t n)
Set size of this array to n doubles.
Definition: TArrayD.cxx:106
void Set(Int_t n)
Set size of this array to n ints.
Definition: TArrayI.cxx:105
Int_t fN
Definition: TArray.h:38
Fill Area Attributes class.
Definition: TAttFill.h:19
virtual Color_t GetFillColor() const
Return the fill area color.
Definition: TAttFill.h:30
virtual Style_t GetFillStyle() const
Return the fill area style.
Definition: TAttFill.h:31
virtual void SetFillColor(Color_t fcolor)
Set the fill area color.
Definition: TAttFill.h:37
virtual void SetFillStyle(Style_t fstyle)
Set the fill area style.
Definition: TAttFill.h:39
Line Attributes class.
Definition: TAttLine.h:18
virtual Color_t GetLineColor() const
Return the line color.
Definition: TAttLine.h:33
virtual void SetLineStyle(Style_t lstyle)
Set the line style.
Definition: TAttLine.h:42
virtual Width_t GetLineWidth() const
Return the line width.
Definition: TAttLine.h:35
virtual void SetLineWidth(Width_t lwidth)
Set the line width.
Definition: TAttLine.h:43
virtual void SetLineColor(Color_t lcolor)
Set the line color.
Definition: TAttLine.h:40
virtual Style_t GetLineStyle() const
Return the line style.
Definition: TAttLine.h:34
Marker Attributes class.
Definition: TAttMarker.h:19
virtual Style_t GetMarkerStyle() const
Return the marker style.
Definition: TAttMarker.h:32
virtual void SetMarkerColor(Color_t mcolor=1)
Set the marker color.
Definition: TAttMarker.h:38
virtual Color_t GetMarkerColor() const
Return the marker color.
Definition: TAttMarker.h:31
virtual Size_t GetMarkerSize() const
Return the marker size.
Definition: TAttMarker.h:33
virtual void SetMarkerStyle(Style_t mstyle=1)
Set the marker style.
Definition: TAttMarker.h:40
virtual void SetMarkerSize(Size_t msize=1)
Set the marker size.
Definition: TAttMarker.h:41
Each class (see TClass) has a linked list of its base class(es).
Definition: TBaseClass.h:33
ROOT::ESTLType IsSTLContainer()
Return which type (if any) of STL container the data member is.
Definition: TBaseClass.cxx:101
Manages buffers for branches of a Tree.
Definition: TBasket.h:34
virtual Int_t DropBuffers()
Drop buffers of this basket if it is not the current basket.
Definition: TBasket.cxx:169
Int_t GetBufferSize() const
Definition: TBasket.h:122
A Branch for the case of an array of clone objects.
Definition: TBranchClones.h:29
A Branch for the case of an object.
virtual void ResetAddress()
Set branch address to zero and free all allocated memory.
virtual void SetBranchFolder()
Int_t GetClassVersion()
virtual const char * GetClassName() const
Return the name of the user class whose content is stored in this branch, if any.
virtual Bool_t IsObjectOwner() const
virtual void SetObject(void *objadd)
Set object this branch is pointing to.
virtual void SetAddress(void *addobj)
Point this branch at an object.
Int_t Unroll(const char *name, TClass *cltop, TClass *cl, char *ptr, Int_t basketsize, Int_t splitlevel, Int_t btype)
Split class cl into sub-branches of this branch.
virtual void SetTargetClass(const char *name)
Set the name of the class of the in-memory object into which the data will loaded.
UInt_t GetCheckSum()
A Branch for the case of an object.
Definition: TBranchObject.h:26
A branch containing and managing a TRefTable for TRef autoloading.
Definition: TBranchRef.h:29
virtual void ResetAfterMerge(TFileMergeInfo *)
Reset a Branch after a Merge operation (drop data but keep customizations) TRefTable is cleared.
Definition: TBranchRef.cxx:198
virtual void Reset(Option_t *option="")
Definition: TBranchRef.cxx:187
virtual void Clear(Option_t *option="")
Clear entries in the TRefTable.
Definition: TBranchRef.cxx:95
virtual void Print(Option_t *option="") const
Print the TRefTable branch.
Definition: TBranchRef.cxx:159
A Branch handling STL collection of pointers (vectors, lists, queues, sets and multisets) while stori...
Definition: TBranchSTL.h:22
A TTree is a list of TBranches.
Definition: TBranch.h:91
virtual TLeaf * GetLeaf(const char *name) const
Return pointer to the 1st Leaf named name in thisBranch.
Definition: TBranch.cxx:1907
virtual void SetupAddresses()
If the branch address is not set, we set all addresses starting with the top level parent branch.
Definition: TBranch.cxx:3127
virtual void ResetAddress()
Reset the address of the branch.
Definition: TBranch.cxx:2488
virtual Long64_t GetBasketSeek(Int_t basket) const
Return address of basket in the file.
Definition: TBranch.cxx:1278
virtual char * GetAddress() const
Definition: TBranch.h:210
void SetCompressionSettings(Int_t settings=ROOT::RCompressionSetting::EDefaults::kUseCompiledDefault)
Set compression settings.
Definition: TBranch.cxx:2642
TTree * GetTree() const
Definition: TBranch.h:250
virtual TString GetFullName() const
Return the 'full' name of the branch.
Definition: TBranch.cxx:1891
Int_t GetWriteBasket() const
Definition: TBranch.h:236
virtual void DropBaskets(Option_t *option="")
Loop on all branch baskets.
Definition: TBranch.cxx:734
TObjArray * GetListOfBranches()
Definition: TBranch.h:244
virtual void SetTree(TTree *tree)
Definition: TBranch.h:285
virtual void SetEntryOffsetLen(Int_t len, Bool_t updateSubBranches=kFALSE)
Update the default value for the branch's fEntryOffsetLen if and only if it was already non zero (and...
Definition: TBranch.cxx:2658
virtual Int_t GetEntry(Long64_t entry=0, Int_t getall=0)
Read all leaves of entry and return total number of bytes read.
Definition: TBranch.cxx:1579
static void ResetCount()
Static function resetting fgCount.
Definition: TBranch.cxx:2511
virtual void SetObject(void *objadd)
Set object this branch is pointing to.
Definition: TBranch.cxx:2773
Int_t FlushBaskets()
Flush to disk all the baskets of this branch and any of subbranches.
Definition: TBranch.cxx:1112
virtual void SetAddress(void *add)
Set address of this branch.
Definition: TBranch.cxx:2519
Int_t GetNleaves() const
Definition: TBranch.h:247
TObjArray * GetListOfBaskets()
Definition: TBranch.h:243
Long64_t GetEntries() const
Definition: TBranch.h:249
virtual void UpdateFile()
Refresh the value of fDirectory (i.e.
Definition: TBranch.cxx:3137
Int_t GetReadBasket() const
Definition: TBranch.h:234
virtual void Print(Option_t *option="") const
Print TBranch parameters.
Definition: TBranch.cxx:2178
Int_t GetMaxBaskets() const
Definition: TBranch.h:246
virtual TFile * GetFile(Int_t mode=0)
Return pointer to the file where branch buffers reside, returns 0 in case branch buffers reside in th...
Definition: TBranch.cxx:1726
virtual void KeepCircular(Long64_t maxEntries)
keep a maximum of fMaxEntries in memory
Definition: TBranch.cxx:2120
virtual void ResetAfterMerge(TFileMergeInfo *)
Reset a Branch.
Definition: TBranch.cxx:2435
virtual Bool_t GetMakeClass() const
Return whether this branch is in a mode where the object are decomposed or not (Also known as MakeCla...
Definition: TBranch.cxx:1969
virtual TBranch * FindBranch(const char *name)
Find the immediate sub-branch with passed name.
Definition: TBranch.cxx:1011
virtual Int_t LoadBaskets()
Baskets associated to this branch are forced to be in memory.
Definition: TBranch.cxx:2146
void SetIOFeatures(TIOFeatures &features)
Definition: TBranch.h:281
Long64_t GetTotBytes(Option_t *option="") const
Return total number of bytes in the branch (excluding current buffer) if option ="*" includes all sub...
Definition: TBranch.cxx:2057
virtual Bool_t SetMakeClass(Bool_t decomposeObj=kTRUE)
Set the branch in a mode where the object are decomposed (Also known as MakeClass mode).
Definition: TBranch.cxx:2764
virtual void SetFile(TFile *file=0)
Set file where this branch writes/reads its buffers.
Definition: TBranch.cxx:2700
virtual void SetOffset(Int_t offset=0)
Definition: TBranch.h:283
virtual Int_t GetExpectedType(TClass *&clptr, EDataType &type)
Fill expectedClass and expectedType with information on the data type of the object/values contained ...
Definition: TBranch.cxx:1707
virtual Int_t GetBasketSize() const
Definition: TBranch.h:215
Long64_t GetZipBytes(Option_t *option="") const
Return total number of zip bytes in the branch if option ="*" includes all sub-branches of this branc...
Definition: TBranch.cxx:2075
virtual void SetBasketSize(Int_t buffsize)
Set the basket size The function makes sure that the basket size is greater than fEntryOffsetlen.
Definition: TBranch.cxx:2566
virtual void Refresh(TBranch *b)
Refresh this branch using new information in b This function is called by TTree::Refresh.
Definition: TBranch.cxx:2345
TObjArray * GetListOfLeaves()
Definition: TBranch.h:245
Int_t Fill()
Definition: TBranch.h:203
virtual void Reset(Option_t *option="")
Reset a Branch.
Definition: TBranch.cxx:2394
TBranch * GetMother() const
Get our top-level parent branch in the tree.
Definition: TBranch.cxx:1979
virtual Int_t FillImpl(ROOT::Internal::TBranchIMTHelper *)
Loop on all leaves of this branch to fill Basket buffer.
Definition: TBranch.cxx:833
Int_t GetEntryOffsetLen() const
Definition: TBranch.h:225
Using a TBrowser one can browse all ROOT objects.
Definition: TBrowser.h:37
The concrete implementation of TBuffer for writing/reading to/from a ROOT file or socket.
Definition: TBufferFile.h:46
Buffer base class used for serializing objects.
Definition: TBuffer.h:42
void Expand(Int_t newsize, Bool_t copy=kTRUE)
Expand (or shrink) the I/O buffer to newsize bytes.
Definition: TBuffer.cxx:223
Int_t BufferSize() const
Definition: TBuffer.h:97
@ kWrite
Definition: TBuffer.h:72
@ kRead
Definition: TBuffer.h:72
TClass instances represent classes, structs and namespaces in the ROOT type system.
Definition: TClass.h:75
TVirtualStreamerInfo * GetStreamerInfo(Int_t version=0) const
returns a pointer to the TVirtualStreamerInfo object for version If the object does not exist,...
Definition: TClass.cxx:4440
Bool_t CanSplit() const
Return true if the data member of this TClass can be saved separately.
Definition: TClass.cxx:2250
ROOT::ESTLType GetCollectionType() const
Return the 'type' of the STL the TClass is representing.
Definition: TClass.cxx:2824
void * New(ENewType defConstructor=kClassNew, Bool_t quiet=kFALSE) const
Return a pointer to a newly allocated object of this class.
Definition: TClass.cxx:4812
Bool_t HasDataMemberInfo() const
Definition: TClass.h:378
void BuildRealData(void *pointer=0, Bool_t isTransient=kFALSE)
Build a full list of persistent data members.
Definition: TClass.cxx:1961
void Destructor(void *obj, Bool_t dtorOnly=kFALSE)
Explicitly call destructor for object.
Definition: TClass.cxx:5169
const std::type_info * GetTypeInfo() const
Definition: TClass.h:466
TList * GetListOfDataMembers(Bool_t load=kTRUE)
Return list containing the TDataMembers of a class.
Definition: TClass.cxx:3606
TList * GetListOfRealData() const
Definition: TClass.h:423
Bool_t CanIgnoreTObjectStreamer()
Definition: TClass.h:365
const ROOT::Detail::TSchemaRuleSet * GetSchemaRules() const
Return the set of the schema rules if any.
Definition: TClass.cxx:1862
TList * GetListOfBases()
Return list containing the TBaseClass(es) of a class.
Definition: TClass.cxx:3496
Bool_t IsLoaded() const
Return true if the shared library of this class is currently in the a process's memory.
Definition: TClass.cxx:5662
Bool_t IsTObject() const
Return kTRUE is the class inherits from TObject.
Definition: TClass.cxx:5688
TVirtualCollectionProxy * GetCollectionProxy() const
Return the proxy describing the collection (if any).
Definition: TClass.cxx:2835
TVirtualStreamerInfo * GetConversionStreamerInfo(const char *onfile_classname, Int_t version) const
Return a Conversion StreamerInfo from the class 'classname' for version number 'version' to this clas...
Definition: TClass.cxx:6780
TVirtualStreamerInfo * FindConversionStreamerInfo(const char *onfile_classname, UInt_t checksum) const
Return a Conversion StreamerInfo from the class 'classname' for the layout represented by 'checksum' ...
Definition: TClass.cxx:6877
Version_t GetClassVersion() const
Definition: TClass.h:391
Bool_t InheritsFrom(const char *cl) const
Return kTRUE if this class inherits from a class with name "classname".
Definition: TClass.cxx:4708
TClass * GetActualClass(const void *object) const
Return a pointer the the real class of the object.
Definition: TClass.cxx:2546
@ kHasCustomStreamerMember
Definition: TClass.h:99
static TClass * GetClass(const char *name, Bool_t load=kTRUE, Bool_t silent=kFALSE)
Static method returning pointer to TClass of the specified class name.
Definition: TClass.cxx:2906
An array of clone (identical) objects.
Definition: TClonesArray.h:32
void BypassStreamer(Bool_t bypass=kTRUE)
When the kBypassStreamer bit is set, the automatically generated Streamer can call directly TClass::W...
TClass * GetClass() const
Definition: TClonesArray.h:56
Collection abstract base class.
Definition: TCollection.h:63
virtual TObject ** GetObjectRef(const TObject *obj) const =0
virtual TIterator * MakeIterator(Bool_t dir=kIterForward) const =0
virtual const char * GetName() const
Return name of this collection.
void SetName(const char *name)
Definition: TCollection.h:204
void Browse(TBrowser *b)
Browse this collection (called by TBrowser).
virtual Int_t GetEntries() const
Definition: TCollection.h:177
virtual void SetOwner(Bool_t enable=kTRUE)
Set whether this collection is the owner (enable==true) of its content.
A specialized string object used for TTree selections.
Definition: TCut.h:25
All ROOT classes may have RTTI (run time type identification) support added.
Definition: TDataMember.h:31
Bool_t IsPersistent() const
Definition: TDataMember.h:89
Long_t GetOffset() const
Get offset from "this".
Bool_t IsBasic() const
Return true if data member is a basic type, e.g. char, int, long...
Bool_t IsaPointer() const
Return true if data member is a pointer.
TDataType * GetDataType() const
Definition: TDataMember.h:74
const char * GetTypeName() const
Get type of data member, e,g.: "class TDirectory*" -> "TDirectory".
const char * GetArrayIndex() const
If the data member is pointer and has a valid array size in its comments GetArrayIndex returns a stri...
const char * GetFullTypeName() const
Get full type description of data member, e,g.: "class TDirectory*".
Basic data type descriptor (datatype information is obtained from CINT).
Definition: TDataType.h:44
Int_t GetType() const
Definition: TDataType.h:68
TString GetTypeName()
Get basic type of typedef, e,g.
Definition: TDataType.cxx:149
void Append(TObject *obj, Bool_t replace=kFALSE) override
Append object to this directory.
Small helper to keep current directory context.
Definition: TDirectory.h:41
Describe directory structure in memory.
Definition: TDirectory.h:34
virtual TList * GetList() const
Definition: TDirectory.h:159
virtual void Append(TObject *obj, Bool_t replace=kFALSE)
Append object to this directory.
Definition: TDirectory.cxx:190
virtual Int_t WriteTObject(const TObject *obj, const char *name=nullptr, Option_t *="", Int_t=0)
See TDirectoryFile::WriteTObject for details.
virtual TFile * GetFile() const
Definition: TDirectory.h:157
virtual Int_t ReadKeys(Bool_t=kTRUE)
Definition: TDirectory.h:184
virtual Bool_t IsWritable() const
Definition: TDirectory.h:173
virtual TKey * GetKey(const char *, Short_t=9999) const
Definition: TDirectory.h:158
virtual Int_t ReadTObject(TObject *, const char *)
Definition: TDirectory.h:185
virtual void SaveSelf(Bool_t=kFALSE)
Definition: TDirectory.h:191
virtual TList * GetListOfKeys() const
Definition: TDirectory.h:160
void GetObject(const char *namecycle, T *&ptr)
Definition: TDirectory.h:149
virtual TObject * Remove(TObject *)
Remove an object from the in-memory list.
virtual Bool_t cd(const char *path=nullptr)
Change current directory to "this" directory.
Definition: TDirectory.cxx:497
Streamer around an arbitrary STL like container, which implements basic container functionality.
A List of entry numbers in a TTree or TChain.
Definition: TEntryList.h:26
virtual void SetReapplyCut(Bool_t apply=kFALSE)
Definition: TEntryList.h:105
virtual void SetTree(const TTree *tree)
If a list for a tree with such name and filename exists, sets it as the current sublist If not,...
virtual TDirectory * GetDirectory() const
Definition: TEntryList.h:74
virtual void SetDirectory(TDirectory *dir)
Add reference to directory dir. dir can be 0.
virtual Bool_t Enter(Long64_t entry, TTree *tree=0)
Add entry #entry to the list.
Definition: TEntryList.cxx:558
virtual Long64_t GetEntry(Int_t index)
Return the number of the entry #index of this TEntryList in the TTree or TChain See also Next().
Definition: TEntryList.cxx:655
virtual Int_t GetValue(const char *name, Int_t dflt) const
Returns the integer value for a resource.
Definition: TEnv.cxx:491
A TEventList object is a list of selected events (entries) in a TTree.
Definition: TEventList.h:31
virtual Long64_t GetEntry(Int_t index) const
Return value of entry at index in the list.
Definition: TEventList.cxx:222
virtual Int_t GetN() const
Definition: TEventList.h:56
virtual Bool_t GetReapplyCut() const
Definition: TEventList.h:57
A cache when reading files over the network.
virtual void WaitFinishPrefetch()
virtual Int_t GetBufferSize() const
TIOFeatures * fIOFeatures
TDirectory * fOutputDirectory
A ROOT file is a suite of consecutive data records (TKey instances) with a well defined format.
Definition: TFile.h:48
Int_t GetCompressionSettings() const
Definition: TFile.h:394
virtual Long64_t GetEND() const
Definition: TFile.h:218
@ kDoNotDisconnect
Definition: TFile.h:65
virtual void Flush()
Synchronize a file's in-memory and on-disk states.
Definition: TFile.cxx:1038
virtual void MakeFree(Long64_t first, Long64_t last)
Mark unused bytes on the file.
Definition: TFile.cxx:1377
static TFile * Open(const char *name, Option_t *option="", const char *ftitle="", Int_t compress=ROOT::RCompressionSetting::EDefaults::kUseCompiledDefault, Int_t netopt=0)
Create / open a file.
Definition: TFile.cxx:3923
virtual void SetCacheRead(TFileCacheRead *cache, TObject *tree=0, ECacheAction action=kDisconnect)
Set a pointer to the read cache.
Definition: TFile.cxx:2206
Int_t GetRecordHeader(char *buf, Long64_t first, Int_t maxbytes, Int_t &nbytes, Int_t &objlen, Int_t &keylen)
Read the logical record header starting at a certain postion.
Definition: TFile.cxx:1196
A TFolder object is a collection of objects and folders.
Definition: TFolder.h:30
TCollection * GetListOfFolders() const
Definition: TFolder.h:55
virtual Int_t Occurence(const TObject *obj) const
Return occurence number of object in the list of objects of this folder.
Definition: TFolder.cxx:436
A TFriendElement TF describes a TTree object TF in a file.
virtual const char * GetTreeName() const
virtual TTree * GetTree()
Return pointer to friend TTree.
virtual TFile * GetFile()
Return pointer to TFile containing this friend TTree.
TTree * fParentTree
! pointer to the parent TTree
virtual Int_t DeleteGlobal(void *obj)=0
void Reset()
Definition: TCollection.h:252
Iterator abstract base class.
Definition: TIterator.h:30
virtual TObject * Next()=0
virtual Option_t * GetOption() const
Definition: TIterator.h:40
Book space in a file, create I/O buffers, to fill them, (un)compress them.
Definition: TKey.h:24
virtual void Delete(Option_t *option="")
Delete an object from the file.
Definition: TKey.cxx:538
Int_t GetKeylen() const
Definition: TKey.h:81
Int_t GetNbytes() const
Definition: TKey.h:83
A TLeaf describes individual elements of a TBranch See TBranch structure in TTree.
Definition: TLeaf.h:49
virtual Double_t GetValue(Int_t i=0) const
Definition: TLeaf.h:174
virtual void * GetValuePointer() const
Definition: TLeaf.h:129
virtual Int_t GetLenType() const
Definition: TLeaf.h:124
virtual void ReadValue(std::istream &, Char_t=' ')
Definition: TLeaf.h:147
virtual Int_t GetMaximum() const
Definition: TLeaf.h:125
virtual Int_t GetLen() const
Return the number of effective elements of this leaf, for the current entry.
Definition: TLeaf.cxx:379
virtual TLeaf * GetLeafCount() const
If this leaf stores a variable-sized array or a multi-dimensional array whose last dimension has vari...
Definition: TLeaf.h:112
virtual Bool_t IncludeRange(TLeaf *)
Definition: TLeaf.h:137
virtual void SetAddress(void *add=0)
Definition: TLeaf.h:176
TBranch * GetBranch() const
Definition: TLeaf.h:107
@ kNewValue
Set if we own the value buffer and so must delete it ourselves.
Definition: TLeaf.h:88
@ kIndirectAddress
Data member is a pointer to an array of basic types.
Definition: TLeaf.h:87
virtual TString GetFullName() const
Return the full name (including the parent's branch names) of the leaf.
Definition: TLeaf.cxx:199
virtual Int_t GetOffset() const
Definition: TLeaf.h:128
virtual void PrintValue(Int_t i=0) const
Definition: TLeaf.h:175
A doubly linked list.
Definition: TList.h:44
virtual void Add(TObject *obj)
Definition: TList.h:87
virtual TObject * Remove(TObject *obj)
Remove object from the list.
Definition: TList.cxx:819
virtual TObject * FindObject(const char *name) const
Find an object in this list using its name.
Definition: TList.cxx:575
virtual TObjLink * FirstLink() const
Definition: TList.h:108
virtual TObject * At(Int_t idx) const
Returns the object at position idx. Returns 0 if idx is out of range.
Definition: TList.cxx:354
virtual void RecursiveRemove(TObject *obj)
Remove object from this collection and recursively remove the object from all other objects (and coll...
Definition: TList.cxx:761
virtual void Delete(Option_t *option="")
Remove all objects from the list AND delete all heap based objects.
Definition: TList.cxx:467
The TNamed class is the base class for all named ROOT classes.
Definition: TNamed.h:29
virtual void SetTitle(const char *title="")
Set the title of the TNamed.
Definition: TNamed.cxx:164
TString fTitle
Definition: TNamed.h:33
TNamed()
Definition: TNamed.h:36
TString fName
Definition: TNamed.h:32
virtual void SetName(const char *name)
Set the name of the TNamed.
Definition: TNamed.cxx:140
virtual const char * GetTitle() const
Returns title of object.
Definition: TNamed.h:48
virtual TObject * Clone(const char *newname="") const
Make a clone of an object using the Streamer facility.
Definition: TNamed.cxx:74
virtual const char * GetName() const
Returns name of object.
Definition: TNamed.h:47
An array of TObjects.
Definition: TObjArray.h:37
Int_t GetEntriesFast() const
Definition: TObjArray.h:64
Int_t GetEntriesUnsafe() const
Return the number of objects in array (i.e.
Definition: TObjArray.cxx:564
void Add(TObject *obj)
Definition: TObjArray.h:74
TObject * Last() const
Return the object in the last filled slot. Returns 0 if no entries.
Definition: TObjArray.cxx:505
virtual void Compress()
Remove empty slots from array.
Definition: TObjArray.cxx:333
Int_t GetEntries() const
Return the number of objects in array (i.e.
Definition: TObjArray.cxx:522
virtual void Clear(Option_t *option="")
Remove all objects from the array.
Definition: TObjArray.cxx:320
TObject * UncheckedAt(Int_t i) const
Definition: TObjArray.h:90
virtual void Delete(Option_t *option="")
Remove all objects from the array AND delete all heap based objects.
Definition: TObjArray.cxx:355
TIterator * MakeIterator(Bool_t dir=kIterForward) const
Returns an array iterator.
Definition: TObjArray.cxx:648
virtual TObject * RemoveAt(Int_t idx)
Remove object at index idx.
Definition: TObjArray.cxx:693
TObject * At(Int_t idx) const
Definition: TObjArray.h:166
Mother of all ROOT objects.
Definition: TObject.h:37
virtual Bool_t Notify()
This method must be overridden to handle object notification.
Definition: TObject.cxx:506
virtual Int_t Write(const char *name=0, Int_t option=0, Int_t bufsize=0)
Write this object to the current directory.
Definition: TObject.cxx:785
virtual const char * GetName() const
Returns name of object.
Definition: TObject.cxx:357
R__ALWAYS_INLINE Bool_t TestBit(UInt_t f) const
Definition: TObject.h:172
@ kBitMask
Definition: TObject.h:82
virtual const char * ClassName() const
Returns name of class to which the object belongs.
Definition: TObject.cxx:128
virtual void Warning(const char *method, const char *msgfmt,...) const
Issue warning message.
Definition: TObject.cxx:866
R__ALWAYS_INLINE Bool_t IsZombie() const
Definition: TObject.h:134
void SetBit(UInt_t f, Bool_t set)
Set or unset the user status bits as specified in f.
Definition: TObject.cxx:694
virtual Bool_t InheritsFrom(const char *classname) const
Returns kTRUE if object inherits from class "classname".
Definition: TObject.cxx:443
virtual void Error(const char *method, const char *msgfmt,...) const
Issue error message.
Definition: TObject.cxx:880
virtual void Fatal(const char *method, const char *msgfmt,...) const
Issue fatal error message.
Definition: TObject.cxx:908
virtual const char * GetTitle() const
Returns title of object.
Definition: TObject.cxx:401
void ResetBit(UInt_t f)
Definition: TObject.h:171
@ kCanDelete
if object in a list can be deleted
Definition: TObject.h:58
@ kMustCleanup
if object destructor must call RecursiveRemove()
Definition: TObject.h:60
virtual void Info(const char *method, const char *msgfmt,...) const
Issue info message.
Definition: TObject.cxx:854
Principal Components Analysis (PCA)
Definition: TPrincipal.h:20
The TRealData class manages the effective list of all data members for a given class.
Definition: TRealData.h:30
TDataMember * GetDataMember() const
Definition: TRealData.h:53
@ kTransient
Definition: TRealData.h:44
Bool_t IsObject() const
Definition: TRealData.h:56
virtual const char * GetName() const
Returns name of object.
Definition: TRealData.h:52
Long_t GetThisOffset() const
Definition: TRealData.h:55
A TRefTable maintains the association between a referenced object and the parent object supporting th...
Definition: TRefTable.h:35
static void SetRefTable(TRefTable *table)
Static function setting the current TRefTable.
Definition: TRefTable.cxx:383
static TRefTable * GetRefTable()
Static function returning the current TRefTable.
Definition: TRefTable.cxx:287
Regular expression class.
Definition: TRegexp.h:31
A TSelector object is used by the TTree::Draw, TTree::Scan, TTree::Process to navigate in a TTree and...
Definition: TSelector.h:33
static void * ReAlloc(void *vp, size_t size)
Reallocate (i.e.
Definition: TStorage.cxx:183
Describe Streamer information for one class version.
Definition: TStreamerInfo.h:43
void ForceWriteInfo(TFile *file, Bool_t force=kFALSE)
Recursively mark streamer infos for writing to a file.
Basic string class.
Definition: TString.h:131
Ssiz_t Length() const
Definition: TString.h:405
void ToLower()
Change string to lower-case.
Definition: TString.cxx:1125
static const Ssiz_t kNPOS
Definition: TString.h:264
TSubString Strip(EStripType s=kTrailing, char c=' ') const
Return a substring of self stripped at beginning and/or end.
Definition: TString.cxx:1106
Double_t Atof() const
Return floating-point value contained in string.
Definition: TString.cxx:1987
Ssiz_t First(char c) const
Find first occurrence of a character c.
Definition: TString.cxx:499
const char * Data() const
Definition: TString.h:364
Bool_t EqualTo(const char *cs, ECaseCompare cmp=kExact) const
Definition: TString.h:628
TString & ReplaceAll(const TString &s1, const TString &s2)
Definition: TString.h:687
@ kLeading
Definition: TString.h:262
@ kTrailing
Definition: TString.h:262
Ssiz_t Last(char c) const
Find last occurrence of a character c.
Definition: TString.cxx:892
TObjArray * Tokenize(const TString &delim) const
This function is used to isolate sequential tokens in a TString.
Definition: TString.cxx:2197
Bool_t IsNull() const
Definition: TString.h:402
TString & Remove(Ssiz_t pos)
Definition: TString.h:668
TString & Append(const char *cs)
Definition: TString.h:559
static TString Format(const char *fmt,...)
Static method which formats a string using a printf style format descriptor and return a TString.
Definition: TString.cxx:2311
void Form(const char *fmt,...)
Formats a string using a printf style format descriptor.
Definition: TString.cxx:2289
Bool_t Contains(const char *pat, ECaseCompare cmp=kExact) const
Definition: TString.h:619
Ssiz_t Index(const char *pat, Ssiz_t i=0, ECaseCompare cmp=kExact) const
Definition: TString.h:634
void SetHistFillColor(Color_t color=1)
Definition: TStyle.h:357
Color_t GetHistLineColor() const
Definition: TStyle.h:221
Bool_t IsReading() const
Definition: TStyle.h:278
void SetHistLineStyle(Style_t styl=0)
Definition: TStyle.h:360
Style_t GetHistFillStyle() const
Definition: TStyle.h:222
Color_t GetHistFillColor() const
Definition: TStyle.h:220
void SetHistLineColor(Color_t color=1)
Definition: TStyle.h:358
Style_t GetHistLineStyle() const
Definition: TStyle.h:223
void SetHistFillStyle(Style_t styl=0)
Definition: TStyle.h:359
Width_t GetHistLineWidth() const
Definition: TStyle.h:224
void SetHistLineWidth(Width_t width=1)
Definition: TStyle.h:361
A zero length substring is legal.
Definition: TString.h:77
TString & String()
Definition: TString.h:116
virtual const char * Getenv(const char *env)
Get environment variable.
Definition: TSystem.cxx:1653
virtual Bool_t AccessPathName(const char *path, EAccessMode mode=kFileExists)
Returns FALSE if one can access a file using the specified access mode.
Definition: TSystem.cxx:1287
A TTreeCache which exploits parallelized decompression of its own content.
static Bool_t IsParallelUnzip()
Static function that tells wether the multithreading unzipping is activated.
A cache to speed-up the reading of ROOT datasets.
Definition: TTreeCache.h:35
virtual Int_t AddBranch(TBranch *b, Bool_t subgbranches=kFALSE)
Add a branch to the list of branches to be stored in the cache this function is called by the user vi...
Definition: TTreeCache.cxx:368
virtual Int_t SetBufferSize(Int_t buffersize)
Change the underlying buffer size of the cache.
static void SetLearnEntries(Int_t n=10)
Static function to set the number of entries to be used in learning mode The default value for n is 1...
TTree * GetTree() const
Definition: TTreeCache.h:152
virtual void SetEntryRange(Long64_t emin, Long64_t emax)
Set the minimum and maximum entry number to be processed this information helps to optimize the numbe...
Bool_t IsAutoCreated() const
Definition: TTreeCache.h:153
void SetAutoCreated(Bool_t val)
Definition: TTreeCache.h:167
virtual Int_t DropBranch(TBranch *b, Bool_t subbranches=kFALSE)
Remove a branch to the list of branches to be stored in the cache this function is called by TBranch:...
Definition: TTreeCache.cxx:533
virtual void StopLearningPhase()
This is the counterpart of StartLearningPhase() and can be used to stop the learning phase.
virtual void Print(Option_t *option="") const
Print cache statistics.
Class implementing or helping the various TTree cloning method.
Definition: TTreeCloner.h:38
Bool_t Exec()
Execute the cloning.
Bool_t IsValid()
Definition: TTreeCloner.h:121
const char * GetWarning() const
Definition: TTreeCloner.h:119
void SetCacheSize(Int_t size)
Set the TFile cache size to be used.
Bool_t NeedConversion()
Definition: TTreeCloner.h:122
Iterator on all the leaves in a TTree and its friend.
Definition: TTree.h:652
TObject * Next()
Go the next friend element.
Definition: TTree.cxx:9547
TTree * fTree
tree being iterated
Definition: TTree.h:655
Option_t * GetOption() const
Returns the object option stored in the list.
Definition: TTree.cxx:9586
TIterator & operator=(const TIterator &rhs)
Overridden assignment operator. Does NOT copy the 'cursor' location!
Definition: TTree.cxx:9524
TIterator * fLeafIter
current leaf sub-iterator.
Definition: TTree.h:656
TIterator * fTreeIter
current tree sub-iterator.
Definition: TTree.h:657
Bool_t fDirection
iteration direction
Definition: TTree.h:658
Helper class to iterate over cluster of baskets.
Definition: TTree.h:258
Long64_t GetEstimatedClusterSize()
Estimate the cluster size.
Definition: TTree.cxx:597
Long64_t Previous()
Move on to the previous cluster and return the starting entry of this previous cluster.
Definition: TTree.cxx:680
Long64_t fNextEntry
Definition: TTree.h:263
Long64_t Next()
Move on to the next cluster and return the starting entry of this next cluster.
Definition: TTree.cxx:636
Long64_t fStartEntry
Definition: TTree.h:262
TClusterIterator(TTree *tree, Long64_t firstEntry)
Regular constructor.
Definition: TTree.cxx:546
Helper class to prevent infinite recursion in the usage of TTree Friends.
Definition: TTree.h:176
TFriendLock & operator=(const TFriendLock &)
Assignment operator.
Definition: TTree.cxx:516
TFriendLock(const TFriendLock &)
Copy constructor.
Definition: TTree.cxx:506
UInt_t fMethodBit
Definition: TTree.h:180
TTree * fTree
Definition: TTree.h:179
~TFriendLock()
Restore the state of tree the same as before we set the lock.
Definition: TTree.cxx:529
Bool_t fPrevious
Definition: TTree.h:181
A TTree represents a columnar dataset.
Definition: TTree.h:72
virtual Int_t Fill()
Fill all branches.
Definition: TTree.cxx:4487
virtual TFriendElement * AddFriend(const char *treename, const char *filename="")
Add a TFriendElement to the list of friends.
Definition: TTree.cxx:1300
TBranchRef * fBranchRef
Branch supporting the TRefTable (if any)
Definition: TTree.h:125
virtual Int_t AddBranchToCache(const char *bname, Bool_t subbranches=kFALSE)
Add branch with name bname to the Tree cache.
Definition: TTree.cxx:1028
virtual TBranch * FindBranch(const char *name)
Return the branch that correspond to the path 'branchname', which can include the name of the tree or...
Definition: TTree.cxx:4723
virtual TBranch * GetBranch(const char *name)
Return pointer to the branch with the given name in this tree or its friends.
Definition: TTree.cxx:5170
static Int_t GetBranchStyle()
Static function returning the current branch style.
Definition: TTree.cxx:5264
TList * fFriends
pointer to list of friend elements
Definition: TTree.h:120
UInt_t fFriendLockStatus
! Record which method is locking the friend recursion
Definition: TTree.h:126
virtual TLeaf * GetLeafImpl(const char *branchname, const char *leafname)
Return pointer to the 1st Leaf named name in any Branch of this Tree or any branch in the list of fri...
Definition: TTree.cxx:5958
Long64_t fTotBytes
Total number of bytes in all branches before compression.
Definition: TTree.h:79
Int_t fMaxClusterRange
! Memory allocated for the cluster range.
Definition: TTree.h:89
virtual void Show(Long64_t entry=-1, Int_t lenmax=20)
Print values of all active leaves for entry.
Definition: TTree.cxx:9096
TEventList * fEventList
! Pointer to event selection list (if one)
Definition: TTree.h:115
virtual Long64_t GetAutoSave() const
Definition: TTree.h:435
virtual Int_t StopCacheLearningPhase()
Stop the cache learning phase.
Definition: TTree.cxx:9185
std::vector< std::pair< Long64_t, TBranch * > > fSortedBranches
! Branches to be processed in parallel when IMT is on, sorted by average task time
Definition: TTree.h:133
virtual void SetCircular(Long64_t maxEntries)
Enable/Disable circularity for this tree.
Definition: TTree.cxx:8629
Long64_t fSavedBytes
Number of autosaved bytes.
Definition: TTree.h:81
virtual TClusterIterator GetClusterIterator(Long64_t firstentry)
Return an iterator over the cluster of baskets starting at firstentry.
Definition: TTree.cxx:5326
virtual void ResetBranchAddress(TBranch *)
Tell all of our branches to set their addresses to zero.
Definition: TTree.cxx:7849
char GetNewlineValue(std::istream &inputStream)
Determine which newline this file is using.
Definition: TTree.cxx:7398
virtual Int_t CheckBranchAddressType(TBranch *branch, TClass *ptrClass, EDataType datatype, Bool_t ptr)
Check whether or not the address described by the last 3 parameters matches the content of the branch...
Definition: TTree.cxx:2809
TIOFeatures fIOFeatures
IO features to define for newly-written baskets and branches.
Definition: TTree.h:107
virtual Long64_t GetEntryNumberWithIndex(Long64_t major, Long64_t minor=0) const
Return entry number corresponding to major and minor number.
Definition: TTree.cxx:5770
Long64_t fDebugMin
! First entry number to debug
Definition: TTree.h:105
virtual Long64_t SetEntries(Long64_t n=-1)
Change number of entries in the tree.
Definition: TTree.cxx:8748
virtual TObjArray * GetListOfLeaves()
Definition: TTree.h:476
Bool_t fCacheDoClusterPrefetch
! true if cache is prefetching whole clusters
Definition: TTree.h:129
virtual TBranch * BranchOld(const char *name, const char *classname, void *addobj, Int_t bufsize=32000, Int_t splitlevel=1)
Create a new TTree BranchObject.
Definition: TTree.cxx:2038
virtual TBranch * BranchRef()
Build the optional branch supporting the TRefTable.
Definition: TTree.cxx:2292
TFile * GetCurrentFile() const
Return pointer to the current file.
Definition: TTree.cxx:5338
TList * fAliases
List of aliases for expressions based on the tree branches.
Definition: TTree.h:114
virtual TTree * CopyTree(const char *selection, Option_t *option="", Long64_t nentries=kMaxEntries, Long64_t firstentry=0)
Copy a tree with selection.
Definition: TTree.cxx:3635
virtual Int_t FlushBaskets(Bool_t create_cluster=true) const
Write to disk all the basket that have not yet been individually written and create an event cluster ...
Definition: TTree.cxx:5005
virtual Int_t Fit(const char *funcname, const char *varexp, const char *selection="", Option_t *option="", Option_t *goption="", Long64_t nentries=kMaxEntries, Long64_t firstentry=0)
Fit a projected item(s) from a tree.
Definition: TTree.cxx:4955
Int_t SetCacheSizeAux(Bool_t autocache=kTRUE, Long64_t cacheSize=0)
Set the size of the file cache and create it if possible.
Definition: TTree.cxx:8449
Long64_t * fClusterRangeEnd
[fNClusterRange] Last entry of a cluster range.
Definition: TTree.h:96
std::atomic< Long64_t > fIMTZipBytes
! Zip bytes for the IMT flush baskets.
Definition: TTree.h:150
void UseCurrentStyle()
Replace current attributes by current style.
Definition: TTree.cxx:9448
TVirtualTreePlayer * GetPlayer()
Load the TTreePlayer (if not already done).
Definition: TTree.cxx:6161
virtual Long64_t ReadStream(std::istream &inputStream, const char *branchDescriptor="", char delimiter=' ')
Create or simply read branches from an input stream.
Definition: TTree.cxx:7425
virtual void SetDebug(Int_t level=1, Long64_t min=0, Long64_t max=9999999)
Set the debug level and the debug range.
Definition: TTree.cxx:8665
Int_t fScanField
Number of runs before prompting in Scan.
Definition: TTree.h:85
virtual ~TTree()
Destructor.
Definition: TTree.cxx:904
virtual TTree * GetFriend(const char *) const
Return a pointer to the TTree friend whose name or alias is 'friendname.
Definition: TTree.cxx:5835
virtual Int_t SetBranchAddress(const char *bname, void *add, TBranch **ptr=0)
Change branch address, dealing with clone trees properly.
Definition: TTree.cxx:8127
virtual Double_t GetMaximum(const char *columname)
Return maximum of column with name columname.
Definition: TTree.cxx:6091
virtual Long64_t GetEntryNumberWithBestIndex(Long64_t major, Long64_t minor=0) const
Return entry number corresponding to major and minor number.
Definition: TTree.cxx:5750
static void SetMaxTreeSize(Long64_t maxsize=100000000000LL)
Set the maximum size in bytes of a Tree file (static function).
Definition: TTree.cxx:8934
virtual TBranch * BronchExec(const char *name, const char *classname, void *addobj, Bool_t isptrptr, Int_t bufsize, Int_t splitlevel)
Helper function implementing TTree::Bronch and TTree::Branch(const char *name, T &obj);.
Definition: TTree.cxx:2376
virtual Int_t UnbinnedFit(const char *funcname, const char *varexp, const char *selection="", Option_t *option="", Long64_t nentries=kMaxEntries, Long64_t firstentry=0)
Unbinned fit of one or more variable(s) from a tree.
Definition: TTree.cxx:9436
Int_t fNClusterRange
Number of Cluster range in addition to the one defined by 'AutoFlush'.
Definition: TTree.h:88
virtual void PrintCacheStats(Option_t *option="") const
Print statistics about the TreeCache for this tree.
Definition: TTree.cxx:7185
virtual Int_t BuildIndex(const char *majorname, const char *minorname="0")
Build a Tree Index (default is TTreeIndex).
Definition: TTree.cxx:2601
TVirtualTreePlayer * fPlayer
! Pointer to current Tree player
Definition: TTree.h:123
virtual void SetMakeClass(Int_t make)
Set all the branches in this TTree to be in decomposed object mode (also known as MakeClass mode).
Definition: TTree.cxx:8914
TObjArray fBranches
List of Branches.
Definition: TTree.h:112
TDirectory * GetDirectory() const
Definition: TTree.h:449
TTreeCache * GetReadCache(TFile *file) const
Find and return the TTreeCache registered with the file and which may contain branches for us.
Definition: TTree.cxx:6174
Bool_t fCacheUserSet
! true if the cache setting was explicitly given by user
Definition: TTree.h:130
Long64_t fEntries
Number of entries.
Definition: TTree.h:77
virtual TFile * ChangeFile(TFile *file)
Called by TTree::Fill() when file has reached its maximum fgMaxTreeSize.
Definition: TTree.cxx:2691
virtual Bool_t GetBranchStatus(const char *branchname) const
Return status of branch with name branchname.
Definition: TTree.cxx:5249
virtual TEntryList * GetEntryList()
Returns the entry list assigned to this tree.
Definition: TTree.cxx:5714
virtual void SetWeight(Double_t w=1, Option_t *option="")
Set tree weight.
Definition: TTree.cxx:9085
void InitializeBranchLists(bool checkLeafCount)
Divides the top-level branches into two vectors: (i) branches to be processed sequentially and (ii) b...
Definition: TTree.cxx:5641
Long64_t * fClusterSize
[fNClusterRange] Number of entries in each cluster for a given range.
Definition: TTree.h:97
Long64_t fFlushedBytes
Number of auto-flushed bytes.
Definition: TTree.h:82
virtual void SetPerfStats(TVirtualPerfStats *perf)
Set perf stats.
Definition: TTree.cxx:9040
std::atomic< Long64_t > fIMTTotBytes
! Total bytes for the IMT flush baskets
Definition: TTree.h:149
virtual void SetCacheLearnEntries(Int_t n=10)
Interface to TTreeCache to set the number of entries for the learning phase.
Definition: TTree.cxx:8602
TEntryList * fEntryList
! Pointer to event selection list (if one)
Definition: TTree.h:116
virtual TVirtualIndex * GetTreeIndex() const
Definition: TTree.h:505
virtual Long64_t Merge(TCollection *list, Option_t *option="")
Merge the trees in the TList into this tree.
Definition: TTree.cxx:6762
virtual void SetMaxVirtualSize(Long64_t size=0)
Definition: TTree.h:609
virtual void DropBaskets()
Remove some baskets from memory.
Definition: TTree.cxx:4406
virtual void SetAutoSave(Long64_t autos=-300000000)
This function may be called at the start of a program to change the default value for fAutoSave (and ...
Definition: TTree.cxx:8084
Long64_t fMaxEntryLoop
Maximum number of entries to process.
Definition: TTree.h:91
virtual void SetDirectory(TDirectory *dir)
Change the tree's directory.
Definition: TTree.cxx:8703
virtual Long64_t CopyEntries(TTree *tree, Long64_t nentries=-1, Option_t *option="")
Copy nentries from given tree to this tree.
Definition: TTree.cxx:3466
void SortBranchesByTime()
Sorts top-level branches by the last average task time recorded per branch.
Definition: TTree.cxx:5694
virtual TBranchRef * GetBranchRef() const
Definition: TTree.h:437
virtual Long64_t Process(const char *filename, Option_t *option="", Long64_t nentries=kMaxEntries, Long64_t firstentry=0)
Process this tree executing the TSelector code in the specified filename.
Definition: TTree.cxx:7265
virtual TBranch * BranchImpRef(const char *branchname, const char *classname, TClass *ptrClass, void *addobj, Int_t bufsize, Int_t splitlevel)
Same as TTree::Branch but automatic detection of the class name.
Definition: TTree.cxx:1602
virtual void SetEventList(TEventList *list)
This function transfroms the given TEventList into a TEntryList The new TEntryList is owned by the TT...
Definition: TTree.cxx:8806
void MoveReadCache(TFile *src, TDirectory *dir)
Move a cache from a file to the current file in dir.
Definition: TTree.cxx:6857
Long64_t fAutoFlush
Auto-flush tree when fAutoFlush entries written or -fAutoFlush (compressed) bytes produced.
Definition: TTree.h:94
Int_t fUpdate
Update frequency for EntryLoop.
Definition: TTree.h:86
virtual void ResetAfterMerge(TFileMergeInfo *)
Resets the state of this TTree after a merge (keep the customization but forget the data).
Definition: TTree.cxx:7818
virtual void CopyAddresses(TTree *, Bool_t undo=kFALSE)
Set branch addresses of passed tree equal to ours.
Definition: TTree.cxx:3238
@ kSplitCollectionOfPointers
Definition: TTree.h:254
virtual Long64_t GetEntries() const
Definition: TTree.h:450
virtual void SetEstimate(Long64_t nentries=1000000)
Set number of entries to estimate variable limits.
Definition: TTree.cxx:8847
virtual TIterator * GetIteratorOnAllLeaves(Bool_t dir=kIterForward)
Creates a new iterator that will go through all the leaves on the tree itself and its friend.
Definition: TTree.cxx:5942
Int_t fTimerInterval
Timer interval in milliseconds.
Definition: TTree.h:84
Int_t fDebug
! Debug level
Definition: TTree.h:104
virtual Long64_t AutoSave(Option_t *option="")
AutoSave tree header every fAutoSave bytes.
Definition: TTree.cxx:1467
virtual Long64_t GetEntryNumber(Long64_t entry) const
Return entry number corresponding to entry.
Definition: TTree.cxx:5725
virtual TTree * CloneTree(Long64_t nentries=-1, Option_t *option="")
Create a clone of this tree and copy nentries.
Definition: TTree.cxx:3078
Int_t fFileNumber
! current file number (if file extensions)
Definition: TTree.h:109
virtual TLeaf * GetLeaf(const char *branchname, const char *leafname)
Return pointer to the 1st Leaf named name in any Branch of this Tree or any branch in the list of fri...
Definition: TTree.cxx:6051
virtual Long64_t GetZipBytes() const
Definition: TTree.h:532
TObjArray fLeaves
Direct pointers to individual branch leaves.
Definition: TTree.h:113
virtual void Reset(Option_t *option="")
Reset baskets, buffers and entries count in all branches and leaves.
Definition: TTree.cxx:7787
virtual void Print(Option_t *option="") const
Print a summary of the tree contents.
Definition: TTree.cxx:7065
virtual void KeepCircular()
Keep a maximum of fMaxEntries in memory.
Definition: TTree.cxx:6271
virtual void DirectoryAutoAdd(TDirectory *)
Called by TKey and TObject::Clone to automatically add us to a directory when we are read from a file...
Definition: TTree.cxx:3735
Long64_t GetCacheAutoSize(Bool_t withDefault=kFALSE) const
Used for automatic sizing of the cache.
Definition: TTree.cxx:5276
virtual Bool_t SetAlias(const char *aliasName, const char *aliasFormula)
Set a tree variable alias.
Definition: TTree.cxx:7920
Long64_t fMaxVirtualSize
Maximum total size of buffers kept in memory.
Definition: TTree.h:92
virtual Long64_t GetTotBytes() const
Definition: TTree.h:503
virtual void SetObject(const char *name, const char *title)
Change the name and title of this tree.
Definition: TTree.cxx:8971
TVirtualPerfStats * fPerfStats
! pointer to the current perf stats object
Definition: TTree.h:121
Double_t fWeight
Tree weight (see TTree::SetWeight)
Definition: TTree.h:83
std::vector< TBranch * > fSeqBranches
! Branches to be processed sequentially when IMT is on
Definition: TTree.h:134
Long64_t fDebugMax
! Last entry number to debug
Definition: TTree.h:106
Int_t fDefaultEntryOffsetLen
Initial Length of fEntryOffset table in the basket buffers.
Definition: TTree.h:87
TTree()
Default constructor and I/O constructor.
Definition: TTree.cxx:723
Long64_t fAutoSave
Autosave tree when fAutoSave entries written or -fAutoSave (compressed) bytes produced.
Definition: TTree.h:93
TBranch * Branch(const char *name, T *obj, Int_t bufsize=32000, Int_t splitlevel=99)
Add a new branch, and infer the data type from the type of obj being passed.
Definition: TTree.h:341
virtual void SetDefaultEntryOffsetLen(Int_t newdefault, Bool_t updateExisting=kFALSE)
Update the default value for the branch's fEntryOffsetLen.
Definition: TTree.cxx:8677
std::atomic< UInt_t > fAllocationCount
indicates basket should be resized to exact memory usage, but causes significant
Definition: TTree.h:141
virtual Int_t GetEntryWithIndex(Int_t major, Int_t minor=0)
Read entry corresponding to major and minor number.
Definition: TTree.cxx:5787
static TTree * MergeTrees(TList *list, Option_t *option="")
Static function merging the trees in the TList into a new tree.
Definition: TTree.cxx:6719
virtual Long64_t GetReadEntry() const
Definition: TTree.h:496
virtual TObjArray * GetListOfBranches()
Definition: TTree.h:475
virtual void SetParallelUnzip(Bool_t opt=kTRUE, Float_t RelSize=-1)
Enable or disable parallel unzipping of Tree buffers.
Definition: TTree.cxx:9002
Long64_t fZipBytes
Total number of bytes in all branches after compression.
Definition: TTree.h:80
virtual void RecursiveRemove(TObject *obj)
Make sure that obj (which is being deleted or will soon be) is no longer referenced by this TTree.
Definition: TTree.cxx:7691
virtual TTree * GetTree() const
Definition: TTree.h:504
TBuffer * fTransientBuffer
! Pointer to the current transient buffer.
Definition: TTree.h:127
Bool_t fIMTEnabled
! true if implicit multi-threading is enabled for this tree
Definition: TTree.h:131
virtual void SetEntryList(TEntryList *list, Option_t *opt="")
Set an EntryList.
Definition: TTree.cxx:8783
virtual Int_t DropBranchFromCache(const char *bname, Bool_t subbranches=kFALSE)
Remove the branch with name 'bname' from the Tree cache.
Definition: TTree.cxx:1111
virtual void AddZipBytes(Int_t zip)
Definition: TTree.h:320
virtual Long64_t LoadTree(Long64_t entry)
Set current entry.
Definition: TTree.cxx:6329
virtual Long64_t ReadFile(const char *filename, const char *branchDescriptor="", char delimiter=' ')
Create or simply read branches from filename.
Definition: TTree.cxx:7379
virtual const char * GetAlias(const char *aliasName) const
Returns the expanded value of the alias. Search in the friends if any.
Definition: TTree.cxx:5102
ROOT::TIOFeatures SetIOFeatures(const ROOT::TIOFeatures &)
Provide the end-user with the ability to enable/disable various experimental IO features for this TTr...
Definition: TTree.cxx:8867
virtual Int_t GetEntry(Long64_t entry=0, Int_t getall=0)
Read all branches of entry and return total number of bytes read.
Definition: TTree.cxx:5497
virtual TBasket * CreateBasket(TBranch *)
Create a basket for this tree and given branch.
Definition: TTree.cxx:3647
TList * fUserInfo
pointer to a list of user objects associated to this Tree
Definition: TTree.h:122
virtual Double_t GetMinimum(const char *columname)
Return minimum of column with name columname.
Definition: TTree.cxx:6131
virtual void RemoveFriend(TTree *)
Remove a friend from the list of friends.
Definition: TTree.cxx:7761
virtual Long64_t GetEntriesFast() const
Definition: TTree.h:452
virtual TList * GetUserInfo()
Return a pointer to the list containing user objects associated to this tree.
Definition: TTree.cxx:6212
Long64_t fChainOffset
! Offset of 1st entry of this Tree in a TChain
Definition: TTree.h:99
@ kOnlyFlushAtCluster
If set, the branch's buffers will grow until an event cluster boundary is hit, guaranteeing a basket ...
Definition: TTree.h:244
@ kEntriesReshuffled
If set, signals that this TTree is the output of the processing of another TTree, and the entries are...
Definition: TTree.h:249
@ kCircular
Definition: TTree.h:240
virtual Long64_t GetEntriesFriend() const
Return pointer to the 1st Leaf named name in any Branch of this Tree or any branch in the list of fri...
Definition: TTree.cxx:5371
virtual TSQLResult * Query(const char *varexp="", const char *selection="", Option_t *option="", Long64_t nentries=kMaxEntries, Long64_t firstentry=0)
Loop over entries and return a TSQLResult object containing entries following selection.
Definition: TTree.cxx:7328
virtual TBranch * Bronch(const char *name, const char *classname, void *addobj, Int_t bufsize=32000, Int_t splitlevel=99)
Create a new TTree BranchElement.
Definition: TTree.cxx:2368
virtual void SetBasketSize(const char *bname, Int_t buffsize=16000)
Set a branch's basket size.
Definition: TTree.cxx:8100
static void SetBranchStyle(Int_t style=1)
Set the current branch style.
Definition: TTree.cxx:8407
void ImportClusterRanges(TTree *fromtree)
Appends the cluster range information stored in 'fromtree' to this tree, including the value of fAuto...
Definition: TTree.cxx:6228
Long64_t fEstimate
Number of entries to estimate histogram limits.
Definition: TTree.h:95
Int_t FlushBasketsImpl() const
Internal implementation of the FlushBaskets algorithm.
Definition: TTree.cxx:5022
virtual Long64_t LoadTreeFriend(Long64_t entry, TTree *T)
Load entry on behalf of our master tree, we may use an index.
Definition: TTree.cxx:6425
TVirtualIndex * fTreeIndex
Pointer to the tree Index (if any)
Definition: TTree.h:119
virtual void Browse(TBrowser *)
Browse content of the TTree.
Definition: TTree.cxx:2573
virtual Int_t GetTreeNumber() const
Definition: TTree.h:506
TObject * fNotify
! Object to be notified when loading a Tree
Definition: TTree.h:110
virtual TBranch * BranchImp(const char *branchname, const char *classname, TClass *ptrClass, void *addobj, Int_t bufsize, Int_t splitlevel)
Same as TTree::Branch() with added check that addobj matches className.
Definition: TTree.cxx:1521
Long64_t fCacheSize
! Maximum size of file buffers
Definition: TTree.h:98
TList * fClones
! List of cloned trees which share our addresses
Definition: TTree.h:124
std::atomic< Long64_t > fTotalBuffers
! Total number of bytes in branch buffers
Definition: TTree.h:101
Bool_t fCacheDoAutoInit
! true if cache auto creation or resize check is needed
Definition: TTree.h:128
virtual Int_t MakeSelector(const char *selector=0, Option_t *option="")
Generate skeleton selector class for this tree.
Definition: TTree.cxx:6690
@ kFindBranch
Definition: TTree.h:200
@ kFindLeaf
Definition: TTree.h:201
@ kGetEntryWithIndex
Definition: TTree.h:205
@ kPrint
Definition: TTree.h:210
@ kGetFriend
Definition: TTree.h:206
@ kGetBranch
Definition: TTree.h:203
@ kSetBranchStatus
Definition: TTree.h:212
@ kLoadTree
Definition: TTree.h:209
@ kGetEntry
Definition: TTree.h:204
@ kGetLeaf
Definition: TTree.h:208
@ kRemoveFriend
Definition: TTree.h:211
@ kGetFriendAlias
Definition: TTree.h:207
@ kGetAlias
Definition: TTree.h:202
virtual void Draw(Option_t *opt)
Default Draw method for all objects.
Definition: TTree.h:419
virtual Int_t MakeClass(const char *classname=0, Option_t *option="")
Generate a skeleton analysis class for this tree.
Definition: TTree.cxx:6475
virtual void SetTreeIndex(TVirtualIndex *index)
The current TreeIndex is replaced by the new index.
Definition: TTree.cxx:9057
virtual void OptimizeBaskets(ULong64_t maxMemory=10000000, Float_t minComp=1.1, Option_t *option="")
This function may be called after having filled some entries in a Tree.
Definition: TTree.cxx:6903
virtual Long64_t Project(const char *hname, const char *varexp, const char *selection="", Option_t *option="", Long64_t nentries=kMaxEntries, Long64_t firstentry=0)
Make a projection of a tree using selections.
Definition: TTree.cxx:7313
virtual Int_t SetCacheEntryRange(Long64_t first, Long64_t last)
interface to TTreeCache to set the cache entry range
Definition: TTree.cxx:8568
static Long64_t GetMaxTreeSize()
Static function which returns the tree file size limit in bytes.
Definition: TTree.cxx:6121
Int_t SetBranchAddressImp(TBranch *branch, void *addr, TBranch **ptr)
Change branch address, dealing with clone trees properly.
Definition: TTree.cxx:8187
Long64_t fMaxEntries
Maximum number of entries in case of circular buffers.
Definition: TTree.h:90
virtual void DropBuffers(Int_t nbytes)
Drop branch buffers to accommodate nbytes below MaxVirtualsize.
Definition: TTree.cxx:4419
virtual void SetName(const char *name)
Change the name of this tree.
Definition: TTree.cxx:8942
virtual void Delete(Option_t *option="")
Delete this tree from memory or/and disk.
Definition: TTree.cxx:3663
virtual TList * GetListOfFriends() const
Definition: TTree.h:477
virtual void Refresh()
Refresh contents of this tree and its branches from the current status on disk.
Definition: TTree.cxx:7722
virtual void SetAutoFlush(Long64_t autof=-30000000)
This function may be called at the start of a program to change the default value for fAutoFlush.
Definition: TTree.cxx:7975
static Long64_t fgMaxTreeSize
Maximum size of a file containing a Tree.
Definition: TTree.h:144
Long64_t fReadEntry
! Number of the entry being processed
Definition: TTree.h:100
TArrayD fIndexValues
Sorted index values.
Definition: TTree.h:117
void MarkEventCluster()
Mark the previous event as being at the end of the event cluster.
Definition: TTree.cxx:8037
virtual Int_t MakeCode(const char *filename=0)
Generate a skeleton function for this tree.
Definition: TTree.cxx:6508
UInt_t fNEntriesSinceSorting
! Number of entries processed since the last re-sorting of branches
Definition: TTree.h:132
virtual Int_t MakeProxy(const char *classname, const char *macrofilename=0, const char *cutfilename=0, const char *option=0, Int_t maxUnrolling=3)
Generate a skeleton analysis class for this Tree using TBranchProxy.
Definition: TTree.cxx:6636
virtual void SetFileNumber(Int_t number=0)
Set fFileNumber to number.
Definition: TTree.cxx:8890
virtual TLeaf * FindLeaf(const char *name)
Find leaf..
Definition: TTree.cxx:4795
virtual void StartViewer()
Start the TTreeViewer on this tree.
Definition: TTree.cxx:9170
Int_t GetMakeClass() const
Definition: TTree.h:482
TDirectory * fDirectory
! Pointer to directory holding this tree
Definition: TTree.h:111
@ kNeedEnableDecomposedObj
Definition: TTree.h:232
@ kClassMismatch
Definition: TTree.h:225
@ kVoidPtr
Definition: TTree.h:230
@ kMatchConversionCollection
Definition: TTree.h:228
@ kMissingCompiledCollectionProxy
Definition: TTree.h:223
@ kMismatch
Definition: TTree.h:224
@ kMatchConversion
Definition: TTree.h:227
@ kInternalError
Definition: TTree.h:222
@ kMatch
Definition: TTree.h:226
@ kMissingBranch
Definition: TTree.h:221
@ kMakeClass
Definition: TTree.h:229
static Int_t fgBranchStyle
Old/New branch style.
Definition: TTree.h:143
virtual void ResetBranchAddresses()
Tell all of our branches to drop their current objects and allocate new ones.
Definition: TTree.cxx:7859
Int_t fNfill
! Local for EntryLoop
Definition: TTree.h:103
TArrayI fIndex
Index of sorted values.
Definition: TTree.h:118
virtual Int_t SetCacheSize(Long64_t cachesize=-1)
Set maximum size of the file cache .
Definition: TTree.cxx:8423
void AddClone(TTree *)
Add a cloned tree to our list of trees to be notified whenever we change our branch addresses or when...
Definition: TTree.cxx:1188
virtual void SetBranchStatus(const char *bname, Bool_t status=1, UInt_t *found=0)
Set branch status to Process or DoNotProcess.
Definition: TTree.cxx:8276
TBuffer * GetTransientBuffer(Int_t size)
Returns the transient buffer currently used by this TTree for reading/writing baskets.
Definition: TTree.cxx:1006
ROOT::TIOFeatures GetIOFeatures() const
Returns the current set of IO settings.
Definition: TTree.cxx:5934
virtual const char * GetFriendAlias(TTree *) const
If the 'tree' is a friend, this method returns its alias name.
Definition: TTree.cxx:5892
virtual Bool_t Notify()
Function called when loading a new class library.
Definition: TTree.cxx:6879
Bool_t MemoryFull(Int_t nbytes)
Check if adding nbytes to memory we are still below MaxVirtualsize.
Definition: TTree.cxx:6705
Int_t fPacketSize
! Number of entries in one packet for parallel root
Definition: TTree.h:102
virtual Int_t Write(const char *name=0, Int_t option=0, Int_t bufsize=0)
Write this object to the current directory.
Definition: TTree.cxx:9485
TStreamerInfo * BuildStreamerInfo(TClass *cl, void *pointer=0, Bool_t canOptimize=kTRUE)
Build StreamerInfo for class cl.
Definition: TTree.cxx:2616
virtual TBranch * BranchImpArr(const char *branchname, EDataType datatype, std::size_t N, void *addobj, Int_t bufsize, Int_t splitlevel)
Definition: TTree.cxx:1698
virtual Long64_t Scan(const char *varexp="", const char *selection="", Option_t *option="", Long64_t nentries=kMaxEntries, Long64_t firstentry=0)
Loop over tree entries and print entries passing selection.
Definition: TTree.cxx:7878
Bool_t fIMTFlush
! True if we are doing a multithreaded flush.
Definition: TTree.h:148
virtual void AddTotBytes(Int_t tot)
Definition: TTree.h:319
Int_t fMakeClass
! not zero when processing code generated by MakeClass
Definition: TTree.h:108
virtual Int_t LoadBaskets(Long64_t maxmemory=2000000000)
Read in memory all baskets from all branches up to the limit of maxmemory bytes.
Definition: TTree.cxx:6307
static constexpr Long64_t kMaxEntries
Definition: TTree.h:217
TPrincipal * Principal(const char *varexp="", const char *selection="", Option_t *option="np", Long64_t nentries=kMaxEntries, Long64_t firstentry=0)
Interface to the Principal Components Analysis class.
Definition: TTree.cxx:7046
virtual Long64_t GetAutoFlush() const
Definition: TTree.h:434
virtual EDataType GetType() const =0
virtual TClass * GetValueClass() const =0
virtual Bool_t HasPointers() const =0
Abstract interface for Tree Index.
Definition: TVirtualIndex.h:30
virtual void Append(const TVirtualIndex *, Bool_t delaySort=kFALSE)=0
virtual const char * GetMajorName() const =0
virtual Long64_t GetEntryNumberWithIndex(Long64_t major, Long64_t minor) const =0
virtual Long64_t GetEntryNumberFriend(const TTree *)=0
virtual const char * GetMinorName() const =0
virtual void SetTree(const TTree *T)=0
virtual Long64_t GetN() const =0
virtual Long64_t GetEntryNumberWithBestIndex(Long64_t major, Long64_t minor) const =0
virtual Bool_t IsValidFor(const TTree *parent)=0
Provides the interface for the PROOF internal performance measurement and event tracing.
Abstract base class defining the interface for the plugins that implement Draw, Scan,...
virtual Int_t MakeProxy(const char *classname, const char *macrofilename=0, const char *cutfilename=0, const char *option=0, Int_t maxUnrolling=3)=0
virtual Long64_t Scan(const char *varexp, const char *selection, Option_t *option, Long64_t nentries, Long64_t firstentry)=0
virtual void UpdateFormulaLeaves()=0
virtual Long64_t DrawSelect(const char *varexp, const char *selection, Option_t *option, Long64_t nentries, Long64_t firstentry)=0
virtual Int_t MakeCode(const char *filename)=0
virtual Int_t UnbinnedFit(const char *formula, const char *varexp, const char *selection, Option_t *option, Long64_t nentries, Long64_t firstentry)=0
virtual Long64_t GetEntries(const char *)=0
virtual TSQLResult * Query(const char *varexp, const char *selection, Option_t *option, Long64_t nentries, Long64_t firstentry)=0
virtual TPrincipal * Principal(const char *varexp="", const char *selection="", Option_t *option="np", Long64_t nentries=kMaxEntries, Long64_t firstentry=0)=0
virtual void StartViewer(Int_t ww, Int_t wh)=0
virtual Int_t MakeReader(const char *classname, Option_t *option)=0
virtual TVirtualIndex * BuildIndex(const TTree *T, const char *majorname, const char *minorname)=0
virtual TTree * CopyTree(const char *selection, Option_t *option="", Long64_t nentries=kMaxEntries, Long64_t firstentry=0)=0
virtual Long64_t Process(const char *filename, Option_t *option="", Long64_t nentries=kMaxEntries, Long64_t firstentry=0)=0
virtual void SetEstimate(Long64_t n)=0
static TVirtualTreePlayer * TreePlayer(TTree *obj)
Static function returning a pointer to a Tree player.
virtual Int_t MakeClass(const char *classname, const char *option)=0
virtual Int_t Fit(const char *formula, const char *varexp, const char *selection, Option_t *option, Option_t *goption, Long64_t nentries, Long64_t firstentry)=0
TLine * line
const Int_t n
Definition: legend1.C:16
constexpr std::array< decltype(std::declval< F >()(std::declval< int >())), N > make(F f)
VSD Structures.
Definition: StringConv.hxx:21
Bool_t IsImplicitMTEnabled()
Returns true if the implicit multi-threading in ROOT is enabled.
Definition: TROOT.cxx:611
ESTLType
Definition: ESTLType.h:28
@ kSTLmap
Definition: ESTLType.h:33
@ kSTLmultimap
Definition: ESTLType.h:34
void ToHumanReadableSize(value_type bytes, Bool_t si, Double_t *coeff, const char **units)
Return the size expressed in 'human readable' format.
Definition: StringConv.hxx:38
EFromHumanReadableSize FromHumanReadableSize(std::string_view str, T &value)
Convert strings like the following into byte counts 5MB, 5 MB, 5M, 3.7GB, 123b, 456kB,...
Definition: StringConv.hxx:86
static constexpr double s
Short_t Max(Short_t a, Short_t b)
Definition: TMathBase.h:212
Short_t Min(Short_t a, Short_t b)
Definition: TMathBase.h:180
Long64_t BinarySearch(Long64_t n, const T *array, T value)
Definition: TMathBase.h:278
Definition: file.py:1
Definition: first.py:1
Definition: tree.py:1
const char * Size
Definition: TXMLSetup.cxx:55
TCanvas * slash()
Definition: slash.C:1
@ kUseGlobal
Use the global compression algorithm.
Definition: Compression.h:83
@ kInherit
Some objects use this value to denote that the compression algorithm should be inherited from the par...
Definition: Compression.h:81
@ kUseCompiledDefault
Use the compile-time default setting.
Definition: Compression.h:50
TCanvas * style()
Definition: style.C:1
auto * m
Definition: textangle.C:8
auto * l
Definition: textangle.C:4
auto * a
Definition: textangle.C:12