Logo ROOT  
Reference Guide
 
Loading...
Searching...
No Matches
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 recommended 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 - `G` : a long signed integer, stored as 64 bit (`Long_t`)
102 - `g` : a long unsigned integer, stored as 64 bit (`ULong_t`)
103 - `O` : [the letter `o`, not a zero] a boolean (`Bool_t`)
104
105 Examples:
106 - A int: "myVar/I"
107 - A float array with fixed size: "myArrfloat[42]/F"
108 - An double array with variable size, held by the `myvar` column: "myArrdouble[myvar]/D"
109 - An Double32_t array with variable size, held by the `myvar` column , with values between 0 and 16: "myArr[myvar]/d[0,10]"
110
111- If the address points to a single numerical variable, the leaflist is optional:
112~~~ {.cpp}
113 int value;
114 `tree->Branch(branchname, &value);`
115~~~
116- If the address points to more than one numerical variable, we strongly recommend
117 that the variable be sorted in decreasing order of size. Any other order will
118 result in a non-portable TTree (i.e. you will not be able to read it back on a
119 platform with a different padding strategy).
120 We recommend to persistify objects rather than composite leaflists.
121- In case of the truncated floating point types (Float16_t and Double32_t) you can
122 furthermore specify the range in the style [xmin,xmax] or [xmin,xmax,nbits] after
123 the type character. For example, for storing a variable size array `myArr` of
124 `Double32_t` with values within a range of `[0, 2*pi]` and the size of which is
125 stored in a branch called `myArrSize`, the syntax for the `leaflist` string would
126 be: `myArr[myArrSize]/d[0,twopi]`. Of course the number of bits could be specified,
127 the standard rules of opaque typedefs annotation are valid. For example, if only
128 18 bits were sufficient, the syntax would become: `myArr[myArrSize]/d[0,twopi,18]`
129
130## <a name="addingacolumnofstl"></a>Adding a column of STL collection instances (e.g. std::vector, std::list, std::unordered_map)
131
132~~~ {.cpp}
133 auto branch = tree.Branch( branchname, STLcollection, buffsize, splitlevel);
134~~~
135STLcollection is the address of a pointer to std::vector, std::list,
136std::deque, std::set or std::multiset containing pointers to objects.
137If the splitlevel is a value bigger than 100 (TTree::kSplitCollectionOfPointers)
138then the collection will be written in split mode, e.g. if it contains objects of
139any types deriving from TTrack this function will sort the objects
140based on their type and store them in separate branches in split
141mode.
142
143~~~ {.cpp}
144 branch->SetAddress(void *address)
145~~~
146In case of dynamic structures changing with each entry for example, one must
147redefine the branch address before filling the branch again.
148This is done via the TBranch::SetAddress member function.
149
150## <a name="addingacolumnofobjs">Add a column of objects
151
152~~~ {.cpp}
153 MyClass object;
154 auto branch = tree.Branch(branchname, &object, bufsize, splitlevel)
155~~~
156Note: The 2nd parameter must be the address of a valid object.
157 The object must not be destroyed (i.e. be deleted) until the TTree
158 is deleted or TTree::ResetBranchAddress is called.
159
160- if splitlevel=0, the object is serialized in the branch buffer.
161- if splitlevel=1 (default), this branch will automatically be split
162 into subbranches, with one subbranch for each data member or object
163 of the object itself. In case the object member is a TClonesArray,
164 the mechanism described in case C is applied to this array.
165- if splitlevel=2 ,this branch will automatically be split
166 into subbranches, with one subbranch for each data member or object
167 of the object itself. In case the object member is a TClonesArray,
168 it is processed as a TObject*, only one branch.
169
170Another available syntax is the following:
171
172~~~ {.cpp}
173 auto branch = tree.Branch(branchname, &p_object, bufsize, splitlevel)
174 auto branch = tree.Branch(branchname, className, &p_object, bufsize, splitlevel)
175~~~
176- p_object is a pointer to an object.
177- If className is not specified, Branch uses the type of p_object to determine the
178 type of the object.
179- If className is used to specify explicitly the object type, the className must
180 be of a type related to the one pointed to by the pointer. It should be either
181 a parent or derived class.
182
183Note: The pointer whose address is passed to TTree::Branch must not
184 be destroyed (i.e. go out of scope) until the TTree is deleted or
185 TTree::ResetBranchAddress is called.
186
187Note: The pointer p_object must be initialized before calling TTree::Branch
188- Do either:
189~~~ {.cpp}
190 MyDataClass* p_object = nullptr;
191 tree.Branch(branchname, &p_object);
192~~~
193- Or:
194~~~ {.cpp}
195 auto p_object = new MyDataClass;
196 tree.Branch(branchname, &p_object);
197~~~
198Whether the pointer is set to zero or not, the ownership of the object
199is not taken over by the TTree. I.e. even though an object will be allocated
200by TTree::Branch if the pointer p_object is zero, the object will <b>not</b>
201be deleted when the TTree is deleted.
202
203## <a name="addingacolumnoftclonesarray">Add a column of TClonesArray instances
204
205*It is recommended to use STL containers instead of TClonesArrays*.
206
207~~~ {.cpp}
208 // clonesarray is the address of a pointer to a TClonesArray.
209 auto branch = tree.Branch(branchname,clonesarray, bufsize, splitlevel)
210~~~
211The TClonesArray is a direct access list of objects of the same class.
212For example, if the TClonesArray is an array of TTrack objects,
213this function will create one subbranch for each data member of
214the object TTrack.
215
216## <a name="fillthetree">Fill the Tree:
217
218A TTree instance is filled with the invocation of the TTree::Fill method:
219~~~ {.cpp}
220 tree.Fill()
221~~~
222Upon its invocation, a loop on all defined branches takes place that for each branch invokes
223the TBranch::Fill method.
224
225## <a name="addcoltoexistingtree">Add a column to an already existing Tree
226
227You may want to add a branch to an existing tree. For example,
228if one variable in the tree was computed with a certain algorithm,
229you may want to try another algorithm and compare the results.
230One solution is to add a new branch, fill it, and save the tree.
231The code below adds a simple branch to an existing tree.
232Note the kOverwrite option in the Write method, it overwrites the
233existing tree. If it is not specified, two copies of the tree headers
234are saved.
235~~~ {.cpp}
236 void tree3AddBranch() {
237 TFile f("tree3.root", "update");
238
239 Float_t new_v;
240 auto t3 = f->Get<TTree>("t3");
241 auto newBranch = t3->Branch("new_v", &new_v, "new_v/F");
242
243 Long64_t nentries = t3->GetEntries(); // read the number of entries in the t3
244
245 for (Long64_t i = 0; i < nentries; i++) {
246 new_v = gRandom->Gaus(0, 1);
247 newBranch->Fill();
248 }
249
250 t3->Write("", TObject::kOverwrite); // save only the new version of the tree
251 }
252~~~
253It is not always possible to add branches to existing datasets stored in TFiles: for example,
254these files might not be writeable, just readable. In addition, modifying in place a TTree
255causes a new TTree instance to be written and the previous one to be deleted.
256For this reasons, ROOT offers the concept of friends for TTree and TChain:
257if is good practice to rely on friend trees rather than adding a branch manually.
258
259## <a name="fullexample">An Example
260
261Begin_Macro
262../../../tutorials/tree/tree.C
263End_Macro
264
265~~~ {.cpp}
266 // A simple example with histograms and a tree
267 //
268 // This program creates :
269 // - a one dimensional histogram
270 // - a two dimensional histogram
271 // - a profile histogram
272 // - a tree
273 //
274 // These objects are filled with some random numbers and saved on a file.
275
276 #include "TFile.h"
277 #include "TH1.h"
278 #include "TH2.h"
279 #include "TProfile.h"
280 #include "TRandom.h"
281 #include "TTree.h"
282
283 //__________________________________________________________________________
284 main(int argc, char **argv)
285 {
286 // Create a new ROOT binary machine independent file.
287 // Note that this file may contain any kind of ROOT objects, histograms,trees
288 // pictures, graphics objects, detector geometries, tracks, events, etc..
289 // This file is now becoming the current directory.
290 TFile hfile("htree.root","RECREATE","Demo ROOT file with histograms & trees");
291
292 // Create some histograms and a profile histogram
293 TH1F hpx("hpx","This is the px distribution",100,-4,4);
294 TH2F hpxpy("hpxpy","py ps px",40,-4,4,40,-4,4);
295 TProfile hprof("hprof","Profile of pz versus px",100,-4,4,0,20);
296
297 // Define some simple structures
298 typedef struct {Float_t x,y,z;} POINT;
299 typedef struct {
300 Int_t ntrack,nseg,nvertex;
301 UInt_t flag;
302 Float_t temperature;
303 } EVENTN;
304 POINT point;
305 EVENTN eventn;
306
307 // Create a ROOT Tree
308 TTree tree("T","An example of ROOT tree with a few branches");
309 tree.Branch("point",&point,"x:y:z");
310 tree.Branch("eventn",&eventn,"ntrack/I:nseg:nvertex:flag/i:temperature/F");
311 tree.Branch("hpx","TH1F",&hpx,128000,0);
312
313 Float_t px,py,pz;
314
315 // Here we start a loop on 1000 events
316 for ( Int_t i=0; i<1000; i++) {
317 gRandom->Rannor(px,py);
318 pz = px*px + py*py;
319 const auto random = gRandom->::Rndm(1);
320
321 // Fill histograms
322 hpx.Fill(px);
323 hpxpy.Fill(px,py,1);
324 hprof.Fill(px,pz,1);
325
326 // Fill structures
327 point.x = 10*(random-1);
328 point.y = 5*random;
329 point.z = 20*random;
330 eventn.ntrack = Int_t(100*random);
331 eventn.nseg = Int_t(2*eventn.ntrack);
332 eventn.nvertex = 1;
333 eventn.flag = Int_t(random+0.5);
334 eventn.temperature = 20+random;
335
336 // Fill the tree. For each event, save the 2 structures and 3 objects
337 // In this simple example, the objects hpx, hprof and hpxpy are slightly
338 // different from event to event. We expect a big compression factor!
339 tree->Fill();
340 }
341 // End of the loop
342
343 tree.Print();
344
345 // Save all objects in this file
346 hfile.Write();
347
348 // Close the file. Note that this is automatically done when you leave
349 // the application upon file destruction.
350 hfile.Close();
351
352 return 0;
353}
354~~~
355*/
356
357#include <ROOT/RConfig.hxx>
358#include "TTree.h"
359
360#include "ROOT/TIOFeatures.hxx"
361#include "TArrayC.h"
362#include "TBufferFile.h"
363#include "TBaseClass.h"
364#include "TBasket.h"
365#include "TBranchClones.h"
366#include "TBranchElement.h"
367#include "TBranchObject.h"
368#include "TBranchRef.h"
369#include "TBrowser.h"
370#include "TClass.h"
371#include "TClassEdit.h"
372#include "TClonesArray.h"
373#include "TCut.h"
374#include "TDataMember.h"
375#include "TDataType.h"
376#include "TDirectory.h"
377#include "TError.h"
378#include "TEntryList.h"
379#include "TEnv.h"
380#include "TEventList.h"
381#include "TFile.h"
382#include "TFolder.h"
383#include "TFriendElement.h"
384#include "TInterpreter.h"
385#include "TLeaf.h"
386#include "TLeafB.h"
387#include "TLeafC.h"
388#include "TLeafD.h"
389#include "TLeafElement.h"
390#include "TLeafF.h"
391#include "TLeafI.h"
392#include "TLeafL.h"
393#include "TLeafObject.h"
394#include "TLeafS.h"
395#include "TList.h"
396#include "TMath.h"
397#include "TMemFile.h"
398#include "TROOT.h"
399#include "TRealData.h"
400#include "TRegexp.h"
401#include "TRefTable.h"
402#include "TStreamerElement.h"
403#include "TStreamerInfo.h"
404#include "TStyle.h"
405#include "TSystem.h"
406#include "TTreeCloner.h"
407#include "TTreeCache.h"
408#include "TTreeCacheUnzip.h"
411#include "TVirtualIndex.h"
412#include "TVirtualPerfStats.h"
413#include "TVirtualPad.h"
414#include "TBranchSTL.h"
415#include "TSchemaRuleSet.h"
416#include "TFileMergeInfo.h"
417#include "ROOT/StringConv.hxx"
418#include "TVirtualMutex.h"
419#include "strlcpy.h"
420#include "snprintf.h"
421
422#include "TBranchIMTHelper.h"
423#include "TNotifyLink.h"
424
425#include <chrono>
426#include <cstddef>
427#include <iostream>
428#include <fstream>
429#include <sstream>
430#include <string>
431#include <cstdio>
432#include <climits>
433#include <algorithm>
434#include <set>
435
436#ifdef R__USE_IMT
438#include <thread>
439#endif
441constexpr Int_t kNEntriesResort = 100;
443
444Int_t TTree::fgBranchStyle = 1; // Use new TBranch style with TBranchElement.
445Long64_t TTree::fgMaxTreeSize = 100000000000LL;
446
448
449////////////////////////////////////////////////////////////////////////////////
450////////////////////////////////////////////////////////////////////////////////
451////////////////////////////////////////////////////////////////////////////////
453static char DataTypeToChar(EDataType datatype)
454{
455 // Return the leaflist 'char' for a given datatype.
456
457 switch(datatype) {
458 case kChar_t: return 'B';
459 case kUChar_t: return 'b';
460 case kBool_t: return 'O';
461 case kShort_t: return 'S';
462 case kUShort_t: return 's';
463 case kCounter:
464 case kInt_t: return 'I';
465 case kUInt_t: return 'i';
466 case kDouble_t: return 'D';
467 case kDouble32_t: return 'd';
468 case kFloat_t: return 'F';
469 case kFloat16_t: return 'f';
470 case kLong_t: return 'G';
471 case kULong_t: return 'g';
472 case kchar: return 0; // unsupported
473 case kLong64_t: return 'L';
474 case kULong64_t: return 'l';
475
476 case kCharStar: return 'C';
477 case kBits: return 0; //unsupported
478
479 case kOther_t:
480 case kNoType_t:
481 default:
482 return 0;
483 }
484 return 0;
485}
486
487////////////////////////////////////////////////////////////////////////////////
488/// \class TTree::TFriendLock
489/// Helper class to prevent infinite recursion in the usage of TTree Friends.
490
491////////////////////////////////////////////////////////////////////////////////
492/// Record in tree that it has been used while recursively looks through the friends.
495: fTree(tree)
496{
497 // We could also add some code to acquire an actual
498 // lock to prevent multi-thread issues
499 fMethodBit = methodbit;
500 if (fTree) {
503 } else {
504 fPrevious = 0;
505 }
506}
507
508////////////////////////////////////////////////////////////////////////////////
509/// Copy constructor.
512 fTree(tfl.fTree),
513 fMethodBit(tfl.fMethodBit),
514 fPrevious(tfl.fPrevious)
515{
516}
517
518////////////////////////////////////////////////////////////////////////////////
519/// Assignment operator.
522{
523 if(this!=&tfl) {
524 fTree=tfl.fTree;
525 fMethodBit=tfl.fMethodBit;
526 fPrevious=tfl.fPrevious;
527 }
528 return *this;
529}
530
531////////////////////////////////////////////////////////////////////////////////
532/// Restore the state of tree the same as before we set the lock.
535{
536 if (fTree) {
537 if (!fPrevious) {
538 fTree->fFriendLockStatus &= ~(fMethodBit & kBitMask);
539 }
540 }
541}
542
543////////////////////////////////////////////////////////////////////////////////
544/// \class TTree::TClusterIterator
545/// Helper class to iterate over cluster of baskets.
546
547////////////////////////////////////////////////////////////////////////////////
548/// Regular constructor.
549/// TTree is not set as const, since we might modify if it is a TChain.
551TTree::TClusterIterator::TClusterIterator(TTree *tree, Long64_t firstEntry) : fTree(tree), fClusterRange(0), fStartEntry(0), fNextEntry(0), fEstimatedSize(-1)
552{
553 if (fTree->fNClusterRange) {
554 // Find the correct cluster range.
555 //
556 // Since fClusterRangeEnd contains the inclusive upper end of the range, we need to search for the
557 // range that was containing the previous entry and add 1 (because BinarySearch consider the values
558 // to be the inclusive start of the bucket).
560
561 Long64_t entryInRange;
562 Long64_t pedestal;
563 if (fClusterRange == 0) {
564 pedestal = 0;
565 entryInRange = firstEntry;
566 } else {
567 pedestal = fTree->fClusterRangeEnd[fClusterRange-1] + 1;
568 entryInRange = firstEntry - pedestal;
569 }
570 Long64_t autoflush;
572 autoflush = fTree->fAutoFlush;
573 } else {
574 autoflush = fTree->fClusterSize[fClusterRange];
575 }
576 if (autoflush <= 0) {
577 autoflush = GetEstimatedClusterSize();
578 }
579 fStartEntry = pedestal + entryInRange - entryInRange%autoflush;
580 } else if ( fTree->GetAutoFlush() <= 0 ) {
581 // Case of old files before November 9 2009 *or* small tree where AutoFlush was never set.
582 fStartEntry = firstEntry;
583 } else {
584 fStartEntry = firstEntry - firstEntry%fTree->GetAutoFlush();
585 }
586 fNextEntry = fStartEntry; // Position correctly for the first call to Next()
587}
588
589////////////////////////////////////////////////////////////////////////////////
590/// Estimate the cluster size.
591///
592/// In almost all cases, this quickly returns the size of the auto-flush
593/// in the TTree.
594///
595/// However, in the case where the cluster size was not fixed (old files and
596/// case where autoflush was explicitly set to zero), we need estimate
597/// a cluster size in relation to the size of the cache.
598///
599/// After this value is calculated once for the TClusterIterator, it is
600/// cached and reused in future calls.
603{
604 auto autoFlush = fTree->GetAutoFlush();
605 if (autoFlush > 0) return autoFlush;
606 if (fEstimatedSize > 0) return fEstimatedSize;
607
608 Long64_t zipBytes = fTree->GetZipBytes();
609 if (zipBytes == 0) {
610 fEstimatedSize = fTree->GetEntries() - 1;
611 if (fEstimatedSize <= 0)
612 fEstimatedSize = 1;
613 } else {
614 Long64_t clusterEstimate = 1;
615 Long64_t cacheSize = fTree->GetCacheSize();
616 if (cacheSize == 0) {
617 // Humm ... let's double check on the file.
618 TFile *file = fTree->GetCurrentFile();
619 if (file) {
620 TFileCacheRead *cache = fTree->GetReadCache(file);
621 if (cache) {
622 cacheSize = cache->GetBufferSize();
623 }
624 }
625 }
626 // If neither file nor tree has a cache, use the current default.
627 if (cacheSize <= 0) {
628 cacheSize = 30000000;
629 }
630 clusterEstimate = fTree->GetEntries() * cacheSize / zipBytes;
631 // If there are no entries, then just default to 1.
632 fEstimatedSize = clusterEstimate ? clusterEstimate : 1;
633 }
634 return fEstimatedSize;
635}
636
637////////////////////////////////////////////////////////////////////////////////
638/// Move on to the next cluster and return the starting entry
639/// of this next cluster
642{
643 fStartEntry = fNextEntry;
644 if (fTree->fNClusterRange || fTree->GetAutoFlush() > 0) {
645 if (fClusterRange == fTree->fNClusterRange) {
646 // We are looking at a range which size
647 // is defined by AutoFlush itself and goes to the GetEntries.
648 fNextEntry += GetEstimatedClusterSize();
649 } else {
650 if (fStartEntry > fTree->fClusterRangeEnd[fClusterRange]) {
651 ++fClusterRange;
652 }
653 if (fClusterRange == fTree->fNClusterRange) {
654 // We are looking at the last range which size
655 // is defined by AutoFlush itself and goes to the GetEntries.
656 fNextEntry += GetEstimatedClusterSize();
657 } else {
658 Long64_t clusterSize = fTree->fClusterSize[fClusterRange];
659 if (clusterSize == 0) {
660 clusterSize = GetEstimatedClusterSize();
661 }
662 fNextEntry += clusterSize;
663 if (fNextEntry > fTree->fClusterRangeEnd[fClusterRange]) {
664 // The last cluster of the range was a partial cluster,
665 // so the next cluster starts at the beginning of the
666 // next range.
667 fNextEntry = fTree->fClusterRangeEnd[fClusterRange] + 1;
668 }
669 }
670 }
671 } else {
672 // Case of old files before November 9 2009
673 fNextEntry = fStartEntry + GetEstimatedClusterSize();
674 }
675 if (fNextEntry > fTree->GetEntries()) {
676 fNextEntry = fTree->GetEntries();
677 }
678 return fStartEntry;
679}
680
681////////////////////////////////////////////////////////////////////////////////
682/// Move on to the previous cluster and return the starting entry
683/// of this previous cluster
686{
687 fNextEntry = fStartEntry;
688 if (fTree->fNClusterRange || fTree->GetAutoFlush() > 0) {
689 if (fClusterRange == 0 || fTree->fNClusterRange == 0) {
690 // We are looking at a range which size
691 // is defined by AutoFlush itself.
692 fStartEntry -= GetEstimatedClusterSize();
693 } else {
694 if (fNextEntry <= fTree->fClusterRangeEnd[fClusterRange]) {
695 --fClusterRange;
696 }
697 if (fClusterRange == 0) {
698 // We are looking at the first range.
699 fStartEntry = 0;
700 } else {
701 Long64_t clusterSize = fTree->fClusterSize[fClusterRange];
702 if (clusterSize == 0) {
703 clusterSize = GetEstimatedClusterSize();
704 }
705 fStartEntry -= clusterSize;
706 }
707 }
708 } else {
709 // Case of old files before November 9 2009 or trees that never auto-flushed.
710 fStartEntry = fNextEntry - GetEstimatedClusterSize();
711 }
712 if (fStartEntry < 0) {
713 fStartEntry = 0;
714 }
715 return fStartEntry;
716}
717
718////////////////////////////////////////////////////////////////////////////////
719////////////////////////////////////////////////////////////////////////////////
720////////////////////////////////////////////////////////////////////////////////
721
722////////////////////////////////////////////////////////////////////////////////
723/// Default constructor and I/O constructor.
724///
725/// Note: We do *not* insert ourself into the current directory.
726///
729: TNamed()
730, TAttLine()
731, TAttFill()
732, TAttMarker()
733, fEntries(0)
734, fTotBytes(0)
735, fZipBytes(0)
736, fSavedBytes(0)
737, fFlushedBytes(0)
738, fWeight(1)
740, fScanField(25)
741, fUpdate(0)
745, fMaxEntries(0)
746, fMaxEntryLoop(0)
748, fAutoSave( -300000000)
749, fAutoFlush(-30000000)
750, fEstimate(1000000)
752, fClusterSize(0)
753, fCacheSize(0)
754, fChainOffset(0)
755, fReadEntry(-1)
756, fTotalBuffers(0)
757, fPacketSize(100)
758, fNfill(0)
759, fDebug(0)
760, fDebugMin(0)
761, fDebugMax(9999999)
762, fMakeClass(0)
763, fFileNumber(0)
764, fNotify(0)
765, fDirectory(0)
766, fBranches()
767, fLeaves()
768, fAliases(0)
769, fEventList(0)
770, fEntryList(0)
771, fIndexValues()
772, fIndex()
773, fTreeIndex(0)
774, fFriends(0)
776, fPerfStats(0)
777, fUserInfo(0)
778, fPlayer(0)
779, fClones(0)
780, fBranchRef(0)
786, fIMTEnabled(ROOT::IsImplicitMTEnabled())
788{
789 fMaxEntries = 1000000000;
790 fMaxEntries *= 1000;
791
792 fMaxEntryLoop = 1000000000;
793 fMaxEntryLoop *= 1000;
794
796}
797
798////////////////////////////////////////////////////////////////////////////////
799/// Normal tree constructor.
800///
801/// The tree is created in the current directory.
802/// Use the various functions Branch below to add branches to this tree.
803///
804/// If the first character of title is a "/", the function assumes a folder name.
805/// In this case, it creates automatically branches following the folder hierarchy.
806/// splitlevel may be used in this case to control the split level.
808TTree::TTree(const char* name, const char* title, Int_t splitlevel /* = 99 */,
809 TDirectory* dir /* = gDirectory*/)
810: TNamed(name, title)
811, TAttLine()
812, TAttFill()
813, TAttMarker()
814, fEntries(0)
815, fTotBytes(0)
816, fZipBytes(0)
817, fSavedBytes(0)
818, fFlushedBytes(0)
819, fWeight(1)
820, fTimerInterval(0)
821, fScanField(25)
822, fUpdate(0)
823, fDefaultEntryOffsetLen(1000)
824, fNClusterRange(0)
825, fMaxClusterRange(0)
826, fMaxEntries(0)
827, fMaxEntryLoop(0)
828, fMaxVirtualSize(0)
829, fAutoSave( -300000000)
830, fAutoFlush(-30000000)
831, fEstimate(1000000)
832, fClusterRangeEnd(0)
833, fClusterSize(0)
834, fCacheSize(0)
835, fChainOffset(0)
836, fReadEntry(-1)
837, fTotalBuffers(0)
838, fPacketSize(100)
839, fNfill(0)
840, fDebug(0)
841, fDebugMin(0)
842, fDebugMax(9999999)
843, fMakeClass(0)
844, fFileNumber(0)
845, fNotify(0)
846, fDirectory(dir)
847, fBranches()
848, fLeaves()
849, fAliases(0)
850, fEventList(0)
851, fEntryList(0)
852, fIndexValues()
853, fIndex()
854, fTreeIndex(0)
855, fFriends(0)
856, fExternalFriends(0)
857, fPerfStats(0)
858, fUserInfo(0)
859, fPlayer(0)
860, fClones(0)
861, fBranchRef(0)
862, fFriendLockStatus(0)
863, fTransientBuffer(0)
864, fCacheDoAutoInit(kTRUE)
865, fCacheDoClusterPrefetch(kFALSE)
866, fCacheUserSet(kFALSE)
867, fIMTEnabled(ROOT::IsImplicitMTEnabled())
868, fNEntriesSinceSorting(0)
869{
870 // TAttLine state.
874
875 // TAttFill state.
878
879 // TAttMarkerState.
883
884 fMaxEntries = 1000000000;
885 fMaxEntries *= 1000;
886
887 fMaxEntryLoop = 1000000000;
888 fMaxEntryLoop *= 1000;
889
890 // Insert ourself into the current directory.
891 // FIXME: This is very annoying behaviour, we should
892 // be able to choose to not do this like we
893 // can with a histogram.
894 if (fDirectory) fDirectory->Append(this);
895
897
898 // If title starts with "/" and is a valid folder name, a superbranch
899 // is created.
900 // FIXME: Why?
901 if (strlen(title) > 2) {
902 if (title[0] == '/') {
903 Branch(title+1,32000,splitlevel);
904 }
905 }
906}
907
908////////////////////////////////////////////////////////////////////////////////
909/// Destructor.
912{
913 if (auto link = dynamic_cast<TNotifyLinkBase*>(fNotify)) {
914 link->Clear();
915 }
916 if (fAllocationCount && (gDebug > 0)) {
917 Info("TTree::~TTree", "For tree %s, allocation count is %u.", GetName(), fAllocationCount.load());
918#ifdef R__TRACK_BASKET_ALLOC_TIME
919 Info("TTree::~TTree", "For tree %s, allocation time is %lluus.", GetName(), fAllocationTime.load());
920#endif
921 }
922
923 if (fDirectory) {
924 // We are in a directory, which may possibly be a file.
925 if (fDirectory->GetList()) {
926 // Remove us from the directory listing.
927 fDirectory->Remove(this);
928 }
929 //delete the file cache if it points to this Tree
932 }
933
934 // Remove the TTree from any list (linked to to the list of Cleanups) to avoid the unnecessary call to
935 // this RecursiveRemove while we delete our content.
937 ResetBit(kMustCleanup); // Don't redo it.
938
939 // We don't own the leaves in fLeaves, the branches do.
940 fLeaves.Clear();
941 // I'm ready to destroy any objects allocated by
942 // SetAddress() by my branches. If I have clones,
943 // tell them to zero their pointers to this shared
944 // memory.
945 if (fClones && fClones->GetEntries()) {
946 // I have clones.
947 // I am about to delete the objects created by
948 // SetAddress() which we are sharing, so tell
949 // the clones to release their pointers to them.
950 for (TObjLink* lnk = fClones->FirstLink(); lnk; lnk = lnk->Next()) {
951 TTree* clone = (TTree*) lnk->GetObject();
952 // clone->ResetBranchAddresses();
953
954 // Reset only the branch we have set the address of.
955 CopyAddresses(clone,kTRUE);
956 }
957 }
958 // Get rid of our branches, note that this will also release
959 // any memory allocated by TBranchElement::SetAddress().
961
962 // The TBranch destructor is using fDirectory to detect whether it
963 // owns the TFile that contains its data (See TBranch::~TBranch)
964 fDirectory = nullptr;
965
966 // FIXME: We must consider what to do with the reset of these if we are a clone.
967 delete fPlayer;
968 fPlayer = 0;
969 if (fExternalFriends) {
970 using namespace ROOT::Detail;
972 fetree->Reset();
973 fExternalFriends->Clear("nodelete");
975 }
976 if (fFriends) {
977 fFriends->Delete();
978 delete fFriends;
979 fFriends = 0;
980 }
981 if (fAliases) {
982 fAliases->Delete();
983 delete fAliases;
984 fAliases = 0;
985 }
986 if (fUserInfo) {
987 fUserInfo->Delete();
988 delete fUserInfo;
989 fUserInfo = 0;
990 }
991 if (fClones) {
992 // Clone trees should no longer be removed from fClones when they are deleted.
993 {
995 gROOT->GetListOfCleanups()->Remove(fClones);
996 }
997 // Note: fClones does not own its content.
998 delete fClones;
999 fClones = 0;
1000 }
1001 if (fEntryList) {
1003 // Delete the entry list if it is marked to be deleted and it is not also
1004 // owned by a directory. (Otherwise we would need to make sure that a
1005 // TDirectoryFile that has a TTree in it does a 'slow' TList::Delete.
1006 delete fEntryList;
1007 fEntryList=0;
1008 }
1009 }
1010 delete fTreeIndex;
1011 fTreeIndex = 0;
1012 delete fBranchRef;
1013 fBranchRef = 0;
1014 delete [] fClusterRangeEnd;
1015 fClusterRangeEnd = 0;
1016 delete [] fClusterSize;
1017 fClusterSize = 0;
1018
1019 if (fTransientBuffer) {
1020 delete fTransientBuffer;
1021 fTransientBuffer = 0;
1022 }
1023}
1024
1025////////////////////////////////////////////////////////////////////////////////
1026/// Returns the transient buffer currently used by this TTree for reading/writing baskets.
1029{
1030 if (fTransientBuffer) {
1031 if (fTransientBuffer->BufferSize() < size) {
1032 fTransientBuffer->Expand(size);
1033 }
1034 return fTransientBuffer;
1035 }
1037 return fTransientBuffer;
1038}
1039
1040////////////////////////////////////////////////////////////////////////////////
1041/// Add branch with name bname to the Tree cache.
1042/// If bname="*" all branches are added to the cache.
1043/// if subbranches is true all the branches of the subbranches are
1044/// also put to the cache.
1045///
1046/// Returns:
1047/// - 0 branch added or already included
1048/// - -1 on error
1050Int_t TTree::AddBranchToCache(const char*bname, Bool_t subbranches)
1051{
1052 if (!GetTree()) {
1053 if (LoadTree(0)<0) {
1054 Error("AddBranchToCache","Could not load a tree");
1055 return -1;
1056 }
1057 }
1058 if (GetTree()) {
1059 if (GetTree() != this) {
1060 return GetTree()->AddBranchToCache(bname, subbranches);
1061 }
1062 } else {
1063 Error("AddBranchToCache", "No tree is available. Branch was not added to the cache");
1064 return -1;
1065 }
1066
1067 TFile *f = GetCurrentFile();
1068 if (!f) {
1069 Error("AddBranchToCache", "No file is available. Branch was not added to the cache");
1070 return -1;
1071 }
1073 if (!tc) {
1074 Error("AddBranchToCache", "No cache is available, branch not added");
1075 return -1;
1076 }
1077 return tc->AddBranch(bname,subbranches);
1078}
1079
1080////////////////////////////////////////////////////////////////////////////////
1081/// Add branch b to the Tree cache.
1082/// if subbranches is true all the branches of the subbranches are
1083/// also put to the cache.
1084///
1085/// Returns:
1086/// - 0 branch added or already included
1087/// - -1 on error
1090{
1091 if (!GetTree()) {
1092 if (LoadTree(0)<0) {
1093 Error("AddBranchToCache","Could not load a tree");
1094 return -1;
1095 }
1096 }
1097 if (GetTree()) {
1098 if (GetTree() != this) {
1099 Int_t res = GetTree()->AddBranchToCache(b, subbranches);
1100 if (res<0) {
1101 Error("AddBranchToCache", "Error adding branch");
1102 }
1103 return res;
1104 }
1105 } else {
1106 Error("AddBranchToCache", "No tree is available. Branch was not added to the cache");
1107 return -1;
1108 }
1109
1110 TFile *f = GetCurrentFile();
1111 if (!f) {
1112 Error("AddBranchToCache", "No file is available. Branch was not added to the cache");
1113 return -1;
1114 }
1116 if (!tc) {
1117 Error("AddBranchToCache", "No cache is available, branch not added");
1118 return -1;
1119 }
1120 return tc->AddBranch(b,subbranches);
1121}
1122
1123////////////////////////////////////////////////////////////////////////////////
1124/// Remove the branch with name 'bname' from the Tree cache.
1125/// If bname="*" all branches are removed from the cache.
1126/// if subbranches is true all the branches of the subbranches are
1127/// also removed from the cache.
1128///
1129/// Returns:
1130/// - 0 branch dropped or not in cache
1131/// - -1 on error
1133Int_t TTree::DropBranchFromCache(const char*bname, Bool_t subbranches)
1134{
1135 if (!GetTree()) {
1136 if (LoadTree(0)<0) {
1137 Error("DropBranchFromCache","Could not load a tree");
1138 return -1;
1139 }
1140 }
1141 if (GetTree()) {
1142 if (GetTree() != this) {
1143 return GetTree()->DropBranchFromCache(bname, subbranches);
1144 }
1145 } else {
1146 Error("DropBranchFromCache", "No tree is available. Branch was not dropped from the cache");
1147 return -1;
1148 }
1149
1150 TFile *f = GetCurrentFile();
1151 if (!f) {
1152 Error("DropBranchFromCache", "No file is available. Branch was not dropped from the cache");
1153 return -1;
1154 }
1156 if (!tc) {
1157 Error("DropBranchFromCache", "No cache is available, branch not dropped");
1158 return -1;
1159 }
1160 return tc->DropBranch(bname,subbranches);
1161}
1162
1163////////////////////////////////////////////////////////////////////////////////
1164/// Remove the branch b from the Tree cache.
1165/// if subbranches is true all the branches of the subbranches are
1166/// also removed from the cache.
1167///
1168/// Returns:
1169/// - 0 branch dropped or not in cache
1170/// - -1 on error
1173{
1174 if (!GetTree()) {
1175 if (LoadTree(0)<0) {
1176 Error("DropBranchFromCache","Could not load a tree");
1177 return -1;
1178 }
1179 }
1180 if (GetTree()) {
1181 if (GetTree() != this) {
1182 Int_t res = GetTree()->DropBranchFromCache(b, subbranches);
1183 if (res<0) {
1184 Error("DropBranchFromCache", "Error dropping branch");
1185 }
1186 return res;
1187 }
1188 } else {
1189 Error("DropBranchFromCache", "No tree is available. Branch was not dropped from the cache");
1190 return -1;
1191 }
1192
1193 TFile *f = GetCurrentFile();
1194 if (!f) {
1195 Error("DropBranchFromCache", "No file is available. Branch was not dropped from the cache");
1196 return -1;
1197 }
1199 if (!tc) {
1200 Error("DropBranchFromCache", "No cache is available, branch not dropped");
1201 return -1;
1202 }
1203 return tc->DropBranch(b,subbranches);
1204}
1205
1206////////////////////////////////////////////////////////////////////////////////
1207/// Add a cloned tree to our list of trees to be notified whenever we change
1208/// our branch addresses or when we are deleted.
1210void TTree::AddClone(TTree* clone)
1211{
1212 if (!fClones) {
1213 fClones = new TList();
1214 fClones->SetOwner(false);
1215 // So that the clones are automatically removed from the list when
1216 // they are deleted.
1217 {
1219 gROOT->GetListOfCleanups()->Add(fClones);
1220 }
1221 }
1222 if (!fClones->FindObject(clone)) {
1223 fClones->Add(clone);
1224 }
1225}
1226
1227// Check whether mainTree and friendTree can be friends w.r.t. the kEntriesReshuffled bit.
1228// In particular, if any has the bit set, then friendTree must have a TTreeIndex and the
1229// branches used for indexing must be present in mainTree.
1230// Return true if the trees can be friends, false otherwise.
1231bool CheckReshuffling(TTree &mainTree, TTree &friendTree)
1232{
1233 const auto isMainReshuffled = mainTree.TestBit(TTree::kEntriesReshuffled);
1234 const auto isFriendReshuffled = friendTree.TestBit(TTree::kEntriesReshuffled);
1235 const auto friendHasValidIndex = [&] {
1236 auto idx = friendTree.GetTreeIndex();
1237 return idx ? idx->IsValidFor(&mainTree) : kFALSE;
1238 }();
1239
1240 if ((isMainReshuffled || isFriendReshuffled) && !friendHasValidIndex) {
1241 const auto reshuffledTreeName = isMainReshuffled ? mainTree.GetName() : friendTree.GetName();
1242 const auto msg = "Tree '%s' has the kEntriesReshuffled bit set, and cannot be used as friend nor can be added as "
1243 "a friend unless the main tree has a TTreeIndex on the friend tree '%s'. You can also unset the "
1244 "bit manually if you know what you are doing.";
1245 Error("AddFriend", msg, reshuffledTreeName, friendTree.GetName());
1246 return false;
1247 }
1248 return true;
1249}
1250
1251////////////////////////////////////////////////////////////////////////////////
1252/// Add a TFriendElement to the list of friends.
1253///
1254/// This function:
1255/// - opens a file if filename is specified
1256/// - reads a Tree with name treename from the file (current directory)
1257/// - adds the Tree to the list of friends
1258/// see other AddFriend functions
1259///
1260/// A TFriendElement TF describes a TTree object TF in a file.
1261/// When a TFriendElement TF is added to the the list of friends of an
1262/// existing TTree T, any variable from TF can be referenced in a query
1263/// to T.
1264///
1265/// A tree keeps a list of friends. In the context of a tree (or a chain),
1266/// friendship means unrestricted access to the friends data. In this way
1267/// it is much like adding another branch to the tree without taking the risk
1268/// of damaging it. To add a friend to the list, you can use the TTree::AddFriend
1269/// method. The tree in the diagram below has two friends (friend_tree1 and
1270/// friend_tree2) and now has access to the variables a,b,c,i,j,k,l and m.
1271///
1272/// \image html ttree_friend1.png
1273///
1274/// The AddFriend method has two parameters, the first is the tree name and the
1275/// second is the name of the ROOT file where the friend tree is saved.
1276/// AddFriend automatically opens the friend file. If no file name is given,
1277/// the tree called ft1 is assumed to be in the same file as the original tree.
1278///
1279/// tree.AddFriend("ft1","friendfile1.root");
1280/// If the friend tree has the same name as the original tree, you can give it
1281/// an alias in the context of the friendship:
1282///
1283/// tree.AddFriend("tree1 = tree","friendfile1.root");
1284/// Once the tree has friends, we can use TTree::Draw as if the friend's
1285/// variables were in the original tree. To specify which tree to use in
1286/// the Draw method, use the syntax:
1287/// ~~~ {.cpp}
1288/// <treeName>.<branchname>.<varname>
1289/// ~~~
1290/// If the variablename is enough to uniquely identify the variable, you can
1291/// leave out the tree and/or branch name.
1292/// For example, these commands generate a 3-d scatter plot of variable "var"
1293/// in the TTree tree versus variable v1 in TTree ft1 versus variable v2 in
1294/// TTree ft2.
1295/// ~~~ {.cpp}
1296/// tree.AddFriend("ft1","friendfile1.root");
1297/// tree.AddFriend("ft2","friendfile2.root");
1298/// tree.Draw("var:ft1.v1:ft2.v2");
1299/// ~~~
1300/// \image html ttree_friend2.png
1301///
1302/// The picture illustrates the access of the tree and its friends with a
1303/// Draw command.
1304/// When AddFriend is called, the ROOT file is automatically opened and the
1305/// friend tree (ft1) is read into memory. The new friend (ft1) is added to
1306/// the list of friends of tree.
1307/// The number of entries in the friend must be equal or greater to the number
1308/// of entries of the original tree. If the friend tree has fewer entries a
1309/// warning is given and the missing entries are not included in the histogram.
1310/// To retrieve the list of friends from a tree use TTree::GetListOfFriends.
1311/// When the tree is written to file (TTree::Write), the friends list is saved
1312/// with it. And when the tree is retrieved, the trees on the friends list are
1313/// also retrieved and the friendship restored.
1314/// When a tree is deleted, the elements of the friend list are also deleted.
1315/// It is possible to declare a friend tree that has the same internal
1316/// structure (same branches and leaves) as the original tree, and compare the
1317/// same values by specifying the tree.
1318/// ~~~ {.cpp}
1319/// tree.Draw("var:ft1.var:ft2.var")
1320/// ~~~
1322TFriendElement *TTree::AddFriend(const char *treename, const char *filename)
1323{
1324 if (!fFriends) {
1325 fFriends = new TList();
1326 }
1327 TFriendElement *fe = new TFriendElement(this, treename, filename);
1328
1329 TTree *t = fe->GetTree();
1330 bool canAddFriend = true;
1331 if (t) {
1332 canAddFriend = CheckReshuffling(*this, *t);
1333 if (!t->GetTreeIndex() && (t->GetEntries() < fEntries)) {
1334 Warning("AddFriend", "FriendElement %s in file %s has less entries %lld than its parent Tree: %lld", treename,
1335 filename, t->GetEntries(), fEntries);
1336 }
1337 } else {
1338 Error("AddFriend", "Cannot find tree '%s' in file '%s', friend not added", treename, filename);
1339 canAddFriend = false;
1340 }
1341
1342 if (canAddFriend)
1343 fFriends->Add(fe);
1344 return fe;
1345}
1346
1347////////////////////////////////////////////////////////////////////////////////
1348/// Add a TFriendElement to the list of friends.
1349///
1350/// The TFile is managed by the user (e.g. the user must delete the file).
1351/// For complete description see AddFriend(const char *, const char *).
1352/// This function:
1353/// - reads a Tree with name treename from the file
1354/// - adds the Tree to the list of friends
1356TFriendElement *TTree::AddFriend(const char *treename, TFile *file)
1357{
1358 if (!fFriends) {
1359 fFriends = new TList();
1360 }
1361 TFriendElement *fe = new TFriendElement(this, treename, file);
1362 R__ASSERT(fe);
1363 TTree *t = fe->GetTree();
1364 bool canAddFriend = true;
1365 if (t) {
1366 canAddFriend = CheckReshuffling(*this, *t);
1367 if (!t->GetTreeIndex() && (t->GetEntries() < fEntries)) {
1368 Warning("AddFriend", "FriendElement %s in file %s has less entries %lld than its parent tree: %lld", treename,
1369 file->GetName(), t->GetEntries(), fEntries);
1370 }
1371 } else {
1372 Error("AddFriend", "Cannot find tree '%s' in file '%s', friend not added", treename, file->GetName());
1373 canAddFriend = false;
1374 }
1375
1376 if (canAddFriend)
1377 fFriends->Add(fe);
1378 return fe;
1379}
1380
1381////////////////////////////////////////////////////////////////////////////////
1382/// Add a TFriendElement to the list of friends.
1383///
1384/// The TTree is managed by the user (e.g., the user must delete the file).
1385/// For a complete description see AddFriend(const char *, const char *).
1387TFriendElement *TTree::AddFriend(TTree *tree, const char *alias, Bool_t warn)
1388{
1389 if (!tree) {
1390 return 0;
1391 }
1392 if (!fFriends) {
1393 fFriends = new TList();
1394 }
1395 TFriendElement *fe = new TFriendElement(this, tree, alias);
1396 R__ASSERT(fe); // this assert is for historical reasons. Don't remove it unless you understand all the consequences.
1397 TTree *t = fe->GetTree();
1398 if (warn && (t->GetEntries() < fEntries)) {
1399 Warning("AddFriend", "FriendElement '%s' in file '%s' has less entries %lld than its parent tree: %lld",
1400 tree->GetName(), fe->GetFile() ? fe->GetFile()->GetName() : "(memory resident)", t->GetEntries(),
1401 fEntries);
1402 }
1403 if (CheckReshuffling(*this, *t))
1404 fFriends->Add(fe);
1405 else
1406 tree->RemoveExternalFriend(fe);
1407 return fe;
1408}
1409
1410////////////////////////////////////////////////////////////////////////////////
1411/// AutoSave tree header every fAutoSave bytes.
1412///
1413/// When large Trees are produced, it is safe to activate the AutoSave
1414/// procedure. Some branches may have buffers holding many entries.
1415/// If fAutoSave is negative, AutoSave is automatically called by
1416/// TTree::Fill when the number of bytes generated since the previous
1417/// AutoSave is greater than -fAutoSave bytes.
1418/// If fAutoSave is positive, AutoSave is automatically called by
1419/// TTree::Fill every N entries.
1420/// This function may also be invoked by the user.
1421/// Each AutoSave generates a new key on the file.
1422/// Once the key with the tree header has been written, the previous cycle
1423/// (if any) is deleted.
1424///
1425/// Note that calling TTree::AutoSave too frequently (or similarly calling
1426/// TTree::SetAutoSave with a small value) is an expensive operation.
1427/// You should make tests for your own application to find a compromise
1428/// between speed and the quantity of information you may loose in case of
1429/// a job crash.
1430///
1431/// In case your program crashes before closing the file holding this tree,
1432/// the file will be automatically recovered when you will connect the file
1433/// in UPDATE mode.
1434/// The Tree will be recovered at the status corresponding to the last AutoSave.
1435///
1436/// if option contains "SaveSelf", gDirectory->SaveSelf() is called.
1437/// This allows another process to analyze the Tree while the Tree is being filled.
1438///
1439/// if option contains "FlushBaskets", TTree::FlushBaskets is called and all
1440/// the current basket are closed-out and written to disk individually.
1441///
1442/// By default the previous header is deleted after having written the new header.
1443/// if option contains "Overwrite", the previous Tree header is deleted
1444/// before written the new header. This option is slightly faster, but
1445/// the default option is safer in case of a problem (disk quota exceeded)
1446/// when writing the new header.
1447///
1448/// The function returns the number of bytes written to the file.
1449/// if the number of bytes is null, an error has occurred while writing
1450/// the header to the file.
1451///
1452/// ## How to write a Tree in one process and view it from another process
1453///
1454/// The following two scripts illustrate how to do this.
1455/// The script treew.C is executed by process1, treer.C by process2
1456///
1457/// script treew.C:
1458/// ~~~ {.cpp}
1459/// void treew() {
1460/// TFile f("test.root","recreate");
1461/// TNtuple *ntuple = new TNtuple("ntuple","Demo","px:py:pz:random:i");
1462/// Float_t px, py, pz;
1463/// for ( Int_t i=0; i<10000000; i++) {
1464/// gRandom->Rannor(px,py);
1465/// pz = px*px + py*py;
1466/// Float_t random = gRandom->Rndm(1);
1467/// ntuple->Fill(px,py,pz,random,i);
1468/// if (i%1000 == 1) ntuple->AutoSave("SaveSelf");
1469/// }
1470/// }
1471/// ~~~
1472/// script treer.C:
1473/// ~~~ {.cpp}
1474/// void treer() {
1475/// TFile f("test.root");
1476/// TTree *ntuple = (TTree*)f.Get("ntuple");
1477/// TCanvas c1;
1478/// Int_t first = 0;
1479/// while(1) {
1480/// if (first == 0) ntuple->Draw("px>>hpx", "","",10000000,first);
1481/// else ntuple->Draw("px>>+hpx","","",10000000,first);
1482/// first = (Int_t)ntuple->GetEntries();
1483/// c1.Update();
1484/// gSystem->Sleep(1000); //sleep 1 second
1485/// ntuple->Refresh();
1486/// }
1487/// }
1488/// ~~~
1491{
1492 if (!fDirectory || fDirectory == gROOT || !fDirectory->IsWritable()) return 0;
1493 if (gDebug > 0) {
1494 Info("AutoSave", "Tree:%s after %lld bytes written\n",GetName(),GetTotBytes());
1495 }
1496 TString opt = option;
1497 opt.ToLower();
1498
1499 if (opt.Contains("flushbaskets")) {
1500 if (gDebug > 0) Info("AutoSave", "calling FlushBaskets \n");
1502 }
1503
1505
1507 Long64_t nbytes;
1508 if (opt.Contains("overwrite")) {
1509 nbytes = fDirectory->WriteTObject(this,"","overwrite");
1510 } else {
1511 nbytes = fDirectory->WriteTObject(this); //nbytes will be 0 if Write failed (disk space exceeded)
1512 if (nbytes && key && strcmp(ClassName(), key->GetClassName()) == 0) {
1513 key->Delete();
1514 delete key;
1515 }
1516 }
1517 // save StreamerInfo
1519 if (file) file->WriteStreamerInfo();
1520
1521 if (opt.Contains("saveself")) {
1523 //the following line is required in case GetUserInfo contains a user class
1524 //for which the StreamerInfo must be written. One could probably be a bit faster (Rene)
1525 if (file) file->WriteHeader();
1526 }
1527
1528 return nbytes;
1529}
1530
1531namespace {
1532 // This error message is repeated several times in the code. We write it once.
1533 const char* writeStlWithoutProxyMsg = "The class requested (%s) for the branch \"%s\""
1534 " is an instance of an stl collection and does not have a compiled CollectionProxy."
1535 " Please generate the dictionary for this collection (%s) to avoid to write corrupted data.";
1536}
1537
1538////////////////////////////////////////////////////////////////////////////////
1539/// Same as TTree::Branch() with added check that addobj matches className.
1540///
1541/// See TTree::Branch() for other details.
1542///
1544TBranch* TTree::BranchImp(const char* branchname, const char* classname, TClass* ptrClass, void* addobj, Int_t bufsize, Int_t splitlevel)
1545{
1546 TClass* claim = TClass::GetClass(classname);
1547 if (!ptrClass) {
1548 if (claim && claim->GetCollectionProxy() && dynamic_cast<TEmulatedCollectionProxy*>(claim->GetCollectionProxy())) {
1549 Error("Branch", writeStlWithoutProxyMsg,
1550 claim->GetName(), branchname, claim->GetName());
1551 return 0;
1552 }
1553 return Branch(branchname, classname, (void*) addobj, bufsize, splitlevel);
1554 }
1555 TClass* actualClass = 0;
1556 void** addr = (void**) addobj;
1557 if (addr) {
1558 actualClass = ptrClass->GetActualClass(*addr);
1559 }
1560 if (ptrClass && claim) {
1561 if (!(claim->InheritsFrom(ptrClass) || ptrClass->InheritsFrom(claim))) {
1562 // Note we currently do not warn in case of splicing or over-expectation).
1563 if (claim->IsLoaded() && ptrClass->IsLoaded() && strcmp( claim->GetTypeInfo()->name(), ptrClass->GetTypeInfo()->name() ) == 0) {
1564 // The type is the same according to the C++ type_info, we must be in the case of
1565 // a template of Double32_t. This is actually a correct case.
1566 } else {
1567 Error("Branch", "The class requested (%s) for \"%s\" is different from the type of the pointer passed (%s)",
1568 claim->GetName(), branchname, ptrClass->GetName());
1569 }
1570 } else if (actualClass && (claim != actualClass) && !actualClass->InheritsFrom(claim)) {
1571 if (claim->IsLoaded() && actualClass->IsLoaded() && strcmp( claim->GetTypeInfo()->name(), actualClass->GetTypeInfo()->name() ) == 0) {
1572 // The type is the same according to the C++ type_info, we must be in the case of
1573 // a template of Double32_t. This is actually a correct case.
1574 } else {
1575 Error("Branch", "The actual class (%s) of the object provided for the definition of the branch \"%s\" does not inherit from %s",
1576 actualClass->GetName(), branchname, claim->GetName());
1577 }
1578 }
1579 }
1580 if (claim && claim->GetCollectionProxy() && dynamic_cast<TEmulatedCollectionProxy*>(claim->GetCollectionProxy())) {
1581 Error("Branch", writeStlWithoutProxyMsg,
1582 claim->GetName(), branchname, claim->GetName());
1583 return 0;
1584 }
1585 return Branch(branchname, classname, (void*) addobj, bufsize, splitlevel);
1586}
1587
1588////////////////////////////////////////////////////////////////////////////////
1589/// Same as TTree::Branch but automatic detection of the class name.
1590/// See TTree::Branch for other details.
1592TBranch* TTree::BranchImp(const char* branchname, TClass* ptrClass, void* addobj, Int_t bufsize, Int_t splitlevel)
1593{
1594 if (!ptrClass) {
1595 Error("Branch", "The pointer specified for %s is not of a class known to ROOT", branchname);
1596 return 0;
1597 }
1598 TClass* actualClass = 0;
1599 void** addr = (void**) addobj;
1600 if (addr && *addr) {
1601 actualClass = ptrClass->GetActualClass(*addr);
1602 if (!actualClass) {
1603 Warning("Branch", "The actual TClass corresponding to the object provided for the definition of the branch \"%s\" is missing.\n\tThe object will be truncated down to its %s part",
1604 branchname, ptrClass->GetName());
1605 actualClass = ptrClass;
1606 } else if ((ptrClass != actualClass) && !actualClass->InheritsFrom(ptrClass)) {
1607 Error("Branch", "The actual class (%s) of the object provided for the definition of the branch \"%s\" does not inherit from %s", actualClass->GetName(), branchname, ptrClass->GetName());
1608 return 0;
1609 }
1610 } else {
1611 actualClass = ptrClass;
1612 }
1613 if (actualClass && actualClass->GetCollectionProxy() && dynamic_cast<TEmulatedCollectionProxy*>(actualClass->GetCollectionProxy())) {
1614 Error("Branch", writeStlWithoutProxyMsg,
1615 actualClass->GetName(), branchname, actualClass->GetName());
1616 return 0;
1617 }
1618 return Branch(branchname, actualClass->GetName(), (void*) addobj, bufsize, splitlevel);
1619}
1620
1621////////////////////////////////////////////////////////////////////////////////
1622/// Same as TTree::Branch but automatic detection of the class name.
1623/// See TTree::Branch for other details.
1625TBranch* TTree::BranchImpRef(const char* branchname, const char *classname, TClass* ptrClass, void *addobj, Int_t bufsize, Int_t splitlevel)
1626{
1627 TClass* claim = TClass::GetClass(classname);
1628 if (!ptrClass) {
1629 if (claim && claim->GetCollectionProxy() && dynamic_cast<TEmulatedCollectionProxy*>(claim->GetCollectionProxy())) {
1630 Error("Branch", writeStlWithoutProxyMsg,
1631 claim->GetName(), branchname, claim->GetName());
1632 return 0;
1633 } else if (claim == 0) {
1634 Error("Branch", "The pointer specified for %s is not of a class known to ROOT and %s is not a known class", branchname, classname);
1635 return 0;
1636 }
1637 ptrClass = claim;
1638 }
1639 TClass* actualClass = 0;
1640 if (!addobj) {
1641 Error("Branch", "Reference interface requires a valid object (for branch: %s)!", branchname);
1642 return 0;
1643 }
1644 actualClass = ptrClass->GetActualClass(addobj);
1645 if (ptrClass && claim) {
1646 if (!(claim->InheritsFrom(ptrClass) || ptrClass->InheritsFrom(claim))) {
1647 // Note we currently do not warn in case of splicing or over-expectation).
1648 if (claim->IsLoaded() && ptrClass->IsLoaded() && strcmp( claim->GetTypeInfo()->name(), ptrClass->GetTypeInfo()->name() ) == 0) {
1649 // The type is the same according to the C++ type_info, we must be in the case of
1650 // a template of Double32_t. This is actually a correct case.
1651 } else {
1652 Error("Branch", "The class requested (%s) for \"%s\" is different from the type of the object passed (%s)",
1653 claim->GetName(), branchname, ptrClass->GetName());
1654 }
1655 } else if (actualClass && (claim != actualClass) && !actualClass->InheritsFrom(claim)) {
1656 if (claim->IsLoaded() && actualClass->IsLoaded() && strcmp( claim->GetTypeInfo()->name(), actualClass->GetTypeInfo()->name() ) == 0) {
1657 // The type is the same according to the C++ type_info, we must be in the case of
1658 // a template of Double32_t. This is actually a correct case.
1659 } else {
1660 Error("Branch", "The actual class (%s) of the object provided for the definition of the branch \"%s\" does not inherit from %s",
1661 actualClass->GetName(), branchname, claim->GetName());
1662 }
1663 }
1664 }
1665 if (!actualClass) {
1666 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",
1667 branchname, ptrClass->GetName());
1668 actualClass = ptrClass;
1669 } else if ((ptrClass != actualClass) && !actualClass->InheritsFrom(ptrClass)) {
1670 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());
1671 return 0;
1672 }
1673 if (actualClass && actualClass->GetCollectionProxy() && dynamic_cast<TEmulatedCollectionProxy*>(actualClass->GetCollectionProxy())) {
1674 Error("Branch", writeStlWithoutProxyMsg,
1675 actualClass->GetName(), branchname, actualClass->GetName());
1676 return 0;
1677 }
1678 return BronchExec(branchname, actualClass->GetName(), (void*) addobj, kFALSE, bufsize, splitlevel);
1679}
1680
1681////////////////////////////////////////////////////////////////////////////////
1682/// Same as TTree::Branch but automatic detection of the class name.
1683/// See TTree::Branch for other details.
1685TBranch* TTree::BranchImpRef(const char* branchname, TClass* ptrClass, EDataType datatype, void* addobj, Int_t bufsize, Int_t splitlevel)
1686{
1687 if (!ptrClass) {
1688 if (datatype == kOther_t || datatype == kNoType_t) {
1689 Error("Branch", "The pointer specified for %s is not of a class or type known to ROOT", branchname);
1690 } else {
1691 TString varname; varname.Form("%s/%c",branchname,DataTypeToChar(datatype));
1692 return Branch(branchname,addobj,varname.Data(),bufsize);
1693 }
1694 return 0;
1695 }
1696 TClass* actualClass = 0;
1697 if (!addobj) {
1698 Error("Branch", "Reference interface requires a valid object (for branch: %s)!", branchname);
1699 return 0;
1700 }
1701 actualClass = ptrClass->GetActualClass(addobj);
1702 if (!actualClass) {
1703 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",
1704 branchname, ptrClass->GetName());
1705 actualClass = ptrClass;
1706 } else if ((ptrClass != actualClass) && !actualClass->InheritsFrom(ptrClass)) {
1707 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());
1708 return 0;
1709 }
1710 if (actualClass && actualClass->GetCollectionProxy() && dynamic_cast<TEmulatedCollectionProxy*>(actualClass->GetCollectionProxy())) {
1711 Error("Branch", writeStlWithoutProxyMsg,
1712 actualClass->GetName(), branchname, actualClass->GetName());
1713 return 0;
1714 }
1715 return BronchExec(branchname, actualClass->GetName(), (void*) addobj, kFALSE, bufsize, splitlevel);
1716}
1717
1718////////////////////////////////////////////////////////////////////////////////
1719// Wrapper to turn Branch call with an std::array into the relevant leaf list
1720// call
1721TBranch *TTree::BranchImpArr(const char *branchname, EDataType datatype, std::size_t N, void *addobj, Int_t bufsize,
1722 Int_t /* splitlevel */)
1723{
1724 if (datatype == kOther_t || datatype == kNoType_t) {
1725 Error("Branch",
1726 "The inner type of the std::array passed specified for %s is not of a class or type known to ROOT",
1727 branchname);
1728 } else {
1729 TString varname;
1730 varname.Form("%s[%d]/%c", branchname, (int)N, DataTypeToChar(datatype));
1731 return Branch(branchname, addobj, varname.Data(), bufsize);
1732 }
1733 return nullptr;
1734}
1735
1736////////////////////////////////////////////////////////////////////////////////
1737/// Deprecated function. Use next function instead.
1739Int_t TTree::Branch(TList* li, Int_t bufsize /* = 32000 */ , Int_t splitlevel /* = 99 */)
1740{
1741 return Branch((TCollection*) li, bufsize, splitlevel);
1742}
1743
1744////////////////////////////////////////////////////////////////////////////////
1745/// Create one branch for each element in the collection.
1746///
1747/// Each entry in the collection becomes a top level branch if the
1748/// corresponding class is not a collection. If it is a collection, the entry
1749/// in the collection becomes in turn top level branches, etc.
1750/// The splitlevel is decreased by 1 every time a new collection is found.
1751/// For example if list is a TObjArray*
1752/// - if splitlevel = 1, one top level branch is created for each element
1753/// of the TObjArray.
1754/// - if splitlevel = 2, one top level branch is created for each array element.
1755/// if, in turn, one of the array elements is a TCollection, one top level
1756/// branch will be created for each element of this collection.
1757///
1758/// In case a collection element is a TClonesArray, the special Tree constructor
1759/// for TClonesArray is called.
1760/// The collection itself cannot be a TClonesArray.
1761///
1762/// The function returns the total number of branches created.
1763///
1764/// If name is given, all branch names will be prefixed with name_.
1765///
1766/// IMPORTANT NOTE1: This function should not be called with splitlevel < 1.
1767///
1768/// IMPORTANT NOTE2: The branches created by this function will have names
1769/// corresponding to the collection or object names. It is important
1770/// to give names to collections to avoid misleading branch names or
1771/// identical branch names. By default collections have a name equal to
1772/// the corresponding class name, e.g. the default name for a TList is "TList".
1773///
1774/// And in general, in case two or more master branches contain subbranches
1775/// with identical names, one must add a "." (dot) character at the end
1776/// of the master branch name. This will force the name of the subbranches
1777/// to be of the form `master.subbranch` instead of simply `subbranch`.
1778/// This situation happens when the top level object
1779/// has two or more members referencing the same class.
1780/// For example, if a Tree has two branches B1 and B2 corresponding
1781/// to objects of the same class MyClass, one can do:
1782/// ~~~ {.cpp}
1783/// tree.Branch("B1.","MyClass",&b1,8000,1);
1784/// tree.Branch("B2.","MyClass",&b2,8000,1);
1785/// ~~~
1786/// if MyClass has 3 members a,b,c, the two instructions above will generate
1787/// subbranches called B1.a, B1.b ,B1.c, B2.a, B2.b, B2.c
1788///
1789/// Example:
1790/// ~~~ {.cpp}
1791/// {
1792/// TTree T("T","test list");
1793/// TList *list = new TList();
1794///
1795/// TObjArray *a1 = new TObjArray();
1796/// a1->SetName("a1");
1797/// list->Add(a1);
1798/// TH1F *ha1a = new TH1F("ha1a","ha1",100,0,1);
1799/// TH1F *ha1b = new TH1F("ha1b","ha1",100,0,1);
1800/// a1->Add(ha1a);
1801/// a1->Add(ha1b);
1802/// TObjArray *b1 = new TObjArray();
1803/// b1->SetName("b1");
1804/// list->Add(b1);
1805/// TH1F *hb1a = new TH1F("hb1a","hb1",100,0,1);
1806/// TH1F *hb1b = new TH1F("hb1b","hb1",100,0,1);
1807/// b1->Add(hb1a);
1808/// b1->Add(hb1b);
1809///
1810/// TObjArray *a2 = new TObjArray();
1811/// a2->SetName("a2");
1812/// list->Add(a2);
1813/// TH1S *ha2a = new TH1S("ha2a","ha2",100,0,1);
1814/// TH1S *ha2b = new TH1S("ha2b","ha2",100,0,1);
1815/// a2->Add(ha2a);
1816/// a2->Add(ha2b);
1817///
1818/// T.Branch(list,16000,2);
1819/// T.Print();
1820/// }
1821/// ~~~
1823Int_t TTree::Branch(TCollection* li, Int_t bufsize /* = 32000 */, Int_t splitlevel /* = 99 */, const char* name /* = "" */)
1824{
1825
1826 if (!li) {
1827 return 0;
1828 }
1829 TObject* obj = 0;
1830 Int_t nbranches = GetListOfBranches()->GetEntries();
1831 if (li->InheritsFrom(TClonesArray::Class())) {
1832 Error("Branch", "Cannot call this constructor for a TClonesArray");
1833 return 0;
1834 }
1835 Int_t nch = strlen(name);
1836 TString branchname;
1837 TIter next(li);
1838 while ((obj = next())) {
1839 if ((splitlevel > 1) && obj->InheritsFrom(TCollection::Class()) && !obj->InheritsFrom(TClonesArray::Class())) {
1840 TCollection* col = (TCollection*) obj;
1841 if (nch) {
1842 branchname.Form("%s_%s_", name, col->GetName());
1843 } else {
1844 branchname.Form("%s_", col->GetName());
1845 }
1846 Branch(col, bufsize, splitlevel - 1, branchname);
1847 } else {
1848 if (nch && (name[nch-1] == '_')) {
1849 branchname.Form("%s%s", name, obj->GetName());
1850 } else {
1851 if (nch) {
1852 branchname.Form("%s_%s", name, obj->GetName());
1853 } else {
1854 branchname.Form("%s", obj->GetName());
1855 }
1856 }
1857 if (splitlevel > 99) {
1858 branchname += ".";
1859 }
1860 Bronch(branchname, obj->ClassName(), li->GetObjectRef(obj), bufsize, splitlevel - 1);
1861 }
1862 }
1863 return GetListOfBranches()->GetEntries() - nbranches;
1864}
1865
1866////////////////////////////////////////////////////////////////////////////////
1867/// Create one branch for each element in the folder.
1868/// Returns the total number of branches created.
1870Int_t TTree::Branch(const char* foldername, Int_t bufsize /* = 32000 */, Int_t splitlevel /* = 99 */)
1871{
1872 TObject* ob = gROOT->FindObjectAny(foldername);
1873 if (!ob) {
1874 return 0;
1875 }
1876 if (ob->IsA() != TFolder::Class()) {
1877 return 0;
1878 }
1879 Int_t nbranches = GetListOfBranches()->GetEntries();
1880 TFolder* folder = (TFolder*) ob;
1881 TIter next(folder->GetListOfFolders());
1882 TObject* obj = 0;
1883 char* curname = new char[1000];
1884 char occur[20];
1885 while ((obj = next())) {
1886 snprintf(curname,1000, "%s/%s", foldername, obj->GetName());
1887 if (obj->IsA() == TFolder::Class()) {
1888 Branch(curname, bufsize, splitlevel - 1);
1889 } else {
1890 void* add = (void*) folder->GetListOfFolders()->GetObjectRef(obj);
1891 for (Int_t i = 0; i < 1000; ++i) {
1892 if (curname[i] == 0) {
1893 break;
1894 }
1895 if (curname[i] == '/') {
1896 curname[i] = '.';
1897 }
1898 }
1899 Int_t noccur = folder->Occurence(obj);
1900 if (noccur > 0) {
1901 snprintf(occur,20, "_%d", noccur);
1902 strlcat(curname, occur,1000);
1903 }
1904 TBranchElement* br = (TBranchElement*) Bronch(curname, obj->ClassName(), add, bufsize, splitlevel - 1);
1905 if (br) br->SetBranchFolder();
1906 }
1907 }
1908 delete[] curname;
1909 return GetListOfBranches()->GetEntries() - nbranches;
1910}
1911
1912////////////////////////////////////////////////////////////////////////////////
1913/// Create a new TTree Branch.
1914///
1915/// This Branch constructor is provided to support non-objects in
1916/// a Tree. The variables described in leaflist may be simple
1917/// variables or structures. // See the two following
1918/// constructors for writing objects in a Tree.
1919///
1920/// By default the branch buffers are stored in the same file as the Tree.
1921/// use TBranch::SetFile to specify a different file
1922///
1923/// * address is the address of the first item of a structure.
1924/// * leaflist is the concatenation of all the variable names and types
1925/// separated by a colon character :
1926/// The variable name and the variable type are separated by a slash (/).
1927/// The variable type may be 0,1 or 2 characters. If no type is given,
1928/// the type of the variable is assumed to be the same as the previous
1929/// variable. If the first variable does not have a type, it is assumed
1930/// of type F by default. The list of currently supported types is given below:
1931/// - `C` : a character string terminated by the 0 character
1932/// - `B` : an 8 bit signed integer (`Char_t`)
1933/// - `b` : an 8 bit unsigned integer (`UChar_t`)
1934/// - `S` : a 16 bit signed integer (`Short_t`)
1935/// - `s` : a 16 bit unsigned integer (`UShort_t`)
1936/// - `I` : a 32 bit signed integer (`Int_t`)
1937/// - `i` : a 32 bit unsigned integer (`UInt_t`)
1938/// - `F` : a 32 bit floating point (`Float_t`)
1939/// - `f` : a 24 bit floating point with truncated mantissa (`Float16_t`)
1940/// - `D` : a 64 bit floating point (`Double_t`)
1941/// - `d` : a 24 bit truncated floating point (`Double32_t`)
1942/// - `L` : a 64 bit signed integer (`Long64_t`)
1943/// - `l` : a 64 bit unsigned integer (`ULong64_t`)
1944/// - `G` : a long signed integer, stored as 64 bit (`Long_t`)
1945/// - `g` : a long unsigned integer, stored as 64 bit (`ULong_t`)
1946/// - `O` : [the letter `o`, not a zero] a boolean (`Bool_t`)
1947///
1948/// Arrays of values are supported with the following syntax:
1949/// - If leaf name has the form var[nelem], where nelem is alphanumeric, then
1950/// if nelem is a leaf name, it is used as the variable size of the array,
1951/// otherwise return 0.
1952/// - If leaf name has the form var[nelem], where nelem is a non-negative integer, then
1953/// it is used as the fixed size of the array.
1954/// - If leaf name has the form of a multi-dimensional array (e.g. var[nelem][nelem2])
1955/// where nelem and nelem2 are non-negative integer) then
1956/// it is used as a 2 dimensional array of fixed size.
1957/// - In case of the truncated floating point types (Float16_t and Double32_t) you can
1958/// furthermore specify the range in the style [xmin,xmax] or [xmin,xmax,nbits] after
1959/// the type character. See `TStreamerElement::GetRange()` for further information.
1960///
1961/// Any of other form is not supported.
1962///
1963/// Note that the TTree will assume that all the item are contiguous in memory.
1964/// On some platform, this is not always true of the member of a struct or a class,
1965/// due to padding and alignment. Sorting your data member in order of decreasing
1966/// sizeof usually leads to their being contiguous in memory.
1967///
1968/// * bufsize is the buffer size in bytes for this branch
1969/// The default value is 32000 bytes and should be ok for most cases.
1970/// You can specify a larger value (e.g. 256000) if your Tree is not split
1971/// and each entry is large (Megabytes)
1972/// A small value for bufsize is optimum if you intend to access
1973/// the entries in the Tree randomly and your Tree is in split mode.
1975TBranch* TTree::Branch(const char* name, void* address, const char* leaflist, Int_t bufsize /* = 32000 */)
1976{
1977 TBranch* branch = new TBranch(this, name, address, leaflist, bufsize);
1978 if (branch->IsZombie()) {
1979 delete branch;
1980 branch = 0;
1981 return 0;
1982 }
1983 fBranches.Add(branch);
1984 return branch;
1985}
1986
1987////////////////////////////////////////////////////////////////////////////////
1988/// Create a new branch with the object of class classname at address addobj.
1989///
1990/// WARNING:
1991///
1992/// Starting with Root version 3.01, the Branch function uses the new style
1993/// branches (TBranchElement). To get the old behaviour, you can:
1994/// - call BranchOld or
1995/// - call TTree::SetBranchStyle(0)
1996///
1997/// Note that with the new style, classname does not need to derive from TObject.
1998/// It must derived from TObject if the branch style has been set to 0 (old)
1999///
2000/// Note: See the comments in TBranchElement::SetAddress() for a more
2001/// detailed discussion of the meaning of the addobj parameter in
2002/// the case of new-style branches.
2003///
2004/// Use splitlevel < 0 instead of splitlevel=0 when the class
2005/// has a custom Streamer
2006///
2007/// Note: if the split level is set to the default (99), TTree::Branch will
2008/// not issue a warning if the class can not be split.
2010TBranch* TTree::Branch(const char* name, const char* classname, void* addobj, Int_t bufsize /* = 32000 */, Int_t splitlevel /* = 99 */)
2011{
2012 if (fgBranchStyle == 1) {
2013 return Bronch(name, classname, addobj, bufsize, splitlevel);
2014 } else {
2015 if (splitlevel < 0) {
2016 splitlevel = 0;
2017 }
2018 return BranchOld(name, classname, addobj, bufsize, splitlevel);
2019 }
2020}
2021
2022////////////////////////////////////////////////////////////////////////////////
2023/// Create a new TTree BranchObject.
2024///
2025/// Build a TBranchObject for an object of class classname.
2026/// addobj is the address of a pointer to an object of class classname.
2027/// IMPORTANT: classname must derive from TObject.
2028/// The class dictionary must be available (ClassDef in class header).
2029///
2030/// This option requires access to the library where the corresponding class
2031/// is defined. Accessing one single data member in the object implies
2032/// reading the full object.
2033/// See the next Branch constructor for a more efficient storage
2034/// in case the entry consists of arrays of identical objects.
2035///
2036/// By default the branch buffers are stored in the same file as the Tree.
2037/// use TBranch::SetFile to specify a different file
2038///
2039/// IMPORTANT NOTE about branch names:
2040///
2041/// And in general, in case two or more master branches contain subbranches
2042/// with identical names, one must add a "." (dot) character at the end
2043/// of the master branch name. This will force the name of the subbranches
2044/// to be of the form `master.subbranch` instead of simply `subbranch`.
2045/// This situation happens when the top level object
2046/// has two or more members referencing the same class.
2047/// For example, if a Tree has two branches B1 and B2 corresponding
2048/// to objects of the same class MyClass, one can do:
2049/// ~~~ {.cpp}
2050/// tree.Branch("B1.","MyClass",&b1,8000,1);
2051/// tree.Branch("B2.","MyClass",&b2,8000,1);
2052/// ~~~
2053/// if MyClass has 3 members a,b,c, the two instructions above will generate
2054/// subbranches called B1.a, B1.b ,B1.c, B2.a, B2.b, B2.c
2055///
2056/// bufsize is the buffer size in bytes for this branch
2057/// The default value is 32000 bytes and should be ok for most cases.
2058/// You can specify a larger value (e.g. 256000) if your Tree is not split
2059/// and each entry is large (Megabytes)
2060/// A small value for bufsize is optimum if you intend to access
2061/// the entries in the Tree randomly and your Tree is in split mode.
2063TBranch* TTree::BranchOld(const char* name, const char* classname, void* addobj, Int_t bufsize /* = 32000 */, Int_t splitlevel /* = 1 */)
2064{
2065 TClass* cl = TClass::GetClass(classname);
2066 if (!cl) {
2067 Error("BranchOld", "Cannot find class: '%s'", classname);
2068 return 0;
2069 }
2070 if (!cl->IsTObject()) {
2071 if (fgBranchStyle == 0) {
2072 Fatal("BranchOld", "The requested class ('%s') does not inherit from TObject.\n"
2073 "\tfgBranchStyle is set to zero requesting by default to use BranchOld.\n"
2074 "\tIf this is intentional use Bronch instead of Branch or BranchOld.", classname);
2075 } else {
2076 Fatal("BranchOld", "The requested class ('%s') does not inherit from TObject.\n"
2077 "\tYou can not use BranchOld to store objects of this type.",classname);
2078 }
2079 return 0;
2080 }
2081 TBranch* branch = new TBranchObject(this, name, classname, addobj, bufsize, splitlevel);
2082 fBranches.Add(branch);
2083 if (!splitlevel) {
2084 return branch;
2085 }
2086 // We are going to fully split the class now.
2087 TObjArray* blist = branch->GetListOfBranches();
2088 const char* rdname = 0;
2089 const char* dname = 0;
2090 TString branchname;
2091 char** apointer = (char**) addobj;
2092 TObject* obj = (TObject*) *apointer;
2093 Bool_t delobj = kFALSE;
2094 if (!obj) {
2095 obj = (TObject*) cl->New();
2096 delobj = kTRUE;
2097 }
2098 // Build the StreamerInfo if first time for the class.
2099 BuildStreamerInfo(cl, obj);
2100 // Loop on all public data members of the class and its base classes.
2101 Int_t lenName = strlen(name);
2102 Int_t isDot = 0;
2103 if (name[lenName-1] == '.') {
2104 isDot = 1;
2105 }
2106 TBranch* branch1 = 0;
2107 TRealData* rd = 0;
2108 TRealData* rdi = 0;
2109 TIter nexti(cl->GetListOfRealData());
2110 TIter next(cl->GetListOfRealData());
2111 // Note: This loop results in a full split because the
2112 // real data list includes all data members of
2113 // data members.
2114 while ((rd = (TRealData*) next())) {
2115 if (rd->TestBit(TRealData::kTransient)) continue;
2116
2117 // Loop over all data members creating branches for each one.
2118 TDataMember* dm = rd->GetDataMember();
2119 if (!dm->IsPersistent()) {
2120 // Do not process members with an "!" as the first character in the comment field.
2121 continue;
2122 }
2123 if (rd->IsObject()) {
2124 // We skip data members of class type.
2125 // But we do build their real data, their
2126 // streamer info, and write their streamer
2127 // info to the current directory's file.
2128 // Oh yes, and we also do this for all of
2129 // their base classes.
2131 if (clm) {
2132 BuildStreamerInfo(clm, (char*) obj + rd->GetThisOffset());
2133 }
2134 continue;
2135 }
2136 rdname = rd->GetName();
2137 dname = dm->GetName();
2138 if (cl->CanIgnoreTObjectStreamer()) {
2139 // Skip the TObject base class data members.
2140 // FIXME: This prevents a user from ever
2141 // using these names themself!
2142 if (!strcmp(dname, "fBits")) {
2143 continue;
2144 }
2145 if (!strcmp(dname, "fUniqueID")) {
2146 continue;
2147 }
2148 }
2149 TDataType* dtype = dm->GetDataType();
2150 Int_t code = 0;
2151 if (dtype) {
2152 code = dm->GetDataType()->GetType();
2153 }
2154 // Encode branch name. Use real data member name
2155 branchname = rdname;
2156 if (isDot) {
2157 if (dm->IsaPointer()) {
2158 // FIXME: This is wrong! The asterisk is not usually in the front!
2159 branchname.Form("%s%s", name, &rdname[1]);
2160 } else {
2161 branchname.Form("%s%s", name, &rdname[0]);
2162 }
2163 }
2164 // FIXME: Change this to a string stream.
2165 TString leaflist;
2166 Int_t offset = rd->GetThisOffset();
2167 char* pointer = ((char*) obj) + offset;
2168 if (dm->IsaPointer()) {
2169 // We have a pointer to an object or a pointer to an array of basic types.
2170 TClass* clobj = 0;
2171 if (!dm->IsBasic()) {
2172 clobj = TClass::GetClass(dm->GetTypeName());
2173 }
2174 if (clobj && clobj->InheritsFrom(TClonesArray::Class())) {
2175 // We have a pointer to a clones array.
2176 char* cpointer = (char*) pointer;
2177 char** ppointer = (char**) cpointer;
2178 TClonesArray* li = (TClonesArray*) *ppointer;
2179 if (splitlevel != 2) {
2180 if (isDot) {
2181 branch1 = new TBranchClones(branch,branchname, pointer, bufsize);
2182 } else {
2183 // FIXME: This is wrong! The asterisk is not usually in the front!
2184 branch1 = new TBranchClones(branch,&branchname.Data()[1], pointer, bufsize);
2185 }
2186 blist->Add(branch1);
2187 } else {
2188 if (isDot) {
2189 branch1 = new TBranchObject(branch, branchname, li->ClassName(), pointer, bufsize);
2190 } else {
2191 // FIXME: This is wrong! The asterisk is not usually in the front!
2192 branch1 = new TBranchObject(branch, &branchname.Data()[1], li->ClassName(), pointer, bufsize);
2193 }
2194 blist->Add(branch1);
2195 }
2196 } else if (clobj) {
2197 // We have a pointer to an object.
2198 //
2199 // It must be a TObject object.
2200 if (!clobj->IsTObject()) {
2201 continue;
2202 }
2203 branch1 = new TBranchObject(branch, dname, clobj->GetName(), pointer, bufsize, 0);
2204 if (isDot) {
2205 branch1->SetName(branchname);
2206 } else {
2207 // FIXME: This is wrong! The asterisk is not usually in the front!
2208 // Do not use the first character (*).
2209 branch1->SetName(&branchname.Data()[1]);
2210 }
2211 blist->Add(branch1);
2212 } else {
2213 // We have a pointer to an array of basic types.
2214 //
2215 // Check the comments in the text of the code for an index specification.
2216 const char* index = dm->GetArrayIndex();
2217 if (index[0]) {
2218 // We are a pointer to a varying length array of basic types.
2219 //check that index is a valid data member name
2220 //if member is part of an object (e.g. fA and index=fN)
2221 //index must be changed from fN to fA.fN
2222 TString aindex (rd->GetName());
2223 Ssiz_t rdot = aindex.Last('.');
2224 if (rdot>=0) {
2225 aindex.Remove(rdot+1);
2226 aindex.Append(index);
2227 }
2228 nexti.Reset();
2229 while ((rdi = (TRealData*) nexti())) {
2230 if (rdi->TestBit(TRealData::kTransient)) continue;
2231
2232 if (!strcmp(rdi->GetName(), index)) {
2233 break;
2234 }
2235 if (!strcmp(rdi->GetName(), aindex)) {
2236 index = rdi->GetName();
2237 break;
2238 }
2239 }
2240
2241 char vcode = DataTypeToChar((EDataType)code);
2242 // Note that we differentiate between strings and
2243 // char array by the fact that there is NO specified
2244 // size for a string (see next if (code == 1)
2245
2246 if (vcode) {
2247 leaflist.Form("%s[%s]/%c", &rdname[0], index, vcode);
2248 } else {
2249 Error("BranchOld", "Cannot create branch for rdname: %s code: %d", branchname.Data(), code);
2250 leaflist = "";
2251 }
2252 } else {
2253 // We are possibly a character string.
2254 if (code == 1) {
2255 // We are a character string.
2256 leaflist.Form("%s/%s", dname, "C");
2257 } else {
2258 // Invalid array specification.
2259 // FIXME: We need an error message here.
2260 continue;
2261 }
2262 }
2263 // There are '*' in both the branchname and leaflist, remove them.
2264 TString bname( branchname );
2265 bname.ReplaceAll("*","");
2266 leaflist.ReplaceAll("*","");
2267 // Add the branch to the tree and indicate that the address
2268 // is that of a pointer to be dereferenced before using.
2269 branch1 = new TBranch(branch, bname, *((void**) pointer), leaflist, bufsize);
2270 TLeaf* leaf = (TLeaf*) branch1->GetListOfLeaves()->At(0);
2272 leaf->SetAddress((void**) pointer);
2273 blist->Add(branch1);
2274 }
2275 } else if (dm->IsBasic()) {
2276 // We have a basic type.
2277
2278 char vcode = DataTypeToChar((EDataType)code);
2279 if (vcode) {
2280 leaflist.Form("%s/%c", rdname, vcode);
2281 } else {
2282 Error("BranchOld", "Cannot create branch for rdname: %s code: %d", branchname.Data(), code);
2283 leaflist = "";
2284 }
2285 branch1 = new TBranch(branch, branchname, pointer, leaflist, bufsize);
2286 branch1->SetTitle(rdname);
2287 blist->Add(branch1);
2288 } else {
2289 // We have a class type.
2290 // Note: This cannot happen due to the rd->IsObject() test above.
2291 // FIXME: Put an error message here just in case.
2292 }
2293 if (branch1) {
2294 branch1->SetOffset(offset);
2295 } else {
2296 Warning("BranchOld", "Cannot process member: '%s'", rdname);
2297 }
2298 }
2299 if (delobj) {
2300 delete obj;
2301 obj = 0;
2302 }
2303 return branch;
2304}
2305
2306////////////////////////////////////////////////////////////////////////////////
2307/// Build the optional branch supporting the TRefTable.
2308/// This branch will keep all the information to find the branches
2309/// containing referenced objects.
2310///
2311/// At each Tree::Fill, the branch numbers containing the
2312/// referenced objects are saved to the TBranchRef basket.
2313/// When the Tree header is saved (via TTree::Write), the branch
2314/// is saved keeping the information with the pointers to the branches
2315/// having referenced objects.
2318{
2319 if (!fBranchRef) {
2320 fBranchRef = new TBranchRef(this);
2321 }
2322 return fBranchRef;
2323}
2324
2325////////////////////////////////////////////////////////////////////////////////
2326/// Create a new TTree BranchElement.
2327///
2328/// ## WARNING about this new function
2329///
2330/// This function is designed to replace the internal
2331/// implementation of the old TTree::Branch (whose implementation
2332/// has been moved to BranchOld).
2333///
2334/// NOTE: The 'Bronch' method supports only one possible calls
2335/// signature (where the object type has to be specified
2336/// explicitly and the address must be the address of a pointer).
2337/// For more flexibility use 'Branch'. Use Bronch only in (rare)
2338/// cases (likely to be legacy cases) where both the new and old
2339/// implementation of Branch needs to be used at the same time.
2340///
2341/// This function is far more powerful than the old Branch
2342/// function. It supports the full C++, including STL and has
2343/// the same behaviour in split or non-split mode. classname does
2344/// not have to derive from TObject. The function is based on
2345/// the new TStreamerInfo.
2346///
2347/// Build a TBranchElement for an object of class classname.
2348///
2349/// addr is the address of a pointer to an object of class
2350/// classname. The class dictionary must be available (ClassDef
2351/// in class header).
2352///
2353/// Note: See the comments in TBranchElement::SetAddress() for a more
2354/// detailed discussion of the meaning of the addr parameter.
2355///
2356/// This option requires access to the library where the
2357/// corresponding class is defined. Accessing one single data
2358/// member in the object implies reading the full object.
2359///
2360/// By default the branch buffers are stored in the same file as the Tree.
2361/// use TBranch::SetFile to specify a different file
2362///
2363/// IMPORTANT NOTE about branch names:
2364///
2365/// And in general, in case two or more master branches contain subbranches
2366/// with identical names, one must add a "." (dot) character at the end
2367/// of the master branch name. This will force the name of the subbranches
2368/// to be of the form `master.subbranch` instead of simply `subbranch`.
2369/// This situation happens when the top level object
2370/// has two or more members referencing the same class.
2371/// For example, if a Tree has two branches B1 and B2 corresponding
2372/// to objects of the same class MyClass, one can do:
2373/// ~~~ {.cpp}
2374/// tree.Branch("B1.","MyClass",&b1,8000,1);
2375/// tree.Branch("B2.","MyClass",&b2,8000,1);
2376/// ~~~
2377/// if MyClass has 3 members a,b,c, the two instructions above will generate
2378/// subbranches called B1.a, B1.b ,B1.c, B2.a, B2.b, B2.c
2379///
2380/// bufsize is the buffer size in bytes for this branch
2381/// The default value is 32000 bytes and should be ok for most cases.
2382/// You can specify a larger value (e.g. 256000) if your Tree is not split
2383/// and each entry is large (Megabytes)
2384/// A small value for bufsize is optimum if you intend to access
2385/// the entries in the Tree randomly and your Tree is in split mode.
2386///
2387/// Use splitlevel < 0 instead of splitlevel=0 when the class
2388/// has a custom Streamer
2389///
2390/// Note: if the split level is set to the default (99), TTree::Branch will
2391/// not issue a warning if the class can not be split.
2393TBranch* TTree::Bronch(const char* name, const char* classname, void* addr, Int_t bufsize /* = 32000 */, Int_t splitlevel /* = 99 */)
2394{
2395 return BronchExec(name, classname, addr, kTRUE, bufsize, splitlevel);
2396}
2397
2398////////////////////////////////////////////////////////////////////////////////
2399/// Helper function implementing TTree::Bronch and TTree::Branch(const char *name, T &obj);
2401TBranch* TTree::BronchExec(const char* name, const char* classname, void* addr, Bool_t isptrptr, Int_t bufsize /* = 32000 */, Int_t splitlevel /* = 99 */)
2402{
2403 TClass* cl = TClass::GetClass(classname);
2404 if (!cl) {
2405 Error("Bronch", "Cannot find class:%s", classname);
2406 return 0;
2407 }
2408
2409 //if splitlevel <= 0 and class has a custom Streamer, we must create
2410 //a TBranchObject. We cannot assume that TClass::ReadBuffer is consistent
2411 //with the custom Streamer. The penalty is that one cannot process
2412 //this Tree without the class library containing the class.
2413
2414 char* objptr = 0;
2415 if (!isptrptr) {
2416 objptr = (char*)addr;
2417 } else if (addr) {
2418 objptr = *((char**) addr);
2419 }
2420
2421 if (cl == TClonesArray::Class()) {
2422 TClonesArray* clones = (TClonesArray*) objptr;
2423 if (!clones) {
2424 Error("Bronch", "Pointer to TClonesArray is null");
2425 return 0;
2426 }
2427 if (!clones->GetClass()) {
2428 Error("Bronch", "TClonesArray with no class defined in branch: %s", name);
2429 return 0;
2430 }
2431 if (!clones->GetClass()->HasDataMemberInfo()) {
2432 Error("Bronch", "TClonesArray with no dictionary defined in branch: %s", name);
2433 return 0;
2434 }
2435 bool hasCustomStreamer = clones->GetClass()->TestBit(TClass::kHasCustomStreamerMember);
2436 if (splitlevel > 0) {
2437 if (hasCustomStreamer)
2438 Warning("Bronch", "Using split mode on a class: %s with a custom Streamer", clones->GetClass()->GetName());
2439 } else {
2440 if (hasCustomStreamer) clones->BypassStreamer(kFALSE);
2441 TBranchObject *branch = new TBranchObject(this,name,classname,addr,bufsize,0,/*compress=*/ -1,isptrptr);
2442 fBranches.Add(branch);
2443 return branch;
2444 }
2445 }
2446
2447 if (cl->GetCollectionProxy()) {
2449 //if (!collProxy) {
2450 // Error("Bronch", "%s is missing its CollectionProxy (for branch %s)", classname, name);
2451 //}
2452 TClass* inklass = collProxy->GetValueClass();
2453 if (!inklass && (collProxy->GetType() == 0)) {
2454 Error("Bronch", "%s with no class defined in branch: %s", classname, name);
2455 return 0;
2456 }
2457 if ((splitlevel > 0) && inklass && (inklass->GetCollectionProxy() == 0)) {
2459 if ((stl != ROOT::kSTLmap) && (stl != ROOT::kSTLmultimap)) {
2460 if (!inklass->HasDataMemberInfo()) {
2461 Error("Bronch", "Container with no dictionary defined in branch: %s", name);
2462 return 0;
2463 }
2465 Warning("Bronch", "Using split mode on a class: %s with a custom Streamer", inklass->GetName());
2466 }
2467 }
2468 }
2469 //-------------------------------------------------------------------------
2470 // If the splitting switch is enabled, the split level is big enough and
2471 // the collection contains pointers we can split it
2472 //////////////////////////////////////////////////////////////////////////
2473
2474 TBranch *branch;
2475 if( splitlevel > kSplitCollectionOfPointers && collProxy->HasPointers() )
2476 branch = new TBranchSTL( this, name, collProxy, bufsize, splitlevel );
2477 else
2478 branch = new TBranchElement(this, name, collProxy, bufsize, splitlevel);
2479 fBranches.Add(branch);
2480 if (isptrptr) {
2481 branch->SetAddress(addr);
2482 } else {
2483 branch->SetObject(addr);
2484 }
2485 return branch;
2486 }
2487
2488 Bool_t hasCustomStreamer = kFALSE;
2489 if (!cl->HasDataMemberInfo() && !cl->GetCollectionProxy()) {
2490 Error("Bronch", "Cannot find dictionary for class: %s", classname);
2491 return 0;
2492 }
2493
2495 // Not an STL container and the linkdef file had a "-" after the class name.
2496 hasCustomStreamer = kTRUE;
2497 }
2498
2499 if (splitlevel < 0 || ((splitlevel == 0) && hasCustomStreamer && cl->IsTObject())) {
2500 TBranchObject* branch = new TBranchObject(this, name, classname, addr, bufsize, 0, /*compress=*/ ROOT::RCompressionSetting::EAlgorithm::kInherit, isptrptr);
2501 fBranches.Add(branch);
2502 return branch;
2503 }
2504
2505 if (cl == TClonesArray::Class()) {
2506 // Special case of TClonesArray.
2507 // No dummy object is created.
2508 // The streamer info is not rebuilt unoptimized.
2509 // No dummy top-level branch is created.
2510 // No splitting is attempted.
2511 TBranchElement* branch = new TBranchElement(this, name, (TClonesArray*) objptr, bufsize, splitlevel%kSplitCollectionOfPointers);
2512 fBranches.Add(branch);
2513 if (isptrptr) {
2514 branch->SetAddress(addr);
2515 } else {
2516 branch->SetObject(addr);
2517 }
2518 return branch;
2519 }
2520
2521 //
2522 // If we are not given an object to use as an i/o buffer
2523 // then create a temporary one which we will delete just
2524 // before returning.
2525 //
2526
2527 Bool_t delobj = kFALSE;
2528
2529 if (!objptr) {
2530 objptr = (char*) cl->New();
2531 delobj = kTRUE;
2532 }
2533
2534 //
2535 // Avoid splitting unsplittable classes.
2536 //
2537
2538 if ((splitlevel > 0) && !cl->CanSplit()) {
2539 if (splitlevel != 99) {
2540 Warning("Bronch", "%s cannot be split, resetting splitlevel to 0", cl->GetName());
2541 }
2542 splitlevel = 0;
2543 }
2544
2545 //
2546 // Make sure the streamer info is built and fetch it.
2547 //
2548 // If we are splitting, then make sure the streamer info
2549 // is built unoptimized (data members are not combined).
2550 //
2551
2552 TStreamerInfo* sinfo = BuildStreamerInfo(cl, objptr, splitlevel==0);
2553 if (!sinfo) {
2554 Error("Bronch", "Cannot build the StreamerInfo for class: %s", cl->GetName());
2555 return 0;
2556 }
2557
2558 //
2559 // Create a dummy top level branch object.
2560 //
2561
2562 Int_t id = -1;
2563 if (splitlevel > 0) {
2564 id = -2;
2565 }
2566 TBranchElement* branch = new TBranchElement(this, name, sinfo, id, objptr, bufsize, splitlevel);
2567 fBranches.Add(branch);
2568
2569 //
2570 // Do splitting, if requested.
2571 //
2572
2573 if (splitlevel%kSplitCollectionOfPointers > 0) {
2574 branch->Unroll(name, cl, sinfo, objptr, bufsize, splitlevel);
2575 }
2576
2577 //
2578 // Setup our offsets into the user's i/o buffer.
2579 //
2580
2581 if (isptrptr) {
2582 branch->SetAddress(addr);
2583 } else {
2584 branch->SetObject(addr);
2585 }
2586
2587 if (delobj) {
2588 cl->Destructor(objptr);
2589 objptr = 0;
2590 }
2591
2592 return branch;
2593}
2594
2595////////////////////////////////////////////////////////////////////////////////
2596/// Browse content of the TTree.
2599{
2601 if (fUserInfo) {
2602 if (strcmp("TList",fUserInfo->GetName())==0) {
2603 fUserInfo->SetName("UserInfo");
2604 b->Add(fUserInfo);
2605 fUserInfo->SetName("TList");
2606 } else {
2607 b->Add(fUserInfo);
2608 }
2609 }
2610}
2611
2612////////////////////////////////////////////////////////////////////////////////
2613/// Build a Tree Index (default is TTreeIndex).
2614/// See a description of the parameters and functionality in
2615/// TTreeIndex::TTreeIndex().
2616///
2617/// The return value is the number of entries in the Index (< 0 indicates failure).
2618///
2619/// A TTreeIndex object pointed by fTreeIndex is created.
2620/// This object will be automatically deleted by the TTree destructor.
2621/// If an index is already existing, this is replaced by the new one without being
2622/// deleted. This behaviour prevents the deletion of a previously external index
2623/// assigned to the TTree via the TTree::SetTreeIndex() method.
2624/// See also comments in TTree::SetTreeIndex().
2626Int_t TTree::BuildIndex(const char* majorname, const char* minorname /* = "0" */)
2627{
2628 fTreeIndex = GetPlayer()->BuildIndex(this, majorname, minorname);
2629 if (fTreeIndex->IsZombie()) {
2630 delete fTreeIndex;
2631 fTreeIndex = 0;
2632 return 0;
2633 }
2634 return fTreeIndex->GetN();
2635}
2636
2637////////////////////////////////////////////////////////////////////////////////
2638/// Build StreamerInfo for class cl.
2639/// pointer is an optional argument that may contain a pointer to an object of cl.
2641TStreamerInfo* TTree::BuildStreamerInfo(TClass* cl, void* pointer /* = 0 */, Bool_t canOptimize /* = kTRUE */ )
2642{
2643 if (!cl) {
2644 return 0;
2645 }
2646 cl->BuildRealData(pointer);
2648
2649 // Create StreamerInfo for all base classes.
2650 TBaseClass* base = 0;
2651 TIter nextb(cl->GetListOfBases());
2652 while((base = (TBaseClass*) nextb())) {
2653 if (base->IsSTLContainer()) {
2654 continue;
2655 }
2656 TClass* clm = TClass::GetClass(base->GetName());
2657 BuildStreamerInfo(clm, pointer, canOptimize);
2658 }
2659 if (sinfo && fDirectory) {
2661 }
2662 return sinfo;
2663}
2664
2665////////////////////////////////////////////////////////////////////////////////
2666/// Enable the TTreeCache unless explicitly disabled for this TTree by
2667/// a prior call to `SetCacheSize(0)`.
2668/// If the environment variable `ROOT_TTREECACHE_SIZE` or the rootrc config
2669/// `TTreeCache.Size` has been set to zero, this call will over-ride them with
2670/// a value of 1.0 (i.e. use a cache size to hold 1 cluster)
2671///
2672/// Return true if there is a cache attached to the `TTree` (either pre-exisiting
2673/// or created as part of this call)
2675{
2677 if (!file)
2678 return kFALSE;
2679 // Check for an existing cache
2681 if (pf)
2682 return kTRUE;
2683 if (fCacheUserSet && fCacheSize == 0)
2684 return kFALSE;
2685 return (0 == SetCacheSizeAux(kTRUE, -1));
2686}
2687
2688////////////////////////////////////////////////////////////////////////////////
2689/// Called by TTree::Fill() when file has reached its maximum fgMaxTreeSize.
2690/// Create a new file. If the original file is named "myfile.root",
2691/// subsequent files are named "myfile_1.root", "myfile_2.root", etc.
2692///
2693/// Returns a pointer to the new file.
2694///
2695/// Currently, the automatic change of file is restricted
2696/// to the case where the tree is in the top level directory.
2697/// The file should not contain sub-directories.
2698///
2699/// Before switching to a new file, the tree header is written
2700/// to the current file, then the current file is closed.
2701///
2702/// To process the multiple files created by ChangeFile, one must use
2703/// a TChain.
2704///
2705/// The new file name has a suffix "_N" where N is equal to fFileNumber+1.
2706/// By default a Root session starts with fFileNumber=0. One can set
2707/// fFileNumber to a different value via TTree::SetFileNumber.
2708/// In case a file named "_N" already exists, the function will try
2709/// a file named "__N", then "___N", etc.
2710///
2711/// fgMaxTreeSize can be set via the static function TTree::SetMaxTreeSize.
2712/// The default value of fgMaxTreeSize is 100 Gigabytes.
2713///
2714/// If the current file contains other objects like TH1 and TTree,
2715/// these objects are automatically moved to the new file.
2716///
2717/// \warning Be careful when writing the final Tree header to the file!
2718/// Don't do:
2719/// ~~~ {.cpp}
2720/// TFile *file = new TFile("myfile.root","recreate");
2721/// TTree *T = new TTree("T","title");
2722/// T->Fill(); // Loop
2723/// file->Write();
2724/// file->Close();
2725/// ~~~
2726/// \warning but do the following:
2727/// ~~~ {.cpp}
2728/// TFile *file = new TFile("myfile.root","recreate");
2729/// TTree *T = new TTree("T","title");
2730/// T->Fill(); // Loop
2731/// file = T->GetCurrentFile(); // To get the pointer to the current file
2732/// file->Write();
2733/// file->Close();
2734/// ~~~
2735///
2736/// \note This method is never called if the input file is a `TMemFile` or derivate.
2739{
2740 file->cd();
2741 Write();
2742 Reset();
2743 constexpr auto kBufSize = 2000;
2744 char* fname = new char[kBufSize];
2745 ++fFileNumber;
2746 char uscore[10];
2747 for (Int_t i = 0; i < 10; ++i) {
2748 uscore[i] = 0;
2749 }
2750 Int_t nus = 0;
2751 // Try to find a suitable file name that does not already exist.
2752 while (nus < 10) {
2753 uscore[nus] = '_';
2754 fname[0] = 0;
2755 strlcpy(fname, file->GetName(), kBufSize);
2756
2757 if (fFileNumber > 1) {
2758 char* cunder = strrchr(fname, '_');
2759 if (cunder) {
2760 snprintf(cunder, kBufSize - Int_t(cunder - fname), "%s%d", uscore, fFileNumber);
2761 const char* cdot = strrchr(file->GetName(), '.');
2762 if (cdot) {
2763 strlcat(fname, cdot, kBufSize);
2764 }
2765 } else {
2766 char fcount[21];
2767 snprintf(fcount,21, "%s%d", uscore, fFileNumber);
2768 strlcat(fname, fcount, kBufSize);
2769 }
2770 } else {
2771 char* cdot = strrchr(fname, '.');
2772 if (cdot) {
2773 snprintf(cdot, kBufSize - Int_t(fname-cdot), "%s%d", uscore, fFileNumber);
2774 strlcat(fname, strrchr(file->GetName(), '.'), kBufSize);
2775 } else {
2776 char fcount[21];
2777 snprintf(fcount,21, "%s%d", uscore, fFileNumber);
2778 strlcat(fname, fcount, kBufSize);
2779 }
2780 }
2781 if (gSystem->AccessPathName(fname)) {
2782 break;
2783 }
2784 ++nus;
2785 Warning("ChangeFile", "file %s already exist, trying with %d underscores", fname, nus+1);
2786 }
2787 Int_t compress = file->GetCompressionSettings();
2788 TFile* newfile = TFile::Open(fname, "recreate", "chain files", compress);
2789 if (newfile == 0) {
2790 Error("Fill","Failed to open new file %s, continuing as a memory tree.",fname);
2791 } else {
2792 Printf("Fill: Switching to new file: %s", fname);
2793 }
2794 // The current directory may contain histograms and trees.
2795 // These objects must be moved to the new file.
2796 TBranch* branch = 0;
2797 TObject* obj = 0;
2798 while ((obj = file->GetList()->First())) {
2799 file->Remove(obj);
2800 // Histogram: just change the directory.
2801 if (obj->InheritsFrom("TH1")) {
2802 gROOT->ProcessLine(TString::Format("((%s*)0x%lx)->SetDirectory((TDirectory*)0x%lx);", obj->ClassName(), (Long_t) obj, (Long_t) newfile));
2803 continue;
2804 }
2805 // Tree: must save all trees in the old file, reset them.
2806 if (obj->InheritsFrom(TTree::Class())) {
2807 TTree* t = (TTree*) obj;
2808 if (t != this) {
2809 t->AutoSave();
2810 t->Reset();
2812 }
2813 t->SetDirectory(newfile);
2814 TIter nextb(t->GetListOfBranches());
2815 while ((branch = (TBranch*)nextb())) {
2816 branch->SetFile(newfile);
2817 }
2818 if (t->GetBranchRef()) {
2819 t->GetBranchRef()->SetFile(newfile);
2820 }
2821 continue;
2822 }
2823 // Not a TH1 or a TTree, move object to new file.
2824 if (newfile) newfile->Append(obj);
2825 file->Remove(obj);
2826 }
2827 file->TObject::Delete();
2828 file = 0;
2829 delete[] fname;
2830 fname = 0;
2831 return newfile;
2832}
2833
2834////////////////////////////////////////////////////////////////////////////////
2835/// Check whether or not the address described by the last 3 parameters
2836/// matches the content of the branch. If a Data Model Evolution conversion
2837/// is involved, reset the fInfo of the branch.
2838/// The return values are:
2839//
2840/// - kMissingBranch (-5) : Missing branch
2841/// - kInternalError (-4) : Internal error (could not find the type corresponding to a data type number)
2842/// - kMissingCompiledCollectionProxy (-3) : Missing compiled collection proxy for a compiled collection
2843/// - kMismatch (-2) : Non-Class Pointer type given does not match the type expected by the branch
2844/// - kClassMismatch (-1) : Class Pointer type given does not match the type expected by the branch
2845/// - kMatch (0) : perfect match
2846/// - kMatchConversion (1) : match with (I/O) conversion
2847/// - kMatchConversionCollection (2) : match with (I/O) conversion of the content of a collection
2848/// - kMakeClass (3) : MakeClass mode so we can not check.
2849/// - kVoidPtr (4) : void* passed so no check was made.
2850/// - kNoCheck (5) : Underlying TBranch not yet available so no check was made.
2851/// In addition this can be multiplexed with the two bits:
2852/// - kNeedEnableDecomposedObj : in order for the address (type) to be 'usable' the branch needs to be in Decomposed Object (aka MakeClass) mode.
2853/// - kNeedDisableDecomposedObj : in order for the address (type) to be 'usable' the branch needs to not be in Decomposed Object (aka MakeClass) mode.
2854/// This bits can be masked out by using kDecomposedObjMask
2856Int_t TTree::CheckBranchAddressType(TBranch* branch, TClass* ptrClass, EDataType datatype, Bool_t isptr)
2857{
2858 if (GetMakeClass()) {
2859 // If we are in MakeClass mode so we do not really use classes.
2860 return kMakeClass;
2861 }
2862
2863 // Let's determine what we need!
2864 TClass* expectedClass = 0;
2865 EDataType expectedType = kOther_t;
2866 if (0 != branch->GetExpectedType(expectedClass,expectedType) ) {
2867 // Something went wrong, the warning message has already been issued.
2868 return kInternalError;
2869 }
2870 bool isBranchElement = branch->InheritsFrom( TBranchElement::Class() );
2871 if (expectedClass && datatype == kOther_t && ptrClass == 0) {
2872 if (isBranchElement) {
2873 TBranchElement* bEl = (TBranchElement*)branch;
2874 bEl->SetTargetClass( expectedClass->GetName() );
2875 }
2876 if (expectedClass && expectedClass->GetCollectionProxy() && dynamic_cast<TEmulatedCollectionProxy*>(expectedClass->GetCollectionProxy())) {
2877 Error("SetBranchAddress", "Unable to determine the type given for the address for \"%s\". "
2878 "The class expected (%s) refers to an stl collection and do not have a compiled CollectionProxy. "
2879 "Please generate the dictionary for this class (%s)",
2880 branch->GetName(), expectedClass->GetName(), expectedClass->GetName());
2882 }
2883 if (!expectedClass->IsLoaded()) {
2884 // The originally expected class does not have a dictionary, it is then plausible that the pointer being passed is the right type
2885 // (we really don't know). So let's express that.
2886 Error("SetBranchAddress", "Unable to determine the type given for the address for \"%s\". "
2887 "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."
2888 "Please generate the dictionary for this class (%s)",
2889 branch->GetName(), expectedClass->GetName(), expectedClass->GetName());
2890 } else {
2891 Error("SetBranchAddress", "Unable to determine the type given for the address for \"%s\". "
2892 "This is probably due to a missing dictionary, the original data class for this branch is %s.", branch->GetName(), expectedClass->GetName());
2893 }
2894 return kClassMismatch;
2895 }
2896 if (expectedClass && ptrClass && (branch->GetMother() == branch)) {
2897 // Top Level branch
2898 if (!isptr) {
2899 Error("SetBranchAddress", "The address for \"%s\" should be the address of a pointer!", branch->GetName());
2900 }
2901 }
2902 if (expectedType == kFloat16_t) {
2903 expectedType = kFloat_t;
2904 }
2905 if (expectedType == kDouble32_t) {
2906 expectedType = kDouble_t;
2907 }
2908 if (datatype == kFloat16_t) {
2909 datatype = kFloat_t;
2910 }
2911 if (datatype == kDouble32_t) {
2912 datatype = kDouble_t;
2913 }
2914
2915 /////////////////////////////////////////////////////////////////////////////
2916 // Deal with the class renaming
2917 /////////////////////////////////////////////////////////////////////////////
2918
2919 if( expectedClass && ptrClass &&
2920 expectedClass != ptrClass &&
2921 isBranchElement &&
2922 ptrClass->GetSchemaRules() &&
2923 ptrClass->GetSchemaRules()->HasRuleWithSourceClass( expectedClass->GetName() ) ) {
2924 TBranchElement* bEl = (TBranchElement*)branch;
2925
2926 if ( ptrClass->GetCollectionProxy() && expectedClass->GetCollectionProxy() ) {
2927 if (gDebug > 7)
2928 Info("SetBranchAddress", "Matching STL collection (at least according to the SchemaRuleSet when "
2929 "reading a %s into a %s",expectedClass->GetName(),ptrClass->GetName());
2930
2931 bEl->SetTargetClass( ptrClass->GetName() );
2932 return kMatchConversion;
2933
2934 } else if ( !ptrClass->GetConversionStreamerInfo( expectedClass, bEl->GetClassVersion() ) &&
2935 !ptrClass->FindConversionStreamerInfo( expectedClass, bEl->GetCheckSum() ) ) {
2936 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());
2937
2938 bEl->SetTargetClass( expectedClass->GetName() );
2939 return kClassMismatch;
2940 }
2941 else {
2942
2943 bEl->SetTargetClass( ptrClass->GetName() );
2944 return kMatchConversion;
2945 }
2946
2947 } else if (expectedClass && ptrClass && !expectedClass->InheritsFrom(ptrClass)) {
2948
2949 if (expectedClass->GetCollectionProxy() && ptrClass->GetCollectionProxy() &&
2950 isBranchElement &&
2951 expectedClass->GetCollectionProxy()->GetValueClass() &&
2952 ptrClass->GetCollectionProxy()->GetValueClass() )
2953 {
2954 // In case of collection, we know how to convert them, if we know how to convert their content.
2955 // NOTE: we need to extend this to std::pair ...
2956
2957 TClass *onfileValueClass = expectedClass->GetCollectionProxy()->GetValueClass();
2958 TClass *inmemValueClass = ptrClass->GetCollectionProxy()->GetValueClass();
2959
2960 if (inmemValueClass->GetSchemaRules() &&
2961 inmemValueClass->GetSchemaRules()->HasRuleWithSourceClass(onfileValueClass->GetName() ) )
2962 {
2963 TBranchElement* bEl = (TBranchElement*)branch;
2964 bEl->SetTargetClass( ptrClass->GetName() );
2966 }
2967 }
2968
2969 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());
2970 if (isBranchElement) {
2971 TBranchElement* bEl = (TBranchElement*)branch;
2972 bEl->SetTargetClass( expectedClass->GetName() );
2973 }
2974 return kClassMismatch;
2975
2976 } else if ((expectedType != kOther_t) && (datatype != kOther_t) && (expectedType != kNoType_t) && (datatype != kNoType_t) && (expectedType != datatype)) {
2977 if (datatype != kChar_t) {
2978 // For backward compatibility we assume that (char*) was just a cast and/or a generic address
2979 Error("SetBranchAddress", "The pointer type given \"%s\" (%d) does not correspond to the type needed \"%s\" (%d) by the branch: %s",
2980 TDataType::GetTypeName(datatype), datatype, TDataType::GetTypeName(expectedType), expectedType, branch->GetName());
2981 return kMismatch;
2982 }
2983 } else if ((expectedClass && (datatype != kOther_t && datatype != kNoType_t && datatype != kInt_t)) ||
2984 (ptrClass && (expectedType != kOther_t && expectedType != kNoType_t && datatype != kInt_t)) ) {
2985 // Sometime a null pointer can look an int, avoid complaining in that case.
2986 if (expectedClass) {
2987 Error("SetBranchAddress", "The pointer type given \"%s\" (%d) does not correspond to the type needed \"%s\" by the branch: %s",
2988 TDataType::GetTypeName(datatype), datatype, expectedClass->GetName(), branch->GetName());
2989 if (isBranchElement) {
2990 TBranchElement* bEl = (TBranchElement*)branch;
2991 bEl->SetTargetClass( expectedClass->GetName() );
2992 }
2993 } else {
2994 // 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
2995 // a struct).
2996 bool found = false;
2997 if (ptrClass->IsLoaded()) {
2998 TIter next(ptrClass->GetListOfRealData());
2999 TRealData *rdm;
3000 while ((rdm = (TRealData*)next())) {
3001 if (rdm->GetThisOffset() == 0) {
3002 TDataType *dmtype = rdm->GetDataMember()->GetDataType();
3003 if (dmtype) {
3004 EDataType etype = (EDataType)dmtype->GetType();
3005 if (etype == expectedType) {
3006 found = true;
3007 }
3008 }
3009 break;
3010 }
3011 }
3012 } else {
3013 TIter next(ptrClass->GetListOfDataMembers());
3014 TDataMember *dm;
3015 while ((dm = (TDataMember*)next())) {
3016 if (dm->GetOffset() == 0) {
3017 TDataType *dmtype = dm->GetDataType();
3018 if (dmtype) {
3019 EDataType etype = (EDataType)dmtype->GetType();
3020 if (etype == expectedType) {
3021 found = true;
3022 }
3023 }
3024 break;
3025 }
3026 }
3027 }
3028 if (found) {
3029 // let's check the size.
3030 TLeaf *last = (TLeaf*)branch->GetListOfLeaves()->Last();
3031 long len = last->GetOffset() + last->GetLenType() * last->GetLen();
3032 if (len <= ptrClass->Size()) {
3033 return kMatch;
3034 }
3035 }
3036 Error("SetBranchAddress", "The pointer type given \"%s\" does not correspond to the type needed \"%s\" (%d) by the branch: %s",
3037 ptrClass->GetName(), TDataType::GetTypeName(expectedType), expectedType, branch->GetName());
3038 }
3039 return kMismatch;
3040 }
3041 if (expectedClass && expectedClass->GetCollectionProxy() && dynamic_cast<TEmulatedCollectionProxy*>(expectedClass->GetCollectionProxy())) {
3042 Error("SetBranchAddress", writeStlWithoutProxyMsg,
3043 expectedClass->GetName(), branch->GetName(), expectedClass->GetName());
3044 if (isBranchElement) {
3045 TBranchElement* bEl = (TBranchElement*)branch;
3046 bEl->SetTargetClass( expectedClass->GetName() );
3047 }
3049 }
3050 if (isBranchElement) {
3051 if (expectedClass) {
3052 TBranchElement* bEl = (TBranchElement*)branch;
3053 bEl->SetTargetClass( expectedClass->GetName() );
3054 } else if (expectedType != kNoType_t && expectedType != kOther_t) {
3056 }
3057 }
3058 return kMatch;
3059}
3060
3061////////////////////////////////////////////////////////////////////////////////
3062/// Create a clone of this tree and copy nentries.
3063///
3064/// By default copy all entries.
3065/// The compression level of the cloned tree is set to the destination
3066/// file's compression level.
3067///
3068/// NOTE: Only active branches are copied.
3069/// NOTE: If the TTree is a TChain, the structure of the first TTree
3070/// is used for the copy.
3071///
3072/// IMPORTANT: The cloned tree stays connected with this tree until
3073/// this tree is deleted. In particular, any changes in
3074/// branch addresses in this tree are forwarded to the
3075/// clone trees, unless a branch in a clone tree has had
3076/// its address changed, in which case that change stays in
3077/// effect. When this tree is deleted, all the addresses of
3078/// the cloned tree are reset to their default values.
3079///
3080/// If 'option' contains the word 'fast' and nentries is -1, the
3081/// cloning will be done without unzipping or unstreaming the baskets
3082/// (i.e., a direct copy of the raw bytes on disk).
3083///
3084/// When 'fast' is specified, 'option' can also contain a sorting
3085/// order for the baskets in the output file.
3086///
3087/// There are currently 3 supported sorting order:
3088///
3089/// - SortBasketsByOffset (the default)
3090/// - SortBasketsByBranch
3091/// - SortBasketsByEntry
3092///
3093/// When using SortBasketsByOffset the baskets are written in the
3094/// output file in the same order as in the original file (i.e. the
3095/// baskets are sorted by their offset in the original file; Usually
3096/// this also means that the baskets are sorted by the index/number of
3097/// the _last_ entry they contain)
3098///
3099/// When using SortBasketsByBranch all the baskets of each individual
3100/// branches are stored contiguously. This tends to optimize reading
3101/// speed when reading a small number (1->5) of branches, since all
3102/// their baskets will be clustered together instead of being spread
3103/// across the file. However it might decrease the performance when
3104/// reading more branches (or the full entry).
3105///
3106/// When using SortBasketsByEntry the baskets with the lowest starting
3107/// entry are written first. (i.e. the baskets are sorted by the
3108/// index/number of the first entry they contain). This means that on
3109/// the file the baskets will be in the order in which they will be
3110/// needed when reading the whole tree sequentially.
3111///
3112/// For examples of CloneTree, see tutorials:
3113///
3114/// - copytree.C:
3115/// A macro to copy a subset of a TTree to a new TTree.
3116/// The input file has been generated by the program in
3117/// $ROOTSYS/test/Event with: Event 1000 1 1 1
3118///
3119/// - copytree2.C:
3120/// A macro to copy a subset of a TTree to a new TTree.
3121/// One branch of the new Tree is written to a separate file.
3122/// The input file has been generated by the program in
3123/// $ROOTSYS/test/Event with: Event 1000 1 1 1
3125TTree* TTree::CloneTree(Long64_t nentries /* = -1 */, Option_t* option /* = "" */)
3126{
3127 // Options
3128 Bool_t fastClone = kFALSE;
3129
3130 TString opt = option;
3131 opt.ToLower();
3132 if (opt.Contains("fast")) {
3133 fastClone = kTRUE;
3134 }
3135
3136 // If we are a chain, switch to the first tree.
3137 if ((fEntries > 0) && (LoadTree(0) < 0)) {
3138 // FIXME: We need an error message here.
3139 return 0;
3140 }
3141
3142 // Note: For a tree we get the this pointer, for
3143 // a chain we get the chain's current tree.
3144 TTree* thistree = GetTree();
3145
3146 // We will use this to override the IO features on the cloned branches.
3147 ROOT::TIOFeatures features = this->GetIOFeatures();
3148 ;
3149
3150 // Note: For a chain, the returned clone will be
3151 // a clone of the chain's first tree.
3152 TTree* newtree = (TTree*) thistree->Clone();
3153 if (!newtree) {
3154 return 0;
3155 }
3156
3157 // The clone should not delete any objects allocated by SetAddress().
3158 TObjArray* branches = newtree->GetListOfBranches();
3159 Int_t nb = branches->GetEntriesFast();
3160 for (Int_t i = 0; i < nb; ++i) {
3161 TBranch* br = (TBranch*) branches->UncheckedAt(i);
3162 if (br->InheritsFrom(TBranchElement::Class())) {
3163 ((TBranchElement*) br)->ResetDeleteObject();
3164 }
3165 }
3166
3167 // Add the new tree to the list of clones so that
3168 // we can later inform it of changes to branch addresses.
3169 thistree->AddClone(newtree);
3170 if (thistree != this) {
3171 // In case this object is a TChain, add the clone
3172 // also to the TChain's list of clones.
3173 AddClone(newtree);
3174 }
3175
3176 newtree->Reset();
3177
3178 TDirectory* ndir = newtree->GetDirectory();
3179 TFile* nfile = 0;
3180 if (ndir) {
3181 nfile = ndir->GetFile();
3182 }
3183 Int_t newcomp = -1;
3184 if (nfile) {
3185 newcomp = nfile->GetCompressionSettings();
3186 }
3187
3188 //
3189 // Delete non-active branches from the clone.
3190 //
3191 // Note: If we are a chain, this does nothing
3192 // since chains have no leaves.
3193 TObjArray* leaves = newtree->GetListOfLeaves();
3194 Int_t nleaves = leaves->GetEntriesFast();
3195 for (Int_t lndx = 0; lndx < nleaves; ++lndx) {
3196 TLeaf* leaf = (TLeaf*) leaves->UncheckedAt(lndx);
3197 if (!leaf) {
3198 continue;
3199 }
3200 TBranch* branch = leaf->GetBranch();
3201 if (branch && (newcomp > -1)) {
3202 branch->SetCompressionSettings(newcomp);
3203 }
3204 if (branch) branch->SetIOFeatures(features);
3205 if (!branch || !branch->TestBit(kDoNotProcess)) {
3206 continue;
3207 }
3208 // size might change at each iteration of the loop over the leaves.
3209 nb = branches->GetEntriesFast();
3210 for (Long64_t i = 0; i < nb; ++i) {
3211 TBranch* br = (TBranch*) branches->UncheckedAt(i);
3212 if (br == branch) {
3213 branches->RemoveAt(i);
3214 delete br;
3215 br = 0;
3216 branches->Compress();
3217 break;
3218 }
3219 TObjArray* lb = br->GetListOfBranches();
3220 Int_t nb1 = lb->GetEntriesFast();
3221 for (Int_t j = 0; j < nb1; ++j) {
3222 TBranch* b1 = (TBranch*) lb->UncheckedAt(j);
3223 if (!b1) {
3224 continue;
3225 }
3226 if (b1 == branch) {
3227 lb->RemoveAt(j);
3228 delete b1;
3229 b1 = 0;
3230 lb->Compress();
3231 break;
3232 }
3233 TObjArray* lb1 = b1->GetListOfBranches();
3234 Int_t nb2 = lb1->GetEntriesFast();
3235 for (Int_t k = 0; k < nb2; ++k) {
3236 TBranch* b2 = (TBranch*) lb1->UncheckedAt(k);
3237 if (!b2) {
3238 continue;
3239 }
3240 if (b2 == branch) {
3241 lb1->RemoveAt(k);
3242 delete b2;
3243 b2 = 0;
3244 lb1->Compress();
3245 break;
3246 }
3247 }
3248 }
3249 }
3250 }
3251 leaves->Compress();
3252
3253 // Copy MakeClass status.
3254 newtree->SetMakeClass(fMakeClass);
3255
3256 // Copy branch addresses.
3257 CopyAddresses(newtree);
3258
3259 //
3260 // Copy entries if requested.
3261 //
3262
3263 if (nentries != 0) {
3264 if (fastClone && (nentries < 0)) {
3265 if ( newtree->CopyEntries( this, -1, option, kFALSE ) < 0 ) {
3266 // There was a problem!
3267 Error("CloneTTree", "TTree has not been cloned\n");
3268 delete newtree;
3269 newtree = 0;
3270 return 0;
3271 }
3272 } else {
3273 newtree->CopyEntries( this, nentries, option, kFALSE );
3274 }
3275 }
3276
3277 return newtree;
3278}
3279
3280////////////////////////////////////////////////////////////////////////////////
3281/// Set branch addresses of passed tree equal to ours.
3282/// If undo is true, reset the branch address instead of copying them.
3283/// This insures 'separation' of a cloned tree from its original
3286{
3287 // Copy branch addresses starting from branches.
3288 TObjArray* branches = GetListOfBranches();
3289 Int_t nbranches = branches->GetEntriesFast();
3290 for (Int_t i = 0; i < nbranches; ++i) {
3291 TBranch* branch = (TBranch*) branches->UncheckedAt(i);
3292 if (branch->TestBit(kDoNotProcess)) {
3293 continue;
3294 }
3295 if (undo) {
3296 TBranch* br = tree->GetBranch(branch->GetName());
3297 tree->ResetBranchAddress(br);
3298 } else {
3299 char* addr = branch->GetAddress();
3300 if (!addr) {
3301 if (branch->IsA() == TBranch::Class()) {
3302 // If the branch was created using a leaflist, the branch itself may not have
3303 // an address but the leaf might already.
3304 TLeaf *firstleaf = (TLeaf*)branch->GetListOfLeaves()->At(0);
3305 if (!firstleaf || firstleaf->GetValuePointer()) {
3306 // Either there is no leaf (and thus no point in copying the address)
3307 // or the leaf has an address but we can not copy it via the branche
3308 // this will be copied via the next loop (over the leaf).
3309 continue;
3310 }
3311 }
3312 // Note: This may cause an object to be allocated.
3313 branch->SetAddress(0);
3314 addr = branch->GetAddress();
3315 }
3316 TBranch* br = tree->GetBranch(branch->GetFullName());
3317 if (br) {
3318 if (br->GetMakeClass() != branch->GetMakeClass())
3319 br->SetMakeClass(branch->GetMakeClass());
3320 br->SetAddress(addr);
3321 // The copy does not own any object allocated by SetAddress().
3322 if (br->InheritsFrom(TBranchElement::Class())) {
3323 ((TBranchElement*) br)->ResetDeleteObject();
3324 }
3325 } else {
3326 Warning("CopyAddresses", "Could not find branch named '%s' in tree named '%s'", branch->GetName(), tree->GetName());
3327 }
3328 }
3329 }
3330
3331 // Copy branch addresses starting from leaves.
3332 TObjArray* tleaves = tree->GetListOfLeaves();
3333 Int_t ntleaves = tleaves->GetEntriesFast();
3334 std::set<TLeaf*> updatedLeafCount;
3335 for (Int_t i = 0; i < ntleaves; ++i) {
3336 TLeaf* tleaf = (TLeaf*) tleaves->UncheckedAt(i);
3337 TBranch* tbranch = tleaf->GetBranch();
3338 TBranch* branch = GetBranch(tbranch->GetName());
3339 if (!branch) {
3340 continue;
3341 }
3342 TLeaf* leaf = branch->GetLeaf(tleaf->GetName());
3343 if (!leaf) {
3344 continue;
3345 }
3346 if (branch->TestBit(kDoNotProcess)) {
3347 continue;
3348 }
3349 if (undo) {
3350 // Now we know whether the address has been transfered
3351 tree->ResetBranchAddress(tbranch);
3352 } else {
3353 TBranchElement *mother = dynamic_cast<TBranchElement*>(leaf->GetBranch()->GetMother());
3354 bool needAddressReset = false;
3355 if (leaf->GetLeafCount() && (leaf->TestBit(TLeaf::kNewValue) || !leaf->GetValuePointer() || (mother && mother->IsObjectOwner())) && tleaf->GetLeafCount())
3356 {
3357 // If it is an array and it was allocated by the leaf itself,
3358 // let's make sure it is large enough for the incoming data.
3359 if (leaf->GetLeafCount()->GetMaximum() < tleaf->GetLeafCount()->GetMaximum()) {
3360 leaf->GetLeafCount()->IncludeRange( tleaf->GetLeafCount() );
3361 updatedLeafCount.insert(leaf->GetLeafCount());
3362 needAddressReset = true;
3363 } else {
3364 needAddressReset = (updatedLeafCount.find(leaf->GetLeafCount()) != updatedLeafCount.end());
3365 }
3366 }
3367 if (needAddressReset && leaf->GetValuePointer()) {
3368 if (leaf->IsA() == TLeafElement::Class() && mother)
3369 mother->ResetAddress();
3370 else
3371 leaf->SetAddress(nullptr);
3372 }
3373 if (!branch->GetAddress() && !leaf->GetValuePointer()) {
3374 // We should attempts to set the address of the branch.
3375 // something like:
3376 //(TBranchElement*)branch->GetMother()->SetAddress(0)
3377 //plus a few more subtleties (see TBranchElement::GetEntry).
3378 //but for now we go the simplest route:
3379 //
3380 // Note: This may result in the allocation of an object.
3381 branch->SetupAddresses();
3382 }
3383 if (branch->GetAddress()) {
3384 tree->SetBranchAddress(branch->GetName(), (void*) branch->GetAddress());
3385 TBranch* br = tree->GetBranch(branch->GetName());
3386 if (br) {
3387 if (br->IsA() != branch->IsA()) {
3388 Error(
3389 "CopyAddresses",
3390 "Branch kind mismatch between input tree '%s' and output tree '%s' for branch '%s': '%s' vs '%s'",
3391 tree->GetName(), br->GetTree()->GetName(), br->GetName(), branch->IsA()->GetName(),
3392 br->IsA()->GetName());
3393 }
3394 // The copy does not own any object allocated by SetAddress().
3395 // FIXME: We do too much here, br may not be a top-level branch.
3396 if (br->InheritsFrom(TBranchElement::Class())) {
3397 ((TBranchElement*) br)->ResetDeleteObject();
3398 }
3399 } else {
3400 Warning("CopyAddresses", "Could not find branch named '%s' in tree named '%s'", branch->GetName(), tree->GetName());
3401 }
3402 } else {
3403 tleaf->SetAddress(leaf->GetValuePointer());
3404 }
3405 }
3406 }
3407
3408 if (undo &&
3409 ( tree->IsA()->InheritsFrom("TNtuple") || tree->IsA()->InheritsFrom("TNtupleD") )
3410 ) {
3411 tree->ResetBranchAddresses();
3412 }
3413}
3414
3415namespace {
3416
3417 enum EOnIndexError { kDrop, kKeep, kBuild };
3418
3419 static Bool_t R__HandleIndex(EOnIndexError onIndexError, TTree *newtree, TTree *oldtree)
3420 {
3421 // Return true if we should continue to handle indices, false otherwise.
3422
3423 Bool_t withIndex = kTRUE;
3424
3425 if ( newtree->GetTreeIndex() ) {
3426 if ( oldtree->GetTree()->GetTreeIndex() == 0 ) {
3427 switch (onIndexError) {
3428 case kDrop:
3429 delete newtree->GetTreeIndex();
3430 newtree->SetTreeIndex(0);
3431 withIndex = kFALSE;
3432 break;
3433 case kKeep:
3434 // Nothing to do really.
3435 break;
3436 case kBuild:
3437 // Build the index then copy it
3438 if (oldtree->GetTree()->BuildIndex(newtree->GetTreeIndex()->GetMajorName(), newtree->GetTreeIndex()->GetMinorName())) {
3439 newtree->GetTreeIndex()->Append(oldtree->GetTree()->GetTreeIndex(), kTRUE);
3440 // Clean up
3441 delete oldtree->GetTree()->GetTreeIndex();
3442 oldtree->GetTree()->SetTreeIndex(0);
3443 }
3444 break;
3445 }
3446 } else {
3447 newtree->GetTreeIndex()->Append(oldtree->GetTree()->GetTreeIndex(), kTRUE);
3448 }
3449 } else if ( oldtree->GetTree()->GetTreeIndex() != 0 ) {
3450 // We discover the first index in the middle of the chain.
3451 switch (onIndexError) {
3452 case kDrop:
3453 // Nothing to do really.
3454 break;
3455 case kKeep: {
3456 TVirtualIndex *index = (TVirtualIndex*) oldtree->GetTree()->GetTreeIndex()->Clone();
3457 index->SetTree(newtree);
3458 newtree->SetTreeIndex(index);
3459 break;
3460 }
3461 case kBuild:
3462 if (newtree->GetEntries() == 0) {
3463 // Start an index.
3464 TVirtualIndex *index = (TVirtualIndex*) oldtree->GetTree()->GetTreeIndex()->Clone();
3465 index->SetTree(newtree);
3466 newtree->SetTreeIndex(index);
3467 } else {
3468 // Build the index so far.
3469 if (newtree->BuildIndex(oldtree->GetTree()->GetTreeIndex()->GetMajorName(), oldtree->GetTree()->GetTreeIndex()->GetMinorName())) {
3470 newtree->GetTreeIndex()->Append(oldtree->GetTree()->GetTreeIndex(), kTRUE);
3471 }
3472 }
3473 break;
3474 }
3475 } else if ( onIndexError == kDrop ) {
3476 // There is no index on this or on tree->GetTree(), we know we have to ignore any further
3477 // index
3478 withIndex = kFALSE;
3479 }
3480 return withIndex;
3481 }
3482}
3483
3484////////////////////////////////////////////////////////////////////////////////
3485/// Copy nentries from given tree to this tree.
3486/// This routines assumes that the branches that intended to be copied are
3487/// already connected. The typical case is that this tree was created using
3488/// tree->CloneTree(0).
3489///
3490/// By default copy all entries.
3491///
3492/// Returns number of bytes copied to this tree.
3493///
3494/// If 'option' contains the word 'fast' and nentries is -1, the cloning will be
3495/// done without unzipping or unstreaming the baskets (i.e., a direct copy of the
3496/// raw bytes on disk).
3497///
3498/// When 'fast' is specified, 'option' can also contains a sorting order for the
3499/// baskets in the output file.
3500///
3501/// There are currently 3 supported sorting order:
3502///
3503/// - SortBasketsByOffset (the default)
3504/// - SortBasketsByBranch
3505/// - SortBasketsByEntry
3506///
3507/// See TTree::CloneTree for a detailed explanation of the semantics of these 3 options.
3508///
3509/// If the tree or any of the underlying tree of the chain has an index, that index and any
3510/// index in the subsequent underlying TTree objects will be merged.
3511///
3512/// There are currently three 'options' to control this merging:
3513/// - NoIndex : all the TTreeIndex object are dropped.
3514/// - DropIndexOnError : if any of the underlying TTree object do no have a TTreeIndex,
3515/// they are all dropped.
3516/// - AsIsIndexOnError [default]: In case of missing TTreeIndex, the resulting TTree index has gaps.
3517/// - BuildIndexOnError : If any of the underlying TTree objects do not have a TTreeIndex,
3518/// all TTreeIndex are 'ignored' and the missing piece are rebuilt.
3520Long64_t TTree::CopyEntries(TTree* tree, Long64_t nentries /* = -1 */, Option_t* option /* = "" */, Bool_t needCopyAddresses /* = false */)
3521{
3522 if (!tree) {
3523 return 0;
3524 }
3525 // Options
3526 TString opt = option;
3527 opt.ToLower();
3528 Bool_t fastClone = opt.Contains("fast");
3529 Bool_t withIndex = !opt.Contains("noindex");
3530 EOnIndexError onIndexError;
3531 if (opt.Contains("asisindex")) {
3532 onIndexError = kKeep;
3533 } else if (opt.Contains("buildindex")) {
3534 onIndexError = kBuild;
3535 } else if (opt.Contains("dropindex")) {
3536 onIndexError = kDrop;
3537 } else {
3538 onIndexError = kBuild;
3539 }
3540 Ssiz_t cacheSizeLoc = opt.Index("cachesize=");
3541 Int_t cacheSize = -1;
3542 if (cacheSizeLoc != TString::kNPOS) {
3543 // If the parse faile, cacheSize stays at -1.
3544 Ssiz_t cacheSizeEnd = opt.Index(" ",cacheSizeLoc+10) - (cacheSizeLoc+10);
3545 TSubString cacheSizeStr( opt(cacheSizeLoc+10,cacheSizeEnd) );
3546 auto parseResult = ROOT::FromHumanReadableSize(cacheSizeStr,cacheSize);
3547 if (parseResult == ROOT::EFromHumanReadableSize::kParseFail) {
3548 Warning("CopyEntries","The cachesize option can not be parsed: %s. The default size will be used.",cacheSizeStr.String().Data());
3549 } else if (parseResult == ROOT::EFromHumanReadableSize::kOverflow) {
3550 double m;
3551 const char *munit = nullptr;
3552 ROOT::ToHumanReadableSize(std::numeric_limits<decltype(cacheSize)>::max(),false,&m,&munit);
3553
3554 Warning("CopyEntries","The cachesize option is too large: %s (%g%s max). The default size will be used.",cacheSizeStr.String().Data(),m,munit);
3555 }
3556 }
3557 if (gDebug > 0 && cacheSize != -1) Info("CopyEntries","Using Cache size: %d\n",cacheSize);
3558
3559 Long64_t nbytes = 0;
3560 Long64_t treeEntries = tree->GetEntriesFast();
3561 if (nentries < 0) {
3562 nentries = treeEntries;
3563 } else if (nentries > treeEntries) {
3564 nentries = treeEntries;
3565 }
3566
3567 if (fastClone && (nentries < 0 || nentries == tree->GetEntriesFast())) {
3568 // Quickly copy the basket without decompression and streaming.
3569 Long64_t totbytes = GetTotBytes();
3570 for (Long64_t i = 0; i < nentries; i += tree->GetTree()->GetEntries()) {
3571 if (tree->LoadTree(i) < 0) {
3572 break;
3573 }
3574 if ( withIndex ) {
3575 withIndex = R__HandleIndex( onIndexError, this, tree );
3576 }
3577 if (this->GetDirectory()) {
3578 TFile* file2 = this->GetDirectory()->GetFile();
3579 if (file2 && (file2->GetEND() > TTree::GetMaxTreeSize())) {
3580 if (this->GetDirectory() == (TDirectory*) file2) {
3581 this->ChangeFile(file2);
3582 }
3583 }
3584 }
3585 TTreeCloner cloner(tree->GetTree(), this, option, TTreeCloner::kNoWarnings);
3586 if (cloner.IsValid()) {
3587 this->SetEntries(this->GetEntries() + tree->GetTree()->GetEntries());
3588 if (cacheSize != -1) cloner.SetCacheSize(cacheSize);
3589 cloner.Exec();
3590 } else {
3591 if (i == 0) {
3592 Warning("CopyEntries","%s",cloner.GetWarning());
3593 // If the first cloning does not work, something is really wrong
3594 // (since apriori the source and target are exactly the same structure!)
3595 return -1;
3596 } else {
3597 if (cloner.NeedConversion()) {
3598 TTree *localtree = tree->GetTree();
3599 Long64_t tentries = localtree->GetEntries();
3600 if (needCopyAddresses) {
3601 // Copy MakeClass status.
3602 tree->SetMakeClass(fMakeClass);
3603 // Copy branch addresses.
3605 }
3606 for (Long64_t ii = 0; ii < tentries; ii++) {
3607 if (localtree->GetEntry(ii) <= 0) {
3608 break;
3609 }
3610 this->Fill();
3611 }
3612 if (needCopyAddresses)
3613 tree->ResetBranchAddresses();
3614 if (this->GetTreeIndex()) {
3615 this->GetTreeIndex()->Append(tree->GetTree()->GetTreeIndex(), kTRUE);
3616 }
3617 } else {
3618 Warning("CopyEntries","%s",cloner.GetWarning());
3619 if (tree->GetDirectory() && tree->GetDirectory()->GetFile()) {
3620 Warning("CopyEntries", "Skipped file %s\n", tree->GetDirectory()->GetFile()->GetName());
3621 } else {
3622 Warning("CopyEntries", "Skipped file number %d\n", tree->GetTreeNumber());
3623 }
3624 }
3625 }
3626 }
3627
3628 }
3629 if (this->GetTreeIndex()) {
3630 this->GetTreeIndex()->Append(0,kFALSE); // Force the sorting
3631 }
3632 nbytes = GetTotBytes() - totbytes;
3633 } else {
3634 if (nentries < 0) {
3635 nentries = treeEntries;
3636 } else if (nentries > treeEntries) {
3637 nentries = treeEntries;
3638 }
3639 if (needCopyAddresses) {
3640 // Copy MakeClass status.
3641 tree->SetMakeClass(fMakeClass);
3642 // Copy branch addresses.
3644 }
3645 Int_t treenumber = -1;
3646 for (Long64_t i = 0; i < nentries; i++) {
3647 if (tree->LoadTree(i) < 0) {
3648 break;
3649 }
3650 if (treenumber != tree->GetTreeNumber()) {
3651 if ( withIndex ) {
3652 withIndex = R__HandleIndex( onIndexError, this, tree );
3653 }
3654 treenumber = tree->GetTreeNumber();
3655 }
3656 if (tree->GetEntry(i) <= 0) {
3657 break;
3658 }
3659 nbytes += this->Fill();
3660 }
3661 if (needCopyAddresses)
3662 tree->ResetBranchAddresses();
3663 if (this->GetTreeIndex()) {
3664 this->GetTreeIndex()->Append(0,kFALSE); // Force the sorting
3665 }
3666 }
3667 return nbytes;
3668}
3669
3670////////////////////////////////////////////////////////////////////////////////
3671/// Copy a tree with selection.
3672///
3673/// ### Important:
3674///
3675/// The returned copied tree stays connected with the original tree
3676/// until the original tree is deleted. In particular, any changes
3677/// to the branch addresses in the original tree are also made to
3678/// the copied tree. Any changes made to the branch addresses of the
3679/// copied tree are overridden anytime the original tree changes its
3680/// branch addresses. When the original tree is deleted, all the
3681/// branch addresses of the copied tree are set to zero.
3682///
3683/// For examples of CopyTree, see the tutorials:
3684///
3685/// - copytree.C:
3686/// Example macro to copy a subset of a tree to a new tree.
3687/// The input file was generated by running the program in
3688/// $ROOTSYS/test/Event in this way:
3689/// ~~~ {.cpp}
3690/// ./Event 1000 1 1 1
3691/// ~~~
3692/// - copytree2.C
3693/// Example macro to copy a subset of a tree to a new tree.
3694/// One branch of the new tree is written to a separate file.
3695/// The input file was generated by running the program in
3696/// $ROOTSYS/test/Event in this way:
3697/// ~~~ {.cpp}
3698/// ./Event 1000 1 1 1
3699/// ~~~
3700/// - copytree3.C
3701/// Example macro to copy a subset of a tree to a new tree.
3702/// Only selected entries are copied to the new tree.
3703/// NOTE that only the active branches are copied.
3705TTree* TTree::CopyTree(const char* selection, Option_t* option /* = 0 */, Long64_t nentries /* = TTree::kMaxEntries */, Long64_t firstentry /* = 0 */)
3706{
3707 GetPlayer();
3708 if (fPlayer) {
3709 return fPlayer->CopyTree(selection, option, nentries, firstentry);
3710 }
3711 return 0;
3712}
3713
3714////////////////////////////////////////////////////////////////////////////////
3715/// Create a basket for this tree and given branch.
3718{
3719 if (!branch) {
3720 return 0;
3721 }
3722 return new TBasket(branch->GetName(), GetName(), branch);
3723}
3724
3725////////////////////////////////////////////////////////////////////////////////
3726/// Delete this tree from memory or/and disk.
3727///
3728/// - if option == "all" delete Tree object from memory AND from disk
3729/// all baskets on disk are deleted. All keys with same name
3730/// are deleted.
3731/// - if option =="" only Tree object in memory is deleted.
3733void TTree::Delete(Option_t* option /* = "" */)
3734{
3736
3737 // delete all baskets and header from file
3738 if (file && !strcmp(option,"all")) {
3739 if (!file->IsWritable()) {
3740 Error("Delete","File : %s is not writable, cannot delete Tree:%s", file->GetName(),GetName());
3741 return;
3742 }
3743
3744 //find key and import Tree header in memory
3745 TKey *key = fDirectory->GetKey(GetName());
3746 if (!key) return;
3747
3748 TDirectory *dirsav = gDirectory;
3749 file->cd();
3750
3751 //get list of leaves and loop on all the branches baskets
3752 TIter next(GetListOfLeaves());
3753 TLeaf *leaf;
3754 char header[16];
3755 Int_t ntot = 0;
3756 Int_t nbask = 0;
3757 Int_t nbytes,objlen,keylen;
3758 while ((leaf = (TLeaf*)next())) {
3759 TBranch *branch = leaf->GetBranch();
3760 Int_t nbaskets = branch->GetMaxBaskets();
3761 for (Int_t i=0;i<nbaskets;i++) {
3762 Long64_t pos = branch->GetBasketSeek(i);
3763 if (!pos) continue;
3764 TFile *branchFile = branch->GetFile();
3765 if (!branchFile) continue;
3766 branchFile->GetRecordHeader(header,pos,16,nbytes,objlen,keylen);
3767 if (nbytes <= 0) continue;
3768 branchFile->MakeFree(pos,pos+nbytes-1);
3769 ntot += nbytes;
3770 nbask++;
3771 }
3772 }
3773
3774 // delete Tree header key and all keys with the same name
3775 // A Tree may have been saved many times. Previous cycles are invalid.
3776 while (key) {
3777 ntot += key->GetNbytes();
3778 key->Delete();
3779 delete key;
3780 key = fDirectory->GetKey(GetName());
3781 }
3782 if (dirsav) dirsav->cd();
3783 if (gDebug) Info("TTree::Delete", "Deleting Tree: %s: %d baskets deleted. Total space freed = %d bytes\n",GetName(),nbask,ntot);
3784 }
3785
3786 if (fDirectory) {
3787 fDirectory->Remove(this);
3788 //delete the file cache if it points to this Tree
3790 fDirectory = 0;
3792 }
3793
3794 // Delete object from CINT symbol table so it can not be used anymore.
3795 gCling->DeleteGlobal(this);
3796
3797 // Warning: We have intentional invalidated this object while inside a member function!
3798 delete this;
3799}
3800
3801 ///////////////////////////////////////////////////////////////////////////////
3802 /// Called by TKey and TObject::Clone to automatically add us to a directory
3803 /// when we are read from a file.
3806{
3807 if (fDirectory == dir) return;
3808 if (fDirectory) {
3809 fDirectory->Remove(this);
3810 // Delete or move the file cache if it points to this Tree
3812 MoveReadCache(file,dir);
3813 }
3814 fDirectory = dir;
3815 TBranch* b = 0;
3816 TIter next(GetListOfBranches());
3817 while((b = (TBranch*) next())) {
3818 b->UpdateFile();
3819 }
3820 if (fBranchRef) {
3822 }
3823 if (fDirectory) fDirectory->Append(this);
3824}
3825
3826////////////////////////////////////////////////////////////////////////////////
3827/// Draw expression varexp for specified entries.
3828///
3829/// \return -1 in case of error or number of selected events in case of success.
3830///
3831/// This function accepts TCut objects as arguments.
3832/// Useful to use the string operator +
3833///
3834/// Example:
3835///
3836/// ~~~ {.cpp}
3837/// ntuple.Draw("x",cut1+cut2+cut3);
3838/// ~~~
3839
3841Long64_t TTree::Draw(const char* varexp, const TCut& selection, Option_t* option, Long64_t nentries, Long64_t firstentry)
3842{
3843 return TTree::Draw(varexp, selection.GetTitle(), option, nentries, firstentry);
3844}
3845
3846////////////////////////////////////////////////////////////////////////////////
3847/// Draw expression varexp for specified entries.
3848///
3849/// \return -1 in case of error or number of selected events in case of success.
3850///
3851/// \param [in] varexp is an expression of the general form
3852/// - "e1" produces a 1-d histogram (TH1F) of expression "e1"
3853/// - "e1:e2" produces an unbinned 2-d scatter-plot (TGraph) of "e1"
3854/// on the y-axis versus "e2" on the x-axis
3855/// - "e1:e2:e3" produces an unbinned 3-d scatter-plot (TPolyMarker3D) of "e1"
3856/// vs "e2" vs "e3" on the x-, y-, z-axis, respectively.
3857/// - "e1:e2:e3:e4" produces an unbinned 3-d scatter-plot (TPolyMarker3D) of "e1"
3858/// vs "e2" vs "e3" and "e4" mapped on the current color palette.
3859/// (to create histograms in the 2, 3, and 4 dimensional case,
3860/// see section "Saving the result of Draw to an histogram")
3861///
3862/// Example:
3863/// - varexp = x simplest case: draw a 1-Dim distribution of column named x
3864/// - varexp = sqrt(x) : draw distribution of sqrt(x)
3865/// - varexp = x*y/z
3866/// - varexp = y:sqrt(x) 2-Dim distribution of y versus sqrt(x)
3867/// - varexp = px:py:pz:2.5*E produces a 3-d scatter-plot of px vs py ps pz
3868/// and the color number of each marker will be 2.5*E.
3869/// If the color number is negative it is set to 0.
3870/// If the color number is greater than the current number of colors
3871/// it is set to the highest color number.The default number of
3872/// colors is 50. see TStyle::SetPalette for setting a new color palette.
3873///
3874/// Note that the variables e1, e2 or e3 may contain a selection.
3875/// example, if e1= x*(y<0), the value histogrammed will be x if y<0
3876/// and will be 0 otherwise.
3877///
3878/// The expressions can use all the operations and build-in functions
3879/// supported by TFormula (See TFormula::Analyze), including free
3880/// standing function taking numerical arguments (TMath::Bessel).
3881/// In addition, you can call member functions taking numerical
3882/// arguments. For example:
3883/// ~~~ {.cpp}
3884/// TMath::BreitWigner(fPx,3,2)
3885/// event.GetHistogram()->GetXaxis()->GetXmax()
3886/// ~~~
3887/// Note: You can only pass expression that depend on the TTree's data
3888/// to static functions and you can only call non-static member function
3889/// with 'fixed' parameters.
3890///
3891/// \param [in] selection is an expression with a combination of the columns.
3892/// In a selection all the C++ operators are authorized.
3893/// The value corresponding to the selection expression is used as a weight
3894/// to fill the histogram.
3895/// If the expression includes only boolean operations, the result
3896/// is 0 or 1. If the result is 0, the histogram is not filled.
3897/// In general, the expression may be of the form:
3898/// ~~~ {.cpp}
3899/// value*(boolean expression)
3900/// ~~~
3901/// if boolean expression is true, the histogram is filled with
3902/// a `weight = value`.
3903/// Examples:
3904/// - selection1 = "x<y && sqrt(z)>3.2"
3905/// - selection2 = "(x+y)*(sqrt(z)>3.2)"
3906/// - selection1 returns a weight = 0 or 1
3907/// - selection2 returns a weight = x+y if sqrt(z)>3.2
3908/// returns a weight = 0 otherwise.
3909///
3910/// \param [in] option is the drawing option.
3911/// - When an histogram is produced it can be any histogram drawing option
3912/// listed in THistPainter.
3913/// - when no option is specified:
3914/// - the default histogram drawing option is used
3915/// if the expression is of the form "e1".
3916/// - if the expression is of the form "e1:e2"or "e1:e2:e3" a cloud of
3917/// unbinned 2D or 3D points is drawn respectively.
3918/// - if the expression has four fields "e1:e2:e3:e4" a cloud of unbinned 3D
3919/// points is produced with e1 vs e2 vs e3, and e4 is mapped on the current color
3920/// palette.
3921/// - If option COL is specified when varexp has three fields:
3922/// ~~~ {.cpp}
3923/// tree.Draw("e1:e2:e3","","col");
3924/// ~~~
3925/// a 2D scatter is produced with e1 vs e2, and e3 is mapped on the current
3926/// color palette. The colors for e3 are evaluated once in linear scale before
3927/// painting. Therefore changing the pad to log scale along Z as no effect
3928/// on the colors.
3929/// - if expression has more than four fields the option "PARA"or "CANDLE"
3930/// can be used.
3931/// - If option contains the string "goff", no graphics is generated.
3932///
3933/// \param [in] nentries is the number of entries to process (default is all)
3934///
3935/// \param [in] firstentry is the first entry to process (default is 0)
3936///
3937/// ### Drawing expressions using arrays and array elements
3938///
3939/// Let assumes, a leaf fMatrix, on the branch fEvent, which is a 3 by 3 array,
3940/// or a TClonesArray.
3941/// In a TTree::Draw expression you can now access fMatrix using the following
3942/// syntaxes:
3943///
3944/// | String passed | What is used for each entry of the tree
3945/// |-----------------|--------------------------------------------------------|
3946/// | `fMatrix` | the 9 elements of fMatrix |
3947/// | `fMatrix[][]` | the 9 elements of fMatrix |
3948/// | `fMatrix[2][2]` | only the elements fMatrix[2][2] |
3949/// | `fMatrix[1]` | the 3 elements fMatrix[1][0], fMatrix[1][1] and fMatrix[1][2] |
3950/// | `fMatrix[1][]` | the 3 elements fMatrix[1][0], fMatrix[1][1] and fMatrix[1][2] |
3951/// | `fMatrix[][0]` | the 3 elements fMatrix[0][0], fMatrix[1][0] and fMatrix[2][0] |
3952///
3953/// "fEvent.fMatrix...." same as "fMatrix..." (unless there is more than one leaf named fMatrix!).
3954///
3955/// In summary, if a specific index is not specified for a dimension, TTree::Draw
3956/// will loop through all the indices along this dimension. Leaving off the
3957/// last (right most) dimension of specifying then with the two characters '[]'
3958/// is equivalent. For variable size arrays (and TClonesArray) the range
3959/// of the first dimension is recalculated for each entry of the tree.
3960/// You can also specify the index as an expression of any other variables from the
3961/// tree.
3962///
3963/// TTree::Draw also now properly handling operations involving 2 or more arrays.
3964///
3965/// Let assume a second matrix fResults[5][2], here are a sample of some
3966/// of the possible combinations, the number of elements they produce and
3967/// the loop used:
3968///
3969/// | expression | element(s) | Loop |
3970/// |----------------------------------|------------|--------------------------|
3971/// | `fMatrix[2][1] - fResults[5][2]` | one | no loop |
3972/// | `fMatrix[2][] - fResults[5][2]` | three | on 2nd dim fMatrix |
3973/// | `fMatrix[2][] - fResults[5][]` | two | on both 2nd dimensions |
3974/// | `fMatrix[][2] - fResults[][1]` | three | on both 1st dimensions |
3975/// | `fMatrix[][2] - fResults[][]` | six | on both 1st and 2nd dimensions of fResults |
3976/// | `fMatrix[][2] - fResults[3][]` | two | on 1st dim of fMatrix and 2nd of fResults (at the same time) |
3977/// | `fMatrix[][] - fResults[][]` | six | on 1st dim then on 2nd dim |
3978/// | `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.|
3979///
3980///
3981/// In summary, TTree::Draw loops through all unspecified dimensions. To
3982/// figure out the range of each loop, we match each unspecified dimension
3983/// from left to right (ignoring ALL dimensions for which an index has been
3984/// specified), in the equivalent loop matched dimensions use the same index
3985/// and are restricted to the smallest range (of only the matched dimensions).
3986/// When involving variable arrays, the range can of course be different
3987/// for each entry of the tree.
3988///
3989/// So the loop equivalent to "fMatrix[][2] - fResults[3][]" is:
3990/// ~~~ {.cpp}
3991/// for (Int_t i0; i < min(3,2); i++) {
3992/// use the value of (fMatrix[i0][2] - fMatrix[3][i0])
3993/// }
3994/// ~~~
3995/// So the loop equivalent to "fMatrix[][2] - fResults[][]" is:
3996/// ~~~ {.cpp}
3997/// for (Int_t i0; i < min(3,5); i++) {
3998/// for (Int_t i1; i1 < 2; i1++) {
3999/// use the value of (fMatrix[i0][2] - fMatrix[i0][i1])
4000/// }
4001/// }
4002/// ~~~
4003/// So the loop equivalent to "fMatrix[][] - fResults[][]" is:
4004/// ~~~ {.cpp}
4005/// for (Int_t i0; i < min(3,5); i++) {
4006/// for (Int_t i1; i1 < min(3,2); i1++) {
4007/// use the value of (fMatrix[i0][i1] - fMatrix[i0][i1])
4008/// }
4009/// }
4010/// ~~~
4011/// So the loop equivalent to "fMatrix[][fResults[][]]" is:
4012/// ~~~ {.cpp}
4013/// for (Int_t i0; i0 < 3; i0++) {
4014/// for (Int_t j2; j2 < 5; j2++) {
4015/// for (Int_t j3; j3 < 2; j3++) {
4016/// i1 = fResults[j2][j3];
4017/// use the value of fMatrix[i0][i1]
4018/// }
4019/// }
4020/// ~~~
4021/// ### Retrieving the result of Draw
4022///
4023/// By default a temporary histogram called `htemp` is created. It will be:
4024///
4025/// - A TH1F* in case of a mono-dimensional distribution: `Draw("e1")`,
4026/// - A TH2F* in case of a bi-dimensional distribution: `Draw("e1:e2")`,
4027/// - A TH3F* in case of a three-dimensional distribution: `Draw("e1:e2:e3")`.
4028///
4029/// In the one dimensional case the `htemp` is filled and drawn whatever the drawing
4030/// option is.
4031///
4032/// In the two and three dimensional cases, with the default drawing option (`""`),
4033/// a cloud of points is drawn and the histogram `htemp` is not filled. For all the other
4034/// drawing options `htemp` will be filled.
4035///
4036/// In all cases `htemp` can be retrieved by calling:
4037///
4038/// ~~~ {.cpp}
4039/// auto htemp = (TH1F*)gPad->GetPrimitive("htemp"); // 1D
4040/// auto htemp = (TH2F*)gPad->GetPrimitive("htemp"); // 2D
4041/// auto htemp = (TH3F*)gPad->GetPrimitive("htemp"); // 3D
4042/// ~~~
4043///
4044/// In the two dimensional case (`Draw("e1;e2")`), with the default drawing option, the
4045/// data is filled into a TGraph named `Graph`. This TGraph can be retrieved by
4046/// calling
4047///
4048/// ~~~ {.cpp}
4049/// auto graph = (TGraph*)gPad->GetPrimitive("Graph");
4050/// ~~~
4051///
4052/// For the three and four dimensional cases, with the default drawing option, an unnamed
4053/// TPolyMarker3D is produced, and therefore cannot be retrieved.
4054///
4055/// In all cases `htemp` can be used to access the axes. For instance in the 2D case:
4056///
4057/// ~~~ {.cpp}
4058/// auto htemp = (TH2F*)gPad->GetPrimitive("htemp");
4059/// auto xaxis = htemp->GetXaxis();
4060/// ~~~
4061///
4062/// When the option `"A"` is used (with TGraph painting option) to draw a 2D
4063/// distribution:
4064/// ~~~ {.cpp}
4065/// tree.Draw("e1:e2","","A*");
4066/// ~~~
4067/// a scatter plot is produced (with stars in that case) but the axis creation is
4068/// delegated to TGraph and `htemp` is not created.
4069///
4070/// ### Saving the result of Draw to a histogram
4071///
4072/// If `varexp` contains `>>hnew` (following the variable(s) name(s)),
4073/// the new histogram called `hnew` is created and it is kept in the current
4074/// directory (and also the current pad). This works for all dimensions.
4075///
4076/// Example:
4077/// ~~~ {.cpp}
4078/// tree.Draw("sqrt(x)>>hsqrt","y>0")
4079/// ~~~
4080/// will draw `sqrt(x)` and save the histogram as "hsqrt" in the current
4081/// directory. To retrieve it do:
4082/// ~~~ {.cpp}
4083/// TH1F *hsqrt = (TH1F*)gDirectory->Get("hsqrt");
4084/// ~~~
4085/// The binning information is taken from the environment variables
4086/// ~~~ {.cpp}
4087/// Hist.Binning.?D.?
4088/// ~~~
4089/// In addition, the name of the histogram can be followed by up to 9
4090/// numbers between '(' and ')', where the numbers describe the
4091/// following:
4092///
4093/// - 1 - bins in x-direction
4094/// - 2 - lower limit in x-direction
4095/// - 3 - upper limit in x-direction
4096/// - 4-6 same for y-direction
4097/// - 7-9 same for z-direction
4098///
4099/// When a new binning is used the new value will become the default.
4100/// Values can be skipped.
4101///
4102/// Example:
4103/// ~~~ {.cpp}
4104/// tree.Draw("sqrt(x)>>hsqrt(500,10,20)")
4105/// // plot sqrt(x) between 10 and 20 using 500 bins
4106/// tree.Draw("sqrt(x):sin(y)>>hsqrt(100,10,60,50,.1,.5)")
4107/// // plot sqrt(x) against sin(y)
4108/// // 100 bins in x-direction; lower limit on x-axis is 10; upper limit is 60
4109/// // 50 bins in y-direction; lower limit on y-axis is .1; upper limit is .5
4110/// ~~~
4111/// By default, the specified histogram is reset.
4112/// To continue to append data to an existing histogram, use "+" in front
4113/// of the histogram name.
4114///
4115/// A '+' in front of the histogram name is ignored, when the name is followed by
4116/// binning information as described in the previous paragraph.
4117/// ~~~ {.cpp}
4118/// tree.Draw("sqrt(x)>>+hsqrt","y>0")
4119/// ~~~
4120/// will not reset `hsqrt`, but will continue filling. This works for 1-D, 2-D
4121/// and 3-D histograms.
4122///
4123/// ### Accessing collection objects
4124///
4125/// TTree::Draw default's handling of collections is to assume that any
4126/// request on a collection pertain to it content. For example, if fTracks
4127/// is a collection of Track objects, the following:
4128/// ~~~ {.cpp}
4129/// tree->Draw("event.fTracks.fPx");
4130/// ~~~
4131/// will plot the value of fPx for each Track objects inside the collection.
4132/// Also
4133/// ~~~ {.cpp}
4134/// tree->Draw("event.fTracks.size()");
4135/// ~~~
4136/// would plot the result of the member function Track::size() for each
4137/// Track object inside the collection.
4138/// To access information about the collection itself, TTree::Draw support
4139/// the '@' notation. If a variable which points to a collection is prefixed
4140/// or postfixed with '@', the next part of the expression will pertain to
4141/// the collection object. For example:
4142/// ~~~ {.cpp}
4143/// tree->Draw("event.@fTracks.size()");
4144/// ~~~
4145/// will plot the size of the collection referred to by `fTracks` (i.e the number
4146/// of Track objects).
4147///
4148/// ### Drawing 'objects'
4149///
4150/// When a class has a member function named AsDouble or AsString, requesting
4151/// to directly draw the object will imply a call to one of the 2 functions.
4152/// If both AsDouble and AsString are present, AsDouble will be used.
4153/// AsString can return either a char*, a std::string or a TString.s
4154/// For example, the following
4155/// ~~~ {.cpp}
4156/// tree->Draw("event.myTTimeStamp");
4157/// ~~~
4158/// will draw the same histogram as
4159/// ~~~ {.cpp}
4160/// tree->Draw("event.myTTimeStamp.AsDouble()");
4161/// ~~~
4162/// In addition, when the object is a type TString or std::string, TTree::Draw
4163/// will call respectively `TString::Data` and `std::string::c_str()`
4164///
4165/// If the object is a TBits, the histogram will contain the index of the bit
4166/// that are turned on.
4167///
4168/// ### Retrieving information about the tree itself.
4169///
4170/// You can refer to the tree (or chain) containing the data by using the
4171/// string 'This'.
4172/// You can then could any TTree methods. For example:
4173/// ~~~ {.cpp}
4174/// tree->Draw("This->GetReadEntry()");
4175/// ~~~
4176/// will display the local entry numbers be read.
4177/// ~~~ {.cpp}
4178/// tree->Draw("This->GetUserInfo()->At(0)->GetName()");
4179/// ~~~
4180/// will display the name of the first 'user info' object.
4181///
4182/// ### Special functions and variables
4183///
4184/// `Entry$`: A TTree::Draw formula can use the special variable `Entry$`
4185/// to access the entry number being read. For example to draw every
4186/// other entry use:
4187/// ~~~ {.cpp}
4188/// tree.Draw("myvar","Entry$%2==0");
4189/// ~~~
4190/// - `Entry$` : return the current entry number (`== TTree::GetReadEntry()`)
4191/// - `LocalEntry$` : return the current entry number in the current tree of a
4192/// chain (`== GetTree()->GetReadEntry()`)
4193/// - `Entries$` : return the total number of entries (== TTree::GetEntries())
4194/// - `LocalEntries$` : return the total number of entries in the current tree
4195/// of a chain (== GetTree()->TTree::GetEntries())
4196/// - `Length$` : return the total number of element of this formula for this
4197/// entry (`==TTreeFormula::GetNdata()`)
4198/// - `Iteration$` : return the current iteration over this formula for this
4199/// entry (i.e. varies from 0 to `Length$`).
4200/// - `Length$(formula )` : return the total number of element of the formula
4201/// given as a parameter.
4202/// - `Sum$(formula )` : return the sum of the value of the elements of the
4203/// formula given as a parameter. For example the mean for all the elements in
4204/// one entry can be calculated with: `Sum$(formula )/Length$(formula )`
4205/// - `Min$(formula )` : return the minimun (within one TTree entry) of the value of the
4206/// elements of the formula given as a parameter.
4207/// - `Max$(formula )` : return the maximum (within one TTree entry) of the value of the
4208/// elements of the formula given as a parameter.
4209/// - `MinIf$(formula,condition)`
4210/// - `MaxIf$(formula,condition)` : return the minimum (maximum) (within one TTree entry)
4211/// of the value of the elements of the formula given as a parameter
4212/// if they match the condition. If no element matches the condition,
4213/// the result is zero. To avoid the resulting peak at zero, use the
4214/// pattern:
4215/// ~~~ {.cpp}
4216/// tree->Draw("MinIf$(formula,condition)","condition");
4217/// ~~~
4218/// which will avoid calculation `MinIf$` for the entries that have no match
4219/// for the condition.
4220/// - `Alt$(primary,alternate)` : return the value of "primary" if it is available
4221/// for the current iteration otherwise return the value of "alternate".
4222/// For example, with arr1[3] and arr2[2]
4223/// ~~~ {.cpp}
4224/// tree->Draw("arr1+Alt$(arr2,0)");
4225/// ~~~
4226/// will draw arr1[0]+arr2[0] ; arr1[1]+arr2[1] and arr1[2]+0
4227/// Or with a variable size array arr3
4228/// ~~~ {.cpp}
4229/// tree->Draw("Alt$(arr3[0],0)+Alt$(arr3[1],0)+Alt$(arr3[2],0)");
4230/// ~~~
4231/// will draw the sum arr3 for the index 0 to min(2,actual_size_of_arr3-1)
4232/// As a comparison
4233/// ~~~ {.cpp}
4234/// tree->Draw("arr3[0]+arr3[1]+arr3[2]");
4235/// ~~~
4236/// will draw the sum arr3 for the index 0 to 2 only if the
4237/// actual_size_of_arr3 is greater or equal to 3.
4238/// Note that the array in 'primary' is flattened/linearized thus using
4239/// `Alt$` with multi-dimensional arrays of different dimensions in unlikely
4240/// to yield the expected results. To visualize a bit more what elements
4241/// would be matched by TTree::Draw, TTree::Scan can be used:
4242/// ~~~ {.cpp}
4243/// tree->Scan("arr1:Alt$(arr2,0)");
4244/// ~~~
4245/// will print on one line the value of arr1 and (arr2,0) that will be
4246/// matched by
4247/// ~~~ {.cpp}
4248/// tree->Draw("arr1-Alt$(arr2,0)");
4249/// ~~~
4250/// The ternary operator is not directly supported in TTree::Draw however, to plot the
4251/// equivalent of `var2<20 ? -99 : var1`, you can use:
4252/// ~~~ {.cpp}
4253/// tree->Draw("(var2<20)*99+(var2>=20)*var1","");
4254/// ~~~
4255///
4256/// ### Drawing a user function accessing the TTree data directly
4257///
4258/// If the formula contains a file name, TTree::MakeProxy will be used
4259/// to load and execute this file. In particular it will draw the
4260/// result of a function with the same name as the file. The function
4261/// will be executed in a context where the name of the branches can
4262/// be used as a C++ variable.
4263///
4264/// For example draw px using the file hsimple.root (generated by the
4265/// hsimple.C tutorial), we need a file named hsimple.cxx:
4266/// ~~~ {.cpp}
4267/// double hsimple() {
4268/// return px;
4269/// }
4270/// ~~~
4271/// MakeProxy can then be used indirectly via the TTree::Draw interface
4272/// as follow:
4273/// ~~~ {.cpp}
4274/// new TFile("hsimple.root")
4275/// ntuple->Draw("hsimple.cxx");
4276/// ~~~
4277/// A more complete example is available in the tutorials directory:
4278/// `h1analysisProxy.cxx`, `h1analysProxy.h` and `h1analysisProxyCut.C`
4279/// which reimplement the selector found in `h1analysis.C`
4280///
4281/// The main features of this facility are:
4282///
4283/// * on-demand loading of branches
4284/// * ability to use the 'branchname' as if it was a data member
4285/// * protection against array out-of-bound
4286/// * ability to use the branch data as object (when the user code is available)
4287///
4288/// See TTree::MakeProxy for more details.
4289///
4290/// ### Making a Profile histogram
4291///
4292/// In case of a 2-Dim expression, one can generate a TProfile histogram
4293/// instead of a TH2F histogram by specifying option=prof or option=profs
4294/// or option=profi or option=profg ; the trailing letter select the way
4295/// the bin error are computed, See TProfile2D::SetErrorOption for
4296/// details on the differences.
4297/// The option=prof is automatically selected in case of y:x>>pf
4298/// where pf is an existing TProfile histogram.
4299///
4300/// ### Making a 2D Profile histogram
4301///
4302/// In case of a 3-Dim expression, one can generate a TProfile2D histogram
4303/// instead of a TH3F histogram by specifying option=prof or option=profs.
4304/// or option=profi or option=profg ; the trailing letter select the way
4305/// the bin error are computed, See TProfile2D::SetErrorOption for
4306/// details on the differences.
4307/// The option=prof is automatically selected in case of z:y:x>>pf
4308/// where pf is an existing TProfile2D histogram.
4309///
4310/// ### Making a 5D plot using GL
4311///
4312/// If option GL5D is specified together with 5 variables, a 5D plot is drawn
4313/// using OpenGL. See $ROOTSYS/tutorials/tree/staff.C as example.
4314///
4315/// ### Making a parallel coordinates plot
4316///
4317/// In case of a 2-Dim or more expression with the option=para, one can generate
4318/// a parallel coordinates plot. With that option, the number of dimensions is
4319/// arbitrary. Giving more than 4 variables without the option=para or
4320/// option=candle or option=goff will produce an error.
4321///
4322/// ### Making a candle sticks chart
4323///
4324/// In case of a 2-Dim or more expression with the option=candle, one can generate
4325/// a candle sticks chart. With that option, the number of dimensions is
4326/// arbitrary. Giving more than 4 variables without the option=para or
4327/// option=candle or option=goff will produce an error.
4328///
4329/// ### Normalizing the output histogram to 1
4330///
4331/// When option contains "norm" the output histogram is normalized to 1.
4332///
4333/// ### Saving the result of Draw to a TEventList, a TEntryList or a TEntryListArray
4334///
4335/// TTree::Draw can be used to fill a TEventList object (list of entry numbers)
4336/// instead of histogramming one variable.
4337/// If varexp0 has the form >>elist , a TEventList object named "elist"
4338/// is created in the current directory. elist will contain the list
4339/// of entry numbers satisfying the current selection.
4340/// If option "entrylist" is used, a TEntryList object is created
4341/// If the selection contains arrays, vectors or any container class and option
4342/// "entrylistarray" is used, a TEntryListArray object is created
4343/// containing also the subentries satisfying the selection, i.e. the indices of
4344/// the branches which hold containers classes.
4345/// Example:
4346/// ~~~ {.cpp}
4347/// tree.Draw(">>yplus","y>0")
4348/// ~~~
4349/// will create a TEventList object named "yplus" in the current directory.
4350/// In an interactive session, one can type (after TTree::Draw)
4351/// ~~~ {.cpp}
4352/// yplus.Print("all")
4353/// ~~~
4354/// to print the list of entry numbers in the list.
4355/// ~~~ {.cpp}
4356/// tree.Draw(">>yplus", "y>0", "entrylist")
4357/// ~~~
4358/// will create a TEntryList object names "yplus" in the current directory
4359/// ~~~ {.cpp}
4360/// tree.Draw(">>yplus", "y>0", "entrylistarray")
4361/// ~~~
4362/// will create a TEntryListArray object names "yplus" in the current directory
4363///
4364/// By default, the specified entry list is reset.
4365/// To continue to append data to an existing list, use "+" in front
4366/// of the list name;
4367/// ~~~ {.cpp}
4368/// tree.Draw(">>+yplus","y>0")
4369/// ~~~
4370/// will not reset yplus, but will enter the selected entries at the end
4371/// of the existing list.
4372///
4373/// ### Using a TEventList, TEntryList or TEntryListArray as Input
4374///
4375/// Once a TEventList or a TEntryList object has been generated, it can be used as input
4376/// for TTree::Draw. Use TTree::SetEventList or TTree::SetEntryList to set the
4377/// current event list
4378///
4379/// Example 1:
4380/// ~~~ {.cpp}
4381/// TEventList *elist = (TEventList*)gDirectory->Get("yplus");
4382/// tree->SetEventList(elist);
4383/// tree->Draw("py");
4384/// ~~~
4385/// Example 2:
4386/// ~~~ {.cpp}
4387/// TEntryList *elist = (TEntryList*)gDirectory->Get("yplus");
4388/// tree->SetEntryList(elist);
4389/// tree->Draw("py");
4390/// ~~~
4391/// If a TEventList object is used as input, a new TEntryList object is created
4392/// inside the SetEventList function. In case of a TChain, all tree headers are loaded
4393/// for this transformation. This new object is owned by the chain and is deleted
4394/// with it, unless the user extracts it by calling GetEntryList() function.
4395/// See also comments to SetEventList() function of TTree and TChain.
4396///
4397/// If arrays are used in the selection criteria and TEntryListArray is not used,
4398/// all the entries that have at least one element of the array that satisfy the selection
4399/// are entered in the list.
4400///
4401/// Example:
4402/// ~~~ {.cpp}
4403/// tree.Draw(">>pyplus","fTracks.fPy>0");
4404/// tree->SetEventList(pyplus);
4405/// tree->Draw("fTracks.fPy");
4406/// ~~~
4407/// will draw the fPy of ALL tracks in event with at least one track with
4408/// a positive fPy.
4409///
4410/// To select only the elements that did match the original selection
4411/// use TEventList::SetReapplyCut or TEntryList::SetReapplyCut.
4412///
4413/// Example:
4414/// ~~~ {.cpp}
4415/// tree.Draw(">>pyplus","fTracks.fPy>0");
4416/// pyplus->SetReapplyCut(kTRUE);
4417/// tree->SetEventList(pyplus);
4418/// tree->Draw("fTracks.fPy");
4419/// ~~~
4420/// will draw the fPy of only the tracks that have a positive fPy.
4421///
4422/// To draw only the elements that match a selection in case of arrays,
4423/// you can also use TEntryListArray (faster in case of a more general selection).
4424///
4425/// Example:
4426/// ~~~ {.cpp}
4427/// tree.Draw(">>pyplus","fTracks.fPy>0", "entrylistarray");
4428/// tree->SetEntryList(pyplus);
4429/// tree->Draw("fTracks.fPy");
4430/// ~~~
4431/// will draw the fPy of only the tracks that have a positive fPy,
4432/// but without redoing the selection.
4433///
4434/// Note: Use tree->SetEventList(0) if you do not want use the list as input.
4435///
4436/// ### How to obtain more info from TTree::Draw
4437///
4438/// Once TTree::Draw has been called, it is possible to access useful
4439/// information still stored in the TTree object via the following functions:
4440///
4441/// - GetSelectedRows() // return the number of values accepted by the selection expression. In case where no selection was specified, returns the number of values processed.
4442/// - GetV1() // returns a pointer to the double array of V1
4443/// - GetV2() // returns a pointer to the double array of V2
4444/// - GetV3() // returns a pointer to the double array of V3
4445/// - GetV4() // returns a pointer to the double array of V4
4446/// - GetW() // returns a pointer to the double array of Weights where weight equal the result of the selection expression.
4447///
4448/// where V1,V2,V3 correspond to the expressions in
4449/// ~~~ {.cpp}
4450/// TTree::Draw("V1:V2:V3:V4",selection);
4451/// ~~~
4452/// If the expression has more than 4 component use GetVal(index)
4453///
4454/// Example:
4455/// ~~~ {.cpp}
4456/// Root > ntuple->Draw("py:px","pz>4");
4457/// Root > TGraph *gr = new TGraph(ntuple->GetSelectedRows(),
4458/// ntuple->GetV2(), ntuple->GetV1());
4459/// Root > gr->Draw("ap"); //draw graph in current pad
4460/// ~~~
4461///
4462/// A more complete complete tutorial (treegetval.C) shows how to use the
4463/// GetVal() method.
4464///
4465/// creates a TGraph object with a number of points corresponding to the
4466/// number of entries selected by the expression "pz>4", the x points of the graph
4467/// being the px values of the Tree and the y points the py values.
4468///
4469/// Important note: By default TTree::Draw creates the arrays obtained
4470/// with GetW, GetV1, GetV2, GetV3, GetV4, GetVal with a length corresponding
4471/// to the parameter fEstimate. The content will be the last `GetSelectedRows() % GetEstimate()`
4472/// values calculated.
4473/// By default fEstimate=1000000 and can be modified
4474/// via TTree::SetEstimate. To keep in memory all the results (in case
4475/// where there is only one result per entry), use
4476/// ~~~ {.cpp}
4477/// tree->SetEstimate(tree->GetEntries()+1); // same as tree->SetEstimate(-1);
4478/// ~~~
4479/// You must call SetEstimate if the expected number of selected rows
4480/// you need to look at is greater than 1000000.
4481///
4482/// You can use the option "goff" to turn off the graphics output
4483/// of TTree::Draw in the above example.
4484///
4485/// ### Automatic interface to TTree::Draw via the TTreeViewer
4486///
4487/// A complete graphical interface to this function is implemented
4488/// in the class TTreeViewer.
4489/// To start the TTreeViewer, three possibilities:
4490/// - select TTree context menu item "StartViewer"
4491/// - type the command "TTreeViewer TV(treeName)"
4492/// - execute statement "tree->StartViewer();"
4494Long64_t TTree::Draw(const char* varexp, const char* selection, Option_t* option, Long64_t nentries, Long64_t firstentry)
4495{
4496 GetPlayer();
4497 if (fPlayer)
4498 return fPlayer->DrawSelect(varexp,selection,option,nentries,firstentry);
4499 return -1;
4500}
4501
4502////////////////////////////////////////////////////////////////////////////////
4503/// Remove some baskets from memory.
4505void TTree::DropBaskets()
4506{
4507 TBranch* branch = 0;
4509 for (Int_t i = 0; i < nb; ++i) {
4510 branch = (TBranch*) fBranches.UncheckedAt(i);
4511 branch->DropBaskets("all");
4512 }
4513}
4514
4515////////////////////////////////////////////////////////////////////////////////
4516/// Drop branch buffers to accommodate nbytes below MaxVirtualsize.
4519{
4520 // Be careful not to remove current read/write buffers.
4521 Int_t ndrop = 0;
4522 Int_t nleaves = fLeaves.GetEntriesFast();
4523 for (Int_t i = 0; i < nleaves; ++i) {
4524 TLeaf* leaf = (TLeaf*) fLeaves.UncheckedAt(i);
4525 TBranch* branch = (TBranch*) leaf->GetBranch();
4526 Int_t nbaskets = branch->GetListOfBaskets()->GetEntries();
4527 for (Int_t j = 0; j < nbaskets - 1; ++j) {
4528 if ((j == branch->GetReadBasket()) || (j == branch->GetWriteBasket())) {
4529 continue;
4530 }
4531 TBasket* basket = (TBasket*)branch->GetListOfBaskets()->UncheckedAt(j);
4532 if (basket) {
4533 ndrop += basket->DropBuffers();
4535 return;
4536 }
4537 }
4538 }
4539 }
4540}
4541
4542////////////////////////////////////////////////////////////////////////////////
4543/// Fill all branches.
4544///
4545/// This function loops on all the branches of this tree. For
4546/// each branch, it copies to the branch buffer (basket) the current
4547/// values of the leaves data types. If a leaf is a simple data type,
4548/// a simple conversion to a machine independent format has to be done.
4549///
4550/// This machine independent version of the data is copied into a
4551/// basket (each branch has its own basket). When a basket is full
4552/// (32k worth of data by default), it is then optionally compressed
4553/// and written to disk (this operation is also called committing or
4554/// 'flushing' the basket). The committed baskets are then
4555/// immediately removed from memory.
4556///
4557/// The function returns the number of bytes committed to the
4558/// individual branches.
4559///
4560/// If a write error occurs, the number of bytes returned is -1.
4561///
4562/// If no data are written, because, e.g., the branch is disabled,
4563/// the number of bytes returned is 0.
4564///
4565/// __The baskets are flushed and the Tree header saved at regular intervals__
4566///
4567/// At regular intervals, when the amount of data written so far is
4568/// greater than fAutoFlush (see SetAutoFlush) all the baskets are flushed to disk.
4569/// This makes future reading faster as it guarantees that baskets belonging to nearby
4570/// entries will be on the same disk region.
4571/// When the first call to flush the baskets happen, we also take this opportunity
4572/// to optimize the baskets buffers.
4573/// We also check if the amount of data written is greater than fAutoSave (see SetAutoSave).
4574/// In this case we also write the Tree header. This makes the Tree recoverable up to this point
4575/// in case the program writing the Tree crashes.
4576/// The decisions to FlushBaskets and Auto Save can be made based either on the number
4577/// of bytes written (fAutoFlush and fAutoSave negative) or on the number of entries
4578/// written (fAutoFlush and fAutoSave positive).
4579/// Note that the user can decide to call FlushBaskets and AutoSave in her event loop
4580/// base on the number of events written instead of the number of bytes written.
4581///
4582/// \note Calling `TTree::FlushBaskets` too often increases the IO time.
4583///
4584/// \note Calling `TTree::AutoSave` too often increases the IO time and also the
4585/// file size.
4586///
4587/// \note This method calls `TTree::ChangeFile` when the tree reaches a size
4588/// greater than `TTree::fgMaxTreeSize`. This doesn't happen if the tree is
4589/// attached to a `TMemFile` or derivate.
4592{
4593 Int_t nbytes = 0;
4594 Int_t nwrite = 0;
4595 Int_t nerror = 0;
4596 Int_t nbranches = fBranches.GetEntriesFast();
4597
4598 // Case of one single super branch. Automatically update
4599 // all the branch addresses if a new object was created.
4600 if (nbranches == 1)
4601 ((TBranch *)fBranches.UncheckedAt(0))->UpdateAddress();
4602
4603 if (fBranchRef)
4604 fBranchRef->Clear();
4605
4606#ifdef R__USE_IMT
4607 const auto useIMT = ROOT::IsImplicitMTEnabled() && fIMTEnabled;
4609 if (useIMT) {
4610 fIMTFlush = true;
4611 fIMTZipBytes.store(0);
4612 fIMTTotBytes.store(0);
4613 }
4614#endif
4615
4616 for (Int_t i = 0; i < nbranches; ++i) {
4617 // Loop over all branches, filling and accumulating bytes written and error counts.
4618 TBranch *branch = (TBranch *)fBranches.UncheckedAt(i);
4619
4620 if (branch->TestBit(kDoNotProcess))
4621 continue;
4622
4623#ifndef R__USE_IMT
4624 nwrite = branch->FillImpl(nullptr);
4625#else
4626 nwrite = branch->FillImpl(useIMT ? &imtHelper : nullptr);
4627#endif
4628 if (nwrite < 0) {
4629 if (nerror < 2) {
4630 Error("Fill", "Failed filling branch:%s.%s, nbytes=%d, entry=%lld\n"
4631 " This error is symptomatic of a Tree created as a memory-resident Tree\n"
4632 " Instead of doing:\n"
4633 " TTree *T = new TTree(...)\n"
4634 " TFile *f = new TFile(...)\n"
4635 " you should do:\n"
4636 " TFile *f = new TFile(...)\n"
4637 " TTree *T = new TTree(...)\n\n",
4638 GetName(), branch->GetName(), nwrite, fEntries + 1);
4639 } else {
4640 Error("Fill", "Failed filling branch:%s.%s, nbytes=%d, entry=%lld", GetName(), branch->GetName(), nwrite,
4641 fEntries + 1);
4642 }
4643 ++nerror;
4644 } else {
4645 nbytes += nwrite;
4646 }
4647 }
4648
4649#ifdef R__USE_IMT
4650 if (fIMTFlush) {
4651 imtHelper.Wait();
4652 fIMTFlush = false;
4653 const_cast<TTree *>(this)->AddTotBytes(fIMTTotBytes);
4654 const_cast<TTree *>(this)->AddZipBytes(fIMTZipBytes);
4655 nbytes += imtHelper.GetNbytes();
4656 nerror += imtHelper.GetNerrors();
4657 }
4658#endif
4659
4660 if (fBranchRef)
4661 fBranchRef->Fill();
4662
4663 ++fEntries;
4664
4665 if (fEntries > fMaxEntries)
4666 KeepCircular();
4667
4668 if (gDebug > 0)
4669 Info("TTree::Fill", " - A: %d %lld %lld %lld %lld %lld %lld \n", nbytes, fEntries, fAutoFlush, fAutoSave,
4671
4672 bool autoFlush = false;
4673 bool autoSave = false;
4674
4675 if (fAutoFlush != 0 || fAutoSave != 0) {
4676 // Is it time to flush or autosave baskets?
4677 if (fFlushedBytes == 0) {
4678 // If fFlushedBytes == 0, it means we never flushed or saved, so
4679 // we need to check if it's time to do it and recompute the values
4680 // of fAutoFlush and fAutoSave in terms of the number of entries.
4681 // Decision can be based initially either on the number of bytes
4682 // or the number of entries written.
4683 Long64_t zipBytes = GetZipBytes();
4684
4685 if (fAutoFlush)
4686 autoFlush = fAutoFlush < 0 ? (zipBytes > -fAutoFlush) : fEntries % fAutoFlush == 0;
4687
4688 if (fAutoSave)
4689 autoSave = fAutoSave < 0 ? (zipBytes > -fAutoSave) : fEntries % fAutoSave == 0;
4690
4691 if (autoFlush || autoSave) {
4692 // First call FlushBasket to make sure that fTotBytes is up to date.
4694 autoFlush = false; // avoid auto flushing again later
4695
4696 // When we are in one-basket-per-cluster mode, there is no need to optimize basket:
4697 // they will automatically grow to the size needed for an event cluster (with the basket
4698 // shrinking preventing them from growing too much larger than the actually-used space).
4700 OptimizeBaskets(GetTotBytes(), 1, "");
4701 if (gDebug > 0)
4702 Info("TTree::Fill", "OptimizeBaskets called at entry %lld, fZipBytes=%lld, fFlushedBytes=%lld\n",
4704 }
4706 fAutoFlush = fEntries; // Use test on entries rather than bytes
4707
4708 // subsequently in run
4709 if (fAutoSave < 0) {
4710 // Set fAutoSave to the largest integer multiple of
4711 // fAutoFlush events such that fAutoSave*fFlushedBytes
4712 // < (minus the input value of fAutoSave)
4713 Long64_t totBytes = GetTotBytes();
4714 if (zipBytes != 0) {
4715 fAutoSave = TMath::Max(fAutoFlush, fEntries * ((-fAutoSave / zipBytes) / fEntries));
4716 } else if (totBytes != 0) {
4717 fAutoSave = TMath::Max(fAutoFlush, fEntries * ((-fAutoSave / totBytes) / fEntries));
4718 } else {
4720 TTree::Class()->WriteBuffer(b, (TTree *)this);
4721 Long64_t total = b.Length();
4723 }
4724 } else if (fAutoSave > 0) {
4726 }
4727
4728 if (fAutoSave != 0 && fEntries >= fAutoSave)
4729 autoSave = true;
4730
4731 if (gDebug > 0)
4732 Info("TTree::Fill", "First AutoFlush. fAutoFlush = %lld, fAutoSave = %lld\n", fAutoFlush, fAutoSave);
4733 }
4734 } else {
4735 // Check if we need to auto flush
4736 if (fAutoFlush) {
4737 if (fNClusterRange == 0)
4738 autoFlush = fEntries > 1 && fEntries % fAutoFlush == 0;
4739 else
4740 autoFlush = (fEntries - (fClusterRangeEnd[fNClusterRange - 1] + 1)) % fAutoFlush == 0;
4741 }
4742 // Check if we need to auto save
4743 if (fAutoSave)
4744 autoSave = fEntries % fAutoSave == 0;
4745 }
4746 }
4747
4748 if (autoFlush) {
4750 if (gDebug > 0)
4751 Info("TTree::Fill", "FlushBaskets() called at entry %lld, fZipBytes=%lld, fFlushedBytes=%lld\n", fEntries,
4754 }
4755
4756 if (autoSave) {
4757 AutoSave(); // does not call FlushBasketsImpl() again
4758 if (gDebug > 0)
4759 Info("TTree::Fill", "AutoSave called at entry %lld, fZipBytes=%lld, fSavedBytes=%lld\n", fEntries,
4761 }
4762
4763 // Check that output file is still below the maximum size.
4764 // If above, close the current file and continue on a new file.
4765 // Currently, the automatic change of file is restricted
4766 // to the case where the tree is in the top level directory.
4767 if (fDirectory)
4768 if (TFile *file = fDirectory->GetFile())
4769 if (static_cast<TDirectory *>(file) == fDirectory && (file->GetEND() > fgMaxTreeSize))
4770 // Changing file clashes with the design of TMemFile and derivates, see #6523.
4771 if (!(dynamic_cast<TMemFile *>(file)))
4773
4774 return nerror == 0 ? nbytes : -1;
4775}
4776
4777////////////////////////////////////////////////////////////////////////////////
4778/// Search in the array for a branch matching the branch name,
4779/// with the branch possibly expressed as a 'full' path name (with dots).
4781static TBranch *R__FindBranchHelper(TObjArray *list, const char *branchname) {
4782 if (list==0 || branchname == 0 || branchname[0] == '\0') return 0;
4783
4784 Int_t nbranches = list->GetEntries();
4785
4786 UInt_t brlen = strlen(branchname);
4787
4788 for(Int_t index = 0; index < nbranches; ++index) {
4789 TBranch *where = (TBranch*)list->UncheckedAt(index);
4790
4791 const char *name = where->GetName();
4792 UInt_t len = strlen(name);
4793 if (len && name[len-1]==']') {
4794 const char *dim = strchr(name,'[');
4795 if (dim) {
4796 len = dim - name;
4797 }
4798 }
4799 if (brlen == len && strncmp(branchname,name,len)==0) {
4800 return where;
4801 }
4802 TBranch *next = 0;
4803 if ((brlen >= len) && (branchname[len] == '.')
4804 && strncmp(name, branchname, len) == 0) {
4805 // The prefix subbranch name match the branch name.
4806
4807 next = where->FindBranch(branchname);
4808 if (!next) {
4809 next = where->FindBranch(branchname+len+1);
4810 }
4811 if (next) return next;
4812 }
4813 const char *dot = strchr((char*)branchname,'.');
4814 if (dot) {
4815 if (len==(size_t)(dot-branchname) &&
4816 strncmp(branchname,name,dot-branchname)==0 ) {
4817 return R__FindBranchHelper(where->GetListOfBranches(),dot+1);
4818 }
4819 }
4820 }
4821 return 0;
4822}
4823
4824////////////////////////////////////////////////////////////////////////////////
4825/// Return the branch that correspond to the path 'branchname', which can
4826/// include the name of the tree or the omitted name of the parent branches.
4827/// In case of ambiguity, returns the first match.
4829TBranch* TTree::FindBranch(const char* branchname)
4830{
4831 // We already have been visited while recursively looking
4832 // through the friends tree, let return
4834 return 0;
4835 }
4836
4837 TBranch* branch = 0;
4838 // If the first part of the name match the TTree name, look for the right part in the
4839 // list of branches.
4840 // This will allow the branchname to be preceded by
4841 // the name of this tree.
4842 if (strncmp(fName.Data(),branchname,fName.Length())==0 && branchname[fName.Length()]=='.') {
4843 branch = R__FindBranchHelper( GetListOfBranches(), branchname + fName.Length() + 1);
4844 if (branch) return branch;
4845 }
4846 // If we did not find it, let's try to find the full name in the list of branches.
4847 branch = R__FindBranchHelper(GetListOfBranches(), branchname);
4848 if (branch) return branch;
4849
4850 // If we still did not find, let's try to find it within each branch assuming it does not the branch name.
4851 TIter next(GetListOfBranches());
4852 while ((branch = (TBranch*) next())) {
4853 TBranch* nestedbranch = branch->FindBranch(branchname);
4854 if (nestedbranch) {
4855 return nestedbranch;
4856 }
4857 }
4858
4859 // Search in list of friends.
4860 if (!fFriends) {
4861 return 0;
4862 }
4863 TFriendLock lock(this, kFindBranch);
4864 TIter nextf(fFriends);
4865 TFriendElement* fe = 0;
4866 while ((fe = (TFriendElement*) nextf())) {
4867 TTree* t = fe->GetTree();
4868 if (!t) {
4869 continue;
4870 }
4871 // If the alias is present replace it with the real name.
4872 const char *subbranch = strstr(branchname, fe->GetName());
4873 if (subbranch != branchname) {
4874 subbranch = 0;
4875 }
4876 if (subbranch) {
4877 subbranch += strlen(fe->GetName());
4878 if (*subbranch != '.') {
4879 subbranch = 0;
4880 } else {
4881 ++subbranch;
4882 }
4883 }
4884 std::ostringstream name;
4885 if (subbranch) {
4886 name << t->GetName() << "." << subbranch;
4887 } else {
4888 name << branchname;
4889 }
4890 branch = t->FindBranch(name.str().c_str());
4891 if (branch) {
4892 return branch;
4893 }
4894 }
4895 return 0;
4896}
4897
4898////////////////////////////////////////////////////////////////////////////////
4899/// Find leaf..
4901TLeaf* TTree::FindLeaf(const char* searchname)
4902{
4903 // We already have been visited while recursively looking
4904 // through the friends tree, let's return.
4906 return 0;
4907 }
4908
4909 // This will allow the branchname to be preceded by
4910 // the name of this tree.
4911 char* subsearchname = (char*) strstr(searchname, GetName());
4912 if (subsearchname != searchname) {
4913 subsearchname = 0;
4914 }
4915 if (subsearchname) {
4916 subsearchname += strlen(GetName());
4917 if (*subsearchname != '.') {
4918 subsearchname = 0;
4919 } else {
4920 ++subsearchname;
4921 if (subsearchname[0]==0) {
4922 subsearchname = 0;
4923 }
4924 }
4925 }
4926
4927 TString leafname;
4928 TString leaftitle;
4929 TString longname;
4930 TString longtitle;
4931
4932 const bool searchnameHasDot = strchr(searchname, '.') != nullptr;
4933
4934 // For leaves we allow for one level up to be prefixed to the name.
4935 TIter next(GetListOfLeaves());
4936 TLeaf* leaf = 0;
4937 while ((leaf = (TLeaf*) next())) {
4938 leafname = leaf->GetName();
4939 Ssiz_t dim = leafname.First('[');
4940 if (dim >= 0) leafname.Remove(dim);
4941
4942 if (leafname == searchname) {
4943 return leaf;
4944 }
4945 if (subsearchname && leafname == subsearchname) {
4946 return leaf;
4947 }
4948 // The TLeafElement contains the branch name
4949 // in its name, let's use the title.
4950 leaftitle = leaf->GetTitle();
4951 dim = leaftitle.First('[');
4952 if (dim >= 0) leaftitle.Remove(dim);
4953
4954 if (leaftitle == searchname) {
4955 return leaf;
4956 }
4957 if (subsearchname && leaftitle == subsearchname) {
4958 return leaf;
4959 }
4960 if (!searchnameHasDot)
4961 continue;
4962 TBranch* branch = leaf->GetBranch();
4963 if (branch) {
4964 longname.Form("%s.%s",branch->GetName(),leafname.Data());
4965 dim = longname.First('[');
4966 if (dim>=0) longname.Remove(dim);
4967 if (longname == searchname) {
4968 return leaf;
4969 }
4970 if (subsearchname && longname == subsearchname) {
4971 return leaf;
4972 }
4973 longtitle.Form("%s.%s",branch->GetName(),leaftitle.Data());
4974 dim = longtitle.First('[');
4975 if (dim>=0) longtitle.Remove(dim);
4976 if (longtitle == searchname) {
4977 return leaf;
4978 }
4979 if (subsearchname && longtitle == subsearchname) {
4980 return leaf;
4981 }
4982 // The following is for the case where the branch is only
4983 // a sub-branch. Since we do not see it through
4984 // TTree::GetListOfBranches, we need to see it indirectly.
4985 // This is the less sturdy part of this search ... it may
4986 // need refining ...
4987 if (strstr(searchname, ".") && !strcmp(searchname, branch->GetName())) {
4988 return leaf;
4989 }
4990 if (subsearchname && strstr(subsearchname, ".") && !strcmp(subsearchname, branch->GetName())) {
4991 return leaf;
4992 }
4993 }
4994 }
4995 // Search in list of friends.
4996 if (!fFriends) {
4997 return 0;
4998 }
4999 TFriendLock lock(this, kFindLeaf);
5000 TIter nextf(fFriends);
5001 TFriendElement* fe = 0;
5002 while ((fe = (TFriendElement*) nextf())) {
5003 TTree* t = fe->GetTree();
5004 if (!t) {
5005 continue;
5006 }
5007 // If the alias is present replace it with the real name.
5008 subsearchname = (char*) strstr(searchname, fe->GetName());
5009 if (subsearchname != searchname) {
5010 subsearchname = 0;
5011 }
5012 if (subsearchname) {
5013 subsearchname += strlen(fe->GetName());
5014 if (*subsearchname != '.') {
5015 subsearchname = 0;
5016 } else {
5017 ++subsearchname;
5018 }
5019 }
5020 if (subsearchname) {
5021 leafname.Form("%s.%s",t->GetName(),subsearchname);
5022 } else {
5023 leafname = searchname;
5024 }
5025 leaf = t->FindLeaf(leafname);
5026 if (leaf) {
5027 return leaf;
5028 }
5029 }
5030 return 0;
5031}
5032
5033////////////////////////////////////////////////////////////////////////////////
5034/// Fit a projected item(s) from a tree.
5035///
5036/// funcname is a TF1 function.
5037///
5038/// See TTree::Draw() for explanations of the other parameters.
5039///
5040/// By default the temporary histogram created is called htemp.
5041/// If varexp contains >>hnew , the new histogram created is called hnew
5042/// and it is kept in the current directory.
5043///
5044/// The function returns the number of selected entries.
5045///
5046/// Example:
5047/// ~~~ {.cpp}
5048/// tree.Fit(pol4,"sqrt(x)>>hsqrt","y>0")
5049/// ~~~
5050/// will fit sqrt(x) and save the histogram as "hsqrt" in the current
5051/// directory.
5052///
5053/// See also TTree::UnbinnedFit
5054///
5055/// ## Return status
5056///
5057/// The function returns the status of the histogram fit (see TH1::Fit)
5058/// If no entries were selected, the function returns -1;
5059/// (i.e. fitResult is null if the fit is OK)
5061Int_t TTree::Fit(const char* funcname, const char* varexp, const char* selection, Option_t* option, Option_t* goption, Long64_t nentries, Long64_t firstentry)
5062{
5063 GetPlayer();
5064 if (fPlayer) {
5065 return fPlayer->Fit(funcname, varexp, selection, option, goption, nentries, firstentry);
5066 }
5067 return -1;
5068}
5069
5070namespace {
5071struct BoolRAIIToggle {
5072 Bool_t &m_val;
5073
5074 BoolRAIIToggle(Bool_t &val) : m_val(val) { m_val = true; }
5075 ~BoolRAIIToggle() { m_val = false; }
5076};
5077}
5078
5079////////////////////////////////////////////////////////////////////////////////
5080/// Write to disk all the basket that have not yet been individually written and
5081/// create an event cluster boundary (by default).
5082///
5083/// If the caller wishes to flush the baskets but not create an event cluster,
5084/// then set create_cluster to false.
5085///
5086/// If ROOT has IMT-mode enabled, this will launch multiple TBB tasks in parallel
5087/// via TThreadExecutor to do this operation; one per basket compression. If the
5088/// caller utilizes TBB also, care must be taken to prevent deadlocks.
5089///
5090/// For example, let's say the caller holds mutex A and calls FlushBaskets; while
5091/// TBB is waiting for the ROOT compression tasks to complete, it may decide to
5092/// run another one of the user's tasks in this thread. If the second user task
5093/// tries to acquire A, then a deadlock will occur. The example call sequence
5094/// looks like this:
5095///
5096/// - User acquires mutex A
5097/// - User calls FlushBaskets.
5098/// - ROOT launches N tasks and calls wait.
5099/// - TBB schedules another user task, T2.
5100/// - T2 tries to acquire mutex A.
5101///
5102/// At this point, the thread will deadlock: the code may function with IMT-mode
5103/// disabled if the user assumed the legacy code never would run their own TBB
5104/// tasks.
5105///
5106/// SO: users of TBB who want to enable IMT-mode should carefully review their
5107/// locking patterns and make sure they hold no coarse-grained application
5108/// locks when they invoke ROOT.
5109///
5110/// Return the number of bytes written or -1 in case of write error.
5111Int_t TTree::FlushBaskets(Bool_t create_cluster) const
5112{
5113 Int_t retval = FlushBasketsImpl();
5114 if (retval == -1) return retval;
5115
5116 if (create_cluster) const_cast<TTree *>(this)->MarkEventCluster();
5117 return retval;
5118}
5119
5120////////////////////////////////////////////////////////////////////////////////
5121/// Internal implementation of the FlushBaskets algorithm.
5122/// Unlike the public interface, this does NOT create an explicit event cluster
5123/// boundary; it is up to the (internal) caller to determine whether that should
5124/// done.
5125///
5126/// Otherwise, the comments for FlushBaskets applies.
5129{
5130 if (!fDirectory) return 0;
5131 Int_t nbytes = 0;
5132 Int_t nerror = 0;
5133 TObjArray *lb = const_cast<TTree*>(this)->GetListOfBranches();
5134 Int_t nb = lb->GetEntriesFast();
5135
5136#ifdef R__USE_IMT
5137 const auto useIMT = ROOT::IsImplicitMTEnabled() && fIMTEnabled;
5138 if (useIMT) {
5139 // ROOT-9668: here we need to check if the size of fSortedBranches is different from the
5140 // size of the list of branches before triggering the initialisation of the fSortedBranches
5141 // container to cover two cases:
5142 // 1. This is the first time we flush. fSortedBranches is empty and we need to fill it.
5143 // 2. We flushed at least once already but a branch has been be added to the tree since then
5144 if (fSortedBranches.size() != unsigned(nb)) { const_cast<TTree*>(this)->InitializeBranchLists(false); }
5145
5146 BoolRAIIToggle sentry(fIMTFlush);
5147 fIMTZipBytes.store(0);
5148 fIMTTotBytes.store(0);
5149 std::atomic<Int_t> nerrpar(0);
5150 std::atomic<Int_t> nbpar(0);
5151 std::atomic<Int_t> pos(0);
5152
5153 auto mapFunction = [&]() {
5154 // The branch to process is obtained when the task starts to run.
5155 // This way, since branches are sorted, we make sure that branches
5156 // leading to big tasks are processed first. If we assigned the
5157 // branch at task creation time, the scheduler would not necessarily
5158 // respect our sorting.
5159 Int_t j = pos.fetch_add(1);
5160
5161 auto branch = fSortedBranches[j].second;
5162 if (R__unlikely(!branch)) { return; }
5163
5164 if (R__unlikely(gDebug > 0)) {
5165 std::stringstream ss;
5166 ss << std::this_thread::get_id();
5167 Info("FlushBaskets", "[IMT] Thread %s", ss.str().c_str());
5168 Info("FlushBaskets", "[IMT] Running task for branch #%d: %s", j, branch->GetName());
5169 }
5170
5171 Int_t nbtask = branch->FlushBaskets();
5172
5173 if (nbtask < 0) { nerrpar++; }
5174 else { nbpar += nbtask; }
5175 };
5176
5178 pool.Foreach(mapFunction, nb);
5179
5180 fIMTFlush = false;
5181 const_cast<TTree*>(this)->AddTotBytes(fIMTTotBytes);
5182 const_cast<TTree*>(this)->AddZipBytes(fIMTZipBytes);
5183
5184 return nerrpar ? -1 : nbpar.load();
5185 }
5186#endif
5187 for (Int_t j = 0; j < nb; j++) {
5188 TBranch* branch = (TBranch*) lb->UncheckedAt(j);
5189 if (branch) {
5190 Int_t nwrite = branch->FlushBaskets();
5191 if (nwrite<0) {
5192 ++nerror;
5193 } else {
5194 nbytes += nwrite;
5195 }
5196 }
5197 }
5198 if (nerror) {
5199 return -1;
5200 } else {
5201 return nbytes;
5202 }
5203}
5204
5205////////////////////////////////////////////////////////////////////////////////
5206/// Returns the expanded value of the alias. Search in the friends if any.
5208const char* TTree::GetAlias(const char* aliasName) const
5209{
5210 // We already have been visited while recursively looking
5211 // through the friends tree, let's return.
5213 return 0;
5214 }
5215 if (fAliases) {
5216 TObject* alias = fAliases->FindObject(aliasName);
5217 if (alias) {
5218 return alias->GetTitle();
5219 }
5220 }
5221 if (!fFriends) {
5222 return 0;
5223 }
5224 TFriendLock lock(const_cast<TTree*>(this), kGetAlias);
5225 TIter nextf(fFriends);
5226 TFriendElement* fe = 0;
5227 while ((fe = (TFriendElement*) nextf())) {
5228 TTree* t = fe->GetTree();
5229 if (t) {
5230 const char* alias = t->GetAlias(aliasName);
5231 if (alias) {
5232 return alias;
5233 }
5234 const char* subAliasName = strstr(aliasName, fe->GetName());
5235 if (subAliasName && (subAliasName[strlen(fe->GetName())] == '.')) {
5236 alias = t->GetAlias(aliasName + strlen(fe->GetName()) + 1);
5237 if (alias) {
5238 return alias;
5239 }
5240 }
5241 }
5242 }
5243 return 0;
5244}
5245
5246namespace {
5247/// Do a breadth first search through the implied hierarchy
5248/// of branches.
5249/// To avoid scanning through the list multiple time
5250/// we also remember the 'depth-first' match.
5251TBranch *R__GetBranch(const TObjArray &branches, const char *name)
5252{
5253 TBranch *result = nullptr;
5254 Int_t nb = branches.GetEntriesFast();
5255 for (Int_t i = 0; i < nb; i++) {
5256 TBranch* b = (TBranch*)branches.UncheckedAt(i);
5257 if (!b)
5258 continue;
5259 if (!strcmp(b->GetName(), name)) {
5260 return b;
5261 }
5262 if (!strcmp(b->GetFullName(), name)) {
5263 return b;
5264 }
5265 if (!result)
5266 result = R__GetBranch(*(b->GetListOfBranches()), name);
5267 }
5268 return result;
5269}
5270}
5271
5272////////////////////////////////////////////////////////////////////////////////
5273/// Return pointer to the branch with the given name in this tree or its friends.
5274/// The search is done breadth first.
5276TBranch* TTree::GetBranch(const char* name)
5277{
5278 if (name == 0) return 0;
5279
5280 // We already have been visited while recursively
5281 // looking through the friends tree, let's return.
5283 return 0;
5284 }
5285
5286 // Look for an exact match in the list of top level
5287 // branches.
5289 if (result)
5290 return result;
5291
5292 // Search using branches, breadth first.
5293 result = R__GetBranch(fBranches, name);
5294 if (result)
5295 return result;
5296
5297 // Search using leaves.
5298 TObjArray* leaves = GetListOfLeaves();
5299 Int_t nleaves = leaves->GetEntriesFast();
5300 for (Int_t i = 0; i < nleaves; i++) {
5301 TLeaf* leaf = (TLeaf*) leaves->UncheckedAt(i);
5302 TBranch* branch = leaf->GetBranch();
5303 if (!strcmp(branch->GetName(), name)) {
5304 return branch;
5305 }
5306 if (!strcmp(branch->GetFullName(), name)) {
5307 return branch;
5308 }
5309 }
5310
5311 if (!fFriends) {
5312 return 0;
5313 }
5314
5315 // Search in list of friends.
5316 TFriendLock lock(this, kGetBranch);
5317 TIter next(fFriends);
5318 TFriendElement* fe = 0;
5319 while ((fe = (TFriendElement*) next())) {
5320 TTree* t = fe->GetTree();
5321 if (t) {
5322 TBranch* branch = t->GetBranch(name);
5323 if (branch) {
5324 return branch;
5325 }
5326 }
5327 }
5328
5329 // Second pass in the list of friends when
5330 // the branch name is prefixed by the tree name.
5331 next.Reset();
5332 while ((fe = (TFriendElement*) next())) {
5333 TTree* t = fe->GetTree();
5334 if (!t) {
5335 continue;
5336 }
5337 char* subname = (char*) strstr(name, fe->GetName());
5338 if (subname != name) {
5339 continue;
5340 }
5341 Int_t l = strlen(fe->GetName());
5342 subname += l;
5343 if (*subname != '.') {
5344 continue;
5345 }
5346 subname++;
5347 TBranch* branch = t->GetBranch(subname);
5348 if (branch) {
5349 return branch;
5350 }
5351 }
5352 return 0;
5353}
5354
5355////////////////////////////////////////////////////////////////////////////////
5356/// Return status of branch with name branchname.
5357///
5358/// - 0 if branch is not activated
5359/// - 1 if branch is activated
5361Bool_t TTree::GetBranchStatus(const char* branchname) const
5362{
5363 TBranch* br = const_cast<TTree*>(this)->GetBranch(branchname);
5364 if (br) {
5365 return br->TestBit(kDoNotProcess) == 0;
5366 }
5367 return 0;
5368}
5369
5370////////////////////////////////////////////////////////////////////////////////
5371/// Static function returning the current branch style.
5372///
5373/// - style = 0 old Branch
5374/// - style = 1 new Bronch
5377{
5378 return fgBranchStyle;
5379}
5380
5381////////////////////////////////////////////////////////////////////////////////
5382/// Used for automatic sizing of the cache.
5383///
5384/// Estimates a suitable size for the tree cache based on AutoFlush.
5385/// A cache sizing factor is taken from the configuration. If this yields zero
5386/// and withDefault is true the historical algorithm for default size is used.
5388Long64_t TTree::GetCacheAutoSize(Bool_t withDefault /* = kFALSE */ )
5389{
5390 auto calculateCacheSize = [=](Double_t cacheFactor)
5391 {
5392 Long64_t cacheSize = 0;
5393 if (fAutoFlush < 0) {
5394 cacheSize = Long64_t(-cacheFactor * fAutoFlush);
5395 } else if (fAutoFlush == 0) {
5396 const auto medianClusterSize = GetMedianClusterSize();
5397 if (medianClusterSize > 0)
5398 cacheSize = Long64_t(cacheFactor * 1.5 * medianClusterSize * GetZipBytes() / (fEntries + 1));
5399 else
5400 cacheSize = Long64_t(cacheFactor * 1.5 * 30000000); // use the default value of fAutoFlush
5401 } else {
5402 cacheSize = Long64_t(cacheFactor * 1.5 * fAutoFlush * GetZipBytes() / (fEntries + 1));
5403 }
5404 if (cacheSize >= (INT_MAX / 4)) {
5405 cacheSize = INT_MAX / 4;
5406 }
5407 return cacheSize;
5408 };
5409
5410 const char *stcs;
5411 Double_t cacheFactor = 0.0;
5412 if (!(stcs = gSystem->Getenv("ROOT_TTREECACHE_SIZE")) || !*stcs) {
5413 cacheFactor = gEnv->GetValue("TTreeCache.Size", 1.0);
5414 } else {
5415 cacheFactor = TString(stcs).Atof();
5416 }
5417
5418 if (cacheFactor < 0.0) {
5419 // ignore negative factors
5420 cacheFactor = 0.0;
5421 }
5422
5423 Long64_t cacheSize = calculateCacheSize(cacheFactor);
5424
5425 if (cacheSize < 0) {
5426 cacheSize = 0;
5427 }
5428
5429 if (cacheSize == 0 && withDefault) {
5430 cacheSize = calculateCacheSize(1.0);
5431 }
5432
5433 return cacheSize;
5434}
5435
5436////////////////////////////////////////////////////////////////////////////////
5437/// Return an iterator over the cluster of baskets starting at firstentry.
5438///
5439/// This iterator is not yet supported for TChain object.
5440/// ~~~ {.cpp}
5441/// TTree::TClusterIterator clusterIter = tree->GetClusterIterator(entry);
5442/// Long64_t clusterStart;
5443/// while( (clusterStart = clusterIter()) < tree->GetEntries() ) {
5444/// printf("The cluster starts at %lld and ends at %lld (inclusive)\n",clusterStart,clusterIter.GetNextEntry()-1);
5445/// }
5446/// ~~~
5449{
5450 // create cache if wanted
5451 if (fCacheDoAutoInit)
5453
5454 return TClusterIterator(this,firstentry);
5455}
5456
5457////////////////////////////////////////////////////////////////////////////////
5458/// Return pointer to the current file.
5461{
5462 if (!fDirectory || fDirectory==gROOT) {
5463 return 0;
5464 }
5465 return fDirectory->GetFile();
5466}
5467
5468////////////////////////////////////////////////////////////////////////////////
5469/// Return the number of entries matching the selection.
5470/// Return -1 in case of errors.
5471///
5472/// If the selection uses any arrays or containers, we return the number
5473/// of entries where at least one element match the selection.
5474/// GetEntries is implemented using the selector class TSelectorEntries,
5475/// which can be used directly (see code in TTreePlayer::GetEntries) for
5476/// additional option.
5477/// If SetEventList was used on the TTree or TChain, only that subset
5478/// of entries will be considered.
5480Long64_t TTree::GetEntries(const char *selection)
5481{
5482 GetPlayer();
5483 if (fPlayer) {
5484 return fPlayer->GetEntries(selection);
5485 }
5486 return -1;
5487}
5488
5489////////////////////////////////////////////////////////////////////////////////
5490/// Return pointer to the 1st Leaf named name in any Branch of this Tree or
5491/// any branch in the list of friend trees.
5494{
5495 if (fEntries) return fEntries;
5496 if (!fFriends) return 0;
5498 if (!fr) return 0;
5499 TTree *t = fr->GetTree();
5500 if (t==0) return 0;
5501 return t->GetEntriesFriend();
5502}
5503
5504////////////////////////////////////////////////////////////////////////////////
5505/// Read all branches of entry and return total number of bytes read.
5506///
5507/// - `getall = 0` : get only active branches
5508/// - `getall = 1` : get all branches
5509///
5510/// The function returns the number of bytes read from the input buffer.
5511/// If entry does not exist the function returns 0.
5512/// If an I/O error occurs, the function returns -1.
5513///
5514/// If the Tree has friends, also read the friends entry.
5515///
5516/// To activate/deactivate one or more branches, use TBranch::SetBranchStatus
5517/// For example, if you have a Tree with several hundred branches, and you
5518/// are interested only by branches named "a" and "b", do
5519/// ~~~ {.cpp}
5520/// mytree.SetBranchStatus("*",0); //disable all branches
5521/// mytree.SetBranchStatus("a",1);
5522/// mytree.SetBranchStatus("b",1);
5523/// ~~~
5524/// when calling mytree.GetEntry(i); only branches "a" and "b" will be read.
5525///
5526/// __WARNING!!__
5527/// If your Tree has been created in split mode with a parent branch "parent.",
5528/// ~~~ {.cpp}
5529/// mytree.SetBranchStatus("parent",1);
5530/// ~~~
5531/// will not activate the sub-branches of "parent". You should do:
5532/// ~~~ {.cpp}
5533/// mytree.SetBranchStatus("parent*",1);
5534/// ~~~
5535/// Without the trailing dot in the branch creation you have no choice but to
5536/// call SetBranchStatus explicitly for each of the sub branches.
5537///
5538/// An alternative is to call directly
5539/// ~~~ {.cpp}
5540/// brancha.GetEntry(i)
5541/// branchb.GetEntry(i);
5542/// ~~~
5543/// ## IMPORTANT NOTE
5544///
5545/// By default, GetEntry reuses the space allocated by the previous object
5546/// for each branch. You can force the previous object to be automatically
5547/// deleted if you call mybranch.SetAutoDelete(kTRUE) (default is kFALSE).
5548///
5549/// Example:
5550///
5551/// Consider the example in $ROOTSYS/test/Event.h
5552/// The top level branch in the tree T is declared with:
5553/// ~~~ {.cpp}
5554/// Event *event = 0; //event must be null or point to a valid object
5555/// //it must be initialized
5556/// T.SetBranchAddress("event",&event);
5557/// ~~~
5558/// When reading the Tree, one can choose one of these 3 options:
5559///
5560/// ## OPTION 1
5561///
5562/// ~~~ {.cpp}
5563/// for (Long64_t i=0;i<nentries;i++) {
5564/// T.GetEntry(i);
5565/// // the object event has been filled at this point
5566/// }
5567/// ~~~
5568/// The default (recommended). At the first entry an object of the class
5569/// Event will be created and pointed by event. At the following entries,
5570/// event will be overwritten by the new data. All internal members that are
5571/// TObject* are automatically deleted. It is important that these members
5572/// be in a valid state when GetEntry is called. Pointers must be correctly
5573/// initialized. However these internal members will not be deleted if the
5574/// characters "->" are specified as the first characters in the comment
5575/// field of the data member declaration.
5576///
5577/// If "->" is specified, the pointer member is read via pointer->Streamer(buf).
5578/// In this case, it is assumed that the pointer is never null (case of
5579/// pointer TClonesArray *fTracks in the Event example). If "->" is not
5580/// specified, the pointer member is read via buf >> pointer. In this case
5581/// the pointer may be null. Note that the option with "->" is faster to
5582/// read or write and it also consumes less space in the file.
5583///
5584/// ## OPTION 2
5585///
5586/// The option AutoDelete is set
5587/// ~~~ {.cpp}
5588/// TBranch *branch = T.GetBranch("event");
5589/// branch->SetAddress(&event);
5590/// branch->SetAutoDelete(kTRUE);
5591/// for (Long64_t i=0;i<nentries;i++) {
5592/// T.GetEntry(i);
5593/// // the object event has been filled at this point
5594/// }
5595/// ~~~
5596/// In this case, at each iteration, the object event is deleted by GetEntry
5597/// and a new instance of Event is created and filled.
5598///
5599/// ## OPTION 3
5600///
5601/// ~~~ {.cpp}
5602/// Same as option 1, but you delete yourself the event.
5603///
5604/// for (Long64_t i=0;i<nentries;i++) {
5605/// delete event;
5606/// event = 0; // EXTREMELY IMPORTANT
5607/// T.GetEntry(i);
5608/// // the object event has been filled at this point
5609/// }
5610/// ~~~
5611/// It is strongly recommended to use the default option 1. It has the
5612/// additional advantage that functions like TTree::Draw (internally calling
5613/// TTree::GetEntry) will be functional even when the classes in the file are
5614/// not available.
5615///
5616/// Note: See the comments in TBranchElement::SetAddress() for the
5617/// object ownership policy of the underlying (user) data.
5619Int_t TTree::GetEntry(Long64_t entry, Int_t getall)
5620{
5621
5622 // We already have been visited while recursively looking
5623 // through the friends tree, let return
5624 if (kGetEntry & fFriendLockStatus) return 0;
5625
5626 if (entry < 0 || entry >= fEntries) return 0;
5627 Int_t i;
5628 Int_t nbytes = 0;
5629 fReadEntry = entry;
5630
5631 // create cache if wanted
5632 if (fCacheDoAutoInit)
5634
5635 Int_t nbranches = fBranches.GetEntriesUnsafe();
5636 Int_t nb=0;
5637
5638 auto seqprocessing = [&]() {
5639 TBranch *branch;
5640 for (i=0;i<nbranches;i++) {
5641 branch = (TBranch*)fBranches.UncheckedAt(i);
5642 nb = branch->GetEntry(entry, getall);
5643 if (nb < 0) break;
5644 nbytes += nb;
5645 }
5646 };
5647
5648#ifdef R__USE_IMT
5650 if (fSortedBranches.empty())
5652
5653 // Count branches are processed first and sequentially
5654 for (auto branch : fSeqBranches) {
5655 nb = branch->GetEntry(entry, getall);
5656 if (nb < 0) break;
5657 nbytes += nb;
5658 }
5659 if (nb < 0) return nb;
5660
5661 // Enable this IMT use case (activate its locks)
5663
5664 Int_t errnb = 0;
5665 std::atomic<Int_t> pos(0);
5666 std::atomic<Int_t> nbpar(0);
5667
5668 auto mapFunction = [&]() {
5669 // The branch to process is obtained when the task starts to run.
5670 // This way, since branches are sorted, we make sure that branches
5671 // leading to big tasks are processed first. If we assigned the
5672 // branch at task creation time, the scheduler would not necessarily
5673 // respect our sorting.
5674 Int_t j = pos.fetch_add(1);
5675
5676 Int_t nbtask = 0;
5677 auto branch = fSortedBranches[j].second;
5678
5679 if (gDebug > 0) {
5680 std::stringstream ss;
5681 ss << std::this_thread::get_id();
5682 Info("GetEntry", "[IMT] Thread %s", ss.str().c_str());
5683 Info("GetEntry", "[IMT] Running task for branch #%d: %s", j, branch->GetName());
5684 }
5685
5686 std::chrono::time_point<std::chrono::system_clock> start, end;
5687
5688 start = std::chrono::system_clock::now();
5689 nbtask = branch->GetEntry(entry, getall);
5690 end = std::chrono::system_clock::now();
5691
5692 Long64_t tasktime = (Long64_t)std::chrono::duration_cast<std::chrono::microseconds>(end - start).count();
5693 fSortedBranches[j].first += tasktime;
5694
5695 if (nbtask < 0) errnb = nbtask;
5696 else nbpar += nbtask;
5697 };
5698
5700 pool.Foreach(mapFunction, fSortedBranches.size());
5701
5702 if (errnb < 0) {
5703 nb = errnb;
5704 }
5705 else {
5706 // Save the number of bytes read by the tasks
5707 nbytes += nbpar;
5708
5709 // Re-sort branches if necessary
5713 }
5714 }
5715 }
5716 else {
5717 seqprocessing();
5718 }
5719#else
5720 seqprocessing();
5721#endif
5722 if (nb < 0) return nb;
5723
5724 // GetEntry in list of friends
5725 if (!fFriends) return nbytes;
5726 TFriendLock lock(this,kGetEntry);
5727 TIter nextf(fFriends);
5728 TFriendElement *fe;
5729 while ((fe = (TFriendElement*)nextf())) {
5730 TTree *t = fe->GetTree();
5731 if (t) {
5733 nb = t->GetEntry(t->GetReadEntry(),getall);
5734 } else {
5735 if ( t->LoadTreeFriend(entry,this) >= 0 ) {
5736 nb = t->GetEntry(t->GetReadEntry(),getall);
5737 } else nb = 0;
5738 }
5739 if (nb < 0) return nb;
5740 nbytes += nb;
5741 }
5742 }
5743 return nbytes;
5744}
5745
5746
5747////////////////////////////////////////////////////////////////////////////////
5748/// Divides the top-level branches into two vectors: (i) branches to be
5749/// processed sequentially and (ii) branches to be processed in parallel.
5750/// Even if IMT is on, some branches might need to be processed first and in a
5751/// sequential fashion: in the parallelization of GetEntry, those are the
5752/// branches that store the size of another branch for every entry
5753/// (e.g. the size of an array branch). If such branches were processed
5754/// in parallel with the rest, there could be two threads invoking
5755/// TBranch::GetEntry on one of them at the same time, since a branch that
5756/// depends on a size (or count) branch will also invoke GetEntry on the latter.
5757/// This method can be invoked several times during the event loop if the TTree
5758/// is being written, for example when adding new branches. In these cases, the
5759/// `checkLeafCount` parameter is false.
5760/// \param[in] checkLeafCount True if we need to check whether some branches are
5761/// count leaves.
5763void TTree::InitializeBranchLists(bool checkLeafCount)
5764{
5765 Int_t nbranches = fBranches.GetEntriesFast();
5766
5767 // The special branch fBranchRef needs to be processed sequentially:
5768 // we add it once only.
5769 if (fBranchRef && fBranchRef != fSeqBranches[0]) {
5770 fSeqBranches.push_back(fBranchRef);
5771 }
5772
5773 // The branches to be processed sequentially are those that are the leaf count of another branch
5774 if (checkLeafCount) {
5775 for (Int_t i = 0; i < nbranches; i++) {
5776 TBranch* branch = (TBranch*)fBranches.UncheckedAt(i);
5777 auto leafCount = ((TLeaf*)branch->GetListOfLeaves()->At(0))->GetLeafCount();
5778 if (leafCount) {
5779 auto countBranch = leafCount->GetBranch();
5780 if (std::find(fSeqBranches.begin(), fSeqBranches.end(), countBranch) == fSeqBranches.end()) {
5781 fSeqBranches.push_back(countBranch);
5782 }
5783 }
5784 }
5785 }
5786
5787 // Any branch that is not a leaf count can be safely processed in parallel when reading
5788 // We need to reset the vector to make sure we do not re-add several times the same branch.
5789 if (!checkLeafCount) {
5790 fSortedBranches.clear();
5791 }
5792 for (Int_t i = 0; i < nbranches; i++) {
5793 Long64_t bbytes = 0;
5794 TBranch* branch = (TBranch*)fBranches.UncheckedAt(i);
5795 if (std::find(fSeqBranches.begin(), fSeqBranches.end(), branch) == fSeqBranches.end()) {
5796 bbytes = branch->GetTotBytes("*");
5797 fSortedBranches.emplace_back(bbytes, branch);
5798 }
5799 }
5800
5801 // Initially sort parallel branches by size
5802 std::sort(fSortedBranches.begin(),
5803 fSortedBranches.end(),
5804 [](std::pair<Long64_t,TBranch*> a, std::pair<Long64_t,TBranch*> b) {
5805 return a.first > b.first;
5806 });
5807
5808 for (size_t i = 0; i < fSortedBranches.size(); i++) {
5809 fSortedBranches[i].first = 0LL;
5810 }
5811}
5812
5813////////////////////////////////////////////////////////////////////////////////
5814/// Sorts top-level branches by the last average task time recorded per branch.
5817{
5818 for (size_t i = 0; i < fSortedBranches.size(); i++) {
5820 }
5821
5822 std::sort(fSortedBranches.begin(),
5823 fSortedBranches.end(),
5824 [](std::pair<Long64_t,TBranch*> a, std::pair<Long64_t,TBranch*> b) {
5825 return a.first > b.first;
5826 });
5827
5828 for (size_t i = 0; i < fSortedBranches.size(); i++) {
5829 fSortedBranches[i].first = 0LL;
5830 }
5831}
5832
5833////////////////////////////////////////////////////////////////////////////////
5834///Returns the entry list assigned to this tree
5837{
5838 return fEntryList;
5839}
5840
5841////////////////////////////////////////////////////////////////////////////////
5842/// Return entry number corresponding to entry.
5843///
5844/// if no TEntryList set returns entry
5845/// else returns the entry number corresponding to the list index=entry
5848{
5849 if (!fEntryList) {
5850 return entry;
5851 }
5852
5853 return fEntryList->GetEntry(entry);
5854}
5855
5856////////////////////////////////////////////////////////////////////////////////
5857/// Return entry number corresponding to major and minor number.
5858/// Note that this function returns only the entry number, not the data
5859/// To read the data corresponding to an entry number, use TTree::GetEntryWithIndex
5860/// the BuildIndex function has created a table of Long64_t* of sorted values
5861/// corresponding to val = major<<31 + minor;
5862/// The function performs binary search in this sorted table.
5863/// If it finds a pair that matches val, it returns directly the
5864/// index in the table.
5865/// If an entry corresponding to major and minor is not found, the function
5866/// returns the index of the major,minor pair immediately lower than the
5867/// requested value, ie it will return -1 if the pair is lower than
5868/// the first entry in the index.
5869///
5870/// See also GetEntryNumberWithIndex
5873{
5874 if (!fTreeIndex) {
5875 return -1;
5876 }
5877 return fTreeIndex->GetEntryNumberWithBestIndex(major, minor);
5878}
5879
5880////////////////////////////////////////////////////////////////////////////////
5881/// Return entry number corresponding to major and minor number.
5882/// Note that this function returns only the entry number, not the data
5883/// To read the data corresponding to an entry number, use TTree::GetEntryWithIndex
5884/// the BuildIndex function has created a table of Long64_t* of sorted values
5885/// corresponding to val = major<<31 + minor;
5886/// The function performs binary search in this sorted table.
5887/// If it finds a pair that matches val, it returns directly the
5888/// index in the table, otherwise it returns -1.
5889///
5890/// See also GetEntryNumberWithBestIndex
5893{
5894 if (!fTreeIndex) {
5895 return -1;
5896 }
5897 return fTreeIndex->GetEntryNumberWithIndex(major, minor);
5898}
5899
5900////////////////////////////////////////////////////////////////////////////////
5901/// Read entry corresponding to major and minor number.
5902///
5903/// The function returns the total number of bytes read.
5904/// If the Tree has friend trees, the corresponding entry with
5905/// the index values (major,minor) is read. Note that the master Tree
5906/// and its friend may have different entry serial numbers corresponding
5907/// to (major,minor).
5910{
5911 // We already have been visited while recursively looking
5912 // through the friends tree, let's return.
5914 return 0;
5915 }
5916 Long64_t serial = GetEntryNumberWithIndex(major, minor);
5917 if (serial < 0) {
5918 return -1;
5919 }
5920 // create cache if wanted
5921 if (fCacheDoAutoInit)
5923
5924 Int_t i;
5925 Int_t nbytes = 0;
5926 fReadEntry = serial;
5927 TBranch *branch;
5928 Int_t nbranches = fBranches.GetEntriesFast();
5929 Int_t nb;
5930 for (i = 0; i < nbranches; ++i) {
5931 branch = (TBranch*)fBranches.UncheckedAt(i);
5932 nb = branch->GetEntry(serial);
5933 if (nb < 0) return nb;
5934 nbytes += nb;
5935 }
5936 // GetEntry in list of friends
5937 if (!fFriends) return nbytes;
5939 TIter nextf(fFriends);
5940 TFriendElement* fe = 0;
5941 while ((fe = (TFriendElement*) nextf())) {
5942 TTree *t = fe->GetTree();
5943 if (t) {
5944 serial = t->GetEntryNumberWithIndex(major,minor);
5945 if (serial <0) return -nbytes;
5946 nb = t->GetEntry(serial);
5947 if (nb < 0) return nb;
5948 nbytes += nb;
5949 }
5950 }
5951 return nbytes;
5952}
5953
5954////////////////////////////////////////////////////////////////////////////////
5955/// Return a pointer to the TTree friend whose name or alias is `friendname`.
5957TTree* TTree::GetFriend(const char *friendname) const
5958{
5959
5960 // We already have been visited while recursively
5961 // looking through the friends tree, let's return.
5963 return 0;
5964 }
5965 if (!fFriends) {
5966 return 0;
5967 }
5968 TFriendLock lock(const_cast<TTree*>(this), kGetFriend);
5969 TIter nextf(fFriends);
5970 TFriendElement* fe = 0;
5971 while ((fe = (TFriendElement*) nextf())) {
5972 if (strcmp(friendname,fe->GetName())==0
5973 || strcmp(friendname,fe->GetTreeName())==0) {
5974 return fe->GetTree();
5975 }
5976 }
5977 // After looking at the first level,
5978 // let's see if it is a friend of friends.
5979 nextf.Reset();
5980 fe = 0;
5981 while ((fe = (TFriendElement*) nextf())) {
5982 TTree *res = fe->GetTree()->GetFriend(friendname);
5983 if (res) {
5984 return res;
5985 }
5986 }
5987 return 0;
5988}
5989
5990////////////////////////////////////////////////////////////////////////////////
5991/// If the 'tree' is a friend, this method returns its alias name.
5992///
5993/// This alias is an alternate name for the tree.
5994///
5995/// It can be used in conjunction with a branch or leaf name in a TTreeFormula,
5996/// to specify in which particular tree the branch or leaf can be found if
5997/// the friend trees have branches or leaves with the same name as the master
5998/// tree.
5999///
6000/// It can also be used in conjunction with an alias created using
6001/// TTree::SetAlias in a TTreeFormula, e.g.:
6002/// ~~~ {.cpp}
6003/// maintree->Draw("treealias.fPx - treealias.myAlias");
6004/// ~~~
6005/// where fPx is a branch of the friend tree aliased as 'treealias' and 'myAlias'
6006/// was created using TTree::SetAlias on the friend tree.
6007///
6008/// However, note that 'treealias.myAlias' will be expanded literally,
6009/// without remembering that it comes from the aliased friend and thus
6010/// the branch name might not be disambiguated properly, which means
6011/// that you may not be able to take advantage of this feature.
6012///
6014const char* TTree::GetFriendAlias(TTree* tree) const
6015{
6016 if ((tree == this) || (tree == GetTree())) {
6017 return 0;
6018 }
6019
6020 // We already have been visited while recursively
6021 // looking through the friends tree, let's return.
6023 return 0;
6024 }
6025 if (!fFriends) {
6026 return 0;
6027 }
6028 TFriendLock lock(const_cast<TTree*>(this), kGetFriendAlias);
6029 TIter nextf(fFriends);
6030 TFriendElement* fe = 0;
6031 while ((fe = (TFriendElement*) nextf())) {
6032 TTree* t = fe->GetTree();
6033 if (t == tree) {
6034 return fe->GetName();
6035 }
6036 // Case of a chain:
6037 if (t && t->GetTree() == tree) {
6038 return fe->GetName();
6039 }
6040 }
6041 // After looking at the first level,
6042 // let's see if it is a friend of friends.
6043 nextf.Reset();
6044 fe = 0;
6045 while ((fe = (TFriendElement*) nextf())) {
6046 const char* res = fe->GetTree()->GetFriendAlias(tree);
6047 if (res) {
6048 return res;
6049 }
6050 }
6051 return 0;
6052}
6053
6054////////////////////////////////////////////////////////////////////////////////
6055/// Returns the current set of IO settings
6057{
6058 return fIOFeatures;
6059}
6060
6061////////////////////////////////////////////////////////////////////////////////
6062/// Creates a new iterator that will go through all the leaves on the tree itself and its friend.
6065{
6066 return new TTreeFriendLeafIter(this, dir);
6067}
6068
6069////////////////////////////////////////////////////////////////////////////////
6070/// Return pointer to the 1st Leaf named name in any Branch of this
6071/// Tree or any branch in the list of friend trees.
6072///
6073/// The leaf name can contain the name of a friend tree with the
6074/// syntax: friend_dir_and_tree.full_leaf_name
6075/// the friend_dir_and_tree can be of the form:
6076/// ~~~ {.cpp}
6077/// TDirectoryName/TreeName
6078/// ~~~
6080TLeaf* TTree::GetLeafImpl(const char* branchname, const char *leafname)
6081{
6082 TLeaf *leaf = 0;
6083 if (branchname) {
6084 TBranch *branch = FindBranch(branchname);
6085 if (branch) {
6086 leaf = branch->GetLeaf(leafname);
6087 if (leaf) {
6088 return leaf;
6089 }
6090 }
6091 }
6092 TIter nextl(GetListOfLeaves());
6093 while ((leaf = (TLeaf*)nextl())) {
6094 if (strcmp(leaf->GetFullName(), leafname) != 0 && strcmp(leaf->GetName(), leafname) != 0)
6095 continue; // leafname does not match GetName() nor GetFullName(), this is not the right leaf
6096 if (branchname) {
6097 // check the branchname is also a match
6098 TBranch *br = leaf->GetBranch();
6099 // if a quick comparison with the branch full name is a match, we are done
6100 if (!strcmp(br->GetFullName(), branchname))
6101 return leaf;
6102 UInt_t nbch = strlen(branchname);
6103 const char* brname = br->GetName();
6104 TBranch *mother = br->GetMother();
6105 if (strncmp(brname,branchname,nbch)) {
6106 if (mother != br) {
6107 const char *mothername = mother->GetName();
6108 UInt_t motherlen = strlen(mothername);
6109 if (!strcmp(mothername, branchname)) {
6110 return leaf;
6111 } else if (nbch > motherlen && strncmp(mothername,branchname,motherlen)==0 && (mothername[motherlen-1]=='.' || branchname[motherlen]=='.')) {
6112 // 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.
6113 if (strncmp(brname,branchname+motherlen+1,nbch-motherlen-1)) {
6114 // No it does not
6115 continue;
6116 } // else we have match so we can proceed.
6117 } else {
6118 // no match
6119 continue;
6120 }
6121 } else {
6122 continue;
6123 }
6124 }
6125 // The start of the branch name is identical to the content
6126 // of 'aname' before the first '/'.
6127 // Let's make sure that it is not longer (we are trying
6128 // to avoid having jet2/value match the branch jet23
6129 if ((strlen(brname) > nbch) && (brname[nbch] != '.') && (brname[nbch] != '[')) {
6130 continue;
6131 }
6132 }
6133 return leaf;
6134 }
6135 if (!fFriends) return 0;
6136 TFriendLock lock(this,kGetLeaf);
6137 TIter next(fFriends);
6138 TFriendElement *fe;
6139 while ((fe = (TFriendElement*)next())) {
6140 TTree *t = fe->GetTree();
6141 if (t) {
6142 leaf = t->GetLeaf(branchname, leafname);
6143 if (leaf) return leaf;
6144 }
6145 }
6146
6147 //second pass in the list of friends when the leaf name
6148 //is prefixed by the tree name
6149 TString strippedArg;
6150 next.Reset();
6151 while ((fe = (TFriendElement*)next())) {
6152 TTree *t = fe->GetTree();
6153 if (t==0) continue;
6154 char *subname = (char*)strstr(leafname,fe->GetName());
6155 if (subname != leafname) continue;
6156 Int_t l = strlen(fe->GetName());
6157 subname += l;
6158 if (*subname != '.') continue;
6159 subname++;
6160 strippedArg += subname;
6161 leaf = t->GetLeaf(branchname,subname);
6162 if (leaf) return leaf;
6163 }
6164 return 0;
6165}
6166
6167////////////////////////////////////////////////////////////////////////////////
6168/// Return pointer to the 1st Leaf named name in any Branch of this
6169/// Tree or any branch in the list of friend trees.
6170///
6171/// The leaf name can contain the name of a friend tree with the
6172/// syntax: friend_dir_and_tree.full_leaf_name
6173/// the friend_dir_and_tree can be of the form:
6174///
6175/// TDirectoryName/TreeName
6177TLeaf* TTree::GetLeaf(const char* branchname, const char *leafname)
6178{
6179 if (leafname == 0) return 0;
6180
6181 // We already have been visited while recursively looking
6182 // through the friends tree, let return
6184 return 0;
6185 }
6186
6187 return GetLeafImpl(branchname,leafname);
6188}
6189
6190////////////////////////////////////////////////////////////////////////////////
6191/// Return pointer to first leaf named \param[name] in any branch of this
6192/// tree or its friend trees.
6193///
6194/// \param[name] may be in the form 'branch/leaf'
6195///
6197TLeaf* TTree::GetLeaf(const char *name)
6198{
6199 // Return nullptr if name is invalid or if we have
6200 // already been visited while searching friend trees
6201 if (!name || (kGetLeaf & fFriendLockStatus))
6202 return nullptr;
6203
6204 std::string path(name);
6205 const auto sep = path.find_last_of("/");
6206 if (sep != std::string::npos)
6207 return GetLeafImpl(path.substr(0, sep).c_str(), name+sep+1);
6208
6209 return GetLeafImpl(nullptr, name);
6210}
6211
6212////////////////////////////////////////////////////////////////////////////////
6213/// Return maximum of column with name columname.
6214/// if the Tree has an associated TEventList or TEntryList, the maximum
6215/// is computed for the entries in this list.
6217Double_t TTree::GetMaximum(const char* columname)
6218{
6219 TLeaf* leaf = this->GetLeaf(columname);
6220 if (!leaf) {
6221 return 0;
6222 }
6223
6224 // create cache if wanted
6225 if (fCacheDoAutoInit)
6227
6228 TBranch* branch = leaf->GetBranch();
6229 Double_t cmax = -DBL_MAX;
6230 for (Long64_t i = 0; i < fEntries; ++i) {
6231 Long64_t entryNumber = this->GetEntryNumber(i);
6232 if (entryNumber < 0) break;
6233 branch->GetEntry(entryNumber);
6234 for (Int_t j = 0; j < leaf->GetLen(); ++j) {
6235 Double_t val = leaf->GetValue(j);
6236 if (val > cmax) {
6237 cmax = val;
6238 }
6239 }
6240 }
6241 return cmax;
6242}
6243
6244////////////////////////////////////////////////////////////////////////////////
6245/// Static function which returns the tree file size limit in bytes.
6248{
6249 return fgMaxTreeSize;
6250}
6251
6252////////////////////////////////////////////////////////////////////////////////
6253/// Return minimum of column with name columname.
6254/// if the Tree has an associated TEventList or TEntryList, the minimum
6255/// is computed for the entries in this list.
6257Double_t TTree::GetMinimum(const char* columname)
6258{
6259 TLeaf* leaf = this->GetLeaf(columname);
6260 if (!leaf) {
6261 return 0;
6262 }
6263
6264 // create cache if wanted
6265 if (fCacheDoAutoInit)
6267
6268 TBranch* branch = leaf->GetBranch();
6269 Double_t cmin = DBL_MAX;
6270 for (Long64_t i = 0; i < fEntries; ++i) {
6271 Long64_t entryNumber = this->GetEntryNumber(i);
6272 if (entryNumber < 0) break;
6273 branch->GetEntry(entryNumber);
6274 for (Int_t j = 0;j < leaf->GetLen(); ++j) {
6275 Double_t val = leaf->GetValue(j);
6276 if (val < cmin) {
6277 cmin = val;
6278 }
6279 }
6280 }
6281 return cmin;
6282}
6283
6284////////////////////////////////////////////////////////////////////////////////
6285/// Load the TTreePlayer (if not already done).
6288{
6289 if (fPlayer) {
6290 return fPlayer;
6291 }
6293 return fPlayer;
6294}
6295
6296////////////////////////////////////////////////////////////////////////////////
6297/// Find and return the TTreeCache registered with the file and which may
6298/// contain branches for us.
6301{
6302 TTreeCache *pe = dynamic_cast<TTreeCache*>(file->GetCacheRead(GetTree()));
6303 if (pe && pe->GetTree() != GetTree())
6304 pe = nullptr;
6305 return pe;
6306}
6307
6308////////////////////////////////////////////////////////////////////////////////
6309/// Find and return the TTreeCache registered with the file and which may
6310/// contain branches for us. If create is true and there is no cache
6311/// a new cache is created with default size.
6314{
6316 if (create && !pe) {
6317 if (fCacheDoAutoInit)
6319 pe = dynamic_cast<TTreeCache*>(file->GetCacheRead(GetTree()));
6320 if (pe && pe->GetTree() != GetTree()) pe = 0;
6321 }
6322 return pe;
6323}
6324
6325////////////////////////////////////////////////////////////////////////////////
6326/// Return a pointer to the list containing user objects associated to this tree.
6327///
6328/// The list is automatically created if it does not exist.
6329///
6330/// WARNING: By default the TTree destructor will delete all objects added
6331/// to this list. If you do not want these objects to be deleted,
6332/// call:
6333///
6334/// mytree->GetUserInfo()->Clear();
6335///
6336/// before deleting the tree.
6339{
6340 if (!fUserInfo) {
6341 fUserInfo = new TList();
6342 fUserInfo->SetName("UserInfo");
6343 }
6344 return fUserInfo;
6345}
6346
6347////////////////////////////////////////////////////////////////////////////////
6348/// Appends the cluster range information stored in 'fromtree' to this tree,
6349/// including the value of fAutoFlush.
6350///
6351/// This is used when doing a fast cloning (by TTreeCloner).
6352/// See also fAutoFlush and fAutoSave if needed.
6354void TTree::ImportClusterRanges(TTree *fromtree)
6355{
6356 Long64_t autoflush = fromtree->GetAutoFlush();
6357 if (fromtree->fNClusterRange == 0 && fromtree->fAutoFlush == fAutoFlush) {
6358 // nothing to do
6359 } else if (fNClusterRange || fromtree->fNClusterRange) {
6360 Int_t newsize = fNClusterRange + 1 + fromtree->fNClusterRange;
6361 if (newsize > fMaxClusterRange) {
6362 if (fMaxClusterRange) {
6364 newsize*sizeof(Long64_t),fMaxClusterRange*sizeof(Long64_t));
6366 newsize*sizeof(Long64_t),fMaxClusterRange*sizeof(Long64_t));
6367 fMaxClusterRange = newsize;
6368 } else {
6369 fMaxClusterRange = newsize;
6372 }
6373 }
6374 if (fEntries) {
6378 }
6379 for (Int_t i = 0 ; i < fromtree->fNClusterRange; ++i) {
6383 }
6384 fAutoFlush = autoflush;
6385 } else {
6386 SetAutoFlush( autoflush );
6387 }
6388 Long64_t autosave = GetAutoSave();
6389 if (autoflush > 0 && autosave > 0) {
6390 SetAutoSave( autoflush*(autosave/autoflush) );
6391 }
6392}
6393
6394////////////////////////////////////////////////////////////////////////////////
6395/// Keep a maximum of fMaxEntries in memory.
6398{
6400 Long64_t maxEntries = fMaxEntries - (fMaxEntries / 10);
6401 for (Int_t i = 0; i < nb; ++i) {
6402 TBranch* branch = (TBranch*) fBranches.UncheckedAt(i);
6403 branch->KeepCircular(maxEntries);
6404 }
6405 if (fNClusterRange) {
6406 Long64_t entriesOffset = fEntries - maxEntries;
6407 Int_t oldsize = fNClusterRange;
6408 for(Int_t i = 0, j = 0; j < oldsize; ++j) {
6409 if (fClusterRangeEnd[j] > entriesOffset) {
6410 fClusterRangeEnd[i] = fClusterRangeEnd[j] - entriesOffset;
6411 ++i;
6412 } else {
6414 }
6415 }
6416 }
6417 fEntries = maxEntries;
6418 fReadEntry = -1;
6419}
6420
6421////////////////////////////////////////////////////////////////////////////////
6422/// Read in memory all baskets from all branches up to the limit of maxmemory bytes.
6423///
6424/// If maxmemory is non null and positive SetMaxVirtualSize is called
6425/// with this value. Default for maxmemory is 2000000000 (2 Gigabytes).
6426/// The function returns the total number of baskets read into memory
6427/// if negative an error occurred while loading the branches.
6428/// This method may be called to force branch baskets in memory
6429/// when random access to branch entries is required.
6430/// If random access to only a few branches is required, you should
6431/// call directly TBranch::LoadBaskets.
6434{
6435 if (maxmemory > 0) SetMaxVirtualSize(maxmemory);
6436
6437 TIter next(GetListOfLeaves());
6438 TLeaf *leaf;
6439 Int_t nimported = 0;
6440 while ((leaf=(TLeaf*)next())) {
6441 nimported += leaf->GetBranch()->LoadBaskets();//break;
6442 }
6443 return nimported;
6444}
6445
6446////////////////////////////////////////////////////////////////////////////////
6447/// Set current entry.
6448///
6449/// Returns -2 if entry does not exist (just as TChain::LoadTree()).
6450/// Returns -6 if an error occurs in the notification callback (just as TChain::LoadTree()).
6451///
6452/// Note: This function is overloaded in TChain.
6453///
6456{
6457 // We already have been visited while recursively looking
6458 // through the friends tree, let return
6460 // We need to return a negative value to avoid a circular list of friend
6461 // to think that there is always an entry somewhere in the list.
6462 return -1;
6463 }
6464
6465 // create cache if wanted
6466 if (fCacheDoAutoInit && entry >=0)
6468
6469 if (fNotify) {
6470 if (fReadEntry < 0) {
6471 fNotify->Notify();
6472 }
6473 }
6474 fReadEntry = entry;
6475
6476 Bool_t friendHasEntry = kFALSE;
6477 if (fFriends) {
6478 // Set current entry in friends as well.
6479 //
6480 // An alternative would move this code to each of the
6481 // functions calling LoadTree (and to overload a few more).
6482 Bool_t needUpdate = kFALSE;
6483 {
6484 // This scope is need to insure the lock is released at the right time
6485 TIter nextf(fFriends);
6486 TFriendLock lock(this, kLoadTree);
6487 TFriendElement* fe = 0;
6488 while ((fe = (TFriendElement*) nextf())) {
6490 // This friend element was added by the chain that owns this
6491 // tree, the chain will deal with loading the correct entry.
6492 continue;
6493 }
6494 TTree* friendTree = fe->GetTree();
6495 if (friendTree) {
6496 if (friendTree->LoadTreeFriend(entry, this) >= 0) {
6497 friendHasEntry = kTRUE;
6498 }
6499 }
6500 if (fe->IsUpdated()) {
6501 needUpdate = kTRUE;
6502 fe->ResetUpdated();
6503 }
6504 } // for each friend
6505 }
6506 if (needUpdate) {
6507 //update list of leaves in all TTreeFormula of the TTreePlayer (if any)
6508 if (fPlayer) {
6510 }
6511 //Notify user if requested
6512 if (fNotify) {
6513 if(!fNotify->Notify()) return -6;
6514 }
6515 }
6516 }
6517
6518 if ((fReadEntry >= fEntries) && !friendHasEntry) {
6519 fReadEntry = -1;
6520 return -2;
6521 }
6522 return fReadEntry;
6523}
6524
6525////////////////////////////////////////////////////////////////////////////////
6526/// Load entry on behalf of our master tree, we may use an index.
6527///
6528/// Called by LoadTree() when the masterTree looks for the entry
6529/// number in a friend tree (us) corresponding to the passed entry
6530/// number in the masterTree.
6531///
6532/// If we have no index, our entry number and the masterTree entry
6533/// number are the same.
6534///
6535/// If we *do* have an index, we must find the (major, minor) value pair
6536/// in masterTree to locate our corresponding entry.
6537///
6539Long64_t TTree::LoadTreeFriend(Long64_t entry, TTree* masterTree)
6540{
6541 if (!fTreeIndex) {
6542 return LoadTree(entry);
6543 }
6544 return LoadTree(fTreeIndex->GetEntryNumberFriend(masterTree));
6545}
6546
6547////////////////////////////////////////////////////////////////////////////////
6548/// Generate a skeleton analysis class for this tree.
6549///
6550/// The following files are produced: classname.h and classname.C.
6551/// If classname is 0, classname will be called "nameoftree".
6552///
6553/// The generated code in classname.h includes the following:
6554///
6555/// - Identification of the original tree and the input file name.
6556/// - Definition of an analysis class (data members and member functions).
6557/// - The following member functions:
6558/// - constructor (by default opening the tree file),
6559/// - GetEntry(Long64_t entry),
6560/// - Init(TTree* tree) to initialize a new TTree,
6561/// - Show(Long64_t entry) to read and dump entry.
6562///
6563/// The generated code in classname.C includes only the main
6564/// analysis function Loop.
6565///
6566/// To use this function:
6567///
6568/// - Open your tree file (eg: TFile f("myfile.root");)
6569/// - T->MakeClass("MyClass");
6570///
6571/// where T is the name of the TTree in file myfile.root,
6572/// and MyClass.h, MyClass.C the name of the files created by this function.
6573/// In a ROOT session, you can do:
6574/// ~~~ {.cpp}
6575/// root > .L MyClass.C
6576/// root > MyClass* t = new MyClass;
6577/// root > t->GetEntry(12); // Fill data members of t with entry number 12.
6578/// root > t->Show(); // Show values of entry 12.
6579/// root > t->Show(16); // Read and show values of entry 16.
6580/// root > t->Loop(); // Loop on all entries.
6581/// ~~~
6582/// NOTE: Do not use the code generated for a single TTree which is part
6583/// of a TChain to process that entire TChain. The maximum dimensions
6584/// calculated for arrays on the basis of a single TTree from the TChain
6585/// might be (will be!) too small when processing all of the TTrees in
6586/// the TChain. You must use myChain.MakeClass() to generate the code,
6587/// not myTree.MakeClass(...).
6589Int_t TTree::MakeClass(const char* classname, Option_t* option)
6590{
6591 GetPlayer();
6592 if (!fPlayer) {
6593 return 0;
6594 }
6595 return fPlayer->MakeClass(classname, option);
6596}
6597
6598////////////////////////////////////////////////////////////////////////////////
6599/// Generate a skeleton function for this tree.
6600///
6601/// The function code is written on filename.
6602/// If filename is 0, filename will be called nameoftree.C
6603///
6604/// The generated code includes the following:
6605/// - Identification of the original Tree and Input file name,
6606/// - Opening the Tree file,
6607/// - Declaration of Tree variables,
6608/// - Setting of branches addresses,
6609/// - A skeleton for the entry loop.
6610///
6611/// To use this function:
6612///
6613/// - Open your Tree file (eg: TFile f("myfile.root");)
6614/// - T->MakeCode("MyAnalysis.C");
6615///
6616/// where T is the name of the TTree in file myfile.root
6617/// and MyAnalysis.C the name of the file created by this function.
6618///
6619/// NOTE: Since the implementation of this function, a new and better
6620/// function TTree::MakeClass() has been developed.
6622Int_t TTree::MakeCode(const char* filename)
6623{
6624 Warning("MakeCode", "MakeCode is obsolete. Use MakeClass or MakeSelector instead");
6625
6626 GetPlayer();
6627 if (!fPlayer) return 0;
6628 return fPlayer->MakeCode(filename);
6629}
6630
6631////////////////////////////////////////////////////////////////////////////////
6632/// Generate a skeleton analysis class for this Tree using TBranchProxy.
6633///
6634/// TBranchProxy is the base of a class hierarchy implementing an
6635/// indirect access to the content of the branches of a TTree.
6636///
6637/// "proxyClassname" is expected to be of the form:
6638/// ~~~ {.cpp}
6639/// [path/]fileprefix
6640/// ~~~
6641/// The skeleton will then be generated in the file:
6642/// ~~~ {.cpp}
6643/// fileprefix.h
6644/// ~~~
6645/// located in the current directory or in 'path/' if it is specified.
6646/// The class generated will be named 'fileprefix'
6647///
6648/// "macrofilename" and optionally "cutfilename" are expected to point
6649/// to source files which will be included by the generated skeleton.
6650/// Method of the same name as the file(minus the extension and path)
6651/// will be called by the generated skeleton's Process method as follow:
6652/// ~~~ {.cpp}
6653/// [if (cutfilename())] htemp->Fill(macrofilename());
6654/// ~~~
6655/// "option" can be used select some of the optional features during
6656/// the code generation. The possible options are:
6657///
6658/// - nohist : indicates that the generated ProcessFill should not fill the histogram.
6659///
6660/// 'maxUnrolling' controls how deep in the class hierarchy does the
6661/// system 'unroll' classes that are not split. Unrolling a class
6662/// allows direct access to its data members (this emulates the behavior
6663/// of TTreeFormula).
6664///
6665/// The main features of this skeleton are:
6666///
6667/// * on-demand loading of branches
6668/// * ability to use the 'branchname' as if it was a data member
6669/// * protection against array out-of-bounds errors
6670/// * ability to use the branch data as an object (when the user code is available)
6671///
6672/// For example with Event.root, if
6673/// ~~~ {.cpp}
6674/// Double_t somePx = fTracks.fPx[2];
6675/// ~~~
6676/// is executed by one of the method of the skeleton,
6677/// somePx will updated with the current value of fPx of the 3rd track.
6678///
6679/// Both macrofilename and the optional cutfilename are expected to be
6680/// the name of source files which contain at least a free standing
6681/// function with the signature:
6682/// ~~~ {.cpp}
6683/// x_t macrofilename(); // i.e function with the same name as the file
6684/// ~~~
6685/// and
6686/// ~~~ {.cpp}
6687/// y_t cutfilename(); // i.e function with the same name as the file
6688/// ~~~
6689/// x_t and y_t needs to be types that can convert respectively to a double
6690/// and a bool (because the skeleton uses:
6691///
6692/// if (cutfilename()) htemp->Fill(macrofilename());
6693///
6694/// These two functions are run in a context such that the branch names are
6695/// available as local variables of the correct (read-only) type.
6696///
6697/// Note that if you use the same 'variable' twice, it is more efficient
6698/// to 'cache' the value. For example:
6699/// ~~~ {.cpp}
6700/// Int_t n = fEventNumber; // Read fEventNumber
6701/// if (n<10 || n>10) { ... }
6702/// ~~~
6703/// is more efficient than
6704/// ~~~ {.cpp}
6705/// if (fEventNumber<10 || fEventNumber>10)
6706/// ~~~
6707/// Also, optionally, the generated selector will also call methods named
6708/// macrofilename_methodname in each of 6 main selector methods if the method
6709/// macrofilename_methodname exist (Where macrofilename is stripped of its
6710/// extension).
6711///
6712/// Concretely, with the script named h1analysisProxy.C,
6713///
6714/// - The method calls the method (if it exist)
6715/// - Begin -> void h1analysisProxy_Begin(TTree*);
6716/// - SlaveBegin -> void h1analysisProxy_SlaveBegin(TTree*);
6717/// - Notify -> Bool_t h1analysisProxy_Notify();
6718/// - Process -> Bool_t h1analysisProxy_Process(Long64_t);
6719/// - SlaveTerminate -> void h1analysisProxy_SlaveTerminate();
6720/// - Terminate -> void h1analysisProxy_Terminate();
6721///
6722/// If a file name macrofilename.h (or .hh, .hpp, .hxx, .hPP, .hXX) exist
6723/// it is included before the declaration of the proxy class. This can
6724/// be used in particular to insure that the include files needed by
6725/// the macro file are properly loaded.
6726///
6727/// The default histogram is accessible via the variable named 'htemp'.
6728///
6729/// If the library of the classes describing the data in the branch is
6730/// loaded, the skeleton will add the needed `include` statements and
6731/// give the ability to access the object stored in the branches.
6732///
6733/// To draw px using the file hsimple.root (generated by the
6734/// hsimple.C tutorial), we need a file named hsimple.cxx:
6735/// ~~~ {.cpp}
6736/// double hsimple() {
6737/// return px;
6738/// }
6739/// ~~~
6740/// MakeProxy can then be used indirectly via the TTree::Draw interface
6741/// as follow:
6742/// ~~~ {.cpp}
6743/// new TFile("hsimple.root")
6744/// ntuple->Draw("hsimple.cxx");
6745/// ~~~
6746/// A more complete example is available in the tutorials directory:
6747/// h1analysisProxy.cxx , h1analysProxy.h and h1analysisProxyCut.C
6748/// which reimplement the selector found in h1analysis.C
6750Int_t TTree::MakeProxy(const char* proxyClassname, const char* macrofilename, const char* cutfilename, const char* option, Int_t maxUnrolling)
6751{
6752 GetPlayer();
6753 if (!fPlayer) return 0;
6754 return fPlayer->MakeProxy(proxyClassname,macrofilename,cutfilename,option,maxUnrolling);
6755}
6756
6757////////////////////////////////////////////////////////////////////////////////
6758/// Generate skeleton selector class for this tree.
6759///
6760/// The following files are produced: selector.h and selector.C.
6761/// If selector is 0, the selector will be called "nameoftree".
6762/// The option can be used to specify the branches that will have a data member.
6763/// - If option is "=legacy", a pre-ROOT6 selector will be generated (data
6764/// members and branch pointers instead of TTreeReaders).
6765/// - If option is empty, readers will be generated for each leaf.
6766/// - If option is "@", readers will be generated for the topmost branches.
6767/// - Individual branches can also be picked by their name:
6768/// - "X" generates readers for leaves of X.
6769/// - "@X" generates a reader for X as a whole.
6770/// - "@X;Y" generates a reader for X as a whole and also readers for the
6771/// leaves of Y.
6772/// - For further examples see the figure below.
6773///
6774/// \image html ttree_makeselector_option_examples.png
6775///
6776/// The generated code in selector.h includes the following:
6777/// - Identification of the original Tree and Input file name
6778/// - Definition of selector class (data and functions)
6779/// - The following class functions:
6780/// - constructor and destructor
6781/// - void Begin(TTree *tree)
6782/// - void SlaveBegin(TTree *tree)
6783/// - void Init(TTree *tree)
6784/// - Bool_t Notify()
6785/// - Bool_t Process(Long64_t entry)
6786/// - void Terminate()
6787/// - void SlaveTerminate()
6788///
6789/// The class selector derives from TSelector.
6790/// The generated code in selector.C includes empty functions defined above.
6791///
6792/// To use this function:
6793///
6794/// - connect your Tree file (eg: `TFile f("myfile.root");`)
6795/// - `T->MakeSelector("myselect");`
6796///
6797/// where T is the name of the Tree in file myfile.root
6798/// and myselect.h, myselect.C the name of the files created by this function.
6799/// In a ROOT session, you can do:
6800/// ~~~ {.cpp}
6801/// root > T->Process("myselect.C")
6802/// ~~~
6804Int_t TTree::MakeSelector(const char* selector, Option_t* option)
6805{
6806 TString opt(option);
6807 if(opt.EqualTo("=legacy", TString::ECaseCompare::kIgnoreCase)) {
6808 return MakeClass(selector, "selector");
6809 } else {
6810 GetPlayer();
6811 if (!fPlayer) return 0;
6812 return fPlayer->MakeReader(selector, option);
6813 }
6814}
6815
6816////////////////////////////////////////////////////////////////////////////////
6817/// Check if adding nbytes to memory we are still below MaxVirtualsize.
6820{
6821 if ((fTotalBuffers + nbytes) < fMaxVirtualSize) {
6822 return kFALSE;
6823 }
6824 return kTRUE;
6825}
6826
6827////////////////////////////////////////////////////////////////////////////////
6828/// Static function merging the trees in the TList into a new tree.
6829///
6830/// Trees in the list can be memory or disk-resident trees.
6831/// The new tree is created in the current directory (memory if gROOT).
6833TTree* TTree::MergeTrees(TList* li, Option_t* options)
6834{
6835 if (!li) return 0;
6836 TIter next(li);
6837 TTree *newtree = 0;
6838 TObject *obj;
6839
6840 while ((obj=next())) {
6841 if (!obj->InheritsFrom(TTree::Class())) continue;
6842 TTree *tree = (TTree*)obj;
6843 Long64_t nentries = tree->GetEntries();
6844 if (nentries == 0) continue;
6845 if (!newtree) {
6846 newtree = (TTree*)tree->CloneTree(-1, options);
6847 if (!newtree) continue;
6848
6849 // Once the cloning is done, separate the trees,
6850 // to avoid as many side-effects as possible
6851 // The list of clones is guaranteed to exist since we
6852 // just cloned the tree.
6853 tree->GetListOfClones()->Remove(newtree);
6854 tree->ResetBranchAddresses();
6855 newtree->ResetBranchAddresses();
6856 continue;
6857 }
6858
6859 newtree->CopyEntries(tree, -1, options, kTRUE);
6860 }
6861 if (newtree && newtree->GetTreeIndex()) {
6862 newtree->GetTreeIndex()->Append(0,kFALSE); // Force the sorting
6863 }
6864 return newtree;
6865}
6866
6867////////////////////////////////////////////////////////////////////////////////
6868/// Merge the trees in the TList into this tree.
6869///
6870/// Returns the total number of entries in the merged tree.
6873{
6874 if (!li) return 0;
6875 Long64_t storeAutoSave = fAutoSave;
6876 // Disable the autosave as the TFileMerge keeps a list of key and deleting the underlying
6877 // key would invalidate its iteration (or require costly measure to not use the deleted keys).
6878 // Also since this is part of a merging operation, the output file is not as precious as in
6879 // the general case since the input file should still be around.
6880 fAutoSave = 0;
6881 TIter next(li);
6882 TTree *tree;
6883 while ((tree = (TTree*)next())) {
6884 if (tree==this) continue;
6885 if (!tree->InheritsFrom(TTree::Class())) {
6886 Error("Add","Attempt to add object of class: %s to a %s", tree->ClassName(), ClassName());
6887 fAutoSave = storeAutoSave;
6888 return -1;
6889 }
6890
6891 Long64_t nentries = tree->GetEntries();
6892 if (nentries == 0) continue;
6893
6894 CopyEntries(tree, -1, options, kTRUE);
6895 }
6896 fAutoSave = storeAutoSave;
6897 return GetEntries();
6898}
6899
6900////////////////////////////////////////////////////////////////////////////////
6901/// Merge the trees in the TList into this tree.
6902/// If info->fIsFirst is true, first we clone this TTree info the directory
6903/// info->fOutputDirectory and then overlay the new TTree information onto
6904/// this TTree object (so that this TTree object is now the appropriate to
6905/// use for further merging).
6906///
6907/// Returns the total number of entries in the merged tree.
6910{
6911 const char *options = info ? info->fOptions.Data() : "";
6912 if (info && info->fIsFirst && info->fOutputDirectory && info->fOutputDirectory->GetFile() != GetCurrentFile()) {
6913 if (GetCurrentFile() == nullptr) {
6914 // In memory TTree, all we need to do is ... write it.
6917 fDirectory->WriteTObject(this);
6918 } else if (info->fOptions.Contains("fast")) {
6920 } else {
6922 TIOFeatures saved_features = fIOFeatures;
6923 TTree *newtree = CloneTree(-1, options);
6924 if (info->fIOFeatures)
6925 fIOFeatures = *(info->fIOFeatures);
6926 else
6927 fIOFeatures = saved_features;
6928 if (newtree) {
6929 newtree->Write();
6930 delete newtree;
6931 }
6932 // Make sure things are really written out to disk before attempting any reading.
6933 info->fOutputDirectory->GetFile()->Flush();
6934 info->fOutputDirectory->ReadTObject(this,this->GetName());
6935 }
6936 }
6937 if (!li) return 0;
6938 Long64_t storeAutoSave = fAutoSave;
6939 // Disable the autosave as the TFileMerge keeps a list of key and deleting the underlying
6940 // key would invalidate its iteration (or require costly measure to not use the deleted keys).
6941 // Also since this is part of a merging operation, the output file is not as precious as in
6942 // the general case since the input file should still be around.
6943 fAutoSave = 0;
6944 TIter next(li);
6945 TTree *tree;
6946 while ((tree = (TTree*)next())) {
6947 if (tree==this) continue;
6948 if (!tree->InheritsFrom(TTree::Class())) {
6949 Error("Add","Attempt to add object of class: %s to a %s", tree->ClassName(), ClassName());
6950 fAutoSave = storeAutoSave;
6951 return -1;
6952 }
6953
6954 CopyEntries(tree, -1, options, kTRUE);
6955 }
6956 fAutoSave = storeAutoSave;
6957 return GetEntries();
6958}
6959
6960////////////////////////////////////////////////////////////////////////////////
6961/// Move a cache from a file to the current file in dir.
6962/// if src is null no operation is done, if dir is null or there is no
6963/// current file the cache is deleted.
6965void TTree::MoveReadCache(TFile *src, TDirectory *dir)
6966{
6967 if (!src) return;
6968 TFile *dst = (dir && dir != gROOT) ? dir->GetFile() : 0;
6969 if (src == dst) return;
6970
6971 TTreeCache *pf = GetReadCache(src);
6972 if (dst) {
6973 src->SetCacheRead(0,this);
6974 dst->SetCacheRead(pf, this);
6975 } else {
6976 if (pf) {
6977 pf->WaitFinishPrefetch();
6978 }
6979 src->SetCacheRead(0,this);
6980 delete pf;
6981 }
6982}
6983
6984////////////////////////////////////////////////////////////////////////////////
6985/// Copy the content to a new new file, update this TTree with the new
6986/// location information and attach this TTree to the new directory.
6987///
6988/// options: Indicates a basket sorting method, see TTreeCloner::TTreeCloner for
6989/// details
6990///
6991/// If new and old directory are in the same file, the data is untouched,
6992/// this "just" does a call to SetDirectory.
6993/// Equivalent to an "in place" cloning of the TTree.
6994Bool_t TTree::InPlaceClone(TDirectory *newdirectory, const char *options)
6995{
6996 if (!newdirectory) {
6998 SetDirectory(nullptr);
6999 return true;
7000 }
7001 if (newdirectory->GetFile() == GetCurrentFile()) {
7002 SetDirectory(newdirectory);
7003 return true;
7004 }
7005 TTreeCloner cloner(this, newdirectory, options);
7006 if (cloner.IsValid())
7007 return cloner.Exec();
7008 else
7009 return false;
7010}
7011
7012////////////////////////////////////////////////////////////////////////////////
7013/// Function called when loading a new class library.
7016{
7017 TIter next(GetListOfLeaves());
7018 TLeaf* leaf = 0;
7019 while ((leaf = (TLeaf*) next())) {
7020 leaf->Notify();
7021 leaf->GetBranch()->Notify();
7022 }
7023 return kTRUE;
7024}
7025
7026////////////////////////////////////////////////////////////////////////////////
7027/// This function may be called after having filled some entries in a Tree.
7028/// Using the information in the existing branch buffers, it will reassign
7029/// new branch buffer sizes to optimize time and memory.
7030///
7031/// The function computes the best values for branch buffer sizes such that
7032/// the total buffer sizes is less than maxMemory and nearby entries written
7033/// at the same time.
7034/// In case the branch compression factor for the data written so far is less
7035/// than compMin, the compression is disabled.
7036///
7037/// if option ="d" an analysis report is printed.
7039void TTree::OptimizeBaskets(ULong64_t maxMemory, Float_t minComp, Option_t *option)
7040{
7041 //Flush existing baskets if the file is writable
7042 if (this->GetDirectory()->IsWritable()) this->FlushBasketsImpl();
7043
7044 TString opt( option );
7045 opt.ToLower();
7046 Bool_t pDebug = opt.Contains("d");
7047 TObjArray *leaves = this->GetListOfLeaves();
7048 Int_t nleaves = leaves->GetEntries();
7049 Double_t treeSize = (Double_t)this->GetTotBytes();
7050
7051 if (nleaves == 0 || treeSize == 0) {
7052 // We're being called too early, we really have nothing to do ...
7053 return;
7054 }
7055 Double_t aveSize = treeSize/nleaves;
7056 UInt_t bmin = 512;
7057 UInt_t bmax = 256000;
7058 Double_t memFactor = 1;
7059 Int_t i, oldMemsize,newMemsize,oldBaskets,newBaskets;
7060 i = oldMemsize = newMemsize = oldBaskets = newBaskets = 0;
7061
7062 //we make two passes
7063 //one pass to compute the relative branch buffer sizes
7064 //a second pass to compute the absolute values
7065 for (Int_t pass =0;pass<2;pass++) {
7066 oldMemsize = 0; //to count size of baskets in memory with old buffer size
7067 newMemsize = 0; //to count size of baskets in memory with new buffer size
7068 oldBaskets = 0; //to count number of baskets with old buffer size
7069 newBaskets = 0; //to count number of baskets with new buffer size
7070 for (i=0;i<nleaves;i++) {
7071 TLeaf *leaf = (TLeaf*)leaves->At(i);
7072 TBranch *branch = leaf->GetBranch();
7073 Double_t totBytes = (Double_t)branch->GetTotBytes();
7074 Double_t idealFactor = totBytes/aveSize;
7075 UInt_t sizeOfOneEntry;
7076 if (branch->GetEntries() == 0) {
7077 // There is no data, so let's make a guess ...
7078 sizeOfOneEntry = aveSize;
7079 } else {
7080 sizeOfOneEntry = 1+(UInt_t)(totBytes / (Double_t)branch->GetEntries());
7081 }
7082 Int_t oldBsize = branch->GetBasketSize();
7083 oldMemsize += oldBsize;
7084 oldBaskets += 1+Int_t(totBytes/oldBsize);
7085 Int_t nb = branch->GetListOfBranches()->GetEntries();
7086 if (nb > 0) {
7087 newBaskets += 1+Int_t(totBytes/oldBsize);
7088 continue;
7089 }
7090 Double_t bsize = oldBsize*idealFactor*memFactor; //bsize can be very large !
7091 if (bsize < 0) bsize = bmax;
7092 if (bsize > bmax) bsize = bmax;
7093 UInt_t newBsize = UInt_t(bsize);
7094 if (pass) { // only on the second pass so that it doesn't interfere with scaling
7095 // If there is an entry offset, it will be stored in the same buffer as the object data; hence,
7096 // we must bump up the size of the branch to account for this extra footprint.
7097 // If fAutoFlush is not set yet, let's assume that it is 'in the process of being set' to
7098 // the value of GetEntries().
7099 Long64_t clusterSize = (fAutoFlush > 0) ? fAutoFlush : branch->GetEntries();
7100 if (branch->GetEntryOffsetLen()) {
7101 newBsize = newBsize + (clusterSize * sizeof(Int_t) * 2);
7102 }
7103 // We used ATLAS fully-split xAOD for testing, which is a rather unbalanced TTree, 10K branches,
7104 // with 8K having baskets smaller than 512 bytes. To achieve good I/O performance ATLAS uses auto-flush 100,
7105 // resulting in the smallest baskets being ~300-400 bytes, so this change increases their memory by about 8k*150B =~ 1MB,
7106 // at the same time it significantly reduces the number of total baskets because it ensures that all 100 entries can be
7107 // stored in a single basket (the old optimization tended to make baskets too small). In a toy example with fixed sized
7108 // structures we found a factor of 2 fewer baskets needed in the new scheme.
7109 // rounds up, increases basket size to ensure all entries fit into single basket as intended
7110 newBsize = newBsize - newBsize%512 + 512;
7111 }
7112 if (newBsize < sizeOfOneEntry) newBsize = sizeOfOneEntry;
7113 if (newBsize < bmin) newBsize = bmin;
7114 if (newBsize > 10000000) newBsize = bmax;
7115 if (pass) {
7116 if (pDebug) Info("OptimizeBaskets", "Changing buffer size from %6d to %6d bytes for %s\n",oldBsize,newBsize,branch->GetName());
7117 branch->SetBasketSize(newBsize);
7118 }
7119 newMemsize += newBsize;
7120 // For this number to be somewhat accurate when newBsize is 'low'
7121 // we do not include any space for meta data in the requested size (newBsize) even-though SetBasketSize will
7122 // not let it be lower than 100+TBranch::fEntryOffsetLen.
7123 newBaskets += 1+Int_t(totBytes/newBsize);
7124 if (pass == 0) continue;
7125 //Reset the compression level in case the compression factor is small
7126 Double_t comp = 1;
7127 if (branch->GetZipBytes() > 0) comp = totBytes/Double_t(branch->GetZipBytes());
7128 if (comp > 1 && comp < minComp) {
7129 if (pDebug) Info("OptimizeBaskets", "Disabling compression for branch : %s\n",branch->GetName());
7131 }
7132 }
7133 // coverity[divide_by_zero] newMemsize can not be zero as there is at least one leaf
7134 memFactor = Double_t(maxMemory)/Double_t(newMemsize);
7135 if (memFactor > 100) memFactor = 100;
7136 Double_t bmin_new = bmin*memFactor;
7137 Double_t bmax_new = bmax*memFactor;
7138 static const UInt_t hardmax = 1*1024*1024*1024; // Really, really never give more than 1Gb to a single buffer.
7139
7140 // Really, really never go lower than 8 bytes (we use this number
7141 // so that the calculation of the number of basket is consistent
7142 // but in fact SetBasketSize will not let the size go below
7143 // TBranch::fEntryOffsetLen + (100 + strlen(branch->GetName())
7144 // (The 2nd part being a slight over estimate of the key length.
7145 static const UInt_t hardmin = 8;
7146 bmin = (bmin_new > hardmax) ? hardmax : ( bmin_new < hardmin ? hardmin : (UInt_t)bmin_new );
7147 bmax = (bmax_new > hardmax) ? bmin : (UInt_t)bmax_new;
7148 }
7149 if (pDebug) {
7150 Info("OptimizeBaskets", "oldMemsize = %d, newMemsize = %d\n",oldMemsize, newMemsize);
7151 Info("OptimizeBaskets", "oldBaskets = %d, newBaskets = %d\n",oldBaskets, newBaskets);
7152 }
7153}
7154
7155////////////////////////////////////////////////////////////////////////////////
7156/// Interface to the Principal Components Analysis class.
7157///
7158/// Create an instance of TPrincipal
7159///
7160/// Fill it with the selected variables
7161///
7162/// - if option "n" is specified, the TPrincipal object is filled with
7163/// normalized variables.
7164/// - If option "p" is specified, compute the principal components
7165/// - If option "p" and "d" print results of analysis
7166/// - If option "p" and "h" generate standard histograms
7167/// - If option "p" and "c" generate code of conversion functions
7168/// - return a pointer to the TPrincipal object. It is the user responsibility
7169/// - to delete this object.
7170/// - The option default value is "np"
7171///
7172/// see TTree::Draw for explanation of the other parameters.
7173///
7174/// The created object is named "principal" and a reference to it
7175/// is added to the list of specials Root objects.
7176/// you can retrieve a pointer to the created object via:
7177/// ~~~ {.cpp}
7178/// TPrincipal *principal =
7179/// (TPrincipal*)gROOT->GetListOfSpecials()->FindObject("principal");
7180/// ~~~
7182TPrincipal* TTree::Principal(const char* varexp, const char* selection, Option_t* option, Long64_t nentries, Long64_t firstentry)
7183{
7184 GetPlayer();
7185 if (fPlayer) {
7186 return fPlayer->Principal(varexp, selection, option, nentries, firstentry);
7187 }
7188 return 0;
7189}
7190
7191////////////////////////////////////////////////////////////////////////////////
7192/// Print a summary of the tree contents.
7193///
7194/// - If option contains "all" friend trees are also printed.
7195/// - If option contains "toponly" only the top level branches are printed.
7196/// - If option contains "clusters" information about the cluster of baskets is printed.
7197///
7198/// Wildcarding can be used to print only a subset of the branches, e.g.,
7199/// `T.Print("Elec*")` will print all branches with name starting with "Elec".
7201void TTree::Print(Option_t* option) const
7202{
7203 // We already have been visited while recursively looking
7204 // through the friends tree, let's return.
7205 if (kPrint & fFriendLockStatus) {
7206 return;
7207 }
7208 Int_t s = 0;
7209 Int_t skey = 0;
7210 if (fDirectory) {
7211 TKey* key = fDirectory->GetKey(GetName());
7212 if (key) {
7213 skey = key->GetKeylen();
7214 s = key->GetNbytes();
7215 }
7216 }
7217 Long64_t total = skey;
7218 Long64_t zipBytes = GetZipBytes();
7219 if (zipBytes > 0) {
7220 total += GetTotBytes();
7221 }
7223 TTree::Class()->WriteBuffer(b, (TTree*) this);
7224 total += b.Length();
7225 Long64_t file = zipBytes + s;
7226 Float_t cx = 1;
7227 if (zipBytes) {
7228 cx = (GetTotBytes() + 0.00001) / zipBytes;
7229 }
7230 Printf("******************************************************************************");
7231 Printf("*Tree :%-10s: %-54s *", GetName(), GetTitle());
7232 Printf("*Entries : %8lld : Total = %15lld bytes File Size = %10lld *", fEntries, total, file);
7233 Printf("* : : Tree compression factor = %6.2f *", cx);
7234 Printf("******************************************************************************");
7235
7236 // Avoid many check of option validity
7237 if (option == nullptr)
7238 option = "";
7239
7240 if (strncmp(option,"clusters",strlen("clusters"))==0) {
7241 Printf("%-16s %-16s %-16s %8s %20s",
7242 "Cluster Range #", "Entry Start", "Last Entry", "Size", "Number of clusters");
7243 Int_t index= 0;
7244 Long64_t clusterRangeStart = 0;
7245 Long64_t totalClusters = 0;
7246 bool estimated = false;
7247 bool unknown = false;
7248 auto printer = [this, &totalClusters, &estimated, &unknown](Int_t ind, Long64_t start, Long64_t end, Long64_t recordedSize) {
7249 Long64_t nclusters = 0;
7250 if (recordedSize > 0) {
7251 nclusters = (1 + end - start) / recordedSize;
7252 Printf("%-16d %-16lld %-16lld %8lld %10lld",
7253 ind, start, end, recordedSize, nclusters);
7254 } else {
7255 // NOTE: const_cast ... DO NOT Merge for now
7256 TClusterIterator iter((TTree*)this, start);
7257 iter.Next();
7258 auto estimated_size = iter.GetNextEntry() - start;
7259 if (estimated_size > 0) {
7260 nclusters = (1 + end - start) / estimated_size;
7261 Printf("%-16d %-16lld %-16lld %8lld %10lld (estimated)",
7262 ind, start, end, recordedSize, nclusters);
7263 estimated = true;
7264 } else {
7265 Printf("%-16d %-16lld %-16lld %8lld (unknown)",
7266 ind, start, end, recordedSize);
7267 unknown = true;
7268 }
7269 }
7270 start = end + 1;
7271 totalClusters += nclusters;
7272 };
7273 if (fNClusterRange) {
7274 for( ; index < fNClusterRange; ++index) {
7275 printer(index, clusterRangeStart, fClusterRangeEnd[index], fClusterSize[index]);
7276 clusterRangeStart = fClusterRangeEnd[index] + 1;
7277 }
7278 }
7279 printer(index, clusterRangeStart, fEntries - 1, fAutoFlush);
7280 if (unknown) {
7281 Printf("Total number of clusters: (unknown)");
7282 } else {
7283 Printf("Total number of clusters: %lld %s", totalClusters, estimated ? "(estimated)" : "");
7284 }
7285 return;
7286 }
7287
7288 Int_t nl = const_cast<TTree*>(this)->GetListOfLeaves()->GetEntries();
7289 Int_t l;
7290 TBranch* br = 0;
7291 TLeaf* leaf = 0;
7292 if (strstr(option, "toponly")) {
7293 Long64_t *count = new Long64_t[nl];
7294 Int_t keep =0;
7295 for (l=0;l<nl;l++) {
7296 leaf = (TLeaf *)const_cast<TTree*>(this)->GetListOfLeaves()->At(l);
7297 br = leaf->GetBranch();
7298 if (strchr(br->GetName(),'.')) {
7299 count[l] = -1;
7300 count[keep] += br->GetZipBytes();
7301 } else {
7302 keep = l;
7303 count[keep] = br->GetZipBytes();
7304 }
7305 }
7306 for (l=0;l<nl;l++) {
7307 if (count[l] < 0) continue;
7308 leaf = (TLeaf *)const_cast<TTree*>(this)->GetListOfLeaves()->At(l);
7309 br = leaf->GetBranch();
7310 Printf("branch: %-20s %9lld\n",br->GetName(),count[l]);
7311 }
7312 delete [] count;
7313 } else {
7314 TString reg = "*";
7315 if (strlen(option) && strchr(option,'*')) reg = option;
7316 TRegexp re(reg,kTRUE);
7317 TIter next(const_cast<TTree*>(this)->GetListOfBranches());
7319 while ((br= (TBranch*)next())) {
7320 TString st = br->GetName();
7321 st.ReplaceAll("/","_");
7322 if (st.Index(re) == kNPOS) continue;
7323 br->Print(option);
7324 }
7325 }
7326
7327 //print TRefTable (if one)
7328 if (fBranchRef) fBranchRef->Print(option);
7329
7330 //print friends if option "all"
7331 if (!fFriends || !strstr(option,"all")) return;
7332 TIter nextf(fFriends);
7333 TFriendLock lock(const_cast<TTree*>(this),kPrint);
7334 TFriendElement *fr;
7335 while ((fr = (TFriendElement*)nextf())) {
7336 TTree * t = fr->GetTree();
7337 if (t) t->Print(option);
7338 }
7339}
7340
7341////////////////////////////////////////////////////////////////////////////////
7342/// Print statistics about the TreeCache for this tree.
7343/// Like:
7344/// ~~~ {.cpp}
7345/// ******TreeCache statistics for file: cms2.root ******
7346/// Reading 73921562 bytes in 716 transactions
7347/// Average transaction = 103.242405 Kbytes
7348/// Number of blocks in current cache: 202, total size : 6001193
7349/// ~~~
7350/// if option = "a" the list of blocks in the cache is printed
7352void TTree::PrintCacheStats(Option_t* option) const
7353{
7354 TFile *f = GetCurrentFile();
7355 if (!f) return;
7356 TTreeCache *tc = GetReadCache(f);
7357 if (tc) tc->Print(option);
7358}
7359
7360////////////////////////////////////////////////////////////////////////////////
7361/// Process this tree executing the TSelector code in the specified filename.
7362/// The return value is -1 in case of error and TSelector::GetStatus() in
7363/// in case of success.
7364///
7365/// The code in filename is loaded (interpreted or compiled, see below),
7366/// filename must contain a valid class implementation derived from TSelector,
7367/// where TSelector has the following member functions:
7368///
7369/// - `Begin()`: called every time a loop on the tree starts,
7370/// a convenient place to create your histograms.
7371/// - `SlaveBegin()`: called after Begin(), when on PROOF called only on the
7372/// slave servers.
7373/// - `Process()`: called for each event, in this function you decide what
7374/// to read and fill your histograms.
7375/// - `SlaveTerminate`: called at the end of the loop on the tree, when on PROOF
7376/// called only on the slave servers.
7377/// - `Terminate()`: called at the end of the loop on the tree,
7378/// a convenient place to draw/fit your histograms.
7379///
7380/// If filename is of the form file.C, the file will be interpreted.
7381///
7382/// If filename is of the form file.C++, the file file.C will be compiled
7383/// and dynamically loaded.
7384///
7385/// If filename is of the form file.C+, the file file.C will be compiled
7386/// and dynamically loaded. At next call, if file.C is older than file.o
7387/// and file.so, the file.C is not compiled, only file.so is loaded.
7388///
7389/// ## NOTE1
7390///
7391/// It may be more interesting to invoke directly the other Process function
7392/// accepting a TSelector* as argument.eg
7393/// ~~~ {.cpp}
7394/// MySelector *selector = (MySelector*)TSelector::GetSelector(filename);
7395/// selector->CallSomeFunction(..);
7396/// mytree.Process(selector,..);
7397/// ~~~
7398/// ## NOTE2
7399//
7400/// One should not call this function twice with the same selector file
7401/// in the same script. If this is required, proceed as indicated in NOTE1,
7402/// by getting a pointer to the corresponding TSelector,eg
7403///
7404/// ### Workaround 1
7405///
7406/// ~~~ {.cpp}
7407/// void stubs1() {
7408/// TSelector *selector = TSelector::GetSelector("h1test.C");
7409/// TFile *f1 = new TFile("stubs_nood_le1.root");
7410/// TTree *h1 = (TTree*)f1->Get("h1");
7411/// h1->Process(selector);
7412/// TFile *f2 = new TFile("stubs_nood_le1_coarse.root");
7413/// TTree *h2 = (TTree*)f2->Get("h1");
7414/// h2->Process(selector);
7415/// }
7416/// ~~~
7417/// or use ACLIC to compile the selector
7418///
7419/// ### Workaround 2
7420///
7421/// ~~~ {.cpp}
7422/// void stubs2() {
7423/// TFile *f1 = new TFile("stubs_nood_le1.root");
7424/// TTree *h1 = (TTree*)f1->Get("h1");
7425/// h1->Process("h1test.C+");
7426/// TFile *f2 = new TFile("stubs_nood_le1_coarse.root");
7427/// TTree *h2 = (TTree*)f2->Get("h1");
7428/// h2->Process("h1test.C+");
7429/// }
7430/// ~~~
7432Long64_t TTree::Process(const char* filename, Option_t* option, Long64_t nentries, Long64_t firstentry)
7433{
7434 GetPlayer();
7435 if (fPlayer) {
7436 return fPlayer->Process(filename, option, nentries, firstentry);
7437 }
7438 return -1;
7439}
7440
7441////////////////////////////////////////////////////////////////////////////////
7442/// Process this tree executing the code in the specified selector.
7443/// The return value is -1 in case of error and TSelector::GetStatus() in
7444/// in case of success.
7445///
7446/// The TSelector class has the following member functions:
7447///
7448/// - `Begin()`: called every time a loop on the tree starts,
7449/// a convenient place to create your histograms.
7450/// - `SlaveBegin()`: called after Begin(), when on PROOF called only on the
7451/// slave servers.
7452/// - `Process()`: called for each event, in this function you decide what
7453/// to read and fill your histograms.
7454/// - `SlaveTerminate`: called at the end of the loop on the tree, when on PROOF
7455/// called only on the slave servers.
7456/// - `Terminate()`: called at the end of the loop on the tree,
7457/// a convenient place to draw/fit your histograms.
7458///
7459/// If the Tree (Chain) has an associated EventList, the loop is on the nentries
7460/// of the EventList, starting at firstentry, otherwise the loop is on the
7461/// specified Tree entries.
7463Long64_t TTree::Process(TSelector* selector, Option_t* option, Long64_t nentries, Long64_t firstentry)
7464{
7465 GetPlayer();
7466 if (fPlayer) {
7467 return fPlayer->Process(selector, option, nentries, firstentry);
7468 }
7469 return -1;
7470}
7471
7472////////////////////////////////////////////////////////////////////////////////
7473/// Make a projection of a tree using selections.
7474///
7475/// Depending on the value of varexp (described in Draw) a 1-D, 2-D, etc.,
7476/// projection of the tree will be filled in histogram hname.
7477/// Note that the dimension of hname must match with the dimension of varexp.
7478///
7480Long64_t TTree::Project(const char* hname, const char* varexp, const char* selection, Option_t* option, Long64_t nentries, Long64_t firstentry)
7481{
7482 TString var;
7483 var.Form("%s>>%s", varexp, hname);
7484 TString opt("goff");
7485 if (option) {
7486 opt.Form("%sgoff", option);
7487 }
7488 Long64_t nsel = Draw(var, selection, opt, nentries, firstentry);
7489 return nsel;
7490}
7491
7492////////////////////////////////////////////////////////////////////////////////
7493/// Loop over entries and return a TSQLResult object containing entries following selection.
7495TSQLResult* TTree::Query(const char* varexp, const char* selection, Option_t* option, Long64_t nentries, Long64_t firstentry)
7496{
7497 GetPlayer();
7498 if (fPlayer) {
7499 return fPlayer->Query(varexp, selection, option, nentries, firstentry);
7500 }
7501 return 0;
7502}
7503
7504////////////////////////////////////////////////////////////////////////////////
7505/// Create or simply read branches from filename.
7506///
7507/// if branchDescriptor = "" (default), it is assumed that the Tree descriptor
7508/// is given in the first line of the file with a syntax like
7509/// ~~~ {.cpp}
7510/// A/D:Table[2]/F:Ntracks/I:astring/C
7511/// ~~~
7512/// otherwise branchDescriptor must be specified with the above syntax.
7513///
7514/// - If the type of the first variable is not specified, it is assumed to be "/F"
7515/// - If the type of any other variable is not specified, the type of the previous
7516/// variable is assumed. eg
7517/// - `x:y:z` (all variables are assumed of type "F"
7518/// - `x/D:y:z` (all variables are of type "D"
7519/// - `x:y/D:z` (x is type "F", y and z of type "D"
7520///
7521/// delimiter allows for the use of another delimiter besides whitespace.
7522/// This provides support for direct import of common data file formats
7523/// like csv. If delimiter != ' ' and branchDescriptor == "", then the
7524/// branch description is taken from the first line in the file, but
7525/// delimiter is used for the branch names tokenization rather than ':'.
7526/// Note however that if the values in the first line do not use the
7527/// /[type] syntax, all variables are assumed to be of type "F".
7528/// If the filename ends with extensions .csv or .CSV and a delimiter is
7529/// not specified (besides ' '), the delimiter is automatically set to ','.
7530///
7531/// Lines in the input file starting with "#" are ignored. Leading whitespace
7532/// for each column data is skipped. Empty lines are skipped.
7533///
7534/// A TBranch object is created for each variable in the expression.
7535/// The total number of rows read from the file is returned.
7536///
7537/// ## FILLING a TTree WITH MULTIPLE INPUT TEXT FILES
7538///
7539/// To fill a TTree with multiple input text files, proceed as indicated above
7540/// for the first input file and omit the second argument for subsequent calls
7541/// ~~~ {.cpp}
7542/// T.ReadFile("file1.dat","branch descriptor");
7543/// T.ReadFile("file2.dat");
7544/// ~~~
7546Long64_t TTree::ReadFile(const char* filename, const char* branchDescriptor, char delimiter)
7547{
7548 std::ifstream in;
7549 in.open(filename);
7550 if (!in.good()) {
7551 Error("ReadFile","Cannot open file: %s",filename);
7552 return 0;
7553 }
7554 const char* ext = strrchr(filename, '.');
7555 if(ext != NULL && ((strcmp(ext, ".csv") == 0) || (strcmp(ext, ".CSV") == 0)) && delimiter == ' ') {
7556 delimiter = ',';
7557 }
7558 return ReadStream(in, branchDescriptor, delimiter);
7559}
7560
7561////////////////////////////////////////////////////////////////////////////////
7562/// Determine which newline this file is using.
7563/// Return '\\r' for Windows '\\r\\n' as that already terminates.
7565char TTree::GetNewlineValue(std::istream &inputStream)
7566{
7567 Long_t inPos = inputStream.tellg();
7568 char newline = '\n';
7569 while(1) {
7570 char c = 0;
7571 inputStream.get(c);
7572 if(!inputStream.good()) {
7573 Error("ReadStream","Error reading stream: no newline found.");
7574 return 0;
7575 }
7576 if(c == newline) break;
7577 if(c == '\r') {
7578 newline = '\r';
7579 break;
7580 }
7581 }
7582 inputStream.clear();
7583 inputStream.seekg(inPos);
7584 return newline;
7585}
7586
7587////////////////////////////////////////////////////////////////////////////////
7588/// Create or simply read branches from an input stream.
7589///
7590/// See reference information for TTree::ReadFile
7592Long64_t TTree::ReadStream(std::istream& inputStream, const char *branchDescriptor, char delimiter)
7593{
7594 char newline = 0;
7595 std::stringstream ss;
7596 std::istream *inTemp;
7597 Long_t inPos = inputStream.tellg();
7598 if (!inputStream.good()) {
7599 Error("ReadStream","Error reading stream");
7600 return 0;
7601 }
7602 if (inPos == -1) {
7603 ss << std::cin.rdbuf();
7604 newline = GetNewlineValue(ss);
7605 inTemp = &ss;
7606 } else {
7607 newline = GetNewlineValue(inputStream);
7608 inTemp = &inputStream;
7609 }
7610 std::istream& in = *inTemp;
7611 Long64_t nlines = 0;
7612
7613 TBranch *branch = 0;
7614 Int_t nbranches = fBranches.GetEntries();
7615 if (nbranches == 0) {
7616 char *bdname = new char[4000];
7617 char *bd = new char[100000];
7618 Int_t nch = 0;
7619 if (branchDescriptor) nch = strlen(branchDescriptor);
7620 // branch Descriptor is null, read its definition from the first line in the file
7621 if (!nch) {
7622 do {
7623 in.getline(bd, 100000, newline);
7624 if (!in.good()) {
7625 delete [] bdname;
7626 delete [] bd;
7627 Error("ReadStream","Error reading stream");
7628 return 0;
7629 }
7630 char *cursor = bd;
7631 while( isspace(*cursor) && *cursor != '\n' && *cursor != '\0') {
7632 ++cursor;
7633 }
7634 if (*cursor != '#' && *cursor != '\n' && *cursor != '\0') {
7635 break;
7636 }
7637 } while (true);
7638 ++nlines;
7639 nch = strlen(bd);
7640 } else {
7641 strlcpy(bd,branchDescriptor,100000);
7642 }
7643
7644 //parse the branch descriptor and create a branch for each element
7645 //separated by ":"
7646 void *address = &bd[90000];
7647 char *bdcur = bd;
7648 TString desc="", olddesc="F";
7649 char bdelim = ':';
7650 if(delimiter != ' ') {
7651 bdelim = delimiter;
7652 if (strchr(bdcur,bdelim)==0 && strchr(bdcur,':') != 0) {
7653 // revert to the default
7654 bdelim = ':';
7655 }
7656 }
7657 while (bdcur) {
7658 char *colon = strchr(bdcur,bdelim);
7659 if (colon) *colon = 0;
7660 strlcpy(bdname,bdcur,4000);
7661 char *slash = strchr(bdname,'/');
7662 if (slash) {
7663 *slash = 0;
7664 desc = bdcur;
7665 olddesc = slash+1;
7666 } else {
7667 desc.Form("%s/%s",bdname,olddesc.Data());
7668 }
7669 char *bracket = strchr(bdname,'[');
7670 if (bracket) {
7671 *bracket = 0;
7672 }
7673 branch = new TBranch(this,bdname,address,desc.Data(),32000);
7674 if (branch->IsZombie()) {
7675 delete branch;
7676 Warning("ReadStream","Illegal branch definition: %s",bdcur);
7677 } else {
7678 fBranches.Add(branch);
7679 branch->SetAddress(0);
7680 }
7681 if (!colon)break;
7682 bdcur = colon+1;
7683 }
7684 delete [] bdname;
7685 delete [] bd;
7686 }
7687
7688 nbranches = fBranches.GetEntries();
7689
7690 if (gDebug > 1) {
7691 Info("ReadStream", "Will use branches:");
7692 for (int i = 0 ; i < nbranches; ++i) {
7693 TBranch* br = (TBranch*) fBranches.At(i);
7694 Info("ReadStream", " %s: %s [%s]", br->GetName(),
7695 br->GetTitle(), br->GetListOfLeaves()->At(0)->IsA()->GetName());
7696 }
7697 if (gDebug > 3) {
7698 Info("ReadStream", "Dumping read tokens, format:");
7699 Info("ReadStream", "LLLLL:BBB:gfbe:GFBE:T");
7700 Info("ReadStream", " L: line number");
7701 Info("ReadStream", " B: branch number");
7702 Info("ReadStream", " gfbe: good / fail / bad / eof of token");
7703 Info("ReadStream", " GFBE: good / fail / bad / eof of file");
7704 Info("ReadStream", " T: Token being read");
7705 }
7706 }
7707
7708 //loop on all lines in the file
7709 Long64_t nGoodLines = 0;
7710 std::string line;
7711 const char sDelimBuf[2] = { delimiter, 0 };
7712 const char* sDelim = sDelimBuf;
7713 if (delimiter == ' ') {
7714 // ' ' really means whitespace
7715 sDelim = "[ \t]";
7716 }
7717 while(in.good()) {
7718 if (newline == '\r' && in.peek() == '\n') {
7719 // Windows, skip '\n':
7720 in.get();
7721 }
7722 std::getline(in, line, newline);
7723 ++nlines;
7724
7725 TString sLine(line);
7726 sLine = sLine.Strip(TString::kLeading); // skip leading whitespace
7727 if (sLine.IsNull()) {
7728 if (gDebug > 2) {
7729 Info("ReadStream", "Skipping empty line number %lld", nlines);
7730 }
7731 continue; // silently skip empty lines
7732 }
7733 if (sLine[0] == '#') {
7734 if (gDebug > 2) {
7735 Info("ReadStream", "Skipping comment line number %lld: '%s'",
7736 nlines, line.c_str());
7737 }
7738 continue;
7739 }
7740 if (gDebug > 2) {
7741 Info("ReadStream", "Parsing line number %lld: '%s'",
7742 nlines, line.c_str());
7743 }
7744
7745 // Loop on branches and read the branch values into their buffer
7746 branch = 0;
7747 TString tok; // one column's data
7748 TString leafData; // leaf data, possibly multiple tokens for e.g. /I[2]
7749 std::stringstream sToken; // string stream feeding leafData into leaves
7750 Ssiz_t pos = 0;
7751 Int_t iBranch = 0;
7752 Bool_t goodLine = kTRUE; // whether the row can be filled into the tree
7753 Int_t remainingLeafLen = 0; // remaining columns for the current leaf
7754 while (goodLine && iBranch < nbranches
7755 && sLine.Tokenize(tok, pos, sDelim)) {
7756 tok = tok.Strip(TString::kLeading); // skip leading whitespace
7757 if (tok.IsNull() && delimiter == ' ') {
7758 // 1 2 should not be interpreted as 1,,,2 but 1, 2.
7759 // Thus continue until we have a non-empty token.
7760 continue;
7761 }
7762
7763 if (!remainingLeafLen) {
7764 // next branch!
7765 branch = (TBranch*)fBranches.At(iBranch);
7766 }
7767 TLeaf *leaf = (TLeaf*)branch->GetListOfLeaves()->At(0);
7768 if (!remainingLeafLen) {
7769 remainingLeafLen = leaf->GetLen();
7770 if (leaf->GetMaximum() > 0) {
7771 // This is a dynamic leaf length, i.e. most likely a TLeafC's
7772 // string size. This still translates into one token:
7773 remainingLeafLen = 1;
7774 }
7775
7776 leafData = tok;
7777 } else {
7778 // append token to laf data:
7779 leafData += " ";
7780 leafData += tok;
7781 }
7782 --remainingLeafLen;
7783 if (remainingLeafLen) {
7784 // need more columns for this branch:
7785 continue;
7786 }
7787 ++iBranch;
7788
7789 // initialize stringstream with token
7790 sToken.clear();
7791 sToken.seekp(0, std::ios_base::beg);
7792 sToken.str(leafData.Data());
7793 sToken.seekg(0, std::ios_base::beg);
7794 leaf->ReadValue(sToken, 0 /* 0 = "all" */);
7795 if (gDebug > 3) {
7796 Info("ReadStream", "%5lld:%3d:%d%d%d%d:%d%d%d%d:%s",
7797 nlines, iBranch,
7798 (int)sToken.good(), (int)sToken.fail(),
7799 (int)sToken.bad(), (int)sToken.eof(),
7800 (int)in.good(), (int)in.fail(),
7801 (int)in.bad(), (int)in.eof(),
7802 sToken.str().c_str());
7803 }
7804
7805 // Error handling
7806 if (sToken.bad()) {
7807 // How could that happen for a stringstream?
7808 Warning("ReadStream",
7809 "Buffer error while reading data for branch %s on line %lld",
7810 branch->GetName(), nlines);
7811 } else if (!sToken.eof()) {
7812 if (sToken.fail()) {
7813 Warning("ReadStream",
7814 "Couldn't read formatted data in \"%s\" for branch %s on line %lld; ignoring line",
7815 tok.Data(), branch->GetName(), nlines);
7816 goodLine = kFALSE;
7817 } else {
7818 std::string remainder;
7819 std::getline(sToken, remainder, newline);
7820 if (!remainder.empty()) {
7821 Warning("ReadStream",
7822 "Ignoring trailing \"%s\" while reading data for branch %s on line %lld",
7823 remainder.c_str(), branch->GetName(), nlines);
7824 }
7825 }
7826 }
7827 } // tokenizer loop
7828
7829 if (iBranch < nbranches) {
7830 Warning("ReadStream",
7831 "Read too few columns (%d < %d) in line %lld; ignoring line",
7832 iBranch, nbranches, nlines);
7833 goodLine = kFALSE;
7834 } else if (pos != kNPOS) {
7835 sLine = sLine.Strip(TString::kTrailing);
7836 if (pos < sLine.Length()) {
7837 Warning("ReadStream",
7838 "Ignoring trailing \"%s\" while reading line %lld",
7839 sLine.Data() + pos - 1 /* also print delimiter */,
7840 nlines);
7841 }
7842 }
7843
7844 //we are now ready to fill the tree
7845 if (goodLine) {
7846 Fill();
7847 ++nGoodLines;
7848 }
7849 }
7850
7851 return nGoodLines;
7852}
7853
7854////////////////////////////////////////////////////////////////////////////////
7855/// Make sure that obj (which is being deleted or will soon be) is no
7856/// longer referenced by this TTree.
7859{
7860 if (obj == fEventList) {
7861 fEventList = 0;
7862 }
7863 if (obj == fEntryList) {
7864 fEntryList = 0;
7865 }
7866 if (fUserInfo) {
7868 }
7869 if (fPlayer == obj) {
7870 fPlayer = 0;
7871 }
7872 if (fTreeIndex == obj) {
7873 fTreeIndex = 0;
7874 }
7875 if (fAliases) {
7877 }
7878 if (fFriends) {
7880 }
7881}
7882
7883////////////////////////////////////////////////////////////////////////////////
7884/// Refresh contents of this tree and its branches from the current status on disk.
7885///
7886/// One can call this function in case the tree file is being
7887/// updated by another process.
7889void TTree::Refresh()
7890{
7891 if (!fDirectory->GetFile()) {
7892 return;
7893 }
7895 fDirectory->Remove(this);
7897 if (!tree) {
7898 return;
7899 }
7900 //copy info from tree header into this Tree
7901 fEntries = 0;
7902 fNClusterRange = 0;
7904
7905 fAutoSave = tree->fAutoSave;
7906 fEntries = tree->fEntries;
7907 fTotBytes = tree->GetTotBytes();
7908 fZipBytes = tree->GetZipBytes();
7909 fSavedBytes = tree->fSavedBytes;
7910 fTotalBuffers = tree->fTotalBuffers.load();
7911
7912 //loop on all branches and update them
7913 Int_t nleaves = fLeaves.GetEntriesFast();
7914 for (Int_t i = 0; i < nleaves; i++) {
7915 TLeaf* leaf = (TLeaf*) fLeaves.UncheckedAt(i);
7916 TBranch* branch = (TBranch*) leaf->GetBranch();
7917 branch->Refresh(tree->GetBranch(branch->GetName()));
7918 }
7920 fDirectory->Append(this);
7921 delete tree;
7922 tree = 0;
7923}
7924
7925////////////////////////////////////////////////////////////////////////////////
7926/// Record a TFriendElement that we need to warn when the chain switches to
7927/// a new file (typically this is because this chain is a friend of another
7928/// TChain)
7931{
7932 if (!fExternalFriends)
7933 fExternalFriends = new TList();
7934 fExternalFriends->Add(fe);
7935}
7936
7937
7938////////////////////////////////////////////////////////////////////////////////
7939/// Removes external friend
7942{
7944}
7945
7946
7947////////////////////////////////////////////////////////////////////////////////
7948/// Remove a friend from the list of friends.
7950void TTree::RemoveFriend(TTree* oldFriend)
7951{
7952 // We already have been visited while recursively looking
7953 // through the friends tree, let return
7955 return;
7956 }
7957 if (!fFriends) {
7958 return;
7959 }
7960 TFriendLock lock(this, kRemoveFriend);
7961 TIter nextf(fFriends);
7962 TFriendElement* fe = 0;
7963 while ((fe = (TFriendElement*) nextf())) {
7964 TTree* friend_t = fe->GetTree();
7965 if (friend_t == oldFriend) {
7966 fFriends->Remove(fe);
7967 delete fe;
7968 fe = 0;
7969 }
7970 }
7971}
7972
7973////////////////////////////////////////////////////////////////////////////////
7974/// Reset baskets, buffers and entries count in all branches and leaves.
7976void TTree::Reset(Option_t* option)
7977{
7978 fNotify = 0;
7979 fEntries = 0;
7980 fNClusterRange = 0;
7981 fTotBytes = 0;
7982 fZipBytes = 0;
7983 fFlushedBytes = 0;
7984 fSavedBytes = 0;
7985 fTotalBuffers = 0;
7986 fChainOffset = 0;
7987 fReadEntry = -1;
7988
7989 delete fTreeIndex;
7990 fTreeIndex = 0;
7991
7993 for (Int_t i = 0; i < nb; ++i) {
7994 TBranch* branch = (TBranch*) fBranches.UncheckedAt(i);
7995 branch->Reset(option);
7996 }
7997
7998 if (fBranchRef) {
7999 fBranchRef->Reset();
8000 }
8001}
8002
8003////////////////////////////////////////////////////////////////////////////////
8004/// Resets the state of this TTree after a merge (keep the customization but
8005/// forget the data).
8008{
8009 fEntries = 0;
8010 fNClusterRange = 0;
8011 fTotBytes = 0;
8012 fZipBytes = 0;
8013 fSavedBytes = 0;
8014 fFlushedBytes = 0;
8015 fTotalBuffers = 0;
8016 fChainOffset = 0;
8017 fReadEntry = -1;
8018
8019 delete fTreeIndex;
8020 fTreeIndex = 0;
8021
8023 for (Int_t i = 0; i < nb; ++i) {
8024 TBranch* branch = (TBranch*) fBranches.UncheckedAt(i);
8025 branch->ResetAfterMerge(info);
8026 }
8027
8028 if (fBranchRef) {
8030 }
8031}
8032
8033////////////////////////////////////////////////////////////////////////////////
8034/// Tell all of our branches to set their addresses to zero.
8035///
8036/// Note: If any of our branches own any objects, they are deleted.
8039{
8040 if (br && br->GetTree()) {
8041 br->ResetAddress();
8042 }
8043}
8044
8045////////////////////////////////////////////////////////////////////////////////
8046/// Tell all of our branches to drop their current objects and allocate new ones.
8049{
8050 TObjArray* branches = GetListOfBranches();
8051 Int_t nbranches = branches->GetEntriesFast();
8052 for (Int_t i = 0; i < nbranches; ++i) {
8053 TBranch* branch = (TBranch*) branches->UncheckedAt(i);
8054 branch->ResetAddress();
8055 }
8056}
8057
8058////////////////////////////////////////////////////////////////////////////////
8059/// Loop over tree entries and print entries passing selection.
8060///
8061/// - If varexp is 0 (or "") then print only first 8 columns.
8062/// - If varexp = "*" print all columns.
8063///
8064/// Otherwise a columns selection can be made using "var1:var2:var3".
8065/// See TTreePlayer::Scan for more information
8067Long64_t TTree::Scan(const char* varexp, const char* selection, Option_t* option, Long64_t nentries, Long64_t firstentry)
8068{
8069 GetPlayer();
8070 if (fPlayer) {
8071 return fPlayer->Scan(varexp, selection, option, nentries, firstentry);
8072 }
8073 return -1;
8074}
8075
8076////////////////////////////////////////////////////////////////////////////////
8077/// Set a tree variable alias.
8078///
8079/// Set an alias for an expression/formula based on the tree 'variables'.
8080///
8081/// The content of 'aliasName' can be used in TTreeFormula (i.e. TTree::Draw,
8082/// TTree::Scan, TTreeViewer) and will be evaluated as the content of
8083/// 'aliasFormula'.
8084///
8085/// If the content of 'aliasFormula' only contains symbol names, periods and
8086/// array index specification (for example event.fTracks[3]), then
8087/// the content of 'aliasName' can be used as the start of symbol.
8088///
8089/// If the alias 'aliasName' already existed, it is replaced by the new
8090/// value.
8091///
8092/// When being used, the alias can be preceded by an eventual 'Friend Alias'
8093/// (see TTree::GetFriendAlias)
8094///
8095/// Return true if it was added properly.
8096///
8097/// For example:
8098/// ~~~ {.cpp}
8099/// tree->SetAlias("x1","(tdc1[1]-tdc1[0])/49");
8100/// tree->SetAlias("y1","(tdc1[3]-tdc1[2])/47");
8101/// tree->SetAlias("x2","(tdc2[1]-tdc2[0])/49");
8102/// tree->SetAlias("y2","(tdc2[3]-tdc2[2])/47");
8103/// tree->Draw("y2-y1:x2-x1");
8104///
8105/// tree->SetAlias("theGoodTrack","event.fTracks[3]");
8106/// tree->Draw("theGoodTrack.fPx"); // same as "event.fTracks[3].fPx"
8107/// ~~~
8109Bool_t TTree::SetAlias(const char* aliasName, const char* aliasFormula)
8110{
8111 if (!aliasName || !aliasFormula) {
8112 return kFALSE;
8113 }
8114 if (!aliasName[0] || !aliasFormula[0]) {
8115 return kFALSE;
8116 }
8117 if (!fAliases) {
8118 fAliases = new TList;
8119 } else {
8120 TNamed* oldHolder = (TNamed*) fAliases->FindObject(aliasName);
8121 if (oldHolder) {
8122 oldHolder->SetTitle(aliasFormula);
8123 return kTRUE;
8124 }
8125 }
8126 TNamed* holder = new TNamed(aliasName, aliasFormula);
8127 fAliases->Add(holder);
8128 return kTRUE;
8129}
8130
8131////////////////////////////////////////////////////////////////////////////////
8132/// This function may be called at the start of a program to change
8133/// the default value for fAutoFlush.
8134///
8135/// ### CASE 1 : autof > 0
8136///
8137/// autof is the number of consecutive entries after which TTree::Fill will
8138/// flush all branch buffers to disk.
8139///
8140/// ### CASE 2 : autof < 0
8141///
8142/// When filling the Tree the branch buffers will be flushed to disk when
8143/// more than autof bytes have been written to the file. At the first FlushBaskets
8144/// TTree::Fill will replace fAutoFlush by the current value of fEntries.
8145///
8146/// Calling this function with autof<0 is interesting when it is hard to estimate
8147/// the size of one entry. This value is also independent of the Tree.
8148///
8149/// The Tree is initialized with fAutoFlush=-30000000, ie that, by default,
8150/// the first AutoFlush will be done when 30 MBytes of data are written to the file.
8151///
8152/// ### CASE 3 : autof = 0
8153///
8154/// The AutoFlush mechanism is disabled.
8155///
8156/// Flushing the buffers at regular intervals optimize the location of
8157/// consecutive entries on the disk by creating clusters of baskets.
8158///
8159/// A cluster of baskets is a set of baskets that contains all
8160/// the data for a (consecutive) set of entries and that is stored
8161/// consecutively on the disk. When reading all the branches, this
8162/// is the minimum set of baskets that the TTreeCache will read.
8164void TTree::SetAutoFlush(Long64_t autof /* = -30000000 */ )
8165{
8166 // Implementation note:
8167 //
8168 // A positive value of autoflush determines the size (in number of entries) of
8169 // a cluster of baskets.
8170 //
8171 // If the value of autoflush is changed over time (this happens in
8172 // particular when the TTree results from fast merging many trees),
8173 // we record the values of fAutoFlush in the data members:
8174 // fClusterRangeEnd and fClusterSize.
8175 // In the code we refer to a range of entries where the size of the
8176 // cluster of baskets is the same (i.e the value of AutoFlush was
8177 // constant) is called a ClusterRange.
8178 //
8179 // The 2 arrays (fClusterRangeEnd and fClusterSize) have fNClusterRange
8180 // active (used) values and have fMaxClusterRange allocated entries.
8181 //
8182 // fClusterRangeEnd contains the last entries number of a cluster range.
8183 // In particular this means that the 'next' cluster starts at fClusterRangeEnd[]+1
8184 // fClusterSize contains the size in number of entries of all the cluster
8185 // within the given range.
8186 // The last range (and the only one if fNClusterRange is zero) start at
8187 // fNClusterRange[fNClusterRange-1]+1 and ends at the end of the TTree. The
8188 // size of the cluster in this range is given by the value of fAutoFlush.
8189 //
8190 // For example printing the beginning and end of each the ranges can be done by:
8191 //
8192 // Printf("%-16s %-16s %-16s %5s",
8193 // "Cluster Range #", "Entry Start", "Last Entry", "Size");
8194 // Int_t index= 0;
8195 // Long64_t clusterRangeStart = 0;
8196 // if (fNClusterRange) {
8197 // for( ; index < fNClusterRange; ++index) {
8198 // Printf("%-16d %-16lld %-16lld %5lld",
8199 // index, clusterRangeStart, fClusterRangeEnd[index], fClusterSize[index]);
8200 // clusterRangeStart = fClusterRangeEnd[index] + 1;
8201 // }
8202 // }
8203 // Printf("%-16d %-16lld %-16lld %5lld",
8204 // index, prevEntry, fEntries - 1, fAutoFlush);
8205 //
8206
8207 // Note: We store the entry number corresponding to the end of the cluster
8208 // rather than its start in order to avoid using the array if the cluster
8209 // size never varies (If there is only one value of AutoFlush for the whole TTree).
8210
8211 if( fAutoFlush != autof) {
8212 if ((fAutoFlush > 0 || autof > 0) && fFlushedBytes) {
8213 // The mechanism was already enabled, let's record the previous
8214 // cluster if needed.
8216 }
8217 fAutoFlush = autof;
8218 }
8219}
8220
8221////////////////////////////////////////////////////////////////////////////////
8222/// Mark the previous event as being at the end of the event cluster.
8223///
8224/// So, if fEntries is set to 10 (and this is the first cluster) when MarkEventCluster
8225/// is called, then the first cluster has 9 events.
8227{
8228 if (!fEntries) return;
8229
8230 if ( (fNClusterRange+1) > fMaxClusterRange ) {
8231 if (fMaxClusterRange) {
8232 // Resize arrays to hold a larger event cluster.
8233 Int_t newsize = TMath::Max(10,Int_t(2*fMaxClusterRange));
8235 newsize*sizeof(Long64_t),fMaxClusterRange*sizeof(Long64_t));
8237 newsize*sizeof(Long64_t),fMaxClusterRange*sizeof(Long64_t));
8238 fMaxClusterRange = newsize;
8239 } else {
8240 // Cluster ranges have never been initialized; create them now.
8241 fMaxClusterRange = 2;
8244 }
8245 }
8247 // If we are auto-flushing, then the cluster size is the same as the current auto-flush setting.
8248 if (fAutoFlush > 0) {
8249 // Even if the user triggers MarkEventRange prior to fAutoFlush being present, the TClusterIterator
8250 // will appropriately go to the next event range.
8252 // Otherwise, assume there is one cluster per event range (e.g., user is manually controlling the flush).
8253 } else if (fNClusterRange == 0) {
8255 } else {
8257 }
8259}
8260
8261/// Estimate the median cluster size for the TTree.
8262/// This value provides e.g. a reasonable cache size default if other heuristics fail.
8263/// Clusters with size 0 and the very last cluster range, that might not have been committed to fClusterSize yet,
8264/// are ignored for the purposes of the calculation.
8266{
8267 std::vector<Long64_t> clusterSizesPerRange;
8268 clusterSizesPerRange.reserve(fNClusterRange);
8269
8270 // We ignore cluster sizes of 0 for the purposes of this function.
8271 // We also ignore the very last cluster range which might not have been committed to fClusterSize.
8272 std::copy_if(fClusterSize, fClusterSize + fNClusterRange, std::back_inserter(clusterSizesPerRange),
8273 [](Long64_t size) { return size != 0; });
8274
8275 std::vector<double> nClustersInRange; // we need to store doubles because of the signature of TMath::Median
8276 nClustersInRange.reserve(clusterSizesPerRange.size());
8277
8278 auto clusterRangeStart = 0ll;
8279 for (int i = 0; i < fNClusterRange; ++i) {
8280 const auto size = fClusterSize[i];
8281 R__ASSERT(size >= 0);
8282 if (fClusterSize[i] == 0)
8283 continue;
8284 const auto nClusters = (1 + fClusterRangeEnd[i] - clusterRangeStart) / fClusterSize[i];
8285 nClustersInRange.emplace_back(nClusters);
8286 clusterRangeStart = fClusterRangeEnd[i] + 1;
8287 }
8288
8289 R__ASSERT(nClustersInRange.size() == clusterSizesPerRange.size());
8290 const auto medianClusterSize =
8291 TMath::Median(nClustersInRange.size(), clusterSizesPerRange.data(), nClustersInRange.data());
8292 return medianClusterSize;
8293}
8294
8295////////////////////////////////////////////////////////////////////////////////
8296/// This function may be called at the start of a program to change
8297/// the default value for fAutoSave (and for SetAutoSave) is -300000000, ie 300 MBytes.
8298/// When filling the Tree the branch buffers as well as the Tree header
8299/// will be flushed to disk when the watermark is reached.
8300/// If fAutoSave is positive the watermark is reached when a multiple of fAutoSave
8301/// entries have been written.
8302/// If fAutoSave is negative the watermark is reached when -fAutoSave bytes
8303/// have been written to the file.
8304/// In case of a program crash, it will be possible to recover the data in the Tree
8305/// up to the last AutoSave point.
8307void TTree::SetAutoSave(Long64_t autos)
8308{
8309 fAutoSave = autos;
8310}
8311
8312////////////////////////////////////////////////////////////////////////////////
8313/// Set a branch's basket size.
8314///
8315/// bname is the name of a branch.
8316///
8317/// - if bname="*", apply to all branches.
8318/// - if bname="xxx*", apply to all branches with name starting with xxx
8319///
8320/// see TRegexp for wildcarding options
8321/// buffsize = branc basket size
8323void TTree::SetBasketSize(const char* bname, Int_t buffsize)
8324{
8325 Int_t nleaves = fLeaves.GetEntriesFast();
8326 TRegexp re(bname, kTRUE);
8327 Int_t nb = 0;
8328 for (Int_t i = 0; i < nleaves; i++) {
8329 TLeaf* leaf = (TLeaf*) fLeaves.UncheckedAt(i);
8330 TBranch* branch = (TBranch*) leaf->GetBranch();
8331 TString s = branch->GetName();
8332 if (strcmp(bname, branch->GetName()) && (s.Index(re) == kNPOS)) {
8333 continue;
8334 }
8335 nb++;
8336 branch->SetBasketSize(buffsize);
8337 }
8338 if (!nb) {
8339 Error("SetBasketSize", "unknown branch -> '%s'", bname);
8340 }
8341}
8342
8343////////////////////////////////////////////////////////////////////////////////
8344/// Change branch address, dealing with clone trees properly.
8345/// See TTree::CheckBranchAddressType for the semantic of the return value.
8346///
8347/// Note: See the comments in TBranchElement::SetAddress() for the
8348/// meaning of the addr parameter and the object ownership policy.
8350Int_t TTree::SetBranchAddress(const char* bname, void* addr, TBranch** ptr)
8351{
8352 TBranch* branch = GetBranch(bname);
8353 if (!branch) {
8354 if (ptr) *ptr = 0;
8355 Error("SetBranchAddress", "unknown branch -> %s", bname);
8356 return kMissingBranch;
8357 }
8358 return SetBranchAddressImp(branch,addr,ptr);
8359}
8360
8361////////////////////////////////////////////////////////////////////////////////
8362/// Verify the validity of the type of addr before calling SetBranchAddress.
8363/// See TTree::CheckBranchAddressType for the semantic of the return value.
8364///
8365/// Note: See the comments in TBranchElement::SetAddress() for the
8366/// meaning of the addr parameter and the object ownership policy.
8368Int_t TTree::SetBranchAddress(const char* bname, void* addr, TClass* ptrClass, EDataType datatype, Bool_t isptr)
8369{
8370 return SetBranchAddress(bname, addr, 0, ptrClass, datatype, isptr);
8371}
8372
8373////////////////////////////////////////////////////////////////////////////////
8374/// Verify the validity of the type of addr before calling SetBranchAddress.
8375/// See TTree::CheckBranchAddressType for the semantic of the return value.
8376///
8377/// Note: See the comments in TBranchElement::SetAddress() for the
8378/// meaning of the addr parameter and the object ownership policy.
8380Int_t TTree::SetBranchAddress(const char* bname, void* addr, TBranch** ptr, TClass* ptrClass, EDataType datatype, Bool_t isptr)
8381{
8382 TBranch* branch = GetBranch(bname);
8383 if (!branch) {
8384 if (ptr) *ptr = 0;
8385 Error("SetBranchAddress", "unknown branch -> %s", bname);
8386 return kMissingBranch;
8387 }
8388
8389 Int_t res = CheckBranchAddressType(branch, ptrClass, datatype, isptr);
8390
8391 // This will set the value of *ptr to branch.
8392 if (res >= 0) {
8393 // The check succeeded.
8394 if ((res & kNeedEnableDecomposedObj) && !branch->GetMakeClass())
8395 branch->SetMakeClass(kTRUE);
8396 SetBranchAddressImp(branch,addr,ptr);
8397 } else {
8398 if (ptr) *ptr = 0;
8399 }
8400 return res;
8401}
8402
8403////////////////////////////////////////////////////////////////////////////////
8404/// Change branch address, dealing with clone trees properly.
8405/// See TTree::CheckBranchAddressType for the semantic of the return value.
8406///
8407/// Note: See the comments in TBranchElement::SetAddress() for the
8408/// meaning of the addr parameter and the object ownership policy.
8410Int_t TTree::SetBranchAddressImp(TBranch *branch, void* addr, TBranch** ptr)
8411{
8412 if (ptr) {
8413 *ptr = branch;
8414 }
8415 if (fClones) {
8416 void* oldAddr = branch->GetAddress();
8417 TIter next(fClones);
8418 TTree* clone = 0;
8419 const char *bname = branch->GetName();
8420 while ((clone = (TTree*) next())) {
8421 TBranch* cloneBr = clone->GetBranch(bname);
8422 if (cloneBr && (cloneBr->GetAddress() == oldAddr)) {
8423 cloneBr->SetAddress(addr);
8424 }
8425 }
8426 }
8427 branch->SetAddress(addr);
8428 return kVoidPtr;
8429}
8430
8431////////////////////////////////////////////////////////////////////////////////
8432/// Set branch status to Process or DoNotProcess.
8433///
8434/// When reading a Tree, by default, all branches are read.
8435/// One can speed up considerably the analysis phase by activating
8436/// only the branches that hold variables involved in a query.
8437///
8438/// bname is the name of a branch.
8439///
8440/// - if bname="*", apply to all branches.
8441/// - if bname="xxx*", apply to all branches with name starting with xxx
8442///
8443/// see TRegexp for wildcarding options
8444///
8445/// - status = 1 branch will be processed
8446/// - = 0 branch will not be processed
8447///
8448/// Example:
8449///
8450/// Assume a tree T with sub-branches a,b,c,d,e,f,g,etc..
8451/// when doing T.GetEntry(i) all branches are read for entry i.
8452/// to read only the branches c and e, one can do
8453/// ~~~ {.cpp}
8454/// T.SetBranchStatus("*",0); //disable all branches
8455/// T.SetBranchStatus("c",1);
8456/// T.setBranchStatus("e",1);
8457/// T.GetEntry(i);
8458/// ~~~
8459/// bname is interpreted as a wild-carded TRegexp (see TRegexp::MakeWildcard).
8460/// Thus, "a*b" or "a.*b" matches branches starting with "a" and ending with
8461/// "b", but not any other branch with an "a" followed at some point by a
8462/// "b". For this second behavior, use "*a*b*". Note that TRegExp does not
8463/// support '|', and so you cannot select, e.g. track and shower branches
8464/// with "track|shower".
8465///
8466/// __WARNING! WARNING! WARNING!__
8467///
8468/// SetBranchStatus is matching the branch based on match of the branch
8469/// 'name' and not on the branch hierarchy! In order to be able to
8470/// selectively enable a top level object that is 'split' you need to make
8471/// sure the name of the top level branch is prefixed to the sub-branches'
8472/// name (by adding a dot ('.') at the end of the Branch creation and use the
8473/// corresponding bname.
8474///
8475/// I.e If your Tree has been created in split mode with a parent branch "parent."
8476/// (note the trailing dot).
8477/// ~~~ {.cpp}
8478/// T.SetBranchStatus("parent",1);
8479/// ~~~
8480/// will not activate the sub-branches of "parent". You should do:
8481/// ~~~ {.cpp}
8482/// T.SetBranchStatus("parent*",1);
8483/// ~~~
8484/// Without the trailing dot in the branch creation you have no choice but to
8485/// call SetBranchStatus explicitly for each of the sub branches.
8486///
8487/// An alternative to this function is to read directly and only
8488/// the interesting branches. Example:
8489/// ~~~ {.cpp}
8490/// TBranch *brc = T.GetBranch("c");
8491/// TBranch *bre = T.GetBranch("e");
8492/// brc->GetEntry(i);
8493/// bre->GetEntry(i);
8494/// ~~~
8495/// If found is not 0, the number of branch(es) found matching the regular
8496/// expression is returned in *found AND the error message 'unknown branch'
8497/// is suppressed.
8499void TTree::SetBranchStatus(const char* bname, Bool_t status, UInt_t* found)
8500{
8501 // We already have been visited while recursively looking
8502 // through the friends tree, let return
8504 return;
8505 }
8506
8507 if (0 == strcmp(bname, "")) {
8508 Error("SetBranchStatus", "Input regexp is an empty string: no match against branch names will be attempted.");
8509 return;
8510 }
8511
8512 TBranch *branch, *bcount, *bson;
8513 TLeaf *leaf, *leafcount;
8514
8515 Int_t i,j;
8516 Int_t nleaves = fLeaves.GetEntriesFast();
8517 TRegexp re(bname,kTRUE);
8518 Int_t nb = 0;
8519
8520 // first pass, loop on all branches
8521 // for leafcount branches activate/deactivate in function of status
8522 for (i=0;i<nleaves;i++) {
8523 leaf = (TLeaf*)fLeaves.UncheckedAt(i);
8524 branch = (TBranch*)leaf->GetBranch();
8525 TString s = branch->GetName();
8526 if (strcmp(bname,"*")) { //Regexp gives wrong result for [] in name
8527 TString longname;
8528 longname.Form("%s.%s",GetName(),branch->GetName());
8529 if (strcmp(bname,branch->GetName())
8530 && longname != bname
8531 && s.Index(re) == kNPOS) continue;
8532 }
8533 nb++;
8534 if (status) branch->ResetBit(kDoNotProcess);
8535 else branch->SetBit(kDoNotProcess);
8536 leafcount = leaf->GetLeafCount();
8537 if (leafcount) {
8538 bcount = leafcount->GetBranch();
8539 if (status) bcount->ResetBit(kDoNotProcess);
8540 else bcount->SetBit(kDoNotProcess);
8541 }
8542 }
8543 if (nb==0 && strchr(bname,'*')==0) {
8544 branch = GetBranch(bname);
8545 if (branch) {
8546 if (status) branch->ResetBit(kDoNotProcess);
8547 else branch->SetBit(kDoNotProcess);
8548 ++nb;
8549 }
8550 }
8551
8552 //search in list of friends
8553 UInt_t foundInFriend = 0;
8554 if (fFriends) {
8555 TFriendLock lock(this,kSetBranchStatus);
8556 TIter nextf(fFriends);
8557 TFriendElement *fe;
8558 TString name;
8559 while ((fe = (TFriendElement*)nextf())) {
8560 TTree *t = fe->GetTree();
8561 if (t==0) continue;
8562
8563 // If the alias is present replace it with the real name.
8564 char *subbranch = (char*)strstr(bname,fe->GetName());
8565 if (subbranch!=bname) subbranch = 0;
8566 if (subbranch) {
8567 subbranch += strlen(fe->GetName());
8568 if ( *subbranch != '.' ) subbranch = 0;
8569 else subbranch ++;
8570 }
8571 if (subbranch) {
8572 name.Form("%s.%s",t->GetName(),subbranch);
8573 } else {
8574 name = bname;
8575 }
8576 t->SetBranchStatus(name,status, &foundInFriend);
8577 }
8578 }
8579 if (!nb && !foundInFriend) {
8580 if (found==0) {
8581 if (status) {
8582 if (strchr(bname,'*') != 0)
8583 Error("SetBranchStatus", "No branch name is matching wildcard -> %s", bname);
8584 else
8585 Error("SetBranchStatus", "unknown branch -> %s", bname);
8586 } else {
8587 if (strchr(bname,'*') != 0)
8588 Warning("SetBranchStatus", "No branch name is matching wildcard -> %s", bname);
8589 else
8590 Warning("SetBranchStatus", "unknown branch -> %s", bname);
8591 }
8592 }
8593 return;
8594 }
8595 if (found) *found = nb + foundInFriend;
8596
8597 // second pass, loop again on all branches
8598 // activate leafcount branches for active branches only
8599 for (i = 0; i < nleaves; i++) {
8600 leaf = (TLeaf*)fLeaves.UncheckedAt(i);
8601 branch = (TBranch*)leaf->GetBranch();
8602 if (!branch->TestBit(kDoNotProcess)) {
8603 leafcount = leaf->GetLeafCount();
8604 if (leafcount) {
8605 bcount = leafcount->GetBranch();
8606 bcount->ResetBit(kDoNotProcess);
8607 }
8608 } else {
8609 //Int_t nbranches = branch->GetListOfBranches()->GetEntriesFast();
8610 Int_t nbranches = branch->GetListOfBranches()->GetEntries();
8611 for (j=0;j<nbranches;j++) {
8612 bson = (TBranch*)branch->GetListOfBranches()->UncheckedAt(j);
8613 if (!bson) continue;
8614 if (!bson->TestBit(kDoNotProcess)) {
8615 if (bson->GetNleaves() <= 0) continue;
8616 branch->ResetBit(kDoNotProcess);
8617 break;
8618 }
8619 }
8620 }
8621 }
8622}
8623
8624////////////////////////////////////////////////////////////////////////////////
8625/// Set the current branch style. (static function)
8626///
8627/// - style = 0 old Branch
8628/// - style = 1 new Bronch
8631{
8633}
8634
8635////////////////////////////////////////////////////////////////////////////////
8636/// Set maximum size of the file cache .
8637//
8638/// - if cachesize = 0 the existing cache (if any) is deleted.
8639/// - if cachesize = -1 (default) it is set to the AutoFlush value when writing
8640/// the Tree (default is 30 MBytes).
8641///
8642/// Returns:
8643/// - 0 size set, cache was created if possible
8644/// - -1 on error
8647{
8648 // remember that the user has requested an explicit cache setup
8650
8651 return SetCacheSizeAux(kFALSE, cacheSize);
8652}
8653
8654////////////////////////////////////////////////////////////////////////////////
8655/// Set the size of the file cache and create it if possible.
8656///
8657/// If autocache is true:
8658/// this may be an autocreated cache, possibly enlarging an existing
8659/// autocreated cache. The size is calculated. The value passed in cacheSize:
8660/// - cacheSize = 0 make cache if default cache creation is enabled
8661/// - cacheSize = -1 make a default sized cache in any case
8662///
8663/// If autocache is false:
8664/// this is a user requested cache. cacheSize is used to size the cache.
8665/// This cache should never be automatically adjusted.
8666///
8667/// Returns:
8668/// - 0 size set, or existing autosized cache almost large enough.
8669/// (cache was created if possible)
8670/// - -1 on error
8672Int_t TTree::SetCacheSizeAux(Bool_t autocache /* = kTRUE */, Long64_t cacheSize /* = 0 */ )
8673{
8674 if (autocache) {
8675 // used as a once only control for automatic cache setup
8677 }
8678
8679 if (!autocache) {
8680 // negative size means the user requests the default
8681 if (cacheSize < 0) {
8682 cacheSize = GetCacheAutoSize(kTRUE);
8683 }
8684 } else {
8685 if (cacheSize == 0) {
8686 cacheSize = GetCacheAutoSize();
8687 } else if (cacheSize < 0) {
8688 cacheSize = GetCacheAutoSize(kTRUE);
8689 }
8690 }
8691
8693 if (!file || GetTree() != this) {
8694 // if there's no file or we are not a plain tree (e.g. if we're a TChain)
8695 // do not create a cache, only record the size if one was given
8696 if (!autocache) {
8697 fCacheSize = cacheSize;
8698 }
8699 if (GetTree() != this) {
8700 return 0;
8701 }
8702 if (!autocache && cacheSize>0) {
8703 Warning("SetCacheSizeAux", "A TTreeCache could not be created because the TTree has no file");
8704 }
8705 return 0;
8706 }
8707
8708 // Check for an existing cache
8710 if (pf) {
8711 if (autocache) {
8712 // reset our cache status tracking in case existing cache was added
8713 // by the user without using one of the TTree methods
8714 fCacheSize = pf->GetBufferSize();
8716
8717 if (fCacheUserSet) {
8718 // existing cache was created by the user, don't change it
8719 return 0;
8720 }
8721 } else {
8722 // update the cache to ensure it records the user has explicitly
8723 // requested it
8725 }
8726
8727 // if we're using an automatically calculated size and the existing
8728 // cache is already almost large enough don't resize
8729 if (autocache && Long64_t(0.80*cacheSize) < fCacheSize) {
8730 // already large enough
8731 return 0;
8732 }
8733
8734 if (cacheSize == fCacheSize) {
8735 return 0;
8736 }
8737
8738 if (cacheSize == 0) {
8739 // delete existing cache
8740 pf->WaitFinishPrefetch();
8741 file->SetCacheRead(0,this);
8742 delete pf;
8743 pf = 0;
8744 } else {
8745 // resize
8746 Int_t res = pf->SetBufferSize(cacheSize);
8747 if (res < 0) {
8748 return -1;
8749 }
8750 }
8751 } else {
8752 // no existing cache
8753 if (autocache) {
8754 if (fCacheUserSet) {
8755 // value was already set manually.
8756 if (fCacheSize == 0) return 0;
8757 // Expected a cache should exist; perhaps the user moved it
8758 // Do nothing more here.
8759 if (cacheSize) {
8760 Error("SetCacheSizeAux", "Not setting up an automatically sized TTreeCache because of missing cache previously set");
8761 }
8762 return -1;
8763 }
8764 }
8765 }
8766
8767 fCacheSize = cacheSize;
8768 if (cacheSize == 0 || pf) {
8769 return 0;
8770 }
8771
8772#ifdef R__USE_IMT
8773 if(TTreeCacheUnzip::IsParallelUnzip() && file->GetCompressionLevel() > 0)
8774 pf = new TTreeCacheUnzip(this, cacheSize);
8775 else
8776#endif
8777 pf = new TTreeCache(this, cacheSize);
8778
8779 pf->SetAutoCreated(autocache);
8780
8781 return 0;
8782}
8783
8784////////////////////////////////////////////////////////////////////////////////
8785///interface to TTreeCache to set the cache entry range
8786///
8787/// Returns:
8788/// - 0 entry range set
8789/// - -1 on error
8792{
8793 if (!GetTree()) {
8794 if (LoadTree(0)<0) {
8795 Error("SetCacheEntryRange","Could not load a tree");
8796 return -1;
8797 }
8798 }
8799 if (GetTree()) {
8800 if (GetTree() != this) {
8801 return GetTree()->SetCacheEntryRange(first, last);
8802 }
8803 } else {
8804 Error("SetCacheEntryRange", "No tree is available. Could not set cache entry range");
8805 return -1;
8806 }
8807
8808 TFile *f = GetCurrentFile();
8809 if (!f) {
8810 Error("SetCacheEntryRange", "No file is available. Could not set cache entry range");
8811 return -1;
8812 }
8814 if (!tc) {
8815 Error("SetCacheEntryRange", "No cache is available. Could not set entry range");
8816 return -1;
8817 }
8818 tc->SetEntryRange(first,last);
8819 return 0;
8820}
8821
8822////////////////////////////////////////////////////////////////////////////////
8823/// Interface to TTreeCache to set the number of entries for the learning phase
8826{
8828}
8829
8830////////////////////////////////////////////////////////////////////////////////
8831/// Enable/Disable circularity for this tree.
8832///
8833/// if maxEntries > 0 a maximum of maxEntries is kept in one buffer/basket
8834/// per branch in memory.
8835/// Note that when this function is called (maxEntries>0) the Tree
8836/// must be empty or having only one basket per branch.
8837/// if maxEntries <= 0 the tree circularity is disabled.
8838///
8839/// #### NOTE 1:
8840/// Circular Trees are interesting in online real time environments
8841/// to store the results of the last maxEntries events.
8842/// #### NOTE 2:
8843/// Calling SetCircular with maxEntries <= 0 is necessary before
8844/// merging circular Trees that have been saved on files.
8845/// #### NOTE 3:
8846/// SetCircular with maxEntries <= 0 is automatically called
8847/// by TChain::Merge
8848/// #### NOTE 4:
8849/// A circular Tree can still be saved in a file. When read back,
8850/// it is still a circular Tree and can be filled again.
8852void TTree::SetCircular(Long64_t maxEntries)
8853{
8854 if (maxEntries <= 0) {
8855 // Disable circularity.
8856 fMaxEntries = 1000000000;
8857 fMaxEntries *= 1000;
8859 //in case the Tree was originally created in gROOT, the branch
8860 //compression level was set to -1. If the Tree is now associated to
8861 //a file, reset the compression level to the file compression level
8862 if (fDirectory) {
8863 TFile* bfile = fDirectory->GetFile();
8865 if (bfile) {
8866 compress = bfile->GetCompressionSettings();
8867 }
8869 for (Int_t i = 0; i < nb; i++) {
8870 TBranch* branch = (TBranch*) fBranches.UncheckedAt(i);
8871 branch->SetCompressionSettings(compress);
8872 }
8873 }
8874 } else {
8875 // Enable circularity.
8876 fMaxEntries = maxEntries;
8878 }
8879}
8880
8881////////////////////////////////////////////////////////////////////////////////
8882/// Set the debug level and the debug range.
8883///
8884/// For entries in the debug range, the functions TBranchElement::Fill
8885/// and TBranchElement::GetEntry will print the number of bytes filled
8886/// or read for each branch.
8888void TTree::SetDebug(Int_t level, Long64_t min, Long64_t max)
8889{
8890 fDebug = level;
8891 fDebugMin = min;
8892 fDebugMax = max;
8893}
8894
8895////////////////////////////////////////////////////////////////////////////////
8896/// Update the default value for the branch's fEntryOffsetLen.
8897/// If updateExisting is true, also update all the existing branches.
8898/// If newdefault is less than 10, the new default value will be 10.
8900void TTree::SetDefaultEntryOffsetLen(Int_t newdefault, Bool_t updateExisting)
8901{
8902 if (newdefault < 10) {
8903 newdefault = 10;
8904 }
8905 fDefaultEntryOffsetLen = newdefault;
8906 if (updateExisting) {
8907 TIter next( GetListOfBranches() );
8908 TBranch *b;
8909 while ( ( b = (TBranch*)next() ) ) {
8910 b->SetEntryOffsetLen( newdefault, kTRUE );
8911 }
8912 if (fBranchRef) {
8913 fBranchRef->SetEntryOffsetLen( newdefault, kTRUE );
8914 }
8915 }
8916}
8917
8918////////////////////////////////////////////////////////////////////////////////
8919/// Change the tree's directory.
8920///
8921/// Remove reference to this tree from current directory and
8922/// add reference to new directory dir. The dir parameter can
8923/// be 0 in which case the tree does not belong to any directory.
8924///
8927{
8928 if (fDirectory == dir) {
8929 return;
8930 }
8931 if (fDirectory) {
8932 fDirectory->Remove(this);
8933
8934 // Delete or move the file cache if it points to this Tree
8936 MoveReadCache(file,dir);
8937 }
8938 fDirectory = dir;
8939 if (fDirectory) {
8940 fDirectory->Append(this);
8941 }
8942 TFile* file = 0;
8943 if (fDirectory) {
8944 file = fDirectory->GetFile();
8945 }
8946 if (fBranchRef) {
8948 }
8949 TBranch* b = 0;
8950 TIter next(GetListOfBranches());
8951 while((b = (TBranch*) next())) {
8952 b->SetFile(file);
8953 }
8954}
8955
8956////////////////////////////////////////////////////////////////////////////////
8957/// Change number of entries in the tree.
8958///
8959/// If n >= 0, set number of entries in the tree = n.
8960///
8961/// If n < 0, set number of entries in the tree to match the
8962/// number of entries in each branch. (default for n is -1)
8963///
8964/// This function should be called only when one fills each branch
8965/// independently via TBranch::Fill without calling TTree::Fill.
8966/// Calling TTree::SetEntries() make sense only if the number of entries
8967/// in each branch is identical, a warning is issued otherwise.
8968/// The function returns the number of entries.
8969///
8972{
8973 // case 1 : force number of entries to n
8974 if (n >= 0) {
8975 fEntries = n;
8976 return n;
8977 }
8978
8979 // case 2; compute the number of entries from the number of entries in the branches
8980 TBranch* b(nullptr), *bMin(nullptr), *bMax(nullptr);
8981 Long64_t nMin = kMaxEntries;
8982 Long64_t nMax = 0;
8983 TIter next(GetListOfBranches());
8984 while((b = (TBranch*) next())){
8985 Long64_t n2 = b->GetEntries();
8986 if (!bMin || n2 < nMin) {
8987 nMin = n2;
8988 bMin = b;
8989 }
8990 if (!bMax || n2 > nMax) {
8991 nMax = n2;
8992 bMax = b;
8993 }
8994 }
8995 if (bMin && nMin != nMax) {
8996 Warning("SetEntries", "Tree branches have different numbers of entries, eg %s has %lld entries while %s has %lld entries.",
8997 bMin->GetName(), nMin, bMax->GetName(), nMax);
8998 }
8999 fEntries = nMax;
9000 return fEntries;
9001}
9002
9003////////////////////////////////////////////////////////////////////////////////
9004/// Set an EntryList
9006void TTree::SetEntryList(TEntryList *enlist, Option_t * /*opt*/)
9007{
9008 if (fEntryList) {
9009 //check if the previous entry list is owned by the tree
9011 delete fEntryList;
9012 }
9013 }
9014 fEventList = 0;
9015 if (!enlist) {
9016 fEntryList = 0;
9017 return;
9018 }
9019 fEntryList = enlist;
9020 fEntryList->SetTree(this);
9021
9022}
9023
9024////////////////////////////////////////////////////////////////////////////////
9025/// This function transfroms the given TEventList into a TEntryList
9026/// The new TEntryList is owned by the TTree and gets deleted when the tree
9027/// is deleted. This TEntryList can be returned by GetEntryList() function.
9029void TTree::SetEventList(TEventList *evlist)
9030{
9031 fEventList = evlist;
9032 if (fEntryList){
9034 TEntryList *tmp = fEntryList;
9035 fEntryList = 0; // Avoid problem with RecursiveRemove.
9036 delete tmp;
9037 } else {
9038 fEntryList = 0;
9039 }
9040 }
9041
9042 if (!evlist) {
9043 fEntryList = 0;
9044 fEventList = 0;
9045 return;
9046 }
9047
9048 fEventList = evlist;
9049 char enlistname[100];
9050 snprintf(enlistname,100, "%s_%s", evlist->GetName(), "entrylist");
9051 fEntryList = new TEntryList(enlistname, evlist->GetTitle());
9052 fEntryList->SetDirectory(0); // We own this.
9053 Int_t nsel = evlist->GetN();
9054 fEntryList->SetTree(this);
9055 Long64_t entry;
9056 for (Int_t i=0; i<nsel; i++){
9057 entry = evlist->GetEntry(i);
9058 fEntryList->Enter(entry);
9059 }
9062}
9063
9064////////////////////////////////////////////////////////////////////////////////
9065/// Set number of entries to estimate variable limits.
9066/// If n is -1, the estimate is set to be the current maximum
9067/// for the tree (i.e. GetEntries() + 1)
9068/// If n is less than -1, the behavior is undefined.
9070void TTree::SetEstimate(Long64_t n /* = 1000000 */)
9071{
9072 if (n == 0) {
9073 n = 10000;
9074 } else if (n < 0) {
9075 n = fEntries - n;
9076 }
9077 fEstimate = n;
9078 GetPlayer();
9079 if (fPlayer) {
9081 }
9082}
9083
9084////////////////////////////////////////////////////////////////////////////////
9085/// Provide the end-user with the ability to enable/disable various experimental
9086/// IO features for this TTree.
9087///
9088/// Returns all the newly-set IO settings.
9091{
9092 // Purposely ignore all unsupported bits; TIOFeatures implementation already warned the user about the
9093 // error of their ways; this is just a safety check.
9094 UChar_t featuresRequested = features.GetFeatures() & static_cast<UChar_t>(TBasket::EIOBits::kSupported);
9095
9096 UChar_t curFeatures = fIOFeatures.GetFeatures();
9097 UChar_t newFeatures = ~curFeatures & featuresRequested;
9098 curFeatures |= newFeatures;
9099 fIOFeatures.Set(curFeatures);
9100
9101 ROOT::TIOFeatures newSettings(newFeatures);
9102 return newSettings;
9103}
9104
9105////////////////////////////////////////////////////////////////////////////////
9106/// Set fFileNumber to number.
9107/// fFileNumber is used by TTree::Fill to set the file name
9108/// for a new file to be created when the current file exceeds fgTreeMaxSize.
9109/// (see TTree::ChangeFile)
9110/// if fFileNumber=10, the new file name will have a suffix "_11",
9111/// ie, fFileNumber is incremented before setting the file name
9113void TTree::SetFileNumber(Int_t number)
9114{
9115 if (fFileNumber < 0) {
9116 Warning("SetFileNumber", "file number must be positive. Set to 0");
9117 fFileNumber = 0;
9118 return;
9119 }
9120 fFileNumber = number;
9121}
9122
9123////////////////////////////////////////////////////////////////////////////////
9124/// Set all the branches in this TTree to be in decomposed object mode
9125/// (also known as MakeClass mode).
9126///
9127/// For MakeClass mode 0, the TTree expects the address where the data is stored
9128/// to be set by either the user or the TTree to the address of a full object
9129/// through the top level branch.
9130/// For MakeClass mode 1, this address is expected to point to a numerical type
9131/// or C-style array (variable or not) of numerical type, representing the
9132/// primitive data members.
9133/// The function's primary purpose is to allow the user to access the data
9134/// directly with numerical type variable rather than having to have the original
9135/// set of classes (or a reproduction thereof).
9137void TTree::SetMakeClass(Int_t make)
9138{
9139 fMakeClass = make;
9140
9142 for (Int_t i = 0; i < nb; ++i) {
9143 TBranch* branch = (TBranch*) fBranches.UncheckedAt(i);
9144 branch->SetMakeClass(make);
9145 }
9146}
9147
9148////////////////////////////////////////////////////////////////////////////////
9149/// Set the maximum size in bytes of a Tree file (static function).
9150/// The default size is 100000000000LL, ie 100 Gigabytes.
9151///
9152/// In TTree::Fill, when the file has a size > fgMaxTreeSize,
9153/// the function closes the current file and starts writing into
9154/// a new file with a name of the style "file_1.root" if the original
9155/// requested file name was "file.root".
9157void TTree::SetMaxTreeSize(Long64_t maxsize)
9158{
9159 fgMaxTreeSize = maxsize;
9160}
9161
9162////////////////////////////////////////////////////////////////////////////////
9163/// Change the name of this tree.
9165void TTree::SetName(const char* name)
9166{
9167 if (gPad) {
9168 gPad->Modified();
9169 }
9170 // Trees are named objects in a THashList.
9171 // We must update hashlists if we change the name.
9172 TFile *file = 0;
9173 TTreeCache *pf = 0;
9174 if (fDirectory) {
9175 fDirectory->Remove(this);
9176 if ((file = GetCurrentFile())) {
9177 pf = GetReadCache(file);
9178 file->SetCacheRead(0,this,TFile::kDoNotDisconnect);
9179 }
9180 }
9181 // This changes our hash value.
9182 fName = name;
9183 if (fDirectory) {
9184 fDirectory->Append(this);
9185 if (pf) {
9186 file->SetCacheRead(pf,this,TFile::kDoNotDisconnect);
9187 }
9188 }
9189}
9190
9191////////////////////////////////////////////////////////////////////////////////
9192/// Change the name and title of this tree.
9194void TTree::SetObject(const char* name, const char* title)
9195{
9196 if (gPad) {
9197 gPad->Modified();
9198 }
9199
9200 // Trees are named objects in a THashList.
9201 // We must update hashlists if we change the name
9202 TFile *file = 0;
9203 TTreeCache *pf = 0;
9204 if (fDirectory) {
9205 fDirectory->Remove(this);
9206 if ((file = GetCurrentFile())) {
9207 pf = GetReadCache(file);
9208 file->SetCacheRead(0,this,TFile::kDoNotDisconnect);
9209 }
9210 }
9211 // This changes our hash value.
9212 fName = name;
9213 fTitle = title;
9214 if (fDirectory) {
9215 fDirectory->Append(this);
9216 if (pf) {
9217 file->SetCacheRead(pf,this,TFile::kDoNotDisconnect);
9218 }
9219 }
9220}
9221
9222////////////////////////////////////////////////////////////////////////////////
9223/// Enable or disable parallel unzipping of Tree buffers.
9225void TTree::SetParallelUnzip(Bool_t opt, Float_t RelSize)
9226{
9227#ifdef R__USE_IMT
9228 if (GetTree() == 0) {
9230 if (!GetTree())
9231 return;
9232 }
9233 if (GetTree() != this) {
9234 GetTree()->SetParallelUnzip(opt, RelSize);
9235 return;
9236 }
9238 if (!file)
9239 return;
9240
9242 if (pf && !( opt ^ (nullptr != dynamic_cast<TTreeCacheUnzip*>(pf)))) {
9243 // done with opt and type are in agreement.
9244 return;
9245 }
9246 delete pf;
9247 auto cacheSize = GetCacheAutoSize(kTRUE);
9248 if (opt) {
9249 auto unzip = new TTreeCacheUnzip(this, cacheSize);
9250 unzip->SetUnzipBufferSize( Long64_t(cacheSize * RelSize) );
9251 } else {
9252 pf = new TTreeCache(this, cacheSize);
9253 }
9254#else
9255 (void)opt;
9256 (void)RelSize;
9257#endif
9258}
9259
9260////////////////////////////////////////////////////////////////////////////////
9261/// Set perf stats
9264{
9265 fPerfStats = perf;
9266}
9267
9268////////////////////////////////////////////////////////////////////////////////
9269/// The current TreeIndex is replaced by the new index.
9270/// Note that this function does not delete the previous index.
9271/// This gives the possibility to play with more than one index, e.g.,
9272/// ~~~ {.cpp}
9273/// TVirtualIndex* oldIndex = tree.GetTreeIndex();
9274/// tree.SetTreeIndex(newIndex);
9275/// tree.Draw();
9276/// tree.SetTreeIndex(oldIndex);
9277/// tree.Draw(); etc
9278/// ~~~
9281{
9282 if (fTreeIndex) {
9283 fTreeIndex->SetTree(0);
9284 }
9285 fTreeIndex = index;
9286}
9287
9288////////////////////////////////////////////////////////////////////////////////
9289/// Set tree weight.
9290///
9291/// The weight is used by TTree::Draw to automatically weight each
9292/// selected entry in the resulting histogram.
9293///
9294/// For example the equivalent of:
9295/// ~~~ {.cpp}
9296/// T.Draw("x", "w")
9297/// ~~~
9298/// is:
9299/// ~~~ {.cpp}
9300/// T.SetWeight(w);
9301/// T.Draw("x");
9302/// ~~~
9303/// This function is redefined by TChain::SetWeight. In case of a
9304/// TChain, an option "global" may be specified to set the same weight
9305/// for all trees in the TChain instead of the default behaviour
9306/// using the weights of each tree in the chain (see TChain::SetWeight).
9309{
9310 fWeight = w;
9311}
9312
9313////////////////////////////////////////////////////////////////////////////////
9314/// Print values of all active leaves for entry.
9315///
9316/// - if entry==-1, print current entry (default)
9317/// - if a leaf is an array, a maximum of lenmax elements is printed.
9319void TTree::Show(Long64_t entry, Int_t lenmax)
9320{
9321 if (entry != -1) {
9322 Int_t ret = LoadTree(entry);
9323 if (ret == -2) {
9324 Error("Show()", "Cannot read entry %lld (entry does not exist)", entry);
9325 return;
9326 } else if (ret == -1) {
9327 Error("Show()", "Cannot read entry %lld (I/O error)", entry);
9328 return;
9329 }
9330 ret = GetEntry(entry);
9331 if (ret == -1) {
9332 Error("Show()", "Cannot read entry %lld (I/O error)", entry);
9333 return;
9334 } else if (ret == 0) {
9335 Error("Show()", "Cannot read entry %lld (no data read)", entry);
9336 return;
9337 }
9338 }
9339 printf("======> EVENT:%lld\n", fReadEntry);
9340 TObjArray* leaves = GetListOfLeaves();
9341 Int_t nleaves = leaves->GetEntriesFast();
9342 Int_t ltype;
9343 for (Int_t i = 0; i < nleaves; i++) {
9344 TLeaf* leaf = (TLeaf*) leaves->UncheckedAt(i);
9345 TBranch* branch = leaf->GetBranch();
9346 if (branch->TestBit(kDoNotProcess)) {
9347 continue;
9348 }
9349 Int_t len = leaf->GetLen();
9350 if (len <= 0) {
9351 continue;
9352 }
9353 len = TMath::Min(len, lenmax);
9354 if (leaf->IsA() == TLeafElement::Class()) {
9355 leaf->PrintValue(lenmax);
9356 continue;
9357 }
9358 if (branch->GetListOfBranches()->GetEntriesFast() > 0) {
9359 continue;
9360 }
9361 ltype = 10;
9362 if (leaf->IsA() == TLeafF::Class()) {
9363 ltype = 5;
9364 }
9365 if (leaf->IsA() == TLeafD::Class()) {
9366 ltype = 5;
9367 }
9368 if (leaf->IsA() == TLeafC::Class()) {
9369 len = 1;
9370 ltype = 5;
9371 };
9372 printf(" %-15s = ", leaf->GetName());
9373 for (Int_t l = 0; l < len; l++) {
9374 leaf->PrintValue(l);
9375 if (l == (len - 1)) {
9376 printf("\n");
9377 continue;
9378 }
9379 printf(", ");
9380 if ((l % ltype) == 0) {
9381 printf("\n ");
9382 }
9383 }
9384 }
9385}
9386
9387////////////////////////////////////////////////////////////////////////////////
9388/// Start the TTreeViewer on this tree.
9389///
9390/// - ww is the width of the canvas in pixels
9391/// - wh is the height of the canvas in pixels
9393void TTree::StartViewer()
9394{
9395 GetPlayer();
9396 if (fPlayer) {
9397 fPlayer->StartViewer(600, 400);
9398 }
9399}
9400
9401////////////////////////////////////////////////////////////////////////////////
9402/// Stop the cache learning phase
9403///
9404/// Returns:
9405/// - 0 learning phase stopped or not active
9406/// - -1 on error
9409{
9410 if (!GetTree()) {
9411 if (LoadTree(0)<0) {
9412 Error("StopCacheLearningPhase","Could not load a tree");
9413 return -1;
9414 }
9415 }
9416 if (GetTree()) {
9417 if (GetTree() != this) {
9418 return GetTree()->StopCacheLearningPhase();
9419 }
9420 } else {
9421 Error("StopCacheLearningPhase", "No tree is available. Could not stop cache learning phase");
9422 return -1;
9423 }
9424
9425 TFile *f = GetCurrentFile();
9426 if (!f) {
9427 Error("StopCacheLearningPhase", "No file is available. Could not stop cache learning phase");
9428 return -1;
9429 }
9431 if (!tc) {
9432 Error("StopCacheLearningPhase", "No cache is available. Could not stop learning phase");
9433 return -1;
9434 }
9435 tc->StopLearningPhase();
9436 return 0;
9437}
9438
9439////////////////////////////////////////////////////////////////////////////////
9440/// Set the fTree member for all branches and sub branches.
9442static void TBranch__SetTree(TTree *tree, TObjArray &branches)
9443{
9444 Int_t nb = branches.GetEntriesFast();
9445 for (Int_t i = 0; i < nb; ++i) {
9446 TBranch* br = (TBranch*) branches.UncheckedAt(i);
9447 br->SetTree(tree);
9448
9449 Int_t writeBasket = br->GetWriteBasket();
9450 for (Int_t j = writeBasket; j >= 0; --j) {
9451 TBasket *bk = (TBasket*)br->GetListOfBaskets()->UncheckedAt(j);
9452 if (bk) {
9453 tree->IncrementTotalBuffers(bk->GetBufferSize());
9454 }
9455 }
9456
9458 }
9459}
9460
9461////////////////////////////////////////////////////////////////////////////////
9462/// Set the fTree member for all friend elements.
9465{
9466 if (frlist) {
9467 TObjLink *lnk = frlist->FirstLink();
9468 while (lnk) {
9469 TFriendElement *elem = (TFriendElement*)lnk->GetObject();
9470 elem->fParentTree = tree;
9471 lnk = lnk->Next();
9472 }
9473 }
9474}
9475
9476////////////////////////////////////////////////////////////////////////////////
9477/// Stream a class object.
9478
9479void TTree::Streamer(TBuffer& b)
9480{
9481 if (b.IsReading()) {
9482 UInt_t R__s, R__c;
9483 if (fDirectory) {
9484 fDirectory->Remove(this);
9485 //delete the file cache if it points to this Tree
9488 }
9489 fDirectory = 0;
9492 Version_t R__v = b.ReadVersion(&R__s, &R__c);
9493 if (R__v > 4) {
9494 b.ReadClassBuffer(TTree::Class(), this, R__v, R__s, R__c);
9495
9496 fBranches.SetOwner(kTRUE); // True needed only for R__v < 19 and most R__v == 19
9497
9498 if (fBranchRef) fBranchRef->SetTree(this);
9501
9502 if (fTreeIndex) {
9503 fTreeIndex->SetTree(this);
9504 }
9505 if (fIndex.fN) {
9506 Warning("Streamer", "Old style index in this tree is deleted. Rebuild the index via TTree::BuildIndex");
9507 fIndex.Set(0);
9508 fIndexValues.Set(0);
9509 }
9510 if (fEstimate <= 10000) {
9511 fEstimate = 1000000;
9512 }
9513
9514 if (fNClusterRange) {
9515 // The I/O allocated just enough memory to hold the
9516 // current set of ranges.
9518 }
9519
9520 // Throughs calls to `GetCacheAutoSize` or `EnableCache` (for example
9521 // by TTreePlayer::Process, the cache size will be automatically
9522 // determined unless the user explicitly call `SetCacheSize`
9523 fCacheSize = 0;
9525
9527 return;
9528 }
9529 //====process old versions before automatic schema evolution
9530 Stat_t djunk;
9531 Int_t ijunk;
9532 TNamed::Streamer(b);
9533 TAttLine::Streamer(b);
9534 TAttFill::Streamer(b);
9535 TAttMarker::Streamer(b);
9536 b >> fScanField;
9537 b >> ijunk; fMaxEntryLoop = (Long64_t)ijunk;
9538 b >> ijunk; fMaxVirtualSize = (Long64_t)ijunk;
9539 b >> djunk; fEntries = (Long64_t)djunk;
9540 b >> djunk; fTotBytes = (Long64_t)djunk;
9541 b >> djunk; fZipBytes = (Long64_t)djunk;
9542 b >> ijunk; fAutoSave = (Long64_t)ijunk;
9543 b >> ijunk; fEstimate = (Long64_t)ijunk;
9544 if (fEstimate <= 10000) fEstimate = 1000000;
9545 fBranches.Streamer(b);
9546 if (fBranchRef) fBranchRef->SetTree(this);
9548 fLeaves.Streamer(b);
9550 if (R__v > 1) fIndexValues.Streamer(b);
9551 if (R__v > 2) fIndex.Streamer(b);
9552 if (R__v > 3) {
9553 TList OldInfoList;
9554 OldInfoList.Streamer(b);
9555 OldInfoList.Delete();
9556 }
9557 fNClusterRange = 0;
9560 b.CheckByteCount(R__s, R__c, TTree::IsA());
9561 //====end of old versions
9562 } else {
9563 if (fBranchRef) {
9564 fBranchRef->Clear();
9565 }
9567 if (table) TRefTable::SetRefTable(0);
9568
9569 b.WriteClassBuffer(TTree::Class(), this);
9570
9571 if (table) TRefTable::SetRefTable(table);
9572 }
9573}
9574
9575////////////////////////////////////////////////////////////////////////////////
9576/// Unbinned fit of one or more variable(s) from a tree.
9577///
9578/// funcname is a TF1 function.
9579///
9580/// See TTree::Draw for explanations of the other parameters.
9581///
9582/// Fit the variable varexp using the function funcname using the
9583/// selection cuts given by selection.
9584///
9585/// The list of fit options is given in parameter option.
9586///
9587/// - option = "Q" Quiet mode (minimum printing)
9588/// - option = "V" Verbose mode (default is between Q and V)
9589/// - option = "E" Perform better Errors estimation using Minos technique
9590/// - option = "M" More. Improve fit results
9591///
9592/// You can specify boundary limits for some or all parameters via
9593/// ~~~ {.cpp}
9594/// func->SetParLimits(p_number, parmin, parmax);
9595/// ~~~
9596/// if parmin>=parmax, the parameter is fixed
9597///
9598/// Note that you are not forced to fix the limits for all parameters.
9599/// For example, if you fit a function with 6 parameters, you can do:
9600/// ~~~ {.cpp}
9601/// func->SetParameters(0,3.1,1.e-6,0.1,-8,100);
9602/// func->SetParLimits(4,-10,-4);
9603/// func->SetParLimits(5, 1,1);
9604/// ~~~
9605/// With this setup:
9606///
9607/// - Parameters 0->3 can vary freely
9608/// - Parameter 4 has boundaries [-10,-4] with initial value -8
9609/// - Parameter 5 is fixed to 100.
9610///
9611/// For the fit to be meaningful, the function must be self-normalized.
9612///
9613/// i.e. It must have the same integral regardless of the parameter
9614/// settings. Otherwise the fit will effectively just maximize the
9615/// area.
9616///
9617/// It is mandatory to have a normalization variable
9618/// which is fixed for the fit. e.g.
9619/// ~~~ {.cpp}
9620/// TF1* f1 = new TF1("f1", "gaus(0)/sqrt(2*3.14159)/[2]", 0, 5);
9621/// f1->SetParameters(1, 3.1, 0.01);
9622/// f1->SetParLimits(0, 1, 1); // fix the normalization parameter to 1
9623/// data->UnbinnedFit("f1", "jpsimass", "jpsipt>3.0");
9624/// ~~~
9625/// 1, 2 and 3 Dimensional fits are supported. See also TTree::Fit
9626///
9627/// Return status:
9628///
9629/// - The function return the status of the fit in the following form
9630/// fitResult = migradResult + 10*minosResult + 100*hesseResult + 1000*improveResult
9631/// - The fitResult is 0 is the fit is OK.
9632/// - The fitResult is negative in case of an error not connected with the fit.
9633/// - The number of entries used in the fit can be obtained via mytree.GetSelectedRows();
9634/// - If the number of selected entries is null the function returns -1
9636Int_t TTree::UnbinnedFit(const char* funcname, const char* varexp, const char* selection, Option_t* option, Long64_t nentries, Long64_t firstentry)
9637{
9638 GetPlayer();
9639 if (fPlayer) {
9640 return fPlayer->UnbinnedFit(funcname, varexp, selection, option, nentries, firstentry);
9641 }
9642 return -1;
9643}
9644
9645////////////////////////////////////////////////////////////////////////////////
9646/// Replace current attributes by current style.
9649{
9650 if (gStyle->IsReading()) {
9659 } else {
9668 }
9669}
9670
9671////////////////////////////////////////////////////////////////////////////////
9672/// Write this object to the current directory. For more see TObject::Write
9673/// If option & kFlushBasket, call FlushBasket before writing the tree.
9675Int_t TTree::Write(const char *name, Int_t option, Int_t bufsize) const
9676{
9678 if (R__unlikely(option & kOnlyPrepStep))
9679 return 0;
9680 return TObject::Write(name, option, bufsize);
9681}
9682
9683////////////////////////////////////////////////////////////////////////////////
9684/// Write this object to the current directory. For more see TObject::Write
9685/// If option & kFlushBasket, call FlushBasket before writing the tree.
9687Int_t TTree::Write(const char *name, Int_t option, Int_t bufsize)
9688{
9689 return ((const TTree*)this)->Write(name, option, bufsize);
9690}
9691
9692////////////////////////////////////////////////////////////////////////////////
9693/// \class TTreeFriendLeafIter
9694///
9695/// Iterator on all the leaves in a TTree and its friend
9696
9698
9699////////////////////////////////////////////////////////////////////////////////
9700/// Create a new iterator. By default the iteration direction
9701/// is kIterForward. To go backward use kIterBackward.
9704: fTree(const_cast<TTree*>(tree))
9705, fLeafIter(0)
9706, fTreeIter(0)
9707, fDirection(dir)
9708{
9709}
9710
9711////////////////////////////////////////////////////////////////////////////////
9712/// Copy constructor. Does NOT copy the 'cursor' location!
9715: TIterator(iter)
9716, fTree(iter.fTree)
9717, fLeafIter(0)
9718, fTreeIter(0)
9719, fDirection(iter.fDirection)
9720{
9721}
9722
9723////////////////////////////////////////////////////////////////////////////////
9724/// Overridden assignment operator. Does NOT copy the 'cursor' location!
9727{
9728 if (this != &rhs && rhs.IsA() == TTreeFriendLeafIter::Class()) {
9729 const TTreeFriendLeafIter &rhs1 = (const TTreeFriendLeafIter &)rhs;
9730 fDirection = rhs1.fDirection;
9731 }
9732 return *this;
9733}
9734
9735////////////////////////////////////////////////////////////////////////////////
9736/// Overridden assignment operator. Does NOT copy the 'cursor' location!
9739{
9740 if (this != &rhs) {
9741 fDirection = rhs.fDirection;
9742 }
9743 return *this;
9744}
9745
9746////////////////////////////////////////////////////////////////////////////////
9747/// Go the next friend element
9750{
9751 if (!fTree) return 0;
9752
9753 TObject * next;
9754 TTree * nextTree;
9755
9756 if (!fLeafIter) {
9757 TObjArray *list = fTree->GetListOfLeaves();
9758 if (!list) return 0; // Can happen with an empty chain.
9760 if (!fLeafIter) return 0;
9761 }
9762
9763 next = fLeafIter->Next();
9764 if (!next) {
9765 if (!fTreeIter) {
9767 if (!list) return next;
9769 if (!fTreeIter) return 0;
9770 }
9771 TFriendElement * nextFriend = (TFriendElement*) fTreeIter->Next();
9772 ///nextTree = (TTree*)fTreeIter->Next();
9773 if (nextFriend) {
9774 nextTree = const_cast<TTree*>(nextFriend->GetTree());
9775 if (!nextTree) return Next();
9778 if (!fLeafIter) return 0;
9779 next = fLeafIter->Next();
9780 }
9781 }
9782 return next;
9783}
9784
9785////////////////////////////////////////////////////////////////////////////////
9786/// Returns the object option stored in the list.
9789{
9790 if (fLeafIter) return fLeafIter->GetOption();
9791 return "";
9792}
#define R__unlikely(expr)
Definition RConfig.hxx:608
#define SafeDelete(p)
Definition RConfig.hxx:547
#define b(i)
Definition RSha256.hxx:100
#define f(i)
Definition RSha256.hxx:104
#define c(i)
Definition RSha256.hxx:101
#define a(i)
Definition RSha256.hxx:99
const Ssiz_t kNPOS
Definition RtypesCore.h:115
int Int_t
Definition RtypesCore.h:45
short Version_t
Definition RtypesCore.h:65
unsigned char UChar_t
Definition RtypesCore.h:38
unsigned int UInt_t
Definition RtypesCore.h:46
const Bool_t kFALSE
Definition RtypesCore.h:92
long Long_t
Definition RtypesCore.h:54
bool Bool_t
Definition RtypesCore.h:63
double Double_t
Definition RtypesCore.h:59
double Stat_t
Definition RtypesCore.h:77
long long Long64_t
Definition RtypesCore.h:73
unsigned long long ULong64_t
Definition RtypesCore.h:74
float Float_t
Definition RtypesCore.h:57
const Bool_t kTRUE
Definition RtypesCore.h:91
const char Option_t
Definition RtypesCore.h:66
#define ClassImp(name)
Definition Rtypes.h:364
const Int_t kDoNotProcess
Definition TBranch.h:56
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:290
R__EXTERN TEnv * gEnv
Definition TEnv.h:171
#define R__ASSERT(e)
Definition TError.h:120
void Error(const char *location, const char *msgfmt,...)
Use this function in case an error occurred.
Definition TError.cxx:187
#define N
static unsigned int total
char name[80]
Definition TGX11.cxx:110
int nentries
R__EXTERN TInterpreter * gCling
Int_t gDebug
Definition TROOT.cxx:590
R__EXTERN TVirtualMutex * gROOTMutex
Definition TROOT.h:63
#define gROOT
Definition TROOT.h:406
void Printf(const char *fmt,...)
R__EXTERN TStyle * gStyle
Definition TStyle.h:412
typedef void((*Func_t)())
R__EXTERN TSystem * gSystem
Definition TSystem.h:559
constexpr Int_t kNEntriesResort
Definition TTree.cxx:440
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:4780
static char DataTypeToChar(EDataType datatype)
Definition TTree.cxx:452
void TFriendElement__SetTree(TTree *tree, TList *frlist)
Set the fTree member for all friend elements.
Definition TTree.cxx:9463
bool CheckReshuffling(TTree &mainTree, TTree &friendTree)
Definition TTree.cxx:1230
static void TBranch__SetTree(TTree *tree, TObjArray &branches)
Set the fTree member for all branches and sub branches.
Definition TTree.cxx:9441
constexpr Float_t kNEntriesResortInv
Definition TTree.cxx:441
#define R__LOCKGUARD(mutex)
#define gPad
#define snprintf
Definition civetweb.c:1540
TRangeStaticCast is an adaptater class that allows the typed iteration through a TCollection.
Bool_t HasRuleWithSourceClass(const TString &source) const
Return True if we have any rule whose source class is 'source'.
A helper class for managing IMT work during TTree:Fill operations.
TIOFeatures provides the end-user with the ability to change the IO behavior of data written via a TT...
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 threads,...
void Foreach(F func, unsigned nTimes, unsigned nChunks=0)
Execute a function without arguments several times in parallel, dividing the execution in nChunks.
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.
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.
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.
A Branch for the case of an object.
A branch containing and managing a TRefTable for TRef autoloading.
Definition TBranchRef.h:34
virtual void ResetAfterMerge(TFileMergeInfo *)
Reset a Branch after a Merge operation (drop data but keep customizations) TRefTable is cleared.
virtual void Reset(Option_t *option="")
virtual void Clear(Option_t *option="")
Clear entries in the TRefTable.
virtual void Print(Option_t *option="") const
Print the TRefTable branch.
A Branch handling STL collection of pointers (vectors, lists, queues, sets and multisets) while stori...
Definition TBranchSTL.h:22
A TTree is a list of TBranches.
Definition TBranch.h:89
virtual TLeaf * GetLeaf(const char *name) const
Return pointer to the 1st Leaf named name in thisBranch.
Definition TBranch.cxx:1993
virtual void SetupAddresses()
If the branch address is not set, we set all addresses starting with the top level parent branch.
Definition TBranch.cxx:3232
virtual void ResetAddress()
Reset the address of the branch.
Definition TBranch.cxx:2589
virtual Long64_t GetBasketSeek(Int_t basket) const
Return address of basket in the file.
Definition TBranch.cxx:1302
virtual char * GetAddress() const
Definition TBranch.h:208
void SetCompressionSettings(Int_t settings=ROOT::RCompressionSetting::EDefaults::kUseCompiledDefault)
Set compression settings.
Definition TBranch.cxx:2743
TTree * GetTree() const
Definition TBranch.h:248
virtual TString GetFullName() const
Return the 'full' name of the branch.
Definition TBranch.cxx:1977
Int_t GetWriteBasket() const
Definition TBranch.h:234
virtual void DropBaskets(Option_t *option="")
Loop on all branch baskets.
Definition TBranch.cxx:757
TObjArray * GetListOfBranches()
Definition TBranch.h:242
virtual void SetTree(TTree *tree)
Definition TBranch.h:283
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:2759
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:1652
static void ResetCount()
Static function resetting fgCount.
Definition TBranch.cxx:2612
virtual void SetObject(void *objadd)
Set object this branch is pointing to.
Definition TBranch.cxx:2874
Int_t FlushBaskets()
Flush to disk all the baskets of this branch and any of subbranches.
Definition TBranch.cxx:1136
virtual void SetAddress(void *add)
Set address of this branch.
Definition TBranch.cxx:2620
Int_t GetNleaves() const
Definition TBranch.h:245
TObjArray * GetListOfBaskets()
Definition TBranch.h:241
Long64_t GetEntries() const
Definition TBranch.h:247
virtual void UpdateFile()
Refresh the value of fDirectory (i.e.
Definition TBranch.cxx:3242
Int_t GetReadBasket() const
Definition TBranch.h:232
virtual void Print(Option_t *option="") const
Print TBranch parameters.
Definition TBranch.cxx:2279
Int_t GetMaxBaskets() const
Definition TBranch.h:244
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:1799
virtual void KeepCircular(Long64_t maxEntries)
keep a maximum of fMaxEntries in memory
Definition TBranch.cxx:2221
virtual void ResetAfterMerge(TFileMergeInfo *)
Reset a Branch.
Definition TBranch.cxx:2536
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:2055
virtual TBranch * FindBranch(const char *name)
Find the immediate sub-branch with passed name.
Definition TBranch.cxx:1035
virtual Int_t LoadBaskets()
Baskets associated to this branch are forced to be in memory.
Definition TBranch.cxx:2247
void SetIOFeatures(TIOFeatures &features)
Definition TBranch.h:279
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:2158
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:2865
virtual void SetFile(TFile *file=0)
Set file where this branch writes/reads its buffers.
Definition TBranch.cxx:2801
virtual void SetOffset(Int_t offset=0)
Definition TBranch.h:281
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:1780
virtual Int_t GetBasketSize() const
Definition TBranch.h:213
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:2176
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:2667
virtual void Refresh(TBranch *b)
Refresh this branch using new information in b This function is called by TTree::Refresh.
Definition TBranch.cxx:2446
TObjArray * GetListOfLeaves()
Definition TBranch.h:243
Int_t Fill()
Definition TBranch.h:201
virtual void Reset(Option_t *option="")
Reset a Branch.
Definition TBranch.cxx:2495
TBranch * GetMother() const
Get our top-level parent branch in the tree.
Definition TBranch.cxx:2065
virtual Int_t FillImpl(ROOT::Internal::TBranchIMTHelper *)
Loop on all leaves of this branch to fill Basket buffer.
Definition TBranch.cxx:856
Int_t GetEntryOffsetLen() const
Definition TBranch.h:223
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:47
Buffer base class used for serializing objects.
Definition TBuffer.h:43
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:98
@ kWrite
Definition TBuffer.h:73
@ kRead
Definition TBuffer.h:73
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:2309
ROOT::ESTLType GetCollectionType() const
Return the 'type' of the STL the TClass is representing.
Definition TClass.cxx:2875
void * New(ENewType defConstructor=kClassNew, Bool_t quiet=kFALSE) const
Return a pointer to a newly allocated object of this class.
Definition TClass.cxx:4955
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:2020
void Destructor(void *obj, Bool_t dtorOnly=kFALSE)
Explicitly call destructor for object.
Definition TClass.cxx:5377
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:3747
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:1921
TList * GetListOfBases()
Return list containing the TBaseClass(es) of a class.
Definition TClass.cxx:3613
Bool_t IsLoaded() const
Return true if the shared library of this class is currently in the a process's memory.
Definition TClass.cxx:5889
Bool_t IsTObject() const
Return kTRUE is the class inherits from TObject.
Definition TClass.cxx:5915
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:4576
TVirtualCollectionProxy * GetCollectionProxy() const
Return the proxy describing the collection (if any).
Definition TClass.cxx:2886
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:7060
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:7167
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:4851
TClass * GetActualClass(const void *object) const
Return a pointer the the real class of the object.
Definition TClass.cxx:2597
@ 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:2957
An array of clone (identical) objects.
void BypassStreamer(Bool_t bypass=kTRUE)
When the kBypassStreamer bit is set, the automatically generated Streamer can call directly TClass::W...
TClass * GetClass() const
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)
void Browse(TBrowser *b)
Browse this collection (called by TBrowser).
virtual Int_t GetEntries() const
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.: "class TDirectory*" -> "TDirectory".
void Append(TObject *obj, Bool_t replace=kFALSE) override
Append object to this directory.
Small helper to keep current directory context.
Definition TDirectory.h:52
Describe directory structure in memory.
Definition TDirectory.h:45
virtual TList * GetList() const
Definition TDirectory.h:176
virtual void Append(TObject *obj, Bool_t replace=kFALSE)
Append object to this directory.
virtual Int_t WriteTObject(const TObject *obj, const char *name=nullptr, Option_t *="", Int_t=0)
virtual TFile * GetFile() const
Definition TDirectory.h:174
virtual Int_t ReadKeys(Bool_t=kTRUE)
Definition TDirectory.h:201
virtual Bool_t IsWritable() const
Definition TDirectory.h:190
virtual TKey * GetKey(const char *, Short_t=9999) const
Definition TDirectory.h:175
virtual Int_t ReadTObject(TObject *, const char *)
Definition TDirectory.h:202
virtual void SaveSelf(Bool_t=kFALSE)
Definition TDirectory.h:208
virtual TList * GetListOfKeys() const
Definition TDirectory.h:177
void GetObject(const char *namecycle, T *&ptr)
Get an object with proper type checking.
Definition TDirectory.h:166
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.
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.
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().
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.
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:54
Int_t GetCompressionSettings() const
Definition TFile.h:399
virtual Long64_t GetEND() const
Definition TFile.h:223
@ kDoNotDisconnect
Definition TFile.h:71
virtual void Flush()
Synchronize a file's in-memory and on-disk states.
Definition TFile.cxx:1061
virtual void MakeFree(Long64_t first, Long64_t last)
Mark unused bytes on the file.
Definition TFile.cxx:1400
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:3997
virtual void SetCacheRead(TFileCacheRead *cache, TObject *tree=0, ECacheAction action=kDisconnect)
Set a pointer to the read cache.
Definition TFile.cxx:2281
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:1219
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:438
A TFriendElement TF describes a TTree object TF in a file.
virtual const char * GetTreeName() const
Get the actual TTree name of the friend.
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()
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:57
virtual Double_t GetValue(Int_t i=0) const
Definition TLeaf.h:183
virtual void * GetValuePointer() const
Definition TLeaf.h:138
virtual Int_t GetLenType() const
Definition TLeaf.h:133
virtual void ReadValue(std::istream &, Char_t=' ')
Definition TLeaf.h:156
virtual Int_t GetMaximum() const
Definition TLeaf.h:134
virtual Int_t GetLen() const
Return the number of effective elements of this leaf, for the current entry.
Definition TLeaf.cxx:404
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:121
virtual Bool_t IncludeRange(TLeaf *)
Definition TLeaf.h:146
virtual void SetAddress(void *add=0)
Definition TLeaf.h:185
TBranch * GetBranch() const
Definition TLeaf.h:116
@ kNewValue
Set if we own the value buffer and so must delete it ourselves.
Definition TLeaf.h:96
@ kIndirectAddress
Data member is a pointer to an array of basic types.
Definition TLeaf.h:95
virtual TString GetFullName() const
Return the full name (including the parent's branch names) of the leaf.
Definition TLeaf.cxx:224
virtual Int_t GetOffset() const
Definition TLeaf.h:137
virtual void PrintValue(Int_t i=0) const
Definition TLeaf.h:184
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:822
virtual TObject * FindObject(const char *name) const
Find an object in this list using its name.
Definition TList.cxx:578
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:357
virtual void RecursiveRemove(TObject *obj)
Remove object from this collection and recursively remove the object from all other objects (and coll...
Definition TList.cxx:764
virtual void Delete(Option_t *option="")
Remove all objects from the list AND delete all heap based objects.
Definition TList.cxx:470
virtual void Clear(Option_t *option="")
Remove all objects from the list.
Definition TList.cxx:402
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.
void Add(TObject *obj)
Definition TObjArray.h:74
TObject * Last() const
Return the object in the last filled slot. Returns 0 if no entries.
virtual void Compress()
Remove empty slots from array.
Int_t GetEntries() const
Return the number of objects in array (i.e.
virtual void Clear(Option_t *option="")
Remove all objects from the array.
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.
virtual TObject * FindObject(const char *name) const
Find an object in this collection using its name.
TIterator * MakeIterator(Bool_t dir=kIterForward) const
Returns an array iterator.
virtual TObject * RemoveAt(Int_t idx)
Remove object at index idx.
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:508
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:798
virtual const char * GetName() const
Returns name of object.
Definition TObject.cxx:359
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:130
virtual void Warning(const char *method, const char *msgfmt,...) const
Issue warning message.
Definition TObject.cxx:879
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:696
virtual Bool_t InheritsFrom(const char *classname) const
Returns kTRUE if object inherits from class "classname".
Definition TObject.cxx:445
virtual void Error(const char *method, const char *msgfmt,...) const
Issue error message.
Definition TObject.cxx:893
virtual void Fatal(const char *method, const char *msgfmt,...) const
Issue fatal error message.
Definition TObject.cxx:921
virtual const char * GetTitle() const
Returns title of object.
Definition TObject.cxx:403
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:867
Principal Components Analysis (PCA)
Definition TPrincipal.h:21
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
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.
static TRefTable * GetRefTable()
Static function returning the current TRefTable.
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:31
static void * ReAlloc(void *vp, size_t size)
Reallocate (i.e.
Definition TStorage.cxx:183
Describe Streamer information for one class version.
void ForceWriteInfo(TFile *file, Bool_t force=kFALSE)
Recursively mark streamer infos for writing to a file.
Basic string class.
Definition TString.h:136
Ssiz_t Length() const
Definition TString.h:410
void ToLower()
Change string to lower-case.
Definition TString.cxx:1145
static const Ssiz_t kNPOS
Definition TString.h:269
TSubString Strip(EStripType s=kTrailing, char c=' ') const
Return a substring of self stripped at beginning and/or end.
Definition TString.cxx:1126
Double_t Atof() const
Return floating-point value contained in string.
Definition TString.cxx:2007
Ssiz_t First(char c) const
Find first occurrence of a character c.
Definition TString.cxx:519
const char * Data() const
Definition TString.h:369
Bool_t EqualTo(const char *cs, ECaseCompare cmp=kExact) const
Definition TString.h:633
TString & ReplaceAll(const TString &s1, const TString &s2)
Definition TString.h:692
@ kLeading
Definition TString.h:267
@ kTrailing
Definition TString.h:267
@ kIgnoreCase
Definition TString.h:268
Ssiz_t Last(char c) const
Find last occurrence of a character c.
Definition TString.cxx:912
TObjArray * Tokenize(const TString &delim) const
This function is used to isolate sequential tokens in a TString.
Definition TString.cxx:2217
Bool_t IsNull() const
Definition TString.h:407
TString & Remove(Ssiz_t pos)
Definition TString.h:673
TString & Append(const char *cs)
Definition TString.h:564
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:2331
void Form(const char *fmt,...)
Formats a string using a printf style format descriptor.
Definition TString.cxx:2309
Bool_t Contains(const char *pat, ECaseCompare cmp=kExact) const
Definition TString.h:624
Ssiz_t Index(const char *pat, Ssiz_t i=0, ECaseCompare cmp=kExact) const
Definition TString.h:639
void SetHistFillColor(Color_t color=1)
Definition TStyle.h:362
Color_t GetHistLineColor() const
Definition TStyle.h:224
Bool_t IsReading() const
Definition TStyle.h:282
void SetHistLineStyle(Style_t styl=0)
Definition TStyle.h:365
Style_t GetHistFillStyle() const
Definition TStyle.h:225
Color_t GetHistFillColor() const
Definition TStyle.h:223
void SetHistLineColor(Color_t color=1)
Definition TStyle.h:363
Style_t GetHistLineStyle() const
Definition TStyle.h:226
void SetHistFillStyle(Style_t styl=0)
Definition TStyle.h:364
Width_t GetHistLineWidth() const
Definition TStyle.h:227
void SetHistLineWidth(Width_t width=1)
Definition TStyle.h:366
A zero length substring is legal.
Definition TString.h:82
TString & String()
Definition TString.h:121
virtual const char * Getenv(const char *env)
Get environment variable.
Definition TSystem.cxx:1661
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:1294
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:32
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...
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:149
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:150
void SetAutoCreated(Bool_t val)
Definition TTreeCache.h:164
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:...
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()
const char * GetWarning() const
void SetCacheSize(Int_t size)
Set the TFile cache size to be used.
Bool_t NeedConversion()
Iterator on all the leaves in a TTree and its friend.
Definition TTree.h:665
TObject * Next()
Go the next friend element.
Definition TTree.cxx:9748
TTree * fTree
tree being iterated
Definition TTree.h:668
Option_t * GetOption() const
Returns the object option stored in the list.
Definition TTree.cxx:9787
TIterator & operator=(const TIterator &rhs)
Overridden assignment operator. Does NOT copy the 'cursor' location!
Definition TTree.cxx:9725
TIterator * fLeafIter
current leaf sub-iterator.
Definition TTree.h:669
TIterator * fTreeIter
current tree sub-iterator.
Definition TTree.h:670
Bool_t fDirection
iteration direction
Definition TTree.h:671
Helper class to iterate over cluster of baskets.
Definition TTree.h:267
Long64_t GetEstimatedClusterSize()
Estimate the cluster size.
Definition TTree.cxx:601
Long64_t Previous()
Move on to the previous cluster and return the starting entry of this previous cluster.
Definition TTree.cxx:684
Long64_t Next()
Move on to the next cluster and return the starting entry of this next cluster.
Definition TTree.cxx:640
Long64_t GetNextEntry()
Definition TTree.h:304
TClusterIterator(TTree *tree, Long64_t firstEntry)
Regular constructor.
Definition TTree.cxx:550
Helper class to prevent infinite recursion in the usage of TTree Friends.
Definition TTree.h:185
TFriendLock & operator=(const TFriendLock &)
Assignment operator.
Definition TTree.cxx:520
TFriendLock(const TFriendLock &)
Copy constructor.
Definition TTree.cxx:510
UInt_t fMethodBit
Definition TTree.h:189
TTree * fTree
Definition TTree.h:188
~TFriendLock()
Restore the state of tree the same as before we set the lock.
Definition TTree.cxx:533
Bool_t fPrevious
Definition TTree.h:190
A TTree represents a columnar dataset.
Definition TTree.h:79
virtual Int_t Fill()
Fill all branches.
Definition TTree.cxx:4590
virtual TFriendElement * AddFriend(const char *treename, const char *filename="")
Add a TFriendElement to the list of friends.
Definition TTree.cxx:1321
TBranchRef * fBranchRef
Branch supporting the TRefTable (if any)
Definition TTree.h:133
virtual Int_t AddBranchToCache(const char *bname, Bool_t subbranches=kFALSE)
Add branch with name bname to the Tree cache.
Definition TTree.cxx:1049
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:4828
@ kSplitCollectionOfPointers
Definition TTree.h:263
virtual TBranch * GetBranch(const char *name)
Return pointer to the branch with the given name in this tree or its friends.
Definition TTree.cxx:5275
static Int_t GetBranchStyle()
Static function returning the current branch style.
Definition TTree.cxx:5375
TList * fFriends
pointer to list of friend elements
Definition TTree.h:127
UInt_t fFriendLockStatus
! Record which method is locking the friend recursion
Definition TTree.h:134
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:6079
Long64_t fTotBytes
Total number of bytes in all branches before compression.
Definition TTree.h:86
Int_t fMaxClusterRange
! Memory allocated for the cluster range.
Definition TTree.h:96
virtual void Show(Long64_t entry=-1, Int_t lenmax=20)
Print values of all active leaves for entry.
Definition TTree.cxx:9318
TEventList * fEventList
! Pointer to event selection list (if one)
Definition TTree.h:122
virtual Long64_t GetAutoSave() const
Definition TTree.h:445
Long64_t GetCacheAutoSize(Bool_t withDefault=kFALSE)
Used for automatic sizing of the cache.
Definition TTree.cxx:5387
virtual Int_t StopCacheLearningPhase()
Stop the cache learning phase.
Definition TTree.cxx:9407
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:141
virtual void SetCircular(Long64_t maxEntries)
Enable/Disable circularity for this tree.
Definition TTree.cxx:8851
Long64_t fSavedBytes
Number of autosaved bytes.
Definition TTree.h:88
Long64_t GetMedianClusterSize()
Estimate the median cluster size for the TTree.
Definition TTree.cxx:8264
virtual TClusterIterator GetClusterIterator(Long64_t firstentry)
Return an iterator over the cluster of baskets starting at firstentry.
Definition TTree.cxx:5447
virtual void ResetBranchAddress(TBranch *)
Tell all of our branches to set their addresses to zero.
Definition TTree.cxx:8037
char GetNewlineValue(std::istream &inputStream)
Determine which newline this file is using.
Definition TTree.cxx:7564
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:2855
TIOFeatures fIOFeatures
IO features to define for newly-written baskets and branches.
Definition TTree.h:114
virtual Long64_t GetEntryNumberWithIndex(Long64_t major, Long64_t minor=0) const
Return entry number corresponding to major and minor number.
Definition TTree.cxx:5891
Long64_t fDebugMin
! First entry number to debug
Definition TTree.h:112
virtual Long64_t SetEntries(Long64_t n=-1)
Change number of entries in the tree.
Definition TTree.cxx:8970
virtual TObjArray * GetListOfLeaves()
Definition TTree.h:486
Bool_t fCacheDoClusterPrefetch
! true if cache is prefetching whole clusters
Definition TTree.h:137
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:2062
virtual TBranch * BranchRef()
Build the optional branch supporting the TRefTable.
Definition TTree.cxx:2316
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:6993
TFile * GetCurrentFile() const
Return pointer to the current file.
Definition TTree.cxx:5459
TList * fAliases
List of aliases for expressions based on the tree branches.
Definition TTree.h:121
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:3704
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:5110
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:5060
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:8671
Long64_t * fClusterRangeEnd
[fNClusterRange] Last entry of a cluster range.
Definition TTree.h:103
std::atomic< Long64_t > fIMTZipBytes
! Zip bytes for the IMT flush baskets.
Definition TTree.h:158
void UseCurrentStyle()
Replace current attributes by current style.
Definition TTree.cxx:9647
TVirtualTreePlayer * GetPlayer()
Load the TTreePlayer (if not already done).
Definition TTree.cxx:6286
virtual Long64_t ReadStream(std::istream &inputStream, const char *branchDescriptor="", char delimiter=' ')
Create or simply read branches from an input stream.
Definition TTree.cxx:7591
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:8887
Int_t fScanField
Number of runs before prompting in Scan.
Definition TTree.h:92
virtual ~TTree()
Destructor.
Definition TTree.cxx:910
virtual TTree * GetFriend(const char *) const
Return a pointer to the TTree friend whose name or alias is friendname.
Definition TTree.cxx:5956
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:3519
virtual Int_t SetBranchAddress(const char *bname, void *add, TBranch **ptr=0)
Change branch address, dealing with clone trees properly.
Definition TTree.cxx:8349
virtual Double_t GetMaximum(const char *columname)
Return maximum of column with name columname.
Definition TTree.cxx:6216
virtual Long64_t GetEntryNumberWithBestIndex(Long64_t major, Long64_t minor=0) const
Return entry number corresponding to major and minor number.
Definition TTree.cxx:5871
static void SetMaxTreeSize(Long64_t maxsize=100000000000LL)
Set the maximum size in bytes of a Tree file (static function).
Definition TTree.cxx:9156
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:2400
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:9635
Int_t fNClusterRange
Number of Cluster range in addition to the one defined by 'AutoFlush'.
Definition TTree.h:95
virtual void PrintCacheStats(Option_t *option="") const
Print statistics about the TreeCache for this tree.
Definition TTree.cxx:7351
virtual Int_t BuildIndex(const char *majorname, const char *minorname="0")
Build a Tree Index (default is TTreeIndex).
Definition TTree.cxx:2625
TVirtualTreePlayer * fPlayer
! Pointer to current Tree player
Definition TTree.h:131
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:9136
TObjArray fBranches
List of Branches.
Definition TTree.h:119
TDirectory * GetDirectory() const
Definition TTree.h:459
TTreeCache * GetReadCache(TFile *file) const
Find and return the TTreeCache registered with the file and which may contain branches for us.
Definition TTree.cxx:6299
Bool_t fCacheUserSet
! true if the cache setting was explicitly given by user
Definition TTree.h:138
Long64_t fEntries
Number of entries.
Definition TTree.h:84
virtual TFile * ChangeFile(TFile *file)
Called by TTree::Fill() when file has reached its maximum fgMaxTreeSize.
Definition TTree.cxx:2737
virtual Bool_t GetBranchStatus(const char *branchname) const
Return status of branch with name branchname.
Definition TTree.cxx:5360
virtual TEntryList * GetEntryList()
Returns the entry list assigned to this tree.
Definition TTree.cxx:5835
virtual void SetWeight(Double_t w=1, Option_t *option="")
Set tree weight.
Definition TTree.cxx:9307
void InitializeBranchLists(bool checkLeafCount)
Divides the top-level branches into two vectors: (i) branches to be processed sequentially and (ii) b...
Definition TTree.cxx:5762
Long64_t * fClusterSize
[fNClusterRange] Number of entries in each cluster for a given range.
Definition TTree.h:104
Long64_t fFlushedBytes
Number of auto-flushed bytes.
Definition TTree.h:89
virtual void SetPerfStats(TVirtualPerfStats *perf)
Set perf stats.
Definition TTree.cxx:9262
std::atomic< Long64_t > fIMTTotBytes
! Total bytes for the IMT flush baskets
Definition TTree.h:157
virtual void SetCacheLearnEntries(Int_t n=10)
Interface to TTreeCache to set the number of entries for the learning phase.
Definition TTree.cxx:8824
TEntryList * fEntryList
! Pointer to event selection list (if one)
Definition TTree.h:123
virtual TVirtualIndex * GetTreeIndex() const
Definition TTree.h:515
TList * fExternalFriends
! List of TFriendsElement pointing to us and need to be notified of LoadTree. Content not owned.
Definition TTree.h:128
virtual Long64_t Merge(TCollection *list, Option_t *option="")
Merge the trees in the TList into this tree.
Definition TTree.cxx:6871
virtual void SetMaxVirtualSize(Long64_t size=0)
Definition TTree.h:622
virtual void DropBaskets()
Remove some baskets from memory.
Definition TTree.cxx:4504
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:8306
Long64_t fMaxEntryLoop
Maximum number of entries to process.
Definition TTree.h:98
virtual void SetDirectory(TDirectory *dir)
Change the tree's directory.
Definition TTree.cxx:8925
void SortBranchesByTime()
Sorts top-level branches by the last average task time recorded per branch.
Definition TTree.cxx:5815
virtual TBranchRef * GetBranchRef() const
Definition TTree.h:447
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:7431
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:1624
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:9028
void MoveReadCache(TFile *src, TDirectory *dir)
Move a cache from a file to the current file in dir.
Definition TTree.cxx:6964
Long64_t fAutoFlush
Auto-flush tree when fAutoFlush entries written or -fAutoFlush (compressed) bytes produced.
Definition TTree.h:101
Int_t fUpdate
Update frequency for EntryLoop.
Definition TTree.h:93
virtual void ResetAfterMerge(TFileMergeInfo *)
Resets the state of this TTree after a merge (keep the customization but forget the data).
Definition TTree.cxx:8006
virtual void CopyAddresses(TTree *, Bool_t undo=kFALSE)
Set branch addresses of passed tree equal to ours.
Definition TTree.cxx:3284
virtual Long64_t GetEntries() const
Definition TTree.h:460
virtual void SetEstimate(Long64_t nentries=1000000)
Set number of entries to estimate variable limits.
Definition TTree.cxx:9069
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:6063
Int_t fTimerInterval
Timer interval in milliseconds.
Definition TTree.h:91
Int_t fDebug
! Debug level
Definition TTree.h:111
virtual Long64_t AutoSave(Option_t *option="")
AutoSave tree header every fAutoSave bytes.
Definition TTree.cxx:1489
virtual Long64_t GetEntryNumber(Long64_t entry) const
Return entry number corresponding to entry.
Definition TTree.cxx:5846
virtual TTree * CloneTree(Long64_t nentries=-1, Option_t *option="")
Create a clone of this tree and copy nentries.
Definition TTree.cxx:3124
Int_t fFileNumber
! current file number (if file extensions)
Definition TTree.h:116
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:6176
virtual Long64_t GetZipBytes() const
Definition TTree.h:542
TObjArray fLeaves
Direct pointers to individual branch leaves.
Definition TTree.h:120
virtual void Reset(Option_t *option="")
Reset baskets, buffers and entries count in all branches and leaves.
Definition TTree.cxx:7975
virtual void Print(Option_t *option="") const
Print a summary of the tree contents.
Definition TTree.cxx:7200
virtual void KeepCircular()
Keep a maximum of fMaxEntries in memory.
Definition TTree.cxx:6396
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:3804
virtual Bool_t SetAlias(const char *aliasName, const char *aliasFormula)
Set a tree variable alias.
Definition TTree.cxx:8108
Long64_t fMaxVirtualSize
Maximum total size of buffers kept in memory.
Definition TTree.h:99
virtual Long64_t GetTotBytes() const
Definition TTree.h:513
virtual void SetObject(const char *name, const char *title)
Change the name and title of this tree.
Definition TTree.cxx:9193
TVirtualPerfStats * fPerfStats
! pointer to the current perf stats object
Definition TTree.h:129
Double_t fWeight
Tree weight (see TTree::SetWeight)
Definition TTree.h:90
std::vector< TBranch * > fSeqBranches
! Branches to be processed sequentially when IMT is on
Definition TTree.h:142
Bool_t EnableCache()
Enable the TTreeCache unless explicitly disabled for this TTree by a prior call to SetCacheSize(0).
Definition TTree.cxx:2673
Long64_t fDebugMax
! Last entry number to debug
Definition TTree.h:113
Int_t fDefaultEntryOffsetLen
Initial Length of fEntryOffset table in the basket buffers.
Definition TTree.h:94
TTree()
Default constructor and I/O constructor.
Definition TTree.cxx:727
Long64_t fAutoSave
Autosave tree when fAutoSave entries written or -fAutoSave (compressed) bytes produced.
Definition TTree.h:100
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:350
virtual void SetDefaultEntryOffsetLen(Int_t newdefault, Bool_t updateExisting=kFALSE)
Update the default value for the branch's fEntryOffsetLen.
Definition TTree.cxx:8899
std::atomic< UInt_t > fAllocationCount
indicates basket should be resized to exact memory usage, but causes significant
Definition TTree.h:149
virtual Int_t GetEntryWithIndex(Int_t major, Int_t minor=0)
Read entry corresponding to major and minor number.
Definition TTree.cxx:5908
static TTree * MergeTrees(TList *list, Option_t *option="")
Static function merging the trees in the TList into a new tree.
Definition TTree.cxx:6832
virtual Long64_t GetReadEntry() const
Definition TTree.h:506
virtual TObjArray * GetListOfBranches()
Definition TTree.h:485
virtual void SetParallelUnzip(Bool_t opt=kTRUE, Float_t RelSize=-1)
Enable or disable parallel unzipping of Tree buffers.
Definition TTree.cxx:9224
Long64_t fZipBytes
Total number of bytes in all branches after compression.
Definition TTree.h:87
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:7857
virtual TTree * GetTree() const
Definition TTree.h:514
TBuffer * fTransientBuffer
! Pointer to the current transient buffer.
Definition TTree.h:135
Bool_t fIMTEnabled
! true if implicit multi-threading is enabled for this tree
Definition TTree.h:139
virtual void SetEntryList(TEntryList *list, Option_t *opt="")
Set an EntryList.
Definition TTree.cxx:9005
virtual Int_t DropBranchFromCache(const char *bname, Bool_t subbranches=kFALSE)
Remove the branch with name 'bname' from the Tree cache.
Definition TTree.cxx:1132
virtual void AddZipBytes(Int_t zip)
Definition TTree.h:329
virtual Long64_t LoadTree(Long64_t entry)
Set current entry.
Definition TTree.cxx:6454
virtual Long64_t ReadFile(const char *filename, const char *branchDescriptor="", char delimiter=' ')
Create or simply read branches from filename.
Definition TTree.cxx:7545
virtual const char * GetAlias(const char *aliasName) const
Returns the expanded value of the alias. Search in the friends if any.
Definition TTree.cxx:5207
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:9089
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:5618
virtual TBasket * CreateBasket(TBranch *)
Create a basket for this tree and given branch.
Definition TTree.cxx:3716
TList * fUserInfo
pointer to a list of user objects associated to this Tree
Definition TTree.h:130
virtual Double_t GetMinimum(const char *columname)
Return minimum of column with name columname.
Definition TTree.cxx:6256
virtual void RemoveFriend(TTree *)
Remove a friend from the list of friends.
Definition TTree.cxx:7949
virtual Long64_t GetEntriesFast() const
Definition TTree.h:462
virtual TList * GetUserInfo()
Return a pointer to the list containing user objects associated to this tree.
Definition TTree.cxx:6337
Long64_t fChainOffset
! Offset of 1st entry of this Tree in a TChain
Definition TTree.h:106
@ kOnlyFlushAtCluster
If set, the branch's buffers will grow until an event cluster boundary is hit, guaranteeing a basket ...
Definition TTree.h:253
@ kEntriesReshuffled
If set, signals that this TTree is the output of the processing of another TTree, and the entries are...
Definition TTree.h:258
@ kCircular
Definition TTree.h:249
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:5492
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:7494
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:2392
virtual void SetBasketSize(const char *bname, Int_t buffsize=16000)
Set a branch's basket size.
Definition TTree.cxx:8322
static void SetBranchStyle(Int_t style=1)
Set the current branch style.
Definition TTree.cxx:8629
void ImportClusterRanges(TTree *fromtree)
Appends the cluster range information stored in 'fromtree' to this tree, including the value of fAuto...
Definition TTree.cxx:6353
Long64_t fEstimate
Number of entries to estimate histogram limits.
Definition TTree.h:102
Int_t FlushBasketsImpl() const
Internal implementation of the FlushBaskets algorithm.
Definition TTree.cxx:5127
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:6538
TVirtualIndex * fTreeIndex
Pointer to the tree Index (if any)
Definition TTree.h:126
virtual void Browse(TBrowser *)
Browse content of the TTree.
Definition TTree.cxx:2597
TObject * fNotify
! Object to be notified when loading a Tree
Definition TTree.h:117
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:1543
Long64_t fCacheSize
! Maximum size of file buffers
Definition TTree.h:105
TList * fClones
! List of cloned trees which share our addresses
Definition TTree.h:132
std::atomic< Long64_t > fTotalBuffers
! Total number of bytes in branch buffers
Definition TTree.h:108
Bool_t fCacheDoAutoInit
! true if cache auto creation or resize check is needed
Definition TTree.h:136
virtual Int_t MakeSelector(const char *selector=0, Option_t *option="")
Generate skeleton selector class for this tree.
Definition TTree.cxx:6803
@ kFindBranch
Definition TTree.h:209
@ kFindLeaf
Definition TTree.h:210
@ kGetEntryWithIndex
Definition TTree.h:214
@ kPrint
Definition TTree.h:219
@ kGetFriend
Definition TTree.h:215
@ kGetBranch
Definition TTree.h:212
@ kSetBranchStatus
Definition TTree.h:221
@ kLoadTree
Definition TTree.h:218
@ kGetEntry
Definition TTree.h:213
@ kGetLeaf
Definition TTree.h:217
@ kRemoveFriend
Definition TTree.h:220
@ kGetFriendAlias
Definition TTree.h:216
@ kGetAlias
Definition TTree.h:211
virtual void Draw(Option_t *opt)
Default Draw method for all objects.
Definition TTree.h:428
virtual Int_t MakeClass(const char *classname=0, Option_t *option="")
Generate a skeleton analysis class for this tree.
Definition TTree.cxx:6588
virtual void SetTreeIndex(TVirtualIndex *index)
The current TreeIndex is replaced by the new index.
Definition TTree.cxx:9279
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:7038
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:7479
virtual Int_t SetCacheEntryRange(Long64_t first, Long64_t last)
interface to TTreeCache to set the cache entry range
Definition TTree.cxx:8790
static Long64_t GetMaxTreeSize()
Static function which returns the tree file size limit in bytes.
Definition TTree.cxx:6246
Int_t SetBranchAddressImp(TBranch *branch, void *addr, TBranch **ptr)
Change branch address, dealing with clone trees properly.
Definition TTree.cxx:8409
Long64_t fMaxEntries
Maximum number of entries in case of circular buffers.
Definition TTree.h:97
virtual void DropBuffers(Int_t nbytes)
Drop branch buffers to accommodate nbytes below MaxVirtualsize.
Definition TTree.cxx:4517
virtual void SetName(const char *name)
Change the name of this tree.
Definition TTree.cxx:9164
virtual void Delete(Option_t *option="")
Delete this tree from memory or/and disk.
Definition TTree.cxx:3732
virtual TList * GetListOfFriends() const
Definition TTree.h:487
virtual void Refresh()
Refresh contents of this tree and its branches from the current status on disk.
Definition TTree.cxx:7888
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:8163
static Long64_t fgMaxTreeSize
Maximum size of a file containing a Tree.
Definition TTree.h:152
Long64_t fReadEntry
! Number of the entry being processed
Definition TTree.h:107
TArrayD fIndexValues
Sorted index values.
Definition TTree.h:124
void MarkEventCluster()
Mark the previous event as being at the end of the event cluster.
Definition TTree.cxx:8225
virtual Int_t MakeCode(const char *filename=0)
Generate a skeleton function for this tree.
Definition TTree.cxx:6621
UInt_t fNEntriesSinceSorting
! Number of entries processed since the last re-sorting of branches
Definition TTree.h:140
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:6749
virtual void SetFileNumber(Int_t number=0)
Set fFileNumber to number.
Definition TTree.cxx:9112
virtual TLeaf * FindLeaf(const char *name)
Find leaf..
Definition TTree.cxx:4900
virtual void StartViewer()
Start the TTreeViewer on this tree.
Definition TTree.cxx:9392
Int_t GetMakeClass() const
Definition TTree.h:492
TDirectory * fDirectory
! Pointer to directory holding this tree
Definition TTree.h:118
@ kNeedEnableDecomposedObj
Definition TTree.h:241
@ kClassMismatch
Definition TTree.h:234
@ kVoidPtr
Definition TTree.h:239
@ kMatchConversionCollection
Definition TTree.h:237
@ kMissingCompiledCollectionProxy
Definition TTree.h:232
@ kMismatch
Definition TTree.h:233
@ kMatchConversion
Definition TTree.h:236
@ kInternalError
Definition TTree.h:231
@ kMatch
Definition TTree.h:235
@ kMissingBranch
Definition TTree.h:230
@ kMakeClass
Definition TTree.h:238
static Int_t fgBranchStyle
Old/New branch style.
Definition TTree.h:151
virtual void ResetBranchAddresses()
Tell all of our branches to drop their current objects and allocate new ones.
Definition TTree.cxx:8047
Int_t fNfill
! Local for EntryLoop
Definition TTree.h:110
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:7929
TArrayI fIndex
Index of sorted values.
Definition TTree.h:125
virtual Int_t SetCacheSize(Long64_t cachesize=-1)
Set maximum size of the file cache .
Definition TTree.cxx:8645
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:1209
virtual void SetBranchStatus(const char *bname, Bool_t status=1, UInt_t *found=0)
Set branch status to Process or DoNotProcess.
Definition TTree.cxx:8498
TBuffer * GetTransientBuffer(Int_t size)
Returns the transient buffer currently used by this TTree for reading/writing baskets.
Definition TTree.cxx:1027
ROOT::TIOFeatures GetIOFeatures() const
Returns the current set of IO settings.
Definition TTree.cxx:6055
virtual const char * GetFriendAlias(TTree *) const
If the 'tree' is a friend, this method returns its alias name.
Definition TTree.cxx:6013
virtual Bool_t Notify()
Function called when loading a new class library.
Definition TTree.cxx:7014
virtual void RemoveExternalFriend(TFriendElement *)
Removes external friend.
Definition TTree.cxx:7940
Bool_t MemoryFull(Int_t nbytes)
Check if adding nbytes to memory we are still below MaxVirtualsize.
Definition TTree.cxx:6818
Int_t fPacketSize
! Number of entries in one packet for parallel root
Definition TTree.h:109
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:9686
TStreamerInfo * BuildStreamerInfo(TClass *cl, void *pointer=0, Bool_t canOptimize=kTRUE)
Build StreamerInfo for class cl.
Definition TTree.cxx:2640
virtual TBranch * BranchImpArr(const char *branchname, EDataType datatype, std::size_t N, void *addobj, Int_t bufsize, Int_t splitlevel)
Definition TTree.cxx:1720
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:8066
Bool_t fIMTFlush
! True if we are doing a multithreaded flush.
Definition TTree.h:156
virtual void AddTotBytes(Int_t tot)
Definition TTree.h:328
Int_t fMakeClass
! not zero when processing code generated by MakeClass
Definition TTree.h:115
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:6432
static constexpr Long64_t kMaxEntries
Definition TTree.h:226
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:7181
virtual Long64_t GetAutoFlush() const
Definition TTree.h:444
virtual EDataType GetType() const =0
virtual TClass * GetValueClass() const =0
virtual Bool_t HasPointers() const =0
Abstract interface for Tree Index.
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
tbb::task_arena is an alias of tbb::interface7::task_arena, which doesn't allow to forward declare tb...
Bool_t IsImplicitMTEnabled()
Returns true if the implicit multi-threading in ROOT is enabled.
Definition TROOT.cxx:556
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.
EFromHumanReadableSize FromHumanReadableSize(std::string_view str, T &value)
Convert strings like the following into byte counts 5MB, 5 MB, 5M, 3.7GB, 123b, 456kB,...
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
Double_t Median(Long64_t n, const T *a, const Double_t *w=0, Long64_t *work=0)
Return the median of the array a where each entry i has weight w[i] .
Definition TMath.h:1247
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
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
th1 Draw()
auto * m
Definition textangle.C:8
auto * l
Definition textangle.C:4