Logo ROOT   6.30.04
Reference Guide
 All Namespaces Files Pages
TTree.cxx
Go to the documentation of this file.
1 // @(#)root/tree:$Id$
2 // Author: Rene Brun 12/01/96
3 
4 /*************************************************************************
5  * Copyright (C) 1995-2000, Rene Brun and Fons Rademakers. *
6  * All rights reserved. *
7  * *
8  * For the licensing terms see $ROOTSYS/LICENSE. *
9  * For the list of contributors see $ROOTSYS/README/CREDITS. *
10  *************************************************************************/
11 /**
12  \defgroup tree Tree Library
13 
14  In order to store columnar datasets, ROOT provides the TTree, TChain,
15  TNtuple and TNtupleD classes.
16  The TTree class represents a columnar dataset. Any C++ type can be stored in the
17  columns. The TTree has allowed to store about **1 EB** of data coming from the LHC alone:
18  it is demonstrated to scale and it's battle tested. It has been optimized during the years
19  to reduce dataset sizes on disk and to deliver excellent runtime performance.
20  It allows to access only part of the columns of the datasets, too.
21  The TNtuple and TNtupleD classes are specialisations of the TTree class which can
22  only hold single precision and double precision floating-point numbers respectively;
23  The TChain is a collection of TTrees, which can be located also in different files.
24 
25 */
26 
27 /** \class TTree
28 \ingroup tree
29 
30 A TTree represents a columnar dataset. Any C++ type can be stored in its columns.
31 
32 A TTree, often called in jargon *tree*, consists of a list of independent columns or *branches*,
33 represented by the TBranch class.
34 Behind each branch, buffers are allocated automatically by ROOT.
35 Such buffers are automatically written to disk or kept in memory until the size stored in the
36 attribute fMaxVirtualSize is reached.
37 Variables of one branch are written to the same buffer. A branch buffer is
38 automatically compressed if the file compression attribute is set (default).
39 Branches may be written to different files (see TBranch::SetFile).
40 
41 The ROOT user can decide to make one single branch and serialize one object into
42 one single I/O buffer or to make several branches.
43 Making several branches is particularly interesting in the data analysis phase,
44 when it is desirable to have a high reading rate and not all columns are equally interesting
45 
46 ## Table of contents:
47 - [Creating a TTree](#creatingattree)
48 - [Add a Column of Fundamental Types and Arrays thereof](#addcolumnoffundamentaltypes)
49 - [Add a Column of a STL Collection instances](#addingacolumnofstl)
50 - [Add a column holding an object](#addingacolumnofobjs)
51 - [Add a column holding a TObjectArray](#addingacolumnofobjs)
52 - [Fill the tree](#fillthetree)
53 - [Add a column to an already existing Tree](#addcoltoexistingtree)
54 - [An Example](#fullexample)
55 
56 ## <a name="creatingattree"></a>Creating a TTree
57 
58 ~~~ {.cpp}
59  TTree tree(name, title)
60 ~~~
61 Creates a Tree with name and title.
62 
63 Various kinds of branches can be added to a tree:
64 - Variables representing fundamental types, simple classes/structures or list of variables: for example for C or Fortran
65 structures.
66 - Any C++ object or collection, provided by the STL or ROOT.
67 
68 In the following, the details about the creation of different types of branches are given.
69 
70 ## <a name="addcolumnoffundamentaltypes"></a>Add a column (`branch`) of fundamental types and arrays thereof
71 This strategy works also for lists of variables, e.g. to describe simple structures.
72 It is strongly reccomended to persistify those as objects rather than lists of leaves.
73 
74 ~~~ {.cpp}
75  auto branch = tree.Branch(branchname, address, leaflist, bufsize)
76 ~~~
77 - address is the address of the first item of a structure
78 - leaflist is the concatenation of all the variable names and types
79  separated by a colon character :
80  The variable name and the variable type are separated by a
81  slash (/). The variable type must be 1 character. (Characters
82  after the first are legal and will be appended to the visible
83  name of the leaf, but have no effect.) If no type is given, the
84  type of the variable is assumed to be the same as the previous
85  variable. If the first variable does not have a type, it is
86  assumed of type F by default. The list of currently supported
87  types is given below:
88  - `C` : a character string terminated by the 0 character
89  - `B` : an 8 bit signed integer (`Char_t`)
90  - `b` : an 8 bit unsigned integer (`UChar_t`)
91  - `S` : a 16 bit signed integer (`Short_t`)
92  - `s` : a 16 bit unsigned integer (`UShort_t`)
93  - `I` : a 32 bit signed integer (`Int_t`)
94  - `i` : a 32 bit unsigned integer (`UInt_t`)
95  - `F` : a 32 bit floating point (`Float_t`)
96  - `f` : a 24 bit floating point with truncated mantissa (`Float16_t`)
97  - `D` : a 64 bit floating point (`Double_t`)
98  - `d` : a 24 bit truncated floating point (`Double32_t`)
99  - `L` : a 64 bit signed integer (`Long64_t`)
100  - `l` : a 64 bit unsigned integer (`ULong64_t`)
101  - `O` : [the letter `o`, not a zero] a boolean (`Bool_t`)
102 
103  Examples:
104  - A int: "myVar/I"
105  - A float array with fixed size: "myArrfloat[42]/F"
106  - An double array with variable size, held by the `myvar` column: "myArrdouble[myvar]/D"
107  - An Double32_t array with variable size, held by the `myvar` column , with values between 0 and 16: "myArr[myvar]/d[0,10]"
108 
109 - If the address points to a single numerical variable, the leaflist is optional:
110 ~~~ {.cpp}
111  int value;
112  `tree->Branch(branchname, &value);`
113 ~~~
114 - If the address points to more than one numerical variable, we strongly recommend
115  that the variable be sorted in decreasing order of size. Any other order will
116  result in a non-portable TTree (i.e. you will not be able to read it back on a
117  platform with a different padding strategy).
118  We recommend to persistify objects rather than composite leaflists.
119 - In case of the truncated floating point types (Float16_t and Double32_t) you can
120  furthermore specify the range in the style [xmin,xmax] or [xmin,xmax,nbits] after
121  the type character. For example, for storing a variable size array `myArr` of
122  `Double32_t` with values within a range of `[0, 2*pi]` and the size of which is
123  stored in a branch called `myArrSize`, the syntax for the `leaflist` string would
124  be: `myArr[myArrSize]/d[0,twopi]`. Of course the number of bits could be specified,
125  the standard rules of opaque typedefs annotation are valid. For example, if only
126  18 bits were sufficient, the syntax would become: `myArr[myArrSize]/d[0,twopi,18]`
127 
128 ## <a name="addingacolumnofstl"></a>Adding a column of STL collection instances (e.g. std::vector, std::list, std::unordered_map)
129 
130 ~~~ {.cpp}
131  auto branch = tree.Branch( branchname, STLcollection, buffsize, splitlevel);
132 ~~~
133 STLcollection is the address of a pointer to std::vector, std::list,
134 std::deque, std::set or std::multiset containing pointers to objects.
135 If the splitlevel is a value bigger than 100 (TTree::kSplitCollectionOfPointers)
136 then the collection will be written in split mode, e.g. if it contains objects of
137 any types deriving from TTrack this function will sort the objects
138 based on their type and store them in separate branches in split
139 mode.
140 
141 ~~~ {.cpp}
142  branch->SetAddress(void *address)
143 ~~~
144 In case of dynamic structures changing with each entry for example, one must
145 redefine the branch address before filling the branch again.
146 This is done via the TBranch::SetAddress member function.
147 
148 ## <a name="addingacolumnofobjs">Add a column of objects
149 
150 ~~~ {.cpp}
151  MyClass object;
152  auto branch = tree.Branch(branchname, &object, bufsize, splitlevel)
153 ~~~
154 Note: The 2nd parameter must be the address of a valid object.
155  The object must not be destroyed (i.e. be deleted) until the TTree
156  is deleted or TTree::ResetBranchAddress is called.
157 
158 - if splitlevel=0, the object is serialized in the branch buffer.
159 - if splitlevel=1 (default), this branch will automatically be split
160  into subbranches, with one subbranch for each data member or object
161  of the object itself. In case the object member is a TClonesArray,
162  the mechanism described in case C is applied to this array.
163 - if splitlevel=2 ,this branch will automatically be split
164  into subbranches, with one subbranch for each data member or object
165  of the object itself. In case the object member is a TClonesArray,
166  it is processed as a TObject*, only one branch.
167 
168 Another available syntax is the following:
169 
170 ~~~ {.cpp}
171  auto branch = tree.Branch(branchname, &p_object, bufsize, splitlevel)
172  auto branch = tree.Branch(branchname, className, &p_object, bufsize, splitlevel)
173 ~~~
174 - p_object is a pointer to an object.
175 - If className is not specified, Branch uses the type of p_object to determine the
176  type of the object.
177 - If className is used to specify explicitly the object type, the className must
178  be of a type related to the one pointed to by the pointer. It should be either
179  a parent or derived class.
180 
181 Note: The pointer whose address is passed to TTree::Branch must not
182  be destroyed (i.e. go out of scope) until the TTree is deleted or
183  TTree::ResetBranchAddress is called.
184 
185 Note: The pointer p_object must be initialized before calling TTree::Branch
186 - Do either:
187 ~~~ {.cpp}
188  MyDataClass* p_object = nullptr;
189  tree.Branch(branchname, &p_object);
190 ~~~
191 - Or:
192 ~~~ {.cpp}
193  auto p_object = new MyDataClass;
194  tree.Branch(branchname, &p_object);
195 ~~~
196 Whether the pointer is set to zero or not, the ownership of the object
197 is not taken over by the TTree. I.e. even though an object will be allocated
198 by TTree::Branch if the pointer p_object is zero, the object will <b>not</b>
199 be deleted when the TTree is deleted.
200 
201 ## <a name="addingacolumnoftclonesarray">Add a column of TClonesArray instances
202 
203 *It is recommended to use STL containers instead of TClonesArrays*.
204 
205 ~~~ {.cpp}
206  // clonesarray is the address of a pointer to a TClonesArray.
207  auto branch = tree.Branch(branchname,clonesarray, bufsize, splitlevel)
208 ~~~
209 The TClonesArray is a direct access list of objects of the same class.
210 For example, if the TClonesArray is an array of TTrack objects,
211 this function will create one subbranch for each data member of
212 the object TTrack.
213 
214 ## <a name="fillthetree">Fill the Tree:
215 
216 A TTree instance is filled with the invocation of the TTree::Fill method:
217 ~~~ {.cpp}
218  tree.Fill()
219 ~~~
220 Upon its invocation, a loop on all defined branches takes place that for each branch invokes
221 the TBranch::Fill method.
222 
223 ## <a name="addcoltoexistingtree">Add a column to an already existing Tree
224 
225 You may want to add a branch to an existing tree. For example,
226 if one variable in the tree was computed with a certain algorithm,
227 you may want to try another algorithm and compare the results.
228 One solution is to add a new branch, fill it, and save the tree.
229 The code below adds a simple branch to an existing tree.
230 Note the kOverwrite option in the Write method, it overwrites the
231 existing tree. If it is not specified, two copies of the tree headers
232 are saved.
233 ~~~ {.cpp}
234  void tree3AddBranch() {
235  TFile f("tree3.root", "update");
236 
237  Float_t new_v;
238  auto t3 = f->Get<TTree>("t3");
239  auto newBranch = t3->Branch("new_v", &new_v, "new_v/F");
240 
241  Long64_t nentries = t3->GetEntries(); // read the number of entries in the t3
242 
243  for (Long64_t i = 0; i < nentries; i++) {
244  new_v = gRandom->Gaus(0, 1);
245  newBranch->Fill();
246  }
247 
248  t3->Write("", TObject::kOverwrite); // save only the new version of the tree
249  }
250 ~~~
251 It is not always possible to add branches to existing datasets stored in TFiles: for example,
252 these files might not be writeable, just readable. In addition, modifying in place a TTree
253 causes a new TTree instance to be written and the previous one to be deleted.
254 For this reasons, ROOT offers the concept of friends for TTree and TChain:
255 if is good practice to rely on friend trees rather than adding a branch manually.
256 
257 ## <a name="fullexample">An Example
258 
259 Begin_Macro
260 ../../../tutorials/tree/tree.C
261 End_Macro
262 
263 ~~~ {.cpp}
264  // A simple example with histograms and a tree
265  //
266  // This program creates :
267  // - a one dimensional histogram
268  // - a two dimensional histogram
269  // - a profile histogram
270  // - a tree
271  //
272  // These objects are filled with some random numbers and saved on a file.
273 
274  #include "TFile.h"
275  #include "TH1.h"
276  #include "TH2.h"
277  #include "TProfile.h"
278  #include "TRandom.h"
279  #include "TTree.h"
280 
281  //__________________________________________________________________________
282  main(int argc, char **argv)
283  {
284  // Create a new ROOT binary machine independent file.
285  // Note that this file may contain any kind of ROOT objects, histograms,trees
286  // pictures, graphics objects, detector geometries, tracks, events, etc..
287  // This file is now becoming the current directory.
288  TFile hfile("htree.root","RECREATE","Demo ROOT file with histograms & trees");
289 
290  // Create some histograms and a profile histogram
291  TH1F hpx("hpx","This is the px distribution",100,-4,4);
292  TH2F hpxpy("hpxpy","py ps px",40,-4,4,40,-4,4);
293  TProfile hprof("hprof","Profile of pz versus px",100,-4,4,0,20);
294 
295  // Define some simple structures
296  typedef struct {Float_t x,y,z;} POINT;
297  typedef struct {
298  Int_t ntrack,nseg,nvertex;
299  UInt_t flag;
300  Float_t temperature;
301  } EVENTN;
302  POINT point;
303  EVENTN eventn;
304 
305  // Create a ROOT Tree
306  TTree tree("T","An example of ROOT tree with a few branches");
307  tree.Branch("point",&point,"x:y:z");
308  tree.Branch("eventn",&eventn,"ntrack/I:nseg:nvertex:flag/i:temperature/F");
309  tree.Branch("hpx","TH1F",&hpx,128000,0);
310 
311  Float_t px,py,pz;
312 
313  // Here we start a loop on 1000 events
314  for ( Int_t i=0; i<1000; i++) {
315  gRandom->Rannor(px,py);
316  pz = px*px + py*py;
317  const auto random = gRandom->::Rndm(1);
318 
319  // Fill histograms
320  hpx.Fill(px);
321  hpxpy.Fill(px,py,1);
322  hprof.Fill(px,pz,1);
323 
324  // Fill structures
325  point.x = 10*(random-1);
326  point.y = 5*random;
327  point.z = 20*random;
328  eventn.ntrack = Int_t(100*random);
329  eventn.nseg = Int_t(2*eventn.ntrack);
330  eventn.nvertex = 1;
331  eventn.flag = Int_t(random+0.5);
332  eventn.temperature = 20+random;
333 
334  // Fill the tree. For each event, save the 2 structures and 3 objects
335  // In this simple example, the objects hpx, hprof and hpxpy are slightly
336  // different from event to event. We expect a big compression factor!
337  tree->Fill();
338  }
339  // End of the loop
340 
341  tree.Print();
342 
343  // Save all objects in this file
344  hfile.Write();
345 
346  // Close the file. Note that this is automatically done when you leave
347  // the application upon file destruction.
348  hfile.Close();
349 
350  return 0;
351 }
352 ~~~
353 */
354 
355 #include <ROOT/RConfig.hxx>
356 #include "TTree.h"
357 
358 #include "ROOT/TIOFeatures.hxx"
359 #include "TArrayC.h"
360 #include "TBufferFile.h"
361 #include "TBaseClass.h"
362 #include "TBasket.h"
363 #include "TBranchClones.h"
364 #include "TBranchElement.h"
365 #include "TBranchObject.h"
366 #include "TBranchRef.h"
367 #include "TBrowser.h"
368 #include "TClass.h"
369 #include "TClassEdit.h"
370 #include "TClonesArray.h"
371 #include "TCut.h"
372 #include "TDataMember.h"
373 #include "TDataType.h"
374 #include "TDirectory.h"
375 #include "TError.h"
376 #include "TEntryList.h"
377 #include "TEnv.h"
378 #include "TEventList.h"
379 #include "TFile.h"
380 #include "TFolder.h"
381 #include "TFriendElement.h"
382 #include "TInterpreter.h"
383 #include "TLeaf.h"
384 #include "TLeafB.h"
385 #include "TLeafC.h"
386 #include "TLeafD.h"
387 #include "TLeafElement.h"
388 #include "TLeafF.h"
389 #include "TLeafI.h"
390 #include "TLeafL.h"
391 #include "TLeafObject.h"
392 #include "TLeafS.h"
393 #include "TList.h"
394 #include "TMath.h"
395 #include "TROOT.h"
396 #include "TRealData.h"
397 #include "TRegexp.h"
398 #include "TStreamerElement.h"
399 #include "TStreamerInfo.h"
400 #include "TStyle.h"
401 #include "TSystem.h"
402 #include "TTreeCloner.h"
403 #include "TTreeCache.h"
404 #include "TTreeCacheUnzip.h"
405 #include "TVirtualCollectionProxy.h"
407 #include "TVirtualIndex.h"
408 #include "TVirtualPerfStats.h"
409 #include "TVirtualPad.h"
410 #include "TBranchSTL.h"
411 #include "TSchemaRuleSet.h"
412 #include "TFileMergeInfo.h"
413 #include "ROOT/StringConv.hxx"
414 #include "TVirtualMutex.h"
415 
416 #include "TBranchIMTHelper.h"
417 #include "TNotifyLink.h"
418 
419 #include <chrono>
420 #include <cstddef>
421 #include <iostream>
422 #include <fstream>
423 #include <sstream>
424 #include <string>
425 #include <stdio.h>
426 #include <limits.h>
427 #include <algorithm>
428 
429 #ifdef R__USE_IMT
430 #include "ROOT/TThreadExecutor.hxx"
431 #include <thread>
432 #include <string>
433 #include <sstream>
434 #endif
435 
436 constexpr Int_t kNEntriesResort = 100;
437 constexpr Float_t kNEntriesResortInv = 1.f/kNEntriesResort;
438 
439 Int_t TTree::fgBranchStyle = 1; // Use new TBranch style with TBranchElement.
440 Long64_t TTree::fgMaxTreeSize = 100000000000LL;
441 
442 ClassImp(TTree);
443 
444 ////////////////////////////////////////////////////////////////////////////////
445 ////////////////////////////////////////////////////////////////////////////////
446 ////////////////////////////////////////////////////////////////////////////////
447 
448 static char DataTypeToChar(EDataType datatype)
449 {
450  // Return the leaflist 'char' for a given datatype.
451 
452  switch(datatype) {
453  case kChar_t: return 'B';
454  case kUChar_t: return 'b';
455  case kBool_t: return 'O';
456  case kShort_t: return 'S';
457  case kUShort_t: return 's';
458  case kCounter:
459  case kInt_t: return 'I';
460  case kUInt_t: return 'i';
461  case kDouble_t: return 'D';
462  case kDouble32_t: return 'd';
463  case kFloat_t: return 'F';
464  case kFloat16_t: return 'f';
465  case kLong_t: return 0; // unsupported
466  case kULong_t: return 0; // unsupported?
467  case kchar: return 0; // unsupported
468  case kLong64_t: return 'L';
469  case kULong64_t: return 'l';
470 
471  case kCharStar: return 'C';
472  case kBits: return 0; //unsupported
473 
474  case kOther_t:
475  case kNoType_t:
476  default:
477  return 0;
478  }
479  return 0;
480 }
481 
482 ////////////////////////////////////////////////////////////////////////////////
483 /// \class TTree::TFriendLock
484 /// Helper class to prevent infinite recursion in the usage of TTree Friends.
485 
486 ////////////////////////////////////////////////////////////////////////////////
487 /// Record in tree that it has been used while recursively looks through the friends.
488 
489 TTree::TFriendLock::TFriendLock(TTree* tree, UInt_t methodbit)
490 : fTree(tree)
491 {
492  // We could also add some code to acquire an actual
493  // lock to prevent multi-thread issues
494  fMethodBit = methodbit;
495  if (fTree) {
496  fPrevious = fTree->fFriendLockStatus & fMethodBit;
497  fTree->fFriendLockStatus |= fMethodBit;
498  } else {
499  fPrevious = 0;
500  }
501 }
502 
503 ////////////////////////////////////////////////////////////////////////////////
504 /// Copy constructor.
505 
506 TTree::TFriendLock::TFriendLock(const TFriendLock& tfl) :
507  fTree(tfl.fTree),
508  fMethodBit(tfl.fMethodBit),
509  fPrevious(tfl.fPrevious)
510 {
511 }
512 
513 ////////////////////////////////////////////////////////////////////////////////
514 /// Assignment operator.
515 
516 TTree::TFriendLock& TTree::TFriendLock::operator=(const TTree::TFriendLock& tfl)
517 {
518  if(this!=&tfl) {
519  fTree=tfl.fTree;
520  fMethodBit=tfl.fMethodBit;
521  fPrevious=tfl.fPrevious;
522  }
523  return *this;
524 }
525 
526 ////////////////////////////////////////////////////////////////////////////////
527 /// Restore the state of tree the same as before we set the lock.
528 
529 TTree::TFriendLock::~TFriendLock()
530 {
531  if (fTree) {
532  if (!fPrevious) {
533  fTree->fFriendLockStatus &= ~(fMethodBit & kBitMask);
534  }
535  }
536 }
537 
538 ////////////////////////////////////////////////////////////////////////////////
539 /// \class TTree::TClusterIterator
540 /// Helper class to iterate over cluster of baskets.
541 
542 ////////////////////////////////////////////////////////////////////////////////
543 /// Regular constructor.
544 /// TTree is not set as const, since we might modify if it is a TChain.
545 
546 TTree::TClusterIterator::TClusterIterator(TTree *tree, Long64_t firstEntry) : fTree(tree), fClusterRange(0), fStartEntry(0), fNextEntry(0), fEstimatedSize(-1)
547 {
548  if (fTree->fNClusterRange) {
549  // Find the correct cluster range.
550  //
551  // Since fClusterRangeEnd contains the inclusive upper end of the range, we need to search for the
552  // range that was containing the previous entry and add 1 (because BinarySearch consider the values
553  // to be the inclusive start of the bucket).
554  fClusterRange = TMath::BinarySearch(fTree->fNClusterRange, fTree->fClusterRangeEnd, firstEntry - 1) + 1;
555 
556  Long64_t entryInRange;
557  Long64_t pedestal;
558  if (fClusterRange == 0) {
559  pedestal = 0;
560  entryInRange = firstEntry;
561  } else {
562  pedestal = fTree->fClusterRangeEnd[fClusterRange-1] + 1;
563  entryInRange = firstEntry - pedestal;
564  }
565  Long64_t autoflush;
566  if (fClusterRange == fTree->fNClusterRange) {
567  autoflush = fTree->fAutoFlush;
568  } else {
569  autoflush = fTree->fClusterSize[fClusterRange];
570  }
571  if (autoflush <= 0) {
572  autoflush = GetEstimatedClusterSize();
573  }
574  fStartEntry = pedestal + entryInRange - entryInRange%autoflush;
575  } else if ( fTree->GetAutoFlush() <= 0 ) {
576  // Case of old files before November 9 2009 *or* small tree where AutoFlush was never set.
577  fStartEntry = firstEntry;
578  } else {
579  fStartEntry = firstEntry - firstEntry%fTree->GetAutoFlush();
580  }
581  fNextEntry = fStartEntry; // Position correctly for the first call to Next()
582 }
583 
584 ////////////////////////////////////////////////////////////////////////////////
585 /// Estimate the cluster size.
586 ///
587 /// In almost all cases, this quickly returns the size of the auto-flush
588 /// in the TTree.
589 ///
590 /// However, in the case where the cluster size was not fixed (old files and
591 /// case where autoflush was explicitly set to zero), we need estimate
592 /// a cluster size in relation to the size of the cache.
593 ///
594 /// After this value is calculated once for the TClusterIterator, it is
595 /// cached and reused in future calls.
596 
597 Long64_t TTree::TClusterIterator::GetEstimatedClusterSize()
598 {
599  auto autoFlush = fTree->GetAutoFlush();
600  if (autoFlush > 0) return autoFlush;
601  if (fEstimatedSize > 0) return fEstimatedSize;
602 
603  Long64_t zipBytes = fTree->GetZipBytes();
604  if (zipBytes == 0) {
605  fEstimatedSize = fTree->GetEntries() - 1;
606  } else {
607  Long64_t clusterEstimate = 1;
608  Long64_t cacheSize = fTree->GetCacheSize();
609  if (cacheSize == 0) {
610  // Humm ... let's double check on the file.
611  TFile *file = fTree->GetCurrentFile();
612  if (file) {
613  TFileCacheRead *cache = fTree->GetReadCache(file);
614  if (cache) {
615  cacheSize = cache->GetBufferSize();
616  }
617  }
618  }
619  // If neither file nor tree has a cache, use the current default.
620  if (cacheSize <= 0) {
621  cacheSize = 30000000;
622  }
623  clusterEstimate = fTree->GetEntries() * cacheSize / zipBytes;
624  // If there are no entries, then just default to 1.
625  fEstimatedSize = clusterEstimate ? clusterEstimate : 1;
626  }
627  return fEstimatedSize;
628 }
629 
630 ////////////////////////////////////////////////////////////////////////////////
631 /// Move on to the next cluster and return the starting entry
632 /// of this next cluster
633 
634 Long64_t TTree::TClusterIterator::Next()
635 {
636  fStartEntry = fNextEntry;
637  if (fTree->fNClusterRange || fTree->GetAutoFlush() > 0) {
638  if (fClusterRange == fTree->fNClusterRange) {
639  // We are looking at a range which size
640  // is defined by AutoFlush itself and goes to the GetEntries.
641  fNextEntry += GetEstimatedClusterSize();
642  } else {
643  if (fStartEntry > fTree->fClusterRangeEnd[fClusterRange]) {
644  ++fClusterRange;
645  }
646  if (fClusterRange == fTree->fNClusterRange) {
647  // We are looking at the last range which size
648  // is defined by AutoFlush itself and goes to the GetEntries.
649  fNextEntry += GetEstimatedClusterSize();
650  } else {
651  Long64_t clusterSize = fTree->fClusterSize[fClusterRange];
652  if (clusterSize == 0) {
653  clusterSize = GetEstimatedClusterSize();
654  }
655  fNextEntry += clusterSize;
656  if (fNextEntry > fTree->fClusterRangeEnd[fClusterRange]) {
657  // The last cluster of the range was a partial cluster,
658  // so the next cluster starts at the beginning of the
659  // next range.
660  fNextEntry = fTree->fClusterRangeEnd[fClusterRange] + 1;
661  }
662  }
663  }
664  } else {
665  // Case of old files before November 9 2009
666  fNextEntry = fStartEntry + GetEstimatedClusterSize();
667  }
668  if (fNextEntry > fTree->GetEntries()) {
669  fNextEntry = fTree->GetEntries();
670  }
671  return fStartEntry;
672 }
673 
674 ////////////////////////////////////////////////////////////////////////////////
675 /// Move on to the previous cluster and return the starting entry
676 /// of this previous cluster
677 
678 Long64_t TTree::TClusterIterator::Previous()
679 {
680  fNextEntry = fStartEntry;
681  if (fTree->fNClusterRange || fTree->GetAutoFlush() > 0) {
682  if (fClusterRange == 0 || fTree->fNClusterRange == 0) {
683  // We are looking at a range which size
684  // is defined by AutoFlush itself.
685  fStartEntry -= GetEstimatedClusterSize();
686  } else {
687  if (fNextEntry <= fTree->fClusterRangeEnd[fClusterRange]) {
688  --fClusterRange;
689  }
690  if (fClusterRange == 0) {
691  // We are looking at the first range.
692  fStartEntry = 0;
693  } else {
694  Long64_t clusterSize = fTree->fClusterSize[fClusterRange];
695  if (clusterSize == 0) {
696  clusterSize = GetEstimatedClusterSize();
697  }
698  fStartEntry -= clusterSize;
699  }
700  }
701  } else {
702  // Case of old files before November 9 2009 or trees that never auto-flushed.
703  fStartEntry = fNextEntry - GetEstimatedClusterSize();
704  }
705  if (fStartEntry < 0) {
706  fStartEntry = 0;
707  }
708  return fStartEntry;
709 }
710 
711 ////////////////////////////////////////////////////////////////////////////////
712 ////////////////////////////////////////////////////////////////////////////////
713 ////////////////////////////////////////////////////////////////////////////////
714 
715 ////////////////////////////////////////////////////////////////////////////////
716 /// Default constructor and I/O constructor.
717 ///
718 /// Note: We do *not* insert ourself into the current directory.
719 ///
720 
721 TTree::TTree()
722 : TNamed()
723 , TAttLine()
724 , TAttFill()
725 , TAttMarker()
726 , fEntries(0)
727 , fTotBytes(0)
728 , fZipBytes(0)
729 , fSavedBytes(0)
730 , fFlushedBytes(0)
731 , fWeight(1)
732 , fTimerInterval(0)
733 , fScanField(25)
734 , fUpdate(0)
735 , fDefaultEntryOffsetLen(1000)
736 , fNClusterRange(0)
737 , fMaxClusterRange(0)
738 , fMaxEntries(0)
739 , fMaxEntryLoop(0)
740 , fMaxVirtualSize(0)
741 , fAutoSave( -300000000)
742 , fAutoFlush(-30000000)
743 , fEstimate(1000000)
744 , fClusterRangeEnd(0)
745 , fClusterSize(0)
746 , fCacheSize(0)
747 , fChainOffset(0)
748 , fReadEntry(-1)
749 , fTotalBuffers(0)
750 , fPacketSize(100)
751 , fNfill(0)
752 , fDebug(0)
753 , fDebugMin(0)
754 , fDebugMax(9999999)
755 , fMakeClass(0)
756 , fFileNumber(0)
757 , fNotify(0)
758 , fDirectory(0)
759 , fBranches()
760 , fLeaves()
761 , fAliases(0)
762 , fEventList(0)
763 , fEntryList(0)
764 , fIndexValues()
765 , fIndex()
766 , fTreeIndex(0)
767 , fFriends(0)
768 , fPerfStats(0)
769 , fUserInfo(0)
770 , fPlayer(0)
771 , fClones(0)
772 , fBranchRef(0)
773 , fFriendLockStatus(0)
774 , fTransientBuffer(0)
775 , fCacheDoAutoInit(kTRUE)
776 , fCacheDoClusterPrefetch(kFALSE)
777 , fCacheUserSet(kFALSE)
778 , fIMTEnabled(ROOT::IsImplicitMTEnabled())
779 , fNEntriesSinceSorting(0)
780 {
781  fMaxEntries = 1000000000;
782  fMaxEntries *= 1000;
783 
784  fMaxEntryLoop = 1000000000;
785  fMaxEntryLoop *= 1000;
786 
787  fBranches.SetOwner(kTRUE);
788 }
789 
790 ////////////////////////////////////////////////////////////////////////////////
791 /// Normal tree constructor.
792 ///
793 /// The tree is created in the current directory.
794 /// Use the various functions Branch below to add branches to this tree.
795 ///
796 /// If the first character of title is a "/", the function assumes a folder name.
797 /// In this case, it creates automatically branches following the folder hierarchy.
798 /// splitlevel may be used in this case to control the split level.
799 
800 TTree::TTree(const char* name, const char* title, Int_t splitlevel /* = 99 */,
801  TDirectory* dir /* = gDirectory*/)
802 : TNamed(name, title)
803 , TAttLine()
804 , TAttFill()
805 , TAttMarker()
806 , fEntries(0)
807 , fTotBytes(0)
808 , fZipBytes(0)
809 , fSavedBytes(0)
810 , fFlushedBytes(0)
811 , fWeight(1)
812 , fTimerInterval(0)
813 , fScanField(25)
814 , fUpdate(0)
815 , fDefaultEntryOffsetLen(1000)
816 , fNClusterRange(0)
817 , fMaxClusterRange(0)
818 , fMaxEntries(0)
819 , fMaxEntryLoop(0)
820 , fMaxVirtualSize(0)
821 , fAutoSave( -300000000)
822 , fAutoFlush(-30000000)
823 , fEstimate(1000000)
824 , fClusterRangeEnd(0)
825 , fClusterSize(0)
826 , fCacheSize(0)
827 , fChainOffset(0)
828 , fReadEntry(-1)
829 , fTotalBuffers(0)
830 , fPacketSize(100)
831 , fNfill(0)
832 , fDebug(0)
833 , fDebugMin(0)
834 , fDebugMax(9999999)
835 , fMakeClass(0)
836 , fFileNumber(0)
837 , fNotify(0)
838 , fDirectory(dir)
839 , fBranches()
840 , fLeaves()
841 , fAliases(0)
842 , fEventList(0)
843 , fEntryList(0)
844 , fIndexValues()
845 , fIndex()
846 , fTreeIndex(0)
847 , fFriends(0)
848 , fPerfStats(0)
849 , fUserInfo(0)
850 , fPlayer(0)
851 , fClones(0)
852 , fBranchRef(0)
853 , fFriendLockStatus(0)
854 , fTransientBuffer(0)
855 , fCacheDoAutoInit(kTRUE)
856 , fCacheDoClusterPrefetch(kFALSE)
857 , fCacheUserSet(kFALSE)
858 , fIMTEnabled(ROOT::IsImplicitMTEnabled())
859 , fNEntriesSinceSorting(0)
860 {
861  // TAttLine state.
862  SetLineColor(gStyle->GetHistLineColor());
863  SetLineStyle(gStyle->GetHistLineStyle());
864  SetLineWidth(gStyle->GetHistLineWidth());
865 
866  // TAttFill state.
867  SetFillColor(gStyle->GetHistFillColor());
868  SetFillStyle(gStyle->GetHistFillStyle());
869 
870  // TAttMarkerState.
871  SetMarkerColor(gStyle->GetMarkerColor());
872  SetMarkerStyle(gStyle->GetMarkerStyle());
873  SetMarkerSize(gStyle->GetMarkerSize());
874 
875  fMaxEntries = 1000000000;
876  fMaxEntries *= 1000;
877 
878  fMaxEntryLoop = 1000000000;
879  fMaxEntryLoop *= 1000;
880 
881  // Insert ourself into the current directory.
882  // FIXME: This is very annoying behaviour, we should
883  // be able to choose to not do this like we
884  // can with a histogram.
885  if (fDirectory) fDirectory->Append(this);
886 
887  fBranches.SetOwner(kTRUE);
888 
889  // If title starts with "/" and is a valid folder name, a superbranch
890  // is created.
891  // FIXME: Why?
892  if (strlen(title) > 2) {
893  if (title[0] == '/') {
894  Branch(title+1,32000,splitlevel);
895  }
896  }
897 }
898 
899 ////////////////////////////////////////////////////////////////////////////////
900 /// Destructor.
901 
902 TTree::~TTree()
903 {
904  if (auto link = dynamic_cast<TNotifyLinkBase*>(fNotify)) {
905  link->Clear();
906  }
907  if (fAllocationCount && (gDebug > 0)) {
908  Info("TTree::~TTree", "For tree %s, allocation count is %u.", GetName(), fAllocationCount.load());
909 #ifdef R__TRACK_BASKET_ALLOC_TIME
910  Info("TTree::~TTree", "For tree %s, allocation time is %lluus.", GetName(), fAllocationTime.load());
911 #endif
912  }
913 
914  if (fDirectory) {
915  // We are in a directory, which may possibly be a file.
916  if (fDirectory->GetList()) {
917  // Remove us from the directory listing.
918  fDirectory->Remove(this);
919  }
920  //delete the file cache if it points to this Tree
921  TFile *file = fDirectory->GetFile();
922  MoveReadCache(file,0);
923  }
924  // We don't own the leaves in fLeaves, the branches do.
925  fLeaves.Clear();
926  // I'm ready to destroy any objects allocated by
927  // SetAddress() by my branches. If I have clones,
928  // tell them to zero their pointers to this shared
929  // memory.
930  if (fClones && fClones->GetEntries()) {
931  // I have clones.
932  // I am about to delete the objects created by
933  // SetAddress() which we are sharing, so tell
934  // the clones to release their pointers to them.
935  for (TObjLink* lnk = fClones->FirstLink(); lnk; lnk = lnk->Next()) {
936  TTree* clone = (TTree*) lnk->GetObject();
937  // clone->ResetBranchAddresses();
938 
939  // Reset only the branch we have set the address of.
940  CopyAddresses(clone,kTRUE);
941  }
942  }
943  // Get rid of our branches, note that this will also release
944  // any memory allocated by TBranchElement::SetAddress().
945  fBranches.Delete();
946  // FIXME: We must consider what to do with the reset of these if we are a clone.
947  delete fPlayer;
948  fPlayer = 0;
949  if (fFriends) {
950  fFriends->Delete();
951  delete fFriends;
952  fFriends = 0;
953  }
954  if (fAliases) {
955  fAliases->Delete();
956  delete fAliases;
957  fAliases = 0;
958  }
959  if (fUserInfo) {
960  fUserInfo->Delete();
961  delete fUserInfo;
962  fUserInfo = 0;
963  }
964  if (fClones) {
965  // Clone trees should no longer be removed from fClones when they are deleted.
966  {
967  R__LOCKGUARD(gROOTMutex);
968  gROOT->GetListOfCleanups()->Remove(fClones);
969  }
970  // Note: fClones does not own its content.
971  delete fClones;
972  fClones = 0;
973  }
974  if (fEntryList) {
975  if (fEntryList->TestBit(kCanDelete) && fEntryList->GetDirectory()==0) {
976  // Delete the entry list if it is marked to be deleted and it is not also
977  // owned by a directory. (Otherwise we would need to make sure that a
978  // TDirectoryFile that has a TTree in it does a 'slow' TList::Delete.
979  delete fEntryList;
980  fEntryList=0;
981  }
982  }
983  delete fTreeIndex;
984  fTreeIndex = 0;
985  delete fBranchRef;
986  fBranchRef = 0;
987  delete [] fClusterRangeEnd;
988  fClusterRangeEnd = 0;
989  delete [] fClusterSize;
990  fClusterSize = 0;
991  // Must be done after the destruction of friends.
992  // Note: We do *not* own our directory.
993  fDirectory = 0;
994 
995  if (fTransientBuffer) {
996  delete fTransientBuffer;
997  fTransientBuffer = 0;
998  }
999 }
1000 
1001 ////////////////////////////////////////////////////////////////////////////////
1002 /// Returns the transient buffer currently used by this TTree for reading/writing baskets.
1003 
1004 TBuffer* TTree::GetTransientBuffer(Int_t size)
1005 {
1006  if (fTransientBuffer) {
1007  if (fTransientBuffer->BufferSize() < size) {
1008  fTransientBuffer->Expand(size);
1009  }
1010  return fTransientBuffer;
1011  }
1012  fTransientBuffer = new TBufferFile(TBuffer::kRead, size);
1013  return fTransientBuffer;
1014 }
1015 
1016 ////////////////////////////////////////////////////////////////////////////////
1017 /// Add branch with name bname to the Tree cache.
1018 /// If bname="*" all branches are added to the cache.
1019 /// if subbranches is true all the branches of the subbranches are
1020 /// also put to the cache.
1021 ///
1022 /// Returns:
1023 /// - 0 branch added or already included
1024 /// - -1 on error
1025 
1026 Int_t TTree::AddBranchToCache(const char*bname, Bool_t subbranches)
1027 {
1028  if (!GetTree()) {
1029  if (LoadTree(0)<0) {
1030  Error("AddBranchToCache","Could not load a tree");
1031  return -1;
1032  }
1033  }
1034  if (GetTree()) {
1035  if (GetTree() != this) {
1036  return GetTree()->AddBranchToCache(bname, subbranches);
1037  }
1038  } else {
1039  Error("AddBranchToCache", "No tree is available. Branch was not added to the cache");
1040  return -1;
1041  }
1042 
1043  TFile *f = GetCurrentFile();
1044  if (!f) {
1045  Error("AddBranchToCache", "No file is available. Branch was not added to the cache");
1046  return -1;
1047  }
1048  TTreeCache *tc = GetReadCache(f,kTRUE);
1049  if (!tc) {
1050  Error("AddBranchToCache", "No cache is available, branch not added");
1051  return -1;
1052  }
1053  return tc->AddBranch(bname,subbranches);
1054 }
1055 
1056 ////////////////////////////////////////////////////////////////////////////////
1057 /// Add branch b to the Tree cache.
1058 /// if subbranches is true all the branches of the subbranches are
1059 /// also put to the cache.
1060 ///
1061 /// Returns:
1062 /// - 0 branch added or already included
1063 /// - -1 on error
1064 
1065 Int_t TTree::AddBranchToCache(TBranch *b, Bool_t subbranches)
1066 {
1067  if (!GetTree()) {
1068  if (LoadTree(0)<0) {
1069  Error("AddBranchToCache","Could not load a tree");
1070  return -1;
1071  }
1072  }
1073  if (GetTree()) {
1074  if (GetTree() != this) {
1075  Int_t res = GetTree()->AddBranchToCache(b, subbranches);
1076  if (res<0) {
1077  Error("AddBranchToCache", "Error adding branch");
1078  }
1079  return res;
1080  }
1081  } else {
1082  Error("AddBranchToCache", "No tree is available. Branch was not added to the cache");
1083  return -1;
1084  }
1085 
1086  TFile *f = GetCurrentFile();
1087  if (!f) {
1088  Error("AddBranchToCache", "No file is available. Branch was not added to the cache");
1089  return -1;
1090  }
1091  TTreeCache *tc = GetReadCache(f,kTRUE);
1092  if (!tc) {
1093  Error("AddBranchToCache", "No cache is available, branch not added");
1094  return -1;
1095  }
1096  return tc->AddBranch(b,subbranches);
1097 }
1098 
1099 ////////////////////////////////////////////////////////////////////////////////
1100 /// Remove the branch with name 'bname' from the Tree cache.
1101 /// If bname="*" all branches are removed from the cache.
1102 /// if subbranches is true all the branches of the subbranches are
1103 /// also removed from the cache.
1104 ///
1105 /// Returns:
1106 /// - 0 branch dropped or not in cache
1107 /// - -1 on error
1108 
1109 Int_t TTree::DropBranchFromCache(const char*bname, Bool_t subbranches)
1110 {
1111  if (!GetTree()) {
1112  if (LoadTree(0)<0) {
1113  Error("DropBranchFromCache","Could not load a tree");
1114  return -1;
1115  }
1116  }
1117  if (GetTree()) {
1118  if (GetTree() != this) {
1119  return GetTree()->DropBranchFromCache(bname, subbranches);
1120  }
1121  } else {
1122  Error("DropBranchFromCache", "No tree is available. Branch was not dropped from the cache");
1123  return -1;
1124  }
1125 
1126  TFile *f = GetCurrentFile();
1127  if (!f) {
1128  Error("DropBranchFromCache", "No file is available. Branch was not dropped from the cache");
1129  return -1;
1130  }
1131  TTreeCache *tc = GetReadCache(f,kTRUE);
1132  if (!tc) {
1133  Error("DropBranchFromCache", "No cache is available, branch not dropped");
1134  return -1;
1135  }
1136  return tc->DropBranch(bname,subbranches);
1137 }
1138 
1139 ////////////////////////////////////////////////////////////////////////////////
1140 /// Remove the branch b from the Tree cache.
1141 /// if subbranches is true all the branches of the subbranches are
1142 /// also removed from the cache.
1143 ///
1144 /// Returns:
1145 /// - 0 branch dropped or not in cache
1146 /// - -1 on error
1147 
1148 Int_t TTree::DropBranchFromCache(TBranch *b, Bool_t subbranches)
1149 {
1150  if (!GetTree()) {
1151  if (LoadTree(0)<0) {
1152  Error("DropBranchFromCache","Could not load a tree");
1153  return -1;
1154  }
1155  }
1156  if (GetTree()) {
1157  if (GetTree() != this) {
1158  Int_t res = GetTree()->DropBranchFromCache(b, subbranches);
1159  if (res<0) {
1160  Error("DropBranchFromCache", "Error dropping branch");
1161  }
1162  return res;
1163  }
1164  } else {
1165  Error("DropBranchFromCache", "No tree is available. Branch was not dropped from the cache");
1166  return -1;
1167  }
1168 
1169  TFile *f = GetCurrentFile();
1170  if (!f) {
1171  Error("DropBranchFromCache", "No file is available. Branch was not dropped from the cache");
1172  return -1;
1173  }
1174  TTreeCache *tc = GetReadCache(f,kTRUE);
1175  if (!tc) {
1176  Error("DropBranchFromCache", "No cache is available, branch not dropped");
1177  return -1;
1178  }
1179  return tc->DropBranch(b,subbranches);
1180 }
1181 
1182 ////////////////////////////////////////////////////////////////////////////////
1183 /// Add a cloned tree to our list of trees to be notified whenever we change
1184 /// our branch addresses or when we are deleted.
1185 
1186 void TTree::AddClone(TTree* clone)
1187 {
1188  if (!fClones) {
1189  fClones = new TList();
1190  fClones->SetOwner(false);
1191  // So that the clones are automatically removed from the list when
1192  // they are deleted.
1193  {
1194  R__LOCKGUARD(gROOTMutex);
1195  gROOT->GetListOfCleanups()->Add(fClones);
1196  }
1197  }
1198  if (!fClones->FindObject(clone)) {
1199  fClones->Add(clone);
1200  }
1201 }
1202 
1203 // Check whether mainTree and friendTree can be friends w.r.t. the kEntriesReshuffled bit.
1204 // In particular, if any has the bit set, then friendTree must have a TTreeIndex and the
1205 // branches used for indexing must be present in mainTree.
1206 // Return true if the trees can be friends, false otherwise.
1207 bool CheckReshuffling(TTree &mainTree, TTree &friendTree)
1208 {
1209  const auto isMainReshuffled = mainTree.TestBit(TTree::kEntriesReshuffled);
1210  const auto isFriendReshuffled = friendTree.TestBit(TTree::kEntriesReshuffled);
1211  const auto friendHasValidIndex = [&] {
1212  auto idx = friendTree.GetTreeIndex();
1213  return idx ? idx->IsValidFor(&mainTree) : kFALSE;
1214  }();
1215 
1216  if ((isMainReshuffled || isFriendReshuffled) && !friendHasValidIndex) {
1217  const auto reshuffledTreeName = isMainReshuffled ? mainTree.GetName() : friendTree.GetName();
1218  const auto msg = "Tree '%s' has the kEntriesReshuffled bit set, and cannot be used as friend nor can be added as "
1219  "a friend unless the main tree has a TTreeIndex on the friend tree '%s'. You can also unset the "
1220  "bit manually if you know what you are doing.";
1221  Error("AddFriend", msg, reshuffledTreeName, friendTree.GetName());
1222  return false;
1223  }
1224  return true;
1225 }
1226 
1227 ////////////////////////////////////////////////////////////////////////////////
1228 /// Add a TFriendElement to the list of friends.
1229 ///
1230 /// This function:
1231 /// - opens a file if filename is specified
1232 /// - reads a Tree with name treename from the file (current directory)
1233 /// - adds the Tree to the list of friends
1234 /// see other AddFriend functions
1235 ///
1236 /// A TFriendElement TF describes a TTree object TF in a file.
1237 /// When a TFriendElement TF is added to the the list of friends of an
1238 /// existing TTree T, any variable from TF can be referenced in a query
1239 /// to T.
1240 ///
1241 /// A tree keeps a list of friends. In the context of a tree (or a chain),
1242 /// friendship means unrestricted access to the friends data. In this way
1243 /// it is much like adding another branch to the tree without taking the risk
1244 /// of damaging it. To add a friend to the list, you can use the TTree::AddFriend
1245 /// method. The tree in the diagram below has two friends (friend_tree1 and
1246 /// friend_tree2) and now has access to the variables a,b,c,i,j,k,l and m.
1247 ///
1248 /// \image html ttree_friend1.png
1249 ///
1250 /// The AddFriend method has two parameters, the first is the tree name and the
1251 /// second is the name of the ROOT file where the friend tree is saved.
1252 /// AddFriend automatically opens the friend file. If no file name is given,
1253 /// the tree called ft1 is assumed to be in the same file as the original tree.
1254 ///
1255 /// tree.AddFriend("ft1","friendfile1.root");
1256 /// If the friend tree has the same name as the original tree, you can give it
1257 /// an alias in the context of the friendship:
1258 ///
1259 /// tree.AddFriend("tree1 = tree","friendfile1.root");
1260 /// Once the tree has friends, we can use TTree::Draw as if the friend's
1261 /// variables were in the original tree. To specify which tree to use in
1262 /// the Draw method, use the syntax:
1263 /// ~~~ {.cpp}
1264 /// <treeName>.<branchname>.<varname>
1265 /// ~~~
1266 /// If the variablename is enough to uniquely identify the variable, you can
1267 /// leave out the tree and/or branch name.
1268 /// For example, these commands generate a 3-d scatter plot of variable "var"
1269 /// in the TTree tree versus variable v1 in TTree ft1 versus variable v2 in
1270 /// TTree ft2.
1271 /// ~~~ {.cpp}
1272 /// tree.AddFriend("ft1","friendfile1.root");
1273 /// tree.AddFriend("ft2","friendfile2.root");
1274 /// tree.Draw("var:ft1.v1:ft2.v2");
1275 /// ~~~
1276 /// \image html ttree_friend2.png
1277 ///
1278 /// The picture illustrates the access of the tree and its friends with a
1279 /// Draw command.
1280 /// When AddFriend is called, the ROOT file is automatically opened and the
1281 /// friend tree (ft1) is read into memory. The new friend (ft1) is added to
1282 /// the list of friends of tree.
1283 /// The number of entries in the friend must be equal or greater to the number
1284 /// of entries of the original tree. If the friend tree has fewer entries a
1285 /// warning is given and the missing entries are not included in the histogram.
1286 /// To retrieve the list of friends from a tree use TTree::GetListOfFriends.
1287 /// When the tree is written to file (TTree::Write), the friends list is saved
1288 /// with it. And when the tree is retrieved, the trees on the friends list are
1289 /// also retrieved and the friendship restored.
1290 /// When a tree is deleted, the elements of the friend list are also deleted.
1291 /// It is possible to declare a friend tree that has the same internal
1292 /// structure (same branches and leaves) as the original tree, and compare the
1293 /// same values by specifying the tree.
1294 /// ~~~ {.cpp}
1295 /// tree.Draw("var:ft1.var:ft2.var")
1296 /// ~~~
1297 
1298 TFriendElement *TTree::AddFriend(const char *treename, const char *filename)
1299 {
1300  if (!fFriends) {
1301  fFriends = new TList();
1302  }
1303  TFriendElement *fe = new TFriendElement(this, treename, filename);
1304 
1305  TTree *t = fe->GetTree();
1306  bool canAddFriend = true;
1307  if (t) {
1308  canAddFriend = CheckReshuffling(*this, *t);
1309  if (!t->GetTreeIndex() && (t->GetEntries() < fEntries)) {
1310  Warning("AddFriend", "FriendElement %s in file %s has less entries %lld than its parent Tree: %lld", treename,
1311  filename, t->GetEntries(), fEntries);
1312  }
1313  } else {
1314  Error("AddFriend", "Cannot find tree '%s' in file '%s', friend not added", treename, filename);
1315  canAddFriend = false;
1316  }
1317 
1318  if (canAddFriend)
1319  fFriends->Add(fe);
1320  return fe;
1321 }
1322 
1323 ////////////////////////////////////////////////////////////////////////////////
1324 /// Add a TFriendElement to the list of friends.
1325 ///
1326 /// The TFile is managed by the user (e.g. the user must delete the file).
1327 /// For complete description see AddFriend(const char *, const char *).
1328 /// This function:
1329 /// - reads a Tree with name treename from the file
1330 /// - adds the Tree to the list of friends
1331 
1332 TFriendElement *TTree::AddFriend(const char *treename, TFile *file)
1333 {
1334  if (!fFriends) {
1335  fFriends = new TList();
1336  }
1337  TFriendElement *fe = new TFriendElement(this, treename, file);
1338  R__ASSERT(fe);
1339  TTree *t = fe->GetTree();
1340  bool canAddFriend = true;
1341  if (t) {
1342  canAddFriend = CheckReshuffling(*this, *t);
1343  if (!t->GetTreeIndex() && (t->GetEntries() < fEntries)) {
1344  Warning("AddFriend", "FriendElement %s in file %s has less entries %lld than its parent tree: %lld", treename,
1345  file->GetName(), t->GetEntries(), fEntries);
1346  }
1347  } else {
1348  Error("AddFriend", "Cannot find tree '%s' in file '%s', friend not added", treename, file->GetName());
1349  canAddFriend = false;
1350  }
1351 
1352  if (canAddFriend)
1353  fFriends->Add(fe);
1354  return fe;
1355 }
1356 
1357 ////////////////////////////////////////////////////////////////////////////////
1358 /// Add a TFriendElement to the list of friends.
1359 ///
1360 /// The TTree is managed by the user (e.g., the user must delete the file).
1361 /// For a complete description see AddFriend(const char *, const char *).
1362 
1363 TFriendElement *TTree::AddFriend(TTree *tree, const char *alias, Bool_t warn)
1364 {
1365  if (!tree) {
1366  return 0;
1367  }
1368  if (!fFriends) {
1369  fFriends = new TList();
1370  }
1371  TFriendElement *fe = new TFriendElement(this, tree, alias);
1372  R__ASSERT(fe); // this assert is for historical reasons. Don't remove it unless you understand all the consequences.
1373  TTree *t = fe->GetTree();
1374  if (warn && (t->GetEntries() < fEntries)) {
1375  Warning("AddFriend", "FriendElement '%s' in file '%s' has less entries %lld than its parent tree: %lld",
1376  tree->GetName(), fe->GetFile() ? fe->GetFile()->GetName() : "(memory resident)", t->GetEntries(),
1377  fEntries);
1378  }
1379  if (CheckReshuffling(*this, *t)) {
1380  fFriends->Add(fe);
1381  }
1382  return fe;
1383 }
1384 
1385 ////////////////////////////////////////////////////////////////////////////////
1386 /// AutoSave tree header every fAutoSave bytes.
1387 ///
1388 /// When large Trees are produced, it is safe to activate the AutoSave
1389 /// procedure. Some branches may have buffers holding many entries.
1390 /// If fAutoSave is negative, AutoSave is automatically called by
1391 /// TTree::Fill when the number of bytes generated since the previous
1392 /// AutoSave is greater than -fAutoSave bytes.
1393 /// If fAutoSave is positive, AutoSave is automatically called by
1394 /// TTree::Fill every N entries.
1395 /// This function may also be invoked by the user.
1396 /// Each AutoSave generates a new key on the file.
1397 /// Once the key with the tree header has been written, the previous cycle
1398 /// (if any) is deleted.
1399 ///
1400 /// Note that calling TTree::AutoSave too frequently (or similarly calling
1401 /// TTree::SetAutoSave with a small value) is an expensive operation.
1402 /// You should make tests for your own application to find a compromise
1403 /// between speed and the quantity of information you may loose in case of
1404 /// a job crash.
1405 ///
1406 /// In case your program crashes before closing the file holding this tree,
1407 /// the file will be automatically recovered when you will connect the file
1408 /// in UPDATE mode.
1409 /// The Tree will be recovered at the status corresponding to the last AutoSave.
1410 ///
1411 /// if option contains "SaveSelf", gDirectory->SaveSelf() is called.
1412 /// This allows another process to analyze the Tree while the Tree is being filled.
1413 ///
1414 /// if option contains "FlushBaskets", TTree::FlushBaskets is called and all
1415 /// the current basket are closed-out and written to disk individually.
1416 ///
1417 /// By default the previous header is deleted after having written the new header.
1418 /// if option contains "Overwrite", the previous Tree header is deleted
1419 /// before written the new header. This option is slightly faster, but
1420 /// the default option is safer in case of a problem (disk quota exceeded)
1421 /// when writing the new header.
1422 ///
1423 /// The function returns the number of bytes written to the file.
1424 /// if the number of bytes is null, an error has occurred while writing
1425 /// the header to the file.
1426 ///
1427 /// ## How to write a Tree in one process and view it from another process
1428 ///
1429 /// The following two scripts illustrate how to do this.
1430 /// The script treew.C is executed by process1, treer.C by process2
1431 ///
1432 /// script treew.C:
1433 /// ~~~ {.cpp}
1434 /// void treew() {
1435 /// TFile f("test.root","recreate");
1436 /// TNtuple *ntuple = new TNtuple("ntuple","Demo","px:py:pz:random:i");
1437 /// Float_t px, py, pz;
1438 /// for ( Int_t i=0; i<10000000; i++) {
1439 /// gRandom->Rannor(px,py);
1440 /// pz = px*px + py*py;
1441 /// Float_t random = gRandom->Rndm(1);
1442 /// ntuple->Fill(px,py,pz,random,i);
1443 /// if (i%1000 == 1) ntuple->AutoSave("SaveSelf");
1444 /// }
1445 /// }
1446 /// ~~~
1447 /// script treer.C:
1448 /// ~~~ {.cpp}
1449 /// void treer() {
1450 /// TFile f("test.root");
1451 /// TTree *ntuple = (TTree*)f.Get("ntuple");
1452 /// TCanvas c1;
1453 /// Int_t first = 0;
1454 /// while(1) {
1455 /// if (first == 0) ntuple->Draw("px>>hpx", "","",10000000,first);
1456 /// else ntuple->Draw("px>>+hpx","","",10000000,first);
1457 /// first = (Int_t)ntuple->GetEntries();
1458 /// c1.Update();
1459 /// gSystem->Sleep(1000); //sleep 1 second
1460 /// ntuple->Refresh();
1461 /// }
1462 /// }
1463 /// ~~~
1464 
1465 Long64_t TTree::AutoSave(Option_t* option)
1466 {
1467  if (!fDirectory || fDirectory == gROOT || !fDirectory->IsWritable()) return 0;
1468  if (gDebug > 0) {
1469  Info("AutoSave", "Tree:%s after %lld bytes written\n",GetName(),GetTotBytes());
1470  }
1471  TString opt = option;
1472  opt.ToLower();
1473 
1474  if (opt.Contains("flushbaskets")) {
1475  if (gDebug > 0) Info("AutoSave", "calling FlushBaskets \n");
1476  FlushBasketsImpl();
1477  }
1478 
1479  fSavedBytes = GetZipBytes();
1480 
1481  TKey *key = (TKey*)fDirectory->GetListOfKeys()->FindObject(GetName());
1482  Long64_t nbytes;
1483  if (opt.Contains("overwrite")) {
1484  nbytes = fDirectory->WriteTObject(this,"","overwrite");
1485  } else {
1486  nbytes = fDirectory->WriteTObject(this); //nbytes will be 0 if Write failed (disk space exceeded)
1487  if (nbytes && key) {
1488  key->Delete();
1489  delete key;
1490  }
1491  }
1492  // save StreamerInfo
1493  TFile *file = fDirectory->GetFile();
1494  if (file) file->WriteStreamerInfo();
1495 
1496  if (opt.Contains("saveself")) {
1497  fDirectory->SaveSelf();
1498  //the following line is required in case GetUserInfo contains a user class
1499  //for which the StreamerInfo must be written. One could probably be a bit faster (Rene)
1500  if (file) file->WriteHeader();
1501  }
1502 
1503  return nbytes;
1504 }
1505 
1506 namespace {
1507  // This error message is repeated several times in the code. We write it once.
1508  const char* writeStlWithoutProxyMsg = "The class requested (%s) for the branch \"%s\""
1509  " is an instance of an stl collection and does not have a compiled CollectionProxy."
1510  " Please generate the dictionary for this collection (%s) to avoid to write corrupted data.";
1511 }
1512 
1513 ////////////////////////////////////////////////////////////////////////////////
1514 /// Same as TTree::Branch() with added check that addobj matches className.
1515 ///
1516 /// See TTree::Branch() for other details.
1517 ///
1518 
1519 TBranch* TTree::BranchImp(const char* branchname, const char* classname, TClass* ptrClass, void* addobj, Int_t bufsize, Int_t splitlevel)
1520 {
1521  TClass* claim = TClass::GetClass(classname);
1522  if (!ptrClass) {
1523  if (claim && claim->GetCollectionProxy() && dynamic_cast<TEmulatedCollectionProxy*>(claim->GetCollectionProxy())) {
1524  Error("Branch", writeStlWithoutProxyMsg,
1525  claim->GetName(), branchname, claim->GetName());
1526  return 0;
1527  }
1528  return Branch(branchname, classname, (void*) addobj, bufsize, splitlevel);
1529  }
1530  TClass* actualClass = 0;
1531  void** addr = (void**) addobj;
1532  if (addr) {
1533  actualClass = ptrClass->GetActualClass(*addr);
1534  }
1535  if (ptrClass && claim) {
1536  if (!(claim->InheritsFrom(ptrClass) || ptrClass->InheritsFrom(claim))) {
1537  // Note we currently do not warn in case of splicing or over-expectation).
1538  if (claim->IsLoaded() && ptrClass->IsLoaded() && strcmp( claim->GetTypeInfo()->name(), ptrClass->GetTypeInfo()->name() ) == 0) {
1539  // The type is the same according to the C++ type_info, we must be in the case of
1540  // a template of Double32_t. This is actually a correct case.
1541  } else {
1542  Error("Branch", "The class requested (%s) for \"%s\" is different from the type of the pointer passed (%s)",
1543  claim->GetName(), branchname, ptrClass->GetName());
1544  }
1545  } else if (actualClass && (claim != actualClass) && !actualClass->InheritsFrom(claim)) {
1546  if (claim->IsLoaded() && actualClass->IsLoaded() && strcmp( claim->GetTypeInfo()->name(), actualClass->GetTypeInfo()->name() ) == 0) {
1547  // The type is the same according to the C++ type_info, we must be in the case of
1548  // a template of Double32_t. This is actually a correct case.
1549  } else {
1550  Error("Branch", "The actual class (%s) of the object provided for the definition of the branch \"%s\" does not inherit from %s",
1551  actualClass->GetName(), branchname, claim->GetName());
1552  }
1553  }
1554  }
1555  if (claim && claim->GetCollectionProxy() && dynamic_cast<TEmulatedCollectionProxy*>(claim->GetCollectionProxy())) {
1556  Error("Branch", writeStlWithoutProxyMsg,
1557  claim->GetName(), branchname, claim->GetName());
1558  return 0;
1559  }
1560  return Branch(branchname, classname, (void*) addobj, bufsize, splitlevel);
1561 }
1562 
1563 ////////////////////////////////////////////////////////////////////////////////
1564 /// Same as TTree::Branch but automatic detection of the class name.
1565 /// See TTree::Branch for other details.
1566 
1567 TBranch* TTree::BranchImp(const char* branchname, TClass* ptrClass, void* addobj, Int_t bufsize, Int_t splitlevel)
1568 {
1569  if (!ptrClass) {
1570  Error("Branch", "The pointer specified for %s is not of a class known to ROOT", branchname);
1571  return 0;
1572  }
1573  TClass* actualClass = 0;
1574  void** addr = (void**) addobj;
1575  if (addr && *addr) {
1576  actualClass = ptrClass->GetActualClass(*addr);
1577  if (!actualClass) {
1578  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",
1579  branchname, ptrClass->GetName());
1580  actualClass = ptrClass;
1581  } else if ((ptrClass != actualClass) && !actualClass->InheritsFrom(ptrClass)) {
1582  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());
1583  return 0;
1584  }
1585  } else {
1586  actualClass = ptrClass;
1587  }
1588  if (actualClass && actualClass->GetCollectionProxy() && dynamic_cast<TEmulatedCollectionProxy*>(actualClass->GetCollectionProxy())) {
1589  Error("Branch", writeStlWithoutProxyMsg,
1590  actualClass->GetName(), branchname, actualClass->GetName());
1591  return 0;
1592  }
1593  return Branch(branchname, actualClass->GetName(), (void*) addobj, bufsize, splitlevel);
1594 }
1595 
1596 ////////////////////////////////////////////////////////////////////////////////
1597 /// Same as TTree::Branch but automatic detection of the class name.
1598 /// See TTree::Branch for other details.
1599 
1600 TBranch* TTree::BranchImpRef(const char* branchname, const char *classname, TClass* ptrClass, void *addobj, Int_t bufsize, Int_t splitlevel)
1601 {
1602  TClass* claim = TClass::GetClass(classname);
1603  if (!ptrClass) {
1604  if (claim && claim->GetCollectionProxy() && dynamic_cast<TEmulatedCollectionProxy*>(claim->GetCollectionProxy())) {
1605  Error("Branch", writeStlWithoutProxyMsg,
1606  claim->GetName(), branchname, claim->GetName());
1607  return 0;
1608  } else if (claim == 0) {
1609  Error("Branch", "The pointer specified for %s is not of a class known to ROOT and %s is not a known class", branchname, classname);
1610  return 0;
1611  }
1612  ptrClass = claim;
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 (ptrClass && claim) {
1621  if (!(claim->InheritsFrom(ptrClass) || ptrClass->InheritsFrom(claim))) {
1622  // Note we currently do not warn in case of splicing or over-expectation).
1623  if (claim->IsLoaded() && ptrClass->IsLoaded() && strcmp( claim->GetTypeInfo()->name(), ptrClass->GetTypeInfo()->name() ) == 0) {
1624  // The type is the same according to the C++ type_info, we must be in the case of
1625  // a template of Double32_t. This is actually a correct case.
1626  } else {
1627  Error("Branch", "The class requested (%s) for \"%s\" is different from the type of the object passed (%s)",
1628  claim->GetName(), branchname, ptrClass->GetName());
1629  }
1630  } else if (actualClass && (claim != actualClass) && !actualClass->InheritsFrom(claim)) {
1631  if (claim->IsLoaded() && actualClass->IsLoaded() && strcmp( claim->GetTypeInfo()->name(), actualClass->GetTypeInfo()->name() ) == 0) {
1632  // The type is the same according to the C++ type_info, we must be in the case of
1633  // a template of Double32_t. This is actually a correct case.
1634  } else {
1635  Error("Branch", "The actual class (%s) of the object provided for the definition of the branch \"%s\" does not inherit from %s",
1636  actualClass->GetName(), branchname, claim->GetName());
1637  }
1638  }
1639  }
1640  if (!actualClass) {
1641  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",
1642  branchname, ptrClass->GetName());
1643  actualClass = ptrClass;
1644  } else if ((ptrClass != actualClass) && !actualClass->InheritsFrom(ptrClass)) {
1645  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());
1646  return 0;
1647  }
1648  if (actualClass && actualClass->GetCollectionProxy() && dynamic_cast<TEmulatedCollectionProxy*>(actualClass->GetCollectionProxy())) {
1649  Error("Branch", writeStlWithoutProxyMsg,
1650  actualClass->GetName(), branchname, actualClass->GetName());
1651  return 0;
1652  }
1653  return BronchExec(branchname, actualClass->GetName(), (void*) addobj, kFALSE, bufsize, splitlevel);
1654 }
1655 
1656 ////////////////////////////////////////////////////////////////////////////////
1657 /// Same as TTree::Branch but automatic detection of the class name.
1658 /// See TTree::Branch for other details.
1659 
1660 TBranch* TTree::BranchImpRef(const char* branchname, TClass* ptrClass, EDataType datatype, void* addobj, Int_t bufsize, Int_t splitlevel)
1661 {
1662  if (!ptrClass) {
1663  if (datatype == kOther_t || datatype == kNoType_t) {
1664  Error("Branch", "The pointer specified for %s is not of a class or type known to ROOT", branchname);
1665  } else {
1666  TString varname; varname.Form("%s/%c",branchname,DataTypeToChar(datatype));
1667  return Branch(branchname,addobj,varname.Data(),bufsize);
1668  }
1669  return 0;
1670  }
1671  TClass* actualClass = 0;
1672  if (!addobj) {
1673  Error("Branch", "Reference interface requires a valid object (for branch: %s)!", branchname);
1674  return 0;
1675  }
1676  actualClass = ptrClass->GetActualClass(addobj);
1677  if (!actualClass) {
1678  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",
1679  branchname, ptrClass->GetName());
1680  actualClass = ptrClass;
1681  } else if ((ptrClass != actualClass) && !actualClass->InheritsFrom(ptrClass)) {
1682  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());
1683  return 0;
1684  }
1685  if (actualClass && actualClass->GetCollectionProxy() && dynamic_cast<TEmulatedCollectionProxy*>(actualClass->GetCollectionProxy())) {
1686  Error("Branch", writeStlWithoutProxyMsg,
1687  actualClass->GetName(), branchname, actualClass->GetName());
1688  return 0;
1689  }
1690  return BronchExec(branchname, actualClass->GetName(), (void*) addobj, kFALSE, bufsize, splitlevel);
1691 }
1692 
1693 ////////////////////////////////////////////////////////////////////////////////
1694 // Wrapper to turn Branch call with an std::array into the relevant leaf list
1695 // call
1696 TBranch *TTree::BranchImpArr(const char *branchname, EDataType datatype, std::size_t N, void *addobj, Int_t bufsize,
1697  Int_t /* splitlevel */)
1698 {
1699  if (datatype == kOther_t || datatype == kNoType_t) {
1700  Error("Branch",
1701  "The inner type of the std::array passed specified for %s is not of a class or type known to ROOT",
1702  branchname);
1703  } else {
1704  TString varname;
1705  varname.Form("%s[%d]/%c", branchname, (int)N, DataTypeToChar(datatype));
1706  return Branch(branchname, addobj, varname.Data(), bufsize);
1707  }
1708  return nullptr;
1709 }
1710 
1711 ////////////////////////////////////////////////////////////////////////////////
1712 /// Deprecated function. Use next function instead.
1713 
1714 Int_t TTree::Branch(TList* li, Int_t bufsize /* = 32000 */ , Int_t splitlevel /* = 99 */)
1715 {
1716  return Branch((TCollection*) li, bufsize, splitlevel);
1717 }
1718 
1719 ////////////////////////////////////////////////////////////////////////////////
1720 /// Create one branch for each element in the collection.
1721 ///
1722 /// Each entry in the collection becomes a top level branch if the
1723 /// corresponding class is not a collection. If it is a collection, the entry
1724 /// in the collection becomes in turn top level branches, etc.
1725 /// The splitlevel is decreased by 1 every time a new collection is found.
1726 /// For example if list is a TObjArray*
1727 /// - if splitlevel = 1, one top level branch is created for each element
1728 /// of the TObjArray.
1729 /// - if splitlevel = 2, one top level branch is created for each array element.
1730 /// if, in turn, one of the array elements is a TCollection, one top level
1731 /// branch will be created for each element of this collection.
1732 ///
1733 /// In case a collection element is a TClonesArray, the special Tree constructor
1734 /// for TClonesArray is called.
1735 /// The collection itself cannot be a TClonesArray.
1736 ///
1737 /// The function returns the total number of branches created.
1738 ///
1739 /// If name is given, all branch names will be prefixed with name_.
1740 ///
1741 /// IMPORTANT NOTE1: This function should not be called with splitlevel < 1.
1742 ///
1743 /// IMPORTANT NOTE2: The branches created by this function will have names
1744 /// corresponding to the collection or object names. It is important
1745 /// to give names to collections to avoid misleading branch names or
1746 /// identical branch names. By default collections have a name equal to
1747 /// the corresponding class name, e.g. the default name for a TList is "TList".
1748 ///
1749 /// And in general, in case two or more master branches contain subbranches
1750 /// with identical names, one must add a "." (dot) character at the end
1751 /// of the master branch name. This will force the name of the subbranches
1752 /// to be of the form `master.subbranch` instead of simply `subbranch`.
1753 /// This situation happens when the top level object
1754 /// has two or more members referencing the same class.
1755 /// For example, if a Tree has two branches B1 and B2 corresponding
1756 /// to objects of the same class MyClass, one can do:
1757 /// ~~~ {.cpp}
1758 /// tree.Branch("B1.","MyClass",&b1,8000,1);
1759 /// tree.Branch("B2.","MyClass",&b2,8000,1);
1760 /// ~~~
1761 /// if MyClass has 3 members a,b,c, the two instructions above will generate
1762 /// subbranches called B1.a, B1.b ,B1.c, B2.a, B2.b, B2.c
1763 ///
1764 /// Example:
1765 /// ~~~ {.cpp}
1766 /// {
1767 /// TTree T("T","test list");
1768 /// TList *list = new TList();
1769 ///
1770 /// TObjArray *a1 = new TObjArray();
1771 /// a1->SetName("a1");
1772 /// list->Add(a1);
1773 /// TH1F *ha1a = new TH1F("ha1a","ha1",100,0,1);
1774 /// TH1F *ha1b = new TH1F("ha1b","ha1",100,0,1);
1775 /// a1->Add(ha1a);
1776 /// a1->Add(ha1b);
1777 /// TObjArray *b1 = new TObjArray();
1778 /// b1->SetName("b1");
1779 /// list->Add(b1);
1780 /// TH1F *hb1a = new TH1F("hb1a","hb1",100,0,1);
1781 /// TH1F *hb1b = new TH1F("hb1b","hb1",100,0,1);
1782 /// b1->Add(hb1a);
1783 /// b1->Add(hb1b);
1784 ///
1785 /// TObjArray *a2 = new TObjArray();
1786 /// a2->SetName("a2");
1787 /// list->Add(a2);
1788 /// TH1S *ha2a = new TH1S("ha2a","ha2",100,0,1);
1789 /// TH1S *ha2b = new TH1S("ha2b","ha2",100,0,1);
1790 /// a2->Add(ha2a);
1791 /// a2->Add(ha2b);
1792 ///
1793 /// T.Branch(list,16000,2);
1794 /// T.Print();
1795 /// }
1796 /// ~~~
1797 
1798 Int_t TTree::Branch(TCollection* li, Int_t bufsize /* = 32000 */, Int_t splitlevel /* = 99 */, const char* name /* = "" */)
1799 {
1800 
1801  if (!li) {
1802  return 0;
1803  }
1804  TObject* obj = 0;
1805  Int_t nbranches = GetListOfBranches()->GetEntries();
1806  if (li->InheritsFrom(TClonesArray::Class())) {
1807  Error("Branch", "Cannot call this constructor for a TClonesArray");
1808  return 0;
1809  }
1810  Int_t nch = strlen(name);
1811  TString branchname;
1812  TIter next(li);
1813  while ((obj = next())) {
1814  if ((splitlevel > 1) && obj->InheritsFrom(TCollection::Class()) && !obj->InheritsFrom(TClonesArray::Class())) {
1815  TCollection* col = (TCollection*) obj;
1816  if (nch) {
1817  branchname.Form("%s_%s_", name, col->GetName());
1818  } else {
1819  branchname.Form("%s_", col->GetName());
1820  }
1821  Branch(col, bufsize, splitlevel - 1, branchname);
1822  } else {
1823  if (nch && (name[nch-1] == '_')) {
1824  branchname.Form("%s%s", name, obj->GetName());
1825  } else {
1826  if (nch) {
1827  branchname.Form("%s_%s", name, obj->GetName());
1828  } else {
1829  branchname.Form("%s", obj->GetName());
1830  }
1831  }
1832  if (splitlevel > 99) {
1833  branchname += ".";
1834  }
1835  Bronch(branchname, obj->ClassName(), li->GetObjectRef(obj), bufsize, splitlevel - 1);
1836  }
1837  }
1838  return GetListOfBranches()->GetEntries() - nbranches;
1839 }
1840 
1841 ////////////////////////////////////////////////////////////////////////////////
1842 /// Create one branch for each element in the folder.
1843 /// Returns the total number of branches created.
1844 
1845 Int_t TTree::Branch(const char* foldername, Int_t bufsize /* = 32000 */, Int_t splitlevel /* = 99 */)
1846 {
1847  TObject* ob = gROOT->FindObjectAny(foldername);
1848  if (!ob) {
1849  return 0;
1850  }
1851  if (ob->IsA() != TFolder::Class()) {
1852  return 0;
1853  }
1854  Int_t nbranches = GetListOfBranches()->GetEntries();
1855  TFolder* folder = (TFolder*) ob;
1856  TIter next(folder->GetListOfFolders());
1857  TObject* obj = 0;
1858  char* curname = new char[1000];
1859  char occur[20];
1860  while ((obj = next())) {
1861  snprintf(curname,1000, "%s/%s", foldername, obj->GetName());
1862  if (obj->IsA() == TFolder::Class()) {
1863  Branch(curname, bufsize, splitlevel - 1);
1864  } else {
1865  void* add = (void*) folder->GetListOfFolders()->GetObjectRef(obj);
1866  for (Int_t i = 0; i < 1000; ++i) {
1867  if (curname[i] == 0) {
1868  break;
1869  }
1870  if (curname[i] == '/') {
1871  curname[i] = '.';
1872  }
1873  }
1874  Int_t noccur = folder->Occurence(obj);
1875  if (noccur > 0) {
1876  snprintf(occur,20, "_%d", noccur);
1877  strlcat(curname, occur,1000);
1878  }
1879  TBranchElement* br = (TBranchElement*) Bronch(curname, obj->ClassName(), add, bufsize, splitlevel - 1);
1880  if (br) br->SetBranchFolder();
1881  }
1882  }
1883  delete[] curname;
1884  return GetListOfBranches()->GetEntries() - nbranches;
1885 }
1886 
1887 ////////////////////////////////////////////////////////////////////////////////
1888 /// Create a new TTree Branch.
1889 ///
1890 /// This Branch constructor is provided to support non-objects in
1891 /// a Tree. The variables described in leaflist may be simple
1892 /// variables or structures. // See the two following
1893 /// constructors for writing objects in a Tree.
1894 ///
1895 /// By default the branch buffers are stored in the same file as the Tree.
1896 /// use TBranch::SetFile to specify a different file
1897 ///
1898 /// * address is the address of the first item of a structure.
1899 /// * leaflist is the concatenation of all the variable names and types
1900 /// separated by a colon character :
1901 /// The variable name and the variable type are separated by a slash (/).
1902 /// The variable type may be 0,1 or 2 characters. If no type is given,
1903 /// the type of the variable is assumed to be the same as the previous
1904 /// variable. If the first variable does not have a type, it is assumed
1905 /// of type F by default. The list of currently supported types is given below:
1906 /// - `C` : a character string terminated by the 0 character
1907 /// - `B` : an 8 bit signed integer (`Char_t`)
1908 /// - `b` : an 8 bit unsigned integer (`UChar_t`)
1909 /// - `S` : a 16 bit signed integer (`Short_t`)
1910 /// - `s` : a 16 bit unsigned integer (`UShort_t`)
1911 /// - `I` : a 32 bit signed integer (`Int_t`)
1912 /// - `i` : a 32 bit unsigned integer (`UInt_t`)
1913 /// - `F` : a 32 bit floating point (`Float_t`)
1914 /// - `f` : a 24 bit floating point with truncated mantissa (`Float16_t`)
1915 /// - `D` : a 64 bit floating point (`Double_t`)
1916 /// - `d` : a 24 bit truncated floating point (`Double32_t`)
1917 /// - `L` : a 64 bit signed integer (`Long64_t`)
1918 /// - `l` : a 64 bit unsigned integer (`ULong64_t`)
1919 /// - `O` : [the letter `o`, not a zero] a boolean (`Bool_t`)
1920 ///
1921 /// Arrays of values are supported with the following syntax:
1922 /// - If leaf name has the form var[nelem], where nelem is alphanumeric, then
1923 /// if nelem is a leaf name, it is used as the variable size of the array,
1924 /// otherwise return 0.
1925 /// - If leaf name has the form var[nelem], where nelem is a non-negative integer, then
1926 /// it is used as the fixed size of the array.
1927 /// - If leaf name has the form of a multi-dimensional array (e.g. var[nelem][nelem2])
1928 /// where nelem and nelem2 are non-negative integer) then
1929 /// it is used as a 2 dimensional array of fixed size.
1930 /// - In case of the truncated floating point types (Float16_t and Double32_t) you can
1931 /// furthermore specify the range in the style [xmin,xmax] or [xmin,xmax,nbits] after
1932 /// the type character. See `TStreamerElement::GetRange()` for further information.
1933 ///
1934 /// Any of other form is not supported.
1935 ///
1936 /// Note that the TTree will assume that all the item are contiguous in memory.
1937 /// On some platform, this is not always true of the member of a struct or a class,
1938 /// due to padding and alignment. Sorting your data member in order of decreasing
1939 /// sizeof usually leads to their being contiguous in memory.
1940 ///
1941 /// * bufsize is the buffer size in bytes for this branch
1942 /// The default value is 32000 bytes and should be ok for most cases.
1943 /// You can specify a larger value (e.g. 256000) if your Tree is not split
1944 /// and each entry is large (Megabytes)
1945 /// A small value for bufsize is optimum if you intend to access
1946 /// the entries in the Tree randomly and your Tree is in split mode.
1947 
1948 TBranch* TTree::Branch(const char* name, void* address, const char* leaflist, Int_t bufsize /* = 32000 */)
1949 {
1950  TBranch* branch = new TBranch(this, name, address, leaflist, bufsize);
1951  if (branch->IsZombie()) {
1952  delete branch;
1953  branch = 0;
1954  return 0;
1955  }
1956  fBranches.Add(branch);
1957  return branch;
1958 }
1959 
1960 ////////////////////////////////////////////////////////////////////////////////
1961 /// Create a new branch with the object of class classname at address addobj.
1962 ///
1963 /// WARNING:
1964 ///
1965 /// Starting with Root version 3.01, the Branch function uses the new style
1966 /// branches (TBranchElement). To get the old behaviour, you can:
1967 /// - call BranchOld or
1968 /// - call TTree::SetBranchStyle(0)
1969 ///
1970 /// Note that with the new style, classname does not need to derive from TObject.
1971 /// It must derived from TObject if the branch style has been set to 0 (old)
1972 ///
1973 /// Note: See the comments in TBranchElement::SetAddress() for a more
1974 /// detailed discussion of the meaning of the addobj parameter in
1975 /// the case of new-style branches.
1976 ///
1977 /// Use splitlevel < 0 instead of splitlevel=0 when the class
1978 /// has a custom Streamer
1979 ///
1980 /// Note: if the split level is set to the default (99), TTree::Branch will
1981 /// not issue a warning if the class can not be split.
1982 
1983 TBranch* TTree::Branch(const char* name, const char* classname, void* addobj, Int_t bufsize /* = 32000 */, Int_t splitlevel /* = 99 */)
1984 {
1985  if (fgBranchStyle == 1) {
1986  return Bronch(name, classname, addobj, bufsize, splitlevel);
1987  } else {
1988  if (splitlevel < 0) {
1989  splitlevel = 0;
1990  }
1991  return BranchOld(name, classname, addobj, bufsize, splitlevel);
1992  }
1993 }
1994 
1995 ////////////////////////////////////////////////////////////////////////////////
1996 /// Create a new TTree BranchObject.
1997 ///
1998 /// Build a TBranchObject for an object of class classname.
1999 /// addobj is the address of a pointer to an object of class classname.
2000 /// IMPORTANT: classname must derive from TObject.
2001 /// The class dictionary must be available (ClassDef in class header).
2002 ///
2003 /// This option requires access to the library where the corresponding class
2004 /// is defined. Accessing one single data member in the object implies
2005 /// reading the full object.
2006 /// See the next Branch constructor for a more efficient storage
2007 /// in case the entry consists of arrays of identical objects.
2008 ///
2009 /// By default the branch buffers are stored in the same file as the Tree.
2010 /// use TBranch::SetFile to specify a different file
2011 ///
2012 /// IMPORTANT NOTE about branch names:
2013 ///
2014 /// And in general, in case two or more master branches contain subbranches
2015 /// with identical names, one must add a "." (dot) character at the end
2016 /// of the master branch name. This will force the name of the subbranches
2017 /// to be of the form `master.subbranch` instead of simply `subbranch`.
2018 /// This situation happens when the top level object
2019 /// has two or more members referencing the same class.
2020 /// For example, if a Tree has two branches B1 and B2 corresponding
2021 /// to objects of the same class MyClass, one can do:
2022 /// ~~~ {.cpp}
2023 /// tree.Branch("B1.","MyClass",&b1,8000,1);
2024 /// tree.Branch("B2.","MyClass",&b2,8000,1);
2025 /// ~~~
2026 /// if MyClass has 3 members a,b,c, the two instructions above will generate
2027 /// subbranches called B1.a, B1.b ,B1.c, B2.a, B2.b, B2.c
2028 ///
2029 /// bufsize is the buffer size in bytes for this branch
2030 /// The default value is 32000 bytes and should be ok for most cases.
2031 /// You can specify a larger value (e.g. 256000) if your Tree is not split
2032 /// and each entry is large (Megabytes)
2033 /// A small value for bufsize is optimum if you intend to access
2034 /// the entries in the Tree randomly and your Tree is in split mode.
2035 
2036 TBranch* TTree::BranchOld(const char* name, const char* classname, void* addobj, Int_t bufsize /* = 32000 */, Int_t splitlevel /* = 1 */)
2037 {
2038  TClass* cl = TClass::GetClass(classname);
2039  if (!cl) {
2040  Error("BranchOld", "Cannot find class: '%s'", classname);
2041  return 0;
2042  }
2043  if (!cl->IsTObject()) {
2044  if (fgBranchStyle == 0) {
2045  Fatal("BranchOld", "The requested class ('%s') does not inherit from TObject.\n"
2046  "\tfgBranchStyle is set to zero requesting by default to use BranchOld.\n"
2047  "\tIf this is intentional use Bronch instead of Branch or BranchOld.", classname);
2048  } else {
2049  Fatal("BranchOld", "The requested class ('%s') does not inherit from TObject.\n"
2050  "\tYou can not use BranchOld to store objects of this type.",classname);
2051  }
2052  return 0;
2053  }
2054  TBranch* branch = new TBranchObject(this, name, classname, addobj, bufsize, splitlevel);
2055  fBranches.Add(branch);
2056  if (!splitlevel) {
2057  return branch;
2058  }
2059  // We are going to fully split the class now.
2060  TObjArray* blist = branch->GetListOfBranches();
2061  const char* rdname = 0;
2062  const char* dname = 0;
2063  TString branchname;
2064  char** apointer = (char**) addobj;
2065  TObject* obj = (TObject*) *apointer;
2066  Bool_t delobj = kFALSE;
2067  if (!obj) {
2068  obj = (TObject*) cl->New();
2069  delobj = kTRUE;
2070  }
2071  // Build the StreamerInfo if first time for the class.
2072  BuildStreamerInfo(cl, obj);
2073  // Loop on all public data members of the class and its base classes.
2074  Int_t lenName = strlen(name);
2075  Int_t isDot = 0;
2076  if (name[lenName-1] == '.') {
2077  isDot = 1;
2078  }
2079  TBranch* branch1 = 0;
2080  TRealData* rd = 0;
2081  TRealData* rdi = 0;
2082  TIter nexti(cl->GetListOfRealData());
2083  TIter next(cl->GetListOfRealData());
2084  // Note: This loop results in a full split because the
2085  // real data list includes all data members of
2086  // data members.
2087  while ((rd = (TRealData*) next())) {
2088  if (rd->TestBit(TRealData::kTransient)) continue;
2089 
2090  // Loop over all data members creating branches for each one.
2091  TDataMember* dm = rd->GetDataMember();
2092  if (!dm->IsPersistent()) {
2093  // Do not process members with an "!" as the first character in the comment field.
2094  continue;
2095  }
2096  if (rd->IsObject()) {
2097  // We skip data members of class type.
2098  // But we do build their real data, their
2099  // streamer info, and write their streamer
2100  // info to the current directory's file.
2101  // Oh yes, and we also do this for all of
2102  // their base classes.
2103  TClass* clm = TClass::GetClass(dm->GetFullTypeName());
2104  if (clm) {
2105  BuildStreamerInfo(clm, (char*) obj + rd->GetThisOffset());
2106  }
2107  continue;
2108  }
2109  rdname = rd->GetName();
2110  dname = dm->GetName();
2111  if (cl->CanIgnoreTObjectStreamer()) {
2112  // Skip the TObject base class data members.
2113  // FIXME: This prevents a user from ever
2114  // using these names themself!
2115  if (!strcmp(dname, "fBits")) {
2116  continue;
2117  }
2118  if (!strcmp(dname, "fUniqueID")) {
2119  continue;
2120  }
2121  }
2122  TDataType* dtype = dm->GetDataType();
2123  Int_t code = 0;
2124  if (dtype) {
2125  code = dm->GetDataType()->GetType();
2126  }
2127  // Encode branch name. Use real data member name
2128  branchname = rdname;
2129  if (isDot) {
2130  if (dm->IsaPointer()) {
2131  // FIXME: This is wrong! The asterisk is not usually in the front!
2132  branchname.Form("%s%s", name, &rdname[1]);
2133  } else {
2134  branchname.Form("%s%s", name, &rdname[0]);
2135  }
2136  }
2137  // FIXME: Change this to a string stream.
2138  TString leaflist;
2139  Int_t offset = rd->GetThisOffset();
2140  char* pointer = ((char*) obj) + offset;
2141  if (dm->IsaPointer()) {
2142  // We have a pointer to an object or a pointer to an array of basic types.
2143  TClass* clobj = 0;
2144  if (!dm->IsBasic()) {
2145  clobj = TClass::GetClass(dm->GetTypeName());
2146  }
2147  if (clobj && clobj->InheritsFrom(TClonesArray::Class())) {
2148  // We have a pointer to a clones array.
2149  char* cpointer = (char*) pointer;
2150  char** ppointer = (char**) cpointer;
2151  TClonesArray* li = (TClonesArray*) *ppointer;
2152  if (splitlevel != 2) {
2153  if (isDot) {
2154  branch1 = new TBranchClones(branch,branchname, pointer, bufsize);
2155  } else {
2156  // FIXME: This is wrong! The asterisk is not usually in the front!
2157  branch1 = new TBranchClones(branch,&branchname.Data()[1], pointer, bufsize);
2158  }
2159  blist->Add(branch1);
2160  } else {
2161  if (isDot) {
2162  branch1 = new TBranchObject(branch, branchname, li->ClassName(), pointer, bufsize);
2163  } else {
2164  // FIXME: This is wrong! The asterisk is not usually in the front!
2165  branch1 = new TBranchObject(branch, &branchname.Data()[1], li->ClassName(), pointer, bufsize);
2166  }
2167  blist->Add(branch1);
2168  }
2169  } else if (clobj) {
2170  // We have a pointer to an object.
2171  //
2172  // It must be a TObject object.
2173  if (!clobj->IsTObject()) {
2174  continue;
2175  }
2176  branch1 = new TBranchObject(branch, dname, clobj->GetName(), pointer, bufsize, 0);
2177  if (isDot) {
2178  branch1->SetName(branchname);
2179  } else {
2180  // FIXME: This is wrong! The asterisk is not usually in the front!
2181  // Do not use the first character (*).
2182  branch1->SetName(&branchname.Data()[1]);
2183  }
2184  blist->Add(branch1);
2185  } else {
2186  // We have a pointer to an array of basic types.
2187  //
2188  // Check the comments in the text of the code for an index specification.
2189  const char* index = dm->GetArrayIndex();
2190  if (index[0]) {
2191  // We are a pointer to a varying length array of basic types.
2192  //check that index is a valid data member name
2193  //if member is part of an object (e.g. fA and index=fN)
2194  //index must be changed from fN to fA.fN
2195  TString aindex (rd->GetName());
2196  Ssiz_t rdot = aindex.Last('.');
2197  if (rdot>=0) {
2198  aindex.Remove(rdot+1);
2199  aindex.Append(index);
2200  }
2201  nexti.Reset();
2202  while ((rdi = (TRealData*) nexti())) {
2203  if (rdi->TestBit(TRealData::kTransient)) continue;
2204 
2205  if (!strcmp(rdi->GetName(), index)) {
2206  break;
2207  }
2208  if (!strcmp(rdi->GetName(), aindex)) {
2209  index = rdi->GetName();
2210  break;
2211  }
2212  }
2213 
2214  char vcode = DataTypeToChar((EDataType)code);
2215  // Note that we differentiate between strings and
2216  // char array by the fact that there is NO specified
2217  // size for a string (see next if (code == 1)
2218 
2219  if (vcode) {
2220  leaflist.Form("%s[%s]/%c", &rdname[0], index, vcode);
2221  } else {
2222  Error("BranchOld", "Cannot create branch for rdname: %s code: %d", branchname.Data(), code);
2223  leaflist = "";
2224  }
2225  } else {
2226  // We are possibly a character string.
2227  if (code == 1) {
2228  // We are a character string.
2229  leaflist.Form("%s/%s", dname, "C");
2230  } else {
2231  // Invalid array specification.
2232  // FIXME: We need an error message here.
2233  continue;
2234  }
2235  }
2236  // There are '*' in both the branchname and leaflist, remove them.
2237  TString bname( branchname );
2238  bname.ReplaceAll("*","");
2239  leaflist.ReplaceAll("*","");
2240  // Add the branch to the tree and indicate that the address
2241  // is that of a pointer to be dereferenced before using.
2242  branch1 = new TBranch(branch, bname, *((void**) pointer), leaflist, bufsize);
2243  TLeaf* leaf = (TLeaf*) branch1->GetListOfLeaves()->At(0);
2244  leaf->SetBit(TLeaf::kIndirectAddress);
2245  leaf->SetAddress((void**) pointer);
2246  blist->Add(branch1);
2247  }
2248  } else if (dm->IsBasic()) {
2249  // We have a basic type.
2250 
2251  char vcode = DataTypeToChar((EDataType)code);
2252  if (vcode) {
2253  leaflist.Form("%s/%c", rdname, vcode);
2254  } else {
2255  Error("BranchOld", "Cannot create branch for rdname: %s code: %d", branchname.Data(), code);
2256  leaflist = "";
2257  }
2258  branch1 = new TBranch(branch, branchname, pointer, leaflist, bufsize);
2259  branch1->SetTitle(rdname);
2260  blist->Add(branch1);
2261  } else {
2262  // We have a class type.
2263  // Note: This cannot happen due to the rd->IsObject() test above.
2264  // FIXME: Put an error message here just in case.
2265  }
2266  if (branch1) {
2267  branch1->SetOffset(offset);
2268  } else {
2269  Warning("BranchOld", "Cannot process member: '%s'", rdname);
2270  }
2271  }
2272  if (delobj) {
2273  delete obj;
2274  obj = 0;
2275  }
2276  return branch;
2277 }
2278 
2279 ////////////////////////////////////////////////////////////////////////////////
2280 /// Build the optional branch supporting the TRefTable.
2281 /// This branch will keep all the information to find the branches
2282 /// containing referenced objects.
2283 ///
2284 /// At each Tree::Fill, the branch numbers containing the
2285 /// referenced objects are saved to the TBranchRef basket.
2286 /// When the Tree header is saved (via TTree::Write), the branch
2287 /// is saved keeping the information with the pointers to the branches
2288 /// having referenced objects.
2289 
2290 TBranch* TTree::BranchRef()
2291 {
2292  if (!fBranchRef) {
2293  fBranchRef = new TBranchRef(this);
2294  }
2295  return fBranchRef;
2296 }
2297 
2298 ////////////////////////////////////////////////////////////////////////////////
2299 /// Create a new TTree BranchElement.
2300 ///
2301 /// ## WARNING about this new function
2302 ///
2303 /// This function is designed to replace the internal
2304 /// implementation of the old TTree::Branch (whose implementation
2305 /// has been moved to BranchOld).
2306 ///
2307 /// NOTE: The 'Bronch' method supports only one possible calls
2308 /// signature (where the object type has to be specified
2309 /// explicitly and the address must be the address of a pointer).
2310 /// For more flexibility use 'Branch'. Use Bronch only in (rare)
2311 /// cases (likely to be legacy cases) where both the new and old
2312 /// implementation of Branch needs to be used at the same time.
2313 ///
2314 /// This function is far more powerful than the old Branch
2315 /// function. It supports the full C++, including STL and has
2316 /// the same behaviour in split or non-split mode. classname does
2317 /// not have to derive from TObject. The function is based on
2318 /// the new TStreamerInfo.
2319 ///
2320 /// Build a TBranchElement for an object of class classname.
2321 ///
2322 /// addr is the address of a pointer to an object of class
2323 /// classname. The class dictionary must be available (ClassDef
2324 /// in class header).
2325 ///
2326 /// Note: See the comments in TBranchElement::SetAddress() for a more
2327 /// detailed discussion of the meaning of the addr parameter.
2328 ///
2329 /// This option requires access to the library where the
2330 /// corresponding class is defined. Accessing one single data
2331 /// member in the object implies reading the full object.
2332 ///
2333 /// By default the branch buffers are stored in the same file as the Tree.
2334 /// use TBranch::SetFile to specify a different file
2335 ///
2336 /// IMPORTANT NOTE about branch names:
2337 ///
2338 /// And in general, in case two or more master branches contain subbranches
2339 /// with identical names, one must add a "." (dot) character at the end
2340 /// of the master branch name. This will force the name of the subbranches
2341 /// to be of the form `master.subbranch` instead of simply `subbranch`.
2342 /// This situation happens when the top level object
2343 /// has two or more members referencing the same class.
2344 /// For example, if a Tree has two branches B1 and B2 corresponding
2345 /// to objects of the same class MyClass, one can do:
2346 /// ~~~ {.cpp}
2347 /// tree.Branch("B1.","MyClass",&b1,8000,1);
2348 /// tree.Branch("B2.","MyClass",&b2,8000,1);
2349 /// ~~~
2350 /// if MyClass has 3 members a,b,c, the two instructions above will generate
2351 /// subbranches called B1.a, B1.b ,B1.c, B2.a, B2.b, B2.c
2352 ///
2353 /// bufsize is the buffer size in bytes for this branch
2354 /// The default value is 32000 bytes and should be ok for most cases.
2355 /// You can specify a larger value (e.g. 256000) if your Tree is not split
2356 /// and each entry is large (Megabytes)
2357 /// A small value for bufsize is optimum if you intend to access
2358 /// the entries in the Tree randomly and your Tree is in split mode.
2359 ///
2360 /// Use splitlevel < 0 instead of splitlevel=0 when the class
2361 /// has a custom Streamer
2362 ///
2363 /// Note: if the split level is set to the default (99), TTree::Branch will
2364 /// not issue a warning if the class can not be split.
2365 
2366 TBranch* TTree::Bronch(const char* name, const char* classname, void* addr, Int_t bufsize /* = 32000 */, Int_t splitlevel /* = 99 */)
2367 {
2368  return BronchExec(name, classname, addr, kTRUE, bufsize, splitlevel);
2369 }
2370 
2371 ////////////////////////////////////////////////////////////////////////////////
2372 /// Helper function implementing TTree::Bronch and TTree::Branch(const char *name, T &obj);
2373 
2374 TBranch* TTree::BronchExec(const char* name, const char* classname, void* addr, Bool_t isptrptr, Int_t bufsize /* = 32000 */, Int_t splitlevel /* = 99 */)
2375 {
2376  TClass* cl = TClass::GetClass(classname);
2377  if (!cl) {
2378  Error("Bronch", "Cannot find class:%s", classname);
2379  return 0;
2380  }
2381 
2382  //if splitlevel <= 0 and class has a custom Streamer, we must create
2383  //a TBranchObject. We cannot assume that TClass::ReadBuffer is consistent
2384  //with the custom Streamer. The penalty is that one cannot process
2385  //this Tree without the class library containing the class.
2386 
2387  char* objptr = 0;
2388  if (!isptrptr) {
2389  objptr = (char*)addr;
2390  } else if (addr) {
2391  objptr = *((char**) addr);
2392  }
2393 
2394  if (cl == TClonesArray::Class()) {
2395  TClonesArray* clones = (TClonesArray*) objptr;
2396  if (!clones) {
2397  Error("Bronch", "Pointer to TClonesArray is null");
2398  return 0;
2399  }
2400  if (!clones->GetClass()) {
2401  Error("Bronch", "TClonesArray with no class defined in branch: %s", name);
2402  return 0;
2403  }
2404  if (!clones->GetClass()->HasDataMemberInfo()) {
2405  Error("Bronch", "TClonesArray with no dictionary defined in branch: %s", name);
2406  return 0;
2407  }
2408  bool hasCustomStreamer = clones->GetClass()->TestBit(TClass::kHasCustomStreamerMember);
2409  if (splitlevel > 0) {
2410  if (hasCustomStreamer)
2411  Warning("Bronch", "Using split mode on a class: %s with a custom Streamer", clones->GetClass()->GetName());
2412  } else {
2413  if (hasCustomStreamer) clones->BypassStreamer(kFALSE);
2414  TBranchObject *branch = new TBranchObject(this,name,classname,addr,bufsize,0,/*compress=*/ -1,isptrptr);
2415  fBranches.Add(branch);
2416  return branch;
2417  }
2418  }
2419 
2420  if (cl->GetCollectionProxy()) {
2421  TVirtualCollectionProxy* collProxy = cl->GetCollectionProxy();
2422  //if (!collProxy) {
2423  // Error("Bronch", "%s is missing its CollectionProxy (for branch %s)", classname, name);
2424  //}
2425  TClass* inklass = collProxy->GetValueClass();
2426  if (!inklass && (collProxy->GetType() == 0)) {
2427  Error("Bronch", "%s with no class defined in branch: %s", classname, name);
2428  return 0;
2429  }
2430  if ((splitlevel > 0) && inklass && (inklass->GetCollectionProxy() == 0)) {
2431  ROOT::ESTLType stl = cl->GetCollectionType();
2432  if ((stl != ROOT::kSTLmap) && (stl != ROOT::kSTLmultimap)) {
2433  if (!inklass->HasDataMemberInfo()) {
2434  Error("Bronch", "Container with no dictionary defined in branch: %s", name);
2435  return 0;
2436  }
2437  if (inklass->TestBit(TClass::kHasCustomStreamerMember)) {
2438  Warning("Bronch", "Using split mode on a class: %s with a custom Streamer", inklass->GetName());
2439  }
2440  }
2441  }
2442  //-------------------------------------------------------------------------
2443  // If the splitting switch is enabled, the split level is big enough and
2444  // the collection contains pointers we can split it
2445  //////////////////////////////////////////////////////////////////////////
2446 
2447  TBranch *branch;
2448  if( splitlevel > kSplitCollectionOfPointers && collProxy->HasPointers() )
2449  branch = new TBranchSTL( this, name, collProxy, bufsize, splitlevel );
2450  else
2451  branch = new TBranchElement(this, name, collProxy, bufsize, splitlevel);
2452  fBranches.Add(branch);
2453  if (isptrptr) {
2454  branch->SetAddress(addr);
2455  } else {
2456  branch->SetObject(addr);
2457  }
2458  return branch;
2459  }
2460 
2461  Bool_t hasCustomStreamer = kFALSE;
2462  if (!cl->HasDataMemberInfo() && !cl->GetCollectionProxy()) {
2463  Error("Bronch", "Cannot find dictionary for class: %s", classname);
2464  return 0;
2465  }
2466 
2467  if (!cl->GetCollectionProxy() && cl->TestBit(TClass::kHasCustomStreamerMember)) {
2468  // Not an STL container and the linkdef file had a "-" after the class name.
2469  hasCustomStreamer = kTRUE;
2470  }
2471 
2472  if (splitlevel < 0 || ((splitlevel == 0) && hasCustomStreamer && cl->IsTObject())) {
2473  TBranchObject* branch = new TBranchObject(this, name, classname, addr, bufsize, 0, /*compress=*/ ROOT::RCompressionSetting::EAlgorithm::kInherit, isptrptr);
2474  fBranches.Add(branch);
2475  return branch;
2476  }
2477 
2478  if (cl == TClonesArray::Class()) {
2479  // Special case of TClonesArray.
2480  // No dummy object is created.
2481  // The streamer info is not rebuilt unoptimized.
2482  // No dummy top-level branch is created.
2483  // No splitting is attempted.
2484  TBranchElement* branch = new TBranchElement(this, name, (TClonesArray*) objptr, bufsize, splitlevel%kSplitCollectionOfPointers);
2485  fBranches.Add(branch);
2486  if (isptrptr) {
2487  branch->SetAddress(addr);
2488  } else {
2489  branch->SetObject(addr);
2490  }
2491  return branch;
2492  }
2493 
2494  //
2495  // If we are not given an object to use as an i/o buffer
2496  // then create a temporary one which we will delete just
2497  // before returning.
2498  //
2499 
2500  Bool_t delobj = kFALSE;
2501 
2502  if (!objptr) {
2503  objptr = (char*) cl->New();
2504  delobj = kTRUE;
2505  }
2506 
2507  //
2508  // Avoid splitting unsplittable classes.
2509  //
2510 
2511  if ((splitlevel > 0) && !cl->CanSplit()) {
2512  if (splitlevel != 99) {
2513  Warning("Bronch", "%s cannot be split, resetting splitlevel to 0", cl->GetName());
2514  }
2515  splitlevel = 0;
2516  }
2517 
2518  //
2519  // Make sure the streamer info is built and fetch it.
2520  //
2521  // If we are splitting, then make sure the streamer info
2522  // is built unoptimized (data members are not combined).
2523  //
2524 
2525  TStreamerInfo* sinfo = BuildStreamerInfo(cl, objptr, splitlevel==0);
2526  if (!sinfo) {
2527  Error("Bronch", "Cannot build the StreamerInfo for class: %s", cl->GetName());
2528  return 0;
2529  }
2530 
2531  //
2532  // Create a dummy top level branch object.
2533  //
2534 
2535  Int_t id = -1;
2536  if (splitlevel > 0) {
2537  id = -2;
2538  }
2539  TBranchElement* branch = new TBranchElement(this, name, sinfo, id, objptr, bufsize, splitlevel);
2540  fBranches.Add(branch);
2541 
2542  //
2543  // Do splitting, if requested.
2544  //
2545 
2546  if (splitlevel%kSplitCollectionOfPointers > 0) {
2547  branch->Unroll(name, cl, sinfo, objptr, bufsize, splitlevel);
2548  }
2549 
2550  //
2551  // Setup our offsets into the user's i/o buffer.
2552  //
2553 
2554  if (isptrptr) {
2555  branch->SetAddress(addr);
2556  } else {
2557  branch->SetObject(addr);
2558  }
2559 
2560  if (delobj) {
2561  cl->Destructor(objptr);
2562  objptr = 0;
2563  }
2564 
2565  return branch;
2566 }
2567 
2568 ////////////////////////////////////////////////////////////////////////////////
2569 /// Browse content of the TTree.
2570 
2571 void TTree::Browse(TBrowser* b)
2572 {
2573  fBranches.Browse(b);
2574  if (fUserInfo) {
2575  if (strcmp("TList",fUserInfo->GetName())==0) {
2576  fUserInfo->SetName("UserInfo");
2577  b->Add(fUserInfo);
2578  fUserInfo->SetName("TList");
2579  } else {
2580  b->Add(fUserInfo);
2581  }
2582  }
2583 }
2584 
2585 ////////////////////////////////////////////////////////////////////////////////
2586 /// Build a Tree Index (default is TTreeIndex).
2587 /// See a description of the parameters and functionality in
2588 /// TTreeIndex::TTreeIndex().
2589 ///
2590 /// The return value is the number of entries in the Index (< 0 indicates failure).
2591 ///
2592 /// A TTreeIndex object pointed by fTreeIndex is created.
2593 /// This object will be automatically deleted by the TTree destructor.
2594 /// If an index is already existing, this is replaced by the new one without being
2595 /// deleted. This behaviour prevents the deletion of a previously external index
2596 /// assigned to the TTree via the TTree::SetTreeIndex() method.
2597 /// See also comments in TTree::SetTreeIndex().
2598 
2599 Int_t TTree::BuildIndex(const char* majorname, const char* minorname /* = "0" */)
2600 {
2601  fTreeIndex = GetPlayer()->BuildIndex(this, majorname, minorname);
2602  if (fTreeIndex->IsZombie()) {
2603  delete fTreeIndex;
2604  fTreeIndex = 0;
2605  return 0;
2606  }
2607  return fTreeIndex->GetN();
2608 }
2609 
2610 ////////////////////////////////////////////////////////////////////////////////
2611 /// Build StreamerInfo for class cl.
2612 /// pointer is an optional argument that may contain a pointer to an object of cl.
2613 
2614 TStreamerInfo* TTree::BuildStreamerInfo(TClass* cl, void* pointer /* = 0 */, Bool_t canOptimize /* = kTRUE */ )
2615 {
2616  if (!cl) {
2617  return 0;
2618  }
2619  cl->BuildRealData(pointer);
2620  TStreamerInfo* sinfo = (TStreamerInfo*)cl->GetStreamerInfo(cl->GetClassVersion());
2621 
2622  // Create StreamerInfo for all base classes.
2623  TBaseClass* base = 0;
2624  TIter nextb(cl->GetListOfBases());
2625  while((base = (TBaseClass*) nextb())) {
2626  if (base->IsSTLContainer()) {
2627  continue;
2628  }
2629  TClass* clm = TClass::GetClass(base->GetName());
2630  BuildStreamerInfo(clm, pointer, canOptimize);
2631  }
2632  if (sinfo && fDirectory) {
2633  sinfo->ForceWriteInfo(fDirectory->GetFile());
2634  }
2635  return sinfo;
2636 }
2637 
2638 ////////////////////////////////////////////////////////////////////////////////
2639 /// Called by TTree::Fill() when file has reached its maximum fgMaxTreeSize.
2640 /// Create a new file. If the original file is named "myfile.root",
2641 /// subsequent files are named "myfile_1.root", "myfile_2.root", etc.
2642 ///
2643 /// Returns a pointer to the new file.
2644 ///
2645 /// Currently, the automatic change of file is restricted
2646 /// to the case where the tree is in the top level directory.
2647 /// The file should not contain sub-directories.
2648 ///
2649 /// Before switching to a new file, the tree header is written
2650 /// to the current file, then the current file is closed.
2651 ///
2652 /// To process the multiple files created by ChangeFile, one must use
2653 /// a TChain.
2654 ///
2655 /// The new file name has a suffix "_N" where N is equal to fFileNumber+1.
2656 /// By default a Root session starts with fFileNumber=0. One can set
2657 /// fFileNumber to a different value via TTree::SetFileNumber.
2658 /// In case a file named "_N" already exists, the function will try
2659 /// a file named "__N", then "___N", etc.
2660 ///
2661 /// fgMaxTreeSize can be set via the static function TTree::SetMaxTreeSize.
2662 /// The default value of fgMaxTreeSize is 100 Gigabytes.
2663 ///
2664 /// If the current file contains other objects like TH1 and TTree,
2665 /// these objects are automatically moved to the new file.
2666 ///
2667 /// IMPORTANT NOTE:
2668 ///
2669 /// Be careful when writing the final Tree header to the file!
2670 ///
2671 /// Don't do:
2672 /// ~~~ {.cpp}
2673 /// TFile *file = new TFile("myfile.root","recreate");
2674 /// TTree *T = new TTree("T","title");
2675 /// T->Fill(); //loop
2676 /// file->Write();
2677 /// file->Close();
2678 /// ~~~
2679 /// but do the following:
2680 /// ~~~ {.cpp}
2681 /// TFile *file = new TFile("myfile.root","recreate");
2682 /// TTree *T = new TTree("T","title");
2683 /// T->Fill(); //loop
2684 /// file = T->GetCurrentFile(); //to get the pointer to the current file
2685 /// file->Write();
2686 /// file->Close();
2687 /// ~~~
2688 
2689 TFile* TTree::ChangeFile(TFile* file)
2690 {
2691  file->cd();
2692  Write();
2693  Reset();
2694  constexpr auto kBufSize = 2000;
2695  char* fname = new char[kBufSize];
2696  ++fFileNumber;
2697  char uscore[10];
2698  for (Int_t i = 0; i < 10; ++i) {
2699  uscore[i] = 0;
2700  }
2701  Int_t nus = 0;
2702  // Try to find a suitable file name that does not already exist.
2703  while (nus < 10) {
2704  uscore[nus] = '_';
2705  fname[0] = 0;
2706  strlcpy(fname, file->GetName(), kBufSize);
2707 
2708  if (fFileNumber > 1) {
2709  char* cunder = strrchr(fname, '_');
2710  if (cunder) {
2711  snprintf(cunder, kBufSize - Int_t(cunder - fname), "%s%d", uscore, fFileNumber);
2712  const char* cdot = strrchr(file->GetName(), '.');
2713  if (cdot) {
2714  strlcat(fname, cdot, kBufSize);
2715  }
2716  } else {
2717  char fcount[21];
2718  snprintf(fcount,21, "%s%d", uscore, fFileNumber);
2719  strlcat(fname, fcount, kBufSize);
2720  }
2721  } else {
2722  char* cdot = strrchr(fname, '.');
2723  if (cdot) {
2724  snprintf(cdot, kBufSize - Int_t(fname-cdot), "%s%d", uscore, fFileNumber);
2725  strlcat(fname, strrchr(file->GetName(), '.'), kBufSize);
2726  } else {
2727  char fcount[21];
2728  snprintf(fcount,21, "%s%d", uscore, fFileNumber);
2729  strlcat(fname, fcount, kBufSize);
2730  }
2731  }
2732  if (gSystem->AccessPathName(fname)) {
2733  break;
2734  }
2735  ++nus;
2736  Warning("ChangeFile", "file %s already exist, trying with %d underscores", fname, nus+1);
2737  }
2738  Int_t compress = file->GetCompressionSettings();
2739  TFile* newfile = TFile::Open(fname, "recreate", "chain files", compress);
2740  if (newfile == 0) {
2741  Error("Fill","Failed to open new file %s, continuing as a memory tree.",fname);
2742  } else {
2743  Printf("Fill: Switching to new file: %s", fname);
2744  }
2745  // The current directory may contain histograms and trees.
2746  // These objects must be moved to the new file.
2747  TBranch* branch = 0;
2748  TObject* obj = 0;
2749  while ((obj = file->GetList()->First())) {
2750  file->Remove(obj);
2751  // Histogram: just change the directory.
2752  if (obj->InheritsFrom("TH1")) {
2753  gROOT->ProcessLine(TString::Format("((%s*)0x%lx)->SetDirectory((TDirectory*)0x%lx);", obj->ClassName(), (Long_t) obj, (Long_t) newfile));
2754  continue;
2755  }
2756  // Tree: must save all trees in the old file, reset them.
2757  if (obj->InheritsFrom(TTree::Class())) {
2758  TTree* t = (TTree*) obj;
2759  if (t != this) {
2760  t->AutoSave();
2761  t->Reset();
2762  t->fFileNumber = fFileNumber;
2763  }
2764  t->SetDirectory(newfile);
2765  TIter nextb(t->GetListOfBranches());
2766  while ((branch = (TBranch*)nextb())) {
2767  branch->SetFile(newfile);
2768  }
2769  if (t->GetBranchRef()) {
2770  t->GetBranchRef()->SetFile(newfile);
2771  }
2772  continue;
2773  }
2774  // Not a TH1 or a TTree, move object to new file.
2775  if (newfile) newfile->Append(obj);
2776  file->Remove(obj);
2777  }
2778  delete file;
2779  file = 0;
2780  delete[] fname;
2781  fname = 0;
2782  return newfile;
2783 }
2784 
2785 ////////////////////////////////////////////////////////////////////////////////
2786 /// Check whether or not the address described by the last 3 parameters
2787 /// matches the content of the branch. If a Data Model Evolution conversion
2788 /// is involved, reset the fInfo of the branch.
2789 /// The return values are:
2790 //
2791 /// - kMissingBranch (-5) : Missing branch
2792 /// - kInternalError (-4) : Internal error (could not find the type corresponding to a data type number)
2793 /// - kMissingCompiledCollectionProxy (-3) : Missing compiled collection proxy for a compiled collection
2794 /// - kMismatch (-2) : Non-Class Pointer type given does not match the type expected by the branch
2795 /// - kClassMismatch (-1) : Class Pointer type given does not match the type expected by the branch
2796 /// - kMatch (0) : perfect match
2797 /// - kMatchConversion (1) : match with (I/O) conversion
2798 /// - kMatchConversionCollection (2) : match with (I/O) conversion of the content of a collection
2799 /// - kMakeClass (3) : MakeClass mode so we can not check.
2800 /// - kVoidPtr (4) : void* passed so no check was made.
2801 /// - kNoCheck (5) : Underlying TBranch not yet available so no check was made.
2802 
2803 Int_t TTree::CheckBranchAddressType(TBranch* branch, TClass* ptrClass, EDataType datatype, Bool_t isptr)
2804 {
2805  if (GetMakeClass()) {
2806  // If we are in MakeClass mode so we do not really use classes.
2807  return kMakeClass;
2808  }
2809 
2810  // Let's determine what we need!
2811  TClass* expectedClass = 0;
2812  EDataType expectedType = kOther_t;
2813  if (0 != branch->GetExpectedType(expectedClass,expectedType) ) {
2814  // Something went wrong, the warning message has already be issued.
2815  return kInternalError;
2816  }
2817  if (expectedClass && datatype == kOther_t && ptrClass == 0) {
2818  if (branch->InheritsFrom( TBranchElement::Class() )) {
2819  TBranchElement* bEl = (TBranchElement*)branch;
2820  bEl->SetTargetClass( expectedClass->GetName() );
2821  }
2822  if (expectedClass && expectedClass->GetCollectionProxy() && dynamic_cast<TEmulatedCollectionProxy*>(expectedClass->GetCollectionProxy())) {
2823  Error("SetBranchAddress", "Unable to determine the type given for the address for \"%s\". "
2824  "The class expected (%s) refers to an stl collection and do not have a compiled CollectionProxy. "
2825  "Please generate the dictionary for this class (%s)",
2826  branch->GetName(), expectedClass->GetName(), expectedClass->GetName());
2827  return kMissingCompiledCollectionProxy;
2828  }
2829  if (!expectedClass->IsLoaded()) {
2830  // The originally expected class does not have a dictionary, it is then plausible that the pointer being passed is the right type
2831  // (we really don't know). So let's express that.
2832  Error("SetBranchAddress", "Unable to determine the type given for the address for \"%s\". "
2833  "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."
2834  "Please generate the dictionary for this class (%s)",
2835  branch->GetName(), expectedClass->GetName(), expectedClass->GetName());
2836  } else {
2837  Error("SetBranchAddress", "Unable to determine the type given for the address for \"%s\". "
2838  "This is probably due to a missing dictionary, the original data class for this branch is %s.", branch->GetName(), expectedClass->GetName());
2839  }
2840  return kClassMismatch;
2841  }
2842  if (expectedClass && ptrClass && (branch->GetMother() == branch)) {
2843  // Top Level branch
2844  if (!isptr) {
2845  Error("SetBranchAddress", "The address for \"%s\" should be the address of a pointer!", branch->GetName());
2846  }
2847  }
2848  if (expectedType == kFloat16_t) {
2849  expectedType = kFloat_t;
2850  }
2851  if (expectedType == kDouble32_t) {
2852  expectedType = kDouble_t;
2853  }
2854  if (datatype == kFloat16_t) {
2855  datatype = kFloat_t;
2856  }
2857  if (datatype == kDouble32_t) {
2858  datatype = kDouble_t;
2859  }
2860 
2861  /////////////////////////////////////////////////////////////////////////////
2862  // Deal with the class renaming
2863  /////////////////////////////////////////////////////////////////////////////
2864 
2865  if( expectedClass && ptrClass &&
2866  expectedClass != ptrClass &&
2867  branch->InheritsFrom( TBranchElement::Class() ) &&
2868  ptrClass->GetSchemaRules() &&
2869  ptrClass->GetSchemaRules()->HasRuleWithSourceClass( expectedClass->GetName() ) ) {
2870  TBranchElement* bEl = (TBranchElement*)branch;
2871 
2872  if ( ptrClass->GetCollectionProxy() && expectedClass->GetCollectionProxy() ) {
2873  if (gDebug > 7)
2874  Info("SetBranchAddress", "Matching STL collection (at least according to the SchemaRuleSet when "
2875  "reading a %s into a %s",expectedClass->GetName(),ptrClass->GetName());
2876 
2877  bEl->SetTargetClass( ptrClass->GetName() );
2878  return kMatchConversion;
2879 
2880  } else if ( !ptrClass->GetConversionStreamerInfo( expectedClass, bEl->GetClassVersion() ) &&
2881  !ptrClass->FindConversionStreamerInfo( expectedClass, bEl->GetCheckSum() ) ) {
2882  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());
2883 
2884  bEl->SetTargetClass( expectedClass->GetName() );
2885  return kClassMismatch;
2886  }
2887  else {
2888 
2889  bEl->SetTargetClass( ptrClass->GetName() );
2890  return kMatchConversion;
2891  }
2892 
2893  } else if (expectedClass && ptrClass && !expectedClass->InheritsFrom(ptrClass)) {
2894 
2895  if (expectedClass->GetCollectionProxy() && ptrClass->GetCollectionProxy() &&
2896  branch->InheritsFrom( TBranchElement::Class() ) &&
2897  expectedClass->GetCollectionProxy()->GetValueClass() &&
2898  ptrClass->GetCollectionProxy()->GetValueClass() )
2899  {
2900  // In case of collection, we know how to convert them, if we know how to convert their content.
2901  // NOTE: we need to extend this to std::pair ...
2902 
2903  TClass *onfileValueClass = expectedClass->GetCollectionProxy()->GetValueClass();
2904  TClass *inmemValueClass = ptrClass->GetCollectionProxy()->GetValueClass();
2905 
2906  if (inmemValueClass->GetSchemaRules() &&
2907  inmemValueClass->GetSchemaRules()->HasRuleWithSourceClass(onfileValueClass->GetName() ) )
2908  {
2909  TBranchElement* bEl = (TBranchElement*)branch;
2910  bEl->SetTargetClass( ptrClass->GetName() );
2911  return kMatchConversionCollection;
2912  }
2913  }
2914 
2915  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());
2916  if (branch->InheritsFrom( TBranchElement::Class() )) {
2917  TBranchElement* bEl = (TBranchElement*)branch;
2918  bEl->SetTargetClass( expectedClass->GetName() );
2919  }
2920  return kClassMismatch;
2921 
2922  } else if ((expectedType != kOther_t) && (datatype != kOther_t) && (expectedType != kNoType_t) && (datatype != kNoType_t) && (expectedType != datatype)) {
2923  if (datatype != kChar_t) {
2924  // For backward compatibility we assume that (char*) was just a cast and/or a generic address
2925  Error("SetBranchAddress", "The pointer type given \"%s\" (%d) does not correspond to the type needed \"%s\" (%d) by the branch: %s",
2926  TDataType::GetTypeName(datatype), datatype, TDataType::GetTypeName(expectedType), expectedType, branch->GetName());
2927  return kMismatch;
2928  }
2929  } else if ((expectedClass && (datatype != kOther_t && datatype != kNoType_t && datatype != kInt_t)) ||
2930  (ptrClass && (expectedType != kOther_t && expectedType != kNoType_t && datatype != kInt_t)) ) {
2931  // Sometime a null pointer can look an int, avoid complaining in that case.
2932  if (expectedClass) {
2933  Error("SetBranchAddress", "The pointer type given \"%s\" (%d) does not correspond to the type needed \"%s\" by the branch: %s",
2934  TDataType::GetTypeName(datatype), datatype, expectedClass->GetName(), branch->GetName());
2935  if (branch->InheritsFrom( TBranchElement::Class() )) {
2936  TBranchElement* bEl = (TBranchElement*)branch;
2937  bEl->SetTargetClass( expectedClass->GetName() );
2938  }
2939  } else {
2940  // 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
2941  // a struct).
2942  bool found = false;
2943  if (ptrClass->IsLoaded()) {
2944  TIter next(ptrClass->GetListOfRealData());
2945  TRealData *rdm;
2946  while ((rdm = (TRealData*)next())) {
2947  if (rdm->GetThisOffset() == 0) {
2948  TDataType *dmtype = rdm->GetDataMember()->GetDataType();
2949  if (dmtype) {
2950  EDataType etype = (EDataType)dmtype->GetType();
2951  if (etype == expectedType) {
2952  found = true;
2953  }
2954  }
2955  break;
2956  }
2957  }
2958  } else {
2959  TIter next(ptrClass->GetListOfDataMembers());
2960  TDataMember *dm;
2961  while ((dm = (TDataMember*)next())) {
2962  if (dm->GetOffset() == 0) {
2963  TDataType *dmtype = dm->GetDataType();
2964  if (dmtype) {
2965  EDataType etype = (EDataType)dmtype->GetType();
2966  if (etype == expectedType) {
2967  found = true;
2968  }
2969  }
2970  break;
2971  }
2972  }
2973  }
2974  if (found) {
2975  // let's check the size.
2976  TLeaf *last = (TLeaf*)branch->GetListOfLeaves()->Last();
2977  long len = last->GetOffset() + last->GetLenType() * last->GetLen();
2978  if (len <= ptrClass->Size()) {
2979  return kMatch;
2980  }
2981  }
2982  Error("SetBranchAddress", "The pointer type given \"%s\" does not correspond to the type needed \"%s\" (%d) by the branch: %s",
2983  ptrClass->GetName(), TDataType::GetTypeName(expectedType), expectedType, branch->GetName());
2984  }
2985  return kMismatch;
2986  }
2987  if (expectedClass && expectedClass->GetCollectionProxy() && dynamic_cast<TEmulatedCollectionProxy*>(expectedClass->GetCollectionProxy())) {
2988  Error("SetBranchAddress", writeStlWithoutProxyMsg,
2989  expectedClass->GetName(), branch->GetName(), expectedClass->GetName());
2990  if (branch->InheritsFrom( TBranchElement::Class() )) {
2991  TBranchElement* bEl = (TBranchElement*)branch;
2992  bEl->SetTargetClass( expectedClass->GetName() );
2993  }
2994  return kMissingCompiledCollectionProxy;
2995  }
2996  if (expectedClass && branch->InheritsFrom( TBranchElement::Class() )) {
2997  TBranchElement* bEl = (TBranchElement*)branch;
2998  bEl->SetTargetClass( expectedClass->GetName() );
2999  }
3000  return kMatch;
3001 }
3002 
3003 ////////////////////////////////////////////////////////////////////////////////
3004 /// Create a clone of this tree and copy nentries.
3005 ///
3006 /// By default copy all entries.
3007 /// The compression level of the cloned tree is set to the destination
3008 /// file's compression level.
3009 ///
3010 /// NOTE: Only active branches are copied.
3011 /// NOTE: If the TTree is a TChain, the structure of the first TTree
3012 /// is used for the copy.
3013 ///
3014 /// IMPORTANT: The cloned tree stays connected with this tree until
3015 /// this tree is deleted. In particular, any changes in
3016 /// branch addresses in this tree are forwarded to the
3017 /// clone trees, unless a branch in a clone tree has had
3018 /// its address changed, in which case that change stays in
3019 /// effect. When this tree is deleted, all the addresses of
3020 /// the cloned tree are reset to their default values.
3021 ///
3022 /// If 'option' contains the word 'fast' and nentries is -1, the
3023 /// cloning will be done without unzipping or unstreaming the baskets
3024 /// (i.e., a direct copy of the raw bytes on disk).
3025 ///
3026 /// When 'fast' is specified, 'option' can also contain a sorting
3027 /// order for the baskets in the output file.
3028 ///
3029 /// There are currently 3 supported sorting order:
3030 ///
3031 /// - SortBasketsByOffset (the default)
3032 /// - SortBasketsByBranch
3033 /// - SortBasketsByEntry
3034 ///
3035 /// When using SortBasketsByOffset the baskets are written in the
3036 /// output file in the same order as in the original file (i.e. the
3037 /// baskets are sorted by their offset in the original file; Usually
3038 /// this also means that the baskets are sorted by the index/number of
3039 /// the _last_ entry they contain)
3040 ///
3041 /// When using SortBasketsByBranch all the baskets of each individual
3042 /// branches are stored contiguously. This tends to optimize reading
3043 /// speed when reading a small number (1->5) of branches, since all
3044 /// their baskets will be clustered together instead of being spread
3045 /// across the file. However it might decrease the performance when
3046 /// reading more branches (or the full entry).
3047 ///
3048 /// When using SortBasketsByEntry the baskets with the lowest starting
3049 /// entry are written first. (i.e. the baskets are sorted by the
3050 /// index/number of the first entry they contain). This means that on
3051 /// the file the baskets will be in the order in which they will be
3052 /// needed when reading the whole tree sequentially.
3053 ///
3054 /// For examples of CloneTree, see tutorials:
3055 ///
3056 /// - copytree.C:
3057 /// A macro to copy a subset of a TTree to a new TTree.
3058 /// The input file has been generated by the program in
3059 /// $ROOTSYS/test/Event with: Event 1000 1 1 1
3060 ///
3061 /// - copytree2.C:
3062 /// A macro to copy a subset of a TTree to a new TTree.
3063 /// One branch of the new Tree is written to a separate file.
3064 /// The input file has been generated by the program in
3065 /// $ROOTSYS/test/Event with: Event 1000 1 1 1
3066 
3067 TTree* TTree::CloneTree(Long64_t nentries /* = -1 */, Option_t* option /* = "" */)
3068 {
3069  // Options
3070  Bool_t fastClone = kFALSE;
3071 
3072  TString opt = option;
3073  opt.ToLower();
3074  if (opt.Contains("fast")) {
3075  fastClone = kTRUE;
3076  }
3077 
3078  // If we are a chain, switch to the first tree.
3079  if ((fEntries > 0) && (LoadTree(0) < 0)) {
3080  // FIXME: We need an error message here.
3081  return 0;
3082  }
3083 
3084  // Note: For a tree we get the this pointer, for
3085  // a chain we get the chain's current tree.
3086  TTree* thistree = GetTree();
3087 
3088  // We will use this to override the IO features on the cloned branches.
3089  ROOT::TIOFeatures features = this->GetIOFeatures();
3090  ;
3091 
3092  // Note: For a chain, the returned clone will be
3093  // a clone of the chain's first tree.
3094  TTree* newtree = (TTree*) thistree->Clone();
3095  if (!newtree) {
3096  return 0;
3097  }
3098 
3099  // The clone should not delete any objects allocated by SetAddress().
3100  TObjArray* branches = newtree->GetListOfBranches();
3101  Int_t nb = branches->GetEntriesFast();
3102  for (Int_t i = 0; i < nb; ++i) {
3103  TBranch* br = (TBranch*) branches->UncheckedAt(i);
3104  if (br->InheritsFrom(TBranchElement::Class())) {
3105  ((TBranchElement*) br)->ResetDeleteObject();
3106  }
3107  }
3108 
3109  // Add the new tree to the list of clones so that
3110  // we can later inform it of changes to branch addresses.
3111  thistree->AddClone(newtree);
3112  if (thistree != this) {
3113  // In case this object is a TChain, add the clone
3114  // also to the TChain's list of clones.
3115  AddClone(newtree);
3116  }
3117 
3118  newtree->Reset();
3119 
3120  TDirectory* ndir = newtree->GetDirectory();
3121  TFile* nfile = 0;
3122  if (ndir) {
3123  nfile = ndir->GetFile();
3124  }
3125  Int_t newcomp = -1;
3126  if (nfile) {
3127  newcomp = nfile->GetCompressionSettings();
3128  }
3129 
3130  //
3131  // Delete non-active branches from the clone.
3132  //
3133  // Note: If we are a chain, this does nothing
3134  // since chains have no leaves.
3135  TObjArray* leaves = newtree->GetListOfLeaves();
3136  Int_t nleaves = leaves->GetEntriesFast();
3137  for (Int_t lndx = 0; lndx < nleaves; ++lndx) {
3138  TLeaf* leaf = (TLeaf*) leaves->UncheckedAt(lndx);
3139  if (!leaf) {
3140  continue;
3141  }
3142  TBranch* branch = leaf->GetBranch();
3143  if (branch && (newcomp > -1)) {
3144  branch->SetCompressionSettings(newcomp);
3145  }
3146  if (branch) branch->SetIOFeatures(features);
3147  if (!branch || !branch->TestBit(kDoNotProcess)) {
3148  continue;
3149  }
3150  // size might change at each iteration of the loop over the leaves.
3151  nb = branches->GetEntriesFast();
3152  for (Long64_t i = 0; i < nb; ++i) {
3153  TBranch* br = (TBranch*) branches->UncheckedAt(i);
3154  if (br == branch) {
3155  branches->RemoveAt(i);
3156  delete br;
3157  br = 0;
3158  branches->Compress();
3159  break;
3160  }
3161  TObjArray* lb = br->GetListOfBranches();
3162  Int_t nb1 = lb->GetEntriesFast();
3163  for (Int_t j = 0; j < nb1; ++j) {
3164  TBranch* b1 = (TBranch*) lb->UncheckedAt(j);
3165  if (!b1) {
3166  continue;
3167  }
3168  if (b1 == branch) {
3169  lb->RemoveAt(j);
3170  delete b1;
3171  b1 = 0;
3172  lb->Compress();
3173  break;
3174  }
3175  TObjArray* lb1 = b1->GetListOfBranches();
3176  Int_t nb2 = lb1->GetEntriesFast();
3177  for (Int_t k = 0; k < nb2; ++k) {
3178  TBranch* b2 = (TBranch*) lb1->UncheckedAt(k);
3179  if (!b2) {
3180  continue;
3181  }
3182  if (b2 == branch) {
3183  lb1->RemoveAt(k);
3184  delete b2;
3185  b2 = 0;
3186  lb1->Compress();
3187  break;
3188  }
3189  }
3190  }
3191  }
3192  }
3193  leaves->Compress();
3194 
3195  // Copy MakeClass status.
3196  newtree->SetMakeClass(fMakeClass);
3197 
3198  // Copy branch addresses.
3199  CopyAddresses(newtree);
3200 
3201  //
3202  // Copy entries if requested.
3203  //
3204 
3205  if (nentries != 0) {
3206  if (fastClone && (nentries < 0)) {
3207  if ( newtree->CopyEntries( this, -1, option ) < 0 ) {
3208  // There was a problem!
3209  Error("CloneTTree", "TTree has not been cloned\n");
3210  delete newtree;
3211  newtree = 0;
3212  return 0;
3213  }
3214  } else {
3215  newtree->CopyEntries( this, nentries, option );
3216  }
3217  }
3218 
3219  return newtree;
3220 }
3221 
3222 ////////////////////////////////////////////////////////////////////////////////
3223 /// Set branch addresses of passed tree equal to ours.
3224 /// If undo is true, reset the branch address instead of copying them.
3225 /// This insures 'separation' of a cloned tree from its original
3226 
3227 void TTree::CopyAddresses(TTree* tree, Bool_t undo)
3228 {
3229  // Copy branch addresses starting from branches.
3230  TObjArray* branches = GetListOfBranches();
3231  Int_t nbranches = branches->GetEntriesFast();
3232  for (Int_t i = 0; i < nbranches; ++i) {
3233  TBranch* branch = (TBranch*) branches->UncheckedAt(i);
3234  if (branch->TestBit(kDoNotProcess)) {
3235  continue;
3236  }
3237  if (undo) {
3238  TBranch* br = tree->GetBranch(branch->GetName());
3239  tree->ResetBranchAddress(br);
3240  } else {
3241  char* addr = branch->GetAddress();
3242  if (!addr) {
3243  if (branch->IsA() == TBranch::Class()) {
3244  // If the branch was created using a leaflist, the branch itself may not have
3245  // an address but the leaf might already.
3246  TLeaf *firstleaf = (TLeaf*)branch->GetListOfLeaves()->At(0);
3247  if (!firstleaf || firstleaf->GetValuePointer()) {
3248  // Either there is no leaf (and thus no point in copying the address)
3249  // or the leaf has an address but we can not copy it via the branche
3250  // this will be copied via the next loop (over the leaf).
3251  continue;
3252  }
3253  }
3254  // Note: This may cause an object to be allocated.
3255  branch->SetAddress(0);
3256  addr = branch->GetAddress();
3257  }
3258  // FIXME: The GetBranch() function is braindead and may
3259  // not find the branch!
3260  TBranch* br = tree->GetBranch(branch->GetName());
3261  if (br) {
3262  br->SetAddress(addr);
3263  // The copy does not own any object allocated by SetAddress().
3264  if (br->InheritsFrom(TBranchElement::Class())) {
3265  ((TBranchElement*) br)->ResetDeleteObject();
3266  }
3267  } else {
3268  Warning("CopyAddresses", "Could not find branch named '%s' in tree named '%s'", branch->GetName(), tree->GetName());
3269  }
3270  }
3271  }
3272 
3273  // Copy branch addresses starting from leaves.
3274  TObjArray* tleaves = tree->GetListOfLeaves();
3275  Int_t ntleaves = tleaves->GetEntriesFast();
3276  for (Int_t i = 0; i < ntleaves; ++i) {
3277  TLeaf* tleaf = (TLeaf*) tleaves->UncheckedAt(i);
3278  TBranch* tbranch = tleaf->GetBranch();
3279  TBranch* branch = GetBranch(tbranch->GetName());
3280  if (!branch) {
3281  continue;
3282  }
3283  TLeaf* leaf = branch->GetLeaf(tleaf->GetName());
3284  if (!leaf) {
3285  continue;
3286  }
3287  if (branch->TestBit(kDoNotProcess)) {
3288  continue;
3289  }
3290  if (undo) {
3291  // Now we know whether the address has been transfered
3292  tree->ResetBranchAddress(tbranch);
3293  } else {
3294  TBranchElement *mother = dynamic_cast<TBranchElement*>(leaf->GetBranch()->GetMother());
3295  if (leaf->GetLeafCount() && (leaf->TestBit(TLeaf::kNewValue) || !leaf->GetValuePointer() || (mother && mother->IsObjectOwner())) && tleaf->GetLeafCount())
3296  {
3297  // If it is an array and it was allocated by the leaf itself,
3298  // let's make sure it is large enough for the incoming data.
3299  if (leaf->GetLeafCount()->GetMaximum() < tleaf->GetLeafCount()->GetMaximum()) {
3300  leaf->GetLeafCount()->IncludeRange( tleaf->GetLeafCount() );
3301  if (leaf->GetValuePointer()) {
3302  if (leaf->IsA() == TLeafElement::Class() && mother)
3303  mother->ResetAddress();
3304  else
3305  leaf->SetAddress(nullptr);
3306  }
3307  }
3308  }
3309  if (!branch->GetAddress() && !leaf->GetValuePointer()) {
3310  // We should attempts to set the address of the branch.
3311  // something like:
3312  //(TBranchElement*)branch->GetMother()->SetAddress(0)
3313  //plus a few more subtilities (see TBranchElement::GetEntry).
3314  //but for now we go the simplest route:
3315  //
3316  // Note: This may result in the allocation of an object.
3317  branch->SetupAddresses();
3318  }
3319  if (branch->GetAddress()) {
3320  tree->SetBranchAddress(branch->GetName(), (void*) branch->GetAddress());
3321  TBranch* br = tree->GetBranch(branch->GetName());
3322  if (br) {
3323  // The copy does not own any object allocated by SetAddress().
3324  // FIXME: We do too much here, br may not be a top-level branch.
3325  if (br->InheritsFrom(TBranchElement::Class())) {
3326  ((TBranchElement*) br)->ResetDeleteObject();
3327  }
3328  } else {
3329  Warning("CopyAddresses", "Could not find branch named '%s' in tree named '%s'", branch->GetName(), tree->GetName());
3330  }
3331  } else {
3332  tleaf->SetAddress(leaf->GetValuePointer());
3333  }
3334  }
3335  }
3336 
3337  if (undo &&
3338  ( tree->IsA()->InheritsFrom("TNtuple") || tree->IsA()->InheritsFrom("TNtupleD") )
3339  ) {
3340  tree->ResetBranchAddresses();
3341  }
3342 }
3343 
3344 namespace {
3345 
3346  enum EOnIndexError { kDrop, kKeep, kBuild };
3347 
3348  static Bool_t R__HandleIndex(EOnIndexError onIndexError, TTree *newtree, TTree *oldtree)
3349  {
3350  // Return true if we should continue to handle indices, false otherwise.
3351 
3352  Bool_t withIndex = kTRUE;
3353 
3354  if ( newtree->GetTreeIndex() ) {
3355  if ( oldtree->GetTree()->GetTreeIndex() == 0 ) {
3356  switch (onIndexError) {
3357  case kDrop:
3358  delete newtree->GetTreeIndex();
3359  newtree->SetTreeIndex(0);
3360  withIndex = kFALSE;
3361  break;
3362  case kKeep:
3363  // Nothing to do really.
3364  break;
3365  case kBuild:
3366  // Build the index then copy it
3367  if (oldtree->GetTree()->BuildIndex(newtree->GetTreeIndex()->GetMajorName(), newtree->GetTreeIndex()->GetMinorName())) {
3368  newtree->GetTreeIndex()->Append(oldtree->GetTree()->GetTreeIndex(), kTRUE);
3369  // Clean up
3370  delete oldtree->GetTree()->GetTreeIndex();
3371  oldtree->GetTree()->SetTreeIndex(0);
3372  }
3373  break;
3374  }
3375  } else {
3376  newtree->GetTreeIndex()->Append(oldtree->GetTree()->GetTreeIndex(), kTRUE);
3377  }
3378  } else if ( oldtree->GetTree()->GetTreeIndex() != 0 ) {
3379  // We discover the first index in the middle of the chain.
3380  switch (onIndexError) {
3381  case kDrop:
3382  // Nothing to do really.
3383  break;
3384  case kKeep: {
3385  TVirtualIndex *index = (TVirtualIndex*) oldtree->GetTree()->GetTreeIndex()->Clone();
3386  index->SetTree(newtree);
3387  newtree->SetTreeIndex(index);
3388  break;
3389  }
3390  case kBuild:
3391  if (newtree->GetEntries() == 0) {
3392  // Start an index.
3393  TVirtualIndex *index = (TVirtualIndex*) oldtree->GetTree()->GetTreeIndex()->Clone();
3394  index->SetTree(newtree);
3395  newtree->SetTreeIndex(index);
3396  } else {
3397  // Build the index so far.
3398  if (newtree->BuildIndex(oldtree->GetTree()->GetTreeIndex()->GetMajorName(), oldtree->GetTree()->GetTreeIndex()->GetMinorName())) {
3399  newtree->GetTreeIndex()->Append(oldtree->GetTree()->GetTreeIndex(), kTRUE);
3400  }
3401  }
3402  break;
3403  }
3404  } else if ( onIndexError == kDrop ) {
3405  // There is no index on this or on tree->GetTree(), we know we have to ignore any further
3406  // index
3407  withIndex = kFALSE;
3408  }
3409  return withIndex;
3410  }
3411 }
3412 
3413 ////////////////////////////////////////////////////////////////////////////////
3414 /// Copy nentries from given tree to this tree.
3415 /// This routines assumes that the branches that intended to be copied are
3416 /// already connected. The typical case is that this tree was created using
3417 /// tree->CloneTree(0).
3418 ///
3419 /// By default copy all entries.
3420 ///
3421 /// Returns number of bytes copied to this tree.
3422 ///
3423 /// If 'option' contains the word 'fast' and nentries is -1, the cloning will be
3424 /// done without unzipping or unstreaming the baskets (i.e., a direct copy of the
3425 /// raw bytes on disk).
3426 ///
3427 /// When 'fast' is specified, 'option' can also contains a sorting order for the
3428 /// baskets in the output file.
3429 ///
3430 /// There are currently 3 supported sorting order:
3431 ///
3432 /// - SortBasketsByOffset (the default)
3433 /// - SortBasketsByBranch
3434 /// - SortBasketsByEntry
3435 ///
3436 /// See TTree::CloneTree for a detailed explanation of the semantics of these 3 options.
3437 ///
3438 /// If the tree or any of the underlying tree of the chain has an index, that index and any
3439 /// index in the subsequent underlying TTree objects will be merged.
3440 ///
3441 /// There are currently three 'options' to control this merging:
3442 /// - NoIndex : all the TTreeIndex object are dropped.
3443 /// - DropIndexOnError : if any of the underlying TTree object do no have a TTreeIndex,
3444 /// they are all dropped.
3445 /// - AsIsIndexOnError [default]: In case of missing TTreeIndex, the resulting TTree index has gaps.
3446 /// - BuildIndexOnError : If any of the underlying TTree objects do not have a TTreeIndex,
3447 /// all TTreeIndex are 'ignored' and the missing piece are rebuilt.
3448 
3449 Long64_t TTree::CopyEntries(TTree* tree, Long64_t nentries /* = -1 */, Option_t* option /* = "" */)
3450 {
3451  if (!tree) {
3452  return 0;
3453  }
3454  // Options
3455  TString opt = option;
3456  opt.ToLower();
3457  Bool_t fastClone = opt.Contains("fast");
3458  Bool_t withIndex = !opt.Contains("noindex");
3459  EOnIndexError onIndexError;
3460  if (opt.Contains("asisindex")) {
3461  onIndexError = kKeep;
3462  } else if (opt.Contains("buildindex")) {
3463  onIndexError = kBuild;
3464  } else if (opt.Contains("dropindex")) {
3465  onIndexError = kDrop;
3466  } else {
3467  onIndexError = kBuild;
3468  }
3469  Ssiz_t cacheSizeLoc = opt.Index("cachesize=");
3470  Int_t cacheSize = -1;
3471  if (cacheSizeLoc != TString::kNPOS) {
3472  // If the parse faile, cacheSize stays at -1.
3473  Ssiz_t cacheSizeEnd = opt.Index(" ",cacheSizeLoc+10) - (cacheSizeLoc+10);
3474  TSubString cacheSizeStr( opt(cacheSizeLoc+10,cacheSizeEnd) );
3475  auto parseResult = ROOT::FromHumanReadableSize(cacheSizeStr,cacheSize);
3476  if (parseResult == ROOT::EFromHumanReadableSize::kParseFail) {
3477  Warning("CopyEntries","The cachesize option can not be parsed: %s. The default size will be used.",cacheSizeStr.String().Data());
3478  } else if (parseResult == ROOT::EFromHumanReadableSize::kOverflow) {
3479  double m;
3480  const char *munit = nullptr;
3481  ROOT::ToHumanReadableSize(std::numeric_limits<decltype(cacheSize)>::max(),false,&m,&munit);
3482 
3483  Warning("CopyEntries","The cachesize option is too large: %s (%g%s max). The default size will be used.",cacheSizeStr.String().Data(),m,munit);
3484  }
3485  }
3486  if (gDebug > 0 && cacheSize != -1) Info("CopyEntries","Using Cache size: %d\n",cacheSize);
3487 
3488  Long64_t nbytes = 0;
3489  Long64_t treeEntries = tree->GetEntriesFast();
3490  if (nentries < 0) {
3491  nentries = treeEntries;
3492  } else if (nentries > treeEntries) {
3493  nentries = treeEntries;
3494  }
3495 
3496  if (fastClone && (nentries < 0 || nentries == tree->GetEntriesFast())) {
3497  // Quickly copy the basket without decompression and streaming.
3498  Long64_t totbytes = GetTotBytes();
3499  for (Long64_t i = 0; i < nentries; i += tree->GetTree()->GetEntries()) {
3500  if (tree->LoadTree(i) < 0) {
3501  break;
3502  }
3503  if ( withIndex ) {
3504  withIndex = R__HandleIndex( onIndexError, this, tree );
3505  }
3506  if (this->GetDirectory()) {
3507  TFile* file2 = this->GetDirectory()->GetFile();
3508  if (file2 && (file2->GetEND() > TTree::GetMaxTreeSize())) {
3509  if (this->GetDirectory() == (TDirectory*) file2) {
3510  this->ChangeFile(file2);
3511  }
3512  }
3513  }
3514  TTreeCloner cloner(tree->GetTree(), this, option, TTreeCloner::kNoWarnings);
3515  if (cloner.IsValid()) {
3516  this->SetEntries(this->GetEntries() + tree->GetTree()->GetEntries());
3517  if (cacheSize != -1) cloner.SetCacheSize(cacheSize);
3518  cloner.Exec();
3519  } else {
3520  if (i == 0) {
3521  Warning("CopyEntries","%s",cloner.GetWarning());
3522  // If the first cloning does not work, something is really wrong
3523  // (since apriori the source and target are exactly the same structure!)
3524  return -1;
3525  } else {
3526  if (cloner.NeedConversion()) {
3527  TTree *localtree = tree->GetTree();
3528  Long64_t tentries = localtree->GetEntries();
3529  for (Long64_t ii = 0; ii < tentries; ii++) {
3530  if (localtree->GetEntry(ii) <= 0) {
3531  break;
3532  }
3533  this->Fill();
3534  }
3535  if (this->GetTreeIndex()) {
3536  this->GetTreeIndex()->Append(tree->GetTree()->GetTreeIndex(), kTRUE);
3537  }
3538  } else {
3539  Warning("CopyEntries","%s",cloner.GetWarning());
3540  if (tree->GetDirectory() && tree->GetDirectory()->GetFile()) {
3541  Warning("CopyEntries", "Skipped file %s\n", tree->GetDirectory()->GetFile()->GetName());
3542  } else {
3543  Warning("CopyEntries", "Skipped file number %d\n", tree->GetTreeNumber());
3544  }
3545  }
3546  }
3547  }
3548 
3549  }
3550  if (this->GetTreeIndex()) {
3551  this->GetTreeIndex()->Append(0,kFALSE); // Force the sorting
3552  }
3553  nbytes = GetTotBytes() - totbytes;
3554  } else {
3555  if (nentries < 0) {
3556  nentries = treeEntries;
3557  } else if (nentries > treeEntries) {
3558  nentries = treeEntries;
3559  }
3560  Int_t treenumber = -1;
3561  for (Long64_t i = 0; i < nentries; i++) {
3562  if (tree->LoadTree(i) < 0) {
3563  break;
3564  }
3565  if (treenumber != tree->GetTreeNumber()) {
3566  if ( withIndex ) {
3567  withIndex = R__HandleIndex( onIndexError, this, tree );
3568  }
3569  treenumber = tree->GetTreeNumber();
3570  }
3571  if (tree->GetEntry(i) <= 0) {
3572  break;
3573  }
3574  nbytes += this->Fill();
3575  }
3576  if (this->GetTreeIndex()) {
3577  this->GetTreeIndex()->Append(0,kFALSE); // Force the sorting
3578  }
3579  }
3580  return nbytes;
3581 }
3582 
3583 ////////////////////////////////////////////////////////////////////////////////
3584 /// Copy a tree with selection.
3585 ///
3586 /// ### Important:
3587 ///
3588 /// The returned copied tree stays connected with the original tree
3589 /// until the original tree is deleted. In particular, any changes
3590 /// to the branch addresses in the original tree are also made to
3591 /// the copied tree. Any changes made to the branch addresses of the
3592 /// copied tree are overridden anytime the original tree changes its
3593 /// branch addresses. When the original tree is deleted, all the
3594 /// branch addresses of the copied tree are set to zero.
3595 ///
3596 /// For examples of CopyTree, see the tutorials:
3597 ///
3598 /// - copytree.C:
3599 /// Example macro to copy a subset of a tree to a new tree.
3600 /// The input file was generated by running the program in
3601 /// $ROOTSYS/test/Event in this way:
3602 /// ~~~ {.cpp}
3603 /// ./Event 1000 1 1 1
3604 /// ~~~
3605 /// - copytree2.C
3606 /// Example macro to copy a subset of a tree to a new tree.
3607 /// One branch of the new tree is written to a separate file.
3608 /// The input file was generated by running the program in
3609 /// $ROOTSYS/test/Event in this way:
3610 /// ~~~ {.cpp}
3611 /// ./Event 1000 1 1 1
3612 /// ~~~
3613 /// - copytree3.C
3614 /// Example macro to copy a subset of a tree to a new tree.
3615 /// Only selected entries are copied to the new tree.
3616 /// NOTE that only the active branches are copied.
3617 
3618 TTree* TTree::CopyTree(const char* selection, Option_t* option /* = 0 */, Long64_t nentries /* = TTree::kMaxEntries */, Long64_t firstentry /* = 0 */)
3619 {
3620  GetPlayer();
3621  if (fPlayer) {
3622  return fPlayer->CopyTree(selection, option, nentries, firstentry);
3623  }
3624  return 0;
3625 }
3626 
3627 ////////////////////////////////////////////////////////////////////////////////
3628 /// Create a basket for this tree and given branch.
3629 
3630 TBasket* TTree::CreateBasket(TBranch* branch)
3631 {
3632  if (!branch) {
3633  return 0;
3634  }
3635  return new TBasket(branch->GetName(), GetName(), branch);
3636 }
3637 
3638 ////////////////////////////////////////////////////////////////////////////////
3639 /// Delete this tree from memory or/and disk.
3640 ///
3641 /// - if option == "all" delete Tree object from memory AND from disk
3642 /// all baskets on disk are deleted. All keys with same name
3643 /// are deleted.
3644 /// - if option =="" only Tree object in memory is deleted.
3645 
3646 void TTree::Delete(Option_t* option /* = "" */)
3647 {
3648  TFile *file = GetCurrentFile();
3649 
3650  // delete all baskets and header from file
3651  if (file && !strcmp(option,"all")) {
3652  if (!file->IsWritable()) {
3653  Error("Delete","File : %s is not writable, cannot delete Tree:%s", file->GetName(),GetName());
3654  return;
3655  }
3656 
3657  //find key and import Tree header in memory
3658  TKey *key = fDirectory->GetKey(GetName());
3659  if (!key) return;
3660 
3661  TDirectory *dirsav = gDirectory;
3662  file->cd();
3663 
3664  //get list of leaves and loop on all the branches baskets
3665  TIter next(GetListOfLeaves());
3666  TLeaf *leaf;
3667  char header[16];
3668  Int_t ntot = 0;
3669  Int_t nbask = 0;
3670  Int_t nbytes,objlen,keylen;
3671  while ((leaf = (TLeaf*)next())) {
3672  TBranch *branch = leaf->GetBranch();
3673  Int_t nbaskets = branch->GetMaxBaskets();
3674  for (Int_t i=0;i<nbaskets;i++) {
3675  Long64_t pos = branch->GetBasketSeek(i);
3676  if (!pos) continue;
3677  TFile *branchFile = branch->GetFile();
3678  if (!branchFile) continue;
3679  branchFile->GetRecordHeader(header,pos,16,nbytes,objlen,keylen);
3680  if (nbytes <= 0) continue;
3681  branchFile->MakeFree(pos,pos+nbytes-1);
3682  ntot += nbytes;
3683  nbask++;
3684  }
3685  }
3686 
3687  // delete Tree header key and all keys with the same name
3688  // A Tree may have been saved many times. Previous cycles are invalid.
3689  while (key) {
3690  ntot += key->GetNbytes();
3691  key->Delete();
3692  delete key;
3693  key = fDirectory->GetKey(GetName());
3694  }
3695  if (dirsav) dirsav->cd();
3696  if (gDebug) Info("TTree::Delete", "Deleting Tree: %s: %d baskets deleted. Total space freed = %d bytes\n",GetName(),nbask,ntot);
3697  }
3698 
3699  if (fDirectory) {
3700  fDirectory->Remove(this);
3701  //delete the file cache if it points to this Tree
3702  MoveReadCache(file,0);
3703  fDirectory = 0;
3704  ResetBit(kMustCleanup);
3705  }
3706 
3707  // Delete object from CINT symbol table so it can not be used anymore.
3708  gCling->DeleteGlobal(this);
3709 
3710  // Warning: We have intentional invalidated this object while inside a member function!
3711  delete this;
3712 }
3713 
3714  ///////////////////////////////////////////////////////////////////////////////
3715  /// Called by TKey and TObject::Clone to automatically add us to a directory
3716  /// when we are read from a file.
3717 
3718 void TTree::DirectoryAutoAdd(TDirectory* dir)
3719 {
3720  if (fDirectory == dir) return;
3721  if (fDirectory) {
3722  fDirectory->Remove(this);
3723  // Delete or move the file cache if it points to this Tree
3724  TFile *file = fDirectory->GetFile();
3725  MoveReadCache(file,dir);
3726  }
3727  fDirectory = dir;
3728  TBranch* b = 0;
3729  TIter next(GetListOfBranches());
3730  while((b = (TBranch*) next())) {
3731  b->UpdateFile();
3732  }
3733  if (fBranchRef) {
3734  fBranchRef->UpdateFile();
3735  }
3736  if (fDirectory) fDirectory->Append(this);
3737 }
3738 
3739 ////////////////////////////////////////////////////////////////////////////////
3740 /// Draw expression varexp for specified entries.
3741 ///
3742 /// \return -1 in case of error or number of selected events in case of success.
3743 ///
3744 /// This function accepts TCut objects as arguments.
3745 /// Useful to use the string operator +
3746 ///
3747 /// Example:
3748 ///
3749 /// ~~~ {.cpp}
3750 /// ntuple.Draw("x",cut1+cut2+cut3);
3751 /// ~~~
3752 
3753 
3754 Long64_t TTree::Draw(const char* varexp, const TCut& selection, Option_t* option, Long64_t nentries, Long64_t firstentry)
3755 {
3756  return TTree::Draw(varexp, selection.GetTitle(), option, nentries, firstentry);
3757 }
3758 
3759 ////////////////////////////////////////////////////////////////////////////////
3760 /// Draw expression varexp for specified entries.
3761 ///
3762 /// \return -1 in case of error or number of selected events in case of success.
3763 ///
3764 /// \param [in] varexp is an expression of the general form
3765 /// - "e1" produces a 1-d histogram (TH1F) of expression "e1"
3766 /// - "e1:e2" produces an unbinned 2-d scatter-plot (TGraph) of "e1"
3767 /// on the y-axis versus "e2" on the x-axis
3768 /// - "e1:e2:e3" produces an unbinned 3-d scatter-plot (TPolyMarker3D) of "e1"
3769 /// vs "e2" vs "e3" on the x-, y-, z-axis, respectively.
3770 /// - "e1:e2:e3:e4" produces an unbinned 3-d scatter-plot (TPolyMarker3D) of "e1"
3771 /// vs "e2" vs "e3" and "e4" mapped on the current color palette.
3772 /// (to create histograms in the 2, 3, and 4 dimensional case,
3773 /// see section "Saving the result of Draw to an histogram")
3774 ///
3775 /// Example:
3776 /// - varexp = x simplest case: draw a 1-Dim distribution of column named x
3777 /// - varexp = sqrt(x) : draw distribution of sqrt(x)
3778 /// - varexp = x*y/z
3779 /// - varexp = y:sqrt(x) 2-Dim distribution of y versus sqrt(x)
3780 /// - varexp = px:py:pz:2.5*E produces a 3-d scatter-plot of px vs py ps pz
3781 /// and the color number of each marker will be 2.5*E.
3782 /// If the color number is negative it is set to 0.
3783 /// If the color number is greater than the current number of colors
3784 /// it is set to the highest color number.The default number of
3785 /// colors is 50. see TStyle::SetPalette for setting a new color palette.
3786 ///
3787 /// Note that the variables e1, e2 or e3 may contain a selection.
3788 /// example, if e1= x*(y<0), the value histogrammed will be x if y<0
3789 /// and will be 0 otherwise.
3790 ///
3791 /// The expressions can use all the operations and build-in functions
3792 /// supported by TFormula (See TFormula::Analyze), including free
3793 /// standing function taking numerical arguments (TMath::Bessel).
3794 /// In addition, you can call member functions taking numerical
3795 /// arguments. For example:
3796 /// ~~~ {.cpp}
3797 /// TMath::BreitWigner(fPx,3,2)
3798 /// event.GetHistogram().GetXaxis().GetXmax()
3799 /// ~~~
3800 /// Note: You can only pass expression that depend on the TTree's data
3801 /// to static functions and you can only call non-static member function
3802 /// with 'fixed' parameters.
3803 ///
3804 /// \param [in] selection is an expression with a combination of the columns.
3805 /// In a selection all the C++ operators are authorized.
3806 /// The value corresponding to the selection expression is used as a weight
3807 /// to fill the histogram.
3808 /// If the expression includes only boolean operations, the result
3809 /// is 0 or 1. If the result is 0, the histogram is not filled.
3810 /// In general, the expression may be of the form:
3811 /// ~~~ {.cpp}
3812 /// value*(boolean expression)
3813 /// ~~~
3814 /// if boolean expression is true, the histogram is filled with
3815 /// a `weight = value`.
3816 /// Examples:
3817 /// - selection1 = "x<y && sqrt(z)>3.2"
3818 /// - selection2 = "(x+y)*(sqrt(z)>3.2)"
3819 /// - selection1 returns a weight = 0 or 1
3820 /// - selection2 returns a weight = x+y if sqrt(z)>3.2
3821 /// returns a weight = 0 otherwise.
3822 ///
3823 /// \param [in] option is the drawing option.
3824 /// - When an histogram is produced it can be any histogram drawing option
3825 /// listed in THistPainter.
3826 /// - when no option is specified:
3827 /// - the default histogram drawing option is used
3828 /// if the expression is of the form "e1".
3829 /// - if the expression is of the form "e1:e2"or "e1:e2:e3" a cloud of
3830 /// unbinned 2D or 3D points is drawn respectively.
3831 /// - if the expression has four fields "e1:e2:e3:e4" a cloud of unbinned 3D
3832 /// points is produced with e1 vs e2 vs e3, and e4 is mapped on the current color
3833 /// palette.
3834 /// - If option COL is specified when varexp has three fields:
3835 /// ~~~ {.cpp}
3836 /// tree.Draw("e1:e2:e3","","col");
3837 /// ~~~
3838 /// a 2D scatter is produced with e1 vs e2, and e3 is mapped on the current
3839 /// color palette. The colors for e3 are evaluated once in linear scale before
3840 /// painting. Therefore changing the pad to log scale along Z as no effect
3841 /// on the colors.
3842 /// - if expression has more than four fields the option "PARA"or "CANDLE"
3843 /// can be used.
3844 /// - If option contains the string "goff", no graphics is generated.
3845 ///
3846 /// \param [in] nentries is the number of entries to process (default is all)
3847 ///
3848 /// \param [in] firstentry is the first entry to process (default is 0)
3849 ///
3850 /// ### Drawing expressions using arrays and array elements
3851 ///
3852 /// Let assumes, a leaf fMatrix, on the branch fEvent, which is a 3 by 3 array,
3853 /// or a TClonesArray.
3854 /// In a TTree::Draw expression you can now access fMatrix using the following
3855 /// syntaxes:
3856 ///
3857 /// | String passed | What is used for each entry of the tree
3858 /// |-----------------|--------------------------------------------------------|
3859 /// | `fMatrix` | the 9 elements of fMatrix |
3860 /// | `fMatrix[][]` | the 9 elements of fMatrix |
3861 /// | `fMatrix[2][2]` | only the elements fMatrix[2][2] |
3862 /// | `fMatrix[1]` | the 3 elements fMatrix[1][0], fMatrix[1][1] and fMatrix[1][2] |
3863 /// | `fMatrix[1][]` | the 3 elements fMatrix[1][0], fMatrix[1][1] and fMatrix[1][2] |
3864 /// | `fMatrix[][0]` | the 3 elements fMatrix[0][0], fMatrix[1][0] and fMatrix[2][0] |
3865 ///
3866 /// "fEvent.fMatrix...." same as "fMatrix..." (unless there is more than one leaf named fMatrix!).
3867 ///
3868 /// In summary, if a specific index is not specified for a dimension, TTree::Draw
3869 /// will loop through all the indices along this dimension. Leaving off the
3870 /// last (right most) dimension of specifying then with the two characters '[]'
3871 /// is equivalent. For variable size arrays (and TClonesArray) the range
3872 /// of the first dimension is recalculated for each entry of the tree.
3873 /// You can also specify the index as an expression of any other variables from the
3874 /// tree.
3875 ///
3876 /// TTree::Draw also now properly handling operations involving 2 or more arrays.
3877 ///
3878 /// Let assume a second matrix fResults[5][2], here are a sample of some
3879 /// of the possible combinations, the number of elements they produce and
3880 /// the loop used:
3881 ///
3882 /// | expression | element(s) | Loop |
3883 /// |----------------------------------|------------|--------------------------|
3884 /// | `fMatrix[2][1] - fResults[5][2]` | one | no loop |
3885 /// | `fMatrix[2][] - fResults[5][2]` | three | on 2nd dim fMatrix |
3886 /// | `fMatrix[2][] - fResults[5][]` | two | on both 2nd dimensions |
3887 /// | `fMatrix[][2] - fResults[][1]` | three | on both 1st dimensions |
3888 /// | `fMatrix[][2] - fResults[][]` | six | on both 1st and 2nd dimensions of fResults |
3889 /// | `fMatrix[][2] - fResults[3][]` | two | on 1st dim of fMatrix and 2nd of fResults (at the same time) |
3890 /// | `fMatrix[][] - fResults[][]` | six | on 1st dim then on 2nd dim |
3891 /// | `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.|
3892 ///
3893 ///
3894 /// In summary, TTree::Draw loops through all unspecified dimensions. To
3895 /// figure out the range of each loop, we match each unspecified dimension
3896 /// from left to right (ignoring ALL dimensions for which an index has been
3897 /// specified), in the equivalent loop matched dimensions use the same index
3898 /// and are restricted to the smallest range (of only the matched dimensions).
3899 /// When involving variable arrays, the range can of course be different
3900 /// for each entry of the tree.
3901 ///
3902 /// So the loop equivalent to "fMatrix[][2] - fResults[3][]" is:
3903 /// ~~~ {.cpp}
3904 /// for (Int_t i0; i < min(3,2); i++) {
3905 /// use the value of (fMatrix[i0][2] - fMatrix[3][i0])
3906 /// }
3907 /// ~~~
3908 /// So the loop equivalent to "fMatrix[][2] - fResults[][]" is:
3909 /// ~~~ {.cpp}
3910 /// for (Int_t i0; i < min(3,5); i++) {
3911 /// for (Int_t i1; i1 < 2; i1++) {
3912 /// use the value of (fMatrix[i0][2] - fMatrix[i0][i1])
3913 /// }
3914 /// }
3915 /// ~~~
3916 /// So the loop equivalent to "fMatrix[][] - fResults[][]" is:
3917 /// ~~~ {.cpp}
3918 /// for (Int_t i0; i < min(3,5); i++) {
3919 /// for (Int_t i1; i1 < min(3,2); i1++) {
3920 /// use the value of (fMatrix[i0][i1] - fMatrix[i0][i1])
3921 /// }
3922 /// }
3923 /// ~~~
3924 /// So the loop equivalent to "fMatrix[][fResults[][]]" is:
3925 /// ~~~ {.cpp}
3926 /// for (Int_t i0; i0 < 3; i0++) {
3927 /// for (Int_t j2; j2 < 5; j2++) {
3928 /// for (Int_t j3; j3 < 2; j3++) {
3929 /// i1 = fResults[j2][j3];
3930 /// use the value of fMatrix[i0][i1]
3931 /// }
3932 /// }
3933 /// ~~~
3934 /// ### Retrieving the result of Draw
3935 ///
3936 /// By default the temporary histogram created is called "htemp", but only in
3937 /// the one dimensional Draw("e1") it contains the TTree's data points. For
3938 /// a two dimensional Draw, the data is filled into a TGraph which is named
3939 /// "Graph". They can be retrieved by calling
3940 /// ~~~ {.cpp}
3941 /// TH1F *htemp = (TH1F*)gPad->GetPrimitive("htemp"); // 1D
3942 /// TGraph *graph = (TGraph*)gPad->GetPrimitive("Graph"); // 2D
3943 /// ~~~
3944 /// For a three and four dimensional Draw the TPolyMarker3D is unnamed, and
3945 /// cannot be retrieved.
3946 ///
3947 /// gPad always contains a TH1 derived object called "htemp" which allows to
3948 /// access the axes:
3949 /// ~~~ {.cpp}
3950 /// TGraph *graph = (TGraph*)gPad->GetPrimitive("Graph"); // 2D
3951 /// TH2F *htemp = (TH2F*)gPad->GetPrimitive("htemp"); // empty, but has axes
3952 /// TAxis *xaxis = htemp->GetXaxis();
3953 /// ~~~
3954 /// ### Saving the result of Draw to an histogram
3955 ///
3956 /// If varexp0 contains >>hnew (following the variable(s) name(s),
3957 /// the new histogram created is called hnew and it is kept in the current
3958 /// directory (and also the current pad). This works for all dimensions.
3959 ///
3960 /// Example:
3961 /// ~~~ {.cpp}
3962 /// tree.Draw("sqrt(x)>>hsqrt","y>0")
3963 /// ~~~
3964 /// will draw `sqrt(x)` and save the histogram as "hsqrt" in the current
3965 /// directory. To retrieve it do:
3966 /// ~~~ {.cpp}
3967 /// TH1F *hsqrt = (TH1F*)gDirectory->Get("hsqrt");
3968 /// ~~~
3969 /// The binning information is taken from the environment variables
3970 /// ~~~ {.cpp}
3971 /// Hist.Binning.?D.?
3972 /// ~~~
3973 /// In addition, the name of the histogram can be followed by up to 9
3974 /// numbers between '(' and ')', where the numbers describe the
3975 /// following:
3976 ///
3977 /// - 1 - bins in x-direction
3978 /// - 2 - lower limit in x-direction
3979 /// - 3 - upper limit in x-direction
3980 /// - 4-6 same for y-direction
3981 /// - 7-9 same for z-direction
3982 ///
3983 /// When a new binning is used the new value will become the default.
3984 /// Values can be skipped.
3985 ///
3986 /// Example:
3987 /// ~~~ {.cpp}
3988 /// tree.Draw("sqrt(x)>>hsqrt(500,10,20)")
3989 /// // plot sqrt(x) between 10 and 20 using 500 bins
3990 /// tree.Draw("sqrt(x):sin(y)>>hsqrt(100,10,60,50,.1,.5)")
3991 /// // plot sqrt(x) against sin(y)
3992 /// // 100 bins in x-direction; lower limit on x-axis is 10; upper limit is 60
3993 /// // 50 bins in y-direction; lower limit on y-axis is .1; upper limit is .5
3994 /// ~~~
3995 /// By default, the specified histogram is reset.
3996 /// To continue to append data to an existing histogram, use "+" in front
3997 /// of the histogram name.
3998 ///
3999 /// A '+' in front of the histogram name is ignored, when the name is followed by
4000 /// binning information as described in the previous paragraph.
4001 /// ~~~ {.cpp}
4002 /// tree.Draw("sqrt(x)>>+hsqrt","y>0")
4003 /// ~~~
4004 /// will not reset `hsqrt`, but will continue filling. This works for 1-D, 2-D
4005 /// and 3-D histograms.
4006 ///
4007 /// ### Accessing collection objects
4008 ///
4009 /// TTree::Draw default's handling of collections is to assume that any
4010 /// request on a collection pertain to it content. For example, if fTracks
4011 /// is a collection of Track objects, the following:
4012 /// ~~~ {.cpp}
4013 /// tree->Draw("event.fTracks.fPx");
4014 /// ~~~
4015 /// will plot the value of fPx for each Track objects inside the collection.
4016 /// Also
4017 /// ~~~ {.cpp}
4018 /// tree->Draw("event.fTracks.size()");
4019 /// ~~~
4020 /// would plot the result of the member function Track::size() for each
4021 /// Track object inside the collection.
4022 /// To access information about the collection itself, TTree::Draw support
4023 /// the '@' notation. If a variable which points to a collection is prefixed
4024 /// or postfixed with '@', the next part of the expression will pertain to
4025 /// the collection object. For example:
4026 /// ~~~ {.cpp}
4027 /// tree->Draw("event.@fTracks.size()");
4028 /// ~~~
4029 /// will plot the size of the collection referred to by `fTracks` (i.e the number
4030 /// of Track objects).
4031 ///
4032 /// ### Drawing 'objects'
4033 ///
4034 /// When a class has a member function named AsDouble or AsString, requesting
4035 /// to directly draw the object will imply a call to one of the 2 functions.
4036 /// If both AsDouble and AsString are present, AsDouble will be used.
4037 /// AsString can return either a char*, a std::string or a TString.s
4038 /// For example, the following
4039 /// ~~~ {.cpp}
4040 /// tree->Draw("event.myTTimeStamp");
4041 /// ~~~
4042 /// will draw the same histogram as
4043 /// ~~~ {.cpp}
4044 /// tree->Draw("event.myTTimeStamp.AsDouble()");
4045 /// ~~~
4046 /// In addition, when the object is a type TString or std::string, TTree::Draw
4047 /// will call respectively `TString::Data` and `std::string::c_str()`
4048 ///
4049 /// If the object is a TBits, the histogram will contain the index of the bit
4050 /// that are turned on.
4051 ///
4052 /// ### Retrieving information about the tree itself.
4053 ///
4054 /// You can refer to the tree (or chain) containing the data by using the
4055 /// string 'This'.
4056 /// You can then could any TTree methods. For example:
4057 /// ~~~ {.cpp}
4058 /// tree->Draw("This->GetReadEntry()");
4059 /// ~~~
4060 /// will display the local entry numbers be read.
4061 /// ~~~ {.cpp}
4062 /// tree->Draw("This->GetUserInfo()->At(0)->GetName()");
4063 /// ~~~
4064 /// will display the name of the first 'user info' object.
4065 ///
4066 /// ### Special functions and variables
4067 ///
4068 /// `Entry$`: A TTree::Draw formula can use the special variable `Entry$`
4069 /// to access the entry number being read. For example to draw every
4070 /// other entry use:
4071 /// ~~~ {.cpp}
4072 /// tree.Draw("myvar","Entry$%2==0");
4073 /// ~~~
4074 /// - `Entry$` : return the current entry number (`== TTree::GetReadEntry()`)
4075 /// - `LocalEntry$` : return the current entry number in the current tree of a
4076 /// chain (`== GetTree()->GetReadEntry()`)
4077 /// - `Entries$` : return the total number of entries (== TTree::GetEntries())
4078 /// - `LocalEntries$` : return the total number of entries in the current tree
4079 /// of a chain (== GetTree()->TTree::GetEntries())
4080 /// - `Length$` : return the total number of element of this formula for this
4081 /// entry (`==TTreeFormula::GetNdata()`)
4082 /// - `Iteration$` : return the current iteration over this formula for this
4083 /// entry (i.e. varies from 0 to `Length$`).
4084 /// - `Length$(formula )` : return the total number of element of the formula
4085 /// given as a parameter.
4086 /// - `Sum$(formula )` : return the sum of the value of the elements of the
4087 /// formula given as a parameter. For example the mean for all the elements in
4088 /// one entry can be calculated with: `Sum$(formula )/Length$(formula )`
4089 /// - `Min$(formula )` : return the minimun (within one TTree entry) of the value of the
4090 /// elements of the formula given as a parameter.
4091 /// - `Max$(formula )` : return the maximum (within one TTree entry) of the value of the
4092 /// elements of the formula given as a parameter.
4093 /// - `MinIf$(formula,condition)`
4094 /// - `MaxIf$(formula,condition)` : return the minimum (maximum) (within one TTree entry)
4095 /// of the value of the elements of the formula given as a parameter
4096 /// if they match the condition. If no element matches the condition,
4097 /// the result is zero. To avoid the resulting peak at zero, use the
4098 /// pattern:
4099 /// ~~~ {.cpp}
4100 /// tree->Draw("MinIf$(formula,condition)","condition");
4101 /// ~~~
4102 /// which will avoid calculation `MinIf$` for the entries that have no match
4103 /// for the condition.
4104 /// - `Alt$(primary,alternate)` : return the value of "primary" if it is available
4105 /// for the current iteration otherwise return the value of "alternate".
4106 /// For example, with arr1[3] and arr2[2]
4107 /// ~~~ {.cpp}
4108 /// tree->Draw("arr1+Alt$(arr2,0)");
4109 /// ~~~
4110 /// will draw arr1[0]+arr2[0] ; arr1[1]+arr2[1] and arr1[2]+0
4111 /// Or with a variable size array arr3
4112 /// ~~~ {.cpp}
4113 /// tree->Draw("Alt$(arr3[0],0)+Alt$(arr3[1],0)+Alt$(arr3[2],0)");
4114 /// ~~~
4115 /// will draw the sum arr3 for the index 0 to min(2,actual_size_of_arr3-1)
4116 /// As a comparison
4117 /// ~~~ {.cpp}
4118 /// tree->Draw("arr3[0]+arr3[1]+arr3[2]");
4119 /// ~~~
4120 /// will draw the sum arr3 for the index 0 to 2 only if the
4121 /// actual_size_of_arr3 is greater or equal to 3.
4122 /// Note that the array in 'primary' is flattened/linearized thus using
4123 /// `Alt$` with multi-dimensional arrays of different dimensions in unlikely
4124 /// to yield the expected results. To visualize a bit more what elements
4125 /// would be matched by TTree::Draw, TTree::Scan can be used:
4126 /// ~~~ {.cpp}
4127 /// tree->Scan("arr1:Alt$(arr2,0)");
4128 /// ~~~
4129 /// will print on one line the value of arr1 and (arr2,0) that will be
4130 /// matched by
4131 /// ~~~ {.cpp}
4132 /// tree->Draw("arr1-Alt$(arr2,0)");
4133 /// ~~~
4134 /// The ternary operator is not directly supported in TTree::Draw however, to plot the
4135 /// equivalent of `var2<20 ? -99 : var1`, you can use:
4136 /// ~~~ {.cpp}
4137 /// tree->Draw("(var2<20)*99+(var2>=20)*var1","");
4138 /// ~~~
4139 ///
4140 /// ### Drawing a user function accessing the TTree data directly
4141 ///
4142 /// If the formula contains a file name, TTree::MakeProxy will be used
4143 /// to load and execute this file. In particular it will draw the
4144 /// result of a function with the same name as the file. The function
4145 /// will be executed in a context where the name of the branches can
4146 /// be used as a C++ variable.
4147 ///
4148 /// For example draw px using the file hsimple.root (generated by the
4149 /// hsimple.C tutorial), we need a file named hsimple.cxx:
4150 /// ~~~ {.cpp}
4151 /// double hsimple() {
4152 /// return px;
4153 /// }
4154 /// ~~~
4155 /// MakeProxy can then be used indirectly via the TTree::Draw interface
4156 /// as follow:
4157 /// ~~~ {.cpp}
4158 /// new TFile("hsimple.root")
4159 /// ntuple->Draw("hsimple.cxx");
4160 /// ~~~
4161 /// A more complete example is available in the tutorials directory:
4162 /// `h1analysisProxy.cxx`, `h1analysProxy.h` and `h1analysisProxyCut.C`
4163 /// which reimplement the selector found in `h1analysis.C`
4164 ///
4165 /// The main features of this facility are:
4166 ///
4167 /// * on-demand loading of branches
4168 /// * ability to use the 'branchname' as if it was a data member
4169 /// * protection against array out-of-bound
4170 /// * ability to use the branch data as object (when the user code is available)
4171 ///
4172 /// See TTree::MakeProxy for more details.
4173 ///
4174 /// ### Making a Profile histogram
4175 ///
4176 /// In case of a 2-Dim expression, one can generate a TProfile histogram
4177 /// instead of a TH2F histogram by specifying option=prof or option=profs
4178 /// or option=profi or option=profg ; the trailing letter select the way
4179 /// the bin error are computed, See TProfile2D::SetErrorOption for
4180 /// details on the differences.
4181 /// The option=prof is automatically selected in case of y:x>>pf
4182 /// where pf is an existing TProfile histogram.
4183 ///
4184 /// ### Making a 2D Profile histogram
4185 ///
4186 /// In case of a 3-Dim expression, one can generate a TProfile2D histogram
4187 /// instead of a TH3F histogram by specifying option=prof or option=profs.
4188 /// or option=profi or option=profg ; the trailing letter select the way
4189 /// the bin error are computed, See TProfile2D::SetErrorOption for
4190 /// details on the differences.
4191 /// The option=prof is automatically selected in case of z:y:x>>pf
4192 /// where pf is an existing TProfile2D histogram.
4193 ///
4194 /// ### Making a 5D plot using GL
4195 ///
4196 /// If option GL5D is specified together with 5 variables, a 5D plot is drawn
4197 /// using OpenGL. See $ROOTSYS/tutorials/tree/staff.C as example.
4198 ///
4199 /// ### Making a parallel coordinates plot
4200 ///
4201 /// In case of a 2-Dim or more expression with the option=para, one can generate
4202 /// a parallel coordinates plot. With that option, the number of dimensions is
4203 /// arbitrary. Giving more than 4 variables without the option=para or
4204 /// option=candle or option=goff will produce an error.
4205 ///
4206 /// ### Making a candle sticks chart
4207 ///
4208 /// In case of a 2-Dim or more expression with the option=candle, one can generate
4209 /// a candle sticks chart. With that option, the number of dimensions is
4210 /// arbitrary. Giving more than 4 variables without the option=para or
4211 /// option=candle or option=goff will produce an error.
4212 ///
4213 /// ### Normalizing the output histogram to 1
4214 ///
4215 /// When option contains "norm" the output histogram is normalized to 1.
4216 ///
4217 /// ### Saving the result of Draw to a TEventList, a TEntryList or a TEntryListArray
4218 ///
4219 /// TTree::Draw can be used to fill a TEventList object (list of entry numbers)
4220 /// instead of histogramming one variable.
4221 /// If varexp0 has the form >>elist , a TEventList object named "elist"
4222 /// is created in the current directory. elist will contain the list
4223 /// of entry numbers satisfying the current selection.
4224 /// If option "entrylist" is used, a TEntryList object is created
4225 /// If the selection contains arrays, vectors or any container class and option
4226 /// "entrylistarray" is used, a TEntryListArray object is created
4227 /// containing also the subentries satisfying the selection, i.e. the indices of
4228 /// the branches which hold containers classes.
4229 /// Example:
4230 /// ~~~ {.cpp}
4231 /// tree.Draw(">>yplus","y>0")
4232 /// ~~~
4233 /// will create a TEventList object named "yplus" in the current directory.
4234 /// In an interactive session, one can type (after TTree::Draw)
4235 /// ~~~ {.cpp}
4236 /// yplus.Print("all")
4237 /// ~~~
4238 /// to print the list of entry numbers in the list.
4239 /// ~~~ {.cpp}
4240 /// tree.Draw(">>yplus", "y>0", "entrylist")
4241 /// ~~~
4242 /// will create a TEntryList object names "yplus" in the current directory
4243 /// ~~~ {.cpp}
4244 /// tree.Draw(">>yplus", "y>0", "entrylistarray")
4245 /// ~~~
4246 /// will create a TEntryListArray object names "yplus" in the current directory
4247 ///
4248 /// By default, the specified entry list is reset.
4249 /// To continue to append data to an existing list, use "+" in front
4250 /// of the list name;
4251 /// ~~~ {.cpp}
4252 /// tree.Draw(">>+yplus","y>0")
4253 /// ~~~
4254 /// will not reset yplus, but will enter the selected entries at the end
4255 /// of the existing list.
4256 ///
4257 /// ### Using a TEventList, TEntryList or TEntryListArray as Input
4258 ///
4259 /// Once a TEventList or a TEntryList object has been generated, it can be used as input
4260 /// for TTree::Draw. Use TTree::SetEventList or TTree::SetEntryList to set the
4261 /// current event list
4262 ///
4263 /// Example 1:
4264 /// ~~~ {.cpp}
4265 /// TEventList *elist = (TEventList*)gDirectory->Get("yplus");
4266 /// tree->SetEventList(elist);
4267 /// tree->Draw("py");
4268 /// ~~~
4269 /// Example 2:
4270 /// ~~~ {.cpp}
4271 /// TEntryList *elist = (TEntryList*)gDirectory->Get("yplus");
4272 /// tree->SetEntryList(elist);
4273 /// tree->Draw("py");
4274 /// ~~~
4275 /// If a TEventList object is used as input, a new TEntryList object is created
4276 /// inside the SetEventList function. In case of a TChain, all tree headers are loaded
4277 /// for this transformation. This new object is owned by the chain and is deleted
4278 /// with it, unless the user extracts it by calling GetEntryList() function.
4279 /// See also comments to SetEventList() function of TTree and TChain.
4280 ///
4281 /// If arrays are used in the selection criteria and TEntryListArray is not used,
4282 /// all the entries that have at least one element of the array that satisfy the selection
4283 /// are entered in the list.
4284 ///
4285 /// Example:
4286 /// ~~~ {.cpp}
4287 /// tree.Draw(">>pyplus","fTracks.fPy>0");
4288 /// tree->SetEventList(pyplus);
4289 /// tree->Draw("fTracks.fPy");
4290 /// ~~~
4291 /// will draw the fPy of ALL tracks in event with at least one track with
4292 /// a positive fPy.
4293 ///
4294 /// To select only the elements that did match the original selection
4295 /// use TEventList::SetReapplyCut or TEntryList::SetReapplyCut.
4296 ///
4297 /// Example:
4298 /// ~~~ {.cpp}
4299 /// tree.Draw(">>pyplus","fTracks.fPy>0");
4300 /// pyplus->SetReapplyCut(kTRUE);
4301 /// tree->SetEventList(pyplus);
4302 /// tree->Draw("fTracks.fPy");
4303 /// ~~~
4304 /// will draw the fPy of only the tracks that have a positive fPy.
4305 ///
4306 /// To draw only the elements that match a selection in case of arrays,
4307 /// you can also use TEntryListArray (faster in case of a more general selection).
4308 ///
4309 /// Example:
4310 /// ~~~ {.cpp}
4311 /// tree.Draw(">>pyplus","fTracks.fPy>0", "entrylistarray");
4312 /// tree->SetEntryList(pyplus);
4313 /// tree->Draw("fTracks.fPy");
4314 /// ~~~
4315 /// will draw the fPy of only the tracks that have a positive fPy,
4316 /// but without redoing the selection.
4317 ///
4318 /// Note: Use tree->SetEventList(0) if you do not want use the list as input.
4319 ///
4320 /// ### How to obtain more info from TTree::Draw
4321 ///
4322 /// Once TTree::Draw has been called, it is possible to access useful
4323 /// information still stored in the TTree object via the following functions:
4324 ///
4325 /// - GetSelectedRows() // return the number of values accepted by the selection expression. In case where no selection was specified, returns the number of values processed.
4326 /// - GetV1() // returns a pointer to the double array of V1
4327 /// - GetV2() // returns a pointer to the double array of V2
4328 /// - GetV3() // returns a pointer to the double array of V3
4329 /// - GetV4() // returns a pointer to the double array of V4
4330 /// - GetW() // returns a pointer to the double array of Weights where weight equal the result of the selection expression.
4331 ///
4332 /// where V1,V2,V3 correspond to the expressions in
4333 /// ~~~ {.cpp}
4334 /// TTree::Draw("V1:V2:V3:V4",selection);
4335 /// ~~~
4336 /// If the expression has more than 4 component use GetVal(index)
4337 ///
4338 /// Example:
4339 /// ~~~ {.cpp}
4340 /// Root > ntuple->Draw("py:px","pz>4");
4341 /// Root > TGraph *gr = new TGraph(ntuple->GetSelectedRows(),
4342 /// ntuple->GetV2(), ntuple->GetV1());
4343 /// Root > gr->Draw("ap"); //draw graph in current pad
4344 /// ~~~
4345 ///
4346 /// A more complete complete tutorial (treegetval.C) shows how to use the
4347 /// GetVal() method.
4348 ///
4349 /// creates a TGraph object with a number of points corresponding to the
4350 /// number of entries selected by the expression "pz>4", the x points of the graph
4351 /// being the px values of the Tree and the y points the py values.
4352 ///
4353 /// Important note: By default TTree::Draw creates the arrays obtained
4354 /// with GetW, GetV1, GetV2, GetV3, GetV4, GetVal with a length corresponding
4355 /// to the parameter fEstimate. The content will be the last `GetSelectedRows() % GetEstimate()`
4356 /// values calculated.
4357 /// By default fEstimate=1000000 and can be modified
4358 /// via TTree::SetEstimate. To keep in memory all the results (in case
4359 /// where there is only one result per entry), use
4360 /// ~~~ {.cpp}
4361 /// tree->SetEstimate(tree->GetEntries()+1); // same as tree->SetEstimate(-1);
4362 /// ~~~
4363 /// You must call SetEstimate if the expected number of selected rows
4364 /// you need to look at is greater than 1000000.
4365 ///
4366 /// You can use the option "goff" to turn off the graphics output
4367 /// of TTree::Draw in the above example.
4368 ///
4369 /// ### Automatic interface to TTree::Draw via the TTreeViewer
4370 ///
4371 /// A complete graphical interface to this function is implemented
4372 /// in the class TTreeViewer.
4373 /// To start the TTreeViewer, three possibilities:
4374 /// - select TTree context menu item "StartViewer"
4375 /// - type the command "TTreeViewer TV(treeName)"
4376 /// - execute statement "tree->StartViewer();"
4377 
4378 Long64_t TTree::Draw(const char* varexp, const char* selection, Option_t* option, Long64_t nentries, Long64_t firstentry)
4379 {
4380  GetPlayer();
4381  if (fPlayer)
4382  return fPlayer->DrawSelect(varexp,selection,option,nentries,firstentry);
4383  return -1;
4384 }
4385 
4386 ////////////////////////////////////////////////////////////////////////////////
4387 /// Remove some baskets from memory.
4388 
4389 void TTree::DropBaskets()
4390 {
4391  TBranch* branch = 0;
4392  Int_t nb = fBranches.GetEntriesFast();
4393  for (Int_t i = 0; i < nb; ++i) {
4394  branch = (TBranch*) fBranches.UncheckedAt(i);
4395  branch->DropBaskets("all");
4396  }
4397 }
4398 
4399 ////////////////////////////////////////////////////////////////////////////////
4400 /// Drop branch buffers to accommodate nbytes below MaxVirtualsize.
4401 
4402 void TTree::DropBuffers(Int_t)
4403 {
4404  // Be careful not to remove current read/write buffers.
4405  Int_t ndrop = 0;
4406  Int_t nleaves = fLeaves.GetEntriesFast();
4407  for (Int_t i = 0; i < nleaves; ++i) {
4408  TLeaf* leaf = (TLeaf*) fLeaves.UncheckedAt(i);
4409  TBranch* branch = (TBranch*) leaf->GetBranch();
4410  Int_t nbaskets = branch->GetListOfBaskets()->GetEntries();
4411  for (Int_t j = 0; j < nbaskets - 1; ++j) {
4412  if ((j == branch->GetReadBasket()) || (j == branch->GetWriteBasket())) {
4413  continue;
4414  }
4415  TBasket* basket = (TBasket*)branch->GetListOfBaskets()->UncheckedAt(j);
4416  if (basket) {
4417  ndrop += basket->DropBuffers();
4418  if (fTotalBuffers < fMaxVirtualSize) {
4419  return;
4420  }
4421  }
4422  }
4423  }
4424 }
4425 
4426 ////////////////////////////////////////////////////////////////////////////////
4427 /// Fill all branches.
4428 ///
4429 /// This function loops on all the branches of this tree. For
4430 /// each branch, it copies to the branch buffer (basket) the current
4431 /// values of the leaves data types. If a leaf is a simple data type,
4432 /// a simple conversion to a machine independent format has to be done.
4433 ///
4434 /// This machine independent version of the data is copied into a
4435 /// basket (each branch has its own basket). When a basket is full
4436 /// (32k worth of data by default), it is then optionally compressed
4437 /// and written to disk (this operation is also called committing or
4438 /// 'flushing' the basket). The committed baskets are then
4439 /// immediately removed from memory.
4440 ///
4441 /// The function returns the number of bytes committed to the
4442 /// individual branches.
4443 ///
4444 /// If a write error occurs, the number of bytes returned is -1.
4445 ///
4446 /// If no data are written, because, e.g., the branch is disabled,
4447 /// the number of bytes returned is 0.
4448 ///
4449 /// __The baskets are flushed and the Tree header saved at regular intervals__
4450 ///
4451 /// At regular intervals, when the amount of data written so far is
4452 /// greater than fAutoFlush (see SetAutoFlush) all the baskets are flushed to disk.
4453 /// This makes future reading faster as it guarantees that baskets belonging to nearby
4454 /// entries will be on the same disk region.
4455 /// When the first call to flush the baskets happen, we also take this opportunity
4456 /// to optimize the baskets buffers.
4457 /// We also check if the amount of data written is greater than fAutoSave (see SetAutoSave).
4458 /// In this case we also write the Tree header. This makes the Tree recoverable up to this point
4459 /// in case the program writing the Tree crashes.
4460 /// The decisions to FlushBaskets and Auto Save can be made based either on the number
4461 /// of bytes written (fAutoFlush and fAutoSave negative) or on the number of entries
4462 /// written (fAutoFlush and fAutoSave positive).
4463 /// Note that the user can decide to call FlushBaskets and AutoSave in her event loop
4464 /// base on the number of events written instead of the number of bytes written.
4465 ///
4466 /// Note that calling FlushBaskets too often increases the IO time.
4467 ///
4468 /// Note that calling AutoSave too often increases the IO time and also the file size.
4469 
4470 Int_t TTree::Fill()
4471 {
4472  Int_t nbytes = 0;
4473  Int_t nwrite = 0;
4474  Int_t nerror = 0;
4475  Int_t nbranches = fBranches.GetEntriesFast();
4476 
4477  // Case of one single super branch. Automatically update
4478  // all the branch addresses if a new object was created.
4479  if (nbranches == 1)
4480  ((TBranch *)fBranches.UncheckedAt(0))->UpdateAddress();
4481 
4482  if (fBranchRef)
4483  fBranchRef->Clear();
4484 
4485 #ifdef R__USE_IMT
4486  const auto useIMT = ROOT::IsImplicitMTEnabled() && fIMTEnabled;
4487  ROOT::Internal::TBranchIMTHelper imtHelper;
4488  if (useIMT) {
4489  fIMTFlush = true;
4490  fIMTZipBytes.store(0);
4491  fIMTTotBytes.store(0);
4492  }
4493 #endif
4494 
4495  for (Int_t i = 0; i < nbranches; ++i) {
4496  // Loop over all branches, filling and accumulating bytes written and error counts.
4497  TBranch *branch = (TBranch *)fBranches.UncheckedAt(i);
4498 
4499  if (branch->TestBit(kDoNotProcess))
4500  continue;
4501 
4502 #ifndef R__USE_IMT
4503  nwrite = branch->FillImpl(nullptr);
4504 #else
4505  nwrite = branch->FillImpl(useIMT ? &imtHelper : nullptr);
4506 #endif
4507  if (nwrite < 0) {
4508  if (nerror < 2) {
4509  Error("Fill", "Failed filling branch:%s.%s, nbytes=%d, entry=%lld\n"
4510  " This error is symptomatic of a Tree created as a memory-resident Tree\n"
4511  " Instead of doing:\n"
4512  " TTree *T = new TTree(...)\n"
4513  " TFile *f = new TFile(...)\n"
4514  " you should do:\n"
4515  " TFile *f = new TFile(...)\n"
4516  " TTree *T = new TTree(...)\n\n",
4517  GetName(), branch->GetName(), nwrite, fEntries + 1);
4518  } else {
4519  Error("Fill", "Failed filling branch:%s.%s, nbytes=%d, entry=%lld", GetName(), branch->GetName(), nwrite,
4520  fEntries + 1);
4521  }
4522  ++nerror;
4523  } else {
4524  nbytes += nwrite;
4525  }
4526  }
4527 
4528 #ifdef R__USE_IMT
4529  if (fIMTFlush) {
4530  imtHelper.Wait();
4531  fIMTFlush = false;
4532  const_cast<TTree *>(this)->AddTotBytes(fIMTTotBytes);
4533  const_cast<TTree *>(this)->AddZipBytes(fIMTZipBytes);
4534  nbytes += imtHelper.GetNbytes();
4535  nerror += imtHelper.GetNerrors();
4536  }
4537 #endif
4538 
4539  if (fBranchRef)
4540  fBranchRef->Fill();
4541 
4542  ++fEntries;
4543 
4544  if (fEntries > fMaxEntries)
4545  KeepCircular();
4546 
4547  if (gDebug > 0)
4548  Info("TTree::Fill", " - A: %d %lld %lld %lld %lld %lld %lld \n", nbytes, fEntries, fAutoFlush, fAutoSave,
4549  GetZipBytes(), fFlushedBytes, fSavedBytes);
4550 
4551  bool autoFlush = false;
4552  bool autoSave = false;
4553 
4554  if (fAutoFlush != 0 || fAutoSave != 0) {
4555  // Is it time to flush or autosave baskets?
4556  if (fFlushedBytes == 0) {
4557  // If fFlushedBytes == 0, it means we never flushed or saved, so
4558  // we need to check if it's time to do it and recompute the values
4559  // of fAutoFlush and fAutoSave in terms of the number of entries.
4560  // Decision can be based initially either on the number of bytes
4561  // or the number of entries written.
4562  Long64_t zipBytes = GetZipBytes();
4563 
4564  if (fAutoFlush)
4565  autoFlush = fAutoFlush < 0 ? (zipBytes > -fAutoFlush) : fEntries % fAutoFlush == 0;
4566 
4567  if (fAutoSave)
4568  autoSave = fAutoSave < 0 ? (zipBytes > -fAutoSave) : fEntries % fAutoSave == 0;
4569 
4570  if (autoFlush || autoSave) {
4571  // First call FlushBasket to make sure that fTotBytes is up to date.
4572  FlushBasketsImpl();
4573  autoFlush = false; // avoid auto flushing again later
4574 
4575  // When we are in one-basket-per-cluster mode, there is no need to optimize basket:
4576  // they will automatically grow to the size needed for an event cluster (with the basket
4577  // shrinking preventing them from growing too much larger than the actually-used space).
4578  if (!TestBit(TTree::kOnlyFlushAtCluster)) {
4579  OptimizeBaskets(GetTotBytes(), 1, "");
4580  if (gDebug > 0)
4581  Info("TTree::Fill", "OptimizeBaskets called at entry %lld, fZipBytes=%lld, fFlushedBytes=%lld\n",
4582  fEntries, GetZipBytes(), fFlushedBytes);
4583  }
4584  fFlushedBytes = GetZipBytes();
4585  fAutoFlush = fEntries; // Use test on entries rather than bytes
4586 
4587  // subsequently in run
4588  if (fAutoSave < 0) {
4589  // Set fAutoSave to the largest integer multiple of
4590  // fAutoFlush events such that fAutoSave*fFlushedBytes
4591  // < (minus the input value of fAutoSave)
4592  Long64_t totBytes = GetTotBytes();
4593  if (zipBytes != 0) {
4594  fAutoSave = TMath::Max(fAutoFlush, fEntries * ((-fAutoSave / zipBytes) / fEntries));
4595  } else if (totBytes != 0) {
4596  fAutoSave = TMath::Max(fAutoFlush, fEntries * ((-fAutoSave / totBytes) / fEntries));
4597  } else {
4598  TBufferFile b(TBuffer::kWrite, 10000);
4599  TTree::Class()->WriteBuffer(b, (TTree *)this);
4600  Long64_t total = b.Length();
4601  fAutoSave = TMath::Max(fAutoFlush, fEntries * ((-fAutoSave / total) / fEntries));
4602  }
4603  } else if (fAutoSave > 0) {
4604  fAutoSave = fAutoFlush * (fAutoSave / fAutoFlush);
4605  }
4606 
4607  if (fAutoSave != 0 && fEntries >= fAutoSave)
4608  autoSave = true;
4609 
4610  if (gDebug > 0)
4611  Info("TTree::Fill", "First AutoFlush. fAutoFlush = %lld, fAutoSave = %lld\n", fAutoFlush, fAutoSave);
4612  }
4613  } else {
4614  // Check if we need to auto flush
4615  if (fAutoFlush) {
4616  if (fNClusterRange == 0)
4617  autoFlush = fEntries > 1 && fEntries % fAutoFlush == 0;
4618  else
4619  autoFlush = (fEntries - (fClusterRangeEnd[fNClusterRange - 1] + 1)) % fAutoFlush == 0;
4620  }
4621  // Check if we need to auto save
4622  if (fAutoSave)
4623  autoSave = fEntries % fAutoSave == 0;
4624  }
4625  }
4626 
4627  if (autoFlush) {
4628  FlushBasketsImpl();
4629  if (gDebug > 0)
4630  Info("TTree::Fill", "FlushBaskets() called at entry %lld, fZipBytes=%lld, fFlushedBytes=%lld\n", fEntries,
4631  GetZipBytes(), fFlushedBytes);
4632  fFlushedBytes = GetZipBytes();
4633  }
4634 
4635  if (autoSave) {
4636  AutoSave(); // does not call FlushBasketsImpl() again
4637  if (gDebug > 0)
4638  Info("TTree::Fill", "AutoSave called at entry %lld, fZipBytes=%lld, fSavedBytes=%lld\n", fEntries,
4639  GetZipBytes(), fSavedBytes);
4640  }
4641 
4642  // Check that output file is still below the maximum size.
4643  // If above, close the current file and continue on a new file.
4644  // Currently, the automatic change of file is restricted
4645  // to the case where the tree is in the top level directory.
4646  if (fDirectory)
4647  if (TFile *file = fDirectory->GetFile())
4648  if ((TDirectory *)file == fDirectory && (file->GetEND() > fgMaxTreeSize))
4649  ChangeFile(file);
4650 
4651  return nerror == 0 ? nbytes : -1;
4652 }
4653 
4654 ////////////////////////////////////////////////////////////////////////////////
4655 /// Search in the array for a branch matching the branch name,
4656 /// with the branch possibly expressed as a 'full' path name (with dots).
4657 
4658 static TBranch *R__FindBranchHelper(TObjArray *list, const char *branchname) {
4659  if (list==0 || branchname == 0 || branchname[0] == '\0') return 0;
4660 
4661  Int_t nbranches = list->GetEntries();
4662 
4663  UInt_t brlen = strlen(branchname);
4664 
4665  for(Int_t index = 0; index < nbranches; ++index) {
4666  TBranch *where = (TBranch*)list->UncheckedAt(index);
4667 
4668  const char *name = where->GetName();
4669  UInt_t len = strlen(name);
4670  if (len && name[len-1]==']') {
4671  const char *dim = strchr(name,'[');
4672  if (dim) {
4673  len = dim - name;
4674  }
4675  }
4676  if (brlen == len && strncmp(branchname,name,len)==0) {
4677  return where;
4678  }
4679  TBranch *next = 0;
4680  if ((brlen >= len) && (branchname[len] == '.')
4681  && strncmp(name, branchname, len) == 0) {
4682  // The prefix subbranch name match the branch name.
4683 
4684  next = where->FindBranch(branchname);
4685  if (!next) {
4686  next = where->FindBranch(branchname+len+1);
4687  }
4688  if (next) return next;
4689  }
4690  const char *dot = strchr((char*)branchname,'.');
4691  if (dot) {
4692  if (len==(size_t)(dot-branchname) &&
4693  strncmp(branchname,name,dot-branchname)==0 ) {
4694  return R__FindBranchHelper(where->GetListOfBranches(),dot+1);
4695  }
4696  }
4697  }
4698  return 0;
4699 }
4700 
4701 ////////////////////////////////////////////////////////////////////////////////
4702 /// Return the branch that correspond to the path 'branchname', which can
4703 /// include the name of the tree or the omitted name of the parent branches.
4704 /// In case of ambiguity, returns the first match.
4705 
4706 TBranch* TTree::FindBranch(const char* branchname)
4707 {
4708  // We already have been visited while recursively looking
4709  // through the friends tree, let return
4710  if (kFindBranch & fFriendLockStatus) {
4711  return 0;
4712  }
4713 
4714  TBranch* branch = 0;
4715  // If the first part of the name match the TTree name, look for the right part in the
4716  // list of branches.
4717  // This will allow the branchname to be preceded by
4718  // the name of this tree.
4719  if (strncmp(fName.Data(),branchname,fName.Length())==0 && branchname[fName.Length()]=='.') {
4720  branch = R__FindBranchHelper( GetListOfBranches(), branchname + fName.Length() + 1);
4721  if (branch) return branch;
4722  }
4723  // If we did not find it, let's try to find the full name in the list of branches.
4724  branch = R__FindBranchHelper(GetListOfBranches(), branchname);
4725  if (branch) return branch;
4726 
4727  // If we still did not find, let's try to find it within each branch assuming it does not the branch name.
4728  TIter next(GetListOfBranches());
4729  while ((branch = (TBranch*) next())) {
4730  TBranch* nestedbranch = branch->FindBranch(branchname);
4731  if (nestedbranch) {
4732  return nestedbranch;
4733  }
4734  }
4735 
4736  // Search in list of friends.
4737  if (!fFriends) {
4738  return 0;
4739  }
4740  TFriendLock lock(this, kFindBranch);
4741  TIter nextf(fFriends);
4742  TFriendElement* fe = 0;
4743  while ((fe = (TFriendElement*) nextf())) {
4744  TTree* t = fe->GetTree();
4745  if (!t) {
4746  continue;
4747  }
4748  // If the alias is present replace it with the real name.
4749  const char *subbranch = strstr(branchname, fe->GetName());
4750  if (subbranch != branchname) {
4751  subbranch = 0;
4752  }
4753  if (subbranch) {
4754  subbranch += strlen(fe->GetName());
4755  if (*subbranch != '.') {
4756  subbranch = 0;
4757  } else {
4758  ++subbranch;
4759  }
4760  }
4761  std::ostringstream name;
4762  if (subbranch) {
4763  name << t->GetName() << "." << subbranch;
4764  } else {
4765  name << branchname;
4766  }
4767  branch = t->FindBranch(name.str().c_str());
4768  if (branch) {
4769  return branch;
4770  }
4771  }
4772  return 0;
4773 }
4774 
4775 ////////////////////////////////////////////////////////////////////////////////
4776 /// Find leaf..
4777 
4778 TLeaf* TTree::FindLeaf(const char* searchname)
4779 {
4780  // We already have been visited while recursively looking
4781  // through the friends tree, let's return.
4782  if (kFindLeaf & fFriendLockStatus) {
4783  return 0;
4784  }
4785 
4786  // This will allow the branchname to be preceded by
4787  // the name of this tree.
4788  char* subsearchname = (char*) strstr(searchname, GetName());
4789  if (subsearchname != searchname) {
4790  subsearchname = 0;
4791  }
4792  if (subsearchname) {
4793  subsearchname += strlen(GetName());
4794  if (*subsearchname != '.') {
4795  subsearchname = 0;
4796  } else {
4797  ++subsearchname;
4798  if (subsearchname[0]==0) {
4799  subsearchname = 0;
4800  }
4801  }
4802  }
4803 
4804  TString leafname;
4805  TString leaftitle;
4806  TString longname;
4807  TString longtitle;
4808 
4809  const bool searchnameHasDot = strchr(searchname, '.') != nullptr;
4810 
4811  // For leaves we allow for one level up to be prefixed to the name.
4812  TIter next(GetListOfLeaves());
4813  TLeaf* leaf = 0;
4814  while ((leaf = (TLeaf*) next())) {
4815  leafname = leaf->GetName();
4816  Ssiz_t dim = leafname.First('[');
4817  if (dim >= 0) leafname.Remove(dim);
4818 
4819  if (leafname == searchname) {
4820  return leaf;
4821  }
4822  if (subsearchname && leafname == subsearchname) {
4823  return leaf;
4824  }
4825  // The TLeafElement contains the branch name
4826  // in its name, let's use the title.
4827  leaftitle = leaf->GetTitle();
4828  dim = leaftitle.First('[');
4829  if (dim >= 0) leaftitle.Remove(dim);
4830 
4831  if (leaftitle == searchname) {
4832  return leaf;
4833  }
4834  if (subsearchname && leaftitle == subsearchname) {
4835  return leaf;
4836  }
4837  if (!searchnameHasDot)
4838  continue;
4839  TBranch* branch = leaf->GetBranch();
4840  if (branch) {
4841  longname.Form("%s.%s",branch->GetName(),leafname.Data());
4842  dim = longname.First('[');
4843  if (dim>=0) longname.Remove(dim);
4844  if (longname == searchname) {
4845  return leaf;
4846  }
4847  if (subsearchname && longname == subsearchname) {
4848  return leaf;
4849  }
4850  longtitle.Form("%s.%s",branch->GetName(),leaftitle.Data());
4851  dim = longtitle.First('[');
4852  if (dim>=0) longtitle.Remove(dim);
4853  if (longtitle == searchname) {
4854  return leaf;
4855  }
4856  if (subsearchname && longtitle == subsearchname) {
4857  return leaf;
4858  }
4859  // The following is for the case where the branch is only
4860  // a sub-branch. Since we do not see it through
4861  // TTree::GetListOfBranches, we need to see it indirectly.
4862  // This is the less sturdy part of this search ... it may
4863  // need refining ...
4864  if (strstr(searchname, ".") && !strcmp(searchname, branch->GetName())) {
4865  return leaf;
4866  }
4867  if (subsearchname && strstr(subsearchname, ".") && !strcmp(subsearchname, branch->GetName())) {
4868  return leaf;
4869  }
4870  }
4871  }
4872  // Search in list of friends.
4873  if (!fFriends) {
4874  return 0;
4875  }
4876  TFriendLock lock(this, kFindLeaf);
4877  TIter nextf(fFriends);
4878  TFriendElement* fe = 0;
4879  while ((fe = (TFriendElement*) nextf())) {
4880  TTree* t = fe->GetTree();
4881  if (!t) {
4882  continue;
4883  }
4884  // If the alias is present replace it with the real name.
4885  subsearchname = (char*) strstr(searchname, fe->GetName());
4886  if (subsearchname != searchname) {
4887  subsearchname = 0;
4888  }
4889  if (subsearchname) {
4890  subsearchname += strlen(fe->GetName());
4891  if (*subsearchname != '.') {
4892  subsearchname = 0;
4893  } else {
4894  ++subsearchname;
4895  }
4896  }
4897  if (subsearchname) {
4898  leafname.Form("%s.%s",t->GetName(),subsearchname);
4899  } else {
4900  leafname = searchname;
4901  }
4902  leaf = t->FindLeaf(leafname);
4903  if (leaf) {
4904  return leaf;
4905  }
4906  }
4907  return 0;
4908 }
4909 
4910 ////////////////////////////////////////////////////////////////////////////////
4911 /// Fit a projected item(s) from a tree.
4912 ///
4913 /// funcname is a TF1 function.
4914 ///
4915 /// See TTree::Draw() for explanations of the other parameters.
4916 ///
4917 /// By default the temporary histogram created is called htemp.
4918 /// If varexp contains >>hnew , the new histogram created is called hnew
4919 /// and it is kept in the current directory.
4920 ///
4921 /// The function returns the number of selected entries.
4922 ///
4923 /// Example:
4924 /// ~~~ {.cpp}
4925 /// tree.Fit(pol4,"sqrt(x)>>hsqrt","y>0")
4926 /// ~~~
4927 /// will fit sqrt(x) and save the histogram as "hsqrt" in the current
4928 /// directory.
4929 ///
4930 /// See also TTree::UnbinnedFit
4931 ///
4932 /// ## Return status
4933 ///
4934 /// The function returns the status of the histogram fit (see TH1::Fit)
4935 /// If no entries were selected, the function returns -1;
4936 /// (i.e. fitResult is null if the fit is OK)
4937 
4938 Int_t TTree::Fit(const char* funcname, const char* varexp, const char* selection, Option_t* option, Option_t* goption, Long64_t nentries, Long64_t firstentry)
4939 {
4940  GetPlayer();
4941  if (fPlayer) {
4942  return fPlayer->Fit(funcname, varexp, selection, option, goption, nentries, firstentry);
4943  }
4944  return -1;
4945 }
4946 
4947 namespace {
4948 struct BoolRAIIToggle {
4949  Bool_t &m_val;
4950 
4951  BoolRAIIToggle(Bool_t &val) : m_val(val) { m_val = true; }
4952  ~BoolRAIIToggle() { m_val = false; }
4953 };
4954 }
4955 
4956 ////////////////////////////////////////////////////////////////////////////////
4957 /// Write to disk all the basket that have not yet been individually written and
4958 /// create an event cluster boundary (by default).
4959 ///
4960 /// If the caller wishes to flush the baskets but not create an event cluster,
4961 /// then set create_cluster to false.
4962 ///
4963 /// If ROOT has IMT-mode enabled, this will launch multiple TBB tasks in parallel
4964 /// via TThreadExecutor to do this operation; one per basket compression. If the
4965 /// caller utilizes TBB also, care must be taken to prevent deadlocks.
4966 ///
4967 /// For example, let's say the caller holds mutex A and calls FlushBaskets; while
4968 /// TBB is waiting for the ROOT compression tasks to complete, it may decide to
4969 /// run another one of the user's tasks in this thread. If the second user task
4970 /// tries to acquire A, then a deadlock will occur. The example call sequence
4971 /// looks like this:
4972 ///
4973 /// - User acquires mutex A
4974 /// - User calls FlushBaskets.
4975 /// - ROOT launches N tasks and calls wait.
4976 /// - TBB schedules another user task, T2.
4977 /// - T2 tries to acquire mutex A.
4978 ///
4979 /// At this point, the thread will deadlock: the code may function with IMT-mode
4980 /// disabled if the user assumed the legacy code never would run their own TBB
4981 /// tasks.
4982 ///
4983 /// SO: users of TBB who want to enable IMT-mode should carefully review their
4984 /// locking patterns and make sure they hold no coarse-grained application
4985 /// locks when they invoke ROOT.
4986 ///
4987 /// Return the number of bytes written or -1 in case of write error.
4988 Int_t TTree::FlushBaskets(Bool_t create_cluster) const
4989 {
4990  Int_t retval = FlushBasketsImpl();
4991  if (retval == -1) return retval;
4992 
4993  if (create_cluster) const_cast<TTree *>(this)->MarkEventCluster();
4994  return retval;
4995 }
4996 
4997 ////////////////////////////////////////////////////////////////////////////////
4998 /// Internal implementation of the FlushBaskets algorithm.
4999 /// Unlike the public interface, this does NOT create an explicit event cluster
5000 /// boundary; it is up to the (internal) caller to determine whether that should
5001 /// done.
5002 ///
5003 /// Otherwise, the comments for FlushBaskets applies.
5004 ///
5005 Int_t TTree::FlushBasketsImpl() const
5006 {
5007  if (!fDirectory) return 0;
5008  Int_t nbytes = 0;
5009  Int_t nerror = 0;
5010  TObjArray *lb = const_cast<TTree*>(this)->GetListOfBranches();
5011  Int_t nb = lb->GetEntriesFast();
5012 
5013 #ifdef R__USE_IMT
5014  const auto useIMT = ROOT::IsImplicitMTEnabled() && fIMTEnabled;
5015  if (useIMT) {
5016  // ROOT-9668: here we need to check if the size of fSortedBranches is different from the
5017  // size of the list of branches before triggering the initialisation of the fSortedBranches
5018  // container to cover two cases:
5019  // 1. This is the first time we flush. fSortedBranches is empty and we need to fill it.
5020  // 2. We flushed at least once already but a branch has been be added to the tree since then
5021  if (fSortedBranches.size() != unsigned(nb)) { const_cast<TTree*>(this)->InitializeBranchLists(false); }
5022 
5023  BoolRAIIToggle sentry(fIMTFlush);
5024  fIMTZipBytes.store(0);
5025  fIMTTotBytes.store(0);
5026  std::atomic<Int_t> nerrpar(0);
5027  std::atomic<Int_t> nbpar(0);
5028  std::atomic<Int_t> pos(0);
5029 
5030  auto mapFunction = [&]() {
5031  // The branch to process is obtained when the task starts to run.
5032  // This way, since branches are sorted, we make sure that branches
5033  // leading to big tasks are processed first. If we assigned the
5034  // branch at task creation time, the scheduler would not necessarily
5035  // respect our sorting.
5036  Int_t j = pos.fetch_add(1);
5037 
5038  auto branch = fSortedBranches[j].second;
5039  if (R__unlikely(!branch)) { return; }
5040 
5041  if (R__unlikely(gDebug > 0)) {
5042  std::stringstream ss;
5043  ss << std::this_thread::get_id();
5044  Info("FlushBaskets", "[IMT] Thread %s", ss.str().c_str());
5045  Info("FlushBaskets", "[IMT] Running task for branch #%d: %s", j, branch->GetName());
5046  }
5047 
5048  Int_t nbtask = branch->FlushBaskets();
5049 
5050  if (nbtask < 0) { nerrpar++; }
5051  else { nbpar += nbtask; }
5052  };
5053 
5054  ROOT::TThreadExecutor pool;
5055  pool.Foreach(mapFunction, nb);
5056 
5057  fIMTFlush = false;
5058  const_cast<TTree*>(this)->AddTotBytes(fIMTTotBytes);
5059  const_cast<TTree*>(this)->AddZipBytes(fIMTZipBytes);
5060 
5061  return nerrpar ? -1 : nbpar.load();
5062  }
5063 #endif
5064  for (Int_t j = 0; j < nb; j++) {
5065  TBranch* branch = (TBranch*) lb->UncheckedAt(j);
5066  if (branch) {
5067  Int_t nwrite = branch->FlushBaskets();
5068  if (nwrite<0) {
5069  ++nerror;
5070  } else {
5071  nbytes += nwrite;
5072  }
5073  }
5074  }
5075  if (nerror) {
5076  return -1;
5077  } else {
5078  return nbytes;
5079  }
5080 }
5081 
5082 ////////////////////////////////////////////////////////////////////////////////
5083 /// Returns the expanded value of the alias. Search in the friends if any.
5084 
5085 const char* TTree::GetAlias(const char* aliasName) const
5086 {
5087  // We already have been visited while recursively looking
5088  // through the friends tree, let's return.
5089  if (kGetAlias & fFriendLockStatus) {
5090  return 0;
5091  }
5092  if (fAliases) {
5093  TObject* alias = fAliases->FindObject(aliasName);
5094  if (alias) {
5095  return alias->GetTitle();
5096  }
5097  }
5098  if (!fFriends) {
5099  return 0;
5100  }
5101  TFriendLock lock(const_cast<TTree*>(this), kGetAlias);
5102  TIter nextf(fFriends);
5103  TFriendElement* fe = 0;
5104  while ((fe = (TFriendElement*) nextf())) {
5105  TTree* t = fe->GetTree();
5106  if (t) {
5107  const char* alias = t->GetAlias(aliasName);
5108  if (alias) {
5109  return alias;
5110  }
5111  const char* subAliasName = strstr(aliasName, fe->GetName());
5112  if (subAliasName && (subAliasName[strlen(fe->GetName())] == '.')) {
5113  alias = t->GetAlias(aliasName + strlen(fe->GetName()) + 1);
5114  if (alias) {
5115  return alias;
5116  }
5117  }
5118  }
5119  }
5120  return 0;
5121 }
5122 
5123 ////////////////////////////////////////////////////////////////////////////////
5124 /// Return pointer to the branch with the given name in this tree or its friends.
5125 
5126 TBranch* TTree::GetBranch(const char* name)
5127 {
5128  if (name == 0) return 0;
5129 
5130  // We already have been visited while recursively
5131  // looking through the friends tree, let's return.
5132  if (kGetBranch & fFriendLockStatus) {
5133  return 0;
5134  }
5135 
5136  // Search using branches.
5137  Int_t nb = fBranches.GetEntriesFast();
5138  for (Int_t i = 0; i < nb; i++) {
5139  TBranch* branch = (TBranch*) fBranches.UncheckedAt(i);
5140  if (!branch) {
5141  continue;
5142  }
5143  if (!strcmp(branch->GetName(), name)) {
5144  return branch;
5145  }
5146  TObjArray* lb = branch->GetListOfBranches();
5147  Int_t nb1 = lb->GetEntriesFast();
5148  for (Int_t j = 0; j < nb1; j++) {
5149  TBranch* b1 = (TBranch*) lb->UncheckedAt(j);
5150  if (!strcmp(b1->GetName(), name)) {
5151  return b1;
5152  }
5153  TObjArray* lb1 = b1->GetListOfBranches();
5154  Int_t nb2 = lb1->GetEntriesFast();
5155  for (Int_t k = 0; k < nb2; k++) {
5156  TBranch* b2 = (TBranch*) lb1->UncheckedAt(k);
5157  if (!strcmp(b2->GetName(), name)) {
5158  return b2;
5159  }
5160  }
5161  }
5162  }
5163 
5164  // Search using leaves.
5165  TObjArray* leaves = GetListOfLeaves();
5166  Int_t nleaves = leaves->GetEntriesFast();
5167  for (Int_t i = 0; i < nleaves; i++) {
5168  TLeaf* leaf = (TLeaf*) leaves->UncheckedAt(i);
5169  TBranch* branch = leaf->GetBranch();
5170  if (!strcmp(branch->GetName(), name)) {
5171  return branch;
5172  }
5173  }
5174 
5175  if (!fFriends) {
5176  return 0;
5177  }
5178 
5179  // Search in list of friends.
5180  TFriendLock lock(this, kGetBranch);
5181  TIter next(fFriends);
5182  TFriendElement* fe = 0;
5183  while ((fe = (TFriendElement*) next())) {
5184  TTree* t = fe->GetTree();
5185  if (t) {
5186  TBranch* branch = t->GetBranch(name);
5187  if (branch) {
5188  return branch;
5189  }
5190  }
5191  }
5192 
5193  // Second pass in the list of friends when
5194  // the branch name is prefixed by the tree name.
5195  next.Reset();
5196  while ((fe = (TFriendElement*) next())) {
5197  TTree* t = fe->GetTree();
5198  if (!t) {
5199  continue;
5200  }
5201  char* subname = (char*) strstr(name, fe->GetName());
5202  if (subname != name) {
5203  continue;
5204  }
5205  Int_t l = strlen(fe->GetName());
5206  subname += l;
5207  if (*subname != '.') {
5208  continue;
5209  }
5210  subname++;
5211  TBranch* branch = t->GetBranch(subname);
5212  if (branch) {
5213  return branch;
5214  }
5215  }
5216  return 0;
5217 }
5218 
5219 ////////////////////////////////////////////////////////////////////////////////
5220 /// Return status of branch with name branchname.
5221 ///
5222 /// - 0 if branch is not activated
5223 /// - 1 if branch is activated
5224 
5225 Bool_t TTree::GetBranchStatus(const char* branchname) const
5226 {
5227  TBranch* br = const_cast<TTree*>(this)->GetBranch(branchname);
5228  if (br) {
5229  return br->TestBit(kDoNotProcess) == 0;
5230  }
5231  return 0;
5232 }
5233 
5234 ////////////////////////////////////////////////////////////////////////////////
5235 /// Static function returning the current branch style.
5236 ///
5237 /// - style = 0 old Branch
5238 /// - style = 1 new Bronch
5239 
5240 Int_t TTree::GetBranchStyle()
5241 {
5242  return fgBranchStyle;
5243 }
5244 
5245 ////////////////////////////////////////////////////////////////////////////////
5246 /// Used for automatic sizing of the cache.
5247 ///
5248 /// Estimates a suitable size for the tree cache based on AutoFlush.
5249 /// A cache sizing factor is taken from the configuration. If this yields zero
5250 /// and withDefault is true the historical algorithm for default size is used.
5251 
5252 Long64_t TTree::GetCacheAutoSize(Bool_t withDefault /* = kFALSE */ ) const
5253 {
5254  const char *stcs;
5255  Double_t cacheFactor = 0.0;
5256  if (!(stcs = gSystem->Getenv("ROOT_TTREECACHE_SIZE")) || !*stcs) {
5257  cacheFactor = gEnv->GetValue("TTreeCache.Size", 1.0);
5258  } else {
5259  cacheFactor = TString(stcs).Atof();
5260  }
5261 
5262  if (cacheFactor < 0.0) {
5263  // ignore negative factors
5264  cacheFactor = 0.0;
5265  }
5266 
5267  Long64_t cacheSize = 0;
5268 
5269  if (fAutoFlush < 0) cacheSize = Long64_t(-cacheFactor*fAutoFlush);
5270  else if (fAutoFlush == 0) cacheSize = 0;
5271  else cacheSize = Long64_t(cacheFactor*1.5*fAutoFlush*GetZipBytes()/(fEntries+1));
5272 
5273  if (cacheSize >= (INT_MAX / 4)) {
5274  cacheSize = INT_MAX / 4;
5275  }
5276 
5277  if (cacheSize < 0) {
5278  cacheSize = 0;
5279  }
5280 
5281  if (cacheSize == 0 && withDefault) {
5282  if (fAutoFlush < 0) cacheSize = -fAutoFlush;
5283  else if (fAutoFlush == 0) cacheSize = 0;
5284  else cacheSize = Long64_t(1.5*fAutoFlush*GetZipBytes()/(fEntries+1));
5285  }
5286 
5287  return cacheSize;
5288 }
5289 
5290 ////////////////////////////////////////////////////////////////////////////////
5291 /// Return an iterator over the cluster of baskets starting at firstentry.
5292 ///
5293 /// This iterator is not yet supported for TChain object.
5294 /// ~~~ {.cpp}
5295 /// TTree::TClusterIterator clusterIter = tree->GetClusterIterator(entry);
5296 /// Long64_t clusterStart;
5297 /// while( (clusterStart = clusterIter()) < tree->GetEntries() ) {
5298 /// printf("The cluster starts at %lld and ends at %lld (inclusive)\n",clusterStart,clusterIter.GetNextEntry()-1);
5299 /// }
5300 /// ~~~
5301 
5302 TTree::TClusterIterator TTree::GetClusterIterator(Long64_t firstentry)
5303 {
5304  // create cache if wanted
5305  if (fCacheDoAutoInit)
5306  SetCacheSizeAux();
5307 
5308  return TClusterIterator(this,firstentry);
5309 }
5310 
5311 ////////////////////////////////////////////////////////////////////////////////
5312 /// Return pointer to the current file.
5313 
5314 TFile* TTree::GetCurrentFile() const
5315 {
5316  if (!fDirectory || fDirectory==gROOT) {
5317  return 0;
5318  }
5319  return fDirectory->GetFile();
5320 }
5321 
5322 ////////////////////////////////////////////////////////////////////////////////
5323 /// Return the number of entries matching the selection.
5324 /// Return -1 in case of errors.
5325 ///
5326 /// If the selection uses any arrays or containers, we return the number
5327 /// of entries where at least one element match the selection.
5328 /// GetEntries is implemented using the selector class TSelectorEntries,
5329 /// which can be used directly (see code in TTreePlayer::GetEntries) for
5330 /// additional option.
5331 /// If SetEventList was used on the TTree or TChain, only that subset
5332 /// of entries will be considered.
5333 
5334 Long64_t TTree::GetEntries(const char *selection)
5335 {
5336  GetPlayer();
5337  if (fPlayer) {
5338  return fPlayer->GetEntries(selection);
5339  }
5340  return -1;
5341 }
5342 
5343 ////////////////////////////////////////////////////////////////////////////////
5344 /// Return pointer to the 1st Leaf named name in any Branch of this Tree or
5345 /// any branch in the list of friend trees.
5346 
5347 Long64_t TTree::GetEntriesFriend() const
5348 {
5349  if (fEntries) return fEntries;
5350  if (!fFriends) return 0;
5351  TFriendElement *fr = (TFriendElement*)fFriends->At(0);
5352  if (!fr) return 0;
5353  TTree *t = fr->GetTree();
5354  if (t==0) return 0;
5355  return t->GetEntriesFriend();
5356 }
5357 
5358 ////////////////////////////////////////////////////////////////////////////////
5359 /// Read all branches of entry and return total number of bytes read.
5360 ///
5361 /// - `getall = 0` : get only active branches
5362 /// - `getall = 1` : get all branches
5363 ///
5364 /// The function returns the number of bytes read from the input buffer.
5365 /// If entry does not exist the function returns 0.
5366 /// If an I/O error occurs, the function returns -1.
5367 ///
5368 /// If the Tree has friends, also read the friends entry.
5369 ///
5370 /// To activate/deactivate one or more branches, use TBranch::SetBranchStatus
5371 /// For example, if you have a Tree with several hundred branches, and you
5372 /// are interested only by branches named "a" and "b", do
5373 /// ~~~ {.cpp}
5374 /// mytree.SetBranchStatus("*",0); //disable all branches
5375 /// mytree.SetBranchStatus("a",1);
5376 /// mytree.SetBranchStatus("b",1);
5377 /// ~~~
5378 /// when calling mytree.GetEntry(i); only branches "a" and "b" will be read.
5379 ///
5380 /// __WARNING!!__
5381 /// If your Tree has been created in split mode with a parent branch "parent.",
5382 /// ~~~ {.cpp}
5383 /// mytree.SetBranchStatus("parent",1);
5384 /// ~~~
5385 /// will not activate the sub-branches of "parent". You should do:
5386 /// ~~~ {.cpp}
5387 /// mytree.SetBranchStatus("parent*",1);
5388 /// ~~~
5389 /// Without the trailing dot in the branch creation you have no choice but to
5390 /// call SetBranchStatus explicitly for each of the sub branches.
5391 ///
5392 /// An alternative is to call directly
5393 /// ~~~ {.cpp}
5394 /// brancha.GetEntry(i)
5395 /// branchb.GetEntry(i);
5396 /// ~~~
5397 /// ## IMPORTANT NOTE
5398 ///
5399 /// By default, GetEntry reuses the space allocated by the previous object
5400 /// for each branch. You can force the previous object to be automatically
5401 /// deleted if you call mybranch.SetAutoDelete(kTRUE) (default is kFALSE).
5402 ///
5403 /// Example:
5404 ///
5405 /// Consider the example in $ROOTSYS/test/Event.h
5406 /// The top level branch in the tree T is declared with:
5407 /// ~~~ {.cpp}
5408 /// Event *event = 0; //event must be null or point to a valid object
5409 /// //it must be initialized
5410 /// T.SetBranchAddress("event",&event);
5411 /// ~~~
5412 /// When reading the Tree, one can choose one of these 3 options:
5413 ///
5414 /// ## OPTION 1
5415 ///
5416 /// ~~~ {.cpp}
5417 /// for (Long64_t i=0;i<nentries;i++) {
5418 /// T.GetEntry(i);
5419 /// // the object event has been filled at this point
5420 /// }
5421 /// ~~~
5422 /// The default (recommended). At the first entry an object of the class
5423 /// Event will be created and pointed by event. At the following entries,
5424 /// event will be overwritten by the new data. All internal members that are
5425 /// TObject* are automatically deleted. It is important that these members
5426 /// be in a valid state when GetEntry is called. Pointers must be correctly
5427 /// initialized. However these internal members will not be deleted if the
5428 /// characters "->" are specified as the first characters in the comment
5429 /// field of the data member declaration.
5430 ///
5431 /// If "->" is specified, the pointer member is read via pointer->Streamer(buf).
5432 /// In this case, it is assumed that the pointer is never null (case of
5433 /// pointer TClonesArray *fTracks in the Event example). If "->" is not
5434 /// specified, the pointer member is read via buf >> pointer. In this case
5435 /// the pointer may be null. Note that the option with "->" is faster to
5436 /// read or write and it also consumes less space in the file.
5437 ///
5438 /// ## OPTION 2
5439 ///
5440 /// The option AutoDelete is set
5441 /// ~~~ {.cpp}
5442 /// TBranch *branch = T.GetBranch("event");
5443 /// branch->SetAddress(&event);
5444 /// branch->SetAutoDelete(kTRUE);
5445 /// for (Long64_t i=0;i<nentries;i++) {
5446 /// T.GetEntry(i);
5447 /// // the object event has been filled at this point
5448 /// }
5449 /// ~~~
5450 /// In this case, at each iteration, the object event is deleted by GetEntry
5451 /// and a new instance of Event is created and filled.
5452 ///
5453 /// ## OPTION 3
5454 ///
5455 /// ~~~ {.cpp}
5456 /// Same as option 1, but you delete yourself the event.
5457 ///
5458 /// for (Long64_t i=0;i<nentries;i++) {
5459 /// delete event;
5460 /// event = 0; // EXTREMELY IMPORTANT
5461 /// T.GetEntry(i);
5462 /// // the object event has been filled at this point
5463 /// }
5464 /// ~~~
5465 /// It is strongly recommended to use the default option 1. It has the
5466 /// additional advantage that functions like TTree::Draw (internally calling
5467 /// TTree::GetEntry) will be functional even when the classes in the file are
5468 /// not available.
5469 ///
5470 /// Note: See the comments in TBranchElement::SetAddress() for the
5471 /// object ownership policy of the underlying (user) data.
5472 
5473 Int_t TTree::GetEntry(Long64_t entry, Int_t getall)
5474 {
5475 
5476  // We already have been visited while recursively looking
5477  // through the friends tree, let return
5478  if (kGetEntry & fFriendLockStatus) return 0;
5479 
5480  if (entry < 0 || entry >= fEntries) return 0;
5481  Int_t i;
5482  Int_t nbytes = 0;
5483  fReadEntry = entry;
5484 
5485  // create cache if wanted
5486  if (fCacheDoAutoInit)
5487  SetCacheSizeAux();
5488 
5489  Int_t nbranches = fBranches.GetEntriesUnsafe();
5490  Int_t nb=0;
5491 
5492  auto seqprocessing = [&]() {
5493  TBranch *branch;
5494  for (i=0;i<nbranches;i++) {
5495  branch = (TBranch*)fBranches.UncheckedAt(i);
5496  nb = branch->GetEntry(entry, getall);
5497  if (nb < 0) break;
5498  nbytes += nb;
5499  }
5500  };
5501 
5502 #ifdef R__USE_IMT
5503  if (nbranches > 1 && ROOT::IsImplicitMTEnabled() && fIMTEnabled && !TTreeCacheUnzip::IsParallelUnzip()) {
5504  if (fSortedBranches.empty())
5505  InitializeBranchLists(true);
5506 
5507  // Count branches are processed first and sequentially
5508  for (auto branch : fSeqBranches) {
5509  nb = branch->GetEntry(entry, getall);
5510  if (nb < 0) break;
5511  nbytes += nb;
5512  }
5513  if (nb < 0) return nb;
5514 
5515  // Enable this IMT use case (activate its locks)
5516  ROOT::Internal::TParBranchProcessingRAII pbpRAII;
5517 
5518  Int_t errnb = 0;
5519  std::atomic<Int_t> pos(0);
5520  std::atomic<Int_t> nbpar(0);
5521 
5522  auto mapFunction = [&]() {
5523  // The branch to process is obtained when the task starts to run.
5524  // This way, since branches are sorted, we make sure that branches
5525  // leading to big tasks are processed first. If we assigned the
5526  // branch at task creation time, the scheduler would not necessarily
5527  // respect our sorting.
5528  Int_t j = pos.fetch_add(1);
5529 
5530  Int_t nbtask = 0;
5531  auto branch = fSortedBranches[j].second;
5532 
5533  if (gDebug > 0) {
5534  std::stringstream ss;
5535  ss << std::this_thread::get_id();
5536  Info("GetEntry", "[IMT] Thread %s", ss.str().c_str());
5537  Info("GetEntry", "[IMT] Running task for branch #%d: %s", j, branch->GetName());
5538  }
5539 
5540  std::chrono::time_point<std::chrono::system_clock> start, end;
5541 
5542  start = std::chrono::system_clock::now();
5543  nbtask = branch->GetEntry(entry, getall);
5544  end = std::chrono::system_clock::now();
5545 
5546  Long64_t tasktime = (Long64_t)std::chrono::duration_cast<std::chrono::microseconds>(end - start).count();
5547  fSortedBranches[j].first += tasktime;
5548 
5549  if (nbtask < 0) errnb = nbtask;
5550  else nbpar += nbtask;
5551  };
5552 
5553  ROOT::TThreadExecutor pool;
5554  pool.Foreach(mapFunction, fSortedBranches.size());
5555 
5556  if (errnb < 0) {
5557  nb = errnb;
5558  }
5559  else {
5560  // Save the number of bytes read by the tasks
5561  nbytes += nbpar;
5562 
5563  // Re-sort branches if necessary
5564  if (++fNEntriesSinceSorting == kNEntriesResort) {
5565  SortBranchesByTime();
5566  fNEntriesSinceSorting = 0;
5567  }
5568  }
5569  }
5570  else {
5571  seqprocessing();
5572  }
5573 #else
5574  seqprocessing();
5575 #endif
5576  if (nb < 0) return nb;
5577 
5578  // GetEntry in list of friends
5579  if (!fFriends) return nbytes;
5580  TFriendLock lock(this,kGetEntry);
5581  TIter nextf(fFriends);
5582  TFriendElement *fe;
5583  while ((fe = (TFriendElement*)nextf())) {
5584  TTree *t = fe->GetTree();
5585  if (t) {
5586  if (fe->TestBit(TFriendElement::kFromChain)) {
5587  nb = t->GetEntry(t->GetReadEntry(),getall);
5588  } else {
5589  if ( t->LoadTreeFriend(entry,this) >= 0 ) {
5590  nb = t->GetEntry(t->GetReadEntry(),getall);
5591  } else nb = 0;
5592  }
5593  if (nb < 0) return nb;
5594  nbytes += nb;
5595  }
5596  }
5597  return nbytes;
5598 }
5599 
5600 
5601 ////////////////////////////////////////////////////////////////////////////////
5602 /// Divides the top-level branches into two vectors: (i) branches to be
5603 /// processed sequentially and (ii) branches to be processed in parallel.
5604 /// Even if IMT is on, some branches might need to be processed first and in a
5605 /// sequential fashion: in the parallelization of GetEntry, those are the
5606 /// branches that store the size of another branch for every entry
5607 /// (e.g. the size of an array branch). If such branches were processed
5608 /// in parallel with the rest, there could be two threads invoking
5609 /// TBranch::GetEntry on one of them at the same time, since a branch that
5610 /// depends on a size (or count) branch will also invoke GetEntry on the latter.
5611 /// This method can be invoked several times during the event loop if the TTree
5612 /// is being written, for example when adding new branches. In these cases, the
5613 /// `checkLeafCount` parameter is false.
5614 /// \param[in] checkLeafCount True if we need to check whether some branches are
5615 /// count leaves.
5616 
5617 void TTree::InitializeBranchLists(bool checkLeafCount)
5618 {
5619  Int_t nbranches = fBranches.GetEntriesFast();
5620 
5621  // The special branch fBranchRef needs to be processed sequentially:
5622  // we add it once only.
5623  if (fBranchRef && fBranchRef != fSeqBranches[0]) {
5624  fSeqBranches.push_back(fBranchRef);
5625  }
5626 
5627  // The branches to be processed sequentially are those that are the leaf count of another branch
5628  if (checkLeafCount) {
5629  for (Int_t i = 0; i < nbranches; i++) {
5630  TBranch* branch = (TBranch*)fBranches.UncheckedAt(i);
5631  auto leafCount = ((TLeaf*)branch->GetListOfLeaves()->At(0))->GetLeafCount();
5632  if (leafCount) {
5633  auto countBranch = leafCount->GetBranch();
5634  if (std::find(fSeqBranches.begin(), fSeqBranches.end(), countBranch) == fSeqBranches.end()) {
5635  fSeqBranches.push_back(countBranch);
5636  }
5637  }
5638  }
5639  }
5640 
5641  // Any branch that is not a leaf count can be safely processed in parallel when reading
5642  // We need to reset the vector to make sure we do not re-add several times the same branch.
5643  if (!checkLeafCount) {
5644  fSortedBranches.clear();
5645  }
5646  for (Int_t i = 0; i < nbranches; i++) {
5647  Long64_t bbytes = 0;
5648  TBranch* branch = (TBranch*)fBranches.UncheckedAt(i);
5649  if (std::find(fSeqBranches.begin(), fSeqBranches.end(), branch) == fSeqBranches.end()) {
5650  bbytes = branch->GetTotBytes("*");
5651  fSortedBranches.emplace_back(bbytes, branch);
5652  }
5653  }
5654 
5655  // Initially sort parallel branches by size
5656  std::sort(fSortedBranches.begin(),
5657  fSortedBranches.end(),
5658  [](std::pair<Long64_t,TBranch*> a, std::pair<Long64_t,TBranch*> b) {
5659  return a.first > b.first;
5660  });
5661 
5662  for (size_t i = 0; i < fSortedBranches.size(); i++) {
5663  fSortedBranches[i].first = 0LL;
5664  }
5665 }
5666 
5667 ////////////////////////////////////////////////////////////////////////////////
5668 /// Sorts top-level branches by the last average task time recorded per branch.
5669 
5670 void TTree::SortBranchesByTime()
5671 {
5672  for (size_t i = 0; i < fSortedBranches.size(); i++) {
5673  fSortedBranches[i].first *= kNEntriesResortInv;
5674  }
5675 
5676  std::sort(fSortedBranches.begin(),
5677  fSortedBranches.end(),
5678  [](std::pair<Long64_t,TBranch*> a, std::pair<Long64_t,TBranch*> b) {
5679  return a.first > b.first;
5680  });
5681 
5682  for (size_t i = 0; i < fSortedBranches.size(); i++) {
5683  fSortedBranches[i].first = 0LL;
5684  }
5685 }
5686 
5687 ////////////////////////////////////////////////////////////////////////////////
5688 ///Returns the entry list assigned to this tree
5689 
5690 TEntryList* TTree::GetEntryList()
5691 {
5692  return fEntryList;
5693 }
5694 
5695 ////////////////////////////////////////////////////////////////////////////////
5696 /// Return entry number corresponding to entry.
5697 ///
5698 /// if no TEntryList set returns entry
5699 /// else returns the entry number corresponding to the list index=entry
5700 
5701 Long64_t TTree::GetEntryNumber(Long64_t entry) const
5702 {
5703  if (!fEntryList) {
5704  return entry;
5705  }
5706 
5707  return fEntryList->GetEntry(entry);
5708 }
5709 
5710 ////////////////////////////////////////////////////////////////////////////////
5711 /// Return entry number corresponding to major and minor number.
5712 /// Note that this function returns only the entry number, not the data
5713 /// To read the data corresponding to an entry number, use TTree::GetEntryWithIndex
5714 /// the BuildIndex function has created a table of Long64_t* of sorted values
5715 /// corresponding to val = major<<31 + minor;
5716 /// The function performs binary search in this sorted table.
5717 /// If it finds a pair that matches val, it returns directly the
5718 /// index in the table.
5719 /// If an entry corresponding to major and minor is not found, the function
5720 /// returns the index of the major,minor pair immediately lower than the
5721 /// requested value, ie it will return -1 if the pair is lower than
5722 /// the first entry in the index.
5723 ///
5724 /// See also GetEntryNumberWithIndex
5725 
5726 Long64_t TTree::GetEntryNumberWithBestIndex(Long64_t major, Long64_t minor) const
5727 {
5728  if (!fTreeIndex) {
5729  return -1;
5730  }
5731  return fTreeIndex->GetEntryNumberWithBestIndex(major, minor);
5732 }
5733 
5734 ////////////////////////////////////////////////////////////////////////////////
5735 /// Return entry number corresponding to major and minor number.
5736 /// Note that this function returns only the entry number, not the data
5737 /// To read the data corresponding to an entry number, use TTree::GetEntryWithIndex
5738 /// the BuildIndex function has created a table of Long64_t* of sorted values
5739 /// corresponding to val = major<<31 + minor;
5740 /// The function performs binary search in this sorted table.
5741 /// If it finds a pair that matches val, it returns directly the
5742 /// index in the table, otherwise it returns -1.
5743 ///
5744 /// See also GetEntryNumberWithBestIndex
5745 
5746 Long64_t TTree::GetEntryNumberWithIndex(Long64_t major, Long64_t minor) const
5747 {
5748  if (!fTreeIndex) {
5749  return -1;
5750  }
5751  return fTreeIndex->GetEntryNumberWithIndex(major, minor);
5752 }
5753 
5754 ////////////////////////////////////////////////////////////////////////////////
5755 /// Read entry corresponding to major and minor number.
5756 ///
5757 /// The function returns the total number of bytes read.
5758 /// If the Tree has friend trees, the corresponding entry with
5759 /// the index values (major,minor) is read. Note that the master Tree
5760 /// and its friend may have different entry serial numbers corresponding
5761 /// to (major,minor).
5762 
5763 Int_t TTree::GetEntryWithIndex(Int_t major, Int_t minor)
5764 {
5765  // We already have been visited while recursively looking
5766  // through the friends tree, let's return.
5767  if (kGetEntryWithIndex & fFriendLockStatus) {
5768  return 0;
5769  }
5770  Long64_t serial = GetEntryNumberWithIndex(major, minor);
5771  if (serial < 0) {
5772  return -1;
5773  }
5774  // create cache if wanted
5775  if (fCacheDoAutoInit)
5776  SetCacheSizeAux();
5777 
5778  Int_t i;
5779  Int_t nbytes = 0;
5780  fReadEntry = serial;
5781  TBranch *branch;
5782  Int_t nbranches = fBranches.GetEntriesFast();
5783  Int_t nb;
5784  for (i = 0; i < nbranches; ++i) {
5785  branch = (TBranch*)fBranches.UncheckedAt(i);
5786  nb = branch->GetEntry(serial);
5787  if (nb < 0) return nb;
5788  nbytes += nb;
5789  }
5790  // GetEntry in list of friends
5791  if (!fFriends) return nbytes;
5792  TFriendLock lock(this,kGetEntryWithIndex);
5793  TIter nextf(fFriends);
5794  TFriendElement* fe = 0;
5795  while ((fe = (TFriendElement*) nextf())) {
5796  TTree *t = fe->GetTree();
5797  if (t) {
5798  serial = t->GetEntryNumberWithIndex(major,minor);
5799  if (serial <0) return -nbytes;
5800  nb = t->GetEntry(serial);
5801  if (nb < 0) return nb;
5802  nbytes += nb;
5803  }
5804  }
5805  return nbytes;
5806 }
5807 
5808 ////////////////////////////////////////////////////////////////////////////////
5809 /// Return a pointer to the TTree friend whose name or alias is 'friendname.
5810 
5811 TTree* TTree::GetFriend(const char *friendname) const
5812 {
5813 
5814  // We already have been visited while recursively
5815  // looking through the friends tree, let's return.
5816  if (kGetFriend & fFriendLockStatus) {
5817  return 0;
5818  }
5819  if (!fFriends) {
5820  return 0;
5821  }
5822  TFriendLock lock(const_cast<TTree*>(this), kGetFriend);
5823  TIter nextf(fFriends);
5824  TFriendElement* fe = 0;
5825  while ((fe = (TFriendElement*) nextf())) {
5826  if (strcmp(friendname,fe->GetName())==0
5827  || strcmp(friendname,fe->GetTreeName())==0) {
5828  return fe->GetTree();
5829  }
5830  }
5831  // After looking at the first level,
5832  // let's see if it is a friend of friends.
5833  nextf.Reset();
5834  fe = 0;
5835  while ((fe = (TFriendElement*) nextf())) {
5836  TTree *res = fe->GetTree()->GetFriend(friendname);
5837  if (res) {
5838  return res;
5839  }
5840  }
5841  return 0;
5842 }
5843 
5844 ////////////////////////////////////////////////////////////////////////////////
5845 /// If the 'tree' is a friend, this method returns its alias name.
5846 ///
5847 /// This alias is an alternate name for the tree.
5848 ///
5849 /// It can be used in conjunction with a branch or leaf name in a TTreeFormula,
5850 /// to specify in which particular tree the branch or leaf can be found if
5851 /// the friend trees have branches or leaves with the same name as the master
5852 /// tree.
5853 ///
5854 /// It can also be used in conjunction with an alias created using
5855 /// TTree::SetAlias in a TTreeFormula, e.g.:
5856 /// ~~~ {.cpp}
5857 /// maintree->Draw("treealias.fPx - treealias.myAlias");
5858 /// ~~~
5859 /// where fPx is a branch of the friend tree aliased as 'treealias' and 'myAlias'
5860 /// was created using TTree::SetAlias on the friend tree.
5861 ///
5862 /// However, note that 'treealias.myAlias' will be expanded literally,
5863 /// without remembering that it comes from the aliased friend and thus
5864 /// the branch name might not be disambiguated properly, which means
5865 /// that you may not be able to take advantage of this feature.
5866 ///
5867 
5868 const char* TTree::GetFriendAlias(TTree* tree) const
5869 {
5870  if ((tree == this) || (tree == GetTree())) {
5871  return 0;
5872  }
5873 
5874  // We already have been visited while recursively
5875  // looking through the friends tree, let's return.
5876  if (kGetFriendAlias & fFriendLockStatus) {
5877  return 0;
5878  }
5879  if (!fFriends) {
5880  return 0;
5881  }
5882  TFriendLock lock(const_cast<TTree*>(this), kGetFriendAlias);
5883  TIter nextf(fFriends);
5884  TFriendElement* fe = 0;
5885  while ((fe = (TFriendElement*) nextf())) {
5886  TTree* t = fe->GetTree();
5887  if (t == tree) {
5888  return fe->GetName();
5889  }
5890  // Case of a chain:
5891  if (t && t->GetTree() == tree) {
5892  return fe->GetName();
5893  }
5894  }
5895  // After looking at the first level,
5896  // let's see if it is a friend of friends.
5897  nextf.Reset();
5898  fe = 0;
5899  while ((fe = (TFriendElement*) nextf())) {
5900  const char* res = fe->GetTree()->GetFriendAlias(tree);
5901  if (res) {
5902  return res;
5903  }
5904  }
5905  return 0;
5906 }
5907 
5908 ////////////////////////////////////////////////////////////////////////////////
5909 /// Returns the current set of IO settings
5910 ROOT::TIOFeatures TTree::GetIOFeatures() const
5911 {
5912  return fIOFeatures;
5913 }
5914 
5915 ////////////////////////////////////////////////////////////////////////////////
5916 /// Creates a new iterator that will go through all the leaves on the tree itself and its friend.
5917 
5918 TIterator* TTree::GetIteratorOnAllLeaves(Bool_t dir)
5919 {
5920  return new TTreeFriendLeafIter(this, dir);
5921 }
5922 
5923 ////////////////////////////////////////////////////////////////////////////////
5924 /// Return pointer to the 1st Leaf named name in any Branch of this
5925 /// Tree or any branch in the list of friend trees.
5926 ///
5927 /// The leaf name can contain the name of a friend tree with the
5928 /// syntax: friend_dir_and_tree.full_leaf_name
5929 /// the friend_dir_and_tree can be of the form:
5930 /// ~~~ {.cpp}
5931 /// TDirectoryName/TreeName
5932 /// ~~~
5933 
5934 TLeaf* TTree::GetLeafImpl(const char* branchname, const char *leafname)
5935 {
5936  TLeaf *leaf = 0;
5937  if (branchname) {
5938  TBranch *branch = FindBranch(branchname);
5939  if (branch) {
5940  leaf = branch->GetLeaf(leafname);
5941  if (leaf) {
5942  return leaf;
5943  }
5944  }
5945  }
5946  TIter nextl(GetListOfLeaves());
5947  while ((leaf = (TLeaf*)nextl())) {
5948  if (strcmp(leaf->GetName(),leafname)) continue;
5949  if (branchname) {
5950  UInt_t nbch = strlen(branchname);
5951  TBranch *br = leaf->GetBranch();
5952  const char* brname = br->GetName();
5953  TBranch *mother = br->GetMother();
5954  if (strncmp(brname,branchname,nbch)) {
5955  if (mother != br) {
5956  const char *mothername = mother->GetName();
5957  UInt_t motherlen = strlen(mothername);
5958  if (nbch > motherlen && strncmp(mothername,branchname,motherlen)==0 && (mothername[motherlen-1]=='.' || branchname[motherlen]=='.')) {
5959  // 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.
5960  if (strncmp(brname,branchname+motherlen+1,nbch-motherlen-1)) {
5961  // No it does not
5962  continue;
5963  } // else we have match so we can proceed.
5964  } else {
5965  // no match
5966  continue;
5967  }
5968  } else {
5969  continue;
5970  }
5971  }
5972  // The start of the branch name is identical to the content
5973  // of 'aname' before the first '/'.
5974  // Let's make sure that it is not longer (we are trying
5975  // to avoid having jet2/value match the branch jet23
5976  if ((strlen(brname) > nbch) && (brname[nbch] != '.') && (brname[nbch] != '[')) {
5977  continue;
5978  }
5979  }
5980  return leaf;
5981  }
5982  if (!fFriends) return 0;
5983  TFriendLock lock(this,kGetLeaf);
5984  TIter next(fFriends);
5985  TFriendElement *fe;
5986  while ((fe = (TFriendElement*)next())) {
5987  TTree *t = fe->GetTree();
5988  if (t) {
5989  leaf = t->GetLeaf(leafname);
5990  if (leaf) return leaf;
5991  }
5992  }
5993 
5994  //second pass in the list of friends when the leaf name
5995  //is prefixed by the tree name
5996  TString strippedArg;
5997  next.Reset();
5998  while ((fe = (TFriendElement*)next())) {
5999  TTree *t = fe->GetTree();
6000  if (t==0) continue;
6001  char *subname = (char*)strstr(leafname,fe->GetName());
6002  if (subname != leafname) continue;
6003  Int_t l = strlen(fe->GetName());
6004  subname += l;
6005  if (*subname != '.') continue;
6006  subname++;
6007  strippedArg += subname;
6008  leaf = t->GetLeaf(branchname,subname);
6009  if (leaf) return leaf;
6010  }
6011  return 0;
6012 }
6013 
6014 ////////////////////////////////////////////////////////////////////////////////
6015 /// Return pointer to the 1st Leaf named name in any Branch of this
6016 /// Tree or any branch in the list of friend trees.
6017 ///
6018 /// The leaf name can contain the name of a friend tree with the
6019 /// syntax: friend_dir_and_tree.full_leaf_name
6020 /// the friend_dir_and_tree can be of the form:
6021 ///
6022 /// TDirectoryName/TreeName
6023 
6024 TLeaf* TTree::GetLeaf(const char* branchname, const char *leafname)
6025 {
6026  if (leafname == 0) return 0;
6027 
6028  // We already have been visited while recursively looking
6029  // through the friends tree, let return
6030  if (kGetLeaf & fFriendLockStatus) {
6031  return 0;
6032  }
6033 
6034  return GetLeafImpl(branchname,leafname);
6035 }
6036 
6037 ////////////////////////////////////////////////////////////////////////////////
6038 /// Return pointer to first leaf named \param[name] in any branch of this
6039 /// tree or its friend trees.
6040 ///
6041 /// \param[name] may be in the form 'branch/leaf'
6042 ///
6043 
6044 TLeaf* TTree::GetLeaf(const char *name)
6045 {
6046  // Return nullptr if name is invalid or if we have
6047  // already been visited while searching friend trees
6048  if (!name || (kGetLeaf & fFriendLockStatus))
6049  return nullptr;
6050 
6051  std::string path(name);
6052  const auto sep = path.find_last_of("/");
6053  if (sep != std::string::npos)
6054  return GetLeafImpl(path.substr(0, sep).c_str(), name+sep+1);
6055 
6056  return GetLeafImpl(nullptr, name);
6057 }
6058 
6059 ////////////////////////////////////////////////////////////////////////////////
6060 /// Return maximum of column with name columname.
6061 /// if the Tree has an associated TEventList or TEntryList, the maximum
6062 /// is computed for the entries in this list.
6063 
6064 Double_t TTree::GetMaximum(const char* columname)
6065 {
6066  TLeaf* leaf = this->GetLeaf(columname);
6067  if (!leaf) {
6068  return 0;
6069  }
6070 
6071  // create cache if wanted
6072  if (fCacheDoAutoInit)
6073  SetCacheSizeAux();
6074 
6075  TBranch* branch = leaf->GetBranch();
6076  Double_t cmax = -DBL_MAX;
6077  for (Long64_t i = 0; i < fEntries; ++i) {
6078  Long64_t entryNumber = this->GetEntryNumber(i);
6079  if (entryNumber < 0) break;
6080  branch->GetEntry(entryNumber);
6081  for (Int_t j = 0; j < leaf->GetLen(); ++j) {
6082  Double_t val = leaf->GetValue(j);
6083  if (val > cmax) {
6084  cmax = val;
6085  }
6086  }
6087  }
6088  return cmax;
6089 }
6090 
6091 ////////////////////////////////////////////////////////////////////////////////
6092 /// Static function which returns the tree file size limit in bytes.
6093 
6094 Long64_t TTree::GetMaxTreeSize()
6095 {
6096  return fgMaxTreeSize;
6097 }
6098 
6099 ////////////////////////////////////////////////////////////////////////////////
6100 /// Return minimum of column with name columname.
6101 /// if the Tree has an associated TEventList or TEntryList, the minimum
6102 /// is computed for the entries in this list.
6103 
6104 Double_t TTree::GetMinimum(const char* columname)
6105 {
6106  TLeaf* leaf = this->GetLeaf(columname);
6107  if (!leaf) {
6108  return 0;
6109  }
6110 
6111  // create cache if wanted
6112  if (fCacheDoAutoInit)
6113  SetCacheSizeAux();
6114 
6115  TBranch* branch = leaf->GetBranch();
6116  Double_t cmin = DBL_MAX;
6117  for (Long64_t i = 0; i < fEntries; ++i) {
6118  Long64_t entryNumber = this->GetEntryNumber(i);
6119  if (entryNumber < 0) break;
6120  branch->GetEntry(entryNumber);
6121  for (Int_t j = 0;j < leaf->GetLen(); ++j) {
6122  Double_t val = leaf->GetValue(j);
6123  if (val < cmin) {
6124  cmin = val;
6125  }
6126  }
6127  }
6128  return cmin;
6129 }
6130 
6131 ////////////////////////////////////////////////////////////////////////////////
6132 /// Load the TTreePlayer (if not already done).
6133 
6134 TVirtualTreePlayer* TTree::GetPlayer()
6135 {
6136  if (fPlayer) {
6137  return fPlayer;
6138  }
6139  fPlayer = TVirtualTreePlayer::TreePlayer(this);
6140  return fPlayer;
6141 }
6142 
6143 ////////////////////////////////////////////////////////////////////////////////
6144 /// Find and return the TTreeCache registered with the file and which may
6145 /// contain branches for us.
6146 
6147 TTreeCache *TTree::GetReadCache(TFile *file) const
6148 {
6149  TTreeCache *pe = dynamic_cast<TTreeCache*>(file->GetCacheRead(this));
6150  if (pe && pe->GetTree() != this)
6151  pe = nullptr;
6152  return pe;
6153 }
6154 
6155 ////////////////////////////////////////////////////////////////////////////////
6156 /// Find and return the TTreeCache registered with the file and which may
6157 /// contain branches for us. If create is true and there is no cache
6158 /// a new cache is created with default size.
6159 
6160 TTreeCache *TTree::GetReadCache(TFile *file, Bool_t create)
6161 {
6162  TTreeCache *pe = GetReadCache(file);
6163  if (create && !pe) {
6164  if (fCacheDoAutoInit)
6165  SetCacheSizeAux(kTRUE, -1);
6166  pe = dynamic_cast<TTreeCache*>(file->GetCacheRead(this));
6167  if (pe && pe->GetTree() != this) pe = 0;
6168  }
6169  return pe;
6170 }
6171 
6172 ////////////////////////////////////////////////////////////////////////////////
6173 /// Return a pointer to the list containing user objects associated to this tree.
6174 ///
6175 /// The list is automatically created if it does not exist.
6176 ///
6177 /// WARNING: By default the TTree destructor will delete all objects added
6178 /// to this list. If you do not want these objects to be deleted,
6179 /// call:
6180 ///
6181 /// mytree->GetUserInfo()->Clear();
6182 ///
6183 /// before deleting the tree.
6184 
6185 TList* TTree::GetUserInfo()
6186 {
6187  if (!fUserInfo) {
6188  fUserInfo = new TList();
6189  fUserInfo->SetName("UserInfo");
6190  }
6191  return fUserInfo;
6192 }
6193 
6194 ////////////////////////////////////////////////////////////////////////////////
6195 /// Appends the cluster range information stored in 'fromtree' to this tree,
6196 /// including the value of fAutoFlush.
6197 ///
6198 /// This is used when doing a fast cloning (by TTreeCloner).
6199 /// See also fAutoFlush and fAutoSave if needed.
6200 
6201 void TTree::ImportClusterRanges(TTree *fromtree)
6202 {
6203  Long64_t autoflush = fromtree->GetAutoFlush();
6204  if (fromtree->fNClusterRange == 0 && fromtree->fAutoFlush == fAutoFlush) {
6205  // nothing to do
6206  } else if (fNClusterRange || fromtree->fNClusterRange) {
6207  Int_t newsize = fNClusterRange + 1 + fromtree->fNClusterRange;
6208  if (newsize > fMaxClusterRange) {
6209  if (fMaxClusterRange) {
6210  fClusterRangeEnd = (Long64_t*)TStorage::ReAlloc(fClusterRangeEnd,
6211  newsize*sizeof(Long64_t),fMaxClusterRange*sizeof(Long64_t));
6212  fClusterSize = (Long64_t*)TStorage::ReAlloc(fClusterSize,
6213  newsize*sizeof(Long64_t),fMaxClusterRange*sizeof(Long64_t));
6214  fMaxClusterRange = newsize;
6215  } else {
6216  fMaxClusterRange = newsize;
6217  fClusterRangeEnd = new Long64_t[fMaxClusterRange];
6218  fClusterSize = new Long64_t[fMaxClusterRange];
6219  }
6220  }
6221  if (fEntries) {
6222  fClusterRangeEnd[fNClusterRange] = fEntries - 1;
6223  fClusterSize[fNClusterRange] = fAutoFlush<0 ? 0 : fAutoFlush;
6224  ++fNClusterRange;
6225  }
6226  for (Int_t i = 0 ; i < fromtree->fNClusterRange; ++i) {
6227  fClusterRangeEnd[fNClusterRange] = fEntries + fromtree->fClusterRangeEnd[i];
6228  fClusterSize[fNClusterRange] = fromtree->fClusterSize[i];
6229  ++fNClusterRange;
6230  }
6231  fAutoFlush = autoflush;
6232  } else {
6233  SetAutoFlush( autoflush );
6234  }
6235  Long64_t autosave = GetAutoSave();
6236  if (autoflush > 0 && autosave > 0) {
6237  SetAutoSave( autoflush*(autosave/autoflush) );
6238  }
6239 }
6240 
6241 ////////////////////////////////////////////////////////////////////////////////
6242 /// Keep a maximum of fMaxEntries in memory.
6243 
6244 void TTree::KeepCircular()
6245 {
6246  Int_t nb = fBranches.GetEntriesFast();
6247  Long64_t maxEntries = fMaxEntries - (fMaxEntries / 10);
6248  for (Int_t i = 0; i < nb; ++i) {
6249  TBranch* branch = (TBranch*) fBranches.UncheckedAt(i);
6250  branch->KeepCircular(maxEntries);
6251  }
6252  if (fNClusterRange) {
6253  Long64_t entriesOffset = fEntries - maxEntries;
6254  Int_t oldsize = fNClusterRange;
6255  for(Int_t i = 0, j = 0; j < oldsize; ++j) {
6256  if (fClusterRangeEnd[j] > entriesOffset) {
6257  fClusterRangeEnd[i] = fClusterRangeEnd[j] - entriesOffset;
6258  ++i;
6259  } else {
6260  --fNClusterRange;
6261  }
6262  }
6263  }
6264  fEntries = maxEntries;
6265  fReadEntry = -1;
6266 }
6267 
6268 ////////////////////////////////////////////////////////////////////////////////
6269 /// Read in memory all baskets from all branches up to the limit of maxmemory bytes.
6270 ///
6271 /// If maxmemory is non null and positive SetMaxVirtualSize is called
6272 /// with this value. Default for maxmemory is 2000000000 (2 Gigabytes).
6273 /// The function returns the total number of baskets read into memory
6274 /// if negative an error occurred while loading the branches.
6275 /// This method may be called to force branch baskets in memory
6276 /// when random access to branch entries is required.
6277 /// If random access to only a few branches is required, you should
6278 /// call directly TBranch::LoadBaskets.
6279 
6280 Int_t TTree::LoadBaskets(Long64_t maxmemory)
6281 {
6282  if (maxmemory > 0) SetMaxVirtualSize(maxmemory);
6283 
6284  TIter next(GetListOfLeaves());
6285  TLeaf *leaf;
6286  Int_t nimported = 0;
6287  while ((leaf=(TLeaf*)next())) {
6288  nimported += leaf->GetBranch()->LoadBaskets();//break;
6289  }
6290  return nimported;
6291 }
6292 
6293 ////////////////////////////////////////////////////////////////////////////////
6294 /// Set current entry.
6295 ///
6296 /// Returns -2 if entry does not exist (just as TChain::LoadTree()).
6297 /// Returns -6 if an error occours in the notification callback (just as TChain::LoadTree()).
6298 ///
6299 /// Note: This function is overloaded in TChain.
6300 ///
6301 
6302 Long64_t TTree::LoadTree(Long64_t entry)
6303 {
6304  // We already have been visited while recursively looking
6305  // through the friends tree, let return
6306  if (kLoadTree & fFriendLockStatus) {
6307  // We need to return a negative value to avoid a circular list of friend
6308  // to think that there is always an entry somewhere in the list.
6309  return -1;
6310  }
6311 
6312  // create cache if wanted
6313  if (fCacheDoAutoInit && entry >=0)
6314  SetCacheSizeAux();
6315 
6316  if (fNotify) {
6317  if (fReadEntry < 0) {
6318  fNotify->Notify();
6319  }
6320  }
6321  fReadEntry = entry;
6322 
6323  Bool_t friendHasEntry = kFALSE;
6324  if (fFriends) {
6325  // Set current entry in friends as well.
6326  //
6327  // An alternative would move this code to each of the
6328  // functions calling LoadTree (and to overload a few more).
6329  Bool_t needUpdate = kFALSE;
6330  {
6331  // This scope is need to insure the lock is released at the right time
6332  TIter nextf(fFriends);
6333  TFriendLock lock(this, kLoadTree);
6334  TFriendElement* fe = 0;
6335  while ((fe = (TFriendElement*) nextf())) {
6336  if (fe->TestBit(TFriendElement::kFromChain)) {
6337  // This friend element was added by the chain that owns this
6338  // tree, the chain will deal with loading the correct entry.
6339  continue;
6340  }
6341  TTree* friendTree = fe->GetTree();
6342  if (friendTree == 0) {
6343  // Somehow we failed to retrieve the friend TTree.
6344  } else if (friendTree->IsA() == TTree::Class()) {
6345  // Friend is actually a tree.
6346  if (friendTree->LoadTreeFriend(entry, this) >= 0) {
6347  friendHasEntry = kTRUE;
6348  }
6349  } else {
6350  // Friend is actually a chain.
6351  // FIXME: This logic should be in the TChain override.
6352  Int_t oldNumber = friendTree->GetTreeNumber();
6353  if (friendTree->LoadTreeFriend(entry, this) >= 0) {
6354  friendHasEntry = kTRUE;
6355  }
6356  Int_t newNumber = friendTree->GetTreeNumber();
6357  if (oldNumber != newNumber) {
6358  // We can not just compare the tree pointers because they could be reused.
6359  // So we compare the tree number instead.
6360  needUpdate = kTRUE;
6361  }
6362  }
6363  } // for each friend
6364  }
6365  if (needUpdate) {
6366  //update list of leaves in all TTreeFormula of the TTreePlayer (if any)
6367  if (fPlayer) {
6368  fPlayer->UpdateFormulaLeaves();
6369  }
6370  //Notify user if requested
6371  if (fNotify) {
6372  if(!fNotify->Notify()) return -6;
6373  }
6374  }
6375  }
6376 
6377  if ((fReadEntry >= fEntries) && !friendHasEntry) {
6378  fReadEntry = -1;
6379  return -2;
6380  }
6381  return fReadEntry;
6382 }
6383 
6384 ////////////////////////////////////////////////////////////////////////////////
6385 /// Load entry on behalf of our master tree, we may use an index.
6386 ///
6387 /// Called by LoadTree() when the masterTree looks for the entry
6388 /// number in a friend tree (us) corresponding to the passed entry
6389 /// number in the masterTree.
6390 ///
6391 /// If we have no index, our entry number and the masterTree entry
6392 /// number are the same.
6393 ///
6394 /// If we *do* have an index, we must find the (major, minor) value pair
6395 /// in masterTree to locate our corresponding entry.
6396 ///
6397 
6398 Long64_t TTree::LoadTreeFriend(Long64_t entry, TTree* masterTree)
6399 {
6400  if (!fTreeIndex) {
6401  return LoadTree(entry);
6402  }
6403  return LoadTree(fTreeIndex->GetEntryNumberFriend(masterTree));
6404 }
6405 
6406 ////////////////////////////////////////////////////////////////////////////////
6407 /// Generate a skeleton analysis class for this tree.
6408 ///
6409 /// The following files are produced: classname.h and classname.C.
6410 /// If classname is 0, classname will be called "nameoftree".
6411 ///
6412 /// The generated code in classname.h includes the following:
6413 ///
6414 /// - Identification of the original tree and the input file name.
6415 /// - Definition of an analysis class (data members and member functions).
6416 /// - The following member functions:
6417 /// - constructor (by default opening the tree file),
6418 /// - GetEntry(Long64_t entry),
6419 /// - Init(TTree* tree) to initialize a new TTree,
6420 /// - Show(Long64_t entry) to read and dump entry.
6421 ///
6422 /// The generated code in classname.C includes only the main
6423 /// analysis function Loop.
6424 ///
6425 /// To use this function:
6426 ///
6427 /// - Open your tree file (eg: TFile f("myfile.root");)
6428 /// - T->MakeClass("MyClass");
6429 ///
6430 /// where T is the name of the TTree in file myfile.root,
6431 /// and MyClass.h, MyClass.C the name of the files created by this function.
6432 /// In a ROOT session, you can do:
6433 /// ~~~ {.cpp}
6434 /// root > .L MyClass.C
6435 /// root > MyClass* t = new MyClass;
6436 /// root > t->GetEntry(12); // Fill data members of t with entry number 12.
6437 /// root > t->Show(); // Show values of entry 12.
6438 /// root > t->Show(16); // Read and show values of entry 16.
6439 /// root > t->Loop(); // Loop on all entries.
6440 /// ~~~
6441 /// NOTE: Do not use the code generated for a single TTree which is part
6442 /// of a TChain to process that entire TChain. The maximum dimensions
6443 /// calculated for arrays on the basis of a single TTree from the TChain
6444 /// might be (will be!) too small when processing all of the TTrees in
6445 /// the TChain. You must use myChain.MakeClass() to generate the code,
6446 /// not myTree.MakeClass(...).
6447 
6448 Int_t TTree::MakeClass(const char* classname, Option_t* option)
6449 {
6450  GetPlayer();
6451  if (!fPlayer) {
6452  return 0;
6453  }
6454  return fPlayer->MakeClass(classname, option);
6455 }
6456 
6457 ////////////////////////////////////////////////////////////////////////////////
6458 /// Generate a skeleton function for this tree.
6459 ///
6460 /// The function code is written on filename.
6461 /// If filename is 0, filename will be called nameoftree.C
6462 ///
6463 /// The generated code includes the following:
6464 /// - Identification of the original Tree and Input file name,
6465 /// - Opening the Tree file,
6466 /// - Declaration of Tree variables,
6467 /// - Setting of branches addresses,
6468 /// - A skeleton for the entry loop.
6469 ///
6470 /// To use this function:
6471 ///
6472 /// - Open your Tree file (eg: TFile f("myfile.root");)
6473 /// - T->MakeCode("MyAnalysis.C");
6474 ///
6475 /// where T is the name of the TTree in file myfile.root
6476 /// and MyAnalysis.C the name of the file created by this function.
6477 ///
6478 /// NOTE: Since the implementation of this function, a new and better
6479 /// function TTree::MakeClass() has been developed.
6480 
6481 Int_t TTree::MakeCode(const char* filename)
6482 {
6483  Warning("MakeCode", "MakeCode is obsolete. Use MakeClass or MakeSelector instead");
6484 
6485  GetPlayer();
6486  if (!fPlayer) return 0;
6487  return fPlayer->MakeCode(filename);
6488 }
6489 
6490 ////////////////////////////////////////////////////////////////////////////////
6491 /// Generate a skeleton analysis class for this Tree using TBranchProxy.
6492 ///
6493 /// TBranchProxy is the base of a class hierarchy implementing an
6494 /// indirect access to the content of the branches of a TTree.
6495 ///
6496 /// "proxyClassname" is expected to be of the form:
6497 /// ~~~ {.cpp}
6498 /// [path/]fileprefix
6499 /// ~~~
6500 /// The skeleton will then be generated in the file:
6501 /// ~~~ {.cpp}
6502 /// fileprefix.h
6503 /// ~~~
6504 /// located in the current directory or in 'path/' if it is specified.
6505 /// The class generated will be named 'fileprefix'
6506 ///
6507 /// "macrofilename" and optionally "cutfilename" are expected to point
6508 /// to source files which will be included by the generated skeleton.
6509 /// Method of the same name as the file(minus the extension and path)
6510 /// will be called by the generated skeleton's Process method as follow:
6511 /// ~~~ {.cpp}
6512 /// [if (cutfilename())] htemp->Fill(macrofilename());
6513 /// ~~~
6514 /// "option" can be used select some of the optional features during
6515 /// the code generation. The possible options are:
6516 ///
6517 /// - nohist : indicates that the generated ProcessFill should not fill the histogram.
6518 ///
6519 /// 'maxUnrolling' controls how deep in the class hierarchy does the
6520 /// system 'unroll' classes that are not split. Unrolling a class
6521 /// allows direct access to its data members (this emulates the behavior
6522 /// of TTreeFormula).
6523 ///
6524 /// The main features of this skeleton are:
6525 ///
6526 /// * on-demand loading of branches
6527 /// * ability to use the 'branchname' as if it was a data member
6528 /// * protection against array out-of-bounds errors
6529 /// * ability to use the branch data as an object (when the user code is available)
6530 ///
6531 /// For example with Event.root, if
6532 /// ~~~ {.cpp}
6533 /// Double_t somePx = fTracks.fPx[2];
6534 /// ~~~
6535 /// is executed by one of the method of the skeleton,
6536 /// somePx will updated with the current value of fPx of the 3rd track.
6537 ///
6538 /// Both macrofilename and the optional cutfilename are expected to be
6539 /// the name of source files which contain at least a free standing
6540 /// function with the signature:
6541 /// ~~~ {.cpp}
6542 /// x_t macrofilename(); // i.e function with the same name as the file
6543 /// ~~~
6544 /// and
6545 /// ~~~ {.cpp}
6546 /// y_t cutfilename(); // i.e function with the same name as the file
6547 /// ~~~
6548 /// x_t and y_t needs to be types that can convert respectively to a double
6549 /// and a bool (because the skeleton uses:
6550 ///
6551 /// if (cutfilename()) htemp->Fill(macrofilename());
6552 ///
6553 /// These two functions are run in a context such that the branch names are
6554 /// available as local variables of the correct (read-only) type.
6555 ///
6556 /// Note that if you use the same 'variable' twice, it is more efficient
6557 /// to 'cache' the value. For example:
6558 /// ~~~ {.cpp}
6559 /// Int_t n = fEventNumber; // Read fEventNumber
6560 /// if (n<10 || n>10) { ... }
6561 /// ~~~
6562 /// is more efficient than
6563 /// ~~~ {.cpp}
6564 /// if (fEventNumber<10 || fEventNumber>10)
6565 /// ~~~
6566 /// Also, optionally, the generated selector will also call methods named
6567 /// macrofilename_methodname in each of 6 main selector methods if the method
6568 /// macrofilename_methodname exist (Where macrofilename is stripped of its
6569 /// extension).
6570 ///
6571 /// Concretely, with the script named h1analysisProxy.C,
6572 ///
6573 /// - The method calls the method (if it exist)
6574 /// - Begin -> void h1analysisProxy_Begin(TTree*);
6575 /// - SlaveBegin -> void h1analysisProxy_SlaveBegin(TTree*);
6576 /// - Notify -> Bool_t h1analysisProxy_Notify();
6577 /// - Process -> Bool_t h1analysisProxy_Process(Long64_t);
6578 /// - SlaveTerminate -> void h1analysisProxy_SlaveTerminate();
6579 /// - Terminate -> void h1analysisProxy_Terminate();
6580 ///
6581 /// If a file name macrofilename.h (or .hh, .hpp, .hxx, .hPP, .hXX) exist
6582 /// it is included before the declaration of the proxy class. This can
6583 /// be used in particular to insure that the include files needed by
6584 /// the macro file are properly loaded.
6585 ///
6586 /// The default histogram is accessible via the variable named 'htemp'.
6587 ///
6588 /// If the library of the classes describing the data in the branch is
6589 /// loaded, the skeleton will add the needed `include` statements and
6590 /// give the ability to access the object stored in the branches.
6591 ///
6592 /// To draw px using the file hsimple.root (generated by the
6593 /// hsimple.C tutorial), we need a file named hsimple.cxx:
6594 /// ~~~ {.cpp}
6595 /// double hsimple() {
6596 /// return px;
6597 /// }
6598 /// ~~~
6599 /// MakeProxy can then be used indirectly via the TTree::Draw interface
6600 /// as follow:
6601 /// ~~~ {.cpp}
6602 /// new TFile("hsimple.root")
6603 /// ntuple->Draw("hsimple.cxx");
6604 /// ~~~
6605 /// A more complete example is available in the tutorials directory:
6606 /// h1analysisProxy.cxx , h1analysProxy.h and h1analysisProxyCut.C
6607 /// which reimplement the selector found in h1analysis.C
6608 
6609 Int_t TTree::MakeProxy(const char* proxyClassname, const char* macrofilename, const char* cutfilename, const char* option, Int_t maxUnrolling)
6610 {
6611  GetPlayer();
6612  if (!fPlayer) return 0;
6613  return fPlayer->MakeProxy(proxyClassname,macrofilename,cutfilename,option,maxUnrolling);
6614 }
6615 
6616 ////////////////////////////////////////////////////////////////////////////////
6617 /// Generate skeleton selector class for this tree.
6618 ///
6619 /// The following files are produced: selector.h and selector.C.
6620 /// If selector is 0, the selector will be called "nameoftree".
6621 /// The option can be used to specify the branches that will have a data member.
6622 /// - If option is "=legacy", a pre-ROOT6 selector will be generated (data
6623 /// members and branch pointers instead of TTreeReaders).
6624 /// - If option is empty, readers will be generated for each leaf.
6625 /// - If option is "@", readers will be generated for the topmost branches.
6626 /// - Individual branches can also be picked by their name:
6627 /// - "X" generates readers for leaves of X.
6628 /// - "@X" generates a reader for X as a whole.
6629 /// - "@X;Y" generates a reader for X as a whole and also readers for the
6630 /// leaves of Y.
6631 /// - For further examples see the figure below.
6632 ///
6633 /// \image html ttree_makeselector_option_examples.png
6634 ///
6635 /// The generated code in selector.h includes the following:
6636 /// - Identification of the original Tree and Input file name
6637 /// - Definition of selector class (data and functions)
6638 /// - The following class functions:
6639 /// - constructor and destructor
6640 /// - void Begin(TTree *tree)
6641 /// - void SlaveBegin(TTree *tree)
6642 /// - void Init(TTree *tree)
6643 /// - Bool_t Notify()
6644 /// - Bool_t Process(Long64_t entry)
6645 /// - void Terminate()
6646 /// - void SlaveTerminate()
6647 ///
6648 /// The class selector derives from TSelector.
6649 /// The generated code in selector.C includes empty functions defined above.
6650 ///
6651 /// To use this function:
6652 ///
6653 /// - connect your Tree file (eg: `TFile f("myfile.root");`)
6654 /// - `T->MakeSelector("myselect");`
6655 ///
6656 /// where T is the name of the Tree in file myfile.root
6657 /// and myselect.h, myselect.C the name of the files created by this function.
6658 /// In a ROOT session, you can do:
6659 /// ~~~ {.cpp}
6660 /// root > T->Process("myselect.C")
6661 /// ~~~
6662 
6663 Int_t TTree::MakeSelector(const char* selector, Option_t* option)
6664 {
6665  TString opt(option);
6666  if(opt.EqualTo("=legacy", TString::ECaseCompare::kIgnoreCase)) {
6667  return MakeClass(selector, "selector");
6668  } else {
6669  GetPlayer();
6670  if (!fPlayer) return 0;
6671  return fPlayer->MakeReader(selector, option);
6672  }
6673 }
6674 
6675 ////////////////////////////////////////////////////////////////////////////////
6676 /// Check if adding nbytes to memory we are still below MaxVirtualsize.
6677 
6678 Bool_t TTree::MemoryFull(Int_t nbytes)
6679 {
6680  if ((fTotalBuffers + nbytes) < fMaxVirtualSize) {
6681  return kFALSE;
6682  }
6683  return kTRUE;
6684 }
6685 
6686 ////////////////////////////////////////////////////////////////////////////////
6687 /// Static function merging the trees in the TList into a new tree.
6688 ///
6689 /// Trees in the list can be memory or disk-resident trees.
6690 /// The new tree is created in the current directory (memory if gROOT).
6691 
6692 TTree* TTree::MergeTrees(TList* li, Option_t* options)
6693 {
6694  if (!li) return 0;
6695  TIter next(li);
6696  TTree *newtree = 0;
6697  TObject *obj;
6698 
6699  while ((obj=next())) {
6700  if (!obj->InheritsFrom(TTree::Class())) continue;
6701  TTree *tree = (TTree*)obj;
6702  Long64_t nentries = tree->GetEntries();
6703  if (nentries == 0) continue;
6704  if (!newtree) {
6705  newtree = (TTree*)tree->CloneTree();
6706  if (!newtree) continue;
6707 
6708  // Once the cloning is done, separate the trees,
6709  // to avoid as many side-effects as possible
6710  // The list of clones is guaranteed to exist since we
6711  // just cloned the tree.
6712  tree->GetListOfClones()->Remove(newtree);
6713  tree->ResetBranchAddresses();
6714  newtree->ResetBranchAddresses();
6715  continue;
6716  }
6717 
6718  newtree->CopyAddresses(tree);
6719 
6720  newtree->CopyEntries(tree,-1,options);
6721 
6722  tree->ResetBranchAddresses(); // Disconnect from new tree.
6723  }
6724  if (newtree && newtree->GetTreeIndex()) {
6725  newtree->GetTreeIndex()->Append(0,kFALSE); // Force the sorting
6726  }
6727  return newtree;
6728 }
6729 
6730 ////////////////////////////////////////////////////////////////////////////////
6731 /// Merge the trees in the TList into this tree.
6732 ///
6733 /// Returns the total number of entries in the merged tree.
6734 
6735 Long64_t TTree::Merge(TCollection* li, Option_t *options)
6736 {
6737  if (!li) return 0;
6738  Long64_t storeAutoSave = fAutoSave;
6739  // Disable the autosave as the TFileMerge keeps a list of key and deleting the underlying
6740  // key would invalidate its iteration (or require costly measure to not use the deleted keys).
6741  // Also since this is part of a merging operation, the output file is not as precious as in
6742  // the general case since the input file should still be around.
6743  fAutoSave = 0;
6744  TIter next(li);
6745  TTree *tree;
6746  while ((tree = (TTree*)next())) {
6747  if (tree==this) continue;
6748  if (!tree->InheritsFrom(TTree::Class())) {
6749  Error("Add","Attempt to add object of class: %s to a %s", tree->ClassName(), ClassName());
6750  fAutoSave = storeAutoSave;
6751  return -1;
6752  }
6753 
6754  Long64_t nentries = tree->GetEntries();
6755  if (nentries == 0) continue;
6756 
6757  CopyAddresses(tree);
6758 
6759  CopyEntries(tree,-1,options);
6760 
6761  tree->ResetBranchAddresses();
6762  }
6763  fAutoSave = storeAutoSave;
6764  return GetEntries();
6765 }
6766 
6767 ////////////////////////////////////////////////////////////////////////////////
6768 /// Merge the trees in the TList into this tree.
6769 /// If info->fIsFirst is true, first we clone this TTree info the directory
6770 /// info->fOutputDirectory and then overlay the new TTree information onto
6771 /// this TTree object (so that this TTree object is now the appropriate to
6772 /// use for further merging).
6773 ///
6774 /// Returns the total number of entries in the merged tree.
6775 
6776 Long64_t TTree::Merge(TCollection* li, TFileMergeInfo *info)
6777 {
6778  const char *options = info ? info->fOptions.Data() : "";
6779  if (info && info->fIsFirst && info->fOutputDirectory && info->fOutputDirectory->GetFile() != GetCurrentFile()) {
6780  TDirectory::TContext ctxt(info->fOutputDirectory);
6781  TIOFeatures saved_features = fIOFeatures;
6782  if (info->fIOFeatures) {
6783  fIOFeatures = *(info->fIOFeatures);
6784  }
6785  TTree *newtree = CloneTree(-1, options);
6786  fIOFeatures = saved_features;
6787  if (newtree) {
6788  newtree->Write();
6789  delete newtree;
6790  }
6791  // Make sure things are really written out to disk before attempting any reading.
6792  info->fOutputDirectory->GetFile()->Flush();
6793  info->fOutputDirectory->ReadTObject(this,this->GetName());
6794  }
6795  if (!li) return 0;
6796  Long64_t storeAutoSave = fAutoSave;
6797  // Disable the autosave as the TFileMerge keeps a list of key and deleting the underlying
6798  // key would invalidate its iteration (or require costly measure to not use the deleted keys).
6799  // Also since this is part of a merging operation, the output file is not as precious as in
6800  // the general case since the input file should still be around.
6801  fAutoSave = 0;
6802  TIter next(li);
6803  TTree *tree;
6804  while ((tree = (TTree*)next())) {
6805  if (tree==this) continue;
6806  if (!tree->InheritsFrom(TTree::Class())) {
6807  Error("Add","Attempt to add object of class: %s to a %s", tree->ClassName(), ClassName());
6808  fAutoSave = storeAutoSave;
6809  return -1;
6810  }
6811  // Copy MakeClass status.
6812  tree->SetMakeClass(fMakeClass);
6813 
6814  // Copy branch addresses.
6815  CopyAddresses(tree);
6816 
6817  CopyEntries(tree,-1,options);
6818 
6819  tree->ResetBranchAddresses();
6820  }
6821  fAutoSave = storeAutoSave;
6822  return GetEntries();
6823 }
6824 
6825 ////////////////////////////////////////////////////////////////////////////////
6826 /// Move a cache from a file to the current file in dir.
6827 /// if src is null no operation is done, if dir is null or there is no
6828 /// current file the cache is deleted.
6829 
6830 void TTree::MoveReadCache(TFile *src, TDirectory *dir)
6831 {
6832  if (!src) return;
6833  TFile *dst = (dir && dir != gROOT) ? dir->GetFile() : 0;
6834  if (src == dst) return;
6835 
6836  TTreeCache *pf = GetReadCache(src);
6837  if (dst) {
6838  src->SetCacheRead(0,this);
6839  dst->SetCacheRead(pf, this);
6840  } else {
6841  if (pf) {
6842  pf->WaitFinishPrefetch();
6843  }
6844  src->SetCacheRead(0,this);
6845  delete pf;
6846  }
6847 }
6848 
6849 ////////////////////////////////////////////////////////////////////////////////
6850 /// Function called when loading a new class library.
6851 
6852 Bool_t TTree::Notify()
6853 {
6854  TIter next(GetListOfLeaves());
6855  TLeaf* leaf = 0;
6856  while ((leaf = (TLeaf*) next())) {
6857  leaf->Notify();
6858  leaf->GetBranch()->Notify();
6859  }
6860  return kTRUE;
6861 }
6862 
6863 ////////////////////////////////////////////////////////////////////////////////
6864 /// This function may be called after having filled some entries in a Tree.
6865 /// Using the information in the existing branch buffers, it will reassign
6866 /// new branch buffer sizes to optimize time and memory.
6867 ///
6868 /// The function computes the best values for branch buffer sizes such that
6869 /// the total buffer sizes is less than maxMemory and nearby entries written
6870 /// at the same time.
6871 /// In case the branch compression factor for the data written so far is less
6872 /// than compMin, the compression is disabled.
6873 ///
6874 /// if option ="d" an analysis report is printed.
6875 
6876 void TTree::OptimizeBaskets(ULong64_t maxMemory, Float_t minComp, Option_t *option)
6877 {
6878  //Flush existing baskets if the file is writable
6879  if (this->GetDirectory()->IsWritable()) this->FlushBasketsImpl();
6880 
6881  TString opt( option );
6882  opt.ToLower();
6883  Bool_t pDebug = opt.Contains("d");
6884  TObjArray *leaves = this->GetListOfLeaves();
6885  Int_t nleaves = leaves->GetEntries();
6886  Double_t treeSize = (Double_t)this->GetTotBytes();
6887 
6888  if (nleaves == 0 || treeSize == 0) {
6889  // We're being called too early, we really have nothing to do ...
6890  return;
6891  }
6892  Double_t aveSize = treeSize/nleaves;
6893  UInt_t bmin = 512;
6894  UInt_t bmax = 256000;
6895  Double_t memFactor = 1;
6896  Int_t i, oldMemsize,newMemsize,oldBaskets,newBaskets;
6897  i = oldMemsize = newMemsize = oldBaskets = newBaskets = 0;
6898 
6899  //we make two passes
6900  //one pass to compute the relative branch buffer sizes
6901  //a second pass to compute the absolute values
6902  for (Int_t pass =0;pass<2;pass++) {
6903  oldMemsize = 0; //to count size of baskets in memory with old buffer size
6904  newMemsize = 0; //to count size of baskets in memory with new buffer size
6905  oldBaskets = 0; //to count number of baskets with old buffer size
6906  newBaskets = 0; //to count number of baskets with new buffer size
6907  for (i=0;i<nleaves;i++) {
6908  TLeaf *leaf = (TLeaf*)leaves->At(i);
6909  TBranch *branch = leaf->GetBranch();
6910  Double_t totBytes = (Double_t)branch->GetTotBytes();
6911  Double_t idealFactor = totBytes/aveSize;
6912  UInt_t sizeOfOneEntry;
6913  if (branch->GetEntries() == 0) {
6914  // There is no data, so let's make a guess ...
6915  sizeOfOneEntry = aveSize;
6916  } else {
6917  sizeOfOneEntry = 1+(UInt_t)(totBytes / (Double_t)branch->GetEntries());
6918  }
6919  Int_t oldBsize = branch->GetBasketSize();
6920  oldMemsize += oldBsize;
6921  oldBaskets += 1+Int_t(totBytes/oldBsize);
6922  Int_t nb = branch->GetListOfBranches()->GetEntries();
6923  if (nb > 0) {
6924  newBaskets += 1+Int_t(totBytes/oldBsize);
6925  continue;
6926  }
6927  Double_t bsize = oldBsize*idealFactor*memFactor; //bsize can be very large !
6928  if (bsize < 0) bsize = bmax;
6929  if (bsize > bmax) bsize = bmax;
6930  UInt_t newBsize = UInt_t(bsize);
6931  if (pass) { // only on the second pass so that it doesn't interfere with scaling
6932  // If there is an entry offset, it will be stored in the same buffer as the object data; hence,
6933  // we must bump up the size of the branch to account for this extra footprint.
6934  // If fAutoFlush is not set yet, let's assume that it is 'in the process of being set' to
6935  // the value of GetEntries().
6936  Long64_t clusterSize = (fAutoFlush > 0) ? fAutoFlush : branch->GetEntries();
6937  if (branch->GetEntryOffsetLen()) {
6938  newBsize = newBsize + (clusterSize * sizeof(Int_t) * 2);
6939  }
6940  // We used ATLAS fully-split xAOD for testing, which is a rather unbalanced TTree, 10K branches,
6941  // with 8K having baskets smaller than 512 bytes. To achieve good I/O performance ATLAS uses auto-flush 100,
6942  // resulting in the smallest baskets being ~300-400 bytes, so this change increases their memory by about 8k*150B =~ 1MB,
6943  // at the same time it significantly reduces the number of total baskets because it ensures that all 100 entries can be
6944  // stored in a single basket (the old optimization tended to make baskets too small). In a toy example with fixed sized
6945  // structures we found a factor of 2 fewer baskets needed in the new scheme.
6946  // rounds up, increases basket size to ensure all entries fit into single basket as intended
6947  newBsize = newBsize - newBsize%512 + 512;
6948  }
6949  if (newBsize < sizeOfOneEntry) newBsize = sizeOfOneEntry;
6950  if (newBsize < bmin) newBsize = bmin;
6951  if (newBsize > 10000000) newBsize = bmax;
6952  if (pass) {
6953  if (pDebug) Info("OptimizeBaskets", "Changing buffer size from %6d to %6d bytes for %s\n",oldBsize,newBsize,branch->GetName());
6954  branch->SetBasketSize(newBsize);
6955  }
6956  newMemsize += newBsize;
6957  // For this number to be somewhat accurate when newBsize is 'low'
6958  // we do not include any space for meta data in the requested size (newBsize) even-though SetBasketSize will
6959  // not let it be lower than 100+TBranch::fEntryOffsetLen.
6960  newBaskets += 1+Int_t(totBytes/newBsize);
6961  if (pass == 0) continue;
6962  //Reset the compression level in case the compression factor is small
6963  Double_t comp = 1;
6964  if (branch->GetZipBytes() > 0) comp = totBytes/Double_t(branch->GetZipBytes());
6965  if (comp > 1 && comp < minComp) {
6966  if (pDebug) Info("OptimizeBaskets", "Disabling compression for branch : %s\n",branch->GetName());
6967  branch->SetCompressionSettings(ROOT::RCompressionSetting::EAlgorithm::kUseGlobal);
6968  }
6969  }
6970  // coverity[divide_by_zero] newMemsize can not be zero as there is at least one leaf
6971  memFactor = Double_t(maxMemory)/Double_t(newMemsize);
6972  if (memFactor > 100) memFactor = 100;
6973  Double_t bmin_new = bmin*memFactor;
6974  Double_t bmax_new = bmax*memFactor;
6975  static const UInt_t hardmax = 1*1024*1024*1024; // Really, really never give more than 1Gb to a single buffer.
6976 
6977  // Really, really never go lower than 8 bytes (we use this number
6978  // so that the calculation of the number of basket is consistent
6979  // but in fact SetBasketSize will not let the size go below
6980  // TBranch::fEntryOffsetLen + (100 + strlen(branch->GetName())
6981  // (The 2nd part being a slight over estimate of the key length.
6982  static const UInt_t hardmin = 8;
6983  bmin = (bmin_new > hardmax) ? hardmax : ( bmin_new < hardmin ? hardmin : (UInt_t)bmin_new );
6984  bmax = (bmax_new > hardmax) ? bmin : (UInt_t)bmax_new;
6985  }
6986  if (pDebug) {
6987  Info("OptimizeBaskets", "oldMemsize = %d, newMemsize = %d\n",oldMemsize, newMemsize);
6988  Info("OptimizeBaskets", "oldBaskets = %d, newBaskets = %d\n",oldBaskets, newBaskets);
6989  }
6990 }
6991 
6992 ////////////////////////////////////////////////////////////////////////////////
6993 /// Interface to the Principal Components Analysis class.
6994 ///
6995 /// Create an instance of TPrincipal
6996 ///
6997 /// Fill it with the selected variables
6998 ///
6999 /// - if option "n" is specified, the TPrincipal object is filled with
7000 /// normalized variables.
7001 /// - If option "p" is specified, compute the principal components
7002 /// - If option "p" and "d" print results of analysis
7003 /// - If option "p" and "h" generate standard histograms
7004 /// - If option "p" and "c" generate code of conversion functions
7005 /// - return a pointer to the TPrincipal object. It is the user responsibility
7006 /// - to delete this object.
7007 /// - The option default value is "np"
7008 ///
7009 /// see TTree::Draw for explanation of the other parameters.
7010 ///
7011 /// The created object is named "principal" and a reference to it
7012 /// is added to the list of specials Root objects.
7013 /// you can retrieve a pointer to the created object via:
7014 /// ~~~ {.cpp}
7015 /// TPrincipal *principal =
7016 /// (TPrincipal*)gROOT->GetListOfSpecials()->FindObject("principal");
7017 /// ~~~
7018 
7019 TPrincipal* TTree::Principal(const char* varexp, const char* selection, Option_t* option, Long64_t nentries, Long64_t firstentry)
7020 {
7021  GetPlayer();
7022  if (fPlayer) {
7023  return fPlayer->Principal(varexp, selection, option, nentries, firstentry);
7024  }
7025  return 0;
7026 }
7027 
7028 ////////////////////////////////////////////////////////////////////////////////
7029 /// Print a summary of the tree contents.
7030 ///
7031 /// - If option contains "all" friend trees are also printed.
7032 /// - If option contains "toponly" only the top level branches are printed.
7033 /// - If option contains "clusters" information about the cluster of baskets is printed.
7034 ///
7035 /// Wildcarding can be used to print only a subset of the branches, e.g.,
7036 /// `T.Print("Elec*")` will print all branches with name starting with "Elec".
7037 
7038 void TTree::Print(Option_t* option) const
7039 {
7040  // We already have been visited while recursively looking
7041  // through the friends tree, let's return.
7042  if (kPrint & fFriendLockStatus) {
7043  return;
7044  }
7045  Int_t s = 0;
7046  Int_t skey = 0;
7047  if (fDirectory) {
7048  TKey* key = fDirectory->GetKey(GetName());
7049  if (key) {
7050  skey = key->GetKeylen();
7051  s = key->GetNbytes();
7052  }
7053  }
7054  Long64_t total = skey;
7055  Long64_t zipBytes = GetZipBytes();
7056  if (zipBytes > 0) {
7057  total += GetTotBytes();
7058  }
7059  TBufferFile b(TBuffer::kWrite, 10000);
7060  TTree::Class()->WriteBuffer(b, (TTree*) this);
7061  total += b.Length();
7062  Long64_t file = zipBytes + s;
7063  Float_t cx = 1;
7064  if (zipBytes) {
7065  cx = (GetTotBytes() + 0.00001) / zipBytes;
7066  }
7067  Printf("******************************************************************************");
7068  Printf("*Tree :%-10s: %-54s *", GetName(), GetTitle());
7069  Printf("*Entries : %8lld : Total = %15lld bytes File Size = %10lld *", fEntries, total, file);
7070  Printf("* : : Tree compression factor = %6.2f *", cx);
7071  Printf("******************************************************************************");
7072 
7073  // Avoid many check of option validity
7074  if (option == nullptr)
7075  option = "";
7076 
7077  if (strncmp(option,"clusters",strlen("clusters"))==0) {
7078  Printf("%-16s %-16s %-16s %5s",
7079  "Cluster Range #", "Entry Start", "Last Entry", "Size");
7080  Int_t index= 0;
7081  Long64_t clusterRangeStart = 0;
7082  if (fNClusterRange) {
7083  for( ; index < fNClusterRange; ++index) {
7084  Printf("%-16d %-16lld %-16lld %5lld",
7085  index, clusterRangeStart, fClusterRangeEnd[index], fClusterSize[index]);
7086  clusterRangeStart = fClusterRangeEnd[index] + 1;
7087  }
7088  }
7089  Printf("%-16d %-16lld %-16lld %5lld",
7090  index, clusterRangeStart, fEntries - 1, fAutoFlush);
7091  return;
7092  }
7093 
7094  Int_t nl = const_cast<TTree*>(this)->GetListOfLeaves()->GetEntries();
7095  Int_t l;
7096  TBranch* br = 0;
7097  TLeaf* leaf = 0;
7098  if (strstr(option, "toponly")) {
7099  Long64_t *count = new Long64_t[nl];
7100  Int_t keep =0;
7101  for (l=0;l<nl;l++) {
7102  leaf = (TLeaf *)const_cast<TTree*>(this)->GetListOfLeaves()->At(l);
7103  br = leaf->GetBranch();
7104  if (strchr(br->GetName(),'.')) {
7105  count[l] = -1;
7106  count[keep] += br->GetZipBytes();
7107  } else {
7108  keep = l;
7109  count[keep] = br->GetZipBytes();
7110  }
7111  }
7112  for (l=0;l<nl;l++) {
7113  if (count[l] < 0) continue;
7114  leaf = (TLeaf *)const_cast<TTree*>(this)->GetListOfLeaves()->At(l);
7115  br = leaf->GetBranch();
7116  Printf("branch: %-20s %9lld\n",br->GetName(),count[l]);
7117  }
7118  delete [] count;
7119  } else {
7120  TString reg = "*";
7121  if (strlen(option) && strchr(option,'*')) reg = option;
7122  TRegexp re(reg,kTRUE);
7123  TIter next(const_cast<TTree*>(this)->GetListOfBranches());
7124  TBranch::ResetCount();
7125  while ((br= (TBranch*)next())) {
7126  TString st = br->GetName();
7127  st.ReplaceAll("/","_");
7128  if (st.Index(re) == kNPOS) continue;
7129  br->Print(option);
7130  }
7131  }
7132 
7133  //print TRefTable (if one)
7134  if (fBranchRef) fBranchRef->Print(option);
7135 
7136  //print friends if option "all"
7137  if (!fFriends || !strstr(option,"all")) return;
7138  TIter nextf(fFriends);
7139  TFriendLock lock(const_cast<TTree*>(this),kPrint);
7140  TFriendElement *fr;
7141  while ((fr = (TFriendElement*)nextf())) {
7142  TTree * t = fr->GetTree();
7143  if (t) t->Print(option);
7144  }
7145 }
7146 
7147 ////////////////////////////////////////////////////////////////////////////////
7148 /// Print statistics about the TreeCache for this tree.
7149 /// Like:
7150 /// ~~~ {.cpp}
7151 /// ******TreeCache statistics for file: cms2.root ******
7152 /// Reading 73921562 bytes in 716 transactions
7153 /// Average transaction = 103.242405 Kbytes
7154 /// Number of blocks in current cache: 202, total size : 6001193
7155 /// ~~~
7156 /// if option = "a" the list of blocks in the cache is printed
7157 
7158 void TTree::PrintCacheStats(Option_t* option) const
7159 {
7160  TFile *f = GetCurrentFile();
7161  if (!f) return;
7162  TTreeCache *tc = GetReadCache(f);
7163  if (tc) tc->Print(option);
7164 }
7165 
7166 ////////////////////////////////////////////////////////////////////////////////
7167 /// Process this tree executing the TSelector code in the specified filename.
7168 /// The return value is -1 in case of error and TSelector::GetStatus() in
7169 /// in case of success.
7170 ///
7171 /// The code in filename is loaded (interpreted or compiled, see below),
7172 /// filename must contain a valid class implementation derived from TSelector,
7173 /// where TSelector has the following member functions:
7174 ///
7175 /// - `Begin()`: called every time a loop on the tree starts,
7176 /// a convenient place to create your histograms.
7177 /// - `SlaveBegin()`: called after Begin(), when on PROOF called only on the
7178 /// slave servers.
7179 /// - `Process()`: called for each event, in this function you decide what
7180 /// to read and fill your histograms.
7181 /// - `SlaveTerminate`: called at the end of the loop on the tree, when on PROOF
7182 /// called only on the slave servers.
7183 /// - `Terminate()`: called at the end of the loop on the tree,
7184 /// a convenient place to draw/fit your histograms.
7185 ///
7186 /// If filename is of the form file.C, the file will be interpreted.
7187 ///
7188 /// If filename is of the form file.C++, the file file.C will be compiled
7189 /// and dynamically loaded.
7190 ///
7191 /// If filename is of the form file.C+, the file file.C will be compiled
7192 /// and dynamically loaded. At next call, if file.C is older than file.o
7193 /// and file.so, the file.C is not compiled, only file.so is loaded.
7194 ///
7195 /// ## NOTE1
7196 ///
7197 /// It may be more interesting to invoke directly the other Process function
7198 /// accepting a TSelector* as argument.eg
7199 /// ~~~ {.cpp}
7200 /// MySelector *selector = (MySelector*)TSelector::GetSelector(filename);
7201 /// selector->CallSomeFunction(..);
7202 /// mytree.Process(selector,..);
7203 /// ~~~
7204 /// ## NOTE2
7205 //
7206 /// One should not call this function twice with the same selector file
7207 /// in the same script. If this is required, proceed as indicated in NOTE1,
7208 /// by getting a pointer to the corresponding TSelector,eg
7209 ///
7210 /// ### Workaround 1
7211 ///
7212 /// ~~~ {.cpp}
7213 /// void stubs1() {
7214 /// TSelector *selector = TSelector::GetSelector("h1test.C");
7215 /// TFile *f1 = new TFile("stubs_nood_le1.root");
7216 /// TTree *h1 = (TTree*)f1->Get("h1");
7217 /// h1->Process(selector);
7218 /// TFile *f2 = new TFile("stubs_nood_le1_coarse.root");
7219 /// TTree *h2 = (TTree*)f2->Get("h1");
7220 /// h2->Process(selector);
7221 /// }
7222 /// ~~~
7223 /// or use ACLIC to compile the selector
7224 ///
7225 /// ### Workaround 2
7226 ///
7227 /// ~~~ {.cpp}
7228 /// void stubs2() {
7229 /// TFile *f1 = new TFile("stubs_nood_le1.root");
7230 /// TTree *h1 = (TTree*)f1->Get("h1");
7231 /// h1->Process("h1test.C+");
7232 /// TFile *f2 = new TFile("stubs_nood_le1_coarse.root");
7233 /// TTree *h2 = (TTree*)f2->Get("h1");
7234 /// h2->Process("h1test.C+");
7235 /// }
7236 /// ~~~
7237 
7238 Long64_t TTree::Process(const char* filename, Option_t* option, Long64_t nentries, Long64_t firstentry)
7239 {
7240  GetPlayer();
7241  if (fPlayer) {
7242  return fPlayer->Process(filename, option, nentries, firstentry);
7243  }
7244  return -1;
7245 }
7246 
7247 ////////////////////////////////////////////////////////////////////////////////
7248 /// Process this tree executing the code in the specified selector.
7249 /// The return value is -1 in case of error and TSelector::GetStatus() in
7250 /// in case of success.
7251 ///
7252 /// The TSelector class has the following member functions:
7253 ///
7254 /// - `Begin()`: called every time a loop on the tree starts,
7255 /// a convenient place to create your histograms.
7256 /// - `SlaveBegin()`: called after Begin(), when on PROOF called only on the
7257 /// slave servers.
7258 /// - `Process()`: called for each event, in this function you decide what
7259 /// to read and fill your histograms.
7260 /// - `SlaveTerminate`: called at the end of the loop on the tree, when on PROOF
7261 /// called only on the slave servers.
7262 /// - `Terminate()`: called at the end of the loop on the tree,
7263 /// a convenient place to draw/fit your histograms.
7264 ///
7265 /// If the Tree (Chain) has an associated EventList, the loop is on the nentries
7266 /// of the EventList, starting at firstentry, otherwise the loop is on the
7267 /// specified Tree entries.
7268 
7269 Long64_t TTree::Process(TSelector* selector, Option_t* option, Long64_t nentries, Long64_t firstentry)
7270 {
7271  GetPlayer();
7272  if (fPlayer) {
7273  return fPlayer->Process(selector, option, nentries, firstentry);
7274  }
7275  return -1;
7276 }
7277 
7278 ////////////////////////////////////////////////////////////////////////////////
7279 /// Make a projection of a tree using selections.
7280 ///
7281 /// Depending on the value of varexp (described in Draw) a 1-D, 2-D, etc.,
7282 /// projection of the tree will be filled in histogram hname.
7283 /// Note that the dimension of hname must match with the dimension of varexp.
7284 ///
7285 
7286 Long64_t TTree::Project(const char* hname, const char* varexp, const char* selection, Option_t* option, Long64_t nentries, Long64_t firstentry)
7287 {
7288  TString var;
7289  var.Form("%s>>%s", varexp, hname);
7290  TString opt("goff");
7291  if (option) {
7292  opt.Form("%sgoff", option);
7293  }
7294  Long64_t nsel = Draw(var, selection, opt, nentries, firstentry);
7295  return nsel;
7296 }
7297 
7298 ////////////////////////////////////////////////////////////////////////////////
7299 /// Loop over entries and return a TSQLResult object containing entries following selection.
7300 
7301 TSQLResult* TTree::Query(const char* varexp, const char* selection, Option_t* option, Long64_t nentries, Long64_t firstentry)
7302 {
7303  GetPlayer();
7304  if (fPlayer) {
7305  return fPlayer->Query(varexp, selection, option, nentries, firstentry);
7306  }
7307  return 0;
7308 }
7309 
7310 ////////////////////////////////////////////////////////////////////////////////
7311 /// Create or simply read branches from filename.
7312 ///
7313 /// if branchDescriptor = "" (default), it is assumed that the Tree descriptor
7314 /// is given in the first line of the file with a syntax like
7315 /// ~~~ {.cpp}
7316 /// A/D:Table[2]/F:Ntracks/I:astring/C
7317 /// ~~~
7318 /// otherwise branchDescriptor must be specified with the above syntax.
7319 ///
7320 /// - If the type of the first variable is not specified, it is assumed to be "/F"
7321 /// - If the type of any other variable is not specified, the type of the previous
7322 /// variable is assumed. eg
7323 /// - `x:y:z` (all variables are assumed of type "F"
7324 /// - `x/D:y:z` (all variables are of type "D"
7325 /// - `x:y/D:z` (x is type "F", y and z of type "D"
7326 ///
7327 /// delimiter allows for the use of another delimiter besides whitespace.
7328 /// This provides support for direct import of common data file formats
7329 /// like csv. If delimiter != ' ' and branchDescriptor == "", then the
7330 /// branch description is taken from the first line in the file, but
7331 /// delimiter is used for the branch names tokenization rather than ':'.
7332 /// Note however that if the values in the first line do not use the
7333 /// /[type] syntax, all variables are assumed to be of type "F".
7334 /// If the filename ends with extensions .csv or .CSV and a delimiter is
7335 /// not specified (besides ' '), the delimiter is automatically set to ','.
7336 ///
7337 /// Lines in the input file starting with "#" are ignored. Leading whitespace
7338 /// for each column data is skipped. Empty lines are skipped.
7339 ///
7340 /// A TBranch object is created for each variable in the expression.
7341 /// The total number of rows read from the file is returned.
7342 ///
7343 /// ## FILLING a TTree WITH MULTIPLE INPUT TEXT FILES
7344 ///
7345 /// To fill a TTree with multiple input text files, proceed as indicated above
7346 /// for the first input file and omit the second argument for subsequent calls
7347 /// ~~~ {.cpp}
7348 /// T.ReadFile("file1.dat","branch descriptor");
7349 /// T.ReadFile("file2.dat");
7350 /// ~~~
7351 
7352 Long64_t TTree::ReadFile(const char* filename, const char* branchDescriptor, char delimiter)
7353 {
7354  std::ifstream in;
7355  in.open(filename);
7356  if (!in.good()) {
7357  Error("ReadFile","Cannot open file: %s",filename);
7358  return 0;
7359  }
7360  const char* ext = strrchr(filename, '.');
7361  if(ext != NULL && ((strcmp(ext, ".csv") == 0) || (strcmp(ext, ".CSV") == 0)) && delimiter == ' ') {
7362  delimiter = ',';
7363  }
7364  return ReadStream(in, branchDescriptor, delimiter);
7365 }
7366 
7367 ////////////////////////////////////////////////////////////////////////////////
7368 /// Determine which newline this file is using.
7369 /// Return '\\r' for Windows '\\r\\n' as that already terminates.
7370 
7371 char TTree::GetNewlineValue(std::istream &inputStream)
7372 {
7373  Long_t inPos = inputStream.tellg();
7374  char newline = '\n';
7375  while(1) {
7376  char c = 0;
7377  inputStream.get(c);
7378  if(!inputStream.good()) {
7379  Error("ReadStream","Error reading stream: no newline found.");
7380  return 0;
7381  }
7382  if(c == newline) break;
7383  if(c == '\r') {
7384  newline = '\r';
7385  break;
7386  }
7387  }
7388  inputStream.clear();
7389  inputStream.seekg(inPos);
7390  return newline;
7391 }
7392 
7393 ////////////////////////////////////////////////////////////////////////////////
7394 /// Create or simply read branches from an input stream.
7395 ///
7396 /// See reference information for TTree::ReadFile
7397 
7398 Long64_t TTree::ReadStream(std::istream& inputStream, const char *branchDescriptor, char delimiter)
7399 {
7400  char newline = 0;
7401  std::stringstream ss;
7402  std::istream *inTemp;
7403  Long_t inPos = inputStream.tellg();
7404  if (!inputStream.good()) {
7405  Error("ReadStream","Error reading stream");
7406  return 0;
7407  }
7408  if (inPos == -1) {
7409  ss << std::cin.rdbuf();
7410  newline = GetNewlineValue(ss);
7411  inTemp = &ss;
7412  } else {
7413  newline = GetNewlineValue(inputStream);
7414  inTemp = &inputStream;
7415  }
7416  std::istream& in = *inTemp;
7417  Long64_t nlines = 0;
7418 
7419  TBranch *branch = 0;
7420  Int_t nbranches = fBranches.GetEntries();
7421  if (nbranches == 0) {
7422  char *bdname = new char[4000];
7423  char *bd = new char[100000];
7424  Int_t nch = 0;
7425  if (branchDescriptor) nch = strlen(branchDescriptor);
7426  // branch Descriptor is null, read its definition from the first line in the file
7427  if (!nch) {
7428  do {
7429  in.getline(bd, 100000, newline);
7430  if (!in.good()) {
7431  delete [] bdname;
7432  delete [] bd;
7433  Error("ReadStream","Error reading stream");
7434  return 0;
7435  }
7436  char *cursor = bd;
7437  while( isspace(*cursor) && *cursor != '\n' && *cursor != '\0') {
7438  ++cursor;
7439  }
7440  if (*cursor != '#' && *cursor != '\n' && *cursor != '\0') {
7441  break;
7442  }
7443  } while (true);
7444  ++nlines;
7445  nch = strlen(bd);
7446  } else {
7447  strlcpy(bd,branchDescriptor,100000);
7448  }
7449 
7450  //parse the branch descriptor and create a branch for each element
7451  //separated by ":"
7452  void *address = &bd[90000];
7453  char *bdcur = bd;
7454  TString desc="", olddesc="F";
7455  char bdelim = ':';
7456  if(delimiter != ' ') {
7457  bdelim = delimiter;
7458  if (strchr(bdcur,bdelim)==0 && strchr(bdcur,':') != 0) {
7459  // revert to the default
7460  bdelim = ':';
7461  }
7462  }
7463  while (bdcur) {
7464  char *colon = strchr(bdcur,bdelim);
7465  if (colon) *colon = 0;
7466  strlcpy(bdname,bdcur,4000);
7467  char *slash = strchr(bdname,'/');
7468  if (slash) {
7469  *slash = 0;
7470  desc = bdcur;
7471  olddesc = slash+1;
7472  } else {
7473  desc.Form("%s/%s",bdname,olddesc.Data());
7474  }
7475  char *bracket = strchr(bdname,'[');
7476  if (bracket) {
7477  *bracket = 0;
7478  }
7479  branch = new TBranch(this,bdname,address,desc.Data(),32000);
7480  if (branch->IsZombie()) {
7481  delete branch;
7482  Warning("ReadStream","Illegal branch definition: %s",bdcur);
7483  } else {
7484  fBranches.Add(branch);
7485  branch->SetAddress(0);
7486  }
7487  if (!colon)break;
7488  bdcur = colon+1;
7489  }
7490  delete [] bdname;
7491  delete [] bd;
7492  }
7493 
7494  nbranches = fBranches.GetEntries();
7495 
7496  if (gDebug > 1) {
7497  Info("ReadStream", "Will use branches:");
7498  for (int i = 0 ; i < nbranches; ++i) {
7499  TBranch* br = (TBranch*) fBranches.At(i);
7500  Info("ReadStream", " %s: %s [%s]", br->GetName(),
7501  br->GetTitle(), br->GetListOfLeaves()->At(0)->IsA()->GetName());
7502  }
7503  if (gDebug > 3) {
7504  Info("ReadStream", "Dumping read tokens, format:");
7505  Info("ReadStream", "LLLLL:BBB:gfbe:GFBE:T");
7506  Info("ReadStream", " L: line number");
7507  Info("ReadStream", " B: branch number");
7508  Info("ReadStream", " gfbe: good / fail / bad / eof of token");
7509  Info("ReadStream", " GFBE: good / fail / bad / eof of file");
7510  Info("ReadStream", " T: Token being read");
7511  }
7512  }
7513 
7514  //loop on all lines in the file
7515  Long64_t nGoodLines = 0;
7516  std::string line;
7517  const char sDelimBuf[2] = { delimiter, 0 };
7518  const char* sDelim = sDelimBuf;
7519  if (delimiter == ' ') {
7520  // ' ' really means whitespace
7521  sDelim = "[ \t]";
7522  }
7523  while(in.good()) {
7524  if (newline == '\r' && in.peek() == '\n') {
7525  // Windows, skip '\n':
7526  in.get();
7527  }
7528  std::getline(in, line, newline);
7529  ++nlines;
7530 
7531  TString sLine(line);
7532  sLine = sLine.Strip(TString::kLeading); // skip leading whitespace
7533  if (sLine.IsNull()) {
7534  if (gDebug > 2) {
7535  Info("ReadStream", "Skipping empty line number %lld", nlines);
7536  }
7537  continue; // silently skip empty lines
7538  }
7539  if (sLine[0] == '#') {
7540  if (gDebug > 2) {
7541  Info("ReadStream", "Skipping comment line number %lld: '%s'",
7542  nlines, line.c_str());
7543  }
7544  continue;
7545  }
7546  if (gDebug > 2) {
7547  Info("ReadStream", "Parsing line number %lld: '%s'",
7548  nlines, line.c_str());
7549  }
7550 
7551  // Loop on branches and read the branch values into their buffer
7552  branch = 0;
7553  TString tok; // one column's data
7554  TString leafData; // leaf data, possibly multiple tokens for e.g. /I[2]
7555  std::stringstream sToken; // string stream feeding leafData into leaves
7556  Ssiz_t pos = 0;
7557  Int_t iBranch = 0;
7558  Bool_t goodLine = kTRUE; // whether the row can be filled into the tree
7559  Int_t remainingLeafLen = 0; // remaining columns for the current leaf
7560  while (goodLine && iBranch < nbranches
7561  && sLine.Tokenize(tok, pos, sDelim)) {
7562  tok = tok.Strip(TString::kLeading); // skip leading whitespace
7563  if (tok.IsNull() && delimiter == ' ') {
7564  // 1 2 should not be interpreted as 1,,,2 but 1, 2.
7565  // Thus continue until we have a non-empty token.
7566  continue;
7567  }
7568 
7569  if (!remainingLeafLen) {
7570  // next branch!
7571  branch = (TBranch*)fBranches.At(iBranch);
7572  }
7573  TLeaf *leaf = (TLeaf*)branch->GetListOfLeaves()->At(0);
7574  if (!remainingLeafLen) {
7575  remainingLeafLen = leaf->GetLen();
7576  if (leaf->GetMaximum() > 0) {
7577  // This is a dynamic leaf length, i.e. most likely a TLeafC's
7578  // string size. This still translates into one token:
7579  remainingLeafLen = 1;
7580  }
7581 
7582  leafData = tok;
7583  } else {
7584  // append token to laf data:
7585  leafData += " ";
7586  leafData += tok;
7587  }
7588  --remainingLeafLen;
7589  if (remainingLeafLen) {
7590  // need more columns for this branch:
7591  continue;
7592  }
7593  ++iBranch;
7594 
7595  // initialize stringstream with token
7596  sToken.clear();
7597  sToken.seekp(0, std::ios_base::beg);
7598  sToken.str(leafData.Data());
7599  sToken.seekg(0, std::ios_base::beg);
7600  leaf->ReadValue(sToken, 0 /* 0 = "all" */);
7601  if (gDebug > 3) {
7602  Info("ReadStream", "%5lld:%3d:%d%d%d%d:%d%d%d%d:%s",
7603  nlines, iBranch,
7604  (int)sToken.good(), (int)sToken.fail(),
7605  (int)sToken.bad(), (int)sToken.eof(),
7606  (int)in.good(), (int)in.fail(),
7607  (int)in.bad(), (int)in.eof(),
7608  sToken.str().c_str());
7609  }
7610 
7611  // Error handling
7612  if (sToken.bad()) {
7613  // How could that happen for a stringstream?
7614  Warning("ReadStream",
7615  "Buffer error while reading data for branch %s on line %lld",
7616  branch->GetName(), nlines);
7617  } else if (!sToken.eof()) {
7618  if (sToken.fail()) {
7619  Warning("ReadStream",
7620  "Couldn't read formatted data in \"%s\" for branch %s on line %lld; ignoring line",
7621  tok.Data(), branch->GetName(), nlines);
7622  goodLine = kFALSE;
7623  } else {
7624  std::string remainder;
7625  std::getline(sToken, remainder, newline);
7626  if (!remainder.empty()) {
7627  Warning("ReadStream",
7628  "Ignoring trailing \"%s\" while reading data for branch %s on line %lld",
7629  remainder.c_str(), branch->GetName(), nlines);
7630  }
7631  }
7632  }
7633  } // tokenizer loop
7634 
7635  if (iBranch < nbranches) {
7636  Warning("ReadStream",
7637  "Read too few columns (%d < %d) in line %lld; ignoring line",
7638  iBranch, nbranches, nlines);
7639  goodLine = kFALSE;
7640  } else if (pos != kNPOS) {
7641  sLine = sLine.Strip(TString::kTrailing);
7642  if (pos < sLine.Length()) {
7643  Warning("ReadStream",
7644  "Ignoring trailing \"%s\" while reading line %lld",
7645  sLine.Data() + pos - 1 /* also print delimiter */,
7646  nlines);
7647  }
7648  }
7649 
7650  //we are now ready to fill the tree
7651  if (goodLine) {
7652  Fill();
7653  ++nGoodLines;
7654  }
7655  }
7656 
7657  return nGoodLines;
7658 }
7659 
7660 ////////////////////////////////////////////////////////////////////////////////
7661 /// Make sure that obj (which is being deleted or will soon be) is no
7662 /// longer referenced by this TTree.
7663 
7664 void TTree::RecursiveRemove(TObject *obj)
7665 {
7666  if (obj == fEventList) {
7667  fEventList = 0;
7668  }
7669  if (obj == fEntryList) {
7670  fEntryList = 0;
7671  }
7672  if (fUserInfo) {
7673  fUserInfo->RecursiveRemove(obj);
7674  }
7675  if (fPlayer == obj) {
7676  fPlayer = 0;
7677  }
7678  if (fTreeIndex == obj) {
7679  fTreeIndex = 0;
7680  }
7681  if (fAliases) {
7682  fAliases->RecursiveRemove(obj);
7683  }
7684  if (fFriends) {
7685  fFriends->RecursiveRemove(obj);
7686  }
7687 }
7688 
7689 ////////////////////////////////////////////////////////////////////////////////
7690 /// Refresh contents of this tree and its branches from the current status on disk.
7691 ///
7692 /// One can call this function in case the tree file is being
7693 /// updated by another process.
7694 
7695 void TTree::Refresh()
7696 {
7697  if (!fDirectory->GetFile()) {
7698  return;
7699  }
7700  fDirectory->ReadKeys();
7701  fDirectory->Remove(this);
7702  TTree* tree; fDirectory->GetObject(GetName(),tree);
7703  if (!tree) {
7704  return;
7705  }
7706  //copy info from tree header into this Tree
7707  fEntries = 0;
7708  fNClusterRange = 0;
7709  ImportClusterRanges(tree);
7710 
7711  fAutoSave = tree->fAutoSave;
7712  fEntries = tree->fEntries;
7713  fTotBytes = tree->GetTotBytes();
7714  fZipBytes = tree->GetZipBytes();
7715  fSavedBytes = tree->fSavedBytes;
7716  fTotalBuffers = tree->fTotalBuffers.load();
7717 
7718  //loop on all branches and update them
7719  Int_t nleaves = fLeaves.GetEntriesFast();
7720  for (Int_t i = 0; i < nleaves; i++) {
7721  TLeaf* leaf = (TLeaf*) fLeaves.UncheckedAt(i);
7722  TBranch* branch = (TBranch*) leaf->GetBranch();
7723  branch->Refresh(tree->GetBranch(branch->GetName()));
7724  }
7725  fDirectory->Remove(tree);
7726  fDirectory->Append(this);
7727  delete tree;
7728  tree = 0;
7729 }
7730 
7731 ////////////////////////////////////////////////////////////////////////////////
7732 /// Remove a friend from the list of friends.
7733 
7734 void TTree::RemoveFriend(TTree* oldFriend)
7735 {
7736  // We already have been visited while recursively looking
7737  // through the friends tree, let return
7738  if (kRemoveFriend & fFriendLockStatus) {
7739  return;
7740  }
7741  if (!fFriends) {
7742  return;
7743  }
7744  TFriendLock lock(this, kRemoveFriend);
7745  TIter nextf(fFriends);
7746  TFriendElement* fe = 0;
7747  while ((fe = (TFriendElement*) nextf())) {
7748  TTree* friend_t = fe->GetTree();
7749  if (friend_t == oldFriend) {
7750  fFriends->Remove(fe);
7751  delete fe;
7752  fe = 0;
7753  }
7754  }
7755 }
7756 
7757 ////////////////////////////////////////////////////////////////////////////////
7758 /// Reset baskets, buffers and entries count in all branches and leaves.
7759 
7760 void TTree::Reset(Option_t* option)
7761 {
7762  fNotify = 0;
7763  fEntries = 0;
7764  fNClusterRange = 0;
7765  fTotBytes = 0;
7766  fZipBytes = 0;
7767  fFlushedBytes = 0;
7768  fSavedBytes = 0;
7769  fTotalBuffers = 0;
7770  fChainOffset = 0;
7771  fReadEntry = -1;
7772 
7773  delete fTreeIndex;
7774  fTreeIndex = 0;
7775 
7776  Int_t nb = fBranches.GetEntriesFast();
7777  for (Int_t i = 0; i < nb; ++i) {
7778  TBranch* branch = (TBranch*) fBranches.UncheckedAt(i);
7779  branch->Reset(option);
7780  }
7781 
7782  if (fBranchRef) {
7783  fBranchRef->Reset();
7784  }
7785 }
7786 
7787 ////////////////////////////////////////////////////////////////////////////////
7788 /// Resets the state of this TTree after a merge (keep the customization but
7789 /// forget the data).
7790 
7791 void TTree::ResetAfterMerge(TFileMergeInfo *info)
7792 {
7793  fEntries = 0;
7794  fNClusterRange = 0;
7795  fTotBytes = 0;
7796  fZipBytes = 0;
7797  fSavedBytes = 0;
7798  fFlushedBytes = 0;
7799  fTotalBuffers = 0;
7800  fChainOffset = 0;
7801  fReadEntry = -1;
7802 
7803  delete fTreeIndex;
7804  fTreeIndex = 0;
7805 
7806  Int_t nb = fBranches.GetEntriesFast();
7807  for (Int_t i = 0; i < nb; ++i) {
7808  TBranch* branch = (TBranch*) fBranches.UncheckedAt(i);
7809  branch->ResetAfterMerge(info);
7810  }
7811 
7812  if (fBranchRef) {
7813  fBranchRef->ResetAfterMerge(info);
7814  }
7815 }
7816 
7817 ////////////////////////////////////////////////////////////////////////////////
7818 /// Tell all of our branches to set their addresses to zero.
7819 ///
7820 /// Note: If any of our branches own any objects, they are deleted.
7821 
7822 void TTree::ResetBranchAddress(TBranch *br)
7823 {
7824  if (br && br->GetTree()) {
7825  br->ResetAddress();
7826  }
7827 }
7828 
7829 ////////////////////////////////////////////////////////////////////////////////
7830 /// Tell all of our branches to drop their current objects and allocate new ones.
7831 
7832 void TTree::ResetBranchAddresses()
7833 {
7834  TObjArray* branches = GetListOfBranches();
7835  Int_t nbranches = branches->GetEntriesFast();
7836  for (Int_t i = 0; i < nbranches; ++i) {
7837  TBranch* branch = (TBranch*) branches->UncheckedAt(i);
7838  branch->ResetAddress();
7839  }
7840 }
7841 
7842 ////////////////////////////////////////////////////////////////////////////////
7843 /// Loop over tree entries and print entries passing selection.
7844 ///
7845 /// - If varexp is 0 (or "") then print only first 8 columns.
7846 /// - If varexp = "*" print all columns.
7847 ///
7848 /// Otherwise a columns selection can be made using "var1:var2:var3".
7849 /// See TTreePlayer::Scan for more information
7850 
7851 Long64_t TTree::Scan(const char* varexp, const char* selection, Option_t* option, Long64_t nentries, Long64_t firstentry)
7852 {
7853  GetPlayer();
7854  if (fPlayer) {
7855  return fPlayer->Scan(varexp, selection, option, nentries, firstentry);
7856  }
7857  return -1;
7858 }
7859 
7860 ////////////////////////////////////////////////////////////////////////////////
7861 /// Set a tree variable alias.
7862 ///
7863 /// Set an alias for an expression/formula based on the tree 'variables'.
7864 ///
7865 /// The content of 'aliasName' can be used in TTreeFormula (i.e. TTree::Draw,
7866 /// TTree::Scan, TTreeViewer) and will be evaluated as the content of
7867 /// 'aliasFormula'.
7868 ///
7869 /// If the content of 'aliasFormula' only contains symbol names, periods and
7870 /// array index specification (for example event.fTracks[3]), then
7871 /// the content of 'aliasName' can be used as the start of symbol.
7872 ///
7873 /// If the alias 'aliasName' already existed, it is replaced by the new
7874 /// value.
7875 ///
7876 /// When being used, the alias can be preceded by an eventual 'Friend Alias'
7877 /// (see TTree::GetFriendAlias)
7878 ///
7879 /// Return true if it was added properly.
7880 ///
7881 /// For example:
7882 /// ~~~ {.cpp}
7883 /// tree->SetAlias("x1","(tdc1[1]-tdc1[0])/49");
7884 /// tree->SetAlias("y1","(tdc1[3]-tdc1[2])/47");
7885 /// tree->SetAlias("x2","(tdc2[1]-tdc2[0])/49");
7886 /// tree->SetAlias("y2","(tdc2[3]-tdc2[2])/47");
7887 /// tree->Draw("y2-y1:x2-x1");
7888 ///
7889 /// tree->SetAlias("theGoodTrack","event.fTracks[3]");
7890 /// tree->Draw("theGoodTrack.fPx"); // same as "event.fTracks[3].fPx"
7891 /// ~~~
7892 
7893 Bool_t TTree::SetAlias(const char* aliasName, const char* aliasFormula)
7894 {
7895  if (!aliasName || !aliasFormula) {
7896  return kFALSE;
7897  }
7898  if (!aliasName[0] || !aliasFormula[0]) {
7899  return kFALSE;
7900  }
7901  if (!fAliases) {
7902  fAliases = new TList;
7903  } else {
7904  TNamed* oldHolder = (TNamed*) fAliases->FindObject(aliasName);
7905  if (oldHolder) {
7906  oldHolder->SetTitle(aliasFormula);
7907  return kTRUE;
7908  }
7909  }
7910  TNamed* holder = new TNamed(aliasName, aliasFormula);
7911  fAliases->Add(holder);
7912  return kTRUE;
7913 }
7914 
7915 ////////////////////////////////////////////////////////////////////////////////
7916 /// This function may be called at the start of a program to change
7917 /// the default value for fAutoFlush.
7918 ///
7919 /// ### CASE 1 : autof > 0
7920 ///
7921 /// autof is the number of consecutive entries after which TTree::Fill will
7922 /// flush all branch buffers to disk.
7923 ///
7924 /// ### CASE 2 : autof < 0
7925 ///
7926 /// When filling the Tree the branch buffers will be flushed to disk when
7927 /// more than autof bytes have been written to the file. At the first FlushBaskets
7928 /// TTree::Fill will replace fAutoFlush by the current value of fEntries.
7929 ///
7930 /// Calling this function with autof<0 is interesting when it is hard to estimate
7931 /// the size of one entry. This value is also independent of the Tree.
7932 ///
7933 /// The Tree is initialized with fAutoFlush=-30000000, ie that, by default,
7934 /// the first AutoFlush will be done when 30 MBytes of data are written to the file.
7935 ///
7936 /// ### CASE 3 : autof = 0
7937 ///
7938 /// The AutoFlush mechanism is disabled.
7939 ///
7940 /// Flushing the buffers at regular intervals optimize the location of
7941 /// consecutive entries on the disk by creating clusters of baskets.
7942 ///
7943 /// A cluster of baskets is a set of baskets that contains all
7944 /// the data for a (consecutive) set of entries and that is stored
7945 /// consecutively on the disk. When reading all the branches, this
7946 /// is the minimum set of baskets that the TTreeCache will read.
7947 
7948 void TTree::SetAutoFlush(Long64_t autof /* = -30000000 */ )
7949 {
7950  // Implementation note:
7951  //
7952  // A positive value of autoflush determines the size (in number of entries) of
7953  // a cluster of baskets.
7954  //
7955  // If the value of autoflush is changed over time (this happens in
7956  // particular when the TTree results from fast merging many trees),
7957  // we record the values of fAutoFlush in the data members:
7958  // fClusterRangeEnd and fClusterSize.
7959  // In the code we refer to a range of entries where the size of the
7960  // cluster of baskets is the same (i.e the value of AutoFlush was
7961  // constant) is called a ClusterRange.
7962  //
7963  // The 2 arrays (fClusterRangeEnd and fClusterSize) have fNClusterRange
7964  // active (used) values and have fMaxClusterRange allocated entries.
7965  //
7966  // fClusterRangeEnd contains the last entries number of a cluster range.
7967  // In particular this means that the 'next' cluster starts at fClusterRangeEnd[]+1
7968  // fClusterSize contains the size in number of entries of all the cluster
7969  // within the given range.
7970  // The last range (and the only one if fNClusterRange is zero) start at
7971  // fNClusterRange[fNClusterRange-1]+1 and ends at the end of the TTree. The
7972  // size of the cluster in this range is given by the value of fAutoFlush.
7973  //
7974  // For example printing the beginning and end of each the ranges can be done by:
7975  //
7976  // Printf("%-16s %-16s %-16s %5s",
7977  // "Cluster Range #", "Entry Start", "Last Entry", "Size");
7978  // Int_t index= 0;
7979  // Long64_t clusterRangeStart = 0;
7980  // if (fNClusterRange) {
7981  // for( ; index < fNClusterRange; ++index) {
7982  // Printf("%-16d %-16lld %-16lld %5lld",
7983  // index, clusterRangeStart, fClusterRangeEnd[index], fClusterSize[index]);
7984  // clusterRangeStart = fClusterRangeEnd[index] + 1;
7985  // }
7986  // }
7987  // Printf("%-16d %-16lld %-16lld %5lld",
7988  // index, prevEntry, fEntries - 1, fAutoFlush);
7989  //
7990 
7991  // Note: We store the entry number corresponding to the end of the cluster
7992  // rather than its start in order to avoid using the array if the cluster
7993  // size never varies (If there is only one value of AutoFlush for the whole TTree).
7994 
7995  if( fAutoFlush != autof) {
7996  if ((fAutoFlush > 0 || autof > 0) && fFlushedBytes) {
7997  // The mechanism was already enabled, let's record the previous
7998  // cluster if needed.
7999  MarkEventCluster();
8000  }
8001  fAutoFlush = autof;
8002  }
8003 }
8004 
8005 ////////////////////////////////////////////////////////////////////////////////
8006 /// Mark the previous event as being at the end of the event cluster.
8007 ///
8008 /// So, if fEntries is set to 10 (and this is the first cluster) when MarkEventCluster
8009 /// is called, then the first cluster has 9 events.
8010 void TTree::MarkEventCluster()
8011 {
8012  if (!fEntries) return;
8013 
8014  if ( (fNClusterRange+1) > fMaxClusterRange ) {
8015  if (fMaxClusterRange) {
8016  // Resize arrays to hold a larger event cluster.
8017  Int_t newsize = TMath::Max(10,Int_t(2*fMaxClusterRange));
8018  fClusterRangeEnd = (Long64_t*)TStorage::ReAlloc(fClusterRangeEnd,
8019  newsize*sizeof(Long64_t),fMaxClusterRange*sizeof(Long64_t));
8020  fClusterSize = (Long64_t*)TStorage::ReAlloc(fClusterSize,
8021  newsize*sizeof(Long64_t),fMaxClusterRange*sizeof(Long64_t));
8022  fMaxClusterRange = newsize;
8023  } else {
8024  // Cluster ranges have never been initialized; create them now.
8025  fMaxClusterRange = 2;
8026  fClusterRangeEnd = new Long64_t[fMaxClusterRange];
8027  fClusterSize = new Long64_t[fMaxClusterRange];
8028  }
8029  }
8030  fClusterRangeEnd[fNClusterRange] = fEntries - 1;
8031  // If we are auto-flushing, then the cluster size is the same as the current auto-flush setting.
8032  if (fAutoFlush > 0) {
8033  // Even if the user triggers MarkEventRange prior to fAutoFlush being present, the TClusterIterator
8034  // will appropriately go to the next event range.
8035  fClusterSize[fNClusterRange] = fAutoFlush;
8036  // Otherwise, assume there is one cluster per event range (e.g., user is manually controlling the flush).
8037  } else if (fNClusterRange == 0) {
8038  fClusterSize[fNClusterRange] = fEntries;
8039  } else {
8040  fClusterSize[fNClusterRange] = fClusterRangeEnd[fNClusterRange] - fClusterRangeEnd[fNClusterRange-1];
8041  }
8042  ++fNClusterRange;
8043 }
8044 
8045 ////////////////////////////////////////////////////////////////////////////////
8046 /// This function may be called at the start of a program to change
8047 /// the default value for fAutoSave (and for SetAutoSave) is -300000000, ie 300 MBytes.
8048 /// When filling the Tree the branch buffers as well as the Tree header
8049 /// will be flushed to disk when the watermark is reached.
8050 /// If fAutoSave is positive the watermark is reached when a multiple of fAutoSave
8051 /// entries have been written.
8052 /// If fAutoSave is negative the watermark is reached when -fAutoSave bytes
8053 /// have been written to the file.
8054 /// In case of a program crash, it will be possible to recover the data in the Tree
8055 /// up to the last AutoSave point.
8056 
8057 void TTree::SetAutoSave(Long64_t autos)
8058 {
8059  fAutoSave = autos;
8060 }
8061 
8062 ////////////////////////////////////////////////////////////////////////////////
8063 /// Set a branch's basket size.
8064 ///
8065 /// bname is the name of a branch.
8066 ///
8067 /// - if bname="*", apply to all branches.
8068 /// - if bname="xxx*", apply to all branches with name starting with xxx
8069 ///
8070 /// see TRegexp for wildcarding options
8071 /// buffsize = branc basket size
8072 
8073 void TTree::SetBasketSize(const char* bname, Int_t buffsize)
8074 {
8075  Int_t nleaves = fLeaves.GetEntriesFast();
8076  TRegexp re(bname, kTRUE);
8077  Int_t nb = 0;
8078  for (Int_t i = 0; i < nleaves; i++) {
8079  TLeaf* leaf = (TLeaf*) fLeaves.UncheckedAt(i);
8080  TBranch* branch = (TBranch*) leaf->GetBranch();
8081  TString s = branch->GetName();
8082  if (strcmp(bname, branch->GetName()) && (s.Index(re) == kNPOS)) {
8083  continue;
8084  }
8085  nb++;
8086  branch->SetBasketSize(buffsize);
8087  }
8088  if (!nb) {
8089  Error("SetBasketSize", "unknown branch -> '%s'", bname);
8090  }
8091 }
8092 
8093 ////////////////////////////////////////////////////////////////////////////////
8094 /// Change branch address, dealing with clone trees properly.
8095 /// See TTree::CheckBranchAddressType for the semantic of the return value.
8096 ///
8097 /// Note: See the comments in TBranchElement::SetAddress() for the
8098 /// meaning of the addr parameter and the object ownership policy.
8099 
8100 Int_t TTree::SetBranchAddress(const char* bname, void* addr, TBranch** ptr)
8101 {
8102  TBranch* branch = GetBranch(bname);
8103  if (!branch) {
8104  if (ptr) *ptr = 0;
8105  Error("SetBranchAddress", "unknown branch -> %s", bname);
8106  return kMissingBranch;
8107  }
8108  return SetBranchAddressImp(branch,addr,ptr);
8109 }
8110 
8111 ////////////////////////////////////////////////////////////////////////////////
8112 /// Verify the validity of the type of addr before calling SetBranchAddress.
8113 /// See TTree::CheckBranchAddressType for the semantic of the return value.
8114 ///
8115 /// Note: See the comments in TBranchElement::SetAddress() for the
8116 /// meaning of the addr parameter and the object ownership policy.
8117 
8118 Int_t TTree::SetBranchAddress(const char* bname, void* addr, TClass* ptrClass, EDataType datatype, Bool_t isptr)
8119 {
8120  return SetBranchAddress(bname, addr, 0, ptrClass, datatype, isptr);
8121 }
8122 
8123 ////////////////////////////////////////////////////////////////////////////////
8124 /// Verify the validity of the type of addr before calling SetBranchAddress.
8125 /// See TTree::CheckBranchAddressType for the semantic of the return value.
8126 ///
8127 /// Note: See the comments in TBranchElement::SetAddress() for the
8128 /// meaning of the addr parameter and the object ownership policy.
8129 
8130 Int_t TTree::SetBranchAddress(const char* bname, void* addr, TBranch** ptr, TClass* ptrClass, EDataType datatype, Bool_t isptr)
8131 {
8132  TBranch* branch = GetBranch(bname);
8133  if (!branch) {
8134  if (ptr) *ptr = 0;
8135  Error("SetBranchAddress", "unknown branch -> %s", bname);
8136  return kMissingBranch;
8137  }
8138 
8139  Int_t res = CheckBranchAddressType(branch, ptrClass, datatype, isptr);
8140  // This will set the value of *ptr to branch.
8141  if (res >= 0) {
8142  // The check succeeded.
8143  SetBranchAddressImp(branch,addr,ptr);
8144  } else {
8145  if (ptr) *ptr = 0;
8146  }
8147  return res;
8148 }
8149 
8150 ////////////////////////////////////////////////////////////////////////////////
8151 /// Change branch address, dealing with clone trees properly.
8152 /// See TTree::CheckBranchAddressType for the semantic of the return value.
8153 ///
8154 /// Note: See the comments in TBranchElement::SetAddress() for the
8155 /// meaning of the addr parameter and the object ownership policy.
8156 
8157 Int_t TTree::SetBranchAddressImp(TBranch *branch, void* addr, TBranch** ptr)
8158 {
8159  if (ptr) {
8160  *ptr = branch;
8161  }
8162  if (fClones) {
8163  void* oldAddr = branch->GetAddress();
8164  TIter next(fClones);
8165  TTree* clone = 0;
8166  const char *bname = branch->GetName();
8167  while ((clone = (TTree*) next())) {
8168  TBranch* cloneBr = clone->GetBranch(bname);
8169  if (cloneBr && (cloneBr->GetAddress() == oldAddr)) {
8170  cloneBr->SetAddress(addr);
8171  }
8172  }
8173  }
8174  branch->SetAddress(addr);
8175  return kVoidPtr;
8176 }
8177 
8178 ////////////////////////////////////////////////////////////////////////////////
8179 /// Set branch status to Process or DoNotProcess.
8180 ///
8181 /// When reading a Tree, by default, all branches are read.
8182 /// One can speed up considerably the analysis phase by activating
8183 /// only the branches that hold variables involved in a query.
8184 ///
8185 /// bname is the name of a branch.
8186 ///
8187 /// - if bname="*", apply to all branches.
8188 /// - if bname="xxx*", apply to all branches with name starting with xxx
8189 ///
8190 /// see TRegexp for wildcarding options
8191 ///
8192 /// - status = 1 branch will be processed
8193 /// - = 0 branch will not be processed
8194 ///
8195 /// Example:
8196 ///
8197 /// Assume a tree T with sub-branches a,b,c,d,e,f,g,etc..
8198 /// when doing T.GetEntry(i) all branches are read for entry i.
8199 /// to read only the branches c and e, one can do
8200 /// ~~~ {.cpp}
8201 /// T.SetBranchStatus("*",0); //disable all branches
8202 /// T.SetBranchStatus("c",1);
8203 /// T.setBranchStatus("e",1);
8204 /// T.GetEntry(i);
8205 /// ~~~
8206 /// bname is interpreted as a wildcarded TRegexp (see TRegexp::MakeWildcard).
8207 /// Thus, "a*b" or "a.*b" matches branches starting with "a" and ending with
8208 /// "b", but not any other branch with an "a" followed at some point by a
8209 /// "b". For this second behavior, use "*a*b*". Note that TRegExp does not
8210 /// support '|', and so you cannot select, e.g. track and shower branches
8211 /// with "track|shower".
8212 ///
8213 /// __WARNING! WARNING! WARNING!__
8214 ///
8215 /// SetBranchStatus is matching the branch based on match of the branch
8216 /// 'name' and not on the branch hierarchy! In order to be able to
8217 /// selectively enable a top level object that is 'split' you need to make
8218 /// sure the name of the top level branch is prefixed to the sub-branches'
8219 /// name (by adding a dot ('.') at the end of the Branch creation and use the
8220 /// corresponding bname.
8221 ///
8222 /// I.e If your Tree has been created in split mode with a parent branch "parent."
8223 /// (note the trailing dot).
8224 /// ~~~ {.cpp}
8225 /// T.SetBranchStatus("parent",1);
8226 /// ~~~
8227 /// will not activate the sub-branches of "parent". You should do:
8228 /// ~~~ {.cpp}
8229 /// T.SetBranchStatus("parent*",1);
8230 /// ~~~
8231 /// Without the trailing dot in the branch creation you have no choice but to
8232 /// call SetBranchStatus explicitly for each of the sub branches.
8233 ///
8234 /// An alternative to this function is to read directly and only
8235 /// the interesting branches. Example:
8236 /// ~~~ {.cpp}
8237 /// TBranch *brc = T.GetBranch("c");
8238 /// TBranch *bre = T.GetBranch("e");
8239 /// brc->GetEntry(i);
8240 /// bre->GetEntry(i);
8241 /// ~~~
8242 /// If found is not 0, the number of branch(es) found matching the regular
8243 /// expression is returned in *found AND the error message 'unknown branch'
8244 /// is suppressed.
8245 
8246 void TTree::SetBranchStatus(const char* bname, Bool_t status, UInt_t* found)
8247 {
8248  // We already have been visited while recursively looking
8249  // through the friends tree, let return
8250  if (kSetBranchStatus & fFriendLockStatus) {
8251  return;
8252  }
8253 
8254  if (0 == strcmp(bname, "")) {
8255  Error("SetBranchStatus", "Input regexp is an empty string: no match against branch names will be attempted.");
8256  return;
8257  }
8258 
8259  TBranch *branch, *bcount, *bson;
8260  TLeaf *leaf, *leafcount;
8261 
8262  Int_t i,j;
8263  Int_t nleaves = fLeaves.GetEntriesFast();
8264  TRegexp re(bname,kTRUE);
8265  Int_t nb = 0;
8266 
8267  // first pass, loop on all branches
8268  // for leafcount branches activate/deactivate in function of status
8269  for (i=0;i<nleaves;i++) {
8270  leaf = (TLeaf*)fLeaves.UncheckedAt(i);
8271  branch = (TBranch*)leaf->GetBranch();
8272  TString s = branch->GetName();
8273  if (strcmp(bname,"*")) { //Regexp gives wrong result for [] in name
8274  TString longname;
8275  longname.Form("%s.%s",GetName(),branch->GetName());
8276  if (strcmp(bname,branch->GetName())
8277  && longname != bname
8278  && s.Index(re) == kNPOS) continue;
8279  }
8280  nb++;
8281  if (status) branch->ResetBit(kDoNotProcess);
8282  else branch->SetBit(kDoNotProcess);
8283  leafcount = leaf->GetLeafCount();
8284  if (leafcount) {
8285  bcount = leafcount->GetBranch();
8286  if (status) bcount->ResetBit(kDoNotProcess);
8287  else bcount->SetBit(kDoNotProcess);
8288  }
8289  }
8290  if (nb==0 && strchr(bname,'*')==0) {
8291  branch = GetBranch(bname);
8292  if (branch) {
8293  if (status) branch->ResetBit(kDoNotProcess);
8294  else branch->SetBit(kDoNotProcess);
8295  ++nb;
8296  }
8297  }
8298 
8299  //search in list of friends
8300  UInt_t foundInFriend = 0;
8301  if (fFriends) {
8302  TFriendLock lock(this,kSetBranchStatus);
8303  TIter nextf(fFriends);
8304  TFriendElement *fe;
8305  TString name;
8306  while ((fe = (TFriendElement*)nextf())) {
8307  TTree *t = fe->GetTree();
8308  if (t==0) continue;
8309 
8310  // If the alias is present replace it with the real name.
8311  char *subbranch = (char*)strstr(bname,fe->GetName());
8312  if (subbranch!=bname) subbranch = 0;
8313  if (subbranch) {
8314  subbranch += strlen(fe->GetName());
8315  if ( *subbranch != '.' ) subbranch = 0;
8316  else subbranch ++;
8317  }
8318  if (subbranch) {
8319  name.Form("%s.%s",t->GetName(),subbranch);
8320  } else {
8321  name = bname;
8322  }
8323  t->SetBranchStatus(name,status, &foundInFriend);
8324  }
8325  }
8326  if (!nb && !foundInFriend) {
8327  if (found==0) {
8328  if (status) {
8329  if (strchr(bname,'*') != 0)
8330  Error("SetBranchStatus", "No branch name is matching wildcard -> %s", bname);
8331  else
8332  Error("SetBranchStatus", "unknown branch -> %s", bname);
8333  } else {
8334  if (strchr(bname,'*') != 0)
8335  Warning("SetBranchStatus", "No branch name is matching wildcard -> %s", bname);
8336  else
8337  Warning("SetBranchStatus", "unknown branch -> %s", bname);
8338  }
8339  }
8340  return;
8341  }
8342  if (found) *found = nb + foundInFriend;
8343 
8344  // second pass, loop again on all branches
8345  // activate leafcount branches for active branches only
8346  for (i = 0; i < nleaves; i++) {
8347  leaf = (TLeaf*)fLeaves.UncheckedAt(i);
8348  branch = (TBranch*)leaf->GetBranch();
8349  if (!branch->TestBit(kDoNotProcess)) {
8350  leafcount = leaf->GetLeafCount();
8351  if (leafcount) {
8352  bcount = leafcount->GetBranch();
8353  bcount->ResetBit(kDoNotProcess);
8354  }
8355  } else {
8356  //Int_t nbranches = branch->GetListOfBranches()->GetEntriesFast();
8357  Int_t nbranches = branch->GetListOfBranches()->GetEntries();
8358  for (j=0;j<nbranches;j++) {
8359  bson = (TBranch*)branch->GetListOfBranches()->UncheckedAt(j);
8360  if (!bson) continue;
8361  if (!bson->TestBit(kDoNotProcess)) {
8362  if (bson->GetNleaves() <= 0) continue;
8363  branch->ResetBit(kDoNotProcess);
8364  break;
8365  }
8366  }
8367  }
8368  }
8369 }
8370 
8371 ////////////////////////////////////////////////////////////////////////////////
8372 /// Set the current branch style. (static function)
8373 ///
8374 /// - style = 0 old Branch
8375 /// - style = 1 new Bronch
8376 
8377 void TTree::SetBranchStyle(Int_t style)
8378 {
8379  fgBranchStyle = style;
8380 }
8381 
8382 ////////////////////////////////////////////////////////////////////////////////
8383 /// Set maximum size of the file cache .
8384 //
8385 /// - if cachesize = 0 the existing cache (if any) is deleted.
8386 /// - if cachesize = -1 (default) it is set to the AutoFlush value when writing
8387 /// the Tree (default is 30 MBytes).
8388 ///
8389 /// Returns:
8390 /// - 0 size set, cache was created if possible
8391 /// - -1 on error
8392 
8393 Int_t TTree::SetCacheSize(Long64_t cacheSize)
8394 {
8395  // remember that the user has requested an explicit cache setup
8396  fCacheUserSet = kTRUE;
8397 
8398  return SetCacheSizeAux(kFALSE, cacheSize);
8399 }
8400 
8401 ////////////////////////////////////////////////////////////////////////////////
8402 /// Set the size of the file cache and create it if possible.
8403 ///
8404 /// If autocache is true:
8405 /// this may be an autocreated cache, possibly enlarging an existing
8406 /// autocreated cache. The size is calculated. The value passed in cacheSize:
8407 /// - cacheSize = 0 make cache if default cache creation is enabled
8408 /// - cacheSize = -1 make a default sized cache in any case
8409 ///
8410 /// If autocache is false:
8411 /// this is a user requested cache. cacheSize is used to size the cache.
8412 /// This cache should never be automatically adjusted.
8413 ///
8414 /// Returns:
8415 /// - 0 size set, or existing autosized cache almost large enough.
8416 /// (cache was created if possible)
8417 /// - -1 on error
8418 
8419 Int_t TTree::SetCacheSizeAux(Bool_t autocache /* = kTRUE */, Long64_t cacheSize /* = 0 */ )
8420 {
8421  if (autocache) {
8422  // used as a once only control for automatic cache setup
8423  fCacheDoAutoInit = kFALSE;
8424  }
8425 
8426  if (!autocache) {
8427  // negative size means the user requests the default
8428  if (cacheSize < 0) {
8429  cacheSize = GetCacheAutoSize(kTRUE);
8430  }
8431  } else {
8432  if (cacheSize == 0) {
8433  cacheSize = GetCacheAutoSize();
8434  } else if (cacheSize < 0) {
8435  cacheSize = GetCacheAutoSize(kTRUE);
8436  }
8437  }
8438 
8439  TFile* file = GetCurrentFile();
8440  if (!file || GetTree() != this) {
8441  // if there's no file or we are not a plain tree (e.g. if we're a TChain)
8442  // do not create a cache, only record the size if one was given
8443  if (!autocache) {
8444  fCacheSize = cacheSize;
8445  }
8446  if (GetTree() != this) {
8447  return 0;
8448  }
8449  if (!autocache && cacheSize>0) {
8450  Warning("SetCacheSizeAux", "A TTreeCache could not be created because the TTree has no file");
8451  }
8452  return 0;
8453  }
8454 
8455  // Check for an existing cache
8456  TTreeCache* pf = GetReadCache(file);
8457  if (pf) {
8458  if (autocache) {
8459  // reset our cache status tracking in case existing cache was added
8460  // by the user without using one of the TTree methods
8461  fCacheSize = pf->GetBufferSize();
8462  fCacheUserSet = !pf->IsAutoCreated();
8463 
8464  if (fCacheUserSet) {
8465  // existing cache was created by the user, don't change it
8466  return 0;
8467  }
8468  } else {
8469  // update the cache to ensure it records the user has explicitly
8470  // requested it
8471  pf->SetAutoCreated(kFALSE);
8472  }
8473 
8474  // if we're using an automatically calculated size and the existing
8475  // cache is already almost large enough don't resize
8476  if (autocache && Long64_t(0.80*cacheSize) < fCacheSize) {
8477  // already large enough
8478  return 0;
8479  }
8480 
8481  if (cacheSize == fCacheSize) {
8482  return 0;
8483  }
8484 
8485  if (cacheSize == 0) {
8486  // delete existing cache
8487  pf->WaitFinishPrefetch();
8488  file->SetCacheRead(0,this);
8489  delete pf;
8490  pf = 0;
8491  } else {
8492  // resize
8493  Int_t res = pf->SetBufferSize(cacheSize);
8494  if (res < 0) {
8495  return -1;
8496  }
8497  }
8498  } else {
8499  // no existing cache
8500  if (autocache) {
8501  if (fCacheUserSet) {
8502  // value was already set manually.
8503  if (fCacheSize == 0) return 0;
8504  // Expected a cache should exist; perhaps the user moved it
8505  // Do nothing more here.
8506  if (cacheSize) {
8507  Error("SetCacheSizeAux", "Not setting up an automatically sized TTreeCache because of missing cache previously set");
8508  }
8509  return -1;
8510  }
8511  }
8512  }
8513 
8514  fCacheSize = cacheSize;
8515  if (cacheSize == 0 || pf) {
8516  return 0;
8517  }
8518 
8519 #ifdef R__USE_IMT
8520  if(TTreeCacheUnzip::IsParallelUnzip() && file->GetCompressionLevel() > 0)
8521  pf = new TTreeCacheUnzip(this, cacheSize);
8522  else
8523 #endif
8524  pf = new TTreeCache(this, cacheSize);
8525 
8526  pf->SetAutoCreated(autocache);
8527 
8528  return 0;
8529 }
8530 
8531 ////////////////////////////////////////////////////////////////////////////////
8532 ///interface to TTreeCache to set the cache entry range
8533 ///
8534 /// Returns:
8535 /// - 0 entry range set
8536 /// - -1 on error
8537 
8538 Int_t TTree::SetCacheEntryRange(Long64_t first, Long64_t last)
8539 {
8540  if (!GetTree()) {
8541  if (LoadTree(0)<0) {
8542  Error("SetCacheEntryRange","Could not load a tree");
8543  return -1;
8544  }
8545  }
8546  if (GetTree()) {
8547  if (GetTree() != this) {
8548  return GetTree()->SetCacheEntryRange(first, last);
8549  }
8550  } else {
8551  Error("SetCacheEntryRange", "No tree is available. Could not set cache entry range");
8552  return -1;
8553  }
8554 
8555  TFile *f = GetCurrentFile();
8556  if (!f) {
8557  Error("SetCacheEntryRange", "No file is available. Could not set cache entry range");
8558  return -1;
8559  }
8560  TTreeCache *tc = GetReadCache(f,kTRUE);
8561  if (!tc) {
8562  Error("SetCacheEntryRange", "No cache is available. Could not set entry range");
8563  return -1;
8564  }
8565  tc->SetEntryRange(first,last);
8566  return 0;
8567 }
8568 
8569 ////////////////////////////////////////////////////////////////////////////////
8570 /// Interface to TTreeCache to set the number of entries for the learning phase
8571 
8572 void TTree::SetCacheLearnEntries(Int_t n)
8573 {
8574  TTreeCache::SetLearnEntries(n);
8575 }
8576 
8577 ////////////////////////////////////////////////////////////////////////////////
8578 /// Enable/Disable circularity for this tree.
8579 ///
8580 /// if maxEntries > 0 a maximum of maxEntries is kept in one buffer/basket
8581 /// per branch in memory.
8582 /// Note that when this function is called (maxEntries>0) the Tree
8583 /// must be empty or having only one basket per branch.
8584 /// if maxEntries <= 0 the tree circularity is disabled.
8585 ///
8586 /// #### NOTE 1:
8587 /// Circular Trees are interesting in online real time environments
8588 /// to store the results of the last maxEntries events.
8589 /// #### NOTE 2:
8590 /// Calling SetCircular with maxEntries <= 0 is necessary before
8591 /// merging circular Trees that have been saved on files.
8592 /// #### NOTE 3:
8593 /// SetCircular with maxEntries <= 0 is automatically called
8594 /// by TChain::Merge
8595 /// #### NOTE 4:
8596 /// A circular Tree can still be saved in a file. When read back,
8597 /// it is still a circular Tree and can be filled again.
8598 
8599 void TTree::SetCircular(Long64_t maxEntries)
8600 {
8601  if (maxEntries <= 0) {
8602  // Disable circularity.
8603  fMaxEntries = 1000000000;
8604  fMaxEntries *= 1000;
8605  ResetBit(kCircular);
8606  //in case the Tree was originally created in gROOT, the branch
8607  //compression level was set to -1. If the Tree is now associated to
8608  //a file, reset the compression level to the file compression level
8609  if (fDirectory) {
8610  TFile* bfile = fDirectory->GetFile();
8611  Int_t compress = ROOT::RCompressionSetting::EDefaults::kUseCompiledDefault;
8612  if (bfile) {
8613  compress = bfile->GetCompressionSettings();
8614  }
8615  Int_t nb = fBranches.GetEntriesFast();
8616  for (Int_t i = 0; i < nb; i++) {
8617  TBranch* branch = (TBranch*) fBranches.UncheckedAt(i);
8618  branch->SetCompressionSettings(compress);
8619  }
8620  }
8621  } else {
8622  // Enable circularity.
8623  fMaxEntries = maxEntries;
8624  SetBit(kCircular);
8625  }
8626 }
8627 
8628 ////////////////////////////////////////////////////////////////////////////////
8629 /// Set the debug level and the debug range.
8630 ///
8631 /// For entries in the debug range, the functions TBranchElement::Fill
8632 /// and TBranchElement::GetEntry will print the number of bytes filled
8633 /// or read for each branch.
8634 
8635 void TTree::SetDebug(Int_t level, Long64_t min, Long64_t max)
8636 {
8637  fDebug = level;
8638  fDebugMin = min;
8639  fDebugMax = max;
8640 }
8641 
8642 ////////////////////////////////////////////////////////////////////////////////
8643 /// Update the default value for the branch's fEntryOffsetLen.
8644 /// If updateExisting is true, also update all the existing branches.
8645 /// If newdefault is less than 10, the new default value will be 10.
8646 
8647 void TTree::SetDefaultEntryOffsetLen(Int_t newdefault, Bool_t updateExisting)
8648 {
8649  if (newdefault < 10) {
8650  newdefault = 10;
8651  }
8652  fDefaultEntryOffsetLen = newdefault;
8653  if (updateExisting) {
8654  TIter next( GetListOfBranches() );
8655  TBranch *b;
8656  while ( ( b = (TBranch*)next() ) ) {
8657  b->SetEntryOffsetLen( newdefault, kTRUE );
8658  }
8659  if (fBranchRef) {
8660  fBranchRef->SetEntryOffsetLen( newdefault, kTRUE );
8661  }
8662  }
8663 }
8664 
8665 ////////////////////////////////////////////////////////////////////////////////
8666 /// Change the tree's directory.
8667 ///
8668 /// Remove reference to this tree from current directory and
8669 /// add reference to new directory dir. The dir parameter can
8670 /// be 0 in which case the tree does not belong to any directory.
8671 ///
8672 
8673 void TTree::SetDirectory(TDirectory* dir)
8674 {
8675  if (fDirectory == dir) {
8676  return;
8677  }
8678  if (fDirectory) {
8679  fDirectory->Remove(this);
8680 
8681  // Delete or move the file cache if it points to this Tree
8682  TFile *file = fDirectory->GetFile();
8683  MoveReadCache(file,dir);
8684  }
8685  fDirectory = dir;
8686  if (fDirectory) {
8687  fDirectory->Append(this);
8688  }
8689  TFile* file = 0;
8690  if (fDirectory) {
8691  file = fDirectory->GetFile();
8692  }
8693  if (fBranchRef) {
8694  fBranchRef->SetFile(file);
8695  }
8696  TBranch* b = 0;
8697  TIter next(GetListOfBranches());
8698  while((b = (TBranch*) next())) {
8699  b->SetFile(file);
8700  }
8701 }
8702 
8703 ////////////////////////////////////////////////////////////////////////////////
8704 /// Change number of entries in the tree.
8705 ///
8706 /// If n >= 0, set number of entries in the tree = n.
8707 ///
8708 /// If n < 0, set number of entries in the tree to match the
8709 /// number of entries in each branch. (default for n is -1)
8710 ///
8711 /// This function should be called only when one fills each branch
8712 /// independently via TBranch::Fill without calling TTree::Fill.
8713 /// Calling TTree::SetEntries() make sense only if the number of entries
8714 /// in each branch is identical, a warning is issued otherwise.
8715 /// The function returns the number of entries.
8716 ///
8717 
8718 Long64_t TTree::SetEntries(Long64_t n)
8719 {
8720  // case 1 : force number of entries to n
8721  if (n >= 0) {
8722  fEntries = n;
8723  return n;
8724  }
8725 
8726  // case 2; compute the number of entries from the number of entries in the branches
8727  TBranch* b(nullptr), *bMin(nullptr), *bMax(nullptr);
8728  Long64_t nMin = kMaxEntries;
8729  Long64_t nMax = 0;
8730  TIter next(GetListOfBranches());
8731  while((b = (TBranch*) next())){
8732  Long64_t n2 = b->GetEntries();
8733  if (!bMin || n2 < nMin) {
8734  nMin = n2;
8735  bMin = b;
8736  }
8737  if (!bMax || n2 > nMax) {
8738  nMax = n2;
8739  bMax = b;
8740  }
8741  }
8742  if (bMin && nMin != nMax) {
8743  Warning("SetEntries", "Tree branches have different numbers of entries, eg %s has %lld entries while %s has %lld entries.",
8744  bMin->GetName(), nMin, bMax->GetName(), nMax);
8745  }
8746  fEntries = nMax;
8747  return fEntries;
8748 }
8749 
8750 ////////////////////////////////////////////////////////////////////////////////
8751 /// Set an EntryList
8752 
8753 void TTree::SetEntryList(TEntryList *enlist, Option_t * /*opt*/)
8754 {
8755  if (fEntryList) {
8756  //check if the previous entry list is owned by the tree
8757  if (fEntryList->TestBit(kCanDelete)){
8758  delete fEntryList;
8759  }
8760  }
8761  fEventList = 0;
8762  if (!enlist) {
8763  fEntryList = 0;
8764  return;
8765  }
8766  fEntryList = enlist;
8767  fEntryList->SetTree(this);
8768 
8769 }
8770 
8771 ////////////////////////////////////////////////////////////////////////////////
8772 /// This function transfroms the given TEventList into a TEntryList
8773 /// The new TEntryList is owned by the TTree and gets deleted when the tree
8774 /// is deleted. This TEntryList can be returned by GetEntryList() function.
8775 
8776 void TTree::SetEventList(TEventList *evlist)
8777 {
8778  fEventList = evlist;
8779  if (fEntryList){
8780  if (fEntryList->TestBit(kCanDelete)) {
8781  TEntryList *tmp = fEntryList;
8782  fEntryList = 0; // Avoid problem with RecursiveRemove.
8783  delete tmp;
8784  } else {
8785  fEntryList = 0;
8786  }
8787  }
8788 
8789  if (!evlist) {
8790  fEntryList = 0;
8791  fEventList = 0;
8792  return;
8793  }
8794 
8795  fEventList = evlist;
8796  char enlistname[100];
8797  snprintf(enlistname,100, "%s_%s", evlist->GetName(), "entrylist");
8798  fEntryList = new TEntryList(enlistname, evlist->GetTitle());
8799  fEntryList->SetDirectory(0); // We own this.
8800  Int_t nsel = evlist->GetN();
8801  fEntryList->SetTree(this);
8802  Long64_t entry;
8803  for (Int_t i=0; i<nsel; i++){
8804  entry = evlist->GetEntry(i);
8805  fEntryList->Enter(entry);
8806  }
8807  fEntryList->SetReapplyCut(evlist->GetReapplyCut());
8808  fEntryList->SetBit(kCanDelete, kTRUE);
8809 }
8810 
8811 ////////////////////////////////////////////////////////////////////////////////
8812 /// Set number of entries to estimate variable limits.
8813 /// If n is -1, the estimate is set to be the current maximum
8814 /// for the tree (i.e. GetEntries() + 1)
8815 /// If n is less than -1, the behavior is undefined.
8816 
8817 void TTree::SetEstimate(Long64_t n /* = 1000000 */)
8818 {
8819  if (n == 0) {
8820  n = 10000;
8821  } else if (n < 0) {
8822  n = fEntries - n;
8823  }
8824  fEstimate = n;
8825  GetPlayer();
8826  if (fPlayer) {
8827  fPlayer->SetEstimate(n);
8828  }
8829 }
8830 
8831 ////////////////////////////////////////////////////////////////////////////////
8832 /// Provide the end-user with the ability to enable/disable various experimental
8833 /// IO features for this TTree.
8834 ///
8835 /// Returns all the newly-set IO settings.
8836 
8837 ROOT::TIOFeatures TTree::SetIOFeatures(const ROOT::TIOFeatures &features)
8838 {
8839  // Purposely ignore all unsupported bits; TIOFeatures implementation already warned the user about the
8840  // error of their ways; this is just a safety check.
8841  UChar_t featuresRequested = features.GetFeatures() & static_cast<UChar_t>(TBasket::EIOBits::kSupported);
8842 
8843  UChar_t curFeatures = fIOFeatures.GetFeatures();
8844  UChar_t newFeatures = ~curFeatures & featuresRequested;
8845  curFeatures |= newFeatures;
8846  fIOFeatures.Set(curFeatures);
8847 
8848  ROOT::TIOFeatures newSettings(newFeatures);
8849  return newSettings;
8850 }
8851 
8852 ////////////////////////////////////////////////////////////////////////////////
8853 /// Set fFileNumber to number.
8854 /// fFileNumber is used by TTree::Fill to set the file name
8855 /// for a new file to be created when the current file exceeds fgTreeMaxSize.
8856 /// (see TTree::ChangeFile)
8857 /// if fFileNumber=10, the new file name will have a suffix "_11",
8858 /// ie, fFileNumber is incremented before setting the file name
8859 
8860 void TTree::SetFileNumber(Int_t number)
8861 {
8862  if (fFileNumber < 0) {
8863  Warning("SetFileNumber", "file number must be positive. Set to 0");
8864  fFileNumber = 0;
8865  return;
8866  }
8867  fFileNumber = number;
8868 }
8869 
8870 ////////////////////////////////////////////////////////////////////////////////
8871 /// Set all the branches in this TTree to be in decomposed object mode
8872 /// (also known as MakeClass mode).
8873 ///
8874 /// For MakeClass mode 0, the TTree expects the address where the data is stored
8875 /// to be set by either the user or the TTree to the address of a full object
8876 /// through the top level branch.
8877 /// For MakeClass mode 1, this address is expected to point to a numerical type
8878 /// or C-style array (variable or not) of numerical type, representing the
8879 /// primitive data members.
8880 /// The function's primary purpose is to allow the user to access the data
8881 /// directly with numerical type variable rather than having to have the original
8882 /// set of classes (or a reproduction thereof).
8883 
8884 void TTree::SetMakeClass(Int_t make)
8885 {
8886  fMakeClass = make;
8887 
8888  Int_t nb = fBranches.GetEntriesFast();
8889  for (Int_t i = 0; i < nb; ++i) {
8890  TBranch* branch = (TBranch*) fBranches.UncheckedAt(i);
8891  branch->SetMakeClass(make);
8892  }
8893 }
8894 
8895 ////////////////////////////////////////////////////////////////////////////////
8896 /// Set the maximum size in bytes of a Tree file (static function).
8897 /// The default size is 100000000000LL, ie 100 Gigabytes.
8898 ///
8899 /// In TTree::Fill, when the file has a size > fgMaxTreeSize,
8900 /// the function closes the current file and starts writing into
8901 /// a new file with a name of the style "file_1.root" if the original
8902 /// requested file name was "file.root".
8903 
8904 void TTree::SetMaxTreeSize(Long64_t maxsize)
8905 {
8906  fgMaxTreeSize = maxsize;
8907 }
8908 
8909 ////////////////////////////////////////////////////////////////////////////////
8910 /// Change the name of this tree.
8911 
8912 void TTree::SetName(const char* name)
8913 {
8914  if (gPad) {
8915  gPad->Modified();
8916  }
8917  // Trees are named objects in a THashList.
8918  // We must update hashlists if we change the name.
8919  TFile *file = 0;
8920  TTreeCache *pf = 0;
8921  if (fDirectory) {
8922  fDirectory->Remove(this);
8923  if ((file = GetCurrentFile())) {
8924  pf = GetReadCache(file);
8925  file->SetCacheRead(0,this,TFile::kDoNotDisconnect);
8926  }
8927  }
8928  // This changes our hash value.
8929  fName = name;
8930  if (fDirectory) {
8931  fDirectory->Append(this);
8932  if (pf) {
8933  file->SetCacheRead(pf,this,TFile::kDoNotDisconnect);
8934  }
8935  }
8936 }
8937 
8938 ////////////////////////////////////////////////////////////////////////////////
8939 /// Change the name and title of this tree.
8940 
8941 void TTree::SetObject(const char* name, const char* title)
8942 {
8943  if (gPad) {
8944  gPad->Modified();
8945  }
8946 
8947  // Trees are named objects in a THashList.
8948  // We must update hashlists if we change the name
8949  TFile *file = 0;
8950  TTreeCache *pf = 0;
8951  if (fDirectory) {
8952  fDirectory->Remove(this);
8953  if ((file = GetCurrentFile())) {
8954  pf = GetReadCache(file);
8955  file->SetCacheRead(0,this,TFile::kDoNotDisconnect);
8956  }
8957  }
8958  // This changes our hash value.
8959  fName = name;
8960  fTitle = title;
8961  if (fDirectory) {
8962  fDirectory->Append(this);
8963  if (pf) {
8964  file->SetCacheRead(pf,this,TFile::kDoNotDisconnect);
8965  }
8966  }
8967 }
8968 
8969 ////////////////////////////////////////////////////////////////////////////////
8970 /// Enable or disable parallel unzipping of Tree buffers.
8971 
8972 void TTree::SetParallelUnzip(Bool_t opt, Float_t RelSize)
8973 {
8974 #ifdef R__USE_IMT
8975  if (GetTree() == 0) {
8976  LoadTree(GetReadEntry());
8977  if (!GetTree())
8978  return;
8979  }
8980  if (GetTree() != this) {
8981  GetTree()->SetParallelUnzip(opt, RelSize);
8982  return;
8983  }
8984  TFile* file = GetCurrentFile();
8985  if (!file)
8986  return;
8987 
8988  TTreeCache* pf = GetReadCache(file);
8989  if (pf && !( opt ^ (nullptr != dynamic_cast<TTreeCacheUnzip*>(pf)))) {
8990  // done with opt and type are in agreement.
8991  return;
8992  }
8993  delete pf;
8994  auto cacheSize = GetCacheAutoSize(kTRUE);
8995  if (opt) {
8996  auto unzip = new TTreeCacheUnzip(this, cacheSize);
8997  unzip->SetUnzipBufferSize( Long64_t(cacheSize * RelSize) );
8998  } else {
8999  pf = new TTreeCache(this, cacheSize);
9000  }
9001 #else
9002  (void)opt;
9003  (void)RelSize;
9004 #endif
9005 }
9006 
9007 ////////////////////////////////////////////////////////////////////////////////
9008 /// Set perf stats
9009 
9010 void TTree::SetPerfStats(TVirtualPerfStats *perf)
9011 {
9012  fPerfStats = perf;
9013 }
9014 
9015 ////////////////////////////////////////////////////////////////////////////////
9016 /// The current TreeIndex is replaced by the new index.
9017 /// Note that this function does not delete the previous index.
9018 /// This gives the possibility to play with more than one index, e.g.,
9019 /// ~~~ {.cpp}
9020 /// TVirtualIndex* oldIndex = tree.GetTreeIndex();
9021 /// tree.SetTreeIndex(newIndex);
9022 /// tree.Draw();
9023 /// tree.SetTreeIndex(oldIndex);
9024 /// tree.Draw(); etc
9025 /// ~~~
9026 
9027 void TTree::SetTreeIndex(TVirtualIndex* index)
9028 {
9029  if (fTreeIndex) {
9030  fTreeIndex->SetTree(0);
9031  }
9032  fTreeIndex = index;
9033 }
9034 
9035 ////////////////////////////////////////////////////////////////////////////////
9036 /// Set tree weight.
9037 ///
9038 /// The weight is used by TTree::Draw to automatically weight each
9039 /// selected entry in the resulting histogram.
9040 ///
9041 /// For example the equivalent of:
9042 /// ~~~ {.cpp}
9043 /// T.Draw("x", "w")
9044 /// ~~~
9045 /// is:
9046 /// ~~~ {.cpp}
9047 /// T.SetWeight(w);
9048 /// T.Draw("x");
9049 /// ~~~
9050 /// This function is redefined by TChain::SetWeight. In case of a
9051 /// TChain, an option "global" may be specified to set the same weight
9052 /// for all trees in the TChain instead of the default behaviour
9053 /// using the weights of each tree in the chain (see TChain::SetWeight).
9054 
9055 void TTree::SetWeight(Double_t w, Option_t*)
9056 {
9057  fWeight = w;
9058 }
9059 
9060 ////////////////////////////////////////////////////////////////////////////////
9061 /// Print values of all active leaves for entry.
9062 ///
9063 /// - if entry==-1, print current entry (default)
9064 /// - if a leaf is an array, a maximum of lenmax elements is printed.
9065 
9066 void TTree::Show(Long64_t entry, Int_t lenmax)
9067 {
9068  if (entry != -1) {
9069  Int_t ret = LoadTree(entry);
9070  if (ret == -2) {
9071  Error("Show()", "Cannot read entry %lld (entry does not exist)", entry);
9072  return;
9073  } else if (ret == -1) {
9074  Error("Show()", "Cannot read entry %lld (I/O error)", entry);
9075  return;
9076  }
9077  ret = GetEntry(entry);
9078  if (ret == -1) {
9079  Error("Show()", "Cannot read entry %lld (I/O error)", entry);
9080  return;
9081  } else if (ret == 0) {
9082  Error("Show()", "Cannot read entry %lld (no data read)", entry);
9083  return;
9084  }
9085  }
9086  printf("======> EVENT:%lld\n", fReadEntry);
9087  TObjArray* leaves = GetListOfLeaves();
9088  Int_t nleaves = leaves->GetEntriesFast();
9089  Int_t ltype;
9090  for (Int_t i = 0; i < nleaves; i++) {
9091  TLeaf* leaf = (TLeaf*) leaves->UncheckedAt(i);
9092  TBranch* branch = leaf->GetBranch();
9093  if (branch->TestBit(kDoNotProcess)) {
9094  continue;
9095  }
9096  Int_t len = leaf->GetLen();
9097  if (len <= 0) {
9098  continue;
9099  }
9100  len = TMath::Min(len, lenmax);
9101  if (leaf->IsA() == TLeafElement::Class()) {
9102  leaf->PrintValue(lenmax);
9103  continue;
9104  }
9105  if (branch->GetListOfBranches()->GetEntriesFast() > 0) {
9106  continue;
9107  }
9108  ltype = 10;
9109  if (leaf->IsA() == TLeafF::Class()) {
9110  ltype = 5;
9111  }
9112  if (leaf->IsA() == TLeafD::Class()) {
9113  ltype = 5;
9114  }
9115  if (leaf->IsA() == TLeafC::Class()) {
9116  len = 1;
9117  ltype = 5;
9118  };
9119  printf(" %-15s = ", leaf->GetName());
9120  for (Int_t l = 0; l < len; l++) {
9121  leaf->PrintValue(l);
9122  if (l == (len - 1)) {
9123  printf("\n");
9124  continue;
9125  }
9126  printf(", ");
9127  if ((l % ltype) == 0) {
9128  printf("\n ");
9129  }
9130  }
9131  }
9132 }
9133 
9134 ////////////////////////////////////////////////////////////////////////////////
9135 /// Start the TTreeViewer on this tree.
9136 ///
9137 /// - ww is the width of the canvas in pixels
9138 /// - wh is the height of the canvas in pixels
9139 
9140 void TTree::StartViewer()
9141 {
9142  GetPlayer();
9143  if (fPlayer) {
9144  fPlayer->StartViewer(600, 400);
9145  }
9146 }
9147 
9148 ////////////////////////////////////////////////////////////////////////////////
9149 /// Stop the cache learning phase
9150 ///
9151 /// Returns:
9152 /// - 0 learning phase stopped or not active
9153 /// - -1 on error
9154 
9155 Int_t TTree::StopCacheLearningPhase()
9156 {
9157  if (!GetTree()) {
9158  if (LoadTree(0)<0) {
9159  Error("StopCacheLearningPhase","Could not load a tree");
9160  return -1;
9161  }
9162  }
9163  if (GetTree()) {
9164  if (GetTree() != this) {
9165  return GetTree()->StopCacheLearningPhase();
9166  }
9167  } else {
9168  Error("StopCacheLearningPhase", "No tree is available. Could not stop cache learning phase");
9169  return -1;
9170  }
9171 
9172  TFile *f = GetCurrentFile();
9173  if (!f) {
9174  Error("StopCacheLearningPhase", "No file is available. Could not stop cache learning phase");
9175  return -1;
9176  }
9177  TTreeCache *tc = GetReadCache(f,kTRUE);
9178  if (!tc) {
9179  Error("StopCacheLearningPhase", "No cache is available. Could not stop learning phase");
9180  return -1;
9181  }
9182  tc->StopLearningPhase();
9183  return 0;
9184 }
9185 
9186 ////////////////////////////////////////////////////////////////////////////////
9187 /// Set the fTree member for all branches and sub branches.
9188 
9189 static void TBranch__SetTree(TTree *tree, TObjArray &branches)
9190 {
9191  Int_t nb = branches.GetEntriesFast();
9192  for (Int_t i = 0; i < nb; ++i) {
9193  TBranch* br = (TBranch*) branches.UncheckedAt(i);
9194  br->SetTree(tree);
9195 
9196  Int_t nBaskets = br->GetListOfBaskets()->GetEntries();
9197  Int_t writeBasket = br->GetWriteBasket();
9198  for (Int_t j=writeBasket,n=0;j>=0 && n<nBaskets;--j) {
9199  TBasket *bk = (TBasket*)br->GetListOfBaskets()->UncheckedAt(j);
9200  if (bk) {
9201  tree->IncrementTotalBuffers(bk->GetBufferSize());
9202  ++n;
9203  }
9204  }
9205 
9206  TBranch__SetTree(tree,*br->GetListOfBranches());
9207  }
9208 }
9209 
9210 ////////////////////////////////////////////////////////////////////////////////
9211 /// Set the fTree member for all friend elements.
9212 
9213 void TFriendElement__SetTree(TTree *tree, TList *frlist)
9214 {
9215  if (frlist) {
9216  TObjLink *lnk = frlist->FirstLink();
9217  while (lnk) {
9218  TFriendElement *elem = (TFriendElement*)lnk->GetObject();
9219  elem->fParentTree = tree;
9220  lnk = lnk->Next();
9221  }
9222  }
9223 }
9224 
9225 ////////////////////////////////////////////////////////////////////////////////
9226 /// Stream a class object.
9227 
9228 void TTree::Streamer(TBuffer& b)
9229 {
9230  if (b.IsReading()) {
9231  UInt_t R__s, R__c;
9232  if (fDirectory) {
9233  fDirectory->Remove(this);
9234  //delete the file cache if it points to this Tree
9235  TFile *file = fDirectory->GetFile();
9236  MoveReadCache(file,0);
9237  }
9238  fDirectory = 0;
9239  fCacheDoAutoInit = kTRUE;
9240  fCacheUserSet = kFALSE;
9241  Version_t R__v = b.ReadVersion(&R__s, &R__c);
9242  if (R__v > 4) {
9243  b.ReadClassBuffer(TTree::Class(), this, R__v, R__s, R__c);
9244 
9245  fBranches.SetOwner(kTRUE); // True needed only for R__v < 19 and most R__v == 19
9246 
9247  if (fBranchRef) fBranchRef->SetTree(this);
9248  TBranch__SetTree(this,fBranches);
9249  TFriendElement__SetTree(this,fFriends);
9250 
9251  if (fTreeIndex) {
9252  fTreeIndex->SetTree(this);
9253  }
9254  if (fIndex.fN) {
9255  Warning("Streamer", "Old style index in this tree is deleted. Rebuild the index via TTree::BuildIndex");
9256  fIndex.Set(0);
9257  fIndexValues.Set(0);
9258  }
9259  if (fEstimate <= 10000) {
9260  fEstimate = 1000000;
9261  }
9262 
9263  if (fNClusterRange) {
9264  // The I/O allocated just enough memory to hold the
9265  // current set of ranges.
9266  fMaxClusterRange = fNClusterRange;
9267  }
9268  if (GetCacheAutoSize() != 0) {
9269  // a cache will be automatically created.
9270  // No need for TTreePlayer::Process to enable the cache
9271  fCacheSize = 0;
9272  } else if (fAutoFlush < 0) {
9273  // If there is no autoflush set, let's keep the cache completely
9274  // disable by default for now.
9275  fCacheSize = fAutoFlush;
9276  } else if (fAutoFlush != 0) {
9277  // Estimate the cluster size.
9278  // This will allow TTree::Process to enable the cache.
9279  Long64_t zipBytes = GetZipBytes();
9280  Long64_t totBytes = GetTotBytes();
9281  if (zipBytes != 0) {
9282  fCacheSize = fAutoFlush*(zipBytes/fEntries);
9283  } else if (totBytes != 0) {
9284  fCacheSize = fAutoFlush*(totBytes/fEntries);
9285  } else {
9286  fCacheSize = 30000000;
9287  }
9288  if (fCacheSize >= (INT_MAX / 4)) {
9289  fCacheSize = INT_MAX / 4;
9290  } else if (fCacheSize == 0) {
9291  fCacheSize = 30000000;
9292  }
9293  } else {
9294  fCacheSize = 0;
9295  }
9296  ResetBit(kMustCleanup);
9297  return;
9298  }
9299  //====process old versions before automatic schema evolution
9300  Stat_t djunk;
9301  Int_t ijunk;
9302  TNamed::Streamer(b);
9303  TAttLine::Streamer(b);
9304  TAttFill::Streamer(b);
9305  TAttMarker::Streamer(b);
9306  b >> fScanField;
9307  b >> ijunk; fMaxEntryLoop = (Long64_t)ijunk;
9308  b >> ijunk; fMaxVirtualSize = (Long64_t)ijunk;
9309  b >> djunk; fEntries = (Long64_t)djunk;
9310  b >> djunk; fTotBytes = (Long64_t)djunk;
9311  b >> djunk; fZipBytes = (Long64_t)djunk;
9312  b >> ijunk; fAutoSave = (Long64_t)ijunk;
9313  b >> ijunk; fEstimate = (Long64_t)ijunk;
9314  if (fEstimate <= 10000) fEstimate = 1000000;
9315  fBranches.Streamer(b);
9316  if (fBranchRef) fBranchRef->SetTree(this);
9317  TBranch__SetTree(this,fBranches);
9318  fLeaves.Streamer(b);
9319  fSavedBytes = fTotBytes;
9320  if (R__v > 1) fIndexValues.Streamer(b);
9321  if (R__v > 2) fIndex.Streamer(b);
9322  if (R__v > 3) {
9323  TList OldInfoList;
9324  OldInfoList.Streamer(b);
9325  OldInfoList.Delete();
9326  }
9327  fNClusterRange = 0;
9328  fDefaultEntryOffsetLen = 1000;
9329  ResetBit(kMustCleanup);
9330  b.CheckByteCount(R__s, R__c, TTree::IsA());
9331  //====end of old versions
9332  } else {
9333  if (fBranchRef) {
9334  fBranchRef->Clear();
9335  }
9336  TRefTable *table = TRefTable::GetRefTable();
9337  if (table) TRefTable::SetRefTable(0);
9338 
9339  b.WriteClassBuffer(TTree::Class(), this);
9340 
9341  if (table) TRefTable::SetRefTable(table);
9342  }
9343 }
9344 
9345 ////////////////////////////////////////////////////////////////////////////////
9346 /// Unbinned fit of one or more variable(s) from a tree.
9347 ///
9348 /// funcname is a TF1 function.
9349 ///
9350 /// See TTree::Draw for explanations of the other parameters.
9351 ///
9352 /// Fit the variable varexp using the function funcname using the
9353 /// selection cuts given by selection.
9354 ///
9355 /// The list of fit options is given in parameter option.
9356 ///
9357 /// - option = "Q" Quiet mode (minimum printing)
9358 /// - option = "V" Verbose mode (default is between Q and V)
9359 /// - option = "E" Perform better Errors estimation using Minos technique
9360 /// - option = "M" More. Improve fit results
9361 ///
9362 /// You can specify boundary limits for some or all parameters via
9363 /// ~~~ {.cpp}
9364 /// func->SetParLimits(p_number, parmin, parmax);
9365 /// ~~~
9366 /// if parmin>=parmax, the parameter is fixed
9367 ///
9368 /// Note that you are not forced to fix the limits for all parameters.
9369 /// For example, if you fit a function with 6 parameters, you can do:
9370 /// ~~~ {.cpp}
9371 /// func->SetParameters(0,3.1,1.e-6,0.1,-8,100);
9372 /// func->SetParLimits(4,-10,-4);
9373 /// func->SetParLimits(5, 1,1);
9374 /// ~~~
9375 /// With this setup:
9376 ///
9377 /// - Parameters 0->3 can vary freely
9378 /// - Parameter 4 has boundaries [-10,-4] with initial value -8
9379 /// - Parameter 5 is fixed to 100.
9380 ///
9381 /// For the fit to be meaningful, the function must be self-normalized.
9382 ///
9383 /// i.e. It must have the same integral regardless of the parameter
9384 /// settings. Otherwise the fit will effectively just maximize the
9385 /// area.
9386 ///
9387 /// It is mandatory to have a normalization variable
9388 /// which is fixed for the fit. e.g.
9389 /// ~~~ {.cpp}
9390 /// TF1* f1 = new TF1("f1", "gaus(0)/sqrt(2*3.14159)/[2]", 0, 5);
9391 /// f1->SetParameters(1, 3.1, 0.01);
9392 /// f1->SetParLimits(0, 1, 1); // fix the normalization parameter to 1
9393 /// data->UnbinnedFit("f1", "jpsimass", "jpsipt>3.0");
9394 /// ~~~
9395 /// 1, 2 and 3 Dimensional fits are supported. See also TTree::Fit
9396 ///
9397 /// Return status:
9398 ///
9399 /// - The function return the status of the fit in the following form
9400 /// fitResult = migradResult + 10*minosResult + 100*hesseResult + 1000*improveResult
9401 /// - The fitResult is 0 is the fit is OK.
9402 /// - The fitResult is negative in case of an error not connected with the fit.
9403 /// - The number of entries used in the fit can be obtained via mytree.GetSelectedRows();
9404 /// - If the number of selected entries is null the function returns -1
9405 
9406 Int_t TTree::UnbinnedFit(const char* funcname, const char* varexp, const char* selection, Option_t* option, Long64_t nentries, Long64_t firstentry)
9407 {
9408  GetPlayer();
9409  if (fPlayer) {
9410  return fPlayer->UnbinnedFit(funcname, varexp, selection, option, nentries, firstentry);
9411  }
9412  return -1;
9413 }
9414 
9415 ////////////////////////////////////////////////////////////////////////////////
9416 /// Replace current attributes by current style.
9417 
9418 void TTree::UseCurrentStyle()
9419 {
9420  if (gStyle->IsReading()) {
9421  SetFillColor(gStyle->GetHistFillColor());
9422  SetFillStyle(gStyle->GetHistFillStyle());
9423  SetLineColor(gStyle->GetHistLineColor());
9424  SetLineStyle(gStyle->GetHistLineStyle());
9425  SetLineWidth(gStyle->GetHistLineWidth());
9426  SetMarkerColor(gStyle->GetMarkerColor());
9427  SetMarkerStyle(gStyle->GetMarkerStyle());
9428  SetMarkerSize(gStyle->GetMarkerSize());
9429  } else {
9430  gStyle->SetHistFillColor(GetFillColor());
9431  gStyle->SetHistFillStyle(GetFillStyle());
9432  gStyle->SetHistLineColor(GetLineColor());
9433  gStyle->SetHistLineStyle(GetLineStyle());
9434  gStyle->SetHistLineWidth(GetLineWidth());
9435  gStyle->SetMarkerColor(GetMarkerColor());
9436  gStyle->SetMarkerStyle(GetMarkerStyle());
9437  gStyle->SetMarkerSize(GetMarkerSize());
9438  }
9439 }
9440 
9441 ////////////////////////////////////////////////////////////////////////////////
9442 /// Write this object to the current directory. For more see TObject::Write
9443 /// If option & kFlushBasket, call FlushBasket before writing the tree.
9444 
9445 Int_t TTree::Write(const char *name, Int_t option, Int_t bufsize) const
9446 {
9447  FlushBasketsImpl();
9448  return TObject::Write(name, option, bufsize);
9449 }
9450 
9451 ////////////////////////////////////////////////////////////////////////////////
9452 /// Write this object to the current directory. For more see TObject::Write
9453 /// If option & kFlushBasket, call FlushBasket before writing the tree.
9454 
9455 Int_t TTree::Write(const char *name, Int_t option, Int_t bufsize)
9456 {
9457  return ((const TTree*)this)->Write(name, option, bufsize);
9458 }
9459 
9460 ////////////////////////////////////////////////////////////////////////////////
9461 /// \class TTreeFriendLeafIter
9462 ///
9463 /// Iterator on all the leaves in a TTree and its friend
9464 
9465 ClassImp(TTreeFriendLeafIter);
9466 
9467 ////////////////////////////////////////////////////////////////////////////////
9468 /// Create a new iterator. By default the iteration direction
9469 /// is kIterForward. To go backward use kIterBackward.
9470 
9471 TTreeFriendLeafIter::TTreeFriendLeafIter(const TTree* tree, Bool_t dir)
9472 : fTree(const_cast<TTree*>(tree))
9473 , fLeafIter(0)
9474 , fTreeIter(0)
9475 , fDirection(dir)
9476 {
9477 }
9478 
9479 ////////////////////////////////////////////////////////////////////////////////
9480 /// Copy constructor. Does NOT copy the 'cursor' location!
9481 
9482 TTreeFriendLeafIter::TTreeFriendLeafIter(const TTreeFriendLeafIter& iter)
9483 : TIterator(iter)
9484 , fTree(iter.fTree)
9485 , fLeafIter(0)
9486 , fTreeIter(0)
9487 , fDirection(iter.fDirection)
9488 {
9489 }
9490 
9491 ////////////////////////////////////////////////////////////////////////////////
9492 /// Overridden assignment operator. Does NOT copy the 'cursor' location!
9493 
9494 TIterator& TTreeFriendLeafIter::operator=(const TIterator& rhs)
9495 {
9496  if (this != &rhs && rhs.IsA() == TTreeFriendLeafIter::Class()) {
9497  const TTreeFriendLeafIter &rhs1 = (const TTreeFriendLeafIter &)rhs;
9498  fDirection = rhs1.fDirection;
9499  }
9500  return *this;
9501 }
9502 
9503 ////////////////////////////////////////////////////////////////////////////////
9504 /// Overridden assignment operator. Does NOT copy the 'cursor' location!
9505 
9506 TTreeFriendLeafIter& TTreeFriendLeafIter::operator=(const TTreeFriendLeafIter& rhs)
9507 {
9508  if (this != &rhs) {
9509  fDirection = rhs.fDirection;
9510  }
9511  return *this;
9512 }
9513 
9514 ////////////////////////////////////////////////////////////////////////////////
9515 /// Go the next friend element
9516 
9517 TObject* TTreeFriendLeafIter::Next()
9518 {
9519  if (!fTree) return 0;
9520 
9521  TObject * next;
9522  TTree * nextTree;
9523 
9524  if (!fLeafIter) {
9525  TObjArray *list = fTree->GetListOfLeaves();
9526  if (!list) return 0; // Can happen with an empty chain.
9527  fLeafIter = list->MakeIterator(fDirection);
9528  if (!fLeafIter) return 0;
9529  }
9530 
9531  next = fLeafIter->Next();
9532  if (!next) {
9533  if (!fTreeIter) {
9534  TCollection * list = fTree->GetListOfFriends();
9535  if (!list) return next;
9536  fTreeIter = list->MakeIterator(fDirection);
9537  if (!fTreeIter) return 0;
9538  }
9539  TFriendElement * nextFriend = (TFriendElement*) fTreeIter->Next();
9540  ///nextTree = (TTree*)fTreeIter->Next();
9541  if (nextFriend) {
9542  nextTree = const_cast<TTree*>(nextFriend->GetTree());
9543  if (!nextTree) return Next();
9544  SafeDelete(fLeafIter);
9545  fLeafIter = nextTree->GetListOfLeaves()->MakeIterator(fDirection);
9546  if (!fLeafIter) return 0;
9547  next = fLeafIter->Next();
9548  }
9549  }
9550  return next;
9551 }
9552 
9553 ////////////////////////////////////////////////////////////////////////////////
9554 /// Returns the object option stored in the list.
9555 
9556 Option_t* TTreeFriendLeafIter::GetOption() const
9557 {
9558  if (fLeafIter) return fLeafIter->GetOption();
9559  return "";
9560 }