Logo ROOT   6.16/01
Reference Guide
TTree.cxx
Go to the documentation of this file.
1// @(#)root/tree:$Id$
2// Author: Rene Brun 12/01/96
3
4/*************************************************************************
5 * Copyright (C) 1995-2000, Rene Brun and Fons Rademakers. *
6 * All rights reserved. *
7 * *
8 * For the licensing terms see $ROOTSYS/LICENSE. *
9 * For the list of contributors see $ROOTSYS/README/CREDITS. *
10 *************************************************************************/
11/**
12 \defgroup tree Tree Library
13
14 To store large quantities of same-class objects, ROOT provides the TTree and
15 TNtuple classes. The TTree class is optimized to
16 reduce disk space and enhance access speed. A TNtuple is a TTree that is limited
17 to only hold floating-point numbers; a TTree on the other hand can hold all kind
18 of data, such as objects or arrays in addition to all the simple types.
19
20*/
21
22/** \class TTree
23\ingroup tree
24
25A TTree object has a header with a name and a title.
26
27It consists of a list of independent branches (TBranch). Each branch has its own
28definition and list of buffers. Branch buffers may be automatically written to
29disk or kept in memory until the Tree attribute `fMaxVirtualSize` is reached.
30Variables of one branch are written to the same buffer. A branch buffer is
31automatically compressed if the file compression attribute is set (default).
32
33Branches may be written to different files (see TBranch::SetFile).
34
35The ROOT user can decide to make one single branch and serialize one object into
36one single I/O buffer or to make several branches. Making one single branch and
37one single buffer can be the right choice when one wants to process only a subset
38of all entries in the tree. (you know for example the list of entry numbers you
39want to process). Making several branches is particularly interesting in the
40data analysis phase, when one wants to histogram some attributes of an object
41(entry) without reading all the attributes.
42~~~ {.cpp}
43 TTree *tree = new TTree(name, title)
44~~~
45Creates a Tree with name and title.
46
47Various kinds of branches can be added to a tree:
48
49- simple structures or list of variables. (may be for C or Fortran structures)
50- any object (inheriting from TObject). (we expect this option be the most frequent)
51- a ClonesArray. (a specialized object for collections of same class objects)
52
53
54## Case A
55
56~~~ {.cpp}
57 TBranch *branch = tree->Branch(branchname, address, leaflist, bufsize)
58~~~
59- address is the address of the first item of a structure
60- leaflist is the concatenation of all the variable names and types
61 separated by a colon character :
62 The variable name and the variable type are separated by a
63 slash (/). The variable type must be 1 character. (Characters
64 after the first are legal and will be appended to the visible
65 name of the leaf, but have no effect.) If no type is given, the
66 type of the variable is assumed to be the same as the previous
67 variable. If the first variable does not have a type, it is
68 assumed of type F by default. The list of currently supported
69 types is given below:
70 - `C` : a character string terminated by the 0 character
71 - `B` : an 8 bit signed integer (`Char_t`)
72 - `b` : an 8 bit unsigned integer (`UChar_t`)
73 - `S` : a 16 bit signed integer (`Short_t`)
74 - `s` : a 16 bit unsigned integer (`UShort_t`)
75 - `I` : a 32 bit signed integer (`Int_t`)
76 - `i` : a 32 bit unsigned integer (`UInt_t`)
77 - `F` : a 32 bit floating point (`Float_t`)
78 - `D` : a 64 bit floating point (`Double_t`)
79 - `L` : a 64 bit signed integer (`Long64_t`)
80 - `l` : a 64 bit unsigned integer (`ULong64_t`)
81 - `O` : [the letter `o`, not a zero] a boolean (`Bool_t`)
82- If the address points to a single numerical variable, the leaflist is optional:
83 int value;
84 `tree->Branch(branchname, &value);`
85- If the address points to more than one numerical variable, we strongly recommend
86 that the variable be sorted in decreasing order of size. Any other order will
87 result in a non-portable (even between CINT and compiled code on the platform)
88 TTree (i.e. you will not be able to read it back on a platform with a different
89 padding strategy).
90
91
92## Case B
93
94~~~ {.cpp}
95 TBranch *branch = tree->Branch(branchname, &p_object, bufsize, splitlevel)
96 TBranch *branch = tree->Branch(branchname, className, &p_object, bufsize, splitlevel)
97~~~
98- p_object is a pointer to an object.
99- If className is not specified, Branch uses the type of p_object to determine the
100 type of the object.
101- If className is used to specify explicitly the object type, the className must
102 be of a type related to the one pointed to by the pointer. It should be either
103 a parent or derived class.
104- if splitlevel=0, the object is serialized in the branch buffer.
105- if splitlevel=1, this branch will automatically be split
106 into subbranches, with one subbranch for each data member or object
107 of the object itself. In case the object member is a TClonesArray,
108 the mechanism described in case C is applied to this array.
109- if splitlevel=2 ,this branch will automatically be split
110 into subbranches, with one subbranch for each data member or object
111 of the object itself. In case the object member is a TClonesArray,
112 it is processed as a TObject*, only one branch.
113
114Note: The pointer whose address is passed to TTree::Branch must not
115 be destroyed (i.e. go out of scope) until the TTree is deleted or
116 TTree::ResetBranchAddress is called.
117
118Note: The pointer p_object must be initialized before calling TTree::Branch
119- Do either:
120~~~ {.cpp}
121 MyDataClass* p_object = 0;
122 tree->Branch(branchname, &p_object);
123~~~
124- Or:
125~~~ {.cpp}
126 MyDataClass* p_object = new MyDataClass;
127 tree->Branch(branchname, &p_object);
128~~~
129Whether the pointer is set to zero or not, the ownership of the object
130is not taken over by the TTree. I.e. even though an object will be allocated
131by TTree::Branch if the pointer p_object is zero, the object will <b>not</b>
132be deleted when the TTree is deleted.
133
134
135## Case C
136
137~~~ {.cpp}
138 MyClass object;
139 TBranch *branch = tree->Branch(branchname, &object, bufsize, splitlevel)
140~~~
141Note: The 2nd parameter must be the address of a valid object.
142 The object must not be destroyed (i.e. be deleted) until the TTree
143 is deleted or TTree::ResetBranchAddress is called.
144
145- if splitlevel=0, the object is serialized in the branch buffer.
146- if splitlevel=1 (default), this branch will automatically be split
147 into subbranches, with one subbranch for each data member or object
148 of the object itself. In case the object member is a TClonesArray,
149 the mechanism described in case C is applied to this array.
150- if splitlevel=2 ,this branch will automatically be split
151 into subbranches, with one subbranch for each data member or object
152 of the object itself. In case the object member is a TClonesArray,
153 it is processed as a TObject*, only one branch.
154
155
156## Case D
157
158~~~ {.cpp}
159 TBranch *branch = tree->Branch(branchname,clonesarray, bufsize, splitlevel)
160 clonesarray is the address of a pointer to a TClonesArray.
161~~~
162The TClonesArray is a direct access list of objects of the same class.
163For example, if the TClonesArray is an array of TTrack objects,
164this function will create one subbranch for each data member of
165the object TTrack.
166
167
168## Case E
169
170~~~ {.cpp}
171 TBranch *branch = tree->Branch( branchname, STLcollection, buffsize, splitlevel);
172~~~
173STLcollection is the address of a pointer to std::vector, std::list,
174std::deque, std::set or std::multiset containing pointers to objects.
175If the splitlevel is a value bigger than 100 (TTree::kSplitCollectionOfPointers)
176then the collection will be written in split mode, e.g. if it contains objects of
177any types deriving from TTrack this function will sort the objects
178based on their type and store them in separate branches in split
179mode.
180~~~ {.cpp}
181 branch->SetAddress(Void *address)
182~~~
183In case of dynamic structures changing with each entry for example, one must
184redefine the branch address before filling the branch again.
185This is done via the TBranch::SetAddress member function.
186~~~ {.cpp}
187 tree->Fill()
188~~~
189loops on all defined branches and for each branch invokes the Fill function.
190
191See also the class TNtuple (a simple Tree with branches of floats)
192and the class TNtupleD (a simple Tree with branches of doubles)
193
194## Adding a Branch to an Existing Tree
195
196You may want to add a branch to an existing tree. For example,
197if one variable in the tree was computed with a certain algorithm,
198you may want to try another algorithm and compare the results.
199One solution is to add a new branch, fill it, and save the tree.
200The code below adds a simple branch to an existing tree.
201Note the kOverwrite option in the Write method, it overwrites the
202existing tree. If it is not specified, two copies of the tree headers
203are saved.
204~~~ {.cpp}
205 void tree3AddBranch() {
206 TFile f("tree3.root", "update");
207
208 Float_t new_v;
209 TTree *t3 = (TTree*)f->Get("t3");
210 TBranch *newBranch = t3->Branch("new_v", &new_v, "new_v/F");
211
212 Long64_t nentries = t3->GetEntries(); // read the number of entries in the t3
213
214 for (Long64_t i = 0; i < nentries; i++) {
215 new_v= gRandom->Gaus(0, 1);
216 newBranch->Fill();
217 }
218
219 t3->Write("", TObject::kOverwrite); // save only the new version of the tree
220 }
221~~~
222Adding a branch is often not possible because the tree is in a read-only
223file and you do not have permission to save the modified tree with the
224new branch. Even if you do have the permission, you risk losing the
225original tree with an unsuccessful attempt to save the modification.
226Since trees are usually large, adding a branch could extend it over the
2272GB limit. In this case, the attempt to write the tree fails, and the
228original data is erased.
229In addition, adding a branch to a tree enlarges the tree and increases
230the amount of memory needed to read an entry, and therefore decreases
231the performance.
232
233For these reasons, ROOT offers the concept of friends for trees (and chains).
234We encourage you to use TTree::AddFriend rather than adding a branch manually.
235
236Begin_Macro
237../../../tutorials/tree/tree.C
238End_Macro
239
240~~~ {.cpp}
241 // A simple example with histograms and a tree
242 //
243 // This program creates :
244 // - a one dimensional histogram
245 // - a two dimensional histogram
246 // - a profile histogram
247 // - a tree
248 //
249 // These objects are filled with some random numbers and saved on a file.
250
251 #include "TFile.h"
252 #include "TH1.h"
253 #include "TH2.h"
254 #include "TProfile.h"
255 #include "TRandom.h"
256 #include "TTree.h"
257
258 //__________________________________________________________________________
259 main(int argc, char **argv)
260 {
261 // Create a new ROOT binary machine independent file.
262 // Note that this file may contain any kind of ROOT objects, histograms,trees
263 // pictures, graphics objects, detector geometries, tracks, events, etc..
264 // This file is now becoming the current directory.
265 TFile hfile("htree.root","RECREATE","Demo ROOT file with histograms & trees");
266
267 // Create some histograms and a profile histogram
268 TH1F *hpx = new TH1F("hpx","This is the px distribution",100,-4,4);
269 TH2F *hpxpy = new TH2F("hpxpy","py ps px",40,-4,4,40,-4,4);
270 TProfile *hprof = new TProfile("hprof","Profile of pz versus px",100,-4,4,0,20);
271
272 // Define some simple structures
273 typedef struct {Float_t x,y,z;} POINT;
274 typedef struct {
275 Int_t ntrack,nseg,nvertex;
276 UInt_t flag;
277 Float_t temperature;
278 } EVENTN;
279 static POINT point;
280 static EVENTN eventn;
281
282 // Create a ROOT Tree
283 TTree *tree = new TTree("T","An example of ROOT tree with a few branches");
284 tree->Branch("point",&point,"x:y:z");
285 tree->Branch("eventn",&eventn,"ntrack/I:nseg:nvertex:flag/i:temperature/F");
286 tree->Branch("hpx","TH1F",&hpx,128000,0);
287
288 Float_t px,py,pz;
289 static Float_t p[3];
290
291 // Here we start a loop on 1000 events
292 for ( Int_t i=0; i<1000; i++) {
293 gRandom->Rannor(px,py);
294 pz = px*px + py*py;
295 Float_t random = gRandom->::Rndm(1);
296
297 // Fill histograms
298 hpx->Fill(px);
299 hpxpy->Fill(px,py,1);
300 hprof->Fill(px,pz,1);
301
302 // Fill structures
303 p[0] = px;
304 p[1] = py;
305 p[2] = pz;
306 point.x = 10*(random-1);;
307 point.y = 5*random;
308 point.z = 20*random;
309 eventn.ntrack = Int_t(100*random);
310 eventn.nseg = Int_t(2*eventn.ntrack);
311 eventn.nvertex = 1;
312 eventn.flag = Int_t(random+0.5);
313 eventn.temperature = 20+random;
314
315 // Fill the tree. For each event, save the 2 structures and 3 objects
316 // In this simple example, the objects hpx, hprof and hpxpy are slightly
317 // different from event to event. We expect a big compression factor!
318 tree->Fill();
319 }
320 // End of the loop
321
322 tree->Print();
323
324 // Save all objects in this file
325 hfile.Write();
326
327 // Close the file. Note that this is automatically done when you leave
328 // the application.
329 hfile.Close();
330
331 return 0;
332}
333~~~
334*/
335
336#include <ROOT/RConfig.hxx>
337#include "TTree.h"
338
339#include "ROOT/TIOFeatures.hxx"
340#include "TArrayC.h"
341#include "TBufferFile.h"
342#include "TBaseClass.h"
343#include "TBasket.h"
344#include "TBranchClones.h"
345#include "TBranchElement.h"
346#include "TBranchObject.h"
347#include "TBranchRef.h"
348#include "TBrowser.h"
349#include "TClass.h"
350#include "TClassEdit.h"
351#include "TClonesArray.h"
352#include "TCut.h"
353#include "TDataMember.h"
354#include "TDataType.h"
355#include "TDirectory.h"
356#include "TError.h"
357#include "TEntryList.h"
358#include "TEnv.h"
359#include "TEventList.h"
360#include "TFile.h"
361#include "TFolder.h"
362#include "TFriendElement.h"
363#include "TInterpreter.h"
364#include "TLeaf.h"
365#include "TLeafB.h"
366#include "TLeafC.h"
367#include "TLeafD.h"
368#include "TLeafElement.h"
369#include "TLeafF.h"
370#include "TLeafI.h"
371#include "TLeafL.h"
372#include "TLeafObject.h"
373#include "TLeafS.h"
374#include "TList.h"
375#include "TMath.h"
376#include "TROOT.h"
377#include "TRealData.h"
378#include "TRegexp.h"
379#include "TStreamerElement.h"
380#include "TStreamerInfo.h"
381#include "TStyle.h"
382#include "TSystem.h"
383#include "TTreeCloner.h"
384#include "TTreeCache.h"
385#include "TTreeCacheUnzip.h"
388#include "TVirtualIndex.h"
389#include "TVirtualPerfStats.h"
390#include "TVirtualPad.h"
391#include "TBranchSTL.h"
392#include "TSchemaRuleSet.h"
393#include "TFileMergeInfo.h"
394#include "ROOT/StringConv.hxx"
395#include "TVirtualMutex.h"
396
397#include "TBranchIMTHelper.h"
398#include "TNotifyLink.h"
399
400#include <chrono>
401#include <cstddef>
402#include <iostream>
403#include <fstream>
404#include <sstream>
405#include <string>
406#include <stdio.h>
407#include <limits.h>
408#include <algorithm>
409#include <set>
410
411#ifdef R__USE_IMT
413#include <thread>
414#include <string>
415#include <sstream>
416#endif
418constexpr Int_t kNEntriesResort = 100;
420
421Int_t TTree::fgBranchStyle = 1; // Use new TBranch style with TBranchElement.
422Long64_t TTree::fgMaxTreeSize = 100000000000LL;
423
425
426////////////////////////////////////////////////////////////////////////////////
427////////////////////////////////////////////////////////////////////////////////
428////////////////////////////////////////////////////////////////////////////////
430static char DataTypeToChar(EDataType datatype)
431{
432 // Return the leaflist 'char' for a given datatype.
433
434 switch(datatype) {
435 case kChar_t: return 'B';
436 case kUChar_t: return 'b';
437 case kBool_t: return 'O';
438 case kShort_t: return 'S';
439 case kUShort_t: return 's';
440 case kCounter:
441 case kInt_t: return 'I';
442 case kUInt_t: return 'i';
443 case kDouble_t:
444 case kDouble32_t: return 'D';
445 case kFloat_t:
446 case kFloat16_t: return 'F';
447 case kLong_t: return 0; // unsupported
448 case kULong_t: return 0; // unsupported?
449 case kchar: return 0; // unsupported
450 case kLong64_t: return 'L';
451 case kULong64_t: return 'l';
452
453 case kCharStar: return 'C';
454 case kBits: return 0; //unsupported
455
456 case kOther_t:
457 case kNoType_t:
458 default:
459 return 0;
460 }
461 return 0;
462}
463
464////////////////////////////////////////////////////////////////////////////////
465/// \class TTree::TFriendLock
466/// Helper class to prevent infinite recursion in the usage of TTree Friends.
467
468////////////////////////////////////////////////////////////////////////////////
469/// Record in tree that it has been used while recursively looks through the friends.
472: fTree(tree)
473{
474 // We could also add some code to acquire an actual
475 // lock to prevent multi-thread issues
476 fMethodBit = methodbit;
477 if (fTree) {
480 } else {
481 fPrevious = 0;
482 }
483}
484
485////////////////////////////////////////////////////////////////////////////////
486/// Copy constructor.
489 fTree(tfl.fTree),
490 fMethodBit(tfl.fMethodBit),
491 fPrevious(tfl.fPrevious)
492{
493}
494
495////////////////////////////////////////////////////////////////////////////////
496/// Assignment operator.
499{
500 if(this!=&tfl) {
501 fTree=tfl.fTree;
502 fMethodBit=tfl.fMethodBit;
503 fPrevious=tfl.fPrevious;
504 }
505 return *this;
506}
507
508////////////////////////////////////////////////////////////////////////////////
509/// Restore the state of tree the same as before we set the lock.
512{
513 if (fTree) {
514 if (!fPrevious) {
515 fTree->fFriendLockStatus &= ~(fMethodBit & kBitMask);
516 }
517 }
518}
519
520////////////////////////////////////////////////////////////////////////////////
521/// \class TTree::TClusterIterator
522/// Helper class to iterate over cluster of baskets.
523
524////////////////////////////////////////////////////////////////////////////////
525/// Regular constructor.
526/// TTree is not set as const, since we might modify if it is a TChain.
528TTree::TClusterIterator::TClusterIterator(TTree *tree, Long64_t firstEntry) : fTree(tree), fClusterRange(0), fStartEntry(0), fNextEntry(0), fEstimatedSize(-1)
529{
530 if (fTree->fNClusterRange) {
531 // Find the correct cluster range.
532 //
533 // Since fClusterRangeEnd contains the inclusive upper end of the range, we need to search for the
534 // range that was containing the previous entry and add 1 (because BinarySearch consider the values
535 // to be the inclusive start of the bucket).
537
538 Long64_t entryInRange;
539 Long64_t pedestal;
540 if (fClusterRange == 0) {
541 pedestal = 0;
542 entryInRange = firstEntry;
543 } else {
544 pedestal = fTree->fClusterRangeEnd[fClusterRange-1] + 1;
545 entryInRange = firstEntry - pedestal;
546 }
547 Long64_t autoflush;
549 autoflush = fTree->fAutoFlush;
550 } else {
551 autoflush = fTree->fClusterSize[fClusterRange];
552 }
553 if (autoflush <= 0) {
554 autoflush = GetEstimatedClusterSize();
555 }
556 fStartEntry = pedestal + entryInRange - entryInRange%autoflush;
557 } else if ( fTree->GetAutoFlush() <= 0 ) {
558 // Case of old files before November 9 2009 *or* small tree where AutoFlush was never set.
559 fStartEntry = firstEntry;
560 } else {
561 fStartEntry = firstEntry - firstEntry%fTree->GetAutoFlush();
562 }
563 fNextEntry = fStartEntry; // Position correctly for the first call to Next()
564}
565
566////////////////////////////////////////////////////////////////////////////////
567/// Estimate the cluster size.
568///
569/// In almost all cases, this quickly returns the size of the auto-flush
570/// in the TTree.
571///
572/// However, in the case where the cluster size was not fixed (old files and
573/// case where autoflush was explicitly set to zero), we need estimate
574/// a cluster size in relation to the size of the cache.
575///
576/// After this value is calculated once for the TClusterIterator, it is
577/// cached and reused in future calls.
580{
581 auto autoFlush = fTree->GetAutoFlush();
582 if (autoFlush > 0) return autoFlush;
583 if (fEstimatedSize > 0) return fEstimatedSize;
584
585 Long64_t zipBytes = fTree->GetZipBytes();
586 if (zipBytes == 0) {
587 fEstimatedSize = fTree->GetEntries() - 1;
588 } else {
589 Long64_t clusterEstimate = 1;
590 Long64_t cacheSize = fTree->GetCacheSize();
591 if (cacheSize == 0) {
592 // Humm ... let's double check on the file.
593 TFile *file = fTree->GetCurrentFile();
594 if (file) {
595 TFileCacheRead *cache = fTree->GetReadCache(file);
596 if (cache) {
597 cacheSize = cache->GetBufferSize();
598 }
599 }
600 }
601 // If neither file nor tree has a cache, use the current default.
602 if (cacheSize <= 0) {
603 cacheSize = 30000000;
604 }
605 clusterEstimate = fTree->GetEntries() * cacheSize / zipBytes;
606 // If there are no entries, then just default to 1.
607 fEstimatedSize = clusterEstimate ? clusterEstimate : 1;
608 }
609 return fEstimatedSize;
610}
611
612////////////////////////////////////////////////////////////////////////////////
613/// Move on to the next cluster and return the starting entry
614/// of this next cluster
617{
618 fStartEntry = fNextEntry;
619 if (fTree->fNClusterRange || fTree->GetAutoFlush() > 0) {
620 if (fClusterRange == fTree->fNClusterRange) {
621 // We are looking at a range which size
622 // is defined by AutoFlush itself and goes to the GetEntries.
623 fNextEntry += GetEstimatedClusterSize();
624 } else {
625 if (fStartEntry > fTree->fClusterRangeEnd[fClusterRange]) {
626 ++fClusterRange;
627 }
628 if (fClusterRange == fTree->fNClusterRange) {
629 // We are looking at the last range which size
630 // is defined by AutoFlush itself and goes to the GetEntries.
631 fNextEntry += GetEstimatedClusterSize();
632 } else {
633 Long64_t clusterSize = fTree->fClusterSize[fClusterRange];
634 if (clusterSize == 0) {
635 clusterSize = GetEstimatedClusterSize();
636 }
637 fNextEntry += clusterSize;
638 if (fNextEntry > fTree->fClusterRangeEnd[fClusterRange]) {
639 // The last cluster of the range was a partial cluster,
640 // so the next cluster starts at the beginning of the
641 // next range.
642 fNextEntry = fTree->fClusterRangeEnd[fClusterRange] + 1;
643 }
644 }
645 }
646 } else {
647 // Case of old files before November 9 2009
648 fNextEntry = fStartEntry + GetEstimatedClusterSize();
649 }
650 if (fNextEntry > fTree->GetEntries()) {
651 fNextEntry = fTree->GetEntries();
652 }
653 return fStartEntry;
654}
655
656////////////////////////////////////////////////////////////////////////////////
657/// Move on to the previous cluster and return the starting entry
658/// of this previous cluster
661{
662 fNextEntry = fStartEntry;
663 if (fTree->fNClusterRange || fTree->GetAutoFlush() > 0) {
664 if (fClusterRange == 0 || fTree->fNClusterRange == 0) {
665 // We are looking at a range which size
666 // is defined by AutoFlush itself.
667 fStartEntry -= GetEstimatedClusterSize();
668 } else {
669 if (fNextEntry <= fTree->fClusterRangeEnd[fClusterRange]) {
670 --fClusterRange;
671 }
672 if (fClusterRange == 0) {
673 // We are looking at the first range.
674 fStartEntry = 0;
675 } else {
676 Long64_t clusterSize = fTree->fClusterSize[fClusterRange];
677 if (clusterSize == 0) {
678 clusterSize = GetEstimatedClusterSize();
679 }
680 fStartEntry -= clusterSize;
681 }
682 }
683 } else {
684 // Case of old files before November 9 2009 or trees that never auto-flushed.
685 fStartEntry = fNextEntry - GetEstimatedClusterSize();
686 }
687 if (fStartEntry < 0) {
688 fStartEntry = 0;
689 }
690 return fStartEntry;
691}
692
693////////////////////////////////////////////////////////////////////////////////
694////////////////////////////////////////////////////////////////////////////////
695////////////////////////////////////////////////////////////////////////////////
696
697////////////////////////////////////////////////////////////////////////////////
698/// Default constructor and I/O constructor.
699///
700/// Note: We do *not* insert ourself into the current directory.
701///
704: TNamed()
705, TAttLine()
706, TAttFill()
707, TAttMarker()
708, fEntries(0)
709, fTotBytes(0)
710, fZipBytes(0)
711, fSavedBytes(0)
712, fFlushedBytes(0)
713, fWeight(1)
715, fScanField(25)
716, fUpdate(0)
720, fMaxEntries(0)
721, fMaxEntryLoop(0)
723, fAutoSave( -300000000)
724, fAutoFlush(-30000000)
725, fEstimate(1000000)
727, fClusterSize(0)
728, fCacheSize(0)
729, fChainOffset(0)
730, fReadEntry(-1)
731, fTotalBuffers(0)
732, fPacketSize(100)
733, fNfill(0)
734, fDebug(0)
735, fDebugMin(0)
736, fDebugMax(9999999)
737, fMakeClass(0)
738, fFileNumber(0)
739, fNotify(0)
740, fDirectory(0)
741, fBranches()
742, fLeaves()
743, fAliases(0)
744, fEventList(0)
745, fEntryList(0)
746, fIndexValues()
747, fIndex()
748, fTreeIndex(0)
749, fFriends(0)
750, fPerfStats(0)
751, fUserInfo(0)
752, fPlayer(0)
753, fClones(0)
754, fBranchRef(0)
762{
763 fMaxEntries = 1000000000;
764 fMaxEntries *= 1000;
765
766 fMaxEntryLoop = 1000000000;
767 fMaxEntryLoop *= 1000;
768
770}
771
772////////////////////////////////////////////////////////////////////////////////
773/// Normal tree constructor.
774///
775/// The tree is created in the current directory.
776/// Use the various functions Branch below to add branches to this tree.
777///
778/// If the first character of title is a "/", the function assumes a folder name.
779/// In this case, it creates automatically branches following the folder hierarchy.
780/// splitlevel may be used in this case to control the split level.
782TTree::TTree(const char* name, const char* title, Int_t splitlevel /* = 99 */,
783 TDirectory* dir /* = gDirectory*/)
784: TNamed(name, title)
785, TAttLine()
786, TAttFill()
787, TAttMarker()
788, fEntries(0)
789, fTotBytes(0)
790, fZipBytes(0)
791, fSavedBytes(0)
792, fFlushedBytes(0)
793, fWeight(1)
794, fTimerInterval(0)
795, fScanField(25)
796, fUpdate(0)
797, fDefaultEntryOffsetLen(1000)
798, fNClusterRange(0)
799, fMaxClusterRange(0)
800, fMaxEntries(0)
801, fMaxEntryLoop(0)
802, fMaxVirtualSize(0)
803, fAutoSave( -300000000)
804, fAutoFlush(-30000000)
805, fEstimate(1000000)
806, fClusterRangeEnd(0)
807, fClusterSize(0)
808, fCacheSize(0)
809, fChainOffset(0)
810, fReadEntry(-1)
811, fTotalBuffers(0)
812, fPacketSize(100)
813, fNfill(0)
814, fDebug(0)
815, fDebugMin(0)
816, fDebugMax(9999999)
817, fMakeClass(0)
818, fFileNumber(0)
819, fNotify(0)
820, fDirectory(dir)
821, fBranches()
822, fLeaves()
823, fAliases(0)
824, fEventList(0)
825, fEntryList(0)
826, fIndexValues()
827, fIndex()
828, fTreeIndex(0)
829, fFriends(0)
830, fPerfStats(0)
831, fUserInfo(0)
832, fPlayer(0)
833, fClones(0)
834, fBranchRef(0)
835, fFriendLockStatus(0)
836, fTransientBuffer(0)
837, fCacheDoAutoInit(kTRUE)
838, fCacheDoClusterPrefetch(kFALSE)
839, fCacheUserSet(kFALSE)
840, fIMTEnabled(ROOT::IsImplicitMTEnabled())
841, fNEntriesSinceSorting(0)
842{
843 // TAttLine state.
847
848 // TAttFill state.
851
852 // TAttMarkerState.
856
857 fMaxEntries = 1000000000;
858 fMaxEntries *= 1000;
859
860 fMaxEntryLoop = 1000000000;
861 fMaxEntryLoop *= 1000;
862
863 // Insert ourself into the current directory.
864 // FIXME: This is very annoying behaviour, we should
865 // be able to choose to not do this like we
866 // can with a histogram.
867 if (fDirectory) fDirectory->Append(this);
868
870
871 // If title starts with "/" and is a valid folder name, a superbranch
872 // is created.
873 // FIXME: Why?
874 if (strlen(title) > 2) {
875 if (title[0] == '/') {
876 Branch(title+1,32000,splitlevel);
877 }
878 }
879}
880
881////////////////////////////////////////////////////////////////////////////////
882/// Destructor.
885{
886 if (auto link = dynamic_cast<TNotifyLinkBase*>(fNotify)) {
887 link->Clear();
888 }
889 if (fAllocationCount && (gDebug > 0)) {
890 Info("TTree::~TTree", "For tree %s, allocation count is %u.", GetName(), fAllocationCount.load());
891#ifdef R__TRACK_BASKET_ALLOC_TIME
892 Info("TTree::~TTree", "For tree %s, allocation time is %lluus.", GetName(), fAllocationTime.load());
893#endif
894 }
895
896 if (fDirectory) {
897 // We are in a directory, which may possibly be a file.
898 if (fDirectory->GetList()) {
899 // Remove us from the directory listing.
900 fDirectory->Remove(this);
901 }
902 //delete the file cache if it points to this Tree
905 }
906 // We don't own the leaves in fLeaves, the branches do.
907 fLeaves.Clear();
908 // I'm ready to destroy any objects allocated by
909 // SetAddress() by my branches. If I have clones,
910 // tell them to zero their pointers to this shared
911 // memory.
912 if (fClones && fClones->GetEntries()) {
913 // I have clones.
914 // I am about to delete the objects created by
915 // SetAddress() which we are sharing, so tell
916 // the clones to release their pointers to them.
917 for (TObjLink* lnk = fClones->FirstLink(); lnk; lnk = lnk->Next()) {
918 TTree* clone = (TTree*) lnk->GetObject();
919 // clone->ResetBranchAddresses();
920
921 // Reset only the branch we have set the address of.
922 CopyAddresses(clone,kTRUE);
923 }
924 }
925 // Get rid of our branches, note that this will also release
926 // any memory allocated by TBranchElement::SetAddress().
928 // FIXME: We must consider what to do with the reset of these if we are a clone.
929 delete fPlayer;
930 fPlayer = 0;
931 if (fFriends) {
932 fFriends->Delete();
933 delete fFriends;
934 fFriends = 0;
935 }
936 if (fAliases) {
937 fAliases->Delete();
938 delete fAliases;
939 fAliases = 0;
940 }
941 if (fUserInfo) {
942 fUserInfo->Delete();
943 delete fUserInfo;
944 fUserInfo = 0;
945 }
946 if (fClones) {
947 // Clone trees should no longer be removed from fClones when they are deleted.
948 {
950 gROOT->GetListOfCleanups()->Remove(fClones);
951 }
952 // Note: fClones does not own its content.
953 delete fClones;
954 fClones = 0;
955 }
956 if (fEntryList) {
958 // Delete the entry list if it is marked to be deleted and it is not also
959 // owned by a directory. (Otherwise we would need to make sure that a
960 // TDirectoryFile that has a TTree in it does a 'slow' TList::Delete.
961 delete fEntryList;
962 fEntryList=0;
963 }
964 }
965 delete fTreeIndex;
966 fTreeIndex = 0;
967 delete fBranchRef;
968 fBranchRef = 0;
969 delete [] fClusterRangeEnd;
971 delete [] fClusterSize;
972 fClusterSize = 0;
973 // Must be done after the destruction of friends.
974 // Note: We do *not* own our directory.
975 fDirectory = 0;
976
977 if (fTransientBuffer) {
978 delete fTransientBuffer;
980 }
981}
982
983////////////////////////////////////////////////////////////////////////////////
984/// Returns the transient buffer currently used by this TTree for reading/writing baskets.
987{
988 if (fTransientBuffer) {
989 if (fTransientBuffer->BufferSize() < size) {
991 }
992 return fTransientBuffer;
993 }
995 return fTransientBuffer;
996}
997
998////////////////////////////////////////////////////////////////////////////////
999/// Add branch with name bname to the Tree cache.
1000/// If bname="*" all branches are added to the cache.
1001/// if subbranches is true all the branches of the subbranches are
1002/// also put to the cache.
1003///
1004/// Returns:
1005/// - 0 branch added or already included
1006/// - -1 on error
1008Int_t TTree::AddBranchToCache(const char*bname, Bool_t subbranches)
1009{
1010 if (!GetTree()) {
1011 if (LoadTree(0)<0) {
1012 Error("AddBranchToCache","Could not load a tree");
1013 return -1;
1014 }
1015 }
1016 if (GetTree()) {
1017 if (GetTree() != this) {
1018 return GetTree()->AddBranchToCache(bname, subbranches);
1019 }
1020 } else {
1021 Error("AddBranchToCache", "No tree is available. Branch was not added to the cache");
1022 return -1;
1023 }
1024
1025 TFile *f = GetCurrentFile();
1026 if (!f) {
1027 Error("AddBranchToCache", "No file is available. Branch was not added to the cache");
1028 return -1;
1029 }
1031 if (!tc) {
1032 Error("AddBranchToCache", "No cache is available, branch not added");
1033 return -1;
1034 }
1035 return tc->AddBranch(bname,subbranches);
1036}
1037
1038////////////////////////////////////////////////////////////////////////////////
1039/// Add branch b to the Tree cache.
1040/// if subbranches is true all the branches of the subbranches are
1041/// also put to the cache.
1042///
1043/// Returns:
1044/// - 0 branch added or already included
1045/// - -1 on error
1048{
1049 if (!GetTree()) {
1050 if (LoadTree(0)<0) {
1051 Error("AddBranchToCache","Could not load a tree");
1052 return -1;
1053 }
1054 }
1055 if (GetTree()) {
1056 if (GetTree() != this) {
1057 Int_t res = GetTree()->AddBranchToCache(b, subbranches);
1058 if (res<0) {
1059 Error("AddBranchToCache", "Error adding branch");
1060 }
1061 return res;
1062 }
1063 } else {
1064 Error("AddBranchToCache", "No tree is available. Branch was not added to the cache");
1065 return -1;
1066 }
1067
1068 TFile *f = GetCurrentFile();
1069 if (!f) {
1070 Error("AddBranchToCache", "No file is available. Branch was not added to the cache");
1071 return -1;
1072 }
1074 if (!tc) {
1075 Error("AddBranchToCache", "No cache is available, branch not added");
1076 return -1;
1077 }
1078 return tc->AddBranch(b,subbranches);
1079}
1080
1081////////////////////////////////////////////////////////////////////////////////
1082/// Remove the branch with name 'bname' from the Tree cache.
1083/// If bname="*" all branches are removed from the cache.
1084/// if subbranches is true all the branches of the subbranches are
1085/// also removed from the cache.
1086///
1087/// Returns:
1088/// - 0 branch dropped or not in cache
1089/// - -1 on error
1091Int_t TTree::DropBranchFromCache(const char*bname, Bool_t subbranches)
1092{
1093 if (!GetTree()) {
1094 if (LoadTree(0)<0) {
1095 Error("DropBranchFromCache","Could not load a tree");
1096 return -1;
1097 }
1098 }
1099 if (GetTree()) {
1100 if (GetTree() != this) {
1101 return GetTree()->DropBranchFromCache(bname, subbranches);
1102 }
1103 } else {
1104 Error("DropBranchFromCache", "No tree is available. Branch was not dropped from the cache");
1105 return -1;
1106 }
1107
1108 TFile *f = GetCurrentFile();
1109 if (!f) {
1110 Error("DropBranchFromCache", "No file is available. Branch was not dropped from the cache");
1111 return -1;
1112 }
1114 if (!tc) {
1115 Error("DropBranchFromCache", "No cache is available, branch not dropped");
1116 return -1;
1117 }
1118 return tc->DropBranch(bname,subbranches);
1119}
1120
1121////////////////////////////////////////////////////////////////////////////////
1122/// Remove the branch b from the Tree cache.
1123/// if subbranches is true all the branches of the subbranches are
1124/// also removed from the cache.
1125///
1126/// Returns:
1127/// - 0 branch dropped or not in cache
1128/// - -1 on error
1131{
1132 if (!GetTree()) {
1133 if (LoadTree(0)<0) {
1134 Error("DropBranchFromCache","Could not load a tree");
1135 return -1;
1136 }
1137 }
1138 if (GetTree()) {
1139 if (GetTree() != this) {
1140 Int_t res = GetTree()->DropBranchFromCache(b, subbranches);
1141 if (res<0) {
1142 Error("DropBranchFromCache", "Error dropping branch");
1143 }
1144 return res;
1145 }
1146 } else {
1147 Error("DropBranchFromCache", "No tree is available. Branch was not dropped from the cache");
1148 return -1;
1149 }
1150
1151 TFile *f = GetCurrentFile();
1152 if (!f) {
1153 Error("DropBranchFromCache", "No file is available. Branch was not dropped from the cache");
1154 return -1;
1155 }
1157 if (!tc) {
1158 Error("DropBranchFromCache", "No cache is available, branch not dropped");
1159 return -1;
1160 }
1161 return tc->DropBranch(b,subbranches);
1162}
1163
1164////////////////////////////////////////////////////////////////////////////////
1165/// Add a cloned tree to our list of trees to be notified whenever we change
1166/// our branch addresses or when we are deleted.
1168void TTree::AddClone(TTree* clone)
1169{
1170 if (!fClones) {
1171 fClones = new TList();
1172 fClones->SetOwner(false);
1173 // So that the clones are automatically removed from the list when
1174 // they are deleted.
1175 {
1177 gROOT->GetListOfCleanups()->Add(fClones);
1178 }
1179 }
1180 if (!fClones->FindObject(clone)) {
1181 fClones->Add(clone);
1182 }
1183}
1184
1185////////////////////////////////////////////////////////////////////////////////
1186/// Add a TFriendElement to the list of friends.
1187///
1188/// This function:
1189/// - opens a file if filename is specified
1190/// - reads a Tree with name treename from the file (current directory)
1191/// - adds the Tree to the list of friends
1192/// see other AddFriend functions
1193///
1194/// A TFriendElement TF describes a TTree object TF in a file.
1195/// When a TFriendElement TF is added to the the list of friends of an
1196/// existing TTree T, any variable from TF can be referenced in a query
1197/// to T.
1198///
1199/// A tree keeps a list of friends. In the context of a tree (or a chain),
1200/// friendship means unrestricted access to the friends data. In this way
1201/// it is much like adding another branch to the tree without taking the risk
1202/// of damaging it. To add a friend to the list, you can use the TTree::AddFriend
1203/// method. The tree in the diagram below has two friends (friend_tree1 and
1204/// friend_tree2) and now has access to the variables a,b,c,i,j,k,l and m.
1205///
1206/// \image html ttree_friend1.png
1207///
1208/// The AddFriend method has two parameters, the first is the tree name and the
1209/// second is the name of the ROOT file where the friend tree is saved.
1210/// AddFriend automatically opens the friend file. If no file name is given,
1211/// the tree called ft1 is assumed to be in the same file as the original tree.
1212///
1213/// tree.AddFriend("ft1","friendfile1.root");
1214/// If the friend tree has the same name as the original tree, you can give it
1215/// an alias in the context of the friendship:
1216///
1217/// tree.AddFriend("tree1 = tree","friendfile1.root");
1218/// Once the tree has friends, we can use TTree::Draw as if the friend's
1219/// variables were in the original tree. To specify which tree to use in
1220/// the Draw method, use the syntax:
1221/// ~~~ {.cpp}
1222/// <treeName>.<branchname>.<varname>
1223/// ~~~
1224/// If the variablename is enough to uniquely identify the variable, you can
1225/// leave out the tree and/or branch name.
1226/// For example, these commands generate a 3-d scatter plot of variable "var"
1227/// in the TTree tree versus variable v1 in TTree ft1 versus variable v2 in
1228/// TTree ft2.
1229/// ~~~ {.cpp}
1230/// tree.AddFriend("ft1","friendfile1.root");
1231/// tree.AddFriend("ft2","friendfile2.root");
1232/// tree.Draw("var:ft1.v1:ft2.v2");
1233/// ~~~
1234/// \image html ttree_friend2.png
1235///
1236/// The picture illustrates the access of the tree and its friends with a
1237/// Draw command.
1238/// When AddFriend is called, the ROOT file is automatically opened and the
1239/// friend tree (ft1) is read into memory. The new friend (ft1) is added to
1240/// the list of friends of tree.
1241/// The number of entries in the friend must be equal or greater to the number
1242/// of entries of the original tree. If the friend tree has fewer entries a
1243/// warning is given and the missing entries are not included in the histogram.
1244/// To retrieve the list of friends from a tree use TTree::GetListOfFriends.
1245/// When the tree is written to file (TTree::Write), the friends list is saved
1246/// with it. And when the tree is retrieved, the trees on the friends list are
1247/// also retrieved and the friendship restored.
1248/// When a tree is deleted, the elements of the friend list are also deleted.
1249/// It is possible to declare a friend tree that has the same internal
1250/// structure (same branches and leaves) as the original tree, and compare the
1251/// same values by specifying the tree.
1252/// ~~~ {.cpp}
1253/// tree.Draw("var:ft1.var:ft2.var")
1254/// ~~~
1256TFriendElement* TTree::AddFriend(const char* treename, const char* filename)
1257{
1258 if (!fFriends) {
1259 fFriends = new TList();
1260 }
1261 TFriendElement* fe = new TFriendElement(this, treename, filename);
1262
1263 fFriends->Add(fe);
1264 TTree* t = fe->GetTree();
1265 if (t) {
1266 if (!t->GetTreeIndex() && (t->GetEntries() < fEntries)) {
1267 Warning("AddFriend", "FriendElement %s in file %s has less entries %lld than its parent Tree: %lld", treename, filename, t->GetEntries(), fEntries);
1268 }
1269 } else {
1270 Warning("AddFriend", "Cannot add FriendElement %s in file %s", treename, filename);
1271 }
1272 return fe;
1273}
1274
1275////////////////////////////////////////////////////////////////////////////////
1276/// Add a TFriendElement to the list of friends.
1277///
1278/// The TFile is managed by the user (e.g. the user must delete the file).
1279/// For complete description see AddFriend(const char *, const char *).
1280/// This function:
1281/// - reads a Tree with name treename from the file
1282/// - adds the Tree to the list of friends
1284TFriendElement* TTree::AddFriend(const char* treename, TFile* file)
1285{
1286 if (!fFriends) {
1287 fFriends = new TList();
1288 }
1289 TFriendElement *fe = new TFriendElement(this, treename, file);
1290 R__ASSERT(fe);
1291 fFriends->Add(fe);
1292 TTree *t = fe->GetTree();
1293 if (t) {
1294 if (!t->GetTreeIndex() && (t->GetEntries() < fEntries)) {
1295 Warning("AddFriend", "FriendElement %s in file %s has less entries %lld than its parent tree: %lld", treename, file->GetName(), t->GetEntries(), fEntries);
1296 }
1297 } else {
1298 Warning("AddFriend", "unknown tree '%s' in file '%s'", treename, file->GetName());
1299 }
1300 return fe;
1301}
1302
1303////////////////////////////////////////////////////////////////////////////////
1304/// Add a TFriendElement to the list of friends.
1305///
1306/// The TTree is managed by the user (e.g., the user must delete the file).
1307/// For a complete description see AddFriend(const char *, const char *).
1309TFriendElement* TTree::AddFriend(TTree* tree, const char* alias, Bool_t warn)
1310{
1311 if (!tree) {
1312 return 0;
1313 }
1314 if (!fFriends) {
1315 fFriends = new TList();
1316 }
1317 TFriendElement* fe = new TFriendElement(this, tree, alias);
1318 R__ASSERT(fe); // this assert is for historical reasons. Don't remove it unless you understand all the consequences.
1319 fFriends->Add(fe);
1320 TTree* t = fe->GetTree();
1321 if (warn && (t->GetEntries() < fEntries)) {
1322 Warning("AddFriend", "FriendElement '%s' in file '%s' has less entries %lld than its parent tree: %lld",
1323 tree->GetName(), fe->GetFile() ? fe->GetFile()->GetName() : "(memory resident)", t->GetEntries(), fEntries);
1324 }
1325 return fe;
1326}
1327
1328////////////////////////////////////////////////////////////////////////////////
1329/// AutoSave tree header every fAutoSave bytes.
1330///
1331/// When large Trees are produced, it is safe to activate the AutoSave
1332/// procedure. Some branches may have buffers holding many entries.
1333/// If fAutoSave is negative, AutoSave is automatically called by
1334/// TTree::Fill when the number of bytes generated since the previous
1335/// AutoSave is greater than -fAutoSave bytes.
1336/// If fAutoSave is positive, AutoSave is automatically called by
1337/// TTree::Fill every N entries.
1338/// This function may also be invoked by the user.
1339/// Each AutoSave generates a new key on the file.
1340/// Once the key with the tree header has been written, the previous cycle
1341/// (if any) is deleted.
1342///
1343/// Note that calling TTree::AutoSave too frequently (or similarly calling
1344/// TTree::SetAutoSave with a small value) is an expensive operation.
1345/// You should make tests for your own application to find a compromise
1346/// between speed and the quantity of information you may loose in case of
1347/// a job crash.
1348///
1349/// In case your program crashes before closing the file holding this tree,
1350/// the file will be automatically recovered when you will connect the file
1351/// in UPDATE mode.
1352/// The Tree will be recovered at the status corresponding to the last AutoSave.
1353///
1354/// if option contains "SaveSelf", gDirectory->SaveSelf() is called.
1355/// This allows another process to analyze the Tree while the Tree is being filled.
1356///
1357/// if option contains "FlushBaskets", TTree::FlushBaskets is called and all
1358/// the current basket are closed-out and written to disk individually.
1359///
1360/// By default the previous header is deleted after having written the new header.
1361/// if option contains "Overwrite", the previous Tree header is deleted
1362/// before written the new header. This option is slightly faster, but
1363/// the default option is safer in case of a problem (disk quota exceeded)
1364/// when writing the new header.
1365///
1366/// The function returns the number of bytes written to the file.
1367/// if the number of bytes is null, an error has occurred while writing
1368/// the header to the file.
1369///
1370/// ## How to write a Tree in one process and view it from another process
1371///
1372/// The following two scripts illustrate how to do this.
1373/// The script treew.C is executed by process1, treer.C by process2
1374///
1375/// script treew.C:
1376/// ~~~ {.cpp}
1377/// void treew() {
1378/// TFile f("test.root","recreate");
1379/// TNtuple *ntuple = new TNtuple("ntuple","Demo","px:py:pz:random:i");
1380/// Float_t px, py, pz;
1381/// for ( Int_t i=0; i<10000000; i++) {
1382/// gRandom->Rannor(px,py);
1383/// pz = px*px + py*py;
1384/// Float_t random = gRandom->Rndm(1);
1385/// ntuple->Fill(px,py,pz,random,i);
1386/// if (i%1000 == 1) ntuple->AutoSave("SaveSelf");
1387/// }
1388/// }
1389/// ~~~
1390/// script treer.C:
1391/// ~~~ {.cpp}
1392/// void treer() {
1393/// TFile f("test.root");
1394/// TTree *ntuple = (TTree*)f.Get("ntuple");
1395/// TCanvas c1;
1396/// Int_t first = 0;
1397/// while(1) {
1398/// if (first == 0) ntuple->Draw("px>>hpx", "","",10000000,first);
1399/// else ntuple->Draw("px>>+hpx","","",10000000,first);
1400/// first = (Int_t)ntuple->GetEntries();
1401/// c1.Update();
1402/// gSystem->Sleep(1000); //sleep 1 second
1403/// ntuple->Refresh();
1404/// }
1405/// }
1406/// ~~~
1409{
1410 if (!fDirectory || fDirectory == gROOT || !fDirectory->IsWritable()) return 0;
1411 if (gDebug > 0) {
1412 Info("AutoSave", "Tree:%s after %lld bytes written\n",GetName(),GetTotBytes());
1413 }
1414 TString opt = option;
1415 opt.ToLower();
1416
1417 if (opt.Contains("flushbaskets")) {
1418 if (gDebug > 0) Info("AutoSave", "calling FlushBaskets \n");
1420 }
1421
1423
1425 Long64_t nbytes;
1426 if (opt.Contains("overwrite")) {
1427 nbytes = fDirectory->WriteTObject(this,"","overwrite");
1428 } else {
1429 nbytes = fDirectory->WriteTObject(this); //nbytes will be 0 if Write failed (disk space exceeded)
1430 if (nbytes && key) {
1431 key->Delete();
1432 delete key;
1433 }
1434 }
1435 // save StreamerInfo
1437 if (file) file->WriteStreamerInfo();
1438
1439 if (opt.Contains("saveself")) {
1441 //the following line is required in case GetUserInfo contains a user class
1442 //for which the StreamerInfo must be written. One could probably be a bit faster (Rene)
1443 if (file) file->WriteHeader();
1444 }
1445
1446 return nbytes;
1447}
1448
1449namespace {
1450 // This error message is repeated several times in the code. We write it once.
1451 const char* writeStlWithoutProxyMsg = "The class requested (%s) for the branch \"%s\""
1452 " is an instance of an stl collection and does not have a compiled CollectionProxy."
1453 " Please generate the dictionary for this collection (%s) to avoid to write corrupted data.";
1454}
1455
1456////////////////////////////////////////////////////////////////////////////////
1457/// Same as TTree::Branch() with added check that addobj matches className.
1458///
1459/// See TTree::Branch() for other details.
1460///
1462TBranch* TTree::BranchImp(const char* branchname, const char* classname, TClass* ptrClass, void* addobj, Int_t bufsize, Int_t splitlevel)
1463{
1464 TClass* claim = TClass::GetClass(classname);
1465 if (!ptrClass) {
1466 if (claim && claim->GetCollectionProxy() && dynamic_cast<TEmulatedCollectionProxy*>(claim->GetCollectionProxy())) {
1467 Error("Branch", writeStlWithoutProxyMsg,
1468 claim->GetName(), branchname, claim->GetName());
1469 return 0;
1470 }
1471 return Branch(branchname, classname, (void*) addobj, bufsize, splitlevel);
1472 }
1473 TClass* actualClass = 0;
1474 void** addr = (void**) addobj;
1475 if (addr) {
1476 actualClass = ptrClass->GetActualClass(*addr);
1477 }
1478 if (ptrClass && claim) {
1479 if (!(claim->InheritsFrom(ptrClass) || ptrClass->InheritsFrom(claim))) {
1480 // Note we currently do not warn in case of splicing or over-expectation).
1481 if (claim->IsLoaded() && ptrClass->IsLoaded() && strcmp( claim->GetTypeInfo()->name(), ptrClass->GetTypeInfo()->name() ) == 0) {
1482 // The type is the same according to the C++ type_info, we must be in the case of
1483 // a template of Double32_t. This is actually a correct case.
1484 } else {
1485 Error("Branch", "The class requested (%s) for \"%s\" is different from the type of the pointer passed (%s)",
1486 claim->GetName(), branchname, ptrClass->GetName());
1487 }
1488 } else if (actualClass && (claim != actualClass) && !actualClass->InheritsFrom(claim)) {
1489 if (claim->IsLoaded() && actualClass->IsLoaded() && strcmp( claim->GetTypeInfo()->name(), actualClass->GetTypeInfo()->name() ) == 0) {
1490 // The type is the same according to the C++ type_info, we must be in the case of
1491 // a template of Double32_t. This is actually a correct case.
1492 } else {
1493 Error("Branch", "The actual class (%s) of the object provided for the definition of the branch \"%s\" does not inherit from %s",
1494 actualClass->GetName(), branchname, claim->GetName());
1495 }
1496 }
1497 }
1498 if (claim && claim->GetCollectionProxy() && dynamic_cast<TEmulatedCollectionProxy*>(claim->GetCollectionProxy())) {
1499 Error("Branch", writeStlWithoutProxyMsg,
1500 claim->GetName(), branchname, claim->GetName());
1501 return 0;
1502 }
1503 return Branch(branchname, classname, (void*) addobj, bufsize, splitlevel);
1504}
1505
1506////////////////////////////////////////////////////////////////////////////////
1507/// Same as TTree::Branch but automatic detection of the class name.
1508/// See TTree::Branch for other details.
1510TBranch* TTree::BranchImp(const char* branchname, TClass* ptrClass, void* addobj, Int_t bufsize, Int_t splitlevel)
1511{
1512 if (!ptrClass) {
1513 Error("Branch", "The pointer specified for %s is not of a class known to ROOT", branchname);
1514 return 0;
1515 }
1516 TClass* actualClass = 0;
1517 void** addr = (void**) addobj;
1518 if (addr && *addr) {
1519 actualClass = ptrClass->GetActualClass(*addr);
1520 if (!actualClass) {
1521 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",
1522 branchname, ptrClass->GetName());
1523 actualClass = ptrClass;
1524 } else if ((ptrClass != actualClass) && !actualClass->InheritsFrom(ptrClass)) {
1525 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());
1526 return 0;
1527 }
1528 } else {
1529 actualClass = ptrClass;
1530 }
1531 if (actualClass && actualClass->GetCollectionProxy() && dynamic_cast<TEmulatedCollectionProxy*>(actualClass->GetCollectionProxy())) {
1532 Error("Branch", writeStlWithoutProxyMsg,
1533 actualClass->GetName(), branchname, actualClass->GetName());
1534 return 0;
1535 }
1536 return Branch(branchname, actualClass->GetName(), (void*) addobj, bufsize, splitlevel);
1537}
1538
1539////////////////////////////////////////////////////////////////////////////////
1540/// Same as TTree::Branch but automatic detection of the class name.
1541/// See TTree::Branch for other details.
1543TBranch* TTree::BranchImpRef(const char* branchname, const char *classname, TClass* ptrClass, void *addobj, Int_t bufsize, Int_t splitlevel)
1544{
1545 TClass* claim = TClass::GetClass(classname);
1546 if (!ptrClass) {
1547 if (claim && claim->GetCollectionProxy() && dynamic_cast<TEmulatedCollectionProxy*>(claim->GetCollectionProxy())) {
1548 Error("Branch", writeStlWithoutProxyMsg,
1549 claim->GetName(), branchname, claim->GetName());
1550 return 0;
1551 } else if (claim == 0) {
1552 Error("Branch", "The pointer specified for %s is not of a class known to ROOT and %s is not a known class", branchname, classname);
1553 return 0;
1554 }
1555 ptrClass = claim;
1556 }
1557 TClass* actualClass = 0;
1558 if (!addobj) {
1559 Error("Branch", "Reference interface requires a valid object (for branch: %s)!", branchname);
1560 return 0;
1561 }
1562 actualClass = ptrClass->GetActualClass(addobj);
1563 if (ptrClass && claim) {
1564 if (!(claim->InheritsFrom(ptrClass) || ptrClass->InheritsFrom(claim))) {
1565 // Note we currently do not warn in case of splicing or over-expectation).
1566 if (claim->IsLoaded() && ptrClass->IsLoaded() && strcmp( claim->GetTypeInfo()->name(), ptrClass->GetTypeInfo()->name() ) == 0) {
1567 // The type is the same according to the C++ type_info, we must be in the case of
1568 // a template of Double32_t. This is actually a correct case.
1569 } else {
1570 Error("Branch", "The class requested (%s) for \"%s\" is different from the type of the object passed (%s)",
1571 claim->GetName(), branchname, ptrClass->GetName());
1572 }
1573 } else if (actualClass && (claim != actualClass) && !actualClass->InheritsFrom(claim)) {
1574 if (claim->IsLoaded() && actualClass->IsLoaded() && strcmp( claim->GetTypeInfo()->name(), actualClass->GetTypeInfo()->name() ) == 0) {
1575 // The type is the same according to the C++ type_info, we must be in the case of
1576 // a template of Double32_t. This is actually a correct case.
1577 } else {
1578 Error("Branch", "The actual class (%s) of the object provided for the definition of the branch \"%s\" does not inherit from %s",
1579 actualClass->GetName(), branchname, claim->GetName());
1580 }
1581 }
1582 }
1583 if (!actualClass) {
1584 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",
1585 branchname, ptrClass->GetName());
1586 actualClass = ptrClass;
1587 } else if ((ptrClass != actualClass) && !actualClass->InheritsFrom(ptrClass)) {
1588 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());
1589 return 0;
1590 }
1591 if (actualClass && actualClass->GetCollectionProxy() && dynamic_cast<TEmulatedCollectionProxy*>(actualClass->GetCollectionProxy())) {
1592 Error("Branch", writeStlWithoutProxyMsg,
1593 actualClass->GetName(), branchname, actualClass->GetName());
1594 return 0;
1595 }
1596 return BronchExec(branchname, actualClass->GetName(), (void*) addobj, kFALSE, bufsize, splitlevel);
1597}
1598
1599////////////////////////////////////////////////////////////////////////////////
1600/// Same as TTree::Branch but automatic detection of the class name.
1601/// See TTree::Branch for other details.
1603TBranch* TTree::BranchImpRef(const char* branchname, TClass* ptrClass, EDataType datatype, void* addobj, Int_t bufsize, Int_t splitlevel)
1604{
1605 if (!ptrClass) {
1606 if (datatype == kOther_t || datatype == kNoType_t) {
1607 Error("Branch", "The pointer specified for %s is not of a class or type known to ROOT", branchname);
1608 } else {
1609 TString varname; varname.Form("%s/%c",branchname,DataTypeToChar(datatype));
1610 return Branch(branchname,addobj,varname.Data(),bufsize);
1611 }
1612 return 0;
1613 }
1614 TClass* actualClass = 0;
1615 if (!addobj) {
1616 Error("Branch", "Reference interface requires a valid object (for branch: %s)!", branchname);
1617 return 0;
1618 }
1619 actualClass = ptrClass->GetActualClass(addobj);
1620 if (!actualClass) {
1621 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",
1622 branchname, ptrClass->GetName());
1623 actualClass = ptrClass;
1624 } else if ((ptrClass != actualClass) && !actualClass->InheritsFrom(ptrClass)) {
1625 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());
1626 return 0;
1627 }
1628 if (actualClass && actualClass->GetCollectionProxy() && dynamic_cast<TEmulatedCollectionProxy*>(actualClass->GetCollectionProxy())) {
1629 Error("Branch", writeStlWithoutProxyMsg,
1630 actualClass->GetName(), branchname, actualClass->GetName());
1631 return 0;
1632 }
1633 return BronchExec(branchname, actualClass->GetName(), (void*) addobj, kFALSE, bufsize, splitlevel);
1634}
1635
1636////////////////////////////////////////////////////////////////////////////////
1637/// Deprecated function. Use next function instead.
1639Int_t TTree::Branch(TList* li, Int_t bufsize /* = 32000 */ , Int_t splitlevel /* = 99 */)
1640{
1641 return Branch((TCollection*) li, bufsize, splitlevel);
1642}
1643
1644////////////////////////////////////////////////////////////////////////////////
1645/// Create one branch for each element in the collection.
1646///
1647/// Each entry in the collection becomes a top level branch if the
1648/// corresponding class is not a collection. If it is a collection, the entry
1649/// in the collection becomes in turn top level branches, etc.
1650/// The splitlevel is decreased by 1 every time a new collection is found.
1651/// For example if list is a TObjArray*
1652/// - if splitlevel = 1, one top level branch is created for each element
1653/// of the TObjArray.
1654/// - if splitlevel = 2, one top level branch is created for each array element.
1655/// if, in turn, one of the array elements is a TCollection, one top level
1656/// branch will be created for each element of this collection.
1657///
1658/// In case a collection element is a TClonesArray, the special Tree constructor
1659/// for TClonesArray is called.
1660/// The collection itself cannot be a TClonesArray.
1661///
1662/// The function returns the total number of branches created.
1663///
1664/// If name is given, all branch names will be prefixed with name_.
1665///
1666/// IMPORTANT NOTE1: This function should not be called with splitlevel < 1.
1667///
1668/// IMPORTANT NOTE2: The branches created by this function will have names
1669/// corresponding to the collection or object names. It is important
1670/// to give names to collections to avoid misleading branch names or
1671/// identical branch names. By default collections have a name equal to
1672/// the corresponding class name, e.g. the default name for a TList is "TList".
1673///
1674/// And in general, in case two or more master branches contain subbranches
1675/// with identical names, one must add a "." (dot) character at the end
1676/// of the master branch name. This will force the name of the subbranches
1677/// to be of the form `master.subbranch` instead of simply `subbranch`.
1678/// This situation happens when the top level object
1679/// has two or more members referencing the same class.
1680/// For example, if a Tree has two branches B1 and B2 corresponding
1681/// to objects of the same class MyClass, one can do:
1682/// ~~~ {.cpp}
1683/// tree.Branch("B1.","MyClass",&b1,8000,1);
1684/// tree.Branch("B2.","MyClass",&b2,8000,1);
1685/// ~~~
1686/// if MyClass has 3 members a,b,c, the two instructions above will generate
1687/// subbranches called B1.a, B1.b ,B1.c, B2.a, B2.b, B2.c
1688///
1689/// Example:
1690/// ~~~ {.cpp}
1691/// {
1692/// TTree T("T","test list");
1693/// TList *list = new TList();
1694///
1695/// TObjArray *a1 = new TObjArray();
1696/// a1->SetName("a1");
1697/// list->Add(a1);
1698/// TH1F *ha1a = new TH1F("ha1a","ha1",100,0,1);
1699/// TH1F *ha1b = new TH1F("ha1b","ha1",100,0,1);
1700/// a1->Add(ha1a);
1701/// a1->Add(ha1b);
1702/// TObjArray *b1 = new TObjArray();
1703/// b1->SetName("b1");
1704/// list->Add(b1);
1705/// TH1F *hb1a = new TH1F("hb1a","hb1",100,0,1);
1706/// TH1F *hb1b = new TH1F("hb1b","hb1",100,0,1);
1707/// b1->Add(hb1a);
1708/// b1->Add(hb1b);
1709///
1710/// TObjArray *a2 = new TObjArray();
1711/// a2->SetName("a2");
1712/// list->Add(a2);
1713/// TH1S *ha2a = new TH1S("ha2a","ha2",100,0,1);
1714/// TH1S *ha2b = new TH1S("ha2b","ha2",100,0,1);
1715/// a2->Add(ha2a);
1716/// a2->Add(ha2b);
1717///
1718/// T.Branch(list,16000,2);
1719/// T.Print();
1720/// }
1721/// ~~~
1723Int_t TTree::Branch(TCollection* li, Int_t bufsize /* = 32000 */, Int_t splitlevel /* = 99 */, const char* name /* = "" */)
1724{
1725
1726 if (!li) {
1727 return 0;
1728 }
1729 TObject* obj = 0;
1730 Int_t nbranches = GetListOfBranches()->GetEntries();
1731 if (li->InheritsFrom(TClonesArray::Class())) {
1732 Error("Branch", "Cannot call this constructor for a TClonesArray");
1733 return 0;
1734 }
1735 Int_t nch = strlen(name);
1736 TString branchname;
1737 TIter next(li);
1738 while ((obj = next())) {
1739 if ((splitlevel > 1) && obj->InheritsFrom(TCollection::Class()) && !obj->InheritsFrom(TClonesArray::Class())) {
1740 TCollection* col = (TCollection*) obj;
1741 if (nch) {
1742 branchname.Form("%s_%s_", name, col->GetName());
1743 } else {
1744 branchname.Form("%s_", col->GetName());
1745 }
1746 Branch(col, bufsize, splitlevel - 1, branchname);
1747 } else {
1748 if (nch && (name[nch-1] == '_')) {
1749 branchname.Form("%s%s", name, obj->GetName());
1750 } else {
1751 if (nch) {
1752 branchname.Form("%s_%s", name, obj->GetName());
1753 } else {
1754 branchname.Form("%s", obj->GetName());
1755 }
1756 }
1757 if (splitlevel > 99) {
1758 branchname += ".";
1759 }
1760 Bronch(branchname, obj->ClassName(), li->GetObjectRef(obj), bufsize, splitlevel - 1);
1761 }
1762 }
1763 return GetListOfBranches()->GetEntries() - nbranches;
1764}
1765
1766////////////////////////////////////////////////////////////////////////////////
1767/// Create one branch for each element in the folder.
1768/// Returns the total number of branches created.
1770Int_t TTree::Branch(const char* foldername, Int_t bufsize /* = 32000 */, Int_t splitlevel /* = 99 */)
1771{
1772 TObject* ob = gROOT->FindObjectAny(foldername);
1773 if (!ob) {
1774 return 0;
1775 }
1776 if (ob->IsA() != TFolder::Class()) {
1777 return 0;
1778 }
1779 Int_t nbranches = GetListOfBranches()->GetEntries();
1780 TFolder* folder = (TFolder*) ob;
1781 TIter next(folder->GetListOfFolders());
1782 TObject* obj = 0;
1783 char* curname = new char[1000];
1784 char occur[20];
1785 while ((obj = next())) {
1786 snprintf(curname,1000, "%s/%s", foldername, obj->GetName());
1787 if (obj->IsA() == TFolder::Class()) {
1788 Branch(curname, bufsize, splitlevel - 1);
1789 } else {
1790 void* add = (void*) folder->GetListOfFolders()->GetObjectRef(obj);
1791 for (Int_t i = 0; i < 1000; ++i) {
1792 if (curname[i] == 0) {
1793 break;
1794 }
1795 if (curname[i] == '/') {
1796 curname[i] = '.';
1797 }
1798 }
1799 Int_t noccur = folder->Occurence(obj);
1800 if (noccur > 0) {
1801 snprintf(occur,20, "_%d", noccur);
1802 strlcat(curname, occur,1000);
1803 }
1804 TBranchElement* br = (TBranchElement*) Bronch(curname, obj->ClassName(), add, bufsize, splitlevel - 1);
1805 if (br) br->SetBranchFolder();
1806 }
1807 }
1808 delete[] curname;
1809 return GetListOfBranches()->GetEntries() - nbranches;
1810}
1811
1812////////////////////////////////////////////////////////////////////////////////
1813/// Create a new TTree Branch.
1814///
1815/// This Branch constructor is provided to support non-objects in
1816/// a Tree. The variables described in leaflist may be simple
1817/// variables or structures. // See the two following
1818/// constructors for writing objects in a Tree.
1819///
1820/// By default the branch buffers are stored in the same file as the Tree.
1821/// use TBranch::SetFile to specify a different file
1822///
1823/// * address is the address of the first item of a structure.
1824/// * leaflist is the concatenation of all the variable names and types
1825/// separated by a colon character :
1826/// The variable name and the variable type are separated by a slash (/).
1827/// The variable type may be 0,1 or 2 characters. If no type is given,
1828/// the type of the variable is assumed to be the same as the previous
1829/// variable. If the first variable does not have a type, it is assumed
1830/// of type F by default. The list of currently supported types is given below:
1831/// - `C` : a character string terminated by the 0 character
1832/// - `B` : an 8 bit signed integer (`Char_t`)
1833/// - `b` : an 8 bit unsigned integer (`UChar_t`)
1834/// - `S` : a 16 bit signed integer (`Short_t`)
1835/// - `s` : a 16 bit unsigned integer (`UShort_t`)
1836/// - `I` : a 32 bit signed integer (`Int_t`)
1837/// - `i` : a 32 bit unsigned integer (`UInt_t`)
1838/// - `F` : a 32 bit floating point (`Float_t`)
1839/// - `D` : a 64 bit floating point (`Double_t`)
1840/// - `L` : a 64 bit signed integer (`Long64_t`)
1841/// - `l` : a 64 bit unsigned integer (`ULong64_t`)
1842/// - `O` : [the letter `o`, not a zero] a boolean (`Bool_t`)
1843///
1844/// Arrays of values are supported with the following syntax:
1845/// - If leaf name has the form var[nelem], where nelem is alphanumeric, then
1846/// if nelem is a leaf name, it is used as the variable size of the array,
1847/// otherwise return 0.
1848/// - If leaf name has the form var[nelem], where nelem is a non-negative integer, then
1849/// it is used as the fixed size of the array.
1850/// - If leaf name has the form of a multi-dimensional array (e.g. var[nelem][nelem2])
1851/// where nelem and nelem2 are non-negative integer) then
1852/// it is used as a 2 dimensional array of fixed size.
1853///
1854/// Any of other form is not supported.
1855///
1856/// Note that the TTree will assume that all the item are contiguous in memory.
1857/// On some platform, this is not always true of the member of a struct or a class,
1858/// due to padding and alignment. Sorting your data member in order of decreasing
1859/// sizeof usually leads to their being contiguous in memory.
1860///
1861/// * bufsize is the buffer size in bytes for this branch
1862/// The default value is 32000 bytes and should be ok for most cases.
1863/// You can specify a larger value (e.g. 256000) if your Tree is not split
1864/// and each entry is large (Megabytes)
1865/// A small value for bufsize is optimum if you intend to access
1866/// the entries in the Tree randomly and your Tree is in split mode.
1868TBranch* TTree::Branch(const char* name, void* address, const char* leaflist, Int_t bufsize /* = 32000 */)
1869{
1870 TBranch* branch = new TBranch(this, name, address, leaflist, bufsize);
1871 if (branch->IsZombie()) {
1872 delete branch;
1873 branch = 0;
1874 return 0;
1875 }
1876 fBranches.Add(branch);
1877 return branch;
1878}
1879
1880////////////////////////////////////////////////////////////////////////////////
1881/// Create a new branch with the object of class classname at address addobj.
1882///
1883/// WARNING:
1884///
1885/// Starting with Root version 3.01, the Branch function uses the new style
1886/// branches (TBranchElement). To get the old behaviour, you can:
1887/// - call BranchOld or
1888/// - call TTree::SetBranchStyle(0)
1889///
1890/// Note that with the new style, classname does not need to derive from TObject.
1891/// It must derived from TObject if the branch style has been set to 0 (old)
1892///
1893/// Note: See the comments in TBranchElement::SetAddress() for a more
1894/// detailed discussion of the meaning of the addobj parameter in
1895/// the case of new-style branches.
1896///
1897/// Use splitlevel < 0 instead of splitlevel=0 when the class
1898/// has a custom Streamer
1899///
1900/// Note: if the split level is set to the default (99), TTree::Branch will
1901/// not issue a warning if the class can not be split.
1903TBranch* TTree::Branch(const char* name, const char* classname, void* addobj, Int_t bufsize /* = 32000 */, Int_t splitlevel /* = 99 */)
1904{
1905 if (fgBranchStyle == 1) {
1906 return Bronch(name, classname, addobj, bufsize, splitlevel);
1907 } else {
1908 if (splitlevel < 0) {
1909 splitlevel = 0;
1910 }
1911 return BranchOld(name, classname, addobj, bufsize, splitlevel);
1912 }
1913}
1914
1915////////////////////////////////////////////////////////////////////////////////
1916/// Create a new TTree BranchObject.
1917///
1918/// Build a TBranchObject for an object of class classname.
1919/// addobj is the address of a pointer to an object of class classname.
1920/// IMPORTANT: classname must derive from TObject.
1921/// The class dictionary must be available (ClassDef in class header).
1922///
1923/// This option requires access to the library where the corresponding class
1924/// is defined. Accessing one single data member in the object implies
1925/// reading the full object.
1926/// See the next Branch constructor for a more efficient storage
1927/// in case the entry consists of arrays of identical objects.
1928///
1929/// By default the branch buffers are stored in the same file as the Tree.
1930/// use TBranch::SetFile to specify a different file
1931///
1932/// IMPORTANT NOTE about branch names:
1933///
1934/// And in general, in case two or more master branches contain subbranches
1935/// with identical names, one must add a "." (dot) character at the end
1936/// of the master branch name. This will force the name of the subbranches
1937/// to be of the form `master.subbranch` instead of simply `subbranch`.
1938/// This situation happens when the top level object
1939/// has two or more members referencing the same class.
1940/// For example, if a Tree has two branches B1 and B2 corresponding
1941/// to objects of the same class MyClass, one can do:
1942/// ~~~ {.cpp}
1943/// tree.Branch("B1.","MyClass",&b1,8000,1);
1944/// tree.Branch("B2.","MyClass",&b2,8000,1);
1945/// ~~~
1946/// if MyClass has 3 members a,b,c, the two instructions above will generate
1947/// subbranches called B1.a, B1.b ,B1.c, B2.a, B2.b, B2.c
1948///
1949/// bufsize is the buffer size in bytes for this branch
1950/// The default value is 32000 bytes and should be ok for most cases.
1951/// You can specify a larger value (e.g. 256000) if your Tree is not split
1952/// and each entry is large (Megabytes)
1953/// A small value for bufsize is optimum if you intend to access
1954/// the entries in the Tree randomly and your Tree is in split mode.
1956TBranch* TTree::BranchOld(const char* name, const char* classname, void* addobj, Int_t bufsize /* = 32000 */, Int_t splitlevel /* = 1 */)
1957{
1958 TClass* cl = TClass::GetClass(classname);
1959 if (!cl) {
1960 Error("BranchOld", "Cannot find class: '%s'", classname);
1961 return 0;
1962 }
1963 if (!cl->IsTObject()) {
1964 if (fgBranchStyle == 0) {
1965 Fatal("BranchOld", "The requested class ('%s') does not inherit from TObject.\n"
1966 "\tfgBranchStyle is set to zero requesting by default to use BranchOld.\n"
1967 "\tIf this is intentional use Bronch instead of Branch or BranchOld.", classname);
1968 } else {
1969 Fatal("BranchOld", "The requested class ('%s') does not inherit from TObject.\n"
1970 "\tYou can not use BranchOld to store objects of this type.",classname);
1971 }
1972 return 0;
1973 }
1974 TBranch* branch = new TBranchObject(this, name, classname, addobj, bufsize, splitlevel);
1975 fBranches.Add(branch);
1976 if (!splitlevel) {
1977 return branch;
1978 }
1979 // We are going to fully split the class now.
1980 TObjArray* blist = branch->GetListOfBranches();
1981 const char* rdname = 0;
1982 const char* dname = 0;
1983 TString branchname;
1984 char** apointer = (char**) addobj;
1985 TObject* obj = (TObject*) *apointer;
1986 Bool_t delobj = kFALSE;
1987 if (!obj) {
1988 obj = (TObject*) cl->New();
1989 delobj = kTRUE;
1990 }
1991 // Build the StreamerInfo if first time for the class.
1992 BuildStreamerInfo(cl, obj);
1993 // Loop on all public data members of the class and its base classes.
1994 Int_t lenName = strlen(name);
1995 Int_t isDot = 0;
1996 if (name[lenName-1] == '.') {
1997 isDot = 1;
1998 }
1999 TBranch* branch1 = 0;
2000 TRealData* rd = 0;
2001 TRealData* rdi = 0;
2002 TIter nexti(cl->GetListOfRealData());
2003 TIter next(cl->GetListOfRealData());
2004 // Note: This loop results in a full split because the
2005 // real data list includes all data members of
2006 // data members.
2007 while ((rd = (TRealData*) next())) {
2008 if (rd->TestBit(TRealData::kTransient)) continue;
2009
2010 // Loop over all data members creating branches for each one.
2011 TDataMember* dm = rd->GetDataMember();
2012 if (!dm->IsPersistent()) {
2013 // Do not process members with an "!" as the first character in the comment field.
2014 continue;
2015 }
2016 if (rd->IsObject()) {
2017 // We skip data members of class type.
2018 // But we do build their real data, their
2019 // streamer info, and write their streamer
2020 // info to the current directory's file.
2021 // Oh yes, and we also do this for all of
2022 // their base classes.
2024 if (clm) {
2025 BuildStreamerInfo(clm, (char*) obj + rd->GetThisOffset());
2026 }
2027 continue;
2028 }
2029 rdname = rd->GetName();
2030 dname = dm->GetName();
2031 if (cl->CanIgnoreTObjectStreamer()) {
2032 // Skip the TObject base class data members.
2033 // FIXME: This prevents a user from ever
2034 // using these names themself!
2035 if (!strcmp(dname, "fBits")) {
2036 continue;
2037 }
2038 if (!strcmp(dname, "fUniqueID")) {
2039 continue;
2040 }
2041 }
2042 TDataType* dtype = dm->GetDataType();
2043 Int_t code = 0;
2044 if (dtype) {
2045 code = dm->GetDataType()->GetType();
2046 }
2047 // Encode branch name. Use real data member name
2048 branchname = rdname;
2049 if (isDot) {
2050 if (dm->IsaPointer()) {
2051 // FIXME: This is wrong! The asterisk is not usually in the front!
2052 branchname.Form("%s%s", name, &rdname[1]);
2053 } else {
2054 branchname.Form("%s%s", name, &rdname[0]);
2055 }
2056 }
2057 // FIXME: Change this to a string stream.
2058 TString leaflist;
2059 Int_t offset = rd->GetThisOffset();
2060 char* pointer = ((char*) obj) + offset;
2061 if (dm->IsaPointer()) {
2062 // We have a pointer to an object or a pointer to an array of basic types.
2063 TClass* clobj = 0;
2064 if (!dm->IsBasic()) {
2065 clobj = TClass::GetClass(dm->GetTypeName());
2066 }
2067 if (clobj && clobj->InheritsFrom(TClonesArray::Class())) {
2068 // We have a pointer to a clones array.
2069 char* cpointer = (char*) pointer;
2070 char** ppointer = (char**) cpointer;
2071 TClonesArray* li = (TClonesArray*) *ppointer;
2072 if (splitlevel != 2) {
2073 if (isDot) {
2074 branch1 = new TBranchClones(branch,branchname, pointer, bufsize);
2075 } else {
2076 // FIXME: This is wrong! The asterisk is not usually in the front!
2077 branch1 = new TBranchClones(branch,&branchname.Data()[1], pointer, bufsize);
2078 }
2079 blist->Add(branch1);
2080 } else {
2081 if (isDot) {
2082 branch1 = new TBranchObject(branch, branchname, li->ClassName(), pointer, bufsize);
2083 } else {
2084 // FIXME: This is wrong! The asterisk is not usually in the front!
2085 branch1 = new TBranchObject(branch, &branchname.Data()[1], li->ClassName(), pointer, bufsize);
2086 }
2087 blist->Add(branch1);
2088 }
2089 } else if (clobj) {
2090 // We have a pointer to an object.
2091 //
2092 // It must be a TObject object.
2093 if (!clobj->IsTObject()) {
2094 continue;
2095 }
2096 branch1 = new TBranchObject(branch, dname, clobj->GetName(), pointer, bufsize, 0);
2097 if (isDot) {
2098 branch1->SetName(branchname);
2099 } else {
2100 // FIXME: This is wrong! The asterisk is not usually in the front!
2101 // Do not use the first character (*).
2102 branch1->SetName(&branchname.Data()[1]);
2103 }
2104 blist->Add(branch1);
2105 } else {
2106 // We have a pointer to an array of basic types.
2107 //
2108 // Check the comments in the text of the code for an index specification.
2109 const char* index = dm->GetArrayIndex();
2110 if (index[0]) {
2111 // We are a pointer to a varying length array of basic types.
2112 //check that index is a valid data member name
2113 //if member is part of an object (e.g. fA and index=fN)
2114 //index must be changed from fN to fA.fN
2115 TString aindex (rd->GetName());
2116 Ssiz_t rdot = aindex.Last('.');
2117 if (rdot>=0) {
2118 aindex.Remove(rdot+1);
2119 aindex.Append(index);
2120 }
2121 nexti.Reset();
2122 while ((rdi = (TRealData*) nexti())) {
2123 if (rdi->TestBit(TRealData::kTransient)) continue;
2124
2125 if (!strcmp(rdi->GetName(), index)) {
2126 break;
2127 }
2128 if (!strcmp(rdi->GetName(), aindex)) {
2129 index = rdi->GetName();
2130 break;
2131 }
2132 }
2133
2134 char vcode = DataTypeToChar((EDataType)code);
2135 // Note that we differentiate between strings and
2136 // char array by the fact that there is NO specified
2137 // size for a string (see next if (code == 1)
2138
2139 if (vcode) {
2140 leaflist.Form("%s[%s]/%c", &rdname[0], index, vcode);
2141 } else {
2142 Error("BranchOld", "Cannot create branch for rdname: %s code: %d", branchname.Data(), code);
2143 leaflist = "";
2144 }
2145 } else {
2146 // We are possibly a character string.
2147 if (code == 1) {
2148 // We are a character string.
2149 leaflist.Form("%s/%s", dname, "C");
2150 } else {
2151 // Invalid array specification.
2152 // FIXME: We need an error message here.
2153 continue;
2154 }
2155 }
2156 // There are '*' in both the branchname and leaflist, remove them.
2157 TString bname( branchname );
2158 bname.ReplaceAll("*","");
2159 leaflist.ReplaceAll("*","");
2160 // Add the branch to the tree and indicate that the address
2161 // is that of a pointer to be dereferenced before using.
2162 branch1 = new TBranch(branch, bname, *((void**) pointer), leaflist, bufsize);
2163 TLeaf* leaf = (TLeaf*) branch1->GetListOfLeaves()->At(0);
2165 leaf->SetAddress((void**) pointer);
2166 blist->Add(branch1);
2167 }
2168 } else if (dm->IsBasic()) {
2169 // We have a basic type.
2170
2171 char vcode = DataTypeToChar((EDataType)code);
2172 if (vcode) {
2173 leaflist.Form("%s/%c", rdname, vcode);
2174 } else {
2175 Error("BranchOld", "Cannot create branch for rdname: %s code: %d", branchname.Data(), code);
2176 leaflist = "";
2177 }
2178 branch1 = new TBranch(branch, branchname, pointer, leaflist, bufsize);
2179 branch1->SetTitle(rdname);
2180 blist->Add(branch1);
2181 } else {
2182 // We have a class type.
2183 // Note: This cannot happen due to the rd->IsObject() test above.
2184 // FIXME: Put an error message here just in case.
2185 }
2186 if (branch1) {
2187 branch1->SetOffset(offset);
2188 } else {
2189 Warning("BranchOld", "Cannot process member: '%s'", rdname);
2190 }
2191 }
2192 if (delobj) {
2193 delete obj;
2194 obj = 0;
2195 }
2196 return branch;
2197}
2198
2199////////////////////////////////////////////////////////////////////////////////
2200/// Build the optional branch supporting the TRefTable.
2201/// This branch will keep all the information to find the branches
2202/// containing referenced objects.
2203///
2204/// At each Tree::Fill, the branch numbers containing the
2205/// referenced objects are saved to the TBranchRef basket.
2206/// When the Tree header is saved (via TTree::Write), the branch
2207/// is saved keeping the information with the pointers to the branches
2208/// having referenced objects.
2211{
2212 if (!fBranchRef) {
2213 fBranchRef = new TBranchRef(this);
2214 }
2215 return fBranchRef;
2216}
2217
2218////////////////////////////////////////////////////////////////////////////////
2219/// Create a new TTree BranchElement.
2220///
2221/// ## WARNING about this new function
2222///
2223/// This function is designed to replace the internal
2224/// implementation of the old TTree::Branch (whose implementation
2225/// has been moved to BranchOld).
2226///
2227/// NOTE: The 'Bronch' method supports only one possible calls
2228/// signature (where the object type has to be specified
2229/// explicitly and the address must be the address of a pointer).
2230/// For more flexibility use 'Branch'. Use Bronch only in (rare)
2231/// cases (likely to be legacy cases) where both the new and old
2232/// implementation of Branch needs to be used at the same time.
2233///
2234/// This function is far more powerful than the old Branch
2235/// function. It supports the full C++, including STL and has
2236/// the same behaviour in split or non-split mode. classname does
2237/// not have to derive from TObject. The function is based on
2238/// the new TStreamerInfo.
2239///
2240/// Build a TBranchElement for an object of class classname.
2241///
2242/// addr is the address of a pointer to an object of class
2243/// classname. The class dictionary must be available (ClassDef
2244/// in class header).
2245///
2246/// Note: See the comments in TBranchElement::SetAddress() for a more
2247/// detailed discussion of the meaning of the addr parameter.
2248///
2249/// This option requires access to the library where the
2250/// corresponding class is defined. Accessing one single data
2251/// member in the object implies reading the full object.
2252///
2253/// By default the branch buffers are stored in the same file as the Tree.
2254/// use TBranch::SetFile to specify a different file
2255///
2256/// IMPORTANT NOTE about branch names:
2257///
2258/// And in general, in case two or more master branches contain subbranches
2259/// with identical names, one must add a "." (dot) character at the end
2260/// of the master branch name. This will force the name of the subbranches
2261/// to be of the form `master.subbranch` instead of simply `subbranch`.
2262/// This situation happens when the top level object
2263/// has two or more members referencing the same class.
2264/// For example, if a Tree has two branches B1 and B2 corresponding
2265/// to objects of the same class MyClass, one can do:
2266/// ~~~ {.cpp}
2267/// tree.Branch("B1.","MyClass",&b1,8000,1);
2268/// tree.Branch("B2.","MyClass",&b2,8000,1);
2269/// ~~~
2270/// if MyClass has 3 members a,b,c, the two instructions above will generate
2271/// subbranches called B1.a, B1.b ,B1.c, B2.a, B2.b, B2.c
2272///
2273/// bufsize is the buffer size in bytes for this branch
2274/// The default value is 32000 bytes and should be ok for most cases.
2275/// You can specify a larger value (e.g. 256000) if your Tree is not split
2276/// and each entry is large (Megabytes)
2277/// A small value for bufsize is optimum if you intend to access
2278/// the entries in the Tree randomly and your Tree is in split mode.
2279///
2280/// Use splitlevel < 0 instead of splitlevel=0 when the class
2281/// has a custom Streamer
2282///
2283/// Note: if the split level is set to the default (99), TTree::Branch will
2284/// not issue a warning if the class can not be split.
2286TBranch* TTree::Bronch(const char* name, const char* classname, void* addr, Int_t bufsize /* = 32000 */, Int_t splitlevel /* = 99 */)
2287{
2288 return BronchExec(name, classname, addr, kTRUE, bufsize, splitlevel);
2289}
2290
2291////////////////////////////////////////////////////////////////////////////////
2292/// Helper function implementing TTree::Bronch and TTree::Branch(const char *name, T &obj);
2294TBranch* TTree::BronchExec(const char* name, const char* classname, void* addr, Bool_t isptrptr, Int_t bufsize /* = 32000 */, Int_t splitlevel /* = 99 */)
2295{
2296 TClass* cl = TClass::GetClass(classname);
2297 if (!cl) {
2298 Error("Bronch", "Cannot find class:%s", classname);
2299 return 0;
2300 }
2301
2302 //if splitlevel <= 0 and class has a custom Streamer, we must create
2303 //a TBranchObject. We cannot assume that TClass::ReadBuffer is consistent
2304 //with the custom Streamer. The penalty is that one cannot process
2305 //this Tree without the class library containing the class.
2306
2307 char* objptr = 0;
2308 if (!isptrptr) {
2309 objptr = (char*)addr;
2310 } else if (addr) {
2311 objptr = *((char**) addr);
2312 }
2313
2314 if (cl == TClonesArray::Class()) {
2315 TClonesArray* clones = (TClonesArray*) objptr;
2316 if (!clones) {
2317 Error("Bronch", "Pointer to TClonesArray is null");
2318 return 0;
2319 }
2320 if (!clones->GetClass()) {
2321 Error("Bronch", "TClonesArray with no class defined in branch: %s", name);
2322 return 0;
2323 }
2324 if (!clones->GetClass()->HasDataMemberInfo()) {
2325 Error("Bronch", "TClonesArray with no dictionary defined in branch: %s", name);
2326 return 0;
2327 }
2328 bool hasCustomStreamer = clones->GetClass()->TestBit(TClass::kHasCustomStreamerMember);
2329 if (splitlevel > 0) {
2330 if (hasCustomStreamer)
2331 Warning("Bronch", "Using split mode on a class: %s with a custom Streamer", clones->GetClass()->GetName());
2332 } else {
2333 if (hasCustomStreamer) clones->BypassStreamer(kFALSE);
2334 TBranchObject *branch = new TBranchObject(this,name,classname,addr,bufsize,0,/*compress=*/ -1,isptrptr);
2335 fBranches.Add(branch);
2336 return branch;
2337 }
2338 }
2339
2340 if (cl->GetCollectionProxy()) {
2342 //if (!collProxy) {
2343 // Error("Bronch", "%s is missing its CollectionProxy (for branch %s)", classname, name);
2344 //}
2345 TClass* inklass = collProxy->GetValueClass();
2346 if (!inklass && (collProxy->GetType() == 0)) {
2347 Error("Bronch", "%s with no class defined in branch: %s", classname, name);
2348 return 0;
2349 }
2350 if ((splitlevel > 0) && inklass && (inklass->GetCollectionProxy() == 0)) {
2352 if ((stl != ROOT::kSTLmap) && (stl != ROOT::kSTLmultimap)) {
2353 if (!inklass->HasDataMemberInfo()) {
2354 Error("Bronch", "Container with no dictionary defined in branch: %s", name);
2355 return 0;
2356 }
2358 Warning("Bronch", "Using split mode on a class: %s with a custom Streamer", inklass->GetName());
2359 }
2360 }
2361 }
2362 //-------------------------------------------------------------------------
2363 // If the splitting switch is enabled, the split level is big enough and
2364 // the collection contains pointers we can split it
2365 //////////////////////////////////////////////////////////////////////////
2366
2367 TBranch *branch;
2368 if( splitlevel > kSplitCollectionOfPointers && collProxy->HasPointers() )
2369 branch = new TBranchSTL( this, name, collProxy, bufsize, splitlevel );
2370 else
2371 branch = new TBranchElement(this, name, collProxy, bufsize, splitlevel);
2372 fBranches.Add(branch);
2373 if (isptrptr) {
2374 branch->SetAddress(addr);
2375 } else {
2376 branch->SetObject(addr);
2377 }
2378 return branch;
2379 }
2380
2381 Bool_t hasCustomStreamer = kFALSE;
2382 if (!cl->HasDataMemberInfo() && !cl->GetCollectionProxy()) {
2383 Error("Bronch", "Cannot find dictionary for class: %s", classname);
2384 return 0;
2385 }
2386
2388 // Not an STL container and the linkdef file had a "-" after the class name.
2389 hasCustomStreamer = kTRUE;
2390 }
2391
2392 if (splitlevel < 0 || ((splitlevel == 0) && hasCustomStreamer && cl->IsTObject())) {
2393 TBranchObject* branch = new TBranchObject(this, name, classname, addr, bufsize, 0, /*compress=*/ ROOT::RCompressionSetting::EAlgorithm::kInherit, isptrptr);
2394 fBranches.Add(branch);
2395 return branch;
2396 }
2397
2398 if (cl == TClonesArray::Class()) {
2399 // Special case of TClonesArray.
2400 // No dummy object is created.
2401 // The streamer info is not rebuilt unoptimized.
2402 // No dummy top-level branch is created.
2403 // No splitting is attempted.
2404 TBranchElement* branch = new TBranchElement(this, name, (TClonesArray*) objptr, bufsize, splitlevel%kSplitCollectionOfPointers);
2405 fBranches.Add(branch);
2406 if (isptrptr) {
2407 branch->SetAddress(addr);
2408 } else {
2409 branch->SetObject(addr);
2410 }
2411 return branch;
2412 }
2413
2414 //
2415 // If we are not given an object to use as an i/o buffer
2416 // then create a temporary one which we will delete just
2417 // before returning.
2418 //
2419
2420 Bool_t delobj = kFALSE;
2421
2422 if (!objptr) {
2423 objptr = (char*) cl->New();
2424 delobj = kTRUE;
2425 }
2426
2427 //
2428 // Avoid splitting unsplittable classes.
2429 //
2430
2431 if ((splitlevel > 0) && !cl->CanSplit()) {
2432 if (splitlevel != 99) {
2433 Warning("Bronch", "%s cannot be split, resetting splitlevel to 0", cl->GetName());
2434 }
2435 splitlevel = 0;
2436 }
2437
2438 //
2439 // Make sure the streamer info is built and fetch it.
2440 //
2441 // If we are splitting, then make sure the streamer info
2442 // is built unoptimized (data members are not combined).
2443 //
2444
2445 TStreamerInfo* sinfo = BuildStreamerInfo(cl, objptr, splitlevel==0);
2446 if (!sinfo) {
2447 Error("Bronch", "Cannot build the StreamerInfo for class: %s", cl->GetName());
2448 return 0;
2449 }
2450
2451 //
2452 // Create a dummy top level branch object.
2453 //
2454
2455 Int_t id = -1;
2456 if (splitlevel > 0) {
2457 id = -2;
2458 }
2459 TBranchElement* branch = new TBranchElement(this, name, sinfo, id, objptr, bufsize, splitlevel);
2460 fBranches.Add(branch);
2461
2462 //
2463 // Do splitting, if requested.
2464 //
2465
2466 if (splitlevel%kSplitCollectionOfPointers > 0) {
2467 branch->Unroll(name, cl, sinfo, objptr, bufsize, splitlevel);
2468 }
2469
2470 //
2471 // Setup our offsets into the user's i/o buffer.
2472 //
2473
2474 if (isptrptr) {
2475 branch->SetAddress(addr);
2476 } else {
2477 branch->SetObject(addr);
2478 }
2479
2480 if (delobj) {
2481 cl->Destructor(objptr);
2482 objptr = 0;
2483 }
2484
2485 return branch;
2486}
2487
2488////////////////////////////////////////////////////////////////////////////////
2489/// Browse content of the TTree.
2492{
2494 if (fUserInfo) {
2495 if (strcmp("TList",fUserInfo->GetName())==0) {
2496 fUserInfo->SetName("UserInfo");
2497 b->Add(fUserInfo);
2498 fUserInfo->SetName("TList");
2499 } else {
2500 b->Add(fUserInfo);
2501 }
2502 }
2503}
2504
2505////////////////////////////////////////////////////////////////////////////////
2506/// Build a Tree Index (default is TTreeIndex).
2507/// See a description of the parameters and functionality in
2508/// TTreeIndex::TTreeIndex().
2509///
2510/// The return value is the number of entries in the Index (< 0 indicates failure).
2511///
2512/// A TTreeIndex object pointed by fTreeIndex is created.
2513/// This object will be automatically deleted by the TTree destructor.
2514/// If an index is already existing, this is replaced by the new one without being
2515/// deleted. This behaviour prevents the deletion of a previously external index
2516/// assigned to the TTree via the TTree::SetTreeIndex() method.
2517/// See also comments in TTree::SetTreeIndex().
2519Int_t TTree::BuildIndex(const char* majorname, const char* minorname /* = "0" */)
2520{
2521 fTreeIndex = GetPlayer()->BuildIndex(this, majorname, minorname);
2522 if (fTreeIndex->IsZombie()) {
2523 delete fTreeIndex;
2524 fTreeIndex = 0;
2525 return 0;
2526 }
2527 return fTreeIndex->GetN();
2528}
2529
2530////////////////////////////////////////////////////////////////////////////////
2531/// Build StreamerInfo for class cl.
2532/// pointer is an optional argument that may contain a pointer to an object of cl.
2534TStreamerInfo* TTree::BuildStreamerInfo(TClass* cl, void* pointer /* = 0 */, Bool_t canOptimize /* = kTRUE */ )
2535{
2536 if (!cl) {
2537 return 0;
2538 }
2539 cl->BuildRealData(pointer);
2541
2542 // Create StreamerInfo for all base classes.
2543 TBaseClass* base = 0;
2544 TIter nextb(cl->GetListOfBases());
2545 while((base = (TBaseClass*) nextb())) {
2546 if (base->IsSTLContainer()) {
2547 continue;
2548 }
2549 TClass* clm = TClass::GetClass(base->GetName());
2550 BuildStreamerInfo(clm, pointer, canOptimize);
2551 }
2552 if (sinfo && fDirectory) {
2554 }
2555 return sinfo;
2556}
2557
2558////////////////////////////////////////////////////////////////////////////////
2559/// Called by TTree::Fill() when file has reached its maximum fgMaxTreeSize.
2560/// Create a new file. If the original file is named "myfile.root",
2561/// subsequent files are named "myfile_1.root", "myfile_2.root", etc.
2562///
2563/// Returns a pointer to the new file.
2564///
2565/// Currently, the automatic change of file is restricted
2566/// to the case where the tree is in the top level directory.
2567/// The file should not contain sub-directories.
2568///
2569/// Before switching to a new file, the tree header is written
2570/// to the current file, then the current file is closed.
2571///
2572/// To process the multiple files created by ChangeFile, one must use
2573/// a TChain.
2574///
2575/// The new file name has a suffix "_N" where N is equal to fFileNumber+1.
2576/// By default a Root session starts with fFileNumber=0. One can set
2577/// fFileNumber to a different value via TTree::SetFileNumber.
2578/// In case a file named "_N" already exists, the function will try
2579/// a file named "__N", then "___N", etc.
2580///
2581/// fgMaxTreeSize can be set via the static function TTree::SetMaxTreeSize.
2582/// The default value of fgMaxTreeSize is 100 Gigabytes.
2583///
2584/// If the current file contains other objects like TH1 and TTree,
2585/// these objects are automatically moved to the new file.
2586///
2587/// IMPORTANT NOTE:
2588///
2589/// Be careful when writing the final Tree header to the file!
2590///
2591/// Don't do:
2592/// ~~~ {.cpp}
2593/// TFile *file = new TFile("myfile.root","recreate");
2594/// TTree *T = new TTree("T","title");
2595/// T->Fill(); //loop
2596/// file->Write();
2597/// file->Close();
2598/// ~~~
2599/// but do the following:
2600/// ~~~ {.cpp}
2601/// TFile *file = new TFile("myfile.root","recreate");
2602/// TTree *T = new TTree("T","title");
2603/// T->Fill(); //loop
2604/// file = T->GetCurrentFile(); //to get the pointer to the current file
2605/// file->Write();
2606/// file->Close();
2607/// ~~~
2610{
2611 file->cd();
2612 Write();
2613 Reset();
2614 constexpr auto kBufSize = 2000;
2615 char* fname = new char[kBufSize];
2616 ++fFileNumber;
2617 char uscore[10];
2618 for (Int_t i = 0; i < 10; ++i) {
2619 uscore[i] = 0;
2620 }
2621 Int_t nus = 0;
2622 // Try to find a suitable file name that does not already exist.
2623 while (nus < 10) {
2624 uscore[nus] = '_';
2625 fname[0] = 0;
2626 strlcpy(fname, file->GetName(), kBufSize);
2627
2628 if (fFileNumber > 1) {
2629 char* cunder = strrchr(fname, '_');
2630 if (cunder) {
2631 snprintf(cunder, kBufSize - Int_t(cunder - fname), "%s%d", uscore, fFileNumber);
2632 const char* cdot = strrchr(file->GetName(), '.');
2633 if (cdot) {
2634 strlcat(fname, cdot, kBufSize);
2635 }
2636 } else {
2637 char fcount[21];
2638 snprintf(fcount,21, "%s%d", uscore, fFileNumber);
2639 strlcat(fname, fcount, kBufSize);
2640 }
2641 } else {
2642 char* cdot = strrchr(fname, '.');
2643 if (cdot) {
2644 snprintf(cdot, kBufSize - Int_t(fname-cdot), "%s%d", uscore, fFileNumber);
2645 strlcat(fname, strrchr(file->GetName(), '.'), kBufSize);
2646 } else {
2647 char fcount[21];
2648 snprintf(fcount,21, "%s%d", uscore, fFileNumber);
2649 strlcat(fname, fcount, kBufSize);
2650 }
2651 }
2652 if (gSystem->AccessPathName(fname)) {
2653 break;
2654 }
2655 ++nus;
2656 Warning("ChangeFile", "file %s already exist, trying with %d underscores", fname, nus+1);
2657 }
2658 Int_t compress = file->GetCompressionSettings();
2659 TFile* newfile = TFile::Open(fname, "recreate", "chain files", compress);
2660 if (newfile == 0) {
2661 Error("Fill","Failed to open new file %s, continuing as a memory tree.",fname);
2662 } else {
2663 Printf("Fill: Switching to new file: %s", fname);
2664 }
2665 // The current directory may contain histograms and trees.
2666 // These objects must be moved to the new file.
2667 TBranch* branch = 0;
2668 TObject* obj = 0;
2669 while ((obj = file->GetList()->First())) {
2670 file->Remove(obj);
2671 // Histogram: just change the directory.
2672 if (obj->InheritsFrom("TH1")) {
2673 gROOT->ProcessLine(TString::Format("((%s*)0x%lx)->SetDirectory((TDirectory*)0x%lx);", obj->ClassName(), (Long_t) obj, (Long_t) newfile));
2674 continue;
2675 }
2676 // Tree: must save all trees in the old file, reset them.
2677 if (obj->InheritsFrom(TTree::Class())) {
2678 TTree* t = (TTree*) obj;
2679 if (t != this) {
2680 t->AutoSave();
2681 t->Reset();
2683 }
2684 t->SetDirectory(newfile);
2685 TIter nextb(t->GetListOfBranches());
2686 while ((branch = (TBranch*)nextb())) {
2687 branch->SetFile(newfile);
2688 }
2689 if (t->GetBranchRef()) {
2690 t->GetBranchRef()->SetFile(newfile);
2691 }
2692 continue;
2693 }
2694 // Not a TH1 or a TTree, move object to new file.
2695 if (newfile) newfile->Append(obj);
2696 file->Remove(obj);
2697 }
2698 delete file;
2699 file = 0;
2700 delete[] fname;
2701 fname = 0;
2702 return newfile;
2703}
2704
2705////////////////////////////////////////////////////////////////////////////////
2706/// Check whether or not the address described by the last 3 parameters
2707/// matches the content of the branch. If a Data Model Evolution conversion
2708/// is involved, reset the fInfo of the branch.
2709/// The return values are:
2710//
2711/// - kMissingBranch (-5) : Missing branch
2712/// - kInternalError (-4) : Internal error (could not find the type corresponding to a data type number)
2713/// - kMissingCompiledCollectionProxy (-3) : Missing compiled collection proxy for a compiled collection
2714/// - kMismatch (-2) : Non-Class Pointer type given does not match the type expected by the branch
2715/// - kClassMismatch (-1) : Class Pointer type given does not match the type expected by the branch
2716/// - kMatch (0) : perfect match
2717/// - kMatchConversion (1) : match with (I/O) conversion
2718/// - kMatchConversionCollection (2) : match with (I/O) conversion of the content of a collection
2719/// - kMakeClass (3) : MakeClass mode so we can not check.
2720/// - kVoidPtr (4) : void* passed so no check was made.
2721/// - kNoCheck (5) : Underlying TBranch not yet available so no check was made.
2723Int_t TTree::CheckBranchAddressType(TBranch* branch, TClass* ptrClass, EDataType datatype, Bool_t isptr)
2724{
2725 if (GetMakeClass()) {
2726 // If we are in MakeClass mode so we do not really use classes.
2727 return kMakeClass;
2728 }
2729
2730 // Let's determine what we need!
2731 TClass* expectedClass = 0;
2732 EDataType expectedType = kOther_t;
2733 if (0 != branch->GetExpectedType(expectedClass,expectedType) ) {
2734 // Something went wrong, the warning message has already be issued.
2735 return kInternalError;
2736 }
2737 if (expectedClass && datatype == kOther_t && ptrClass == 0) {
2738 if (branch->InheritsFrom( TBranchElement::Class() )) {
2739 TBranchElement* bEl = (TBranchElement*)branch;
2740 bEl->SetTargetClass( expectedClass->GetName() );
2741 }
2742 if (expectedClass && expectedClass->GetCollectionProxy() && dynamic_cast<TEmulatedCollectionProxy*>(expectedClass->GetCollectionProxy())) {
2743 Error("SetBranchAddress", "Unable to determine the type given for the address for \"%s\". "
2744 "The class expected (%s) refers to an stl collection and do not have a compiled CollectionProxy. "
2745 "Please generate the dictionary for this class (%s)",
2746 branch->GetName(), expectedClass->GetName(), expectedClass->GetName());
2748 }
2749 if (!expectedClass->IsLoaded()) {
2750 // The originally expected class does not have a dictionary, it is then plausible that the pointer being passed is the right type
2751 // (we really don't know). So let's express that.
2752 Error("SetBranchAddress", "Unable to determine the type given for the address for \"%s\". "
2753 "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."
2754 "Please generate the dictionary for this class (%s)",
2755 branch->GetName(), expectedClass->GetName(), expectedClass->GetName());
2756 } else {
2757 Error("SetBranchAddress", "Unable to determine the type given for the address for \"%s\". "
2758 "This is probably due to a missing dictionary, the original data class for this branch is %s.", branch->GetName(), expectedClass->GetName());
2759 }
2760 return kClassMismatch;
2761 }
2762 if (expectedClass && ptrClass && (branch->GetMother() == branch)) {
2763 // Top Level branch
2764 if (!isptr) {
2765 Error("SetBranchAddress", "The address for \"%s\" should be the address of a pointer!", branch->GetName());
2766 }
2767 }
2768 if (expectedType == kFloat16_t) {
2769 expectedType = kFloat_t;
2770 }
2771 if (expectedType == kDouble32_t) {
2772 expectedType = kDouble_t;
2773 }
2774 if (datatype == kFloat16_t) {
2775 datatype = kFloat_t;
2776 }
2777 if (datatype == kDouble32_t) {
2778 datatype = kDouble_t;
2779 }
2780
2781 /////////////////////////////////////////////////////////////////////////////
2782 // Deal with the class renaming
2783 /////////////////////////////////////////////////////////////////////////////
2784
2785 if( expectedClass && ptrClass &&
2786 expectedClass != ptrClass &&
2787 branch->InheritsFrom( TBranchElement::Class() ) &&
2788 ptrClass->GetSchemaRules() &&
2789 ptrClass->GetSchemaRules()->HasRuleWithSourceClass( expectedClass->GetName() ) ) {
2790 TBranchElement* bEl = (TBranchElement*)branch;
2791
2792 if ( ptrClass->GetCollectionProxy() && expectedClass->GetCollectionProxy() ) {
2793 if (gDebug > 7)
2794 Info("SetBranchAddress", "Matching STL collection (at least according to the SchemaRuleSet when "
2795 "reading a %s into a %s",expectedClass->GetName(),ptrClass->GetName());
2796
2797 bEl->SetTargetClass( ptrClass->GetName() );
2798 return kMatchConversion;
2799
2800 } else if ( !ptrClass->GetConversionStreamerInfo( expectedClass, bEl->GetClassVersion() ) &&
2801 !ptrClass->FindConversionStreamerInfo( expectedClass, bEl->GetCheckSum() ) ) {
2802 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());
2803
2804 bEl->SetTargetClass( expectedClass->GetName() );
2805 return kClassMismatch;
2806 }
2807 else {
2808
2809 bEl->SetTargetClass( ptrClass->GetName() );
2810 return kMatchConversion;
2811 }
2812
2813 } else if (expectedClass && ptrClass && !expectedClass->InheritsFrom(ptrClass)) {
2814
2815 if (expectedClass->GetCollectionProxy() && ptrClass->GetCollectionProxy() &&
2816 branch->InheritsFrom( TBranchElement::Class() ) &&
2817 expectedClass->GetCollectionProxy()->GetValueClass() &&
2818 ptrClass->GetCollectionProxy()->GetValueClass() )
2819 {
2820 // In case of collection, we know how to convert them, if we know how to convert their content.
2821 // NOTE: we need to extend this to std::pair ...
2822
2823 TClass *onfileValueClass = expectedClass->GetCollectionProxy()->GetValueClass();
2824 TClass *inmemValueClass = ptrClass->GetCollectionProxy()->GetValueClass();
2825
2826 if (inmemValueClass->GetSchemaRules() &&
2827 inmemValueClass->GetSchemaRules()->HasRuleWithSourceClass(onfileValueClass->GetName() ) )
2828 {
2829 TBranchElement* bEl = (TBranchElement*)branch;
2830 bEl->SetTargetClass( ptrClass->GetName() );
2832 }
2833 }
2834
2835 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());
2836 if (branch->InheritsFrom( TBranchElement::Class() )) {
2837 TBranchElement* bEl = (TBranchElement*)branch;
2838 bEl->SetTargetClass( expectedClass->GetName() );
2839 }
2840 return kClassMismatch;
2841
2842 } else if ((expectedType != kOther_t) && (datatype != kOther_t) && (expectedType != kNoType_t) && (datatype != kNoType_t) && (expectedType != datatype)) {
2843 if (datatype != kChar_t) {
2844 // For backward compatibility we assume that (char*) was just a cast and/or a generic address
2845 Error("SetBranchAddress", "The pointer type given \"%s\" (%d) does not correspond to the type needed \"%s\" (%d) by the branch: %s",
2846 TDataType::GetTypeName(datatype), datatype, TDataType::GetTypeName(expectedType), expectedType, branch->GetName());
2847 return kMismatch;
2848 }
2849 } else if ((expectedClass && (datatype != kOther_t && datatype != kNoType_t && datatype != kInt_t)) ||
2850 (ptrClass && (expectedType != kOther_t && expectedType != kNoType_t && datatype != kInt_t)) ) {
2851 // Sometime a null pointer can look an int, avoid complaining in that case.
2852 if (expectedClass) {
2853 Error("SetBranchAddress", "The pointer type given \"%s\" (%d) does not correspond to the type needed \"%s\" by the branch: %s",
2854 TDataType::GetTypeName(datatype), datatype, expectedClass->GetName(), branch->GetName());
2855 if (branch->InheritsFrom( TBranchElement::Class() )) {
2856 TBranchElement* bEl = (TBranchElement*)branch;
2857 bEl->SetTargetClass( expectedClass->GetName() );
2858 }
2859 } else {
2860 // 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
2861 // a struct).
2862 bool found = false;
2863 if (ptrClass->IsLoaded()) {
2864 TIter next(ptrClass->GetListOfRealData());
2865 TRealData *rdm;
2866 while ((rdm = (TRealData*)next())) {
2867 if (rdm->GetThisOffset() == 0) {
2868 TDataType *dmtype = rdm->GetDataMember()->GetDataType();
2869 if (dmtype) {
2870 EDataType etype = (EDataType)dmtype->GetType();
2871 if (etype == expectedType) {
2872 found = true;
2873 }
2874 }
2875 break;
2876 }
2877 }
2878 } else {
2879 TIter next(ptrClass->GetListOfDataMembers());
2880 TDataMember *dm;
2881 while ((dm = (TDataMember*)next())) {
2882 if (dm->GetOffset() == 0) {
2883 TDataType *dmtype = dm->GetDataType();
2884 if (dmtype) {
2885 EDataType etype = (EDataType)dmtype->GetType();
2886 if (etype == expectedType) {
2887 found = true;
2888 }
2889 }
2890 break;
2891 }
2892 }
2893 }
2894 if (found) {
2895 // let's check the size.
2896 TLeaf *last = (TLeaf*)branch->GetListOfLeaves()->Last();
2897 long len = last->GetOffset() + last->GetLenType() * last->GetLen();
2898 if (len <= ptrClass->Size()) {
2899 return kMatch;
2900 }
2901 }
2902 Error("SetBranchAddress", "The pointer type given \"%s\" does not correspond to the type needed \"%s\" (%d) by the branch: %s",
2903 ptrClass->GetName(), TDataType::GetTypeName(expectedType), expectedType, branch->GetName());
2904 }
2905 return kMismatch;
2906 }
2907 if (expectedClass && expectedClass->GetCollectionProxy() && dynamic_cast<TEmulatedCollectionProxy*>(expectedClass->GetCollectionProxy())) {
2908 Error("SetBranchAddress", writeStlWithoutProxyMsg,
2909 expectedClass->GetName(), branch->GetName(), expectedClass->GetName());
2910 if (branch->InheritsFrom( TBranchElement::Class() )) {
2911 TBranchElement* bEl = (TBranchElement*)branch;
2912 bEl->SetTargetClass( expectedClass->GetName() );
2913 }
2915 }
2916 if (expectedClass && branch->InheritsFrom( TBranchElement::Class() )) {
2917 TBranchElement* bEl = (TBranchElement*)branch;
2918 bEl->SetTargetClass( expectedClass->GetName() );
2919 }
2920 return kMatch;
2921}
2922
2923////////////////////////////////////////////////////////////////////////////////
2924/// Create a clone of this tree and copy nentries.
2925///
2926/// By default copy all entries.
2927/// The compression level of the cloned tree is set to the destination
2928/// file's compression level.
2929///
2930/// NOTE: Only active branches are copied.
2931/// NOTE: If the TTree is a TChain, the structure of the first TTree
2932/// is used for the copy.
2933///
2934/// IMPORTANT: The cloned tree stays connected with this tree until
2935/// this tree is deleted. In particular, any changes in
2936/// branch addresses in this tree are forwarded to the
2937/// clone trees, unless a branch in a clone tree has had
2938/// its address changed, in which case that change stays in
2939/// effect. When this tree is deleted, all the addresses of
2940/// the cloned tree are reset to their default values.
2941///
2942/// If 'option' contains the word 'fast' and nentries is -1, the
2943/// cloning will be done without unzipping or unstreaming the baskets
2944/// (i.e., a direct copy of the raw bytes on disk).
2945///
2946/// When 'fast' is specified, 'option' can also contain a sorting
2947/// order for the baskets in the output file.
2948///
2949/// There are currently 3 supported sorting order:
2950///
2951/// - SortBasketsByOffset (the default)
2952/// - SortBasketsByBranch
2953/// - SortBasketsByEntry
2954///
2955/// When using SortBasketsByOffset the baskets are written in the
2956/// output file in the same order as in the original file (i.e. the
2957/// baskets are sorted by their offset in the original file; Usually
2958/// this also means that the baskets are sorted by the index/number of
2959/// the _last_ entry they contain)
2960///
2961/// When using SortBasketsByBranch all the baskets of each individual
2962/// branches are stored contiguously. This tends to optimize reading
2963/// speed when reading a small number (1->5) of branches, since all
2964/// their baskets will be clustered together instead of being spread
2965/// across the file. However it might decrease the performance when
2966/// reading more branches (or the full entry).
2967///
2968/// When using SortBasketsByEntry the baskets with the lowest starting
2969/// entry are written first. (i.e. the baskets are sorted by the
2970/// index/number of the first entry they contain). This means that on
2971/// the file the baskets will be in the order in which they will be
2972/// needed when reading the whole tree sequentially.
2973///
2974/// For examples of CloneTree, see tutorials:
2975///
2976/// - copytree.C:
2977/// A macro to copy a subset of a TTree to a new TTree.
2978/// The input file has been generated by the program in
2979/// $ROOTSYS/test/Event with: Event 1000 1 1 1
2980///
2981/// - copytree2.C:
2982/// A macro to copy a subset of a TTree to a new TTree.
2983/// One branch of the new Tree is written to a separate file.
2984/// The input file has been generated by the program in
2985/// $ROOTSYS/test/Event with: Event 1000 1 1 1
2987TTree* TTree::CloneTree(Long64_t nentries /* = -1 */, Option_t* option /* = "" */)
2988{
2989 // Options
2990 Bool_t fastClone = kFALSE;
2991
2992 TString opt = option;
2993 opt.ToLower();
2994 if (opt.Contains("fast")) {
2995 fastClone = kTRUE;
2996 }
2997
2998 // If we are a chain, switch to the first tree.
2999 if ((fEntries > 0) && (LoadTree(0) < 0)) {
3000 // FIXME: We need an error message here.
3001 return 0;
3002 }
3003
3004 // Note: For a tree we get the this pointer, for
3005 // a chain we get the chain's current tree.
3006 TTree* thistree = GetTree();
3007
3008 // We will use this to override the IO features on the cloned branches.
3009 ROOT::TIOFeatures features = this->GetIOFeatures();
3010 ;
3011
3012 // Note: For a chain, the returned clone will be
3013 // a clone of the chain's first tree.
3014 TTree* newtree = (TTree*) thistree->Clone();
3015 if (!newtree) {
3016 return 0;
3017 }
3018
3019 // The clone should not delete any objects allocated by SetAddress().
3020 TObjArray* branches = newtree->GetListOfBranches();
3021 Int_t nb = branches->GetEntriesFast();
3022 for (Int_t i = 0; i < nb; ++i) {
3023 TBranch* br = (TBranch*) branches->UncheckedAt(i);
3025 ((TBranchElement*) br)->ResetDeleteObject();
3026 }
3027 }
3028
3029 // Add the new tree to the list of clones so that
3030 // we can later inform it of changes to branch addresses.
3031 thistree->AddClone(newtree);
3032 if (thistree != this) {
3033 // In case this object is a TChain, add the clone
3034 // also to the TChain's list of clones.
3035 AddClone(newtree);
3036 }
3037
3038 newtree->Reset();
3039
3040 TDirectory* ndir = newtree->GetDirectory();
3041 TFile* nfile = 0;
3042 if (ndir) {
3043 nfile = ndir->GetFile();
3044 }
3045 Int_t newcomp = -1;
3046 if (nfile) {
3047 newcomp = nfile->GetCompressionSettings();
3048 }
3049
3050 //
3051 // Delete non-active branches from the clone.
3052 //
3053 // Note: If we are a chain, this does nothing
3054 // since chains have no leaves.
3055 TObjArray* leaves = newtree->GetListOfLeaves();
3056 Int_t nleaves = leaves->GetEntriesFast();
3057 for (Int_t lndx = 0; lndx < nleaves; ++lndx) {
3058 TLeaf* leaf = (TLeaf*) leaves->UncheckedAt(lndx);
3059 if (!leaf) {
3060 continue;
3061 }
3062 TBranch* branch = leaf->GetBranch();
3063 if (branch && (newcomp > -1)) {
3064 branch->SetCompressionSettings(newcomp);
3065 }
3066 if (branch) branch->SetIOFeatures(features);
3067 if (!branch || !branch->TestBit(kDoNotProcess)) {
3068 continue;
3069 }
3070 // size might change at each iteration of the loop over the leaves.
3071 nb = branches->GetEntriesFast();
3072 for (Long64_t i = 0; i < nb; ++i) {
3073 TBranch* br = (TBranch*) branches->UncheckedAt(i);
3074 if (br == branch) {
3075 branches->RemoveAt(i);
3076 delete br;
3077 br = 0;
3078 branches->Compress();
3079 break;
3080 }
3081 TObjArray* lb = br->GetListOfBranches();
3082 Int_t nb1 = lb->GetEntriesFast();
3083 for (Int_t j = 0; j < nb1; ++j) {
3084 TBranch* b1 = (TBranch*) lb->UncheckedAt(j);
3085 if (!b1) {
3086 continue;
3087 }
3088 if (b1 == branch) {
3089 lb->RemoveAt(j);
3090 delete b1;
3091 b1 = 0;
3092 lb->Compress();
3093 break;
3094 }
3095 TObjArray* lb1 = b1->GetListOfBranches();
3096 Int_t nb2 = lb1->GetEntriesFast();
3097 for (Int_t k = 0; k < nb2; ++k) {
3098 TBranch* b2 = (TBranch*) lb1->UncheckedAt(k);
3099 if (!b2) {
3100 continue;
3101 }
3102 if (b2 == branch) {
3103 lb1->RemoveAt(k);
3104 delete b2;
3105 b2 = 0;
3106 lb1->Compress();
3107 break;
3108 }
3109 }
3110 }
3111 }
3112 }
3113 leaves->Compress();
3114
3115 // Copy MakeClass status.
3116 newtree->SetMakeClass(fMakeClass);
3117
3118 // Copy branch addresses.
3119 CopyAddresses(newtree);
3120
3121 //
3122 // Copy entries if requested.
3123 //
3124
3125 if (nentries != 0) {
3126 if (fastClone && (nentries < 0)) {
3127 if ( newtree->CopyEntries( this, -1, option ) < 0 ) {
3128 // There was a problem!
3129 Error("CloneTTree", "TTree has not been cloned\n");
3130 delete newtree;
3131 newtree = 0;
3132 return 0;
3133 }
3134 } else {
3135 newtree->CopyEntries( this, nentries, option );
3136 }
3137 }
3138
3139 return newtree;
3140}
3141
3142////////////////////////////////////////////////////////////////////////////////
3143/// Set branch addresses of passed tree equal to ours.
3144/// If undo is true, reset the branch address instead of copying them.
3145/// This insures 'separation' of a cloned tree from its original
3148{
3149 // Copy branch addresses starting from branches.
3151 Int_t nbranches = branches->GetEntriesFast();
3152 for (Int_t i = 0; i < nbranches; ++i) {
3153 TBranch* branch = (TBranch*) branches->UncheckedAt(i);
3154 if (branch->TestBit(kDoNotProcess)) {
3155 continue;
3156 }
3157 if (undo) {
3158 TBranch* br = tree->GetBranch(branch->GetName());
3159 tree->ResetBranchAddress(br);
3160 } else {
3161 char* addr = branch->GetAddress();
3162 if (!addr) {
3163 if (branch->IsA() == TBranch::Class()) {
3164 // If the branch was created using a leaflist, the branch itself may not have
3165 // an address but the leaf might already.
3166 TLeaf *firstleaf = (TLeaf*)branch->GetListOfLeaves()->At(0);
3167 if (!firstleaf || firstleaf->GetValuePointer()) {
3168 // Either there is no leaf (and thus no point in copying the address)
3169 // or the leaf has an address but we can not copy it via the branche
3170 // this will be copied via the next loop (over the leaf).
3171 continue;
3172 }
3173 }
3174 // Note: This may cause an object to be allocated.
3175 branch->SetAddress(0);
3176 addr = branch->GetAddress();
3177 }
3178 // FIXME: The GetBranch() function is braindead and may
3179 // not find the branch!
3180 TBranch* br = tree->GetBranch(branch->GetName());
3181 if (br) {
3182 br->SetAddress(addr);
3183 // The copy does not own any object allocated by SetAddress().
3185 ((TBranchElement*) br)->ResetDeleteObject();
3186 }
3187 } else {
3188 Warning("CopyAddresses", "Could not find branch named '%s' in tree named '%s'", branch->GetName(), tree->GetName());
3189 }
3190 }
3191 }
3192
3193 // Copy branch addresses starting from leaves.
3194 TObjArray* tleaves = tree->GetListOfLeaves();
3195 Int_t ntleaves = tleaves->GetEntriesFast();
3196 std::set<TLeaf*> updatedLeafCount;
3197 for (Int_t i = 0; i < ntleaves; ++i) {
3198 TLeaf* tleaf = (TLeaf*) tleaves->UncheckedAt(i);
3199 TBranch* tbranch = tleaf->GetBranch();
3200 TBranch* branch = GetBranch(tbranch->GetName());
3201 if (!branch) {
3202 continue;
3203 }
3204 TLeaf* leaf = branch->GetLeaf(tleaf->GetName());
3205 if (!leaf) {
3206 continue;
3207 }
3208 if (branch->TestBit(kDoNotProcess)) {
3209 continue;
3210 }
3211 if (undo) {
3212 // Now we know whether the address has been transfered
3213 tree->ResetBranchAddress(tbranch);
3214 } else {
3215 TBranchElement *mother = dynamic_cast<TBranchElement*>(leaf->GetBranch()->GetMother());
3216 bool needAddressReset = false;
3217 if (leaf->GetLeafCount() && (leaf->TestBit(TLeaf::kNewValue) || !leaf->GetValuePointer() || (mother && mother->IsObjectOwner())) && tleaf->GetLeafCount())
3218 {
3219 // If it is an array and it was allocated by the leaf itself,
3220 // let's make sure it is large enough for the incoming data.
3221 if (leaf->GetLeafCount()->GetMaximum() < tleaf->GetLeafCount()->GetMaximum()) {
3222 leaf->GetLeafCount()->IncludeRange( tleaf->GetLeafCount() );
3223 updatedLeafCount.insert(leaf->GetLeafCount());
3224 needAddressReset = true;
3225 } else {
3226 needAddressReset = (updatedLeafCount.find(leaf->GetLeafCount()) != updatedLeafCount.end());
3227 }
3228 }
3229 if (needAddressReset && leaf->GetValuePointer()) {
3230 if (leaf->IsA() == TLeafElement::Class() && mother)
3231 mother->ResetAddress();
3232 else
3233 leaf->SetAddress(nullptr);
3234 }
3235 if (!branch->GetAddress() && !leaf->GetValuePointer()) {
3236 // We should attempts to set the address of the branch.
3237 // something like:
3238 //(TBranchElement*)branch->GetMother()->SetAddress(0)
3239 //plus a few more subtilities (see TBranchElement::GetEntry).
3240 //but for now we go the simplest route:
3241 //
3242 // Note: This may result in the allocation of an object.
3243 branch->SetupAddresses();
3244 }
3245 if (branch->GetAddress()) {
3246 tree->SetBranchAddress(branch->GetName(), (void*) branch->GetAddress());
3247 TBranch* br = tree->GetBranch(branch->GetName());
3248 if (br) {
3249 // The copy does not own any object allocated by SetAddress().
3250 // FIXME: We do too much here, br may not be a top-level branch.
3252 ((TBranchElement*) br)->ResetDeleteObject();
3253 }
3254 } else {
3255 Warning("CopyAddresses", "Could not find branch named '%s' in tree named '%s'", branch->GetName(), tree->GetName());
3256 }
3257 } else {
3258 tleaf->SetAddress(leaf->GetValuePointer());
3259 }
3260 }
3261 }
3262
3263 if (undo &&
3264 ( tree->IsA()->InheritsFrom("TNtuple") || tree->IsA()->InheritsFrom("TNtupleD") )
3265 ) {
3266 tree->ResetBranchAddresses();
3267 }
3268}
3269
3270namespace {
3271
3272 enum EOnIndexError { kDrop, kKeep, kBuild };
3273
3274 static Bool_t R__HandleIndex(EOnIndexError onIndexError, TTree *newtree, TTree *oldtree)
3275 {
3276 // Return true if we should continue to handle indices, false otherwise.
3277
3278 Bool_t withIndex = kTRUE;
3279
3280 if ( newtree->GetTreeIndex() ) {
3281 if ( oldtree->GetTree()->GetTreeIndex() == 0 ) {
3282 switch (onIndexError) {
3283 case kDrop:
3284 delete newtree->GetTreeIndex();
3285 newtree->SetTreeIndex(0);
3286 withIndex = kFALSE;
3287 break;
3288 case kKeep:
3289 // Nothing to do really.
3290 break;
3291 case kBuild:
3292 // Build the index then copy it
3293 if (oldtree->GetTree()->BuildIndex(newtree->GetTreeIndex()->GetMajorName(), newtree->GetTreeIndex()->GetMinorName())) {
3294 newtree->GetTreeIndex()->Append(oldtree->GetTree()->GetTreeIndex(), kTRUE);
3295 // Clean up
3296 delete oldtree->GetTree()->GetTreeIndex();
3297 oldtree->GetTree()->SetTreeIndex(0);
3298 }
3299 break;
3300 }
3301 } else {
3302 newtree->GetTreeIndex()->Append(oldtree->GetTree()->GetTreeIndex(), kTRUE);
3303 }
3304 } else if ( oldtree->GetTree()->GetTreeIndex() != 0 ) {
3305 // We discover the first index in the middle of the chain.
3306 switch (onIndexError) {
3307 case kDrop:
3308 // Nothing to do really.
3309 break;
3310 case kKeep: {
3311 TVirtualIndex *index = (TVirtualIndex*) oldtree->GetTree()->GetTreeIndex()->Clone();
3312 index->SetTree(newtree);
3313 newtree->SetTreeIndex(index);
3314 break;
3315 }
3316 case kBuild:
3317 if (newtree->GetEntries() == 0) {
3318 // Start an index.
3319 TVirtualIndex *index = (TVirtualIndex*) oldtree->GetTree()->GetTreeIndex()->Clone();
3320 index->SetTree(newtree);
3321 newtree->SetTreeIndex(index);
3322 } else {
3323 // Build the index so far.
3324 if (newtree->BuildIndex(oldtree->GetTree()->GetTreeIndex()->GetMajorName(), oldtree->GetTree()->GetTreeIndex()->GetMinorName())) {
3325 newtree->GetTreeIndex()->Append(oldtree->GetTree()->GetTreeIndex(), kTRUE);
3326 }
3327 }
3328 break;
3329 }
3330 } else if ( onIndexError == kDrop ) {
3331 // There is no index on this or on tree->GetTree(), we know we have to ignore any further
3332 // index
3333 withIndex = kFALSE;
3334 }
3335 return withIndex;
3336 }
3337}
3338
3339////////////////////////////////////////////////////////////////////////////////
3340/// Copy nentries from given tree to this tree.
3341/// This routines assumes that the branches that intended to be copied are
3342/// already connected. The typical case is that this tree was created using
3343/// tree->CloneTree(0).
3344///
3345/// By default copy all entries.
3346///
3347/// Returns number of bytes copied to this tree.
3348///
3349/// If 'option' contains the word 'fast' and nentries is -1, the cloning will be
3350/// done without unzipping or unstreaming the baskets (i.e., a direct copy of the
3351/// raw bytes on disk).
3352///
3353/// When 'fast' is specified, 'option' can also contains a sorting order for the
3354/// baskets in the output file.
3355///
3356/// There are currently 3 supported sorting order:
3357///
3358/// - SortBasketsByOffset (the default)
3359/// - SortBasketsByBranch
3360/// - SortBasketsByEntry
3361///
3362/// See TTree::CloneTree for a detailed explanation of the semantics of these 3 options.
3363///
3364/// If the tree or any of the underlying tree of the chain has an index, that index and any
3365/// index in the subsequent underlying TTree objects will be merged.
3366///
3367/// There are currently three 'options' to control this merging:
3368/// - NoIndex : all the TTreeIndex object are dropped.
3369/// - DropIndexOnError : if any of the underlying TTree object do no have a TTreeIndex,
3370/// they are all dropped.
3371/// - AsIsIndexOnError [default]: In case of missing TTreeIndex, the resulting TTree index has gaps.
3372/// - BuildIndexOnError : If any of the underlying TTree objects do not have a TTreeIndex,
3373/// all TTreeIndex are 'ignored' and the missing piece are rebuilt.
3375Long64_t TTree::CopyEntries(TTree* tree, Long64_t nentries /* = -1 */, Option_t* option /* = "" */)
3376{
3377 if (!tree) {
3378 return 0;
3379 }
3380 // Options
3381 TString opt = option;
3382 opt.ToLower();
3383 Bool_t fastClone = opt.Contains("fast");
3384 Bool_t withIndex = !opt.Contains("noindex");
3385 EOnIndexError onIndexError;
3386 if (opt.Contains("asisindex")) {
3387 onIndexError = kKeep;
3388 } else if (opt.Contains("buildindex")) {
3389 onIndexError = kBuild;
3390 } else if (opt.Contains("dropindex")) {
3391 onIndexError = kDrop;
3392 } else {
3393 onIndexError = kBuild;
3394 }
3395 Ssiz_t cacheSizeLoc = opt.Index("cachesize=");
3396 Int_t cacheSize = -1;
3397 if (cacheSizeLoc != TString::kNPOS) {
3398 // If the parse faile, cacheSize stays at -1.
3399 Ssiz_t cacheSizeEnd = opt.Index(" ",cacheSizeLoc+10) - (cacheSizeLoc+10);
3400 TSubString cacheSizeStr( opt(cacheSizeLoc+10,cacheSizeEnd) );
3401 auto parseResult = ROOT::FromHumanReadableSize(cacheSizeStr,cacheSize);
3402 if (parseResult == ROOT::EFromHumanReadableSize::kParseFail) {
3403 Warning("CopyEntries","The cachesize option can not be parsed: %s. The default size will be used.",cacheSizeStr.String().Data());
3404 } else if (parseResult == ROOT::EFromHumanReadableSize::kOverflow) {
3405 double m;
3406 const char *munit = nullptr;
3407 ROOT::ToHumanReadableSize(std::numeric_limits<decltype(cacheSize)>::max(),false,&m,&munit);
3408
3409 Warning("CopyEntries","The cachesize option is too large: %s (%g%s max). The default size will be used.",cacheSizeStr.String().Data(),m,munit);
3410 }
3411 }
3412 if (gDebug > 0 && cacheSize != -1) Info("CopyEntries","Using Cache size: %d\n",cacheSize);
3413
3414 Long64_t nbytes = 0;
3415 Long64_t treeEntries = tree->GetEntriesFast();
3416 if (nentries < 0) {
3417 nentries = treeEntries;
3418 } else if (nentries > treeEntries) {
3419 nentries = treeEntries;
3420 }
3421
3422 if (fastClone && (nentries < 0 || nentries == tree->GetEntriesFast())) {
3423 // Quickly copy the basket without decompression and streaming.
3424 Long64_t totbytes = GetTotBytes();
3425 for (Long64_t i = 0; i < nentries; i += tree->GetTree()->GetEntries()) {
3426 if (tree->LoadTree(i) < 0) {
3427 break;
3428 }
3429 if ( withIndex ) {
3430 withIndex = R__HandleIndex( onIndexError, this, tree );
3431 }
3432 if (this->GetDirectory()) {
3433 TFile* file2 = this->GetDirectory()->GetFile();
3434 if (file2 && (file2->GetEND() > TTree::GetMaxTreeSize())) {
3435 if (this->GetDirectory() == (TDirectory*) file2) {
3436 this->ChangeFile(file2);
3437 }
3438 }
3439 }
3440 TTreeCloner cloner(tree->GetTree(), this, option, TTreeCloner::kNoWarnings);
3441 if (cloner.IsValid()) {
3442 this->SetEntries(this->GetEntries() + tree->GetTree()->GetEntries());
3443 if (cacheSize != -1) cloner.SetCacheSize(cacheSize);
3444 cloner.Exec();
3445 } else {
3446 if (i == 0) {
3447 Warning("CopyEntries","%s",cloner.GetWarning());
3448 // If the first cloning does not work, something is really wrong
3449 // (since apriori the source and target are exactly the same structure!)
3450 return -1;
3451 } else {
3452 if (cloner.NeedConversion()) {
3453 TTree *localtree = tree->GetTree();
3454 Long64_t tentries = localtree->GetEntries();
3455 for (Long64_t ii = 0; ii < tentries; ii++) {
3456 if (localtree->GetEntry(ii) <= 0) {
3457 break;
3458 }
3459 this->Fill();
3460 }
3461 if (this->GetTreeIndex()) {
3462 this->GetTreeIndex()->Append(tree->GetTree()->GetTreeIndex(), kTRUE);
3463 }
3464 } else {
3465 Warning("CopyEntries","%s",cloner.GetWarning());
3466 if (tree->GetDirectory() && tree->GetDirectory()->GetFile()) {
3467 Warning("CopyEntries", "Skipped file %s\n", tree->GetDirectory()->GetFile()->GetName());
3468 } else {
3469 Warning("CopyEntries", "Skipped file number %d\n", tree->GetTreeNumber());
3470 }
3471 }
3472 }
3473 }
3474
3475 }
3476 if (this->GetTreeIndex()) {
3477 this->GetTreeIndex()->Append(0,kFALSE); // Force the sorting
3478 }
3479 nbytes = GetTotBytes() - totbytes;
3480 } else {
3481 if (nentries < 0) {
3482 nentries = treeEntries;
3483 } else if (nentries > treeEntries) {
3484 nentries = treeEntries;
3485 }
3486 Int_t treenumber = -1;
3487 for (Long64_t i = 0; i < nentries; i++) {
3488 if (tree->LoadTree(i) < 0) {
3489 break;
3490 }
3491 if (treenumber != tree->GetTreeNumber()) {
3492 if ( withIndex ) {
3493 withIndex = R__HandleIndex( onIndexError, this, tree );
3494 }
3495 treenumber = tree->GetTreeNumber();
3496 }
3497 if (tree->GetEntry(i) <= 0) {
3498 break;
3499 }
3500 nbytes += this->Fill();
3501 }
3502 if (this->GetTreeIndex()) {
3503 this->GetTreeIndex()->Append(0,kFALSE); // Force the sorting
3504 }
3505 }
3506 return nbytes;
3507}
3508
3509////////////////////////////////////////////////////////////////////////////////
3510/// Copy a tree with selection.
3511///
3512/// ### Important:
3513///
3514/// The returned copied tree stays connected with the original tree
3515/// until the original tree is deleted. In particular, any changes
3516/// to the branch addresses in the original tree are also made to
3517/// the copied tree. Any changes made to the branch addresses of the
3518/// copied tree are overridden anytime the original tree changes its
3519/// branch addresses. When the original tree is deleted, all the
3520/// branch addresses of the copied tree are set to zero.
3521///
3522/// For examples of CopyTree, see the tutorials:
3523///
3524/// - copytree.C:
3525/// Example macro to copy a subset of a tree to a new tree.
3526/// The input file was generated by running the program in
3527/// $ROOTSYS/test/Event in this way:
3528/// ~~~ {.cpp}
3529/// ./Event 1000 1 1 1
3530/// ~~~
3531/// - copytree2.C
3532/// Example macro to copy a subset of a tree to a new tree.
3533/// One branch of the new tree is written to a separate file.
3534/// The input file was generated by running the program in
3535/// $ROOTSYS/test/Event in this way:
3536/// ~~~ {.cpp}
3537/// ./Event 1000 1 1 1
3538/// ~~~
3539/// - copytree3.C
3540/// Example macro to copy a subset of a tree to a new tree.
3541/// Only selected entries are copied to the new tree.
3542/// NOTE that only the active branches are copied.
3544TTree* TTree::CopyTree(const char* selection, Option_t* option /* = 0 */, Long64_t nentries /* = TTree::kMaxEntries */, Long64_t firstentry /* = 0 */)
3545{
3546 GetPlayer();
3547 if (fPlayer) {
3548 return fPlayer->CopyTree(selection, option, nentries, firstentry);
3549 }
3550 return 0;
3551}
3552
3553////////////////////////////////////////////////////////////////////////////////
3554/// Create a basket for this tree and given branch.
3557{
3558 if (!branch) {
3559 return 0;
3560 }
3561 return new TBasket(branch->GetName(), GetName(), branch);
3562}
3563
3564////////////////////////////////////////////////////////////////////////////////
3565/// Delete this tree from memory or/and disk.
3566///
3567/// - if option == "all" delete Tree object from memory AND from disk
3568/// all baskets on disk are deleted. All keys with same name
3569/// are deleted.
3570/// - if option =="" only Tree object in memory is deleted.
3572void TTree::Delete(Option_t* option /* = "" */)
3573{
3575
3576 // delete all baskets and header from file
3577 if (file && !strcmp(option,"all")) {
3578 if (!file->IsWritable()) {
3579 Error("Delete","File : %s is not writable, cannot delete Tree:%s", file->GetName(),GetName());
3580 return;
3581 }
3582
3583 //find key and import Tree header in memory
3584 TKey *key = fDirectory->GetKey(GetName());
3585 if (!key) return;
3586
3587 TDirectory *dirsav = gDirectory;
3588 file->cd();
3589
3590 //get list of leaves and loop on all the branches baskets
3591 TIter next(GetListOfLeaves());
3592 TLeaf *leaf;
3593 char header[16];
3594 Int_t ntot = 0;
3595 Int_t nbask = 0;
3596 Int_t nbytes,objlen,keylen;
3597 while ((leaf = (TLeaf*)next())) {
3598 TBranch *branch = leaf->GetBranch();
3599 Int_t nbaskets = branch->GetMaxBaskets();
3600 for (Int_t i=0;i<nbaskets;i++) {
3601 Long64_t pos = branch->GetBasketSeek(i);
3602 if (!pos) continue;
3603 TFile *branchFile = branch->GetFile();
3604 if (!branchFile) continue;
3605 branchFile->GetRecordHeader(header,pos,16,nbytes,objlen,keylen);
3606 if (nbytes <= 0) continue;
3607 branchFile->MakeFree(pos,pos+nbytes-1);
3608 ntot += nbytes;
3609 nbask++;
3610 }
3611 }
3612
3613 // delete Tree header key and all keys with the same name
3614 // A Tree may have been saved many times. Previous cycles are invalid.
3615 while (key) {
3616 ntot += key->GetNbytes();
3617 key->Delete();
3618 delete key;
3619 key = fDirectory->GetKey(GetName());
3620 }
3621 if (dirsav) dirsav->cd();
3622 if (gDebug) Info("TTree::Delete", "Deleting Tree: %s: %d baskets deleted. Total space freed = %d bytes\n",GetName(),nbask,ntot);
3623 }
3624
3625 if (fDirectory) {
3626 fDirectory->Remove(this);
3627 //delete the file cache if it points to this Tree
3629 fDirectory = 0;
3631 }
3632
3633 // Delete object from CINT symbol table so it can not be used anymore.
3634 gCling->DeleteGlobal(this);
3635
3636 // Warning: We have intentional invalidated this object while inside a member function!
3637 delete this;
3638}
3639
3640 ///////////////////////////////////////////////////////////////////////////////
3641 /// Called by TKey and TObject::Clone to automatically add us to a directory
3642 /// when we are read from a file.
3645{
3646 if (fDirectory == dir) return;
3647 if (fDirectory) {
3648 fDirectory->Remove(this);
3649 // Delete or move the file cache if it points to this Tree
3651 MoveReadCache(file,dir);
3652 }
3653 fDirectory = dir;
3654 TBranch* b = 0;
3655 TIter next(GetListOfBranches());
3656 while((b = (TBranch*) next())) {
3657 b->UpdateFile();
3658 }
3659 if (fBranchRef) {
3661 }
3662 if (fDirectory) fDirectory->Append(this);
3663}
3664
3665////////////////////////////////////////////////////////////////////////////////
3666/// Draw expression varexp for specified entries.
3667///
3668/// \return -1 in case of error or number of selected events in case of success.
3669///
3670/// This function accepts TCut objects as arguments.
3671/// Useful to use the string operator +
3672///
3673/// Example:
3674///
3675/// ~~~ {.cpp}
3676/// ntuple.Draw("x",cut1+cut2+cut3);
3677/// ~~~
3678
3680Long64_t TTree::Draw(const char* varexp, const TCut& selection, Option_t* option, Long64_t nentries, Long64_t firstentry)
3681{
3682 return TTree::Draw(varexp, selection.GetTitle(), option, nentries, firstentry);
3683}
3684
3685////////////////////////////////////////////////////////////////////////////////
3686/// Draw expression varexp for specified entries.
3687///
3688/// \return -1 in case of error or number of selected events in case of success.
3689///
3690/// \param [in] varexp is an expression of the general form
3691/// - "e1" produces a 1-d histogram (TH1F) of expression "e1"
3692/// - "e1:e2" produces an unbinned 2-d scatter-plot (TGraph) of "e1"
3693/// on the y-axis versus "e2" on the x-axis
3694/// - "e1:e2:e3" produces an unbinned 3-d scatter-plot (TPolyMarker3D) of "e1"
3695/// vs "e2" vs "e3" on the x-, y-, z-axis, respectively.
3696/// - "e1:e2:e3:e4" produces an unbinned 3-d scatter-plot (TPolyMarker3D) of "e1"
3697/// vs "e2" vs "e3" and "e4" mapped on the current color palette.
3698/// (to create histograms in the 2, 3, and 4 dimensional case,
3699/// see section "Saving the result of Draw to an histogram")
3700///
3701/// Example:
3702/// - varexp = x simplest case: draw a 1-Dim distribution of column named x
3703/// - varexp = sqrt(x) : draw distribution of sqrt(x)
3704/// - varexp = x*y/z
3705/// - varexp = y:sqrt(x) 2-Dim distribution of y versus sqrt(x)
3706/// - varexp = px:py:pz:2.5*E produces a 3-d scatter-plot of px vs py ps pz
3707/// and the color number of each marker will be 2.5*E.
3708/// If the color number is negative it is set to 0.
3709/// If the color number is greater than the current number of colors
3710/// it is set to the highest color number.The default number of
3711/// colors is 50. see TStyle::SetPalette for setting a new color palette.
3712///
3713/// Note that the variables e1, e2 or e3 may contain a selection.
3714/// example, if e1= x*(y<0), the value histogrammed will be x if y<0
3715/// and will be 0 otherwise.
3716///
3717/// The expressions can use all the operations and build-in functions
3718/// supported by TFormula (See TFormula::Analyze), including free
3719/// standing function taking numerical arguments (TMath::Bessel).
3720/// In addition, you can call member functions taking numerical
3721/// arguments. For example:
3722/// ~~~ {.cpp}
3723/// TMath::BreitWigner(fPx,3,2)
3724/// event.GetHistogram().GetXaxis().GetXmax()
3725/// ~~~
3726/// Note: You can only pass expression that depend on the TTree's data
3727/// to static functions and you can only call non-static member function
3728/// with 'fixed' parameters.
3729///
3730/// \param [in] selection is an expression with a combination of the columns.
3731/// In a selection all the C++ operators are authorized.
3732/// The value corresponding to the selection expression is used as a weight
3733/// to fill the histogram.
3734/// If the expression includes only boolean operations, the result
3735/// is 0 or 1. If the result is 0, the histogram is not filled.
3736/// In general, the expression may be of the form:
3737/// ~~~ {.cpp}
3738/// value*(boolean expression)
3739/// ~~~
3740/// if boolean expression is true, the histogram is filled with
3741/// a `weight = value`.
3742/// Examples:
3743/// - selection1 = "x<y && sqrt(z)>3.2"
3744/// - selection2 = "(x+y)*(sqrt(z)>3.2)"
3745/// - selection1 returns a weight = 0 or 1
3746/// - selection2 returns a weight = x+y if sqrt(z)>3.2
3747/// returns a weight = 0 otherwise.
3748///
3749/// \param [in] option is the drawing option.
3750/// - When an histogram is produced it can be any histogram drawing option
3751/// listed in THistPainter.
3752/// - when no option is specified:
3753/// - the default histogram drawing option is used
3754/// if the expression is of the form "e1".
3755/// - if the expression is of the form "e1:e2"or "e1:e2:e3" a cloud of
3756/// unbinned 2D or 3D points is drawn respectively.
3757/// - if the expression has four fields "e1:e2:e3:e4" a 2D scatter is
3758/// produced with e1 vs e2 vs e3, and e4 is mapped on the current color
3759/// palette.
3760/// - If option COL is specified when varexp has three fields:
3761/// ~~~ {.cpp}
3762/// tree.Draw("e1:e2:e3","","col");
3763/// ~~~
3764/// a 2D scatter is produced with e1 vs e2, and e3 is mapped on the current
3765/// color palette. The colors for e3 are evaluated once in linear scale before
3766/// painting. Therefore changing the pad to log scale along Z as no effect
3767/// on the colors.
3768/// - if expression has more than four fields the option "PARA"or "CANDLE"
3769/// can be used.
3770/// - If option contains the string "goff", no graphics is generated.
3771///
3772/// \param [in] nentries is the number of entries to process (default is all)
3773///
3774/// \param [in] firstentry is the first entry to process (default is 0)
3775///
3776/// ### Drawing expressions using arrays and array elements
3777///
3778/// Let assumes, a leaf fMatrix, on the branch fEvent, which is a 3 by 3 array,
3779/// or a TClonesArray.
3780/// In a TTree::Draw expression you can now access fMatrix using the following
3781/// syntaxes:
3782///
3783/// | String passed | What is used for each entry of the tree
3784/// |-----------------|--------------------------------------------------------|
3785/// | `fMatrix` | the 9 elements of fMatrix |
3786/// | `fMatrix[][]` | the 9 elements of fMatrix |
3787/// | `fMatrix[2][2]` | only the elements fMatrix[2][2] |
3788/// | `fMatrix[1]` | the 3 elements fMatrix[1][0], fMatrix[1][1] and fMatrix[1][2] |
3789/// | `fMatrix[1][]` | the 3 elements fMatrix[1][0], fMatrix[1][1] and fMatrix[1][2] |
3790/// | `fMatrix[][0]` | the 3 elements fMatrix[0][0], fMatrix[1][0] and fMatrix[2][0] |
3791///
3792/// "fEvent.fMatrix...." same as "fMatrix..." (unless there is more than one leaf named fMatrix!).
3793///
3794/// In summary, if a specific index is not specified for a dimension, TTree::Draw
3795/// will loop through all the indices along this dimension. Leaving off the
3796/// last (right most) dimension of specifying then with the two characters '[]'
3797/// is equivalent. For variable size arrays (and TClonesArray) the range
3798/// of the first dimension is recalculated for each entry of the tree.
3799/// You can also specify the index as an expression of any other variables from the
3800/// tree.
3801///
3802/// TTree::Draw also now properly handling operations involving 2 or more arrays.
3803///
3804/// Let assume a second matrix fResults[5][2], here are a sample of some
3805/// of the possible combinations, the number of elements they produce and
3806/// the loop used:
3807///
3808/// | expression | element(s) | Loop |
3809/// |----------------------------------|------------|--------------------------|
3810/// | `fMatrix[2][1] - fResults[5][2]` | one | no loop |
3811/// | `fMatrix[2][] - fResults[5][2]` | three | on 2nd dim fMatrix |
3812/// | `fMatrix[2][] - fResults[5][]` | two | on both 2nd dimensions |
3813/// | `fMatrix[][2] - fResults[][1]` | three | on both 1st dimensions |
3814/// | `fMatrix[][2] - fResults[][]` | six | on both 1st and 2nd dimensions of fResults |
3815/// | `fMatrix[][2] - fResults[3][]` | two | on 1st dim of fMatrix and 2nd of fResults (at the same time) |
3816/// | `fMatrix[][] - fResults[][]` | six | on 1st dim then on 2nd dim |
3817/// | `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.|
3818///
3819///
3820/// In summary, TTree::Draw loops through all unspecified dimensions. To
3821/// figure out the range of each loop, we match each unspecified dimension
3822/// from left to right (ignoring ALL dimensions for which an index has been
3823/// specified), in the equivalent loop matched dimensions use the same index
3824/// and are restricted to the smallest range (of only the matched dimensions).
3825/// When involving variable arrays, the range can of course be different
3826/// for each entry of the tree.
3827///
3828/// So the loop equivalent to "fMatrix[][2] - fResults[3][]" is:
3829/// ~~~ {.cpp}
3830/// for (Int_t i0; i < min(3,2); i++) {
3831/// use the value of (fMatrix[i0][2] - fMatrix[3][i0])
3832/// }
3833/// ~~~
3834/// So the loop equivalent to "fMatrix[][2] - fResults[][]" is:
3835/// ~~~ {.cpp}
3836/// for (Int_t i0; i < min(3,5); i++) {
3837/// for (Int_t i1; i1 < 2; i1++) {
3838/// use the value of (fMatrix[i0][2] - fMatrix[i0][i1])
3839/// }
3840/// }
3841/// ~~~
3842/// So the loop equivalent to "fMatrix[][] - fResults[][]" is:
3843/// ~~~ {.cpp}
3844/// for (Int_t i0; i < min(3,5); i++) {
3845/// for (Int_t i1; i1 < min(3,2); i1++) {
3846/// use the value of (fMatrix[i0][i1] - fMatrix[i0][i1])
3847/// }
3848/// }
3849/// ~~~
3850/// So the loop equivalent to "fMatrix[][fResults[][]]" is:
3851/// ~~~ {.cpp}
3852/// for (Int_t i0; i0 < 3; i0++) {
3853/// for (Int_t j2; j2 < 5; j2++) {
3854/// for (Int_t j3; j3 < 2; j3++) {
3855/// i1 = fResults[j2][j3];
3856/// use the value of fMatrix[i0][i1]
3857/// }
3858/// }
3859/// ~~~
3860/// ### Retrieving the result of Draw
3861///
3862/// By default the temporary histogram created is called "htemp", but only in
3863/// the one dimensional Draw("e1") it contains the TTree's data points. For
3864/// a two dimensional Draw, the data is filled into a TGraph which is named
3865/// "Graph". They can be retrieved by calling
3866/// ~~~ {.cpp}
3867/// TH1F *htemp = (TH1F*)gPad->GetPrimitive("htemp"); // 1D
3868/// TGraph *graph = (TGraph*)gPad->GetPrimitive("Graph"); // 2D
3869/// ~~~
3870/// For a three and four dimensional Draw the TPolyMarker3D is unnamed, and
3871/// cannot be retrieved.
3872///
3873/// gPad always contains a TH1 derived object called "htemp" which allows to
3874/// access the axes:
3875/// ~~~ {.cpp}
3876/// TGraph *graph = (TGraph*)gPad->GetPrimitive("Graph"); // 2D
3877/// TH2F *htemp = (TH2F*)gPad->GetPrimitive("htemp"); // empty, but has axes
3878/// TAxis *xaxis = htemp->GetXaxis();
3879/// ~~~
3880/// ### Saving the result of Draw to an histogram
3881///
3882/// If varexp0 contains >>hnew (following the variable(s) name(s),
3883/// the new histogram created is called hnew and it is kept in the current
3884/// directory (and also the current pad). This works for all dimensions.
3885///
3886/// Example:
3887/// ~~~ {.cpp}
3888/// tree.Draw("sqrt(x)>>hsqrt","y>0")
3889/// ~~~
3890/// will draw `sqrt(x)` and save the histogram as "hsqrt" in the current
3891/// directory. To retrieve it do:
3892/// ~~~ {.cpp}
3893/// TH1F *hsqrt = (TH1F*)gDirectory->Get("hsqrt");
3894/// ~~~
3895/// The binning information is taken from the environment variables
3896/// ~~~ {.cpp}
3897/// Hist.Binning.?D.?
3898/// ~~~
3899/// In addition, the name of the histogram can be followed by up to 9
3900/// numbers between '(' and ')', where the numbers describe the
3901/// following:
3902///
3903/// - 1 - bins in x-direction
3904/// - 2 - lower limit in x-direction
3905/// - 3 - upper limit in x-direction
3906/// - 4-6 same for y-direction
3907/// - 7-9 same for z-direction
3908///
3909/// When a new binning is used the new value will become the default.
3910/// Values can be skipped.
3911///
3912/// Example:
3913/// ~~~ {.cpp}
3914/// tree.Draw("sqrt(x)>>hsqrt(500,10,20)")
3915/// // plot sqrt(x) between 10 and 20 using 500 bins
3916/// tree.Draw("sqrt(x):sin(y)>>hsqrt(100,10,60,50,.1,.5)")
3917/// // plot sqrt(x) against sin(y)
3918/// // 100 bins in x-direction; lower limit on x-axis is 10; upper limit is 60
3919/// // 50 bins in y-direction; lower limit on y-axis is .1; upper limit is .5
3920/// ~~~
3921/// By default, the specified histogram is reset.
3922/// To continue to append data to an existing histogram, use "+" in front
3923/// of the histogram name.
3924///
3925/// A '+' in front of the histogram name is ignored, when the name is followed by
3926/// binning information as described in the previous paragraph.
3927/// ~~~ {.cpp}
3928/// tree.Draw("sqrt(x)>>+hsqrt","y>0")
3929/// ~~~
3930/// will not reset `hsqrt`, but will continue filling. This works for 1-D, 2-D
3931/// and 3-D histograms.
3932///
3933/// ### Accessing collection objects
3934///
3935/// TTree::Draw default's handling of collections is to assume that any
3936/// request on a collection pertain to it content. For example, if fTracks
3937/// is a collection of Track objects, the following:
3938/// ~~~ {.cpp}
3939/// tree->Draw("event.fTracks.fPx");
3940/// ~~~
3941/// will plot the value of fPx for each Track objects inside the collection.
3942/// Also
3943/// ~~~ {.cpp}
3944/// tree->Draw("event.fTracks.size()");
3945/// ~~~
3946/// would plot the result of the member function Track::size() for each
3947/// Track object inside the collection.
3948/// To access information about the collection itself, TTree::Draw support
3949/// the '@' notation. If a variable which points to a collection is prefixed
3950/// or postfixed with '@', the next part of the expression will pertain to
3951/// the collection object. For example:
3952/// ~~~ {.cpp}
3953/// tree->Draw("event.@fTracks.size()");
3954/// ~~~
3955/// will plot the size of the collection referred to by `fTracks` (i.e the number
3956/// of Track objects).
3957///
3958/// ### Drawing 'objects'
3959///
3960/// When a class has a member function named AsDouble or AsString, requesting
3961/// to directly draw the object will imply a call to one of the 2 functions.
3962/// If both AsDouble and AsString are present, AsDouble will be used.
3963/// AsString can return either a char*, a std::string or a TString.s
3964/// For example, the following
3965/// ~~~ {.cpp}
3966/// tree->Draw("event.myTTimeStamp");
3967/// ~~~
3968/// will draw the same histogram as
3969/// ~~~ {.cpp}
3970/// tree->Draw("event.myTTimeStamp.AsDouble()");
3971/// ~~~
3972/// In addition, when the object is a type TString or std::string, TTree::Draw
3973/// will call respectively `TString::Data` and `std::string::c_str()`
3974///
3975/// If the object is a TBits, the histogram will contain the index of the bit
3976/// that are turned on.
3977///
3978/// ### Retrieving information about the tree itself.
3979///
3980/// You can refer to the tree (or chain) containing the data by using the
3981/// string 'This'.
3982/// You can then could any TTree methods. For example:
3983/// ~~~ {.cpp}
3984/// tree->Draw("This->GetReadEntry()");
3985/// ~~~
3986/// will display the local entry numbers be read.
3987/// ~~~ {.cpp}
3988/// tree->Draw("This->GetUserInfo()->At(0)->GetName()");
3989/// ~~~
3990/// will display the name of the first 'user info' object.
3991///
3992/// ### Special functions and variables
3993///
3994/// `Entry$`: A TTree::Draw formula can use the special variable `Entry$`
3995/// to access the entry number being read. For example to draw every
3996/// other entry use:
3997/// ~~~ {.cpp}
3998/// tree.Draw("myvar","Entry$%2==0");
3999/// ~~~
4000/// - `Entry$` : return the current entry number (`== TTree::GetReadEntry()`)
4001/// - `LocalEntry$` : return the current entry number in the current tree of a
4002/// chain (`== GetTree()->GetReadEntry()`)
4003/// - `Entries$` : return the total number of entries (== TTree::GetEntries())
4004/// - `LocalEntries$` : return the total number of entries in the current tree
4005/// of a chain (== GetTree()->TTree::GetEntries())
4006/// - `Length$` : return the total number of element of this formula for this
4007/// entry (`==TTreeFormula::GetNdata()`)
4008/// - `Iteration$` : return the current iteration over this formula for this
4009/// entry (i.e. varies from 0 to `Length$`).
4010/// - `Length$(formula )` : return the total number of element of the formula
4011/// given as a parameter.
4012/// - `Sum$(formula )` : return the sum of the value of the elements of the
4013/// formula given as a parameter. For example the mean for all the elements in
4014/// one entry can be calculated with: `Sum$(formula )/Length$(formula )`
4015/// - `Min$(formula )` : return the minimun (within one TTree entry) of the value of the
4016/// elements of the formula given as a parameter.
4017/// - `Max$(formula )` : return the maximum (within one TTree entry) of the value of the
4018/// elements of the formula given as a parameter.
4019/// - `MinIf$(formula,condition)`
4020/// - `MaxIf$(formula,condition)` : return the minimum (maximum) (within one TTree entry)
4021/// of the value of the elements of the formula given as a parameter
4022/// if they match the condition. If no element matches the condition,
4023/// the result is zero. To avoid the resulting peak at zero, use the
4024/// pattern:
4025/// ~~~ {.cpp}
4026/// tree->Draw("MinIf$(formula,condition)","condition");
4027/// ~~~
4028/// which will avoid calculation `MinIf$` for the entries that have no match
4029/// for the condition.
4030/// - `Alt$(primary,alternate)` : return the value of "primary" if it is available
4031/// for the current iteration otherwise return the value of "alternate".
4032/// For example, with arr1[3] and arr2[2]
4033/// ~~~ {.cpp}
4034/// tree->Draw("arr1+Alt$(arr2,0)");
4035/// ~~~
4036/// will draw arr1[0]+arr2[0] ; arr1[1]+arr2[1] and arr1[2]+0
4037/// Or with a variable size array arr3
4038/// ~~~ {.cpp}
4039/// tree->Draw("Alt$(arr3[0],0)+Alt$(arr3[1],0)+Alt$(arr3[2],0)");
4040/// ~~~
4041/// will draw the sum arr3 for the index 0 to min(2,actual_size_of_arr3-1)
4042/// As a comparison
4043/// ~~~ {.cpp}
4044/// tree->Draw("arr3[0]+arr3[1]+arr3[2]");
4045/// ~~~
4046/// will draw the sum arr3 for the index 0 to 2 only if the
4047/// actual_size_of_arr3 is greater or equal to 3.
4048/// Note that the array in 'primary' is flattened/linearized thus using
4049/// `Alt$` with multi-dimensional arrays of different dimensions in unlikely
4050/// to yield the expected results. To visualize a bit more what elements
4051/// would be matched by TTree::Draw, TTree::Scan can be used:
4052/// ~~~ {.cpp}
4053/// tree->Scan("arr1:Alt$(arr2,0)");
4054/// ~~~
4055/// will print on one line the value of arr1 and (arr2,0) that will be
4056/// matched by
4057/// ~~~ {.cpp}
4058/// tree->Draw("arr1-Alt$(arr2,0)");
4059/// ~~~
4060/// The ternary operator is not directly supported in TTree::Draw however, to plot the
4061/// equivalent of `var2<20 ? -99 : var1`, you can use:
4062/// ~~~ {.cpp}
4063/// tree->Draw("(var2<20)*99+(var2>=20)*var1","");
4064/// ~~~
4065///
4066/// ### Drawing a user function accessing the TTree data directly
4067///
4068/// If the formula contains a file name, TTree::MakeProxy will be used
4069/// to load and execute this file. In particular it will draw the
4070/// result of a function with the same name as the file. The function
4071/// will be executed in a context where the name of the branches can
4072/// be used as a C++ variable.
4073///
4074/// For example draw px using the file hsimple.root (generated by the
4075/// hsimple.C tutorial), we need a file named hsimple.cxx:
4076/// ~~~ {.cpp}
4077/// double hsimple() {
4078/// return px;
4079/// }
4080/// ~~~
4081/// MakeProxy can then be used indirectly via the TTree::Draw interface
4082/// as follow:
4083/// ~~~ {.cpp}
4084/// new TFile("hsimple.root")
4085/// ntuple->Draw("hsimple.cxx");
4086/// ~~~
4087/// A more complete example is available in the tutorials directory:
4088/// `h1analysisProxy.cxx`, `h1analysProxy.h` and `h1analysisProxyCut.C`
4089/// which reimplement the selector found in `h1analysis.C`
4090///
4091/// The main features of this facility are:
4092///
4093/// * on-demand loading of branches
4094/// * ability to use the 'branchname' as if it was a data member
4095/// * protection against array out-of-bound
4096/// * ability to use the branch data as object (when the user code is available)
4097///
4098/// See TTree::MakeProxy for more details.
4099///
4100/// ### Making a Profile histogram
4101///
4102/// In case of a 2-Dim expression, one can generate a TProfile histogram
4103/// instead of a TH2F histogram by specifying option=prof or option=profs
4104/// or option=profi or option=profg ; the trailing letter select the way
4105/// the bin error are computed, See TProfile2D::SetErrorOption for
4106/// details on the differences.
4107/// The option=prof is automatically selected in case of y:x>>pf
4108/// where pf is an existing TProfile histogram.
4109///
4110/// ### Making a 2D Profile histogram
4111///
4112/// In case of a 3-Dim expression, one can generate a TProfile2D histogram
4113/// instead of a TH3F histogram by specifying option=prof or option=profs.
4114/// or option=profi or option=profg ; the trailing letter select the way
4115/// the bin error are computed, See TProfile2D::SetErrorOption for
4116/// details on the differences.
4117/// The option=prof is automatically selected in case of z:y:x>>pf
4118/// where pf is an existing TProfile2D histogram.
4119///
4120/// ### Making a 5D plot using GL
4121///
4122/// If option GL5D is specified together with 5 variables, a 5D plot is drawn
4123/// using OpenGL. See $ROOTSYS/tutorials/tree/staff.C as example.
4124///
4125/// ### Making a parallel coordinates plot
4126///
4127/// In case of a 2-Dim or more expression with the option=para, one can generate
4128/// a parallel coordinates plot. With that option, the number of dimensions is
4129/// arbitrary. Giving more than 4 variables without the option=para or
4130/// option=candle or option=goff will produce an error.
4131///
4132/// ### Making a candle sticks chart
4133///
4134/// In case of a 2-Dim or more expression with the option=candle, one can generate
4135/// a candle sticks chart. With that option, the number of dimensions is
4136/// arbitrary. Giving more than 4 variables without the option=para or
4137/// option=candle or option=goff will produce an error.
4138///
4139/// ### Normalizing the output histogram to 1
4140///
4141/// When option contains "norm" the output histogram is normalized to 1.
4142///
4143/// ### Saving the result of Draw to a TEventList, a TEntryList or a TEntryListArray
4144///
4145/// TTree::Draw can be used to fill a TEventList object (list of entry numbers)
4146/// instead of histogramming one variable.
4147/// If varexp0 has the form >>elist , a TEventList object named "elist"
4148/// is created in the current directory. elist will contain the list
4149/// of entry numbers satisfying the current selection.
4150/// If option "entrylist" is used, a TEntryList object is created
4151/// If the selection contains arrays, vectors or any container class and option
4152/// "entrylistarray" is used, a TEntryListArray object is created
4153/// containing also the subentries satisfying the selection, i.e. the indices of
4154/// the branches which hold containers classes.
4155/// Example:
4156/// ~~~ {.cpp}
4157/// tree.Draw(">>yplus","y>0")
4158/// ~~~
4159/// will create a TEventList object named "yplus" in the current directory.
4160/// In an interactive session, one can type (after TTree::Draw)
4161/// ~~~ {.cpp}
4162/// yplus.Print("all")
4163/// ~~~
4164/// to print the list of entry numbers in the list.
4165/// ~~~ {.cpp}
4166/// tree.Draw(">>yplus", "y>0", "entrylist")
4167/// ~~~
4168/// will create a TEntryList object names "yplus" in the current directory
4169/// ~~~ {.cpp}
4170/// tree.Draw(">>yplus", "y>0", "entrylistarray")
4171/// ~~~
4172/// will create a TEntryListArray object names "yplus" in the current directory
4173///
4174/// By default, the specified entry list is reset.
4175/// To continue to append data to an existing list, use "+" in front
4176/// of the list name;
4177/// ~~~ {.cpp}
4178/// tree.Draw(">>+yplus","y>0")
4179/// ~~~
4180/// will not reset yplus, but will enter the selected entries at the end
4181/// of the existing list.
4182///
4183/// ### Using a TEventList, TEntryList or TEntryListArray as Input
4184///
4185/// Once a TEventList or a TEntryList object has been generated, it can be used as input
4186/// for TTree::Draw. Use TTree::SetEventList or TTree::SetEntryList to set the
4187/// current event list
4188///
4189/// Example 1:
4190/// ~~~ {.cpp}
4191/// TEventList *elist = (TEventList*)gDirectory->Get("yplus");
4192/// tree->SetEventList(elist);
4193/// tree->Draw("py");
4194/// ~~~
4195/// Example 2:
4196/// ~~~ {.cpp}
4197/// TEntryList *elist = (TEntryList*)gDirectory->Get("yplus");
4198/// tree->SetEntryList(elist);
4199/// tree->Draw("py");
4200/// ~~~
4201/// If a TEventList object is used as input, a new TEntryList object is created
4202/// inside the SetEventList function. In case of a TChain, all tree headers are loaded
4203/// for this transformation. This new object is owned by the chain and is deleted
4204/// with it, unless the user extracts it by calling GetEntryList() function.
4205/// See also comments to SetEventList() function of TTree and TChain.
4206///
4207/// If arrays are used in the selection criteria and TEntryListArray is not used,
4208/// all the entries that have at least one element of the array that satisfy the selection
4209/// are entered in the list.
4210///
4211/// Example:
4212/// ~~~ {.cpp}
4213/// tree.Draw(">>pyplus","fTracks.fPy>0");
4214/// tree->SetEventList(pyplus);
4215/// tree->Draw("fTracks.fPy");
4216/// ~~~
4217/// will draw the fPy of ALL tracks in event with at least one track with
4218/// a positive fPy.
4219///
4220/// To select only the elements that did match the original selection
4221/// use TEventList::SetReapplyCut or TEntryList::SetReapplyCut.
4222///
4223/// Example:
4224/// ~~~ {.cpp}
4225/// tree.Draw(">>pyplus","fTracks.fPy>0");
4226/// pyplus->SetReapplyCut(kTRUE);
4227/// tree->SetEventList(pyplus);
4228/// tree->Draw("fTracks.fPy");
4229/// ~~~
4230/// will draw the fPy of only the tracks that have a positive fPy.
4231///
4232/// To draw only the elements that match a selection in case of arrays,
4233/// you can also use TEntryListArray (faster in case of a more general selection).
4234///
4235/// Example:
4236/// ~~~ {.cpp}
4237/// tree.Draw(">>pyplus","fTracks.fPy>0", "entrylistarray");
4238/// tree->SetEntryList(pyplus);
4239/// tree->Draw("fTracks.fPy");
4240/// ~~~
4241/// will draw the fPy of only the tracks that have a positive fPy,
4242/// but without redoing the selection.
4243///
4244/// Note: Use tree->SetEventList(0) if you do not want use the list as input.
4245///
4246/// ### How to obtain more info from TTree::Draw
4247///
4248/// Once TTree::Draw has been called, it is possible to access useful
4249/// information still stored in the TTree object via the following functions:
4250///
4251/// - GetSelectedRows() // return the number of values accepted by the selection expression. In case where no selection was specified, returns the number of values processed.
4252/// - GetV1() // returns a pointer to the double array of V1
4253/// - GetV2() // returns a pointer to the double array of V2
4254/// - GetV3() // returns a pointer to the double array of V3
4255/// - GetV4() // returns a pointer to the double array of V4
4256/// - GetW() // returns a pointer to the double array of Weights where weight equal the result of the selection expression.
4257///
4258/// where V1,V2,V3 correspond to the expressions in
4259/// ~~~ {.cpp}
4260/// TTree::Draw("V1:V2:V3:V4",selection);
4261/// ~~~
4262/// If the expression has more than 4 component use GetVal(index)
4263///
4264/// Example:
4265/// ~~~ {.cpp}
4266/// Root > ntuple->Draw("py:px","pz>4");
4267/// Root > TGraph *gr = new TGraph(ntuple->GetSelectedRows(),
4268/// ntuple->GetV2(), ntuple->GetV1());
4269/// Root > gr->Draw("ap"); //draw graph in current pad
4270/// ~~~
4271///
4272/// A more complete complete tutorial (treegetval.C) shows how to use the
4273/// GetVal() method.
4274///
4275/// creates a TGraph object with a number of points corresponding to the
4276/// number of entries selected by the expression "pz>4", the x points of the graph
4277/// being the px values of the Tree and the y points the py values.
4278///
4279/// Important note: By default TTree::Draw creates the arrays obtained
4280/// with GetW, GetV1, GetV2, GetV3, GetV4, GetVal with a length corresponding
4281/// to the parameter fEstimate. The content will be the last `GetSelectedRows() % GetEstimate()`
4282/// values calculated.
4283/// By default fEstimate=1000000 and can be modified
4284/// via TTree::SetEstimate. To keep in memory all the results (in case
4285/// where there is only one result per entry), use
4286/// ~~~ {.cpp}
4287/// tree->SetEstimate(tree->GetEntries()+1); // same as tree->SetEstimate(-1);
4288/// ~~~
4289/// You must call SetEstimate if the expected number of selected rows
4290/// you need to look at is greater than 1000000.
4291///
4292/// You can use the option "goff" to turn off the graphics output
4293/// of TTree::Draw in the above example.
4294///
4295/// ### Automatic interface to TTree::Draw via the TTreeViewer
4296///
4297/// A complete graphical interface to this function is implemented
4298/// in the class TTreeViewer.
4299/// To start the TTreeViewer, three possibilities:
4300/// - select TTree context menu item "StartViewer"
4301/// - type the command "TTreeViewer TV(treeName)"
4302/// - execute statement "tree->StartViewer();"
4304Long64_t TTree::Draw(const char* varexp, const char* selection, Option_t* option, Long64_t nentries, Long64_t firstentry)
4305{
4306 GetPlayer();
4307 if (fPlayer)
4308 return fPlayer->DrawSelect(varexp,selection,option,nentries,firstentry);
4309 return -1;
4310}
4311
4312////////////////////////////////////////////////////////////////////////////////
4313/// Remove some baskets from memory.
4315void TTree::DropBaskets()
4316{
4317 TBranch* branch = 0;
4319 for (Int_t i = 0; i < nb; ++i) {
4320 branch = (TBranch*) fBranches.UncheckedAt(i);
4321 branch->DropBaskets("all");
4322 }
4323}
4324
4325////////////////////////////////////////////////////////////////////////////////
4326/// Drop branch buffers to accommodate nbytes below MaxVirtualsize.
4329{
4330 // Be careful not to remove current read/write buffers.
4331 Int_t ndrop = 0;
4332 Int_t nleaves = fLeaves.GetEntriesFast();
4333 for (Int_t i = 0; i < nleaves; ++i) {
4334 TLeaf* leaf = (TLeaf*) fLeaves.UncheckedAt(i);
4335 TBranch* branch = (TBranch*) leaf->GetBranch();
4336 Int_t nbaskets = branch->GetListOfBaskets()->GetEntries();
4337 for (Int_t j = 0; j < nbaskets - 1; ++j) {
4338 if ((j == branch->GetReadBasket()) || (j == branch->GetWriteBasket())) {
4339 continue;
4340 }
4341 TBasket* basket = (TBasket*)branch->GetListOfBaskets()->UncheckedAt(j);
4342 if (basket) {
4343 ndrop += basket->DropBuffers();
4345 return;
4346 }
4347 }
4348 }
4349 }
4350}
4351
4352////////////////////////////////////////////////////////////////////////////////
4353/// Fill all branches.
4354///
4355/// This function loops on all the branches of this tree. For
4356/// each branch, it copies to the branch buffer (basket) the current
4357/// values of the leaves data types. If a leaf is a simple data type,
4358/// a simple conversion to a machine independent format has to be done.
4359///
4360/// This machine independent version of the data is copied into a
4361/// basket (each branch has its own basket). When a basket is full
4362/// (32k worth of data by default), it is then optionally compressed
4363/// and written to disk (this operation is also called committing or
4364/// 'flushing' the basket). The committed baskets are then
4365/// immediately removed from memory.
4366///
4367/// The function returns the number of bytes committed to the
4368/// individual branches.
4369///
4370/// If a write error occurs, the number of bytes returned is -1.
4371///
4372/// If no data are written, because, e.g., the branch is disabled,
4373/// the number of bytes returned is 0.
4374///
4375/// __The baskets are flushed and the Tree header saved at regular intervals__
4376///
4377/// At regular intervals, when the amount of data written so far is
4378/// greater than fAutoFlush (see SetAutoFlush) all the baskets are flushed to disk.
4379/// This makes future reading faster as it guarantees that baskets belonging to nearby
4380/// entries will be on the same disk region.
4381/// When the first call to flush the baskets happen, we also take this opportunity
4382/// to optimize the baskets buffers.
4383/// We also check if the amount of data written is greater than fAutoSave (see SetAutoSave).
4384/// In this case we also write the Tree header. This makes the Tree recoverable up to this point
4385/// in case the program writing the Tree crashes.
4386/// The decisions to FlushBaskets and Auto Save can be made based either on the number
4387/// of bytes written (fAutoFlush and fAutoSave negative) or on the number of entries
4388/// written (fAutoFlush and fAutoSave positive).
4389/// Note that the user can decide to call FlushBaskets and AutoSave in her event loop
4390/// base on the number of events written instead of the number of bytes written.
4391///
4392/// Note that calling FlushBaskets too often increases the IO time.
4393///
4394/// Note that calling AutoSave too often increases the IO time and also the file size.
4397{
4398 Int_t nbytes = 0;
4399 Int_t nwrite = 0;
4400 Int_t nerror = 0;
4401 Int_t nbranches = fBranches.GetEntriesFast();
4402
4403 // Case of one single super branch. Automatically update
4404 // all the branch addresses if a new object was created.
4405 if (nbranches == 1)
4406 ((TBranch *)fBranches.UncheckedAt(0))->UpdateAddress();
4407
4408 if (fBranchRef)
4409 fBranchRef->Clear();
4410
4411#ifdef R__USE_IMT
4412 const auto useIMT = ROOT::IsImplicitMTEnabled() && fIMTEnabled;
4414 if (useIMT) {
4415 fIMTFlush = true;
4416 fIMTZipBytes.store(0);
4417 fIMTTotBytes.store(0);
4418 }
4419#endif
4420
4421 for (Int_t i = 0; i < nbranches; ++i) {
4422 // Loop over all branches, filling and accumulating bytes written and error counts.
4423 TBranch *branch = (TBranch *)fBranches.UncheckedAt(i);
4424
4425 if (branch->TestBit(kDoNotProcess))
4426 continue;
4427
4428#ifndef R__USE_IMT
4429 nwrite = branch->FillImpl(nullptr);
4430#else
4431 nwrite = branch->FillImpl(useIMT ? &imtHelper : nullptr);
4432#endif
4433 if (nwrite < 0) {
4434 if (nerror < 2) {
4435 Error("Fill", "Failed filling branch:%s.%s, nbytes=%d, entry=%lld\n"
4436 " This error is symptomatic of a Tree created as a memory-resident Tree\n"
4437 " Instead of doing:\n"
4438 " TTree *T = new TTree(...)\n"
4439 " TFile *f = new TFile(...)\n"
4440 " you should do:\n"
4441 " TFile *f = new TFile(...)\n"
4442 " TTree *T = new TTree(...)\n\n",
4443 GetName(), branch->GetName(), nwrite, fEntries + 1);
4444 } else {
4445 Error("Fill", "Failed filling branch:%s.%s, nbytes=%d, entry=%lld", GetName(), branch->GetName(), nwrite,
4446 fEntries + 1);
4447 }
4448 ++nerror;
4449 } else {
4450 nbytes += nwrite;
4451 }
4452 }
4453
4454#ifdef R__USE_IMT
4455 if (fIMTFlush) {
4456 imtHelper.Wait();
4457 fIMTFlush = false;
4458 const_cast<TTree *>(this)->AddTotBytes(fIMTTotBytes);
4459 const_cast<TTree *>(this)->AddZipBytes(fIMTZipBytes);
4460 nbytes += imtHelper.GetNbytes();
4461 nerror += imtHelper.GetNerrors();
4462 }
4463#endif
4464
4465 if (fBranchRef)
4466 fBranchRef->Fill();
4467
4468 ++fEntries;
4469
4470 if (fEntries > fMaxEntries)
4471 KeepCircular();
4472
4473 if (gDebug > 0)
4474 Info("TTree::Fill", " - A: %d %lld %lld %lld %lld %lld %lld \n", nbytes, fEntries, fAutoFlush, fAutoSave,
4476
4477 bool autoFlush = false;
4478 bool autoSave = false;
4479
4480 if (fAutoFlush != 0 || fAutoSave != 0) {
4481 // Is it time to flush or autosave baskets?
4482 if (fFlushedBytes == 0) {
4483 // If fFlushedBytes == 0, it means we never flushed or saved, so
4484 // we need to check if it's time to do it and recompute the values
4485 // of fAutoFlush and fAutoSave in terms of the number of entries.
4486 // Decision can be based initially either on the number of bytes
4487 // or the number of entries written.
4488 Long64_t zipBytes = GetZipBytes();
4489
4490 if (fAutoFlush)
4491 autoFlush = fAutoFlush < 0 ? (zipBytes > -fAutoFlush) : fEntries % fAutoFlush == 0;
4492
4493 if (fAutoSave)
4494 autoSave = fAutoSave < 0 ? (zipBytes > -fAutoSave) : fEntries % fAutoSave == 0;
4495
4496 if (autoFlush || autoSave) {
4497 // First call FlushBasket to make sure that fTotBytes is up to date.
4499 autoFlush = false; // avoid auto flushing again later
4500
4501 // When we are in one-basket-per-cluster mode, there is no need to optimize basket:
4502 // they will automatically grow to the size needed for an event cluster (with the basket
4503 // shrinking preventing them from growing too much larger than the actually-used space).
4505 OptimizeBaskets(GetTotBytes(), 1, "");
4506 if (gDebug > 0)
4507 Info("TTree::Fill", "OptimizeBaskets called at entry %lld, fZipBytes=%lld, fFlushedBytes=%lld\n",
4509 }
4511 fAutoFlush = fEntries; // Use test on entries rather than bytes
4512
4513 // subsequently in run
4514 if (fAutoSave < 0) {
4515 // Set fAutoSave to the largest integer multiple of
4516 // fAutoFlush events such that fAutoSave*fFlushedBytes
4517 // < (minus the input value of fAutoSave)
4518 Long64_t totBytes = GetTotBytes();
4519 if (zipBytes != 0) {
4520 fAutoSave = TMath::Max(fAutoFlush, fEntries * ((-fAutoSave / zipBytes) / fEntries));
4521 } else if (totBytes != 0) {
4522 fAutoSave = TMath::Max(fAutoFlush, fEntries * ((-fAutoSave / totBytes) / fEntries));
4523 } else {
4525 TTree::Class()->WriteBuffer(b, (TTree *)this);
4526 Long64_t total = b.Length();
4528 }
4529 } else if (fAutoSave > 0) {
4531 }
4532
4533 if (fAutoSave != 0 && fEntries >= fAutoSave)
4534 autoSave = true;
4535
4536 if (gDebug > 0)
4537 Info("TTree::Fill", "First AutoFlush. fAutoFlush = %lld, fAutoSave = %lld\n", fAutoFlush, fAutoSave);
4538 }
4539 } else {
4540 // Check if we need to auto flush
4541 if (fAutoFlush) {
4542 if (fNClusterRange == 0)
4543 autoFlush = fEntries > 1 && fEntries % fAutoFlush == 0;
4544 else
4545 autoFlush = (fEntries - (fClusterRangeEnd[fNClusterRange - 1] + 1)) % fAutoFlush == 0;
4546 }
4547 // Check if we need to auto save
4548 if (fAutoSave)
4549 autoSave = fEntries % fAutoSave == 0;
4550 }
4551 }
4552
4553 if (autoFlush) {
4555 if (gDebug > 0)
4556 Info("TTree::Fill", "FlushBaskets() called at entry %lld, fZipBytes=%lld, fFlushedBytes=%lld\n", fEntries,
4559 }
4560
4561 if (autoSave) {
4562 AutoSave(); // does not call FlushBasketsImpl() again
4563 if (gDebug > 0)
4564 Info("TTree::Fill", "AutoSave called at entry %lld, fZipBytes=%lld, fSavedBytes=%lld\n", fEntries,
4566 }
4567
4568 // Check that output file is still below the maximum size.
4569 // If above, close the current file and continue on a new file.
4570 // Currently, the automatic change of file is restricted
4571 // to the case where the tree is in the top level directory.
4572 if (fDirectory)
4573 if (TFile *file = fDirectory->GetFile())
4574 if ((TDirectory *)file == fDirectory && (file->GetEND() > fgMaxTreeSize))
4576
4577 return nerror == 0 ? nbytes : -1;
4578}
4579
4580////////////////////////////////////////////////////////////////////////////////
4581/// Search in the array for a branch matching the branch name,
4582/// with the branch possibly expressed as a 'full' path name (with dots).
4584static TBranch *R__FindBranchHelper(TObjArray *list, const char *branchname) {
4585 if (list==0 || branchname == 0 || branchname[0] == '\0') return 0;
4586
4587 Int_t nbranches = list->GetEntries();
4588
4589 UInt_t brlen = strlen(branchname);
4590
4591 for(Int_t index = 0; index < nbranches; ++index) {
4592 TBranch *where = (TBranch*)list->UncheckedAt(index);
4593
4594 const char *name = where->GetName();
4595 UInt_t len = strlen(name);
4596 if (len && name[len-1]==']') {
4597 const char *dim = strchr(name,'[');
4598 if (dim) {
4599 len = dim - name;
4600 }
4601 }
4602 if (brlen == len && strncmp(branchname,name,len)==0) {
4603 return where;
4604 }
4605 TBranch *next = 0;
4606 if ((brlen >= len) && (branchname[len] == '.')
4607 && strncmp(name, branchname, len) == 0) {
4608 // The prefix subbranch name match the branch name.
4609
4610 next = where->FindBranch(branchname);
4611 if (!next) {
4612 next = where->FindBranch(branchname+len+1);
4613 }
4614 if (next) return next;
4615 }
4616 const char *dot = strchr((char*)branchname,'.');
4617 if (dot) {
4618 if (len==(size_t)(dot-branchname) &&
4619 strncmp(branchname,name,dot-branchname)==0 ) {
4620 return R__FindBranchHelper(where->GetListOfBranches(),dot+1);
4621 }
4622 }
4623 }
4624 return 0;
4625}
4626
4627////////////////////////////////////////////////////////////////////////////////
4628/// Return the branch that correspond to the path 'branchname', which can
4629/// include the name of the tree or the omitted name of the parent branches.
4630/// In case of ambiguity, returns the first match.
4632TBranch* TTree::FindBranch(const char* branchname)
4633{
4634 // We already have been visited while recursively looking
4635 // through the friends tree, let return
4637 return 0;
4638 }
4639
4640 TBranch* branch = 0;
4641 // If the first part of the name match the TTree name, look for the right part in the
4642 // list of branches.
4643 // This will allow the branchname to be preceded by
4644 // the name of this tree.
4645 if (strncmp(fName.Data(),branchname,fName.Length())==0 && branchname[fName.Length()]=='.') {
4646 branch = R__FindBranchHelper( GetListOfBranches(), branchname + fName.Length() + 1);
4647 if (branch) return branch;
4648 }
4649 // If we did not find it, let's try to find the full name in the list of branches.
4650 branch = R__FindBranchHelper(GetListOfBranches(), branchname);
4651 if (branch) return branch;
4652
4653 // If we still did not find, let's try to find it within each branch assuming it does not the branch name.
4654 TIter next(GetListOfBranches());
4655 while ((branch = (TBranch*) next())) {
4656 TBranch* nestedbranch = branch->FindBranch(branchname);
4657 if (nestedbranch) {
4658 return nestedbranch;
4659 }
4660 }
4661
4662 // Search in list of friends.
4663 if (!fFriends) {
4664 return 0;
4665 }
4666 TFriendLock lock(this, kFindBranch);
4667 TIter nextf(fFriends);
4668 TFriendElement* fe = 0;
4669 while ((fe = (TFriendElement*) nextf())) {
4670 TTree* t = fe->GetTree();
4671 if (!t) {
4672 continue;
4673 }
4674 // If the alias is present replace it with the real name.
4675 const char *subbranch = strstr(branchname, fe->GetName());
4676 if (subbranch != branchname) {
4677 subbranch = 0;
4678 }
4679 if (subbranch) {
4680 subbranch += strlen(fe->GetName());
4681 if (*subbranch != '.') {
4682 subbranch = 0;
4683 } else {
4684 ++subbranch;
4685 }
4686 }
4687 std::ostringstream name;
4688 if (subbranch) {
4689 name << t->GetName() << "." << subbranch;
4690 } else {
4691 name << branchname;
4692 }
4693 branch = t->FindBranch(name.str().c_str());
4694 if (branch) {
4695 return branch;
4696 }
4697 }
4698 return 0;
4699}
4700
4701////////////////////////////////////////////////////////////////////////////////
4702/// Find leaf..
4704TLeaf* TTree::FindLeaf(const char* searchname)
4705{
4706 // We already have been visited while recursively looking
4707 // through the friends tree, let's return.
4709 return 0;
4710 }
4711
4712 // This will allow the branchname to be preceded by
4713 // the name of this tree.
4714 char* subsearchname = (char*) strstr(searchname, GetName());
4715 if (subsearchname != searchname) {
4716 subsearchname = 0;
4717 }
4718 if (subsearchname) {
4719 subsearchname += strlen(GetName());
4720 if (*subsearchname != '.') {
4721 subsearchname = 0;
4722 } else {
4723 ++subsearchname;
4724 if (subsearchname[0]==0) {
4725 subsearchname = 0;
4726 }
4727 }
4728 }
4729
4730 TString leafname;
4731 TString leaftitle;
4732 TString longname;
4733 TString longtitle;
4734
4735 const bool searchnameHasDot = strchr(searchname, '.') != nullptr;
4736
4737 // For leaves we allow for one level up to be prefixed to the name.
4738 TIter next(GetListOfLeaves());
4739 TLeaf* leaf = 0;
4740 while ((leaf = (TLeaf*) next())) {
4741 leafname = leaf->GetName();
4742 Ssiz_t dim = leafname.First('[');
4743 if (dim >= 0) leafname.Remove(dim);
4744
4745 if (leafname == searchname) {
4746 return leaf;
4747 }
4748 if (subsearchname && leafname == subsearchname) {
4749 return leaf;
4750 }
4751 // The TLeafElement contains the branch name
4752 // in its name, let's use the title.
4753 leaftitle = leaf->GetTitle();
4754 dim = leaftitle.First('[');
4755 if (dim >= 0) leaftitle.Remove(dim);
4756
4757 if (leaftitle == searchname) {
4758 return leaf;
4759 }
4760 if (subsearchname && leaftitle == subsearchname) {
4761 return leaf;
4762 }
4763 if (!searchnameHasDot)
4764 continue;
4765 TBranch* branch = leaf->GetBranch();
4766 if (branch) {
4767 longname.Form("%s.%s",branch->GetName(),leafname.Data());
4768 dim = longname.First('[');
4769 if (dim>=0) longname.Remove(dim);
4770 if (longname == searchname) {
4771 return leaf;
4772 }
4773 if (subsearchname && longname == subsearchname) {
4774 return leaf;
4775 }
4776 longtitle.Form("%s.%s",branch->GetName(),leaftitle.Data());
4777 dim = longtitle.First('[');
4778 if (dim>=0) longtitle.Remove(dim);
4779 if (longtitle == searchname) {
4780 return leaf;
4781 }
4782 if (subsearchname && longtitle == subsearchname) {
4783 return leaf;
4784 }
4785 // The following is for the case where the branch is only
4786 // a sub-branch. Since we do not see it through
4787 // TTree::GetListOfBranches, we need to see it indirectly.
4788 // This is the less sturdy part of this search ... it may
4789 // need refining ...
4790 if (strstr(searchname, ".") && !strcmp(searchname, branch->GetName())) {
4791 return leaf;
4792 }
4793 if (subsearchname && strstr(subsearchname, ".") && !strcmp(subsearchname, branch->GetName())) {
4794 return leaf;
4795 }
4796 }
4797 }
4798 // Search in list of friends.
4799 if (!fFriends) {
4800 return 0;
4801 }
4802 TFriendLock lock(this, kFindLeaf);
4803 TIter nextf(fFriends);
4804 TFriendElement* fe = 0;
4805 while ((fe = (TFriendElement*) nextf())) {
4806 TTree* t = fe->GetTree();
4807 if (!t) {
4808 continue;
4809 }
4810 // If the alias is present replace it with the real name.
4811 subsearchname = (char*) strstr(searchname, fe->GetName());
4812 if (subsearchname != searchname) {
4813 subsearchname = 0;
4814 }
4815 if (subsearchname) {
4816 subsearchname += strlen(fe->GetName());
4817 if (*subsearchname != '.') {
4818 subsearchname = 0;
4819 } else {
4820 ++subsearchname;
4821 }
4822 }
4823 if (subsearchname) {
4824 leafname.Form("%s.%s",t->GetName(),subsearchname);
4825 } else {
4826 leafname = searchname;
4827 }
4828 leaf = t->FindLeaf(leafname);
4829 if (leaf) {
4830 return leaf;
4831 }
4832 }
4833 return 0;
4834}
4835
4836////////////////////////////////////////////////////////////////////////////////
4837/// Fit a projected item(s) from a tree.
4838///
4839/// funcname is a TF1 function.
4840///
4841/// See TTree::Draw() for explanations of the other parameters.
4842///
4843/// By default the temporary histogram created is called htemp.
4844/// If varexp contains >>hnew , the new histogram created is called hnew
4845/// and it is kept in the current directory.
4846///
4847/// The function returns the number of selected entries.
4848///
4849/// Example:
4850/// ~~~ {.cpp}
4851/// tree.Fit(pol4,"sqrt(x)>>hsqrt","y>0")
4852/// ~~~
4853/// will fit sqrt(x) and save the histogram as "hsqrt" in the current
4854/// directory.
4855///
4856/// See also TTree::UnbinnedFit
4857///
4858/// ## Return status
4859///
4860/// The function returns the status of the histogram fit (see TH1::Fit)
4861/// If no entries were selected, the function returns -1;
4862/// (i.e. fitResult is null if the fit is OK)
4864Int_t TTree::Fit(const char* funcname, const char* varexp, const char* selection, Option_t* option, Option_t* goption, Long64_t nentries, Long64_t firstentry)
4865{
4866 GetPlayer();
4867 if (fPlayer) {
4868 return fPlayer->Fit(funcname, varexp, selection, option, goption, nentries, firstentry);
4869 }
4870 return -1;
4871}
4872
4873namespace {
4874struct BoolRAIIToggle {
4875 Bool_t &m_val;
4876
4877 BoolRAIIToggle(Bool_t &val) : m_val(val) { m_val = true; }
4878 ~BoolRAIIToggle() { m_val = false; }
4879};
4880}
4881
4882////////////////////////////////////////////////////////////////////////////////
4883/// Write to disk all the basket that have not yet been individually written and
4884/// create an event cluster boundary (by default).
4885///
4886/// If the caller wishes to flush the baskets but not create an event cluster,
4887/// then set create_cluster to false.
4888///
4889/// If ROOT has IMT-mode enabled, this will launch multiple TBB tasks in parallel
4890/// via TThreadExecutor to do this operation; one per basket compression. If the
4891/// caller utilizes TBB also, care must be taken to prevent deadlocks.
4892///
4893/// For example, let's say the caller holds mutex A and calls FlushBaskets; while
4894/// TBB is waiting for the ROOT compression tasks to complete, it may decide to
4895/// run another one of the user's tasks in this thread. If the second user task
4896/// tries to acquire A, then a deadlock will occur. The example call sequence
4897/// looks like this:
4898///
4899/// - User acquires mutex A
4900/// - User calls FlushBaskets.
4901/// - ROOT launches N tasks and calls wait.
4902/// - TBB schedules another user task, T2.
4903/// - T2 tries to acquire mutex A.
4904///
4905/// At this point, the thread will deadlock: the code may function with IMT-mode
4906/// disabled if the user assumed the legacy code never would run their own TBB
4907/// tasks.
4908///
4909/// SO: users of TBB who want to enable IMT-mode should carefully review their
4910/// locking patterns and make sure they hold no coarse-grained application
4911/// locks when they invoke ROOT.
4912///
4913/// Return the number of bytes written or -1 in case of write error.
4914Int_t TTree::FlushBaskets(Bool_t create_cluster) const
4915{
4916 Int_t retval = FlushBasketsImpl();
4917 if (retval == -1) return retval;
4918
4919 if (create_cluster) const_cast<TTree *>(this)->MarkEventCluster();
4920 return retval;
4921}
4922
4923////////////////////////////////////////////////////////////////////////////////
4924/// Internal implementation of the FlushBaskets algorithm.
4925/// Unlike the public interface, this does NOT create an explicit event cluster
4926/// boundary; it is up to the (internal) caller to determine whether that should
4927/// done.
4928///
4929/// Otherwise, the comments for FlushBaskets applies.
4932{
4933 if (!fDirectory) return 0;
4934 Int_t nbytes = 0;
4935 Int_t nerror = 0;
4936 TObjArray *lb = const_cast<TTree*>(this)->GetListOfBranches();
4937 Int_t nb = lb->GetEntriesFast();
4938
4939#ifdef R__USE_IMT
4940 const auto useIMT = ROOT::IsImplicitMTEnabled() && fIMTEnabled;
4941 if (useIMT) {
4942 // ROOT-9668: here we need to check if the size of fSortedBranches is different from the
4943 // size of the list of branches before triggering the initialisation of the fSortedBranches
4944 // container to cover two cases:
4945 // 1. This is the first time we flush. fSortedBranches is empty and we need to fill it.
4946 // 2. We flushed at least once already but a branch has been be added to the tree since then
4947 if (fSortedBranches.size() != unsigned(nb)) { const_cast<TTree*>(this)->InitializeBranchLists(false); }
4948
4949 BoolRAIIToggle sentry(fIMTFlush);
4950 fIMTZipBytes.store(0);
4951 fIMTTotBytes.store(0);
4952 std::atomic<Int_t> nerrpar(0);
4953 std::atomic<Int_t> nbpar(0);
4954 std::atomic<Int_t> pos(0);
4955
4956 auto mapFunction = [&]() {
4957 // The branch to process is obtained when the task starts to run.
4958 // This way, since branches are sorted, we make sure that branches
4959 // leading to big tasks are processed first. If we assigned the
4960 // branch at task creation time, the scheduler would not necessarily
4961 // respect our sorting.
4962 Int_t j = pos.fetch_add(1);
4963
4964 auto branch = fSortedBranches[j].second;
4965 if (R__unlikely(!branch)) { return; }
4966
4967 if (R__unlikely(gDebug > 0)) {
4968 std::stringstream ss;
4969 ss << std::this_thread::get_id();
4970 Info("FlushBaskets", "[IMT] Thread %s", ss.str().c_str());
4971 Info("FlushBaskets", "[IMT] Running task for branch #%d: %s", j, branch->GetName());
4972 }
4973
4974 Int_t nbtask = branch->FlushBaskets();
4975
4976 if (nbtask < 0) { nerrpar++; }
4977 else { nbpar += nbtask; }
4978 };
4979
4981 pool.Foreach(mapFunction, nb);
4982
4983 fIMTFlush = false;
4984 const_cast<TTree*>(this)->AddTotBytes(fIMTTotBytes);
4985 const_cast<TTree*>(this)->AddZipBytes(fIMTZipBytes);
4986
4987 return nerrpar ? -1 : nbpar.load();
4988 }
4989#endif
4990 for (Int_t j = 0; j < nb; j++) {
4991 TBranch* branch = (TBranch*) lb->UncheckedAt(j);
4992 if (branch) {
4993 Int_t nwrite = branch->FlushBaskets();
4994 if (nwrite<0) {
4995 ++nerror;
4996 } else {
4997 nbytes += nwrite;
4998 }
4999 }
5000 }
5001 if (nerror) {
5002 return -1;
5003 } else {
5004 return nbytes;
5005 }
5006}
5007
5008////////////////////////////////////////////////////////////////////////////////
5009/// Returns the expanded value of the alias. Search in the friends if any.
5011const char* TTree::GetAlias(const char* aliasName) const
5012{
5013 // We already have been visited while recursively looking
5014 // through the friends tree, let's return.
5016 return 0;
5017 }
5018 if (fAliases) {
5019 TObject* alias = fAliases->FindObject(aliasName);
5020 if (alias) {
5021 return alias->GetTitle();
5022 }
5023 }
5024 if (!fFriends) {
5025 return 0;
5026 }
5027 TFriendLock lock(const_cast<TTree*>(this), kGetAlias);
5028 TIter nextf(fFriends);
5029 TFriendElement* fe = 0;
5030 while ((fe = (TFriendElement*) nextf())) {
5031 TTree* t = fe->GetTree();
5032 if (t) {
5033 const char* alias = t->GetAlias(aliasName);
5034 if (alias) {
5035 return alias;
5036 }
5037 const char* subAliasName = strstr(aliasName, fe->GetName());
5038 if (subAliasName && (subAliasName[strlen(fe->GetName())] == '.')) {
5039 alias = t->GetAlias(aliasName + strlen(fe->GetName()) + 1);
5040 if (alias) {
5041 return alias;
5042 }
5043 }
5044 }
5045 }
5046 return 0;
5047}
5048
5049////////////////////////////////////////////////////////////////////////////////
5050/// Return pointer to the branch with the given name in this tree or its friends.
5052TBranch* TTree::GetBranch(const char* name)
5053{
5054 if (name == 0) return 0;
5055
5056 // We already have been visited while recursively
5057 // looking through the friends tree, let's return.
5059 return 0;
5060 }
5061
5062 // Search using branches.
5064 for (Int_t i = 0; i < nb; i++) {
5065 TBranch* branch = (TBranch*) fBranches.UncheckedAt(i);
5066 if (!branch) {
5067 continue;
5068 }
5069 if (!strcmp(branch->GetName(), name)) {
5070 return branch;
5071 }
5072 TObjArray* lb = branch->GetListOfBranches();
5073 Int_t nb1 = lb->GetEntriesFast();
5074 for (Int_t j = 0; j < nb1; j++) {
5075 TBranch* b1 = (TBranch*) lb->UncheckedAt(j);
5076 if (!strcmp(b1->GetName(), name)) {
5077 return b1;
5078 }
5079 TObjArray* lb1 = b1->GetListOfBranches();
5080 Int_t nb2 = lb1->GetEntriesFast();
5081 for (Int_t k = 0; k < nb2; k++) {
5082 TBranch* b2 = (TBranch*) lb1->UncheckedAt(k);
5083 if (!strcmp(b2->GetName(), name)) {
5084 return b2;
5085 }
5086 }
5087 }
5088 }
5089
5090 // Search using leaves.
5091 TObjArray* leaves = GetListOfLeaves();
5092 Int_t nleaves = leaves->GetEntriesFast();
5093 for (Int_t i = 0; i < nleaves; i++) {
5094 TLeaf* leaf = (TLeaf*) leaves->UncheckedAt(i);
5095 TBranch* branch = leaf->GetBranch();
5096 if (!strcmp(branch->GetName(), name)) {
5097 return branch;
5098 }
5099 }
5100
5101 if (!fFriends) {
5102 return 0;
5103 }
5104
5105 // Search in list of friends.
5106 TFriendLock lock(this, kGetBranch);
5107 TIter next(fFriends);
5108 TFriendElement* fe = 0;
5109 while ((fe = (TFriendElement*) next())) {
5110 TTree* t = fe->GetTree();
5111 if (t) {
5112 TBranch* branch = t->GetBranch(name);
5113 if (branch) {
5114 return branch;
5115 }
5116 }
5117 }
5118
5119 // Second pass in the list of friends when
5120 // the branch name is prefixed by the tree name.
5121 next.Reset();
5122 while ((fe = (TFriendElement*) next())) {
5123 TTree* t = fe->GetTree();
5124 if (!t) {
5125 continue;
5126 }
5127 char* subname = (char*) strstr(name, fe->GetName());
5128 if (subname != name) {
5129 continue;
5130 }
5131 Int_t l = strlen(fe->GetName());
5132 subname += l;
5133 if (*subname != '.') {
5134 continue;
5135 }
5136 subname++;
5137 TBranch* branch = t->GetBranch(subname);
5138 if (branch) {
5139 return branch;
5140 }
5141 }
5142 return 0;
5143}
5144
5145////////////////////////////////////////////////////////////////////////////////
5146/// Return status of branch with name branchname.
5147///
5148/// - 0 if branch is not activated
5149/// - 1 if branch is activated
5151Bool_t TTree::GetBranchStatus(const char* branchname) const
5152{
5153 TBranch* br = const_cast<TTree*>(this)->GetBranch(branchname);
5154 if (br) {
5155 return br->TestBit(kDoNotProcess) == 0;
5156 }
5157 return 0;
5158}
5159
5160////////////////////////////////////////////////////////////////////////////////
5161/// Static function returning the current branch style.
5162///
5163/// - style = 0 old Branch
5164/// - style = 1 new Bronch
5167{
5168 return fgBranchStyle;
5169}
5170
5171////////////////////////////////////////////////////////////////////////////////
5172/// Used for automatic sizing of the cache.
5173///
5174/// Estimates a suitable size for the tree cache based on AutoFlush.
5175/// A cache sizing factor is taken from the configuration. If this yields zero
5176/// and withDefault is true the historical algorithm for default size is used.
5178Long64_t TTree::GetCacheAutoSize(Bool_t withDefault /* = kFALSE */ ) const
5179{
5180 const char *stcs;
5181 Double_t cacheFactor = 0.0;
5182 if (!(stcs = gSystem->Getenv("ROOT_TTREECACHE_SIZE")) || !*stcs) {
5183 cacheFactor = gEnv->GetValue("TTreeCache.Size", 1.0);
5184 } else {
5185 cacheFactor = TString(stcs).Atof();
5186 }
5187
5188 if (cacheFactor < 0.0) {
5189 // ignore negative factors
5190 cacheFactor = 0.0;
5191 }
5192
5193 Long64_t cacheSize = 0;
5194
5195 if (fAutoFlush < 0) cacheSize = Long64_t(-cacheFactor*fAutoFlush);
5196 else if (fAutoFlush == 0) cacheSize = 0;
5197 else cacheSize = Long64_t(cacheFactor*1.5*fAutoFlush*GetZipBytes()/(fEntries+1));
5198
5199 if (cacheSize >= (INT_MAX / 4)) {
5200 cacheSize = INT_MAX / 4;
5201 }
5202
5203 if (cacheSize < 0) {
5204 cacheSize = 0;
5205 }
5206
5207 if (cacheSize == 0 && withDefault) {
5208 if (fAutoFlush < 0) cacheSize = -fAutoFlush;
5209 else if (fAutoFlush == 0) cacheSize = 0;
5210 else cacheSize = Long64_t(1.5*fAutoFlush*GetZipBytes()/(fEntries+1));
5211 }
5212
5213 return cacheSize;
5214}
5215
5216////////////////////////////////////////////////////////////////////////////////
5217/// Return an iterator over the cluster of baskets starting at firstentry.
5218///
5219/// This iterator is not yet supported for TChain object.
5220/// ~~~ {.cpp}
5221/// TTree::TClusterIterator clusterIter = tree->GetClusterIterator(entry);
5222/// Long64_t clusterStart;
5223/// while( (clusterStart = clusterIter()) < tree->GetEntries() ) {
5224/// printf("The cluster starts at %lld and ends at %lld (inclusive)\n",clusterStart,clusterIter.GetNextEntry()-1);
5225/// }
5226/// ~~~
5229{
5230 // create cache if wanted
5231 if (fCacheDoAutoInit)
5233
5234 return TClusterIterator(this,firstentry);
5235}
5236
5237////////////////////////////////////////////////////////////////////////////////
5238/// Return pointer to the current file.
5241{
5242 if (!fDirectory || fDirectory==gROOT) {
5243 return 0;
5244 }
5245 return fDirectory->GetFile();
5246}
5247
5248////////////////////////////////////////////////////////////////////////////////
5249/// Return the number of entries matching the selection.
5250/// Return -1 in case of errors.
5251///
5252/// If the selection uses any arrays or containers, we return the number
5253/// of entries where at least one element match the selection.
5254/// GetEntries is implemented using the selector class TSelectorEntries,
5255/// which can be used directly (see code in TTreePlayer::GetEntries) for
5256/// additional option.
5257/// If SetEventList was used on the TTree or TChain, only that subset
5258/// of entries will be considered.
5260Long64_t TTree::GetEntries(const char *selection)
5261{
5262 GetPlayer();
5263 if (fPlayer) {
5264 return fPlayer->GetEntries(selection);
5265 }
5266 return -1;
5267}
5268
5269////////////////////////////////////////////////////////////////////////////////
5270/// Return pointer to the 1st Leaf named name in any Branch of this Tree or
5271/// any branch in the list of friend trees.
5274{
5275 if (fEntries) return fEntries;
5276 if (!fFriends) return 0;
5278 if (!fr) return 0;
5279 TTree *t = fr->GetTree();
5280 if (t==0) return 0;
5281 return t->GetEntriesFriend();
5282}
5283
5284////////////////////////////////////////////////////////////////////////////////
5285/// Read all branches of entry and return total number of bytes read.
5286///
5287/// - `getall = 0` : get only active branches
5288/// - `getall = 1` : get all branches
5289///
5290/// The function returns the number of bytes read from the input buffer.
5291/// If entry does not exist the function returns 0.
5292/// If an I/O error occurs, the function returns -1.
5293///
5294/// If the Tree has friends, also read the friends entry.
5295///
5296/// To activate/deactivate one or more branches, use TBranch::SetBranchStatus
5297/// For example, if you have a Tree with several hundred branches, and you
5298/// are interested only by branches named "a" and "b", do
5299/// ~~~ {.cpp}
5300/// mytree.SetBranchStatus("*",0); //disable all branches
5301/// mytree.SetBranchStatus("a",1);
5302/// mytree.SetBranchStatus("b",1);
5303/// ~~~
5304/// when calling mytree.GetEntry(i); only branches "a" and "b" will be read.
5305///
5306/// __WARNING!!__
5307/// If your Tree has been created in split mode with a parent branch "parent.",
5308/// ~~~ {.cpp}
5309/// mytree.SetBranchStatus("parent",1);
5310/// ~~~
5311/// will not activate the sub-branches of "parent". You should do:
5312/// ~~~ {.cpp}
5313/// mytree.SetBranchStatus("parent*",1);
5314/// ~~~
5315/// Without the trailing dot in the branch creation you have no choice but to
5316/// call SetBranchStatus explicitly for each of the sub branches.
5317///
5318/// An alternative is to call directly
5319/// ~~~ {.cpp}
5320/// brancha.GetEntry(i)
5321/// branchb.GetEntry(i);
5322/// ~~~
5323/// ## IMPORTANT NOTE
5324///
5325/// By default, GetEntry reuses the space allocated by the previous object
5326/// for each branch. You can force the previous object to be automatically
5327/// deleted if you call mybranch.SetAutoDelete(kTRUE) (default is kFALSE).
5328///
5329/// Example:
5330///
5331/// Consider the example in $ROOTSYS/test/Event.h
5332/// The top level branch in the tree T is declared with:
5333/// ~~~ {.cpp}
5334/// Event *event = 0; //event must be null or point to a valid object
5335/// //it must be initialized
5336/// T.SetBranchAddress("event",&event);
5337/// ~~~
5338/// When reading the Tree, one can choose one of these 3 options:
5339///
5340/// ## OPTION 1
5341///
5342/// ~~~ {.cpp}
5343/// for (Long64_t i=0;i<nentries;i++) {
5344/// T.GetEntry(i);
5345/// // the object event has been filled at this point
5346/// }
5347/// ~~~
5348/// The default (recommended). At the first entry an object of the class
5349/// Event will be created and pointed by event. At the following entries,
5350/// event will be overwritten by the new data. All internal members that are
5351/// TObject* are automatically deleted. It is important that these members
5352/// be in a valid state when GetEntry is called. Pointers must be correctly
5353/// initialized. However these internal members will not be deleted if the
5354/// characters "->" are specified as the first characters in the comment
5355/// field of the data member declaration.
5356///
5357/// If "->" is specified, the pointer member is read via pointer->Streamer(buf).
5358/// In this case, it is assumed that the pointer is never null (case of
5359/// pointer TClonesArray *fTracks in the Event example). If "->" is not
5360/// specified, the pointer member is read via buf >> pointer. In this case
5361/// the pointer may be null. Note that the option with "->" is faster to
5362/// read or write and it also consumes less space in the file.
5363///
5364/// ## OPTION 2
5365///
5366/// The option AutoDelete is set
5367/// ~~~ {.cpp}
5368/// TBranch *branch = T.GetBranch("event");
5369/// branch->SetAddress(&event);
5370/// branch->SetAutoDelete(kTRUE);
5371/// for (Long64_t i=0;i<nentries;i++) {
5372/// T.GetEntry(i);
5373/// // the object event has been filled at this point
5374/// }
5375/// ~~~
5376/// In this case, at each iteration, the object event is deleted by GetEntry
5377/// and a new instance of Event is created and filled.
5378///
5379/// ## OPTION 3
5380/// ~~~ {.cpp}
5381/// Same as option 1, but you delete yourself the event.
5382///
5383/// for (Long64_t i=0;i<nentries;i++) {
5384/// delete event;
5385/// event = 0; // EXTREMELY IMPORTANT
5386/// T.GetEntry(i);
5387/// // the object event has been filled at this point
5388/// }
5389/// ~~~
5390/// It is strongly recommended to use the default option 1. It has the
5391/// additional advantage that functions like TTree::Draw (internally calling
5392/// TTree::GetEntry) will be functional even when the classes in the file are
5393/// not available.
5394///
5395/// Note: See the comments in TBranchElement::SetAddress() for the
5396/// object ownership policy of the underlying (user) data.
5398Int_t TTree::GetEntry(Long64_t entry, Int_t getall)
5399{
5400
5401 // We already have been visited while recursively looking
5402 // through the friends tree, let return
5403 if (kGetEntry & fFriendLockStatus) return 0;
5404
5405 if (entry < 0 || entry >= fEntries) return 0;
5406 Int_t i;
5407 Int_t nbytes = 0;
5408 fReadEntry = entry;
5409
5410 // create cache if wanted
5411 if (fCacheDoAutoInit)
5413
5414 Int_t nbranches = fBranches.GetEntriesFast();
5415 Int_t nb=0;
5416
5417 auto seqprocessing = [&]() {
5418 TBranch *branch;
5419 for (i=0;i<nbranches;i++) {
5420 branch = (TBranch*)fBranches.UncheckedAt(i);
5421 nb = branch->GetEntry(entry, getall);
5422 if (nb < 0) break;
5423 nbytes += nb;
5424 }
5425 };
5426
5427#ifdef R__USE_IMT
5428 const auto nBranches = GetListOfBranches()->GetEntries();
5430 if (fSortedBranches.empty())
5432
5433 // Count branches are processed first and sequentially
5434 for (auto branch : fSeqBranches) {
5435 nb = branch->GetEntry(entry, getall);
5436 if (nb < 0) break;
5437 nbytes += nb;
5438 }
5439 if (nb < 0) return nb;
5440
5441 // Enable this IMT use case (activate its locks)
5443
5444 Int_t errnb = 0;
5445 std::atomic<Int_t> pos(0);
5446 std::atomic<Int_t> nbpar(0);
5447
5448 auto mapFunction = [&]() {
5449 // The branch to process is obtained when the task starts to run.
5450 // This way, since branches are sorted, we make sure that branches
5451 // leading to big tasks are processed first. If we assigned the
5452 // branch at task creation time, the scheduler would not necessarily
5453 // respect our sorting.
5454 Int_t j = pos.fetch_add(1);
5455
5456 Int_t nbtask = 0;
5457 auto branch = fSortedBranches[j].second;
5458
5459 if (gDebug > 0) {
5460 std::stringstream ss;
5461 ss << std::this_thread::get_id();
5462 Info("GetEntry", "[IMT] Thread %s", ss.str().c_str());
5463 Info("GetEntry", "[IMT] Running task for branch #%d: %s", j, branch->GetName());
5464 }
5465
5466 std::chrono::time_point<std::chrono::system_clock> start, end;
5467
5468 start = std::chrono::system_clock::now();
5469 nbtask = branch->GetEntry(entry, getall);
5470 end = std::chrono::system_clock::now();
5471
5472 Long64_t tasktime = (Long64_t)std::chrono::duration_cast<std::chrono::microseconds>(end - start).count();
5473 fSortedBranches[j].first += tasktime;
5474
5475 if (nbtask < 0) errnb = nbtask;
5476 else nbpar += nbtask;
5477 };
5478
5480 pool.Foreach(mapFunction, fSortedBranches.size());
5481
5482 if (errnb < 0) {
5483 nb = errnb;
5484 }
5485 else {
5486 // Save the number of bytes read by the tasks
5487 nbytes += nbpar;
5488
5489 // Re-sort branches if necessary
5493 }
5494 }
5495 }
5496 else {
5497 seqprocessing();
5498 }
5499#else
5500 seqprocessing();
5501#endif
5502 if (nb < 0) return nb;
5503
5504 // GetEntry in list of friends
5505 if (!fFriends) return nbytes;
5506 TFriendLock lock(this,kGetEntry);
5507 TIter nextf(fFriends);
5508 TFriendElement *fe;
5509 while ((fe = (TFriendElement*)nextf())) {
5510 TTree *t = fe->GetTree();
5511 if (t) {
5513 nb = t->GetEntry(t->GetReadEntry(),getall);
5514 } else {
5515 if ( t->LoadTreeFriend(entry,this) >= 0 ) {
5516 nb = t->GetEntry(t->GetReadEntry(),getall);
5517 } else nb = 0;
5518 }
5519 if (nb < 0) return nb;
5520 nbytes += nb;
5521 }
5522 }
5523 return nbytes;
5524}
5525
5526
5527////////////////////////////////////////////////////////////////////////////////
5528/// Divides the top-level branches into two vectors: (i) branches to be
5529/// processed sequentially and (ii) branches to be processed in parallel.
5530/// Even if IMT is on, some branches might need to be processed first and in a
5531/// sequential fashion: in the parallelization of GetEntry, those are the
5532/// branches that store the size of another branch for every entry
5533/// (e.g. the size of an array branch). If such branches were processed
5534/// in parallel with the rest, there could be two threads invoking
5535/// TBranch::GetEntry on one of them at the same time, since a branch that
5536/// depends on a size (or count) branch will also invoke GetEntry on the latter.
5537/// This method can be invoked several times during the event loop if the TTree
5538/// is being written, for example when adding new branches. In these cases, the
5539/// `checkLeafCount` parameter is false.
5540/// \param[in] checkLeafCount True if we need to check whether some branches are
5541/// count leaves.
5543void TTree::InitializeBranchLists(bool checkLeafCount)
5544{
5545 Int_t nbranches = fBranches.GetEntriesFast();
5546
5547 // The special branch fBranchRef needs to be processed sequentially:
5548 // we add it once only.
5549 if (fBranchRef && fBranchRef != fSeqBranches[0]) {
5550 fSeqBranches.push_back(fBranchRef);
5551 }
5552
5553 // The branches to be processed sequentially are those that are the leaf count of another branch
5554 if (checkLeafCount) {
5555 for (Int_t i = 0; i < nbranches; i++) {
5556 TBranch* branch = (TBranch*)fBranches.UncheckedAt(i);
5557 auto leafCount = ((TLeaf*)branch->GetListOfLeaves()->At(0))->GetLeafCount();
5558 if (leafCount) {
5559 auto countBranch = leafCount->GetBranch();
5560 if (std::find(fSeqBranches.begin(), fSeqBranches.end(), countBranch) == fSeqBranches.end()) {
5561 fSeqBranches.push_back(countBranch);
5562 }
5563 }
5564 }
5565 }
5566
5567 // Any branch that is not a leaf count can be safely processed in parallel when reading
5568 // We need to reset the vector to make sure we do not re-add several times the same branch.
5569 if (!checkLeafCount) {
5570 fSortedBranches.clear();
5571 }
5572 for (Int_t i = 0; i < nbranches; i++) {
5573 Long64_t bbytes = 0;
5574 TBranch* branch = (TBranch*)fBranches.UncheckedAt(i);
5575 if (std::find(fSeqBranches.begin(), fSeqBranches.end(), branch) == fSeqBranches.end()) {
5576 bbytes = branch->GetTotBytes("*");
5577 fSortedBranches.emplace_back(bbytes, branch);
5578 }
5579 }
5580
5581 // Initially sort parallel branches by size
5582 std::sort(fSortedBranches.begin(),
5583 fSortedBranches.end(),
5584 [](std::pair<Long64_t,TBranch*> a, std::pair<Long64_t,TBranch*> b) {
5585 return a.first > b.first;
5586 });
5587
5588 for (size_t i = 0; i < fSortedBranches.size(); i++) {
5589 fSortedBranches[i].first = 0LL;
5590 }
5591}
5592
5593////////////////////////////////////////////////////////////////////////////////
5594/// Sorts top-level branches by the last average task time recorded per branch.
5597{
5598 for (size_t i = 0; i < fSortedBranches.size(); i++) {
5600 }
5601
5602 std::sort(fSortedBranches.begin(),
5603 fSortedBranches.end(),
5604 [](std::pair<Long64_t,TBranch*> a, std::pair<Long64_t,TBranch*> b) {
5605 return a.first > b.first;
5606 });
5607
5608 for (size_t i = 0; i < fSortedBranches.size(); i++) {
5609 fSortedBranches[i].first = 0LL;
5610 }
5611}
5612
5613////////////////////////////////////////////////////////////////////////////////
5614///Returns the entry list, set to this tree
5617{
5618 return fEntryList;
5619}
5620
5621////////////////////////////////////////////////////////////////////////////////
5622/// Return entry number corresponding to entry.
5623///
5624/// if no TEntryList set returns entry
5625/// else returns the entry number corresponding to the list index=entry
5628{
5629 if (!fEntryList) {
5630 return entry;
5631 }
5632
5633 return fEntryList->GetEntry(entry);
5634}
5635
5636////////////////////////////////////////////////////////////////////////////////
5637/// Return entry number corresponding to major and minor number.
5638/// Note that this function returns only the entry number, not the data
5639/// To read the data corresponding to an entry number, use TTree::GetEntryWithIndex
5640/// the BuildIndex function has created a table of Long64_t* of sorted values
5641/// corresponding to val = major<<31 + minor;
5642/// The function performs binary search in this sorted table.
5643/// If it finds a pair that matches val, it returns directly the
5644/// index in the table.
5645/// If an entry corresponding to major and minor is not found, the function
5646/// returns the index of the major,minor pair immediately lower than the
5647/// requested value, ie it will return -1 if the pair is lower than
5648/// the first entry in the index.
5649///
5650/// See also GetEntryNumberWithIndex
5653{
5654 if (!fTreeIndex) {
5655 return -1;
5656 }
5657 return fTreeIndex->GetEntryNumberWithBestIndex(major, minor);
5658}
5659
5660////////////////////////////////////////////////////////////////////////////////
5661/// Return entry number corresponding to major and minor number.
5662/// Note that this function returns only the entry number, not the data
5663/// To read the data corresponding to an entry number, use TTree::GetEntryWithIndex
5664/// the BuildIndex function has created a table of Long64_t* of sorted values
5665/// corresponding to val = major<<31 + minor;
5666/// The function performs binary search in this sorted table.
5667/// If it finds a pair that matches val, it returns directly the
5668/// index in the table, otherwise it returns -1.
5669///
5670/// See also GetEntryNumberWithBestIndex
5673{
5674 if (!fTreeIndex) {
5675 return -1;
5676 }
5677 return fTreeIndex->GetEntryNumberWithIndex(major, minor);
5678}
5679
5680////////////////////////////////////////////////////////////////////////////////
5681/// Read entry corresponding to major and minor number.
5682///
5683/// The function returns the total number of bytes read.
5684/// If the Tree has friend trees, the corresponding entry with
5685/// the index values (major,minor) is read. Note that the master Tree
5686/// and its friend may have different entry serial numbers corresponding
5687/// to (major,minor).
5690{
5691 // We already have been visited while recursively looking
5692 // through the friends tree, let's return.
5694 return 0;
5695 }
5696 Long64_t serial = GetEntryNumberWithIndex(major, minor);
5697 if (serial < 0) {
5698 return -1;
5699 }
5700 // create cache if wanted
5701 if (fCacheDoAutoInit)
5703
5704 Int_t i;
5705 Int_t nbytes = 0;
5706 fReadEntry = serial;
5707 TBranch *branch;
5708 Int_t nbranches = fBranches.GetEntriesFast();
5709 Int_t nb;
5710 for (i = 0; i < nbranches; ++i) {
5711 branch = (TBranch*)fBranches.UncheckedAt(i);
5712 nb = branch->GetEntry(serial);
5713 if (nb < 0) return nb;
5714 nbytes += nb;
5715 }
5716 // GetEntry in list of friends
5717 if (!fFriends) return nbytes;
5719 TIter nextf(fFriends);
5720 TFriendElement* fe = 0;
5721 while ((fe = (TFriendElement*) nextf())) {
5722 TTree *t = fe->GetTree();
5723 if (t) {
5724 serial = t->GetEntryNumberWithIndex(major,minor);
5725 if (serial <0) return -nbytes;
5726 nb = t->GetEntry(serial);
5727 if (nb < 0) return nb;
5728 nbytes += nb;
5729 }
5730 }
5731 return nbytes;
5732}
5733
5734////////////////////////////////////////////////////////////////////////////////
5735/// Return a pointer to the TTree friend whose name or alias is 'friendname.
5737TTree* TTree::GetFriend(const char *friendname) const
5738{
5739
5740 // We already have been visited while recursively
5741 // looking through the friends tree, let's return.
5743 return 0;
5744 }
5745 if (!fFriends) {
5746 return 0;
5747 }
5748 TFriendLock lock(const_cast<TTree*>(this), kGetFriend);
5749 TIter nextf(fFriends);
5750 TFriendElement* fe = 0;
5751 while ((fe = (TFriendElement*) nextf())) {
5752 if (strcmp(friendname,fe->GetName())==0
5753 || strcmp(friendname,fe->GetTreeName())==0) {
5754 return fe->GetTree();
5755 }
5756 }
5757 // After looking at the first level,
5758 // let's see if it is a friend of friends.
5759 nextf.Reset();
5760 fe = 0;
5761 while ((fe = (TFriendElement*) nextf())) {
5762 TTree *res = fe->GetTree()->GetFriend(friendname);
5763 if (res) {
5764 return res;
5765 }
5766 }
5767 return 0;
5768}
5769
5770////////////////////////////////////////////////////////////////////////////////
5771/// If the 'tree' is a friend, this method returns its alias name.
5772///
5773/// This alias is an alternate name for the tree.
5774///
5775/// It can be used in conjunction with a branch or leaf name in a TTreeFormula,
5776/// to specify in which particular tree the branch or leaf can be found if
5777/// the friend trees have branches or leaves with the same name as the master
5778/// tree.
5779///
5780/// It can also be used in conjunction with an alias created using
5781/// TTree::SetAlias in a TTreeFormula, e.g.:
5782/// ~~~ {.cpp}
5783/// maintree->Draw("treealias.fPx - treealias.myAlias");
5784/// ~~~
5785/// where fPx is a branch of the friend tree aliased as 'treealias' and 'myAlias'
5786/// was created using TTree::SetAlias on the friend tree.
5787///
5788/// However, note that 'treealias.myAlias' will be expanded literally,
5789/// without remembering that it comes from the aliased friend and thus
5790/// the branch name might not be disambiguated properly, which means
5791/// that you may not be able to take advantage of this feature.
5792///
5794const char* TTree::GetFriendAlias(TTree* tree) const
5795{
5796 if ((tree == this) || (tree == GetTree())) {
5797 return 0;
5798 }
5799
5800 // We already have been visited while recursively
5801 // looking through the friends tree, let's return.
5803 return 0;
5804 }
5805 if (!fFriends) {
5806 return 0;
5807 }
5808 TFriendLock lock(const_cast<TTree*>(this), kGetFriendAlias);
5809 TIter nextf(fFriends);
5810 TFriendElement* fe = 0;
5811 while ((fe = (TFriendElement*) nextf())) {
5812 TTree* t = fe->GetTree();
5813 if (t == tree) {
5814 return fe->GetName();
5815 }
5816 // Case of a chain:
5817 if (t && t->GetTree() == tree) {
5818 return fe->GetName();
5819 }
5820 }
5821 // After looking at the first level,
5822 // let's see if it is a friend of friends.
5823 nextf.Reset();
5824 fe = 0;
5825 while ((fe = (TFriendElement*) nextf())) {
5826 const char* res = fe->GetTree()->GetFriendAlias(tree);
5827 if (res) {
5828 return res;
5829 }
5830 }
5831 return 0;
5832}
5833
5834////////////////////////////////////////////////////////////////////////////////
5835/// Returns the current set of IO settings
5837{
5838 return fIOFeatures;
5839}
5840
5841////////////////////////////////////////////////////////////////////////////////
5842/// Creates a new iterator that will go through all the leaves on the tree itself and its friend.
5845{
5846 return new TTreeFriendLeafIter(this, dir);
5847}
5848
5849////////////////////////////////////////////////////////////////////////////////
5850/// Return pointer to the 1st Leaf named name in any Branch of this
5851/// Tree or any branch in the list of friend trees.
5852///
5853/// The leaf name can contain the name of a friend tree with the
5854/// syntax: friend_dir_and_tree.full_leaf_name
5855/// the friend_dir_and_tree can be of the form:
5856/// ~~~ {.cpp}
5857/// TDirectoryName/TreeName
5858/// ~~~
5860TLeaf* TTree::GetLeafImpl(const char* branchname, const char *leafname)
5861{
5862 TLeaf *leaf = 0;
5863 if (branchname) {
5864 TBranch *branch = FindBranch(branchname);
5865 if (branch) {
5866 leaf = branch->GetLeaf(leafname);
5867 if (leaf) {
5868 return leaf;
5869 }
5870 }
5871 }
5872 TIter nextl(GetListOfLeaves());
5873 while ((leaf = (TLeaf*)nextl())) {
5874 if (strcmp(leaf->GetName(),leafname)) continue;
5875 if (branchname) {
5876 UInt_t nbch = strlen(branchname);
5877 TBranch *br = leaf->GetBranch();
5878 const char* brname = br->GetName();
5879 TBranch *mother = br->GetMother();
5880 if (strncmp(brname,branchname,nbch)) {
5881 if (mother != br) {
5882 const char *mothername = mother->GetName();
5883 UInt_t motherlen = strlen(mothername);
5884 if (nbch > motherlen && strncmp(mothername,branchname,motherlen)==0 && (mothername[motherlen-1]=='.' || branchname[motherlen]=='.')) {
5885 // 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.
5886 if (strncmp(brname,branchname+motherlen+1,nbch-motherlen-1)) {
5887 // No it does not
5888 continue;
5889 } // else we have match so we can proceed.
5890 } else {
5891 // no match
5892 continue;
5893 }
5894 } else {
5895 continue;
5896 }
5897 }
5898 // The start of the branch name is identical to the content
5899 // of 'aname' before the first '/'.
5900 // Let's make sure that it is not longer (we are trying
5901 // to avoid having jet2/value match the branch jet23
5902 if ((strlen(brname) > nbch) && (brname[nbch] != '.') && (brname[nbch] != '[')) {
5903 continue;
5904 }
5905 }
5906 return leaf;
5907 }
5908 if (!fFriends) return 0;
5909 TFriendLock lock(this,kGetLeaf);
5910 TIter next(fFriends);
5911 TFriendElement *fe;
5912 while ((fe = (TFriendElement*)next())) {
5913 TTree *t = fe->GetTree();
5914 if (t) {
5915 leaf = t->GetLeaf(leafname);
5916 if (leaf) return leaf;
5917 }
5918 }
5919
5920 //second pass in the list of friends when the leaf name
5921 //is prefixed by the tree name
5922 TString strippedArg;
5923 next.Reset();
5924 while ((fe = (TFriendElement*)next())) {
5925 TTree *t = fe->GetTree();
5926 if (t==0) continue;
5927 char *subname = (char*)strstr(leafname,fe->GetName());
5928 if (subname != leafname) continue;
5929 Int_t l = strlen(fe->GetName());
5930 subname += l;
5931 if (*subname != '.') continue;
5932 subname++;
5933 strippedArg += subname;
5934 leaf = t->GetLeaf(branchname,subname);
5935 if (leaf) return leaf;
5936 }
5937 return 0;
5938}
5939
5940////////////////////////////////////////////////////////////////////////////////
5941/// Return pointer to the 1st Leaf named name in any Branch of this
5942/// Tree or any branch in the list of friend trees.
5943///
5944/// The leaf name can contain the name of a friend tree with the
5945/// syntax: friend_dir_and_tree.full_leaf_name
5946/// the friend_dir_and_tree can be of the form:
5947///
5948/// TDirectoryName/TreeName
5950TLeaf* TTree::GetLeaf(const char* branchname, const char *leafname)
5951{
5952 if (leafname == 0) return 0;
5953
5954 // We already have been visited while recursively looking
5955 // through the friends tree, let return
5957 return 0;
5958 }
5959
5960 return GetLeafImpl(branchname,leafname);
5961}
5962
5963////////////////////////////////////////////////////////////////////////////////
5964/// Return pointer to first leaf named \param[name] in any branch of this
5965/// tree or its friend trees.
5966///
5967/// \param[name] may be in the form 'branch/leaf'
5968///
5970TLeaf* TTree::GetLeaf(const char *name)
5971{
5972 // Return nullptr if name is invalid or if we have
5973 // already been visited while searching friend trees
5974 if (!name || (kGetLeaf & fFriendLockStatus))
5975 return nullptr;
5976
5977 std::string path(name);
5978 const auto sep = path.find_last_of("/");
5979 if (sep != std::string::npos)
5980 return GetLeafImpl(path.substr(0, sep).c_str(), name+sep+1);
5981
5982 return GetLeafImpl(nullptr, name);
5983}
5984
5985////////////////////////////////////////////////////////////////////////////////
5986/// Return maximum of column with name columname.
5987/// if the Tree has an associated TEventList or TEntryList, the maximum
5988/// is computed for the entries in this list.
5990Double_t TTree::GetMaximum(const char* columname)
5991{
5992 TLeaf* leaf = this->GetLeaf(columname);
5993 if (!leaf) {
5994 return 0;
5995 }
5996
5997 // create cache if wanted
5998 if (fCacheDoAutoInit)
6000
6001 TBranch* branch = leaf->GetBranch();
6002 Double_t cmax = -DBL_MAX;
6003 for (Long64_t i = 0; i < fEntries; ++i) {
6004 Long64_t entryNumber = this->GetEntryNumber(i);
6005 if (entryNumber < 0) break;
6006 branch->GetEntry(entryNumber);
6007 for (Int_t j = 0; j < leaf->GetLen(); ++j) {
6008 Double_t val = leaf->GetValue(j);
6009 if (val > cmax) {
6010 cmax = val;
6011 }
6012 }
6013 }
6014 return cmax;
6015}
6016
6017////////////////////////////////////////////////////////////////////////////////
6018/// Static function which returns the tree file size limit in bytes.
6021{
6022 return fgMaxTreeSize;
6023}
6024
6025////////////////////////////////////////////////////////////////////////////////
6026/// Return minimum of column with name columname.
6027/// if the Tree has an associated TEventList or TEntryList, the minimum
6028/// is computed for the entries in this list.
6030Double_t TTree::GetMinimum(const char* columname)
6031{
6032 TLeaf* leaf = this->GetLeaf(columname);
6033 if (!leaf) {
6034 return 0;
6035 }
6036
6037 // create cache if wanted
6038 if (fCacheDoAutoInit)
6040
6041 TBranch* branch = leaf->GetBranch();
6042 Double_t cmin = DBL_MAX;
6043 for (Long64_t i = 0; i < fEntries; ++i) {
6044 Long64_t entryNumber = this->GetEntryNumber(i);
6045 if (entryNumber < 0) break;
6046 branch->GetEntry(entryNumber);
6047 for (Int_t j = 0;j < leaf->GetLen(); ++j) {
6048 Double_t val = leaf->GetValue(j);
6049 if (val < cmin) {
6050 cmin = val;
6051 }
6052 }
6053 }
6054 return cmin;
6055}
6056
6057////////////////////////////////////////////////////////////////////////////////
6058/// Load the TTreePlayer (if not already done).
6061{
6062 if (fPlayer) {
6063 return fPlayer;
6064 }
6066 return fPlayer;
6067}
6068
6069////////////////////////////////////////////////////////////////////////////////
6070/// Find and return the TTreeCache registered with the file and which may
6071/// contain branches for us.
6074{
6075 TTreeCache *pe = dynamic_cast<TTreeCache*>(file->GetCacheRead(this));
6076 if (pe && pe->GetTree() != this)
6077 pe = nullptr;
6078 return pe;
6079}
6080
6081////////////////////////////////////////////////////////////////////////////////
6082/// Find and return the TTreeCache registered with the file and which may
6083/// contain branches for us. If create is true and there is no cache
6084/// a new cache is created with default size.
6087{
6089 if (create && !pe) {
6090 if (fCacheDoAutoInit)
6092 pe = dynamic_cast<TTreeCache*>(file->GetCacheRead(this));
6093 if (pe && pe->GetTree() != this) pe = 0;
6094 }
6095 return pe;
6096}
6097
6098////////////////////////////////////////////////////////////////////////////////
6099/// Return a pointer to the list containing user objects associated to this tree.
6100///
6101/// The list is automatically created if it does not exist.
6102///
6103/// WARNING: By default the TTree destructor will delete all objects added
6104/// to this list. If you do not want these objects to be deleted,
6105/// call:
6106///
6107/// mytree->GetUserInfo()->Clear();
6108///
6109/// before deleting the tree.
6112{
6113 if (!fUserInfo) {
6114 fUserInfo = new TList();
6115 fUserInfo->SetName("UserInfo");
6116 }
6117 return fUserInfo;
6118}
6119
6120////////////////////////////////////////////////////////////////////////////////
6121/// Appends the cluster range information stored in 'fromtree' to this tree,
6122/// including the value of fAutoFlush.
6123///
6124/// This is used when doing a fast cloning (by TTreeCloner).
6125/// See also fAutoFlush and fAutoSave if needed.
6127void TTree::ImportClusterRanges(TTree *fromtree)
6128{
6129 Long64_t autoflush = fromtree->GetAutoFlush();
6130 if (fromtree->fNClusterRange == 0 && fromtree->fAutoFlush == fAutoFlush) {
6131 // nothing to do
6132 } else if (fNClusterRange || fromtree->fNClusterRange) {
6133 Int_t newsize = fNClusterRange + 1 + fromtree->fNClusterRange;
6134 if (newsize > fMaxClusterRange) {
6135 if (fMaxClusterRange) {
6137 newsize*sizeof(Long64_t),fMaxClusterRange*sizeof(Long64_t));
6139 newsize*sizeof(Long64_t),fMaxClusterRange*sizeof(Long64_t));
6140 fMaxClusterRange = newsize;
6141 } else {
6142 fMaxClusterRange = newsize;
6145 }
6146 }
6147 if (fEntries) {
6151 }
6152 for (Int_t i = 0 ; i < fromtree->fNClusterRange; ++i) {
6156 }
6157 fAutoFlush = autoflush;
6158 } else {
6159 SetAutoFlush( autoflush );
6160 }
6161 Long64_t autosave = GetAutoSave();
6162 if (autoflush > 0 && autosave > 0) {
6163 SetAutoSave( autoflush*(autosave/autoflush) );
6164 }
6165}
6166
6167////////////////////////////////////////////////////////////////////////////////
6168/// Keep a maximum of fMaxEntries in memory.
6171{
6173 Long64_t maxEntries = fMaxEntries - (fMaxEntries / 10);
6174 for (Int_t i = 0; i < nb; ++i) {
6175 TBranch* branch = (TBranch*) fBranches.UncheckedAt(i);
6176 branch->KeepCircular(maxEntries);
6177 }
6178 if (fNClusterRange) {
6179 Long64_t entriesOffset = fEntries - maxEntries;
6180 Int_t oldsize = fNClusterRange;
6181 for(Int_t i = 0, j = 0; j < oldsize; ++j) {
6182 if (fClusterRangeEnd[j] > entriesOffset) {
6183 fClusterRangeEnd[i] = fClusterRangeEnd[j] - entriesOffset;
6184 ++i;
6185 } else {
6187 }
6188 }
6189 }
6190 fEntries = maxEntries;
6191 fReadEntry = -1;
6192}
6193
6194////////////////////////////////////////////////////////////////////////////////
6195/// Read in memory all baskets from all branches up to the limit of maxmemory bytes.
6196///
6197/// If maxmemory is non null and positive SetMaxVirtualSize is called
6198/// with this value. Default for maxmemory is 2000000000 (2 Gigabytes).
6199/// The function returns the total number of baskets read into memory
6200/// if negative an error occurred while loading the branches.
6201/// This method may be called to force branch baskets in memory
6202/// when random access to branch entries is required.
6203/// If random access to only a few branches is required, you should
6204/// call directly TBranch::LoadBaskets.
6207{
6208 if (maxmemory > 0) SetMaxVirtualSize(maxmemory);
6209
6210 TIter next(GetListOfLeaves());
6211 TLeaf *leaf;
6212 Int_t nimported = 0;
6213 while ((leaf=(TLeaf*)next())) {
6214 nimported += leaf->GetBranch()->LoadBaskets();//break;
6215 }
6216 return nimported;
6217}
6218
6219////////////////////////////////////////////////////////////////////////////////
6220/// Set current entry.
6221///
6222/// Returns -2 if entry does not exist (just as TChain::LoadTree()).
6223///
6224/// Note: This function is overloaded in TChain.
6225///
6228{
6229 // We already have been visited while recursively looking
6230 // through the friends tree, let return
6232 // We need to return a negative value to avoid a circular list of friend
6233 // to think that there is always an entry somewhere in the list.
6234 return -1;
6235 }
6236
6237 // create cache if wanted
6238 if (fCacheDoAutoInit && entry >=0)
6240
6241 if (fNotify) {
6242 if (fReadEntry < 0) {
6243 fNotify->Notify();
6244 }
6245 }
6246 fReadEntry = entry;
6247
6248 Bool_t friendHasEntry = kFALSE;
6249 if (fFriends) {
6250 // Set current entry in friends as well.
6251 //
6252 // An alternative would move this code to each of the
6253 // functions calling LoadTree (and to overload a few more).
6254 Bool_t needUpdate = kFALSE;
6255 {
6256 // This scope is need to insure the lock is released at the right time
6257 TIter nextf(fFriends);
6258 TFriendLock lock(this, kLoadTree);
6259 TFriendElement* fe = 0;
6260 while ((fe = (TFriendElement*) nextf())) {
6262 // This friend element was added by the chain that owns this
6263 // tree, the chain will deal with loading the correct entry.
6264 continue;
6265 }
6266 TTree* friendTree = fe->GetTree();
6267 if (friendTree == 0) {
6268 // Somehow we failed to retrieve the friend TTree.
6269 } else if (friendTree->IsA() == TTree::Class()) {
6270 // Friend is actually a tree.
6271 if (friendTree->LoadTreeFriend(entry, this) >= 0) {
6272 friendHasEntry = kTRUE;
6273 }
6274 } else {
6275 // Friend is actually a chain.
6276 // FIXME: This logic should be in the TChain override.
6277 Int_t oldNumber = friendTree->GetTreeNumber();
6278 if (friendTree->LoadTreeFriend(entry, this) >= 0) {
6279 friendHasEntry = kTRUE;
6280 }
6281 Int_t newNumber = friendTree->GetTreeNumber();
6282 if (oldNumber != newNumber) {
6283 // We can not just compare the tree pointers because they could be reused.
6284 // So we compare the tree number instead.
6285 needUpdate = kTRUE;
6286 }
6287 }
6288 } // for each friend
6289 }
6290 if (needUpdate) {
6291 //update list of leaves in all TTreeFormula of the TTreePlayer (if any)
6292 if (fPlayer) {
6294 }
6295 //Notify user if requested
6296 if (fNotify) {
6297 fNotify->Notify();
6298 }
6299 }
6300 }
6301
6302 if ((fReadEntry >= fEntries) && !friendHasEntry) {
6303 fReadEntry = -1;
6304 return -2;
6305 }
6306 return fReadEntry;
6307}
6308
6309////////////////////////////////////////////////////////////////////////////////
6310/// Load entry on behalf of our master tree, we may use an index.
6311///
6312/// Called by LoadTree() when the masterTree looks for the entry
6313/// number in a friend tree (us) corresponding to the passed entry
6314/// number in the masterTree.
6315///
6316/// If we have no index, our entry number and the masterTree entry
6317/// number are the same.
6318///
6319/// If we *do* have an index, we must find the (major, minor) value pair
6320/// in masterTree to locate our corresponding entry.
6321///
6323Long64_t TTree::LoadTreeFriend(Long64_t entry, TTree* masterTree)
6324{
6325 if (!fTreeIndex) {
6326 return LoadTree(entry);
6327 }
6328 return LoadTree(fTreeIndex->GetEntryNumberFriend(masterTree));
6329}
6330
6331////////////////////////////////////////////////////////////////////////////////
6332/// Generate a skeleton analysis class for this tree.
6333///
6334/// The following files are produced: classname.h and classname.C.
6335/// If classname is 0, classname will be called "nameoftree".
6336///
6337/// The generated code in classname.h includes the following:
6338///
6339/// - Identification of the original tree and the input file name.
6340/// - Definition of an analysis class (data members and member functions).
6341/// - The following member functions:
6342/// - constructor (by default opening the tree file),
6343/// - GetEntry(Long64_t entry),
6344/// - Init(TTree* tree) to initialize a new TTree,
6345/// - Show(Long64_t entry) to read and dump entry.
6346///
6347/// The generated code in classname.C includes only the main
6348/// analysis function Loop.
6349///
6350/// To use this function:
6351///
6352/// - Open your tree file (eg: TFile f("myfile.root");)
6353/// - T->MakeClass("MyClass");
6354///
6355/// where T is the name of the TTree in file myfile.root,
6356/// and MyClass.h, MyClass.C the name of the files created by this function.
6357/// In a ROOT session, you can do:
6358/// ~~~ {.cpp}
6359/// root > .L MyClass.C
6360/// root > MyClass* t = new MyClass;
6361/// root > t->GetEntry(12); // Fill data members of t with entry number 12.
6362/// root > t->Show(); // Show values of entry 12.
6363/// root > t->Show(16); // Read and show values of entry 16.
6364/// root > t->Loop(); // Loop on all entries.
6365/// ~~~
6366/// NOTE: Do not use the code generated for a single TTree which is part
6367/// of a TChain to process that entire TChain. The maximum dimensions
6368/// calculated for arrays on the basis of a single TTree from the TChain
6369/// might be (will be!) too small when processing all of the TTrees in
6370/// the TChain. You must use myChain.MakeClass() to generate the code,
6371/// not myTree.MakeClass(...).
6373Int_t TTree::MakeClass(const char* classname, Option_t* option)
6374{
6375 GetPlayer();
6376 if (!fPlayer) {
6377 return 0;
6378 }
6379 return fPlayer->MakeClass(classname, option);
6380}
6381
6382////////////////////////////////////////////////////////////////////////////////
6383/// Generate a skeleton function for this tree.
6384///
6385/// The function code is written on filename.
6386/// If filename is 0, filename will be called nameoftree.C
6387///
6388/// The generated code includes the following:
6389/// - Identification of the original Tree and Input file name,
6390/// - Opening the Tree file,
6391/// - Declaration of Tree variables,
6392/// - Setting of branches addresses,
6393/// - A skeleton for the entry loop.
6394///
6395/// To use this function:
6396///
6397/// - Open your Tree file (eg: TFile f("myfile.root");)
6398/// - T->MakeCode("MyAnalysis.C");
6399///
6400/// where T is the name of the TTree in file myfile.root
6401/// and MyAnalysis.C the name of the file created by this function.
6402///
6403/// NOTE: Since the implementation of this function, a new and better
6404/// function TTree::MakeClass() has been developed.
6406Int_t TTree::MakeCode(const char* filename)
6407{
6408 Warning("MakeCode", "MakeCode is obsolete. Use MakeClass or MakeSelector instead");
6409
6410 GetPlayer();
6411 if (!fPlayer) return 0;
6412 return fPlayer->MakeCode(filename);
6413}
6414
6415////////////////////////////////////////////////////////////////////////////////
6416/// Generate a skeleton analysis class for this Tree using TBranchProxy.
6417///
6418/// TBranchProxy is the base of a class hierarchy implementing an
6419/// indirect access to the content of the branches of a TTree.
6420///
6421/// "proxyClassname" is expected to be of the form:
6422/// ~~~ {.cpp}
6423/// [path/]fileprefix
6424/// ~~~
6425/// The skeleton will then be generated in the file:
6426/// ~~~ {.cpp}
6427/// fileprefix.h
6428/// ~~~
6429/// located in the current directory or in 'path/' if it is specified.
6430/// The class generated will be named 'fileprefix'
6431///
6432/// "macrofilename" and optionally "cutfilename" are expected to point
6433/// to source files which will be included by the generated skeleton.
6434/// Method of the same name as the file(minus the extension and path)
6435/// will be called by the generated skeleton's Process method as follow:
6436/// ~~~ {.cpp}
6437/// [if (cutfilename())] htemp->Fill(macrofilename());
6438/// ~~~
6439/// "option" can be used select some of the optional features during
6440/// the code generation. The possible options are:
6441///
6442/// - nohist : indicates that the generated ProcessFill should not fill the histogram.
6443///
6444/// 'maxUnrolling' controls how deep in the class hierarchy does the
6445/// system 'unroll' classes that are not split. Unrolling a class
6446/// allows direct access to its data members (this emulates the behavior
6447/// of TTreeFormula).
6448///
6449/// The main features of this skeleton are:
6450///
6451/// * on-demand loading of branches
6452/// * ability to use the 'branchname' as if it was a data member
6453/// * protection against array out-of-bounds errors
6454/// * ability to use the branch data as an object (when the user code is available)
6455///
6456/// For example with Event.root, if
6457/// ~~~ {.cpp}
6458/// Double_t somePx = fTracks.fPx[2];
6459/// ~~~
6460/// is executed by one of the method of the skeleton,
6461/// somePx will updated with the current value of fPx of the 3rd track.
6462///
6463/// Both macrofilename and the optional cutfilename are expected to be
6464/// the name of source files which contain at least a free standing
6465/// function with the signature:
6466/// ~~~ {.cpp}
6467/// x_t macrofilename(); // i.e function with the same name as the file
6468/// ~~~
6469/// and
6470/// ~~~ {.cpp}
6471/// y_t cutfilename(); // i.e function with the same name as the file
6472/// ~~~
6473/// x_t and y_t needs to be types that can convert respectively to a double
6474/// and a bool (because the skeleton uses:
6475///
6476/// if (cutfilename()) htemp->Fill(macrofilename());
6477///
6478/// These two functions are run in a context such that the branch names are
6479/// available as local variables of the correct (read-only) type.
6480///
6481/// Note that if you use the same 'variable' twice, it is more efficient
6482/// to 'cache' the value. For example:
6483/// ~~~ {.cpp}
6484/// Int_t n = fEventNumber; // Read fEventNumber
6485/// if (n<10 || n>10) { ... }
6486/// ~~~
6487/// is more efficient than
6488/// ~~~ {.cpp}
6489/// if (fEventNumber<10 || fEventNumber>10)
6490/// ~~~
6491/// Also, optionally, the generated selector will also call methods named
6492/// macrofilename_methodname in each of 6 main selector methods if the method
6493/// macrofilename_methodname exist (Where macrofilename is stripped of its
6494/// extension).
6495///
6496/// Concretely, with the script named h1analysisProxy.C,
6497///
6498/// - The method calls the method (if it exist)
6499/// - Begin -> void h1analysisProxy_Begin(TTree*);
6500/// - SlaveBegin -> void h1analysisProxy_SlaveBegin(TTree*);
6501/// - Notify -> Bool_t h1analysisProxy_Notify();
6502/// - Process -> Bool_t h1analysisProxy_Process(Long64_t);
6503/// - SlaveTerminate -> void h1analysisProxy_SlaveTerminate();
6504/// - Terminate -> void h1analysisProxy_Terminate();
6505///
6506/// If a file name macrofilename.h (or .hh, .hpp, .hxx, .hPP, .hXX) exist
6507/// it is included before the declaration of the proxy class. This can
6508/// be used in particular to insure that the include files needed by
6509/// the macro file are properly loaded.
6510///
6511/// The default histogram is accessible via the variable named 'htemp'.
6512///
6513/// If the library of the classes describing the data in the branch is
6514/// loaded, the skeleton will add the needed `include` statements and
6515/// give the ability to access the object stored in the branches.
6516///
6517/// To draw px using the file hsimple.root (generated by the
6518/// hsimple.C tutorial), we need a file named hsimple.cxx:
6519/// ~~~ {.cpp}
6520/// double hsimple() {
6521/// return px;
6522/// }
6523/// ~~~
6524/// MakeProxy can then be used indirectly via the TTree::Draw interface
6525/// as follow:
6526/// ~~~ {.cpp}
6527/// new TFile("hsimple.root")
6528/// ntuple->Draw("hsimple.cxx");
6529/// ~~~
6530/// A more complete example is available in the tutorials directory:
6531/// h1analysisProxy.cxx , h1analysProxy.h and h1analysisProxyCut.C
6532/// which reimplement the selector found in h1analysis.C
6534Int_t TTree::MakeProxy(const char* proxyClassname, const char* macrofilename, const char* cutfilename, const char* option, Int_t maxUnrolling)
6535{
6536 GetPlayer();
6537 if (!fPlayer) return 0;
6538 return fPlayer->MakeProxy(proxyClassname,macrofilename,cutfilename,option,maxUnrolling);
6539}
6540
6541////////////////////////////////////////////////////////////////////////////////
6542/// Generate skeleton selector class for this tree.
6543///
6544/// The following files are produced: selector.h and selector.C.
6545/// If selector is 0, the selector will be called "nameoftree".
6546/// The option can be used to specify the branches that will have a data member.
6547/// - If option is "=legacy", a pre-ROOT6 selector will be generated (data
6548/// members and branch pointers instead of TTreeReaders).
6549/// - If option is empty, readers will be generated for each leaf.
6550/// - If option is "@", readers will be generated for the topmost branches.
6551/// - Individual branches can also be picked by their name:
6552/// - "X" generates readers for leaves of X.
6553/// - "@X" generates a reader for X as a whole.
6554/// - "@X;Y" generates a reader for X as a whole and also readers for the
6555/// leaves of Y.
6556/// - For further examples see the figure below.
6557///
6558/// \image html ttree_makeselector_option_examples.png
6559///
6560/// The generated code in selector.h includes the following:
6561/// - Identification of the original Tree and Input file name
6562/// - Definition of selector class (data and functions)
6563/// - The following class functions:
6564/// - constructor and destructor
6565/// - void Begin(TTree *tree)
6566/// - void SlaveBegin(TTree *tree)
6567/// - void Init(TTree *tree)
6568/// - Bool_t Notify()
6569/// - Bool_t Process(Long64_t entry)
6570/// - void Terminate()
6571/// - void SlaveTerminate()
6572///
6573/// The class selector derives from TSelector.
6574/// The generated code in selector.C includes empty functions defined above.
6575///
6576/// To use this function:
6577///
6578/// - connect your Tree file (eg: `TFile f("myfile.root");`)
6579/// - `T->MakeSelector("myselect");`
6580///
6581/// where T is the name of the Tree in file myfile.root
6582/// and myselect.h, myselect.C the name of the files created by this function.
6583/// In a ROOT session, you can do:
6584/// ~~~ {.cpp}
6585/// root > T->Process("myselect.C")
6586/// ~~~
6588Int_t TTree::MakeSelector(const char* selector, Option_t* option)
6589{
6590 TString opt(option);
6591 if(opt.EqualTo("=legacy", TString::ECaseCompare::kIgnoreCase)) {
6592 return MakeClass(selector, "selector");
6593 } else {
6594 GetPlayer();
6595 if (!fPlayer) return 0;
6596 return fPlayer->MakeReader(selector, option);
6597 }
6598}
6599
6600////////////////////////////////////////////////////////////////////////////////
6601/// Check if adding nbytes to memory we are still below MaxVirtualsize.
6604{
6605 if ((fTotalBuffers + nbytes) < fMaxVirtualSize) {
6606 return kFALSE;
6607 }
6608 return kTRUE;
6609}
6610
6611////////////////////////////////////////////////////////////////////////////////
6612/// Static function merging the trees in the TList into a new tree.
6613///
6614/// Trees in the list can be memory or disk-resident trees.
6615/// The new tree is created in the current directory (memory if gROOT).
6617TTree* TTree::MergeTrees(TList* li, Option_t* options)
6618{
6619 if (!li) return 0;
6620 TIter next(li);
6621 TTree *newtree = 0;
6622 TObject *obj;
6623
6624 while ((obj=next())) {
6625 if (!obj->InheritsFrom(TTree::Class())) continue;
6626 TTree *tree = (TTree*)obj;
6627 Long64_t nentries = tree->GetEntries();
6628 if (nentries == 0) continue;
6629 if (!newtree) {
6630 newtree = (TTree*)tree->CloneTree();
6631 if (!newtree) continue;
6632
6633 // Once the cloning is done, separate the trees,
6634 // to avoid as many side-effects as possible
6635 // The list of clones is guaranteed to exist since we
6636 // just cloned the tree.
6637 tree->GetListOfClones()->Remove(newtree);
6638 tree->ResetBranchAddresses();
6639 newtree->ResetBranchAddresses();
6640 continue;
6641 }
6642
6643 newtree->CopyAddresses(tree);
6644
6645 newtree->CopyEntries(tree,-1,options);
6646
6647 tree->ResetBranchAddresses(); // Disconnect from new tree.
6648 }
6649 if (newtree && newtree->GetTreeIndex()) {
6650 newtree->GetTreeIndex()->Append(0,kFALSE); // Force the sorting
6651 }
6652 return newtree;
6653}
6654
6655////////////////////////////////////////////////////////////////////////////////
6656/// Merge the trees in the TList into this tree.
6657///
6658/// Returns the total number of entries in the merged tree.
6661{
6662 if (!li) return 0;
6663 Long64_t storeAutoSave = fAutoSave;
6664 // Disable the autosave as the TFileMerge keeps a list of key and deleting the underlying
6665 // key would invalidate its iteration (or require costly measure to not use the deleted keys).
6666 // Also since this is part of a merging operation, the output file is not as precious as in
6667 // the general case since the input file should still be around.
6668 fAutoSave = 0;
6669 TIter next(li);
6670 TTree *tree;
6671 while ((tree = (TTree*)next())) {
6672 if (tree==this) continue;
6673 if (!tree->InheritsFrom(TTree::Class())) {
6674 Error("Add","Attempt to add object of class: %s to a %s", tree->ClassName(), ClassName());
6675 fAutoSave = storeAutoSave;
6676 return -1;
6677 }
6678
6679 Long64_t nentries = tree->GetEntries();
6680 if (nentries == 0) continue;
6681
6683
6684 CopyEntries(tree,-1,options);
6685
6686 tree->ResetBranchAddresses();
6687 }
6688 fAutoSave = storeAutoSave;
6689 return GetEntries();
6690}
6691
6692////////////////////////////////////////////////////////////////////////////////
6693/// Merge the trees in the TList into this tree.
6694/// If info->fIsFirst is true, first we clone this TTree info the directory
6695/// info->fOutputDirectory and then overlay the new TTree information onto
6696/// this TTree object (so that this TTree object is now the appropriate to
6697/// use for further merging).
6698///
6699/// Returns the total number of entries in the merged tree.
6702{
6703 const char *options = info ? info->fOptions.Data() : "";
6704 if (info && info->fIsFirst && info->fOutputDirectory && info->fOutputDirectory->GetFile() != GetCurrentFile()) {
6706 TIOFeatures saved_features = fIOFeatures;
6707 if (info->fIOFeatures) {
6708 fIOFeatures = *(info->fIOFeatures);
6709 }
6710 TTree *newtree = CloneTree(-1, options);
6711 fIOFeatures = saved_features;
6712 if (newtree) {
6713 newtree->Write();
6714 delete newtree;
6715 }
6716 // Make sure things are really written out to disk before attempting any reading.
6717 info->fOutputDirectory->GetFile()->Flush();
6718 info->fOutputDirectory->ReadTObject(this,this->GetName());
6719 }
6720 if (!li) return 0;
6721 Long64_t storeAutoSave = fAutoSave;
6722 // Disable the autosave as the TFileMerge keeps a list of key and deleting the underlying
6723 // key would invalidate its iteration (or require costly measure to not use the deleted keys).
6724 // Also since this is part of a merging operation, the output file is not as precious as in
6725 // the general case since the input file should still be around.
6726 fAutoSave = 0;
6727 TIter next(li);
6728 TTree *tree;
6729 while ((tree = (TTree*)next())) {
6730 if (tree==this) continue;
6731 if (!tree->InheritsFrom(TTree::Class())) {
6732 Error("Add","Attempt to add object of class: %s to a %s", tree->ClassName(), ClassName());
6733 fAutoSave = storeAutoSave;
6734 return -1;
6735 }
6736 // Copy MakeClass status.
6737 tree->SetMakeClass(fMakeClass);
6738
6739 // Copy branch addresses.
6741
6742 CopyEntries(tree,-1,options);
6743
6744 tree->ResetBranchAddresses();
6745 }
6746 fAutoSave = storeAutoSave;
6747 return GetEntries();
6748}
6749
6750////////////////////////////////////////////////////////////////////////////////
6751/// Move a cache from a file to the current file in dir.
6752/// if src is null no operation is done, if dir is null or there is no
6753/// current file the cache is deleted.
6755void TTree::MoveReadCache(TFile *src, TDirectory *dir)
6756{
6757 if (!src) return;
6758 TFile *dst = (dir && dir != gROOT) ? dir->GetFile() : 0;
6759 if (src == dst) return;
6760
6761 TTreeCache *pf = GetReadCache(src);
6762 if (dst) {
6763 src->SetCacheRead(0,this);
6764 dst->SetCacheRead(pf, this);
6765 } else {
6766 if (pf) {
6767 pf->WaitFinishPrefetch();
6768 }
6769 src->SetCacheRead(0,this);
6770 delete pf;
6771 }
6772}
6773
6774////////////////////////////////////////////////////////////////////////////////
6775/// Function called when loading a new class library.
6778{
6779 TIter next(GetListOfLeaves());
6780 TLeaf* leaf = 0;
6781 while ((leaf = (TLeaf*) next())) {
6782 leaf->Notify();
6783 leaf->GetBranch()->Notify();
6784 }
6785 return kTRUE;
6786}
6787
6788////////////////////////////////////////////////////////////////////////////////
6789/// This function may be called after having filled some entries in a Tree.
6790/// Using the information in the existing branch buffers, it will reassign
6791/// new branch buffer sizes to optimize time and memory.
6792///
6793/// The function computes the best values for branch buffer sizes such that
6794/// the total buffer sizes is less than maxMemory and nearby entries written
6795/// at the same time.
6796/// In case the branch compression factor for the data written so far is less
6797/// than compMin, the compression is disabled.
6798///
6799/// if option ="d" an analysis report is printed.
6801void TTree::OptimizeBaskets(ULong64_t maxMemory, Float_t minComp, Option_t *option)
6802{
6803 //Flush existing baskets if the file is writable
6804 if (this->GetDirectory()->IsWritable()) this->FlushBasketsImpl();
6805
6806 TString opt( option );
6807 opt.ToLower();
6808 Bool_t pDebug = opt.Contains("d");
6809 TObjArray *leaves = this->GetListOfLeaves();
6810 Int_t nleaves = leaves->GetEntries();
6811 Double_t treeSize = (Double_t)this->GetTotBytes();
6812
6813 if (nleaves == 0 || treeSize == 0) {
6814 // We're being called too early, we really have nothing to do ...
6815 return;
6816 }
6817 Double_t aveSize = treeSize/nleaves;
6818 UInt_t bmin = 512;
6819 UInt_t bmax = 256000;
6820 Double_t memFactor = 1;
6821 Int_t i, oldMemsize,newMemsize,oldBaskets,newBaskets;
6822 i = oldMemsize = newMemsize = oldBaskets = newBaskets = 0;
6823
6824 //we make two passes
6825 //one pass to compute the relative branch buffer sizes
6826 //a second pass to compute the absolute values
6827 for (Int_t pass =0;pass<2;pass++) {
6828 oldMemsize = 0; //to count size of baskets in memory with old buffer size
6829 newMemsize = 0; //to count size of baskets in memory with new buffer size
6830 oldBaskets = 0; //to count number of baskets with old buffer size
6831 newBaskets = 0; //to count number of baskets with new buffer size
6832 for (i=0;i<nleaves;i++) {
6833 TLeaf *leaf = (TLeaf*)leaves->At(i);
6834 TBranch *branch = leaf->GetBranch();
6835 Double_t totBytes = (Double_t)branch->GetTotBytes();
6836 Double_t idealFactor = totBytes/aveSize;
6837 UInt_t sizeOfOneEntry;
6838 if (branch->GetEntries() == 0) {
6839 // There is no data, so let's make a guess ...
6840 sizeOfOneEntry = aveSize;
6841 } else {
6842 sizeOfOneEntry = 1+(UInt_t)(totBytes / (Double_t)branch->GetEntries());
6843 }
6844 Int_t oldBsize = branch->GetBasketSize();
6845 oldMemsize += oldBsize;
6846 oldBaskets += 1+Int_t(totBytes/oldBsize);
6847 Int_t nb = branch->GetListOfBranches()->GetEntries();
6848 if (nb > 0) {
6849 newBaskets += 1+Int_t(totBytes/oldBsize);
6850 continue;
6851 }
6852 Double_t bsize = oldBsize*idealFactor*memFactor; //bsize can be very large !
6853 if (bsize < 0) bsize = bmax;
6854 if (bsize > bmax) bsize = bmax;
6855 UInt_t newBsize = UInt_t(bsize);
6856 if (pass) { // only on the second pass so that it doesn't interfere with scaling
6857 // If there is an entry offset, it will be stored in the same buffer as the object data; hence,
6858 // we must bump up the size of the branch to account for this extra footprint.
6859 // If fAutoFlush is not set yet, let's assume that it is 'in the process of being set' to
6860 // the value of GetEntries().
6861 Long64_t clusterSize = (fAutoFlush > 0) ? fAutoFlush : branch->GetEntries();
6862 if (branch->GetEntryOffsetLen()) {
6863 newBsize = newBsize + (clusterSize * sizeof(Int_t) * 2);
6864 }
6865 // We used ATLAS fully-split xAOD for testing, which is a rather unbalanced TTree, 10K branches,
6866 // with 8K having baskets smaller than 512 bytes. To achieve good I/O performance ATLAS uses auto-flush 100,
6867 // resulting in the smallest baskets being ~300-400 bytes, so this change increases their memory by about 8k*150B =~ 1MB,
6868 // at the same time it significantly reduces the number of total baskets because it ensures that all 100 entries can be
6869 // stored in a single basket (the old optimization tended to make baskets too small). In a toy example with fixed sized
6870 // structures we found a factor of 2 fewer baskets needed in the new scheme.
6871 // rounds up, increases basket size to ensure all entries fit into single basket as intended
6872 newBsize = newBsize - newBsize%512 + 512;
6873 }
6874 if (newBsize < sizeOfOneEntry) newBsize = sizeOfOneEntry;
6875 if (newBsize < bmin) newBsize = bmin;
6876 if (newBsize > 10000000) newBsize = bmax;
6877 if (pass) {
6878 if (pDebug) Info("OptimizeBaskets", "Changing buffer size from %6d to %6d bytes for %s\n",oldBsize,newBsize,branch->GetName());
6879 branch->SetBasketSize(newBsize);
6880 }
6881 newMemsize += newBsize;
6882 // For this number to be somewhat accurate when newBsize is 'low'
6883 // we do not include any space for meta data in the requested size (newBsize) even-though SetBasketSize will
6884 // not let it be lower than 100+TBranch::fEntryOffsetLen.
6885 newBaskets += 1+Int_t(totBytes/newBsize);
6886 if (pass == 0) continue;
6887 //Reset the compression level in case the compression factor is small
6888 Double_t comp = 1;
6889 if (branch->GetZipBytes() > 0) comp = totBytes/Double_t(branch->GetZipBytes());
6890 if (comp > 1 && comp < minComp) {
6891 if (pDebug) Info("OptimizeBaskets", "Disabling compression for branch : %s\n",branch->GetName());
6893 }
6894 }
6895 // coverity[divide_by_zero] newMemsize can not be zero as there is at least one leaf
6896 memFactor = Double_t(maxMemory)/Double_t(newMemsize);
6897 if (memFactor > 100) memFactor = 100;
6898 Double_t bmin_new = bmin*memFactor;
6899 Double_t bmax_new = bmax*memFactor;
6900 static const UInt_t hardmax = 1*1024*1024*1024; // Really, really never give more than 1Gb to a single buffer.
6901
6902 // Really, really never go lower than 8 bytes (we use this number
6903 // so that the calculation of the number of basket is consistent
6904 // but in fact SetBasketSize will not let the size go below
6905 // TBranch::fEntryOffsetLen + (100 + strlen(branch->GetName())
6906 // (The 2nd part being a slight over estimate of the key length.
6907 static const UInt_t hardmin = 8;
6908 bmin = (bmin_new > hardmax) ? hardmax : ( bmin_new < hardmin ? hardmin : (UInt_t)bmin_new );
6909 bmax = (bmax_new > hardmax) ? bmin : (UInt_t)bmax_new;
6910 }
6911 if (pDebug) {
6912 Info("OptimizeBaskets", "oldMemsize = %d, newMemsize = %d\n",oldMemsize, newMemsize);
6913 Info("OptimizeBaskets", "oldBaskets = %d, newBaskets = %d\n",oldBaskets, newBaskets);
6914 }
6915}
6916
6917////////////////////////////////////////////////////////////////////////////////
6918/// Interface to the Principal Components Analysis class.
6919///
6920/// Create an instance of TPrincipal
6921///
6922/// Fill it with the selected variables
6923///
6924/// - if option "n" is specified, the TPrincipal object is filled with
6925/// normalized variables.
6926/// - If option "p" is specified, compute the principal components
6927/// - If option "p" and "d" print results of analysis
6928/// - If option "p" and "h" generate standard histograms
6929/// - If option "p" and "c" generate code of conversion functions
6930/// - return a pointer to the TPrincipal object. It is the user responsibility
6931/// - to delete this object.
6932/// - The option default value is "np"
6933///
6934/// see TTree::Draw for explanation of the other parameters.
6935///
6936/// The created object is named "principal" and a reference to it
6937/// is added to the list of specials Root objects.
6938/// you can retrieve a pointer to the created object via:
6939/// ~~~ {.cpp}
6940/// TPrincipal *principal =
6941/// (TPrincipal*)gROOT->GetListOfSpecials()->FindObject("principal");
6942/// ~~~
6944TPrincipal* TTree::Principal(const char* varexp, const char* selection, Option_t* option, Long64_t nentries, Long64_t firstentry)
6945{
6946 GetPlayer();
6947 if (fPlayer) {
6948 return fPlayer->Principal(varexp, selection, option, nentries, firstentry);
6949 }
6950 return 0;
6951}
6952
6953////////////////////////////////////////////////////////////////////////////////
6954/// Print a summary of the tree contents.
6955///
6956/// - If option contains "all" friend trees are also printed.
6957/// - If option contains "toponly" only the top level branches are printed.
6958/// - If option contains "clusters" information about the cluster of baskets is printed.
6959///
6960/// Wildcarding can be used to print only a subset of the branches, e.g.,
6961/// `T.Print("Elec*")` will print all branches with name starting with "Elec".
6963void TTree::Print(Option_t* option) const
6964{
6965 // We already have been visited while recursively looking
6966 // through the friends tree, let's return.
6967 if (kPrint & fFriendLockStatus) {
6968 return;
6969 }
6970 Int_t s = 0;
6971 Int_t skey = 0;
6972 if (fDirectory) {
6973 TKey* key = fDirectory->GetKey(GetName());
6974 if (key) {
6975 skey = key->GetKeylen();
6976 s = key->GetNbytes();
6977 }
6978 }
6979 Long64_t total = skey;
6980 Long64_t zipBytes = GetZipBytes();
6981 if (zipBytes > 0) {
6982 total += GetTotBytes();
6983 }
6985 TTree::Class()->WriteBuffer(b, (TTree*) this);
6986 total += b.Length();
6987 Long64_t file = zipBytes + s;
6988 Float_t cx = 1;
6989 if (zipBytes) {
6990 cx = (GetTotBytes() + 0.00001) / zipBytes;
6991 }
6992 Printf("******************************************************************************");
6993 Printf("*Tree :%-10s: %-54s *", GetName(), GetTitle());
6994 Printf("*Entries : %8lld : Total = %15lld bytes File Size = %10lld *", fEntries, total, file);
6995 Printf("* : : Tree compression factor = %6.2f *", cx);
6996 Printf("******************************************************************************");
6997
6998 // Avoid many check of option validity
6999 if (option == nullptr)
7000 option = "";
7001
7002 if (strncmp(option,"clusters",strlen("clusters"))==0) {
7003 Printf("%-16s %-16s %-16s %5s",
7004 "Cluster Range #", "Entry Start", "Last Entry", "Size");
7005 Int_t index= 0;
7006 Long64_t clusterRangeStart = 0;
7007 if (fNClusterRange) {
7008 for( ; index < fNClusterRange; ++index) {
7009 Printf("%-16d %-16lld %-16lld %5lld",
7010 index, clusterRangeStart, fClusterRangeEnd[index], fClusterSize[index]);
7011 clusterRangeStart = fClusterRangeEnd[index] + 1;
7012 }
7013 }
7014 Printf("%-16d %-16lld %-16lld %5lld",
7015 index, clusterRangeStart, fEntries - 1, fAutoFlush);
7016 return;
7017 }
7018
7019 Int_t nl = const_cast<TTree*>(this)->GetListOfLeaves()->GetEntries();
7020 Int_t l;
7021 TBranch* br = 0;
7022 TLeaf* leaf = 0;
7023 if (strstr(option, "toponly")) {
7024 Long64_t *count = new Long64_t[nl];
7025 Int_t keep =0;
7026 for (l=0;l<nl;l++) {
7027 leaf = (TLeaf *)const_cast<TTree*>(this)->GetListOfLeaves()->At(l);
7028 br = leaf->GetBranch();
7029 if (strchr(br->GetName(),'.')) {
7030 count[l] = -1;
7031 count[keep] += br->GetZipBytes();
7032 } else {
7033 keep = l;
7034 count[keep] = br->GetZipBytes();
7035 }
7036 }
7037 for (l=0;l<nl;l++) {
7038 if (count[l] < 0) continue;
7039 leaf = (TLeaf *)const_cast<TTree*>(this)->GetListOfLeaves()->At(l);
7040 br = leaf->GetBranch();
7041 Printf("branch: %-20s %9lld\n",br->GetName(),count[l]);
7042 }
7043 delete [] count;
7044 } else {
7045 TString reg = "*";
7046 if (strlen(option) && strchr(option,'*')) reg = option;
7047 TRegexp re(reg,kTRUE);
7048 TIter next(const_cast<TTree*>(this)->GetListOfBranches());
7050 while ((br= (TBranch*)next())) {
7051 TString st = br->GetName();
7052 st.ReplaceAll("/","_");
7053 if (st.Index(re) == kNPOS) continue;
7054 br->Print(option);
7055 }
7056 }
7057
7058 //print TRefTable (if one)
7059 if (fBranchRef) fBranchRef->Print(option);
7060
7061 //print friends if option "all"
7062 if (!fFriends || !strstr(option,"all")) return;
7063 TIter nextf(fFriends);
7064 TFriendLock lock(const_cast<TTree*>(this),kPrint);
7065 TFriendElement *fr;
7066 while ((fr = (TFriendElement*)nextf())) {
7067 TTree * t = fr->GetTree();
7068 if (t) t->Print(option);
7069 }
7070}
7071
7072////////////////////////////////////////////////////////////////////////////////
7073/// Print statistics about the TreeCache for this tree.
7074/// Like:
7075/// ~~~ {.cpp}
7076/// ******TreeCache statistics for file: cms2.root ******
7077/// Reading 73921562 bytes in 716 transactions
7078/// Average transaction = 103.242405 Kbytes
7079/// Number of blocks in current cache: 202, total size : 6001193
7080/// ~~~
7081/// if option = "a" the list of blocks in the cache is printed
7083void TTree::PrintCacheStats(Option_t* option) const
7084{
7085 TFile *f = GetCurrentFile();
7086 if (!f) return;
7087 TTreeCache *tc = GetReadCache(f);
7088 if (tc) tc->Print(option);
7089}
7090
7091////////////////////////////////////////////////////////////////////////////////
7092/// Process this tree executing the TSelector code in the specified filename.
7093/// The return value is -1 in case of error and TSelector::GetStatus() in
7094/// in case of success.
7095///
7096/// The code in filename is loaded (interpreted or compiled, see below),
7097/// filename must contain a valid class implementation derived from TSelector,
7098/// where TSelector has the following member functions:
7099///
7100/// - `Begin()`: called every time a loop on the tree starts,
7101/// a convenient place to create your histograms.
7102/// - `SlaveBegin()`: called after Begin(), when on PROOF called only on the
7103/// slave servers.
7104/// - `Process()`: called for each event, in this function you decide what
7105/// to read and fill your histograms.
7106/// - `SlaveTerminate`: called at the end of the loop on the tree, when on PROOF
7107/// called only on the slave servers.
7108/// - `Terminate()`: called at the end of the loop on the tree,
7109/// a convenient place to draw/fit your histograms.
7110///
7111/// If filename is of the form file.C, the file will be interpreted.
7112///
7113/// If filename is of the form file.C++, the file file.C will be compiled
7114/// and dynamically loaded.
7115///
7116/// If filename is of the form file.C+, the file file.C will be compiled
7117/// and dynamically loaded. At next call, if file.C is older than file.o
7118/// and file.so, the file.C is not compiled, only file.so is loaded.
7119///
7120/// ## NOTE1
7121///
7122/// It may be more interesting to invoke directly the other Process function
7123/// accepting a TSelector* as argument.eg
7124/// ~~~ {.cpp}
7125/// MySelector *selector = (MySelector*)TSelector::GetSelector(filename);
7126/// selector->CallSomeFunction(..);
7127/// mytree.Process(selector,..);
7128/// ~~~
7129/// ## NOTE2
7130//
7131/// One should not call this function twice with the same selector file
7132/// in the same script. If this is required, proceed as indicated in NOTE1,
7133/// by getting a pointer to the corresponding TSelector,eg
7134///
7135/// ### workaround 1
7136/// ~~~ {.cpp}
7137/// void stubs1() {
7138/// TSelector *selector = TSelector::GetSelector("h1test.C");
7139/// TFile *f1 = new TFile("stubs_nood_le1.root");
7140/// TTree *h1 = (TTree*)f1->Get("h1");
7141/// h1->Process(selector);
7142/// TFile *f2 = new TFile("stubs_nood_le1_coarse.root");
7143/// TTree *h2 = (TTree*)f2->Get("h1");
7144/// h2->Process(selector);
7145/// }
7146/// ~~~
7147/// or use ACLIC to compile the selector
7148///
7149/// ### workaround 2
7150/// ~~~ {.cpp}
7151/// void stubs2() {
7152/// TFile *f1 = new TFile("stubs_nood_le1.root");
7153/// TTree *h1 = (TTree*)f1->Get("h1");
7154/// h1->Process("h1test.C+");
7155/// TFile *f2 = new TFile("stubs_nood_le1_coarse.root");
7156/// TTree *h2 = (TTree*)f2->Get("h1");
7157/// h2->Process("h1test.C+");
7158/// }
7159/// ~~~
7161Long64_t TTree::Process(const char* filename, Option_t* option, Long64_t nentries, Long64_t firstentry)
7162{
7163 GetPlayer();
7164 if (fPlayer) {
7165 return fPlayer->Process(filename, option, nentries, firstentry);
7166 }
7167 return -1;
7168}
7169
7170////////////////////////////////////////////////////////////////////////////////
7171/// Process this tree executing the code in the specified selector.
7172/// The return value is -1 in case of error and TSelector::GetStatus() in
7173/// in case of success.
7174///
7175/// The TSelector class has the following member functions:
7176///
7177/// - `Begin()`: called every time a loop on the tree starts,
7178/// a convenient place to create your histograms.
7179/// - `SlaveBegin()`: called after Begin(), when on PROOF called only on the
7180/// slave servers.
7181/// - `Process()`: called for each event, in this function you decide what
7182/// to read and fill your histograms.
7183/// - `SlaveTerminate`: called at the end of the loop on the tree, when on PROOF
7184/// called only on the slave servers.
7185/// - `Terminate()`: called at the end of the loop on the tree,
7186/// a convenient place to draw/fit your histograms.
7187///
7188/// If the Tree (Chain) has an associated EventList, the loop is on the nentries
7189/// of the EventList, starting at firstentry, otherwise the loop is on the
7190/// specified Tree entries.
7192Long64_t TTree::Process(TSelector* selector, Option_t* option, Long64_t nentries, Long64_t firstentry)
7193{
7194 GetPlayer();
7195 if (fPlayer) {
7196 return fPlayer->Process(selector, option, nentries, firstentry);
7197 }
7198 return -1;
7199}
7200
7201////////////////////////////////////////////////////////////////////////////////
7202/// Make a projection of a tree using selections.
7203///
7204/// Depending on the value of varexp (described in Draw) a 1-D, 2-D, etc.,
7205/// projection of the tree will be filled in histogram hname.
7206/// Note that the dimension of hname must match with the dimension of varexp.
7207///
7209Long64_t TTree::Project(const char* hname, const char* varexp, const char* selection, Option_t* option, Long64_t nentries, Long64_t firstentry)
7210{
7211 TString var;
7212 var.Form("%s>>%s", varexp, hname);
7213 TString opt("goff");
7214 if (option) {
7215 opt.Form("%sgoff", option);
7216 }
7217 Long64_t nsel = Draw(var, selection, opt, nentries, firstentry);
7218 return nsel;
7219}
7220
7221////////////////////////////////////////////////////////////////////////////////
7222/// Loop over entries and return a TSQLResult object containing entries following selection.
7224TSQLResult* TTree::Query(const char* varexp, const char* selection, Option_t* option, Long64_t nentries, Long64_t firstentry)
7225{
7226 GetPlayer();
7227 if (fPlayer) {
7228 return fPlayer->Query(varexp, selection, option, nentries, firstentry);
7229 }
7230 return 0;
7231}
7232
7233////////////////////////////////////////////////////////////////////////////////
7234/// Create or simply read branches from filename.
7235///
7236/// if branchDescriptor = "" (default), it is assumed that the Tree descriptor
7237/// is given in the first line of the file with a syntax like
7238/// ~~~ {.cpp}
7239/// A/D:Table[2]/F:Ntracks/I:astring/C
7240/// ~~~
7241/// otherwise branchDescriptor must be specified with the above syntax.
7242///
7243/// - If the type of the first variable is not specified, it is assumed to be "/F"
7244/// - If the type of any other variable is not specified, the type of the previous
7245/// variable is assumed. eg
7246/// - `x:y:z` (all variables are assumed of type "F"
7247/// - `x/D:y:z` (all variables are of type "D"
7248/// - `x:y/D:z` (x is type "F", y and z of type "D"
7249///
7250/// delimiter allows for the use of another delimiter besides whitespace.
7251/// This provides support for direct import of common data file formats
7252/// like csv. If delimiter != ' ' and branchDescriptor == "", then the
7253/// branch description is taken from the first line in the file, but
7254/// delimiter is used for the branch names tokenization rather than ':'.
7255/// Note however that if the values in the first line do not use the
7256/// /[type] syntax, all variables are assumed to be of type "F".
7257/// If the filename ends with extensions .csv or .CSV and a delimiter is
7258/// not specified (besides ' '), the delimiter is automatically set to ','.
7259///
7260/// Lines in the input file starting with "#" are ignored. Leading whitespace
7261/// for each column data is skipped. Empty lines are skipped.
7262///
7263/// A TBranch object is created for each variable in the expression.
7264/// The total number of rows read from the file is returned.
7265///
7266/// ## FILLING a TTree WITH MULTIPLE INPUT TEXT FILES
7267///
7268/// To fill a TTree with multiple input text files, proceed as indicated above
7269/// for the first input file and omit the second argument for subsequent calls
7270/// ~~~ {.cpp}
7271/// T.ReadFile("file1.dat","branch descriptor");
7272/// T.ReadFile("file2.dat");
7273/// ~~~
7275Long64_t TTree::ReadFile(const char* filename, const char* branchDescriptor, char delimiter)
7276{
7277 std::ifstream in;
7278 in.open(filename);
7279 if (!in.good()) {
7280 Error("ReadFile","Cannot open file: %s",filename);
7281 return 0;
7282 }
7283 const char* ext = strrchr(filename, '.');
7284 if(ext != NULL && ((strcmp(ext, ".csv") == 0) || (strcmp(ext, ".CSV") == 0)) && delimiter == ' ') {
7285 delimiter = ',';
7286 }
7287 return ReadStream(in, branchDescriptor, delimiter);
7288}
7289
7290////////////////////////////////////////////////////////////////////////////////
7291/// Determine which newline this file is using.
7292/// Return '\\r' for Windows '\\r\\n' as that already terminates.
7294char TTree::GetNewlineValue(std::istream &inputStream)
7295{
7296 Long_t inPos = inputStream.tellg();
7297 char newline = '\n';
7298 while(1) {
7299 char c = 0;
7300 inputStream.get(c);
7301 if(!inputStream.good()) {
7302 Error("ReadStream","Error reading stream: no newline found.");
7303 return 0;
7304 }
7305 if(c == newline) break;
7306 if(c == '\r') {
7307 newline = '\r';
7308 break;
7309 }
7310 }
7311 inputStream.clear();
7312 inputStream.seekg(inPos);
7313 return newline;
7314}
7315
7316////////////////////////////////////////////////////////////////////////////////
7317/// Create or simply read branches from an input stream.
7318///
7319/// See reference information for TTree::ReadFile
7321Long64_t TTree::ReadStream(std::istream& inputStream, const char *branchDescriptor, char delimiter)
7322{
7323 char newline = 0;
7324 std::stringstream ss;
7325 std::istream *inTemp;
7326 Long_t inPos = inputStream.tellg();
7327 if (!inputStream.good()) {
7328 Error("ReadStream","Error reading stream");
7329 return 0;
7330 }
7331 if (inPos == -1) {
7332 ss << std::cin.rdbuf();
7333 newline = GetNewlineValue(ss);
7334 inTemp = &ss;
7335 } else {
7336 newline = GetNewlineValue(inputStream);
7337 inTemp = &inputStream;
7338 }
7339 std::istream& in = *inTemp;
7340 Long64_t nlines = 0;
7341
7342 TBranch *branch = 0;
7343 Int_t nbranches = fBranches.GetEntries();
7344 if (nbranches == 0) {
7345 char *bdname = new char[4000];
7346 char *bd = new char[100000];
7347 Int_t nch = 0;
7348 if (branchDescriptor) nch = strlen(branchDescriptor);
7349 // branch Descriptor is null, read its definition from the first line in the file
7350 if (!nch) {
7351 do {
7352 in.getline(bd, 100000, newline);
7353 if (!in.good()) {
7354 delete [] bdname;
7355 delete [] bd;
7356 Error("ReadStream","Error reading stream");
7357 return 0;
7358 }
7359 char *cursor = bd;
7360 while( isspace(*cursor) && *cursor != '\n' && *cursor != '\0') {
7361 ++cursor;
7362 }
7363 if (*cursor != '#' && *cursor != '\n' && *cursor != '\0') {
7364 break;
7365 }
7366 } while (true);
7367 ++nlines;
7368 nch = strlen(bd);
7369 } else {
7370 strlcpy(bd,branchDescriptor,100000);
7371 }
7372
7373 //parse the branch descriptor and create a branch for each element
7374 //separated by ":"
7375 void *address = &bd[90000];
7376 char *bdcur = bd;
7377 TString desc="", olddesc="F";
7378 char bdelim = ':';
7379 if(delimiter != ' ') {
7380 bdelim = delimiter;
7381 if (strchr(bdcur,bdelim)==0 && strchr(bdcur,':') != 0) {
7382 // revert to the default
7383 bdelim = ':';
7384 }
7385 }
7386 while (bdcur) {
7387 char *colon = strchr(bdcur,bdelim);
7388 if (colon) *colon = 0;
7389 strlcpy(bdname,bdcur,4000);
7390 char *slash = strchr(bdname,'/');
7391 if (slash) {
7392 *slash = 0;
7393 desc = bdcur;
7394 olddesc = slash+1;
7395 } else {
7396 desc.Form("%s/%s",bdname,olddesc.Data());
7397 }
7398 char *bracket = strchr(bdname,'[');
7399 if (bracket) {
7400 *bracket = 0;
7401 }
7402 branch = new TBranch(this,bdname,address,desc.Data(),32000);
7403 if (branch->IsZombie()) {
7404 delete branch;
7405 Warning("ReadStream","Illegal branch definition: %s",bdcur);
7406 } else {
7407 fBranches.Add(branch);
7408 branch->SetAddress(0);
7409 }
7410 if (!colon)break;
7411 bdcur = colon+1;
7412 }
7413 delete [] bdname;
7414 delete [] bd;
7415 }
7416
7417 nbranches = fBranches.GetEntries();
7418
7419 if (gDebug > 1) {
7420 Info("ReadStream", "Will use branches:");
7421 for (int i = 0 ; i < nbranches; ++i) {
7422 TBranch* br = (TBranch*) fBranches.At(i);
7423 Info("ReadStream", " %s: %s [%s]", br->GetName(),
7424 br->GetTitle(), br->GetListOfLeaves()->At(0)->IsA()->GetName());
7425 }
7426 if (gDebug > 3) {
7427 Info("ReadStream", "Dumping read tokens, format:");
7428 Info("ReadStream", "LLLLL:BBB:gfbe:GFBE:T");
7429 Info("ReadStream", " L: line number");
7430 Info("ReadStream", " B: branch number");
7431 Info("ReadStream", " gfbe: good / fail / bad / eof of token");
7432 Info("ReadStream", " GFBE: good / fail / bad / eof of file");
7433 Info("ReadStream", " T: Token being read");
7434 }
7435 }
7436
7437 //loop on all lines in the file
7438 Long64_t nGoodLines = 0;
7439 std::string line;
7440 const char sDelimBuf[2] = { delimiter, 0 };
7441 const char* sDelim = sDelimBuf;
7442 if (delimiter == ' ') {
7443 // ' ' really means whitespace
7444 sDelim = "[ \t]";
7445 }
7446 while(in.good()) {
7447 if (newline == '\r' && in.peek() == '\n') {
7448 // Windows, skip '\n':
7449 in.get();
7450 }
7451 std::getline(in, line, newline);
7452 ++nlines;
7453
7454 TString sLine(line);
7455 sLine = sLine.Strip(TString::kLeading); // skip leading whitespace
7456 if (sLine.IsNull()) {
7457 if (gDebug > 2) {
7458 Info("ReadStream", "Skipping empty line number %lld", nlines);
7459 }
7460 continue; // silently skip empty lines
7461 }
7462 if (sLine[0] == '#') {
7463 if (gDebug > 2) {
7464 Info("ReadStream", "Skipping comment line number %lld: '%s'",
7465 nlines, line.c_str());
7466 }
7467 continue;
7468 }
7469 if (gDebug > 2) {
7470 Info("ReadStream", "Parsing line number %lld: '%s'",
7471 nlines, line.c_str());
7472 }
7473
7474 // Loop on branches and read the branch values into their buffer
7475 branch = 0;
7476 TString tok; // one column's data
7477 TString leafData; // leaf data, possibly multiple tokens for e.g. /I[2]
7478 std::stringstream sToken; // string stream feeding leafData into leaves
7479 Ssiz_t pos = 0;
7480 Int_t iBranch = 0;
7481 Bool_t goodLine = kTRUE; // whether the row can be filled into the tree
7482 Int_t remainingLeafLen = 0; // remaining columns for the current leaf
7483 while (goodLine && iBranch < nbranches
7484 && sLine.Tokenize(tok, pos, sDelim)) {
7485 tok = tok.Strip(TString::kLeading); // skip leading whitespace
7486 if (tok.IsNull() && delimiter == ' ') {
7487 // 1 2 should not be interpreted as 1,,,2 but 1, 2.
7488 // Thus continue until we have a non-empty token.
7489 continue;
7490 }
7491
7492 if (!remainingLeafLen) {
7493 // next branch!
7494 branch = (TBranch*)fBranches.At(iBranch);
7495 }
7496 TLeaf *leaf = (TLeaf*)branch->GetListOfLeaves()->At(0);
7497 if (!remainingLeafLen) {
7498 remainingLeafLen = leaf->GetLen();
7499 if (leaf->GetMaximum() > 0) {
7500 // This is a dynamic leaf length, i.e. most likely a TLeafC's
7501 // string size. This still translates into one token:
7502 remainingLeafLen = 1;
7503 }
7504
7505 leafData = tok;
7506 } else {
7507 // append token to laf data:
7508 leafData += " ";
7509 leafData += tok;
7510 }
7511 --remainingLeafLen;
7512 if (remainingLeafLen) {
7513 // need more columns for this branch:
7514 continue;
7515 }
7516 ++iBranch;
7517
7518 // initialize stringstream with token
7519 sToken.clear();
7520 sToken.seekp(0, std::ios_base::beg);
7521 sToken.str(leafData.Data());
7522 sToken.seekg(0, std::ios_base::beg);
7523 leaf->ReadValue(sToken, 0 /* 0 = "all" */);
7524 if (gDebug > 3) {
7525 Info("ReadStream", "%5lld:%3d:%d%d%d%d:%d%d%d%d:%s",
7526 nlines, iBranch,
7527 (int)sToken.good(), (int)sToken.fail(),
7528 (int)sToken.bad(), (int)sToken.eof(),
7529 (int)in.good(), (int)in.fail(),
7530 (int)in.bad(), (int)in.eof(),
7531 sToken.str().c_str());
7532 }
7533
7534 // Error handling
7535 if (sToken.bad()) {
7536 // How could that happen for a stringstream?
7537 Warning("ReadStream",
7538 "Buffer error while reading data for branch %s on line %lld",
7539 branch->GetName(), nlines);
7540 } else if (!sToken.eof()) {
7541 if (sToken.fail()) {
7542 Warning("ReadStream",
7543 "Couldn't read formatted data in \"%s\" for branch %s on line %lld; ignoring line",
7544 tok.Data(), branch->GetName(), nlines);
7545 goodLine = kFALSE;
7546 } else {
7547 std::string remainder;
7548 std::getline(sToken, remainder, newline);
7549 if (!remainder.empty()) {
7550 Warning("ReadStream",
7551 "Ignoring trailing \"%s\" while reading data for branch %s on line %lld",
7552 remainder.c_str(), branch->GetName(), nlines);
7553 }
7554 }
7555 }
7556 } // tokenizer loop
7557
7558 if (iBranch < nbranches) {
7559 Warning("ReadStream",
7560 "Read too few columns (%d < %d) in line %lld; ignoring line",
7561 iBranch, nbranches, nlines);
7562 goodLine = kFALSE;
7563 } else if (pos != kNPOS) {
7564 sLine = sLine.Strip(TString::kTrailing);
7565 if (pos < sLine.Length()) {
7566 Warning("ReadStream",
7567 "Ignoring trailing \"%s\" while reading line %lld",
7568 sLine.Data() + pos - 1 /* also print delimiter */,
7569 nlines);
7570 }
7571 }
7572
7573 //we are now ready to fill the tree
7574 if (goodLine) {
7575 Fill();
7576 ++nGoodLines;
7577 }
7578 }
7579
7580 return nGoodLines;
7581}
7582
7583////////////////////////////////////////////////////////////////////////////////
7584/// Make sure that obj (which is being deleted or will soon be) is no
7585/// longer referenced by this TTree.
7588{
7589 if (obj == fEventList) {
7590 fEventList = 0;
7591 }
7592 if (obj == fEntryList) {
7593 fEntryList = 0;
7594 }
7595 if (fUserInfo) {
7597 }
7598 if (fPlayer == obj) {
7599 fPlayer = 0;
7600 }
7601 if (fTreeIndex == obj) {
7602 fTreeIndex = 0;
7603 }
7604 if (fAliases) {
7606 }
7607 if (fFriends) {
7609 }
7610}
7611
7612////////////////////////////////////////////////////////////////////////////////
7613/// Refresh contents of this tree and its branches from the current status on disk.
7614///
7615/// One can call this function in case the tree file is being
7616/// updated by another process.
7618void TTree::Refresh()
7619{
7620 if (!fDirectory->GetFile()) {
7621 return;
7622 }
7624 fDirectory->Remove(this);
7626 if (!tree) {
7627 return;
7628 }
7629 //copy info from tree header into this Tree
7630 fEntries = 0;
7631 fNClusterRange = 0;
7633
7634 fAutoSave = tree->fAutoSave;
7635 fEntries = tree->fEntries;
7636 fTotBytes = tree->GetTotBytes();
7637 fZipBytes = tree->GetZipBytes();
7638 fSavedBytes = tree->fSavedBytes;
7639 fTotalBuffers = tree->fTotalBuffers.load();
7640
7641 //loop on all branches and update them
7642 Int_t nleaves = fLeaves.GetEntriesFast();
7643 for (Int_t i = 0; i < nleaves; i++) {
7644 TLeaf* leaf = (TLeaf*) fLeaves.UncheckedAt(i);
7645 TBranch* branch = (TBranch*) leaf->GetBranch();
7646 branch->Refresh(tree->GetBranch(branch->GetName()));
7647 }
7649 fDirectory->Append(this);
7650 delete tree;
7651 tree = 0;
7652}
7653
7654////////////////////////////////////////////////////////////////////////////////
7655/// Remove a friend from the list of friends.
7657void TTree::RemoveFriend(TTree* oldFriend)
7658{
7659 // We already have been visited while recursively looking
7660 // through the friends tree, let return
7662 return;
7663 }
7664 if (!fFriends) {
7665 return;
7666 }
7667 TFriendLock lock(this, kRemoveFriend);
7668 TIter nextf(fFriends);
7669 TFriendElement* fe = 0;
7670 while ((fe = (TFriendElement*) nextf())) {
7671 TTree* friend_t = fe->GetTree();
7672 if (friend_t == oldFriend) {
7673 fFriends->Remove(fe);
7674 delete fe;
7675 fe = 0;
7676 }
7677 }
7678}
7679
7680////////////////////////////////////////////////////////////////////////////////
7681/// Reset baskets, buffers and entries count in all branches and leaves.
7683void TTree::Reset(Option_t* option)
7684{
7685 fNotify = 0;
7686 fEntries = 0;
7687 fNClusterRange = 0;
7688 fTotBytes = 0;
7689 fZipBytes = 0;
7690 fFlushedBytes = 0;
7691 fSavedBytes = 0;
7692 fTotalBuffers = 0;
7693 fChainOffset = 0;
7694 fReadEntry = -1;
7695
7696 delete fTreeIndex;
7697 fTreeIndex = 0;
7698
7700 for (Int_t i = 0; i < nb; ++i) {
7701 TBranch* branch = (TBranch*) fBranches.UncheckedAt(i);
7702 branch->Reset(option);
7703 }
7704
7705 if (fBranchRef) {
7706 fBranchRef->Reset();
7707 }
7708}
7709
7710////////////////////////////////////////////////////////////////////////////////
7711/// Resets the state of this TTree after a merge (keep the customization but
7712/// forget the data).
7715{
7716 fEntries = 0;
7717 fNClusterRange = 0;
7718 fTotBytes = 0;
7719 fZipBytes = 0;
7720 fSavedBytes = 0;
7721 fFlushedBytes = 0;
7722 fTotalBuffers = 0;
7723 fChainOffset = 0;
7724 fReadEntry = -1;
7725
7726 delete fTreeIndex;
7727 fTreeIndex = 0;
7728
7730 for (Int_t i = 0; i < nb; ++i) {
7731 TBranch* branch = (TBranch*) fBranches.UncheckedAt(i);
7732 branch->ResetAfterMerge(info);
7733 }
7734
7735 if (fBranchRef) {
7737 }
7738}
7739
7740////////////////////////////////////////////////////////////////////////////////
7741/// Tell all of our branches to set their addresses to zero.
7742///
7743/// Note: If any of our branches own any objects, they are deleted.
7746{
7747 if (br && br->GetTree()) {
7748 br->ResetAddress();
7749 }
7750}
7751
7752////////////////////////////////////////////////////////////////////////////////
7753/// Tell all of our branches to drop their current objects and allocate new ones.
7756{
7758 Int_t nbranches = branches->GetEntriesFast();
7759 for (Int_t i = 0; i < nbranches; ++i) {
7760 TBranch* branch = (TBranch*) branches->UncheckedAt(i);
7761 branch->ResetAddress();
7762 }
7763}
7764
7765////////////////////////////////////////////////////////////////////////////////
7766/// Loop over tree entries and print entries passing selection.
7767///
7768/// - If varexp is 0 (or "") then print only first 8 columns.
7769/// - If varexp = "*" print all columns.
7770///
7771/// Otherwise a columns selection can be made using "var1:var2:var3".
7772/// See TTreePlayer::Scan for more information
7774Long64_t TTree::Scan(const char* varexp, const char* selection, Option_t* option, Long64_t nentries, Long64_t firstentry)
7775{
7776 GetPlayer();
7777 if (fPlayer) {
7778 return fPlayer->Scan(varexp, selection, option, nentries, firstentry);
7779 }
7780 return -1;
7781}
7782
7783////////////////////////////////////////////////////////////////////////////////
7784/// Set a tree variable alias.
7785///
7786/// Set an alias for an expression/formula based on the tree 'variables'.
7787///
7788/// The content of 'aliasName' can be used in TTreeFormula (i.e. TTree::Draw,
7789/// TTree::Scan, TTreeViewer) and will be evaluated as the content of
7790/// 'aliasFormula'.
7791///
7792/// If the content of 'aliasFormula' only contains symbol names, periods and
7793/// array index specification (for example event.fTracks[3]), then
7794/// the content of 'aliasName' can be used as the start of symbol.
7795///
7796/// If the alias 'aliasName' already existed, it is replaced by the new
7797/// value.
7798///
7799/// When being used, the alias can be preceded by an eventual 'Friend Alias'
7800/// (see TTree::GetFriendAlias)
7801///
7802/// Return true if it was added properly.
7803///
7804/// For example:
7805/// ~~~ {.cpp}
7806/// tree->SetAlias("x1","(tdc1[1]-tdc1[0])/49");
7807/// tree->SetAlias("y1","(tdc1[3]-tdc1[2])/47");
7808/// tree->SetAlias("x2","(tdc2[1]-tdc2[0])/49");
7809/// tree->SetAlias("y2","(tdc2[3]-tdc2[2])/47");
7810/// tree->Draw("y2-y1:x2-x1");
7811///
7812/// tree->SetAlias("theGoodTrack","event.fTracks[3]");
7813/// tree->Draw("theGoodTrack.fPx"); // same as "event.fTracks[3].fPx"
7814/// ~~~
7816Bool_t TTree::SetAlias(const char* aliasName, const char* aliasFormula)
7817{
7818 if (!aliasName || !aliasFormula) {
7819 return kFALSE;
7820 }
7821 if (!aliasName[0] || !aliasFormula[0]) {
7822 return kFALSE;
7823 }
7824 if (!fAliases) {
7825 fAliases = new TList;
7826 } else {
7827 TNamed* oldHolder = (TNamed*) fAliases->FindObject(aliasName);
7828 if (oldHolder) {
7829 oldHolder->SetTitle(aliasFormula);
7830 return kTRUE;
7831 }
7832 }
7833 TNamed* holder = new TNamed(aliasName, aliasFormula);
7834 fAliases->Add(holder);
7835 return kTRUE;
7836}
7837
7838////////////////////////////////////////////////////////////////////////////////
7839/// This function may be called at the start of a program to change
7840/// the default value for fAutoFlush.
7841///
7842/// ### CASE 1 : autof > 0
7843///
7844/// autof is the number of consecutive entries after which TTree::Fill will
7845/// flush all branch buffers to disk.
7846///
7847/// ### CASE 2 : autof < 0
7848///
7849/// When filling the Tree the branch buffers will be flushed to disk when
7850/// more than autof bytes have been written to the file. At the first FlushBaskets
7851/// TTree::Fill will replace fAutoFlush by the current value of fEntries.
7852///
7853/// Calling this function with autof<0 is interesting when it is hard to estimate
7854/// the size of one entry. This value is also independent of the Tree.
7855///
7856/// The Tree is initialized with fAutoFlush=-30000000, ie that, by default,
7857/// the first AutoFlush will be done when 30 MBytes of data are written to the file.
7858///
7859/// ### CASE 3 : autof = 0
7860///
7861/// The AutoFlush mechanism is disabled.
7862///
7863/// Flushing the buffers at regular intervals optimize the location of
7864/// consecutive entries on the disk by creating clusters of baskets.
7865///
7866/// A cluster of baskets is a set of baskets that contains all
7867/// the data for a (consecutive) set of entries and that is stored
7868/// consecutively on the disk. When reading all the branches, this
7869/// is the minimum set of baskets that the TTreeCache will read.
7871void TTree::SetAutoFlush(Long64_t autof /* = -30000000 */ )
7872{
7873 // Implementation note:
7874 //
7875 // A positive value of autoflush determines the size (in number of entries) of
7876 // a cluster of baskets.
7877 //
7878 // If the value of autoflush is changed over time (this happens in
7879 // particular when the TTree results from fast merging many trees),
7880 // we record the values of fAutoFlush in the data members:
7881 // fClusterRangeEnd and fClusterSize.
7882 // In the code we refer to a range of entries where the size of the
7883 // cluster of baskets is the same (i.e the value of AutoFlush was
7884 // constant) is called a ClusterRange.
7885 //
7886 // The 2 arrays (fClusterRangeEnd and fClusterSize) have fNClusterRange
7887 // active (used) values and have fMaxClusterRange allocated entries.
7888 //
7889 // fClusterRangeEnd contains the last entries number of a cluster range.
7890 // In particular this means that the 'next' cluster starts at fClusterRangeEnd[]+1
7891 // fClusterSize contains the size in number of entries of all the cluster
7892 // within the given range.
7893 // The last range (and the only one if fNClusterRange is zero) start at
7894 // fNClusterRange[fNClusterRange-1]+1 and ends at the end of the TTree. The
7895 // size of the cluster in this range is given by the value of fAutoFlush.
7896 //
7897 // For example printing the beginning and end of each the ranges can be done by:
7898 //
7899 // Printf("%-16s %-16s %-16s %5s",
7900 // "Cluster Range #", "Entry Start", "Last Entry", "Size");
7901 // Int_t index= 0;
7902 // Long64_t clusterRangeStart = 0;
7903 // if (fNClusterRange) {
7904 // for( ; index < fNClusterRange; ++index) {
7905 // Printf("%-16d %-16lld %-16lld %5lld",
7906 // index, clusterRangeStart, fClusterRangeEnd[index], fClusterSize[index]);
7907 // clusterRangeStart = fClusterRangeEnd[index] + 1;
7908 // }
7909 // }
7910 // Printf("%-16d %-16lld %-16lld %5lld",
7911 // index, prevEntry, fEntries - 1, fAutoFlush);
7912 //
7913
7914 // Note: We store the entry number corresponding to the end of the cluster
7915 // rather than its start in order to avoid using the array if the cluster
7916 // size never varies (If there is only one value of AutoFlush for the whole TTree).
7917
7918 if( fAutoFlush != autof) {
7919 if ((fAutoFlush > 0 || autof > 0) && fFlushedBytes) {
7920 // The mechanism was already enabled, let's record the previous
7921 // cluster if needed.
7923 }
7924 fAutoFlush = autof;
7925 }
7926}
7927
7928////////////////////////////////////////////////////////////////////////////////
7929/// Mark the previous event as being at the end of the event cluster.
7930///
7931/// So, if fEntries is set to 10 (and this is the first cluster) when MarkEventCluster
7932/// is called, then the first cluster has 9 events.
7934{
7935 if (!fEntries) return;
7936
7937 if ( (fNClusterRange+1) > fMaxClusterRange ) {
7938 if (fMaxClusterRange) {
7939 // Resize arrays to hold a larger event cluster.
7940 Int_t newsize = TMath::Max(10,Int_t(2*fMaxClusterRange));
7942 newsize*sizeof(Long64_t),fMaxClusterRange*sizeof(Long64_t));
7944 newsize*sizeof(Long64_t),fMaxClusterRange*sizeof(Long64_t));
7945 fMaxClusterRange = newsize;
7946 } else {
7947 // Cluster ranges have never been initialized; create them now.
7948 fMaxClusterRange = 2;
7951 }
7952 }
7954 // If we are auto-flushing, then the cluster size is the same as the current auto-flush setting.
7955 if (fAutoFlush > 0) {
7956 // Even if the user triggers MarkEventRange prior to fAutoFlush being present, the TClusterIterator
7957 // will appropriately go to the next event range.
7959 // Otherwise, assume there is one cluster per event range (e.g., user is manually controlling the flush).
7960 } else if (fNClusterRange == 0) {
7962 } else {
7964 }
7966}
7967
7968////////////////////////////////////////////////////////////////////////////////
7969/// This function may be called at the start of a program to change
7970/// the default value for fAutoSave (and for SetAutoSave) is -300000000, ie 300 MBytes.
7971/// When filling the Tree the branch buffers as well as the Tree header
7972/// will be flushed to disk when the watermark is reached.
7973/// If fAutoSave is positive the watermark is reached when a multiple of fAutoSave
7974/// entries have been written.
7975/// If fAutoSave is negative the watermark is reached when -fAutoSave bytes
7976/// have been written to the file.
7977/// In case of a program crash, it will be possible to recover the data in the Tree
7978/// up to the last AutoSave point.
7980void TTree::SetAutoSave(Long64_t autos)
7981{
7982 fAutoSave = autos;
7983}
7984
7985////////////////////////////////////////////////////////////////////////////////
7986/// Set a branch's basket size.
7987///
7988/// bname is the name of a branch.
7989///
7990/// - if bname="*", apply to all branches.
7991/// - if bname="xxx*", apply to all branches with name starting with xxx
7992///
7993/// see TRegexp for wildcarding options
7994/// buffsize = branc basket size
7996void TTree::SetBasketSize(const char* bname, Int_t buffsize)
7997{
7998 Int_t nleaves = fLeaves.GetEntriesFast();
7999 TRegexp re(bname, kTRUE);
8000 Int_t nb = 0;
8001 for (Int_t i = 0; i < nleaves; i++) {
8002 TLeaf* leaf = (TLeaf*) fLeaves.UncheckedAt(i);
8003 TBranch* branch = (TBranch*) leaf->GetBranch();
8004 TString s = branch->GetName();
8005 if (strcmp(bname, branch->GetName()) && (s.Index(re) == kNPOS)) {
8006 continue;
8007 }
8008 nb++;
8009 branch->SetBasketSize(buffsize);
8010 }
8011 if (!nb) {
8012 Error("SetBasketSize", "unknown branch -> '%s'", bname);
8013 }
8014}
8015
8016////////////////////////////////////////////////////////////////////////////////
8017/// Change branch address, dealing with clone trees properly.
8018/// See TTree::CheckBranchAddressType for the semantic of the return value.
8019///
8020/// Note: See the comments in TBranchElement::SetAddress() for the
8021/// meaning of the addr parameter and the object ownership policy.
8023Int_t TTree::SetBranchAddress(const char* bname, void* addr, TBranch** ptr)
8024{
8025 TBranch* branch = GetBranch(bname);
8026 if (!branch) {
8027 if (ptr) *ptr = 0;
8028 Error("SetBranchAddress", "unknown branch -> %s", bname);
8029 return kMissingBranch;
8030 }
8031 return SetBranchAddressImp(branch,addr,ptr);
8032}
8033
8034////////////////////////////////////////////////////////////////////////////////
8035/// Verify the validity of the type of addr before calling SetBranchAddress.
8036/// See TTree::CheckBranchAddressType for the semantic of the return value.
8037///
8038/// Note: See the comments in TBranchElement::SetAddress() for the
8039/// meaning of the addr parameter and the object ownership policy.
8041Int_t TTree::SetBranchAddress(const char* bname, void* addr, TClass* ptrClass, EDataType datatype, Bool_t isptr)
8042{
8043 return SetBranchAddress(bname, addr, 0, ptrClass, datatype, isptr);
8044}
8045
8046////////////////////////////////////////////////////////////////////////////////
8047/// Verify the validity of the type of addr before calling SetBranchAddress.
8048/// See TTree::CheckBranchAddressType for the semantic of the return value.
8049///
8050/// Note: See the comments in TBranchElement::SetAddress() for the
8051/// meaning of the addr parameter and the object ownership policy.
8053Int_t TTree::SetBranchAddress(const char* bname, void* addr, TBranch** ptr, TClass* ptrClass, EDataType datatype, Bool_t isptr)
8054{
8055 TBranch* branch = GetBranch(bname);
8056 if (!branch) {
8057 if (ptr) *ptr = 0;
8058 Error("SetBranchAddress", "unknown branch -> %s", bname);
8059 return kMissingBranch;
8060 }
8061
8062 Int_t res = CheckBranchAddressType(branch, ptrClass, datatype, isptr);
8063 // This will set the value of *ptr to branch.
8064 if (res >= 0) {
8065 // The check succeeded.
8066 SetBranchAddressImp(branch,addr,ptr);
8067 } else {
8068 if (ptr) *ptr = 0;
8069 }
8070 return res;
8071}
8072
8073////////////////////////////////////////////////////////////////////////////////
8074/// Change branch address, dealing with clone trees properly.
8075/// See TTree::CheckBranchAddressType for the semantic of the return value.
8076///
8077/// Note: See the comments in TBranchElement::SetAddress() for the
8078/// meaning of the addr parameter and the object ownership policy.
8080Int_t TTree::SetBranchAddressImp(TBranch *branch, void* addr, TBranch** ptr)
8081{
8082 if (ptr) {
8083 *ptr = branch;
8084 }
8085 if (fClones) {
8086 void* oldAddr = branch->GetAddress();
8087 TIter next(fClones);
8088 TTree* clone = 0;
8089 const char *bname = branch->GetName();
8090 while ((clone = (TTree*) next())) {
8091 TBranch* cloneBr = clone->GetBranch(bname);
8092 if (cloneBr && (cloneBr->GetAddress() == oldAddr)) {
8093 cloneBr->SetAddress(addr);
8094 }
8095 }
8096 }
8097 branch->SetAddress(addr);
8098 return kVoidPtr;
8099}
8100
8101////////////////////////////////////////////////////////////////////////////////
8102/// Set branch status to Process or DoNotProcess.
8103///
8104/// When reading a Tree, by default, all branches are read.
8105/// One can speed up considerably the analysis phase by activating
8106/// only the branches that hold variables involved in a query.
8107///
8108/// bname is the name of a branch.
8109///
8110/// - if bname="*", apply to all branches.
8111/// - if bname="xxx*", apply to all branches with name starting with xxx
8112///
8113/// see TRegexp for wildcarding options
8114///
8115/// - status = 1 branch will be processed
8116/// - = 0 branch will not be processed
8117///
8118/// Example:
8119///
8120/// Assume a tree T with sub-branches a,b,c,d,e,f,g,etc..
8121/// when doing T.GetEntry(i) all branches are read for entry i.
8122/// to read only the branches c and e, one can do
8123/// ~~~ {.cpp}
8124/// T.SetBranchStatus("*",0); //disable all branches
8125/// T.SetBranchStatus("c",1);
8126/// T.setBranchStatus("e",1);
8127/// T.GetEntry(i);
8128/// ~~~
8129/// bname is interpreted as a wildcarded TRegexp (see TRegexp::MakeWildcard).
8130/// Thus, "a*b" or "a.*b" matches branches starting with "a" and ending with
8131/// "b", but not any other branch with an "a" followed at some point by a
8132/// "b". For this second behavior, use "*a*b*". Note that TRegExp does not
8133/// support '|', and so you cannot select, e.g. track and shower branches
8134/// with "track|shower".
8135///
8136/// __WARNING! WARNING! WARNING!__
8137///
8138/// SetBranchStatus is matching the branch based on match of the branch
8139/// 'name' and not on the branch hierarchy! In order to be able to
8140/// selectively enable a top level object that is 'split' you need to make
8141/// sure the name of the top level branch is prefixed to the sub-branches'
8142/// name (by adding a dot ('.') at the end of the Branch creation and use the
8143/// corresponding bname.
8144///
8145/// I.e If your Tree has been created in split mode with a parent branch "parent."
8146/// (note the trailing dot).
8147/// ~~~ {.cpp}
8148/// T.SetBranchStatus("parent",1);
8149/// ~~~
8150/// will not activate the sub-branches of "parent". You should do:
8151/// ~~~ {.cpp}
8152/// T.SetBranchStatus("parent*",1);
8153/// ~~~
8154/// Without the trailing dot in the branch creation you have no choice but to
8155/// call SetBranchStatus explicitly for each of the sub branches.
8156///
8157/// An alternative to this function is to read directly and only
8158/// the interesting branches. Example:
8159/// ~~~ {.cpp}
8160/// TBranch *brc = T.GetBranch("c");
8161/// TBranch *bre = T.GetBranch("e");
8162/// brc->GetEntry(i);
8163/// bre->GetEntry(i);
8164/// ~~~
8165/// If found is not 0, the number of branch(es) found matching the regular
8166/// expression is returned in *found AND the error message 'unknown branch'
8167/// is suppressed.
8169void TTree::SetBranchStatus(const char* bname, Bool_t status, UInt_t* found)
8170{
8171 // We already have been visited while recursively looking
8172 // through the friends tree, let return
8174 return;
8175 }
8176
8177 TBranch *branch, *bcount, *bson;
8178 TLeaf *leaf, *leafcount;
8179
8180 Int_t i,j;
8181 Int_t nleaves = fLeaves.GetEntriesFast();
8182 TRegexp re(bname,kTRUE);
8183 Int_t nb = 0;
8184
8185 // first pass, loop on all branches
8186 // for leafcount branches activate/deactivate in function of status
8187 for (i=0;i<nleaves;i++) {
8188 leaf = (TLeaf*)fLeaves.UncheckedAt(i);
8189 branch = (TBranch*)leaf->GetBranch();
8190 TString s = branch->GetName();
8191 if (strcmp(bname,"*")) { //Regexp gives wrong result for [] in name
8192 TString longname;
8193 longname.Form("%s.%s",GetName(),branch->GetName());
8194 if (strcmp(bname,branch->GetName())
8195 && longname != bname
8196 && s.Index(re) == kNPOS) continue;
8197 }
8198 nb++;
8199 if (status) branch->ResetBit(kDoNotProcess);
8200 else branch->SetBit(kDoNotProcess);
8201 leafcount = leaf->GetLeafCount();
8202 if (leafcount) {
8203 bcount = leafcount->GetBranch();
8204 if (status) bcount->ResetBit(kDoNotProcess);
8205 else bcount->SetBit(kDoNotProcess);
8206 }
8207 }
8208 if (nb==0 && strchr(bname,'*')==0) {
8209 branch = GetBranch(bname);
8210 if (branch) {
8211 if (status) branch->ResetBit(kDoNotProcess);
8212 else branch->SetBit(kDoNotProcess);
8213 ++nb;
8214 }
8215 }
8216
8217 //search in list of friends
8218 UInt_t foundInFriend = 0;
8219 if (fFriends) {
8220 TFriendLock lock(this,kSetBranchStatus);
8221 TIter nextf(fFriends);
8222 TFriendElement *fe;
8223 TString name;
8224 while ((fe = (TFriendElement*)nextf())) {
8225 TTree *t = fe->GetTree();
8226 if (t==0) continue;
8227
8228 // If the alias is present replace it with the real name.
8229 char *subbranch = (char*)strstr(bname,fe->GetName());
8230 if (subbranch!=bname) subbranch = 0;
8231 if (subbranch) {
8232 subbranch += strlen(fe->GetName());
8233 if ( *subbranch != '.' ) subbranch = 0;
8234 else subbranch ++;
8235 }
8236 if (subbranch) {
8237 name.Form("%s.%s",t->GetName(),subbranch);
8238 } else {
8239 name = bname;
8240 }
8241 t->SetBranchStatus(name,status, &foundInFriend);
8242 }
8243 }
8244 if (!nb && !foundInFriend) {
8245 if (found==0) {
8246 if (status) {
8247 if (strchr(bname,'*') != 0)
8248 Error("SetBranchStatus", "No branch name is matching wildcard -> %s", bname);
8249 else
8250 Error("SetBranchStatus", "unknown branch -> %s", bname);
8251 } else {
8252 if (strchr(bname,'*') != 0)
8253 Warning("SetBranchStatus", "No branch name is matching wildcard -> %s", bname);
8254 else
8255 Warning("SetBranchStatus", "unknown branch -> %s", bname);
8256 }
8257 }
8258 return;
8259 }
8260 if (found) *found = nb + foundInFriend;
8261
8262 // second pass, loop again on all branches
8263 // activate leafcount branches for active branches only
8264 for (i = 0; i < nleaves; i++) {
8265 leaf = (TLeaf*)fLeaves.UncheckedAt(i);
8266 branch = (TBranch*)leaf->GetBranch();
8267 if (!branch->TestBit(kDoNotProcess)) {
8268 leafcount = leaf->GetLeafCount();
8269 if (leafcount) {
8270 bcount = leafcount->GetBranch();
8271 bcount->ResetBit(kDoNotProcess);
8272 }
8273 } else {
8274 //Int_t nbranches = branch->GetListOfBranches()->GetEntriesFast();
8275 Int_t nbranches = branch->GetListOfBranches()->GetEntries();
8276 for (j=0;j<nbranches;j++) {
8277 bson = (TBranch*)branch->GetListOfBranches()->UncheckedAt(j);
8278 if (!bson) continue;
8279 if (!bson->TestBit(kDoNotProcess)) {
8280 if (bson->GetNleaves() <= 0) continue;
8281 branch->ResetBit(kDoNotProcess);
8282 break;
8283 }
8284 }
8285 }
8286 }
8287}
8288
8289////////////////////////////////////////////////////////////////////////////////
8290/// Set the current branch style. (static function)
8291///
8292/// - style = 0 old Branch
8293/// - style = 1 new Bronch
8296{
8298}
8299
8300////////////////////////////////////////////////////////////////////////////////
8301/// Set maximum size of the file cache .
8302//
8303/// - if cachesize = 0 the existing cache (if any) is deleted.
8304/// - if cachesize = -1 (default) it is set to the AutoFlush value when writing
8305/// the Tree (default is 30 MBytes).
8306///
8307/// Returns:
8308/// - 0 size set, cache was created if possible
8309/// - -1 on error
8312{
8313 // remember that the user has requested an explicit cache setup
8315
8316 return SetCacheSizeAux(kFALSE, cacheSize);
8317}
8318
8319////////////////////////////////////////////////////////////////////////////////
8320/// Set the size of the file cache and create it if possible.
8321///
8322/// If autocache is true:
8323/// this may be an autocreated cache, possibly enlarging an existing
8324/// autocreated cache. The size is calculated. The value passed in cacheSize:
8325/// - cacheSize = 0 make cache if default cache creation is enabled
8326/// - cacheSize = -1 make a default sized cache in any case
8327///
8328/// If autocache is false:
8329/// this is a user requested cache. cacheSize is used to size the cache.
8330/// This cache should never be automatically adjusted.
8331///
8332/// Returns:
8333/// - 0 size set, or existing autosized cache almost large enough.
8334/// (cache was created if possible)
8335/// - -1 on error
8337Int_t TTree::SetCacheSizeAux(Bool_t autocache /* = kTRUE */, Long64_t cacheSize /* = 0 */ )
8338{
8339 if (autocache) {
8340 // used as a once only control for automatic cache setup
8342 }
8343
8344 if (!autocache) {
8345 // negative size means the user requests the default
8346 if (cacheSize < 0) {
8347 cacheSize = GetCacheAutoSize(kTRUE);
8348 }
8349 } else {
8350 if (cacheSize == 0) {
8351 cacheSize = GetCacheAutoSize();
8352 } else if (cacheSize < 0) {
8353 cacheSize = GetCacheAutoSize(kTRUE);
8354 }
8355 }
8356
8358 if (!file || GetTree() != this) {
8359 // if there's no file or we are not a plain tree (e.g. if we're a TChain)
8360 // do not create a cache, only record the size if one was given
8361 if (!autocache) {
8362 fCacheSize = cacheSize;
8363 }
8364 if (GetTree() != this) {
8365 return 0;
8366 }
8367 if (!autocache && cacheSize>0) {
8368 Warning("SetCacheSizeAux", "A TTreeCache could not be created because the TTree has no file");
8369 }
8370 return 0;
8371 }
8372
8373 // Check for an existing cache
8375 if (pf) {
8376 if (autocache) {
8377 // reset our cache status tracking in case existing cache was added
8378 // by the user without using one of the TTree methods
8379 fCacheSize = pf->GetBufferSize();
8381
8382 if (fCacheUserSet) {
8383 // existing cache was created by the user, don't change it
8384 return 0;
8385 }
8386 } else {
8387 // update the cache to ensure it records the user has explicitly
8388 // requested it
8390 }
8391
8392 // if we're using an automatically calculated size and the existing
8393 // cache is already almost large enough don't resize
8394 if (autocache && Long64_t(0.80*cacheSize) < fCacheSize) {
8395 // already large enough
8396 return 0;
8397 }
8398
8399 if (cacheSize == fCacheSize) {
8400 return 0;
8401 }
8402
8403 if (cacheSize == 0) {
8404 // delete existing cache
8405 pf->WaitFinishPrefetch();
8406 file->SetCacheRead(0,this);
8407 delete pf;
8408 pf = 0;
8409 } else {
8410 // resize
8411 Int_t res = pf->SetBufferSize(cacheSize);
8412 if (res < 0) {
8413 return -1;
8414 }
8415 }
8416 } else {
8417 // no existing cache
8418 if (autocache) {
8419 if (fCacheUserSet) {
8420 // value was already set manually.
8421 if (fCacheSize == 0) return 0;
8422 // Expected a cache should exist; perhaps the user moved it
8423 // Do nothing more here.
8424 if (cacheSize) {
8425 Error("SetCacheSizeAux", "Not setting up an automatically sized TTreeCache because of missing cache previously set");
8426 }
8427 return -1;
8428 }
8429 }
8430 }
8431
8432 fCacheSize = cacheSize;
8433 if (cacheSize == 0 || pf) {
8434 return 0;
8435 }
8436
8437#ifdef R__USE_IMT
8438 if(TTreeCacheUnzip::IsParallelUnzip() && file->GetCompressionLevel() > 0)
8439 pf = new TTreeCacheUnzip(this, cacheSize);
8440 else
8441#endif
8442 pf = new TTreeCache(this, cacheSize);
8443
8444 pf->SetAutoCreated(autocache);
8445
8446 return 0;
8447}
8448
8449////////////////////////////////////////////////////////////////////////////////
8450///interface to TTreeCache to set the cache entry range
8451///
8452/// Returns:
8453/// - 0 entry range set
8454/// - -1 on error
8457{
8458 if (!GetTree()) {
8459 if (LoadTree(0)<0) {
8460 Error("SetCacheEntryRange","Could not load a tree");
8461 return -1;
8462 }
8463 }
8464 if (GetTree()) {
8465 if (GetTree() != this) {
8466 return GetTree()->SetCacheEntryRange(first, last);
8467 }
8468 } else {
8469 Error("SetCacheEntryRange", "No tree is available. Could not set cache entry range");
8470 return -1;
8471 }
8472
8473 TFile *f = GetCurrentFile();
8474 if (!f) {
8475 Error("SetCacheEntryRange", "No file is available. Could not set cache entry range");
8476 return -1;
8477 }
8479 if (!tc) {
8480 Error("SetCacheEntryRange", "No cache is available. Could not set entry range");
8481 return -1;
8482 }
8483 tc->SetEntryRange(first,last);
8484 return 0;
8485}
8486
8487////////////////////////////////////////////////////////////////////////////////
8488/// Interface to TTreeCache to set the number of entries for the learning phase
8491{
8493}
8494
8495////////////////////////////////////////////////////////////////////////////////
8496/// Enable/Disable circularity for this tree.
8497///
8498/// if maxEntries > 0 a maximum of maxEntries is kept in one buffer/basket
8499/// per branch in memory.
8500/// Note that when this function is called (maxEntries>0) the Tree
8501/// must be empty or having only one basket per branch.
8502/// if maxEntries <= 0 the tree circularity is disabled.
8503///
8504/// #### NOTE 1:
8505/// Circular Trees are interesting in online real time environments
8506/// to store the results of the last maxEntries events.
8507/// #### NOTE 2:
8508/// Calling SetCircular with maxEntries <= 0 is necessary before
8509/// merging circular Trees that have been saved on files.
8510/// #### NOTE 3:
8511/// SetCircular with maxEntries <= 0 is automatically called
8512/// by TChain::Merge
8513/// #### NOTE 4:
8514/// A circular Tree can still be saved in a file. When read back,
8515/// it is still a circular Tree and can be filled again.
8517void TTree::SetCircular(Long64_t maxEntries)
8518{
8519 if (maxEntries <= 0) {
8520 // Disable circularity.
8521 fMaxEntries = 1000000000;
8522 fMaxEntries *= 1000;
8524 //in case the Tree was originally created in gROOT, the branch
8525 //compression level was set to -1. If the Tree is now associated to
8526 //a file, reset the compression level to the file compression level
8527 if (fDirectory) {
8528 TFile* bfile = fDirectory->GetFile();
8530 if (bfile) {
8531 compress = bfile->GetCompressionSettings();
8532 }
8534 for (Int_t i = 0; i < nb; i++) {
8535 TBranch* branch = (TBranch*) fBranches.UncheckedAt(i);
8536 branch->SetCompressionSettings(compress);
8537 }
8538 }
8539 } else {
8540 // Enable circularity.
8541 fMaxEntries = maxEntries;
8543 }
8544}
8545
8546////////////////////////////////////////////////////////////////////////////////
8547/// Set the debug level and the debug range.
8548///
8549/// For entries in the debug range, the functions TBranchElement::Fill
8550/// and TBranchElement::GetEntry will print the number of bytes filled
8551/// or read for each branch.
8553void TTree::SetDebug(Int_t level, Long64_t min, Long64_t max)
8554{
8555 fDebug = level;
8556 fDebugMin = min;
8557 fDebugMax = max;
8558}
8559
8560////////////////////////////////////////////////////////////////////////////////
8561/// Update the default value for the branch's fEntryOffsetLen.
8562/// If updateExisting is true, also update all the existing branches.
8563/// If newdefault is less than 10, the new default value will be 10.
8565void TTree::SetDefaultEntryOffsetLen(Int_t newdefault, Bool_t updateExisting)
8566{
8567 if (newdefault < 10) {
8568 newdefault = 10;
8569 }
8570 fDefaultEntryOffsetLen = newdefault;
8571 if (updateExisting) {
8572 TIter next( GetListOfBranches() );
8573 TBranch *b;
8574 while ( ( b = (TBranch*)next() ) ) {
8575 b->SetEntryOffsetLen( newdefault, kTRUE );
8576 }
8577 if (fBranchRef) {
8578 fBranchRef->SetEntryOffsetLen( newdefault, kTRUE );
8579 }
8580 }
8581}
8582
8583////////////////////////////////////////////////////////////////////////////////
8584/// Change the tree's directory.
8585///
8586/// Remove reference to this tree from current directory and
8587/// add reference to new directory dir. The dir parameter can
8588/// be 0 in which case the tree does not belong to any directory.
8589///
8592{
8593 if (fDirectory == dir) {
8594 return;
8595 }
8596 if (fDirectory) {
8597 fDirectory->Remove(this);
8598
8599 // Delete or move the file cache if it points to this Tree
8601 MoveReadCache(file,dir);
8602 }
8603 fDirectory = dir;
8604 if (fDirectory) {
8605 fDirectory->Append(this);
8606 }
8607 TFile* file = 0;
8608 if (fDirectory) {
8609 file = fDirectory->GetFile();
8610 }
8611 if (fBranchRef) {
8613 }
8614 TBranch* b = 0;
8615 TIter next(GetListOfBranches());
8616 while((b = (TBranch*) next())) {
8617 b->SetFile(file);
8618 }
8619}
8620
8621////////////////////////////////////////////////////////////////////////////////
8622/// Change number of entries in the tree.
8623///
8624/// If n >= 0, set number of entries in the tree = n.
8625///
8626/// If n < 0, set number of entries in the tree to match the
8627/// number of entries in each branch. (default for n is -1)
8628///
8629/// This function should be called only when one fills each branch
8630/// independently via TBranch::Fill without calling TTree::Fill.
8631/// Calling TTree::SetEntries() make sense only if the number of entries
8632/// in each branch is identical, a warning is issued otherwise.
8633/// The function returns the number of entries.
8634///
8637{
8638 // case 1 : force number of entries to n
8639 if (n >= 0) {
8640 fEntries = n;
8641 return n;
8642 }
8643
8644 // case 2; compute the number of entries from the number of entries in the branches
8645 TBranch* b(nullptr), *bMin(nullptr), *bMax(nullptr);
8646 Long64_t nMin = kMaxEntries;
8647 Long64_t nMax = 0;
8648 TIter next(GetListOfBranches());
8649 while((b = (TBranch*) next())){
8650 Long64_t n2 = b->GetEntries();
8651 if (!bMin || n2 < nMin) {
8652 nMin = n2;
8653 bMin = b;
8654 }
8655 if (!bMax || n2 > nMax) {
8656 nMax = n2;
8657 bMax = b;
8658 }
8659 }
8660 if (bMin && nMin != nMax) {
8661 Warning("SetEntries", "Tree branches have different numbers of entries, eg %s has %lld entries while %s has %lld entries.",
8662 bMin->GetName(), nMin, bMax->GetName(), nMax);
8663 }
8664 fEntries = nMax;
8665 return fEntries;
8666}
8667
8668////////////////////////////////////////////////////////////////////////////////
8669/// Set an EntryList
8671void TTree::SetEntryList(TEntryList *enlist, Option_t * /*opt*/)
8672{
8673 if (fEntryList) {
8674 //check if the previous entry list is owned by the tree
8676 delete fEntryList;
8677 }
8678 }
8679 fEventList = 0;
8680 if (!enlist) {
8681 fEntryList = 0;
8682 return;
8683 }
8684 fEntryList = enlist;
8685 fEntryList->SetTree(this);
8686
8687}
8688
8689////////////////////////////////////////////////////////////////////////////////
8690/// This function transfroms the given TEventList into a TEntryList
8691/// The new TEntryList is owned by the TTree and gets deleted when the tree
8692/// is deleted. This TEntryList can be returned by GetEntryList() function.
8694void TTree::SetEventList(TEventList *evlist)
8695{
8696 fEventList = evlist;
8697 if (fEntryList){
8699 TEntryList *tmp = fEntryList;
8700 fEntryList = 0; // Avoid problem with RecursiveRemove.
8701 delete tmp;
8702 } else {
8703 fEntryList = 0;
8704 }
8705 }
8706
8707 if (!evlist) {
8708 fEntryList = 0;
8709 fEventList = 0;
8710 return;
8711 }
8712
8713 fEventList = evlist;
8714 char enlistname[100];
8715 snprintf(enlistname,100, "%s_%s", evlist->GetName(), "entrylist");
8716 fEntryList = new TEntryList(enlistname, evlist->GetTitle());
8717 fEntryList->SetDirectory(0); // We own this.
8718 Int_t nsel = evlist->GetN();
8719 fEntryList->SetTree(this);
8720 Long64_t entry;
8721 for (Int_t i=0; i<nsel; i++){
8722 entry = evlist->GetEntry(i);
8723 fEntryList->Enter(entry);
8724 }
8727}
8728
8729////////////////////////////////////////////////////////////////////////////////
8730/// Set number of entries to estimate variable limits.
8731/// If n is -1, the estimate is set to be the current maximum
8732/// for the tree (i.e. GetEntries() + 1)
8733/// If n is less than -1, the behavior is undefined.
8735void TTree::SetEstimate(Long64_t n /* = 1000000 */)
8736{
8737 if (n == 0) {
8738 n = 10000;
8739 } else if (n < 0) {
8740 n = fEntries - n;
8741 }
8742 fEstimate = n;
8743 GetPlayer();
8744 if (fPlayer) {
8746 }
8747}
8748
8749////////////////////////////////////////////////////////////////////////////////
8750/// Provide the end-user with the ability to enable/disable various experimental
8751/// IO features for this TTree.
8752///
8753/// Returns all the newly-set IO settings.
8756{
8757 // Purposely ignore all unsupported bits; TIOFeatures implementation already warned the user about the
8758 // error of their ways; this is just a safety check.
8759 UChar_t featuresRequested = features.GetFeatures() & static_cast<UChar_t>(TBasket::EIOBits::kSupported);
8760
8761 UChar_t curFeatures = fIOFeatures.GetFeatures();
8762 UChar_t newFeatures = ~curFeatures & featuresRequested;
8763 curFeatures |= newFeatures;
8764 fIOFeatures.Set(curFeatures);
8765
8766 ROOT::TIOFeatures newSettings(newFeatures);
8767 return newSettings;
8768}
8769
8770////////////////////////////////////////////////////////////////////////////////
8771/// Set fFileNumber to number.
8772/// fFileNumber is used by TTree::Fill to set the file name
8773/// for a new file to be created when the current file exceeds fgTreeMaxSize.
8774/// (see TTree::ChangeFile)
8775/// if fFileNumber=10, the new file name will have a suffix "_11",
8776/// ie, fFileNumber is incremented before setting the file name
8778void TTree::SetFileNumber(Int_t number)
8779{
8780 if (fFileNumber < 0) {
8781 Warning("SetFileNumber", "file number must be positive. Set to 0");
8782 fFileNumber = 0;
8783 return;
8784 }
8785 fFileNumber = number;
8786}
8787
8788////////////////////////////////////////////////////////////////////////////////
8789/// Set all the branches in this TTree to be in decomposed object mode
8790/// (also known as MakeClass mode).
8793{
8794 fMakeClass = make;
8795
8797 for (Int_t i = 0; i < nb; ++i) {
8798 TBranch* branch = (TBranch*) fBranches.UncheckedAt(i);
8799 branch->SetMakeClass(make);
8800 }
8801}
8802
8803////////////////////////////////////////////////////////////////////////////////
8804/// Set the maximum size in bytes of a Tree file (static function).
8805/// The default size is 100000000000LL, ie 100 Gigabytes.
8806///
8807/// In TTree::Fill, when the file has a size > fgMaxTreeSize,
8808/// the function closes the current file and starts writing into
8809/// a new file with a name of the style "file_1.root" if the original
8810/// requested file name was "file.root".
8812void TTree::SetMaxTreeSize(Long64_t maxsize)
8813{
8814 fgMaxTreeSize = maxsize;
8815}
8816
8817////////////////////////////////////////////////////////////////////////////////
8818/// Change the name of this tree.
8820void TTree::SetName(const char* name)
8821{
8822 if (gPad) {
8823 gPad->Modified();
8824 }
8825 // Trees are named objects in a THashList.
8826 // We must update hashlists if we change the name.
8827 TFile *file = 0;
8828 TTreeCache *pf = 0;
8829 if (fDirectory) {
8830 fDirectory->Remove(this);
8831 if ((file = GetCurrentFile())) {
8832 pf = GetReadCache(file);
8833 file->SetCacheRead(0,this,TFile::kDoNotDisconnect);
8834 }
8835 }
8836 // This changes our hash value.
8837 fName = name;
8838 if (fDirectory) {
8839 fDirectory->Append(this);
8840 if (pf) {
8841 file->SetCacheRead(pf,this,TFile::kDoNotDisconnect);
8842 }
8843 }
8844}
8845
8846////////////////////////////////////////////////////////////////////////////////
8847/// Change the name and title of this tree.
8849void TTree::SetObject(const char* name, const char* title)
8850{
8851 if (gPad) {
8852 gPad->Modified();
8853 }
8854
8855 // Trees are named objects in a THashList.
8856 // We must update hashlists if we change the name
8857 TFile *file = 0;
8858 TTreeCache *pf = 0;
8859 if (fDirectory) {
8860 fDirectory->Remove(this);
8861 if ((file = GetCurrentFile())) {
8862 pf = GetReadCache(file);
8863 file->SetCacheRead(0,this,TFile::kDoNotDisconnect);
8864 }
8865 }
8866 // This changes our hash value.
8867 fName = name;
8868 fTitle = title;
8869 if (fDirectory) {
8870 fDirectory->Append(this);
8871 if (pf) {
8872 file->SetCacheRead(pf,this,TFile::kDoNotDisconnect);
8873 }
8874 }
8875}
8876
8877////////////////////////////////////////////////////////////////////////////////
8878/// Enable or disable parallel unzipping of Tree buffers.
8880void TTree::SetParallelUnzip(Bool_t opt, Float_t RelSize)
8881{
8884
8885 if (RelSize > 0) {
8887 }
8888
8889}
8890
8891////////////////////////////////////////////////////////////////////////////////
8892/// Set perf stats
8895{
8896 fPerfStats = perf;
8897}
8898
8899////////////////////////////////////////////////////////////////////////////////
8900/// The current TreeIndex is replaced by the new index.
8901/// Note that this function does not delete the previous index.
8902/// This gives the possibility to play with more than one index, e.g.,
8903/// ~~~ {.cpp}
8904/// TVirtualIndex* oldIndex = tree.GetTreeIndex();
8905/// tree.SetTreeIndex(newIndex);
8906/// tree.Draw();
8907/// tree.SetTreeIndex(oldIndex);
8908/// tree.Draw(); etc
8909/// ~~~
8912{
8913 if (fTreeIndex) {
8914 fTreeIndex->SetTree(0);
8915 }
8916 fTreeIndex = index;
8917}
8918
8919////////////////////////////////////////////////////////////////////////////////
8920/// Set tree weight.
8921///
8922/// The weight is used by TTree::Draw to automatically weight each
8923/// selected entry in the resulting histogram.
8924///
8925/// For example the equivalent of:
8926/// ~~~ {.cpp}
8927/// T.Draw("x", "w")
8928/// ~~~
8929/// is:
8930/// ~~~ {.cpp}
8931/// T.SetWeight(w);
8932/// T.Draw("x");
8933/// ~~~
8934/// This function is redefined by TChain::SetWeight. In case of a
8935/// TChain, an option "global" may be specified to set the same weight
8936/// for all trees in the TChain instead of the default behaviour
8937/// using the weights of each tree in the chain (see TChain::SetWeight).
8940{
8941 fWeight = w;
8942}
8943
8944////////////////////////////////////////////////////////////////////////////////
8945/// Print values of all active leaves for entry.
8946///
8947/// - if entry==-1, print current entry (default)
8948/// - if a leaf is an array, a maximum of lenmax elements is printed.
8950void TTree::Show(Long64_t entry, Int_t lenmax)
8951{
8952 if (entry != -1) {
8953 Int_t ret = LoadTree(entry);
8954 if (ret == -2) {
8955 Error("Show()", "Cannot read entry %lld (entry does not exist)", entry);
8956 return;
8957 } else if (ret == -1) {
8958 Error("Show()", "Cannot read entry %lld (I/O error)", entry);
8959 return;
8960 }
8961 ret = GetEntry(entry);
8962 if (ret == -1) {
8963 Error("Show()", "Cannot read entry %lld (I/O error)", entry);
8964 return;
8965 } else if (ret == 0) {
8966 Error("Show()", "Cannot read entry %lld (no data read)", entry);
8967 return;
8968 }
8969 }
8970 printf("======> EVENT:%lld\n", fReadEntry);
8971 TObjArray* leaves = GetListOfLeaves();
8972 Int_t nleaves = leaves->GetEntriesFast();
8973 Int_t ltype;
8974 for (Int_t i = 0; i < nleaves; i++) {
8975 TLeaf* leaf = (TLeaf*) leaves->UncheckedAt(i);
8976 TBranch* branch = leaf->GetBranch();
8977 if (branch->TestBit(kDoNotProcess)) {
8978 continue;
8979 }
8980 Int_t len = leaf->GetLen();
8981 if (len <= 0) {
8982 continue;
8983 }
8984 len = TMath::Min(len, lenmax);
8985 if (leaf->IsA() == TLeafElement::Class()) {
8986 leaf->PrintValue(lenmax);
8987 continue;
8988 }
8989 if (branch->GetListOfBranches()->GetEntriesFast() > 0) {
8990 continue;
8991 }
8992 ltype = 10;
8993 if (leaf->IsA() == TLeafF::Class()) {
8994 ltype = 5;
8995 }
8996 if (leaf->IsA() == TLeafD::Class()) {
8997 ltype = 5;
8998 }
8999 if (leaf->IsA() == TLeafC::Class()) {
9000 len = 1;
9001 ltype = 5;
9002 };
9003 printf(" %-15s = ", leaf->GetName());
9004 for (Int_t l = 0; l < len; l++) {
9005 leaf->PrintValue(l);
9006 if (l == (len - 1)) {
9007 printf("\n");
9008 continue;
9009 }
9010 printf(", ");
9011 if ((l % ltype) == 0) {
9012 printf("\n ");
9013 }
9014 }
9015 }
9016}
9017
9018////////////////////////////////////////////////////////////////////////////////
9019/// Start the TTreeViewer on this tree.
9020///
9021/// - ww is the width of the canvas in pixels
9022/// - wh is the height of the canvas in pixels
9024void TTree::StartViewer()
9025{
9026 GetPlayer();
9027 if (fPlayer) {
9028 fPlayer->StartViewer(600, 400);
9029 }
9030}
9031
9032////////////////////////////////////////////////////////////////////////////////
9033/// Stop the cache learning phase
9034///
9035/// Returns:
9036/// - 0 learning phase stopped or not active
9037/// - -1 on error
9040{
9041 if (!GetTree()) {
9042 if (LoadTree(0)<0) {
9043 Error("StopCacheLearningPhase","Could not load a tree");
9044 return -1;
9045 }
9046 }
9047 if (GetTree()) {
9048 if (GetTree() != this) {
9049 return GetTree()->StopCacheLearningPhase();
9050 }
9051 } else {
9052 Error("StopCacheLearningPhase", "No tree is available. Could not stop cache learning phase");
9053 return -1;
9054 }
9055
9056 TFile *f = GetCurrentFile();
9057 if (!f) {
9058 Error("StopCacheLearningPhase", "No file is available. Could not stop cache learning phase");
9059 return -1;
9060 }
9062 if (!tc) {
9063 Error("StopCacheLearningPhase", "No cache is available. Could not stop learning phase");
9064 return -1;
9065 }
9066 tc->StopLearningPhase();
9067 return 0;
9068}
9069
9070////////////////////////////////////////////////////////////////////////////////
9071/// Set the fTree member for all branches and sub branches.
9074{
9075 Int_t nb = branches.GetEntriesFast();
9076 for (Int_t i = 0; i < nb; ++i) {
9077 TBranch* br = (TBranch*) branches.UncheckedAt(i);
9078 br->SetTree(tree);
9079
9080 Int_t nBaskets = br->GetListOfBaskets()->GetEntries();
9081 Int_t writeBasket = br->GetWriteBasket();
9082 for (Int_t j=writeBasket,n=0;j>=0 && n<nBaskets;--j) {
9083 TBasket *bk = (TBasket*)br->GetListOfBaskets()->UncheckedAt(j);
9084 if (bk) {
9085 tree->IncrementTotalBuffers(bk->GetBufferSize());
9086 ++n;
9087 }
9088 }
9089
9091 }
9092}
9093
9094////////////////////////////////////////////////////////////////////////////////
9095/// Set the fTree member for all friend elements.
9098{
9099 if (frlist) {
9100 TObjLink *lnk = frlist->FirstLink();
9101 while (lnk) {
9102 TFriendElement *elem = (TFriendElement*)lnk->GetObject();
9103 elem->fParentTree = tree;
9104 lnk = lnk->Next();
9105 }
9106 }
9107}
9108
9109////////////////////////////////////////////////////////////////////////////////
9110/// Stream a class object.
9111
9112void TTree::Streamer(TBuffer& b)
9113{
9114 if (b.IsReading()) {
9115 UInt_t R__s, R__c;
9116 if (fDirectory) {
9117 fDirectory->Remove(this);
9118 //delete the file cache if it points to this Tree
9121 }
9122 fDirectory = 0;
9125 Version_t R__v = b.ReadVersion(&R__s, &R__c);
9126 if (R__v > 4) {
9127 b.ReadClassBuffer(TTree::Class(), this, R__v, R__s, R__c);
9128
9129 fBranches.SetOwner(kTRUE); // True needed only for R__v < 19 and most R__v == 19
9130
9131 if (fBranchRef) fBranchRef->SetTree(this);
9134
9135 if (fTreeIndex) {
9136 fTreeIndex->SetTree(this);
9137 }
9138 if (fIndex.fN) {
9139 Warning("Streamer", "Old style index in this tree is deleted. Rebuild the index via TTree::BuildIndex");
9140 fIndex.Set(0);
9141 fIndexValues.Set(0);
9142 }
9143 if (fEstimate <= 10000) {
9144 fEstimate = 1000000;
9145 }
9146
9147 if (fNClusterRange) {
9148 // The I/O allocated just enough memory to hold the
9149 // current set of ranges.
9151 }
9152 if (GetCacheAutoSize() != 0) {
9153 // a cache will be automatically created.
9154 // No need for TTreePlayer::Process to enable the cache
9155 fCacheSize = 0;
9156 } else if (fAutoFlush < 0) {
9157 // If there is no autoflush set, let's keep the cache completely
9158 // disable by default for now.
9160 } else if (fAutoFlush != 0) {
9161 // Estimate the cluster size.
9162 // This will allow TTree::Process to enable the cache.
9163 Long64_t zipBytes = GetZipBytes();
9164 Long64_t totBytes = GetTotBytes();
9165 if (zipBytes != 0) {
9166 fCacheSize = fAutoFlush*(zipBytes/fEntries);
9167 } else if (totBytes != 0) {
9168 fCacheSize = fAutoFlush*(totBytes/fEntries);
9169 } else {
9170 fCacheSize = 30000000;
9171 }
9172 if (fCacheSize >= (INT_MAX / 4)) {
9173 fCacheSize = INT_MAX / 4;
9174 } else if (fCacheSize == 0) {
9175 fCacheSize = 30000000;
9176 }
9177 } else {
9178 fCacheSize = 0;
9179 }
9181 return;
9182 }
9183 //====process old versions before automatic schema evolution
9184 Stat_t djunk;
9185 Int_t ijunk;
9186 TNamed::Streamer(b);
9187 TAttLine::Streamer(b);
9188 TAttFill::Streamer(b);
9189 TAttMarker::Streamer(b);
9190 b >> fScanField;
9191 b >> ijunk; fMaxEntryLoop = (Long64_t)ijunk;
9192 b >> ijunk; fMaxVirtualSize = (Long64_t)ijunk;
9193 b >> djunk; fEntries = (Long64_t)djunk;
9194 b >> djunk; fTotBytes = (Long64_t)djunk;
9195 b >> djunk; fZipBytes = (Long64_t)djunk;
9196 b >> ijunk; fAutoSave = (Long64_t)ijunk;
9197 b >> ijunk; fEstimate = (Long64_t)ijunk;
9198 if (fEstimate <= 10000) fEstimate = 1000000;
9199 fBranches.Streamer(b);
9200 if (fBranchRef) fBranchRef->SetTree(this);
9202 fLeaves.Streamer(b);
9204 if (R__v > 1) fIndexValues.Streamer(b);
9205 if (R__v > 2) fIndex.Streamer(b);
9206 if (R__v > 3) {
9207 TList OldInfoList;
9208 OldInfoList.Streamer(b);
9209 OldInfoList.Delete();
9210 }
9211 fNClusterRange = 0;
9214 b.CheckByteCount(R__s, R__c, TTree::IsA());
9215 //====end of old versions
9216 } else {
9217 if (fBranchRef) {
9218 fBranchRef->Clear();
9219 }
9222
9223 b.WriteClassBuffer(TTree::Class(), this);
9224
9226 }
9227}
9228
9229////////////////////////////////////////////////////////////////////////////////
9230/// Unbinned fit of one or more variable(s) from a tree.
9231///
9232/// funcname is a TF1 function.
9233///
9234/// See TTree::Draw for explanations of the other parameters.
9235///
9236/// Fit the variable varexp using the function funcname using the
9237/// selection cuts given by selection.
9238///
9239/// The list of fit options is given in parameter option.
9240///
9241/// - option = "Q" Quiet mode (minimum printing)
9242/// - option = "V" Verbose mode (default is between Q and V)
9243/// - option = "E" Perform better Errors estimation using Minos technique
9244/// - option = "M" More. Improve fit results
9245///
9246/// You can specify boundary limits for some or all parameters via
9247/// ~~~ {.cpp}
9248/// func->SetParLimits(p_number, parmin, parmax);
9249/// ~~~
9250/// if parmin>=parmax, the parameter is fixed
9251///
9252/// Note that you are not forced to fix the limits for all parameters.
9253/// For example, if you fit a function with 6 parameters, you can do:
9254/// ~~~ {.cpp}
9255/// func->SetParameters(0,3.1,1.e-6,0.1,-8,100);
9256/// func->SetParLimits(4,-10,-4);
9257/// func->SetParLimits(5, 1,1);
9258/// ~~~
9259/// With this setup:
9260///
9261/// - Parameters 0->3 can vary freely
9262/// - Parameter 4 has boundaries [-10,-4] with initial value -8
9263/// - Parameter 5 is fixed to 100.
9264///
9265/// For the fit to be meaningful, the function must be self-normalized.
9266///
9267/// i.e. It must have the same integral regardless of the parameter
9268/// settings. Otherwise the fit will effectively just maximize the
9269/// area.
9270///
9271/// It is mandatory to have a normalization variable
9272/// which is fixed for the fit. e.g.
9273/// ~~~ {.cpp}
9274/// TF1* f1 = new TF1("f1", "gaus(0)/sqrt(2*3.14159)/[2]", 0, 5);
9275/// f1->SetParameters(1, 3.1, 0.01);
9276/// f1->SetParLimits(0, 1, 1); // fix the normalization parameter to 1
9277/// data->UnbinnedFit("f1", "jpsimass", "jpsipt>3.0");
9278/// ~~~
9279/// 1, 2 and 3 Dimensional fits are supported. See also TTree::Fit
9280///
9281/// Return status:
9282///
9283/// - The function return the status of the fit in the following form
9284/// fitResult = migradResult + 10*minosResult + 100*hesseResult + 1000*improveResult
9285/// - The fitResult is 0 is the fit is OK.
9286/// - The fitResult is negative in case of an error not connected with the fit.
9287/// - The number of entries used in the fit can be obtained via mytree.GetSelectedRows();
9288/// - If the number of selected entries is null the function returns -1
9290Int_t TTree::UnbinnedFit(const char* funcname, const char* varexp, const char* selection, Option_t* option, Long64_t nentries, Long64_t firstentry)
9291{
9292 GetPlayer();
9293 if (fPlayer) {
9294 return fPlayer->UnbinnedFit(funcname, varexp, selection, option, nentries, firstentry);
9295 }
9296 return -1;
9297}
9298
9299////////////////////////////////////////////////////////////////////////////////
9300/// Replace current attributes by current style.
9303{
9304 if (gStyle->IsReading()) {
9313 } else {
9322 }
9323}
9324
9325////////////////////////////////////////////////////////////////////////////////
9326/// Write this object to the current directory. For more see TObject::Write
9327/// If option & kFlushBasket, call FlushBasket before writing the tree.
9329Int_t TTree::Write(const char *name, Int_t option, Int_t bufsize) const
9330{
9332 return TObject::Write(name, option, bufsize);
9333}
9334
9335////////////////////////////////////////////////////////////////////////////////
9336/// Write this object to the current directory. For more see TObject::Write
9337/// If option & kFlushBasket, call FlushBasket before writing the tree.
9339Int_t TTree::Write(const char *name, Int_t option, Int_t bufsize)
9340{
9341 return ((const TTree*)this)->Write(name, option, bufsize);
9342}
9343
9344////////////////////////////////////////////////////////////////////////////////
9345/// \class TTreeFriendLeafIter
9346///
9347/// Iterator on all the leaves in a TTree and its friend
9348
9350
9351////////////////////////////////////////////////////////////////////////////////
9352/// Create a new iterator. By default the iteration direction
9353/// is kIterForward. To go backward use kIterBackward.
9356: fTree(const_cast<TTree*>(tree))
9357, fLeafIter(0)
9358, fTreeIter(0)
9359, fDirection(dir)
9360{
9361}
9362
9363////////////////////////////////////////////////////////////////////////////////
9364/// Copy constructor. Does NOT copy the 'cursor' location!
9367: TIterator(iter)
9368, fTree(iter.fTree)
9369, fLeafIter(0)
9370, fTreeIter(0)
9371, fDirection(iter.fDirection)
9372{
9373}
9374
9375////////////////////////////////////////////////////////////////////////////////
9376/// Overridden assignment operator. Does NOT copy the 'cursor' location!
9379{
9380 if (this != &rhs && rhs.IsA() == TTreeFriendLeafIter::Class()) {
9381 const TTreeFriendLeafIter &rhs1 = (const TTreeFriendLeafIter &)rhs;
9382 fDirection = rhs1.fDirection;
9383 }
9384 return *this;
9385}
9386
9387////////////////////////////////////////////////////////////////////////////////
9388/// Overridden assignment operator. Does NOT copy the 'cursor' location!
9391{
9392 if (this != &rhs) {
9393 fDirection = rhs.fDirection;
9394 }
9395 return *this;
9396}
9397
9398////////////////////////////////////////////////////////////////////////////////
9399/// Go the next friend element
9402{
9403 if (!fTree) return 0;
9404
9405 TObject * next;
9406 TTree * nextTree;
9407
9408 if (!fLeafIter) {
9409 TObjArray *list = fTree->GetListOfLeaves();
9410 if (!list) return 0; // Can happen with an empty chain.
9412 if (!fLeafIter) return 0;
9413 }
9414
9415 next = fLeafIter->Next();
9416 if (!next) {
9417 if (!fTreeIter) {
9419 if (!list) return next;
9421 if (!fTreeIter) return 0;
9422 }
9423 TFriendElement * nextFriend = (TFriendElement*) fTreeIter->Next();
9424 ///nextTree = (TTree*)fTreeIter->Next();
9425 if (nextFriend) {
9426 nextTree = const_cast<TTree*>(nextFriend->GetTree());
9427 if (!nextTree) return Next();
9430 if (!fLeafIter) return 0;
9431 next = fLeafIter->Next();
9432 }
9433 }
9434 return next;
9435}
9436
9437////////////////////////////////////////////////////////////////////////////////
9438/// Returns the object option stored in the list.
9441{
9442 if (fLeafIter) return fLeafIter->GetOption();
9443 return "";
9444}
void Class()
Definition: Class.C:29
#define R__unlikely(expr)
Definition: RConfig.hxx:578
#define SafeDelete(p)
Definition: RConfig.hxx:529
#define b(i)
Definition: RSha256.hxx:100
#define f(i)
Definition: RSha256.hxx:104
#define c(i)
Definition: RSha256.hxx:101
const Ssiz_t kNPOS
Definition: RtypesCore.h:111
int Int_t
Definition: RtypesCore.h:41
short Version_t
Definition: RtypesCore.h:61
unsigned char UChar_t
Definition: RtypesCore.h:34
int Ssiz_t
Definition: RtypesCore.h:63
unsigned int UInt_t
Definition: RtypesCore.h:42
const Bool_t kFALSE
Definition: RtypesCore.h:88
long Long_t
Definition: RtypesCore.h:50
bool Bool_t
Definition: RtypesCore.h:59
double Double_t
Definition: RtypesCore.h:55
double Stat_t
Definition: RtypesCore.h:73
long long Long64_t
Definition: RtypesCore.h:69
unsigned long long ULong64_t
Definition: RtypesCore.h:70
float Float_t
Definition: RtypesCore.h:53
const Bool_t kTRUE
Definition: RtypesCore.h:87
const char Option_t
Definition: RtypesCore.h:62
#define ClassImp(name)
Definition: Rtypes.h:363
R__EXTERN Int_t gDebug
Definition: Rtypes.h:90
const Int_t kDoNotProcess
Definition: TBranch.h:52
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:213
R__EXTERN TEnv * gEnv
Definition: TEnv.h:171
#define R__ASSERT(e)
Definition: TError.h:96
static unsigned int total
#define Printf
Definition: TGeoToOCC.h:18
int nentries
Definition: THbookFile.cxx:89
R__EXTERN TInterpreter * gCling
Definition: TInterpreter.h:540
R__EXTERN TVirtualMutex * gROOTMutex
Definition: TROOT.h:57
#define gROOT
Definition: TROOT.h:410
R__EXTERN TStyle * gStyle
Definition: TStyle.h:406
R__EXTERN TSystem * gSystem
Definition: TSystem.h:540
constexpr Int_t kNEntriesResort
Definition: TTree.cxx:417
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:4583
static char DataTypeToChar(EDataType datatype)
Definition: TTree.cxx:429
void TFriendElement__SetTree(TTree *tree, TList *frlist)
Set the fTree member for all friend elements.
Definition: TTree.cxx:9096
static void TBranch__SetTree(TTree *tree, TObjArray &branches)
Set the fTree member for all branches and sub branches.
Definition: TTree.cxx:9072
constexpr Float_t kNEntriesResortInv
Definition: TTree.cxx:418
#define R__LOCKGUARD(mutex)
#define gPad
Definition: TVirtualPad.h:286
#define snprintf
Definition: civetweb.c:1540
Bool_t HasRuleWithSourceClass(const TString &source) const
Return True if we have any rule whose source class is 'source'.
TIOFeatures provides the end-user with the ability to change the IO behavior of data written via a TT...
Definition: TIOFeatures.hxx:62
UChar_t GetFeatures() const
bool Set(EIOFeatures bits)
Set a specific IO feature.
This class provides a simple interface to execute the same task multiple times in parallel,...
void Foreach(F func, unsigned nTimes, unsigned nChunks=0)
Execute func (with no arguments) nTimes in parallel.
void Set(Int_t n)
Set size of this array to n doubles.
Definition: TArrayD.cxx:106
void Set(Int_t n)
Set size of this array to n ints.
Definition: TArrayI.cxx:105
Int_t fN
Definition: TArray.h:38
Fill Area Attributes class.
Definition: TAttFill.h:19
virtual Color_t GetFillColor() const
Return the fill area color.
Definition: TAttFill.h:30
virtual Style_t GetFillStyle() const
Return the fill area style.
Definition: TAttFill.h:31
virtual void SetFillColor(Color_t fcolor)
Set the fill area color.
Definition: TAttFill.h:37
virtual void SetFillStyle(Style_t fstyle)
Set the fill area style.
Definition: TAttFill.h:39
Line Attributes class.
Definition: TAttLine.h:18
virtual Color_t GetLineColor() const
Return the line color.
Definition: TAttLine.h:33
virtual void SetLineStyle(Style_t lstyle)
Set the line style.
Definition: TAttLine.h:42
virtual Width_t GetLineWidth() const
Return the line width.
Definition: TAttLine.h:35
virtual void SetLineWidth(Width_t lwidth)
Set the line width.
Definition: TAttLine.h:43
virtual void SetLineColor(Color_t lcolor)
Set the line color.
Definition: TAttLine.h:40
virtual Style_t GetLineStyle() const
Return the line style.
Definition: TAttLine.h:34
Marker Attributes class.
Definition: TAttMarker.h:19
virtual Style_t GetMarkerStyle() const
Return the marker style.
Definition: TAttMarker.h:32
virtual void SetMarkerColor(Color_t mcolor=1)
Set the marker color.
Definition: TAttMarker.h:38
virtual Color_t GetMarkerColor() const
Return the marker color.
Definition: TAttMarker.h:31
virtual Size_t GetMarkerSize() const
Return the marker size.
Definition: TAttMarker.h:33
virtual void SetMarkerStyle(Style_t mstyle=1)
Set the marker style.
Definition: TAttMarker.h:40
virtual void SetMarkerSize(Size_t msize=1)
Set the marker size.
Definition: TAttMarker.h:41
Each class (see TClass) has a linked list of its base class(es).
Definition: TBaseClass.h:33
ROOT::ESTLType IsSTLContainer()
Return which type (if any) of STL container the data member is.
Definition: TBaseClass.cxx:101
Manages buffers for branches of a Tree.
Definition: TBasket.h:34
virtual Int_t DropBuffers()
Drop buffers of this basket if it is not the current basket.
Definition: TBasket.cxx:169
Int_t GetBufferSize() const
Definition: TBasket.h:115
A Branch for the case of an array of clone objects.
Definition: TBranchClones.h:29
A Branch for the case of an object.
virtual void ResetAddress()
Set branch address to zero and free all allocated memory.
virtual void SetBranchFolder()
Int_t GetClassVersion()
virtual const char * GetClassName() const
Return the name of the user class whose content is stored in this branch, if any.
virtual Bool_t IsObjectOwner() const
virtual void SetObject(void *objadd)
Set object this branch is pointing to.
virtual void SetAddress(void *addobj)
Point this branch at an object.
Int_t Unroll(const char *name, TClass *cltop, TClass *cl, char *ptr, Int_t basketsize, Int_t splitlevel, Int_t btype)
Split class cl into sub-branches of this branch.
virtual void SetTargetClass(const char *name)
Set the name of the class of the in-memory object into which the data will loaded.
UInt_t GetCheckSum()
A Branch for the case of an object.
Definition: TBranchObject.h:26
A branch containing and managing a TRefTable for TRef autoloading.
Definition: TBranchRef.h:29
virtual void ResetAfterMerge(TFileMergeInfo *)
Reset a Branch after a Merge operation (drop data but keep customizations) TRefTable is cleared.
Definition: TBranchRef.cxx:198
virtual void Reset(Option_t *option="")
Definition: TBranchRef.cxx:187
virtual void Clear(Option_t *option="")
Clear entries in the TRefTable.
Definition: TBranchRef.cxx:95
virtual void Print(Option_t *option="") const
Print the TRefTable branch.
Definition: TBranchRef.cxx:159
A Branch handling STL collection of pointers (vectors, lists, queues, sets and multisets) while stori...
Definition: TBranchSTL.h:22
A TTree is a list of TBranches.
Definition: TBranch.h:64
virtual TLeaf * GetLeaf(const char *name) const
Return pointer to the 1st Leaf named name in thisBranch.
Definition: TBranch.cxx:1652
virtual void SetupAddresses()
If the branch address is not set, we set all addresses starting with the top level parent branch.
Definition: TBranch.cxx:2873
virtual void ResetAddress()
Reset the address of the branch.
Definition: TBranch.cxx:2234
virtual Long64_t GetBasketSeek(Int_t basket) const
Return address of basket in the file.
Definition: TBranch.cxx:1260
virtual char * GetAddress() const
Definition: TBranch.h:171
TTree * GetTree() const
Definition: TBranch.h:209
Int_t GetWriteBasket() const
Definition: TBranch.h:195
virtual void DropBaskets(Option_t *option="")
Loop on all branch baskets.
Definition: TBranch.cxx:719
TObjArray * GetListOfBranches()
Definition: TBranch.h:203
virtual void SetTree(TTree *tree)
Definition: TBranch.h:244
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:2404
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:1317
static void ResetCount()
Static function resetting fgCount.
Definition: TBranch.cxx:2257
virtual void SetObject(void *objadd)
Set object this branch is pointing to.
Definition: TBranch.cxx:2519
Int_t FlushBaskets()
Flush to disk all the baskets of this branch and any of subbranches.
Definition: TBranch.cxx:1097
virtual void SetAddress(void *add)
Set address of this branch.
Definition: TBranch.cxx:2265
Int_t GetNleaves() const
Definition: TBranch.h:206
TObjArray * GetListOfBaskets()
Definition: TBranch.h:202
Long64_t GetEntries() const
Definition: TBranch.h:208
virtual void UpdateFile()
Refresh the value of fDirectory (i.e.
Definition: TBranch.cxx:2883
void SetCompressionSettings(Int_t settings=ROOT::RCompressionSetting::EDefaults::kUseGeneralPurpose)
Set compression settings.
Definition: TBranch.cxx:2388
Int_t GetReadBasket() const
Definition: TBranch.h:193
virtual void Print(Option_t *option="") const
Print TBranch parameters.
Definition: TBranch.cxx:1924
Int_t GetMaxBaskets() const
Definition: TBranch.h:205
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:1508
virtual void KeepCircular(Long64_t maxEntries)
keep a maximum of fMaxEntries in memory
Definition: TBranch.cxx:1866
virtual void ResetAfterMerge(TFileMergeInfo *)
Reset a Branch.
Definition: TBranch.cxx:2181
virtual TBranch * FindBranch(const char *name)
Find the immediate sub-branch with passed name.
Definition: TBranch.cxx:996
virtual Int_t LoadBaskets()
Baskets associated to this branch are forced to be in memory.
Definition: TBranch.cxx:1892
void SetIOFeatures(TIOFeatures &features)
Definition: TBranch.h:240
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:1803
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:2510
virtual void SetFile(TFile *file=0)
Set file where this branch writes/reads its buffers.
Definition: TBranch.cxx:2446
virtual void SetOffset(Int_t offset=0)
Definition: TBranch.h:242
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:1489
virtual Int_t GetBasketSize() const
Definition: TBranch.h:176
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:1821
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:2312
virtual void Refresh(TBranch *b)
Refresh this branch using new information in b This function is called by TTree::Refresh.
Definition: TBranch.cxx:2091
TObjArray * GetListOfLeaves()
Definition: TBranch.h:204
Int_t Fill()
Definition: TBranch.h:164
virtual void Reset(Option_t *option="")
Reset a Branch.
Definition: TBranch.cxx:2140
TBranch * GetMother() const
Get our top-level parent branch in the tree.
Definition: TBranch.cxx:1725
virtual Int_t FillImpl(ROOT::Internal::TBranchIMTHelper *)
Loop on all leaves of this branch to fill Basket buffer.
Definition: TBranch.cxx:818
Int_t GetEntryOffsetLen() const
Definition: TBranch.h:185
Using a TBrowser one can browse all ROOT objects.
Definition: TBrowser.h:37
The concrete implementation of TBuffer for writing/reading to/from a ROOT file or socket.
Definition: TBufferFile.h:46
Buffer base class used for serializing objects.
Definition: TBuffer.h:40
void Expand(Int_t newsize, Bool_t copy=kTRUE)
Expand (or shrink) the I/O buffer to newsize bytes.
Definition: TBuffer.cxx:211
Int_t BufferSize() const
Definition: TBuffer.h:94
@ kWrite
Definition: TBuffer.h:70
@ kRead
Definition: TBuffer.h:70
The ROOT global object gROOT contains a list of all defined classes.
Definition: TClass.h:75
TVirtualStreamerInfo * GetStreamerInfo(Int_t version=0) const
returns a pointer to the TVirtualStreamerInfo object for version If the object does not exist,...
Definition: TClass.cxx:4452
Bool_t CanSplit() const
Return true if the data member of this TClass can be saved separately.
Definition: TClass.cxx:2229
ROOT::ESTLType GetCollectionType() const
Return the 'type' of the STL the TClass is representing.
Definition: TClass.cxx:2803
void * New(ENewType defConstructor=kClassNew, Bool_t quiet=kFALSE) const
Return a pointer to a newly allocated object of this class.
Definition: TClass.cxx:4824
Bool_t HasDataMemberInfo() const
Definition: TClass.h:378
void BuildRealData(void *pointer=0, Bool_t isTransient=kFALSE)
Build a full list of persistent data members.
Definition: TClass.cxx:1940
void Destructor(void *obj, Bool_t dtorOnly=kFALSE)
Explicitly call destructor for object.
Definition: TClass.cxx:5181
const std::type_info * GetTypeInfo() const
Definition: TClass.h:466
TList * GetListOfDataMembers(Bool_t load=kTRUE)
Return list containing the TDataMembers of a class.
Definition: TClass.cxx:3615
TList * GetListOfRealData() const
Definition: TClass.h:423
Bool_t CanIgnoreTObjectStreamer()
Definition: TClass.h:365
const ROOT::Detail::TSchemaRuleSet * GetSchemaRules() const
Return the set of the schema rules if any.
Definition: TClass.cxx:1841
TList * GetListOfBases()
Return list containing the TBaseClass(es) of a class.
Definition: TClass.cxx:3505
Bool_t IsLoaded() const
Return true if the shared library of this class is currently in the a process's memory.
Definition: TClass.cxx:5674
Bool_t IsTObject() const
Return kTRUE is the class inherits from TObject.
Definition: TClass.cxx:5700
TVirtualCollectionProxy * GetCollectionProxy() const
Return the proxy describing the collection (if any).
Definition: TClass.cxx:2814
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:6793
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:6890
Version_t GetClassVersion() const
Definition: TClass.h:391
Bool_t InheritsFrom(const char *cl) const
Return kTRUE if this class inherits from a class with name "classname".
Definition: TClass.cxx:4720
TClass * GetActualClass(const void *object) const
Return a pointer the the real class of the object.
Definition: TClass.cxx:2525
@ kHasCustomStreamerMember
Definition: TClass.h:99
static TClass * GetClass(const char *name, Bool_t load=kTRUE, Bool_t silent=kFALSE)
Static method returning pointer to TClass of the specified class name.
Definition: TClass.cxx:2885
An array of clone (identical) objects.
Definition: TClonesArray.h:32
void BypassStreamer(Bool_t bypass=kTRUE)
When the kBypassStreamer bit is set, the automatically generated Streamer can call directly TClass::W...
TClass * GetClass() const
Definition: TClonesArray.h:56
Collection abstract base class.
Definition: TCollection.h:63
virtual TObject ** GetObjectRef(const TObject *obj) const =0
virtual TIterator * MakeIterator(Bool_t dir=kIterForward) const =0
virtual const char * GetName() const
Return name of this collection.
void SetName(const char *name)
Definition: TCollection.h:204
void Browse(TBrowser *b)
Browse this collection (called by TBrowser).
virtual Int_t GetEntries() const
Definition: TCollection.h:177
virtual void SetOwner(Bool_t enable=kTRUE)
Set whether this collection is the owner (enable==true) of its content.
A specialized string object used for TTree selections.
Definition: TCut.h:25
All ROOT classes may have RTTI (run time type identification) support added.
Definition: TDataMember.h:31
Bool_t IsPersistent() const
Definition: TDataMember.h:89
Long_t GetOffset() const
Get offset from "this".
Bool_t IsBasic() const
Return true if data member is a basic type, e.g. char, int, long...
Bool_t IsaPointer() const
Return true if data member is a pointer.
TDataType * GetDataType() const
Definition: TDataMember.h:74
const char * GetTypeName() const
Get type of data member, e,g.: "class TDirectory*" -> "TDirectory".
const char * GetArrayIndex() const
If the data member is pointer and has a valid array size in its comments GetArrayIndex returns a stri...
const char * GetFullTypeName() const
Get full type description of data member, e,g.: "class TDirectory*".
Basic data type descriptor (datatype information is obtained from CINT).
Definition: TDataType.h:44
Int_t GetType() const
Definition: TDataType.h:68
TString GetTypeName()
Get basic type of typedef, e,g.
Definition: TDataType.cxx:149
virtual void Append(TObject *obj, Bool_t replace=kFALSE)
Append object to this directory.
Describe directory structure in memory.
Definition: TDirectory.h:34
virtual TList * GetList() const
Definition: TDirectory.h:149
virtual Bool_t cd(const char *path=0)
Change current directory to "this" directory.
Definition: TDirectory.cxx:497
virtual void Append(TObject *obj, Bool_t replace=kFALSE)
Append object to this directory.
Definition: TDirectory.cxx:190
virtual TFile * GetFile() const
Definition: TDirectory.h:147
virtual Int_t ReadKeys(Bool_t=kTRUE)
Definition: TDirectory.h:174
virtual Int_t WriteTObject(const TObject *obj, const char *name=0, Option_t *="", Int_t=0)
See TDirectoryFile::WriteTObject for details.
virtual Bool_t IsWritable() const
Definition: TDirectory.h:163
virtual TKey * GetKey(const char *, Short_t=9999) const
Definition: TDirectory.h:148
virtual Int_t ReadTObject(TObject *, const char *)
Definition: TDirectory.h:175
virtual void SaveSelf(Bool_t=kFALSE)
Definition: TDirectory.h:181
virtual TList * GetListOfKeys() const
Definition: TDirectory.h:150
void GetObject(const char *namecycle, T *&ptr)
Definition: TDirectory.h:139
virtual TObject * Remove(TObject *)
Remove an object from the in-memory list.
Streamer around an arbitrary STL like container, which implements basic container functionality.
A List of entry numbers in a TTree or TChain.
Definition: TEntryList.h:26
virtual void SetReapplyCut(Bool_t apply=kFALSE)
Definition: TEntryList.h:105
virtual void SetTree(const TTree *tree)
If a list for a tree with such name and filename exists, sets it as the current sublist If not,...
virtual TDirectory * GetDirectory() const
Definition: TEntryList.h:74
virtual void SetDirectory(TDirectory *dir)
Add reference to directory dir. dir can be 0.
virtual Bool_t Enter(Long64_t entry, TTree *tree=0)
Add entry #entry to the list.
Definition: TEntryList.cxx:558
virtual Long64_t GetEntry(Int_t index)
Return the number of the entry #index of this TEntryList in the TTree or TChain See also Next().
Definition: TEntryList.cxx:653
virtual Int_t GetValue(const char *name, Int_t dflt) const
Returns the integer value for a resource.
Definition: TEnv.cxx:491
A TEventList object is a list of selected events (entries) in a TTree.
Definition: TEventList.h:31
virtual Long64_t GetEntry(Int_t index) const
Return value of entry at index in the list.
Definition: TEventList.cxx:222
virtual Int_t GetN() const
Definition: TEventList.h:56
virtual Bool_t GetReapplyCut() const
Definition: TEventList.h:57
A cache when reading files over the network.
virtual void WaitFinishPrefetch()
virtual Int_t GetBufferSize() const
TIOFeatures * fIOFeatures
TDirectory * fOutputDirectory
A ROOT file is a suite of consecutive data records (TKey instances) with a well defined format.
Definition: TFile.h:48
Int_t GetCompressionSettings() const
Definition: TFile.h:391
virtual Long64_t GetEND() const
Definition: TFile.h:215
@ kDoNotDisconnect
Definition: TFile.h:65
virtual void Flush()
Synchronize a file's in-memory and on-disk states.
Definition: TFile.cxx:1094
virtual void MakeFree(Long64_t first, Long64_t last)
Mark unused bytes on the file.
Definition: TFile.cxx:1433
static TFile * Open(const char *name, Option_t *option="", const char *ftitle="", Int_t compress=ROOT::RCompressionSetting::EDefaults::kUseGeneralPurpose, Int_t netopt=0)
Create / open a file.
Definition: TFile.cxx:3975
virtual void SetCacheRead(TFileCacheRead *cache, TObject *tree=0, ECacheAction action=kDisconnect)
Set a pointer to the read cache.
Definition: TFile.cxx:2264
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:1252
A TFolder object is a collection of objects and folders.
Definition: TFolder.h:30
TCollection * GetListOfFolders() const
Definition: TFolder.h:55
virtual Int_t Occurence(const TObject *obj) const
Return occurence number of object in the list of objects of this folder.
Definition: TFolder.cxx:436
A TFriendElement TF describes a TTree object TF in a file.
virtual const char * GetTreeName() const
virtual TTree * GetTree()
Return pointer to friend TTree.
virtual TFile * GetFile()
Return pointer to TFile containing this friend TTree.
TTree * fParentTree
! pointer to the parent TTree
virtual Int_t DeleteGlobal(void *obj)=0
void Reset()
Definition: TCollection.h:252
Iterator abstract base class.
Definition: TIterator.h:30
virtual TObject * Next()=0
virtual Option_t * GetOption() const
Definition: TIterator.h:40
Book space in a file, create I/O buffers, to fill them, (un)compress them.
Definition: TKey.h:24
virtual void Delete(Option_t *option="")
Delete an object from the file.
Definition: TKey.cxx:534
Int_t GetKeylen() const
Definition: TKey.h:80
Int_t GetNbytes() const
Definition: TKey.h:82
A TLeaf describes individual elements of a TBranch See TBranch structure in TTree.
Definition: TLeaf.h:32
virtual Double_t GetValue(Int_t i=0) const
Definition: TLeaf.h:135
virtual void * GetValuePointer() const
Definition: TLeaf.h:92
virtual Int_t GetLenType() const
Definition: TLeaf.h:87
virtual void ReadValue(std::istream &, Char_t=' ')
Definition: TLeaf.h:108
virtual Int_t GetMaximum() const
Definition: TLeaf.h:88
virtual Int_t GetLen() const
Return the number of effective elements of this leaf, for the current entry.
Definition: TLeaf.cxx:311
virtual TLeaf * GetLeafCount() const
If this leaf stores a variable-sized array or a multi-dimensional array whose last dimension has vari...
Definition: TLeaf.h:78
virtual Bool_t IncludeRange(TLeaf *)
Definition: TLeaf.h:100
virtual void SetAddress(void *add=0)
Definition: TLeaf.h:137
TBranch * GetBranch() const
Definition: TLeaf.h:75
@ kNewValue
Set if we own the value buffer and so must delete it ourselves.
Definition: TLeaf.h:63
@ kIndirectAddress
Data member is a pointer to an array of basic types.
Definition: TLeaf.h:62
virtual Int_t GetOffset() const
Definition: TLeaf.h:91
virtual void PrintValue(Int_t i=0) const
Definition: TLeaf.h:136
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:818
virtual TObject * FindObject(const char *name) const
Delete a TObjLink object.
Definition: TList.cxx:574
virtual TObjLink * FirstLink() const
Definition: TList.h:108
virtual TObject * At(Int_t idx) const
Returns the object at position idx. Returns 0 if idx is out of range.
Definition: TList.cxx:354
virtual void RecursiveRemove(TObject *obj)
Remove object from this collection and recursively remove the object from all other objects (and coll...
Definition: TList.cxx:760
virtual void Delete(Option_t *option="")
Remove all objects from the list AND delete all heap based objects.
Definition: TList.cxx:467
The TNamed class is the base class for all named ROOT classes.
Definition: TNamed.h:29
virtual void SetTitle(const char *title="")
Set the title of the TNamed.
Definition: TNamed.cxx:164
TString fTitle
Definition: TNamed.h:33
TNamed()
Definition: TNamed.h:36
TString fName
Definition: TNamed.h:32
virtual void SetName(const char *name)
Set the name of the TNamed.
Definition: TNamed.cxx:140
virtual const char * GetTitle() const
Returns title of object.
Definition: TNamed.h:48
virtual TObject * Clone(const char *newname="") const
Make a clone of an object using the Streamer facility.
Definition: TNamed.cxx:74
virtual const char * GetName() const
Returns name of object.
Definition: TNamed.h:47
An array of TObjects.
Definition: TObjArray.h:37
Int_t GetEntriesFast() const
Definition: TObjArray.h:64
void Add(TObject *obj)
Definition: TObjArray.h:73
TObject * Last() const
Return the object in the last filled slot. Returns 0 if no entries.
Definition: TObjArray.cxx:505
virtual void Compress()
Remove empty slots from array.
Definition: TObjArray.cxx:333
Int_t GetEntries() const
Return the number of objects in array (i.e.
Definition: TObjArray.cxx:522
virtual void Clear(Option_t *option="")
Remove all objects from the array.
Definition: TObjArray.cxx:320
TObject * UncheckedAt(Int_t i) const
Definition: TObjArray.h:89
virtual void Delete(Option_t *option="")
Remove all objects from the array AND delete all heap based objects.
Definition: TObjArray.cxx:355
TIterator * MakeIterator(Bool_t dir=kIterForward) const
Returns an array iterator.
Definition: TObjArray.cxx:633
virtual TObject * RemoveAt(Int_t idx)
Remove object at index idx.
Definition: TObjArray.cxx:678
TObject * At(Int_t idx) const
Definition: TObjArray.h:165
Mother of all ROOT objects.
Definition: TObject.h:37
virtual Bool_t Notify()
This method must be overridden to handle object notification.
Definition: TObject.cxx:506
virtual Int_t Write(const char *name=0, Int_t option=0, Int_t bufsize=0)
Write this object to the current directory.
Definition: TObject.cxx:785
@ kBitMask
Definition: TObject.h:82
virtual const char * GetName() const
Returns name of object.
Definition: TObject.cxx:357
R__ALWAYS_INLINE Bool_t TestBit(UInt_t f) const
Definition: TObject.h:172
virtual const char * ClassName() const
Returns name of class to which the object belongs.
Definition: TObject.cxx:128
virtual void Warning(const char *method, const char *msgfmt,...) const
Issue warning message.
Definition: TObject.cxx:866
R__ALWAYS_INLINE Bool_t IsZombie() const
Definition: TObject.h:134
void SetBit(UInt_t f, Bool_t set)
Set or unset the user status bits as specified in f.
Definition: TObject.cxx:694
virtual Bool_t InheritsFrom(const char *classname) const
Returns kTRUE if object inherits from class "classname".
Definition: TObject.cxx:443
virtual void Error(const char *method, const char *msgfmt,...) const
Issue error message.
Definition: TObject.cxx:880
virtual void Fatal(const char *method, const char *msgfmt,...) const
Issue fatal error message.
Definition: TObject.cxx:908
virtual const char * GetTitle() const
Returns title of object.
Definition: TObject.cxx:401
void ResetBit(UInt_t f)
Definition: TObject.h:171
@ kCanDelete
if object in a list can be deleted
Definition: TObject.h:58
@ kMustCleanup
if object destructor must call RecursiveRemove()
Definition: TObject.h:60
virtual void Info(const char *method, const char *msgfmt,...) const
Issue info message.
Definition: TObject.cxx:854
Principal Components Analysis (PCA)
Definition: TPrincipal.h:20
The TRealData class manages the effective list of all data members for a given class.
Definition: TRealData.h:30
TDataMember * GetDataMember() const
Definition: TRealData.h:53
@ kTransient
Definition: TRealData.h:44
Bool_t IsObject() const
Definition: TRealData.h:56
virtual const char * GetName() const
Returns name of object.
Definition: TRealData.h:52
Long_t GetThisOffset() const
Definition: TRealData.h:55
A TRefTable maintains the association between a referenced object and the parent object supporting th...
Definition: TRefTable.h:35
static void SetRefTable(TRefTable *table)
Static function setting the current TRefTable.
Definition: TRefTable.cxx:383
static TRefTable * GetRefTable()
Static function returning the current TRefTable.
Definition: TRefTable.cxx:287
Regular expression class.
Definition: TRegexp.h:31
A TSelector object is used by the TTree::Draw, TTree::Scan, TTree::Process to navigate in a TTree and...
Definition: TSelector.h:33
static void * ReAlloc(void *vp, size_t size)
Reallocate (i.e.
Definition: TStorage.cxx:183
Describe Streamer information for one class version.
Definition: TStreamerInfo.h:43
void ForceWriteInfo(TFile *file, Bool_t force=kFALSE)
Recursively mark streamer infos for writing to a file.
Basic string class.
Definition: TString.h:131
Ssiz_t Length() const
Definition: TString.h:405
void ToLower()
Change string to lower-case.
Definition: TString.cxx:1100
static const Ssiz_t kNPOS
Definition: TString.h:264
TSubString Strip(EStripType s=kTrailing, char c=' ') const
Return a substring of self stripped at beginning and/or end.
Definition: TString.cxx:1081
Double_t Atof() const
Return floating-point value contained in string.
Definition: TString.cxx:1962
Ssiz_t First(char c) const
Find first occurrence of a character c.
Definition: TString.cxx:487
const char * Data() const
Definition: TString.h:364
Bool_t EqualTo(const char *cs, ECaseCompare cmp=kExact) const
Definition: TString.h:628
TString & ReplaceAll(const TString &s1, const TString &s2)
Definition: TString.h:687
@ kLeading
Definition: TString.h:262
@ kTrailing
Definition: TString.h:262
Ssiz_t Last(char c) const
Find last occurrence of a character c.
Definition: TString.cxx:876
TObjArray * Tokenize(const TString &delim) const
This function is used to isolate sequential tokens in a TString.
Definition: TString.cxx:2172
Bool_t IsNull() const
Definition: TString.h:402
TString & Remove(Ssiz_t pos)
Definition: TString.h:668
TString & Append(const char *cs)
Definition: TString.h:559
static TString Format(const char *fmt,...)
Static method which formats a string using a printf style format descriptor and return a TString.
Definition: TString.cxx:2286
void Form(const char *fmt,...)
Formats a string using a printf style format descriptor.
Definition: TString.cxx:2264
Bool_t Contains(const char *pat, ECaseCompare cmp=kExact) const
Definition: TString.h:619
Ssiz_t Index(const char *pat, Ssiz_t i=0, ECaseCompare cmp=kExact) const
Definition: TString.h:634
void SetHistFillColor(Color_t color=1)
Definition: TStyle.h:356
Color_t GetHistLineColor() const
Definition: TStyle.h:220
Bool_t IsReading() const
Definition: TStyle.h:277
void SetHistLineStyle(Style_t styl=0)
Definition: TStyle.h:359
Style_t GetHistFillStyle() const
Definition: TStyle.h:221
Color_t GetHistFillColor() const
Definition: TStyle.h:219
void SetHistLineColor(Color_t color=1)
Definition: TStyle.h:357
Style_t GetHistLineStyle() const
Definition: TStyle.h:222
void SetHistFillStyle(Style_t styl=0)
Definition: TStyle.h:358
Width_t GetHistLineWidth() const
Definition: TStyle.h:223
void SetHistLineWidth(Width_t width=1)
Definition: TStyle.h:360
A zero length substring is legal.
Definition: TString.h:77
TString & String()
Definition: TString.h:116
virtual const char * Getenv(const char *env)
Get environment variable.
Definition: TSystem.cxx:1652
virtual Bool_t AccessPathName(const char *path, EAccessMode mode=kFileExists)
Returns FALSE if one can access a file using the specified access mode.
Definition: TSystem.cxx:1286
Specialization of TTreeCache for parallel Unzipping.
static Int_t SetParallelUnzip(TTreeCacheUnzip::EParUnzipMode option=TTreeCacheUnzip::kEnable)
Static function that (de)activates multithreading unzipping.
static void SetUnzipRelBufferSize(Float_t relbufferSize)
static function: Sets the unzip relatibe buffer size
static Bool_t IsParallelUnzip()
Static function that tells wether the multithreading unzipping is activated.
virtual Int_t AddBranch(TBranch *b, Bool_t subgbranches=kFALSE)
Add a branch to the list of branches to be stored in the cache this function is called by the user vi...
Definition: TTreeCache.cxx:367
virtual Int_t SetBufferSize(Int_t buffersize)
Change the underlying buffer size of the cache.
static void SetLearnEntries(Int_t n=10)
Static function to set the number of entries to be used in learning mode The default value for n is 1...
TTree * GetTree() const
Definition: TTreeCache.h:152
virtual void SetEntryRange(Long64_t emin, Long64_t emax)
Set the minimum and maximum entry number to be processed this information helps to optimize the numbe...
Bool_t IsAutoCreated() const
Definition: TTreeCache.h:153
void SetAutoCreated(Bool_t val)
Definition: TTreeCache.h:167
virtual Int_t DropBranch(TBranch *b, Bool_t subbranches=kFALSE)
Remove a branch to the list of branches to be stored in the cache this function is called by TBranch:...
Definition: TTreeCache.cxx:532
virtual void StopLearningPhase()
This is the counterpart of StartLearningPhase() and can be used to stop the learning phase.
virtual void Print(Option_t *option="") const
Print cache statistics.
Class implementing or helping the various TTree cloning method.
Definition: TTreeCloner.h:38
Bool_t Exec()
Execute the cloning.
Bool_t IsValid()
Definition: TTreeCloner.h:121
const char * GetWarning() const
Definition: TTreeCloner.h:119
void SetCacheSize(Int_t size)
Set the TFile cache size to be used.
Bool_t NeedConversion()
Definition: TTreeCloner.h:122
Iterator on all the leaves in a TTree and its friend.
Definition: TTree.h:604
TObject * Next()
Go the next friend element.
Definition: TTree.cxx:9400
TTree * fTree
tree being iterated
Definition: TTree.h:607
Option_t * GetOption() const
Returns the object option stored in the list.
Definition: TTree.cxx:9439
TIterator & operator=(const TIterator &rhs)
Overridden assignment operator. Does NOT copy the 'cursor' location!
Definition: TTree.cxx:9377
TIterator * fLeafIter
current leaf sub-iterator.
Definition: TTree.h:608
TIterator * fTreeIter
current tree sub-iterator.
Definition: TTree.h:609
Bool_t fDirection
iteration direction
Definition: TTree.h:610
Helper class to iterate over cluster of baskets.
Definition: TTree.h:247
Long64_t GetEstimatedClusterSize()
Estimate the cluster size.
Definition: TTree.cxx:578
Long64_t Previous()
Move on to the previous cluster and return the starting entry of this previous cluster.
Definition: TTree.cxx:659
Long64_t fNextEntry
Definition: TTree.h:252
Long64_t Next()
Move on to the next cluster and return the starting entry of this next cluster.
Definition: TTree.cxx:615
Long64_t fStartEntry
Definition: TTree.h:251
TClusterIterator(TTree *tree, Long64_t firstEntry)
Regular constructor.
Definition: TTree.cxx:527
Helper class to prevent infinite recursion in the usage of TTree Friends.
Definition: TTree.h:174
TFriendLock & operator=(const TFriendLock &)
Assignment operator.
Definition: TTree.cxx:497
TFriendLock(const TFriendLock &)
Copy constructor.
Definition: TTree.cxx:487
UInt_t fMethodBit
Definition: TTree.h:178
TTree * fTree
Definition: TTree.h:177
~TFriendLock()
Restore the state of tree the same as before we set the lock.
Definition: TTree.cxx:510
Bool_t fPrevious
Definition: TTree.h:179
A TTree object has a header with a name and a title.
Definition: TTree.h:71
virtual Int_t Fill()
Fill all branches.
Definition: TTree.cxx:4395
virtual TFriendElement * AddFriend(const char *treename, const char *filename="")
Add a TFriendElement to the list of friends.
Definition: TTree.cxx:1255
TBranchRef * fBranchRef
Branch supporting the TRefTable (if any)
Definition: TTree.h:124
virtual Int_t AddBranchToCache(const char *bname, Bool_t subbranches=kFALSE)
Add branch with name bname to the Tree cache.
Definition: TTree.cxx:1007
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:4631
virtual TBranch * GetBranch(const char *name)
Return pointer to the branch with the given name in this tree or its friends.
Definition: TTree.cxx:5051
static Int_t GetBranchStyle()
Static function returning the current branch style.
Definition: TTree.cxx:5165
TList * fFriends
pointer to list of friend elements
Definition: TTree.h:119
UInt_t fFriendLockStatus
! Record which method is locking the friend recursion
Definition: TTree.h:125
virtual TLeaf * GetLeafImpl(const char *branchname, const char *leafname)
Return pointer to the 1st Leaf named name in any Branch of this Tree or any branch in the list of fri...
Definition: TTree.cxx:5859
Long64_t fTotBytes
Total number of bytes in all branches before compression.
Definition: TTree.h:78
Int_t fMaxClusterRange
! Memory allocated for the cluster range.
Definition: TTree.h:88
virtual void Show(Long64_t entry=-1, Int_t lenmax=20)
Print values of all active leaves for entry.
Definition: TTree.cxx:8949
TEventList * fEventList
! Pointer to event selection list (if one)
Definition: TTree.h:114
virtual Long64_t GetAutoSave() const
Definition: TTree.h:387
virtual Int_t StopCacheLearningPhase()
Stop the cache learning phase.
Definition: TTree.cxx:9038
std::vector< std::pair< Long64_t, TBranch * > > fSortedBranches
! Branches to be processed in parallel when IMT is on, sorted by average task time
Definition: TTree.h:132
virtual void SetCircular(Long64_t maxEntries)
Enable/Disable circularity for this tree.
Definition: TTree.cxx:8516
Long64_t fSavedBytes
Number of autosaved bytes.
Definition: TTree.h:80
virtual TClusterIterator GetClusterIterator(Long64_t firstentry)
Return an iterator over the cluster of baskets starting at firstentry.
Definition: TTree.cxx:5227
virtual void ResetBranchAddress(TBranch *)
Tell all of our branches to set their addresses to zero.
Definition: TTree.cxx:7744
char GetNewlineValue(std::istream &inputStream)
Determine which newline this file is using.
Definition: TTree.cxx:7293
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:2722
TIOFeatures fIOFeatures
IO features to define for newly-written baskets and branches.
Definition: TTree.h:106
virtual Long64_t GetEntryNumberWithIndex(Long64_t major, Long64_t minor=0) const
Return entry number corresponding to major and minor number.
Definition: TTree.cxx:5671
Long64_t fDebugMin
! First entry number to debug
Definition: TTree.h:104
virtual Long64_t SetEntries(Long64_t n=-1)
Change number of entries in the tree.
Definition: TTree.cxx:8635
virtual TObjArray * GetListOfLeaves()
Definition: TTree.h:428
Bool_t fCacheDoClusterPrefetch
! true if cache is prefetching whole clusters
Definition: TTree.h:128
virtual TBranch * BranchOld(const char *name, const char *classname, void *addobj, Int_t bufsize=32000, Int_t splitlevel=1)
Create a new TTree BranchObject.
Definition: TTree.cxx:1955
virtual TBranch * BranchRef()
Build the optional branch supporting the TRefTable.
Definition: TTree.cxx:2209
TFile * GetCurrentFile() const
Return pointer to the current file.
Definition: TTree.cxx:5239
TList * fAliases
List of aliases for expressions based on the tree branches.
Definition: TTree.h:113
virtual TTree * CopyTree(const char *selection, Option_t *option="", Long64_t nentries=kMaxEntries, Long64_t firstentry=0)
Copy a tree with selection.
Definition: TTree.cxx:3543
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:4913
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:4863
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:8336
Long64_t * fClusterRangeEnd
[fNClusterRange] Last entry of a cluster range.
Definition: TTree.h:95
std::atomic< Long64_t > fIMTZipBytes
! Zip bytes for the IMT flush baskets.
Definition: TTree.h:149
void UseCurrentStyle()
Replace current attributes by current style.
Definition: TTree.cxx:9301
TVirtualTreePlayer * GetPlayer()
Load the TTreePlayer (if not already done).
Definition: TTree.cxx:6059
virtual Long64_t ReadStream(std::istream &inputStream, const char *branchDescriptor="", char delimiter=' ')
Create or simply read branches from an input stream.
Definition: TTree.cxx:7320
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:8552
Int_t fScanField
Number of runs before prompting in Scan.
Definition: TTree.h:84
virtual ~TTree()
Destructor.
Definition: TTree.cxx:883
virtual TTree * GetFriend(const char *) const
Return a pointer to the TTree friend whose name or alias is 'friendname.
Definition: TTree.cxx:5736
virtual Int_t SetBranchAddress(const char *bname, void *add, TBranch **ptr=0)
Change branch address, dealing with clone trees properly.
Definition: TTree.cxx:8022
virtual Double_t GetMaximum(const char *columname)
Return maximum of column with name columname.
Definition: TTree.cxx:5989
virtual Long64_t GetEntryNumberWithBestIndex(Long64_t major, Long64_t minor=0) const
Return entry number corresponding to major and minor number.
Definition: TTree.cxx:5651
static void SetMaxTreeSize(Long64_t maxsize=100000000000LL)
Set the maximum size in bytes of a Tree file (static function).
Definition: TTree.cxx:8811
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:2293
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:9289
Int_t fNClusterRange
Number of Cluster range in addition to the one defined by 'AutoFlush'.
Definition: TTree.h:87
virtual void PrintCacheStats(Option_t *option="") const
Print statistics about the TreeCache for this tree.
Definition: TTree.cxx:7082
virtual Int_t BuildIndex(const char *majorname, const char *minorname="0")
Build a Tree Index (default is TTreeIndex).
Definition: TTree.cxx:2518
TVirtualTreePlayer * fPlayer
! Pointer to current Tree player
Definition: TTree.h:122
virtual void SetMakeClass(Int_t make)
Set all the branches in this TTree to be in decomposed object mode (also known as MakeClass mode).
Definition: TTree.cxx:8791
TObjArray fBranches
List of Branches.
Definition: TTree.h:111
TDirectory * GetDirectory() const
Definition: TTree.h:401
TTreeCache * GetReadCache(TFile *file) const
Find and return the TTreeCache registered with the file and which may contain branches for us.
Definition: TTree.cxx:6072
Bool_t fCacheUserSet
! true if the cache setting was explicitly given by user
Definition: TTree.h:129
Long64_t fEntries
Number of entries.
Definition: TTree.h:76
virtual TFile * ChangeFile(TFile *file)
Called by TTree::Fill() when file has reached its maximum fgMaxTreeSize.
Definition: TTree.cxx:2608
virtual Bool_t GetBranchStatus(const char *branchname) const
Return status of branch with name branchname.
Definition: TTree.cxx:5150
virtual TEntryList * GetEntryList()
Returns the entry list, set to this tree.
Definition: TTree.cxx:5615
virtual void SetWeight(Double_t w=1, Option_t *option="")
Set tree weight.
Definition: TTree.cxx:8938
void InitializeBranchLists(bool checkLeafCount)
Divides the top-level branches into two vectors: (i) branches to be processed sequentially and (ii) b...
Definition: TTree.cxx:5542
Long64_t * fClusterSize
[fNClusterRange] Number of entries in each cluster for a given range.
Definition: TTree.h:96
Long64_t fFlushedBytes
Number of auto-flushed bytes.
Definition: TTree.h:81
virtual void SetPerfStats(TVirtualPerfStats *perf)
Set perf stats.
Definition: TTree.cxx:8893
std::atomic< Long64_t > fIMTTotBytes
! Total bytes for the IMT flush baskets
Definition: TTree.h:148
virtual void SetCacheLearnEntries(Int_t n=10)
Interface to TTreeCache to set the number of entries for the learning phase.
Definition: TTree.cxx:8489
TEntryList * fEntryList
! Pointer to event selection list (if one)
Definition: TTree.h:115
virtual TVirtualIndex * GetTreeIndex() const
Definition: TTree.h:457
virtual Long64_t Merge(TCollection *list, Option_t *option="")
Merge the trees in the TList into this tree.
Definition: TTree.cxx:6659
virtual void SetMaxVirtualSize(Long64_t size=0)
Definition: TTree.h:561
virtual void DropBaskets()
Remove some baskets from memory.
Definition: TTree.cxx:4314
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:7979
Long64_t fMaxEntryLoop
Maximum number of entries to process.
Definition: TTree.h:90
virtual void SetDirectory(TDirectory *dir)
Change the tree's directory.
Definition: TTree.cxx:8590
virtual Long64_t CopyEntries(TTree *tree, Long64_t nentries=-1, Option_t *option="")
Copy nentries from given tree to this tree.
Definition: TTree.cxx:3374
void SortBranchesByTime()
Sorts top-level branches by the last average task time recorded per branch.
Definition: TTree.cxx:5595
virtual TBranchRef * GetBranchRef() const
Definition: TTree.h:389
virtual Long64_t Process(const char *filename, Option_t *option="", Long64_t nentries=kMaxEntries, Long64_t firstentry=0)
Process this tree executing the TSelector code in the specified filename.
Definition: TTree.cxx:7160
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:1542
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:8693
void MoveReadCache(TFile *src, TDirectory *dir)
Move a cache from a file to the current file in dir.
Definition: TTree.cxx:6754
Long64_t fAutoFlush
Auto-flush tree when fAutoFlush entries written or -fAutoFlush (compressed) bytes produced.
Definition: TTree.h:93
Int_t fUpdate
Update frequency for EntryLoop.
Definition: TTree.h:85
virtual void ResetAfterMerge(TFileMergeInfo *)
Resets the state of this TTree after a merge (keep the customization but forget the data).
Definition: TTree.cxx:7713
virtual void CopyAddresses(TTree *, Bool_t undo=kFALSE)
Set branch addresses of passed tree equal to ours.
Definition: TTree.cxx:3146
virtual Long64_t GetEntries() const
Definition: TTree.h:402
virtual void SetEstimate(Long64_t nentries=1000000)
Set number of entries to estimate variable limits.
Definition: TTree.cxx:8734
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:5843
Int_t fTimerInterval
Timer interval in milliseconds.
Definition: TTree.h:83
Int_t fDebug
! Debug level
Definition: TTree.h:103
virtual Long64_t AutoSave(Option_t *option="")
AutoSave tree header every fAutoSave bytes.
Definition: TTree.cxx:1407
virtual Long64_t GetEntryNumber(Long64_t entry) const
Return entry number corresponding to entry.
Definition: TTree.cxx:5626
virtual TTree * CloneTree(Long64_t nentries=-1, Option_t *option="")
Create a clone of this tree and copy nentries.
Definition: TTree.cxx:2986
Int_t fFileNumber
! current file number (if file extensions)
Definition: TTree.h:108
virtual TLeaf * GetLeaf(const char *branchname, const char *leafname)
Return pointer to the 1st Leaf named name in any Branch of this Tree or any branch in the list of fri...
Definition: TTree.cxx:5949
virtual Long64_t GetZipBytes() const
Definition: TTree.h:484
TObjArray fLeaves
Direct pointers to individual branch leaves.
Definition: TTree.h:112
virtual void Reset(Option_t *option="")
Reset baskets, buffers and entries count in all branches and leaves.
Definition: TTree.cxx:7682
virtual void Print(Option_t *option="") const
Print a summary of the tree contents.
Definition: TTree.cxx:6962
virtual void KeepCircular()
Keep a maximum of fMaxEntries in memory.
Definition: TTree.cxx:6169
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:3643
Long64_t GetCacheAutoSize(Bool_t withDefault=kFALSE) const
Used for automatic sizing of the cache.
Definition: TTree.cxx:5177
virtual Bool_t SetAlias(const char *aliasName, const char *aliasFormula)
Set a tree variable alias.
Definition: TTree.cxx:7815
Long64_t fMaxVirtualSize
Maximum total size of buffers kept in memory.
Definition: TTree.h:91
virtual Long64_t GetTotBytes() const
Definition: TTree.h:455
virtual void SetObject(const char *name, const char *title)
Change the name and title of this tree.
Definition: TTree.cxx:8848
TVirtualPerfStats * fPerfStats
! pointer to the current perf stats object
Definition: TTree.h:120
Double_t fWeight
Tree weight (see TTree::SetWeight)
Definition: TTree.h:82
std::vector< TBranch * > fSeqBranches
! Branches to be processed sequentially when IMT is on
Definition: TTree.h:133
Long64_t fDebugMax
! Last entry number to debug
Definition: TTree.h:105
Int_t fDefaultEntryOffsetLen
Initial Length of fEntryOffset table in the basket buffers.
Definition: TTree.h:86
TTree()
Default constructor and I/O constructor.
Definition: TTree.cxx:702
Long64_t fAutoSave
Autosave tree when fAutoSave entries written or -fAutoSave (compressed) bytes produced.
Definition: TTree.h:92
virtual void SetDefaultEntryOffsetLen(Int_t newdefault, Bool_t updateExisting=kFALSE)
Update the default value for the branch's fEntryOffsetLen.
Definition: TTree.cxx:8564
std::atomic< UInt_t > fAllocationCount
indicates basket should be resized to exact memory usage, but causes significant
Definition: TTree.h:140
virtual Int_t GetEntryWithIndex(Int_t major, Int_t minor=0)
Read entry corresponding to major and minor number.
Definition: TTree.cxx:5688
static TTree * MergeTrees(TList *list, Option_t *option="")
Static function merging the trees in the TList into a new tree.
Definition: TTree.cxx:6616
virtual Long64_t GetReadEntry() const
Definition: TTree.h:448
virtual TObjArray * GetListOfBranches()
Definition: TTree.h:427
virtual void SetParallelUnzip(Bool_t opt=kTRUE, Float_t RelSize=-1)
Enable or disable parallel unzipping of Tree buffers.
Definition: TTree.cxx:8879
Long64_t fZipBytes
Total number of bytes in all branches after compression.
Definition: TTree.h:79
virtual void RecursiveRemove(TObject *obj)
Make sure that obj (which is being deleted or will soon be) is no longer referenced by this TTree.
Definition: TTree.cxx:7586
virtual TTree * GetTree() const
Definition: TTree.h:456
TBuffer * fTransientBuffer
! Pointer to the current transient buffer.
Definition: TTree.h:126
Bool_t fIMTEnabled
! true if implicit multi-threading is enabled for this tree
Definition: TTree.h:130
virtual void SetEntryList(TEntryList *list, Option_t *opt="")
Set an EntryList.
Definition: TTree.cxx:8670
virtual Int_t DropBranchFromCache(const char *bname, Bool_t subbranches=kFALSE)
Remove the branch with name 'bname' from the Tree cache.
Definition: TTree.cxx:1090
virtual void AddZipBytes(Int_t zip)
Definition: TTree.h:309
virtual Long64_t LoadTree(Long64_t entry)
Set current entry.
Definition: TTree.cxx:6226
virtual Long64_t ReadFile(const char *filename, const char *branchDescriptor="", char delimiter=' ')
Create or simply read branches from filename.
Definition: TTree.cxx:7274
virtual const char * GetAlias(const char *aliasName) const
Returns the expanded value of the alias. Search in the friends if any.
Definition: TTree.cxx:5010
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:8754
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:5397
virtual TBasket * CreateBasket(TBranch *)
Create a basket for this tree and given branch.
Definition: TTree.cxx:3555
TList * fUserInfo
pointer to a list of user objects associated to this Tree
Definition: TTree.h:121
virtual Double_t GetMinimum(const char *columname)
Return minimum of column with name columname.
Definition: TTree.cxx:6029
virtual void RemoveFriend(TTree *)
Remove a friend from the list of friends.
Definition: TTree.cxx:7656
virtual Long64_t GetEntriesFast() const
Definition: TTree.h:404
virtual TList * GetUserInfo()
Return a pointer to the list containing user objects associated to this tree.
Definition: TTree.cxx:6110
@ kSplitCollectionOfPointers
Definition: TTree.h:243
Long64_t fChainOffset
! Offset of 1st entry of this Tree in a TChain
Definition: TTree.h:98
@ kOnlyFlushAtCluster
Definition: TTree.h:236
@ kCircular
Definition: TTree.h:235
virtual Long64_t GetEntriesFriend() const
Return pointer to the 1st Leaf named name in any Branch of this Tree or any branch in the list of fri...
Definition: TTree.cxx:5272
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:7223
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:2285
virtual void SetBasketSize(const char *bname, Int_t buffsize=16000)
Set a branch's basket size.
Definition: TTree.cxx:7995
static void SetBranchStyle(Int_t style=1)
Set the current branch style.
Definition: TTree.cxx:8294
void ImportClusterRanges(TTree *fromtree)
Appends the cluster range information stored in 'fromtree' to this tree, including the value of fAuto...
Definition: TTree.cxx:6126
Long64_t fEstimate
Number of entries to estimate histogram limits.
Definition: TTree.h:94
Int_t FlushBasketsImpl() const
Internal implementation of the FlushBaskets algorithm.
Definition: TTree.cxx:4930
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:6322
TVirtualIndex * fTreeIndex
Pointer to the tree Index (if any)
Definition: TTree.h:118
virtual void Browse(TBrowser *)
Browse content of the TTree.
Definition: TTree.cxx:2490
virtual Int_t GetTreeNumber() const
Definition: TTree.h:458
TObject * fNotify
! Object to be notified when loading a Tree
Definition: TTree.h:109
virtual TBranch * BranchImp(const char *branchname, const char *classname, TClass *ptrClass, void *addobj, Int_t bufsize, Int_t splitlevel)
Same as TTree::Branch() with added check that addobj matches className.
Definition: TTree.cxx:1461
Long64_t fCacheSize
! Maximum size of file buffers
Definition: TTree.h:97
TList * fClones
! List of cloned trees which share our addresses
Definition: TTree.h:123
std::atomic< Long64_t > fTotalBuffers
! Total number of bytes in branch buffers
Definition: TTree.h:100
Bool_t fCacheDoAutoInit
! true if cache auto creation or resize check is needed
Definition: TTree.h:127
virtual Int_t MakeSelector(const char *selector=0, Option_t *option="")
Generate skeleton selector class for this tree.
Definition: TTree.cxx:6587
@ kFindBranch
Definition: TTree.h:198
@ kFindLeaf
Definition: TTree.h:199
@ kGetEntryWithIndex
Definition: TTree.h:203
@ kPrint
Definition: TTree.h:208
@ kGetFriend
Definition: TTree.h:204
@ kGetBranch
Definition: TTree.h:201
@ kSetBranchStatus
Definition: TTree.h:210
@ kLoadTree
Definition: TTree.h:207
@ kGetEntry
Definition: TTree.h:202
@ kGetLeaf
Definition: TTree.h:206
@ kRemoveFriend
Definition: TTree.h:209
@ kGetFriendAlias
Definition: TTree.h:205
@ kGetAlias
Definition: TTree.h:200
virtual void Draw(Option_t *opt)
Default Draw method for all objects.
Definition: TTree.h:371
virtual Int_t MakeClass(const char *classname=0, Option_t *option="")
Generate a skeleton analysis class for this tree.
Definition: TTree.cxx:6372
virtual void SetTreeIndex(TVirtualIndex *index)
The current TreeIndex is replaced by the new index.
Definition: TTree.cxx:8910
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:6800
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:7208
virtual Int_t SetCacheEntryRange(Long64_t first, Long64_t last)
interface to TTreeCache to set the cache entry range
Definition: TTree.cxx:8455
static Long64_t GetMaxTreeSize()
Static function which returns the tree file size limit in bytes.
Definition: TTree.cxx:6019
Int_t SetBranchAddressImp(TBranch *branch, void *addr, TBranch **ptr)
Change branch address, dealing with clone trees properly.
Definition: TTree.cxx:8079
Long64_t fMaxEntries
Maximum number of entries in case of circular buffers.
Definition: TTree.h:89
virtual void DropBuffers(Int_t nbytes)
Drop branch buffers to accommodate nbytes below MaxVirtualsize.
Definition: TTree.cxx:4327
virtual void SetName(const char *name)
Change the name of this tree.
Definition: TTree.cxx:8819
virtual void Delete(Option_t *option="")
Delete this tree from memory or/and disk.
Definition: TTree.cxx:3571
virtual TList * GetListOfFriends() const
Definition: TTree.h:429
virtual void Refresh()
Refresh contents of this tree and its branches from the current status on disk.
Definition: TTree.cxx:7617
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:7870
static Long64_t fgMaxTreeSize
Maximum size of a file containing a Tree.
Definition: TTree.h:143
Long64_t fReadEntry
! Number of the entry being processed
Definition: TTree.h:99
TArrayD fIndexValues
Sorted index values.
Definition: TTree.h:116
void MarkEventCluster()
Mark the previous event as being at the end of the event cluster.
Definition: TTree.cxx:7932
virtual Int_t MakeCode(const char *filename=0)
Generate a skeleton function for this tree.
Definition: TTree.cxx:6405
UInt_t fNEntriesSinceSorting
! Number of entries processed since the last re-sorting of branches
Definition: TTree.h:131
virtual Int_t MakeProxy(const char *classname, const char *macrofilename=0, const char *cutfilename=0, const char *option=0, Int_t maxUnrolling=3)
Generate a skeleton analysis class for this Tree using TBranchProxy.
Definition: TTree.cxx:6533
virtual void SetFileNumber(Int_t number=0)
Set fFileNumber to number.
Definition: TTree.cxx:8777
virtual TLeaf * FindLeaf(const char *name)
Find leaf..
Definition: TTree.cxx:4703
virtual void StartViewer()
Start the TTreeViewer on this tree.
Definition: TTree.cxx:9023
Int_t GetMakeClass() const
Definition: TTree.h:434
TDirectory * fDirectory
! Pointer to directory holding this tree
Definition: TTree.h:110
@ kClassMismatch
Definition: TTree.h:223
@ kVoidPtr
Definition: TTree.h:228
@ kMatchConversionCollection
Definition: TTree.h:226
@ kMissingCompiledCollectionProxy
Definition: TTree.h:221
@ kMismatch
Definition: TTree.h:222
@ kMatchConversion
Definition: TTree.h:225
@ kInternalError
Definition: TTree.h:220
@ kMatch
Definition: TTree.h:224
@ kMissingBranch
Definition: TTree.h:219
@ kMakeClass
Definition: TTree.h:227
static Int_t fgBranchStyle
Old/New branch style.
Definition: TTree.h:142
virtual void ResetBranchAddresses()
Tell all of our branches to drop their current objects and allocate new ones.
Definition: TTree.cxx:7754
Int_t fNfill
! Local for EntryLoop
Definition: TTree.h:102
TArrayI fIndex
Index of sorted values.
Definition: TTree.h:117
virtual Int_t SetCacheSize(Long64_t cachesize=-1)
Set maximum size of the file cache .
Definition: TTree.cxx:8310
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:1167
virtual void SetBranchStatus(const char *bname, Bool_t status=1, UInt_t *found=0)
Set branch status to Process or DoNotProcess.
Definition: TTree.cxx:8168
TBuffer * GetTransientBuffer(Int_t size)
Returns the transient buffer currently used by this TTree for reading/writing baskets.
Definition: TTree.cxx:985
ROOT::TIOFeatures GetIOFeatures() const
Returns the current set of IO settings.
Definition: TTree.cxx:5835
virtual const char * GetFriendAlias(TTree *) const
If the 'tree' is a friend, this method returns its alias name.
Definition: TTree.cxx:5793
virtual Bool_t Notify()
Function called when loading a new class library.
Definition: TTree.cxx:6776
Bool_t MemoryFull(Int_t nbytes)
Check if adding nbytes to memory we are still below MaxVirtualsize.
Definition: TTree.cxx:6602
Int_t fPacketSize
! Number of entries in one packet for parallel root
Definition: TTree.h:101
virtual Int_t Branch(TCollection *list, Int_t bufsize=32000, Int_t splitlevel=99, const char *name="")
Create one branch for each element in the collection.
Definition: TTree.cxx:1722
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:9338
TStreamerInfo * BuildStreamerInfo(TClass *cl, void *pointer=0, Bool_t canOptimize=kTRUE)
Build StreamerInfo for class cl.
Definition: TTree.cxx:2533
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:7773
Bool_t fIMTFlush
! True if we are doing a multithreaded flush.
Definition: TTree.h:147
virtual void AddTotBytes(Int_t tot)
Definition: TTree.h:308
Int_t fMakeClass
! not zero when processing code generated by MakeClass
Definition: TTree.h:107
virtual Int_t LoadBaskets(Long64_t maxmemory=2000000000)
Read in memory all baskets from all branches up to the limit of maxmemory bytes.
Definition: TTree.cxx:6205
static constexpr Long64_t kMaxEntries
Definition: TTree.h:215
TPrincipal * Principal(const char *varexp="", const char *selection="", Option_t *option="np", Long64_t nentries=kMaxEntries, Long64_t firstentry=0)
Interface to the Principal Components Analysis class.
Definition: TTree.cxx:6943
virtual Long64_t GetAutoFlush() const
Definition: TTree.h:386
virtual EDataType GetType() const =0
virtual TClass * GetValueClass() const =0
virtual Bool_t HasPointers() const =0
Abstract interface for Tree Index.
Definition: TVirtualIndex.h:29
virtual void Append(const TVirtualIndex *, Bool_t delaySort=kFALSE)=0
virtual const char * GetMajorName() const =0
virtual Long64_t GetEntryNumberWithIndex(Long64_t major, Long64_t minor) const =0
virtual Long64_t GetEntryNumberFriend(const TTree *)=0
virtual const char * GetMinorName() const =0
virtual void SetTree(const TTree *T)=0
virtual Long64_t GetN() const =0
virtual Long64_t GetEntryNumberWithBestIndex(Long64_t major, Long64_t minor) const =0
Provides the interface for the PROOF internal performance measurement and event tracing.
Abstract base class defining the interface for the plugins that implement Draw, Scan,...
virtual Int_t MakeProxy(const char *classname, const char *macrofilename=0, const char *cutfilename=0, const char *option=0, Int_t maxUnrolling=3)=0
virtual Long64_t Scan(const char *varexp, const char *selection, Option_t *option, Long64_t nentries, Long64_t firstentry)=0
virtual void UpdateFormulaLeaves()=0
virtual Long64_t DrawSelect(const char *varexp, const char *selection, Option_t *option, Long64_t nentries, Long64_t firstentry)=0
virtual Int_t MakeCode(const char *filename)=0
virtual Int_t UnbinnedFit(const char *formula, const char *varexp, const char *selection, Option_t *option, Long64_t nentries, Long64_t firstentry)=0
virtual Long64_t GetEntries(const char *)=0
virtual TSQLResult * Query(const char *varexp, const char *selection, Option_t *option, Long64_t nentries, Long64_t firstentry)=0
virtual TPrincipal * Principal(const char *varexp="", const char *selection="", Option_t *option="np", Long64_t nentries=kMaxEntries, Long64_t firstentry=0)=0
virtual void StartViewer(Int_t ww, Int_t wh)=0
virtual Int_t MakeReader(const char *classname, Option_t *option)=0
virtual TVirtualIndex * BuildIndex(const TTree *T, const char *majorname, const char *minorname)=0
virtual TTree * CopyTree(const char *selection, Option_t *option="", Long64_t nentries=kMaxEntries, Long64_t firstentry=0)=0
virtual Long64_t Process(const char *filename, Option_t *option="", Long64_t nentries=kMaxEntries, Long64_t firstentry=0)=0
virtual void SetEstimate(Long64_t n)=0
static TVirtualTreePlayer * TreePlayer(TTree *obj)
Static function returning a pointer to a Tree player.
virtual Int_t MakeClass(const char *classname, const char *option)=0
virtual Int_t Fit(const char *formula, const char *varexp, const char *selection, Option_t *option, Option_t *goption, Long64_t nentries, Long64_t firstentry)=0
TLine * line
const Int_t n
Definition: legend1.C:16
constexpr std::array< decltype(std::declval< F >()(std::declval< int >())), N > make(F f)
Namespace for new ROOT classes and functions.
Definition: StringConv.hxx:21
ESTLType
Definition: ESTLType.h:28
@ kSTLmap
Definition: ESTLType.h:33
@ kSTLmultimap
Definition: ESTLType.h:34
Bool_t IsImplicitMTEnabled()
Returns true if the implicit multi-threading in ROOT is enabled.
Definition: TROOT.cxx:607
void ToHumanReadableSize(value_type bytes, Bool_t si, Double_t *coeff, const char **units)
Return the size expressed in 'human readable' format.
Definition: StringConv.hxx:38
EFromHumanReadableSize FromHumanReadableSize(std::string_view str, T &value)
Convert strings like the following into byte counts 5MB, 5 MB, 5M, 3.7GB, 123b, 456kB,...
Definition: StringConv.hxx:86
static constexpr double s
Short_t Max(Short_t a, Short_t b)
Definition: TMathBase.h:212
Short_t Min(Short_t a, Short_t b)
Definition: TMathBase.h:180
Long64_t BinarySearch(Long64_t n, const T *array, T value)
Definition: TMathBase.h:278
Definition: file.py:1
Definition: first.py:1
Definition: tree.py:1
const char * Size
Definition: TXMLSetup.cxx:55
TCanvas * slash()
Definition: slash.C:1
@ kUseGlobal
Use the global compression algorithm.
Definition: Compression.h:81
@ kInherit
Some objects use this value to denote that the compression algorithm should be inherited from the par...
Definition: Compression.h:79
@ kUseGeneralPurpose
Use the recommended general-purpose setting; moderate read / write speed and compression ratio.
Definition: Compression.h:53
TCanvas * style()
Definition: style.C:1
void table()
Definition: table.C:85
auto * m
Definition: textangle.C:8
auto * l
Definition: textangle.C:4
auto * a
Definition: textangle.C:12