Logo ROOT   6.14/05
Reference Guide
TTree.cxx
Go to the documentation of this file.
1 // @(#)root/tree:$Id$
2 // Author: Rene Brun 12/01/96
3 
4 /*************************************************************************
5  * Copyright (C) 1995-2000, Rene Brun and Fons Rademakers. *
6  * All rights reserved. *
7  * *
8  * For the licensing terms see $ROOTSYS/LICENSE. *
9  * For the list of contributors see $ROOTSYS/README/CREDITS. *
10  *************************************************************************/
11 /**
12  \defgroup tree Tree Library
13 
14  To store large quantities of same-class objects, ROOT provides the TTree and
15  TNtuple classes. The TTree class is optimized to
16  reduce disk space and enhance access speed. A TNtuple is a TTree that is limited
17  to only hold floating-point numbers; a TTree on the other hand can hold all kind
18  of data, such as objects or arrays in addition to all the simple types.
19 
20 */
21 
22 /** \class TTree
23 \ingroup tree
24 
25 A TTree object has a header with a name and a title.
26 
27 It consists of a list of independent branches (TBranch). Each branch has its own
28 definition and list of buffers. Branch buffers may be automatically written to
29 disk or kept in memory until the Tree attribute `fMaxVirtualSize` is reached.
30 Variables of one branch are written to the same buffer. A branch buffer is
31 automatically compressed if the file compression attribute is set (default).
32 
33 Branches may be written to different files (see TBranch::SetFile).
34 
35 The ROOT user can decide to make one single branch and serialize one object into
36 one single I/O buffer or to make several branches. Making one single branch and
37 one single buffer can be the right choice when one wants to process only a subset
38 of all entries in the tree. (you know for example the list of entry numbers you
39 want to process). Making several branches is particularly interesting in the
40 data analysis phase, when one wants to histogram some attributes of an object
41 (entry) without reading all the attributes.
42 ~~~ {.cpp}
43  TTree *tree = new TTree(name, title)
44 ~~~
45 Creates a Tree with name and title.
46 
47 Various kinds of branches can be added to a tree:
48 
49 - simple structures or list of variables. (may be for C or Fortran structures)
50 - any object (inheriting from TObject). (we expect this option be the most frequent)
51 - a ClonesArray. (a specialized object for collections of same class objects)
52 
53 
54 ## Case A
55 
56 ~~~ {.cpp}
57  TBranch *branch = tree->Branch(branchname, address, leaflist, bufsize)
58 ~~~
59 - address is the address of the first item of a structure
60 - leaflist is the concatenation of all the variable names and types
61  separated by a colon character :
62  The variable name and the variable type are separated by a
63  slash (/). The variable type must be 1 character. (Characters
64  after the first are legal and will be appended to the visible
65  name of the leaf, but have no effect.) If no type is given, the
66  type of the variable is assumed to be the same as the previous
67  variable. If the first variable does not have a type, it is
68  assumed of type F by default. The list of currently supported
69  types is given below:
70  - `C` : a character string terminated by the 0 character
71  - `B` : an 8 bit signed integer (`Char_t`)
72  - `b` : an 8 bit unsigned integer (`UChar_t`)
73  - `S` : a 16 bit signed integer (`Short_t`)
74  - `s` : a 16 bit unsigned integer (`UShort_t`)
75  - `I` : a 32 bit signed integer (`Int_t`)
76  - `i` : a 32 bit unsigned integer (`UInt_t`)
77  - `F` : a 32 bit floating point (`Float_t`)
78  - `D` : a 64 bit floating point (`Double_t`)
79  - `L` : a 64 bit signed integer (`Long64_t`)
80  - `l` : a 64 bit unsigned integer (`ULong64_t`)
81  - `O` : [the letter `o`, not a zero] a boolean (`Bool_t`)
82 - If the address points to a single numerical variable, the leaflist is optional:
83  int value;
84  `tree->Branch(branchname, &value);`
85 - If the address points to more than one numerical variable, we strongly recommend
86  that the variable be sorted in decreasing order of size. Any other order will
87  result in a non-portable (even between CINT and compiled code on the platform)
88  TTree (i.e. you will not be able to read it back on a platform with a different
89  padding strategy).
90 
91 
92 ## Case B
93 
94 ~~~ {.cpp}
95  TBranch *branch = tree->Branch(branchname, &p_object, bufsize, splitlevel)
96  TBranch *branch = tree->Branch(branchname, className, &p_object, bufsize, splitlevel)
97 ~~~
98 - p_object is a pointer to an object.
99 - If className is not specified, Branch uses the type of p_object to determine the
100  type of the object.
101 - If className is used to specify explicitly the object type, the className must
102  be of a type related to the one pointed to by the pointer. It should be either
103  a parent or derived class.
104 - if splitlevel=0, the object is serialized in the branch buffer.
105 - if splitlevel=1, this branch will automatically be split
106  into subbranches, with one subbranch for each data member or object
107  of the object itself. In case the object member is a TClonesArray,
108  the mechanism described in case C is applied to this array.
109 - if splitlevel=2 ,this branch will automatically be split
110  into subbranches, with one subbranch for each data member or object
111  of the object itself. In case the object member is a TClonesArray,
112  it is processed as a TObject*, only one branch.
113 
114 Note: The pointer whose address is passed to TTree::Branch must not
115  be destroyed (i.e. go out of scope) until the TTree is deleted or
116  TTree::ResetBranchAddress is called.
117 
118 Note: The pointer p_object must be initialized before calling TTree::Branch
119 - Do either:
120 ~~~ {.cpp}
121  MyDataClass* p_object = 0;
122  tree->Branch(branchname, &p_object);
123 ~~~
124 - Or:
125 ~~~ {.cpp}
126  MyDataClass* p_object = new MyDataClass;
127  tree->Branch(branchname, &p_object);
128 ~~~
129 Whether the pointer is set to zero or not, the ownership of the object
130 is not taken over by the TTree. I.e. even though an object will be allocated
131 by TTree::Branch if the pointer p_object is zero, the object will <b>not</b>
132 be deleted when the TTree is deleted.
133 
134 
135 ## Case C
136 
137 ~~~ {.cpp}
138  MyClass object;
139  TBranch *branch = tree->Branch(branchname, &object, bufsize, splitlevel)
140 ~~~
141 Note: The 2nd parameter must be the address of a valid object.
142  The object must not be destroyed (i.e. be deleted) until the TTree
143  is deleted or TTree::ResetBranchAddress is called.
144 
145 - if splitlevel=0, the object is serialized in the branch buffer.
146 - if splitlevel=1 (default), this branch will automatically be split
147  into subbranches, with one subbranch for each data member or object
148  of the object itself. In case the object member is a TClonesArray,
149  the mechanism described in case C is applied to this array.
150 - if splitlevel=2 ,this branch will automatically be split
151  into subbranches, with one subbranch for each data member or object
152  of the object itself. In case the object member is a TClonesArray,
153  it is processed as a TObject*, only one branch.
154 
155 
156 ## Case D
157 
158 ~~~ {.cpp}
159  TBranch *branch = tree->Branch(branchname,clonesarray, bufsize, splitlevel)
160  clonesarray is the address of a pointer to a TClonesArray.
161 ~~~
162 The TClonesArray is a direct access list of objects of the same class.
163 For example, if the TClonesArray is an array of TTrack objects,
164 this function will create one subbranch for each data member of
165 the object TTrack.
166 
167 
168 ## Case E
169 
170 ~~~ {.cpp}
171  TBranch *branch = tree->Branch( branchname, STLcollection, buffsize, splitlevel);
172 ~~~
173 STLcollection is the address of a pointer to std::vector, std::list,
174 std::deque, std::set or std::multiset containing pointers to objects.
175 If the splitlevel is a value bigger than 100 (TTree::kSplitCollectionOfPointers)
176 then the collection will be written in split mode, e.g. if it contains objects of
177 any types deriving from TTrack this function will sort the objects
178 based on their type and store them in separate branches in split
179 mode.
180 ~~~ {.cpp}
181  branch->SetAddress(Void *address)
182 ~~~
183 In case of dynamic structures changing with each entry for example, one must
184 redefine the branch address before filling the branch again.
185 This is done via the TBranch::SetAddress member function.
186 ~~~ {.cpp}
187  tree->Fill()
188 ~~~
189 loops on all defined branches and for each branch invokes the Fill function.
190 
191 See also the class TNtuple (a simple Tree with branches of floats)
192 and the class TNtupleD (a simple Tree with branches of doubles)
193 
194 ## Adding a Branch to an Existing Tree
195 
196 You may want to add a branch to an existing tree. For example,
197 if one variable in the tree was computed with a certain algorithm,
198 you may want to try another algorithm and compare the results.
199 One solution is to add a new branch, fill it, and save the tree.
200 The code below adds a simple branch to an existing tree.
201 Note the kOverwrite option in the Write method, it overwrites the
202 existing tree. If it is not specified, two copies of the tree headers
203 are saved.
204 ~~~ {.cpp}
205  void tree3AddBranch() {
206  TFile f("tree3.root", "update");
207 
208  Float_t new_v;
209  TTree *t3 = (TTree*)f->Get("t3");
210  TBranch *newBranch = t3->Branch("new_v", &new_v, "new_v/F");
211 
212  Long64_t nentries = t3->GetEntries(); // read the number of entries in the t3
213 
214  for (Long64_t i = 0; i < nentries; i++) {
215  new_v= gRandom->Gaus(0, 1);
216  newBranch->Fill();
217  }
218 
219  t3->Write("", TObject::kOverwrite); // save only the new version of the tree
220  }
221 ~~~
222 Adding a branch is often not possible because the tree is in a read-only
223 file and you do not have permission to save the modified tree with the
224 new branch. Even if you do have the permission, you risk losing the
225 original tree with an unsuccessful attempt to save the modification.
226 Since trees are usually large, adding a branch could extend it over the
227 2GB limit. In this case, the attempt to write the tree fails, and the
228 original data is erased.
229 In addition, adding a branch to a tree enlarges the tree and increases
230 the amount of memory needed to read an entry, and therefore decreases
231 the performance.
232 
233 For these reasons, ROOT offers the concept of friends for trees (and chains).
234 We encourage you to use TTree::AddFriend rather than adding a branch manually.
235 
236 Begin_Macro
237 ../../../tutorials/tree/tree.C
238 End_Macro
239 
240 ~~~ {.cpp}
241  // A simple example with histograms and a tree
242  //
243  // This program creates :
244  // - a one dimensional histogram
245  // - a two dimensional histogram
246  // - a profile histogram
247  // - a tree
248  //
249  // These objects are filled with some random numbers and saved on a file.
250 
251  #include "TFile.h"
252  #include "TH1.h"
253  #include "TH2.h"
254  #include "TProfile.h"
255  #include "TRandom.h"
256  #include "TTree.h"
257 
258  //__________________________________________________________________________
259  main(int argc, char **argv)
260  {
261  // Create a new ROOT binary machine independent file.
262  // Note that this file may contain any kind of ROOT objects, histograms,trees
263  // pictures, graphics objects, detector geometries, tracks, events, etc..
264  // This file is now becoming the current directory.
265  TFile hfile("htree.root","RECREATE","Demo ROOT file with histograms & trees");
266 
267  // Create some histograms and a profile histogram
268  TH1F *hpx = new TH1F("hpx","This is the px distribution",100,-4,4);
269  TH2F *hpxpy = new TH2F("hpxpy","py ps px",40,-4,4,40,-4,4);
270  TProfile *hprof = new TProfile("hprof","Profile of pz versus px",100,-4,4,0,20);
271 
272  // Define some simple structures
273  typedef struct {Float_t x,y,z;} POINT;
274  typedef struct {
275  Int_t ntrack,nseg,nvertex;
276  UInt_t flag;
277  Float_t temperature;
278  } EVENTN;
279  static POINT point;
280  static EVENTN eventn;
281 
282  // Create a ROOT Tree
283  TTree *tree = new TTree("T","An example of ROOT tree with a few branches");
284  tree->Branch("point",&point,"x:y:z");
285  tree->Branch("eventn",&eventn,"ntrack/I:nseg:nvertex:flag/i:temperature/F");
286  tree->Branch("hpx","TH1F",&hpx,128000,0);
287 
288  Float_t px,py,pz;
289  static Float_t p[3];
290 
291  // Here we start a loop on 1000 events
292  for ( Int_t i=0; i<1000; i++) {
293  gRandom->Rannor(px,py);
294  pz = px*px + py*py;
295  Float_t random = gRandom->::Rndm(1);
296 
297  // Fill histograms
298  hpx->Fill(px);
299  hpxpy->Fill(px,py,1);
300  hprof->Fill(px,pz,1);
301 
302  // Fill structures
303  p[0] = px;
304  p[1] = py;
305  p[2] = pz;
306  point.x = 10*(random-1);;
307  point.y = 5*random;
308  point.z = 20*random;
309  eventn.ntrack = Int_t(100*random);
310  eventn.nseg = Int_t(2*eventn.ntrack);
311  eventn.nvertex = 1;
312  eventn.flag = Int_t(random+0.5);
313  eventn.temperature = 20+random;
314 
315  // Fill the tree. For each event, save the 2 structures and 3 objects
316  // In this simple example, the objects hpx, hprof and hpxpy are slightly
317  // different from event to event. We expect a big compression factor!
318  tree->Fill();
319  }
320  // End of the loop
321 
322  tree->Print();
323 
324  // Save all objects in this file
325  hfile.Write();
326 
327  // Close the file. Note that this is automatically done when you leave
328  // the application.
329  hfile.Close();
330 
331  return 0;
332 }
333 ~~~
334 */
335 
336 #include <ROOT/RConfig.h>
337 #include "TTree.h"
338 
339 #include "ROOT/TIOFeatures.hxx"
340 #include "TArrayC.h"
341 #include "TBufferFile.h"
342 #include "TBaseClass.h"
343 #include "TBasket.h"
344 #include "TBranchClones.h"
345 #include "TBranchElement.h"
346 #include "TBranchObject.h"
347 #include "TBranchRef.h"
348 #include "TBrowser.h"
349 #include "TClass.h"
350 #include "TClassEdit.h"
351 #include "TClonesArray.h"
352 #include "TCut.h"
353 #include "TDataMember.h"
354 #include "TDataType.h"
355 #include "TDirectory.h"
356 #include "TError.h"
357 #include "TEntryList.h"
358 #include "TEnv.h"
359 #include "TEventList.h"
360 #include "TFile.h"
361 #include "TFolder.h"
362 #include "TFriendElement.h"
363 #include "TInterpreter.h"
364 #include "TLeaf.h"
365 #include "TLeafB.h"
366 #include "TLeafC.h"
367 #include "TLeafD.h"
368 #include "TLeafElement.h"
369 #include "TLeafF.h"
370 #include "TLeafI.h"
371 #include "TLeafL.h"
372 #include "TLeafObject.h"
373 #include "TLeafS.h"
374 #include "TList.h"
375 #include "TMath.h"
376 #include "TROOT.h"
377 #include "TRealData.h"
378 #include "TRegexp.h"
379 #include "TStreamerElement.h"
380 #include "TStreamerInfo.h"
381 #include "TStyle.h"
382 #include "TSystem.h"
383 #include "TTreeCloner.h"
384 #include "TTreeCache.h"
385 #include "TTreeCacheUnzip.h"
386 #include "TVirtualCollectionProxy.h"
388 #include "TVirtualFitter.h"
389 #include "TVirtualIndex.h"
390 #include "TVirtualPerfStats.h"
391 #include "TVirtualPad.h"
392 #include "TBranchSTL.h"
393 #include "TSchemaRuleSet.h"
394 #include "TFileMergeInfo.h"
395 #include "ROOT/StringConv.hxx"
396 #include "TVirtualMutex.h"
397 
398 #include "TBranchIMTHelper.h"
399 
400 #include <chrono>
401 #include <cstddef>
402 #include <iostream>
403 #include <fstream>
404 #include <sstream>
405 #include <string>
406 #include <stdio.h>
407 #include <limits.h>
408 #include <algorithm>
409 
410 #ifdef R__USE_IMT
411 #include "ROOT/TThreadExecutor.hxx"
412 #include <thread>
413 #include <string>
414 #include <sstream>
415 #endif
417 constexpr Int_t kNEntriesResort = 100;
419 
420 Int_t TTree::fgBranchStyle = 1; // Use new TBranch style with TBranchElement.
421 Long64_t TTree::fgMaxTreeSize = 100000000000LL;
422 
423 ClassImp(TTree);
424 
425 ////////////////////////////////////////////////////////////////////////////////
426 ////////////////////////////////////////////////////////////////////////////////
427 ////////////////////////////////////////////////////////////////////////////////
429 static char DataTypeToChar(EDataType datatype)
430 {
431  // Return the leaflist 'char' for a given datatype.
432 
433  switch(datatype) {
434  case kChar_t: return 'B';
435  case kUChar_t: return 'b';
436  case kBool_t: return 'O';
437  case kShort_t: return 'S';
438  case kUShort_t: return 's';
439  case kCounter:
440  case kInt_t: return 'I';
441  case kUInt_t: return 'i';
442  case kDouble_t:
443  case kDouble32_t: return 'D';
444  case kFloat_t:
445  case kFloat16_t: return 'F';
446  case kLong_t: return 0; // unsupported
447  case kULong_t: return 0; // unsupported?
448  case kchar: return 0; // unsupported
449  case kLong64_t: return 'L';
450  case kULong64_t: return 'l';
451 
452  case kCharStar: return 'C';
453  case kBits: return 0; //unsupported
454 
455  case kOther_t:
456  case kNoType_t:
457  default:
458  return 0;
459  }
460  return 0;
461 }
462 
463 ////////////////////////////////////////////////////////////////////////////////
464 /// \class TTree::TFriendLock
465 /// Helper class to prevent infinite recursion in the usage of TTree Friends.
466 
467 ////////////////////////////////////////////////////////////////////////////////
468 /// Record in tree that it has been used while recursively looks through the friends.
471 : fTree(tree)
472 {
473  // We could also add some code to acquire an actual
474  // lock to prevent multi-thread issues
475  fMethodBit = methodbit;
476  if (fTree) {
479  } else {
480  fPrevious = 0;
481  }
482 }
483 
484 ////////////////////////////////////////////////////////////////////////////////
485 /// Copy constructor.
488  fTree(tfl.fTree),
489  fMethodBit(tfl.fMethodBit),
490  fPrevious(tfl.fPrevious)
491 {
492 }
493 
494 ////////////////////////////////////////////////////////////////////////////////
495 /// Assignment operator.
498 {
499  if(this!=&tfl) {
500  fTree=tfl.fTree;
502  fPrevious=tfl.fPrevious;
503  }
504  return *this;
505 }
506 
507 ////////////////////////////////////////////////////////////////////////////////
508 /// Restore the state of tree the same as before we set the lock.
511 {
512  if (fTree) {
513  if (!fPrevious) {
515  }
516  }
517 }
518 
519 ////////////////////////////////////////////////////////////////////////////////
520 /// \class TTree::TClusterIterator
521 /// Helper class to iterate over cluster of baskets.
522 
523 ////////////////////////////////////////////////////////////////////////////////
524 /// Regular constructor.
525 /// TTree is not set as const, since we might modify if it is a TChain.
527 TTree::TClusterIterator::TClusterIterator(TTree *tree, Long64_t firstEntry) : fTree(tree), fClusterRange(0), fStartEntry(0), fNextEntry(0), fEstimatedSize(-1)
528 {
529  if (fTree->fNClusterRange) {
530  // Find the correct cluster range.
531  //
532  // Since fClusterRangeEnd contains the inclusive upper end of the range, we need to search for the
533  // range that was containing the previous entry and add 1 (because BinarySearch consider the values
534  // to be the inclusive start of the bucket).
536 
537  Long64_t entryInRange;
538  Long64_t pedestal;
539  if (fClusterRange == 0) {
540  pedestal = 0;
541  entryInRange = firstEntry;
542  } else {
543  pedestal = fTree->fClusterRangeEnd[fClusterRange-1] + 1;
544  entryInRange = firstEntry - pedestal;
545  }
546  Long64_t autoflush;
548  autoflush = fTree->fAutoFlush;
549  } else {
550  autoflush = fTree->fClusterSize[fClusterRange];
551  }
552  if (autoflush <= 0) {
553  autoflush = GetEstimatedClusterSize();
554  }
555  fStartEntry = pedestal + entryInRange - entryInRange%autoflush;
556  } else if ( fTree->GetAutoFlush() <= 0 ) {
557  // Case of old files before November 9 2009 *or* small tree where AutoFlush was never set.
558  fStartEntry = firstEntry;
559  } else {
560  fStartEntry = firstEntry - firstEntry%fTree->GetAutoFlush();
561  }
562  fNextEntry = fStartEntry; // Position correctly for the first call to Next()
563 }
564 
565 ////////////////////////////////////////////////////////////////////////////////
566 /// Estimate the cluster size.
567 ///
568 /// In almost all cases, this quickly returns the size of the auto-flush
569 /// in the TTree.
570 ///
571 /// However, in the case where the cluster size was not fixed (old files and
572 /// case where autoflush was explicitly set to zero), we need estimate
573 /// a cluster size in relation to the size of the cache.
574 ///
575 /// After this value is calculated once for the TClusterIterator, it is
576 /// cached and reused in future calls.
579 {
580  auto autoFlush = fTree->GetAutoFlush();
581  if (autoFlush > 0) return autoFlush;
582  if (fEstimatedSize > 0) return fEstimatedSize;
583 
584  Long64_t zipBytes = fTree->GetZipBytes();
585  if (zipBytes == 0) {
587  } else {
588  Long64_t clusterEstimate = 1;
589  Long64_t cacheSize = fTree->GetCacheSize();
590  if (cacheSize == 0) {
591  // Humm ... let's double check on the file.
593  if (file) {
594  TFileCacheRead *cache = fTree->GetReadCache(file);
595  if (cache) {
596  cacheSize = cache->GetBufferSize();
597  }
598  }
599  }
600  // If neither file nor tree has a cache, use the current default.
601  if (cacheSize <= 0) {
602  cacheSize = 30000000;
603  }
604  clusterEstimate = fTree->GetEntries() * cacheSize / zipBytes;
605  // If there are no entries, then just default to 1.
606  fEstimatedSize = clusterEstimate ? clusterEstimate : 1;
607  }
608  return fEstimatedSize;
609 }
610 
611 ////////////////////////////////////////////////////////////////////////////////
612 /// Move on to the next cluster and return the starting entry
613 /// of this next cluster
616 {
618  if (fTree->fNClusterRange || fTree->GetAutoFlush() > 0) {
620  // We are looking at a range which size
621  // is defined by AutoFlush itself and goes to the GetEntries.
623  } else {
625  ++fClusterRange;
626  }
628  // We are looking at the last range which size
629  // is defined by AutoFlush itself and goes to the GetEntries.
631  } else {
632  Long64_t clusterSize = fTree->fClusterSize[fClusterRange];
633  if (clusterSize == 0) {
634  clusterSize = GetEstimatedClusterSize();
635  }
636  fNextEntry += clusterSize;
638  // The last cluster of the range was a partial cluster,
639  // so the next cluster starts at the beginning of the
640  // next range.
642  }
643  }
644  }
645  } else {
646  // Case of old files before November 9 2009
648  }
649  if (fNextEntry > fTree->GetEntries()) {
651  }
652  return fStartEntry;
653 }
654 
655 ////////////////////////////////////////////////////////////////////////////////
656 /// Move on to the previous cluster and return the starting entry
657 /// of this previous cluster
660 {
662  if (fTree->fNClusterRange || fTree->GetAutoFlush() > 0) {
663  if (fClusterRange == 0 || fTree->fNClusterRange == 0) {
664  // We are looking at a range which size
665  // is defined by AutoFlush itself.
667  } else {
668  if (fNextEntry <= fTree->fClusterRangeEnd[fClusterRange]) {
669  --fClusterRange;
670  }
671  if (fClusterRange == 0) {
672  // We are looking at the first range.
673  fStartEntry = 0;
674  } else {
675  Long64_t clusterSize = fTree->fClusterSize[fClusterRange];
676  if (clusterSize == 0) {
677  clusterSize = GetEstimatedClusterSize();
678  }
679  fStartEntry -= clusterSize;
680  }
681  }
682  } else {
683  // Case of old files before November 9 2009 or trees that never auto-flushed.
685  }
686  if (fStartEntry < 0) {
687  fStartEntry = 0;
688  }
689  return fStartEntry;
690 }
691 
692 ////////////////////////////////////////////////////////////////////////////////
693 ////////////////////////////////////////////////////////////////////////////////
694 ////////////////////////////////////////////////////////////////////////////////
695 
696 ////////////////////////////////////////////////////////////////////////////////
697 /// Default constructor and I/O constructor.
698 ///
699 /// Note: We do *not* insert ourself into the current directory.
700 ///
702 TTree::TTree()
703 : TNamed()
704 , TAttLine()
705 , TAttFill()
706 , TAttMarker()
707 , fEntries(0)
708 , fTotBytes(0)
709 , fZipBytes(0)
710 , fSavedBytes(0)
711 , fFlushedBytes(0)
712 , fWeight(1)
713 , fTimerInterval(0)
714 , fScanField(25)
715 , fUpdate(0)
717 , fNClusterRange(0)
718 , fMaxClusterRange(0)
719 , fMaxEntries(0)
720 , fMaxEntryLoop(0)
721 , fMaxVirtualSize(0)
722 , fAutoSave( -300000000)
723 , fAutoFlush(-30000000)
724 , fEstimate(1000000)
725 , fClusterRangeEnd(0)
726 , fClusterSize(0)
727 , fCacheSize(0)
728 , fChainOffset(0)
729 , fReadEntry(-1)
730 , fTotalBuffers(0)
731 , fPacketSize(100)
732 , fNfill(0)
733 , fDebug(0)
734 , fDebugMin(0)
735 , fDebugMax(9999999)
736 , fMakeClass(0)
737 , fFileNumber(0)
738 , fNotify(0)
739 , fDirectory(0)
740 , fBranches()
741 , fLeaves()
742 , fAliases(0)
743 , fEventList(0)
744 , fEntryList(0)
745 , fIndexValues()
746 , fIndex()
747 , fTreeIndex(0)
748 , fFriends(0)
749 , fPerfStats(0)
750 , fUserInfo(0)
751 , fPlayer(0)
752 , fClones(0)
753 , fBranchRef(0)
755 , fTransientBuffer(0)
761 {
762  fMaxEntries = 1000000000;
763  fMaxEntries *= 1000;
764 
765  fMaxEntryLoop = 1000000000;
766  fMaxEntryLoop *= 1000;
767 
769 }
770 
771 ////////////////////////////////////////////////////////////////////////////////
772 /// Normal tree constructor.
773 ///
774 /// The tree is created in the current directory.
775 /// Use the various functions Branch below to add branches to this tree.
776 ///
777 /// If the first character of title is a "/", the function assumes a folder name.
778 /// In this case, it creates automatically branches following the folder hierarchy.
779 /// splitlevel may be used in this case to control the split level.
781 TTree::TTree(const char* name, const char* title, Int_t splitlevel /* = 99 */,
782  TDirectory* dir /* = gDirectory*/)
783 : TNamed(name, title)
784 , TAttLine()
785 , TAttFill()
786 , TAttMarker()
787 , fEntries(0)
788 , fTotBytes(0)
789 , fZipBytes(0)
790 , fSavedBytes(0)
791 , fFlushedBytes(0)
792 , fWeight(1)
793 , fTimerInterval(0)
794 , fScanField(25)
795 , fUpdate(0)
797 , fNClusterRange(0)
798 , fMaxClusterRange(0)
799 , fMaxEntries(0)
800 , fMaxEntryLoop(0)
801 , fMaxVirtualSize(0)
802 , fAutoSave( -300000000)
803 , fAutoFlush(-30000000)
804 , fEstimate(1000000)
805 , fClusterRangeEnd(0)
806 , fClusterSize(0)
807 , fCacheSize(0)
808 , fChainOffset(0)
809 , fReadEntry(-1)
810 , fTotalBuffers(0)
811 , fPacketSize(100)
812 , fNfill(0)
813 , fDebug(0)
814 , fDebugMin(0)
815 , fDebugMax(9999999)
816 , fMakeClass(0)
817 , fFileNumber(0)
818 , fNotify(0)
819 , fDirectory(dir)
820 , fBranches()
821 , fLeaves()
822 , fAliases(0)
823 , fEventList(0)
824 , fEntryList(0)
825 , fIndexValues()
826 , fIndex()
827 , fTreeIndex(0)
828 , fFriends(0)
829 , fPerfStats(0)
830 , fUserInfo(0)
831 , fPlayer(0)
832 , fClones(0)
833 , fBranchRef(0)
835 , fTransientBuffer(0)
841 {
842  // TAttLine state.
846 
847  // TAttFill state.
850 
851  // TAttMarkerState.
855 
856  fMaxEntries = 1000000000;
857  fMaxEntries *= 1000;
858 
859  fMaxEntryLoop = 1000000000;
860  fMaxEntryLoop *= 1000;
861 
862  // Insert ourself into the current directory.
863  // FIXME: This is very annoying behaviour, we should
864  // be able to choose to not do this like we
865  // can with a histogram.
866  if (fDirectory) fDirectory->Append(this);
867 
869 
870  // If title starts with "/" and is a valid folder name, a superbranch
871  // is created.
872  // FIXME: Why?
873  if (strlen(title) > 2) {
874  if (title[0] == '/') {
875  Branch(title+1,32000,splitlevel);
876  }
877  }
878 }
879 
880 ////////////////////////////////////////////////////////////////////////////////
881 /// Destructor.
884 {
885  if (fDirectory) {
886  // We are in a directory, which may possibly be a file.
887  if (fDirectory->GetList()) {
888  // Remove us from the directory listing.
889  fDirectory->Remove(this);
890  }
891  //delete the file cache if it points to this Tree
893  MoveReadCache(file,0);
894  }
895  // We don't own the leaves in fLeaves, the branches do.
896  fLeaves.Clear();
897  // I'm ready to destroy any objects allocated by
898  // SetAddress() by my branches. If I have clones,
899  // tell them to zero their pointers to this shared
900  // memory.
901  if (fClones && fClones->GetEntries()) {
902  // I have clones.
903  // I am about to delete the objects created by
904  // SetAddress() which we are sharing, so tell
905  // the clones to release their pointers to them.
906  for (TObjLink* lnk = fClones->FirstLink(); lnk; lnk = lnk->Next()) {
907  TTree* clone = (TTree*) lnk->GetObject();
908  // clone->ResetBranchAddresses();
909 
910  // Reset only the branch we have set the address of.
911  CopyAddresses(clone,kTRUE);
912  }
913  }
914  // Get rid of our branches, note that this will also release
915  // any memory allocated by TBranchElement::SetAddress().
916  fBranches.Delete();
917  // FIXME: We must consider what to do with the reset of these if we are a clone.
918  delete fPlayer;
919  fPlayer = 0;
920  if (fFriends) {
921  fFriends->Delete();
922  delete fFriends;
923  fFriends = 0;
924  }
925  if (fAliases) {
926  fAliases->Delete();
927  delete fAliases;
928  fAliases = 0;
929  }
930  if (fUserInfo) {
931  fUserInfo->Delete();
932  delete fUserInfo;
933  fUserInfo = 0;
934  }
935  if (fClones) {
936  // Clone trees should no longer be removed from fClones when they are deleted.
937  {
939  gROOT->GetListOfCleanups()->Remove(fClones);
940  }
941  // Note: fClones does not own its content.
942  delete fClones;
943  fClones = 0;
944  }
945  if (fEntryList) {
947  // Delete the entry list if it is marked to be deleted and it is not also
948  // owned by a directory. (Otherwise we would need to make sure that a
949  // TDirectoryFile that has a TTree in it does a 'slow' TList::Delete.
950  delete fEntryList;
951  fEntryList=0;
952  }
953  }
954  delete fTreeIndex;
955  fTreeIndex = 0;
956  delete fBranchRef;
957  fBranchRef = 0;
958  delete [] fClusterRangeEnd;
959  fClusterRangeEnd = 0;
960  delete [] fClusterSize;
961  fClusterSize = 0;
962  // Must be done after the destruction of friends.
963  // Note: We do *not* own our directory.
964  fDirectory = 0;
965 
966  if (fTransientBuffer) {
967  delete fTransientBuffer;
968  fTransientBuffer = 0;
969  }
970 }
971 
972 ////////////////////////////////////////////////////////////////////////////////
973 /// Returns the transient buffer currently used by this TTree for reading/writing baskets.
976 {
977  if (fTransientBuffer) {
978  if (fTransientBuffer->BufferSize() < size) {
979  fTransientBuffer->Expand(size);
980  }
981  return fTransientBuffer;
982  }
984  return fTransientBuffer;
985 }
986 
987 ////////////////////////////////////////////////////////////////////////////////
988 /// Add branch with name bname to the Tree cache.
989 /// If bname="*" all branches are added to the cache.
990 /// if subbranches is true all the branches of the subbranches are
991 /// also put to the cache.
992 ///
993 /// Returns:
994 /// - 0 branch added or already included
995 /// - -1 on error
997 Int_t TTree::AddBranchToCache(const char*bname, Bool_t subbranches)
998 {
999  if (!GetTree()) {
1000  if (LoadTree(0)<0) {
1001  Error("AddBranchToCache","Could not load a tree");
1002  return -1;
1003  }
1004  }
1005  if (GetTree()) {
1006  if (GetTree() != this) {
1007  return GetTree()->AddBranchToCache(bname, subbranches);
1008  }
1009  } else {
1010  Error("AddBranchToCache", "No tree is available. Branch was not added to the cache");
1011  return -1;
1012  }
1013 
1014  TFile *f = GetCurrentFile();
1015  if (!f) {
1016  Error("AddBranchToCache", "No file is available. Branch was not added to the cache");
1017  return -1;
1018  }
1019  TTreeCache *tc = GetReadCache(f,kTRUE);
1020  if (!tc) {
1021  Error("AddBranchToCache", "No cache is available, branch not added");
1022  return -1;
1023  }
1024  return tc->AddBranch(bname,subbranches);
1025 }
1026 
1027 ////////////////////////////////////////////////////////////////////////////////
1028 /// Add branch b to the Tree cache.
1029 /// if subbranches is true all the branches of the subbranches are
1030 /// also put to the cache.
1031 ///
1032 /// Returns:
1033 /// - 0 branch added or already included
1034 /// - -1 on error
1037 {
1038  if (!GetTree()) {
1039  if (LoadTree(0)<0) {
1040  Error("AddBranchToCache","Could not load a tree");
1041  return -1;
1042  }
1043  }
1044  if (GetTree()) {
1045  if (GetTree() != this) {
1046  Int_t res = GetTree()->AddBranchToCache(b, subbranches);
1047  if (res<0) {
1048  Error("AddBranchToCache", "Error adding branch");
1049  }
1050  return res;
1051  }
1052  } else {
1053  Error("AddBranchToCache", "No tree is available. Branch was not added to the cache");
1054  return -1;
1055  }
1056 
1057  TFile *f = GetCurrentFile();
1058  if (!f) {
1059  Error("AddBranchToCache", "No file is available. Branch was not added to the cache");
1060  return -1;
1061  }
1062  TTreeCache *tc = GetReadCache(f,kTRUE);
1063  if (!tc) {
1064  Error("AddBranchToCache", "No cache is available, branch not added");
1065  return -1;
1066  }
1067  return tc->AddBranch(b,subbranches);
1068 }
1069 
1070 ////////////////////////////////////////////////////////////////////////////////
1071 /// Remove the branch with name 'bname' from the Tree cache.
1072 /// If bname="*" all branches are removed from the cache.
1073 /// if subbranches is true all the branches of the subbranches are
1074 /// also removed from the cache.
1075 ///
1076 /// Returns:
1077 /// - 0 branch dropped or not in cache
1078 /// - -1 on error
1080 Int_t TTree::DropBranchFromCache(const char*bname, Bool_t subbranches)
1081 {
1082  if (!GetTree()) {
1083  if (LoadTree(0)<0) {
1084  Error("DropBranchFromCache","Could not load a tree");
1085  return -1;
1086  }
1087  }
1088  if (GetTree()) {
1089  if (GetTree() != this) {
1090  return GetTree()->DropBranchFromCache(bname, subbranches);
1091  }
1092  } else {
1093  Error("DropBranchFromCache", "No tree is available. Branch was not dropped from the cache");
1094  return -1;
1095  }
1096 
1097  TFile *f = GetCurrentFile();
1098  if (!f) {
1099  Error("DropBranchFromCache", "No file is available. Branch was not dropped from the cache");
1100  return -1;
1101  }
1102  TTreeCache *tc = GetReadCache(f,kTRUE);
1103  if (!tc) {
1104  Error("DropBranchFromCache", "No cache is available, branch not dropped");
1105  return -1;
1106  }
1107  return tc->DropBranch(bname,subbranches);
1108 }
1109 
1110 ////////////////////////////////////////////////////////////////////////////////
1111 /// Remove the branch b from the Tree cache.
1112 /// if subbranches is true all the branches of the subbranches are
1113 /// also removed from the cache.
1114 ///
1115 /// Returns:
1116 /// - 0 branch dropped or not in cache
1117 /// - -1 on error
1120 {
1121  if (!GetTree()) {
1122  if (LoadTree(0)<0) {
1123  Error("DropBranchFromCache","Could not load a tree");
1124  return -1;
1125  }
1126  }
1127  if (GetTree()) {
1128  if (GetTree() != this) {
1129  Int_t res = GetTree()->DropBranchFromCache(b, subbranches);
1130  if (res<0) {
1131  Error("DropBranchFromCache", "Error dropping branch");
1132  }
1133  return res;
1134  }
1135  } else {
1136  Error("DropBranchFromCache", "No tree is available. Branch was not dropped from the cache");
1137  return -1;
1138  }
1139 
1140  TFile *f = GetCurrentFile();
1141  if (!f) {
1142  Error("DropBranchFromCache", "No file is available. Branch was not dropped from the cache");
1143  return -1;
1144  }
1145  TTreeCache *tc = GetReadCache(f,kTRUE);
1146  if (!tc) {
1147  Error("DropBranchFromCache", "No cache is available, branch not dropped");
1148  return -1;
1149  }
1150  return tc->DropBranch(b,subbranches);
1151 }
1152 
1153 ////////////////////////////////////////////////////////////////////////////////
1154 /// Add a cloned tree to our list of trees to be notified whenever we change
1155 /// our branch addresses or when we are deleted.
1157 void TTree::AddClone(TTree* clone)
1158 {
1159  if (!fClones) {
1160  fClones = new TList();
1161  fClones->SetOwner(false);
1162  // So that the clones are automatically removed from the list when
1163  // they are deleted.
1164  {
1166  gROOT->GetListOfCleanups()->Add(fClones);
1167  }
1168  }
1169  if (!fClones->FindObject(clone)) {
1170  fClones->Add(clone);
1171  }
1172 }
1173 
1174 ////////////////////////////////////////////////////////////////////////////////
1175 /// Add a TFriendElement to the list of friends.
1176 ///
1177 /// This function:
1178 /// - opens a file if filename is specified
1179 /// - reads a Tree with name treename from the file (current directory)
1180 /// - adds the Tree to the list of friends
1181 /// see other AddFriend functions
1182 ///
1183 /// A TFriendElement TF describes a TTree object TF in a file.
1184 /// When a TFriendElement TF is added to the the list of friends of an
1185 /// existing TTree T, any variable from TF can be referenced in a query
1186 /// to T.
1187 ///
1188 /// A tree keeps a list of friends. In the context of a tree (or a chain),
1189 /// friendship means unrestricted access to the friends data. In this way
1190 /// it is much like adding another branch to the tree without taking the risk
1191 /// of damaging it. To add a friend to the list, you can use the TTree::AddFriend
1192 /// method. The tree in the diagram below has two friends (friend_tree1 and
1193 /// friend_tree2) and now has access to the variables a,b,c,i,j,k,l and m.
1194 ///
1195 /// \image html ttree_friend1.png
1196 ///
1197 /// The AddFriend method has two parameters, the first is the tree name and the
1198 /// second is the name of the ROOT file where the friend tree is saved.
1199 /// AddFriend automatically opens the friend file. If no file name is given,
1200 /// the tree called ft1 is assumed to be in the same file as the original tree.
1201 ///
1202 /// tree.AddFriend("ft1","friendfile1.root");
1203 /// If the friend tree has the same name as the original tree, you can give it
1204 /// an alias in the context of the friendship:
1205 ///
1206 /// tree.AddFriend("tree1 = tree","friendfile1.root");
1207 /// Once the tree has friends, we can use TTree::Draw as if the friend's
1208 /// variables were in the original tree. To specify which tree to use in
1209 /// the Draw method, use the syntax:
1210 /// ~~~ {.cpp}
1211 /// <treeName>.<branchname>.<varname>
1212 /// ~~~
1213 /// If the variablename is enough to uniquely identify the variable, you can
1214 /// leave out the tree and/or branch name.
1215 /// For example, these commands generate a 3-d scatter plot of variable "var"
1216 /// in the TTree tree versus variable v1 in TTree ft1 versus variable v2 in
1217 /// TTree ft2.
1218 /// ~~~ {.cpp}
1219 /// tree.AddFriend("ft1","friendfile1.root");
1220 /// tree.AddFriend("ft2","friendfile2.root");
1221 /// tree.Draw("var:ft1.v1:ft2.v2");
1222 /// ~~~
1223 /// \image html ttree_friend2.png
1224 ///
1225 /// The picture illustrates the access of the tree and its friends with a
1226 /// Draw command.
1227 /// When AddFriend is called, the ROOT file is automatically opened and the
1228 /// friend tree (ft1) is read into memory. The new friend (ft1) is added to
1229 /// the list of friends of tree.
1230 /// The number of entries in the friend must be equal or greater to the number
1231 /// of entries of the original tree. If the friend tree has fewer entries a
1232 /// warning is given and the missing entries are not included in the histogram.
1233 /// To retrieve the list of friends from a tree use TTree::GetListOfFriends.
1234 /// When the tree is written to file (TTree::Write), the friends list is saved
1235 /// with it. And when the tree is retrieved, the trees on the friends list are
1236 /// also retrieved and the friendship restored.
1237 /// When a tree is deleted, the elements of the friend list are also deleted.
1238 /// It is possible to declare a friend tree that has the same internal
1239 /// structure (same branches and leaves) as the original tree, and compare the
1240 /// same values by specifying the tree.
1241 /// ~~~ {.cpp}
1242 /// tree.Draw("var:ft1.var:ft2.var")
1243 /// ~~~
1245 TFriendElement* TTree::AddFriend(const char* treename, const char* filename)
1246 {
1247  if (!fFriends) {
1248  fFriends = new TList();
1249  }
1250  TFriendElement* fe = new TFriendElement(this, treename, filename);
1251 
1252  fFriends->Add(fe);
1253  TTree* t = fe->GetTree();
1254  if (t) {
1255  if (!t->GetTreeIndex() && (t->GetEntries() < fEntries)) {
1256  Warning("AddFriend", "FriendElement %s in file %s has less entries %lld than its parent Tree: %lld", treename, filename, t->GetEntries(), fEntries);
1257  }
1258  } else {
1259  Warning("AddFriend", "Cannot add FriendElement %s in file %s", treename, filename);
1260  }
1261  return fe;
1262 }
1263 
1264 ////////////////////////////////////////////////////////////////////////////////
1265 /// Add a TFriendElement to the list of friends.
1266 ///
1267 /// The TFile is managed by the user (e.g. the user must delete the file).
1268 /// For complete description see AddFriend(const char *, const char *).
1269 /// This function:
1270 /// - reads a Tree with name treename from the file
1271 /// - adds the Tree to the list of friends
1273 TFriendElement* TTree::AddFriend(const char* treename, TFile* file)
1274 {
1275  if (!fFriends) {
1276  fFriends = new TList();
1277  }
1278  TFriendElement *fe = new TFriendElement(this, treename, file);
1279  R__ASSERT(fe);
1280  fFriends->Add(fe);
1281  TTree *t = fe->GetTree();
1282  if (t) {
1283  if (!t->GetTreeIndex() && (t->GetEntries() < fEntries)) {
1284  Warning("AddFriend", "FriendElement %s in file %s has less entries %lld than its parent tree: %lld", treename, file->GetName(), t->GetEntries(), fEntries);
1285  }
1286  } else {
1287  Warning("AddFriend", "unknown tree '%s' in file '%s'", treename, file->GetName());
1288  }
1289  return fe;
1290 }
1291 
1292 ////////////////////////////////////////////////////////////////////////////////
1293 /// Add a TFriendElement to the list of friends.
1294 ///
1295 /// The TTree is managed by the user (e.g., the user must delete the file).
1296 /// For a complete description see AddFriend(const char *, const char *).
1298 TFriendElement* TTree::AddFriend(TTree* tree, const char* alias, Bool_t warn)
1299 {
1300  if (!tree) {
1301  return 0;
1302  }
1303  if (!fFriends) {
1304  fFriends = new TList();
1305  }
1306  TFriendElement* fe = new TFriendElement(this, tree, alias);
1307  R__ASSERT(fe); // this assert is for historical reasons. Don't remove it unless you understand all the consequences.
1308  fFriends->Add(fe);
1309  TTree* t = fe->GetTree();
1310  if (warn && (t->GetEntries() < fEntries)) {
1311  Warning("AddFriend", "FriendElement '%s' in file '%s' has less entries %lld than its parent tree: %lld",
1312  tree->GetName(), fe->GetFile() ? fe->GetFile()->GetName() : "(memory resident)", t->GetEntries(), fEntries);
1313  }
1314  return fe;
1315 }
1316 
1317 ////////////////////////////////////////////////////////////////////////////////
1318 /// AutoSave tree header every fAutoSave bytes.
1319 ///
1320 /// When large Trees are produced, it is safe to activate the AutoSave
1321 /// procedure. Some branches may have buffers holding many entries.
1322 /// If fAutoSave is negative, AutoSave is automatically called by
1323 /// TTree::Fill when the number of bytes generated since the previous
1324 /// AutoSave is greater than -fAutoSave bytes.
1325 /// If fAutoSave is positive, AutoSave is automatically called by
1326 /// TTree::Fill every N entries.
1327 /// This function may also be invoked by the user.
1328 /// Each AutoSave generates a new key on the file.
1329 /// Once the key with the tree header has been written, the previous cycle
1330 /// (if any) is deleted.
1331 ///
1332 /// Note that calling TTree::AutoSave too frequently (or similarly calling
1333 /// TTree::SetAutoSave with a small value) is an expensive operation.
1334 /// You should make tests for your own application to find a compromise
1335 /// between speed and the quantity of information you may loose in case of
1336 /// a job crash.
1337 ///
1338 /// In case your program crashes before closing the file holding this tree,
1339 /// the file will be automatically recovered when you will connect the file
1340 /// in UPDATE mode.
1341 /// The Tree will be recovered at the status corresponding to the last AutoSave.
1342 ///
1343 /// if option contains "SaveSelf", gDirectory->SaveSelf() is called.
1344 /// This allows another process to analyze the Tree while the Tree is being filled.
1345 ///
1346 /// if option contains "FlushBaskets", TTree::FlushBaskets is called and all
1347 /// the current basket are closed-out and written to disk individually.
1348 ///
1349 /// By default the previous header is deleted after having written the new header.
1350 /// if option contains "Overwrite", the previous Tree header is deleted
1351 /// before written the new header. This option is slightly faster, but
1352 /// the default option is safer in case of a problem (disk quota exceeded)
1353 /// when writing the new header.
1354 ///
1355 /// The function returns the number of bytes written to the file.
1356 /// if the number of bytes is null, an error has occurred while writing
1357 /// the header to the file.
1358 ///
1359 /// ## How to write a Tree in one process and view it from another process
1360 ///
1361 /// The following two scripts illustrate how to do this.
1362 /// The script treew.C is executed by process1, treer.C by process2
1363 ///
1364 /// script treew.C:
1365 /// ~~~ {.cpp}
1366 /// void treew() {
1367 /// TFile f("test.root","recreate");
1368 /// TNtuple *ntuple = new TNtuple("ntuple","Demo","px:py:pz:random:i");
1369 /// Float_t px, py, pz;
1370 /// for ( Int_t i=0; i<10000000; i++) {
1371 /// gRandom->Rannor(px,py);
1372 /// pz = px*px + py*py;
1373 /// Float_t random = gRandom->Rndm(1);
1374 /// ntuple->Fill(px,py,pz,random,i);
1375 /// if (i%1000 == 1) ntuple->AutoSave("SaveSelf");
1376 /// }
1377 /// }
1378 /// ~~~
1379 /// script treer.C:
1380 /// ~~~ {.cpp}
1381 /// void treer() {
1382 /// TFile f("test.root");
1383 /// TTree *ntuple = (TTree*)f.Get("ntuple");
1384 /// TCanvas c1;
1385 /// Int_t first = 0;
1386 /// while(1) {
1387 /// if (first == 0) ntuple->Draw("px>>hpx", "","",10000000,first);
1388 /// else ntuple->Draw("px>>+hpx","","",10000000,first);
1389 /// first = (Int_t)ntuple->GetEntries();
1390 /// c1.Update();
1391 /// gSystem->Sleep(1000); //sleep 1 second
1392 /// ntuple->Refresh();
1393 /// }
1394 /// }
1395 /// ~~~
1398 {
1399  if (!fDirectory || fDirectory == gROOT || !fDirectory->IsWritable()) return 0;
1400  if (gDebug > 0) {
1401  Info("AutoSave", "Tree:%s after %lld bytes written\n",GetName(),GetTotBytes());
1402  }
1403  TString opt = option;
1404  opt.ToLower();
1405 
1406  if (opt.Contains("flushbaskets")) {
1407  if (gDebug > 0) Info("AutoSave", "calling FlushBaskets \n");
1408  FlushBasketsImpl();
1409  }
1410 
1412 
1414  Long64_t nbytes;
1415  if (opt.Contains("overwrite")) {
1416  nbytes = fDirectory->WriteTObject(this,"","overwrite");
1417  } else {
1418  nbytes = fDirectory->WriteTObject(this); //nbytes will be 0 if Write failed (disk space exceeded)
1419  if (nbytes && key) {
1420  key->Delete();
1421  delete key;
1422  }
1423  }
1424  // save StreamerInfo
1425  TFile *file = fDirectory->GetFile();
1426  if (file) file->WriteStreamerInfo();
1427 
1428  if (opt.Contains("saveself")) {
1429  fDirectory->SaveSelf();
1430  //the following line is required in case GetUserInfo contains a user class
1431  //for which the StreamerInfo must be written. One could probably be a bit faster (Rene)
1432  if (file) file->WriteHeader();
1433  }
1434 
1435  return nbytes;
1436 }
1437 
1438 namespace {
1439  // This error message is repeated several times in the code. We write it once.
1440  const char* writeStlWithoutProxyMsg = "The class requested (%s) for the branch \"%s\""
1441  " is an instance of an stl collection and does not have a compiled CollectionProxy."
1442  " Please generate the dictionary for this collection (%s) to avoid to write corrupted data.";
1443 }
1444 
1445 ////////////////////////////////////////////////////////////////////////////////
1446 /// Same as TTree::Branch() with added check that addobj matches className.
1447 ///
1448 /// See TTree::Branch() for other details.
1449 ///
1451 TBranch* TTree::BranchImp(const char* branchname, const char* classname, TClass* ptrClass, void* addobj, Int_t bufsize, Int_t splitlevel)
1452 {
1453  TClass* claim = TClass::GetClass(classname);
1454  if (!ptrClass) {
1455  if (claim && claim->GetCollectionProxy() && dynamic_cast<TEmulatedCollectionProxy*>(claim->GetCollectionProxy())) {
1456  Error("Branch", writeStlWithoutProxyMsg,
1457  claim->GetName(), branchname, claim->GetName());
1458  return 0;
1459  }
1460  return Branch(branchname, classname, (void*) addobj, bufsize, splitlevel);
1461  }
1462  TClass* actualClass = 0;
1463  void** addr = (void**) addobj;
1464  if (addr) {
1465  actualClass = ptrClass->GetActualClass(*addr);
1466  }
1467  if (ptrClass && claim) {
1468  if (!(claim->InheritsFrom(ptrClass) || ptrClass->InheritsFrom(claim))) {
1469  // Note we currently do not warn in case of splicing or over-expectation).
1470  if (claim->IsLoaded() && ptrClass->IsLoaded() && strcmp( claim->GetTypeInfo()->name(), ptrClass->GetTypeInfo()->name() ) == 0) {
1471  // The type is the same according to the C++ type_info, we must be in the case of
1472  // a template of Double32_t. This is actually a correct case.
1473  } else {
1474  Error("Branch", "The class requested (%s) for \"%s\" is different from the type of the pointer passed (%s)",
1475  claim->GetName(), branchname, ptrClass->GetName());
1476  }
1477  } else if (actualClass && (claim != actualClass) && !actualClass->InheritsFrom(claim)) {
1478  if (claim->IsLoaded() && actualClass->IsLoaded() && strcmp( claim->GetTypeInfo()->name(), actualClass->GetTypeInfo()->name() ) == 0) {
1479  // The type is the same according to the C++ type_info, we must be in the case of
1480  // a template of Double32_t. This is actually a correct case.
1481  } else {
1482  Error("Branch", "The actual class (%s) of the object provided for the definition of the branch \"%s\" does not inherit from %s",
1483  actualClass->GetName(), branchname, claim->GetName());
1484  }
1485  }
1486  }
1487  if (claim && claim->GetCollectionProxy() && dynamic_cast<TEmulatedCollectionProxy*>(claim->GetCollectionProxy())) {
1488  Error("Branch", writeStlWithoutProxyMsg,
1489  claim->GetName(), branchname, claim->GetName());
1490  return 0;
1491  }
1492  return Branch(branchname, classname, (void*) addobj, bufsize, splitlevel);
1493 }
1494 
1495 ////////////////////////////////////////////////////////////////////////////////
1496 /// Same as TTree::Branch but automatic detection of the class name.
1497 /// See TTree::Branch for other details.
1499 TBranch* TTree::BranchImp(const char* branchname, TClass* ptrClass, void* addobj, Int_t bufsize, Int_t splitlevel)
1500 {
1501  if (!ptrClass) {
1502  Error("Branch", "The pointer specified for %s is not of a class known to ROOT", branchname);
1503  return 0;
1504  }
1505  TClass* actualClass = 0;
1506  void** addr = (void**) addobj;
1507  if (addr && *addr) {
1508  actualClass = ptrClass->GetActualClass(*addr);
1509  if (!actualClass) {
1510  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",
1511  branchname, ptrClass->GetName());
1512  actualClass = ptrClass;
1513  } else if ((ptrClass != actualClass) && !actualClass->InheritsFrom(ptrClass)) {
1514  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());
1515  return 0;
1516  }
1517  } else {
1518  actualClass = ptrClass;
1519  }
1520  if (actualClass && actualClass->GetCollectionProxy() && dynamic_cast<TEmulatedCollectionProxy*>(actualClass->GetCollectionProxy())) {
1521  Error("Branch", writeStlWithoutProxyMsg,
1522  actualClass->GetName(), branchname, actualClass->GetName());
1523  return 0;
1524  }
1525  return Branch(branchname, actualClass->GetName(), (void*) addobj, bufsize, splitlevel);
1526 }
1527 
1528 ////////////////////////////////////////////////////////////////////////////////
1529 /// Same as TTree::Branch but automatic detection of the class name.
1530 /// See TTree::Branch for other details.
1532 TBranch* TTree::BranchImpRef(const char* branchname, const char *classname, TClass* ptrClass, void *addobj, Int_t bufsize, Int_t splitlevel)
1533 {
1534  TClass* claim = TClass::GetClass(classname);
1535  if (!ptrClass) {
1536  if (claim && claim->GetCollectionProxy() && dynamic_cast<TEmulatedCollectionProxy*>(claim->GetCollectionProxy())) {
1537  Error("Branch", writeStlWithoutProxyMsg,
1538  claim->GetName(), branchname, claim->GetName());
1539  return 0;
1540  } else if (claim == 0) {
1541  Error("Branch", "The pointer specified for %s is not of a class known to ROOT and %s is not a known class", branchname, classname);
1542  return 0;
1543  }
1544  ptrClass = claim;
1545  }
1546  TClass* actualClass = 0;
1547  if (!addobj) {
1548  Error("Branch", "Reference interface requires a valid object (for branch: %s)!", branchname);
1549  return 0;
1550  }
1551  actualClass = ptrClass->GetActualClass(addobj);
1552  if (ptrClass && claim) {
1553  if (!(claim->InheritsFrom(ptrClass) || ptrClass->InheritsFrom(claim))) {
1554  // Note we currently do not warn in case of splicing or over-expectation).
1555  if (claim->IsLoaded() && ptrClass->IsLoaded() && strcmp( claim->GetTypeInfo()->name(), ptrClass->GetTypeInfo()->name() ) == 0) {
1556  // The type is the same according to the C++ type_info, we must be in the case of
1557  // a template of Double32_t. This is actually a correct case.
1558  } else {
1559  Error("Branch", "The class requested (%s) for \"%s\" is different from the type of the object passed (%s)",
1560  claim->GetName(), branchname, ptrClass->GetName());
1561  }
1562  } else if (actualClass && (claim != actualClass) && !actualClass->InheritsFrom(claim)) {
1563  if (claim->IsLoaded() && actualClass->IsLoaded() && strcmp( claim->GetTypeInfo()->name(), actualClass->GetTypeInfo()->name() ) == 0) {
1564  // The type is the same according to the C++ type_info, we must be in the case of
1565  // a template of Double32_t. This is actually a correct case.
1566  } else {
1567  Error("Branch", "The actual class (%s) of the object provided for the definition of the branch \"%s\" does not inherit from %s",
1568  actualClass->GetName(), branchname, claim->GetName());
1569  }
1570  }
1571  }
1572  if (!actualClass) {
1573  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",
1574  branchname, ptrClass->GetName());
1575  actualClass = ptrClass;
1576  } else if ((ptrClass != actualClass) && !actualClass->InheritsFrom(ptrClass)) {
1577  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());
1578  return 0;
1579  }
1580  if (actualClass && actualClass->GetCollectionProxy() && dynamic_cast<TEmulatedCollectionProxy*>(actualClass->GetCollectionProxy())) {
1581  Error("Branch", writeStlWithoutProxyMsg,
1582  actualClass->GetName(), branchname, actualClass->GetName());
1583  return 0;
1584  }
1585  return BronchExec(branchname, actualClass->GetName(), (void*) addobj, kFALSE, bufsize, splitlevel);
1586 }
1587 
1588 ////////////////////////////////////////////////////////////////////////////////
1589 /// Same as TTree::Branch but automatic detection of the class name.
1590 /// See TTree::Branch for other details.
1592 TBranch* TTree::BranchImpRef(const char* branchname, TClass* ptrClass, EDataType datatype, void* addobj, Int_t bufsize, Int_t splitlevel)
1593 {
1594  if (!ptrClass) {
1595  if (datatype == kOther_t || datatype == kNoType_t) {
1596  Error("Branch", "The pointer specified for %s is not of a class or type known to ROOT", branchname);
1597  } else {
1598  TString varname; varname.Form("%s/%c",branchname,DataTypeToChar(datatype));
1599  return Branch(branchname,addobj,varname.Data(),bufsize);
1600  }
1601  return 0;
1602  }
1603  TClass* actualClass = 0;
1604  if (!addobj) {
1605  Error("Branch", "Reference interface requires a valid object (for branch: %s)!", branchname);
1606  return 0;
1607  }
1608  actualClass = ptrClass->GetActualClass(addobj);
1609  if (!actualClass) {
1610  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",
1611  branchname, ptrClass->GetName());
1612  actualClass = ptrClass;
1613  } else if ((ptrClass != actualClass) && !actualClass->InheritsFrom(ptrClass)) {
1614  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());
1615  return 0;
1616  }
1617  if (actualClass && actualClass->GetCollectionProxy() && dynamic_cast<TEmulatedCollectionProxy*>(actualClass->GetCollectionProxy())) {
1618  Error("Branch", writeStlWithoutProxyMsg,
1619  actualClass->GetName(), branchname, actualClass->GetName());
1620  return 0;
1621  }
1622  return BronchExec(branchname, actualClass->GetName(), (void*) addobj, kFALSE, bufsize, splitlevel);
1623 }
1624 
1625 ////////////////////////////////////////////////////////////////////////////////
1626 /// Deprecated function. Use next function instead.
1628 Int_t TTree::Branch(TList* li, Int_t bufsize /* = 32000 */ , Int_t splitlevel /* = 99 */)
1629 {
1630  return Branch((TCollection*) li, bufsize, splitlevel);
1631 }
1632 
1633 ////////////////////////////////////////////////////////////////////////////////
1634 /// Create one branch for each element in the collection.
1635 ///
1636 /// Each entry in the collection becomes a top level branch if the
1637 /// corresponding class is not a collection. If it is a collection, the entry
1638 /// in the collection becomes in turn top level branches, etc.
1639 /// The splitlevel is decreased by 1 every time a new collection is found.
1640 /// For example if list is a TObjArray*
1641 /// - if splitlevel = 1, one top level branch is created for each element
1642 /// of the TObjArray.
1643 /// - if splitlevel = 2, one top level branch is created for each array element.
1644 /// if, in turn, one of the array elements is a TCollection, one top level
1645 /// branch will be created for each element of this collection.
1646 ///
1647 /// In case a collection element is a TClonesArray, the special Tree constructor
1648 /// for TClonesArray is called.
1649 /// The collection itself cannot be a TClonesArray.
1650 ///
1651 /// The function returns the total number of branches created.
1652 ///
1653 /// If name is given, all branch names will be prefixed with name_.
1654 ///
1655 /// IMPORTANT NOTE1: This function should not be called with splitlevel < 1.
1656 ///
1657 /// IMPORTANT NOTE2: The branches created by this function will have names
1658 /// corresponding to the collection or object names. It is important
1659 /// to give names to collections to avoid misleading branch names or
1660 /// identical branch names. By default collections have a name equal to
1661 /// the corresponding class name, e.g. the default name for a TList is "TList".
1662 ///
1663 /// And in general, in case two or more master branches contain subbranches
1664 /// with identical names, one must add a "." (dot) character at the end
1665 /// of the master branch name. This will force the name of the subbranches
1666 /// to be of the form `master.subbranch` instead of simply `subbranch`.
1667 /// This situation happens when the top level object
1668 /// has two or more members referencing the same class.
1669 /// For example, if a Tree has two branches B1 and B2 corresponding
1670 /// to objects of the same class MyClass, one can do:
1671 /// ~~~ {.cpp}
1672 /// tree.Branch("B1.","MyClass",&b1,8000,1);
1673 /// tree.Branch("B2.","MyClass",&b2,8000,1);
1674 /// ~~~
1675 /// if MyClass has 3 members a,b,c, the two instructions above will generate
1676 /// subbranches called B1.a, B1.b ,B1.c, B2.a, B2.b, B2.c
1677 ///
1678 /// Example:
1679 /// ~~~ {.cpp}
1680 /// {
1681 /// TTree T("T","test list");
1682 /// TList *list = new TList();
1683 ///
1684 /// TObjArray *a1 = new TObjArray();
1685 /// a1->SetName("a1");
1686 /// list->Add(a1);
1687 /// TH1F *ha1a = new TH1F("ha1a","ha1",100,0,1);
1688 /// TH1F *ha1b = new TH1F("ha1b","ha1",100,0,1);
1689 /// a1->Add(ha1a);
1690 /// a1->Add(ha1b);
1691 /// TObjArray *b1 = new TObjArray();
1692 /// b1->SetName("b1");
1693 /// list->Add(b1);
1694 /// TH1F *hb1a = new TH1F("hb1a","hb1",100,0,1);
1695 /// TH1F *hb1b = new TH1F("hb1b","hb1",100,0,1);
1696 /// b1->Add(hb1a);
1697 /// b1->Add(hb1b);
1698 ///
1699 /// TObjArray *a2 = new TObjArray();
1700 /// a2->SetName("a2");
1701 /// list->Add(a2);
1702 /// TH1S *ha2a = new TH1S("ha2a","ha2",100,0,1);
1703 /// TH1S *ha2b = new TH1S("ha2b","ha2",100,0,1);
1704 /// a2->Add(ha2a);
1705 /// a2->Add(ha2b);
1706 ///
1707 /// T.Branch(list,16000,2);
1708 /// T.Print();
1709 /// }
1710 /// ~~~
1712 Int_t TTree::Branch(TCollection* li, Int_t bufsize /* = 32000 */, Int_t splitlevel /* = 99 */, const char* name /* = "" */)
1713 {
1714 
1715  if (!li) {
1716  return 0;
1717  }
1718  TObject* obj = 0;
1719  Int_t nbranches = GetListOfBranches()->GetEntries();
1720  if (li->InheritsFrom(TClonesArray::Class())) {
1721  Error("Branch", "Cannot call this constructor for a TClonesArray");
1722  return 0;
1723  }
1724  Int_t nch = strlen(name);
1725  TString branchname;
1726  TIter next(li);
1727  while ((obj = next())) {
1728  if ((splitlevel > 1) && obj->InheritsFrom(TCollection::Class()) && !obj->InheritsFrom(TClonesArray::Class())) {
1729  TCollection* col = (TCollection*) obj;
1730  if (nch) {
1731  branchname.Form("%s_%s_", name, col->GetName());
1732  } else {
1733  branchname.Form("%s_", col->GetName());
1734  }
1735  Branch(col, bufsize, splitlevel - 1, branchname);
1736  } else {
1737  if (nch && (name[nch-1] == '_')) {
1738  branchname.Form("%s%s", name, obj->GetName());
1739  } else {
1740  if (nch) {
1741  branchname.Form("%s_%s", name, obj->GetName());
1742  } else {
1743  branchname.Form("%s", obj->GetName());
1744  }
1745  }
1746  if (splitlevel > 99) {
1747  branchname += ".";
1748  }
1749  Bronch(branchname, obj->ClassName(), li->GetObjectRef(obj), bufsize, splitlevel - 1);
1750  }
1751  }
1752  return GetListOfBranches()->GetEntries() - nbranches;
1753 }
1754 
1755 ////////////////////////////////////////////////////////////////////////////////
1756 /// Create one branch for each element in the folder.
1757 /// Returns the total number of branches created.
1759 Int_t TTree::Branch(const char* foldername, Int_t bufsize /* = 32000 */, Int_t splitlevel /* = 99 */)
1760 {
1761  TObject* ob = gROOT->FindObjectAny(foldername);
1762  if (!ob) {
1763  return 0;
1764  }
1765  if (ob->IsA() != TFolder::Class()) {
1766  return 0;
1767  }
1768  Int_t nbranches = GetListOfBranches()->GetEntries();
1769  TFolder* folder = (TFolder*) ob;
1770  TIter next(folder->GetListOfFolders());
1771  TObject* obj = 0;
1772  char* curname = new char[1000];
1773  char occur[20];
1774  while ((obj = next())) {
1775  snprintf(curname,1000, "%s/%s", foldername, obj->GetName());
1776  if (obj->IsA() == TFolder::Class()) {
1777  Branch(curname, bufsize, splitlevel - 1);
1778  } else {
1779  void* add = (void*) folder->GetListOfFolders()->GetObjectRef(obj);
1780  for (Int_t i = 0; i < 1000; ++i) {
1781  if (curname[i] == 0) {
1782  break;
1783  }
1784  if (curname[i] == '/') {
1785  curname[i] = '.';
1786  }
1787  }
1788  Int_t noccur = folder->Occurence(obj);
1789  if (noccur > 0) {
1790  snprintf(occur,20, "_%d", noccur);
1791  strlcat(curname, occur,1000);
1792  }
1793  TBranchElement* br = (TBranchElement*) Bronch(curname, obj->ClassName(), add, bufsize, splitlevel - 1);
1794  if (br) br->SetBranchFolder();
1795  }
1796  }
1797  delete[] curname;
1798  return GetListOfBranches()->GetEntries() - nbranches;
1799 }
1800 
1801 ////////////////////////////////////////////////////////////////////////////////
1802 /// Create a new TTree Branch.
1803 ///
1804 /// This Branch constructor is provided to support non-objects in
1805 /// a Tree. The variables described in leaflist may be simple
1806 /// variables or structures. // See the two following
1807 /// constructors for writing objects in a Tree.
1808 ///
1809 /// By default the branch buffers are stored in the same file as the Tree.
1810 /// use TBranch::SetFile to specify a different file
1811 ///
1812 /// * address is the address of the first item of a structure.
1813 /// * leaflist is the concatenation of all the variable names and types
1814 /// separated by a colon character :
1815 /// The variable name and the variable type are separated by a slash (/).
1816 /// The variable type may be 0,1 or 2 characters. If no type is given,
1817 /// the type of the variable is assumed to be the same as the previous
1818 /// variable. If the first variable does not have a type, it is assumed
1819 /// of type F by default. The list of currently supported types is given below:
1820 /// - `C` : a character string terminated by the 0 character
1821 /// - `B` : an 8 bit signed integer (`Char_t`)
1822 /// - `b` : an 8 bit unsigned integer (`UChar_t`)
1823 /// - `S` : a 16 bit signed integer (`Short_t`)
1824 /// - `s` : a 16 bit unsigned integer (`UShort_t`)
1825 /// - `I` : a 32 bit signed integer (`Int_t`)
1826 /// - `i` : a 32 bit unsigned integer (`UInt_t`)
1827 /// - `F` : a 32 bit floating point (`Float_t`)
1828 /// - `D` : a 64 bit floating point (`Double_t`)
1829 /// - `L` : a 64 bit signed integer (`Long64_t`)
1830 /// - `l` : a 64 bit unsigned integer (`ULong64_t`)
1831 /// - `O` : [the letter `o`, not a zero] a boolean (`Bool_t`)
1832 ///
1833 /// Arrays of values are supported with the following syntax:
1834 /// - If leaf name has the form var[nelem], where nelem is alphanumeric, then
1835 /// if nelem is a leaf name, it is used as the variable size of the array,
1836 /// otherwise return 0.
1837 /// - If leaf name has the form var[nelem], where nelem is a non-negative integer, then
1838 /// it is used as the fixed size of the array.
1839 /// - If leaf name has the form of a multi-dimensional array (e.g. var[nelem][nelem2])
1840 /// where nelem and nelem2 are non-negative integer) then
1841 /// it is used as a 2 dimensional array of fixed size.
1842 ///
1843 /// Any of other form is not supported.
1844 ///
1845 /// Note that the TTree will assume that all the item are contiguous in memory.
1846 /// On some platform, this is not always true of the member of a struct or a class,
1847 /// due to padding and alignment. Sorting your data member in order of decreasing
1848 /// sizeof usually leads to their being contiguous in memory.
1849 ///
1850 /// * bufsize is the buffer size in bytes for this branch
1851 /// The default value is 32000 bytes and should be ok for most cases.
1852 /// You can specify a larger value (e.g. 256000) if your Tree is not split
1853 /// and each entry is large (Megabytes)
1854 /// A small value for bufsize is optimum if you intend to access
1855 /// the entries in the Tree randomly and your Tree is in split mode.
1857 TBranch* TTree::Branch(const char* name, void* address, const char* leaflist, Int_t bufsize /* = 32000 */)
1858 {
1859  TBranch* branch = new TBranch(this, name, address, leaflist, bufsize);
1860  if (branch->IsZombie()) {
1861  delete branch;
1862  branch = 0;
1863  return 0;
1864  }
1865  fBranches.Add(branch);
1866  return branch;
1867 }
1868 
1869 ////////////////////////////////////////////////////////////////////////////////
1870 /// Create a new branch with the object of class classname at address addobj.
1871 ///
1872 /// WARNING:
1873 ///
1874 /// Starting with Root version 3.01, the Branch function uses the new style
1875 /// branches (TBranchElement). To get the old behaviour, you can:
1876 /// - call BranchOld or
1877 /// - call TTree::SetBranchStyle(0)
1878 ///
1879 /// Note that with the new style, classname does not need to derive from TObject.
1880 /// It must derived from TObject if the branch style has been set to 0 (old)
1881 ///
1882 /// Note: See the comments in TBranchElement::SetAddress() for a more
1883 /// detailed discussion of the meaning of the addobj parameter in
1884 /// the case of new-style branches.
1885 ///
1886 /// Use splitlevel < 0 instead of splitlevel=0 when the class
1887 /// has a custom Streamer
1888 ///
1889 /// Note: if the split level is set to the default (99), TTree::Branch will
1890 /// not issue a warning if the class can not be split.
1892 TBranch* TTree::Branch(const char* name, const char* classname, void* addobj, Int_t bufsize /* = 32000 */, Int_t splitlevel /* = 99 */)
1893 {
1894  if (fgBranchStyle == 1) {
1895  return Bronch(name, classname, addobj, bufsize, splitlevel);
1896  } else {
1897  if (splitlevel < 0) {
1898  splitlevel = 0;
1899  }
1900  return BranchOld(name, classname, addobj, bufsize, splitlevel);
1901  }
1902 }
1903 
1904 ////////////////////////////////////////////////////////////////////////////////
1905 /// Create a new TTree BranchObject.
1906 ///
1907 /// Build a TBranchObject for an object of class classname.
1908 /// addobj is the address of a pointer to an object of class classname.
1909 /// IMPORTANT: classname must derive from TObject.
1910 /// The class dictionary must be available (ClassDef in class header).
1911 ///
1912 /// This option requires access to the library where the corresponding class
1913 /// is defined. Accessing one single data member in the object implies
1914 /// reading the full object.
1915 /// See the next Branch constructor for a more efficient storage
1916 /// in case the entry consists of arrays of identical objects.
1917 ///
1918 /// By default the branch buffers are stored in the same file as the Tree.
1919 /// use TBranch::SetFile to specify a different file
1920 ///
1921 /// IMPORTANT NOTE about branch names:
1922 ///
1923 /// And in general, in case two or more master branches contain subbranches
1924 /// with identical names, one must add a "." (dot) character at the end
1925 /// of the master branch name. This will force the name of the subbranches
1926 /// to be of the form `master.subbranch` instead of simply `subbranch`.
1927 /// This situation happens when the top level object
1928 /// has two or more members referencing the same class.
1929 /// For example, if a Tree has two branches B1 and B2 corresponding
1930 /// to objects of the same class MyClass, one can do:
1931 /// ~~~ {.cpp}
1932 /// tree.Branch("B1.","MyClass",&b1,8000,1);
1933 /// tree.Branch("B2.","MyClass",&b2,8000,1);
1934 /// ~~~
1935 /// if MyClass has 3 members a,b,c, the two instructions above will generate
1936 /// subbranches called B1.a, B1.b ,B1.c, B2.a, B2.b, B2.c
1937 ///
1938 /// bufsize is the buffer size in bytes for this branch
1939 /// The default value is 32000 bytes and should be ok for most cases.
1940 /// You can specify a larger value (e.g. 256000) if your Tree is not split
1941 /// and each entry is large (Megabytes)
1942 /// A small value for bufsize is optimum if you intend to access
1943 /// the entries in the Tree randomly and your Tree is in split mode.
1945 TBranch* TTree::BranchOld(const char* name, const char* classname, void* addobj, Int_t bufsize /* = 32000 */, Int_t splitlevel /* = 1 */)
1946 {
1947  TClass* cl = TClass::GetClass(classname);
1948  if (!cl) {
1949  Error("BranchOld", "Cannot find class: '%s'", classname);
1950  return 0;
1951  }
1952  if (!cl->IsTObject()) {
1953  if (fgBranchStyle == 0) {
1954  Fatal("BranchOld", "The requested class ('%s') does not inherit from TObject.\n"
1955  "\tfgBranchStyle is set to zero requesting by default to use BranchOld.\n"
1956  "\tIf this is intentional use Bronch instead of Branch or BranchOld.", classname);
1957  } else {
1958  Fatal("BranchOld", "The requested class ('%s') does not inherit from TObject.\n"
1959  "\tYou can not use BranchOld to store objects of this type.",classname);
1960  }
1961  return 0;
1962  }
1963  TBranch* branch = new TBranchObject(this, name, classname, addobj, bufsize, splitlevel);
1964  fBranches.Add(branch);
1965  if (!splitlevel) {
1966  return branch;
1967  }
1968  // We are going to fully split the class now.
1969  TObjArray* blist = branch->GetListOfBranches();
1970  const char* rdname = 0;
1971  const char* dname = 0;
1972  TString branchname;
1973  char** apointer = (char**) addobj;
1974  TObject* obj = (TObject*) *apointer;
1975  Bool_t delobj = kFALSE;
1976  if (!obj) {
1977  obj = (TObject*) cl->New();
1978  delobj = kTRUE;
1979  }
1980  // Build the StreamerInfo if first time for the class.
1981  BuildStreamerInfo(cl, obj);
1982  // Loop on all public data members of the class and its base classes.
1983  Int_t lenName = strlen(name);
1984  Int_t isDot = 0;
1985  if (name[lenName-1] == '.') {
1986  isDot = 1;
1987  }
1988  TBranch* branch1 = 0;
1989  TRealData* rd = 0;
1990  TRealData* rdi = 0;
1991  TIter nexti(cl->GetListOfRealData());
1992  TIter next(cl->GetListOfRealData());
1993  // Note: This loop results in a full split because the
1994  // real data list includes all data members of
1995  // data members.
1996  while ((rd = (TRealData*) next())) {
1997  if (rd->TestBit(TRealData::kTransient)) continue;
1998 
1999  // Loop over all data members creating branches for each one.
2000  TDataMember* dm = rd->GetDataMember();
2001  if (!dm->IsPersistent()) {
2002  // Do not process members with an "!" as the first character in the comment field.
2003  continue;
2004  }
2005  if (rd->IsObject()) {
2006  // We skip data members of class type.
2007  // But we do build their real data, their
2008  // streamer info, and write their streamer
2009  // info to the current directory's file.
2010  // Oh yes, and we also do this for all of
2011  // their base classes.
2012  TClass* clm = TClass::GetClass(dm->GetFullTypeName());
2013  if (clm) {
2014  BuildStreamerInfo(clm, (char*) obj + rd->GetThisOffset());
2015  }
2016  continue;
2017  }
2018  rdname = rd->GetName();
2019  dname = dm->GetName();
2020  if (cl->CanIgnoreTObjectStreamer()) {
2021  // Skip the TObject base class data members.
2022  // FIXME: This prevents a user from ever
2023  // using these names themself!
2024  if (!strcmp(dname, "fBits")) {
2025  continue;
2026  }
2027  if (!strcmp(dname, "fUniqueID")) {
2028  continue;
2029  }
2030  }
2031  TDataType* dtype = dm->GetDataType();
2032  Int_t code = 0;
2033  if (dtype) {
2034  code = dm->GetDataType()->GetType();
2035  }
2036  // Encode branch name. Use real data member name
2037  branchname = rdname;
2038  if (isDot) {
2039  if (dm->IsaPointer()) {
2040  // FIXME: This is wrong! The asterisk is not usually in the front!
2041  branchname.Form("%s%s", name, &rdname[1]);
2042  } else {
2043  branchname.Form("%s%s", name, &rdname[0]);
2044  }
2045  }
2046  // FIXME: Change this to a string stream.
2047  TString leaflist;
2048  Int_t offset = rd->GetThisOffset();
2049  char* pointer = ((char*) obj) + offset;
2050  if (dm->IsaPointer()) {
2051  // We have a pointer to an object or a pointer to an array of basic types.
2052  TClass* clobj = 0;
2053  if (!dm->IsBasic()) {
2054  clobj = TClass::GetClass(dm->GetTypeName());
2055  }
2056  if (clobj && clobj->InheritsFrom(TClonesArray::Class())) {
2057  // We have a pointer to a clones array.
2058  char* cpointer = (char*) pointer;
2059  char** ppointer = (char**) cpointer;
2060  TClonesArray* li = (TClonesArray*) *ppointer;
2061  if (splitlevel != 2) {
2062  if (isDot) {
2063  branch1 = new TBranchClones(branch,branchname, pointer, bufsize);
2064  } else {
2065  // FIXME: This is wrong! The asterisk is not usually in the front!
2066  branch1 = new TBranchClones(branch,&branchname.Data()[1], pointer, bufsize);
2067  }
2068  blist->Add(branch1);
2069  } else {
2070  if (isDot) {
2071  branch1 = new TBranchObject(branch, branchname, li->ClassName(), pointer, bufsize);
2072  } else {
2073  // FIXME: This is wrong! The asterisk is not usually in the front!
2074  branch1 = new TBranchObject(branch, &branchname.Data()[1], li->ClassName(), pointer, bufsize);
2075  }
2076  blist->Add(branch1);
2077  }
2078  } else if (clobj) {
2079  // We have a pointer to an object.
2080  //
2081  // It must be a TObject object.
2082  if (!clobj->IsTObject()) {
2083  continue;
2084  }
2085  branch1 = new TBranchObject(branch, dname, clobj->GetName(), pointer, bufsize, 0);
2086  if (isDot) {
2087  branch1->SetName(branchname);
2088  } else {
2089  // FIXME: This is wrong! The asterisk is not usually in the front!
2090  // Do not use the first character (*).
2091  branch1->SetName(&branchname.Data()[1]);
2092  }
2093  blist->Add(branch1);
2094  } else {
2095  // We have a pointer to an array of basic types.
2096  //
2097  // Check the comments in the text of the code for an index specification.
2098  const char* index = dm->GetArrayIndex();
2099  if (index[0]) {
2100  // We are a pointer to a varying length array of basic types.
2101  //check that index is a valid data member name
2102  //if member is part of an object (e.g. fA and index=fN)
2103  //index must be changed from fN to fA.fN
2104  TString aindex (rd->GetName());
2105  Ssiz_t rdot = aindex.Last('.');
2106  if (rdot>=0) {
2107  aindex.Remove(rdot+1);
2108  aindex.Append(index);
2109  }
2110  nexti.Reset();
2111  while ((rdi = (TRealData*) nexti())) {
2112  if (rdi->TestBit(TRealData::kTransient)) continue;
2113 
2114  if (!strcmp(rdi->GetName(), index)) {
2115  break;
2116  }
2117  if (!strcmp(rdi->GetName(), aindex)) {
2118  index = rdi->GetName();
2119  break;
2120  }
2121  }
2122 
2123  char vcode = DataTypeToChar((EDataType)code);
2124  // Note that we differentiate between strings and
2125  // char array by the fact that there is NO specified
2126  // size for a string (see next if (code == 1)
2127 
2128  if (vcode) {
2129  leaflist.Form("%s[%s]/%c", &rdname[0], index, vcode);
2130  } else {
2131  Error("BranchOld", "Cannot create branch for rdname: %s code: %d", branchname.Data(), code);
2132  leaflist = "";
2133  }
2134  } else {
2135  // We are possibly a character string.
2136  if (code == 1) {
2137  // We are a character string.
2138  leaflist.Form("%s/%s", dname, "C");
2139  } else {
2140  // Invalid array specification.
2141  // FIXME: We need an error message here.
2142  continue;
2143  }
2144  }
2145  // There are '*' in both the branchname and leaflist, remove them.
2146  TString bname( branchname );
2147  bname.ReplaceAll("*","");
2148  leaflist.ReplaceAll("*","");
2149  // Add the branch to the tree and indicate that the address
2150  // is that of a pointer to be dereferenced before using.
2151  branch1 = new TBranch(branch, bname, *((void**) pointer), leaflist, bufsize);
2152  TLeaf* leaf = (TLeaf*) branch1->GetListOfLeaves()->At(0);
2154  leaf->SetAddress((void**) pointer);
2155  blist->Add(branch1);
2156  }
2157  } else if (dm->IsBasic()) {
2158  // We have a basic type.
2159 
2160  char vcode = DataTypeToChar((EDataType)code);
2161  if (vcode) {
2162  leaflist.Form("%s/%c", rdname, vcode);
2163  } else {
2164  Error("BranchOld", "Cannot create branch for rdname: %s code: %d", branchname.Data(), code);
2165  leaflist = "";
2166  }
2167  branch1 = new TBranch(branch, branchname, pointer, leaflist, bufsize);
2168  branch1->SetTitle(rdname);
2169  blist->Add(branch1);
2170  } else {
2171  // We have a class type.
2172  // Note: This cannot happen due to the rd->IsObject() test above.
2173  // FIXME: Put an error message here just in case.
2174  }
2175  if (branch1) {
2176  branch1->SetOffset(offset);
2177  } else {
2178  Warning("BranchOld", "Cannot process member: '%s'", rdname);
2179  }
2180  }
2181  if (delobj) {
2182  delete obj;
2183  obj = 0;
2184  }
2185  return branch;
2186 }
2187 
2188 ////////////////////////////////////////////////////////////////////////////////
2189 /// Build the optional branch supporting the TRefTable.
2190 /// This branch will keep all the information to find the branches
2191 /// containing referenced objects.
2192 ///
2193 /// At each Tree::Fill, the branch numbers containing the
2194 /// referenced objects are saved to the TBranchRef basket.
2195 /// When the Tree header is saved (via TTree::Write), the branch
2196 /// is saved keeping the information with the pointers to the branches
2197 /// having referenced objects.
2200 {
2201  if (!fBranchRef) {
2202  fBranchRef = new TBranchRef(this);
2203  }
2204  return fBranchRef;
2205 }
2206 
2207 ////////////////////////////////////////////////////////////////////////////////
2208 /// Create a new TTree BranchElement.
2209 ///
2210 /// ## WARNING about this new function
2211 ///
2212 /// This function is designed to replace the internal
2213 /// implementation of the old TTree::Branch (whose implementation
2214 /// has been moved to BranchOld).
2215 ///
2216 /// NOTE: The 'Bronch' method supports only one possible calls
2217 /// signature (where the object type has to be specified
2218 /// explicitly and the address must be the address of a pointer).
2219 /// For more flexibility use 'Branch'. Use Bronch only in (rare)
2220 /// cases (likely to be legacy cases) where both the new and old
2221 /// implementation of Branch needs to be used at the same time.
2222 ///
2223 /// This function is far more powerful than the old Branch
2224 /// function. It supports the full C++, including STL and has
2225 /// the same behaviour in split or non-split mode. classname does
2226 /// not have to derive from TObject. The function is based on
2227 /// the new TStreamerInfo.
2228 ///
2229 /// Build a TBranchElement for an object of class classname.
2230 ///
2231 /// addr is the address of a pointer to an object of class
2232 /// classname. The class dictionary must be available (ClassDef
2233 /// in class header).
2234 ///
2235 /// Note: See the comments in TBranchElement::SetAddress() for a more
2236 /// detailed discussion of the meaning of the addr parameter.
2237 ///
2238 /// This option requires access to the library where the
2239 /// corresponding class is defined. Accessing one single data
2240 /// member in the object implies reading the full object.
2241 ///
2242 /// By default the branch buffers are stored in the same file as the Tree.
2243 /// use TBranch::SetFile to specify a different file
2244 ///
2245 /// IMPORTANT NOTE about branch names:
2246 ///
2247 /// And in general, in case two or more master branches contain subbranches
2248 /// with identical names, one must add a "." (dot) character at the end
2249 /// of the master branch name. This will force the name of the subbranches
2250 /// to be of the form `master.subbranch` instead of simply `subbranch`.
2251 /// This situation happens when the top level object
2252 /// has two or more members referencing the same class.
2253 /// For example, if a Tree has two branches B1 and B2 corresponding
2254 /// to objects of the same class MyClass, one can do:
2255 /// ~~~ {.cpp}
2256 /// tree.Branch("B1.","MyClass",&b1,8000,1);
2257 /// tree.Branch("B2.","MyClass",&b2,8000,1);
2258 /// ~~~
2259 /// if MyClass has 3 members a,b,c, the two instructions above will generate
2260 /// subbranches called B1.a, B1.b ,B1.c, B2.a, B2.b, B2.c
2261 ///
2262 /// bufsize is the buffer size in bytes for this branch
2263 /// The default value is 32000 bytes and should be ok for most cases.
2264 /// You can specify a larger value (e.g. 256000) if your Tree is not split
2265 /// and each entry is large (Megabytes)
2266 /// A small value for bufsize is optimum if you intend to access
2267 /// the entries in the Tree randomly and your Tree is in split mode.
2268 ///
2269 /// Use splitlevel < 0 instead of splitlevel=0 when the class
2270 /// has a custom Streamer
2271 ///
2272 /// Note: if the split level is set to the default (99), TTree::Branch will
2273 /// not issue a warning if the class can not be split.
2275 TBranch* TTree::Bronch(const char* name, const char* classname, void* addr, Int_t bufsize /* = 32000 */, Int_t splitlevel /* = 99 */)
2276 {
2277  return BronchExec(name, classname, addr, kTRUE, bufsize, splitlevel);
2278 }
2279 
2280 ////////////////////////////////////////////////////////////////////////////////
2281 /// Helper function implementing TTree::Bronch and TTree::Branch(const char *name, T &obj);
2283 TBranch* TTree::BronchExec(const char* name, const char* classname, void* addr, Bool_t isptrptr, Int_t bufsize /* = 32000 */, Int_t splitlevel /* = 99 */)
2284 {
2285  TClass* cl = TClass::GetClass(classname);
2286  if (!cl) {
2287  Error("Bronch", "Cannot find class:%s", classname);
2288  return 0;
2289  }
2290 
2291  //if splitlevel <= 0 and class has a custom Streamer, we must create
2292  //a TBranchObject. We cannot assume that TClass::ReadBuffer is consistent
2293  //with the custom Streamer. The penalty is that one cannot process
2294  //this Tree without the class library containing the class.
2295 
2296  char* objptr = 0;
2297  if (!isptrptr) {
2298  objptr = (char*)addr;
2299  } else if (addr) {
2300  objptr = *((char**) addr);
2301  }
2302 
2303  if (cl == TClonesArray::Class()) {
2304  TClonesArray* clones = (TClonesArray*) objptr;
2305  if (!clones) {
2306  Error("Bronch", "Pointer to TClonesArray is null");
2307  return 0;
2308  }
2309  if (!clones->GetClass()) {
2310  Error("Bronch", "TClonesArray with no class defined in branch: %s", name);
2311  return 0;
2312  }
2313  if (!clones->GetClass()->HasDataMemberInfo()) {
2314  Error("Bronch", "TClonesArray with no dictionary defined in branch: %s", name);
2315  return 0;
2316  }
2317  bool hasCustomStreamer = clones->GetClass()->TestBit(TClass::kHasCustomStreamerMember);
2318  if (splitlevel > 0) {
2319  if (hasCustomStreamer)
2320  Warning("Bronch", "Using split mode on a class: %s with a custom Streamer", clones->GetClass()->GetName());
2321  } else {
2322  if (hasCustomStreamer) clones->BypassStreamer(kFALSE);
2323  TBranchObject *branch = new TBranchObject(this,name,classname,addr,bufsize,0,/*compress=*/ -1,isptrptr);
2324  fBranches.Add(branch);
2325  return branch;
2326  }
2327  }
2328 
2329  if (cl->GetCollectionProxy()) {
2330  TVirtualCollectionProxy* collProxy = cl->GetCollectionProxy();
2331  //if (!collProxy) {
2332  // Error("Bronch", "%s is missing its CollectionProxy (for branch %s)", classname, name);
2333  //}
2334  TClass* inklass = collProxy->GetValueClass();
2335  if (!inklass && (collProxy->GetType() == 0)) {
2336  Error("Bronch", "%s with no class defined in branch: %s", classname, name);
2337  return 0;
2338  }
2339  if ((splitlevel > 0) && inklass && (inklass->GetCollectionProxy() == 0)) {
2340  ROOT::ESTLType stl = cl->GetCollectionType();
2341  if ((stl != ROOT::kSTLmap) && (stl != ROOT::kSTLmultimap)) {
2342  if (!inklass->HasDataMemberInfo()) {
2343  Error("Bronch", "Container with no dictionary defined in branch: %s", name);
2344  return 0;
2345  }
2346  if (inklass->TestBit(TClass::kHasCustomStreamerMember)) {
2347  Warning("Bronch", "Using split mode on a class: %s with a custom Streamer", inklass->GetName());
2348  }
2349  }
2350  }
2351  //-------------------------------------------------------------------------
2352  // If the splitting switch is enabled, the split level is big enough and
2353  // the collection contains pointers we can split it
2354  //////////////////////////////////////////////////////////////////////////
2355 
2356  TBranch *branch;
2357  if( splitlevel > kSplitCollectionOfPointers && collProxy->HasPointers() )
2358  branch = new TBranchSTL( this, name, collProxy, bufsize, splitlevel );
2359  else
2360  branch = new TBranchElement(this, name, collProxy, bufsize, splitlevel);
2361  fBranches.Add(branch);
2362  if (isptrptr) {
2363  branch->SetAddress(addr);
2364  } else {
2365  branch->SetObject(addr);
2366  }
2367  return branch;
2368  }
2369 
2370  Bool_t hasCustomStreamer = kFALSE;
2371  if (!cl->HasDataMemberInfo() && !cl->GetCollectionProxy()) {
2372  Error("Bronch", "Cannot find dictionary for class: %s", classname);
2373  return 0;
2374  }
2375 
2377  // Not an STL container and the linkdef file had a "-" after the class name.
2378  hasCustomStreamer = kTRUE;
2379  }
2380 
2381  if (splitlevel < 0 || ((splitlevel == 0) && hasCustomStreamer && cl->IsTObject())) {
2382  TBranchObject* branch = new TBranchObject(this, name, classname, addr, bufsize, 0, /*compress=*/ -1, isptrptr);
2383  fBranches.Add(branch);
2384  return branch;
2385  }
2386 
2387  if (cl == TClonesArray::Class()) {
2388  // Special case of TClonesArray.
2389  // No dummy object is created.
2390  // The streamer info is not rebuilt unoptimized.
2391  // No dummy top-level branch is created.
2392  // No splitting is attempted.
2393  TBranchElement* branch = new TBranchElement(this, name, (TClonesArray*) objptr, bufsize, splitlevel%kSplitCollectionOfPointers);
2394  fBranches.Add(branch);
2395  if (isptrptr) {
2396  branch->SetAddress(addr);
2397  } else {
2398  branch->SetObject(addr);
2399  }
2400  return branch;
2401  }
2402 
2403  //
2404  // If we are not given an object to use as an i/o buffer
2405  // then create a temporary one which we will delete just
2406  // before returning.
2407  //
2408 
2409  Bool_t delobj = kFALSE;
2410 
2411  if (!objptr) {
2412  objptr = (char*) cl->New();
2413  delobj = kTRUE;
2414  }
2415 
2416  //
2417  // Avoid splitting unsplittable classes.
2418  //
2419 
2420  if ((splitlevel > 0) && !cl->CanSplit()) {
2421  if (splitlevel != 99) {
2422  Warning("Bronch", "%s cannot be split, resetting splitlevel to 0", cl->GetName());
2423  }
2424  splitlevel = 0;
2425  }
2426 
2427  //
2428  // Make sure the streamer info is built and fetch it.
2429  //
2430  // If we are splitting, then make sure the streamer info
2431  // is built unoptimized (data members are not combined).
2432  //
2433 
2434  TStreamerInfo* sinfo = BuildStreamerInfo(cl, objptr, splitlevel==0);
2435  if (!sinfo) {
2436  Error("Bronch", "Cannot build the StreamerInfo for class: %s", cl->GetName());
2437  return 0;
2438  }
2439 
2440  //
2441  // Create a dummy top level branch object.
2442  //
2443 
2444  Int_t id = -1;
2445  if (splitlevel > 0) {
2446  id = -2;
2447  }
2448  TBranchElement* branch = new TBranchElement(this, name, sinfo, id, objptr, bufsize, splitlevel);
2449  fBranches.Add(branch);
2450 
2451  //
2452  // Do splitting, if requested.
2453  //
2454 
2455  if (splitlevel%kSplitCollectionOfPointers > 0) {
2456  branch->Unroll(name, cl, sinfo, objptr, bufsize, splitlevel);
2457  }
2458 
2459  //
2460  // Setup our offsets into the user's i/o buffer.
2461  //
2462 
2463  if (isptrptr) {
2464  branch->SetAddress(addr);
2465  } else {
2466  branch->SetObject(addr);
2467  }
2468 
2469  if (delobj) {
2470  cl->Destructor(objptr);
2471  objptr = 0;
2472  }
2473 
2474  return branch;
2475 }
2476 
2477 ////////////////////////////////////////////////////////////////////////////////
2478 /// Browse content of the TTree.
2480 void TTree::Browse(TBrowser* b)
2481 {
2482  fBranches.Browse(b);
2483  if (fUserInfo) {
2484  if (strcmp("TList",fUserInfo->GetName())==0) {
2485  fUserInfo->SetName("UserInfo");
2486  b->Add(fUserInfo);
2487  fUserInfo->SetName("TList");
2488  } else {
2489  b->Add(fUserInfo);
2490  }
2491  }
2492 }
2493 
2494 ////////////////////////////////////////////////////////////////////////////////
2495 /// Build a Tree Index (default is TTreeIndex).
2496 /// See a description of the parameters and functionality in
2497 /// TTreeIndex::TTreeIndex().
2498 ///
2499 /// The return value is the number of entries in the Index (< 0 indicates failure).
2500 ///
2501 /// A TTreeIndex object pointed by fTreeIndex is created.
2502 /// This object will be automatically deleted by the TTree destructor.
2503 /// See also comments in TTree::SetTreeIndex().
2505 Int_t TTree::BuildIndex(const char* majorname, const char* minorname /* = "0" */)
2506 {
2507  fTreeIndex = GetPlayer()->BuildIndex(this, majorname, minorname);
2508  if (fTreeIndex->IsZombie()) {
2509  delete fTreeIndex;
2510  fTreeIndex = 0;
2511  return 0;
2512  }
2513  return fTreeIndex->GetN();
2514 }
2515 
2516 ////////////////////////////////////////////////////////////////////////////////
2517 /// Build StreamerInfo for class cl.
2518 /// pointer is an optional argument that may contain a pointer to an object of cl.
2520 TStreamerInfo* TTree::BuildStreamerInfo(TClass* cl, void* pointer /* = 0 */, Bool_t canOptimize /* = kTRUE */ )
2521 {
2522  if (!cl) {
2523  return 0;
2524  }
2525  cl->BuildRealData(pointer);
2527 
2528  // Create StreamerInfo for all base classes.
2529  TBaseClass* base = 0;
2530  TIter nextb(cl->GetListOfBases());
2531  while((base = (TBaseClass*) nextb())) {
2532  if (base->IsSTLContainer()) {
2533  continue;
2534  }
2535  TClass* clm = TClass::GetClass(base->GetName());
2536  BuildStreamerInfo(clm, pointer, canOptimize);
2537  }
2538  if (sinfo && fDirectory) {
2539  sinfo->ForceWriteInfo(fDirectory->GetFile());
2540  }
2541  return sinfo;
2542 }
2543 
2544 ////////////////////////////////////////////////////////////////////////////////
2545 /// Called by TTree::Fill() when file has reached its maximum fgMaxTreeSize.
2546 /// Create a new file. If the original file is named "myfile.root",
2547 /// subsequent files are named "myfile_1.root", "myfile_2.root", etc.
2548 ///
2549 /// Returns a pointer to the new file.
2550 ///
2551 /// Currently, the automatic change of file is restricted
2552 /// to the case where the tree is in the top level directory.
2553 /// The file should not contain sub-directories.
2554 ///
2555 /// Before switching to a new file, the tree header is written
2556 /// to the current file, then the current file is closed.
2557 ///
2558 /// To process the multiple files created by ChangeFile, one must use
2559 /// a TChain.
2560 ///
2561 /// The new file name has a suffix "_N" where N is equal to fFileNumber+1.
2562 /// By default a Root session starts with fFileNumber=0. One can set
2563 /// fFileNumber to a different value via TTree::SetFileNumber.
2564 /// In case a file named "_N" already exists, the function will try
2565 /// a file named "__N", then "___N", etc.
2566 ///
2567 /// fgMaxTreeSize can be set via the static function TTree::SetMaxTreeSize.
2568 /// The default value of fgMaxTreeSize is 100 Gigabytes.
2569 ///
2570 /// If the current file contains other objects like TH1 and TTree,
2571 /// these objects are automatically moved to the new file.
2572 ///
2573 /// IMPORTANT NOTE:
2574 ///
2575 /// Be careful when writing the final Tree header to the file!
2576 ///
2577 /// Don't do:
2578 /// ~~~ {.cpp}
2579 /// TFile *file = new TFile("myfile.root","recreate");
2580 /// TTree *T = new TTree("T","title");
2581 /// T->Fill(); //loop
2582 /// file->Write();
2583 /// file->Close();
2584 /// ~~~
2585 /// but do the following:
2586 /// ~~~ {.cpp}
2587 /// TFile *file = new TFile("myfile.root","recreate");
2588 /// TTree *T = new TTree("T","title");
2589 /// T->Fill(); //loop
2590 /// file = T->GetCurrentFile(); //to get the pointer to the current file
2591 /// file->Write();
2592 /// file->Close();
2593 /// ~~~
2596 {
2597  file->cd();
2598  Write();
2599  Reset();
2600  char* fname = new char[2000];
2601  ++fFileNumber;
2602  char uscore[10];
2603  for (Int_t i = 0; i < 10; ++i) {
2604  uscore[i] = 0;
2605  }
2606  Int_t nus = 0;
2607  // Try to find a suitable file name that does not already exist.
2608  while (nus < 10) {
2609  uscore[nus] = '_';
2610  fname[0] = 0;
2611  strlcpy(fname, file->GetName(),2000);
2612 
2613  if (fFileNumber > 1) {
2614  char* cunder = strrchr(fname, '_');
2615  if (cunder) {
2616  snprintf(cunder,2000-Int_t(cunder-fname), "%s%d", uscore, fFileNumber);
2617  const char* cdot = strrchr(file->GetName(), '.');
2618  if (cdot) {
2619  strlcat(fname, cdot,2000);
2620  }
2621  } else {
2622  char fcount[10];
2623  snprintf(fcount,10, "%s%d", uscore, fFileNumber);
2624  strlcat(fname, fcount,2000);
2625  }
2626  } else {
2627  char* cdot = strrchr(fname, '.');
2628  if (cdot) {
2629  snprintf(cdot,2000-Int_t(fname-cdot), "%s%d", uscore, fFileNumber);
2630  strlcat(fname, strrchr(file->GetName(), '.'),2000);
2631  } else {
2632  char fcount[10];
2633  snprintf(fcount,10, "%s%d", uscore, fFileNumber);
2634  strlcat(fname, fcount,2000);
2635  }
2636  }
2637  if (gSystem->AccessPathName(fname)) {
2638  break;
2639  }
2640  ++nus;
2641  Warning("ChangeFile", "file %s already exist, trying with %d underscores", fname, nus+1);
2642  }
2643  Int_t compress = file->GetCompressionSettings();
2644  TFile* newfile = TFile::Open(fname, "recreate", "chain files", compress);
2645  if (newfile == 0) {
2646  Error("Fill","Failed to open new file %s, continuing as a memory tree.",fname);
2647  } else {
2648  Printf("Fill: Switching to new file: %s", fname);
2649  }
2650  // The current directory may contain histograms and trees.
2651  // These objects must be moved to the new file.
2652  TBranch* branch = 0;
2653  TObject* obj = 0;
2654  while ((obj = file->GetList()->First())) {
2655  file->Remove(obj);
2656  // Histogram: just change the directory.
2657  if (obj->InheritsFrom("TH1")) {
2658  gROOT->ProcessLine(TString::Format("((%s*)0x%lx)->SetDirectory((TDirectory*)0x%lx);", obj->ClassName(), (Long_t) obj, (Long_t) newfile));
2659  continue;
2660  }
2661  // Tree: must save all trees in the old file, reset them.
2662  if (obj->InheritsFrom(TTree::Class())) {
2663  TTree* t = (TTree*) obj;
2664  if (t != this) {
2665  t->AutoSave();
2666  t->Reset();
2667  t->fFileNumber = fFileNumber;
2668  }
2669  t->SetDirectory(newfile);
2670  TIter nextb(t->GetListOfBranches());
2671  while ((branch = (TBranch*)nextb())) {
2672  branch->SetFile(newfile);
2673  }
2674  if (t->GetBranchRef()) {
2675  t->GetBranchRef()->SetFile(newfile);
2676  }
2677  continue;
2678  }
2679  // Not a TH1 or a TTree, move object to new file.
2680  if (newfile) newfile->Append(obj);
2681  file->Remove(obj);
2682  }
2683  delete file;
2684  file = 0;
2685  delete[] fname;
2686  fname = 0;
2687  return newfile;
2688 }
2689 
2690 ////////////////////////////////////////////////////////////////////////////////
2691 /// Check whether or not the address described by the last 3 parameters
2692 /// matches the content of the branch. If a Data Model Evolution conversion
2693 /// is involved, reset the fInfo of the branch.
2694 /// The return values are:
2695 //
2696 /// - kMissingBranch (-5) : Missing branch
2697 /// - kInternalError (-4) : Internal error (could not find the type corresponding to a data type number)
2698 /// - kMissingCompiledCollectionProxy (-3) : Missing compiled collection proxy for a compiled collection
2699 /// - kMismatch (-2) : Non-Class Pointer type given does not match the type expected by the branch
2700 /// - kClassMismatch (-1) : Class Pointer type given does not match the type expected by the branch
2701 /// - kMatch (0) : perfect match
2702 /// - kMatchConversion (1) : match with (I/O) conversion
2703 /// - kMatchConversionCollection (2) : match with (I/O) conversion of the content of a collection
2704 /// - kMakeClass (3) : MakeClass mode so we can not check.
2705 /// - kVoidPtr (4) : void* passed so no check was made.
2706 /// - kNoCheck (5) : Underlying TBranch not yet available so no check was made.
2708 Int_t TTree::CheckBranchAddressType(TBranch* branch, TClass* ptrClass, EDataType datatype, Bool_t isptr)
2709 {
2710  if (GetMakeClass()) {
2711  // If we are in MakeClass mode so we do not really use classes.
2712  return kMakeClass;
2713  }
2714 
2715  // Let's determine what we need!
2716  TClass* expectedClass = 0;
2717  EDataType expectedType = kOther_t;
2718  if (0 != branch->GetExpectedType(expectedClass,expectedType) ) {
2719  // Something went wrong, the warning message has already be issued.
2720  return kInternalError;
2721  }
2722  if (expectedClass && datatype == kOther_t && ptrClass == 0) {
2723  if (branch->InheritsFrom( TBranchElement::Class() )) {
2724  TBranchElement* bEl = (TBranchElement*)branch;
2725  bEl->SetTargetClass( expectedClass->GetName() );
2726  }
2727  if (expectedClass && expectedClass->GetCollectionProxy() && dynamic_cast<TEmulatedCollectionProxy*>(expectedClass->GetCollectionProxy())) {
2728  Error("SetBranchAddress", "Unable to determine the type given for the address for \"%s\". "
2729  "The class expected (%s) refers to an stl collection and do not have a compiled CollectionProxy. "
2730  "Please generate the dictionary for this class (%s)",
2731  branch->GetName(), expectedClass->GetName(), expectedClass->GetName());
2733  }
2734  if (!expectedClass->IsLoaded()) {
2735  // The originally expected class does not have a dictionary, it is then plausible that the pointer being passed is the right type
2736  // (we really don't know). So let's express that.
2737  Error("SetBranchAddress", "Unable to determine the type given for the address for \"%s\". "
2738  "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."
2739  "Please generate the dictionary for this class (%s)",
2740  branch->GetName(), expectedClass->GetName(), expectedClass->GetName());
2741  } else {
2742  Error("SetBranchAddress", "Unable to determine the type given for the address for \"%s\". "
2743  "This is probably due to a missing dictionary, the original data class for this branch is %s.", branch->GetName(), expectedClass->GetName());
2744  }
2745  return kClassMismatch;
2746  }
2747  if (expectedClass && ptrClass && (branch->GetMother() == branch)) {
2748  // Top Level branch
2749  if (!isptr) {
2750  Error("SetBranchAddress", "The address for \"%s\" should be the address of a pointer!", branch->GetName());
2751  }
2752  }
2753  if (expectedType == kFloat16_t) {
2754  expectedType = kFloat_t;
2755  }
2756  if (expectedType == kDouble32_t) {
2757  expectedType = kDouble_t;
2758  }
2759  if (datatype == kFloat16_t) {
2760  datatype = kFloat_t;
2761  }
2762  if (datatype == kDouble32_t) {
2763  datatype = kDouble_t;
2764  }
2765 
2766  /////////////////////////////////////////////////////////////////////////////
2767  // Deal with the class renaming
2768  /////////////////////////////////////////////////////////////////////////////
2769 
2770  if( expectedClass && ptrClass &&
2771  expectedClass != ptrClass &&
2772  branch->InheritsFrom( TBranchElement::Class() ) &&
2773  ptrClass->GetSchemaRules() &&
2774  ptrClass->GetSchemaRules()->HasRuleWithSourceClass( expectedClass->GetName() ) ) {
2775  TBranchElement* bEl = (TBranchElement*)branch;
2776 
2777  if ( ptrClass->GetCollectionProxy() && expectedClass->GetCollectionProxy() ) {
2778  if (gDebug > 7)
2779  Info("SetBranchAddress", "Matching STL collection (at least according to the SchemaRuleSet when "
2780  "reading a %s into a %s",expectedClass->GetName(),ptrClass->GetName());
2781 
2782  bEl->SetTargetClass( ptrClass->GetName() );
2783  return kMatchConversion;
2784 
2785  } else if ( !ptrClass->GetConversionStreamerInfo( expectedClass, bEl->GetClassVersion() ) &&
2786  !ptrClass->FindConversionStreamerInfo( expectedClass, bEl->GetCheckSum() ) ) {
2787  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());
2788 
2789  bEl->SetTargetClass( expectedClass->GetName() );
2790  return kClassMismatch;
2791  }
2792  else {
2793 
2794  bEl->SetTargetClass( ptrClass->GetName() );
2795  return kMatchConversion;
2796  }
2797 
2798  } else if (expectedClass && ptrClass && !expectedClass->InheritsFrom(ptrClass)) {
2799 
2800  if (expectedClass->GetCollectionProxy() && ptrClass->GetCollectionProxy() &&
2801  branch->InheritsFrom( TBranchElement::Class() ) &&
2802  expectedClass->GetCollectionProxy()->GetValueClass() &&
2803  ptrClass->GetCollectionProxy()->GetValueClass() )
2804  {
2805  // In case of collection, we know how to convert them, if we know how to convert their content.
2806  // NOTE: we need to extend this to std::pair ...
2807 
2808  TClass *onfileValueClass = expectedClass->GetCollectionProxy()->GetValueClass();
2809  TClass *inmemValueClass = ptrClass->GetCollectionProxy()->GetValueClass();
2810 
2811  if (inmemValueClass->GetSchemaRules() &&
2812  inmemValueClass->GetSchemaRules()->HasRuleWithSourceClass(onfileValueClass->GetName() ) )
2813  {
2814  TBranchElement* bEl = (TBranchElement*)branch;
2815  bEl->SetTargetClass( ptrClass->GetName() );
2817  }
2818  }
2819 
2820  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());
2821  if (branch->InheritsFrom( TBranchElement::Class() )) {
2822  TBranchElement* bEl = (TBranchElement*)branch;
2823  bEl->SetTargetClass( expectedClass->GetName() );
2824  }
2825  return kClassMismatch;
2826 
2827  } else if ((expectedType != kOther_t) && (datatype != kOther_t) && (expectedType != kNoType_t) && (datatype != kNoType_t) && (expectedType != datatype)) {
2828  if (datatype != kChar_t) {
2829  // For backward compatibility we assume that (char*) was just a cast and/or a generic address
2830  Error("SetBranchAddress", "The pointer type given \"%s\" (%d) does not correspond to the type needed \"%s\" (%d) by the branch: %s",
2831  TDataType::GetTypeName(datatype), datatype, TDataType::GetTypeName(expectedType), expectedType, branch->GetName());
2832  return kMismatch;
2833  }
2834  } else if ((expectedClass && (datatype != kOther_t && datatype != kNoType_t && datatype != kInt_t)) ||
2835  (ptrClass && (expectedType != kOther_t && expectedType != kNoType_t && datatype != kInt_t)) ) {
2836  // Sometime a null pointer can look an int, avoid complaining in that case.
2837  if (expectedClass) {
2838  Error("SetBranchAddress", "The pointer type given \"%s\" (%d) does not correspond to the type needed \"%s\" by the branch: %s",
2839  TDataType::GetTypeName(datatype), datatype, expectedClass->GetName(), branch->GetName());
2840  if (branch->InheritsFrom( TBranchElement::Class() )) {
2841  TBranchElement* bEl = (TBranchElement*)branch;
2842  bEl->SetTargetClass( expectedClass->GetName() );
2843  }
2844  } else {
2845  // 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
2846  // a struct).
2847  bool found = false;
2848  if (ptrClass->IsLoaded()) {
2849  TIter next(ptrClass->GetListOfRealData());
2850  TRealData *rdm;
2851  while ((rdm = (TRealData*)next())) {
2852  if (rdm->GetThisOffset() == 0) {
2853  TDataType *dmtype = rdm->GetDataMember()->GetDataType();
2854  if (dmtype) {
2855  EDataType etype = (EDataType)dmtype->GetType();
2856  if (etype == expectedType) {
2857  found = true;
2858  }
2859  }
2860  break;
2861  }
2862  }
2863  } else {
2864  TIter next(ptrClass->GetListOfDataMembers());
2865  TDataMember *dm;
2866  while ((dm = (TDataMember*)next())) {
2867  if (dm->GetOffset() == 0) {
2868  TDataType *dmtype = dm->GetDataType();
2869  if (dmtype) {
2870  EDataType etype = (EDataType)dmtype->GetType();
2871  if (etype == expectedType) {
2872  found = true;
2873  }
2874  }
2875  break;
2876  }
2877  }
2878  }
2879  if (found) {
2880  // let's check the size.
2881  TLeaf *last = (TLeaf*)branch->GetListOfLeaves()->Last();
2882  long len = last->GetOffset() + last->GetLenType() * last->GetLen();
2883  if (len <= ptrClass->Size()) {
2884  return kMatch;
2885  }
2886  }
2887  Error("SetBranchAddress", "The pointer type given \"%s\" does not correspond to the type needed \"%s\" (%d) by the branch: %s",
2888  ptrClass->GetName(), TDataType::GetTypeName(expectedType), expectedType, branch->GetName());
2889  }
2890  return kMismatch;
2891  }
2892  if (expectedClass && expectedClass->GetCollectionProxy() && dynamic_cast<TEmulatedCollectionProxy*>(expectedClass->GetCollectionProxy())) {
2893  Error("SetBranchAddress", writeStlWithoutProxyMsg,
2894  expectedClass->GetName(), branch->GetName(), expectedClass->GetName());
2895  if (branch->InheritsFrom( TBranchElement::Class() )) {
2896  TBranchElement* bEl = (TBranchElement*)branch;
2897  bEl->SetTargetClass( expectedClass->GetName() );
2898  }
2900  }
2901  if (expectedClass && branch->InheritsFrom( TBranchElement::Class() )) {
2902  TBranchElement* bEl = (TBranchElement*)branch;
2903  bEl->SetTargetClass( expectedClass->GetName() );
2904  }
2905  return kMatch;
2906 }
2907 
2908 ////////////////////////////////////////////////////////////////////////////////
2909 /// Create a clone of this tree and copy nentries.
2910 ///
2911 /// By default copy all entries.
2912 /// The compression level of the cloned tree is set to the destination
2913 /// file's compression level.
2914 ///
2915 /// NOTE: Only active branches are copied.
2916 /// NOTE: If the TTree is a TChain, the structure of the first TTree
2917 /// is used for the copy.
2918 ///
2919 /// IMPORTANT: The cloned tree stays connected with this tree until
2920 /// this tree is deleted. In particular, any changes in
2921 /// branch addresses in this tree are forwarded to the
2922 /// clone trees, unless a branch in a clone tree has had
2923 /// its address changed, in which case that change stays in
2924 /// effect. When this tree is deleted, all the addresses of
2925 /// the cloned tree are reset to their default values.
2926 ///
2927 /// If 'option' contains the word 'fast' and nentries is -1, the
2928 /// cloning will be done without unzipping or unstreaming the baskets
2929 /// (i.e., a direct copy of the raw bytes on disk).
2930 ///
2931 /// When 'fast' is specified, 'option' can also contain a sorting
2932 /// order for the baskets in the output file.
2933 ///
2934 /// There are currently 3 supported sorting order:
2935 ///
2936 /// - SortBasketsByOffset (the default)
2937 /// - SortBasketsByBranch
2938 /// - SortBasketsByEntry
2939 ///
2940 /// When using SortBasketsByOffset the baskets are written in the
2941 /// output file in the same order as in the original file (i.e. the
2942 /// baskets are sorted by their offset in the original file; Usually
2943 /// this also means that the baskets are sorted by the index/number of
2944 /// the _last_ entry they contain)
2945 ///
2946 /// When using SortBasketsByBranch all the baskets of each individual
2947 /// branches are stored contiguously. This tends to optimize reading
2948 /// speed when reading a small number (1->5) of branches, since all
2949 /// their baskets will be clustered together instead of being spread
2950 /// across the file. However it might decrease the performance when
2951 /// reading more branches (or the full entry).
2952 ///
2953 /// When using SortBasketsByEntry the baskets with the lowest starting
2954 /// entry are written first. (i.e. the baskets are sorted by the
2955 /// index/number of the first entry they contain). This means that on
2956 /// the file the baskets will be in the order in which they will be
2957 /// needed when reading the whole tree sequentially.
2958 ///
2959 /// For examples of CloneTree, see tutorials:
2960 ///
2961 /// - copytree.C:
2962 /// A macro to copy a subset of a TTree to a new TTree.
2963 /// The input file has been generated by the program in
2964 /// $ROOTSYS/test/Event with: Event 1000 1 1 1
2965 ///
2966 /// - copytree2.C:
2967 /// A macro to copy a subset of a TTree to a new TTree.
2968 /// One branch of the new Tree is written to a separate file.
2969 /// The input file has been generated by the program in
2970 /// $ROOTSYS/test/Event with: Event 1000 1 1 1
2972 TTree* TTree::CloneTree(Long64_t nentries /* = -1 */, Option_t* option /* = "" */)
2973 {
2974  // Options
2975  Bool_t fastClone = kFALSE;
2976 
2977  TString opt = option;
2978  opt.ToLower();
2979  if (opt.Contains("fast")) {
2980  fastClone = kTRUE;
2981  }
2982 
2983  // If we are a chain, switch to the first tree.
2984  if ((fEntries > 0) && (LoadTree(0) < 0)) {
2985  // FIXME: We need an error message here.
2986  return 0;
2987  }
2988 
2989  // Note: For a tree we get the this pointer, for
2990  // a chain we get the chain's current tree.
2991  TTree* thistree = GetTree();
2992 
2993  // We will use this to override the IO features on the cloned branches.
2994  ROOT::TIOFeatures features = this->GetIOFeatures();
2995  ;
2996 
2997  // Note: For a chain, the returned clone will be
2998  // a clone of the chain's first tree.
2999  TTree* newtree = (TTree*) thistree->Clone();
3000  if (!newtree) {
3001  return 0;
3002  }
3003 
3004  // The clone should not delete any objects allocated by SetAddress().
3005  TObjArray* branches = newtree->GetListOfBranches();
3006  Int_t nb = branches->GetEntriesFast();
3007  for (Int_t i = 0; i < nb; ++i) {
3008  TBranch* br = (TBranch*) branches->UncheckedAt(i);
3009  if (br->InheritsFrom(TBranchElement::Class())) {
3010  ((TBranchElement*) br)->ResetDeleteObject();
3011  }
3012  }
3013 
3014  // Add the new tree to the list of clones so that
3015  // we can later inform it of changes to branch addresses.
3016  thistree->AddClone(newtree);
3017  if (thistree != this) {
3018  // In case this object is a TChain, add the clone
3019  // also to the TChain's list of clones.
3020  AddClone(newtree);
3021  }
3022 
3023  newtree->Reset();
3024 
3025  TDirectory* ndir = newtree->GetDirectory();
3026  TFile* nfile = 0;
3027  if (ndir) {
3028  nfile = ndir->GetFile();
3029  }
3030  Int_t newcomp = -1;
3031  if (nfile) {
3032  newcomp = nfile->GetCompressionSettings();
3033  }
3034 
3035  //
3036  // Delete non-active branches from the clone.
3037  //
3038  // Note: If we are a chain, this does nothing
3039  // since chains have no leaves.
3040  TObjArray* leaves = newtree->GetListOfLeaves();
3041  Int_t nleaves = leaves->GetEntriesFast();
3042  for (Int_t lndx = 0; lndx < nleaves; ++lndx) {
3043  TLeaf* leaf = (TLeaf*) leaves->UncheckedAt(lndx);
3044  if (!leaf) {
3045  continue;
3046  }
3047  TBranch* branch = leaf->GetBranch();
3048  if (branch && (newcomp > -1)) {
3049  branch->SetCompressionSettings(newcomp);
3050  }
3051  if (branch) branch->SetIOFeatures(features);
3052  if (!branch || !branch->TestBit(kDoNotProcess)) {
3053  continue;
3054  }
3055  // size might change at each iteration of the loop over the leaves.
3056  nb = branches->GetEntriesFast();
3057  for (Long64_t i = 0; i < nb; ++i) {
3058  TBranch* br = (TBranch*) branches->UncheckedAt(i);
3059  if (br == branch) {
3060  branches->RemoveAt(i);
3061  delete br;
3062  br = 0;
3063  branches->Compress();
3064  break;
3065  }
3066  TObjArray* lb = br->GetListOfBranches();
3067  Int_t nb1 = lb->GetEntriesFast();
3068  for (Int_t j = 0; j < nb1; ++j) {
3069  TBranch* b1 = (TBranch*) lb->UncheckedAt(j);
3070  if (!b1) {
3071  continue;
3072  }
3073  if (b1 == branch) {
3074  lb->RemoveAt(j);
3075  delete b1;
3076  b1 = 0;
3077  lb->Compress();
3078  break;
3079  }
3080  TObjArray* lb1 = b1->GetListOfBranches();
3081  Int_t nb2 = lb1->GetEntriesFast();
3082  for (Int_t k = 0; k < nb2; ++k) {
3083  TBranch* b2 = (TBranch*) lb1->UncheckedAt(k);
3084  if (!b2) {
3085  continue;
3086  }
3087  if (b2 == branch) {
3088  lb1->RemoveAt(k);
3089  delete b2;
3090  b2 = 0;
3091  lb1->Compress();
3092  break;
3093  }
3094  }
3095  }
3096  }
3097  }
3098  leaves->Compress();
3099 
3100  // Copy MakeClass status.
3101  newtree->SetMakeClass(fMakeClass);
3102 
3103  // Copy branch addresses.
3104  CopyAddresses(newtree);
3105 
3106  //
3107  // Copy entries if requested.
3108  //
3109 
3110  if (nentries != 0) {
3111  if (fastClone && (nentries < 0)) {
3112  if ( newtree->CopyEntries( this, -1, option ) < 0 ) {
3113  // There was a problem!
3114  Error("CloneTTree", "TTree has not been cloned\n");
3115  delete newtree;
3116  newtree = 0;
3117  return 0;
3118  }
3119  } else {
3120  newtree->CopyEntries( this, nentries, option );
3121  }
3122  }
3123 
3124  return newtree;
3125 }
3126 
3127 ////////////////////////////////////////////////////////////////////////////////
3128 /// Set branch addresses of passed tree equal to ours.
3129 /// If undo is true, reset the branch address instead of copying them.
3130 /// This insures 'separation' of a cloned tree from its original
3133 {
3134  // Copy branch addresses starting from branches.
3136  Int_t nbranches = branches->GetEntriesFast();
3137  for (Int_t i = 0; i < nbranches; ++i) {
3138  TBranch* branch = (TBranch*) branches->UncheckedAt(i);
3139  if (branch->TestBit(kDoNotProcess)) {
3140  continue;
3141  }
3142  if (undo) {
3143  TBranch* br = tree->GetBranch(branch->GetName());
3144  tree->ResetBranchAddress(br);
3145  } else {
3146  char* addr = branch->GetAddress();
3147  if (!addr) {
3148  if (branch->IsA() == TBranch::Class()) {
3149  // If the branch was created using a leaflist, the branch itself may not have
3150  // an address but the leaf might already.
3151  TLeaf *firstleaf = (TLeaf*)branch->GetListOfLeaves()->At(0);
3152  if (!firstleaf || firstleaf->GetValuePointer()) {
3153  // Either there is no leaf (and thus no point in copying the address)
3154  // or the leaf has an address but we can not copy it via the branche
3155  // this will be copied via the next loop (over the leaf).
3156  continue;
3157  }
3158  }
3159  // Note: This may cause an object to be allocated.
3160  branch->SetAddress(0);
3161  addr = branch->GetAddress();
3162  }
3163  // FIXME: The GetBranch() function is braindead and may
3164  // not find the branch!
3165  TBranch* br = tree->GetBranch(branch->GetName());
3166  if (br) {
3167  br->SetAddress(addr);
3168  // The copy does not own any object allocated by SetAddress().
3169  if (br->InheritsFrom(TBranchElement::Class())) {
3170  ((TBranchElement*) br)->ResetDeleteObject();
3171  }
3172  } else {
3173  Warning("CopyAddresses", "Could not find branch named '%s' in tree named '%s'", branch->GetName(), tree->GetName());
3174  }
3175  }
3176  }
3177 
3178  // Copy branch addresses starting from leaves.
3179  TObjArray* tleaves = tree->GetListOfLeaves();
3180  Int_t ntleaves = tleaves->GetEntriesFast();
3181  for (Int_t i = 0; i < ntleaves; ++i) {
3182  TLeaf* tleaf = (TLeaf*) tleaves->UncheckedAt(i);
3183  TBranch* tbranch = tleaf->GetBranch();
3184  TBranch* branch = GetBranch(tbranch->GetName());
3185  if (!branch) {
3186  continue;
3187  }
3188  TLeaf* leaf = branch->GetLeaf(tleaf->GetName());
3189  if (!leaf) {
3190  continue;
3191  }
3192  if (branch->TestBit(kDoNotProcess)) {
3193  continue;
3194  }
3195  if (undo) {
3196  // Now we know whether the address has been transfered
3197  tree->ResetBranchAddress(tbranch);
3198  } else {
3199  TBranchElement *mother = dynamic_cast<TBranchElement*>(leaf->GetBranch()->GetMother());
3200  if (leaf->GetLeafCount() && (leaf->TestBit(TLeaf::kNewValue) || !leaf->GetValuePointer() || (mother && mother->IsObjectOwner())) && tleaf->GetLeafCount())
3201  {
3202  // If it is an array and it was allocated by the leaf itself,
3203  // let's make sure it is large enough for the incoming data.
3204  if (leaf->GetLeafCount()->GetMaximum() < tleaf->GetLeafCount()->GetMaximum()) {
3205  leaf->GetLeafCount()->IncludeRange( tleaf->GetLeafCount() );
3206  if (leaf->GetValuePointer()) {
3207  if (leaf->IsA() == TLeafElement::Class() && mother)
3208  mother->ResetAddress();
3209  else
3210  leaf->SetAddress(nullptr);
3211  }
3212  }
3213  }
3214  if (!branch->GetAddress() && !leaf->GetValuePointer()) {
3215  // We should attempts to set the address of the branch.
3216  // something like:
3217  //(TBranchElement*)branch->GetMother()->SetAddress(0)
3218  //plus a few more subtilities (see TBranchElement::GetEntry).
3219  //but for now we go the simplest route:
3220  //
3221  // Note: This may result in the allocation of an object.
3222  branch->SetupAddresses();
3223  }
3224  if (branch->GetAddress()) {
3225  tree->SetBranchAddress(branch->GetName(), (void*) branch->GetAddress());
3226  TBranch* br = tree->GetBranch(branch->GetName());
3227  if (br) {
3228  // The copy does not own any object allocated by SetAddress().
3229  // FIXME: We do too much here, br may not be a top-level branch.
3230  if (br->InheritsFrom(TBranchElement::Class())) {
3231  ((TBranchElement*) br)->ResetDeleteObject();
3232  }
3233  } else {
3234  Warning("CopyAddresses", "Could not find branch named '%s' in tree named '%s'", branch->GetName(), tree->GetName());
3235  }
3236  } else {
3237  tleaf->SetAddress(leaf->GetValuePointer());
3238  }
3239  }
3240  }
3241 
3242  if (undo &&
3243  ( tree->IsA()->InheritsFrom("TNtuple") || tree->IsA()->InheritsFrom("TNtupleD") )
3244  ) {
3245  tree->ResetBranchAddresses();
3246  }
3247 }
3248 
3249 namespace {
3251  enum EOnIndexError { kDrop, kKeep, kBuild };
3252 
3253  static Bool_t R__HandleIndex(EOnIndexError onIndexError, TTree *newtree, TTree *oldtree)
3254  {
3255  // Return true if we should continue to handle indices, false otherwise.
3256 
3257  Bool_t withIndex = kTRUE;
3258 
3259  if ( newtree->GetTreeIndex() ) {
3260  if ( oldtree->GetTree()->GetTreeIndex() == 0 ) {
3261  switch (onIndexError) {
3262  case kDrop:
3263  delete newtree->GetTreeIndex();
3264  newtree->SetTreeIndex(0);
3265  withIndex = kFALSE;
3266  break;
3267  case kKeep:
3268  // Nothing to do really.
3269  break;
3270  case kBuild:
3271  // Build the index then copy it
3272  if (oldtree->GetTree()->BuildIndex(newtree->GetTreeIndex()->GetMajorName(), newtree->GetTreeIndex()->GetMinorName())) {
3273  newtree->GetTreeIndex()->Append(oldtree->GetTree()->GetTreeIndex(), kTRUE);
3274  // Clean up
3275  delete oldtree->GetTree()->GetTreeIndex();
3276  oldtree->GetTree()->SetTreeIndex(0);
3277  }
3278  break;
3279  }
3280  } else {
3281  newtree->GetTreeIndex()->Append(oldtree->GetTree()->GetTreeIndex(), kTRUE);
3282  }
3283  } else if ( oldtree->GetTree()->GetTreeIndex() != 0 ) {
3284  // We discover the first index in the middle of the chain.
3285  switch (onIndexError) {
3286  case kDrop:
3287  // Nothing to do really.
3288  break;
3289  case kKeep: {
3290  TVirtualIndex *index = (TVirtualIndex*) oldtree->GetTree()->GetTreeIndex()->Clone();
3291  index->SetTree(newtree);
3292  newtree->SetTreeIndex(index);
3293  break;
3294  }
3295  case kBuild:
3296  if (newtree->GetEntries() == 0) {
3297  // Start an index.
3298  TVirtualIndex *index = (TVirtualIndex*) oldtree->GetTree()->GetTreeIndex()->Clone();
3299  index->SetTree(newtree);
3300  newtree->SetTreeIndex(index);
3301  } else {
3302  // Build the index so far.
3303  if (newtree->BuildIndex(oldtree->GetTree()->GetTreeIndex()->GetMajorName(), oldtree->GetTree()->GetTreeIndex()->GetMinorName())) {
3304  newtree->GetTreeIndex()->Append(oldtree->GetTree()->GetTreeIndex(), kTRUE);
3305  }
3306  }
3307  break;
3308  }
3309  } else if ( onIndexError == kDrop ) {
3310  // There is no index on this or on tree->GetTree(), we know we have to ignore any further
3311  // index
3312  withIndex = kFALSE;
3313  }
3314  return withIndex;
3315  }
3316 }
3317 
3318 ////////////////////////////////////////////////////////////////////////////////
3319 /// Copy nentries from given tree to this tree.
3320 /// This routines assumes that the branches that intended to be copied are
3321 /// already connected. The typical case is that this tree was created using
3322 /// tree->CloneTree(0).
3323 ///
3324 /// By default copy all entries.
3325 ///
3326 /// Returns number of bytes copied to this tree.
3327 ///
3328 /// If 'option' contains the word 'fast' and nentries is -1, the cloning will be
3329 /// done without unzipping or unstreaming the baskets (i.e., a direct copy of the
3330 /// raw bytes on disk).
3331 ///
3332 /// When 'fast' is specified, 'option' can also contains a sorting order for the
3333 /// baskets in the output file.
3334 ///
3335 /// There are currently 3 supported sorting order:
3336 ///
3337 /// - SortBasketsByOffset (the default)
3338 /// - SortBasketsByBranch
3339 /// - SortBasketsByEntry
3340 ///
3341 /// See TTree::CloneTree for a detailed explanation of the semantics of these 3 options.
3342 ///
3343 /// If the tree or any of the underlying tree of the chain has an index, that index and any
3344 /// index in the subsequent underlying TTree objects will be merged.
3345 ///
3346 /// There are currently three 'options' to control this merging:
3347 /// - NoIndex : all the TTreeIndex object are dropped.
3348 /// - DropIndexOnError : if any of the underlying TTree object do no have a TTreeIndex,
3349 /// they are all dropped.
3350 /// - AsIsIndexOnError [default]: In case of missing TTreeIndex, the resulting TTree index has gaps.
3351 /// - BuildIndexOnError : If any of the underlying TTree objects do not have a TTreeIndex,
3352 /// all TTreeIndex are 'ignored' and the missing piece are rebuilt.
3354 Long64_t TTree::CopyEntries(TTree* tree, Long64_t nentries /* = -1 */, Option_t* option /* = "" */)
3355 {
3356  if (!tree) {
3357  return 0;
3358  }
3359  // Options
3360  TString opt = option;
3361  opt.ToLower();
3362  Bool_t fastClone = opt.Contains("fast");
3363  Bool_t withIndex = !opt.Contains("noindex");
3364  EOnIndexError onIndexError;
3365  if (opt.Contains("asisindex")) {
3366  onIndexError = kKeep;
3367  } else if (opt.Contains("buildindex")) {
3368  onIndexError = kBuild;
3369  } else if (opt.Contains("dropindex")) {
3370  onIndexError = kDrop;
3371  } else {
3372  onIndexError = kBuild;
3373  }
3374  Ssiz_t cacheSizeLoc = opt.Index("cachesize=");
3375  Int_t cacheSize = -1;
3376  if (cacheSizeLoc != TString::kNPOS) {
3377  // If the parse faile, cacheSize stays at -1.
3378  Ssiz_t cacheSizeEnd = opt.Index(" ",cacheSizeLoc+10) - (cacheSizeLoc+10);
3379  TSubString cacheSizeStr( opt(cacheSizeLoc+10,cacheSizeEnd) );
3380  auto parseResult = ROOT::FromHumanReadableSize(cacheSizeStr,cacheSize);
3381  if (parseResult == ROOT::EFromHumanReadableSize::kParseFail) {
3382  Warning("CopyEntries","The cachesize option can not be parsed: %s. The default size will be used.",cacheSizeStr.String().Data());
3383  } else if (parseResult == ROOT::EFromHumanReadableSize::kOverflow) {
3384  double m;
3385  const char *munit = nullptr;
3386  ROOT::ToHumanReadableSize(std::numeric_limits<decltype(cacheSize)>::max(),false,&m,&munit);
3387 
3388  Warning("CopyEntries","The cachesize option is too large: %s (%g%s max). The default size will be used.",cacheSizeStr.String().Data(),m,munit);
3389  }
3390  }
3391  if (gDebug > 0 && cacheSize != -1) Info("CopyEntries","Using Cache size: %d\n",cacheSize);
3392 
3393  Long64_t nbytes = 0;
3394  Long64_t treeEntries = tree->GetEntriesFast();
3395  if (nentries < 0) {
3396  nentries = treeEntries;
3397  } else if (nentries > treeEntries) {
3398  nentries = treeEntries;
3399  }
3400 
3401  if (fastClone && (nentries < 0 || nentries == tree->GetEntriesFast())) {
3402  // Quickly copy the basket without decompression and streaming.
3403  Long64_t totbytes = GetTotBytes();
3404  for (Long64_t i = 0; i < nentries; i += tree->GetTree()->GetEntries()) {
3405  if (tree->LoadTree(i) < 0) {
3406  break;
3407  }
3408  if ( withIndex ) {
3409  withIndex = R__HandleIndex( onIndexError, this, tree );
3410  }
3411  if (this->GetDirectory()) {
3412  TFile* file2 = this->GetDirectory()->GetFile();
3413  if (file2 && (file2->GetEND() > TTree::GetMaxTreeSize())) {
3414  if (this->GetDirectory() == (TDirectory*) file2) {
3415  this->ChangeFile(file2);
3416  }
3417  }
3418  }
3419  TTreeCloner cloner(tree->GetTree(), this, option, TTreeCloner::kNoWarnings);
3420  if (cloner.IsValid()) {
3421  this->SetEntries(this->GetEntries() + tree->GetTree()->GetEntries());
3422  if (cacheSize != -1) cloner.SetCacheSize(cacheSize);
3423  cloner.Exec();
3424  } else {
3425  if (i == 0) {
3426  Warning("CopyEntries","%s",cloner.GetWarning());
3427  // If the first cloning does not work, something is really wrong
3428  // (since apriori the source and target are exactly the same structure!)
3429  return -1;
3430  } else {
3431  if (cloner.NeedConversion()) {
3432  TTree *localtree = tree->GetTree();
3433  Long64_t tentries = localtree->GetEntries();
3434  for (Long64_t ii = 0; ii < tentries; ii++) {
3435  if (localtree->GetEntry(ii) <= 0) {
3436  break;
3437  }
3438  this->Fill();
3439  }
3440  if (this->GetTreeIndex()) {
3441  this->GetTreeIndex()->Append(tree->GetTree()->GetTreeIndex(), kTRUE);
3442  }
3443  } else {
3444  Warning("CopyEntries","%s",cloner.GetWarning());
3445  if (tree->GetDirectory() && tree->GetDirectory()->GetFile()) {
3446  Warning("CopyEntries", "Skipped file %s\n", tree->GetDirectory()->GetFile()->GetName());
3447  } else {
3448  Warning("CopyEntries", "Skipped file number %d\n", tree->GetTreeNumber());
3449  }
3450  }
3451  }
3452  }
3453 
3454  }
3455  if (this->GetTreeIndex()) {
3456  this->GetTreeIndex()->Append(0,kFALSE); // Force the sorting
3457  }
3458  nbytes = GetTotBytes() - totbytes;
3459  } else {
3460  if (nentries < 0) {
3461  nentries = treeEntries;
3462  } else if (nentries > treeEntries) {
3463  nentries = treeEntries;
3464  }
3465  Int_t treenumber = -1;
3466  for (Long64_t i = 0; i < nentries; i++) {
3467  if (tree->LoadTree(i) < 0) {
3468  break;
3469  }
3470  if (treenumber != tree->GetTreeNumber()) {
3471  if ( withIndex ) {
3472  withIndex = R__HandleIndex( onIndexError, this, tree );
3473  }
3474  treenumber = tree->GetTreeNumber();
3475  }
3476  if (tree->GetEntry(i) <= 0) {
3477  break;
3478  }
3479  nbytes += this->Fill();
3480  }
3481  if (this->GetTreeIndex()) {
3482  this->GetTreeIndex()->Append(0,kFALSE); // Force the sorting
3483  }
3484  }
3485  return nbytes;
3486 }
3487 
3488 ////////////////////////////////////////////////////////////////////////////////
3489 /// Copy a tree with selection.
3490 ///
3491 /// ### Important:
3492 ///
3493 /// The returned copied tree stays connected with the original tree
3494 /// until the original tree is deleted. In particular, any changes
3495 /// to the branch addresses in the original tree are also made to
3496 /// the copied tree. Any changes made to the branch addresses of the
3497 /// copied tree are overridden anytime the original tree changes its
3498 /// branch addresses. When the original tree is deleted, all the
3499 /// branch addresses of the copied tree are set to zero.
3500 ///
3501 /// For examples of CopyTree, see the tutorials:
3502 ///
3503 /// - copytree.C:
3504 /// Example macro to copy a subset of a tree to a new tree.
3505 /// The input file was generated by running the program in
3506 /// $ROOTSYS/test/Event in this way:
3507 /// ~~~ {.cpp}
3508 /// ./Event 1000 1 1 1
3509 /// ~~~
3510 /// - copytree2.C
3511 /// Example macro to copy a subset of a tree to a new tree.
3512 /// One branch of the new tree is written to a separate file.
3513 /// The input file was generated by running the program in
3514 /// $ROOTSYS/test/Event in this way:
3515 /// ~~~ {.cpp}
3516 /// ./Event 1000 1 1 1
3517 /// ~~~
3518 /// - copytree3.C
3519 /// Example macro to copy a subset of a tree to a new tree.
3520 /// Only selected entries are copied to the new tree.
3521 /// NOTE that only the active branches are copied.
3523 TTree* TTree::CopyTree(const char* selection, Option_t* option /* = 0 */, Long64_t nentries /* = TTree::kMaxEntries */, Long64_t firstentry /* = 0 */)
3524 {
3525  GetPlayer();
3526  if (fPlayer) {
3527  return fPlayer->CopyTree(selection, option, nentries, firstentry);
3528  }
3529  return 0;
3530 }
3531 
3532 ////////////////////////////////////////////////////////////////////////////////
3533 /// Create a basket for this tree and given branch.
3536 {
3537  if (!branch) {
3538  return 0;
3539  }
3540  return new TBasket(branch->GetName(), GetName(), branch);
3541 }
3542 
3543 ////////////////////////////////////////////////////////////////////////////////
3544 /// Delete this tree from memory or/and disk.
3545 ///
3546 /// - if option == "all" delete Tree object from memory AND from disk
3547 /// all baskets on disk are deleted. All keys with same name
3548 /// are deleted.
3549 /// - if option =="" only Tree object in memory is deleted.
3551 void TTree::Delete(Option_t* option /* = "" */)
3552 {
3553  TFile *file = GetCurrentFile();
3554 
3555  // delete all baskets and header from file
3556  if (file && !strcmp(option,"all")) {
3557  if (!file->IsWritable()) {
3558  Error("Delete","File : %s is not writable, cannot delete Tree:%s", file->GetName(),GetName());
3559  return;
3560  }
3561 
3562  //find key and import Tree header in memory
3563  TKey *key = fDirectory->GetKey(GetName());
3564  if (!key) return;
3565 
3566  TDirectory *dirsav = gDirectory;
3567  file->cd();
3568 
3569  //get list of leaves and loop on all the branches baskets
3570  TIter next(GetListOfLeaves());
3571  TLeaf *leaf;
3572  char header[16];
3573  Int_t ntot = 0;
3574  Int_t nbask = 0;
3575  Int_t nbytes,objlen,keylen;
3576  while ((leaf = (TLeaf*)next())) {
3577  TBranch *branch = leaf->GetBranch();
3578  Int_t nbaskets = branch->GetMaxBaskets();
3579  for (Int_t i=0;i<nbaskets;i++) {
3580  Long64_t pos = branch->GetBasketSeek(i);
3581  if (!pos) continue;
3582  TFile *branchFile = branch->GetFile();
3583  if (!branchFile) continue;
3584  branchFile->GetRecordHeader(header,pos,16,nbytes,objlen,keylen);
3585  if (nbytes <= 0) continue;
3586  branchFile->MakeFree(pos,pos+nbytes-1);
3587  ntot += nbytes;
3588  nbask++;
3589  }
3590  }
3591 
3592  // delete Tree header key and all keys with the same name
3593  // A Tree may have been saved many times. Previous cycles are invalid.
3594  while (key) {
3595  ntot += key->GetNbytes();
3596  key->Delete();
3597  delete key;
3598  key = fDirectory->GetKey(GetName());
3599  }
3600  if (dirsav) dirsav->cd();
3601  if (gDebug) Info("TTree::Delete", "Deleting Tree: %s: %d baskets deleted. Total space freed = %d bytes\n",GetName(),nbask,ntot);
3602  }
3603 
3604  if (fDirectory) {
3605  fDirectory->Remove(this);
3606  //delete the file cache if it points to this Tree
3607  MoveReadCache(file,0);
3608  fDirectory = 0;
3610  }
3611 
3612  // Delete object from CINT symbol table so it can not be used anymore.
3613  gCling->DeleteGlobal(this);
3614 
3615  // Warning: We have intentional invalidated this object while inside a member function!
3616  delete this;
3617 }
3618 
3619  ///////////////////////////////////////////////////////////////////////////////
3620  /// Called by TKey and TObject::Clone to automatically add us to a directory
3621  /// when we are read from a file.
3624 {
3625  if (fDirectory == dir) return;
3626  if (fDirectory) {
3627  fDirectory->Remove(this);
3628  // Delete or move the file cache if it points to this Tree
3629  TFile *file = fDirectory->GetFile();
3630  MoveReadCache(file,dir);
3631  }
3632  fDirectory = dir;
3633  TBranch* b = 0;
3634  TIter next(GetListOfBranches());
3635  while((b = (TBranch*) next())) {
3636  b->UpdateFile();
3637  }
3638  if (fBranchRef) {
3640  }
3641  if (fDirectory) fDirectory->Append(this);
3642 }
3643 
3644 ////////////////////////////////////////////////////////////////////////////////
3645 /// Draw expression varexp for specified entries.
3646 ///
3647 /// \return -1 in case of error or number of selected events in case of success.
3648 ///
3649 /// This function accepts TCut objects as arguments.
3650 /// Useful to use the string operator +
3651 ///
3652 /// Example:
3653 ///
3654 /// ~~~ {.cpp}
3655 /// ntuple.Draw("x",cut1+cut2+cut3);
3656 /// ~~~
3657 
3659 Long64_t TTree::Draw(const char* varexp, const TCut& selection, Option_t* option, Long64_t nentries, Long64_t firstentry)
3660 {
3661  return TTree::Draw(varexp, selection.GetTitle(), option, nentries, firstentry);
3662 }
3663 
3664 ////////////////////////////////////////////////////////////////////////////////
3665 /// Draw expression varexp for specified entries.
3666 ///
3667 /// \return -1 in case of error or number of selected events in case of success.
3668 ///
3669 /// \param [in] varexp is an expression of the general form
3670 /// - "e1" produces a 1-d histogram (TH1F) of expression "e1"
3671 /// - "e1:e2" produces an unbinned 2-d scatter-plot (TGraph) of "e1"
3672 /// on the y-axis versus "e2" on the x-axis
3673 /// - "e1:e2:e3" produces an unbinned 3-d scatter-plot (TPolyMarker3D) of "e1"
3674 /// vs "e2" vs "e3" on the x-, y-, z-axis, respectively.
3675 /// - "e1:e2:e3:e4" produces an unbinned 3-d scatter-plot (TPolyMarker3D) of "e1"
3676 /// vs "e2" vs "e3" and "e4" mapped on the current color palette.
3677 /// (to create histograms in the 2, 3, and 4 dimensional case,
3678 /// see section "Saving the result of Draw to an histogram")
3679 ///
3680 /// Example:
3681 /// - varexp = x simplest case: draw a 1-Dim distribution of column named x
3682 /// - varexp = sqrt(x) : draw distribution of sqrt(x)
3683 /// - varexp = x*y/z
3684 /// - varexp = y:sqrt(x) 2-Dim distribution of y versus sqrt(x)
3685 /// - varexp = px:py:pz:2.5*E produces a 3-d scatter-plot of px vs py ps pz
3686 /// and the color number of each marker will be 2.5*E.
3687 /// If the color number is negative it is set to 0.
3688 /// If the color number is greater than the current number of colors
3689 /// it is set to the highest color number.The default number of
3690 /// colors is 50. see TStyle::SetPalette for setting a new color palette.
3691 ///
3692 /// Note that the variables e1, e2 or e3 may contain a selection.
3693 /// example, if e1= x*(y<0), the value histogrammed will be x if y<0
3694 /// and will be 0 otherwise.
3695 ///
3696 /// The expressions can use all the operations and build-in functions
3697 /// supported by TFormula (See TFormula::Analyze), including free
3698 /// standing function taking numerical arguments (TMath::Bessel).
3699 /// In addition, you can call member functions taking numerical
3700 /// arguments. For example:
3701 /// ~~~ {.cpp}
3702 /// TMath::BreitWigner(fPx,3,2)
3703 /// event.GetHistogram().GetXaxis().GetXmax()
3704 /// ~~~
3705 /// Note: You can only pass expression that depend on the TTree's data
3706 /// to static functions and you can only call non-static member function
3707 /// with 'fixed' parameters.
3708 ///
3709 /// \param [in] selection is an expression with a combination of the columns.
3710 /// In a selection all the C++ operators are authorized.
3711 /// The value corresponding to the selection expression is used as a weight
3712 /// to fill the histogram.
3713 /// If the expression includes only boolean operations, the result
3714 /// is 0 or 1. If the result is 0, the histogram is not filled.
3715 /// In general, the expression may be of the form:
3716 /// ~~~ {.cpp}
3717 /// value*(boolean expression)
3718 /// ~~~
3719 /// if boolean expression is true, the histogram is filled with
3720 /// a `weight = value`.
3721 /// Examples:
3722 /// - selection1 = "x<y && sqrt(z)>3.2"
3723 /// - selection2 = "(x+y)*(sqrt(z)>3.2)"
3724 /// - selection1 returns a weight = 0 or 1
3725 /// - selection2 returns a weight = x+y if sqrt(z)>3.2
3726 /// returns a weight = 0 otherwise.
3727 ///
3728 /// \param [in] option is the drawing option.
3729 /// - When an histogram is produced it can be any histogram drawing option
3730 /// listed in THistPainter.
3731 /// - when no option is specified:
3732 /// - the default histogram drawing option is used
3733 /// if the expression is of the form "e1".
3734 /// - if the expression is of the form "e1:e2"or "e1:e2:e3" a cloud of
3735 /// unbinned 2D or 3D points is drawn respectively.
3736 /// - if the expression has four fields "e1:e2:e3:e4" a 2D scatter is
3737 /// produced with e1 vs e2 vs e3, and e4 is mapped on the current color
3738 /// palette.
3739 /// - If option COL is specified when varexp has three fields:
3740 /// ~~~ {.cpp}
3741 /// tree.Draw("e1:e2:e3","","col");
3742 /// ~~~
3743 /// a 2D scatter is produced with e1 vs e2, and e3 is mapped on the current
3744 /// color palette. The colors for e3 are evaluated once in linear scale before
3745 /// painting. Therefore changing the pad to log scale along Z as no effect
3746 /// on the colors.
3747 /// - if expression has more than four fields the option "PARA"or "CANDLE"
3748 /// can be used.
3749 /// - If option contains the string "goff", no graphics is generated.
3750 ///
3751 /// \param [in] nentries is the number of entries to process (default is all)
3752 ///
3753 /// \param [in] firstentry is the first entry to process (default is 0)
3754 ///
3755 /// ### Drawing expressions using arrays and array elements
3756 ///
3757 /// Let assumes, a leaf fMatrix, on the branch fEvent, which is a 3 by 3 array,
3758 /// or a TClonesArray.
3759 /// In a TTree::Draw expression you can now access fMatrix using the following
3760 /// syntaxes:
3761 ///
3762 /// | String passed | What is used for each entry of the tree
3763 /// |-----------------|--------------------------------------------------------|
3764 /// | `fMatrix` | the 9 elements of fMatrix |
3765 /// | `fMatrix[][]` | the 9 elements of fMatrix |
3766 /// | `fMatrix[2][2]` | only the elements fMatrix[2][2] |
3767 /// | `fMatrix[1]` | the 3 elements fMatrix[1][0], fMatrix[1][1] and fMatrix[1][2] |
3768 /// | `fMatrix[1][]` | the 3 elements fMatrix[1][0], fMatrix[1][1] and fMatrix[1][2] |
3769 /// | `fMatrix[][0]` | the 3 elements fMatrix[0][0], fMatrix[1][0] and fMatrix[2][0] |
3770 ///
3771 /// "fEvent.fMatrix...." same as "fMatrix..." (unless there is more than one leaf named fMatrix!).
3772 ///
3773 /// In summary, if a specific index is not specified for a dimension, TTree::Draw
3774 /// will loop through all the indices along this dimension. Leaving off the
3775 /// last (right most) dimension of specifying then with the two characters '[]'
3776 /// is equivalent. For variable size arrays (and TClonesArray) the range
3777 /// of the first dimension is recalculated for each entry of the tree.
3778 /// You can also specify the index as an expression of any other variables from the
3779 /// tree.
3780 ///
3781 /// TTree::Draw also now properly handling operations involving 2 or more arrays.
3782 ///
3783 /// Let assume a second matrix fResults[5][2], here are a sample of some
3784 /// of the possible combinations, the number of elements they produce and
3785 /// the loop used:
3786 ///
3787 /// | expression | element(s) | Loop |
3788 /// |----------------------------------|------------|--------------------------|
3789 /// | `fMatrix[2][1] - fResults[5][2]` | one | no loop |
3790 /// | `fMatrix[2][] - fResults[5][2]` | three | on 2nd dim fMatrix |
3791 /// | `fMatrix[2][] - fResults[5][]` | two | on both 2nd dimensions |
3792 /// | `fMatrix[][2] - fResults[][1]` | three | on both 1st dimensions |
3793 /// | `fMatrix[][2] - fResults[][]` | six | on both 1st and 2nd dimensions of fResults |
3794 /// | `fMatrix[][2] - fResults[3][]` | two | on 1st dim of fMatrix and 2nd of fResults (at the same time) |
3795 /// | `fMatrix[][] - fResults[][]` | six | on 1st dim then on 2nd dim |
3796 /// | `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.|
3797 ///
3798 ///
3799 /// In summary, TTree::Draw loops through all unspecified dimensions. To
3800 /// figure out the range of each loop, we match each unspecified dimension
3801 /// from left to right (ignoring ALL dimensions for which an index has been
3802 /// specified), in the equivalent loop matched dimensions use the same index
3803 /// and are restricted to the smallest range (of only the matched dimensions).
3804 /// When involving variable arrays, the range can of course be different
3805 /// for each entry of the tree.
3806 ///
3807 /// So the loop equivalent to "fMatrix[][2] - fResults[3][]" is:
3808 /// ~~~ {.cpp}
3809 /// for (Int_t i0; i < min(3,2); i++) {
3810 /// use the value of (fMatrix[i0][2] - fMatrix[3][i0])
3811 /// }
3812 /// ~~~
3813 /// So the loop equivalent to "fMatrix[][2] - fResults[][]" is:
3814 /// ~~~ {.cpp}
3815 /// for (Int_t i0; i < min(3,5); i++) {
3816 /// for (Int_t i1; i1 < 2; i1++) {
3817 /// use the value of (fMatrix[i0][2] - fMatrix[i0][i1])
3818 /// }
3819 /// }
3820 /// ~~~
3821 /// So the loop equivalent to "fMatrix[][] - fResults[][]" is:
3822 /// ~~~ {.cpp}
3823 /// for (Int_t i0; i < min(3,5); i++) {
3824 /// for (Int_t i1; i1 < min(3,2); i1++) {
3825 /// use the value of (fMatrix[i0][i1] - fMatrix[i0][i1])
3826 /// }
3827 /// }
3828 /// ~~~
3829 /// So the loop equivalent to "fMatrix[][fResults[][]]" is:
3830 /// ~~~ {.cpp}
3831 /// for (Int_t i0; i0 < 3; i0++) {
3832 /// for (Int_t j2; j2 < 5; j2++) {
3833 /// for (Int_t j3; j3 < 2; j3++) {
3834 /// i1 = fResults[j2][j3];
3835 /// use the value of fMatrix[i0][i1]
3836 /// }
3837 /// }
3838 /// ~~~
3839 /// ### Retrieving the result of Draw
3840 ///
3841 /// By default the temporary histogram created is called "htemp", but only in
3842 /// the one dimensional Draw("e1") it contains the TTree's data points. For
3843 /// a two dimensional Draw, the data is filled into a TGraph which is named
3844 /// "Graph". They can be retrieved by calling
3845 /// ~~~ {.cpp}
3846 /// TH1F *htemp = (TH1F*)gPad->GetPrimitive("htemp"); // 1D
3847 /// TGraph *graph = (TGraph*)gPad->GetPrimitive("Graph"); // 2D
3848 /// ~~~
3849 /// For a three and four dimensional Draw the TPolyMarker3D is unnamed, and
3850 /// cannot be retrieved.
3851 ///
3852 /// gPad always contains a TH1 derived object called "htemp" which allows to
3853 /// access the axes:
3854 /// ~~~ {.cpp}
3855 /// TGraph *graph = (TGraph*)gPad->GetPrimitive("Graph"); // 2D
3856 /// TH2F *htemp = (TH2F*)gPad->GetPrimitive("htemp"); // empty, but has axes
3857 /// TAxis *xaxis = htemp->GetXaxis();
3858 /// ~~~
3859 /// ### Saving the result of Draw to an histogram
3860 ///
3861 /// If varexp0 contains >>hnew (following the variable(s) name(s),
3862 /// the new histogram created is called hnew and it is kept in the current
3863 /// directory (and also the current pad). This works for all dimensions.
3864 ///
3865 /// Example:
3866 /// ~~~ {.cpp}
3867 /// tree.Draw("sqrt(x)>>hsqrt","y>0")
3868 /// ~~~
3869 /// will draw `sqrt(x)` and save the histogram as "hsqrt" in the current
3870 /// directory. To retrieve it do:
3871 /// ~~~ {.cpp}
3872 /// TH1F *hsqrt = (TH1F*)gDirectory->Get("hsqrt");
3873 /// ~~~
3874 /// The binning information is taken from the environment variables
3875 /// ~~~ {.cpp}
3876 /// Hist.Binning.?D.?
3877 /// ~~~
3878 /// In addition, the name of the histogram can be followed by up to 9
3879 /// numbers between '(' and ')', where the numbers describe the
3880 /// following:
3881 ///
3882 /// - 1 - bins in x-direction
3883 /// - 2 - lower limit in x-direction
3884 /// - 3 - upper limit in x-direction
3885 /// - 4-6 same for y-direction
3886 /// - 7-9 same for z-direction
3887 ///
3888 /// When a new binning is used the new value will become the default.
3889 /// Values can be skipped.
3890 ///
3891 /// Example:
3892 /// ~~~ {.cpp}
3893 /// tree.Draw("sqrt(x)>>hsqrt(500,10,20)")
3894 /// // plot sqrt(x) between 10 and 20 using 500 bins
3895 /// tree.Draw("sqrt(x):sin(y)>>hsqrt(100,10,60,50,.1,.5)")
3896 /// // plot sqrt(x) against sin(y)
3897 /// // 100 bins in x-direction; lower limit on x-axis is 10; upper limit is 60
3898 /// // 50 bins in y-direction; lower limit on y-axis is .1; upper limit is .5
3899 /// ~~~
3900 /// By default, the specified histogram is reset.
3901 /// To continue to append data to an existing histogram, use "+" in front
3902 /// of the histogram name.
3903 ///
3904 /// A '+' in front of the histogram name is ignored, when the name is followed by
3905 /// binning information as described in the previous paragraph.
3906 /// ~~~ {.cpp}
3907 /// tree.Draw("sqrt(x)>>+hsqrt","y>0")
3908 /// ~~~
3909 /// will not reset `hsqrt`, but will continue filling. This works for 1-D, 2-D
3910 /// and 3-D histograms.
3911 ///
3912 /// ### Accessing collection objects
3913 ///
3914 /// TTree::Draw default's handling of collections is to assume that any
3915 /// request on a collection pertain to it content. For example, if fTracks
3916 /// is a collection of Track objects, the following:
3917 /// ~~~ {.cpp}
3918 /// tree->Draw("event.fTracks.fPx");
3919 /// ~~~
3920 /// will plot the value of fPx for each Track objects inside the collection.
3921 /// Also
3922 /// ~~~ {.cpp}
3923 /// tree->Draw("event.fTracks.size()");
3924 /// ~~~
3925 /// would plot the result of the member function Track::size() for each
3926 /// Track object inside the collection.
3927 /// To access information about the collection itself, TTree::Draw support
3928 /// the '@' notation. If a variable which points to a collection is prefixed
3929 /// or postfixed with '@', the next part of the expression will pertain to
3930 /// the collection object. For example:
3931 /// ~~~ {.cpp}
3932 /// tree->Draw("event.@fTracks.size()");
3933 /// ~~~
3934 /// will plot the size of the collection referred to by `fTracks` (i.e the number
3935 /// of Track objects).
3936 ///
3937 /// ### Drawing 'objects'
3938 ///
3939 /// When a class has a member function named AsDouble or AsString, requesting
3940 /// to directly draw the object will imply a call to one of the 2 functions.
3941 /// If both AsDouble and AsString are present, AsDouble will be used.
3942 /// AsString can return either a char*, a std::string or a TString.s
3943 /// For example, the following
3944 /// ~~~ {.cpp}
3945 /// tree->Draw("event.myTTimeStamp");
3946 /// ~~~
3947 /// will draw the same histogram as
3948 /// ~~~ {.cpp}
3949 /// tree->Draw("event.myTTimeStamp.AsDouble()");
3950 /// ~~~
3951 /// In addition, when the object is a type TString or std::string, TTree::Draw
3952 /// will call respectively `TString::Data` and `std::string::c_str()`
3953 ///
3954 /// If the object is a TBits, the histogram will contain the index of the bit
3955 /// that are turned on.
3956 ///
3957 /// ### Retrieving information about the tree itself.
3958 ///
3959 /// You can refer to the tree (or chain) containing the data by using the
3960 /// string 'This'.
3961 /// You can then could any TTree methods. For example:
3962 /// ~~~ {.cpp}
3963 /// tree->Draw("This->GetReadEntry()");
3964 /// ~~~
3965 /// will display the local entry numbers be read.
3966 /// ~~~ {.cpp}
3967 /// tree->Draw("This->GetUserInfo()->At(0)->GetName()");
3968 /// ~~~
3969 /// will display the name of the first 'user info' object.
3970 ///
3971 /// ### Special functions and variables
3972 ///
3973 /// `Entry$`: A TTree::Draw formula can use the special variable `Entry$`
3974 /// to access the entry number being read. For example to draw every
3975 /// other entry use:
3976 /// ~~~ {.cpp}
3977 /// tree.Draw("myvar","Entry$%2==0");
3978 /// ~~~
3979 /// - `Entry$` : return the current entry number (`== TTree::GetReadEntry()`)
3980 /// - `LocalEntry$` : return the current entry number in the current tree of a
3981 /// chain (`== GetTree()->GetReadEntry()`)
3982 /// - `Entries$` : return the total number of entries (== TTree::GetEntries())
3983 /// - `LocalEntries$` : return the total number of entries in the current tree
3984 /// of a chain (== GetTree()->TTree::GetEntries())
3985 /// - `Length$` : return the total number of element of this formula for this
3986 /// entry (`==TTreeFormula::GetNdata()`)
3987 /// - `Iteration$` : return the current iteration over this formula for this
3988 /// entry (i.e. varies from 0 to `Length$`).
3989 /// - `Length$(formula )` : return the total number of element of the formula
3990 /// given as a parameter.
3991 /// - `Sum$(formula )` : return the sum of the value of the elements of the
3992 /// formula given as a parameter. For example the mean for all the elements in
3993 /// one entry can be calculated with: `Sum$(formula )/Length$(formula )`
3994 /// - `Min$(formula )` : return the minimun (within one TTree entry) of the value of the
3995 /// elements of the formula given as a parameter.
3996 /// - `Max$(formula )` : return the maximum (within one TTree entry) of the value of the
3997 /// elements of the formula given as a parameter.
3998 /// - `MinIf$(formula,condition)`
3999 /// - `MaxIf$(formula,condition)` : return the minimum (maximum) (within one TTree entry)
4000 /// of the value of the elements of the formula given as a parameter
4001 /// if they match the condition. If no element matches the condition,
4002 /// the result is zero. To avoid the resulting peak at zero, use the
4003 /// pattern:
4004 /// ~~~ {.cpp}
4005 /// tree->Draw("MinIf$(formula,condition)","condition");
4006 /// ~~~
4007 /// which will avoid calculation `MinIf$` for the entries that have no match
4008 /// for the condition.
4009 /// - `Alt$(primary,alternate)` : return the value of "primary" if it is available
4010 /// for the current iteration otherwise return the value of "alternate".
4011 /// For example, with arr1[3] and arr2[2]
4012 /// ~~~ {.cpp}
4013 /// tree->Draw("arr1+Alt$(arr2,0)");
4014 /// ~~~
4015 /// will draw arr1[0]+arr2[0] ; arr1[1]+arr2[1] and arr1[2]+0
4016 /// Or with a variable size array arr3
4017 /// ~~~ {.cpp}
4018 /// tree->Draw("Alt$(arr3[0],0)+Alt$(arr3[1],0)+Alt$(arr3[2],0)");
4019 /// ~~~
4020 /// will draw the sum arr3 for the index 0 to min(2,actual_size_of_arr3-1)
4021 /// As a comparison
4022 /// ~~~ {.cpp}
4023 /// tree->Draw("arr3[0]+arr3[1]+arr3[2]");
4024 /// ~~~
4025 /// will draw the sum arr3 for the index 0 to 2 only if the
4026 /// actual_size_of_arr3 is greater or equal to 3.
4027 /// Note that the array in 'primary' is flattened/linearized thus using
4028 /// `Alt$` with multi-dimensional arrays of different dimensions in unlikely
4029 /// to yield the expected results. To visualize a bit more what elements
4030 /// would be matched by TTree::Draw, TTree::Scan can be used:
4031 /// ~~~ {.cpp}
4032 /// tree->Scan("arr1:Alt$(arr2,0)");
4033 /// ~~~
4034 /// will print on one line the value of arr1 and (arr2,0) that will be
4035 /// matched by
4036 /// ~~~ {.cpp}
4037 /// tree->Draw("arr1-Alt$(arr2,0)");
4038 /// ~~~
4039 /// The ternary operator is not directly supported in TTree::Draw however, to plot the
4040 /// equivalent of `var2<20 ? -99 : var1`, you can use:
4041 /// ~~~ {.cpp}
4042 /// tree->Draw("(var2<20)*99+(var2>=20)*var1","");
4043 /// ~~~
4044 ///
4045 /// ### Drawing a user function accessing the TTree data directly
4046 ///
4047 /// If the formula contains a file name, TTree::MakeProxy will be used
4048 /// to load and execute this file. In particular it will draw the
4049 /// result of a function with the same name as the file. The function
4050 /// will be executed in a context where the name of the branches can
4051 /// be used as a C++ variable.
4052 ///
4053 /// For example draw px using the file hsimple.root (generated by the
4054 /// hsimple.C tutorial), we need a file named hsimple.cxx:
4055 /// ~~~ {.cpp}
4056 /// double hsimple() {
4057 /// return px;
4058 /// }
4059 /// ~~~
4060 /// MakeProxy can then be used indirectly via the TTree::Draw interface
4061 /// as follow:
4062 /// ~~~ {.cpp}
4063 /// new TFile("hsimple.root")
4064 /// ntuple->Draw("hsimple.cxx");
4065 /// ~~~
4066 /// A more complete example is available in the tutorials directory:
4067 /// `h1analysisProxy.cxx`, `h1analysProxy.h` and `h1analysisProxyCut.C`
4068 /// which reimplement the selector found in `h1analysis.C`
4069 ///
4070 /// The main features of this facility are:
4071 ///
4072 /// * on-demand loading of branches
4073 /// * ability to use the 'branchname' as if it was a data member
4074 /// * protection against array out-of-bound
4075 /// * ability to use the branch data as object (when the user code is available)
4076 ///
4077 /// See TTree::MakeProxy for more details.
4078 ///
4079 /// ### Making a Profile histogram
4080 ///
4081 /// In case of a 2-Dim expression, one can generate a TProfile histogram
4082 /// instead of a TH2F histogram by specifying option=prof or option=profs
4083 /// or option=profi or option=profg ; the trailing letter select the way
4084 /// the bin error are computed, See TProfile2D::SetErrorOption for
4085 /// details on the differences.
4086 /// The option=prof is automatically selected in case of y:x>>pf
4087 /// where pf is an existing TProfile histogram.
4088 ///
4089 /// ### Making a 2D Profile histogram
4090 ///
4091 /// In case of a 3-Dim expression, one can generate a TProfile2D histogram
4092 /// instead of a TH3F histogram by specifying option=prof or option=profs.
4093 /// or option=profi or option=profg ; the trailing letter select the way
4094 /// the bin error are computed, See TProfile2D::SetErrorOption for
4095 /// details on the differences.
4096 /// The option=prof is automatically selected in case of z:y:x>>pf
4097 /// where pf is an existing TProfile2D histogram.
4098 ///
4099 /// ### Making a 5D plot using GL
4100 ///
4101 /// If option GL5D is specified together with 5 variables, a 5D plot is drawn
4102 /// using OpenGL. See $ROOTSYS/tutorials/tree/staff.C as example.
4103 ///
4104 /// ### Making a parallel coordinates plot
4105 ///
4106 /// In case of a 2-Dim or more expression with the option=para, one can generate
4107 /// a parallel coordinates plot. With that option, the number of dimensions is
4108 /// arbitrary. Giving more than 4 variables without the option=para or
4109 /// option=candle or option=goff will produce an error.
4110 ///
4111 /// ### Making a candle sticks chart
4112 ///
4113 /// In case of a 2-Dim or more expression with the option=candle, one can generate
4114 /// a candle sticks chart. With that option, the number of dimensions is
4115 /// arbitrary. Giving more than 4 variables without the option=para or
4116 /// option=candle or option=goff will produce an error.
4117 ///
4118 /// ### Normalizing the output histogram to 1
4119 ///
4120 /// When option contains "norm" the output histogram is normalized to 1.
4121 ///
4122 /// ### Saving the result of Draw to a TEventList, a TEntryList or a TEntryListArray
4123 ///
4124 /// TTree::Draw can be used to fill a TEventList object (list of entry numbers)
4125 /// instead of histogramming one variable.
4126 /// If varexp0 has the form >>elist , a TEventList object named "elist"
4127 /// is created in the current directory. elist will contain the list
4128 /// of entry numbers satisfying the current selection.
4129 /// If option "entrylist" is used, a TEntryList object is created
4130 /// If the selection contains arrays, vectors or any container class and option
4131 /// "entrylistarray" is used, a TEntryListArray object is created
4132 /// containing also the subentries satisfying the selection, i.e. the indices of
4133 /// the branches which hold containers classes.
4134 /// Example:
4135 /// ~~~ {.cpp}
4136 /// tree.Draw(">>yplus","y>0")
4137 /// ~~~
4138 /// will create a TEventList object named "yplus" in the current directory.
4139 /// In an interactive session, one can type (after TTree::Draw)
4140 /// ~~~ {.cpp}
4141 /// yplus.Print("all")
4142 /// ~~~
4143 /// to print the list of entry numbers in the list.
4144 /// ~~~ {.cpp}
4145 /// tree.Draw(">>yplus", "y>0", "entrylist")
4146 /// ~~~
4147 /// will create a TEntryList object names "yplus" in the current directory
4148 /// ~~~ {.cpp}
4149 /// tree.Draw(">>yplus", "y>0", "entrylistarray")
4150 /// ~~~
4151 /// will create a TEntryListArray object names "yplus" in the current directory
4152 ///
4153 /// By default, the specified entry list is reset.
4154 /// To continue to append data to an existing list, use "+" in front
4155 /// of the list name;
4156 /// ~~~ {.cpp}
4157 /// tree.Draw(">>+yplus","y>0")
4158 /// ~~~
4159 /// will not reset yplus, but will enter the selected entries at the end
4160 /// of the existing list.
4161 ///
4162 /// ### Using a TEventList, TEntryList or TEntryListArray as Input
4163 ///
4164 /// Once a TEventList or a TEntryList object has been generated, it can be used as input
4165 /// for TTree::Draw. Use TTree::SetEventList or TTree::SetEntryList to set the
4166 /// current event list
4167 ///
4168 /// Example 1:
4169 /// ~~~ {.cpp}
4170 /// TEventList *elist = (TEventList*)gDirectory->Get("yplus");
4171 /// tree->SetEventList(elist);
4172 /// tree->Draw("py");
4173 /// ~~~
4174 /// Example 2:
4175 /// ~~~ {.cpp}
4176 /// TEntryList *elist = (TEntryList*)gDirectory->Get("yplus");
4177 /// tree->SetEntryList(elist);
4178 /// tree->Draw("py");
4179 /// ~~~
4180 /// If a TEventList object is used as input, a new TEntryList object is created
4181 /// inside the SetEventList function. In case of a TChain, all tree headers are loaded
4182 /// for this transformation. This new object is owned by the chain and is deleted
4183 /// with it, unless the user extracts it by calling GetEntryList() function.
4184 /// See also comments to SetEventList() function of TTree and TChain.
4185 ///
4186 /// If arrays are used in the selection criteria and TEntryListArray is not used,
4187 /// all the entries that have at least one element of the array that satisfy the selection
4188 /// are entered in the list.
4189 ///
4190 /// Example:
4191 /// ~~~ {.cpp}
4192 /// tree.Draw(">>pyplus","fTracks.fPy>0");
4193 /// tree->SetEventList(pyplus);
4194 /// tree->Draw("fTracks.fPy");
4195 /// ~~~
4196 /// will draw the fPy of ALL tracks in event with at least one track with
4197 /// a positive fPy.
4198 ///
4199 /// To select only the elements that did match the original selection
4200 /// use TEventList::SetReapplyCut or TEntryList::SetReapplyCut.
4201 ///
4202 /// Example:
4203 /// ~~~ {.cpp}
4204 /// tree.Draw(">>pyplus","fTracks.fPy>0");
4205 /// pyplus->SetReapplyCut(kTRUE);
4206 /// tree->SetEventList(pyplus);
4207 /// tree->Draw("fTracks.fPy");
4208 /// ~~~
4209 /// will draw the fPy of only the tracks that have a positive fPy.
4210 ///
4211 /// To draw only the elements that match a selection in case of arrays,
4212 /// you can also use TEntryListArray (faster in case of a more general selection).
4213 ///
4214 /// Example:
4215 /// ~~~ {.cpp}
4216 /// tree.Draw(">>pyplus","fTracks.fPy>0", "entrylistarray");
4217 /// tree->SetEntryList(pyplus);
4218 /// tree->Draw("fTracks.fPy");
4219 /// ~~~
4220 /// will draw the fPy of only the tracks that have a positive fPy,
4221 /// but without redoing the selection.
4222 ///
4223 /// Note: Use tree->SetEventList(0) if you do not want use the list as input.
4224 ///
4225 /// ### How to obtain more info from TTree::Draw
4226 ///
4227 /// Once TTree::Draw has been called, it is possible to access useful
4228 /// information still stored in the TTree object via the following functions:
4229 ///
4230 /// - GetSelectedRows() // return the number of values accepted by the selection expression. In case where no selection was specified, returns the number of values processed.
4231 /// - GetV1() // returns a pointer to the double array of V1
4232 /// - GetV2() // returns a pointer to the double array of V2
4233 /// - GetV3() // returns a pointer to the double array of V3
4234 /// - GetV4() // returns a pointer to the double array of V4
4235 /// - GetW() // returns a pointer to the double array of Weights where weight equal the result of the selection expression.
4236 ///
4237 /// where V1,V2,V3 correspond to the expressions in
4238 /// ~~~ {.cpp}
4239 /// TTree::Draw("V1:V2:V3:V4",selection);
4240 /// ~~~
4241 /// If the expression has more than 4 component use GetVal(index)
4242 ///
4243 /// Example:
4244 /// ~~~ {.cpp}
4245 /// Root > ntuple->Draw("py:px","pz>4");
4246 /// Root > TGraph *gr = new TGraph(ntuple->GetSelectedRows(),
4247 /// ntuple->GetV2(), ntuple->GetV1());
4248 /// Root > gr->Draw("ap"); //draw graph in current pad
4249 /// ~~~
4250 ///
4251 /// A more complete complete tutorial (treegetval.C) shows how to use the
4252 /// GetVal() method.
4253 ///
4254 /// creates a TGraph object with a number of points corresponding to the
4255 /// number of entries selected by the expression "pz>4", the x points of the graph
4256 /// being the px values of the Tree and the y points the py values.
4257 ///
4258 /// Important note: By default TTree::Draw creates the arrays obtained
4259 /// with GetW, GetV1, GetV2, GetV3, GetV4, GetVal with a length corresponding
4260 /// to the parameter fEstimate. The content will be the last `GetSelectedRows() % GetEstimate()`
4261 /// values calculated.
4262 /// By default fEstimate=1000000 and can be modified
4263 /// via TTree::SetEstimate. To keep in memory all the results (in case
4264 /// where there is only one result per entry), use
4265 /// ~~~ {.cpp}
4266 /// tree->SetEstimate(tree->GetEntries()+1); // same as tree->SetEstimate(-1);
4267 /// ~~~
4268 /// You must call SetEstimate if the expected number of selected rows
4269 /// you need to look at is greater than 1000000.
4270 ///
4271 /// You can use the option "goff" to turn off the graphics output
4272 /// of TTree::Draw in the above example.
4273 ///
4274 /// ### Automatic interface to TTree::Draw via the TTreeViewer
4275 ///
4276 /// A complete graphical interface to this function is implemented
4277 /// in the class TTreeViewer.
4278 /// To start the TTreeViewer, three possibilities:
4279 /// - select TTree context menu item "StartViewer"
4280 /// - type the command "TTreeViewer TV(treeName)"
4281 /// - execute statement "tree->StartViewer();"
4283 Long64_t TTree::Draw(const char* varexp, const char* selection, Option_t* option, Long64_t nentries, Long64_t firstentry)
4284 {
4285  GetPlayer();
4286  if (fPlayer)
4287  return fPlayer->DrawSelect(varexp,selection,option,nentries,firstentry);
4288  return -1;
4289 }
4290 
4291 ////////////////////////////////////////////////////////////////////////////////
4292 /// Remove some baskets from memory.
4294 void TTree::DropBaskets()
4295 {
4296  TBranch* branch = 0;
4298  for (Int_t i = 0; i < nb; ++i) {
4299  branch = (TBranch*) fBranches.UncheckedAt(i);
4300  branch->DropBaskets("all");
4301  }
4302 }
4303 
4304 ////////////////////////////////////////////////////////////////////////////////
4305 /// Drop branch buffers to accommodate nbytes below MaxVirtualsize.
4308 {
4309  // Be careful not to remove current read/write buffers.
4310  Int_t ndrop = 0;
4311  Int_t nleaves = fLeaves.GetEntriesFast();
4312  for (Int_t i = 0; i < nleaves; ++i) {
4313  TLeaf* leaf = (TLeaf*) fLeaves.UncheckedAt(i);
4314  TBranch* branch = (TBranch*) leaf->GetBranch();
4315  Int_t nbaskets = branch->GetListOfBaskets()->GetEntries();
4316  for (Int_t j = 0; j < nbaskets - 1; ++j) {
4317  if ((j == branch->GetReadBasket()) || (j == branch->GetWriteBasket())) {
4318  continue;
4319  }
4320  TBasket* basket = (TBasket*)branch->GetListOfBaskets()->UncheckedAt(j);
4321  if (basket) {
4322  ndrop += basket->DropBuffers();
4324  return;
4325  }
4326  }
4327  }
4328  }
4329 }
4330 
4331 ////////////////////////////////////////////////////////////////////////////////
4332 /// Fill all branches.
4333 ///
4334 /// This function loops on all the branches of this tree. For
4335 /// each branch, it copies to the branch buffer (basket) the current
4336 /// values of the leaves data types. If a leaf is a simple data type,
4337 /// a simple conversion to a machine independent format has to be done.
4338 ///
4339 /// This machine independent version of the data is copied into a
4340 /// basket (each branch has its own basket). When a basket is full
4341 /// (32k worth of data by default), it is then optionally compressed
4342 /// and written to disk (this operation is also called committing or
4343 /// 'flushing' the basket). The committed baskets are then
4344 /// immediately removed from memory.
4345 ///
4346 /// The function returns the number of bytes committed to the
4347 /// individual branches.
4348 ///
4349 /// If a write error occurs, the number of bytes returned is -1.
4350 ///
4351 /// If no data are written, because, e.g., the branch is disabled,
4352 /// the number of bytes returned is 0.
4353 ///
4354 /// __The baskets are flushed and the Tree header saved at regular intervals__
4355 ///
4356 /// At regular intervals, when the amount of data written so far is
4357 /// greater than fAutoFlush (see SetAutoFlush) all the baskets are flushed to disk.
4358 /// This makes future reading faster as it guarantees that baskets belonging to nearby
4359 /// entries will be on the same disk region.
4360 /// When the first call to flush the baskets happen, we also take this opportunity
4361 /// to optimize the baskets buffers.
4362 /// We also check if the amount of data written is greater than fAutoSave (see SetAutoSave).
4363 /// In this case we also write the Tree header. This makes the Tree recoverable up to this point
4364 /// in case the program writing the Tree crashes.
4365 /// The decisions to FlushBaskets and Auto Save can be made based either on the number
4366 /// of bytes written (fAutoFlush and fAutoSave negative) or on the number of entries
4367 /// written (fAutoFlush and fAutoSave positive).
4368 /// Note that the user can decide to call FlushBaskets and AutoSave in her event loop
4369 /// base on the number of events written instead of the number of bytes written.
4370 ///
4371 /// Note that calling FlushBaskets too often increases the IO time.
4372 ///
4373 /// Note that calling AutoSave too often increases the IO time and also the file size.
4376 {
4377  Int_t nbytes = 0;
4378  Int_t nwrite = 0;
4379  Int_t nerror = 0;
4380  Int_t nbranches = fBranches.GetEntriesFast();
4381 
4382  // Case of one single super branch. Automatically update
4383  // all the branch addresses if a new object was created.
4384  if (nbranches == 1)
4385  ((TBranch *)fBranches.UncheckedAt(0))->UpdateAddress();
4386 
4387  if (fBranchRef)
4388  fBranchRef->Clear();
4389 
4390 #ifdef R__USE_IMT
4391  const auto useIMT = ROOT::IsImplicitMTEnabled() && fIMTEnabled;
4393  if (useIMT) {
4394  fIMTFlush = true;
4395  fIMTZipBytes.store(0);
4396  fIMTTotBytes.store(0);
4397  }
4398 #endif
4399 
4400  for (Int_t i = 0; i < nbranches; ++i) {
4401  // Loop over all branches, filling and accumulating bytes written and error counts.
4402  TBranch *branch = (TBranch *)fBranches.UncheckedAt(i);
4403 
4404  if (branch->TestBit(kDoNotProcess))
4405  continue;
4406 
4407 #ifndef R__USE_IMT
4408  nwrite = branch->FillImpl(nullptr);
4409 #else
4410  nwrite = branch->FillImpl(useIMT ? &imtHelper : nullptr);
4411 #endif
4412  if (nwrite < 0) {
4413  if (nerror < 2) {
4414  Error("Fill", "Failed filling branch:%s.%s, nbytes=%d, entry=%lld\n"
4415  " This error is symptomatic of a Tree created as a memory-resident Tree\n"
4416  " Instead of doing:\n"
4417  " TTree *T = new TTree(...)\n"
4418  " TFile *f = new TFile(...)\n"
4419  " you should do:\n"
4420  " TFile *f = new TFile(...)\n"
4421  " TTree *T = new TTree(...)\n\n",
4422  GetName(), branch->GetName(), nwrite, fEntries + 1);
4423  } else {
4424  Error("Fill", "Failed filling branch:%s.%s, nbytes=%d, entry=%lld", GetName(), branch->GetName(), nwrite,
4425  fEntries + 1);
4426  }
4427  ++nerror;
4428  } else {
4429  nbytes += nwrite;
4430  }
4431  }
4432 
4433 #ifdef R__USE_IMT
4434  if (fIMTFlush) {
4435  imtHelper.Wait();
4436  fIMTFlush = false;
4437  const_cast<TTree *>(this)->AddTotBytes(fIMTTotBytes);
4438  const_cast<TTree *>(this)->AddZipBytes(fIMTZipBytes);
4439  nbytes += imtHelper.GetNbytes();
4440  nerror += imtHelper.GetNerrors();
4441  }
4442 #endif
4443 
4444  if (fBranchRef)
4445  fBranchRef->Fill();
4446 
4447  ++fEntries;
4448 
4449  if (fEntries > fMaxEntries)
4450  KeepCircular();
4451 
4452  if (gDebug > 0)
4453  Info("TTree::Fill", " - A: %d %lld %lld %lld %lld %lld %lld \n", nbytes, fEntries, fAutoFlush, fAutoSave,
4455 
4456  bool autoFlush = false;
4457  bool autoSave = false;
4458 
4459  if (fAutoFlush != 0 || fAutoSave != 0) {
4460  // Is it time to flush or autosave baskets?
4461  if (fFlushedBytes == 0) {
4462  // If fFlushedBytes == 0, it means we never flushed or saved, so
4463  // we need to check if it's time to do it and recompute the values
4464  // of fAutoFlush and fAutoSave in terms of the number of entries.
4465  // Decision can be based initially either on the number of bytes
4466  // or the number of entries written.
4467  Long64_t zipBytes = GetZipBytes();
4468 
4469  if (fAutoFlush)
4470  autoFlush = fAutoFlush < 0 ? (zipBytes > -fAutoFlush) : fEntries % fAutoFlush == 0;
4471 
4472  if (fAutoSave)
4473  autoSave = fAutoSave < 0 ? (zipBytes > -fAutoSave) : fEntries % fAutoSave == 0;
4474 
4475  if (autoFlush || autoSave) {
4476  // First call FlushBasket to make sure that fTotBytes is up to date.
4477  FlushBasketsImpl();
4478  OptimizeBaskets(GetTotBytes(), 1, "");
4479  autoFlush = false; // avoid auto flushing again later
4480 
4481  if (gDebug > 0)
4482  Info("TTree::Fill", "OptimizeBaskets called at entry %lld, fZipBytes=%lld, fFlushedBytes=%lld\n",
4484 
4486  fAutoFlush = fEntries; // Use test on entries rather than bytes
4487 
4488  // subsequently in run
4489  if (fAutoSave < 0) {
4490  // Set fAutoSave to the largest integer multiple of
4491  // fAutoFlush events such that fAutoSave*fFlushedBytes
4492  // < (minus the input value of fAutoSave)
4493  Long64_t totBytes = GetTotBytes();
4494  if (zipBytes != 0) {
4495  fAutoSave = TMath::Max(fAutoFlush, fEntries * ((-fAutoSave / zipBytes) / fEntries));
4496  } else if (totBytes != 0) {
4497  fAutoSave = TMath::Max(fAutoFlush, fEntries * ((-fAutoSave / totBytes) / fEntries));
4498  } else {
4499  TBufferFile b(TBuffer::kWrite, 10000);
4500  TTree::Class()->WriteBuffer(b, (TTree *)this);
4501  Long64_t total = b.Length();
4503  }
4504  } else if (fAutoSave > 0) {
4506  }
4507 
4508  if (fAutoSave != 0 && fEntries >= fAutoSave)
4509  autoSave = true;
4510 
4511  if (gDebug > 0)
4512  Info("TTree::Fill", "First AutoFlush. fAutoFlush = %lld, fAutoSave = %lld\n", fAutoFlush, fAutoSave);
4513  }
4514  } else {
4515  // Check if we need to auto flush
4516  if (fAutoFlush) {
4517  if (fNClusterRange == 0)
4518  autoFlush = fEntries > 1 && fEntries % fAutoFlush == 0;
4519  else
4520  autoFlush = (fEntries - (fClusterRangeEnd[fNClusterRange - 1] + 1)) % fAutoFlush == 0;
4521  }
4522  // Check if we need to auto save
4523  if (fAutoSave)
4524  autoSave = fEntries % fAutoSave == 0;
4525  }
4526  }
4527 
4528  if (autoFlush) {
4529  FlushBasketsImpl();
4530  if (gDebug > 0)
4531  Info("TTree::Fill", "FlushBaskets() called at entry %lld, fZipBytes=%lld, fFlushedBytes=%lld\n", fEntries,
4534  }
4535 
4536  if (autoSave) {
4537  AutoSave(); // does not call FlushBasketsImpl() again
4538  if (gDebug > 0)
4539  Info("TTree::Fill", "AutoSave called at entry %lld, fZipBytes=%lld, fSavedBytes=%lld\n", fEntries,
4541  }
4542 
4543  // Check that output file is still below the maximum size.
4544  // If above, close the current file and continue on a new file.
4545  // Currently, the automatic change of file is restricted
4546  // to the case where the tree is in the top level directory.
4547  if (fDirectory)
4548  if (TFile *file = fDirectory->GetFile())
4549  if ((TDirectory *)file == fDirectory && (file->GetEND() > fgMaxTreeSize))
4550  ChangeFile(file);
4551 
4552  return nerror == 0 ? nbytes : -1;
4553 }
4554 
4555 ////////////////////////////////////////////////////////////////////////////////
4556 /// Search in the array for a branch matching the branch name,
4557 /// with the branch possibly expressed as a 'full' path name (with dots).
4559 static TBranch *R__FindBranchHelper(TObjArray *list, const char *branchname) {
4560  if (list==0 || branchname == 0 || branchname[0] == '\0') return 0;
4561 
4562  Int_t nbranches = list->GetEntries();
4563 
4564  UInt_t brlen = strlen(branchname);
4565 
4566  for(Int_t index = 0; index < nbranches; ++index) {
4567  TBranch *where = (TBranch*)list->UncheckedAt(index);
4568 
4569  const char *name = where->GetName();
4570  UInt_t len = strlen(name);
4571  if (len && name[len-1]==']') {
4572  const char *dim = strchr(name,'[');
4573  if (dim) {
4574  len = dim - name;
4575  }
4576  }
4577  if (brlen == len && strncmp(branchname,name,len)==0) {
4578  return where;
4579  }
4580  TBranch *next = 0;
4581  if ((brlen >= len) && (branchname[len] == '.')
4582  && strncmp(name, branchname, len) == 0) {
4583  // The prefix subbranch name match the branch name.
4584 
4585  next = where->FindBranch(branchname);
4586  if (!next) {
4587  next = where->FindBranch(branchname+len+1);
4588  }
4589  if (next) return next;
4590  }
4591  const char *dot = strchr((char*)branchname,'.');
4592  if (dot) {
4593  if (len==(size_t)(dot-branchname) &&
4594  strncmp(branchname,name,dot-branchname)==0 ) {
4595  return R__FindBranchHelper(where->GetListOfBranches(),dot+1);
4596  }
4597  }
4598  }
4599  return 0;
4600 }
4601 
4602 ////////////////////////////////////////////////////////////////////////////////
4603 /// Return the branch that correspond to the path 'branchname', which can
4604 /// include the name of the tree or the omitted name of the parent branches.
4605 /// In case of ambiguity, returns the first match.
4607 TBranch* TTree::FindBranch(const char* branchname)
4608 {
4609  // We already have been visited while recursively looking
4610  // through the friends tree, let return
4612  return 0;
4613  }
4614 
4615  TBranch* branch = 0;
4616  // If the first part of the name match the TTree name, look for the right part in the
4617  // list of branches.
4618  // This will allow the branchname to be preceded by
4619  // the name of this tree.
4620  if (strncmp(fName.Data(),branchname,fName.Length())==0 && branchname[fName.Length()]=='.') {
4621  branch = R__FindBranchHelper( GetListOfBranches(), branchname + fName.Length() + 1);
4622  if (branch) return branch;
4623  }
4624  // If we did not find it, let's try to find the full name in the list of branches.
4625  branch = R__FindBranchHelper(GetListOfBranches(), branchname);
4626  if (branch) return branch;
4627 
4628  // If we still did not find, let's try to find it within each branch assuming it does not the branch name.
4629  TIter next(GetListOfBranches());
4630  while ((branch = (TBranch*) next())) {
4631  TBranch* nestedbranch = branch->FindBranch(branchname);
4632  if (nestedbranch) {
4633  return nestedbranch;
4634  }
4635  }
4636 
4637  // Search in list of friends.
4638  if (!fFriends) {
4639  return 0;
4640  }
4641  TFriendLock lock(this, kFindBranch);
4642  TIter nextf(fFriends);
4643  TFriendElement* fe = 0;
4644  while ((fe = (TFriendElement*) nextf())) {
4645  TTree* t = fe->GetTree();
4646  if (!t) {
4647  continue;
4648  }
4649  // If the alias is present replace it with the real name.
4650  const char *subbranch = strstr(branchname, fe->GetName());
4651  if (subbranch != branchname) {
4652  subbranch = 0;
4653  }
4654  if (subbranch) {
4655  subbranch += strlen(fe->GetName());
4656  if (*subbranch != '.') {
4657  subbranch = 0;
4658  } else {
4659  ++subbranch;
4660  }
4661  }
4662  std::ostringstream name;
4663  if (subbranch) {
4664  name << t->GetName() << "." << subbranch;
4665  } else {
4666  name << branchname;
4667  }
4668  branch = t->FindBranch(name.str().c_str());
4669  if (branch) {
4670  return branch;
4671  }
4672  }
4673  return 0;
4674 }
4675 
4676 ////////////////////////////////////////////////////////////////////////////////
4677 /// Find leaf..
4679 TLeaf* TTree::FindLeaf(const char* searchname)
4680 {
4681  // We already have been visited while recursively looking
4682  // through the friends tree, let's return.
4683  if (kFindLeaf & fFriendLockStatus) {
4684  return 0;
4685  }
4686 
4687  // This will allow the branchname to be preceded by
4688  // the name of this tree.
4689  char* subsearchname = (char*) strstr(searchname, GetName());
4690  if (subsearchname != searchname) {
4691  subsearchname = 0;
4692  }
4693  if (subsearchname) {
4694  subsearchname += strlen(GetName());
4695  if (*subsearchname != '.') {
4696  subsearchname = 0;
4697  } else {
4698  ++subsearchname;
4699  if (subsearchname[0]==0) {
4700  subsearchname = 0;
4701  }
4702  }
4703  }
4704 
4705  TString leafname;
4706  TString leaftitle;
4707  TString longname;
4708  TString longtitle;
4709 
4710  // For leaves we allow for one level up to be prefixed to the name.
4711  TIter next(GetListOfLeaves());
4712  TLeaf* leaf = 0;
4713  while ((leaf = (TLeaf*) next())) {
4714  leafname = leaf->GetName();
4715  Ssiz_t dim = leafname.First('[');
4716  if (dim >= 0) leafname.Remove(dim);
4717 
4718  if (leafname == searchname) {
4719  return leaf;
4720  }
4721  if (subsearchname && leafname == subsearchname) {
4722  return leaf;
4723  }
4724  // The TLeafElement contains the branch name
4725  // in its name, let's use the title.
4726  leaftitle = leaf->GetTitle();
4727  dim = leaftitle.First('[');
4728  if (dim >= 0) leaftitle.Remove(dim);
4729 
4730  if (leaftitle == searchname) {
4731  return leaf;
4732  }
4733  if (subsearchname && leaftitle == subsearchname) {
4734  return leaf;
4735  }
4736  TBranch* branch = leaf->GetBranch();
4737  if (branch) {
4738  longname.Form("%s.%s",branch->GetName(),leafname.Data());
4739  dim = longname.First('[');
4740  if (dim>=0) longname.Remove(dim);
4741  if (longname == searchname) {
4742  return leaf;
4743  }
4744  if (subsearchname && longname == subsearchname) {
4745  return leaf;
4746  }
4747  longtitle.Form("%s.%s",branch->GetName(),leaftitle.Data());
4748  dim = longtitle.First('[');
4749  if (dim>=0) longtitle.Remove(dim);
4750  if (longtitle == searchname) {
4751  return leaf;
4752  }
4753  if (subsearchname && longtitle == subsearchname) {
4754  return leaf;
4755  }
4756  // The following is for the case where the branch is only
4757  // a sub-branch. Since we do not see it through
4758  // TTree::GetListOfBranches, we need to see it indirectly.
4759  // This is the less sturdy part of this search ... it may
4760  // need refining ...
4761  if (strstr(searchname, ".") && !strcmp(searchname, branch->GetName())) {
4762  return leaf;
4763  }
4764  if (subsearchname && strstr(subsearchname, ".") && !strcmp(subsearchname, branch->GetName())) {
4765  return leaf;
4766  }
4767  }
4768  }
4769  // Search in list of friends.
4770  if (!fFriends) {
4771  return 0;
4772  }
4773  TFriendLock lock(this, kFindLeaf);
4774  TIter nextf(fFriends);
4775  TFriendElement* fe = 0;
4776  while ((fe = (TFriendElement*) nextf())) {
4777  TTree* t = fe->GetTree();
4778  if (!t) {
4779  continue;
4780  }
4781  // If the alias is present replace it with the real name.
4782  subsearchname = (char*) strstr(searchname, fe->GetName());
4783  if (subsearchname != searchname) {
4784  subsearchname = 0;
4785  }
4786  if (subsearchname) {
4787  subsearchname += strlen(fe->GetName());
4788  if (*subsearchname != '.') {
4789  subsearchname = 0;
4790  } else {
4791  ++subsearchname;
4792  }
4793  }
4794  if (subsearchname) {
4795  leafname.Form("%s.%s",t->GetName(),subsearchname);
4796  } else {
4797  leafname = searchname;
4798  }
4799  leaf = t->FindLeaf(leafname);
4800  if (leaf) {
4801  return leaf;
4802  }
4803  }
4804  return 0;
4805 }
4806 
4807 ////////////////////////////////////////////////////////////////////////////////
4808 /// Fit a projected item(s) from a tree.
4809 ///
4810 /// funcname is a TF1 function.
4811 ///
4812 /// See TTree::Draw() for explanations of the other parameters.
4813 ///
4814 /// By default the temporary histogram created is called htemp.
4815 /// If varexp contains >>hnew , the new histogram created is called hnew
4816 /// and it is kept in the current directory.
4817 ///
4818 /// The function returns the number of selected entries.
4819 ///
4820 /// Example:
4821 /// ~~~ {.cpp}
4822 /// tree.Fit(pol4,"sqrt(x)>>hsqrt","y>0")
4823 /// ~~~
4824 /// will fit sqrt(x) and save the histogram as "hsqrt" in the current
4825 /// directory.
4826 ///
4827 /// See also TTree::UnbinnedFit
4828 ///
4829 /// ## Return status
4830 ///
4831 /// The function returns the status of the histogram fit (see TH1::Fit)
4832 /// If no entries were selected, the function returns -1;
4833 /// (i.e. fitResult is null if the fit is OK)
4835 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)
4836 {
4837  GetPlayer();
4838  if (fPlayer) {
4839  return fPlayer->Fit(funcname, varexp, selection, option, goption, nentries, firstentry);
4840  }
4841  return -1;
4842 }
4843 
4844 namespace {
4845 struct BoolRAIIToggle {
4846  Bool_t &m_val;
4847 
4848  BoolRAIIToggle(Bool_t &val) : m_val(val) { m_val = true; }
4849  ~BoolRAIIToggle() { m_val = false; }
4850 };
4851 }
4852 
4853 ////////////////////////////////////////////////////////////////////////////////
4854 /// Write to disk all the basket that have not yet been individually written and
4855 /// create an event cluster boundary (by default).
4856 ///
4857 /// If the caller wishes to flush the baskets but not create an event cluster,
4858 /// then set create_cluster to false.
4859 ///
4860 /// If ROOT has IMT-mode enabled, this will launch multiple TBB tasks in parallel
4861 /// via TThreadExecutor to do this operation; one per basket compression. If the
4862 /// caller utilizes TBB also, care must be taken to prevent deadlocks.
4863 ///
4864 /// For example, let's say the caller holds mutex A and calls FlushBaskets; while
4865 /// TBB is waiting for the ROOT compression tasks to complete, it may decide to
4866 /// run another one of the user's tasks in this thread. If the second user task
4867 /// tries to acquire A, then a deadlock will occur. The example call sequence
4868 /// looks like this:
4869 ///
4870 /// - User acquires mutex A
4871 /// - User calls FlushBaskets.
4872 /// - ROOT launches N tasks and calls wait.
4873 /// - TBB schedules another user task, T2.
4874 /// - T2 tries to acquire mutex A.
4875 ///
4876 /// At this point, the thread will deadlock: the code may function with IMT-mode
4877 /// disabled if the user assumed the legacy code never would run their own TBB
4878 /// tasks.
4879 ///
4880 /// SO: users of TBB who want to enable IMT-mode should carefully review their
4881 /// locking patterns and make sure they hold no coarse-grained application
4882 /// locks when they invoke ROOT.
4883 ///
4884 /// Return the number of bytes written or -1 in case of write error.
4885 Int_t TTree::FlushBaskets(Bool_t create_cluster) const
4886 {
4887  Int_t retval = FlushBasketsImpl();
4888  if (retval == -1) return retval;
4889 
4890  if (create_cluster) const_cast<TTree *>(this)->MarkEventCluster();
4891  return retval;
4892 }
4893 
4894 ////////////////////////////////////////////////////////////////////////////////
4895 /// Internal implementation of the FlushBaskets algorithm.
4896 /// Unlike the public interface, this does NOT create an explicit event cluster
4897 /// boundary; it is up to the (internal) caller to determine whether that should
4898 /// done.
4899 ///
4900 /// Otherwise, the comments for FlushBaskets applies.
4901 ///
4903 {
4904  if (!fDirectory) return 0;
4905  Int_t nbytes = 0;
4906  Int_t nerror = 0;
4907  TObjArray *lb = const_cast<TTree*>(this)->GetListOfBranches();
4908  Int_t nb = lb->GetEntriesFast();
4909 
4910 #ifdef R__USE_IMT
4911  const auto useIMT = ROOT::IsImplicitMTEnabled() && fIMTEnabled;
4912  if (useIMT) {
4913  if (fSortedBranches.empty()) { const_cast<TTree*>(this)->InitializeBranchLists(false); }
4914 
4915  BoolRAIIToggle sentry(fIMTFlush);
4916  fIMTZipBytes.store(0);
4917  fIMTTotBytes.store(0);
4918  std::atomic<Int_t> nerrpar(0);
4919  std::atomic<Int_t> nbpar(0);
4920  std::atomic<Int_t> pos(0);
4921 
4922  auto mapFunction = [&]() {
4923  // The branch to process is obtained when the task starts to run.
4924  // This way, since branches are sorted, we make sure that branches
4925  // leading to big tasks are processed first. If we assigned the
4926  // branch at task creation time, the scheduler would not necessarily
4927  // respect our sorting.
4928  Int_t j = pos.fetch_add(1);
4929 
4930  auto branch = fSortedBranches[j].second;
4931  if (R__unlikely(!branch)) { return; }
4932 
4933  if (R__unlikely(gDebug > 0)) {
4934  std::stringstream ss;
4935  ss << std::this_thread::get_id();
4936  Info("FlushBaskets", "[IMT] Thread %s", ss.str().c_str());
4937  Info("FlushBaskets", "[IMT] Running task for branch #%d: %s", j, branch->GetName());
4938  }
4939 
4940  Int_t nbtask = branch->FlushBaskets();
4941 
4942  if (nbtask < 0) { nerrpar++; }
4943  else { nbpar += nbtask; }
4944  };
4945 
4946  ROOT::TThreadExecutor pool;
4947  pool.Foreach(mapFunction, nb);
4948 
4949  fIMTFlush = false;
4950  const_cast<TTree*>(this)->AddTotBytes(fIMTTotBytes);
4951  const_cast<TTree*>(this)->AddZipBytes(fIMTZipBytes);
4952 
4953  return nerrpar ? -1 : nbpar.load();
4954  }
4955 #endif
4956  for (Int_t j = 0; j < nb; j++) {
4957  TBranch* branch = (TBranch*) lb->UncheckedAt(j);
4958  if (branch) {
4959  Int_t nwrite = branch->FlushBaskets();
4960  if (nwrite<0) {
4961  ++nerror;
4962  } else {
4963  nbytes += nwrite;
4964  }
4965  }
4966  }
4967  if (nerror) {
4968  return -1;
4969  } else {
4970  return nbytes;
4971  }
4972 }
4973 
4974 ////////////////////////////////////////////////////////////////////////////////
4975 /// Returns the expanded value of the alias. Search in the friends if any.
4977 const char* TTree::GetAlias(const char* aliasName) const
4978 {
4979  // We already have been visited while recursively looking
4980  // through the friends tree, let's return.
4981  if (kGetAlias & fFriendLockStatus) {
4982  return 0;
4983  }
4984  if (fAliases) {
4985  TObject* alias = fAliases->FindObject(aliasName);
4986  if (alias) {
4987  return alias->GetTitle();
4988  }
4989  }
4990  if (!fFriends) {
4991  return 0;
4992  }
4993  TFriendLock lock(const_cast<TTree*>(this), kGetAlias);
4994  TIter nextf(fFriends);
4995  TFriendElement* fe = 0;
4996  while ((fe = (TFriendElement*) nextf())) {
4997  TTree* t = fe->GetTree();
4998  if (t) {
4999  const char* alias = t->GetAlias(aliasName);
5000  if (alias) {
5001  return alias;
5002  }
5003  const char* subAliasName = strstr(aliasName, fe->GetName());
5004  if (subAliasName && (subAliasName[strlen(fe->GetName())] == '.')) {
5005  alias = t->GetAlias(aliasName + strlen(fe->GetName()) + 1);
5006  if (alias) {
5007  return alias;
5008  }
5009  }
5010  }
5011  }
5012  return 0;
5013 }
5014 
5015 ////////////////////////////////////////////////////////////////////////////////
5016 /// Return pointer to the branch with the given name in this tree or its friends.
5018 TBranch* TTree::GetBranch(const char* name)
5019 {
5020  if (name == 0) return 0;
5021 
5022  // We already have been visited while recursively
5023  // looking through the friends tree, let's return.
5024  if (kGetBranch & fFriendLockStatus) {
5025  return 0;
5026  }
5027 
5028  // Search using branches.
5030  for (Int_t i = 0; i < nb; i++) {
5031  TBranch* branch = (TBranch*) fBranches.UncheckedAt(i);
5032  if (!branch) {
5033  continue;
5034  }
5035  if (!strcmp(branch->GetName(), name)) {
5036  return branch;
5037  }
5038  TObjArray* lb = branch->GetListOfBranches();
5039  Int_t nb1 = lb->GetEntriesFast();
5040  for (Int_t j = 0; j < nb1; j++) {
5041  TBranch* b1 = (TBranch*) lb->UncheckedAt(j);
5042  if (!strcmp(b1->GetName(), name)) {
5043  return b1;
5044  }
5045  TObjArray* lb1 = b1->GetListOfBranches();
5046  Int_t nb2 = lb1->GetEntriesFast();
5047  for (Int_t k = 0; k < nb2; k++) {
5048  TBranch* b2 = (TBranch*) lb1->UncheckedAt(k);
5049  if (!strcmp(b2->GetName(), name)) {
5050  return b2;
5051  }
5052  }
5053  }
5054  }
5055 
5056  // Search using leaves.
5057  TObjArray* leaves = GetListOfLeaves();
5058  Int_t nleaves = leaves->GetEntriesFast();
5059  for (Int_t i = 0; i < nleaves; i++) {
5060  TLeaf* leaf = (TLeaf*) leaves->UncheckedAt(i);
5061  TBranch* branch = leaf->GetBranch();
5062  if (!strcmp(branch->GetName(), name)) {
5063  return branch;
5064  }
5065  }
5066 
5067  if (!fFriends) {
5068  return 0;
5069  }
5070 
5071  // Search in list of friends.
5072  TFriendLock lock(this, kGetBranch);
5073  TIter next(fFriends);
5074  TFriendElement* fe = 0;
5075  while ((fe = (TFriendElement*) next())) {
5076  TTree* t = fe->GetTree();
5077  if (t) {
5078  TBranch* branch = t->GetBranch(name);
5079  if (branch) {
5080  return branch;
5081  }
5082  }
5083  }
5084 
5085  // Second pass in the list of friends when
5086  // the branch name is prefixed by the tree name.
5087  next.Reset();
5088  while ((fe = (TFriendElement*) next())) {
5089  TTree* t = fe->GetTree();
5090  if (!t) {
5091  continue;
5092  }
5093  char* subname = (char*) strstr(name, fe->GetName());
5094  if (subname != name) {
5095  continue;
5096  }
5097  Int_t l = strlen(fe->GetName());
5098  subname += l;
5099  if (*subname != '.') {
5100  continue;
5101  }
5102  subname++;
5103  TBranch* branch = t->GetBranch(subname);
5104  if (branch) {
5105  return branch;
5106  }
5107  }
5108  return 0;
5109 }
5110 
5111 ////////////////////////////////////////////////////////////////////////////////
5112 /// Return status of branch with name branchname.
5113 ///
5114 /// - 0 if branch is not activated
5115 /// - 1 if branch is activated
5117 Bool_t TTree::GetBranchStatus(const char* branchname) const
5118 {
5119  TBranch* br = const_cast<TTree*>(this)->GetBranch(branchname);
5120  if (br) {
5121  return br->TestBit(kDoNotProcess) == 0;
5122  }
5123  return 0;
5124 }
5125 
5126 ////////////////////////////////////////////////////////////////////////////////
5127 /// Static function returning the current branch style.
5128 ///
5129 /// - style = 0 old Branch
5130 /// - style = 1 new Bronch
5133 {
5134  return fgBranchStyle;
5135 }
5136 
5137 ////////////////////////////////////////////////////////////////////////////////
5138 /// Used for automatic sizing of the cache.
5139 ///
5140 /// Estimates a suitable size for the tree cache based on AutoFlush.
5141 /// A cache sizing factor is taken from the configuration. If this yields zero
5142 /// and withDefault is true the historical algorithm for default size is used.
5144 Long64_t TTree::GetCacheAutoSize(Bool_t withDefault /* = kFALSE */ ) const
5145 {
5146  const char *stcs;
5147  Double_t cacheFactor = 0.0;
5148  if (!(stcs = gSystem->Getenv("ROOT_TTREECACHE_SIZE")) || !*stcs) {
5149  cacheFactor = gEnv->GetValue("TTreeCache.Size", 1.0);
5150  } else {
5151  cacheFactor = TString(stcs).Atof();
5152  }
5153 
5154  if (cacheFactor < 0.0) {
5155  // ignore negative factors
5156  cacheFactor = 0.0;
5157  }
5158 
5159  Long64_t cacheSize = 0;
5160 
5161  if (fAutoFlush < 0) cacheSize = Long64_t(-cacheFactor*fAutoFlush);
5162  else if (fAutoFlush == 0) cacheSize = 0;
5163  else cacheSize = Long64_t(cacheFactor*1.5*fAutoFlush*GetZipBytes()/(fEntries+1));
5164 
5165  if (cacheSize >= (INT_MAX / 4)) {
5166  cacheSize = INT_MAX / 4;
5167  }
5168 
5169  if (cacheSize < 0) {
5170  cacheSize = 0;
5171  }
5172 
5173  if (cacheSize == 0 && withDefault) {
5174  if (fAutoFlush < 0) cacheSize = -fAutoFlush;
5175  else if (fAutoFlush == 0) cacheSize = 0;
5176  else cacheSize = Long64_t(1.5*fAutoFlush*GetZipBytes()/(fEntries+1));
5177  }
5178 
5179  return cacheSize;
5180 }
5181 
5182 ////////////////////////////////////////////////////////////////////////////////
5183 /// Return an iterator over the cluster of baskets starting at firstentry.
5184 ///
5185 /// This iterator is not yet supported for TChain object.
5186 /// ~~~ {.cpp}
5187 /// TTree::TClusterIterator clusterIter = tree->GetClusterIterator(entry);
5188 /// Long64_t clusterStart;
5189 /// while( (clusterStart = clusterIter()) < tree->GetEntries() ) {
5190 /// printf("The cluster starts at %lld and ends at %lld (inclusive)\n",clusterStart,clusterIter.GetNextEntry()-1);
5191 /// }
5192 /// ~~~
5195 {
5196  // create cache if wanted
5197  if (fCacheDoAutoInit)
5198  SetCacheSizeAux();
5199 
5200  return TClusterIterator(this,firstentry);
5201 }
5202 
5203 ////////////////////////////////////////////////////////////////////////////////
5204 /// Return pointer to the current file.
5207 {
5208  if (!fDirectory || fDirectory==gROOT) {
5209  return 0;
5210  }
5211  return fDirectory->GetFile();
5212 }
5213 
5214 ////////////////////////////////////////////////////////////////////////////////
5215 /// Return the number of entries matching the selection.
5216 /// Return -1 in case of errors.
5217 ///
5218 /// If the selection uses any arrays or containers, we return the number
5219 /// of entries where at least one element match the selection.
5220 /// GetEntries is implemented using the selector class TSelectorEntries,
5221 /// which can be used directly (see code in TTreePlayer::GetEntries) for
5222 /// additional option.
5223 /// If SetEventList was used on the TTree or TChain, only that subset
5224 /// of entries will be considered.
5226 Long64_t TTree::GetEntries(const char *selection)
5227 {
5228  GetPlayer();
5229  if (fPlayer) {
5230  return fPlayer->GetEntries(selection);
5231  }
5232  return -1;
5233 }
5234 
5235 ////////////////////////////////////////////////////////////////////////////////
5236 /// Return pointer to the 1st Leaf named name in any Branch of this Tree or
5237 /// any branch in the list of friend trees.
5240 {
5241  if (fEntries) return fEntries;
5242  if (!fFriends) return 0;
5244  if (!fr) return 0;
5245  TTree *t = fr->GetTree();
5246  if (t==0) return 0;
5247  return t->GetEntriesFriend();
5248 }
5249 
5250 ////////////////////////////////////////////////////////////////////////////////
5251 /// Read all branches of entry and return total number of bytes read.
5252 ///
5253 /// - `getall = 0` : get only active branches
5254 /// - `getall = 1` : get all branches
5255 ///
5256 /// The function returns the number of bytes read from the input buffer.
5257 /// If entry does not exist the function returns 0.
5258 /// If an I/O error occurs, the function returns -1.
5259 ///
5260 /// If the Tree has friends, also read the friends entry.
5261 ///
5262 /// To activate/deactivate one or more branches, use TBranch::SetBranchStatus
5263 /// For example, if you have a Tree with several hundred branches, and you
5264 /// are interested only by branches named "a" and "b", do
5265 /// ~~~ {.cpp}
5266 /// mytree.SetBranchStatus("*",0); //disable all branches
5267 /// mytree.SetBranchStatus("a",1);
5268 /// mytree.SetBranchStatus("b",1);
5269 /// ~~~
5270 /// when calling mytree.GetEntry(i); only branches "a" and "b" will be read.
5271 ///
5272 /// __WARNING!!__
5273 /// If your Tree has been created in split mode with a parent branch "parent.",
5274 /// ~~~ {.cpp}
5275 /// mytree.SetBranchStatus("parent",1);
5276 /// ~~~
5277 /// will not activate the sub-branches of "parent". You should do:
5278 /// ~~~ {.cpp}
5279 /// mytree.SetBranchStatus("parent*",1);
5280 /// ~~~
5281 /// Without the trailing dot in the branch creation you have no choice but to
5282 /// call SetBranchStatus explicitly for each of the sub branches.
5283 ///
5284 /// An alternative is to call directly
5285 /// ~~~ {.cpp}
5286 /// brancha.GetEntry(i)
5287 /// branchb.GetEntry(i);
5288 /// ~~~
5289 /// ## IMPORTANT NOTE
5290 ///
5291 /// By default, GetEntry reuses the space allocated by the previous object
5292 /// for each branch. You can force the previous object to be automatically
5293 /// deleted if you call mybranch.SetAutoDelete(kTRUE) (default is kFALSE).
5294 ///
5295 /// Example:
5296 ///
5297 /// Consider the example in $ROOTSYS/test/Event.h
5298 /// The top level branch in the tree T is declared with:
5299 /// ~~~ {.cpp}
5300 /// Event *event = 0; //event must be null or point to a valid object
5301 /// //it must be initialized
5302 /// T.SetBranchAddress("event",&event);
5303 /// ~~~
5304 /// When reading the Tree, one can choose one of these 3 options:
5305 ///
5306 /// ## OPTION 1
5307 ///
5308 /// ~~~ {.cpp}
5309 /// for (Long64_t i=0;i<nentries;i++) {
5310 /// T.GetEntry(i);
5311 /// // the object event has been filled at this point
5312 /// }
5313 /// ~~~
5314 /// The default (recommended). At the first entry an object of the class
5315 /// Event will be created and pointed by event. At the following entries,
5316 /// event will be overwritten by the new data. All internal members that are
5317 /// TObject* are automatically deleted. It is important that these members
5318 /// be in a valid state when GetEntry is called. Pointers must be correctly
5319 /// initialized. However these internal members will not be deleted if the
5320 /// characters "->" are specified as the first characters in the comment
5321 /// field of the data member declaration.
5322 ///
5323 /// If "->" is specified, the pointer member is read via pointer->Streamer(buf).
5324 /// In this case, it is assumed that the pointer is never null (case of
5325 /// pointer TClonesArray *fTracks in the Event example). If "->" is not
5326 /// specified, the pointer member is read via buf >> pointer. In this case
5327 /// the pointer may be null. Note that the option with "->" is faster to
5328 /// read or write and it also consumes less space in the file.
5329 ///
5330 /// ## OPTION 2
5331 ///
5332 /// The option AutoDelete is set
5333 /// ~~~ {.cpp}
5334 /// TBranch *branch = T.GetBranch("event");
5335 /// branch->SetAddress(&event);
5336 /// branch->SetAutoDelete(kTRUE);
5337 /// for (Long64_t i=0;i<nentries;i++) {
5338 /// T.GetEntry(i);
5339 /// // the object event has been filled at this point
5340 /// }
5341 /// ~~~
5342 /// In this case, at each iteration, the object event is deleted by GetEntry
5343 /// and a new instance of Event is created and filled.
5344 ///
5345 /// ## OPTION 3
5346 /// ~~~ {.cpp}
5347 /// Same as option 1, but you delete yourself the event.
5348 ///
5349 /// for (Long64_t i=0;i<nentries;i++) {
5350 /// delete event;
5351 /// event = 0; // EXTREMELY IMPORTANT
5352 /// T.GetEntry(i);
5353 /// // the object event has been filled at this point
5354 /// }
5355 /// ~~~
5356 /// It is strongly recommended to use the default option 1. It has the
5357 /// additional advantage that functions like TTree::Draw (internally calling
5358 /// TTree::GetEntry) will be functional even when the classes in the file are
5359 /// not available.
5360 ///
5361 /// Note: See the comments in TBranchElement::SetAddress() for the
5362 /// object ownership policy of the underlying (user) data.
5364 Int_t TTree::GetEntry(Long64_t entry, Int_t getall)
5365 {
5366 
5367  // We already have been visited while recursively looking
5368  // through the friends tree, let return
5369  if (kGetEntry & fFriendLockStatus) return 0;
5370 
5371  if (entry < 0 || entry >= fEntries) return 0;
5372  Int_t i;
5373  Int_t nbytes = 0;
5374  fReadEntry = entry;
5375 
5376  // create cache if wanted
5377  if (fCacheDoAutoInit)
5378  SetCacheSizeAux();
5379 
5380  Int_t nbranches = fBranches.GetEntriesFast();
5381  Int_t nb=0;
5382 
5383  auto seqprocessing = [&]() {
5384  TBranch *branch;
5385  for (i=0;i<nbranches;i++) {
5386  branch = (TBranch*)fBranches.UncheckedAt(i);
5387  nb = branch->GetEntry(entry, getall);
5388  if (nb < 0) break;
5389  nbytes += nb;
5390  }
5391  };
5392 
5393 #ifdef R__USE_IMT
5394  const auto nBranches = GetListOfBranches()->GetEntries();
5396  if (fSortedBranches.empty())
5397  InitializeBranchLists(true);
5398 
5399  // Count branches are processed first and sequentially
5400  for (auto branch : fSeqBranches) {
5401  nb = branch->GetEntry(entry, getall);
5402  if (nb < 0) break;
5403  nbytes += nb;
5404  }
5405  if (nb < 0) return nb;
5406 
5407  // Enable this IMT use case (activate its locks)
5409 
5410  Int_t errnb = 0;
5411  std::atomic<Int_t> pos(0);
5412  std::atomic<Int_t> nbpar(0);
5413 
5414  auto mapFunction = [&]() {
5415  // The branch to process is obtained when the task starts to run.
5416  // This way, since branches are sorted, we make sure that branches
5417  // leading to big tasks are processed first. If we assigned the
5418  // branch at task creation time, the scheduler would not necessarily
5419  // respect our sorting.
5420  Int_t j = pos.fetch_add(1);
5421 
5422  Int_t nbtask = 0;
5423  auto branch = fSortedBranches[j].second;
5424 
5425  if (gDebug > 0) {
5426  std::stringstream ss;
5427  ss << std::this_thread::get_id();
5428  Info("GetEntry", "[IMT] Thread %s", ss.str().c_str());
5429  Info("GetEntry", "[IMT] Running task for branch #%d: %s", j, branch->GetName());
5430  }
5431 
5432  std::chrono::time_point<std::chrono::system_clock> start, end;
5433 
5434  start = std::chrono::system_clock::now();
5435  nbtask = branch->GetEntry(entry, getall);
5436  end = std::chrono::system_clock::now();
5437 
5438  Long64_t tasktime = (Long64_t)std::chrono::duration_cast<std::chrono::microseconds>(end - start).count();
5439  fSortedBranches[j].first += tasktime;
5440 
5441  if (nbtask < 0) errnb = nbtask;
5442  else nbpar += nbtask;
5443  };
5444 
5445  ROOT::TThreadExecutor pool;
5446  pool.Foreach(mapFunction, fSortedBranches.size());
5447 
5448  if (errnb < 0) {
5449  nb = errnb;
5450  }
5451  else {
5452  // Save the number of bytes read by the tasks
5453  nbytes += nbpar;
5454 
5455  // Re-sort branches if necessary
5459  }
5460  }
5461  }
5462  else {
5463  seqprocessing();
5464  }
5465 #else
5466  seqprocessing();
5467 #endif
5468  if (nb < 0) return nb;
5469 
5470  // GetEntry in list of friends
5471  if (!fFriends) return nbytes;
5472  TFriendLock lock(this,kGetEntry);
5473  TIter nextf(fFriends);
5474  TFriendElement *fe;
5475  while ((fe = (TFriendElement*)nextf())) {
5476  TTree *t = fe->GetTree();
5477  if (t) {
5479  nb = t->GetEntry(t->GetReadEntry(),getall);
5480  } else {
5481  if ( t->LoadTreeFriend(entry,this) >= 0 ) {
5482  nb = t->GetEntry(t->GetReadEntry(),getall);
5483  } else nb = 0;
5484  }
5485  if (nb < 0) return nb;
5486  nbytes += nb;
5487  }
5488  }
5489  return nbytes;
5490 }
5491 
5492 
5493 ////////////////////////////////////////////////////////////////////////////////
5494 /// Divides the top-level branches into two vectors: (i) branches to be
5495 /// processed sequentially and (ii) branches to be processed in parallel.
5496 /// Even if IMT is on, some branches might need to be processed first and in a
5497 /// sequential fashion: in the parallelization of GetEntry, those are the
5498 /// branches that store the size of another branch for every entry
5499 /// (e.g. the size of an array branch). If such branches were processed
5500 /// in parallel with the rest, there could be two threads invoking
5501 /// TBranch::GetEntry on one of them at the same time, since a branch that
5502 /// depends on a size (or count) branch will also invoke GetEntry on the latter.
5503 /// \param[in] checkLeafCount True if we need to check whether some branches are
5504 /// count leaves.
5506 void TTree::InitializeBranchLists(bool checkLeafCount)
5507 {
5508  Int_t nbranches = fBranches.GetEntriesFast();
5509 
5510  // The branches to be processed sequentially are those that are the leaf count of another branch
5511  if (checkLeafCount) {
5512  for (Int_t i = 0; i < nbranches; i++) {
5513  TBranch* branch = (TBranch*)fBranches.UncheckedAt(i);
5514  auto leafCount = ((TLeaf*)branch->GetListOfLeaves()->At(0))->GetLeafCount();
5515  if (leafCount) {
5516  auto countBranch = leafCount->GetBranch();
5517  if (std::find(fSeqBranches.begin(), fSeqBranches.end(), countBranch) == fSeqBranches.end()) {
5518  fSeqBranches.push_back(countBranch);
5519  }
5520  }
5521  }
5522  }
5523 
5524  // The special branch fBranchRef also needs to be processed sequentially
5525  if (fBranchRef) {
5526  fSeqBranches.push_back(fBranchRef);
5527  }
5528 
5529  // Any branch that is not a leaf count can be safely processed in parallel when reading
5530  for (Int_t i = 0; i < nbranches; i++) {
5531  Long64_t bbytes = 0;
5532  TBranch* branch = (TBranch*)fBranches.UncheckedAt(i);
5533  if (std::find(fSeqBranches.begin(), fSeqBranches.end(), branch) == fSeqBranches.end()) {
5534  bbytes = branch->GetTotBytes("*");
5535  fSortedBranches.emplace_back(bbytes, branch);
5536  }
5537  }
5538 
5539  // Initially sort parallel branches by size
5540  std::sort(fSortedBranches.begin(),
5541  fSortedBranches.end(),
5542  [](std::pair<Long64_t,TBranch*> a, std::pair<Long64_t,TBranch*> b) {
5543  return a.first > b.first;
5544  });
5545 
5546  for (size_t i = 0; i < fSortedBranches.size(); i++) {
5547  fSortedBranches[i].first = 0LL;
5548  }
5549 }
5550 
5551 ////////////////////////////////////////////////////////////////////////////////
5552 /// Sorts top-level branches by the last average task time recorded per branch.
5555 {
5556  for (size_t i = 0; i < fSortedBranches.size(); i++) {
5557  fSortedBranches[i].first *= kNEntriesResortInv;
5558  }
5559 
5560  std::sort(fSortedBranches.begin(),
5561  fSortedBranches.end(),
5562  [](std::pair<Long64_t,TBranch*> a, std::pair<Long64_t,TBranch*> b) {
5563  return a.first > b.first;
5564  });
5565 
5566  for (size_t i = 0; i < fSortedBranches.size(); i++) {
5567  fSortedBranches[i].first = 0LL;
5568  }
5569 }
5570 
5571 ////////////////////////////////////////////////////////////////////////////////
5572 ///Returns the entry list, set to this tree
5575 {
5576  return fEntryList;
5577 }
5578 
5579 ////////////////////////////////////////////////////////////////////////////////
5580 /// Return entry number corresponding to entry.
5581 ///
5582 /// if no TEntryList set returns entry
5583 /// else returns the entry number corresponding to the list index=entry
5586 {
5587  if (!fEntryList) {
5588  return entry;
5589  }
5590 
5591  return fEntryList->GetEntry(entry);
5592 }
5593 
5594 ////////////////////////////////////////////////////////////////////////////////
5595 /// Return entry number corresponding to major and minor number.
5596 /// Note that this function returns only the entry number, not the data
5597 /// To read the data corresponding to an entry number, use TTree::GetEntryWithIndex
5598 /// the BuildIndex function has created a table of Long64_t* of sorted values
5599 /// corresponding to val = major<<31 + minor;
5600 /// The function performs binary search in this sorted table.
5601 /// If it finds a pair that matches val, it returns directly the
5602 /// index in the table.
5603 /// If an entry corresponding to major and minor is not found, the function
5604 /// returns the index of the major,minor pair immediately lower than the
5605 /// requested value, ie it will return -1 if the pair is lower than
5606 /// the first entry in the index.
5607 ///
5608 /// See also GetEntryNumberWithIndex
5611 {
5612  if (!fTreeIndex) {
5613  return -1;
5614  }
5615  return fTreeIndex->GetEntryNumberWithBestIndex(major, minor);
5616 }
5617 
5618 ////////////////////////////////////////////////////////////////////////////////
5619 /// Return entry number corresponding to major and minor number.
5620 /// Note that this function returns only the entry number, not the data
5621 /// To read the data corresponding to an entry number, use TTree::GetEntryWithIndex
5622 /// the BuildIndex function has created a table of Long64_t* of sorted values
5623 /// corresponding to val = major<<31 + minor;
5624 /// The function performs binary search in this sorted table.
5625 /// If it finds a pair that matches val, it returns directly the
5626 /// index in the table, otherwise it returns -1.
5627 ///
5628 /// See also GetEntryNumberWithBestIndex
5631 {
5632  if (!fTreeIndex) {
5633  return -1;
5634  }
5635  return fTreeIndex->GetEntryNumberWithIndex(major, minor);
5636 }
5637 
5638 ////////////////////////////////////////////////////////////////////////////////
5639 /// Read entry corresponding to major and minor number.
5640 ///
5641 /// The function returns the total number of bytes read.
5642 /// If the Tree has friend trees, the corresponding entry with
5643 /// the index values (major,minor) is read. Note that the master Tree
5644 /// and its friend may have different entry serial numbers corresponding
5645 /// to (major,minor).
5648 {
5649  // We already have been visited while recursively looking
5650  // through the friends tree, let's return.
5652  return 0;
5653  }
5654  Long64_t serial = GetEntryNumberWithIndex(major, minor);
5655  if (serial < 0) {
5656  return -1;
5657  }
5658  // create cache if wanted
5659  if (fCacheDoAutoInit)
5660  SetCacheSizeAux();
5661 
5662  Int_t i;
5663  Int_t nbytes = 0;
5664  fReadEntry = serial;
5665  TBranch *branch;
5666  Int_t nbranches = fBranches.GetEntriesFast();
5667  Int_t nb;
5668  for (i = 0; i < nbranches; ++i) {
5669  branch = (TBranch*)fBranches.UncheckedAt(i);
5670  nb = branch->GetEntry(serial);
5671  if (nb < 0) return nb;
5672  nbytes += nb;
5673  }
5674  // GetEntry in list of friends
5675  if (!fFriends) return nbytes;
5676  TFriendLock lock(this,kGetEntryWithIndex);
5677  TIter nextf(fFriends);
5678  TFriendElement* fe = 0;
5679  while ((fe = (TFriendElement*) nextf())) {
5680  TTree *t = fe->GetTree();
5681  if (t) {
5682  serial = t->GetEntryNumberWithIndex(major,minor);
5683  if (serial <0) return -nbytes;
5684  nb = t->GetEntry(serial);
5685  if (nb < 0) return nb;
5686  nbytes += nb;
5687  }
5688  }
5689  return nbytes;
5690 }
5691 
5692 ////////////////////////////////////////////////////////////////////////////////
5693 /// Return a pointer to the TTree friend whose name or alias is 'friendname.
5695 TTree* TTree::GetFriend(const char *friendname) const
5696 {
5697 
5698  // We already have been visited while recursively
5699  // looking through the friends tree, let's return.
5700  if (kGetFriend & fFriendLockStatus) {
5701  return 0;
5702  }
5703  if (!fFriends) {
5704  return 0;
5705  }
5706  TFriendLock lock(const_cast<TTree*>(this), kGetFriend);
5707  TIter nextf(fFriends);
5708  TFriendElement* fe = 0;
5709  while ((fe = (TFriendElement*) nextf())) {
5710  if (strcmp(friendname,fe->GetName())==0
5711  || strcmp(friendname,fe->GetTreeName())==0) {
5712  return fe->GetTree();
5713  }
5714  }
5715  // After looking at the first level,
5716  // let's see if it is a friend of friends.
5717  nextf.Reset();
5718  fe = 0;
5719  while ((fe = (TFriendElement*) nextf())) {
5720  TTree *res = fe->GetTree()->GetFriend(friendname);
5721  if (res) {
5722  return res;
5723  }
5724  }
5725  return 0;
5726 }
5727 
5728 ////////////////////////////////////////////////////////////////////////////////
5729 /// If the 'tree' is a friend, this method returns its alias name.
5730 ///
5731 /// This alias is an alternate name for the tree.
5732 ///
5733 /// It can be used in conjunction with a branch or leaf name in a TTreeFormula,
5734 /// to specify in which particular tree the branch or leaf can be found if
5735 /// the friend trees have branches or leaves with the same name as the master
5736 /// tree.
5737 ///
5738 /// It can also be used in conjunction with an alias created using
5739 /// TTree::SetAlias in a TTreeFormula, e.g.:
5740 /// ~~~ {.cpp}
5741 /// maintree->Draw("treealias.fPx - treealias.myAlias");
5742 /// ~~~
5743 /// where fPx is a branch of the friend tree aliased as 'treealias' and 'myAlias'
5744 /// was created using TTree::SetAlias on the friend tree.
5745 ///
5746 /// However, note that 'treealias.myAlias' will be expanded literally,
5747 /// without remembering that it comes from the aliased friend and thus
5748 /// the branch name might not be disambiguated properly, which means
5749 /// that you may not be able to take advantage of this feature.
5750 ///
5752 const char* TTree::GetFriendAlias(TTree* tree) const
5753 {
5754  if ((tree == this) || (tree == GetTree())) {
5755  return 0;
5756  }
5757 
5758  // We already have been visited while recursively
5759  // looking through the friends tree, let's return.
5761  return 0;
5762  }
5763  if (!fFriends) {
5764  return 0;
5765  }
5766  TFriendLock lock(const_cast<TTree*>(this), kGetFriendAlias);
5767  TIter nextf(fFriends);
5768  TFriendElement* fe = 0;
5769  while ((fe = (TFriendElement*) nextf())) {
5770  TTree* t = fe->GetTree();
5771  if (t == tree) {
5772  return fe->GetName();
5773  }
5774  // Case of a chain:
5775  if (t && t->GetTree() == tree) {
5776  return fe->GetName();
5777  }
5778  }
5779  // After looking at the first level,
5780  // let's see if it is a friend of friends.
5781  nextf.Reset();
5782  fe = 0;
5783  while ((fe = (TFriendElement*) nextf())) {
5784  const char* res = fe->GetTree()->GetFriendAlias(tree);
5785  if (res) {
5786  return res;
5787  }
5788  }
5789  return 0;
5790 }
5791 
5792 ////////////////////////////////////////////////////////////////////////////////
5793 /// Returns the current set of IO settings
5795 {
5796  return fIOFeatures;
5797 }
5798 
5799 ////////////////////////////////////////////////////////////////////////////////
5800 /// Creates a new iterator that will go through all the leaves on the tree itself and its friend.
5803 {
5804  return new TTreeFriendLeafIter(this, dir);
5805 }
5806 
5807 ////////////////////////////////////////////////////////////////////////////////
5808 /// Return pointer to the 1st Leaf named name in any Branch of this
5809 /// Tree or any branch in the list of friend trees.
5810 ///
5811 /// The leaf name can contain the name of a friend tree with the
5812 /// syntax: friend_dir_and_tree.full_leaf_name
5813 /// the friend_dir_and_tree can be of the form:
5814 /// ~~~ {.cpp}
5815 /// TDirectoryName/TreeName
5816 /// ~~~
5818 TLeaf* TTree::GetLeafImpl(const char* branchname, const char *leafname)
5819 {
5820  TLeaf *leaf = 0;
5821  if (branchname) {
5822  TBranch *branch = FindBranch(branchname);
5823  if (branch) {
5824  leaf = branch->GetLeaf(leafname);
5825  if (leaf) {
5826  return leaf;
5827  }
5828  }
5829  }
5830  TIter nextl(GetListOfLeaves());
5831  while ((leaf = (TLeaf*)nextl())) {
5832  if (strcmp(leaf->GetName(),leafname)) continue;
5833  if (branchname) {
5834  UInt_t nbch = strlen(branchname);
5835  TBranch *br = leaf->GetBranch();
5836  const char* brname = br->GetName();
5837  TBranch *mother = br->GetMother();
5838  if (strncmp(brname,branchname,nbch)) {
5839  if (mother != br) {
5840  const char *mothername = mother->GetName();
5841  UInt_t motherlen = strlen(mothername);
5842  if (nbch > motherlen && strncmp(mothername,branchname,motherlen)==0 && (mothername[motherlen-1]=='.' || branchname[motherlen]=='.')) {
5843  // 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.
5844  if (strncmp(brname,branchname+motherlen+1,nbch-motherlen-1)) {
5845  // No it does not
5846  continue;
5847  } // else we have match so we can proceed.
5848  } else {
5849  // no match
5850  continue;
5851  }
5852  } else {
5853  continue;
5854  }
5855  }
5856  // The start of the branch name is identical to the content
5857  // of 'aname' before the first '/'.
5858  // Let's make sure that it is not longer (we are trying
5859  // to avoid having jet2/value match the branch jet23
5860  if ((strlen(brname) > nbch) && (brname[nbch] != '.') && (brname[nbch] != '[')) {
5861  continue;
5862  }
5863  }
5864  return leaf;
5865  }
5866  if (!fFriends) return 0;
5867  TFriendLock lock(this,kGetLeaf);
5868  TIter next(fFriends);
5869  TFriendElement *fe;
5870  while ((fe = (TFriendElement*)next())) {
5871  TTree *t = fe->GetTree();
5872  if (t) {
5873  leaf = t->GetLeaf(leafname);
5874  if (leaf) return leaf;
5875  }
5876  }
5877 
5878  //second pass in the list of friends when the leaf name
5879  //is prefixed by the tree name
5880  TString strippedArg;
5881  next.Reset();
5882  while ((fe = (TFriendElement*)next())) {
5883  TTree *t = fe->GetTree();
5884  if (t==0) continue;
5885  char *subname = (char*)strstr(leafname,fe->GetName());
5886  if (subname != leafname) continue;
5887  Int_t l = strlen(fe->GetName());
5888  subname += l;
5889  if (*subname != '.') continue;
5890  subname++;
5891  strippedArg += subname;
5892  leaf = t->GetLeaf(branchname,subname);
5893  if (leaf) return leaf;
5894  }
5895  return 0;
5896 }
5897 
5898 ////////////////////////////////////////////////////////////////////////////////
5899 /// Return pointer to the 1st Leaf named name in any Branch of this
5900 /// Tree or any branch in the list of friend trees.
5901 ///
5902 /// The leaf name can contain the name of a friend tree with the
5903 /// syntax: friend_dir_and_tree.full_leaf_name
5904 /// the friend_dir_and_tree can be of the form:
5905 ///
5906 /// TDirectoryName/TreeName
5908 TLeaf* TTree::GetLeaf(const char* branchname, const char *leafname)
5909 {
5910  if (leafname == 0) return 0;
5911 
5912  // We already have been visited while recursively looking
5913  // through the friends tree, let return
5914  if (kGetLeaf & fFriendLockStatus) {
5915  return 0;
5916  }
5917 
5918  return GetLeafImpl(branchname,leafname);
5919 }
5920 
5921 ////////////////////////////////////////////////////////////////////////////////
5922 /// Return pointer to the 1st Leaf named name in any Branch of this
5923 /// Tree or any branch in the list of friend trees.
5924 ///
5925 /// aname may be of the form branchname/leafname
5927 TLeaf* TTree::GetLeaf(const char* aname)
5928 {
5929  if (aname == 0) return 0;
5930 
5931  // We already have been visited while recursively looking
5932  // through the friends tree, let return
5933  if (kGetLeaf & fFriendLockStatus) {
5934  return 0;
5935  }
5936  char* slash = (char*) strrchr(aname, '/');
5937  char* name = 0;
5938  UInt_t nbch = 0;
5939  if (slash) {
5940  name = slash + 1;
5941  nbch = slash - aname;
5942  TString brname(aname,nbch);
5943  return GetLeafImpl(brname.Data(),name);
5944  } else {
5945  return GetLeafImpl(0,aname);
5946  }
5947 }
5948 
5949 ////////////////////////////////////////////////////////////////////////////////
5950 /// Return maximum of column with name columname.
5951 /// if the Tree has an associated TEventList or TEntryList, the maximum
5952 /// is computed for the entries in this list.
5954 Double_t TTree::GetMaximum(const char* columname)
5955 {
5956  TLeaf* leaf = this->GetLeaf(columname);
5957  if (!leaf) {
5958  return 0;
5959  }
5960 
5961  // create cache if wanted
5962  if (fCacheDoAutoInit)
5963  SetCacheSizeAux();
5964 
5965  TBranch* branch = leaf->GetBranch();
5966  Double_t cmax = -DBL_MAX;
5967  for (Long64_t i = 0; i < fEntries; ++i) {
5968  Long64_t entryNumber = this->GetEntryNumber(i);
5969  if (entryNumber < 0) break;
5970  branch->GetEntry(entryNumber);
5971  for (Int_t j = 0; j < leaf->GetLen(); ++j) {
5972  Double_t val = leaf->GetValue(j);
5973  if (val > cmax) {
5974  cmax = val;
5975  }
5976  }
5977  }
5978  return cmax;
5979 }
5980 
5981 ////////////////////////////////////////////////////////////////////////////////
5982 /// Static function which returns the tree file size limit in bytes.
5985 {
5986  return fgMaxTreeSize;
5987 }
5988 
5989 ////////////////////////////////////////////////////////////////////////////////
5990 /// Return minimum of column with name columname.
5991 /// if the Tree has an associated TEventList or TEntryList, the minimum
5992 /// is computed for the entries in this list.
5994 Double_t TTree::GetMinimum(const char* columname)
5995 {
5996  TLeaf* leaf = this->GetLeaf(columname);
5997  if (!leaf) {
5998  return 0;
5999  }
6000 
6001  // create cache if wanted
6002  if (fCacheDoAutoInit)
6003  SetCacheSizeAux();
6004 
6005  TBranch* branch = leaf->GetBranch();
6006  Double_t cmin = DBL_MAX;
6007  for (Long64_t i = 0; i < fEntries; ++i) {
6008  Long64_t entryNumber = this->GetEntryNumber(i);
6009  if (entryNumber < 0) break;
6010  branch->GetEntry(entryNumber);
6011  for (Int_t j = 0;j < leaf->GetLen(); ++j) {
6012  Double_t val = leaf->GetValue(j);
6013  if (val < cmin) {
6014  cmin = val;
6015  }
6016  }
6017  }
6018  return cmin;
6019 }
6020 
6021 ////////////////////////////////////////////////////////////////////////////////
6022 /// Load the TTreePlayer (if not already done).
6025 {
6026  if (fPlayer) {
6027  return fPlayer;
6028  }
6030  return fPlayer;
6031 }
6032 
6033 ////////////////////////////////////////////////////////////////////////////////
6034 /// Find and return the TTreeCache registered with the file and which may
6035 /// contain branches for us.
6038 {
6039  TTreeCache *pe = dynamic_cast<TTreeCache*>(file->GetCacheRead(this));
6040  if (pe && pe->GetTree() != this)
6041  pe = nullptr;
6042  return pe;
6043 }
6044 
6045 ////////////////////////////////////////////////////////////////////////////////
6046 /// Find and return the TTreeCache registered with the file and which may
6047 /// contain branches for us. If create is true and there is no cache
6048 /// a new cache is created with default size.
6051 {
6052  TTreeCache *pe = GetReadCache(file);
6053  if (create && !pe) {
6054  if (fCacheDoAutoInit)
6055  SetCacheSizeAux(kTRUE, -1);
6056  pe = dynamic_cast<TTreeCache*>(file->GetCacheRead(this));
6057  if (pe && pe->GetTree() != this) pe = 0;
6058  }
6059  return pe;
6060 }
6061 
6062 ////////////////////////////////////////////////////////////////////////////////
6063 /// Return a pointer to the list containing user objects associated to this tree.
6064 ///
6065 /// The list is automatically created if it does not exist.
6066 ///
6067 /// WARNING: By default the TTree destructor will delete all objects added
6068 /// to this list. If you do not want these objects to be deleted,
6069 /// call:
6070 ///
6071 /// mytree->GetUserInfo()->Clear();
6072 ///
6073 /// before deleting the tree.
6076 {
6077  if (!fUserInfo) {
6078  fUserInfo = new TList();
6079  fUserInfo->SetName("UserInfo");
6080  }
6081  return fUserInfo;
6082 }
6083 
6084 ////////////////////////////////////////////////////////////////////////////////
6085 /// Appends the cluster range information stored in 'fromtree' to this tree,
6086 /// including the value of fAutoFlush.
6087 ///
6088 /// This is used when doing a fast cloning (by TTreeCloner).
6089 /// See also fAutoFlush and fAutoSave if needed.
6091 void TTree::ImportClusterRanges(TTree *fromtree)
6092 {
6093  Long64_t autoflush = fromtree->GetAutoFlush();
6094  if (fromtree->fNClusterRange == 0 && fromtree->fAutoFlush == fAutoFlush) {
6095  // nothing to do
6096  } else if (fNClusterRange || fromtree->fNClusterRange) {
6097  Int_t newsize = fNClusterRange + 1 + fromtree->fNClusterRange;
6098  if (newsize > fMaxClusterRange) {
6099  if (fMaxClusterRange) {
6101  newsize*sizeof(Long64_t),fMaxClusterRange*sizeof(Long64_t));
6103  newsize*sizeof(Long64_t),fMaxClusterRange*sizeof(Long64_t));
6104  fMaxClusterRange = newsize;
6105  } else {
6106  fMaxClusterRange = newsize;
6109  }
6110  }
6111  if (fEntries) {
6114  ++fNClusterRange;
6115  }
6116  for (Int_t i = 0 ; i < fromtree->fNClusterRange; ++i) {
6118  fClusterSize[fNClusterRange] = fromtree->fClusterSize[i];
6119  ++fNClusterRange;
6120  }
6121  fAutoFlush = autoflush;
6122  } else {
6123  SetAutoFlush( autoflush );
6124  }
6125  Long64_t autosave = GetAutoSave();
6126  if (autoflush > 0 && autosave > 0) {
6127  SetAutoSave( autoflush*(autosave/autoflush) );
6128  }
6129 }
6130 
6131 ////////////////////////////////////////////////////////////////////////////////
6132 /// Keep a maximum of fMaxEntries in memory.
6134 void TTree::KeepCircular()
6135 {
6137  Long64_t maxEntries = fMaxEntries - (fMaxEntries / 10);
6138  for (Int_t i = 0; i < nb; ++i) {
6139  TBranch* branch = (TBranch*) fBranches.UncheckedAt(i);
6140  branch->KeepCircular(maxEntries);
6141  }
6142  if (fNClusterRange) {
6143  Long64_t entriesOffset = fEntries - maxEntries;
6144  Int_t oldsize = fNClusterRange;
6145  for(Int_t i = 0, j = 0; j < oldsize; ++j) {
6146  if (fClusterRangeEnd[j] > entriesOffset) {
6147  fClusterRangeEnd[i] = fClusterRangeEnd[j] - entriesOffset;
6148  ++i;
6149  } else {
6150  --fNClusterRange;
6151  }
6152  }
6153  }
6154  fEntries = maxEntries;
6155  fReadEntry = -1;
6156 }
6157 
6158 ////////////////////////////////////////////////////////////////////////////////
6159 /// Read in memory all baskets from all branches up to the limit of maxmemory bytes.
6160 ///
6161 /// If maxmemory is non null and positive SetMaxVirtualSize is called
6162 /// with this value. Default for maxmemory is 2000000000 (2 Gigabytes).
6163 /// The function returns the total number of baskets read into memory
6164 /// if negative an error occurred while loading the branches.
6165 /// This method may be called to force branch baskets in memory
6166 /// when random access to branch entries is required.
6167 /// If random access to only a few branches is required, you should
6168 /// call directly TBranch::LoadBaskets.
6171 {
6172  if (maxmemory > 0) SetMaxVirtualSize(maxmemory);
6173 
6174  TIter next(GetListOfLeaves());
6175  TLeaf *leaf;
6176  Int_t nimported = 0;
6177  while ((leaf=(TLeaf*)next())) {
6178  nimported += leaf->GetBranch()->LoadBaskets();//break;
6179  }
6180  return nimported;
6181 }
6182 
6183 ////////////////////////////////////////////////////////////////////////////////
6184 /// Set current entry.
6185 ///
6186 /// Returns -2 if entry does not exist (just as TChain::LoadTree()).
6187 ///
6188 /// Note: This function is overloaded in TChain.
6189 ///
6192 {
6193  // We already have been visited while recursively looking
6194  // through the friends tree, let return
6195  if (kLoadTree & fFriendLockStatus) {
6196  // We need to return a negative value to avoid a circular list of friend
6197  // to think that there is always an entry somewhere in the list.
6198  return -1;
6199  }
6200 
6201  // create cache if wanted
6202  if (fCacheDoAutoInit && entry >=0)
6203  SetCacheSizeAux();
6204 
6205  if (fNotify) {
6206  if (fReadEntry < 0) {
6207  fNotify->Notify();
6208  }
6209  }
6210  fReadEntry = entry;
6211 
6212  Bool_t friendHasEntry = kFALSE;
6213  if (fFriends) {
6214  // Set current entry in friends as well.
6215  //
6216  // An alternative would move this code to each of the
6217  // functions calling LoadTree (and to overload a few more).
6218  Bool_t needUpdate = kFALSE;
6219  {
6220  // This scope is need to insure the lock is released at the right time
6221  TIter nextf(fFriends);
6222  TFriendLock lock(this, kLoadTree);
6223  TFriendElement* fe = 0;
6224  while ((fe = (TFriendElement*) nextf())) {
6226  // This friend element was added by the chain that owns this
6227  // tree, the chain will deal with loading the correct entry.
6228  continue;
6229  }
6230  TTree* friendTree = fe->GetTree();
6231  if (friendTree == 0) {
6232  // Somehow we failed to retrieve the friend TTree.
6233  } else if (friendTree->IsA() == TTree::Class()) {
6234  // Friend is actually a tree.
6235  if (friendTree->LoadTreeFriend(entry, this) >= 0) {
6236  friendHasEntry = kTRUE;
6237  }
6238  } else {
6239  // Friend is actually a chain.
6240  // FIXME: This logic should be in the TChain override.
6241  Int_t oldNumber = friendTree->GetTreeNumber();
6242  if (friendTree->LoadTreeFriend(entry, this) >= 0) {
6243  friendHasEntry = kTRUE;
6244  }
6245  Int_t newNumber = friendTree->GetTreeNumber();
6246  if (oldNumber != newNumber) {
6247  // We can not just compare the tree pointers because they could be reused.
6248  // So we compare the tree number instead.
6249  needUpdate = kTRUE;
6250  }
6251  }
6252  } // for each friend
6253  }
6254  if (needUpdate) {
6255  //update list of leaves in all TTreeFormula of the TTreePlayer (if any)
6256  if (fPlayer) {
6258  }
6259  //Notify user if requested
6260  if (fNotify) {
6261  fNotify->Notify();
6262  }
6263  }
6264  }
6265 
6266  if ((fReadEntry >= fEntries) && !friendHasEntry) {
6267  fReadEntry = -1;
6268  return -2;
6269  }
6270  return fReadEntry;
6271 }
6272 
6273 ////////////////////////////////////////////////////////////////////////////////
6274 /// Load entry on behalf of our master tree, we may use an index.
6275 ///
6276 /// Called by LoadTree() when the masterTree looks for the entry
6277 /// number in a friend tree (us) corresponding to the passed entry
6278 /// number in the masterTree.
6279 ///
6280 /// If we have no index, our entry number and the masterTree entry
6281 /// number are the same.
6282 ///
6283 /// If we *do* have an index, we must find the (major, minor) value pair
6284 /// in masterTree to locate our corresponding entry.
6285 ///
6287 Long64_t TTree::LoadTreeFriend(Long64_t entry, TTree* masterTree)
6288 {
6289  if (!fTreeIndex) {
6290  return LoadTree(entry);
6291  }
6292  return LoadTree(fTreeIndex->GetEntryNumberFriend(masterTree));
6293 }
6294 
6295 ////////////////////////////////////////////////////////////////////////////////
6296 /// Generate a skeleton analysis class for this tree.
6297 ///
6298 /// The following files are produced: classname.h and classname.C.
6299 /// If classname is 0, classname will be called "nameoftree".
6300 ///
6301 /// The generated code in classname.h includes the following:
6302 ///
6303 /// - Identification of the original tree and the input file name.
6304 /// - Definition of an analysis class (data members and member functions).
6305 /// - The following member functions:
6306 /// - constructor (by default opening the tree file),
6307 /// - GetEntry(Long64_t entry),
6308 /// - Init(TTree* tree) to initialize a new TTree,
6309 /// - Show(Long64_t entry) to read and dump entry.
6310 ///
6311 /// The generated code in classname.C includes only the main
6312 /// analysis function Loop.
6313 ///
6314 /// To use this function:
6315 ///
6316 /// - Open your tree file (eg: TFile f("myfile.root");)
6317 /// - T->MakeClass("MyClass");
6318 ///
6319 /// where T is the name of the TTree in file myfile.root,
6320 /// and MyClass.h, MyClass.C the name of the files created by this function.
6321 /// In a ROOT session, you can do:
6322 /// ~~~ {.cpp}
6323 /// root > .L MyClass.C
6324 /// root > MyClass* t = new MyClass;
6325 /// root > t->GetEntry(12); // Fill data members of t with entry number 12.
6326 /// root > t->Show(); // Show values of entry 12.
6327 /// root > t->Show(16); // Read and show values of entry 16.
6328 /// root > t->Loop(); // Loop on all entries.
6329 /// ~~~
6330 /// NOTE: Do not use the code generated for a single TTree which is part
6331 /// of a TChain to process that entire TChain. The maximum dimensions
6332 /// calculated for arrays on the basis of a single TTree from the TChain
6333 /// might be (will be!) too small when processing all of the TTrees in
6334 /// the TChain. You must use myChain.MakeClass() to generate the code,
6335 /// not myTree.MakeClass(...).
6337 Int_t TTree::MakeClass(const char* classname, Option_t* option)
6338 {
6339  GetPlayer();
6340  if (!fPlayer) {
6341  return 0;
6342  }
6343  return fPlayer->MakeClass(classname, option);
6344 }
6345 
6346 ////////////////////////////////////////////////////////////////////////////////
6347 /// Generate a skeleton function for this tree.
6348 ///
6349 /// The function code is written on filename.
6350 /// If filename is 0, filename will be called nameoftree.C
6351 ///
6352 /// The generated code includes the following:
6353 /// - Identification of the original Tree and Input file name,
6354 /// - Opening the Tree file,
6355 /// - Declaration of Tree variables,
6356 /// - Setting of branches addresses,
6357 /// - A skeleton for the entry loop.
6358 ///
6359 /// To use this function:
6360 ///
6361 /// - Open your Tree file (eg: TFile f("myfile.root");)
6362 /// - T->MakeCode("MyAnalysis.C");
6363 ///
6364 /// where T is the name of the TTree in file myfile.root
6365 /// and MyAnalysis.C the name of the file created by this function.
6366 ///
6367 /// NOTE: Since the implementation of this function, a new and better
6368 /// function TTree::MakeClass() has been developed.
6370 Int_t TTree::MakeCode(const char* filename)
6371 {
6372  Warning("MakeCode", "MakeCode is obsolete. Use MakeClass or MakeSelector instead");
6373 
6374  GetPlayer();
6375  if (!fPlayer) return 0;
6376  return fPlayer->MakeCode(filename);
6377 }
6378 
6379 ////////////////////////////////////////////////////////////////////////////////
6380 /// Generate a skeleton analysis class for this Tree using TBranchProxy.
6381 ///
6382 /// TBranchProxy is the base of a class hierarchy implementing an
6383 /// indirect access to the content of the branches of a TTree.
6384 ///
6385 /// "proxyClassname" is expected to be of the form:
6386 /// ~~~ {.cpp}
6387 /// [path/]fileprefix
6388 /// ~~~
6389 /// The skeleton will then be generated in the file:
6390 /// ~~~ {.cpp}
6391 /// fileprefix.h
6392 /// ~~~
6393 /// located in the current directory or in 'path/' if it is specified.
6394 /// The class generated will be named 'fileprefix'
6395 ///
6396 /// "macrofilename" and optionally "cutfilename" are expected to point
6397 /// to source files which will be included by the generated skeleton.
6398 /// Method of the same name as the file(minus the extension and path)
6399 /// will be called by the generated skeleton's Process method as follow:
6400 /// ~~~ {.cpp}
6401 /// [if (cutfilename())] htemp->Fill(macrofilename());
6402 /// ~~~
6403 /// "option" can be used select some of the optional features during
6404 /// the code generation. The possible options are:
6405 ///
6406 /// - nohist : indicates that the generated ProcessFill should not fill the histogram.
6407 ///
6408 /// 'maxUnrolling' controls how deep in the class hierarchy does the
6409 /// system 'unroll' classes that are not split. Unrolling a class
6410 /// allows direct access to its data members (this emulates the behavior
6411 /// of TTreeFormula).
6412 ///
6413 /// The main features of this skeleton are:
6414 ///
6415 /// * on-demand loading of branches
6416 /// * ability to use the 'branchname' as if it was a data member
6417 /// * protection against array out-of-bounds errors
6418 /// * ability to use the branch data as an object (when the user code is available)
6419 ///
6420 /// For example with Event.root, if
6421 /// ~~~ {.cpp}
6422 /// Double_t somePx = fTracks.fPx[2];
6423 /// ~~~
6424 /// is executed by one of the method of the skeleton,
6425 /// somePx will updated with the current value of fPx of the 3rd track.
6426 ///
6427 /// Both macrofilename and the optional cutfilename are expected to be
6428 /// the name of source files which contain at least a free standing
6429 /// function with the signature:
6430 /// ~~~ {.cpp}
6431 /// x_t macrofilename(); // i.e function with the same name as the file
6432 /// ~~~
6433 /// and
6434 /// ~~~ {.cpp}
6435 /// y_t cutfilename(); // i.e function with the same name as the file
6436 /// ~~~
6437 /// x_t and y_t needs to be types that can convert respectively to a double
6438 /// and a bool (because the skeleton uses:
6439 ///
6440 /// if (cutfilename()) htemp->Fill(macrofilename());
6441 ///
6442 /// These two functions are run in a context such that the branch names are
6443 /// available as local variables of the correct (read-only) type.
6444 ///
6445 /// Note that if you use the same 'variable' twice, it is more efficient
6446 /// to 'cache' the value. For example:
6447 /// ~~~ {.cpp}
6448 /// Int_t n = fEventNumber; // Read fEventNumber
6449 /// if (n<10 || n>10) { ... }
6450 /// ~~~
6451 /// is more efficient than
6452 /// ~~~ {.cpp}
6453 /// if (fEventNumber<10 || fEventNumber>10)
6454 /// ~~~
6455 /// Also, optionally, the generated selector will also call methods named
6456 /// macrofilename_methodname in each of 6 main selector methods if the method
6457 /// macrofilename_methodname exist (Where macrofilename is stripped of its
6458 /// extension).
6459 ///
6460 /// Concretely, with the script named h1analysisProxy.C,
6461 ///
6462 /// - The method calls the method (if it exist)
6463 /// - Begin -> void h1analysisProxy_Begin(TTree*);
6464 /// - SlaveBegin -> void h1analysisProxy_SlaveBegin(TTree*);
6465 /// - Notify -> Bool_t h1analysisProxy_Notify();
6466 /// - Process -> Bool_t h1analysisProxy_Process(Long64_t);
6467 /// - SlaveTerminate -> void h1analysisProxy_SlaveTerminate();
6468 /// - Terminate -> void h1analysisProxy_Terminate();
6469 ///
6470 /// If a file name macrofilename.h (or .hh, .hpp, .hxx, .hPP, .hXX) exist
6471 /// it is included before the declaration of the proxy class. This can
6472 /// be used in particular to insure that the include files needed by
6473 /// the macro file are properly loaded.
6474 ///
6475 /// The default histogram is accessible via the variable named 'htemp'.
6476 ///
6477 /// If the library of the classes describing the data in the branch is
6478 /// loaded, the skeleton will add the needed `include` statements and
6479 /// give the ability to access the object stored in the branches.
6480 ///
6481 /// To draw px using the file hsimple.root (generated by the
6482 /// hsimple.C tutorial), we need a file named hsimple.cxx:
6483 /// ~~~ {.cpp}
6484 /// double hsimple() {
6485 /// return px;
6486 /// }
6487 /// ~~~
6488 /// MakeProxy can then be used indirectly via the TTree::Draw interface
6489 /// as follow:
6490 /// ~~~ {.cpp}
6491 /// new TFile("hsimple.root")
6492 /// ntuple->Draw("hsimple.cxx");
6493 /// ~~~
6494 /// A more complete example is available in the tutorials directory:
6495 /// h1analysisProxy.cxx , h1analysProxy.h and h1analysisProxyCut.C
6496 /// which reimplement the selector found in h1analysis.C
6498 Int_t TTree::MakeProxy(const char* proxyClassname, const char* macrofilename, const char* cutfilename, const char* option, Int_t maxUnrolling)
6499 {
6500  GetPlayer();
6501  if (!fPlayer) return 0;
6502  return fPlayer->MakeProxy(proxyClassname,macrofilename,cutfilename,option,maxUnrolling);
6503 }
6504 
6505 ////////////////////////////////////////////////////////////////////////////////
6506 /// Generate skeleton selector class for this tree.
6507 ///
6508 /// The following files are produced: selector.h and selector.C.
6509 /// If selector is 0, the selector will be called "nameoftree".
6510 /// The option can be used to specify the branches that will have a data member.
6511 /// - If option is "=legacy", a pre-ROOT6 selector will be generated (data
6512 /// members and branch pointers instead of TTreeReaders).
6513 /// - If option is empty, readers will be generated for each leaf.
6514 /// - If option is "@", readers will be generated for the topmost branches.
6515 /// - Individual branches can also be picked by their name:
6516 /// - "X" generates readers for leaves of X.
6517 /// - "@X" generates a reader for X as a whole.
6518 /// - "@X;Y" generates a reader for X as a whole and also readers for the
6519 /// leaves of Y.
6520 /// - For further examples see the figure below.
6521 ///
6522 /// \image html ttree_makeselector_option_examples.png
6523 ///
6524 /// The generated code in selector.h includes the following:
6525 /// - Identification of the original Tree and Input file name
6526 /// - Definition of selector class (data and functions)
6527 /// - The following class functions:
6528 /// - constructor and destructor
6529 /// - void Begin(TTree *tree)
6530 /// - void SlaveBegin(TTree *tree)
6531 /// - void Init(TTree *tree)
6532 /// - Bool_t Notify()
6533 /// - Bool_t Process(Long64_t entry)
6534 /// - void Terminate()
6535 /// - void SlaveTerminate()
6536 ///
6537 /// The class selector derives from TSelector.
6538 /// The generated code in selector.C includes empty functions defined above.
6539 ///
6540 /// To use this function:
6541 ///
6542 /// - connect your Tree file (eg: `TFile f("myfile.root");`)
6543 /// - `T->MakeSelector("myselect");`
6544 ///
6545 /// where T is the name of the Tree in file myfile.root
6546 /// and myselect.h, myselect.C the name of the files created by this function.
6547 /// In a ROOT session, you can do:
6548 /// ~~~ {.cpp}
6549 /// root > T->Process("myselect.C")
6550 /// ~~~
6552 Int_t TTree::MakeSelector(const char* selector, Option_t* option)
6553 {
6554  TString opt(option);
6555  if(opt.EqualTo("=legacy", TString::ECaseCompare::kIgnoreCase)) {
6556  return MakeClass(selector, "selector");
6557  } else {
6558  GetPlayer();
6559  if (!fPlayer) return 0;
6560  return fPlayer->MakeReader(selector, option);
6561  }
6562 }
6563 
6564 ////////////////////////////////////////////////////////////////////////////////
6565 /// Check if adding nbytes to memory we are still below MaxVirtualsize.
6568 {
6569  if ((fTotalBuffers + nbytes) < fMaxVirtualSize) {
6570  return kFALSE;
6571  }
6572  return kTRUE;
6573 }
6574 
6575 ////////////////////////////////////////////////////////////////////////////////
6576 /// Static function merging the trees in the TList into a new tree.
6577 ///
6578 /// Trees in the list can be memory or disk-resident trees.
6579 /// The new tree is created in the current directory (memory if gROOT).
6581 TTree* TTree::MergeTrees(TList* li, Option_t* options)
6582 {
6583  if (!li) return 0;
6584  TIter next(li);
6585  TTree *newtree = 0;
6586  TObject *obj;
6587 
6588  while ((obj=next())) {
6589  if (!obj->InheritsFrom(TTree::Class())) continue;
6590  TTree *tree = (TTree*)obj;
6591  Long64_t nentries = tree->GetEntries();
6592  if (nentries == 0) continue;
6593  if (!newtree) {
6594  newtree = (TTree*)tree->CloneTree();
6595  if (!newtree) continue;
6596 
6597  // Once the cloning is done, separate the trees,
6598  // to avoid as many side-effects as possible
6599  // The list of clones is guaranteed to exist since we
6600  // just cloned the tree.
6601  tree->GetListOfClones()->Remove(newtree);
6602  tree->ResetBranchAddresses();
6603  newtree->ResetBranchAddresses();
6604  continue;
6605  }
6606 
6607  newtree->CopyAddresses(tree);
6608 
6609  newtree->CopyEntries(tree,-1,options);
6610 
6611  tree->ResetBranchAddresses(); // Disconnect from new tree.
6612  }
6613  if (newtree && newtree->GetTreeIndex()) {
6614  newtree->GetTreeIndex()->Append(0,kFALSE); // Force the sorting
6615  }
6616  return newtree;
6617 }
6618 
6619 ////////////////////////////////////////////////////////////////////////////////
6620 /// Merge the trees in the TList into this tree.
6621 ///
6622 /// Returns the total number of entries in the merged tree.
6625 {
6626  if (!li) return 0;
6627  Long64_t storeAutoSave = fAutoSave;
6628  // Disable the autosave as the TFileMerge keeps a list of key and deleting the underlying
6629  // key would invalidate its iteration (or require costly measure to not use the deleted keys).
6630  // Also since this is part of a merging operation, the output file is not as precious as in
6631  // the general case since the input file should still be around.
6632  fAutoSave = 0;
6633  TIter next(li);
6634  TTree *tree;
6635  while ((tree = (TTree*)next())) {
6636  if (tree==this) continue;
6637  if (!tree->InheritsFrom(TTree::Class())) {
6638  Error("Add","Attempt to add object of class: %s to a %s", tree->ClassName(), ClassName());
6639  fAutoSave = storeAutoSave;
6640  return -1;
6641  }
6642 
6643  Long64_t nentries = tree->GetEntries();
6644  if (nentries == 0) continue;
6645 
6646  CopyAddresses(tree);
6647 
6648  CopyEntries(tree,-1,options);
6649 
6650  tree->ResetBranchAddresses();
6651  }
6652  fAutoSave = storeAutoSave;
6653  return GetEntries();
6654 }
6655 
6656 ////////////////////////////////////////////////////////////////////////////////
6657 /// Merge the trees in the TList into this tree.
6658 /// If info->fIsFirst is true, first we clone this TTree info the directory
6659 /// info->fOutputDirectory and then overlay the new TTree information onto
6660 /// this TTree object (so that this TTree object is now the appropriate to
6661 /// use for further merging).
6662 ///
6663 /// Returns the total number of entries in the merged tree.
6666 {
6667  const char *options = info ? info->fOptions.Data() : "";
6668  if (info && info->fIsFirst && info->fOutputDirectory && info->fOutputDirectory->GetFile() != GetCurrentFile()) {
6670  TIOFeatures saved_features = fIOFeatures;
6671  if (info->fIOFeatures) {
6672  fIOFeatures = *(info->fIOFeatures);
6673  }
6674  TTree *newtree = CloneTree(-1, options);
6675  fIOFeatures = saved_features;
6676  if (newtree) {
6677  newtree->Write();
6678  delete newtree;
6679  }
6680  // Make sure things are really written out to disk before attempting any reading.
6681  info->fOutputDirectory->GetFile()->Flush();
6682  info->fOutputDirectory->ReadTObject(this,this->GetName());
6683  }
6684  if (!li) return 0;
6685  Long64_t storeAutoSave = fAutoSave;
6686  // Disable the autosave as the TFileMerge keeps a list of key and deleting the underlying
6687  // key would invalidate its iteration (or require costly measure to not use the deleted keys).
6688  // Also since this is part of a merging operation, the output file is not as precious as in
6689  // the general case since the input file should still be around.
6690  fAutoSave = 0;
6691  TIter next(li);
6692  TTree *tree;
6693  while ((tree = (TTree*)next())) {
6694  if (tree==this) continue;
6695  if (!tree->InheritsFrom(TTree::Class())) {
6696  Error("Add","Attempt to add object of class: %s to a %s", tree->ClassName(), ClassName());
6697  fAutoSave = storeAutoSave;
6698  return -1;
6699  }
6700  // Copy MakeClass status.
6701  tree->SetMakeClass(fMakeClass);
6702 
6703  // Copy branch addresses.
6704  CopyAddresses(tree);
6705 
6706  CopyEntries(tree,-1,options);
6707 
6708  tree->ResetBranchAddresses();
6709  }
6710  fAutoSave = storeAutoSave;
6711  return GetEntries();
6712 }
6713 
6714 ////////////////////////////////////////////////////////////////////////////////
6715 /// Move a cache from a file to the current file in dir.
6716 /// if src is null no operation is done, if dir is null or there is no
6717 /// current file the cache is deleted.
6719 void TTree::MoveReadCache(TFile *src, TDirectory *dir)
6720 {
6721  if (!src) return;
6722  TFile *dst = (dir && dir != gROOT) ? dir->GetFile() : 0;
6723  if (src == dst) return;
6724 
6725  TTreeCache *pf = GetReadCache(src);
6726  if (dst) {
6727  src->SetCacheRead(0,this);
6728  dst->SetCacheRead(pf, this);
6729  } else {
6730  if (pf) {
6731  pf->WaitFinishPrefetch();
6732  }
6733  src->SetCacheRead(0,this);
6734  delete pf;
6735  }
6736 }
6737 
6738 ////////////////////////////////////////////////////////////////////////////////
6739 /// Function called when loading a new class library.
6742 {
6743  TIter next(GetListOfLeaves());
6744  TLeaf* leaf = 0;
6745  while ((leaf = (TLeaf*) next())) {
6746  leaf->Notify();
6747  leaf->GetBranch()->Notify();
6748  }
6749  return kTRUE;
6750 }
6751 
6752 ////////////////////////////////////////////////////////////////////////////////
6753 /// This function may be called after having filled some entries in a Tree.
6754 /// Using the information in the existing branch buffers, it will reassign
6755 /// new branch buffer sizes to optimize time and memory.
6756 ///
6757 /// The function computes the best values for branch buffer sizes such that
6758 /// the total buffer sizes is less than maxMemory and nearby entries written
6759 /// at the same time.
6760 /// In case the branch compression factor for the data written so far is less
6761 /// than compMin, the compression is disabled.
6762 ///
6763 /// if option ="d" an analysis report is printed.
6765 void TTree::OptimizeBaskets(ULong64_t maxMemory, Float_t minComp, Option_t *option)
6766 {
6767  //Flush existing baskets if the file is writable
6768  if (this->GetDirectory()->IsWritable()) this->FlushBasketsImpl();
6769 
6770  TString opt( option );
6771  opt.ToLower();
6772  Bool_t pDebug = opt.Contains("d");
6773  TObjArray *leaves = this->GetListOfLeaves();
6774  Int_t nleaves = leaves->GetEntries();
6775  Double_t treeSize = (Double_t)this->GetTotBytes();
6776 
6777  if (nleaves == 0 || treeSize == 0) {
6778  // We're being called too early, we really have nothing to do ...
6779  return;
6780  }
6781  Double_t aveSize = treeSize/nleaves;
6782  UInt_t bmin = 512;
6783  UInt_t bmax = 256000;
6784  Double_t memFactor = 1;
6785  Int_t i, oldMemsize,newMemsize,oldBaskets,newBaskets;
6786  i = oldMemsize = newMemsize = oldBaskets = newBaskets = 0;
6787 
6788  //we make two passes
6789  //one pass to compute the relative branch buffer sizes
6790  //a second pass to compute the absolute values
6791  for (Int_t pass =0;pass<2;pass++) {
6792  oldMemsize = 0; //to count size of baskets in memory with old buffer size
6793  newMemsize = 0; //to count size of baskets in memory with new buffer size
6794  oldBaskets = 0; //to count number of baskets with old buffer size
6795  newBaskets = 0; //to count number of baskets with new buffer size
6796  for (i=0;i<nleaves;i++) {
6797  TLeaf *leaf = (TLeaf*)leaves->At(i);
6798  TBranch *branch = leaf->GetBranch();
6799  Double_t totBytes = (Double_t)branch->GetTotBytes();
6800  Double_t idealFactor = totBytes/aveSize;
6801  UInt_t sizeOfOneEntry;
6802  if (branch->GetEntries() == 0) {
6803  // There is no data, so let's make a guess ...
6804  sizeOfOneEntry = aveSize;
6805  } else {
6806  sizeOfOneEntry = 1+(UInt_t)(totBytes / (Double_t)branch->GetEntries());
6807  }
6808  Int_t oldBsize = branch->GetBasketSize();
6809  oldMemsize += oldBsize;
6810  oldBaskets += 1+Int_t(totBytes/oldBsize);
6811  Int_t nb = branch->GetListOfBranches()->GetEntries();
6812  if (nb > 0) {
6813  newBaskets += 1+Int_t(totBytes/oldBsize);
6814  continue;
6815  }
6816  Double_t bsize = oldBsize*idealFactor*memFactor; //bsize can be very large !
6817  if (bsize < 0) bsize = bmax;
6818  if (bsize > bmax) bsize = bmax;
6819  UInt_t newBsize = UInt_t(bsize);
6820  if (pass) { // only on the second pass so that it doesn't interfere with scaling
6821  // If there is an entry offset, it will be stored in the same buffer as the object data; hence,
6822  // we must bump up the size of the branch to account for this extra footprint.
6823  // If fAutoFlush is not set yet, let's assume that it is 'in the process of being set' to
6824  // the value of GetEntries().
6825  Long64_t clusterSize = (fAutoFlush > 0) ? fAutoFlush : branch->GetEntries();
6826  if (branch->GetEntryOffsetLen()) {
6827  newBsize = newBsize + (clusterSize * sizeof(Int_t) * 2);
6828  }
6829  // We used ATLAS fully-split xAOD for testing, which is a rather unbalanced TTree, 10K branches,
6830  // with 8K having baskets smaller than 512 bytes. To achieve good I/O performance ATLAS uses auto-flush 100,
6831  // resulting in the smallest baskets being ~300-400 bytes, so this change increases their memory by about 8k*150B =~ 1MB,
6832  // at the same time it significantly reduces the number of total baskets because it ensures that all 100 entries can be
6833  // stored in a single basket (the old optimization tended to make baskets too small). In a toy example with fixed sized
6834  // structures we found a factor of 2 fewer baskets needed in the new scheme.
6835  // rounds up, increases basket size to ensure all entries fit into single basket as intended
6836  newBsize = newBsize - newBsize%512 + 512;
6837  }
6838  if (newBsize < sizeOfOneEntry) newBsize = sizeOfOneEntry;
6839  if (newBsize < bmin) newBsize = bmin;
6840  if (newBsize > 10000000) newBsize = bmax;
6841  if (pass) {
6842  if (pDebug) Info("OptimizeBaskets", "Changing buffer size from %6d to %6d bytes for %s\n",oldBsize,newBsize,branch->GetName());
6843  branch->SetBasketSize(newBsize);
6844  }
6845  newMemsize += newBsize;
6846  // For this number to be somewhat accurate when newBsize is 'low'
6847  // we do not include any space for meta data in the requested size (newBsize) even-though SetBasketSize will
6848  // not let it be lower than 100+TBranch::fEntryOffsetLen.
6849  newBaskets += 1+Int_t(totBytes/newBsize);
6850  if (pass == 0) continue;
6851  //Reset the compression level in case the compression factor is small
6852  Double_t comp = 1;
6853  if (branch->GetZipBytes() > 0) comp = totBytes/Double_t(branch->GetZipBytes());
6854  if (comp > 1 && comp < minComp) {
6855  if (pDebug) Info("OptimizeBaskets", "Disabling compression for branch : %s\n",branch->GetName());
6856  branch->SetCompressionSettings(0);
6857  }
6858  }
6859  // coverity[divide_by_zero] newMemsize can not be zero as there is at least one leaf
6860  memFactor = Double_t(maxMemory)/Double_t(newMemsize);
6861  if (memFactor > 100) memFactor = 100;
6862  Double_t bmin_new = bmin*memFactor;
6863  Double_t bmax_new = bmax*memFactor;
6864  static const UInt_t hardmax = 1*1024*1024*1024; // Really, really never give more than 1Gb to a single buffer.
6865 
6866  // Really, really never go lower than 8 bytes (we use this number
6867  // so that the calculation of the number of basket is consistent
6868  // but in fact SetBasketSize will not let the size go below
6869  // TBranch::fEntryOffsetLen + (100 + strlen(branch->GetName())
6870  // (The 2nd part being a slight over estimate of the key length.
6871  static const UInt_t hardmin = 8;
6872  bmin = (bmin_new > hardmax) ? hardmax : ( bmin_new < hardmin ? hardmin : (UInt_t)bmin_new );
6873  bmax = (bmax_new > hardmax) ? bmin : (UInt_t)bmax_new;
6874  }
6875  if (pDebug) {
6876  Info("OptimizeBaskets", "oldMemsize = %d, newMemsize = %d\n",oldMemsize, newMemsize);
6877  Info("OptimizeBaskets", "oldBaskets = %d, newBaskets = %d\n",oldBaskets, newBaskets);
6878  }
6879 }
6880 
6881 ////////////////////////////////////////////////////////////////////////////////
6882 /// Interface to the Principal Components Analysis class.
6883 ///
6884 /// Create an instance of TPrincipal
6885 ///
6886 /// Fill it with the selected variables
6887 ///
6888 /// - if option "n" is specified, the TPrincipal object is filled with
6889 /// normalized variables.
6890 /// - If option "p" is specified, compute the principal components
6891 /// - If option "p" and "d" print results of analysis
6892 /// - If option "p" and "h" generate standard histograms
6893 /// - If option "p" and "c" generate code of conversion functions
6894 /// - return a pointer to the TPrincipal object. It is the user responsibility
6895 /// - to delete this object.
6896 /// - The option default value is "np"
6897 ///
6898 /// see TTree::Draw for explanation of the other parameters.
6899 ///
6900 /// The created object is named "principal" and a reference to it
6901 /// is added to the list of specials Root objects.
6902 /// you can retrieve a pointer to the created object via:
6903 /// ~~~ {.cpp}
6904 /// TPrincipal *principal =
6905 /// (TPrincipal*)gROOT->GetListOfSpecials()->FindObject("principal");
6906 /// ~~~
6908 TPrincipal* TTree::Principal(const char* varexp, const char* selection, Option_t* option, Long64_t nentries, Long64_t firstentry)
6909 {
6910  GetPlayer();
6911  if (fPlayer) {
6912  return fPlayer->Principal(varexp, selection, option, nentries, firstentry);
6913  }
6914  return 0;
6915 }
6916 
6917 ////////////////////////////////////////////////////////////////////////////////
6918 /// Print a summary of the tree contents.
6919 ///
6920 /// - If option contains "all" friend trees are also printed.
6921 /// - If option contains "toponly" only the top level branches are printed.
6922 /// - If option contains "clusters" information about the cluster of baskets is printed.
6923 ///
6924 /// Wildcarding can be used to print only a subset of the branches, e.g.,
6925 /// `T.Print("Elec*")` will print all branches with name starting with "Elec".
6927 void TTree::Print(Option_t* option) const
6928 {
6929  // We already have been visited while recursively looking
6930  // through the friends tree, let's return.
6931  if (kPrint & fFriendLockStatus) {
6932  return;
6933  }
6934  Int_t s = 0;
6935  Int_t skey = 0;
6936  if (fDirectory) {
6937  TKey* key = fDirectory->GetKey(GetName());
6938  if (key) {
6939  skey = key->GetKeylen();
6940  s = key->GetNbytes();
6941  }
6942  }
6943  Long64_t total = skey;
6944  Long64_t zipBytes = GetZipBytes();
6945  if (zipBytes > 0) {
6946  total += GetTotBytes();
6947  }
6948  TBufferFile b(TBuffer::kWrite, 10000);
6949  TTree::Class()->WriteBuffer(b, (TTree*) this);
6950  total += b.Length();
6951  Long64_t file = zipBytes + s;
6952  Float_t cx = 1;
6953  if (zipBytes) {
6954  cx = (GetTotBytes() + 0.00001) / zipBytes;
6955  }
6956  Printf("******************************************************************************");
6957  Printf("*Tree :%-10s: %-54s *", GetName(), GetTitle());
6958  Printf("*Entries : %8lld : Total = %15lld bytes File Size = %10lld *", fEntries, total, file);
6959  Printf("* : : Tree compression factor = %6.2f *", cx);
6960  Printf("******************************************************************************");
6961 
6962  if (strncmp(option,"clusters",strlen("clusters"))==0) {
6963  Printf("%-16s %-16s %-16s %5s",
6964  "Cluster Range #", "Entry Start", "Last Entry", "Size");
6965  Int_t index= 0;
6966  Long64_t clusterRangeStart = 0;
6967  if (fNClusterRange) {
6968  for( ; index < fNClusterRange; ++index) {
6969  Printf("%-16d %-16lld %-16lld %5lld",
6970  index, clusterRangeStart, fClusterRangeEnd[index], fClusterSize[index]);
6971  clusterRangeStart = fClusterRangeEnd[index] + 1;
6972  }
6973  }
6974  Printf("%-16d %-16lld %-16lld %5lld",
6975  index, clusterRangeStart, fEntries - 1, fAutoFlush);
6976  return;
6977  }
6978 
6979  Int_t nl = const_cast<TTree*>(this)->GetListOfLeaves()->GetEntries();
6980  Int_t l;
6981  TBranch* br = 0;
6982  TLeaf* leaf = 0;
6983  if (strstr(option, "toponly")) {
6984  Long64_t *count = new Long64_t[nl];
6985  Int_t keep =0;
6986  for (l=0;l<nl;l++) {
6987  leaf = (TLeaf *)const_cast<TTree*>(this)->GetListOfLeaves()->At(l);
6988  br = leaf->GetBranch();
6989  if (strchr(br->GetName(),'.')) {
6990  count[l] = -1;
6991  count[keep] += br->GetZipBytes();
6992  } else {
6993  keep = l;
6994  count[keep] = br->GetZipBytes();
6995  }
6996  }
6997  for (l=0;l<nl;l++) {
6998  if (count[l] < 0) continue;
6999  leaf = (TLeaf *)const_cast<TTree*>(this)->GetListOfLeaves()->At(l);
7000  br = leaf->GetBranch();
7001  Printf("branch: %-20s %9lld\n",br->GetName(),count[l]);
7002  }
7003  delete [] count;
7004  } else {
7005  TString reg = "*";
7006  if (strlen(option) && strchr(option,'*')) reg = option;
7007  TRegexp re(reg,kTRUE);
7008  TIter next(const_cast<TTree*>(this)->GetListOfBranches());
7010  while ((br= (TBranch*)next())) {
7011  TString st = br->GetName();
7012  st.ReplaceAll("/","_");
7013  if (st.Index(re) == kNPOS) continue;
7014  br->Print(option);
7015  }
7016  }
7017 
7018  //print TRefTable (if one)
7019  if (fBranchRef) fBranchRef->Print(option);
7020 
7021  //print friends if option "all"
7022  if (!fFriends || !strstr(option,"all")) return;
7023  TIter nextf(fFriends);
7024  TFriendLock lock(const_cast<TTree*>(this),kPrint);
7025  TFriendElement *fr;
7026  while ((fr = (TFriendElement*)nextf())) {
7027  TTree * t = fr->GetTree();
7028  if (t) t->Print(option);
7029  }
7030 }
7031 
7032 ////////////////////////////////////////////////////////////////////////////////
7033 /// Print statistics about the TreeCache for this tree.
7034 /// Like:
7035 /// ~~~ {.cpp}
7036 /// ******TreeCache statistics for file: cms2.root ******
7037 /// Reading 73921562 bytes in 716 transactions
7038 /// Average transaction = 103.242405 Kbytes
7039 /// Number of blocks in current cache: 202, total size : 6001193
7040 /// ~~~
7041 /// if option = "a" the list of blocks in the cache is printed
7043 void TTree::PrintCacheStats(Option_t* option) const
7044 {
7045  TFile *f = GetCurrentFile();
7046  if (!f) return;
7047  TTreeCache *tc = GetReadCache(f);
7048  if (tc) tc->Print(option);
7049 }
7050 
7051 ////////////////////////////////////////////////////////////////////////////////
7052 /// Process this tree executing the TSelector code in the specified filename.
7053 /// The return value is -1 in case of error and TSelector::GetStatus() in
7054 /// in case of success.
7055 ///
7056 /// The code in filename is loaded (interpreted or compiled, see below),
7057 /// filename must contain a valid class implementation derived from TSelector,
7058 /// where TSelector has the following member functions:
7059 ///
7060 /// - `Begin()`: called every time a loop on the tree starts,
7061 /// a convenient place to create your histograms.
7062 /// - `SlaveBegin()`: called after Begin(), when on PROOF called only on the
7063 /// slave servers.
7064 /// - `Process()`: called for each event, in this function you decide what
7065 /// to read and fill your histograms.
7066 /// - `SlaveTerminate`: called at the end of the loop on the tree, when on PROOF
7067 /// called only on the slave servers.
7068 /// - `Terminate()`: called at the end of the loop on the tree,
7069 /// a convenient place to draw/fit your histograms.
7070 ///
7071 /// If filename is of the form file.C, the file will be interpreted.
7072 ///
7073 /// If filename is of the form file.C++, the file file.C will be compiled
7074 /// and dynamically loaded.
7075 ///
7076 /// If filename is of the form file.C+, the file file.C will be compiled
7077 /// and dynamically loaded. At next call, if file.C is older than file.o
7078 /// and file.so, the file.C is not compiled, only file.so is loaded.
7079 ///
7080 /// ## NOTE1
7081 ///
7082 /// It may be more interesting to invoke directly the other Process function
7083 /// accepting a TSelector* as argument.eg
7084 /// ~~~ {.cpp}
7085 /// MySelector *selector = (MySelector*)TSelector::GetSelector(filename);
7086 /// selector->CallSomeFunction(..);
7087 /// mytree.Process(selector,..);
7088 /// ~~~
7089 /// ## NOTE2
7090 //
7091 /// One should not call this function twice with the same selector file
7092 /// in the same script. If this is required, proceed as indicated in NOTE1,
7093 /// by getting a pointer to the corresponding TSelector,eg
7094 ///
7095 /// ### workaround 1
7096 /// ~~~ {.cpp}
7097 /// void stubs1() {
7098 /// TSelector *selector = TSelector::GetSelector("h1test.C");
7099 /// TFile *f1 = new TFile("stubs_nood_le1.root");
7100 /// TTree *h1 = (TTree*)f1->Get("h1");
7101 /// h1->Process(selector);
7102 /// TFile *f2 = new TFile("stubs_nood_le1_coarse.root");
7103 /// TTree *h2 = (TTree*)f2->Get("h1");
7104 /// h2->Process(selector);
7105 /// }
7106 /// ~~~
7107 /// or use ACLIC to compile the selector
7108 ///
7109 /// ### workaround 2
7110 /// ~~~ {.cpp}
7111 /// void stubs2() {
7112 /// TFile *f1 = new TFile("stubs_nood_le1.root");
7113 /// TTree *h1 = (TTree*)f1->Get("h1");
7114 /// h1->Process("h1test.C+");
7115 /// TFile *f2 = new TFile("stubs_nood_le1_coarse.root");
7116 /// TTree *h2 = (TTree*)f2->Get("h1");
7117 /// h2->Process("h1test.C+");
7118 /// }
7119 /// ~~~
7121 Long64_t TTree::Process(const char* filename, Option_t* option, Long64_t nentries, Long64_t firstentry)
7122 {
7123  GetPlayer();
7124  if (fPlayer) {
7125  return fPlayer->Process(filename, option, nentries, firstentry);
7126  }
7127  return -1;
7128 }
7129 
7130 ////////////////////////////////////////////////////////////////////////////////
7131 /// Process this tree executing the code in the specified selector.
7132 /// The return value is -1 in case of error and TSelector::GetStatus() in
7133 /// in case of success.
7134 ///
7135 /// The TSelector class has the following member functions:
7136 ///
7137 /// - `Begin()`: called every time a loop on the tree starts,
7138 /// a convenient place to create your histograms.
7139 /// - `SlaveBegin()`: called after Begin(), when on PROOF called only on the
7140 /// slave servers.
7141 /// - `Process()`: called for each event, in this function you decide what
7142 /// to read and fill your histograms.
7143 /// - `SlaveTerminate`: called at the end of the loop on the tree, when on PROOF
7144 /// called only on the slave servers.
7145 /// - `Terminate()`: called at the end of the loop on the tree,
7146 /// a convenient place to draw/fit your histograms.
7147 ///
7148 /// If the Tree (Chain) has an associated EventList, the loop is on the nentries
7149 /// of the EventList, starting at firstentry, otherwise the loop is on the
7150 /// specified Tree entries.
7152 Long64_t TTree::Process(TSelector* selector, Option_t* option, Long64_t nentries, Long64_t firstentry)
7153 {
7154  GetPlayer();
7155  if (fPlayer) {
7156  return fPlayer->Process(selector, option, nentries, firstentry);
7157  }
7158  return -1;
7159 }
7160 
7161 ////////////////////////////////////////////////////////////////////////////////
7162 /// Make a projection of a tree using selections.
7163 ///
7164 /// Depending on the value of varexp (described in Draw) a 1-D, 2-D, etc.,
7165 /// projection of the tree will be filled in histogram hname.
7166 /// Note that the dimension of hname must match with the dimension of varexp.
7167 ///
7169 Long64_t TTree::Project(const char* hname, const char* varexp, const char* selection, Option_t* option, Long64_t nentries, Long64_t firstentry)
7170 {
7171  TString var;
7172  var.Form("%s>>%s", varexp, hname);
7173  TString opt("goff");
7174  if (option) {
7175  opt.Form("%sgoff", option);
7176  }
7177  Long64_t nsel = Draw(var, selection, opt, nentries, firstentry);
7178  return nsel;
7179 }
7180 
7181 ////////////////////////////////////////////////////////////////////////////////
7182 /// Loop over entries and return a TSQLResult object containing entries following selection.
7184 TSQLResult* TTree::Query(const char* varexp, const char* selection, Option_t* option, Long64_t nentries, Long64_t firstentry)
7185 {
7186  GetPlayer();
7187  if (fPlayer) {
7188  return fPlayer->Query(varexp, selection, option, nentries, firstentry);
7189  }
7190  return 0;
7191 }
7192 
7193 ////////////////////////////////////////////////////////////////////////////////
7194 /// Create or simply read branches from filename.
7195 ///
7196 /// if branchDescriptor = "" (default), it is assumed that the Tree descriptor
7197 /// is given in the first line of the file with a syntax like
7198 /// ~~~ {.cpp}
7199 /// A/D:Table[2]/F:Ntracks/I:astring/C
7200 /// ~~~
7201 /// otherwise branchDescriptor must be specified with the above syntax.
7202 ///
7203 /// - If the type of the first variable is not specified, it is assumed to be "/F"
7204 /// - If the type of any other variable is not specified, the type of the previous
7205 /// variable is assumed. eg
7206 /// - `x:y:z` (all variables are assumed of type "F"
7207 /// - `x/D:y:z` (all variables are of type "D"
7208 /// - `x:y/D:z` (x is type "F", y and z of type "D"
7209 ///
7210 /// delimiter allows for the use of another delimiter besides whitespace.
7211 /// This provides support for direct import of common data file formats
7212 /// like csv. If delimiter != ' ' and branchDescriptor == "", then the
7213 /// branch description is taken from the first line in the file, but
7214 /// delimiter is used for the branch names tokenization rather than ':'.
7215 /// Note however that if the values in the first line do not use the
7216 /// /[type] syntax, all variables are assumed to be of type "F".
7217 /// If the filename ends with extensions .csv or .CSV and a delimiter is
7218 /// not specified (besides ' '), the delimiter is automatically set to ','.
7219 ///
7220 /// Lines in the input file starting with "#" are ignored. Leading whitespace
7221 /// for each column data is skipped. Empty lines are skipped.
7222 ///
7223 /// A TBranch object is created for each variable in the expression.
7224 /// The total number of rows read from the file is returned.
7225 ///
7226 /// ## FILLING a TTree WITH MULTIPLE INPUT TEXT FILES
7227 ///
7228 /// To fill a TTree with multiple input text files, proceed as indicated above
7229 /// for the first input file and omit the second argument for subsequent calls
7230 /// ~~~ {.cpp}
7231 /// T.ReadFile("file1.dat","branch descriptor");
7232 /// T.ReadFile("file2.dat");
7233 /// ~~~
7235 Long64_t TTree::ReadFile(const char* filename, const char* branchDescriptor, char delimiter)
7236 {
7237  std::ifstream in;
7238  in.open(filename);
7239  if (!in.good()) {
7240  Error("ReadFile","Cannot open file: %s",filename);
7241  return 0;
7242  }
7243  const char* ext = strrchr(filename, '.');
7244  if(ext != NULL && ((strcmp(ext, ".csv") == 0) || (strcmp(ext, ".CSV") == 0)) && delimiter == ' ') {
7245  delimiter = ',';
7246  }
7247  return ReadStream(in, branchDescriptor, delimiter);
7248 }
7249 
7250 ////////////////////////////////////////////////////////////////////////////////
7251 /// Determine which newline this file is using.
7252 /// Return '\\r' for Windows '\\r\\n' as that already terminates.
7254 char TTree::GetNewlineValue(std::istream &inputStream)
7255 {
7256  Long_t inPos = inputStream.tellg();
7257  char newline = '\n';
7258  while(1) {
7259  char c = 0;
7260  inputStream.get(c);
7261  if(!inputStream.good()) {
7262  Error("ReadStream","Error reading stream: no newline found.");
7263  return 0;
7264  }
7265  if(c == newline) break;
7266  if(c == '\r') {
7267  newline = '\r';
7268  break;
7269  }
7270  }
7271  inputStream.clear();
7272  inputStream.seekg(inPos);
7273  return newline;
7274 }
7275 
7276 ////////////////////////////////////////////////////////////////////////////////
7277 /// Create or simply read branches from an input stream.
7278 ///
7279 /// See reference information for TTree::ReadFile
7281 Long64_t TTree::ReadStream(std::istream& inputStream, const char *branchDescriptor, char delimiter)
7282 {
7283  char newline = 0;
7284  std::stringstream ss;
7285  std::istream *inTemp;
7286  Long_t inPos = inputStream.tellg();
7287  if (!inputStream.good()) {
7288  Error("ReadStream","Error reading stream");
7289  return 0;
7290  }
7291  if (inPos == -1) {
7292  ss << std::cin.rdbuf();
7293  newline = GetNewlineValue(ss);
7294  inTemp = &ss;
7295  } else {
7296  newline = GetNewlineValue(inputStream);
7297  inTemp = &inputStream;
7298  }
7299  std::istream& in = *inTemp;
7300  Long64_t nlines = 0;
7301 
7302  TBranch *branch = 0;
7303  Int_t nbranches = fBranches.GetEntries();
7304  if (nbranches == 0) {
7305  char *bdname = new char[4000];
7306  char *bd = new char[100000];
7307  Int_t nch = 0;
7308  if (branchDescriptor) nch = strlen(branchDescriptor);
7309  // branch Descriptor is null, read its definition from the first line in the file
7310  if (!nch) {
7311  do {
7312  in.getline(bd, 100000, newline);
7313  if (!in.good()) {
7314  delete [] bdname;
7315  delete [] bd;
7316  Error("ReadStream","Error reading stream");
7317  return 0;
7318  }
7319  char *cursor = bd;
7320  while( isspace(*cursor) && *cursor != '\n' && *cursor != '\0') {
7321  ++cursor;
7322  }
7323  if (*cursor != '#' && *cursor != '\n' && *cursor != '\0') {
7324  break;
7325  }
7326  } while (true);
7327  ++nlines;
7328  nch = strlen(bd);
7329  } else {
7330  strlcpy(bd,branchDescriptor,100000);
7331  }
7332 
7333  //parse the branch descriptor and create a branch for each element
7334  //separated by ":"
7335  void *address = &bd[90000];
7336  char *bdcur = bd;
7337  TString desc="", olddesc="F";
7338  char bdelim = ':';
7339  if(delimiter != ' ') {
7340  bdelim = delimiter;
7341  if (strchr(bdcur,bdelim)==0 && strchr(bdcur,':') != 0) {
7342  // revert to the default
7343  bdelim = ':';
7344  }
7345  }
7346  while (bdcur) {
7347  char *colon = strchr(bdcur,bdelim);
7348  if (colon) *colon = 0;
7349  strlcpy(bdname,bdcur,4000);
7350  char *slash = strchr(bdname,'/');
7351  if (slash) {
7352  *slash = 0;
7353  desc = bdcur;
7354  olddesc = slash+1;
7355  } else {
7356  desc.Form("%s/%s",bdname,olddesc.Data());
7357  }
7358  char *bracket = strchr(bdname,'[');
7359  if (bracket) {
7360  *bracket = 0;
7361  }
7362  branch = new TBranch(this,bdname,address,desc.Data(),32000);
7363  if (branch->IsZombie()) {
7364  delete branch;
7365  Warning("ReadStream","Illegal branch definition: %s",bdcur);
7366  } else {
7367  fBranches.Add(branch);
7368  branch->SetAddress(0);
7369  }
7370  if (!colon)break;
7371  bdcur = colon+1;
7372  }
7373  delete [] bdname;
7374  delete [] bd;
7375  }
7376 
7377  nbranches = fBranches.GetEntries();
7378 
7379  if (gDebug > 1) {
7380  Info("ReadStream", "Will use branches:");
7381  for (int i = 0 ; i < nbranches; ++i) {
7382  TBranch* br = (TBranch*) fBranches.At(i);
7383  Info("ReadStream", " %s: %s [%s]", br->GetName(),
7384  br->GetTitle(), br->GetListOfLeaves()->At(0)->IsA()->GetName());
7385  }
7386  if (gDebug > 3) {
7387  Info("ReadStream", "Dumping read tokens, format:");
7388  Info("ReadStream", "LLLLL:BBB:gfbe:GFBE:T");
7389  Info("ReadStream", " L: line number");
7390  Info("ReadStream", " B: branch number");
7391  Info("ReadStream", " gfbe: good / fail / bad / eof of token");
7392  Info("ReadStream", " GFBE: good / fail / bad / eof of file");
7393  Info("ReadStream", " T: Token being read");
7394  }
7395  }
7396 
7397  //loop on all lines in the file
7398  Long64_t nGoodLines = 0;
7399  std::string line;
7400  const char sDelimBuf[2] = { delimiter, 0 };
7401  const char* sDelim = sDelimBuf;
7402  if (delimiter == ' ') {
7403  // ' ' really means whitespace
7404  sDelim = "[ \t]";
7405  }
7406  while(in.good()) {
7407  if (newline == '\r' && in.peek() == '\n') {
7408  // Windows, skip '\n':
7409  in.get();
7410  }
7411  std::getline(in, line, newline);
7412  ++nlines;
7413 
7414  TString sLine(line);
7415  sLine = sLine.Strip(TString::kLeading); // skip leading whitespace
7416  if (sLine.IsNull()) {
7417  if (gDebug > 2) {
7418  Info("ReadStream", "Skipping empty line number %lld", nlines);
7419  }
7420  continue; // silently skip empty lines
7421  }
7422  if (sLine[0] == '#') {
7423  if (gDebug > 2) {
7424  Info("ReadStream", "Skipping comment line number %lld: '%s'",
7425  nlines, line.c_str());
7426  }
7427  continue;
7428  }
7429  if (gDebug > 2) {
7430  Info("ReadStream", "Parsing line number %lld: '%s'",
7431  nlines, line.c_str());
7432  }
7433 
7434  // Loop on branches and read the branch values into their buffer
7435  branch = 0;
7436  TString tok; // one column's data
7437  TString leafData; // leaf data, possibly multiple tokens for e.g. /I[2]
7438  std::stringstream sToken; // string stream feeding leafData into leaves
7439  Ssiz_t pos = 0;
7440  Int_t iBranch = 0;
7441  Bool_t goodLine = kTRUE; // whether the row can be filled into the tree
7442  Int_t remainingLeafLen = 0; // remaining columns for the current leaf
7443  while (goodLine && iBranch < nbranches
7444  && sLine.Tokenize(tok, pos, sDelim)) {
7445  tok = tok.Strip(TString::kLeading); // skip leading whitespace
7446  if (tok.IsNull() && delimiter == ' ') {
7447  // 1 2 should not be interpreted as 1,,,2 but 1, 2.
7448  // Thus continue until we have a non-empty token.
7449  continue;
7450  }
7451 
7452  if (!remainingLeafLen) {
7453  // next branch!
7454  branch = (TBranch*)fBranches.At(iBranch);
7455  }
7456  TLeaf *leaf = (TLeaf*)branch->GetListOfLeaves()->At(0);
7457  if (!remainingLeafLen) {
7458  remainingLeafLen = leaf->GetLen();
7459  if (leaf->GetMaximum() > 0) {
7460  // This is a dynamic leaf length, i.e. most likely a TLeafC's
7461  // string size. This still translates into one token:
7462  remainingLeafLen = 1;
7463  }
7464 
7465  leafData = tok;
7466  } else {
7467  // append token to laf data:
7468  leafData += " ";
7469  leafData += tok;
7470  }
7471  --remainingLeafLen;
7472  if (remainingLeafLen) {
7473  // need more columns for this branch:
7474  continue;
7475  }
7476  ++iBranch;
7477 
7478  // initialize stringstream with token
7479  sToken.clear();
7480  sToken.seekp(0, std::ios_base::beg);
7481  sToken.str(leafData.Data());
7482  sToken.seekg(0, std::ios_base::beg);
7483  leaf->ReadValue(sToken, 0 /* 0 = "all" */);
7484  if (gDebug > 3) {
7485  Info("ReadStream", "%5lld:%3d:%d%d%d%d:%d%d%d%d:%s",
7486  nlines, iBranch,
7487  (int)sToken.good(), (int)sToken.fail(),
7488  (int)sToken.bad(), (int)sToken.eof(),
7489  (int)in.good(), (int)in.fail(),
7490  (int)in.bad(), (int)in.eof(),
7491  sToken.str().c_str());
7492  }
7493 
7494  // Error handling
7495  if (sToken.bad()) {
7496  // How could that happen for a stringstream?
7497  Warning("ReadStream",
7498  "Buffer error while reading data for branch %s on line %lld",
7499  branch->GetName(), nlines);
7500  } else if (!sToken.eof()) {
7501  if (sToken.fail()) {
7502  Warning("ReadStream",
7503  "Couldn't read formatted data in \"%s\" for branch %s on line %lld; ignoring line",
7504  tok.Data(), branch->GetName(), nlines);
7505  goodLine = kFALSE;
7506  } else {
7507  std::string remainder;
7508  std::getline(sToken, remainder, newline);
7509  if (!remainder.empty()) {
7510  Warning("ReadStream",
7511  "Ignoring trailing \"%s\" while reading data for branch %s on line %lld",
7512  remainder.c_str(), branch->GetName(), nlines);
7513  }
7514  }
7515  }
7516  } // tokenizer loop
7517 
7518  if (iBranch < nbranches) {
7519  Warning("ReadStream",
7520  "Read too few columns (%d < %d) in line %lld; ignoring line",
7521  iBranch, nbranches, nlines);
7522  goodLine = kFALSE;
7523  } else if (pos != kNPOS) {
7524  sLine = sLine.Strip(TString::kTrailing);
7525  if (pos < sLine.Length()) {
7526  Warning("ReadStream",
7527  "Ignoring trailing \"%s\" while reading line %lld",
7528  sLine.Data() + pos - 1 /* also print delimiter */,
7529  nlines);
7530  }
7531  }
7532 
7533  //we are now ready to fill the tree
7534  if (goodLine) {
7535  Fill();
7536  ++nGoodLines;
7537  }
7538  }
7539 
7540  return nGoodLines;
7541 }
7542 
7543 ////////////////////////////////////////////////////////////////////////////////
7544 /// Make sure that obj (which is being deleted or will soon be) is no
7545 /// longer referenced by this TTree.
7548 {
7549  if (obj == fEventList) {
7550  fEventList = 0;
7551  }
7552  if (obj == fEntryList) {
7553  fEntryList = 0;
7554  }
7555  if (fUserInfo) {
7556  fUserInfo->RecursiveRemove(obj);
7557  }
7558  if (fPlayer == obj) {
7559  fPlayer = 0;
7560  }
7561  if (fTreeIndex == obj) {
7562  fTreeIndex = 0;
7563  }
7564  if (fAliases) {
7565  fAliases->RecursiveRemove(obj);
7566  }
7567  if (fFriends) {
7568  fFriends->RecursiveRemove(obj);
7569  }
7570 }
7571 
7572 ////////////////////////////////////////////////////////////////////////////////
7573 /// Refresh contents of this tree and its branches from the current status on disk.
7574 ///
7575 /// One can call this function in case the tree file is being
7576 /// updated by another process.
7578 void TTree::Refresh()
7579 {
7580  if (!fDirectory->GetFile()) {
7581  return;
7582  }
7583  fDirectory->ReadKeys();
7584  fDirectory->Remove(this);
7585  TTree* tree; fDirectory->GetObject(GetName(),tree);
7586  if (!tree) {
7587  return;
7588  }
7589  //copy info from tree header into this Tree
7590  fEntries = 0;
7591  fNClusterRange = 0;
7592  ImportClusterRanges(tree);
7593 
7594  fAutoSave = tree->fAutoSave;
7595  fEntries = tree->fEntries;
7596  fTotBytes = tree->GetTotBytes();
7597  fZipBytes = tree->GetZipBytes();
7598  fSavedBytes = tree->fSavedBytes;
7599  fTotalBuffers = tree->fTotalBuffers.load();
7600 
7601  //loop on all branches and update them
7602  Int_t nleaves = fLeaves.GetEntriesFast();
7603  for (Int_t i = 0; i < nleaves; i++) {
7604  TLeaf* leaf = (TLeaf*) fLeaves.UncheckedAt(i);
7605  TBranch* branch = (TBranch*) leaf->GetBranch();
7606  branch->Refresh(tree->GetBranch(branch->GetName()));
7607  }
7608  fDirectory->Remove(tree);
7609  fDirectory->Append(this);
7610  delete tree;
7611  tree = 0;
7612 }
7613 
7614 ////////////////////////////////////////////////////////////////////////////////
7615 /// Remove a friend from the list of friends.
7617 void TTree::RemoveFriend(TTree* oldFriend)
7618 {
7619  // We already have been visited while recursively looking
7620  // through the friends tree, let return
7622  return;
7623  }
7624  if (!fFriends) {
7625  return;
7626  }
7627  TFriendLock lock(this, kRemoveFriend);
7628  TIter nextf(fFriends);
7629  TFriendElement* fe = 0;
7630  while ((fe = (TFriendElement*) nextf())) {
7631  TTree* friend_t = fe->GetTree();
7632  if (friend_t == oldFriend) {
7633  fFriends->Remove(fe);
7634  delete fe;
7635  fe = 0;
7636  }
7637  }
7638 }
7639 
7640 ////////////////////////////////////////////////////////////////////////////////
7641 /// Reset baskets, buffers and entries count in all branches and leaves.
7643 void TTree::Reset(Option_t* option)
7644 {
7645  fNotify = 0;
7646  fEntries = 0;
7647  fNClusterRange = 0;
7648  fTotBytes = 0;
7649  fZipBytes = 0;
7650  fFlushedBytes = 0;
7651  fSavedBytes = 0;
7652  fTotalBuffers = 0;
7653  fChainOffset = 0;
7654  fReadEntry = -1;
7655 
7656  delete fTreeIndex;
7657  fTreeIndex = 0;
7658 
7660  for (Int_t i = 0; i < nb; ++i) {
7661  TBranch* branch = (TBranch*) fBranches.UncheckedAt(i);
7662  branch->Reset(option);
7663  }
7664 
7665  if (fBranchRef) {
7666  fBranchRef->Reset();
7667  }
7668 }
7669 
7670 ////////////////////////////////////////////////////////////////////////////////
7671 /// Resets the state of this TTree after a merge (keep the customization but
7672 /// forget the data).
7675 {
7676  fEntries = 0;
7677  fNClusterRange = 0;
7678  fTotBytes = 0;
7679  fZipBytes = 0;
7680  fSavedBytes = 0;
7681  fFlushedBytes = 0;
7682  fTotalBuffers = 0;
7683  fChainOffset = 0;
7684  fReadEntry = -1;
7685 
7686  delete fTreeIndex;
7687  fTreeIndex = 0;
7688 
7690  for (Int_t i = 0; i < nb; ++i) {
7691  TBranch* branch = (TBranch*) fBranches.UncheckedAt(i);
7692  branch->ResetAfterMerge(info);
7693  }
7694 
7695  if (fBranchRef) {
7696  fBranchRef->ResetAfterMerge(info);
7697  }
7698 }
7699 
7700 ////////////////////////////////////////////////////////////////////////////////
7701 /// Tell all of our branches to set their addresses to zero.
7702 ///
7703 /// Note: If any of our branches own any objects, they are deleted.
7706 {
7707  if (br && br->GetTree()) {
7708  br->ResetAddress();
7709  }
7710 }
7711 
7712 ////////////////////////////////////////////////////////////////////////////////
7713 /// Tell all of our branches to drop their current objects and allocate new ones.
7716 {
7718  Int_t nbranches = branches->GetEntriesFast();
7719  for (Int_t i = 0; i < nbranches; ++i) {
7720  TBranch* branch = (TBranch*) branches->UncheckedAt(i);
7721  branch->ResetAddress();
7722  }
7723 }
7724 
7725 ////////////////////////////////////////////////////////////////////////////////
7726 /// Loop over tree entries and print entries passing selection.
7727 ///
7728 /// - If varexp is 0 (or "") then print only first 8 columns.
7729 /// - If varexp = "*" print all columns.
7730 ///
7731 /// Otherwise a columns selection can be made using "var1:var2:var3".
7732 /// See TTreePlayer::Scan for more information
7734 Long64_t TTree::Scan(const char* varexp, const char* selection, Option_t* option, Long64_t nentries, Long64_t firstentry)
7735 {
7736  GetPlayer();
7737  if (fPlayer) {
7738  return fPlayer->Scan(varexp, selection, option, nentries, firstentry);
7739  }
7740  return -1;
7741 }
7742 
7743 ////////////////////////////////////////////////////////////////////////////////
7744 /// Set a tree variable alias.
7745 ///
7746 /// Set an alias for an expression/formula based on the tree 'variables'.
7747 ///
7748 /// The content of 'aliasName' can be used in TTreeFormula (i.e. TTree::Draw,
7749 /// TTree::Scan, TTreeViewer) and will be evaluated as the content of
7750 /// 'aliasFormula'.
7751 ///
7752 /// If the content of 'aliasFormula' only contains symbol names, periods and
7753 /// array index specification (for example event.fTracks[3]), then
7754 /// the content of 'aliasName' can be used as the start of symbol.
7755 ///
7756 /// If the alias 'aliasName' already existed, it is replaced by the new
7757 /// value.
7758 ///
7759 /// When being used, the alias can be preceded by an eventual 'Friend Alias'
7760 /// (see TTree::GetFriendAlias)
7761 ///
7762 /// Return true if it was added properly.
7763 ///
7764 /// For example:
7765 /// ~~~ {.cpp}
7766 /// tree->SetAlias("x1","(tdc1[1]-tdc1[0])/49");
7767 /// tree->SetAlias("y1","(tdc1[3]-tdc1[2])/47");
7768 /// tree->SetAlias("x2","(tdc2[1]-tdc2[0])/49");
7769 /// tree->SetAlias("y2","(tdc2[3]-tdc2[2])/47");
7770 /// tree->Draw("y2-y1:x2-x1");
7771 ///
7772 /// tree->SetAlias("theGoodTrack","event.fTracks[3]");
7773 /// tree->Draw("theGoodTrack.fPx"); // same as "event.fTracks[3].fPx"
7774 /// ~~~
7776 Bool_t TTree::SetAlias(const char* aliasName, const char* aliasFormula)
7777 {
7778  if (!aliasName || !aliasFormula) {
7779  return kFALSE;
7780  }
7781  if (!aliasName[0] || !aliasFormula[0]) {
7782  return kFALSE;
7783  }
7784  if (!fAliases) {
7785  fAliases = new TList;
7786  } else {
7787  TNamed* oldHolder = (TNamed*) fAliases->FindObject(aliasName);
7788  if (oldHolder) {
7789  oldHolder->SetTitle(aliasFormula);
7790  return kTRUE;
7791  }
7792  }
7793  TNamed* holder = new TNamed(aliasName, aliasFormula);
7794  fAliases->Add(holder);
7795  return kTRUE;
7796 }
7797 
7798 ////////////////////////////////////////////////////////////////////////////////
7799 /// This function may be called at the start of a program to change
7800 /// the default value for fAutoFlush.
7801 ///
7802 /// ### CASE 1 : autof > 0
7803 ///
7804 /// autof is the number of consecutive entries after which TTree::Fill will
7805 /// flush all branch buffers to disk.
7806 ///
7807 /// ### CASE 2 : autof < 0
7808 ///
7809 /// When filling the Tree the branch buffers will be flushed to disk when
7810 /// more than autof bytes have been written to the file. At the first FlushBaskets
7811 /// TTree::Fill will replace fAutoFlush by the current value of fEntries.
7812 ///
7813 /// Calling this function with autof<0 is interesting when it is hard to estimate
7814 /// the size of one entry. This value is also independent of the Tree.
7815 ///
7816 /// The Tree is initialized with fAutoFlush=-30000000, ie that, by default,
7817 /// the first AutoFlush will be done when 30 MBytes of data are written to the file.
7818 ///
7819 /// ### CASE 3 : autof = 0
7820 ///
7821 /// The AutoFlush mechanism is disabled.
7822 ///
7823 /// Flushing the buffers at regular intervals optimize the location of
7824 /// consecutive entries on the disk by creating clusters of baskets.
7825 ///
7826 /// A cluster of baskets is a set of baskets that contains all
7827 /// the data for a (consecutive) set of entries and that is stored
7828 /// consecutively on the disk. When reading all the branches, this
7829 /// is the minimum set of baskets that the TTreeCache will read.
7831 void TTree::SetAutoFlush(Long64_t autof /* = -30000000 */ )
7832 {
7833  // Implementation note:
7834  //
7835  // A positive value of autoflush determines the size (in number of entries) of
7836  // a cluster of baskets.
7837  //
7838  // If the value of autoflush is changed over time (this happens in
7839  // particular when the TTree results from fast merging many trees),
7840  // we record the values of fAutoFlush in the data members:
7841  // fClusterRangeEnd and fClusterSize.
7842  // In the code we refer to a range of entries where the size of the
7843  // cluster of baskets is the same (i.e the value of AutoFlush was
7844  // constant) is called a ClusterRange.
7845  //
7846  // The 2 arrays (fClusterRangeEnd and fClusterSize) have fNClusterRange
7847  // active (used) values and have fMaxClusterRange allocated entries.
7848  //
7849  // fClusterRangeEnd contains the last entries number of a cluster range.
7850  // In particular this means that the 'next' cluster starts at fClusterRangeEnd[]+1
7851  // fClusterSize contains the size in number of entries of all the cluster
7852  // within the given range.
7853  // The last range (and the only one if fNClusterRange is zero) start at
7854  // fNClusterRange[fNClusterRange-1]+1 and ends at the end of the TTree. The
7855  // size of the cluster in this range is given by the value of fAutoFlush.
7856  //
7857  // For example printing the beginning and end of each the ranges can be done by:
7858  //
7859  // Printf("%-16s %-16s %-16s %5s",
7860  // "Cluster Range #", "Entry Start", "Last Entry", "Size");
7861  // Int_t index= 0;
7862  // Long64_t clusterRangeStart = 0;
7863  // if (fNClusterRange) {
7864  // for( ; index < fNClusterRange; ++index) {
7865  // Printf("%-16d %-16lld %-16lld %5lld",
7866  // index, clusterRangeStart, fClusterRangeEnd[index], fClusterSize[index]);
7867  // clusterRangeStart = fClusterRangeEnd[index] + 1;
7868  // }
7869  // }
7870  // Printf("%-16d %-16lld %-16lld %5lld",
7871  // index, prevEntry, fEntries - 1, fAutoFlush);
7872  //
7873 
7874  // Note: We store the entry number corresponding to the end of the cluster
7875  // rather than its start in order to avoid using the array if the cluster
7876  // size never varies (If there is only one value of AutoFlush for the whole TTree).
7877 
7878  if( fAutoFlush != autof) {
7879  if ((fAutoFlush > 0 || autof > 0) && fFlushedBytes) {
7880  // The mechanism was already enabled, let's record the previous
7881  // cluster if needed.
7882  MarkEventCluster();
7883  }
7884  fAutoFlush = autof;
7885  }
7886 }
7887 
7888 ////////////////////////////////////////////////////////////////////////////////
7889 /// Mark the previous event as being at the end of the event cluster.
7890 ///
7891 /// So, if fEntries is set to 10 (and this is the first cluster) when MarkEventCluster
7892 /// is called, then the first cluster has 9 events.
7894 {
7895  if (!fEntries) return;
7896 
7897  if ( (fNClusterRange+1) > fMaxClusterRange ) {
7898  if (fMaxClusterRange) {
7899  // Resize arrays to hold a larger event cluster.
7900  Int_t newsize = TMath::Max(10,Int_t(2*fMaxClusterRange));
7902  newsize*sizeof(Long64_t),fMaxClusterRange*sizeof(Long64_t));
7904  newsize*sizeof(Long64_t),fMaxClusterRange*sizeof(Long64_t));
7905  fMaxClusterRange = newsize;
7906  } else {
7907  // Cluster ranges have never been initialized; create them now.
7908  fMaxClusterRange = 2;
7911  }
7912  }
7914  // If we are auto-flushing, then the cluster size is the same as the current auto-flush setting.
7915  if (fAutoFlush > 0) {
7916  // Even if the user triggers MarkEventRange prior to fAutoFlush being present, the TClusterIterator
7917  // will appropriately go to the next event range.
7919  // Otherwise, assume there is one cluster per event range (e.g., user is manually controlling the flush).
7920  } else if (fNClusterRange == 0) {
7922  } else {
7924  }
7925  ++fNClusterRange;
7926 }
7927 
7928 ////////////////////////////////////////////////////////////////////////////////
7929 /// This function may be called at the start of a program to change
7930 /// the default value for fAutoSave (and for SetAutoSave) is -300000000, ie 300 MBytes.
7931 /// When filling the Tree the branch buffers as well as the Tree header
7932 /// will be flushed to disk when the watermark is reached.
7933 /// If fAutoSave is positive the watermark is reached when a multiple of fAutoSave
7934 /// entries have been written.
7935 /// If fAutoSave is negative the watermark is reached when -fAutoSave bytes
7936 /// have been written to the file.
7937 /// In case of a program crash, it will be possible to recover the data in the Tree
7938 /// up to the last AutoSave point.
7940 void TTree::SetAutoSave(Long64_t autos)
7941 {
7942  fAutoSave = autos;
7943 }
7944 
7945 ////////////////////////////////////////////////////////////////////////////////
7946 /// Set a branch's basket size.
7947 ///
7948 /// bname is the name of a branch.
7949 ///
7950 /// - if bname="*", apply to all branches.
7951 /// - if bname="xxx*", apply to all branches with name starting with xxx
7952 ///
7953 /// see TRegexp for wildcarding options
7954 /// buffsize = branc basket size
7956 void TTree::SetBasketSize(const char* bname, Int_t buffsize)
7957 {
7958  Int_t nleaves = fLeaves.GetEntriesFast();
7959  TRegexp re(bname, kTRUE);
7960  Int_t nb = 0;
7961  for (Int_t i = 0; i < nleaves; i++) {
7962  TLeaf* leaf = (TLeaf*) fLeaves.UncheckedAt(i);
7963  TBranch* branch = (TBranch*) leaf->GetBranch();
7964  TString s = branch->GetName();
7965  if (strcmp(bname, branch->GetName()) && (s.Index(re) == kNPOS)) {
7966  continue;
7967  }
7968  nb++;
7969  branch->SetBasketSize(buffsize);
7970  }
7971  if (!nb) {
7972  Error("SetBasketSize", "unknown branch -> '%s'", bname);
7973  }
7974 }
7975 
7976 ////////////////////////////////////////////////////////////////////////////////
7977 /// Change branch address, dealing with clone trees properly.
7978 /// See TTree::CheckBranchAddressType for the semantic of the return value.
7979 ///
7980 /// Note: See the comments in TBranchElement::SetAddress() for the
7981 /// meaning of the addr parameter and the object ownership policy.
7983 Int_t TTree::SetBranchAddress(const char* bname, void* addr, TBranch** ptr)
7984 {
7985  TBranch* branch = GetBranch(bname);
7986  if (!branch) {
7987  if (ptr) *ptr = 0;
7988  Error("SetBranchAddress", "unknown branch -> %s", bname);
7989  return kMissingBranch;
7990  }
7991  return SetBranchAddressImp(branch,addr,ptr);
7992 }
7993 
7994 ////////////////////////////////////////////////////////////////////////////////
7995 /// Verify the validity of the type of addr before calling SetBranchAddress.
7996 /// See TTree::CheckBranchAddressType for the semantic of the return value.
7997 ///
7998 /// Note: See the comments in TBranchElement::SetAddress() for the
7999 /// meaning of the addr parameter and the object ownership policy.
8001 Int_t TTree::SetBranchAddress(const char* bname, void* addr, TClass* ptrClass, EDataType datatype, Bool_t isptr)
8002 {
8003  return SetBranchAddress(bname, addr, 0, ptrClass, datatype, isptr);
8004 }
8005 
8006 ////////////////////////////////////////////////////////////////////////////////
8007 /// Verify the validity of the type of addr before calling SetBranchAddress.
8008 /// See TTree::CheckBranchAddressType for the semantic of the return value.
8009 ///
8010 /// Note: See the comments in TBranchElement::SetAddress() for the
8011 /// meaning of the addr parameter and the object ownership policy.
8013 Int_t TTree::SetBranchAddress(const char* bname, void* addr, TBranch** ptr, TClass* ptrClass, EDataType datatype, Bool_t isptr)
8014 {
8015  TBranch* branch = GetBranch(bname);
8016  if (!branch) {
8017  if (ptr) *ptr = 0;
8018  Error("SetBranchAddress", "unknown branch -> %s", bname);
8019  return kMissingBranch;
8020  }
8021 
8022  Int_t res = CheckBranchAddressType(branch, ptrClass, datatype, isptr);
8023  // This will set the value of *ptr to branch.
8024  if (res >= 0) {
8025  // The check succeeded.
8026  SetBranchAddressImp(branch,addr,ptr);
8027  } else {
8028  if (ptr) *ptr = 0;
8029  }
8030  return res;
8031 }
8032 
8033 ////////////////////////////////////////////////////////////////////////////////
8034 /// Change branch address, dealing with clone trees properly.
8035 /// See TTree::CheckBranchAddressType for the semantic of the return value.
8036 ///
8037 /// Note: See the comments in TBranchElement::SetAddress() for the
8038 /// meaning of the addr parameter and the object ownership policy.
8040 Int_t TTree::SetBranchAddressImp(TBranch *branch, void* addr, TBranch** ptr)
8041 {
8042  if (ptr) {
8043  *ptr = branch;
8044  }
8045  if (fClones) {
8046  void* oldAddr = branch->GetAddress();
8047  TIter next(fClones);
8048  TTree* clone = 0;
8049  const char *bname = branch->GetName();
8050  while ((clone = (TTree*) next())) {
8051  TBranch* cloneBr = clone->GetBranch(bname);
8052  if (cloneBr && (cloneBr->GetAddress() == oldAddr)) {
8053  cloneBr->SetAddress(addr);
8054  }
8055  }
8056  }
8057  branch->SetAddress(addr);
8058  return kVoidPtr;
8059 }
8060 
8061 ////////////////////////////////////////////////////////////////////////////////
8062 /// Set branch status to Process or DoNotProcess.
8063 ///
8064 /// When reading a Tree, by default, all branches are read.
8065 /// One can speed up considerably the analysis phase by activating
8066 /// only the branches that hold variables involved in a query.
8067 ///
8068 /// bname is the name of a branch.
8069 ///
8070 /// - if bname="*", apply to all branches.
8071 /// - if bname="xxx*", apply to all branches with name starting with xxx
8072 ///
8073 /// see TRegexp for wildcarding options
8074 ///
8075 /// - status = 1 branch will be processed
8076 /// - = 0 branch will not be processed
8077 ///
8078 /// Example:
8079 ///
8080 /// Assume a tree T with sub-branches a,b,c,d,e,f,g,etc..
8081 /// when doing T.GetEntry(i) all branches are read for entry i.
8082 /// to read only the branches c and e, one can do
8083 /// ~~~ {.cpp}
8084 /// T.SetBranchStatus("*",0); //disable all branches
8085 /// T.SetBranchStatus("c",1);
8086 /// T.setBranchStatus("e",1);
8087 /// T.GetEntry(i);
8088 /// ~~~
8089 /// bname is interpreted as a wildcarded TRegexp (see TRegexp::MakeWildcard).
8090 /// Thus, "a*b" or "a.*b" matches branches starting with "a" and ending with
8091 /// "b", but not any other branch with an "a" followed at some point by a
8092 /// "b". For this second behavior, use "*a*b*". Note that TRegExp does not
8093 /// support '|', and so you cannot select, e.g. track and shower branches
8094 /// with "track|shower".
8095 ///
8096 /// __WARNING! WARNING! WARNING!__
8097 ///
8098 /// SetBranchStatus is matching the branch based on match of the branch
8099 /// 'name' and not on the branch hierarchy! In order to be able to
8100 /// selectively enable a top level object that is 'split' you need to make
8101 /// sure the name of the top level branch is prefixed to the sub-branches'
8102 /// name (by adding a dot ('.') at the end of the Branch creation and use the
8103 /// corresponding bname.
8104 ///
8105 /// I.e If your Tree has been created in split mode with a parent branch "parent."
8106 /// (note the trailing dot).
8107 /// ~~~ {.cpp}
8108 /// T.SetBranchStatus("parent",1);
8109 /// ~~~
8110 /// will not activate the sub-branches of "parent". You should do:
8111 /// ~~~ {.cpp}
8112 /// T.SetBranchStatus("parent*",1);
8113 /// ~~~
8114 /// Without the trailing dot in the branch creation you have no choice but to
8115 /// call SetBranchStatus explicitly for each of the sub branches.
8116 ///
8117 /// An alternative to this function is to read directly and only
8118 /// the interesting branches. Example:
8119 /// ~~~ {.cpp}
8120 /// TBranch *brc = T.GetBranch("c");
8121 /// TBranch *bre = T.GetBranch("e");
8122 /// brc->GetEntry(i);
8123 /// bre->GetEntry(i);
8124 /// ~~~
8125 /// If found is not 0, the number of branch(es) found matching the regular
8126 /// expression is returned in *found AND the error message 'unknown branch'
8127 /// is suppressed.
8129 void TTree::SetBranchStatus(const char* bname, Bool_t status, UInt_t* found)
8130 {
8131  // We already have been visited while recursively looking
8132  // through the friends tree, let return
8134  return;
8135  }
8136 
8137  TBranch *branch, *bcount, *bson;
8138  TLeaf *leaf, *leafcount;
8139 
8140  Int_t i,j;
8141  Int_t nleaves = fLeaves.GetEntriesFast();
8142  TRegexp re(bname,kTRUE);
8143  Int_t nb = 0;
8144 
8145  // first pass, loop on all branches
8146  // for leafcount branches activate/deactivate in function of status
8147  for (i=0;i<nleaves;i++) {
8148  leaf = (TLeaf*)fLeaves.UncheckedAt(i);
8149  branch = (TBranch*)leaf->GetBranch();
8150  TString s = branch->GetName();
8151  if (strcmp(bname,"*")) { //Regexp gives wrong result for [] in name
8152  TString longname;
8153  longname.Form("%s.%s",GetName(),branch->GetName());
8154  if (strcmp(bname,branch->GetName())
8155  && longname != bname
8156  && s.Index(re) == kNPOS) continue;
8157  }
8158  nb++;
8159  if (status) branch->ResetBit(kDoNotProcess);
8160  else branch->SetBit(kDoNotProcess);
8161  leafcount = leaf->GetLeafCount();
8162  if (leafcount) {
8163  bcount = leafcount->GetBranch();
8164  if (status) bcount->ResetBit(kDoNotProcess);
8165  else bcount->SetBit(kDoNotProcess);
8166  }
8167  }
8168  if (nb==0 && strchr(bname,'*')==0) {
8169  branch = GetBranch(bname);
8170  if (branch) {
8171  if (status) branch->ResetBit(kDoNotProcess);
8172  else branch->SetBit(kDoNotProcess);
8173  ++nb;
8174  }
8175  }
8176 
8177  //search in list of friends
8178  UInt_t foundInFriend = 0;
8179  if (fFriends) {
8180  TFriendLock lock(this,kSetBranchStatus);
8181  TIter nextf(fFriends);
8182  TFriendElement *fe;
8183  TString name;
8184  while ((fe = (TFriendElement*)nextf())) {
8185  TTree *t = fe->GetTree();
8186  if (t==0) continue;
8187 
8188  // If the alias is present replace it with the real name.
8189  char *subbranch = (char*)strstr(bname,fe->GetName());
8190  if (subbranch!=bname) subbranch = 0;
8191  if (subbranch) {
8192  subbranch += strlen(fe->GetName());
8193  if ( *subbranch != '.' ) subbranch = 0;
8194  else subbranch ++;
8195  }
8196  if (subbranch) {
8197  name.Form("%s.%s",t->GetName(),subbranch);
8198  } else {
8199  name = bname;
8200  }
8201  t->SetBranchStatus(name,status, &foundInFriend);
8202  }
8203  }
8204  if (!nb && !foundInFriend) {
8205  if (found==0) {
8206  if (status) {
8207  if (strchr(bname,'*') != 0)
8208  Error("SetBranchStatus", "No branch name is matching wildcard -> %s", bname);
8209  else
8210  Error("SetBranchStatus", "unknown branch -> %s", bname);
8211  } else {
8212  if (strchr(bname,'*') != 0)
8213  Warning("SetBranchStatus", "No branch name is matching wildcard -> %s", bname);
8214  else
8215  Warning("SetBranchStatus", "unknown branch -> %s", bname);
8216  }
8217  }
8218  return;
8219  }
8220  if (found) *found = nb + foundInFriend;
8221 
8222  // second pass, loop again on all branches
8223  // activate leafcount branches for active branches only
8224  for (i = 0; i < nleaves; i++) {
8225  leaf = (TLeaf*)fLeaves.UncheckedAt(i);
8226  branch = (TBranch*)leaf->GetBranch();
8227  if (!branch->TestBit(kDoNotProcess)) {
8228  leafcount = leaf->GetLeafCount();
8229  if (leafcount) {
8230  bcount = leafcount->GetBranch();
8231  bcount->ResetBit(kDoNotProcess);
8232  }
8233  } else {
8234  //Int_t nbranches = branch->GetListOfBranches()->GetEntriesFast();
8235  Int_t nbranches = branch->GetListOfBranches()->GetEntries();
8236  for (j=0;j<nbranches;j++) {
8237  bson = (TBranch*)branch->GetListOfBranches()->UncheckedAt(j);
8238  if (!bson) continue;
8239  if (!bson->TestBit(kDoNotProcess)) {
8240  if (bson->GetNleaves() <= 0) continue;
8241  branch->ResetBit(kDoNotProcess);
8242  break;
8243  }
8244  }
8245  }
8246  }
8247 }
8248 
8249 ////////////////////////////////////////////////////////////////////////////////
8250 /// Set the current branch style. (static function)
8251 ///
8252 /// - style = 0 old Branch
8253 /// - style = 1 new Bronch
8256 {
8257  fgBranchStyle = style;
8258 }
8259 
8260 ////////////////////////////////////////////////////////////////////////////////
8261 /// Set maximum size of the file cache .
8262 //
8263 /// - if cachesize = 0 the existing cache (if any) is deleted.
8264 /// - if cachesize = -1 (default) it is set to the AutoFlush value when writing
8265 /// the Tree (default is 30 MBytes).
8266 ///
8267 /// Returns:
8268 /// - 0 size set, cache was created if possible
8269 /// - -1 on error
8272 {
8273  // remember that the user has requested an explicit cache setup
8274  fCacheUserSet = kTRUE;
8275 
8276  return SetCacheSizeAux(kFALSE, cacheSize);
8277 }
8278 
8279 ////////////////////////////////////////////////////////////////////////////////
8280 /// Set the size of the file cache and create it if possible.
8281 ///
8282 /// If autocache is true:
8283 /// this may be an autocreated cache, possibly enlarging an existing
8284 /// autocreated cache. The size is calculated. The value passed in cacheSize:
8285 /// - cacheSize = 0 make cache if default cache creation is enabled
8286 /// - cacheSize = -1 make a default sized cache in any case
8287 ///
8288 /// If autocache is false:
8289 /// this is a user requested cache. cacheSize is used to size the cache.
8290 /// This cache should never be automatically adjusted.
8291 ///
8292 /// Returns:
8293 /// - 0 size set, or existing autosized cache almost large enough.
8294 /// (cache was created if possible)
8295 /// - -1 on error
8297 Int_t TTree::SetCacheSizeAux(Bool_t autocache /* = kTRUE */, Long64_t cacheSize /* = 0 */ )
8298 {
8299  if (autocache) {
8300  // used as a once only control for automatic cache setup
8302  }
8303 
8304  if (!autocache) {
8305  // negative size means the user requests the default
8306  if (cacheSize < 0) {
8307  cacheSize = GetCacheAutoSize(kTRUE);
8308  }
8309  } else {
8310  if (cacheSize == 0) {
8311  cacheSize = GetCacheAutoSize();
8312  } else if (cacheSize < 0) {
8313  cacheSize = GetCacheAutoSize(kTRUE);
8314  }
8315  }
8316 
8317  TFile* file = GetCurrentFile();
8318  if (!file || GetTree() != this) {
8319  // if there's no file or we are not a plain tree (e.g. if we're a TChain)
8320  // do not create a cache, only record the size if one was given
8321  if (!autocache) {
8322  fCacheSize = cacheSize;
8323  }
8324  if (GetTree() != this) {
8325  return 0;
8326  }
8327  if (!autocache && cacheSize>0) {
8328  Warning("SetCacheSizeAux", "A TTreeCache could not be created because the TTree has no file");
8329  }
8330  return 0;
8331  }
8332 
8333  // Check for an existing cache
8334  TTreeCache* pf = GetReadCache(file);
8335  if (pf) {
8336  if (autocache) {
8337  // reset our cache status tracking in case existing cache was added
8338  // by the user without using one of the TTree methods
8339  fCacheSize = pf->GetBufferSize();
8340  fCacheUserSet = !pf->IsAutoCreated();
8341 
8342  if (fCacheUserSet) {
8343  // existing cache was created by the user, don't change it
8344  return 0;
8345  }
8346  } else {
8347  // update the cache to ensure it records the user has explicitly
8348  // requested it
8349  pf->SetAutoCreated(kFALSE);
8350  }
8351 
8352  // if we're using an automatically calculated size and the existing
8353  // cache is already almost large enough don't resize
8354  if (autocache && Long64_t(0.80*cacheSize) < fCacheSize) {
8355  // already large enough
8356  return 0;
8357  }
8358 
8359  if (cacheSize == fCacheSize) {
8360  return 0;
8361  }
8362 
8363  if (cacheSize == 0) {
8364  // delete existing cache
8365  pf->WaitFinishPrefetch();
8366  file->SetCacheRead(0,this);
8367  delete pf;
8368  pf = 0;
8369  } else {
8370  // resize
8371  Int_t res = pf->SetBufferSize(cacheSize);
8372  if (res < 0) {
8373  return -1;
8374  }
8375  }
8376  } else {
8377  // no existing cache
8378  if (autocache) {
8379  if (fCacheUserSet) {
8380  // value was already set manually.
8381  if (fCacheSize == 0) return 0;
8382  // Expected a cache should exist; perhaps the user moved it
8383  // Do nothing more here.
8384  if (cacheSize) {
8385  Error("SetCacheSizeAux", "Not setting up an automatically sized TTreeCache because of missing cache previously set");
8386  }
8387  return -1;
8388  }
8389  }
8390  }
8391 
8392  fCacheSize = cacheSize;
8393  if (cacheSize == 0 || pf) {
8394  return 0;
8395  }
8396 
8397 #ifdef R__USE_IMT
8399  pf = new TTreeCacheUnzip(this, cacheSize);
8400  else
8401 #endif
8402  pf = new TTreeCache(this, cacheSize);
8403 
8404  pf->SetAutoCreated(autocache);
8405 
8406  return 0;
8407 }
8408 
8409 ////////////////////////////////////////////////////////////////////////////////
8410 ///interface to TTreeCache to set the cache entry range
8411 ///
8412 /// Returns:
8413 /// - 0 entry range set
8414 /// - -1 on error
8417 {
8418  if (!GetTree()) {
8419  if (LoadTree(0)<0) {
8420  Error("SetCacheEntryRange","Could not load a tree");
8421  return -1;
8422  }
8423  }
8424  if (GetTree()) {
8425  if (GetTree() != this) {
8426  return GetTree()->SetCacheEntryRange(first, last);
8427  }
8428  } else {
8429  Error("SetCacheEntryRange", "No tree is available. Could not set cache entry range");
8430  return -1;
8431  }
8432 
8433  TFile *f = GetCurrentFile();
8434  if (!f) {
8435  Error("SetCacheEntryRange", "No file is available. Could not set cache entry range");
8436  return -1;
8437  }
8438  TTreeCache *tc = GetReadCache(f,kTRUE);
8439  if (!tc) {
8440  Error("SetCacheEntryRange", "No cache is available. Could not set entry range");
8441  return -1;
8442  }
8443  tc->SetEntryRange(first,last);
8444  return 0;
8445 }
8446 
8447 ////////////////////////////////////////////////////////////////////////////////
8448 /// Interface to TTreeCache to set the number of entries for the learning phase
8451 {
8453 }
8454 
8455 ////////////////////////////////////////////////////////////////////////////////
8456 /// Enable/Disable circularity for this tree.
8457 ///
8458 /// if maxEntries > 0 a maximum of maxEntries is kept in one buffer/basket
8459 /// per branch in memory.
8460 /// Note that when this function is called (maxEntries>0) the Tree
8461 /// must be empty or having only one basket per branch.
8462 /// if maxEntries <= 0 the tree circularity is disabled.
8463 ///
8464 /// #### NOTE 1:
8465 /// Circular Trees are interesting in online real time environments
8466 /// to store the results of the last maxEntries events.
8467 /// #### NOTE 2:
8468 /// Calling SetCircular with maxEntries <= 0 is necessary before
8469 /// merging circular Trees that have been saved on files.
8470 /// #### NOTE 3:
8471 /// SetCircular with maxEntries <= 0 is automatically called
8472 /// by TChain::Merge
8473 /// #### NOTE 4:
8474 /// A circular Tree can still be saved in a file. When read back,
8475 /// it is still a circular Tree and can be filled again.
8477 void TTree::SetCircular(Long64_t maxEntries)
8478 {
8479  if (maxEntries <= 0) {
8480  // Disable circularity.
8481  fMaxEntries = 1000000000;
8482  fMaxEntries *= 1000;
8484  //in case the Tree was originally created in gROOT, the branch
8485  //compression level was set to -1. If the Tree is now associated to
8486  //a file, reset the compression level to the file compression level
8487  if (fDirectory) {
8488  TFile* bfile = fDirectory->GetFile();
8489  Int_t compress = 1;
8490  if (bfile) {
8491  compress = bfile->GetCompressionSettings();
8492  }
8494  for (Int_t i = 0; i < nb; i++) {
8495  TBranch* branch = (TBranch*) fBranches.UncheckedAt(i);
8496  branch->SetCompressionSettings(compress);
8497  }
8498  }
8499  } else {
8500  // Enable circularity.
8501  fMaxEntries = maxEntries;
8502  SetBit(kCircular);
8503  }
8504 }
8505 
8506 ////////////////////////////////////////////////////////////////////////////////
8507 /// Set the debug level and the debug range.
8508 ///
8509 /// For entries in the debug range, the functions TBranchElement::Fill
8510 /// and TBranchElement::GetEntry will print the number of bytes filled
8511 /// or read for each branch.
8513 void TTree::SetDebug(Int_t level, Long64_t min, Long64_t max)
8514 {
8515  fDebug = level;
8516  fDebugMin = min;
8517  fDebugMax = max;
8518 }
8519 
8520 ////////////////////////////////////////////////////////////////////////////////
8521 /// Update the default value for the branch's fEntryOffsetLen.
8522 /// If updateExisting is true, also update all the existing branches.
8523 /// If newdefault is less than 10, the new default value will be 10.
8525 void TTree::SetDefaultEntryOffsetLen(Int_t newdefault, Bool_t updateExisting)
8526 {
8527  if (newdefault < 10) {
8528  newdefault = 10;
8529  }
8530  fDefaultEntryOffsetLen = newdefault;
8531  if (updateExisting) {
8532  TIter next( GetListOfBranches() );
8533  TBranch *b;
8534  while ( ( b = (TBranch*)next() ) ) {
8535  b->SetEntryOffsetLen( newdefault, kTRUE );
8536  }
8537  if (fBranchRef) {
8538  fBranchRef->SetEntryOffsetLen( newdefault, kTRUE );
8539  }
8540  }
8541 }
8542 
8543 ////////////////////////////////////////////////////////////////////////////////
8544 /// Change the tree's directory.
8545 ///
8546 /// Remove reference to this tree from current directory and
8547 /// add reference to new directory dir. The dir parameter can
8548 /// be 0 in which case the tree does not belong to any directory.
8549 ///
8552 {
8553  if (fDirectory == dir) {
8554  return;
8555  }
8556  if (fDirectory) {
8557  fDirectory->Remove(this);
8558 
8559  // Delete or move the file cache if it points to this Tree
8560  TFile *file = fDirectory->GetFile();
8561  MoveReadCache(file,dir);
8562  }
8563  fDirectory = dir;
8564  if (fDirectory) {
8565  fDirectory->Append(this);
8566  }
8567  TFile* file = 0;
8568  if (fDirectory) {
8569  file = fDirectory->GetFile();
8570  }
8571  if (fBranchRef) {
8572  fBranchRef->SetFile(file);
8573  }
8574  TBranch* b = 0;
8575  TIter next(GetListOfBranches());
8576  while((b = (TBranch*) next())) {
8577  b->SetFile(file);
8578  }
8579 }
8580 
8581 ////////////////////////////////////////////////////////////////////////////////
8582 /// Change number of entries in the tree.
8583 ///
8584 /// If n >= 0, set number of entries in the tree = n.
8585 ///
8586 /// If n < 0, set number of entries in the tree to match the
8587 /// number of entries in each branch. (default for n is -1)
8588 ///
8589 /// This function should be called only when one fills each branch
8590 /// independently via TBranch::Fill without calling TTree::Fill.
8591 /// Calling TTree::SetEntries() make sense only if the number of entries
8592 /// in each branch is identical, a warning is issued otherwise.
8593 /// The function returns the number of entries.
8594 ///
8597 {
8598  // case 1 : force number of entries to n
8599  if (n >= 0) {
8600  fEntries = n;
8601  return n;
8602  }
8603 
8604  // case 2; compute the number of entries from the number of entries in the branches
8605  TBranch* b(nullptr), *bMin(nullptr), *bMax(nullptr);
8606  Long64_t nMin = kMaxEntries;
8607  Long64_t nMax = 0;
8608  TIter next(GetListOfBranches());
8609  while((b = (TBranch*) next())){
8610  Long64_t n2 = b->GetEntries();
8611  if (!bMin || n2 < nMin) {
8612  nMin = n2;
8613  bMin = b;
8614  }
8615  if (!bMax || n2 > nMax) {
8616  nMax = n2;
8617  bMax = b;
8618  }
8619  }
8620  if (bMin && nMin != nMax) {
8621  Warning("SetEntries", "Tree branches have different numbers of entries, eg %s has %lld entries while %s has %lld entries.",
8622  bMin->GetName(), nMin, bMax->GetName(), nMax);
8623  }
8624  fEntries = nMax;
8625  return fEntries;
8626 }
8627 
8628 ////////////////////////////////////////////////////////////////////////////////
8629 /// Set an EntryList
8631 void TTree::SetEntryList(TEntryList *enlist, Option_t * /*opt*/)
8632 {
8633  if (fEntryList) {
8634  //check if the previous entry list is owned by the tree
8635  if (fEntryList->TestBit(kCanDelete)){
8636  delete fEntryList;
8637  }
8638  }
8639  fEventList = 0;
8640  if (!enlist) {
8641  fEntryList = 0;
8642  return;
8643  }
8644  fEntryList = enlist;
8645  fEntryList->SetTree(this);
8646 
8647 }
8648 
8649 ////////////////////////////////////////////////////////////////////////////////
8650 /// This function transfroms the given TEventList into a TEntryList
8651 /// The new TEntryList is owned by the TTree and gets deleted when the tree
8652 /// is deleted. This TEntryList can be returned by GetEntryList() function.
8654 void TTree::SetEventList(TEventList *evlist)
8655 {
8656  fEventList = evlist;
8657  if (fEntryList){
8658  if (fEntryList->TestBit(kCanDelete)) {
8659  TEntryList *tmp = fEntryList;
8660  fEntryList = 0; // Avoid problem with RecursiveRemove.
8661  delete tmp;
8662  } else {
8663  fEntryList = 0;
8664  }
8665  }
8666 
8667  if (!evlist) {
8668  fEntryList = 0;
8669  fEventList = 0;
8670  return;
8671  }
8672 
8673  fEventList = evlist;
8674  char enlistname[100];
8675  snprintf(enlistname,100, "%s_%s", evlist->GetName(), "entrylist");
8676  fEntryList = new TEntryList(enlistname, evlist->GetTitle());
8677  fEntryList->SetDirectory(0); // We own this.
8678  Int_t nsel = evlist->GetN();
8679  fEntryList->SetTree(this);
8680  Long64_t entry;
8681  for (Int_t i=0; i<nsel; i++){
8682  entry = evlist->GetEntry(i);
8683  fEntryList->Enter(entry);
8684  }
8685  fEntryList->SetReapplyCut(evlist->GetReapplyCut());
8686  fEntryList->SetBit(kCanDelete, kTRUE);
8687 }
8688 
8689 ////////////////////////////////////////////////////////////////////////////////
8690 /// Set number of entries to estimate variable limits.
8691 /// If n is -1, the estimate is set to be the current maximum
8692 /// for the tree (i.e. GetEntries() + 1)
8693 /// If n is less than -1, the behavior is undefined.
8695 void TTree::SetEstimate(Long64_t n /* = 1000000 */)
8696 {
8697  if (n == 0) {
8698  n = 10000;
8699  } else if (n < 0) {
8700  n = fEntries - n;
8701  }
8702  fEstimate = n;
8703  GetPlayer();
8704  if (fPlayer) {
8705  fPlayer->SetEstimate(n);
8706  }
8707 }
8708 
8709 ////////////////////////////////////////////////////////////////////////////////
8710 /// Provide the end-user with the ability to enable/disable various experimental
8711 /// IO features for this TTree.
8712 ///
8713 /// Returns all the newly-set IO settings.
8716 {
8717  // Purposely ignore all unsupported bits; TIOFeatures implementation already warned the user about the
8718  // error of their ways; this is just a safety check.
8719  UChar_t featuresRequested = features.GetFeatures() & static_cast<UChar_t>(TBasket::EIOBits::kSupported);
8720 
8721  UChar_t curFeatures = fIOFeatures.GetFeatures();
8722  UChar_t newFeatures = ~curFeatures & featuresRequested;
8723  curFeatures |= newFeatures;
8724  fIOFeatures.Set(curFeatures);
8725 
8726  ROOT::TIOFeatures newSettings(newFeatures);
8727  return newSettings;
8728 }
8729 
8730 ////////////////////////////////////////////////////////////////////////////////
8731 /// Set fFileNumber to number.
8732 /// fFileNumber is used by TTree::Fill to set the file name
8733 /// for a new file to be created when the current file exceeds fgTreeMaxSize.
8734 /// (see TTree::ChangeFile)
8735 /// if fFileNumber=10, the new file name will have a suffix "_11",
8736 /// ie, fFileNumber is incremented before setting the file name
8738 void TTree::SetFileNumber(Int_t number)
8739 {
8740  if (fFileNumber < 0) {
8741  Warning("SetFileNumber", "file number must be positive. Set to 0");
8742  fFileNumber = 0;
8743  return;
8744  }
8745  fFileNumber = number;
8746 }
8747 
8748 ////////////////////////////////////////////////////////////////////////////////
8749 /// Set all the branches in this TTree to be in decomposed object mode
8750 /// (also known as MakeClass mode).
8753 {
8754  fMakeClass = make;
8755 
8757  for (Int_t i = 0; i < nb; ++i) {
8758  TBranch* branch = (TBranch*) fBranches.UncheckedAt(i);
8759  branch->SetMakeClass(make);
8760  }
8761 }
8762 
8763 ////////////////////////////////////////////////////////////////////////////////
8764 /// Set the maximum size in bytes of a Tree file (static function).
8765 /// The default size is 100000000000LL, ie 100 Gigabytes.
8766 ///
8767 /// In TTree::Fill, when the file has a size > fgMaxTreeSize,
8768 /// the function closes the current file and starts writing into
8769 /// a new file with a name of the style "file_1.root" if the original
8770 /// requested file name was "file.root".
8772 void TTree::SetMaxTreeSize(Long64_t maxsize)
8773 {
8774  fgMaxTreeSize = maxsize;
8775 }
8776 
8777 ////////////////////////////////////////////////////////////////////////////////
8778 /// Change the name of this tree.
8780 void TTree::SetName(const char* name)
8781 {
8782  if (gPad) {
8783  gPad->Modified();
8784  }
8785  // Trees are named objects in a THashList.
8786  // We must update hashlists if we change the name.
8787  TFile *file = 0;
8788  TTreeCache *pf = 0;
8789  if (fDirectory) {
8790  fDirectory->Remove(this);
8791  if ((file = GetCurrentFile())) {
8792  pf = GetReadCache(file);
8793  file->SetCacheRead(0,this,TFile::kDoNotDisconnect);
8794  }
8795  }
8796  // This changes our hash value.
8797  fName = name;
8798  if (fDirectory) {
8799  fDirectory->Append(this);
8800  if (pf) {
8801  file->SetCacheRead(pf,this,TFile::kDoNotDisconnect);
8802  }
8803  }
8804 }
8805 
8806 ////////////////////////////////////////////////////////////////////////////////
8807 /// Change the name and title of this tree.
8809 void TTree::SetObject(const char* name, const char* title)
8810 {
8811  if (gPad) {
8812  gPad->Modified();
8813  }
8814 
8815  // Trees are named objects in a THashList.
8816  // We must update hashlists if we change the name
8817  TFile *file = 0;
8818  TTreeCache *pf = 0;
8819  if (fDirectory) {
8820  fDirectory->Remove(this);
8821  if ((file = GetCurrentFile())) {
8822  pf = GetReadCache(file);
8823  file->SetCacheRead(0,this,TFile::kDoNotDisconnect);
8824  }
8825  }
8826  // This changes our hash value.
8827  fName = name;
8828  fTitle = title;
8829  if (fDirectory) {
8830  fDirectory->Append(this);
8831  if (pf) {
8832  file->SetCacheRead(pf,this,TFile::kDoNotDisconnect);
8833  }
8834  }
8835 }
8836 
8837 ////////////////////////////////////////////////////////////////////////////////
8838 /// Enable or disable parallel unzipping of Tree buffers.
8840 void TTree::SetParallelUnzip(Bool_t opt, Float_t RelSize)
8841 {
8844 
8845  if (RelSize > 0) {
8847  }
8848 
8849 }
8850 
8851 ////////////////////////////////////////////////////////////////////////////////
8852 /// Set perf stats
8855 {
8856  fPerfStats = perf;
8857 }
8858 
8859 ////////////////////////////////////////////////////////////////////////////////
8860 /// The current TreeIndex is replaced by the new index.
8861 /// Note that this function does not delete the previous index.
8862 /// This gives the possibility to play with more than one index, e.g.,
8863 /// ~~~ {.cpp}
8864 /// TVirtualIndex* oldIndex = tree.GetTreeIndex();
8865 /// tree.SetTreeIndex(newIndex);
8866 /// tree.Draw();
8867 /// tree.SetTreeIndex(oldIndex);
8868 /// tree.Draw(); etc
8869 /// ~~~
8872 {
8873  if (fTreeIndex) {
8874  fTreeIndex->SetTree(0);
8875  }
8876  fTreeIndex = index;
8877 }
8878 
8879 ////////////////////////////////////////////////////////////////////////////////
8880 /// Set tree weight.
8881 ///
8882 /// The weight is used by TTree::Draw to automatically weight each
8883 /// selected entry in the resulting histogram.
8884 ///
8885 /// For example the equivalent of:
8886 /// ~~~ {.cpp}
8887 /// T.Draw("x", "w")
8888 /// ~~~
8889 /// is:
8890 /// ~~~ {.cpp}
8891 /// T.SetWeight(w);
8892 /// T.Draw("x");
8893 /// ~~~
8894 /// This function is redefined by TChain::SetWeight. In case of a
8895 /// TChain, an option "global" may be specified to set the same weight
8896 /// for all trees in the TChain instead of the default behaviour
8897 /// using the weights of each tree in the chain (see TChain::SetWeight).
8900 {
8901  fWeight = w;
8902 }
8903 
8904 ////////////////////////////////////////////////////////////////////////////////
8905 /// Print values of all active leaves for entry.
8906 ///
8907 /// - if entry==-1, print current entry (default)
8908 /// - if a leaf is an array, a maximum of lenmax elements is printed.
8910 void TTree::Show(Long64_t entry, Int_t lenmax)
8911 {
8912  if (entry != -1) {
8913  Int_t ret = LoadTree(entry);
8914  if (ret == -2) {
8915  Error("Show()", "Cannot read entry %lld (entry does not exist)", entry);
8916  return;
8917  } else if (ret == -1) {
8918  Error("Show()", "Cannot read entry %lld (I/O error)", entry);
8919  return;
8920  }
8921  ret = GetEntry(entry);
8922  if (ret == -1) {
8923  Error("Show()", "Cannot read entry %lld (I/O error)", entry);
8924  return;
8925  } else if (ret == 0) {
8926  Error("Show()", "Cannot read entry %lld (no data read)", entry);
8927  return;
8928  }
8929  }
8930  printf("======> EVENT:%lld\n", fReadEntry);
8931  TObjArray* leaves = GetListOfLeaves();
8932  Int_t nleaves = leaves->GetEntriesFast();
8933  Int_t ltype;
8934  for (Int_t i = 0; i < nleaves; i++) {
8935  TLeaf* leaf = (TLeaf*) leaves->UncheckedAt(i);
8936  TBranch* branch = leaf->GetBranch();
8937  if (branch->TestBit(kDoNotProcess)) {
8938  continue;
8939  }
8940  Int_t len = leaf->GetLen();
8941  if (len <= 0) {
8942  continue;
8943  }
8944  len = TMath::Min(len, lenmax);
8945  if (leaf->IsA() == TLeafElement::Class()) {
8946  leaf->PrintValue(lenmax);
8947  continue;
8948  }
8949  if (branch->GetListOfBranches()->GetEntriesFast() > 0) {
8950  continue;
8951  }
8952  ltype = 10;
8953  if (leaf->IsA() == TLeafF::Class()) {
8954  ltype = 5;
8955  }
8956  if (leaf->IsA() == TLeafD::Class()) {
8957  ltype = 5;
8958  }
8959  if (leaf->IsA() == TLeafC::Class()) {
8960  len = 1;
8961  ltype = 5;
8962  };
8963  printf(" %-15s = ", leaf->GetName());
8964  for (Int_t l = 0; l < len; l++) {
8965  leaf->PrintValue(l);
8966  if (l == (len - 1)) {
8967  printf("\n");
8968  continue;
8969  }
8970  printf(", ");
8971  if ((l % ltype) == 0) {
8972  printf("\n ");
8973  }
8974  }
8975  }
8976 }
8977 
8978 ////////////////////////////////////////////////////////////////////////////////
8979 /// Start the TTreeViewer on this tree.
8980 ///
8981 /// - ww is the width of the canvas in pixels
8982 /// - wh is the height of the canvas in pixels
8984 void TTree::StartViewer()
8985 {
8986  GetPlayer();
8987  if (fPlayer) {
8988  fPlayer->StartViewer(600, 400);
8989  }
8990 }
8991 
8992 ////////////////////////////////////////////////////////////////////////////////
8993 /// Stop the cache learning phase
8994 ///
8995 /// Returns:
8996 /// - 0 learning phase stopped or not active
8997 /// - -1 on error
9000 {
9001  if (!GetTree()) {
9002  if (LoadTree(0)<0) {
9003  Error("StopCacheLearningPhase","Could not load a tree");
9004  return -1;
9005  }
9006  }
9007  if (GetTree()) {
9008  if (GetTree() != this) {
9009  return GetTree()->StopCacheLearningPhase();
9010  }
9011  } else {
9012  Error("StopCacheLearningPhase", "No tree is available. Could not stop cache learning phase");
9013  return -1;
9014  }
9015 
9016  TFile *f = GetCurrentFile();
9017  if (!f) {
9018  Error("StopCacheLearningPhase", "No file is available. Could not stop cache learning phase");
9019  return -1;
9020  }
9021  TTreeCache *tc = GetReadCache(f,kTRUE);
9022  if (!tc) {
9023  Error("StopCacheLearningPhase", "No cache is available. Could not stop learning phase");
9024  return -1;
9025  }
9026  tc->StopLearningPhase();
9027  return 0;
9028 }
9029 
9030 ////////////////////////////////////////////////////////////////////////////////
9031 /// Set the fTree member for all branches and sub branches.
9034 {
9035  Int_t nb = branches.GetEntriesFast();
9036  for (Int_t i = 0; i < nb; ++i) {
9037  TBranch* br = (TBranch*) branches.UncheckedAt(i);
9038  br->SetTree(tree);
9039 
9040  Int_t nBaskets = br->GetListOfBaskets()->GetEntries();
9041  Int_t writeBasket = br->GetWriteBasket();
9042  for (Int_t j=writeBasket,n=0;j>=0 && n<nBaskets;--j) {
9043  TBasket *bk = (TBasket*)br->GetListOfBaskets()->UncheckedAt(j);
9044  if (bk) {
9045  tree->IncrementTotalBuffers(bk->GetBufferSize());
9046  ++n;
9047  }
9048  }
9049 
9050  TBranch__SetTree(tree,*br->GetListOfBranches());
9051  }
9052 }
9053 
9054 ////////////////////////////////////////////////////////////////////////////////
9055 /// Set the fTree member for all friend elements.
9057 void TFriendElement__SetTree(TTree *tree, TList *frlist)
9058 {
9059  if (frlist) {
9060  TObjLink *lnk = frlist->FirstLink();
9061  while (lnk) {
9062  TFriendElement *elem = (TFriendElement*)lnk->GetObject();
9063  elem->fParentTree = tree;
9064  lnk = lnk->Next();
9065  }
9066  }
9067 }
9068 
9069 ////////////////////////////////////////////////////////////////////////////////
9070 /// Stream a class object.
9071 
9072 void TTree::Streamer(TBuffer& b)
9073 {
9074  if (b.IsReading()) {
9075  UInt_t R__s, R__c;
9076  if (fDirectory) {
9077  fDirectory->Remove(this);
9078  //delete the file cache if it points to this Tree
9079  TFile *file = fDirectory->GetFile();
9080  MoveReadCache(file,0);
9081  }
9082  fDirectory = 0;
9085  Version_t R__v = b.ReadVersion(&R__s, &R__c);
9086  if (R__v > 4) {
9087  b.ReadClassBuffer(TTree::Class(), this, R__v, R__s, R__c);
9088 
9089  fBranches.SetOwner(kTRUE); // True needed only for R__v < 19 and most R__v == 19
9090 
9091  if (fBranchRef) fBranchRef->SetTree(this);
9094 
9095  if (fTreeIndex) {
9096  fTreeIndex->SetTree(this);
9097  }
9098  if (fIndex.fN) {
9099  Warning("Streamer", "Old style index in this tree is deleted. Rebuild the index via TTree::BuildIndex");
9100  fIndex.Set(0);
9101  fIndexValues.Set(0);
9102  }
9103  if (fEstimate <= 10000) {
9104  fEstimate = 1000000;
9105  }
9106 
9107  if (fNClusterRange) {
9108  // The I/O allocated just enough memory to hold the
9109  // current set of ranges.
9111  }
9112  if (GetCacheAutoSize() != 0) {
9113  // a cache will be automatically created.
9114  // No need for TTreePlayer::Process to enable the cache
9115  fCacheSize = 0;
9116  } else if (fAutoFlush < 0) {
9117  // If there is no autoflush set, let's keep the cache completely
9118  // disable by default for now.
9120  } else if (fAutoFlush != 0) {
9121  // Estimate the cluster size.
9122  // This will allow TTree::Process to enable the cache.
9123  Long64_t zipBytes = GetZipBytes();
9124  Long64_t totBytes = GetTotBytes();
9125  if (zipBytes != 0) {
9126  fCacheSize = fAutoFlush*(zipBytes/fEntries);
9127  } else if (totBytes != 0) {
9128  fCacheSize = fAutoFlush*(totBytes/fEntries);
9129  } else {
9130  fCacheSize = 30000000;
9131  }
9132  if (fCacheSize >= (INT_MAX / 4)) {
9133  fCacheSize = INT_MAX / 4;
9134  } else if (fCacheSize == 0) {
9135  fCacheSize = 30000000;
9136  }
9137  } else {
9138  fCacheSize = 0;
9139  }
9141  return;
9142  }
9143  //====process old versions before automatic schema evolution
9144  Stat_t djunk;
9145  Int_t ijunk;
9146  TNamed::Streamer(b);
9147  TAttLine::Streamer(b);
9148  TAttFill::Streamer(b);
9149  TAttMarker::Streamer(b);
9150  b >> fScanField;
9151  b >> ijunk; fMaxEntryLoop = (Long64_t)ijunk;
9152  b >> ijunk; fMaxVirtualSize = (Long64_t)ijunk;
9153  b >> djunk; fEntries = (Long64_t)djunk;
9154  b >> djunk; fTotBytes = (Long64_t)djunk;
9155  b >> djunk; fZipBytes = (Long64_t)djunk;
9156  b >> ijunk; fAutoSave = (Long64_t)ijunk;
9157  b >> ijunk; fEstimate = (Long64_t)ijunk;
9158  if (fEstimate <= 10000) fEstimate = 1000000;
9159  fBranches.Streamer(b);
9160  if (fBranchRef) fBranchRef->SetTree(this);
9162  fLeaves.Streamer(b);
9164  if (R__v > 1) fIndexValues.Streamer(b);
9165  if (R__v > 2) fIndex.Streamer(b);
9166  if (R__v > 3) {
9167  TList OldInfoList;
9168  OldInfoList.Streamer(b);
9169  OldInfoList.Delete();
9170  }
9171  fNClusterRange = 0;
9172  fDefaultEntryOffsetLen = 1000;
9174  b.CheckByteCount(R__s, R__c, TTree::IsA());
9175  //====end of old versions
9176  } else {
9177  if (fBranchRef) {
9178  fBranchRef->Clear();
9179  }
9180  TRefTable *table = TRefTable::GetRefTable();
9181  if (table) TRefTable::SetRefTable(0);
9182 
9183  b.WriteClassBuffer(TTree::Class(), this);
9184 
9185  if (table) TRefTable::SetRefTable(table);
9186  }
9187 }
9188 
9189 ////////////////////////////////////////////////////////////////////////////////
9190 /// Unbinned fit of one or more variable(s) from a tree.
9191 ///
9192 /// funcname is a TF1 function.
9193 ///
9194 /// See TTree::Draw for explanations of the other parameters.
9195 ///
9196 /// Fit the variable varexp using the function funcname using the
9197 /// selection cuts given by selection.
9198 ///
9199 /// The list of fit options is given in parameter option.
9200 ///
9201 /// - option = "Q" Quiet mode (minimum printing)
9202 /// - option = "V" Verbose mode (default is between Q and V)
9203 /// - option = "E" Perform better Errors estimation using Minos technique
9204 /// - option = "M" More. Improve fit results
9205 ///
9206 /// You can specify boundary limits for some or all parameters via
9207 /// ~~~ {.cpp}
9208 /// func->SetParLimits(p_number, parmin, parmax);
9209 /// ~~~
9210 /// if parmin>=parmax, the parameter is fixed
9211 ///
9212 /// Note that you are not forced to fix the limits for all parameters.
9213 /// For example, if you fit a function with 6 parameters, you can do:
9214 /// ~~~ {.cpp}
9215 /// func->SetParameters(0,3.1,1.e-6,0.1,-8,100);
9216 /// func->SetParLimits(4,-10,-4);
9217 /// func->SetParLimits(5, 1,1);
9218 /// ~~~
9219 /// With this setup:
9220 ///
9221 /// - Parameters 0->3 can vary freely
9222 /// - Parameter 4 has boundaries [-10,-4] with initial value -8
9223 /// - Parameter 5 is fixed to 100.
9224 ///
9225 /// For the fit to be meaningful, the function must be self-normalized.
9226 ///
9227 /// i.e. It must have the same integral regardless of the parameter
9228 /// settings. Otherwise the fit will effectively just maximize the
9229 /// area.
9230 ///
9231 /// It is mandatory to have a normalization variable
9232 /// which is fixed for the fit. e.g.
9233 /// ~~~ {.cpp}
9234 /// TF1* f1 = new TF1("f1", "gaus(0)/sqrt(2*3.14159)/[2]", 0, 5);
9235 /// f1->SetParameters(1, 3.1, 0.01);
9236 /// f1->SetParLimits(0, 1, 1); // fix the normalization parameter to 1
9237 /// data->UnbinnedFit("f1", "jpsimass", "jpsipt>3.0");
9238 /// ~~~
9239 /// 1, 2 and 3 Dimensional fits are supported. See also TTree::Fit
9240 ///
9241 /// Return status:
9242 ///
9243 /// - The function return the status of the fit in the following form
9244 /// fitResult = migradResult + 10*minosResult + 100*hesseResult + 1000*improveResult
9245 /// - The fitResult is 0 is the fit is OK.
9246 /// - The fitResult is negative in case of an error not connected with the fit.
9247 /// - The number of entries used in the fit can be obtained via mytree.GetSelectedRows();
9248 /// - If the number of selected entries is null the function returns -1
9250 Int_t TTree::UnbinnedFit(const char* funcname, const char* varexp, const char* selection, Option_t* option, Long64_t nentries, Long64_t firstentry)
9251 {
9252  GetPlayer();
9253  if (fPlayer) {
9254  return fPlayer->UnbinnedFit(funcname, varexp, selection, option, nentries, firstentry);
9255  }
9256  return -1;
9257 }
9258 
9259 ////////////////////////////////////////////////////////////////////////////////
9260 /// Replace current attributes by current style.
9263 {
9264  if (gStyle->IsReading()) {
9273  } else {
9282  }
9283 }
9284 
9285 ////////////////////////////////////////////////////////////////////////////////
9286 /// Write this object to the current directory. For more see TObject::Write
9287 /// Write calls TTree::FlushBaskets before writing the tree.
9289 Int_t TTree::Write(const char *name, Int_t option, Int_t bufsize) const
9290 {
9291  FlushBasketsImpl();
9292  return TObject::Write(name, option, bufsize);
9293 }
9294 
9295 ////////////////////////////////////////////////////////////////////////////////
9296 /// Write this object to the current directory. For more see TObject::Write
9297 /// If option & kFlushBasket, call FlushBasket before writing the tree.
9299 Int_t TTree::Write(const char *name, Int_t option, Int_t bufsize)
9300 {
9301  return ((const TTree*)this)->Write(name, option, bufsize);
9302 }
9303 
9304 ////////////////////////////////////////////////////////////////////////////////
9305 /// \class TTreeFriendLeafIter
9306 ///
9307 /// Iterator on all the leaves in a TTree and its friend
9308 
9310 
9311 ////////////////////////////////////////////////////////////////////////////////
9312 /// Create a new iterator. By default the iteration direction
9313 /// is kIterForward. To go backward use kIterBackward.
9316 : fTree(const_cast<TTree*>(tree))
9317 , fLeafIter(0)
9318 , fTreeIter(0)
9319 , fDirection(dir)
9320 {
9321 }
9322 
9323 ////////////////////////////////////////////////////////////////////////////////
9324 /// Copy constructor. Does NOT copy the 'cursor' location!
9327 : TIterator(iter)
9328 , fTree(iter.fTree)
9329 , fLeafIter(0)
9330 , fTreeIter(0)
9331 , fDirection(iter.fDirection)
9332 {
9333 }
9334 
9335 ////////////////////////////////////////////////////////////////////////////////
9336 /// Overridden assignment operator. Does NOT copy the 'cursor' location!
9339 {
9340  if (this != &rhs && rhs.IsA() == TTreeFriendLeafIter::Class()) {
9341  const TTreeFriendLeafIter &rhs1 = (const TTreeFriendLeafIter &)rhs;
9342  fDirection = rhs1.fDirection;
9343  }
9344  return *this;
9345 }
9346 
9347 ////////////////////////////////////////////////////////////////////////////////
9348 /// Overridden assignment operator. Does NOT copy the 'cursor' location!
9351 {
9352  if (this != &rhs) {
9353  fDirection = rhs.fDirection;
9354  }
9355  return *this;
9356 }
9357 
9358 ////////////////////////////////////////////////////////////////////////////////
9359 /// Go the next friend element
9362 {
9363  if (!fTree) return 0;
9364 
9365  TObject * next;
9366  TTree * nextTree;
9367 
9368  if (!fLeafIter) {
9369  TObjArray *list = fTree->GetListOfLeaves();
9370  if (!list) return 0; // Can happen with an empty chain.
9372  if (!fLeafIter) return 0;
9373  }
9374 
9375  next = fLeafIter->Next();
9376  if (!next) {
9377  if (!fTreeIter) {
9378  TCollection * list = fTree->GetListOfFriends();
9379  if (!list) return next;
9381  if (!fTreeIter) return 0;
9382  }
9383  TFriendElement * nextFriend = (TFriendElement*) fTreeIter->Next();
9384  ///nextTree = (TTree*)fTreeIter->Next();
9385  if (nextFriend) {
9386  nextTree = const_cast<TTree*>(nextFriend->GetTree());
9387  if (!nextTree) return Next();
9390  if (!fLeafIter) return 0;
9391  next = fLeafIter->Next();
9392  }
9393  }
9394  return next;
9395 }
9396 
9397 ////////////////////////////////////////////////////////////////////////////////
9398 /// Returns the object option stored in the list.
9401 {
9402  if (fLeafIter) return fLeafIter->GetOption();
9403  return "";
9404 }
A zero length substring is legal.
Definition: TString.h:77
Bool_t HasRuleWithSourceClass(const TString &source) const
Return True if we have any rule whose source class is &#39;source&#39;.
TString fTitle
Definition: TNamed.h:33
TTree * fParentTree
! pointer to the parent TTree
void Add(TObject *obj, const char *name=0, Int_t check=-1)
Add object with name to browser.
Definition: TBrowser.cxx:261
Describe Streamer information for one class version.
Definition: TStreamerInfo.h:43
void Foreach(F func, unsigned nTimes)
Execute func (with no arguments) nTimes in parallel.
virtual Bool_t GetReapplyCut() const
Definition: TEventList.h:57
virtual Bool_t cd(const char *path=0)
Change current directory to "this" directory.
virtual TBranch * FindBranch(const char *name)
Return the branch that correspond to the path &#39;branchname&#39;, which can include the name of the tree or...
Definition: TTree.cxx:4606
virtual const char * GetName() const
Returns name of object.
Definition: TNamed.h:47
virtual Int_t Write(const char *name=0, Int_t option=0, Int_t bufsize=0)
Write this object to the current directory.
Definition: TObject.cxx:785
Double_t fWeight
Tree weight (see TTree::SetWeight)
Definition: TTree.h:81
virtual Int_t Occurence(const TObject *obj) const
Return occurence number of object in the list of objects of this folder.
Definition: TFolder.cxx:436
virtual Bool_t AccessPathName(const char *path, EAccessMode mode=kFileExists)
Returns FALSE if one can access a file using the specified access mode.
Definition: TSystem.cxx:1276
virtual Int_t MakeProxy(const char *classname, const char *macrofilename=0, const char *cutfilename=0, const char *option=0, Int_t maxUnrolling=3)=0
A TLeaf describes individual elements of a TBranch See TBranch structure in TTree.
Definition: TLeaf.h:32
virtual void SetLineWidth(Width_t lwidth)
Set the line width.
Definition: TAttLine.h:43
Int_t Unroll(const char *name, TClass *cltop, TClass *cl, char *ptr, Int_t basketsize, Int_t splitlevel, Int_t btype)
Split class cl into sub-branches of this branch.
Long64_t Previous()
Move on to the previous cluster and return the starting entry of this previous cluster.
Definition: TTree.cxx:658
Bool_t IsReading() const
Definition: TBuffer.h:83
TTreeCache * GetReadCache(TFile *file) const
Find and return the TTreeCache registered with the file and which may contain branches for us...
Definition: TTree.cxx:6036
virtual void AddTotBytes(Int_t tot)
Definition: TTree.h:297
A TFolder object is a collection of objects and folders.
Definition: TFolder.h:30
virtual void ResetAfterMerge(TFileMergeInfo *)
Reset a Branch after a Merge operation (drop data but keep customizations) TRefTable is cleared...
Definition: TBranchRef.cxx:198
virtual TList * GetListOfClones()
Definition: TTree.h:408
Bool_t CanSplit() const
Return true if the data member of this TClass can be saved separately.
Definition: TClass.cxx:2231
TList * GetListOfBases()
Return list containing the TBaseClass(es) of a class.
Definition: TClass.cxx:3507
virtual TTree * CopyTree(const char *selection, Option_t *option="", Long64_t nentries=kMaxEntries, Long64_t firstentry=0)=0
ESTLType
Definition: ESTLType.h:28
TStreamerInfo * BuildStreamerInfo(TClass *cl, void *pointer=0, Bool_t canOptimize=kTRUE)
Build StreamerInfo for class cl.
Definition: TTree.cxx:2519
An array of TObjects.
Definition: TObjArray.h:37
static TDataType * GetDataType(EDataType type)
Given a EDataType type, get the TDataType* that represents it.
Definition: TDataType.cxx:440
Long64_t fDebugMin
! First entry number to debug
Definition: TTree.h:103
Principal Components Analysis (PCA)
Definition: TPrincipal.h:20
TTree * fTree
tree being iterated
Definition: TTree.h:595
virtual Int_t FillImpl(ROOT::Internal::TBranchIMTHelper *)
Loop on all leaves of this branch to fill Basket buffer.
Definition: TBranch.cxx:818
virtual TDirectory * GetDirectory() const
Definition: TEntryList.h:74
virtual void Append(const TVirtualIndex *, Bool_t delaySort=kFALSE)=0
virtual Int_t WriteClassBuffer(const TClass *cl, void *pointer)=0
Bool_t fPrevious
Definition: TTree.h:171
virtual TList * GetListOfKeys() const
Definition: TDirectory.h:150
virtual void Delete(Option_t *option="")
Remove all objects from the list AND delete all heap based objects.
Definition: TList.cxx:467
virtual void UpdateFile()
Refresh the value of fDirectory (i.e.
Definition: TBranch.cxx:2872
virtual void Info(const char *method, const char *msgfmt,...) const
Issue info message.
Definition: TObject.cxx:854
virtual Option_t * GetOption() const
Definition: TIterator.h:40
TString GetTypeName()
Get basic type of typedef, e,g.
Definition: TDataType.cxx:149
virtual TTree * GetTree()
Return pointer to friend TTree.
The concrete implementation of TBuffer for writing/reading to/from a ROOT file or socket...
Definition: TBufferFile.h:46
virtual void SetAddress(void *add)
Set address of this branch.
Definition: TBranch.cxx:2258
virtual void OptimizeBaskets(ULong64_t maxMemory=10000000, Float_t minComp=1.1, Option_t *option="")
This function may be called after having filled some entries in a Tree.
Definition: TTree.cxx:6764
Bool_t MemoryFull(Int_t nbytes)
Check if adding nbytes to memory we are still below MaxVirtualsize.
Definition: TTree.cxx:6566
virtual TBranch * BranchImpRef(const char *branchname, const char *classname, TClass *ptrClass, void *addobj, Int_t bufsize, Int_t splitlevel)
Same as TTree::Branch but automatic detection of the class name.
Definition: TTree.cxx:1531
virtual Int_t MakeCode(const char *filename=0)
Generate a skeleton function for this tree.
Definition: TTree.cxx:6369
long long Long64_t
Definition: RtypesCore.h:69
TIterator * fTreeIter
current tree sub-iterator.
Definition: TTree.h:597
Abstract interface for Tree Index.
Definition: TVirtualIndex.h:29
auto * m
Definition: textangle.C:8
virtual Int_t GetBasketSize() const
Definition: TBranch.h:174
virtual Int_t MakeReader(const char *classname, Option_t *option)=0
virtual Long64_t ReadStream(std::istream &inputStream, const char *branchDescriptor="", char delimiter=' ')
Create or simply read branches from an input stream.
Definition: TTree.cxx:7280
Namespace for new ROOT classes and functions.
Definition: StringConv.hxx:21
virtual Int_t StopCacheLearningPhase()
Stop the cache learning phase.
Definition: TTree.cxx:8998
virtual void SetBranchStatus(const char *bname, Bool_t status=1, UInt_t *found=0)
Set branch status to Process or DoNotProcess.
Definition: TTree.cxx:8128
virtual void IncrementTotalBuffers(Int_t nbytes)
Definition: TTree.h:466
short Version_t
Definition: RtypesCore.h:61
virtual void Delete(Option_t *option="")
Delete this tree from memory or/and disk.
Definition: TTree.cxx:3550
#define R__unlikely(expr)
Definition: RConfig.h:578
Bool_t EqualTo(const char *cs, ECaseCompare cmp=kExact) const
Definition: TString.h:628
virtual Int_t FlushBaskets(Bool_t create_cluster=true) const
Write to disk all the basket that have not yet been individually written and create an event cluster ...
Definition: TTree.cxx:4884
A Branch for the case of an object.
Definition: TBranchObject.h:26
const char * GetFullTypeName() const
Get full type description of data member, e,g.: "class TDirectory*".
TObjArray * GetListOfBaskets()
Definition: TBranch.h:200
TLine * line
static Int_t fgBranchStyle
Old/New branch style.
Definition: TTree.h:134
virtual void AddZipBytes(Int_t zip)
Definition: TTree.h:298
virtual void SetTree(const TTree *T)=0
virtual Int_t LoadBaskets(Long64_t maxmemory=2000000000)
Read in memory all baskets from all branches up to the limit of maxmemory bytes.
Definition: TTree.cxx:6169
virtual void Clear(Option_t *option="")
Remove all objects from the array.
Definition: TObjArray.cxx:320
float Float_t
Definition: RtypesCore.h:53
virtual Int_t GetExpectedType(TClass *&clptr, EDataType &type)
Fill expectedClass and expectedType with information on the data type of the object/values contained ...
Definition: TBranch.cxx:1482
TVirtualStreamerInfo * FindConversionStreamerInfo(const char *onfile_classname, UInt_t checksum) const
Return a Conversion StreamerInfo from the class &#39;classname&#39; for the layout represented by &#39;checksum&#39; ...
Definition: TClass.cxx:6854
static Long64_t GetMaxTreeSize()
Static function which returns the tree file size limit in bytes.
Definition: TTree.cxx:5983
virtual void SetParallelUnzip(Bool_t opt=kTRUE, Float_t RelSize=-1)
Enable or disable parallel unzipping of Tree buffers.
Definition: TTree.cxx:8839
TVirtualStreamerInfo * GetConversionStreamerInfo(const char *onfile_classname, Int_t version) const
Return a Conversion StreamerInfo from the class &#39;classname&#39; for version number &#39;version&#39; to this clas...
Definition: TClass.cxx:6757
virtual Int_t MakeCode(const char *filename)=0
Provides the interface for the PROOF internal performance measurement and event tracing.
A cache when reading files over the network.
const char Option_t
Definition: RtypesCore.h:62
virtual Bool_t Notify()
Function called when loading a new class library.
Definition: TTree.cxx:6740
TTree()
Default constructor and I/O constructor.
Definition: TTree.cxx:701
virtual TTree * GetFriend(const char *) const
Return a pointer to the TTree friend whose name or alias is &#39;friendname.
Definition: TTree.cxx:5694
void GetObject(const char *namecycle, T *&ptr)
Definition: TDirectory.h:139
virtual TClass * GetValueClass() const =0
virtual void Delete(Option_t *option="")
Remove all objects from the array AND delete all heap based objects.
Definition: TObjArray.cxx:355
All ROOT classes may have RTTI (run time type identification) support added.
Definition: TDataMember.h:31
virtual Long64_t GetEntriesFast() const
Definition: TTree.h:386
const char * Size
Definition: TXMLSetup.cxx:55
TBuffer * fTransientBuffer
! Pointer to the current transient buffer.
Definition: TTree.h:125
virtual void Flush()
Synchronize a file&#39;s in-memory and on-disk states.
Definition: TFile.cxx:1099
virtual void Print(Option_t *option="") const
Print a summary of the tree contents.
Definition: TTree.cxx:6926
virtual void SetCacheRead(TFileCacheRead *cache, TObject *tree=0, ECacheAction action=kDisconnect)
Set a pointer to the read cache.
Definition: TFile.cxx:2265
Long64_t GetZipBytes(Option_t *option="") const
Return total number of zip bytes in the branch if option ="*" includes all sub-branches of this branc...
Definition: TBranch.cxx:1814
virtual Int_t Fit(const char *funcname, const char *varexp, const char *selection="", Option_t *option="", Option_t *goption="", Long64_t nentries=kMaxEntries, Long64_t firstentry=0)
Fit a projected item(s) from a tree.
Definition: TTree.cxx:4834
const Ssiz_t kNPOS
Definition: RtypesCore.h:111
TIterator * fLeafIter
current leaf sub-iterator.
Definition: TTree.h:596
TString & ReplaceAll(const TString &s1, const TString &s2)
Definition: TString.h:687
R__EXTERN TStyle * gStyle
Definition: TStyle.h:406
TList * fFriends
pointer to list of friend elements
Definition: TTree.h:118
void SetHistLineWidth(Width_t width=1)
Definition: TStyle.h:360
TPrincipal * Principal(const char *varexp="", const char *selection="", Option_t *option="np", Long64_t nentries=kMaxEntries, Long64_t firstentry=0)
Interface to the Principal Components Analysis class.
Definition: TTree.cxx:6907
virtual Int_t Fill()
Fill all branches.
Definition: TTree.cxx:4374
Int_t GetMakeClass() const
Definition: TTree.h:416
virtual TEntryList * GetEntryList()
Returns the entry list, set to this tree.
Definition: TTree.cxx:5573
ROOT::TIOFeatures SetIOFeatures(const ROOT::TIOFeatures &)
Provide the end-user with the ability to enable/disable various experimental IO features for this TTr...
Definition: TTree.cxx:8714
virtual void SetName(const char *name)
Set the name of the TNamed.
Definition: TNamed.cxx:140
virtual void SetOwner(Bool_t enable=kTRUE)
Set whether this collection is the owner (enable==true) of its content.
virtual void DropBaskets(Option_t *option="")
Loop on all branch baskets.
Definition: TBranch.cxx:719
static void SetBranchStyle(Int_t style=1)
Set the current branch style.
Definition: TTree.cxx:8254
A specialized TFileCacheRead object for a TTree.
Definition: TTreeCache.h:35
virtual TLeaf * GetLeaf(const char *branchname, const char *leafname)
Return pointer to the 1st Leaf named name in any Branch of this Tree or any branch in the list of fri...
Definition: TTree.cxx:5907
TTree * fTree
Definition: TTree.h:169
const std::type_info * GetTypeInfo() const
Definition: TClass.h:461
static Int_t SetParallelUnzip(TTreeCacheUnzip::EParUnzipMode option=TTreeCacheUnzip::kEnable)
Static function that (de)activates multithreading unzipping.
static char DataTypeToChar(EDataType datatype)
Definition: TTree.cxx:428
TVirtualStreamerInfo * GetStreamerInfo(Int_t version=0) const
returns a pointer to the TVirtualStreamerInfo object for version If the object does not exist...
Definition: TClass.cxx:4420
virtual void PrintValue(Int_t i=0) const
Definition: TLeaf.h:132
A ROOT file is a suite of consecutive data records (TKey instances) with a well defined format...
Definition: TFile.h:47
const char * GetTypeName() const
Get type of data member, e,g.: "class TDirectory*" -> "TDirectory".
virtual Int_t GetEntries() const
Definition: TCollection.h:177
virtual TLeaf * GetLeafImpl(const char *branchname, const char *leafname)
Return pointer to the 1st Leaf named name in any Branch of this Tree or any branch in the list of fri...
Definition: TTree.cxx:5817
virtual TList * GetListOfFriends() const
Definition: TTree.h:411
virtual Long64_t GetAutoFlush() const
Definition: TTree.h:368
Buffer base class used for serializing objects.
Definition: TBuffer.h:40
bool Set(EIOFeatures bits)
Set a specific IO feature.
Regular expression class.
Definition: TRegexp.h:31
TDirectory * fDirectory
! Pointer to directory holding this tree
Definition: TTree.h:109
constexpr Float_t kNEntriesResortInv
Definition: TTree.cxx:417
Int_t fMakeClass
! not zero when processing code generated by MakeClass
Definition: TTree.h:106
#define R__ASSERT(e)
Definition: TError.h:96
virtual TBasket * CreateBasket(TBranch *)
Create a basket for this tree and given branch.
Definition: TTree.cxx:3534
virtual Int_t CheckByteCount(UInt_t startpos, UInt_t bcnt, const TClass *clss)=0
#define gROOT
Definition: TROOT.h:410
TList * GetListOfDataMembers(Bool_t load=kTRUE)
Return list containing the TDataMembers of a class.
Definition: TClass.cxx:3617
Ssiz_t Index(const char *pat, Ssiz_t i=0, ECaseCompare cmp=kExact) const
Definition: TString.h:634
R__ALWAYS_INLINE Bool_t TestBit(UInt_t f) const
Definition: TObject.h:172
virtual Int_t WriteTObject(const TObject *obj, const char *name=0, Option_t *="", Int_t=0)
See TDirectoryFile::WriteTObject for details.
void ForceWriteInfo(TFile *file, Bool_t force=kFALSE)
Recursively mark streamer infos for writing to a file.
virtual TPrincipal * Principal(const char *varexp="", const char *selection="", Option_t *option="np", Long64_t nentries=kMaxEntries, Long64_t firstentry=0)=0
virtual void SetAutoSave(Long64_t autos=-300000000)
This function may be called at the start of a program to change the default value for fAutoSave (and ...
Definition: TTree.cxx:7939
Long64_t fEstimatedSize
Definition: TTree.h:242
virtual Int_t GetEntry(Long64_t entry=0, Int_t getall=0)
Read all branches of entry and return total number of bytes read.
Definition: TTree.cxx:5363
virtual Int_t ReadKeys(Bool_t=kTRUE)
Definition: TDirectory.h:174
virtual Int_t GetOffset() const
Definition: TLeaf.h:87
Basic string class.
Definition: TString.h:131
TVirtualCollectionProxy * GetCollectionProxy() const
Return the proxy describing the collection (if any).
Definition: TClass.cxx:2816
virtual void SetAddress(void *addobj)
Point this branch at an object.
virtual Int_t MakeProxy(const char *classname, const char *macrofilename=0, const char *cutfilename=0, const char *option=0, Int_t maxUnrolling=3)
Generate a skeleton analysis class for this Tree using TBranchProxy.
Definition: TTree.cxx:6497
virtual Long64_t GetEntryNumberWithBestIndex(Long64_t major, Long64_t minor) const =0
#define f(i)
Definition: RSha256.hxx:104
Short_t Min(Short_t a, Short_t b)
Definition: TMathBase.h:168
virtual void SetTargetClass(const char *name)
Set the name of the class of the in-memory object into which the data will loaded.
void ToLower()
Change string to lower-case.
Definition: TString.cxx:1100
static TBranch * R__FindBranchHelper(TObjArray *list, const char *branchname)
Search in the array for a branch matching the branch name, with the branch possibly expressed as a &#39;f...
Definition: TTree.cxx:4558
int Int_t
Definition: RtypesCore.h:41
bool Bool_t
Definition: RtypesCore.h:59
R__EXTERN TVirtualMutex * gROOTMutex
Definition: TROOT.h:57
virtual void Browse(TBrowser *)
Browse content of the TTree.
Definition: TTree.cxx:2479
constexpr std::array< decltype(std::declval< F >)(std::declval< int >))), N > make(F f)
virtual void SetFillStyle(Style_t fstyle)
Set the fill area style.
Definition: TAttFill.h:39
virtual void StopLearningPhase()
This is the counterpart of StartLearningPhase() and can be used to stop the learning phase...
static void SetMaxTreeSize(Long64_t maxsize=100000000000LL)
Set the maximum size in bytes of a Tree file (static function).
Definition: TTree.cxx:8771
TIOFeatures provides the end-user with the ability to change the IO behavior of data written via a TT...
Definition: TIOFeatures.hxx:62
Int_t fScanField
Number of runs before prompting in Scan.
Definition: TTree.h:83
virtual TTree * CloneTree(Long64_t nentries=-1, Option_t *option="")
Create a clone of this tree and copy nentries.
Definition: TTree.cxx:2971
TObject * At(Int_t idx) const
Definition: TObjArray.h:165
virtual TTree * CopyTree(const char *selection, Option_t *option="", Long64_t nentries=kMaxEntries, Long64_t firstentry=0)
Copy a tree with selection.
Definition: TTree.cxx:3522
virtual void KeepCircular()
Keep a maximum of fMaxEntries in memory.
Definition: TTree.cxx:6133
TArrayD fIndexValues
Sorted index values.
Definition: TTree.h:115
void SetAutoCreated(Bool_t val)
Definition: TTreeCache.h:164
virtual EDataType GetType() const =0
constexpr Int_t kNEntriesResort
Definition: TTree.cxx:416
virtual Long64_t GetEntries(const char *)=0
Int_t GetEntryOffsetLen() const
Definition: TBranch.h:183
Long64_t fMaxEntryLoop
Maximum number of entries to process.
Definition: TTree.h:89
TVirtualTreePlayer * GetPlayer()
Load the TTreePlayer (if not already done).
Definition: TTree.cxx:6023
virtual void SetMaxVirtualSize(Long64_t size=0)
Definition: TTree.h:550
virtual TSQLResult * Query(const char *varexp="", const char *selection="", Option_t *option="", Long64_t nentries=kMaxEntries, Long64_t firstentry=0)
Loop over entries and return a TSQLResult object containing entries following selection.
Definition: TTree.cxx:7183
Streamer around an arbitrary STL like container, which implements basic container functionality...
void ToHumanReadableSize(value_type bytes, Bool_t si, Double_t *coeff, const char **units)
Return the size expressed in &#39;human readable&#39; format.
Definition: StringConv.hxx:38
virtual Int_t AddBranch(TBranch *b, Bool_t subgbranches=kFALSE)
Add a branch to the list of branches to be stored in the cache this function is called by TBranch::Ge...
Definition: TTreeCache.cxx:307
virtual Int_t DeleteGlobal(void *obj)=0
virtual void SetupAddresses()
If the branch address is not set, we set all addresses starting with the top level parent branch...
Definition: TBranch.cxx:2862
virtual void SetTree(const TTree *tree)
If a list for a tree with such name and filename exists, sets it as the current sublist If not...
Long64_t fStartEntry
Definition: TTree.h:240
Iterator abstract base class.
Definition: TIterator.h:30
virtual Width_t GetLineWidth() const
Return the line width.
Definition: TAttLine.h:35
void Reset()
Definition: TCollection.h:252
void BypassStreamer(Bool_t bypass=kTRUE)
When the kBypassStreamer bit is set, the automatically generated Streamer can call directly TClass::W...
void SetBit(UInt_t f, Bool_t set)
Set or unset the user status bits as specified in f.
Definition: TObject.cxx:694
virtual void Reset(Option_t *option="")
Definition: TBranchRef.cxx:187
virtual Int_t Fit(const char *formula, const char *varexp, const char *selection, Option_t *option, Option_t *goption, Long64_t nentries, Long64_t firstentry)=0
virtual TObject * FindObject(const char *name) const
Delete a TObjLink object.
Definition: TList.cxx:574
virtual void Refresh()
Refresh contents of this tree and its branches from the current status on disk.
Definition: TTree.cxx:7577
Width_t GetHistLineWidth() const
Definition: TStyle.h:223
if object in a list can be deleted
Definition: TObject.h:58
virtual void SetFileNumber(Int_t number=0)
Set fFileNumber to number.
Definition: TTree.cxx:8737
virtual Double_t GetMinimum(const char *columname)
Return minimum of column with name columname.
Definition: TTree.cxx:5993
virtual void Print(Option_t *option="") const
Print the TRefTable branch.
Definition: TBranchRef.cxx:159
virtual void DirectoryAutoAdd(TDirectory *)
Called by TKey and TObject::Clone to automatically add us to a directory when we are read from a file...
Definition: TTree.cxx:3622
static Bool_t IsParallelUnzip()
Static function that tells wether the multithreading unzipping is activated.
static TFile * Open(const char *name, Option_t *option="", const char *ftitle="", Int_t compress=1, Int_t netopt=0)
Create / open a file.
Definition: TFile.cxx:3976
Int_t Length() const
Definition: TBuffer.h:96
virtual void SetTree(TTree *tree)
Definition: TBranch.h:242
virtual void SetDirectory(TDirectory *dir)
Add reference to directory dir. dir can be 0.
static void SetRefTable(TRefTable *table)
Static function setting the current TRefTable.
Definition: TRefTable.cxx:383
Bool_t fIMTFlush
! True if we are doing a multithreaded flush.
Definition: TTree.h:139
virtual Style_t GetMarkerStyle() const
Return the marker style.
Definition: TAttMarker.h:32
virtual void StartViewer()
Start the TTreeViewer on this tree.
Definition: TTree.cxx:8983
virtual Long64_t Merge(TCollection *list, Option_t *option="")
Merge the trees in the TList into this tree.
Definition: TTree.cxx:6623
Marker Attributes class.
Definition: TAttMarker.h:19
static TVirtualTreePlayer * TreePlayer(TTree *obj)
Static function returning a pointer to a Tree player.
virtual void SetBranchFolder()
virtual Style_t GetLineStyle() const
Return the line style.
Definition: TAttLine.h:34
virtual Int_t GetEntryWithIndex(Int_t major, Int_t minor=0)
Read entry corresponding to major and minor number.
Definition: TTree.cxx:5646
TList * fAliases
List of aliases for expressions based on the tree branches.
Definition: TTree.h:112
EFromHumanReadableSize FromHumanReadableSize(std::string_view str, T &value)
Convert strings like the following into byte counts 5MB, 5 MB, 5M, 3.7GB, 123b, 456kB, 3.7GiB, 5MiB with some amount of forgiveness baked into the parsing.
Definition: StringConv.hxx:86
Long64_t GetTotBytes(Option_t *option="") const
Return total number of bytes in the branch (excluding current buffer) if option ="*" includes all sub...
Definition: TBranch.cxx:1796
virtual Long64_t DrawSelect(const char *varexp, const char *selection, Option_t *option, Long64_t nentries, Long64_t firstentry)=0
TObject * Last() const
Return the object in the last filled slot. Returns 0 if no entries.
Definition: TObjArray.cxx:505
Bool_t fCacheDoClusterPrefetch
! true if cache is prefetching whole clusters
Definition: TTree.h:127
virtual Long64_t GetCacheSize() const
Definition: TTree.h:374
Bool_t IsBasic() const
Return true if data member is a basic type, e.g. char, int, long...
virtual TObjArray * GetListOfBranches()
Definition: TTree.h:409
Helper class to iterate over cluster of baskets.
Definition: TTree.h:235
TVirtualTreePlayer * fPlayer
! Pointer to current Tree player
Definition: TTree.h:121
virtual const char * ClassName() const
Returns name of class to which the object belongs.
Definition: TObject.cxx:128
Fill Area Attributes class.
Definition: TAttFill.h:19
void ImportClusterRanges(TTree *fromtree)
Appends the cluster range information stored in &#39;fromtree&#39; to this tree, including the value of fAuto...
Definition: TTree.cxx:6090
virtual void SetAutoFlush(Long64_t autof=-30000000)
This function may be called at the start of a program to change the default value for fAutoFlush...
Definition: TTree.cxx:7830
static TString Format(const char *fmt,...)
Static method which formats a string using a printf style format descriptor and return a TString...
Definition: TString.cxx:2286
Bool_t IsAutoCreated() const
Definition: TTreeCache.h:151
void Class()
Definition: Class.C:29
virtual Long64_t CopyEntries(TTree *tree, Long64_t nentries=-1, Option_t *option="")
Copy nentries from given tree to this tree.
Definition: TTree.cxx:3353
virtual Int_t SetBranchAddress(const char *bname, void *add, TBranch **ptr=0)
Change branch address, dealing with clone trees properly.
Definition: TTree.cxx:7982
void SetHistFillColor(Color_t color=1)
Definition: TStyle.h:356
Int_t fNfill
! Local for EntryLoop
Definition: TTree.h:101
UChar_t GetFeatures() const
virtual Bool_t IncludeRange(TLeaf *)
Definition: TLeaf.h:96
virtual Double_t GetValue(Int_t i=0) const
Definition: TLeaf.h:131
virtual void SetObject(const char *name, const char *title)
Change the name and title of this tree.
Definition: TTree.cxx:8808
virtual Bool_t IsWritable() const
Definition: TDirectory.h:163
The TNamed class is the base class for all named ROOT classes.
Definition: TNamed.h:29
virtual Long64_t GetEntryNumberWithBestIndex(Long64_t major, Long64_t minor=0) const
Return entry number corresponding to major and minor number.
Definition: TTree.cxx:5609
virtual Bool_t Notify()
This method must be overridden to handle object notification.
Definition: TObject.cxx:506
virtual Long64_t GetReadEntry() const
Definition: TTree.h:430
virtual const char * GetAlias(const char *aliasName) const
Returns the expanded value of the alias. Search in the friends if any.
Definition: TTree.cxx:4976
virtual TLeaf * GetLeaf(const char *name) const
Return pointer to the 1st Leaf named name in thisBranch.
Definition: TBranch.cxx:1645
virtual Long64_t LoadTree(Long64_t entry)
Set current entry.
Definition: TTree.cxx:6190
Bool_t fCacheUserSet
! true if the cache setting was explicitly given by user
Definition: TTree.h:128
virtual void SetTreeIndex(TVirtualIndex *index)
The current TreeIndex is replaced by the new index.
Definition: TTree.cxx:8870
virtual Long64_t GetEntry(Int_t index) const
Return value of entry at index in the list.
Definition: TEventList.cxx:222
Int_t fMaxClusterRange
! Memory allocated for the cluster range.
Definition: TTree.h:87
static Int_t GetBranchStyle()
Static function returning the current branch style.
Definition: TTree.cxx:5131
virtual Int_t BuildIndex(const char *majorname, const char *minorname="0")
Build a Tree Index (default is TTreeIndex).
Definition: TTree.cxx:2504
virtual Int_t UnbinnedFit(const char *funcname, const char *varexp, const char *selection="", Option_t *option="", Long64_t nentries=kMaxEntries, Long64_t firstentry=0)
Unbinned fit of one or more variable(s) from a tree.
Definition: TTree.cxx:9249
virtual Bool_t SetMakeClass(Bool_t decomposeObj=kTRUE)
Set the branch in a mode where the object are decomposed (Also known as MakeClass mode)...
Definition: TBranch.cxx:2503
virtual TBranch * BranchOld(const char *name, const char *classname, void *addobj, Int_t bufsize=32000, Int_t splitlevel=1)
Create a new TTree BranchObject.
Definition: TTree.cxx:1944
Bool_t IsLoaded() const
Return true if the shared library of this class is currently in the a process&#39;s memory.
Definition: TClass.cxx:5642
Set if we own the value buffer and so must delete it ourselves.
Definition: TLeaf.h:59
virtual void Show(Long64_t entry=-1, Int_t lenmax=20)
Print values of all active leaves for entry.
Definition: TTree.cxx:8909
virtual TBranch * FindBranch(const char *name)
Find the immediate sub-branch with passed name.
Definition: TBranch.cxx:989
TBranchRef * fBranchRef
Branch supporting the TRefTable (if any)
Definition: TTree.h:123
virtual Int_t MakeClass(const char *classname=0, Option_t *option="")
Generate a skeleton analysis class for this tree.
Definition: TTree.cxx:6336
virtual const char * Getenv(const char *env)
Get environment variable.
Definition: TSystem.cxx:1638
virtual TClusterIterator GetClusterIterator(Long64_t firstentry)
Return an iterator over the cluster of baskets starting at firstentry.
Definition: TTree.cxx:5193
TIOFeatures * fIOFeatures
virtual Int_t GetN() const
Definition: TEventList.h:56
virtual void SetMarkerColor(Color_t mcolor=1)
Set the marker color.
Definition: TAttMarker.h:38
Style_t GetHistFillStyle() const
Definition: TStyle.h:221
const Int_t kDoNotProcess
Definition: TBranch.h:50
UInt_t fFriendLockStatus
! Record which method is locking the friend recursion
Definition: TTree.h:124
virtual void Append(TObject *obj, Bool_t replace=kFALSE)
Append object to this directory.
Long_t GetThisOffset() const
Definition: TRealData.h:55
virtual Int_t MakeClass(const char *classname, const char *option)=0
Int_t fTimerInterval
Timer interval in milliseconds.
Definition: TTree.h:82
virtual Size_t GetMarkerSize() const
Return the marker size.
Definition: TAttMarker.h:33
virtual TFriendElement * AddFriend(const char *treename, const char *filename="")
Add a TFriendElement to the list of friends.
Definition: TTree.cxx:1244
TDataType * GetDataType() const
Definition: TDataMember.h:74
virtual Long64_t Scan(const char *varexp="", const char *selection="", Option_t *option="", Long64_t nentries=kMaxEntries, Long64_t firstentry=0)
Loop over tree entries and print entries passing selection.
Definition: TTree.cxx:7733
Long64_t fFlushedBytes
Number of auto-flushed bytes.
Definition: TTree.h:80
virtual Int_t GetLenType() const
Definition: TLeaf.h:83
TObjArray * GetListOfBranches()
Definition: TBranch.h:201
UInt_t fNEntriesSinceSorting
! Number of entries processed since the last re-sorting of branches
Definition: TTree.h:130
Ssiz_t First(char c) const
Find first occurrence of a character c.
Definition: TString.cxx:487
Specialization of TTreeCache for parallel Unzipping.
virtual TList * GetList() const
Definition: TDirectory.h:149
Book space in a file, create I/O buffers, to fill them, (un)compress them.
Definition: TKey.h:24
virtual void Delete(Option_t *option="")
Delete an object from the file.
Definition: TKey.cxx:534
virtual Double_t GetMaximum(const char *columname)
Return maximum of column with name columname.
Definition: TTree.cxx:5953
void Set(Int_t n)
Set size of this array to n ints.
Definition: TArrayI.cxx:105
virtual void RemoveFriend(TTree *)
Remove a friend from the list of friends.
Definition: TTree.cxx:7616
virtual void SetAddress(void *add=0)
Definition: TLeaf.h:133
TCollection * GetListOfFolders() const
Definition: TFolder.h:55
virtual TList * GetUserInfo()
Return a pointer to the list containing user objects associated to this tree.
Definition: TTree.cxx:6074
std::atomic< Long64_t > fIMTZipBytes
! Zip bytes for the IMT flush baskets.
Definition: TTree.h:141
virtual void SetCacheLearnEntries(Int_t n=10)
Interface to TTreeCache to set the number of entries for the learning phase.
Definition: TTree.cxx:8449
A branch containing and managing a TRefTable for TRef autoloading.
Definition: TBranchRef.h:29
Long64_t fZipBytes
Total number of bytes in all branches after compression.
Definition: TTree.h:78
virtual TFile * GetFile() const
Definition: TDirectory.h:147
Long64_t fDebugMax
! Last entry number to debug
Definition: TTree.h:104
virtual TBranch * BranchImp(const char *branchname, const char *classname, TClass *ptrClass, void *addobj, Int_t bufsize, Int_t splitlevel)
Same as TTree::Branch() with added check that addobj matches className.
Definition: TTree.cxx:1450
R__ALWAYS_INLINE Bool_t IsZombie() const
Definition: TObject.h:134
virtual void ResetAddress()
Set branch address to zero and free all allocated memory.
virtual TTree * GetTree() const
Definition: TTree.h:438
virtual void SetEventList(TEventList *list)
This function transfroms the given TEventList into a TEntryList The new TEntryList is owned by the TT...
Definition: TTree.cxx:8653
void Expand(Int_t newsize, Bool_t copy=kTRUE)
Expand (or shrink) the I/O buffer to newsize bytes.
Definition: TBuffer.cxx:211
virtual Int_t GetTreeNumber() const
Definition: TTree.h:440
void UseCurrentStyle()
Replace current attributes by current style.
Definition: TTree.cxx:9261
A specialized string object used for TTree selections.
Definition: TCut.h:25
A doubly linked list.
Definition: TList.h:44
virtual void ResetAfterMerge(TFileMergeInfo *)
Reset a Branch.
Definition: TBranch.cxx:2174
virtual TBranch * GetBranch(const char *name)
Return pointer to the branch with the given name in this tree or its friends.
Definition: TTree.cxx:5017
Bool_t fCacheDoAutoInit
! true if cache auto creation or resize check is needed
Definition: TTree.h:126
Int_t GetRecordHeader(char *buf, Long64_t first, Int_t maxbytes, Int_t &nbytes, Int_t &objlen, Int_t &keylen)
Read the logical record header starting at a certain postion.
Definition: TFile.cxx:1252
Int_t GetType() const
Definition: TDataType.h:68
Int_t Fill()
Definition: TBranch.h:162
TObjArray fLeaves
Direct pointers to individual branch leaves.
Definition: TTree.h:111
Long64_t * fClusterRangeEnd
[fNClusterRange] Last entry of a cluster range.
Definition: TTree.h:94
virtual void SetLineColor(Color_t lcolor)
Set the line color.
Definition: TAttLine.h:40
void BuildRealData(void *pointer=0, Bool_t isTransient=kFALSE)
Build a full list of persistent data members.
Definition: TClass.cxx:1942
Using a TBrowser one can browse all ROOT objects.
Definition: TBrowser.h:37
This class provides a simple interface to execute the same task multiple times in parallel...
Int_t fNClusterRange
Number of Cluster range in addition to the one defined by &#39;AutoFlush&#39;.
Definition: TTree.h:86
virtual Long64_t GetEntryNumber(Long64_t entry) const
Return entry number corresponding to entry.
Definition: TTree.cxx:5584
Int_t fN
Definition: TArray.h:38
TEntryList * fEntryList
! Pointer to event selection list (if one)
Definition: TTree.h:114
virtual Int_t GetLen() const
Return the number of effective elements of this leaf, for the current entry.
Definition: TLeaf.cxx:310
virtual Long64_t GetAutoSave() const
Definition: TTree.h:369
virtual void SetEntryRange(Long64_t emin, Long64_t emax)
Set the minimum and maximum entry number to be processed this information helps to optimize the numbe...
Int_t GetReadBasket() const
Definition: TBranch.h:191
virtual Int_t Write(const char *name=0, Int_t option=0, Int_t bufsize=0)
Write this object to the current directory.
Definition: TTree.cxx:9298
virtual void SetEstimate(Long64_t nentries=1000000)
Set number of entries to estimate variable limits.
Definition: TTree.cxx:8694
virtual void SetOffset(Int_t offset=0)
Definition: TBranch.h:240
virtual TObject * First() const
Return the first object in the list. Returns 0 when list is empty.
Definition: TList.cxx:655
virtual Long64_t Process(const char *filename, Option_t *option="", Long64_t nentries=kMaxEntries, Long64_t firstentry=0)=0
virtual void UpdateFormulaLeaves()=0
virtual Int_t DropBranch(TBranch *b, Bool_t subbranches=kFALSE)
Remove a branch to the list of branches to be stored in the cache this function is called by TBranch:...
Definition: TTreeCache.cxx:482
void SetHistFillStyle(Style_t styl=0)
Definition: TStyle.h:358
void SetCompressionSettings(Int_t settings=1)
Set compression settings.
Definition: TBranch.cxx:2381
R__EXTERN TSystem * gSystem
Definition: TSystem.h:540
Long64_t fChainOffset
! Offset of 1st entry of this Tree in a TChain
Definition: TTree.h:97
~TFriendLock()
Restore the state of tree the same as before we set the lock.
Definition: TTree.cxx:509
Long64_t * fClusterSize
[fNClusterRange] Number of entries in each cluster for a given range.
Definition: TTree.h:95
virtual void WriteStreamerInfo()
Write the list of TStreamerInfo as a single object in this file The class Streamer description for al...
Definition: TFile.cxx:3684
virtual void SetFillColor(Color_t fcolor)
Set the fill area color.
Definition: TAttFill.h:37
Basic data type descriptor (datatype information is obtained from CINT).
Definition: TDataType.h:44
void TFriendElement__SetTree(TTree *tree, TList *frlist)
Set the fTree member for all friend elements.
Definition: TTree.cxx:9056
auto * a
Definition: textangle.C:12
virtual Long64_t GetEntryNumberWithIndex(Long64_t major, Long64_t minor=0) const
Return entry number corresponding to major and minor number.
Definition: TTree.cxx:5629
TVirtualPerfStats * fPerfStats
! pointer to the current perf stats object
Definition: TTree.h:119
TClass * GetActualClass(const void *object) const
Return a pointer the the real class of the object.
Definition: TClass.cxx:2527
virtual TIterator * MakeIterator(Bool_t dir=kIterForward) const =0
TTree * GetTree() const
Definition: TTreeCache.h:150
virtual TObject * RemoveAt(Int_t idx)
Remove object at index idx.
Definition: TObjArray.cxx:678
virtual Int_t ReadTObject(TObject *, const char *)
Definition: TDirectory.h:175
virtual TObject * Remove(TObject *obj)
Remove object from the list.
Definition: TList.cxx:818
Long64_t fReadEntry
! Number of the entry being processed
Definition: TTree.h:98
virtual TVirtualIndex * GetTreeIndex() const
Definition: TTree.h:439
virtual Bool_t HasPointers() const =0
virtual Bool_t InheritsFrom(const char *classname) const
Returns kTRUE if object inherits from class "classname".
Definition: TObject.cxx:443
Int_t GetWriteBasket() const
Definition: TBranch.h:193
virtual ~TTree()
Destructor.
Definition: TTree.cxx:882
TDataMember * GetDataMember() const
Definition: TRealData.h:53
Collection abstract base class.
Definition: TCollection.h:63
void Destructor(void *obj, Bool_t dtorOnly=kFALSE)
Explicitly call destructor for object.
Definition: TClass.cxx:5149
TList * fUserInfo
pointer to a list of user objects associated to this Tree
Definition: TTree.h:120
TObjArray fBranches
List of Branches.
Definition: TTree.h:110
void Form(const char *fmt,...)
Formats a string using a printf style format descriptor.
Definition: TString.cxx:2264
unsigned int UInt_t
Definition: RtypesCore.h:42
Int_t GetEntriesFast() const
Definition: TObjArray.h:64
virtual void Error(const char *method, const char *msgfmt,...) const
Issue error message.
Definition: TObject.cxx:880
TFile * GetCurrentFile() const
Return pointer to the current file.
Definition: TTree.cxx:5205
virtual Long64_t GetN() const =0
virtual Long64_t GetEntry(Int_t index)
Return the number of the entry #index of this TEntryList in the TTree or TChain See also Next()...
Definition: TEntryList.cxx:653
Ssiz_t Length() const
Definition: TString.h:405
virtual void MakeFree(Long64_t first, Long64_t last)
Mark unused bytes on the file.
Definition: TFile.cxx:1433
virtual void Append(TObject *obj, Bool_t replace=kFALSE)
Append object to this directory.
Definition: TDirectory.cxx:190
virtual TLeaf * GetLeafCount() const
If this leaf stores a variable-sized array or a multi-dimensional array whose last dimension has vari...
Definition: TLeaf.h:74
Manages buffers for branches of a Tree.
Definition: TBasket.h:34
virtual void * GetValuePointer() const
Definition: TLeaf.h:88
TSubString Strip(EStripType s=kTrailing, char c=' ') const
Return a substring of self stripped at beginning and/or end.
Definition: TString.cxx:1081
Int_t GetMaxBaskets() const
Definition: TBranch.h:203
A TEventList object is a list of selected events (entries) in a TTree.
Definition: TEventList.h:31
virtual TLeaf * FindLeaf(const char *name)
Find leaf..
Definition: TTree.cxx:4678
The TRealData class manages the effective list of all data members for a given class.
Definition: TRealData.h:30
virtual Int_t GetEntry(Long64_t entry=0, Int_t getall=0)
Read all leaves of entry and return total number of bytes read.
Definition: TBranch.cxx:1310
Bool_t CanIgnoreTObjectStreamer()
Definition: TClass.h:365
TArrayI fIndex
Index of sorted values.
Definition: TTree.h:116
The ROOT global object gROOT contains a list of all defined classes.
Definition: TClass.h:75
virtual void SetMarkerStyle(Style_t mstyle=1)
Set the marker style.
Definition: TAttMarker.h:40
static void SetLearnEntries(Int_t n=10)
Static function to set the number of entries to be used in learning mode The default value for n is 1...
TFileCacheRead * GetCacheRead(const TObject *tree=0) const
Return a pointer to the current read cache.
Definition: TFile.cxx:1215
ROOT::ESTLType GetCollectionType() const
Return the &#39;type&#39; of the STL the TClass is representing.
Definition: TClass.cxx:2805
virtual TObject * At(Int_t idx) const
Returns the object at position idx. Returns 0 if idx is out of range.
Definition: TList.cxx:354
Bool_t fIMTEnabled
! true if implicit multi-threading is enabled for this tree
Definition: TTree.h:129
Option_t * GetOption() const
Returns the object option stored in the list.
Definition: TTree.cxx:9399
virtual TBranchRef * GetBranchRef() const
Definition: TTree.h:371
Bool_t InheritsFrom(const char *cl) const
Return kTRUE if this class inherits from a class with name "classname".
Definition: TClass.cxx:4688
void SetName(const char *name)
Definition: TCollection.h:204
virtual void ResetBranchAddress(TBranch *)
Tell all of our branches to set their addresses to zero.
Definition: TTree.cxx:7704
ROOT::TIOFeatures GetIOFeatures() const
Returns the current set of IO settings.
Definition: TTree.cxx:5793
Bool_t fDirection
iteration direction
Definition: TTree.h:598
TEventList * fEventList
! Pointer to event selection list (if one)
Definition: TTree.h:113
TString fName
Definition: TNamed.h:32
virtual TBranch * Bronch(const char *name, const char *classname, void *addobj, Int_t bufsize=32000, Int_t splitlevel=99)
Create a new TTree BranchElement.
Definition: TTree.cxx:2274
virtual const char * GetTreeName() const
virtual Bool_t GetBranchStatus(const char *branchname) const
Return status of branch with name branchname.
Definition: TTree.cxx:5116
if object destructor must call RecursiveRemove()
Definition: TObject.h:60
virtual void SetMarkerSize(Size_t msize=1)
Set the marker size.
Definition: TAttMarker.h:41
Long64_t fMaxEntries
Maximum number of entries in case of circular buffers.
Definition: TTree.h:88
void AddClone(TTree *)
Add a cloned tree to our list of trees to be notified whenever we change our branch addresses or when...
Definition: TTree.cxx:1156
void MarkEventCluster()
Mark the previous event as being at the end of the event cluster.
Definition: TTree.cxx:7892
void SetIOFeatures(TIOFeatures &features)
Definition: TBranch.h:238
virtual void KeepCircular(Long64_t maxEntries)
keep a maximum of fMaxEntries in memory
Definition: TBranch.cxx:1859
Each class (see TClass) has a linked list of its base class(es).
Definition: TBaseClass.h:33
char GetNewlineValue(std::istream &inputStream)
Determine which newline this file is using.
Definition: TTree.cxx:7253
virtual TObjLink * FirstLink() const
Definition: TList.h:108
A Branch for the case of an object.
virtual Long64_t GetBasketSeek(Int_t basket) const
Return address of basket in the file.
Definition: TBranch.cxx:1253
#define Printf
Definition: TGeoToOCC.h:18
virtual Int_t DropBranchFromCache(const char *bname, Bool_t subbranches=kFALSE)
Remove the branch with name &#39;bname&#39; from the Tree cache.
Definition: TTree.cxx:1079
void InitializeBranchLists(bool checkLeafCount)
Divides the top-level branches into two vectors: (i) branches to be processed sequentially and (ii) b...
Definition: TTree.cxx:5505
Long64_t fAutoSave
Autosave tree when fAutoSave entries written or -fAutoSave (compressed) bytes produced.
Definition: TTree.h:91
const Bool_t kFALSE
Definition: RtypesCore.h:88
virtual void SaveSelf(Bool_t=kFALSE)
Definition: TDirectory.h:181
virtual void SetBasketSize(Int_t buffsize)
Set the basket size The function makes sure that the basket size is greater than fEntryOffsetlen.
Definition: TBranch.cxx:2305
virtual Int_t CheckBranchAddressType(TBranch *branch, TClass *ptrClass, EDataType datatype, Bool_t ptr)
Check whether or not the address described by the last 3 parameters matches the content of the branch...
Definition: TTree.cxx:2707
virtual Color_t GetLineColor() const
Return the line color.
Definition: TAttLine.h:33
virtual void SetDebug(Int_t level=1, Long64_t min=0, Long64_t max=9999999)
Set the debug level and the debug range.
Definition: TTree.cxx:8512
virtual Long64_t Process(const char *filename, Option_t *option="", Long64_t nentries=kMaxEntries, Long64_t firstentry=0)
Process this tree executing the TSelector code in the specified filename.
Definition: TTree.cxx:7120
static unsigned int total
static const Ssiz_t kNPOS
Definition: TString.h:264
#define SafeDelete(p)
Definition: RConfig.h:529
TString & Remove(Ssiz_t pos)
Definition: TString.h:668
long Long_t
Definition: RtypesCore.h:50
virtual Int_t ReadClassBuffer(const TClass *cl, void *pointer, const TClass *onfile_class=0)=0
int Ssiz_t
Definition: RtypesCore.h:63
virtual void DropBuffers(Int_t nbytes)
Drop branch buffers to accommodate nbytes below MaxVirtualsize.
Definition: TTree.cxx:4306
virtual void SetMakeClass(Int_t make)
Set all the branches in this TTree to be in decomposed object mode (also known as MakeClass mode)...
Definition: TTree.cxx:8751
virtual void SetWeight(Double_t w=1, Option_t *option="")
Set tree weight.
Definition: TTree.cxx:8898
Color_t GetHistFillColor() const
Definition: TStyle.h:219
Version_t GetClassVersion() const
Definition: TClass.h:391
TObjArray * Tokenize(const TString &delim) const
This function is used to isolate sequential tokens in a TString.
Definition: TString.cxx:2172
Long64_t Next()
Move on to the next cluster and return the starting entry of this next cluster.
Definition: TTree.cxx:614
TIterator * MakeIterator(Bool_t dir=kIterForward) const
Returns an array iterator.
Definition: TObjArray.cxx:633
virtual void SetDirectory(TDirectory *dir)
Change the tree&#39;s directory.
Definition: TTree.cxx:8550
virtual Long64_t LoadTreeFriend(Long64_t entry, TTree *T)
Load entry on behalf of our master tree, we may use an index.
Definition: TTree.cxx:6286
virtual void SetEstimate(Long64_t n)=0
TObject * UncheckedAt(Int_t i) const
Definition: TObjArray.h:89
virtual void Print(Option_t *option="") const
Print cache statistics.
Long64_t fMaxVirtualSize
Maximum total size of buffers kept in memory.
Definition: TTree.h:90
virtual TObject * Remove(TObject *)
Remove an object from the in-memory list.
virtual Int_t GetMaximum() const
Definition: TLeaf.h:84
#define ClassImp(name)
Definition: Rtypes.h:359
virtual void StartViewer(Int_t ww, Int_t wh)=0
virtual void SetEntryList(TEntryList *list, Option_t *opt="")
Set an EntryList.
Definition: TTree.cxx:8630
TIterator & operator=(const TIterator &rhs)
Overridden assignment operator. Does NOT copy the &#39;cursor&#39; location!
Definition: TTree.cxx:9337
virtual void ResetAddress()
Reset the address of the branch.
Definition: TBranch.cxx:2227
virtual TKey * GetKey(const char *, Short_t=9999) const
Definition: TDirectory.h:148
double Double_t
Definition: RtypesCore.h:55
virtual void Clear(Option_t *option="")
Clear entries in the TRefTable.
Definition: TBranchRef.cxx:95
Ssiz_t Last(char c) const
Find last occurrence of a character c.
Definition: TString.cxx:876
static TRefTable * GetRefTable()
Static function returning the current TRefTable.
Definition: TRefTable.cxx:287
Long64_t GetCacheAutoSize(Bool_t withDefault=kFALSE) const
Used for automatic sizing of the cache.
Definition: TTree.cxx:5143
void SetHistLineStyle(Style_t styl=0)
Definition: TStyle.h:359
Long64_t fTotBytes
Total number of bytes in all branches before compression.
Definition: TTree.h:77
virtual void WaitFinishPrefetch()
Data member is a pointer to an array of basic types.
Definition: TLeaf.h:58
Color_t GetHistLineColor() const
Definition: TStyle.h:220
std::vector< TBranch * > fSeqBranches
! Branches to be processed sequentially when IMT is on
Definition: TTree.h:132
Describe directory structure in memory.
Definition: TDirectory.h:34
virtual void SetPerfStats(TVirtualPerfStats *perf)
Set perf stats.
Definition: TTree.cxx:8853
std::vector< std::pair< Long64_t, TBranch * > > fSortedBranches
! Branches to be processed in parallel when IMT is on, sorted by average task time ...
Definition: TTree.h:131
TDirectory * GetDirectory() const
Definition: TTree.h:383
virtual const char * GetClassName() const
Return the name of the user class whose content is stored in this branch, if any. ...
static void TBranch__SetTree(TTree *tree, TObjArray &branches)
Set the fTree member for all branches and sub branches.
Definition: TTree.cxx:9032
void SortBranchesByTime()
Sorts top-level branches by the last average task time recorded per branch.
Definition: TTree.cxx:5553
R__EXTERN TEnv * gEnv
Definition: TEnv.h:171
virtual Int_t GetBufferSize() const
unsigned long long ULong64_t
Definition: RtypesCore.h:70
virtual Long64_t ReadFile(const char *filename, const char *branchDescriptor="", char delimiter=' ')
Create or simply read branches from filename.
Definition: TTree.cxx:7234
TList * GetListOfRealData() const
Definition: TClass.h:418
Bool_t HasDataMemberInfo() const
Definition: TClass.h:378
TNamed()
Definition: TNamed.h:36
Long64_t fAutoFlush
Auto-flush tree when fAutoFlush entries written or -fAutoFlush (compressed) bytes produced...
Definition: TTree.h:92
Int_t GetNbytes() const
Definition: TKey.h:82
virtual void ResetBranchAddresses()
Tell all of our branches to drop their current objects and allocate new ones.
Definition: TTree.cxx:7714
virtual void Draw(Option_t *opt)
Default Draw method for all objects.
Definition: TTree.h:357
virtual void SetObject(void *objadd)
Set object this branch is pointing to.
TCanvas * style()
Definition: style.C:1
int nentries
Definition: THbookFile.cxx:89
A TRefTable maintains the association between a referenced object and the parent object supporting th...
Definition: TRefTable.h:35
EDataType
Definition: TDataType.h:28
virtual Color_t GetFillColor() const
Return the fill area color.
Definition: TAttFill.h:30
Int_t fDefaultEntryOffsetLen
Initial Length of fEntryOffset table in the basket buffers.
Definition: TTree.h:85
Bool_t Contains(const char *pat, ECaseCompare cmp=kExact) const
Definition: TString.h:619
static constexpr double s
#define R__LOCKGUARD(mutex)
void Browse(TBrowser *b)
Browse this collection (called by TBrowser).
TObjArray * GetListOfLeaves()
Definition: TBranch.h:202
Long64_t fEstimate
Number of entries to estimate histogram limits.
Definition: TTree.h:93
Int_t BufferSize() const
Definition: TBuffer.h:94
static void SetUnzipRelBufferSize(Float_t relbufferSize)
static function: Sets the unzip relatibe buffer size
UInt_t fMethodBit
Definition: TTree.h:170
Helper class to prevent infinite recursion in the usage of TTree Friends.
Definition: TTree.h:166
static TClass * GetClass(const char *name, Bool_t load=kTRUE, Bool_t silent=kFALSE)
Static method returning pointer to TClass of the specified class name.
Definition: TClass.cxx:2887
virtual Int_t SetBufferSize(Int_t buffersize)
Change the underlying buffer size of the cache.
virtual Int_t SetCacheSize(Long64_t cachesize=-1)
Set maximum size of the file cache .
Definition: TTree.cxx:8270
Int_t fDebug
! Debug level
Definition: TTree.h:102
EOnIndexError
Definition: TTree.cxx:3250
TCanvas * slash()
Definition: slash.C:1
virtual Int_t UnbinnedFit(const char *formula, const char *varexp, const char *selection, Option_t *option, Long64_t nentries, Long64_t firstentry)=0
UInt_t GetCheckSum()
Int_t SetCacheSizeAux(Bool_t autocache=kTRUE, Long64_t cacheSize=0)
Set the size of the file cache and create it if possible.
Definition: TTree.cxx:8296
double Stat_t
Definition: RtypesCore.h:73
virtual void SetLineStyle(Style_t lstyle)
Set the line style.
Definition: TAttLine.h:42
virtual Long64_t GetEntries() const
Definition: TTree.h:384
Int_t GetKeylen() const
Definition: TKey.h:80
Bool_t IsPersistent() const
Definition: TDataMember.h:89
Bool_t IsNull() const
Definition: TString.h:402
TClass * GetClass() const
Definition: TClonesArray.h:56
virtual TObject * Clone(const char *newname="") const
Make a clone of an object using the Streamer facility.
Definition: TNamed.cxx:74
virtual void SetBasketSize(const char *bname, Int_t buffsize=16000)
Set a branch&#39;s basket size.
Definition: TTree.cxx:7955
virtual TFile * GetFile()
Return pointer to TFile containing this friend TTree.
virtual TBranch * BranchRef()
Build the optional branch supporting the TRefTable.
Definition: TTree.cxx:2198
virtual void ResetAfterMerge(TFileMergeInfo *)
Resets the state of this TTree after a merge (keep the customization but forget the data)...
Definition: TTree.cxx:7673
virtual Bool_t SetAlias(const char *aliasName, const char *aliasFormula)
Set a tree variable alias.
Definition: TTree.cxx:7775
Int_t fFileNumber
! current file number (if file extensions)
Definition: TTree.h:107
Mother of all ROOT objects.
Definition: TObject.h:37
Int_t fUpdate
Update frequency for EntryLoop.
Definition: TTree.h:84
virtual void ReadValue(std::istream &, Char_t=' ')
Definition: TLeaf.h:104
Bool_t IsReading() const
Definition: TStyle.h:277
virtual Long64_t GetEND() const
Definition: TFile.h:214
A Branch handling STL collection of pointers (vectors, lists, queues, sets and multisets) while stori...
Definition: TBranchSTL.h:22
static void * ReAlloc(void *vp, size_t size)
Reallocate (i.e.
Definition: TStorage.cxx:183
virtual Int_t Branch(TCollection *list, Int_t bufsize=32000, Int_t splitlevel=99, const char *name="")
Create one branch for each element in the collection.
Definition: TTree.cxx:1711
TDirectory * fOutputDirectory
virtual void SetEntryOffsetLen(Int_t len, Bool_t updateSubBranches=kFALSE)
Update the default value for the branch&#39;s fEntryOffsetLen if and only if it was already non zero (and...
Definition: TBranch.cxx:2397
virtual Long64_t Scan(const char *varexp, const char *selection, Option_t *option, Long64_t nentries, Long64_t firstentry)=0
virtual const char * GetTitle() const
Returns title of object.
Definition: TObject.cxx:401
virtual void SetFile(TFile *file=0)
Set file where this branch writes/reads its buffers.
Definition: TBranch.cxx:2439
Long64_t fEntries
Number of entries.
Definition: TTree.h:75
Bool_t IsTObject() const
Return kTRUE is the class inherits from TObject.
Definition: TClass.cxx:5668
TList * fClones
! List of cloned trees which share our addresses
Definition: TTree.h:122
virtual void Refresh(TBranch *b)
Refresh this branch using new information in b This function is called by TTree::Refresh.
Definition: TBranch.cxx:2084
Long64_t GetEntries() const
Definition: TBranch.h:206
Style_t GetHistLineStyle() const
Definition: TStyle.h:222
virtual Int_t MakeSelector(const char *selector=0, Option_t *option="")
Generate skeleton selector class for this tree.
Definition: TTree.cxx:6551
An array of clone (identical) objects.
Definition: TClonesArray.h:32
TBuffer * GetTransientBuffer(Int_t size)
Returns the transient buffer currently used by this TTree for reading/writing baskets.
Definition: TTree.cxx:974
virtual Long64_t GetTotBytes() const
Definition: TTree.h:437
Class implementing or helping the various TTree cloning method.
Definition: TTreeCloner.h:38
virtual Bool_t cd(const char *path=0)
Change current directory to "this" directory.
Definition: TDirectory.cxx:497
virtual Int_t DropBuffers()
Drop buffers of this basket if it is not the current basket.
Definition: TBasket.cxx:163
ROOT::ESTLType IsSTLContainer()
Return which type (if any) of STL container the data member is.
Definition: TBaseClass.cxx:101
Abstract base class defining the interface for the plugins that implement Draw, Scan, Process, MakeProxy, etc.
A Branch for the case of an array of clone objects.
Definition: TBranchClones.h:29
virtual void Add(TObject *obj)
Definition: TList.h:87
auto * l
Definition: textangle.C:4
Bool_t IsImplicitMTEnabled()
Returns true if the implicit multi-threading in ROOT is enabled.
Definition: TROOT.cxx:607
TClusterIterator(TTree *tree, Long64_t firstEntry)
Regular constructor.
Definition: TTree.cxx:526
virtual void RecursiveRemove(TObject *obj)
Remove object from this collection and recursively remove the object from all other objects (and coll...
Definition: TList.cxx:760
Definition: file.py:1
Int_t GetClassVersion()
const char * GetArrayIndex() const
If the data member is pointer and has a valid array size in its comments GetArrayIndex returns a stri...
Short_t Max(Short_t a, Short_t b)
Definition: TMathBase.h:200
virtual void Reset(Option_t *option="")
Reset a Branch.
Definition: TBranch.cxx:2133
A TFriendElement TF describes a TTree object TF in a file.
virtual Long64_t GetZipBytes() const
Definition: TTree.h:465
Long64_t fNextEntry
Definition: TTree.h:241
virtual TObject * Next()=0
virtual const char * GetMinorName() const =0
Iterator on all the leaves in a TTree and its friend.
Definition: TTree.h:592
virtual TBranch * BronchExec(const char *name, const char *classname, void *addobj, Bool_t isptrptr, Int_t bufsize, Int_t splitlevel)
Helper function implementing TTree::Bronch and TTree::Branch(const char *name, T &obj);.
Definition: TTree.cxx:2282
virtual void RecursiveRemove(TObject *obj)
Make sure that obj (which is being deleted or will soon be) is no longer referenced by this TTree...
Definition: TTree.cxx:7546
you should not use this method at all Int_t Int_t Double_t Double_t Double_t Int_t Double_t Double_t Double_t Double_t b
Definition: TRolke.cxx:630
virtual Int_t LoadBaskets()
Baskets associated to this branch are forced to be in memory.
Definition: TBranch.cxx:1885
#define snprintf
Definition: civetweb.c:1351
TTree * GetTree() const
Definition: TBranch.h:207
#define gPad
Definition: TVirtualPad.h:285
Int_t GetEntries() const
Return the number of objects in array (i.e.
Definition: TObjArray.cxx:522
virtual void SetCircular(Long64_t maxEntries)
Enable/Disable circularity for this tree.
Definition: TTree.cxx:8476
R__EXTERN Int_t gDebug
Definition: Rtypes.h:86
#define c(i)
Definition: RSha256.hxx:101
Int_t GetBufferSize() const
Definition: TBasket.h:110
virtual void Reset(Option_t *option="")
Reset baskets, buffers and entries count in all branches and leaves.
Definition: TTree.cxx:7642
virtual const char * GetMajorName() const =0
Definition: tree.py:1
std::atomic< Long64_t > fTotalBuffers
! Total number of bytes in branch buffers
Definition: TTree.h:99
virtual char * GetAddress() const
Definition: TBranch.h:169
TObject * fNotify
! Object to be notified when loading a Tree
Definition: TTree.h:108
virtual Int_t SetCacheEntryRange(Long64_t first, Long64_t last)
interface to TTreeCache to set the cache entry range
Definition: TTree.cxx:8415
void Add(TObject *obj)
Definition: TObjArray.h:73
Double_t Atof() const
Return floating-point value contained in string.
Definition: TString.cxx:1962
A TTree object has a header with a name and a title.
Definition: TTree.h:70
#define gDirectory
Definition: TDirectory.h:213
TVirtualIndex * fTreeIndex
Pointer to the tree Index (if any)
Definition: TTree.h:117
TFriendLock & operator=(const TFriendLock &)
Assignment operator.
Definition: TTree.cxx:496
Int_t SetBranchAddressImp(TBranch *branch, void *addr, TBranch **ptr)
Change branch address, dealing with clone trees properly.
Definition: TTree.cxx:8039
virtual TVirtualIndex * BuildIndex(const TTree *T, const char *majorname, const char *minorname)=0
void ResetBit(UInt_t f)
Definition: TObject.h:171
unsigned char UChar_t
Definition: RtypesCore.h:34
virtual void SetDefaultEntryOffsetLen(Int_t newdefault, Bool_t updateExisting=kFALSE)
Update the default value for the branch&#39;s fEntryOffsetLen.
Definition: TTree.cxx:8524
virtual TObject ** GetObjectRef(const TObject *obj) const =0
const ROOT::Detail::TSchemaRuleSet * GetSchemaRules() const
Return the set of the schema rules if any.
Definition: TClass.cxx:1843
TObject * Next()
Go the next friend element.
Definition: TTree.cxx:9360
Definition: first.py:1
virtual Color_t GetMarkerColor() const
Return the marker color.
Definition: TAttMarker.h:31
virtual void DropBaskets()
Remove some baskets from memory.
Definition: TTree.cxx:4293
Int_t FlushBaskets()
Flush to disk all the baskets of this branch and any of subbranches.
Definition: TBranch.cxx:1090
virtual TSQLResult * Query(const char *varexp, const char *selection, Option_t *option, Long64_t nentries, Long64_t firstentry)=0
virtual TIterator * GetIteratorOnAllLeaves(Bool_t dir=kIterForward)
Creates a new iterator that will go through all the leaves on the tree itself and its friend...
Definition: TTree.cxx:5801
static Long64_t fgMaxTreeSize
Maximum size of a file containing a Tree.
Definition: TTree.h:135
virtual Style_t GetFillStyle() const
Return the fill area style.
Definition: TAttFill.h:31
virtual void Fatal(const char *method, const char *msgfmt,...) const
Issue fatal error message.
Definition: TObject.cxx:908
virtual void WriteHeader()
Write File Header.
Definition: TFile.cxx:2515
Bool_t IsWritable() const
virtual Long64_t GetEntryNumberFriend(const TTree *)=0
virtual TFile * GetFile(Int_t mode=0)
Return pointer to the file where branch buffers reside, returns 0 in case branch buffers reside in th...
Definition: TBranch.cxx:1501
virtual Long64_t SetEntries(Long64_t n=-1)
Change number of entries in the tree.
Definition: TTree.cxx:8595
R__EXTERN TInterpreter * gCling
Definition: TInterpreter.h:529
TBranch * GetBranch() const
Definition: TLeaf.h:71
virtual void Compress()
Remove empty slots from array.
Definition: TObjArray.cxx:333
virtual TFile * ChangeFile(TFile *file)
Called by TTree::Fill() when file has reached its maximum fgMaxTreeSize.
Definition: TTree.cxx:2594
virtual const char * GetName() const
Returns name of object.
Definition: TObject.cxx:357
static TTree * MergeTrees(TList *list, Option_t *option="")
Static function merging the trees in the TList into a new tree.
Definition: TTree.cxx:6580
A TTree is a list of TBranches.
Definition: TBranch.h:62
virtual const char * GetName() const
Returns name of object.
Definition: TRealData.h:52
A TSelector object is used by the TTree::Draw, TTree::Scan, TTree::Process to navigate in a TTree and...
Definition: TSelector.h:33
Int_t FlushBasketsImpl() const
Internal implementation of the FlushBaskets algorithm.
Definition: TTree.cxx:4901
virtual void SetTitle(const char *title="")
Set the title of the TNamed.
Definition: TNamed.cxx:164
void SetHistLineColor(Color_t color=1)
Definition: TStyle.h:357
Bool_t IsaPointer() const
Return true if data member is a pointer.
virtual void Print(Option_t *option="") const
Print TBranch parameters.
Definition: TBranch.cxx:1917
virtual Int_t GetValue(const char *name, Int_t dflt) const
Returns the integer value for a resource.
Definition: TEnv.cxx:491
A List of entry numbers in a TTree or TChain.
Definition: TEntryList.h:25
virtual Int_t AddBranchToCache(const char *bname, Bool_t subbranches=kFALSE)
Add branch with name bname to the Tree cache.
Definition: TTree.cxx:996
const Bool_t kTRUE
Definition: RtypesCore.h:87
Int_t fPacketSize
! Number of entries in one packet for parallel root
Definition: TTree.h:100
void Set(Int_t n)
Set size of this array to n doubles.
Definition: TArrayD.cxx:106
const Int_t n
Definition: legend1.C:16
TString & String()
Definition: TString.h:116
virtual Long64_t Project(const char *hname, const char *varexp, const char *selection="", Option_t *option="", Long64_t nentries=kMaxEntries, Long64_t firstentry=0)
Make a projection of a tree using selections.
Definition: TTree.cxx:7168
Line Attributes class.
Definition: TAttLine.h:18
virtual Long64_t GetEntryNumberWithIndex(Long64_t major, Long64_t minor) const =0
virtual Bool_t IsObjectOwner() const
Int_t GetCompressionLevel() const
Definition: TFile.h:384
Bool_t IsObject() const
Definition: TRealData.h:56
TIOFeatures fIOFeatures
IO features to define for newly-written baskets and branches.
Definition: TTree.h:105
Long64_t BinarySearch(Long64_t n, const T *array, T value)
Binary search in an array of n values to locate value.
Definition: TMath.h:1221
static constexpr Long64_t kMaxEntries
Definition: TTree.h:207
TBranch * GetMother() const
Get our top-level parent branch in the tree.
Definition: TBranch.cxx:1718
char name[80]
Definition: TGX11.cxx:109
TFriendLock(const TFriendLock &)
Copy constructor.
Definition: TTree.cxx:486
virtual void Warning(const char *method, const char *msgfmt,...) const
Issue warning message.
Definition: TObject.cxx:866
virtual const char * GetName() const
Return name of this collection.
virtual Long64_t GetEntriesFriend() const
Return pointer to the 1st Leaf named name in any Branch of this Tree or any branch in the list of fri...
Definition: TTree.cxx:5238
virtual void SetName(const char *name)
Change the name of this tree.
Definition: TTree.cxx:8779
Int_t GetCompressionSettings() const
Definition: TFile.h:390
virtual Version_t ReadVersion(UInt_t *start=0, UInt_t *bcnt=0, const TClass *cl=0)=0
Long64_t GetEstimatedClusterSize()
Estimate the cluster size.
Definition: TTree.cxx:577
virtual const char * GetTitle() const
Returns title of object.
Definition: TNamed.h:48
virtual void PrintCacheStats(Option_t *option="") const
Print statistics about the TreeCache for this tree.
Definition: TTree.cxx:7042
void MoveReadCache(TFile *src, TDirectory *dir)
Move a cache from a file to the current file in dir.
Definition: TTree.cxx:6718
virtual void CopyAddresses(TTree *, Bool_t undo=kFALSE)
Set branch addresses of passed tree equal to ours.
Definition: TTree.cxx:3131
virtual TObjArray * GetListOfLeaves()
Definition: TTree.h:410
static void ResetCount()
Static function resetting fgCount.
Definition: TBranch.cxx:2250
Long64_t fSavedBytes
Number of autosaved bytes.
Definition: TTree.h:79
Long64_t fCacheSize
! Maximum size of file buffers
Definition: TTree.h:96
virtual const char * GetFriendAlias(TTree *) const
If the &#39;tree&#39; is a friend, this method returns its alias name.
Definition: TTree.cxx:5751
void * New(ENewType defConstructor=kClassNew, Bool_t quiet=kFALSE) const
Return a pointer to a newly allocated object of this class.
Definition: TClass.cxx:4792
Int_t GetNleaves() const
Definition: TBranch.h:204
virtual Long64_t AutoSave(Option_t *option="")
AutoSave tree header every fAutoSave bytes.
Definition: TTree.cxx:1396
const char * Data() const
Definition: TString.h:364
std::atomic< Long64_t > fIMTTotBytes
! Total bytes for the IMT flush baskets
Definition: TTree.h:140