Logo ROOT  
Reference Guide
TTree.cxx
Go to the documentation of this file.
1// @(#)root/tree:$Id$
2// Author: Rene Brun 12/01/96
3
4/*************************************************************************
5 * Copyright (C) 1995-2000, Rene Brun and Fons Rademakers. *
6 * All rights reserved. *
7 * *
8 * For the licensing terms see $ROOTSYS/LICENSE. *
9 * For the list of contributors see $ROOTSYS/README/CREDITS. *
10 *************************************************************************/
11/**
12 \defgroup tree Tree Library
13
14 In order to store columnar datasets, ROOT provides the TTree, TChain,
15 TNtuple and TNtupleD classes.
16 The TTree class represents a columnar dataset. Any C++ type can be stored in the
17 columns. The TTree has allowed to store about **1 EB** of data coming from the LHC alone:
18 it is demonstrated to scale and it's battle tested. It has been optimized during the years
19 to reduce dataset sizes on disk and to deliver excellent runtime performance.
20 It allows to access only part of the columns of the datasets, too.
21 The TNtuple and TNtupleD classes are specialisations of the TTree class which can
22 only hold single precision and double precision floating-point numbers respectively;
23 The TChain is a collection of TTrees, which can be located also in different files.
24
25*/
26
27/** \class TTree
28\ingroup tree
29
30A TTree represents a columnar dataset. Any C++ type can be stored in its columns.
31
32A TTree, often called in jargon *tree*, consists of a list of independent columns or *branches*,
33represented by the TBranch class.
34Behind each branch, buffers are allocated automatically by ROOT.
35Such buffers are automatically written to disk or kept in memory until the size stored in the
36attribute fMaxVirtualSize is reached.
37Variables of one branch are written to the same buffer. A branch buffer is
38automatically compressed if the file compression attribute is set (default).
39Branches may be written to different files (see TBranch::SetFile).
40
41The ROOT user can decide to make one single branch and serialize one object into
42one single I/O buffer or to make several branches.
43Making several branches is particularly interesting in the data analysis phase,
44when it is desirable to have a high reading rate and not all columns are equally interesting
45
46## Table of contents:
47- [Creating a TTree](#creatingattree)
48- [Add a Column of Fundamental Types and Arrays thereof](#addcolumnoffundamentaltypes)
49- [Add a Column of a STL Collection instances](#addingacolumnofstl)
50- [Add a column holding an object](#addingacolumnofobjs)
51- [Add a column holding a TObjectArray](#addingacolumnofobjs)
52- [Fill the tree](#fillthetree)
53- [Add a column to an already existing Tree](#addcoltoexistingtree)
54- [An Example](#fullexample)
55
56## <a name="creatingattree"></a>Creating a TTree
57
58~~~ {.cpp}
59 TTree tree(name, title)
60~~~
61Creates a Tree with name and title.
62
63Various kinds of branches can be added to a tree:
64- Variables representing fundamental types, simple classes/structures or list of variables: for example for C or Fortran
65structures.
66- Any C++ object or collection, provided by the STL or ROOT.
67
68In the following, the details about the creation of different types of branches are given.
69
70## <a name="addcolumnoffundamentaltypes"></a>Add a column (`branch`) of fundamental types and arrays thereof
71This strategy works also for lists of variables, e.g. to describe simple structures.
72It is strongly reccomended to persistify those as objects rather than lists of leaves.
73
74~~~ {.cpp}
75 auto branch = tree.Branch(branchname, address, leaflist, bufsize)
76~~~
77- address is the address of the first item of a structure
78- leaflist is the concatenation of all the variable names and types
79 separated by a colon character :
80 The variable name and the variable type are separated by a
81 slash (/). The variable type must be 1 character. (Characters
82 after the first are legal and will be appended to the visible
83 name of the leaf, but have no effect.) If no type is given, the
84 type of the variable is assumed to be the same as the previous
85 variable. If the first variable does not have a type, it is
86 assumed of type F by default. The list of currently supported
87 types is given below:
88 - `C` : a character string terminated by the 0 character
89 - `B` : an 8 bit signed integer (`Char_t`)
90 - `b` : an 8 bit unsigned integer (`UChar_t`)
91 - `S` : a 16 bit signed integer (`Short_t`)
92 - `s` : a 16 bit unsigned integer (`UShort_t`)
93 - `I` : a 32 bit signed integer (`Int_t`)
94 - `i` : a 32 bit unsigned integer (`UInt_t`)
95 - `F` : a 32 bit floating point (`Float_t`)
96 - `f` : a 24 bit floating point with truncated mantissa (`Float16_t`)
97 - `D` : a 64 bit floating point (`Double_t`)
98 - `d` : a 24 bit truncated floating point (`Double32_t`)
99 - `L` : a 64 bit signed integer (`Long64_t`)
100 - `l` : a 64 bit unsigned integer (`ULong64_t`)
101 - `O` : [the letter `o`, not a zero] a boolean (`Bool_t`)
102
103 Examples:
104 - A int: "myVar/I"
105 - A float array with fixed size: "myArrfloat[42]/F"
106 - An double array with variable size, held by the `myvar` column: "myArrdouble[myvar]/D"
107 - An Double32_t array with variable size, held by the `myvar` column , with values between 0 and 16: "myArr[myvar]/d[0,10]"
108
109- If the address points to a single numerical variable, the leaflist is optional:
110~~~ {.cpp}
111 int value;
112 `tree->Branch(branchname, &value);`
113~~~
114- If the address points to more than one numerical variable, we strongly recommend
115 that the variable be sorted in decreasing order of size. Any other order will
116 result in a non-portable TTree (i.e. you will not be able to read it back on a
117 platform with a different padding strategy).
118 We recommend to persistify objects rather than composite leaflists.
119- In case of the truncated floating point types (Float16_t and Double32_t) you can
120 furthermore specify the range in the style [xmin,xmax] or [xmin,xmax,nbits] after
121 the type character. For example, for storing a variable size array `myArr` of
122 `Double32_t` with values within a range of `[0, 2*pi]` and the size of which is
123 stored in a branch called `myArrSize`, the syntax for the `leaflist` string would
124 be: `myArr[myArrSize]/d[0,twopi]`. Of course the number of bits could be specified,
125 the standard rules of opaque typedefs annotation are valid. For example, if only
126 18 bits were sufficient, the syntax would become: `myArr[myArrSize]/d[0,twopi,18]`
127
128## <a name="addingacolumnofstl"></a>Adding a column of STL collection instances (e.g. std::vector, std::list, std::unordered_map)
129
130~~~ {.cpp}
131 auto branch = tree.Branch( branchname, STLcollection, buffsize, splitlevel);
132~~~
133STLcollection is the address of a pointer to std::vector, std::list,
134std::deque, std::set or std::multiset containing pointers to objects.
135If the splitlevel is a value bigger than 100 (TTree::kSplitCollectionOfPointers)
136then the collection will be written in split mode, e.g. if it contains objects of
137any types deriving from TTrack this function will sort the objects
138based on their type and store them in separate branches in split
139mode.
140
141~~~ {.cpp}
142 branch->SetAddress(void *address)
143~~~
144In case of dynamic structures changing with each entry for example, one must
145redefine the branch address before filling the branch again.
146This is done via the TBranch::SetAddress member function.
147
148## <a name="addingacolumnofobjs">Add a column of objects
149
150~~~ {.cpp}
151 MyClass object;
152 auto branch = tree.Branch(branchname, &object, bufsize, splitlevel)
153~~~
154Note: The 2nd parameter must be the address of a valid object.
155 The object must not be destroyed (i.e. be deleted) until the TTree
156 is deleted or TTree::ResetBranchAddress is called.
157
158- if splitlevel=0, the object is serialized in the branch buffer.
159- if splitlevel=1 (default), this branch will automatically be split
160 into subbranches, with one subbranch for each data member or object
161 of the object itself. In case the object member is a TClonesArray,
162 the mechanism described in case C is applied to this array.
163- if splitlevel=2 ,this branch will automatically be split
164 into subbranches, with one subbranch for each data member or object
165 of the object itself. In case the object member is a TClonesArray,
166 it is processed as a TObject*, only one branch.
167
168Another available syntax is the following:
169
170~~~ {.cpp}
171 auto branch = tree.Branch(branchname, &p_object, bufsize, splitlevel)
172 auto branch = tree.Branch(branchname, className, &p_object, bufsize, splitlevel)
173~~~
174- p_object is a pointer to an object.
175- If className is not specified, Branch uses the type of p_object to determine the
176 type of the object.
177- If className is used to specify explicitly the object type, the className must
178 be of a type related to the one pointed to by the pointer. It should be either
179 a parent or derived class.
180
181Note: The pointer whose address is passed to TTree::Branch must not
182 be destroyed (i.e. go out of scope) until the TTree is deleted or
183 TTree::ResetBranchAddress is called.
184
185Note: The pointer p_object must be initialized before calling TTree::Branch
186- Do either:
187~~~ {.cpp}
188 MyDataClass* p_object = nullptr;
189 tree.Branch(branchname, &p_object);
190~~~
191- Or:
192~~~ {.cpp}
193 auto p_object = new MyDataClass;
194 tree.Branch(branchname, &p_object);
195~~~
196Whether the pointer is set to zero or not, the ownership of the object
197is not taken over by the TTree. I.e. even though an object will be allocated
198by TTree::Branch if the pointer p_object is zero, the object will <b>not</b>
199be deleted when the TTree is deleted.
200
201## <a name="addingacolumnoftclonesarray">Add a column of TClonesArray instances
202
203*It is recommended to use STL containers instead of TClonesArrays*.
204
205~~~ {.cpp}
206 // clonesarray is the address of a pointer to a TClonesArray.
207 auto branch = tree.Branch(branchname,clonesarray, bufsize, splitlevel)
208~~~
209The TClonesArray is a direct access list of objects of the same class.
210For example, if the TClonesArray is an array of TTrack objects,
211this function will create one subbranch for each data member of
212the object TTrack.
213
214## <a name="fillthetree">Fill the Tree:
215
216A TTree instance is filled with the invocation of the TTree::Fill method:
217~~~ {.cpp}
218 tree.Fill()
219~~~
220Upon its invocation, a loop on all defined branches takes place that for each branch invokes
221the TBranch::Fill method.
222
223## <a name="addcoltoexistingtree">Add a column to an already existing Tree
224
225You may want to add a branch to an existing tree. For example,
226if one variable in the tree was computed with a certain algorithm,
227you may want to try another algorithm and compare the results.
228One solution is to add a new branch, fill it, and save the tree.
229The code below adds a simple branch to an existing tree.
230Note the kOverwrite option in the Write method, it overwrites the
231existing tree. If it is not specified, two copies of the tree headers
232are saved.
233~~~ {.cpp}
234 void tree3AddBranch() {
235 TFile f("tree3.root", "update");
236
237 Float_t new_v;
238 auto t3 = f->Get<TTree>("t3");
239 auto newBranch = t3->Branch("new_v", &new_v, "new_v/F");
240
241 Long64_t nentries = t3->GetEntries(); // read the number of entries in the t3
242
243 for (Long64_t i = 0; i < nentries; i++) {
244 new_v = gRandom->Gaus(0, 1);
245 newBranch->Fill();
246 }
247
248 t3->Write("", TObject::kOverwrite); // save only the new version of the tree
249 }
250~~~
251It is not always possible to add branches to existing datasets stored in TFiles: for example,
252these files might not be writeable, just readable. In addition, modifying in place a TTree
253causes a new TTree instance to be written and the previous one to be deleted.
254For this reasons, ROOT offers the concept of friends for TTree and TChain:
255if is good practice to rely on friend trees rather than adding a branch manually.
256
257## <a name="fullexample">An Example
258
259Begin_Macro
260../../../tutorials/tree/tree.C
261End_Macro
262
263~~~ {.cpp}
264 // A simple example with histograms and a tree
265 //
266 // This program creates :
267 // - a one dimensional histogram
268 // - a two dimensional histogram
269 // - a profile histogram
270 // - a tree
271 //
272 // These objects are filled with some random numbers and saved on a file.
273
274 #include "TFile.h"
275 #include "TH1.h"
276 #include "TH2.h"
277 #include "TProfile.h"
278 #include "TRandom.h"
279 #include "TTree.h"
280
281 //__________________________________________________________________________
282 main(int argc, char **argv)
283 {
284 // Create a new ROOT binary machine independent file.
285 // Note that this file may contain any kind of ROOT objects, histograms,trees
286 // pictures, graphics objects, detector geometries, tracks, events, etc..
287 // This file is now becoming the current directory.
288 TFile hfile("htree.root","RECREATE","Demo ROOT file with histograms & trees");
289
290 // Create some histograms and a profile histogram
291 TH1F hpx("hpx","This is the px distribution",100,-4,4);
292 TH2F hpxpy("hpxpy","py ps px",40,-4,4,40,-4,4);
293 TProfile hprof("hprof","Profile of pz versus px",100,-4,4,0,20);
294
295 // Define some simple structures
296 typedef struct {Float_t x,y,z;} POINT;
297 typedef struct {
298 Int_t ntrack,nseg,nvertex;
299 UInt_t flag;
300 Float_t temperature;
301 } EVENTN;
302 POINT point;
303 EVENTN eventn;
304
305 // Create a ROOT Tree
306 TTree tree("T","An example of ROOT tree with a few branches");
307 tree.Branch("point",&point,"x:y:z");
308 tree.Branch("eventn",&eventn,"ntrack/I:nseg:nvertex:flag/i:temperature/F");
309 tree.Branch("hpx","TH1F",&hpx,128000,0);
310
311 Float_t px,py,pz;
312
313 // Here we start a loop on 1000 events
314 for ( Int_t i=0; i<1000; i++) {
315 gRandom->Rannor(px,py);
316 pz = px*px + py*py;
317 const auto random = gRandom->::Rndm(1);
318
319 // Fill histograms
320 hpx.Fill(px);
321 hpxpy.Fill(px,py,1);
322 hprof.Fill(px,pz,1);
323
324 // Fill structures
325 point.x = 10*(random-1);
326 point.y = 5*random;
327 point.z = 20*random;
328 eventn.ntrack = Int_t(100*random);
329 eventn.nseg = Int_t(2*eventn.ntrack);
330 eventn.nvertex = 1;
331 eventn.flag = Int_t(random+0.5);
332 eventn.temperature = 20+random;
333
334 // Fill the tree. For each event, save the 2 structures and 3 objects
335 // In this simple example, the objects hpx, hprof and hpxpy are slightly
336 // different from event to event. We expect a big compression factor!
337 tree->Fill();
338 }
339 // End of the loop
340
341 tree.Print();
342
343 // Save all objects in this file
344 hfile.Write();
345
346 // Close the file. Note that this is automatically done when you leave
347 // the application upon file destruction.
348 hfile.Close();
349
350 return 0;
351}
352~~~
353*/
354
355#include <ROOT/RConfig.hxx>
356#include "TTree.h"
357
358#include "ROOT/TIOFeatures.hxx"
359#include "TArrayC.h"
360#include "TBufferFile.h"
361#include "TBaseClass.h"
362#include "TBasket.h"
363#include "TBranchClones.h"
364#include "TBranchElement.h"
365#include "TBranchObject.h"
366#include "TBranchRef.h"
367#include "TBrowser.h"
368#include "TClass.h"
369#include "TClassEdit.h"
370#include "TClonesArray.h"
371#include "TCut.h"
372#include "TDataMember.h"
373#include "TDataType.h"
374#include "TDirectory.h"
375#include "TError.h"
376#include "TEntryList.h"
377#include "TEnv.h"
378#include "TEventList.h"
379#include "TFile.h"
380#include "TFolder.h"
381#include "TFriendElement.h"
382#include "TInterpreter.h"
383#include "TLeaf.h"
384#include "TLeafB.h"
385#include "TLeafC.h"
386#include "TLeafD.h"
387#include "TLeafElement.h"
388#include "TLeafF.h"
389#include "TLeafI.h"
390#include "TLeafL.h"
391#include "TLeafObject.h"
392#include "TLeafS.h"
393#include "TList.h"
394#include "TMath.h"
395#include "TMemFile.h"
396#include "TROOT.h"
397#include "TRealData.h"
398#include "TRegexp.h"
399#include "TStreamerElement.h"
400#include "TStreamerInfo.h"
401#include "TStyle.h"
402#include "TSystem.h"
403#include "TTreeCloner.h"
404#include "TTreeCache.h"
405#include "TTreeCacheUnzip.h"
408#include "TVirtualIndex.h"
409#include "TVirtualPerfStats.h"
410#include "TVirtualPad.h"
411#include "TBranchSTL.h"
412#include "TSchemaRuleSet.h"
413#include "TFileMergeInfo.h"
414#include "ROOT/StringConv.hxx"
415#include "TVirtualMutex.h"
416
417#include "TBranchIMTHelper.h"
418#include "TNotifyLink.h"
419
420#include <chrono>
421#include <cstddef>
422#include <iostream>
423#include <fstream>
424#include <sstream>
425#include <string>
426#include <stdio.h>
427#include <limits.h>
428#include <algorithm>
429#include <set>
430
431#ifdef R__USE_IMT
433#include <thread>
434#endif
436constexpr Int_t kNEntriesResort = 100;
438
439Int_t TTree::fgBranchStyle = 1; // Use new TBranch style with TBranchElement.
440Long64_t TTree::fgMaxTreeSize = 100000000000LL;
441
443
444////////////////////////////////////////////////////////////////////////////////
445////////////////////////////////////////////////////////////////////////////////
446////////////////////////////////////////////////////////////////////////////////
448static char DataTypeToChar(EDataType datatype)
449{
450 // Return the leaflist 'char' for a given datatype.
451
452 switch(datatype) {
453 case kChar_t: return 'B';
454 case kUChar_t: return 'b';
455 case kBool_t: return 'O';
456 case kShort_t: return 'S';
457 case kUShort_t: return 's';
458 case kCounter:
459 case kInt_t: return 'I';
460 case kUInt_t: return 'i';
461 case kDouble_t: return 'D';
462 case kDouble32_t: return 'd';
463 case kFloat_t: return 'F';
464 case kFloat16_t: return 'f';
465 case kLong_t: return 0; // unsupported
466 case kULong_t: return 0; // unsupported?
467 case kchar: return 0; // unsupported
468 case kLong64_t: return 'L';
469 case kULong64_t: return 'l';
470
471 case kCharStar: return 'C';
472 case kBits: return 0; //unsupported
473
474 case kOther_t:
475 case kNoType_t:
476 default:
477 return 0;
478 }
479 return 0;
480}
481
482////////////////////////////////////////////////////////////////////////////////
483/// \class TTree::TFriendLock
484/// Helper class to prevent infinite recursion in the usage of TTree Friends.
485
486////////////////////////////////////////////////////////////////////////////////
487/// Record in tree that it has been used while recursively looks through the friends.
490: fTree(tree)
491{
492 // We could also add some code to acquire an actual
493 // lock to prevent multi-thread issues
494 fMethodBit = methodbit;
495 if (fTree) {
498 } else {
499 fPrevious = 0;
500 }
501}
502
503////////////////////////////////////////////////////////////////////////////////
504/// Copy constructor.
507 fTree(tfl.fTree),
508 fMethodBit(tfl.fMethodBit),
509 fPrevious(tfl.fPrevious)
510{
511}
512
513////////////////////////////////////////////////////////////////////////////////
514/// Assignment operator.
517{
518 if(this!=&tfl) {
519 fTree=tfl.fTree;
520 fMethodBit=tfl.fMethodBit;
521 fPrevious=tfl.fPrevious;
522 }
523 return *this;
524}
525
526////////////////////////////////////////////////////////////////////////////////
527/// Restore the state of tree the same as before we set the lock.
530{
531 if (fTree) {
532 if (!fPrevious) {
533 fTree->fFriendLockStatus &= ~(fMethodBit & kBitMask);
534 }
535 }
536}
537
538////////////////////////////////////////////////////////////////////////////////
539/// \class TTree::TClusterIterator
540/// Helper class to iterate over cluster of baskets.
541
542////////////////////////////////////////////////////////////////////////////////
543/// Regular constructor.
544/// TTree is not set as const, since we might modify if it is a TChain.
546TTree::TClusterIterator::TClusterIterator(TTree *tree, Long64_t firstEntry) : fTree(tree), fClusterRange(0), fStartEntry(0), fNextEntry(0), fEstimatedSize(-1)
547{
548 if (fTree->fNClusterRange) {
549 // Find the correct cluster range.
550 //
551 // Since fClusterRangeEnd contains the inclusive upper end of the range, we need to search for the
552 // range that was containing the previous entry and add 1 (because BinarySearch consider the values
553 // to be the inclusive start of the bucket).
555
556 Long64_t entryInRange;
557 Long64_t pedestal;
558 if (fClusterRange == 0) {
559 pedestal = 0;
560 entryInRange = firstEntry;
561 } else {
562 pedestal = fTree->fClusterRangeEnd[fClusterRange-1] + 1;
563 entryInRange = firstEntry - pedestal;
564 }
565 Long64_t autoflush;
567 autoflush = fTree->fAutoFlush;
568 } else {
569 autoflush = fTree->fClusterSize[fClusterRange];
570 }
571 if (autoflush <= 0) {
572 autoflush = GetEstimatedClusterSize();
573 }
574 fStartEntry = pedestal + entryInRange - entryInRange%autoflush;
575 } else if ( fTree->GetAutoFlush() <= 0 ) {
576 // Case of old files before November 9 2009 *or* small tree where AutoFlush was never set.
577 fStartEntry = firstEntry;
578 } else {
579 fStartEntry = firstEntry - firstEntry%fTree->GetAutoFlush();
580 }
581 fNextEntry = fStartEntry; // Position correctly for the first call to Next()
582}
583
584////////////////////////////////////////////////////////////////////////////////
585/// Estimate the cluster size.
586///
587/// In almost all cases, this quickly returns the size of the auto-flush
588/// in the TTree.
589///
590/// However, in the case where the cluster size was not fixed (old files and
591/// case where autoflush was explicitly set to zero), we need estimate
592/// a cluster size in relation to the size of the cache.
593///
594/// After this value is calculated once for the TClusterIterator, it is
595/// cached and reused in future calls.
598{
599 auto autoFlush = fTree->GetAutoFlush();
600 if (autoFlush > 0) return autoFlush;
601 if (fEstimatedSize > 0) return fEstimatedSize;
602
603 Long64_t zipBytes = fTree->GetZipBytes();
604 if (zipBytes == 0) {
605 fEstimatedSize = fTree->GetEntries() - 1;
606 if (fEstimatedSize <= 0)
607 fEstimatedSize = 1;
608 } else {
609 Long64_t clusterEstimate = 1;
610 Long64_t cacheSize = fTree->GetCacheSize();
611 if (cacheSize == 0) {
612 // Humm ... let's double check on the file.
613 TFile *file = fTree->GetCurrentFile();
614 if (file) {
615 TFileCacheRead *cache = fTree->GetReadCache(file);
616 if (cache) {
617 cacheSize = cache->GetBufferSize();
618 }
619 }
620 }
621 // If neither file nor tree has a cache, use the current default.
622 if (cacheSize <= 0) {
623 cacheSize = 30000000;
624 }
625 clusterEstimate = fTree->GetEntries() * cacheSize / zipBytes;
626 // If there are no entries, then just default to 1.
627 fEstimatedSize = clusterEstimate ? clusterEstimate : 1;
628 }
629 return fEstimatedSize;
630}
631
632////////////////////////////////////////////////////////////////////////////////
633/// Move on to the next cluster and return the starting entry
634/// of this next cluster
637{
638 fStartEntry = fNextEntry;
639 if (fTree->fNClusterRange || fTree->GetAutoFlush() > 0) {
640 if (fClusterRange == fTree->fNClusterRange) {
641 // We are looking at a range which size
642 // is defined by AutoFlush itself and goes to the GetEntries.
643 fNextEntry += GetEstimatedClusterSize();
644 } else {
645 if (fStartEntry > fTree->fClusterRangeEnd[fClusterRange]) {
646 ++fClusterRange;
647 }
648 if (fClusterRange == fTree->fNClusterRange) {
649 // We are looking at the last range which size
650 // is defined by AutoFlush itself and goes to the GetEntries.
651 fNextEntry += GetEstimatedClusterSize();
652 } else {
653 Long64_t clusterSize = fTree->fClusterSize[fClusterRange];
654 if (clusterSize == 0) {
655 clusterSize = GetEstimatedClusterSize();
656 }
657 fNextEntry += clusterSize;
658 if (fNextEntry > fTree->fClusterRangeEnd[fClusterRange]) {
659 // The last cluster of the range was a partial cluster,
660 // so the next cluster starts at the beginning of the
661 // next range.
662 fNextEntry = fTree->fClusterRangeEnd[fClusterRange] + 1;
663 }
664 }
665 }
666 } else {
667 // Case of old files before November 9 2009
668 fNextEntry = fStartEntry + GetEstimatedClusterSize();
669 }
670 if (fNextEntry > fTree->GetEntries()) {
671 fNextEntry = fTree->GetEntries();
672 }
673 return fStartEntry;
674}
675
676////////////////////////////////////////////////////////////////////////////////
677/// Move on to the previous cluster and return the starting entry
678/// of this previous cluster
681{
682 fNextEntry = fStartEntry;
683 if (fTree->fNClusterRange || fTree->GetAutoFlush() > 0) {
684 if (fClusterRange == 0 || fTree->fNClusterRange == 0) {
685 // We are looking at a range which size
686 // is defined by AutoFlush itself.
687 fStartEntry -= GetEstimatedClusterSize();
688 } else {
689 if (fNextEntry <= fTree->fClusterRangeEnd[fClusterRange]) {
690 --fClusterRange;
691 }
692 if (fClusterRange == 0) {
693 // We are looking at the first range.
694 fStartEntry = 0;
695 } else {
696 Long64_t clusterSize = fTree->fClusterSize[fClusterRange];
697 if (clusterSize == 0) {
698 clusterSize = GetEstimatedClusterSize();
699 }
700 fStartEntry -= clusterSize;
701 }
702 }
703 } else {
704 // Case of old files before November 9 2009 or trees that never auto-flushed.
705 fStartEntry = fNextEntry - GetEstimatedClusterSize();
706 }
707 if (fStartEntry < 0) {
708 fStartEntry = 0;
709 }
710 return fStartEntry;
711}
712
713////////////////////////////////////////////////////////////////////////////////
714////////////////////////////////////////////////////////////////////////////////
715////////////////////////////////////////////////////////////////////////////////
716
717////////////////////////////////////////////////////////////////////////////////
718/// Default constructor and I/O constructor.
719///
720/// Note: We do *not* insert ourself into the current directory.
721///
724: TNamed()
725, TAttLine()
726, TAttFill()
727, TAttMarker()
728, fEntries(0)
729, fTotBytes(0)
730, fZipBytes(0)
731, fSavedBytes(0)
732, fFlushedBytes(0)
733, fWeight(1)
735, fScanField(25)
736, fUpdate(0)
740, fMaxEntries(0)
741, fMaxEntryLoop(0)
743, fAutoSave( -300000000)
744, fAutoFlush(-30000000)
745, fEstimate(1000000)
747, fClusterSize(0)
748, fCacheSize(0)
749, fChainOffset(0)
750, fReadEntry(-1)
751, fTotalBuffers(0)
752, fPacketSize(100)
753, fNfill(0)
754, fDebug(0)
755, fDebugMin(0)
756, fDebugMax(9999999)
757, fMakeClass(0)
758, fFileNumber(0)
759, fNotify(0)
760, fDirectory(0)
761, fBranches()
762, fLeaves()
763, fAliases(0)
764, fEventList(0)
765, fEntryList(0)
766, fIndexValues()
767, fIndex()
768, fTreeIndex(0)
769, fFriends(0)
771, fPerfStats(0)
772, fUserInfo(0)
773, fPlayer(0)
774, fClones(0)
775, fBranchRef(0)
783{
784 fMaxEntries = 1000000000;
785 fMaxEntries *= 1000;
786
787 fMaxEntryLoop = 1000000000;
788 fMaxEntryLoop *= 1000;
789
791}
792
793////////////////////////////////////////////////////////////////////////////////
794/// Normal tree constructor.
795///
796/// The tree is created in the current directory.
797/// Use the various functions Branch below to add branches to this tree.
798///
799/// If the first character of title is a "/", the function assumes a folder name.
800/// In this case, it creates automatically branches following the folder hierarchy.
801/// splitlevel may be used in this case to control the split level.
803TTree::TTree(const char* name, const char* title, Int_t splitlevel /* = 99 */,
804 TDirectory* dir /* = gDirectory*/)
805: TNamed(name, title)
806, TAttLine()
807, TAttFill()
808, TAttMarker()
809, fEntries(0)
810, fTotBytes(0)
811, fZipBytes(0)
812, fSavedBytes(0)
813, fFlushedBytes(0)
814, fWeight(1)
815, fTimerInterval(0)
816, fScanField(25)
817, fUpdate(0)
818, fDefaultEntryOffsetLen(1000)
819, fNClusterRange(0)
820, fMaxClusterRange(0)
821, fMaxEntries(0)
822, fMaxEntryLoop(0)
823, fMaxVirtualSize(0)
824, fAutoSave( -300000000)
825, fAutoFlush(-30000000)
826, fEstimate(1000000)
827, fClusterRangeEnd(0)
828, fClusterSize(0)
829, fCacheSize(0)
830, fChainOffset(0)
831, fReadEntry(-1)
832, fTotalBuffers(0)
833, fPacketSize(100)
834, fNfill(0)
835, fDebug(0)
836, fDebugMin(0)
837, fDebugMax(9999999)
838, fMakeClass(0)
839, fFileNumber(0)
840, fNotify(0)
841, fDirectory(dir)
842, fBranches()
843, fLeaves()
844, fAliases(0)
845, fEventList(0)
846, fEntryList(0)
847, fIndexValues()
848, fIndex()
849, fTreeIndex(0)
850, fFriends(0)
851, fExternalFriends(0)
852, fPerfStats(0)
853, fUserInfo(0)
854, fPlayer(0)
855, fClones(0)
856, fBranchRef(0)
857, fFriendLockStatus(0)
858, fTransientBuffer(0)
859, fCacheDoAutoInit(kTRUE)
860, fCacheDoClusterPrefetch(kFALSE)
861, fCacheUserSet(kFALSE)
862, fIMTEnabled(ROOT::IsImplicitMTEnabled())
863, fNEntriesSinceSorting(0)
864{
865 // TAttLine state.
869
870 // TAttFill state.
873
874 // TAttMarkerState.
878
879 fMaxEntries = 1000000000;
880 fMaxEntries *= 1000;
881
882 fMaxEntryLoop = 1000000000;
883 fMaxEntryLoop *= 1000;
884
885 // Insert ourself into the current directory.
886 // FIXME: This is very annoying behaviour, we should
887 // be able to choose to not do this like we
888 // can with a histogram.
889 if (fDirectory) fDirectory->Append(this);
890
892
893 // If title starts with "/" and is a valid folder name, a superbranch
894 // is created.
895 // FIXME: Why?
896 if (strlen(title) > 2) {
897 if (title[0] == '/') {
898 Branch(title+1,32000,splitlevel);
899 }
900 }
901}
902
903////////////////////////////////////////////////////////////////////////////////
904/// Destructor.
907{
908 if (auto link = dynamic_cast<TNotifyLinkBase*>(fNotify)) {
909 link->Clear();
910 }
911 if (fAllocationCount && (gDebug > 0)) {
912 Info("TTree::~TTree", "For tree %s, allocation count is %u.", GetName(), fAllocationCount.load());
913#ifdef R__TRACK_BASKET_ALLOC_TIME
914 Info("TTree::~TTree", "For tree %s, allocation time is %lluus.", GetName(), fAllocationTime.load());
915#endif
916 }
917
918 if (fDirectory) {
919 // We are in a directory, which may possibly be a file.
920 if (fDirectory->GetList()) {
921 // Remove us from the directory listing.
922 fDirectory->Remove(this);
923 }
924 //delete the file cache if it points to this Tree
927 }
928
929 // Remove the TTree from any list (linked to to the list of Cleanups) to avoid the unnecessary call to
930 // this RecursiveRemove while we delete our content.
932 ResetBit(kMustCleanup); // Don't redo it.
933
934 // We don't own the leaves in fLeaves, the branches do.
935 fLeaves.Clear();
936 // I'm ready to destroy any objects allocated by
937 // SetAddress() by my branches. If I have clones,
938 // tell them to zero their pointers to this shared
939 // memory.
940 if (fClones && fClones->GetEntries()) {
941 // I have clones.
942 // I am about to delete the objects created by
943 // SetAddress() which we are sharing, so tell
944 // the clones to release their pointers to them.
945 for (TObjLink* lnk = fClones->FirstLink(); lnk; lnk = lnk->Next()) {
946 TTree* clone = (TTree*) lnk->GetObject();
947 // clone->ResetBranchAddresses();
948
949 // Reset only the branch we have set the address of.
950 CopyAddresses(clone,kTRUE);
951 }
952 }
953 // Get rid of our branches, note that this will also release
954 // any memory allocated by TBranchElement::SetAddress().
956
957 // The TBranch destructor is using fDirectory to detect whether it
958 // owns the TFile that contains its data (See TBranch::~TBranch)
959 fDirectory = nullptr;
960
961 // FIXME: We must consider what to do with the reset of these if we are a clone.
962 delete fPlayer;
963 fPlayer = 0;
964 if (fExternalFriends) {
965 using namespace ROOT::Detail;
967 fetree->Reset();
968 fExternalFriends->Clear("nodelete");
970 }
971 if (fFriends) {
972 fFriends->Delete();
973 delete fFriends;
974 fFriends = 0;
975 }
976 if (fAliases) {
977 fAliases->Delete();
978 delete fAliases;
979 fAliases = 0;
980 }
981 if (fUserInfo) {
982 fUserInfo->Delete();
983 delete fUserInfo;
984 fUserInfo = 0;
985 }
986 if (fClones) {
987 // Clone trees should no longer be removed from fClones when they are deleted.
988 {
990 gROOT->GetListOfCleanups()->Remove(fClones);
991 }
992 // Note: fClones does not own its content.
993 delete fClones;
994 fClones = 0;
995 }
996 if (fEntryList) {
998 // Delete the entry list if it is marked to be deleted and it is not also
999 // owned by a directory. (Otherwise we would need to make sure that a
1000 // TDirectoryFile that has a TTree in it does a 'slow' TList::Delete.
1001 delete fEntryList;
1002 fEntryList=0;
1003 }
1004 }
1005 delete fTreeIndex;
1006 fTreeIndex = 0;
1007 delete fBranchRef;
1008 fBranchRef = 0;
1009 delete [] fClusterRangeEnd;
1010 fClusterRangeEnd = 0;
1011 delete [] fClusterSize;
1012 fClusterSize = 0;
1013
1014 if (fTransientBuffer) {
1015 delete fTransientBuffer;
1016 fTransientBuffer = 0;
1017 }
1018}
1019
1020////////////////////////////////////////////////////////////////////////////////
1021/// Returns the transient buffer currently used by this TTree for reading/writing baskets.
1024{
1025 if (fTransientBuffer) {
1026 if (fTransientBuffer->BufferSize() < size) {
1027 fTransientBuffer->Expand(size);
1028 }
1029 return fTransientBuffer;
1030 }
1032 return fTransientBuffer;
1033}
1034
1035////////////////////////////////////////////////////////////////////////////////
1036/// Add branch with name bname to the Tree cache.
1037/// If bname="*" all branches are added to the cache.
1038/// if subbranches is true all the branches of the subbranches are
1039/// also put to the cache.
1040///
1041/// Returns:
1042/// - 0 branch added or already included
1043/// - -1 on error
1045Int_t TTree::AddBranchToCache(const char*bname, Bool_t subbranches)
1046{
1047 if (!GetTree()) {
1048 if (LoadTree(0)<0) {
1049 Error("AddBranchToCache","Could not load a tree");
1050 return -1;
1051 }
1052 }
1053 if (GetTree()) {
1054 if (GetTree() != this) {
1055 return GetTree()->AddBranchToCache(bname, subbranches);
1056 }
1057 } else {
1058 Error("AddBranchToCache", "No tree is available. Branch was not added to the cache");
1059 return -1;
1060 }
1061
1062 TFile *f = GetCurrentFile();
1063 if (!f) {
1064 Error("AddBranchToCache", "No file is available. Branch was not added to the cache");
1065 return -1;
1066 }
1068 if (!tc) {
1069 Error("AddBranchToCache", "No cache is available, branch not added");
1070 return -1;
1071 }
1072 return tc->AddBranch(bname,subbranches);
1073}
1074
1075////////////////////////////////////////////////////////////////////////////////
1076/// Add branch b to the Tree cache.
1077/// if subbranches is true all the branches of the subbranches are
1078/// also put to the cache.
1079///
1080/// Returns:
1081/// - 0 branch added or already included
1082/// - -1 on error
1085{
1086 if (!GetTree()) {
1087 if (LoadTree(0)<0) {
1088 Error("AddBranchToCache","Could not load a tree");
1089 return -1;
1090 }
1091 }
1092 if (GetTree()) {
1093 if (GetTree() != this) {
1094 Int_t res = GetTree()->AddBranchToCache(b, subbranches);
1095 if (res<0) {
1096 Error("AddBranchToCache", "Error adding branch");
1097 }
1098 return res;
1099 }
1100 } else {
1101 Error("AddBranchToCache", "No tree is available. Branch was not added to the cache");
1102 return -1;
1103 }
1104
1105 TFile *f = GetCurrentFile();
1106 if (!f) {
1107 Error("AddBranchToCache", "No file is available. Branch was not added to the cache");
1108 return -1;
1109 }
1111 if (!tc) {
1112 Error("AddBranchToCache", "No cache is available, branch not added");
1113 return -1;
1114 }
1115 return tc->AddBranch(b,subbranches);
1116}
1117
1118////////////////////////////////////////////////////////////////////////////////
1119/// Remove the branch with name 'bname' from the Tree cache.
1120/// If bname="*" all branches are removed from the cache.
1121/// if subbranches is true all the branches of the subbranches are
1122/// also removed from the cache.
1123///
1124/// Returns:
1125/// - 0 branch dropped or not in cache
1126/// - -1 on error
1128Int_t TTree::DropBranchFromCache(const char*bname, Bool_t subbranches)
1129{
1130 if (!GetTree()) {
1131 if (LoadTree(0)<0) {
1132 Error("DropBranchFromCache","Could not load a tree");
1133 return -1;
1134 }
1135 }
1136 if (GetTree()) {
1137 if (GetTree() != this) {
1138 return GetTree()->DropBranchFromCache(bname, subbranches);
1139 }
1140 } else {
1141 Error("DropBranchFromCache", "No tree is available. Branch was not dropped from the cache");
1142 return -1;
1143 }
1144
1145 TFile *f = GetCurrentFile();
1146 if (!f) {
1147 Error("DropBranchFromCache", "No file is available. Branch was not dropped from the cache");
1148 return -1;
1149 }
1151 if (!tc) {
1152 Error("DropBranchFromCache", "No cache is available, branch not dropped");
1153 return -1;
1154 }
1155 return tc->DropBranch(bname,subbranches);
1156}
1157
1158////////////////////////////////////////////////////////////////////////////////
1159/// Remove the branch b from the Tree cache.
1160/// if subbranches is true all the branches of the subbranches are
1161/// also removed from the cache.
1162///
1163/// Returns:
1164/// - 0 branch dropped or not in cache
1165/// - -1 on error
1168{
1169 if (!GetTree()) {
1170 if (LoadTree(0)<0) {
1171 Error("DropBranchFromCache","Could not load a tree");
1172 return -1;
1173 }
1174 }
1175 if (GetTree()) {
1176 if (GetTree() != this) {
1177 Int_t res = GetTree()->DropBranchFromCache(b, subbranches);
1178 if (res<0) {
1179 Error("DropBranchFromCache", "Error dropping branch");
1180 }
1181 return res;
1182 }
1183 } else {
1184 Error("DropBranchFromCache", "No tree is available. Branch was not dropped from the cache");
1185 return -1;
1186 }
1187
1188 TFile *f = GetCurrentFile();
1189 if (!f) {
1190 Error("DropBranchFromCache", "No file is available. Branch was not dropped from the cache");
1191 return -1;
1192 }
1194 if (!tc) {
1195 Error("DropBranchFromCache", "No cache is available, branch not dropped");
1196 return -1;
1197 }
1198 return tc->DropBranch(b,subbranches);
1199}
1200
1201////////////////////////////////////////////////////////////////////////////////
1202/// Add a cloned tree to our list of trees to be notified whenever we change
1203/// our branch addresses or when we are deleted.
1205void TTree::AddClone(TTree* clone)
1206{
1207 if (!fClones) {
1208 fClones = new TList();
1209 fClones->SetOwner(false);
1210 // So that the clones are automatically removed from the list when
1211 // they are deleted.
1212 {
1214 gROOT->GetListOfCleanups()->Add(fClones);
1215 }
1216 }
1217 if (!fClones->FindObject(clone)) {
1218 fClones->Add(clone);
1219 }
1220}
1221
1222// Check whether mainTree and friendTree can be friends w.r.t. the kEntriesReshuffled bit.
1223// In particular, if any has the bit set, then friendTree must have a TTreeIndex and the
1224// branches used for indexing must be present in mainTree.
1225// Return true if the trees can be friends, false otherwise.
1226bool CheckReshuffling(TTree &mainTree, TTree &friendTree)
1227{
1228 const auto isMainReshuffled = mainTree.TestBit(TTree::kEntriesReshuffled);
1229 const auto isFriendReshuffled = friendTree.TestBit(TTree::kEntriesReshuffled);
1230 const auto friendHasValidIndex = [&] {
1231 auto idx = friendTree.GetTreeIndex();
1232 return idx ? idx->IsValidFor(&mainTree) : kFALSE;
1233 }();
1234
1235 if ((isMainReshuffled || isFriendReshuffled) && !friendHasValidIndex) {
1236 const auto reshuffledTreeName = isMainReshuffled ? mainTree.GetName() : friendTree.GetName();
1237 const auto msg = "Tree '%s' has the kEntriesReshuffled bit set, and cannot be used as friend nor can be added as "
1238 "a friend unless the main tree has a TTreeIndex on the friend tree '%s'. You can also unset the "
1239 "bit manually if you know what you are doing.";
1240 Error("AddFriend", msg, reshuffledTreeName, friendTree.GetName());
1241 return false;
1242 }
1243 return true;
1244}
1245
1246////////////////////////////////////////////////////////////////////////////////
1247/// Add a TFriendElement to the list of friends.
1248///
1249/// This function:
1250/// - opens a file if filename is specified
1251/// - reads a Tree with name treename from the file (current directory)
1252/// - adds the Tree to the list of friends
1253/// see other AddFriend functions
1254///
1255/// A TFriendElement TF describes a TTree object TF in a file.
1256/// When a TFriendElement TF is added to the the list of friends of an
1257/// existing TTree T, any variable from TF can be referenced in a query
1258/// to T.
1259///
1260/// A tree keeps a list of friends. In the context of a tree (or a chain),
1261/// friendship means unrestricted access to the friends data. In this way
1262/// it is much like adding another branch to the tree without taking the risk
1263/// of damaging it. To add a friend to the list, you can use the TTree::AddFriend
1264/// method. The tree in the diagram below has two friends (friend_tree1 and
1265/// friend_tree2) and now has access to the variables a,b,c,i,j,k,l and m.
1266///
1267/// \image html ttree_friend1.png
1268///
1269/// The AddFriend method has two parameters, the first is the tree name and the
1270/// second is the name of the ROOT file where the friend tree is saved.
1271/// AddFriend automatically opens the friend file. If no file name is given,
1272/// the tree called ft1 is assumed to be in the same file as the original tree.
1273///
1274/// tree.AddFriend("ft1","friendfile1.root");
1275/// If the friend tree has the same name as the original tree, you can give it
1276/// an alias in the context of the friendship:
1277///
1278/// tree.AddFriend("tree1 = tree","friendfile1.root");
1279/// Once the tree has friends, we can use TTree::Draw as if the friend's
1280/// variables were in the original tree. To specify which tree to use in
1281/// the Draw method, use the syntax:
1282/// ~~~ {.cpp}
1283/// <treeName>.<branchname>.<varname>
1284/// ~~~
1285/// If the variablename is enough to uniquely identify the variable, you can
1286/// leave out the tree and/or branch name.
1287/// For example, these commands generate a 3-d scatter plot of variable "var"
1288/// in the TTree tree versus variable v1 in TTree ft1 versus variable v2 in
1289/// TTree ft2.
1290/// ~~~ {.cpp}
1291/// tree.AddFriend("ft1","friendfile1.root");
1292/// tree.AddFriend("ft2","friendfile2.root");
1293/// tree.Draw("var:ft1.v1:ft2.v2");
1294/// ~~~
1295/// \image html ttree_friend2.png
1296///
1297/// The picture illustrates the access of the tree and its friends with a
1298/// Draw command.
1299/// When AddFriend is called, the ROOT file is automatically opened and the
1300/// friend tree (ft1) is read into memory. The new friend (ft1) is added to
1301/// the list of friends of tree.
1302/// The number of entries in the friend must be equal or greater to the number
1303/// of entries of the original tree. If the friend tree has fewer entries a
1304/// warning is given and the missing entries are not included in the histogram.
1305/// To retrieve the list of friends from a tree use TTree::GetListOfFriends.
1306/// When the tree is written to file (TTree::Write), the friends list is saved
1307/// with it. And when the tree is retrieved, the trees on the friends list are
1308/// also retrieved and the friendship restored.
1309/// When a tree is deleted, the elements of the friend list are also deleted.
1310/// It is possible to declare a friend tree that has the same internal
1311/// structure (same branches and leaves) as the original tree, and compare the
1312/// same values by specifying the tree.
1313/// ~~~ {.cpp}
1314/// tree.Draw("var:ft1.var:ft2.var")
1315/// ~~~
1317TFriendElement *TTree::AddFriend(const char *treename, const char *filename)
1318{
1319 if (!fFriends) {
1320 fFriends = new TList();
1321 }
1322 TFriendElement *fe = new TFriendElement(this, treename, filename);
1323
1324 TTree *t = fe->GetTree();
1325 bool canAddFriend = true;
1326 if (t) {
1327 canAddFriend = CheckReshuffling(*this, *t);
1328 if (!t->GetTreeIndex() && (t->GetEntries() < fEntries)) {
1329 Warning("AddFriend", "FriendElement %s in file %s has less entries %lld than its parent Tree: %lld", treename,
1330 filename, t->GetEntries(), fEntries);
1331 }
1332 } else {
1333 Error("AddFriend", "Cannot find tree '%s' in file '%s', friend not added", treename, filename);
1334 canAddFriend = false;
1335 }
1336
1337 if (canAddFriend)
1338 fFriends->Add(fe);
1339 return fe;
1340}
1341
1342////////////////////////////////////////////////////////////////////////////////
1343/// Add a TFriendElement to the list of friends.
1344///
1345/// The TFile is managed by the user (e.g. the user must delete the file).
1346/// For complete description see AddFriend(const char *, const char *).
1347/// This function:
1348/// - reads a Tree with name treename from the file
1349/// - adds the Tree to the list of friends
1351TFriendElement *TTree::AddFriend(const char *treename, TFile *file)
1352{
1353 if (!fFriends) {
1354 fFriends = new TList();
1355 }
1356 TFriendElement *fe = new TFriendElement(this, treename, file);
1357 R__ASSERT(fe);
1358 TTree *t = fe->GetTree();
1359 bool canAddFriend = true;
1360 if (t) {
1361 canAddFriend = CheckReshuffling(*this, *t);
1362 if (!t->GetTreeIndex() && (t->GetEntries() < fEntries)) {
1363 Warning("AddFriend", "FriendElement %s in file %s has less entries %lld than its parent tree: %lld", treename,
1364 file->GetName(), t->GetEntries(), fEntries);
1365 }
1366 } else {
1367 Error("AddFriend", "Cannot find tree '%s' in file '%s', friend not added", treename, file->GetName());
1368 canAddFriend = false;
1369 }
1370
1371 if (canAddFriend)
1372 fFriends->Add(fe);
1373 return fe;
1374}
1375
1376////////////////////////////////////////////////////////////////////////////////
1377/// Add a TFriendElement to the list of friends.
1378///
1379/// The TTree is managed by the user (e.g., the user must delete the file).
1380/// For a complete description see AddFriend(const char *, const char *).
1382TFriendElement *TTree::AddFriend(TTree *tree, const char *alias, Bool_t warn)
1383{
1384 if (!tree) {
1385 return 0;
1386 }
1387 if (!fFriends) {
1388 fFriends = new TList();
1389 }
1390 TFriendElement *fe = new TFriendElement(this, tree, alias);
1391 R__ASSERT(fe); // this assert is for historical reasons. Don't remove it unless you understand all the consequences.
1392 TTree *t = fe->GetTree();
1393 if (warn && (t->GetEntries() < fEntries)) {
1394 Warning("AddFriend", "FriendElement '%s' in file '%s' has less entries %lld than its parent tree: %lld",
1395 tree->GetName(), fe->GetFile() ? fe->GetFile()->GetName() : "(memory resident)", t->GetEntries(),
1396 fEntries);
1397 }
1398 if (CheckReshuffling(*this, *t))
1399 fFriends->Add(fe);
1400 else
1401 tree->RemoveExternalFriend(fe);
1402 return fe;
1403}
1404
1405////////////////////////////////////////////////////////////////////////////////
1406/// AutoSave tree header every fAutoSave bytes.
1407///
1408/// When large Trees are produced, it is safe to activate the AutoSave
1409/// procedure. Some branches may have buffers holding many entries.
1410/// If fAutoSave is negative, AutoSave is automatically called by
1411/// TTree::Fill when the number of bytes generated since the previous
1412/// AutoSave is greater than -fAutoSave bytes.
1413/// If fAutoSave is positive, AutoSave is automatically called by
1414/// TTree::Fill every N entries.
1415/// This function may also be invoked by the user.
1416/// Each AutoSave generates a new key on the file.
1417/// Once the key with the tree header has been written, the previous cycle
1418/// (if any) is deleted.
1419///
1420/// Note that calling TTree::AutoSave too frequently (or similarly calling
1421/// TTree::SetAutoSave with a small value) is an expensive operation.
1422/// You should make tests for your own application to find a compromise
1423/// between speed and the quantity of information you may loose in case of
1424/// a job crash.
1425///
1426/// In case your program crashes before closing the file holding this tree,
1427/// the file will be automatically recovered when you will connect the file
1428/// in UPDATE mode.
1429/// The Tree will be recovered at the status corresponding to the last AutoSave.
1430///
1431/// if option contains "SaveSelf", gDirectory->SaveSelf() is called.
1432/// This allows another process to analyze the Tree while the Tree is being filled.
1433///
1434/// if option contains "FlushBaskets", TTree::FlushBaskets is called and all
1435/// the current basket are closed-out and written to disk individually.
1436///
1437/// By default the previous header is deleted after having written the new header.
1438/// if option contains "Overwrite", the previous Tree header is deleted
1439/// before written the new header. This option is slightly faster, but
1440/// the default option is safer in case of a problem (disk quota exceeded)
1441/// when writing the new header.
1442///
1443/// The function returns the number of bytes written to the file.
1444/// if the number of bytes is null, an error has occurred while writing
1445/// the header to the file.
1446///
1447/// ## How to write a Tree in one process and view it from another process
1448///
1449/// The following two scripts illustrate how to do this.
1450/// The script treew.C is executed by process1, treer.C by process2
1451///
1452/// script treew.C:
1453/// ~~~ {.cpp}
1454/// void treew() {
1455/// TFile f("test.root","recreate");
1456/// TNtuple *ntuple = new TNtuple("ntuple","Demo","px:py:pz:random:i");
1457/// Float_t px, py, pz;
1458/// for ( Int_t i=0; i<10000000; i++) {
1459/// gRandom->Rannor(px,py);
1460/// pz = px*px + py*py;
1461/// Float_t random = gRandom->Rndm(1);
1462/// ntuple->Fill(px,py,pz,random,i);
1463/// if (i%1000 == 1) ntuple->AutoSave("SaveSelf");
1464/// }
1465/// }
1466/// ~~~
1467/// script treer.C:
1468/// ~~~ {.cpp}
1469/// void treer() {
1470/// TFile f("test.root");
1471/// TTree *ntuple = (TTree*)f.Get("ntuple");
1472/// TCanvas c1;
1473/// Int_t first = 0;
1474/// while(1) {
1475/// if (first == 0) ntuple->Draw("px>>hpx", "","",10000000,first);
1476/// else ntuple->Draw("px>>+hpx","","",10000000,first);
1477/// first = (Int_t)ntuple->GetEntries();
1478/// c1.Update();
1479/// gSystem->Sleep(1000); //sleep 1 second
1480/// ntuple->Refresh();
1481/// }
1482/// }
1483/// ~~~
1486{
1487 if (!fDirectory || fDirectory == gROOT || !fDirectory->IsWritable()) return 0;
1488 if (gDebug > 0) {
1489 Info("AutoSave", "Tree:%s after %lld bytes written\n",GetName(),GetTotBytes());
1490 }
1491 TString opt = option;
1492 opt.ToLower();
1493
1494 if (opt.Contains("flushbaskets")) {
1495 if (gDebug > 0) Info("AutoSave", "calling FlushBaskets \n");
1497 }
1498
1500
1502 Long64_t nbytes;
1503 if (opt.Contains("overwrite")) {
1504 nbytes = fDirectory->WriteTObject(this,"","overwrite");
1505 } else {
1506 nbytes = fDirectory->WriteTObject(this); //nbytes will be 0 if Write failed (disk space exceeded)
1507 if (nbytes && key && strcmp(ClassName(), key->GetClassName()) == 0) {
1508 key->Delete();
1509 delete key;
1510 }
1511 }
1512 // save StreamerInfo
1514 if (file) file->WriteStreamerInfo();
1515
1516 if (opt.Contains("saveself")) {
1518 //the following line is required in case GetUserInfo contains a user class
1519 //for which the StreamerInfo must be written. One could probably be a bit faster (Rene)
1520 if (file) file->WriteHeader();
1521 }
1522
1523 return nbytes;
1524}
1525
1526namespace {
1527 // This error message is repeated several times in the code. We write it once.
1528 const char* writeStlWithoutProxyMsg = "The class requested (%s) for the branch \"%s\""
1529 " is an instance of an stl collection and does not have a compiled CollectionProxy."
1530 " Please generate the dictionary for this collection (%s) to avoid to write corrupted data.";
1531}
1532
1533////////////////////////////////////////////////////////////////////////////////
1534/// Same as TTree::Branch() with added check that addobj matches className.
1535///
1536/// See TTree::Branch() for other details.
1537///
1539TBranch* TTree::BranchImp(const char* branchname, const char* classname, TClass* ptrClass, void* addobj, Int_t bufsize, Int_t splitlevel)
1540{
1541 TClass* claim = TClass::GetClass(classname);
1542 if (!ptrClass) {
1543 if (claim && claim->GetCollectionProxy() && dynamic_cast<TEmulatedCollectionProxy*>(claim->GetCollectionProxy())) {
1544 Error("Branch", writeStlWithoutProxyMsg,
1545 claim->GetName(), branchname, claim->GetName());
1546 return 0;
1547 }
1548 return Branch(branchname, classname, (void*) addobj, bufsize, splitlevel);
1549 }
1550 TClass* actualClass = 0;
1551 void** addr = (void**) addobj;
1552 if (addr) {
1553 actualClass = ptrClass->GetActualClass(*addr);
1554 }
1555 if (ptrClass && claim) {
1556 if (!(claim->InheritsFrom(ptrClass) || ptrClass->InheritsFrom(claim))) {
1557 // Note we currently do not warn in case of splicing or over-expectation).
1558 if (claim->IsLoaded() && ptrClass->IsLoaded() && strcmp( claim->GetTypeInfo()->name(), ptrClass->GetTypeInfo()->name() ) == 0) {
1559 // The type is the same according to the C++ type_info, we must be in the case of
1560 // a template of Double32_t. This is actually a correct case.
1561 } else {
1562 Error("Branch", "The class requested (%s) for \"%s\" is different from the type of the pointer passed (%s)",
1563 claim->GetName(), branchname, ptrClass->GetName());
1564 }
1565 } else if (actualClass && (claim != actualClass) && !actualClass->InheritsFrom(claim)) {
1566 if (claim->IsLoaded() && actualClass->IsLoaded() && strcmp( claim->GetTypeInfo()->name(), actualClass->GetTypeInfo()->name() ) == 0) {
1567 // The type is the same according to the C++ type_info, we must be in the case of
1568 // a template of Double32_t. This is actually a correct case.
1569 } else {
1570 Error("Branch", "The actual class (%s) of the object provided for the definition of the branch \"%s\" does not inherit from %s",
1571 actualClass->GetName(), branchname, claim->GetName());
1572 }
1573 }
1574 }
1575 if (claim && claim->GetCollectionProxy() && dynamic_cast<TEmulatedCollectionProxy*>(claim->GetCollectionProxy())) {
1576 Error("Branch", writeStlWithoutProxyMsg,
1577 claim->GetName(), branchname, claim->GetName());
1578 return 0;
1579 }
1580 return Branch(branchname, classname, (void*) addobj, bufsize, splitlevel);
1581}
1582
1583////////////////////////////////////////////////////////////////////////////////
1584/// Same as TTree::Branch but automatic detection of the class name.
1585/// See TTree::Branch for other details.
1587TBranch* TTree::BranchImp(const char* branchname, TClass* ptrClass, void* addobj, Int_t bufsize, Int_t splitlevel)
1588{
1589 if (!ptrClass) {
1590 Error("Branch", "The pointer specified for %s is not of a class known to ROOT", branchname);
1591 return 0;
1592 }
1593 TClass* actualClass = 0;
1594 void** addr = (void**) addobj;
1595 if (addr && *addr) {
1596 actualClass = ptrClass->GetActualClass(*addr);
1597 if (!actualClass) {
1598 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",
1599 branchname, ptrClass->GetName());
1600 actualClass = ptrClass;
1601 } else if ((ptrClass != actualClass) && !actualClass->InheritsFrom(ptrClass)) {
1602 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());
1603 return 0;
1604 }
1605 } else {
1606 actualClass = ptrClass;
1607 }
1608 if (actualClass && actualClass->GetCollectionProxy() && dynamic_cast<TEmulatedCollectionProxy*>(actualClass->GetCollectionProxy())) {
1609 Error("Branch", writeStlWithoutProxyMsg,
1610 actualClass->GetName(), branchname, actualClass->GetName());
1611 return 0;
1612 }
1613 return Branch(branchname, actualClass->GetName(), (void*) addobj, bufsize, splitlevel);
1614}
1615
1616////////////////////////////////////////////////////////////////////////////////
1617/// Same as TTree::Branch but automatic detection of the class name.
1618/// See TTree::Branch for other details.
1620TBranch* TTree::BranchImpRef(const char* branchname, const char *classname, TClass* ptrClass, void *addobj, Int_t bufsize, Int_t splitlevel)
1621{
1622 TClass* claim = TClass::GetClass(classname);
1623 if (!ptrClass) {
1624 if (claim && claim->GetCollectionProxy() && dynamic_cast<TEmulatedCollectionProxy*>(claim->GetCollectionProxy())) {
1625 Error("Branch", writeStlWithoutProxyMsg,
1626 claim->GetName(), branchname, claim->GetName());
1627 return 0;
1628 } else if (claim == 0) {
1629 Error("Branch", "The pointer specified for %s is not of a class known to ROOT and %s is not a known class", branchname, classname);
1630 return 0;
1631 }
1632 ptrClass = claim;
1633 }
1634 TClass* actualClass = 0;
1635 if (!addobj) {
1636 Error("Branch", "Reference interface requires a valid object (for branch: %s)!", branchname);
1637 return 0;
1638 }
1639 actualClass = ptrClass->GetActualClass(addobj);
1640 if (ptrClass && claim) {
1641 if (!(claim->InheritsFrom(ptrClass) || ptrClass->InheritsFrom(claim))) {
1642 // Note we currently do not warn in case of splicing or over-expectation).
1643 if (claim->IsLoaded() && ptrClass->IsLoaded() && strcmp( claim->GetTypeInfo()->name(), ptrClass->GetTypeInfo()->name() ) == 0) {
1644 // The type is the same according to the C++ type_info, we must be in the case of
1645 // a template of Double32_t. This is actually a correct case.
1646 } else {
1647 Error("Branch", "The class requested (%s) for \"%s\" is different from the type of the object passed (%s)",
1648 claim->GetName(), branchname, ptrClass->GetName());
1649 }
1650 } else if (actualClass && (claim != actualClass) && !actualClass->InheritsFrom(claim)) {
1651 if (claim->IsLoaded() && actualClass->IsLoaded() && strcmp( claim->GetTypeInfo()->name(), actualClass->GetTypeInfo()->name() ) == 0) {
1652 // The type is the same according to the C++ type_info, we must be in the case of
1653 // a template of Double32_t. This is actually a correct case.
1654 } else {
1655 Error("Branch", "The actual class (%s) of the object provided for the definition of the branch \"%s\" does not inherit from %s",
1656 actualClass->GetName(), branchname, claim->GetName());
1657 }
1658 }
1659 }
1660 if (!actualClass) {
1661 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",
1662 branchname, ptrClass->GetName());
1663 actualClass = ptrClass;
1664 } else if ((ptrClass != actualClass) && !actualClass->InheritsFrom(ptrClass)) {
1665 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());
1666 return 0;
1667 }
1668 if (actualClass && actualClass->GetCollectionProxy() && dynamic_cast<TEmulatedCollectionProxy*>(actualClass->GetCollectionProxy())) {
1669 Error("Branch", writeStlWithoutProxyMsg,
1670 actualClass->GetName(), branchname, actualClass->GetName());
1671 return 0;
1672 }
1673 return BronchExec(branchname, actualClass->GetName(), (void*) addobj, kFALSE, bufsize, splitlevel);
1674}
1675
1676////////////////////////////////////////////////////////////////////////////////
1677/// Same as TTree::Branch but automatic detection of the class name.
1678/// See TTree::Branch for other details.
1680TBranch* TTree::BranchImpRef(const char* branchname, TClass* ptrClass, EDataType datatype, void* addobj, Int_t bufsize, Int_t splitlevel)
1681{
1682 if (!ptrClass) {
1683 if (datatype == kOther_t || datatype == kNoType_t) {
1684 Error("Branch", "The pointer specified for %s is not of a class or type known to ROOT", branchname);
1685 } else {
1686 TString varname; varname.Form("%s/%c",branchname,DataTypeToChar(datatype));
1687 return Branch(branchname,addobj,varname.Data(),bufsize);
1688 }
1689 return 0;
1690 }
1691 TClass* actualClass = 0;
1692 if (!addobj) {
1693 Error("Branch", "Reference interface requires a valid object (for branch: %s)!", branchname);
1694 return 0;
1695 }
1696 actualClass = ptrClass->GetActualClass(addobj);
1697 if (!actualClass) {
1698 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",
1699 branchname, ptrClass->GetName());
1700 actualClass = ptrClass;
1701 } else if ((ptrClass != actualClass) && !actualClass->InheritsFrom(ptrClass)) {
1702 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());
1703 return 0;
1704 }
1705 if (actualClass && actualClass->GetCollectionProxy() && dynamic_cast<TEmulatedCollectionProxy*>(actualClass->GetCollectionProxy())) {
1706 Error("Branch", writeStlWithoutProxyMsg,
1707 actualClass->GetName(), branchname, actualClass->GetName());
1708 return 0;
1709 }
1710 return BronchExec(branchname, actualClass->GetName(), (void*) addobj, kFALSE, bufsize, splitlevel);
1711}
1712
1713////////////////////////////////////////////////////////////////////////////////
1714// Wrapper to turn Branch call with an std::array into the relevant leaf list
1715// call
1716TBranch *TTree::BranchImpArr(const char *branchname, EDataType datatype, std::size_t N, void *addobj, Int_t bufsize,
1717 Int_t /* splitlevel */)
1718{
1719 if (datatype == kOther_t || datatype == kNoType_t) {
1720 Error("Branch",
1721 "The inner type of the std::array passed specified for %s is not of a class or type known to ROOT",
1722 branchname);
1723 } else {
1724 TString varname;
1725 varname.Form("%s[%d]/%c", branchname, (int)N, DataTypeToChar(datatype));
1726 return Branch(branchname, addobj, varname.Data(), bufsize);
1727 }
1728 return nullptr;
1729}
1730
1731////////////////////////////////////////////////////////////////////////////////
1732/// Deprecated function. Use next function instead.
1734Int_t TTree::Branch(TList* li, Int_t bufsize /* = 32000 */ , Int_t splitlevel /* = 99 */)
1735{
1736 return Branch((TCollection*) li, bufsize, splitlevel);
1737}
1738
1739////////////////////////////////////////////////////////////////////////////////
1740/// Create one branch for each element in the collection.
1741///
1742/// Each entry in the collection becomes a top level branch if the
1743/// corresponding class is not a collection. If it is a collection, the entry
1744/// in the collection becomes in turn top level branches, etc.
1745/// The splitlevel is decreased by 1 every time a new collection is found.
1746/// For example if list is a TObjArray*
1747/// - if splitlevel = 1, one top level branch is created for each element
1748/// of the TObjArray.
1749/// - if splitlevel = 2, one top level branch is created for each array element.
1750/// if, in turn, one of the array elements is a TCollection, one top level
1751/// branch will be created for each element of this collection.
1752///
1753/// In case a collection element is a TClonesArray, the special Tree constructor
1754/// for TClonesArray is called.
1755/// The collection itself cannot be a TClonesArray.
1756///
1757/// The function returns the total number of branches created.
1758///
1759/// If name is given, all branch names will be prefixed with name_.
1760///
1761/// IMPORTANT NOTE1: This function should not be called with splitlevel < 1.
1762///
1763/// IMPORTANT NOTE2: The branches created by this function will have names
1764/// corresponding to the collection or object names. It is important
1765/// to give names to collections to avoid misleading branch names or
1766/// identical branch names. By default collections have a name equal to
1767/// the corresponding class name, e.g. the default name for a TList is "TList".
1768///
1769/// And in general, in case two or more master branches contain subbranches
1770/// with identical names, one must add a "." (dot) character at the end
1771/// of the master branch name. This will force the name of the subbranches
1772/// to be of the form `master.subbranch` instead of simply `subbranch`.
1773/// This situation happens when the top level object
1774/// has two or more members referencing the same class.
1775/// For example, if a Tree has two branches B1 and B2 corresponding
1776/// to objects of the same class MyClass, one can do:
1777/// ~~~ {.cpp}
1778/// tree.Branch("B1.","MyClass",&b1,8000,1);
1779/// tree.Branch("B2.","MyClass",&b2,8000,1);
1780/// ~~~
1781/// if MyClass has 3 members a,b,c, the two instructions above will generate
1782/// subbranches called B1.a, B1.b ,B1.c, B2.a, B2.b, B2.c
1783///
1784/// Example:
1785/// ~~~ {.cpp}
1786/// {
1787/// TTree T("T","test list");
1788/// TList *list = new TList();
1789///
1790/// TObjArray *a1 = new TObjArray();
1791/// a1->SetName("a1");
1792/// list->Add(a1);
1793/// TH1F *ha1a = new TH1F("ha1a","ha1",100,0,1);
1794/// TH1F *ha1b = new TH1F("ha1b","ha1",100,0,1);
1795/// a1->Add(ha1a);
1796/// a1->Add(ha1b);
1797/// TObjArray *b1 = new TObjArray();
1798/// b1->SetName("b1");
1799/// list->Add(b1);
1800/// TH1F *hb1a = new TH1F("hb1a","hb1",100,0,1);
1801/// TH1F *hb1b = new TH1F("hb1b","hb1",100,0,1);
1802/// b1->Add(hb1a);
1803/// b1->Add(hb1b);
1804///
1805/// TObjArray *a2 = new TObjArray();
1806/// a2->SetName("a2");
1807/// list->Add(a2);
1808/// TH1S *ha2a = new TH1S("ha2a","ha2",100,0,1);
1809/// TH1S *ha2b = new TH1S("ha2b","ha2",100,0,1);
1810/// a2->Add(ha2a);
1811/// a2->Add(ha2b);
1812///
1813/// T.Branch(list,16000,2);
1814/// T.Print();
1815/// }
1816/// ~~~
1818Int_t TTree::Branch(TCollection* li, Int_t bufsize /* = 32000 */, Int_t splitlevel /* = 99 */, const char* name /* = "" */)
1819{
1820
1821 if (!li) {
1822 return 0;
1823 }
1824 TObject* obj = 0;
1825 Int_t nbranches = GetListOfBranches()->GetEntries();
1826 if (li->InheritsFrom(TClonesArray::Class())) {
1827 Error("Branch", "Cannot call this constructor for a TClonesArray");
1828 return 0;
1829 }
1830 Int_t nch = strlen(name);
1831 TString branchname;
1832 TIter next(li);
1833 while ((obj = next())) {
1834 if ((splitlevel > 1) && obj->InheritsFrom(TCollection::Class()) && !obj->InheritsFrom(TClonesArray::Class())) {
1835 TCollection* col = (TCollection*) obj;
1836 if (nch) {
1837 branchname.Form("%s_%s_", name, col->GetName());
1838 } else {
1839 branchname.Form("%s_", col->GetName());
1840 }
1841 Branch(col, bufsize, splitlevel - 1, branchname);
1842 } else {
1843 if (nch && (name[nch-1] == '_')) {
1844 branchname.Form("%s%s", name, obj->GetName());
1845 } else {
1846 if (nch) {
1847 branchname.Form("%s_%s", name, obj->GetName());
1848 } else {
1849 branchname.Form("%s", obj->GetName());
1850 }
1851 }
1852 if (splitlevel > 99) {
1853 branchname += ".";
1854 }
1855 Bronch(branchname, obj->ClassName(), li->GetObjectRef(obj), bufsize, splitlevel - 1);
1856 }
1857 }
1858 return GetListOfBranches()->GetEntries() - nbranches;
1859}
1860
1861////////////////////////////////////////////////////////////////////////////////
1862/// Create one branch for each element in the folder.
1863/// Returns the total number of branches created.
1865Int_t TTree::Branch(const char* foldername, Int_t bufsize /* = 32000 */, Int_t splitlevel /* = 99 */)
1866{
1867 TObject* ob = gROOT->FindObjectAny(foldername);
1868 if (!ob) {
1869 return 0;
1870 }
1871 if (ob->IsA() != TFolder::Class()) {
1872 return 0;
1873 }
1874 Int_t nbranches = GetListOfBranches()->GetEntries();
1875 TFolder* folder = (TFolder*) ob;
1876 TIter next(folder->GetListOfFolders());
1877 TObject* obj = 0;
1878 char* curname = new char[1000];
1879 char occur[20];
1880 while ((obj = next())) {
1881 snprintf(curname,1000, "%s/%s", foldername, obj->GetName());
1882 if (obj->IsA() == TFolder::Class()) {
1883 Branch(curname, bufsize, splitlevel - 1);
1884 } else {
1885 void* add = (void*) folder->GetListOfFolders()->GetObjectRef(obj);
1886 for (Int_t i = 0; i < 1000; ++i) {
1887 if (curname[i] == 0) {
1888 break;
1889 }
1890 if (curname[i] == '/') {
1891 curname[i] = '.';
1892 }
1893 }
1894 Int_t noccur = folder->Occurence(obj);
1895 if (noccur > 0) {
1896 snprintf(occur,20, "_%d", noccur);
1897 strlcat(curname, occur,1000);
1898 }
1899 TBranchElement* br = (TBranchElement*) Bronch(curname, obj->ClassName(), add, bufsize, splitlevel - 1);
1900 if (br) br->SetBranchFolder();
1901 }
1902 }
1903 delete[] curname;
1904 return GetListOfBranches()->GetEntries() - nbranches;
1905}
1906
1907////////////////////////////////////////////////////////////////////////////////
1908/// Create a new TTree Branch.
1909///
1910/// This Branch constructor is provided to support non-objects in
1911/// a Tree. The variables described in leaflist may be simple
1912/// variables or structures. // See the two following
1913/// constructors for writing objects in a Tree.
1914///
1915/// By default the branch buffers are stored in the same file as the Tree.
1916/// use TBranch::SetFile to specify a different file
1917///
1918/// * address is the address of the first item of a structure.
1919/// * leaflist is the concatenation of all the variable names and types
1920/// separated by a colon character :
1921/// The variable name and the variable type are separated by a slash (/).
1922/// The variable type may be 0,1 or 2 characters. If no type is given,
1923/// the type of the variable is assumed to be the same as the previous
1924/// variable. If the first variable does not have a type, it is assumed
1925/// of type F by default. The list of currently supported types is given below:
1926/// - `C` : a character string terminated by the 0 character
1927/// - `B` : an 8 bit signed integer (`Char_t`)
1928/// - `b` : an 8 bit unsigned integer (`UChar_t`)
1929/// - `S` : a 16 bit signed integer (`Short_t`)
1930/// - `s` : a 16 bit unsigned integer (`UShort_t`)
1931/// - `I` : a 32 bit signed integer (`Int_t`)
1932/// - `i` : a 32 bit unsigned integer (`UInt_t`)
1933/// - `F` : a 32 bit floating point (`Float_t`)
1934/// - `f` : a 24 bit floating point with truncated mantissa (`Float16_t`)
1935/// - `D` : a 64 bit floating point (`Double_t`)
1936/// - `d` : a 24 bit truncated floating point (`Double32_t`)
1937/// - `L` : a 64 bit signed integer (`Long64_t`)
1938/// - `l` : a 64 bit unsigned integer (`ULong64_t`)
1939/// - `O` : [the letter `o`, not a zero] a boolean (`Bool_t`)
1940///
1941/// Arrays of values are supported with the following syntax:
1942/// - If leaf name has the form var[nelem], where nelem is alphanumeric, then
1943/// if nelem is a leaf name, it is used as the variable size of the array,
1944/// otherwise return 0.
1945/// - If leaf name has the form var[nelem], where nelem is a non-negative integer, then
1946/// it is used as the fixed size of the array.
1947/// - If leaf name has the form of a multi-dimensional array (e.g. var[nelem][nelem2])
1948/// where nelem and nelem2 are non-negative integer) then
1949/// it is used as a 2 dimensional array of fixed size.
1950/// - In case of the truncated floating point types (Float16_t and Double32_t) you can
1951/// furthermore specify the range in the style [xmin,xmax] or [xmin,xmax,nbits] after
1952/// the type character. See `TStreamerElement::GetRange()` for further information.
1953///
1954/// Any of other form is not supported.
1955///
1956/// Note that the TTree will assume that all the item are contiguous in memory.
1957/// On some platform, this is not always true of the member of a struct or a class,
1958/// due to padding and alignment. Sorting your data member in order of decreasing
1959/// sizeof usually leads to their being contiguous in memory.
1960///
1961/// * bufsize is the buffer size in bytes for this branch
1962/// The default value is 32000 bytes and should be ok for most cases.
1963/// You can specify a larger value (e.g. 256000) if your Tree is not split
1964/// and each entry is large (Megabytes)
1965/// A small value for bufsize is optimum if you intend to access
1966/// the entries in the Tree randomly and your Tree is in split mode.
1968TBranch* TTree::Branch(const char* name, void* address, const char* leaflist, Int_t bufsize /* = 32000 */)
1969{
1970 TBranch* branch = new TBranch(this, name, address, leaflist, bufsize);
1971 if (branch->IsZombie()) {
1972 delete branch;
1973 branch = 0;
1974 return 0;
1975 }
1976 fBranches.Add(branch);
1977 return branch;
1978}
1979
1980////////////////////////////////////////////////////////////////////////////////
1981/// Create a new branch with the object of class classname at address addobj.
1982///
1983/// WARNING:
1984///
1985/// Starting with Root version 3.01, the Branch function uses the new style
1986/// branches (TBranchElement). To get the old behaviour, you can:
1987/// - call BranchOld or
1988/// - call TTree::SetBranchStyle(0)
1989///
1990/// Note that with the new style, classname does not need to derive from TObject.
1991/// It must derived from TObject if the branch style has been set to 0 (old)
1992///
1993/// Note: See the comments in TBranchElement::SetAddress() for a more
1994/// detailed discussion of the meaning of the addobj parameter in
1995/// the case of new-style branches.
1996///
1997/// Use splitlevel < 0 instead of splitlevel=0 when the class
1998/// has a custom Streamer
1999///
2000/// Note: if the split level is set to the default (99), TTree::Branch will
2001/// not issue a warning if the class can not be split.
2003TBranch* TTree::Branch(const char* name, const char* classname, void* addobj, Int_t bufsize /* = 32000 */, Int_t splitlevel /* = 99 */)
2004{
2005 if (fgBranchStyle == 1) {
2006 return Bronch(name, classname, addobj, bufsize, splitlevel);
2007 } else {
2008 if (splitlevel < 0) {
2009 splitlevel = 0;
2010 }
2011 return BranchOld(name, classname, addobj, bufsize, splitlevel);
2012 }
2013}
2014
2015////////////////////////////////////////////////////////////////////////////////
2016/// Create a new TTree BranchObject.
2017///
2018/// Build a TBranchObject for an object of class classname.
2019/// addobj is the address of a pointer to an object of class classname.
2020/// IMPORTANT: classname must derive from TObject.
2021/// The class dictionary must be available (ClassDef in class header).
2022///
2023/// This option requires access to the library where the corresponding class
2024/// is defined. Accessing one single data member in the object implies
2025/// reading the full object.
2026/// See the next Branch constructor for a more efficient storage
2027/// in case the entry consists of arrays of identical objects.
2028///
2029/// By default the branch buffers are stored in the same file as the Tree.
2030/// use TBranch::SetFile to specify a different file
2031///
2032/// IMPORTANT NOTE about branch names:
2033///
2034/// And in general, in case two or more master branches contain subbranches
2035/// with identical names, one must add a "." (dot) character at the end
2036/// of the master branch name. This will force the name of the subbranches
2037/// to be of the form `master.subbranch` instead of simply `subbranch`.
2038/// This situation happens when the top level object
2039/// has two or more members referencing the same class.
2040/// For example, if a Tree has two branches B1 and B2 corresponding
2041/// to objects of the same class MyClass, one can do:
2042/// ~~~ {.cpp}
2043/// tree.Branch("B1.","MyClass",&b1,8000,1);
2044/// tree.Branch("B2.","MyClass",&b2,8000,1);
2045/// ~~~
2046/// if MyClass has 3 members a,b,c, the two instructions above will generate
2047/// subbranches called B1.a, B1.b ,B1.c, B2.a, B2.b, B2.c
2048///
2049/// bufsize is the buffer size in bytes for this branch
2050/// The default value is 32000 bytes and should be ok for most cases.
2051/// You can specify a larger value (e.g. 256000) if your Tree is not split
2052/// and each entry is large (Megabytes)
2053/// A small value for bufsize is optimum if you intend to access
2054/// the entries in the Tree randomly and your Tree is in split mode.
2056TBranch* TTree::BranchOld(const char* name, const char* classname, void* addobj, Int_t bufsize /* = 32000 */, Int_t splitlevel /* = 1 */)
2057{
2058 TClass* cl = TClass::GetClass(classname);
2059 if (!cl) {
2060 Error("BranchOld", "Cannot find class: '%s'", classname);
2061 return 0;
2062 }
2063 if (!cl->IsTObject()) {
2064 if (fgBranchStyle == 0) {
2065 Fatal("BranchOld", "The requested class ('%s') does not inherit from TObject.\n"
2066 "\tfgBranchStyle is set to zero requesting by default to use BranchOld.\n"
2067 "\tIf this is intentional use Bronch instead of Branch or BranchOld.", classname);
2068 } else {
2069 Fatal("BranchOld", "The requested class ('%s') does not inherit from TObject.\n"
2070 "\tYou can not use BranchOld to store objects of this type.",classname);
2071 }
2072 return 0;
2073 }
2074 TBranch* branch = new TBranchObject(this, name, classname, addobj, bufsize, splitlevel);
2075 fBranches.Add(branch);
2076 if (!splitlevel) {
2077 return branch;
2078 }
2079 // We are going to fully split the class now.
2080 TObjArray* blist = branch->GetListOfBranches();
2081 const char* rdname = 0;
2082 const char* dname = 0;
2083 TString branchname;
2084 char** apointer = (char**) addobj;
2085 TObject* obj = (TObject*) *apointer;
2086 Bool_t delobj = kFALSE;
2087 if (!obj) {
2088 obj = (TObject*) cl->New();
2089 delobj = kTRUE;
2090 }
2091 // Build the StreamerInfo if first time for the class.
2092 BuildStreamerInfo(cl, obj);
2093 // Loop on all public data members of the class and its base classes.
2094 Int_t lenName = strlen(name);
2095 Int_t isDot = 0;
2096 if (name[lenName-1] == '.') {
2097 isDot = 1;
2098 }
2099 TBranch* branch1 = 0;
2100 TRealData* rd = 0;
2101 TRealData* rdi = 0;
2102 TIter nexti(cl->GetListOfRealData());
2103 TIter next(cl->GetListOfRealData());
2104 // Note: This loop results in a full split because the
2105 // real data list includes all data members of
2106 // data members.
2107 while ((rd = (TRealData*) next())) {
2108 if (rd->TestBit(TRealData::kTransient)) continue;
2109
2110 // Loop over all data members creating branches for each one.
2111 TDataMember* dm = rd->GetDataMember();
2112 if (!dm->IsPersistent()) {
2113 // Do not process members with an "!" as the first character in the comment field.
2114 continue;
2115 }
2116 if (rd->IsObject()) {
2117 // We skip data members of class type.
2118 // But we do build their real data, their
2119 // streamer info, and write their streamer
2120 // info to the current directory's file.
2121 // Oh yes, and we also do this for all of
2122 // their base classes.
2124 if (clm) {
2125 BuildStreamerInfo(clm, (char*) obj + rd->GetThisOffset());
2126 }
2127 continue;
2128 }
2129 rdname = rd->GetName();
2130 dname = dm->GetName();
2131 if (cl->CanIgnoreTObjectStreamer()) {
2132 // Skip the TObject base class data members.
2133 // FIXME: This prevents a user from ever
2134 // using these names themself!
2135 if (!strcmp(dname, "fBits")) {
2136 continue;
2137 }
2138 if (!strcmp(dname, "fUniqueID")) {
2139 continue;
2140 }
2141 }
2142 TDataType* dtype = dm->GetDataType();
2143 Int_t code = 0;
2144 if (dtype) {
2145 code = dm->GetDataType()->GetType();
2146 }
2147 // Encode branch name. Use real data member name
2148 branchname = rdname;
2149 if (isDot) {
2150 if (dm->IsaPointer()) {
2151 // FIXME: This is wrong! The asterisk is not usually in the front!
2152 branchname.Form("%s%s", name, &rdname[1]);
2153 } else {
2154 branchname.Form("%s%s", name, &rdname[0]);
2155 }
2156 }
2157 // FIXME: Change this to a string stream.
2158 TString leaflist;
2159 Int_t offset = rd->GetThisOffset();
2160 char* pointer = ((char*) obj) + offset;
2161 if (dm->IsaPointer()) {
2162 // We have a pointer to an object or a pointer to an array of basic types.
2163 TClass* clobj = 0;
2164 if (!dm->IsBasic()) {
2165 clobj = TClass::GetClass(dm->GetTypeName());
2166 }
2167 if (clobj && clobj->InheritsFrom(TClonesArray::Class())) {
2168 // We have a pointer to a clones array.
2169 char* cpointer = (char*) pointer;
2170 char** ppointer = (char**) cpointer;
2171 TClonesArray* li = (TClonesArray*) *ppointer;
2172 if (splitlevel != 2) {
2173 if (isDot) {
2174 branch1 = new TBranchClones(branch,branchname, pointer, bufsize);
2175 } else {
2176 // FIXME: This is wrong! The asterisk is not usually in the front!
2177 branch1 = new TBranchClones(branch,&branchname.Data()[1], pointer, bufsize);
2178 }
2179 blist->Add(branch1);
2180 } else {
2181 if (isDot) {
2182 branch1 = new TBranchObject(branch, branchname, li->ClassName(), pointer, bufsize);
2183 } else {
2184 // FIXME: This is wrong! The asterisk is not usually in the front!
2185 branch1 = new TBranchObject(branch, &branchname.Data()[1], li->ClassName(), pointer, bufsize);
2186 }
2187 blist->Add(branch1);
2188 }
2189 } else if (clobj) {
2190 // We have a pointer to an object.
2191 //
2192 // It must be a TObject object.
2193 if (!clobj->IsTObject()) {
2194 continue;
2195 }
2196 branch1 = new TBranchObject(branch, dname, clobj->GetName(), pointer, bufsize, 0);
2197 if (isDot) {
2198 branch1->SetName(branchname);
2199 } else {
2200 // FIXME: This is wrong! The asterisk is not usually in the front!
2201 // Do not use the first character (*).
2202 branch1->SetName(&branchname.Data()[1]);
2203 }
2204 blist->Add(branch1);
2205 } else {
2206 // We have a pointer to an array of basic types.
2207 //
2208 // Check the comments in the text of the code for an index specification.
2209 const char* index = dm->GetArrayIndex();
2210 if (index[0]) {
2211 // We are a pointer to a varying length array of basic types.
2212 //check that index is a valid data member name
2213 //if member is part of an object (e.g. fA and index=fN)
2214 //index must be changed from fN to fA.fN
2215 TString aindex (rd->GetName());
2216 Ssiz_t rdot = aindex.Last('.');
2217 if (rdot>=0) {
2218 aindex.Remove(rdot+1);
2219 aindex.Append(index);
2220 }
2221 nexti.Reset();
2222 while ((rdi = (TRealData*) nexti())) {
2223 if (rdi->TestBit(TRealData::kTransient)) continue;
2224
2225 if (!strcmp(rdi->GetName(), index)) {
2226 break;
2227 }
2228 if (!strcmp(rdi->GetName(), aindex)) {
2229 index = rdi->GetName();
2230 break;
2231 }
2232 }
2233
2234 char vcode = DataTypeToChar((EDataType)code);
2235 // Note that we differentiate between strings and
2236 // char array by the fact that there is NO specified
2237 // size for a string (see next if (code == 1)
2238
2239 if (vcode) {
2240 leaflist.Form("%s[%s]/%c", &rdname[0], index, vcode);
2241 } else {
2242 Error("BranchOld", "Cannot create branch for rdname: %s code: %d", branchname.Data(), code);
2243 leaflist = "";
2244 }
2245 } else {
2246 // We are possibly a character string.
2247 if (code == 1) {
2248 // We are a character string.
2249 leaflist.Form("%s/%s", dname, "C");
2250 } else {
2251 // Invalid array specification.
2252 // FIXME: We need an error message here.
2253 continue;
2254 }
2255 }
2256 // There are '*' in both the branchname and leaflist, remove them.
2257 TString bname( branchname );
2258 bname.ReplaceAll("*","");
2259 leaflist.ReplaceAll("*","");
2260 // Add the branch to the tree and indicate that the address
2261 // is that of a pointer to be dereferenced before using.
2262 branch1 = new TBranch(branch, bname, *((void**) pointer), leaflist, bufsize);
2263 TLeaf* leaf = (TLeaf*) branch1->GetListOfLeaves()->At(0);
2265 leaf->SetAddress((void**) pointer);
2266 blist->Add(branch1);
2267 }
2268 } else if (dm->IsBasic()) {
2269 // We have a basic type.
2270
2271 char vcode = DataTypeToChar((EDataType)code);
2272 if (vcode) {
2273 leaflist.Form("%s/%c", rdname, vcode);
2274 } else {
2275 Error("BranchOld", "Cannot create branch for rdname: %s code: %d", branchname.Data(), code);
2276 leaflist = "";
2277 }
2278 branch1 = new TBranch(branch, branchname, pointer, leaflist, bufsize);
2279 branch1->SetTitle(rdname);
2280 blist->Add(branch1);
2281 } else {
2282 // We have a class type.
2283 // Note: This cannot happen due to the rd->IsObject() test above.
2284 // FIXME: Put an error message here just in case.
2285 }
2286 if (branch1) {
2287 branch1->SetOffset(offset);
2288 } else {
2289 Warning("BranchOld", "Cannot process member: '%s'", rdname);
2290 }
2291 }
2292 if (delobj) {
2293 delete obj;
2294 obj = 0;
2295 }
2296 return branch;
2297}
2298
2299////////////////////////////////////////////////////////////////////////////////
2300/// Build the optional branch supporting the TRefTable.
2301/// This branch will keep all the information to find the branches
2302/// containing referenced objects.
2303///
2304/// At each Tree::Fill, the branch numbers containing the
2305/// referenced objects are saved to the TBranchRef basket.
2306/// When the Tree header is saved (via TTree::Write), the branch
2307/// is saved keeping the information with the pointers to the branches
2308/// having referenced objects.
2311{
2312 if (!fBranchRef) {
2313 fBranchRef = new TBranchRef(this);
2314 }
2315 return fBranchRef;
2316}
2317
2318////////////////////////////////////////////////////////////////////////////////
2319/// Create a new TTree BranchElement.
2320///
2321/// ## WARNING about this new function
2322///
2323/// This function is designed to replace the internal
2324/// implementation of the old TTree::Branch (whose implementation
2325/// has been moved to BranchOld).
2326///
2327/// NOTE: The 'Bronch' method supports only one possible calls
2328/// signature (where the object type has to be specified
2329/// explicitly and the address must be the address of a pointer).
2330/// For more flexibility use 'Branch'. Use Bronch only in (rare)
2331/// cases (likely to be legacy cases) where both the new and old
2332/// implementation of Branch needs to be used at the same time.
2333///
2334/// This function is far more powerful than the old Branch
2335/// function. It supports the full C++, including STL and has
2336/// the same behaviour in split or non-split mode. classname does
2337/// not have to derive from TObject. The function is based on
2338/// the new TStreamerInfo.
2339///
2340/// Build a TBranchElement for an object of class classname.
2341///
2342/// addr is the address of a pointer to an object of class
2343/// classname. The class dictionary must be available (ClassDef
2344/// in class header).
2345///
2346/// Note: See the comments in TBranchElement::SetAddress() for a more
2347/// detailed discussion of the meaning of the addr parameter.
2348///
2349/// This option requires access to the library where the
2350/// corresponding class is defined. Accessing one single data
2351/// member in the object implies reading the full object.
2352///
2353/// By default the branch buffers are stored in the same file as the Tree.
2354/// use TBranch::SetFile to specify a different file
2355///
2356/// IMPORTANT NOTE about branch names:
2357///
2358/// And in general, in case two or more master branches contain subbranches
2359/// with identical names, one must add a "." (dot) character at the end
2360/// of the master branch name. This will force the name of the subbranches
2361/// to be of the form `master.subbranch` instead of simply `subbranch`.
2362/// This situation happens when the top level object
2363/// has two or more members referencing the same class.
2364/// For example, if a Tree has two branches B1 and B2 corresponding
2365/// to objects of the same class MyClass, one can do:
2366/// ~~~ {.cpp}
2367/// tree.Branch("B1.","MyClass",&b1,8000,1);
2368/// tree.Branch("B2.","MyClass",&b2,8000,1);
2369/// ~~~
2370/// if MyClass has 3 members a,b,c, the two instructions above will generate
2371/// subbranches called B1.a, B1.b ,B1.c, B2.a, B2.b, B2.c
2372///
2373/// bufsize is the buffer size in bytes for this branch
2374/// The default value is 32000 bytes and should be ok for most cases.
2375/// You can specify a larger value (e.g. 256000) if your Tree is not split
2376/// and each entry is large (Megabytes)
2377/// A small value for bufsize is optimum if you intend to access
2378/// the entries in the Tree randomly and your Tree is in split mode.
2379///
2380/// Use splitlevel < 0 instead of splitlevel=0 when the class
2381/// has a custom Streamer
2382///
2383/// Note: if the split level is set to the default (99), TTree::Branch will
2384/// not issue a warning if the class can not be split.
2386TBranch* TTree::Bronch(const char* name, const char* classname, void* addr, Int_t bufsize /* = 32000 */, Int_t splitlevel /* = 99 */)
2387{
2388 return BronchExec(name, classname, addr, kTRUE, bufsize, splitlevel);
2389}
2390
2391////////////////////////////////////////////////////////////////////////////////
2392/// Helper function implementing TTree::Bronch and TTree::Branch(const char *name, T &obj);
2394TBranch* TTree::BronchExec(const char* name, const char* classname, void* addr, Bool_t isptrptr, Int_t bufsize /* = 32000 */, Int_t splitlevel /* = 99 */)
2395{
2396 TClass* cl = TClass::GetClass(classname);
2397 if (!cl) {
2398 Error("Bronch", "Cannot find class:%s", classname);
2399 return 0;
2400 }
2401
2402 //if splitlevel <= 0 and class has a custom Streamer, we must create
2403 //a TBranchObject. We cannot assume that TClass::ReadBuffer is consistent
2404 //with the custom Streamer. The penalty is that one cannot process
2405 //this Tree without the class library containing the class.
2406
2407 char* objptr = 0;
2408 if (!isptrptr) {
2409 objptr = (char*)addr;
2410 } else if (addr) {
2411 objptr = *((char**) addr);
2412 }
2413
2414 if (cl == TClonesArray::Class()) {
2415 TClonesArray* clones = (TClonesArray*) objptr;
2416 if (!clones) {
2417 Error("Bronch", "Pointer to TClonesArray is null");
2418 return 0;
2419 }
2420 if (!clones->GetClass()) {
2421 Error("Bronch", "TClonesArray with no class defined in branch: %s", name);
2422 return 0;
2423 }
2424 if (!clones->GetClass()->HasDataMemberInfo()) {
2425 Error("Bronch", "TClonesArray with no dictionary defined in branch: %s", name);
2426 return 0;
2427 }
2428 bool hasCustomStreamer = clones->GetClass()->TestBit(TClass::kHasCustomStreamerMember);
2429 if (splitlevel > 0) {
2430 if (hasCustomStreamer)
2431 Warning("Bronch", "Using split mode on a class: %s with a custom Streamer", clones->GetClass()->GetName());
2432 } else {
2433 if (hasCustomStreamer) clones->BypassStreamer(kFALSE);
2434 TBranchObject *branch = new TBranchObject(this,name,classname,addr,bufsize,0,/*compress=*/ -1,isptrptr);
2435 fBranches.Add(branch);
2436 return branch;
2437 }
2438 }
2439
2440 if (cl->GetCollectionProxy()) {
2442 //if (!collProxy) {
2443 // Error("Bronch", "%s is missing its CollectionProxy (for branch %s)", classname, name);
2444 //}
2445 TClass* inklass = collProxy->GetValueClass();
2446 if (!inklass && (collProxy->GetType() == 0)) {
2447 Error("Bronch", "%s with no class defined in branch: %s", classname, name);
2448 return 0;
2449 }
2450 if ((splitlevel > 0) && inklass && (inklass->GetCollectionProxy() == 0)) {
2452 if ((stl != ROOT::kSTLmap) && (stl != ROOT::kSTLmultimap)) {
2453 if (!inklass->HasDataMemberInfo()) {
2454 Error("Bronch", "Container with no dictionary defined in branch: %s", name);
2455 return 0;
2456 }
2458 Warning("Bronch", "Using split mode on a class: %s with a custom Streamer", inklass->GetName());
2459 }
2460 }
2461 }
2462 //-------------------------------------------------------------------------
2463 // If the splitting switch is enabled, the split level is big enough and
2464 // the collection contains pointers we can split it
2465 //////////////////////////////////////////////////////////////////////////
2466
2467 TBranch *branch;
2468 if( splitlevel > kSplitCollectionOfPointers && collProxy->HasPointers() )
2469 branch = new TBranchSTL( this, name, collProxy, bufsize, splitlevel );
2470 else
2471 branch = new TBranchElement(this, name, collProxy, bufsize, splitlevel);
2472 fBranches.Add(branch);
2473 if (isptrptr) {
2474 branch->SetAddress(addr);
2475 } else {
2476 branch->SetObject(addr);
2477 }
2478 return branch;
2479 }
2480
2481 Bool_t hasCustomStreamer = kFALSE;
2482 if (!cl->HasDataMemberInfo() && !cl->GetCollectionProxy()) {
2483 Error("Bronch", "Cannot find dictionary for class: %s", classname);
2484 return 0;
2485 }
2486
2488 // Not an STL container and the linkdef file had a "-" after the class name.
2489 hasCustomStreamer = kTRUE;
2490 }
2491
2492 if (splitlevel < 0 || ((splitlevel == 0) && hasCustomStreamer && cl->IsTObject())) {
2493 TBranchObject* branch = new TBranchObject(this, name, classname, addr, bufsize, 0, /*compress=*/ ROOT::RCompressionSetting::EAlgorithm::kInherit, isptrptr);
2494 fBranches.Add(branch);
2495 return branch;
2496 }
2497
2498 if (cl == TClonesArray::Class()) {
2499 // Special case of TClonesArray.
2500 // No dummy object is created.
2501 // The streamer info is not rebuilt unoptimized.
2502 // No dummy top-level branch is created.
2503 // No splitting is attempted.
2504 TBranchElement* branch = new TBranchElement(this, name, (TClonesArray*) objptr, bufsize, splitlevel%kSplitCollectionOfPointers);
2505 fBranches.Add(branch);
2506 if (isptrptr) {
2507 branch->SetAddress(addr);
2508 } else {
2509 branch->SetObject(addr);
2510 }
2511 return branch;
2512 }
2513
2514 //
2515 // If we are not given an object to use as an i/o buffer
2516 // then create a temporary one which we will delete just
2517 // before returning.
2518 //
2519
2520 Bool_t delobj = kFALSE;
2521
2522 if (!objptr) {
2523 objptr = (char*) cl->New();
2524 delobj = kTRUE;
2525 }
2526
2527 //
2528 // Avoid splitting unsplittable classes.
2529 //
2530
2531 if ((splitlevel > 0) && !cl->CanSplit()) {
2532 if (splitlevel != 99) {
2533 Warning("Bronch", "%s cannot be split, resetting splitlevel to 0", cl->GetName());
2534 }
2535 splitlevel = 0;
2536 }
2537
2538 //
2539 // Make sure the streamer info is built and fetch it.
2540 //
2541 // If we are splitting, then make sure the streamer info
2542 // is built unoptimized (data members are not combined).
2543 //
2544
2545 TStreamerInfo* sinfo = BuildStreamerInfo(cl, objptr, splitlevel==0);
2546 if (!sinfo) {
2547 Error("Bronch", "Cannot build the StreamerInfo for class: %s", cl->GetName());
2548 return 0;
2549 }
2550
2551 //
2552 // Create a dummy top level branch object.
2553 //
2554
2555 Int_t id = -1;
2556 if (splitlevel > 0) {
2557 id = -2;
2558 }
2559 TBranchElement* branch = new TBranchElement(this, name, sinfo, id, objptr, bufsize, splitlevel);
2560 fBranches.Add(branch);
2561
2562 //
2563 // Do splitting, if requested.
2564 //
2565
2566 if (splitlevel%kSplitCollectionOfPointers > 0) {
2567 branch->Unroll(name, cl, sinfo, objptr, bufsize, splitlevel);
2568 }
2569
2570 //
2571 // Setup our offsets into the user's i/o buffer.
2572 //
2573
2574 if (isptrptr) {
2575 branch->SetAddress(addr);
2576 } else {
2577 branch->SetObject(addr);
2578 }
2579
2580 if (delobj) {
2581 cl->Destructor(objptr);
2582 objptr = 0;
2583 }
2584
2585 return branch;
2586}
2587
2588////////////////////////////////////////////////////////////////////////////////
2589/// Browse content of the TTree.
2592{
2594 if (fUserInfo) {
2595 if (strcmp("TList",fUserInfo->GetName())==0) {
2596 fUserInfo->SetName("UserInfo");
2597 b->Add(fUserInfo);
2598 fUserInfo->SetName("TList");
2599 } else {
2600 b->Add(fUserInfo);
2601 }
2602 }
2603}
2604
2605////////////////////////////////////////////////////////////////////////////////
2606/// Build a Tree Index (default is TTreeIndex).
2607/// See a description of the parameters and functionality in
2608/// TTreeIndex::TTreeIndex().
2609///
2610/// The return value is the number of entries in the Index (< 0 indicates failure).
2611///
2612/// A TTreeIndex object pointed by fTreeIndex is created.
2613/// This object will be automatically deleted by the TTree destructor.
2614/// If an index is already existing, this is replaced by the new one without being
2615/// deleted. This behaviour prevents the deletion of a previously external index
2616/// assigned to the TTree via the TTree::SetTreeIndex() method.
2617/// See also comments in TTree::SetTreeIndex().
2619Int_t TTree::BuildIndex(const char* majorname, const char* minorname /* = "0" */)
2620{
2621 fTreeIndex = GetPlayer()->BuildIndex(this, majorname, minorname);
2622 if (fTreeIndex->IsZombie()) {
2623 delete fTreeIndex;
2624 fTreeIndex = 0;
2625 return 0;
2626 }
2627 return fTreeIndex->GetN();
2628}
2629
2630////////////////////////////////////////////////////////////////////////////////
2631/// Build StreamerInfo for class cl.
2632/// pointer is an optional argument that may contain a pointer to an object of cl.
2634TStreamerInfo* TTree::BuildStreamerInfo(TClass* cl, void* pointer /* = 0 */, Bool_t canOptimize /* = kTRUE */ )
2635{
2636 if (!cl) {
2637 return 0;
2638 }
2639 cl->BuildRealData(pointer);
2641
2642 // Create StreamerInfo for all base classes.
2643 TBaseClass* base = 0;
2644 TIter nextb(cl->GetListOfBases());
2645 while((base = (TBaseClass*) nextb())) {
2646 if (base->IsSTLContainer()) {
2647 continue;
2648 }
2649 TClass* clm = TClass::GetClass(base->GetName());
2650 BuildStreamerInfo(clm, pointer, canOptimize);
2651 }
2652 if (sinfo && fDirectory) {
2654 }
2655 return sinfo;
2656}
2657
2658////////////////////////////////////////////////////////////////////////////////
2659/// Called by TTree::Fill() when file has reached its maximum fgMaxTreeSize.
2660/// Create a new file. If the original file is named "myfile.root",
2661/// subsequent files are named "myfile_1.root", "myfile_2.root", etc.
2662///
2663/// Returns a pointer to the new file.
2664///
2665/// Currently, the automatic change of file is restricted
2666/// to the case where the tree is in the top level directory.
2667/// The file should not contain sub-directories.
2668///
2669/// Before switching to a new file, the tree header is written
2670/// to the current file, then the current file is closed.
2671///
2672/// To process the multiple files created by ChangeFile, one must use
2673/// a TChain.
2674///
2675/// The new file name has a suffix "_N" where N is equal to fFileNumber+1.
2676/// By default a Root session starts with fFileNumber=0. One can set
2677/// fFileNumber to a different value via TTree::SetFileNumber.
2678/// In case a file named "_N" already exists, the function will try
2679/// a file named "__N", then "___N", etc.
2680///
2681/// fgMaxTreeSize can be set via the static function TTree::SetMaxTreeSize.
2682/// The default value of fgMaxTreeSize is 100 Gigabytes.
2683///
2684/// If the current file contains other objects like TH1 and TTree,
2685/// these objects are automatically moved to the new file.
2686///
2687/// \warning Be careful when writing the final Tree header to the file!
2688/// Don't do:
2689/// ~~~ {.cpp}
2690/// TFile *file = new TFile("myfile.root","recreate");
2691/// TTree *T = new TTree("T","title");
2692/// T->Fill(); // Loop
2693/// file->Write();
2694/// file->Close();
2695/// ~~~
2696/// \warning but do the following:
2697/// ~~~ {.cpp}
2698/// TFile *file = new TFile("myfile.root","recreate");
2699/// TTree *T = new TTree("T","title");
2700/// T->Fill(); // Loop
2701/// file = T->GetCurrentFile(); // To get the pointer to the current file
2702/// file->Write();
2703/// file->Close();
2704/// ~~~
2705///
2706/// \note This method is never called if the input file is a `TMemFile` or derivate.
2709{
2710 file->cd();
2711 Write();
2712 Reset();
2713 constexpr auto kBufSize = 2000;
2714 char* fname = new char[kBufSize];
2715 ++fFileNumber;
2716 char uscore[10];
2717 for (Int_t i = 0; i < 10; ++i) {
2718 uscore[i] = 0;
2719 }
2720 Int_t nus = 0;
2721 // Try to find a suitable file name that does not already exist.
2722 while (nus < 10) {
2723 uscore[nus] = '_';
2724 fname[0] = 0;
2725 strlcpy(fname, file->GetName(), kBufSize);
2726
2727 if (fFileNumber > 1) {
2728 char* cunder = strrchr(fname, '_');
2729 if (cunder) {
2730 snprintf(cunder, kBufSize - Int_t(cunder - fname), "%s%d", uscore, fFileNumber);
2731 const char* cdot = strrchr(file->GetName(), '.');
2732 if (cdot) {
2733 strlcat(fname, cdot, kBufSize);
2734 }
2735 } else {
2736 char fcount[21];
2737 snprintf(fcount,21, "%s%d", uscore, fFileNumber);
2738 strlcat(fname, fcount, kBufSize);
2739 }
2740 } else {
2741 char* cdot = strrchr(fname, '.');
2742 if (cdot) {
2743 snprintf(cdot, kBufSize - Int_t(fname-cdot), "%s%d", uscore, fFileNumber);
2744 strlcat(fname, strrchr(file->GetName(), '.'), kBufSize);
2745 } else {
2746 char fcount[21];
2747 snprintf(fcount,21, "%s%d", uscore, fFileNumber);
2748 strlcat(fname, fcount, kBufSize);
2749 }
2750 }
2751 if (gSystem->AccessPathName(fname)) {
2752 break;
2753 }
2754 ++nus;
2755 Warning("ChangeFile", "file %s already exist, trying with %d underscores", fname, nus+1);
2756 }
2757 Int_t compress = file->GetCompressionSettings();
2758 TFile* newfile = TFile::Open(fname, "recreate", "chain files", compress);
2759 if (newfile == 0) {
2760 Error("Fill","Failed to open new file %s, continuing as a memory tree.",fname);
2761 } else {
2762 Printf("Fill: Switching to new file: %s", fname);
2763 }
2764 // The current directory may contain histograms and trees.
2765 // These objects must be moved to the new file.
2766 TBranch* branch = 0;
2767 TObject* obj = 0;
2768 while ((obj = file->GetList()->First())) {
2769 file->Remove(obj);
2770 // Histogram: just change the directory.
2771 if (obj->InheritsFrom("TH1")) {
2772 gROOT->ProcessLine(TString::Format("((%s*)0x%lx)->SetDirectory((TDirectory*)0x%lx);", obj->ClassName(), (Long_t) obj, (Long_t) newfile));
2773 continue;
2774 }
2775 // Tree: must save all trees in the old file, reset them.
2776 if (obj->InheritsFrom(TTree::Class())) {
2777 TTree* t = (TTree*) obj;
2778 if (t != this) {
2779 t->AutoSave();
2780 t->Reset();
2782 }
2783 t->SetDirectory(newfile);
2784 TIter nextb(t->GetListOfBranches());
2785 while ((branch = (TBranch*)nextb())) {
2786 branch->SetFile(newfile);
2787 }
2788 if (t->GetBranchRef()) {
2789 t->GetBranchRef()->SetFile(newfile);
2790 }
2791 continue;
2792 }
2793 // Not a TH1 or a TTree, move object to new file.
2794 if (newfile) newfile->Append(obj);
2795 file->Remove(obj);
2796 }
2797 delete file;
2798 file = 0;
2799 delete[] fname;
2800 fname = 0;
2801 return newfile;
2802}
2803
2804////////////////////////////////////////////////////////////////////////////////
2805/// Check whether or not the address described by the last 3 parameters
2806/// matches the content of the branch. If a Data Model Evolution conversion
2807/// is involved, reset the fInfo of the branch.
2808/// The return values are:
2809//
2810/// - kMissingBranch (-5) : Missing branch
2811/// - kInternalError (-4) : Internal error (could not find the type corresponding to a data type number)
2812/// - kMissingCompiledCollectionProxy (-3) : Missing compiled collection proxy for a compiled collection
2813/// - kMismatch (-2) : Non-Class Pointer type given does not match the type expected by the branch
2814/// - kClassMismatch (-1) : Class Pointer type given does not match the type expected by the branch
2815/// - kMatch (0) : perfect match
2816/// - kMatchConversion (1) : match with (I/O) conversion
2817/// - kMatchConversionCollection (2) : match with (I/O) conversion of the content of a collection
2818/// - kMakeClass (3) : MakeClass mode so we can not check.
2819/// - kVoidPtr (4) : void* passed so no check was made.
2820/// - kNoCheck (5) : Underlying TBranch not yet available so no check was made.
2821/// In addition this can be multiplexed with the two bits:
2822/// - kNeedEnableDecomposedObj : in order for the address (type) to be 'usable' the branch needs to be in Decomposed Object (aka MakeClass) mode.
2823/// - kNeedDisableDecomposedObj : in order for the address (type) to be 'usable' the branch needs to not be in Decomposed Object (aka MakeClass) mode.
2824/// This bits can be masked out by using kDecomposedObjMask
2826Int_t TTree::CheckBranchAddressType(TBranch* branch, TClass* ptrClass, EDataType datatype, Bool_t isptr)
2827{
2828 if (GetMakeClass()) {
2829 // If we are in MakeClass mode so we do not really use classes.
2830 return kMakeClass;
2831 }
2832
2833 // Let's determine what we need!
2834 TClass* expectedClass = 0;
2835 EDataType expectedType = kOther_t;
2836 if (0 != branch->GetExpectedType(expectedClass,expectedType) ) {
2837 // Something went wrong, the warning message has already been issued.
2838 return kInternalError;
2839 }
2840 bool isBranchElement = branch->InheritsFrom( TBranchElement::Class() );
2841 if (expectedClass && datatype == kOther_t && ptrClass == 0) {
2842 if (isBranchElement) {
2843 TBranchElement* bEl = (TBranchElement*)branch;
2844 bEl->SetTargetClass( expectedClass->GetName() );
2845 }
2846 if (expectedClass && expectedClass->GetCollectionProxy() && dynamic_cast<TEmulatedCollectionProxy*>(expectedClass->GetCollectionProxy())) {
2847 Error("SetBranchAddress", "Unable to determine the type given for the address for \"%s\". "
2848 "The class expected (%s) refers to an stl collection and do not have a compiled CollectionProxy. "
2849 "Please generate the dictionary for this class (%s)",
2850 branch->GetName(), expectedClass->GetName(), expectedClass->GetName());
2852 }
2853 if (!expectedClass->IsLoaded()) {
2854 // The originally expected class does not have a dictionary, it is then plausible that the pointer being passed is the right type
2855 // (we really don't know). So let's express that.
2856 Error("SetBranchAddress", "Unable to determine the type given for the address for \"%s\". "
2857 "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."
2858 "Please generate the dictionary for this class (%s)",
2859 branch->GetName(), expectedClass->GetName(), expectedClass->GetName());
2860 } else {
2861 Error("SetBranchAddress", "Unable to determine the type given for the address for \"%s\". "
2862 "This is probably due to a missing dictionary, the original data class for this branch is %s.", branch->GetName(), expectedClass->GetName());
2863 }
2864 return kClassMismatch;
2865 }
2866 if (expectedClass && ptrClass && (branch->GetMother() == branch)) {
2867 // Top Level branch
2868 if (!isptr) {
2869 Error("SetBranchAddress", "The address for \"%s\" should be the address of a pointer!", branch->GetName());
2870 }
2871 }
2872 if (expectedType == kFloat16_t) {
2873 expectedType = kFloat_t;
2874 }
2875 if (expectedType == kDouble32_t) {
2876 expectedType = kDouble_t;
2877 }
2878 if (datatype == kFloat16_t) {
2879 datatype = kFloat_t;
2880 }
2881 if (datatype == kDouble32_t) {
2882 datatype = kDouble_t;
2883 }
2884
2885 /////////////////////////////////////////////////////////////////////////////
2886 // Deal with the class renaming
2887 /////////////////////////////////////////////////////////////////////////////
2888
2889 if( expectedClass && ptrClass &&
2890 expectedClass != ptrClass &&
2891 isBranchElement &&
2892 ptrClass->GetSchemaRules() &&
2893 ptrClass->GetSchemaRules()->HasRuleWithSourceClass( expectedClass->GetName() ) ) {
2894 TBranchElement* bEl = (TBranchElement*)branch;
2895
2896 if ( ptrClass->GetCollectionProxy() && expectedClass->GetCollectionProxy() ) {
2897 if (gDebug > 7)
2898 Info("SetBranchAddress", "Matching STL collection (at least according to the SchemaRuleSet when "
2899 "reading a %s into a %s",expectedClass->GetName(),ptrClass->GetName());
2900
2901 bEl->SetTargetClass( ptrClass->GetName() );
2902 return kMatchConversion;
2903
2904 } else if ( !ptrClass->GetConversionStreamerInfo( expectedClass, bEl->GetClassVersion() ) &&
2905 !ptrClass->FindConversionStreamerInfo( expectedClass, bEl->GetCheckSum() ) ) {
2906 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());
2907
2908 bEl->SetTargetClass( expectedClass->GetName() );
2909 return kClassMismatch;
2910 }
2911 else {
2912
2913 bEl->SetTargetClass( ptrClass->GetName() );
2914 return kMatchConversion;
2915 }
2916
2917 } else if (expectedClass && ptrClass && !expectedClass->InheritsFrom(ptrClass)) {
2918
2919 if (expectedClass->GetCollectionProxy() && ptrClass->GetCollectionProxy() &&
2920 isBranchElement &&
2921 expectedClass->GetCollectionProxy()->GetValueClass() &&
2922 ptrClass->GetCollectionProxy()->GetValueClass() )
2923 {
2924 // In case of collection, we know how to convert them, if we know how to convert their content.
2925 // NOTE: we need to extend this to std::pair ...
2926
2927 TClass *onfileValueClass = expectedClass->GetCollectionProxy()->GetValueClass();
2928 TClass *inmemValueClass = ptrClass->GetCollectionProxy()->GetValueClass();
2929
2930 if (inmemValueClass->GetSchemaRules() &&
2931 inmemValueClass->GetSchemaRules()->HasRuleWithSourceClass(onfileValueClass->GetName() ) )
2932 {
2933 TBranchElement* bEl = (TBranchElement*)branch;
2934 bEl->SetTargetClass( ptrClass->GetName() );
2936 }
2937 }
2938
2939 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());
2940 if (isBranchElement) {
2941 TBranchElement* bEl = (TBranchElement*)branch;
2942 bEl->SetTargetClass( expectedClass->GetName() );
2943 }
2944 return kClassMismatch;
2945
2946 } else if ((expectedType != kOther_t) && (datatype != kOther_t) && (expectedType != kNoType_t) && (datatype != kNoType_t) && (expectedType != datatype)) {
2947 if (datatype != kChar_t) {
2948 // For backward compatibility we assume that (char*) was just a cast and/or a generic address
2949 Error("SetBranchAddress", "The pointer type given \"%s\" (%d) does not correspond to the type needed \"%s\" (%d) by the branch: %s",
2950 TDataType::GetTypeName(datatype), datatype, TDataType::GetTypeName(expectedType), expectedType, branch->GetName());
2951 return kMismatch;
2952 }
2953 } else if ((expectedClass && (datatype != kOther_t && datatype != kNoType_t && datatype != kInt_t)) ||
2954 (ptrClass && (expectedType != kOther_t && expectedType != kNoType_t && datatype != kInt_t)) ) {
2955 // Sometime a null pointer can look an int, avoid complaining in that case.
2956 if (expectedClass) {
2957 Error("SetBranchAddress", "The pointer type given \"%s\" (%d) does not correspond to the type needed \"%s\" by the branch: %s",
2958 TDataType::GetTypeName(datatype), datatype, expectedClass->GetName(), branch->GetName());
2959 if (isBranchElement) {
2960 TBranchElement* bEl = (TBranchElement*)branch;
2961 bEl->SetTargetClass( expectedClass->GetName() );
2962 }
2963 } else {
2964 // 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
2965 // a struct).
2966 bool found = false;
2967 if (ptrClass->IsLoaded()) {
2968 TIter next(ptrClass->GetListOfRealData());
2969 TRealData *rdm;
2970 while ((rdm = (TRealData*)next())) {
2971 if (rdm->GetThisOffset() == 0) {
2972 TDataType *dmtype = rdm->GetDataMember()->GetDataType();
2973 if (dmtype) {
2974 EDataType etype = (EDataType)dmtype->GetType();
2975 if (etype == expectedType) {
2976 found = true;
2977 }
2978 }
2979 break;
2980 }
2981 }
2982 } else {
2983 TIter next(ptrClass->GetListOfDataMembers());
2984 TDataMember *dm;
2985 while ((dm = (TDataMember*)next())) {
2986 if (dm->GetOffset() == 0) {
2987 TDataType *dmtype = dm->GetDataType();
2988 if (dmtype) {
2989 EDataType etype = (EDataType)dmtype->GetType();
2990 if (etype == expectedType) {
2991 found = true;
2992 }
2993 }
2994 break;
2995 }
2996 }
2997 }
2998 if (found) {
2999 // let's check the size.
3000 TLeaf *last = (TLeaf*)branch->GetListOfLeaves()->Last();
3001 long len = last->GetOffset() + last->GetLenType() * last->GetLen();
3002 if (len <= ptrClass->Size()) {
3003 return kMatch;
3004 }
3005 }
3006 Error("SetBranchAddress", "The pointer type given \"%s\" does not correspond to the type needed \"%s\" (%d) by the branch: %s",
3007 ptrClass->GetName(), TDataType::GetTypeName(expectedType), expectedType, branch->GetName());
3008 }
3009 return kMismatch;
3010 }
3011 if (expectedClass && expectedClass->GetCollectionProxy() && dynamic_cast<TEmulatedCollectionProxy*>(expectedClass->GetCollectionProxy())) {
3012 Error("SetBranchAddress", writeStlWithoutProxyMsg,
3013 expectedClass->GetName(), branch->GetName(), expectedClass->GetName());
3014 if (isBranchElement) {
3015 TBranchElement* bEl = (TBranchElement*)branch;
3016 bEl->SetTargetClass( expectedClass->GetName() );
3017 }
3019 }
3020 if (isBranchElement) {
3021 if (expectedClass) {
3022 TBranchElement* bEl = (TBranchElement*)branch;
3023 bEl->SetTargetClass( expectedClass->GetName() );
3024 } else if (expectedType != kNoType_t && expectedType != kOther_t) {
3026 }
3027 }
3028 return kMatch;
3029}
3030
3031////////////////////////////////////////////////////////////////////////////////
3032/// Create a clone of this tree and copy nentries.
3033///
3034/// By default copy all entries.
3035/// The compression level of the cloned tree is set to the destination
3036/// file's compression level.
3037///
3038/// NOTE: Only active branches are copied.
3039/// NOTE: If the TTree is a TChain, the structure of the first TTree
3040/// is used for the copy.
3041///
3042/// IMPORTANT: The cloned tree stays connected with this tree until
3043/// this tree is deleted. In particular, any changes in
3044/// branch addresses in this tree are forwarded to the
3045/// clone trees, unless a branch in a clone tree has had
3046/// its address changed, in which case that change stays in
3047/// effect. When this tree is deleted, all the addresses of
3048/// the cloned tree are reset to their default values.
3049///
3050/// If 'option' contains the word 'fast' and nentries is -1, the
3051/// cloning will be done without unzipping or unstreaming the baskets
3052/// (i.e., a direct copy of the raw bytes on disk).
3053///
3054/// When 'fast' is specified, 'option' can also contain a sorting
3055/// order for the baskets in the output file.
3056///
3057/// There are currently 3 supported sorting order:
3058///
3059/// - SortBasketsByOffset (the default)
3060/// - SortBasketsByBranch
3061/// - SortBasketsByEntry
3062///
3063/// When using SortBasketsByOffset the baskets are written in the
3064/// output file in the same order as in the original file (i.e. the
3065/// baskets are sorted by their offset in the original file; Usually
3066/// this also means that the baskets are sorted by the index/number of
3067/// the _last_ entry they contain)
3068///
3069/// When using SortBasketsByBranch all the baskets of each individual
3070/// branches are stored contiguously. This tends to optimize reading
3071/// speed when reading a small number (1->5) of branches, since all
3072/// their baskets will be clustered together instead of being spread
3073/// across the file. However it might decrease the performance when
3074/// reading more branches (or the full entry).
3075///
3076/// When using SortBasketsByEntry the baskets with the lowest starting
3077/// entry are written first. (i.e. the baskets are sorted by the
3078/// index/number of the first entry they contain). This means that on
3079/// the file the baskets will be in the order in which they will be
3080/// needed when reading the whole tree sequentially.
3081///
3082/// For examples of CloneTree, see tutorials:
3083///
3084/// - copytree.C:
3085/// A macro to copy a subset of a TTree to a new TTree.
3086/// The input file has been generated by the program in
3087/// $ROOTSYS/test/Event with: Event 1000 1 1 1
3088///
3089/// - copytree2.C:
3090/// A macro to copy a subset of a TTree to a new TTree.
3091/// One branch of the new Tree is written to a separate file.
3092/// The input file has been generated by the program in
3093/// $ROOTSYS/test/Event with: Event 1000 1 1 1
3095TTree* TTree::CloneTree(Long64_t nentries /* = -1 */, Option_t* option /* = "" */)
3096{
3097 // Options
3098 Bool_t fastClone = kFALSE;
3099
3100 TString opt = option;
3101 opt.ToLower();
3102 if (opt.Contains("fast")) {
3103 fastClone = kTRUE;
3104 }
3105
3106 // If we are a chain, switch to the first tree.
3107 if ((fEntries > 0) && (LoadTree(0) < 0)) {
3108 // FIXME: We need an error message here.
3109 return 0;
3110 }
3111
3112 // Note: For a tree we get the this pointer, for
3113 // a chain we get the chain's current tree.
3114 TTree* thistree = GetTree();
3115
3116 // We will use this to override the IO features on the cloned branches.
3117 ROOT::TIOFeatures features = this->GetIOFeatures();
3118 ;
3119
3120 // Note: For a chain, the returned clone will be
3121 // a clone of the chain's first tree.
3122 TTree* newtree = (TTree*) thistree->Clone();
3123 if (!newtree) {
3124 return 0;
3125 }
3126
3127 // The clone should not delete any objects allocated by SetAddress().
3128 TObjArray* branches = newtree->GetListOfBranches();
3129 Int_t nb = branches->GetEntriesFast();
3130 for (Int_t i = 0; i < nb; ++i) {
3131 TBranch* br = (TBranch*) branches->UncheckedAt(i);
3133 ((TBranchElement*) br)->ResetDeleteObject();
3134 }
3135 }
3136
3137 // Add the new tree to the list of clones so that
3138 // we can later inform it of changes to branch addresses.
3139 thistree->AddClone(newtree);
3140 if (thistree != this) {
3141 // In case this object is a TChain, add the clone
3142 // also to the TChain's list of clones.
3143 AddClone(newtree);
3144 }
3145
3146 newtree->Reset();
3147
3148 TDirectory* ndir = newtree->GetDirectory();
3149 TFile* nfile = 0;
3150 if (ndir) {
3151 nfile = ndir->GetFile();
3152 }
3153 Int_t newcomp = -1;
3154 if (nfile) {
3155 newcomp = nfile->GetCompressionSettings();
3156 }
3157
3158 //
3159 // Delete non-active branches from the clone.
3160 //
3161 // Note: If we are a chain, this does nothing
3162 // since chains have no leaves.
3163 TObjArray* leaves = newtree->GetListOfLeaves();
3164 Int_t nleaves = leaves->GetEntriesFast();
3165 for (Int_t lndx = 0; lndx < nleaves; ++lndx) {
3166 TLeaf* leaf = (TLeaf*) leaves->UncheckedAt(lndx);
3167 if (!leaf) {
3168 continue;
3169 }
3170 TBranch* branch = leaf->GetBranch();
3171 if (branch && (newcomp > -1)) {
3172 branch->SetCompressionSettings(newcomp);
3173 }
3174 if (branch) branch->SetIOFeatures(features);
3175 if (!branch || !branch->TestBit(kDoNotProcess)) {
3176 continue;
3177 }
3178 // size might change at each iteration of the loop over the leaves.
3179 nb = branches->GetEntriesFast();
3180 for (Long64_t i = 0; i < nb; ++i) {
3181 TBranch* br = (TBranch*) branches->UncheckedAt(i);
3182 if (br == branch) {
3183 branches->RemoveAt(i);
3184 delete br;
3185 br = 0;
3186 branches->Compress();
3187 break;
3188 }
3189 TObjArray* lb = br->GetListOfBranches();
3190 Int_t nb1 = lb->GetEntriesFast();
3191 for (Int_t j = 0; j < nb1; ++j) {
3192 TBranch* b1 = (TBranch*) lb->UncheckedAt(j);
3193 if (!b1) {
3194 continue;
3195 }
3196 if (b1 == branch) {
3197 lb->RemoveAt(j);
3198 delete b1;
3199 b1 = 0;
3200 lb->Compress();
3201 break;
3202 }
3203 TObjArray* lb1 = b1->GetListOfBranches();
3204 Int_t nb2 = lb1->GetEntriesFast();
3205 for (Int_t k = 0; k < nb2; ++k) {
3206 TBranch* b2 = (TBranch*) lb1->UncheckedAt(k);
3207 if (!b2) {
3208 continue;
3209 }
3210 if (b2 == branch) {
3211 lb1->RemoveAt(k);
3212 delete b2;
3213 b2 = 0;
3214 lb1->Compress();
3215 break;
3216 }
3217 }
3218 }
3219 }
3220 }
3221 leaves->Compress();
3222
3223 // Copy MakeClass status.
3224 newtree->SetMakeClass(fMakeClass);
3225
3226 // Copy branch addresses.
3227 CopyAddresses(newtree);
3228
3229 //
3230 // Copy entries if requested.
3231 //
3232
3233 if (nentries != 0) {
3234 if (fastClone && (nentries < 0)) {
3235 if ( newtree->CopyEntries( this, -1, option, kFALSE ) < 0 ) {
3236 // There was a problem!
3237 Error("CloneTTree", "TTree has not been cloned\n");
3238 delete newtree;
3239 newtree = 0;
3240 return 0;
3241 }
3242 } else {
3243 newtree->CopyEntries( this, nentries, option, kFALSE );
3244 }
3245 }
3246
3247 return newtree;
3248}
3249
3250////////////////////////////////////////////////////////////////////////////////
3251/// Set branch addresses of passed tree equal to ours.
3252/// If undo is true, reset the branch address instead of copying them.
3253/// This insures 'separation' of a cloned tree from its original
3256{
3257 // Copy branch addresses starting from branches.
3258 TObjArray* branches = GetListOfBranches();
3259 Int_t nbranches = branches->GetEntriesFast();
3260 for (Int_t i = 0; i < nbranches; ++i) {
3261 TBranch* branch = (TBranch*) branches->UncheckedAt(i);
3262 if (branch->TestBit(kDoNotProcess)) {
3263 continue;
3264 }
3265 if (undo) {
3266 TBranch* br = tree->GetBranch(branch->GetName());
3267 tree->ResetBranchAddress(br);
3268 } else {
3269 char* addr = branch->GetAddress();
3270 if (!addr) {
3271 if (branch->IsA() == TBranch::Class()) {
3272 // If the branch was created using a leaflist, the branch itself may not have
3273 // an address but the leaf might already.
3274 TLeaf *firstleaf = (TLeaf*)branch->GetListOfLeaves()->At(0);
3275 if (!firstleaf || firstleaf->GetValuePointer()) {
3276 // Either there is no leaf (and thus no point in copying the address)
3277 // or the leaf has an address but we can not copy it via the branche
3278 // this will be copied via the next loop (over the leaf).
3279 continue;
3280 }
3281 }
3282 // Note: This may cause an object to be allocated.
3283 branch->SetAddress(0);
3284 addr = branch->GetAddress();
3285 }
3286 TBranch* br = tree->GetBranch(branch->GetFullName());
3287 if (br) {
3288 if (br->GetMakeClass() != branch->GetMakeClass())
3289 br->SetMakeClass(branch->GetMakeClass());
3290 br->SetAddress(addr);
3291 // The copy does not own any object allocated by SetAddress().
3293 ((TBranchElement*) br)->ResetDeleteObject();
3294 }
3295 } else {
3296 Warning("CopyAddresses", "Could not find branch named '%s' in tree named '%s'", branch->GetName(), tree->GetName());
3297 }
3298 }
3299 }
3300
3301 // Copy branch addresses starting from leaves.
3302 TObjArray* tleaves = tree->GetListOfLeaves();
3303 Int_t ntleaves = tleaves->GetEntriesFast();
3304 std::set<TLeaf*> updatedLeafCount;
3305 for (Int_t i = 0; i < ntleaves; ++i) {
3306 TLeaf* tleaf = (TLeaf*) tleaves->UncheckedAt(i);
3307 TBranch* tbranch = tleaf->GetBranch();
3308 TBranch* branch = GetBranch(tbranch->GetName());
3309 if (!branch) {
3310 continue;
3311 }
3312 TLeaf* leaf = branch->GetLeaf(tleaf->GetName());
3313 if (!leaf) {
3314 continue;
3315 }
3316 if (branch->TestBit(kDoNotProcess)) {
3317 continue;
3318 }
3319 if (undo) {
3320 // Now we know whether the address has been transfered
3321 tree->ResetBranchAddress(tbranch);
3322 } else {
3323 TBranchElement *mother = dynamic_cast<TBranchElement*>(leaf->GetBranch()->GetMother());
3324 bool needAddressReset = false;
3325 if (leaf->GetLeafCount() && (leaf->TestBit(TLeaf::kNewValue) || !leaf->GetValuePointer() || (mother && mother->IsObjectOwner())) && tleaf->GetLeafCount())
3326 {
3327 // If it is an array and it was allocated by the leaf itself,
3328 // let's make sure it is large enough for the incoming data.
3329 if (leaf->GetLeafCount()->GetMaximum() < tleaf->GetLeafCount()->GetMaximum()) {
3330 leaf->GetLeafCount()->IncludeRange( tleaf->GetLeafCount() );
3331 updatedLeafCount.insert(leaf->GetLeafCount());
3332 needAddressReset = true;
3333 } else {
3334 needAddressReset = (updatedLeafCount.find(leaf->GetLeafCount()) != updatedLeafCount.end());
3335 }
3336 }
3337 if (needAddressReset && leaf->GetValuePointer()) {
3338 if (leaf->IsA() == TLeafElement::Class() && mother)
3339 mother->ResetAddress();
3340 else
3341 leaf->SetAddress(nullptr);
3342 }
3343 if (!branch->GetAddress() && !leaf->GetValuePointer()) {
3344 // We should attempts to set the address of the branch.
3345 // something like:
3346 //(TBranchElement*)branch->GetMother()->SetAddress(0)
3347 //plus a few more subtilities (see TBranchElement::GetEntry).
3348 //but for now we go the simplest route:
3349 //
3350 // Note: This may result in the allocation of an object.
3351 branch->SetupAddresses();
3352 }
3353 if (branch->GetAddress()) {
3354 tree->SetBranchAddress(branch->GetName(), (void*) branch->GetAddress());
3355 TBranch* br = tree->GetBranch(branch->GetName());
3356 if (br) {
3357 // The copy does not own any object allocated by SetAddress().
3358 // FIXME: We do too much here, br may not be a top-level branch.
3360 ((TBranchElement*) br)->ResetDeleteObject();
3361 }
3362 } else {
3363 Warning("CopyAddresses", "Could not find branch named '%s' in tree named '%s'", branch->GetName(), tree->GetName());
3364 }
3365 } else {
3366 tleaf->SetAddress(leaf->GetValuePointer());
3367 }
3368 }
3369 }
3370
3371 if (undo &&
3372 ( tree->IsA()->InheritsFrom("TNtuple") || tree->IsA()->InheritsFrom("TNtupleD") )
3373 ) {
3374 tree->ResetBranchAddresses();
3375 }
3376}
3377
3378namespace {
3379
3380 enum EOnIndexError { kDrop, kKeep, kBuild };
3381
3382 static Bool_t R__HandleIndex(EOnIndexError onIndexError, TTree *newtree, TTree *oldtree)
3383 {
3384 // Return true if we should continue to handle indices, false otherwise.
3385
3386 Bool_t withIndex = kTRUE;
3387
3388 if ( newtree->GetTreeIndex() ) {
3389 if ( oldtree->GetTree()->GetTreeIndex() == 0 ) {
3390 switch (onIndexError) {
3391 case kDrop:
3392 delete newtree->GetTreeIndex();
3393 newtree->SetTreeIndex(0);
3394 withIndex = kFALSE;
3395 break;
3396 case kKeep:
3397 // Nothing to do really.
3398 break;
3399 case kBuild:
3400 // Build the index then copy it
3401 if (oldtree->GetTree()->BuildIndex(newtree->GetTreeIndex()->GetMajorName(), newtree->GetTreeIndex()->GetMinorName())) {
3402 newtree->GetTreeIndex()->Append(oldtree->GetTree()->GetTreeIndex(), kTRUE);
3403 // Clean up
3404 delete oldtree->GetTree()->GetTreeIndex();
3405 oldtree->GetTree()->SetTreeIndex(0);
3406 }
3407 break;
3408 }
3409 } else {
3410 newtree->GetTreeIndex()->Append(oldtree->GetTree()->GetTreeIndex(), kTRUE);
3411 }
3412 } else if ( oldtree->GetTree()->GetTreeIndex() != 0 ) {
3413 // We discover the first index in the middle of the chain.
3414 switch (onIndexError) {
3415 case kDrop:
3416 // Nothing to do really.
3417 break;
3418 case kKeep: {
3419 TVirtualIndex *index = (TVirtualIndex*) oldtree->GetTree()->GetTreeIndex()->Clone();
3420 index->SetTree(newtree);
3421 newtree->SetTreeIndex(index);
3422 break;
3423 }
3424 case kBuild:
3425 if (newtree->GetEntries() == 0) {
3426 // Start an index.
3427 TVirtualIndex *index = (TVirtualIndex*) oldtree->GetTree()->GetTreeIndex()->Clone();
3428 index->SetTree(newtree);
3429 newtree->SetTreeIndex(index);
3430 } else {
3431 // Build the index so far.
3432 if (newtree->BuildIndex(oldtree->GetTree()->GetTreeIndex()->GetMajorName(), oldtree->GetTree()->GetTreeIndex()->GetMinorName())) {
3433 newtree->GetTreeIndex()->Append(oldtree->GetTree()->GetTreeIndex(), kTRUE);
3434 }
3435 }
3436 break;
3437 }
3438 } else if ( onIndexError == kDrop ) {
3439 // There is no index on this or on tree->GetTree(), we know we have to ignore any further
3440 // index
3441 withIndex = kFALSE;
3442 }
3443 return withIndex;
3444 }
3445}
3446
3447////////////////////////////////////////////////////////////////////////////////
3448/// Copy nentries from given tree to this tree.
3449/// This routines assumes that the branches that intended to be copied are
3450/// already connected. The typical case is that this tree was created using
3451/// tree->CloneTree(0).
3452///
3453/// By default copy all entries.
3454///
3455/// Returns number of bytes copied to this tree.
3456///
3457/// If 'option' contains the word 'fast' and nentries is -1, the cloning will be
3458/// done without unzipping or unstreaming the baskets (i.e., a direct copy of the
3459/// raw bytes on disk).
3460///
3461/// When 'fast' is specified, 'option' can also contains a sorting order for the
3462/// baskets in the output file.
3463///
3464/// There are currently 3 supported sorting order:
3465///
3466/// - SortBasketsByOffset (the default)
3467/// - SortBasketsByBranch
3468/// - SortBasketsByEntry
3469///
3470/// See TTree::CloneTree for a detailed explanation of the semantics of these 3 options.
3471///
3472/// If the tree or any of the underlying tree of the chain has an index, that index and any
3473/// index in the subsequent underlying TTree objects will be merged.
3474///
3475/// There are currently three 'options' to control this merging:
3476/// - NoIndex : all the TTreeIndex object are dropped.
3477/// - DropIndexOnError : if any of the underlying TTree object do no have a TTreeIndex,
3478/// they are all dropped.
3479/// - AsIsIndexOnError [default]: In case of missing TTreeIndex, the resulting TTree index has gaps.
3480/// - BuildIndexOnError : If any of the underlying TTree objects do not have a TTreeIndex,
3481/// all TTreeIndex are 'ignored' and the missing piece are rebuilt.
3483Long64_t TTree::CopyEntries(TTree* tree, Long64_t nentries /* = -1 */, Option_t* option /* = "" */, Bool_t needCopyAddresses /* = false */)
3484{
3485 if (!tree) {
3486 return 0;
3487 }
3488 // Options
3489 TString opt = option;
3490 opt.ToLower();
3491 Bool_t fastClone = opt.Contains("fast");
3492 Bool_t withIndex = !opt.Contains("noindex");
3493 EOnIndexError onIndexError;
3494 if (opt.Contains("asisindex")) {
3495 onIndexError = kKeep;
3496 } else if (opt.Contains("buildindex")) {
3497 onIndexError = kBuild;
3498 } else if (opt.Contains("dropindex")) {
3499 onIndexError = kDrop;
3500 } else {
3501 onIndexError = kBuild;
3502 }
3503 Ssiz_t cacheSizeLoc = opt.Index("cachesize=");
3504 Int_t cacheSize = -1;
3505 if (cacheSizeLoc != TString::kNPOS) {
3506 // If the parse faile, cacheSize stays at -1.
3507 Ssiz_t cacheSizeEnd = opt.Index(" ",cacheSizeLoc+10) - (cacheSizeLoc+10);
3508 TSubString cacheSizeStr( opt(cacheSizeLoc+10,cacheSizeEnd) );
3509 auto parseResult = ROOT::FromHumanReadableSize(cacheSizeStr,cacheSize);
3510 if (parseResult == ROOT::EFromHumanReadableSize::kParseFail) {
3511 Warning("CopyEntries","The cachesize option can not be parsed: %s. The default size will be used.",cacheSizeStr.String().Data());
3512 } else if (parseResult == ROOT::EFromHumanReadableSize::kOverflow) {
3513 double m;
3514 const char *munit = nullptr;
3515 ROOT::ToHumanReadableSize(std::numeric_limits<decltype(cacheSize)>::max(),false,&m,&munit);
3516
3517 Warning("CopyEntries","The cachesize option is too large: %s (%g%s max). The default size will be used.",cacheSizeStr.String().Data(),m,munit);
3518 }
3519 }
3520 if (gDebug > 0 && cacheSize != -1) Info("CopyEntries","Using Cache size: %d\n",cacheSize);
3521
3522 Long64_t nbytes = 0;
3523 Long64_t treeEntries = tree->GetEntriesFast();
3524 if (nentries < 0) {
3525 nentries = treeEntries;
3526 } else if (nentries > treeEntries) {
3527 nentries = treeEntries;
3528 }
3529
3530 if (fastClone && (nentries < 0 || nentries == tree->GetEntriesFast())) {
3531 // Quickly copy the basket without decompression and streaming.
3532 Long64_t totbytes = GetTotBytes();
3533 for (Long64_t i = 0; i < nentries; i += tree->GetTree()->GetEntries()) {
3534 if (tree->LoadTree(i) < 0) {
3535 break;
3536 }
3537 if ( withIndex ) {
3538 withIndex = R__HandleIndex( onIndexError, this, tree );
3539 }
3540 if (this->GetDirectory()) {
3541 TFile* file2 = this->GetDirectory()->GetFile();
3542 if (file2 && (file2->GetEND() > TTree::GetMaxTreeSize())) {
3543 if (this->GetDirectory() == (TDirectory*) file2) {
3544 this->ChangeFile(file2);
3545 }
3546 }
3547 }
3548 TTreeCloner cloner(tree->GetTree(), this, option, TTreeCloner::kNoWarnings);
3549 if (cloner.IsValid()) {
3550 this->SetEntries(this->GetEntries() + tree->GetTree()->GetEntries());
3551 if (cacheSize != -1) cloner.SetCacheSize(cacheSize);
3552 cloner.Exec();
3553 } else {
3554 if (i == 0) {
3555 Warning("CopyEntries","%s",cloner.GetWarning());
3556 // If the first cloning does not work, something is really wrong
3557 // (since apriori the source and target are exactly the same structure!)
3558 return -1;
3559 } else {
3560 if (cloner.NeedConversion()) {
3561 TTree *localtree = tree->GetTree();
3562 Long64_t tentries = localtree->GetEntries();
3563 if (needCopyAddresses) {
3564 // Copy MakeClass status.
3565 tree->SetMakeClass(fMakeClass);
3566 // Copy branch addresses.
3568 }
3569 for (Long64_t ii = 0; ii < tentries; ii++) {
3570 if (localtree->GetEntry(ii) <= 0) {
3571 break;
3572 }
3573 this->Fill();
3574 }
3575 if (needCopyAddresses)
3576 tree->ResetBranchAddresses();
3577 if (this->GetTreeIndex()) {
3578 this->GetTreeIndex()->Append(tree->GetTree()->GetTreeIndex(), kTRUE);
3579 }
3580 } else {
3581 Warning("CopyEntries","%s",cloner.GetWarning());
3582 if (tree->GetDirectory() && tree->GetDirectory()->GetFile()) {
3583 Warning("CopyEntries", "Skipped file %s\n", tree->GetDirectory()->GetFile()->GetName());
3584 } else {
3585 Warning("CopyEntries", "Skipped file number %d\n", tree->GetTreeNumber());
3586 }
3587 }
3588 }
3589 }
3590
3591 }
3592 if (this->GetTreeIndex()) {
3593 this->GetTreeIndex()->Append(0,kFALSE); // Force the sorting
3594 }
3595 nbytes = GetTotBytes() - totbytes;
3596 } else {
3597 if (nentries < 0) {
3598 nentries = treeEntries;
3599 } else if (nentries > treeEntries) {
3600 nentries = treeEntries;
3601 }
3602 if (needCopyAddresses) {
3603 // Copy MakeClass status.
3604 tree->SetMakeClass(fMakeClass);
3605 // Copy branch addresses.
3607 }
3608 Int_t treenumber = -1;
3609 for (Long64_t i = 0; i < nentries; i++) {
3610 if (tree->LoadTree(i) < 0) {
3611 break;
3612 }
3613 if (treenumber != tree->GetTreeNumber()) {
3614 if ( withIndex ) {
3615 withIndex = R__HandleIndex( onIndexError, this, tree );
3616 }
3617 treenumber = tree->GetTreeNumber();
3618 }
3619 if (tree->GetEntry(i) <= 0) {
3620 break;
3621 }
3622 nbytes += this->Fill();
3623 }
3624 if (needCopyAddresses)
3625 tree->ResetBranchAddresses();
3626 if (this->GetTreeIndex()) {
3627 this->GetTreeIndex()->Append(0,kFALSE); // Force the sorting
3628 }
3629 }
3630 return nbytes;
3631}
3632
3633////////////////////////////////////////////////////////////////////////////////
3634/// Copy a tree with selection.
3635///
3636/// ### Important:
3637///
3638/// The returned copied tree stays connected with the original tree
3639/// until the original tree is deleted. In particular, any changes
3640/// to the branch addresses in the original tree are also made to
3641/// the copied tree. Any changes made to the branch addresses of the
3642/// copied tree are overridden anytime the original tree changes its
3643/// branch addresses. When the original tree is deleted, all the
3644/// branch addresses of the copied tree are set to zero.
3645///
3646/// For examples of CopyTree, see the tutorials:
3647///
3648/// - copytree.C:
3649/// Example macro to copy a subset of a tree to a new tree.
3650/// The input file was generated by running the program in
3651/// $ROOTSYS/test/Event in this way:
3652/// ~~~ {.cpp}
3653/// ./Event 1000 1 1 1
3654/// ~~~
3655/// - copytree2.C
3656/// Example macro to copy a subset of a tree to a new tree.
3657/// One branch of the new tree is written to a separate file.
3658/// The input file was generated by running the program in
3659/// $ROOTSYS/test/Event in this way:
3660/// ~~~ {.cpp}
3661/// ./Event 1000 1 1 1
3662/// ~~~
3663/// - copytree3.C
3664/// Example macro to copy a subset of a tree to a new tree.
3665/// Only selected entries are copied to the new tree.
3666/// NOTE that only the active branches are copied.
3668TTree* TTree::CopyTree(const char* selection, Option_t* option /* = 0 */, Long64_t nentries /* = TTree::kMaxEntries */, Long64_t firstentry /* = 0 */)
3669{
3670 GetPlayer();
3671 if (fPlayer) {
3672 return fPlayer->CopyTree(selection, option, nentries, firstentry);
3673 }
3674 return 0;
3675}
3676
3677////////////////////////////////////////////////////////////////////////////////
3678/// Create a basket for this tree and given branch.
3681{
3682 if (!branch) {
3683 return 0;
3684 }
3685 return new TBasket(branch->GetName(), GetName(), branch);
3686}
3687
3688////////////////////////////////////////////////////////////////////////////////
3689/// Delete this tree from memory or/and disk.
3690///
3691/// - if option == "all" delete Tree object from memory AND from disk
3692/// all baskets on disk are deleted. All keys with same name
3693/// are deleted.
3694/// - if option =="" only Tree object in memory is deleted.
3696void TTree::Delete(Option_t* option /* = "" */)
3697{
3699
3700 // delete all baskets and header from file
3701 if (file && !strcmp(option,"all")) {
3702 if (!file->IsWritable()) {
3703 Error("Delete","File : %s is not writable, cannot delete Tree:%s", file->GetName(),GetName());
3704 return;
3705 }
3706
3707 //find key and import Tree header in memory
3708 TKey *key = fDirectory->GetKey(GetName());
3709 if (!key) return;
3710
3711 TDirectory *dirsav = gDirectory;
3712 file->cd();
3713
3714 //get list of leaves and loop on all the branches baskets
3715 TIter next(GetListOfLeaves());
3716 TLeaf *leaf;
3717 char header[16];
3718 Int_t ntot = 0;
3719 Int_t nbask = 0;
3720 Int_t nbytes,objlen,keylen;
3721 while ((leaf = (TLeaf*)next())) {
3722 TBranch *branch = leaf->GetBranch();
3723 Int_t nbaskets = branch->GetMaxBaskets();
3724 for (Int_t i=0;i<nbaskets;i++) {
3725 Long64_t pos = branch->GetBasketSeek(i);
3726 if (!pos) continue;
3727 TFile *branchFile = branch->GetFile();
3728 if (!branchFile) continue;
3729 branchFile->GetRecordHeader(header,pos,16,nbytes,objlen,keylen);
3730 if (nbytes <= 0) continue;
3731 branchFile->MakeFree(pos,pos+nbytes-1);
3732 ntot += nbytes;
3733 nbask++;
3734 }
3735 }
3736
3737 // delete Tree header key and all keys with the same name
3738 // A Tree may have been saved many times. Previous cycles are invalid.
3739 while (key) {
3740 ntot += key->GetNbytes();
3741 key->Delete();
3742 delete key;
3743 key = fDirectory->GetKey(GetName());
3744 }
3745 if (dirsav) dirsav->cd();
3746 if (gDebug) Info("TTree::Delete", "Deleting Tree: %s: %d baskets deleted. Total space freed = %d bytes\n",GetName(),nbask,ntot);
3747 }
3748
3749 if (fDirectory) {
3750 fDirectory->Remove(this);
3751 //delete the file cache if it points to this Tree
3753 fDirectory = 0;
3755 }
3756
3757 // Delete object from CINT symbol table so it can not be used anymore.
3758 gCling->DeleteGlobal(this);
3759
3760 // Warning: We have intentional invalidated this object while inside a member function!
3761 delete this;
3762}
3763
3764 ///////////////////////////////////////////////////////////////////////////////
3765 /// Called by TKey and TObject::Clone to automatically add us to a directory
3766 /// when we are read from a file.
3769{
3770 if (fDirectory == dir) return;
3771 if (fDirectory) {
3772 fDirectory->Remove(this);
3773 // Delete or move the file cache if it points to this Tree
3775 MoveReadCache(file,dir);
3776 }
3777 fDirectory = dir;
3778 TBranch* b = 0;
3779 TIter next(GetListOfBranches());
3780 while((b = (TBranch*) next())) {
3781 b->UpdateFile();
3782 }
3783 if (fBranchRef) {
3785 }
3786 if (fDirectory) fDirectory->Append(this);
3787}
3788
3789////////////////////////////////////////////////////////////////////////////////
3790/// Draw expression varexp for specified entries.
3791///
3792/// \return -1 in case of error or number of selected events in case of success.
3793///
3794/// This function accepts TCut objects as arguments.
3795/// Useful to use the string operator +
3796///
3797/// Example:
3798///
3799/// ~~~ {.cpp}
3800/// ntuple.Draw("x",cut1+cut2+cut3);
3801/// ~~~
3802
3804Long64_t TTree::Draw(const char* varexp, const TCut& selection, Option_t* option, Long64_t nentries, Long64_t firstentry)
3805{
3806 return TTree::Draw(varexp, selection.GetTitle(), option, nentries, firstentry);
3807}
3808
3809////////////////////////////////////////////////////////////////////////////////
3810/// Draw expression varexp for specified entries.
3811///
3812/// \return -1 in case of error or number of selected events in case of success.
3813///
3814/// \param [in] varexp is an expression of the general form
3815/// - "e1" produces a 1-d histogram (TH1F) of expression "e1"
3816/// - "e1:e2" produces an unbinned 2-d scatter-plot (TGraph) of "e1"
3817/// on the y-axis versus "e2" on the x-axis
3818/// - "e1:e2:e3" produces an unbinned 3-d scatter-plot (TPolyMarker3D) of "e1"
3819/// vs "e2" vs "e3" on the x-, y-, z-axis, respectively.
3820/// - "e1:e2:e3:e4" produces an unbinned 3-d scatter-plot (TPolyMarker3D) of "e1"
3821/// vs "e2" vs "e3" and "e4" mapped on the current color palette.
3822/// (to create histograms in the 2, 3, and 4 dimensional case,
3823/// see section "Saving the result of Draw to an histogram")
3824///
3825/// Example:
3826/// - varexp = x simplest case: draw a 1-Dim distribution of column named x
3827/// - varexp = sqrt(x) : draw distribution of sqrt(x)
3828/// - varexp = x*y/z
3829/// - varexp = y:sqrt(x) 2-Dim distribution of y versus sqrt(x)
3830/// - varexp = px:py:pz:2.5*E produces a 3-d scatter-plot of px vs py ps pz
3831/// and the color number of each marker will be 2.5*E.
3832/// If the color number is negative it is set to 0.
3833/// If the color number is greater than the current number of colors
3834/// it is set to the highest color number.The default number of
3835/// colors is 50. see TStyle::SetPalette for setting a new color palette.
3836///
3837/// Note that the variables e1, e2 or e3 may contain a selection.
3838/// example, if e1= x*(y<0), the value histogrammed will be x if y<0
3839/// and will be 0 otherwise.
3840///
3841/// The expressions can use all the operations and build-in functions
3842/// supported by TFormula (See TFormula::Analyze), including free
3843/// standing function taking numerical arguments (TMath::Bessel).
3844/// In addition, you can call member functions taking numerical
3845/// arguments. For example:
3846/// ~~~ {.cpp}
3847/// TMath::BreitWigner(fPx,3,2)
3848/// event.GetHistogram().GetXaxis().GetXmax()
3849/// ~~~
3850/// Note: You can only pass expression that depend on the TTree's data
3851/// to static functions and you can only call non-static member function
3852/// with 'fixed' parameters.
3853///
3854/// \param [in] selection is an expression with a combination of the columns.
3855/// In a selection all the C++ operators are authorized.
3856/// The value corresponding to the selection expression is used as a weight
3857/// to fill the histogram.
3858/// If the expression includes only boolean operations, the result
3859/// is 0 or 1. If the result is 0, the histogram is not filled.
3860/// In general, the expression may be of the form:
3861/// ~~~ {.cpp}
3862/// value*(boolean expression)
3863/// ~~~
3864/// if boolean expression is true, the histogram is filled with
3865/// a `weight = value`.
3866/// Examples:
3867/// - selection1 = "x<y && sqrt(z)>3.2"
3868/// - selection2 = "(x+y)*(sqrt(z)>3.2)"
3869/// - selection1 returns a weight = 0 or 1
3870/// - selection2 returns a weight = x+y if sqrt(z)>3.2
3871/// returns a weight = 0 otherwise.
3872///
3873/// \param [in] option is the drawing option.
3874/// - When an histogram is produced it can be any histogram drawing option
3875/// listed in THistPainter.
3876/// - when no option is specified:
3877/// - the default histogram drawing option is used
3878/// if the expression is of the form "e1".
3879/// - if the expression is of the form "e1:e2"or "e1:e2:e3" a cloud of
3880/// unbinned 2D or 3D points is drawn respectively.
3881/// - if the expression has four fields "e1:e2:e3:e4" a cloud of unbinned 3D
3882/// points is produced with e1 vs e2 vs e3, and e4 is mapped on the current color
3883/// palette.
3884/// - If option COL is specified when varexp has three fields:
3885/// ~~~ {.cpp}
3886/// tree.Draw("e1:e2:e3","","col");
3887/// ~~~
3888/// a 2D scatter is produced with e1 vs e2, and e3 is mapped on the current
3889/// color palette. The colors for e3 are evaluated once in linear scale before
3890/// painting. Therefore changing the pad to log scale along Z as no effect
3891/// on the colors.
3892/// - if expression has more than four fields the option "PARA"or "CANDLE"
3893/// can be used.
3894/// - If option contains the string "goff", no graphics is generated.
3895///
3896/// \param [in] nentries is the number of entries to process (default is all)
3897///
3898/// \param [in] firstentry is the first entry to process (default is 0)
3899///
3900/// ### Drawing expressions using arrays and array elements
3901///
3902/// Let assumes, a leaf fMatrix, on the branch fEvent, which is a 3 by 3 array,
3903/// or a TClonesArray.
3904/// In a TTree::Draw expression you can now access fMatrix using the following
3905/// syntaxes:
3906///
3907/// | String passed | What is used for each entry of the tree
3908/// |-----------------|--------------------------------------------------------|
3909/// | `fMatrix` | the 9 elements of fMatrix |
3910/// | `fMatrix[][]` | the 9 elements of fMatrix |
3911/// | `fMatrix[2][2]` | only the elements fMatrix[2][2] |
3912/// | `fMatrix[1]` | the 3 elements fMatrix[1][0], fMatrix[1][1] and fMatrix[1][2] |
3913/// | `fMatrix[1][]` | the 3 elements fMatrix[1][0], fMatrix[1][1] and fMatrix[1][2] |
3914/// | `fMatrix[][0]` | the 3 elements fMatrix[0][0], fMatrix[1][0] and fMatrix[2][0] |
3915///
3916/// "fEvent.fMatrix...." same as "fMatrix..." (unless there is more than one leaf named fMatrix!).
3917///
3918/// In summary, if a specific index is not specified for a dimension, TTree::Draw
3919/// will loop through all the indices along this dimension. Leaving off the
3920/// last (right most) dimension of specifying then with the two characters '[]'
3921/// is equivalent. For variable size arrays (and TClonesArray) the range
3922/// of the first dimension is recalculated for each entry of the tree.
3923/// You can also specify the index as an expression of any other variables from the
3924/// tree.
3925///
3926/// TTree::Draw also now properly handling operations involving 2 or more arrays.
3927///
3928/// Let assume a second matrix fResults[5][2], here are a sample of some
3929/// of the possible combinations, the number of elements they produce and
3930/// the loop used:
3931///
3932/// | expression | element(s) | Loop |
3933/// |----------------------------------|------------|--------------------------|
3934/// | `fMatrix[2][1] - fResults[5][2]` | one | no loop |
3935/// | `fMatrix[2][] - fResults[5][2]` | three | on 2nd dim fMatrix |
3936/// | `fMatrix[2][] - fResults[5][]` | two | on both 2nd dimensions |
3937/// | `fMatrix[][2] - fResults[][1]` | three | on both 1st dimensions |
3938/// | `fMatrix[][2] - fResults[][]` | six | on both 1st and 2nd dimensions of fResults |
3939/// | `fMatrix[][2] - fResults[3][]` | two | on 1st dim of fMatrix and 2nd of fResults (at the same time) |
3940/// | `fMatrix[][] - fResults[][]` | six | on 1st dim then on 2nd dim |
3941/// | `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.|
3942///
3943///
3944/// In summary, TTree::Draw loops through all unspecified dimensions. To
3945/// figure out the range of each loop, we match each unspecified dimension
3946/// from left to right (ignoring ALL dimensions for which an index has been
3947/// specified), in the equivalent loop matched dimensions use the same index
3948/// and are restricted to the smallest range (of only the matched dimensions).
3949/// When involving variable arrays, the range can of course be different
3950/// for each entry of the tree.
3951///
3952/// So the loop equivalent to "fMatrix[][2] - fResults[3][]" is:
3953/// ~~~ {.cpp}
3954/// for (Int_t i0; i < min(3,2); i++) {
3955/// use the value of (fMatrix[i0][2] - fMatrix[3][i0])
3956/// }
3957/// ~~~
3958/// So the loop equivalent to "fMatrix[][2] - fResults[][]" is:
3959/// ~~~ {.cpp}
3960/// for (Int_t i0; i < min(3,5); i++) {
3961/// for (Int_t i1; i1 < 2; i1++) {
3962/// use the value of (fMatrix[i0][2] - fMatrix[i0][i1])
3963/// }
3964/// }
3965/// ~~~
3966/// So the loop equivalent to "fMatrix[][] - fResults[][]" is:
3967/// ~~~ {.cpp}
3968/// for (Int_t i0; i < min(3,5); i++) {
3969/// for (Int_t i1; i1 < min(3,2); i1++) {
3970/// use the value of (fMatrix[i0][i1] - fMatrix[i0][i1])
3971/// }
3972/// }
3973/// ~~~
3974/// So the loop equivalent to "fMatrix[][fResults[][]]" is:
3975/// ~~~ {.cpp}
3976/// for (Int_t i0; i0 < 3; i0++) {
3977/// for (Int_t j2; j2 < 5; j2++) {
3978/// for (Int_t j3; j3 < 2; j3++) {
3979/// i1 = fResults[j2][j3];
3980/// use the value of fMatrix[i0][i1]
3981/// }
3982/// }
3983/// ~~~
3984/// ### Retrieving the result of Draw
3985///
3986/// By default the temporary histogram created is called "htemp", but only in
3987/// the one dimensional Draw("e1") it contains the TTree's data points. For
3988/// a two dimensional Draw, the data is filled into a TGraph which is named
3989/// "Graph". They can be retrieved by calling
3990/// ~~~ {.cpp}
3991/// TH1F *htemp = (TH1F*)gPad->GetPrimitive("htemp"); // 1D
3992/// TGraph *graph = (TGraph*)gPad->GetPrimitive("Graph"); // 2D
3993/// ~~~
3994/// For a three and four dimensional Draw the TPolyMarker3D is unnamed, and
3995/// cannot be retrieved.
3996///
3997/// gPad always contains a TH1 derived object called "htemp" which allows to
3998/// access the axes:
3999/// ~~~ {.cpp}
4000/// TGraph *graph = (TGraph*)gPad->GetPrimitive("Graph"); // 2D
4001/// TH2F *htemp = (TH2F*)gPad->GetPrimitive("htemp"); // empty, but has axes
4002/// TAxis *xaxis = htemp->GetXaxis();
4003/// ~~~
4004/// ### Saving the result of Draw to an histogram
4005///
4006/// If varexp0 contains >>hnew (following the variable(s) name(s),
4007/// the new histogram created is called hnew and it is kept in the current
4008/// directory (and also the current pad). This works for all dimensions.
4009///
4010/// Example:
4011/// ~~~ {.cpp}
4012/// tree.Draw("sqrt(x)>>hsqrt","y>0")
4013/// ~~~
4014/// will draw `sqrt(x)` and save the histogram as "hsqrt" in the current
4015/// directory. To retrieve it do:
4016/// ~~~ {.cpp}
4017/// TH1F *hsqrt = (TH1F*)gDirectory->Get("hsqrt");
4018/// ~~~
4019/// The binning information is taken from the environment variables
4020/// ~~~ {.cpp}
4021/// Hist.Binning.?D.?
4022/// ~~~
4023/// In addition, the name of the histogram can be followed by up to 9
4024/// numbers between '(' and ')', where the numbers describe the
4025/// following:
4026///
4027/// - 1 - bins in x-direction
4028/// - 2 - lower limit in x-direction
4029/// - 3 - upper limit in x-direction
4030/// - 4-6 same for y-direction
4031/// - 7-9 same for z-direction
4032///
4033/// When a new binning is used the new value will become the default.
4034/// Values can be skipped.
4035///
4036/// Example:
4037/// ~~~ {.cpp}
4038/// tree.Draw("sqrt(x)>>hsqrt(500,10,20)")
4039/// // plot sqrt(x) between 10 and 20 using 500 bins
4040/// tree.Draw("sqrt(x):sin(y)>>hsqrt(100,10,60,50,.1,.5)")
4041/// // plot sqrt(x) against sin(y)
4042/// // 100 bins in x-direction; lower limit on x-axis is 10; upper limit is 60
4043/// // 50 bins in y-direction; lower limit on y-axis is .1; upper limit is .5
4044/// ~~~
4045/// By default, the specified histogram is reset.
4046/// To continue to append data to an existing histogram, use "+" in front
4047/// of the histogram name.
4048///
4049/// A '+' in front of the histogram name is ignored, when the name is followed by
4050/// binning information as described in the previous paragraph.
4051/// ~~~ {.cpp}
4052/// tree.Draw("sqrt(x)>>+hsqrt","y>0")
4053/// ~~~
4054/// will not reset `hsqrt`, but will continue filling. This works for 1-D, 2-D
4055/// and 3-D histograms.
4056///
4057/// ### Accessing collection objects
4058///
4059/// TTree::Draw default's handling of collections is to assume that any
4060/// request on a collection pertain to it content. For example, if fTracks
4061/// is a collection of Track objects, the following:
4062/// ~~~ {.cpp}
4063/// tree->Draw("event.fTracks.fPx");
4064/// ~~~
4065/// will plot the value of fPx for each Track objects inside the collection.
4066/// Also
4067/// ~~~ {.cpp}
4068/// tree->Draw("event.fTracks.size()");
4069/// ~~~
4070/// would plot the result of the member function Track::size() for each
4071/// Track object inside the collection.
4072/// To access information about the collection itself, TTree::Draw support
4073/// the '@' notation. If a variable which points to a collection is prefixed
4074/// or postfixed with '@', the next part of the expression will pertain to
4075/// the collection object. For example:
4076/// ~~~ {.cpp}
4077/// tree->Draw("event.@fTracks.size()");
4078/// ~~~
4079/// will plot the size of the collection referred to by `fTracks` (i.e the number
4080/// of Track objects).
4081///
4082/// ### Drawing 'objects'
4083///
4084/// When a class has a member function named AsDouble or AsString, requesting
4085/// to directly draw the object will imply a call to one of the 2 functions.
4086/// If both AsDouble and AsString are present, AsDouble will be used.
4087/// AsString can return either a char*, a std::string or a TString.s
4088/// For example, the following
4089/// ~~~ {.cpp}
4090/// tree->Draw("event.myTTimeStamp");
4091/// ~~~
4092/// will draw the same histogram as
4093/// ~~~ {.cpp}
4094/// tree->Draw("event.myTTimeStamp.AsDouble()");
4095/// ~~~
4096/// In addition, when the object is a type TString or std::string, TTree::Draw
4097/// will call respectively `TString::Data` and `std::string::c_str()`
4098///
4099/// If the object is a TBits, the histogram will contain the index of the bit
4100/// that are turned on.
4101///
4102/// ### Retrieving information about the tree itself.
4103///
4104/// You can refer to the tree (or chain) containing the data by using the
4105/// string 'This'.
4106/// You can then could any TTree methods. For example:
4107/// ~~~ {.cpp}
4108/// tree->Draw("This->GetReadEntry()");
4109/// ~~~
4110/// will display the local entry numbers be read.
4111/// ~~~ {.cpp}
4112/// tree->Draw("This->GetUserInfo()->At(0)->GetName()");
4113/// ~~~
4114/// will display the name of the first 'user info' object.
4115///
4116/// ### Special functions and variables
4117///
4118/// `Entry$`: A TTree::Draw formula can use the special variable `Entry$`
4119/// to access the entry number being read. For example to draw every
4120/// other entry use:
4121/// ~~~ {.cpp}
4122/// tree.Draw("myvar","Entry$%2==0");
4123/// ~~~
4124/// - `Entry$` : return the current entry number (`== TTree::GetReadEntry()`)
4125/// - `LocalEntry$` : return the current entry number in the current tree of a
4126/// chain (`== GetTree()->GetReadEntry()`)
4127/// - `Entries$` : return the total number of entries (== TTree::GetEntries())
4128/// - `LocalEntries$` : return the total number of entries in the current tree
4129/// of a chain (== GetTree()->TTree::GetEntries())
4130/// - `Length$` : return the total number of element of this formula for this
4131/// entry (`==TTreeFormula::GetNdata()`)
4132/// - `Iteration$` : return the current iteration over this formula for this
4133/// entry (i.e. varies from 0 to `Length$`).
4134/// - `Length$(formula )` : return the total number of element of the formula
4135/// given as a parameter.
4136/// - `Sum$(formula )` : return the sum of the value of the elements of the
4137/// formula given as a parameter. For example the mean for all the elements in
4138/// one entry can be calculated with: `Sum$(formula )/Length$(formula )`
4139/// - `Min$(formula )` : return the minimun (within one TTree entry) of the value of the
4140/// elements of the formula given as a parameter.
4141/// - `Max$(formula )` : return the maximum (within one TTree entry) of the value of the
4142/// elements of the formula given as a parameter.
4143/// - `MinIf$(formula,condition)`
4144/// - `MaxIf$(formula,condition)` : return the minimum (maximum) (within one TTree entry)
4145/// of the value of the elements of the formula given as a parameter
4146/// if they match the condition. If no element matches the condition,
4147/// the result is zero. To avoid the resulting peak at zero, use the
4148/// pattern:
4149/// ~~~ {.cpp}
4150/// tree->Draw("MinIf$(formula,condition)","condition");
4151/// ~~~
4152/// which will avoid calculation `MinIf$` for the entries that have no match
4153/// for the condition.
4154/// - `Alt$(primary,alternate)` : return the value of "primary" if it is available
4155/// for the current iteration otherwise return the value of "alternate".
4156/// For example, with arr1[3] and arr2[2]
4157/// ~~~ {.cpp}
4158/// tree->Draw("arr1+Alt$(arr2,0)");
4159/// ~~~
4160/// will draw arr1[0]+arr2[0] ; arr1[1]+arr2[1] and arr1[2]+0
4161/// Or with a variable size array arr3
4162/// ~~~ {.cpp}
4163/// tree->Draw("Alt$(arr3[0],0)+Alt$(arr3[1],0)+Alt$(arr3[2],0)");
4164/// ~~~
4165/// will draw the sum arr3 for the index 0 to min(2,actual_size_of_arr3-1)
4166/// As a comparison
4167/// ~~~ {.cpp}
4168/// tree->Draw("arr3[0]+arr3[1]+arr3[2]");
4169/// ~~~
4170/// will draw the sum arr3 for the index 0 to 2 only if the
4171/// actual_size_of_arr3 is greater or equal to 3.
4172/// Note that the array in 'primary' is flattened/linearized thus using
4173/// `Alt$` with multi-dimensional arrays of different dimensions in unlikely
4174/// to yield the expected results. To visualize a bit more what elements
4175/// would be matched by TTree::Draw, TTree::Scan can be used:
4176/// ~~~ {.cpp}
4177/// tree->Scan("arr1:Alt$(arr2,0)");
4178/// ~~~
4179/// will print on one line the value of arr1 and (arr2,0) that will be
4180/// matched by
4181/// ~~~ {.cpp}
4182/// tree->Draw("arr1-Alt$(arr2,0)");
4183/// ~~~
4184/// The ternary operator is not directly supported in TTree::Draw however, to plot the
4185/// equivalent of `var2<20 ? -99 : var1`, you can use:
4186/// ~~~ {.cpp}
4187/// tree->Draw("(var2<20)*99+(var2>=20)*var1","");
4188/// ~~~
4189///
4190/// ### Drawing a user function accessing the TTree data directly
4191///
4192/// If the formula contains a file name, TTree::MakeProxy will be used
4193/// to load and execute this file. In particular it will draw the
4194/// result of a function with the same name as the file. The function
4195/// will be executed in a context where the name of the branches can
4196/// be used as a C++ variable.
4197///
4198/// For example draw px using the file hsimple.root (generated by the
4199/// hsimple.C tutorial), we need a file named hsimple.cxx:
4200/// ~~~ {.cpp}
4201/// double hsimple() {
4202/// return px;
4203/// }
4204/// ~~~
4205/// MakeProxy can then be used indirectly via the TTree::Draw interface
4206/// as follow:
4207/// ~~~ {.cpp}
4208/// new TFile("hsimple.root")
4209/// ntuple->Draw("hsimple.cxx");
4210/// ~~~
4211/// A more complete example is available in the tutorials directory:
4212/// `h1analysisProxy.cxx`, `h1analysProxy.h` and `h1analysisProxyCut.C`
4213/// which reimplement the selector found in `h1analysis.C`
4214///
4215/// The main features of this facility are:
4216///
4217/// * on-demand loading of branches
4218/// * ability to use the 'branchname' as if it was a data member
4219/// * protection against array out-of-bound
4220/// * ability to use the branch data as object (when the user code is available)
4221///
4222/// See TTree::MakeProxy for more details.
4223///
4224/// ### Making a Profile histogram
4225///
4226/// In case of a 2-Dim expression, one can generate a TProfile histogram
4227/// instead of a TH2F histogram by specifying option=prof or option=profs
4228/// or option=profi or option=profg ; the trailing letter select the way
4229/// the bin error are computed, See TProfile2D::SetErrorOption for
4230/// details on the differences.
4231/// The option=prof is automatically selected in case of y:x>>pf
4232/// where pf is an existing TProfile histogram.
4233///
4234/// ### Making a 2D Profile histogram
4235///
4236/// In case of a 3-Dim expression, one can generate a TProfile2D histogram
4237/// instead of a TH3F histogram by specifying option=prof or option=profs.
4238/// or option=profi or option=profg ; the trailing letter select the way
4239/// the bin error are computed, See TProfile2D::SetErrorOption for
4240/// details on the differences.
4241/// The option=prof is automatically selected in case of z:y:x>>pf
4242/// where pf is an existing TProfile2D histogram.
4243///
4244/// ### Making a 5D plot using GL
4245///
4246/// If option GL5D is specified together with 5 variables, a 5D plot is drawn
4247/// using OpenGL. See $ROOTSYS/tutorials/tree/staff.C as example.
4248///
4249/// ### Making a parallel coordinates plot
4250///
4251/// In case of a 2-Dim or more expression with the option=para, one can generate
4252/// a parallel coordinates plot. With that option, the number of dimensions is
4253/// arbitrary. Giving more than 4 variables without the option=para or
4254/// option=candle or option=goff will produce an error.
4255///
4256/// ### Making a candle sticks chart
4257///
4258/// In case of a 2-Dim or more expression with the option=candle, one can generate
4259/// a candle sticks chart. With that option, the number of dimensions is
4260/// arbitrary. Giving more than 4 variables without the option=para or
4261/// option=candle or option=goff will produce an error.
4262///
4263/// ### Normalizing the output histogram to 1
4264///
4265/// When option contains "norm" the output histogram is normalized to 1.
4266///
4267/// ### Saving the result of Draw to a TEventList, a TEntryList or a TEntryListArray
4268///
4269/// TTree::Draw can be used to fill a TEventList object (list of entry numbers)
4270/// instead of histogramming one variable.
4271/// If varexp0 has the form >>elist , a TEventList object named "elist"
4272/// is created in the current directory. elist will contain the list
4273/// of entry numbers satisfying the current selection.
4274/// If option "entrylist" is used, a TEntryList object is created
4275/// If the selection contains arrays, vectors or any container class and option
4276/// "entrylistarray" is used, a TEntryListArray object is created
4277/// containing also the subentries satisfying the selection, i.e. the indices of
4278/// the branches which hold containers classes.
4279/// Example:
4280/// ~~~ {.cpp}
4281/// tree.Draw(">>yplus","y>0")
4282/// ~~~
4283/// will create a TEventList object named "yplus" in the current directory.
4284/// In an interactive session, one can type (after TTree::Draw)
4285/// ~~~ {.cpp}
4286/// yplus.Print("all")
4287/// ~~~
4288/// to print the list of entry numbers in the list.
4289/// ~~~ {.cpp}
4290/// tree.Draw(">>yplus", "y>0", "entrylist")
4291/// ~~~
4292/// will create a TEntryList object names "yplus" in the current directory
4293/// ~~~ {.cpp}
4294/// tree.Draw(">>yplus", "y>0", "entrylistarray")
4295/// ~~~
4296/// will create a TEntryListArray object names "yplus" in the current directory
4297///
4298/// By default, the specified entry list is reset.
4299/// To continue to append data to an existing list, use "+" in front
4300/// of the list name;
4301/// ~~~ {.cpp}
4302/// tree.Draw(">>+yplus","y>0")
4303/// ~~~
4304/// will not reset yplus, but will enter the selected entries at the end
4305/// of the existing list.
4306///
4307/// ### Using a TEventList, TEntryList or TEntryListArray as Input
4308///
4309/// Once a TEventList or a TEntryList object has been generated, it can be used as input
4310/// for TTree::Draw. Use TTree::SetEventList or TTree::SetEntryList to set the
4311/// current event list
4312///
4313/// Example 1:
4314/// ~~~ {.cpp}
4315/// TEventList *elist = (TEventList*)gDirectory->Get("yplus");
4316/// tree->SetEventList(elist);
4317/// tree->Draw("py");
4318/// ~~~
4319/// Example 2:
4320/// ~~~ {.cpp}
4321/// TEntryList *elist = (TEntryList*)gDirectory->Get("yplus");
4322/// tree->SetEntryList(elist);
4323/// tree->Draw("py");
4324/// ~~~
4325/// If a TEventList object is used as input, a new TEntryList object is created
4326/// inside the SetEventList function. In case of a TChain, all tree headers are loaded
4327/// for this transformation. This new object is owned by the chain and is deleted
4328/// with it, unless the user extracts it by calling GetEntryList() function.
4329/// See also comments to SetEventList() function of TTree and TChain.
4330///
4331/// If arrays are used in the selection criteria and TEntryListArray is not used,
4332/// all the entries that have at least one element of the array that satisfy the selection
4333/// are entered in the list.
4334///
4335/// Example:
4336/// ~~~ {.cpp}
4337/// tree.Draw(">>pyplus","fTracks.fPy>0");
4338/// tree->SetEventList(pyplus);
4339/// tree->Draw("fTracks.fPy");
4340/// ~~~
4341/// will draw the fPy of ALL tracks in event with at least one track with
4342/// a positive fPy.
4343///
4344/// To select only the elements that did match the original selection
4345/// use TEventList::SetReapplyCut or TEntryList::SetReapplyCut.
4346///
4347/// Example:
4348/// ~~~ {.cpp}
4349/// tree.Draw(">>pyplus","fTracks.fPy>0");
4350/// pyplus->SetReapplyCut(kTRUE);
4351/// tree->SetEventList(pyplus);
4352/// tree->Draw("fTracks.fPy");
4353/// ~~~
4354/// will draw the fPy of only the tracks that have a positive fPy.
4355///
4356/// To draw only the elements that match a selection in case of arrays,
4357/// you can also use TEntryListArray (faster in case of a more general selection).
4358///
4359/// Example:
4360/// ~~~ {.cpp}
4361/// tree.Draw(">>pyplus","fTracks.fPy>0", "entrylistarray");
4362/// tree->SetEntryList(pyplus);
4363/// tree->Draw("fTracks.fPy");
4364/// ~~~
4365/// will draw the fPy of only the tracks that have a positive fPy,
4366/// but without redoing the selection.
4367///
4368/// Note: Use tree->SetEventList(0) if you do not want use the list as input.
4369///
4370/// ### How to obtain more info from TTree::Draw
4371///
4372/// Once TTree::Draw has been called, it is possible to access useful
4373/// information still stored in the TTree object via the following functions:
4374///
4375/// - GetSelectedRows() // return the number of values accepted by the selection expression. In case where no selection was specified, returns the number of values processed.
4376/// - GetV1() // returns a pointer to the double array of V1
4377/// - GetV2() // returns a pointer to the double array of V2
4378/// - GetV3() // returns a pointer to the double array of V3
4379/// - GetV4() // returns a pointer to the double array of V4
4380/// - GetW() // returns a pointer to the double array of Weights where weight equal the result of the selection expression.
4381///
4382/// where V1,V2,V3 correspond to the expressions in
4383/// ~~~ {.cpp}
4384/// TTree::Draw("V1:V2:V3:V4",selection);
4385/// ~~~
4386/// If the expression has more than 4 component use GetVal(index)
4387///
4388/// Example:
4389/// ~~~ {.cpp}
4390/// Root > ntuple->Draw("py:px","pz>4");
4391/// Root > TGraph *gr = new TGraph(ntuple->GetSelectedRows(),
4392/// ntuple->GetV2(), ntuple->GetV1());
4393/// Root > gr->Draw("ap"); //draw graph in current pad
4394/// ~~~
4395///
4396/// A more complete complete tutorial (treegetval.C) shows how to use the
4397/// GetVal() method.
4398///
4399/// creates a TGraph object with a number of points corresponding to the
4400/// number of entries selected by the expression "pz>4", the x points of the graph
4401/// being the px values of the Tree and the y points the py values.
4402///
4403/// Important note: By default TTree::Draw creates the arrays obtained
4404/// with GetW, GetV1, GetV2, GetV3, GetV4, GetVal with a length corresponding
4405/// to the parameter fEstimate. The content will be the last `GetSelectedRows() % GetEstimate()`
4406/// values calculated.
4407/// By default fEstimate=1000000 and can be modified
4408/// via TTree::SetEstimate. To keep in memory all the results (in case
4409/// where there is only one result per entry), use
4410/// ~~~ {.cpp}
4411/// tree->SetEstimate(tree->GetEntries()+1); // same as tree->SetEstimate(-1);
4412/// ~~~
4413/// You must call SetEstimate if the expected number of selected rows
4414/// you need to look at is greater than 1000000.
4415///
4416/// You can use the option "goff" to turn off the graphics output
4417/// of TTree::Draw in the above example.
4418///
4419/// ### Automatic interface to TTree::Draw via the TTreeViewer
4420///
4421/// A complete graphical interface to this function is implemented
4422/// in the class TTreeViewer.
4423/// To start the TTreeViewer, three possibilities:
4424/// - select TTree context menu item "StartViewer"
4425/// - type the command "TTreeViewer TV(treeName)"
4426/// - execute statement "tree->StartViewer();"
4428Long64_t TTree::Draw(const char* varexp, const char* selection, Option_t* option, Long64_t nentries, Long64_t firstentry)
4429{
4430 GetPlayer();
4431 if (fPlayer)
4432 return fPlayer->DrawSelect(varexp,selection,option,nentries,firstentry);
4433 return -1;
4434}
4435
4436////////////////////////////////////////////////////////////////////////////////
4437/// Remove some baskets from memory.
4439void TTree::DropBaskets()
4440{
4441 TBranch* branch = 0;
4443 for (Int_t i = 0; i < nb; ++i) {
4444 branch = (TBranch*) fBranches.UncheckedAt(i);
4445 branch->DropBaskets("all");
4446 }
4447}
4448
4449////////////////////////////////////////////////////////////////////////////////
4450/// Drop branch buffers to accommodate nbytes below MaxVirtualsize.
4453{
4454 // Be careful not to remove current read/write buffers.
4455 Int_t ndrop = 0;
4456 Int_t nleaves = fLeaves.GetEntriesFast();
4457 for (Int_t i = 0; i < nleaves; ++i) {
4458 TLeaf* leaf = (TLeaf*) fLeaves.UncheckedAt(i);
4459 TBranch* branch = (TBranch*) leaf->GetBranch();
4460 Int_t nbaskets = branch->GetListOfBaskets()->GetEntries();
4461 for (Int_t j = 0; j < nbaskets - 1; ++j) {
4462 if ((j == branch->GetReadBasket()) || (j == branch->GetWriteBasket())) {
4463 continue;
4464 }
4465 TBasket* basket = (TBasket*)branch->GetListOfBaskets()->UncheckedAt(j);
4466 if (basket) {
4467 ndrop += basket->DropBuffers();
4469 return;
4470 }
4471 }
4472 }
4473 }
4474}
4475
4476////////////////////////////////////////////////////////////////////////////////
4477/// Fill all branches.
4478///
4479/// This function loops on all the branches of this tree. For
4480/// each branch, it copies to the branch buffer (basket) the current
4481/// values of the leaves data types. If a leaf is a simple data type,
4482/// a simple conversion to a machine independent format has to be done.
4483///
4484/// This machine independent version of the data is copied into a
4485/// basket (each branch has its own basket). When a basket is full
4486/// (32k worth of data by default), it is then optionally compressed
4487/// and written to disk (this operation is also called committing or
4488/// 'flushing' the basket). The committed baskets are then
4489/// immediately removed from memory.
4490///
4491/// The function returns the number of bytes committed to the
4492/// individual branches.
4493///
4494/// If a write error occurs, the number of bytes returned is -1.
4495///
4496/// If no data are written, because, e.g., the branch is disabled,
4497/// the number of bytes returned is 0.
4498///
4499/// __The baskets are flushed and the Tree header saved at regular intervals__
4500///
4501/// At regular intervals, when the amount of data written so far is
4502/// greater than fAutoFlush (see SetAutoFlush) all the baskets are flushed to disk.
4503/// This makes future reading faster as it guarantees that baskets belonging to nearby
4504/// entries will be on the same disk region.
4505/// When the first call to flush the baskets happen, we also take this opportunity
4506/// to optimize the baskets buffers.
4507/// We also check if the amount of data written is greater than fAutoSave (see SetAutoSave).
4508/// In this case we also write the Tree header. This makes the Tree recoverable up to this point
4509/// in case the program writing the Tree crashes.
4510/// The decisions to FlushBaskets and Auto Save can be made based either on the number
4511/// of bytes written (fAutoFlush and fAutoSave negative) or on the number of entries
4512/// written (fAutoFlush and fAutoSave positive).
4513/// Note that the user can decide to call FlushBaskets and AutoSave in her event loop
4514/// base on the number of events written instead of the number of bytes written.
4515///
4516/// \note Calling `TTree::FlushBaskets` too often increases the IO time.
4517///
4518/// \note Calling `TTree::AutoSave` too often increases the IO time and also the
4519/// file size.
4520///
4521/// \note This method calls `TTree::ChangeFile` when the tree reaches a size
4522/// greater than `TTree::fgMaxTreeSize`. This doesn't happen if the tree is
4523/// attached to a `TMemFile` or derivate.
4526{
4527 Int_t nbytes = 0;
4528 Int_t nwrite = 0;
4529 Int_t nerror = 0;
4530 Int_t nbranches = fBranches.GetEntriesFast();
4531
4532 // Case of one single super branch. Automatically update
4533 // all the branch addresses if a new object was created.
4534 if (nbranches == 1)
4535 ((TBranch *)fBranches.UncheckedAt(0))->UpdateAddress();
4536
4537 if (fBranchRef)
4538 fBranchRef->Clear();
4539
4540#ifdef R__USE_IMT
4541 const auto useIMT = ROOT::IsImplicitMTEnabled() && fIMTEnabled;
4543 if (useIMT) {
4544 fIMTFlush = true;
4545 fIMTZipBytes.store(0);
4546 fIMTTotBytes.store(0);
4547 }
4548#endif
4549
4550 for (Int_t i = 0; i < nbranches; ++i) {
4551 // Loop over all branches, filling and accumulating bytes written and error counts.
4552 TBranch *branch = (TBranch *)fBranches.UncheckedAt(i);
4553
4554 if (branch->TestBit(kDoNotProcess))
4555 continue;
4556
4557#ifndef R__USE_IMT
4558 nwrite = branch->FillImpl(nullptr);
4559#else
4560 nwrite = branch->FillImpl(useIMT ? &imtHelper : nullptr);
4561#endif
4562 if (nwrite < 0) {
4563 if (nerror < 2) {
4564 Error("Fill", "Failed filling branch:%s.%s, nbytes=%d, entry=%lld\n"
4565 " This error is symptomatic of a Tree created as a memory-resident Tree\n"
4566 " Instead of doing:\n"
4567 " TTree *T = new TTree(...)\n"
4568 " TFile *f = new TFile(...)\n"
4569 " you should do:\n"
4570 " TFile *f = new TFile(...)\n"
4571 " TTree *T = new TTree(...)\n\n",
4572 GetName(), branch->GetName(), nwrite, fEntries + 1);
4573 } else {
4574 Error("Fill", "Failed filling branch:%s.%s, nbytes=%d, entry=%lld", GetName(), branch->GetName(), nwrite,
4575 fEntries + 1);
4576 }
4577 ++nerror;
4578 } else {
4579 nbytes += nwrite;
4580 }
4581 }
4582
4583#ifdef R__USE_IMT
4584 if (fIMTFlush) {
4585 imtHelper.Wait();
4586 fIMTFlush = false;
4587 const_cast<TTree *>(this)->AddTotBytes(fIMTTotBytes);
4588 const_cast<TTree *>(this)->AddZipBytes(fIMTZipBytes);
4589 nbytes += imtHelper.GetNbytes();
4590 nerror += imtHelper.GetNerrors();
4591 }
4592#endif
4593
4594 if (fBranchRef)
4595 fBranchRef->Fill();
4596
4597 ++fEntries;
4598
4599 if (fEntries > fMaxEntries)
4600 KeepCircular();
4601
4602 if (gDebug > 0)
4603 Info("TTree::Fill", " - A: %d %lld %lld %lld %lld %lld %lld \n", nbytes, fEntries, fAutoFlush, fAutoSave,
4605
4606 bool autoFlush = false;
4607 bool autoSave = false;
4608
4609 if (fAutoFlush != 0 || fAutoSave != 0) {
4610 // Is it time to flush or autosave baskets?
4611 if (fFlushedBytes == 0) {
4612 // If fFlushedBytes == 0, it means we never flushed or saved, so
4613 // we need to check if it's time to do it and recompute the values
4614 // of fAutoFlush and fAutoSave in terms of the number of entries.
4615 // Decision can be based initially either on the number of bytes
4616 // or the number of entries written.
4617 Long64_t zipBytes = GetZipBytes();
4618
4619 if (fAutoFlush)
4620 autoFlush = fAutoFlush < 0 ? (zipBytes > -fAutoFlush) : fEntries % fAutoFlush == 0;
4621
4622 if (fAutoSave)
4623 autoSave = fAutoSave < 0 ? (zipBytes > -fAutoSave) : fEntries % fAutoSave == 0;
4624
4625 if (autoFlush || autoSave) {
4626 // First call FlushBasket to make sure that fTotBytes is up to date.
4628 autoFlush = false; // avoid auto flushing again later
4629
4630 // When we are in one-basket-per-cluster mode, there is no need to optimize basket:
4631 // they will automatically grow to the size needed for an event cluster (with the basket
4632 // shrinking preventing them from growing too much larger than the actually-used space).
4634 OptimizeBaskets(GetTotBytes(), 1, "");
4635 if (gDebug > 0)
4636 Info("TTree::Fill", "OptimizeBaskets called at entry %lld, fZipBytes=%lld, fFlushedBytes=%lld\n",
4638 }
4640 fAutoFlush = fEntries; // Use test on entries rather than bytes
4641
4642 // subsequently in run
4643 if (fAutoSave < 0) {
4644 // Set fAutoSave to the largest integer multiple of
4645 // fAutoFlush events such that fAutoSave*fFlushedBytes
4646 // < (minus the input value of fAutoSave)
4647 Long64_t totBytes = GetTotBytes();
4648 if (zipBytes != 0) {
4649 fAutoSave = TMath::Max(fAutoFlush, fEntries * ((-fAutoSave / zipBytes) / fEntries));
4650 } else if (totBytes != 0) {
4651 fAutoSave = TMath::Max(fAutoFlush, fEntries * ((-fAutoSave / totBytes) / fEntries));
4652 } else {
4654 TTree::Class()->WriteBuffer(b, (TTree *)this);
4655 Long64_t total = b.Length();
4657 }
4658 } else if (fAutoSave > 0) {
4660 }
4661
4662 if (fAutoSave != 0 && fEntries >= fAutoSave)
4663 autoSave = true;
4664
4665 if (gDebug > 0)
4666 Info("TTree::Fill", "First AutoFlush. fAutoFlush = %lld, fAutoSave = %lld\n", fAutoFlush, fAutoSave);
4667 }
4668 } else {
4669 // Check if we need to auto flush
4670 if (fAutoFlush) {
4671 if (fNClusterRange == 0)
4672 autoFlush = fEntries > 1 && fEntries % fAutoFlush == 0;
4673 else
4674 autoFlush = (fEntries - (fClusterRangeEnd[fNClusterRange - 1] + 1)) % fAutoFlush == 0;
4675 }
4676 // Check if we need to auto save
4677 if (fAutoSave)
4678 autoSave = fEntries % fAutoSave == 0;
4679 }
4680 }
4681
4682 if (autoFlush) {
4684 if (gDebug > 0)
4685 Info("TTree::Fill", "FlushBaskets() called at entry %lld, fZipBytes=%lld, fFlushedBytes=%lld\n", fEntries,
4688 }
4689
4690 if (autoSave) {
4691 AutoSave(); // does not call FlushBasketsImpl() again
4692 if (gDebug > 0)
4693 Info("TTree::Fill", "AutoSave called at entry %lld, fZipBytes=%lld, fSavedBytes=%lld\n", fEntries,
4695 }
4696
4697 // Check that output file is still below the maximum size.
4698 // If above, close the current file and continue on a new file.
4699 // Currently, the automatic change of file is restricted
4700 // to the case where the tree is in the top level directory.
4701 if (fDirectory)
4702 if (TFile *file = fDirectory->GetFile())
4703 if (static_cast<TDirectory *>(file) == fDirectory && (file->GetEND() > fgMaxTreeSize))
4704 // Changing file clashes with the design of TMemFile and derivates, see #6523.
4705 if (!(dynamic_cast<TMemFile *>(file)))
4707
4708 return nerror == 0 ? nbytes : -1;
4709}
4710
4711////////////////////////////////////////////////////////////////////////////////
4712/// Search in the array for a branch matching the branch name,
4713/// with the branch possibly expressed as a 'full' path name (with dots).
4715static TBranch *R__FindBranchHelper(TObjArray *list, const char *branchname) {
4716 if (list==0 || branchname == 0 || branchname[0] == '\0') return 0;
4717
4718 Int_t nbranches = list->GetEntries();
4719
4720 UInt_t brlen = strlen(branchname);
4721
4722 for(Int_t index = 0; index < nbranches; ++index) {
4723 TBranch *where = (TBranch*)list->UncheckedAt(index);
4724
4725 const char *name = where->GetName();
4726 UInt_t len = strlen(name);
4727 if (len && name[len-1]==']') {
4728 const char *dim = strchr(name,'[');
4729 if (dim) {
4730 len = dim - name;
4731 }
4732 }
4733 if (brlen == len && strncmp(branchname,name,len)==0) {
4734 return where;
4735 }
4736 TBranch *next = 0;
4737 if ((brlen >= len) && (branchname[len] == '.')
4738 && strncmp(name, branchname, len) == 0) {
4739 // The prefix subbranch name match the branch name.
4740
4741 next = where->FindBranch(branchname);
4742 if (!next) {
4743 next = where->FindBranch(branchname+len+1);
4744 }
4745 if (next) return next;
4746 }
4747 const char *dot = strchr((char*)branchname,'.');
4748 if (dot) {
4749 if (len==(size_t)(dot-branchname) &&
4750 strncmp(branchname,name,dot-branchname)==0 ) {
4751 return R__FindBranchHelper(where->GetListOfBranches(),dot+1);
4752 }
4753 }
4754 }
4755 return 0;
4756}
4757
4758////////////////////////////////////////////////////////////////////////////////
4759/// Return the branch that correspond to the path 'branchname', which can
4760/// include the name of the tree or the omitted name of the parent branches.
4761/// In case of ambiguity, returns the first match.
4763TBranch* TTree::FindBranch(const char* branchname)
4764{
4765 // We already have been visited while recursively looking
4766 // through the friends tree, let return
4768 return 0;
4769 }
4770
4771 TBranch* branch = 0;
4772 // If the first part of the name match the TTree name, look for the right part in the
4773 // list of branches.
4774 // This will allow the branchname to be preceded by
4775 // the name of this tree.
4776 if (strncmp(fName.Data(),branchname,fName.Length())==0 && branchname[fName.Length()]=='.') {
4777 branch = R__FindBranchHelper( GetListOfBranches(), branchname + fName.Length() + 1);
4778 if (branch) return branch;
4779 }
4780 // If we did not find it, let's try to find the full name in the list of branches.
4781 branch = R__FindBranchHelper(GetListOfBranches(), branchname);
4782 if (branch) return branch;
4783
4784 // If we still did not find, let's try to find it within each branch assuming it does not the branch name.
4785 TIter next(GetListOfBranches());
4786 while ((branch = (TBranch*) next())) {
4787 TBranch* nestedbranch = branch->FindBranch(branchname);
4788 if (nestedbranch) {
4789 return nestedbranch;
4790 }
4791 }
4792
4793 // Search in list of friends.
4794 if (!fFriends) {
4795 return 0;
4796 }
4797 TFriendLock lock(this, kFindBranch);
4798 TIter nextf(fFriends);
4799 TFriendElement* fe = 0;
4800 while ((fe = (TFriendElement*) nextf())) {
4801 TTree* t = fe->GetTree();
4802 if (!t) {
4803 continue;
4804 }
4805 // If the alias is present replace it with the real name.
4806 const char *subbranch = strstr(branchname, fe->GetName());
4807 if (subbranch != branchname) {
4808 subbranch = 0;
4809 }
4810 if (subbranch) {
4811 subbranch += strlen(fe->GetName());
4812 if (*subbranch != '.') {
4813 subbranch = 0;
4814 } else {
4815 ++subbranch;
4816 }
4817 }
4818 std::ostringstream name;
4819 if (subbranch) {
4820 name << t->GetName() << "." << subbranch;
4821 } else {
4822 name << branchname;
4823 }
4824 branch = t->FindBranch(name.str().c_str());
4825 if (branch) {
4826 return branch;
4827 }
4828 }
4829 return 0;
4830}
4831
4832////////////////////////////////////////////////////////////////////////////////
4833/// Find leaf..
4835TLeaf* TTree::FindLeaf(const char* searchname)
4836{
4837 // We already have been visited while recursively looking
4838 // through the friends tree, let's return.
4840 return 0;
4841 }
4842
4843 // This will allow the branchname to be preceded by
4844 // the name of this tree.
4845 char* subsearchname = (char*) strstr(searchname, GetName());
4846 if (subsearchname != searchname) {
4847 subsearchname = 0;
4848 }
4849 if (subsearchname) {
4850 subsearchname += strlen(GetName());
4851 if (*subsearchname != '.') {
4852 subsearchname = 0;
4853 } else {
4854 ++subsearchname;
4855 if (subsearchname[0]==0) {
4856 subsearchname = 0;
4857 }
4858 }
4859 }
4860
4861 TString leafname;
4862 TString leaftitle;
4863 TString longname;
4864 TString longtitle;
4865
4866 const bool searchnameHasDot = strchr(searchname, '.') != nullptr;
4867
4868 // For leaves we allow for one level up to be prefixed to the name.
4869 TIter next(GetListOfLeaves());
4870 TLeaf* leaf = 0;
4871 while ((leaf = (TLeaf*) next())) {
4872 leafname = leaf->GetName();
4873 Ssiz_t dim = leafname.First('[');
4874 if (dim >= 0) leafname.Remove(dim);
4875
4876 if (leafname == searchname) {
4877 return leaf;
4878 }
4879 if (subsearchname && leafname == subsearchname) {
4880 return leaf;
4881 }
4882 // The TLeafElement contains the branch name
4883 // in its name, let's use the title.
4884 leaftitle = leaf->GetTitle();
4885 dim = leaftitle.First('[');
4886 if (dim >= 0) leaftitle.Remove(dim);
4887
4888 if (leaftitle == searchname) {
4889 return leaf;
4890 }
4891 if (subsearchname && leaftitle == subsearchname) {
4892 return leaf;
4893 }
4894 if (!searchnameHasDot)
4895 continue;
4896 TBranch* branch = leaf->GetBranch();
4897 if (branch) {
4898 longname.Form("%s.%s",branch->GetName(),leafname.Data());
4899 dim = longname.First('[');
4900 if (dim>=0) longname.Remove(dim);
4901 if (longname == searchname) {
4902 return leaf;
4903 }
4904 if (subsearchname && longname == subsearchname) {
4905 return leaf;
4906 }
4907 longtitle.Form("%s.%s",branch->GetName(),leaftitle.Data());
4908 dim = longtitle.First('[');
4909 if (dim>=0) longtitle.Remove(dim);
4910 if (longtitle == searchname) {
4911 return leaf;
4912 }
4913 if (subsearchname && longtitle == subsearchname) {
4914 return leaf;
4915 }
4916 // The following is for the case where the branch is only
4917 // a sub-branch. Since we do not see it through
4918 // TTree::GetListOfBranches, we need to see it indirectly.
4919 // This is the less sturdy part of this search ... it may
4920 // need refining ...
4921 if (strstr(searchname, ".") && !strcmp(searchname, branch->GetName())) {
4922 return leaf;
4923 }
4924 if (subsearchname && strstr(subsearchname, ".") && !strcmp(subsearchname, branch->GetName())) {
4925 return leaf;
4926 }
4927 }
4928 }
4929 // Search in list of friends.
4930 if (!fFriends) {
4931 return 0;
4932 }
4933 TFriendLock lock(this, kFindLeaf);
4934 TIter nextf(fFriends);
4935 TFriendElement* fe = 0;
4936 while ((fe = (TFriendElement*) nextf())) {
4937 TTree* t = fe->GetTree();
4938 if (!t) {
4939 continue;
4940 }
4941 // If the alias is present replace it with the real name.
4942 subsearchname = (char*) strstr(searchname, fe->GetName());
4943 if (subsearchname != searchname) {
4944 subsearchname = 0;
4945 }
4946 if (subsearchname) {
4947 subsearchname += strlen(fe->GetName());
4948 if (*subsearchname != '.') {
4949 subsearchname = 0;
4950 } else {
4951 ++subsearchname;
4952 }
4953 }
4954 if (subsearchname) {
4955 leafname.Form("%s.%s",t->GetName(),subsearchname);
4956 } else {
4957 leafname = searchname;
4958 }
4959 leaf = t->FindLeaf(leafname);
4960 if (leaf) {
4961 return leaf;
4962 }
4963 }
4964 return 0;
4965}
4966
4967////////////////////////////////////////////////////////////////////////////////
4968/// Fit a projected item(s) from a tree.
4969///
4970/// funcname is a TF1 function.
4971///
4972/// See TTree::Draw() for explanations of the other parameters.
4973///
4974/// By default the temporary histogram created is called htemp.
4975/// If varexp contains >>hnew , the new histogram created is called hnew
4976/// and it is kept in the current directory.
4977///
4978/// The function returns the number of selected entries.
4979///
4980/// Example:
4981/// ~~~ {.cpp}
4982/// tree.Fit(pol4,"sqrt(x)>>hsqrt","y>0")
4983/// ~~~
4984/// will fit sqrt(x) and save the histogram as "hsqrt" in the current
4985/// directory.
4986///
4987/// See also TTree::UnbinnedFit
4988///
4989/// ## Return status
4990///
4991/// The function returns the status of the histogram fit (see TH1::Fit)
4992/// If no entries were selected, the function returns -1;
4993/// (i.e. fitResult is null if the fit is OK)
4995Int_t TTree::Fit(const char* funcname, const char* varexp, const char* selection, Option_t* option, Option_t* goption, Long64_t nentries, Long64_t firstentry)
4996{
4997 GetPlayer();
4998 if (fPlayer) {
4999 return fPlayer->Fit(funcname, varexp, selection, option, goption, nentries, firstentry);
5000 }
5001 return -1;
5002}
5003
5004namespace {
5005struct BoolRAIIToggle {
5006 Bool_t &m_val;
5007
5008 BoolRAIIToggle(Bool_t &val) : m_val(val) { m_val = true; }
5009 ~BoolRAIIToggle() { m_val = false; }
5010};
5011}
5012
5013////////////////////////////////////////////////////////////////////////////////
5014/// Write to disk all the basket that have not yet been individually written and
5015/// create an event cluster boundary (by default).
5016///
5017/// If the caller wishes to flush the baskets but not create an event cluster,
5018/// then set create_cluster to false.
5019///
5020/// If ROOT has IMT-mode enabled, this will launch multiple TBB tasks in parallel
5021/// via TThreadExecutor to do this operation; one per basket compression. If the
5022/// caller utilizes TBB also, care must be taken to prevent deadlocks.
5023///
5024/// For example, let's say the caller holds mutex A and calls FlushBaskets; while
5025/// TBB is waiting for the ROOT compression tasks to complete, it may decide to
5026/// run another one of the user's tasks in this thread. If the second user task
5027/// tries to acquire A, then a deadlock will occur. The example call sequence
5028/// looks like this:
5029///
5030/// - User acquires mutex A
5031/// - User calls FlushBaskets.
5032/// - ROOT launches N tasks and calls wait.
5033/// - TBB schedules another user task, T2.
5034/// - T2 tries to acquire mutex A.
5035///
5036/// At this point, the thread will deadlock: the code may function with IMT-mode
5037/// disabled if the user assumed the legacy code never would run their own TBB
5038/// tasks.
5039///
5040/// SO: users of TBB who want to enable IMT-mode should carefully review their
5041/// locking patterns and make sure they hold no coarse-grained application
5042/// locks when they invoke ROOT.
5043///
5044/// Return the number of bytes written or -1 in case of write error.
5045Int_t TTree::FlushBaskets(Bool_t create_cluster) const
5046{
5047 Int_t retval = FlushBasketsImpl();
5048 if (retval == -1) return retval;
5049
5050 if (create_cluster) const_cast<TTree *>(this)->MarkEventCluster();
5051 return retval;
5052}
5053
5054////////////////////////////////////////////////////////////////////////////////
5055/// Internal implementation of the FlushBaskets algorithm.
5056/// Unlike the public interface, this does NOT create an explicit event cluster
5057/// boundary; it is up to the (internal) caller to determine whether that should
5058/// done.
5059///
5060/// Otherwise, the comments for FlushBaskets applies.
5063{
5064 if (!fDirectory) return 0;
5065 Int_t nbytes = 0;
5066 Int_t nerror = 0;
5067 TObjArray *lb = const_cast<TTree*>(this)->GetListOfBranches();
5068 Int_t nb = lb->GetEntriesFast();
5069
5070#ifdef R__USE_IMT
5071 const auto useIMT = ROOT::IsImplicitMTEnabled() && fIMTEnabled;
5072 if (useIMT) {
5073 // ROOT-9668: here we need to check if the size of fSortedBranches is different from the
5074 // size of the list of branches before triggering the initialisation of the fSortedBranches
5075 // container to cover two cases:
5076 // 1. This is the first time we flush. fSortedBranches is empty and we need to fill it.
5077 // 2. We flushed at least once already but a branch has been be added to the tree since then
5078 if (fSortedBranches.size() != unsigned(nb)) { const_cast<TTree*>(this)->InitializeBranchLists(false); }
5079
5080 BoolRAIIToggle sentry(fIMTFlush);
5081 fIMTZipBytes.store(0);
5082 fIMTTotBytes.store(0);
5083 std::atomic<Int_t> nerrpar(0);
5084 std::atomic<Int_t> nbpar(0);
5085 std::atomic<Int_t> pos(0);
5086
5087 auto mapFunction = [&]() {
5088 // The branch to process is obtained when the task starts to run.
5089 // This way, since branches are sorted, we make sure that branches
5090 // leading to big tasks are processed first. If we assigned the
5091 // branch at task creation time, the scheduler would not necessarily
5092 // respect our sorting.
5093 Int_t j = pos.fetch_add(1);
5094
5095 auto branch = fSortedBranches[j].second;
5096 if (R__unlikely(!branch)) { return; }
5097
5098 if (R__unlikely(gDebug > 0)) {
5099 std::stringstream ss;
5100 ss << std::this_thread::get_id();
5101 Info("FlushBaskets", "[IMT] Thread %s", ss.str().c_str());
5102 Info("FlushBaskets", "[IMT] Running task for branch #%d: %s", j, branch->GetName());
5103 }
5104
5105 Int_t nbtask = branch->FlushBaskets();
5106
5107 if (nbtask < 0) { nerrpar++; }
5108 else { nbpar += nbtask; }
5109 };
5110
5112 pool.Foreach(mapFunction, nb);
5113
5114 fIMTFlush = false;
5115 const_cast<TTree*>(this)->AddTotBytes(fIMTTotBytes);
5116 const_cast<TTree*>(this)->AddZipBytes(fIMTZipBytes);
5117
5118 return nerrpar ? -1 : nbpar.load();
5119 }
5120#endif
5121 for (Int_t j = 0; j < nb; j++) {
5122 TBranch* branch = (TBranch*) lb->UncheckedAt(j);
5123 if (branch) {
5124 Int_t nwrite = branch->FlushBaskets();
5125 if (nwrite<0) {
5126 ++nerror;
5127 } else {
5128 nbytes += nwrite;
5129 }
5130 }
5131 }
5132 if (nerror) {
5133 return -1;
5134 } else {
5135 return nbytes;
5136 }
5137}
5138
5139////////////////////////////////////////////////////////////////////////////////
5140/// Returns the expanded value of the alias. Search in the friends if any.
5142const char* TTree::GetAlias(const char* aliasName) const
5143{
5144 // We already have been visited while recursively looking
5145 // through the friends tree, let's return.
5147 return 0;
5148 }
5149 if (fAliases) {
5150 TObject* alias = fAliases->FindObject(aliasName);
5151 if (alias) {
5152 return alias->GetTitle();
5153 }
5154 }
5155 if (!fFriends) {
5156 return 0;
5157 }
5158 TFriendLock lock(const_cast<TTree*>(this), kGetAlias);
5159 TIter nextf(fFriends);
5160 TFriendElement* fe = 0;
5161 while ((fe = (TFriendElement*) nextf())) {
5162 TTree* t = fe->GetTree();
5163 if (t) {
5164 const char* alias = t->GetAlias(aliasName);
5165 if (alias) {
5166 return alias;
5167 }
5168 const char* subAliasName = strstr(aliasName, fe->GetName());
5169 if (subAliasName && (subAliasName[strlen(fe->GetName())] == '.')) {
5170 alias = t->GetAlias(aliasName + strlen(fe->GetName()) + 1);
5171 if (alias) {
5172 return alias;
5173 }
5174 }
5175 }
5176 }
5177 return 0;
5178}
5179
5180namespace {
5181/// Do a breadth first search through the implied hierarchy
5182/// of branches.
5183/// To avoid scanning through the list multiple time
5184/// we also remember the 'depth-first' match.
5185TBranch *R__GetBranch(const TObjArray &branches, const char *name)
5186{
5187 TBranch *result = nullptr;
5188 Int_t nb = branches.GetEntriesFast();
5189 for (Int_t i = 0; i < nb; i++) {
5190 TBranch* b = (TBranch*)branches.UncheckedAt(i);
5191 if (!b)
5192 continue;
5193 if (!strcmp(b->GetName(), name)) {
5194 return b;
5195 }
5196 if (!strcmp(b->GetFullName(), name)) {
5197 return b;
5198 }
5199 if (!result)
5200 result = R__GetBranch(*(b->GetListOfBranches()), name);
5201 }
5202 return result;
5203}
5204}
5205
5206////////////////////////////////////////////////////////////////////////////////
5207/// Return pointer to the branch with the given name in this tree or its friends.
5208/// The search is done breadth first.
5210TBranch* TTree::GetBranch(const char* name)
5211{
5212 if (name == 0) return 0;
5213
5214 // We already have been visited while recursively
5215 // looking through the friends tree, let's return.
5217 return 0;
5218 }
5219
5220 // Look for an exact match in the list of top level
5221 // branches.
5223 if (result)
5224 return result;
5225
5226 // Search using branches, breadth first.
5227 result = R__GetBranch(fBranches, name);
5228 if (result)
5229 return result;
5230
5231 // Search using leaves.
5232 TObjArray* leaves = GetListOfLeaves();
5233 Int_t nleaves = leaves->GetEntriesFast();
5234 for (Int_t i = 0; i < nleaves; i++) {
5235 TLeaf* leaf = (TLeaf*) leaves->UncheckedAt(i);
5236 TBranch* branch = leaf->GetBranch();
5237 if (!strcmp(branch->GetName(), name)) {
5238 return branch;
5239 }
5240 if (!strcmp(branch->GetFullName(), name)) {
5241 return branch;
5242 }
5243 }
5244
5245 if (!fFriends) {
5246 return 0;
5247 }
5248
5249 // Search in list of friends.
5250 TFriendLock lock(this, kGetBranch);
5251 TIter next(fFriends);
5252 TFriendElement* fe = 0;
5253 while ((fe = (TFriendElement*) next())) {
5254 TTree* t = fe->GetTree();
5255 if (t) {
5256 TBranch* branch = t->GetBranch(name);
5257 if (branch) {
5258 return branch;
5259 }
5260 }
5261 }
5262
5263 // Second pass in the list of friends when
5264 // the branch name is prefixed by the tree name.
5265 next.Reset();
5266 while ((fe = (TFriendElement*) next())) {
5267 TTree* t = fe->GetTree();
5268 if (!t) {
5269 continue;
5270 }
5271 char* subname = (char*) strstr(name, fe->GetName());
5272 if (subname != name) {
5273 continue;
5274 }
5275 Int_t l = strlen(fe->GetName());
5276 subname += l;
5277 if (*subname != '.') {
5278 continue;
5279 }
5280 subname++;
5281 TBranch* branch = t->GetBranch(subname);
5282 if (branch) {
5283 return branch;
5284 }
5285 }
5286 return 0;
5287}
5288
5289////////////////////////////////////////////////////////////////////////////////
5290/// Return status of branch with name branchname.
5291///
5292/// - 0 if branch is not activated
5293/// - 1 if branch is activated
5295Bool_t TTree::GetBranchStatus(const char* branchname) const
5296{
5297 TBranch* br = const_cast<TTree*>(this)->GetBranch(branchname);
5298 if (br) {
5299 return br->TestBit(kDoNotProcess) == 0;
5300 }
5301 return 0;
5302}
5303
5304////////////////////////////////////////////////////////////////////////////////
5305/// Static function returning the current branch style.
5306///
5307/// - style = 0 old Branch
5308/// - style = 1 new Bronch
5311{
5312 return fgBranchStyle;
5313}
5314
5315////////////////////////////////////////////////////////////////////////////////
5316/// Used for automatic sizing of the cache.
5317///
5318/// Estimates a suitable size for the tree cache based on AutoFlush.
5319/// A cache sizing factor is taken from the configuration. If this yields zero
5320/// and withDefault is true the historical algorithm for default size is used.
5322Long64_t TTree::GetCacheAutoSize(Bool_t withDefault /* = kFALSE */ ) const
5323{
5324 const char *stcs;
5325 Double_t cacheFactor = 0.0;
5326 if (!(stcs = gSystem->Getenv("ROOT_TTREECACHE_SIZE")) || !*stcs) {
5327 cacheFactor = gEnv->GetValue("TTreeCache.Size", 1.0);
5328 } else {
5329 cacheFactor = TString(stcs).Atof();
5330 }
5331
5332 if (cacheFactor < 0.0) {
5333 // ignore negative factors
5334 cacheFactor = 0.0;
5335 }
5336
5337 Long64_t cacheSize = 0;
5338
5339 if (fAutoFlush < 0) cacheSize = Long64_t(-cacheFactor*fAutoFlush);
5340 else if (fAutoFlush == 0) cacheSize = 0;
5341 else cacheSize = Long64_t(cacheFactor*1.5*fAutoFlush*GetZipBytes()/(fEntries+1));
5342
5343 if (cacheSize >= (INT_MAX / 4)) {
5344 cacheSize = INT_MAX / 4;
5345 }
5346
5347 if (cacheSize < 0) {
5348 cacheSize = 0;
5349 }
5350
5351 if (cacheSize == 0 && withDefault) {
5352 if (fAutoFlush < 0) cacheSize = -fAutoFlush;
5353 else if (fAutoFlush == 0) cacheSize = 0;
5354 else cacheSize = Long64_t(1.5*fAutoFlush*GetZipBytes()/(fEntries+1));
5355 }
5356
5357 return cacheSize;
5358}
5359
5360////////////////////////////////////////////////////////////////////////////////
5361/// Return an iterator over the cluster of baskets starting at firstentry.
5362///
5363/// This iterator is not yet supported for TChain object.
5364/// ~~~ {.cpp}
5365/// TTree::TClusterIterator clusterIter = tree->GetClusterIterator(entry);
5366/// Long64_t clusterStart;
5367/// while( (clusterStart = clusterIter()) < tree->GetEntries() ) {
5368/// printf("The cluster starts at %lld and ends at %lld (inclusive)\n",clusterStart,clusterIter.GetNextEntry()-1);
5369/// }
5370/// ~~~
5373{
5374 // create cache if wanted
5375 if (fCacheDoAutoInit)
5377
5378 return TClusterIterator(this,firstentry);
5379}
5380
5381////////////////////////////////////////////////////////////////////////////////
5382/// Return pointer to the current file.
5385{
5386 if (!fDirectory || fDirectory==gROOT) {
5387 return 0;
5388 }
5389 return fDirectory->GetFile();
5390}
5391
5392////////////////////////////////////////////////////////////////////////////////
5393/// Return the number of entries matching the selection.
5394/// Return -1 in case of errors.
5395///
5396/// If the selection uses any arrays or containers, we return the number
5397/// of entries where at least one element match the selection.
5398/// GetEntries is implemented using the selector class TSelectorEntries,
5399/// which can be used directly (see code in TTreePlayer::GetEntries) for
5400/// additional option.
5401/// If SetEventList was used on the TTree or TChain, only that subset
5402/// of entries will be considered.
5404Long64_t TTree::GetEntries(const char *selection)
5405{
5406 GetPlayer();
5407 if (fPlayer) {
5408 return fPlayer->GetEntries(selection);
5409 }
5410 return -1;
5411}
5412
5413////////////////////////////////////////////////////////////////////////////////
5414/// Return pointer to the 1st Leaf named name in any Branch of this Tree or
5415/// any branch in the list of friend trees.
5418{
5419 if (fEntries) return fEntries;
5420 if (!fFriends) return 0;
5422 if (!fr) return 0;
5423 TTree *t = fr->GetTree();
5424 if (t==0) return 0;
5425 return t->GetEntriesFriend();
5426}
5427
5428////////////////////////////////////////////////////////////////////////////////
5429/// Read all branches of entry and return total number of bytes read.
5430///
5431/// - `getall = 0` : get only active branches
5432/// - `getall = 1` : get all branches
5433///
5434/// The function returns the number of bytes read from the input buffer.
5435/// If entry does not exist the function returns 0.
5436/// If an I/O error occurs, the function returns -1.
5437///
5438/// If the Tree has friends, also read the friends entry.
5439///
5440/// To activate/deactivate one or more branches, use TBranch::SetBranchStatus
5441/// For example, if you have a Tree with several hundred branches, and you
5442/// are interested only by branches named "a" and "b", do
5443/// ~~~ {.cpp}
5444/// mytree.SetBranchStatus("*",0); //disable all branches
5445/// mytree.SetBranchStatus("a",1);
5446/// mytree.SetBranchStatus("b",1);
5447/// ~~~
5448/// when calling mytree.GetEntry(i); only branches "a" and "b" will be read.
5449///
5450/// __WARNING!!__
5451/// If your Tree has been created in split mode with a parent branch "parent.",
5452/// ~~~ {.cpp}
5453/// mytree.SetBranchStatus("parent",1);
5454/// ~~~
5455/// will not activate the sub-branches of "parent". You should do:
5456/// ~~~ {.cpp}
5457/// mytree.SetBranchStatus("parent*",1);
5458/// ~~~
5459/// Without the trailing dot in the branch creation you have no choice but to
5460/// call SetBranchStatus explicitly for each of the sub branches.
5461///
5462/// An alternative is to call directly
5463/// ~~~ {.cpp}
5464/// brancha.GetEntry(i)
5465/// branchb.GetEntry(i);
5466/// ~~~
5467/// ## IMPORTANT NOTE
5468///
5469/// By default, GetEntry reuses the space allocated by the previous object
5470/// for each branch. You can force the previous object to be automatically
5471/// deleted if you call mybranch.SetAutoDelete(kTRUE) (default is kFALSE).
5472///
5473/// Example:
5474///
5475/// Consider the example in $ROOTSYS/test/Event.h
5476/// The top level branch in the tree T is declared with:
5477/// ~~~ {.cpp}
5478/// Event *event = 0; //event must be null or point to a valid object
5479/// //it must be initialized
5480/// T.SetBranchAddress("event",&event);
5481/// ~~~
5482/// When reading the Tree, one can choose one of these 3 options:
5483///
5484/// ## OPTION 1
5485///
5486/// ~~~ {.cpp}
5487/// for (Long64_t i=0;i<nentries;i++) {
5488/// T.GetEntry(i);
5489/// // the object event has been filled at this point
5490/// }
5491/// ~~~
5492/// The default (recommended). At the first entry an object of the class
5493/// Event will be created and pointed by event. At the following entries,
5494/// event will be overwritten by the new data. All internal members that are
5495/// TObject* are automatically deleted. It is important that these members
5496/// be in a valid state when GetEntry is called. Pointers must be correctly
5497/// initialized. However these internal members will not be deleted if the
5498/// characters "->" are specified as the first characters in the comment
5499/// field of the data member declaration.
5500///
5501/// If "->" is specified, the pointer member is read via pointer->Streamer(buf).
5502/// In this case, it is assumed that the pointer is never null (case of
5503/// pointer TClonesArray *fTracks in the Event example). If "->" is not
5504/// specified, the pointer member is read via buf >> pointer. In this case
5505/// the pointer may be null. Note that the option with "->" is faster to
5506/// read or write and it also consumes less space in the file.
5507///
5508/// ## OPTION 2
5509///
5510/// The option AutoDelete is set
5511/// ~~~ {.cpp}
5512/// TBranch *branch = T.GetBranch("event");
5513/// branch->SetAddress(&event);
5514/// branch->SetAutoDelete(kTRUE);
5515/// for (Long64_t i=0;i<nentries;i++) {
5516/// T.GetEntry(i);
5517/// // the object event has been filled at this point
5518/// }
5519/// ~~~
5520/// In this case, at each iteration, the object event is deleted by GetEntry
5521/// and a new instance of Event is created and filled.
5522///
5523/// ## OPTION 3
5524///
5525/// ~~~ {.cpp}
5526/// Same as option 1, but you delete yourself the event.
5527///
5528/// for (Long64_t i=0;i<nentries;i++) {
5529/// delete event;
5530/// event = 0; // EXTREMELY IMPORTANT
5531/// T.GetEntry(i);
5532/// // the object event has been filled at this point
5533/// }
5534/// ~~~
5535/// It is strongly recommended to use the default option 1. It has the
5536/// additional advantage that functions like TTree::Draw (internally calling
5537/// TTree::GetEntry) will be functional even when the classes in the file are
5538/// not available.
5539///
5540/// Note: See the comments in TBranchElement::SetAddress() for the
5541/// object ownership policy of the underlying (user) data.
5543Int_t TTree::GetEntry(Long64_t entry, Int_t getall)
5544{
5545
5546 // We already have been visited while recursively looking
5547 // through the friends tree, let return
5548 if (kGetEntry & fFriendLockStatus) return 0;
5549
5550 if (entry < 0 || entry >= fEntries) return 0;
5551 Int_t i;
5552 Int_t nbytes = 0;
5553 fReadEntry = entry;
5554
5555 // create cache if wanted
5556 if (fCacheDoAutoInit)
5558
5559 Int_t nbranches = fBranches.GetEntriesUnsafe();
5560 Int_t nb=0;
5561
5562 auto seqprocessing = [&]() {
5563 TBranch *branch;
5564 for (i=0;i<nbranches;i++) {
5565 branch = (TBranch*)fBranches.UncheckedAt(i);
5566 nb = branch->GetEntry(entry, getall);
5567 if (nb < 0) break;
5568 nbytes += nb;
5569 }
5570 };
5571
5572#ifdef R__USE_IMT
5574 if (fSortedBranches.empty())
5576
5577 // Count branches are processed first and sequentially
5578 for (auto branch : fSeqBranches) {
5579 nb = branch->GetEntry(entry, getall);
5580 if (nb < 0) break;
5581 nbytes += nb;
5582 }
5583 if (nb < 0) return nb;
5584
5585 // Enable this IMT use case (activate its locks)
5587
5588 Int_t errnb = 0;
5589 std::atomic<Int_t> pos(0);
5590 std::atomic<Int_t> nbpar(0);
5591
5592 auto mapFunction = [&]() {
5593 // The branch to process is obtained when the task starts to run.
5594 // This way, since branches are sorted, we make sure that branches
5595 // leading to big tasks are processed first. If we assigned the
5596 // branch at task creation time, the scheduler would not necessarily
5597 // respect our sorting.
5598 Int_t j = pos.fetch_add(1);
5599
5600 Int_t nbtask = 0;
5601 auto branch = fSortedBranches[j].second;
5602
5603 if (gDebug > 0) {
5604 std::stringstream ss;
5605 ss << std::this_thread::get_id();
5606 Info("GetEntry", "[IMT] Thread %s", ss.str().c_str());
5607 Info("GetEntry", "[IMT] Running task for branch #%d: %s", j, branch->GetName());
5608 }
5609
5610 std::chrono::time_point<std::chrono::system_clock> start, end;
5611
5612 start = std::chrono::system_clock::now();
5613 nbtask = branch->GetEntry(entry, getall);
5614 end = std::chrono::system_clock::now();
5615
5616 Long64_t tasktime = (Long64_t)std::chrono::duration_cast<std::chrono::microseconds>(end - start).count();
5617 fSortedBranches[j].first += tasktime;
5618
5619 if (nbtask < 0) errnb = nbtask;
5620 else nbpar += nbtask;
5621 };
5622
5624 pool.Foreach(mapFunction, fSortedBranches.size());
5625
5626 if (errnb < 0) {
5627 nb = errnb;
5628 }
5629 else {
5630 // Save the number of bytes read by the tasks
5631 nbytes += nbpar;
5632
5633 // Re-sort branches if necessary
5637 }
5638 }
5639 }
5640 else {
5641 seqprocessing();
5642 }
5643#else
5644 seqprocessing();
5645#endif
5646 if (nb < 0) return nb;
5647
5648 // GetEntry in list of friends
5649 if (!fFriends) return nbytes;
5650 TFriendLock lock(this,kGetEntry);
5651 TIter nextf(fFriends);
5652 TFriendElement *fe;
5653 while ((fe = (TFriendElement*)nextf())) {
5654 TTree *t = fe->GetTree();
5655 if (t) {
5657 nb = t->GetEntry(t->GetReadEntry(),getall);
5658 } else {
5659 if ( t->LoadTreeFriend(entry,this) >= 0 ) {
5660 nb = t->GetEntry(t->GetReadEntry(),getall);
5661 } else nb = 0;
5662 }
5663 if (nb < 0) return nb;
5664 nbytes += nb;
5665 }
5666 }
5667 return nbytes;
5668}
5669
5670
5671////////////////////////////////////////////////////////////////////////////////
5672/// Divides the top-level branches into two vectors: (i) branches to be
5673/// processed sequentially and (ii) branches to be processed in parallel.
5674/// Even if IMT is on, some branches might need to be processed first and in a
5675/// sequential fashion: in the parallelization of GetEntry, those are the
5676/// branches that store the size of another branch for every entry
5677/// (e.g. the size of an array branch). If such branches were processed
5678/// in parallel with the rest, there could be two threads invoking
5679/// TBranch::GetEntry on one of them at the same time, since a branch that
5680/// depends on a size (or count) branch will also invoke GetEntry on the latter.
5681/// This method can be invoked several times during the event loop if the TTree
5682/// is being written, for example when adding new branches. In these cases, the
5683/// `checkLeafCount` parameter is false.
5684/// \param[in] checkLeafCount True if we need to check whether some branches are
5685/// count leaves.
5687void TTree::InitializeBranchLists(bool checkLeafCount)
5688{
5689 Int_t nbranches = fBranches.GetEntriesFast();
5690
5691 // The special branch fBranchRef needs to be processed sequentially:
5692 // we add it once only.
5693 if (fBranchRef && fBranchRef != fSeqBranches[0]) {
5694 fSeqBranches.push_back(fBranchRef);
5695 }
5696
5697 // The branches to be processed sequentially are those that are the leaf count of another branch
5698 if (checkLeafCount) {
5699 for (Int_t i = 0; i < nbranches; i++) {
5700 TBranch* branch = (TBranch*)fBranches.UncheckedAt(i);
5701 auto leafCount = ((TLeaf*)branch->GetListOfLeaves()->At(0))->GetLeafCount();
5702 if (leafCount) {
5703 auto countBranch = leafCount->GetBranch();
5704 if (std::find(fSeqBranches.begin(), fSeqBranches.end(), countBranch) == fSeqBranches.end()) {
5705 fSeqBranches.push_back(countBranch);
5706 }
5707 }
5708 }
5709 }
5710
5711 // Any branch that is not a leaf count can be safely processed in parallel when reading
5712 // We need to reset the vector to make sure we do not re-add several times the same branch.
5713 if (!checkLeafCount) {
5714 fSortedBranches.clear();
5715 }
5716 for (Int_t i = 0; i < nbranches; i++) {
5717 Long64_t bbytes = 0;
5718 TBranch* branch = (TBranch*)fBranches.UncheckedAt(i);
5719 if (std::find(fSeqBranches.begin(), fSeqBranches.end(), branch) == fSeqBranches.end()) {
5720 bbytes = branch->GetTotBytes("*");
5721 fSortedBranches.emplace_back(bbytes, branch);
5722 }
5723 }
5724
5725 // Initially sort parallel branches by size
5726 std::sort(fSortedBranches.begin(),
5727 fSortedBranches.end(),
5728 [](std::pair<Long64_t,TBranch*> a, std::pair<Long64_t,TBranch*> b) {
5729 return a.first > b.first;
5730 });
5731
5732 for (size_t i = 0; i < fSortedBranches.size(); i++) {
5733 fSortedBranches[i].first = 0LL;
5734 }
5735}
5736
5737////////////////////////////////////////////////////////////////////////////////
5738/// Sorts top-level branches by the last average task time recorded per branch.
5741{
5742 for (size_t i = 0; i < fSortedBranches.size(); i++) {
5744 }
5745
5746 std::sort(fSortedBranches.begin(),
5747 fSortedBranches.end(),
5748 [](std::pair<Long64_t,TBranch*> a, std::pair<Long64_t,TBranch*> b) {
5749 return a.first > b.first;
5750 });
5751
5752 for (size_t i = 0; i < fSortedBranches.size(); i++) {
5753 fSortedBranches[i].first = 0LL;
5754 }
5755}
5756
5757////////////////////////////////////////////////////////////////////////////////
5758///Returns the entry list assigned to this tree
5761{
5762 return fEntryList;
5763}
5764
5765////////////////////////////////////////////////////////////////////////////////
5766/// Return entry number corresponding to entry.
5767///
5768/// if no TEntryList set returns entry
5769/// else returns the entry number corresponding to the list index=entry
5772{
5773 if (!fEntryList) {
5774 return entry;
5775 }
5776
5777 return fEntryList->GetEntry(entry);
5778}
5779
5780////////////////////////////////////////////////////////////////////////////////
5781/// Return entry number corresponding to major and minor number.
5782/// Note that this function returns only the entry number, not the data
5783/// To read the data corresponding to an entry number, use TTree::GetEntryWithIndex
5784/// the BuildIndex function has created a table of Long64_t* of sorted values
5785/// corresponding to val = major<<31 + minor;
5786/// The function performs binary search in this sorted table.
5787/// If it finds a pair that matches val, it returns directly the
5788/// index in the table.
5789/// If an entry corresponding to major and minor is not found, the function
5790/// returns the index of the major,minor pair immediately lower than the
5791/// requested value, ie it will return -1 if the pair is lower than
5792/// the first entry in the index.
5793///
5794/// See also GetEntryNumberWithIndex
5797{
5798 if (!fTreeIndex) {
5799 return -1;
5800 }
5801 return fTreeIndex->GetEntryNumberWithBestIndex(major, minor);
5802}
5803
5804////////////////////////////////////////////////////////////////////////////////
5805/// Return entry number corresponding to major and minor number.
5806/// Note that this function returns only the entry number, not the data
5807/// To read the data corresponding to an entry number, use TTree::GetEntryWithIndex
5808/// the BuildIndex function has created a table of Long64_t* of sorted values
5809/// corresponding to val = major<<31 + minor;
5810/// The function performs binary search in this sorted table.
5811/// If it finds a pair that matches val, it returns directly the
5812/// index in the table, otherwise it returns -1.
5813///
5814/// See also GetEntryNumberWithBestIndex
5817{
5818 if (!fTreeIndex) {
5819 return -1;
5820 }
5821 return fTreeIndex->GetEntryNumberWithIndex(major, minor);
5822}
5823
5824////////////////////////////////////////////////////////////////////////////////
5825/// Read entry corresponding to major and minor number.
5826///
5827/// The function returns the total number of bytes read.
5828/// If the Tree has friend trees, the corresponding entry with
5829/// the index values (major,minor) is read. Note that the master Tree
5830/// and its friend may have different entry serial numbers corresponding
5831/// to (major,minor).
5834{
5835 // We already have been visited while recursively looking
5836 // through the friends tree, let's return.
5838 return 0;
5839 }
5840 Long64_t serial = GetEntryNumberWithIndex(major, minor);
5841 if (serial < 0) {
5842 return -1;
5843 }
5844 // create cache if wanted
5845 if (fCacheDoAutoInit)
5847
5848 Int_t i;
5849 Int_t nbytes = 0;
5850 fReadEntry = serial;
5851 TBranch *branch;
5852 Int_t nbranches = fBranches.GetEntriesFast();
5853 Int_t nb;
5854 for (i = 0; i < nbranches; ++i) {
5855 branch = (TBranch*)fBranches.UncheckedAt(i);
5856 nb = branch->GetEntry(serial);
5857 if (nb < 0) return nb;
5858 nbytes += nb;
5859 }
5860 // GetEntry in list of friends
5861 if (!fFriends) return nbytes;
5863 TIter nextf(fFriends);
5864 TFriendElement* fe = 0;
5865 while ((fe = (TFriendElement*) nextf())) {
5866 TTree *t = fe->GetTree();
5867 if (t) {
5868 serial = t->GetEntryNumberWithIndex(major,minor);
5869 if (serial <0) return -nbytes;
5870 nb = t->GetEntry(serial);
5871 if (nb < 0) return nb;
5872 nbytes += nb;
5873 }
5874 }
5875 return nbytes;
5876}
5877
5878////////////////////////////////////////////////////////////////////////////////
5879/// Return a pointer to the TTree friend whose name or alias is 'friendname.
5881TTree* TTree::GetFriend(const char *friendname) const
5882{
5883
5884 // We already have been visited while recursively
5885 // looking through the friends tree, let's return.
5887 return 0;
5888 }
5889 if (!fFriends) {
5890 return 0;
5891 }
5892 TFriendLock lock(const_cast<TTree*>(this), kGetFriend);
5893 TIter nextf(fFriends);
5894 TFriendElement* fe = 0;
5895 while ((fe = (TFriendElement*) nextf())) {
5896 if (strcmp(friendname,fe->GetName())==0
5897 || strcmp(friendname,fe->GetTreeName())==0) {
5898 return fe->GetTree();
5899 }
5900 }
5901 // After looking at the first level,
5902 // let's see if it is a friend of friends.
5903 nextf.Reset();
5904 fe = 0;
5905 while ((fe = (TFriendElement*) nextf())) {
5906 TTree *res = fe->GetTree()->GetFriend(friendname);
5907 if (res) {
5908 return res;
5909 }
5910 }
5911 return 0;
5912}
5913
5914////////////////////////////////////////////////////////////////////////////////
5915/// If the 'tree' is a friend, this method returns its alias name.
5916///
5917/// This alias is an alternate name for the tree.
5918///
5919/// It can be used in conjunction with a branch or leaf name in a TTreeFormula,
5920/// to specify in which particular tree the branch or leaf can be found if
5921/// the friend trees have branches or leaves with the same name as the master
5922/// tree.
5923///
5924/// It can also be used in conjunction with an alias created using
5925/// TTree::SetAlias in a TTreeFormula, e.g.:
5926/// ~~~ {.cpp}
5927/// maintree->Draw("treealias.fPx - treealias.myAlias");
5928/// ~~~
5929/// where fPx is a branch of the friend tree aliased as 'treealias' and 'myAlias'
5930/// was created using TTree::SetAlias on the friend tree.
5931///
5932/// However, note that 'treealias.myAlias' will be expanded literally,
5933/// without remembering that it comes from the aliased friend and thus
5934/// the branch name might not be disambiguated properly, which means
5935/// that you may not be able to take advantage of this feature.
5936///
5938const char* TTree::GetFriendAlias(TTree* tree) const
5939{
5940 if ((tree == this) || (tree == GetTree())) {
5941 return 0;
5942 }
5943
5944 // We already have been visited while recursively
5945 // looking through the friends tree, let's return.
5947 return 0;
5948 }
5949 if (!fFriends) {
5950 return 0;
5951 }
5952 TFriendLock lock(const_cast<TTree*>(this), kGetFriendAlias);
5953 TIter nextf(fFriends);
5954 TFriendElement* fe = 0;
5955 while ((fe = (TFriendElement*) nextf())) {
5956 TTree* t = fe->GetTree();
5957 if (t == tree) {
5958 return fe->GetName();
5959 }
5960 // Case of a chain:
5961 if (t && t->GetTree() == tree) {
5962 return fe->GetName();
5963 }
5964 }
5965 // After looking at the first level,
5966 // let's see if it is a friend of friends.
5967 nextf.Reset();
5968 fe = 0;
5969 while ((fe = (TFriendElement*) nextf())) {
5970 const char* res = fe->GetTree()->GetFriendAlias(tree);
5971 if (res) {
5972 return res;
5973 }
5974 }
5975 return 0;
5976}
5977
5978////////////////////////////////////////////////////////////////////////////////
5979/// Returns the current set of IO settings
5981{
5982 return fIOFeatures;
5983}
5984
5985////////////////////////////////////////////////////////////////////////////////
5986/// Creates a new iterator that will go through all the leaves on the tree itself and its friend.
5989{
5990 return new TTreeFriendLeafIter(this, dir);
5991}
5992
5993////////////////////////////////////////////////////////////////////////////////
5994/// Return pointer to the 1st Leaf named name in any Branch of this
5995/// Tree or any branch in the list of friend trees.
5996///
5997/// The leaf name can contain the name of a friend tree with the
5998/// syntax: friend_dir_and_tree.full_leaf_name
5999/// the friend_dir_and_tree can be of the form:
6000/// ~~~ {.cpp}
6001/// TDirectoryName/TreeName
6002/// ~~~
6004TLeaf* TTree::GetLeafImpl(const char* branchname, const char *leafname)
6005{
6006 TLeaf *leaf = 0;
6007 if (branchname) {
6008 TBranch *branch = FindBranch(branchname);
6009 if (branch) {
6010 leaf = branch->GetLeaf(leafname);
6011 if (leaf) {
6012 return leaf;
6013 }
6014 }
6015 }
6016 TIter nextl(GetListOfLeaves());
6017 while ((leaf = (TLeaf*)nextl())) {
6018 if (strcmp(leaf->GetFullName(), leafname) != 0 && strcmp(leaf->GetName(), leafname) != 0)
6019 continue; // leafname does not match GetName() nor GetFullName(), this is not the right leaf
6020 if (branchname) {
6021 // check the branchname is also a match
6022 TBranch *br = leaf->GetBranch();
6023 // if a quick comparison with the branch full name is a match, we are done
6024 if (!strcmp(br->GetFullName(), branchname))
6025 return leaf;
6026 UInt_t nbch = strlen(branchname);
6027 const char* brname = br->GetName();
6028 TBranch *mother = br->GetMother();
6029 if (strncmp(brname,branchname,nbch)) {
6030 if (mother != br) {
6031 const char *mothername = mother->GetName();
6032 UInt_t motherlen = strlen(mothername);
6033 if (nbch > motherlen && strncmp(mothername,branchname,motherlen)==0 && (mothername[motherlen-1]=='.' || branchname[motherlen]=='.')) {
6034 // 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.
6035 if (strncmp(brname,branchname+motherlen+1,nbch-motherlen-1)) {
6036 // No it does not
6037 continue;
6038 } // else we have match so we can proceed.
6039 } else {
6040 // no match
6041 continue;
6042 }
6043 } else {
6044 continue;
6045 }
6046 }
6047 // The start of the branch name is identical to the content
6048 // of 'aname' before the first '/'.
6049 // Let's make sure that it is not longer (we are trying
6050 // to avoid having jet2/value match the branch jet23
6051 if ((strlen(brname) > nbch) && (brname[nbch] != '.') && (brname[nbch] != '[')) {
6052 continue;
6053 }
6054 }
6055 return leaf;
6056 }
6057 if (!fFriends) return 0;
6058 TFriendLock lock(this,kGetLeaf);
6059 TIter next(fFriends);
6060 TFriendElement *fe;
6061 while ((fe = (TFriendElement*)next())) {
6062 TTree *t = fe->GetTree();
6063 if (t) {
6064 leaf = t->GetLeaf(branchname, leafname);
6065 if (leaf) return leaf;
6066 }
6067 }
6068
6069 //second pass in the list of friends when the leaf name
6070 //is prefixed by the tree name
6071 TString strippedArg;
6072 next.Reset();
6073 while ((fe = (TFriendElement*)next())) {
6074 TTree *t = fe->GetTree();
6075 if (t==0) continue;
6076 char *subname = (char*)strstr(leafname,fe->GetName());
6077 if (subname != leafname) continue;
6078 Int_t l = strlen(fe->GetName());
6079 subname += l;
6080 if (*subname != '.') continue;
6081 subname++;
6082 strippedArg += subname;
6083 leaf = t->GetLeaf(branchname,subname);
6084 if (leaf) return leaf;
6085 }
6086 return 0;
6087}
6088
6089////////////////////////////////////////////////////////////////////////////////
6090/// Return pointer to the 1st Leaf named name in any Branch of this
6091/// Tree or any branch in the list of friend trees.
6092///
6093/// The leaf name can contain the name of a friend tree with the
6094/// syntax: friend_dir_and_tree.full_leaf_name
6095/// the friend_dir_and_tree can be of the form:
6096///
6097/// TDirectoryName/TreeName
6099TLeaf* TTree::GetLeaf(const char* branchname, const char *leafname)
6100{
6101 if (leafname == 0) return 0;
6102
6103 // We already have been visited while recursively looking
6104 // through the friends tree, let return
6106 return 0;
6107 }
6108
6109 return GetLeafImpl(branchname,leafname);
6110}
6111
6112////////////////////////////////////////////////////////////////////////////////
6113/// Return pointer to first leaf named \param[name] in any branch of this
6114/// tree or its friend trees.
6115///
6116/// \param[name] may be in the form 'branch/leaf'
6117///
6119TLeaf* TTree::GetLeaf(const char *name)
6120{
6121 // Return nullptr if name is invalid or if we have
6122 // already been visited while searching friend trees
6123 if (!name || (kGetLeaf & fFriendLockStatus))
6124 return nullptr;
6125
6126 std::string path(name);
6127 const auto sep = path.find_last_of("/");
6128 if (sep != std::string::npos)
6129 return GetLeafImpl(path.substr(0, sep).c_str(), name+sep+1);
6130
6131 return GetLeafImpl(nullptr, name);
6132}
6133
6134////////////////////////////////////////////////////////////////////////////////
6135/// Return maximum of column with name columname.
6136/// if the Tree has an associated TEventList or TEntryList, the maximum
6137/// is computed for the entries in this list.
6139Double_t TTree::GetMaximum(const char* columname)
6140{
6141 TLeaf* leaf = this->GetLeaf(columname);
6142 if (!leaf) {
6143 return 0;
6144 }
6145
6146 // create cache if wanted
6147 if (fCacheDoAutoInit)
6149
6150 TBranch* branch = leaf->GetBranch();
6151 Double_t cmax = -DBL_MAX;
6152 for (Long64_t i = 0; i < fEntries; ++i) {
6153 Long64_t entryNumber = this->GetEntryNumber(i);
6154 if (entryNumber < 0) break;
6155 branch->GetEntry(entryNumber);
6156 for (Int_t j = 0; j < leaf->GetLen(); ++j) {
6157 Double_t val = leaf->GetValue(j);
6158 if (val > cmax) {
6159 cmax = val;
6160 }
6161 }
6162 }
6163 return cmax;
6164}
6165
6166////////////////////////////////////////////////////////////////////////////////
6167/// Static function which returns the tree file size limit in bytes.
6170{
6171 return fgMaxTreeSize;
6172}
6173
6174////////////////////////////////////////////////////////////////////////////////
6175/// Return minimum of column with name columname.
6176/// if the Tree has an associated TEventList or TEntryList, the minimum
6177/// is computed for the entries in this list.
6179Double_t TTree::GetMinimum(const char* columname)
6180{
6181 TLeaf* leaf = this->GetLeaf(columname);
6182 if (!leaf) {
6183 return 0;
6184 }
6185
6186 // create cache if wanted
6187 if (fCacheDoAutoInit)
6189
6190 TBranch* branch = leaf->GetBranch();
6191 Double_t cmin = DBL_MAX;
6192 for (Long64_t i = 0; i < fEntries; ++i) {
6193 Long64_t entryNumber = this->GetEntryNumber(i);
6194 if (entryNumber < 0) break;
6195 branch->GetEntry(entryNumber);
6196 for (Int_t j = 0;j < leaf->GetLen(); ++j) {
6197 Double_t val = leaf->GetValue(j);
6198 if (val < cmin) {
6199 cmin = val;
6200 }
6201 }
6202 }
6203 return cmin;
6204}
6205
6206////////////////////////////////////////////////////////////////////////////////
6207/// Load the TTreePlayer (if not already done).
6210{
6211 if (fPlayer) {
6212 return fPlayer;
6213 }
6215 return fPlayer;
6216}
6217
6218////////////////////////////////////////////////////////////////////////////////
6219/// Find and return the TTreeCache registered with the file and which may
6220/// contain branches for us.
6223{
6224 TTreeCache *pe = dynamic_cast<TTreeCache*>(file->GetCacheRead(GetTree()));
6225 if (pe && pe->GetTree() != GetTree())
6226 pe = nullptr;
6227 return pe;
6228}
6229
6230////////////////////////////////////////////////////////////////////////////////
6231/// Find and return the TTreeCache registered with the file and which may
6232/// contain branches for us. If create is true and there is no cache
6233/// a new cache is created with default size.
6236{
6238 if (create && !pe) {
6239 if (fCacheDoAutoInit)
6241 pe = dynamic_cast<TTreeCache*>(file->GetCacheRead(GetTree()));
6242 if (pe && pe->GetTree() != GetTree()) pe = 0;
6243 }
6244 return pe;
6245}
6246
6247////////////////////////////////////////////////////////////////////////////////
6248/// Return a pointer to the list containing user objects associated to this tree.
6249///
6250/// The list is automatically created if it does not exist.
6251///
6252/// WARNING: By default the TTree destructor will delete all objects added
6253/// to this list. If you do not want these objects to be deleted,
6254/// call:
6255///
6256/// mytree->GetUserInfo()->Clear();
6257///
6258/// before deleting the tree.
6261{
6262 if (!fUserInfo) {
6263 fUserInfo = new TList();
6264 fUserInfo->SetName("UserInfo");
6265 }
6266 return fUserInfo;
6267}
6268
6269////////////////////////////////////////////////////////////////////////////////
6270/// Appends the cluster range information stored in 'fromtree' to this tree,
6271/// including the value of fAutoFlush.
6272///
6273/// This is used when doing a fast cloning (by TTreeCloner).
6274/// See also fAutoFlush and fAutoSave if needed.
6276void TTree::ImportClusterRanges(TTree *fromtree)
6277{
6278 Long64_t autoflush = fromtree->GetAutoFlush();
6279 if (fromtree->fNClusterRange == 0 && fromtree->fAutoFlush == fAutoFlush) {
6280 // nothing to do
6281 } else if (fNClusterRange || fromtree->fNClusterRange) {
6282 Int_t newsize = fNClusterRange + 1 + fromtree->fNClusterRange;
6283 if (newsize > fMaxClusterRange) {
6284 if (fMaxClusterRange) {
6286 newsize*sizeof(Long64_t),fMaxClusterRange*sizeof(Long64_t));
6288 newsize*sizeof(Long64_t),fMaxClusterRange*sizeof(Long64_t));
6289 fMaxClusterRange = newsize;
6290 } else {
6291 fMaxClusterRange = newsize;
6294 }
6295 }
6296 if (fEntries) {
6300 }
6301 for (Int_t i = 0 ; i < fromtree->fNClusterRange; ++i) {
6305 }
6306 fAutoFlush = autoflush;
6307 } else {
6308 SetAutoFlush( autoflush );
6309 }
6310 Long64_t autosave = GetAutoSave();
6311 if (autoflush > 0 && autosave > 0) {
6312 SetAutoSave( autoflush*(autosave/autoflush) );
6313 }
6314}
6315
6316////////////////////////////////////////////////////////////////////////////////
6317/// Keep a maximum of fMaxEntries in memory.
6320{
6322 Long64_t maxEntries = fMaxEntries - (fMaxEntries / 10);
6323 for (Int_t i = 0; i < nb; ++i) {
6324 TBranch* branch = (TBranch*) fBranches.UncheckedAt(i);
6325 branch->KeepCircular(maxEntries);
6326 }
6327 if (fNClusterRange) {
6328 Long64_t entriesOffset = fEntries - maxEntries;
6329 Int_t oldsize = fNClusterRange;
6330 for(Int_t i = 0, j = 0; j < oldsize; ++j) {
6331 if (fClusterRangeEnd[j] > entriesOffset) {
6332 fClusterRangeEnd[i] = fClusterRangeEnd[j] - entriesOffset;
6333 ++i;
6334 } else {
6336 }
6337 }
6338 }
6339 fEntries = maxEntries;
6340 fReadEntry = -1;
6341}
6342
6343////////////////////////////////////////////////////////////////////////////////
6344/// Read in memory all baskets from all branches up to the limit of maxmemory bytes.
6345///
6346/// If maxmemory is non null and positive SetMaxVirtualSize is called
6347/// with this value. Default for maxmemory is 2000000000 (2 Gigabytes).
6348/// The function returns the total number of baskets read into memory
6349/// if negative an error occurred while loading the branches.
6350/// This method may be called to force branch baskets in memory
6351/// when random access to branch entries is required.
6352/// If random access to only a few branches is required, you should
6353/// call directly TBranch::LoadBaskets.
6356{
6357 if (maxmemory > 0) SetMaxVirtualSize(maxmemory);
6358
6359 TIter next(GetListOfLeaves());
6360 TLeaf *leaf;
6361 Int_t nimported = 0;
6362 while ((leaf=(TLeaf*)next())) {
6363 nimported += leaf->GetBranch()->LoadBaskets();//break;
6364 }
6365 return nimported;
6366}
6367
6368////////////////////////////////////////////////////////////////////////////////
6369/// Set current entry.
6370///
6371/// Returns -2 if entry does not exist (just as TChain::LoadTree()).
6372/// Returns -6 if an error occours in the notification callback (just as TChain::LoadTree()).
6373///
6374/// Note: This function is overloaded in TChain.
6375///
6378{
6379 // We already have been visited while recursively looking
6380 // through the friends tree, let return
6382 // We need to return a negative value to avoid a circular list of friend
6383 // to think that there is always an entry somewhere in the list.
6384 return -1;
6385 }
6386
6387 // create cache if wanted
6388 if (fCacheDoAutoInit && entry >=0)
6390
6391 if (fNotify) {
6392 if (fReadEntry < 0) {
6393 fNotify->Notify();
6394 }
6395 }
6396 fReadEntry = entry;
6397
6398 Bool_t friendHasEntry = kFALSE;
6399 if (fFriends) {
6400 // Set current entry in friends as well.
6401 //
6402 // An alternative would move this code to each of the
6403 // functions calling LoadTree (and to overload a few more).
6404 Bool_t needUpdate = kFALSE;
6405 {
6406 // This scope is need to insure the lock is released at the right time
6407 TIter nextf(fFriends);
6408 TFriendLock lock(this, kLoadTree);
6409 TFriendElement* fe = 0;
6410 while ((fe = (TFriendElement*) nextf())) {
6412 // This friend element was added by the chain that owns this
6413 // tree, the chain will deal with loading the correct entry.
6414 continue;
6415 }
6416 TTree* friendTree = fe->GetTree();
6417 if (friendTree) {
6418 if (friendTree->LoadTreeFriend(entry, this) >= 0) {
6419 friendHasEntry = kTRUE;
6420 }
6421 }
6422 if (fe->IsUpdated()) {
6423 needUpdate = kTRUE;
6424 fe->ResetUpdated();
6425 }
6426 } // for each friend
6427 }
6428 if (needUpdate) {
6429 //update list of leaves in all TTreeFormula of the TTreePlayer (if any)
6430 if (fPlayer) {
6432 }
6433 //Notify user if requested
6434 if (fNotify) {
6435 if(!fNotify->Notify()) return -6;
6436 }
6437 }
6438 }
6439
6440 if ((fReadEntry >= fEntries) && !friendHasEntry) {
6441 fReadEntry = -1;
6442 return -2;
6443 }
6444 return fReadEntry;
6445}
6446
6447////////////////////////////////////////////////////////////////////////////////
6448/// Load entry on behalf of our master tree, we may use an index.
6449///
6450/// Called by LoadTree() when the masterTree looks for the entry
6451/// number in a friend tree (us) corresponding to the passed entry
6452/// number in the masterTree.
6453///
6454/// If we have no index, our entry number and the masterTree entry
6455/// number are the same.
6456///
6457/// If we *do* have an index, we must find the (major, minor) value pair
6458/// in masterTree to locate our corresponding entry.
6459///
6461Long64_t TTree::LoadTreeFriend(Long64_t entry, TTree* masterTree)
6462{
6463 if (!fTreeIndex) {
6464 return LoadTree(entry);
6465 }
6466 return LoadTree(fTreeIndex->GetEntryNumberFriend(masterTree));
6467}
6468
6469////////////////////////////////////////////////////////////////////////////////
6470/// Generate a skeleton analysis class for this tree.
6471///
6472/// The following files are produced: classname.h and classname.C.
6473/// If classname is 0, classname will be called "nameoftree".
6474///
6475/// The generated code in classname.h includes the following:
6476///
6477/// - Identification of the original tree and the input file name.
6478/// - Definition of an analysis class (data members and member functions).
6479/// - The following member functions:
6480/// - constructor (by default opening the tree file),
6481/// - GetEntry(Long64_t entry),
6482/// - Init(TTree* tree) to initialize a new TTree,
6483/// - Show(Long64_t entry) to read and dump entry.
6484///
6485/// The generated code in classname.C includes only the main
6486/// analysis function Loop.
6487///
6488/// To use this function:
6489///
6490/// - Open your tree file (eg: TFile f("myfile.root");)
6491/// - T->MakeClass("MyClass");
6492///
6493/// where T is the name of the TTree in file myfile.root,
6494/// and MyClass.h, MyClass.C the name of the files created by this function.
6495/// In a ROOT session, you can do:
6496/// ~~~ {.cpp}
6497/// root > .L MyClass.C
6498/// root > MyClass* t = new MyClass;
6499/// root > t->GetEntry(12); // Fill data members of t with entry number 12.
6500/// root > t->Show(); // Show values of entry 12.
6501/// root > t->Show(16); // Read and show values of entry 16.
6502/// root > t->Loop(); // Loop on all entries.
6503/// ~~~
6504/// NOTE: Do not use the code generated for a single TTree which is part
6505/// of a TChain to process that entire TChain. The maximum dimensions
6506/// calculated for arrays on the basis of a single TTree from the TChain
6507/// might be (will be!) too small when processing all of the TTrees in
6508/// the TChain. You must use myChain.MakeClass() to generate the code,
6509/// not myTree.MakeClass(...).
6511Int_t TTree::MakeClass(const char* classname, Option_t* option)
6512{
6513 GetPlayer();
6514 if (!fPlayer) {
6515 return 0;
6516 }
6517 return fPlayer->MakeClass(classname, option);
6518}
6519
6520////////////////////////////////////////////////////////////////////////////////
6521/// Generate a skeleton function for this tree.
6522///
6523/// The function code is written on filename.
6524/// If filename is 0, filename will be called nameoftree.C
6525///
6526/// The generated code includes the following:
6527/// - Identification of the original Tree and Input file name,
6528/// - Opening the Tree file,
6529/// - Declaration of Tree variables,
6530/// - Setting of branches addresses,
6531/// - A skeleton for the entry loop.
6532///
6533/// To use this function:
6534///
6535/// - Open your Tree file (eg: TFile f("myfile.root");)
6536/// - T->MakeCode("MyAnalysis.C");
6537///
6538/// where T is the name of the TTree in file myfile.root
6539/// and MyAnalysis.C the name of the file created by this function.
6540///
6541/// NOTE: Since the implementation of this function, a new and better
6542/// function TTree::MakeClass() has been developed.
6544Int_t TTree::MakeCode(const char* filename)
6545{
6546 Warning("MakeCode", "MakeCode is obsolete. Use MakeClass or MakeSelector instead");
6547
6548 GetPlayer();
6549 if (!fPlayer) return 0;
6550 return fPlayer->MakeCode(filename);
6551}
6552
6553////////////////////////////////////////////////////////////////////////////////
6554/// Generate a skeleton analysis class for this Tree using TBranchProxy.
6555///
6556/// TBranchProxy is the base of a class hierarchy implementing an
6557/// indirect access to the content of the branches of a TTree.
6558///
6559/// "proxyClassname" is expected to be of the form:
6560/// ~~~ {.cpp}
6561/// [path/]fileprefix
6562/// ~~~
6563/// The skeleton will then be generated in the file:
6564/// ~~~ {.cpp}
6565/// fileprefix.h
6566/// ~~~
6567/// located in the current directory or in 'path/' if it is specified.
6568/// The class generated will be named 'fileprefix'
6569///
6570/// "macrofilename" and optionally "cutfilename" are expected to point
6571/// to source files which will be included by the generated skeleton.
6572/// Method of the same name as the file(minus the extension and path)
6573/// will be called by the generated skeleton's Process method as follow:
6574/// ~~~ {.cpp}
6575/// [if (cutfilename())] htemp->Fill(macrofilename());
6576/// ~~~
6577/// "option" can be used select some of the optional features during
6578/// the code generation. The possible options are:
6579///
6580/// - nohist : indicates that the generated ProcessFill should not fill the histogram.
6581///
6582/// 'maxUnrolling' controls how deep in the class hierarchy does the
6583/// system 'unroll' classes that are not split. Unrolling a class
6584/// allows direct access to its data members (this emulates the behavior
6585/// of TTreeFormula).
6586///
6587/// The main features of this skeleton are:
6588///
6589/// * on-demand loading of branches
6590/// * ability to use the 'branchname' as if it was a data member
6591/// * protection against array out-of-bounds errors
6592/// * ability to use the branch data as an object (when the user code is available)
6593///
6594/// For example with Event.root, if
6595/// ~~~ {.cpp}
6596/// Double_t somePx = fTracks.fPx[2];
6597/// ~~~
6598/// is executed by one of the method of the skeleton,
6599/// somePx will updated with the current value of fPx of the 3rd track.
6600///
6601/// Both macrofilename and the optional cutfilename are expected to be
6602/// the name of source files which contain at least a free standing
6603/// function with the signature:
6604/// ~~~ {.cpp}
6605/// x_t macrofilename(); // i.e function with the same name as the file
6606/// ~~~
6607/// and
6608/// ~~~ {.cpp}
6609/// y_t cutfilename(); // i.e function with the same name as the file
6610/// ~~~
6611/// x_t and y_t needs to be types that can convert respectively to a double
6612/// and a bool (because the skeleton uses:
6613///
6614/// if (cutfilename()) htemp->Fill(macrofilename());
6615///
6616/// These two functions are run in a context such that the branch names are
6617/// available as local variables of the correct (read-only) type.
6618///
6619/// Note that if you use the same 'variable' twice, it is more efficient
6620/// to 'cache' the value. For example:
6621/// ~~~ {.cpp}
6622/// Int_t n = fEventNumber; // Read fEventNumber
6623/// if (n<10 || n>10) { ... }
6624/// ~~~
6625/// is more efficient than
6626/// ~~~ {.cpp}
6627/// if (fEventNumber<10 || fEventNumber>10)
6628/// ~~~
6629/// Also, optionally, the generated selector will also call methods named
6630/// macrofilename_methodname in each of 6 main selector methods if the method
6631/// macrofilename_methodname exist (Where macrofilename is stripped of its
6632/// extension).
6633///
6634/// Concretely, with the script named h1analysisProxy.C,
6635///
6636/// - The method calls the method (if it exist)
6637/// - Begin -> void h1analysisProxy_Begin(TTree*);
6638/// - SlaveBegin -> void h1analysisProxy_SlaveBegin(TTree*);
6639/// - Notify -> Bool_t h1analysisProxy_Notify();
6640/// - Process -> Bool_t h1analysisProxy_Process(Long64_t);
6641/// - SlaveTerminate -> void h1analysisProxy_SlaveTerminate();
6642/// - Terminate -> void h1analysisProxy_Terminate();
6643///
6644/// If a file name macrofilename.h (or .hh, .hpp, .hxx, .hPP, .hXX) exist
6645/// it is included before the declaration of the proxy class. This can
6646/// be used in particular to insure that the include files needed by
6647/// the macro file are properly loaded.
6648///
6649/// The default histogram is accessible via the variable named 'htemp'.
6650///
6651/// If the library of the classes describing the data in the branch is
6652/// loaded, the skeleton will add the needed `include` statements and
6653/// give the ability to access the object stored in the branches.
6654///
6655/// To draw px using the file hsimple.root (generated by the
6656/// hsimple.C tutorial), we need a file named hsimple.cxx:
6657/// ~~~ {.cpp}
6658/// double hsimple() {
6659/// return px;
6660/// }
6661/// ~~~
6662/// MakeProxy can then be used indirectly via the TTree::Draw interface
6663/// as follow:
6664/// ~~~ {.cpp}
6665/// new TFile("hsimple.root")
6666/// ntuple->Draw("hsimple.cxx");
6667/// ~~~
6668/// A more complete example is available in the tutorials directory:
6669/// h1analysisProxy.cxx , h1analysProxy.h and h1analysisProxyCut.C
6670/// which reimplement the selector found in h1analysis.C
6672Int_t TTree::MakeProxy(const char* proxyClassname, const char* macrofilename, const char* cutfilename, const char* option, Int_t maxUnrolling)
6673{
6674 GetPlayer();
6675 if (!fPlayer) return 0;
6676 return fPlayer->MakeProxy(proxyClassname,macrofilename,cutfilename,option,maxUnrolling);
6677}
6678
6679////////////////////////////////////////////////////////////////////////////////
6680/// Generate skeleton selector class for this tree.
6681///
6682/// The following files are produced: selector.h and selector.C.
6683/// If selector is 0, the selector will be called "nameoftree".
6684/// The option can be used to specify the branches that will have a data member.
6685/// - If option is "=legacy", a pre-ROOT6 selector will be generated (data
6686/// members and branch pointers instead of TTreeReaders).
6687/// - If option is empty, readers will be generated for each leaf.
6688/// - If option is "@", readers will be generated for the topmost branches.
6689/// - Individual branches can also be picked by their name:
6690/// - "X" generates readers for leaves of X.
6691/// - "@X" generates a reader for X as a whole.
6692/// - "@X;Y" generates a reader for X as a whole and also readers for the
6693/// leaves of Y.
6694/// - For further examples see the figure below.
6695///
6696/// \image html ttree_makeselector_option_examples.png
6697///
6698/// The generated code in selector.h includes the following:
6699/// - Identification of the original Tree and Input file name
6700/// - Definition of selector class (data and functions)
6701/// - The following class functions:
6702/// - constructor and destructor
6703/// - void Begin(TTree *tree)
6704/// - void SlaveBegin(TTree *tree)
6705/// - void Init(TTree *tree)
6706/// - Bool_t Notify()
6707/// - Bool_t Process(Long64_t entry)
6708/// - void Terminate()
6709/// - void SlaveTerminate()
6710///
6711/// The class selector derives from TSelector.
6712/// The generated code in selector.C includes empty functions defined above.
6713///
6714/// To use this function:
6715///
6716/// - connect your Tree file (eg: `TFile f("myfile.root");`)
6717/// - `T->MakeSelector("myselect");`
6718///
6719/// where T is the name of the Tree in file myfile.root
6720/// and myselect.h, myselect.C the name of the files created by this function.
6721/// In a ROOT session, you can do:
6722/// ~~~ {.cpp}
6723/// root > T->Process("myselect.C")
6724/// ~~~
6726Int_t TTree::MakeSelector(const char* selector, Option_t* option)
6727{
6728 TString opt(option);
6729 if(opt.EqualTo("=legacy", TString::ECaseCompare::kIgnoreCase)) {
6730 return MakeClass(selector, "selector");
6731 } else {
6732 GetPlayer();
6733 if (!fPlayer) return 0;
6734 return fPlayer->MakeReader(selector, option);
6735 }
6736}
6737
6738////////////////////////////////////////////////////////////////////////////////
6739/// Check if adding nbytes to memory we are still below MaxVirtualsize.
6742{
6743 if ((fTotalBuffers + nbytes) < fMaxVirtualSize) {
6744 return kFALSE;
6745 }
6746 return kTRUE;
6747}
6748
6749////////////////////////////////////////////////////////////////////////////////
6750/// Static function merging the trees in the TList into a new tree.
6751///
6752/// Trees in the list can be memory or disk-resident trees.
6753/// The new tree is created in the current directory (memory if gROOT).
6755TTree* TTree::MergeTrees(TList* li, Option_t* options)
6756{
6757 if (!li) return 0;
6758 TIter next(li);
6759 TTree *newtree = 0;
6760 TObject *obj;
6761
6762 while ((obj=next())) {
6763 if (!obj->InheritsFrom(TTree::Class())) continue;
6764 TTree *tree = (TTree*)obj;
6765 Long64_t nentries = tree->GetEntries();
6766 if (nentries == 0) continue;
6767 if (!newtree) {
6768 newtree = (TTree*)tree->CloneTree(-1, options);
6769 if (!newtree) continue;
6770
6771 // Once the cloning is done, separate the trees,
6772 // to avoid as many side-effects as possible
6773 // The list of clones is guaranteed to exist since we
6774 // just cloned the tree.
6775 tree->GetListOfClones()->Remove(newtree);
6776 tree->ResetBranchAddresses();
6777 newtree->ResetBranchAddresses();
6778 continue;
6779 }
6780
6781 newtree->CopyEntries(tree, -1, options, kTRUE);
6782 }
6783 if (newtree && newtree->GetTreeIndex()) {
6784 newtree->GetTreeIndex()->Append(0,kFALSE); // Force the sorting
6785 }
6786 return newtree;
6787}
6788
6789////////////////////////////////////////////////////////////////////////////////
6790/// Merge the trees in the TList into this tree.
6791///
6792/// Returns the total number of entries in the merged tree.
6795{
6796 if (!li) return 0;
6797 Long64_t storeAutoSave = fAutoSave;
6798 // Disable the autosave as the TFileMerge keeps a list of key and deleting the underlying
6799 // key would invalidate its iteration (or require costly measure to not use the deleted keys).
6800 // Also since this is part of a merging operation, the output file is not as precious as in
6801 // the general case since the input file should still be around.
6802 fAutoSave = 0;
6803 TIter next(li);
6804 TTree *tree;
6805 while ((tree = (TTree*)next())) {
6806 if (tree==this) continue;
6807 if (!tree->InheritsFrom(TTree::Class())) {
6808 Error("Add","Attempt to add object of class: %s to a %s", tree->ClassName(), ClassName());
6809 fAutoSave = storeAutoSave;
6810 return -1;
6811 }
6812
6813 Long64_t nentries = tree->GetEntries();
6814 if (nentries == 0) continue;
6815
6816 CopyEntries(tree, -1, options, kTRUE);
6817 }
6818 fAutoSave = storeAutoSave;
6819 return GetEntries();
6820}
6821
6822////////////////////////////////////////////////////////////////////////////////
6823/// Merge the trees in the TList into this tree.
6824/// If info->fIsFirst is true, first we clone this TTree info the directory
6825/// info->fOutputDirectory and then overlay the new TTree information onto
6826/// this TTree object (so that this TTree object is now the appropriate to
6827/// use for further merging).
6828///
6829/// Returns the total number of entries in the merged tree.
6832{
6833 const char *options = info ? info->fOptions.Data() : "";
6834 if (info && info->fIsFirst && info->fOutputDirectory && info->fOutputDirectory->GetFile() != GetCurrentFile()) {
6835 if (GetCurrentFile() == nullptr) {
6836 // In memory TTree, all we need to do is ... write it.
6839 fDirectory->WriteTObject(this);
6840 } else if (info->fOptions.Contains("fast")) {
6842 } else {
6844 TIOFeatures saved_features = fIOFeatures;
6845 TTree *newtree = CloneTree(-1, options);
6846 if (info->fIOFeatures)
6847 fIOFeatures = *(info->fIOFeatures);
6848 else
6849 fIOFeatures = saved_features;
6850 if (newtree) {
6851 newtree->Write();
6852 delete newtree;
6853 }
6854 // Make sure things are really written out to disk before attempting any reading.
6855 info->fOutputDirectory->GetFile()->Flush();
6856 info->fOutputDirectory->ReadTObject(this,this->GetName());
6857 }
6858 }
6859 if (!li) return 0;
6860 Long64_t storeAutoSave = fAutoSave;
6861 // Disable the autosave as the TFileMerge keeps a list of key and deleting the underlying
6862 // key would invalidate its iteration (or require costly measure to not use the deleted keys).
6863 // Also since this is part of a merging operation, the output file is not as precious as in
6864 // the general case since the input file should still be around.
6865 fAutoSave = 0;
6866 TIter next(li);
6867 TTree *tree;
6868 while ((tree = (TTree*)next())) {
6869 if (tree==this) continue;
6870 if (!tree->InheritsFrom(TTree::Class())) {
6871 Error("Add","Attempt to add object of class: %s to a %s", tree->ClassName(), ClassName());
6872 fAutoSave = storeAutoSave;
6873 return -1;
6874 }
6875
6876 CopyEntries(tree, -1, options, kTRUE);
6877 }
6878 fAutoSave = storeAutoSave;
6879 return GetEntries();
6880}
6881
6882////////////////////////////////////////////////////////////////////////////////
6883/// Move a cache from a file to the current file in dir.
6884/// if src is null no operation is done, if dir is null or there is no
6885/// current file the cache is deleted.
6887void TTree::MoveReadCache(TFile *src, TDirectory *dir)
6888{
6889 if (!src) return;
6890 TFile *dst = (dir && dir != gROOT) ? dir->GetFile() : 0;
6891 if (src == dst) return;
6892
6893 TTreeCache *pf = GetReadCache(src);
6894 if (dst) {
6895 src->SetCacheRead(0,this);
6896 dst->SetCacheRead(pf, this);
6897 } else {
6898 if (pf) {
6899 pf->WaitFinishPrefetch();
6900 }
6901 src->SetCacheRead(0,this);
6902 delete pf;
6903 }
6904}
6905
6906////////////////////////////////////////////////////////////////////////////////
6907/// Copy the content to a new new file, update this TTree with the new
6908/// location information and attach this TTree to the new directory.
6909///
6910/// options: Indicates a basket sorting method, see TTreeCloner::TTreeCloner for
6911/// details
6912///
6913/// If new and old directory are in the same file, the data is untouched,
6914/// this "just" does a call to SetDirectory.
6915/// Equivalent to an "in place" cloning of the TTree.
6916Bool_t TTree::InPlaceClone(TDirectory *newdirectory, const char *options)
6917{
6918 if (!newdirectory) {
6920 SetDirectory(nullptr);
6921 return true;
6922 }
6923 if (newdirectory->GetFile() == GetCurrentFile()) {
6924 SetDirectory(newdirectory);
6925 return true;
6926 }
6927 TTreeCloner cloner(this, newdirectory, options);
6928 if (cloner.IsValid())
6929 return cloner.Exec();
6930 else
6931 return false;
6932}
6933
6934////////////////////////////////////////////////////////////////////////////////
6935/// Function called when loading a new class library.
6938{
6939 TIter next(GetListOfLeaves());
6940 TLeaf* leaf = 0;
6941 while ((leaf = (TLeaf*) next())) {
6942 leaf->Notify();
6943 leaf->GetBranch()->Notify();
6944 }
6945 return kTRUE;
6946}
6947
6948////////////////////////////////////////////////////////////////////////////////
6949/// This function may be called after having filled some entries in a Tree.
6950/// Using the information in the existing branch buffers, it will reassign
6951/// new branch buffer sizes to optimize time and memory.
6952///
6953/// The function computes the best values for branch buffer sizes such that
6954/// the total buffer sizes is less than maxMemory and nearby entries written
6955/// at the same time.
6956/// In case the branch compression factor for the data written so far is less
6957/// than compMin, the compression is disabled.
6958///
6959/// if option ="d" an analysis report is printed.
6961void TTree::OptimizeBaskets(ULong64_t maxMemory, Float_t minComp, Option_t *option)
6962{
6963 //Flush existing baskets if the file is writable
6964 if (this->GetDirectory()->IsWritable()) this->FlushBasketsImpl();
6965
6966 TString opt( option );
6967 opt.ToLower();
6968 Bool_t pDebug = opt.Contains("d");
6969 TObjArray *leaves = this->GetListOfLeaves();
6970 Int_t nleaves = leaves->GetEntries();
6971 Double_t treeSize = (Double_t)this->GetTotBytes();
6972
6973 if (nleaves == 0 || treeSize == 0) {
6974 // We're being called too early, we really have nothing to do ...
6975 return;
6976 }
6977 Double_t aveSize = treeSize/nleaves;
6978 UInt_t bmin = 512;
6979 UInt_t bmax = 256000;
6980 Double_t memFactor = 1;
6981 Int_t i, oldMemsize,newMemsize,oldBaskets,newBaskets;
6982 i = oldMemsize = newMemsize = oldBaskets = newBaskets = 0;
6983
6984 //we make two passes
6985 //one pass to compute the relative branch buffer sizes
6986 //a second pass to compute the absolute values
6987 for (Int_t pass =0;pass<2;pass++) {
6988 oldMemsize = 0; //to count size of baskets in memory with old buffer size
6989 newMemsize = 0; //to count size of baskets in memory with new buffer size
6990 oldBaskets = 0; //to count number of baskets with old buffer size
6991 newBaskets = 0; //to count number of baskets with new buffer size
6992 for (i=0;i<nleaves;i++) {
6993 TLeaf *leaf = (TLeaf*)leaves->At(i);
6994 TBranch *branch = leaf->GetBranch();
6995 Double_t totBytes = (Double_t)branch->GetTotBytes();
6996 Double_t idealFactor = totBytes/aveSize;
6997 UInt_t sizeOfOneEntry;
6998 if (branch->GetEntries() == 0) {
6999 // There is no data, so let's make a guess ...
7000 sizeOfOneEntry = aveSize;
7001 } else {
7002 sizeOfOneEntry = 1+(UInt_t)(totBytes / (Double_t)branch->GetEntries());
7003 }
7004 Int_t oldBsize = branch->GetBasketSize();
7005 oldMemsize += oldBsize;
7006 oldBaskets += 1+Int_t(totBytes/oldBsize);
7007 Int_t nb = branch->GetListOfBranches()->GetEntries();
7008 if (nb > 0) {
7009 newBaskets += 1+Int_t(totBytes/oldBsize);
7010 continue;
7011 }
7012 Double_t bsize = oldBsize*idealFactor*memFactor; //bsize can be very large !
7013 if (bsize < 0) bsize = bmax;
7014 if (bsize > bmax) bsize = bmax;
7015 UInt_t newBsize = UInt_t(bsize);
7016 if (pass) { // only on the second pass so that it doesn't interfere with scaling
7017 // If there is an entry offset, it will be stored in the same buffer as the object data; hence,
7018 // we must bump up the size of the branch to account for this extra footprint.
7019 // If fAutoFlush is not set yet, let's assume that it is 'in the process of being set' to
7020 // the value of GetEntries().
7021 Long64_t clusterSize = (fAutoFlush > 0) ? fAutoFlush : branch->GetEntries();
7022 if (branch->GetEntryOffsetLen()) {
7023 newBsize = newBsize + (clusterSize * sizeof(Int_t) * 2);
7024 }
7025 // We used ATLAS fully-split xAOD for testing, which is a rather unbalanced TTree, 10K branches,
7026 // with 8K having baskets smaller than 512 bytes. To achieve good I/O performance ATLAS uses auto-flush 100,
7027 // resulting in the smallest baskets being ~300-400 bytes, so this change increases their memory by about 8k*150B =~ 1MB,
7028 // at the same time it significantly reduces the number of total baskets because it ensures that all 100 entries can be
7029 // stored in a single basket (the old optimization tended to make baskets too small). In a toy example with fixed sized
7030 // structures we found a factor of 2 fewer baskets needed in the new scheme.
7031 // rounds up, increases basket size to ensure all entries fit into single basket as intended
7032 newBsize = newBsize - newBsize%512 + 512;
7033 }
7034 if (newBsize < sizeOfOneEntry) newBsize = sizeOfOneEntry;
7035 if (newBsize < bmin) newBsize = bmin;
7036 if (newBsize > 10000000) newBsize = bmax;
7037 if (pass) {
7038 if (pDebug) Info("OptimizeBaskets", "Changing buffer size from %6d to %6d bytes for %s\n",oldBsize,newBsize,branch->GetName());
7039 branch->SetBasketSize(newBsize);
7040 }
7041 newMemsize += newBsize;
7042 // For this number to be somewhat accurate when newBsize is 'low'
7043 // we do not include any space for meta data in the requested size (newBsize) even-though SetBasketSize will
7044 // not let it be lower than 100+TBranch::fEntryOffsetLen.
7045 newBaskets += 1+Int_t(totBytes/newBsize);
7046 if (pass == 0) continue;
7047 //Reset the compression level in case the compression factor is small
7048 Double_t comp = 1;
7049 if (branch->GetZipBytes() > 0) comp = totBytes/Double_t(branch->GetZipBytes());
7050 if (comp > 1 && comp < minComp) {
7051 if (pDebug) Info("OptimizeBaskets", "Disabling compression for branch : %s\n",branch->GetName());
7053 }
7054 }
7055 // coverity[divide_by_zero] newMemsize can not be zero as there is at least one leaf
7056 memFactor = Double_t(maxMemory)/Double_t(newMemsize);
7057 if (memFactor > 100) memFactor = 100;
7058 Double_t bmin_new = bmin*memFactor;
7059 Double_t bmax_new = bmax*memFactor;
7060 static const UInt_t hardmax = 1*1024*1024*1024; // Really, really never give more than 1Gb to a single buffer.
7061
7062 // Really, really never go lower than 8 bytes (we use this number
7063 // so that the calculation of the number of basket is consistent
7064 // but in fact SetBasketSize will not let the size go below
7065 // TBranch::fEntryOffsetLen + (100 + strlen(branch->GetName())
7066 // (The 2nd part being a slight over estimate of the key length.
7067 static const UInt_t hardmin = 8;
7068 bmin = (bmin_new > hardmax) ? hardmax : ( bmin_new < hardmin ? hardmin : (UInt_t)bmin_new );
7069 bmax = (bmax_new > hardmax) ? bmin : (UInt_t)bmax_new;
7070 }
7071 if (pDebug) {
7072 Info("OptimizeBaskets", "oldMemsize = %d, newMemsize = %d\n",oldMemsize, newMemsize);
7073 Info("OptimizeBaskets", "oldBaskets = %d, newBaskets = %d\n",oldBaskets, newBaskets);
7074 }
7075}
7076
7077////////////////////////////////////////////////////////////////////////////////
7078/// Interface to the Principal Components Analysis class.
7079///
7080/// Create an instance of TPrincipal
7081///
7082/// Fill it with the selected variables
7083///
7084/// - if option "n" is specified, the TPrincipal object is filled with
7085/// normalized variables.
7086/// - If option "p" is specified, compute the principal components
7087/// - If option "p" and "d" print results of analysis
7088/// - If option "p" and "h" generate standard histograms
7089/// - If option "p" and "c" generate code of conversion functions
7090/// - return a pointer to the TPrincipal object. It is the user responsibility
7091/// - to delete this object.
7092/// - The option default value is "np"
7093///
7094/// see TTree::Draw for explanation of the other parameters.
7095///
7096/// The created object is named "principal" and a reference to it
7097/// is added to the list of specials Root objects.
7098/// you can retrieve a pointer to the created object via:
7099/// ~~~ {.cpp}
7100/// TPrincipal *principal =
7101/// (TPrincipal*)gROOT->GetListOfSpecials()->FindObject("principal");
7102/// ~~~
7104TPrincipal* TTree::Principal(const char* varexp, const char* selection, Option_t* option, Long64_t nentries, Long64_t firstentry)
7105{
7106 GetPlayer();
7107 if (fPlayer) {
7108 return fPlayer->Principal(varexp, selection, option, nentries, firstentry);
7109 }
7110 return 0;
7111}
7112
7113////////////////////////////////////////////////////////////////////////////////
7114/// Print a summary of the tree contents.
7115///
7116/// - If option contains "all" friend trees are also printed.
7117/// - If option contains "toponly" only the top level branches are printed.
7118/// - If option contains "clusters" information about the cluster of baskets is printed.
7119///
7120/// Wildcarding can be used to print only a subset of the branches, e.g.,
7121/// `T.Print("Elec*")` will print all branches with name starting with "Elec".
7123void TTree::Print(Option_t* option) const
7124{
7125 // We already have been visited while recursively looking
7126 // through the friends tree, let's return.
7127 if (kPrint & fFriendLockStatus) {
7128 return;
7129 }
7130 Int_t s = 0;
7131 Int_t skey = 0;
7132 if (fDirectory) {
7133 TKey* key = fDirectory->GetKey(GetName());
7134 if (key) {
7135 skey = key->GetKeylen();
7136 s = key->GetNbytes();
7137 }
7138 }
7139 Long64_t total = skey;
7140 Long64_t zipBytes = GetZipBytes();
7141 if (zipBytes > 0) {
7142 total += GetTotBytes();
7143 }
7145 TTree::Class()->WriteBuffer(b, (TTree*) this);
7146 total += b.Length();
7147 Long64_t file = zipBytes + s;
7148 Float_t cx = 1;
7149 if (zipBytes) {
7150 cx = (GetTotBytes() + 0.00001) / zipBytes;
7151 }
7152 Printf("******************************************************************************");
7153 Printf("*Tree :%-10s: %-54s *", GetName(), GetTitle());
7154 Printf("*Entries : %8lld : Total = %15lld bytes File Size = %10lld *", fEntries, total, file);
7155 Printf("* : : Tree compression factor = %6.2f *", cx);
7156 Printf("******************************************************************************");
7157
7158 // Avoid many check of option validity
7159 if (option == nullptr)
7160 option = "";
7161
7162 if (strncmp(option,"clusters",strlen("clusters"))==0) {
7163 Printf("%-16s %-16s %-16s %8s %20s",
7164 "Cluster Range #", "Entry Start", "Last Entry", "Size", "Number of clusters");
7165 Int_t index= 0;
7166 Long64_t clusterRangeStart = 0;
7167 Long64_t totalClusters = 0;
7168 bool estimated = false;
7169 bool unknown = false;
7170 auto printer = [this, &totalClusters, &estimated, &unknown](Int_t ind, Long64_t start, Long64_t end, Long64_t recordedSize) {
7171 Long64_t nclusters = 0;
7172 if (recordedSize > 0) {
7173 nclusters = (1 + end - start) / recordedSize;
7174 Printf("%-16d %-16lld %-16lld %8lld %10lld",
7175 ind, start, end, recordedSize, nclusters);
7176 } else {
7177 // NOTE: const_cast ... DO NOT Merge for now
7178 TClusterIterator iter((TTree*)this, start);
7179 iter.Next();
7180 auto estimated_size = iter.GetNextEntry() - start;
7181 if (estimated_size > 0) {
7182 nclusters = (1 + end - start) / estimated_size;
7183 Printf("%-16d %-16lld %-16lld %8lld %10lld (estimated)",
7184 ind, start, end, recordedSize, nclusters);
7185 estimated = true;
7186 } else {
7187 Printf("%-16d %-16lld %-16lld %8lld (unknown)",
7188 ind, start, end, recordedSize);
7189 unknown = true;
7190 }
7191 }
7192 start = end + 1;
7193 totalClusters += nclusters;
7194 };
7195 if (fNClusterRange) {
7196 for( ; index < fNClusterRange; ++index) {
7197 printer(index, clusterRangeStart, fClusterRangeEnd[index], fClusterSize[index]);
7198 clusterRangeStart = fClusterRangeEnd[index] + 1;
7199 }
7200 }
7201 printer(index, clusterRangeStart, fEntries - 1, fAutoFlush);
7202 if (unknown) {
7203 Printf("Total number of clusters: (unknown)");
7204 } else {
7205 Printf("Total number of clusters: %lld %s", totalClusters, estimated ? "(estimated)" : "");
7206 }
7207 return;
7208 }
7209
7210 Int_t nl = const_cast<TTree*>(this)->GetListOfLeaves()->GetEntries();
7211 Int_t l;
7212 TBranch* br = 0;
7213 TLeaf* leaf = 0;
7214 if (strstr(option, "toponly")) {
7215 Long64_t *count = new Long64_t[nl];
7216 Int_t keep =0;
7217 for (l=0;l<nl;l++) {
7218 leaf = (TLeaf *)const_cast<TTree*>(this)->GetListOfLeaves()->At(l);
7219 br = leaf->GetBranch();
7220 if (strchr(br->GetName(),'.')) {
7221 count[l] = -1;
7222 count[keep] += br->GetZipBytes();
7223 } else {
7224 keep = l;
7225 count[keep] = br->GetZipBytes();
7226 }
7227 }
7228 for (l=0;l<nl;l++) {
7229 if (count[l] < 0) continue;
7230 leaf = (TLeaf *)const_cast<TTree*>(this)->GetListOfLeaves()->At(l);
7231 br = leaf->GetBranch();
7232 Printf("branch: %-20s %9lld\n",br->GetName(),count[l]);
7233 }
7234 delete [] count;
7235 } else {
7236 TString reg = "*";
7237 if (strlen(option) && strchr(option,'*')) reg = option;
7238 TRegexp re(reg,kTRUE);
7239 TIter next(const_cast<TTree*>(this)->GetListOfBranches());
7241 while ((br= (TBranch*)next())) {
7242 TString st = br->GetName();
7243 st.ReplaceAll("/","_");
7244 if (st.Index(re) == kNPOS) continue;
7245 br->Print(option);
7246 }
7247 }
7248
7249 //print TRefTable (if one)
7250 if (fBranchRef) fBranchRef->Print(option);
7251
7252 //print friends if option "all"
7253 if (!fFriends || !strstr(option,"all")) return;
7254 TIter nextf(fFriends);
7255 TFriendLock lock(const_cast<TTree*>(this),kPrint);
7256 TFriendElement *fr;
7257 while ((fr = (TFriendElement*)nextf())) {
7258 TTree * t = fr->GetTree();
7259 if (t) t->Print(option);
7260 }
7261}
7262
7263////////////////////////////////////////////////////////////////////////////////
7264/// Print statistics about the TreeCache for this tree.
7265/// Like:
7266/// ~~~ {.cpp}
7267/// ******TreeCache statistics for file: cms2.root ******
7268/// Reading 73921562 bytes in 716 transactions
7269/// Average transaction = 103.242405 Kbytes
7270/// Number of blocks in current cache: 202, total size : 6001193
7271/// ~~~
7272/// if option = "a" the list of blocks in the cache is printed
7274void TTree::PrintCacheStats(Option_t* option) const
7275{
7276 TFile *f = GetCurrentFile();
7277 if (!f) return;
7278 TTreeCache *tc = GetReadCache(f);
7279 if (tc) tc->Print(option);
7280}
7281
7282////////////////////////////////////////////////////////////////////////////////
7283/// Process this tree executing the TSelector code in the specified filename.
7284/// The return value is -1 in case of error and TSelector::GetStatus() in
7285/// in case of success.
7286///
7287/// The code in filename is loaded (interpreted or compiled, see below),
7288/// filename must contain a valid class implementation derived from TSelector,
7289/// where TSelector has the following member functions:
7290///
7291/// - `Begin()`: called every time a loop on the tree starts,
7292/// a convenient place to create your histograms.
7293/// - `SlaveBegin()`: called after Begin(), when on PROOF called only on the
7294/// slave servers.
7295/// - `Process()`: called for each event, in this function you decide what
7296/// to read and fill your histograms.
7297/// - `SlaveTerminate`: called at the end of the loop on the tree, when on PROOF
7298/// called only on the slave servers.
7299/// - `Terminate()`: called at the end of the loop on the tree,
7300/// a convenient place to draw/fit your histograms.
7301///
7302/// If filename is of the form file.C, the file will be interpreted.
7303///
7304/// If filename is of the form file.C++, the file file.C will be compiled
7305/// and dynamically loaded.
7306///
7307/// If filename is of the form file.C+, the file file.C will be compiled
7308/// and dynamically loaded. At next call, if file.C is older than file.o
7309/// and file.so, the file.C is not compiled, only file.so is loaded.
7310///
7311/// ## NOTE1
7312///
7313/// It may be more interesting to invoke directly the other Process function
7314/// accepting a TSelector* as argument.eg
7315/// ~~~ {.cpp}
7316/// MySelector *selector = (MySelector*)TSelector::GetSelector(filename);
7317/// selector->CallSomeFunction(..);
7318/// mytree.Process(selector,..);
7319/// ~~~
7320/// ## NOTE2
7321//
7322/// One should not call this function twice with the same selector file
7323/// in the same script. If this is required, proceed as indicated in NOTE1,
7324/// by getting a pointer to the corresponding TSelector,eg
7325///
7326/// ### Workaround 1
7327///
7328/// ~~~ {.cpp}
7329/// void stubs1() {
7330/// TSelector *selector = TSelector::GetSelector("h1test.C");
7331/// TFile *f1 = new TFile("stubs_nood_le1.root");
7332/// TTree *h1 = (TTree*)f1->Get("h1");
7333/// h1->Process(selector);
7334/// TFile *f2 = new TFile("stubs_nood_le1_coarse.root");
7335/// TTree *h2 = (TTree*)f2->Get("h1");
7336/// h2->Process(selector);
7337/// }
7338/// ~~~
7339/// or use ACLIC to compile the selector
7340///
7341/// ### Workaround 2
7342///
7343/// ~~~ {.cpp}
7344/// void stubs2() {
7345/// TFile *f1 = new TFile("stubs_nood_le1.root");
7346/// TTree *h1 = (TTree*)f1->Get("h1");
7347/// h1->Process("h1test.C+");
7348/// TFile *f2 = new TFile("stubs_nood_le1_coarse.root");
7349/// TTree *h2 = (TTree*)f2->Get("h1");
7350/// h2->Process("h1test.C+");
7351/// }
7352/// ~~~
7354Long64_t TTree::Process(const char* filename, Option_t* option, Long64_t nentries, Long64_t firstentry)
7355{
7356 GetPlayer();
7357 if (fPlayer) {
7358 return fPlayer->Process(filename, option, nentries, firstentry);
7359 }
7360 return -1;
7361}
7362
7363////////////////////////////////////////////////////////////////////////////////
7364/// Process this tree executing the code in the specified selector.
7365/// The return value is -1 in case of error and TSelector::GetStatus() in
7366/// in case of success.
7367///
7368/// The TSelector class has the following member functions:
7369///
7370/// - `Begin()`: called every time a loop on the tree starts,
7371/// a convenient place to create your histograms.
7372/// - `SlaveBegin()`: called after Begin(), when on PROOF called only on the
7373/// slave servers.
7374/// - `Process()`: called for each event, in this function you decide what
7375/// to read and fill your histograms.
7376/// - `SlaveTerminate`: called at the end of the loop on the tree, when on PROOF
7377/// called only on the slave servers.
7378/// - `Terminate()`: called at the end of the loop on the tree,
7379/// a convenient place to draw/fit your histograms.
7380///
7381/// If the Tree (Chain) has an associated EventList, the loop is on the nentries
7382/// of the EventList, starting at firstentry, otherwise the loop is on the
7383/// specified Tree entries.
7385Long64_t TTree::Process(TSelector* selector, Option_t* option, Long64_t nentries, Long64_t firstentry)
7386{
7387 GetPlayer();
7388 if (fPlayer) {
7389 return fPlayer->Process(selector, option, nentries, firstentry);
7390 }
7391 return -1;
7392}
7393
7394////////////////////////////////////////////////////////////////////////////////
7395/// Make a projection of a tree using selections.
7396///
7397/// Depending on the value of varexp (described in Draw) a 1-D, 2-D, etc.,
7398/// projection of the tree will be filled in histogram hname.
7399/// Note that the dimension of hname must match with the dimension of varexp.
7400///
7402Long64_t TTree::Project(const char* hname, const char* varexp, const char* selection, Option_t* option, Long64_t nentries, Long64_t firstentry)
7403{
7404 TString var;
7405 var.Form("%s>>%s", varexp, hname);
7406 TString opt("goff");
7407 if (option) {
7408 opt.Form("%sgoff", option);
7409 }
7410 Long64_t nsel = Draw(var, selection, opt, nentries, firstentry);
7411 return nsel;
7412}
7413
7414////////////////////////////////////////////////////////////////////////////////
7415/// Loop over entries and return a TSQLResult object containing entries following selection.
7417TSQLResult* TTree::Query(const char* varexp, const char* selection, Option_t* option, Long64_t nentries, Long64_t firstentry)
7418{
7419 GetPlayer();
7420 if (fPlayer) {
7421 return fPlayer->Query(varexp, selection, option, nentries, firstentry);
7422 }
7423 return 0;
7424}
7425
7426////////////////////////////////////////////////////////////////////////////////
7427/// Create or simply read branches from filename.
7428///
7429/// if branchDescriptor = "" (default), it is assumed that the Tree descriptor
7430/// is given in the first line of the file with a syntax like
7431/// ~~~ {.cpp}
7432/// A/D:Table[2]/F:Ntracks/I:astring/C
7433/// ~~~
7434/// otherwise branchDescriptor must be specified with the above syntax.
7435///
7436/// - If the type of the first variable is not specified, it is assumed to be "/F"
7437/// - If the type of any other variable is not specified, the type of the previous
7438/// variable is assumed. eg
7439/// - `x:y:z` (all variables are assumed of type "F"
7440/// - `x/D:y:z` (all variables are of type "D"
7441/// - `x:y/D:z` (x is type "F", y and z of type "D"
7442///
7443/// delimiter allows for the use of another delimiter besides whitespace.
7444/// This provides support for direct import of common data file formats
7445/// like csv. If delimiter != ' ' and branchDescriptor == "", then the
7446/// branch description is taken from the first line in the file, but
7447/// delimiter is used for the branch names tokenization rather than ':'.
7448/// Note however that if the values in the first line do not use the
7449/// /[type] syntax, all variables are assumed to be of type "F".
7450/// If the filename ends with extensions .csv or .CSV and a delimiter is
7451/// not specified (besides ' '), the delimiter is automatically set to ','.
7452///
7453/// Lines in the input file starting with "#" are ignored. Leading whitespace
7454/// for each column data is skipped. Empty lines are skipped.
7455///
7456/// A TBranch object is created for each variable in the expression.
7457/// The total number of rows read from the file is returned.
7458///
7459/// ## FILLING a TTree WITH MULTIPLE INPUT TEXT FILES
7460///
7461/// To fill a TTree with multiple input text files, proceed as indicated above
7462/// for the first input file and omit the second argument for subsequent calls
7463/// ~~~ {.cpp}
7464/// T.ReadFile("file1.dat","branch descriptor");
7465/// T.ReadFile("file2.dat");
7466/// ~~~
7468Long64_t TTree::ReadFile(const char* filename, const char* branchDescriptor, char delimiter)
7469{
7470 std::ifstream in;
7471 in.open(filename);
7472 if (!in.good()) {
7473 Error("ReadFile","Cannot open file: %s",filename);
7474 return 0;
7475 }
7476 const char* ext = strrchr(filename, '.');
7477 if(ext != NULL && ((strcmp(ext, ".csv") == 0) || (strcmp(ext, ".CSV") == 0)) && delimiter == ' ') {
7478 delimiter = ',';
7479 }
7480 return ReadStream(in, branchDescriptor, delimiter);
7481}
7482
7483////////////////////////////////////////////////////////////////////////////////
7484/// Determine which newline this file is using.
7485/// Return '\\r' for Windows '\\r\\n' as that already terminates.
7487char TTree::GetNewlineValue(std::istream &inputStream)
7488{
7489 Long_t inPos = inputStream.tellg();
7490 char newline = '\n';
7491 while(1) {
7492 char c = 0;
7493 inputStream.get(c);
7494 if(!inputStream.good()) {
7495 Error("ReadStream","Error reading stream: no newline found.");
7496 return 0;
7497 }
7498 if(c == newline) break;
7499 if(c == '\r') {
7500 newline = '\r';
7501 break;
7502 }
7503 }
7504 inputStream.clear();
7505 inputStream.seekg(inPos);
7506 return newline;
7507}
7508
7509////////////////////////////////////////////////////////////////////////////////
7510/// Create or simply read branches from an input stream.
7511///
7512/// See reference information for TTree::ReadFile
7514Long64_t TTree::ReadStream(std::istream& inputStream, const char *branchDescriptor, char delimiter)
7515{
7516 char newline = 0;
7517 std::stringstream ss;
7518 std::istream *inTemp;
7519 Long_t inPos = inputStream.tellg();
7520 if (!inputStream.good()) {
7521 Error("ReadStream","Error reading stream");
7522 return 0;
7523 }
7524 if (inPos == -1) {
7525 ss << std::cin.rdbuf();
7526 newline = GetNewlineValue(ss);
7527 inTemp = &ss;
7528 } else {
7529 newline = GetNewlineValue(inputStream);
7530 inTemp = &inputStream;
7531 }
7532 std::istream& in = *inTemp;
7533 Long64_t nlines = 0;
7534
7535 TBranch *branch = 0;
7536 Int_t nbranches = fBranches.GetEntries();
7537 if (nbranches == 0) {
7538 char *bdname = new char[4000];
7539 char *bd = new char[100000];
7540 Int_t nch = 0;
7541 if (branchDescriptor) nch = strlen(branchDescriptor);
7542 // branch Descriptor is null, read its definition from the first line in the file
7543 if (!nch) {
7544 do {
7545 in.getline(bd, 100000, newline);
7546 if (!in.good()) {
7547 delete [] bdname;
7548 delete [] bd;
7549 Error("ReadStream","Error reading stream");
7550 return 0;
7551 }
7552 char *cursor = bd;
7553 while( isspace(*cursor) && *cursor != '\n' && *cursor != '\0') {
7554 ++cursor;
7555 }
7556 if (*cursor != '#' && *cursor != '\n' && *cursor != '\0') {
7557 break;
7558 }
7559 } while (true);
7560 ++nlines;
7561 nch = strlen(bd);
7562 } else {
7563 strlcpy(bd,branchDescriptor,100000);
7564 }
7565
7566 //parse the branch descriptor and create a branch for each element
7567 //separated by ":"
7568 void *address = &bd[90000];
7569 char *bdcur = bd;
7570 TString desc="", olddesc="F";
7571 char bdelim = ':';
7572 if(delimiter != ' ') {
7573 bdelim = delimiter;
7574 if (strchr(bdcur,bdelim)==0 && strchr(bdcur,':') != 0) {
7575 // revert to the default
7576 bdelim = ':';
7577 }
7578 }
7579 while (bdcur) {
7580 char *colon = strchr(bdcur,bdelim);
7581 if (colon) *colon = 0;
7582 strlcpy(bdname,bdcur,4000);
7583 char *slash = strchr(bdname,'/');
7584 if (slash) {
7585 *slash = 0;
7586 desc = bdcur;
7587 olddesc = slash+1;
7588 } else {
7589 desc.Form("%s/%s",bdname,olddesc.Data());
7590 }
7591 char *bracket = strchr(bdname,'[');
7592 if (bracket) {
7593 *bracket = 0;
7594 }
7595 branch = new TBranch(this,bdname,address,desc.Data(),32000);
7596 if (branch->IsZombie()) {
7597 delete branch;
7598 Warning("ReadStream","Illegal branch definition: %s",bdcur);
7599 } else {
7600 fBranches.Add(branch);
7601 branch->SetAddress(0);
7602 }
7603 if (!colon)break;
7604 bdcur = colon+1;
7605 }
7606 delete [] bdname;
7607 delete [] bd;
7608 }
7609
7610 nbranches = fBranches.GetEntries();
7611
7612 if (gDebug > 1) {
7613 Info("ReadStream", "Will use branches:");
7614 for (int i = 0 ; i < nbranches; ++i) {
7615 TBranch* br = (TBranch*) fBranches.At(i);
7616 Info("ReadStream", " %s: %s [%s]", br->GetName(),
7617 br->GetTitle(), br->GetListOfLeaves()->At(0)->IsA()->GetName());
7618 }
7619 if (gDebug > 3) {
7620 Info("ReadStream", "Dumping read tokens, format:");
7621 Info("ReadStream", "LLLLL:BBB:gfbe:GFBE:T");
7622 Info("ReadStream", " L: line number");
7623 Info("ReadStream", " B: branch number");
7624 Info("ReadStream", " gfbe: good / fail / bad / eof of token");
7625 Info("ReadStream", " GFBE: good / fail / bad / eof of file");
7626 Info("ReadStream", " T: Token being read");
7627 }
7628 }
7629
7630 //loop on all lines in the file
7631 Long64_t nGoodLines = 0;
7632 std::string line;
7633 const char sDelimBuf[2] = { delimiter, 0 };
7634 const char* sDelim = sDelimBuf;
7635 if (delimiter == ' ') {
7636 // ' ' really means whitespace
7637 sDelim = "[ \t]";
7638 }
7639 while(in.good()) {
7640 if (newline == '\r' && in.peek() == '\n') {
7641 // Windows, skip '\n':
7642 in.get();
7643 }
7644 std::getline(in, line, newline);
7645 ++nlines;
7646
7647 TString sLine(line);
7648 sLine = sLine.Strip(TString::kLeading); // skip leading whitespace
7649 if (sLine.IsNull()) {
7650 if (gDebug > 2) {
7651 Info("ReadStream", "Skipping empty line number %lld", nlines);
7652 }
7653 continue; // silently skip empty lines
7654 }
7655 if (sLine[0] == '#') {
7656 if (gDebug > 2) {
7657 Info("ReadStream", "Skipping comment line number %lld: '%s'",
7658 nlines, line.c_str());
7659 }
7660 continue;
7661 }
7662 if (gDebug > 2) {
7663 Info("ReadStream", "Parsing line number %lld: '%s'",
7664 nlines, line.c_str());
7665 }
7666
7667 // Loop on branches and read the branch values into their buffer
7668 branch = 0;
7669 TString tok; // one column's data
7670 TString leafData; // leaf data, possibly multiple tokens for e.g. /I[2]
7671 std::stringstream sToken; // string stream feeding leafData into leaves
7672 Ssiz_t pos = 0;
7673 Int_t iBranch = 0;
7674 Bool_t goodLine = kTRUE; // whether the row can be filled into the tree
7675 Int_t remainingLeafLen = 0; // remaining columns for the current leaf
7676 while (goodLine && iBranch < nbranches
7677 && sLine.Tokenize(tok, pos, sDelim)) {
7678 tok = tok.Strip(TString::kLeading); // skip leading whitespace
7679 if (tok.IsNull() && delimiter == ' ') {
7680 // 1 2 should not be interpreted as 1,,,2 but 1, 2.
7681 // Thus continue until we have a non-empty token.
7682 continue;
7683 }
7684
7685 if (!remainingLeafLen) {
7686 // next branch!
7687 branch = (TBranch*)fBranches.At(iBranch);
7688 }
7689 TLeaf *leaf = (TLeaf*)branch->GetListOfLeaves()->At(0);
7690 if (!remainingLeafLen) {
7691 remainingLeafLen = leaf->GetLen();
7692 if (leaf->GetMaximum() > 0) {
7693 // This is a dynamic leaf length, i.e. most likely a TLeafC's
7694 // string size. This still translates into one token:
7695 remainingLeafLen = 1;
7696 }
7697
7698 leafData = tok;
7699 } else {
7700 // append token to laf data:
7701 leafData += " ";
7702 leafData += tok;
7703 }
7704 --remainingLeafLen;
7705 if (remainingLeafLen) {
7706 // need more columns for this branch:
7707 continue;
7708 }
7709 ++iBranch;
7710
7711 // initialize stringstream with token
7712 sToken.clear();
7713 sToken.seekp(0, std::ios_base::beg);
7714 sToken.str(leafData.Data());
7715 sToken.seekg(0, std::ios_base::beg);
7716 leaf->ReadValue(sToken, 0 /* 0 = "all" */);
7717 if (gDebug > 3) {
7718 Info("ReadStream", "%5lld:%3d:%d%d%d%d:%d%d%d%d:%s",
7719 nlines, iBranch,
7720 (int)sToken.good(), (int)sToken.fail(),
7721 (int)sToken.bad(), (int)sToken.eof(),
7722 (int)in.good(), (int)in.fail(),
7723 (int)in.bad(), (int)in.eof(),
7724 sToken.str().c_str());
7725 }
7726
7727 // Error handling
7728 if (sToken.bad()) {
7729 // How could that happen for a stringstream?
7730 Warning("ReadStream",
7731 "Buffer error while reading data for branch %s on line %lld",
7732 branch->GetName(), nlines);
7733 } else if (!sToken.eof()) {
7734 if (sToken.fail()) {
7735 Warning("ReadStream",
7736 "Couldn't read formatted data in \"%s\" for branch %s on line %lld; ignoring line",
7737 tok.Data(), branch->GetName(), nlines);
7738 goodLine = kFALSE;
7739 } else {
7740 std::string remainder;
7741 std::getline(sToken, remainder, newline);
7742 if (!remainder.empty()) {
7743 Warning("ReadStream",
7744 "Ignoring trailing \"%s\" while reading data for branch %s on line %lld",
7745 remainder.c_str(), branch->GetName(), nlines);
7746 }
7747 }
7748 }
7749 } // tokenizer loop
7750
7751 if (iBranch < nbranches) {
7752 Warning("ReadStream",
7753 "Read too few columns (%d < %d) in line %lld; ignoring line",
7754 iBranch, nbranches, nlines);
7755 goodLine = kFALSE;
7756 } else if (pos != kNPOS) {
7757 sLine = sLine.Strip(TString::kTrailing);
7758 if (pos < sLine.Length()) {
7759 Warning("ReadStream",
7760 "Ignoring trailing \"%s\" while reading line %lld",
7761 sLine.Data() + pos - 1 /* also print delimiter */,
7762 nlines);
7763 }
7764 }
7765
7766 //we are now ready to fill the tree
7767 if (goodLine) {
7768 Fill();
7769 ++nGoodLines;
7770 }
7771 }
7772
7773 return nGoodLines;
7774}
7775
7776////////////////////////////////////////////////////////////////////////////////
7777/// Make sure that obj (which is being deleted or will soon be) is no
7778/// longer referenced by this TTree.
7781{
7782 if (obj == fEventList) {
7783 fEventList = 0;
7784 }
7785 if (obj == fEntryList) {
7786 fEntryList = 0;
7787 }
7788 if (fUserInfo) {
7790 }
7791 if (fPlayer == obj) {
7792 fPlayer = 0;
7793 }
7794 if (fTreeIndex == obj) {
7795 fTreeIndex = 0;
7796 }
7797 if (fAliases) {
7799 }
7800 if (fFriends) {
7802 }
7803}
7804
7805////////////////////////////////////////////////////////////////////////////////
7806/// Refresh contents of this tree and its branches from the current status on disk.
7807///
7808/// One can call this function in case the tree file is being
7809/// updated by another process.
7811void TTree::Refresh()
7812{
7813 if (!fDirectory->GetFile()) {
7814 return;
7815 }
7817 fDirectory->Remove(this);
7819 if (!tree) {
7820 return;
7821 }
7822 //copy info from tree header into this Tree
7823 fEntries = 0;
7824 fNClusterRange = 0;
7826
7827 fAutoSave = tree->fAutoSave;
7828 fEntries = tree->fEntries;
7829 fTotBytes = tree->GetTotBytes();
7830 fZipBytes = tree->GetZipBytes();
7831 fSavedBytes = tree->fSavedBytes;
7832 fTotalBuffers = tree->fTotalBuffers.load();
7833
7834 //loop on all branches and update them
7835 Int_t nleaves = fLeaves.GetEntriesFast();
7836 for (Int_t i = 0; i < nleaves; i++) {
7837 TLeaf* leaf = (TLeaf*) fLeaves.UncheckedAt(i);
7838 TBranch* branch = (TBranch*) leaf->GetBranch();
7839 branch->Refresh(tree->GetBranch(branch->GetName()));
7840 }
7842 fDirectory->Append(this);
7843 delete tree;
7844 tree = 0;
7845}
7846
7847////////////////////////////////////////////////////////////////////////////////
7848/// Record a TFriendElement that we need to warn when the chain switches to
7849/// a new file (typically this is because this chain is a friend of another
7850/// TChain)
7853{
7854 if (!fExternalFriends)
7855 fExternalFriends = new TList();
7856 fExternalFriends->Add(fe);
7857}
7858
7859
7860////////////////////////////////////////////////////////////////////////////////
7861/// Removes external friend
7864{
7866}
7867
7868
7869////////////////////////////////////////////////////////////////////////////////
7870/// Remove a friend from the list of friends.
7872void TTree::RemoveFriend(TTree* oldFriend)
7873{
7874 // We already have been visited while recursively looking
7875 // through the friends tree, let return
7877 return;
7878 }
7879 if (!fFriends) {
7880 return;
7881 }
7882 TFriendLock lock(this, kRemoveFriend);
7883 TIter nextf(fFriends);
7884 TFriendElement* fe = 0;
7885 while ((fe = (TFriendElement*) nextf())) {
7886 TTree* friend_t = fe->GetTree();
7887 if (friend_t == oldFriend) {
7888 fFriends->Remove(fe);
7889 delete fe;
7890 fe = 0;
7891 }
7892 }
7893}
7894
7895////////////////////////////////////////////////////////////////////////////////
7896/// Reset baskets, buffers and entries count in all branches and leaves.
7898void TTree::Reset(Option_t* option)
7899{
7900 fNotify = 0;
7901 fEntries = 0;
7902 fNClusterRange = 0;
7903 fTotBytes = 0;
7904 fZipBytes = 0;
7905 fFlushedBytes = 0;
7906 fSavedBytes = 0;
7907 fTotalBuffers = 0;
7908 fChainOffset = 0;
7909 fReadEntry = -1;
7910
7911 delete fTreeIndex;
7912 fTreeIndex = 0;
7913
7915 for (Int_t i = 0; i < nb; ++i) {
7916 TBranch* branch = (TBranch*) fBranches.UncheckedAt(i);
7917 branch->Reset(option);
7918 }
7919
7920 if (fBranchRef) {
7921 fBranchRef->Reset();
7922 }
7923}
7924
7925////////////////////////////////////////////////////////////////////////////////
7926/// Resets the state of this TTree after a merge (keep the customization but
7927/// forget the data).
7930{
7931 fEntries = 0;
7932 fNClusterRange = 0;
7933 fTotBytes = 0;
7934 fZipBytes = 0;
7935 fSavedBytes = 0;
7936 fFlushedBytes = 0;
7937 fTotalBuffers = 0;
7938 fChainOffset = 0;
7939 fReadEntry = -1;
7940
7941 delete fTreeIndex;
7942 fTreeIndex = 0;
7943
7945 for (Int_t i = 0; i < nb; ++i) {
7946 TBranch* branch = (TBranch*) fBranches.UncheckedAt(i);
7947 branch->ResetAfterMerge(info);
7948 }
7949
7950 if (fBranchRef) {
7952 }
7953}
7954
7955////////////////////////////////////////////////////////////////////////////////
7956/// Tell all of our branches to set their addresses to zero.
7957///
7958/// Note: If any of our branches own any objects, they are deleted.
7961{
7962 if (br && br->GetTree()) {
7963 br->ResetAddress();
7964 }
7965}
7966
7967////////////////////////////////////////////////////////////////////////////////
7968/// Tell all of our branches to drop their current objects and allocate new ones.
7971{
7972 TObjArray* branches = GetListOfBranches();
7973 Int_t nbranches = branches->GetEntriesFast();
7974 for (Int_t i = 0; i < nbranches; ++i) {
7975 TBranch* branch = (TBranch*) branches->UncheckedAt(i);
7976 branch->ResetAddress();
7977 }
7978}
7979
7980////////////////////////////////////////////////////////////////////////////////
7981/// Loop over tree entries and print entries passing selection.
7982///
7983/// - If varexp is 0 (or "") then print only first 8 columns.
7984/// - If varexp = "*" print all columns.
7985///
7986/// Otherwise a columns selection can be made using "var1:var2:var3".
7987/// See TTreePlayer::Scan for more information
7989Long64_t TTree::Scan(const char* varexp, const char* selection, Option_t* option, Long64_t nentries, Long64_t firstentry)
7990{
7991 GetPlayer();
7992 if (fPlayer) {
7993 return fPlayer->Scan(varexp, selection, option, nentries, firstentry);
7994 }
7995 return -1;
7996}
7997
7998////////////////////////////////////////////////////////////////////////////////
7999/// Set a tree variable alias.
8000///
8001/// Set an alias for an expression/formula based on the tree 'variables'.
8002///
8003/// The content of 'aliasName' can be used in TTreeFormula (i.e. TTree::Draw,
8004/// TTree::Scan, TTreeViewer) and will be evaluated as the content of
8005/// 'aliasFormula'.
8006///
8007/// If the content of 'aliasFormula' only contains symbol names, periods and
8008/// array index specification (for example event.fTracks[3]), then
8009/// the content of 'aliasName' can be used as the start of symbol.
8010///
8011/// If the alias 'aliasName' already existed, it is replaced by the new
8012/// value.
8013///
8014/// When being used, the alias can be preceded by an eventual 'Friend Alias'
8015/// (see TTree::GetFriendAlias)
8016///
8017/// Return true if it was added properly.
8018///
8019/// For example:
8020/// ~~~ {.cpp}
8021/// tree->SetAlias("x1","(tdc1[1]-tdc1[0])/49");
8022/// tree->SetAlias("y1","(tdc1[3]-tdc1[2])/47");
8023/// tree->SetAlias("x2","(tdc2[1]-tdc2[0])/49");
8024/// tree->SetAlias("y2","(tdc2[3]-tdc2[2])/47");
8025/// tree->Draw("y2-y1:x2-x1");
8026///
8027/// tree->SetAlias("theGoodTrack","event.fTracks[3]");
8028/// tree->Draw("theGoodTrack.fPx"); // same as "event.fTracks[3].fPx"
8029/// ~~~
8031Bool_t TTree::SetAlias(const char* aliasName, const char* aliasFormula)
8032{
8033 if (!aliasName || !aliasFormula) {
8034 return kFALSE;
8035 }
8036 if (!aliasName[0] || !aliasFormula[0]) {
8037 return kFALSE;
8038 }
8039 if (!fAliases) {
8040 fAliases = new TList;
8041 } else {
8042 TNamed* oldHolder = (TNamed*) fAliases->FindObject(aliasName);
8043 if (oldHolder) {
8044 oldHolder->SetTitle(aliasFormula);
8045 return kTRUE;
8046 }
8047 }
8048 TNamed* holder = new TNamed(aliasName, aliasFormula);
8049 fAliases->Add(holder);
8050 return kTRUE;
8051}
8052
8053////////////////////////////////////////////////////////////////////////////////
8054/// This function may be called at the start of a program to change
8055/// the default value for fAutoFlush.
8056///
8057/// ### CASE 1 : autof > 0
8058///
8059/// autof is the number of consecutive entries after which TTree::Fill will
8060/// flush all branch buffers to disk.
8061///
8062/// ### CASE 2 : autof < 0
8063///
8064/// When filling the Tree the branch buffers will be flushed to disk when
8065/// more than autof bytes have been written to the file. At the first FlushBaskets
8066/// TTree::Fill will replace fAutoFlush by the current value of fEntries.
8067///
8068/// Calling this function with autof<0 is interesting when it is hard to estimate
8069/// the size of one entry. This value is also independent of the Tree.
8070///
8071/// The Tree is initialized with fAutoFlush=-30000000, ie that, by default,
8072/// the first AutoFlush will be done when 30 MBytes of data are written to the file.
8073///
8074/// ### CASE 3 : autof = 0
8075///
8076/// The AutoFlush mechanism is disabled.
8077///
8078/// Flushing the buffers at regular intervals optimize the location of
8079/// consecutive entries on the disk by creating clusters of baskets.
8080///
8081/// A cluster of baskets is a set of baskets that contains all
8082/// the data for a (consecutive) set of entries and that is stored
8083/// consecutively on the disk. When reading all the branches, this
8084/// is the minimum set of baskets that the TTreeCache will read.
8086void TTree::SetAutoFlush(Long64_t autof /* = -30000000 */ )
8087{
8088 // Implementation note:
8089 //
8090 // A positive value of autoflush determines the size (in number of entries) of
8091 // a cluster of baskets.
8092 //
8093 // If the value of autoflush is changed over time (this happens in
8094 // particular when the TTree results from fast merging many trees),
8095 // we record the values of fAutoFlush in the data members:
8096 // fClusterRangeEnd and fClusterSize.
8097 // In the code we refer to a range of entries where the size of the
8098 // cluster of baskets is the same (i.e the value of AutoFlush was
8099 // constant) is called a ClusterRange.
8100 //
8101 // The 2 arrays (fClusterRangeEnd and fClusterSize) have fNClusterRange
8102 // active (used) values and have fMaxClusterRange allocated entries.
8103 //
8104 // fClusterRangeEnd contains the last entries number of a cluster range.
8105 // In particular this means that the 'next' cluster starts at fClusterRangeEnd[]+1
8106 // fClusterSize contains the size in number of entries of all the cluster
8107 // within the given range.
8108 // The last range (and the only one if fNClusterRange is zero) start at
8109 // fNClusterRange[fNClusterRange-1]+1 and ends at the end of the TTree. The
8110 // size of the cluster in this range is given by the value of fAutoFlush.
8111 //
8112 // For example printing the beginning and end of each the ranges can be done by:
8113 //
8114 // Printf("%-16s %-16s %-16s %5s",
8115 // "Cluster Range #", "Entry Start", "Last Entry", "Size");
8116 // Int_t index= 0;
8117 // Long64_t clusterRangeStart = 0;
8118 // if (fNClusterRange) {
8119 // for( ; index < fNClusterRange; ++index) {
8120 // Printf("%-16d %-16lld %-16lld %5lld",
8121 // index, clusterRangeStart, fClusterRangeEnd[index], fClusterSize[index]);
8122 // clusterRangeStart = fClusterRangeEnd[index] + 1;
8123 // }
8124 // }
8125 // Printf("%-16d %-16lld %-16lld %5lld",
8126 // index, prevEntry, fEntries - 1, fAutoFlush);
8127 //
8128
8129 // Note: We store the entry number corresponding to the end of the cluster
8130 // rather than its start in order to avoid using the array if the cluster
8131 // size never varies (If there is only one value of AutoFlush for the whole TTree).
8132
8133 if( fAutoFlush != autof) {
8134 if ((fAutoFlush > 0 || autof > 0) && fFlushedBytes) {
8135 // The mechanism was already enabled, let's record the previous
8136 // cluster if needed.
8138 }
8139 fAutoFlush = autof;
8140 }
8141}
8142
8143////////////////////////////////////////////////////////////////////////////////
8144/// Mark the previous event as being at the end of the event cluster.
8145///
8146/// So, if fEntries is set to 10 (and this is the first cluster) when MarkEventCluster
8147/// is called, then the first cluster has 9 events.
8149{
8150 if (!fEntries) return;
8151
8152 if ( (fNClusterRange+1) > fMaxClusterRange ) {
8153 if (fMaxClusterRange) {
8154 // Resize arrays to hold a larger event cluster.
8155 Int_t newsize = TMath::Max(10,Int_t(2*fMaxClusterRange));
8157 newsize*sizeof(Long64_t),fMaxClusterRange*sizeof(Long64_t));
8159 newsize*sizeof(Long64_t),fMaxClusterRange*sizeof(Long64_t));
8160 fMaxClusterRange = newsize;
8161 } else {
8162 // Cluster ranges have never been initialized; create them now.
8163 fMaxClusterRange = 2;
8166 }
8167 }
8169 // If we are auto-flushing, then the cluster size is the same as the current auto-flush setting.
8170 if (fAutoFlush > 0) {
8171 // Even if the user triggers MarkEventRange prior to fAutoFlush being present, the TClusterIterator
8172 // will appropriately go to the next event range.
8174 // Otherwise, assume there is one cluster per event range (e.g., user is manually controlling the flush).
8175 } else if (fNClusterRange == 0) {
8177 } else {
8179 }
8181}
8182
8183////////////////////////////////////////////////////////////////////////////////
8184/// This function may be called at the start of a program to change
8185/// the default value for fAutoSave (and for SetAutoSave) is -300000000, ie 300 MBytes.
8186/// When filling the Tree the branch buffers as well as the Tree header
8187/// will be flushed to disk when the watermark is reached.
8188/// If fAutoSave is positive the watermark is reached when a multiple of fAutoSave
8189/// entries have been written.
8190/// If fAutoSave is negative the watermark is reached when -fAutoSave bytes
8191/// have been written to the file.
8192/// In case of a program crash, it will be possible to recover the data in the Tree
8193/// up to the last AutoSave point.
8195void TTree::SetAutoSave(Long64_t autos)
8196{
8197 fAutoSave = autos;
8198}
8199
8200////////////////////////////////////////////////////////////////////////////////
8201/// Set a branch's basket size.
8202///
8203/// bname is the name of a branch.
8204///
8205/// - if bname="*", apply to all branches.
8206/// - if bname="xxx*", apply to all branches with name starting with xxx
8207///
8208/// see TRegexp for wildcarding options
8209/// buffsize = branc basket size
8211void TTree::SetBasketSize(const char* bname, Int_t buffsize)
8212{
8213 Int_t nleaves = fLeaves.GetEntriesFast();
8214 TRegexp re(bname, kTRUE);
8215 Int_t nb = 0;
8216 for (Int_t i = 0; i < nleaves; i++) {
8217 TLeaf* leaf = (TLeaf*) fLeaves.UncheckedAt(i);
8218 TBranch* branch = (TBranch*) leaf->GetBranch();
8219 TString s = branch->GetName();
8220 if (strcmp(bname, branch->GetName()) && (s.Index(re) == kNPOS)) {
8221 continue;
8222 }
8223 nb++;
8224 branch->SetBasketSize(buffsize);
8225 }
8226 if (!nb) {
8227 Error("SetBasketSize", "unknown branch -> '%s'", bname);
8228 }
8229}
8230
8231////////////////////////////////////////////////////////////////////////////////
8232/// Change branch address, dealing with clone trees properly.
8233/// See TTree::CheckBranchAddressType for the semantic of the return value.
8234///
8235/// Note: See the comments in TBranchElement::SetAddress() for the
8236/// meaning of the addr parameter and the object ownership policy.
8238Int_t TTree::SetBranchAddress(const char* bname, void* addr, TBranch** ptr)
8239{
8240 TBranch* branch = GetBranch(bname);
8241 if (!branch) {
8242 if (ptr) *ptr = 0;
8243 Error("SetBranchAddress", "unknown branch -> %s", bname);
8244 return kMissingBranch;
8245 }
8246 return SetBranchAddressImp(branch,addr,ptr);
8247}
8248
8249////////////////////////////////////////////////////////////////////////////////
8250/// Verify the validity of the type of addr before calling SetBranchAddress.
8251/// See TTree::CheckBranchAddressType for the semantic of the return value.
8252///
8253/// Note: See the comments in TBranchElement::SetAddress() for the
8254/// meaning of the addr parameter and the object ownership policy.
8256Int_t TTree::SetBranchAddress(const char* bname, void* addr, TClass* ptrClass, EDataType datatype, Bool_t isptr)
8257{
8258 return SetBranchAddress(bname, addr, 0, ptrClass, datatype, isptr);
8259}
8260
8261////////////////////////////////////////////////////////////////////////////////
8262/// Verify the validity of the type of addr before calling SetBranchAddress.
8263/// See TTree::CheckBranchAddressType for the semantic of the return value.
8264///
8265/// Note: See the comments in TBranchElement::SetAddress() for the
8266/// meaning of the addr parameter and the object ownership policy.
8268Int_t TTree::SetBranchAddress(const char* bname, void* addr, TBranch** ptr, TClass* ptrClass, EDataType datatype, Bool_t isptr)
8269{
8270 TBranch* branch = GetBranch(bname);
8271 if (!branch) {
8272 if (ptr) *ptr = 0;
8273 Error("SetBranchAddress", "unknown branch -> %s", bname);
8274 return kMissingBranch;
8275 }
8276
8277 Int_t res = CheckBranchAddressType(branch, ptrClass, datatype, isptr);
8278
8279 // This will set the value of *ptr to branch.
8280 if (res >= 0) {
8281 // The check succeeded.
8282 if ((res & kNeedEnableDecomposedObj) && !branch->GetMakeClass())
8283 branch->SetMakeClass(kTRUE);
8284 SetBranchAddressImp(branch,addr,ptr);
8285 } else {
8286 if (ptr) *ptr = 0;
8287 }
8288 return res;
8289}
8290
8291////////////////////////////////////////////////////////////////////////////////
8292/// Change branch address, dealing with clone trees properly.
8293/// See TTree::CheckBranchAddressType for the semantic of the return value.
8294///
8295/// Note: See the comments in TBranchElement::SetAddress() for the
8296/// meaning of the addr parameter and the object ownership policy.
8298Int_t TTree::SetBranchAddressImp(TBranch *branch, void* addr, TBranch** ptr)
8299{
8300 if (ptr) {
8301 *ptr = branch;
8302 }
8303 if (fClones) {
8304 void* oldAddr = branch->GetAddress();
8305 TIter next(fClones);
8306 TTree* clone = 0;
8307 const char *bname = branch->GetName();
8308 while ((clone = (TTree*) next())) {
8309 TBranch* cloneBr = clone->GetBranch(bname);
8310 if (cloneBr && (cloneBr->GetAddress() == oldAddr)) {
8311 cloneBr->SetAddress(addr);
8312 }
8313 }
8314 }
8315 branch->SetAddress(addr);
8316 return kVoidPtr;
8317}
8318
8319////////////////////////////////////////////////////////////////////////////////
8320/// Set branch status to Process or DoNotProcess.
8321///
8322/// When reading a Tree, by default, all branches are read.
8323/// One can speed up considerably the analysis phase by activating
8324/// only the branches that hold variables involved in a query.
8325///
8326/// bname is the name of a branch.
8327///
8328/// - if bname="*", apply to all branches.
8329/// - if bname="xxx*", apply to all branches with name starting with xxx
8330///
8331/// see TRegexp for wildcarding options
8332///
8333/// - status = 1 branch will be processed
8334/// - = 0 branch will not be processed
8335///
8336/// Example:
8337///
8338/// Assume a tree T with sub-branches a,b,c,d,e,f,g,etc..
8339/// when doing T.GetEntry(i) all branches are read for entry i.
8340/// to read only the branches c and e, one can do
8341/// ~~~ {.cpp}
8342/// T.SetBranchStatus("*",0); //disable all branches
8343/// T.SetBranchStatus("c",1);
8344/// T.setBranchStatus("e",1);
8345/// T.GetEntry(i);
8346/// ~~~
8347/// bname is interpreted as a wildcarded TRegexp (see TRegexp::MakeWildcard).
8348/// Thus, "a*b" or "a.*b" matches branches starting with "a" and ending with
8349/// "b", but not any other branch with an "a" followed at some point by a
8350/// "b". For this second behavior, use "*a*b*". Note that TRegExp does not
8351/// support '|', and so you cannot select, e.g. track and shower branches
8352/// with "track|shower".
8353///
8354/// __WARNING! WARNING! WARNING!__
8355///
8356/// SetBranchStatus is matching the branch based on match of the branch
8357/// 'name' and not on the branch hierarchy! In order to be able to
8358/// selectively enable a top level object that is 'split' you need to make
8359/// sure the name of the top level branch is prefixed to the sub-branches'
8360/// name (by adding a dot ('.') at the end of the Branch creation and use the
8361/// corresponding bname.
8362///
8363/// I.e If your Tree has been created in split mode with a parent branch "parent."
8364/// (note the trailing dot).
8365/// ~~~ {.cpp}
8366/// T.SetBranchStatus("parent",1);
8367/// ~~~
8368/// will not activate the sub-branches of "parent". You should do:
8369/// ~~~ {.cpp}
8370/// T.SetBranchStatus("parent*",1);
8371/// ~~~
8372/// Without the trailing dot in the branch creation you have no choice but to
8373/// call SetBranchStatus explicitly for each of the sub branches.
8374///
8375/// An alternative to this function is to read directly and only
8376/// the interesting branches. Example:
8377/// ~~~ {.cpp}
8378/// TBranch *brc = T.GetBranch("c");
8379/// TBranch *bre = T.GetBranch("e");
8380/// brc->GetEntry(i);
8381/// bre->GetEntry(i);
8382/// ~~~
8383/// If found is not 0, the number of branch(es) found matching the regular
8384/// expression is returned in *found AND the error message 'unknown branch'
8385/// is suppressed.
8387void TTree::SetBranchStatus(const char* bname, Bool_t status, UInt_t* found)
8388{
8389 // We already have been visited while recursively looking
8390 // through the friends tree, let return
8392 return;
8393 }
8394
8395 if (0 == strcmp(bname, "")) {
8396 Error("SetBranchStatus", "Input regexp is an empty string: no match against branch names will be attempted.");
8397 return;
8398 }
8399
8400 TBranch *branch, *bcount, *bson;
8401 TLeaf *leaf, *leafcount;
8402
8403 Int_t i,j;
8404 Int_t nleaves = fLeaves.GetEntriesFast();
8405 TRegexp re(bname,kTRUE);
8406 Int_t nb = 0;
8407
8408 // first pass, loop on all branches
8409 // for leafcount branches activate/deactivate in function of status
8410 for (i=0;i<nleaves;i++) {
8411 leaf = (TLeaf*)fLeaves.UncheckedAt(i);
8412 branch = (TBranch*)leaf->GetBranch();
8413 TString s = branch->GetName();
8414 if (strcmp(bname,"*")) { //Regexp gives wrong result for [] in name
8415 TString longname;
8416 longname.Form("%s.%s",GetName(),branch->GetName());
8417 if (strcmp(bname,branch->GetName())
8418 && longname != bname
8419 && s.Index(re) == kNPOS) continue;
8420 }
8421 nb++;
8422 if (status) branch->ResetBit(kDoNotProcess);
8423 else branch->SetBit(kDoNotProcess);
8424 leafcount = leaf->GetLeafCount();
8425 if (leafcount) {
8426 bcount = leafcount->GetBranch();
8427 if (status) bcount->ResetBit(kDoNotProcess);
8428 else bcount->SetBit(kDoNotProcess);
8429 }
8430 }
8431 if (nb==0 && strchr(bname,'*')==0) {
8432 branch = GetBranch(bname);
8433 if (branch) {
8434 if (status) branch->ResetBit(kDoNotProcess);
8435 else branch->SetBit(kDoNotProcess);
8436 ++nb;
8437 }
8438 }
8439
8440 //search in list of friends
8441 UInt_t foundInFriend = 0;
8442 if (fFriends) {
8443 TFriendLock lock(this,kSetBranchStatus);
8444 TIter nextf(fFriends);
8445 TFriendElement *fe;
8446 TString name;
8447 while ((fe = (TFriendElement*)nextf())) {
8448 TTree *t = fe->GetTree();
8449 if (t==0) continue;
8450
8451 // If the alias is present replace it with the real name.
8452 char *subbranch = (char*)strstr(bname,fe->GetName());
8453 if (subbranch!=bname) subbranch = 0;
8454 if (subbranch) {
8455 subbranch += strlen(fe->GetName());
8456 if ( *subbranch != '.' ) subbranch = 0;
8457 else subbranch ++;
8458 }
8459 if (subbranch) {
8460 name.Form("%s.%s",t->GetName(),subbranch);
8461 } else {
8462 name = bname;
8463 }
8464 t->SetBranchStatus(name,status, &foundInFriend);
8465 }
8466 }
8467 if (!nb && !foundInFriend) {
8468 if (found==0) {
8469 if (status) {
8470 if (strchr(bname,'*') != 0)
8471 Error("SetBranchStatus", "No branch name is matching wildcard -> %s", bname);
8472 else
8473 Error("SetBranchStatus", "unknown branch -> %s", bname);
8474 } else {
8475 if (strchr(bname,'*') != 0)
8476 Warning("SetBranchStatus", "No branch name is matching wildcard -> %s", bname);
8477 else
8478 Warning("SetBranchStatus", "unknown branch -> %s", bname);
8479 }
8480 }
8481 return;
8482 }
8483 if (found) *found = nb + foundInFriend;
8484
8485 // second pass, loop again on all branches
8486 // activate leafcount branches for active branches only
8487 for (i = 0; i < nleaves; i++) {
8488 leaf = (TLeaf*)fLeaves.UncheckedAt(i);
8489 branch = (TBranch*)leaf->GetBranch();
8490 if (!branch->TestBit(kDoNotProcess)) {
8491 leafcount = leaf->GetLeafCount();
8492 if (leafcount) {
8493 bcount = leafcount->GetBranch();
8494 bcount->ResetBit(kDoNotProcess);
8495 }
8496 } else {
8497 //Int_t nbranches = branch->GetListOfBranches()->GetEntriesFast();
8498 Int_t nbranches = branch->GetListOfBranches()->GetEntries();
8499 for (j=0;j<nbranches;j++) {
8500 bson = (TBranch*)branch->GetListOfBranches()->UncheckedAt(j);
8501 if (!bson) continue;
8502 if (!bson->TestBit(kDoNotProcess)) {
8503 if (bson->GetNleaves() <= 0) continue;
8504 branch->ResetBit(kDoNotProcess);
8505 break;
8506 }
8507 }
8508 }
8509 }
8510}
8511
8512////////////////////////////////////////////////////////////////////////////////
8513/// Set the current branch style. (static function)
8514///
8515/// - style = 0 old Branch
8516/// - style = 1 new Bronch
8519{
8521}
8522
8523////////////////////////////////////////////////////////////////////////////////
8524/// Set maximum size of the file cache .
8525//
8526/// - if cachesize = 0 the existing cache (if any) is deleted.
8527/// - if cachesize = -1 (default) it is set to the AutoFlush value when writing
8528/// the Tree (default is 30 MBytes).
8529///
8530/// Returns:
8531/// - 0 size set, cache was created if possible
8532/// - -1 on error
8535{
8536 // remember that the user has requested an explicit cache setup
8538
8539 return SetCacheSizeAux(kFALSE, cacheSize);
8540}
8541
8542////////////////////////////////////////////////////////////////////////////////
8543/// Set the size of the file cache and create it if possible.
8544///
8545/// If autocache is true:
8546/// this may be an autocreated cache, possibly enlarging an existing
8547/// autocreated cache. The size is calculated. The value passed in cacheSize:
8548/// - cacheSize = 0 make cache if default cache creation is enabled
8549/// - cacheSize = -1 make a default sized cache in any case
8550///
8551/// If autocache is false:
8552/// this is a user requested cache. cacheSize is used to size the cache.
8553/// This cache should never be automatically adjusted.
8554///
8555/// Returns:
8556/// - 0 size set, or existing autosized cache almost large enough.
8557/// (cache was created if possible)
8558/// - -1 on error
8560Int_t TTree::SetCacheSizeAux(Bool_t autocache /* = kTRUE */, Long64_t cacheSize /* = 0 */ )
8561{
8562 if (autocache) {
8563 // used as a once only control for automatic cache setup
8565 }
8566
8567 if (!autocache) {
8568 // negative size means the user requests the default
8569 if (cacheSize < 0) {
8570 cacheSize = GetCacheAutoSize(kTRUE);
8571 }
8572 } else {
8573 if (cacheSize == 0) {
8574 cacheSize = GetCacheAutoSize();
8575 } else if (cacheSize < 0) {
8576 cacheSize = GetCacheAutoSize(kTRUE);
8577 }
8578 }
8579
8581 if (!file || GetTree() != this) {
8582 // if there's no file or we are not a plain tree (e.g. if we're a TChain)
8583 // do not create a cache, only record the size if one was given
8584 if (!autocache) {
8585 fCacheSize = cacheSize;
8586 }
8587 if (GetTree() != this) {
8588 return 0;
8589 }
8590 if (!autocache && cacheSize>0) {
8591 Warning("SetCacheSizeAux", "A TTreeCache could not be created because the TTree has no file");
8592 }
8593 return 0;
8594 }
8595
8596 // Check for an existing cache
8598 if (pf) {
8599 if (autocache) {
8600 // reset our cache status tracking in case existing cache was added
8601 // by the user without using one of the TTree methods
8602 fCacheSize = pf->GetBufferSize();
8604
8605 if (fCacheUserSet) {
8606 // existing cache was created by the user, don't change it
8607 return 0;
8608 }
8609 } else {
8610 // update the cache to ensure it records the user has explicitly
8611 // requested it
8613 }
8614
8615 // if we're using an automatically calculated size and the existing
8616 // cache is already almost large enough don't resize
8617 if (autocache && Long64_t(0.80*cacheSize) < fCacheSize) {
8618 // already large enough
8619 return 0;
8620 }
8621
8622 if (cacheSize == fCacheSize) {
8623 return 0;
8624 }
8625
8626 if (cacheSize == 0) {
8627 // delete existing cache
8628 pf->WaitFinishPrefetch();
8629 file->SetCacheRead(0,this);
8630 delete pf;
8631 pf = 0;
8632 } else {
8633 // resize
8634 Int_t res = pf->SetBufferSize(cacheSize);
8635 if (res < 0) {
8636 return -1;
8637 }
8638 }
8639 } else {
8640 // no existing cache
8641 if (autocache) {
8642 if (fCacheUserSet) {
8643 // value was already set manually.
8644 if (fCacheSize == 0) return 0;
8645 // Expected a cache should exist; perhaps the user moved it
8646 // Do nothing more here.
8647 if (cacheSize) {
8648 Error("SetCacheSizeAux", "Not setting up an automatically sized TTreeCache because of missing cache previously set");
8649 }
8650 return -1;
8651 }
8652 }
8653 }
8654
8655 fCacheSize = cacheSize;
8656 if (cacheSize == 0 || pf) {
8657 return 0;
8658 }
8659
8660#ifdef R__USE_IMT
8661 if(TTreeCacheUnzip::IsParallelUnzip() && file->GetCompressionLevel() > 0)
8662 pf = new TTreeCacheUnzip(this, cacheSize);
8663 else
8664#endif
8665 pf = new TTreeCache(this, cacheSize);
8666
8667 pf->SetAutoCreated(autocache);
8668
8669 return 0;
8670}
8671
8672////////////////////////////////////////////////////////////////////////////////
8673///interface to TTreeCache to set the cache entry range
8674///
8675/// Returns:
8676/// - 0 entry range set
8677/// - -1 on error
8680{
8681 if (!GetTree()) {
8682 if (LoadTree(0)<0) {
8683 Error("SetCacheEntryRange","Could not load a tree");
8684 return -1;
8685 }
8686 }
8687 if (GetTree()) {
8688 if (GetTree() != this) {
8689 return GetTree()->SetCacheEntryRange(first, last);
8690 }
8691 } else {
8692 Error("SetCacheEntryRange", "No tree is available. Could not set cache entry range");
8693 return -1;
8694 }
8695
8696 TFile *f = GetCurrentFile();
8697 if (!f) {
8698 Error("SetCacheEntryRange", "No file is available. Could not set cache entry range");
8699 return -1;
8700 }
8702 if (!tc) {
8703 Error("SetCacheEntryRange", "No cache is available. Could not set entry range");
8704 return -1;
8705 }
8706 tc->SetEntryRange(first,last);
8707 return 0;
8708}
8709
8710////////////////////////////////////////////////////////////////////////////////
8711/// Interface to TTreeCache to set the number of entries for the learning phase
8714{
8716}
8717
8718////////////////////////////////////////////////////////////////////////////////
8719/// Enable/Disable circularity for this tree.
8720///
8721/// if maxEntries > 0 a maximum of maxEntries is kept in one buffer/basket
8722/// per branch in memory.
8723/// Note that when this function is called (maxEntries>0) the Tree
8724/// must be empty or having only one basket per branch.
8725/// if maxEntries <= 0 the tree circularity is disabled.
8726///
8727/// #### NOTE 1:
8728/// Circular Trees are interesting in online real time environments
8729/// to store the results of the last maxEntries events.
8730/// #### NOTE 2:
8731/// Calling SetCircular with maxEntries <= 0 is necessary before
8732/// merging circular Trees that have been saved on files.
8733/// #### NOTE 3:
8734/// SetCircular with maxEntries <= 0 is automatically called
8735/// by TChain::Merge
8736/// #### NOTE 4:
8737/// A circular Tree can still be saved in a file. When read back,
8738/// it is still a circular Tree and can be filled again.
8740void TTree::SetCircular(Long64_t maxEntries)
8741{
8742 if (maxEntries <= 0) {
8743 // Disable circularity.
8744 fMaxEntries = 1000000000;
8745 fMaxEntries *= 1000;
8747 //in case the Tree was originally created in gROOT, the branch
8748 //compression level was set to -1. If the Tree is now associated to
8749 //a file, reset the compression level to the file compression level
8750 if (fDirectory) {
8751 TFile* bfile = fDirectory->GetFile();
8753 if (bfile) {
8754 compress = bfile->GetCompressionSettings();
8755 }
8757 for (Int_t i = 0; i < nb; i++) {
8758 TBranch* branch = (TBranch*) fBranches.UncheckedAt(i);
8759 branch->SetCompressionSettings(compress);
8760 }
8761 }
8762 } else {
8763 // Enable circularity.
8764 fMaxEntries = maxEntries;
8766 }
8767}
8768
8769////////////////////////////////////////////////////////////////////////////////
8770/// Set the debug level and the debug range.
8771///
8772/// For entries in the debug range, the functions TBranchElement::Fill
8773/// and TBranchElement::GetEntry will print the number of bytes filled
8774/// or read for each branch.
8776void TTree::SetDebug(Int_t level, Long64_t min, Long64_t max)
8777{
8778 fDebug = level;
8779 fDebugMin = min;
8780 fDebugMax = max;
8781}
8782
8783////////////////////////////////////////////////////////////////////////////////
8784/// Update the default value for the branch's fEntryOffsetLen.
8785/// If updateExisting is true, also update all the existing branches.
8786/// If newdefault is less than 10, the new default value will be 10.
8788void TTree::SetDefaultEntryOffsetLen(Int_t newdefault, Bool_t updateExisting)
8789{
8790 if (newdefault < 10) {
8791 newdefault = 10;
8792 }
8793 fDefaultEntryOffsetLen = newdefault;
8794 if (updateExisting) {
8795 TIter next( GetListOfBranches() );
8796 TBranch *b;
8797 while ( ( b = (TBranch*)next() ) ) {
8798 b->SetEntryOffsetLen( newdefault, kTRUE );
8799 }
8800 if (fBranchRef) {
8801 fBranchRef->SetEntryOffsetLen( newdefault, kTRUE );
8802 }
8803 }
8804}
8805
8806////////////////////////////////////////////////////////////////////////////////
8807/// Change the tree's directory.
8808///
8809/// Remove reference to this tree from current directory and
8810/// add reference to new directory dir. The dir parameter can
8811/// be 0 in which case the tree does not belong to any directory.
8812///
8815{
8816 if (fDirectory == dir) {
8817 return;
8818 }
8819 if (fDirectory) {
8820 fDirectory->Remove(this);
8821
8822 // Delete or move the file cache if it points to this Tree
8824 MoveReadCache(file,dir);
8825 }
8826 fDirectory = dir;
8827 if (fDirectory) {
8828 fDirectory->Append(this);
8829 }
8830 TFile* file = 0;
8831 if (fDirectory) {
8832 file = fDirectory->GetFile();
8833 }
8834 if (fBranchRef) {
8836 }
8837 TBranch* b = 0;
8838 TIter next(GetListOfBranches());
8839 while((b = (TBranch*) next())) {
8840 b->SetFile(file);
8841 }
8842}
8843
8844////////////////////////////////////////////////////////////////////////////////
8845/// Change number of entries in the tree.
8846///
8847/// If n >= 0, set number of entries in the tree = n.
8848///
8849/// If n < 0, set number of entries in the tree to match the
8850/// number of entries in each branch. (default for n is -1)
8851///
8852/// This function should be called only when one fills each branch
8853/// independently via TBranch::Fill without calling TTree::Fill.
8854/// Calling TTree::SetEntries() make sense only if the number of entries
8855/// in each branch is identical, a warning is issued otherwise.
8856/// The function returns the number of entries.
8857///
8860{
8861 // case 1 : force number of entries to n
8862 if (n >= 0) {
8863 fEntries = n;
8864 return n;
8865 }
8866
8867 // case 2; compute the number of entries from the number of entries in the branches
8868 TBranch* b(nullptr), *bMin(nullptr), *bMax(nullptr);
8869 Long64_t nMin = kMaxEntries;
8870 Long64_t nMax = 0;
8871 TIter next(GetListOfBranches());
8872 while((b = (TBranch*) next())){
8873 Long64_t n2 = b->GetEntries();
8874 if (!bMin || n2 < nMin) {
8875 nMin = n2;
8876 bMin = b;
8877 }
8878 if (!bMax || n2 > nMax) {
8879 nMax = n2;
8880 bMax = b;
8881 }
8882 }
8883 if (bMin && nMin != nMax) {
8884 Warning("SetEntries", "Tree branches have different numbers of entries, eg %s has %lld entries while %s has %lld entries.",
8885 bMin->GetName(), nMin, bMax->GetName(), nMax);
8886 }
8887 fEntries = nMax;
8888 return fEntries;
8889}
8890
8891////////////////////////////////////////////////////////////////////////////////
8892/// Set an EntryList
8894void TTree::SetEntryList(TEntryList *enlist, Option_t * /*opt*/)
8895{
8896 if (fEntryList) {
8897 //check if the previous entry list is owned by the tree
8899 delete fEntryList;
8900 }
8901 }
8902 fEventList = 0;
8903 if (!enlist) {
8904 fEntryList = 0;
8905 return;
8906 }
8907 fEntryList = enlist;
8908 fEntryList->SetTree(this);
8909
8910}
8911
8912////////////////////////////////////////////////////////////////////////////////
8913/// This function transfroms the given TEventList into a TEntryList
8914/// The new TEntryList is owned by the TTree and gets deleted when the tree
8915/// is deleted. This TEntryList can be returned by GetEntryList() function.
8917void TTree::SetEventList(TEventList *evlist)
8918{
8919 fEventList = evlist;
8920 if (fEntryList){
8922 TEntryList *tmp = fEntryList;
8923 fEntryList = 0; // Avoid problem with RecursiveRemove.
8924 delete tmp;
8925 } else {
8926 fEntryList = 0;
8927 }
8928 }
8929
8930 if (!evlist) {
8931 fEntryList = 0;
8932 fEventList = 0;
8933 return;
8934 }
8935
8936 fEventList = evlist;
8937 char enlistname[100];
8938 snprintf(enlistname,100, "%s_%s", evlist->GetName(), "entrylist");
8939 fEntryList = new TEntryList(enlistname, evlist->GetTitle());
8940 fEntryList->SetDirectory(0); // We own this.
8941 Int_t nsel = evlist->GetN();
8942 fEntryList->SetTree(this);
8943 Long64_t entry;
8944 for (Int_t i=0; i<nsel; i++){
8945 entry = evlist->GetEntry(i);
8946 fEntryList->Enter(entry);
8947 }
8950}
8951
8952////////////////////////////////////////////////////////////////////////////////
8953/// Set number of entries to estimate variable limits.
8954/// If n is -1, the estimate is set to be the current maximum
8955/// for the tree (i.e. GetEntries() + 1)
8956/// If n is less than -1, the behavior is undefined.
8958void TTree::SetEstimate(Long64_t n /* = 1000000 */)
8959{
8960 if (n == 0) {
8961 n = 10000;
8962 } else if (n < 0) {
8963 n = fEntries - n;
8964 }
8965 fEstimate = n;
8966 GetPlayer();
8967 if (fPlayer) {
8969 }
8970}
8971
8972////////////////////////////////////////////////////////////////////////////////
8973/// Provide the end-user with the ability to enable/disable various experimental
8974/// IO features for this TTree.
8975///
8976/// Returns all the newly-set IO settings.
8979{
8980 // Purposely ignore all unsupported bits; TIOFeatures implementation already warned the user about the
8981 // error of their ways; this is just a safety check.
8982 UChar_t featuresRequested = features.GetFeatures() & static_cast<UChar_t>(TBasket::EIOBits::kSupported);
8983
8984 UChar_t curFeatures = fIOFeatures.GetFeatures();
8985 UChar_t newFeatures = ~curFeatures & featuresRequested;
8986 curFeatures |= newFeatures;
8987 fIOFeatures.Set(curFeatures);
8988
8989 ROOT::TIOFeatures newSettings(newFeatures);
8990 return newSettings;
8991}
8992
8993////////////////////////////////////////////////////////////////////////////////
8994/// Set fFileNumber to number.
8995/// fFileNumber is used by TTree::Fill to set the file name
8996/// for a new file to be created when the current file exceeds fgTreeMaxSize.
8997/// (see TTree::ChangeFile)
8998/// if fFileNumber=10, the new file name will have a suffix "_11",
8999/// ie, fFileNumber is incremented before setting the file name
9001void TTree::SetFileNumber(Int_t number)
9002{
9003 if (fFileNumber < 0) {
9004 Warning("SetFileNumber", "file number must be positive. Set to 0");
9005 fFileNumber = 0;
9006 return;
9007 }
9008 fFileNumber = number;
9009}
9010
9011////////////////////////////////////////////////////////////////////////////////
9012/// Set all the branches in this TTree to be in decomposed object mode
9013/// (also known as MakeClass mode).
9014///
9015/// For MakeClass mode 0, the TTree expects the address where the data is stored
9016/// to be set by either the user or the TTree to the address of a full object
9017/// through the top level branch.
9018/// For MakeClass mode 1, this address is expected to point to a numerical type
9019/// or C-style array (variable or not) of numerical type, representing the
9020/// primitive data members.
9021/// The function's primary purpose is to allow the user to access the data
9022/// directly with numerical type variable rather than having to have the original
9023/// set of classes (or a reproduction thereof).
9026{
9027 fMakeClass = make;
9028
9030 for (Int_t i = 0; i < nb; ++i) {
9031 TBranch* branch = (TBranch*) fBranches.UncheckedAt(i);
9032 branch->SetMakeClass(make);
9033 }
9034}
9035
9036////////////////////////////////////////////////////////////////////////////////
9037/// Set the maximum size in bytes of a Tree file (static function).
9038/// The default size is 100000000000LL, ie 100 Gigabytes.
9039///
9040/// In TTree::Fill, when the file has a size > fgMaxTreeSize,
9041/// the function closes the current file and starts writing into
9042/// a new file with a name of the style "file_1.root" if the original
9043/// requested file name was "file.root".
9045void TTree::SetMaxTreeSize(Long64_t maxsize)
9046{
9047 fgMaxTreeSize = maxsize;
9048}
9049
9050////////////////////////////////////////////////////////////////////////////////
9051/// Change the name of this tree.
9053void TTree::SetName(const char* name)
9054{
9055 if (gPad) {
9056 gPad->Modified();
9057 }
9058 // Trees are named objects in a THashList.
9059 // We must update hashlists if we change the name.
9060 TFile *file = 0;
9061 TTreeCache *pf = 0;
9062 if (fDirectory) {
9063 fDirectory->Remove(this);
9064 if ((file = GetCurrentFile())) {
9065 pf = GetReadCache(file);
9066 file->SetCacheRead(0,this,TFile::kDoNotDisconnect);
9067 }
9068 }
9069 // This changes our hash value.
9070 fName = name;
9071 if (fDirectory) {
9072 fDirectory->Append(this);
9073 if (pf) {
9074 file->SetCacheRead(pf,this,TFile::kDoNotDisconnect);
9075 }
9076 }
9077}
9078
9079////////////////////////////////////////////////////////////////////////////////
9080/// Change the name and title of this tree.
9082void TTree::SetObject(const char* name, const char* title)
9083{
9084 if (gPad) {
9085 gPad->Modified();
9086 }
9087
9088 // Trees are named objects in a THashList.
9089 // We must update hashlists if we change the name
9090 TFile *file = 0;
9091 TTreeCache *pf = 0;
9092 if (fDirectory) {
9093 fDirectory->Remove(this);
9094 if ((file = GetCurrentFile())) {
9095 pf = GetReadCache(file);
9096 file->SetCacheRead(0,this,TFile::kDoNotDisconnect);
9097 }
9098 }
9099 // This changes our hash value.
9100 fName = name;
9101 fTitle = title;
9102 if (fDirectory) {
9103 fDirectory->Append(this);
9104 if (pf) {
9105 file->SetCacheRead(pf,this,TFile::kDoNotDisconnect);
9106 }
9107 }
9108}
9109
9110////////////////////////////////////////////////////////////////////////////////
9111/// Enable or disable parallel unzipping of Tree buffers.
9113void TTree::SetParallelUnzip(Bool_t opt, Float_t RelSize)
9114{
9115#ifdef R__USE_IMT
9116 if (GetTree() == 0) {
9118 if (!GetTree())
9119 return;
9120 }
9121 if (GetTree() != this) {
9122 GetTree()->SetParallelUnzip(opt, RelSize);
9123 return;
9124 }
9126 if (!file)
9127 return;
9128
9130 if (pf && !( opt ^ (nullptr != dynamic_cast<TTreeCacheUnzip*>(pf)))) {
9131 // done with opt and type are in agreement.
9132 return;
9133 }
9134 delete pf;
9135 auto cacheSize = GetCacheAutoSize(kTRUE);
9136 if (opt) {
9137 auto unzip = new TTreeCacheUnzip(this, cacheSize);
9138 unzip->SetUnzipBufferSize( Long64_t(cacheSize * RelSize) );
9139 } else {
9140 pf = new TTreeCache(this, cacheSize);
9141 }
9142#else
9143 (void)opt;
9144 (void)RelSize;
9145#endif
9146}
9147
9148////////////////////////////////////////////////////////////////////////////////
9149/// Set perf stats
9152{
9153 fPerfStats = perf;
9154}
9155
9156////////////////////////////////////////////////////////////////////////////////
9157/// The current TreeIndex is replaced by the new index.
9158/// Note that this function does not delete the previous index.
9159/// This gives the possibility to play with more than one index, e.g.,
9160/// ~~~ {.cpp}
9161/// TVirtualIndex* oldIndex = tree.GetTreeIndex();
9162/// tree.SetTreeIndex(newIndex);
9163/// tree.Draw();
9164/// tree.SetTreeIndex(oldIndex);
9165/// tree.Draw(); etc
9166/// ~~~
9169{
9170 if (fTreeIndex) {
9171 fTreeIndex->SetTree(0);
9172 }
9173 fTreeIndex = index;
9174}
9175
9176////////////////////////////////////////////////////////////////////////////////
9177/// Set tree weight.
9178///
9179/// The weight is used by TTree::Draw to automatically weight each
9180/// selected entry in the resulting histogram.
9181///
9182/// For example the equivalent of:
9183/// ~~~ {.cpp}
9184/// T.Draw("x", "w")
9185/// ~~~
9186/// is:
9187/// ~~~ {.cpp}
9188/// T.SetWeight(w);
9189/// T.Draw("x");
9190/// ~~~
9191/// This function is redefined by TChain::SetWeight. In case of a
9192/// TChain, an option "global" may be specified to set the same weight
9193/// for all trees in the TChain instead of the default behaviour
9194/// using the weights of each tree in the chain (see TChain::SetWeight).
9197{
9198 fWeight = w;
9199}
9200
9201////////////////////////////////////////////////////////////////////////////////
9202/// Print values of all active leaves for entry.
9203///
9204/// - if entry==-1, print current entry (default)
9205/// - if a leaf is an array, a maximum of lenmax elements is printed.
9207void TTree::Show(Long64_t entry, Int_t lenmax)
9208{
9209 if (entry != -1) {
9210 Int_t ret = LoadTree(entry);
9211 if (ret == -2) {
9212 Error("Show()", "Cannot read entry %lld (entry does not exist)", entry);
9213 return;
9214 } else if (ret == -1) {
9215 Error("Show()", "Cannot read entry %lld (I/O error)", entry);
9216 return;
9217 }
9218 ret = GetEntry(entry);
9219 if (ret == -1) {
9220 Error("Show()", "Cannot read entry %lld (I/O error)", entry);
9221 return;
9222 } else if (ret == 0) {
9223 Error("Show()", "Cannot read entry %lld (no data read)", entry);
9224 return;
9225 }
9226 }
9227 printf("======> EVENT:%lld\n", fReadEntry);
9228 TObjArray* leaves = GetListOfLeaves();
9229 Int_t nleaves = leaves->GetEntriesFast();
9230 Int_t ltype;
9231 for (Int_t i = 0; i < nleaves; i++) {
9232 TLeaf* leaf = (TLeaf*) leaves->UncheckedAt(i);
9233 TBranch* branch = leaf->GetBranch();
9234 if (branch->TestBit(kDoNotProcess)) {
9235 continue;
9236 }
9237 Int_t len = leaf->GetLen();
9238 if (len <= 0) {
9239 continue;
9240 }
9241 len = TMath::Min(len, lenmax);
9242 if (leaf->IsA() == TLeafElement::Class()) {
9243 leaf->PrintValue(lenmax);
9244 continue;
9245 }
9246 if (branch->GetListOfBranches()->GetEntriesFast() > 0) {
9247 continue;
9248 }
9249 ltype = 10;
9250 if (leaf->IsA() == TLeafF::Class()) {
9251 ltype = 5;
9252 }
9253 if (leaf->IsA() == TLeafD::Class()) {
9254 ltype = 5;
9255 }
9256 if (leaf->IsA() == TLeafC::Class()) {
9257 len = 1;
9258 ltype = 5;
9259 };
9260 printf(" %-15s = ", leaf->GetName());
9261 for (Int_t l = 0; l < len; l++) {
9262 leaf->PrintValue(l);
9263 if (l == (len - 1)) {
9264 printf("\n");
9265 continue;
9266 }
9267 printf(", ");
9268 if ((l % ltype) == 0) {
9269 printf("\n ");
9270 }
9271 }
9272 }
9273}
9274
9275////////////////////////////////////////////////////////////////////////////////
9276/// Start the TTreeViewer on this tree.
9277///
9278/// - ww is the width of the canvas in pixels
9279/// - wh is the height of the canvas in pixels
9281void TTree::StartViewer()
9282{
9283 GetPlayer();
9284 if (fPlayer) {
9285 fPlayer->StartViewer(600, 400);
9286 }
9287}
9288
9289////////////////////////////////////////////////////////////////////////////////
9290/// Stop the cache learning phase
9291///
9292/// Returns:
9293/// - 0 learning phase stopped or not active
9294/// - -1 on error
9297{
9298 if (!GetTree()) {
9299 if (LoadTree(0)<0) {
9300 Error("StopCacheLearningPhase","Could not load a tree");
9301 return -1;
9302 }
9303 }
9304 if (GetTree()) {
9305 if (GetTree() != this) {
9306 return GetTree()->StopCacheLearningPhase();
9307 }
9308 } else {
9309 Error("StopCacheLearningPhase", "No tree is available. Could not stop cache learning phase");
9310 return -1;
9311 }
9312
9313 TFile *f = GetCurrentFile();
9314 if (!f) {
9315 Error("StopCacheLearningPhase", "No file is available. Could not stop cache learning phase");
9316 return -1;
9317 }
9319 if (!tc) {
9320 Error("StopCacheLearningPhase", "No cache is available. Could not stop learning phase");
9321 return -1;
9322 }
9323 tc->StopLearningPhase();
9324 return 0;
9325}
9326
9327////////////////////////////////////////////////////////////////////////////////
9328/// Set the fTree member for all branches and sub branches.
9330static void TBranch__SetTree(TTree *tree, TObjArray &branches)
9331{
9332 Int_t nb = branches.GetEntriesFast();
9333 for (Int_t i = 0; i < nb; ++i) {
9334 TBranch* br = (TBranch*) branches.UncheckedAt(i);
9335 br->SetTree(tree);
9336
9337 Int_t writeBasket = br->GetWriteBasket();
9338 for (Int_t j = writeBasket; j >= 0; --j) {
9339 TBasket *bk = (TBasket*)br->GetListOfBaskets()->UncheckedAt(j);
9340 if (bk) {
9341 tree->IncrementTotalBuffers(bk->GetBufferSize());
9342 }
9343 }
9344
9346 }
9347}
9348
9349////////////////////////////////////////////////////////////////////////////////
9350/// Set the fTree member for all friend elements.
9353{
9354 if (frlist) {
9355 TObjLink *lnk = frlist->FirstLink();
9356 while (lnk) {
9357 TFriendElement *elem = (TFriendElement*)lnk->GetObject();
9358 elem->fParentTree = tree;
9359 lnk = lnk->Next();
9360 }
9361 }
9362}
9363
9364////////////////////////////////////////////////////////////////////////////////
9365/// Stream a class object.
9366
9367void TTree::Streamer(TBuffer& b)
9368{
9369 if (b.IsReading()) {
9370 UInt_t R__s, R__c;
9371 if (fDirectory) {
9372 fDirectory->Remove(this);
9373 //delete the file cache if it points to this Tree
9376 }
9377 fDirectory = 0;
9380 Version_t R__v = b.ReadVersion(&R__s, &R__c);
9381 if (R__v > 4) {
9382 b.ReadClassBuffer(TTree::Class(), this, R__v, R__s, R__c);
9383
9384 fBranches.SetOwner(kTRUE); // True needed only for R__v < 19 and most R__v == 19
9385
9386 if (fBranchRef) fBranchRef->SetTree(this);
9389
9390 if (fTreeIndex) {
9391 fTreeIndex->SetTree(this);
9392 }
9393 if (fIndex.fN) {
9394 Warning("Streamer", "Old style index in this tree is deleted. Rebuild the index via TTree::BuildIndex");
9395 fIndex.Set(0);
9396 fIndexValues.Set(0);
9397 }
9398 if (fEstimate <= 10000) {
9399 fEstimate = 1000000;
9400 }
9401
9402 if (fNClusterRange) {
9403 // The I/O allocated just enough memory to hold the
9404 // current set of ranges.
9406 }
9407 if (GetCacheAutoSize() != 0) {
9408 // a cache will be automatically created.
9409 // No need for TTreePlayer::Process to enable the cache
9410 fCacheSize = 0;
9411 } else if (fAutoFlush < 0) {
9412 // If there is no autoflush set, let's keep the cache completely
9413 // disable by default for now.
9415 } else if (fAutoFlush != 0) {
9416 // Estimate the cluster size.
9417 // This will allow TTree::Process to enable the cache.
9418 Long64_t zipBytes = GetZipBytes();
9419 Long64_t totBytes = GetTotBytes();
9420 if (zipBytes != 0) {
9421 fCacheSize = fAutoFlush*(zipBytes/fEntries);
9422 } else if (totBytes != 0) {
9423 fCacheSize = fAutoFlush*(totBytes/fEntries);
9424 } else {
9425 fCacheSize = 30000000;
9426 }
9427 if (fCacheSize >= (INT_MAX / 4)) {
9428 fCacheSize = INT_MAX / 4;
9429 } else if (fCacheSize == 0) {
9430 fCacheSize = 30000000;
9431 }
9432 } else {
9433 fCacheSize = 0;
9434 }
9436 return;
9437 }
9438 //====process old versions before automatic schema evolution
9439 Stat_t djunk;
9440 Int_t ijunk;
9441 TNamed::Streamer(b);
9442 TAttLine::Streamer(b);
9443 TAttFill::Streamer(b);
9444 TAttMarker::Streamer(b);
9445 b >> fScanField;
9446 b >> ijunk; fMaxEntryLoop = (Long64_t)ijunk;
9447 b >> ijunk; fMaxVirtualSize = (Long64_t)ijunk;
9448 b >> djunk; fEntries = (Long64_t)djunk;
9449 b >> djunk; fTotBytes = (Long64_t)djunk;
9450 b >> djunk; fZipBytes = (Long64_t)djunk;
9451 b >> ijunk; fAutoSave = (Long64_t)ijunk;
9452 b >> ijunk; fEstimate = (Long64_t)ijunk;
9453 if (fEstimate <= 10000) fEstimate = 1000000;
9454 fBranches.Streamer(b);
9455 if (fBranchRef) fBranchRef->SetTree(this);
9457 fLeaves.Streamer(b);
9459 if (R__v > 1) fIndexValues.Streamer(b);
9460 if (R__v > 2) fIndex.Streamer(b);
9461 if (R__v > 3) {
9462 TList OldInfoList;
9463 OldInfoList.Streamer(b);
9464 OldInfoList.Delete();
9465 }
9466 fNClusterRange = 0;
9469 b.CheckByteCount(R__s, R__c, TTree::IsA());
9470 //====end of old versions
9471 } else {
9472 if (fBranchRef) {
9473 fBranchRef->Clear();
9474 }
9476 if (table) TRefTable::SetRefTable(0);
9477
9478 b.WriteClassBuffer(TTree::Class(), this);
9479
9480 if (table) TRefTable::SetRefTable(table);
9481 }
9482}
9483
9484////////////////////////////////////////////////////////////////////////////////
9485/// Unbinned fit of one or more variable(s) from a tree.
9486///
9487/// funcname is a TF1 function.
9488///
9489/// See TTree::Draw for explanations of the other parameters.
9490///
9491/// Fit the variable varexp using the function funcname using the
9492/// selection cuts given by selection.
9493///
9494/// The list of fit options is given in parameter option.
9495///
9496/// - option = "Q" Quiet mode (minimum printing)
9497/// - option = "V" Verbose mode (default is between Q and V)
9498/// - option = "E" Perform better Errors estimation using Minos technique
9499/// - option = "M" More. Improve fit results
9500///
9501/// You can specify boundary limits for some or all parameters via
9502/// ~~~ {.cpp}
9503/// func->SetParLimits(p_number, parmin, parmax);
9504/// ~~~
9505/// if parmin>=parmax, the parameter is fixed
9506///
9507/// Note that you are not forced to fix the limits for all parameters.
9508/// For example, if you fit a function with 6 parameters, you can do:
9509/// ~~~ {.cpp}
9510/// func->SetParameters(0,3.1,1.e-6,0.1,-8,100);
9511/// func->SetParLimits(4,-10,-4);
9512/// func->SetParLimits(5, 1,1);
9513/// ~~~
9514/// With this setup:
9515///
9516/// - Parameters 0->3 can vary freely
9517/// - Parameter 4 has boundaries [-10,-4] with initial value -8
9518/// - Parameter 5 is fixed to 100.
9519///
9520/// For the fit to be meaningful, the function must be self-normalized.
9521///
9522/// i.e. It must have the same integral regardless of the parameter
9523/// settings. Otherwise the fit will effectively just maximize the
9524/// area.
9525///
9526/// It is mandatory to have a normalization variable
9527/// which is fixed for the fit. e.g.
9528/// ~~~ {.cpp}
9529/// TF1* f1 = new TF1("f1", "gaus(0)/sqrt(2*3.14159)/[2]", 0, 5);
9530/// f1->SetParameters(1, 3.1, 0.01);
9531/// f1->SetParLimits(0, 1, 1); // fix the normalization parameter to 1
9532/// data->UnbinnedFit("f1", "jpsimass", "jpsipt>3.0");
9533/// ~~~
9534/// 1, 2 and 3 Dimensional fits are supported. See also TTree::Fit
9535///
9536/// Return status:
9537///
9538/// - The function return the status of the fit in the following form
9539/// fitResult = migradResult + 10*minosResult + 100*hesseResult + 1000*improveResult
9540/// - The fitResult is 0 is the fit is OK.
9541/// - The fitResult is negative in case of an error not connected with the fit.
9542/// - The number of entries used in the fit can be obtained via mytree.GetSelectedRows();
9543/// - If the number of selected entries is null the function returns -1
9545Int_t TTree::UnbinnedFit(const char* funcname, const char* varexp, const char* selection, Option_t* option, Long64_t nentries, Long64_t firstentry)
9546{
9547 GetPlayer();
9548 if (fPlayer) {
9549 return fPlayer->UnbinnedFit(funcname, varexp, selection, option, nentries, firstentry);
9550 }
9551 return -1;
9552}
9553
9554////////////////////////////////////////////////////////////////////////////////
9555/// Replace current attributes by current style.
9558{
9559 if (gStyle->IsReading()) {
9568 } else {
9577 }
9578}
9579
9580////////////////////////////////////////////////////////////////////////////////
9581/// Write this object to the current directory. For more see TObject::Write
9582/// If option & kFlushBasket, call FlushBasket before writing the tree.
9584Int_t TTree::Write(const char *name, Int_t option, Int_t bufsize) const
9585{
9587 if (R__unlikely(option & kOnlyPrepStep))
9588 return 0;
9589 return TObject::Write(name, option, bufsize);
9590}
9591
9592////////////////////////////////////////////////////////////////////////////////
9593/// Write this object to the current directory. For more see TObject::Write
9594/// If option & kFlushBasket, call FlushBasket before writing the tree.
9596Int_t TTree::Write(const char *name, Int_t option, Int_t bufsize)
9597{
9598 return ((const TTree*)this)->Write(name, option, bufsize);
9599}
9600
9601////////////////////////////////////////////////////////////////////////////////
9602/// \class TTreeFriendLeafIter
9603///
9604/// Iterator on all the leaves in a TTree and its friend
9605
9607
9608////////////////////////////////////////////////////////////////////////////////
9609/// Create a new iterator. By default the iteration direction
9610/// is kIterForward. To go backward use kIterBackward.
9613: fTree(const_cast<TTree*>(tree))
9614, fLeafIter(0)
9615, fTreeIter(0)
9616, fDirection(dir)
9617{
9618}
9619
9620////////////////////////////////////////////////////////////////////////////////
9621/// Copy constructor. Does NOT copy the 'cursor' location!
9624: TIterator(iter)
9625, fTree(iter.fTree)
9626, fLeafIter(0)
9627, fTreeIter(0)
9628, fDirection(iter.fDirection)
9629{
9630}
9631
9632////////////////////////////////////////////////////////////////////////////////
9633/// Overridden assignment operator. Does NOT copy the 'cursor' location!
9636{
9637 if (this != &rhs && rhs.IsA() == TTreeFriendLeafIter::Class()) {
9638 const TTreeFriendLeafIter &rhs1 = (const TTreeFriendLeafIter &)rhs;
9639 fDirection = rhs1.fDirection;
9640 }
9641 return *this;
9642}
9643
9644////////////////////////////////////////////////////////////////////////////////
9645/// Overridden assignment operator. Does NOT copy the 'cursor' location!
9648{
9649 if (this != &rhs) {
9650 fDirection = rhs.fDirection;
9651 }
9652 return *this;
9653}
9654
9655////////////////////////////////////////////////////////////////////////////////
9656/// Go the next friend element
9659{
9660 if (!fTree) return 0;
9661
9662 TObject * next;
9663 TTree * nextTree;
9664
9665 if (!fLeafIter) {
9666 TObjArray *list = fTree->GetListOfLeaves();
9667 if (!list) return 0; // Can happen with an empty chain.
9669 if (!fLeafIter) return 0;
9670 }
9671
9672 next = fLeafIter->Next();
9673 if (!next) {
9674 if (!fTreeIter) {
9676 if (!list) return next;
9678 if (!fTreeIter) return 0;
9679 }
9680 TFriendElement * nextFriend = (TFriendElement*) fTreeIter->Next();
9681 ///nextTree = (TTree*)fTreeIter->Next();
9682 if (nextFriend) {
9683 nextTree = const_cast<TTree*>(nextFriend->GetTree());
9684 if (!nextTree) return Next();
9687 if (!fLeafIter) return 0;
9688 next = fLeafIter->Next();
9689 }
9690 }
9691 return next;
9692}
9693
9694////////////////////////////////////////////////////////////////////////////////
9695/// Returns the object option stored in the list.
9698{
9699 if (fLeafIter) return fLeafIter->GetOption();
9700 return "";
9701}
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:113
int Int_t
Definition: RtypesCore.h:43
short Version_t
Definition: RtypesCore.h:63
unsigned char UChar_t
Definition: RtypesCore.h:36
unsigned int UInt_t
Definition: RtypesCore.h:44
const Bool_t kFALSE
Definition: RtypesCore.h:90
long Long_t
Definition: RtypesCore.h:52
double Double_t
Definition: RtypesCore.h:57
double Stat_t
Definition: RtypesCore.h:75
R__EXTERN Int_t gDebug
Definition: RtypesCore.h:117
long long Long64_t
Definition: RtypesCore.h:71
unsigned long long ULong64_t
Definition: RtypesCore.h:72
float Float_t
Definition: RtypesCore.h:55
const Bool_t kTRUE
Definition: RtypesCore.h:89
const char Option_t
Definition: RtypesCore.h:64
#define ClassImp(name)
Definition: Rtypes.h:361
const Int_t kDoNotProcess
Definition: TBranch.h:58
EDataType
Definition: TDataType.h:28
@ kNoType_t
Definition: TDataType.h:33
@ kFloat_t
Definition: TDataType.h:31
@ kULong64_t
Definition: TDataType.h:32
@ kInt_t
Definition: TDataType.h:30
@ kchar
Definition: TDataType.h:31
@ kLong_t
Definition: TDataType.h:30
@ kDouble32_t
Definition: TDataType.h:31
@ kShort_t
Definition: TDataType.h:29
@ kBool_t
Definition: TDataType.h:32
@ kBits
Definition: TDataType.h:34
@ kULong_t
Definition: TDataType.h:30
@ kLong64_t
Definition: TDataType.h:32
@ kUShort_t
Definition: TDataType.h:29
@ kDouble_t
Definition: TDataType.h:31
@ kCharStar
Definition: TDataType.h:34
@ kChar_t
Definition: TDataType.h:29
@ kUChar_t
Definition: TDataType.h:29
@ kCounter
Definition: TDataType.h:34
@ kUInt_t
Definition: TDataType.h:30
@ kFloat16_t
Definition: TDataType.h:33
@ kOther_t
Definition: TDataType.h:32
#define gDirectory
Definition: TDirectory.h:229
R__EXTERN TEnv * gEnv
Definition: TEnv.h:171
#define R__ASSERT(e)
Definition: TError.h:96
void Error(const char *location, const char *msgfmt,...)
#define N
static unsigned int total
char name[80]
Definition: TGX11.cxx:109
int nentries
Definition: THbookFile.cxx:89
R__EXTERN TInterpreter * gCling
Definition: TInterpreter.h:557
R__EXTERN TVirtualMutex * gROOTMutex
Definition: TROOT.h:59
#define gROOT
Definition: TROOT.h:406
void Printf(const char *fmt,...)
R__EXTERN TStyle * gStyle
Definition: TStyle.h:410
typedef void((*Func_t)())
R__EXTERN TSystem * gSystem
Definition: TSystem.h:556
constexpr Int_t kNEntriesResort
Definition: TTree.cxx:435
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:4714
static char DataTypeToChar(EDataType datatype)
Definition: TTree.cxx:447
void TFriendElement__SetTree(TTree *tree, TList *frlist)
Set the fTree member for all friend elements.
Definition: TTree.cxx:9351
bool CheckReshuffling(TTree &mainTree, TTree &friendTree)
Definition: TTree.cxx:1225
static void TBranch__SetTree(TTree *tree, TObjArray &branches)
Set the fTree member for all branches and sub branches.
Definition: TTree.cxx:9329
constexpr Float_t kNEntriesResortInv
Definition: TTree.cxx:436
#define R__LOCKGUARD(mutex)
#define gPad
Definition: TVirtualPad.h:287
#define snprintf
Definition: civetweb.c:1540
TRangeStaticCast is an adaptater class that allows the typed iteration through a TCollection.
Definition: TCollection.h:382
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:69
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:173
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:23
A TTree is a list of TBranches.
Definition: TBranch.h:91
virtual TLeaf * GetLeaf(const char *name) const
Return pointer to the 1st Leaf named name in thisBranch.
Definition: TBranch.cxx:1919
virtual void SetupAddresses()
If the branch address is not set, we set all addresses starting with the top level parent branch.
Definition: TBranch.cxx:3158
virtual void ResetAddress()
Reset the address of the branch.
Definition: TBranch.cxx:2515
virtual Long64_t GetBasketSeek(Int_t basket) const
Return address of basket in the file.
Definition: TBranch.cxx:1290
virtual char * GetAddress() const
Definition: TBranch.h:210
void SetCompressionSettings(Int_t settings=ROOT::RCompressionSetting::EDefaults::kUseCompiledDefault)
Set compression settings.
Definition: TBranch.cxx:2669
TTree * GetTree() const
Definition: TBranch.h:250
virtual TString GetFullName() const
Return the 'full' name of the branch.
Definition: TBranch.cxx:1903
Int_t GetWriteBasket() const
Definition: TBranch.h:236
virtual void DropBaskets(Option_t *option="")
Loop on all branch baskets.
Definition: TBranch.cxx:745
TObjArray * GetListOfBranches()
Definition: TBranch.h:244
virtual void SetTree(TTree *tree)
Definition: TBranch.h:285
virtual void SetEntryOffsetLen(Int_t len, Bool_t updateSubBranches=kFALSE)
Update the default value for the branch's fEntryOffsetLen if and only if it was already non zero (and...
Definition: TBranch.cxx:2685
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:1591
static void ResetCount()
Static function resetting fgCount.
Definition: TBranch.cxx:2538
virtual void SetObject(void *objadd)
Set object this branch is pointing to.
Definition: TBranch.cxx:2800
Int_t FlushBaskets()
Flush to disk all the baskets of this branch and any of subbranches.
Definition: TBranch.cxx:1124
virtual void SetAddress(void *add)
Set address of this branch.
Definition: TBranch.cxx:2546
Int_t GetNleaves() const
Definition: TBranch.h:247
TObjArray * GetListOfBaskets()
Definition: TBranch.h:243
Long64_t GetEntries() const
Definition: TBranch.h:249
virtual void UpdateFile()
Refresh the value of fDirectory (i.e.
Definition: TBranch.cxx:3168
Int_t GetReadBasket() const
Definition: TBranch.h:234
virtual void Print(Option_t *option="") const
Print TBranch parameters.
Definition: TBranch.cxx:2205
Int_t GetMaxBaskets() const
Definition: TBranch.h:246
virtual TFile * GetFile(Int_t mode=0)
Return pointer to the file where branch buffers reside, returns 0 in case branch buffers reside in th...
Definition: TBranch.cxx:1738
virtual void KeepCircular(Long64_t maxEntries)
keep a maximum of fMaxEntries in memory
Definition: TBranch.cxx:2147
virtual void ResetAfterMerge(TFileMergeInfo *)
Reset a Branch.
Definition: TBranch.cxx:2462
virtual Bool_t GetMakeClass() const
Return whether this branch is in a mode where the object are decomposed or not (Also known as MakeCla...
Definition: TBranch.cxx:1981
virtual TBranch * FindBranch(const char *name)
Find the immediate sub-branch with passed name.
Definition: TBranch.cxx:1023
virtual Int_t LoadBaskets()
Baskets associated to this branch are forced to be in memory.
Definition: TBranch.cxx:2173
void SetIOFeatures(TIOFeatures &features)
Definition: TBranch.h:281
Long64_t GetTotBytes(Option_t *option="") const
Return total number of bytes in the branch (excluding current buffer) if option ="*" includes all sub...
Definition: TBranch.cxx:2084
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:2791
virtual void SetFile(TFile *file=0)
Set file where this branch writes/reads its buffers.
Definition: TBranch.cxx:2727
virtual void SetOffset(Int_t offset=0)
Definition: TBranch.h:283
virtual Int_t GetExpectedType(TClass *&clptr, EDataType &type)
Fill expectedClass and expectedType with information on the data type of the object/values contained ...
Definition: TBranch.cxx:1719
virtual Int_t GetBasketSize() const
Definition: TBranch.h:215
Long64_t GetZipBytes(Option_t *option="") const
Return total number of zip bytes in the branch if option ="*" includes all sub-branches of this branc...
Definition: TBranch.cxx:2102
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:2593
virtual void Refresh(TBranch *b)
Refresh this branch using new information in b This function is called by TTree::Refresh.
Definition: TBranch.cxx:2372
TObjArray * GetListOfLeaves()
Definition: TBranch.h:245
Int_t Fill()
Definition: TBranch.h:203
virtual void Reset(Option_t *option="")
Reset a Branch.
Definition: TBranch.cxx:2421
TBranch * GetMother() const
Get our top-level parent branch in the tree.
Definition: TBranch.cxx:1991
virtual Int_t FillImpl(ROOT::Internal::TBranchIMTHelper *)
Loop on all leaves of this branch to fill Basket buffer.
Definition: TBranch.cxx:844
Int_t GetEntryOffsetLen() const
Definition: TBranch.h:225
Using a TBrowser one can browse all ROOT objects.
Definition: TBrowser.h:37
The concrete implementation of TBuffer for writing/reading to/from a ROOT file or socket.
Definition: TBufferFile.h:46
Buffer base class used for serializing objects.
Definition: TBuffer.h:42
void Expand(Int_t newsize, Bool_t copy=kTRUE)
Expand (or shrink) the I/O buffer to newsize bytes.
Definition: TBuffer.cxx:223
Int_t BufferSize() const
Definition: TBuffer.h:97
@ kWrite
Definition: TBuffer.h:72
@ kRead
Definition: TBuffer.h:72
TClass instances represent classes, structs and namespaces in the ROOT type system.
Definition: TClass.h:80
Bool_t CanSplit() const
Return true if the data member of this TClass can be saved separately.
Definition: TClass.cxx:2300
ROOT::ESTLType GetCollectionType() const
Return the 'type' of the STL the TClass is representing.
Definition: TClass.cxx:2866
void * New(ENewType defConstructor=kClassNew, Bool_t quiet=kFALSE) const
Return a pointer to a newly allocated object of this class.
Definition: TClass.cxx:4941
Bool_t HasDataMemberInfo() const
Definition: TClass.h:404
void BuildRealData(void *pointer=0, Bool_t isTransient=kFALSE)
Build a full list of persistent data members.
Definition: TClass.cxx:2011
void Destructor(void *obj, Bool_t dtorOnly=kFALSE)
Explicitly call destructor for object.
Definition: TClass.cxx:5363
const std::type_info * GetTypeInfo() const
Definition: TClass.h:493
TList * GetListOfDataMembers(Bool_t load=kTRUE)
Return list containing the TDataMembers of a class.
Definition: TClass.cxx:3738
TList * GetListOfRealData() const
Definition: TClass.h:450
Bool_t CanIgnoreTObjectStreamer()
Definition: TClass.h:391
const ROOT::Detail::TSchemaRuleSet * GetSchemaRules() const
Return the set of the schema rules if any.
Definition: TClass.cxx:1912
TList * GetListOfBases()
Return list containing the TBaseClass(es) of a class.
Definition: TClass.cxx:3604
Bool_t IsLoaded() const
Return true if the shared library of this class is currently in the a process's memory.
Definition: TClass.cxx:5875
Bool_t IsTObject() const
Return kTRUE is the class inherits from TObject.
Definition: TClass.cxx:5901
TVirtualStreamerInfo * GetStreamerInfo(Int_t version=0, Bool_t isTransient=kFALSE) const
returns a pointer to the TVirtualStreamerInfo object for version If the object does not exist,...
Definition: TClass.cxx:4562
TVirtualCollectionProxy * GetCollectionProxy() const
Return the proxy describing the collection (if any).
Definition: TClass.cxx:2877
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:7007
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:7114
Version_t GetClassVersion() const
Definition: TClass.h:417
Bool_t InheritsFrom(const char *cl) const
Return kTRUE if this class inherits from a class with name "classname".
Definition: TClass.cxx:4837
TClass * GetActualClass(const void *object) const
Return a pointer the the real class of the object.
Definition: TClass.cxx:2588
@ kHasCustomStreamerMember
Definition: TClass.h:105
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:2948
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:91
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:76
const char * GetTypeName() const
Get type of data member, e,g.: "class TDirectory*" -> "TDirectory".
const char * GetArrayIndex() const
If the data member is pointer and has a valid array size in its comments GetArrayIndex returns a stri...
const char * GetFullTypeName() const
Get full type description of data member, e,g.: "class TDirectory*".
Basic data type descriptor (datatype information is obtained from CINT).
Definition: TDataType.h:44
Int_t GetType() const
Definition: TDataType.h:68
TString GetTypeName()
Get basic type of typedef, e,g.
Definition: TDataType.cxx:149
void Append(TObject *obj, Bool_t replace=kFALSE) override
Append object to this directory.
Small helper to keep current directory context.
Definition: TDirectory.h:47
Describe directory structure in memory.
Definition: TDirectory.h:40
virtual TList * GetList() const
Definition: TDirectory.h:165
virtual void Append(TObject *obj, Bool_t replace=kFALSE)
Append object to this directory.
Definition: TDirectory.cxx:191
virtual Int_t WriteTObject(const TObject *obj, const char *name=nullptr, Option_t *="", Int_t=0)
See TDirectoryFile::WriteTObject for details.
virtual TFile * GetFile() const
Definition: TDirectory.h:163
virtual Int_t ReadKeys(Bool_t=kTRUE)
Definition: TDirectory.h:190
virtual Bool_t IsWritable() const
Definition: TDirectory.h:179
virtual TKey * GetKey(const char *, Short_t=9999) const
Definition: TDirectory.h:164
virtual Int_t ReadTObject(TObject *, const char *)
Definition: TDirectory.h:191
virtual void SaveSelf(Bool_t=kFALSE)
Definition: TDirectory.h:197
virtual TList * GetListOfKeys() const
Definition: TDirectory.h:166
void GetObject(const char *namecycle, T *&ptr)
Definition: TDirectory.h:155
virtual TObject * Remove(TObject *)
Remove an object from the in-memory list.
virtual Bool_t cd(const char *path=nullptr)
Change current directory to "this" directory.
Definition: TDirectory.cxx:498
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:560
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:657
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:223
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:53
Int_t GetCompressionSettings() const
Definition: TFile.h:398
virtual Long64_t GetEND() const
Definition: TFile.h:222
@ kDoNotDisconnect
Definition: TFile.h:70
virtual void Flush()
Synchronize a file's in-memory and on-disk states.
Definition: TFile.cxx:1055
virtual void MakeFree(Long64_t first, Long64_t last)
Mark unused bytes on the file.
Definition: TFile.cxx:1394
static TFile * Open(const char *name, Option_t *option="", const char *ftitle="", Int_t compress=ROOT::RCompressionSetting::EDefaults::kUseCompiledDefault, Int_t netopt=0)
Create / open a file.
Definition: TFile.cxx:3942
virtual void SetCacheRead(TFileCacheRead *cache, TObject *tree=0, ECacheAction action=kDisconnect)
Set a pointer to the read cache.
Definition: TFile.cxx:2226
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:1213
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.
Bool_t IsUpdated() const
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:28
virtual void Delete(Option_t *option="")
Delete an object from the file.
Definition: TKey.cxx:538
Int_t GetKeylen() const
Definition: TKey.h:85
Int_t GetNbytes() const
Definition: TKey.h:87
virtual const char * GetClassName() const
Definition: TKey.h:76
A TLeaf describes individual elements of a TBranch See TBranch structure in TTree.
Definition: TLeaf.h:49
virtual Double_t GetValue(Int_t i=0) const
Definition: TLeaf.h:174
virtual void * GetValuePointer() const
Definition: TLeaf.h:129
virtual Int_t GetLenType() const
Definition: TLeaf.h:124
virtual void ReadValue(std::istream &, Char_t=' ')
Definition: TLeaf.h:147
virtual Int_t GetMaximum() const
Definition: TLeaf.h:125
virtual Int_t GetLen() const
Return the number of effective elements of this leaf, for the current entry.
Definition: TLeaf.cxx:382
virtual TLeaf * GetLeafCount() const
If this leaf stores a variable-sized array or a multi-dimensional array whose last dimension has vari...
Definition: TLeaf.h:112
virtual Bool_t IncludeRange(TLeaf *)
Definition: TLeaf.h:137
virtual void SetAddress(void *add=0)
Definition: TLeaf.h:176
TBranch * GetBranch() const
Definition: TLeaf.h:107
@ kNewValue
Set if we own the value buffer and so must delete it ourselves.
Definition: TLeaf.h:88
@ kIndirectAddress
Data member is a pointer to an array of basic types.
Definition: TLeaf.h:87
virtual TString GetFullName() const
Return the full name (including the parent's branch names) of the leaf.
Definition: TLeaf.cxx:202
virtual Int_t GetOffset() const
Definition: TLeaf.h:128
virtual void PrintValue(Int_t i=0) const
Definition: TLeaf.h:175
A doubly linked list.
Definition: TList.h:44
virtual void Add(TObject *obj)
Definition: TList.h:87
virtual TObject * Remove(TObject *obj)
Remove object from the list.
Definition: TList.cxx:821
virtual TObject * FindObject(const char *name) const
Find an object in this list using its name.
Definition: TList.cxx:577
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:356
virtual void RecursiveRemove(TObject *obj)
Remove object from this collection and recursively remove the object from all other objects (and coll...
Definition: TList.cxx:763
virtual void Delete(Option_t *option="")
Remove all objects from the list AND delete all heap based objects.
Definition: TList.cxx:469
virtual void Clear(Option_t *option="")
Remove all objects from the list.
Definition: TList.cxx:401
A TMemFile is like a normal TFile except that it reads and writes only from memory.
Definition: TMemFile.h:19
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:565
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:506
virtual void Compress()
Remove empty slots from array.
Definition: TObjArray.cxx:334
Int_t GetEntries() const
Return the number of objects in array (i.e.
Definition: TObjArray.cxx:523
virtual void Clear(Option_t *option="")
Remove all objects from the array.
Definition: TObjArray.cxx:321
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:356
virtual TObject * FindObject(const char *name) const
Find an object in this collection using its name.
Definition: TObjArray.cxx:415
TIterator * MakeIterator(Bool_t dir=kIterForward) const
Returns an array iterator.
Definition: TObjArray.cxx:649
virtual TObject * RemoveAt(Int_t idx)
Remove object at index idx.
Definition: TObjArray.cxx:694
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:796
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:187
@ kBitMask
Definition: TObject.h:82
virtual const char * ClassName() const
Returns name of class to which the object belongs.
Definition: TObject.cxx:128
virtual void Warning(const char *method, const char *msgfmt,...) const
Issue warning message.
Definition: TObject.cxx:877
R__ALWAYS_INLINE Bool_t IsZombie() const
Definition: TObject.h:149
@ kOnlyPrepStep
Used to request that the class specific implementation of TObject::Write just prepare the objects to ...
Definition: TObject.h:102
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:891
virtual void Fatal(const char *method, const char *msgfmt,...) const
Issue fatal error message.
Definition: TObject.cxx:919
virtual const char * GetTitle() const
Returns title of object.
Definition: TObject.cxx:401
void ResetBit(UInt_t f)
Definition: TObject.h:186
@ 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:865
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:46
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:360
Color_t GetHistLineColor() const
Definition: TStyle.h:222
Bool_t IsReading() const
Definition: TStyle.h:280
void SetHistLineStyle(Style_t styl=0)
Definition: TStyle.h:363
Style_t GetHistFillStyle() const
Definition: TStyle.h:223
Color_t GetHistFillColor() const
Definition: TStyle.h:221
void SetHistLineColor(Color_t color=1)
Definition: TStyle.h:361
Style_t GetHistLineStyle() const
Definition: TStyle.h:224
void SetHistFillStyle(Style_t styl=0)
Definition: TStyle.h:362
Width_t GetHistLineWidth() const
Definition: TStyle.h:225
void SetHistLineWidth(Width_t width=1)
Definition: TStyle.h:364
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:1658
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:1291
A TTreeCache which exploits parallelized decompression of its own content.
static Bool_t IsParallelUnzip()
Static function that tells wether the multithreading unzipping is activated.
A cache to speed-up the reading of ROOT datasets.
Definition: TTreeCache.h:35
virtual Int_t AddBranch(TBranch *b, Bool_t subgbranches=kFALSE)
Add a branch to the list of branches to be stored in the cache this function is called by the user vi...
Definition: TTreeCache.cxx:368
virtual Int_t SetBufferSize(Int_t buffersize)
Change the underlying buffer size of the cache.
static void SetLearnEntries(Int_t n=10)
Static function to set the number of entries to be used in learning mode The default value for n is 1...
TTree * GetTree() const
Definition: TTreeCache.h:152
virtual void SetEntryRange(Long64_t emin, Long64_t emax)
Set the minimum and maximum entry number to be processed this information helps to optimize the numbe...
Bool_t IsAutoCreated() const
Definition: TTreeCache.h:153
void SetAutoCreated(Bool_t val)
Definition: TTreeCache.h:167
virtual Int_t DropBranch(TBranch *b, Bool_t subbranches=kFALSE)
Remove a branch to the list of branches to be stored in the cache this function is called by TBranch:...
Definition: TTreeCache.cxx:533
virtual void StopLearningPhase()
This is the counterpart of StartLearningPhase() and can be used to stop the learning phase.
virtual void Print(Option_t *option="") const
Print cache statistics.
Class implementing or helping the various TTree cloning method.
Definition: TTreeCloner.h:31
Bool_t Exec()
Execute the cloning.
Bool_t IsValid()
Definition: TTreeCloner.h:120
const char * GetWarning() const
Definition: TTreeCloner.h:117
void SetCacheSize(Int_t size)
Set the TFile cache size to be used.
Bool_t NeedConversion()
Definition: TTreeCloner.h:121
Iterator on all the leaves in a TTree and its friend.
Definition: TTree.h:662
TObject * Next()
Go the next friend element.
Definition: TTree.cxx:9657
TTree * fTree
tree being iterated
Definition: TTree.h:665
Option_t * GetOption() const
Returns the object option stored in the list.
Definition: TTree.cxx:9696
TIterator & operator=(const TIterator &rhs)
Overridden assignment operator. Does NOT copy the 'cursor' location!
Definition: TTree.cxx:9634
TIterator * fLeafIter
current leaf sub-iterator.
Definition: TTree.h:666
TIterator * fTreeIter
current tree sub-iterator.
Definition: TTree.h:667
Bool_t fDirection
iteration direction
Definition: TTree.h:668
Helper class to iterate over cluster of baskets.
Definition: TTree.h:265
Long64_t GetEstimatedClusterSize()
Estimate the cluster size.
Definition: TTree.cxx:596
Long64_t Previous()
Move on to the previous cluster and return the starting entry of this previous cluster.
Definition: TTree.cxx:679
Long64_t fNextEntry
Definition: TTree.h:270
Long64_t Next()
Move on to the next cluster and return the starting entry of this next cluster.
Definition: TTree.cxx:635
Long64_t GetNextEntry()
Definition: TTree.h:302
Long64_t fStartEntry
Definition: TTree.h:269
TClusterIterator(TTree *tree, Long64_t firstEntry)
Regular constructor.
Definition: TTree.cxx:545
Helper class to prevent infinite recursion in the usage of TTree Friends.
Definition: TTree.h:183
TFriendLock & operator=(const TFriendLock &)
Assignment operator.
Definition: TTree.cxx:515
TFriendLock(const TFriendLock &)
Copy constructor.
Definition: TTree.cxx:505
UInt_t fMethodBit
Definition: TTree.h:187
TTree * fTree
Definition: TTree.h:186
~TFriendLock()
Restore the state of tree the same as before we set the lock.
Definition: TTree.cxx:528
Bool_t fPrevious
Definition: TTree.h:188
A TTree represents a columnar dataset.
Definition: TTree.h:78
virtual Int_t Fill()
Fill all branches.
Definition: TTree.cxx:4524
virtual TFriendElement * AddFriend(const char *treename, const char *filename="")
Add a TFriendElement to the list of friends.
Definition: TTree.cxx:1316
TBranchRef * fBranchRef
Branch supporting the TRefTable (if any)
Definition: TTree.h:132
virtual Int_t AddBranchToCache(const char *bname, Bool_t subbranches=kFALSE)
Add branch with name bname to the Tree cache.
Definition: TTree.cxx:1044
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:4762
virtual TBranch * GetBranch(const char *name)
Return pointer to the branch with the given name in this tree or its friends.
Definition: TTree.cxx:5209
static Int_t GetBranchStyle()
Static function returning the current branch style.
Definition: TTree.cxx:5309
TList * fFriends
pointer to list of friend elements
Definition: TTree.h:126
UInt_t fFriendLockStatus
! Record which method is locking the friend recursion
Definition: TTree.h:133
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:6003
Long64_t fTotBytes
Total number of bytes in all branches before compression.
Definition: TTree.h:85
Int_t fMaxClusterRange
! Memory allocated for the cluster range.
Definition: TTree.h:95
virtual void Show(Long64_t entry=-1, Int_t lenmax=20)
Print values of all active leaves for entry.
Definition: TTree.cxx:9206
TEventList * fEventList
! Pointer to event selection list (if one)
Definition: TTree.h:121
virtual Long64_t GetAutoSave() const
Definition: TTree.h:442
virtual Int_t StopCacheLearningPhase()
Stop the cache learning phase.
Definition: TTree.cxx:9295
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:140
virtual void SetCircular(Long64_t maxEntries)
Enable/Disable circularity for this tree.
Definition: TTree.cxx:8739
Long64_t fSavedBytes
Number of autosaved bytes.
Definition: TTree.h:87
virtual TClusterIterator GetClusterIterator(Long64_t firstentry)
Return an iterator over the cluster of baskets starting at firstentry.
Definition: TTree.cxx:5371
virtual void ResetBranchAddress(TBranch *)
Tell all of our branches to set their addresses to zero.
Definition: TTree.cxx:7959
char GetNewlineValue(std::istream &inputStream)
Determine which newline this file is using.
Definition: TTree.cxx:7486
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:2825
TIOFeatures fIOFeatures
IO features to define for newly-written baskets and branches.
Definition: TTree.h:113
virtual Long64_t GetEntryNumberWithIndex(Long64_t major, Long64_t minor=0) const
Return entry number corresponding to major and minor number.
Definition: TTree.cxx:5815
Long64_t fDebugMin
! First entry number to debug
Definition: TTree.h:111
virtual Long64_t SetEntries(Long64_t n=-1)
Change number of entries in the tree.
Definition: TTree.cxx:8858
virtual TObjArray * GetListOfLeaves()
Definition: TTree.h:483
Bool_t fCacheDoClusterPrefetch
! true if cache is prefetching whole clusters
Definition: TTree.h:136
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:2055
virtual TBranch * BranchRef()
Build the optional branch supporting the TRefTable.
Definition: TTree.cxx:2309
virtual Bool_t InPlaceClone(TDirectory *newdirectory, const char *options="")
Copy the content to a new new file, update this TTree with the new location information and attach th...
Definition: TTree.cxx:6915
TFile * GetCurrentFile() const
Return pointer to the current file.
Definition: TTree.cxx:5383
TList * fAliases
List of aliases for expressions based on the tree branches.
Definition: TTree.h:120
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:3667
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:5044
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:4994
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:8559
Long64_t * fClusterRangeEnd
[fNClusterRange] Last entry of a cluster range.
Definition: TTree.h:102
std::atomic< Long64_t > fIMTZipBytes
! Zip bytes for the IMT flush baskets.
Definition: TTree.h:157
void UseCurrentStyle()
Replace current attributes by current style.
Definition: TTree.cxx:9556
TVirtualTreePlayer * GetPlayer()
Load the TTreePlayer (if not already done).
Definition: TTree.cxx:6208
virtual Long64_t ReadStream(std::istream &inputStream, const char *branchDescriptor="", char delimiter=' ')
Create or simply read branches from an input stream.
Definition: TTree.cxx:7513
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:8775
Int_t fScanField
Number of runs before prompting in Scan.
Definition: TTree.h:91
virtual ~TTree()
Destructor.
Definition: TTree.cxx:905
virtual TTree * GetFriend(const char *) const
Return a pointer to the TTree friend whose name or alias is 'friendname.
Definition: TTree.cxx:5880
virtual Long64_t CopyEntries(TTree *tree, Long64_t nentries=-1, Option_t *option="", Bool_t needCopyAddresses=false)
Copy nentries from given tree to this tree.
Definition: TTree.cxx:3482
virtual Int_t SetBranchAddress(const char *bname, void *add, TBranch **ptr=0)
Change branch address, dealing with clone trees properly.
Definition: TTree.cxx:8237
virtual Double_t GetMaximum(const char *columname)
Return maximum of column with name columname.
Definition: TTree.cxx:6138
virtual Long64_t GetEntryNumberWithBestIndex(Long64_t major, Long64_t minor=0) const
Return entry number corresponding to major and minor number.
Definition: TTree.cxx:5795
static void SetMaxTreeSize(Long64_t maxsize=100000000000LL)
Set the maximum size in bytes of a Tree file (static function).
Definition: TTree.cxx:9044
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:2393
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:9544
Int_t fNClusterRange
Number of Cluster range in addition to the one defined by 'AutoFlush'.
Definition: TTree.h:94
virtual void PrintCacheStats(Option_t *option="") const
Print statistics about the TreeCache for this tree.
Definition: TTree.cxx:7273
virtual Int_t BuildIndex(const char *majorname, const char *minorname="0")
Build a Tree Index (default is TTreeIndex).
Definition: TTree.cxx:2618
TVirtualTreePlayer * fPlayer
! Pointer to current Tree player
Definition: TTree.h:130
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:9024
TObjArray fBranches
List of Branches.
Definition: TTree.h:118
TDirectory * GetDirectory() const
Definition: TTree.h:456
TTreeCache * GetReadCache(TFile *file) const
Find and return the TTreeCache registered with the file and which may contain branches for us.
Definition: TTree.cxx:6221
Bool_t fCacheUserSet
! true if the cache setting was explicitly given by user
Definition: TTree.h:137
Long64_t fEntries
Number of entries.
Definition: TTree.h:83
virtual TFile * ChangeFile(TFile *file)
Called by TTree::Fill() when file has reached its maximum fgMaxTreeSize.
Definition: TTree.cxx:2707
virtual Bool_t GetBranchStatus(const char *branchname) const
Return status of branch with name branchname.
Definition: TTree.cxx:5294
virtual TEntryList * GetEntryList()
Returns the entry list assigned to this tree.
Definition: TTree.cxx:5759
virtual void SetWeight(Double_t w=1, Option_t *option="")
Set tree weight.
Definition: TTree.cxx:9195
void InitializeBranchLists(bool checkLeafCount)
Divides the top-level branches into two vectors: (i) branches to be processed sequentially and (ii) b...
Definition: TTree.cxx:5686
Long64_t * fClusterSize
[fNClusterRange] Number of entries in each cluster for a given range.
Definition: TTree.h:103
Long64_t fFlushedBytes
Number of auto-flushed bytes.
Definition: TTree.h:88
virtual void SetPerfStats(TVirtualPerfStats *perf)
Set perf stats.
Definition: TTree.cxx:9150
std::atomic< Long64_t > fIMTTotBytes
! Total bytes for the IMT flush baskets
Definition: TTree.h:156
virtual void SetCacheLearnEntries(Int_t n=10)
Interface to TTreeCache to set the number of entries for the learning phase.
Definition: TTree.cxx:8712
TEntryList * fEntryList
! Pointer to event selection list (if one)
Definition: TTree.h:122
virtual TVirtualIndex * GetTreeIndex() const
Definition: TTree.h:512
TList * fExternalFriends
! List of TFriendsElement pointing to us and need to be notified of LoadTree. Content not owned.
Definition: TTree.h:127
virtual Long64_t Merge(TCollection *list, Option_t *option="")
Merge the trees in the TList into this tree.
Definition: TTree.cxx:6793
virtual void SetMaxVirtualSize(Long64_t size=0)
Definition: TTree.h:619
virtual void DropBaskets()
Remove some baskets from memory.
Definition: TTree.cxx:4438
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:8194
Long64_t fMaxEntryLoop
Maximum number of entries to process.
Definition: TTree.h:97
virtual void SetDirectory(TDirectory *dir)
Change the tree's directory.
Definition: TTree.cxx:8813
void SortBranchesByTime()
Sorts top-level branches by the last average task time recorded per branch.
Definition: TTree.cxx:5739
virtual TBranchRef * GetBranchRef() const
Definition: TTree.h:444
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:7353
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:1619
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:8916
void MoveReadCache(TFile *src, TDirectory *dir)
Move a cache from a file to the current file in dir.
Definition: TTree.cxx:6886
Long64_t fAutoFlush
Auto-flush tree when fAutoFlush entries written or -fAutoFlush (compressed) bytes produced.
Definition: TTree.h:100
Int_t fUpdate
Update frequency for EntryLoop.
Definition: TTree.h:92
virtual void ResetAfterMerge(TFileMergeInfo *)
Resets the state of this TTree after a merge (keep the customization but forget the data).
Definition: TTree.cxx:7928
virtual void CopyAddresses(TTree *, Bool_t undo=kFALSE)
Set branch addresses of passed tree equal to ours.
Definition: TTree.cxx:3254
virtual Long64_t GetEntries() const
Definition: TTree.h:457
virtual void SetEstimate(Long64_t nentries=1000000)
Set number of entries to estimate variable limits.
Definition: TTree.cxx:8957
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:5987
Int_t fTimerInterval
Timer interval in milliseconds.
Definition: TTree.h:90
Int_t fDebug
! Debug level
Definition: TTree.h:110
virtual Long64_t AutoSave(Option_t *option="")
AutoSave tree header every fAutoSave bytes.
Definition: TTree.cxx:1484
virtual Long64_t GetEntryNumber(Long64_t entry) const
Return entry number corresponding to entry.
Definition: TTree.cxx:5770
virtual TTree * CloneTree(Long64_t nentries=-1, Option_t *option="")
Create a clone of this tree and copy nentries.
Definition: TTree.cxx:3094
Int_t fFileNumber
! current file number (if file extensions)
Definition: TTree.h:115
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:6098
virtual Long64_t GetZipBytes() const
Definition: TTree.h:539
TObjArray fLeaves
Direct pointers to individual branch leaves.
Definition: TTree.h:119
virtual void Reset(Option_t *option="")
Reset baskets, buffers and entries count in all branches and leaves.
Definition: TTree.cxx:7897
virtual void Print(Option_t *option="") const
Print a summary of the tree contents.
Definition: TTree.cxx:7122
virtual void KeepCircular()
Keep a maximum of fMaxEntries in memory.
Definition: TTree.cxx:6318
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:3767
Long64_t GetCacheAutoSize(Bool_t withDefault=kFALSE) const
Used for automatic sizing of the cache.
Definition: TTree.cxx:5321
virtual Bool_t SetAlias(const char *aliasName, const char *aliasFormula)
Set a tree variable alias.
Definition: TTree.cxx:8030
Long64_t fMaxVirtualSize
Maximum total size of buffers kept in memory.
Definition: TTree.h:98
virtual Long64_t GetTotBytes() const
Definition: TTree.h:510
virtual void SetObject(const char *name, const char *title)
Change the name and title of this tree.
Definition: TTree.cxx:9081
TVirtualPerfStats * fPerfStats
! pointer to the current perf stats object
Definition: TTree.h:128
Double_t fWeight
Tree weight (see TTree::SetWeight)
Definition: TTree.h:89
std::vector< TBranch * > fSeqBranches
! Branches to be processed sequentially when IMT is on
Definition: TTree.h:141
Long64_t fDebugMax
! Last entry number to debug
Definition: TTree.h:112
Int_t fDefaultEntryOffsetLen
Initial Length of fEntryOffset table in the basket buffers.
Definition: TTree.h:93
TTree()
Default constructor and I/O constructor.
Definition: TTree.cxx:722
Long64_t fAutoSave
Autosave tree when fAutoSave entries written or -fAutoSave (compressed) bytes produced.
Definition: TTree.h:99
TBranch * Branch(const char *name, T *obj, Int_t bufsize=32000, Int_t splitlevel=99)
Add a new branch, and infer the data type from the type of obj being passed.
Definition: TTree.h:348
virtual void SetDefaultEntryOffsetLen(Int_t newdefault, Bool_t updateExisting=kFALSE)
Update the default value for the branch's fEntryOffsetLen.
Definition: TTree.cxx:8787
std::atomic< UInt_t > fAllocationCount
indicates basket should be resized to exact memory usage, but causes significant
Definition: TTree.h:148
virtual Int_t GetEntryWithIndex(Int_t major, Int_t minor=0)
Read entry corresponding to major and minor number.
Definition: TTree.cxx:5832
static TTree * MergeTrees(TList *list, Option_t *option="")
Static function merging the trees in the TList into a new tree.
Definition: TTree.cxx:6754
virtual Long64_t GetReadEntry() const
Definition: TTree.h:503
virtual TObjArray * GetListOfBranches()
Definition: TTree.h:482
virtual void SetParallelUnzip(Bool_t opt=kTRUE, Float_t RelSize=-1)
Enable or disable parallel unzipping of Tree buffers.
Definition: TTree.cxx:9112
Long64_t fZipBytes
Total number of bytes in all branches after compression.
Definition: TTree.h:86
@ kSplitCollectionOfPointers
Definition: TTree.h:261
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:7779
virtual TTree * GetTree() const
Definition: TTree.h:511
TBuffer * fTransientBuffer
! Pointer to the current transient buffer.
Definition: TTree.h:134
Bool_t fIMTEnabled
! true if implicit multi-threading is enabled for this tree
Definition: TTree.h:138
virtual void SetEntryList(TEntryList *list, Option_t *opt="")
Set an EntryList.
Definition: TTree.cxx:8893
virtual Int_t DropBranchFromCache(const char *bname, Bool_t subbranches=kFALSE)
Remove the branch with name 'bname' from the Tree cache.
Definition: TTree.cxx:1127
virtual void AddZipBytes(Int_t zip)
Definition: TTree.h:327
virtual Long64_t LoadTree(Long64_t entry)
Set current entry.
Definition: TTree.cxx:6376
virtual Long64_t ReadFile(const char *filename, const char *branchDescriptor="", char delimiter=' ')
Create or simply read branches from filename.
Definition: TTree.cxx:7467
virtual const char * GetAlias(const char *aliasName) const
Returns the expanded value of the alias. Search in the friends if any.
Definition: TTree.cxx:5141
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:8977
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:5542
virtual TBasket * CreateBasket(TBranch *)
Create a basket for this tree and given branch.
Definition: TTree.cxx:3679
TList * fUserInfo
pointer to a list of user objects associated to this Tree
Definition: TTree.h:129
virtual Double_t GetMinimum(const char *columname)
Return minimum of column with name columname.
Definition: TTree.cxx:6178
virtual void RemoveFriend(TTree *)
Remove a friend from the list of friends.
Definition: TTree.cxx:7871
virtual Long64_t GetEntriesFast() const
Definition: TTree.h:459
virtual TList * GetUserInfo()
Return a pointer to the list containing user objects associated to this tree.
Definition: TTree.cxx:6259
Long64_t fChainOffset
! Offset of 1st entry of this Tree in a TChain
Definition: TTree.h:105
@ kOnlyFlushAtCluster
If set, the branch's buffers will grow until an event cluster boundary is hit, guaranteeing a basket ...
Definition: TTree.h:251
@ kEntriesReshuffled
If set, signals that this TTree is the output of the processing of another TTree, and the entries are...
Definition: TTree.h:256
@ kCircular
Definition: TTree.h:247
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:5416
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:7416
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:2385
virtual void SetBasketSize(const char *bname, Int_t buffsize=16000)
Set a branch's basket size.
Definition: TTree.cxx:8210
static void SetBranchStyle(Int_t style=1)
Set the current branch style.
Definition: TTree.cxx:8517
void ImportClusterRanges(TTree *fromtree)
Appends the cluster range information stored in 'fromtree' to this tree, including the value of fAuto...
Definition: TTree.cxx:6275
Long64_t fEstimate
Number of entries to estimate histogram limits.
Definition: TTree.h:101
Int_t FlushBasketsImpl() const
Internal implementation of the FlushBaskets algorithm.
Definition: TTree.cxx:5061
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:6460
TVirtualIndex * fTreeIndex
Pointer to the tree Index (if any)
Definition: TTree.h:125
virtual void Browse(TBrowser *)
Browse content of the TTree.
Definition: TTree.cxx:2590
TObject * fNotify
! Object to be notified when loading a Tree
Definition: TTree.h:116
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:1538
Long64_t fCacheSize
! Maximum size of file buffers
Definition: TTree.h:104
TList * fClones
! List of cloned trees which share our addresses
Definition: TTree.h:131
std::atomic< Long64_t > fTotalBuffers
! Total number of bytes in branch buffers
Definition: TTree.h:107
Bool_t fCacheDoAutoInit
! true if cache auto creation or resize check is needed
Definition: TTree.h:135
virtual Int_t MakeSelector(const char *selector=0, Option_t *option="")
Generate skeleton selector class for this tree.
Definition: TTree.cxx:6725
@ kFindBranch
Definition: TTree.h:207
@ kFindLeaf
Definition: TTree.h:208
@ kGetEntryWithIndex
Definition: TTree.h:212
@ kPrint
Definition: TTree.h:217
@ kGetFriend
Definition: TTree.h:213
@ kGetBranch
Definition: TTree.h:210
@ kSetBranchStatus
Definition: TTree.h:219
@ kLoadTree
Definition: TTree.h:216
@ kGetEntry
Definition: TTree.h:211
@ kGetLeaf
Definition: TTree.h:215
@ kRemoveFriend
Definition: TTree.h:218
@ kGetFriendAlias
Definition: TTree.h:214
@ kGetAlias
Definition: TTree.h:209
virtual void Draw(Option_t *opt)
Default Draw method for all objects.
Definition: TTree.h:426
virtual Int_t MakeClass(const char *classname=0, Option_t *option="")
Generate a skeleton analysis class for this tree.
Definition: TTree.cxx:6510
virtual void SetTreeIndex(TVirtualIndex *index)
The current TreeIndex is replaced by the new index.
Definition: TTree.cxx:9167
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:6960
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:7401
virtual Int_t SetCacheEntryRange(Long64_t first, Long64_t last)
interface to TTreeCache to set the cache entry range
Definition: TTree.cxx:8678
static Long64_t GetMaxTreeSize()
Static function which returns the tree file size limit in bytes.
Definition: TTree.cxx:6168
Int_t SetBranchAddressImp(TBranch *branch, void *addr, TBranch **ptr)
Change branch address, dealing with clone trees properly.
Definition: TTree.cxx:8297
Long64_t fMaxEntries
Maximum number of entries in case of circular buffers.
Definition: TTree.h:96
virtual void DropBuffers(Int_t nbytes)
Drop branch buffers to accommodate nbytes below MaxVirtualsize.
Definition: TTree.cxx:4451
virtual void SetName(const char *name)
Change the name of this tree.
Definition: TTree.cxx:9052
virtual void Delete(Option_t *option="")
Delete this tree from memory or/and disk.
Definition: TTree.cxx:3695
virtual TList * GetListOfFriends() const
Definition: TTree.h:484
virtual void Refresh()
Refresh contents of this tree and its branches from the current status on disk.
Definition: TTree.cxx:7810
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:8085
static Long64_t fgMaxTreeSize
Maximum size of a file containing a Tree.
Definition: TTree.h:151
Long64_t fReadEntry
! Number of the entry being processed
Definition: TTree.h:106
TArrayD fIndexValues
Sorted index values.
Definition: TTree.h:123
void MarkEventCluster()
Mark the previous event as being at the end of the event cluster.
Definition: TTree.cxx:8147
virtual Int_t MakeCode(const char *filename=0)
Generate a skeleton function for this tree.
Definition: TTree.cxx:6543
UInt_t fNEntriesSinceSorting
! Number of entries processed since the last re-sorting of branches
Definition: TTree.h:139
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:6671
virtual void SetFileNumber(Int_t number=0)
Set fFileNumber to number.
Definition: TTree.cxx:9000
virtual TLeaf * FindLeaf(const char *name)
Find leaf..
Definition: TTree.cxx:4834
virtual void StartViewer()
Start the TTreeViewer on this tree.
Definition: TTree.cxx:9280
Int_t GetMakeClass() const
Definition: TTree.h:489
TDirectory * fDirectory
! Pointer to directory holding this tree
Definition: TTree.h:117
@ kNeedEnableDecomposedObj
Definition: TTree.h:239
@ kClassMismatch
Definition: TTree.h:232
@ kVoidPtr
Definition: TTree.h:237
@ kMatchConversionCollection
Definition: TTree.h:235
@ kMissingCompiledCollectionProxy
Definition: TTree.h:230
@ kMismatch
Definition: TTree.h:231
@ kMatchConversion
Definition: TTree.h:234
@ kInternalError
Definition: TTree.h:229
@ kMatch
Definition: TTree.h:233
@ kMissingBranch
Definition: TTree.h:228
@ kMakeClass
Definition: TTree.h:236
static Int_t fgBranchStyle
Old/New branch style.
Definition: TTree.h:150
virtual void ResetBranchAddresses()
Tell all of our branches to drop their current objects and allocate new ones.
Definition: TTree.cxx:7969
Int_t fNfill
! Local for EntryLoop
Definition: TTree.h:109
virtual void RegisterExternalFriend(TFriendElement *)
Record a TFriendElement that we need to warn when the chain switches to a new file (typically this is...
Definition: TTree.cxx:7851
TArrayI fIndex
Index of sorted values.
Definition: TTree.h:124
virtual Int_t SetCacheSize(Long64_t cachesize=-1)
Set maximum size of the file cache .
Definition: TTree.cxx:8533
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:1204
virtual void SetBranchStatus(const char *bname, Bool_t status=1, UInt_t *found=0)
Set branch status to Process or DoNotProcess.
Definition: TTree.cxx:8386
TBuffer * GetTransientBuffer(Int_t size)
Returns the transient buffer currently used by this TTree for reading/writing baskets.
Definition: TTree.cxx:1022
ROOT::TIOFeatures GetIOFeatures() const
Returns the current set of IO settings.
Definition: TTree.cxx:5979
virtual const char * GetFriendAlias(TTree *) const
If the 'tree' is a friend, this method returns its alias name.
Definition: TTree.cxx:5937
virtual Bool_t Notify()
Function called when loading a new class library.
Definition: TTree.cxx:6936
virtual void RemoveExternalFriend(TFriendElement *)
Removes external friend.
Definition: TTree.cxx:7862
Bool_t MemoryFull(Int_t nbytes)
Check if adding nbytes to memory we are still below MaxVirtualsize.
Definition: TTree.cxx:6740
Int_t fPacketSize
! Number of entries in one packet for parallel root
Definition: TTree.h:108
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:9595
TStreamerInfo * BuildStreamerInfo(TClass *cl, void *pointer=0, Bool_t canOptimize=kTRUE)
Build StreamerInfo for class cl.
Definition: TTree.cxx:2633
virtual TBranch * BranchImpArr(const char *branchname, EDataType datatype, std::size_t N, void *addobj, Int_t bufsize, Int_t splitlevel)
Definition: TTree.cxx:1715
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:7988
Bool_t fIMTFlush
! True if we are doing a multithreaded flush.
Definition: TTree.h:155
virtual void AddTotBytes(Int_t tot)
Definition: TTree.h:326
Int_t fMakeClass
! not zero when processing code generated by MakeClass
Definition: TTree.h:114
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:6354
static constexpr Long64_t kMaxEntries
Definition: TTree.h:224
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:7103
virtual Long64_t GetAutoFlush() const
Definition: TTree.h:441
virtual EDataType GetType() const =0
virtual TClass * GetValueClass() const =0
virtual Bool_t HasPointers() const =0
Abstract interface for Tree Index.
Definition: TVirtualIndex.h:30
virtual void Append(const TVirtualIndex *, Bool_t delaySort=kFALSE)=0
virtual const char * GetMajorName() const =0
virtual Long64_t GetEntryNumberWithIndex(Long64_t major, Long64_t minor) const =0
virtual Long64_t GetEntryNumberFriend(const TTree *)=0
virtual const char * GetMinorName() const =0
virtual void SetTree(const TTree *T)=0
virtual Long64_t GetN() const =0
virtual Long64_t GetEntryNumberWithBestIndex(Long64_t major, Long64_t minor) const =0
virtual Bool_t IsValidFor(const TTree *parent)=0
Provides the interface for the PROOF internal performance measurement and event tracing.
Abstract base class defining the interface for the plugins that implement Draw, Scan,...
virtual Int_t MakeProxy(const char *classname, const char *macrofilename=0, const char *cutfilename=0, const char *option=0, Int_t maxUnrolling=3)=0
virtual Long64_t Scan(const char *varexp, const char *selection, Option_t *option, Long64_t nentries, Long64_t firstentry)=0
virtual void UpdateFormulaLeaves()=0
virtual Long64_t DrawSelect(const char *varexp, const char *selection, Option_t *option, Long64_t nentries, Long64_t firstentry)=0
virtual Int_t MakeCode(const char *filename)=0
virtual Int_t UnbinnedFit(const char *formula, const char *varexp, const char *selection, Option_t *option, Long64_t nentries, Long64_t firstentry)=0
virtual Long64_t GetEntries(const char *)=0
virtual TSQLResult * Query(const char *varexp, const char *selection, Option_t *option, Long64_t nentries, Long64_t firstentry)=0
virtual TPrincipal * Principal(const char *varexp="", const char *selection="", Option_t *option="np", Long64_t nentries=kMaxEntries, Long64_t firstentry=0)=0
virtual void StartViewer(Int_t ww, Int_t wh)=0
virtual Int_t MakeReader(const char *classname, Option_t *option)=0
virtual TVirtualIndex * BuildIndex(const TTree *T, const char *majorname, const char *minorname)=0
virtual TTree * CopyTree(const char *selection, Option_t *option="", Long64_t nentries=kMaxEntries, Long64_t firstentry=0)=0
virtual Long64_t Process(const char *filename, Option_t *option="", Long64_t nentries=kMaxEntries, Long64_t firstentry=0)=0
virtual void SetEstimate(Long64_t n)=0
static TVirtualTreePlayer * TreePlayer(TTree *obj)
Static function returning a pointer to a Tree player.
virtual Int_t MakeClass(const char *classname, const char *option)=0
virtual Int_t Fit(const char *formula, const char *varexp, const char *selection, Option_t *option, Option_t *goption, Long64_t nentries, Long64_t firstentry)=0
TLine * line
const Int_t n
Definition: legend1.C:16
constexpr std::array< decltype(std::declval< F >()(std::declval< int >())), N > make(F f)
tbb::task_arena is an alias of tbb::interface7::task_arena, which doesn't allow to forward declare tb...
Definition: StringConv.hxx:21
Bool_t IsImplicitMTEnabled()
Returns true if the implicit multi-threading in ROOT is enabled.
Definition: TROOT.cxx:557
ESTLType
Definition: ESTLType.h:28
@ kSTLmap
Definition: ESTLType.h:33
@ kSTLmultimap
Definition: ESTLType.h:34
void CallRecursiveRemoveIfNeeded(TObject &obj)
call RecursiveRemove for obj if gROOT is valid and obj.TestBit(kMustCleanup) is true.
Definition: TROOT.h:395
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:88
@ kInherit
Some objects use this value to denote that the compression algorithm should be inherited from the par...
Definition: Compression.h:86
@ kUseCompiledDefault
Use the compile-time default setting.
Definition: Compression.h:50
TCanvas * style()
Definition: style.C:1
auto * m
Definition: textangle.C:8
auto * l
Definition: textangle.C:4
auto * a
Definition: textangle.C:12