Logo ROOT   6.18/05
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 } else {
608 Long64_t clusterEstimate = 1;
609 Long64_t cacheSize = fTree->GetCacheSize();
610 if (cacheSize == 0) {
611 // Humm ... let's double check on the file.
612 TFile *file = fTree->GetCurrentFile();
613 if (file) {
614 TFileCacheRead *cache = fTree->GetReadCache(file);
615 if (cache) {
616 cacheSize = cache->GetBufferSize();
617 }
618 }
619 }
620 // If neither file nor tree has a cache, use the current default.
621 if (cacheSize <= 0) {
622 cacheSize = 30000000;
623 }
624 clusterEstimate = fTree->GetEntries() * cacheSize / zipBytes;
625 // If there are no entries, then just default to 1.
626 fEstimatedSize = clusterEstimate ? clusterEstimate : 1;
627 }
628 return fEstimatedSize;
629}
630
631////////////////////////////////////////////////////////////////////////////////
632/// Move on to the next cluster and return the starting entry
633/// of this next cluster
636{
637 fStartEntry = fNextEntry;
638 if (fTree->fNClusterRange || fTree->GetAutoFlush() > 0) {
639 if (fClusterRange == fTree->fNClusterRange) {
640 // We are looking at a range which size
641 // is defined by AutoFlush itself and goes to the GetEntries.
642 fNextEntry += GetEstimatedClusterSize();
643 } else {
644 if (fStartEntry > fTree->fClusterRangeEnd[fClusterRange]) {
645 ++fClusterRange;
646 }
647 if (fClusterRange == fTree->fNClusterRange) {
648 // We are looking at the last range which size
649 // is defined by AutoFlush itself and goes to the GetEntries.
650 fNextEntry += GetEstimatedClusterSize();
651 } else {
652 Long64_t clusterSize = fTree->fClusterSize[fClusterRange];
653 if (clusterSize == 0) {
654 clusterSize = GetEstimatedClusterSize();
655 }
656 fNextEntry += clusterSize;
657 if (fNextEntry > fTree->fClusterRangeEnd[fClusterRange]) {
658 // The last cluster of the range was a partial cluster,
659 // so the next cluster starts at the beginning of the
660 // next range.
661 fNextEntry = fTree->fClusterRangeEnd[fClusterRange] + 1;
662 }
663 }
664 }
665 } else {
666 // Case of old files before November 9 2009
667 fNextEntry = fStartEntry + GetEstimatedClusterSize();
668 }
669 if (fNextEntry > fTree->GetEntries()) {
670 fNextEntry = fTree->GetEntries();
671 }
672 return fStartEntry;
673}
674
675////////////////////////////////////////////////////////////////////////////////
676/// Move on to the previous cluster and return the starting entry
677/// of this previous cluster
680{
681 fNextEntry = fStartEntry;
682 if (fTree->fNClusterRange || fTree->GetAutoFlush() > 0) {
683 if (fClusterRange == 0 || fTree->fNClusterRange == 0) {
684 // We are looking at a range which size
685 // is defined by AutoFlush itself.
686 fStartEntry -= GetEstimatedClusterSize();
687 } else {
688 if (fNextEntry <= fTree->fClusterRangeEnd[fClusterRange]) {
689 --fClusterRange;
690 }
691 if (fClusterRange == 0) {
692 // We are looking at the first range.
693 fStartEntry = 0;
694 } else {
695 Long64_t clusterSize = fTree->fClusterSize[fClusterRange];
696 if (clusterSize == 0) {
697 clusterSize = GetEstimatedClusterSize();
698 }
699 fStartEntry -= clusterSize;
700 }
701 }
702 } else {
703 // Case of old files before November 9 2009 or trees that never auto-flushed.
704 fStartEntry = fNextEntry - GetEstimatedClusterSize();
705 }
706 if (fStartEntry < 0) {
707 fStartEntry = 0;
708 }
709 return fStartEntry;
710}
711
712////////////////////////////////////////////////////////////////////////////////
713////////////////////////////////////////////////////////////////////////////////
714////////////////////////////////////////////////////////////////////////////////
715
716////////////////////////////////////////////////////////////////////////////////
717/// Default constructor and I/O constructor.
718///
719/// Note: We do *not* insert ourself into the current directory.
720///
723: TNamed()
724, TAttLine()
725, TAttFill()
726, TAttMarker()
727, fEntries(0)
728, fTotBytes(0)
729, fZipBytes(0)
730, fSavedBytes(0)
731, fFlushedBytes(0)
732, fWeight(1)
734, fScanField(25)
735, fUpdate(0)
739, fMaxEntries(0)
740, fMaxEntryLoop(0)
742, fAutoSave( -300000000)
743, fAutoFlush(-30000000)
744, fEstimate(1000000)
746, fClusterSize(0)
747, fCacheSize(0)
748, fChainOffset(0)
749, fReadEntry(-1)
750, fTotalBuffers(0)
751, fPacketSize(100)
752, fNfill(0)
753, fDebug(0)
754, fDebugMin(0)
755, fDebugMax(9999999)
756, fMakeClass(0)
757, fFileNumber(0)
758, fNotify(0)
759, fDirectory(0)
760, fBranches()
761, fLeaves()
762, fAliases(0)
763, fEventList(0)
764, fEntryList(0)
765, fIndexValues()
766, fIndex()
767, fTreeIndex(0)
768, fFriends(0)
769, fPerfStats(0)
770, fUserInfo(0)
771, fPlayer(0)
772, fClones(0)
773, fBranchRef(0)
781{
782 fMaxEntries = 1000000000;
783 fMaxEntries *= 1000;
784
785 fMaxEntryLoop = 1000000000;
786 fMaxEntryLoop *= 1000;
787
789}
790
791////////////////////////////////////////////////////////////////////////////////
792/// Normal tree constructor.
793///
794/// The tree is created in the current directory.
795/// Use the various functions Branch below to add branches to this tree.
796///
797/// If the first character of title is a "/", the function assumes a folder name.
798/// In this case, it creates automatically branches following the folder hierarchy.
799/// splitlevel may be used in this case to control the split level.
801TTree::TTree(const char* name, const char* title, Int_t splitlevel /* = 99 */,
802 TDirectory* dir /* = gDirectory*/)
803: TNamed(name, title)
804, TAttLine()
805, TAttFill()
806, TAttMarker()
807, fEntries(0)
808, fTotBytes(0)
809, fZipBytes(0)
810, fSavedBytes(0)
811, fFlushedBytes(0)
812, fWeight(1)
813, fTimerInterval(0)
814, fScanField(25)
815, fUpdate(0)
816, fDefaultEntryOffsetLen(1000)
817, fNClusterRange(0)
818, fMaxClusterRange(0)
819, fMaxEntries(0)
820, fMaxEntryLoop(0)
821, fMaxVirtualSize(0)
822, fAutoSave( -300000000)
823, fAutoFlush(-30000000)
824, fEstimate(1000000)
825, fClusterRangeEnd(0)
826, fClusterSize(0)
827, fCacheSize(0)
828, fChainOffset(0)
829, fReadEntry(-1)
830, fTotalBuffers(0)
831, fPacketSize(100)
832, fNfill(0)
833, fDebug(0)
834, fDebugMin(0)
835, fDebugMax(9999999)
836, fMakeClass(0)
837, fFileNumber(0)
838, fNotify(0)
839, fDirectory(dir)
840, fBranches()
841, fLeaves()
842, fAliases(0)
843, fEventList(0)
844, fEntryList(0)
845, fIndexValues()
846, fIndex()
847, fTreeIndex(0)
848, fFriends(0)
849, fPerfStats(0)
850, fUserInfo(0)
851, fPlayer(0)
852, fClones(0)
853, fBranchRef(0)
854, fFriendLockStatus(0)
855, fTransientBuffer(0)
856, fCacheDoAutoInit(kTRUE)
857, fCacheDoClusterPrefetch(kFALSE)
858, fCacheUserSet(kFALSE)
859, fIMTEnabled(ROOT::IsImplicitMTEnabled())
860, fNEntriesSinceSorting(0)
861{
862 // TAttLine state.
866
867 // TAttFill state.
870
871 // TAttMarkerState.
875
876 fMaxEntries = 1000000000;
877 fMaxEntries *= 1000;
878
879 fMaxEntryLoop = 1000000000;
880 fMaxEntryLoop *= 1000;
881
882 // Insert ourself into the current directory.
883 // FIXME: This is very annoying behaviour, we should
884 // be able to choose to not do this like we
885 // can with a histogram.
886 if (fDirectory) fDirectory->Append(this);
887
889
890 // If title starts with "/" and is a valid folder name, a superbranch
891 // is created.
892 // FIXME: Why?
893 if (strlen(title) > 2) {
894 if (title[0] == '/') {
895 Branch(title+1,32000,splitlevel);
896 }
897 }
898}
899
900////////////////////////////////////////////////////////////////////////////////
901/// Destructor.
904{
905 if (auto link = dynamic_cast<TNotifyLinkBase*>(fNotify)) {
906 link->Clear();
907 }
908 if (fAllocationCount && (gDebug > 0)) {
909 Info("TTree::~TTree", "For tree %s, allocation count is %u.", GetName(), fAllocationCount.load());
910#ifdef R__TRACK_BASKET_ALLOC_TIME
911 Info("TTree::~TTree", "For tree %s, allocation time is %lluus.", GetName(), fAllocationTime.load());
912#endif
913 }
914
915 if (fDirectory) {
916 // We are in a directory, which may possibly be a file.
917 if (fDirectory->GetList()) {
918 // Remove us from the directory listing.
919 fDirectory->Remove(this);
920 }
921 //delete the file cache if it points to this Tree
924 }
925 // We don't own the leaves in fLeaves, the branches do.
926 fLeaves.Clear();
927 // I'm ready to destroy any objects allocated by
928 // SetAddress() by my branches. If I have clones,
929 // tell them to zero their pointers to this shared
930 // memory.
931 if (fClones && fClones->GetEntries()) {
932 // I have clones.
933 // I am about to delete the objects created by
934 // SetAddress() which we are sharing, so tell
935 // the clones to release their pointers to them.
936 for (TObjLink* lnk = fClones->FirstLink(); lnk; lnk = lnk->Next()) {
937 TTree* clone = (TTree*) lnk->GetObject();
938 // clone->ResetBranchAddresses();
939
940 // Reset only the branch we have set the address of.
941 CopyAddresses(clone,kTRUE);
942 }
943 }
944 // Get rid of our branches, note that this will also release
945 // any memory allocated by TBranchElement::SetAddress().
947 // FIXME: We must consider what to do with the reset of these if we are a clone.
948 delete fPlayer;
949 fPlayer = 0;
950 if (fFriends) {
951 fFriends->Delete();
952 delete fFriends;
953 fFriends = 0;
954 }
955 if (fAliases) {
956 fAliases->Delete();
957 delete fAliases;
958 fAliases = 0;
959 }
960 if (fUserInfo) {
961 fUserInfo->Delete();
962 delete fUserInfo;
963 fUserInfo = 0;
964 }
965 if (fClones) {
966 // Clone trees should no longer be removed from fClones when they are deleted.
967 {
969 gROOT->GetListOfCleanups()->Remove(fClones);
970 }
971 // Note: fClones does not own its content.
972 delete fClones;
973 fClones = 0;
974 }
975 if (fEntryList) {
977 // Delete the entry list if it is marked to be deleted and it is not also
978 // owned by a directory. (Otherwise we would need to make sure that a
979 // TDirectoryFile that has a TTree in it does a 'slow' TList::Delete.
980 delete fEntryList;
981 fEntryList=0;
982 }
983 }
984 delete fTreeIndex;
985 fTreeIndex = 0;
986 delete fBranchRef;
987 fBranchRef = 0;
988 delete [] fClusterRangeEnd;
990 delete [] fClusterSize;
991 fClusterSize = 0;
992 // Must be done after the destruction of friends.
993 // Note: We do *not* own our directory.
994 fDirectory = 0;
995
996 if (fTransientBuffer) {
997 delete fTransientBuffer;
999 }
1000}
1001
1002////////////////////////////////////////////////////////////////////////////////
1003/// Returns the transient buffer currently used by this TTree for reading/writing baskets.
1006{
1007 if (fTransientBuffer) {
1008 if (fTransientBuffer->BufferSize() < size) {
1009 fTransientBuffer->Expand(size);
1010 }
1011 return fTransientBuffer;
1012 }
1014 return fTransientBuffer;
1015}
1016
1017////////////////////////////////////////////////////////////////////////////////
1018/// Add branch with name bname to the Tree cache.
1019/// If bname="*" all branches are added to the cache.
1020/// if subbranches is true all the branches of the subbranches are
1021/// also put to the cache.
1022///
1023/// Returns:
1024/// - 0 branch added or already included
1025/// - -1 on error
1027Int_t TTree::AddBranchToCache(const char*bname, Bool_t subbranches)
1028{
1029 if (!GetTree()) {
1030 if (LoadTree(0)<0) {
1031 Error("AddBranchToCache","Could not load a tree");
1032 return -1;
1033 }
1034 }
1035 if (GetTree()) {
1036 if (GetTree() != this) {
1037 return GetTree()->AddBranchToCache(bname, subbranches);
1038 }
1039 } else {
1040 Error("AddBranchToCache", "No tree is available. Branch was not added to the cache");
1041 return -1;
1042 }
1043
1044 TFile *f = GetCurrentFile();
1045 if (!f) {
1046 Error("AddBranchToCache", "No file is available. Branch was not added to the cache");
1047 return -1;
1048 }
1050 if (!tc) {
1051 Error("AddBranchToCache", "No cache is available, branch not added");
1052 return -1;
1053 }
1054 return tc->AddBranch(bname,subbranches);
1055}
1056
1057////////////////////////////////////////////////////////////////////////////////
1058/// Add branch b to the Tree cache.
1059/// if subbranches is true all the branches of the subbranches are
1060/// also put to the cache.
1061///
1062/// Returns:
1063/// - 0 branch added or already included
1064/// - -1 on error
1067{
1068 if (!GetTree()) {
1069 if (LoadTree(0)<0) {
1070 Error("AddBranchToCache","Could not load a tree");
1071 return -1;
1072 }
1073 }
1074 if (GetTree()) {
1075 if (GetTree() != this) {
1076 Int_t res = GetTree()->AddBranchToCache(b, subbranches);
1077 if (res<0) {
1078 Error("AddBranchToCache", "Error adding branch");
1079 }
1080 return res;
1081 }
1082 } else {
1083 Error("AddBranchToCache", "No tree is available. Branch was not added to the cache");
1084 return -1;
1085 }
1086
1087 TFile *f = GetCurrentFile();
1088 if (!f) {
1089 Error("AddBranchToCache", "No file is available. Branch was not added to the cache");
1090 return -1;
1091 }
1093 if (!tc) {
1094 Error("AddBranchToCache", "No cache is available, branch not added");
1095 return -1;
1096 }
1097 return tc->AddBranch(b,subbranches);
1098}
1099
1100////////////////////////////////////////////////////////////////////////////////
1101/// Remove the branch with name 'bname' from the Tree cache.
1102/// If bname="*" all branches are removed from the cache.
1103/// if subbranches is true all the branches of the subbranches are
1104/// also removed from the cache.
1105///
1106/// Returns:
1107/// - 0 branch dropped or not in cache
1108/// - -1 on error
1110Int_t TTree::DropBranchFromCache(const char*bname, Bool_t subbranches)
1111{
1112 if (!GetTree()) {
1113 if (LoadTree(0)<0) {
1114 Error("DropBranchFromCache","Could not load a tree");
1115 return -1;
1116 }
1117 }
1118 if (GetTree()) {
1119 if (GetTree() != this) {
1120 return GetTree()->DropBranchFromCache(bname, subbranches);
1121 }
1122 } else {
1123 Error("DropBranchFromCache", "No tree is available. Branch was not dropped from the cache");
1124 return -1;
1125 }
1126
1127 TFile *f = GetCurrentFile();
1128 if (!f) {
1129 Error("DropBranchFromCache", "No file is available. Branch was not dropped from the cache");
1130 return -1;
1131 }
1133 if (!tc) {
1134 Error("DropBranchFromCache", "No cache is available, branch not dropped");
1135 return -1;
1136 }
1137 return tc->DropBranch(bname,subbranches);
1138}
1139
1140////////////////////////////////////////////////////////////////////////////////
1141/// Remove the branch b from the Tree cache.
1142/// if subbranches is true all the branches of the subbranches are
1143/// also removed from the cache.
1144///
1145/// Returns:
1146/// - 0 branch dropped or not in cache
1147/// - -1 on error
1150{
1151 if (!GetTree()) {
1152 if (LoadTree(0)<0) {
1153 Error("DropBranchFromCache","Could not load a tree");
1154 return -1;
1155 }
1156 }
1157 if (GetTree()) {
1158 if (GetTree() != this) {
1159 Int_t res = GetTree()->DropBranchFromCache(b, subbranches);
1160 if (res<0) {
1161 Error("DropBranchFromCache", "Error dropping branch");
1162 }
1163 return res;
1164 }
1165 } else {
1166 Error("DropBranchFromCache", "No tree is available. Branch was not dropped from the cache");
1167 return -1;
1168 }
1169
1170 TFile *f = GetCurrentFile();
1171 if (!f) {
1172 Error("DropBranchFromCache", "No file is available. Branch was not dropped from the cache");
1173 return -1;
1174 }
1176 if (!tc) {
1177 Error("DropBranchFromCache", "No cache is available, branch not dropped");
1178 return -1;
1179 }
1180 return tc->DropBranch(b,subbranches);
1181}
1182
1183////////////////////////////////////////////////////////////////////////////////
1184/// Add a cloned tree to our list of trees to be notified whenever we change
1185/// our branch addresses or when we are deleted.
1187void TTree::AddClone(TTree* clone)
1188{
1189 if (!fClones) {
1190 fClones = new TList();
1191 fClones->SetOwner(false);
1192 // So that the clones are automatically removed from the list when
1193 // they are deleted.
1194 {
1196 gROOT->GetListOfCleanups()->Add(fClones);
1197 }
1198 }
1199 if (!fClones->FindObject(clone)) {
1200 fClones->Add(clone);
1201 }
1202}
1203
1204////////////////////////////////////////////////////////////////////////////////
1205/// Add a TFriendElement to the list of friends.
1206///
1207/// This function:
1208/// - opens a file if filename is specified
1209/// - reads a Tree with name treename from the file (current directory)
1210/// - adds the Tree to the list of friends
1211/// see other AddFriend functions
1212///
1213/// A TFriendElement TF describes a TTree object TF in a file.
1214/// When a TFriendElement TF is added to the the list of friends of an
1215/// existing TTree T, any variable from TF can be referenced in a query
1216/// to T.
1217///
1218/// A tree keeps a list of friends. In the context of a tree (or a chain),
1219/// friendship means unrestricted access to the friends data. In this way
1220/// it is much like adding another branch to the tree without taking the risk
1221/// of damaging it. To add a friend to the list, you can use the TTree::AddFriend
1222/// method. The tree in the diagram below has two friends (friend_tree1 and
1223/// friend_tree2) and now has access to the variables a,b,c,i,j,k,l and m.
1224///
1225/// \image html ttree_friend1.png
1226///
1227/// The AddFriend method has two parameters, the first is the tree name and the
1228/// second is the name of the ROOT file where the friend tree is saved.
1229/// AddFriend automatically opens the friend file. If no file name is given,
1230/// the tree called ft1 is assumed to be in the same file as the original tree.
1231///
1232/// tree.AddFriend("ft1","friendfile1.root");
1233/// If the friend tree has the same name as the original tree, you can give it
1234/// an alias in the context of the friendship:
1235///
1236/// tree.AddFriend("tree1 = tree","friendfile1.root");
1237/// Once the tree has friends, we can use TTree::Draw as if the friend's
1238/// variables were in the original tree. To specify which tree to use in
1239/// the Draw method, use the syntax:
1240/// ~~~ {.cpp}
1241/// <treeName>.<branchname>.<varname>
1242/// ~~~
1243/// If the variablename is enough to uniquely identify the variable, you can
1244/// leave out the tree and/or branch name.
1245/// For example, these commands generate a 3-d scatter plot of variable "var"
1246/// in the TTree tree versus variable v1 in TTree ft1 versus variable v2 in
1247/// TTree ft2.
1248/// ~~~ {.cpp}
1249/// tree.AddFriend("ft1","friendfile1.root");
1250/// tree.AddFriend("ft2","friendfile2.root");
1251/// tree.Draw("var:ft1.v1:ft2.v2");
1252/// ~~~
1253/// \image html ttree_friend2.png
1254///
1255/// The picture illustrates the access of the tree and its friends with a
1256/// Draw command.
1257/// When AddFriend is called, the ROOT file is automatically opened and the
1258/// friend tree (ft1) is read into memory. The new friend (ft1) is added to
1259/// the list of friends of tree.
1260/// The number of entries in the friend must be equal or greater to the number
1261/// of entries of the original tree. If the friend tree has fewer entries a
1262/// warning is given and the missing entries are not included in the histogram.
1263/// To retrieve the list of friends from a tree use TTree::GetListOfFriends.
1264/// When the tree is written to file (TTree::Write), the friends list is saved
1265/// with it. And when the tree is retrieved, the trees on the friends list are
1266/// also retrieved and the friendship restored.
1267/// When a tree is deleted, the elements of the friend list are also deleted.
1268/// It is possible to declare a friend tree that has the same internal
1269/// structure (same branches and leaves) as the original tree, and compare the
1270/// same values by specifying the tree.
1271/// ~~~ {.cpp}
1272/// tree.Draw("var:ft1.var:ft2.var")
1273/// ~~~
1275TFriendElement* TTree::AddFriend(const char* treename, const char* filename)
1276{
1277 if (!fFriends) {
1278 fFriends = new TList();
1279 }
1280 TFriendElement* fe = new TFriendElement(this, treename, filename);
1281
1282 fFriends->Add(fe);
1283 TTree* t = fe->GetTree();
1284 if (t) {
1285 if (!t->GetTreeIndex() && (t->GetEntries() < fEntries)) {
1286 Warning("AddFriend", "FriendElement %s in file %s has less entries %lld than its parent Tree: %lld", treename, filename, t->GetEntries(), fEntries);
1287 }
1288 } else {
1289 Warning("AddFriend", "Cannot add FriendElement %s in file %s", treename, filename);
1290 }
1291 return fe;
1292}
1293
1294////////////////////////////////////////////////////////////////////////////////
1295/// Add a TFriendElement to the list of friends.
1296///
1297/// The TFile is managed by the user (e.g. the user must delete the file).
1298/// For complete description see AddFriend(const char *, const char *).
1299/// This function:
1300/// - reads a Tree with name treename from the file
1301/// - adds the Tree to the list of friends
1303TFriendElement* TTree::AddFriend(const char* treename, TFile* file)
1304{
1305 if (!fFriends) {
1306 fFriends = new TList();
1307 }
1308 TFriendElement *fe = new TFriendElement(this, treename, file);
1309 R__ASSERT(fe);
1310 fFriends->Add(fe);
1311 TTree *t = fe->GetTree();
1312 if (t) {
1313 if (!t->GetTreeIndex() && (t->GetEntries() < fEntries)) {
1314 Warning("AddFriend", "FriendElement %s in file %s has less entries %lld than its parent tree: %lld", treename, file->GetName(), t->GetEntries(), fEntries);
1315 }
1316 } else {
1317 Warning("AddFriend", "unknown tree '%s' in file '%s'", treename, file->GetName());
1318 }
1319 return fe;
1320}
1321
1322////////////////////////////////////////////////////////////////////////////////
1323/// Add a TFriendElement to the list of friends.
1324///
1325/// The TTree is managed by the user (e.g., the user must delete the file).
1326/// For a complete description see AddFriend(const char *, const char *).
1328TFriendElement* TTree::AddFriend(TTree* tree, const char* alias, Bool_t warn)
1329{
1330 if (!tree) {
1331 return 0;
1332 }
1333 if (!fFriends) {
1334 fFriends = new TList();
1335 }
1336 TFriendElement* fe = new TFriendElement(this, tree, alias);
1337 R__ASSERT(fe); // this assert is for historical reasons. Don't remove it unless you understand all the consequences.
1338 fFriends->Add(fe);
1339 TTree* t = fe->GetTree();
1340 if (warn && (t->GetEntries() < fEntries)) {
1341 Warning("AddFriend", "FriendElement '%s' in file '%s' has less entries %lld than its parent tree: %lld",
1342 tree->GetName(), fe->GetFile() ? fe->GetFile()->GetName() : "(memory resident)", t->GetEntries(), fEntries);
1343 }
1344 return fe;
1345}
1346
1347////////////////////////////////////////////////////////////////////////////////
1348/// AutoSave tree header every fAutoSave bytes.
1349///
1350/// When large Trees are produced, it is safe to activate the AutoSave
1351/// procedure. Some branches may have buffers holding many entries.
1352/// If fAutoSave is negative, AutoSave is automatically called by
1353/// TTree::Fill when the number of bytes generated since the previous
1354/// AutoSave is greater than -fAutoSave bytes.
1355/// If fAutoSave is positive, AutoSave is automatically called by
1356/// TTree::Fill every N entries.
1357/// This function may also be invoked by the user.
1358/// Each AutoSave generates a new key on the file.
1359/// Once the key with the tree header has been written, the previous cycle
1360/// (if any) is deleted.
1361///
1362/// Note that calling TTree::AutoSave too frequently (or similarly calling
1363/// TTree::SetAutoSave with a small value) is an expensive operation.
1364/// You should make tests for your own application to find a compromise
1365/// between speed and the quantity of information you may loose in case of
1366/// a job crash.
1367///
1368/// In case your program crashes before closing the file holding this tree,
1369/// the file will be automatically recovered when you will connect the file
1370/// in UPDATE mode.
1371/// The Tree will be recovered at the status corresponding to the last AutoSave.
1372///
1373/// if option contains "SaveSelf", gDirectory->SaveSelf() is called.
1374/// This allows another process to analyze the Tree while the Tree is being filled.
1375///
1376/// if option contains "FlushBaskets", TTree::FlushBaskets is called and all
1377/// the current basket are closed-out and written to disk individually.
1378///
1379/// By default the previous header is deleted after having written the new header.
1380/// if option contains "Overwrite", the previous Tree header is deleted
1381/// before written the new header. This option is slightly faster, but
1382/// the default option is safer in case of a problem (disk quota exceeded)
1383/// when writing the new header.
1384///
1385/// The function returns the number of bytes written to the file.
1386/// if the number of bytes is null, an error has occurred while writing
1387/// the header to the file.
1388///
1389/// ## How to write a Tree in one process and view it from another process
1390///
1391/// The following two scripts illustrate how to do this.
1392/// The script treew.C is executed by process1, treer.C by process2
1393///
1394/// script treew.C:
1395/// ~~~ {.cpp}
1396/// void treew() {
1397/// TFile f("test.root","recreate");
1398/// TNtuple *ntuple = new TNtuple("ntuple","Demo","px:py:pz:random:i");
1399/// Float_t px, py, pz;
1400/// for ( Int_t i=0; i<10000000; i++) {
1401/// gRandom->Rannor(px,py);
1402/// pz = px*px + py*py;
1403/// Float_t random = gRandom->Rndm(1);
1404/// ntuple->Fill(px,py,pz,random,i);
1405/// if (i%1000 == 1) ntuple->AutoSave("SaveSelf");
1406/// }
1407/// }
1408/// ~~~
1409/// script treer.C:
1410/// ~~~ {.cpp}
1411/// void treer() {
1412/// TFile f("test.root");
1413/// TTree *ntuple = (TTree*)f.Get("ntuple");
1414/// TCanvas c1;
1415/// Int_t first = 0;
1416/// while(1) {
1417/// if (first == 0) ntuple->Draw("px>>hpx", "","",10000000,first);
1418/// else ntuple->Draw("px>>+hpx","","",10000000,first);
1419/// first = (Int_t)ntuple->GetEntries();
1420/// c1.Update();
1421/// gSystem->Sleep(1000); //sleep 1 second
1422/// ntuple->Refresh();
1423/// }
1424/// }
1425/// ~~~
1428{
1429 if (!fDirectory || fDirectory == gROOT || !fDirectory->IsWritable()) return 0;
1430 if (gDebug > 0) {
1431 Info("AutoSave", "Tree:%s after %lld bytes written\n",GetName(),GetTotBytes());
1432 }
1433 TString opt = option;
1434 opt.ToLower();
1435
1436 if (opt.Contains("flushbaskets")) {
1437 if (gDebug > 0) Info("AutoSave", "calling FlushBaskets \n");
1439 }
1440
1442
1444 Long64_t nbytes;
1445 if (opt.Contains("overwrite")) {
1446 nbytes = fDirectory->WriteTObject(this,"","overwrite");
1447 } else {
1448 nbytes = fDirectory->WriteTObject(this); //nbytes will be 0 if Write failed (disk space exceeded)
1449 if (nbytes && key) {
1450 key->Delete();
1451 delete key;
1452 }
1453 }
1454 // save StreamerInfo
1456 if (file) file->WriteStreamerInfo();
1457
1458 if (opt.Contains("saveself")) {
1460 //the following line is required in case GetUserInfo contains a user class
1461 //for which the StreamerInfo must be written. One could probably be a bit faster (Rene)
1462 if (file) file->WriteHeader();
1463 }
1464
1465 return nbytes;
1466}
1467
1468namespace {
1469 // This error message is repeated several times in the code. We write it once.
1470 const char* writeStlWithoutProxyMsg = "The class requested (%s) for the branch \"%s\""
1471 " is an instance of an stl collection and does not have a compiled CollectionProxy."
1472 " Please generate the dictionary for this collection (%s) to avoid to write corrupted data.";
1473}
1474
1475////////////////////////////////////////////////////////////////////////////////
1476/// Same as TTree::Branch() with added check that addobj matches className.
1477///
1478/// See TTree::Branch() for other details.
1479///
1481TBranch* TTree::BranchImp(const char* branchname, const char* classname, TClass* ptrClass, void* addobj, Int_t bufsize, Int_t splitlevel)
1482{
1483 TClass* claim = TClass::GetClass(classname);
1484 if (!ptrClass) {
1485 if (claim && claim->GetCollectionProxy() && dynamic_cast<TEmulatedCollectionProxy*>(claim->GetCollectionProxy())) {
1486 Error("Branch", writeStlWithoutProxyMsg,
1487 claim->GetName(), branchname, claim->GetName());
1488 return 0;
1489 }
1490 return Branch(branchname, classname, (void*) addobj, bufsize, splitlevel);
1491 }
1492 TClass* actualClass = 0;
1493 void** addr = (void**) addobj;
1494 if (addr) {
1495 actualClass = ptrClass->GetActualClass(*addr);
1496 }
1497 if (ptrClass && claim) {
1498 if (!(claim->InheritsFrom(ptrClass) || ptrClass->InheritsFrom(claim))) {
1499 // Note we currently do not warn in case of splicing or over-expectation).
1500 if (claim->IsLoaded() && ptrClass->IsLoaded() && strcmp( claim->GetTypeInfo()->name(), ptrClass->GetTypeInfo()->name() ) == 0) {
1501 // The type is the same according to the C++ type_info, we must be in the case of
1502 // a template of Double32_t. This is actually a correct case.
1503 } else {
1504 Error("Branch", "The class requested (%s) for \"%s\" is different from the type of the pointer passed (%s)",
1505 claim->GetName(), branchname, ptrClass->GetName());
1506 }
1507 } else if (actualClass && (claim != actualClass) && !actualClass->InheritsFrom(claim)) {
1508 if (claim->IsLoaded() && actualClass->IsLoaded() && strcmp( claim->GetTypeInfo()->name(), actualClass->GetTypeInfo()->name() ) == 0) {
1509 // The type is the same according to the C++ type_info, we must be in the case of
1510 // a template of Double32_t. This is actually a correct case.
1511 } else {
1512 Error("Branch", "The actual class (%s) of the object provided for the definition of the branch \"%s\" does not inherit from %s",
1513 actualClass->GetName(), branchname, claim->GetName());
1514 }
1515 }
1516 }
1517 if (claim && claim->GetCollectionProxy() && dynamic_cast<TEmulatedCollectionProxy*>(claim->GetCollectionProxy())) {
1518 Error("Branch", writeStlWithoutProxyMsg,
1519 claim->GetName(), branchname, claim->GetName());
1520 return 0;
1521 }
1522 return Branch(branchname, classname, (void*) addobj, bufsize, splitlevel);
1523}
1524
1525////////////////////////////////////////////////////////////////////////////////
1526/// Same as TTree::Branch but automatic detection of the class name.
1527/// See TTree::Branch for other details.
1529TBranch* TTree::BranchImp(const char* branchname, TClass* ptrClass, void* addobj, Int_t bufsize, Int_t splitlevel)
1530{
1531 if (!ptrClass) {
1532 Error("Branch", "The pointer specified for %s is not of a class known to ROOT", branchname);
1533 return 0;
1534 }
1535 TClass* actualClass = 0;
1536 void** addr = (void**) addobj;
1537 if (addr && *addr) {
1538 actualClass = ptrClass->GetActualClass(*addr);
1539 if (!actualClass) {
1540 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",
1541 branchname, ptrClass->GetName());
1542 actualClass = ptrClass;
1543 } else if ((ptrClass != actualClass) && !actualClass->InheritsFrom(ptrClass)) {
1544 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());
1545 return 0;
1546 }
1547 } else {
1548 actualClass = ptrClass;
1549 }
1550 if (actualClass && actualClass->GetCollectionProxy() && dynamic_cast<TEmulatedCollectionProxy*>(actualClass->GetCollectionProxy())) {
1551 Error("Branch", writeStlWithoutProxyMsg,
1552 actualClass->GetName(), branchname, actualClass->GetName());
1553 return 0;
1554 }
1555 return Branch(branchname, actualClass->GetName(), (void*) addobj, bufsize, splitlevel);
1556}
1557
1558////////////////////////////////////////////////////////////////////////////////
1559/// Same as TTree::Branch but automatic detection of the class name.
1560/// See TTree::Branch for other details.
1562TBranch* TTree::BranchImpRef(const char* branchname, const char *classname, TClass* ptrClass, void *addobj, Int_t bufsize, Int_t splitlevel)
1563{
1564 TClass* claim = TClass::GetClass(classname);
1565 if (!ptrClass) {
1566 if (claim && claim->GetCollectionProxy() && dynamic_cast<TEmulatedCollectionProxy*>(claim->GetCollectionProxy())) {
1567 Error("Branch", writeStlWithoutProxyMsg,
1568 claim->GetName(), branchname, claim->GetName());
1569 return 0;
1570 } else if (claim == 0) {
1571 Error("Branch", "The pointer specified for %s is not of a class known to ROOT and %s is not a known class", branchname, classname);
1572 return 0;
1573 }
1574 ptrClass = claim;
1575 }
1576 TClass* actualClass = 0;
1577 if (!addobj) {
1578 Error("Branch", "Reference interface requires a valid object (for branch: %s)!", branchname);
1579 return 0;
1580 }
1581 actualClass = ptrClass->GetActualClass(addobj);
1582 if (ptrClass && claim) {
1583 if (!(claim->InheritsFrom(ptrClass) || ptrClass->InheritsFrom(claim))) {
1584 // Note we currently do not warn in case of splicing or over-expectation).
1585 if (claim->IsLoaded() && ptrClass->IsLoaded() && strcmp( claim->GetTypeInfo()->name(), ptrClass->GetTypeInfo()->name() ) == 0) {
1586 // The type is the same according to the C++ type_info, we must be in the case of
1587 // a template of Double32_t. This is actually a correct case.
1588 } else {
1589 Error("Branch", "The class requested (%s) for \"%s\" is different from the type of the object passed (%s)",
1590 claim->GetName(), branchname, ptrClass->GetName());
1591 }
1592 } else if (actualClass && (claim != actualClass) && !actualClass->InheritsFrom(claim)) {
1593 if (claim->IsLoaded() && actualClass->IsLoaded() && strcmp( claim->GetTypeInfo()->name(), actualClass->GetTypeInfo()->name() ) == 0) {
1594 // The type is the same according to the C++ type_info, we must be in the case of
1595 // a template of Double32_t. This is actually a correct case.
1596 } else {
1597 Error("Branch", "The actual class (%s) of the object provided for the definition of the branch \"%s\" does not inherit from %s",
1598 actualClass->GetName(), branchname, claim->GetName());
1599 }
1600 }
1601 }
1602 if (!actualClass) {
1603 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",
1604 branchname, ptrClass->GetName());
1605 actualClass = ptrClass;
1606 } else if ((ptrClass != actualClass) && !actualClass->InheritsFrom(ptrClass)) {
1607 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());
1608 return 0;
1609 }
1610 if (actualClass && actualClass->GetCollectionProxy() && dynamic_cast<TEmulatedCollectionProxy*>(actualClass->GetCollectionProxy())) {
1611 Error("Branch", writeStlWithoutProxyMsg,
1612 actualClass->GetName(), branchname, actualClass->GetName());
1613 return 0;
1614 }
1615 return BronchExec(branchname, actualClass->GetName(), (void*) addobj, kFALSE, bufsize, splitlevel);
1616}
1617
1618////////////////////////////////////////////////////////////////////////////////
1619/// Same as TTree::Branch but automatic detection of the class name.
1620/// See TTree::Branch for other details.
1622TBranch* TTree::BranchImpRef(const char* branchname, TClass* ptrClass, EDataType datatype, void* addobj, Int_t bufsize, Int_t splitlevel)
1623{
1624 if (!ptrClass) {
1625 if (datatype == kOther_t || datatype == kNoType_t) {
1626 Error("Branch", "The pointer specified for %s is not of a class or type known to ROOT", branchname);
1627 } else {
1628 TString varname; varname.Form("%s/%c",branchname,DataTypeToChar(datatype));
1629 return Branch(branchname,addobj,varname.Data(),bufsize);
1630 }
1631 return 0;
1632 }
1633 TClass* actualClass = 0;
1634 if (!addobj) {
1635 Error("Branch", "Reference interface requires a valid object (for branch: %s)!", branchname);
1636 return 0;
1637 }
1638 actualClass = ptrClass->GetActualClass(addobj);
1639 if (!actualClass) {
1640 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",
1641 branchname, ptrClass->GetName());
1642 actualClass = ptrClass;
1643 } else if ((ptrClass != actualClass) && !actualClass->InheritsFrom(ptrClass)) {
1644 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());
1645 return 0;
1646 }
1647 if (actualClass && actualClass->GetCollectionProxy() && dynamic_cast<TEmulatedCollectionProxy*>(actualClass->GetCollectionProxy())) {
1648 Error("Branch", writeStlWithoutProxyMsg,
1649 actualClass->GetName(), branchname, actualClass->GetName());
1650 return 0;
1651 }
1652 return BronchExec(branchname, actualClass->GetName(), (void*) addobj, kFALSE, bufsize, splitlevel);
1653}
1654
1655////////////////////////////////////////////////////////////////////////////////
1656/// Deprecated function. Use next function instead.
1658Int_t TTree::Branch(TList* li, Int_t bufsize /* = 32000 */ , Int_t splitlevel /* = 99 */)
1659{
1660 return Branch((TCollection*) li, bufsize, splitlevel);
1661}
1662
1663////////////////////////////////////////////////////////////////////////////////
1664/// Create one branch for each element in the collection.
1665///
1666/// Each entry in the collection becomes a top level branch if the
1667/// corresponding class is not a collection. If it is a collection, the entry
1668/// in the collection becomes in turn top level branches, etc.
1669/// The splitlevel is decreased by 1 every time a new collection is found.
1670/// For example if list is a TObjArray*
1671/// - if splitlevel = 1, one top level branch is created for each element
1672/// of the TObjArray.
1673/// - if splitlevel = 2, one top level branch is created for each array element.
1674/// if, in turn, one of the array elements is a TCollection, one top level
1675/// branch will be created for each element of this collection.
1676///
1677/// In case a collection element is a TClonesArray, the special Tree constructor
1678/// for TClonesArray is called.
1679/// The collection itself cannot be a TClonesArray.
1680///
1681/// The function returns the total number of branches created.
1682///
1683/// If name is given, all branch names will be prefixed with name_.
1684///
1685/// IMPORTANT NOTE1: This function should not be called with splitlevel < 1.
1686///
1687/// IMPORTANT NOTE2: The branches created by this function will have names
1688/// corresponding to the collection or object names. It is important
1689/// to give names to collections to avoid misleading branch names or
1690/// identical branch names. By default collections have a name equal to
1691/// the corresponding class name, e.g. the default name for a TList is "TList".
1692///
1693/// And in general, in case two or more master branches contain subbranches
1694/// with identical names, one must add a "." (dot) character at the end
1695/// of the master branch name. This will force the name of the subbranches
1696/// to be of the form `master.subbranch` instead of simply `subbranch`.
1697/// This situation happens when the top level object
1698/// has two or more members referencing the same class.
1699/// For example, if a Tree has two branches B1 and B2 corresponding
1700/// to objects of the same class MyClass, one can do:
1701/// ~~~ {.cpp}
1702/// tree.Branch("B1.","MyClass",&b1,8000,1);
1703/// tree.Branch("B2.","MyClass",&b2,8000,1);
1704/// ~~~
1705/// if MyClass has 3 members a,b,c, the two instructions above will generate
1706/// subbranches called B1.a, B1.b ,B1.c, B2.a, B2.b, B2.c
1707///
1708/// Example:
1709/// ~~~ {.cpp}
1710/// {
1711/// TTree T("T","test list");
1712/// TList *list = new TList();
1713///
1714/// TObjArray *a1 = new TObjArray();
1715/// a1->SetName("a1");
1716/// list->Add(a1);
1717/// TH1F *ha1a = new TH1F("ha1a","ha1",100,0,1);
1718/// TH1F *ha1b = new TH1F("ha1b","ha1",100,0,1);
1719/// a1->Add(ha1a);
1720/// a1->Add(ha1b);
1721/// TObjArray *b1 = new TObjArray();
1722/// b1->SetName("b1");
1723/// list->Add(b1);
1724/// TH1F *hb1a = new TH1F("hb1a","hb1",100,0,1);
1725/// TH1F *hb1b = new TH1F("hb1b","hb1",100,0,1);
1726/// b1->Add(hb1a);
1727/// b1->Add(hb1b);
1728///
1729/// TObjArray *a2 = new TObjArray();
1730/// a2->SetName("a2");
1731/// list->Add(a2);
1732/// TH1S *ha2a = new TH1S("ha2a","ha2",100,0,1);
1733/// TH1S *ha2b = new TH1S("ha2b","ha2",100,0,1);
1734/// a2->Add(ha2a);
1735/// a2->Add(ha2b);
1736///
1737/// T.Branch(list,16000,2);
1738/// T.Print();
1739/// }
1740/// ~~~
1742Int_t TTree::Branch(TCollection* li, Int_t bufsize /* = 32000 */, Int_t splitlevel /* = 99 */, const char* name /* = "" */)
1743{
1744
1745 if (!li) {
1746 return 0;
1747 }
1748 TObject* obj = 0;
1749 Int_t nbranches = GetListOfBranches()->GetEntries();
1750 if (li->InheritsFrom(TClonesArray::Class())) {
1751 Error("Branch", "Cannot call this constructor for a TClonesArray");
1752 return 0;
1753 }
1754 Int_t nch = strlen(name);
1755 TString branchname;
1756 TIter next(li);
1757 while ((obj = next())) {
1758 if ((splitlevel > 1) && obj->InheritsFrom(TCollection::Class()) && !obj->InheritsFrom(TClonesArray::Class())) {
1759 TCollection* col = (TCollection*) obj;
1760 if (nch) {
1761 branchname.Form("%s_%s_", name, col->GetName());
1762 } else {
1763 branchname.Form("%s_", col->GetName());
1764 }
1765 Branch(col, bufsize, splitlevel - 1, branchname);
1766 } else {
1767 if (nch && (name[nch-1] == '_')) {
1768 branchname.Form("%s%s", name, obj->GetName());
1769 } else {
1770 if (nch) {
1771 branchname.Form("%s_%s", name, obj->GetName());
1772 } else {
1773 branchname.Form("%s", obj->GetName());
1774 }
1775 }
1776 if (splitlevel > 99) {
1777 branchname += ".";
1778 }
1779 Bronch(branchname, obj->ClassName(), li->GetObjectRef(obj), bufsize, splitlevel - 1);
1780 }
1781 }
1782 return GetListOfBranches()->GetEntries() - nbranches;
1783}
1784
1785////////////////////////////////////////////////////////////////////////////////
1786/// Create one branch for each element in the folder.
1787/// Returns the total number of branches created.
1789Int_t TTree::Branch(const char* foldername, Int_t bufsize /* = 32000 */, Int_t splitlevel /* = 99 */)
1790{
1791 TObject* ob = gROOT->FindObjectAny(foldername);
1792 if (!ob) {
1793 return 0;
1794 }
1795 if (ob->IsA() != TFolder::Class()) {
1796 return 0;
1797 }
1798 Int_t nbranches = GetListOfBranches()->GetEntries();
1799 TFolder* folder = (TFolder*) ob;
1800 TIter next(folder->GetListOfFolders());
1801 TObject* obj = 0;
1802 char* curname = new char[1000];
1803 char occur[20];
1804 while ((obj = next())) {
1805 snprintf(curname,1000, "%s/%s", foldername, obj->GetName());
1806 if (obj->IsA() == TFolder::Class()) {
1807 Branch(curname, bufsize, splitlevel - 1);
1808 } else {
1809 void* add = (void*) folder->GetListOfFolders()->GetObjectRef(obj);
1810 for (Int_t i = 0; i < 1000; ++i) {
1811 if (curname[i] == 0) {
1812 break;
1813 }
1814 if (curname[i] == '/') {
1815 curname[i] = '.';
1816 }
1817 }
1818 Int_t noccur = folder->Occurence(obj);
1819 if (noccur > 0) {
1820 snprintf(occur,20, "_%d", noccur);
1821 strlcat(curname, occur,1000);
1822 }
1823 TBranchElement* br = (TBranchElement*) Bronch(curname, obj->ClassName(), add, bufsize, splitlevel - 1);
1824 if (br) br->SetBranchFolder();
1825 }
1826 }
1827 delete[] curname;
1828 return GetListOfBranches()->GetEntries() - nbranches;
1829}
1830
1831////////////////////////////////////////////////////////////////////////////////
1832/// Create a new TTree Branch.
1833///
1834/// This Branch constructor is provided to support non-objects in
1835/// a Tree. The variables described in leaflist may be simple
1836/// variables or structures. // See the two following
1837/// constructors for writing objects in a Tree.
1838///
1839/// By default the branch buffers are stored in the same file as the Tree.
1840/// use TBranch::SetFile to specify a different file
1841///
1842/// * address is the address of the first item of a structure.
1843/// * leaflist is the concatenation of all the variable names and types
1844/// separated by a colon character :
1845/// The variable name and the variable type are separated by a slash (/).
1846/// The variable type may be 0,1 or 2 characters. If no type is given,
1847/// the type of the variable is assumed to be the same as the previous
1848/// variable. If the first variable does not have a type, it is assumed
1849/// of type F by default. The list of currently supported types is given below:
1850/// - `C` : a character string terminated by the 0 character
1851/// - `B` : an 8 bit signed integer (`Char_t`)
1852/// - `b` : an 8 bit unsigned integer (`UChar_t`)
1853/// - `S` : a 16 bit signed integer (`Short_t`)
1854/// - `s` : a 16 bit unsigned integer (`UShort_t`)
1855/// - `I` : a 32 bit signed integer (`Int_t`)
1856/// - `i` : a 32 bit unsigned integer (`UInt_t`)
1857/// - `F` : a 32 bit floating point (`Float_t`)
1858/// - `f` : a 24 bit floating point with truncated mantissa (`Float16_t`)
1859/// - `D` : a 64 bit floating point (`Double_t`)
1860/// - `d` : a 24 bit truncated floating point (`Double32_t`)
1861/// - `L` : a 64 bit signed integer (`Long64_t`)
1862/// - `l` : a 64 bit unsigned integer (`ULong64_t`)
1863/// - `O` : [the letter `o`, not a zero] a boolean (`Bool_t`)
1864///
1865/// Arrays of values are supported with the following syntax:
1866/// - If leaf name has the form var[nelem], where nelem is alphanumeric, then
1867/// if nelem is a leaf name, it is used as the variable size of the array,
1868/// otherwise return 0.
1869/// - If leaf name has the form var[nelem], where nelem is a non-negative integer, then
1870/// it is used as the fixed size of the array.
1871/// - If leaf name has the form of a multi-dimensional array (e.g. var[nelem][nelem2])
1872/// where nelem and nelem2 are non-negative integer) then
1873/// it is used as a 2 dimensional array of fixed size.
1874/// - In case of the truncated floating point types (Float16_t and Double32_t) you can
1875/// furthermore specify the range in the style [xmin,xmax] or [xmin,xmax,nbits] after
1876/// the type character. See `TStreamerElement::GetRange()` for further information.
1877///
1878/// Any of other form is not supported.
1879///
1880/// Note that the TTree will assume that all the item are contiguous in memory.
1881/// On some platform, this is not always true of the member of a struct or a class,
1882/// due to padding and alignment. Sorting your data member in order of decreasing
1883/// sizeof usually leads to their being contiguous in memory.
1884///
1885/// * bufsize is the buffer size in bytes for this branch
1886/// The default value is 32000 bytes and should be ok for most cases.
1887/// You can specify a larger value (e.g. 256000) if your Tree is not split
1888/// and each entry is large (Megabytes)
1889/// A small value for bufsize is optimum if you intend to access
1890/// the entries in the Tree randomly and your Tree is in split mode.
1892TBranch* TTree::Branch(const char* name, void* address, const char* leaflist, Int_t bufsize /* = 32000 */)
1893{
1894 TBranch* branch = new TBranch(this, name, address, leaflist, bufsize);
1895 if (branch->IsZombie()) {
1896 delete branch;
1897 branch = 0;
1898 return 0;
1899 }
1900 fBranches.Add(branch);
1901 return branch;
1902}
1903
1904////////////////////////////////////////////////////////////////////////////////
1905/// Create a new branch with the object of class classname at address addobj.
1906///
1907/// WARNING:
1908///
1909/// Starting with Root version 3.01, the Branch function uses the new style
1910/// branches (TBranchElement). To get the old behaviour, you can:
1911/// - call BranchOld or
1912/// - call TTree::SetBranchStyle(0)
1913///
1914/// Note that with the new style, classname does not need to derive from TObject.
1915/// It must derived from TObject if the branch style has been set to 0 (old)
1916///
1917/// Note: See the comments in TBranchElement::SetAddress() for a more
1918/// detailed discussion of the meaning of the addobj parameter in
1919/// the case of new-style branches.
1920///
1921/// Use splitlevel < 0 instead of splitlevel=0 when the class
1922/// has a custom Streamer
1923///
1924/// Note: if the split level is set to the default (99), TTree::Branch will
1925/// not issue a warning if the class can not be split.
1927TBranch* TTree::Branch(const char* name, const char* classname, void* addobj, Int_t bufsize /* = 32000 */, Int_t splitlevel /* = 99 */)
1928{
1929 if (fgBranchStyle == 1) {
1930 return Bronch(name, classname, addobj, bufsize, splitlevel);
1931 } else {
1932 if (splitlevel < 0) {
1933 splitlevel = 0;
1934 }
1935 return BranchOld(name, classname, addobj, bufsize, splitlevel);
1936 }
1937}
1938
1939////////////////////////////////////////////////////////////////////////////////
1940/// Create a new TTree BranchObject.
1941///
1942/// Build a TBranchObject for an object of class classname.
1943/// addobj is the address of a pointer to an object of class classname.
1944/// IMPORTANT: classname must derive from TObject.
1945/// The class dictionary must be available (ClassDef in class header).
1946///
1947/// This option requires access to the library where the corresponding class
1948/// is defined. Accessing one single data member in the object implies
1949/// reading the full object.
1950/// See the next Branch constructor for a more efficient storage
1951/// in case the entry consists of arrays of identical objects.
1952///
1953/// By default the branch buffers are stored in the same file as the Tree.
1954/// use TBranch::SetFile to specify a different file
1955///
1956/// IMPORTANT NOTE about branch names:
1957///
1958/// And in general, in case two or more master branches contain subbranches
1959/// with identical names, one must add a "." (dot) character at the end
1960/// of the master branch name. This will force the name of the subbranches
1961/// to be of the form `master.subbranch` instead of simply `subbranch`.
1962/// This situation happens when the top level object
1963/// has two or more members referencing the same class.
1964/// For example, if a Tree has two branches B1 and B2 corresponding
1965/// to objects of the same class MyClass, one can do:
1966/// ~~~ {.cpp}
1967/// tree.Branch("B1.","MyClass",&b1,8000,1);
1968/// tree.Branch("B2.","MyClass",&b2,8000,1);
1969/// ~~~
1970/// if MyClass has 3 members a,b,c, the two instructions above will generate
1971/// subbranches called B1.a, B1.b ,B1.c, B2.a, B2.b, B2.c
1972///
1973/// bufsize is the buffer size in bytes for this branch
1974/// The default value is 32000 bytes and should be ok for most cases.
1975/// You can specify a larger value (e.g. 256000) if your Tree is not split
1976/// and each entry is large (Megabytes)
1977/// A small value for bufsize is optimum if you intend to access
1978/// the entries in the Tree randomly and your Tree is in split mode.
1980TBranch* TTree::BranchOld(const char* name, const char* classname, void* addobj, Int_t bufsize /* = 32000 */, Int_t splitlevel /* = 1 */)
1981{
1982 TClass* cl = TClass::GetClass(classname);
1983 if (!cl) {
1984 Error("BranchOld", "Cannot find class: '%s'", classname);
1985 return 0;
1986 }
1987 if (!cl->IsTObject()) {
1988 if (fgBranchStyle == 0) {
1989 Fatal("BranchOld", "The requested class ('%s') does not inherit from TObject.\n"
1990 "\tfgBranchStyle is set to zero requesting by default to use BranchOld.\n"
1991 "\tIf this is intentional use Bronch instead of Branch or BranchOld.", classname);
1992 } else {
1993 Fatal("BranchOld", "The requested class ('%s') does not inherit from TObject.\n"
1994 "\tYou can not use BranchOld to store objects of this type.",classname);
1995 }
1996 return 0;
1997 }
1998 TBranch* branch = new TBranchObject(this, name, classname, addobj, bufsize, splitlevel);
1999 fBranches.Add(branch);
2000 if (!splitlevel) {
2001 return branch;
2002 }
2003 // We are going to fully split the class now.
2004 TObjArray* blist = branch->GetListOfBranches();
2005 const char* rdname = 0;
2006 const char* dname = 0;
2007 TString branchname;
2008 char** apointer = (char**) addobj;
2009 TObject* obj = (TObject*) *apointer;
2010 Bool_t delobj = kFALSE;
2011 if (!obj) {
2012 obj = (TObject*) cl->New();
2013 delobj = kTRUE;
2014 }
2015 // Build the StreamerInfo if first time for the class.
2016 BuildStreamerInfo(cl, obj);
2017 // Loop on all public data members of the class and its base classes.
2018 Int_t lenName = strlen(name);
2019 Int_t isDot = 0;
2020 if (name[lenName-1] == '.') {
2021 isDot = 1;
2022 }
2023 TBranch* branch1 = 0;
2024 TRealData* rd = 0;
2025 TRealData* rdi = 0;
2026 TIter nexti(cl->GetListOfRealData());
2027 TIter next(cl->GetListOfRealData());
2028 // Note: This loop results in a full split because the
2029 // real data list includes all data members of
2030 // data members.
2031 while ((rd = (TRealData*) next())) {
2032 if (rd->TestBit(TRealData::kTransient)) continue;
2033
2034 // Loop over all data members creating branches for each one.
2035 TDataMember* dm = rd->GetDataMember();
2036 if (!dm->IsPersistent()) {
2037 // Do not process members with an "!" as the first character in the comment field.
2038 continue;
2039 }
2040 if (rd->IsObject()) {
2041 // We skip data members of class type.
2042 // But we do build their real data, their
2043 // streamer info, and write their streamer
2044 // info to the current directory's file.
2045 // Oh yes, and we also do this for all of
2046 // their base classes.
2048 if (clm) {
2049 BuildStreamerInfo(clm, (char*) obj + rd->GetThisOffset());
2050 }
2051 continue;
2052 }
2053 rdname = rd->GetName();
2054 dname = dm->GetName();
2055 if (cl->CanIgnoreTObjectStreamer()) {
2056 // Skip the TObject base class data members.
2057 // FIXME: This prevents a user from ever
2058 // using these names themself!
2059 if (!strcmp(dname, "fBits")) {
2060 continue;
2061 }
2062 if (!strcmp(dname, "fUniqueID")) {
2063 continue;
2064 }
2065 }
2066 TDataType* dtype = dm->GetDataType();
2067 Int_t code = 0;
2068 if (dtype) {
2069 code = dm->GetDataType()->GetType();
2070 }
2071 // Encode branch name. Use real data member name
2072 branchname = rdname;
2073 if (isDot) {
2074 if (dm->IsaPointer()) {
2075 // FIXME: This is wrong! The asterisk is not usually in the front!
2076 branchname.Form("%s%s", name, &rdname[1]);
2077 } else {
2078 branchname.Form("%s%s", name, &rdname[0]);
2079 }
2080 }
2081 // FIXME: Change this to a string stream.
2082 TString leaflist;
2083 Int_t offset = rd->GetThisOffset();
2084 char* pointer = ((char*) obj) + offset;
2085 if (dm->IsaPointer()) {
2086 // We have a pointer to an object or a pointer to an array of basic types.
2087 TClass* clobj = 0;
2088 if (!dm->IsBasic()) {
2089 clobj = TClass::GetClass(dm->GetTypeName());
2090 }
2091 if (clobj && clobj->InheritsFrom(TClonesArray::Class())) {
2092 // We have a pointer to a clones array.
2093 char* cpointer = (char*) pointer;
2094 char** ppointer = (char**) cpointer;
2095 TClonesArray* li = (TClonesArray*) *ppointer;
2096 if (splitlevel != 2) {
2097 if (isDot) {
2098 branch1 = new TBranchClones(branch,branchname, pointer, bufsize);
2099 } else {
2100 // FIXME: This is wrong! The asterisk is not usually in the front!
2101 branch1 = new TBranchClones(branch,&branchname.Data()[1], pointer, bufsize);
2102 }
2103 blist->Add(branch1);
2104 } else {
2105 if (isDot) {
2106 branch1 = new TBranchObject(branch, branchname, li->ClassName(), pointer, bufsize);
2107 } else {
2108 // FIXME: This is wrong! The asterisk is not usually in the front!
2109 branch1 = new TBranchObject(branch, &branchname.Data()[1], li->ClassName(), pointer, bufsize);
2110 }
2111 blist->Add(branch1);
2112 }
2113 } else if (clobj) {
2114 // We have a pointer to an object.
2115 //
2116 // It must be a TObject object.
2117 if (!clobj->IsTObject()) {
2118 continue;
2119 }
2120 branch1 = new TBranchObject(branch, dname, clobj->GetName(), pointer, bufsize, 0);
2121 if (isDot) {
2122 branch1->SetName(branchname);
2123 } else {
2124 // FIXME: This is wrong! The asterisk is not usually in the front!
2125 // Do not use the first character (*).
2126 branch1->SetName(&branchname.Data()[1]);
2127 }
2128 blist->Add(branch1);
2129 } else {
2130 // We have a pointer to an array of basic types.
2131 //
2132 // Check the comments in the text of the code for an index specification.
2133 const char* index = dm->GetArrayIndex();
2134 if (index[0]) {
2135 // We are a pointer to a varying length array of basic types.
2136 //check that index is a valid data member name
2137 //if member is part of an object (e.g. fA and index=fN)
2138 //index must be changed from fN to fA.fN
2139 TString aindex (rd->GetName());
2140 Ssiz_t rdot = aindex.Last('.');
2141 if (rdot>=0) {
2142 aindex.Remove(rdot+1);
2143 aindex.Append(index);
2144 }
2145 nexti.Reset();
2146 while ((rdi = (TRealData*) nexti())) {
2147 if (rdi->TestBit(TRealData::kTransient)) continue;
2148
2149 if (!strcmp(rdi->GetName(), index)) {
2150 break;
2151 }
2152 if (!strcmp(rdi->GetName(), aindex)) {
2153 index = rdi->GetName();
2154 break;
2155 }
2156 }
2157
2158 char vcode = DataTypeToChar((EDataType)code);
2159 // Note that we differentiate between strings and
2160 // char array by the fact that there is NO specified
2161 // size for a string (see next if (code == 1)
2162
2163 if (vcode) {
2164 leaflist.Form("%s[%s]/%c", &rdname[0], index, vcode);
2165 } else {
2166 Error("BranchOld", "Cannot create branch for rdname: %s code: %d", branchname.Data(), code);
2167 leaflist = "";
2168 }
2169 } else {
2170 // We are possibly a character string.
2171 if (code == 1) {
2172 // We are a character string.
2173 leaflist.Form("%s/%s", dname, "C");
2174 } else {
2175 // Invalid array specification.
2176 // FIXME: We need an error message here.
2177 continue;
2178 }
2179 }
2180 // There are '*' in both the branchname and leaflist, remove them.
2181 TString bname( branchname );
2182 bname.ReplaceAll("*","");
2183 leaflist.ReplaceAll("*","");
2184 // Add the branch to the tree and indicate that the address
2185 // is that of a pointer to be dereferenced before using.
2186 branch1 = new TBranch(branch, bname, *((void**) pointer), leaflist, bufsize);
2187 TLeaf* leaf = (TLeaf*) branch1->GetListOfLeaves()->At(0);
2189 leaf->SetAddress((void**) pointer);
2190 blist->Add(branch1);
2191 }
2192 } else if (dm->IsBasic()) {
2193 // We have a basic type.
2194
2195 char vcode = DataTypeToChar((EDataType)code);
2196 if (vcode) {
2197 leaflist.Form("%s/%c", rdname, vcode);
2198 } else {
2199 Error("BranchOld", "Cannot create branch for rdname: %s code: %d", branchname.Data(), code);
2200 leaflist = "";
2201 }
2202 branch1 = new TBranch(branch, branchname, pointer, leaflist, bufsize);
2203 branch1->SetTitle(rdname);
2204 blist->Add(branch1);
2205 } else {
2206 // We have a class type.
2207 // Note: This cannot happen due to the rd->IsObject() test above.
2208 // FIXME: Put an error message here just in case.
2209 }
2210 if (branch1) {
2211 branch1->SetOffset(offset);
2212 } else {
2213 Warning("BranchOld", "Cannot process member: '%s'", rdname);
2214 }
2215 }
2216 if (delobj) {
2217 delete obj;
2218 obj = 0;
2219 }
2220 return branch;
2221}
2222
2223////////////////////////////////////////////////////////////////////////////////
2224/// Build the optional branch supporting the TRefTable.
2225/// This branch will keep all the information to find the branches
2226/// containing referenced objects.
2227///
2228/// At each Tree::Fill, the branch numbers containing the
2229/// referenced objects are saved to the TBranchRef basket.
2230/// When the Tree header is saved (via TTree::Write), the branch
2231/// is saved keeping the information with the pointers to the branches
2232/// having referenced objects.
2235{
2236 if (!fBranchRef) {
2237 fBranchRef = new TBranchRef(this);
2238 }
2239 return fBranchRef;
2240}
2241
2242////////////////////////////////////////////////////////////////////////////////
2243/// Create a new TTree BranchElement.
2244///
2245/// ## WARNING about this new function
2246///
2247/// This function is designed to replace the internal
2248/// implementation of the old TTree::Branch (whose implementation
2249/// has been moved to BranchOld).
2250///
2251/// NOTE: The 'Bronch' method supports only one possible calls
2252/// signature (where the object type has to be specified
2253/// explicitly and the address must be the address of a pointer).
2254/// For more flexibility use 'Branch'. Use Bronch only in (rare)
2255/// cases (likely to be legacy cases) where both the new and old
2256/// implementation of Branch needs to be used at the same time.
2257///
2258/// This function is far more powerful than the old Branch
2259/// function. It supports the full C++, including STL and has
2260/// the same behaviour in split or non-split mode. classname does
2261/// not have to derive from TObject. The function is based on
2262/// the new TStreamerInfo.
2263///
2264/// Build a TBranchElement for an object of class classname.
2265///
2266/// addr is the address of a pointer to an object of class
2267/// classname. The class dictionary must be available (ClassDef
2268/// in class header).
2269///
2270/// Note: See the comments in TBranchElement::SetAddress() for a more
2271/// detailed discussion of the meaning of the addr parameter.
2272///
2273/// This option requires access to the library where the
2274/// corresponding class is defined. Accessing one single data
2275/// member in the object implies reading the full object.
2276///
2277/// By default the branch buffers are stored in the same file as the Tree.
2278/// use TBranch::SetFile to specify a different file
2279///
2280/// IMPORTANT NOTE about branch names:
2281///
2282/// And in general, in case two or more master branches contain subbranches
2283/// with identical names, one must add a "." (dot) character at the end
2284/// of the master branch name. This will force the name of the subbranches
2285/// to be of the form `master.subbranch` instead of simply `subbranch`.
2286/// This situation happens when the top level object
2287/// has two or more members referencing the same class.
2288/// For example, if a Tree has two branches B1 and B2 corresponding
2289/// to objects of the same class MyClass, one can do:
2290/// ~~~ {.cpp}
2291/// tree.Branch("B1.","MyClass",&b1,8000,1);
2292/// tree.Branch("B2.","MyClass",&b2,8000,1);
2293/// ~~~
2294/// if MyClass has 3 members a,b,c, the two instructions above will generate
2295/// subbranches called B1.a, B1.b ,B1.c, B2.a, B2.b, B2.c
2296///
2297/// bufsize is the buffer size in bytes for this branch
2298/// The default value is 32000 bytes and should be ok for most cases.
2299/// You can specify a larger value (e.g. 256000) if your Tree is not split
2300/// and each entry is large (Megabytes)
2301/// A small value for bufsize is optimum if you intend to access
2302/// the entries in the Tree randomly and your Tree is in split mode.
2303///
2304/// Use splitlevel < 0 instead of splitlevel=0 when the class
2305/// has a custom Streamer
2306///
2307/// Note: if the split level is set to the default (99), TTree::Branch will
2308/// not issue a warning if the class can not be split.
2310TBranch* TTree::Bronch(const char* name, const char* classname, void* addr, Int_t bufsize /* = 32000 */, Int_t splitlevel /* = 99 */)
2311{
2312 return BronchExec(name, classname, addr, kTRUE, bufsize, splitlevel);
2313}
2314
2315////////////////////////////////////////////////////////////////////////////////
2316/// Helper function implementing TTree::Bronch and TTree::Branch(const char *name, T &obj);
2318TBranch* TTree::BronchExec(const char* name, const char* classname, void* addr, Bool_t isptrptr, Int_t bufsize /* = 32000 */, Int_t splitlevel /* = 99 */)
2319{
2320 TClass* cl = TClass::GetClass(classname);
2321 if (!cl) {
2322 Error("Bronch", "Cannot find class:%s", classname);
2323 return 0;
2324 }
2325
2326 //if splitlevel <= 0 and class has a custom Streamer, we must create
2327 //a TBranchObject. We cannot assume that TClass::ReadBuffer is consistent
2328 //with the custom Streamer. The penalty is that one cannot process
2329 //this Tree without the class library containing the class.
2330
2331 char* objptr = 0;
2332 if (!isptrptr) {
2333 objptr = (char*)addr;
2334 } else if (addr) {
2335 objptr = *((char**) addr);
2336 }
2337
2338 if (cl == TClonesArray::Class()) {
2339 TClonesArray* clones = (TClonesArray*) objptr;
2340 if (!clones) {
2341 Error("Bronch", "Pointer to TClonesArray is null");
2342 return 0;
2343 }
2344 if (!clones->GetClass()) {
2345 Error("Bronch", "TClonesArray with no class defined in branch: %s", name);
2346 return 0;
2347 }
2348 if (!clones->GetClass()->HasDataMemberInfo()) {
2349 Error("Bronch", "TClonesArray with no dictionary defined in branch: %s", name);
2350 return 0;
2351 }
2352 bool hasCustomStreamer = clones->GetClass()->TestBit(TClass::kHasCustomStreamerMember);
2353 if (splitlevel > 0) {
2354 if (hasCustomStreamer)
2355 Warning("Bronch", "Using split mode on a class: %s with a custom Streamer", clones->GetClass()->GetName());
2356 } else {
2357 if (hasCustomStreamer) clones->BypassStreamer(kFALSE);
2358 TBranchObject *branch = new TBranchObject(this,name,classname,addr,bufsize,0,/*compress=*/ -1,isptrptr);
2359 fBranches.Add(branch);
2360 return branch;
2361 }
2362 }
2363
2364 if (cl->GetCollectionProxy()) {
2366 //if (!collProxy) {
2367 // Error("Bronch", "%s is missing its CollectionProxy (for branch %s)", classname, name);
2368 //}
2369 TClass* inklass = collProxy->GetValueClass();
2370 if (!inklass && (collProxy->GetType() == 0)) {
2371 Error("Bronch", "%s with no class defined in branch: %s", classname, name);
2372 return 0;
2373 }
2374 if ((splitlevel > 0) && inklass && (inklass->GetCollectionProxy() == 0)) {
2376 if ((stl != ROOT::kSTLmap) && (stl != ROOT::kSTLmultimap)) {
2377 if (!inklass->HasDataMemberInfo()) {
2378 Error("Bronch", "Container with no dictionary defined in branch: %s", name);
2379 return 0;
2380 }
2382 Warning("Bronch", "Using split mode on a class: %s with a custom Streamer", inklass->GetName());
2383 }
2384 }
2385 }
2386 //-------------------------------------------------------------------------
2387 // If the splitting switch is enabled, the split level is big enough and
2388 // the collection contains pointers we can split it
2389 //////////////////////////////////////////////////////////////////////////
2390
2391 TBranch *branch;
2392 if( splitlevel > kSplitCollectionOfPointers && collProxy->HasPointers() )
2393 branch = new TBranchSTL( this, name, collProxy, bufsize, splitlevel );
2394 else
2395 branch = new TBranchElement(this, name, collProxy, bufsize, splitlevel);
2396 fBranches.Add(branch);
2397 if (isptrptr) {
2398 branch->SetAddress(addr);
2399 } else {
2400 branch->SetObject(addr);
2401 }
2402 return branch;
2403 }
2404
2405 Bool_t hasCustomStreamer = kFALSE;
2406 if (!cl->HasDataMemberInfo() && !cl->GetCollectionProxy()) {
2407 Error("Bronch", "Cannot find dictionary for class: %s", classname);
2408 return 0;
2409 }
2410
2412 // Not an STL container and the linkdef file had a "-" after the class name.
2413 hasCustomStreamer = kTRUE;
2414 }
2415
2416 if (splitlevel < 0 || ((splitlevel == 0) && hasCustomStreamer && cl->IsTObject())) {
2417 TBranchObject* branch = new TBranchObject(this, name, classname, addr, bufsize, 0, /*compress=*/ ROOT::RCompressionSetting::EAlgorithm::kInherit, isptrptr);
2418 fBranches.Add(branch);
2419 return branch;
2420 }
2421
2422 if (cl == TClonesArray::Class()) {
2423 // Special case of TClonesArray.
2424 // No dummy object is created.
2425 // The streamer info is not rebuilt unoptimized.
2426 // No dummy top-level branch is created.
2427 // No splitting is attempted.
2428 TBranchElement* branch = new TBranchElement(this, name, (TClonesArray*) objptr, bufsize, splitlevel%kSplitCollectionOfPointers);
2429 fBranches.Add(branch);
2430 if (isptrptr) {
2431 branch->SetAddress(addr);
2432 } else {
2433 branch->SetObject(addr);
2434 }
2435 return branch;
2436 }
2437
2438 //
2439 // If we are not given an object to use as an i/o buffer
2440 // then create a temporary one which we will delete just
2441 // before returning.
2442 //
2443
2444 Bool_t delobj = kFALSE;
2445
2446 if (!objptr) {
2447 objptr = (char*) cl->New();
2448 delobj = kTRUE;
2449 }
2450
2451 //
2452 // Avoid splitting unsplittable classes.
2453 //
2454
2455 if ((splitlevel > 0) && !cl->CanSplit()) {
2456 if (splitlevel != 99) {
2457 Warning("Bronch", "%s cannot be split, resetting splitlevel to 0", cl->GetName());
2458 }
2459 splitlevel = 0;
2460 }
2461
2462 //
2463 // Make sure the streamer info is built and fetch it.
2464 //
2465 // If we are splitting, then make sure the streamer info
2466 // is built unoptimized (data members are not combined).
2467 //
2468
2469 TStreamerInfo* sinfo = BuildStreamerInfo(cl, objptr, splitlevel==0);
2470 if (!sinfo) {
2471 Error("Bronch", "Cannot build the StreamerInfo for class: %s", cl->GetName());
2472 return 0;
2473 }
2474
2475 //
2476 // Create a dummy top level branch object.
2477 //
2478
2479 Int_t id = -1;
2480 if (splitlevel > 0) {
2481 id = -2;
2482 }
2483 TBranchElement* branch = new TBranchElement(this, name, sinfo, id, objptr, bufsize, splitlevel);
2484 fBranches.Add(branch);
2485
2486 //
2487 // Do splitting, if requested.
2488 //
2489
2490 if (splitlevel%kSplitCollectionOfPointers > 0) {
2491 branch->Unroll(name, cl, sinfo, objptr, bufsize, splitlevel);
2492 }
2493
2494 //
2495 // Setup our offsets into the user's i/o buffer.
2496 //
2497
2498 if (isptrptr) {
2499 branch->SetAddress(addr);
2500 } else {
2501 branch->SetObject(addr);
2502 }
2503
2504 if (delobj) {
2505 cl->Destructor(objptr);
2506 objptr = 0;
2507 }
2508
2509 return branch;
2510}
2511
2512////////////////////////////////////////////////////////////////////////////////
2513/// Browse content of the TTree.
2516{
2518 if (fUserInfo) {
2519 if (strcmp("TList",fUserInfo->GetName())==0) {
2520 fUserInfo->SetName("UserInfo");
2521 b->Add(fUserInfo);
2522 fUserInfo->SetName("TList");
2523 } else {
2524 b->Add(fUserInfo);
2525 }
2526 }
2527}
2528
2529////////////////////////////////////////////////////////////////////////////////
2530/// Build a Tree Index (default is TTreeIndex).
2531/// See a description of the parameters and functionality in
2532/// TTreeIndex::TTreeIndex().
2533///
2534/// The return value is the number of entries in the Index (< 0 indicates failure).
2535///
2536/// A TTreeIndex object pointed by fTreeIndex is created.
2537/// This object will be automatically deleted by the TTree destructor.
2538/// If an index is already existing, this is replaced by the new one without being
2539/// deleted. This behaviour prevents the deletion of a previously external index
2540/// assigned to the TTree via the TTree::SetTreeIndex() method.
2541/// See also comments in TTree::SetTreeIndex().
2543Int_t TTree::BuildIndex(const char* majorname, const char* minorname /* = "0" */)
2544{
2545 fTreeIndex = GetPlayer()->BuildIndex(this, majorname, minorname);
2546 if (fTreeIndex->IsZombie()) {
2547 delete fTreeIndex;
2548 fTreeIndex = 0;
2549 return 0;
2550 }
2551 return fTreeIndex->GetN();
2552}
2553
2554////////////////////////////////////////////////////////////////////////////////
2555/// Build StreamerInfo for class cl.
2556/// pointer is an optional argument that may contain a pointer to an object of cl.
2558TStreamerInfo* TTree::BuildStreamerInfo(TClass* cl, void* pointer /* = 0 */, Bool_t canOptimize /* = kTRUE */ )
2559{
2560 if (!cl) {
2561 return 0;
2562 }
2563 cl->BuildRealData(pointer);
2565
2566 // Create StreamerInfo for all base classes.
2567 TBaseClass* base = 0;
2568 TIter nextb(cl->GetListOfBases());
2569 while((base = (TBaseClass*) nextb())) {
2570 if (base->IsSTLContainer()) {
2571 continue;
2572 }
2573 TClass* clm = TClass::GetClass(base->GetName());
2574 BuildStreamerInfo(clm, pointer, canOptimize);
2575 }
2576 if (sinfo && fDirectory) {
2578 }
2579 return sinfo;
2580}
2581
2582////////////////////////////////////////////////////////////////////////////////
2583/// Called by TTree::Fill() when file has reached its maximum fgMaxTreeSize.
2584/// Create a new file. If the original file is named "myfile.root",
2585/// subsequent files are named "myfile_1.root", "myfile_2.root", etc.
2586///
2587/// Returns a pointer to the new file.
2588///
2589/// Currently, the automatic change of file is restricted
2590/// to the case where the tree is in the top level directory.
2591/// The file should not contain sub-directories.
2592///
2593/// Before switching to a new file, the tree header is written
2594/// to the current file, then the current file is closed.
2595///
2596/// To process the multiple files created by ChangeFile, one must use
2597/// a TChain.
2598///
2599/// The new file name has a suffix "_N" where N is equal to fFileNumber+1.
2600/// By default a Root session starts with fFileNumber=0. One can set
2601/// fFileNumber to a different value via TTree::SetFileNumber.
2602/// In case a file named "_N" already exists, the function will try
2603/// a file named "__N", then "___N", etc.
2604///
2605/// fgMaxTreeSize can be set via the static function TTree::SetMaxTreeSize.
2606/// The default value of fgMaxTreeSize is 100 Gigabytes.
2607///
2608/// If the current file contains other objects like TH1 and TTree,
2609/// these objects are automatically moved to the new file.
2610///
2611/// IMPORTANT NOTE:
2612///
2613/// Be careful when writing the final Tree header to the file!
2614///
2615/// Don't do:
2616/// ~~~ {.cpp}
2617/// TFile *file = new TFile("myfile.root","recreate");
2618/// TTree *T = new TTree("T","title");
2619/// T->Fill(); //loop
2620/// file->Write();
2621/// file->Close();
2622/// ~~~
2623/// but do the following:
2624/// ~~~ {.cpp}
2625/// TFile *file = new TFile("myfile.root","recreate");
2626/// TTree *T = new TTree("T","title");
2627/// T->Fill(); //loop
2628/// file = T->GetCurrentFile(); //to get the pointer to the current file
2629/// file->Write();
2630/// file->Close();
2631/// ~~~
2634{
2635 file->cd();
2636 Write();
2637 Reset();
2638 constexpr auto kBufSize = 2000;
2639 char* fname = new char[kBufSize];
2640 ++fFileNumber;
2641 char uscore[10];
2642 for (Int_t i = 0; i < 10; ++i) {
2643 uscore[i] = 0;
2644 }
2645 Int_t nus = 0;
2646 // Try to find a suitable file name that does not already exist.
2647 while (nus < 10) {
2648 uscore[nus] = '_';
2649 fname[0] = 0;
2650 strlcpy(fname, file->GetName(), kBufSize);
2651
2652 if (fFileNumber > 1) {
2653 char* cunder = strrchr(fname, '_');
2654 if (cunder) {
2655 snprintf(cunder, kBufSize - Int_t(cunder - fname), "%s%d", uscore, fFileNumber);
2656 const char* cdot = strrchr(file->GetName(), '.');
2657 if (cdot) {
2658 strlcat(fname, cdot, kBufSize);
2659 }
2660 } else {
2661 char fcount[21];
2662 snprintf(fcount,21, "%s%d", uscore, fFileNumber);
2663 strlcat(fname, fcount, kBufSize);
2664 }
2665 } else {
2666 char* cdot = strrchr(fname, '.');
2667 if (cdot) {
2668 snprintf(cdot, kBufSize - Int_t(fname-cdot), "%s%d", uscore, fFileNumber);
2669 strlcat(fname, strrchr(file->GetName(), '.'), kBufSize);
2670 } else {
2671 char fcount[21];
2672 snprintf(fcount,21, "%s%d", uscore, fFileNumber);
2673 strlcat(fname, fcount, kBufSize);
2674 }
2675 }
2676 if (gSystem->AccessPathName(fname)) {
2677 break;
2678 }
2679 ++nus;
2680 Warning("ChangeFile", "file %s already exist, trying with %d underscores", fname, nus+1);
2681 }
2682 Int_t compress = file->GetCompressionSettings();
2683 TFile* newfile = TFile::Open(fname, "recreate", "chain files", compress);
2684 if (newfile == 0) {
2685 Error("Fill","Failed to open new file %s, continuing as a memory tree.",fname);
2686 } else {
2687 Printf("Fill: Switching to new file: %s", fname);
2688 }
2689 // The current directory may contain histograms and trees.
2690 // These objects must be moved to the new file.
2691 TBranch* branch = 0;
2692 TObject* obj = 0;
2693 while ((obj = file->GetList()->First())) {
2694 file->Remove(obj);
2695 // Histogram: just change the directory.
2696 if (obj->InheritsFrom("TH1")) {
2697 gROOT->ProcessLine(TString::Format("((%s*)0x%lx)->SetDirectory((TDirectory*)0x%lx);", obj->ClassName(), (Long_t) obj, (Long_t) newfile));
2698 continue;
2699 }
2700 // Tree: must save all trees in the old file, reset them.
2701 if (obj->InheritsFrom(TTree::Class())) {
2702 TTree* t = (TTree*) obj;
2703 if (t != this) {
2704 t->AutoSave();
2705 t->Reset();
2707 }
2708 t->SetDirectory(newfile);
2709 TIter nextb(t->GetListOfBranches());
2710 while ((branch = (TBranch*)nextb())) {
2711 branch->SetFile(newfile);
2712 }
2713 if (t->GetBranchRef()) {
2714 t->GetBranchRef()->SetFile(newfile);
2715 }
2716 continue;
2717 }
2718 // Not a TH1 or a TTree, move object to new file.
2719 if (newfile) newfile->Append(obj);
2720 file->Remove(obj);
2721 }
2722 delete file;
2723 file = 0;
2724 delete[] fname;
2725 fname = 0;
2726 return newfile;
2727}
2728
2729////////////////////////////////////////////////////////////////////////////////
2730/// Check whether or not the address described by the last 3 parameters
2731/// matches the content of the branch. If a Data Model Evolution conversion
2732/// is involved, reset the fInfo of the branch.
2733/// The return values are:
2734//
2735/// - kMissingBranch (-5) : Missing branch
2736/// - kInternalError (-4) : Internal error (could not find the type corresponding to a data type number)
2737/// - kMissingCompiledCollectionProxy (-3) : Missing compiled collection proxy for a compiled collection
2738/// - kMismatch (-2) : Non-Class Pointer type given does not match the type expected by the branch
2739/// - kClassMismatch (-1) : Class Pointer type given does not match the type expected by the branch
2740/// - kMatch (0) : perfect match
2741/// - kMatchConversion (1) : match with (I/O) conversion
2742/// - kMatchConversionCollection (2) : match with (I/O) conversion of the content of a collection
2743/// - kMakeClass (3) : MakeClass mode so we can not check.
2744/// - kVoidPtr (4) : void* passed so no check was made.
2745/// - kNoCheck (5) : Underlying TBranch not yet available so no check was made.
2747Int_t TTree::CheckBranchAddressType(TBranch* branch, TClass* ptrClass, EDataType datatype, Bool_t isptr)
2748{
2749 if (GetMakeClass()) {
2750 // If we are in MakeClass mode so we do not really use classes.
2751 return kMakeClass;
2752 }
2753
2754 // Let's determine what we need!
2755 TClass* expectedClass = 0;
2756 EDataType expectedType = kOther_t;
2757 if (0 != branch->GetExpectedType(expectedClass,expectedType) ) {
2758 // Something went wrong, the warning message has already be issued.
2759 return kInternalError;
2760 }
2761 if (expectedClass && datatype == kOther_t && ptrClass == 0) {
2762 if (branch->InheritsFrom( TBranchElement::Class() )) {
2763 TBranchElement* bEl = (TBranchElement*)branch;
2764 bEl->SetTargetClass( expectedClass->GetName() );
2765 }
2766 if (expectedClass && expectedClass->GetCollectionProxy() && dynamic_cast<TEmulatedCollectionProxy*>(expectedClass->GetCollectionProxy())) {
2767 Error("SetBranchAddress", "Unable to determine the type given for the address for \"%s\". "
2768 "The class expected (%s) refers to an stl collection and do not have a compiled CollectionProxy. "
2769 "Please generate the dictionary for this class (%s)",
2770 branch->GetName(), expectedClass->GetName(), expectedClass->GetName());
2772 }
2773 if (!expectedClass->IsLoaded()) {
2774 // The originally expected class does not have a dictionary, it is then plausible that the pointer being passed is the right type
2775 // (we really don't know). So let's express that.
2776 Error("SetBranchAddress", "Unable to determine the type given for the address for \"%s\". "
2777 "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."
2778 "Please generate the dictionary for this class (%s)",
2779 branch->GetName(), expectedClass->GetName(), expectedClass->GetName());
2780 } else {
2781 Error("SetBranchAddress", "Unable to determine the type given for the address for \"%s\". "
2782 "This is probably due to a missing dictionary, the original data class for this branch is %s.", branch->GetName(), expectedClass->GetName());
2783 }
2784 return kClassMismatch;
2785 }
2786 if (expectedClass && ptrClass && (branch->GetMother() == branch)) {
2787 // Top Level branch
2788 if (!isptr) {
2789 Error("SetBranchAddress", "The address for \"%s\" should be the address of a pointer!", branch->GetName());
2790 }
2791 }
2792 if (expectedType == kFloat16_t) {
2793 expectedType = kFloat_t;
2794 }
2795 if (expectedType == kDouble32_t) {
2796 expectedType = kDouble_t;
2797 }
2798 if (datatype == kFloat16_t) {
2799 datatype = kFloat_t;
2800 }
2801 if (datatype == kDouble32_t) {
2802 datatype = kDouble_t;
2803 }
2804
2805 /////////////////////////////////////////////////////////////////////////////
2806 // Deal with the class renaming
2807 /////////////////////////////////////////////////////////////////////////////
2808
2809 if( expectedClass && ptrClass &&
2810 expectedClass != ptrClass &&
2811 branch->InheritsFrom( TBranchElement::Class() ) &&
2812 ptrClass->GetSchemaRules() &&
2813 ptrClass->GetSchemaRules()->HasRuleWithSourceClass( expectedClass->GetName() ) ) {
2814 TBranchElement* bEl = (TBranchElement*)branch;
2815
2816 if ( ptrClass->GetCollectionProxy() && expectedClass->GetCollectionProxy() ) {
2817 if (gDebug > 7)
2818 Info("SetBranchAddress", "Matching STL collection (at least according to the SchemaRuleSet when "
2819 "reading a %s into a %s",expectedClass->GetName(),ptrClass->GetName());
2820
2821 bEl->SetTargetClass( ptrClass->GetName() );
2822 return kMatchConversion;
2823
2824 } else if ( !ptrClass->GetConversionStreamerInfo( expectedClass, bEl->GetClassVersion() ) &&
2825 !ptrClass->FindConversionStreamerInfo( expectedClass, bEl->GetCheckSum() ) ) {
2826 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());
2827
2828 bEl->SetTargetClass( expectedClass->GetName() );
2829 return kClassMismatch;
2830 }
2831 else {
2832
2833 bEl->SetTargetClass( ptrClass->GetName() );
2834 return kMatchConversion;
2835 }
2836
2837 } else if (expectedClass && ptrClass && !expectedClass->InheritsFrom(ptrClass)) {
2838
2839 if (expectedClass->GetCollectionProxy() && ptrClass->GetCollectionProxy() &&
2840 branch->InheritsFrom( TBranchElement::Class() ) &&
2841 expectedClass->GetCollectionProxy()->GetValueClass() &&
2842 ptrClass->GetCollectionProxy()->GetValueClass() )
2843 {
2844 // In case of collection, we know how to convert them, if we know how to convert their content.
2845 // NOTE: we need to extend this to std::pair ...
2846
2847 TClass *onfileValueClass = expectedClass->GetCollectionProxy()->GetValueClass();
2848 TClass *inmemValueClass = ptrClass->GetCollectionProxy()->GetValueClass();
2849
2850 if (inmemValueClass->GetSchemaRules() &&
2851 inmemValueClass->GetSchemaRules()->HasRuleWithSourceClass(onfileValueClass->GetName() ) )
2852 {
2853 TBranchElement* bEl = (TBranchElement*)branch;
2854 bEl->SetTargetClass( ptrClass->GetName() );
2856 }
2857 }
2858
2859 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());
2860 if (branch->InheritsFrom( TBranchElement::Class() )) {
2861 TBranchElement* bEl = (TBranchElement*)branch;
2862 bEl->SetTargetClass( expectedClass->GetName() );
2863 }
2864 return kClassMismatch;
2865
2866 } else if ((expectedType != kOther_t) && (datatype != kOther_t) && (expectedType != kNoType_t) && (datatype != kNoType_t) && (expectedType != datatype)) {
2867 if (datatype != kChar_t) {
2868 // For backward compatibility we assume that (char*) was just a cast and/or a generic address
2869 Error("SetBranchAddress", "The pointer type given \"%s\" (%d) does not correspond to the type needed \"%s\" (%d) by the branch: %s",
2870 TDataType::GetTypeName(datatype), datatype, TDataType::GetTypeName(expectedType), expectedType, branch->GetName());
2871 return kMismatch;
2872 }
2873 } else if ((expectedClass && (datatype != kOther_t && datatype != kNoType_t && datatype != kInt_t)) ||
2874 (ptrClass && (expectedType != kOther_t && expectedType != kNoType_t && datatype != kInt_t)) ) {
2875 // Sometime a null pointer can look an int, avoid complaining in that case.
2876 if (expectedClass) {
2877 Error("SetBranchAddress", "The pointer type given \"%s\" (%d) does not correspond to the type needed \"%s\" by the branch: %s",
2878 TDataType::GetTypeName(datatype), datatype, expectedClass->GetName(), branch->GetName());
2879 if (branch->InheritsFrom( TBranchElement::Class() )) {
2880 TBranchElement* bEl = (TBranchElement*)branch;
2881 bEl->SetTargetClass( expectedClass->GetName() );
2882 }
2883 } else {
2884 // 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
2885 // a struct).
2886 bool found = false;
2887 if (ptrClass->IsLoaded()) {
2888 TIter next(ptrClass->GetListOfRealData());
2889 TRealData *rdm;
2890 while ((rdm = (TRealData*)next())) {
2891 if (rdm->GetThisOffset() == 0) {
2892 TDataType *dmtype = rdm->GetDataMember()->GetDataType();
2893 if (dmtype) {
2894 EDataType etype = (EDataType)dmtype->GetType();
2895 if (etype == expectedType) {
2896 found = true;
2897 }
2898 }
2899 break;
2900 }
2901 }
2902 } else {
2903 TIter next(ptrClass->GetListOfDataMembers());
2904 TDataMember *dm;
2905 while ((dm = (TDataMember*)next())) {
2906 if (dm->GetOffset() == 0) {
2907 TDataType *dmtype = dm->GetDataType();
2908 if (dmtype) {
2909 EDataType etype = (EDataType)dmtype->GetType();
2910 if (etype == expectedType) {
2911 found = true;
2912 }
2913 }
2914 break;
2915 }
2916 }
2917 }
2918 if (found) {
2919 // let's check the size.
2920 TLeaf *last = (TLeaf*)branch->GetListOfLeaves()->Last();
2921 long len = last->GetOffset() + last->GetLenType() * last->GetLen();
2922 if (len <= ptrClass->Size()) {
2923 return kMatch;
2924 }
2925 }
2926 Error("SetBranchAddress", "The pointer type given \"%s\" does not correspond to the type needed \"%s\" (%d) by the branch: %s",
2927 ptrClass->GetName(), TDataType::GetTypeName(expectedType), expectedType, branch->GetName());
2928 }
2929 return kMismatch;
2930 }
2931 if (expectedClass && expectedClass->GetCollectionProxy() && dynamic_cast<TEmulatedCollectionProxy*>(expectedClass->GetCollectionProxy())) {
2932 Error("SetBranchAddress", writeStlWithoutProxyMsg,
2933 expectedClass->GetName(), branch->GetName(), expectedClass->GetName());
2934 if (branch->InheritsFrom( TBranchElement::Class() )) {
2935 TBranchElement* bEl = (TBranchElement*)branch;
2936 bEl->SetTargetClass( expectedClass->GetName() );
2937 }
2939 }
2940 if (expectedClass && branch->InheritsFrom( TBranchElement::Class() )) {
2941 TBranchElement* bEl = (TBranchElement*)branch;
2942 bEl->SetTargetClass( expectedClass->GetName() );
2943 }
2944 return kMatch;
2945}
2946
2947////////////////////////////////////////////////////////////////////////////////
2948/// Create a clone of this tree and copy nentries.
2949///
2950/// By default copy all entries.
2951/// The compression level of the cloned tree is set to the destination
2952/// file's compression level.
2953///
2954/// NOTE: Only active branches are copied.
2955/// NOTE: If the TTree is a TChain, the structure of the first TTree
2956/// is used for the copy.
2957///
2958/// IMPORTANT: The cloned tree stays connected with this tree until
2959/// this tree is deleted. In particular, any changes in
2960/// branch addresses in this tree are forwarded to the
2961/// clone trees, unless a branch in a clone tree has had
2962/// its address changed, in which case that change stays in
2963/// effect. When this tree is deleted, all the addresses of
2964/// the cloned tree are reset to their default values.
2965///
2966/// If 'option' contains the word 'fast' and nentries is -1, the
2967/// cloning will be done without unzipping or unstreaming the baskets
2968/// (i.e., a direct copy of the raw bytes on disk).
2969///
2970/// When 'fast' is specified, 'option' can also contain a sorting
2971/// order for the baskets in the output file.
2972///
2973/// There are currently 3 supported sorting order:
2974///
2975/// - SortBasketsByOffset (the default)
2976/// - SortBasketsByBranch
2977/// - SortBasketsByEntry
2978///
2979/// When using SortBasketsByOffset the baskets are written in the
2980/// output file in the same order as in the original file (i.e. the
2981/// baskets are sorted by their offset in the original file; Usually
2982/// this also means that the baskets are sorted by the index/number of
2983/// the _last_ entry they contain)
2984///
2985/// When using SortBasketsByBranch all the baskets of each individual
2986/// branches are stored contiguously. This tends to optimize reading
2987/// speed when reading a small number (1->5) of branches, since all
2988/// their baskets will be clustered together instead of being spread
2989/// across the file. However it might decrease the performance when
2990/// reading more branches (or the full entry).
2991///
2992/// When using SortBasketsByEntry the baskets with the lowest starting
2993/// entry are written first. (i.e. the baskets are sorted by the
2994/// index/number of the first entry they contain). This means that on
2995/// the file the baskets will be in the order in which they will be
2996/// needed when reading the whole tree sequentially.
2997///
2998/// For examples of CloneTree, see tutorials:
2999///
3000/// - copytree.C:
3001/// A macro to copy a subset of a TTree to a new TTree.
3002/// The input file has been generated by the program in
3003/// $ROOTSYS/test/Event with: Event 1000 1 1 1
3004///
3005/// - copytree2.C:
3006/// A macro to copy a subset of a TTree to a new TTree.
3007/// One branch of the new Tree is written to a separate file.
3008/// The input file has been generated by the program in
3009/// $ROOTSYS/test/Event with: Event 1000 1 1 1
3011TTree* TTree::CloneTree(Long64_t nentries /* = -1 */, Option_t* option /* = "" */)
3012{
3013 // Options
3014 Bool_t fastClone = kFALSE;
3015
3016 TString opt = option;
3017 opt.ToLower();
3018 if (opt.Contains("fast")) {
3019 fastClone = kTRUE;
3020 }
3021
3022 // If we are a chain, switch to the first tree.
3023 if ((fEntries > 0) && (LoadTree(0) < 0)) {
3024 // FIXME: We need an error message here.
3025 return 0;
3026 }
3027
3028 // Note: For a tree we get the this pointer, for
3029 // a chain we get the chain's current tree.
3030 TTree* thistree = GetTree();
3031
3032 // We will use this to override the IO features on the cloned branches.
3033 ROOT::TIOFeatures features = this->GetIOFeatures();
3034 ;
3035
3036 // Note: For a chain, the returned clone will be
3037 // a clone of the chain's first tree.
3038 TTree* newtree = (TTree*) thistree->Clone();
3039 if (!newtree) {
3040 return 0;
3041 }
3042
3043 // The clone should not delete any objects allocated by SetAddress().
3044 TObjArray* branches = newtree->GetListOfBranches();
3045 Int_t nb = branches->GetEntriesFast();
3046 for (Int_t i = 0; i < nb; ++i) {
3047 TBranch* br = (TBranch*) branches->UncheckedAt(i);
3049 ((TBranchElement*) br)->ResetDeleteObject();
3050 }
3051 }
3052
3053 // Add the new tree to the list of clones so that
3054 // we can later inform it of changes to branch addresses.
3055 thistree->AddClone(newtree);
3056 if (thistree != this) {
3057 // In case this object is a TChain, add the clone
3058 // also to the TChain's list of clones.
3059 AddClone(newtree);
3060 }
3061
3062 newtree->Reset();
3063
3064 TDirectory* ndir = newtree->GetDirectory();
3065 TFile* nfile = 0;
3066 if (ndir) {
3067 nfile = ndir->GetFile();
3068 }
3069 Int_t newcomp = -1;
3070 if (nfile) {
3071 newcomp = nfile->GetCompressionSettings();
3072 }
3073
3074 //
3075 // Delete non-active branches from the clone.
3076 //
3077 // Note: If we are a chain, this does nothing
3078 // since chains have no leaves.
3079 TObjArray* leaves = newtree->GetListOfLeaves();
3080 Int_t nleaves = leaves->GetEntriesFast();
3081 for (Int_t lndx = 0; lndx < nleaves; ++lndx) {
3082 TLeaf* leaf = (TLeaf*) leaves->UncheckedAt(lndx);
3083 if (!leaf) {
3084 continue;
3085 }
3086 TBranch* branch = leaf->GetBranch();
3087 if (branch && (newcomp > -1)) {
3088 branch->SetCompressionSettings(newcomp);
3089 }
3090 if (branch) branch->SetIOFeatures(features);
3091 if (!branch || !branch->TestBit(kDoNotProcess)) {
3092 continue;
3093 }
3094 // size might change at each iteration of the loop over the leaves.
3095 nb = branches->GetEntriesFast();
3096 for (Long64_t i = 0; i < nb; ++i) {
3097 TBranch* br = (TBranch*) branches->UncheckedAt(i);
3098 if (br == branch) {
3099 branches->RemoveAt(i);
3100 delete br;
3101 br = 0;
3102 branches->Compress();
3103 break;
3104 }
3105 TObjArray* lb = br->GetListOfBranches();
3106 Int_t nb1 = lb->GetEntriesFast();
3107 for (Int_t j = 0; j < nb1; ++j) {
3108 TBranch* b1 = (TBranch*) lb->UncheckedAt(j);
3109 if (!b1) {
3110 continue;
3111 }
3112 if (b1 == branch) {
3113 lb->RemoveAt(j);
3114 delete b1;
3115 b1 = 0;
3116 lb->Compress();
3117 break;
3118 }
3119 TObjArray* lb1 = b1->GetListOfBranches();
3120 Int_t nb2 = lb1->GetEntriesFast();
3121 for (Int_t k = 0; k < nb2; ++k) {
3122 TBranch* b2 = (TBranch*) lb1->UncheckedAt(k);
3123 if (!b2) {
3124 continue;
3125 }
3126 if (b2 == branch) {
3127 lb1->RemoveAt(k);
3128 delete b2;
3129 b2 = 0;
3130 lb1->Compress();
3131 break;
3132 }
3133 }
3134 }
3135 }
3136 }
3137 leaves->Compress();
3138
3139 // Copy MakeClass status.
3140 newtree->SetMakeClass(fMakeClass);
3141
3142 // Copy branch addresses.
3143 CopyAddresses(newtree);
3144
3145 //
3146 // Copy entries if requested.
3147 //
3148
3149 if (nentries != 0) {
3150 if (fastClone && (nentries < 0)) {
3151 if ( newtree->CopyEntries( this, -1, option ) < 0 ) {
3152 // There was a problem!
3153 Error("CloneTTree", "TTree has not been cloned\n");
3154 delete newtree;
3155 newtree = 0;
3156 return 0;
3157 }
3158 } else {
3159 newtree->CopyEntries( this, nentries, option );
3160 }
3161 }
3162
3163 return newtree;
3164}
3165
3166////////////////////////////////////////////////////////////////////////////////
3167/// Set branch addresses of passed tree equal to ours.
3168/// If undo is true, reset the branch address instead of copying them.
3169/// This insures 'separation' of a cloned tree from its original
3172{
3173 // Copy branch addresses starting from branches.
3174 TObjArray* branches = GetListOfBranches();
3175 Int_t nbranches = branches->GetEntriesFast();
3176 for (Int_t i = 0; i < nbranches; ++i) {
3177 TBranch* branch = (TBranch*) branches->UncheckedAt(i);
3178 if (branch->TestBit(kDoNotProcess)) {
3179 continue;
3180 }
3181 if (undo) {
3182 TBranch* br = tree->GetBranch(branch->GetName());
3183 tree->ResetBranchAddress(br);
3184 } else {
3185 char* addr = branch->GetAddress();
3186 if (!addr) {
3187 if (branch->IsA() == TBranch::Class()) {
3188 // If the branch was created using a leaflist, the branch itself may not have
3189 // an address but the leaf might already.
3190 TLeaf *firstleaf = (TLeaf*)branch->GetListOfLeaves()->At(0);
3191 if (!firstleaf || firstleaf->GetValuePointer()) {
3192 // Either there is no leaf (and thus no point in copying the address)
3193 // or the leaf has an address but we can not copy it via the branche
3194 // this will be copied via the next loop (over the leaf).
3195 continue;
3196 }
3197 }
3198 // Note: This may cause an object to be allocated.
3199 branch->SetAddress(0);
3200 addr = branch->GetAddress();
3201 }
3202 // FIXME: The GetBranch() function is braindead and may
3203 // not find the branch!
3204 TBranch* br = tree->GetBranch(branch->GetName());
3205 if (br) {
3206 br->SetAddress(addr);
3207 // The copy does not own any object allocated by SetAddress().
3209 ((TBranchElement*) br)->ResetDeleteObject();
3210 }
3211 } else {
3212 Warning("CopyAddresses", "Could not find branch named '%s' in tree named '%s'", branch->GetName(), tree->GetName());
3213 }
3214 }
3215 }
3216
3217 // Copy branch addresses starting from leaves.
3218 TObjArray* tleaves = tree->GetListOfLeaves();
3219 Int_t ntleaves = tleaves->GetEntriesFast();
3220 std::set<TLeaf*> updatedLeafCount;
3221 for (Int_t i = 0; i < ntleaves; ++i) {
3222 TLeaf* tleaf = (TLeaf*) tleaves->UncheckedAt(i);
3223 TBranch* tbranch = tleaf->GetBranch();
3224 TBranch* branch = GetBranch(tbranch->GetName());
3225 if (!branch) {
3226 continue;
3227 }
3228 TLeaf* leaf = branch->GetLeaf(tleaf->GetName());
3229 if (!leaf) {
3230 continue;
3231 }
3232 if (branch->TestBit(kDoNotProcess)) {
3233 continue;
3234 }
3235 if (undo) {
3236 // Now we know whether the address has been transfered
3237 tree->ResetBranchAddress(tbranch);
3238 } else {
3239 TBranchElement *mother = dynamic_cast<TBranchElement*>(leaf->GetBranch()->GetMother());
3240 bool needAddressReset = false;
3241 if (leaf->GetLeafCount() && (leaf->TestBit(TLeaf::kNewValue) || !leaf->GetValuePointer() || (mother && mother->IsObjectOwner())) && tleaf->GetLeafCount())
3242 {
3243 // If it is an array and it was allocated by the leaf itself,
3244 // let's make sure it is large enough for the incoming data.
3245 if (leaf->GetLeafCount()->GetMaximum() < tleaf->GetLeafCount()->GetMaximum()) {
3246 leaf->GetLeafCount()->IncludeRange( tleaf->GetLeafCount() );
3247 updatedLeafCount.insert(leaf->GetLeafCount());
3248 needAddressReset = true;
3249 } else {
3250 needAddressReset = (updatedLeafCount.find(leaf->GetLeafCount()) != updatedLeafCount.end());
3251 }
3252 }
3253 if (needAddressReset && leaf->GetValuePointer()) {
3254 if (leaf->IsA() == TLeafElement::Class() && mother)
3255 mother->ResetAddress();
3256 else
3257 leaf->SetAddress(nullptr);
3258 }
3259 if (!branch->GetAddress() && !leaf->GetValuePointer()) {
3260 // We should attempts to set the address of the branch.
3261 // something like:
3262 //(TBranchElement*)branch->GetMother()->SetAddress(0)
3263 //plus a few more subtilities (see TBranchElement::GetEntry).
3264 //but for now we go the simplest route:
3265 //
3266 // Note: This may result in the allocation of an object.
3267 branch->SetupAddresses();
3268 }
3269 if (branch->GetAddress()) {
3270 tree->SetBranchAddress(branch->GetName(), (void*) branch->GetAddress());
3271 TBranch* br = tree->GetBranch(branch->GetName());
3272 if (br) {
3273 // The copy does not own any object allocated by SetAddress().
3274 // FIXME: We do too much here, br may not be a top-level branch.
3276 ((TBranchElement*) br)->ResetDeleteObject();
3277 }
3278 } else {
3279 Warning("CopyAddresses", "Could not find branch named '%s' in tree named '%s'", branch->GetName(), tree->GetName());
3280 }
3281 } else {
3282 tleaf->SetAddress(leaf->GetValuePointer());
3283 }
3284 }
3285 }
3286
3287 if (undo &&
3288 ( tree->IsA()->InheritsFrom("TNtuple") || tree->IsA()->InheritsFrom("TNtupleD") )
3289 ) {
3290 tree->ResetBranchAddresses();
3291 }
3292}
3293
3294namespace {
3295
3296 enum EOnIndexError { kDrop, kKeep, kBuild };
3297
3298 static Bool_t R__HandleIndex(EOnIndexError onIndexError, TTree *newtree, TTree *oldtree)
3299 {
3300 // Return true if we should continue to handle indices, false otherwise.
3301
3302 Bool_t withIndex = kTRUE;
3303
3304 if ( newtree->GetTreeIndex() ) {
3305 if ( oldtree->GetTree()->GetTreeIndex() == 0 ) {
3306 switch (onIndexError) {
3307 case kDrop:
3308 delete newtree->GetTreeIndex();
3309 newtree->SetTreeIndex(0);
3310 withIndex = kFALSE;
3311 break;
3312 case kKeep:
3313 // Nothing to do really.
3314 break;
3315 case kBuild:
3316 // Build the index then copy it
3317 if (oldtree->GetTree()->BuildIndex(newtree->GetTreeIndex()->GetMajorName(), newtree->GetTreeIndex()->GetMinorName())) {
3318 newtree->GetTreeIndex()->Append(oldtree->GetTree()->GetTreeIndex(), kTRUE);
3319 // Clean up
3320 delete oldtree->GetTree()->GetTreeIndex();
3321 oldtree->GetTree()->SetTreeIndex(0);
3322 }
3323 break;
3324 }
3325 } else {
3326 newtree->GetTreeIndex()->Append(oldtree->GetTree()->GetTreeIndex(), kTRUE);
3327 }
3328 } else if ( oldtree->GetTree()->GetTreeIndex() != 0 ) {
3329 // We discover the first index in the middle of the chain.
3330 switch (onIndexError) {
3331 case kDrop:
3332 // Nothing to do really.
3333 break;
3334 case kKeep: {
3335 TVirtualIndex *index = (TVirtualIndex*) oldtree->GetTree()->GetTreeIndex()->Clone();
3336 index->SetTree(newtree);
3337 newtree->SetTreeIndex(index);
3338 break;
3339 }
3340 case kBuild:
3341 if (newtree->GetEntries() == 0) {
3342 // Start an index.
3343 TVirtualIndex *index = (TVirtualIndex*) oldtree->GetTree()->GetTreeIndex()->Clone();
3344 index->SetTree(newtree);
3345 newtree->SetTreeIndex(index);
3346 } else {
3347 // Build the index so far.
3348 if (newtree->BuildIndex(oldtree->GetTree()->GetTreeIndex()->GetMajorName(), oldtree->GetTree()->GetTreeIndex()->GetMinorName())) {
3349 newtree->GetTreeIndex()->Append(oldtree->GetTree()->GetTreeIndex(), kTRUE);
3350 }
3351 }
3352 break;
3353 }
3354 } else if ( onIndexError == kDrop ) {
3355 // There is no index on this or on tree->GetTree(), we know we have to ignore any further
3356 // index
3357 withIndex = kFALSE;
3358 }
3359 return withIndex;
3360 }
3361}
3362
3363////////////////////////////////////////////////////////////////////////////////
3364/// Copy nentries from given tree to this tree.
3365/// This routines assumes that the branches that intended to be copied are
3366/// already connected. The typical case is that this tree was created using
3367/// tree->CloneTree(0).
3368///
3369/// By default copy all entries.
3370///
3371/// Returns number of bytes copied to this tree.
3372///
3373/// If 'option' contains the word 'fast' and nentries is -1, the cloning will be
3374/// done without unzipping or unstreaming the baskets (i.e., a direct copy of the
3375/// raw bytes on disk).
3376///
3377/// When 'fast' is specified, 'option' can also contains a sorting order for the
3378/// baskets in the output file.
3379///
3380/// There are currently 3 supported sorting order:
3381///
3382/// - SortBasketsByOffset (the default)
3383/// - SortBasketsByBranch
3384/// - SortBasketsByEntry
3385///
3386/// See TTree::CloneTree for a detailed explanation of the semantics of these 3 options.
3387///
3388/// If the tree or any of the underlying tree of the chain has an index, that index and any
3389/// index in the subsequent underlying TTree objects will be merged.
3390///
3391/// There are currently three 'options' to control this merging:
3392/// - NoIndex : all the TTreeIndex object are dropped.
3393/// - DropIndexOnError : if any of the underlying TTree object do no have a TTreeIndex,
3394/// they are all dropped.
3395/// - AsIsIndexOnError [default]: In case of missing TTreeIndex, the resulting TTree index has gaps.
3396/// - BuildIndexOnError : If any of the underlying TTree objects do not have a TTreeIndex,
3397/// all TTreeIndex are 'ignored' and the missing piece are rebuilt.
3399Long64_t TTree::CopyEntries(TTree* tree, Long64_t nentries /* = -1 */, Option_t* option /* = "" */)
3400{
3401 if (!tree) {
3402 return 0;
3403 }
3404 // Options
3405 TString opt = option;
3406 opt.ToLower();
3407 Bool_t fastClone = opt.Contains("fast");
3408 Bool_t withIndex = !opt.Contains("noindex");
3409 EOnIndexError onIndexError;
3410 if (opt.Contains("asisindex")) {
3411 onIndexError = kKeep;
3412 } else if (opt.Contains("buildindex")) {
3413 onIndexError = kBuild;
3414 } else if (opt.Contains("dropindex")) {
3415 onIndexError = kDrop;
3416 } else {
3417 onIndexError = kBuild;
3418 }
3419 Ssiz_t cacheSizeLoc = opt.Index("cachesize=");
3420 Int_t cacheSize = -1;
3421 if (cacheSizeLoc != TString::kNPOS) {
3422 // If the parse faile, cacheSize stays at -1.
3423 Ssiz_t cacheSizeEnd = opt.Index(" ",cacheSizeLoc+10) - (cacheSizeLoc+10);
3424 TSubString cacheSizeStr( opt(cacheSizeLoc+10,cacheSizeEnd) );
3425 auto parseResult = ROOT::FromHumanReadableSize(cacheSizeStr,cacheSize);
3426 if (parseResult == ROOT::EFromHumanReadableSize::kParseFail) {
3427 Warning("CopyEntries","The cachesize option can not be parsed: %s. The default size will be used.",cacheSizeStr.String().Data());
3428 } else if (parseResult == ROOT::EFromHumanReadableSize::kOverflow) {
3429 double m;
3430 const char *munit = nullptr;
3431 ROOT::ToHumanReadableSize(std::numeric_limits<decltype(cacheSize)>::max(),false,&m,&munit);
3432
3433 Warning("CopyEntries","The cachesize option is too large: %s (%g%s max). The default size will be used.",cacheSizeStr.String().Data(),m,munit);
3434 }
3435 }
3436 if (gDebug > 0 && cacheSize != -1) Info("CopyEntries","Using Cache size: %d\n",cacheSize);
3437
3438 Long64_t nbytes = 0;
3439 Long64_t treeEntries = tree->GetEntriesFast();
3440 if (nentries < 0) {
3441 nentries = treeEntries;
3442 } else if (nentries > treeEntries) {
3443 nentries = treeEntries;
3444 }
3445
3446 if (fastClone && (nentries < 0 || nentries == tree->GetEntriesFast())) {
3447 // Quickly copy the basket without decompression and streaming.
3448 Long64_t totbytes = GetTotBytes();
3449 for (Long64_t i = 0; i < nentries; i += tree->GetTree()->GetEntries()) {
3450 if (tree->LoadTree(i) < 0) {
3451 break;
3452 }
3453 if ( withIndex ) {
3454 withIndex = R__HandleIndex( onIndexError, this, tree );
3455 }
3456 if (this->GetDirectory()) {
3457 TFile* file2 = this->GetDirectory()->GetFile();
3458 if (file2 && (file2->GetEND() > TTree::GetMaxTreeSize())) {
3459 if (this->GetDirectory() == (TDirectory*) file2) {
3460 this->ChangeFile(file2);
3461 }
3462 }
3463 }
3464 TTreeCloner cloner(tree->GetTree(), this, option, TTreeCloner::kNoWarnings);
3465 if (cloner.IsValid()) {
3466 this->SetEntries(this->GetEntries() + tree->GetTree()->GetEntries());
3467 if (cacheSize != -1) cloner.SetCacheSize(cacheSize);
3468 cloner.Exec();
3469 } else {
3470 if (i == 0) {
3471 Warning("CopyEntries","%s",cloner.GetWarning());
3472 // If the first cloning does not work, something is really wrong
3473 // (since apriori the source and target are exactly the same structure!)
3474 return -1;
3475 } else {
3476 if (cloner.NeedConversion()) {
3477 TTree *localtree = tree->GetTree();
3478 Long64_t tentries = localtree->GetEntries();
3479 for (Long64_t ii = 0; ii < tentries; ii++) {
3480 if (localtree->GetEntry(ii) <= 0) {
3481 break;
3482 }
3483 this->Fill();
3484 }
3485 if (this->GetTreeIndex()) {
3486 this->GetTreeIndex()->Append(tree->GetTree()->GetTreeIndex(), kTRUE);
3487 }
3488 } else {
3489 Warning("CopyEntries","%s",cloner.GetWarning());
3490 if (tree->GetDirectory() && tree->GetDirectory()->GetFile()) {
3491 Warning("CopyEntries", "Skipped file %s\n", tree->GetDirectory()->GetFile()->GetName());
3492 } else {
3493 Warning("CopyEntries", "Skipped file number %d\n", tree->GetTreeNumber());
3494 }
3495 }
3496 }
3497 }
3498
3499 }
3500 if (this->GetTreeIndex()) {
3501 this->GetTreeIndex()->Append(0,kFALSE); // Force the sorting
3502 }
3503 nbytes = GetTotBytes() - totbytes;
3504 } else {
3505 if (nentries < 0) {
3506 nentries = treeEntries;
3507 } else if (nentries > treeEntries) {
3508 nentries = treeEntries;
3509 }
3510 Int_t treenumber = -1;
3511 for (Long64_t i = 0; i < nentries; i++) {
3512 if (tree->LoadTree(i) < 0) {
3513 break;
3514 }
3515 if (treenumber != tree->GetTreeNumber()) {
3516 if ( withIndex ) {
3517 withIndex = R__HandleIndex( onIndexError, this, tree );
3518 }
3519 treenumber = tree->GetTreeNumber();
3520 }
3521 if (tree->GetEntry(i) <= 0) {
3522 break;
3523 }
3524 nbytes += this->Fill();
3525 }
3526 if (this->GetTreeIndex()) {
3527 this->GetTreeIndex()->Append(0,kFALSE); // Force the sorting
3528 }
3529 }
3530 return nbytes;
3531}
3532
3533////////////////////////////////////////////////////////////////////////////////
3534/// Copy a tree with selection.
3535///
3536/// ### Important:
3537///
3538/// The returned copied tree stays connected with the original tree
3539/// until the original tree is deleted. In particular, any changes
3540/// to the branch addresses in the original tree are also made to
3541/// the copied tree. Any changes made to the branch addresses of the
3542/// copied tree are overridden anytime the original tree changes its
3543/// branch addresses. When the original tree is deleted, all the
3544/// branch addresses of the copied tree are set to zero.
3545///
3546/// For examples of CopyTree, see the tutorials:
3547///
3548/// - copytree.C:
3549/// Example macro to copy a subset of a tree to a new tree.
3550/// The input file was generated by running the program in
3551/// $ROOTSYS/test/Event in this way:
3552/// ~~~ {.cpp}
3553/// ./Event 1000 1 1 1
3554/// ~~~
3555/// - copytree2.C
3556/// Example macro to copy a subset of a tree to a new tree.
3557/// One branch of the new tree is written to a separate file.
3558/// The input file was generated by running the program in
3559/// $ROOTSYS/test/Event in this way:
3560/// ~~~ {.cpp}
3561/// ./Event 1000 1 1 1
3562/// ~~~
3563/// - copytree3.C
3564/// Example macro to copy a subset of a tree to a new tree.
3565/// Only selected entries are copied to the new tree.
3566/// NOTE that only the active branches are copied.
3568TTree* TTree::CopyTree(const char* selection, Option_t* option /* = 0 */, Long64_t nentries /* = TTree::kMaxEntries */, Long64_t firstentry /* = 0 */)
3569{
3570 GetPlayer();
3571 if (fPlayer) {
3572 return fPlayer->CopyTree(selection, option, nentries, firstentry);
3573 }
3574 return 0;
3575}
3576
3577////////////////////////////////////////////////////////////////////////////////
3578/// Create a basket for this tree and given branch.
3581{
3582 if (!branch) {
3583 return 0;
3584 }
3585 return new TBasket(branch->GetName(), GetName(), branch);
3586}
3587
3588////////////////////////////////////////////////////////////////////////////////
3589/// Delete this tree from memory or/and disk.
3590///
3591/// - if option == "all" delete Tree object from memory AND from disk
3592/// all baskets on disk are deleted. All keys with same name
3593/// are deleted.
3594/// - if option =="" only Tree object in memory is deleted.
3596void TTree::Delete(Option_t* option /* = "" */)
3597{
3599
3600 // delete all baskets and header from file
3601 if (file && !strcmp(option,"all")) {
3602 if (!file->IsWritable()) {
3603 Error("Delete","File : %s is not writable, cannot delete Tree:%s", file->GetName(),GetName());
3604 return;
3605 }
3606
3607 //find key and import Tree header in memory
3608 TKey *key = fDirectory->GetKey(GetName());
3609 if (!key) return;
3610
3611 TDirectory *dirsav = gDirectory;
3612 file->cd();
3613
3614 //get list of leaves and loop on all the branches baskets
3615 TIter next(GetListOfLeaves());
3616 TLeaf *leaf;
3617 char header[16];
3618 Int_t ntot = 0;
3619 Int_t nbask = 0;
3620 Int_t nbytes,objlen,keylen;
3621 while ((leaf = (TLeaf*)next())) {
3622 TBranch *branch = leaf->GetBranch();
3623 Int_t nbaskets = branch->GetMaxBaskets();
3624 for (Int_t i=0;i<nbaskets;i++) {
3625 Long64_t pos = branch->GetBasketSeek(i);
3626 if (!pos) continue;
3627 TFile *branchFile = branch->GetFile();
3628 if (!branchFile) continue;
3629 branchFile->GetRecordHeader(header,pos,16,nbytes,objlen,keylen);
3630 if (nbytes <= 0) continue;
3631 branchFile->MakeFree(pos,pos+nbytes-1);
3632 ntot += nbytes;
3633 nbask++;
3634 }
3635 }
3636
3637 // delete Tree header key and all keys with the same name
3638 // A Tree may have been saved many times. Previous cycles are invalid.
3639 while (key) {
3640 ntot += key->GetNbytes();
3641 key->Delete();
3642 delete key;
3643 key = fDirectory->GetKey(GetName());
3644 }
3645 if (dirsav) dirsav->cd();
3646 if (gDebug) Info("TTree::Delete", "Deleting Tree: %s: %d baskets deleted. Total space freed = %d bytes\n",GetName(),nbask,ntot);
3647 }
3648
3649 if (fDirectory) {
3650 fDirectory->Remove(this);
3651 //delete the file cache if it points to this Tree
3653 fDirectory = 0;
3655 }
3656
3657 // Delete object from CINT symbol table so it can not be used anymore.
3658 gCling->DeleteGlobal(this);
3659
3660 // Warning: We have intentional invalidated this object while inside a member function!
3661 delete this;
3662}
3663
3664 ///////////////////////////////////////////////////////////////////////////////
3665 /// Called by TKey and TObject::Clone to automatically add us to a directory
3666 /// when we are read from a file.
3669{
3670 if (fDirectory == dir) return;
3671 if (fDirectory) {
3672 fDirectory->Remove(this);
3673 // Delete or move the file cache if it points to this Tree
3675 MoveReadCache(file,dir);
3676 }
3677 fDirectory = dir;
3678 TBranch* b = 0;
3679 TIter next(GetListOfBranches());
3680 while((b = (TBranch*) next())) {
3681 b->UpdateFile();
3682 }
3683 if (fBranchRef) {
3685 }
3686 if (fDirectory) fDirectory->Append(this);
3687}
3688
3689////////////////////////////////////////////////////////////////////////////////
3690/// Draw expression varexp for specified entries.
3691///
3692/// \return -1 in case of error or number of selected events in case of success.
3693///
3694/// This function accepts TCut objects as arguments.
3695/// Useful to use the string operator +
3696///
3697/// Example:
3698///
3699/// ~~~ {.cpp}
3700/// ntuple.Draw("x",cut1+cut2+cut3);
3701/// ~~~
3702
3704Long64_t TTree::Draw(const char* varexp, const TCut& selection, Option_t* option, Long64_t nentries, Long64_t firstentry)
3705{
3706 return TTree::Draw(varexp, selection.GetTitle(), option, nentries, firstentry);
3707}
3708
3709////////////////////////////////////////////////////////////////////////////////
3710/// Draw expression varexp for specified entries.
3711///
3712/// \return -1 in case of error or number of selected events in case of success.
3713///
3714/// \param [in] varexp is an expression of the general form
3715/// - "e1" produces a 1-d histogram (TH1F) of expression "e1"
3716/// - "e1:e2" produces an unbinned 2-d scatter-plot (TGraph) of "e1"
3717/// on the y-axis versus "e2" on the x-axis
3718/// - "e1:e2:e3" produces an unbinned 3-d scatter-plot (TPolyMarker3D) of "e1"
3719/// vs "e2" vs "e3" on the x-, y-, z-axis, respectively.
3720/// - "e1:e2:e3:e4" produces an unbinned 3-d scatter-plot (TPolyMarker3D) of "e1"
3721/// vs "e2" vs "e3" and "e4" mapped on the current color palette.
3722/// (to create histograms in the 2, 3, and 4 dimensional case,
3723/// see section "Saving the result of Draw to an histogram")
3724///
3725/// Example:
3726/// - varexp = x simplest case: draw a 1-Dim distribution of column named x
3727/// - varexp = sqrt(x) : draw distribution of sqrt(x)
3728/// - varexp = x*y/z
3729/// - varexp = y:sqrt(x) 2-Dim distribution of y versus sqrt(x)
3730/// - varexp = px:py:pz:2.5*E produces a 3-d scatter-plot of px vs py ps pz
3731/// and the color number of each marker will be 2.5*E.
3732/// If the color number is negative it is set to 0.
3733/// If the color number is greater than the current number of colors
3734/// it is set to the highest color number.The default number of
3735/// colors is 50. see TStyle::SetPalette for setting a new color palette.
3736///
3737/// Note that the variables e1, e2 or e3 may contain a selection.
3738/// example, if e1= x*(y<0), the value histogrammed will be x if y<0
3739/// and will be 0 otherwise.
3740///
3741/// The expressions can use all the operations and build-in functions
3742/// supported by TFormula (See TFormula::Analyze), including free
3743/// standing function taking numerical arguments (TMath::Bessel).
3744/// In addition, you can call member functions taking numerical
3745/// arguments. For example:
3746/// ~~~ {.cpp}
3747/// TMath::BreitWigner(fPx,3,2)
3748/// event.GetHistogram().GetXaxis().GetXmax()
3749/// ~~~
3750/// Note: You can only pass expression that depend on the TTree's data
3751/// to static functions and you can only call non-static member function
3752/// with 'fixed' parameters.
3753///
3754/// \param [in] selection is an expression with a combination of the columns.
3755/// In a selection all the C++ operators are authorized.
3756/// The value corresponding to the selection expression is used as a weight
3757/// to fill the histogram.
3758/// If the expression includes only boolean operations, the result
3759/// is 0 or 1. If the result is 0, the histogram is not filled.
3760/// In general, the expression may be of the form:
3761/// ~~~ {.cpp}
3762/// value*(boolean expression)
3763/// ~~~
3764/// if boolean expression is true, the histogram is filled with
3765/// a `weight = value`.
3766/// Examples:
3767/// - selection1 = "x<y && sqrt(z)>3.2"
3768/// - selection2 = "(x+y)*(sqrt(z)>3.2)"
3769/// - selection1 returns a weight = 0 or 1
3770/// - selection2 returns a weight = x+y if sqrt(z)>3.2
3771/// returns a weight = 0 otherwise.
3772///
3773/// \param [in] option is the drawing option.
3774/// - When an histogram is produced it can be any histogram drawing option
3775/// listed in THistPainter.
3776/// - when no option is specified:
3777/// - the default histogram drawing option is used
3778/// if the expression is of the form "e1".
3779/// - if the expression is of the form "e1:e2"or "e1:e2:e3" a cloud of
3780/// unbinned 2D or 3D points is drawn respectively.
3781/// - if the expression has four fields "e1:e2:e3:e4" a 2D scatter is
3782/// produced with e1 vs e2 vs e3, and e4 is mapped on the current color
3783/// palette.
3784/// - If option COL is specified when varexp has three fields:
3785/// ~~~ {.cpp}
3786/// tree.Draw("e1:e2:e3","","col");
3787/// ~~~
3788/// a 2D scatter is produced with e1 vs e2, and e3 is mapped on the current
3789/// color palette. The colors for e3 are evaluated once in linear scale before
3790/// painting. Therefore changing the pad to log scale along Z as no effect
3791/// on the colors.
3792/// - if expression has more than four fields the option "PARA"or "CANDLE"
3793/// can be used.
3794/// - If option contains the string "goff", no graphics is generated.
3795///
3796/// \param [in] nentries is the number of entries to process (default is all)
3797///
3798/// \param [in] firstentry is the first entry to process (default is 0)
3799///
3800/// ### Drawing expressions using arrays and array elements
3801///
3802/// Let assumes, a leaf fMatrix, on the branch fEvent, which is a 3 by 3 array,
3803/// or a TClonesArray.
3804/// In a TTree::Draw expression you can now access fMatrix using the following
3805/// syntaxes:
3806///
3807/// | String passed | What is used for each entry of the tree
3808/// |-----------------|--------------------------------------------------------|
3809/// | `fMatrix` | the 9 elements of fMatrix |
3810/// | `fMatrix[][]` | the 9 elements of fMatrix |
3811/// | `fMatrix[2][2]` | only the elements fMatrix[2][2] |
3812/// | `fMatrix[1]` | the 3 elements fMatrix[1][0], fMatrix[1][1] and fMatrix[1][2] |
3813/// | `fMatrix[1][]` | the 3 elements fMatrix[1][0], fMatrix[1][1] and fMatrix[1][2] |
3814/// | `fMatrix[][0]` | the 3 elements fMatrix[0][0], fMatrix[1][0] and fMatrix[2][0] |
3815///
3816/// "fEvent.fMatrix...." same as "fMatrix..." (unless there is more than one leaf named fMatrix!).
3817///
3818/// In summary, if a specific index is not specified for a dimension, TTree::Draw
3819/// will loop through all the indices along this dimension. Leaving off the
3820/// last (right most) dimension of specifying then with the two characters '[]'
3821/// is equivalent. For variable size arrays (and TClonesArray) the range
3822/// of the first dimension is recalculated for each entry of the tree.
3823/// You can also specify the index as an expression of any other variables from the
3824/// tree.
3825///
3826/// TTree::Draw also now properly handling operations involving 2 or more arrays.
3827///
3828/// Let assume a second matrix fResults[5][2], here are a sample of some
3829/// of the possible combinations, the number of elements they produce and
3830/// the loop used:
3831///
3832/// | expression | element(s) | Loop |
3833/// |----------------------------------|------------|--------------------------|
3834/// | `fMatrix[2][1] - fResults[5][2]` | one | no loop |
3835/// | `fMatrix[2][] - fResults[5][2]` | three | on 2nd dim fMatrix |
3836/// | `fMatrix[2][] - fResults[5][]` | two | on both 2nd dimensions |
3837/// | `fMatrix[][2] - fResults[][1]` | three | on both 1st dimensions |
3838/// | `fMatrix[][2] - fResults[][]` | six | on both 1st and 2nd dimensions of fResults |
3839/// | `fMatrix[][2] - fResults[3][]` | two | on 1st dim of fMatrix and 2nd of fResults (at the same time) |
3840/// | `fMatrix[][] - fResults[][]` | six | on 1st dim then on 2nd dim |
3841/// | `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.|
3842///
3843///
3844/// In summary, TTree::Draw loops through all unspecified dimensions. To
3845/// figure out the range of each loop, we match each unspecified dimension
3846/// from left to right (ignoring ALL dimensions for which an index has been
3847/// specified), in the equivalent loop matched dimensions use the same index
3848/// and are restricted to the smallest range (of only the matched dimensions).
3849/// When involving variable arrays, the range can of course be different
3850/// for each entry of the tree.
3851///
3852/// So the loop equivalent to "fMatrix[][2] - fResults[3][]" is:
3853/// ~~~ {.cpp}
3854/// for (Int_t i0; i < min(3,2); i++) {
3855/// use the value of (fMatrix[i0][2] - fMatrix[3][i0])
3856/// }
3857/// ~~~
3858/// So the loop equivalent to "fMatrix[][2] - fResults[][]" is:
3859/// ~~~ {.cpp}
3860/// for (Int_t i0; i < min(3,5); i++) {
3861/// for (Int_t i1; i1 < 2; i1++) {
3862/// use the value of (fMatrix[i0][2] - fMatrix[i0][i1])
3863/// }
3864/// }
3865/// ~~~
3866/// So the loop equivalent to "fMatrix[][] - fResults[][]" is:
3867/// ~~~ {.cpp}
3868/// for (Int_t i0; i < min(3,5); i++) {
3869/// for (Int_t i1; i1 < min(3,2); i1++) {
3870/// use the value of (fMatrix[i0][i1] - fMatrix[i0][i1])
3871/// }
3872/// }
3873/// ~~~
3874/// So the loop equivalent to "fMatrix[][fResults[][]]" is:
3875/// ~~~ {.cpp}
3876/// for (Int_t i0; i0 < 3; i0++) {
3877/// for (Int_t j2; j2 < 5; j2++) {
3878/// for (Int_t j3; j3 < 2; j3++) {
3879/// i1 = fResults[j2][j3];
3880/// use the value of fMatrix[i0][i1]
3881/// }
3882/// }
3883/// ~~~
3884/// ### Retrieving the result of Draw
3885///
3886/// By default the temporary histogram created is called "htemp", but only in
3887/// the one dimensional Draw("e1") it contains the TTree's data points. For
3888/// a two dimensional Draw, the data is filled into a TGraph which is named
3889/// "Graph". They can be retrieved by calling
3890/// ~~~ {.cpp}
3891/// TH1F *htemp = (TH1F*)gPad->GetPrimitive("htemp"); // 1D
3892/// TGraph *graph = (TGraph*)gPad->GetPrimitive("Graph"); // 2D
3893/// ~~~
3894/// For a three and four dimensional Draw the TPolyMarker3D is unnamed, and
3895/// cannot be retrieved.
3896///
3897/// gPad always contains a TH1 derived object called "htemp" which allows to
3898/// access the axes:
3899/// ~~~ {.cpp}
3900/// TGraph *graph = (TGraph*)gPad->GetPrimitive("Graph"); // 2D
3901/// TH2F *htemp = (TH2F*)gPad->GetPrimitive("htemp"); // empty, but has axes
3902/// TAxis *xaxis = htemp->GetXaxis();
3903/// ~~~
3904/// ### Saving the result of Draw to an histogram
3905///
3906/// If varexp0 contains >>hnew (following the variable(s) name(s),
3907/// the new histogram created is called hnew and it is kept in the current
3908/// directory (and also the current pad). This works for all dimensions.
3909///
3910/// Example:
3911/// ~~~ {.cpp}
3912/// tree.Draw("sqrt(x)>>hsqrt","y>0")
3913/// ~~~
3914/// will draw `sqrt(x)` and save the histogram as "hsqrt" in the current
3915/// directory. To retrieve it do:
3916/// ~~~ {.cpp}
3917/// TH1F *hsqrt = (TH1F*)gDirectory->Get("hsqrt");
3918/// ~~~
3919/// The binning information is taken from the environment variables
3920/// ~~~ {.cpp}
3921/// Hist.Binning.?D.?
3922/// ~~~
3923/// In addition, the name of the histogram can be followed by up to 9
3924/// numbers between '(' and ')', where the numbers describe the
3925/// following:
3926///
3927/// - 1 - bins in x-direction
3928/// - 2 - lower limit in x-direction
3929/// - 3 - upper limit in x-direction
3930/// - 4-6 same for y-direction
3931/// - 7-9 same for z-direction
3932///
3933/// When a new binning is used the new value will become the default.
3934/// Values can be skipped.
3935///
3936/// Example:
3937/// ~~~ {.cpp}
3938/// tree.Draw("sqrt(x)>>hsqrt(500,10,20)")
3939/// // plot sqrt(x) between 10 and 20 using 500 bins
3940/// tree.Draw("sqrt(x):sin(y)>>hsqrt(100,10,60,50,.1,.5)")
3941/// // plot sqrt(x) against sin(y)
3942/// // 100 bins in x-direction; lower limit on x-axis is 10; upper limit is 60
3943/// // 50 bins in y-direction; lower limit on y-axis is .1; upper limit is .5
3944/// ~~~
3945/// By default, the specified histogram is reset.
3946/// To continue to append data to an existing histogram, use "+" in front
3947/// of the histogram name.
3948///
3949/// A '+' in front of the histogram name is ignored, when the name is followed by
3950/// binning information as described in the previous paragraph.
3951/// ~~~ {.cpp}
3952/// tree.Draw("sqrt(x)>>+hsqrt","y>0")
3953/// ~~~
3954/// will not reset `hsqrt`, but will continue filling. This works for 1-D, 2-D
3955/// and 3-D histograms.
3956///
3957/// ### Accessing collection objects
3958///
3959/// TTree::Draw default's handling of collections is to assume that any
3960/// request on a collection pertain to it content. For example, if fTracks
3961/// is a collection of Track objects, the following:
3962/// ~~~ {.cpp}
3963/// tree->Draw("event.fTracks.fPx");
3964/// ~~~
3965/// will plot the value of fPx for each Track objects inside the collection.
3966/// Also
3967/// ~~~ {.cpp}
3968/// tree->Draw("event.fTracks.size()");
3969/// ~~~
3970/// would plot the result of the member function Track::size() for each
3971/// Track object inside the collection.
3972/// To access information about the collection itself, TTree::Draw support
3973/// the '@' notation. If a variable which points to a collection is prefixed
3974/// or postfixed with '@', the next part of the expression will pertain to
3975/// the collection object. For example:
3976/// ~~~ {.cpp}
3977/// tree->Draw("event.@fTracks.size()");
3978/// ~~~
3979/// will plot the size of the collection referred to by `fTracks` (i.e the number
3980/// of Track objects).
3981///
3982/// ### Drawing 'objects'
3983///
3984/// When a class has a member function named AsDouble or AsString, requesting
3985/// to directly draw the object will imply a call to one of the 2 functions.
3986/// If both AsDouble and AsString are present, AsDouble will be used.
3987/// AsString can return either a char*, a std::string or a TString.s
3988/// For example, the following
3989/// ~~~ {.cpp}
3990/// tree->Draw("event.myTTimeStamp");
3991/// ~~~
3992/// will draw the same histogram as
3993/// ~~~ {.cpp}
3994/// tree->Draw("event.myTTimeStamp.AsDouble()");
3995/// ~~~
3996/// In addition, when the object is a type TString or std::string, TTree::Draw
3997/// will call respectively `TString::Data` and `std::string::c_str()`
3998///
3999/// If the object is a TBits, the histogram will contain the index of the bit
4000/// that are turned on.
4001///
4002/// ### Retrieving information about the tree itself.
4003///
4004/// You can refer to the tree (or chain) containing the data by using the
4005/// string 'This'.
4006/// You can then could any TTree methods. For example:
4007/// ~~~ {.cpp}
4008/// tree->Draw("This->GetReadEntry()");
4009/// ~~~
4010/// will display the local entry numbers be read.
4011/// ~~~ {.cpp}
4012/// tree->Draw("This->GetUserInfo()->At(0)->GetName()");
4013/// ~~~
4014/// will display the name of the first 'user info' object.
4015///
4016/// ### Special functions and variables
4017///
4018/// `Entry$`: A TTree::Draw formula can use the special variable `Entry$`
4019/// to access the entry number being read. For example to draw every
4020/// other entry use:
4021/// ~~~ {.cpp}
4022/// tree.Draw("myvar","Entry$%2==0");
4023/// ~~~
4024/// - `Entry$` : return the current entry number (`== TTree::GetReadEntry()`)
4025/// - `LocalEntry$` : return the current entry number in the current tree of a
4026/// chain (`== GetTree()->GetReadEntry()`)
4027/// - `Entries$` : return the total number of entries (== TTree::GetEntries())
4028/// - `LocalEntries$` : return the total number of entries in the current tree
4029/// of a chain (== GetTree()->TTree::GetEntries())
4030/// - `Length$` : return the total number of element of this formula for this
4031/// entry (`==TTreeFormula::GetNdata()`)
4032/// - `Iteration$` : return the current iteration over this formula for this
4033/// entry (i.e. varies from 0 to `Length$`).
4034/// - `Length$(formula )` : return the total number of element of the formula
4035/// given as a parameter.
4036/// - `Sum$(formula )` : return the sum of the value of the elements of the
4037/// formula given as a parameter. For example the mean for all the elements in
4038/// one entry can be calculated with: `Sum$(formula )/Length$(formula )`
4039/// - `Min$(formula )` : return the minimun (within one TTree entry) of the value of the
4040/// elements of the formula given as a parameter.
4041/// - `Max$(formula )` : return the maximum (within one TTree entry) of the value of the
4042/// elements of the formula given as a parameter.
4043/// - `MinIf$(formula,condition)`
4044/// - `MaxIf$(formula,condition)` : return the minimum (maximum) (within one TTree entry)
4045/// of the value of the elements of the formula given as a parameter
4046/// if they match the condition. If no element matches the condition,
4047/// the result is zero. To avoid the resulting peak at zero, use the
4048/// pattern:
4049/// ~~~ {.cpp}
4050/// tree->Draw("MinIf$(formula,condition)","condition");
4051/// ~~~
4052/// which will avoid calculation `MinIf$` for the entries that have no match
4053/// for the condition.
4054/// - `Alt$(primary,alternate)` : return the value of "primary" if it is available
4055/// for the current iteration otherwise return the value of "alternate".
4056/// For example, with arr1[3] and arr2[2]
4057/// ~~~ {.cpp}
4058/// tree->Draw("arr1+Alt$(arr2,0)");
4059/// ~~~
4060/// will draw arr1[0]+arr2[0] ; arr1[1]+arr2[1] and arr1[2]+0
4061/// Or with a variable size array arr3
4062/// ~~~ {.cpp}
4063/// tree->Draw("Alt$(arr3[0],0)+Alt$(arr3[1],0)+Alt$(arr3[2],0)");
4064/// ~~~
4065/// will draw the sum arr3 for the index 0 to min(2,actual_size_of_arr3-1)
4066/// As a comparison
4067/// ~~~ {.cpp}
4068/// tree->Draw("arr3[0]+arr3[1]+arr3[2]");
4069/// ~~~
4070/// will draw the sum arr3 for the index 0 to 2 only if the
4071/// actual_size_of_arr3 is greater or equal to 3.
4072/// Note that the array in 'primary' is flattened/linearized thus using
4073/// `Alt$` with multi-dimensional arrays of different dimensions in unlikely
4074/// to yield the expected results. To visualize a bit more what elements
4075/// would be matched by TTree::Draw, TTree::Scan can be used:
4076/// ~~~ {.cpp}
4077/// tree->Scan("arr1:Alt$(arr2,0)");
4078/// ~~~
4079/// will print on one line the value of arr1 and (arr2,0) that will be
4080/// matched by
4081/// ~~~ {.cpp}
4082/// tree->Draw("arr1-Alt$(arr2,0)");
4083/// ~~~
4084/// The ternary operator is not directly supported in TTree::Draw however, to plot the
4085/// equivalent of `var2<20 ? -99 : var1`, you can use:
4086/// ~~~ {.cpp}
4087/// tree->Draw("(var2<20)*99+(var2>=20)*var1","");
4088/// ~~~
4089///
4090/// ### Drawing a user function accessing the TTree data directly
4091///
4092/// If the formula contains a file name, TTree::MakeProxy will be used
4093/// to load and execute this file. In particular it will draw the
4094/// result of a function with the same name as the file. The function
4095/// will be executed in a context where the name of the branches can
4096/// be used as a C++ variable.
4097///
4098/// For example draw px using the file hsimple.root (generated by the
4099/// hsimple.C tutorial), we need a file named hsimple.cxx:
4100/// ~~~ {.cpp}
4101/// double hsimple() {
4102/// return px;
4103/// }
4104/// ~~~
4105/// MakeProxy can then be used indirectly via the TTree::Draw interface
4106/// as follow:
4107/// ~~~ {.cpp}
4108/// new TFile("hsimple.root")
4109/// ntuple->Draw("hsimple.cxx");
4110/// ~~~
4111/// A more complete example is available in the tutorials directory:
4112/// `h1analysisProxy.cxx`, `h1analysProxy.h` and `h1analysisProxyCut.C`
4113/// which reimplement the selector found in `h1analysis.C`
4114///
4115/// The main features of this facility are:
4116///
4117/// * on-demand loading of branches
4118/// * ability to use the 'branchname' as if it was a data member
4119/// * protection against array out-of-bound
4120/// * ability to use the branch data as object (when the user code is available)
4121///
4122/// See TTree::MakeProxy for more details.
4123///
4124/// ### Making a Profile histogram
4125///
4126/// In case of a 2-Dim expression, one can generate a TProfile histogram
4127/// instead of a TH2F histogram by specifying option=prof or option=profs
4128/// or option=profi or option=profg ; the trailing letter select the way
4129/// the bin error are computed, See TProfile2D::SetErrorOption for
4130/// details on the differences.
4131/// The option=prof is automatically selected in case of y:x>>pf
4132/// where pf is an existing TProfile histogram.
4133///
4134/// ### Making a 2D Profile histogram
4135///
4136/// In case of a 3-Dim expression, one can generate a TProfile2D histogram
4137/// instead of a TH3F histogram by specifying option=prof or option=profs.
4138/// or option=profi or option=profg ; the trailing letter select the way
4139/// the bin error are computed, See TProfile2D::SetErrorOption for
4140/// details on the differences.
4141/// The option=prof is automatically selected in case of z:y:x>>pf
4142/// where pf is an existing TProfile2D histogram.
4143///
4144/// ### Making a 5D plot using GL
4145///
4146/// If option GL5D is specified together with 5 variables, a 5D plot is drawn
4147/// using OpenGL. See $ROOTSYS/tutorials/tree/staff.C as example.
4148///
4149/// ### Making a parallel coordinates plot
4150///
4151/// In case of a 2-Dim or more expression with the option=para, one can generate
4152/// a parallel coordinates plot. With that option, the number of dimensions is
4153/// arbitrary. Giving more than 4 variables without the option=para or
4154/// option=candle or option=goff will produce an error.
4155///
4156/// ### Making a candle sticks chart
4157///
4158/// In case of a 2-Dim or more expression with the option=candle, one can generate
4159/// a candle sticks chart. With that option, the number of dimensions is
4160/// arbitrary. Giving more than 4 variables without the option=para or
4161/// option=candle or option=goff will produce an error.
4162///
4163/// ### Normalizing the output histogram to 1
4164///
4165/// When option contains "norm" the output histogram is normalized to 1.
4166///
4167/// ### Saving the result of Draw to a TEventList, a TEntryList or a TEntryListArray
4168///
4169/// TTree::Draw can be used to fill a TEventList object (list of entry numbers)
4170/// instead of histogramming one variable.
4171/// If varexp0 has the form >>elist , a TEventList object named "elist"
4172/// is created in the current directory. elist will contain the list
4173/// of entry numbers satisfying the current selection.
4174/// If option "entrylist" is used, a TEntryList object is created
4175/// If the selection contains arrays, vectors or any container class and option
4176/// "entrylistarray" is used, a TEntryListArray object is created
4177/// containing also the subentries satisfying the selection, i.e. the indices of
4178/// the branches which hold containers classes.
4179/// Example:
4180/// ~~~ {.cpp}
4181/// tree.Draw(">>yplus","y>0")
4182/// ~~~
4183/// will create a TEventList object named "yplus" in the current directory.
4184/// In an interactive session, one can type (after TTree::Draw)
4185/// ~~~ {.cpp}
4186/// yplus.Print("all")
4187/// ~~~
4188/// to print the list of entry numbers in the list.
4189/// ~~~ {.cpp}
4190/// tree.Draw(">>yplus", "y>0", "entrylist")
4191/// ~~~
4192/// will create a TEntryList object names "yplus" in the current directory
4193/// ~~~ {.cpp}
4194/// tree.Draw(">>yplus", "y>0", "entrylistarray")
4195/// ~~~
4196/// will create a TEntryListArray object names "yplus" in the current directory
4197///
4198/// By default, the specified entry list is reset.
4199/// To continue to append data to an existing list, use "+" in front
4200/// of the list name;
4201/// ~~~ {.cpp}
4202/// tree.Draw(">>+yplus","y>0")
4203/// ~~~
4204/// will not reset yplus, but will enter the selected entries at the end
4205/// of the existing list.
4206///
4207/// ### Using a TEventList, TEntryList or TEntryListArray as Input
4208///
4209/// Once a TEventList or a TEntryList object has been generated, it can be used as input
4210/// for TTree::Draw. Use TTree::SetEventList or TTree::SetEntryList to set the
4211/// current event list
4212///
4213/// Example 1:
4214/// ~~~ {.cpp}
4215/// TEventList *elist = (TEventList*)gDirectory->Get("yplus");
4216/// tree->SetEventList(elist);
4217/// tree->Draw("py");
4218/// ~~~
4219/// Example 2:
4220/// ~~~ {.cpp}
4221/// TEntryList *elist = (TEntryList*)gDirectory->Get("yplus");
4222/// tree->SetEntryList(elist);
4223/// tree->Draw("py");
4224/// ~~~
4225/// If a TEventList object is used as input, a new TEntryList object is created
4226/// inside the SetEventList function. In case of a TChain, all tree headers are loaded
4227/// for this transformation. This new object is owned by the chain and is deleted
4228/// with it, unless the user extracts it by calling GetEntryList() function.
4229/// See also comments to SetEventList() function of TTree and TChain.
4230///
4231/// If arrays are used in the selection criteria and TEntryListArray is not used,
4232/// all the entries that have at least one element of the array that satisfy the selection
4233/// are entered in the list.
4234///
4235/// Example:
4236/// ~~~ {.cpp}
4237/// tree.Draw(">>pyplus","fTracks.fPy>0");
4238/// tree->SetEventList(pyplus);
4239/// tree->Draw("fTracks.fPy");
4240/// ~~~
4241/// will draw the fPy of ALL tracks in event with at least one track with
4242/// a positive fPy.
4243///
4244/// To select only the elements that did match the original selection
4245/// use TEventList::SetReapplyCut or TEntryList::SetReapplyCut.
4246///
4247/// Example:
4248/// ~~~ {.cpp}
4249/// tree.Draw(">>pyplus","fTracks.fPy>0");
4250/// pyplus->SetReapplyCut(kTRUE);
4251/// tree->SetEventList(pyplus);
4252/// tree->Draw("fTracks.fPy");
4253/// ~~~
4254/// will draw the fPy of only the tracks that have a positive fPy.
4255///
4256/// To draw only the elements that match a selection in case of arrays,
4257/// you can also use TEntryListArray (faster in case of a more general selection).
4258///
4259/// Example:
4260/// ~~~ {.cpp}
4261/// tree.Draw(">>pyplus","fTracks.fPy>0", "entrylistarray");
4262/// tree->SetEntryList(pyplus);
4263/// tree->Draw("fTracks.fPy");
4264/// ~~~
4265/// will draw the fPy of only the tracks that have a positive fPy,
4266/// but without redoing the selection.
4267///
4268/// Note: Use tree->SetEventList(0) if you do not want use the list as input.
4269///
4270/// ### How to obtain more info from TTree::Draw
4271///
4272/// Once TTree::Draw has been called, it is possible to access useful
4273/// information still stored in the TTree object via the following functions:
4274///
4275/// - GetSelectedRows() // return the number of values accepted by the selection expression. In case where no selection was specified, returns the number of values processed.
4276/// - GetV1() // returns a pointer to the double array of V1
4277/// - GetV2() // returns a pointer to the double array of V2
4278/// - GetV3() // returns a pointer to the double array of V3
4279/// - GetV4() // returns a pointer to the double array of V4
4280/// - GetW() // returns a pointer to the double array of Weights where weight equal the result of the selection expression.
4281///
4282/// where V1,V2,V3 correspond to the expressions in
4283/// ~~~ {.cpp}
4284/// TTree::Draw("V1:V2:V3:V4",selection);
4285/// ~~~
4286/// If the expression has more than 4 component use GetVal(index)
4287///
4288/// Example:
4289/// ~~~ {.cpp}
4290/// Root > ntuple->Draw("py:px","pz>4");
4291/// Root > TGraph *gr = new TGraph(ntuple->GetSelectedRows(),
4292/// ntuple->GetV2(), ntuple->GetV1());
4293/// Root > gr->Draw("ap"); //draw graph in current pad
4294/// ~~~
4295///
4296/// A more complete complete tutorial (treegetval.C) shows how to use the
4297/// GetVal() method.
4298///
4299/// creates a TGraph object with a number of points corresponding to the
4300/// number of entries selected by the expression "pz>4", the x points of the graph
4301/// being the px values of the Tree and the y points the py values.
4302///
4303/// Important note: By default TTree::Draw creates the arrays obtained
4304/// with GetW, GetV1, GetV2, GetV3, GetV4, GetVal with a length corresponding
4305/// to the parameter fEstimate. The content will be the last `GetSelectedRows() % GetEstimate()`
4306/// values calculated.
4307/// By default fEstimate=1000000 and can be modified
4308/// via TTree::SetEstimate. To keep in memory all the results (in case
4309/// where there is only one result per entry), use
4310/// ~~~ {.cpp}
4311/// tree->SetEstimate(tree->GetEntries()+1); // same as tree->SetEstimate(-1);
4312/// ~~~
4313/// You must call SetEstimate if the expected number of selected rows
4314/// you need to look at is greater than 1000000.
4315///
4316/// You can use the option "goff" to turn off the graphics output
4317/// of TTree::Draw in the above example.
4318///
4319/// ### Automatic interface to TTree::Draw via the TTreeViewer
4320///
4321/// A complete graphical interface to this function is implemented
4322/// in the class TTreeViewer.
4323/// To start the TTreeViewer, three possibilities:
4324/// - select TTree context menu item "StartViewer"
4325/// - type the command "TTreeViewer TV(treeName)"
4326/// - execute statement "tree->StartViewer();"
4328Long64_t TTree::Draw(const char* varexp, const char* selection, Option_t* option, Long64_t nentries, Long64_t firstentry)
4329{
4330 GetPlayer();
4331 if (fPlayer)
4332 return fPlayer->DrawSelect(varexp,selection,option,nentries,firstentry);
4333 return -1;
4334}
4335
4336////////////////////////////////////////////////////////////////////////////////
4337/// Remove some baskets from memory.
4339void TTree::DropBaskets()
4340{
4341 TBranch* branch = 0;
4343 for (Int_t i = 0; i < nb; ++i) {
4344 branch = (TBranch*) fBranches.UncheckedAt(i);
4345 branch->DropBaskets("all");
4346 }
4347}
4348
4349////////////////////////////////////////////////////////////////////////////////
4350/// Drop branch buffers to accommodate nbytes below MaxVirtualsize.
4353{
4354 // Be careful not to remove current read/write buffers.
4355 Int_t ndrop = 0;
4356 Int_t nleaves = fLeaves.GetEntriesFast();
4357 for (Int_t i = 0; i < nleaves; ++i) {
4358 TLeaf* leaf = (TLeaf*) fLeaves.UncheckedAt(i);
4359 TBranch* branch = (TBranch*) leaf->GetBranch();
4360 Int_t nbaskets = branch->GetListOfBaskets()->GetEntries();
4361 for (Int_t j = 0; j < nbaskets - 1; ++j) {
4362 if ((j == branch->GetReadBasket()) || (j == branch->GetWriteBasket())) {
4363 continue;
4364 }
4365 TBasket* basket = (TBasket*)branch->GetListOfBaskets()->UncheckedAt(j);
4366 if (basket) {
4367 ndrop += basket->DropBuffers();
4369 return;
4370 }
4371 }
4372 }
4373 }
4374}
4375
4376////////////////////////////////////////////////////////////////////////////////
4377/// Fill all branches.
4378///
4379/// This function loops on all the branches of this tree. For
4380/// each branch, it copies to the branch buffer (basket) the current
4381/// values of the leaves data types. If a leaf is a simple data type,
4382/// a simple conversion to a machine independent format has to be done.
4383///
4384/// This machine independent version of the data is copied into a
4385/// basket (each branch has its own basket). When a basket is full
4386/// (32k worth of data by default), it is then optionally compressed
4387/// and written to disk (this operation is also called committing or
4388/// 'flushing' the basket). The committed baskets are then
4389/// immediately removed from memory.
4390///
4391/// The function returns the number of bytes committed to the
4392/// individual branches.
4393///
4394/// If a write error occurs, the number of bytes returned is -1.
4395///
4396/// If no data are written, because, e.g., the branch is disabled,
4397/// the number of bytes returned is 0.
4398///
4399/// __The baskets are flushed and the Tree header saved at regular intervals__
4400///
4401/// At regular intervals, when the amount of data written so far is
4402/// greater than fAutoFlush (see SetAutoFlush) all the baskets are flushed to disk.
4403/// This makes future reading faster as it guarantees that baskets belonging to nearby
4404/// entries will be on the same disk region.
4405/// When the first call to flush the baskets happen, we also take this opportunity
4406/// to optimize the baskets buffers.
4407/// We also check if the amount of data written is greater than fAutoSave (see SetAutoSave).
4408/// In this case we also write the Tree header. This makes the Tree recoverable up to this point
4409/// in case the program writing the Tree crashes.
4410/// The decisions to FlushBaskets and Auto Save can be made based either on the number
4411/// of bytes written (fAutoFlush and fAutoSave negative) or on the number of entries
4412/// written (fAutoFlush and fAutoSave positive).
4413/// Note that the user can decide to call FlushBaskets and AutoSave in her event loop
4414/// base on the number of events written instead of the number of bytes written.
4415///
4416/// Note that calling FlushBaskets too often increases the IO time.
4417///
4418/// Note that calling AutoSave too often increases the IO time and also the file size.
4421{
4422 Int_t nbytes = 0;
4423 Int_t nwrite = 0;
4424 Int_t nerror = 0;
4425 Int_t nbranches = fBranches.GetEntriesFast();
4426
4427 // Case of one single super branch. Automatically update
4428 // all the branch addresses if a new object was created.
4429 if (nbranches == 1)
4430 ((TBranch *)fBranches.UncheckedAt(0))->UpdateAddress();
4431
4432 if (fBranchRef)
4433 fBranchRef->Clear();
4434
4435#ifdef R__USE_IMT
4436 const auto useIMT = ROOT::IsImplicitMTEnabled() && fIMTEnabled;
4438 if (useIMT) {
4439 fIMTFlush = true;
4440 fIMTZipBytes.store(0);
4441 fIMTTotBytes.store(0);
4442 }
4443#endif
4444
4445 for (Int_t i = 0; i < nbranches; ++i) {
4446 // Loop over all branches, filling and accumulating bytes written and error counts.
4447 TBranch *branch = (TBranch *)fBranches.UncheckedAt(i);
4448
4449 if (branch->TestBit(kDoNotProcess))
4450 continue;
4451
4452#ifndef R__USE_IMT
4453 nwrite = branch->FillImpl(nullptr);
4454#else
4455 nwrite = branch->FillImpl(useIMT ? &imtHelper : nullptr);
4456#endif
4457 if (nwrite < 0) {
4458 if (nerror < 2) {
4459 Error("Fill", "Failed filling branch:%s.%s, nbytes=%d, entry=%lld\n"
4460 " This error is symptomatic of a Tree created as a memory-resident Tree\n"
4461 " Instead of doing:\n"
4462 " TTree *T = new TTree(...)\n"
4463 " TFile *f = new TFile(...)\n"
4464 " you should do:\n"
4465 " TFile *f = new TFile(...)\n"
4466 " TTree *T = new TTree(...)\n\n",
4467 GetName(), branch->GetName(), nwrite, fEntries + 1);
4468 } else {
4469 Error("Fill", "Failed filling branch:%s.%s, nbytes=%d, entry=%lld", GetName(), branch->GetName(), nwrite,
4470 fEntries + 1);
4471 }
4472 ++nerror;
4473 } else {
4474 nbytes += nwrite;
4475 }
4476 }
4477
4478#ifdef R__USE_IMT
4479 if (fIMTFlush) {
4480 imtHelper.Wait();
4481 fIMTFlush = false;
4482 const_cast<TTree *>(this)->AddTotBytes(fIMTTotBytes);
4483 const_cast<TTree *>(this)->AddZipBytes(fIMTZipBytes);
4484 nbytes += imtHelper.GetNbytes();
4485 nerror += imtHelper.GetNerrors();
4486 }
4487#endif
4488
4489 if (fBranchRef)
4490 fBranchRef->Fill();
4491
4492 ++fEntries;
4493
4494 if (fEntries > fMaxEntries)
4495 KeepCircular();
4496
4497 if (gDebug > 0)
4498 Info("TTree::Fill", " - A: %d %lld %lld %lld %lld %lld %lld \n", nbytes, fEntries, fAutoFlush, fAutoSave,
4500
4501 bool autoFlush = false;
4502 bool autoSave = false;
4503
4504 if (fAutoFlush != 0 || fAutoSave != 0) {
4505 // Is it time to flush or autosave baskets?
4506 if (fFlushedBytes == 0) {
4507 // If fFlushedBytes == 0, it means we never flushed or saved, so
4508 // we need to check if it's time to do it and recompute the values
4509 // of fAutoFlush and fAutoSave in terms of the number of entries.
4510 // Decision can be based initially either on the number of bytes
4511 // or the number of entries written.
4512 Long64_t zipBytes = GetZipBytes();
4513
4514 if (fAutoFlush)
4515 autoFlush = fAutoFlush < 0 ? (zipBytes > -fAutoFlush) : fEntries % fAutoFlush == 0;
4516
4517 if (fAutoSave)
4518 autoSave = fAutoSave < 0 ? (zipBytes > -fAutoSave) : fEntries % fAutoSave == 0;
4519
4520 if (autoFlush || autoSave) {
4521 // First call FlushBasket to make sure that fTotBytes is up to date.
4523 autoFlush = false; // avoid auto flushing again later
4524
4525 // When we are in one-basket-per-cluster mode, there is no need to optimize basket:
4526 // they will automatically grow to the size needed for an event cluster (with the basket
4527 // shrinking preventing them from growing too much larger than the actually-used space).
4529 OptimizeBaskets(GetTotBytes(), 1, "");
4530 if (gDebug > 0)
4531 Info("TTree::Fill", "OptimizeBaskets called at entry %lld, fZipBytes=%lld, fFlushedBytes=%lld\n",
4533 }
4535 fAutoFlush = fEntries; // Use test on entries rather than bytes
4536
4537 // subsequently in run
4538 if (fAutoSave < 0) {
4539 // Set fAutoSave to the largest integer multiple of
4540 // fAutoFlush events such that fAutoSave*fFlushedBytes
4541 // < (minus the input value of fAutoSave)
4542 Long64_t totBytes = GetTotBytes();
4543 if (zipBytes != 0) {
4544 fAutoSave = TMath::Max(fAutoFlush, fEntries * ((-fAutoSave / zipBytes) / fEntries));
4545 } else if (totBytes != 0) {
4546 fAutoSave = TMath::Max(fAutoFlush, fEntries * ((-fAutoSave / totBytes) / fEntries));
4547 } else {
4549 TTree::Class()->WriteBuffer(b, (TTree *)this);
4550 Long64_t total = b.Length();
4552 }
4553 } else if (fAutoSave > 0) {
4555 }
4556
4557 if (fAutoSave != 0 && fEntries >= fAutoSave)
4558 autoSave = true;
4559
4560 if (gDebug > 0)
4561 Info("TTree::Fill", "First AutoFlush. fAutoFlush = %lld, fAutoSave = %lld\n", fAutoFlush, fAutoSave);
4562 }
4563 } else {
4564 // Check if we need to auto flush
4565 if (fAutoFlush) {
4566 if (fNClusterRange == 0)
4567 autoFlush = fEntries > 1 && fEntries % fAutoFlush == 0;
4568 else
4569 autoFlush = (fEntries - (fClusterRangeEnd[fNClusterRange - 1] + 1)) % fAutoFlush == 0;
4570 }
4571 // Check if we need to auto save
4572 if (fAutoSave)
4573 autoSave = fEntries % fAutoSave == 0;
4574 }
4575 }
4576
4577 if (autoFlush) {
4579 if (gDebug > 0)
4580 Info("TTree::Fill", "FlushBaskets() called at entry %lld, fZipBytes=%lld, fFlushedBytes=%lld\n", fEntries,
4583 }
4584
4585 if (autoSave) {
4586 AutoSave(); // does not call FlushBasketsImpl() again
4587 if (gDebug > 0)
4588 Info("TTree::Fill", "AutoSave called at entry %lld, fZipBytes=%lld, fSavedBytes=%lld\n", fEntries,
4590 }
4591
4592 // Check that output file is still below the maximum size.
4593 // If above, close the current file and continue on a new file.
4594 // Currently, the automatic change of file is restricted
4595 // to the case where the tree is in the top level directory.
4596 if (fDirectory)
4597 if (TFile *file = fDirectory->GetFile())
4598 if ((TDirectory *)file == fDirectory && (file->GetEND() > fgMaxTreeSize))
4600
4601 return nerror == 0 ? nbytes : -1;
4602}
4603
4604////////////////////////////////////////////////////////////////////////////////
4605/// Search in the array for a branch matching the branch name,
4606/// with the branch possibly expressed as a 'full' path name (with dots).
4608static TBranch *R__FindBranchHelper(TObjArray *list, const char *branchname) {
4609 if (list==0 || branchname == 0 || branchname[0] == '\0') return 0;
4610
4611 Int_t nbranches = list->GetEntries();
4612
4613 UInt_t brlen = strlen(branchname);
4614
4615 for(Int_t index = 0; index < nbranches; ++index) {
4616 TBranch *where = (TBranch*)list->UncheckedAt(index);
4617
4618 const char *name = where->GetName();
4619 UInt_t len = strlen(name);
4620 if (len && name[len-1]==']') {
4621 const char *dim = strchr(name,'[');
4622 if (dim) {
4623 len = dim - name;
4624 }
4625 }
4626 if (brlen == len && strncmp(branchname,name,len)==0) {
4627 return where;
4628 }
4629 TBranch *next = 0;
4630 if ((brlen >= len) && (branchname[len] == '.')
4631 && strncmp(name, branchname, len) == 0) {
4632 // The prefix subbranch name match the branch name.
4633
4634 next = where->FindBranch(branchname);
4635 if (!next) {
4636 next = where->FindBranch(branchname+len+1);
4637 }
4638 if (next) return next;
4639 }
4640 const char *dot = strchr((char*)branchname,'.');
4641 if (dot) {
4642 if (len==(size_t)(dot-branchname) &&
4643 strncmp(branchname,name,dot-branchname)==0 ) {
4644 return R__FindBranchHelper(where->GetListOfBranches(),dot+1);
4645 }
4646 }
4647 }
4648 return 0;
4649}
4650
4651////////////////////////////////////////////////////////////////////////////////
4652/// Return the branch that correspond to the path 'branchname', which can
4653/// include the name of the tree or the omitted name of the parent branches.
4654/// In case of ambiguity, returns the first match.
4656TBranch* TTree::FindBranch(const char* branchname)
4657{
4658 // We already have been visited while recursively looking
4659 // through the friends tree, let return
4661 return 0;
4662 }
4663
4664 TBranch* branch = 0;
4665 // If the first part of the name match the TTree name, look for the right part in the
4666 // list of branches.
4667 // This will allow the branchname to be preceded by
4668 // the name of this tree.
4669 if (strncmp(fName.Data(),branchname,fName.Length())==0 && branchname[fName.Length()]=='.') {
4670 branch = R__FindBranchHelper( GetListOfBranches(), branchname + fName.Length() + 1);
4671 if (branch) return branch;
4672 }
4673 // If we did not find it, let's try to find the full name in the list of branches.
4674 branch = R__FindBranchHelper(GetListOfBranches(), branchname);
4675 if (branch) return branch;
4676
4677 // If we still did not find, let's try to find it within each branch assuming it does not the branch name.
4678 TIter next(GetListOfBranches());
4679 while ((branch = (TBranch*) next())) {
4680 TBranch* nestedbranch = branch->FindBranch(branchname);
4681 if (nestedbranch) {
4682 return nestedbranch;
4683 }
4684 }
4685
4686 // Search in list of friends.
4687 if (!fFriends) {
4688 return 0;
4689 }
4690 TFriendLock lock(this, kFindBranch);
4691 TIter nextf(fFriends);
4692 TFriendElement* fe = 0;
4693 while ((fe = (TFriendElement*) nextf())) {
4694 TTree* t = fe->GetTree();
4695 if (!t) {
4696 continue;
4697 }
4698 // If the alias is present replace it with the real name.
4699 const char *subbranch = strstr(branchname, fe->GetName());
4700 if (subbranch != branchname) {
4701 subbranch = 0;
4702 }
4703 if (subbranch) {
4704 subbranch += strlen(fe->GetName());
4705 if (*subbranch != '.') {
4706 subbranch = 0;
4707 } else {
4708 ++subbranch;
4709 }
4710 }
4711 std::ostringstream name;
4712 if (subbranch) {
4713 name << t->GetName() << "." << subbranch;
4714 } else {
4715 name << branchname;
4716 }
4717 branch = t->FindBranch(name.str().c_str());
4718 if (branch) {
4719 return branch;
4720 }
4721 }
4722 return 0;
4723}
4724
4725////////////////////////////////////////////////////////////////////////////////
4726/// Find leaf..
4728TLeaf* TTree::FindLeaf(const char* searchname)
4729{
4730 // We already have been visited while recursively looking
4731 // through the friends tree, let's return.
4733 return 0;
4734 }
4735
4736 // This will allow the branchname to be preceded by
4737 // the name of this tree.
4738 char* subsearchname = (char*) strstr(searchname, GetName());
4739 if (subsearchname != searchname) {
4740 subsearchname = 0;
4741 }
4742 if (subsearchname) {
4743 subsearchname += strlen(GetName());
4744 if (*subsearchname != '.') {
4745 subsearchname = 0;
4746 } else {
4747 ++subsearchname;
4748 if (subsearchname[0]==0) {
4749 subsearchname = 0;
4750 }
4751 }
4752 }
4753
4754 TString leafname;
4755 TString leaftitle;
4756 TString longname;
4757 TString longtitle;
4758
4759 const bool searchnameHasDot = strchr(searchname, '.') != nullptr;
4760
4761 // For leaves we allow for one level up to be prefixed to the name.
4762 TIter next(GetListOfLeaves());
4763 TLeaf* leaf = 0;
4764 while ((leaf = (TLeaf*) next())) {
4765 leafname = leaf->GetName();
4766 Ssiz_t dim = leafname.First('[');
4767 if (dim >= 0) leafname.Remove(dim);
4768
4769 if (leafname == searchname) {
4770 return leaf;
4771 }
4772 if (subsearchname && leafname == subsearchname) {
4773 return leaf;
4774 }
4775 // The TLeafElement contains the branch name
4776 // in its name, let's use the title.
4777 leaftitle = leaf->GetTitle();
4778 dim = leaftitle.First('[');
4779 if (dim >= 0) leaftitle.Remove(dim);
4780
4781 if (leaftitle == searchname) {
4782 return leaf;
4783 }
4784 if (subsearchname && leaftitle == subsearchname) {
4785 return leaf;
4786 }
4787 if (!searchnameHasDot)
4788 continue;
4789 TBranch* branch = leaf->GetBranch();
4790 if (branch) {
4791 longname.Form("%s.%s",branch->GetName(),leafname.Data());
4792 dim = longname.First('[');
4793 if (dim>=0) longname.Remove(dim);
4794 if (longname == searchname) {
4795 return leaf;
4796 }
4797 if (subsearchname && longname == subsearchname) {
4798 return leaf;
4799 }
4800 longtitle.Form("%s.%s",branch->GetName(),leaftitle.Data());
4801 dim = longtitle.First('[');
4802 if (dim>=0) longtitle.Remove(dim);
4803 if (longtitle == searchname) {
4804 return leaf;
4805 }
4806 if (subsearchname && longtitle == subsearchname) {
4807 return leaf;
4808 }
4809 // The following is for the case where the branch is only
4810 // a sub-branch. Since we do not see it through
4811 // TTree::GetListOfBranches, we need to see it indirectly.
4812 // This is the less sturdy part of this search ... it may
4813 // need refining ...
4814 if (strstr(searchname, ".") && !strcmp(searchname, branch->GetName())) {
4815 return leaf;
4816 }
4817 if (subsearchname && strstr(subsearchname, ".") && !strcmp(subsearchname, branch->GetName())) {
4818 return leaf;
4819 }
4820 }
4821 }
4822 // Search in list of friends.
4823 if (!fFriends) {
4824 return 0;
4825 }
4826 TFriendLock lock(this, kFindLeaf);
4827 TIter nextf(fFriends);
4828 TFriendElement* fe = 0;
4829 while ((fe = (TFriendElement*) nextf())) {
4830 TTree* t = fe->GetTree();
4831 if (!t) {
4832 continue;
4833 }
4834 // If the alias is present replace it with the real name.
4835 subsearchname = (char*) strstr(searchname, fe->GetName());
4836 if (subsearchname != searchname) {
4837 subsearchname = 0;
4838 }
4839 if (subsearchname) {
4840 subsearchname += strlen(fe->GetName());
4841 if (*subsearchname != '.') {
4842 subsearchname = 0;
4843 } else {
4844 ++subsearchname;
4845 }
4846 }
4847 if (subsearchname) {
4848 leafname.Form("%s.%s",t->GetName(),subsearchname);
4849 } else {
4850 leafname = searchname;
4851 }
4852 leaf = t->FindLeaf(leafname);
4853 if (leaf) {
4854 return leaf;
4855 }
4856 }
4857 return 0;
4858}
4859
4860////////////////////////////////////////////////////////////////////////////////
4861/// Fit a projected item(s) from a tree.
4862///
4863/// funcname is a TF1 function.
4864///
4865/// See TTree::Draw() for explanations of the other parameters.
4866///
4867/// By default the temporary histogram created is called htemp.
4868/// If varexp contains >>hnew , the new histogram created is called hnew
4869/// and it is kept in the current directory.
4870///
4871/// The function returns the number of selected entries.
4872///
4873/// Example:
4874/// ~~~ {.cpp}
4875/// tree.Fit(pol4,"sqrt(x)>>hsqrt","y>0")
4876/// ~~~
4877/// will fit sqrt(x) and save the histogram as "hsqrt" in the current
4878/// directory.
4879///
4880/// See also TTree::UnbinnedFit
4881///
4882/// ## Return status
4883///
4884/// The function returns the status of the histogram fit (see TH1::Fit)
4885/// If no entries were selected, the function returns -1;
4886/// (i.e. fitResult is null if the fit is OK)
4888Int_t TTree::Fit(const char* funcname, const char* varexp, const char* selection, Option_t* option, Option_t* goption, Long64_t nentries, Long64_t firstentry)
4889{
4890 GetPlayer();
4891 if (fPlayer) {
4892 return fPlayer->Fit(funcname, varexp, selection, option, goption, nentries, firstentry);
4893 }
4894 return -1;
4895}
4896
4897namespace {
4898struct BoolRAIIToggle {
4899 Bool_t &m_val;
4900
4901 BoolRAIIToggle(Bool_t &val) : m_val(val) { m_val = true; }
4902 ~BoolRAIIToggle() { m_val = false; }
4903};
4904}
4905
4906////////////////////////////////////////////////////////////////////////////////
4907/// Write to disk all the basket that have not yet been individually written and
4908/// create an event cluster boundary (by default).
4909///
4910/// If the caller wishes to flush the baskets but not create an event cluster,
4911/// then set create_cluster to false.
4912///
4913/// If ROOT has IMT-mode enabled, this will launch multiple TBB tasks in parallel
4914/// via TThreadExecutor to do this operation; one per basket compression. If the
4915/// caller utilizes TBB also, care must be taken to prevent deadlocks.
4916///
4917/// For example, let's say the caller holds mutex A and calls FlushBaskets; while
4918/// TBB is waiting for the ROOT compression tasks to complete, it may decide to
4919/// run another one of the user's tasks in this thread. If the second user task
4920/// tries to acquire A, then a deadlock will occur. The example call sequence
4921/// looks like this:
4922///
4923/// - User acquires mutex A
4924/// - User calls FlushBaskets.
4925/// - ROOT launches N tasks and calls wait.
4926/// - TBB schedules another user task, T2.
4927/// - T2 tries to acquire mutex A.
4928///
4929/// At this point, the thread will deadlock: the code may function with IMT-mode
4930/// disabled if the user assumed the legacy code never would run their own TBB
4931/// tasks.
4932///
4933/// SO: users of TBB who want to enable IMT-mode should carefully review their
4934/// locking patterns and make sure they hold no coarse-grained application
4935/// locks when they invoke ROOT.
4936///
4937/// Return the number of bytes written or -1 in case of write error.
4938Int_t TTree::FlushBaskets(Bool_t create_cluster) const
4939{
4940 Int_t retval = FlushBasketsImpl();
4941 if (retval == -1) return retval;
4942
4943 if (create_cluster) const_cast<TTree *>(this)->MarkEventCluster();
4944 return retval;
4945}
4946
4947////////////////////////////////////////////////////////////////////////////////
4948/// Internal implementation of the FlushBaskets algorithm.
4949/// Unlike the public interface, this does NOT create an explicit event cluster
4950/// boundary; it is up to the (internal) caller to determine whether that should
4951/// done.
4952///
4953/// Otherwise, the comments for FlushBaskets applies.
4956{
4957 if (!fDirectory) return 0;
4958 Int_t nbytes = 0;
4959 Int_t nerror = 0;
4960 TObjArray *lb = const_cast<TTree*>(this)->GetListOfBranches();
4961 Int_t nb = lb->GetEntriesFast();
4962
4963#ifdef R__USE_IMT
4964 const auto useIMT = ROOT::IsImplicitMTEnabled() && fIMTEnabled;
4965 if (useIMT) {
4966 // ROOT-9668: here we need to check if the size of fSortedBranches is different from the
4967 // size of the list of branches before triggering the initialisation of the fSortedBranches
4968 // container to cover two cases:
4969 // 1. This is the first time we flush. fSortedBranches is empty and we need to fill it.
4970 // 2. We flushed at least once already but a branch has been be added to the tree since then
4971 if (fSortedBranches.size() != unsigned(nb)) { const_cast<TTree*>(this)->InitializeBranchLists(false); }
4972
4973 BoolRAIIToggle sentry(fIMTFlush);
4974 fIMTZipBytes.store(0);
4975 fIMTTotBytes.store(0);
4976 std::atomic<Int_t> nerrpar(0);
4977 std::atomic<Int_t> nbpar(0);
4978 std::atomic<Int_t> pos(0);
4979
4980 auto mapFunction = [&]() {
4981 // The branch to process is obtained when the task starts to run.
4982 // This way, since branches are sorted, we make sure that branches
4983 // leading to big tasks are processed first. If we assigned the
4984 // branch at task creation time, the scheduler would not necessarily
4985 // respect our sorting.
4986 Int_t j = pos.fetch_add(1);
4987
4988 auto branch = fSortedBranches[j].second;
4989 if (R__unlikely(!branch)) { return; }
4990
4991 if (R__unlikely(gDebug > 0)) {
4992 std::stringstream ss;
4993 ss << std::this_thread::get_id();
4994 Info("FlushBaskets", "[IMT] Thread %s", ss.str().c_str());
4995 Info("FlushBaskets", "[IMT] Running task for branch #%d: %s", j, branch->GetName());
4996 }
4997
4998 Int_t nbtask = branch->FlushBaskets();
4999
5000 if (nbtask < 0) { nerrpar++; }
5001 else { nbpar += nbtask; }
5002 };
5003
5005 pool.Foreach(mapFunction, nb);
5006
5007 fIMTFlush = false;
5008 const_cast<TTree*>(this)->AddTotBytes(fIMTTotBytes);
5009 const_cast<TTree*>(this)->AddZipBytes(fIMTZipBytes);
5010
5011 return nerrpar ? -1 : nbpar.load();
5012 }
5013#endif
5014 for (Int_t j = 0; j < nb; j++) {
5015 TBranch* branch = (TBranch*) lb->UncheckedAt(j);
5016 if (branch) {
5017 Int_t nwrite = branch->FlushBaskets();
5018 if (nwrite<0) {
5019 ++nerror;
5020 } else {
5021 nbytes += nwrite;
5022 }
5023 }
5024 }
5025 if (nerror) {
5026 return -1;
5027 } else {
5028 return nbytes;
5029 }
5030}
5031
5032////////////////////////////////////////////////////////////////////////////////
5033/// Returns the expanded value of the alias. Search in the friends if any.
5035const char* TTree::GetAlias(const char* aliasName) const
5036{
5037 // We already have been visited while recursively looking
5038 // through the friends tree, let's return.
5040 return 0;
5041 }
5042 if (fAliases) {
5043 TObject* alias = fAliases->FindObject(aliasName);
5044 if (alias) {
5045 return alias->GetTitle();
5046 }
5047 }
5048 if (!fFriends) {
5049 return 0;
5050 }
5051 TFriendLock lock(const_cast<TTree*>(this), kGetAlias);
5052 TIter nextf(fFriends);
5053 TFriendElement* fe = 0;
5054 while ((fe = (TFriendElement*) nextf())) {
5055 TTree* t = fe->GetTree();
5056 if (t) {
5057 const char* alias = t->GetAlias(aliasName);
5058 if (alias) {
5059 return alias;
5060 }
5061 const char* subAliasName = strstr(aliasName, fe->GetName());
5062 if (subAliasName && (subAliasName[strlen(fe->GetName())] == '.')) {
5063 alias = t->GetAlias(aliasName + strlen(fe->GetName()) + 1);
5064 if (alias) {
5065 return alias;
5066 }
5067 }
5068 }
5069 }
5070 return 0;
5071}
5072
5073////////////////////////////////////////////////////////////////////////////////
5074/// Return pointer to the branch with the given name in this tree or its friends.
5076TBranch* TTree::GetBranch(const char* name)
5077{
5078 if (name == 0) return 0;
5079
5080 // We already have been visited while recursively
5081 // looking through the friends tree, let's return.
5083 return 0;
5084 }
5085
5086 // Search using branches.
5088 for (Int_t i = 0; i < nb; i++) {
5089 TBranch* branch = (TBranch*) fBranches.UncheckedAt(i);
5090 if (!branch) {
5091 continue;
5092 }
5093 if (!strcmp(branch->GetName(), name)) {
5094 return branch;
5095 }
5096 TObjArray* lb = branch->GetListOfBranches();
5097 Int_t nb1 = lb->GetEntriesFast();
5098 for (Int_t j = 0; j < nb1; j++) {
5099 TBranch* b1 = (TBranch*) lb->UncheckedAt(j);
5100 if (!strcmp(b1->GetName(), name)) {
5101 return b1;
5102 }
5103 TObjArray* lb1 = b1->GetListOfBranches();
5104 Int_t nb2 = lb1->GetEntriesFast();
5105 for (Int_t k = 0; k < nb2; k++) {
5106 TBranch* b2 = (TBranch*) lb1->UncheckedAt(k);
5107 if (!strcmp(b2->GetName(), name)) {
5108 return b2;
5109 }
5110 }
5111 }
5112 }
5113
5114 // Search using leaves.
5115 TObjArray* leaves = GetListOfLeaves();
5116 Int_t nleaves = leaves->GetEntriesFast();
5117 for (Int_t i = 0; i < nleaves; i++) {
5118 TLeaf* leaf = (TLeaf*) leaves->UncheckedAt(i);
5119 TBranch* branch = leaf->GetBranch();
5120 if (!strcmp(branch->GetName(), name)) {
5121 return branch;
5122 }
5123 }
5124
5125 if (!fFriends) {
5126 return 0;
5127 }
5128
5129 // Search in list of friends.
5130 TFriendLock lock(this, kGetBranch);
5131 TIter next(fFriends);
5132 TFriendElement* fe = 0;
5133 while ((fe = (TFriendElement*) next())) {
5134 TTree* t = fe->GetTree();
5135 if (t) {
5136 TBranch* branch = t->GetBranch(name);
5137 if (branch) {
5138 return branch;
5139 }
5140 }
5141 }
5142
5143 // Second pass in the list of friends when
5144 // the branch name is prefixed by the tree name.
5145 next.Reset();
5146 while ((fe = (TFriendElement*) next())) {
5147 TTree* t = fe->GetTree();
5148 if (!t) {
5149 continue;
5150 }
5151 char* subname = (char*) strstr(name, fe->GetName());
5152 if (subname != name) {
5153 continue;
5154 }
5155 Int_t l = strlen(fe->GetName());
5156 subname += l;
5157 if (*subname != '.') {
5158 continue;
5159 }
5160 subname++;
5161 TBranch* branch = t->GetBranch(subname);
5162 if (branch) {
5163 return branch;
5164 }
5165 }
5166 return 0;
5167}
5168
5169////////////////////////////////////////////////////////////////////////////////
5170/// Return status of branch with name branchname.
5171///
5172/// - 0 if branch is not activated
5173/// - 1 if branch is activated
5175Bool_t TTree::GetBranchStatus(const char* branchname) const
5176{
5177 TBranch* br = const_cast<TTree*>(this)->GetBranch(branchname);
5178 if (br) {
5179 return br->TestBit(kDoNotProcess) == 0;
5180 }
5181 return 0;
5182}
5183
5184////////////////////////////////////////////////////////////////////////////////
5185/// Static function returning the current branch style.
5186///
5187/// - style = 0 old Branch
5188/// - style = 1 new Bronch
5191{
5192 return fgBranchStyle;
5193}
5194
5195////////////////////////////////////////////////////////////////////////////////
5196/// Used for automatic sizing of the cache.
5197///
5198/// Estimates a suitable size for the tree cache based on AutoFlush.
5199/// A cache sizing factor is taken from the configuration. If this yields zero
5200/// and withDefault is true the historical algorithm for default size is used.
5202Long64_t TTree::GetCacheAutoSize(Bool_t withDefault /* = kFALSE */ ) const
5203{
5204 const char *stcs;
5205 Double_t cacheFactor = 0.0;
5206 if (!(stcs = gSystem->Getenv("ROOT_TTREECACHE_SIZE")) || !*stcs) {
5207 cacheFactor = gEnv->GetValue("TTreeCache.Size", 1.0);
5208 } else {
5209 cacheFactor = TString(stcs).Atof();
5210 }
5211
5212 if (cacheFactor < 0.0) {
5213 // ignore negative factors
5214 cacheFactor = 0.0;
5215 }
5216
5217 Long64_t cacheSize = 0;
5218
5219 if (fAutoFlush < 0) cacheSize = Long64_t(-cacheFactor*fAutoFlush);
5220 else if (fAutoFlush == 0) cacheSize = 0;
5221 else cacheSize = Long64_t(cacheFactor*1.5*fAutoFlush*GetZipBytes()/(fEntries+1));
5222
5223 if (cacheSize >= (INT_MAX / 4)) {
5224 cacheSize = INT_MAX / 4;
5225 }
5226
5227 if (cacheSize < 0) {
5228 cacheSize = 0;
5229 }
5230
5231 if (cacheSize == 0 && withDefault) {
5232 if (fAutoFlush < 0) cacheSize = -fAutoFlush;
5233 else if (fAutoFlush == 0) cacheSize = 0;
5234 else cacheSize = Long64_t(1.5*fAutoFlush*GetZipBytes()/(fEntries+1));
5235 }
5236
5237 return cacheSize;
5238}
5239
5240////////////////////////////////////////////////////////////////////////////////
5241/// Return an iterator over the cluster of baskets starting at firstentry.
5242///
5243/// This iterator is not yet supported for TChain object.
5244/// ~~~ {.cpp}
5245/// TTree::TClusterIterator clusterIter = tree->GetClusterIterator(entry);
5246/// Long64_t clusterStart;
5247/// while( (clusterStart = clusterIter()) < tree->GetEntries() ) {
5248/// printf("The cluster starts at %lld and ends at %lld (inclusive)\n",clusterStart,clusterIter.GetNextEntry()-1);
5249/// }
5250/// ~~~
5253{
5254 // create cache if wanted
5255 if (fCacheDoAutoInit)
5257
5258 return TClusterIterator(this,firstentry);
5259}
5260
5261////////////////////////////////////////////////////////////////////////////////
5262/// Return pointer to the current file.
5265{
5266 if (!fDirectory || fDirectory==gROOT) {
5267 return 0;
5268 }
5269 return fDirectory->GetFile();
5270}
5271
5272////////////////////////////////////////////////////////////////////////////////
5273/// Return the number of entries matching the selection.
5274/// Return -1 in case of errors.
5275///
5276/// If the selection uses any arrays or containers, we return the number
5277/// of entries where at least one element match the selection.
5278/// GetEntries is implemented using the selector class TSelectorEntries,
5279/// which can be used directly (see code in TTreePlayer::GetEntries) for
5280/// additional option.
5281/// If SetEventList was used on the TTree or TChain, only that subset
5282/// of entries will be considered.
5284Long64_t TTree::GetEntries(const char *selection)
5285{
5286 GetPlayer();
5287 if (fPlayer) {
5288 return fPlayer->GetEntries(selection);
5289 }
5290 return -1;
5291}
5292
5293////////////////////////////////////////////////////////////////////////////////
5294/// Return pointer to the 1st Leaf named name in any Branch of this Tree or
5295/// any branch in the list of friend trees.
5298{
5299 if (fEntries) return fEntries;
5300 if (!fFriends) return 0;
5302 if (!fr) return 0;
5303 TTree *t = fr->GetTree();
5304 if (t==0) return 0;
5305 return t->GetEntriesFriend();
5306}
5307
5308////////////////////////////////////////////////////////////////////////////////
5309/// Read all branches of entry and return total number of bytes read.
5310///
5311/// - `getall = 0` : get only active branches
5312/// - `getall = 1` : get all branches
5313///
5314/// The function returns the number of bytes read from the input buffer.
5315/// If entry does not exist the function returns 0.
5316/// If an I/O error occurs, the function returns -1.
5317///
5318/// If the Tree has friends, also read the friends entry.
5319///
5320/// To activate/deactivate one or more branches, use TBranch::SetBranchStatus
5321/// For example, if you have a Tree with several hundred branches, and you
5322/// are interested only by branches named "a" and "b", do
5323/// ~~~ {.cpp}
5324/// mytree.SetBranchStatus("*",0); //disable all branches
5325/// mytree.SetBranchStatus("a",1);
5326/// mytree.SetBranchStatus("b",1);
5327/// ~~~
5328/// when calling mytree.GetEntry(i); only branches "a" and "b" will be read.
5329///
5330/// __WARNING!!__
5331/// If your Tree has been created in split mode with a parent branch "parent.",
5332/// ~~~ {.cpp}
5333/// mytree.SetBranchStatus("parent",1);
5334/// ~~~
5335/// will not activate the sub-branches of "parent". You should do:
5336/// ~~~ {.cpp}
5337/// mytree.SetBranchStatus("parent*",1);
5338/// ~~~
5339/// Without the trailing dot in the branch creation you have no choice but to
5340/// call SetBranchStatus explicitly for each of the sub branches.
5341///
5342/// An alternative is to call directly
5343/// ~~~ {.cpp}
5344/// brancha.GetEntry(i)
5345/// branchb.GetEntry(i);
5346/// ~~~
5347/// ## IMPORTANT NOTE
5348///
5349/// By default, GetEntry reuses the space allocated by the previous object
5350/// for each branch. You can force the previous object to be automatically
5351/// deleted if you call mybranch.SetAutoDelete(kTRUE) (default is kFALSE).
5352///
5353/// Example:
5354///
5355/// Consider the example in $ROOTSYS/test/Event.h
5356/// The top level branch in the tree T is declared with:
5357/// ~~~ {.cpp}
5358/// Event *event = 0; //event must be null or point to a valid object
5359/// //it must be initialized
5360/// T.SetBranchAddress("event",&event);
5361/// ~~~
5362/// When reading the Tree, one can choose one of these 3 options:
5363///
5364/// ## OPTION 1
5365///
5366/// ~~~ {.cpp}
5367/// for (Long64_t i=0;i<nentries;i++) {
5368/// T.GetEntry(i);
5369/// // the object event has been filled at this point
5370/// }
5371/// ~~~
5372/// The default (recommended). At the first entry an object of the class
5373/// Event will be created and pointed by event. At the following entries,
5374/// event will be overwritten by the new data. All internal members that are
5375/// TObject* are automatically deleted. It is important that these members
5376/// be in a valid state when GetEntry is called. Pointers must be correctly
5377/// initialized. However these internal members will not be deleted if the
5378/// characters "->" are specified as the first characters in the comment
5379/// field of the data member declaration.
5380///
5381/// If "->" is specified, the pointer member is read via pointer->Streamer(buf).
5382/// In this case, it is assumed that the pointer is never null (case of
5383/// pointer TClonesArray *fTracks in the Event example). If "->" is not
5384/// specified, the pointer member is read via buf >> pointer. In this case
5385/// the pointer may be null. Note that the option with "->" is faster to
5386/// read or write and it also consumes less space in the file.
5387///
5388/// ## OPTION 2
5389///
5390/// The option AutoDelete is set
5391/// ~~~ {.cpp}
5392/// TBranch *branch = T.GetBranch("event");
5393/// branch->SetAddress(&event);
5394/// branch->SetAutoDelete(kTRUE);
5395/// for (Long64_t i=0;i<nentries;i++) {
5396/// T.GetEntry(i);
5397/// // the object event has been filled at this point
5398/// }
5399/// ~~~
5400/// In this case, at each iteration, the object event is deleted by GetEntry
5401/// and a new instance of Event is created and filled.
5402///
5403/// ## OPTION 3
5404///
5405/// ~~~ {.cpp}
5406/// Same as option 1, but you delete yourself the event.
5407///
5408/// for (Long64_t i=0;i<nentries;i++) {
5409/// delete event;
5410/// event = 0; // EXTREMELY IMPORTANT
5411/// T.GetEntry(i);
5412/// // the object event has been filled at this point
5413/// }
5414/// ~~~
5415/// It is strongly recommended to use the default option 1. It has the
5416/// additional advantage that functions like TTree::Draw (internally calling
5417/// TTree::GetEntry) will be functional even when the classes in the file are
5418/// not available.
5419///
5420/// Note: See the comments in TBranchElement::SetAddress() for the
5421/// object ownership policy of the underlying (user) data.
5423Int_t TTree::GetEntry(Long64_t entry, Int_t getall)
5424{
5425
5426 // We already have been visited while recursively looking
5427 // through the friends tree, let return
5428 if (kGetEntry & fFriendLockStatus) return 0;
5429
5430 if (entry < 0 || entry >= fEntries) return 0;
5431 Int_t i;
5432 Int_t nbytes = 0;
5433 fReadEntry = entry;
5434
5435 // create cache if wanted
5436 if (fCacheDoAutoInit)
5438
5439 Int_t nbranches = fBranches.GetEntriesUnsafe();
5440 Int_t nb=0;
5441
5442 auto seqprocessing = [&]() {
5443 TBranch *branch;
5444 for (i=0;i<nbranches;i++) {
5445 branch = (TBranch*)fBranches.UncheckedAt(i);
5446 nb = branch->GetEntry(entry, getall);
5447 if (nb < 0) break;
5448 nbytes += nb;
5449 }
5450 };
5451
5452#ifdef R__USE_IMT
5454 if (fSortedBranches.empty())
5456
5457 // Count branches are processed first and sequentially
5458 for (auto branch : fSeqBranches) {
5459 nb = branch->GetEntry(entry, getall);
5460 if (nb < 0) break;
5461 nbytes += nb;
5462 }
5463 if (nb < 0) return nb;
5464
5465 // Enable this IMT use case (activate its locks)
5467
5468 Int_t errnb = 0;
5469 std::atomic<Int_t> pos(0);
5470 std::atomic<Int_t> nbpar(0);
5471
5472 auto mapFunction = [&]() {
5473 // The branch to process is obtained when the task starts to run.
5474 // This way, since branches are sorted, we make sure that branches
5475 // leading to big tasks are processed first. If we assigned the
5476 // branch at task creation time, the scheduler would not necessarily
5477 // respect our sorting.
5478 Int_t j = pos.fetch_add(1);
5479
5480 Int_t nbtask = 0;
5481 auto branch = fSortedBranches[j].second;
5482
5483 if (gDebug > 0) {
5484 std::stringstream ss;
5485 ss << std::this_thread::get_id();
5486 Info("GetEntry", "[IMT] Thread %s", ss.str().c_str());
5487 Info("GetEntry", "[IMT] Running task for branch #%d: %s", j, branch->GetName());
5488 }
5489
5490 std::chrono::time_point<std::chrono::system_clock> start, end;
5491
5492 start = std::chrono::system_clock::now();
5493 nbtask = branch->GetEntry(entry, getall);
5494 end = std::chrono::system_clock::now();
5495
5496 Long64_t tasktime = (Long64_t)std::chrono::duration_cast<std::chrono::microseconds>(end - start).count();
5497 fSortedBranches[j].first += tasktime;
5498
5499 if (nbtask < 0) errnb = nbtask;
5500 else nbpar += nbtask;
5501 };
5502
5504 pool.Foreach(mapFunction, fSortedBranches.size());
5505
5506 if (errnb < 0) {
5507 nb = errnb;
5508 }
5509 else {
5510 // Save the number of bytes read by the tasks
5511 nbytes += nbpar;
5512
5513 // Re-sort branches if necessary
5517 }
5518 }
5519 }
5520 else {
5521 seqprocessing();
5522 }
5523#else
5524 seqprocessing();
5525#endif
5526 if (nb < 0) return nb;
5527
5528 // GetEntry in list of friends
5529 if (!fFriends) return nbytes;
5530 TFriendLock lock(this,kGetEntry);
5531 TIter nextf(fFriends);
5532 TFriendElement *fe;
5533 while ((fe = (TFriendElement*)nextf())) {
5534 TTree *t = fe->GetTree();
5535 if (t) {
5537 nb = t->GetEntry(t->GetReadEntry(),getall);
5538 } else {
5539 if ( t->LoadTreeFriend(entry,this) >= 0 ) {
5540 nb = t->GetEntry(t->GetReadEntry(),getall);
5541 } else nb = 0;
5542 }
5543 if (nb < 0) return nb;
5544 nbytes += nb;
5545 }
5546 }
5547 return nbytes;
5548}
5549
5550
5551////////////////////////////////////////////////////////////////////////////////
5552/// Divides the top-level branches into two vectors: (i) branches to be
5553/// processed sequentially and (ii) branches to be processed in parallel.
5554/// Even if IMT is on, some branches might need to be processed first and in a
5555/// sequential fashion: in the parallelization of GetEntry, those are the
5556/// branches that store the size of another branch for every entry
5557/// (e.g. the size of an array branch). If such branches were processed
5558/// in parallel with the rest, there could be two threads invoking
5559/// TBranch::GetEntry on one of them at the same time, since a branch that
5560/// depends on a size (or count) branch will also invoke GetEntry on the latter.
5561/// This method can be invoked several times during the event loop if the TTree
5562/// is being written, for example when adding new branches. In these cases, the
5563/// `checkLeafCount` parameter is false.
5564/// \param[in] checkLeafCount True if we need to check whether some branches are
5565/// count leaves.
5567void TTree::InitializeBranchLists(bool checkLeafCount)
5568{
5569 Int_t nbranches = fBranches.GetEntriesFast();
5570
5571 // The special branch fBranchRef needs to be processed sequentially:
5572 // we add it once only.
5573 if (fBranchRef && fBranchRef != fSeqBranches[0]) {
5574 fSeqBranches.push_back(fBranchRef);
5575 }
5576
5577 // The branches to be processed sequentially are those that are the leaf count of another branch
5578 if (checkLeafCount) {
5579 for (Int_t i = 0; i < nbranches; i++) {
5580 TBranch* branch = (TBranch*)fBranches.UncheckedAt(i);
5581 auto leafCount = ((TLeaf*)branch->GetListOfLeaves()->At(0))->GetLeafCount();
5582 if (leafCount) {
5583 auto countBranch = leafCount->GetBranch();
5584 if (std::find(fSeqBranches.begin(), fSeqBranches.end(), countBranch) == fSeqBranches.end()) {
5585 fSeqBranches.push_back(countBranch);
5586 }
5587 }
5588 }
5589 }
5590
5591 // Any branch that is not a leaf count can be safely processed in parallel when reading
5592 // We need to reset the vector to make sure we do not re-add several times the same branch.
5593 if (!checkLeafCount) {
5594 fSortedBranches.clear();
5595 }
5596 for (Int_t i = 0; i < nbranches; i++) {
5597 Long64_t bbytes = 0;
5598 TBranch* branch = (TBranch*)fBranches.UncheckedAt(i);
5599 if (std::find(fSeqBranches.begin(), fSeqBranches.end(), branch) == fSeqBranches.end()) {
5600 bbytes = branch->GetTotBytes("*");
5601 fSortedBranches.emplace_back(bbytes, branch);
5602 }
5603 }
5604
5605 // Initially sort parallel branches by size
5606 std::sort(fSortedBranches.begin(),
5607 fSortedBranches.end(),
5608 [](std::pair<Long64_t,TBranch*> a, std::pair<Long64_t,TBranch*> b) {
5609 return a.first > b.first;
5610 });
5611
5612 for (size_t i = 0; i < fSortedBranches.size(); i++) {
5613 fSortedBranches[i].first = 0LL;
5614 }
5615}
5616
5617////////////////////////////////////////////////////////////////////////////////
5618/// Sorts top-level branches by the last average task time recorded per branch.
5621{
5622 for (size_t i = 0; i < fSortedBranches.size(); i++) {
5624 }
5625
5626 std::sort(fSortedBranches.begin(),
5627 fSortedBranches.end(),
5628 [](std::pair<Long64_t,TBranch*> a, std::pair<Long64_t,TBranch*> b) {
5629 return a.first > b.first;
5630 });
5631
5632 for (size_t i = 0; i < fSortedBranches.size(); i++) {
5633 fSortedBranches[i].first = 0LL;
5634 }
5635}
5636
5637////////////////////////////////////////////////////////////////////////////////
5638///Returns the entry list assigned to this tree
5641{
5642 return fEntryList;
5643}
5644
5645////////////////////////////////////////////////////////////////////////////////
5646/// Return entry number corresponding to entry.
5647///
5648/// if no TEntryList set returns entry
5649/// else returns the entry number corresponding to the list index=entry
5652{
5653 if (!fEntryList) {
5654 return entry;
5655 }
5656
5657 return fEntryList->GetEntry(entry);
5658}
5659
5660////////////////////////////////////////////////////////////////////////////////
5661/// Return entry number corresponding to major and minor number.
5662/// Note that this function returns only the entry number, not the data
5663/// To read the data corresponding to an entry number, use TTree::GetEntryWithIndex
5664/// the BuildIndex function has created a table of Long64_t* of sorted values
5665/// corresponding to val = major<<31 + minor;
5666/// The function performs binary search in this sorted table.
5667/// If it finds a pair that matches val, it returns directly the
5668/// index in the table.
5669/// If an entry corresponding to major and minor is not found, the function
5670/// returns the index of the major,minor pair immediately lower than the
5671/// requested value, ie it will return -1 if the pair is lower than
5672/// the first entry in the index.
5673///
5674/// See also GetEntryNumberWithIndex
5677{
5678 if (!fTreeIndex) {
5679 return -1;
5680 }
5681 return fTreeIndex->GetEntryNumberWithBestIndex(major, minor);
5682}
5683
5684////////////////////////////////////////////////////////////////////////////////
5685/// Return entry number corresponding to major and minor number.
5686/// Note that this function returns only the entry number, not the data
5687/// To read the data corresponding to an entry number, use TTree::GetEntryWithIndex
5688/// the BuildIndex function has created a table of Long64_t* of sorted values
5689/// corresponding to val = major<<31 + minor;
5690/// The function performs binary search in this sorted table.
5691/// If it finds a pair that matches val, it returns directly the
5692/// index in the table, otherwise it returns -1.
5693///
5694/// See also GetEntryNumberWithBestIndex
5697{
5698 if (!fTreeIndex) {
5699 return -1;
5700 }
5701 return fTreeIndex->GetEntryNumberWithIndex(major, minor);
5702}
5703
5704////////////////////////////////////////////////////////////////////////////////
5705/// Read entry corresponding to major and minor number.
5706///
5707/// The function returns the total number of bytes read.
5708/// If the Tree has friend trees, the corresponding entry with
5709/// the index values (major,minor) is read. Note that the master Tree
5710/// and its friend may have different entry serial numbers corresponding
5711/// to (major,minor).
5714{
5715 // We already have been visited while recursively looking
5716 // through the friends tree, let's return.
5718 return 0;
5719 }
5720 Long64_t serial = GetEntryNumberWithIndex(major, minor);
5721 if (serial < 0) {
5722 return -1;
5723 }
5724 // create cache if wanted
5725 if (fCacheDoAutoInit)
5727
5728 Int_t i;
5729 Int_t nbytes = 0;
5730 fReadEntry = serial;
5731 TBranch *branch;
5732 Int_t nbranches = fBranches.GetEntriesFast();
5733 Int_t nb;
5734 for (i = 0; i < nbranches; ++i) {
5735 branch = (TBranch*)fBranches.UncheckedAt(i);
5736 nb = branch->GetEntry(serial);
5737 if (nb < 0) return nb;
5738 nbytes += nb;
5739 }
5740 // GetEntry in list of friends
5741 if (!fFriends) return nbytes;
5743 TIter nextf(fFriends);
5744 TFriendElement* fe = 0;
5745 while ((fe = (TFriendElement*) nextf())) {
5746 TTree *t = fe->GetTree();
5747 if (t) {
5748 serial = t->GetEntryNumberWithIndex(major,minor);
5749 if (serial <0) return -nbytes;
5750 nb = t->GetEntry(serial);
5751 if (nb < 0) return nb;
5752 nbytes += nb;
5753 }
5754 }
5755 return nbytes;
5756}
5757
5758////////////////////////////////////////////////////////////////////////////////
5759/// Return a pointer to the TTree friend whose name or alias is 'friendname.
5761TTree* TTree::GetFriend(const char *friendname) const
5762{
5763
5764 // We already have been visited while recursively
5765 // looking through the friends tree, let's return.
5767 return 0;
5768 }
5769 if (!fFriends) {
5770 return 0;
5771 }
5772 TFriendLock lock(const_cast<TTree*>(this), kGetFriend);
5773 TIter nextf(fFriends);
5774 TFriendElement* fe = 0;
5775 while ((fe = (TFriendElement*) nextf())) {
5776 if (strcmp(friendname,fe->GetName())==0
5777 || strcmp(friendname,fe->GetTreeName())==0) {
5778 return fe->GetTree();
5779 }
5780 }
5781 // After looking at the first level,
5782 // let's see if it is a friend of friends.
5783 nextf.Reset();
5784 fe = 0;
5785 while ((fe = (TFriendElement*) nextf())) {
5786 TTree *res = fe->GetTree()->GetFriend(friendname);
5787 if (res) {
5788 return res;
5789 }
5790 }
5791 return 0;
5792}
5793
5794////////////////////////////////////////////////////////////////////////////////
5795/// If the 'tree' is a friend, this method returns its alias name.
5796///
5797/// This alias is an alternate name for the tree.
5798///
5799/// It can be used in conjunction with a branch or leaf name in a TTreeFormula,
5800/// to specify in which particular tree the branch or leaf can be found if
5801/// the friend trees have branches or leaves with the same name as the master
5802/// tree.
5803///
5804/// It can also be used in conjunction with an alias created using
5805/// TTree::SetAlias in a TTreeFormula, e.g.:
5806/// ~~~ {.cpp}
5807/// maintree->Draw("treealias.fPx - treealias.myAlias");
5808/// ~~~
5809/// where fPx is a branch of the friend tree aliased as 'treealias' and 'myAlias'
5810/// was created using TTree::SetAlias on the friend tree.
5811///
5812/// However, note that 'treealias.myAlias' will be expanded literally,
5813/// without remembering that it comes from the aliased friend and thus
5814/// the branch name might not be disambiguated properly, which means
5815/// that you may not be able to take advantage of this feature.
5816///
5818const char* TTree::GetFriendAlias(TTree* tree) const
5819{
5820 if ((tree == this) || (tree == GetTree())) {
5821 return 0;
5822 }
5823
5824 // We already have been visited while recursively
5825 // looking through the friends tree, let's return.
5827 return 0;
5828 }
5829 if (!fFriends) {
5830 return 0;
5831 }
5832 TFriendLock lock(const_cast<TTree*>(this), kGetFriendAlias);
5833 TIter nextf(fFriends);
5834 TFriendElement* fe = 0;
5835 while ((fe = (TFriendElement*) nextf())) {
5836 TTree* t = fe->GetTree();
5837 if (t == tree) {
5838 return fe->GetName();
5839 }
5840 // Case of a chain:
5841 if (t && t->GetTree() == tree) {
5842 return fe->GetName();
5843 }
5844 }
5845 // After looking at the first level,
5846 // let's see if it is a friend of friends.
5847 nextf.Reset();
5848 fe = 0;
5849 while ((fe = (TFriendElement*) nextf())) {
5850 const char* res = fe->GetTree()->GetFriendAlias(tree);
5851 if (res) {
5852 return res;
5853 }
5854 }
5855 return 0;
5856}
5857
5858////////////////////////////////////////////////////////////////////////////////
5859/// Returns the current set of IO settings
5861{
5862 return fIOFeatures;
5863}
5864
5865////////////////////////////////////////////////////////////////////////////////
5866/// Creates a new iterator that will go through all the leaves on the tree itself and its friend.
5869{
5870 return new TTreeFriendLeafIter(this, dir);
5871}
5872
5873////////////////////////////////////////////////////////////////////////////////
5874/// Return pointer to the 1st Leaf named name in any Branch of this
5875/// Tree or any branch in the list of friend trees.
5876///
5877/// The leaf name can contain the name of a friend tree with the
5878/// syntax: friend_dir_and_tree.full_leaf_name
5879/// the friend_dir_and_tree can be of the form:
5880/// ~~~ {.cpp}
5881/// TDirectoryName/TreeName
5882/// ~~~
5884TLeaf* TTree::GetLeafImpl(const char* branchname, const char *leafname)
5885{
5886 TLeaf *leaf = 0;
5887 if (branchname) {
5888 TBranch *branch = FindBranch(branchname);
5889 if (branch) {
5890 leaf = branch->GetLeaf(leafname);
5891 if (leaf) {
5892 return leaf;
5893 }
5894 }
5895 }
5896 TIter nextl(GetListOfLeaves());
5897 while ((leaf = (TLeaf*)nextl())) {
5898 if (strcmp(leaf->GetName(),leafname)) continue;
5899 if (branchname) {
5900 UInt_t nbch = strlen(branchname);
5901 TBranch *br = leaf->GetBranch();
5902 const char* brname = br->GetName();
5903 TBranch *mother = br->GetMother();
5904 if (strncmp(brname,branchname,nbch)) {
5905 if (mother != br) {
5906 const char *mothername = mother->GetName();
5907 UInt_t motherlen = strlen(mothername);
5908 if (nbch > motherlen && strncmp(mothername,branchname,motherlen)==0 && (mothername[motherlen-1]=='.' || branchname[motherlen]=='.')) {
5909 // 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.
5910 if (strncmp(brname,branchname+motherlen+1,nbch-motherlen-1)) {
5911 // No it does not
5912 continue;
5913 } // else we have match so we can proceed.
5914 } else {
5915 // no match
5916 continue;
5917 }
5918 } else {
5919 continue;
5920 }
5921 }
5922 // The start of the branch name is identical to the content
5923 // of 'aname' before the first '/'.
5924 // Let's make sure that it is not longer (we are trying
5925 // to avoid having jet2/value match the branch jet23
5926 if ((strlen(brname) > nbch) && (brname[nbch] != '.') && (brname[nbch] != '[')) {
5927 continue;
5928 }
5929 }
5930 return leaf;
5931 }
5932 if (!fFriends) return 0;
5933 TFriendLock lock(this,kGetLeaf);
5934 TIter next(fFriends);
5935 TFriendElement *fe;
5936 while ((fe = (TFriendElement*)next())) {
5937 TTree *t = fe->GetTree();
5938 if (t) {
5939 leaf = t->GetLeaf(leafname);
5940 if (leaf) return leaf;
5941 }
5942 }
5943
5944 //second pass in the list of friends when the leaf name
5945 //is prefixed by the tree name
5946 TString strippedArg;
5947 next.Reset();
5948 while ((fe = (TFriendElement*)next())) {
5949 TTree *t = fe->GetTree();
5950 if (t==0) continue;
5951 char *subname = (char*)strstr(leafname,fe->GetName());
5952 if (subname != leafname) continue;
5953 Int_t l = strlen(fe->GetName());
5954 subname += l;
5955 if (*subname != '.') continue;
5956 subname++;
5957 strippedArg += subname;
5958 leaf = t->GetLeaf(branchname,subname);
5959 if (leaf) return leaf;
5960 }
5961 return 0;
5962}
5963
5964////////////////////////////////////////////////////////////////////////////////
5965/// Return pointer to the 1st Leaf named name in any Branch of this
5966/// Tree or any branch in the list of friend trees.
5967///
5968/// The leaf name can contain the name of a friend tree with the
5969/// syntax: friend_dir_and_tree.full_leaf_name
5970/// the friend_dir_and_tree can be of the form:
5971///
5972/// TDirectoryName/TreeName
5974TLeaf* TTree::GetLeaf(const char* branchname, const char *leafname)
5975{
5976 if (leafname == 0) return 0;
5977
5978 // We already have been visited while recursively looking
5979 // through the friends tree, let return
5981 return 0;
5982 }
5983
5984 return GetLeafImpl(branchname,leafname);
5985}
5986
5987////////////////////////////////////////////////////////////////////////////////
5988/// Return pointer to first leaf named \param[name] in any branch of this
5989/// tree or its friend trees.
5990///
5991/// \param[name] may be in the form 'branch/leaf'
5992///
5994TLeaf* TTree::GetLeaf(const char *name)
5995{
5996 // Return nullptr if name is invalid or if we have
5997 // already been visited while searching friend trees
5998 if (!name || (kGetLeaf & fFriendLockStatus))
5999 return nullptr;
6000
6001 std::string path(name);
6002 const auto sep = path.find_last_of("/");
6003 if (sep != std::string::npos)
6004 return GetLeafImpl(path.substr(0, sep).c_str(), name+sep+1);
6005
6006 return GetLeafImpl(nullptr, name);
6007}
6008
6009////////////////////////////////////////////////////////////////////////////////
6010/// Return maximum of column with name columname.
6011/// if the Tree has an associated TEventList or TEntryList, the maximum
6012/// is computed for the entries in this list.
6014Double_t TTree::GetMaximum(const char* columname)
6015{
6016 TLeaf* leaf = this->GetLeaf(columname);
6017 if (!leaf) {
6018 return 0;
6019 }
6020
6021 // create cache if wanted
6022 if (fCacheDoAutoInit)
6024
6025 TBranch* branch = leaf->GetBranch();
6026 Double_t cmax = -DBL_MAX;
6027 for (Long64_t i = 0; i < fEntries; ++i) {
6028 Long64_t entryNumber = this->GetEntryNumber(i);
6029 if (entryNumber < 0) break;
6030 branch->GetEntry(entryNumber);
6031 for (Int_t j = 0; j < leaf->GetLen(); ++j) {
6032 Double_t val = leaf->GetValue(j);
6033 if (val > cmax) {
6034 cmax = val;
6035 }
6036 }
6037 }
6038 return cmax;
6039}
6040
6041////////////////////////////////////////////////////////////////////////////////
6042/// Static function which returns the tree file size limit in bytes.
6045{
6046 return fgMaxTreeSize;
6047}
6048
6049////////////////////////////////////////////////////////////////////////////////
6050/// Return minimum of column with name columname.
6051/// if the Tree has an associated TEventList or TEntryList, the minimum
6052/// is computed for the entries in this list.
6054Double_t TTree::GetMinimum(const char* columname)
6055{
6056 TLeaf* leaf = this->GetLeaf(columname);
6057 if (!leaf) {
6058 return 0;
6059 }
6060
6061 // create cache if wanted
6062 if (fCacheDoAutoInit)
6064
6065 TBranch* branch = leaf->GetBranch();
6066 Double_t cmin = DBL_MAX;
6067 for (Long64_t i = 0; i < fEntries; ++i) {
6068 Long64_t entryNumber = this->GetEntryNumber(i);
6069 if (entryNumber < 0) break;
6070 branch->GetEntry(entryNumber);
6071 for (Int_t j = 0;j < leaf->GetLen(); ++j) {
6072 Double_t val = leaf->GetValue(j);
6073 if (val < cmin) {
6074 cmin = val;
6075 }
6076 }
6077 }
6078 return cmin;
6079}
6080
6081////////////////////////////////////////////////////////////////////////////////
6082/// Load the TTreePlayer (if not already done).
6085{
6086 if (fPlayer) {
6087 return fPlayer;
6088 }
6090 return fPlayer;
6091}
6092
6093////////////////////////////////////////////////////////////////////////////////
6094/// Find and return the TTreeCache registered with the file and which may
6095/// contain branches for us.
6098{
6099 TTreeCache *pe = dynamic_cast<TTreeCache*>(file->GetCacheRead(this));
6100 if (pe && pe->GetTree() != this)
6101 pe = nullptr;
6102 return pe;
6103}
6104
6105////////////////////////////////////////////////////////////////////////////////
6106/// Find and return the TTreeCache registered with the file and which may
6107/// contain branches for us. If create is true and there is no cache
6108/// a new cache is created with default size.
6111{
6113 if (create && !pe) {
6114 if (fCacheDoAutoInit)
6116 pe = dynamic_cast<TTreeCache*>(file->GetCacheRead(this));
6117 if (pe && pe->GetTree() != this) pe = 0;
6118 }
6119 return pe;
6120}
6121
6122////////////////////////////////////////////////////////////////////////////////
6123/// Return a pointer to the list containing user objects associated to this tree.
6124///
6125/// The list is automatically created if it does not exist.
6126///
6127/// WARNING: By default the TTree destructor will delete all objects added
6128/// to this list. If you do not want these objects to be deleted,
6129/// call:
6130///
6131/// mytree->GetUserInfo()->Clear();
6132///
6133/// before deleting the tree.
6136{
6137 if (!fUserInfo) {
6138 fUserInfo = new TList();
6139 fUserInfo->SetName("UserInfo");
6140 }
6141 return fUserInfo;
6142}
6143
6144////////////////////////////////////////////////////////////////////////////////
6145/// Appends the cluster range information stored in 'fromtree' to this tree,
6146/// including the value of fAutoFlush.
6147///
6148/// This is used when doing a fast cloning (by TTreeCloner).
6149/// See also fAutoFlush and fAutoSave if needed.
6151void TTree::ImportClusterRanges(TTree *fromtree)
6152{
6153 Long64_t autoflush = fromtree->GetAutoFlush();
6154 if (fromtree->fNClusterRange == 0 && fromtree->fAutoFlush == fAutoFlush) {
6155 // nothing to do
6156 } else if (fNClusterRange || fromtree->fNClusterRange) {
6157 Int_t newsize = fNClusterRange + 1 + fromtree->fNClusterRange;
6158 if (newsize > fMaxClusterRange) {
6159 if (fMaxClusterRange) {
6161 newsize*sizeof(Long64_t),fMaxClusterRange*sizeof(Long64_t));
6163 newsize*sizeof(Long64_t),fMaxClusterRange*sizeof(Long64_t));
6164 fMaxClusterRange = newsize;
6165 } else {
6166 fMaxClusterRange = newsize;
6169 }
6170 }
6171 if (fEntries) {
6175 }
6176 for (Int_t i = 0 ; i < fromtree->fNClusterRange; ++i) {
6180 }
6181 fAutoFlush = autoflush;
6182 } else {
6183 SetAutoFlush( autoflush );
6184 }
6185 Long64_t autosave = GetAutoSave();
6186 if (autoflush > 0 && autosave > 0) {
6187 SetAutoSave( autoflush*(autosave/autoflush) );
6188 }
6189}
6190
6191////////////////////////////////////////////////////////////////////////////////
6192/// Keep a maximum of fMaxEntries in memory.
6195{
6197 Long64_t maxEntries = fMaxEntries - (fMaxEntries / 10);
6198 for (Int_t i = 0; i < nb; ++i) {
6199 TBranch* branch = (TBranch*) fBranches.UncheckedAt(i);
6200 branch->KeepCircular(maxEntries);
6201 }
6202 if (fNClusterRange) {
6203 Long64_t entriesOffset = fEntries - maxEntries;
6204 Int_t oldsize = fNClusterRange;
6205 for(Int_t i = 0, j = 0; j < oldsize; ++j) {
6206 if (fClusterRangeEnd[j] > entriesOffset) {
6207 fClusterRangeEnd[i] = fClusterRangeEnd[j] - entriesOffset;
6208 ++i;
6209 } else {
6211 }
6212 }
6213 }
6214 fEntries = maxEntries;
6215 fReadEntry = -1;
6216}
6217
6218////////////////////////////////////////////////////////////////////////////////
6219/// Read in memory all baskets from all branches up to the limit of maxmemory bytes.
6220///
6221/// If maxmemory is non null and positive SetMaxVirtualSize is called
6222/// with this value. Default for maxmemory is 2000000000 (2 Gigabytes).
6223/// The function returns the total number of baskets read into memory
6224/// if negative an error occurred while loading the branches.
6225/// This method may be called to force branch baskets in memory
6226/// when random access to branch entries is required.
6227/// If random access to only a few branches is required, you should
6228/// call directly TBranch::LoadBaskets.
6231{
6232 if (maxmemory > 0) SetMaxVirtualSize(maxmemory);
6233
6234 TIter next(GetListOfLeaves());
6235 TLeaf *leaf;
6236 Int_t nimported = 0;
6237 while ((leaf=(TLeaf*)next())) {
6238 nimported += leaf->GetBranch()->LoadBaskets();//break;
6239 }
6240 return nimported;
6241}
6242
6243////////////////////////////////////////////////////////////////////////////////
6244/// Set current entry.
6245///
6246/// Returns -2 if entry does not exist (just as TChain::LoadTree()).
6247/// Returns -6 if an error occours in the notification callback (just as TChain::LoadTree()).
6248///
6249/// Note: This function is overloaded in TChain.
6250///
6253{
6254 // We already have been visited while recursively looking
6255 // through the friends tree, let return
6257 // We need to return a negative value to avoid a circular list of friend
6258 // to think that there is always an entry somewhere in the list.
6259 return -1;
6260 }
6261
6262 // create cache if wanted
6263 if (fCacheDoAutoInit && entry >=0)
6265
6266 if (fNotify) {
6267 if (fReadEntry < 0) {
6268 fNotify->Notify();
6269 }
6270 }
6271 fReadEntry = entry;
6272
6273 Bool_t friendHasEntry = kFALSE;
6274 if (fFriends) {
6275 // Set current entry in friends as well.
6276 //
6277 // An alternative would move this code to each of the
6278 // functions calling LoadTree (and to overload a few more).
6279 Bool_t needUpdate = kFALSE;
6280 {
6281 // This scope is need to insure the lock is released at the right time
6282 TIter nextf(fFriends);
6283 TFriendLock lock(this, kLoadTree);
6284 TFriendElement* fe = 0;
6285 while ((fe = (TFriendElement*) nextf())) {
6287 // This friend element was added by the chain that owns this
6288 // tree, the chain will deal with loading the correct entry.
6289 continue;
6290 }
6291 TTree* friendTree = fe->GetTree();
6292 if (friendTree == 0) {
6293 // Somehow we failed to retrieve the friend TTree.
6294 } else if (friendTree->IsA() == TTree::Class()) {
6295 // Friend is actually a tree.
6296 if (friendTree->LoadTreeFriend(entry, this) >= 0) {
6297 friendHasEntry = kTRUE;
6298 }
6299 } else {
6300 // Friend is actually a chain.
6301 // FIXME: This logic should be in the TChain override.
6302 Int_t oldNumber = friendTree->GetTreeNumber();
6303 if (friendTree->LoadTreeFriend(entry, this) >= 0) {
6304 friendHasEntry = kTRUE;
6305 }
6306 Int_t newNumber = friendTree->GetTreeNumber();
6307 if (oldNumber != newNumber) {
6308 // We can not just compare the tree pointers because they could be reused.
6309 // So we compare the tree number instead.
6310 needUpdate = kTRUE;
6311 }
6312 }
6313 } // for each friend
6314 }
6315 if (needUpdate) {
6316 //update list of leaves in all TTreeFormula of the TTreePlayer (if any)
6317 if (fPlayer) {
6319 }
6320 //Notify user if requested
6321 if (fNotify) {
6322 if(!fNotify->Notify()) return -6;
6323 }
6324 }
6325 }
6326
6327 if ((fReadEntry >= fEntries) && !friendHasEntry) {
6328 fReadEntry = -1;
6329 return -2;
6330 }
6331 return fReadEntry;
6332}
6333
6334////////////////////////////////////////////////////////////////////////////////
6335/// Load entry on behalf of our master tree, we may use an index.
6336///
6337/// Called by LoadTree() when the masterTree looks for the entry
6338/// number in a friend tree (us) corresponding to the passed entry
6339/// number in the masterTree.
6340///
6341/// If we have no index, our entry number and the masterTree entry
6342/// number are the same.
6343///
6344/// If we *do* have an index, we must find the (major, minor) value pair
6345/// in masterTree to locate our corresponding entry.
6346///
6348Long64_t TTree::LoadTreeFriend(Long64_t entry, TTree* masterTree)
6349{
6350 if (!fTreeIndex) {
6351 return LoadTree(entry);
6352 }
6353 return LoadTree(fTreeIndex->GetEntryNumberFriend(masterTree));
6354}
6355
6356////////////////////////////////////////////////////////////////////////////////
6357/// Generate a skeleton analysis class for this tree.
6358///
6359/// The following files are produced: classname.h and classname.C.
6360/// If classname is 0, classname will be called "nameoftree".
6361///
6362/// The generated code in classname.h includes the following:
6363///
6364/// - Identification of the original tree and the input file name.
6365/// - Definition of an analysis class (data members and member functions).
6366/// - The following member functions:
6367/// - constructor (by default opening the tree file),
6368/// - GetEntry(Long64_t entry),
6369/// - Init(TTree* tree) to initialize a new TTree,
6370/// - Show(Long64_t entry) to read and dump entry.
6371///
6372/// The generated code in classname.C includes only the main
6373/// analysis function Loop.
6374///
6375/// To use this function:
6376///
6377/// - Open your tree file (eg: TFile f("myfile.root");)
6378/// - T->MakeClass("MyClass");
6379///
6380/// where T is the name of the TTree in file myfile.root,
6381/// and MyClass.h, MyClass.C the name of the files created by this function.
6382/// In a ROOT session, you can do:
6383/// ~~~ {.cpp}
6384/// root > .L MyClass.C
6385/// root > MyClass* t = new MyClass;
6386/// root > t->GetEntry(12); // Fill data members of t with entry number 12.
6387/// root > t->Show(); // Show values of entry 12.
6388/// root > t->Show(16); // Read and show values of entry 16.
6389/// root > t->Loop(); // Loop on all entries.
6390/// ~~~
6391/// NOTE: Do not use the code generated for a single TTree which is part
6392/// of a TChain to process that entire TChain. The maximum dimensions
6393/// calculated for arrays on the basis of a single TTree from the TChain
6394/// might be (will be!) too small when processing all of the TTrees in
6395/// the TChain. You must use myChain.MakeClass() to generate the code,
6396/// not myTree.MakeClass(...).
6398Int_t TTree::MakeClass(const char* classname, Option_t* option)
6399{
6400 GetPlayer();
6401 if (!fPlayer) {
6402 return 0;
6403 }
6404 return fPlayer->MakeClass(classname, option);
6405}
6406
6407////////////////////////////////////////////////////////////////////////////////
6408/// Generate a skeleton function for this tree.
6409///
6410/// The function code is written on filename.
6411/// If filename is 0, filename will be called nameoftree.C
6412///
6413/// The generated code includes the following:
6414/// - Identification of the original Tree and Input file name,
6415/// - Opening the Tree file,
6416/// - Declaration of Tree variables,
6417/// - Setting of branches addresses,
6418/// - A skeleton for the entry loop.
6419///
6420/// To use this function:
6421///
6422/// - Open your Tree file (eg: TFile f("myfile.root");)
6423/// - T->MakeCode("MyAnalysis.C");
6424///
6425/// where T is the name of the TTree in file myfile.root
6426/// and MyAnalysis.C the name of the file created by this function.
6427///
6428/// NOTE: Since the implementation of this function, a new and better
6429/// function TTree::MakeClass() has been developed.
6431Int_t TTree::MakeCode(const char* filename)
6432{
6433 Warning("MakeCode", "MakeCode is obsolete. Use MakeClass or MakeSelector instead");
6434
6435 GetPlayer();
6436 if (!fPlayer) return 0;
6437 return fPlayer->MakeCode(filename);
6438}
6439
6440////////////////////////////////////////////////////////////////////////////////
6441/// Generate a skeleton analysis class for this Tree using TBranchProxy.
6442///
6443/// TBranchProxy is the base of a class hierarchy implementing an
6444/// indirect access to the content of the branches of a TTree.
6445///
6446/// "proxyClassname" is expected to be of the form:
6447/// ~~~ {.cpp}
6448/// [path/]fileprefix
6449/// ~~~
6450/// The skeleton will then be generated in the file:
6451/// ~~~ {.cpp}
6452/// fileprefix.h
6453/// ~~~
6454/// located in the current directory or in 'path/' if it is specified.
6455/// The class generated will be named 'fileprefix'
6456///
6457/// "macrofilename" and optionally "cutfilename" are expected to point
6458/// to source files which will be included by the generated skeleton.
6459/// Method of the same name as the file(minus the extension and path)
6460/// will be called by the generated skeleton's Process method as follow:
6461/// ~~~ {.cpp}
6462/// [if (cutfilename())] htemp->Fill(macrofilename());
6463/// ~~~
6464/// "option" can be used select some of the optional features during
6465/// the code generation. The possible options are:
6466///
6467/// - nohist : indicates that the generated ProcessFill should not fill the histogram.
6468///
6469/// 'maxUnrolling' controls how deep in the class hierarchy does the
6470/// system 'unroll' classes that are not split. Unrolling a class
6471/// allows direct access to its data members (this emulates the behavior
6472/// of TTreeFormula).
6473///
6474/// The main features of this skeleton are:
6475///
6476/// * on-demand loading of branches
6477/// * ability to use the 'branchname' as if it was a data member
6478/// * protection against array out-of-bounds errors
6479/// * ability to use the branch data as an object (when the user code is available)
6480///
6481/// For example with Event.root, if
6482/// ~~~ {.cpp}
6483/// Double_t somePx = fTracks.fPx[2];
6484/// ~~~
6485/// is executed by one of the method of the skeleton,
6486/// somePx will updated with the current value of fPx of the 3rd track.
6487///
6488/// Both macrofilename and the optional cutfilename are expected to be
6489/// the name of source files which contain at least a free standing
6490/// function with the signature:
6491/// ~~~ {.cpp}
6492/// x_t macrofilename(); // i.e function with the same name as the file
6493/// ~~~
6494/// and
6495/// ~~~ {.cpp}
6496/// y_t cutfilename(); // i.e function with the same name as the file
6497/// ~~~
6498/// x_t and y_t needs to be types that can convert respectively to a double
6499/// and a bool (because the skeleton uses:
6500///
6501/// if (cutfilename()) htemp->Fill(macrofilename());
6502///
6503/// These two functions are run in a context such that the branch names are
6504/// available as local variables of the correct (read-only) type.
6505///
6506/// Note that if you use the same 'variable' twice, it is more efficient
6507/// to 'cache' the value. For example:
6508/// ~~~ {.cpp}
6509/// Int_t n = fEventNumber; // Read fEventNumber
6510/// if (n<10 || n>10) { ... }
6511/// ~~~
6512/// is more efficient than
6513/// ~~~ {.cpp}
6514/// if (fEventNumber<10 || fEventNumber>10)
6515/// ~~~
6516/// Also, optionally, the generated selector will also call methods named
6517/// macrofilename_methodname in each of 6 main selector methods if the method
6518/// macrofilename_methodname exist (Where macrofilename is stripped of its
6519/// extension).
6520///
6521/// Concretely, with the script named h1analysisProxy.C,
6522///
6523/// - The method calls the method (if it exist)
6524/// - Begin -> void h1analysisProxy_Begin(TTree*);
6525/// - SlaveBegin -> void h1analysisProxy_SlaveBegin(TTree*);
6526/// - Notify -> Bool_t h1analysisProxy_Notify();
6527/// - Process -> Bool_t h1analysisProxy_Process(Long64_t);
6528/// - SlaveTerminate -> void h1analysisProxy_SlaveTerminate();
6529/// - Terminate -> void h1analysisProxy_Terminate();
6530///
6531/// If a file name macrofilename.h (or .hh, .hpp, .hxx, .hPP, .hXX) exist
6532/// it is included before the declaration of the proxy class. This can
6533/// be used in particular to insure that the include files needed by
6534/// the macro file are properly loaded.
6535///
6536/// The default histogram is accessible via the variable named 'htemp'.
6537///
6538/// If the library of the classes describing the data in the branch is
6539/// loaded, the skeleton will add the needed `include` statements and
6540/// give the ability to access the object stored in the branches.
6541///
6542/// To draw px using the file hsimple.root (generated by the
6543/// hsimple.C tutorial), we need a file named hsimple.cxx:
6544/// ~~~ {.cpp}
6545/// double hsimple() {
6546/// return px;
6547/// }
6548/// ~~~
6549/// MakeProxy can then be used indirectly via the TTree::Draw interface
6550/// as follow:
6551/// ~~~ {.cpp}
6552/// new TFile("hsimple.root")
6553/// ntuple->Draw("hsimple.cxx");
6554/// ~~~
6555/// A more complete example is available in the tutorials directory:
6556/// h1analysisProxy.cxx , h1analysProxy.h and h1analysisProxyCut.C
6557/// which reimplement the selector found in h1analysis.C
6559Int_t TTree::MakeProxy(const char* proxyClassname, const char* macrofilename, const char* cutfilename, const char* option, Int_t maxUnrolling)
6560{
6561 GetPlayer();
6562 if (!fPlayer) return 0;
6563 return fPlayer->MakeProxy(proxyClassname,macrofilename,cutfilename,option,maxUnrolling);
6564}
6565
6566////////////////////////////////////////////////////////////////////////////////
6567/// Generate skeleton selector class for this tree.
6568///
6569/// The following files are produced: selector.h and selector.C.
6570/// If selector is 0, the selector will be called "nameoftree".
6571/// The option can be used to specify the branches that will have a data member.
6572/// - If option is "=legacy", a pre-ROOT6 selector will be generated (data
6573/// members and branch pointers instead of TTreeReaders).
6574/// - If option is empty, readers will be generated for each leaf.
6575/// - If option is "@", readers will be generated for the topmost branches.
6576/// - Individual branches can also be picked by their name:
6577/// - "X" generates readers for leaves of X.
6578/// - "@X" generates a reader for X as a whole.
6579/// - "@X;Y" generates a reader for X as a whole and also readers for the
6580/// leaves of Y.
6581/// - For further examples see the figure below.
6582///
6583/// \image html ttree_makeselector_option_examples.png
6584///
6585/// The generated code in selector.h includes the following:
6586/// - Identification of the original Tree and Input file name
6587/// - Definition of selector class (data and functions)
6588/// - The following class functions:
6589/// - constructor and destructor
6590/// - void Begin(TTree *tree)
6591/// - void SlaveBegin(TTree *tree)
6592/// - void Init(TTree *tree)
6593/// - Bool_t Notify()
6594/// - Bool_t Process(Long64_t entry)
6595/// - void Terminate()
6596/// - void SlaveTerminate()
6597///
6598/// The class selector derives from TSelector.
6599/// The generated code in selector.C includes empty functions defined above.
6600///
6601/// To use this function:
6602///
6603/// - connect your Tree file (eg: `TFile f("myfile.root");`)
6604/// - `T->MakeSelector("myselect");`
6605///
6606/// where T is the name of the Tree in file myfile.root
6607/// and myselect.h, myselect.C the name of the files created by this function.
6608/// In a ROOT session, you can do:
6609/// ~~~ {.cpp}
6610/// root > T->Process("myselect.C")
6611/// ~~~
6613Int_t TTree::MakeSelector(const char* selector, Option_t* option)
6614{
6615 TString opt(option);
6616 if(opt.EqualTo("=legacy", TString::ECaseCompare::kIgnoreCase)) {
6617 return MakeClass(selector, "selector");
6618 } else {
6619 GetPlayer();
6620 if (!fPlayer) return 0;
6621 return fPlayer->MakeReader(selector, option);
6622 }
6623}
6624
6625////////////////////////////////////////////////////////////////////////////////
6626/// Check if adding nbytes to memory we are still below MaxVirtualsize.
6629{
6630 if ((fTotalBuffers + nbytes) < fMaxVirtualSize) {
6631 return kFALSE;
6632 }
6633 return kTRUE;
6634}
6635
6636////////////////////////////////////////////////////////////////////////////////
6637/// Static function merging the trees in the TList into a new tree.
6638///
6639/// Trees in the list can be memory or disk-resident trees.
6640/// The new tree is created in the current directory (memory if gROOT).
6642TTree* TTree::MergeTrees(TList* li, Option_t* options)
6643{
6644 if (!li) return 0;
6645 TIter next(li);
6646 TTree *newtree = 0;
6647 TObject *obj;
6648
6649 while ((obj=next())) {
6650 if (!obj->InheritsFrom(TTree::Class())) continue;
6651 TTree *tree = (TTree*)obj;
6652 Long64_t nentries = tree->GetEntries();
6653 if (nentries == 0) continue;
6654 if (!newtree) {
6655 newtree = (TTree*)tree->CloneTree();
6656 if (!newtree) continue;
6657
6658 // Once the cloning is done, separate the trees,
6659 // to avoid as many side-effects as possible
6660 // The list of clones is guaranteed to exist since we
6661 // just cloned the tree.
6662 tree->GetListOfClones()->Remove(newtree);
6663 tree->ResetBranchAddresses();
6664 newtree->ResetBranchAddresses();
6665 continue;
6666 }
6667
6668 newtree->CopyAddresses(tree);
6669
6670 newtree->CopyEntries(tree,-1,options);
6671
6672 tree->ResetBranchAddresses(); // Disconnect from new tree.
6673 }
6674 if (newtree && newtree->GetTreeIndex()) {
6675 newtree->GetTreeIndex()->Append(0,kFALSE); // Force the sorting
6676 }
6677 return newtree;
6678}
6679
6680////////////////////////////////////////////////////////////////////////////////
6681/// Merge the trees in the TList into this tree.
6682///
6683/// Returns the total number of entries in the merged tree.
6686{
6687 if (!li) return 0;
6688 Long64_t storeAutoSave = fAutoSave;
6689 // Disable the autosave as the TFileMerge keeps a list of key and deleting the underlying
6690 // key would invalidate its iteration (or require costly measure to not use the deleted keys).
6691 // Also since this is part of a merging operation, the output file is not as precious as in
6692 // the general case since the input file should still be around.
6693 fAutoSave = 0;
6694 TIter next(li);
6695 TTree *tree;
6696 while ((tree = (TTree*)next())) {
6697 if (tree==this) continue;
6698 if (!tree->InheritsFrom(TTree::Class())) {
6699 Error("Add","Attempt to add object of class: %s to a %s", tree->ClassName(), ClassName());
6700 fAutoSave = storeAutoSave;
6701 return -1;
6702 }
6703
6704 Long64_t nentries = tree->GetEntries();
6705 if (nentries == 0) continue;
6706
6708
6709 CopyEntries(tree,-1,options);
6710
6711 tree->ResetBranchAddresses();
6712 }
6713 fAutoSave = storeAutoSave;
6714 return GetEntries();
6715}
6716
6717////////////////////////////////////////////////////////////////////////////////
6718/// Merge the trees in the TList into this tree.
6719/// If info->fIsFirst is true, first we clone this TTree info the directory
6720/// info->fOutputDirectory and then overlay the new TTree information onto
6721/// this TTree object (so that this TTree object is now the appropriate to
6722/// use for further merging).
6723///
6724/// Returns the total number of entries in the merged tree.
6727{
6728 const char *options = info ? info->fOptions.Data() : "";
6729 if (info && info->fIsFirst && info->fOutputDirectory && info->fOutputDirectory->GetFile() != GetCurrentFile()) {
6731 TIOFeatures saved_features = fIOFeatures;
6732 if (info->fIOFeatures) {
6733 fIOFeatures = *(info->fIOFeatures);
6734 }
6735 TTree *newtree = CloneTree(-1, options);
6736 fIOFeatures = saved_features;
6737 if (newtree) {
6738 newtree->Write();
6739 delete newtree;
6740 }
6741 // Make sure things are really written out to disk before attempting any reading.
6742 info->fOutputDirectory->GetFile()->Flush();
6743 info->fOutputDirectory->ReadTObject(this,this->GetName());
6744 }
6745 if (!li) return 0;
6746 Long64_t storeAutoSave = fAutoSave;
6747 // Disable the autosave as the TFileMerge keeps a list of key and deleting the underlying
6748 // key would invalidate its iteration (or require costly measure to not use the deleted keys).
6749 // Also since this is part of a merging operation, the output file is not as precious as in
6750 // the general case since the input file should still be around.
6751 fAutoSave = 0;
6752 TIter next(li);
6753 TTree *tree;
6754 while ((tree = (TTree*)next())) {
6755 if (tree==this) continue;
6756 if (!tree->InheritsFrom(TTree::Class())) {
6757 Error("Add","Attempt to add object of class: %s to a %s", tree->ClassName(), ClassName());
6758 fAutoSave = storeAutoSave;
6759 return -1;
6760 }
6761 // Copy MakeClass status.
6762 tree->SetMakeClass(fMakeClass);
6763
6764 // Copy branch addresses.
6766
6767 CopyEntries(tree,-1,options);
6768
6769 tree->ResetBranchAddresses();
6770 }
6771 fAutoSave = storeAutoSave;
6772 return GetEntries();
6773}
6774
6775////////////////////////////////////////////////////////////////////////////////
6776/// Move a cache from a file to the current file in dir.
6777/// if src is null no operation is done, if dir is null or there is no
6778/// current file the cache is deleted.
6780void TTree::MoveReadCache(TFile *src, TDirectory *dir)
6781{
6782 if (!src) return;
6783 TFile *dst = (dir && dir != gROOT) ? dir->GetFile() : 0;
6784 if (src == dst) return;
6785
6786 TTreeCache *pf = GetReadCache(src);
6787 if (dst) {
6788 src->SetCacheRead(0,this);
6789 dst->SetCacheRead(pf, this);
6790 } else {
6791 if (pf) {
6792 pf->WaitFinishPrefetch();
6793 }
6794 src->SetCacheRead(0,this);
6795 delete pf;
6796 }
6797}
6798
6799////////////////////////////////////////////////////////////////////////////////
6800/// Function called when loading a new class library.
6803{
6804 TIter next(GetListOfLeaves());
6805 TLeaf* leaf = 0;
6806 while ((leaf = (TLeaf*) next())) {
6807 leaf->Notify();
6808 leaf->GetBranch()->Notify();
6809 }
6810 return kTRUE;
6811}
6812
6813////////////////////////////////////////////////////////////////////////////////
6814/// This function may be called after having filled some entries in a Tree.
6815/// Using the information in the existing branch buffers, it will reassign
6816/// new branch buffer sizes to optimize time and memory.
6817///
6818/// The function computes the best values for branch buffer sizes such that
6819/// the total buffer sizes is less than maxMemory and nearby entries written
6820/// at the same time.
6821/// In case the branch compression factor for the data written so far is less
6822/// than compMin, the compression is disabled.
6823///
6824/// if option ="d" an analysis report is printed.
6826void TTree::OptimizeBaskets(ULong64_t maxMemory, Float_t minComp, Option_t *option)
6827{
6828 //Flush existing baskets if the file is writable
6829 if (this->GetDirectory()->IsWritable()) this->FlushBasketsImpl();
6830
6831 TString opt( option );
6832 opt.ToLower();
6833 Bool_t pDebug = opt.Contains("d");
6834 TObjArray *leaves = this->GetListOfLeaves();
6835 Int_t nleaves = leaves->GetEntries();
6836 Double_t treeSize = (Double_t)this->GetTotBytes();
6837
6838 if (nleaves == 0 || treeSize == 0) {
6839 // We're being called too early, we really have nothing to do ...
6840 return;
6841 }
6842 Double_t aveSize = treeSize/nleaves;
6843 UInt_t bmin = 512;
6844 UInt_t bmax = 256000;
6845 Double_t memFactor = 1;
6846 Int_t i, oldMemsize,newMemsize,oldBaskets,newBaskets;
6847 i = oldMemsize = newMemsize = oldBaskets = newBaskets = 0;
6848
6849 //we make two passes
6850 //one pass to compute the relative branch buffer sizes
6851 //a second pass to compute the absolute values
6852 for (Int_t pass =0;pass<2;pass++) {
6853 oldMemsize = 0; //to count size of baskets in memory with old buffer size
6854 newMemsize = 0; //to count size of baskets in memory with new buffer size
6855 oldBaskets = 0; //to count number of baskets with old buffer size
6856 newBaskets = 0; //to count number of baskets with new buffer size
6857 for (i=0;i<nleaves;i++) {
6858 TLeaf *leaf = (TLeaf*)leaves->At(i);
6859 TBranch *branch = leaf->GetBranch();
6860 Double_t totBytes = (Double_t)branch->GetTotBytes();
6861 Double_t idealFactor = totBytes/aveSize;
6862 UInt_t sizeOfOneEntry;
6863 if (branch->GetEntries() == 0) {
6864 // There is no data, so let's make a guess ...
6865 sizeOfOneEntry = aveSize;
6866 } else {
6867 sizeOfOneEntry = 1+(UInt_t)(totBytes / (Double_t)branch->GetEntries());
6868 }
6869 Int_t oldBsize = branch->GetBasketSize();
6870 oldMemsize += oldBsize;
6871 oldBaskets += 1+Int_t(totBytes/oldBsize);
6872 Int_t nb = branch->GetListOfBranches()->GetEntries();
6873 if (nb > 0) {
6874 newBaskets += 1+Int_t(totBytes/oldBsize);
6875 continue;
6876 }
6877 Double_t bsize = oldBsize*idealFactor*memFactor; //bsize can be very large !
6878 if (bsize < 0) bsize = bmax;
6879 if (bsize > bmax) bsize = bmax;
6880 UInt_t newBsize = UInt_t(bsize);
6881 if (pass) { // only on the second pass so that it doesn't interfere with scaling
6882 // If there is an entry offset, it will be stored in the same buffer as the object data; hence,
6883 // we must bump up the size of the branch to account for this extra footprint.
6884 // If fAutoFlush is not set yet, let's assume that it is 'in the process of being set' to
6885 // the value of GetEntries().
6886 Long64_t clusterSize = (fAutoFlush > 0) ? fAutoFlush : branch->GetEntries();
6887 if (branch->GetEntryOffsetLen()) {
6888 newBsize = newBsize + (clusterSize * sizeof(Int_t) * 2);
6889 }
6890 // We used ATLAS fully-split xAOD for testing, which is a rather unbalanced TTree, 10K branches,
6891 // with 8K having baskets smaller than 512 bytes. To achieve good I/O performance ATLAS uses auto-flush 100,
6892 // resulting in the smallest baskets being ~300-400 bytes, so this change increases their memory by about 8k*150B =~ 1MB,
6893 // at the same time it significantly reduces the number of total baskets because it ensures that all 100 entries can be
6894 // stored in a single basket (the old optimization tended to make baskets too small). In a toy example with fixed sized
6895 // structures we found a factor of 2 fewer baskets needed in the new scheme.
6896 // rounds up, increases basket size to ensure all entries fit into single basket as intended
6897 newBsize = newBsize - newBsize%512 + 512;
6898 }
6899 if (newBsize < sizeOfOneEntry) newBsize = sizeOfOneEntry;
6900 if (newBsize < bmin) newBsize = bmin;
6901 if (newBsize > 10000000) newBsize = bmax;
6902 if (pass) {
6903 if (pDebug) Info("OptimizeBaskets", "Changing buffer size from %6d to %6d bytes for %s\n",oldBsize,newBsize,branch->GetName());
6904 branch->SetBasketSize(newBsize);
6905 }
6906 newMemsize += newBsize;
6907 // For this number to be somewhat accurate when newBsize is 'low'
6908 // we do not include any space for meta data in the requested size (newBsize) even-though SetBasketSize will
6909 // not let it be lower than 100+TBranch::fEntryOffsetLen.
6910 newBaskets += 1+Int_t(totBytes/newBsize);
6911 if (pass == 0) continue;
6912 //Reset the compression level in case the compression factor is small
6913 Double_t comp = 1;
6914 if (branch->GetZipBytes() > 0) comp = totBytes/Double_t(branch->GetZipBytes());
6915 if (comp > 1 && comp < minComp) {
6916 if (pDebug) Info("OptimizeBaskets", "Disabling compression for branch : %s\n",branch->GetName());
6918 }
6919 }
6920 // coverity[divide_by_zero] newMemsize can not be zero as there is at least one leaf
6921 memFactor = Double_t(maxMemory)/Double_t(newMemsize);
6922 if (memFactor > 100) memFactor = 100;
6923 Double_t bmin_new = bmin*memFactor;
6924 Double_t bmax_new = bmax*memFactor;
6925 static const UInt_t hardmax = 1*1024*1024*1024; // Really, really never give more than 1Gb to a single buffer.
6926
6927 // Really, really never go lower than 8 bytes (we use this number
6928 // so that the calculation of the number of basket is consistent
6929 // but in fact SetBasketSize will not let the size go below
6930 // TBranch::fEntryOffsetLen + (100 + strlen(branch->GetName())
6931 // (The 2nd part being a slight over estimate of the key length.
6932 static const UInt_t hardmin = 8;
6933 bmin = (bmin_new > hardmax) ? hardmax : ( bmin_new < hardmin ? hardmin : (UInt_t)bmin_new );
6934 bmax = (bmax_new > hardmax) ? bmin : (UInt_t)bmax_new;
6935 }
6936 if (pDebug) {
6937 Info("OptimizeBaskets", "oldMemsize = %d, newMemsize = %d\n",oldMemsize, newMemsize);
6938 Info("OptimizeBaskets", "oldBaskets = %d, newBaskets = %d\n",oldBaskets, newBaskets);
6939 }
6940}
6941
6942////////////////////////////////////////////////////////////////////////////////
6943/// Interface to the Principal Components Analysis class.
6944///
6945/// Create an instance of TPrincipal
6946///
6947/// Fill it with the selected variables
6948///
6949/// - if option "n" is specified, the TPrincipal object is filled with
6950/// normalized variables.
6951/// - If option "p" is specified, compute the principal components
6952/// - If option "p" and "d" print results of analysis
6953/// - If option "p" and "h" generate standard histograms
6954/// - If option "p" and "c" generate code of conversion functions
6955/// - return a pointer to the TPrincipal object. It is the user responsibility
6956/// - to delete this object.
6957/// - The option default value is "np"
6958///
6959/// see TTree::Draw for explanation of the other parameters.
6960///
6961/// The created object is named "principal" and a reference to it
6962/// is added to the list of specials Root objects.
6963/// you can retrieve a pointer to the created object via:
6964/// ~~~ {.cpp}
6965/// TPrincipal *principal =
6966/// (TPrincipal*)gROOT->GetListOfSpecials()->FindObject("principal");
6967/// ~~~
6969TPrincipal* TTree::Principal(const char* varexp, const char* selection, Option_t* option, Long64_t nentries, Long64_t firstentry)
6970{
6971 GetPlayer();
6972 if (fPlayer) {
6973 return fPlayer->Principal(varexp, selection, option, nentries, firstentry);
6974 }
6975 return 0;
6976}
6977
6978////////////////////////////////////////////////////////////////////////////////
6979/// Print a summary of the tree contents.
6980///
6981/// - If option contains "all" friend trees are also printed.
6982/// - If option contains "toponly" only the top level branches are printed.
6983/// - If option contains "clusters" information about the cluster of baskets is printed.
6984///
6985/// Wildcarding can be used to print only a subset of the branches, e.g.,
6986/// `T.Print("Elec*")` will print all branches with name starting with "Elec".
6988void TTree::Print(Option_t* option) const
6989{
6990 // We already have been visited while recursively looking
6991 // through the friends tree, let's return.
6992 if (kPrint & fFriendLockStatus) {
6993 return;
6994 }
6995 Int_t s = 0;
6996 Int_t skey = 0;
6997 if (fDirectory) {
6998 TKey* key = fDirectory->GetKey(GetName());
6999 if (key) {
7000 skey = key->GetKeylen();
7001 s = key->GetNbytes();
7002 }
7003 }
7004 Long64_t total = skey;
7005 Long64_t zipBytes = GetZipBytes();
7006 if (zipBytes > 0) {
7007 total += GetTotBytes();
7008 }
7010 TTree::Class()->WriteBuffer(b, (TTree*) this);
7011 total += b.Length();
7012 Long64_t file = zipBytes + s;
7013 Float_t cx = 1;
7014 if (zipBytes) {
7015 cx = (GetTotBytes() + 0.00001) / zipBytes;
7016 }
7017 Printf("******************************************************************************");
7018 Printf("*Tree :%-10s: %-54s *", GetName(), GetTitle());
7019 Printf("*Entries : %8lld : Total = %15lld bytes File Size = %10lld *", fEntries, total, file);
7020 Printf("* : : Tree compression factor = %6.2f *", cx);
7021 Printf("******************************************************************************");
7022
7023 // Avoid many check of option validity
7024 if (option == nullptr)
7025 option = "";
7026
7027 if (strncmp(option,"clusters",strlen("clusters"))==0) {
7028 Printf("%-16s %-16s %-16s %5s",
7029 "Cluster Range #", "Entry Start", "Last Entry", "Size");
7030 Int_t index= 0;
7031 Long64_t clusterRangeStart = 0;
7032 if (fNClusterRange) {
7033 for( ; index < fNClusterRange; ++index) {
7034 Printf("%-16d %-16lld %-16lld %5lld",
7035 index, clusterRangeStart, fClusterRangeEnd[index], fClusterSize[index]);
7036 clusterRangeStart = fClusterRangeEnd[index] + 1;
7037 }
7038 }
7039 Printf("%-16d %-16lld %-16lld %5lld",
7040 index, clusterRangeStart, fEntries - 1, fAutoFlush);
7041 return;
7042 }
7043
7044 Int_t nl = const_cast<TTree*>(this)->GetListOfLeaves()->GetEntries();
7045 Int_t l;
7046 TBranch* br = 0;
7047 TLeaf* leaf = 0;
7048 if (strstr(option, "toponly")) {
7049 Long64_t *count = new Long64_t[nl];
7050 Int_t keep =0;
7051 for (l=0;l<nl;l++) {
7052 leaf = (TLeaf *)const_cast<TTree*>(this)->GetListOfLeaves()->At(l);
7053 br = leaf->GetBranch();
7054 if (strchr(br->GetName(),'.')) {
7055 count[l] = -1;
7056 count[keep] += br->GetZipBytes();
7057 } else {
7058 keep = l;
7059 count[keep] = br->GetZipBytes();
7060 }
7061 }
7062 for (l=0;l<nl;l++) {
7063 if (count[l] < 0) continue;
7064 leaf = (TLeaf *)const_cast<TTree*>(this)->GetListOfLeaves()->At(l);
7065 br = leaf->GetBranch();
7066 Printf("branch: %-20s %9lld\n",br->GetName(),count[l]);
7067 }
7068 delete [] count;
7069 } else {
7070 TString reg = "*";
7071 if (strlen(option) && strchr(option,'*')) reg = option;
7072 TRegexp re(reg,kTRUE);
7073 TIter next(const_cast<TTree*>(this)->GetListOfBranches());
7075 while ((br= (TBranch*)next())) {
7076 TString st = br->GetName();
7077 st.ReplaceAll("/","_");
7078 if (st.Index(re) == kNPOS) continue;
7079 br->Print(option);
7080 }
7081 }
7082
7083 //print TRefTable (if one)
7084 if (fBranchRef) fBranchRef->Print(option);
7085
7086 //print friends if option "all"
7087 if (!fFriends || !strstr(option,"all")) return;
7088 TIter nextf(fFriends);
7089 TFriendLock lock(const_cast<TTree*>(this),kPrint);
7090 TFriendElement *fr;
7091 while ((fr = (TFriendElement*)nextf())) {
7092 TTree * t = fr->GetTree();
7093 if (t) t->Print(option);
7094 }
7095}
7096
7097////////////////////////////////////////////////////////////////////////////////
7098/// Print statistics about the TreeCache for this tree.
7099/// Like:
7100/// ~~~ {.cpp}
7101/// ******TreeCache statistics for file: cms2.root ******
7102/// Reading 73921562 bytes in 716 transactions
7103/// Average transaction = 103.242405 Kbytes
7104/// Number of blocks in current cache: 202, total size : 6001193
7105/// ~~~
7106/// if option = "a" the list of blocks in the cache is printed
7108void TTree::PrintCacheStats(Option_t* option) const
7109{
7110 TFile *f = GetCurrentFile();
7111 if (!f) return;
7112 TTreeCache *tc = GetReadCache(f);
7113 if (tc) tc->Print(option);
7114}
7115
7116////////////////////////////////////////////////////////////////////////////////
7117/// Process this tree executing the TSelector code in the specified filename.
7118/// The return value is -1 in case of error and TSelector::GetStatus() in
7119/// in case of success.
7120///
7121/// The code in filename is loaded (interpreted or compiled, see below),
7122/// filename must contain a valid class implementation derived from TSelector,
7123/// where TSelector has the following member functions:
7124///
7125/// - `Begin()`: called every time a loop on the tree starts,
7126/// a convenient place to create your histograms.
7127/// - `SlaveBegin()`: called after Begin(), when on PROOF called only on the
7128/// slave servers.
7129/// - `Process()`: called for each event, in this function you decide what
7130/// to read and fill your histograms.
7131/// - `SlaveTerminate`: called at the end of the loop on the tree, when on PROOF
7132/// called only on the slave servers.
7133/// - `Terminate()`: called at the end of the loop on the tree,
7134/// a convenient place to draw/fit your histograms.
7135///
7136/// If filename is of the form file.C, the file will be interpreted.
7137///
7138/// If filename is of the form file.C++, the file file.C will be compiled
7139/// and dynamically loaded.
7140///
7141/// If filename is of the form file.C+, the file file.C will be compiled
7142/// and dynamically loaded. At next call, if file.C is older than file.o
7143/// and file.so, the file.C is not compiled, only file.so is loaded.
7144///
7145/// ## NOTE1
7146///
7147/// It may be more interesting to invoke directly the other Process function
7148/// accepting a TSelector* as argument.eg
7149/// ~~~ {.cpp}
7150/// MySelector *selector = (MySelector*)TSelector::GetSelector(filename);
7151/// selector->CallSomeFunction(..);
7152/// mytree.Process(selector,..);
7153/// ~~~
7154/// ## NOTE2
7155//
7156/// One should not call this function twice with the same selector file
7157/// in the same script. If this is required, proceed as indicated in NOTE1,
7158/// by getting a pointer to the corresponding TSelector,eg
7159///
7160/// ### Workaround 1
7161///
7162/// ~~~ {.cpp}
7163/// void stubs1() {
7164/// TSelector *selector = TSelector::GetSelector("h1test.C");
7165/// TFile *f1 = new TFile("stubs_nood_le1.root");
7166/// TTree *h1 = (TTree*)f1->Get("h1");
7167/// h1->Process(selector);
7168/// TFile *f2 = new TFile("stubs_nood_le1_coarse.root");
7169/// TTree *h2 = (TTree*)f2->Get("h1");
7170/// h2->Process(selector);
7171/// }
7172/// ~~~
7173/// or use ACLIC to compile the selector
7174///
7175/// ### Workaround 2
7176///
7177/// ~~~ {.cpp}
7178/// void stubs2() {
7179/// TFile *f1 = new TFile("stubs_nood_le1.root");
7180/// TTree *h1 = (TTree*)f1->Get("h1");
7181/// h1->Process("h1test.C+");
7182/// TFile *f2 = new TFile("stubs_nood_le1_coarse.root");
7183/// TTree *h2 = (TTree*)f2->Get("h1");
7184/// h2->Process("h1test.C+");
7185/// }
7186/// ~~~
7188Long64_t TTree::Process(const char* filename, Option_t* option, Long64_t nentries, Long64_t firstentry)
7189{
7190 GetPlayer();
7191 if (fPlayer) {
7192 return fPlayer->Process(filename, option, nentries, firstentry);
7193 }
7194 return -1;
7195}
7196
7197////////////////////////////////////////////////////////////////////////////////
7198/// Process this tree executing the code in the specified selector.
7199/// The return value is -1 in case of error and TSelector::GetStatus() in
7200/// in case of success.
7201///
7202/// The TSelector class has the following member functions:
7203///
7204/// - `Begin()`: called every time a loop on the tree starts,
7205/// a convenient place to create your histograms.
7206/// - `SlaveBegin()`: called after Begin(), when on PROOF called only on the
7207/// slave servers.
7208/// - `Process()`: called for each event, in this function you decide what
7209/// to read and fill your histograms.
7210/// - `SlaveTerminate`: called at the end of the loop on the tree, when on PROOF
7211/// called only on the slave servers.
7212/// - `Terminate()`: called at the end of the loop on the tree,
7213/// a convenient place to draw/fit your histograms.
7214///
7215/// If the Tree (Chain) has an associated EventList, the loop is on the nentries
7216/// of the EventList, starting at firstentry, otherwise the loop is on the
7217/// specified Tree entries.
7219Long64_t TTree::Process(TSelector* selector, Option_t* option, Long64_t nentries, Long64_t firstentry)
7220{
7221 GetPlayer();
7222 if (fPlayer) {
7223 return fPlayer->Process(selector, option, nentries, firstentry);
7224 }
7225 return -1;
7226}
7227
7228////////////////////////////////////////////////////////////////////////////////
7229/// Make a projection of a tree using selections.
7230///
7231/// Depending on the value of varexp (described in Draw) a 1-D, 2-D, etc.,
7232/// projection of the tree will be filled in histogram hname.
7233/// Note that the dimension of hname must match with the dimension of varexp.
7234///
7236Long64_t TTree::Project(const char* hname, const char* varexp, const char* selection, Option_t* option, Long64_t nentries, Long64_t firstentry)
7237{
7238 TString var;
7239 var.Form("%s>>%s", varexp, hname);
7240 TString opt("goff");
7241 if (option) {
7242 opt.Form("%sgoff", option);
7243 }
7244 Long64_t nsel = Draw(var, selection, opt, nentries, firstentry);
7245 return nsel;
7246}
7247
7248////////////////////////////////////////////////////////////////////////////////
7249/// Loop over entries and return a TSQLResult object containing entries following selection.
7251TSQLResult* TTree::Query(const char* varexp, const char* selection, Option_t* option, Long64_t nentries, Long64_t firstentry)
7252{
7253 GetPlayer();
7254 if (fPlayer) {
7255 return fPlayer->Query(varexp, selection, option, nentries, firstentry);
7256 }
7257 return 0;
7258}
7259
7260////////////////////////////////////////////////////////////////////////////////
7261/// Create or simply read branches from filename.
7262///
7263/// if branchDescriptor = "" (default), it is assumed that the Tree descriptor
7264/// is given in the first line of the file with a syntax like
7265/// ~~~ {.cpp}
7266/// A/D:Table[2]/F:Ntracks/I:astring/C
7267/// ~~~
7268/// otherwise branchDescriptor must be specified with the above syntax.
7269///
7270/// - If the type of the first variable is not specified, it is assumed to be "/F"
7271/// - If the type of any other variable is not specified, the type of the previous
7272/// variable is assumed. eg
7273/// - `x:y:z` (all variables are assumed of type "F"
7274/// - `x/D:y:z` (all variables are of type "D"
7275/// - `x:y/D:z` (x is type "F", y and z of type "D"
7276///
7277/// delimiter allows for the use of another delimiter besides whitespace.
7278/// This provides support for direct import of common data file formats
7279/// like csv. If delimiter != ' ' and branchDescriptor == "", then the
7280/// branch description is taken from the first line in the file, but
7281/// delimiter is used for the branch names tokenization rather than ':'.
7282/// Note however that if the values in the first line do not use the
7283/// /[type] syntax, all variables are assumed to be of type "F".
7284/// If the filename ends with extensions .csv or .CSV and a delimiter is
7285/// not specified (besides ' '), the delimiter is automatically set to ','.
7286///
7287/// Lines in the input file starting with "#" are ignored. Leading whitespace
7288/// for each column data is skipped. Empty lines are skipped.
7289///
7290/// A TBranch object is created for each variable in the expression.
7291/// The total number of rows read from the file is returned.
7292///
7293/// ## FILLING a TTree WITH MULTIPLE INPUT TEXT FILES
7294///
7295/// To fill a TTree with multiple input text files, proceed as indicated above
7296/// for the first input file and omit the second argument for subsequent calls
7297/// ~~~ {.cpp}
7298/// T.ReadFile("file1.dat","branch descriptor");
7299/// T.ReadFile("file2.dat");
7300/// ~~~
7302Long64_t TTree::ReadFile(const char* filename, const char* branchDescriptor, char delimiter)
7303{
7304 std::ifstream in;
7305 in.open(filename);
7306 if (!in.good()) {
7307 Error("ReadFile","Cannot open file: %s",filename);
7308 return 0;
7309 }
7310 const char* ext = strrchr(filename, '.');
7311 if(ext != NULL && ((strcmp(ext, ".csv") == 0) || (strcmp(ext, ".CSV") == 0)) && delimiter == ' ') {
7312 delimiter = ',';
7313 }
7314 return ReadStream(in, branchDescriptor, delimiter);
7315}
7316
7317////////////////////////////////////////////////////////////////////////////////
7318/// Determine which newline this file is using.
7319/// Return '\\r' for Windows '\\r\\n' as that already terminates.
7321char TTree::GetNewlineValue(std::istream &inputStream)
7322{
7323 Long_t inPos = inputStream.tellg();
7324 char newline = '\n';
7325 while(1) {
7326 char c = 0;
7327 inputStream.get(c);
7328 if(!inputStream.good()) {
7329 Error("ReadStream","Error reading stream: no newline found.");
7330 return 0;
7331 }
7332 if(c == newline) break;
7333 if(c == '\r') {
7334 newline = '\r';
7335 break;
7336 }
7337 }
7338 inputStream.clear();
7339 inputStream.seekg(inPos);
7340 return newline;
7341}
7342
7343////////////////////////////////////////////////////////////////////////////////
7344/// Create or simply read branches from an input stream.
7345///
7346/// See reference information for TTree::ReadFile
7348Long64_t TTree::ReadStream(std::istream& inputStream, const char *branchDescriptor, char delimiter)
7349{
7350 char newline = 0;
7351 std::stringstream ss;
7352 std::istream *inTemp;
7353 Long_t inPos = inputStream.tellg();
7354 if (!inputStream.good()) {
7355 Error("ReadStream","Error reading stream");
7356 return 0;
7357 }
7358 if (inPos == -1) {
7359 ss << std::cin.rdbuf();
7360 newline = GetNewlineValue(ss);
7361 inTemp = &ss;
7362 } else {
7363 newline = GetNewlineValue(inputStream);
7364 inTemp = &inputStream;
7365 }
7366 std::istream& in = *inTemp;
7367 Long64_t nlines = 0;
7368
7369 TBranch *branch = 0;
7370 Int_t nbranches = fBranches.GetEntries();
7371 if (nbranches == 0) {
7372 char *bdname = new char[4000];
7373 char *bd = new char[100000];
7374 Int_t nch = 0;
7375 if (branchDescriptor) nch = strlen(branchDescriptor);
7376 // branch Descriptor is null, read its definition from the first line in the file
7377 if (!nch) {
7378 do {
7379 in.getline(bd, 100000, newline);
7380 if (!in.good()) {
7381 delete [] bdname;
7382 delete [] bd;
7383 Error("ReadStream","Error reading stream");
7384 return 0;
7385 }
7386 char *cursor = bd;
7387 while( isspace(*cursor) && *cursor != '\n' && *cursor != '\0') {
7388 ++cursor;
7389 }
7390 if (*cursor != '#' && *cursor != '\n' && *cursor != '\0') {
7391 break;
7392 }
7393 } while (true);
7394 ++nlines;
7395 nch = strlen(bd);
7396 } else {
7397 strlcpy(bd,branchDescriptor,100000);
7398 }
7399
7400 //parse the branch descriptor and create a branch for each element
7401 //separated by ":"
7402 void *address = &bd[90000];
7403 char *bdcur = bd;
7404 TString desc="", olddesc="F";
7405 char bdelim = ':';
7406 if(delimiter != ' ') {
7407 bdelim = delimiter;
7408 if (strchr(bdcur,bdelim)==0 && strchr(bdcur,':') != 0) {
7409 // revert to the default
7410 bdelim = ':';
7411 }
7412 }
7413 while (bdcur) {
7414 char *colon = strchr(bdcur,bdelim);
7415 if (colon) *colon = 0;
7416 strlcpy(bdname,bdcur,4000);
7417 char *slash = strchr(bdname,'/');
7418 if (slash) {
7419 *slash = 0;
7420 desc = bdcur;
7421 olddesc = slash+1;
7422 } else {
7423 desc.Form("%s/%s",bdname,olddesc.Data());
7424 }
7425 char *bracket = strchr(bdname,'[');
7426 if (bracket) {
7427 *bracket = 0;
7428 }
7429 branch = new TBranch(this,bdname,address,desc.Data(),32000);
7430 if (branch->IsZombie()) {
7431 delete branch;
7432 Warning("ReadStream","Illegal branch definition: %s",bdcur);
7433 } else {
7434 fBranches.Add(branch);
7435 branch->SetAddress(0);
7436 }
7437 if (!colon)break;
7438 bdcur = colon+1;
7439 }
7440 delete [] bdname;
7441 delete [] bd;
7442 }
7443
7444 nbranches = fBranches.GetEntries();
7445
7446 if (gDebug > 1) {
7447 Info("ReadStream", "Will use branches:");
7448 for (int i = 0 ; i < nbranches; ++i) {
7449 TBranch* br = (TBranch*) fBranches.At(i);
7450 Info("ReadStream", " %s: %s [%s]", br->GetName(),
7451 br->GetTitle(), br->GetListOfLeaves()->At(0)->IsA()->GetName());
7452 }
7453 if (gDebug > 3) {
7454 Info("ReadStream", "Dumping read tokens, format:");
7455 Info("ReadStream", "LLLLL:BBB:gfbe:GFBE:T");
7456 Info("ReadStream", " L: line number");
7457 Info("ReadStream", " B: branch number");
7458 Info("ReadStream", " gfbe: good / fail / bad / eof of token");
7459 Info("ReadStream", " GFBE: good / fail / bad / eof of file");
7460 Info("ReadStream", " T: Token being read");
7461 }
7462 }
7463
7464 //loop on all lines in the file
7465 Long64_t nGoodLines = 0;
7466 std::string line;
7467 const char sDelimBuf[2] = { delimiter, 0 };
7468 const char* sDelim = sDelimBuf;
7469 if (delimiter == ' ') {
7470 // ' ' really means whitespace
7471 sDelim = "[ \t]";
7472 }
7473 while(in.good()) {
7474 if (newline == '\r' && in.peek() == '\n') {
7475 // Windows, skip '\n':
7476 in.get();
7477 }
7478 std::getline(in, line, newline);
7479 ++nlines;
7480
7481 TString sLine(line);
7482 sLine = sLine.Strip(TString::kLeading); // skip leading whitespace
7483 if (sLine.IsNull()) {
7484 if (gDebug > 2) {
7485 Info("ReadStream", "Skipping empty line number %lld", nlines);
7486 }
7487 continue; // silently skip empty lines
7488 }
7489 if (sLine[0] == '#') {
7490 if (gDebug > 2) {
7491 Info("ReadStream", "Skipping comment line number %lld: '%s'",
7492 nlines, line.c_str());
7493 }
7494 continue;
7495 }
7496 if (gDebug > 2) {
7497 Info("ReadStream", "Parsing line number %lld: '%s'",
7498 nlines, line.c_str());
7499 }
7500
7501 // Loop on branches and read the branch values into their buffer
7502 branch = 0;
7503 TString tok; // one column's data
7504 TString leafData; // leaf data, possibly multiple tokens for e.g. /I[2]
7505 std::stringstream sToken; // string stream feeding leafData into leaves
7506 Ssiz_t pos = 0;
7507 Int_t iBranch = 0;
7508 Bool_t goodLine = kTRUE; // whether the row can be filled into the tree
7509 Int_t remainingLeafLen = 0; // remaining columns for the current leaf
7510 while (goodLine && iBranch < nbranches
7511 && sLine.Tokenize(tok, pos, sDelim)) {
7512 tok = tok.Strip(TString::kLeading); // skip leading whitespace
7513 if (tok.IsNull() && delimiter == ' ') {
7514 // 1 2 should not be interpreted as 1,,,2 but 1, 2.
7515 // Thus continue until we have a non-empty token.
7516 continue;
7517 }
7518
7519 if (!remainingLeafLen) {
7520 // next branch!
7521 branch = (TBranch*)fBranches.At(iBranch);
7522 }
7523 TLeaf *leaf = (TLeaf*)branch->GetListOfLeaves()->At(0);
7524 if (!remainingLeafLen) {
7525 remainingLeafLen = leaf->GetLen();
7526 if (leaf->GetMaximum() > 0) {
7527 // This is a dynamic leaf length, i.e. most likely a TLeafC's
7528 // string size. This still translates into one token:
7529 remainingLeafLen = 1;
7530 }
7531
7532 leafData = tok;
7533 } else {
7534 // append token to laf data:
7535 leafData += " ";
7536 leafData += tok;
7537 }
7538 --remainingLeafLen;
7539 if (remainingLeafLen) {
7540 // need more columns for this branch:
7541 continue;
7542 }
7543 ++iBranch;
7544
7545 // initialize stringstream with token
7546 sToken.clear();
7547 sToken.seekp(0, std::ios_base::beg);
7548 sToken.str(leafData.Data());
7549 sToken.seekg(0, std::ios_base::beg);
7550 leaf->ReadValue(sToken, 0 /* 0 = "all" */);
7551 if (gDebug > 3) {
7552 Info("ReadStream", "%5lld:%3d:%d%d%d%d:%d%d%d%d:%s",
7553 nlines, iBranch,
7554 (int)sToken.good(), (int)sToken.fail(),
7555 (int)sToken.bad(), (int)sToken.eof(),
7556 (int)in.good(), (int)in.fail(),
7557 (int)in.bad(), (int)in.eof(),
7558 sToken.str().c_str());
7559 }
7560
7561 // Error handling
7562 if (sToken.bad()) {
7563 // How could that happen for a stringstream?
7564 Warning("ReadStream",
7565 "Buffer error while reading data for branch %s on line %lld",
7566 branch->GetName(), nlines);
7567 } else if (!sToken.eof()) {
7568 if (sToken.fail()) {
7569 Warning("ReadStream",
7570 "Couldn't read formatted data in \"%s\" for branch %s on line %lld; ignoring line",
7571 tok.Data(), branch->GetName(), nlines);
7572 goodLine = kFALSE;
7573 } else {
7574 std::string remainder;
7575 std::getline(sToken, remainder, newline);
7576 if (!remainder.empty()) {
7577 Warning("ReadStream",
7578 "Ignoring trailing \"%s\" while reading data for branch %s on line %lld",
7579 remainder.c_str(), branch->GetName(), nlines);
7580 }
7581 }
7582 }
7583 } // tokenizer loop
7584
7585 if (iBranch < nbranches) {
7586 Warning("ReadStream",
7587 "Read too few columns (%d < %d) in line %lld; ignoring line",
7588 iBranch, nbranches, nlines);
7589 goodLine = kFALSE;
7590 } else if (pos != kNPOS) {
7591 sLine = sLine.Strip(TString::kTrailing);
7592 if (pos < sLine.Length()) {
7593 Warning("ReadStream",
7594 "Ignoring trailing \"%s\" while reading line %lld",
7595 sLine.Data() + pos - 1 /* also print delimiter */,
7596 nlines);
7597 }
7598 }
7599
7600 //we are now ready to fill the tree
7601 if (goodLine) {
7602 Fill();
7603 ++nGoodLines;
7604 }
7605 }
7606
7607 return nGoodLines;
7608}
7609
7610////////////////////////////////////////////////////////////////////////////////
7611/// Make sure that obj (which is being deleted or will soon be) is no
7612/// longer referenced by this TTree.
7615{
7616 if (obj == fEventList) {
7617 fEventList = 0;
7618 }
7619 if (obj == fEntryList) {
7620 fEntryList = 0;
7621 }
7622 if (fUserInfo) {
7624 }
7625 if (fPlayer == obj) {
7626 fPlayer = 0;
7627 }
7628 if (fTreeIndex == obj) {
7629 fTreeIndex = 0;
7630 }
7631 if (fAliases) {
7633 }
7634 if (fFriends) {
7636 }
7637}
7638
7639////////////////////////////////////////////////////////////////////////////////
7640/// Refresh contents of this tree and its branches from the current status on disk.
7641///
7642/// One can call this function in case the tree file is being
7643/// updated by another process.
7645void TTree::Refresh()
7646{
7647 if (!fDirectory->GetFile()) {
7648 return;
7649 }
7651 fDirectory->Remove(this);
7653 if (!tree) {
7654 return;
7655 }
7656 //copy info from tree header into this Tree
7657 fEntries = 0;
7658 fNClusterRange = 0;
7660
7661 fAutoSave = tree->fAutoSave;
7662 fEntries = tree->fEntries;
7663 fTotBytes = tree->GetTotBytes();
7664 fZipBytes = tree->GetZipBytes();
7665 fSavedBytes = tree->fSavedBytes;
7666 fTotalBuffers = tree->fTotalBuffers.load();
7667
7668 //loop on all branches and update them
7669 Int_t nleaves = fLeaves.GetEntriesFast();
7670 for (Int_t i = 0; i < nleaves; i++) {
7671 TLeaf* leaf = (TLeaf*) fLeaves.UncheckedAt(i);
7672 TBranch* branch = (TBranch*) leaf->GetBranch();
7673 branch->Refresh(tree->GetBranch(branch->GetName()));
7674 }
7676 fDirectory->Append(this);
7677 delete tree;
7678 tree = 0;
7679}
7680
7681////////////////////////////////////////////////////////////////////////////////
7682/// Remove a friend from the list of friends.
7684void TTree::RemoveFriend(TTree* oldFriend)
7685{
7686 // We already have been visited while recursively looking
7687 // through the friends tree, let return
7689 return;
7690 }
7691 if (!fFriends) {
7692 return;
7693 }
7694 TFriendLock lock(this, kRemoveFriend);
7695 TIter nextf(fFriends);
7696 TFriendElement* fe = 0;
7697 while ((fe = (TFriendElement*) nextf())) {
7698 TTree* friend_t = fe->GetTree();
7699 if (friend_t == oldFriend) {
7700 fFriends->Remove(fe);
7701 delete fe;
7702 fe = 0;
7703 }
7704 }
7705}
7706
7707////////////////////////////////////////////////////////////////////////////////
7708/// Reset baskets, buffers and entries count in all branches and leaves.
7710void TTree::Reset(Option_t* option)
7711{
7712 fNotify = 0;
7713 fEntries = 0;
7714 fNClusterRange = 0;
7715 fTotBytes = 0;
7716 fZipBytes = 0;
7717 fFlushedBytes = 0;
7718 fSavedBytes = 0;
7719 fTotalBuffers = 0;
7720 fChainOffset = 0;
7721 fReadEntry = -1;
7722
7723 delete fTreeIndex;
7724 fTreeIndex = 0;
7725
7727 for (Int_t i = 0; i < nb; ++i) {
7728 TBranch* branch = (TBranch*) fBranches.UncheckedAt(i);
7729 branch->Reset(option);
7730 }
7731
7732 if (fBranchRef) {
7733 fBranchRef->Reset();
7734 }
7735}
7736
7737////////////////////////////////////////////////////////////////////////////////
7738/// Resets the state of this TTree after a merge (keep the customization but
7739/// forget the data).
7742{
7743 fEntries = 0;
7744 fNClusterRange = 0;
7745 fTotBytes = 0;
7746 fZipBytes = 0;
7747 fSavedBytes = 0;
7748 fFlushedBytes = 0;
7749 fTotalBuffers = 0;
7750 fChainOffset = 0;
7751 fReadEntry = -1;
7752
7753 delete fTreeIndex;
7754 fTreeIndex = 0;
7755
7757 for (Int_t i = 0; i < nb; ++i) {
7758 TBranch* branch = (TBranch*) fBranches.UncheckedAt(i);
7759 branch->ResetAfterMerge(info);
7760 }
7761
7762 if (fBranchRef) {
7764 }
7765}
7766
7767////////////////////////////////////////////////////////////////////////////////
7768/// Tell all of our branches to set their addresses to zero.
7769///
7770/// Note: If any of our branches own any objects, they are deleted.
7773{
7774 if (br && br->GetTree()) {
7775 br->ResetAddress();
7776 }
7777}
7778
7779////////////////////////////////////////////////////////////////////////////////
7780/// Tell all of our branches to drop their current objects and allocate new ones.
7783{
7784 TObjArray* branches = GetListOfBranches();
7785 Int_t nbranches = branches->GetEntriesFast();
7786 for (Int_t i = 0; i < nbranches; ++i) {
7787 TBranch* branch = (TBranch*) branches->UncheckedAt(i);
7788 branch->ResetAddress();
7789 }
7790}
7791
7792////////////////////////////////////////////////////////////////////////////////
7793/// Loop over tree entries and print entries passing selection.
7794///
7795/// - If varexp is 0 (or "") then print only first 8 columns.
7796/// - If varexp = "*" print all columns.
7797///
7798/// Otherwise a columns selection can be made using "var1:var2:var3".
7799/// See TTreePlayer::Scan for more information
7801Long64_t TTree::Scan(const char* varexp, const char* selection, Option_t* option, Long64_t nentries, Long64_t firstentry)
7802{
7803 GetPlayer();
7804 if (fPlayer) {
7805 return fPlayer->Scan(varexp, selection, option, nentries, firstentry);
7806 }
7807 return -1;
7808}
7809
7810////////////////////////////////////////////////////////////////////////////////
7811/// Set a tree variable alias.
7812///
7813/// Set an alias for an expression/formula based on the tree 'variables'.
7814///
7815/// The content of 'aliasName' can be used in TTreeFormula (i.e. TTree::Draw,
7816/// TTree::Scan, TTreeViewer) and will be evaluated as the content of
7817/// 'aliasFormula'.
7818///
7819/// If the content of 'aliasFormula' only contains symbol names, periods and
7820/// array index specification (for example event.fTracks[3]), then
7821/// the content of 'aliasName' can be used as the start of symbol.
7822///
7823/// If the alias 'aliasName' already existed, it is replaced by the new
7824/// value.
7825///
7826/// When being used, the alias can be preceded by an eventual 'Friend Alias'
7827/// (see TTree::GetFriendAlias)
7828///
7829/// Return true if it was added properly.
7830///
7831/// For example:
7832/// ~~~ {.cpp}
7833/// tree->SetAlias("x1","(tdc1[1]-tdc1[0])/49");
7834/// tree->SetAlias("y1","(tdc1[3]-tdc1[2])/47");
7835/// tree->SetAlias("x2","(tdc2[1]-tdc2[0])/49");
7836/// tree->SetAlias("y2","(tdc2[3]-tdc2[2])/47");
7837/// tree->Draw("y2-y1:x2-x1");
7838///
7839/// tree->SetAlias("theGoodTrack","event.fTracks[3]");
7840/// tree->Draw("theGoodTrack.fPx"); // same as "event.fTracks[3].fPx"
7841/// ~~~
7843Bool_t TTree::SetAlias(const char* aliasName, const char* aliasFormula)
7844{
7845 if (!aliasName || !aliasFormula) {
7846 return kFALSE;
7847 }
7848 if (!aliasName[0] || !aliasFormula[0]) {
7849 return kFALSE;
7850 }
7851 if (!fAliases) {
7852 fAliases = new TList;
7853 } else {
7854 TNamed* oldHolder = (TNamed*) fAliases->FindObject(aliasName);
7855 if (oldHolder) {
7856 oldHolder->SetTitle(aliasFormula);
7857 return kTRUE;
7858 }
7859 }
7860 TNamed* holder = new TNamed(aliasName, aliasFormula);
7861 fAliases->Add(holder);
7862 return kTRUE;
7863}
7864
7865////////////////////////////////////////////////////////////////////////////////
7866/// This function may be called at the start of a program to change
7867/// the default value for fAutoFlush.
7868///
7869/// ### CASE 1 : autof > 0
7870///
7871/// autof is the number of consecutive entries after which TTree::Fill will
7872/// flush all branch buffers to disk.
7873///
7874/// ### CASE 2 : autof < 0
7875///
7876/// When filling the Tree the branch buffers will be flushed to disk when
7877/// more than autof bytes have been written to the file. At the first FlushBaskets
7878/// TTree::Fill will replace fAutoFlush by the current value of fEntries.
7879///
7880/// Calling this function with autof<0 is interesting when it is hard to estimate
7881/// the size of one entry. This value is also independent of the Tree.
7882///
7883/// The Tree is initialized with fAutoFlush=-30000000, ie that, by default,
7884/// the first AutoFlush will be done when 30 MBytes of data are written to the file.
7885///
7886/// ### CASE 3 : autof = 0
7887///
7888/// The AutoFlush mechanism is disabled.
7889///
7890/// Flushing the buffers at regular intervals optimize the location of
7891/// consecutive entries on the disk by creating clusters of baskets.
7892///
7893/// A cluster of baskets is a set of baskets that contains all
7894/// the data for a (consecutive) set of entries and that is stored
7895/// consecutively on the disk. When reading all the branches, this
7896/// is the minimum set of baskets that the TTreeCache will read.
7898void TTree::SetAutoFlush(Long64_t autof /* = -30000000 */ )
7899{
7900 // Implementation note:
7901 //
7902 // A positive value of autoflush determines the size (in number of entries) of
7903 // a cluster of baskets.
7904 //
7905 // If the value of autoflush is changed over time (this happens in
7906 // particular when the TTree results from fast merging many trees),
7907 // we record the values of fAutoFlush in the data members:
7908 // fClusterRangeEnd and fClusterSize.
7909 // In the code we refer to a range of entries where the size of the
7910 // cluster of baskets is the same (i.e the value of AutoFlush was
7911 // constant) is called a ClusterRange.
7912 //
7913 // The 2 arrays (fClusterRangeEnd and fClusterSize) have fNClusterRange
7914 // active (used) values and have fMaxClusterRange allocated entries.
7915 //
7916 // fClusterRangeEnd contains the last entries number of a cluster range.
7917 // In particular this means that the 'next' cluster starts at fClusterRangeEnd[]+1
7918 // fClusterSize contains the size in number of entries of all the cluster
7919 // within the given range.
7920 // The last range (and the only one if fNClusterRange is zero) start at
7921 // fNClusterRange[fNClusterRange-1]+1 and ends at the end of the TTree. The
7922 // size of the cluster in this range is given by the value of fAutoFlush.
7923 //
7924 // For example printing the beginning and end of each the ranges can be done by:
7925 //
7926 // Printf("%-16s %-16s %-16s %5s",
7927 // "Cluster Range #", "Entry Start", "Last Entry", "Size");
7928 // Int_t index= 0;
7929 // Long64_t clusterRangeStart = 0;
7930 // if (fNClusterRange) {
7931 // for( ; index < fNClusterRange; ++index) {
7932 // Printf("%-16d %-16lld %-16lld %5lld",
7933 // index, clusterRangeStart, fClusterRangeEnd[index], fClusterSize[index]);
7934 // clusterRangeStart = fClusterRangeEnd[index] + 1;
7935 // }
7936 // }
7937 // Printf("%-16d %-16lld %-16lld %5lld",
7938 // index, prevEntry, fEntries - 1, fAutoFlush);
7939 //
7940
7941 // Note: We store the entry number corresponding to the end of the cluster
7942 // rather than its start in order to avoid using the array if the cluster
7943 // size never varies (If there is only one value of AutoFlush for the whole TTree).
7944
7945 if( fAutoFlush != autof) {
7946 if ((fAutoFlush > 0 || autof > 0) && fFlushedBytes) {
7947 // The mechanism was already enabled, let's record the previous
7948 // cluster if needed.
7950 }
7951 fAutoFlush = autof;
7952 }
7953}
7954
7955////////////////////////////////////////////////////////////////////////////////
7956/// Mark the previous event as being at the end of the event cluster.
7957///
7958/// So, if fEntries is set to 10 (and this is the first cluster) when MarkEventCluster
7959/// is called, then the first cluster has 9 events.
7961{
7962 if (!fEntries) return;
7963
7964 if ( (fNClusterRange+1) > fMaxClusterRange ) {
7965 if (fMaxClusterRange) {
7966 // Resize arrays to hold a larger event cluster.
7967 Int_t newsize = TMath::Max(10,Int_t(2*fMaxClusterRange));
7969 newsize*sizeof(Long64_t),fMaxClusterRange*sizeof(Long64_t));
7971 newsize*sizeof(Long64_t),fMaxClusterRange*sizeof(Long64_t));
7972 fMaxClusterRange = newsize;
7973 } else {
7974 // Cluster ranges have never been initialized; create them now.
7975 fMaxClusterRange = 2;
7978 }
7979 }
7981 // If we are auto-flushing, then the cluster size is the same as the current auto-flush setting.
7982 if (fAutoFlush > 0) {
7983 // Even if the user triggers MarkEventRange prior to fAutoFlush being present, the TClusterIterator
7984 // will appropriately go to the next event range.
7986 // Otherwise, assume there is one cluster per event range (e.g., user is manually controlling the flush).
7987 } else if (fNClusterRange == 0) {
7989 } else {
7991 }
7993}
7994
7995////////////////////////////////////////////////////////////////////////////////
7996/// This function may be called at the start of a program to change
7997/// the default value for fAutoSave (and for SetAutoSave) is -300000000, ie 300 MBytes.
7998/// When filling the Tree the branch buffers as well as the Tree header
7999/// will be flushed to disk when the watermark is reached.
8000/// If fAutoSave is positive the watermark is reached when a multiple of fAutoSave
8001/// entries have been written.
8002/// If fAutoSave is negative the watermark is reached when -fAutoSave bytes
8003/// have been written to the file.
8004/// In case of a program crash, it will be possible to recover the data in the Tree
8005/// up to the last AutoSave point.
8007void TTree::SetAutoSave(Long64_t autos)
8008{
8009 fAutoSave = autos;
8010}
8011
8012////////////////////////////////////////////////////////////////////////////////
8013/// Set a branch's basket size.
8014///
8015/// bname is the name of a branch.
8016///
8017/// - if bname="*", apply to all branches.
8018/// - if bname="xxx*", apply to all branches with name starting with xxx
8019///
8020/// see TRegexp for wildcarding options
8021/// buffsize = branc basket size
8023void TTree::SetBasketSize(const char* bname, Int_t buffsize)
8024{
8025 Int_t nleaves = fLeaves.GetEntriesFast();
8026 TRegexp re(bname, kTRUE);
8027 Int_t nb = 0;
8028 for (Int_t i = 0; i < nleaves; i++) {
8029 TLeaf* leaf = (TLeaf*) fLeaves.UncheckedAt(i);
8030 TBranch* branch = (TBranch*) leaf->GetBranch();
8031 TString s = branch->GetName();
8032 if (strcmp(bname, branch->GetName()) && (s.Index(re) == kNPOS)) {
8033 continue;
8034 }
8035 nb++;
8036 branch->SetBasketSize(buffsize);
8037 }
8038 if (!nb) {
8039 Error("SetBasketSize", "unknown branch -> '%s'", bname);
8040 }
8041}
8042
8043////////////////////////////////////////////////////////////////////////////////
8044/// Change branch address, dealing with clone trees properly.
8045/// See TTree::CheckBranchAddressType for the semantic of the return value.
8046///
8047/// Note: See the comments in TBranchElement::SetAddress() for the
8048/// meaning of the addr parameter and the object ownership policy.
8050Int_t TTree::SetBranchAddress(const char* bname, void* addr, TBranch** ptr)
8051{
8052 TBranch* branch = GetBranch(bname);
8053 if (!branch) {
8054 if (ptr) *ptr = 0;
8055 Error("SetBranchAddress", "unknown branch -> %s", bname);
8056 return kMissingBranch;
8057 }
8058 return SetBranchAddressImp(branch,addr,ptr);
8059}
8060
8061////////////////////////////////////////////////////////////////////////////////
8062/// Verify the validity of the type of addr before calling SetBranchAddress.
8063/// See TTree::CheckBranchAddressType for the semantic of the return value.
8064///
8065/// Note: See the comments in TBranchElement::SetAddress() for the
8066/// meaning of the addr parameter and the object ownership policy.
8068Int_t TTree::SetBranchAddress(const char* bname, void* addr, TClass* ptrClass, EDataType datatype, Bool_t isptr)
8069{
8070 return SetBranchAddress(bname, addr, 0, ptrClass, datatype, isptr);
8071}
8072
8073////////////////////////////////////////////////////////////////////////////////
8074/// Verify the validity of the type of addr before calling SetBranchAddress.
8075/// See TTree::CheckBranchAddressType for the semantic of the return value.
8076///
8077/// Note: See the comments in TBranchElement::SetAddress() for the
8078/// meaning of the addr parameter and the object ownership policy.
8080Int_t TTree::SetBranchAddress(const char* bname, void* addr, TBranch** ptr, TClass* ptrClass, EDataType datatype, Bool_t isptr)
8081{
8082 TBranch* branch = GetBranch(bname);
8083 if (!branch) {
8084 if (ptr) *ptr = 0;
8085 Error("SetBranchAddress", "unknown branch -> %s", bname);
8086 return kMissingBranch;
8087 }
8088
8089 Int_t res = CheckBranchAddressType(branch, ptrClass, datatype, isptr);
8090 // This will set the value of *ptr to branch.
8091 if (res >= 0) {
8092 // The check succeeded.
8093 SetBranchAddressImp(branch,addr,ptr);
8094 } else {
8095 if (ptr) *ptr = 0;
8096 }
8097 return res;
8098}
8099
8100////////////////////////////////////////////////////////////////////////////////
8101/// Change branch address, dealing with clone trees properly.
8102/// See TTree::CheckBranchAddressType for the semantic of the return value.
8103///
8104/// Note: See the comments in TBranchElement::SetAddress() for the
8105/// meaning of the addr parameter and the object ownership policy.
8107Int_t TTree::SetBranchAddressImp(TBranch *branch, void* addr, TBranch** ptr)
8108{
8109 if (ptr) {
8110 *ptr = branch;
8111 }
8112 if (fClones) {
8113 void* oldAddr = branch->GetAddress();
8114 TIter next(fClones);
8115 TTree* clone = 0;
8116 const char *bname = branch->GetName();
8117 while ((clone = (TTree*) next())) {
8118 TBranch* cloneBr = clone->GetBranch(bname);
8119 if (cloneBr && (cloneBr->GetAddress() == oldAddr)) {
8120 cloneBr->SetAddress(addr);
8121 }
8122 }
8123 }
8124 branch->SetAddress(addr);
8125 return kVoidPtr;
8126}
8127
8128////////////////////////////////////////////////////////////////////////////////
8129/// Set branch status to Process or DoNotProcess.
8130///
8131/// When reading a Tree, by default, all branches are read.
8132/// One can speed up considerably the analysis phase by activating
8133/// only the branches that hold variables involved in a query.
8134///
8135/// bname is the name of a branch.
8136///
8137/// - if bname="*", apply to all branches.
8138/// - if bname="xxx*", apply to all branches with name starting with xxx
8139///
8140/// see TRegexp for wildcarding options
8141///
8142/// - status = 1 branch will be processed
8143/// - = 0 branch will not be processed
8144///
8145/// Example:
8146///
8147/// Assume a tree T with sub-branches a,b,c,d,e,f,g,etc..
8148/// when doing T.GetEntry(i) all branches are read for entry i.
8149/// to read only the branches c and e, one can do
8150/// ~~~ {.cpp}
8151/// T.SetBranchStatus("*",0); //disable all branches
8152/// T.SetBranchStatus("c",1);
8153/// T.setBranchStatus("e",1);
8154/// T.GetEntry(i);
8155/// ~~~
8156/// bname is interpreted as a wildcarded TRegexp (see TRegexp::MakeWildcard).
8157/// Thus, "a*b" or "a.*b" matches branches starting with "a" and ending with
8158/// "b", but not any other branch with an "a" followed at some point by a
8159/// "b". For this second behavior, use "*a*b*". Note that TRegExp does not
8160/// support '|', and so you cannot select, e.g. track and shower branches
8161/// with "track|shower".
8162///
8163/// __WARNING! WARNING! WARNING!__
8164///
8165/// SetBranchStatus is matching the branch based on match of the branch
8166/// 'name' and not on the branch hierarchy! In order to be able to
8167/// selectively enable a top level object that is 'split' you need to make
8168/// sure the name of the top level branch is prefixed to the sub-branches'
8169/// name (by adding a dot ('.') at the end of the Branch creation and use the
8170/// corresponding bname.
8171///
8172/// I.e If your Tree has been created in split mode with a parent branch "parent."
8173/// (note the trailing dot).
8174/// ~~~ {.cpp}
8175/// T.SetBranchStatus("parent",1);
8176/// ~~~
8177/// will not activate the sub-branches of "parent". You should do:
8178/// ~~~ {.cpp}
8179/// T.SetBranchStatus("parent*",1);
8180/// ~~~
8181/// Without the trailing dot in the branch creation you have no choice but to
8182/// call SetBranchStatus explicitly for each of the sub branches.
8183///
8184/// An alternative to this function is to read directly and only
8185/// the interesting branches. Example:
8186/// ~~~ {.cpp}
8187/// TBranch *brc = T.GetBranch("c");
8188/// TBranch *bre = T.GetBranch("e");
8189/// brc->GetEntry(i);
8190/// bre->GetEntry(i);
8191/// ~~~
8192/// If found is not 0, the number of branch(es) found matching the regular
8193/// expression is returned in *found AND the error message 'unknown branch'
8194/// is suppressed.
8196void TTree::SetBranchStatus(const char* bname, Bool_t status, UInt_t* found)
8197{
8198 // We already have been visited while recursively looking
8199 // through the friends tree, let return
8201 return;
8202 }
8203
8204 if (0 == strcmp(bname, "")) {
8205 Error("SetBranchStatus", "Input regexp is an empty string: no match against branch names will be attempted.");
8206 return;
8207 }
8208
8209 TBranch *branch, *bcount, *bson;
8210 TLeaf *leaf, *leafcount;
8211
8212 Int_t i,j;
8213 Int_t nleaves = fLeaves.GetEntriesFast();
8214 TRegexp re(bname,kTRUE);
8215 Int_t nb = 0;
8216
8217 // first pass, loop on all branches
8218 // for leafcount branches activate/deactivate in function of status
8219 for (i=0;i<nleaves;i++) {
8220 leaf = (TLeaf*)fLeaves.UncheckedAt(i);
8221 branch = (TBranch*)leaf->GetBranch();
8222 TString s = branch->GetName();
8223 if (strcmp(bname,"*")) { //Regexp gives wrong result for [] in name
8224 TString longname;
8225 longname.Form("%s.%s",GetName(),branch->GetName());
8226 if (strcmp(bname,branch->GetName())
8227 && longname != bname
8228 && s.Index(re) == kNPOS) continue;
8229 }
8230 nb++;
8231 if (status) branch->ResetBit(kDoNotProcess);
8232 else branch->SetBit(kDoNotProcess);
8233 leafcount = leaf->GetLeafCount();
8234 if (leafcount) {
8235 bcount = leafcount->GetBranch();
8236 if (status) bcount->ResetBit(kDoNotProcess);
8237 else bcount->SetBit(kDoNotProcess);
8238 }
8239 }
8240 if (nb==0 && strchr(bname,'*')==0) {
8241 branch = GetBranch(bname);
8242 if (branch) {
8243 if (status) branch->ResetBit(kDoNotProcess);
8244 else branch->SetBit(kDoNotProcess);
8245 ++nb;
8246 }
8247 }
8248
8249 //search in list of friends
8250 UInt_t foundInFriend = 0;
8251 if (fFriends) {
8252 TFriendLock lock(this,kSetBranchStatus);
8253 TIter nextf(fFriends);
8254 TFriendElement *fe;
8255 TString name;
8256 while ((fe = (TFriendElement*)nextf())) {
8257 TTree *t = fe->GetTree();
8258 if (t==0) continue;
8259
8260 // If the alias is present replace it with the real name.
8261 char *subbranch = (char*)strstr(bname,fe->GetName());
8262 if (subbranch!=bname) subbranch = 0;
8263 if (subbranch) {
8264 subbranch += strlen(fe->GetName());
8265 if ( *subbranch != '.' ) subbranch = 0;
8266 else subbranch ++;
8267 }
8268 if (subbranch) {
8269 name.Form("%s.%s",t->GetName(),subbranch);
8270 } else {
8271 name = bname;
8272 }
8273 t->SetBranchStatus(name,status, &foundInFriend);
8274 }
8275 }
8276 if (!nb && !foundInFriend) {
8277 if (found==0) {
8278 if (status) {
8279 if (strchr(bname,'*') != 0)
8280 Error("SetBranchStatus", "No branch name is matching wildcard -> %s", bname);
8281 else
8282 Error("SetBranchStatus", "unknown branch -> %s", bname);
8283 } else {
8284 if (strchr(bname,'*') != 0)
8285 Warning("SetBranchStatus", "No branch name is matching wildcard -> %s", bname);
8286 else
8287 Warning("SetBranchStatus", "unknown branch -> %s", bname);
8288 }
8289 }
8290 return;
8291 }
8292 if (found) *found = nb + foundInFriend;
8293
8294 // second pass, loop again on all branches
8295 // activate leafcount branches for active branches only
8296 for (i = 0; i < nleaves; i++) {
8297 leaf = (TLeaf*)fLeaves.UncheckedAt(i);
8298 branch = (TBranch*)leaf->GetBranch();
8299 if (!branch->TestBit(kDoNotProcess)) {
8300 leafcount = leaf->GetLeafCount();
8301 if (leafcount) {
8302 bcount = leafcount->GetBranch();
8303 bcount->ResetBit(kDoNotProcess);
8304 }
8305 } else {
8306 //Int_t nbranches = branch->GetListOfBranches()->GetEntriesFast();
8307 Int_t nbranches = branch->GetListOfBranches()->GetEntries();
8308 for (j=0;j<nbranches;j++) {
8309 bson = (TBranch*)branch->GetListOfBranches()->UncheckedAt(j);
8310 if (!bson) continue;
8311 if (!bson->TestBit(kDoNotProcess)) {
8312 if (bson->GetNleaves() <= 0) continue;
8313 branch->ResetBit(kDoNotProcess);
8314 break;
8315 }
8316 }
8317 }
8318 }
8319}
8320
8321////////////////////////////////////////////////////////////////////////////////
8322/// Set the current branch style. (static function)
8323///
8324/// - style = 0 old Branch
8325/// - style = 1 new Bronch
8328{
8330}
8331
8332////////////////////////////////////////////////////////////////////////////////
8333/// Set maximum size of the file cache .
8334//
8335/// - if cachesize = 0 the existing cache (if any) is deleted.
8336/// - if cachesize = -1 (default) it is set to the AutoFlush value when writing
8337/// the Tree (default is 30 MBytes).
8338///
8339/// Returns:
8340/// - 0 size set, cache was created if possible
8341/// - -1 on error
8344{
8345 // remember that the user has requested an explicit cache setup
8347
8348 return SetCacheSizeAux(kFALSE, cacheSize);
8349}
8350
8351////////////////////////////////////////////////////////////////////////////////
8352/// Set the size of the file cache and create it if possible.
8353///
8354/// If autocache is true:
8355/// this may be an autocreated cache, possibly enlarging an existing
8356/// autocreated cache. The size is calculated. The value passed in cacheSize:
8357/// - cacheSize = 0 make cache if default cache creation is enabled
8358/// - cacheSize = -1 make a default sized cache in any case
8359///
8360/// If autocache is false:
8361/// this is a user requested cache. cacheSize is used to size the cache.
8362/// This cache should never be automatically adjusted.
8363///
8364/// Returns:
8365/// - 0 size set, or existing autosized cache almost large enough.
8366/// (cache was created if possible)
8367/// - -1 on error
8369Int_t TTree::SetCacheSizeAux(Bool_t autocache /* = kTRUE */, Long64_t cacheSize /* = 0 */ )
8370{
8371 if (autocache) {
8372 // used as a once only control for automatic cache setup
8374 }
8375
8376 if (!autocache) {
8377 // negative size means the user requests the default
8378 if (cacheSize < 0) {
8379 cacheSize = GetCacheAutoSize(kTRUE);
8380 }
8381 } else {
8382 if (cacheSize == 0) {
8383 cacheSize = GetCacheAutoSize();
8384 } else if (cacheSize < 0) {
8385 cacheSize = GetCacheAutoSize(kTRUE);
8386 }
8387 }
8388
8390 if (!file || GetTree() != this) {
8391 // if there's no file or we are not a plain tree (e.g. if we're a TChain)
8392 // do not create a cache, only record the size if one was given
8393 if (!autocache) {
8394 fCacheSize = cacheSize;
8395 }
8396 if (GetTree() != this) {
8397 return 0;
8398 }
8399 if (!autocache && cacheSize>0) {
8400 Warning("SetCacheSizeAux", "A TTreeCache could not be created because the TTree has no file");
8401 }
8402 return 0;
8403 }
8404
8405 // Check for an existing cache
8407 if (pf) {
8408 if (autocache) {
8409 // reset our cache status tracking in case existing cache was added
8410 // by the user without using one of the TTree methods
8411 fCacheSize = pf->GetBufferSize();
8413
8414 if (fCacheUserSet) {
8415 // existing cache was created by the user, don't change it
8416 return 0;
8417 }
8418 } else {
8419 // update the cache to ensure it records the user has explicitly
8420 // requested it
8422 }
8423
8424 // if we're using an automatically calculated size and the existing
8425 // cache is already almost large enough don't resize
8426 if (autocache && Long64_t(0.80*cacheSize) < fCacheSize) {
8427 // already large enough
8428 return 0;
8429 }
8430
8431 if (cacheSize == fCacheSize) {
8432 return 0;
8433 }
8434
8435 if (cacheSize == 0) {
8436 // delete existing cache
8437 pf->WaitFinishPrefetch();
8438 file->SetCacheRead(0,this);
8439 delete pf;
8440 pf = 0;
8441 } else {
8442 // resize
8443 Int_t res = pf->SetBufferSize(cacheSize);
8444 if (res < 0) {
8445 return -1;
8446 }
8447 }
8448 } else {
8449 // no existing cache
8450 if (autocache) {
8451 if (fCacheUserSet) {
8452 // value was already set manually.
8453 if (fCacheSize == 0) return 0;
8454 // Expected a cache should exist; perhaps the user moved it
8455 // Do nothing more here.
8456 if (cacheSize) {
8457 Error("SetCacheSizeAux", "Not setting up an automatically sized TTreeCache because of missing cache previously set");
8458 }
8459 return -1;
8460 }
8461 }
8462 }
8463
8464 fCacheSize = cacheSize;
8465 if (cacheSize == 0 || pf) {
8466 return 0;
8467 }
8468
8469#ifdef R__USE_IMT
8470 if(TTreeCacheUnzip::IsParallelUnzip() && file->GetCompressionLevel() > 0)
8471 pf = new TTreeCacheUnzip(this, cacheSize);
8472 else
8473#endif
8474 pf = new TTreeCache(this, cacheSize);
8475
8476 pf->SetAutoCreated(autocache);
8477
8478 return 0;
8479}
8480
8481////////////////////////////////////////////////////////////////////////////////
8482///interface to TTreeCache to set the cache entry range
8483///
8484/// Returns:
8485/// - 0 entry range set
8486/// - -1 on error
8489{
8490 if (!GetTree()) {
8491 if (LoadTree(0)<0) {
8492 Error("SetCacheEntryRange","Could not load a tree");
8493 return -1;
8494 }
8495 }
8496 if (GetTree()) {
8497 if (GetTree() != this) {
8498 return GetTree()->SetCacheEntryRange(first, last);
8499 }
8500 } else {
8501 Error("SetCacheEntryRange", "No tree is available. Could not set cache entry range");
8502 return -1;
8503 }
8504
8505 TFile *f = GetCurrentFile();
8506 if (!f) {
8507 Error("SetCacheEntryRange", "No file is available. Could not set cache entry range");
8508 return -1;
8509 }
8511 if (!tc) {
8512 Error("SetCacheEntryRange", "No cache is available. Could not set entry range");
8513 return -1;
8514 }
8515 tc->SetEntryRange(first,last);
8516 return 0;
8517}
8518
8519////////////////////////////////////////////////////////////////////////////////
8520/// Interface to TTreeCache to set the number of entries for the learning phase
8523{
8525}
8526
8527////////////////////////////////////////////////////////////////////////////////
8528/// Enable/Disable circularity for this tree.
8529///
8530/// if maxEntries > 0 a maximum of maxEntries is kept in one buffer/basket
8531/// per branch in memory.
8532/// Note that when this function is called (maxEntries>0) the Tree
8533/// must be empty or having only one basket per branch.
8534/// if maxEntries <= 0 the tree circularity is disabled.
8535///
8536/// #### NOTE 1:
8537/// Circular Trees are interesting in online real time environments
8538/// to store the results of the last maxEntries events.
8539/// #### NOTE 2:
8540/// Calling SetCircular with maxEntries <= 0 is necessary before
8541/// merging circular Trees that have been saved on files.
8542/// #### NOTE 3:
8543/// SetCircular with maxEntries <= 0 is automatically called
8544/// by TChain::Merge
8545/// #### NOTE 4:
8546/// A circular Tree can still be saved in a file. When read back,
8547/// it is still a circular Tree and can be filled again.
8549void TTree::SetCircular(Long64_t maxEntries)
8550{
8551 if (maxEntries <= 0) {
8552 // Disable circularity.
8553 fMaxEntries = 1000000000;
8554 fMaxEntries *= 1000;
8556 //in case the Tree was originally created in gROOT, the branch
8557 //compression level was set to -1. If the Tree is now associated to
8558 //a file, reset the compression level to the file compression level
8559 if (fDirectory) {
8560 TFile* bfile = fDirectory->GetFile();
8562 if (bfile) {
8563 compress = bfile->GetCompressionSettings();
8564 }
8566 for (Int_t i = 0; i < nb; i++) {
8567 TBranch* branch = (TBranch*) fBranches.UncheckedAt(i);
8568 branch->SetCompressionSettings(compress);
8569 }
8570 }
8571 } else {
8572 // Enable circularity.
8573 fMaxEntries = maxEntries;
8575 }
8576}
8577
8578////////////////////////////////////////////////////////////////////////////////
8579/// Set the debug level and the debug range.
8580///
8581/// For entries in the debug range, the functions TBranchElement::Fill
8582/// and TBranchElement::GetEntry will print the number of bytes filled
8583/// or read for each branch.
8585void TTree::SetDebug(Int_t level, Long64_t min, Long64_t max)
8586{
8587 fDebug = level;
8588 fDebugMin = min;
8589 fDebugMax = max;
8590}
8591
8592////////////////////////////////////////////////////////////////////////////////
8593/// Update the default value for the branch's fEntryOffsetLen.
8594/// If updateExisting is true, also update all the existing branches.
8595/// If newdefault is less than 10, the new default value will be 10.
8597void TTree::SetDefaultEntryOffsetLen(Int_t newdefault, Bool_t updateExisting)
8598{
8599 if (newdefault < 10) {
8600 newdefault = 10;
8601 }
8602 fDefaultEntryOffsetLen = newdefault;
8603 if (updateExisting) {
8604 TIter next( GetListOfBranches() );
8605 TBranch *b;
8606 while ( ( b = (TBranch*)next() ) ) {
8607 b->SetEntryOffsetLen( newdefault, kTRUE );
8608 }
8609 if (fBranchRef) {
8610 fBranchRef->SetEntryOffsetLen( newdefault, kTRUE );
8611 }
8612 }
8613}
8614
8615////////////////////////////////////////////////////////////////////////////////
8616/// Change the tree's directory.
8617///
8618/// Remove reference to this tree from current directory and
8619/// add reference to new directory dir. The dir parameter can
8620/// be 0 in which case the tree does not belong to any directory.
8621///
8624{
8625 if (fDirectory == dir) {
8626 return;
8627 }
8628 if (fDirectory) {
8629 fDirectory->Remove(this);
8630
8631 // Delete or move the file cache if it points to this Tree
8633 MoveReadCache(file,dir);
8634 }
8635 fDirectory = dir;
8636 if (fDirectory) {
8637 fDirectory->Append(this);
8638 }
8639 TFile* file = 0;
8640 if (fDirectory) {
8641 file = fDirectory->GetFile();
8642 }
8643 if (fBranchRef) {
8645 }
8646 TBranch* b = 0;
8647 TIter next(GetListOfBranches());
8648 while((b = (TBranch*) next())) {
8649 b->SetFile(file);
8650 }
8651}
8652
8653////////////////////////////////////////////////////////////////////////////////
8654/// Change number of entries in the tree.
8655///
8656/// If n >= 0, set number of entries in the tree = n.
8657///
8658/// If n < 0, set number of entries in the tree to match the
8659/// number of entries in each branch. (default for n is -1)
8660///
8661/// This function should be called only when one fills each branch
8662/// independently via TBranch::Fill without calling TTree::Fill.
8663/// Calling TTree::SetEntries() make sense only if the number of entries
8664/// in each branch is identical, a warning is issued otherwise.
8665/// The function returns the number of entries.
8666///
8669{
8670 // case 1 : force number of entries to n
8671 if (n >= 0) {
8672 fEntries = n;
8673 return n;
8674 }
8675
8676 // case 2; compute the number of entries from the number of entries in the branches
8677 TBranch* b(nullptr), *bMin(nullptr), *bMax(nullptr);
8678 Long64_t nMin = kMaxEntries;
8679 Long64_t nMax = 0;
8680 TIter next(GetListOfBranches());
8681 while((b = (TBranch*) next())){
8682 Long64_t n2 = b->GetEntries();
8683 if (!bMin || n2 < nMin) {
8684 nMin = n2;
8685 bMin = b;
8686 }
8687 if (!bMax || n2 > nMax) {
8688 nMax = n2;
8689 bMax = b;
8690 }
8691 }
8692 if (bMin && nMin != nMax) {
8693 Warning("SetEntries", "Tree branches have different numbers of entries, eg %s has %lld entries while %s has %lld entries.",
8694 bMin->GetName(), nMin, bMax->GetName(), nMax);
8695 }
8696 fEntries = nMax;
8697 return fEntries;
8698}
8699
8700////////////////////////////////////////////////////////////////////////////////
8701/// Set an EntryList
8703void TTree::SetEntryList(TEntryList *enlist, Option_t * /*opt*/)
8704{
8705 if (fEntryList) {
8706 //check if the previous entry list is owned by the tree
8708 delete fEntryList;
8709 }
8710 }
8711 fEventList = 0;
8712 if (!enlist) {
8713 fEntryList = 0;
8714 return;
8715 }
8716 fEntryList = enlist;
8717 fEntryList->SetTree(this);
8718
8719}
8720
8721////////////////////////////////////////////////////////////////////////////////
8722/// This function transfroms the given TEventList into a TEntryList
8723/// The new TEntryList is owned by the TTree and gets deleted when the tree
8724/// is deleted. This TEntryList can be returned by GetEntryList() function.
8726void TTree::SetEventList(TEventList *evlist)
8727{
8728 fEventList = evlist;
8729 if (fEntryList){
8731 TEntryList *tmp = fEntryList;
8732 fEntryList = 0; // Avoid problem with RecursiveRemove.
8733 delete tmp;
8734 } else {
8735 fEntryList = 0;
8736 }
8737 }
8738
8739 if (!evlist) {
8740 fEntryList = 0;
8741 fEventList = 0;
8742 return;
8743 }
8744
8745 fEventList = evlist;
8746 char enlistname[100];
8747 snprintf(enlistname,100, "%s_%s", evlist->GetName(), "entrylist");
8748 fEntryList = new TEntryList(enlistname, evlist->GetTitle());
8749 fEntryList->SetDirectory(0); // We own this.
8750 Int_t nsel = evlist->GetN();
8751 fEntryList->SetTree(this);
8752 Long64_t entry;
8753 for (Int_t i=0; i<nsel; i++){
8754 entry = evlist->GetEntry(i);
8755 fEntryList->Enter(entry);
8756 }
8759}
8760
8761////////////////////////////////////////////////////////////////////////////////
8762/// Set number of entries to estimate variable limits.
8763/// If n is -1, the estimate is set to be the current maximum
8764/// for the tree (i.e. GetEntries() + 1)
8765/// If n is less than -1, the behavior is undefined.
8767void TTree::SetEstimate(Long64_t n /* = 1000000 */)
8768{
8769 if (n == 0) {
8770 n = 10000;
8771 } else if (n < 0) {
8772 n = fEntries - n;
8773 }
8774 fEstimate = n;
8775 GetPlayer();
8776 if (fPlayer) {
8778 }
8779}
8780
8781////////////////////////////////////////////////////////////////////////////////
8782/// Provide the end-user with the ability to enable/disable various experimental
8783/// IO features for this TTree.
8784///
8785/// Returns all the newly-set IO settings.
8788{
8789 // Purposely ignore all unsupported bits; TIOFeatures implementation already warned the user about the
8790 // error of their ways; this is just a safety check.
8791 UChar_t featuresRequested = features.GetFeatures() & static_cast<UChar_t>(TBasket::EIOBits::kSupported);
8792
8793 UChar_t curFeatures = fIOFeatures.GetFeatures();
8794 UChar_t newFeatures = ~curFeatures & featuresRequested;
8795 curFeatures |= newFeatures;
8796 fIOFeatures.Set(curFeatures);
8797
8798 ROOT::TIOFeatures newSettings(newFeatures);
8799 return newSettings;
8800}
8801
8802////////////////////////////////////////////////////////////////////////////////
8803/// Set fFileNumber to number.
8804/// fFileNumber is used by TTree::Fill to set the file name
8805/// for a new file to be created when the current file exceeds fgTreeMaxSize.
8806/// (see TTree::ChangeFile)
8807/// if fFileNumber=10, the new file name will have a suffix "_11",
8808/// ie, fFileNumber is incremented before setting the file name
8810void TTree::SetFileNumber(Int_t number)
8811{
8812 if (fFileNumber < 0) {
8813 Warning("SetFileNumber", "file number must be positive. Set to 0");
8814 fFileNumber = 0;
8815 return;
8816 }
8817 fFileNumber = number;
8818}
8819
8820////////////////////////////////////////////////////////////////////////////////
8821/// Set all the branches in this TTree to be in decomposed object mode
8822/// (also known as MakeClass mode).
8825{
8826 fMakeClass = make;
8827
8829 for (Int_t i = 0; i < nb; ++i) {
8830 TBranch* branch = (TBranch*) fBranches.UncheckedAt(i);
8831 branch->SetMakeClass(make);
8832 }
8833}
8834
8835////////////////////////////////////////////////////////////////////////////////
8836/// Set the maximum size in bytes of a Tree file (static function).
8837/// The default size is 100000000000LL, ie 100 Gigabytes.
8838///
8839/// In TTree::Fill, when the file has a size > fgMaxTreeSize,
8840/// the function closes the current file and starts writing into
8841/// a new file with a name of the style "file_1.root" if the original
8842/// requested file name was "file.root".
8844void TTree::SetMaxTreeSize(Long64_t maxsize)
8845{
8846 fgMaxTreeSize = maxsize;
8847}
8848
8849////////////////////////////////////////////////////////////////////////////////
8850/// Change the name of this tree.
8852void TTree::SetName(const char* name)
8853{
8854 if (gPad) {
8855 gPad->Modified();
8856 }
8857 // Trees are named objects in a THashList.
8858 // We must update hashlists if we change the name.
8859 TFile *file = 0;
8860 TTreeCache *pf = 0;
8861 if (fDirectory) {
8862 fDirectory->Remove(this);
8863 if ((file = GetCurrentFile())) {
8864 pf = GetReadCache(file);
8865 file->SetCacheRead(0,this,TFile::kDoNotDisconnect);
8866 }
8867 }
8868 // This changes our hash value.
8869 fName = name;
8870 if (fDirectory) {
8871 fDirectory->Append(this);
8872 if (pf) {
8873 file->SetCacheRead(pf,this,TFile::kDoNotDisconnect);
8874 }
8875 }
8876}
8877
8878////////////////////////////////////////////////////////////////////////////////
8879/// Change the name and title of this tree.
8881void TTree::SetObject(const char* name, const char* title)
8882{
8883 if (gPad) {
8884 gPad->Modified();
8885 }
8886
8887 // Trees are named objects in a THashList.
8888 // We must update hashlists if we change the name
8889 TFile *file = 0;
8890 TTreeCache *pf = 0;
8891 if (fDirectory) {
8892 fDirectory->Remove(this);
8893 if ((file = GetCurrentFile())) {
8894 pf = GetReadCache(file);
8895 file->SetCacheRead(0,this,TFile::kDoNotDisconnect);
8896 }
8897 }
8898 // This changes our hash value.
8899 fName = name;
8900 fTitle = title;
8901 if (fDirectory) {
8902 fDirectory->Append(this);
8903 if (pf) {
8904 file->SetCacheRead(pf,this,TFile::kDoNotDisconnect);
8905 }
8906 }
8907}
8908
8909////////////////////////////////////////////////////////////////////////////////
8910/// Enable or disable parallel unzipping of Tree buffers.
8912void TTree::SetParallelUnzip(Bool_t opt, Float_t RelSize)
8913{
8916
8917 if (RelSize > 0) {
8919 }
8920
8921}
8922
8923////////////////////////////////////////////////////////////////////////////////
8924/// Set perf stats
8927{
8928 fPerfStats = perf;
8929}
8930
8931////////////////////////////////////////////////////////////////////////////////
8932/// The current TreeIndex is replaced by the new index.
8933/// Note that this function does not delete the previous index.
8934/// This gives the possibility to play with more than one index, e.g.,
8935/// ~~~ {.cpp}
8936/// TVirtualIndex* oldIndex = tree.GetTreeIndex();
8937/// tree.SetTreeIndex(newIndex);
8938/// tree.Draw();
8939/// tree.SetTreeIndex(oldIndex);
8940/// tree.Draw(); etc
8941/// ~~~
8944{
8945 if (fTreeIndex) {
8946 fTreeIndex->SetTree(0);
8947 }
8948 fTreeIndex = index;
8949}
8950
8951////////////////////////////////////////////////////////////////////////////////
8952/// Set tree weight.
8953///
8954/// The weight is used by TTree::Draw to automatically weight each
8955/// selected entry in the resulting histogram.
8956///
8957/// For example the equivalent of:
8958/// ~~~ {.cpp}
8959/// T.Draw("x", "w")
8960/// ~~~
8961/// is:
8962/// ~~~ {.cpp}
8963/// T.SetWeight(w);
8964/// T.Draw("x");
8965/// ~~~
8966/// This function is redefined by TChain::SetWeight. In case of a
8967/// TChain, an option "global" may be specified to set the same weight
8968/// for all trees in the TChain instead of the default behaviour
8969/// using the weights of each tree in the chain (see TChain::SetWeight).
8972{
8973 fWeight = w;
8974}
8975
8976////////////////////////////////////////////////////////////////////////////////
8977/// Print values of all active leaves for entry.
8978///
8979/// - if entry==-1, print current entry (default)
8980/// - if a leaf is an array, a maximum of lenmax elements is printed.
8982void TTree::Show(Long64_t entry, Int_t lenmax)
8983{
8984 if (entry != -1) {
8985 Int_t ret = LoadTree(entry);
8986 if (ret == -2) {
8987 Error("Show()", "Cannot read entry %lld (entry does not exist)", entry);
8988 return;
8989 } else if (ret == -1) {
8990 Error("Show()", "Cannot read entry %lld (I/O error)", entry);
8991 return;
8992 }
8993 ret = GetEntry(entry);
8994 if (ret == -1) {
8995 Error("Show()", "Cannot read entry %lld (I/O error)", entry);
8996 return;
8997 } else if (ret == 0) {
8998 Error("Show()", "Cannot read entry %lld (no data read)", entry);
8999 return;
9000 }
9001 }
9002 printf("======> EVENT:%lld\n", fReadEntry);
9003 TObjArray* leaves = GetListOfLeaves();
9004 Int_t nleaves = leaves->GetEntriesFast();
9005 Int_t ltype;
9006 for (Int_t i = 0; i < nleaves; i++) {
9007 TLeaf* leaf = (TLeaf*) leaves->UncheckedAt(i);
9008 TBranch* branch = leaf->GetBranch();
9009 if (branch->TestBit(kDoNotProcess)) {
9010 continue;
9011 }
9012 Int_t len = leaf->GetLen();
9013 if (len <= 0) {
9014 continue;
9015 }
9016 len = TMath::Min(len, lenmax);
9017 if (leaf->IsA() == TLeafElement::Class()) {
9018 leaf->PrintValue(lenmax);
9019 continue;
9020 }
9021 if (branch->GetListOfBranches()->GetEntriesFast() > 0) {
9022 continue;
9023 }
9024 ltype = 10;
9025 if (leaf->IsA() == TLeafF::Class()) {
9026 ltype = 5;
9027 }
9028 if (leaf->IsA() == TLeafD::Class()) {
9029 ltype = 5;
9030 }
9031 if (leaf->IsA() == TLeafC::Class()) {
9032 len = 1;
9033 ltype = 5;
9034 };
9035 printf(" %-15s = ", leaf->GetName());
9036 for (Int_t l = 0; l < len; l++) {
9037 leaf->PrintValue(l);
9038 if (l == (len - 1)) {
9039 printf("\n");
9040 continue;
9041 }
9042 printf(", ");
9043 if ((l % ltype) == 0) {
9044 printf("\n ");
9045 }
9046 }
9047 }
9048}
9049
9050////////////////////////////////////////////////////////////////////////////////
9051/// Start the TTreeViewer on this tree.
9052///
9053/// - ww is the width of the canvas in pixels
9054/// - wh is the height of the canvas in pixels
9056void TTree::StartViewer()
9057{
9058 GetPlayer();
9059 if (fPlayer) {
9060 fPlayer->StartViewer(600, 400);
9061 }
9062}
9063
9064////////////////////////////////////////////////////////////////////////////////
9065/// Stop the cache learning phase
9066///
9067/// Returns:
9068/// - 0 learning phase stopped or not active
9069/// - -1 on error
9072{
9073 if (!GetTree()) {
9074 if (LoadTree(0)<0) {
9075 Error("StopCacheLearningPhase","Could not load a tree");
9076 return -1;
9077 }
9078 }
9079 if (GetTree()) {
9080 if (GetTree() != this) {
9081 return GetTree()->StopCacheLearningPhase();
9082 }
9083 } else {
9084 Error("StopCacheLearningPhase", "No tree is available. Could not stop cache learning phase");
9085 return -1;
9086 }
9087
9088 TFile *f = GetCurrentFile();
9089 if (!f) {
9090 Error("StopCacheLearningPhase", "No file is available. Could not stop cache learning phase");
9091 return -1;
9092 }
9094 if (!tc) {
9095 Error("StopCacheLearningPhase", "No cache is available. Could not stop learning phase");
9096 return -1;
9097 }
9098 tc->StopLearningPhase();
9099 return 0;
9100}
9101
9102////////////////////////////////////////////////////////////////////////////////
9103/// Set the fTree member for all branches and sub branches.
9105static void TBranch__SetTree(TTree *tree, TObjArray &branches)
9106{
9107 Int_t nb = branches.GetEntriesFast();
9108 for (Int_t i = 0; i < nb; ++i) {
9109 TBranch* br = (TBranch*) branches.UncheckedAt(i);
9110 br->SetTree(tree);
9111
9112 Int_t nBaskets = br->GetListOfBaskets()->GetEntries();
9113 Int_t writeBasket = br->GetWriteBasket();
9114 for (Int_t j=writeBasket,n=0;j>=0 && n<nBaskets;--j) {
9115 TBasket *bk = (TBasket*)br->GetListOfBaskets()->UncheckedAt(j);
9116 if (bk) {
9117 tree->IncrementTotalBuffers(bk->GetBufferSize());
9118 ++n;
9119 }
9120 }
9121
9123 }
9124}
9125
9126////////////////////////////////////////////////////////////////////////////////
9127/// Set the fTree member for all friend elements.
9130{
9131 if (frlist) {
9132 TObjLink *lnk = frlist->FirstLink();
9133 while (lnk) {
9134 TFriendElement *elem = (TFriendElement*)lnk->GetObject();
9135 elem->fParentTree = tree;
9136 lnk = lnk->Next();
9137 }
9138 }
9139}
9140
9141////////////////////////////////////////////////////////////////////////////////
9142/// Stream a class object.
9143
9144void TTree::Streamer(TBuffer& b)
9145{
9146 if (b.IsReading()) {
9147 UInt_t R__s, R__c;
9148 if (fDirectory) {
9149 fDirectory->Remove(this);
9150 //delete the file cache if it points to this Tree
9153 }
9154 fDirectory = 0;
9157 Version_t R__v = b.ReadVersion(&R__s, &R__c);
9158 if (R__v > 4) {
9159 b.ReadClassBuffer(TTree::Class(), this, R__v, R__s, R__c);
9160
9161 fBranches.SetOwner(kTRUE); // True needed only for R__v < 19 and most R__v == 19
9162
9163 if (fBranchRef) fBranchRef->SetTree(this);
9166
9167 if (fTreeIndex) {
9168 fTreeIndex->SetTree(this);
9169 }
9170 if (fIndex.fN) {
9171 Warning("Streamer", "Old style index in this tree is deleted. Rebuild the index via TTree::BuildIndex");
9172 fIndex.Set(0);
9173 fIndexValues.Set(0);
9174 }
9175 if (fEstimate <= 10000) {
9176 fEstimate = 1000000;
9177 }
9178
9179 if (fNClusterRange) {
9180 // The I/O allocated just enough memory to hold the
9181 // current set of ranges.
9183 }
9184 if (GetCacheAutoSize() != 0) {
9185 // a cache will be automatically created.
9186 // No need for TTreePlayer::Process to enable the cache
9187 fCacheSize = 0;
9188 } else if (fAutoFlush < 0) {
9189 // If there is no autoflush set, let's keep the cache completely
9190 // disable by default for now.
9192 } else if (fAutoFlush != 0) {
9193 // Estimate the cluster size.
9194 // This will allow TTree::Process to enable the cache.
9195 Long64_t zipBytes = GetZipBytes();
9196 Long64_t totBytes = GetTotBytes();
9197 if (zipBytes != 0) {
9198 fCacheSize = fAutoFlush*(zipBytes/fEntries);
9199 } else if (totBytes != 0) {
9200 fCacheSize = fAutoFlush*(totBytes/fEntries);
9201 } else {
9202 fCacheSize = 30000000;
9203 }
9204 if (fCacheSize >= (INT_MAX / 4)) {
9205 fCacheSize = INT_MAX / 4;
9206 } else if (fCacheSize == 0) {
9207 fCacheSize = 30000000;
9208 }
9209 } else {
9210 fCacheSize = 0;
9211 }
9213 return;
9214 }
9215 //====process old versions before automatic schema evolution
9216 Stat_t djunk;
9217 Int_t ijunk;
9218 TNamed::Streamer(b);
9219 TAttLine::Streamer(b);
9220 TAttFill::Streamer(b);
9221 TAttMarker::Streamer(b);
9222 b >> fScanField;
9223 b >> ijunk; fMaxEntryLoop = (Long64_t)ijunk;
9224 b >> ijunk; fMaxVirtualSize = (Long64_t)ijunk;
9225 b >> djunk; fEntries = (Long64_t)djunk;
9226 b >> djunk; fTotBytes = (Long64_t)djunk;
9227 b >> djunk; fZipBytes = (Long64_t)djunk;
9228 b >> ijunk; fAutoSave = (Long64_t)ijunk;
9229 b >> ijunk; fEstimate = (Long64_t)ijunk;
9230 if (fEstimate <= 10000) fEstimate = 1000000;
9231 fBranches.Streamer(b);
9232 if (fBranchRef) fBranchRef->SetTree(this);
9234 fLeaves.Streamer(b);
9236 if (R__v > 1) fIndexValues.Streamer(b);
9237 if (R__v > 2) fIndex.Streamer(b);
9238 if (R__v > 3) {
9239 TList OldInfoList;
9240 OldInfoList.Streamer(b);
9241 OldInfoList.Delete();
9242 }
9243 fNClusterRange = 0;
9246 b.CheckByteCount(R__s, R__c, TTree::IsA());
9247 //====end of old versions
9248 } else {
9249 if (fBranchRef) {
9250 fBranchRef->Clear();
9251 }
9253 if (table) TRefTable::SetRefTable(0);
9254
9255 b.WriteClassBuffer(TTree::Class(), this);
9256
9257 if (table) TRefTable::SetRefTable(table);
9258 }
9259}
9260
9261////////////////////////////////////////////////////////////////////////////////
9262/// Unbinned fit of one or more variable(s) from a tree.
9263///
9264/// funcname is a TF1 function.
9265///
9266/// See TTree::Draw for explanations of the other parameters.
9267///
9268/// Fit the variable varexp using the function funcname using the
9269/// selection cuts given by selection.
9270///
9271/// The list of fit options is given in parameter option.
9272///
9273/// - option = "Q" Quiet mode (minimum printing)
9274/// - option = "V" Verbose mode (default is between Q and V)
9275/// - option = "E" Perform better Errors estimation using Minos technique
9276/// - option = "M" More. Improve fit results
9277///
9278/// You can specify boundary limits for some or all parameters via
9279/// ~~~ {.cpp}
9280/// func->SetParLimits(p_number, parmin, parmax);
9281/// ~~~
9282/// if parmin>=parmax, the parameter is fixed
9283///
9284/// Note that you are not forced to fix the limits for all parameters.
9285/// For example, if you fit a function with 6 parameters, you can do:
9286/// ~~~ {.cpp}
9287/// func->SetParameters(0,3.1,1.e-6,0.1,-8,100);
9288/// func->SetParLimits(4,-10,-4);
9289/// func->SetParLimits(5, 1,1);
9290/// ~~~
9291/// With this setup:
9292///
9293/// - Parameters 0->3 can vary freely
9294/// - Parameter 4 has boundaries [-10,-4] with initial value -8
9295/// - Parameter 5 is fixed to 100.
9296///
9297/// For the fit to be meaningful, the function must be self-normalized.
9298///
9299/// i.e. It must have the same integral regardless of the parameter
9300/// settings. Otherwise the fit will effectively just maximize the
9301/// area.
9302///
9303/// It is mandatory to have a normalization variable
9304/// which is fixed for the fit. e.g.
9305/// ~~~ {.cpp}
9306/// TF1* f1 = new TF1("f1", "gaus(0)/sqrt(2*3.14159)/[2]", 0, 5);
9307/// f1->SetParameters(1, 3.1, 0.01);
9308/// f1->SetParLimits(0, 1, 1); // fix the normalization parameter to 1
9309/// data->UnbinnedFit("f1", "jpsimass", "jpsipt>3.0");
9310/// ~~~
9311/// 1, 2 and 3 Dimensional fits are supported. See also TTree::Fit
9312///
9313/// Return status:
9314///
9315/// - The function return the status of the fit in the following form
9316/// fitResult = migradResult + 10*minosResult + 100*hesseResult + 1000*improveResult
9317/// - The fitResult is 0 is the fit is OK.
9318/// - The fitResult is negative in case of an error not connected with the fit.
9319/// - The number of entries used in the fit can be obtained via mytree.GetSelectedRows();
9320/// - If the number of selected entries is null the function returns -1
9322Int_t TTree::UnbinnedFit(const char* funcname, const char* varexp, const char* selection, Option_t* option, Long64_t nentries, Long64_t firstentry)
9323{
9324 GetPlayer();
9325 if (fPlayer) {
9326 return fPlayer->UnbinnedFit(funcname, varexp, selection, option, nentries, firstentry);
9327 }
9328 return -1;
9329}
9330
9331////////////////////////////////////////////////////////////////////////////////
9332/// Replace current attributes by current style.
9335{
9336 if (gStyle->IsReading()) {
9345 } else {
9354 }
9355}
9356
9357////////////////////////////////////////////////////////////////////////////////
9358/// Write this object to the current directory. For more see TObject::Write
9359/// If option & kFlushBasket, call FlushBasket before writing the tree.
9361Int_t TTree::Write(const char *name, Int_t option, Int_t bufsize) const
9362{
9364 return TObject::Write(name, option, bufsize);
9365}
9366
9367////////////////////////////////////////////////////////////////////////////////
9368/// Write this object to the current directory. For more see TObject::Write
9369/// If option & kFlushBasket, call FlushBasket before writing the tree.
9371Int_t TTree::Write(const char *name, Int_t option, Int_t bufsize)
9372{
9373 return ((const TTree*)this)->Write(name, option, bufsize);
9374}
9375
9376////////////////////////////////////////////////////////////////////////////////
9377/// \class TTreeFriendLeafIter
9378///
9379/// Iterator on all the leaves in a TTree and its friend
9380
9382
9383////////////////////////////////////////////////////////////////////////////////
9384/// Create a new iterator. By default the iteration direction
9385/// is kIterForward. To go backward use kIterBackward.
9388: fTree(const_cast<TTree*>(tree))
9389, fLeafIter(0)
9390, fTreeIter(0)
9391, fDirection(dir)
9392{
9393}
9394
9395////////////////////////////////////////////////////////////////////////////////
9396/// Copy constructor. Does NOT copy the 'cursor' location!
9399: TIterator(iter)
9400, fTree(iter.fTree)
9401, fLeafIter(0)
9402, fTreeIter(0)
9403, fDirection(iter.fDirection)
9404{
9405}
9406
9407////////////////////////////////////////////////////////////////////////////////
9408/// Overridden assignment operator. Does NOT copy the 'cursor' location!
9411{
9412 if (this != &rhs && rhs.IsA() == TTreeFriendLeafIter::Class()) {
9413 const TTreeFriendLeafIter &rhs1 = (const TTreeFriendLeafIter &)rhs;
9414 fDirection = rhs1.fDirection;
9415 }
9416 return *this;
9417}
9418
9419////////////////////////////////////////////////////////////////////////////////
9420/// Overridden assignment operator. Does NOT copy the 'cursor' location!
9423{
9424 if (this != &rhs) {
9425 fDirection = rhs.fDirection;
9426 }
9427 return *this;
9428}
9429
9430////////////////////////////////////////////////////////////////////////////////
9431/// Go the next friend element
9434{
9435 if (!fTree) return 0;
9436
9437 TObject * next;
9438 TTree * nextTree;
9439
9440 if (!fLeafIter) {
9441 TObjArray *list = fTree->GetListOfLeaves();
9442 if (!list) return 0; // Can happen with an empty chain.
9444 if (!fLeafIter) return 0;
9445 }
9446
9447 next = fLeafIter->Next();
9448 if (!next) {
9449 if (!fTreeIter) {
9451 if (!list) return next;
9453 if (!fTreeIter) return 0;
9454 }
9455 TFriendElement * nextFriend = (TFriendElement*) fTreeIter->Next();
9456 ///nextTree = (TTree*)fTreeIter->Next();
9457 if (nextFriend) {
9458 nextTree = const_cast<TTree*>(nextFriend->GetTree());
9459 if (!nextTree) return Next();
9462 if (!fLeafIter) return 0;
9463 next = fLeafIter->Next();
9464 }
9465 }
9466 return next;
9467}
9468
9469////////////////////////////////////////////////////////////////////////////////
9470/// Returns the object option stored in the list.
9473{
9474 if (fLeafIter) return fLeafIter->GetOption();
9475 return "";
9476}
void Class()
Definition: Class.C:29
#define R__unlikely(expr)
Definition: RConfig.hxx:604
#define SafeDelete(p)
Definition: RConfig.hxx:543
#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:53
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:218
R__EXTERN TEnv * gEnv
Definition: TEnv.h:171
#define R__ASSERT(e)
Definition: TError.h:96
static unsigned int total
char name[80]
Definition: TGX11.cxx:109
int nentries
Definition: THbookFile.cxx:89
R__EXTERN TInterpreter * gCling
Definition: TInterpreter.h:554
R__EXTERN TVirtualMutex * gROOTMutex
Definition: TROOT.h:59
#define gROOT
Definition: TROOT.h:414
void Printf(const char *fmt,...)
R__EXTERN TStyle * gStyle
Definition: TStyle.h:406
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:4607
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:9128
static void TBranch__SetTree(TTree *tree, TObjArray &branches)
Set the fTree member for all branches and sub branches.
Definition: TTree.cxx:9104
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:65
virtual TLeaf * GetLeaf(const char *name) const
Return pointer to the 1st Leaf named name in thisBranch.
Definition: TBranch.cxx:1892
virtual void SetupAddresses()
If the branch address is not set, we set all addresses starting with the top level parent branch.
Definition: TBranch.cxx:3112
virtual void ResetAddress()
Reset the address of the branch.
Definition: TBranch.cxx:2473
virtual Long64_t GetBasketSeek(Int_t basket) const
Return address of basket in the file.
Definition: TBranch.cxx:1279
virtual char * GetAddress() const
Definition: TBranch.h:181
TTree * GetTree() const
Definition: TBranch.h:220
Int_t GetWriteBasket() const
Definition: TBranch.h:206
virtual void DropBaskets(Option_t *option="")
Loop on all branch baskets.
Definition: TBranch.cxx:735
TObjArray * GetListOfBranches()
Definition: TBranch.h:214
virtual void SetTree(TTree *tree)
Definition: TBranch.h:255
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:2643
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:1580
static void ResetCount()
Static function resetting fgCount.
Definition: TBranch.cxx:2496
virtual void SetObject(void *objadd)
Set object this branch is pointing to.
Definition: TBranch.cxx:2758
Int_t FlushBaskets()
Flush to disk all the baskets of this branch and any of subbranches.
Definition: TBranch.cxx:1113
virtual void SetAddress(void *add)
Set address of this branch.
Definition: TBranch.cxx:2504
Int_t GetNleaves() const
Definition: TBranch.h:217
TObjArray * GetListOfBaskets()
Definition: TBranch.h:213
Long64_t GetEntries() const
Definition: TBranch.h:219
virtual void UpdateFile()
Refresh the value of fDirectory (i.e.
Definition: TBranch.cxx:3122
void SetCompressionSettings(Int_t settings=ROOT::RCompressionSetting::EDefaults::kUseGeneralPurpose)
Set compression settings.
Definition: TBranch.cxx:2627
Int_t GetReadBasket() const
Definition: TBranch.h:204
virtual void Print(Option_t *option="") const
Print TBranch parameters.
Definition: TBranch.cxx:2163
Int_t GetMaxBaskets() const
Definition: TBranch.h:216
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:1727
virtual void KeepCircular(Long64_t maxEntries)
keep a maximum of fMaxEntries in memory
Definition: TBranch.cxx:2105
virtual void ResetAfterMerge(TFileMergeInfo *)
Reset a Branch.
Definition: TBranch.cxx:2420
virtual TBranch * FindBranch(const char *name)
Find the immediate sub-branch with passed name.
Definition: TBranch.cxx:1012
virtual Int_t LoadBaskets()
Baskets associated to this branch are forced to be in memory.
Definition: TBranch.cxx:2131
void SetIOFeatures(TIOFeatures &features)
Definition: TBranch.h:251
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:2042
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:2749
virtual void SetFile(TFile *file=0)
Set file where this branch writes/reads its buffers.
Definition: TBranch.cxx:2685
virtual void SetOffset(Int_t offset=0)
Definition: TBranch.h:253
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:1708
virtual Int_t GetBasketSize() const
Definition: TBranch.h:186
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:2060
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:2551
virtual void Refresh(TBranch *b)
Refresh this branch using new information in b This function is called by TTree::Refresh.
Definition: TBranch.cxx:2330
TObjArray * GetListOfLeaves()
Definition: TBranch.h:215
Int_t Fill()
Definition: TBranch.h:174
virtual void Reset(Option_t *option="")
Reset a Branch.
Definition: TBranch.cxx:2379
TBranch * GetMother() const
Get our top-level parent branch in the tree.
Definition: TBranch.cxx:1964
virtual Int_t FillImpl(ROOT::Internal::TBranchIMTHelper *)
Loop on all leaves of this branch to fill Basket buffer.
Definition: TBranch.cxx:834
Int_t GetEntryOffsetLen() const
Definition: TBranch.h:196
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:4469
Bool_t CanSplit() const
Return true if the data member of this TClass can be saved separately.
Definition: TClass.cxx:2239
ROOT::ESTLType GetCollectionType() const
Return the 'type' of the STL the TClass is representing.
Definition: TClass.cxx:2813
void * New(ENewType defConstructor=kClassNew, Bool_t quiet=kFALSE) const
Return a pointer to a newly allocated object of this class.
Definition: TClass.cxx:4841
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:1950
void Destructor(void *obj, Bool_t dtorOnly=kFALSE)
Explicitly call destructor for object.
Definition: TClass.cxx:5198
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:3635
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:1851
TList * GetListOfBases()
Return list containing the TBaseClass(es) of a class.
Definition: TClass.cxx:3525
Bool_t IsLoaded() const
Return true if the shared library of this class is currently in the a process's memory.
Definition: TClass.cxx:5691
Bool_t IsTObject() const
Return kTRUE is the class inherits from TObject.
Definition: TClass.cxx:5717
TVirtualCollectionProxy * GetCollectionProxy() const
Return the proxy describing the collection (if any).
Definition: TClass.cxx:2824
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:6809
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:6906
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:4737
TClass * GetActualClass(const void *object) const
Return a pointer the the real class of the object.
Definition: TClass.cxx:2535
@ 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:2895
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
virtual void Append(TObject *obj, Bool_t replace=kFALSE)
Append object to this directory.
Describe directory structure in memory.
Definition: TDirectory.h:34
virtual TList * GetList() const
Definition: TDirectory.h:154
virtual Bool_t cd(const char *path=0)
Change current directory to "this" directory.
Definition: TDirectory.cxx:497
virtual void Append(TObject *obj, Bool_t replace=kFALSE)
Append object to this directory.
Definition: TDirectory.cxx:190
virtual TFile * GetFile() const
Definition: TDirectory.h:152
virtual Int_t ReadKeys(Bool_t=kTRUE)
Definition: TDirectory.h:179
virtual Int_t WriteTObject(const TObject *obj, const char *name=0, Option_t *="", Int_t=0)
See TDirectoryFile::WriteTObject for details.
virtual Bool_t IsWritable() const
Definition: TDirectory.h:168
virtual TKey * GetKey(const char *, Short_t=9999) const
Definition: TDirectory.h:153
virtual Int_t ReadTObject(TObject *, const char *)
Definition: TDirectory.h:180
virtual void SaveSelf(Bool_t=kFALSE)
Definition: TDirectory.h:186
virtual TList * GetListOfKeys() const
Definition: TDirectory.h:155
void GetObject(const char *namecycle, T *&ptr)
Definition: TDirectory.h:144
virtual TObject * Remove(TObject *)
Remove an object from the in-memory list.
Streamer around an arbitrary STL like container, which implements basic container functionality.
A List of entry numbers in a TTree or TChain.
Definition: TEntryList.h:26
virtual void SetReapplyCut(Bool_t apply=kFALSE)
Definition: TEntryList.h: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:391
virtual Long64_t GetEND() const
Definition: TFile.h:215
@ kDoNotDisconnect
Definition: TFile.h:65
virtual void Flush()
Synchronize a file's in-memory and on-disk states.
Definition: TFile.cxx:1096
virtual void MakeFree(Long64_t first, Long64_t last)
Mark unused bytes on the file.
Definition: TFile.cxx:1435
static TFile * Open(const char *name, Option_t *option="", const char *ftitle="", Int_t compress=ROOT::RCompressionSetting::EDefaults::kUseGeneralPurpose, Int_t netopt=0)
Create / open a file.
Definition: TFile.cxx:3980
virtual void SetCacheRead(TFileCacheRead *cache, TObject *tree=0, ECacheAction action=kDisconnect)
Set a pointer to the read cache.
Definition: TFile.cxx:2266
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:1254
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:534
Int_t GetKeylen() const
Definition: TKey.h:80
Int_t GetNbytes() const
Definition: TKey.h:82
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:162
virtual void * GetValuePointer() const
Definition: TLeaf.h:117
virtual Int_t GetLenType() const
Definition: TLeaf.h:112
virtual void ReadValue(std::istream &, Char_t=' ')
Definition: TLeaf.h:135
virtual Int_t GetMaximum() const
Definition: TLeaf.h:113
virtual Int_t GetLen() const
Return the number of effective elements of this leaf, for the current entry.
Definition: TLeaf.cxx:311
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:103
virtual Bool_t IncludeRange(TLeaf *)
Definition: TLeaf.h:125
virtual void SetAddress(void *add=0)
Definition: TLeaf.h:164
TBranch * GetBranch() const
Definition: TLeaf.h:99
@ kNewValue
Set if we own the value buffer and so must delete it ourselves.
Definition: TLeaf.h:80
@ kIndirectAddress
Data member is a pointer to an array of basic types.
Definition: TLeaf.h:79
virtual Int_t GetOffset() const
Definition: TLeaf.h:116
virtual void PrintValue(Int_t i=0) const
Definition: TLeaf.h:163
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
@ kBitMask
Definition: TObject.h:82
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
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:356
Color_t GetHistLineColor() const
Definition: TStyle.h:220
Bool_t IsReading() const
Definition: TStyle.h:277
void SetHistLineStyle(Style_t styl=0)
Definition: TStyle.h:359
Style_t GetHistFillStyle() const
Definition: TStyle.h:221
Color_t GetHistFillColor() const
Definition: TStyle.h:219
void SetHistLineColor(Color_t color=1)
Definition: TStyle.h:357
Style_t GetHistLineStyle() const
Definition: TStyle.h:222
void SetHistFillStyle(Style_t styl=0)
Definition: TStyle.h:358
Width_t GetHistLineWidth() const
Definition: TStyle.h:223
void SetHistLineWidth(Width_t width=1)
Definition: TStyle.h:360
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:1652
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:1286
A TTreeCache which exploits parallelized decompression of its own content.
static Int_t SetParallelUnzip(TTreeCacheUnzip::EParUnzipMode option=TTreeCacheUnzip::kEnable)
Static function that (de)activates multithreading unzipping.
static void SetUnzipRelBufferSize(Float_t relbufferSize)
static function: Sets the unzip relatibe buffer size
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:604
TObject * Next()
Go the next friend element.
Definition: TTree.cxx:9432
TTree * fTree
tree being iterated
Definition: TTree.h:607
Option_t * GetOption() const
Returns the object option stored in the list.
Definition: TTree.cxx:9471
TIterator & operator=(const TIterator &rhs)
Overridden assignment operator. Does NOT copy the 'cursor' location!
Definition: TTree.cxx:9409
TIterator * fLeafIter
current leaf sub-iterator.
Definition: TTree.h:608
TIterator * fTreeIter
current tree sub-iterator.
Definition: TTree.h:609
Bool_t fDirection
iteration direction
Definition: TTree.h:610
Helper class to iterate over cluster of baskets.
Definition: TTree.h:247
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:678
Long64_t fNextEntry
Definition: TTree.h:252
Long64_t Next()
Move on to the next cluster and return the starting entry of this next cluster.
Definition: TTree.cxx:634
Long64_t fStartEntry
Definition: TTree.h:251
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:174
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:178
TTree * fTree
Definition: TTree.h:177
~TFriendLock()
Restore the state of tree the same as before we set the lock.
Definition: TTree.cxx:529
Bool_t fPrevious
Definition: TTree.h:179
A TTree represents a columnar dataset.
Definition: TTree.h:71
virtual Int_t Fill()
Fill all branches.
Definition: TTree.cxx:4419
virtual TFriendElement * AddFriend(const char *treename, const char *filename="")
Add a TFriendElement to the list of friends.
Definition: TTree.cxx:1274
TBranchRef * fBranchRef
Branch supporting the TRefTable (if any)
Definition: TTree.h:124
virtual Int_t AddBranchToCache(const char *bname, Bool_t subbranches=kFALSE)
Add branch with name bname to the Tree cache.
Definition: TTree.cxx:1026
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:4655
virtual TBranch * GetBranch(const char *name)
Return pointer to the branch with the given name in this tree or its friends.
Definition: TTree.cxx:5075
static Int_t GetBranchStyle()
Static function returning the current branch style.
Definition: TTree.cxx:5189
TList * fFriends
pointer to list of friend elements
Definition: TTree.h:119
UInt_t fFriendLockStatus
! Record which method is locking the friend recursion
Definition: TTree.h:125
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:5883
Long64_t fTotBytes
Total number of bytes in all branches before compression.
Definition: TTree.h:78
Int_t fMaxClusterRange
! Memory allocated for the cluster range.
Definition: TTree.h:88
virtual void Show(Long64_t entry=-1, Int_t lenmax=20)
Print values of all active leaves for entry.
Definition: TTree.cxx:8981
TEventList * fEventList
! Pointer to event selection list (if one)
Definition: TTree.h:114
virtual Long64_t GetAutoSave() const
Definition: TTree.h:387
virtual Int_t StopCacheLearningPhase()
Stop the cache learning phase.
Definition: TTree.cxx:9070
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:132
virtual void SetCircular(Long64_t maxEntries)
Enable/Disable circularity for this tree.
Definition: TTree.cxx:8548
Long64_t fSavedBytes
Number of autosaved bytes.
Definition: TTree.h:80
virtual TClusterIterator GetClusterIterator(Long64_t firstentry)
Return an iterator over the cluster of baskets starting at firstentry.
Definition: TTree.cxx:5251
virtual void ResetBranchAddress(TBranch *)
Tell all of our branches to set their addresses to zero.
Definition: TTree.cxx:7771
char GetNewlineValue(std::istream &inputStream)
Determine which newline this file is using.
Definition: TTree.cxx:7320
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:2746
TIOFeatures fIOFeatures
IO features to define for newly-written baskets and branches.
Definition: TTree.h:106
virtual Long64_t GetEntryNumberWithIndex(Long64_t major, Long64_t minor=0) const
Return entry number corresponding to major and minor number.
Definition: TTree.cxx:5695
Long64_t fDebugMin
! First entry number to debug
Definition: TTree.h:104
virtual Long64_t SetEntries(Long64_t n=-1)
Change number of entries in the tree.
Definition: TTree.cxx:8667
virtual TObjArray * GetListOfLeaves()
Definition: TTree.h:428
Bool_t fCacheDoClusterPrefetch
! true if cache is prefetching whole clusters
Definition: TTree.h:128
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:1979
virtual TBranch * BranchRef()
Build the optional branch supporting the TRefTable.
Definition: TTree.cxx:2233
TFile * GetCurrentFile() const
Return pointer to the current file.
Definition: TTree.cxx:5263
TList * fAliases
List of aliases for expressions based on the tree branches.
Definition: TTree.h:113
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:3567
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:4937
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:4887
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:8368
Long64_t * fClusterRangeEnd
[fNClusterRange] Last entry of a cluster range.
Definition: TTree.h:95
std::atomic< Long64_t > fIMTZipBytes
! Zip bytes for the IMT flush baskets.
Definition: TTree.h:149
void UseCurrentStyle()
Replace current attributes by current style.
Definition: TTree.cxx:9333
TVirtualTreePlayer * GetPlayer()
Load the TTreePlayer (if not already done).
Definition: TTree.cxx:6083
virtual Long64_t ReadStream(std::istream &inputStream, const char *branchDescriptor="", char delimiter=' ')
Create or simply read branches from an input stream.
Definition: TTree.cxx:7347
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:8584
Int_t fScanField
Number of runs before prompting in Scan.
Definition: TTree.h:84
virtual ~TTree()
Destructor.
Definition: TTree.cxx:902
virtual TTree * GetFriend(const char *) const
Return a pointer to the TTree friend whose name or alias is 'friendname.
Definition: TTree.cxx:5760
virtual Int_t SetBranchAddress(const char *bname, void *add, TBranch **ptr=0)
Change branch address, dealing with clone trees properly.
Definition: TTree.cxx:8049
virtual Double_t GetMaximum(const char *columname)
Return maximum of column with name columname.
Definition: TTree.cxx:6013
virtual Long64_t GetEntryNumberWithBestIndex(Long64_t major, Long64_t minor=0) const
Return entry number corresponding to major and minor number.
Definition: TTree.cxx:5675
static void SetMaxTreeSize(Long64_t maxsize=100000000000LL)
Set the maximum size in bytes of a Tree file (static function).
Definition: TTree.cxx:8843
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:2317
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:9321
Int_t fNClusterRange
Number of Cluster range in addition to the one defined by 'AutoFlush'.
Definition: TTree.h:87
virtual void PrintCacheStats(Option_t *option="") const
Print statistics about the TreeCache for this tree.
Definition: TTree.cxx:7107
virtual Int_t BuildIndex(const char *majorname, const char *minorname="0")
Build a Tree Index (default is TTreeIndex).
Definition: TTree.cxx:2542
TVirtualTreePlayer * fPlayer
! Pointer to current Tree player
Definition: TTree.h:122
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:8823
TObjArray fBranches
List of Branches.
Definition: TTree.h:111
TDirectory * GetDirectory() const
Definition: TTree.h:401
TTreeCache * GetReadCache(TFile *file) const
Find and return the TTreeCache registered with the file and which may contain branches for us.
Definition: TTree.cxx:6096
Bool_t fCacheUserSet
! true if the cache setting was explicitly given by user
Definition: TTree.h:129
Long64_t fEntries
Number of entries.
Definition: TTree.h:76
virtual TFile * ChangeFile(TFile *file)
Called by TTree::Fill() when file has reached its maximum fgMaxTreeSize.
Definition: TTree.cxx:2632
virtual Bool_t GetBranchStatus(const char *branchname) const
Return status of branch with name branchname.
Definition: TTree.cxx:5174
virtual TEntryList * GetEntryList()
Returns the entry list assigned to this tree.
Definition: TTree.cxx:5639
virtual void SetWeight(Double_t w=1, Option_t *option="")
Set tree weight.
Definition: TTree.cxx:8970
void InitializeBranchLists(bool checkLeafCount)
Divides the top-level branches into two vectors: (i) branches to be processed sequentially and (ii) b...
Definition: TTree.cxx:5566
Long64_t * fClusterSize
[fNClusterRange] Number of entries in each cluster for a given range.
Definition: TTree.h:96
Long64_t fFlushedBytes
Number of auto-flushed bytes.
Definition: TTree.h:81
virtual void SetPerfStats(TVirtualPerfStats *perf)
Set perf stats.
Definition: TTree.cxx:8925
std::atomic< Long64_t > fIMTTotBytes
! Total bytes for the IMT flush baskets
Definition: TTree.h:148
virtual void SetCacheLearnEntries(Int_t n=10)
Interface to TTreeCache to set the number of entries for the learning phase.
Definition: TTree.cxx:8521
TEntryList * fEntryList
! Pointer to event selection list (if one)
Definition: TTree.h:115
virtual TVirtualIndex * GetTreeIndex() const
Definition: TTree.h:457
virtual Long64_t Merge(TCollection *list, Option_t *option="")
Merge the trees in the TList into this tree.
Definition: TTree.cxx:6684
virtual void SetMaxVirtualSize(Long64_t size=0)
Definition: TTree.h:561
virtual void DropBaskets()
Remove some baskets from memory.
Definition: TTree.cxx:4338
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:8006
Long64_t fMaxEntryLoop
Maximum number of entries to process.
Definition: TTree.h:90
virtual void SetDirectory(TDirectory *dir)
Change the tree's directory.
Definition: TTree.cxx:8622
virtual Long64_t CopyEntries(TTree *tree, Long64_t nentries=-1, Option_t *option="")
Copy nentries from given tree to this tree.
Definition: TTree.cxx:3398
void SortBranchesByTime()
Sorts top-level branches by the last average task time recorded per branch.
Definition: TTree.cxx:5619
virtual TBranchRef * GetBranchRef() const
Definition: TTree.h:389
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:7187
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:1561
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:8725
void MoveReadCache(TFile *src, TDirectory *dir)
Move a cache from a file to the current file in dir.
Definition: TTree.cxx:6779
Long64_t fAutoFlush
Auto-flush tree when fAutoFlush entries written or -fAutoFlush (compressed) bytes produced.
Definition: TTree.h:93
Int_t fUpdate
Update frequency for EntryLoop.
Definition: TTree.h:85
virtual void ResetAfterMerge(TFileMergeInfo *)
Resets the state of this TTree after a merge (keep the customization but forget the data).
Definition: TTree.cxx:7740
virtual void CopyAddresses(TTree *, Bool_t undo=kFALSE)
Set branch addresses of passed tree equal to ours.
Definition: TTree.cxx:3170
virtual Long64_t GetEntries() const
Definition: TTree.h:402
virtual void SetEstimate(Long64_t nentries=1000000)
Set number of entries to estimate variable limits.
Definition: TTree.cxx:8766
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:5867
Int_t fTimerInterval
Timer interval in milliseconds.
Definition: TTree.h:83
Int_t fDebug
! Debug level
Definition: TTree.h:103
virtual Long64_t AutoSave(Option_t *option="")
AutoSave tree header every fAutoSave bytes.
Definition: TTree.cxx:1426
virtual Long64_t GetEntryNumber(Long64_t entry) const
Return entry number corresponding to entry.
Definition: TTree.cxx:5650
virtual TTree * CloneTree(Long64_t nentries=-1, Option_t *option="")
Create a clone of this tree and copy nentries.
Definition: TTree.cxx:3010
Int_t fFileNumber
! current file number (if file extensions)
Definition: TTree.h:108
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:5973
virtual Long64_t GetZipBytes() const
Definition: TTree.h:484
TObjArray fLeaves
Direct pointers to individual branch leaves.
Definition: TTree.h:112
virtual void Reset(Option_t *option="")
Reset baskets, buffers and entries count in all branches and leaves.
Definition: TTree.cxx:7709
virtual void Print(Option_t *option="") const
Print a summary of the tree contents.
Definition: TTree.cxx:6987
virtual void KeepCircular()
Keep a maximum of fMaxEntries in memory.
Definition: TTree.cxx:6193
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:3667
Long64_t GetCacheAutoSize(Bool_t withDefault=kFALSE) const
Used for automatic sizing of the cache.
Definition: TTree.cxx:5201
virtual Bool_t SetAlias(const char *aliasName, const char *aliasFormula)
Set a tree variable alias.
Definition: TTree.cxx:7842
Long64_t fMaxVirtualSize
Maximum total size of buffers kept in memory.
Definition: TTree.h:91
virtual Long64_t GetTotBytes() const
Definition: TTree.h:455
virtual void SetObject(const char *name, const char *title)
Change the name and title of this tree.
Definition: TTree.cxx:8880
TVirtualPerfStats * fPerfStats
! pointer to the current perf stats object
Definition: TTree.h:120
Double_t fWeight
Tree weight (see TTree::SetWeight)
Definition: TTree.h:82
std::vector< TBranch * > fSeqBranches
! Branches to be processed sequentially when IMT is on
Definition: TTree.h:133
Long64_t fDebugMax
! Last entry number to debug
Definition: TTree.h:105
Int_t fDefaultEntryOffsetLen
Initial Length of fEntryOffset table in the basket buffers.
Definition: TTree.h:86
TTree()
Default constructor and I/O constructor.
Definition: TTree.cxx:721
Long64_t fAutoSave
Autosave tree when fAutoSave entries written or -fAutoSave (compressed) bytes produced.
Definition: TTree.h:92
virtual void SetDefaultEntryOffsetLen(Int_t newdefault, Bool_t updateExisting=kFALSE)
Update the default value for the branch's fEntryOffsetLen.
Definition: TTree.cxx:8596
std::atomic< UInt_t > fAllocationCount
indicates basket should be resized to exact memory usage, but causes significant
Definition: TTree.h:140
virtual Int_t GetEntryWithIndex(Int_t major, Int_t minor=0)
Read entry corresponding to major and minor number.
Definition: TTree.cxx:5712
static TTree * MergeTrees(TList *list, Option_t *option="")
Static function merging the trees in the TList into a new tree.
Definition: TTree.cxx:6641
virtual Long64_t GetReadEntry() const
Definition: TTree.h:448
virtual TObjArray * GetListOfBranches()
Definition: TTree.h:427
virtual void SetParallelUnzip(Bool_t opt=kTRUE, Float_t RelSize=-1)
Enable or disable parallel unzipping of Tree buffers.
Definition: TTree.cxx:8911
Long64_t fZipBytes
Total number of bytes in all branches after compression.
Definition: TTree.h:79
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:7613
virtual TTree * GetTree() const
Definition: TTree.h:456
TBuffer * fTransientBuffer
! Pointer to the current transient buffer.
Definition: TTree.h:126
Bool_t fIMTEnabled
! true if implicit multi-threading is enabled for this tree
Definition: TTree.h:130
virtual void SetEntryList(TEntryList *list, Option_t *opt="")
Set an EntryList.
Definition: TTree.cxx:8702
virtual Int_t DropBranchFromCache(const char *bname, Bool_t subbranches=kFALSE)
Remove the branch with name 'bname' from the Tree cache.
Definition: TTree.cxx:1109
virtual void AddZipBytes(Int_t zip)
Definition: TTree.h:309
virtual Long64_t LoadTree(Long64_t entry)
Set current entry.
Definition: TTree.cxx:6251
virtual Long64_t ReadFile(const char *filename, const char *branchDescriptor="", char delimiter=' ')
Create or simply read branches from filename.
Definition: TTree.cxx:7301
virtual const char * GetAlias(const char *aliasName) const
Returns the expanded value of the alias. Search in the friends if any.
Definition: TTree.cxx:5034
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:8786
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:5422
virtual TBasket * CreateBasket(TBranch *)
Create a basket for this tree and given branch.
Definition: TTree.cxx:3579
TList * fUserInfo
pointer to a list of user objects associated to this Tree
Definition: TTree.h:121
virtual Double_t GetMinimum(const char *columname)
Return minimum of column with name columname.
Definition: TTree.cxx:6053
virtual void RemoveFriend(TTree *)
Remove a friend from the list of friends.
Definition: TTree.cxx:7683
virtual Long64_t GetEntriesFast() const
Definition: TTree.h:404
virtual TList * GetUserInfo()
Return a pointer to the list containing user objects associated to this tree.
Definition: TTree.cxx:6134
Long64_t fChainOffset
! Offset of 1st entry of this Tree in a TChain
Definition: TTree.h:98
@ kOnlyFlushAtCluster
Definition: TTree.h:236
@ kCircular
Definition: TTree.h:235
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:5296
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:7250
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:2309
virtual void SetBasketSize(const char *bname, Int_t buffsize=16000)
Set a branch's basket size.
Definition: TTree.cxx:8022
static void SetBranchStyle(Int_t style=1)
Set the current branch style.
Definition: TTree.cxx:8326
void ImportClusterRanges(TTree *fromtree)
Appends the cluster range information stored in 'fromtree' to this tree, including the value of fAuto...
Definition: TTree.cxx:6150
@ kSplitCollectionOfPointers
Definition: TTree.h:243
Long64_t fEstimate
Number of entries to estimate histogram limits.
Definition: TTree.h:94
Int_t FlushBasketsImpl() const
Internal implementation of the FlushBaskets algorithm.
Definition: TTree.cxx:4954
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:6347
TVirtualIndex * fTreeIndex
Pointer to the tree Index (if any)
Definition: TTree.h:118
virtual void Browse(TBrowser *)
Browse content of the TTree.
Definition: TTree.cxx:2514
virtual Int_t GetTreeNumber() const
Definition: TTree.h:458
TObject * fNotify
! Object to be notified when loading a Tree
Definition: TTree.h:109
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:1480
Long64_t fCacheSize
! Maximum size of file buffers
Definition: TTree.h:97
TList * fClones
! List of cloned trees which share our addresses
Definition: TTree.h:123
std::atomic< Long64_t > fTotalBuffers
! Total number of bytes in branch buffers
Definition: TTree.h:100
Bool_t fCacheDoAutoInit
! true if cache auto creation or resize check is needed
Definition: TTree.h:127
virtual Int_t MakeSelector(const char *selector=0, Option_t *option="")
Generate skeleton selector class for this tree.
Definition: TTree.cxx:6612
@ kFindBranch
Definition: TTree.h:198
@ kFindLeaf
Definition: TTree.h:199
@ kGetEntryWithIndex
Definition: TTree.h:203
@ kPrint
Definition: TTree.h:208
@ kGetFriend
Definition: TTree.h:204
@ kGetBranch
Definition: TTree.h:201
@ kSetBranchStatus
Definition: TTree.h:210
@ kLoadTree
Definition: TTree.h:207
@ kGetEntry
Definition: TTree.h:202
@ kGetLeaf
Definition: TTree.h:206
@ kRemoveFriend
Definition: TTree.h:209
@ kGetFriendAlias
Definition: TTree.h:205
@ kGetAlias
Definition: TTree.h:200
virtual void Draw(Option_t *opt)
Default Draw method for all objects.
Definition: TTree.h:371
virtual Int_t MakeClass(const char *classname=0, Option_t *option="")
Generate a skeleton analysis class for this tree.
Definition: TTree.cxx:6397
virtual void SetTreeIndex(TVirtualIndex *index)
The current TreeIndex is replaced by the new index.
Definition: TTree.cxx:8942
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:6825
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:7235
virtual Int_t SetCacheEntryRange(Long64_t first, Long64_t last)
interface to TTreeCache to set the cache entry range
Definition: TTree.cxx:8487
static Long64_t GetMaxTreeSize()
Static function which returns the tree file size limit in bytes.
Definition: TTree.cxx:6043
Int_t SetBranchAddressImp(TBranch *branch, void *addr, TBranch **ptr)
Change branch address, dealing with clone trees properly.
Definition: TTree.cxx:8106
Long64_t fMaxEntries
Maximum number of entries in case of circular buffers.
Definition: TTree.h:89
virtual void DropBuffers(Int_t nbytes)
Drop branch buffers to accommodate nbytes below MaxVirtualsize.
Definition: TTree.cxx:4351
virtual void SetName(const char *name)
Change the name of this tree.
Definition: TTree.cxx:8851
virtual void Delete(Option_t *option="")
Delete this tree from memory or/and disk.
Definition: TTree.cxx:3595
virtual TList * GetListOfFriends() const
Definition: TTree.h:429
virtual void Refresh()
Refresh contents of this tree and its branches from the current status on disk.
Definition: TTree.cxx:7644
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:7897
static Long64_t fgMaxTreeSize
Maximum size of a file containing a Tree.
Definition: TTree.h:143
Long64_t fReadEntry
! Number of the entry being processed
Definition: TTree.h:99
TArrayD fIndexValues
Sorted index values.
Definition: TTree.h:116
void MarkEventCluster()
Mark the previous event as being at the end of the event cluster.
Definition: TTree.cxx:7959
virtual Int_t MakeCode(const char *filename=0)
Generate a skeleton function for this tree.
Definition: TTree.cxx:6430
UInt_t fNEntriesSinceSorting
! Number of entries processed since the last re-sorting of branches
Definition: TTree.h:131
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:6558
virtual void SetFileNumber(Int_t number=0)
Set fFileNumber to number.
Definition: TTree.cxx:8809
virtual TLeaf * FindLeaf(const char *name)
Find leaf..
Definition: TTree.cxx:4727
virtual void StartViewer()
Start the TTreeViewer on this tree.
Definition: TTree.cxx:9055
Int_t GetMakeClass() const
Definition: TTree.h:434
TDirectory * fDirectory
! Pointer to directory holding this tree
Definition: TTree.h:110
@ kClassMismatch
Definition: TTree.h:223
@ kVoidPtr
Definition: TTree.h:228
@ kMatchConversionCollection
Definition: TTree.h:226
@ kMissingCompiledCollectionProxy
Definition: TTree.h:221
@ kMismatch
Definition: TTree.h:222
@ kMatchConversion
Definition: TTree.h:225
@ kInternalError
Definition: TTree.h:220
@ kMatch
Definition: TTree.h:224
@ kMissingBranch
Definition: TTree.h:219
@ kMakeClass
Definition: TTree.h:227
static Int_t fgBranchStyle
Old/New branch style.
Definition: TTree.h:142
virtual void ResetBranchAddresses()
Tell all of our branches to drop their current objects and allocate new ones.
Definition: TTree.cxx:7781
Int_t fNfill
! Local for EntryLoop
Definition: TTree.h:102
TArrayI fIndex
Index of sorted values.
Definition: TTree.h:117
virtual Int_t SetCacheSize(Long64_t cachesize=-1)
Set maximum size of the file cache .
Definition: TTree.cxx:8342
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:1186
virtual void SetBranchStatus(const char *bname, Bool_t status=1, UInt_t *found=0)
Set branch status to Process or DoNotProcess.
Definition: TTree.cxx:8195
TBuffer * GetTransientBuffer(Int_t size)
Returns the transient buffer currently used by this TTree for reading/writing baskets.
Definition: TTree.cxx:1004
ROOT::TIOFeatures GetIOFeatures() const
Returns the current set of IO settings.
Definition: TTree.cxx:5859
virtual const char * GetFriendAlias(TTree *) const
If the 'tree' is a friend, this method returns its alias name.
Definition: TTree.cxx:5817
virtual Bool_t Notify()
Function called when loading a new class library.
Definition: TTree.cxx:6801
Bool_t MemoryFull(Int_t nbytes)
Check if adding nbytes to memory we are still below MaxVirtualsize.
Definition: TTree.cxx:6627
Int_t fPacketSize
! Number of entries in one packet for parallel root
Definition: TTree.h:101
virtual Int_t Branch(TCollection *list, Int_t bufsize=32000, Int_t splitlevel=99, const char *name="")
Create one branch for each element in the collection.
Definition: TTree.cxx:1741
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:9370
TStreamerInfo * BuildStreamerInfo(TClass *cl, void *pointer=0, Bool_t canOptimize=kTRUE)
Build StreamerInfo for class cl.
Definition: TTree.cxx:2557
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:7800
Bool_t fIMTFlush
! True if we are doing a multithreaded flush.
Definition: TTree.h:147
virtual void AddTotBytes(Int_t tot)
Definition: TTree.h:308
Int_t fMakeClass
! not zero when processing code generated by MakeClass
Definition: TTree.h:107
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:6229
static constexpr Long64_t kMaxEntries
Definition: TTree.h:215
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:6968
virtual Long64_t GetAutoFlush() const
Definition: TTree.h:386
virtual EDataType GetType() const =0
virtual TClass * GetValueClass() const =0
virtual Bool_t HasPointers() const =0
Abstract interface for Tree Index.
Definition: TVirtualIndex.h:29
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
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)
Namespace for new ROOT classes and functions.
Definition: StringConv.hxx:21
Bool_t IsImplicitMTEnabled()
Returns true if the implicit multi-threading in ROOT is enabled.
Definition: TROOT.cxx:610
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:81
@ kInherit
Some objects use this value to denote that the compression algorithm should be inherited from the par...
Definition: Compression.h:79
@ kUseGeneralPurpose
Use the recommended general-purpose setting; moderate read / write speed and compression ratio.
Definition: Compression.h:53
TCanvas * style()
Definition: style.C:1
auto * m
Definition: textangle.C:8
auto * l
Definition: textangle.C:4
auto * a
Definition: textangle.C:12