Logo ROOT   6.10/09
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 "RConfig.h"
337 #include "TTree.h"
338 
339 #include "TArrayC.h"
340 #include "TBufferFile.h"
341 #include "TBaseClass.h"
342 #include "TBasket.h"
343 #include "TBranchClones.h"
344 #include "TBranchElement.h"
345 #include "TBranchObject.h"
346 #include "TBranchRef.h"
347 #include "TBrowser.h"
348 #include "TClass.h"
349 #include "TClassEdit.h"
350 #include "TClonesArray.h"
351 #include "TCut.h"
352 #include "TDataMember.h"
353 #include "TDataType.h"
354 #include "TDirectory.h"
355 #include "TError.h"
356 #include "TEntryList.h"
357 #include "TEnv.h"
358 #include "TEventList.h"
359 #include "TFile.h"
360 #include "TFolder.h"
361 #include "TFriendElement.h"
362 #include "TInterpreter.h"
363 #include "TLeaf.h"
364 #include "TLeafB.h"
365 #include "TLeafC.h"
366 #include "TLeafD.h"
367 #include "TLeafElement.h"
368 #include "TLeafF.h"
369 #include "TLeafI.h"
370 #include "TLeafL.h"
371 #include "TLeafObject.h"
372 #include "TLeafS.h"
373 #include "TList.h"
374 #include "TMath.h"
375 #include "TROOT.h"
376 #include "TRealData.h"
377 #include "TRegexp.h"
378 #include "TStreamerElement.h"
379 #include "TStreamerInfo.h"
380 #include "TStyle.h"
381 #include "TSystem.h"
382 #include "TTreeCloner.h"
383 #include "TTreeCache.h"
384 #include "TTreeCacheUnzip.h"
385 #include "TVirtualCollectionProxy.h"
387 #include "TVirtualFitter.h"
388 #include "TVirtualIndex.h"
389 #include "TVirtualPerfStats.h"
390 #include "TVirtualPad.h"
391 #include "TBranchSTL.h"
392 #include "TSchemaRuleSet.h"
393 #include "TFileMergeInfo.h"
394 #include "ROOT/StringConv.hxx"
395 #include "TVirtualMutex.h"
396 
397 #include "TBranchIMTHelper.h"
398 
399 #include <chrono>
400 #include <cstddef>
401 #include <iostream>
402 #include <fstream>
403 #include <sstream>
404 #include <string>
405 #include <stdio.h>
406 #include <limits.h>
407 #include <algorithm>
408 
409 #ifdef R__USE_IMT
410 #include "ROOT/TThreadExecutor.hxx"
411 #include <thread>
412 #include <string>
413 #include <sstream>
414 #endif
415 
416 constexpr Int_t kNEntriesResort = 100;
419 Int_t TTree::fgBranchStyle = 1; // Use new TBranch style with TBranchElement.
420 Long64_t TTree::fgMaxTreeSize = 100000000000LL;
421 
423 
424 ////////////////////////////////////////////////////////////////////////////////
425 ////////////////////////////////////////////////////////////////////////////////
426 ////////////////////////////////////////////////////////////////////////////////
427 
428 static char DataTypeToChar(EDataType datatype)
429 {
430  // Return the leaflist 'char' for a given datatype.
431 
432  switch(datatype) {
433  case kChar_t: return 'B';
434  case kUChar_t: return 'b';
435  case kBool_t: return 'O';
436  case kShort_t: return 'S';
437  case kUShort_t: return 's';
438  case kCounter:
439  case kInt_t: return 'I';
440  case kUInt_t: return 'i';
441  case kDouble_t:
442  case kDouble32_t: return 'D';
443  case kFloat_t:
444  case kFloat16_t: return 'F';
445  case kLong_t: return 0; // unsupported
446  case kULong_t: return 0; // unsupported?
447  case kchar: return 0; // unsupported
448  case kLong64_t: return 'L';
449  case kULong64_t: return 'l';
450 
451  case kCharStar: return 'C';
452  case kBits: return 0; //unsupported
453 
454  case kOther_t:
455  case kNoType_t:
456  default:
457  return 0;
458  }
459  return 0;
460 }
461 
462 ////////////////////////////////////////////////////////////////////////////////
463 /// \class TTree::TFriendLock
464 /// Helper class to prevent infinite recursion in the usage of TTree Friends.
465 
466 ////////////////////////////////////////////////////////////////////////////////
467 /// Record in tree that it has been used while recursively looks through the friends.
468 
470 : fTree(tree)
471 {
472  // We could also add some code to acquire an actual
473  // lock to prevent multi-thread issues
474  fMethodBit = methodbit;
475  if (fTree) {
476  fPrevious = fTree->fFriendLockStatus & fMethodBit;
477  fTree->fFriendLockStatus |= fMethodBit;
478  } else {
479  fPrevious = 0;
480  }
481 }
482 
483 ////////////////////////////////////////////////////////////////////////////////
484 /// Copy constructor.
485 
487  fTree(tfl.fTree),
488  fMethodBit(tfl.fMethodBit),
489  fPrevious(tfl.fPrevious)
490 {
491 }
492 
493 ////////////////////////////////////////////////////////////////////////////////
494 /// Assignment operator.
495 
497 {
498  if(this!=&tfl) {
499  fTree=tfl.fTree;
501  fPrevious=tfl.fPrevious;
502  }
503  return *this;
504 }
505 
506 ////////////////////////////////////////////////////////////////////////////////
507 /// Restore the state of tree the same as before we set the lock.
508 
510 {
511  if (fTree) {
512  if (!fPrevious) {
514  }
515  }
516 }
517 
518 ////////////////////////////////////////////////////////////////////////////////
519 /// \class TTree::TClusterIterator
520 /// Helper class to iterate over cluster of baskets.
521 
522 ////////////////////////////////////////////////////////////////////////////////
523 /// Regular constructor.
524 /// TTree is not set as const, since we might modify if it is a TChain.
525 
526 TTree::TClusterIterator::TClusterIterator(TTree *tree, Long64_t firstEntry) : fTree(tree), fClusterRange(0), fStartEntry(0), fNextEntry(0)
527 {
528  if ( fTree->GetAutoFlush() <= 0 ) {
529  // Case of old files before November 9 2009
530  fStartEntry = firstEntry;
531  } else if (fTree->fNClusterRange) {
532  // Find the correct cluster range.
533  //
534  // Since fClusterRangeEnd contains the inclusive upper end of the range, we need to search for the
535  // range that was containing the previous entry and add 1 (because BinarySearch consider the values
536  // to be the inclusive start of the bucket).
537  fClusterRange = TMath::BinarySearch(fTree->fNClusterRange, fTree->fClusterRangeEnd, firstEntry - 1) + 1;
538 
539  Long64_t entryInRange;
540  Long64_t pedestal;
541  if (fClusterRange == 0) {
542  pedestal = 0;
543  entryInRange = firstEntry;
544  } else {
545  pedestal = fTree->fClusterRangeEnd[fClusterRange-1] + 1;
546  entryInRange = firstEntry - pedestal;
547  }
548  Long64_t autoflush;
549  if (fClusterRange == fTree->fNClusterRange) {
550  autoflush = fTree->fAutoFlush;
551  } else {
552  autoflush = fTree->fClusterSize[fClusterRange];
553  }
554  if (autoflush == 0) {
555  autoflush = GetEstimatedClusterSize();
556  }
557  fStartEntry = pedestal + entryInRange - entryInRange%autoflush;
558  } else {
559  fStartEntry = firstEntry - firstEntry%fTree->GetAutoFlush();
560  }
561  fNextEntry = fStartEntry; // Position correctly for the first call to Next()
562 }
563 
564 ////////////////////////////////////////////////////////////////////////////////
565 /// In the case where the cluster size was not fixed (old files and
566 /// case where autoflush was explicitly set to zero, we need estimate
567 /// a cluster size in relation to the size of the cache.
568 
570 {
571  Long64_t zipBytes = fTree->GetZipBytes();
572  if (zipBytes == 0) {
573  return fTree->GetEntries() - 1;
574  } else {
575  Long64_t clusterEstimate = 1;
576  Long64_t cacheSize = fTree->GetCacheSize();
577  if (cacheSize == 0) {
578  // Humm ... let's double check on the file.
580  if (file) {
581  TFileCacheRead *cache = file->GetCacheRead(fTree);
582  if (cache) {
583  cacheSize = cache->GetBufferSize();
584  }
585  }
586  }
587  if (cacheSize > 0) {
588  clusterEstimate = fTree->GetEntries() * cacheSize / zipBytes;
589  if (clusterEstimate == 0)
590  clusterEstimate = 1;
591  }
592  return clusterEstimate;
593  }
594 }
595 
596 ////////////////////////////////////////////////////////////////////////////////
597 /// Move on to the next cluster and return the starting entry
598 /// of this next cluster
599 
601 {
602  fStartEntry = fNextEntry;
603  if ( fTree->GetAutoFlush() <= 0 ) {
604  // Case of old files before November 9 2009
605  Long64_t clusterEstimate = GetEstimatedClusterSize();
606  fNextEntry = fStartEntry + clusterEstimate;
607  } else {
608  if (fClusterRange == fTree->fNClusterRange) {
609  // We are looking at the last range ; its size
610  // is defined by AutoFlush itself and goes to the GetEntries.
611  fNextEntry += fTree->GetAutoFlush();
612  } else {
613  if (fStartEntry > fTree->fClusterRangeEnd[fClusterRange]) {
614  ++fClusterRange;
615  }
616  if (fClusterRange == fTree->fNClusterRange) {
617  // We are looking at the last range which size
618  // is defined by AutoFlush itself and goes to the GetEntries.
619  fNextEntry += fTree->GetAutoFlush();
620  } else {
621  Long64_t clusterSize = fTree->fClusterSize[fClusterRange];
622  if (clusterSize == 0) {
623  clusterSize = GetEstimatedClusterSize();
624  }
625  fNextEntry += clusterSize;
626  if (fNextEntry > fTree->fClusterRangeEnd[fClusterRange]) {
627  // The last cluster of the range was a partial cluster,
628  // so the next cluster starts at the beginning of the
629  // next range.
630  fNextEntry = fTree->fClusterRangeEnd[fClusterRange] + 1;
631  }
632  }
633  }
634  }
635  if (fNextEntry > fTree->GetEntries()) {
636  fNextEntry = fTree->GetEntries();
637  }
638  return fStartEntry;
639 }
640 
641 ////////////////////////////////////////////////////////////////////////////////
642 ////////////////////////////////////////////////////////////////////////////////
643 ////////////////////////////////////////////////////////////////////////////////
644 
645 ////////////////////////////////////////////////////////////////////////////////
646 /// Default constructor and I/O constructor.
647 ///
648 /// Note: We do *not* insert ourself into the current directory.
649 ///
650 
651 TTree::TTree()
653 , TAttLine()
654 , TAttFill()
655 , TAttMarker()
656 , fEntries(0)
657 , fTotBytes(0)
658 , fZipBytes(0)
659 , fSavedBytes(0)
660 , fFlushedBytes(0)
661 , fWeight(1)
662 , fTimerInterval(0)
663 , fScanField(25)
664 , fUpdate(0)
666 , fNClusterRange(0)
667 , fMaxClusterRange(0)
668 , fMaxEntries(0)
669 , fMaxEntryLoop(0)
670 , fMaxVirtualSize(0)
671 , fAutoSave( -300000000)
672 , fAutoFlush(-30000000)
673 , fEstimate(1000000)
674 , fClusterRangeEnd(0)
675 , fClusterSize(0)
676 , fCacheSize(0)
677 , fChainOffset(0)
678 , fReadEntry(-1)
679 , fTotalBuffers(0)
680 , fPacketSize(100)
681 , fNfill(0)
682 , fDebug(0)
683 , fDebugMin(0)
684 , fDebugMax(9999999)
685 , fMakeClass(0)
686 , fFileNumber(0)
687 , fNotify(0)
688 , fDirectory(0)
689 , fBranches()
690 , fLeaves()
691 , fAliases(0)
692 , fEventList(0)
693 , fEntryList(0)
694 , fIndexValues()
695 , fIndex()
696 , fTreeIndex(0)
697 , fFriends(0)
698 , fPerfStats(0)
699 , fUserInfo(0)
700 , fPlayer(0)
701 , fClones(0)
702 , fBranchRef(0)
704 , fTransientBuffer(0)
709 {
710  fMaxEntries = 1000000000;
711  fMaxEntries *= 1000;
712 
713  fMaxEntryLoop = 1000000000;
714  fMaxEntryLoop *= 1000;
715 
717 }
718 
719 ////////////////////////////////////////////////////////////////////////////////
720 /// Normal tree constructor.
721 ///
722 /// The tree is created in the current directory.
723 /// Use the various functions Branch below to add branches to this tree.
724 ///
725 /// If the first character of title is a "/", the function assumes a folder name.
726 /// In this case, it creates automatically branches following the folder hierarchy.
727 /// splitlevel may be used in this case to control the split level.
728 
729 TTree::TTree(const char* name, const char* title, Int_t splitlevel /* = 99 */)
730 : TNamed(name, title)
731 , TAttLine()
732 , TAttFill()
733 , TAttMarker()
734 , fEntries(0)
735 , fTotBytes(0)
736 , fZipBytes(0)
737 , fSavedBytes(0)
738 , fFlushedBytes(0)
739 , fWeight(1)
740 , fTimerInterval(0)
741 , fScanField(25)
742 , fUpdate(0)
744 , fNClusterRange(0)
745 , fMaxClusterRange(0)
746 , fMaxEntries(0)
747 , fMaxEntryLoop(0)
748 , fMaxVirtualSize(0)
749 , fAutoSave( -300000000)
750 , fAutoFlush(-30000000)
751 , fEstimate(1000000)
752 , fClusterRangeEnd(0)
753 , fClusterSize(0)
754 , fCacheSize(0)
755 , fChainOffset(0)
756 , fReadEntry(-1)
757 , fTotalBuffers(0)
758 , fPacketSize(100)
759 , fNfill(0)
760 , fDebug(0)
761 , fDebugMin(0)
762 , fDebugMax(9999999)
763 , fMakeClass(0)
764 , fFileNumber(0)
765 , fNotify(0)
766 , fDirectory(0)
767 , fBranches()
768 , fLeaves()
769 , fAliases(0)
770 , fEventList(0)
771 , fEntryList(0)
772 , fIndexValues()
773 , fIndex()
774 , fTreeIndex(0)
775 , fFriends(0)
776 , fPerfStats(0)
777 , fUserInfo(0)
778 , fPlayer(0)
779 , fClones(0)
780 , fBranchRef(0)
782 , fTransientBuffer(0)
787 {
788  // TAttLine state.
792 
793  // TAttFill state.
796 
797  // TAttMarkerState.
801 
802  fMaxEntries = 1000000000;
803  fMaxEntries *= 1000;
804 
805  fMaxEntryLoop = 1000000000;
806  fMaxEntryLoop *= 1000;
807 
808  // Insert ourself into the current directory.
809  // FIXME: This is very annoying behaviour, we should
810  // be able to choose to not do this like we
811  // can with a histogram.
813  if (fDirectory) fDirectory->Append(this);
814 
816 
817  // If title starts with "/" and is a valid folder name, a superbranch
818  // is created.
819  // FIXME: Why?
820  if (strlen(title) > 2) {
821  if (title[0] == '/') {
822  Branch(title+1,32000,splitlevel);
823  }
824  }
825 }
826 
827 ////////////////////////////////////////////////////////////////////////////////
828 /// Destructor.
829 
831 {
832  if (fDirectory) {
833  // We are in a directory, which may possibly be a file.
834  if (fDirectory->GetList()) {
835  // Remove us from the directory listing.
836  fDirectory->Remove(this);
837  }
838  //delete the file cache if it points to this Tree
840  MoveReadCache(file,0);
841  }
842  // We don't own the leaves in fLeaves, the branches do.
843  fLeaves.Clear();
844  // I'm ready to destroy any objects allocated by
845  // SetAddress() by my branches. If I have clones,
846  // tell them to zero their pointers to this shared
847  // memory.
848  if (fClones && fClones->GetEntries()) {
849  // I have clones.
850  // I am about to delete the objects created by
851  // SetAddress() which we are sharing, so tell
852  // the clones to release their pointers to them.
853  for (TObjLink* lnk = fClones->FirstLink(); lnk; lnk = lnk->Next()) {
854  TTree* clone = (TTree*) lnk->GetObject();
855  // clone->ResetBranchAddresses();
856 
857  // Reset only the branch we have set the address of.
858  CopyAddresses(clone,kTRUE);
859  }
860  }
861  // Get rid of our branches, note that this will also release
862  // any memory allocated by TBranchElement::SetAddress().
863  fBranches.Delete();
864  // FIXME: We must consider what to do with the reset of these if we are a clone.
865  delete fPlayer;
866  fPlayer = 0;
867  if (fFriends) {
868  fFriends->Delete();
869  delete fFriends;
870  fFriends = 0;
871  }
872  if (fAliases) {
873  fAliases->Delete();
874  delete fAliases;
875  fAliases = 0;
876  }
877  if (fUserInfo) {
878  fUserInfo->Delete();
879  delete fUserInfo;
880  fUserInfo = 0;
881  }
882  if (fClones) {
883  // Clone trees should no longer be removed from fClones when they are deleted.
884  {
886  gROOT->GetListOfCleanups()->Remove(fClones);
887  }
888  // Note: fClones does not own its content.
889  delete fClones;
890  fClones = 0;
891  }
892  if (fEntryList) {
894  // Delete the entry list if it is marked to be deleted and it is not also
895  // owned by a directory. (Otherwise we would need to make sure that a
896  // TDirectoryFile that has a TTree in it does a 'slow' TList::Delete.
897  delete fEntryList;
898  fEntryList=0;
899  }
900  }
901  delete fTreeIndex;
902  fTreeIndex = 0;
903  delete fBranchRef;
904  fBranchRef = 0;
905  delete [] fClusterRangeEnd;
906  fClusterRangeEnd = 0;
907  delete [] fClusterSize;
908  fClusterSize = 0;
909  // Must be done after the destruction of friends.
910  // Note: We do *not* own our directory.
911  fDirectory = 0;
912 
913  if (fTransientBuffer) {
914  delete fTransientBuffer;
915  fTransientBuffer = 0;
916  }
917 }
918 
919 ////////////////////////////////////////////////////////////////////////////////
920 /// Returns the transient buffer currently used by this TTree for reading/writing baskets.
921 
923 {
924  if (fTransientBuffer) {
925  if (fTransientBuffer->BufferSize() < size) {
926  fTransientBuffer->Expand(size);
927  }
928  return fTransientBuffer;
929  }
931  return fTransientBuffer;
932 }
933 
934 ////////////////////////////////////////////////////////////////////////////////
935 /// Add branch with name bname to the Tree cache.
936 /// If bname="*" all branches are added to the cache.
937 /// if subbranches is true all the branches of the subbranches are
938 /// also put to the cache.
939 ///
940 /// Returns:
941 /// - 0 branch added or already included
942 /// - -1 on error
943 
944 Int_t TTree::AddBranchToCache(const char*bname, Bool_t subbranches)
945 {
946  if (!GetTree()) {
947  if (LoadTree(0)<0) {
948  Error("AddBranchToCache","Could not load a tree");
949  return -1;
950  }
951  }
952  if (GetTree()) {
953  if (GetTree() != this) {
954  return GetTree()->AddBranchToCache(bname, subbranches);
955  }
956  } else {
957  Error("AddBranchToCache", "No tree is available. Branch was not added to the cache");
958  return -1;
959  }
960 
961  TFile *f = GetCurrentFile();
962  if (!f) {
963  Error("AddBranchToCache", "No file is available. Branch was not added to the cache");
964  return -1;
965  }
966  TTreeCache *tc = GetReadCache(f,kTRUE);
967  if (!tc) {
968  Error("AddBranchToCache", "No cache is available, branch not added");
969  return -1;
970  }
971  return tc->AddBranch(bname,subbranches);
972 }
973 
974 ////////////////////////////////////////////////////////////////////////////////
975 /// Add branch b to the Tree cache.
976 /// if subbranches is true all the branches of the subbranches are
977 /// also put to the cache.
978 ///
979 /// Returns:
980 /// - 0 branch added or already included
981 /// - -1 on error
982 
984 {
985  if (!GetTree()) {
986  if (LoadTree(0)<0) {
987  Error("AddBranchToCache","Could not load a tree");
988  return -1;
989  }
990  }
991  if (GetTree()) {
992  if (GetTree() != this) {
993  Int_t res = GetTree()->AddBranchToCache(b, subbranches);
994  if (res<0) {
995  Error("AddBranchToCache", "Error adding branch");
996  }
997  return res;
998  }
999  } else {
1000  Error("AddBranchToCache", "No tree is available. Branch was not added to the cache");
1001  return -1;
1002  }
1003 
1004  TFile *f = GetCurrentFile();
1005  if (!f) {
1006  Error("AddBranchToCache", "No file is available. Branch was not added to the cache");
1007  return -1;
1008  }
1009  TTreeCache *tc = GetReadCache(f,kTRUE);
1010  if (!tc) {
1011  Error("AddBranchToCache", "No cache is available, branch not added");
1012  return -1;
1013  }
1014  return tc->AddBranch(b,subbranches);
1015 }
1016 
1017 ////////////////////////////////////////////////////////////////////////////////
1018 /// Remove the branch with name 'bname' from the Tree cache.
1019 /// If bname="*" all branches are removed from the cache.
1020 /// if subbranches is true all the branches of the subbranches are
1021 /// also removed from the cache.
1022 ///
1023 /// Returns:
1024 /// - 0 branch dropped or not in cache
1025 /// - -1 on error
1026 
1027 Int_t TTree::DropBranchFromCache(const char*bname, Bool_t subbranches)
1029  if (!GetTree()) {
1030  if (LoadTree(0)<0) {
1031  Error("DropBranchFromCache","Could not load a tree");
1032  return -1;
1033  }
1034  }
1035  if (GetTree()) {
1036  if (GetTree() != this) {
1037  return GetTree()->DropBranchFromCache(bname, subbranches);
1038  }
1039  } else {
1040  Error("DropBranchFromCache", "No tree is available. Branch was not dropped from the cache");
1041  return -1;
1042  }
1043 
1044  TFile *f = GetCurrentFile();
1045  if (!f) {
1046  Error("DropBranchFromCache", "No file is available. Branch was not dropped from the cache");
1047  return -1;
1048  }
1049  TTreeCache *tc = GetReadCache(f,kTRUE);
1050  if (!tc) {
1051  Error("DropBranchFromCache", "No cache is available, branch not dropped");
1052  return -1;
1053  }
1054  return tc->DropBranch(bname,subbranches);
1055 }
1056 
1057 ////////////////////////////////////////////////////////////////////////////////
1058 /// Remove the branch b from the Tree cache.
1059 /// if subbranches is true all the branches of the subbranches are
1060 /// also removed from the cache.
1061 ///
1062 /// Returns:
1063 /// - 0 branch dropped or not in cache
1064 /// - -1 on error
1065 
1068  if (!GetTree()) {
1069  if (LoadTree(0)<0) {
1070  Error("DropBranchFromCache","Could not load a tree");
1071  return -1;
1072  }
1073  }
1074  if (GetTree()) {
1075  if (GetTree() != this) {
1076  Int_t res = GetTree()->DropBranchFromCache(b, subbranches);
1077  if (res<0) {
1078  Error("DropBranchFromCache", "Error dropping branch");
1079  }
1080  return res;
1081  }
1082  } else {
1083  Error("DropBranchFromCache", "No tree is available. Branch was not dropped from the cache");
1084  return -1;
1085  }
1086 
1087  TFile *f = GetCurrentFile();
1088  if (!f) {
1089  Error("DropBranchFromCache", "No file is available. Branch was not dropped from the cache");
1090  return -1;
1091  }
1092  TTreeCache *tc = GetReadCache(f,kTRUE);
1093  if (!tc) {
1094  Error("DropBranchFromCache", "No cache is available, branch not dropped");
1095  return -1;
1096  }
1097  return tc->DropBranch(b,subbranches);
1098 }
1099 
1100 ////////////////////////////////////////////////////////////////////////////////
1101 /// Add a cloned tree to our list of trees to be notified whenever we change
1102 /// our branch addresses or when we are deleted.
1103 
1104 void TTree::AddClone(TTree* clone)
1106  if (!fClones) {
1107  fClones = new TList();
1108  fClones->SetOwner(false);
1109  // So that the clones are automatically removed from the list when
1110  // they are deleted.
1111  {
1113  gROOT->GetListOfCleanups()->Add(fClones);
1114  }
1115  }
1116  if (!fClones->FindObject(clone)) {
1117  fClones->Add(clone);
1118  }
1119 }
1120 
1121 ////////////////////////////////////////////////////////////////////////////////
1122 /// Add a TFriendElement to the list of friends.
1123 ///
1124 /// This function:
1125 /// - opens a file if filename is specified
1126 /// - reads a Tree with name treename from the file (current directory)
1127 /// - adds the Tree to the list of friends
1128 /// see other AddFriend functions
1129 ///
1130 /// A TFriendElement TF describes a TTree object TF in a file.
1131 /// When a TFriendElement TF is added to the the list of friends of an
1132 /// existing TTree T, any variable from TF can be referenced in a query
1133 /// to T.
1134 ///
1135 /// A tree keeps a list of friends. In the context of a tree (or a chain),
1136 /// friendship means unrestricted access to the friends data. In this way
1137 /// it is much like adding another branch to the tree without taking the risk
1138 /// of damaging it. To add a friend to the list, you can use the TTree::AddFriend
1139 /// method. The tree in the diagram below has two friends (friend_tree1 and
1140 /// friend_tree2) and now has access to the variables a,b,c,i,j,k,l and m.
1141 ///
1142 /// \image html ttree_friend1.png
1143 ///
1144 /// The AddFriend method has two parameters, the first is the tree name and the
1145 /// second is the name of the ROOT file where the friend tree is saved.
1146 /// AddFriend automatically opens the friend file. If no file name is given,
1147 /// the tree called ft1 is assumed to be in the same file as the original tree.
1148 ///
1149 /// tree.AddFriend("ft1","friendfile1.root");
1150 /// If the friend tree has the same name as the original tree, you can give it
1151 /// an alias in the context of the friendship:
1152 ///
1153 /// tree.AddFriend("tree1 = tree","friendfile1.root");
1154 /// Once the tree has friends, we can use TTree::Draw as if the friend's
1155 /// variables were in the original tree. To specify which tree to use in
1156 /// the Draw method, use the syntax:
1157 /// ~~~ {.cpp}
1158 /// <treeName>.<branchname>.<varname>
1159 /// ~~~
1160 /// If the variablename is enough to uniquely identify the variable, you can
1161 /// leave out the tree and/or branch name.
1162 /// For example, these commands generate a 3-d scatter plot of variable "var"
1163 /// in the TTree tree versus variable v1 in TTree ft1 versus variable v2 in
1164 /// TTree ft2.
1165 /// ~~~ {.cpp}
1166 /// tree.AddFriend("ft1","friendfile1.root");
1167 /// tree.AddFriend("ft2","friendfile2.root");
1168 /// tree.Draw("var:ft1.v1:ft2.v2");
1169 /// ~~~
1170 /// \image html ttree_friend2.png
1171 ///
1172 /// The picture illustrates the access of the tree and its friends with a
1173 /// Draw command.
1174 /// When AddFriend is called, the ROOT file is automatically opened and the
1175 /// friend tree (ft1) is read into memory. The new friend (ft1) is added to
1176 /// the list of friends of tree.
1177 /// The number of entries in the friend must be equal or greater to the number
1178 /// of entries of the original tree. If the friend tree has fewer entries a
1179 /// warning is given and the missing entries are not included in the histogram.
1180 /// To retrieve the list of friends from a tree use TTree::GetListOfFriends.
1181 /// When the tree is written to file (TTree::Write), the friends list is saved
1182 /// with it. And when the tree is retrieved, the trees on the friends list are
1183 /// also retrieved and the friendship restored.
1184 /// When a tree is deleted, the elements of the friend list are also deleted.
1185 /// It is possible to declare a friend tree that has the same internal
1186 /// structure (same branches and leaves) as the original tree, and compare the
1187 /// same values by specifying the tree.
1188 /// ~~~ {.cpp}
1189 /// tree.Draw("var:ft1.var:ft2.var")
1190 /// ~~~
1191 
1192 TFriendElement* TTree::AddFriend(const char* treename, const char* filename)
1194  if (!fFriends) {
1195  fFriends = new TList();
1196  }
1197  TFriendElement* fe = new TFriendElement(this, treename, filename);
1198 
1199  fFriends->Add(fe);
1200  TTree* t = fe->GetTree();
1201  if (t) {
1202  if (!t->GetTreeIndex() && (t->GetEntries() < fEntries)) {
1203  Warning("AddFriend", "FriendElement %s in file %s has less entries %lld than its parent Tree: %lld", treename, filename, t->GetEntries(), fEntries);
1204  }
1205  } else {
1206  Warning("AddFriend", "Cannot add FriendElement %s in file %s", treename, filename);
1207  }
1208  return fe;
1209 }
1210 
1211 ////////////////////////////////////////////////////////////////////////////////
1212 /// Add a TFriendElement to the list of friends.
1213 ///
1214 /// The TFile is managed by the user (e.g. the user must delete the file).
1215 /// For complete description see AddFriend(const char *, const char *).
1216 /// This function:
1217 /// - reads a Tree with name treename from the file
1218 /// - adds the Tree to the list of friends
1219 
1220 TFriendElement* TTree::AddFriend(const char* treename, TFile* file)
1222  if (!fFriends) {
1223  fFriends = new TList();
1224  }
1225  TFriendElement *fe = new TFriendElement(this, treename, file);
1226  R__ASSERT(fe);
1227  fFriends->Add(fe);
1228  TTree *t = fe->GetTree();
1229  if (t) {
1230  if (!t->GetTreeIndex() && (t->GetEntries() < fEntries)) {
1231  Warning("AddFriend", "FriendElement %s in file %s has less entries %lld than its parent tree: %lld", treename, file->GetName(), t->GetEntries(), fEntries);
1232  }
1233  } else {
1234  Warning("AddFriend", "unknown tree '%s' in file '%s'", treename, file->GetName());
1235  }
1236  return fe;
1237 }
1238 
1239 ////////////////////////////////////////////////////////////////////////////////
1240 /// Add a TFriendElement to the list of friends.
1241 ///
1242 /// The TTree is managed by the user (e.g., the user must delete the file).
1243 /// For a complete description see AddFriend(const char *, const char *).
1244 
1245 TFriendElement* TTree::AddFriend(TTree* tree, const char* alias, Bool_t warn)
1247  if (!tree) {
1248  return 0;
1249  }
1250  if (!fFriends) {
1251  fFriends = new TList();
1252  }
1253  TFriendElement* fe = new TFriendElement(this, tree, alias);
1254  R__ASSERT(fe); // this assert is for historical reasons. Don't remove it unless you understand all the consequences.
1255  fFriends->Add(fe);
1256  TTree* t = fe->GetTree();
1257  if (warn && (t->GetEntries() < fEntries)) {
1258  Warning("AddFriend", "FriendElement '%s' in file '%s' has less entries %lld than its parent tree: %lld",
1259  tree->GetName(), fe->GetFile() ? fe->GetFile()->GetName() : "(memory resident)", t->GetEntries(), fEntries);
1260  }
1261  return fe;
1262 }
1263 
1264 ////////////////////////////////////////////////////////////////////////////////
1265 /// AutoSave tree header every fAutoSave bytes.
1266 ///
1267 /// When large Trees are produced, it is safe to activate the AutoSave
1268 /// procedure. Some branches may have buffers holding many entries.
1269 /// If fAutoSave is negative, AutoSave is automatically called by
1270 /// TTree::Fill when the number of bytes generated since the previous
1271 /// AutoSave is greater than -fAutoSave bytes.
1272 /// If fAutoSave is positive, AutoSave is automatically called by
1273 /// TTree::Fill every N entries.
1274 /// This function may also be invoked by the user.
1275 /// Each AutoSave generates a new key on the file.
1276 /// Once the key with the tree header has been written, the previous cycle
1277 /// (if any) is deleted.
1278 ///
1279 /// Note that calling TTree::AutoSave too frequently (or similarly calling
1280 /// TTree::SetAutoSave with a small value) is an expensive operation.
1281 /// You should make tests for your own application to find a compromise
1282 /// between speed and the quantity of information you may loose in case of
1283 /// a job crash.
1284 ///
1285 /// In case your program crashes before closing the file holding this tree,
1286 /// the file will be automatically recovered when you will connect the file
1287 /// in UPDATE mode.
1288 /// The Tree will be recovered at the status corresponding to the last AutoSave.
1289 ///
1290 /// if option contains "SaveSelf", gDirectory->SaveSelf() is called.
1291 /// This allows another process to analyze the Tree while the Tree is being filled.
1292 ///
1293 /// if option contains "FlushBaskets", TTree::FlushBaskets is called and all
1294 /// the current basket are closed-out and written to disk individually.
1295 ///
1296 /// By default the previous header is deleted after having written the new header.
1297 /// if option contains "Overwrite", the previous Tree header is deleted
1298 /// before written the new header. This option is slightly faster, but
1299 /// the default option is safer in case of a problem (disk quota exceeded)
1300 /// when writing the new header.
1301 ///
1302 /// The function returns the number of bytes written to the file.
1303 /// if the number of bytes is null, an error has occurred while writing
1304 /// the header to the file.
1305 ///
1306 /// ## How to write a Tree in one process and view it from another process
1307 ///
1308 /// The following two scripts illustrate how to do this.
1309 /// The script treew.C is executed by process1, treer.C by process2
1310 ///
1311 /// script treew.C:
1312 /// ~~~ {.cpp}
1313 /// void treew() {
1314 /// TFile f("test.root","recreate");
1315 /// TNtuple *ntuple = new TNtuple("ntuple","Demo","px:py:pz:random:i");
1316 /// Float_t px, py, pz;
1317 /// for ( Int_t i=0; i<10000000; i++) {
1318 /// gRandom->Rannor(px,py);
1319 /// pz = px*px + py*py;
1320 /// Float_t random = gRandom->Rndm(1);
1321 /// ntuple->Fill(px,py,pz,random,i);
1322 /// if (i%1000 == 1) ntuple->AutoSave("SaveSelf");
1323 /// }
1324 /// }
1325 /// ~~~
1326 /// script treer.C:
1327 /// ~~~ {.cpp}
1328 /// void treer() {
1329 /// TFile f("test.root");
1330 /// TTree *ntuple = (TTree*)f.Get("ntuple");
1331 /// TCanvas c1;
1332 /// Int_t first = 0;
1333 /// while(1) {
1334 /// if (first == 0) ntuple->Draw("px>>hpx", "","",10000000,first);
1335 /// else ntuple->Draw("px>>+hpx","","",10000000,first);
1336 /// first = (Int_t)ntuple->GetEntries();
1337 /// c1.Update();
1338 /// gSystem->Sleep(1000); //sleep 1 second
1339 /// ntuple->Refresh();
1340 /// }
1341 /// }
1342 /// ~~~
1343 
1346  if (!fDirectory || fDirectory == gROOT || !fDirectory->IsWritable()) return 0;
1347  if (gDebug > 0) {
1348  Info("AutoSave", "Tree:%s after %lld bytes written\n",GetName(),GetTotBytes());
1349  }
1350  TString opt = option;
1351  opt.ToLower();
1352 
1353  if (opt.Contains("flushbaskets")) {
1354  if (gDebug > 0) Info("AutoSave", "calling FlushBaskets \n");
1355  FlushBaskets();
1356  }
1357 
1359 
1361  Long64_t nbytes;
1362  if (opt.Contains("overwrite")) {
1363  nbytes = fDirectory->WriteTObject(this,"","overwrite");
1364  } else {
1365  nbytes = fDirectory->WriteTObject(this); //nbytes will be 0 if Write failed (disk space exceeded)
1366  if (nbytes && key) {
1367  key->Delete();
1368  delete key;
1369  }
1370  }
1371  // save StreamerInfo
1372  TFile *file = fDirectory->GetFile();
1373  if (file) file->WriteStreamerInfo();
1374 
1375  if (opt.Contains("saveself")) {
1376  fDirectory->SaveSelf();
1377  //the following line is required in case GetUserInfo contains a user class
1378  //for which the StreamerInfo must be written. One could probably be a bit faster (Rene)
1379  if (file) file->WriteHeader();
1380  }
1381 
1382  return nbytes;
1383 }
1384 
1385 namespace {
1386  // This error message is repeated several times in the code. We write it once.
1387  const char* writeStlWithoutProxyMsg = "The class requested (%s) for the branch \"%s\""
1388  " is an instance of an stl collection and does not have a compiled CollectionProxy."
1389  " Please generate the dictionary for this collection (%s) to avoid to write corrupted data.";
1390 }
1391 
1392 ////////////////////////////////////////////////////////////////////////////////
1393 /// Same as TTree::Branch() with added check that addobj matches className.
1394 ///
1395 /// See TTree::Branch() for other details.
1396 ///
1397 
1398 TBranch* TTree::BranchImp(const char* branchname, const char* classname, TClass* ptrClass, void* addobj, Int_t bufsize, Int_t splitlevel)
1400  TClass* claim = TClass::GetClass(classname);
1401  if (!ptrClass) {
1402  if (claim && claim->GetCollectionProxy() && dynamic_cast<TEmulatedCollectionProxy*>(claim->GetCollectionProxy())) {
1403  Error("Branch", writeStlWithoutProxyMsg,
1404  claim->GetName(), branchname, claim->GetName());
1405  return 0;
1406  }
1407  return Branch(branchname, classname, (void*) addobj, bufsize, splitlevel);
1408  }
1409  TClass* actualClass = 0;
1410  void** addr = (void**) addobj;
1411  if (addr) {
1412  actualClass = ptrClass->GetActualClass(*addr);
1413  }
1414  if (ptrClass && claim) {
1415  if (!(claim->InheritsFrom(ptrClass) || ptrClass->InheritsFrom(claim))) {
1416  // Note we currently do not warn in case of splicing or over-expectation).
1417  if (claim->IsLoaded() && ptrClass->IsLoaded() && strcmp( claim->GetTypeInfo()->name(), ptrClass->GetTypeInfo()->name() ) == 0) {
1418  // The type is the same according to the C++ type_info, we must be in the case of
1419  // a template of Double32_t. This is actually a correct case.
1420  } else {
1421  Error("Branch", "The class requested (%s) for \"%s\" is different from the type of the pointer passed (%s)",
1422  claim->GetName(), branchname, ptrClass->GetName());
1423  }
1424  } else if (actualClass && (claim != actualClass) && !actualClass->InheritsFrom(claim)) {
1425  if (claim->IsLoaded() && actualClass->IsLoaded() && strcmp( claim->GetTypeInfo()->name(), actualClass->GetTypeInfo()->name() ) == 0) {
1426  // The type is the same according to the C++ type_info, we must be in the case of
1427  // a template of Double32_t. This is actually a correct case.
1428  } else {
1429  Error("Branch", "The actual class (%s) of the object provided for the definition of the branch \"%s\" does not inherit from %s",
1430  actualClass->GetName(), branchname, claim->GetName());
1431  }
1432  }
1433  }
1434  if (claim && claim->GetCollectionProxy() && dynamic_cast<TEmulatedCollectionProxy*>(claim->GetCollectionProxy())) {
1435  Error("Branch", writeStlWithoutProxyMsg,
1436  claim->GetName(), branchname, claim->GetName());
1437  return 0;
1438  }
1439  return Branch(branchname, classname, (void*) addobj, bufsize, splitlevel);
1440 }
1441 
1442 ////////////////////////////////////////////////////////////////////////////////
1443 /// Same as TTree::Branch but automatic detection of the class name.
1444 /// See TTree::Branch for other details.
1445 
1446 TBranch* TTree::BranchImp(const char* branchname, TClass* ptrClass, void* addobj, Int_t bufsize, Int_t splitlevel)
1448  if (!ptrClass) {
1449  Error("Branch", "The pointer specified for %s is not of a class known to ROOT", branchname);
1450  return 0;
1451  }
1452  TClass* actualClass = 0;
1453  void** addr = (void**) addobj;
1454  if (addr && *addr) {
1455  actualClass = ptrClass->GetActualClass(*addr);
1456  if (!actualClass) {
1457  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",
1458  branchname, ptrClass->GetName());
1459  actualClass = ptrClass;
1460  } else if ((ptrClass != actualClass) && !actualClass->InheritsFrom(ptrClass)) {
1461  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());
1462  return 0;
1463  }
1464  } else {
1465  actualClass = ptrClass;
1466  }
1467  if (actualClass && actualClass->GetCollectionProxy() && dynamic_cast<TEmulatedCollectionProxy*>(actualClass->GetCollectionProxy())) {
1468  Error("Branch", writeStlWithoutProxyMsg,
1469  actualClass->GetName(), branchname, actualClass->GetName());
1470  return 0;
1471  }
1472  return Branch(branchname, actualClass->GetName(), (void*) addobj, bufsize, splitlevel);
1473 }
1474 
1475 ////////////////////////////////////////////////////////////////////////////////
1476 /// Same as TTree::Branch but automatic detection of the class name.
1477 /// See TTree::Branch for other details.
1478 
1479 TBranch* TTree::BranchImpRef(const char* branchname, const char *classname, TClass* ptrClass, void *addobj, Int_t bufsize, Int_t splitlevel)
1481  TClass* claim = TClass::GetClass(classname);
1482  if (!ptrClass) {
1483  if (claim && claim->GetCollectionProxy() && dynamic_cast<TEmulatedCollectionProxy*>(claim->GetCollectionProxy())) {
1484  Error("Branch", writeStlWithoutProxyMsg,
1485  claim->GetName(), branchname, claim->GetName());
1486  return 0;
1487  } else if (claim == 0) {
1488  Error("Branch", "The pointer specified for %s is not of a class known to ROOT and %s is not a known class", branchname, classname);
1489  return 0;
1490  }
1491  ptrClass = claim;
1492  }
1493  TClass* actualClass = 0;
1494  if (!addobj) {
1495  Error("Branch", "Reference interface requires a valid object (for branch: %s)!", branchname);
1496  return 0;
1497  }
1498  actualClass = ptrClass->GetActualClass(addobj);
1499  if (ptrClass && claim) {
1500  if (!(claim->InheritsFrom(ptrClass) || ptrClass->InheritsFrom(claim))) {
1501  // Note we currently do not warn in case of splicing or over-expectation).
1502  if (claim->IsLoaded() && ptrClass->IsLoaded() && strcmp( claim->GetTypeInfo()->name(), ptrClass->GetTypeInfo()->name() ) == 0) {
1503  // The type is the same according to the C++ type_info, we must be in the case of
1504  // a template of Double32_t. This is actually a correct case.
1505  } else {
1506  Error("Branch", "The class requested (%s) for \"%s\" is different from the type of the object passed (%s)",
1507  claim->GetName(), branchname, ptrClass->GetName());
1508  }
1509  } else if (actualClass && (claim != actualClass) && !actualClass->InheritsFrom(claim)) {
1510  if (claim->IsLoaded() && actualClass->IsLoaded() && strcmp( claim->GetTypeInfo()->name(), actualClass->GetTypeInfo()->name() ) == 0) {
1511  // The type is the same according to the C++ type_info, we must be in the case of
1512  // a template of Double32_t. This is actually a correct case.
1513  } else {
1514  Error("Branch", "The actual class (%s) of the object provided for the definition of the branch \"%s\" does not inherit from %s",
1515  actualClass->GetName(), branchname, claim->GetName());
1516  }
1517  }
1518  }
1519  if (!actualClass) {
1520  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",
1521  branchname, ptrClass->GetName());
1522  actualClass = ptrClass;
1523  } else if ((ptrClass != actualClass) && !actualClass->InheritsFrom(ptrClass)) {
1524  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());
1525  return 0;
1526  }
1527  if (actualClass && actualClass->GetCollectionProxy() && dynamic_cast<TEmulatedCollectionProxy*>(actualClass->GetCollectionProxy())) {
1528  Error("Branch", writeStlWithoutProxyMsg,
1529  actualClass->GetName(), branchname, actualClass->GetName());
1530  return 0;
1531  }
1532  return BronchExec(branchname, actualClass->GetName(), (void*) addobj, kFALSE, bufsize, splitlevel);
1533 }
1534 
1535 ////////////////////////////////////////////////////////////////////////////////
1536 /// Same as TTree::Branch but automatic detection of the class name.
1537 /// See TTree::Branch for other details.
1538 
1539 TBranch* TTree::BranchImpRef(const char* branchname, TClass* ptrClass, EDataType datatype, void* addobj, Int_t bufsize, Int_t splitlevel)
1541  if (!ptrClass) {
1542  if (datatype == kOther_t || datatype == kNoType_t) {
1543  Error("Branch", "The pointer specified for %s is not of a class or type known to ROOT", branchname);
1544  } else {
1545  TString varname; varname.Form("%s/%c",branchname,DataTypeToChar(datatype));
1546  return Branch(branchname,addobj,varname.Data(),bufsize);
1547  }
1548  return 0;
1549  }
1550  TClass* actualClass = 0;
1551  if (!addobj) {
1552  Error("Branch", "Reference interface requires a valid object (for branch: %s)!", branchname);
1553  return 0;
1554  }
1555  actualClass = ptrClass->GetActualClass(addobj);
1556  if (!actualClass) {
1557  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",
1558  branchname, ptrClass->GetName());
1559  actualClass = ptrClass;
1560  } else if ((ptrClass != actualClass) && !actualClass->InheritsFrom(ptrClass)) {
1561  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());
1562  return 0;
1563  }
1564  if (actualClass && actualClass->GetCollectionProxy() && dynamic_cast<TEmulatedCollectionProxy*>(actualClass->GetCollectionProxy())) {
1565  Error("Branch", writeStlWithoutProxyMsg,
1566  actualClass->GetName(), branchname, actualClass->GetName());
1567  return 0;
1568  }
1569  return BronchExec(branchname, actualClass->GetName(), (void*) addobj, kFALSE, bufsize, splitlevel);
1570 }
1571 
1572 ////////////////////////////////////////////////////////////////////////////////
1573 /// Deprecated function. Use next function instead.
1574 
1575 Int_t TTree::Branch(TList* li, Int_t bufsize /* = 32000 */ , Int_t splitlevel /* = 99 */)
1577  return Branch((TCollection*) li, bufsize, splitlevel);
1578 }
1579 
1580 ////////////////////////////////////////////////////////////////////////////////
1581 /// Create one branch for each element in the collection.
1582 ///
1583 /// Each entry in the collection becomes a top level branch if the
1584 /// corresponding class is not a collection. If it is a collection, the entry
1585 /// in the collection becomes in turn top level branches, etc.
1586 /// The splitlevel is decreased by 1 every time a new collection is found.
1587 /// For example if list is a TObjArray*
1588 /// - if splitlevel = 1, one top level branch is created for each element
1589 /// of the TObjArray.
1590 /// - if splitlevel = 2, one top level branch is created for each array element.
1591 /// if, in turn, one of the array elements is a TCollection, one top level
1592 /// branch will be created for each element of this collection.
1593 ///
1594 /// In case a collection element is a TClonesArray, the special Tree constructor
1595 /// for TClonesArray is called.
1596 /// The collection itself cannot be a TClonesArray.
1597 ///
1598 /// The function returns the total number of branches created.
1599 ///
1600 /// If name is given, all branch names will be prefixed with name_.
1601 ///
1602 /// IMPORTANT NOTE1: This function should not be called with splitlevel < 1.
1603 ///
1604 /// IMPORTANT NOTE2: The branches created by this function will have names
1605 /// corresponding to the collection or object names. It is important
1606 /// to give names to collections to avoid misleading branch names or
1607 /// identical branch names. By default collections have a name equal to
1608 /// the corresponding class name, e.g. the default name for a TList is "TList".
1609 ///
1610 /// And in general in any cases two or more master branches contain subbranches
1611 /// with identical names, one must add a "." (dot) character at the end
1612 /// of the master branch name. This will force the name of the subbranch
1613 /// to be master.subbranch instead of simply subbranch.
1614 /// This situation happens when the top level object (say event)
1615 /// has two or more members referencing the same class.
1616 /// For example, if a Tree has two branches B1 and B2 corresponding
1617 /// to objects of the same class MyClass, one can do:
1618 /// ~~~ {.cpp}
1619 /// tree.Branch("B1.","MyClass",&b1,8000,1);
1620 /// tree.Branch("B2.","MyClass",&b2,8000,1);
1621 /// ~~~
1622 /// if MyClass has 3 members a,b,c, the two instructions above will generate
1623 /// subbranches called B1.a, B1.b ,B1.c, B2.a, B2.b, B2.c
1624 ///
1625 /// Example:
1626 /// ~~~ {.cpp}
1627 /// {
1628 /// TTree T("T","test list");
1629 /// TList *list = new TList();
1630 ///
1631 /// TObjArray *a1 = new TObjArray();
1632 /// a1->SetName("a1");
1633 /// list->Add(a1);
1634 /// TH1F *ha1a = new TH1F("ha1a","ha1",100,0,1);
1635 /// TH1F *ha1b = new TH1F("ha1b","ha1",100,0,1);
1636 /// a1->Add(ha1a);
1637 /// a1->Add(ha1b);
1638 /// TObjArray *b1 = new TObjArray();
1639 /// b1->SetName("b1");
1640 /// list->Add(b1);
1641 /// TH1F *hb1a = new TH1F("hb1a","hb1",100,0,1);
1642 /// TH1F *hb1b = new TH1F("hb1b","hb1",100,0,1);
1643 /// b1->Add(hb1a);
1644 /// b1->Add(hb1b);
1645 ///
1646 /// TObjArray *a2 = new TObjArray();
1647 /// a2->SetName("a2");
1648 /// list->Add(a2);
1649 /// TH1S *ha2a = new TH1S("ha2a","ha2",100,0,1);
1650 /// TH1S *ha2b = new TH1S("ha2b","ha2",100,0,1);
1651 /// a2->Add(ha2a);
1652 /// a2->Add(ha2b);
1653 ///
1654 /// T.Branch(list,16000,2);
1655 /// T.Print();
1656 /// }
1657 /// ~~~
1658 
1659 Int_t TTree::Branch(TCollection* li, Int_t bufsize /* = 32000 */, Int_t splitlevel /* = 99 */, const char* name /* = "" */)
1661 
1662  if (!li) {
1663  return 0;
1664  }
1665  TObject* obj = 0;
1666  Int_t nbranches = GetListOfBranches()->GetEntries();
1667  if (li->InheritsFrom(TClonesArray::Class())) {
1668  Error("Branch", "Cannot call this constructor for a TClonesArray");
1669  return 0;
1670  }
1671  Int_t nch = strlen(name);
1672  TString branchname;
1673  TIter next(li);
1674  while ((obj = next())) {
1675  if ((splitlevel > 1) && obj->InheritsFrom(TCollection::Class()) && !obj->InheritsFrom(TClonesArray::Class())) {
1676  TCollection* col = (TCollection*) obj;
1677  if (nch) {
1678  branchname.Form("%s_%s_", name, col->GetName());
1679  } else {
1680  branchname.Form("%s_", col->GetName());
1681  }
1682  Branch(col, bufsize, splitlevel - 1, branchname);
1683  } else {
1684  if (nch && (name[nch-1] == '_')) {
1685  branchname.Form("%s%s", name, obj->GetName());
1686  } else {
1687  if (nch) {
1688  branchname.Form("%s_%s", name, obj->GetName());
1689  } else {
1690  branchname.Form("%s", obj->GetName());
1691  }
1692  }
1693  if (splitlevel > 99) {
1694  branchname += ".";
1695  }
1696  Bronch(branchname, obj->ClassName(), li->GetObjectRef(obj), bufsize, splitlevel - 1);
1697  }
1698  }
1699  return GetListOfBranches()->GetEntries() - nbranches;
1700 }
1701 
1702 ////////////////////////////////////////////////////////////////////////////////
1703 /// Create one branch for each element in the folder.
1704 /// Returns the total number of branches created.
1705 
1706 Int_t TTree::Branch(const char* foldername, Int_t bufsize /* = 32000 */, Int_t splitlevel /* = 99 */)
1708  TObject* ob = gROOT->FindObjectAny(foldername);
1709  if (!ob) {
1710  return 0;
1711  }
1712  if (ob->IsA() != TFolder::Class()) {
1713  return 0;
1714  }
1715  Int_t nbranches = GetListOfBranches()->GetEntries();
1716  TFolder* folder = (TFolder*) ob;
1717  TIter next(folder->GetListOfFolders());
1718  TObject* obj = 0;
1719  char* curname = new char[1000];
1720  char occur[20];
1721  while ((obj = next())) {
1722  snprintf(curname,1000, "%s/%s", foldername, obj->GetName());
1723  if (obj->IsA() == TFolder::Class()) {
1724  Branch(curname, bufsize, splitlevel - 1);
1725  } else {
1726  void* add = (void*) folder->GetListOfFolders()->GetObjectRef(obj);
1727  for (Int_t i = 0; i < 1000; ++i) {
1728  if (curname[i] == 0) {
1729  break;
1730  }
1731  if (curname[i] == '/') {
1732  curname[i] = '.';
1733  }
1734  }
1735  Int_t noccur = folder->Occurence(obj);
1736  if (noccur > 0) {
1737  snprintf(occur,20, "_%d", noccur);
1738  strlcat(curname, occur,1000);
1739  }
1740  TBranchElement* br = (TBranchElement*) Bronch(curname, obj->ClassName(), add, bufsize, splitlevel - 1);
1741  if (br) br->SetBranchFolder();
1742  }
1743  }
1744  delete[] curname;
1745  return GetListOfBranches()->GetEntries() - nbranches;
1746 }
1747 
1748 ////////////////////////////////////////////////////////////////////////////////
1749 /// Create a new TTree Branch.
1750 ///
1751 /// This Branch constructor is provided to support non-objects in
1752 /// a Tree. The variables described in leaflist may be simple
1753 /// variables or structures. // See the two following
1754 /// constructors for writing objects in a Tree.
1755 ///
1756 /// By default the branch buffers are stored in the same file as the Tree.
1757 /// use TBranch::SetFile to specify a different file
1758 ///
1759 /// * address is the address of the first item of a structure.
1760 /// * leaflist is the concatenation of all the variable names and types
1761 /// separated by a colon character :
1762 /// The variable name and the variable type are separated by a slash (/).
1763 /// The variable type may be 0,1 or 2 characters. If no type is given,
1764 /// the type of the variable is assumed to be the same as the previous
1765 /// variable. If the first variable does not have a type, it is assumed
1766 /// of type F by default. The list of currently supported types is given below:
1767 /// - `C` : a character string terminated by the 0 character
1768 /// - `B` : an 8 bit signed integer (`Char_t`)
1769 /// - `b` : an 8 bit unsigned integer (`UChar_t`)
1770 /// - `S` : a 16 bit signed integer (`Short_t`)
1771 /// - `s` : a 16 bit unsigned integer (`UShort_t`)
1772 /// - `I` : a 32 bit signed integer (`Int_t`)
1773 /// - `i` : a 32 bit unsigned integer (`UInt_t`)
1774 /// - `F` : a 32 bit floating point (`Float_t`)
1775 /// - `D` : a 64 bit floating point (`Double_t`)
1776 /// - `L` : a 64 bit signed integer (`Long64_t`)
1777 /// - `l` : a 64 bit unsigned integer (`ULong64_t`)
1778 /// - `O` : [the letter `o`, not a zero] a boolean (`Bool_t`)
1779 ///
1780 /// Arrays of values are supported with the following syntax:
1781 /// - If leaf name has the form var[nelem], where nelem is alphanumeric, then
1782 /// if nelem is a leaf name, it is used as the variable size of the array,
1783 /// otherwise return 0.
1784 /// - If leaf name has the form var[nelem], where nelem is a non-negative integer, then
1785 /// it is used as the fixed size of the array.
1786 /// - If leaf name has the form of a multi-dimensional array (e.g. var[nelem][nelem2])
1787 /// where nelem and nelem2 are non-negative integer) then
1788 /// it is used as a 2 dimensional array of fixed size.
1789 ///
1790 /// Any of other form is not supported.
1791 ///
1792 /// Note that the TTree will assume that all the item are contiguous in memory.
1793 /// On some platform, this is not always true of the member of a struct or a class,
1794 /// due to padding and alignment. Sorting your data member in order of decreasing
1795 /// sizeof usually leads to their being contiguous in memory.
1796 ///
1797 /// * bufsize is the buffer size in bytes for this branch
1798 /// The default value is 32000 bytes and should be ok for most cases.
1799 /// You can specify a larger value (e.g. 256000) if your Tree is not split
1800 /// and each entry is large (Megabytes)
1801 /// A small value for bufsize is optimum if you intend to access
1802 /// the entries in the Tree randomly and your Tree is in split mode.
1803 
1804 TBranch* TTree::Branch(const char* name, void* address, const char* leaflist, Int_t bufsize /* = 32000 */)
1806  TBranch* branch = new TBranch(this, name, address, leaflist, bufsize);
1807  if (branch->IsZombie()) {
1808  delete branch;
1809  branch = 0;
1810  return 0;
1811  }
1812  fBranches.Add(branch);
1813  return branch;
1814 }
1815 
1816 ////////////////////////////////////////////////////////////////////////////////
1817 /// Create a new branch with the object of class classname at address addobj.
1818 ///
1819 /// WARNING:
1820 ///
1821 /// Starting with Root version 3.01, the Branch function uses the new style
1822 /// branches (TBranchElement). To get the old behaviour, you can:
1823 /// - call BranchOld or
1824 /// - call TTree::SetBranchStyle(0)
1825 ///
1826 /// Note that with the new style, classname does not need to derive from TObject.
1827 /// It must derived from TObject if the branch style has been set to 0 (old)
1828 ///
1829 /// Note: See the comments in TBranchElement::SetAddress() for a more
1830 /// detailed discussion of the meaning of the addobj parameter in
1831 /// the case of new-style branches.
1832 ///
1833 /// Use splitlevel < 0 instead of splitlevel=0 when the class
1834 /// has a custom Streamer
1835 ///
1836 /// Note: if the split level is set to the default (99), TTree::Branch will
1837 /// not issue a warning if the class can not be split.
1838 
1839 TBranch* TTree::Branch(const char* name, const char* classname, void* addobj, Int_t bufsize /* = 32000 */, Int_t splitlevel /* = 99 */)
1841  if (fgBranchStyle == 1) {
1842  return Bronch(name, classname, addobj, bufsize, splitlevel);
1843  } else {
1844  if (splitlevel < 0) {
1845  splitlevel = 0;
1846  }
1847  return BranchOld(name, classname, addobj, bufsize, splitlevel);
1848  }
1849 }
1850 
1851 ////////////////////////////////////////////////////////////////////////////////
1852 /// Create a new TTree BranchObject.
1853 ///
1854 /// Build a TBranchObject for an object of class classname.
1855 /// addobj is the address of a pointer to an object of class classname.
1856 /// IMPORTANT: classname must derive from TObject.
1857 /// The class dictionary must be available (ClassDef in class header).
1858 ///
1859 /// This option requires access to the library where the corresponding class
1860 /// is defined. Accessing one single data member in the object implies
1861 /// reading the full object.
1862 /// See the next Branch constructor for a more efficient storage
1863 /// in case the entry consists of arrays of identical objects.
1864 ///
1865 /// By default the branch buffers are stored in the same file as the Tree.
1866 /// use TBranch::SetFile to specify a different file
1867 ///
1868 /// IMPORTANT NOTE about branch names:
1869 ///
1870 /// In case two or more master branches contain subbranches with
1871 /// identical names, one must add a "." (dot) character at the end
1872 /// of the master branch name. This will force the name of the subbranch
1873 /// to be master.subbranch instead of simply subbranch.
1874 /// This situation happens when the top level object (say event)
1875 /// has two or more members referencing the same class.
1876 /// For example, if a Tree has two branches B1 and B2 corresponding
1877 /// to objects of the same class MyClass, one can do:
1878 /// ~~~ {.cpp}
1879 /// tree.Branch("B1.","MyClass",&b1,8000,1);
1880 /// tree.Branch("B2.","MyClass",&b2,8000,1);
1881 /// ~~~
1882 /// if MyClass has 3 members a,b,c, the two instructions above will generate
1883 /// subbranches called B1.a, B1.b ,B1.c, B2.a, B2.b, B2.c
1884 ///
1885 /// bufsize is the buffer size in bytes for this branch
1886 /// The default value is 32000 bytes and should be ok for most cases.
1887 /// You can specify a larger value (e.g. 256000) if your Tree is not split
1888 /// and each entry is large (Megabytes)
1889 /// A small value for bufsize is optimum if you intend to access
1890 /// the entries in the Tree randomly and your Tree is in split mode.
1891 
1892 TBranch* TTree::BranchOld(const char* name, const char* classname, void* addobj, Int_t bufsize /* = 32000 */, Int_t splitlevel /* = 1 */)
1894  TClass* cl = TClass::GetClass(classname);
1895  if (!cl) {
1896  Error("BranchOld", "Cannot find class: '%s'", classname);
1897  return 0;
1898  }
1899  if (!cl->IsTObject()) {
1900  if (fgBranchStyle == 0) {
1901  Fatal("BranchOld", "The requested class ('%s') does not inherit from TObject.\n"
1902  "\tfgBranchStyle is set to zero requesting by default to use BranchOld.\n"
1903  "\tIf this is intentional use Bronch instead of Branch or BranchOld.", classname);
1904  } else {
1905  Fatal("BranchOld", "The requested class ('%s') does not inherit from TObject.\n"
1906  "\tYou can not use BranchOld to store objects of this type.",classname);
1907  }
1908  return 0;
1909  }
1910  TBranch* branch = new TBranchObject(this, name, classname, addobj, bufsize, splitlevel);
1911  fBranches.Add(branch);
1912  if (!splitlevel) {
1913  return branch;
1914  }
1915  // We are going to fully split the class now.
1916  TObjArray* blist = branch->GetListOfBranches();
1917  const char* rdname = 0;
1918  const char* dname = 0;
1919  TString branchname;
1920  char** apointer = (char**) addobj;
1921  TObject* obj = (TObject*) *apointer;
1922  Bool_t delobj = kFALSE;
1923  if (!obj) {
1924  obj = (TObject*) cl->New();
1925  delobj = kTRUE;
1926  }
1927  // Build the StreamerInfo if first time for the class.
1928  BuildStreamerInfo(cl, obj);
1929  // Loop on all public data members of the class and its base classes.
1930  Int_t lenName = strlen(name);
1931  Int_t isDot = 0;
1932  if (name[lenName-1] == '.') {
1933  isDot = 1;
1934  }
1935  TBranch* branch1 = 0;
1936  TRealData* rd = 0;
1937  TRealData* rdi = 0;
1938  TIter nexti(cl->GetListOfRealData());
1939  TIter next(cl->GetListOfRealData());
1940  // Note: This loop results in a full split because the
1941  // real data list includes all data members of
1942  // data members.
1943  while ((rd = (TRealData*) next())) {
1944  if (rd->TestBit(TRealData::kTransient)) continue;
1945 
1946  // Loop over all data members creating branches for each one.
1947  TDataMember* dm = rd->GetDataMember();
1948  if (!dm->IsPersistent()) {
1949  // Do not process members with an "!" as the first character in the comment field.
1950  continue;
1951  }
1952  if (rd->IsObject()) {
1953  // We skip data members of class type.
1954  // But we do build their real data, their
1955  // streamer info, and write their streamer
1956  // info to the current directory's file.
1957  // Oh yes, and we also do this for all of
1958  // their base classes.
1959  TClass* clm = TClass::GetClass(dm->GetFullTypeName());
1960  if (clm) {
1961  BuildStreamerInfo(clm, (char*) obj + rd->GetThisOffset());
1962  }
1963  continue;
1964  }
1965  rdname = rd->GetName();
1966  dname = dm->GetName();
1967  if (cl->CanIgnoreTObjectStreamer()) {
1968  // Skip the TObject base class data members.
1969  // FIXME: This prevents a user from ever
1970  // using these names themself!
1971  if (!strcmp(dname, "fBits")) {
1972  continue;
1973  }
1974  if (!strcmp(dname, "fUniqueID")) {
1975  continue;
1976  }
1977  }
1978  TDataType* dtype = dm->GetDataType();
1979  Int_t code = 0;
1980  if (dtype) {
1981  code = dm->GetDataType()->GetType();
1982  }
1983  // Encode branch name. Use real data member name
1984  branchname = rdname;
1985  if (isDot) {
1986  if (dm->IsaPointer()) {
1987  // FIXME: This is wrong! The asterisk is not usually in the front!
1988  branchname.Form("%s%s", name, &rdname[1]);
1989  } else {
1990  branchname.Form("%s%s", name, &rdname[0]);
1991  }
1992  }
1993  // FIXME: Change this to a string stream.
1994  TString leaflist;
1995  Int_t offset = rd->GetThisOffset();
1996  char* pointer = ((char*) obj) + offset;
1997  if (dm->IsaPointer()) {
1998  // We have a pointer to an object or a pointer to an array of basic types.
1999  TClass* clobj = 0;
2000  if (!dm->IsBasic()) {
2001  clobj = TClass::GetClass(dm->GetTypeName());
2002  }
2003  if (clobj && clobj->InheritsFrom(TClonesArray::Class())) {
2004  // We have a pointer to a clones array.
2005  char* cpointer = (char*) pointer;
2006  char** ppointer = (char**) cpointer;
2007  TClonesArray* li = (TClonesArray*) *ppointer;
2008  if (splitlevel != 2) {
2009  if (isDot) {
2010  branch1 = new TBranchClones(branch,branchname, pointer, bufsize);
2011  } else {
2012  // FIXME: This is wrong! The asterisk is not usually in the front!
2013  branch1 = new TBranchClones(branch,&branchname.Data()[1], pointer, bufsize);
2014  }
2015  blist->Add(branch1);
2016  } else {
2017  if (isDot) {
2018  branch1 = new TBranchObject(branch, branchname, li->ClassName(), pointer, bufsize);
2019  } else {
2020  // FIXME: This is wrong! The asterisk is not usually in the front!
2021  branch1 = new TBranchObject(branch, &branchname.Data()[1], li->ClassName(), pointer, bufsize);
2022  }
2023  blist->Add(branch1);
2024  }
2025  } else if (clobj) {
2026  // We have a pointer to an object.
2027  //
2028  // It must be a TObject object.
2029  if (!clobj->IsTObject()) {
2030  continue;
2031  }
2032  branch1 = new TBranchObject(branch, dname, clobj->GetName(), pointer, bufsize, 0);
2033  if (isDot) {
2034  branch1->SetName(branchname);
2035  } else {
2036  // FIXME: This is wrong! The asterisk is not usually in the front!
2037  // Do not use the first character (*).
2038  branch1->SetName(&branchname.Data()[1]);
2039  }
2040  blist->Add(branch1);
2041  } else {
2042  // We have a pointer to an array of basic types.
2043  //
2044  // Check the comments in the text of the code for an index specification.
2045  const char* index = dm->GetArrayIndex();
2046  if (index[0]) {
2047  // We are a pointer to a varying length array of basic types.
2048  //check that index is a valid data member name
2049  //if member is part of an object (e.g. fA and index=fN)
2050  //index must be changed from fN to fA.fN
2051  TString aindex (rd->GetName());
2052  Ssiz_t rdot = aindex.Last('.');
2053  if (rdot>=0) {
2054  aindex.Remove(rdot+1);
2055  aindex.Append(index);
2056  }
2057  nexti.Reset();
2058  while ((rdi = (TRealData*) nexti())) {
2059  if (rdi->TestBit(TRealData::kTransient)) continue;
2060 
2061  if (!strcmp(rdi->GetName(), index)) {
2062  break;
2063  }
2064  if (!strcmp(rdi->GetName(), aindex)) {
2065  index = rdi->GetName();
2066  break;
2067  }
2068  }
2069 
2070  char vcode = DataTypeToChar((EDataType)code);
2071  // Note that we differentiate between strings and
2072  // char array by the fact that there is NO specified
2073  // size for a string (see next if (code == 1)
2074 
2075  if (vcode) {
2076  leaflist.Form("%s[%s]/%c", &rdname[0], index, vcode);
2077  } else {
2078  Error("BranchOld", "Cannot create branch for rdname: %s code: %d", branchname.Data(), code);
2079  leaflist = "";
2080  }
2081  } else {
2082  // We are possibly a character string.
2083  if (code == 1) {
2084  // We are a character string.
2085  leaflist.Form("%s/%s", dname, "C");
2086  } else {
2087  // Invalid array specification.
2088  // FIXME: We need an error message here.
2089  continue;
2090  }
2091  }
2092  // There are '*' in both the branchname and leaflist, remove them.
2093  TString bname( branchname );
2094  bname.ReplaceAll("*","");
2095  leaflist.ReplaceAll("*","");
2096  // Add the branch to the tree and indicate that the address
2097  // is that of a pointer to be dereferenced before using.
2098  branch1 = new TBranch(branch, bname, *((void**) pointer), leaflist, bufsize);
2099  TLeaf* leaf = (TLeaf*) branch1->GetListOfLeaves()->At(0);
2101  leaf->SetAddress((void**) pointer);
2102  blist->Add(branch1);
2103  }
2104  } else if (dm->IsBasic()) {
2105  // We have a basic type.
2106 
2107  char vcode = DataTypeToChar((EDataType)code);
2108  if (vcode) {
2109  leaflist.Form("%s/%c", rdname, vcode);
2110  } else {
2111  Error("BranchOld", "Cannot create branch for rdname: %s code: %d", branchname.Data(), code);
2112  leaflist = "";
2113  }
2114  branch1 = new TBranch(branch, branchname, pointer, leaflist, bufsize);
2115  branch1->SetTitle(rdname);
2116  blist->Add(branch1);
2117  } else {
2118  // We have a class type.
2119  // Note: This cannot happen due to the rd->IsObject() test above.
2120  // FIXME: Put an error message here just in case.
2121  }
2122  if (branch1) {
2123  branch1->SetOffset(offset);
2124  } else {
2125  Warning("BranchOld", "Cannot process member: '%s'", rdname);
2126  }
2127  }
2128  if (delobj) {
2129  delete obj;
2130  obj = 0;
2131  }
2132  return branch;
2133 }
2134 
2135 ////////////////////////////////////////////////////////////////////////////////
2136 /// Build the optional branch supporting the TRefTable.
2137 /// This branch will keep all the information to find the branches
2138 /// containing referenced objects.
2139 ///
2140 /// At each Tree::Fill, the branch numbers containing the
2141 /// referenced objects are saved to the TBranchRef basket.
2142 /// When the Tree header is saved (via TTree::Write), the branch
2143 /// is saved keeping the information with the pointers to the branches
2144 /// having referenced objects.
2145 
2148  if (!fBranchRef) {
2149  fBranchRef = new TBranchRef(this);
2150  }
2151  return fBranchRef;
2152 }
2153 
2154 ////////////////////////////////////////////////////////////////////////////////
2155 /// Create a new TTree BranchElement.
2156 ///
2157 /// ## WARNING about this new function
2158 ///
2159 /// This function is designed to replace the internal
2160 /// implementation of the old TTree::Branch (whose implementation
2161 /// has been moved to BranchOld).
2162 ///
2163 /// NOTE: The 'Bronch' method supports only one possible calls
2164 /// signature (where the object type has to be specified
2165 /// explicitly and the address must be the address of a pointer).
2166 /// For more flexibility use 'Branch'. Use Bronch only in (rare)
2167 /// cases (likely to be legacy cases) where both the new and old
2168 /// implementation of Branch needs to be used at the same time.
2169 ///
2170 /// This function is far more powerful than the old Branch
2171 /// function. It supports the full C++, including STL and has
2172 /// the same behaviour in split or non-split mode. classname does
2173 /// not have to derive from TObject. The function is based on
2174 /// the new TStreamerInfo.
2175 ///
2176 /// Build a TBranchElement for an object of class classname.
2177 ///
2178 /// addr is the address of a pointer to an object of class
2179 /// classname. The class dictionary must be available (ClassDef
2180 /// in class header).
2181 ///
2182 /// Note: See the comments in TBranchElement::SetAddress() for a more
2183 /// detailed discussion of the meaning of the addr parameter.
2184 ///
2185 /// This option requires access to the library where the
2186 /// corresponding class is defined. Accessing one single data
2187 /// member in the object implies reading the full object.
2188 ///
2189 /// By default the branch buffers are stored in the same file as the Tree.
2190 /// use TBranch::SetFile to specify a different file
2191 ///
2192 /// IMPORTANT NOTE about branch names:
2193 ///
2194 /// In case two or more master branches contain subbranches with
2195 /// identical names, one must add a "." (dot) character at the end
2196 /// of the master branch name. This will force the name of the subbranch
2197 /// to be master.subbranch instead of simply subbranch.
2198 /// This situation happens when the top level object (say event)
2199 /// has two or more members referencing the same class.
2200 /// For example, if a Tree has two branches B1 and B2 corresponding
2201 /// to objects of the same class MyClass, one can do:
2202 /// ~~~ {.cpp}
2203 /// tree.Branch("B1.","MyClass",&b1,8000,1);
2204 /// tree.Branch("B2.","MyClass",&b2,8000,1);
2205 /// ~~~
2206 /// if MyClass has 3 members a,b,c, the two instructions above will generate
2207 /// subbranches called B1.a, B1.b ,B1.c, B2.a, B2.b, B2.c
2208 ///
2209 /// bufsize is the buffer size in bytes for this branch
2210 /// The default value is 32000 bytes and should be ok for most cases.
2211 /// You can specify a larger value (e.g. 256000) if your Tree is not split
2212 /// and each entry is large (Megabytes)
2213 /// A small value for bufsize is optimum if you intend to access
2214 /// the entries in the Tree randomly and your Tree is in split mode.
2215 ///
2216 /// Use splitlevel < 0 instead of splitlevel=0 when the class
2217 /// has a custom Streamer
2218 ///
2219 /// Note: if the split level is set to the default (99), TTree::Branch will
2220 /// not issue a warning if the class can not be split.
2221 
2222 TBranch* TTree::Bronch(const char* name, const char* classname, void* addr, Int_t bufsize /* = 32000 */, Int_t splitlevel /* = 99 */)
2224  return BronchExec(name, classname, addr, kTRUE, bufsize, splitlevel);
2225 }
2226 
2227 ////////////////////////////////////////////////////////////////////////////////
2228 /// Helper function implementing TTree::Bronch and TTree::Branch(const char *name, T &obj);
2229 
2230 TBranch* TTree::BronchExec(const char* name, const char* classname, void* addr, Bool_t isptrptr, Int_t bufsize /* = 32000 */, Int_t splitlevel /* = 99 */)
2232  TClass* cl = TClass::GetClass(classname);
2233  if (!cl) {
2234  Error("Bronch", "Cannot find class:%s", classname);
2235  return 0;
2236  }
2237 
2238  //if splitlevel <= 0 and class has a custom Streamer, we must create
2239  //a TBranchObject. We cannot assume that TClass::ReadBuffer is consistent
2240  //with the custom Streamer. The penalty is that one cannot process
2241  //this Tree without the class library containing the class.
2242 
2243  char* objptr = 0;
2244  if (!isptrptr) {
2245  objptr = (char*)addr;
2246  } else if (addr) {
2247  objptr = *((char**) addr);
2248  }
2249 
2250  if (cl == TClonesArray::Class()) {
2251  TClonesArray* clones = (TClonesArray*) objptr;
2252  if (!clones) {
2253  Error("Bronch", "Pointer to TClonesArray is null");
2254  return 0;
2255  }
2256  if (!clones->GetClass()) {
2257  Error("Bronch", "TClonesArray with no class defined in branch: %s", name);
2258  return 0;
2259  }
2260  if (!clones->GetClass()->HasDataMemberInfo()) {
2261  Error("Bronch", "TClonesArray with no dictionary defined in branch: %s", name);
2262  return 0;
2263  }
2264  bool hasCustomStreamer = clones->GetClass()->TestBit(TClass::kHasCustomStreamerMember);
2265  if (splitlevel > 0) {
2266  if (hasCustomStreamer)
2267  Warning("Bronch", "Using split mode on a class: %s with a custom Streamer", clones->GetClass()->GetName());
2268  } else {
2269  if (hasCustomStreamer) clones->BypassStreamer(kFALSE);
2270  TBranchObject *branch = new TBranchObject(this,name,classname,addr,bufsize,0,/*compress=*/ -1,isptrptr);
2271  fBranches.Add(branch);
2272  return branch;
2273  }
2274  }
2275 
2276  if (cl->GetCollectionProxy()) {
2277  TVirtualCollectionProxy* collProxy = cl->GetCollectionProxy();
2278  //if (!collProxy) {
2279  // Error("Bronch", "%s is missing its CollectionProxy (for branch %s)", classname, name);
2280  //}
2281  TClass* inklass = collProxy->GetValueClass();
2282  if (!inklass && (collProxy->GetType() == 0)) {
2283  Error("Bronch", "%s with no class defined in branch: %s", classname, name);
2284  return 0;
2285  }
2286  if ((splitlevel > 0) && inklass && (inklass->GetCollectionProxy() == 0)) {
2287  ROOT::ESTLType stl = cl->GetCollectionType();
2288  if ((stl != ROOT::kSTLmap) && (stl != ROOT::kSTLmultimap)) {
2289  if (!inklass->HasDataMemberInfo()) {
2290  Error("Bronch", "Container with no dictionary defined in branch: %s", name);
2291  return 0;
2292  }
2293  if (inklass->TestBit(TClass::kHasCustomStreamerMember)) {
2294  Warning("Bronch", "Using split mode on a class: %s with a custom Streamer", inklass->GetName());
2295  }
2296  }
2297  }
2298  //-------------------------------------------------------------------------
2299  // If the splitting switch is enabled, the split level is big enough and
2300  // the collection contains pointers we can split it
2301  //////////////////////////////////////////////////////////////////////////
2302 
2303  TBranch *branch;
2304  if( splitlevel > kSplitCollectionOfPointers && collProxy->HasPointers() )
2305  branch = new TBranchSTL( this, name, collProxy, bufsize, splitlevel );
2306  else
2307  branch = new TBranchElement(this, name, collProxy, bufsize, splitlevel);
2308  fBranches.Add(branch);
2309  if (isptrptr) {
2310  branch->SetAddress(addr);
2311  } else {
2312  branch->SetObject(addr);
2313  }
2314  return branch;
2315  }
2316 
2317  Bool_t hasCustomStreamer = kFALSE;
2318  if (!cl->HasDataMemberInfo() && !cl->GetCollectionProxy()) {
2319  Error("Bronch", "Cannot find dictionary for class: %s", classname);
2320  return 0;
2321  }
2322 
2324  // Not an STL container and the linkdef file had a "-" after the class name.
2325  hasCustomStreamer = kTRUE;
2326  }
2327 
2328  if (splitlevel < 0 || ((splitlevel == 0) && hasCustomStreamer && cl->IsTObject())) {
2329  TBranchObject* branch = new TBranchObject(this, name, classname, addr, bufsize, 0, /*compress=*/ -1, isptrptr);
2330  fBranches.Add(branch);
2331  return branch;
2332  }
2333 
2334  if (cl == TClonesArray::Class()) {
2335  // Special case of TClonesArray.
2336  // No dummy object is created.
2337  // The streamer info is not rebuilt unoptimized.
2338  // No dummy top-level branch is created.
2339  // No splitting is attempted.
2340  TBranchElement* branch = new TBranchElement(this, name, (TClonesArray*) objptr, bufsize, splitlevel%kSplitCollectionOfPointers);
2341  fBranches.Add(branch);
2342  if (isptrptr) {
2343  branch->SetAddress(addr);
2344  } else {
2345  branch->SetObject(addr);
2346  }
2347  return branch;
2348  }
2349 
2350  //
2351  // If we are not given an object to use as an i/o buffer
2352  // then create a temporary one which we will delete just
2353  // before returning.
2354  //
2355 
2356  Bool_t delobj = kFALSE;
2357 
2358  if (!objptr) {
2359  objptr = (char*) cl->New();
2360  delobj = kTRUE;
2361  }
2362 
2363  //
2364  // Avoid splitting unsplittable classes.
2365  //
2366 
2367  if ((splitlevel > 0) && !cl->CanSplit()) {
2368  if (splitlevel != 99) {
2369  Warning("Bronch", "%s cannot be split, resetting splitlevel to 0", cl->GetName());
2370  }
2371  splitlevel = 0;
2372  }
2373 
2374  //
2375  // Make sure the streamer info is built and fetch it.
2376  //
2377  // If we are splitting, then make sure the streamer info
2378  // is built unoptimized (data members are not combined).
2379  //
2380 
2381  TStreamerInfo* sinfo = BuildStreamerInfo(cl, objptr, splitlevel==0);
2382  if (!sinfo) {
2383  Error("Bronch", "Cannot build the StreamerInfo for class: %s", cl->GetName());
2384  return 0;
2385  }
2386 
2387  //
2388  // Do we have a final dot in our name?
2389  //
2390 
2391  // Note: The branch constructor which takes a folder as input
2392  // creates top-level branch names with dots in them to
2393  // indicate the folder hierarchy.
2394  char* dot = (char*) strchr(name, '.');
2395  Int_t nch = strlen(name);
2396  Bool_t dotlast = kFALSE;
2397  if (nch && (name[nch-1] == '.')) {
2398  dotlast = kTRUE;
2399  }
2400 
2401  //
2402  // Create a dummy top level branch object.
2403  //
2404 
2405  Int_t id = -1;
2406  if (splitlevel > 0) {
2407  id = -2;
2408  }
2409  TBranchElement* branch = new TBranchElement(this, name, sinfo, id, objptr, bufsize, splitlevel);
2410  fBranches.Add(branch);
2411 
2412  //
2413  // Do splitting, if requested.
2414  //
2415 
2416  if (splitlevel%kSplitCollectionOfPointers > 0) {
2417  // Loop on all public data members of the class and its base classes and create branches for each one.
2418  TObjArray* blist = branch->GetListOfBranches();
2419  TIter next(sinfo->GetElements());
2420  TStreamerElement* element = 0;
2421  TString bname;
2422  for (id = 0; (element = (TStreamerElement*) next()); ++id) {
2423  if (element->IsA() == TStreamerArtificial::Class()) {
2424  continue;
2425  }
2426  if (element->TestBit(TStreamerElement::kRepeat)) {
2427  continue;
2428  }
2429  if (element->TestBit(TStreamerElement::kCache) && !element->TestBit(TStreamerElement::kWrite)) {
2430  continue;
2431  }
2432  char* pointer = (char*) (objptr + element->GetOffset());
2433  // FIXME: This is not good enough, an STL container can be
2434  // a base, and the test will fail.
2435  // See TBranchElement::InitializeOffsets() for the
2436  // correct test.
2437  Bool_t isBase = (element->IsA() == TStreamerBase::Class());
2438  if (isBase) {
2439  TClass* clbase = element->GetClassPointer();
2440  if ((clbase == TObject::Class()) && cl->CanIgnoreTObjectStreamer()) {
2441  // Note: TStreamerInfo::Compile() leaves this element
2442  // out of the optimized info, although it does
2443  // exists in the non-compiled and non-optimized info.
2444  // FIXME: The test that TStreamerInfo::Compile() uses
2445  // is element->GetType() < 0, so that is what
2446  // we should do as well.
2447  continue;
2448  }
2449  if (clbase->GetListOfRealData()->GetSize() == 0) {
2450  // Do not create a branch for empty bases.
2451  continue;
2452  }
2453  }
2454  if (dot) {
2455  if (dotlast) {
2456  bname.Form("%s%s", name, element->GetFullName());
2457  } else {
2458  // FIXME: We are in the case where we have a top-level
2459  // branch name that was created by the branch
2460  // constructor which takes a folder as input.
2461  // The internal dots in the name are in place of
2462  // of the original slashes and represent the
2463  // folder hierarchy.
2464  if (isBase) {
2465  // FIXME: This is very strange, this is the only case where
2466  // we create a branch for a base class that does
2467  // not have the base class name in the branch name.
2468  // FIXME: This is also quite bad since classes with two
2469  // or more base classes end up with sub-branches
2470  // that have the same name.
2471  bname = name;
2472  } else {
2473  bname.Form("%s.%s", name, element->GetFullName());
2474  }
2475  }
2476  } else {
2477  // Note: For a base class element, this results in the branchname
2478  // being the name of the base class.
2479  bname.Form("%s", element->GetFullName());
2480  }
2481 
2482  if( splitlevel > kSplitCollectionOfPointers && element->GetClass() &&
2483  element->GetClass()->GetCollectionProxy() &&
2484  element->GetClass()->GetCollectionProxy()->HasPointers() )
2485  {
2486  TBranchSTL* brSTL = new TBranchSTL( branch, bname, element->GetClass()->GetCollectionProxy(), bufsize, splitlevel-1, sinfo, id );
2487  blist->Add(brSTL);
2488  }
2489  else
2490  {
2491  TBranchElement* bre = new TBranchElement(branch, bname, sinfo, id, pointer, bufsize, splitlevel - 1);
2492  bre->SetParentClass(cl);
2493  blist->Add(bre);
2494  }
2495  }
2496  }
2497 
2498  //
2499  // Setup our offsets into the user's i/o buffer.
2500  //
2501 
2502  if (isptrptr) {
2503  branch->SetAddress(addr);
2504  } else {
2505  branch->SetObject(addr);
2506  }
2507 
2508  if (delobj) {
2509  cl->Destructor(objptr);
2510  objptr = 0;
2511  }
2512 
2513  return branch;
2514 }
2515 
2516 ////////////////////////////////////////////////////////////////////////////////
2517 /// Browse content of the TTree.
2518 
2519 void TTree::Browse(TBrowser* b)
2521  fBranches.Browse(b);
2522  if (fUserInfo) {
2523  if (strcmp("TList",fUserInfo->GetName())==0) {
2524  fUserInfo->SetName("UserInfo");
2525  b->Add(fUserInfo);
2526  fUserInfo->SetName("TList");
2527  } else {
2528  b->Add(fUserInfo);
2529  }
2530  }
2531 }
2532 
2533 ////////////////////////////////////////////////////////////////////////////////
2534 /// Build a Tree Index (default is TTreeIndex).
2535 /// See a description of the parameters and functionality in
2536 /// TTreeIndex::TTreeIndex().
2537 ///
2538 /// The return value is the number of entries in the Index (< 0 indicates failure).
2539 ///
2540 /// A TTreeIndex object pointed by fTreeIndex is created.
2541 /// This object will be automatically deleted by the TTree destructor.
2542 /// See also comments in TTree::SetTreeIndex().
2543 
2544 Int_t TTree::BuildIndex(const char* majorname, const char* minorname /* = "0" */)
2546  fTreeIndex = GetPlayer()->BuildIndex(this, majorname, minorname);
2547  if (fTreeIndex->IsZombie()) {
2548  delete fTreeIndex;
2549  fTreeIndex = 0;
2550  return 0;
2551  }
2552  return fTreeIndex->GetN();
2553 }
2554 
2555 ////////////////////////////////////////////////////////////////////////////////
2556 /// Build StreamerInfo for class cl.
2557 /// pointer is an optional argument that may contain a pointer to an object of cl.
2558 
2559 TStreamerInfo* TTree::BuildStreamerInfo(TClass* cl, void* pointer /* = 0 */, Bool_t canOptimize /* = kTRUE */ )
2561  if (!cl) {
2562  return 0;
2563  }
2564  cl->BuildRealData(pointer);
2566 
2567  // Create StreamerInfo for all base classes.
2568  TBaseClass* base = 0;
2569  TIter nextb(cl->GetListOfBases());
2570  while((base = (TBaseClass*) nextb())) {
2571  if (base->IsSTLContainer()) {
2572  continue;
2573  }
2574  TClass* clm = TClass::GetClass(base->GetName());
2575  BuildStreamerInfo(clm, pointer, canOptimize);
2576  }
2577  if (sinfo && fDirectory) {
2578  sinfo->ForceWriteInfo(fDirectory->GetFile());
2579  }
2580  return sinfo;
2581 }
2582 
2583 ////////////////////////////////////////////////////////////////////////////////
2584 /// Called by TTree::Fill() when file has reached its maximum fgMaxTreeSize.
2585 /// Create a new file. If the original file is named "myfile.root",
2586 /// subsequent files are named "myfile_1.root", "myfile_2.root", etc.
2587 ///
2588 /// Returns a pointer to the new file.
2589 ///
2590 /// Currently, the automatic change of file is restricted
2591 /// to the case where the tree is in the top level directory.
2592 /// The file should not contain sub-directories.
2593 ///
2594 /// Before switching to a new file, the tree header is written
2595 /// to the current file, then the current file is closed.
2596 ///
2597 /// To process the multiple files created by ChangeFile, one must use
2598 /// a TChain.
2599 ///
2600 /// The new file name has a suffix "_N" where N is equal to fFileNumber+1.
2601 /// By default a Root session starts with fFileNumber=0. One can set
2602 /// fFileNumber to a different value via TTree::SetFileNumber.
2603 /// In case a file named "_N" already exists, the function will try
2604 /// a file named "__N", then "___N", etc.
2605 ///
2606 /// fgMaxTreeSize can be set via the static function TTree::SetMaxTreeSize.
2607 /// The default value of fgMaxTreeSize is 100 Gigabytes.
2608 ///
2609 /// If the current file contains other objects like TH1 and TTree,
2610 /// these objects are automatically moved to the new file.
2611 ///
2612 /// IMPORTANT NOTE:
2613 ///
2614 /// Be careful when writing the final Tree header to the file!
2615 ///
2616 /// Don't do:
2617 /// ~~~ {.cpp}
2618 /// TFile *file = new TFile("myfile.root","recreate");
2619 /// TTree *T = new TTree("T","title");
2620 /// T->Fill(); //loop
2621 /// file->Write();
2622 /// file->Close();
2623 /// ~~~
2624 /// but do the following:
2625 /// ~~~ {.cpp}
2626 /// TFile *file = new TFile("myfile.root","recreate");
2627 /// TTree *T = new TTree("T","title");
2628 /// T->Fill(); //loop
2629 /// file = T->GetCurrentFile(); //to get the pointer to the current file
2630 /// file->Write();
2631 /// file->Close();
2632 /// ~~~
2633 
2636  file->cd();
2637  Write();
2638  Reset();
2639  char* fname = new char[2000];
2640  ++fFileNumber;
2641  char uscore[10];
2642  for (Int_t i = 0; i < 10; ++i) {
2643  uscore[i] = 0;
2644  }
2645  Int_t nus = 0;
2646  // Try to find a suitable file name that does not already exist.
2647  while (nus < 10) {
2648  uscore[nus] = '_';
2649  fname[0] = 0;
2650  strlcpy(fname, file->GetName(),2000);
2651 
2652  if (fFileNumber > 1) {
2653  char* cunder = strrchr(fname, '_');
2654  if (cunder) {
2655  snprintf(cunder,2000-Int_t(cunder-fname), "%s%d", uscore, fFileNumber);
2656  const char* cdot = strrchr(file->GetName(), '.');
2657  if (cdot) {
2658  strlcat(fname, cdot,2000);
2659  }
2660  } else {
2661  char fcount[10];
2662  snprintf(fcount,10, "%s%d", uscore, fFileNumber);
2663  strlcat(fname, fcount,2000);
2664  }
2665  } else {
2666  char* cdot = strrchr(fname, '.');
2667  if (cdot) {
2668  snprintf(cdot,2000-Int_t(fname-cdot), "%s%d", uscore, fFileNumber);
2669  strlcat(fname, strrchr(file->GetName(), '.'),2000);
2670  } else {
2671  char fcount[10];
2672  snprintf(fcount,10, "%s%d", uscore, fFileNumber);
2673  strlcat(fname, fcount,2000);
2674  }
2675  }
2676  if (gSystem->AccessPathName(fname)) {
2677  break;
2678  }
2679  ++nus;
2680  Warning("ChangeFile", "file %s already exist, trying with %d underscores", fname, nus+1);
2681  }
2682  Int_t compress = file->GetCompressionSettings();
2683  TFile* newfile = TFile::Open(fname, "recreate", "chain files", compress);
2684  if (newfile == 0) {
2685  Error("Fill","Failed to open new file %s, continuing as a memory tree.",fname);
2686  } else {
2687  Printf("Fill: Switching to new file: %s", fname);
2688  }
2689  // The current directory may contain histograms and trees.
2690  // These objects must be moved to the new file.
2691  TBranch* branch = 0;
2692  TObject* obj = 0;
2693  while ((obj = file->GetList()->First())) {
2694  file->Remove(obj);
2695  // Histogram: just change the directory.
2696  if (obj->InheritsFrom("TH1")) {
2697  gROOT->ProcessLine(TString::Format("((%s*)0x%lx)->SetDirectory((TDirectory*)0x%lx);", obj->ClassName(), (Long_t) obj, (Long_t) newfile));
2698  continue;
2699  }
2700  // Tree: must save all trees in the old file, reset them.
2701  if (obj->InheritsFrom(TTree::Class())) {
2702  TTree* t = (TTree*) obj;
2703  if (t != this) {
2704  t->AutoSave();
2705  t->Reset();
2706  t->fFileNumber = fFileNumber;
2707  }
2708  t->SetDirectory(newfile);
2709  TIter nextb(t->GetListOfBranches());
2710  while ((branch = (TBranch*)nextb())) {
2711  branch->SetFile(newfile);
2712  }
2713  if (t->GetBranchRef()) {
2714  t->GetBranchRef()->SetFile(newfile);
2715  }
2716  continue;
2717  }
2718  // Not a TH1 or a TTree, move object to new file.
2719  if (newfile) newfile->Append(obj);
2720  file->Remove(obj);
2721  }
2722  delete file;
2723  file = 0;
2724  delete[] fname;
2725  fname = 0;
2726  return newfile;
2727 }
2728 
2729 ////////////////////////////////////////////////////////////////////////////////
2730 /// Check whether or not the address described by the last 3 parameters
2731 /// matches the content of the branch. If a Data Model Evolution conversion
2732 /// is involved, reset the fInfo of the branch.
2733 /// The return values are:
2734 //
2735 /// - kMissingBranch (-5) : Missing branch
2736 /// - kInternalError (-4) : Internal error (could not find the type corresponding to a data type number)
2737 /// - kMissingCompiledCollectionProxy (-3) : Missing compiled collection proxy for a compiled collection
2738 /// - kMismatch (-2) : Non-Class Pointer type given does not match the type expected by the branch
2739 /// - kClassMismatch (-1) : Class Pointer type given does not match the type expected by the branch
2740 /// - kMatch (0) : perfect match
2741 /// - kMatchConversion (1) : match with (I/O) conversion
2742 /// - kMatchConversionCollection (2) : match with (I/O) conversion of the content of a collection
2743 /// - kMakeClass (3) : MakeClass mode so we can not check.
2744 /// - kVoidPtr (4) : void* passed so no check was made.
2745 /// - kNoCheck (5) : Underlying TBranch not yet available so no check was made.
2746 
2747 Int_t TTree::CheckBranchAddressType(TBranch* branch, TClass* ptrClass, EDataType datatype, Bool_t isptr)
2749  if (GetMakeClass()) {
2750  // If we are in MakeClass mode so we do not really use classes.
2751  return kMakeClass;
2752  }
2753 
2754  // Let's determine what we need!
2755  TClass* expectedClass = 0;
2756  EDataType expectedType = kOther_t;
2757  if (0 != branch->GetExpectedType(expectedClass,expectedType) ) {
2758  // Something went wrong, the warning message has already be issued.
2759  return kInternalError;
2760  }
2761  if (expectedClass && datatype == kOther_t && ptrClass == 0) {
2762  if (branch->InheritsFrom( TBranchElement::Class() )) {
2763  TBranchElement* bEl = (TBranchElement*)branch;
2764  bEl->SetTargetClass( expectedClass->GetName() );
2765  }
2766  if (expectedClass && expectedClass->GetCollectionProxy() && dynamic_cast<TEmulatedCollectionProxy*>(expectedClass->GetCollectionProxy())) {
2767  Error("SetBranchAddress", "Unable to determine the type given for the address for \"%s\". "
2768  "The class expected (%s) refers to an stl collection and do not have a compiled CollectionProxy. "
2769  "Please generate the dictionary for this class (%s)",
2770  branch->GetName(), expectedClass->GetName(), expectedClass->GetName());
2772  }
2773  if (!expectedClass->IsLoaded()) {
2774  // The originally expected class does not have a dictionary, it is then plausible that the pointer being passed is the right type
2775  // (we really don't know). So let's express that.
2776  Error("SetBranchAddress", "Unable to determine the type given for the address for \"%s\". "
2777  "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."
2778  "Please generate the dictionary for this class (%s)",
2779  branch->GetName(), expectedClass->GetName(), expectedClass->GetName());
2780  } else {
2781  Error("SetBranchAddress", "Unable to determine the type given for the address for \"%s\". "
2782  "This is probably due to a missing dictionary, the original data class for this branch is %s.", branch->GetName(), expectedClass->GetName());
2783  }
2784  return kClassMismatch;
2785  }
2786  if (expectedClass && ptrClass && (branch->GetMother() == branch)) {
2787  // Top Level branch
2788  if (!isptr) {
2789  Error("SetBranchAddress", "The address for \"%s\" should be the address of a pointer!", branch->GetName());
2790  }
2791  }
2792  if (expectedType == kFloat16_t) {
2793  expectedType = kFloat_t;
2794  }
2795  if (expectedType == kDouble32_t) {
2796  expectedType = kDouble_t;
2797  }
2798  if (datatype == kFloat16_t) {
2799  datatype = kFloat_t;
2800  }
2801  if (datatype == kDouble32_t) {
2802  datatype = kDouble_t;
2803  }
2804 
2805  /////////////////////////////////////////////////////////////////////////////
2806  // Deal with the class renaming
2807  /////////////////////////////////////////////////////////////////////////////
2808 
2809  if( expectedClass && ptrClass &&
2810  expectedClass != ptrClass &&
2811  branch->InheritsFrom( TBranchElement::Class() ) &&
2812  ptrClass->GetSchemaRules() &&
2813  ptrClass->GetSchemaRules()->HasRuleWithSourceClass( expectedClass->GetName() ) ) {
2814  TBranchElement* bEl = (TBranchElement*)branch;
2815 
2816  if ( ptrClass->GetCollectionProxy() && expectedClass->GetCollectionProxy() ) {
2817  if (gDebug > 7)
2818  Info("SetBranchAddress", "Matching STL collection (at least according to the SchemaRuleSet when "
2819  "reading a %s into a %s",expectedClass->GetName(),ptrClass->GetName());
2820 
2821  bEl->SetTargetClass( ptrClass->GetName() );
2822  return kMatchConversion;
2823 
2824  } else if ( !ptrClass->GetConversionStreamerInfo( expectedClass, bEl->GetClassVersion() ) &&
2825  !ptrClass->FindConversionStreamerInfo( expectedClass, bEl->GetCheckSum() ) ) {
2826  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());
2827 
2828  bEl->SetTargetClass( expectedClass->GetName() );
2829  return kClassMismatch;
2830  }
2831  else {
2832 
2833  bEl->SetTargetClass( ptrClass->GetName() );
2834  return kMatchConversion;
2835  }
2836 
2837  } else if (expectedClass && ptrClass && !expectedClass->InheritsFrom(ptrClass)) {
2838 
2839  if (expectedClass->GetCollectionProxy() && ptrClass->GetCollectionProxy() &&
2840  branch->InheritsFrom( TBranchElement::Class() ) &&
2841  expectedClass->GetCollectionProxy()->GetValueClass() &&
2842  ptrClass->GetCollectionProxy()->GetValueClass() )
2843  {
2844  // In case of collection, we know how to convert them, if we know how to convert their content.
2845  // NOTE: we need to extend this to std::pair ...
2846 
2847  TClass *onfileValueClass = expectedClass->GetCollectionProxy()->GetValueClass();
2848  TClass *inmemValueClass = ptrClass->GetCollectionProxy()->GetValueClass();
2849 
2850  if (inmemValueClass->GetSchemaRules() &&
2851  inmemValueClass->GetSchemaRules()->HasRuleWithSourceClass(onfileValueClass->GetName() ) )
2852  {
2853  TBranchElement* bEl = (TBranchElement*)branch;
2854  bEl->SetTargetClass( ptrClass->GetName() );
2856  }
2857  }
2858 
2859  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());
2860  if (branch->InheritsFrom( TBranchElement::Class() )) {
2861  TBranchElement* bEl = (TBranchElement*)branch;
2862  bEl->SetTargetClass( expectedClass->GetName() );
2863  }
2864  return kClassMismatch;
2865 
2866  } else if ((expectedType != kOther_t) && (datatype != kOther_t) && (expectedType != kNoType_t) && (datatype != kNoType_t) && (expectedType != datatype)) {
2867  if (datatype != kChar_t) {
2868  // For backward compatibility we assume that (char*) was just a cast and/or a generic address
2869  Error("SetBranchAddress", "The pointer type given \"%s\" (%d) does not correspond to the type needed \"%s\" (%d) by the branch: %s",
2870  TDataType::GetTypeName(datatype), datatype, TDataType::GetTypeName(expectedType), expectedType, branch->GetName());
2871  return kMismatch;
2872  }
2873  } else if ((expectedClass && (datatype != kOther_t && datatype != kNoType_t && datatype != kInt_t)) ||
2874  (ptrClass && (expectedType != kOther_t && expectedType != kNoType_t && datatype != kInt_t)) ) {
2875  // Sometime a null pointer can look an int, avoid complaining in that case.
2876  if (expectedClass) {
2877  Error("SetBranchAddress", "The pointer type given \"%s\" (%d) does not correspond to the type needed \"%s\" by the branch: %s",
2878  TDataType::GetTypeName(datatype), datatype, expectedClass->GetName(), branch->GetName());
2879  if (branch->InheritsFrom( TBranchElement::Class() )) {
2880  TBranchElement* bEl = (TBranchElement*)branch;
2881  bEl->SetTargetClass( expectedClass->GetName() );
2882  }
2883  } else {
2884  // 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
2885  // a struct).
2886  bool found = false;
2887  if (ptrClass->IsLoaded()) {
2888  TIter next(ptrClass->GetListOfRealData());
2889  TRealData *rdm;
2890  while ((rdm = (TRealData*)next())) {
2891  if (rdm->GetThisOffset() == 0) {
2892  TDataType *dmtype = rdm->GetDataMember()->GetDataType();
2893  if (dmtype) {
2894  EDataType etype = (EDataType)dmtype->GetType();
2895  if (etype == expectedType) {
2896  found = true;
2897  }
2898  }
2899  break;
2900  }
2901  }
2902  } else {
2903  TIter next(ptrClass->GetListOfDataMembers());
2904  TDataMember *dm;
2905  while ((dm = (TDataMember*)next())) {
2906  if (dm->GetOffset() == 0) {
2907  TDataType *dmtype = dm->GetDataType();
2908  if (dmtype) {
2909  EDataType etype = (EDataType)dmtype->GetType();
2910  if (etype == expectedType) {
2911  found = true;
2912  }
2913  }
2914  break;
2915  }
2916  }
2917  }
2918  if (found) {
2919  // let's check the size.
2920  TLeaf *last = (TLeaf*)branch->GetListOfLeaves()->Last();
2921  long len = last->GetOffset() + last->GetLenType() * last->GetLen();
2922  if (len <= ptrClass->Size()) {
2923  return kMatch;
2924  }
2925  }
2926  Error("SetBranchAddress", "The pointer type given \"%s\" does not correspond to the type needed \"%s\" (%d) by the branch: %s",
2927  ptrClass->GetName(), TDataType::GetTypeName(expectedType), expectedType, branch->GetName());
2928  }
2929  return kMismatch;
2930  }
2931  if (expectedClass && expectedClass->GetCollectionProxy() && dynamic_cast<TEmulatedCollectionProxy*>(expectedClass->GetCollectionProxy())) {
2932  Error("SetBranchAddress", writeStlWithoutProxyMsg,
2933  expectedClass->GetName(), branch->GetName(), expectedClass->GetName());
2934  if (branch->InheritsFrom( TBranchElement::Class() )) {
2935  TBranchElement* bEl = (TBranchElement*)branch;
2936  bEl->SetTargetClass( expectedClass->GetName() );
2937  }
2939  }
2940  if (expectedClass && branch->InheritsFrom( TBranchElement::Class() )) {
2941  TBranchElement* bEl = (TBranchElement*)branch;
2942  bEl->SetTargetClass( expectedClass->GetName() );
2943  }
2944  return kMatch;
2945 }
2946 
2947 ////////////////////////////////////////////////////////////////////////////////
2948 /// Create a clone of this tree and copy nentries.
2949 ///
2950 /// By default copy all entries.
2951 /// The compression level of the cloned tree is set to the destination
2952 /// file's compression level.
2953 ///
2954 /// NOTE: Only active branches are copied.
2955 /// NOTE: If the TTree is a TChain, the structure of the first TTree
2956 /// is used for the copy.
2957 ///
2958 /// IMPORTANT: The cloned tree stays connected with this tree until
2959 /// this tree is deleted. In particular, any changes in
2960 /// branch addresses in this tree are forwarded to the
2961 /// clone trees, unless a branch in a clone tree has had
2962 /// its address changed, in which case that change stays in
2963 /// effect. When this tree is deleted, all the addresses of
2964 /// the cloned tree are reset to their default values.
2965 ///
2966 /// If 'option' contains the word 'fast' and nentries is -1, the
2967 /// cloning will be done without unzipping or unstreaming the baskets
2968 /// (i.e., a direct copy of the raw bytes on disk).
2969 ///
2970 /// When 'fast' is specified, 'option' can also contain a sorting
2971 /// order for the baskets in the output file.
2972 ///
2973 /// There are currently 3 supported sorting order:
2974 ///
2975 /// - SortBasketsByOffset (the default)
2976 /// - SortBasketsByBranch
2977 /// - SortBasketsByEntry
2978 ///
2979 /// When using SortBasketsByOffset the baskets are written in the
2980 /// output file in the same order as in the original file (i.e. the
2981 /// baskets are sorted by their offset in the original file; Usually
2982 /// this also means that the baskets are sorted by the index/number of
2983 /// the _last_ entry they contain)
2984 ///
2985 /// When using SortBasketsByBranch all the baskets of each individual
2986 /// branches are stored contiguously. This tends to optimize reading
2987 /// speed when reading a small number (1->5) of branches, since all
2988 /// their baskets will be clustered together instead of being spread
2989 /// across the file. However it might decrease the performance when
2990 /// reading more branches (or the full entry).
2991 ///
2992 /// When using SortBasketsByEntry the baskets with the lowest starting
2993 /// entry are written first. (i.e. the baskets are sorted by the
2994 /// index/number of the first entry they contain). This means that on
2995 /// the file the baskets will be in the order in which they will be
2996 /// needed when reading the whole tree sequentially.
2997 ///
2998 /// For examples of CloneTree, see tutorials:
2999 ///
3000 /// - copytree:
3001 /// A macro to copy a subset of a TTree to a new TTree.
3002 /// The input file has been generated by the program in
3003 /// $ROOTSYS/test/Event with: Event 1000 1 1 1
3004 ///
3005 /// - copytree2:
3006 /// A macro to copy a subset of a TTree to a new TTree.
3007 /// One branch of the new Tree is written to a separate file.
3008 /// The input file has been generated by the program in
3009 /// $ROOTSYS/test/Event with: Event 1000 1 1 1
3010 
3011 TTree* TTree::CloneTree(Long64_t nentries /* = -1 */, Option_t* option /* = "" */)
3013  // Options
3014  Bool_t fastClone = kFALSE;
3015 
3016  TString opt = option;
3017  opt.ToLower();
3018  if (opt.Contains("fast")) {
3019  fastClone = kTRUE;
3020  }
3021 
3022  // If we are a chain, switch to the first tree.
3023  if ((fEntries > 0) && (LoadTree(0) < 0)) {
3024  // FIXME: We need an error message here.
3025  return 0;
3026  }
3027 
3028  // Note: For a tree we get the this pointer, for
3029  // a chain we get the chain's current tree.
3030  TTree* thistree = GetTree();
3031 
3032  // Note: For a chain, the returned clone will be
3033  // a clone of the chain's first tree.
3034  TTree* newtree = (TTree*) thistree->Clone();
3035  if (!newtree) {
3036  return 0;
3037  }
3038 
3039  // The clone should not delete any objects allocated by SetAddress().
3040  TObjArray* branches = newtree->GetListOfBranches();
3041  Int_t nb = branches->GetEntriesFast();
3042  for (Int_t i = 0; i < nb; ++i) {
3043  TBranch* br = (TBranch*) branches->UncheckedAt(i);
3044  if (br->InheritsFrom(TBranchElement::Class())) {
3045  ((TBranchElement*) br)->ResetDeleteObject();
3046  }
3047  }
3048 
3049  // Add the new tree to the list of clones so that
3050  // we can later inform it of changes to branch addresses.
3051  thistree->AddClone(newtree);
3052  if (thistree != this) {
3053  // In case this object is a TChain, add the clone
3054  // also to the TChain's list of clones.
3055  AddClone(newtree);
3056  }
3057 
3058  newtree->Reset();
3059 
3060  TDirectory* ndir = newtree->GetDirectory();
3061  TFile* nfile = 0;
3062  if (ndir) {
3063  nfile = ndir->GetFile();
3064  }
3065  Int_t newcomp = -1;
3066  if (nfile) {
3067  newcomp = nfile->GetCompressionSettings();
3068  }
3069 
3070  //
3071  // Delete non-active branches from the clone.
3072  //
3073  // Note: If we are a chain, this does nothing
3074  // since chains have no leaves.
3075  TObjArray* leaves = newtree->GetListOfLeaves();
3076  Int_t nleaves = leaves->GetEntriesFast();
3077  for (Int_t lndx = 0; lndx < nleaves; ++lndx) {
3078  TLeaf* leaf = (TLeaf*) leaves->UncheckedAt(lndx);
3079  if (!leaf) {
3080  continue;
3081  }
3082  TBranch* branch = leaf->GetBranch();
3083  if (branch && (newcomp > -1)) {
3084  branch->SetCompressionSettings(newcomp);
3085  }
3086  if (!branch || !branch->TestBit(kDoNotProcess)) {
3087  continue;
3088  }
3089  // size might change at each iteration of the loop over the leaves.
3090  nb = branches->GetEntriesFast();
3091  for (Long64_t i = 0; i < nb; ++i) {
3092  TBranch* br = (TBranch*) branches->UncheckedAt(i);
3093  if (br == branch) {
3094  branches->RemoveAt(i);
3095  delete br;
3096  br = 0;
3097  branches->Compress();
3098  break;
3099  }
3100  TObjArray* lb = br->GetListOfBranches();
3101  Int_t nb1 = lb->GetEntriesFast();
3102  for (Int_t j = 0; j < nb1; ++j) {
3103  TBranch* b1 = (TBranch*) lb->UncheckedAt(j);
3104  if (!b1) {
3105  continue;
3106  }
3107  if (b1 == branch) {
3108  lb->RemoveAt(j);
3109  delete b1;
3110  b1 = 0;
3111  lb->Compress();
3112  break;
3113  }
3114  TObjArray* lb1 = b1->GetListOfBranches();
3115  Int_t nb2 = lb1->GetEntriesFast();
3116  for (Int_t k = 0; k < nb2; ++k) {
3117  TBranch* b2 = (TBranch*) lb1->UncheckedAt(k);
3118  if (!b2) {
3119  continue;
3120  }
3121  if (b2 == branch) {
3122  lb1->RemoveAt(k);
3123  delete b2;
3124  b2 = 0;
3125  lb1->Compress();
3126  break;
3127  }
3128  }
3129  }
3130  }
3131  }
3132  leaves->Compress();
3133 
3134  // Copy MakeClass status.
3135  newtree->SetMakeClass(fMakeClass);
3136 
3137  // Copy branch addresses.
3138  CopyAddresses(newtree);
3139 
3140  //
3141  // Copy entries if requested.
3142  //
3143 
3144  if (nentries != 0) {
3145  if (fastClone && (nentries < 0)) {
3146  if ( newtree->CopyEntries( this, -1, option ) < 0 ) {
3147  // There was a problem!
3148  Error("CloneTTree", "TTree has not been cloned\n");
3149  delete newtree;
3150  newtree = 0;
3151  return 0;
3152  }
3153  } else {
3154  newtree->CopyEntries( this, nentries, option );
3155  }
3156  }
3157 
3158  return newtree;
3159 }
3160 
3161 ////////////////////////////////////////////////////////////////////////////////
3162 /// Set branch addresses of passed tree equal to ours.
3163 /// If undo is true, reset the branch address instead of copying them.
3164 /// This insures 'separation' of a cloned tree from its original
3165 
3166 void TTree::CopyAddresses(TTree* tree, Bool_t undo)
3168  // Copy branch addresses starting from branches.
3170  Int_t nbranches = branches->GetEntriesFast();
3171  for (Int_t i = 0; i < nbranches; ++i) {
3172  TBranch* branch = (TBranch*) branches->UncheckedAt(i);
3173  if (branch->TestBit(kDoNotProcess)) {
3174  continue;
3175  }
3176  if (undo) {
3177  TBranch* br = tree->GetBranch(branch->GetName());
3178  tree->ResetBranchAddress(br);
3179  } else {
3180  char* addr = branch->GetAddress();
3181  if (!addr) {
3182  if (branch->IsA() == TBranch::Class()) {
3183  // If the branch was created using a leaflist, the branch itself may not have
3184  // an address but the leaf might already.
3185  TLeaf *firstleaf = (TLeaf*)branch->GetListOfLeaves()->At(0);
3186  if (!firstleaf || firstleaf->GetValuePointer()) {
3187  // Either there is no leaf (and thus no point in copying the address)
3188  // or the leaf has an address but we can not copy it via the branche
3189  // this will be copied via the next loop (over the leaf).
3190  continue;
3191  }
3192  }
3193  // Note: This may cause an object to be allocated.
3194  branch->SetAddress(0);
3195  addr = branch->GetAddress();
3196  }
3197  // FIXME: The GetBranch() function is braindead and may
3198  // not find the branch!
3199  TBranch* br = tree->GetBranch(branch->GetName());
3200  if (br) {
3201  br->SetAddress(addr);
3202  // The copy does not own any object allocated by SetAddress().
3203  if (br->InheritsFrom(TBranchElement::Class())) {
3204  ((TBranchElement*) br)->ResetDeleteObject();
3205  }
3206  } else {
3207  Warning("CopyAddresses", "Could not find branch named '%s' in tree named '%s'", branch->GetName(), tree->GetName());
3208  }
3209  }
3210  }
3211 
3212  // Copy branch addresses starting from leaves.
3213  TObjArray* tleaves = tree->GetListOfLeaves();
3214  Int_t ntleaves = tleaves->GetEntriesFast();
3215  for (Int_t i = 0; i < ntleaves; ++i) {
3216  TLeaf* tleaf = (TLeaf*) tleaves->UncheckedAt(i);
3217  TBranch* tbranch = tleaf->GetBranch();
3218  TBranch* branch = GetBranch(tbranch->GetName());
3219  if (!branch) {
3220  continue;
3221  }
3222  TLeaf* leaf = branch->GetLeaf(tleaf->GetName());
3223  if (!leaf) {
3224  continue;
3225  }
3226  if (branch->TestBit(kDoNotProcess)) {
3227  continue;
3228  }
3229  if (undo) {
3230  // Now we know whether the address has been transfered
3231  tree->ResetBranchAddress(tbranch);
3232  } else {
3233  if (!branch->GetAddress() && !leaf->GetValuePointer()) {
3234  // We should attempts to set the address of the branch.
3235  // something like:
3236  //(TBranchElement*)branch->GetMother()->SetAddress(0)
3237  //plus a few more subtilities (see TBranchElement::GetEntry).
3238  //but for now we go the simplest route:
3239  //
3240  // Note: This may result in the allocation of an object.
3241  branch->SetupAddresses();
3242  }
3243  if (branch->GetAddress()) {
3244  tree->SetBranchAddress(branch->GetName(), (void*) branch->GetAddress());
3245  TBranch* br = tree->GetBranch(branch->GetName());
3246  if (br) {
3247  // The copy does not own any object allocated by SetAddress().
3248  // FIXME: We do too much here, br may not be a top-level branch.
3249  if (br->InheritsFrom(TBranchElement::Class())) {
3250  ((TBranchElement*) br)->ResetDeleteObject();
3251  }
3252  } else {
3253  Warning("CopyAddresses", "Could not find branch named '%s' in tree named '%s'", branch->GetName(), tree->GetName());
3254  }
3255  } else {
3256  tleaf->SetAddress(leaf->GetValuePointer());
3257  }
3258  }
3259  }
3260 
3261  if (undo &&
3262  ( tree->IsA()->InheritsFrom("TNtuple") || tree->IsA()->InheritsFrom("TNtupleD") )
3263  ) {
3264  tree->ResetBranchAddresses();
3265  }
3266 }
3267 
3268 namespace {
3269 
3270  enum EOnIndexError { kDrop, kKeep, kBuild };
3272  static Bool_t R__HandleIndex(EOnIndexError onIndexError, TTree *newtree, TTree *oldtree)
3273  {
3274  // Return true if we should continue to handle indices, false otherwise.
3275 
3276  Bool_t withIndex = kTRUE;
3277 
3278  if ( newtree->GetTreeIndex() ) {
3279  if ( oldtree->GetTree()->GetTreeIndex() == 0 ) {
3280  switch (onIndexError) {
3281  case kDrop:
3282  delete newtree->GetTreeIndex();
3283  newtree->SetTreeIndex(0);
3284  withIndex = kFALSE;
3285  break;
3286  case kKeep:
3287  // Nothing to do really.
3288  break;
3289  case kBuild:
3290  // Build the index then copy it
3291  if (oldtree->GetTree()->BuildIndex(newtree->GetTreeIndex()->GetMajorName(), newtree->GetTreeIndex()->GetMinorName())) {
3292  newtree->GetTreeIndex()->Append(oldtree->GetTree()->GetTreeIndex(), kTRUE);
3293  // Clean up
3294  delete oldtree->GetTree()->GetTreeIndex();
3295  oldtree->GetTree()->SetTreeIndex(0);
3296  }
3297  break;
3298  }
3299  } else {
3300  newtree->GetTreeIndex()->Append(oldtree->GetTree()->GetTreeIndex(), kTRUE);
3301  }
3302  } else if ( oldtree->GetTree()->GetTreeIndex() != 0 ) {
3303  // We discover the first index in the middle of the chain.
3304  switch (onIndexError) {
3305  case kDrop:
3306  // Nothing to do really.
3307  break;
3308  case kKeep: {
3309  TVirtualIndex *index = (TVirtualIndex*) oldtree->GetTree()->GetTreeIndex()->Clone();
3310  index->SetTree(newtree);
3311  newtree->SetTreeIndex(index);
3312  break;
3313  }
3314  case kBuild:
3315  if (newtree->GetEntries() == 0) {
3316  // Start an index.
3317  TVirtualIndex *index = (TVirtualIndex*) oldtree->GetTree()->GetTreeIndex()->Clone();
3318  index->SetTree(newtree);
3319  newtree->SetTreeIndex(index);
3320  } else {
3321  // Build the index so far.
3322  if (newtree->BuildIndex(oldtree->GetTree()->GetTreeIndex()->GetMajorName(), oldtree->GetTree()->GetTreeIndex()->GetMinorName())) {
3323  newtree->GetTreeIndex()->Append(oldtree->GetTree()->GetTreeIndex(), kTRUE);
3324  }
3325  }
3326  break;
3327  }
3328  } else if ( onIndexError == kDrop ) {
3329  // There is no index on this or on tree->GetTree(), we know we have to ignore any further
3330  // index
3331  withIndex = kFALSE;
3332  }
3333  return withIndex;
3334  }
3335 }
3336 
3337 ////////////////////////////////////////////////////////////////////////////////
3338 /// Copy nentries from given tree to this tree.
3339 /// This routines assumes that the branches that intended to be copied are
3340 /// already connected. The typical case is that this tree was created using
3341 /// tree->CloneTree(0).
3342 ///
3343 /// By default copy all entries.
3344 ///
3345 /// Returns number of bytes copied to this tree.
3346 ///
3347 /// If 'option' contains the word 'fast' and nentries is -1, the cloning will be
3348 /// done without unzipping or unstreaming the baskets (i.e., a direct copy of the
3349 /// raw bytes on disk).
3350 ///
3351 /// When 'fast' is specified, 'option' can also contains a sorting order for the
3352 /// baskets in the output file.
3353 ///
3354 /// There are currently 3 supported sorting order:
3355 ///
3356 /// - SortBasketsByOffset (the default)
3357 /// - SortBasketsByBranch
3358 /// - SortBasketsByEntry
3359 ///
3360 /// See TTree::CloneTree for a detailed explanation of the semantics of these 3 options.
3361 ///
3362 /// If the tree or any of the underlying tree of the chain has an index, that index and any
3363 /// index in the subsequent underlying TTree objects will be merged.
3364 ///
3365 /// There are currently three 'options' to control this merging:
3366 /// - NoIndex : all the TTreeIndex object are dropped.
3367 /// - DropIndexOnError : if any of the underlying TTree object do no have a TTreeIndex,
3368 /// they are all dropped.
3369 /// - AsIsIndexOnError [default]: In case of missing TTreeIndex, the resulting TTree index has gaps.
3370 /// - BuildIndexOnError : If any of the underlying TTree objects do not have a TTreeIndex,
3371 /// all TTreeIndex are 'ignored' and the missing piece are rebuilt.
3372 
3373 Long64_t TTree::CopyEntries(TTree* tree, Long64_t nentries /* = -1 */, Option_t* option /* = "" */)
3375  if (!tree) {
3376  return 0;
3377  }
3378  // Options
3379  TString opt = option;
3380  opt.ToLower();
3381  Bool_t fastClone = opt.Contains("fast");
3382  Bool_t withIndex = !opt.Contains("noindex");
3383  EOnIndexError onIndexError;
3384  if (opt.Contains("asisindex")) {
3385  onIndexError = kKeep;
3386  } else if (opt.Contains("buildindex")) {
3387  onIndexError = kBuild;
3388  } else if (opt.Contains("dropindex")) {
3389  onIndexError = kDrop;
3390  } else {
3391  onIndexError = kBuild;
3392  }
3393  Ssiz_t cacheSizeLoc = opt.Index("cachesize=");
3394  Int_t cacheSize = -1;
3395  if (cacheSizeLoc != TString::kNPOS) {
3396  // If the parse faile, cacheSize stays at -1.
3397  Ssiz_t cacheSizeEnd = opt.Index(" ",cacheSizeLoc+10) - (cacheSizeLoc+10);
3398  TSubString cacheSizeStr( opt(cacheSizeLoc+10,cacheSizeEnd) );
3399  auto parseResult = ROOT::FromHumanReadableSize(cacheSizeStr,cacheSize);
3400  if (parseResult == ROOT::EFromHumanReadableSize::kParseFail) {
3401  Warning("CopyEntries","The cachesize option can not be parsed: %s. The default size will be used.",cacheSizeStr.String().Data());
3402  } else if (parseResult == ROOT::EFromHumanReadableSize::kOverflow) {
3403  double m;
3404  const char *munit = nullptr;
3405  ROOT::ToHumanReadableSize(std::numeric_limits<decltype(cacheSize)>::max(),false,&m,&munit);
3406 
3407  Warning("CopyEntries","The cachesize option is too large: %s (%g%s max). The default size will be used.",cacheSizeStr.String().Data(),m,munit);
3408  }
3409  }
3410  if (gDebug > 0 && cacheSize != -1) Info("CopyEntries","Using Cache size: %d\n",cacheSize);
3411 
3412  Long64_t nbytes = 0;
3413  Long64_t treeEntries = tree->GetEntriesFast();
3414  if (nentries < 0) {
3415  nentries = treeEntries;
3416  } else if (nentries > treeEntries) {
3417  nentries = treeEntries;
3418  }
3419 
3420  if (fastClone && (nentries < 0 || nentries == tree->GetEntriesFast())) {
3421  // Quickly copy the basket without decompression and streaming.
3422  Long64_t totbytes = GetTotBytes();
3423  for (Long64_t i = 0; i < nentries; i += tree->GetTree()->GetEntries()) {
3424  if (tree->LoadTree(i) < 0) {
3425  break;
3426  }
3427  if ( withIndex ) {
3428  withIndex = R__HandleIndex( onIndexError, this, tree );
3429  }
3430  if (this->GetDirectory()) {
3431  TFile* file2 = this->GetDirectory()->GetFile();
3432  if (file2 && (file2->GetEND() > TTree::GetMaxTreeSize())) {
3433  if (this->GetDirectory() == (TDirectory*) file2) {
3434  this->ChangeFile(file2);
3435  }
3436  }
3437  }
3438  TTreeCloner cloner(tree->GetTree(), this, option, TTreeCloner::kNoWarnings);
3439  if (cloner.IsValid()) {
3440  this->SetEntries(this->GetEntries() + tree->GetTree()->GetEntries());
3441  if (cacheSize != -1) cloner.SetCacheSize(cacheSize);
3442  cloner.Exec();
3443  } else {
3444  if (i == 0) {
3445  Warning("CopyEntries","%s",cloner.GetWarning());
3446  // If the first cloning does not work, something is really wrong
3447  // (since apriori the source and target are exactly the same structure!)
3448  return -1;
3449  } else {
3450  if (cloner.NeedConversion()) {
3451  TTree *localtree = tree->GetTree();
3452  Long64_t tentries = localtree->GetEntries();
3453  for (Long64_t ii = 0; ii < tentries; ii++) {
3454  if (localtree->GetEntry(ii) <= 0) {
3455  break;
3456  }
3457  this->Fill();
3458  }
3459  if (this->GetTreeIndex()) {
3460  this->GetTreeIndex()->Append(tree->GetTree()->GetTreeIndex(), kTRUE);
3461  }
3462  } else {
3463  Warning("CopyEntries","%s",cloner.GetWarning());
3464  if (tree->GetDirectory() && tree->GetDirectory()->GetFile()) {
3465  Warning("CopyEntries", "Skipped file %s\n", tree->GetDirectory()->GetFile()->GetName());
3466  } else {
3467  Warning("CopyEntries", "Skipped file number %d\n", tree->GetTreeNumber());
3468  }
3469  }
3470  }
3471  }
3472 
3473  }
3474  if (this->GetTreeIndex()) {
3475  this->GetTreeIndex()->Append(0,kFALSE); // Force the sorting
3476  }
3477  nbytes = GetTotBytes() - totbytes;
3478  } else {
3479  if (nentries < 0) {
3480  nentries = treeEntries;
3481  } else if (nentries > treeEntries) {
3482  nentries = treeEntries;
3483  }
3484  Int_t treenumber = -1;
3485  for (Long64_t i = 0; i < nentries; i++) {
3486  if (tree->LoadTree(i) < 0) {
3487  break;
3488  }
3489  if (treenumber != tree->GetTreeNumber()) {
3490  if ( withIndex ) {
3491  withIndex = R__HandleIndex( onIndexError, this, tree );
3492  }
3493  treenumber = tree->GetTreeNumber();
3494  }
3495  if (tree->GetEntry(i) <= 0) {
3496  break;
3497  }
3498  nbytes += this->Fill();
3499  }
3500  if (this->GetTreeIndex()) {
3501  this->GetTreeIndex()->Append(0,kFALSE); // Force the sorting
3502  }
3503  }
3504  return nbytes;
3505 }
3506 
3507 ////////////////////////////////////////////////////////////////////////////////
3508 /// Copy a tree with selection.
3509 ///
3510 /// IMPORTANT:
3511 ///
3512 /// The returned copied tree stays connected with the original tree
3513 /// until the original tree is deleted. In particular, any changes
3514 /// to the branch addresses in the original tree are also made to
3515 /// the copied tree. Any changes made to the branch addresses of the
3516 /// copied tree are overridden anytime the original tree changes its
3517 /// branch addresses. When the original tree is deleted, all the
3518 /// branch addresses of the copied tree are set to zero.
3519 ///
3520 /// For examples of CopyTree, see the tutorials:
3521 ///
3522 /// - copytree:
3523 /// Example macro to copy a subset of a tree to a new tree.
3524 /// The input file was generated by running the program in
3525 /// $ROOTSYS/test/Event in this way:
3526 /// ~~~ {.cpp}
3527 /// ./Event 1000 1 1 1
3528 /// ~~~
3529 /// - copytree2
3530 /// Example macro to copy a subset of a tree to a new tree.
3531 /// One branch of the new tree is written to a separate file.
3532 /// The input file was generated by running the program in
3533 /// $ROOTSYS/test/Event in this way:
3534 /// ~~~ {.cpp}
3535 /// ./Event 1000 1 1 1
3536 /// ~~~
3537 /// - copytree3
3538 /// Example macro to copy a subset of a tree to a new tree.
3539 /// Only selected entries are copied to the new tree.
3540 /// NOTE that only the active branches are copied.
3541 
3542 TTree* TTree::CopyTree(const char* selection, Option_t* option /* = 0 */, Long64_t nentries /* = TTree::kMaxEntries */, Long64_t firstentry /* = 0 */)
3544  GetPlayer();
3545  if (fPlayer) {
3546  return fPlayer->CopyTree(selection, option, nentries, firstentry);
3547  }
3548  return 0;
3549 }
3550 
3551 ////////////////////////////////////////////////////////////////////////////////
3552 /// Create a basket for this tree and given branch.
3553 
3556  if (!branch) {
3557  return 0;
3558  }
3559  return new TBasket(branch->GetName(), GetName(), branch);
3560 }
3561 
3562 ////////////////////////////////////////////////////////////////////////////////
3563 /// Delete this tree from memory or/and disk.
3564 ///
3565 /// - if option == "all" delete Tree object from memory AND from disk
3566 /// all baskets on disk are deleted. All keys with same name
3567 /// are deleted.
3568 /// - if option =="" only Tree object in memory is deleted.
3569 
3570 void TTree::Delete(Option_t* option /* = "" */)
3572  TFile *file = GetCurrentFile();
3573 
3574  // delete all baskets and header from file
3575  if (file && !strcmp(option,"all")) {
3576  if (!file->IsWritable()) {
3577  Error("Delete","File : %s is not writable, cannot delete Tree:%s", file->GetName(),GetName());
3578  return;
3579  }
3580 
3581  //find key and import Tree header in memory
3582  TKey *key = fDirectory->GetKey(GetName());
3583  if (!key) return;
3584 
3585  TDirectory *dirsav = gDirectory;
3586  file->cd();
3587 
3588  //get list of leaves and loop on all the branches baskets
3589  TIter next(GetListOfLeaves());
3590  TLeaf *leaf;
3591  char header[16];
3592  Int_t ntot = 0;
3593  Int_t nbask = 0;
3594  Int_t nbytes,objlen,keylen;
3595  while ((leaf = (TLeaf*)next())) {
3596  TBranch *branch = leaf->GetBranch();
3597  Int_t nbaskets = branch->GetMaxBaskets();
3598  for (Int_t i=0;i<nbaskets;i++) {
3599  Long64_t pos = branch->GetBasketSeek(i);
3600  if (!pos) continue;
3601  TFile *branchFile = branch->GetFile();
3602  if (!branchFile) continue;
3603  branchFile->GetRecordHeader(header,pos,16,nbytes,objlen,keylen);
3604  if (nbytes <= 0) continue;
3605  branchFile->MakeFree(pos,pos+nbytes-1);
3606  ntot += nbytes;
3607  nbask++;
3608  }
3609  }
3610 
3611  // delete Tree header key and all keys with the same name
3612  // A Tree may have been saved many times. Previous cycles are invalid.
3613  while (key) {
3614  ntot += key->GetNbytes();
3615  key->Delete();
3616  delete key;
3617  key = fDirectory->GetKey(GetName());
3618  }
3619  if (dirsav) dirsav->cd();
3620  if (gDebug) Info("TTree::Delete", "Deleting Tree: %s: %d baskets deleted. Total space freed = %d bytes\n",GetName(),nbask,ntot);
3621  }
3622 
3623  if (fDirectory) {
3624  fDirectory->Remove(this);
3625  //delete the file cache if it points to this Tree
3626  MoveReadCache(file,0);
3627  fDirectory = 0;
3629  }
3630 
3631  // Delete object from CINT symbol table so it can not be used anymore.
3632  gCling->DeleteGlobal(this);
3633 
3634  // Warning: We have intentional invalidated this object while inside a member function!
3635  delete this;
3636 }
3637 
3638  ///////////////////////////////////////////////////////////////////////////////
3639  /// Called by TKey and TObject::Clone to automatically add us to a directory
3640  /// when we are read from a file.
3641 
3644  if (fDirectory == dir) return;
3645  if (fDirectory) {
3646  fDirectory->Remove(this);
3647  // Delete or move the file cache if it points to this Tree
3648  TFile *file = fDirectory->GetFile();
3649  MoveReadCache(file,dir);
3650  }
3651  fDirectory = dir;
3652  TBranch* b = 0;
3653  TIter next(GetListOfBranches());
3654  while((b = (TBranch*) next())) {
3655  b->UpdateFile();
3656  }
3657  if (fBranchRef) {
3659  }
3660  if (fDirectory) fDirectory->Append(this);
3661 }
3662 
3663 ////////////////////////////////////////////////////////////////////////////////
3664 /// Draw expression varexp for specified entries.
3665 /// Returns -1 in case of error or number of selected events in case of success.
3666 ///
3667 /// This function accepts TCut objects as arguments.
3668 /// Useful to use the string operator +
3669 ///
3670 /// Example:
3671 ///
3672 /// ntuple.Draw("x",cut1+cut2+cut3);
3673 
3674 Long64_t TTree::Draw(const char* varexp, const TCut& selection, Option_t* option, Long64_t nentries, Long64_t firstentry)
3676  return TTree::Draw(varexp, selection.GetTitle(), option, nentries, firstentry);
3677 }
3678 
3679 ////////////////////////////////////////////////////////////////////////////////
3680 /// Draw expression varexp for specified entries.
3681 /// Returns -1 in case of error or number of selected events in case of success.
3682 ///
3683 /// varexp is an expression of the general form
3684 /// - "e1" produces a 1-d histogram (TH1F) of expression "e1"
3685 /// - "e1:e2" produces an unbinned 2-d scatter-plot (TGraph) of "e1"
3686 /// on the y-axis versus "e2" on the x-axis
3687 /// - "e1:e2:e3" produces an unbinned 3-d scatter-plot (TPolyMarker3D) of "e1"
3688 /// versus "e2" versus "e3" on the x-, y-, z-axis, respectively.
3689 /// - "e1:e2:e3:e4" produces an unbinned 3-d scatter-plot (TPolyMarker3D) of "e1"
3690 /// versus "e2" versus "e3" and "e4" mapped on the color number.
3691 /// (to create histograms in the 2, 3, and 4 dimensional case, see section "Saving
3692 /// the result of Draw to an histogram")
3693 ///
3694 /// Example:
3695 /// - varexp = x simplest case: draw a 1-Dim distribution of column named x
3696 /// - varexp = sqrt(x) : draw distribution of sqrt(x)
3697 /// - varexp = x*y/z
3698 /// - varexp = y:sqrt(x) 2-Dim distribution of y versus sqrt(x)
3699 /// - varexp = px:py:pz:2.5*E produces a 3-d scatter-plot of px vs py ps pz
3700 /// and the color number of each marker will be 2.5*E.
3701 /// If the color number is negative it is set to 0.
3702 /// If the color number is greater than the current number of colors
3703 /// it is set to the highest color number.The default number of
3704 /// colors is 50. see TStyle::SetPalette for setting a new color palette.
3705 ///
3706 /// Note that the variables e1, e2 or e3 may contain a selection.
3707 /// example, if e1= x*(y<0), the value histogrammed will be x if y<0
3708 /// and will be 0 otherwise.
3709 ///
3710 /// The expressions can use all the operations and build-in functions
3711 /// supported by TFormula (See TFormula::Analyze), including free
3712 /// standing function taking numerical arguments (TMath::Bessel).
3713 /// In addition, you can call member functions taking numerical
3714 /// arguments. For example:
3715 /// ~~~ {.cpp}
3716 /// TMath::BreitWigner(fPx,3,2)
3717 /// event.GetHistogram().GetXaxis().GetXmax()
3718 /// ~~~
3719 /// Note: You can only pass expression that depend on the TTree's data
3720 /// to static functions and you can only call non-static member function
3721 /// with 'fixed' parameters.
3722 ///
3723 /// selection is an expression with a combination of the columns.
3724 /// In a selection all the C++ operators are authorized.
3725 /// The value corresponding to the selection expression is used as a weight
3726 /// to fill the histogram.
3727 /// If the expression includes only boolean operations, the result
3728 /// is 0 or 1. If the result is 0, the histogram is not filled.
3729 /// In general, the expression may be of the form:
3730 /// ~~~ {.cpp}
3731 /// value*(boolean expression)
3732 /// ~~~
3733 /// if boolean expression is true, the histogram is filled with
3734 /// a `weight = value`.
3735 ///
3736 /// Examples:
3737 /// - selection1 = "x<y && sqrt(z)>3.2"
3738 /// - selection2 = "(x+y)*(sqrt(z)>3.2)"
3739 ///
3740 /// - selection1 returns a weight = 0 or 1
3741 /// - selection2 returns a weight = x+y if sqrt(z)>3.2
3742 /// returns a weight = 0 otherwise.
3743 ///
3744 /// option is the drawing option.
3745 /// - See TH1::Draw for the list of all drawing options.
3746 /// - If option COL is specified when varexp has three fields:
3747 /// ~~~ {.cpp}
3748 /// tree.Draw("e1:e2:e3","","col");
3749 /// ~~~
3750 /// a 2D scatter is produced with e1 vs e2, and e3 is mapped on the color
3751 /// table. The colors for e3 are evaluated once in linear scale before
3752 /// painting. Therefore changing the pad to log scale along Z as no effect
3753 /// on the colors.
3754 /// - If option contains the string "goff", no graphics is generated.
3755 ///
3756 /// `nentries` is the number of entries to process (default is all)
3757 /// first is the first entry to process (default is 0)
3758 ///
3759 /// This function returns the number of selected entries. It returns -1
3760 /// if an error occurs.
3761 ///
3762 /// ## Drawing expressions using arrays and array elements
3763 ///
3764 /// Let assumes, a leaf fMatrix, on the branch fEvent, which is a 3 by 3 array,
3765 /// or a TClonesArray.
3766 /// In a TTree::Draw expression you can now access fMatrix using the following
3767 /// syntaxes:
3768 ///
3769 /// | String passed | What is used for each entry of the tree
3770 /// |-----------------|--------------------------------------------------------|
3771 /// | `fMatrix` | the 9 elements of fMatrix |
3772 /// | `fMatrix[][]` | the 9 elements of fMatrix |
3773 /// | `fMatrix[2][2]` | only the elements fMatrix[2][2] |
3774 /// | `fMatrix[1]` | the 3 elements fMatrix[1][0], fMatrix[1][1] and fMatrix[1][2] |
3775 /// | `fMatrix[1][]` | the 3 elements fMatrix[1][0], fMatrix[1][1] and fMatrix[1][2] |
3776 /// | `fMatrix[][0]` | the 3 elements fMatrix[0][0], fMatrix[1][0] and fMatrix[2][0] |
3777 ///
3778 /// "fEvent.fMatrix...." same as "fMatrix..." (unless there is more than one leaf named fMatrix!).
3779 ///
3780 /// In summary, if a specific index is not specified for a dimension, TTree::Draw
3781 /// will loop through all the indices along this dimension. Leaving off the
3782 /// last (right most) dimension of specifying then with the two characters '[]'
3783 /// is equivalent. For variable size arrays (and TClonesArray) the range
3784 /// of the first dimension is recalculated for each entry of the tree.
3785 /// You can also specify the index as an expression of any other variables from the
3786 /// tree.
3787 ///
3788 /// TTree::Draw also now properly handling operations involving 2 or more arrays.
3789 ///
3790 /// Let assume a second matrix fResults[5][2], here are a sample of some
3791 /// of the possible combinations, the number of elements they produce and
3792 /// the loop used:
3793 ///
3794 /// | expression | element(s) | Loop |
3795 /// |----------------------------------|------------|--------------------------|
3796 /// | `fMatrix[2][1] - fResults[5][2]` | one | no loop |
3797 /// | `fMatrix[2][] - fResults[5][2]` | three | on 2nd dim fMatrix |
3798 /// | `fMatrix[2][] - fResults[5][]` | two | on both 2nd dimensions |
3799 /// | `fMatrix[][2] - fResults[][1]` | three | on both 1st dimensions |
3800 /// | `fMatrix[][2] - fResults[][]` | six | on both 1st and 2nd dimensions of fResults |
3801 /// | `fMatrix[][2] - fResults[3][]` | two | on 1st dim of fMatrix and 2nd of fResults (at the same time) |
3802 /// | `fMatrix[][] - fResults[][]` | six | on 1st dim then on 2nd dim |
3803 /// | `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.|
3804 ///
3805 ///
3806 /// In summary, TTree::Draw loops through all unspecified dimensions. To
3807 /// figure out the range of each loop, we match each unspecified dimension
3808 /// from left to right (ignoring ALL dimensions for which an index has been
3809 /// specified), in the equivalent loop matched dimensions use the same index
3810 /// and are restricted to the smallest range (of only the matched dimensions).
3811 /// When involving variable arrays, the range can of course be different
3812 /// for each entry of the tree.
3813 ///
3814 /// So the loop equivalent to "fMatrix[][2] - fResults[3][]" is:
3815 /// ~~~ {.cpp}
3816 /// for (Int_t i0; i < min(3,2); i++) {
3817 /// use the value of (fMatrix[i0][2] - fMatrix[3][i0])
3818 /// }
3819 /// ~~~
3820 /// So the loop equivalent to "fMatrix[][2] - fResults[][]" is:
3821 /// ~~~ {.cpp}
3822 /// for (Int_t i0; i < min(3,5); i++) {
3823 /// for (Int_t i1; i1 < 2; i1++) {
3824 /// use the value of (fMatrix[i0][2] - fMatrix[i0][i1])
3825 /// }
3826 /// }
3827 /// ~~~
3828 /// So the loop equivalent to "fMatrix[][] - fResults[][]" is:
3829 /// ~~~ {.cpp}
3830 /// for (Int_t i0; i < min(3,5); i++) {
3831 /// for (Int_t i1; i1 < min(3,2); i1++) {
3832 /// use the value of (fMatrix[i0][i1] - fMatrix[i0][i1])
3833 /// }
3834 /// }
3835 /// ~~~
3836 /// So the loop equivalent to "fMatrix[][fResults[][]]" is:
3837 /// ~~~ {.cpp}
3838 /// for (Int_t i0; i0 < 3; i0++) {
3839 /// for (Int_t j2; j2 < 5; j2++) {
3840 /// for (Int_t j3; j3 < 2; j3++) {
3841 /// i1 = fResults[j2][j3];
3842 /// use the value of fMatrix[i0][i1]
3843 /// }
3844 /// }
3845 /// ~~~
3846 /// ## Retrieving the result of Draw
3847 ///
3848 /// By default the temporary histogram created is called "htemp", but only in
3849 /// the one dimensional Draw("e1") it contains the TTree's data points. For
3850 /// a two dimensional Draw, the data is filled into a TGraph which is named
3851 /// "Graph". They can be retrieved by calling
3852 /// ~~~ {.cpp}
3853 /// TH1F *htemp = (TH1F*)gPad->GetPrimitive("htemp"); // 1D
3854 /// TGraph *graph = (TGraph*)gPad->GetPrimitive("Graph"); // 2D
3855 /// ~~~
3856 /// For a three and four dimensional Draw the TPolyMarker3D is unnamed, and
3857 /// cannot be retrieved.
3858 ///
3859 /// gPad always contains a TH1 derived object called "htemp" which allows to
3860 /// access the axes:
3861 /// ~~~ {.cpp}
3862 /// TGraph *graph = (TGraph*)gPad->GetPrimitive("Graph"); // 2D
3863 /// TH2F *htemp = (TH2F*)gPad->GetPrimitive("htemp"); // empty, but has axes
3864 /// TAxis *xaxis = htemp->GetXaxis();
3865 /// ~~~
3866 /// ## Saving the result of Draw to an histogram
3867 ///
3868 /// If varexp0 contains >>hnew (following the variable(s) name(s),
3869 /// the new histogram created is called hnew and it is kept in the current
3870 /// directory (and also the current pad). This works for all dimensions.
3871 ///
3872 /// Example:
3873 /// ~~~ {.cpp}
3874 /// tree.Draw("sqrt(x)>>hsqrt","y>0")
3875 /// ~~~
3876 /// will draw `sqrt(x)` and save the histogram as "hsqrt" in the current
3877 /// directory. To retrieve it do:
3878 /// ~~~ {.cpp}
3879 /// TH1F *hsqrt = (TH1F*)gDirectory->Get("hsqrt");
3880 /// ~~~
3881 /// The binning information is taken from the environment variables
3882 /// ~~~ {.cpp}
3883 /// Hist.Binning.?D.?
3884 /// ~~~
3885 /// In addition, the name of the histogram can be followed by up to 9
3886 /// numbers between '(' and ')', where the numbers describe the
3887 /// following:
3888 ///
3889 /// - 1 - bins in x-direction
3890 /// - 2 - lower limit in x-direction
3891 /// - 3 - upper limit in x-direction
3892 /// - 4-6 same for y-direction
3893 /// - 7-9 same for z-direction
3894 ///
3895 /// When a new binning is used the new value will become the default.
3896 /// Values can be skipped.
3897 ///
3898 /// Example:
3899 /// ~~~ {.cpp}
3900 /// tree.Draw("sqrt(x)>>hsqrt(500,10,20)")
3901 /// // plot sqrt(x) between 10 and 20 using 500 bins
3902 /// tree.Draw("sqrt(x):sin(y)>>hsqrt(100,10,60,50,.1,.5)")
3903 /// // plot sqrt(x) against sin(y)
3904 /// // 100 bins in x-direction; lower limit on x-axis is 10; upper limit is 60
3905 /// // 50 bins in y-direction; lower limit on y-axis is .1; upper limit is .5
3906 /// ~~~
3907 /// By default, the specified histogram is reset.
3908 /// To continue to append data to an existing histogram, use "+" in front
3909 /// of the histogram name.
3910 ///
3911 /// A '+' in front of the histogram name is ignored, when the name is followed by
3912 /// binning information as described in the previous paragraph.
3913 /// ~~~ {.cpp}
3914 /// tree.Draw("sqrt(x)>>+hsqrt","y>0")
3915 /// ~~~
3916 /// will not reset `hsqrt`, but will continue filling. This works for 1-D, 2-D
3917 /// and 3-D histograms.
3918 ///
3919 /// ## Accessing collection objects
3920 ///
3921 /// TTree::Draw default's handling of collections is to assume that any
3922 /// request on a collection pertain to it content. For example, if fTracks
3923 /// is a collection of Track objects, the following:
3924 /// ~~~ {.cpp}
3925 /// tree->Draw("event.fTracks.fPx");
3926 /// ~~~
3927 /// will plot the value of fPx for each Track objects inside the collection.
3928 /// Also
3929 /// ~~~ {.cpp}
3930 /// tree->Draw("event.fTracks.size()");
3931 /// ~~~
3932 /// would plot the result of the member function Track::size() for each
3933 /// Track object inside the collection.
3934 /// To access information about the collection itself, TTree::Draw support
3935 /// the '@' notation. If a variable which points to a collection is prefixed
3936 /// or postfixed with '@', the next part of the expression will pertain to
3937 /// the collection object. For example:
3938 /// ~~~ {.cpp}
3939 /// tree->Draw("event.@fTracks.size()");
3940 /// ~~~
3941 /// will plot the size of the collection referred to by `fTracks` (i.e the number
3942 /// of Track objects).
3943 ///
3944 /// ## Drawing 'objects'
3945 ///
3946 /// When a class has a member function named AsDouble or AsString, requesting
3947 /// to directly draw the object will imply a call to one of the 2 functions.
3948 /// If both AsDouble and AsString are present, AsDouble will be used.
3949 /// AsString can return either a char*, a std::string or a TString.s
3950 /// For example, the following
3951 /// ~~~ {.cpp}
3952 /// tree->Draw("event.myTTimeStamp");
3953 /// ~~~
3954 /// will draw the same histogram as
3955 /// ~~~ {.cpp}
3956 /// tree->Draw("event.myTTimeStamp.AsDouble()");
3957 /// ~~~
3958 /// In addition, when the object is a type TString or std::string, TTree::Draw
3959 /// will call respectively `TString::Data` and `std::string::c_str()`
3960 ///
3961 /// If the object is a TBits, the histogram will contain the index of the bit
3962 /// that are turned on.
3963 ///
3964 /// ## Retrieving information about the tree itself.
3965 ///
3966 /// You can refer to the tree (or chain) containing the data by using the
3967 /// string 'This'.
3968 /// You can then could any TTree methods. For example:
3969 /// ~~~ {.cpp}
3970 /// tree->Draw("This->GetReadEntry()");
3971 /// ~~~
3972 /// will display the local entry numbers be read.
3973 /// ~~~ {.cpp}
3974 /// tree->Draw("This->GetUserInfo()->At(0)->GetName()");
3975 /// ~~~
3976 /// will display the name of the first 'user info' object.
3977 ///
3978 /// ## Special functions and variables
3979 ///
3980 /// `Entry$`: A TTree::Draw formula can use the special variable `Entry$`
3981 /// to access the entry number being read. For example to draw every
3982 /// other entry use:
3983 /// ~~~ {.cpp}
3984 /// tree.Draw("myvar","Entry$%2==0");
3985 /// ~~~
3986 /// - `Entry$` : return the current entry number (`== TTree::GetReadEntry()`)
3987 /// - `LocalEntry$` : return the current entry number in the current tree of a
3988 /// chain (`== GetTree()->GetReadEntry()`)
3989 /// - `Entries$` : return the total number of entries (== TTree::GetEntries())
3990 /// - `LocalEntries$` : return the total number of entries in the current tree
3991 /// of a chain (== GetTree()->TTree::GetEntries())
3992 /// - `Length$` : return the total number of element of this formula for this
3993 /// entry (`==TTreeFormula::GetNdata()`)
3994 /// - `Iteration$` : return the current iteration over this formula for this
3995 /// entry (i.e. varies from 0 to `Length$`).
3996 /// - `Length$(formula )` : return the total number of element of the formula
3997 /// given as a parameter.
3998 /// - `Sum$(formula )` : return the sum of the value of the elements of the
3999 /// formula given as a parameter. For example the mean for all the elements in
4000 /// one entry can be calculated with: `Sum$(formula )/Length$(formula )`
4001 /// - `Min$(formula )` : return the minimun (within one TTree entry) of the value of the
4002 /// elements of the formula given as a parameter.
4003 /// - `Max$(formula )` : return the maximum (within one TTree entry) of the value of the
4004 /// elements of the formula given as a parameter.
4005 /// - `MinIf$(formula,condition)`
4006 /// - `MaxIf$(formula,condition)` : return the minimum (maximum) (within one TTree entry)
4007 /// of the value of the elements of the formula given as a parameter
4008 /// if they match the condition. If no element matches the condition,
4009 /// the result is zero. To avoid the resulting peak at zero, use the
4010 /// pattern:
4011 /// ~~~ {.cpp}
4012 /// tree->Draw("MinIf$(formula,condition)","condition");
4013 /// ~~~
4014 /// which will avoid calculation `MinIf$` for the entries that have no match
4015 /// for the condition.
4016 /// - `Alt$(primary,alternate)` : return the value of "primary" if it is available
4017 /// for the current iteration otherwise return the value of "alternate".
4018 /// For example, with arr1[3] and arr2[2]
4019 /// ~~~ {.cpp}
4020 /// tree->Draw("arr1+Alt$(arr2,0)");
4021 /// ~~~
4022 /// will draw arr1[0]+arr2[0] ; arr1[1]+arr2[1] and arr1[2]+0
4023 /// Or with a variable size array arr3
4024 /// ~~~ {.cpp}
4025 /// tree->Draw("Alt$(arr3[0],0)+Alt$(arr3[1],0)+Alt$(arr3[2],0)");
4026 /// ~~~
4027 /// will draw the sum arr3 for the index 0 to min(2,actual_size_of_arr3-1)
4028 /// As a comparison
4029 /// ~~~ {.cpp}
4030 /// tree->Draw("arr3[0]+arr3[1]+arr3[2]");
4031 /// ~~~
4032 /// will draw the sum arr3 for the index 0 to 2 only if the
4033 /// actual_size_of_arr3 is greater or equal to 3.
4034 /// Note that the array in 'primary' is flattened/linearized thus using
4035 /// `Alt$` with multi-dimensional arrays of different dimensions in unlikely
4036 /// to yield the expected results. To visualize a bit more what elements
4037 /// would be matched by TTree::Draw, TTree::Scan can be used:
4038 /// ~~~ {.cpp}
4039 /// tree->Scan("arr1:Alt$(arr2,0)");
4040 /// ~~~
4041 /// will print on one line the value of arr1 and (arr2,0) that will be
4042 /// matched by
4043 /// ~~~ {.cpp}
4044 /// tree->Draw("arr1-Alt$(arr2,0)");
4045 /// ~~~
4046 /// The ternary operator is not directly supported in TTree::Draw however, to plot the
4047 /// equivalent of `var2<20 ? -99 : var1`, you can use:
4048 /// ~~~ {.cpp}
4049 /// tree->Draw("(var2<20)*99+(var2>=20)*var1","");
4050 /// ~~~
4051 ///
4052 /// ## Drawing a user function accessing the TTree data directly
4053 ///
4054 /// If the formula contains a file name, TTree::MakeProxy will be used
4055 /// to load and execute this file. In particular it will draw the
4056 /// result of a function with the same name as the file. The function
4057 /// will be executed in a context where the name of the branches can
4058 /// be used as a C++ variable.
4059 ///
4060 /// For example draw px using the file hsimple.root (generated by the
4061 /// hsimple.C tutorial), we need a file named hsimple.cxx:
4062 /// ~~~ {.cpp}
4063 /// double hsimple() {
4064 /// return px;
4065 /// }
4066 /// ~~~
4067 /// MakeProxy can then be used indirectly via the TTree::Draw interface
4068 /// as follow:
4069 /// ~~~ {.cpp}
4070 /// new TFile("hsimple.root")
4071 /// ntuple->Draw("hsimple.cxx");
4072 /// ~~~
4073 /// A more complete example is available in the tutorials directory:
4074 /// `h1analysisProxy.cxx`, `h1analysProxy.h` and `h1analysisProxyCut.C`
4075 /// which reimplement the selector found in `h1analysis.C`
4076 ///
4077 /// The main features of this facility are:
4078 ///
4079 /// * on-demand loading of branches
4080 /// * ability to use the 'branchname' as if it was a data member
4081 /// * protection against array out-of-bound
4082 /// * ability to use the branch data as object (when the user code is available)
4083 ///
4084 /// See TTree::MakeProxy for more details.
4085 ///
4086 /// ## Making a Profile histogram
4087 ///
4088 /// In case of a 2-Dim expression, one can generate a TProfile histogram
4089 /// instead of a TH2F histogram by specifying option=prof or option=profs
4090 /// or option=profi or option=profg ; the trailing letter select the way
4091 /// the bin error are computed, See TProfile2D::SetErrorOption for
4092 /// details on the differences.
4093 /// The option=prof is automatically selected in case of y:x>>pf
4094 /// where pf is an existing TProfile histogram.
4095 ///
4096 /// ## Making a 2D Profile histogram
4097 ///
4098 /// In case of a 3-Dim expression, one can generate a TProfile2D histogram
4099 /// instead of a TH3F histogram by specifying option=prof or option=profs.
4100 /// or option=profi or option=profg ; the trailing letter select the way
4101 /// the bin error are computed, See TProfile2D::SetErrorOption for
4102 /// details on the differences.
4103 /// The option=prof is automatically selected in case of z:y:x>>pf
4104 /// where pf is an existing TProfile2D histogram.
4105 ///
4106 /// ## Making a 5D plot using GL
4107 ///
4108 /// If option GL5D is specified together with 5 variables, a 5D plot is drawn
4109 /// using OpenGL. See $ROOTSYS/tutorials/tree/staff.C as example.
4110 ///
4111 /// ## Making a parallel coordinates plot
4112 ///
4113 /// In case of a 2-Dim or more expression with the option=para, one can generate
4114 /// a parallel coordinates plot. 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 /// ## Making a candle sticks chart
4119 ///
4120 /// In case of a 2-Dim or more expression with the option=candle, one can generate
4121 /// a candle sticks chart. With that option, the number of dimensions is
4122 /// arbitrary. Giving more than 4 variables without the option=para or
4123 /// option=candle or option=goff will produce an error.
4124 ///
4125 /// ## Normalizing the output histogram to 1
4126 ///
4127 /// When option contains "norm" the output histogram is normalized to 1.
4128 ///
4129 /// ## Saving the result of Draw to a TEventList, a TEntryList or a TEntryListArray
4130 ///
4131 /// TTree::Draw can be used to fill a TEventList object (list of entry numbers)
4132 /// instead of histogramming one variable.
4133 /// If varexp0 has the form >>elist , a TEventList object named "elist"
4134 /// is created in the current directory. elist will contain the list
4135 /// of entry numbers satisfying the current selection.
4136 /// If option "entrylist" is used, a TEntryList object is created
4137 /// If the selection contains arrays, vectors or any container class and option
4138 /// "entrylistarray" is used, a TEntryListArray object is created
4139 /// containing also the subentries satisfying the selection, i.e. the indices of
4140 /// the branches which hold containers classes.
4141 /// Example:
4142 /// ~~~ {.cpp}
4143 /// tree.Draw(">>yplus","y>0")
4144 /// ~~~
4145 /// will create a TEventList object named "yplus" in the current directory.
4146 /// In an interactive session, one can type (after TTree::Draw)
4147 /// ~~~ {.cpp}
4148 /// yplus.Print("all")
4149 /// ~~~
4150 /// to print the list of entry numbers in the list.
4151 /// ~~~ {.cpp}
4152 /// tree.Draw(">>yplus", "y>0", "entrylist")
4153 /// ~~~
4154 /// will create a TEntryList object names "yplus" in the current directory
4155 /// ~~~ {.cpp}
4156 /// tree.Draw(">>yplus", "y>0", "entrylistarray")
4157 /// ~~~
4158 /// will create a TEntryListArray object names "yplus" in the current directory
4159 ///
4160 /// By default, the specified entry list is reset.
4161 /// To continue to append data to an existing list, use "+" in front
4162 /// of the list name;
4163 /// ~~~ {.cpp}
4164 /// tree.Draw(">>+yplus","y>0")
4165 /// ~~~
4166 /// will not reset yplus, but will enter the selected entries at the end
4167 /// of the existing list.
4168 ///
4169 /// ## Using a TEventList, TEntryList or TEntryListArray as Input
4170 ///
4171 /// Once a TEventList or a TEntryList object has been generated, it can be used as input
4172 /// for TTree::Draw. Use TTree::SetEventList or TTree::SetEntryList to set the
4173 /// current event list
4174 ///
4175 /// Example 1:
4176 /// ~~~ {.cpp}
4177 /// TEventList *elist = (TEventList*)gDirectory->Get("yplus");
4178 /// tree->SetEventList(elist);
4179 /// tree->Draw("py");
4180 /// ~~~
4181 /// Example 2:
4182 /// ~~~ {.cpp}
4183 /// TEntryList *elist = (TEntryList*)gDirectory->Get("yplus");
4184 /// tree->SetEntryList(elist);
4185 /// tree->Draw("py");
4186 /// ~~~
4187 /// If a TEventList object is used as input, a new TEntryList object is created
4188 /// inside the SetEventList function. In case of a TChain, all tree headers are loaded
4189 /// for this transformation. This new object is owned by the chain and is deleted
4190 /// with it, unless the user extracts it by calling GetEntryList() function.
4191 /// See also comments to SetEventList() function of TTree and TChain.
4192 ///
4193 /// If arrays are used in the selection criteria and TEntryListArray is not used,
4194 /// all the entries that have at least one element of the array that satisfy the selection
4195 /// are entered in the list.
4196 ///
4197 /// Example:
4198 /// ~~~ {.cpp}
4199 /// tree.Draw(">>pyplus","fTracks.fPy>0");
4200 /// tree->SetEventList(pyplus);
4201 /// tree->Draw("fTracks.fPy");
4202 /// ~~~
4203 /// will draw the fPy of ALL tracks in event with at least one track with
4204 /// a positive fPy.
4205 ///
4206 /// To select only the elements that did match the original selection
4207 /// use TEventList::SetReapplyCut or TEntryList::SetReapplyCut.
4208 ///
4209 /// Example:
4210 /// ~~~ {.cpp}
4211 /// tree.Draw(">>pyplus","fTracks.fPy>0");
4212 /// pyplus->SetReapplyCut(kTRUE);
4213 /// tree->SetEventList(pyplus);
4214 /// tree->Draw("fTracks.fPy");
4215 /// ~~~
4216 /// will draw the fPy of only the tracks that have a positive fPy.
4217 ///
4218 /// To draw only the elements that match a selection in case of arrays,
4219 /// you can also use TEntryListArray (faster in case of a more general selection).
4220 ///
4221 /// Example:
4222 /// ~~~ {.cpp}
4223 /// tree.Draw(">>pyplus","fTracks.fPy>0", "entrylistarray");
4224 /// tree->SetEntryList(pyplus);
4225 /// tree->Draw("fTracks.fPy");
4226 /// ~~~
4227 /// will draw the fPy of only the tracks that have a positive fPy,
4228 /// but without redoing the selection.
4229 ///
4230 /// Note: Use tree->SetEventList(0) if you do not want use the list as input.
4231 ///
4232 /// ## How to obtain more info from TTree::Draw
4233 ///
4234 /// Once TTree::Draw has been called, it is possible to access useful
4235 /// information still stored in the TTree object via the following functions:
4236 ///
4237 /// - GetSelectedRows() // return the number of values accepted by the selection expression. In case where no selection was specified, returns the number of values processed.
4238 /// - GetV1() // returns a pointer to the double array of V1
4239 /// - GetV2() // returns a pointer to the double array of V2
4240 /// - GetV3() // returns a pointer to the double array of V3
4241 /// - GetV4() // returns a pointer to the double array of V4
4242 /// - GetW() // returns a pointer to the double array of Weights where weight equal the result of the selection expression.
4243 ///
4244 /// where V1,V2,V3 correspond to the expressions in
4245 /// ~~~ {.cpp}
4246 /// TTree::Draw("V1:V2:V3:V4",selection);
4247 /// ~~~
4248 /// If the expression has more than 4 component use GetVal(index)
4249 ///
4250 /// Example:
4251 /// ~~~ {.cpp}
4252 /// Root > ntuple->Draw("py:px","pz>4");
4253 /// Root > TGraph *gr = new TGraph(ntuple->GetSelectedRows(),
4254 /// ntuple->GetV2(), ntuple->GetV1());
4255 /// Root > gr->Draw("ap"); //draw graph in current pad
4256 /// ~~~
4257 ///
4258 /// A more complete complete tutorial (treegetval.C) shows how to use the
4259 /// GetVal() method.
4260 ///
4261 /// creates a TGraph object with a number of points corresponding to the
4262 /// number of entries selected by the expression "pz>4", the x points of the graph
4263 /// being the px values of the Tree and the y points the py values.
4264 ///
4265 /// Important note: By default TTree::Draw creates the arrays obtained
4266 /// with GetW, GetV1, GetV2, GetV3, GetV4, GetVal with a length corresponding
4267 /// to the parameter fEstimate. The content will be the last `GetSelectedRows() % GetEstimate()`
4268 /// values calculated.
4269 /// By default fEstimate=1000000 and can be modified
4270 /// via TTree::SetEstimate. To keep in memory all the results (in case
4271 /// where there is only one result per entry), use
4272 /// ~~~ {.cpp}
4273 /// tree->SetEstimate(tree->GetEntries()+1); // same as tree->SetEstimate(-1);
4274 /// ~~~
4275 /// You must call SetEstimate if the expected number of selected rows
4276 /// you need to look at is greater than 1000000.
4277 ///
4278 /// You can use the option "goff" to turn off the graphics output
4279 /// of TTree::Draw in the above example.
4280 ///
4281 /// ## Automatic interface to TTree::Draw via the TTreeViewer
4282 ///
4283 /// A complete graphical interface to this function is implemented
4284 /// in the class TTreeViewer.
4285 /// To start the TTreeViewer, three possibilities:
4286 /// - select TTree context menu item "StartViewer"
4287 /// - type the command "TTreeViewer TV(treeName)"
4288 /// - execute statement "tree->StartViewer();"
4289 
4290 Long64_t TTree::Draw(const char* varexp, const char* selection, Option_t* option, Long64_t nentries, Long64_t firstentry)
4292  GetPlayer();
4293  if (fPlayer)
4294  return fPlayer->DrawSelect(varexp,selection,option,nentries,firstentry);
4295  return -1;
4296 }
4297 
4298 ////////////////////////////////////////////////////////////////////////////////
4299 /// Remove some baskets from memory.
4300 
4301 void TTree::DropBaskets()
4303  TBranch* branch = 0;
4305  for (Int_t i = 0; i < nb; ++i) {
4306  branch = (TBranch*) fBranches.UncheckedAt(i);
4307  branch->DropBaskets("all");
4308  }
4309 }
4310 
4311 ////////////////////////////////////////////////////////////////////////////////
4312 /// Drop branch buffers to accommodate nbytes below MaxVirtualsize.
4313 
4316  // Be careful not to remove current read/write buffers.
4317  Int_t ndrop = 0;
4318  Int_t nleaves = fLeaves.GetEntriesFast();
4319  for (Int_t i = 0; i < nleaves; ++i) {
4320  TLeaf* leaf = (TLeaf*) fLeaves.UncheckedAt(i);
4321  TBranch* branch = (TBranch*) leaf->GetBranch();
4322  Int_t nbaskets = branch->GetListOfBaskets()->GetEntries();
4323  for (Int_t j = 0; j < nbaskets - 1; ++j) {
4324  if ((j == branch->GetReadBasket()) || (j == branch->GetWriteBasket())) {
4325  continue;
4326  }
4327  TBasket* basket = (TBasket*)branch->GetListOfBaskets()->UncheckedAt(j);
4328  if (basket) {
4329  ndrop += basket->DropBuffers();
4331  return;
4332  }
4333  }
4334  }
4335  }
4336 }
4337 
4338 ////////////////////////////////////////////////////////////////////////////////
4339 /// Fill all branches.
4340 ///
4341 /// This function loops on all the branches of this tree. For
4342 /// each branch, it copies to the branch buffer (basket) the current
4343 /// values of the leaves data types. If a leaf is a simple data type,
4344 /// a simple conversion to a machine independent format has to be done.
4345 ///
4346 /// This machine independent version of the data is copied into a
4347 /// basket (each branch has its own basket). When a basket is full
4348 /// (32k worth of data by default), it is then optionally compressed
4349 /// and written to disk (this operation is also called committing or
4350 /// 'flushing' the basket). The committed baskets are then
4351 /// immediately removed from memory.
4352 ///
4353 /// The function returns the number of bytes committed to the
4354 /// individual branches.
4355 ///
4356 /// If a write error occurs, the number of bytes returned is -1.
4357 ///
4358 /// If no data are written, because, e.g., the branch is disabled,
4359 /// the number of bytes returned is 0.
4360 ///
4361 /// __The baskets are flushed and the Tree header saved at regular intervals__
4362 ///
4363 /// At regular intervals, when the amount of data written so far is
4364 /// greater than fAutoFlush (see SetAutoFlush) all the baskets are flushed to disk.
4365 /// This makes future reading faster as it guarantees that baskets belonging to nearby
4366 /// entries will be on the same disk region.
4367 /// When the first call to flush the baskets happen, we also take this opportunity
4368 /// to optimize the baskets buffers.
4369 /// We also check if the amount of data written is greater than fAutoSave (see SetAutoSave).
4370 /// In this case we also write the Tree header. This makes the Tree recoverable up to this point
4371 /// in case the program writing the Tree crashes.
4372 /// The decisions to FlushBaskets and Auto Save can be made based either on the number
4373 /// of bytes written (fAutoFlush and fAutoSave negative) or on the number of entries
4374 /// written (fAutoFlush and fAutoSave positive).
4375 /// Note that the user can decide to call FlushBaskets and AutoSave in her event loop
4376 /// base on the number of events written instead of the number of bytes written.
4377 ///
4378 /// Note that calling FlushBaskets too often increases the IO time.
4379 ///
4380 /// Note that calling AutoSave too often increases the IO time and also the file size.
4381 
4384  Int_t nbytes = 0;
4385  Int_t nerror = 0;
4387  if (nb == 1) {
4388  // Case of one single super branch. Automatically update
4389  // all the branch addresses if a new object was created.
4390  TBranch* branch = (TBranch*) fBranches.UncheckedAt(0);
4391  branch->UpdateAddress();
4392  }
4393  if (fBranchRef) {
4394  fBranchRef->Clear();
4395  }
4396 
4398  #ifdef R__USE_IMT
4399  if (fIMTEnabled) {
4400  fIMTFlush = true;
4401  fIMTZipBytes.store(0);
4402  fIMTTotBytes.store(0);
4403  }
4404  #endif
4405 
4406  for (Int_t i = 0; i < nb; ++i) {
4407  // Loop over all branches, filling and accumulating bytes written and error counts.
4408  TBranch* branch = (TBranch*) fBranches.UncheckedAt(i);
4409  if (branch->TestBit(kDoNotProcess)) {
4410  continue;
4411  }
4412  Int_t nwrite = branch->FillImpl(fIMTEnabled ? &imtHelper : nullptr);
4413  if (nwrite < 0) {
4414  if (nerror < 2) {
4415  Error("Fill", "Failed filling branch:%s.%s, nbytes=%d, entry=%lld\n"
4416  " This error is symptomatic of a Tree created as a memory-resident Tree\n"
4417  " Instead of doing:\n"
4418  " TTree *T = new TTree(...)\n"
4419  " TFile *f = new TFile(...)\n"
4420  " you should do:\n"
4421  " TFile *f = new TFile(...)\n"
4422  " TTree *T = new TTree(...)",
4423  GetName(), branch->GetName(), nwrite,fEntries+1);
4424  } else {
4425  Error("Fill", "Failed filling branch:%s.%s, nbytes=%d, entry=%lld", GetName(), branch->GetName(), nwrite,fEntries+1);
4426  }
4427  ++nerror;
4428  } else {
4429  nbytes += nwrite;
4430  }
4431  }
4432  #ifdef R__USE_IMT
4433  if (fIMTFlush) {
4434  imtHelper.Wait();
4435  fIMTFlush = false;
4436  const_cast<TTree*>(this)->AddTotBytes(fIMTTotBytes);
4437  const_cast<TTree*>(this)->AddZipBytes(fIMTZipBytes);
4438  nbytes += imtHelper.GetNbytes();
4439  nerror += imtHelper.GetNerrors();
4440  }
4441  #endif
4442 
4443  if (fBranchRef) {
4444  fBranchRef->Fill();
4445  }
4446  ++fEntries;
4447  if (fEntries > fMaxEntries) {
4448  KeepCircular();
4449  }
4450  if (gDebug > 0) Info("TTree::Fill", " - A: %d %lld %lld %lld %lld %lld %lld \n",
4452 
4453  if (fAutoFlush != 0 || fAutoSave != 0) {
4454  // Is it time to flush or autosave baskets?
4455  if (fFlushedBytes == 0) {
4456  // Decision can be based initially either on the number of bytes
4457  // or the number of entries written.
4458  Long64_t zipBytes = GetZipBytes();
4459  if ((fAutoFlush<0 && zipBytes > -fAutoFlush) ||
4460  (fAutoSave <0 && zipBytes > -fAutoSave ) ||
4461  (fAutoFlush>0 && fEntries%TMath::Max((Long64_t)1,fAutoFlush) == 0) ||
4462  (fAutoSave >0 && fEntries%TMath::Max((Long64_t)1,fAutoSave) == 0) ) {
4463 
4464  //First call FlushBasket to make sure that fTotBytes is up to date.
4465  FlushBaskets();
4466  OptimizeBaskets(GetTotBytes(),1,"");
4467  if (gDebug > 0) Info("TTree::Fill","OptimizeBaskets called at entry %lld, fZipBytes=%lld, fFlushedBytes=%lld\n",fEntries,GetZipBytes(),fFlushedBytes);
4469  fAutoFlush = fEntries; // Use test on entries rather than bytes
4470 
4471  // subsequently in run
4472  if (fAutoSave < 0) {
4473  // Set fAutoSave to the largest integer multiple of
4474  // fAutoFlush events such that fAutoSave*fFlushedBytes
4475  // < (minus the input value of fAutoSave)
4476  Long64_t totBytes = GetTotBytes();
4477  if (zipBytes != 0) {
4479  } else if (totBytes != 0) {
4481  } else {
4482  TBufferFile b(TBuffer::kWrite, 10000);
4483  TTree::Class()->WriteBuffer(b, (TTree*) this);
4484  Long64_t total = b.Length();
4486  }
4487  } else if(fAutoSave > 0) {
4489  }
4490  if (fAutoSave!=0 && fEntries >= fAutoSave) AutoSave(); // FlushBaskets not called in AutoSave
4491  if (gDebug > 0) Info("TTree::Fill","First AutoFlush. fAutoFlush = %lld, fAutoSave = %lld\n", fAutoFlush, fAutoSave);
4492  }
4493  } else if (fNClusterRange && fAutoFlush && ( (fEntries-fClusterRangeEnd[fNClusterRange-1]) % fAutoFlush == 0) ) {
4494  if (fAutoSave != 0 && fEntries%fAutoSave == 0) {
4495  //We are at an AutoSave point. AutoSave flushes baskets and saves the Tree header
4496  AutoSave("flushbaskets");
4497  if (gDebug > 0) Info("TTree::Fill","AutoSave called at entry %lld, fZipBytes=%lld, fSavedBytes=%lld\n",fEntries,GetZipBytes(),fSavedBytes);
4498  } else {
4499  //We only FlushBaskets
4500  FlushBaskets();
4501  if (gDebug > 0) Info("TTree::Fill","FlushBasket called at entry %lld, fZipBytes=%lld, fFlushedBytes=%lld\n",fEntries,GetZipBytes(),fFlushedBytes);
4502  }
4504  } else if (fNClusterRange == 0 && fEntries > 1 && fAutoFlush && fEntries%fAutoFlush == 0) {
4505  if (fAutoSave != 0 && fEntries%fAutoSave == 0) {
4506  //We are at an AutoSave point. AutoSave flushes baskets and saves the Tree header
4507  AutoSave("flushbaskets");
4508  if (gDebug > 0) Info("TTree::Fill","AutoSave called at entry %lld, fZipBytes=%lld, fSavedBytes=%lld\n",fEntries,GetZipBytes(),fSavedBytes);
4509  } else {
4510  //We only FlushBaskets
4511  FlushBaskets();
4512  if (gDebug > 0) Info("TTree::Fill","FlushBasket called at entry %lld, fZipBytes=%lld, fFlushedBytes=%lld\n",fEntries,GetZipBytes(),fFlushedBytes);
4513  }
4515  }
4516  }
4517  // Check that output file is still below the maximum size.
4518  // If above, close the current file and continue on a new file.
4519  // Currently, the automatic change of file is restricted
4520  // to the case where the tree is in the top level directory.
4521  if (!fDirectory) {
4522  return nbytes;
4523  }
4524  TFile* file = fDirectory->GetFile();
4525  if (file && (file->GetEND() > fgMaxTreeSize)) {
4526  if (fDirectory == (TDirectory*) file) {
4527  ChangeFile(file);
4528  }
4529  }
4530  if (nerror) {
4531  return -1;
4532  }
4533  return nbytes;
4534 }
4535 
4536 ////////////////////////////////////////////////////////////////////////////////
4537 /// Search in the array for a branch matching the branch name,
4538 /// with the branch possibly expressed as a 'full' path name (with dots).
4539 
4540 static TBranch *R__FindBranchHelper(TObjArray *list, const char *branchname) {
4541  if (list==0 || branchname == 0 || branchname[0] == '\0') return 0;
4542 
4543  Int_t nbranches = list->GetEntries();
4544 
4545  UInt_t brlen = strlen(branchname);
4546 
4547  for(Int_t index = 0; index < nbranches; ++index) {
4548  TBranch *where = (TBranch*)list->UncheckedAt(index);
4549 
4550  const char *name = where->GetName();
4551  UInt_t len = strlen(name);
4552  if (len && name[len-1]==']') {
4553  const char *dim = strchr(name,'[');
4554  if (dim) {
4555  len = dim - name;
4556  }
4557  }
4558  if (brlen == len && strncmp(branchname,name,len)==0) {
4559  return where;
4560  }
4561  TBranch *next = 0;
4562  if ((brlen >= len) && (branchname[len] == '.')
4563  && strncmp(name, branchname, len) == 0) {
4564  // The prefix subbranch name match the branch name.
4565 
4566  next = where->FindBranch(branchname);
4567  if (!next) {
4568  next = where->FindBranch(branchname+len+1);
4569  }
4570  if (next) return next;
4571  }
4572  const char *dot = strchr((char*)branchname,'.');
4573  if (dot) {
4574  if (len==(size_t)(dot-branchname) &&
4575  strncmp(branchname,name,dot-branchname)==0 ) {
4576  return R__FindBranchHelper(where->GetListOfBranches(),dot+1);
4577  }
4578  }
4579  }
4580  return 0;
4581 }
4582 
4583 ////////////////////////////////////////////////////////////////////////////////
4584 /// Return the branch that correspond to the path 'branchname', which can
4585 /// include the name of the tree or the omitted name of the parent branches.
4586 /// In case of ambiguity, returns the first match.
4587 
4588 TBranch* TTree::FindBranch(const char* branchname)
4590  // We already have been visited while recursively looking
4591  // through the friends tree, let return
4593  return 0;
4594  }
4595 
4596  TBranch* branch = 0;
4597  // If the first part of the name match the TTree name, look for the right part in the
4598  // list of branches.
4599  // This will allow the branchname to be preceded by
4600  // the name of this tree.
4601  if (strncmp(fName.Data(),branchname,fName.Length())==0 && branchname[fName.Length()]=='.') {
4602  branch = R__FindBranchHelper( GetListOfBranches(), branchname + fName.Length() + 1);
4603  if (branch) return branch;
4604  }
4605  // If we did not find it, let's try to find the full name in the list of branches.
4606  branch = R__FindBranchHelper(GetListOfBranches(), branchname);
4607  if (branch) return branch;
4608 
4609  // If we still did not find, let's try to find it within each branch assuming it does not the branch name.
4610  TIter next(GetListOfBranches());
4611  while ((branch = (TBranch*) next())) {
4612  TBranch* nestedbranch = branch->FindBranch(branchname);
4613  if (nestedbranch) {
4614  return nestedbranch;
4615  }
4616  }
4617 
4618  // Search in list of friends.
4619  if (!fFriends) {
4620  return 0;
4621  }
4622  TFriendLock lock(this, kFindBranch);
4623  TIter nextf(fFriends);
4624  TFriendElement* fe = 0;
4625  while ((fe = (TFriendElement*) nextf())) {
4626  TTree* t = fe->GetTree();
4627  if (!t) {
4628  continue;
4629  }
4630  // If the alias is present replace it with the real name.
4631  const char *subbranch = strstr(branchname, fe->GetName());
4632  if (subbranch != branchname) {
4633  subbranch = 0;
4634  }
4635  if (subbranch) {
4636  subbranch += strlen(fe->GetName());
4637  if (*subbranch != '.') {
4638  subbranch = 0;
4639  } else {
4640  ++subbranch;
4641  }
4642  }
4643  std::ostringstream name;
4644  if (subbranch) {
4645  name << t->GetName() << "." << subbranch;
4646  } else {
4647  name << branchname;
4648  }
4649  branch = t->FindBranch(name.str().c_str());
4650  if (branch) {
4651  return branch;
4652  }
4653  }
4654  return 0;
4655 }
4656 
4657 ////////////////////////////////////////////////////////////////////////////////
4658 /// Find leaf..
4659 
4660 TLeaf* TTree::FindLeaf(const char* searchname)
4662  // We already have been visited while recursively looking
4663  // through the friends tree, let's return.
4664  if (kFindLeaf & fFriendLockStatus) {
4665  return 0;
4666  }
4667 
4668  // This will allow the branchname to be preceded by
4669  // the name of this tree.
4670  char* subsearchname = (char*) strstr(searchname, GetName());
4671  if (subsearchname != searchname) {
4672  subsearchname = 0;
4673  }
4674  if (subsearchname) {
4675  subsearchname += strlen(GetName());
4676  if (*subsearchname != '.') {
4677  subsearchname = 0;
4678  } else {
4679  ++subsearchname;
4680  if (subsearchname[0]==0) {
4681  subsearchname = 0;
4682  }
4683  }
4684  }
4685 
4686  TString leafname;
4687  TString leaftitle;
4688  TString longname;
4689  TString longtitle;
4690 
4691  // For leaves we allow for one level up to be prefixed to the name.
4692  TIter next(GetListOfLeaves());
4693  TLeaf* leaf = 0;
4694  while ((leaf = (TLeaf*) next())) {
4695  leafname = leaf->GetName();
4696  Ssiz_t dim = leafname.First('[');
4697  if (dim >= 0) leafname.Remove(dim);
4698 
4699  if (leafname == searchname) {
4700  return leaf;
4701  }
4702  if (subsearchname && leafname == subsearchname) {
4703  return leaf;
4704  }
4705  // The TLeafElement contains the branch name
4706  // in its name, let's use the title.
4707  leaftitle = leaf->GetTitle();
4708  dim = leaftitle.First('[');
4709  if (dim >= 0) leaftitle.Remove(dim);
4710 
4711  if (leaftitle == searchname) {
4712  return leaf;
4713  }
4714  if (subsearchname && leaftitle == subsearchname) {
4715  return leaf;
4716  }
4717  TBranch* branch = leaf->GetBranch();
4718  if (branch) {
4719  longname.Form("%s.%s",branch->GetName(),leafname.Data());
4720  dim = longname.First('[');
4721  if (dim>=0) longname.Remove(dim);
4722  if (longname == searchname) {
4723  return leaf;
4724  }
4725  if (subsearchname && longname == subsearchname) {
4726  return leaf;
4727  }
4728  longtitle.Form("%s.%s",branch->GetName(),leaftitle.Data());
4729  dim = longtitle.First('[');
4730  if (dim>=0) longtitle.Remove(dim);
4731  if (longtitle == searchname) {
4732  return leaf;
4733  }
4734  if (subsearchname && longtitle == subsearchname) {
4735  return leaf;
4736  }
4737  // The following is for the case where the branch is only
4738  // a sub-branch. Since we do not see it through
4739  // TTree::GetListOfBranches, we need to see it indirectly.
4740  // This is the less sturdy part of this search ... it may
4741  // need refining ...
4742  if (strstr(searchname, ".") && !strcmp(searchname, branch->GetName())) {
4743  return leaf;
4744  }
4745  if (subsearchname && strstr(subsearchname, ".") && !strcmp(subsearchname, branch->GetName())) {
4746  return leaf;
4747  }
4748  }
4749  }
4750  // Search in list of friends.
4751  if (!fFriends) {
4752  return 0;
4753  }
4754  TFriendLock lock(this, kFindLeaf);
4755  TIter nextf(fFriends);
4756  TFriendElement* fe = 0;
4757  while ((fe = (TFriendElement*) nextf())) {
4758  TTree* t = fe->GetTree();
4759  if (!t) {
4760  continue;
4761  }
4762  // If the alias is present replace it with the real name.
4763  subsearchname = (char*) strstr(searchname, fe->GetName());
4764  if (subsearchname != searchname) {
4765  subsearchname = 0;
4766  }
4767  if (subsearchname) {
4768  subsearchname += strlen(fe->GetName());
4769  if (*subsearchname != '.') {
4770  subsearchname = 0;
4771  } else {
4772  ++subsearchname;
4773  }
4774  }
4775  if (subsearchname) {
4776  leafname.Form("%s.%s",t->GetName(),subsearchname);
4777  } else {
4778  leafname = searchname;
4779  }
4780  leaf = t->FindLeaf(leafname);
4781  if (leaf) {
4782  return leaf;
4783  }
4784  }
4785  return 0;
4786 }
4787 
4788 ////////////////////////////////////////////////////////////////////////////////
4789 /// Fit a projected item(s) from a tree.
4790 ///
4791 /// funcname is a TF1 function.
4792 ///
4793 /// See TTree::Draw() for explanations of the other parameters.
4794 ///
4795 /// By default the temporary histogram created is called htemp.
4796 /// If varexp contains >>hnew , the new histogram created is called hnew
4797 /// and it is kept in the current directory.
4798 ///
4799 /// The function returns the number of selected entries.
4800 ///
4801 /// Example:
4802 /// ~~~ {.cpp}
4803 /// tree.Fit(pol4,"sqrt(x)>>hsqrt","y>0")
4804 /// ~~~
4805 /// will fit sqrt(x) and save the histogram as "hsqrt" in the current
4806 /// directory.
4807 ///
4808 /// See also TTree::UnbinnedFit
4809 ///
4810 /// ## Return status
4811 ///
4812 /// The function returns the status of the histogram fit (see TH1::Fit)
4813 /// If no entries were selected, the function returns -1;
4814 /// (i.e. fitResult is null if the fit is OK)
4815 
4816 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)
4818  GetPlayer();
4819  if (fPlayer) {
4820  return fPlayer->Fit(funcname, varexp, selection, option, goption, nentries, firstentry);
4821  }
4822  return -1;
4823 }
4824 
4825 namespace {
4826 struct BoolRAIIToggle {
4827  Bool_t &m_val;
4828 
4829  BoolRAIIToggle(Bool_t &val) : m_val(val) { m_val = true; }
4830  ~BoolRAIIToggle() { m_val = false; }
4831 };
4832 }
4833 
4834 ////////////////////////////////////////////////////////////////////////////////
4835 /// Write to disk all the basket that have not yet been individually written.
4836 ///
4837 /// If ROOT has IMT-mode enabled, this will launch multiple TBB tasks in parallel
4838 /// via TThreadExecutor to do this operation; one per basket compression. If the
4839 /// caller utilizes TBB also, care must be taken to prevent deadlocks.
4840 ///
4841 /// For example, let's say the caller holds mutex A and calls FlushBaskets; while
4842 /// TBB is waiting for the ROOT compression tasks to complete, it may decide to
4843 /// run another one of the user's tasks in this thread. If the second user task
4844 /// tries to acquire A, then a deadlock will occur. The example call sequence
4845 /// looks like this:
4846 ///
4847 /// - User acquires mutex A
4848 /// - User calls FlushBaskets.
4849 /// - ROOT launches N tasks and calls wait.
4850 /// - TBB schedules another user task, T2.
4851 /// - T2 tries to acquire mutex A.
4852 ///
4853 /// At this point, the thread will deadlock: the code may function with IMT-mode
4854 /// disabled if the user assumed the legacy code never would run their own TBB
4855 /// tasks.
4856 ///
4857 /// SO: users of TBB who want to enable IMT-mode should carefully review their
4858 /// locking patterns and make sure they hold no coarse-grained application
4859 /// locks when they invoke ROOT.
4860 ///
4861 /// Return the number of bytes written or -1 in case of write error.
4862 
4863 Int_t TTree::FlushBaskets() const
4865  if (!fDirectory) return 0;
4866  Int_t nbytes = 0;
4867  Int_t nerror = 0;
4868  TObjArray *lb = const_cast<TTree*>(this)->GetListOfBranches();
4869  Int_t nb = lb->GetEntriesFast();
4870 
4871 #ifdef R__USE_IMT
4872  if (fIMTEnabled) {
4873  if (fSortedBranches.empty()) { const_cast<TTree*>(this)->InitializeBranchLists(false); }
4874 
4875  BoolRAIIToggle sentry(fIMTFlush);
4876  fIMTZipBytes.store(0);
4877  fIMTTotBytes.store(0);
4878  std::atomic<Int_t> nerrpar(0);
4879  std::atomic<Int_t> nbpar(0);
4880  std::atomic<Int_t> pos(0);
4881 
4882  auto mapFunction = [&]() {
4883  // The branch to process is obtained when the task starts to run.
4884  // This way, since branches are sorted, we make sure that branches
4885  // leading to big tasks are processed first. If we assigned the
4886  // branch at task creation time, the scheduler would not necessarily
4887  // respect our sorting.
4888  Int_t j = pos.fetch_add(1);
4889 
4890  auto branch = fSortedBranches[j].second;
4891  if (R__unlikely(!branch)) { return; }
4892 
4893  if (R__unlikely(gDebug > 0)) {
4894  std::stringstream ss;
4895  ss << std::this_thread::get_id();
4896  Info("FlushBaskets", "[IMT] Thread %s", ss.str().c_str());
4897  Info("FlushBaskets", "[IMT] Running task for branch #%d: %s", j, branch->GetName());
4898  }
4899 
4900  Int_t nbtask = branch->FlushBaskets();
4901 
4902  if (nbtask < 0) { nerrpar++; }
4903  else { nbpar += nbtask; }
4904  };
4905 
4906  ROOT::TThreadExecutor pool;
4907  pool.Foreach(mapFunction, nb);
4908 
4909  fIMTFlush = false;
4910  const_cast<TTree*>(this)->AddTotBytes(fIMTTotBytes);
4911  const_cast<TTree*>(this)->AddZipBytes(fIMTZipBytes);
4912 
4913  return nerrpar ? -1 : nbpar.load();
4914  }
4915 #endif
4916  for (Int_t j = 0; j < nb; j++) {
4917  TBranch* branch = (TBranch*) lb->UncheckedAt(j);
4918  if (branch) {
4919  Int_t nwrite = branch->FlushBaskets();
4920  if (nwrite<0) {
4921  ++nerror;
4922  } else {
4923  nbytes += nwrite;
4924  }
4925  }
4926  }
4927  if (nerror) {
4928  return -1;
4929  } else {
4930  return nbytes;
4931  }
4932 }
4933 
4934 ////////////////////////////////////////////////////////////////////////////////
4935 /// Returns the expanded value of the alias. Search in the friends if any.
4936 
4937 const char* TTree::GetAlias(const char* aliasName) const
4939  // We already have been visited while recursively looking
4940  // through the friends tree, let's return.
4941  if (kGetAlias & fFriendLockStatus) {
4942  return 0;
4943  }
4944  if (fAliases) {
4945  TObject* alias = fAliases->FindObject(aliasName);
4946  if (alias) {
4947  return alias->GetTitle();
4948  }
4949  }
4950  if (!fFriends) {
4951  return 0;
4952  }
4953  TFriendLock lock(const_cast<TTree*>(this), kGetAlias);
4954  TIter nextf(fFriends);
4955  TFriendElement* fe = 0;
4956  while ((fe = (TFriendElement*) nextf())) {
4957  TTree* t = fe->GetTree();
4958  if (t) {
4959  const char* alias = t->GetAlias(aliasName);
4960  if (alias) {
4961  return alias;
4962  }
4963  const char* subAliasName = strstr(aliasName, fe->GetName());
4964  if (subAliasName && (subAliasName[strlen(fe->GetName())] == '.')) {
4965  alias = t->GetAlias(aliasName + strlen(fe->GetName()) + 1);
4966  if (alias) {
4967  return alias;
4968  }
4969  }
4970  }
4971  }
4972  return 0;
4973 }
4974 
4975 ////////////////////////////////////////////////////////////////////////////////
4976 /// Return pointer to the branch with the given name in this tree or its friends.
4977 
4978 TBranch* TTree::GetBranch(const char* name)
4980  if (name == 0) return 0;
4981 
4982  // We already have been visited while recursively
4983  // looking through the friends tree, let's return.
4984  if (kGetBranch & fFriendLockStatus) {
4985  return 0;
4986  }
4987 
4988  // Search using branches.
4990  for (Int_t i = 0; i < nb; i++) {
4991  TBranch* branch = (TBranch*) fBranches.UncheckedAt(i);
4992  if (!strcmp(branch->GetName(), name)) {
4993  return branch;
4994  }
4995  TObjArray* lb = branch->GetListOfBranches();
4996  Int_t nb1 = lb->GetEntriesFast();
4997  for (Int_t j = 0; j < nb1; j++) {
4998  TBranch* b1 = (TBranch*) lb->UncheckedAt(j);
4999  if (!strcmp(b1->GetName(), name)) {
5000  return b1;
5001  }
5002  TObjArray* lb1 = b1->GetListOfBranches();
5003  Int_t nb2 = lb1->GetEntriesFast();
5004  for (Int_t k = 0; k < nb2; k++) {
5005  TBranch* b2 = (TBranch*) lb1->UncheckedAt(k);
5006  if (!strcmp(b2->GetName(), name)) {
5007  return b2;
5008  }
5009  }
5010  }
5011  }
5012 
5013  // Search using leaves.
5014  TObjArray* leaves = GetListOfLeaves();
5015  Int_t nleaves = leaves->GetEntriesFast();
5016  for (Int_t i = 0; i < nleaves; i++) {
5017  TLeaf* leaf = (TLeaf*) leaves->UncheckedAt(i);
5018  TBranch* branch = leaf->GetBranch();
5019  if (!strcmp(branch->GetName(), name)) {
5020  return branch;
5021  }
5022  }
5023 
5024  if (!fFriends) {
5025  return 0;
5026  }
5027 
5028  // Search in list of friends.
5029  TFriendLock lock(this, kGetBranch);
5030  TIter next(fFriends);
5031  TFriendElement* fe = 0;
5032  while ((fe = (TFriendElement*) next())) {
5033  TTree* t = fe->GetTree();
5034  if (t) {
5035  TBranch* branch = t->GetBranch(name);
5036  if (branch) {
5037  return branch;
5038  }
5039  }
5040  }
5041 
5042  // Second pass in the list of friends when
5043  // the branch name is prefixed by the tree name.
5044  next.Reset();
5045  while ((fe = (TFriendElement*) next())) {
5046  TTree* t = fe->GetTree();
5047  if (!t) {
5048  continue;
5049  }
5050  char* subname = (char*) strstr(name, fe->GetName());
5051  if (subname != name) {
5052  continue;
5053  }
5054  Int_t l = strlen(fe->GetName());
5055  subname += l;
5056  if (*subname != '.') {
5057  continue;
5058  }
5059  subname++;
5060  TBranch* branch = t->GetBranch(subname);
5061  if (branch) {
5062  return branch;
5063  }
5064  }
5065  return 0;
5066 }
5067 
5068 ////////////////////////////////////////////////////////////////////////////////
5069 /// Return status of branch with name branchname.
5070 ///
5071 /// - 0 if branch is not activated
5072 /// - 1 if branch is activated
5073 
5074 Bool_t TTree::GetBranchStatus(const char* branchname) const
5076  TBranch* br = const_cast<TTree*>(this)->GetBranch(branchname);
5077  if (br) {
5078  return br->TestBit(kDoNotProcess) == 0;
5079  }
5080  return 0;
5081 }
5082 
5083 ////////////////////////////////////////////////////////////////////////////////
5084 /// Static function returning the current branch style.
5085 ///
5086 /// - style = 0 old Branch
5087 /// - style = 1 new Bronch
5088 
5091  return fgBranchStyle;
5092 }
5093 
5094 ////////////////////////////////////////////////////////////////////////////////
5095 /// Used for automatic sizing of the cache.
5096 ///
5097 /// Estimates a suitable size for the tree cache based on AutoFlush.
5098 /// A cache sizing factor is taken from the configuration. If this yields zero
5099 /// and withDefault is true the historical algorithm for default size is used.
5100 
5101 Long64_t TTree::GetCacheAutoSize(Bool_t withDefault /* = kFALSE */ ) const
5103  const char *stcs;
5104  Double_t cacheFactor = 0.0;
5105  if (!(stcs = gSystem->Getenv("ROOT_TTREECACHE_SIZE")) || !*stcs) {
5106  cacheFactor = gEnv->GetValue("TTreeCache.Size", 1.0);
5107  } else {
5108  cacheFactor = TString(stcs).Atof();
5109  }
5110 
5111  if (cacheFactor < 0.0) {
5112  // ignore negative factors
5113  cacheFactor = 0.0;
5114  }
5115 
5116  Long64_t cacheSize = 0;
5117 
5118  if (fAutoFlush < 0) cacheSize = Long64_t(-cacheFactor*fAutoFlush);
5119  else if (fAutoFlush == 0) cacheSize = 0;
5120  else cacheSize = Long64_t(cacheFactor*1.5*fAutoFlush*GetZipBytes()/(fEntries+1));
5121 
5122  if (cacheSize >= (INT_MAX / 4)) {
5123  cacheSize = INT_MAX / 4;
5124  }
5125 
5126  if (cacheSize < 0) {
5127  cacheSize = 0;
5128  }
5129 
5130  if (cacheSize == 0 && withDefault) {
5131  if (fAutoFlush < 0) cacheSize = -fAutoFlush;
5132  else if (fAutoFlush == 0) cacheSize = 0;
5133  else cacheSize = Long64_t(1.5*fAutoFlush*GetZipBytes()/(fEntries+1));
5134  }
5135 
5136  return cacheSize;
5137 }
5138 
5139 ////////////////////////////////////////////////////////////////////////////////
5140 /// Return an iterator over the cluster of baskets starting at firstentry.
5141 ///
5142 /// This iterator is not yet supported for TChain object.
5143 /// ~~~ {.cpp}
5144 /// TTree::TClusterIterator clusterIter = tree->GetClusterIterator(entry);
5145 /// Long64_t clusterStart;
5146 /// while( (clusterStart = clusterIter()) < tree->GetEntries() ) {
5147 /// printf("The cluster starts at %lld and ends at %lld (inclusive)\n",clusterStart,clusterIter.GetNextEntry()-1);
5148 /// }
5149 /// ~~~
5150 
5153  // create cache if wanted
5155 
5156  return TClusterIterator(this,firstentry);
5157 }
5158 
5159 ////////////////////////////////////////////////////////////////////////////////
5160 /// Return pointer to the current file.
5161 
5164  if (!fDirectory || fDirectory==gROOT) {
5165  return 0;
5166  }
5167  return fDirectory->GetFile();
5168 }
5169 
5170 ////////////////////////////////////////////////////////////////////////////////
5171 /// Return the number of entries matching the selection.
5172 /// Return -1 in case of errors.
5173 ///
5174 /// If the selection uses any arrays or containers, we return the number
5175 /// of entries where at least one element match the selection.
5176 /// GetEntries is implemented using the selector class TSelectorEntries,
5177 /// which can be used directly (see code in TTreePlayer::GetEntries) for
5178 /// additional option.
5179 /// If SetEventList was used on the TTree or TChain, only that subset
5180 /// of entries will be considered.
5181 
5182 Long64_t TTree::GetEntries(const char *selection)
5184  GetPlayer();
5185  if (fPlayer) {
5186  return fPlayer->GetEntries(selection);
5187  }
5188  return -1;
5189 }
5190 
5191 ////////////////////////////////////////////////////////////////////////////////
5192 /// Return pointer to the 1st Leaf named name in any Branch of this Tree or
5193 /// any branch in the list of friend trees.
5194 
5197  if (fEntries) return fEntries;
5198  if (!fFriends) return 0;
5200  if (!fr) return 0;
5201  TTree *t = fr->GetTree();
5202  if (t==0) return 0;
5203  return t->GetEntriesFriend();
5204 }
5205 
5206 ////////////////////////////////////////////////////////////////////////////////
5207 /// Read all branches of entry and return total number of bytes read.
5208 ///
5209 /// - `getall = 0` : get only active branches
5210 /// - `getall = 1` : get all branches
5211 ///
5212 /// The function returns the number of bytes read from the input buffer.
5213 /// If entry does not exist the function returns 0.
5214 /// If an I/O error occurs, the function returns -1.
5215 ///
5216 /// If the Tree has friends, also read the friends entry.
5217 ///
5218 /// To activate/deactivate one or more branches, use TBranch::SetBranchStatus
5219 /// For example, if you have a Tree with several hundred branches, and you
5220 /// are interested only by branches named "a" and "b", do
5221 /// ~~~ {.cpp}
5222 /// mytree.SetBranchStatus("*",0); //disable all branches
5223 /// mytree.SetBranchStatus("a",1);
5224 /// mytree.SetBranchStatus("b",1);
5225 /// ~~~
5226 /// when calling mytree.GetEntry(i); only branches "a" and "b" will be read.
5227 ///
5228 /// __WARNING!!__
5229 /// If your Tree has been created in split mode with a parent branch "parent.",
5230 /// ~~~ {.cpp}
5231 /// mytree.SetBranchStatus("parent",1);
5232 /// ~~~
5233 /// will not activate the sub-branches of "parent". You should do:
5234 /// ~~~ {.cpp}
5235 /// mytree.SetBranchStatus("parent*",1);
5236 /// ~~~
5237 /// Without the trailing dot in the branch creation you have no choice but to
5238 /// call SetBranchStatus explicitly for each of the sub branches.
5239 ///
5240 /// An alternative is to call directly
5241 /// ~~~ {.cpp}
5242 /// brancha.GetEntry(i)
5243 /// branchb.GetEntry(i);
5244 /// ~~~
5245 /// ## IMPORTANT NOTE
5246 ///
5247 /// By default, GetEntry reuses the space allocated by the previous object
5248 /// for each branch. You can force the previous object to be automatically
5249 /// deleted if you call mybranch.SetAutoDelete(kTRUE) (default is kFALSE).
5250 ///
5251 /// Example:
5252 ///
5253 /// Consider the example in $ROOTSYS/test/Event.h
5254 /// The top level branch in the tree T is declared with:
5255 /// ~~~ {.cpp}
5256 /// Event *event = 0; //event must be null or point to a valid object
5257 /// //it must be initialized
5258 /// T.SetBranchAddress("event",&event);
5259 /// ~~~
5260 /// When reading the Tree, one can choose one of these 3 options:
5261 ///
5262 /// ## OPTION 1
5263 ///
5264 /// ~~~ {.cpp}
5265 /// for (Long64_t i=0;i<nentries;i++) {
5266 /// T.GetEntry(i);
5267 /// // the object event has been filled at this point
5268 /// }
5269 /// ~~~
5270 /// The default (recommended). At the first entry an object of the class
5271 /// Event will be created and pointed by event. At the following entries,
5272 /// event will be overwritten by the new data. All internal members that are
5273 /// TObject* are automatically deleted. It is important that these members
5274 /// be in a valid state when GetEntry is called. Pointers must be correctly
5275 /// initialized. However these internal members will not be deleted if the
5276 /// characters "->" are specified as the first characters in the comment
5277 /// field of the data member declaration.
5278 ///
5279 /// If "->" is specified, the pointer member is read via pointer->Streamer(buf).
5280 /// In this case, it is assumed that the pointer is never null (case of
5281 /// pointer TClonesArray *fTracks in the Event example). If "->" is not
5282 /// specified, the pointer member is read via buf >> pointer. In this case
5283 /// the pointer may be null. Note that the option with "->" is faster to
5284 /// read or write and it also consumes less space in the file.
5285 ///
5286 /// ## OPTION 2
5287 ///
5288 /// The option AutoDelete is set
5289 /// ~~~ {.cpp}
5290 /// TBranch *branch = T.GetBranch("event");
5291 /// branch->SetAddress(&event);
5292 /// branch->SetAutoDelete(kTRUE);
5293 /// for (Long64_t i=0;i<nentries;i++) {
5294 /// T.GetEntry(i);
5295 /// // the object event has been filled at this point
5296 /// }
5297 /// ~~~
5298 /// In this case, at each iteration, the object event is deleted by GetEntry
5299 /// and a new instance of Event is created and filled.
5300 ///
5301 /// ## OPTION 3
5302 /// ~~~ {.cpp}
5303 /// Same as option 1, but you delete yourself the event.
5304 ///
5305 /// for (Long64_t i=0;i<nentries;i++) {
5306 /// delete event;
5307 /// event = 0; // EXTREMELY IMPORTANT
5308 /// T.GetEntry(i);
5309 /// // the object event has been filled at this point
5310 /// }
5311 /// ~~~
5312 /// It is strongly recommended to use the default option 1. It has the
5313 /// additional advantage that functions like TTree::Draw (internally calling
5314 /// TTree::GetEntry) will be functional even when the classes in the file are
5315 /// not available.
5316 ///
5317 /// Note: See the comments in TBranchElement::SetAddress() for the
5318 /// object ownership policy of the underlying (user) data.
5319 
5320 Int_t TTree::GetEntry(Long64_t entry, Int_t getall)
5322 
5323  // We already have been visited while recursively looking
5324  // through the friends tree, let return
5325  if (kGetEntry & fFriendLockStatus) return 0;
5326 
5327  if (entry < 0 || entry >= fEntries) return 0;
5328  Int_t i;
5329  Int_t nbytes = 0;
5330  fReadEntry = entry;
5331 
5332  // create cache if wanted
5334 
5335  Int_t nbranches = fBranches.GetEntriesFast();
5336  Int_t nb=0;
5337 
5338  auto seqprocessing = [&]() {
5339  TBranch *branch;
5340  for (i=0;i<nbranches;i++) {
5341  branch = (TBranch*)fBranches.UncheckedAt(i);
5342  nb = branch->GetEntry(entry, getall);
5343  if (nb < 0) break;
5344  nbytes += nb;
5345  }
5346  };
5347 
5348 #ifdef R__USE_IMT
5350  if (fSortedBranches.empty()) InitializeBranchLists(true);
5351 
5352  // Count branches are processed first and sequentially
5353  for (auto branch : fSeqBranches) {
5354  nb = branch->GetEntry(entry, getall);
5355  if (nb < 0) break;
5356  nbytes += nb;
5357  }
5358  if (nb < 0) return nb;
5359 
5360  // Enable this IMT use case (activate its locks)
5362 
5363  Int_t errnb = 0;
5364  std::atomic<Int_t> pos(0);
5365  std::atomic<Int_t> nbpar(0);
5366 
5367  auto mapFunction = [&]() {
5368  // The branch to process is obtained when the task starts to run.
5369  // This way, since branches are sorted, we make sure that branches
5370  // leading to big tasks are processed first. If we assigned the
5371  // branch at task creation time, the scheduler would not necessarily
5372  // respect our sorting.
5373  Int_t j = pos.fetch_add(1);
5374 
5375  Int_t nbtask = 0;
5376  auto branch = fSortedBranches[j].second;
5377 
5378  if (gDebug > 0) {
5379  std::stringstream ss;
5380  ss << std::this_thread::get_id();
5381  Info("GetEntry", "[IMT] Thread %s", ss.str().c_str());
5382  Info("GetEntry", "[IMT] Running task for branch #%d: %s", j, branch->GetName());
5383  }
5384 
5385  std::chrono::time_point<std::chrono::system_clock> start, end;
5386 
5387  start = std::chrono::system_clock::now();
5388  nbtask = branch->GetEntry(entry, getall);
5389  end = std::chrono::system_clock::now();
5390 
5391  Long64_t tasktime = (Long64_t)std::chrono::duration_cast<std::chrono::microseconds>(end - start).count();
5392  fSortedBranches[j].first += tasktime;
5393 
5394  if (nbtask < 0) errnb = nbtask;
5395  else nbpar += nbtask;
5396  };
5397 
5398  ROOT::TThreadExecutor pool;
5399  pool.Foreach(mapFunction, fSortedBranches.size());
5400 
5401  if (errnb < 0) {
5402  nb = errnb;
5403  }
5404  else {
5405  // Save the number of bytes read by the tasks
5406  nbytes += nbpar;
5407 
5408  // Re-sort branches if necessary
5412  }
5413  }
5414  }
5415  else {
5416  seqprocessing();
5417  }
5418 #else
5419  seqprocessing();
5420 #endif
5421  if (nb < 0) return nb;
5422 
5423  // GetEntry in list of friends
5424  if (!fFriends) return nbytes;
5425  TFriendLock lock(this,kGetEntry);
5426  TIter nextf(fFriends);
5427  TFriendElement *fe;
5428  while ((fe = (TFriendElement*)nextf())) {
5429  TTree *t = fe->GetTree();
5430  if (t) {
5432  nb = t->GetEntry(t->GetReadEntry(),getall);
5433  } else {
5434  if ( t->LoadTreeFriend(entry,this) >= 0 ) {
5435  nb = t->GetEntry(t->GetReadEntry(),getall);
5436  } else nb = 0;
5437  }
5438  if (nb < 0) return nb;
5439  nbytes += nb;
5440  }
5441  }
5442  return nbytes;
5443 }
5444 
5445 
5446 ////////////////////////////////////////////////////////////////////////////////
5447 /// Divides the top-level branches into two vectors: (i) branches to be
5448 /// processed sequentially and (ii) branches to be processed in parallel.
5449 /// Even if IMT is on, some branches might need to be processed first and in a
5450 /// sequential fashion: in the parallelization of GetEntry, those are the
5451 /// branches that store the size of another branch for every entry
5452 /// (e.g. the size of an array branch). If such branches were processed
5453 /// in parallel with the rest, there could be two threads invoking
5454 /// TBranch::GetEntry on one of them at the same time, since a branch that
5455 /// depends on a size (or count) branch will also invoke GetEntry on the latter.
5456 /// \param[in] checkLeafCount True if we need to check whether some branches are
5457 /// count leaves.
5458 
5459 void TTree::InitializeBranchLists(bool checkLeafCount)
5461  Int_t nbranches = fBranches.GetEntriesFast();
5462 
5463  // The branches to be processed sequentially are those that are the leaf count of another branch
5464  if (checkLeafCount) {
5465  for (Int_t i = 0; i < nbranches; i++) {
5466  TBranch* branch = (TBranch*)fBranches.UncheckedAt(i);
5467  auto leafCount = ((TLeaf*)branch->GetListOfLeaves()->At(0))->GetLeafCount();
5468  if (leafCount) {
5469  auto countBranch = leafCount->GetBranch();
5470  if (std::find(fSeqBranches.begin(), fSeqBranches.end(), countBranch) == fSeqBranches.end()) {
5471  fSeqBranches.push_back(countBranch);
5472  }
5473  }
5474  }
5475  }
5476 
5477  // The special branch fBranchRef also needs to be processed sequentially
5478  if (fBranchRef) {
5479  fSeqBranches.push_back(fBranchRef);
5480  }
5481 
5482  // Any branch that is not a leaf count can be safely processed in parallel when reading
5483  for (Int_t i = 0; i < nbranches; i++) {
5484  Long64_t bbytes = 0;
5485  TBranch* branch = (TBranch*)fBranches.UncheckedAt(i);
5486  if (std::find(fSeqBranches.begin(), fSeqBranches.end(), branch) == fSeqBranches.end()) {
5487  bbytes = branch->GetTotBytes("*");
5488  fSortedBranches.emplace_back(bbytes, branch);
5489  }
5490  }
5491 
5492  // Initially sort parallel branches by size
5493  std::sort(fSortedBranches.begin(),
5494  fSortedBranches.end(),
5495  [](std::pair<Long64_t,TBranch*> a, std::pair<Long64_t,TBranch*> b) {
5496  return a.first > b.first;
5497  });
5498 
5499  for (size_t i = 0; i < fSortedBranches.size(); i++) {
5500  fSortedBranches[i].first = 0LL;
5501  }
5502 }
5503 
5504 ////////////////////////////////////////////////////////////////////////////////
5505 /// Sorts top-level branches by the last average task time recorded per branch.
5506 
5509  for (size_t i = 0; i < fSortedBranches.size(); i++) {
5510  fSortedBranches[i].first *= kNEntriesResortInv;
5511  }
5512 
5513  std::sort(fSortedBranches.begin(),
5514  fSortedBranches.end(),
5515  [](std::pair<Long64_t,TBranch*> a, std::pair<Long64_t,TBranch*> b) {
5516  return a.first > b.first;
5517  });
5518 
5519  for (size_t i = 0; i < fSortedBranches.size(); i++) {
5520  fSortedBranches[i].first = 0LL;
5521  }
5522 }
5523 
5524 ////////////////////////////////////////////////////////////////////////////////
5525 ///Returns the entry list, set to this tree
5526 
5529  return fEntryList;
5530 }
5531 
5532 ////////////////////////////////////////////////////////////////////////////////
5533 /// Return entry number corresponding to entry.
5534 ///
5535 /// if no TEntryList set returns entry
5536 /// else returns the entry number corresponding to the list index=entry
5537 
5540  if (!fEntryList) {
5541  return entry;
5542  }
5543 
5544  return fEntryList->GetEntry(entry);
5545 }
5546 
5547 ////////////////////////////////////////////////////////////////////////////////
5548 /// Return entry number corresponding to major and minor number.
5549 /// Note that this function returns only the entry number, not the data
5550 /// To read the data corresponding to an entry number, use TTree::GetEntryWithIndex
5551 /// the BuildIndex function has created a table of Long64_t* of sorted values
5552 /// corresponding to val = major<<31 + minor;
5553 /// The function performs binary search in this sorted table.
5554 /// If it finds a pair that matches val, it returns directly the
5555 /// index in the table.
5556 /// If an entry corresponding to major and minor is not found, the function
5557 /// returns the index of the major,minor pair immediately lower than the
5558 /// requested value, ie it will return -1 if the pair is lower than
5559 /// the first entry in the index.
5560 ///
5561 /// See also GetEntryNumberWithIndex
5562 
5565  if (!fTreeIndex) {
5566  return -1;
5567  }
5568  return fTreeIndex->GetEntryNumberWithBestIndex(major, minor);
5569 }
5570 
5571 ////////////////////////////////////////////////////////////////////////////////
5572 /// Return entry number corresponding to major and minor number.
5573 /// Note that this function returns only the entry number, not the data
5574 /// To read the data corresponding to an entry number, use TTree::GetEntryWithIndex
5575 /// the BuildIndex function has created a table of Long64_t* of sorted values
5576 /// corresponding to val = major<<31 + minor;
5577 /// The function performs binary search in this sorted table.
5578 /// If it finds a pair that matches val, it returns directly the
5579 /// index in the table, otherwise it returns -1.
5580 ///
5581 /// See also GetEntryNumberWithBestIndex
5582 
5585  if (!fTreeIndex) {
5586  return -1;
5587  }
5588  return fTreeIndex->GetEntryNumberWithIndex(major, minor);
5589 }
5590 
5591 ////////////////////////////////////////////////////////////////////////////////
5592 /// Read entry corresponding to major and minor number.
5593 ///
5594 /// The function returns the total number of bytes read.
5595 /// If the Tree has friend trees, the corresponding entry with
5596 /// the index values (major,minor) is read. Note that the master Tree
5597 /// and its friend may have different entry serial numbers corresponding
5598 /// to (major,minor).
5599 
5602  // We already have been visited while recursively looking
5603  // through the friends tree, let's return.
5605  return 0;
5606  }
5607  Long64_t serial = GetEntryNumberWithIndex(major, minor);
5608  if (serial < 0) {
5609  return -1;
5610  }
5611  // create cache if wanted
5613 
5614  Int_t i;
5615  Int_t nbytes = 0;
5616  fReadEntry = serial;
5617  TBranch *branch;
5618  Int_t nbranches = fBranches.GetEntriesFast();
5619  Int_t nb;
5620  for (i = 0; i < nbranches; ++i) {
5621  branch = (TBranch*)fBranches.UncheckedAt(i);
5622  nb = branch->GetEntry(serial);
5623  if (nb < 0) return nb;
5624  nbytes += nb;
5625  }
5626  // GetEntry in list of friends
5627  if (!fFriends) return nbytes;
5628  TFriendLock lock(this,kGetEntryWithIndex);
5629  TIter nextf(fFriends);
5630  TFriendElement* fe = 0;
5631  while ((fe = (TFriendElement*) nextf())) {
5632  TTree *t = fe->GetTree();
5633  if (t) {
5634  serial = t->GetEntryNumberWithIndex(major,minor);
5635  if (serial <0) return -nbytes;
5636  nb = t->GetEntry(serial);
5637  if (nb < 0) return nb;
5638  nbytes += nb;
5639  }
5640  }
5641  return nbytes;
5642 }
5643 
5644 ////////////////////////////////////////////////////////////////////////////////
5645 /// Return a pointer to the TTree friend whose name or alias is 'friendname.
5646 
5647 TTree* TTree::GetFriend(const char *friendname) const
5649 
5650  // We already have been visited while recursively
5651  // looking through the friends tree, let's return.
5652  if (kGetFriend & fFriendLockStatus) {
5653  return 0;
5654  }
5655  if (!fFriends) {
5656  return 0;
5657  }
5658  TFriendLock lock(const_cast<TTree*>(this), kGetFriend);
5659  TIter nextf(fFriends);
5660  TFriendElement* fe = 0;
5661  while ((fe = (TFriendElement*) nextf())) {
5662  if (strcmp(friendname,fe->GetName())==0
5663  || strcmp(friendname,fe->GetTreeName())==0) {
5664  return fe->GetTree();
5665  }
5666  }
5667  // After looking at the first level,
5668  // let's see if it is a friend of friends.
5669  nextf.Reset();
5670  fe = 0;
5671  while ((fe = (TFriendElement*) nextf())) {
5672  TTree *res = fe->GetTree()->GetFriend(friendname);
5673  if (res) {
5674  return res;
5675  }
5676  }
5677  return 0;
5678 }
5679 
5680 ////////////////////////////////////////////////////////////////////////////////
5681 /// If the 'tree' is a friend, this method returns its alias name.
5682 ///
5683 /// This alias is an alternate name for the tree.
5684 ///
5685 /// It can be used in conjunction with a branch or leaf name in a TTreeFormula,
5686 /// to specify in which particular tree the branch or leaf can be found if
5687 /// the friend trees have branches or leaves with the same name as the master
5688 /// tree.
5689 ///
5690 /// It can also be used in conjunction with an alias created using
5691 /// TTree::SetAlias in a TTreeFormula, e.g.:
5692 /// ~~~ {.cpp}
5693 /// maintree->Draw("treealias.fPx - treealias.myAlias");
5694 /// ~~~
5695 /// where fPx is a branch of the friend tree aliased as 'treealias' and 'myAlias'
5696 /// was created using TTree::SetAlias on the friend tree.
5697 ///
5698 /// However, note that 'treealias.myAlias' will be expanded literally,
5699 /// without remembering that it comes from the aliased friend and thus
5700 /// the branch name might not be disambiguated properly, which means
5701 /// that you may not be able to take advantage of this feature.
5702 ///
5703 
5704 const char* TTree::GetFriendAlias(TTree* tree) const
5706  if ((tree == this) || (tree == GetTree())) {
5707  return 0;
5708  }
5709 
5710  // We already have been visited while recursively
5711  // looking through the friends tree, let's return.
5713  return 0;
5714  }
5715  if (!fFriends) {
5716  return 0;
5717  }
5718  TFriendLock lock(const_cast<TTree*>(this), kGetFriendAlias);
5719  TIter nextf(fFriends);
5720  TFriendElement* fe = 0;
5721  while ((fe = (TFriendElement*) nextf())) {
5722  TTree* t = fe->GetTree();
5723  if (t == tree) {
5724  return fe->GetName();
5725  }
5726  // Case of a chain:
5727  if (t && t->GetTree() == tree) {
5728  return fe->GetName();
5729  }
5730  }
5731  // After looking at the first level,
5732  // let's see if it is a friend of friends.
5733  nextf.Reset();
5734  fe = 0;
5735  while ((fe = (TFriendElement*) nextf())) {
5736  const char* res = fe->GetTree()->GetFriendAlias(tree);
5737  if (res) {
5738  return res;
5739  }
5740  }
5741  return 0;
5742 }
5743 
5744 ////////////////////////////////////////////////////////////////////////////////
5745 /// Creates a new iterator that will go through all the leaves on the tree itself and its friend.
5746 
5749  return new TTreeFriendLeafIter(this, dir);
5750 }
5751 
5752 ////////////////////////////////////////////////////////////////////////////////
5753 /// Return pointer to the 1st Leaf named name in any Branch of this
5754 /// Tree or any branch in the list of friend trees.
5755 ///
5756 /// The leaf name can contain the name of a friend tree with the
5757 /// syntax: friend_dir_and_tree.full_leaf_name
5758 /// the friend_dir_and_tree can be of the form:
5759 /// ~~~ {.cpp}
5760 /// TDirectoryName/TreeName
5761 /// ~~~
5762 
5763 TLeaf* TTree::GetLeafImpl(const char* branchname, const char *leafname)
5765  TLeaf *leaf = 0;
5766  if (branchname) {
5767  TBranch *branch = FindBranch(branchname);
5768  if (branch) {
5769  leaf = branch->GetLeaf(leafname);
5770  if (leaf) {
5771  return leaf;
5772  }
5773  }
5774  }
5775  TIter nextl(GetListOfLeaves());
5776  while ((leaf = (TLeaf*)nextl())) {
5777  if (strcmp(leaf->GetName(),leafname)) continue;
5778  if (branchname) {
5779  UInt_t nbch = strlen(branchname);
5780  TBranch *br = leaf->GetBranch();
5781  const char* brname = br->GetName();
5782  TBranch *mother = br->GetMother();
5783  if (strncmp(brname,branchname,nbch)) {
5784  if (mother != br) {
5785  const char *mothername = mother->GetName();
5786  UInt_t motherlen = strlen(mothername);
5787  if (nbch > motherlen && strncmp(mothername,branchname,motherlen)==0 && (mothername[motherlen-1]=='.' || branchname[motherlen]=='.')) {
5788  // 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.
5789  if (strncmp(brname,branchname+motherlen+1,nbch-motherlen-1)) {
5790  // No it does not
5791  continue;
5792  } // else we have match so we can proceed.
5793  } else {
5794  // no match
5795  continue;
5796  }
5797  } else {
5798  continue;
5799  }
5800  }
5801  // The start of the branch name is identical to the content
5802  // of 'aname' before the first '/'.
5803  // Let's make sure that it is not longer (we are trying
5804  // to avoid having jet2/value match the branch jet23
5805  if ((strlen(brname) > nbch) && (brname[nbch] != '.') && (brname[nbch] != '[')) {
5806  continue;
5807  }
5808  }
5809  return leaf;
5810  }
5811  if (!fFriends) return 0;
5812  TFriendLock lock(this,kGetLeaf);
5813  TIter next(fFriends);
5814  TFriendElement *fe;
5815  while ((fe = (TFriendElement*)next())) {
5816  TTree *t = fe->GetTree();
5817  if (t) {
5818  leaf = t->GetLeaf(leafname);
5819  if (leaf) return leaf;
5820  }
5821  }
5822 
5823  //second pass in the list of friends when the leaf name
5824  //is prefixed by the tree name
5825  TString strippedArg;
5826  next.Reset();
5827  while ((fe = (TFriendElement*)next())) {
5828  TTree *t = fe->GetTree();
5829  if (t==0) continue;
5830  char *subname = (char*)strstr(leafname,fe->GetName());
5831  if (subname != leafname) continue;
5832  Int_t l = strlen(fe->GetName());
5833  subname += l;
5834  if (*subname != '.') continue;
5835  subname++;
5836  strippedArg += subname;
5837  leaf = t->GetLeaf(branchname,subname);
5838  if (leaf) return leaf;
5839  }
5840  return 0;
5841 }
5842 
5843 ////////////////////////////////////////////////////////////////////////////////
5844 /// Return pointer to the 1st Leaf named name in any Branch of this
5845 /// Tree or any branch in the list of friend trees.
5846 ///
5847 /// The leaf name can contain the name of a friend tree with the
5848 /// syntax: friend_dir_and_tree.full_leaf_name
5849 /// the friend_dir_and_tree can be of the form:
5850 ///
5851 /// TDirectoryName/TreeName
5852 
5853 TLeaf* TTree::GetLeaf(const char* branchname, const char *leafname)
5855  if (leafname == 0) return 0;
5856 
5857  // We already have been visited while recursively looking
5858  // through the friends tree, let return
5859  if (kGetLeaf & fFriendLockStatus) {
5860  return 0;
5861  }
5862 
5863  return GetLeafImpl(branchname,leafname);
5864 }
5865 
5866 ////////////////////////////////////////////////////////////////////////////////
5867 /// Return pointer to the 1st Leaf named name in any Branch of this
5868 /// Tree or any branch in the list of friend trees.
5869 ///
5870 /// aname may be of the form branchname/leafname
5871 
5872 TLeaf* TTree::GetLeaf(const char* aname)
5874  if (aname == 0) return 0;
5875 
5876  // We already have been visited while recursively looking
5877  // through the friends tree, let return
5878  if (kGetLeaf & fFriendLockStatus) {
5879  return 0;
5880  }
5881  char* slash = (char*) strrchr(aname, '/');
5882  char* name = 0;
5883  UInt_t nbch = 0;
5884  if (slash) {
5885  name = slash + 1;
5886  nbch = slash - aname;
5887  TString brname(aname,nbch);
5888  return GetLeafImpl(brname.Data(),name);
5889  } else {
5890  return GetLeafImpl(0,aname);
5891  }
5892 }
5893 
5894 ////////////////////////////////////////////////////////////////////////////////
5895 /// Return maximum of column with name columname.
5896 /// if the Tree has an associated TEventList or TEntryList, the maximum
5897 /// is computed for the entries in this list.
5898 
5899 Double_t TTree::GetMaximum(const char* columname)
5901  TLeaf* leaf = this->GetLeaf(columname);
5902  if (!leaf) {
5903  return 0;
5904  }
5905 
5906  // create cache if wanted
5908 
5909  TBranch* branch = leaf->GetBranch();
5910  Double_t cmax = -DBL_MAX;
5911  for (Long64_t i = 0; i < fEntries; ++i) {
5912  Long64_t entryNumber = this->GetEntryNumber(i);
5913  if (entryNumber < 0) break;
5914  branch->GetEntry(entryNumber);
5915  for (Int_t j = 0; j < leaf->GetLen(); ++j) {
5916  Double_t val = leaf->GetValue(j);
5917  if (val > cmax) {
5918  cmax = val;
5919  }
5920  }
5921  }
5922  return cmax;
5923 }
5924 
5925 ////////////////////////////////////////////////////////////////////////////////
5926 /// Static function which returns the tree file size limit in bytes.
5927 
5930  return fgMaxTreeSize;
5931 }
5932 
5933 ////////////////////////////////////////////////////////////////////////////////
5934 /// Return minimum of column with name columname.
5935 /// if the Tree has an associated TEventList or TEntryList, the minimum
5936 /// is computed for the entries in this list.
5937 
5938 Double_t TTree::GetMinimum(const char* columname)
5940  TLeaf* leaf = this->GetLeaf(columname);
5941  if (!leaf) {
5942  return 0;
5943  }
5944 
5945  // create cache if wanted
5947 
5948  TBranch* branch = leaf->GetBranch();
5949  Double_t cmin = DBL_MAX;
5950  for (Long64_t i = 0; i < fEntries; ++i) {
5951  Long64_t entryNumber = this->GetEntryNumber(i);
5952  if (entryNumber < 0) break;
5953  branch->GetEntry(entryNumber);
5954  for (Int_t j = 0;j < leaf->GetLen(); ++j) {
5955  Double_t val = leaf->GetValue(j);
5956  if (val < cmin) {
5957  cmin = val;
5958  }
5959  }
5960  }
5961  return cmin;
5962 }
5963 
5964 ////////////////////////////////////////////////////////////////////////////////
5965 /// Load the TTreePlayer (if not already done).
5966 
5969  if (fPlayer) {
5970  return fPlayer;
5971  }
5973  return fPlayer;
5974 }
5975 
5976 ////////////////////////////////////////////////////////////////////////////////
5977 /// Find and return the TTreeCache registered with the file and which may
5978 /// contain branches for us. If create is true and there is no cache
5979 /// a new cache is created with default size.
5980 
5981 TTreeCache *TTree::GetReadCache(TFile *file, Bool_t create /* = kFALSE */ )
5983  TTreeCache *pe = dynamic_cast<TTreeCache*>(file->GetCacheRead(this));
5984  if (pe && pe->GetTree() != this) pe = 0;
5985  if (create && !pe) {
5987  pe = dynamic_cast<TTreeCache*>(file->GetCacheRead(this));
5988  if (pe && pe->GetTree() != this) pe = 0;
5989  }
5990  return pe;
5991 }
5992 
5993 ////////////////////////////////////////////////////////////////////////////////
5994 /// Return a pointer to the list containing user objects associated to this tree.
5995 ///
5996 /// The list is automatically created if it does not exist.
5997 ///
5998 /// WARNING: By default the TTree destructor will delete all objects added
5999 /// to this list. If you do not want these objects to be deleted,
6000 /// call:
6001 ///
6002 /// mytree->GetUserInfo()->Clear();
6003 ///
6004 /// before deleting the tree.
6005 
6008  if (!fUserInfo) {
6009  fUserInfo = new TList();
6010  fUserInfo->SetName("UserInfo");
6011  }
6012  return fUserInfo;
6013 }
6014 
6015 ////////////////////////////////////////////////////////////////////////////////
6016 /// Appends the cluster range information stored in 'fromtree' to this tree,
6017 /// including the value of fAutoFlush.
6018 ///
6019 /// This is used when doing a fast cloning (by TTreeCloner).
6020 /// See also fAutoFlush and fAutoSave if needed.
6021 
6022 void TTree::ImportClusterRanges(TTree *fromtree)
6024  Long64_t autoflush = fromtree->GetAutoFlush();
6025  if (fNClusterRange || fromtree->fNClusterRange) {
6026  Int_t newsize = fNClusterRange + 1 + fromtree->fNClusterRange;
6027  if (newsize > fMaxClusterRange) {
6028  if (fMaxClusterRange) {
6030  newsize*sizeof(Long64_t),fMaxClusterRange*sizeof(Long64_t));
6032  newsize*sizeof(Long64_t),fMaxClusterRange*sizeof(Long64_t));
6033  fMaxClusterRange = newsize;
6034  } else {
6035  fMaxClusterRange = newsize;
6038  }
6039  }
6040  if (fEntries) {
6043  ++fNClusterRange;
6044  }
6045  for (Int_t i = 0 ; i < fromtree->fNClusterRange; ++i) {
6047  fClusterSize[fNClusterRange] = fromtree->fClusterSize[i];
6048  ++fNClusterRange;
6049  }
6050  fAutoFlush = autoflush;
6051  } else {
6052  SetAutoFlush( autoflush );
6053  }
6054  Long64_t autosave = GetAutoSave();
6055  if (autoflush > 0 && autosave > 0) {
6056  SetAutoSave( autoflush*(autosave/autoflush) );
6057  }
6058 }
6059 
6060 ////////////////////////////////////////////////////////////////////////////////
6061 /// Keep a maximum of fMaxEntries in memory.
6062 
6063 void TTree::KeepCircular()
6066  Long64_t maxEntries = fMaxEntries - (fMaxEntries / 10);
6067  for (Int_t i = 0; i < nb; ++i) {
6068  TBranch* branch = (TBranch*) fBranches.UncheckedAt(i);
6069  branch->KeepCircular(maxEntries);
6070  }
6071  if (fNClusterRange) {
6072  Long64_t entriesOffset = fEntries - maxEntries;
6073  Int_t oldsize = fNClusterRange;
6074  for(Int_t i = 0, j = 0; j < oldsize; ++j) {
6075  if (fClusterRangeEnd[j] > entriesOffset) {
6076  fClusterRangeEnd[i] = fClusterRangeEnd[j] - entriesOffset;
6077  ++i;
6078  } else {
6079  --fNClusterRange;
6080  }
6081  }
6082  }
6083  fEntries = maxEntries;
6084  fReadEntry = -1;
6085 }
6086 
6087 ////////////////////////////////////////////////////////////////////////////////
6088 /// Read in memory all baskets from all branches up to the limit of maxmemory bytes.
6089 ///
6090 /// If maxmemory is non null and positive SetMaxVirtualSize is called
6091 /// with this value. Default for maxmemory is 2000000000 (2 Gigabytes).
6092 /// The function returns the total number of baskets read into memory
6093 /// if negative an error occurred while loading the branches.
6094 /// This method may be called to force branch baskets in memory
6095 /// when random access to branch entries is required.
6096 /// If random access to only a few branches is required, you should
6097 /// call directly TBranch::LoadBaskets.
6098 
6101  if (maxmemory > 0) SetMaxVirtualSize(maxmemory);
6102 
6103  TIter next(GetListOfLeaves());
6104  TLeaf *leaf;
6105  Int_t nimported = 0;
6106  while ((leaf=(TLeaf*)next())) {
6107  nimported += leaf->GetBranch()->LoadBaskets();//break;
6108  }
6109  return nimported;
6110 }
6111 
6112 ////////////////////////////////////////////////////////////////////////////////
6113 /// Set current entry.
6114 ///
6115 /// Returns -2 if entry does not exist (just as TChain::LoadTree()).
6116 ///
6117 /// Note: This function is overloaded in TChain.
6118 ///
6119 
6122  // We already have been visited while recursively looking
6123  // through the friends tree, let return
6124  if (kLoadTree & fFriendLockStatus) {
6125  // We need to return a negative value to avoid a circular list of friend
6126  // to think that there is always an entry somewhere in the list.
6127  return -1;
6128  }
6129 
6130  if (fNotify) {
6131  if (fReadEntry < 0) {
6132  fNotify->Notify();
6133  }
6134  }
6135  fReadEntry = entry;
6136 
6137  Bool_t friendHasEntry = kFALSE;
6138  if (fFriends) {
6139  // Set current entry in friends as well.
6140  //
6141  // An alternative would move this code to each of the
6142  // functions calling LoadTree (and to overload a few more).
6143  Bool_t needUpdate = kFALSE;
6144  {
6145  // This scope is need to insure the lock is released at the right time
6146  TIter nextf(fFriends);
6147  TFriendLock lock(this, kLoadTree);
6148  TFriendElement* fe = 0;
6149  while ((fe = (TFriendElement*) nextf())) {
6151  // This friend element was added by the chain that owns this
6152  // tree, the chain will deal with loading the correct entry.
6153  continue;
6154  }
6155  TTree* friendTree = fe->GetTree();
6156  if (friendTree == 0) {
6157  // Somehow we failed to retrieve the friend TTree.
6158  } else if (friendTree->IsA() == TTree::Class()) {
6159  // Friend is actually a tree.
6160  if (friendTree->LoadTreeFriend(entry, this) >= 0) {
6161  friendHasEntry = kTRUE;
6162  }
6163  } else {
6164  // Friend is actually a chain.
6165  // FIXME: This logic should be in the TChain override.
6166  Int_t oldNumber = friendTree->GetTreeNumber();
6167  if (friendTree->LoadTreeFriend(entry, this) >= 0) {
6168  friendHasEntry = kTRUE;
6169  }
6170  Int_t newNumber = friendTree->GetTreeNumber();
6171  if (oldNumber != newNumber) {
6172  // We can not just compare the tree pointers because they could be reused.
6173  // So we compare the tree number instead.
6174  needUpdate = kTRUE;
6175  }
6176  }
6177  } // for each friend
6178  }
6179  if (needUpdate) {
6180  //update list of leaves in all TTreeFormula of the TTreePlayer (if any)
6181  if (fPlayer) {
6183  }
6184  //Notify user if requested
6185  if (fNotify) {
6186  fNotify->Notify();
6187  }
6188  }
6189  }
6190 
6191  if ((fReadEntry >= fEntries) && !friendHasEntry) {
6192  fReadEntry = -1;
6193  return -2;
6194  }
6195  return fReadEntry;
6196 }
6197 
6198 ////////////////////////////////////////////////////////////////////////////////
6199 /// Load entry on behalf of our master tree, we may use an index.
6200 ///
6201 /// Called by LoadTree() when the masterTree looks for the entry
6202 /// number in a friend tree (us) corresponding to the passed entry
6203 /// number in the masterTree.
6204 ///
6205 /// If we have no index, our entry number and the masterTree entry
6206 /// number are the same.
6207 ///
6208 /// If we *do* have an index, we must find the (major, minor) value pair
6209 /// in masterTree to locate our corresponding entry.
6210 ///
6211 
6212 Long64_t TTree::LoadTreeFriend(Long64_t entry, TTree* masterTree)
6214  if (!fTreeIndex) {
6215  return LoadTree(entry);
6216  }
6217  return LoadTree(fTreeIndex->GetEntryNumberFriend(masterTree));
6218 }
6219 
6220 ////////////////////////////////////////////////////////////////////////////////
6221 /// Generate a skeleton analysis class for this tree.
6222 ///
6223 /// The following files are produced: classname.h and classname.C.
6224 /// If classname is 0, classname will be called "nameoftree".
6225 ///
6226 /// The generated code in classname.h includes the following:
6227 ///
6228 /// - Identification of the original tree and the input file name.
6229 /// - Definition of an analysis class (data members and member functions).
6230 /// - The following member functions:
6231 /// - constructor (by default opening the tree file),
6232 /// - GetEntry(Long64_t entry),
6233 /// - Init(TTree* tree) to initialize a new TTree,
6234 /// - Show(Long64_t entry) to read and dump entry.
6235 ///
6236 /// The generated code in classname.C includes only the main
6237 /// analysis function Loop.
6238 ///
6239 /// To use this function:
6240 ///
6241 /// - Open your tree file (eg: TFile f("myfile.root");)
6242 /// - T->MakeClass("MyClass");
6243 ///
6244 /// where T is the name of the TTree in file myfile.root,
6245 /// and MyClass.h, MyClass.C the name of the files created by this function.
6246 /// In a ROOT session, you can do:
6247 /// ~~~ {.cpp}
6248 /// root > .L MyClass.C
6249 /// root > MyClass* t = new MyClass;
6250 /// root > t->GetEntry(12); // Fill data members of t with entry number 12.
6251 /// root > t->Show(); // Show values of entry 12.
6252 /// root > t->Show(16); // Read and show values of entry 16.
6253 /// root > t->Loop(); // Loop on all entries.
6254 /// ~~~
6255 /// NOTE: Do not use the code generated for a single TTree which is part
6256 /// of a TChain to process that entire TChain. The maximum dimensions
6257 /// calculated for arrays on the basis of a single TTree from the TChain
6258 /// might be (will be!) too small when processing all of the TTrees in
6259 /// the TChain. You must use myChain.MakeClass() to generate the code,
6260 /// not myTree.MakeClass(...).
6261 
6262 Int_t TTree::MakeClass(const char* classname, Option_t* option)
6264  GetPlayer();
6265  if (!fPlayer) {
6266  return 0;
6267  }
6268  return fPlayer->MakeClass(classname, option);
6269 }
6270 
6271 ////////////////////////////////////////////////////////////////////////////////
6272 /// Generate a skeleton function for this tree.
6273 ///
6274 /// The function code is written on filename.
6275 /// If filename is 0, filename will be called nameoftree.C
6276 ///
6277 /// The generated code includes the following:
6278 /// - Identification of the original Tree and Input file name,
6279 /// - Opening the Tree file,
6280 /// - Declaration of Tree variables,
6281 /// - Setting of branches addresses,
6282 /// - A skeleton for the entry loop.
6283 ///
6284 /// To use this function:
6285 ///
6286 /// - Open your Tree file (eg: TFile f("myfile.root");)
6287 /// - T->MakeCode("MyAnalysis.C");
6288 ///
6289 /// where T is the name of the TTree in file myfile.root
6290 /// and MyAnalysis.C the name of the file created by this function.
6291 ///
6292 /// NOTE: Since the implementation of this function, a new and better
6293 /// function TTree::MakeClass() has been developed.
6294 
6295 Int_t TTree::MakeCode(const char* filename)
6297  Warning("MakeCode", "MakeCode is obsolete. Use MakeClass or MakeSelector instead");
6298 
6299  GetPlayer();
6300  if (!fPlayer) return 0;
6301  return fPlayer->MakeCode(filename);
6302 }
6303 
6304 ////////////////////////////////////////////////////////////////////////////////
6305 /// Generate a skeleton analysis class for this Tree using TBranchProxy.
6306 ///
6307 /// TBranchProxy is the base of a class hierarchy implementing an
6308 /// indirect access to the content of the branches of a TTree.
6309 ///
6310 /// "proxyClassname" is expected to be of the form:
6311 /// ~~~ {.cpp}
6312 /// [path/]fileprefix
6313 /// ~~~
6314 /// The skeleton will then be generated in the file:
6315 /// ~~~ {.cpp}
6316 /// fileprefix.h
6317 /// ~~~
6318 /// located in the current directory or in 'path/' if it is specified.
6319 /// The class generated will be named 'fileprefix'
6320 ///
6321 /// "macrofilename" and optionally "cutfilename" are expected to point
6322 /// to source files which will be included by the generated skeleton.
6323 /// Method of the same name as the file(minus the extension and path)
6324 /// will be called by the generated skeleton's Process method as follow:
6325 /// ~~~ {.cpp}
6326 /// [if (cutfilename())] htemp->Fill(macrofilename());
6327 /// ~~~
6328 /// "option" can be used select some of the optional features during
6329 /// the code generation. The possible options are:
6330 ///
6331 /// - nohist : indicates that the generated ProcessFill should not fill the histogram.
6332 ///
6333 /// 'maxUnrolling' controls how deep in the class hierarchy does the
6334 /// system 'unroll' classes that are not split. Unrolling a class
6335 /// allows direct access to its data members (this emulates the behavior
6336 /// of TTreeFormula).
6337 ///
6338 /// The main features of this skeleton are:
6339 ///
6340 /// * on-demand loading of branches
6341 /// * ability to use the 'branchname' as if it was a data member
6342 /// * protection against array out-of-bounds errors
6343 /// * ability to use the branch data as an object (when the user code is available)
6344 ///
6345 /// For example with Event.root, if
6346 /// ~~~ {.cpp}
6347 /// Double_t somePx = fTracks.fPx[2];
6348 /// ~~~
6349 /// is executed by one of the method of the skeleton,
6350 /// somePx will updated with the current value of fPx of the 3rd track.
6351 ///
6352 /// Both macrofilename and the optional cutfilename are expected to be
6353 /// the name of source files which contain at least a free standing
6354 /// function with the signature:
6355 /// ~~~ {.cpp}
6356 /// x_t macrofilename(); // i.e function with the same name as the file
6357 /// ~~~
6358 /// and
6359 /// ~~~ {.cpp}
6360 /// y_t cutfilename(); // i.e function with the same name as the file
6361 /// ~~~
6362 /// x_t and y_t needs to be types that can convert respectively to a double
6363 /// and a bool (because the skeleton uses:
6364 ///
6365 /// if (cutfilename()) htemp->Fill(macrofilename());
6366 ///
6367 /// These two functions are run in a context such that the branch names are
6368 /// available as local variables of the correct (read-only) type.
6369 ///
6370 /// Note that if you use the same 'variable' twice, it is more efficient
6371 /// to 'cache' the value. For example:
6372 /// ~~~ {.cpp}
6373 /// Int_t n = fEventNumber; // Read fEventNumber
6374 /// if (n<10 || n>10) { ... }
6375 /// ~~~
6376 /// is more efficient than
6377 /// ~~~ {.cpp}
6378 /// if (fEventNumber<10 || fEventNumber>10)
6379 /// ~~~
6380 /// Also, optionally, the generated selector will also call methods named
6381 /// macrofilename_methodname in each of 6 main selector methods if the method
6382 /// macrofilename_methodname exist (Where macrofilename is stripped of its
6383 /// extension).
6384 ///
6385 /// Concretely, with the script named h1analysisProxy.C,
6386 ///
6387 /// - The method calls the method (if it exist)
6388 /// - Begin -> void h1analysisProxy_Begin(TTree*);
6389 /// - SlaveBegin -> void h1analysisProxy_SlaveBegin(TTree*);
6390 /// - Notify -> Bool_t h1analysisProxy_Notify();
6391 /// - Process -> Bool_t h1analysisProxy_Process(Long64_t);
6392 /// - SlaveTerminate -> void h1analysisProxy_SlaveTerminate();
6393 /// - Terminate -> void h1analysisProxy_Terminate();
6394 ///
6395 /// If a file name macrofilename.h (or .hh, .hpp, .hxx, .hPP, .hXX) exist
6396 /// it is included before the declaration of the proxy class. This can
6397 /// be used in particular to insure that the include files needed by
6398 /// the macro file are properly loaded.
6399 ///
6400 /// The default histogram is accessible via the variable named 'htemp'.
6401 ///
6402 /// If the library of the classes describing the data in the branch is
6403 /// loaded, the skeleton will add the needed `include` statements and
6404 /// give the ability to access the object stored in the branches.
6405 ///
6406 /// To draw px using the file hsimple.root (generated by the
6407 /// hsimple.C tutorial), we need a file named hsimple.cxx:
6408 /// ~~~ {.cpp}
6409 /// double hsimple() {
6410 /// return px;
6411 /// }
6412 /// ~~~
6413 /// MakeProxy can then be used indirectly via the TTree::Draw interface
6414 /// as follow:
6415 /// ~~~ {.cpp}
6416 /// new TFile("hsimple.root")
6417 /// ntuple->Draw("hsimple.cxx");
6418 /// ~~~
6419 /// A more complete example is available in the tutorials directory:
6420 /// h1analysisProxy.cxx , h1analysProxy.h and h1analysisProxyCut.C
6421 /// which reimplement the selector found in h1analysis.C
6422 
6423 Int_t TTree::MakeProxy(const char* proxyClassname, const char* macrofilename, const char* cutfilename, const char* option, Int_t maxUnrolling)
6425  GetPlayer();
6426  if (!fPlayer) return 0;
6427  return fPlayer->MakeProxy(proxyClassname,macrofilename,cutfilename,option,maxUnrolling);
6428 }
6429 
6430 ////////////////////////////////////////////////////////////////////////////////
6431 /// Generate skeleton selector class for this tree.
6432 ///
6433 /// The following files are produced: selector.h and selector.C.
6434 /// If selector is 0, the selector will be called "nameoftree".
6435 /// The option can be used to specify the branches that will have a data member.
6436 /// - If option is "=legacy", a pre-ROOT6 selector will be generated (data
6437 /// members and branch pointers instead of TTreeReaders).
6438 /// - If option is empty, readers will be generated for each leaf.
6439 /// - If option is "@", readers will be generated for the topmost branches.
6440 /// - Individual branches can also be picked by their name:
6441 /// - "X" generates readers for leaves of X.
6442 /// - "@X" generates a reader for X as a whole.
6443 /// - "@X;Y" generates a reader for X as a whole and also readers for the
6444 /// leaves of Y.
6445 /// - For further examples see the figure below.
6446 ///
6447 /// \image html ttree_makeselector_option_examples.png
6448 ///
6449 /// The generated code in selector.h includes the following:
6450 /// - Identification of the original Tree and Input file name
6451 /// - Definition of selector class (data and functions)
6452 /// - The following class functions:
6453 /// - constructor and destructor
6454 /// - void Begin(TTree *tree)
6455 /// - void SlaveBegin(TTree *tree)
6456 /// - void Init(TTree *tree)
6457 /// - Bool_t Notify()
6458 /// - Bool_t Process(Long64_t entry)
6459 /// - void Terminate()
6460 /// - void SlaveTerminate()
6461 ///
6462 /// The class selector derives from TSelector.
6463 /// The generated code in selector.C includes empty functions defined above.
6464 ///
6465 /// To use this function:
6466 ///
6467 /// - connect your Tree file (eg: `TFile f("myfile.root");`)
6468 /// - `T->MakeSelector("myselect");`
6469 ///
6470 /// where T is the name of the Tree in file myfile.root
6471 /// and myselect.h, myselect.C the name of the files created by this function.
6472 /// In a ROOT session, you can do:
6473 /// ~~~ {.cpp}
6474 /// root > T->Process("myselect.C")
6475 /// ~~~
6476 
6477 Int_t TTree::MakeSelector(const char* selector, Option_t* option)
6479  TString opt(option);
6480  if(opt.EqualTo("=legacy", TString::ECaseCompare::kIgnoreCase)) {
6481  return MakeClass(selector, "selector");
6482  } else {
6483  GetPlayer();
6484  if (!fPlayer) return 0;
6485  return fPlayer->MakeReader(selector, option);
6486  }
6487 }
6488 
6489 ////////////////////////////////////////////////////////////////////////////////
6490 /// Check if adding nbytes to memory we are still below MaxVirtualsize.
6491 
6494  if ((fTotalBuffers + nbytes) < fMaxVirtualSize) {
6495  return kFALSE;
6496  }
6497  return kTRUE;
6498 }
6499 
6500 ////////////////////////////////////////////////////////////////////////////////
6501 /// Static function merging the trees in the TList into a new tree.
6502 ///
6503 /// Trees in the list can be memory or disk-resident trees.
6504 /// The new tree is created in the current directory (memory if gROOT).
6505 
6506 TTree* TTree::MergeTrees(TList* li, Option_t* options)
6508  if (!li) return 0;
6509  TIter next(li);
6510  TTree *newtree = 0;
6511  TObject *obj;
6512 
6513  while ((obj=next())) {
6514  if (!obj->InheritsFrom(TTree::Class())) continue;
6515  TTree *tree = (TTree*)obj;
6516  Long64_t nentries = tree->GetEntries();
6517  if (nentries == 0) continue;
6518  if (!newtree) {
6519  newtree = (TTree*)tree->CloneTree();
6520  if (!newtree) continue;
6521 
6522  // Once the cloning is done, separate the trees,
6523  // to avoid as many side-effects as possible
6524  // The list of clones is guaranteed to exist since we
6525  // just cloned the tree.
6526  tree->GetListOfClones()->Remove(newtree);
6527  tree->ResetBranchAddresses();
6528  newtree->ResetBranchAddresses();
6529  continue;
6530  }
6531 
6532  newtree->CopyAddresses(tree);
6533 
6534  newtree->CopyEntries(tree,-1,options);
6535 
6536  tree->ResetBranchAddresses(); // Disconnect from new tree.
6537  }
6538  if (newtree && newtree->GetTreeIndex()) {
6539  newtree->GetTreeIndex()->Append(0,kFALSE); // Force the sorting
6540  }
6541  return newtree;
6542 }
6543 
6544 ////////////////////////////////////////////////////////////////////////////////
6545 /// Merge the trees in the TList into this tree.
6546 ///
6547 /// Returns the total number of entries in the merged tree.
6548 
6551  if (!li) return 0;
6552  Long64_t storeAutoSave = fAutoSave;
6553  // Disable the autosave as the TFileMerge keeps a list of key and deleting the underlying
6554  // key would invalidate its iteration (or require costly measure to not use the deleted keys).
6555  // Also since this is part of a merging operation, the output file is not as precious as in
6556  // the general case since the input file should still be around.
6557  fAutoSave = 0;
6558  TIter next(li);
6559  TTree *tree;
6560  while ((tree = (TTree*)next())) {
6561  if (tree==this) continue;
6562  if (!tree->InheritsFrom(TTree::Class())) {
6563  Error("Add","Attempt to add object of class: %s to a %s", tree->ClassName(), ClassName());
6564  fAutoSave = storeAutoSave;
6565  return -1;
6566  }
6567 
6568  Long64_t nentries = tree->GetEntries();
6569  if (nentries == 0) continue;
6570 
6571  CopyAddresses(tree);
6572 
6573  CopyEntries(tree,-1,options);
6574 
6575  tree->ResetBranchAddresses();
6576  }
6577  fAutoSave = storeAutoSave;
6578  return GetEntries();
6579 }
6580 
6581 ////////////////////////////////////////////////////////////////////////////////
6582 /// Merge the trees in the TList into this tree.
6583 /// If info->fIsFirst is true, first we clone this TTree info the directory
6584 /// info->fOutputDirectory and then overlay the new TTree information onto
6585 /// this TTree object (so that this TTree object is now the appropriate to
6586 /// use for further merging).
6587 ///
6588 /// Returns the total number of entries in the merged tree.
6589 
6592  const char *options = info ? info->fOptions.Data() : "";
6593  if (info && info->fIsFirst && info->fOutputDirectory && info->fOutputDirectory->GetFile() != GetCurrentFile()) {
6595  TTree *newtree = CloneTree(-1, options);
6596  if (newtree) {
6597  newtree->Write();
6598  delete newtree;
6599  }
6600  // Make sure things are really written out to disk before attempting any reading.
6601  info->fOutputDirectory->GetFile()->Flush();
6602  info->fOutputDirectory->ReadTObject(this,this->GetName());
6603  }
6604  if (!li) return 0;
6605  Long64_t storeAutoSave = fAutoSave;
6606  // Disable the autosave as the TFileMerge keeps a list of key and deleting the underlying
6607  // key would invalidate its iteration (or require costly measure to not use the deleted keys).
6608  // Also since this is part of a merging operation, the output file is not as precious as in
6609  // the general case since the input file should still be around.
6610  fAutoSave = 0;
6611  TIter next(li);
6612  TTree *tree;
6613  while ((tree = (TTree*)next())) {
6614  if (tree==this) continue;
6615  if (!tree->InheritsFrom(TTree::Class())) {
6616  Error("Add","Attempt to add object of class: %s to a %s", tree->ClassName(), ClassName());
6617  fAutoSave = storeAutoSave;
6618  return -1;
6619  }
6620  // Copy MakeClass status.
6621  tree->SetMakeClass(fMakeClass);
6622 
6623  // Copy branch addresses.
6624  CopyAddresses(tree);
6625 
6626  CopyEntries(tree,-1,options);
6627 
6628  tree->ResetBranchAddresses();
6629  }
6630  fAutoSave = storeAutoSave;
6631  return GetEntries();
6632 }
6633 
6634 ////////////////////////////////////////////////////////////////////////////////
6635 /// Move a cache from a file to the current file in dir.
6636 /// if src is null no operation is done, if dir is null or there is no
6637 /// current file the cache is deleted.
6638 
6639 void TTree::MoveReadCache(TFile *src, TDirectory *dir)
6641  if (!src) return;
6642  TFile *dst = (dir && dir != gROOT) ? dir->GetFile() : 0;
6643  if (src == dst) return;
6644 
6645  TTreeCache *pf = GetReadCache(src);
6646  if (dst) {
6647  src->SetCacheRead(0,this);
6648  dst->SetCacheRead(pf, this);
6649  } else {
6650  if (pf) {
6651  pf->WaitFinishPrefetch();
6652  }
6653  src->SetCacheRead(0,this);
6654  delete pf;
6655  }
6656 }
6657 
6658 ////////////////////////////////////////////////////////////////////////////////
6659 /// Function called when loading a new class library.
6660 
6663  TIter next(GetListOfLeaves());
6664  TLeaf* leaf = 0;
6665  while ((leaf = (TLeaf*) next())) {
6666  leaf->Notify();
6667  leaf->GetBranch()->Notify();
6668  }
6669  return kTRUE;
6670 }
6671 
6672 ////////////////////////////////////////////////////////////////////////////////
6673 /// This function may be called after having filled some entries in a Tree.
6674 /// Using the information in the existing branch buffers, it will reassign
6675 /// new branch buffer sizes to optimize time and memory.
6676 ///
6677 /// The function computes the best values for branch buffer sizes such that
6678 /// the total buffer sizes is less than maxMemory and nearby entries written
6679 /// at the same time.
6680 /// In case the branch compression factor for the data written so far is less
6681 /// than compMin, the compression is disabled.
6682 ///
6683 /// if option ="d" an analysis report is printed.
6684 
6685 void TTree::OptimizeBaskets(ULong64_t maxMemory, Float_t minComp, Option_t *option)
6687  //Flush existing baskets if the file is writable
6688  if (this->GetDirectory()->IsWritable()) this->FlushBaskets();
6689 
6690  TString opt( option );
6691  opt.ToLower();
6692  Bool_t pDebug = opt.Contains("d");
6693  TObjArray *leaves = this->GetListOfLeaves();
6694  Int_t nleaves = leaves->GetEntries();
6695  Double_t treeSize = (Double_t)this->GetTotBytes();
6696 
6697  if (nleaves == 0 || treeSize == 0) {
6698  // We're being called too early, we really have nothing to do ...
6699  return;
6700  }
6701  Double_t aveSize = treeSize/nleaves;
6702  UInt_t bmin = 512;
6703  UInt_t bmax = 256000;
6704  Double_t memFactor = 1;
6705  Int_t i, oldMemsize,newMemsize,oldBaskets,newBaskets;
6706  i = oldMemsize = newMemsize = oldBaskets = newBaskets = 0;
6707 
6708  //we make two passes
6709  //one pass to compute the relative branch buffer sizes
6710  //a second pass to compute the absolute values
6711  for (Int_t pass =0;pass<2;pass++) {
6712  oldMemsize = 0; //to count size of baskets in memory with old buffer size
6713  newMemsize = 0; //to count size of baskets in memory with new buffer size
6714  oldBaskets = 0; //to count number of baskets with old buffer size
6715  newBaskets = 0; //to count number of baskets with new buffer size
6716  for (i=0;i<nleaves;i++) {
6717  TLeaf *leaf = (TLeaf*)leaves->At(i);
6718  TBranch *branch = leaf->GetBranch();
6719  Double_t totBytes = (Double_t)branch->GetTotBytes();
6720  Double_t idealFactor = totBytes/aveSize;
6721  UInt_t sizeOfOneEntry;
6722  if (branch->GetEntries() == 0) {
6723  // There is no data, so let's make a guess ...
6724  sizeOfOneEntry = aveSize;
6725  } else {
6726  sizeOfOneEntry = 1+(UInt_t)(totBytes / (Double_t)branch->GetEntries());
6727  }
6728  Int_t oldBsize = branch->GetBasketSize();
6729  oldMemsize += oldBsize;
6730  oldBaskets += 1+Int_t(totBytes/oldBsize);
6731  Int_t nb = branch->GetListOfBranches()->GetEntries();
6732  if (nb > 0) {
6733  newBaskets += 1+Int_t(totBytes/oldBsize);
6734  continue;
6735  }
6736  Double_t bsize = oldBsize*idealFactor*memFactor; //bsize can be very large !
6737  if (bsize < 0) bsize = bmax;
6738  if (bsize > bmax) bsize = bmax;
6739  UInt_t newBsize = UInt_t(bsize);
6740  if (pass) { // only on the second pass so that it doesn't interfere with scaling
6741  newBsize = newBsize + (branch->GetEntries() * sizeof(Int_t) * 2); // make room for meta data
6742  // We used ATLAS fully-split xAOD for testing, which is a rather unbalanced TTree, 10K branches,
6743  // with 8K having baskets smaller than 512 bytes. To achieve good I/O performance ATLAS uses auto-flush 100,
6744  // resulting in the smallest baskets being ~300-400 bytes, so this change increases their memory by about 8k*150B =~ 1MB,
6745  // at the same time it significantly reduces the number of total baskets because it ensures that all 100 entries can be
6746  // stored in a single basket (the old optimization tended to make baskets too small). In a toy example with fixed sized
6747  // structures we found a factor of 2 fewer baskets needed in the new scheme.
6748  // rounds up, increases basket size to ensure all entries fit into single basket as intended
6749  newBsize = newBsize - newBsize%512 + 512;
6750  }
6751  if (newBsize < sizeOfOneEntry) newBsize = sizeOfOneEntry;
6752  if (newBsize < bmin) newBsize = bmin;
6753  if (newBsize > 10000000) newBsize = bmax;
6754  if (pass) {
6755  if (pDebug) Info("OptimizeBaskets", "Changing buffer size from %6d to %6d bytes for %s\n",oldBsize,newBsize,branch->GetName());
6756  branch->SetBasketSize(newBsize);
6757  }
6758  newMemsize += newBsize;
6759  // For this number to be somewhat accurate when newBsize is 'low'
6760  // we do not include any space for meta data in the requested size (newBsize) even-though SetBasketSize will
6761  // not let it be lower than 100+TBranch::fEntryOffsetLen.
6762  newBaskets += 1+Int_t(totBytes/newBsize);
6763  if (pass == 0) continue;
6764  //Reset the compression level in case the compression factor is small
6765  Double_t comp = 1;
6766  if (branch->GetZipBytes() > 0) comp = totBytes/Double_t(branch->GetZipBytes());
6767  if (comp > 1 && comp < minComp) {
6768  if (pDebug) Info("OptimizeBaskets", "Disabling compression for branch : %s\n",branch->GetName());
6769  branch->SetCompressionSettings(0);
6770  }
6771  }
6772  // coverity[divide_by_zero] newMemsize can not be zero as there is at least one leaf
6773  memFactor = Double_t(maxMemory)/Double_t(newMemsize);
6774  if (memFactor > 100) memFactor = 100;
6775  Double_t bmin_new = bmin*memFactor;
6776  Double_t bmax_new = bmax*memFactor;
6777  static const UInt_t hardmax = 1*1024*1024*1024; // Really, really never give more than 1Gb to a single buffer.
6778 
6779  // Really, really never go lower than 8 bytes (we use this number
6780  // so that the calculation of the number of basket is consistent
6781  // but in fact SetBasketSize will not let the size go below
6782  // TBranch::fEntryOffsetLen + (100 + strlen(branch->GetName())
6783  // (The 2nd part being a slight over estimate of the key length.
6784  static const UInt_t hardmin = 8;
6785  bmin = (bmin_new > hardmax) ? hardmax : ( bmin_new < hardmin ? hardmin : (UInt_t)bmin_new );
6786  bmax = (bmax_new > hardmax) ? bmin : (UInt_t)bmax_new;
6787  }
6788  if (pDebug) {
6789  Info("OptimizeBaskets", "oldMemsize = %d, newMemsize = %d\n",oldMemsize, newMemsize);
6790  Info("OptimizeBaskets", "oldBaskets = %d, newBaskets = %d\n",oldBaskets, newBaskets);
6791  }
6792 }
6793 
6794 ////////////////////////////////////////////////////////////////////////////////
6795 /// Interface to the Principal Components Analysis class.
6796 ///
6797 /// Create an instance of TPrincipal
6798 ///
6799 /// Fill it with the selected variables
6800 ///
6801 /// - if option "n" is specified, the TPrincipal object is filled with
6802 /// normalized variables.
6803 /// - If option "p" is specified, compute the principal components
6804 /// - If option "p" and "d" print results of analysis
6805 /// - If option "p" and "h" generate standard histograms
6806 /// - If option "p" and "c" generate code of conversion functions
6807 /// - return a pointer to the TPrincipal object. It is the user responsibility
6808 /// - to delete this object.
6809 /// - The option default value is "np"
6810 ///
6811 /// see TTree::Draw for explanation of the other parameters.
6812 ///
6813 /// The created object is named "principal" and a reference to it
6814 /// is added to the list of specials Root objects.
6815 /// you can retrieve a pointer to the created object via:
6816 /// ~~~ {.cpp}
6817 /// TPrincipal *principal =
6818 /// (TPrincipal*)gROOT->GetListOfSpecials()->FindObject("principal");
6819 /// ~~~
6820 
6821 TPrincipal* TTree::Principal(const char* varexp, const char* selection, Option_t* option, Long64_t nentries, Long64_t firstentry)
6823  GetPlayer();
6824  if (fPlayer) {
6825  return fPlayer->Principal(varexp, selection, option, nentries, firstentry);
6826  }
6827  return 0;
6828 }
6829 
6830 ////////////////////////////////////////////////////////////////////////////////
6831 /// Print a summary of the tree contents.
6832 ///
6833 /// - If option contains "all" friend trees are also printed.
6834 /// - If option contains "toponly" only the top level branches are printed.
6835 /// - If option contains "clusters" information about the cluster of baskets is printed.
6836 ///
6837 /// Wildcarding can be used to print only a subset of the branches, e.g.,
6838 /// `T.Print("Elec*")` will print all branches with name starting with "Elec".
6839 
6840 void TTree::Print(Option_t* option) const
6842  // We already have been visited while recursively looking
6843  // through the friends tree, let's return.
6844  if (kPrint & fFriendLockStatus) {
6845  return;
6846  }
6847  Int_t s = 0;
6848  Int_t skey = 0;
6849  if (fDirectory) {
6850  TKey* key = fDirectory->GetKey(GetName());
6851  if (key) {
6852  skey = key->GetKeylen();
6853  s = key->GetNbytes();
6854  }
6855  }
6856  Long64_t total = skey;
6857  Long64_t zipBytes = GetZipBytes();
6858  if (zipBytes > 0) {
6859  total += GetTotBytes();
6860  }
6861  TBufferFile b(TBuffer::kWrite, 10000);
6862  TTree::Class()->WriteBuffer(b, (TTree*) this);
6863  total += b.Length();
6864  Long64_t file = zipBytes + s;
6865  Float_t cx = 1;
6866  if (zipBytes) {
6867  cx = (GetTotBytes() + 0.00001) / zipBytes;
6868  }
6869  Printf("******************************************************************************");
6870  Printf("*Tree :%-10s: %-54s *", GetName(), GetTitle());
6871  Printf("*Entries : %8lld : Total = %15lld bytes File Size = %10lld *", fEntries, total, file);
6872  Printf("* : : Tree compression factor = %6.2f *", cx);
6873  Printf("******************************************************************************");
6874 
6875  if (strncmp(option,"clusters",strlen("clusters"))==0) {
6876  Printf("%-16s %-16s %-16s %5s",
6877  "Cluster Range #", "Entry Start", "Last Entry", "Size");
6878  Int_t index= 0;
6879  Long64_t clusterRangeStart = 0;
6880  if (fNClusterRange) {
6881  for( ; index < fNClusterRange; ++index) {
6882  Printf("%-16d %-16lld %-16lld %5lld",
6883  index, clusterRangeStart, fClusterRangeEnd[index], fClusterSize[index]);
6884  clusterRangeStart = fClusterRangeEnd[index] + 1;
6885  }
6886  }
6887  Printf("%-16d %-16lld %-16lld %5lld",
6888  index, clusterRangeStart, fEntries - 1, fAutoFlush);
6889  return;
6890  }
6891 
6892  Int_t nl = const_cast<TTree*>(this)->GetListOfLeaves()->GetEntries();
6893  Int_t l;
6894  TBranch* br = 0;
6895  TLeaf* leaf = 0;
6896  if (strstr(option, "toponly")) {
6897  Long64_t *count = new Long64_t[nl];
6898  Int_t keep =0;
6899  for (l=0;l<nl;l++) {
6900  leaf = (TLeaf *)const_cast<TTree*>(this)->GetListOfLeaves()->At(l);
6901  br = leaf->GetBranch();
6902  if (strchr(br->GetName(),'.')) {
6903  count[l] = -1;
6904  count[keep] += br->GetZipBytes();
6905  } else {
6906  keep = l;
6907  count[keep] = br->GetZipBytes();
6908  }
6909  }
6910  for (l=0;l<nl;l++) {
6911  if (count[l] < 0) continue;
6912  leaf = (TLeaf *)const_cast<TTree*>(this)->GetListOfLeaves()->At(l);
6913  br = leaf->GetBranch();
6914  Printf("branch: %-20s %9lld\n",br->GetName(),count[l]);
6915  }
6916  delete [] count;
6917  } else {
6918  TString reg = "*";
6919  if (strlen(option) && strchr(option,'*')) reg = option;
6920  TRegexp re(reg,kTRUE);
6921  TIter next(const_cast<TTree*>(this)->GetListOfBranches());
6923  while ((br= (TBranch*)next())) {
6924  TString st = br->GetName();
6925  st.ReplaceAll("/","_");
6926  if (st.Index(re) == kNPOS) continue;
6927  br->Print(option);
6928  }
6929  }
6930 
6931  //print TRefTable (if one)
6932  if (fBranchRef) fBranchRef->Print(option);
6933 
6934  //print friends if option "all"
6935  if (!fFriends || !strstr(option,"all")) return;
6936  TIter nextf(fFriends);
6937  TFriendLock lock(const_cast<TTree*>(this),kPrint);
6938  TFriendElement *fr;
6939  while ((fr = (TFriendElement*)nextf())) {
6940  TTree * t = fr->GetTree();
6941  if (t) t->Print(option);
6942  }
6943 }
6944 
6945 ////////////////////////////////////////////////////////////////////////////////
6946 /// Print statistics about the TreeCache for this tree.
6947 /// Like:
6948 /// ~~~ {.cpp}
6949 /// ******TreeCache statistics for file: cms2.root ******
6950 /// Reading 73921562 bytes in 716 transactions
6951 /// Average transaction = 103.242405 Kbytes
6952 /// Number of blocks in current cache: 202, total size : 6001193
6953 /// ~~~
6954 /// if option = "a" the list of blocks in the cache is printed
6955 
6956 void TTree::PrintCacheStats(Option_t* option) const
6958  TFile *f = GetCurrentFile();
6959  if (!f) return;
6960  TTreeCache *tc = (TTreeCache*)f->GetCacheRead(const_cast<TTree*>(this));
6961  if (tc) tc->Print(option);
6962 }
6963 
6964 ////////////////////////////////////////////////////////////////////////////////
6965 /// Process this tree executing the TSelector code in the specified filename.
6966 /// The return value is -1 in case of error and TSelector::GetStatus() in
6967 /// in case of success.
6968 ///
6969 /// The code in filename is loaded (interpreted or compiled, see below),
6970 /// filename must contain a valid class implementation derived from TSelector,
6971 /// where TSelector has the following member functions:
6972 ///
6973 /// - `Begin()`: called every time a loop on the tree starts,
6974 /// a convenient place to create your histograms.
6975 /// - `SlaveBegin()`: called after Begin(), when on PROOF called only on the
6976 /// slave servers.
6977 /// - `Process()`: called for each event, in this function you decide what
6978 /// to read and fill your histograms.
6979 /// - `SlaveTerminate`: called at the end of the loop on the tree, when on PROOF
6980 /// called only on the slave servers.
6981 /// - `Terminate()`: called at the end of the loop on the tree,
6982 /// a convenient place to draw/fit your histograms.
6983 ///
6984 /// If filename is of the form file.C, the file will be interpreted.
6985 ///
6986 /// If filename is of the form file.C++, the file file.C will be compiled
6987 /// and dynamically loaded.
6988 ///
6989 /// If filename is of the form file.C+, the file file.C will be compiled
6990 /// and dynamically loaded. At next call, if file.C is older than file.o
6991 /// and file.so, the file.C is not compiled, only file.so is loaded.
6992 ///
6993 /// ## NOTE1
6994 ///
6995 /// It may be more interesting to invoke directly the other Process function
6996 /// accepting a TSelector* as argument.eg
6997 /// ~~~ {.cpp}
6998 /// MySelector *selector = (MySelector*)TSelector::GetSelector(filename);
6999 /// selector->CallSomeFunction(..);
7000 /// mytree.Process(selector,..);
7001 /// ~~~
7002 /// ## NOTE2
7003 //
7004 /// One should not call this function twice with the same selector file
7005 /// in the same script. If this is required, proceed as indicated in NOTE1,
7006 /// by getting a pointer to the corresponding TSelector,eg
7007 ///
7008 /// ### workaround 1
7009 /// ~~~ {.cpp}
7010 /// void stubs1() {
7011 /// TSelector *selector = TSelector::GetSelector("h1test.C");
7012 /// TFile *f1 = new TFile("stubs_nood_le1.root");
7013 /// TTree *h1 = (TTree*)f1->Get("h1");
7014 /// h1->Process(selector);
7015 /// TFile *f2 = new TFile("stubs_nood_le1_coarse.root");
7016 /// TTree *h2 = (TTree*)f2->Get("h1");
7017 /// h2->Process(selector);
7018 /// }
7019 /// ~~~
7020 /// or use ACLIC to compile the selector
7021 ///
7022 /// ### workaround 2
7023 /// ~~~ {.cpp}
7024 /// void stubs2() {
7025 /// TFile *f1 = new TFile("stubs_nood_le1.root");
7026 /// TTree *h1 = (TTree*)f1->Get("h1");
7027 /// h1->Process("h1test.C+");
7028 /// TFile *f2 = new TFile("stubs_nood_le1_coarse.root");
7029 /// TTree *h2 = (TTree*)f2->Get("h1");
7030 /// h2->Process("h1test.C+");
7031 /// }
7032 /// ~~~
7033 
7034 Long64_t TTree::Process(const char* filename, Option_t* option, Long64_t nentries, Long64_t firstentry)
7036  GetPlayer();
7037  if (fPlayer) {
7038  return fPlayer->Process(filename, option, nentries, firstentry);
7039  }
7040  return -1;
7041 }
7042 
7043 ////////////////////////////////////////////////////////////////////////////////
7044 /// Process this tree executing the code in the specified selector.
7045 /// The return value is -1 in case of error and TSelector::GetStatus() in
7046 /// in case of success.
7047 ///
7048 /// The TSelector class has the following member functions:
7049 ///
7050 /// - `Begin()`: called every time a loop on the tree starts,
7051 /// a convenient place to create your histograms.
7052 /// - `SlaveBegin()`: called after Begin(), when on PROOF called only on the
7053 /// slave servers.
7054 /// - `Process()`: called for each event, in this function you decide what
7055 /// to read and fill your histograms.
7056 /// - `SlaveTerminate`: called at the end of the loop on the tree, when on PROOF
7057 /// called only on the slave servers.
7058 /// - `Terminate()`: called at the end of the loop on the tree,
7059 /// a convenient place to draw/fit your histograms.
7060 ///
7061 /// If the Tree (Chain) has an associated EventList, the loop is on the nentries
7062 /// of the EventList, starting at firstentry, otherwise the loop is on the
7063 /// specified Tree entries.
7064 
7065 Long64_t TTree::Process(TSelector* selector, Option_t* option, Long64_t nentries, Long64_t firstentry)
7067  GetPlayer();
7068  if (fPlayer) {
7069  return fPlayer->Process(selector, option, nentries, firstentry);
7070  }
7071  return -1;
7072 }
7073 
7074 ////////////////////////////////////////////////////////////////////////////////
7075 /// Make a projection of a tree using selections.
7076 ///
7077 /// Depending on the value of varexp (described in Draw) a 1-D, 2-D, etc.,
7078 /// projection of the tree will be filled in histogram hname.
7079 /// Note that the dimension of hname must match with the dimension of varexp.
7080 ///
7081 
7082 Long64_t TTree::Project(const char* hname, const char* varexp, const char* selection, Option_t* option, Long64_t nentries, Long64_t firstentry)
7084  TString var;
7085  var.Form("%s>>%s", varexp, hname);
7086  TString opt("goff");
7087  if (option) {
7088  opt.Form("%sgoff", option);
7089  }
7090  Long64_t nsel = Draw(var, selection, opt, nentries, firstentry);
7091  return nsel;
7092 }
7093 
7094 ////////////////////////////////////////////////////////////////////////////////
7095 /// Loop over entries and return a TSQLResult object containing entries following selection.
7096 
7097 TSQLResult* TTree::Query(const char* varexp, const char* selection, Option_t* option, Long64_t nentries, Long64_t firstentry)
7099  GetPlayer();
7100  if (fPlayer) {
7101  return fPlayer->Query(varexp, selection, option, nentries, firstentry);
7102  }
7103  return 0;
7104 }
7105 
7106 ////////////////////////////////////////////////////////////////////////////////
7107 /// Create or simply read branches from filename.
7108 ///
7109 /// if branchDescriptor = "" (default), it is assumed that the Tree descriptor
7110 /// is given in the first line of the file with a syntax like
7111 /// ~~~ {.cpp}
7112 /// A/D:Table[2]/F:Ntracks/I:astring/C
7113 /// ~~~
7114 /// otherwise branchDescriptor must be specified with the above syntax.
7115 ///
7116 /// - If the type of the first variable is not specified, it is assumed to be "/F"
7117 /// - If the type of any other variable is not specified, the type of the previous
7118 /// variable is assumed. eg
7119 /// - `x:y:z` (all variables are assumed of type "F"
7120 /// - `x/D:y:z` (all variables are of type "D"
7121 /// - `x:y/D:z` (x is type "F", y and z of type "D"
7122 ///
7123 /// delimiter allows for the use of another delimiter besides whitespace.
7124 /// This provides support for direct import of common data file formats
7125 /// like csv. If delimiter != ' ' and branchDescriptor == "", then the
7126 /// branch description is taken from the first line in the file, but
7127 /// delimiter is used for the branch names tokenization rather than ':'.
7128 /// Note however that if the values in the first line do not use the
7129 /// /[type] syntax, all variables are assumed to be of type "F".
7130 /// If the filename ends with extensions .csv or .CSV and a delimiter is
7131 /// not specified (besides ' '), the delimiter is automatically set to ','.
7132 ///
7133 /// Lines in the input file starting with "#" are ignored. Leading whitespace
7134 /// for each column data is skipped. Empty lines are skipped.
7135 ///
7136 /// A TBranch object is created for each variable in the expression.
7137 /// The total number of rows read from the file is returned.
7138 ///
7139 /// ## FILLING a TTree WITH MULTIPLE INPUT TEXT FILES
7140 ///
7141 /// To fill a TTree with multiple input text files, proceed as indicated above
7142 /// for the first input file and omit the second argument for subsequent calls
7143 /// ~~~ {.cpp}
7144 /// T.ReadFile("file1.dat","branch descriptor");
7145 /// T.ReadFile("file2.dat");
7146 /// ~~~
7147 
7148 Long64_t TTree::ReadFile(const char* filename, const char* branchDescriptor, char delimiter)
7150  std::ifstream in;
7151  in.open(filename);
7152  if (!in.good()) {
7153  Error("ReadFile","Cannot open file: %s",filename);
7154  return 0;
7155  }
7156  const char* ext = strrchr(filename, '.');
7157  if(ext != NULL && ((strcmp(ext, ".csv") == 0) || (strcmp(ext, ".CSV") == 0)) && delimiter == ' ') {
7158  delimiter = ',';
7159  }
7160  return ReadStream(in, branchDescriptor, delimiter);
7161 }
7162 
7163 ////////////////////////////////////////////////////////////////////////////////
7164 /// Determine which newline this file is using.
7165 /// Return '\\r' for Windows '\\r\\n' as that already terminates.
7166 
7167 char TTree::GetNewlineValue(std::istream &inputStream)
7169  Long_t inPos = inputStream.tellg();
7170  char newline = '\n';
7171  while(1) {
7172  char c = 0;
7173  inputStream.get(c);
7174  if(!inputStream.good()) {
7175  Error("ReadStream","Error reading stream: no newline found.");
7176  return 0;
7177  }
7178  if(c == newline) break;
7179  if(c == '\r') {
7180  newline = '\r';
7181  break;
7182  }
7183  }
7184  inputStream.clear();
7185  inputStream.seekg(inPos);
7186  return newline;
7187 }
7188 
7189 ////////////////////////////////////////////////////////////////////////////////
7190 /// Create or simply read branches from an input stream.
7191 ///
7192 /// See reference information for TTree::ReadFile
7193 
7194 Long64_t TTree::ReadStream(std::istream& inputStream, const char *branchDescriptor, char delimiter)
7196  char newline = 0;
7197  std::stringstream ss;
7198  std::istream *inTemp;
7199  Long_t inPos = inputStream.tellg();
7200  if (!inputStream.good()) {
7201  Error("ReadStream","Error reading stream");
7202  return 0;
7203  }
7204  if (inPos == -1) {
7205  ss << std::cin.rdbuf();
7206  newline = GetNewlineValue(ss);
7207  inTemp = &ss;
7208  } else {
7209  newline = GetNewlineValue(inputStream);
7210  inTemp = &inputStream;
7211  }
7212  std::istream& in = *inTemp;
7213  Long64_t nlines = 0;
7214 
7215  TBranch *branch = 0;
7216  Int_t nbranches = fBranches.GetEntries();
7217  if (nbranches == 0) {
7218  char *bdname = new char[4000];
7219  char *bd = new char[100000];
7220  Int_t nch = 0;
7221  if (branchDescriptor) nch = strlen(branchDescriptor);
7222  // branch Descriptor is null, read its definition from the first line in the file
7223  if (!nch) {
7224  do {
7225  in.getline(bd, 100000, newline);
7226  if (!in.good()) {
7227  delete [] bdname;
7228  delete [] bd;
7229  Error("ReadStream","Error reading stream");
7230  return 0;
7231  }
7232  char *cursor = bd;
7233  while( isspace(*cursor) && *cursor != '\n' && *cursor != '\0') {
7234  ++cursor;
7235  }
7236  if (*cursor != '#' && *cursor != '\n' && *cursor != '\0') {
7237  break;
7238  }
7239  } while (true);
7240  ++nlines;
7241  nch = strlen(bd);
7242  } else {
7243  strlcpy(bd,branchDescriptor,100000);
7244  }
7245 
7246  //parse the branch descriptor and create a branch for each element
7247  //separated by ":"
7248  void *address = &bd[90000];
7249  char *bdcur = bd;
7250  TString desc="", olddesc="F";
7251  char bdelim = ':';
7252  if(delimiter != ' ') {
7253  bdelim = delimiter;
7254  if (strchr(bdcur,bdelim)==0 && strchr(bdcur,':') != 0) {
7255  // revert to the default
7256  bdelim = ':';
7257  }
7258  }
7259  while (bdcur) {
7260  char *colon = strchr(bdcur,bdelim);
7261  if (colon) *colon = 0;
7262  strlcpy(bdname,bdcur,4000);
7263  char *slash = strchr(bdname,'/');
7264  if (slash) {
7265  *slash = 0;
7266  desc = bdcur;
7267  olddesc = slash+1;
7268  } else {
7269  desc.Form("%s/%s",bdname,olddesc.Data());
7270  }
7271  char *bracket = strchr(bdname,'[');
7272  if (bracket) {
7273  *bracket = 0;
7274  }
7275  branch = new TBranch(this,bdname,address,desc.Data(),32000);
7276  if (branch->IsZombie()) {
7277  delete branch;
7278  Warning("ReadStream","Illegal branch definition: %s",bdcur);
7279  } else {
7280  fBranches.Add(branch);
7281  branch->SetAddress(0);
7282  }
7283  if (!colon)break;
7284  bdcur = colon+1;
7285  }
7286  delete [] bdname;
7287  delete [] bd;
7288  }
7289 
7290  nbranches = fBranches.GetEntries();
7291 
7292  if (gDebug > 1) {
7293  Info("ReadStream", "Will use branches:");
7294  for (int i = 0 ; i < nbranches; ++i) {
7295  TBranch* br = (TBranch*) fBranches.At(i);
7296  Info("ReadStream", " %s: %s [%s]", br->GetName(),
7297  br->GetTitle(), br->GetListOfLeaves()->At(0)->IsA()->GetName());
7298  }
7299  if (gDebug > 3) {
7300  Info("ReadStream", "Dumping read tokens, format:");
7301  Info("ReadStream", "LLLLL:BBB:gfbe:GFBE:T");
7302  Info("ReadStream", " L: line number");
7303  Info("ReadStream", " B: branch number");
7304  Info("ReadStream", " gfbe: good / fail / bad / eof of token");
7305  Info("ReadStream", " GFBE: good / fail / bad / eof of file");
7306  Info("ReadStream", " T: Token being read");
7307  }
7308  }
7309 
7310  //loop on all lines in the file
7311  Long64_t nGoodLines = 0;
7312  std::string line;
7313  const char sDelimBuf[2] = { delimiter, 0 };
7314  const char* sDelim = sDelimBuf;
7315  if (delimiter == ' ') {
7316  // ' ' really means whitespace
7317  sDelim = "[ \t]";
7318  }
7319  while(in.good()) {
7320  if (newline == '\r' && in.peek() == '\n') {
7321  // Windows, skip '\n':
7322  in.get();
7323  }
7324  std::getline(in, line, newline);
7325  ++nlines;
7326 
7327  TString sLine(line);
7328  sLine = sLine.Strip(TString::kLeading); // skip leading whitespace
7329  if (sLine.IsNull()) {
7330  if (gDebug > 2) {
7331  Info("ReadStream", "Skipping empty line number %lld", nlines);
7332  }
7333  continue; // silently skip empty lines
7334  }
7335  if (sLine[0] == '#') {
7336  if (gDebug > 2) {
7337  Info("ReadStream", "Skipping comment line number %lld: '%s'",
7338  nlines, line.c_str());
7339  }
7340  continue;
7341  }
7342  if (gDebug > 2) {
7343  Info("ReadStream", "Parsing line number %lld: '%s'",
7344  nlines, line.c_str());
7345  }
7346 
7347  // Loop on branches and read the branch values into their buffer
7348  branch = 0;
7349  TString tok; // one column's data
7350  TString leafData; // leaf data, possibly multiple tokens for e.g. /I[2]
7351  std::stringstream sToken; // string stream feeding leafData into leaves
7352  Ssiz_t pos = 0;
7353  Int_t iBranch = 0;
7354  Bool_t goodLine = kTRUE; // whether the row can be filled into the tree
7355  Int_t remainingLeafLen = 0; // remaining columns for the current leaf
7356  while (goodLine && iBranch < nbranches
7357  && sLine.Tokenize(tok, pos, sDelim)) {
7358  tok = tok.Strip(TString::kLeading); // skip leading whitespace
7359  if (tok.IsNull() && delimiter == ' ') {
7360  // 1 2 should not be interpreted as 1,,,2 but 1, 2.
7361  // Thus continue until we have a non-empty token.
7362  continue;
7363  }
7364 
7365  if (!remainingLeafLen) {
7366  // next branch!
7367  branch = (TBranch*)fBranches.At(iBranch);
7368  }
7369  TLeaf *leaf = (TLeaf*)branch->GetListOfLeaves()->At(0);
7370  if (!remainingLeafLen) {
7371  remainingLeafLen = leaf->GetLen();
7372  if (leaf->GetMaximum() > 0) {
7373  // This is a dynamic leaf length, i.e. most likely a TLeafC's
7374  // string size. This still translates into one token:
7375  remainingLeafLen = 1;
7376  }
7377 
7378  leafData = tok;
7379  } else {
7380  // append token to laf data:
7381  leafData += " ";
7382  leafData += tok;
7383  }
7384  --remainingLeafLen;
7385  if (remainingLeafLen) {
7386  // need more columns for this branch:
7387  continue;
7388  }
7389  ++iBranch;
7390 
7391  // initialize stringstream with token
7392  sToken.clear();
7393  sToken.seekp(0, std::ios_base::beg);
7394  sToken.str(leafData.Data());
7395  sToken.seekg(0, std::ios_base::beg);
7396  leaf->ReadValue(sToken, 0 /* 0 = "all" */);
7397  if (gDebug > 3) {
7398  Info("ReadStream", "%5lld:%3d:%d%d%d%d:%d%d%d%d:%s",
7399  nlines, iBranch,
7400  (int)sToken.good(), (int)sToken.fail(),
7401  (int)sToken.bad(), (int)sToken.eof(),
7402  (int)in.good(), (int)in.fail(),
7403  (int)in.bad(), (int)in.eof(),
7404  sToken.str().c_str());
7405  }
7406 
7407  // Error handling
7408  if (sToken.bad()) {
7409  // How could that happen for a stringstream?
7410  Warning("ReadStream",
7411  "Buffer error while reading data for branch %s on line %lld",
7412  branch->GetName(), nlines);
7413  } else if (!sToken.eof()) {
7414  if (sToken.fail()) {
7415  Warning("ReadStream",
7416  "Couldn't read formatted data in \"%s\" for branch %s on line %lld; ignoring line",
7417  tok.Data(), branch->GetName(), nlines);
7418  goodLine = kFALSE;
7419  } else {
7420  std::string remainder;
7421  std::getline(sToken, remainder, newline);
7422  if (!remainder.empty()) {
7423  Warning("ReadStream",
7424  "Ignoring trailing \"%s\" while reading data for branch %s on line %lld",
7425  remainder.c_str(), branch->GetName(), nlines);
7426  }
7427  }
7428  }
7429  } // tokenizer loop
7430 
7431  if (iBranch < nbranches) {
7432  Warning("ReadStream",
7433  "Read too few columns (%d < %d) in line %lld; ignoring line",
7434  iBranch, nbranches, nlines);
7435  goodLine = kFALSE;
7436  } else if (pos != kNPOS) {
7437  sLine = sLine.Strip(TString::kTrailing);
7438  if (pos < sLine.Length()) {
7439  Warning("ReadStream",
7440  "Ignoring trailing \"%s\" while reading line %lld",
7441  sLine.Data() + pos - 1 /* also print delimiter */,
7442  nlines);
7443  }
7444  }
7445 
7446  //we are now ready to fill the tree
7447  if (goodLine) {
7448  Fill();
7449  ++nGoodLines;
7450  }
7451  }
7452 
7453  return nGoodLines;
7454 }
7455 
7456 ////////////////////////////////////////////////////////////////////////////////
7457 /// Make sure that obj (which is being deleted or will soon be) is no
7458 /// longer referenced by this TTree.
7459 
7462  if (obj == fEventList) {
7463  fEventList = 0;
7464  }
7465  if (obj == fEntryList) {
7466  fEntryList = 0;
7467  }
7468  if (fUserInfo) {
7469  fUserInfo->RecursiveRemove(obj);
7470  }
7471  if (fPlayer == obj) {
7472  fPlayer = 0;
7473  }
7474  if (fTreeIndex == obj) {
7475  fTreeIndex = 0;
7476  }
7477  if (fAliases) {
7478  fAliases->RecursiveRemove(obj);
7479  }
7480  if (fFriends) {
7481  fFriends->RecursiveRemove(obj);
7482  }
7483 }
7484 
7485 ////////////////////////////////////////////////////////////////////////////////
7486 /// Refresh contents of this tree and its branches from the current status on disk.
7487 ///
7488 /// One can call this function in case the tree file is being
7489 /// updated by another process.
7490 
7491 void TTree::Refresh()
7493  if (!fDirectory->GetFile()) {
7494  return;
7495  }
7496  fDirectory->ReadKeys();
7497  fDirectory->Remove(this);
7498  TTree* tree; fDirectory->GetObject(GetName(),tree);
7499  if (!tree) {
7500  return;
7501  }
7502  //copy info from tree header into this Tree
7503  fEntries = 0;
7504  fNClusterRange = 0;
7505  ImportClusterRanges(tree);
7506 
7507  fAutoSave = tree->fAutoSave;
7508  fEntries = tree->fEntries;
7509  fTotBytes = tree->GetTotBytes();
7510  fZipBytes = tree->GetZipBytes();
7511  fSavedBytes = tree->fSavedBytes;
7512  fTotalBuffers = tree->fTotalBuffers.load();
7513 
7514  //loop on all branches and update them
7515  Int_t nleaves = fLeaves.GetEntriesFast();
7516  for (Int_t i = 0; i < nleaves; i++) {
7517  TLeaf* leaf = (TLeaf*) fLeaves.UncheckedAt(i);
7518  TBranch* branch = (TBranch*) leaf->GetBranch();
7519  branch->Refresh(tree->GetBranch(branch->GetName()));
7520  }
7521  fDirectory->Remove(tree);
7522  fDirectory->Append(this);
7523  delete tree;
7524  tree = 0;
7525 }
7526 
7527 ////////////////////////////////////////////////////////////////////////////////
7528 /// Remove a friend from the list of friends.
7529 
7530 void TTree::RemoveFriend(TTree* oldFriend)
7532  // We already have been visited while recursively looking
7533  // through the friends tree, let return
7535  return;
7536  }
7537  if (!fFriends) {
7538  return;
7539  }
7540  TFriendLock lock(this, kRemoveFriend);
7541  TIter nextf(fFriends);
7542  TFriendElement* fe = 0;
7543  while ((fe = (TFriendElement*) nextf())) {
7544  TTree* friend_t = fe->GetTree();
7545  if (friend_t == oldFriend) {
7546  fFriends->Remove(fe);
7547  delete fe;
7548  fe = 0;
7549  }
7550  }
7551 }
7552 
7553 ////////////////////////////////////////////////////////////////////////////////
7554 /// Reset baskets, buffers and entries count in all branches and leaves.
7555 
7556 void TTree::Reset(Option_t* option)
7558  fNotify = 0;
7559  fEntries = 0;
7560  fNClusterRange = 0;
7561  fTotBytes = 0;
7562  fZipBytes = 0;
7563  fFlushedBytes = 0;
7564  fSavedBytes = 0;
7565  fTotalBuffers = 0;
7566  fChainOffset = 0;
7567  fReadEntry = -1;
7568 
7569  delete fTreeIndex;
7570  fTreeIndex = 0;
7571 
7573  for (Int_t i = 0; i < nb; ++i) {
7574  TBranch* branch = (TBranch*) fBranches.UncheckedAt(i);
7575  branch->Reset(option);
7576  }
7577 
7578  if (fBranchRef) {
7579  fBranchRef->Reset();
7580  }
7581 }
7582 
7583 ////////////////////////////////////////////////////////////////////////////////
7584 /// Resets the state of this TTree after a merge (keep the customization but
7585 /// forget the data).
7586 
7589  fEntries = 0;
7590  fNClusterRange = 0;
7591  fTotBytes = 0;
7592  fZipBytes = 0;
7593  fSavedBytes = 0;
7594  fFlushedBytes = 0;
7595  fTotalBuffers = 0;
7596  fChainOffset = 0;
7597  fReadEntry = -1;
7598 
7599  delete fTreeIndex;
7600  fTreeIndex = 0;
7601 
7603  for (Int_t i = 0; i < nb; ++i) {
7604  TBranch* branch = (TBranch*) fBranches.UncheckedAt(i);
7605  branch->ResetAfterMerge(info);
7606  }
7607 
7608  if (fBranchRef) {
7609  fBranchRef->ResetAfterMerge(info);
7610  }
7611 }
7612 
7613 ////////////////////////////////////////////////////////////////////////////////
7614 /// Tell all of our branches to set their addresses to zero.
7615 ///
7616 /// Note: If any of our branches own any objects, they are deleted.
7617 
7620  if (br && br->GetTree()) {
7621  br->ResetAddress();
7622  }
7623 }
7624 
7625 ////////////////////////////////////////////////////////////////////////////////
7626 /// Tell all of our branches to drop their current objects and allocate new ones.
7627 
7631  Int_t nbranches = branches->GetEntriesFast();
7632  for (Int_t i = 0; i < nbranches; ++i) {
7633  TBranch* branch = (TBranch*) branches->UncheckedAt(i);
7634  branch->ResetAddress();
7635  }
7636 }
7637 
7638 ////////////////////////////////////////////////////////////////////////////////
7639 /// Loop over tree entries and print entries passing selection.
7640 ///
7641 /// - If varexp is 0 (or "") then print only first 8 columns.
7642 /// - If varexp = "*" print all columns.
7643 ///
7644 /// Otherwise a columns selection can be made using "var1:var2:var3".
7645 /// See TTreePlayer::Scan for more information
7646 
7647 Long64_t TTree::Scan(const char* varexp, const char* selection, Option_t* option, Long64_t nentries, Long64_t firstentry)
7649  GetPlayer();
7650  if (fPlayer) {
7651  return fPlayer->Scan(varexp, selection, option, nentries, firstentry);
7652  }
7653  return -1;
7654 }
7655 
7656 ////////////////////////////////////////////////////////////////////////////////
7657 /// Set a tree variable alias.
7658 ///
7659 /// Set an alias for an expression/formula based on the tree 'variables'.
7660 ///
7661 /// The content of 'aliasName' can be used in TTreeFormula (i.e. TTree::Draw,
7662 /// TTree::Scan, TTreeViewer) and will be evaluated as the content of
7663 /// 'aliasFormula'.
7664 ///
7665 /// If the content of 'aliasFormula' only contains symbol names, periods and
7666 /// array index specification (for example event.fTracks[3]), then
7667 /// the content of 'aliasName' can be used as the start of symbol.
7668 ///
7669 /// If the alias 'aliasName' already existed, it is replaced by the new
7670 /// value.
7671 ///
7672 /// When being used, the alias can be preceded by an eventual 'Friend Alias'
7673 /// (see TTree::GetFriendAlias)
7674 ///
7675 /// Return true if it was added properly.
7676 ///
7677 /// For example:
7678 /// ~~~ {.cpp}
7679 /// tree->SetAlias("x1","(tdc1[1]-tdc1[0])/49");
7680 /// tree->SetAlias("y1","(tdc1[3]-tdc1[2])/47");
7681 /// tree->SetAlias("x2","(tdc2[1]-tdc2[0])/49");
7682 /// tree->SetAlias("y2","(tdc2[3]-tdc2[2])/47");
7683 /// tree->Draw("y2-y1:x2-x1");
7684 ///
7685 /// tree->SetAlias("theGoodTrack","event.fTracks[3]");
7686 /// tree->Draw("theGoodTrack.fPx"); // same as "event.fTracks[3].fPx"
7687 /// ~~~
7688 
7689 Bool_t TTree::SetAlias(const char* aliasName, const char* aliasFormula)
7691  if (!aliasName || !aliasFormula) {
7692  return kFALSE;
7693  }
7694  if (!aliasName[0] || !aliasFormula[0]) {
7695  return kFALSE;
7696  }
7697  if (!fAliases) {
7698  fAliases = new TList;
7699  } else {
7700  TNamed* oldHolder = (TNamed*) fAliases->FindObject(aliasName);
7701  if (oldHolder) {
7702  oldHolder->SetTitle(aliasFormula);
7703  return kTRUE;
7704  }
7705  }
7706  TNamed* holder = new TNamed(aliasName, aliasFormula);
7707  fAliases->Add(holder);
7708  return kTRUE;
7709 }
7710 
7711 ////////////////////////////////////////////////////////////////////////////////
7712 /// This function may be called at the start of a program to change
7713 /// the default value for fAutoFlush.
7714 ///
7715 /// ### CASE 1 : autof > 0
7716 ///
7717 /// autof is the number of consecutive entries after which TTree::Fill will
7718 /// flush all branch buffers to disk.
7719 ///
7720 /// ### CASE 2 : autof < 0
7721 ///
7722 /// When filling the Tree the branch buffers will be flushed to disk when
7723 /// more than autof bytes have been written to the file. At the first FlushBaskets
7724 /// TTree::Fill will replace fAutoFlush by the current value of fEntries.
7725 ///
7726 /// Calling this function with autof<0 is interesting when it is hard to estimate
7727 /// the size of one entry. This value is also independent of the Tree.
7728 ///
7729 /// The Tree is initialized with fAutoFlush=-30000000, ie that, by default,
7730 /// the first AutoFlush will be done when 30 MBytes of data are written to the file.
7731 ///
7732 /// ### CASE 3 : autof = 0
7733 ///
7734 /// The AutoFlush mechanism is disabled.
7735 ///
7736 /// Flushing the buffers at regular intervals optimize the location of
7737 /// consecutive entries on the disk by creating clusters of baskets.
7738 ///
7739 /// A cluster of baskets is a set of baskets that contains all
7740 /// the data for a (consecutive) set of entries and that is stored
7741 /// consecutively on the disk. When reading all the branches, this
7742 /// is the minimum set of baskets that the TTreeCache will read.
7743 
7744 void TTree::SetAutoFlush(Long64_t autof /* = -30000000 */ )
7746  // Implementation note:
7747  //
7748  // A positive value of autoflush determines the size (in number of entries) of
7749  // a cluster of baskets.
7750  //
7751  // If the value of autoflush is changed over time (this happens in
7752  // particular when the TTree results from fast merging many trees),
7753  // we record the values of fAutoFlush in the data members:
7754  // fClusterRangeEnd and fClusterSize.
7755  // In the code we refer to a range of entries where the size of the
7756  // cluster of baskets is the same (i.e the value of AutoFlush was
7757  // constant) is called a ClusterRange.
7758  //
7759  // The 2 arrays (fClusterRangeEnd and fClusterSize) have fNClusterRange
7760  // active (used) values and have fMaxClusterRange allocated entries.
7761  //
7762  // fClusterRangeEnd contains the last entries number of a cluster range.
7763  // In particular this means that the 'next' cluster starts at fClusterRangeEnd[]+1
7764  // fClusterSize contains the size in number of entries of all the cluster
7765  // within the given range.
7766  // The last range (and the only one if fNClusterRange is zero) start at
7767  // fNClusterRange[fNClusterRange-1]+1 and ends at the end of the TTree. The
7768  // size of the cluster in this range is given by the value of fAutoFlush.
7769  //
7770  // For example printing the beginning and end of each the ranges can be done by:
7771  //
7772  // Printf("%-16s %-16s %-16s %5s",
7773  // "Cluster Range #", "Entry Start", "Last Entry", "Size");
7774  // Int_t index= 0;
7775  // Long64_t clusterRangeStart = 0;
7776  // if (fNClusterRange) {
7777  // for( ; index < fNClusterRange; ++index) {
7778  // Printf("%-16d %-16lld %-16lld %5lld",
7779  // index, clusterRangeStart, fClusterRangeEnd[index], fClusterSize[index]);
7780  // clusterRangeStart = fClusterRangeEnd[index] + 1;
7781  // }
7782  // }
7783  // Printf("%-16d %-16lld %-16lld %5lld",
7784  // index, prevEntry, fEntries - 1, fAutoFlush);
7785  //
7786 
7787  // Note: We store the entry number corresponding to the end of the cluster
7788  // rather than its start in order to avoid using the array if the cluster
7789  // size never varies (If there is only one value of AutoFlush for the whole TTree).
7790 
7791  if (fAutoFlush > 0 || autof > 0) {
7792  // The mechanism was already enabled, let's record the previous
7793  // cluster if needed.
7794  if (fFlushedBytes && fEntries) {
7795  if ( (fNClusterRange+1) > fMaxClusterRange ) {
7796  if (fMaxClusterRange) {
7797  Int_t newsize = TMath::Max(10,Int_t(2*fMaxClusterRange));
7799  newsize*sizeof(Long64_t),fMaxClusterRange*sizeof(Long64_t));
7801  newsize*sizeof(Long64_t),fMaxClusterRange*sizeof(Long64_t));
7802  fMaxClusterRange = newsize;
7803  } else {
7804  fMaxClusterRange = 2;
7807  }
7808  }
7811  ++fNClusterRange;
7812  }
7813  }
7814  fAutoFlush = autof;
7815 }
7816 
7817 ////////////////////////////////////////////////////////////////////////////////
7818 /// This function may be called at the start of a program to change
7819 /// the default value for fAutoSave (and for SetAutoSave) is -300000000, ie 300 MBytes.
7820 /// When filling the Tree the branch buffers as well as the Tree header
7821 /// will be flushed to disk when the watermark is reached.
7822 /// If fAutoSave is positive the watermark is reached when a multiple of fAutoSave
7823 /// entries have been written.
7824 /// If fAutoSave is negative the watermark is reached when -fAutoSave bytes
7825 /// have been written to the file.
7826 /// In case of a program crash, it will be possible to recover the data in the Tree
7827 /// up to the last AutoSave point.
7828 
7829 void TTree::SetAutoSave(Long64_t autos)
7831  fAutoSave = autos;
7832 }
7833 
7834 ////////////////////////////////////////////////////////////////////////////////
7835 /// Set a branch's basket size.
7836 ///
7837 /// bname is the name of a branch.
7838 ///
7839 /// - if bname="*", apply to all branches.
7840 /// - if bname="xxx*", apply to all branches with name starting with xxx
7841 ///
7842 /// see TRegexp for wildcarding options
7843 /// buffsize = branc basket size
7844 
7845 void TTree::SetBasketSize(const char* bname, Int_t buffsize)
7847  Int_t nleaves = fLeaves.GetEntriesFast();
7848  TRegexp re(bname, kTRUE);
7849  Int_t nb = 0;
7850  for (Int_t i = 0; i < nleaves; i++) {
7851  TLeaf* leaf = (TLeaf*) fLeaves.UncheckedAt(i);
7852  TBranch* branch = (TBranch*) leaf->GetBranch();
7853  TString s = branch->GetName();
7854  if (strcmp(bname, branch->GetName()) && (s.Index(re) == kNPOS)) {
7855  continue;
7856  }
7857  nb++;
7858  branch->SetBasketSize(buffsize);
7859  }
7860  if (!nb) {
7861  Error("SetBasketSize", "unknown branch -> '%s'", bname);
7862  }
7863 }
7864 
7865 ////////////////////////////////////////////////////////////////////////////////
7866 /// Change branch address, dealing with clone trees properly.
7867 /// See TTree::CheckBranchAddressType for the semantic of the return value.
7868 ///
7869 /// Note: See the comments in TBranchElement::SetAddress() for the
7870 /// meaning of the addr parameter and the object ownership policy.
7871 
7872 Int_t TTree::SetBranchAddress(const char* bname, void* addr, TBranch** ptr)
7874  TBranch* branch = GetBranch(bname);
7875  if (!branch) {
7876  if (ptr) *ptr = 0;
7877  Error("SetBranchAddress", "unknown branch -> %s", bname);
7878  return kMissingBranch;
7879  }
7880  return SetBranchAddressImp(branch,addr,ptr);
7881 }
7882 
7883 ////////////////////////////////////////////////////////////////////////////////
7884 /// Verify the validity of the type of addr before calling SetBranchAddress.
7885 /// See TTree::CheckBranchAddressType for the semantic of the return value.
7886 ///
7887 /// Note: See the comments in TBranchElement::SetAddress() for the
7888 /// meaning of the addr parameter and the object ownership policy.
7889 
7890 Int_t TTree::SetBranchAddress(const char* bname, void* addr, TClass* ptrClass, EDataType datatype, Bool_t isptr)
7892  return SetBranchAddress(bname, addr, 0, ptrClass, datatype, isptr);
7893 }
7894 
7895 ////////////////////////////////////////////////////////////////////////////////
7896 /// Verify the validity of the type of addr before calling SetBranchAddress.
7897 /// See TTree::CheckBranchAddressType for the semantic of the return value.
7898 ///
7899 /// Note: See the comments in TBranchElement::SetAddress() for the
7900 /// meaning of the addr parameter and the object ownership policy.
7901 
7902 Int_t TTree::SetBranchAddress(const char* bname, void* addr, TBranch** ptr, TClass* ptrClass, EDataType datatype, Bool_t isptr)
7904  TBranch* branch = GetBranch(bname);
7905  if (!branch) {
7906  if (ptr) *ptr = 0;
7907  Error("SetBranchAddress", "unknown branch -> %s", bname);
7908  return kMissingBranch;
7909  }
7910 
7911  Int_t res = CheckBranchAddressType(branch, ptrClass, datatype, isptr);
7912  // This will set the value of *ptr to branch.
7913  if (res >= 0) {
7914  // The check succeeded.
7915  SetBranchAddressImp(branch,addr,ptr);
7916  } else {
7917  if (ptr) *ptr = 0;
7918  }
7919  return res;
7920 }
7921 
7922 ////////////////////////////////////////////////////////////////////////////////
7923 /// Change branch address, dealing with clone trees properly.
7924 /// See TTree::CheckBranchAddressType for the semantic of the return value.
7925 ///
7926 /// Note: See the comments in TBranchElement::SetAddress() for the
7927 /// meaning of the addr parameter and the object ownership policy.
7928 
7929 Int_t TTree::SetBranchAddressImp(TBranch *branch, void* addr, TBranch** ptr)
7931  if (ptr) {
7932  *ptr = branch;
7933  }
7934  if (fClones) {
7935  void* oldAddr = branch->GetAddress();
7936  TIter next(fClones);
7937  TTree* clone = 0;
7938  const char *bname = branch->GetName();
7939  while ((clone = (TTree*) next())) {
7940  TBranch* cloneBr = clone->GetBranch(bname);
7941  if (cloneBr && (cloneBr->GetAddress() == oldAddr)) {
7942  cloneBr->SetAddress(addr);
7943  }
7944  }
7945  }
7946  branch->SetAddress(addr);
7947  return kVoidPtr;
7948 }
7949 
7950 ////////////////////////////////////////////////////////////////////////////////
7951 /// Set branch status to Process or DoNotProcess.
7952 ///
7953 /// When reading a Tree, by default, all branches are read.
7954 /// One can speed up considerably the analysis phase by activating
7955 /// only the branches that hold variables involved in a query.
7956 ///
7957 /// bname is the name of a branch.
7958 ///
7959 /// - if bname="*", apply to all branches.
7960 /// - if bname="xxx*", apply to all branches with name starting with xxx
7961 ///
7962 /// see TRegexp for wildcarding options
7963 ///
7964 /// - status = 1 branch will be processed
7965 /// - = 0 branch will not be processed
7966 ///
7967 /// Example:
7968 ///
7969 /// Assume a tree T with sub-branches a,b,c,d,e,f,g,etc..
7970 /// when doing T.GetEntry(i) all branches are read for entry i.
7971 /// to read only the branches c and e, one can do
7972 /// ~~~ {.cpp}
7973 /// T.SetBranchStatus("*",0); //disable all branches
7974 /// T.SetBranchStatus("c",1);
7975 /// T.setBranchStatus("e",1);
7976 /// T.GetEntry(i);
7977 /// ~~~
7978 /// bname is interpreted as a wildcarded TRegexp (see TRegexp::MakeWildcard).
7979 /// Thus, "a*b" or "a.*b" matches branches starting with "a" and ending with
7980 /// "b", but not any other branch with an "a" followed at some point by a
7981 /// "b". For this second behavior, use "*a*b*". Note that TRegExp does not
7982 /// support '|', and so you cannot select, e.g. track and shower branches
7983 /// with "track|shower".
7984 ///
7985 /// __WARNING! WARNING! WARNING!__
7986 ///
7987 /// SetBranchStatus is matching the branch based on match of the branch
7988 /// 'name' and not on the branch hierarchy! In order to be able to
7989 /// selectively enable a top level object that is 'split' you need to make
7990 /// sure the name of the top level branch is prefixed to the sub-branches'
7991 /// name (by adding a dot ('.') at the end of the Branch creation and use the
7992 /// corresponding bname.
7993 ///
7994 /// I.e If your Tree has been created in split mode with a parent branch "parent."
7995 /// (note the trailing dot).
7996 /// ~~~ {.cpp}
7997 /// T.SetBranchStatus("parent",1);
7998 /// ~~~
7999 /// will not activate the sub-branches of "parent". You should do:
8000 /// ~~~ {.cpp}
8001 /// T.SetBranchStatus("parent*",1);
8002 /// ~~~
8003 /// Without the trailing dot in the branch creation you have no choice but to
8004 /// call SetBranchStatus explicitly for each of the sub branches.
8005 ///
8006 /// An alternative to this function is to read directly and only
8007 /// the interesting branches. Example:
8008 /// ~~~ {.cpp}
8009 /// TBranch *brc = T.GetBranch("c");
8010 /// TBranch *bre = T.GetBranch("e");
8011 /// brc->GetEntry(i);
8012 /// bre->GetEntry(i);
8013 /// ~~~
8014 /// If found is not 0, the number of branch(es) found matching the regular
8015 /// expression is returned in *found AND the error message 'unknown branch'
8016 /// is suppressed.
8017 
8018 void TTree::SetBranchStatus(const char* bname, Bool_t status, UInt_t* found)
8020  // We already have been visited while recursively looking
8021  // through the friends tree, let return
8023  return;
8024  }
8025 
8026  TBranch *branch, *bcount, *bson;
8027  TLeaf *leaf, *leafcount;
8028 
8029  Int_t i,j;
8030  Int_t nleaves = fLeaves.GetEntriesFast();
8031  TRegexp re(bname,kTRUE);
8032  Int_t nb = 0;
8033 
8034  // first pass, loop on all branches
8035  // for leafcount branches activate/deactivate in function of status
8036  for (i=0;i<nleaves;i++) {
8037  leaf = (TLeaf*)fLeaves.UncheckedAt(i);
8038  branch = (TBranch*)leaf->GetBranch();
8039  TString s = branch->GetName();
8040  if (strcmp(bname,"*")) { //Regexp gives wrong result for [] in name
8041  TString longname;
8042  longname.Form("%s.%s",GetName(),branch->GetName());
8043  if (strcmp(bname,branch->GetName())
8044  && longname != bname
8045  && s.Index(re) == kNPOS) continue;
8046  }
8047  nb++;
8048  if (status) branch->ResetBit(kDoNotProcess);
8049  else branch->SetBit(kDoNotProcess);
8050  leafcount = leaf->GetLeafCount();
8051  if (leafcount) {
8052  bcount = leafcount->GetBranch();
8053  if (status) bcount->ResetBit(kDoNotProcess);
8054  else bcount->SetBit(kDoNotProcess);
8055  }
8056  }
8057  if (nb==0 && strchr(bname,'*')==0) {
8058  branch = GetBranch(bname);
8059  if (branch) {
8060  if (status) branch->ResetBit(kDoNotProcess);
8061  else branch->SetBit(kDoNotProcess);
8062  ++nb;
8063  }
8064  }
8065 
8066  //search in list of friends
8067  UInt_t foundInFriend = 0;
8068  if (fFriends) {
8069  TFriendLock lock(this,kSetBranchStatus);
8070  TIter nextf(fFriends);
8071  TFriendElement *fe;
8072  TString name;
8073  while ((fe = (TFriendElement*)nextf())) {
8074  TTree *t = fe->GetTree();
8075  if (t==0) continue;
8076 
8077  // If the alias is present replace it with the real name.
8078  char *subbranch = (char*)strstr(bname,fe->GetName());
8079  if (subbranch!=bname) subbranch = 0;
8080  if (subbranch) {
8081  subbranch += strlen(fe->GetName());
8082  if ( *subbranch != '.' ) subbranch = 0;
8083  else subbranch ++;
8084  }
8085  if (subbranch) {
8086  name.Form("%s.%s",t->GetName(),subbranch);
8087  } else {
8088  name = bname;
8089  }
8090  t->SetBranchStatus(name,status, &foundInFriend);
8091  }
8092  }
8093  if (!nb && !foundInFriend) {
8094  if (found==0) {
8095  if (status) {
8096  if (strchr(bname,'*') != 0)
8097  Error("SetBranchStatus", "No branch name is matching wildcard -> %s", bname);
8098  else
8099  Error("SetBranchStatus", "unknown branch -> %s", bname);
8100  } else {
8101  if (strchr(bname,'*') != 0)
8102  Warning("SetBranchStatus", "No branch name is matching wildcard -> %s", bname);
8103  else
8104  Warning("SetBranchStatus", "unknown branch -> %s", bname);
8105  }
8106  }
8107  return;
8108  }
8109  if (found) *found = nb + foundInFriend;
8110 
8111  // second pass, loop again on all branches
8112  // activate leafcount branches for active branches only
8113  for (i = 0; i < nleaves; i++) {
8114  leaf = (TLeaf*)fLeaves.UncheckedAt(i);
8115  branch = (TBranch*)leaf->GetBranch();
8116  if (!branch->TestBit(kDoNotProcess)) {
8117  leafcount = leaf->GetLeafCount();
8118  if (leafcount) {
8119  bcount = leafcount->GetBranch();
8120  bcount->ResetBit(kDoNotProcess);
8121  }
8122  } else {
8123  //Int_t nbranches = branch->GetListOfBranches()->GetEntriesFast();
8124  Int_t nbranches = branch->GetListOfBranches()->GetEntries();
8125  for (j=0;j<nbranches;j++) {
8126  bson = (TBranch*)branch->GetListOfBranches()->UncheckedAt(j);
8127  if (!bson) continue;
8128  if (!bson->TestBit(kDoNotProcess)) {
8129  if (bson->GetNleaves() <= 0) continue;
8130  branch->ResetBit(kDoNotProcess);
8131  break;
8132  }
8133  }
8134  }
8135  }
8136 }
8137 
8138 ////////////////////////////////////////////////////////////////////////////////
8139 /// Set the current branch style. (static function)
8140 ///
8141 /// - style = 0 old Branch
8142 /// - style = 1 new Bronch
8143 
8146  fgBranchStyle = style;
8147 }
8148 
8149 ////////////////////////////////////////////////////////////////////////////////
8150 /// Set maximum size of the file cache .
8151 //
8152 /// - if cachesize = 0 the existing cache (if any) is deleted.
8153 /// - if cachesize = -1 (default) it is set to the AutoFlush value when writing
8154 /// the Tree (default is 30 MBytes).
8155 ///
8156 /// Returns:
8157 /// - 0 size set, cache was created if possible
8158 /// - -1 on error
8159 
8162  // remember that the user has requested an explicit cache setup
8163  fCacheUserSet = kTRUE;
8164 
8165  return SetCacheSizeAux(kFALSE, cacheSize);
8166 }
8167 
8168 ////////////////////////////////////////////////////////////////////////////////
8169 /// Set the size of the file cache and create it if possible.
8170 ///
8171 /// If autocache is true:
8172 /// this may be an autocreated cache, possibly enlarging an existing
8173 /// autocreated cache. The size is calculated. The value passed in cacheSize:
8174 /// - cacheSize = 0 make cache if default cache creation is enabled
8175 /// - cacheSize = -1 make a default sized cache in any case
8176 ///
8177 /// If autocache is false:
8178 /// this is a user requested cache. cacheSize is used to size the cache.
8179 /// This cache should never be automatically adjusted.
8180 ///
8181 /// Returns:
8182 /// - 0 size set, or existing autosized cache almost large enough.
8183 /// (cache was created if possible)
8184 /// - -1 on error
8185 
8186 Int_t TTree::SetCacheSizeAux(Bool_t autocache /* = kTRUE */, Long64_t cacheSize /* = 0 */ )
8188  if (autocache) {
8189  // used as a once only control for automatic cache setup
8191  }
8192 
8193  if (!autocache) {
8194  // negative size means the user requests the default
8195  if (cacheSize < 0) {
8196  cacheSize = GetCacheAutoSize(kTRUE);
8197  }
8198  } else {
8199  if (cacheSize == 0) {
8200  cacheSize = GetCacheAutoSize();
8201  } else if (cacheSize < 0) {
8202  cacheSize = GetCacheAutoSize(kTRUE);
8203  }
8204  }
8205 
8206  TFile* file = GetCurrentFile();
8207  if (!file || GetTree() != this) {
8208  // if there's no file or we are not a plain tree (e.g. if we're a TChain)
8209  // do not create a cache, only record the size if one was given
8210  if (!autocache) {
8211  fCacheSize = cacheSize;
8212  }
8213  if (GetTree() != this) {
8214  return 0;
8215  }
8216  if (!autocache && cacheSize>0) {
8217  Warning("SetCacheSizeAux", "A TTreeCache could not be created because the TTree has no file");
8218  }
8219  return 0;
8220  }
8221 
8222  // Check for an existing cache
8223  TTreeCache* pf = GetReadCache(file);
8224  if (pf) {
8225  if (autocache) {
8226  // reset our cache status tracking in case existing cache was added
8227  // by the user without using one of the TTree methods
8228  fCacheSize = pf->GetBufferSize();
8229  fCacheUserSet = !pf->IsAutoCreated();
8230 
8231  if (fCacheUserSet) {
8232  // existing cache was created by the user, don't change it
8233  return 0;
8234  }
8235  } else {
8236  // update the cache to ensure it records the user has explicitly
8237  // requested it
8238  pf->SetAutoCreated(kFALSE);
8239  }
8240 
8241  // if we're using an automatically calculated size and the existing
8242  // cache is already almost large enough don't resize
8243  if (autocache && Long64_t(0.80*cacheSize) < fCacheSize) {
8244  // already large enough
8245  return 0;
8246  }
8247 
8248  if (cacheSize == fCacheSize) {
8249  return 0;
8250  }
8251 
8252  if (cacheSize == 0) {
8253  // delete existing cache
8254  pf->WaitFinishPrefetch();
8255  file->SetCacheRead(0,this);
8256  delete pf;
8257  pf = 0;
8258  } else {
8259  // resize
8260  Int_t res = pf->SetBufferSize(cacheSize);
8261  if (res < 0) {
8262  return -1;
8263  }
8264  }
8265  } else {
8266  // no existing cache
8267  if (autocache) {
8268  if (fCacheUserSet) {
8269  // value was already set manually.
8270  if (fCacheSize == 0) return 0;
8271  // Expected a cache should exist; perhaps the user moved it
8272  // Do nothing more here.
8273  if (cacheSize) {
8274  Error("SetCacheSizeAux", "Not setting up an automatically sized TTreeCache because of missing cache previously set");
8275  }
8276  return -1;
8277  }
8278  }
8279  }
8280 
8281  fCacheSize = cacheSize;
8282  if (cacheSize == 0 || pf) {
8283  return 0;
8284  }
8285 
8287  pf = new TTreeCacheUnzip(this, cacheSize);
8288  else
8289  pf = new TTreeCache(this, cacheSize);
8290 
8291  pf->SetAutoCreated(autocache);
8292 
8293  return 0;
8294 }
8295 
8296 ////////////////////////////////////////////////////////////////////////////////
8297 ///interface to TTreeCache to set the cache entry range
8298 ///
8299 /// Returns:
8300 /// - 0 entry range set
8301 /// - -1 on error
8302 
8305  if (!GetTree()) {
8306  if (LoadTree(0)<0) {
8307  Error("SetCacheEntryRange","Could not load a tree");
8308  return -1;
8309  }
8310  }
8311  if (GetTree()) {
8312  if (GetTree() != this) {
8313  return GetTree()->SetCacheEntryRange(first, last);
8314  }
8315  } else {
8316  Error("SetCacheEntryRange", "No tree is available. Could not set cache entry range");
8317  return -1;
8318  }
8319 
8320  TFile *f = GetCurrentFile();
8321  if (!f) {
8322  Error("SetCacheEntryRange", "No file is available. Could not set cache entry range");
8323  return -1;
8324  }
8325  TTreeCache *tc = GetReadCache(f,kTRUE);
8326  if (!tc) {
8327  Error("SetCacheEntryRange", "No cache is available. Could not set entry range");
8328  return -1;
8329  }
8330  tc->SetEntryRange(first,last);
8331  return 0;
8332 }
8333 
8334 ////////////////////////////////////////////////////////////////////////////////
8335 /// Interface to TTreeCache to set the number of entries for the learning phase
8336 
8340 }
8341 
8342 ////////////////////////////////////////////////////////////////////////////////
8343 /// Enable/Disable circularity for this tree.
8344 ///
8345 /// if maxEntries > 0 a maximum of maxEntries is kept in one buffer/basket
8346 /// per branch in memory.
8347 /// Note that when this function is called (maxEntries>0) the Tree
8348 /// must be empty or having only one basket per branch.
8349 /// if maxEntries <= 0 the tree circularity is disabled.
8350 ///
8351 /// #### NOTE 1:
8352 /// Circular Trees are interesting in online real time environments
8353 /// to store the results of the last maxEntries events.
8354 /// #### NOTE 2:
8355 /// Calling SetCircular with maxEntries <= 0 is necessary before
8356 /// merging circular Trees that have been saved on files.
8357 /// #### NOTE 3:
8358 /// SetCircular with maxEntries <= 0 is automatically called
8359 /// by TChain::Merge
8360 /// #### NOTE 4:
8361 /// A circular Tree can still be saved in a file. When read back,
8362 /// it is still a circular Tree and can be filled again.
8363 
8364 void TTree::SetCircular(Long64_t maxEntries)
8366  if (maxEntries <= 0) {
8367  // Disable circularity.
8368  fMaxEntries = 1000000000;
8369  fMaxEntries *= 1000;
8371  //in case the Tree was originally created in gROOT, the branch
8372  //compression level was set to -1. If the Tree is now associated to
8373  //a file, reset the compression level to the file compression level
8374  if (fDirectory) {
8375  TFile* bfile = fDirectory->GetFile();
8376  Int_t compress = 1;
8377  if (bfile) {
8378  compress = bfile->GetCompressionSettings();
8379  }
8381  for (Int_t i = 0; i < nb; i++) {
8382  TBranch* branch = (TBranch*) fBranches.UncheckedAt(i);
8383  branch->SetCompressionSettings(compress);
8384  }
8385  }
8386  } else {
8387  // Enable circularity.
8388  fMaxEntries = maxEntries;
8389  SetBit(kCircular);
8390  }
8391 }
8392 
8393 ////////////////////////////////////////////////////////////////////////////////
8394 /// Set the debug level and the debug range.
8395 ///
8396 /// For entries in the debug range, the functions TBranchElement::Fill
8397 /// and TBranchElement::GetEntry will print the number of bytes filled
8398 /// or read for each branch.
8399 
8400 void TTree::SetDebug(Int_t level, Long64_t min, Long64_t max)
8402  fDebug = level;
8403  fDebugMin = min;
8404  fDebugMax = max;
8405 }
8406 
8407 ////////////////////////////////////////////////////////////////////////////////
8408 /// Update the default value for the branch's fEntryOffsetLen.
8409 /// If updateExisting is true, also update all the existing branches.
8410 /// If newdefault is less than 10, the new default value will be 10.
8411 
8412 void TTree::SetDefaultEntryOffsetLen(Int_t newdefault, Bool_t updateExisting)
8414  if (newdefault < 10) {
8415  newdefault = 10;
8416  }
8417  fDefaultEntryOffsetLen = newdefault;
8418  if (updateExisting) {
8419  TIter next( GetListOfBranches() );
8420  TBranch *b;
8421  while ( ( b = (TBranch*)next() ) ) {
8422  b->SetEntryOffsetLen( newdefault, kTRUE );
8423  }
8424  if (fBranchRef) {
8425  fBranchRef->SetEntryOffsetLen( newdefault, kTRUE );
8426  }
8427  }
8428 }
8429 
8430 ////////////////////////////////////////////////////////////////////////////////
8431 /// Change the tree's directory.
8432 ///
8433 /// Remove reference to this tree from current directory and
8434 /// add reference to new directory dir. The dir parameter can
8435 /// be 0 in which case the tree does not belong to any directory.
8436 ///
8437 
8440  if (fDirectory == dir) {
8441  return;
8442  }
8443  if (fDirectory) {
8444  fDirectory->Remove(this);
8445 
8446  // Delete or move the file cache if it points to this Tree
8447  TFile *file = fDirectory->GetFile();
8448  MoveReadCache(file,dir);
8449  }
8450  fDirectory = dir;
8451  if (fDirectory) {
8452  fDirectory->Append(this);
8453  }
8454  TFile* file = 0;
8455  if (fDirectory) {
8456  file = fDirectory->GetFile();
8457  }
8458  if (fBranchRef) {
8459  fBranchRef->SetFile(file);
8460  }
8461  TBranch* b = 0;
8462  TIter next(GetListOfBranches());
8463  while((b = (TBranch*) next())) {
8464  b->SetFile(file);
8465  }
8466 }
8467 
8468 ////////////////////////////////////////////////////////////////////////////////
8469 /// Change number of entries in the tree.
8470 ///
8471 /// If n >= 0, set number of entries in the tree = n.
8472 ///
8473 /// If n < 0, set number of entries in the tree to match the
8474 /// number of entries in each branch. (default for n is -1)
8475 ///
8476 /// This function should be called only when one fills each branch
8477 /// independently via TBranch::Fill without calling TTree::Fill.
8478 /// Calling TTree::SetEntries() make sense only if the number of entries
8479 /// in each branch is identical, a warning is issued otherwise.
8480 /// The function returns the number of entries.
8481 ///
8482 
8485  // case 1 : force number of entries to n
8486  if (n >= 0) {
8487  fEntries = n;
8488  return n;
8489  }
8490 
8491  // case 2; compute the number of entries from the number of entries in the branches
8492  TBranch* b = 0;
8493  Long64_t nMin = 99999999;
8494  Long64_t nMax = 0;
8495  TIter next(GetListOfBranches());
8496  while((b = (TBranch*) next())){
8497  Long64_t n2 = b->GetEntries();
8498  if (n2 < nMin) {
8499  nMin = n2;
8500  }
8501  if (n2 > nMax) {
8502  nMax = n2;
8503  }
8504  }
8505  if (nMin != nMax) {
8506  Warning("SetEntries", "Tree branches have different numbers of entries, with %lld maximum.", nMax);
8507  }
8508  fEntries = nMax;
8509  return fEntries;
8510 }
8511 
8512 ////////////////////////////////////////////////////////////////////////////////
8513 /// Set an EntryList
8514 
8515 void TTree::SetEntryList(TEntryList *enlist, Option_t * /*opt*/)
8517  if (fEntryList) {
8518  //check if the previous entry list is owned by the tree
8519  if (fEntryList->TestBit(kCanDelete)){
8520  delete fEntryList;
8521  }
8522  }
8523  fEventList = 0;
8524  if (!enlist) {
8525  fEntryList = 0;
8526  return;
8527  }
8528  fEntryList = enlist;
8529  fEntryList->SetTree(this);
8530 
8531 }
8532 
8533 ////////////////////////////////////////////////////////////////////////////////
8534 /// This function transfroms the given TEventList into a TEntryList
8535 /// The new TEntryList is owned by the TTree and gets deleted when the tree
8536 /// is deleted. This TEntryList can be returned by GetEntryList() function.
8537 
8538 void TTree::SetEventList(TEventList *evlist)
8540  fEventList = evlist;
8541  if (fEntryList){
8542  if (fEntryList->TestBit(kCanDelete)) {
8543  TEntryList *tmp = fEntryList;
8544  fEntryList = 0; // Avoid problem with RecursiveRemove.
8545  delete tmp;
8546  } else {
8547  fEntryList = 0;
8548  }
8549  }
8550 
8551  if (!evlist) {
8552  fEntryList = 0;
8553  fEventList = 0;
8554  return;
8555  }
8556 
8557  fEventList = evlist;
8558  char enlistname[100];
8559  snprintf(enlistname,100, "%s_%s", evlist->GetName(), "entrylist");
8560  fEntryList = new TEntryList(enlistname, evlist->GetTitle());
8561  fEntryList->SetDirectory(0); // We own this.
8562  Int_t nsel = evlist->GetN();
8563  fEntryList->SetTree(this);
8564  Long64_t entry;
8565  for (Int_t i=0; i<nsel; i++){
8566  entry = evlist->GetEntry(i);
8567  fEntryList->Enter(entry);
8568  }
8569  fEntryList->SetReapplyCut(evlist->GetReapplyCut());
8570  fEntryList->SetBit(kCanDelete, kTRUE);
8571 }
8572 
8573 ////////////////////////////////////////////////////////////////////////////////
8574 /// Set number of entries to estimate variable limits.
8575 /// If n is -1, the estimate is set to be the current maximum
8576 /// for the tree (i.e. GetEntries() + 1)
8577 /// If n is less than -1, the behavior is undefined.
8578 
8579 void TTree::SetEstimate(Long64_t n /* = 1000000 */)
8581  if (n == 0) {
8582  n = 10000;
8583  } else if (n < 0) {
8584  n = fEntries - n;
8585  }
8586  fEstimate = n;
8587  GetPlayer();
8588  if (fPlayer) {
8589  fPlayer->SetEstimate(n);
8590  }
8591 }
8592 
8593 ////////////////////////////////////////////////////////////////////////////////
8594 /// Set fFileNumber to number.
8595 /// fFileNumber is used by TTree::Fill to set the file name
8596 /// for a new file to be created when the current file exceeds fgTreeMaxSize.
8597 /// (see TTree::ChangeFile)
8598 /// if fFileNumber=10, the new file name will have a suffix "_11",
8599 /// ie, fFileNumber is incremented before setting the file name
8600 
8601 void TTree::SetFileNumber(Int_t number)
8603  if (fFileNumber < 0) {
8604  Warning("SetFileNumber", "file number must be positive. Set to 0");
8605  fFileNumber = 0;
8606  return;
8607  }
8608  fFileNumber = number;
8609 }
8610 
8611 ////////////////////////////////////////////////////////////////////////////////
8612 /// Set all the branches in this TTree to be in decomposed object mode
8613 /// (also known as MakeClass mode).
8614 
8617  fMakeClass = make;
8618 
8620  for (Int_t i = 0; i < nb; ++i) {
8621  TBranch* branch = (TBranch*) fBranches.UncheckedAt(i);
8622  branch->SetMakeClass(make);
8623  }
8624 }
8625 
8626 ////////////////////////////////////////////////////////////////////////////////
8627 /// Set the maximum size in bytes of a Tree file (static function).
8628 /// The default size is 100000000000LL, ie 100 Gigabytes.
8629 ///
8630 /// In TTree::Fill, when the file has a size > fgMaxTreeSize,
8631 /// the function closes the current file and starts writing into
8632 /// a new file with a name of the style "file_1.root" if the original
8633 /// requested file name was "file.root".
8634 
8638 }
8639 
8640 ////////////////////////////////////////////////////////////////////////////////
8641 /// Change the name of this tree.
8642 
8643 void TTree::SetName(const char* name)
8645  if (gPad) {
8646  gPad->Modified();
8647  }
8648  // Trees are named objects in a THashList.
8649  // We must update hashlists if we change the name.
8650  TFile *file = 0;
8651  TTreeCache *pf = 0;
8652  if (fDirectory) {
8653  fDirectory->Remove(this);
8654  if ((file = GetCurrentFile())) {
8655  pf = GetReadCache(file);
8656  file->SetCacheRead(0,this,TFile::kDoNotDisconnect);
8657  }
8658  }
8659  // This changes our hash value.
8660  fName = name;
8661  if (fDirectory) {
8662  fDirectory->Append(this);
8663  if (pf) {
8664  file->SetCacheRead(pf,this,TFile::kDoNotDisconnect);
8665  }
8666  }
8667 }
8668 
8669 ////////////////////////////////////////////////////////////////////////////////
8670 /// Change the name and title of this tree.
8671 
8672 void TTree::SetObject(const char* name, const char* title)
8674  if (gPad) {
8675  gPad->Modified();
8676  }
8677 
8678  // Trees are named objects in a THashList.
8679  // We must update hashlists if we change the name
8680  TFile *file = 0;
8681  TTreeCache *pf = 0;
8682  if (fDirectory) {
8683  fDirectory->Remove(this);
8684  if ((file = GetCurrentFile())) {
8685  pf = GetReadCache(file);
8686  file->SetCacheRead(0,this,TFile::kDoNotDisconnect);
8687  }
8688  }
8689  // This changes our hash value.
8690  fName = name;
8691  fTitle = title;
8692  if (fDirectory) {
8693  fDirectory->Append(this);
8694  if (pf) {
8695  file->SetCacheRead(pf,this,TFile::kDoNotDisconnect);
8696  }
8697  }
8698 }
8699 
8700 ////////////////////////////////////////////////////////////////////////////////
8701 /// Enable or disable parallel unzipping of Tree buffers.
8702 
8703 void TTree::SetParallelUnzip(Bool_t opt, Float_t RelSize)
8707 
8708  if (RelSize > 0) {
8710  }
8711 
8712 }
8713 
8714 ////////////////////////////////////////////////////////////////////////////////
8715 /// Set perf stats
8716 
8719  fPerfStats = perf;
8720 }
8721 
8722 ////////////////////////////////////////////////////////////////////////////////
8723 /// The current TreeIndex is replaced by the new index.
8724 /// Note that this function does not delete the previous index.
8725 /// This gives the possibility to play with more than one index, e.g.,
8726 /// ~~~ {.cpp}
8727 /// TVirtualIndex* oldIndex = tree.GetTreeIndex();
8728 /// tree.SetTreeIndex(newIndex);
8729 /// tree.Draw();
8730 /// tree.SetTreeIndex(oldIndex);
8731 /// tree.Draw(); etc
8732 /// ~~~
8733 
8736  if (fTreeIndex) {
8737  fTreeIndex->SetTree(0);
8738  }
8739  fTreeIndex = index;
8740 }
8741 
8742 ////////////////////////////////////////////////////////////////////////////////
8743 /// Set tree weight.
8744 ///
8745 /// The weight is used by TTree::Draw to automatically weight each
8746 /// selected entry in the resulting histogram.
8747 ///
8748 /// For example the equivalent of:
8749 /// ~~~ {.cpp}
8750 /// T.Draw("x", "w")
8751 /// ~~~
8752 /// is:
8753 /// ~~~ {.cpp}
8754 /// T.SetWeight(w);
8755 /// T.Draw("x");
8756 /// ~~~
8757 /// This function is redefined by TChain::SetWeight. In case of a
8758 /// TChain, an option "global" may be specified to set the same weight
8759 /// for all trees in the TChain instead of the default behaviour
8760 /// using the weights of each tree in the chain (see TChain::SetWeight).
8761 
8764  fWeight = w;
8765 }
8766 
8767 ////////////////////////////////////////////////////////////////////////////////
8768 /// Print values of all active leaves for entry.
8769 ///
8770 /// - if entry==-1, print current entry (default)
8771 /// - if a leaf is an array, a maximum of lenmax elements is printed.
8772 
8773 void TTree::Show(Long64_t entry, Int_t lenmax)
8775  if (entry != -1) {
8776  Int_t ret = LoadTree(entry);
8777  if (ret == -2) {
8778  Error("Show()", "Cannot read entry %lld (entry does not exist)", entry);
8779  return;
8780  } else if (ret == -1) {
8781  Error("Show()", "Cannot read entry %lld (I/O error)", entry);
8782  return;
8783  }
8784  ret = GetEntry(entry);
8785  if (ret == -1) {
8786  Error("Show()", "Cannot read entry %lld (I/O error)", entry);
8787  return;
8788  } else if (ret == 0) {
8789  Error("Show()", "Cannot read entry %lld (no data read)", entry);
8790  return;
8791  }
8792  }
8793  printf("======> EVENT:%lld\n", fReadEntry);
8794  TObjArray* leaves = GetListOfLeaves();
8795  Int_t nleaves = leaves->GetEntriesFast();
8796  Int_t ltype;
8797  for (Int_t i = 0; i < nleaves; i++) {
8798  TLeaf* leaf = (TLeaf*) leaves->UncheckedAt(i);
8799  TBranch* branch = leaf->GetBranch();
8800  if (branch->TestBit(kDoNotProcess)) {
8801  continue;
8802  }
8803  Int_t len = leaf->GetLen();
8804  if (len <= 0) {
8805  continue;
8806  }
8807  len = TMath::Min(len, lenmax);
8808  if (leaf->IsA() == TLeafElement::Class()) {
8809  leaf->PrintValue(lenmax);
8810  continue;
8811  }
8812  if (branch->GetListOfBranches()->GetEntriesFast() > 0) {
8813  continue;
8814  }
8815  ltype = 10;
8816  if (leaf->IsA() == TLeafF::Class()) {
8817  ltype = 5;
8818  }
8819  if (leaf->IsA() == TLeafD::Class()) {
8820  ltype = 5;
8821  }
8822  if (leaf->IsA() == TLeafC::Class()) {
8823  len = 1;
8824  ltype = 5;
8825  };
8826  printf(" %-15s = ", leaf->GetName());
8827  for (Int_t l = 0; l < len; l++) {
8828  leaf->PrintValue(l);
8829  if (l == (len - 1)) {
8830  printf("\n");
8831  continue;
8832  }
8833  printf(", ");
8834  if ((l % ltype) == 0) {
8835  printf("\n ");
8836  }
8837  }
8838  }
8839 }
8840 
8841 ////////////////////////////////////////////////////////////////////////////////
8842 /// Start the TTreeViewer on this tree.
8843 ///
8844 /// - ww is the width of the canvas in pixels
8845 /// - wh is the height of the canvas in pixels
8846 
8847 void TTree::StartViewer()
8849  GetPlayer();
8850  if (fPlayer) {
8851  fPlayer->StartViewer(600, 400);
8852  }
8853 }
8854 
8855 ////////////////////////////////////////////////////////////////////////////////
8856 /// Stop the cache learning phase
8857 ///
8858 /// Returns:
8859 /// - 0 learning phase stopped or not active
8860 /// - -1 on error
8861 
8864  if (!GetTree()) {
8865  if (LoadTree(0)<0) {
8866  Error("StopCacheLearningPhase","Could not load a tree");
8867  return -1;
8868  }
8869  }
8870  if (GetTree()) {
8871  if (GetTree() != this) {
8872  return GetTree()->StopCacheLearningPhase();
8873  }
8874  } else {
8875  Error("StopCacheLearningPhase", "No tree is available. Could not stop cache learning phase");
8876  return -1;
8877  }
8878 
8879  TFile *f = GetCurrentFile();
8880  if (!f) {
8881  Error("StopCacheLearningPhase", "No file is available. Could not stop cache learning phase");
8882  return -1;
8883  }
8884  TTreeCache *tc = GetReadCache(f,kTRUE);
8885  if (!tc) {
8886  Error("StopCacheLearningPhase", "No cache is available. Could not stop learning phase");
8887  return -1;
8888  }
8889  tc->StopLearningPhase();
8890  return 0;
8891 }
8892 
8893 ////////////////////////////////////////////////////////////////////////////////
8894 /// Set the fTree member for all branches and sub branches.
8895 
8896 static void TBranch__SetTree(TTree *tree, TObjArray &branches)
8898  Int_t nb = branches.GetEntriesFast();
8899  for (Int_t i = 0; i < nb; ++i) {
8900  TBranch* br = (TBranch*) branches.UncheckedAt(i);
8901  br->SetTree(tree);
8902 
8903  Int_t nBaskets = br->GetListOfBaskets()->GetEntries();
8904  Int_t writeBasket = br->GetWriteBasket();
8905  for (Int_t j=writeBasket,n=0;j>=0 && n<nBaskets;--j) {
8906  TBasket *bk = (TBasket*)br->GetListOfBaskets()->UncheckedAt(j);
8907  if (bk) {
8908  tree->IncrementTotalBuffers(bk->GetBufferSize());
8909  ++n;
8910  }
8911  }
8912 
8913  TBranch__SetTree(tree,*br->GetListOfBranches());
8914  }
8915 }
8916 
8917 ////////////////////////////////////////////////////////////////////////////////
8918 /// Set the fTree member for all friend elements.
8919 
8920 void TFriendElement__SetTree(TTree *tree, TList *frlist)
8922  if (frlist) {
8923  TObjLink *lnk = frlist->FirstLink();
8924  while (lnk) {
8925  TFriendElement *elem = (TFriendElement*)lnk->GetObject();
8926  elem->fParentTree = tree;
8927  lnk = lnk->Next();
8928  }
8929  }
8930 }
8931 
8932 ////////////////////////////////////////////////////////////////////////////////
8933 /// Stream a class object.
8934 
8935 void TTree::Streamer(TBuffer& b)
8936 {
8937  if (b.IsReading()) {
8938  UInt_t R__s, R__c;
8939  if (fDirectory) {
8940  fDirectory->Remove(this);
8941  //delete the file cache if it points to this Tree
8942  TFile *file = fDirectory->GetFile();
8943  MoveReadCache(file,0);
8944  }
8945  fDirectory = 0;
8948  Version_t R__v = b.ReadVersion(&R__s, &R__c);
8949  if (R__v > 4) {
8950  b.ReadClassBuffer(TTree::Class(), this, R__v, R__s, R__c);
8951 
8952  fBranches.SetOwner(kTRUE); // True needed only for R__v < 19 and most R__v == 19
8953 
8954  if (fBranchRef) fBranchRef->SetTree(this);
8957 
8958  if (fTreeIndex) {
8959  fTreeIndex->SetTree(this);
8960  }
8961  if (fIndex.fN) {
8962  Warning("Streamer", "Old style index in this tree is deleted. Rebuild the index via TTree::BuildIndex");
8963  fIndex.Set(0);
8964  fIndexValues.Set(0);
8965  }
8966  if (fEstimate <= 10000) {
8967  fEstimate = 1000000;
8968  }
8969 
8970  if (fNClusterRange) {
8971  // The I/O allocated just enough memory to hold the
8972  // current set of ranges.
8974  }
8975  if (GetCacheAutoSize() != 0) {
8976  // a cache will be automatically created.
8977  // No need for TTreePlayer::Process to enable the cache
8978  fCacheSize = 0;
8979  } else if (fAutoFlush < 0) {
8980  // If there is no autoflush set, let's keep the cache completely
8981  // disable by default for now.
8983  } else if (fAutoFlush != 0) {
8984  // Estimate the cluster size.
8985  // This will allow TTree::Process to enable the cache.
8986  Long64_t zipBytes = GetZipBytes();
8987  Long64_t totBytes = GetTotBytes();
8988  if (zipBytes != 0) {
8989  fCacheSize = fAutoFlush*(zipBytes/fEntries);
8990  } else if (totBytes != 0) {
8991  fCacheSize = fAutoFlush*(totBytes/fEntries);
8992  } else {
8993  fCacheSize = 30000000;
8994  }
8995  if (fCacheSize >= (INT_MAX / 4)) {
8996  fCacheSize = INT_MAX / 4;
8997  } else if (fCacheSize == 0) {
8998  fCacheSize = 30000000;
8999  }
9000  } else {
9001  fCacheSize = 0;
9002  }
9004  return;
9005  }
9006  //====process old versions before automatic schema evolution
9007  Stat_t djunk;
9008  Int_t ijunk;
9009  TNamed::Streamer(b);
9010  TAttLine::Streamer(b);
9011  TAttFill::Streamer(b);
9012  TAttMarker::Streamer(b);
9013  b >> fScanField;
9014  b >> ijunk; fMaxEntryLoop = (Long64_t)ijunk;
9015  b >> ijunk; fMaxVirtualSize = (Long64_t)ijunk;
9016  b >> djunk; fEntries = (Long64_t)djunk;
9017  b >> djunk; fTotBytes = (Long64_t)djunk;
9018  b >> djunk; fZipBytes = (Long64_t)djunk;
9019  b >> ijunk; fAutoSave = (Long64_t)ijunk;
9020  b >> ijunk; fEstimate = (Long64_t)ijunk;
9021  if (fEstimate <= 10000) fEstimate = 1000000;
9022  fBranches.Streamer(b);
9023  if (fBranchRef) fBranchRef->SetTree(this);
9025  fLeaves.Streamer(b);
9027  if (R__v > 1) fIndexValues.Streamer(b);
9028  if (R__v > 2) fIndex.Streamer(b);
9029  if (R__v > 3) {
9030  TList OldInfoList;
9031  OldInfoList.Streamer(b);
9032  OldInfoList.Delete();
9033  }
9034  fNClusterRange = 0;
9035  fDefaultEntryOffsetLen = 1000;
9037  b.CheckByteCount(R__s, R__c, TTree::IsA());
9038  //====end of old versions
9039  } else {
9040  if (fBranchRef) {
9041  fBranchRef->Clear();
9042  }
9043  TRefTable *table = TRefTable::GetRefTable();
9044  if (table) TRefTable::SetRefTable(0);
9045 
9046  b.WriteClassBuffer(TTree::Class(), this);
9047 
9048  if (table) TRefTable::SetRefTable(table);
9049  }
9050 }
9051 
9052 ////////////////////////////////////////////////////////////////////////////////
9053 /// Unbinned fit of one or more variable(s) from a tree.
9054 ///
9055 /// funcname is a TF1 function.
9056 ///
9057 /// See TTree::Draw for explanations of the other parameters.
9058 ///
9059 /// Fit the variable varexp using the function funcname using the
9060 /// selection cuts given by selection.
9061 ///
9062 /// The list of fit options is given in parameter option.
9063 ///
9064 /// - option = "Q" Quiet mode (minimum printing)
9065 /// - option = "V" Verbose mode (default is between Q and V)
9066 /// - option = "E" Perform better Errors estimation using Minos technique
9067 /// - option = "M" More. Improve fit results
9068 ///
9069 /// You can specify boundary limits for some or all parameters via
9070 /// ~~~ {.cpp}
9071 /// func->SetParLimits(p_number, parmin, parmax);
9072 /// ~~~
9073 /// if parmin>=parmax, the parameter is fixed
9074 ///
9075 /// Note that you are not forced to fix the limits for all parameters.
9076 /// For example, if you fit a function with 6 parameters, you can do:
9077 /// ~~~ {.cpp}
9078 /// func->SetParameters(0,3.1,1.e-6,0.1,-8,100);
9079 /// func->SetParLimits(4,-10,-4);
9080 /// func->SetParLimits(5, 1,1);
9081 /// ~~~
9082 /// With this setup:
9083 ///
9084 /// - Parameters 0->3 can vary freely
9085 /// - Parameter 4 has boundaries [-10,-4] with initial value -8
9086 /// - Parameter 5 is fixed to 100.
9087 ///
9088 /// For the fit to be meaningful, the function must be self-normalized.
9089 ///
9090 /// i.e. It must have the same integral regardless of the parameter
9091 /// settings. Otherwise the fit will effectively just maximize the
9092 /// area.
9093 ///
9094 /// It is mandatory to have a normalization variable
9095 /// which is fixed for the fit. e.g.
9096 /// ~~~ {.cpp}
9097 /// TF1* f1 = new TF1("f1", "gaus(0)/sqrt(2*3.14159)/[2]", 0, 5);
9098 /// f1->SetParameters(1, 3.1, 0.01);
9099 /// f1->SetParLimits(0, 1, 1); // fix the normalization parameter to 1
9100 /// data->UnbinnedFit("f1", "jpsimass", "jpsipt>3.0");
9101 /// ~~~
9102 /// 1, 2 and 3 Dimensional fits are supported. See also TTree::Fit
9103 ///
9104 /// Return status:
9105 ///
9106 /// - The function return the status of the fit in the following form
9107 /// fitResult = migradResult + 10*minosResult + 100*hesseResult + 1000*improveResult
9108 /// - The fitResult is 0 is the fit is OK.
9109 /// - The fitResult is negative in case of an error not connected with the fit.
9110 /// - The number of entries used in the fit can be obtained via mytree.GetSelectedRows();
9111 /// - If the number of selected entries is null the function returns -1
9112 
9113 Int_t TTree::UnbinnedFit(const char* funcname, const char* varexp, const char* selection, Option_t* option, Long64_t nentries, Long64_t firstentry)
9115  GetPlayer();
9116  if (fPlayer) {
9117  return fPlayer->UnbinnedFit(funcname, varexp, selection, option, nentries, firstentry);
9118  }
9119  return -1;
9120 }
9121 
9122 ////////////////////////////////////////////////////////////////////////////////
9123 /// Replace current attributes by current style.
9124 
9127  if (gStyle->IsReading()) {
9136  } else {
9145  }
9146 }
9147 
9148 ////////////////////////////////////////////////////////////////////////////////
9149 /// Write this object to the current directory. For more see TObject::Write
9150 /// Write calls TTree::FlushBaskets before writing the tree.
9151 
9152 Int_t TTree::Write(const char *name, Int_t option, Int_t bufsize) const
9154  FlushBaskets();
9155  return TObject::Write(name, option, bufsize);
9156 }
9157 
9158 ////////////////////////////////////////////////////////////////////////////////
9159 /// Write this object to the current directory. For more see TObject::Write
9160 /// If option & kFlushBasket, call FlushBasket before writing the tree.
9161 
9162 Int_t TTree::Write(const char *name, Int_t option, Int_t bufsize)
9164  return ((const TTree*)this)->Write(name, option, bufsize);
9165 }
9166 
9167 ////////////////////////////////////////////////////////////////////////////////
9168 /// \class TTreeFriendLeafIter
9169 ///
9170 /// Iterator on all the leaves in a TTree and its friend
9171 
9173 
9174 ////////////////////////////////////////////////////////////////////////////////
9175 /// Create a new iterator. By default the iteration direction
9176 /// is kIterForward. To go backward use kIterBackward.
9177 
9179 : fTree(const_cast<TTree*>(tree))
9180 , fLeafIter(0)
9181 , fTreeIter(0)
9182 , fDirection(dir)
9183 {
9184 }
9185 
9186 ////////////////////////////////////////////////////////////////////////////////
9187 /// Copy constructor. Does NOT copy the 'cursor' location!
9188 
9190 : TIterator(iter)
9191 , fTree(iter.fTree)
9192 , fLeafIter(0)
9193 , fTreeIter(0)
9194 , fDirection(iter.fDirection)
9195 {
9196 }
9197 
9198 ////////////////////////////////////////////////////////////////////////////////
9199 /// Overridden assignment operator. Does NOT copy the 'cursor' location!
9200 
9203  if (this != &rhs && rhs.IsA() == TTreeFriendLeafIter::Class()) {
9204  const TTreeFriendLeafIter &rhs1 = (const TTreeFriendLeafIter &)rhs;
9205  fDirection = rhs1.fDirection;
9206  }
9207  return *this;
9208 }
9209 
9210 ////////////////////////////////////////////////////////////////////////////////
9211 /// Overridden assignment operator. Does NOT copy the 'cursor' location!
9212 
9215  if (this != &rhs) {
9216  fDirection = rhs.fDirection;
9217  }
9218  return *this;
9219 }
9220 
9221 ////////////////////////////////////////////////////////////////////////////////
9222 /// Go the next friend element
9223 
9226  if (!fTree) return 0;
9227 
9228  TObject * next;
9229  TTree * nextTree;
9230 
9231  if (!fLeafIter) {
9232  TObjArray *list = fTree->GetListOfLeaves();
9233  if (!list) return 0; // Can happen with an empty chain.
9234  fLeafIter = list->MakeIterator(fDirection);
9235  if (!fLeafIter) return 0;
9236  }
9237 
9238  next = fLeafIter->Next();
9239  if (!next) {
9240  if (!fTreeIter) {
9241  TCollection * list = fTree->GetListOfFriends();
9242  if (!list) return next;
9243  fTreeIter = list->MakeIterator(fDirection);
9244  if (!fTreeIter) return 0;
9245  }
9246  TFriendElement * nextFriend = (TFriendElement*) fTreeIter->Next();
9247  ///nextTree = (TTree*)fTreeIter->Next();
9248  if (nextFriend) {
9249  nextTree = const_cast<TTree*>(nextFriend->GetTree());
9250  if (!nextTree) return Next();
9251  SafeDelete(fLeafIter);
9252  fLeafIter = nextTree->GetListOfLeaves()->MakeIterator(fDirection);
9253  if (!fLeafIter) return 0;
9254  next = fLeafIter->Next();
9255  }
9256  }
9257  return next;
9258 }
9259 
9260 ////////////////////////////////////////////////////////////////////////////////
9261 /// Returns the object option stored in the list.
9262 
9265  if (fLeafIter) return fLeafIter->GetOption();
9266  return "";
9267 }
A zero length substring is legal.
Definition: TString.h:75
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 void UpdateAddress()
Definition: TBranch.h:223
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:4589
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:778
Double_t fWeight
Tree weight (see TTree::SetWeight)
Definition: TTree.h:87
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:1272
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
Bool_t IsReading() const
Definition: TBuffer.h:81
virtual void AddTotBytes(Int_t tot)
Definition: TTree.h:295
TTreeCache * GetReadCache(TFile *file, Bool_t create=kFALSE)
Find and return the TTreeCache registered with the file and which may contain branches for us...
Definition: TTree.cxx:5982
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:404
Bool_t CanSplit() const
Return true if the data member of this TClass can be saved separately.
Definition: TClass.cxx:2232
TList * GetListOfBases()
Return list containing the TBaseClass(es) of a class.
Definition: TClass.cxx:3452
virtual TTree * CopyTree(const char *selection, Option_t *option="", Long64_t nentries=kMaxEntries, Long64_t firstentry=0)=0
TStreamerInfo * BuildStreamerInfo(TClass *cl, void *pointer=0, Bool_t canOptimize=kTRUE)
Build StreamerInfo for class cl.
Definition: TTree.cxx:2560
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:109
Principal Components Analysis (PCA)
Definition: TPrincipal.h:20
virtual Int_t FillImpl(ROOT::Internal::TBranchIMTHelper *)
Loop on all leaves of this branch to fill Basket buffer.
Definition: TBranch.cxx:810
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:177
virtual TList * GetListOfKeys() const
Definition: TDirectory.h:148
virtual void Delete(Option_t *option="")
Remove all objects from the list AND delete all heap based objects.
Definition: TList.cxx:409
virtual void UpdateFile()
Refresh the value of fDirectory (i.e.
Definition: TBranch.cxx:2762
virtual void Info(const char *method, const char *msgfmt,...) const
Issue info message.
Definition: TObject.cxx:847
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:47
virtual void SetAddress(void *add)
Set address of this branch.
Definition: TBranch.cxx:2148
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:6686
Bool_t MemoryFull(Int_t nbytes)
Check if adding nbytes to memory we are still below MaxVirtualsize.
Definition: TTree.cxx:6493
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:1480
virtual Int_t MakeCode(const char *filename=0)
Generate a skeleton function for this tree.
Definition: TTree.cxx:6296
long long Long64_t
Definition: RtypesCore.h:69
Abstract interface for Tree Index.
Definition: TVirtualIndex.h:29
virtual Int_t GetBasketSize() const
Definition: TBranch.h:156
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:7195
Namespace for new ROOT classes and functions.
Definition: StringConv.hxx:21
virtual Int_t StopCacheLearningPhase()
Stop the cache learning phase.
Definition: TTree.cxx:8863
virtual void SetBranchStatus(const char *bname, Bool_t status=1, UInt_t *found=0)
Set branch status to Process or DoNotProcess.
Definition: TTree.cxx:8019
virtual void IncrementTotalBuffers(Int_t nbytes)
Definition: TTree.h:460
short Version_t
Definition: RtypesCore.h:61
virtual void Delete(Option_t *option="")
Delete this tree from memory or/and disk.
Definition: TTree.cxx:3571
Bool_t EqualTo(const char *cs, ECaseCompare cmp=kExact) const
Definition: TString.h:581
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:181
TLine * line
static Int_t fgBranchStyle
Old/New branch style.
Definition: TTree.h:138
virtual void AddZipBytes(Int_t zip)
Definition: TTree.h:296
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:6100
virtual void Clear(Option_t *option="")
Remove all objects from the array.
Definition: TObjArray.cxx:298
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:1455
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:6734
static Long64_t GetMaxTreeSize()
Static function which returns the tree file size limit in bytes.
Definition: TTree.cxx:5929
virtual void SetParallelUnzip(Bool_t opt=kTRUE, Float_t RelSize=-1)
Enable or disable parallel unzipping of Tree buffers.
Definition: TTree.cxx:8704
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:6637
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:6662
TTree()
Default constructor and I/O constructor.
Definition: TTree.cxx:652
virtual TTree * GetFriend(const char *) const
Return a pointer to the TTree friend whose name or alias is &#39;friendname.
Definition: TTree.cxx:5648
void GetObject(const char *namecycle, T *&ptr)
Definition: TDirectory.h:137
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:329
All ROOT classes may have RTTI (run time type identification) support added.
Definition: TDataMember.h:31
virtual Long64_t GetEntriesFast() const
Definition: TTree.h:383
const char * Size
Definition: TXMLSetup.cxx:56
TBuffer * fTransientBuffer
! Pointer to the current transient buffer.
Definition: TTree.h:130
virtual void Flush()
Synchronize a file&#39;s in-memory and on-disk states.
Definition: TFile.cxx:1086
virtual void Print(Option_t *option="") const
Print a summary of the tree contents.
Definition: TTree.cxx:6841
virtual void SetCacheRead(TFileCacheRead *cache, TObject *tree=0, ECacheAction action=kDisconnect)
Set a pointer to the read cache.
Definition: TFile.cxx:2201
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:1721
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:4817
const Ssiz_t kNPOS
Definition: RtypesCore.h:115
TString & ReplaceAll(const TString &s1, const TString &s2)
Definition: TString.h:640
R__EXTERN TStyle * gStyle
Definition: TStyle.h:402
TList * fFriends
pointer to list of friend elements
Definition: TTree.h:123
void SetHistLineWidth(Width_t width=1)
Definition: TStyle.h:357
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:6822
Bool_t TestBit(UInt_t f) const
Definition: TObject.h:159
virtual Int_t Fill()
Fill all branches.
Definition: TTree.cxx:4383
Int_t GetMakeClass() const
Definition: TTree.h:412
virtual TEntryList * GetEntryList()
Returns the entry list, set to this tree.
Definition: TTree.cxx:5528
virtual void SetName(const char *name)
Set the name of the TNamed.
Definition: TNamed.cxx:131
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:711
static void SetBranchStyle(Int_t style=1)
Set the current branch style.
Definition: TTree.cxx:8145
A specialized TFileCacheRead object for a TTree.
Definition: TTreeCache.h:30
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:5854
TTree * fTree
Definition: TTree.h:175
const std::type_info * GetTypeInfo() const
Definition: TClass.h:441
static Int_t SetParallelUnzip(TTreeCacheUnzip::EParUnzipMode option=TTreeCacheUnzip::kEnable)
Static function that (de)activates multithreading unzipping.
static char DataTypeToChar(EDataType datatype)
Definition: TTree.cxx:429
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:4360
virtual void PrintValue(Int_t i=0) const
Definition: TLeaf.h:118
A ROOT file is a suite of consecutive data records (TKey instances) with a well defined format...
Definition: TFile.h:46
const char * GetTypeName() const
Get type of data member, e,g.: "class TDirectory*" -> "TDirectory".
virtual Int_t GetEntries() const
Definition: TCollection.h:86
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:5764
virtual TList * GetListOfFriends() const
Definition: TTree.h:407
virtual Long64_t GetAutoFlush() const
Definition: TTree.h:366
Buffer base class used for serializing objects.
Definition: TBuffer.h:40
Regular expression class.
Definition: TRegexp.h:31
TDirectory * fDirectory
! Pointer to directory holding this tree
Definition: TTree.h:114
constexpr Float_t kNEntriesResortInv
Definition: TTree.cxx:418
Int_t fMakeClass
! not zero when processing code generated by MakeClass
Definition: TTree.h:111
#define R__ASSERT(e)
Definition: TError.h:96
virtual TBasket * CreateBasket(TBranch *)
Create a basket for this tree and given branch.
Definition: TTree.cxx:3555
virtual Int_t CheckByteCount(UInt_t startpos, UInt_t bcnt, const TClass *clss)=0
#define gROOT
Definition: TROOT.h:375
TList * GetListOfDataMembers(Bool_t load=kTRUE)
Return list containing the TDataMembers of a class.
Definition: TClass.cxx:3562
Ssiz_t Index(const char *pat, Ssiz_t i=0, ECaseCompare cmp=kExact) const
Definition: TString.h:587
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:7830
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:5321
virtual Int_t ReadKeys(Bool_t=kTRUE)
Definition: TDirectory.h:172
virtual Int_t GetOffset() const
Definition: TLeaf.h:74
Basic string class.
Definition: TString.h:129
TVirtualCollectionProxy * GetCollectionProxy() const
Return the proxy describing the collection (if any).
Definition: TClass.cxx:2814
virtual void SetAddress(void *addobj)
Point this branch at an object.
Data member is a pointer to an array of basic types.
Definition: TLeaf.h:54
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:6424
virtual Long64_t GetEntryNumberWithBestIndex(Long64_t major, Long64_t minor) const =0
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:1099
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:4541
int Int_t
Definition: RtypesCore.h:41
bool Bool_t
Definition: RtypesCore.h:59
TArc * a
Definition: textangle.C:12
R__EXTERN TVirtualMutex * gROOTMutex
Definition: TROOT.h:57
virtual void Browse(TBrowser *)
Browse content of the TTree.
Definition: TTree.cxx:2520
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:8636
Int_t fScanField
Number of runs before prompting in Scan.
Definition: TTree.h:89
#define NULL
Definition: RtypesCore.h:88
virtual TTree * CloneTree(Long64_t nentries=-1, Option_t *option="")
Create a clone of this tree and copy nentries.
Definition: TTree.cxx:3012
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:3543
virtual void KeepCircular()
Keep a maximum of fMaxEntries in memory.
Definition: TTree.cxx:6064
TArrayD fIndexValues
Sorted index values.
Definition: TTree.h:120
void SetAutoCreated(Bool_t val)
Definition: TTreeCache.h:97
virtual EDataType GetType() const =0
constexpr Int_t kNEntriesResort
Definition: TTree.cxx:417
virtual Long64_t GetEntries(const char *)=0
Long64_t fMaxEntryLoop
Maximum number of entries to process.
Definition: TTree.h:95
TVirtualTreePlayer * GetPlayer()
Load the TTreePlayer (if not already done).
Definition: TTree.cxx:5968
virtual void SetMaxVirtualSize(Long64_t size=0)
Definition: TTree.h:542
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:7098
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:332
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:2752
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...
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:156
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:687
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
Find an object in this list using its name.
Definition: TList.cxx:501
virtual void Refresh()
Refresh contents of this tree and its branches from the current status on disk.
Definition: TTree.cxx:7492
Width_t GetHistLineWidth() const
Definition: TStyle.h:221
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:8602
virtual Double_t GetMinimum(const char *columname)
Return minimum of column with name columname.
Definition: TTree.cxx:5939
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:3643
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:3909
Int_t Length() const
Definition: TBuffer.h:94
virtual void SetTree(TTree *tree)
Definition: TBranch.h:221
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:146
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:8848
virtual Long64_t Merge(TCollection *list, Option_t *option="")
Merge the trees in the TList into this tree.
Definition: TTree.cxx:6550
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:5601
TList * fAliases
List of aliases for expressions based on the tree branches.
Definition: TTree.h:117
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:1703
virtual Long64_t DrawSelect(const char *varexp, const char *selection, Option_t *option, Long64_t nentries, Long64_t firstentry)=0
virtual Int_t FlushBaskets() const
Write to disk all the basket that have not yet been individually written.
Definition: TTree.cxx:4864
TObject * Last() const
Return the object in the last filled slot. Returns 0 if no entries.
Definition: TObjArray.cxx:479
#define SafeDelete(p)
Definition: RConfig.h:499
virtual Long64_t GetCacheSize() const
Definition: TTree.h:372
Bool_t IsBasic() const
Return true if data member is a basic type, e.g. char, int, long...
virtual TObjArray * GetListOfBranches()
Definition: TTree.h:405
Helper class to iterate over cluster of baskets.
Definition: TTree.h:241
TVirtualTreePlayer * fPlayer
! Pointer to current Tree player
Definition: TTree.h:126
virtual const char * ClassName() const
Returns name of class to which the object belongs.
Definition: TObject.cxx:135
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:6023
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:7745
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:2345
Bool_t IsAutoCreated() const
Definition: TTreeCache.h:85
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:3374
virtual Int_t SetBranchAddress(const char *bname, void *add, TBranch **ptr=0)
Change branch address, dealing with clone trees properly.
Definition: TTree.cxx:7873
void SetHistFillColor(Color_t color=1)
Definition: TStyle.h:353
Int_t fNfill
! Local for EntryLoop
Definition: TTree.h:107
virtual Double_t GetValue(Int_t i=0) const
Definition: TLeaf.h:117
Int_t bsize[]
Definition: SparseFit4.cxx:31
virtual void SetObject(const char *name, const char *title)
Change the name and title of this tree.
Definition: TTree.cxx:8673
virtual Bool_t IsWritable() const
Definition: TDirectory.h:161
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:5564
virtual Bool_t Notify()
This method must be overridden to handle object notification.
Definition: TObject.cxx:499
virtual Long64_t GetReadEntry() const
Definition: TTree.h:424
virtual const char * GetAlias(const char *aliasName) const
Returns the expanded value of the alias. Search in the friends if any.
Definition: TTree.cxx:4938
virtual TLeaf * GetLeaf(const char *name) const
Return pointer to the 1st Leaf named name in thisBranch.
Definition: TBranch.cxx:1552
virtual Long64_t LoadTree(Long64_t entry)
Set current entry.
Definition: TTree.cxx:6121
Bool_t fCacheUserSet
! true if the cache setting was explicitly given by user
Definition: TTree.h:132
virtual void SetTreeIndex(TVirtualIndex *index)
The current TreeIndex is replaced by the new index.
Definition: TTree.cxx:8735
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:93
static Int_t GetBranchStyle()
Static function returning the current branch style.
Definition: TTree.cxx:5090
virtual Int_t BuildIndex(const char *majorname, const char *minorname="0")
Build a Tree Index (default is TTreeIndex).
Definition: TTree.cxx:2545
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:9114
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:2393
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:1893
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:5549
virtual void Show(Long64_t entry=-1, Int_t lenmax=20)
Print values of all active leaves for entry.
Definition: TTree.cxx:8774
virtual TBranch * FindBranch(const char *name)
Find the immediate sub-branch with passed name.
Definition: TBranch.cxx:981
TBranchRef * fBranchRef
Branch supporting the TRefTable (if any)
Definition: TTree.h:128
virtual Int_t MakeClass(const char *classname=0, Option_t *option="")
Generate a skeleton analysis class for this tree.
Definition: TTree.cxx:6263
virtual const char * Getenv(const char *env)
Get environment variable.
Definition: TSystem.cxx:1634
virtual TClusterIterator GetClusterIterator(Long64_t firstentry)
Return an iterator over the cluster of baskets starting at firstentry.
Definition: TTree.cxx:5152
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:219
const Int_t kDoNotProcess
Definition: TBranch.h:45
UInt_t fFriendLockStatus
! Record which method is locking the friend recursion
Definition: TTree.h:129
virtual void Append(TObject *obj, Bool_t replace=kFALSE)
Append object to this directory.
Long_t GetThisOffset() const
Definition: TRealData.h:55
const int maxsize
virtual Int_t MakeClass(const char *classname, const char *option)=0
Int_t fTimerInterval
Timer interval in milliseconds.
Definition: TTree.h:88
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:1193
TDataType * GetDataType() const
Definition: TDataMember.h:72
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:7648
Long64_t fFlushedBytes
Number of auto-flushed bytes.
Definition: TTree.h:86
virtual Int_t GetLenType() const
Definition: TLeaf.h:70
TObjArray * GetListOfBranches()
Definition: TBranch.h:182
UInt_t fNEntriesSinceSorting
! Number of entries processed since the last re-sorting of branches
Definition: TTree.h:134
Ssiz_t First(char c) const
Find first occurrence of a character c.
Definition: TString.cxx:477
Specialization of TTreeCache for parallel Unzipping.
virtual TList * GetList() const
Definition: TDirectory.h:147
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:5900
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:7531
virtual void SetAddress(void *add=0)
Definition: TLeaf.h:119
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:6007
std::atomic< Long64_t > fIMTZipBytes
! Zip bytes for the IMT flush baskets.
Definition: TTree.h:148
virtual void SetCacheLearnEntries(Int_t n=10)
Interface to TTreeCache to set the number of entries for the learning phase.
Definition: TTree.cxx:8338
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:84
virtual TFile * GetFile() const
Definition: TDirectory.h:145
Long64_t fDebugMax
! Last entry number to debug
Definition: TTree.h:110
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:1399
virtual TTree * GetTree() const
Definition: TTree.h:432
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:8539
void Expand(Int_t newsize, Bool_t copy=kTRUE)
Expand (or shrink) the I/O buffer to newsize bytes.
Definition: TBuffer.cxx:201
virtual Int_t GetTreeNumber() const
Definition: TTree.h:434
void UseCurrentStyle()
Replace current attributes by current style.
Definition: TTree.cxx:9126
A specialized string object used for TTree selections.
Definition: TCut.h:25
A doubly linked list.
Definition: TList.h:43
virtual void ResetAfterMerge(TFileMergeInfo *)
Reset a Branch.
Definition: TBranch.cxx:2064
virtual TBranch * GetBranch(const char *name)
Return pointer to the branch with the given name in this tree or its friends.
Definition: TTree.cxx:4979
Bool_t fCacheDoAutoInit
! true if cache auto creation or resize check is needed
Definition: TTree.h:131
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:1239
Int_t GetType() const
Definition: TDataType.h:68
Int_t Fill()
Definition: TBranch.h:144
TObjArray fLeaves
Direct pointers to individual branch leaves.
Definition: TTree.h:116
Long64_t * fClusterRangeEnd
[fNClusterRange] Last entry of a cluster range.
Definition: TTree.h:100
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:1943
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:92
virtual Long64_t GetEntryNumber(Long64_t entry) const
Return entry number corresponding to entry.
Definition: TTree.cxx:5539
Int_t fN
Definition: TArray.h:38
TEntryList * fEntryList
! Pointer to event selection list (if one)
Definition: TTree.h:119
virtual Int_t GetLen() const
Return the number of effective elements of this leaf.
Definition: TLeaf.cxx:279
virtual Long64_t GetAutoSave() const
Definition: TTree.h:367
void SetParentClass(TClass *clparent)
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:173
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:9163
virtual void SetEstimate(Long64_t nentries=1000000)
Set number of entries to estimate variable limits.
Definition: TTree.cxx:8580
virtual void SetOffset(Int_t offset=0)
Definition: TBranch.h:219
virtual TObject * First() const
Return the first object in the list. Returns 0 when list is empty.
Definition: TList.cxx:561
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:484
void SetHistFillStyle(Style_t styl=0)
Definition: TStyle.h:355
void SetCompressionSettings(Int_t settings=1)
Set compression settings.
Definition: TBranch.cxx:2271
R__EXTERN TSystem * gSystem
Definition: TSystem.h:539
Long64_t fChainOffset
! Offset of 1st entry of this Tree in a TChain
Definition: TTree.h:103
~TFriendLock()
Restore the state of tree the same as before we set the lock.
Definition: TTree.cxx:510
Long64_t * fClusterSize
[fNClusterRange] Number of entries in each cluster for a given range.
Definition: TTree.h:101
virtual void WriteStreamerInfo()
Write the list of TStreamerInfo as a single object in this file The class Streamer description for al...
Definition: TFile.cxx:3612
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:8921
virtual Long64_t GetEntryNumberWithIndex(Long64_t major, Long64_t minor=0) const
Return entry number corresponding to major and minor number.
Definition: TTree.cxx:5584
TVirtualPerfStats * fPerfStats
! pointer to the current perf stats object
Definition: TTree.h:124
TClass * GetActualClass(const void *object) const
Return a pointer the the real class of the object.
Definition: TClass.cxx:2528
virtual TIterator * MakeIterator(Bool_t dir=kIterForward) const =0
TTree * GetTree() const
Definition: TTreeCache.h:84
virtual TObject * RemoveAt(Int_t idx)
Remove object at index idx.
Definition: TObjArray.cxx:630
virtual Int_t GetValue(const char *name, Int_t dflt)
Returns the integer value for a resource.
Definition: TEnv.cxx:482
virtual Int_t ReadTObject(TObject *, const char *)
Definition: TDirectory.h:173
virtual TObject * Remove(TObject *obj)
Remove object from the list.
Definition: TList.cxx:679
Long64_t fReadEntry
! Number of the entry being processed
Definition: TTree.h:104
virtual TVirtualIndex * GetTreeIndex() const
Definition: TTree.h:433
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:436
Int_t GetWriteBasket() const
Definition: TBranch.h:175
virtual ~TTree()
Destructor.
Definition: TTree.cxx:831
TDataMember * GetDataMember() const
Definition: TRealData.h:53
Collection abstract base class.
Definition: TCollection.h:42
void Destructor(void *obj, Bool_t dtorOnly=kFALSE)
Explicitly call destructor for object.
Definition: TClass.cxx:5063
TList * fUserInfo
pointer to a list of user objects associated to this Tree
Definition: TTree.h:125
TObjArray fBranches
List of Branches.
Definition: TTree.h:115
void Form(const char *fmt,...)
Formats a string using a printf style format descriptor.
Definition: TString.cxx:2332
unsigned int UInt_t
Definition: RtypesCore.h:42
TMarker * m
Definition: textangle.C:8
Int_t GetEntriesFast() const
Definition: TObjArray.h:64
virtual void Error(const char *method, const char *msgfmt,...) const
Issue error message.
Definition: TObject.cxx:873
TFile * GetCurrentFile() const
Return pointer to the current file.
Definition: TTree.cxx:5163
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:657
Ssiz_t Length() const
Definition: TString.h:388
virtual void MakeFree(Long64_t first, Long64_t last)
Mark unused bytes on the file.
Definition: TFile.cxx:1398
virtual void Append(TObject *obj, Bool_t replace=kFALSE)
Append object to this directory.
Definition: TDirectory.cxx:153
virtual TLeaf * GetLeafCount() const
Definition: TLeaf.h:66
Manages buffers for branches of a Tree.
Definition: TBasket.h:36
virtual void * GetValuePointer() const
Definition: TLeaf.h:75
TSubString Strip(EStripType s=kTrailing, char c=' ') const
Return a substring of self stripped at beginning and/or end.
Definition: TString.cxx:1080
Int_t GetMaxBaskets() const
Definition: TBranch.h:184
A TEventList object is a list of selected events (entries) in a TTree.
Definition: TEventList.h:31
TLine * l
Definition: textangle.C:4
virtual TLeaf * FindLeaf(const char *name)
Find leaf..
Definition: TTree.cxx:4661
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:1291
Bool_t CanIgnoreTObjectStreamer()
Definition: TClass.h:348
TArrayI fIndex
Index of sorted values.
Definition: TTree.h:121
The ROOT global object gROOT contains a list of all defined classes.
Definition: TClass.h:71
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...
ROOT::ESTLType GetCollectionType() const
Return the &#39;type&#39; of the STL the TClass is representing.
Definition: TClass.cxx:2803
virtual TObject * At(Int_t idx) const
Returns the object at position idx. Returns 0 if idx is out of range.
Definition: TList.cxx:315
Bool_t fIMTEnabled
! true if implicit multi-threading is enabled for this tree
Definition: TTree.h:133
Option_t * GetOption() const
Returns the object option stored in the list.
Definition: TTree.cxx:9264
virtual TBranchRef * GetBranchRef() const
Definition: TTree.h:369
Bool_t InheritsFrom(const char *cl) const
Return kTRUE if this class inherits from a class with name "classname".
Definition: TClass.cxx:4602
void SetName(const char *name)
Definition: TCollection.h:111
virtual void ResetBranchAddress(TBranch *)
Tell all of our branches to set their addresses to zero.
Definition: TTree.cxx:7619
Bool_t fDirection
iteration direction
Definition: TTree.h:591
TEventList * fEventList
! Pointer to event selection list (if one)
Definition: TTree.h:118
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:2223
virtual const char * GetTreeName() const
virtual Bool_t GetBranchStatus(const char *branchname) const
Return status of branch with name branchname.
Definition: TTree.cxx:5075
if object destructor must call RecursiveRemove()
Definition: TObject.h:59
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:94
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:1105
virtual void KeepCircular(Long64_t maxEntries)
keep a maximum of fMaxEntries in memory
Definition: TBranch.cxx:1758
Each class (see TClass) has a linked list of its base class(es).
Definition: TBaseClass.h:31
char GetNewlineValue(std::istream &inputStream)
Determine which newline this file is using.
Definition: TTree.cxx:7168
virtual TObjLink * FirstLink() const
Definition: TList.h:97
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:1234
#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:1028
void InitializeBranchLists(bool checkLeafCount)
Divides the top-level branches into two vectors: (i) branches to be processed sequentially and (ii) b...
Definition: TTree.cxx:5460
Long64_t fAutoSave
Autosave tree when fAutoSave entries written or -fAutoSave (compressed) bytes produced.
Definition: TTree.h:97
#define R__LOCKGUARD2(mutex)
const Bool_t kFALSE
Definition: RtypesCore.h:92
virtual void SaveSelf(Bool_t=kFALSE)
Definition: TDirectory.h:179
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:2195
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:2748
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:8401
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:7035
static unsigned int total
static const Ssiz_t kNPOS
Definition: TString.h:250
TString & Remove(Ssiz_t pos)
Definition: TString.h:621
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:4315
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:8616
virtual void SetWeight(Double_t w=1, Option_t *option="")
Set tree weight.
Definition: TTree.cxx:8763
Color_t GetHistFillColor() const
Definition: TStyle.h:217
Version_t GetClassVersion() const
Definition: TClass.h:372
TObjArray * Tokenize(const TString &delim) const
This function is used to isolate sequential tokens in a TString.
Definition: TString.cxx:2251
Long64_t Next()
Move on to the next cluster and return the starting entry of this next cluster.
Definition: TTree.cxx:601
TIterator * MakeIterator(Bool_t dir=kIterForward) const
Returns an array iterator.
Definition: TObjArray.cxx:591
virtual void SetDirectory(TDirectory *dir)
Change the tree&#39;s directory.
Definition: TTree.cxx:8439
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:6213
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:96
virtual TObject * Remove(TObject *)
Remove an object from the in-memory list.
virtual Int_t GetMaximum() const
Definition: TLeaf.h:71
#define ClassImp(name)
Definition: Rtypes.h:336
double f(double x)
Bool_t IsZombie() const
Definition: TObject.h:122
virtual void StartViewer(Int_t ww, Int_t wh)=0
virtual void SetEntryList(TEntryList *list, Option_t *opt="")
Set an EntryList.
Definition: TTree.cxx:8516
TIterator & operator=(const TIterator &rhs)
Overridden assignment operator. Does NOT copy the &#39;cursor&#39; location!
Definition: TTree.cxx:9202
virtual void ResetAddress()
Reset the address of the branch.
Definition: TBranch.cxx:2117
virtual TKey * GetKey(const char *, Short_t=9999) const
Definition: TDirectory.h:146
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:875
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:5102
void SetHistLineStyle(Style_t styl=0)
Definition: TStyle.h:356
Long64_t fTotBytes
Total number of bytes in all branches before compression.
Definition: TTree.h:83
virtual void WaitFinishPrefetch()
Color_t GetHistLineColor() const
Definition: TStyle.h:218
std::vector< TBranch * > fSeqBranches
! Branches to be processed sequentially when IMT is on
Definition: TTree.h:136
Describe directory structure in memory.
Definition: TDirectory.h:34
virtual void SetPerfStats(TVirtualPerfStats *perf)
Set perf stats.
Definition: TTree.cxx:8718
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:135
TDirectory * GetDirectory() const
Definition: TTree.h:380
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:8897
void SortBranchesByTime()
Sorts top-level branches by the last average task time recorded per branch.
Definition: TTree.cxx:5508
R__EXTERN TEnv * gEnv
Definition: TEnv.h:170
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:7149
TList * GetListOfRealData() const
Definition: TClass.h:395
Bool_t HasDataMemberInfo() const
Definition: TClass.h:361
TNamed()
Definition: TNamed.h:36
Long64_t fAutoFlush
Auto-flush tree when fAutoFlush entries written or -fAutoFlush (compressed) bytes produced...
Definition: TTree.h:98
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:7629
virtual void Draw(Option_t *opt)
Default Draw method for all objects.
Definition: TTree.h:355
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:91
Bool_t Contains(const char *pat, ECaseCompare cmp=kExact) const
Definition: TString.h:572
void Browse(TBrowser *b)
Browse this collection (called by TBrowser).
TObjArray * GetListOfLeaves()
Definition: TBranch.h:183
Long64_t fEstimate
Number of entries to estimate histogram limits.
Definition: TTree.h:99
Int_t BufferSize() const
Definition: TBuffer.h:92
static void SetUnzipRelBufferSize(Float_t relbufferSize)
static function: Sets the unzip relatibe buffer size
UInt_t fMethodBit
Definition: TTree.h:176
Helper class to prevent infinite recursion in the usage of TTree Friends.
Definition: TTree.h:172
static TClass * GetClass(const char *name, Bool_t load=kTRUE, Bool_t silent=kFALSE)
Static method returning pointer to TClass of the specified class name.
Definition: TClass.cxx:2885
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:8161
Int_t fDebug
! Debug level
Definition: TTree.h:108
EOnIndexError
Definition: TTree.cxx:3271
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:8187
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:381
Int_t GetKeylen() const
Definition: TKey.h:80
Bool_t IsPersistent() const
Definition: TDataMember.h:87
Bool_t IsNull() const
Definition: TString.h:385
TClass * GetClass() const
Definition: TClonesArray.h:57
virtual TObject * Clone(const char *newname="") const
Make a clone of an object using the Streamer facility.
Definition: TNamed.cxx:65
virtual void SetBasketSize(const char *bname, Int_t buffsize=16000)
Set a branch&#39;s basket size.
Definition: TTree.cxx:7846
virtual TFile * GetFile()
Return pointer to TFile containing this friend TTree.
virtual TBranch * BranchRef()
Build the optional branch supporting the TRefTable.
Definition: TTree.cxx:2147
virtual void ResetAfterMerge(TFileMergeInfo *)
Resets the state of this TTree after a merge (keep the customization but forget the data)...
Definition: TTree.cxx:7588
virtual Bool_t SetAlias(const char *aliasName, const char *aliasFormula)
Set a tree variable alias.
Definition: TTree.cxx:7690
Int_t fFileNumber
! current file number (if file extensions)
Definition: TTree.h:112
Mother of all ROOT objects.
Definition: TObject.h:37
TObjArray * GetElements() const
Int_t fUpdate
Update frequency for EntryLoop.
Definition: TTree.h:90
virtual void ReadValue(std::istream &, Char_t=' ')
Definition: TLeaf.h:90
Bool_t IsReading() const
Definition: TStyle.h:274
virtual Long64_t GetEND() const
Definition: TFile.h:202
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:1660
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:2287
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:408
virtual void SetFile(TFile *file=0)
Set file where this branch writes/reads its buffers.
Definition: TBranch.cxx:2329
Long64_t fEntries
Number of entries.
Definition: TTree.h:81
Bool_t IsTObject() const
Return kTRUE is the class inherits from TObject.
Definition: TClass.cxx:5575
TList * fClones
! List of cloned trees which share our addresses
Definition: TTree.h:127
virtual void Refresh(TBranch *b)
Refresh this branch using new information in b This function is called by TTree::Refresh.
Definition: TBranch.cxx:1974
Long64_t GetEntries() const
Definition: TBranch.h:187
Style_t GetHistLineStyle() const
Definition: TStyle.h:220
virtual Int_t MakeSelector(const char *selector=0, Option_t *option="")
Generate skeleton selector class for this tree.
Definition: TTree.cxx:6478
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:923
virtual Long64_t GetTotBytes() const
Definition: TTree.h:431
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:435
virtual Int_t DropBuffers()
Drop buffers of this basket if it is not the current basket.
Definition: TBasket.cxx:187
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:77
#define R__unlikely(expr)
Definition: RConfig.h:539
Bool_t IsImplicitMTEnabled()
Returns true if the implicit multi-threading in ROOT is enabled.
Definition: TROOT.cxx:552
TClusterIterator(TTree *tree, Long64_t firstEntry)
Regular constructor.
Definition: TTree.cxx:527
virtual void RecursiveRemove(TObject *obj)
Remove object from this collection and recursively remove the object from all other objects (and coll...
Definition: TList.cxx:639
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:2023
A TFriendElement TF describes a TTree object TF in a file.
virtual Long64_t GetZipBytes() const
Definition: TTree.h:459
virtual const char * GetMinorName() const =0
Iterator on all the leaves in a TTree and its friend.
Definition: TTree.h:585
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:2231
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:7461
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:1784
#define snprintf
Definition: civetweb.c:822
TTree * GetTree() const
Definition: TBranch.h:188
#define gPad
Definition: TVirtualPad.h:284
Int_t GetEntries() const
Return the number of objects in array (i.e.
Definition: TObjArray.cxx:494
virtual void SetCircular(Long64_t maxEntries)
Enable/Disable circularity for this tree.
Definition: TTree.cxx:8365
R__EXTERN Int_t gDebug
Definition: Rtypes.h:83
Int_t GetBufferSize() const
Definition: TBasket.h:73
virtual void Reset(Option_t *option="")
Reset baskets, buffers and entries count in all branches and leaves.
Definition: TTree.cxx:7557
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:105
TFileCacheRead * GetCacheRead(TObject *tree=0) const
Return a pointer to the current read cache.
Definition: TFile.cxx:1202
virtual char * GetAddress() const
Definition: TBranch.h:151
TObject * fNotify
! Object to be notified when loading a Tree
Definition: TTree.h:113
virtual Int_t SetCacheEntryRange(Long64_t first, Long64_t last)
interface to TTreeCache to set the cache entry range
Definition: TTree.cxx:8304
void Add(TObject *obj)
Definition: TObjArray.h:73
Double_t Atof() const
Return floating-point value contained in string.
Definition: TString.cxx:2041
A TTree object has a header with a name and a title.
Definition: TTree.h:78
#define gDirectory
Definition: TDirectory.h:211
TVirtualIndex * fTreeIndex
Pointer to the tree Index (if any)
Definition: TTree.h:122
TFriendLock & operator=(const TFriendLock &)
Assignment operator.
Definition: TTree.cxx:497
Int_t SetBranchAddressImp(TBranch *branch, void *addr, TBranch **ptr)
Change branch address, dealing with clone trees properly.
Definition: TTree.cxx:7930
virtual TVirtualIndex * BuildIndex(const TTree *T, const char *majorname, const char *minorname)=0
void ResetBit(UInt_t f)
Definition: TObject.h:158
virtual void SetDefaultEntryOffsetLen(Int_t newdefault, Bool_t updateExisting=kFALSE)
Update the default value for the branch&#39;s fEntryOffsetLen.
Definition: TTree.cxx:8413
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:1844
TObject * Next()
Go the next friend element.
Definition: TTree.cxx:9225
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:4302
Int_t FlushBaskets()
Flush to disk all the baskets of this branch and any of subbranches.
Definition: TBranch.cxx:1082
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:5748
static Long64_t fgMaxTreeSize
Maximum size of a file containing a Tree.
Definition: TTree.h:139
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:901
virtual void WriteHeader()
Write File Header.
Definition: TFile.cxx:2451
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:1474
virtual Long64_t SetEntries(Long64_t n=-1)
Change number of entries in the tree.
Definition: TTree.cxx:8484
R__EXTERN TInterpreter * gCling
Definition: TInterpreter.h:501
TBranch * GetBranch() const
Definition: TLeaf.h:65
virtual void Compress()
Remove empty slots from array.
Definition: TObjArray.cxx:309
virtual TFile * ChangeFile(TFile *file)
Called by TTree::Fill() when file has reached its maximum fgMaxTreeSize.
Definition: TTree.cxx:2635
virtual const char * GetName() const
Returns name of object.
Definition: TObject.cxx:364
static TTree * MergeTrees(TList *list, Option_t *option="")
Static function merging the trees in the TList into a new tree.
Definition: TTree.cxx:6507
virtual Int_t GetSize() const
Definition: TCollection.h:89
A TTree is a list of TBranches.
Definition: TBranch.h:57
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
virtual void SetTitle(const char *title="")
Set the title of the TNamed.
Definition: TNamed.cxx:155
void SetHistLineColor(Color_t color=1)
Definition: TStyle.h:354
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:1816
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:945
const Bool_t kTRUE
Definition: RtypesCore.h:91
Int_t fPacketSize
! Number of entries in one packet for parallel root
Definition: TTree.h:106
void Set(Int_t n)
Set size of this array to n doubles.
Definition: TArrayD.cxx:105
const Int_t n
Definition: legend1.C:16
TString & String()
Definition: TString.h:114
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:7083
Line Attributes class.
Definition: TAttLine.h:18
virtual Long64_t GetEntryNumberWithIndex(Long64_t major, Long64_t minor) const =0
Int_t GetCompressionLevel() const
Definition: TFile.h:368
Bool_t IsObject() const
Definition: TRealData.h:56
Long64_t BinarySearch(Long64_t n, const T *array, T value)
Definition: TMath.h:1093
TBranch * GetMother() const
Get our top-level parent branch in the tree.
Definition: TBranch.cxx:1625
TFriendLock(const TFriendLock &)
Copy constructor.
Definition: TTree.cxx:487
virtual void Warning(const char *method, const char *msgfmt,...) const
Issue warning message.
Definition: TObject.cxx:859
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:5196
virtual void SetName(const char *name)
Change the name of this tree.
Definition: TTree.cxx:8644
Int_t GetCompressionSettings() const
Definition: TFile.h:374
virtual Version_t ReadVersion(UInt_t *start=0, UInt_t *bcnt=0, const TClass *cl=0)=0
Long64_t GetEstimatedClusterSize()
In the case where the cluster size was not fixed (old files and case where autoflush was explicitly s...
Definition: TTree.cxx:570
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:6957
void MoveReadCache(TFile *src, TDirectory *dir)
Move a cache from a file to the current file in dir.
Definition: TTree.cxx:6640
virtual void CopyAddresses(TTree *, Bool_t undo=kFALSE)
Set branch addresses of passed tree equal to ours.
Definition: TTree.cxx:3167
virtual TObjArray * GetListOfLeaves()
Definition: TTree.h:406
static void ResetCount()
Static function resetting fgCount.
Definition: TBranch.cxx:2140
Long64_t fSavedBytes
Number of autosaved bytes.
Definition: TTree.h:85
Long64_t fCacheSize
! Maximum size of file buffers
Definition: TTree.h:102
virtual const char * GetFriendAlias(TTree *) const
If the &#39;tree&#39; is a friend, this method returns its alias name.
Definition: TTree.cxx:5705
void * New(ENewType defConstructor=kClassNew, Bool_t quiet=kFALSE) const
Return a pointer to a newly allocated object of this class.
Definition: TClass.cxx:4706
Int_t GetNleaves() const
Definition: TBranch.h:185
virtual Long64_t AutoSave(Option_t *option="")
AutoSave tree header every fAutoSave bytes.
Definition: TTree.cxx:1345
const char * Data() const
Definition: TString.h:347
std::atomic< Long64_t > fIMTTotBytes
! Total bytes for the IMT flush baskets
Definition: TTree.h:147