Logo ROOT   6.08/07
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 
396 #include <chrono>
397 #include <cstddef>
398 #include <iostream>
399 #include <fstream>
400 #include <sstream>
401 #include <string>
402 #include <stdio.h>
403 #include <limits.h>
404 #include <algorithm>
405 
406 #ifdef R__USE_IMT
407 #include "tbb/task.h"
408 #include "tbb/task_group.h"
409 #include <thread>
410 #include <string>
411 #include <sstream>
412 #endif
413 
414 constexpr Int_t kNEntriesResort = 100;
417 Int_t TTree::fgBranchStyle = 1; // Use new TBranch style with TBranchElement.
418 Long64_t TTree::fgMaxTreeSize = 100000000000LL;
419 
421 
422 ////////////////////////////////////////////////////////////////////////////////
423 ////////////////////////////////////////////////////////////////////////////////
424 ////////////////////////////////////////////////////////////////////////////////
425 
426 static char DataTypeToChar(EDataType datatype)
427 {
428  // Return the leaflist 'char' for a given datatype.
429 
430  switch(datatype) {
431  case kChar_t: return 'B';
432  case kUChar_t: return 'b';
433  case kBool_t: return 'O';
434  case kShort_t: return 'S';
435  case kUShort_t: return 's';
436  case kCounter:
437  case kInt_t: return 'I';
438  case kUInt_t: return 'i';
439  case kDouble_t:
440  case kDouble32_t: return 'D';
441  case kFloat_t:
442  case kFloat16_t: return 'F';
443  case kLong_t: return 0; // unsupported
444  case kULong_t: return 0; // unsupported?
445  case kchar: return 0; // unsupported
446  case kLong64_t: return 'L';
447  case kULong64_t: return 'l';
448 
449  case kCharStar: return 'C';
450  case kBits: return 0; //unsupported
451 
452  case kOther_t:
453  case kNoType_t:
454  default:
455  return 0;
456  }
457  return 0;
458 }
459 
460 ////////////////////////////////////////////////////////////////////////////////
461 /// \class TTree::TFriendLock
462 /// Helper class to prevent infinite recursion in the usage of TTree Friends.
463 
464 ////////////////////////////////////////////////////////////////////////////////
465 /// Record in tree that it has been used while recursively looks through the friends.
466 
468 : fTree(tree)
469 {
470  // We could also add some code to acquire an actual
471  // lock to prevent multi-thread issues
472  fMethodBit = methodbit;
473  if (fTree) {
474  fPrevious = fTree->fFriendLockStatus & fMethodBit;
475  fTree->fFriendLockStatus |= fMethodBit;
476  } else {
477  fPrevious = 0;
478  }
479 }
480 
481 ////////////////////////////////////////////////////////////////////////////////
482 /// Copy constructor.
483 
485  fTree(tfl.fTree),
486  fMethodBit(tfl.fMethodBit),
487  fPrevious(tfl.fPrevious)
488 {
489 }
490 
491 ////////////////////////////////////////////////////////////////////////////////
492 /// Assignment operator.
493 
495 {
496  if(this!=&tfl) {
497  fTree=tfl.fTree;
499  fPrevious=tfl.fPrevious;
500  }
501  return *this;
502 }
503 
504 ////////////////////////////////////////////////////////////////////////////////
505 /// Restore the state of tree the same as before we set the lock.
506 
508 {
509  if (fTree) {
510  if (!fPrevious) {
512  }
513  }
514 }
515 
516 ////////////////////////////////////////////////////////////////////////////////
517 /// \class TTree::TClusterIterator
518 /// Helper class to iterate over cluster of baskets.
519 
520 ////////////////////////////////////////////////////////////////////////////////
521 /// Regular constructor.
522 /// TTree is not set as const, since we might modify if it is a TChain.
523 
524 TTree::TClusterIterator::TClusterIterator(TTree *tree, Long64_t firstEntry) : fTree(tree), fClusterRange(0), fStartEntry(0), fNextEntry(0)
525 {
526  if ( fTree->GetAutoFlush() <= 0 ) {
527  // Case of old files before November 9 2009
528  fStartEntry = firstEntry;
529  } else if (fTree->fNClusterRange) {
530  // Find the correct cluster range.
531  //
532  // Since fClusterRangeEnd contains the inclusive upper end of the range, we need to search for the
533  // range that was containing the previous entry and add 1 (because BinarySearch consider the values
534  // to be the inclusive start of the bucket).
535  fClusterRange = TMath::BinarySearch(fTree->fNClusterRange, fTree->fClusterRangeEnd, firstEntry - 1) + 1;
536 
537  Long64_t entryInRange;
538  Long64_t pedestal;
539  if (fClusterRange == 0) {
540  pedestal = 0;
541  entryInRange = firstEntry;
542  } else {
543  pedestal = fTree->fClusterRangeEnd[fClusterRange-1] + 1;
544  entryInRange = firstEntry - pedestal;
545  }
546  Long64_t autoflush;
547  if (fClusterRange == fTree->fNClusterRange) {
548  autoflush = fTree->fAutoFlush;
549  } else {
550  autoflush = fTree->fClusterSize[fClusterRange];
551  }
552  if (autoflush == 0) {
553  autoflush = GetEstimatedClusterSize();
554  }
555  fStartEntry = pedestal + entryInRange - entryInRange%autoflush;
556  } else {
557  fStartEntry = firstEntry - firstEntry%fTree->GetAutoFlush();
558  }
559  fNextEntry = fStartEntry; // Position correctly for the first call to Next()
560 }
561 
562 ////////////////////////////////////////////////////////////////////////////////
563 /// In the case where the cluster size was not fixed (old files and
564 /// case where autoflush was explicitly set to zero, we need estimate
565 /// a cluster size in relation to the size of the cache.
566 
568 {
569  Long64_t zipBytes = fTree->GetZipBytes();
570  if (zipBytes == 0) {
571  return fTree->GetEntries() - 1;
572  } else {
573  Long64_t clusterEstimate = 1;
574  Long64_t cacheSize = fTree->GetCacheSize();
575  if (cacheSize == 0) {
576  // Humm ... let's double check on the file.
578  if (file) {
579  TFileCacheRead *cache = file->GetCacheRead(fTree);
580  if (cache) {
581  cacheSize = cache->GetBufferSize();
582  }
583  }
584  }
585  if (cacheSize > 0) {
586  clusterEstimate = fTree->GetEntries() * cacheSize / zipBytes;
587  if (clusterEstimate == 0)
588  clusterEstimate = 1;
589  }
590  return clusterEstimate;
591  }
592 }
593 
594 ////////////////////////////////////////////////////////////////////////////////
595 /// Move on to the next cluster and return the starting entry
596 /// of this next cluster
597 
599 {
600  fStartEntry = fNextEntry;
601  if ( fTree->GetAutoFlush() <= 0 ) {
602  // Case of old files before November 9 2009
603  Long64_t clusterEstimate = GetEstimatedClusterSize();
604  fNextEntry = fStartEntry + clusterEstimate;
605  } else {
606  if (fClusterRange == fTree->fNClusterRange) {
607  // We are looking at the last range ; its size
608  // is defined by AutoFlush itself and goes to the GetEntries.
609  fNextEntry += fTree->GetAutoFlush();
610  } else {
611  if (fStartEntry > fTree->fClusterRangeEnd[fClusterRange]) {
612  ++fClusterRange;
613  }
614  if (fClusterRange == fTree->fNClusterRange) {
615  // We are looking at the last range which size
616  // is defined by AutoFlush itself and goes to the GetEntries.
617  fNextEntry += fTree->GetAutoFlush();
618  } else {
619  Long64_t clusterSize = fTree->fClusterSize[fClusterRange];
620  if (clusterSize == 0) {
621  clusterSize = GetEstimatedClusterSize();
622  }
623  fNextEntry += clusterSize;
624  if (fNextEntry > fTree->fClusterRangeEnd[fClusterRange]) {
625  // The last cluster of the range was a partial cluster,
626  // so the next cluster starts at the beginning of the
627  // next range.
628  fNextEntry = fTree->fClusterRangeEnd[fClusterRange] + 1;
629  }
630  }
631  }
632  }
633  if (fNextEntry > fTree->GetEntries()) {
634  fNextEntry = fTree->GetEntries();
635  }
636  return fStartEntry;
637 }
638 
639 ////////////////////////////////////////////////////////////////////////////////
640 ////////////////////////////////////////////////////////////////////////////////
641 ////////////////////////////////////////////////////////////////////////////////
642 
643 ////////////////////////////////////////////////////////////////////////////////
644 /// Default constructor and I/O constructor.
645 ///
646 /// Note: We do *not* insert ourself into the current directory.
647 ///
648 
649 TTree::TTree()
651 , TAttLine()
652 , TAttFill()
653 , TAttMarker()
654 , fEntries(0)
655 , fTotBytes(0)
656 , fZipBytes(0)
657 , fSavedBytes(0)
658 , fFlushedBytes(0)
659 , fWeight(1)
660 , fTimerInterval(0)
661 , fScanField(25)
662 , fUpdate(0)
664 , fNClusterRange(0)
665 , fMaxClusterRange(0)
666 , fMaxEntries(0)
667 , fMaxEntryLoop(0)
668 , fMaxVirtualSize(0)
669 , fAutoSave( -300000000)
670 , fAutoFlush(-30000000)
671 , fEstimate(1000000)
672 , fClusterRangeEnd(0)
673 , fClusterSize(0)
674 , fCacheSize(0)
675 , fChainOffset(0)
676 , fReadEntry(-1)
677 , fTotalBuffers(0)
678 , fPacketSize(100)
679 , fNfill(0)
680 , fDebug(0)
681 , fDebugMin(0)
682 , fDebugMax(9999999)
683 , fMakeClass(0)
684 , fFileNumber(0)
685 , fNotify(0)
686 , fDirectory(0)
687 , fBranches()
688 , fLeaves()
689 , fAliases(0)
690 , fEventList(0)
691 , fEntryList(0)
692 , fIndexValues()
693 , fIndex()
694 , fTreeIndex(0)
695 , fFriends(0)
696 , fPerfStats(0)
697 , fUserInfo(0)
698 , fPlayer(0)
699 , fClones(0)
700 , fBranchRef(0)
702 , fTransientBuffer(0)
707 {
708  fMaxEntries = 1000000000;
709  fMaxEntries *= 1000;
710 
711  fMaxEntryLoop = 1000000000;
712  fMaxEntryLoop *= 1000;
713 
715 }
716 
717 ////////////////////////////////////////////////////////////////////////////////
718 /// Normal tree constructor.
719 ///
720 /// The tree is created in the current directory.
721 /// Use the various functions Branch below to add branches to this tree.
722 ///
723 /// If the first character of title is a "/", the function assumes a folder name.
724 /// In this case, it creates automatically branches following the folder hierarchy.
725 /// splitlevel may be used in this case to control the split level.
726 
727 TTree::TTree(const char* name, const char* title, Int_t splitlevel /* = 99 */)
728 : TNamed(name, title)
729 , TAttLine()
730 , TAttFill()
731 , TAttMarker()
732 , fEntries(0)
733 , fTotBytes(0)
734 , fZipBytes(0)
735 , fSavedBytes(0)
736 , fFlushedBytes(0)
737 , fWeight(1)
738 , fTimerInterval(0)
739 , fScanField(25)
740 , fUpdate(0)
742 , fNClusterRange(0)
743 , fMaxClusterRange(0)
744 , fMaxEntries(0)
745 , fMaxEntryLoop(0)
746 , fMaxVirtualSize(0)
747 , fAutoSave( -300000000)
748 , fAutoFlush(-30000000)
749 , fEstimate(1000000)
750 , fClusterRangeEnd(0)
751 , fClusterSize(0)
752 , fCacheSize(0)
753 , fChainOffset(0)
754 , fReadEntry(-1)
755 , fTotalBuffers(0)
756 , fPacketSize(100)
757 , fNfill(0)
758 , fDebug(0)
759 , fDebugMin(0)
760 , fDebugMax(9999999)
761 , fMakeClass(0)
762 , fFileNumber(0)
763 , fNotify(0)
764 , fDirectory(0)
765 , fBranches()
766 , fLeaves()
767 , fAliases(0)
768 , fEventList(0)
769 , fEntryList(0)
770 , fIndexValues()
771 , fIndex()
772 , fTreeIndex(0)
773 , fFriends(0)
774 , fPerfStats(0)
775 , fUserInfo(0)
776 , fPlayer(0)
777 , fClones(0)
778 , fBranchRef(0)
780 , fTransientBuffer(0)
785 {
786  // TAttLine state.
790 
791  // TAttFill state.
794 
795  // TAttMarkerState.
799 
800  fMaxEntries = 1000000000;
801  fMaxEntries *= 1000;
802 
803  fMaxEntryLoop = 1000000000;
804  fMaxEntryLoop *= 1000;
805 
806  // Insert ourself into the current directory.
807  // FIXME: This is very annoying behaviour, we should
808  // be able to choose to not do this like we
809  // can with a histogram.
811  if (fDirectory) fDirectory->Append(this);
812 
814 
815  // If title starts with "/" and is a valid folder name, a superbranch
816  // is created.
817  // FIXME: Why?
818  if (strlen(title) > 2) {
819  if (title[0] == '/') {
820  Branch(title+1,32000,splitlevel);
821  }
822  }
823 }
824 
825 ////////////////////////////////////////////////////////////////////////////////
826 /// Destructor.
827 
829 {
830  if (fDirectory) {
831  // We are in a directory, which may possibly be a file.
832  if (fDirectory->GetList()) {
833  // Remove us from the directory listing.
834  fDirectory->Remove(this);
835  }
836  //delete the file cache if it points to this Tree
838  MoveReadCache(file,0);
839  }
840  // We don't own the leaves in fLeaves, the branches do.
841  fLeaves.Clear();
842  // I'm ready to destroy any objects allocated by
843  // SetAddress() by my branches. If I have clones,
844  // tell them to zero their pointers to this shared
845  // memory.
846  if (fClones && fClones->GetEntries()) {
847  // I have clones.
848  // I am about to delete the objects created by
849  // SetAddress() which we are sharing, so tell
850  // the clones to release their pointers to them.
851  for (TObjLink* lnk = fClones->FirstLink(); lnk; lnk = lnk->Next()) {
852  TTree* clone = (TTree*) lnk->GetObject();
853  // clone->ResetBranchAddresses();
854 
855  // Reset only the branch we have set the address of.
856  CopyAddresses(clone,kTRUE);
857  }
858  }
859  // Get rid of our branches, note that this will also release
860  // any memory allocated by TBranchElement::SetAddress().
861  fBranches.Delete();
862  // FIXME: We must consider what to do with the reset of these if we are a clone.
863  delete fPlayer;
864  fPlayer = 0;
865  if (fFriends) {
866  fFriends->Delete();
867  delete fFriends;
868  fFriends = 0;
869  }
870  if (fAliases) {
871  fAliases->Delete();
872  delete fAliases;
873  fAliases = 0;
874  }
875  if (fUserInfo) {
876  fUserInfo->Delete();
877  delete fUserInfo;
878  fUserInfo = 0;
879  }
880  if (fClones) {
881  // Clone trees should no longer be removed from fClones when they are deleted.
882  gROOT->GetListOfCleanups()->Remove(fClones);
883  // Note: fClones does not own its content.
884  delete fClones;
885  fClones = 0;
886  }
887  if (fEntryList) {
889  // Delete the entry list if it is marked to be deleted and it is not also
890  // owned by a directory. (Otherwise we would need to make sure that a
891  // TDirectoryFile that has a TTree in it does a 'slow' TList::Delete.
892  delete fEntryList;
893  fEntryList=0;
894  }
895  }
896  delete fTreeIndex;
897  fTreeIndex = 0;
898  delete fBranchRef;
899  fBranchRef = 0;
900  delete [] fClusterRangeEnd;
901  fClusterRangeEnd = 0;
902  delete [] fClusterSize;
903  fClusterSize = 0;
904  // Must be done after the destruction of friends.
905  // Note: We do *not* own our directory.
906  fDirectory = 0;
907 
908  if (fTransientBuffer) {
909  delete fTransientBuffer;
910  fTransientBuffer = 0;
911  }
912 }
913 
914 ////////////////////////////////////////////////////////////////////////////////
915 /// Returns the transient buffer currently used by this TTree for reading/writing baskets.
916 
918 {
919  if (fTransientBuffer) {
920  if (fTransientBuffer->BufferSize() < size) {
921  fTransientBuffer->Expand(size);
922  }
923  return fTransientBuffer;
924  }
926  return fTransientBuffer;
927 }
928 
929 ////////////////////////////////////////////////////////////////////////////////
930 /// Add branch with name bname to the Tree cache.
931 /// If bname="*" all branches are added to the cache.
932 /// if subbranches is true all the branches of the subbranches are
933 /// also put to the cache.
934 ///
935 /// Returns:
936 /// - 0 branch added or already included
937 /// - -1 on error
938 
939 Int_t TTree::AddBranchToCache(const char*bname, Bool_t subbranches)
940 {
941  if (!GetTree()) {
942  if (LoadTree(0)<0) {
943  Error("AddBranchToCache","Could not load a tree");
944  return -1;
945  }
946  }
947  if (GetTree()) {
948  if (GetTree() != this) {
949  return GetTree()->AddBranchToCache(bname, subbranches);
950  }
951  } else {
952  Error("AddBranchToCache", "No tree is available. Branch was not added to the cache");
953  return -1;
954  }
955 
956  TFile *f = GetCurrentFile();
957  if (!f) {
958  Error("AddBranchToCache", "No file is available. Branch was not added to the cache");
959  return -1;
960  }
961  TTreeCache *tc = GetReadCache(f,kTRUE);
962  if (!tc) {
963  Error("AddBranchToCache", "No cache is available, branch not added");
964  return -1;
965  }
966  return tc->AddBranch(bname,subbranches);
967 }
968 
969 ////////////////////////////////////////////////////////////////////////////////
970 /// Add branch b to the Tree cache.
971 /// if subbranches is true all the branches of the subbranches are
972 /// also put to the cache.
973 ///
974 /// Returns:
975 /// - 0 branch added or already included
976 /// - -1 on error
977 
979 {
980  if (!GetTree()) {
981  if (LoadTree(0)<0) {
982  Error("AddBranchToCache","Could not load a tree");
983  return -1;
984  }
985  }
986  if (GetTree()) {
987  if (GetTree() != this) {
988  Int_t res = GetTree()->AddBranchToCache(b, subbranches);
989  if (res<0) {
990  Error("AddBranchToCache", "Error adding branch");
991  }
992  return res;
993  }
994  } else {
995  Error("AddBranchToCache", "No tree is available. Branch was not added to the cache");
996  return -1;
997  }
998 
999  TFile *f = GetCurrentFile();
1000  if (!f) {
1001  Error("AddBranchToCache", "No file is available. Branch was not added to the cache");
1002  return -1;
1003  }
1004  TTreeCache *tc = GetReadCache(f,kTRUE);
1005  if (!tc) {
1006  Error("AddBranchToCache", "No cache is available, branch not added");
1007  return -1;
1008  }
1009  return tc->AddBranch(b,subbranches);
1010 }
1011 
1012 ////////////////////////////////////////////////////////////////////////////////
1013 /// Remove the branch with name 'bname' from the Tree cache.
1014 /// If bname="*" all branches are removed from the cache.
1015 /// if subbranches is true all the branches of the subbranches are
1016 /// also removed from the cache.
1017 ///
1018 /// Returns:
1019 /// - 0 branch dropped or not in cache
1020 /// - -1 on error
1021 
1022 Int_t TTree::DropBranchFromCache(const char*bname, Bool_t subbranches)
1024  if (!GetTree()) {
1025  if (LoadTree(0)<0) {
1026  Error("DropBranchFromCache","Could not load a tree");
1027  return -1;
1028  }
1029  }
1030  if (GetTree()) {
1031  if (GetTree() != this) {
1032  return GetTree()->DropBranchFromCache(bname, subbranches);
1033  }
1034  } else {
1035  Error("DropBranchFromCache", "No tree is available. Branch was not dropped from the cache");
1036  return -1;
1037  }
1038 
1039  TFile *f = GetCurrentFile();
1040  if (!f) {
1041  Error("DropBranchFromCache", "No file is available. Branch was not dropped from the cache");
1042  return -1;
1043  }
1044  TTreeCache *tc = GetReadCache(f,kTRUE);
1045  if (!tc) {
1046  Error("DropBranchFromCache", "No cache is available, branch not dropped");
1047  return -1;
1048  }
1049  return tc->DropBranch(bname,subbranches);
1050 }
1051 
1052 ////////////////////////////////////////////////////////////////////////////////
1053 /// Remove the branch b from the Tree cache.
1054 /// if subbranches is true all the branches of the subbranches are
1055 /// also removed from the cache.
1056 ///
1057 /// Returns:
1058 /// - 0 branch dropped or not in cache
1059 /// - -1 on error
1060 
1063  if (!GetTree()) {
1064  if (LoadTree(0)<0) {
1065  Error("DropBranchFromCache","Could not load a tree");
1066  return -1;
1067  }
1068  }
1069  if (GetTree()) {
1070  if (GetTree() != this) {
1071  Int_t res = GetTree()->DropBranchFromCache(b, subbranches);
1072  if (res<0) {
1073  Error("DropBranchFromCache", "Error dropping branch");
1074  }
1075  return res;
1076  }
1077  } else {
1078  Error("DropBranchFromCache", "No tree is available. Branch was not dropped from the cache");
1079  return -1;
1080  }
1081 
1082  TFile *f = GetCurrentFile();
1083  if (!f) {
1084  Error("DropBranchFromCache", "No file is available. Branch was not dropped from the cache");
1085  return -1;
1086  }
1087  TTreeCache *tc = GetReadCache(f,kTRUE);
1088  if (!tc) {
1089  Error("DropBranchFromCache", "No cache is available, branch not dropped");
1090  return -1;
1091  }
1092  return tc->DropBranch(b,subbranches);
1093 }
1094 
1095 ////////////////////////////////////////////////////////////////////////////////
1096 /// Add a cloned tree to our list of trees to be notified whenever we change
1097 /// our branch addresses or when we are deleted.
1098 
1099 void TTree::AddClone(TTree* clone)
1101  if (!fClones) {
1102  fClones = new TList();
1103  fClones->SetOwner(false);
1104  // So that the clones are automatically removed from the list when
1105  // they are deleted.
1106  gROOT->GetListOfCleanups()->Add(fClones);
1107  }
1108  if (!fClones->FindObject(clone)) {
1109  fClones->Add(clone);
1110  }
1111 }
1112 
1113 ////////////////////////////////////////////////////////////////////////////////
1114 /// Add a TFriendElement to the list of friends.
1115 ///
1116 /// This function:
1117 /// - opens a file if filename is specified
1118 /// - reads a Tree with name treename from the file (current directory)
1119 /// - adds the Tree to the list of friends
1120 /// see other AddFriend functions
1121 ///
1122 /// A TFriendElement TF describes a TTree object TF in a file.
1123 /// When a TFriendElement TF is added to the the list of friends of an
1124 /// existing TTree T, any variable from TF can be referenced in a query
1125 /// to T.
1126 ///
1127 /// A tree keeps a list of friends. In the context of a tree (or a chain),
1128 /// friendship means unrestricted access to the friends data. In this way
1129 /// it is much like adding another branch to the tree without taking the risk
1130 /// of damaging it. To add a friend to the list, you can use the TTree::AddFriend
1131 /// method. The tree in the diagram below has two friends (friend_tree1 and
1132 /// friend_tree2) and now has access to the variables a,b,c,i,j,k,l and m.
1133 ///
1134 /// \image html ttree_friend1.png
1135 ///
1136 /// The AddFriend method has two parameters, the first is the tree name and the
1137 /// second is the name of the ROOT file where the friend tree is saved.
1138 /// AddFriend automatically opens the friend file. If no file name is given,
1139 /// the tree called ft1 is assumed to be in the same file as the original tree.
1140 ///
1141 /// tree.AddFriend("ft1","friendfile1.root");
1142 /// If the friend tree has the same name as the original tree, you can give it
1143 /// an alias in the context of the friendship:
1144 ///
1145 /// tree.AddFriend("tree1 = tree","friendfile1.root");
1146 /// Once the tree has friends, we can use TTree::Draw as if the friend's
1147 /// variables were in the original tree. To specify which tree to use in
1148 /// the Draw method, use the syntax:
1149 /// ~~~ {.cpp}
1150 /// <treeName>.<branchname>.<varname>
1151 /// ~~~
1152 /// If the variablename is enough to uniquely identify the variable, you can
1153 /// leave out the tree and/or branch name.
1154 /// For example, these commands generate a 3-d scatter plot of variable "var"
1155 /// in the TTree tree versus variable v1 in TTree ft1 versus variable v2 in
1156 /// TTree ft2.
1157 /// ~~~ {.cpp}
1158 /// tree.AddFriend("ft1","friendfile1.root");
1159 /// tree.AddFriend("ft2","friendfile2.root");
1160 /// tree.Draw("var:ft1.v1:ft2.v2");
1161 /// ~~~
1162 /// \image html ttree_friend2.png
1163 ///
1164 /// The picture illustrates the access of the tree and its friends with a
1165 /// Draw command.
1166 /// When AddFriend is called, the ROOT file is automatically opened and the
1167 /// friend tree (ft1) is read into memory. The new friend (ft1) is added to
1168 /// the list of friends of tree.
1169 /// The number of entries in the friend must be equal or greater to the number
1170 /// of entries of the original tree. If the friend tree has fewer entries a
1171 /// warning is given and the missing entries are not included in the histogram.
1172 /// To retrieve the list of friends from a tree use TTree::GetListOfFriends.
1173 /// When the tree is written to file (TTree::Write), the friends list is saved
1174 /// with it. And when the tree is retrieved, the trees on the friends list are
1175 /// also retrieved and the friendship restored.
1176 /// When a tree is deleted, the elements of the friend list are also deleted.
1177 /// It is possible to declare a friend tree that has the same internal
1178 /// structure (same branches and leaves) as the original tree, and compare the
1179 /// same values by specifying the tree.
1180 /// ~~~ {.cpp}
1181 /// tree.Draw("var:ft1.var:ft2.var")
1182 /// ~~~
1183 
1184 TFriendElement* TTree::AddFriend(const char* treename, const char* filename)
1186  if (!fFriends) {
1187  fFriends = new TList();
1188  }
1189  TFriendElement* fe = new TFriendElement(this, treename, filename);
1190 
1191  fFriends->Add(fe);
1192  TTree* t = fe->GetTree();
1193  if (t) {
1194  if (!t->GetTreeIndex() && (t->GetEntries() < fEntries)) {
1195  Warning("AddFriend", "FriendElement %s in file %s has less entries %lld than its parent Tree: %lld", treename, filename, t->GetEntries(), fEntries);
1196  }
1197  } else {
1198  Warning("AddFriend", "Cannot add FriendElement %s in file %s", treename, filename);
1199  }
1200  return fe;
1201 }
1202 
1203 ////////////////////////////////////////////////////////////////////////////////
1204 /// Add a TFriendElement to the list of friends.
1205 ///
1206 /// The TFile is managed by the user (e.g. the user must delete the file).
1207 /// For complete description see AddFriend(const char *, const char *).
1208 /// This function:
1209 /// - reads a Tree with name treename from the file
1210 /// - adds the Tree to the list of friends
1211 
1212 TFriendElement* TTree::AddFriend(const char* treename, TFile* file)
1214  if (!fFriends) {
1215  fFriends = new TList();
1216  }
1217  TFriendElement *fe = new TFriendElement(this, treename, file);
1218  R__ASSERT(fe);
1219  fFriends->Add(fe);
1220  TTree *t = fe->GetTree();
1221  if (t) {
1222  if (!t->GetTreeIndex() && (t->GetEntries() < fEntries)) {
1223  Warning("AddFriend", "FriendElement %s in file %s has less entries %lld than its parent tree: %lld", treename, file->GetName(), t->GetEntries(), fEntries);
1224  }
1225  } else {
1226  Warning("AddFriend", "unknown tree '%s' in file '%s'", treename, file->GetName());
1227  }
1228  return fe;
1229 }
1230 
1231 ////////////////////////////////////////////////////////////////////////////////
1232 /// Add a TFriendElement to the list of friends.
1233 ///
1234 /// The TTree is managed by the user (e.g., the user must delete the file).
1235 /// For a complete description see AddFriend(const char *, const char *).
1236 
1237 TFriendElement* TTree::AddFriend(TTree* tree, const char* alias, Bool_t warn)
1239  if (!tree) {
1240  return 0;
1241  }
1242  if (!fFriends) {
1243  fFriends = new TList();
1244  }
1245  TFriendElement* fe = new TFriendElement(this, tree, alias);
1246  R__ASSERT(fe); // this assert is for historical reasons. Don't remove it unless you understand all the consequences.
1247  fFriends->Add(fe);
1248  TTree* t = fe->GetTree();
1249  if (warn && (t->GetEntries() < fEntries)) {
1250  Warning("AddFriend", "FriendElement '%s' in file '%s' has less entries %lld than its parent tree: %lld",
1251  tree->GetName(), fe->GetFile() ? fe->GetFile()->GetName() : "(memory resident)", t->GetEntries(), fEntries);
1252  }
1253  return fe;
1254 }
1255 
1256 ////////////////////////////////////////////////////////////////////////////////
1257 /// AutoSave tree header every fAutoSave bytes.
1258 ///
1259 /// When large Trees are produced, it is safe to activate the AutoSave
1260 /// procedure. Some branches may have buffers holding many entries.
1261 /// If fAutoSave is negative, AutoSave is automatically called by
1262 /// TTree::Fill when the number of bytes generated since the previous
1263 /// AutoSave is greater than -fAutoSave bytes.
1264 /// If fAutoSave is positive, AutoSave is automatically called by
1265 /// TTree::Fill every N entries.
1266 /// This function may also be invoked by the user.
1267 /// Each AutoSave generates a new key on the file.
1268 /// Once the key with the tree header has been written, the previous cycle
1269 /// (if any) is deleted.
1270 ///
1271 /// Note that calling TTree::AutoSave too frequently (or similarly calling
1272 /// TTree::SetAutoSave with a small value) is an expensive operation.
1273 /// You should make tests for your own application to find a compromise
1274 /// between speed and the quantity of information you may loose in case of
1275 /// a job crash.
1276 ///
1277 /// In case your program crashes before closing the file holding this tree,
1278 /// the file will be automatically recovered when you will connect the file
1279 /// in UPDATE mode.
1280 /// The Tree will be recovered at the status corresponding to the last AutoSave.
1281 ///
1282 /// if option contains "SaveSelf", gDirectory->SaveSelf() is called.
1283 /// This allows another process to analyze the Tree while the Tree is being filled.
1284 ///
1285 /// if option contains "FlushBaskets", TTree::FlushBaskets is called and all
1286 /// the current basket are closed-out and written to disk individually.
1287 ///
1288 /// By default the previous header is deleted after having written the new header.
1289 /// if option contains "Overwrite", the previous Tree header is deleted
1290 /// before written the new header. This option is slightly faster, but
1291 /// the default option is safer in case of a problem (disk quota exceeded)
1292 /// when writing the new header.
1293 ///
1294 /// The function returns the number of bytes written to the file.
1295 /// if the number of bytes is null, an error has occurred while writing
1296 /// the header to the file.
1297 ///
1298 /// ## How to write a Tree in one process and view it from another process
1299 ///
1300 /// The following two scripts illustrate how to do this.
1301 /// The script treew.C is executed by process1, treer.C by process2
1302 ///
1303 /// script treew.C:
1304 /// ~~~ {.cpp}
1305 /// void treew() {
1306 /// TFile f("test.root","recreate");
1307 /// TNtuple *ntuple = new TNtuple("ntuple","Demo","px:py:pz:random:i");
1308 /// Float_t px, py, pz;
1309 /// for ( Int_t i=0; i<10000000; i++) {
1310 /// gRandom->Rannor(px,py);
1311 /// pz = px*px + py*py;
1312 /// Float_t random = gRandom->Rndm(1);
1313 /// ntuple->Fill(px,py,pz,random,i);
1314 /// if (i%1000 == 1) ntuple->AutoSave("SaveSelf");
1315 /// }
1316 /// }
1317 /// ~~~
1318 /// script treer.C:
1319 /// ~~~ {.cpp}
1320 /// void treer() {
1321 /// TFile f("test.root");
1322 /// TTree *ntuple = (TTree*)f.Get("ntuple");
1323 /// TCanvas c1;
1324 /// Int_t first = 0;
1325 /// while(1) {
1326 /// if (first == 0) ntuple->Draw("px>>hpx", "","",10000000,first);
1327 /// else ntuple->Draw("px>>+hpx","","",10000000,first);
1328 /// first = (Int_t)ntuple->GetEntries();
1329 /// c1.Update();
1330 /// gSystem->Sleep(1000); //sleep 1 second
1331 /// ntuple->Refresh();
1332 /// }
1333 /// }
1334 /// ~~~
1335 
1338  if (!fDirectory || fDirectory == gROOT || !fDirectory->IsWritable()) return 0;
1339  if (gDebug > 0) {
1340  printf("AutoSave Tree:%s after %lld bytes written\n",GetName(),fTotBytes);
1341  }
1342  TString opt = option;
1343  opt.ToLower();
1344 
1345  if (opt.Contains("flushbaskets")) {
1346  if (gDebug > 0) printf("AutoSave: calling FlushBaskets \n");
1347  FlushBaskets();
1348  }
1349 
1351 
1353  Long64_t nbytes;
1354  if (opt.Contains("overwrite")) {
1355  nbytes = fDirectory->WriteTObject(this,"","overwrite");
1356  } else {
1357  nbytes = fDirectory->WriteTObject(this); //nbytes will be 0 if Write failed (disk space exceeded)
1358  if (nbytes && key) {
1359  key->Delete();
1360  delete key;
1361  }
1362  }
1363  // save StreamerInfo
1364  TFile *file = fDirectory->GetFile();
1365  if (file) file->WriteStreamerInfo();
1366 
1367  if (opt.Contains("saveself")) {
1368  fDirectory->SaveSelf();
1369  //the following line is required in case GetUserInfo contains a user class
1370  //for which the StreamerInfo must be written. One could probably be a bit faster (Rene)
1371  if (file) file->WriteHeader();
1372  }
1373 
1374  return nbytes;
1375 }
1376 
1377 namespace {
1378  // This error message is repeated several times in the code. We write it once.
1379  const char* writeStlWithoutProxyMsg = "The class requested (%s) for the branch \"%s\""
1380  " is an instance of an stl collection and does not have a compiled CollectionProxy."
1381  " Please generate the dictionary for this collection (%s) to avoid to write corrupted data.";
1382 }
1383 
1384 ////////////////////////////////////////////////////////////////////////////////
1385 /// Same as TTree::Branch() with added check that addobj matches className.
1386 ///
1387 /// See TTree::Branch() for other details.
1388 ///
1389 
1390 TBranch* TTree::BranchImp(const char* branchname, const char* classname, TClass* ptrClass, void* addobj, Int_t bufsize, Int_t splitlevel)
1392  TClass* claim = TClass::GetClass(classname);
1393  if (!ptrClass) {
1394  if (claim && claim->GetCollectionProxy() && dynamic_cast<TEmulatedCollectionProxy*>(claim->GetCollectionProxy())) {
1395  Error("Branch", writeStlWithoutProxyMsg,
1396  claim->GetName(), branchname, claim->GetName());
1397  return 0;
1398  }
1399  return Branch(branchname, classname, (void*) addobj, bufsize, splitlevel);
1400  }
1401  TClass* actualClass = 0;
1402  void** addr = (void**) addobj;
1403  if (addr) {
1404  actualClass = ptrClass->GetActualClass(*addr);
1405  }
1406  if (ptrClass && claim) {
1407  if (!(claim->InheritsFrom(ptrClass) || ptrClass->InheritsFrom(claim))) {
1408  // Note we currently do not warn in case of splicing or over-expectation).
1409  if (claim->IsLoaded() && ptrClass->IsLoaded() && strcmp( claim->GetTypeInfo()->name(), ptrClass->GetTypeInfo()->name() ) == 0) {
1410  // The type is the same according to the C++ type_info, we must be in the case of
1411  // a template of Double32_t. This is actually a correct case.
1412  } else {
1413  Error("Branch", "The class requested (%s) for \"%s\" is different from the type of the pointer passed (%s)",
1414  claim->GetName(), branchname, ptrClass->GetName());
1415  }
1416  } else if (actualClass && (claim != actualClass) && !actualClass->InheritsFrom(claim)) {
1417  if (claim->IsLoaded() && actualClass->IsLoaded() && strcmp( claim->GetTypeInfo()->name(), actualClass->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 actual class (%s) of the object provided for the definition of the branch \"%s\" does not inherit from %s",
1422  actualClass->GetName(), branchname, claim->GetName());
1423  }
1424  }
1425  }
1426  if (claim && claim->GetCollectionProxy() && dynamic_cast<TEmulatedCollectionProxy*>(claim->GetCollectionProxy())) {
1427  Error("Branch", writeStlWithoutProxyMsg,
1428  claim->GetName(), branchname, claim->GetName());
1429  return 0;
1430  }
1431  return Branch(branchname, classname, (void*) addobj, bufsize, splitlevel);
1432 }
1433 
1434 ////////////////////////////////////////////////////////////////////////////////
1435 /// Same as TTree::Branch but automatic detection of the class name.
1436 /// See TTree::Branch for other details.
1437 
1438 TBranch* TTree::BranchImp(const char* branchname, TClass* ptrClass, void* addobj, Int_t bufsize, Int_t splitlevel)
1440  if (!ptrClass) {
1441  Error("Branch", "The pointer specified for %s is not of a class known to ROOT", branchname);
1442  return 0;
1443  }
1444  TClass* actualClass = 0;
1445  void** addr = (void**) addobj;
1446  if (addr && *addr) {
1447  actualClass = ptrClass->GetActualClass(*addr);
1448  if (!actualClass) {
1449  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",
1450  branchname, ptrClass->GetName());
1451  actualClass = ptrClass;
1452  } else if ((ptrClass != actualClass) && !actualClass->InheritsFrom(ptrClass)) {
1453  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());
1454  return 0;
1455  }
1456  } else {
1457  actualClass = ptrClass;
1458  }
1459  if (actualClass && actualClass->GetCollectionProxy() && dynamic_cast<TEmulatedCollectionProxy*>(actualClass->GetCollectionProxy())) {
1460  Error("Branch", writeStlWithoutProxyMsg,
1461  actualClass->GetName(), branchname, actualClass->GetName());
1462  return 0;
1463  }
1464  return Branch(branchname, actualClass->GetName(), (void*) addobj, bufsize, splitlevel);
1465 }
1466 
1467 ////////////////////////////////////////////////////////////////////////////////
1468 /// Same as TTree::Branch but automatic detection of the class name.
1469 /// See TTree::Branch for other details.
1470 
1471 TBranch* TTree::BranchImpRef(const char* branchname, const char *classname, TClass* ptrClass, void *addobj, Int_t bufsize, Int_t splitlevel)
1473  TClass* claim = TClass::GetClass(classname);
1474  if (!ptrClass) {
1475  if (claim && claim->GetCollectionProxy() && dynamic_cast<TEmulatedCollectionProxy*>(claim->GetCollectionProxy())) {
1476  Error("Branch", writeStlWithoutProxyMsg,
1477  claim->GetName(), branchname, claim->GetName());
1478  return 0;
1479  } else if (claim == 0) {
1480  Error("Branch", "The pointer specified for %s is not of a class known to ROOT and %s is not a known class", branchname, classname);
1481  return 0;
1482  }
1483  ptrClass = claim;
1484  }
1485  TClass* actualClass = 0;
1486  if (!addobj) {
1487  Error("Branch", "Reference interface requires a valid object (for branch: %s)!", branchname);
1488  return 0;
1489  }
1490  actualClass = ptrClass->GetActualClass(addobj);
1491  if (ptrClass && claim) {
1492  if (!(claim->InheritsFrom(ptrClass) || ptrClass->InheritsFrom(claim))) {
1493  // Note we currently do not warn in case of splicing or over-expectation).
1494  if (claim->IsLoaded() && ptrClass->IsLoaded() && strcmp( claim->GetTypeInfo()->name(), ptrClass->GetTypeInfo()->name() ) == 0) {
1495  // The type is the same according to the C++ type_info, we must be in the case of
1496  // a template of Double32_t. This is actually a correct case.
1497  } else {
1498  Error("Branch", "The class requested (%s) for \"%s\" is different from the type of the object passed (%s)",
1499  claim->GetName(), branchname, ptrClass->GetName());
1500  }
1501  } else if (actualClass && (claim != actualClass) && !actualClass->InheritsFrom(claim)) {
1502  if (claim->IsLoaded() && actualClass->IsLoaded() && strcmp( claim->GetTypeInfo()->name(), actualClass->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 actual class (%s) of the object provided for the definition of the branch \"%s\" does not inherit from %s",
1507  actualClass->GetName(), branchname, claim->GetName());
1508  }
1509  }
1510  }
1511  if (!actualClass) {
1512  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",
1513  branchname, ptrClass->GetName());
1514  actualClass = ptrClass;
1515  } else if ((ptrClass != actualClass) && !actualClass->InheritsFrom(ptrClass)) {
1516  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());
1517  return 0;
1518  }
1519  if (actualClass && actualClass->GetCollectionProxy() && dynamic_cast<TEmulatedCollectionProxy*>(actualClass->GetCollectionProxy())) {
1520  Error("Branch", writeStlWithoutProxyMsg,
1521  actualClass->GetName(), branchname, actualClass->GetName());
1522  return 0;
1523  }
1524  return BronchExec(branchname, actualClass->GetName(), (void*) addobj, kFALSE, bufsize, splitlevel);
1525 }
1526 
1527 ////////////////////////////////////////////////////////////////////////////////
1528 /// Same as TTree::Branch but automatic detection of the class name.
1529 /// See TTree::Branch for other details.
1530 
1531 TBranch* TTree::BranchImpRef(const char* branchname, TClass* ptrClass, EDataType datatype, void* addobj, Int_t bufsize, Int_t splitlevel)
1533  if (!ptrClass) {
1534  if (datatype == kOther_t || datatype == kNoType_t) {
1535  Error("Branch", "The pointer specified for %s is not of a class or type known to ROOT", branchname);
1536  } else {
1537  TString varname; varname.Form("%s/%c",branchname,DataTypeToChar(datatype));
1538  return Branch(branchname,addobj,varname.Data(),bufsize);
1539  }
1540  return 0;
1541  }
1542  TClass* actualClass = 0;
1543  if (!addobj) {
1544  Error("Branch", "Reference interface requires a valid object (for branch: %s)!", branchname);
1545  return 0;
1546  }
1547  actualClass = ptrClass->GetActualClass(addobj);
1548  if (!actualClass) {
1549  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",
1550  branchname, ptrClass->GetName());
1551  actualClass = ptrClass;
1552  } else if ((ptrClass != actualClass) && !actualClass->InheritsFrom(ptrClass)) {
1553  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());
1554  return 0;
1555  }
1556  if (actualClass && actualClass->GetCollectionProxy() && dynamic_cast<TEmulatedCollectionProxy*>(actualClass->GetCollectionProxy())) {
1557  Error("Branch", writeStlWithoutProxyMsg,
1558  actualClass->GetName(), branchname, actualClass->GetName());
1559  return 0;
1560  }
1561  return BronchExec(branchname, actualClass->GetName(), (void*) addobj, kFALSE, bufsize, splitlevel);
1562 }
1563 
1564 ////////////////////////////////////////////////////////////////////////////////
1565 /// Deprecated function. Use next function instead.
1566 
1567 Int_t TTree::Branch(TList* li, Int_t bufsize /* = 32000 */ , Int_t splitlevel /* = 99 */)
1569  return Branch((TCollection*) li, bufsize, splitlevel);
1570 }
1571 
1572 ////////////////////////////////////////////////////////////////////////////////
1573 /// Create one branch for each element in the collection.
1574 ///
1575 /// Each entry in the collection becomes a top level branch if the
1576 /// corresponding class is not a collection. If it is a collection, the entry
1577 /// in the collection becomes in turn top level branches, etc.
1578 /// The splitlevel is decreased by 1 every time a new collection is found.
1579 /// For example if list is a TObjArray*
1580 /// - if splitlevel = 1, one top level branch is created for each element
1581 /// of the TObjArray.
1582 /// - if splitlevel = 2, one top level branch is created for each array element.
1583 /// if, in turn, one of the array elements is a TCollection, one top level
1584 /// branch will be created for each element of this collection.
1585 ///
1586 /// In case a collection element is a TClonesArray, the special Tree constructor
1587 /// for TClonesArray is called.
1588 /// The collection itself cannot be a TClonesArray.
1589 ///
1590 /// The function returns the total number of branches created.
1591 ///
1592 /// If name is given, all branch names will be prefixed with name_.
1593 ///
1594 /// IMPORTANT NOTE1: This function should not be called with splitlevel < 1.
1595 ///
1596 /// IMPORTANT NOTE2: The branches created by this function will have names
1597 /// corresponding to the collection or object names. It is important
1598 /// to give names to collections to avoid misleading branch names or
1599 /// identical branch names. By default collections have a name equal to
1600 /// the corresponding class name, e.g. the default name for a TList is "TList".
1601 ///
1602 /// And in general in any cases two or more master branches contain subbranches
1603 /// with identical names, one must add a "." (dot) character at the end
1604 /// of the master branch name. This will force the name of the subbranch
1605 /// to be master.subbranch instead of simply subbranch.
1606 /// This situation happens when the top level object (say event)
1607 /// has two or more members referencing the same class.
1608 /// For example, if a Tree has two branches B1 and B2 corresponding
1609 /// to objects of the same class MyClass, one can do:
1610 /// ~~~ {.cpp}
1611 /// tree.Branch("B1.","MyClass",&b1,8000,1);
1612 /// tree.Branch("B2.","MyClass",&b2,8000,1);
1613 /// ~~~
1614 /// if MyClass has 3 members a,b,c, the two instructions above will generate
1615 /// subbranches called B1.a, B1.b ,B1.c, B2.a, B2.b, B2.c
1616 ///
1617 /// Example:
1618 /// ~~~ {.cpp}
1619 /// {
1620 /// TTree T("T","test list");
1621 /// TList *list = new TList();
1622 ///
1623 /// TObjArray *a1 = new TObjArray();
1624 /// a1->SetName("a1");
1625 /// list->Add(a1);
1626 /// TH1F *ha1a = new TH1F("ha1a","ha1",100,0,1);
1627 /// TH1F *ha1b = new TH1F("ha1b","ha1",100,0,1);
1628 /// a1->Add(ha1a);
1629 /// a1->Add(ha1b);
1630 /// TObjArray *b1 = new TObjArray();
1631 /// b1->SetName("b1");
1632 /// list->Add(b1);
1633 /// TH1F *hb1a = new TH1F("hb1a","hb1",100,0,1);
1634 /// TH1F *hb1b = new TH1F("hb1b","hb1",100,0,1);
1635 /// b1->Add(hb1a);
1636 /// b1->Add(hb1b);
1637 ///
1638 /// TObjArray *a2 = new TObjArray();
1639 /// a2->SetName("a2");
1640 /// list->Add(a2);
1641 /// TH1S *ha2a = new TH1S("ha2a","ha2",100,0,1);
1642 /// TH1S *ha2b = new TH1S("ha2b","ha2",100,0,1);
1643 /// a2->Add(ha2a);
1644 /// a2->Add(ha2b);
1645 ///
1646 /// T.Branch(list,16000,2);
1647 /// T.Print();
1648 /// }
1649 /// ~~~
1650 
1651 Int_t TTree::Branch(TCollection* li, Int_t bufsize /* = 32000 */, Int_t splitlevel /* = 99 */, const char* name /* = "" */)
1653 
1654  if (!li) {
1655  return 0;
1656  }
1657  TObject* obj = 0;
1658  Int_t nbranches = GetListOfBranches()->GetEntries();
1659  if (li->InheritsFrom(TClonesArray::Class())) {
1660  Error("Branch", "Cannot call this constructor for a TClonesArray");
1661  return 0;
1662  }
1663  Int_t nch = strlen(name);
1664  TString branchname;
1665  TIter next(li);
1666  while ((obj = next())) {
1667  if ((splitlevel > 1) && obj->InheritsFrom(TCollection::Class()) && !obj->InheritsFrom(TClonesArray::Class())) {
1668  TCollection* col = (TCollection*) obj;
1669  if (nch) {
1670  branchname.Form("%s_%s_", name, col->GetName());
1671  } else {
1672  branchname.Form("%s_", col->GetName());
1673  }
1674  Branch(col, bufsize, splitlevel - 1, branchname);
1675  } else {
1676  if (nch && (name[nch-1] == '_')) {
1677  branchname.Form("%s%s", name, obj->GetName());
1678  } else {
1679  if (nch) {
1680  branchname.Form("%s_%s", name, obj->GetName());
1681  } else {
1682  branchname.Form("%s", obj->GetName());
1683  }
1684  }
1685  if (splitlevel > 99) {
1686  branchname += ".";
1687  }
1688  Bronch(branchname, obj->ClassName(), li->GetObjectRef(obj), bufsize, splitlevel - 1);
1689  }
1690  }
1691  return GetListOfBranches()->GetEntries() - nbranches;
1692 }
1693 
1694 ////////////////////////////////////////////////////////////////////////////////
1695 /// Create one branch for each element in the folder.
1696 /// Returns the total number of branches created.
1697 
1698 Int_t TTree::Branch(const char* foldername, Int_t bufsize /* = 32000 */, Int_t splitlevel /* = 99 */)
1700  TObject* ob = gROOT->FindObjectAny(foldername);
1701  if (!ob) {
1702  return 0;
1703  }
1704  if (ob->IsA() != TFolder::Class()) {
1705  return 0;
1706  }
1707  Int_t nbranches = GetListOfBranches()->GetEntries();
1708  TFolder* folder = (TFolder*) ob;
1709  TIter next(folder->GetListOfFolders());
1710  TObject* obj = 0;
1711  char* curname = new char[1000];
1712  char occur[20];
1713  while ((obj = next())) {
1714  snprintf(curname,1000, "%s/%s", foldername, obj->GetName());
1715  if (obj->IsA() == TFolder::Class()) {
1716  Branch(curname, bufsize, splitlevel - 1);
1717  } else {
1718  void* add = (void*) folder->GetListOfFolders()->GetObjectRef(obj);
1719  for (Int_t i = 0; i < 1000; ++i) {
1720  if (curname[i] == 0) {
1721  break;
1722  }
1723  if (curname[i] == '/') {
1724  curname[i] = '.';
1725  }
1726  }
1727  Int_t noccur = folder->Occurence(obj);
1728  if (noccur > 0) {
1729  snprintf(occur,20, "_%d", noccur);
1730  strlcat(curname, occur,1000);
1731  }
1732  TBranchElement* br = (TBranchElement*) Bronch(curname, obj->ClassName(), add, bufsize, splitlevel - 1);
1733  if (br) br->SetBranchFolder();
1734  }
1735  }
1736  delete[] curname;
1737  return GetListOfBranches()->GetEntries() - nbranches;
1738 }
1739 
1740 ////////////////////////////////////////////////////////////////////////////////
1741 /// Create a new TTree Branch.
1742 ///
1743 /// This Branch constructor is provided to support non-objects in
1744 /// a Tree. The variables described in leaflist may be simple
1745 /// variables or structures. // See the two following
1746 /// constructors for writing objects in a Tree.
1747 ///
1748 /// By default the branch buffers are stored in the same file as the Tree.
1749 /// use TBranch::SetFile to specify a different file
1750 ///
1751 /// * address is the address of the first item of a structure.
1752 /// * leaflist is the concatenation of all the variable names and types
1753 /// separated by a colon character :
1754 /// The variable name and the variable type are separated by a slash (/).
1755 /// The variable type may be 0,1 or 2 characters. If no type is given,
1756 /// the type of the variable is assumed to be the same as the previous
1757 /// variable. If the first variable does not have a type, it is assumed
1758 /// of type F by default. The list of currently supported types is given below:
1759 /// - `C` : a character string terminated by the 0 character
1760 /// - `B` : an 8 bit signed integer (`Char_t`)
1761 /// - `b` : an 8 bit unsigned integer (`UChar_t`)
1762 /// - `S` : a 16 bit signed integer (`Short_t`)
1763 /// - `s` : a 16 bit unsigned integer (`UShort_t`)
1764 /// - `I` : a 32 bit signed integer (`Int_t`)
1765 /// - `i` : a 32 bit unsigned integer (`UInt_t`)
1766 /// - `F` : a 32 bit floating point (`Float_t`)
1767 /// - `D` : a 64 bit floating point (`Double_t`)
1768 /// - `L` : a 64 bit signed integer (`Long64_t`)
1769 /// - `l` : a 64 bit unsigned integer (`ULong64_t`)
1770 /// - `O` : [the letter `o`, not a zero] a boolean (`Bool_t`)
1771 ///
1772 /// Arrays of values are supported with the following syntax:
1773 /// - If leaf name has the form var[nelem], where nelem is alphanumeric, then
1774 /// if nelem is a leaf name, it is used as the variable size of the array,
1775 /// otherwise return 0.
1776 /// - If leaf name has the form var[nelem], where nelem is a non-negative integer, then
1777 /// it is used as the fixed size of the array.
1778 /// - If leaf name has the form of a multi-dimensional array (e.g. var[nelem][nelem2])
1779 /// where nelem and nelem2 are non-negative integer) then
1780 /// it is used as a 2 dimensional array of fixed size.
1781 ///
1782 /// Any of other form is not supported.
1783 ///
1784 /// Note that the TTree will assume that all the item are contiguous in memory.
1785 /// On some platform, this is not always true of the member of a struct or a class,
1786 /// due to padding and alignment. Sorting your data member in order of decreasing
1787 /// sizeof usually leads to their being contiguous in memory.
1788 ///
1789 /// * bufsize is the buffer size in bytes for this branch
1790 /// The default value is 32000 bytes and should be ok for most cases.
1791 /// You can specify a larger value (e.g. 256000) if your Tree is not split
1792 /// and each entry is large (Megabytes)
1793 /// A small value for bufsize is optimum if you intend to access
1794 /// the entries in the Tree randomly and your Tree is in split mode.
1795 
1796 TBranch* TTree::Branch(const char* name, void* address, const char* leaflist, Int_t bufsize /* = 32000 */)
1798  TBranch* branch = new TBranch(this, name, address, leaflist, bufsize);
1799  if (branch->IsZombie()) {
1800  delete branch;
1801  branch = 0;
1802  return 0;
1803  }
1804  fBranches.Add(branch);
1805  return branch;
1806 }
1807 
1808 ////////////////////////////////////////////////////////////////////////////////
1809 /// Create a new branch with the object of class classname at address addobj.
1810 ///
1811 /// WARNING:
1812 ///
1813 /// Starting with Root version 3.01, the Branch function uses the new style
1814 /// branches (TBranchElement). To get the old behaviour, you can:
1815 /// - call BranchOld or
1816 /// - call TTree::SetBranchStyle(0)
1817 ///
1818 /// Note that with the new style, classname does not need to derive from TObject.
1819 /// It must derived from TObject if the branch style has been set to 0 (old)
1820 ///
1821 /// Note: See the comments in TBranchElement::SetAddress() for a more
1822 /// detailed discussion of the meaning of the addobj parameter in
1823 /// the case of new-style branches.
1824 ///
1825 /// Use splitlevel < 0 instead of splitlevel=0 when the class
1826 /// has a custom Streamer
1827 ///
1828 /// Note: if the split level is set to the default (99), TTree::Branch will
1829 /// not issue a warning if the class can not be split.
1830 
1831 TBranch* TTree::Branch(const char* name, const char* classname, void* addobj, Int_t bufsize /* = 32000 */, Int_t splitlevel /* = 99 */)
1833  if (fgBranchStyle == 1) {
1834  return Bronch(name, classname, addobj, bufsize, splitlevel);
1835  } else {
1836  if (splitlevel < 0) {
1837  splitlevel = 0;
1838  }
1839  return BranchOld(name, classname, addobj, bufsize, splitlevel);
1840  }
1841 }
1842 
1843 ////////////////////////////////////////////////////////////////////////////////
1844 /// Create a new TTree BranchObject.
1845 ///
1846 /// Build a TBranchObject for an object of class classname.
1847 /// addobj is the address of a pointer to an object of class classname.
1848 /// IMPORTANT: classname must derive from TObject.
1849 /// The class dictionary must be available (ClassDef in class header).
1850 ///
1851 /// This option requires access to the library where the corresponding class
1852 /// is defined. Accessing one single data member in the object implies
1853 /// reading the full object.
1854 /// See the next Branch constructor for a more efficient storage
1855 /// in case the entry consists of arrays of identical objects.
1856 ///
1857 /// By default the branch buffers are stored in the same file as the Tree.
1858 /// use TBranch::SetFile to specify a different file
1859 ///
1860 /// IMPORTANT NOTE about branch names:
1861 ///
1862 /// In case two or more master branches contain subbranches with
1863 /// identical names, one must add a "." (dot) character at the end
1864 /// of the master branch name. This will force the name of the subbranch
1865 /// to be master.subbranch instead of simply subbranch.
1866 /// This situation happens when the top level object (say event)
1867 /// has two or more members referencing the same class.
1868 /// For example, if a Tree has two branches B1 and B2 corresponding
1869 /// to objects of the same class MyClass, one can do:
1870 /// ~~~ {.cpp}
1871 /// tree.Branch("B1.","MyClass",&b1,8000,1);
1872 /// tree.Branch("B2.","MyClass",&b2,8000,1);
1873 /// ~~~
1874 /// if MyClass has 3 members a,b,c, the two instructions above will generate
1875 /// subbranches called B1.a, B1.b ,B1.c, B2.a, B2.b, B2.c
1876 ///
1877 /// bufsize is the buffer size in bytes for this branch
1878 /// The default value is 32000 bytes and should be ok for most cases.
1879 /// You can specify a larger value (e.g. 256000) if your Tree is not split
1880 /// and each entry is large (Megabytes)
1881 /// A small value for bufsize is optimum if you intend to access
1882 /// the entries in the Tree randomly and your Tree is in split mode.
1883 
1884 TBranch* TTree::BranchOld(const char* name, const char* classname, void* addobj, Int_t bufsize /* = 32000 */, Int_t splitlevel /* = 1 */)
1886  TClass* cl = TClass::GetClass(classname);
1887  if (!cl) {
1888  Error("BranchOld", "Cannot find class: '%s'", classname);
1889  return 0;
1890  }
1891  if (!cl->IsTObject()) {
1892  if (fgBranchStyle == 0) {
1893  Fatal("BranchOld", "The requested class ('%s') does not inherit from TObject.\n"
1894  "\tfgBranchStyle is set to zero requesting by default to use BranchOld.\n"
1895  "\tIf this is intentional use Bronch instead of Branch or BranchOld.", classname);
1896  } else {
1897  Fatal("BranchOld", "The requested class ('%s') does not inherit from TObject.\n"
1898  "\tYou can not use BranchOld to store objects of this type.",classname);
1899  }
1900  return 0;
1901  }
1902  TBranch* branch = new TBranchObject(this, name, classname, addobj, bufsize, splitlevel);
1903  fBranches.Add(branch);
1904  if (!splitlevel) {
1905  return branch;
1906  }
1907  // We are going to fully split the class now.
1908  TObjArray* blist = branch->GetListOfBranches();
1909  const char* rdname = 0;
1910  const char* dname = 0;
1911  TString branchname;
1912  char** apointer = (char**) addobj;
1913  TObject* obj = (TObject*) *apointer;
1914  Bool_t delobj = kFALSE;
1915  if (!obj) {
1916  obj = (TObject*) cl->New();
1917  delobj = kTRUE;
1918  }
1919  // Build the StreamerInfo if first time for the class.
1920  BuildStreamerInfo(cl, obj);
1921  // Loop on all public data members of the class and its base classes.
1922  Int_t lenName = strlen(name);
1923  Int_t isDot = 0;
1924  if (name[lenName-1] == '.') {
1925  isDot = 1;
1926  }
1927  TBranch* branch1 = 0;
1928  TRealData* rd = 0;
1929  TRealData* rdi = 0;
1930  TIter nexti(cl->GetListOfRealData());
1931  TIter next(cl->GetListOfRealData());
1932  // Note: This loop results in a full split because the
1933  // real data list includes all data members of
1934  // data members.
1935  while ((rd = (TRealData*) next())) {
1936  if (rd->TestBit(TRealData::kTransient)) continue;
1937 
1938  // Loop over all data members creating branches for each one.
1939  TDataMember* dm = rd->GetDataMember();
1940  if (!dm->IsPersistent()) {
1941  // Do not process members with an "!" as the first character in the comment field.
1942  continue;
1943  }
1944  if (rd->IsObject()) {
1945  // We skip data members of class type.
1946  // But we do build their real data, their
1947  // streamer info, and write their streamer
1948  // info to the current directory's file.
1949  // Oh yes, and we also do this for all of
1950  // their base classes.
1951  TClass* clm = TClass::GetClass(dm->GetFullTypeName());
1952  if (clm) {
1953  BuildStreamerInfo(clm, (char*) obj + rd->GetThisOffset());
1954  }
1955  continue;
1956  }
1957  rdname = rd->GetName();
1958  dname = dm->GetName();
1959  if (cl->CanIgnoreTObjectStreamer()) {
1960  // Skip the TObject base class data members.
1961  // FIXME: This prevents a user from ever
1962  // using these names themself!
1963  if (!strcmp(dname, "fBits")) {
1964  continue;
1965  }
1966  if (!strcmp(dname, "fUniqueID")) {
1967  continue;
1968  }
1969  }
1970  TDataType* dtype = dm->GetDataType();
1971  Int_t code = 0;
1972  if (dtype) {
1973  code = dm->GetDataType()->GetType();
1974  }
1975  // Encode branch name. Use real data member name
1976  branchname = rdname;
1977  if (isDot) {
1978  if (dm->IsaPointer()) {
1979  // FIXME: This is wrong! The asterisk is not usually in the front!
1980  branchname.Form("%s%s", name, &rdname[1]);
1981  } else {
1982  branchname.Form("%s%s", name, &rdname[0]);
1983  }
1984  }
1985  // FIXME: Change this to a string stream.
1986  TString leaflist;
1987  Int_t offset = rd->GetThisOffset();
1988  char* pointer = ((char*) obj) + offset;
1989  if (dm->IsaPointer()) {
1990  // We have a pointer to an object or a pointer to an array of basic types.
1991  TClass* clobj = 0;
1992  if (!dm->IsBasic()) {
1993  clobj = TClass::GetClass(dm->GetTypeName());
1994  }
1995  if (clobj && clobj->InheritsFrom(TClonesArray::Class())) {
1996  // We have a pointer to a clones array.
1997  char* cpointer = (char*) pointer;
1998  char** ppointer = (char**) cpointer;
1999  TClonesArray* li = (TClonesArray*) *ppointer;
2000  if (splitlevel != 2) {
2001  if (isDot) {
2002  branch1 = new TBranchClones(branch,branchname, pointer, bufsize);
2003  } else {
2004  // FIXME: This is wrong! The asterisk is not usually in the front!
2005  branch1 = new TBranchClones(branch,&branchname.Data()[1], pointer, bufsize);
2006  }
2007  blist->Add(branch1);
2008  } else {
2009  if (isDot) {
2010  branch1 = new TBranchObject(branch, branchname, li->ClassName(), pointer, bufsize);
2011  } else {
2012  // FIXME: This is wrong! The asterisk is not usually in the front!
2013  branch1 = new TBranchObject(branch, &branchname.Data()[1], li->ClassName(), pointer, bufsize);
2014  }
2015  blist->Add(branch1);
2016  }
2017  } else if (clobj) {
2018  // We have a pointer to an object.
2019  //
2020  // It must be a TObject object.
2021  if (!clobj->IsTObject()) {
2022  continue;
2023  }
2024  branch1 = new TBranchObject(branch, dname, clobj->GetName(), pointer, bufsize, 0);
2025  if (isDot) {
2026  branch1->SetName(branchname);
2027  } else {
2028  // FIXME: This is wrong! The asterisk is not usually in the front!
2029  // Do not use the first character (*).
2030  branch1->SetName(&branchname.Data()[1]);
2031  }
2032  blist->Add(branch1);
2033  } else {
2034  // We have a pointer to an array of basic types.
2035  //
2036  // Check the comments in the text of the code for an index specification.
2037  const char* index = dm->GetArrayIndex();
2038  if (index[0]) {
2039  // We are a pointer to a varying length array of basic types.
2040  //check that index is a valid data member name
2041  //if member is part of an object (e.g. fA and index=fN)
2042  //index must be changed from fN to fA.fN
2043  TString aindex (rd->GetName());
2044  Ssiz_t rdot = aindex.Last('.');
2045  if (rdot>=0) {
2046  aindex.Remove(rdot+1);
2047  aindex.Append(index);
2048  }
2049  nexti.Reset();
2050  while ((rdi = (TRealData*) nexti())) {
2051  if (rdi->TestBit(TRealData::kTransient)) continue;
2052 
2053  if (!strcmp(rdi->GetName(), index)) {
2054  break;
2055  }
2056  if (!strcmp(rdi->GetName(), aindex)) {
2057  index = rdi->GetName();
2058  break;
2059  }
2060  }
2061 
2062  char vcode = DataTypeToChar((EDataType)code);
2063  // Note that we differentiate between strings and
2064  // char array by the fact that there is NO specified
2065  // size for a string (see next if (code == 1)
2066 
2067  if (vcode) {
2068  leaflist.Form("%s[%s]/%c", &rdname[0], index, vcode);
2069  } else {
2070  Error("BranchOld", "Cannot create branch for rdname: %s code: %d", branchname.Data(), code);
2071  leaflist = "";
2072  }
2073  } else {
2074  // We are possibly a character string.
2075  if (code == 1) {
2076  // We are a character string.
2077  leaflist.Form("%s/%s", dname, "C");
2078  } else {
2079  // Invalid array specification.
2080  // FIXME: We need an error message here.
2081  continue;
2082  }
2083  }
2084  // There are '*' in both the branchname and leaflist, remove them.
2085  TString bname( branchname );
2086  bname.ReplaceAll("*","");
2087  leaflist.ReplaceAll("*","");
2088  // Add the branch to the tree and indicate that the address
2089  // is that of a pointer to be dereferenced before using.
2090  branch1 = new TBranch(branch, bname, *((void**) pointer), leaflist, bufsize);
2091  TLeaf* leaf = (TLeaf*) branch1->GetListOfLeaves()->At(0);
2093  leaf->SetAddress((void**) pointer);
2094  blist->Add(branch1);
2095  }
2096  } else if (dm->IsBasic()) {
2097  // We have a basic type.
2098 
2099  char vcode = DataTypeToChar((EDataType)code);
2100  if (vcode) {
2101  leaflist.Form("%s/%c", rdname, vcode);
2102  } else {
2103  Error("BranchOld", "Cannot create branch for rdname: %s code: %d", branchname.Data(), code);
2104  leaflist = "";
2105  }
2106  branch1 = new TBranch(branch, branchname, pointer, leaflist, bufsize);
2107  branch1->SetTitle(rdname);
2108  blist->Add(branch1);
2109  } else {
2110  // We have a class type.
2111  // Note: This cannot happen due to the rd->IsObject() test above.
2112  // FIXME: Put an error message here just in case.
2113  }
2114  if (branch1) {
2115  branch1->SetOffset(offset);
2116  } else {
2117  Warning("BranchOld", "Cannot process member: '%s'", rdname);
2118  }
2119  }
2120  if (delobj) {
2121  delete obj;
2122  obj = 0;
2123  }
2124  return branch;
2125 }
2126 
2127 ////////////////////////////////////////////////////////////////////////////////
2128 /// Build the optional branch supporting the TRefTable.
2129 /// This branch will keep all the information to find the branches
2130 /// containing referenced objects.
2131 ///
2132 /// At each Tree::Fill, the branch numbers containing the
2133 /// referenced objects are saved to the TBranchRef basket.
2134 /// When the Tree header is saved (via TTree::Write), the branch
2135 /// is saved keeping the information with the pointers to the branches
2136 /// having referenced objects.
2137 
2140  if (!fBranchRef) {
2141  fBranchRef = new TBranchRef(this);
2142  }
2143  return fBranchRef;
2144 }
2145 
2146 ////////////////////////////////////////////////////////////////////////////////
2147 /// Create a new TTree BranchElement.
2148 ///
2149 /// ## WARNING about this new function
2150 ///
2151 /// This function is designed to replace the internal
2152 /// implementation of the old TTree::Branch (whose implementation
2153 /// has been moved to BranchOld).
2154 ///
2155 /// NOTE: The 'Bronch' method supports only one possible calls
2156 /// signature (where the object type has to be specified
2157 /// explicitly and the address must be the address of a pointer).
2158 /// For more flexibility use 'Branch'. Use Bronch only in (rare)
2159 /// cases (likely to be legacy cases) where both the new and old
2160 /// implementation of Branch needs to be used at the same time.
2161 ///
2162 /// This function is far more powerful than the old Branch
2163 /// function. It supports the full C++, including STL and has
2164 /// the same behaviour in split or non-split mode. classname does
2165 /// not have to derive from TObject. The function is based on
2166 /// the new TStreamerInfo.
2167 ///
2168 /// Build a TBranchElement for an object of class classname.
2169 ///
2170 /// addr is the address of a pointer to an object of class
2171 /// classname. The class dictionary must be available (ClassDef
2172 /// in class header).
2173 ///
2174 /// Note: See the comments in TBranchElement::SetAddress() for a more
2175 /// detailed discussion of the meaning of the addr parameter.
2176 ///
2177 /// This option requires access to the library where the
2178 /// corresponding class is defined. Accessing one single data
2179 /// member in the object implies reading the full object.
2180 ///
2181 /// By default the branch buffers are stored in the same file as the Tree.
2182 /// use TBranch::SetFile to specify a different file
2183 ///
2184 /// IMPORTANT NOTE about branch names:
2185 ///
2186 /// In case two or more master branches contain subbranches with
2187 /// identical names, one must add a "." (dot) character at the end
2188 /// of the master branch name. This will force the name of the subbranch
2189 /// to be master.subbranch instead of simply subbranch.
2190 /// This situation happens when the top level object (say event)
2191 /// has two or more members referencing the same class.
2192 /// For example, if a Tree has two branches B1 and B2 corresponding
2193 /// to objects of the same class MyClass, one can do:
2194 /// ~~~ {.cpp}
2195 /// tree.Branch("B1.","MyClass",&b1,8000,1);
2196 /// tree.Branch("B2.","MyClass",&b2,8000,1);
2197 /// ~~~
2198 /// if MyClass has 3 members a,b,c, the two instructions above will generate
2199 /// subbranches called B1.a, B1.b ,B1.c, B2.a, B2.b, B2.c
2200 ///
2201 /// bufsize is the buffer size in bytes for this branch
2202 /// The default value is 32000 bytes and should be ok for most cases.
2203 /// You can specify a larger value (e.g. 256000) if your Tree is not split
2204 /// and each entry is large (Megabytes)
2205 /// A small value for bufsize is optimum if you intend to access
2206 /// the entries in the Tree randomly and your Tree is in split mode.
2207 ///
2208 /// Use splitlevel < 0 instead of splitlevel=0 when the class
2209 /// has a custom Streamer
2210 ///
2211 /// Note: if the split level is set to the default (99), TTree::Branch will
2212 /// not issue a warning if the class can not be split.
2213 
2214 TBranch* TTree::Bronch(const char* name, const char* classname, void* addr, Int_t bufsize /* = 32000 */, Int_t splitlevel /* = 99 */)
2216  return BronchExec(name, classname, addr, kTRUE, bufsize, splitlevel);
2217 }
2218 
2219 ////////////////////////////////////////////////////////////////////////////////
2220 /// Helper function implementing TTree::Bronch and TTree::Branch(const char *name, T &obj);
2221 
2222 TBranch* TTree::BronchExec(const char* name, const char* classname, void* addr, Bool_t isptrptr, Int_t bufsize /* = 32000 */, Int_t splitlevel /* = 99 */)
2224  TClass* cl = TClass::GetClass(classname);
2225  if (!cl) {
2226  Error("Bronch", "Cannot find class:%s", classname);
2227  return 0;
2228  }
2229 
2230  //if splitlevel <= 0 and class has a custom Streamer, we must create
2231  //a TBranchObject. We cannot assume that TClass::ReadBuffer is consistent
2232  //with the custom Streamer. The penalty is that one cannot process
2233  //this Tree without the class library containing the class.
2234 
2235  char* objptr = 0;
2236  if (!isptrptr) {
2237  objptr = (char*)addr;
2238  } else if (addr) {
2239  objptr = *((char**) addr);
2240  }
2241 
2242  if (cl == TClonesArray::Class()) {
2243  TClonesArray* clones = (TClonesArray*) objptr;
2244  if (!clones) {
2245  Error("Bronch", "Pointer to TClonesArray is null");
2246  return 0;
2247  }
2248  if (!clones->GetClass()) {
2249  Error("Bronch", "TClonesArray with no class defined in branch: %s", name);
2250  return 0;
2251  }
2252  if (!clones->GetClass()->HasDataMemberInfo()) {
2253  Error("Bronch", "TClonesArray with no dictionary defined in branch: %s", name);
2254  return 0;
2255  }
2256  bool hasCustomStreamer = clones->GetClass()->TestBit(TClass::kHasCustomStreamerMember);
2257  if (splitlevel > 0) {
2258  if (hasCustomStreamer)
2259  Warning("Bronch", "Using split mode on a class: %s with a custom Streamer", clones->GetClass()->GetName());
2260  } else {
2261  if (hasCustomStreamer) clones->BypassStreamer(kFALSE);
2262  TBranchObject *branch = new TBranchObject(this,name,classname,addr,bufsize,0,/*compress=*/ -1,isptrptr);
2263  fBranches.Add(branch);
2264  return branch;
2265  }
2266  }
2267 
2268  if (cl->GetCollectionProxy()) {
2269  TVirtualCollectionProxy* collProxy = cl->GetCollectionProxy();
2270  //if (!collProxy) {
2271  // Error("Bronch", "%s is missing its CollectionProxy (for branch %s)", classname, name);
2272  //}
2273  TClass* inklass = collProxy->GetValueClass();
2274  if (!inklass && (collProxy->GetType() == 0)) {
2275  Error("Bronch", "%s with no class defined in branch: %s", classname, name);
2276  return 0;
2277  }
2278  if ((splitlevel > 0) && inklass && (inklass->GetCollectionProxy() == 0)) {
2279  ROOT::ESTLType stl = cl->GetCollectionType();
2280  if ((stl != ROOT::kSTLmap) && (stl != ROOT::kSTLmultimap)) {
2281  if (!inklass->HasDataMemberInfo()) {
2282  Error("Bronch", "Container with no dictionary defined in branch: %s", name);
2283  return 0;
2284  }
2285  if (inklass->TestBit(TClass::kHasCustomStreamerMember)) {
2286  Warning("Bronch", "Using split mode on a class: %s with a custom Streamer", inklass->GetName());
2287  }
2288  }
2289  }
2290  //-------------------------------------------------------------------------
2291  // If the splitting switch is enabled, the split level is big enough and
2292  // the collection contains pointers we can split it
2293  //////////////////////////////////////////////////////////////////////////
2294 
2295  TBranch *branch;
2296  if( splitlevel > kSplitCollectionOfPointers && collProxy->HasPointers() )
2297  branch = new TBranchSTL( this, name, collProxy, bufsize, splitlevel );
2298  else
2299  branch = new TBranchElement(this, name, collProxy, bufsize, splitlevel);
2300  fBranches.Add(branch);
2301  if (isptrptr) {
2302  branch->SetAddress(addr);
2303  } else {
2304  branch->SetObject(addr);
2305  }
2306  return branch;
2307  }
2308 
2309  Bool_t hasCustomStreamer = kFALSE;
2310  if (!cl->HasDataMemberInfo() && !cl->GetCollectionProxy()) {
2311  Error("Bronch", "Cannot find dictionary for class: %s", classname);
2312  return 0;
2313  }
2314 
2316  // Not an STL container and the linkdef file had a "-" after the class name.
2317  hasCustomStreamer = kTRUE;
2318  }
2319 
2320  if (splitlevel < 0 || ((splitlevel == 0) && hasCustomStreamer && cl->IsTObject())) {
2321  TBranchObject* branch = new TBranchObject(this, name, classname, addr, bufsize, 0, /*compress=*/ -1, isptrptr);
2322  fBranches.Add(branch);
2323  return branch;
2324  }
2325 
2326  if (cl == TClonesArray::Class()) {
2327  // Special case of TClonesArray.
2328  // No dummy object is created.
2329  // The streamer info is not rebuilt unoptimized.
2330  // No dummy top-level branch is created.
2331  // No splitting is attempted.
2332  TBranchElement* branch = new TBranchElement(this, name, (TClonesArray*) objptr, bufsize, splitlevel%kSplitCollectionOfPointers);
2333  fBranches.Add(branch);
2334  if (isptrptr) {
2335  branch->SetAddress(addr);
2336  } else {
2337  branch->SetObject(addr);
2338  }
2339  return branch;
2340  }
2341 
2342  //
2343  // If we are not given an object to use as an i/o buffer
2344  // then create a temporary one which we will delete just
2345  // before returning.
2346  //
2347 
2348  Bool_t delobj = kFALSE;
2349 
2350  if (!objptr) {
2351  objptr = (char*) cl->New();
2352  delobj = kTRUE;
2353  }
2354 
2355  //
2356  // Avoid splitting unsplittable classes.
2357  //
2358 
2359  if ((splitlevel > 0) && !cl->CanSplit()) {
2360  if (splitlevel != 99) {
2361  Warning("Bronch", "%s cannot be split, resetting splitlevel to 0", cl->GetName());
2362  }
2363  splitlevel = 0;
2364  }
2365 
2366  //
2367  // Make sure the streamer info is built and fetch it.
2368  //
2369  // If we are splitting, then make sure the streamer info
2370  // is built unoptimized (data members are not combined).
2371  //
2372 
2373  TStreamerInfo* sinfo = BuildStreamerInfo(cl, objptr, splitlevel==0);
2374  if (!sinfo) {
2375  Error("Bronch", "Cannot build the StreamerInfo for class: %s", cl->GetName());
2376  return 0;
2377  }
2378 
2379  //
2380  // Do we have a final dot in our name?
2381  //
2382 
2383  // Note: The branch constructor which takes a folder as input
2384  // creates top-level branch names with dots in them to
2385  // indicate the folder hierarchy.
2386  char* dot = (char*) strchr(name, '.');
2387  Int_t nch = strlen(name);
2388  Bool_t dotlast = kFALSE;
2389  if (nch && (name[nch-1] == '.')) {
2390  dotlast = kTRUE;
2391  }
2392 
2393  //
2394  // Create a dummy top level branch object.
2395  //
2396 
2397  Int_t id = -1;
2398  if (splitlevel > 0) {
2399  id = -2;
2400  }
2401  TBranchElement* branch = new TBranchElement(this, name, sinfo, id, objptr, bufsize, splitlevel);
2402  fBranches.Add(branch);
2403 
2404  //
2405  // Do splitting, if requested.
2406  //
2407 
2408  if (splitlevel%kSplitCollectionOfPointers > 0) {
2409  // Loop on all public data members of the class and its base classes and create branches for each one.
2410  TObjArray* blist = branch->GetListOfBranches();
2411  TIter next(sinfo->GetElements());
2412  TStreamerElement* element = 0;
2413  TString bname;
2414  for (id = 0; (element = (TStreamerElement*) next()); ++id) {
2415  if (element->IsA() == TStreamerArtificial::Class()) {
2416  continue;
2417  }
2418  if (element->TestBit(TStreamerElement::kRepeat)) {
2419  continue;
2420  }
2421  if (element->TestBit(TStreamerElement::kCache) && !element->TestBit(TStreamerElement::kWrite)) {
2422  continue;
2423  }
2424  char* pointer = (char*) (objptr + element->GetOffset());
2425  // FIXME: This is not good enough, an STL container can be
2426  // a base, and the test will fail.
2427  // See TBranchElement::InitializeOffsets() for the
2428  // correct test.
2429  Bool_t isBase = (element->IsA() == TStreamerBase::Class());
2430  if (isBase) {
2431  TClass* clbase = element->GetClassPointer();
2432  if ((clbase == TObject::Class()) && cl->CanIgnoreTObjectStreamer()) {
2433  // Note: TStreamerInfo::Compile() leaves this element
2434  // out of the optimized info, although it does
2435  // exists in the non-compiled and non-optimized info.
2436  // FIXME: The test that TStreamerInfo::Compile() uses
2437  // is element->GetType() < 0, so that is what
2438  // we should do as well.
2439  continue;
2440  }
2441  if (clbase->GetListOfRealData()->GetSize() == 0) {
2442  // Do not create a branch for empty bases.
2443  continue;
2444  }
2445  }
2446  if (dot) {
2447  if (dotlast) {
2448  bname.Form("%s%s", name, element->GetFullName());
2449  } else {
2450  // FIXME: We are in the case where we have a top-level
2451  // branch name that was created by the branch
2452  // constructor which takes a folder as input.
2453  // The internal dots in the name are in place of
2454  // of the original slashes and represent the
2455  // folder hierarchy.
2456  if (isBase) {
2457  // FIXME: This is very strange, this is the only case where
2458  // we create a branch for a base class that does
2459  // not have the base class name in the branch name.
2460  // FIXME: This is also quite bad since classes with two
2461  // or more base classes end up with sub-branches
2462  // that have the same name.
2463  bname = name;
2464  } else {
2465  bname.Form("%s.%s", name, element->GetFullName());
2466  }
2467  }
2468  } else {
2469  // Note: For a base class element, this results in the branchname
2470  // being the name of the base class.
2471  bname.Form("%s", element->GetFullName());
2472  }
2473 
2474  if( splitlevel > kSplitCollectionOfPointers && element->GetClass() &&
2475  element->GetClass()->GetCollectionProxy() &&
2476  element->GetClass()->GetCollectionProxy()->HasPointers() )
2477  {
2478  TBranchSTL* brSTL = new TBranchSTL( branch, bname, element->GetClass()->GetCollectionProxy(), bufsize, splitlevel-1, sinfo, id );
2479  blist->Add(brSTL);
2480  }
2481  else
2482  {
2483  TBranchElement* bre = new TBranchElement(branch, bname, sinfo, id, pointer, bufsize, splitlevel - 1);
2484  bre->SetParentClass(cl);
2485  blist->Add(bre);
2486  }
2487  }
2488  }
2489 
2490  //
2491  // Setup our offsets into the user's i/o buffer.
2492  //
2493 
2494  if (isptrptr) {
2495  branch->SetAddress(addr);
2496  } else {
2497  branch->SetObject(addr);
2498  }
2499 
2500  if (delobj) {
2501  cl->Destructor(objptr);
2502  objptr = 0;
2503  }
2504 
2505  return branch;
2506 }
2507 
2508 ////////////////////////////////////////////////////////////////////////////////
2509 /// Browse content of the TTree.
2510 
2511 void TTree::Browse(TBrowser* b)
2513  fBranches.Browse(b);
2514  if (fUserInfo) {
2515  if (strcmp("TList",fUserInfo->GetName())==0) {
2516  fUserInfo->SetName("UserInfo");
2517  b->Add(fUserInfo);
2518  fUserInfo->SetName("TList");
2519  } else {
2520  b->Add(fUserInfo);
2521  }
2522  }
2523 }
2524 
2525 ////////////////////////////////////////////////////////////////////////////////
2526 /// Build a Tree Index (default is TTreeIndex).
2527 /// See a description of the parameters and functionality in
2528 /// TTreeIndex::TTreeIndex().
2529 ///
2530 /// The return value is the number of entries in the Index (< 0 indicates failure).
2531 ///
2532 /// A TTreeIndex object pointed by fTreeIndex is created.
2533 /// This object will be automatically deleted by the TTree destructor.
2534 /// See also comments in TTree::SetTreeIndex().
2535 
2536 Int_t TTree::BuildIndex(const char* majorname, const char* minorname /* = "0" */)
2538  fTreeIndex = GetPlayer()->BuildIndex(this, majorname, minorname);
2539  if (fTreeIndex->IsZombie()) {
2540  delete fTreeIndex;
2541  fTreeIndex = 0;
2542  return 0;
2543  }
2544  return fTreeIndex->GetN();
2545 }
2546 
2547 ////////////////////////////////////////////////////////////////////////////////
2548 /// Build StreamerInfo for class cl.
2549 /// pointer is an optional argument that may contain a pointer to an object of cl.
2550 
2551 TStreamerInfo* TTree::BuildStreamerInfo(TClass* cl, void* pointer /* = 0 */, Bool_t canOptimize /* = kTRUE */ )
2553  if (!cl) {
2554  return 0;
2555  }
2556  cl->BuildRealData(pointer);
2558 
2559  // Create StreamerInfo for all base classes.
2560  TBaseClass* base = 0;
2561  TIter nextb(cl->GetListOfBases());
2562  while((base = (TBaseClass*) nextb())) {
2563  if (base->IsSTLContainer()) {
2564  continue;
2565  }
2566  TClass* clm = TClass::GetClass(base->GetName());
2567  BuildStreamerInfo(clm, pointer, canOptimize);
2568  }
2569  if (sinfo && fDirectory) {
2570  sinfo->ForceWriteInfo(fDirectory->GetFile());
2571  }
2572  return sinfo;
2573 }
2574 
2575 ////////////////////////////////////////////////////////////////////////////////
2576 /// Called by TTree::Fill() when file has reached its maximum fgMaxTreeSize.
2577 /// Create a new file. If the original file is named "myfile.root",
2578 /// subsequent files are named "myfile_1.root", "myfile_2.root", etc.
2579 ///
2580 /// Returns a pointer to the new file.
2581 ///
2582 /// Currently, the automatic change of file is restricted
2583 /// to the case where the tree is in the top level directory.
2584 /// The file should not contain sub-directories.
2585 ///
2586 /// Before switching to a new file, the tree header is written
2587 /// to the current file, then the current file is closed.
2588 ///
2589 /// To process the multiple files created by ChangeFile, one must use
2590 /// a TChain.
2591 ///
2592 /// The new file name has a suffix "_N" where N is equal to fFileNumber+1.
2593 /// By default a Root session starts with fFileNumber=0. One can set
2594 /// fFileNumber to a different value via TTree::SetFileNumber.
2595 /// In case a file named "_N" already exists, the function will try
2596 /// a file named "__N", then "___N", etc.
2597 ///
2598 /// fgMaxTreeSize can be set via the static function TTree::SetMaxTreeSize.
2599 /// The default value of fgMaxTreeSize is 100 Gigabytes.
2600 ///
2601 /// If the current file contains other objects like TH1 and TTree,
2602 /// these objects are automatically moved to the new file.
2603 ///
2604 /// IMPORTANT NOTE:
2605 ///
2606 /// Be careful when writing the final Tree header to the file!
2607 ///
2608 /// Don't do:
2609 /// ~~~ {.cpp}
2610 /// TFile *file = new TFile("myfile.root","recreate");
2611 /// TTree *T = new TTree("T","title");
2612 /// T->Fill(); //loop
2613 /// file->Write();
2614 /// file->Close();
2615 /// ~~~
2616 /// but do the following:
2617 /// ~~~ {.cpp}
2618 /// TFile *file = new TFile("myfile.root","recreate");
2619 /// TTree *T = new TTree("T","title");
2620 /// T->Fill(); //loop
2621 /// file = T->GetCurrentFile(); //to get the pointer to the current file
2622 /// file->Write();
2623 /// file->Close();
2624 /// ~~~
2625 
2628  file->cd();
2629  Write();
2630  Reset();
2631  char* fname = new char[2000];
2632  ++fFileNumber;
2633  char uscore[10];
2634  for (Int_t i = 0; i < 10; ++i) {
2635  uscore[i] = 0;
2636  }
2637  Int_t nus = 0;
2638  // Try to find a suitable file name that does not already exist.
2639  while (nus < 10) {
2640  uscore[nus] = '_';
2641  fname[0] = 0;
2642  strlcpy(fname, file->GetName(),2000);
2643 
2644  if (fFileNumber > 1) {
2645  char* cunder = strrchr(fname, '_');
2646  if (cunder) {
2647  snprintf(cunder,2000-Int_t(cunder-fname), "%s%d", uscore, fFileNumber);
2648  const char* cdot = strrchr(file->GetName(), '.');
2649  if (cdot) {
2650  strlcat(fname, cdot,2000);
2651  }
2652  } else {
2653  char fcount[10];
2654  snprintf(fcount,10, "%s%d", uscore, fFileNumber);
2655  strlcat(fname, fcount,2000);
2656  }
2657  } else {
2658  char* cdot = strrchr(fname, '.');
2659  if (cdot) {
2660  snprintf(cdot,2000-Int_t(fname-cdot), "%s%d", uscore, fFileNumber);
2661  strlcat(fname, strrchr(file->GetName(), '.'),2000);
2662  } else {
2663  char fcount[10];
2664  snprintf(fcount,10, "%s%d", uscore, fFileNumber);
2665  strlcat(fname, fcount,2000);
2666  }
2667  }
2668  if (gSystem->AccessPathName(fname)) {
2669  break;
2670  }
2671  ++nus;
2672  Warning("ChangeFile", "file %s already exist, trying with %d underscores", fname, nus+1);
2673  }
2674  Int_t compress = file->GetCompressionSettings();
2675  TFile* newfile = TFile::Open(fname, "recreate", "chain files", compress);
2676  if (newfile == 0) {
2677  Error("Fill","Failed to open new file %s, continuing as a memory tree.",fname);
2678  } else {
2679  Printf("Fill: Switching to new file: %s", fname);
2680  }
2681  // The current directory may contain histograms and trees.
2682  // These objects must be moved to the new file.
2683  TBranch* branch = 0;
2684  TObject* obj = 0;
2685  while ((obj = file->GetList()->First())) {
2686  file->Remove(obj);
2687  // Histogram: just change the directory.
2688  if (obj->InheritsFrom("TH1")) {
2689  gROOT->ProcessLine(TString::Format("((%s*)0x%lx)->SetDirectory((TDirectory*)0x%lx);", obj->ClassName(), (Long_t) obj, (Long_t) newfile));
2690  continue;
2691  }
2692  // Tree: must save all trees in the old file, reset them.
2693  if (obj->InheritsFrom(TTree::Class())) {
2694  TTree* t = (TTree*) obj;
2695  if (t != this) {
2696  t->AutoSave();
2697  t->Reset();
2698  t->fFileNumber = fFileNumber;
2699  }
2700  t->SetDirectory(newfile);
2701  TIter nextb(t->GetListOfBranches());
2702  while ((branch = (TBranch*)nextb())) {
2703  branch->SetFile(newfile);
2704  }
2705  if (t->GetBranchRef()) {
2706  t->GetBranchRef()->SetFile(newfile);
2707  }
2708  continue;
2709  }
2710  // Not a TH1 or a TTree, move object to new file.
2711  if (newfile) newfile->Append(obj);
2712  file->Remove(obj);
2713  }
2714  delete file;
2715  file = 0;
2716  delete[] fname;
2717  fname = 0;
2718  return newfile;
2719 }
2720 
2721 ////////////////////////////////////////////////////////////////////////////////
2722 /// Check whether or not the address described by the last 3 parameters
2723 /// matches the content of the branch. If a Data Model Evolution conversion
2724 /// is involved, reset the fInfo of the branch.
2725 /// The return values are:
2726 //
2727 /// - kMissingBranch (-5) : Missing branch
2728 /// - kInternalError (-4) : Internal error (could not find the type corresponding to a data type number)
2729 /// - kMissingCompiledCollectionProxy (-3) : Missing compiled collection proxy for a compiled collection
2730 /// - kMismatch (-2) : Non-Class Pointer type given does not match the type expected by the branch
2731 /// - kClassMismatch (-1) : Class Pointer type given does not match the type expected by the branch
2732 /// - kMatch (0) : perfect match
2733 /// - kMatchConversion (1) : match with (I/O) conversion
2734 /// - kMatchConversionCollection (2) : match with (I/O) conversion of the content of a collection
2735 /// - kMakeClass (3) : MakeClass mode so we can not check.
2736 /// - kVoidPtr (4) : void* passed so no check was made.
2737 /// - kNoCheck (5) : Underlying TBranch not yet available so no check was made.
2738 
2739 Int_t TTree::CheckBranchAddressType(TBranch* branch, TClass* ptrClass, EDataType datatype, Bool_t isptr)
2741  if (GetMakeClass()) {
2742  // If we are in MakeClass mode so we do not really use classes.
2743  return kMakeClass;
2744  }
2745 
2746  // Let's determine what we need!
2747  TClass* expectedClass = 0;
2748  EDataType expectedType = kOther_t;
2749  if (0 != branch->GetExpectedType(expectedClass,expectedType) ) {
2750  // Something went wrong, the warning message has already be issued.
2751  return kInternalError;
2752  }
2753  if (expectedClass && datatype == kOther_t && ptrClass == 0) {
2754  if (branch->InheritsFrom( TBranchElement::Class() )) {
2755  TBranchElement* bEl = (TBranchElement*)branch;
2756  bEl->SetTargetClass( expectedClass->GetName() );
2757  }
2758  if (expectedClass && expectedClass->GetCollectionProxy() && dynamic_cast<TEmulatedCollectionProxy*>(expectedClass->GetCollectionProxy())) {
2759  Error("SetBranchAddress", "Unable to determine the type given for the address for \"%s\". "
2760  "The class expected (%s) refers to an stl collection and do not have a compiled CollectionProxy. "
2761  "Please generate the dictionary for this class (%s)",
2762  branch->GetName(), expectedClass->GetName(), expectedClass->GetName());
2764  }
2765  if (!expectedClass->IsLoaded()) {
2766  // The originally expected class does not have a dictionary, it is then plausible that the pointer being passed is the right type
2767  // (we really don't know). So let's express that.
2768  Error("SetBranchAddress", "Unable to determine the type given for the address for \"%s\". "
2769  "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."
2770  "Please generate the dictionary for this class (%s)",
2771  branch->GetName(), expectedClass->GetName(), expectedClass->GetName());
2772  } else {
2773  Error("SetBranchAddress", "Unable to determine the type given for the address for \"%s\". "
2774  "This is probably due to a missing dictionary, the original data class for this branch is %s.", branch->GetName(), expectedClass->GetName());
2775  }
2776  return kClassMismatch;
2777  }
2778  if (expectedClass && ptrClass && (branch->GetMother() == branch)) {
2779  // Top Level branch
2780  if (!isptr) {
2781  Error("SetBranchAddress", "The address for \"%s\" should be the address of a pointer!", branch->GetName());
2782  }
2783  }
2784  if (expectedType == kFloat16_t) {
2785  expectedType = kFloat_t;
2786  }
2787  if (expectedType == kDouble32_t) {
2788  expectedType = kDouble_t;
2789  }
2790  if (datatype == kFloat16_t) {
2791  datatype = kFloat_t;
2792  }
2793  if (datatype == kDouble32_t) {
2794  datatype = kDouble_t;
2795  }
2796 
2797  /////////////////////////////////////////////////////////////////////////////
2798  // Deal with the class renaming
2799  /////////////////////////////////////////////////////////////////////////////
2800 
2801  if( expectedClass && ptrClass &&
2802  expectedClass != ptrClass &&
2803  branch->InheritsFrom( TBranchElement::Class() ) &&
2804  ptrClass->GetSchemaRules() &&
2805  ptrClass->GetSchemaRules()->HasRuleWithSourceClass( expectedClass->GetName() ) ) {
2806  TBranchElement* bEl = (TBranchElement*)branch;
2807 
2808  if ( ptrClass->GetCollectionProxy() && expectedClass->GetCollectionProxy() ) {
2809  if (gDebug > 7)
2810  Info("SetBranchAddress", "Matching STL collection (at least according to the SchemaRuleSet when "
2811  "reading a %s into a %s",expectedClass->GetName(),ptrClass->GetName());
2812 
2813  bEl->SetTargetClass( ptrClass->GetName() );
2814  return kMatchConversion;
2815 
2816  } else if ( !ptrClass->GetConversionStreamerInfo( expectedClass, bEl->GetClassVersion() ) &&
2817  !ptrClass->FindConversionStreamerInfo( expectedClass, bEl->GetCheckSum() ) ) {
2818  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());
2819 
2820  bEl->SetTargetClass( expectedClass->GetName() );
2821  return kClassMismatch;
2822  }
2823  else {
2824 
2825  bEl->SetTargetClass( ptrClass->GetName() );
2826  return kMatchConversion;
2827  }
2828 
2829  } else if (expectedClass && ptrClass && !expectedClass->InheritsFrom(ptrClass)) {
2830 
2831  if (expectedClass->GetCollectionProxy() && ptrClass->GetCollectionProxy() &&
2832  branch->InheritsFrom( TBranchElement::Class() ) &&
2833  expectedClass->GetCollectionProxy()->GetValueClass() &&
2834  ptrClass->GetCollectionProxy()->GetValueClass() )
2835  {
2836  // In case of collection, we know how to convert them, if we know how to convert their content.
2837  // NOTE: we need to extend this to std::pair ...
2838 
2839  TClass *onfileValueClass = expectedClass->GetCollectionProxy()->GetValueClass();
2840  TClass *inmemValueClass = ptrClass->GetCollectionProxy()->GetValueClass();
2841 
2842  if (inmemValueClass->GetSchemaRules() &&
2843  inmemValueClass->GetSchemaRules()->HasRuleWithSourceClass(onfileValueClass->GetName() ) )
2844  {
2845  TBranchElement* bEl = (TBranchElement*)branch;
2846  bEl->SetTargetClass( ptrClass->GetName() );
2848  }
2849  }
2850 
2851  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());
2852  if (branch->InheritsFrom( TBranchElement::Class() )) {
2853  TBranchElement* bEl = (TBranchElement*)branch;
2854  bEl->SetTargetClass( expectedClass->GetName() );
2855  }
2856  return kClassMismatch;
2857 
2858  } else if ((expectedType != kOther_t) && (datatype != kOther_t) && (expectedType != kNoType_t) && (datatype != kNoType_t) && (expectedType != datatype)) {
2859  if (datatype != kChar_t) {
2860  // For backward compatibility we assume that (char*) was just a cast and/or a generic address
2861  Error("SetBranchAddress", "The pointer type given \"%s\" (%d) does not correspond to the type needed \"%s\" (%d) by the branch: %s",
2862  TDataType::GetTypeName(datatype), datatype, TDataType::GetTypeName(expectedType), expectedType, branch->GetName());
2863  return kMismatch;
2864  }
2865  } else if ((expectedClass && (datatype != kOther_t && datatype != kNoType_t && datatype != kInt_t)) ||
2866  (ptrClass && (expectedType != kOther_t && expectedType != kNoType_t && datatype != kInt_t)) ) {
2867  // Sometime a null pointer can look an int, avoid complaining in that case.
2868  if (expectedClass) {
2869  Error("SetBranchAddress", "The pointer type given \"%s\" (%d) does not correspond to the type needed \"%s\" by the branch: %s",
2870  TDataType::GetTypeName(datatype), datatype, expectedClass->GetName(), branch->GetName());
2871  if (branch->InheritsFrom( TBranchElement::Class() )) {
2872  TBranchElement* bEl = (TBranchElement*)branch;
2873  bEl->SetTargetClass( expectedClass->GetName() );
2874  }
2875  } else {
2876  // 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
2877  // a struct).
2878  bool found = false;
2879  if (ptrClass->IsLoaded()) {
2880  TIter next(ptrClass->GetListOfRealData());
2881  TRealData *rdm;
2882  while ((rdm = (TRealData*)next())) {
2883  if (rdm->GetThisOffset() == 0) {
2884  TDataType *dmtype = rdm->GetDataMember()->GetDataType();
2885  if (dmtype) {
2886  EDataType etype = (EDataType)dmtype->GetType();
2887  if (etype == expectedType) {
2888  found = true;
2889  }
2890  }
2891  break;
2892  }
2893  }
2894  } else {
2895  TIter next(ptrClass->GetListOfDataMembers());
2896  TDataMember *dm;
2897  while ((dm = (TDataMember*)next())) {
2898  if (dm->GetOffset() == 0) {
2899  TDataType *dmtype = dm->GetDataType();
2900  if (dmtype) {
2901  EDataType etype = (EDataType)dmtype->GetType();
2902  if (etype == expectedType) {
2903  found = true;
2904  }
2905  }
2906  break;
2907  }
2908  }
2909  }
2910  if (found) {
2911  // let's check the size.
2912  TLeaf *last = (TLeaf*)branch->GetListOfLeaves()->Last();
2913  long len = last->GetOffset() + last->GetLenType() * last->GetLen();
2914  if (len <= ptrClass->Size()) {
2915  return kMatch;
2916  }
2917  }
2918  Error("SetBranchAddress", "The pointer type given \"%s\" does not correspond to the type needed \"%s\" (%d) by the branch: %s",
2919  ptrClass->GetName(), TDataType::GetTypeName(expectedType), expectedType, branch->GetName());
2920  }
2921  return kMismatch;
2922  }
2923  if (expectedClass && expectedClass->GetCollectionProxy() && dynamic_cast<TEmulatedCollectionProxy*>(expectedClass->GetCollectionProxy())) {
2924  Error("SetBranchAddress", writeStlWithoutProxyMsg,
2925  expectedClass->GetName(), branch->GetName(), expectedClass->GetName());
2926  if (branch->InheritsFrom( TBranchElement::Class() )) {
2927  TBranchElement* bEl = (TBranchElement*)branch;
2928  bEl->SetTargetClass( expectedClass->GetName() );
2929  }
2931  }
2932  if (expectedClass && branch->InheritsFrom( TBranchElement::Class() )) {
2933  TBranchElement* bEl = (TBranchElement*)branch;
2934  bEl->SetTargetClass( expectedClass->GetName() );
2935  }
2936  return kMatch;
2937 }
2938 
2939 ////////////////////////////////////////////////////////////////////////////////
2940 /// Create a clone of this tree and copy nentries.
2941 ///
2942 /// By default copy all entries.
2943 /// The compression level of the cloned tree is set to the destination
2944 /// file's compression level.
2945 ///
2946 /// NOTE: Only active branches are copied.
2947 /// NOTE: If the TTree is a TChain, the structure of the first TTree
2948 /// is used for the copy.
2949 ///
2950 /// IMPORTANT: The cloned tree stays connected with this tree until
2951 /// this tree is deleted. In particular, any changes in
2952 /// branch addresses in this tree are forwarded to the
2953 /// clone trees, unless a branch in a clone tree has had
2954 /// its address changed, in which case that change stays in
2955 /// effect. When this tree is deleted, all the addresses of
2956 /// the cloned tree are reset to their default values.
2957 ///
2958 /// If 'option' contains the word 'fast' and nentries is -1, the
2959 /// cloning will be done without unzipping or unstreaming the baskets
2960 /// (i.e., a direct copy of the raw bytes on disk).
2961 ///
2962 /// When 'fast' is specified, 'option' can also contain a sorting
2963 /// order for the baskets in the output file.
2964 ///
2965 /// There are currently 3 supported sorting order:
2966 ///
2967 /// - SortBasketsByOffset (the default)
2968 /// - SortBasketsByBranch
2969 /// - SortBasketsByEntry
2970 ///
2971 /// When using SortBasketsByOffset the baskets are written in the
2972 /// output file in the same order as in the original file (i.e. the
2973 /// baskets are sorted by their offset in the original file; Usually
2974 /// this also means that the baskets are sorted by the index/number of
2975 /// the _last_ entry they contain)
2976 ///
2977 /// When using SortBasketsByBranch all the baskets of each individual
2978 /// branches are stored contiguously. This tends to optimize reading
2979 /// speed when reading a small number (1->5) of branches, since all
2980 /// their baskets will be clustered together instead of being spread
2981 /// across the file. However it might decrease the performance when
2982 /// reading more branches (or the full entry).
2983 ///
2984 /// When using SortBasketsByEntry the baskets with the lowest starting
2985 /// entry are written first. (i.e. the baskets are sorted by the
2986 /// index/number of the first entry they contain). This means that on
2987 /// the file the baskets will be in the order in which they will be
2988 /// needed when reading the whole tree sequentially.
2989 ///
2990 /// For examples of CloneTree, see tutorials:
2991 ///
2992 /// - copytree:
2993 /// A macro to copy a subset of a TTree to a new TTree.
2994 /// The input file has been generated by the program in
2995 /// $ROOTSYS/test/Event with: Event 1000 1 1 1
2996 ///
2997 /// - copytree2:
2998 /// A macro to copy a subset of a TTree to a new TTree.
2999 /// One branch of the new Tree is written to a separate file.
3000 /// The input file has been generated by the program in
3001 /// $ROOTSYS/test/Event with: Event 1000 1 1 1
3002 
3003 TTree* TTree::CloneTree(Long64_t nentries /* = -1 */, Option_t* option /* = "" */)
3005  // Options
3006  Bool_t fastClone = kFALSE;
3007 
3008  TString opt = option;
3009  opt.ToLower();
3010  if (opt.Contains("fast")) {
3011  fastClone = kTRUE;
3012  }
3013 
3014  // If we are a chain, switch to the first tree.
3015  if ((fEntries > 0) && (LoadTree(0) < 0)) {
3016  // FIXME: We need an error message here.
3017  return 0;
3018  }
3019 
3020  // Note: For a tree we get the this pointer, for
3021  // a chain we get the chain's current tree.
3022  TTree* thistree = GetTree();
3023 
3024  // Note: For a chain, the returned clone will be
3025  // a clone of the chain's first tree.
3026  TTree* newtree = (TTree*) thistree->Clone();
3027  if (!newtree) {
3028  return 0;
3029  }
3030 
3031  // The clone should not delete any objects allocated by SetAddress().
3032  TObjArray* branches = newtree->GetListOfBranches();
3033  Int_t nb = branches->GetEntriesFast();
3034  for (Int_t i = 0; i < nb; ++i) {
3035  TBranch* br = (TBranch*) branches->UncheckedAt(i);
3036  if (br->InheritsFrom(TBranchElement::Class())) {
3037  ((TBranchElement*) br)->ResetDeleteObject();
3038  }
3039  }
3040 
3041  // Add the new tree to the list of clones so that
3042  // we can later inform it of changes to branch addresses.
3043  thistree->AddClone(newtree);
3044  if (thistree != this) {
3045  // In case this object is a TChain, add the clone
3046  // also to the TChain's list of clones.
3047  AddClone(newtree);
3048  }
3049 
3050  newtree->Reset();
3051 
3052  TDirectory* ndir = newtree->GetDirectory();
3053  TFile* nfile = 0;
3054  if (ndir) {
3055  nfile = ndir->GetFile();
3056  }
3057  Int_t newcomp = -1;
3058  if (nfile) {
3059  newcomp = nfile->GetCompressionSettings();
3060  }
3061 
3062  //
3063  // Delete non-active branches from the clone.
3064  //
3065  // Note: If we are a chain, this does nothing
3066  // since chains have no leaves.
3067  TObjArray* leaves = newtree->GetListOfLeaves();
3068  Int_t nleaves = leaves->GetEntriesFast();
3069  for (Int_t lndx = 0; lndx < nleaves; ++lndx) {
3070  TLeaf* leaf = (TLeaf*) leaves->UncheckedAt(lndx);
3071  if (!leaf) {
3072  continue;
3073  }
3074  TBranch* branch = leaf->GetBranch();
3075  if (branch && (newcomp > -1)) {
3076  branch->SetCompressionSettings(newcomp);
3077  }
3078  if (!branch || !branch->TestBit(kDoNotProcess)) {
3079  continue;
3080  }
3081  // size might change at each iteration of the loop over the leaves.
3082  nb = branches->GetEntriesFast();
3083  for (Long64_t i = 0; i < nb; ++i) {
3084  TBranch* br = (TBranch*) branches->UncheckedAt(i);
3085  if (br == branch) {
3086  branches->RemoveAt(i);
3087  delete br;
3088  br = 0;
3089  branches->Compress();
3090  break;
3091  }
3092  TObjArray* lb = br->GetListOfBranches();
3093  Int_t nb1 = lb->GetEntriesFast();
3094  for (Int_t j = 0; j < nb1; ++j) {
3095  TBranch* b1 = (TBranch*) lb->UncheckedAt(j);
3096  if (!b1) {
3097  continue;
3098  }
3099  if (b1 == branch) {
3100  lb->RemoveAt(j);
3101  delete b1;
3102  b1 = 0;
3103  lb->Compress();
3104  break;
3105  }
3106  TObjArray* lb1 = b1->GetListOfBranches();
3107  Int_t nb2 = lb1->GetEntriesFast();
3108  for (Int_t k = 0; k < nb2; ++k) {
3109  TBranch* b2 = (TBranch*) lb1->UncheckedAt(k);
3110  if (!b2) {
3111  continue;
3112  }
3113  if (b2 == branch) {
3114  lb1->RemoveAt(k);
3115  delete b2;
3116  b2 = 0;
3117  lb1->Compress();
3118  break;
3119  }
3120  }
3121  }
3122  }
3123  }
3124  leaves->Compress();
3125 
3126  // Copy MakeClass status.
3127  newtree->SetMakeClass(fMakeClass);
3128 
3129  // Copy branch addresses.
3130  CopyAddresses(newtree);
3131 
3132  //
3133  // Copy entries if requested.
3134  //
3135 
3136  if (nentries != 0) {
3137  if (fastClone && (nentries < 0)) {
3138  if ( newtree->CopyEntries( this, -1, option ) < 0 ) {
3139  // There was a problem!
3140  Error("CloneTTree", "TTree has not been cloned\n");
3141  delete newtree;
3142  newtree = 0;
3143  return 0;
3144  }
3145  } else {
3146  newtree->CopyEntries( this, nentries, option );
3147  }
3148  }
3149 
3150  return newtree;
3151 }
3152 
3153 ////////////////////////////////////////////////////////////////////////////////
3154 /// Set branch addresses of passed tree equal to ours.
3155 /// If undo is true, reset the branch address instead of copying them.
3156 /// This insures 'separation' of a cloned tree from its original
3157 
3158 void TTree::CopyAddresses(TTree* tree, Bool_t undo)
3160  // Copy branch addresses starting from branches.
3162  Int_t nbranches = branches->GetEntriesFast();
3163  for (Int_t i = 0; i < nbranches; ++i) {
3164  TBranch* branch = (TBranch*) branches->UncheckedAt(i);
3165  if (branch->TestBit(kDoNotProcess)) {
3166  continue;
3167  }
3168  if (undo) {
3169  TBranch* br = tree->GetBranch(branch->GetName());
3170  tree->ResetBranchAddress(br);
3171  } else {
3172  char* addr = branch->GetAddress();
3173  if (!addr) {
3174  if (branch->IsA() == TBranch::Class()) {
3175  // If the branch was created using a leaflist, the branch itself may not have
3176  // an address but the leaf might already.
3177  TLeaf *firstleaf = (TLeaf*)branch->GetListOfLeaves()->At(0);
3178  if (!firstleaf || firstleaf->GetValuePointer()) {
3179  // Either there is no leaf (and thus no point in copying the address)
3180  // or the leaf has an address but we can not copy it via the branche
3181  // this will be copied via the next loop (over the leaf).
3182  continue;
3183  }
3184  }
3185  // Note: This may cause an object to be allocated.
3186  branch->SetAddress(0);
3187  addr = branch->GetAddress();
3188  }
3189  // FIXME: The GetBranch() function is braindead and may
3190  // not find the branch!
3191  TBranch* br = tree->GetBranch(branch->GetName());
3192  if (br) {
3193  br->SetAddress(addr);
3194  // The copy does not own any object allocated by SetAddress().
3195  if (br->InheritsFrom(TBranchElement::Class())) {
3196  ((TBranchElement*) br)->ResetDeleteObject();
3197  }
3198  } else {
3199  Warning("CopyAddresses", "Could not find branch named '%s' in tree named '%s'", branch->GetName(), tree->GetName());
3200  }
3201  }
3202  }
3203 
3204  // Copy branch addresses starting from leaves.
3205  TObjArray* tleaves = tree->GetListOfLeaves();
3206  Int_t ntleaves = tleaves->GetEntriesFast();
3207  for (Int_t i = 0; i < ntleaves; ++i) {
3208  TLeaf* tleaf = (TLeaf*) tleaves->UncheckedAt(i);
3209  TBranch* tbranch = tleaf->GetBranch();
3210  TBranch* branch = GetBranch(tbranch->GetName());
3211  if (!branch) {
3212  continue;
3213  }
3214  TLeaf* leaf = branch->GetLeaf(tleaf->GetName());
3215  if (!leaf) {
3216  continue;
3217  }
3218  if (branch->TestBit(kDoNotProcess)) {
3219  continue;
3220  }
3221  if (undo) {
3222  // Now we know whether the address has been transfered
3223  tree->ResetBranchAddress(tbranch);
3224  } else {
3225  if (!branch->GetAddress() && !leaf->GetValuePointer()) {
3226  // We should attempts to set the address of the branch.
3227  // something like:
3228  //(TBranchElement*)branch->GetMother()->SetAddress(0)
3229  //plus a few more subtilities (see TBranchElement::GetEntry).
3230  //but for now we go the simplest route:
3231  //
3232  // Note: This may result in the allocation of an object.
3233  branch->SetupAddresses();
3234  }
3235  if (branch->GetAddress()) {
3236  tree->SetBranchAddress(branch->GetName(), (void*) branch->GetAddress());
3237  TBranch* br = tree->GetBranch(branch->GetName());
3238  if (br) {
3239  // The copy does not own any object allocated by SetAddress().
3240  // FIXME: We do too much here, br may not be a top-level branch.
3241  if (br->InheritsFrom(TBranchElement::Class())) {
3242  ((TBranchElement*) br)->ResetDeleteObject();
3243  }
3244  } else {
3245  Warning("CopyAddresses", "Could not find branch named '%s' in tree named '%s'", branch->GetName(), tree->GetName());
3246  }
3247  } else {
3248  tleaf->SetAddress(leaf->GetValuePointer());
3249  }
3250  }
3251  }
3252 
3253  if (undo &&
3254  ( tree->IsA()->InheritsFrom("TNtuple") || tree->IsA()->InheritsFrom("TNtupleD") )
3255  ) {
3256  tree->ResetBranchAddresses();
3257  }
3258 }
3259 
3260 namespace {
3261 
3262  enum EOnIndexError { kDrop, kKeep, kBuild };
3264  static Bool_t R__HandleIndex(EOnIndexError onIndexError, TTree *newtree, TTree *oldtree)
3265  {
3266  // Return true if we should continue to handle indices, false otherwise.
3267 
3268  Bool_t withIndex = kTRUE;
3269 
3270  if ( newtree->GetTreeIndex() ) {
3271  if ( oldtree->GetTree()->GetTreeIndex() == 0 ) {
3272  switch (onIndexError) {
3273  case kDrop:
3274  delete newtree->GetTreeIndex();
3275  newtree->SetTreeIndex(0);
3276  withIndex = kFALSE;
3277  break;
3278  case kKeep:
3279  // Nothing to do really.
3280  break;
3281  case kBuild:
3282  // Build the index then copy it
3283  if (oldtree->GetTree()->BuildIndex(newtree->GetTreeIndex()->GetMajorName(), newtree->GetTreeIndex()->GetMinorName())) {
3284  newtree->GetTreeIndex()->Append(oldtree->GetTree()->GetTreeIndex(), kTRUE);
3285  // Clean up
3286  delete oldtree->GetTree()->GetTreeIndex();
3287  oldtree->GetTree()->SetTreeIndex(0);
3288  }
3289  break;
3290  }
3291  } else {
3292  newtree->GetTreeIndex()->Append(oldtree->GetTree()->GetTreeIndex(), kTRUE);
3293  }
3294  } else if ( oldtree->GetTree()->GetTreeIndex() != 0 ) {
3295  // We discover the first index in the middle of the chain.
3296  switch (onIndexError) {
3297  case kDrop:
3298  // Nothing to do really.
3299  break;
3300  case kKeep: {
3301  TVirtualIndex *index = (TVirtualIndex*) oldtree->GetTree()->GetTreeIndex()->Clone();
3302  index->SetTree(newtree);
3303  newtree->SetTreeIndex(index);
3304  break;
3305  }
3306  case kBuild:
3307  if (newtree->GetEntries() == 0) {
3308  // Start an index.
3309  TVirtualIndex *index = (TVirtualIndex*) oldtree->GetTree()->GetTreeIndex()->Clone();
3310  index->SetTree(newtree);
3311  newtree->SetTreeIndex(index);
3312  } else {
3313  // Build the index so far.
3314  if (newtree->BuildIndex(oldtree->GetTree()->GetTreeIndex()->GetMajorName(), oldtree->GetTree()->GetTreeIndex()->GetMinorName())) {
3315  newtree->GetTreeIndex()->Append(oldtree->GetTree()->GetTreeIndex(), kTRUE);
3316  }
3317  }
3318  break;
3319  }
3320  } else if ( onIndexError == kDrop ) {
3321  // There is no index on this or on tree->GetTree(), we know we have to ignore any further
3322  // index
3323  withIndex = kFALSE;
3324  }
3325  return withIndex;
3326  }
3327 }
3328 
3329 ////////////////////////////////////////////////////////////////////////////////
3330 /// Copy nentries from given tree to this tree.
3331 /// This routines assumes that the branches that intended to be copied are
3332 /// already connected. The typical case is that this tree was created using
3333 /// tree->CloneTree(0).
3334 ///
3335 /// By default copy all entries.
3336 ///
3337 /// Returns number of bytes copied to this tree.
3338 ///
3339 /// If 'option' contains the word 'fast' and nentries is -1, the cloning will be
3340 /// done without unzipping or unstreaming the baskets (i.e., a direct copy of the
3341 /// raw bytes on disk).
3342 ///
3343 /// When 'fast' is specified, 'option' can also contains a sorting order for the
3344 /// baskets in the output file.
3345 ///
3346 /// There are currently 3 supported sorting order:
3347 ///
3348 /// - SortBasketsByOffset (the default)
3349 /// - SortBasketsByBranch
3350 /// - SortBasketsByEntry
3351 ///
3352 /// See TTree::CloneTree for a detailed explanation of the semantics of these 3 options.
3353 ///
3354 /// If the tree or any of the underlying tree of the chain has an index, that index and any
3355 /// index in the subsequent underlying TTree objects will be merged.
3356 ///
3357 /// There are currently three 'options' to control this merging:
3358 /// - NoIndex : all the TTreeIndex object are dropped.
3359 /// - DropIndexOnError : if any of the underlying TTree object do no have a TTreeIndex,
3360 /// they are all dropped.
3361 /// - AsIsIndexOnError [default]: In case of missing TTreeIndex, the resulting TTree index has gaps.
3362 /// - BuildIndexOnError : If any of the underlying TTree objects do not have a TTreeIndex,
3363 /// all TTreeIndex are 'ignored' and the missing piece are rebuilt.
3364 
3365 Long64_t TTree::CopyEntries(TTree* tree, Long64_t nentries /* = -1 */, Option_t* option /* = "" */)
3367  if (!tree) {
3368  return 0;
3369  }
3370  // Options
3371  TString opt = option;
3372  opt.ToLower();
3373  Bool_t fastClone = opt.Contains("fast");
3374  Bool_t withIndex = !opt.Contains("noindex");
3375  EOnIndexError onIndexError;
3376  if (opt.Contains("asisindex")) {
3377  onIndexError = kKeep;
3378  } else if (opt.Contains("buildindex")) {
3379  onIndexError = kBuild;
3380  } else if (opt.Contains("dropindex")) {
3381  onIndexError = kDrop;
3382  } else {
3383  onIndexError = kBuild;
3384  }
3385  Ssiz_t cacheSizeLoc = opt.Index("cachesize=");
3386  Int_t cacheSize = -1;
3387  if (cacheSizeLoc != TString::kNPOS) {
3388  // If the parse faile, cacheSize stays at -1.
3389  Ssiz_t cacheSizeEnd = opt.Index(" ",cacheSizeLoc+10) - (cacheSizeLoc+10);
3390  TSubString cacheSizeStr( opt(cacheSizeLoc+10,cacheSizeEnd) );
3391  auto parseResult = ROOT::FromHumanReadableSize(cacheSizeStr,cacheSize);
3392  if (parseResult == ROOT::EFromHumanReadableSize::kParseFail) {
3393  Warning("CopyEntries","The cachesize option can not be parsed: %s. The default size will be used.",cacheSizeStr.String().Data());
3394  } else if (parseResult == ROOT::EFromHumanReadableSize::kOverflow) {
3395  double m;
3396  const char *munit = nullptr;
3397  ROOT::ToHumanReadableSize(std::numeric_limits<decltype(cacheSize)>::max(),false,&m,&munit);
3398 
3399  Warning("CopyEntries","The cachesize option is too large: %s (%g%s max). The default size will be used.",cacheSizeStr.String().Data(),m,munit);
3400  }
3401  }
3402  if (gDebug > 0 && cacheSize != -1) Info("CopyEntries","Using Cache size: %d\n",cacheSize);
3403 
3404  Long64_t nbytes = 0;
3405  Long64_t treeEntries = tree->GetEntriesFast();
3406  if (nentries < 0) {
3407  nentries = treeEntries;
3408  } else if (nentries > treeEntries) {
3409  nentries = treeEntries;
3410  }
3411 
3412  if (fastClone && (nentries < 0 || nentries == tree->GetEntriesFast())) {
3413  // Quickly copy the basket without decompression and streaming.
3414  Long64_t totbytes = GetTotBytes();
3415  for (Long64_t i = 0; i < nentries; i += tree->GetTree()->GetEntries()) {
3416  if (tree->LoadTree(i) < 0) {
3417  break;
3418  }
3419  if ( withIndex ) {
3420  withIndex = R__HandleIndex( onIndexError, this, tree );
3421  }
3422  if (this->GetDirectory()) {
3423  TFile* file2 = this->GetDirectory()->GetFile();
3424  if (file2 && (file2->GetEND() > TTree::GetMaxTreeSize())) {
3425  if (this->GetDirectory() == (TDirectory*) file2) {
3426  this->ChangeFile(file2);
3427  }
3428  }
3429  }
3430  TTreeCloner cloner(tree->GetTree(), this, option, TTreeCloner::kNoWarnings);
3431  if (cloner.IsValid()) {
3432  this->SetEntries(this->GetEntries() + tree->GetTree()->GetEntries());
3433  if (cacheSize != -1) cloner.SetCacheSize(cacheSize);
3434  cloner.Exec();
3435  } else {
3436  if (i == 0) {
3437  Warning("CopyEntries","%s",cloner.GetWarning());
3438  // If the first cloning does not work, something is really wrong
3439  // (since apriori the source and target are exactly the same structure!)
3440  return -1;
3441  } else {
3442  if (cloner.NeedConversion()) {
3443  TTree *localtree = tree->GetTree();
3444  Long64_t tentries = localtree->GetEntries();
3445  for (Long64_t ii = 0; ii < tentries; ii++) {
3446  if (localtree->GetEntry(ii) <= 0) {
3447  break;
3448  }
3449  this->Fill();
3450  }
3451  if (this->GetTreeIndex()) {
3452  this->GetTreeIndex()->Append(tree->GetTree()->GetTreeIndex(), kTRUE);
3453  }
3454  } else {
3455  Warning("CopyEntries","%s",cloner.GetWarning());
3456  if (tree->GetDirectory() && tree->GetDirectory()->GetFile()) {
3457  Warning("CopyEntries", "Skipped file %s\n", tree->GetDirectory()->GetFile()->GetName());
3458  } else {
3459  Warning("CopyEntries", "Skipped file number %d\n", tree->GetTreeNumber());
3460  }
3461  }
3462  }
3463  }
3464 
3465  }
3466  if (this->GetTreeIndex()) {
3467  this->GetTreeIndex()->Append(0,kFALSE); // Force the sorting
3468  }
3469  nbytes = GetTotBytes() - totbytes;
3470  } else {
3471  if (nentries < 0) {
3472  nentries = treeEntries;
3473  } else if (nentries > treeEntries) {
3474  nentries = treeEntries;
3475  }
3476  Int_t treenumber = -1;
3477  for (Long64_t i = 0; i < nentries; i++) {
3478  if (tree->LoadTree(i) < 0) {
3479  break;
3480  }
3481  if (treenumber != tree->GetTreeNumber()) {
3482  if ( withIndex ) {
3483  withIndex = R__HandleIndex( onIndexError, this, tree );
3484  }
3485  treenumber = tree->GetTreeNumber();
3486  }
3487  if (tree->GetEntry(i) <= 0) {
3488  break;
3489  }
3490  nbytes += this->Fill();
3491  }
3492  if (this->GetTreeIndex()) {
3493  this->GetTreeIndex()->Append(0,kFALSE); // Force the sorting
3494  }
3495  }
3496  return nbytes;
3497 }
3498 
3499 ////////////////////////////////////////////////////////////////////////////////
3500 /// Copy a tree with selection.
3501 ///
3502 /// IMPORTANT:
3503 ///
3504 /// The returned copied tree stays connected with the original tree
3505 /// until the original tree is deleted. In particular, any changes
3506 /// to the branch addresses in the original tree are also made to
3507 /// the copied tree. Any changes made to the branch addresses of the
3508 /// copied tree are overridden anytime the original tree changes its
3509 /// branch addresses. When the original tree is deleted, all the
3510 /// branch addresses of the copied tree are set to zero.
3511 ///
3512 /// For examples of CopyTree, see the tutorials:
3513 ///
3514 /// - copytree:
3515 /// Example macro to copy a subset of a tree to a new tree.
3516 /// The input file was generated by running the program in
3517 /// $ROOTSYS/test/Event in this way:
3518 /// ~~~ {.cpp}
3519 /// ./Event 1000 1 1 1
3520 /// ~~~
3521 /// - copytree2
3522 /// Example macro to copy a subset of a tree to a new tree.
3523 /// One branch of the new tree is written to a separate file.
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 /// - copytree3
3530 /// Example macro to copy a subset of a tree to a new tree.
3531 /// Only selected entries are copied to the new tree.
3532 /// NOTE that only the active branches are copied.
3533 
3534 TTree* TTree::CopyTree(const char* selection, Option_t* option /* = 0 */, Long64_t nentries /* = TTree::kMaxEntries */, Long64_t firstentry /* = 0 */)
3536  GetPlayer();
3537  if (fPlayer) {
3538  return fPlayer->CopyTree(selection, option, nentries, firstentry);
3539  }
3540  return 0;
3541 }
3542 
3543 ////////////////////////////////////////////////////////////////////////////////
3544 /// Create a basket for this tree and given branch.
3545 
3548  if (!branch) {
3549  return 0;
3550  }
3551  return new TBasket(branch->GetName(), GetName(), branch);
3552 }
3553 
3554 ////////////////////////////////////////////////////////////////////////////////
3555 /// Delete this tree from memory or/and disk.
3556 ///
3557 /// - if option == "all" delete Tree object from memory AND from disk
3558 /// all baskets on disk are deleted. All keys with same name
3559 /// are deleted.
3560 /// - if option =="" only Tree object in memory is deleted.
3561 
3562 void TTree::Delete(Option_t* option /* = "" */)
3564  TFile *file = GetCurrentFile();
3565 
3566  // delete all baskets and header from file
3567  if (file && !strcmp(option,"all")) {
3568  if (!file->IsWritable()) {
3569  Error("Delete","File : %s is not writable, cannot delete Tree:%s", file->GetName(),GetName());
3570  return;
3571  }
3572 
3573  //find key and import Tree header in memory
3574  TKey *key = fDirectory->GetKey(GetName());
3575  if (!key) return;
3576 
3577  TDirectory *dirsav = gDirectory;
3578  file->cd();
3579 
3580  //get list of leaves and loop on all the branches baskets
3581  TIter next(GetListOfLeaves());
3582  TLeaf *leaf;
3583  char header[16];
3584  Int_t ntot = 0;
3585  Int_t nbask = 0;
3586  Int_t nbytes,objlen,keylen;
3587  while ((leaf = (TLeaf*)next())) {
3588  TBranch *branch = leaf->GetBranch();
3589  Int_t nbaskets = branch->GetMaxBaskets();
3590  for (Int_t i=0;i<nbaskets;i++) {
3591  Long64_t pos = branch->GetBasketSeek(i);
3592  if (!pos) continue;
3593  TFile *branchFile = branch->GetFile();
3594  if (!branchFile) continue;
3595  branchFile->GetRecordHeader(header,pos,16,nbytes,objlen,keylen);
3596  if (nbytes <= 0) continue;
3597  branchFile->MakeFree(pos,pos+nbytes-1);
3598  ntot += nbytes;
3599  nbask++;
3600  }
3601  }
3602 
3603  // delete Tree header key and all keys with the same name
3604  // A Tree may have been saved many times. Previous cycles are invalid.
3605  while (key) {
3606  ntot += key->GetNbytes();
3607  key->Delete();
3608  delete key;
3609  key = fDirectory->GetKey(GetName());
3610  }
3611  if (dirsav) dirsav->cd();
3612  if (gDebug) printf(" Deleting Tree: %s: %d baskets deleted. Total space freed = %d bytes\n",GetName(),nbask,ntot);
3613  }
3614 
3615  if (fDirectory) {
3616  fDirectory->Remove(this);
3617  //delete the file cache if it points to this Tree
3618  MoveReadCache(file,0);
3619  fDirectory = 0;
3621  }
3622 
3623  // Delete object from CINT symbol table so it can not be used anymore.
3624  gCling->DeleteGlobal(this);
3625 
3626  // Warning: We have intentional invalidated this object while inside a member function!
3627  delete this;
3628 }
3629 
3630  ///////////////////////////////////////////////////////////////////////////////
3631  /// Called by TKey and TObject::Clone to automatically add us to a directory
3632  /// when we are read from a file.
3633 
3636  if (fDirectory == dir) return;
3637  if (fDirectory) {
3638  fDirectory->Remove(this);
3639  // Delete or move the file cache if it points to this Tree
3640  TFile *file = fDirectory->GetFile();
3641  MoveReadCache(file,dir);
3642  }
3643  fDirectory = dir;
3644  TBranch* b = 0;
3645  TIter next(GetListOfBranches());
3646  while((b = (TBranch*) next())) {
3647  b->UpdateFile();
3648  }
3649  if (fBranchRef) {
3651  }
3652  if (fDirectory) fDirectory->Append(this);
3653 }
3654 
3655 ////////////////////////////////////////////////////////////////////////////////
3656 /// Draw expression varexp for specified entries.
3657 /// Returns -1 in case of error or number of selected events in case of success.
3658 ///
3659 /// This function accepts TCut objects as arguments.
3660 /// Useful to use the string operator +
3661 ///
3662 /// Example:
3663 ///
3664 /// ntuple.Draw("x",cut1+cut2+cut3);
3665 
3666 Long64_t TTree::Draw(const char* varexp, const TCut& selection, Option_t* option, Long64_t nentries, Long64_t firstentry)
3668  return TTree::Draw(varexp, selection.GetTitle(), option, nentries, firstentry);
3669 }
3670 
3671 ////////////////////////////////////////////////////////////////////////////////
3672 /// Draw expression varexp for specified entries.
3673 /// Returns -1 in case of error or number of selected events in case of success.
3674 ///
3675 /// varexp is an expression of the general form
3676 /// - "e1" produces a 1-d histogram (TH1F) of expression "e1"
3677 /// - "e1:e2" produces an unbinned 2-d scatter-plot (TGraph) of "e1"
3678 /// on the y-axis versus "e2" on the x-axis
3679 /// - "e1:e2:e3" produces an unbinned 3-d scatter-plot (TPolyMarker3D) of "e1"
3680 /// versus "e2" versus "e3" on the x-, y-, z-axis, respectively.
3681 /// - "e1:e2:e3:e4" produces an unbinned 3-d scatter-plot (TPolyMarker3D) of "e1"
3682 /// versus "e2" versus "e3" and "e4" mapped on the color number.
3683 /// (to create histograms in the 2, 3, and 4 dimensional case, see section "Saving
3684 /// the result of Draw to an histogram")
3685 ///
3686 /// Example:
3687 /// - varexp = x simplest case: draw a 1-Dim distribution of column named x
3688 /// - varexp = sqrt(x) : draw distribution of sqrt(x)
3689 /// - varexp = x*y/z
3690 /// - varexp = y:sqrt(x) 2-Dim distribution of y versus sqrt(x)
3691 /// - varexp = px:py:pz:2.5*E produces a 3-d scatter-plot of px vs py ps pz
3692 /// and the color number of each marker will be 2.5*E.
3693 /// If the color number is negative it is set to 0.
3694 /// If the color number is greater than the current number of colors
3695 /// it is set to the highest color number.The default number of
3696 /// colors is 50. see TStyle::SetPalette for setting a new color palette.
3697 ///
3698 /// Note that the variables e1, e2 or e3 may contain a selection.
3699 /// example, if e1= x*(y<0), the value histogrammed will be x if y<0
3700 /// and will be 0 otherwise.
3701 ///
3702 /// The expressions can use all the operations and build-in functions
3703 /// supported by TFormula (See TFormula::Analyze), including free
3704 /// standing function taking numerical arguments (TMath::Bessel).
3705 /// In addition, you can call member functions taking numerical
3706 /// arguments. For example:
3707 /// ~~~ {.cpp}
3708 /// TMath::BreitWigner(fPx,3,2)
3709 /// event.GetHistogram().GetXaxis().GetXmax()
3710 /// ~~~
3711 /// Note: You can only pass expression that depend on the TTree's data
3712 /// to static functions and you can only call non-static member function
3713 /// with 'fixed' parameters.
3714 ///
3715 /// selection is an expression with a combination of the columns.
3716 /// In a selection all the C++ operators are authorized.
3717 /// The value corresponding to the selection expression is used as a weight
3718 /// to fill the histogram.
3719 /// If the expression includes only boolean operations, the result
3720 /// is 0 or 1. If the result is 0, the histogram is not filled.
3721 /// In general, the expression may be of the form:
3722 /// ~~~ {.cpp}
3723 /// value*(boolean expression)
3724 /// ~~~
3725 /// if boolean expression is true, the histogram is filled with
3726 /// a `weight = value`.
3727 ///
3728 /// Examples:
3729 /// - selection1 = "x<y && sqrt(z)>3.2"
3730 /// - selection2 = "(x+y)*(sqrt(z)>3.2)"
3731 ///
3732 /// - selection1 returns a weight = 0 or 1
3733 /// - selection2 returns a weight = x+y if sqrt(z)>3.2
3734 /// returns a weight = 0 otherwise.
3735 ///
3736 /// option is the drawing option.
3737 /// - See TH1::Draw for the list of all drawing options.
3738 /// - If option COL is specified when varexp has three fields:
3739 /// ~~~ {.cpp}
3740 /// tree.Draw("e1:e2:e3","","col");
3741 /// ~~~
3742 /// a 2D scatter is produced with e1 vs e2, and e3 is mapped on the color
3743 /// table. The colors for e3 are evaluated once in linear scale before
3744 /// painting. Therefore changing the pad to log scale along Z as no effect
3745 /// on the colors.
3746 /// - If option contains the string "goff", no graphics is generated.
3747 ///
3748 /// `nentries` is the number of entries to process (default is all)
3749 /// first is the first entry to process (default is 0)
3750 ///
3751 /// This function returns the number of selected entries. It returns -1
3752 /// if an error occurs.
3753 ///
3754 /// ## Drawing expressions using arrays and array elements
3755 ///
3756 /// Let assumes, a leaf fMatrix, on the branch fEvent, which is a 3 by 3 array,
3757 /// or a TClonesArray.
3758 /// In a TTree::Draw expression you can now access fMatrix using the following
3759 /// syntaxes:
3760 ///
3761 /// | String passed | What is used for each entry of the tree
3762 /// |-----------------|--------------------------------------------------------|
3763 /// | `fMatrix` | the 9 elements of fMatrix |
3764 /// | `fMatrix[][]` | the 9 elements of fMatrix |
3765 /// | `fMatrix[2][2]` | only the elements fMatrix[2][2] |
3766 /// | `fMatrix[1]` | the 3 elements fMatrix[1][0], fMatrix[1][1] and fMatrix[1][2] |
3767 /// | `fMatrix[1][]` | the 3 elements fMatrix[1][0], fMatrix[1][1] and fMatrix[1][2] |
3768 /// | `fMatrix[][0]` | the 3 elements fMatrix[0][0], fMatrix[1][0] and fMatrix[2][0] |
3769 ///
3770 /// "fEvent.fMatrix...." same as "fMatrix..." (unless there is more than one leaf named fMatrix!).
3771 ///
3772 /// In summary, if a specific index is not specified for a dimension, TTree::Draw
3773 /// will loop through all the indices along this dimension. Leaving off the
3774 /// last (right most) dimension of specifying then with the two characters '[]'
3775 /// is equivalent. For variable size arrays (and TClonesArray) the range
3776 /// of the first dimension is recalculated for each entry of the tree.
3777 /// You can also specify the index as an expression of any other variables from the
3778 /// tree.
3779 ///
3780 /// TTree::Draw also now properly handling operations involving 2 or more arrays.
3781 ///
3782 /// Let assume a second matrix fResults[5][2], here are a sample of some
3783 /// of the possible combinations, the number of elements they produce and
3784 /// the loop used:
3785 ///
3786 /// | expression | element(s) | Loop |
3787 /// |----------------------------------|------------|--------------------------|
3788 /// | `fMatrix[2][1] - fResults[5][2]` | one | no loop |
3789 /// | `fMatrix[2][] - fResults[5][2]` | three | on 2nd dim fMatrix |
3790 /// | `fMatrix[2][] - fResults[5][]` | two | on both 2nd dimensions |
3791 /// | `fMatrix[][2] - fResults[][1]` | three | on both 1st dimensions |
3792 /// | `fMatrix[][2] - fResults[][]` | six | on both 1st and 2nd dimensions of fResults |
3793 /// | `fMatrix[][2] - fResults[3][]` | two | on 1st dim of fMatrix and 2nd of fResults (at the same time) |
3794 /// | `fMatrix[][] - fResults[][]` | six | on 1st dim then on 2nd dim |
3795 /// | `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.|
3796 ///
3797 ///
3798 /// In summary, TTree::Draw loops through all unspecified dimensions. To
3799 /// figure out the range of each loop, we match each unspecified dimension
3800 /// from left to right (ignoring ALL dimensions for which an index has been
3801 /// specified), in the equivalent loop matched dimensions use the same index
3802 /// and are restricted to the smallest range (of only the matched dimensions).
3803 /// When involving variable arrays, the range can of course be different
3804 /// for each entry of the tree.
3805 ///
3806 /// So the loop equivalent to "fMatrix[][2] - fResults[3][]" is:
3807 /// ~~~ {.cpp}
3808 /// for (Int_t i0; i < min(3,2); i++) {
3809 /// use the value of (fMatrix[i0][2] - fMatrix[3][i0])
3810 /// }
3811 /// ~~~
3812 /// So the loop equivalent to "fMatrix[][2] - fResults[][]" is:
3813 /// ~~~ {.cpp}
3814 /// for (Int_t i0; i < min(3,5); i++) {
3815 /// for (Int_t i1; i1 < 2; i1++) {
3816 /// use the value of (fMatrix[i0][2] - fMatrix[i0][i1])
3817 /// }
3818 /// }
3819 /// ~~~
3820 /// So the loop equivalent to "fMatrix[][] - fResults[][]" is:
3821 /// ~~~ {.cpp}
3822 /// for (Int_t i0; i < min(3,5); i++) {
3823 /// for (Int_t i1; i1 < min(3,2); i1++) {
3824 /// use the value of (fMatrix[i0][i1] - fMatrix[i0][i1])
3825 /// }
3826 /// }
3827 /// ~~~
3828 /// So the loop equivalent to "fMatrix[][fResults[][]]" is:
3829 /// ~~~ {.cpp}
3830 /// for (Int_t i0; i0 < 3; i0++) {
3831 /// for (Int_t j2; j2 < 5; j2++) {
3832 /// for (Int_t j3; j3 < 2; j3++) {
3833 /// i1 = fResults[j2][j3];
3834 /// use the value of fMatrix[i0][i1]
3835 /// }
3836 /// }
3837 /// ~~~
3838 /// ## Retrieving the result of Draw
3839 ///
3840 /// By default the temporary histogram created is called "htemp", but only in
3841 /// the one dimensional Draw("e1") it contains the TTree's data points. For
3842 /// a two dimensional Draw, the data is filled into a TGraph which is named
3843 /// "Graph". They can be retrieved by calling
3844 /// ~~~ {.cpp}
3845 /// TH1F *htemp = (TH1F*)gPad->GetPrimitive("htemp"); // 1D
3846 /// TGraph *graph = (TGraph*)gPad->GetPrimitive("Graph"); // 2D
3847 /// ~~~
3848 /// For a three and four dimensional Draw the TPolyMarker3D is unnamed, and
3849 /// cannot be retrieved.
3850 ///
3851 /// gPad always contains a TH1 derived object called "htemp" which allows to
3852 /// access the axes:
3853 /// ~~~ {.cpp}
3854 /// TGraph *graph = (TGraph*)gPad->GetPrimitive("Graph"); // 2D
3855 /// TH2F *htemp = (TH2F*)gPad->GetPrimitive("htemp"); // empty, but has axes
3856 /// TAxis *xaxis = htemp->GetXaxis();
3857 /// ~~~
3858 /// ## Saving the result of Draw to an histogram
3859 ///
3860 /// If varexp0 contains >>hnew (following the variable(s) name(s),
3861 /// the new histogram created is called hnew and it is kept in the current
3862 /// directory (and also the current pad). This works for all dimensions.
3863 ///
3864 /// Example:
3865 /// ~~~ {.cpp}
3866 /// tree.Draw("sqrt(x)>>hsqrt","y>0")
3867 /// ~~~
3868 /// will draw `sqrt(x)` and save the histogram as "hsqrt" in the current
3869 /// directory. To retrieve it do:
3870 /// ~~~ {.cpp}
3871 /// TH1F *hsqrt = (TH1F*)gDirectory->Get("hsqrt");
3872 /// ~~~
3873 /// The binning information is taken from the environment variables
3874 /// ~~~ {.cpp}
3875 /// Hist.Binning.?D.?
3876 /// ~~~
3877 /// In addition, the name of the histogram can be followed by up to 9
3878 /// numbers between '(' and ')', where the numbers describe the
3879 /// following:
3880 ///
3881 /// - 1 - bins in x-direction
3882 /// - 2 - lower limit in x-direction
3883 /// - 3 - upper limit in x-direction
3884 /// - 4-6 same for y-direction
3885 /// - 7-9 same for z-direction
3886 ///
3887 /// When a new binning is used the new value will become the default.
3888 /// Values can be skipped.
3889 ///
3890 /// Example:
3891 /// ~~~ {.cpp}
3892 /// tree.Draw("sqrt(x)>>hsqrt(500,10,20)")
3893 /// // plot sqrt(x) between 10 and 20 using 500 bins
3894 /// tree.Draw("sqrt(x):sin(y)>>hsqrt(100,10,60,50,.1,.5)")
3895 /// // plot sqrt(x) against sin(y)
3896 /// // 100 bins in x-direction; lower limit on x-axis is 10; upper limit is 60
3897 /// // 50 bins in y-direction; lower limit on y-axis is .1; upper limit is .5
3898 /// ~~~
3899 /// By default, the specified histogram is reset.
3900 /// To continue to append data to an existing histogram, use "+" in front
3901 /// of the histogram name.
3902 ///
3903 /// A '+' in front of the histogram name is ignored, when the name is followed by
3904 /// binning information as described in the previous paragraph.
3905 /// ~~~ {.cpp}
3906 /// tree.Draw("sqrt(x)>>+hsqrt","y>0")
3907 /// ~~~
3908 /// will not reset `hsqrt`, but will continue filling. This works for 1-D, 2-D
3909 /// and 3-D histograms.
3910 ///
3911 /// ## Accessing collection objects
3912 ///
3913 /// TTree::Draw default's handling of collections is to assume that any
3914 /// request on a collection pertain to it content. For example, if fTracks
3915 /// is a collection of Track objects, the following:
3916 /// ~~~ {.cpp}
3917 /// tree->Draw("event.fTracks.fPx");
3918 /// ~~~
3919 /// will plot the value of fPx for each Track objects inside the collection.
3920 /// Also
3921 /// ~~~ {.cpp}
3922 /// tree->Draw("event.fTracks.size()");
3923 /// ~~~
3924 /// would plot the result of the member function Track::size() for each
3925 /// Track object inside the collection.
3926 /// To access information about the collection itself, TTree::Draw support
3927 /// the '@' notation. If a variable which points to a collection is prefixed
3928 /// or postfixed with '@', the next part of the expression will pertain to
3929 /// the collection object. For example:
3930 /// ~~~ {.cpp}
3931 /// tree->Draw("event.@fTracks.size()");
3932 /// ~~~
3933 /// will plot the size of the collection referred to by `fTracks` (i.e the number
3934 /// of Track objects).
3935 ///
3936 /// ## Drawing 'objects'
3937 ///
3938 /// When a class has a member function named AsDouble or AsString, requesting
3939 /// to directly draw the object will imply a call to one of the 2 functions.
3940 /// If both AsDouble and AsString are present, AsDouble will be used.
3941 /// AsString can return either a char*, a std::string or a TString.s
3942 /// For example, the following
3943 /// ~~~ {.cpp}
3944 /// tree->Draw("event.myTTimeStamp");
3945 /// ~~~
3946 /// will draw the same histogram as
3947 /// ~~~ {.cpp}
3948 /// tree->Draw("event.myTTimeStamp.AsDouble()");
3949 /// ~~~
3950 /// In addition, when the object is a type TString or std::string, TTree::Draw
3951 /// will call respectively `TString::Data` and `std::string::c_str()`
3952 ///
3953 /// If the object is a TBits, the histogram will contain the index of the bit
3954 /// that are turned on.
3955 ///
3956 /// ## Retrieving information about the tree itself.
3957 ///
3958 /// You can refer to the tree (or chain) containing the data by using the
3959 /// string 'This'.
3960 /// You can then could any TTree methods. For example:
3961 /// ~~~ {.cpp}
3962 /// tree->Draw("This->GetReadEntry()");
3963 /// ~~~
3964 /// will display the local entry numbers be read.
3965 /// ~~~ {.cpp}
3966 /// tree->Draw("This->GetUserInfo()->At(0)->GetName()");
3967 /// ~~~
3968 /// will display the name of the first 'user info' object.
3969 ///
3970 /// ## Special functions and variables
3971 ///
3972 /// `Entry$`: A TTree::Draw formula can use the special variable `Entry$`
3973 /// to access the entry number being read. For example to draw every
3974 /// other entry use:
3975 /// ~~~ {.cpp}
3976 /// tree.Draw("myvar","Entry$%2==0");
3977 /// ~~~
3978 /// - `Entry$` : return the current entry number (`== TTree::GetReadEntry()`)
3979 /// - `LocalEntry$` : return the current entry number in the current tree of a
3980 /// chain (`== GetTree()->GetReadEntry()`)
3981 /// - `Entries$` : return the total number of entries (== TTree::GetEntries())
3982 /// - `LocalEntries$` : return the total number of entries in the current tree
3983 /// of a chain (== GetTree()->TTree::GetEntries())
3984 /// - `Length$` : return the total number of element of this formula for this
3985 /// entry (`==TTreeFormula::GetNdata()`)
3986 /// - `Iteration$` : return the current iteration over this formula for this
3987 /// entry (i.e. varies from 0 to `Length$`).
3988 /// - `Length$(formula )` : return the total number of element of the formula
3989 /// given as a parameter.
3990 /// - `Sum$(formula )` : return the sum of the value of the elements of the
3991 /// formula given as a parameter. For example the mean for all the elements in
3992 /// one entry can be calculated with: `Sum$(formula )/Length$(formula )`
3993 /// - `Min$(formula )` : return the minimun (within one TTree entry) of the value of the
3994 /// elements of the formula given as a parameter.
3995 /// - `Max$(formula )` : return the maximum (within one TTree entry) of the value of the
3996 /// elements of the formula given as a parameter.
3997 /// - `MinIf$(formula,condition)`
3998 /// - `MaxIf$(formula,condition)` : return the minimum (maximum) (within one TTree entry)
3999 /// of the value of the elements of the formula given as a parameter
4000 /// if they match the condition. If no element matches the condition,
4001 /// the result is zero. To avoid the resulting peak at zero, use the
4002 /// pattern:
4003 /// ~~~ {.cpp}
4004 /// tree->Draw("MinIf$(formula,condition)","condition");
4005 /// ~~~
4006 /// which will avoid calculation `MinIf$` for the entries that have no match
4007 /// for the condition.
4008 /// - `Alt$(primary,alternate)` : return the value of "primary" if it is available
4009 /// for the current iteration otherwise return the value of "alternate".
4010 /// For example, with arr1[3] and arr2[2]
4011 /// ~~~ {.cpp}
4012 /// tree->Draw("arr1+Alt$(arr2,0)");
4013 /// ~~~
4014 /// will draw arr1[0]+arr2[0] ; arr1[1]+arr2[1] and arr1[2]+0
4015 /// Or with a variable size array arr3
4016 /// ~~~ {.cpp}
4017 /// tree->Draw("Alt$(arr3[0],0)+Alt$(arr3[1],0)+Alt$(arr3[2],0)");
4018 /// ~~~
4019 /// will draw the sum arr3 for the index 0 to min(2,actual_size_of_arr3-1)
4020 /// As a comparison
4021 /// ~~~ {.cpp}
4022 /// tree->Draw("arr3[0]+arr3[1]+arr3[2]");
4023 /// ~~~
4024 /// will draw the sum arr3 for the index 0 to 2 only if the
4025 /// actual_size_of_arr3 is greater or equal to 3.
4026 /// Note that the array in 'primary' is flattened/linearized thus using
4027 /// `Alt$` with multi-dimensional arrays of different dimensions in unlikely
4028 /// to yield the expected results. To visualize a bit more what elements
4029 /// would be matched by TTree::Draw, TTree::Scan can be used:
4030 /// ~~~ {.cpp}
4031 /// tree->Scan("arr1:Alt$(arr2,0)");
4032 /// ~~~
4033 /// will print on one line the value of arr1 and (arr2,0) that will be
4034 /// matched by
4035 /// ~~~ {.cpp}
4036 /// tree->Draw("arr1-Alt$(arr2,0)");
4037 /// ~~~
4038 /// The ternary operator is not directly supported in TTree::Draw however, to plot the
4039 /// equivalent of `var2<20 ? -99 : var1`, you can use:
4040 /// ~~~ {.cpp}
4041 /// tree->Draw("(var2<20)*99+(var2>=20)*var1","");
4042 /// ~~~
4043 ///
4044 /// ## Drawing a user function accessing the TTree data directly
4045 ///
4046 /// If the formula contains a file name, TTree::MakeProxy will be used
4047 /// to load and execute this file. In particular it will draw the
4048 /// result of a function with the same name as the file. The function
4049 /// will be executed in a context where the name of the branches can
4050 /// be used as a C++ variable.
4051 ///
4052 /// For example draw px using the file hsimple.root (generated by the
4053 /// hsimple.C tutorial), we need a file named hsimple.cxx:
4054 /// ~~~ {.cpp}
4055 /// double hsimple() {
4056 /// return px;
4057 /// }
4058 /// ~~~
4059 /// MakeProxy can then be used indirectly via the TTree::Draw interface
4060 /// as follow:
4061 /// ~~~ {.cpp}
4062 /// new TFile("hsimple.root")
4063 /// ntuple->Draw("hsimple.cxx");
4064 /// ~~~
4065 /// A more complete example is available in the tutorials directory:
4066 /// `h1analysisProxy.cxx`, `h1analysProxy.h` and `h1analysisProxyCut.C`
4067 /// which reimplement the selector found in `h1analysis.C`
4068 ///
4069 /// The main features of this facility are:
4070 ///
4071 /// * on-demand loading of branches
4072 /// * ability to use the 'branchname' as if it was a data member
4073 /// * protection against array out-of-bound
4074 /// * ability to use the branch data as object (when the user code is available)
4075 ///
4076 /// See TTree::MakeProxy for more details.
4077 ///
4078 /// ## Making a Profile histogram
4079 ///
4080 /// In case of a 2-Dim expression, one can generate a TProfile histogram
4081 /// instead of a TH2F histogram by specifying option=prof or option=profs
4082 /// or option=profi or option=profg ; the trailing letter select the way
4083 /// the bin error are computed, See TProfile2D::SetErrorOption for
4084 /// details on the differences.
4085 /// The option=prof is automatically selected in case of y:x>>pf
4086 /// where pf is an existing TProfile histogram.
4087 ///
4088 /// ## Making a 2D Profile histogram
4089 ///
4090 /// In case of a 3-Dim expression, one can generate a TProfile2D histogram
4091 /// instead of a TH3F histogram by specifying option=prof or option=profs.
4092 /// or option=profi or option=profg ; the trailing letter select the way
4093 /// the bin error are computed, See TProfile2D::SetErrorOption for
4094 /// details on the differences.
4095 /// The option=prof is automatically selected in case of z:y:x>>pf
4096 /// where pf is an existing TProfile2D histogram.
4097 ///
4098 /// ## Making a 5D plot using GL
4099 ///
4100 /// If option GL5D is specified together with 5 variables, a 5D plot is drawn
4101 /// using OpenGL. See $ROOTSYS/tutorials/tree/staff.C as example.
4102 ///
4103 /// ## Making a parallel coordinates plot
4104 ///
4105 /// In case of a 2-Dim or more expression with the option=para, one can generate
4106 /// a parallel coordinates plot. With that option, the number of dimensions is
4107 /// arbitrary. Giving more than 4 variables without the option=para or
4108 /// option=candle or option=goff will produce an error.
4109 ///
4110 /// ## Making a candle sticks chart
4111 ///
4112 /// In case of a 2-Dim or more expression with the option=candle, one can generate
4113 /// a candle sticks chart. With that option, the number of dimensions is
4114 /// arbitrary. Giving more than 4 variables without the option=para or
4115 /// option=candle or option=goff will produce an error.
4116 ///
4117 /// ## Normalizing the output histogram to 1
4118 ///
4119 /// When option contains "norm" the output histogram is normalized to 1.
4120 ///
4121 /// ## Saving the result of Draw to a TEventList, a TEntryList or a TEntryListArray
4122 ///
4123 /// TTree::Draw can be used to fill a TEventList object (list of entry numbers)
4124 /// instead of histogramming one variable.
4125 /// If varexp0 has the form >>elist , a TEventList object named "elist"
4126 /// is created in the current directory. elist will contain the list
4127 /// of entry numbers satisfying the current selection.
4128 /// If option "entrylist" is used, a TEntryList object is created
4129 /// If the selection contains arrays, vectors or any container class and option
4130 /// "entrylistarray" is used, a TEntryListArray object is created
4131 /// containing also the subentries satisfying the selection, i.e. the indices of
4132 /// the branches which hold containers classes.
4133 /// Example:
4134 /// ~~~ {.cpp}
4135 /// tree.Draw(">>yplus","y>0")
4136 /// ~~~
4137 /// will create a TEventList object named "yplus" in the current directory.
4138 /// In an interactive session, one can type (after TTree::Draw)
4139 /// ~~~ {.cpp}
4140 /// yplus.Print("all")
4141 /// ~~~
4142 /// to print the list of entry numbers in the list.
4143 /// ~~~ {.cpp}
4144 /// tree.Draw(">>yplus", "y>0", "entrylist")
4145 /// ~~~
4146 /// will create a TEntryList object names "yplus" in the current directory
4147 /// ~~~ {.cpp}
4148 /// tree.Draw(">>yplus", "y>0", "entrylistarray")
4149 /// ~~~
4150 /// will create a TEntryListArray object names "yplus" in the current directory
4151 ///
4152 /// By default, the specified entry list is reset.
4153 /// To continue to append data to an existing list, use "+" in front
4154 /// of the list name;
4155 /// ~~~ {.cpp}
4156 /// tree.Draw(">>+yplus","y>0")
4157 /// ~~~
4158 /// will not reset yplus, but will enter the selected entries at the end
4159 /// of the existing list.
4160 ///
4161 /// ## Using a TEventList, TEntryList or TEntryListArray as Input
4162 ///
4163 /// Once a TEventList or a TEntryList object has been generated, it can be used as input
4164 /// for TTree::Draw. Use TTree::SetEventList or TTree::SetEntryList to set the
4165 /// current event list
4166 ///
4167 /// Example 1:
4168 /// ~~~ {.cpp}
4169 /// TEventList *elist = (TEventList*)gDirectory->Get("yplus");
4170 /// tree->SetEventList(elist);
4171 /// tree->Draw("py");
4172 /// ~~~
4173 /// Example 2:
4174 /// ~~~ {.cpp}
4175 /// TEntryList *elist = (TEntryList*)gDirectory->Get("yplus");
4176 /// tree->SetEntryList(elist);
4177 /// tree->Draw("py");
4178 /// ~~~
4179 /// If a TEventList object is used as input, a new TEntryList object is created
4180 /// inside the SetEventList function. In case of a TChain, all tree headers are loaded
4181 /// for this transformation. This new object is owned by the chain and is deleted
4182 /// with it, unless the user extracts it by calling GetEntryList() function.
4183 /// See also comments to SetEventList() function of TTree and TChain.
4184 ///
4185 /// If arrays are used in the selection criteria and TEntryListArray is not used,
4186 /// all the entries that have at least one element of the array that satisfy the selection
4187 /// are entered in the list.
4188 ///
4189 /// Example:
4190 /// ~~~ {.cpp}
4191 /// tree.Draw(">>pyplus","fTracks.fPy>0");
4192 /// tree->SetEventList(pyplus);
4193 /// tree->Draw("fTracks.fPy");
4194 /// ~~~
4195 /// will draw the fPy of ALL tracks in event with at least one track with
4196 /// a positive fPy.
4197 ///
4198 /// To select only the elements that did match the original selection
4199 /// use TEventList::SetReapplyCut or TEntryList::SetReapplyCut.
4200 ///
4201 /// Example:
4202 /// ~~~ {.cpp}
4203 /// tree.Draw(">>pyplus","fTracks.fPy>0");
4204 /// pyplus->SetReapplyCut(kTRUE);
4205 /// tree->SetEventList(pyplus);
4206 /// tree->Draw("fTracks.fPy");
4207 /// ~~~
4208 /// will draw the fPy of only the tracks that have a positive fPy.
4209 ///
4210 /// To draw only the elements that match a selection in case of arrays,
4211 /// you can also use TEntryListArray (faster in case of a more general selection).
4212 ///
4213 /// Example:
4214 /// ~~~ {.cpp}
4215 /// tree.Draw(">>pyplus","fTracks.fPy>0", "entrylistarray");
4216 /// tree->SetEntryList(pyplus);
4217 /// tree->Draw("fTracks.fPy");
4218 /// ~~~
4219 /// will draw the fPy of only the tracks that have a positive fPy,
4220 /// but without redoing the selection.
4221 ///
4222 /// Note: Use tree->SetEventList(0) if you do not want use the list as input.
4223 ///
4224 /// ## How to obtain more info from TTree::Draw
4225 ///
4226 /// Once TTree::Draw has been called, it is possible to access useful
4227 /// information still stored in the TTree object via the following functions:
4228 ///
4229 /// - GetSelectedRows() // return the number of values accepted by the selection expression. In case where no selection was specified, returns the number of values processed.
4230 /// - GetV1() // returns a pointer to the double array of V1
4231 /// - GetV2() // returns a pointer to the double array of V2
4232 /// - GetV3() // returns a pointer to the double array of V3
4233 /// - GetV4() // returns a pointer to the double array of V4
4234 /// - GetW() // returns a pointer to the double array of Weights where weight equal the result of the selection expression.
4235 ///
4236 /// where V1,V2,V3 correspond to the expressions in
4237 /// ~~~ {.cpp}
4238 /// TTree::Draw("V1:V2:V3:V4",selection);
4239 /// ~~~
4240 /// If the expression has more than 4 component use GetVal(index)
4241 ///
4242 /// Example:
4243 /// ~~~ {.cpp}
4244 /// Root > ntuple->Draw("py:px","pz>4");
4245 /// Root > TGraph *gr = new TGraph(ntuple->GetSelectedRows(),
4246 /// ntuple->GetV2(), ntuple->GetV1());
4247 /// Root > gr->Draw("ap"); //draw graph in current pad
4248 /// ~~~
4249 ///
4250 /// A more complete complete tutorial (treegetval.C) shows how to use the
4251 /// GetVal() method.
4252 ///
4253 /// creates a TGraph object with a number of points corresponding to the
4254 /// number of entries selected by the expression "pz>4", the x points of the graph
4255 /// being the px values of the Tree and the y points the py values.
4256 ///
4257 /// Important note: By default TTree::Draw creates the arrays obtained
4258 /// with GetW, GetV1, GetV2, GetV3, GetV4, GetVal with a length corresponding
4259 /// to the parameter fEstimate. The content will be the last `GetSelectedRows() % GetEstimate()`
4260 /// values calculated.
4261 /// By default fEstimate=1000000 and can be modified
4262 /// via TTree::SetEstimate. To keep in memory all the results (in case
4263 /// where there is only one result per entry), use
4264 /// ~~~ {.cpp}
4265 /// tree->SetEstimate(tree->GetEntries()+1); // same as tree->SetEstimate(-1);
4266 /// ~~~
4267 /// You must call SetEstimate if the expected number of selected rows
4268 /// you need to look at is greater than 1000000.
4269 ///
4270 /// You can use the option "goff" to turn off the graphics output
4271 /// of TTree::Draw in the above example.
4272 ///
4273 /// ## Automatic interface to TTree::Draw via the TTreeViewer
4274 ///
4275 /// A complete graphical interface to this function is implemented
4276 /// in the class TTreeViewer.
4277 /// To start the TTreeViewer, three possibilities:
4278 /// - select TTree context menu item "StartViewer"
4279 /// - type the command "TTreeViewer TV(treeName)"
4280 /// - execute statement "tree->StartViewer();"
4281 
4282 Long64_t TTree::Draw(const char* varexp, const char* selection, Option_t* option, Long64_t nentries, Long64_t firstentry)
4284  GetPlayer();
4285  if (fPlayer)
4286  return fPlayer->DrawSelect(varexp,selection,option,nentries,firstentry);
4287  return -1;
4288 }
4289 
4290 ////////////////////////////////////////////////////////////////////////////////
4291 /// Remove some baskets from memory.
4292 
4293 void TTree::DropBaskets()
4295  TBranch* branch = 0;
4297  for (Int_t i = 0; i < nb; ++i) {
4298  branch = (TBranch*) fBranches.UncheckedAt(i);
4299  branch->DropBaskets("all");
4300  }
4301 }
4302 
4303 ////////////////////////////////////////////////////////////////////////////////
4304 /// Drop branch buffers to accommodate nbytes below MaxVirtualsize.
4305 
4308  // Be careful not to remove current read/write buffers.
4309  Int_t ndrop = 0;
4310  Int_t nleaves = fLeaves.GetEntriesFast();
4311  for (Int_t i = 0; i < nleaves; ++i) {
4312  TLeaf* leaf = (TLeaf*) fLeaves.UncheckedAt(i);
4313  TBranch* branch = (TBranch*) leaf->GetBranch();
4314  Int_t nbaskets = branch->GetListOfBaskets()->GetEntries();
4315  for (Int_t j = 0; j < nbaskets - 1; ++j) {
4316  if ((j == branch->GetReadBasket()) || (j == branch->GetWriteBasket())) {
4317  continue;
4318  }
4319  TBasket* basket = (TBasket*)branch->GetListOfBaskets()->UncheckedAt(j);
4320  if (basket) {
4321  ndrop += basket->DropBuffers();
4323  return;
4324  }
4325  }
4326  }
4327  }
4328 }
4329 
4330 ////////////////////////////////////////////////////////////////////////////////
4331 /// Fill all branches.
4332 ///
4333 /// This function loops on all the branches of this tree. For
4334 /// each branch, it copies to the branch buffer (basket) the current
4335 /// values of the leaves data types. If a leaf is a simple data type,
4336 /// a simple conversion to a machine independent format has to be done.
4337 ///
4338 /// This machine independent version of the data is copied into a
4339 /// basket (each branch has its own basket). When a basket is full
4340 /// (32k worth of data by default), it is then optionally compressed
4341 /// and written to disk (this operation is also called committing or
4342 /// 'flushing' the basket). The committed baskets are then
4343 /// immediately removed from memory.
4344 ///
4345 /// The function returns the number of bytes committed to the
4346 /// individual branches.
4347 ///
4348 /// If a write error occurs, the number of bytes returned is -1.
4349 ///
4350 /// If no data are written, because, e.g., the branch is disabled,
4351 /// the number of bytes returned is 0.
4352 ///
4353 /// __The baskets are flushed and the Tree header saved at regular intervals__
4354 ///
4355 /// At regular intervals, when the amount of data written so far is
4356 /// greater than fAutoFlush (see SetAutoFlush) all the baskets are flushed to disk.
4357 /// This makes future reading faster as it guarantees that baskets belonging to nearby
4358 /// entries will be on the same disk region.
4359 /// When the first call to flush the baskets happen, we also take this opportunity
4360 /// to optimize the baskets buffers.
4361 /// We also check if the amount of data written is greater than fAutoSave (see SetAutoSave).
4362 /// In this case we also write the Tree header. This makes the Tree recoverable up to this point
4363 /// in case the program writing the Tree crashes.
4364 /// The decisions to FlushBaskets and Auto Save can be made based either on the number
4365 /// of bytes written (fAutoFlush and fAutoSave negative) or on the number of entries
4366 /// written (fAutoFlush and fAutoSave positive).
4367 /// Note that the user can decide to call FlushBaskets and AutoSave in her event loop
4368 /// base on the number of events written instead of the number of bytes written.
4369 ///
4370 /// Note that calling FlushBaskets too often increases the IO time.
4371 ///
4372 /// Note that calling AutoSave too often increases the IO time and also the file size.
4373 
4376  Int_t nbytes = 0;
4377  Int_t nerror = 0;
4379  if (nb == 1) {
4380  // Case of one single super branch. Automatically update
4381  // all the branch addresses if a new object was created.
4382  TBranch* branch = (TBranch*) fBranches.UncheckedAt(0);
4383  branch->UpdateAddress();
4384  }
4385  if (fBranchRef) {
4386  fBranchRef->Clear();
4387  }
4388  for (Int_t i = 0; i < nb; ++i) {
4389  // Loop over all branches, filling and accumulating bytes written and error counts.
4390  TBranch* branch = (TBranch*) fBranches.UncheckedAt(i);
4391  if (branch->TestBit(kDoNotProcess)) {
4392  continue;
4393  }
4394  Int_t nwrite = branch->Fill();
4395  if (nwrite < 0) {
4396  if (nerror < 2) {
4397  Error("Fill", "Failed filling branch:%s.%s, nbytes=%d, entry=%lld\n"
4398  " This error is symptomatic of a Tree created as a memory-resident Tree\n"
4399  " Instead of doing:\n"
4400  " TTree *T = new TTree(...)\n"
4401  " TFile *f = new TFile(...)\n"
4402  " you should do:\n"
4403  " TFile *f = new TFile(...)\n"
4404  " TTree *T = new TTree(...)",
4405  GetName(), branch->GetName(), nwrite,fEntries+1);
4406  } else {
4407  Error("Fill", "Failed filling branch:%s.%s, nbytes=%d, entry=%lld", GetName(), branch->GetName(), nwrite,fEntries+1);
4408  }
4409  ++nerror;
4410  } else {
4411  nbytes += nwrite;
4412  }
4413  }
4414  if (fBranchRef) {
4415  fBranchRef->Fill();
4416  }
4417  ++fEntries;
4418  if (fEntries > fMaxEntries) {
4419  KeepCircular();
4420  }
4421  if (gDebug > 0) printf("TTree::Fill - A: %d %lld %lld %lld %lld %lld %lld \n",
4423 
4424  if (fAutoFlush != 0 || fAutoSave != 0) {
4425  // Is it time to flush or autosave baskets?
4426  if (fFlushedBytes == 0) {
4427  // Decision can be based initially either on the number of bytes
4428  // or the number of entries written.
4429  if ((fAutoFlush<0 && fZipBytes > -fAutoFlush) ||
4430  (fAutoSave <0 && fZipBytes > -fAutoSave ) ||
4431  (fAutoFlush>0 && fEntries%TMath::Max((Long64_t)1,fAutoFlush) == 0) ||
4432  (fAutoSave >0 && fEntries%TMath::Max((Long64_t)1,fAutoSave) == 0) ) {
4433 
4434  //First call FlushBasket to make sure that fTotBytes is up to date.
4435  FlushBaskets();
4436  OptimizeBaskets(fTotBytes,1,"");
4437  if (gDebug > 0) Info("TTree::Fill","OptimizeBaskets called at entry %lld, fZipBytes=%lld, fFlushedBytes=%lld\n",fEntries,fZipBytes,fFlushedBytes);
4439  fAutoFlush = fEntries; // Use test on entries rather than bytes
4440 
4441  // subsequently in run
4442  if (fAutoSave < 0) {
4443  // Set fAutoSave to the largest integer multiple of
4444  // fAutoFlush events such that fAutoSave*fFlushedBytes
4445  // < (minus the input value of fAutoSave)
4446  if (fZipBytes != 0) {
4448  } else if (fTotBytes != 0) {
4450  } else {
4451  TBufferFile b(TBuffer::kWrite, 10000);
4452  TTree::Class()->WriteBuffer(b, (TTree*) this);
4453  Long64_t total = b.Length();
4455  }
4456  } else if(fAutoSave > 0) {
4458  }
4459  if (fAutoSave!=0 && fEntries >= fAutoSave) AutoSave(); // FlushBaskets not called in AutoSave
4460  if (gDebug > 0) Info("TTree::Fill","First AutoFlush. fAutoFlush = %lld, fAutoSave = %lld\n", fAutoFlush, fAutoSave);
4461  }
4462  } else if (fNClusterRange && fAutoFlush && ( (fEntries-fClusterRangeEnd[fNClusterRange-1]) % fAutoFlush == 0) ) {
4463  if (fAutoSave != 0 && fEntries%fAutoSave == 0) {
4464  //We are at an AutoSave point. AutoSave flushes baskets and saves the Tree header
4465  AutoSave("flushbaskets");
4466  if (gDebug > 0) Info("TTree::Fill","AutoSave called at entry %lld, fZipBytes=%lld, fSavedBytes=%lld\n",fEntries,fZipBytes,fSavedBytes);
4467  } else {
4468  //We only FlushBaskets
4469  FlushBaskets();
4470  if (gDebug > 0) Info("TTree::Fill","FlushBasket called at entry %lld, fZipBytes=%lld, fFlushedBytes=%lld\n",fEntries,fZipBytes,fFlushedBytes);
4471  }
4473  } else if (fNClusterRange == 0 && fEntries > 1 && fAutoFlush && fEntries%fAutoFlush == 0) {
4474  if (fAutoSave != 0 && fEntries%fAutoSave == 0) {
4475  //We are at an AutoSave point. AutoSave flushes baskets and saves the Tree header
4476  AutoSave("flushbaskets");
4477  if (gDebug > 0) Info("TTree::Fill","AutoSave called at entry %lld, fZipBytes=%lld, fSavedBytes=%lld\n",fEntries,fZipBytes,fSavedBytes);
4478  } else {
4479  //We only FlushBaskets
4480  FlushBaskets();
4481  if (gDebug > 0) Info("TTree::Fill","FlushBasket called at entry %lld, fZipBytes=%lld, fFlushedBytes=%lld\n",fEntries,fZipBytes,fFlushedBytes);
4482  }
4484  }
4485  }
4486  // Check that output file is still below the maximum size.
4487  // If above, close the current file and continue on a new file.
4488  // Currently, the automatic change of file is restricted
4489  // to the case where the tree is in the top level directory.
4490  if (!fDirectory) {
4491  return nbytes;
4492  }
4493  TFile* file = fDirectory->GetFile();
4494  if (file && (file->GetEND() > fgMaxTreeSize)) {
4495  if (fDirectory == (TDirectory*) file) {
4496  ChangeFile(file);
4497  }
4498  }
4499  if (nerror) {
4500  return -1;
4501  }
4502  return nbytes;
4503 }
4504 
4505 ////////////////////////////////////////////////////////////////////////////////
4506 /// Search in the array for a branch matching the branch name,
4507 /// with the branch possibly expressed as a 'full' path name (with dots).
4508 
4509 static TBranch *R__FindBranchHelper(TObjArray *list, const char *branchname) {
4510  if (list==0 || branchname == 0 || branchname[0] == '\0') return 0;
4511 
4512  Int_t nbranches = list->GetEntries();
4513 
4514  UInt_t brlen = strlen(branchname);
4515 
4516  for(Int_t index = 0; index < nbranches; ++index) {
4517  TBranch *where = (TBranch*)list->UncheckedAt(index);
4518 
4519  const char *name = where->GetName();
4520  UInt_t len = strlen(name);
4521  if (len && name[len-1]==']') {
4522  const char *dim = strchr(name,'[');
4523  if (dim) {
4524  len = dim - name;
4525  }
4526  }
4527  if (brlen == len && strncmp(branchname,name,len)==0) {
4528  return where;
4529  }
4530  TBranch *next = 0;
4531  if ((brlen >= len) && (branchname[len] == '.')
4532  && strncmp(name, branchname, len) == 0) {
4533  // The prefix subbranch name match the branch name.
4534 
4535  next = where->FindBranch(branchname);
4536  if (!next) {
4537  next = where->FindBranch(branchname+len+1);
4538  }
4539  if (next) return next;
4540  }
4541  const char *dot = strchr((char*)branchname,'.');
4542  if (dot) {
4543  if (len==(size_t)(dot-branchname) &&
4544  strncmp(branchname,name,dot-branchname)==0 ) {
4545  return R__FindBranchHelper(where->GetListOfBranches(),dot+1);
4546  }
4547  }
4548  }
4549  return 0;
4550 }
4551 
4552 ////////////////////////////////////////////////////////////////////////////////
4553 /// Return the branch that correspond to the path 'branchname', which can
4554 /// include the name of the tree or the omitted name of the parent branches.
4555 /// In case of ambiguity, returns the first match.
4556 
4557 TBranch* TTree::FindBranch(const char* branchname)
4559  // We already have been visited while recursively looking
4560  // through the friends tree, let return
4562  return 0;
4563  }
4564 
4565  TBranch* branch = 0;
4566  // If the first part of the name match the TTree name, look for the right part in the
4567  // list of branches.
4568  // This will allow the branchname to be preceded by
4569  // the name of this tree.
4570  if (strncmp(fName.Data(),branchname,fName.Length())==0 && branchname[fName.Length()]=='.') {
4571  branch = R__FindBranchHelper( GetListOfBranches(), branchname + fName.Length() + 1);
4572  if (branch) return branch;
4573  }
4574  // If we did not find it, let's try to find the full name in the list of branches.
4575  branch = R__FindBranchHelper(GetListOfBranches(), branchname);
4576  if (branch) return branch;
4577 
4578  // If we still did not find, let's try to find it within each branch assuming it does not the branch name.
4579  TIter next(GetListOfBranches());
4580  while ((branch = (TBranch*) next())) {
4581  TBranch* nestedbranch = branch->FindBranch(branchname);
4582  if (nestedbranch) {
4583  return nestedbranch;
4584  }
4585  }
4586 
4587  // Search in list of friends.
4588  if (!fFriends) {
4589  return 0;
4590  }
4591  TFriendLock lock(this, kFindBranch);
4592  TIter nextf(fFriends);
4593  TFriendElement* fe = 0;
4594  while ((fe = (TFriendElement*) nextf())) {
4595  TTree* t = fe->GetTree();
4596  if (!t) {
4597  continue;
4598  }
4599  // If the alias is present replace it with the real name.
4600  const char *subbranch = strstr(branchname, fe->GetName());
4601  if (subbranch != branchname) {
4602  subbranch = 0;
4603  }
4604  if (subbranch) {
4605  subbranch += strlen(fe->GetName());
4606  if (*subbranch != '.') {
4607  subbranch = 0;
4608  } else {
4609  ++subbranch;
4610  }
4611  }
4612  std::ostringstream name;
4613  if (subbranch) {
4614  name << t->GetName() << "." << subbranch;
4615  } else {
4616  name << branchname;
4617  }
4618  branch = t->FindBranch(name.str().c_str());
4619  if (branch) {
4620  return branch;
4621  }
4622  }
4623  return 0;
4624 }
4625 
4626 ////////////////////////////////////////////////////////////////////////////////
4627 /// Find leaf..
4628 
4629 TLeaf* TTree::FindLeaf(const char* searchname)
4631  // We already have been visited while recursively looking
4632  // through the friends tree, let's return.
4633  if (kFindLeaf & fFriendLockStatus) {
4634  return 0;
4635  }
4636 
4637  // This will allow the branchname to be preceded by
4638  // the name of this tree.
4639  char* subsearchname = (char*) strstr(searchname, GetName());
4640  if (subsearchname != searchname) {
4641  subsearchname = 0;
4642  }
4643  if (subsearchname) {
4644  subsearchname += strlen(GetName());
4645  if (*subsearchname != '.') {
4646  subsearchname = 0;
4647  } else {
4648  ++subsearchname;
4649  if (subsearchname[0]==0) {
4650  subsearchname = 0;
4651  }
4652  }
4653  }
4654 
4655  TString leafname;
4656  TString leaftitle;
4657  TString longname;
4658  TString longtitle;
4659 
4660  // For leaves we allow for one level up to be prefixed to the name.
4661  TIter next(GetListOfLeaves());
4662  TLeaf* leaf = 0;
4663  while ((leaf = (TLeaf*) next())) {
4664  leafname = leaf->GetName();
4665  Ssiz_t dim = leafname.First('[');
4666  if (dim >= 0) leafname.Remove(dim);
4667 
4668  if (leafname == searchname) {
4669  return leaf;
4670  }
4671  if (subsearchname && leafname == subsearchname) {
4672  return leaf;
4673  }
4674  // The TLeafElement contains the branch name
4675  // in its name, let's use the title.
4676  leaftitle = leaf->GetTitle();
4677  dim = leaftitle.First('[');
4678  if (dim >= 0) leaftitle.Remove(dim);
4679 
4680  if (leaftitle == searchname) {
4681  return leaf;
4682  }
4683  if (subsearchname && leaftitle == subsearchname) {
4684  return leaf;
4685  }
4686  TBranch* branch = leaf->GetBranch();
4687  if (branch) {
4688  longname.Form("%s.%s",branch->GetName(),leafname.Data());
4689  dim = longname.First('[');
4690  if (dim>=0) longname.Remove(dim);
4691  if (longname == searchname) {
4692  return leaf;
4693  }
4694  if (subsearchname && longname == subsearchname) {
4695  return leaf;
4696  }
4697  longtitle.Form("%s.%s",branch->GetName(),leaftitle.Data());
4698  dim = longtitle.First('[');
4699  if (dim>=0) longtitle.Remove(dim);
4700  if (longtitle == searchname) {
4701  return leaf;
4702  }
4703  if (subsearchname && longtitle == subsearchname) {
4704  return leaf;
4705  }
4706  // The following is for the case where the branch is only
4707  // a sub-branch. Since we do not see it through
4708  // TTree::GetListOfBranches, we need to see it indirectly.
4709  // This is the less sturdy part of this search ... it may
4710  // need refining ...
4711  if (strstr(searchname, ".") && !strcmp(searchname, branch->GetName())) {
4712  return leaf;
4713  }
4714  if (subsearchname && strstr(subsearchname, ".") && !strcmp(subsearchname, branch->GetName())) {
4715  return leaf;
4716  }
4717  }
4718  }
4719  // Search in list of friends.
4720  if (!fFriends) {
4721  return 0;
4722  }
4723  TFriendLock lock(this, kFindLeaf);
4724  TIter nextf(fFriends);
4725  TFriendElement* fe = 0;
4726  while ((fe = (TFriendElement*) nextf())) {
4727  TTree* t = fe->GetTree();
4728  if (!t) {
4729  continue;
4730  }
4731  // If the alias is present replace it with the real name.
4732  subsearchname = (char*) strstr(searchname, fe->GetName());
4733  if (subsearchname != searchname) {
4734  subsearchname = 0;
4735  }
4736  if (subsearchname) {
4737  subsearchname += strlen(fe->GetName());
4738  if (*subsearchname != '.') {
4739  subsearchname = 0;
4740  } else {
4741  ++subsearchname;
4742  }
4743  }
4744  if (subsearchname) {
4745  leafname.Form("%s.%s",t->GetName(),subsearchname);
4746  } else {
4747  leafname = searchname;
4748  }
4749  leaf = t->FindLeaf(leafname);
4750  if (leaf) {
4751  return leaf;
4752  }
4753  }
4754  return 0;
4755 }
4756 
4757 ////////////////////////////////////////////////////////////////////////////////
4758 /// Fit a projected item(s) from a tree.
4759 ///
4760 /// funcname is a TF1 function.
4761 ///
4762 /// See TTree::Draw() for explanations of the other parameters.
4763 ///
4764 /// By default the temporary histogram created is called htemp.
4765 /// If varexp contains >>hnew , the new histogram created is called hnew
4766 /// and it is kept in the current directory.
4767 ///
4768 /// The function returns the number of selected entries.
4769 ///
4770 /// Example:
4771 /// ~~~ {.cpp}
4772 /// tree.Fit(pol4,"sqrt(x)>>hsqrt","y>0")
4773 /// ~~~
4774 /// will fit sqrt(x) and save the histogram as "hsqrt" in the current
4775 /// directory.
4776 ///
4777 /// See also TTree::UnbinnedFit
4778 ///
4779 /// ## Return status
4780 ///
4781 /// The function returns the status of the histogram fit (see TH1::Fit)
4782 /// If no entries were selected, the function returns -1;
4783 /// (i.e. fitResult is null if the fit is OK)
4784 
4785 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)
4787  GetPlayer();
4788  if (fPlayer) {
4789  return fPlayer->Fit(funcname, varexp, selection, option, goption, nentries, firstentry);
4790  }
4791  return -1;
4792 }
4793 
4794 ////////////////////////////////////////////////////////////////////////////////
4795 /// Write to disk all the basket that have not yet been individually written.
4796 ///
4797 /// Return the number of bytes written or -1 in case of write error.
4798 
4799 Int_t TTree::FlushBaskets() const
4801  if (!fDirectory) return 0;
4802  Int_t nbytes = 0;
4803  Int_t nerror = 0;
4804  TObjArray *lb = const_cast<TTree*>(this)->GetListOfBranches();
4805  Int_t nb = lb->GetEntriesFast();
4806  for (Int_t j = 0; j < nb; j++) {
4807  TBranch* branch = (TBranch*) lb->UncheckedAt(j);
4808  if (branch) {
4809  Int_t nwrite = branch->FlushBaskets();
4810  if (nwrite<0) {
4811  ++nerror;
4812  } else {
4813  nbytes += nwrite;
4814  }
4815  }
4816  }
4817  if (nerror) {
4818  return -1;
4819  } else {
4820  return nbytes;
4821  }
4822 }
4823 
4824 ////////////////////////////////////////////////////////////////////////////////
4825 /// Returns the expanded value of the alias. Search in the friends if any.
4826 
4827 const char* TTree::GetAlias(const char* aliasName) const
4829  // We already have been visited while recursively looking
4830  // through the friends tree, let's return.
4831  if (kGetAlias & fFriendLockStatus) {
4832  return 0;
4833  }
4834  if (fAliases) {
4835  TObject* alias = fAliases->FindObject(aliasName);
4836  if (alias) {
4837  return alias->GetTitle();
4838  }
4839  }
4840  if (!fFriends) {
4841  return 0;
4842  }
4843  TFriendLock lock(const_cast<TTree*>(this), kGetAlias);
4844  TIter nextf(fFriends);
4845  TFriendElement* fe = 0;
4846  while ((fe = (TFriendElement*) nextf())) {
4847  TTree* t = fe->GetTree();
4848  if (t) {
4849  const char* alias = t->GetAlias(aliasName);
4850  if (alias) {
4851  return alias;
4852  }
4853  const char* subAliasName = strstr(aliasName, fe->GetName());
4854  if (subAliasName && (subAliasName[strlen(fe->GetName())] == '.')) {
4855  alias = t->GetAlias(aliasName + strlen(fe->GetName()) + 1);
4856  if (alias) {
4857  return alias;
4858  }
4859  }
4860  }
4861  }
4862  return 0;
4863 }
4864 
4865 ////////////////////////////////////////////////////////////////////////////////
4866 /// Return pointer to the branch with the given name in this tree or its friends.
4867 
4868 TBranch* TTree::GetBranch(const char* name)
4870  if (name == 0) return 0;
4871 
4872  // We already have been visited while recursively
4873  // looking through the friends tree, let's return.
4874  if (kGetBranch & fFriendLockStatus) {
4875  return 0;
4876  }
4877 
4878  // Search using branches.
4880  for (Int_t i = 0; i < nb; i++) {
4881  TBranch* branch = (TBranch*) fBranches.UncheckedAt(i);
4882  if (!strcmp(branch->GetName(), name)) {
4883  return branch;
4884  }
4885  TObjArray* lb = branch->GetListOfBranches();
4886  Int_t nb1 = lb->GetEntriesFast();
4887  for (Int_t j = 0; j < nb1; j++) {
4888  TBranch* b1 = (TBranch*) lb->UncheckedAt(j);
4889  if (!strcmp(b1->GetName(), name)) {
4890  return b1;
4891  }
4892  TObjArray* lb1 = b1->GetListOfBranches();
4893  Int_t nb2 = lb1->GetEntriesFast();
4894  for (Int_t k = 0; k < nb2; k++) {
4895  TBranch* b2 = (TBranch*) lb1->UncheckedAt(k);
4896  if (!strcmp(b2->GetName(), name)) {
4897  return b2;
4898  }
4899  }
4900  }
4901  }
4902 
4903  // Search using leaves.
4904  TObjArray* leaves = GetListOfLeaves();
4905  Int_t nleaves = leaves->GetEntriesFast();
4906  for (Int_t i = 0; i < nleaves; i++) {
4907  TLeaf* leaf = (TLeaf*) leaves->UncheckedAt(i);
4908  TBranch* branch = leaf->GetBranch();
4909  if (!strcmp(branch->GetName(), name)) {
4910  return branch;
4911  }
4912  }
4913 
4914  if (!fFriends) {
4915  return 0;
4916  }
4917 
4918  // Search in list of friends.
4919  TFriendLock lock(this, kGetBranch);
4920  TIter next(fFriends);
4921  TFriendElement* fe = 0;
4922  while ((fe = (TFriendElement*) next())) {
4923  TTree* t = fe->GetTree();
4924  if (t) {
4925  TBranch* branch = t->GetBranch(name);
4926  if (branch) {
4927  return branch;
4928  }
4929  }
4930  }
4931 
4932  // Second pass in the list of friends when
4933  // the branch name is prefixed by the tree name.
4934  next.Reset();
4935  while ((fe = (TFriendElement*) next())) {
4936  TTree* t = fe->GetTree();
4937  if (!t) {
4938  continue;
4939  }
4940  char* subname = (char*) strstr(name, fe->GetName());
4941  if (subname != name) {
4942  continue;
4943  }
4944  Int_t l = strlen(fe->GetName());
4945  subname += l;
4946  if (*subname != '.') {
4947  continue;
4948  }
4949  subname++;
4950  TBranch* branch = t->GetBranch(subname);
4951  if (branch) {
4952  return branch;
4953  }
4954  }
4955  return 0;
4956 }
4957 
4958 ////////////////////////////////////////////////////////////////////////////////
4959 /// Return status of branch with name branchname.
4960 ///
4961 /// - 0 if branch is not activated
4962 /// - 1 if branch is activated
4963 
4964 Bool_t TTree::GetBranchStatus(const char* branchname) const
4966  TBranch* br = const_cast<TTree*>(this)->GetBranch(branchname);
4967  if (br) {
4968  return br->TestBit(kDoNotProcess) == 0;
4969  }
4970  return 0;
4971 }
4972 
4973 ////////////////////////////////////////////////////////////////////////////////
4974 /// Static function returning the current branch style.
4975 ///
4976 /// - style = 0 old Branch
4977 /// - style = 1 new Bronch
4978 
4981  return fgBranchStyle;
4982 }
4983 
4984 ////////////////////////////////////////////////////////////////////////////////
4985 /// Used for automatic sizing of the cache.
4986 ///
4987 /// Estimates a suitable size for the tree cache based on AutoFlush.
4988 /// A cache sizing factor is taken from the configuration. If this yields zero
4989 /// and withDefault is true the historical algorithm for default size is used.
4990 
4991 Long64_t TTree::GetCacheAutoSize(Bool_t withDefault /* = kFALSE */ ) const
4993  const char *stcs;
4994  Double_t cacheFactor = 0.0;
4995  if (!(stcs = gSystem->Getenv("ROOT_TTREECACHE_SIZE")) || !*stcs) {
4996  cacheFactor = gEnv->GetValue("TTreeCache.Size", 1.0);
4997  } else {
4998  cacheFactor = TString(stcs).Atof();
4999  }
5000 
5001  if (cacheFactor < 0.0) {
5002  // ignore negative factors
5003  cacheFactor = 0.0;
5004  }
5005 
5006  Long64_t cacheSize = 0;
5007 
5008  if (fAutoFlush < 0) cacheSize = Long64_t(-cacheFactor*fAutoFlush);
5009  else if (fAutoFlush == 0) cacheSize = 0;
5010  else cacheSize = Long64_t(cacheFactor*1.5*fAutoFlush*fZipBytes/(fEntries+1));
5011 
5012  if (cacheSize >= (INT_MAX / 4)) {
5013  cacheSize = INT_MAX / 4;
5014  }
5015 
5016  if (cacheSize < 0) {
5017  cacheSize = 0;
5018  }
5019 
5020  if (cacheSize == 0 && withDefault) {
5021  if (fAutoFlush < 0) cacheSize = -fAutoFlush;
5022  else if (fAutoFlush == 0) cacheSize = 0;
5023  else cacheSize = Long64_t(1.5*fAutoFlush*fZipBytes/(fEntries+1));
5024  }
5025 
5026  return cacheSize;
5027 }
5028 
5029 ////////////////////////////////////////////////////////////////////////////////
5030 /// Return an iterator over the cluster of baskets starting at firstentry.
5031 ///
5032 /// This iterator is not yet supported for TChain object.
5033 /// ~~~ {.cpp}
5034 /// TTree::TClusterIterator clusterIter = tree->GetClusterIterator(entry);
5035 /// Long64_t clusterStart;
5036 /// while( (clusterStart = clusterIter()) < tree->GetEntries() ) {
5037 /// printf("The cluster starts at %lld and ends at %lld (inclusive)\n",clusterStart,clusterIter.GetNextEntry()-1);
5038 /// }
5039 /// ~~~
5040 
5043  // create cache if wanted
5045 
5046  return TClusterIterator(this,firstentry);
5047 }
5048 
5049 ////////////////////////////////////////////////////////////////////////////////
5050 /// Return pointer to the current file.
5051 
5054  if (!fDirectory || fDirectory==gROOT) {
5055  return 0;
5056  }
5057  return fDirectory->GetFile();
5058 }
5059 
5060 ////////////////////////////////////////////////////////////////////////////////
5061 /// Return the number of entries matching the selection.
5062 /// Return -1 in case of errors.
5063 ///
5064 /// If the selection uses any arrays or containers, we return the number
5065 /// of entries where at least one element match the selection.
5066 /// GetEntries is implemented using the selector class TSelectorEntries,
5067 /// which can be used directly (see code in TTreePlayer::GetEntries) for
5068 /// additional option.
5069 /// If SetEventList was used on the TTree or TChain, only that subset
5070 /// of entries will be considered.
5071 
5072 Long64_t TTree::GetEntries(const char *selection)
5074  GetPlayer();
5075  if (fPlayer) {
5076  return fPlayer->GetEntries(selection);
5077  }
5078  return -1;
5079 }
5080 
5081 ////////////////////////////////////////////////////////////////////////////////
5082 /// Return pointer to the 1st Leaf named name in any Branch of this Tree or
5083 /// any branch in the list of friend trees.
5084 
5087  if (fEntries) return fEntries;
5088  if (!fFriends) return 0;
5090  if (!fr) return 0;
5091  TTree *t = fr->GetTree();
5092  if (t==0) return 0;
5093  return t->GetEntriesFriend();
5094 }
5095 
5096 ////////////////////////////////////////////////////////////////////////////////
5097 /// Read all branches of entry and return total number of bytes read.
5098 ///
5099 /// - `getall = 0` : get only active branches
5100 /// - `getall = 1` : get all branches
5101 ///
5102 /// The function returns the number of bytes read from the input buffer.
5103 /// If entry does not exist the function returns 0.
5104 /// If an I/O error occurs, the function returns -1.
5105 ///
5106 /// If the Tree has friends, also read the friends entry.
5107 ///
5108 /// To activate/deactivate one or more branches, use TBranch::SetBranchStatus
5109 /// For example, if you have a Tree with several hundred branches, and you
5110 /// are interested only by branches named "a" and "b", do
5111 /// ~~~ {.cpp}
5112 /// mytree.SetBranchStatus("*",0); //disable all branches
5113 /// mytree.SetBranchStatus("a",1);
5114 /// mytree.SetBranchStatus("b",1);
5115 /// ~~~
5116 /// when calling mytree.GetEntry(i); only branches "a" and "b" will be read.
5117 ///
5118 /// __WARNING!!__
5119 /// If your Tree has been created in split mode with a parent branch "parent.",
5120 /// ~~~ {.cpp}
5121 /// mytree.SetBranchStatus("parent",1);
5122 /// ~~~
5123 /// will not activate the sub-branches of "parent". You should do:
5124 /// ~~~ {.cpp}
5125 /// mytree.SetBranchStatus("parent*",1);
5126 /// ~~~
5127 /// Without the trailing dot in the branch creation you have no choice but to
5128 /// call SetBranchStatus explicitly for each of the sub branches.
5129 ///
5130 /// An alternative is to call directly
5131 /// ~~~ {.cpp}
5132 /// brancha.GetEntry(i)
5133 /// branchb.GetEntry(i);
5134 /// ~~~
5135 /// ## IMPORTANT NOTE
5136 ///
5137 /// By default, GetEntry reuses the space allocated by the previous object
5138 /// for each branch. You can force the previous object to be automatically
5139 /// deleted if you call mybranch.SetAutoDelete(kTRUE) (default is kFALSE).
5140 ///
5141 /// Example:
5142 ///
5143 /// Consider the example in $ROOTSYS/test/Event.h
5144 /// The top level branch in the tree T is declared with:
5145 /// ~~~ {.cpp}
5146 /// Event *event = 0; //event must be null or point to a valid object
5147 /// //it must be initialized
5148 /// T.SetBranchAddress("event",&event);
5149 /// ~~~
5150 /// When reading the Tree, one can choose one of these 3 options:
5151 ///
5152 /// ## OPTION 1
5153 ///
5154 /// ~~~ {.cpp}
5155 /// for (Long64_t i=0;i<nentries;i++) {
5156 /// T.GetEntry(i);
5157 /// // the object event has been filled at this point
5158 /// }
5159 /// ~~~
5160 /// The default (recommended). At the first entry an object of the class
5161 /// Event will be created and pointed by event. At the following entries,
5162 /// event will be overwritten by the new data. All internal members that are
5163 /// TObject* are automatically deleted. It is important that these members
5164 /// be in a valid state when GetEntry is called. Pointers must be correctly
5165 /// initialized. However these internal members will not be deleted if the
5166 /// characters "->" are specified as the first characters in the comment
5167 /// field of the data member declaration.
5168 ///
5169 /// If "->" is specified, the pointer member is read via pointer->Streamer(buf).
5170 /// In this case, it is assumed that the pointer is never null (case of
5171 /// pointer TClonesArray *fTracks in the Event example). If "->" is not
5172 /// specified, the pointer member is read via buf >> pointer. In this case
5173 /// the pointer may be null. Note that the option with "->" is faster to
5174 /// read or write and it also consumes less space in the file.
5175 ///
5176 /// ## OPTION 2
5177 ///
5178 /// The option AutoDelete is set
5179 /// ~~~ {.cpp}
5180 /// TBranch *branch = T.GetBranch("event");
5181 /// branch->SetAddress(&event);
5182 /// branch->SetAutoDelete(kTRUE);
5183 /// for (Long64_t i=0;i<nentries;i++) {
5184 /// T.GetEntry(i);
5185 /// // the object event has been filled at this point
5186 /// }
5187 /// ~~~
5188 /// In this case, at each iteration, the object event is deleted by GetEntry
5189 /// and a new instance of Event is created and filled.
5190 ///
5191 /// ## OPTION 3
5192 /// ~~~ {.cpp}
5193 /// Same as option 1, but you delete yourself the event.
5194 ///
5195 /// for (Long64_t i=0;i<nentries;i++) {
5196 /// delete event;
5197 /// event = 0; // EXTREMELY IMPORTANT
5198 /// T.GetEntry(i);
5199 /// // the object event has been filled at this point
5200 /// }
5201 /// ~~~
5202 /// It is strongly recommended to use the default option 1. It has the
5203 /// additional advantage that functions like TTree::Draw (internally calling
5204 /// TTree::GetEntry) will be functional even when the classes in the file are
5205 /// not available.
5206 ///
5207 /// Note: See the comments in TBranchElement::SetAddress() for the
5208 /// object ownership policy of the underlying (user) data.
5209 
5210 Int_t TTree::GetEntry(Long64_t entry, Int_t getall)
5212 
5213  // We already have been visited while recursively looking
5214  // through the friends tree, let return
5215  if (kGetEntry & fFriendLockStatus) return 0;
5216 
5217  if (entry < 0 || entry >= fEntries) return 0;
5218  Int_t i;
5219  Int_t nbytes = 0;
5220  fReadEntry = entry;
5221 
5222  // create cache if wanted
5224 
5225  Int_t nbranches = fBranches.GetEntriesFast();
5226  Int_t nb=0;
5227 
5228  auto seqprocessing = [&]() {
5229  TBranch *branch;
5230  for (i=0;i<nbranches;i++) {
5231  branch = (TBranch*)fBranches.UncheckedAt(i);
5232  nb = branch->GetEntry(entry, getall);
5233  if (nb < 0) break;
5234  nbytes += nb;
5235  }
5236  };
5237 
5238 #ifdef R__USE_IMT
5240  if (fSortedBranches.empty()) InitializeBranchLists(true);
5241 
5242  // Count branches are processed first and sequentially
5243  for (auto branch : fSeqBranches) {
5244  nb = branch->GetEntry(entry, getall);
5245  if (nb < 0) break;
5246  nbytes += nb;
5247  }
5248  if (nb < 0) return nb;
5249 
5250  // Enable this IMT use case (activate its locks)
5252 
5253  Int_t errnb = 0;
5254  std::atomic<Int_t> pos(0);
5255  std::atomic<Int_t> nbpar(0);
5256  tbb::task_group g;
5257 
5258  for (size_t idx = 0; idx < fSortedBranches.size(); ++idx) {
5259  g.run([&]() {
5260  // The branch to process is obtained when the task starts to run.
5261  // This way, since branches are sorted, we make sure that branches
5262  // leading to big tasks are processed first. If we assigned the
5263  // branch at task creation time, the scheduler would not necessarily
5264  // respect our sorting.
5265  Int_t j = pos.fetch_add(1);
5266 
5267  Int_t nbtask = 0;
5268  auto branch = fSortedBranches[j].second;
5269 
5270  if (gDebug > 0) {
5271  std::stringstream ss;
5272  ss << std::this_thread::get_id();
5273  Info("GetEntry", "[IMT] Thread %s", ss.str().c_str());
5274  Info("GetEntry", "[IMT] Running task for branch #%d: %s", j, branch->GetName());
5275  }
5276 
5277  std::chrono::time_point<std::chrono::system_clock> start, end;
5278 
5279  start = std::chrono::system_clock::now();
5280  nbtask = branch->GetEntry(entry, getall);
5281  end = std::chrono::system_clock::now();
5282 
5283  Long64_t tasktime = (Long64_t)std::chrono::duration_cast<std::chrono::microseconds>(end - start).count();
5284  fSortedBranches[j].first += tasktime;
5285 
5286  if (nbtask < 0) errnb = nbtask;
5287  else nbpar += nbtask;
5288  });
5289  }
5290  g.wait();
5291 
5292  if (errnb < 0) {
5293  nb = errnb;
5294  }
5295  else {
5296  // Save the number of bytes read by the tasks
5297  nbytes += nbpar;
5298 
5299  // Re-sort branches if necessary
5303  }
5304  }
5305  }
5306  else {
5307  seqprocessing();
5308  }
5309 #else
5310  seqprocessing();
5311 #endif
5312  if (nb < 0) return nb;
5313 
5314  // GetEntry in list of friends
5315  if (!fFriends) return nbytes;
5316  TFriendLock lock(this,kGetEntry);
5317  TIter nextf(fFriends);
5318  TFriendElement *fe;
5319  while ((fe = (TFriendElement*)nextf())) {
5320  TTree *t = fe->GetTree();
5321  if (t) {
5323  nb = t->GetEntry(t->GetReadEntry(),getall);
5324  } else {
5325  if ( t->LoadTreeFriend(entry,this) >= 0 ) {
5326  nb = t->GetEntry(t->GetReadEntry(),getall);
5327  } else nb = 0;
5328  }
5329  if (nb < 0) return nb;
5330  nbytes += nb;
5331  }
5332  }
5333  return nbytes;
5334 }
5335 
5336 
5337 ////////////////////////////////////////////////////////////////////////////////
5338 /// Divides the top-level branches into two vectors: (i) branches to be
5339 /// processed sequentially and (ii) branches to be processed in parallel.
5340 /// Even if IMT is on, some branches might need to be processed first and in a
5341 /// sequential fashion: in the parallelization of GetEntry, those are the
5342 /// branches that store the size of another branch for every entry
5343 /// (e.g. the size of an array branch). If such branches were processed
5344 /// in parallel with the rest, there could be two threads invoking
5345 /// TBranch::GetEntry on one of them at the same time, since a branch that
5346 /// depends on a size (or count) branch will also invoke GetEntry on the latter.
5347 /// \param[in] checkLeafCount True if we need to check whether some branches are
5348 /// count leaves.
5349 
5350 void TTree::InitializeBranchLists(bool checkLeafCount)
5352  Int_t nbranches = fBranches.GetEntriesFast();
5353 
5354  // The branches to be processed sequentially are those that are the leaf count of another branch
5355  if (checkLeafCount) {
5356  for (Int_t i = 0; i < nbranches; i++) {
5357  TBranch* branch = (TBranch*)fBranches.UncheckedAt(i);
5358  auto leafCount = ((TLeaf*)branch->GetListOfLeaves()->At(0))->GetLeafCount();
5359  if (leafCount) {
5360  auto countBranch = leafCount->GetBranch();
5361  if (std::find(fSeqBranches.begin(), fSeqBranches.end(), countBranch) == fSeqBranches.end()) {
5362  fSeqBranches.push_back(countBranch);
5363  }
5364  }
5365  }
5366  }
5367 
5368  // The special branch fBranchRef also needs to be processed sequentially
5369  if (fBranchRef) {
5370  fSeqBranches.push_back(fBranchRef);
5371  }
5372 
5373  // Any branch that is not a leaf count can be safely processed in parallel when reading
5374  for (Int_t i = 0; i < nbranches; i++) {
5375  Long64_t bbytes = 0;
5376  TBranch* branch = (TBranch*)fBranches.UncheckedAt(i);
5377  if (std::find(fSeqBranches.begin(), fSeqBranches.end(), branch) == fSeqBranches.end()) {
5378  bbytes = branch->GetTotBytes("*");
5379  fSortedBranches.emplace_back(bbytes, branch);
5380  }
5381  }
5382 
5383  // Initially sort parallel branches by size
5384  std::sort(fSortedBranches.begin(),
5385  fSortedBranches.end(),
5386  [](std::pair<Long64_t,TBranch*> a, std::pair<Long64_t,TBranch*> b) {
5387  return a.first > b.first;
5388  });
5389 
5390  for (size_t i = 0; i < fSortedBranches.size(); i++) {
5391  fSortedBranches[i].first = 0LL;
5392  }
5393 }
5394 
5395 ////////////////////////////////////////////////////////////////////////////////
5396 /// Sorts top-level branches by the last average task time recorded per branch.
5397 
5400  for (size_t i = 0; i < fSortedBranches.size(); i++) {
5401  fSortedBranches[i].first *= kNEntriesResortInv;
5402  }
5403 
5404  std::sort(fSortedBranches.begin(),
5405  fSortedBranches.end(),
5406  [](std::pair<Long64_t,TBranch*> a, std::pair<Long64_t,TBranch*> b) {
5407  return a.first > b.first;
5408  });
5409 
5410  for (size_t i = 0; i < fSortedBranches.size(); i++) {
5411  fSortedBranches[i].first = 0LL;
5412  }
5413 }
5414 
5415 ////////////////////////////////////////////////////////////////////////////////
5416 ///Returns the entry list, set to this tree
5417 
5420  return fEntryList;
5421 }
5422 
5423 ////////////////////////////////////////////////////////////////////////////////
5424 /// Return entry number corresponding to entry.
5425 ///
5426 /// if no TEntryList set returns entry
5427 /// else returns the entry number corresponding to the list index=entry
5428 
5431  if (!fEntryList) {
5432  return entry;
5433  }
5434 
5435  return fEntryList->GetEntry(entry);
5436 }
5437 
5438 ////////////////////////////////////////////////////////////////////////////////
5439 /// Return entry number corresponding to major and minor number.
5440 /// Note that this function returns only the entry number, not the data
5441 /// To read the data corresponding to an entry number, use TTree::GetEntryWithIndex
5442 /// the BuildIndex function has created a table of Long64_t* of sorted values
5443 /// corresponding to val = major<<31 + minor;
5444 /// The function performs binary search in this sorted table.
5445 /// If it finds a pair that matches val, it returns directly the
5446 /// index in the table.
5447 /// If an entry corresponding to major and minor is not found, the function
5448 /// returns the index of the major,minor pair immediately lower than the
5449 /// requested value, ie it will return -1 if the pair is lower than
5450 /// the first entry in the index.
5451 ///
5452 /// See also GetEntryNumberWithIndex
5453 
5456  if (!fTreeIndex) {
5457  return -1;
5458  }
5459  return fTreeIndex->GetEntryNumberWithBestIndex(major, minor);
5460 }
5461 
5462 ////////////////////////////////////////////////////////////////////////////////
5463 /// Return entry number corresponding to major and minor number.
5464 /// Note that this function returns only the entry number, not the data
5465 /// To read the data corresponding to an entry number, use TTree::GetEntryWithIndex
5466 /// the BuildIndex function has created a table of Long64_t* of sorted values
5467 /// corresponding to val = major<<31 + minor;
5468 /// The function performs binary search in this sorted table.
5469 /// If it finds a pair that matches val, it returns directly the
5470 /// index in the table, otherwise it returns -1.
5471 ///
5472 /// See also GetEntryNumberWithBestIndex
5473 
5476  if (!fTreeIndex) {
5477  return -1;
5478  }
5479  return fTreeIndex->GetEntryNumberWithIndex(major, minor);
5480 }
5481 
5482 ////////////////////////////////////////////////////////////////////////////////
5483 /// Read entry corresponding to major and minor number.
5484 ///
5485 /// The function returns the total number of bytes read.
5486 /// If the Tree has friend trees, the corresponding entry with
5487 /// the index values (major,minor) is read. Note that the master Tree
5488 /// and its friend may have different entry serial numbers corresponding
5489 /// to (major,minor).
5490 
5493  // We already have been visited while recursively looking
5494  // through the friends tree, let's return.
5496  return 0;
5497  }
5498  Long64_t serial = GetEntryNumberWithIndex(major, minor);
5499  if (serial < 0) {
5500  return -1;
5501  }
5502  // create cache if wanted
5504 
5505  Int_t i;
5506  Int_t nbytes = 0;
5507  fReadEntry = serial;
5508  TBranch *branch;
5509  Int_t nbranches = fBranches.GetEntriesFast();
5510  Int_t nb;
5511  for (i = 0; i < nbranches; ++i) {
5512  branch = (TBranch*)fBranches.UncheckedAt(i);
5513  nb = branch->GetEntry(serial);
5514  if (nb < 0) return nb;
5515  nbytes += nb;
5516  }
5517  // GetEntry in list of friends
5518  if (!fFriends) return nbytes;
5519  TFriendLock lock(this,kGetEntryWithIndex);
5520  TIter nextf(fFriends);
5521  TFriendElement* fe = 0;
5522  while ((fe = (TFriendElement*) nextf())) {
5523  TTree *t = fe->GetTree();
5524  if (t) {
5525  serial = t->GetEntryNumberWithIndex(major,minor);
5526  if (serial <0) return -nbytes;
5527  nb = t->GetEntry(serial);
5528  if (nb < 0) return nb;
5529  nbytes += nb;
5530  }
5531  }
5532  return nbytes;
5533 }
5534 
5535 ////////////////////////////////////////////////////////////////////////////////
5536 /// Return a pointer to the TTree friend whose name or alias is 'friendname.
5537 
5538 TTree* TTree::GetFriend(const char *friendname) const
5540 
5541  // We already have been visited while recursively
5542  // looking through the friends tree, let's return.
5543  if (kGetFriend & fFriendLockStatus) {
5544  return 0;
5545  }
5546  if (!fFriends) {
5547  return 0;
5548  }
5549  TFriendLock lock(const_cast<TTree*>(this), kGetFriend);
5550  TIter nextf(fFriends);
5551  TFriendElement* fe = 0;
5552  while ((fe = (TFriendElement*) nextf())) {
5553  if (strcmp(friendname,fe->GetName())==0
5554  || strcmp(friendname,fe->GetTreeName())==0) {
5555  return fe->GetTree();
5556  }
5557  }
5558  // After looking at the first level,
5559  // let's see if it is a friend of friends.
5560  nextf.Reset();
5561  fe = 0;
5562  while ((fe = (TFriendElement*) nextf())) {
5563  TTree *res = fe->GetTree()->GetFriend(friendname);
5564  if (res) {
5565  return res;
5566  }
5567  }
5568  return 0;
5569 }
5570 
5571 ////////////////////////////////////////////////////////////////////////////////
5572 /// If the 'tree' is a friend, this method returns its alias name.
5573 ///
5574 /// This alias is an alternate name for the tree.
5575 ///
5576 /// It can be used in conjunction with a branch or leaf name in a TTreeFormula,
5577 /// to specify in which particular tree the branch or leaf can be found if
5578 /// the friend trees have branches or leaves with the same name as the master
5579 /// tree.
5580 ///
5581 /// It can also be used in conjunction with an alias created using
5582 /// TTree::SetAlias in a TTreeFormula, e.g.:
5583 /// ~~~ {.cpp}
5584 /// maintree->Draw("treealias.fPx - treealias.myAlias");
5585 /// ~~~
5586 /// where fPx is a branch of the friend tree aliased as 'treealias' and 'myAlias'
5587 /// was created using TTree::SetAlias on the friend tree.
5588 ///
5589 /// However, note that 'treealias.myAlias' will be expanded literally,
5590 /// without remembering that it comes from the aliased friend and thus
5591 /// the branch name might not be disambiguated properly, which means
5592 /// that you may not be able to take advantage of this feature.
5593 ///
5594 
5595 const char* TTree::GetFriendAlias(TTree* tree) const
5597  if ((tree == this) || (tree == GetTree())) {
5598  return 0;
5599  }
5600 
5601  // We already have been visited while recursively
5602  // looking through the friends tree, let's return.
5604  return 0;
5605  }
5606  if (!fFriends) {
5607  return 0;
5608  }
5609  TFriendLock lock(const_cast<TTree*>(this), kGetFriendAlias);
5610  TIter nextf(fFriends);
5611  TFriendElement* fe = 0;
5612  while ((fe = (TFriendElement*) nextf())) {
5613  TTree* t = fe->GetTree();
5614  if (t == tree) {
5615  return fe->GetName();
5616  }
5617  // Case of a chain:
5618  if (t->GetTree() == tree) {
5619  return fe->GetName();
5620  }
5621  }
5622  // After looking at the first level,
5623  // let's see if it is a friend of friends.
5624  nextf.Reset();
5625  fe = 0;
5626  while ((fe = (TFriendElement*) nextf())) {
5627  const char* res = fe->GetTree()->GetFriendAlias(tree);
5628  if (res) {
5629  return res;
5630  }
5631  }
5632  return 0;
5633 }
5634 
5635 ////////////////////////////////////////////////////////////////////////////////
5636 /// Creates a new iterator that will go through all the leaves on the tree itself and its friend.
5637 
5640  return new TTreeFriendLeafIter(this, dir);
5641 }
5642 
5643 ////////////////////////////////////////////////////////////////////////////////
5644 /// Return pointer to the 1st Leaf named name in any Branch of this
5645 /// Tree or any branch in the list of friend trees.
5646 ///
5647 /// The leaf name can contain the name of a friend tree with the
5648 /// syntax: friend_dir_and_tree.full_leaf_name
5649 /// the friend_dir_and_tree can be of the form:
5650 /// ~~~ {.cpp}
5651 /// TDirectoryName/TreeName
5652 /// ~~~
5653 
5654 TLeaf* TTree::GetLeafImpl(const char* branchname, const char *leafname)
5656  TLeaf *leaf = 0;
5657  if (branchname) {
5658  TBranch *branch = FindBranch(branchname);
5659  if (branch) {
5660  leaf = branch->GetLeaf(leafname);
5661  if (leaf) {
5662  return leaf;
5663  }
5664  }
5665  }
5666  TIter nextl(GetListOfLeaves());
5667  while ((leaf = (TLeaf*)nextl())) {
5668  if (strcmp(leaf->GetName(),leafname)) continue;
5669  if (branchname) {
5670  UInt_t nbch = strlen(branchname);
5671  TBranch *br = leaf->GetBranch();
5672  const char* brname = br->GetName();
5673  TBranch *mother = br->GetMother();
5674  if (strncmp(brname,branchname,nbch)) {
5675  if (mother != br) {
5676  const char *mothername = mother->GetName();
5677  UInt_t motherlen = strlen(mothername);
5678  if (nbch > motherlen && strncmp(mothername,branchname,motherlen)==0 && (mothername[motherlen-1]=='.' || branchname[motherlen]=='.')) {
5679  // 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.
5680  if (strncmp(brname,branchname+motherlen+1,nbch-motherlen-1)) {
5681  // No it does not
5682  continue;
5683  } // else we have match so we can proceed.
5684  } else {
5685  // no match
5686  continue;
5687  }
5688  } else {
5689  continue;
5690  }
5691  }
5692  // The start of the branch name is identical to the content
5693  // of 'aname' before the first '/'.
5694  // Let's make sure that it is not longer (we are trying
5695  // to avoid having jet2/value match the branch jet23
5696  if ((strlen(brname) > nbch) && (brname[nbch] != '.') && (brname[nbch] != '[')) {
5697  continue;
5698  }
5699  }
5700  return leaf;
5701  }
5702  if (!fFriends) return 0;
5703  TFriendLock lock(this,kGetLeaf);
5704  TIter next(fFriends);
5705  TFriendElement *fe;
5706  while ((fe = (TFriendElement*)next())) {
5707  TTree *t = fe->GetTree();
5708  if (t) {
5709  leaf = t->GetLeaf(leafname);
5710  if (leaf) return leaf;
5711  }
5712  }
5713 
5714  //second pass in the list of friends when the leaf name
5715  //is prefixed by the tree name
5716  TString strippedArg;
5717  next.Reset();
5718  while ((fe = (TFriendElement*)next())) {
5719  TTree *t = fe->GetTree();
5720  if (t==0) continue;
5721  char *subname = (char*)strstr(leafname,fe->GetName());
5722  if (subname != leafname) continue;
5723  Int_t l = strlen(fe->GetName());
5724  subname += l;
5725  if (*subname != '.') continue;
5726  subname++;
5727  strippedArg += subname;
5728  leaf = t->GetLeaf(branchname,subname);
5729  if (leaf) return leaf;
5730  }
5731  return 0;
5732 }
5733 
5734 ////////////////////////////////////////////////////////////////////////////////
5735 /// Return pointer to the 1st Leaf named name in any Branch of this
5736 /// Tree or any branch in the list of friend trees.
5737 ///
5738 /// The leaf name can contain the name of a friend tree with the
5739 /// syntax: friend_dir_and_tree.full_leaf_name
5740 /// the friend_dir_and_tree can be of the form:
5741 ///
5742 /// TDirectoryName/TreeName
5743 
5744 TLeaf* TTree::GetLeaf(const char* branchname, const char *leafname)
5746  if (leafname == 0) return 0;
5747 
5748  // We already have been visited while recursively looking
5749  // through the friends tree, let return
5750  if (kGetLeaf & fFriendLockStatus) {
5751  return 0;
5752  }
5753 
5754  return GetLeafImpl(branchname,leafname);
5755 }
5756 
5757 ////////////////////////////////////////////////////////////////////////////////
5758 /// Return pointer to the 1st Leaf named name in any Branch of this
5759 /// Tree or any branch in the list of friend trees.
5760 ///
5761 /// aname may be of the form branchname/leafname
5762 
5763 TLeaf* TTree::GetLeaf(const char* aname)
5765  if (aname == 0) return 0;
5766 
5767  // We already have been visited while recursively looking
5768  // through the friends tree, let return
5769  if (kGetLeaf & fFriendLockStatus) {
5770  return 0;
5771  }
5772  char* slash = (char*) strrchr(aname, '/');
5773  char* name = 0;
5774  UInt_t nbch = 0;
5775  if (slash) {
5776  name = slash + 1;
5777  nbch = slash - aname;
5778  TString brname(aname,nbch);
5779  return GetLeafImpl(brname.Data(),name);
5780  } else {
5781  return GetLeafImpl(0,aname);
5782  }
5783 }
5784 
5785 ////////////////////////////////////////////////////////////////////////////////
5786 /// Return maximum of column with name columname.
5787 /// if the Tree has an associated TEventList or TEntryList, the maximum
5788 /// is computed for the entries in this list.
5789 
5790 Double_t TTree::GetMaximum(const char* columname)
5792  TLeaf* leaf = this->GetLeaf(columname);
5793  if (!leaf) {
5794  return 0;
5795  }
5796 
5797  // create cache if wanted
5799 
5800  TBranch* branch = leaf->GetBranch();
5801  Double_t cmax = -DBL_MAX;
5802  for (Long64_t i = 0; i < fEntries; ++i) {
5803  Long64_t entryNumber = this->GetEntryNumber(i);
5804  if (entryNumber < 0) break;
5805  branch->GetEntry(entryNumber);
5806  for (Int_t j = 0; j < leaf->GetLen(); ++j) {
5807  Double_t val = leaf->GetValue(j);
5808  if (val > cmax) {
5809  cmax = val;
5810  }
5811  }
5812  }
5813  return cmax;
5814 }
5815 
5816 ////////////////////////////////////////////////////////////////////////////////
5817 /// Static function which returns the tree file size limit in bytes.
5818 
5821  return fgMaxTreeSize;
5822 }
5823 
5824 ////////////////////////////////////////////////////////////////////////////////
5825 /// Return minimum of column with name columname.
5826 /// if the Tree has an associated TEventList or TEntryList, the minimum
5827 /// is computed for the entries in this list.
5828 
5829 Double_t TTree::GetMinimum(const char* columname)
5831  TLeaf* leaf = this->GetLeaf(columname);
5832  if (!leaf) {
5833  return 0;
5834  }
5835 
5836  // create cache if wanted
5838 
5839  TBranch* branch = leaf->GetBranch();
5840  Double_t cmin = DBL_MAX;
5841  for (Long64_t i = 0; i < fEntries; ++i) {
5842  Long64_t entryNumber = this->GetEntryNumber(i);
5843  if (entryNumber < 0) break;
5844  branch->GetEntry(entryNumber);
5845  for (Int_t j = 0;j < leaf->GetLen(); ++j) {
5846  Double_t val = leaf->GetValue(j);
5847  if (val < cmin) {
5848  cmin = val;
5849  }
5850  }
5851  }
5852  return cmin;
5853 }
5854 
5855 ////////////////////////////////////////////////////////////////////////////////
5856 /// Load the TTreePlayer (if not already done).
5857 
5860  if (fPlayer) {
5861  return fPlayer;
5862  }
5864  return fPlayer;
5865 }
5866 
5867 ////////////////////////////////////////////////////////////////////////////////
5868 /// Find and return the TTreeCache registered with the file and which may
5869 /// contain branches for us. If create is true and there is no cache
5870 /// a new cache is created with default size.
5871 
5872 TTreeCache *TTree::GetReadCache(TFile *file, Bool_t create /* = kFALSE */ )
5874  TTreeCache *pe = dynamic_cast<TTreeCache*>(file->GetCacheRead(this));
5875  if (pe && pe->GetTree() != this) pe = 0;
5876  if (create && !pe) {
5878  pe = dynamic_cast<TTreeCache*>(file->GetCacheRead(this));
5879  if (pe && pe->GetTree() != this) pe = 0;
5880  }
5881  return pe;
5882 }
5883 
5884 ////////////////////////////////////////////////////////////////////////////////
5885 /// Return a pointer to the list containing user objects associated to this tree.
5886 ///
5887 /// The list is automatically created if it does not exist.
5888 ///
5889 /// WARNING: By default the TTree destructor will delete all objects added
5890 /// to this list. If you do not want these objects to be deleted,
5891 /// call:
5892 ///
5893 /// mytree->GetUserInfo()->Clear();
5894 ///
5895 /// before deleting the tree.
5896 
5899  if (!fUserInfo) {
5900  fUserInfo = new TList();
5901  fUserInfo->SetName("UserInfo");
5902  }
5903  return fUserInfo;
5904 }
5905 
5906 ////////////////////////////////////////////////////////////////////////////////
5907 /// Appends the cluster range information stored in 'fromtree' to this tree,
5908 /// including the value of fAutoFlush.
5909 ///
5910 /// This is used when doing a fast cloning (by TTreeCloner).
5911 /// See also fAutoFlush and fAutoSave if needed.
5912 
5913 void TTree::ImportClusterRanges(TTree *fromtree)
5915  Long64_t autoflush = fromtree->GetAutoFlush();
5916  if (fNClusterRange || fromtree->fNClusterRange) {
5917  Int_t newsize = fNClusterRange + 1 + fromtree->fNClusterRange;
5918  if (newsize > fMaxClusterRange) {
5919  if (fMaxClusterRange) {
5921  newsize*sizeof(Long64_t),fMaxClusterRange*sizeof(Long64_t));
5923  newsize*sizeof(Long64_t),fMaxClusterRange*sizeof(Long64_t));
5924  fMaxClusterRange = newsize;
5925  } else {
5926  fMaxClusterRange = newsize;
5929  }
5930  }
5933  ++fNClusterRange;
5934  for (Int_t i = 0 ; i < fromtree->fNClusterRange; ++i) {
5936  fClusterSize[fNClusterRange] = fromtree->fClusterSize[i];
5937  ++fNClusterRange;
5938  }
5939  fAutoFlush = autoflush;
5940  } else {
5941  SetAutoFlush( autoflush );
5942  }
5943  Long64_t autosave = GetAutoSave();
5944  if (autoflush > 0 && autosave > 0) {
5945  SetAutoSave( autoflush*(autosave/autoflush) );
5946  }
5947 }
5948 
5949 ////////////////////////////////////////////////////////////////////////////////
5950 /// Keep a maximum of fMaxEntries in memory.
5951 
5952 void TTree::KeepCircular()
5955  Long64_t maxEntries = fMaxEntries - (fMaxEntries / 10);
5956  for (Int_t i = 0; i < nb; ++i) {
5957  TBranch* branch = (TBranch*) fBranches.UncheckedAt(i);
5958  branch->KeepCircular(maxEntries);
5959  }
5960  if (fNClusterRange) {
5961  Long64_t entriesOffset = fEntries - maxEntries;
5962  Int_t oldsize = fNClusterRange;
5963  for(Int_t i = 0, j = 0; j < oldsize; ++j) {
5964  if (fClusterRangeEnd[j] > entriesOffset) {
5965  fClusterRangeEnd[i] = fClusterRangeEnd[j] - entriesOffset;
5966  ++i;
5967  } else {
5968  --fNClusterRange;
5969  }
5970  }
5971  }
5972  fEntries = maxEntries;
5973  fReadEntry = -1;
5974 }
5975 
5976 ////////////////////////////////////////////////////////////////////////////////
5977 /// Read in memory all baskets from all branches up to the limit of maxmemory bytes.
5978 ///
5979 /// If maxmemory is non null and positive SetMaxVirtualSize is called
5980 /// with this value. Default for maxmemory is 2000000000 (2 Gigabytes).
5981 /// The function returns the total number of baskets read into memory
5982 /// if negative an error occurred while loading the branches.
5983 /// This method may be called to force branch baskets in memory
5984 /// when random access to branch entries is required.
5985 /// If random access to only a few branches is required, you should
5986 /// call directly TBranch::LoadBaskets.
5987 
5990  if (maxmemory > 0) SetMaxVirtualSize(maxmemory);
5991 
5992  TIter next(GetListOfLeaves());
5993  TLeaf *leaf;
5994  Int_t nimported = 0;
5995  while ((leaf=(TLeaf*)next())) {
5996  nimported += leaf->GetBranch()->LoadBaskets();//break;
5997  }
5998  return nimported;
5999 }
6000 
6001 ////////////////////////////////////////////////////////////////////////////////
6002 /// Set current entry.
6003 ///
6004 /// Returns -2 if entry does not exist (just as TChain::LoadTree()).
6005 ///
6006 /// Note: This function is overloaded in TChain.
6007 ///
6008 
6011  // We already have been visited while recursively looking
6012  // through the friends tree, let return
6013  if (kLoadTree & fFriendLockStatus) {
6014  // We need to return a negative value to avoid a circular list of friend
6015  // to think that there is always an entry somewhere in the list.
6016  return -1;
6017  }
6018 
6019  if (fNotify) {
6020  if (fReadEntry < 0) {
6021  fNotify->Notify();
6022  }
6023  }
6024  fReadEntry = entry;
6025 
6026  Bool_t friendHasEntry = kFALSE;
6027  if (fFriends) {
6028  // Set current entry in friends as well.
6029  //
6030  // An alternative would move this code to each of the
6031  // functions calling LoadTree (and to overload a few more).
6032  Bool_t needUpdate = kFALSE;
6033  {
6034  // This scope is need to insure the lock is released at the right time
6035  TIter nextf(fFriends);
6036  TFriendLock lock(this, kLoadTree);
6037  TFriendElement* fe = 0;
6038  while ((fe = (TFriendElement*) nextf())) {
6040  // This friend element was added by the chain that owns this
6041  // tree, the chain will deal with loading the correct entry.
6042  continue;
6043  }
6044  TTree* friendTree = fe->GetTree();
6045  if (friendTree == 0) {
6046  // Somehow we failed to retrieve the friend TTree.
6047  } else if (friendTree->IsA() == TTree::Class()) {
6048  // Friend is actually a tree.
6049  if (friendTree->LoadTreeFriend(entry, this) >= 0) {
6050  friendHasEntry = kTRUE;
6051  }
6052  } else {
6053  // Friend is actually a chain.
6054  // FIXME: This logic should be in the TChain override.
6055  Int_t oldNumber = friendTree->GetTreeNumber();
6056  if (friendTree->LoadTreeFriend(entry, this) >= 0) {
6057  friendHasEntry = kTRUE;
6058  }
6059  Int_t newNumber = friendTree->GetTreeNumber();
6060  if (oldNumber != newNumber) {
6061  // We can not just compare the tree pointers because they could be reused.
6062  // So we compare the tree number instead.
6063  needUpdate = kTRUE;
6064  }
6065  }
6066  } // for each friend
6067  }
6068  if (needUpdate) {
6069  //update list of leaves in all TTreeFormula of the TTreePlayer (if any)
6070  if (fPlayer) {
6072  }
6073  //Notify user if requested
6074  if (fNotify) {
6075  fNotify->Notify();
6076  }
6077  }
6078  }
6079 
6080  if ((fReadEntry >= fEntries) && !friendHasEntry) {
6081  fReadEntry = -1;
6082  return -2;
6083  }
6084  return fReadEntry;
6085 }
6086 
6087 ////////////////////////////////////////////////////////////////////////////////
6088 /// Load entry on behalf of our master tree, we may use an index.
6089 ///
6090 /// Called by LoadTree() when the masterTree looks for the entry
6091 /// number in a friend tree (us) corresponding to the passed entry
6092 /// number in the masterTree.
6093 ///
6094 /// If we have no index, our entry number and the masterTree entry
6095 /// number are the same.
6096 ///
6097 /// If we *do* have an index, we must find the (major, minor) value pair
6098 /// in masterTree to locate our corresponding entry.
6099 ///
6100 
6101 Long64_t TTree::LoadTreeFriend(Long64_t entry, TTree* masterTree)
6103  if (!fTreeIndex) {
6104  return LoadTree(entry);
6105  }
6106  return LoadTree(fTreeIndex->GetEntryNumberFriend(masterTree));
6107 }
6108 
6109 ////////////////////////////////////////////////////////////////////////////////
6110 /// Generate a skeleton analysis class for this tree.
6111 ///
6112 /// The following files are produced: classname.h and classname.C.
6113 /// If classname is 0, classname will be called "nameoftree".
6114 ///
6115 /// The generated code in classname.h includes the following:
6116 ///
6117 /// - Identification of the original tree and the input file name.
6118 /// - Definition of an analysis class (data members and member functions).
6119 /// - The following member functions:
6120 /// - constructor (by default opening the tree file),
6121 /// - GetEntry(Long64_t entry),
6122 /// - Init(TTree* tree) to initialize a new TTree,
6123 /// - Show(Long64_t entry) to read and dump entry.
6124 ///
6125 /// The generated code in classname.C includes only the main
6126 /// analysis function Loop.
6127 ///
6128 /// To use this function:
6129 ///
6130 /// - Open your tree file (eg: TFile f("myfile.root");)
6131 /// - T->MakeClass("MyClass");
6132 ///
6133 /// where T is the name of the TTree in file myfile.root,
6134 /// and MyClass.h, MyClass.C the name of the files created by this function.
6135 /// In a ROOT session, you can do:
6136 /// ~~~ {.cpp}
6137 /// root > .L MyClass.C
6138 /// root > MyClass* t = new MyClass;
6139 /// root > t->GetEntry(12); // Fill data members of t with entry number 12.
6140 /// root > t->Show(); // Show values of entry 12.
6141 /// root > t->Show(16); // Read and show values of entry 16.
6142 /// root > t->Loop(); // Loop on all entries.
6143 /// ~~~
6144 /// NOTE: Do not use the code generated for a single TTree which is part
6145 /// of a TChain to process that entire TChain. The maximum dimensions
6146 /// calculated for arrays on the basis of a single TTree from the TChain
6147 /// might be (will be!) too small when processing all of the TTrees in
6148 /// the TChain. You must use myChain.MakeClass() to generate the code,
6149 /// not myTree.MakeClass(...).
6150 
6151 Int_t TTree::MakeClass(const char* classname, Option_t* option)
6153  GetPlayer();
6154  if (!fPlayer) {
6155  return 0;
6156  }
6157  return fPlayer->MakeClass(classname, option);
6158 }
6159 
6160 ////////////////////////////////////////////////////////////////////////////////
6161 /// Generate a skeleton function for this tree.
6162 ///
6163 /// The function code is written on filename.
6164 /// If filename is 0, filename will be called nameoftree.C
6165 ///
6166 /// The generated code includes the following:
6167 /// - Identification of the original Tree and Input file name,
6168 /// - Opening the Tree file,
6169 /// - Declaration of Tree variables,
6170 /// - Setting of branches addresses,
6171 /// - A skeleton for the entry loop.
6172 ///
6173 /// To use this function:
6174 ///
6175 /// - Open your Tree file (eg: TFile f("myfile.root");)
6176 /// - T->MakeCode("MyAnalysis.C");
6177 ///
6178 /// where T is the name of the TTree in file myfile.root
6179 /// and MyAnalysis.C the name of the file created by this function.
6180 ///
6181 /// NOTE: Since the implementation of this function, a new and better
6182 /// function TTree::MakeClass() has been developed.
6183 
6184 Int_t TTree::MakeCode(const char* filename)
6186  Warning("MakeCode", "MakeCode is obsolete. Use MakeClass or MakeSelector instead");
6187 
6188  GetPlayer();
6189  if (!fPlayer) return 0;
6190  return fPlayer->MakeCode(filename);
6191 }
6192 
6193 ////////////////////////////////////////////////////////////////////////////////
6194 /// Generate a skeleton analysis class for this Tree using TBranchProxy.
6195 ///
6196 /// TBranchProxy is the base of a class hierarchy implementing an
6197 /// indirect access to the content of the branches of a TTree.
6198 ///
6199 /// "proxyClassname" is expected to be of the form:
6200 /// ~~~ {.cpp}
6201 /// [path/]fileprefix
6202 /// ~~~
6203 /// The skeleton will then be generated in the file:
6204 /// ~~~ {.cpp}
6205 /// fileprefix.h
6206 /// ~~~
6207 /// located in the current directory or in 'path/' if it is specified.
6208 /// The class generated will be named 'fileprefix'
6209 ///
6210 /// "macrofilename" and optionally "cutfilename" are expected to point
6211 /// to source files which will be included by the generated skeleton.
6212 /// Method of the same name as the file(minus the extension and path)
6213 /// will be called by the generated skeleton's Process method as follow:
6214 /// ~~~ {.cpp}
6215 /// [if (cutfilename())] htemp->Fill(macrofilename());
6216 /// ~~~
6217 /// "option" can be used select some of the optional features during
6218 /// the code generation. The possible options are:
6219 ///
6220 /// - nohist : indicates that the generated ProcessFill should not fill the histogram.
6221 ///
6222 /// 'maxUnrolling' controls how deep in the class hierarchy does the
6223 /// system 'unroll' classes that are not split. Unrolling a class
6224 /// allows direct access to its data members (this emulates the behavior
6225 /// of TTreeFormula).
6226 ///
6227 /// The main features of this skeleton are:
6228 ///
6229 /// * on-demand loading of branches
6230 /// * ability to use the 'branchname' as if it was a data member
6231 /// * protection against array out-of-bounds errors
6232 /// * ability to use the branch data as an object (when the user code is available)
6233 ///
6234 /// For example with Event.root, if
6235 /// ~~~ {.cpp}
6236 /// Double_t somePx = fTracks.fPx[2];
6237 /// ~~~
6238 /// is executed by one of the method of the skeleton,
6239 /// somePx will updated with the current value of fPx of the 3rd track.
6240 ///
6241 /// Both macrofilename and the optional cutfilename are expected to be
6242 /// the name of source files which contain at least a free standing
6243 /// function with the signature:
6244 /// ~~~ {.cpp}
6245 /// x_t macrofilename(); // i.e function with the same name as the file
6246 /// ~~~
6247 /// and
6248 /// ~~~ {.cpp}
6249 /// y_t cutfilename(); // i.e function with the same name as the file
6250 /// ~~~
6251 /// x_t and y_t needs to be types that can convert respectively to a double
6252 /// and a bool (because the skeleton uses:
6253 ///
6254 /// if (cutfilename()) htemp->Fill(macrofilename());
6255 ///
6256 /// These two functions are run in a context such that the branch names are
6257 /// available as local variables of the correct (read-only) type.
6258 ///
6259 /// Note that if you use the same 'variable' twice, it is more efficient
6260 /// to 'cache' the value. For example:
6261 /// ~~~ {.cpp}
6262 /// Int_t n = fEventNumber; // Read fEventNumber
6263 /// if (n<10 || n>10) { ... }
6264 /// ~~~
6265 /// is more efficient than
6266 /// ~~~ {.cpp}
6267 /// if (fEventNumber<10 || fEventNumber>10)
6268 /// ~~~
6269 /// Also, optionally, the generated selector will also call methods named
6270 /// macrofilename_methodname in each of 6 main selector methods if the method
6271 /// macrofilename_methodname exist (Where macrofilename is stripped of its
6272 /// extension).
6273 ///
6274 /// Concretely, with the script named h1analysisProxy.C,
6275 ///
6276 /// - The method calls the method (if it exist)
6277 /// - Begin -> void h1analysisProxy_Begin(TTree*);
6278 /// - SlaveBegin -> void h1analysisProxy_SlaveBegin(TTree*);
6279 /// - Notify -> Bool_t h1analysisProxy_Notify();
6280 /// - Process -> Bool_t h1analysisProxy_Process(Long64_t);
6281 /// - SlaveTerminate -> void h1analysisProxy_SlaveTerminate();
6282 /// - Terminate -> void h1analysisProxy_Terminate();
6283 ///
6284 /// If a file name macrofilename.h (or .hh, .hpp, .hxx, .hPP, .hXX) exist
6285 /// it is included before the declaration of the proxy class. This can
6286 /// be used in particular to insure that the include files needed by
6287 /// the macro file are properly loaded.
6288 ///
6289 /// The default histogram is accessible via the variable named 'htemp'.
6290 ///
6291 /// If the library of the classes describing the data in the branch is
6292 /// loaded, the skeleton will add the needed #include statements and
6293 /// give the ability to access the object stored in the branches.
6294 ///
6295 /// To draw px using the file hsimple.root (generated by the
6296 /// hsimple.C tutorial), we need a file named hsimple.cxx:
6297 /// ~~~ {.cpp}
6298 /// double hsimple() {
6299 /// return px;
6300 /// }
6301 /// ~~~
6302 /// MakeProxy can then be used indirectly via the TTree::Draw interface
6303 /// as follow:
6304 /// ~~~ {.cpp}
6305 /// new TFile("hsimple.root")
6306 /// ntuple->Draw("hsimple.cxx");
6307 /// ~~~
6308 /// A more complete example is available in the tutorials directory:
6309 /// h1analysisProxy.cxx , h1analysProxy.h and h1analysisProxyCut.C
6310 /// which reimplement the selector found in h1analysis.C
6311 
6312 Int_t TTree::MakeProxy(const char* proxyClassname, const char* macrofilename, const char* cutfilename, const char* option, Int_t maxUnrolling)
6314  GetPlayer();
6315  if (!fPlayer) return 0;
6316  return fPlayer->MakeProxy(proxyClassname,macrofilename,cutfilename,option,maxUnrolling);
6317 }
6318 
6319 ////////////////////////////////////////////////////////////////////////////////
6320 /// Generate skeleton selector class for this tree.
6321 ///
6322 /// The following files are produced: selector.h and selector.C.
6323 /// If selector is 0, the selector will be called "nameoftree".
6324 /// The option can be used to specify the branches that will have a data member.
6325 /// - If option is "=legacy", a pre-ROOT6 selector will be generated (data
6326 /// members and branch pointers instead of TTreeReaders).
6327 /// - If option is empty, readers will be generated for each leaf.
6328 /// - If option is "@", readers will be generated for the topmost branches.
6329 /// - Individual branches can also be picked by their name:
6330 /// - "X" generates readers for leaves of X.
6331 /// - "@X" generates a reader for X as a whole.
6332 /// - "@X;Y" generates a reader for X as a whole and also readers for the
6333 /// leaves of Y.
6334 /// - For further examples see the figure below.
6335 ///
6336 /// \image html ttree_makeselector_option_examples.png
6337 ///
6338 /// The generated code in selector.h includes the following:
6339 /// - Identification of the original Tree and Input file name
6340 /// - Definition of selector class (data and functions)
6341 /// - The following class functions:
6342 /// - constructor and destructor
6343 /// - void Begin(TTree *tree)
6344 /// - void SlaveBegin(TTree *tree)
6345 /// - void Init(TTree *tree)
6346 /// - Bool_t Notify()
6347 /// - Bool_t Process(Long64_t entry)
6348 /// - void Terminate()
6349 /// - void SlaveTerminate()
6350 ///
6351 /// The class selector derives from TSelector.
6352 /// The generated code in selector.C includes empty functions defined above.
6353 ///
6354 /// To use this function:
6355 ///
6356 /// - connect your Tree file (eg: `TFile f("myfile.root");`)
6357 /// - `T->MakeSelector("myselect");`
6358 ///
6359 /// where T is the name of the Tree in file myfile.root
6360 /// and myselect.h, myselect.C the name of the files created by this function.
6361 /// In a ROOT session, you can do:
6362 /// ~~~ {.cpp}
6363 /// root > T->Process("myselect.C")
6364 /// ~~~
6365 
6366 Int_t TTree::MakeSelector(const char* selector, Option_t* option)
6368  TString opt(option);
6369  if(opt.EqualTo("=legacy", TString::ECaseCompare::kIgnoreCase)) {
6370  return MakeClass(selector, "selector");
6371  } else {
6372  GetPlayer();
6373  if (!fPlayer) return 0;
6374  return fPlayer->MakeReader(selector, option);
6375  }
6376 }
6377 
6378 ////////////////////////////////////////////////////////////////////////////////
6379 /// Check if adding nbytes to memory we are still below MaxVirtualsize.
6380 
6383  if ((fTotalBuffers + nbytes) < fMaxVirtualSize) {
6384  return kFALSE;
6385  }
6386  return kTRUE;
6387 }
6388 
6389 ////////////////////////////////////////////////////////////////////////////////
6390 /// Static function merging the trees in the TList into a new tree.
6391 ///
6392 /// Trees in the list can be memory or disk-resident trees.
6393 /// The new tree is created in the current directory (memory if gROOT).
6394 
6395 TTree* TTree::MergeTrees(TList* li, Option_t* options)
6397  if (!li) return 0;
6398  TIter next(li);
6399  TTree *newtree = 0;
6400  TObject *obj;
6401 
6402  while ((obj=next())) {
6403  if (!obj->InheritsFrom(TTree::Class())) continue;
6404  TTree *tree = (TTree*)obj;
6405  Long64_t nentries = tree->GetEntries();
6406  if (nentries == 0) continue;
6407  if (!newtree) {
6408  newtree = (TTree*)tree->CloneTree();
6409  if (!newtree) continue;
6410 
6411  // Once the cloning is done, separate the trees,
6412  // to avoid as many side-effects as possible
6413  // The list of clones is guaranteed to exist since we
6414  // just cloned the tree.
6415  tree->GetListOfClones()->Remove(newtree);
6416  tree->ResetBranchAddresses();
6417  newtree->ResetBranchAddresses();
6418  continue;
6419  }
6420 
6421  newtree->CopyAddresses(tree);
6422 
6423  newtree->CopyEntries(tree,-1,options);
6424 
6425  tree->ResetBranchAddresses(); // Disconnect from new tree.
6426  }
6427  if (newtree && newtree->GetTreeIndex()) {
6428  newtree->GetTreeIndex()->Append(0,kFALSE); // Force the sorting
6429  }
6430  return newtree;
6431 }
6432 
6433 ////////////////////////////////////////////////////////////////////////////////
6434 /// Merge the trees in the TList into this tree.
6435 ///
6436 /// Returns the total number of entries in the merged tree.
6437 
6440  if (!li) return 0;
6441  Long64_t storeAutoSave = fAutoSave;
6442  // Disable the autosave as the TFileMerge keeps a list of key and deleting the underlying
6443  // key would invalidate its iteration (or require costly measure to not use the deleted keys).
6444  // Also since this is part of a merging operation, the output file is not as precious as in
6445  // the general case since the input file should still be around.
6446  fAutoSave = 0;
6447  TIter next(li);
6448  TTree *tree;
6449  while ((tree = (TTree*)next())) {
6450  if (tree==this) continue;
6451  if (!tree->InheritsFrom(TTree::Class())) {
6452  Error("Add","Attempt to add object of class: %s to a %s", tree->ClassName(), ClassName());
6453  fAutoSave = storeAutoSave;
6454  return -1;
6455  }
6456 
6457  Long64_t nentries = tree->GetEntries();
6458  if (nentries == 0) continue;
6459 
6460  CopyAddresses(tree);
6461 
6462  CopyEntries(tree,-1,options);
6463 
6464  tree->ResetBranchAddresses();
6465  }
6466  fAutoSave = storeAutoSave;
6467  return GetEntries();
6468 }
6469 
6470 ////////////////////////////////////////////////////////////////////////////////
6471 /// Merge the trees in the TList into this tree.
6472 /// If info->fIsFirst is true, first we clone this TTree info the directory
6473 /// info->fOutputDirectory and then overlay the new TTree information onto
6474 /// this TTree object (so that this TTree object is now the appropriate to
6475 /// use for further merging).
6476 ///
6477 /// Returns the total number of entries in the merged tree.
6478 
6481  const char *options = info ? info->fOptions.Data() : "";
6482  if (info && info->fIsFirst && info->fOutputDirectory && info->fOutputDirectory->GetFile() != GetCurrentFile()) {
6484  TTree *newtree = CloneTree(-1, options);
6485  if (newtree) {
6486  newtree->Write();
6487  delete newtree;
6488  }
6489  // Make sure things are really written out to disk before attempting any reading.
6490  info->fOutputDirectory->GetFile()->Flush();
6491  info->fOutputDirectory->ReadTObject(this,this->GetName());
6492  }
6493  if (!li) return 0;
6494  Long64_t storeAutoSave = fAutoSave;
6495  // Disable the autosave as the TFileMerge keeps a list of key and deleting the underlying
6496  // key would invalidate its iteration (or require costly measure to not use the deleted keys).
6497  // Also since this is part of a merging operation, the output file is not as precious as in
6498  // the general case since the input file should still be around.
6499  fAutoSave = 0;
6500  TIter next(li);
6501  TTree *tree;
6502  while ((tree = (TTree*)next())) {
6503  if (tree==this) continue;
6504  if (!tree->InheritsFrom(TTree::Class())) {
6505  Error("Add","Attempt to add object of class: %s to a %s", tree->ClassName(), ClassName());
6506  fAutoSave = storeAutoSave;
6507  return -1;
6508  }
6509  // Copy MakeClass status.
6510  tree->SetMakeClass(fMakeClass);
6511 
6512  // Copy branch addresses.
6513  CopyAddresses(tree);
6514 
6515  CopyEntries(tree,-1,options);
6516 
6517  tree->ResetBranchAddresses();
6518  }
6519  fAutoSave = storeAutoSave;
6520  return GetEntries();
6521 }
6522 
6523 ////////////////////////////////////////////////////////////////////////////////
6524 /// Move a cache from a file to the current file in dir.
6525 /// if src is null no operation is done, if dir is null or there is no
6526 /// current file the cache is deleted.
6527 
6528 void TTree::MoveReadCache(TFile *src, TDirectory *dir)
6530  if (!src) return;
6531  TFile *dst = (dir && dir != gROOT) ? dir->GetFile() : 0;
6532  if (src == dst) return;
6533 
6534  TTreeCache *pf = GetReadCache(src);
6535  if (dst) {
6536  src->SetCacheRead(0,this);
6537  dst->SetCacheRead(pf, this);
6538  } else {
6539  if (pf) {
6540  pf->WaitFinishPrefetch();
6541  }
6542  src->SetCacheRead(0,this);
6543  delete pf;
6544  }
6545 }
6546 
6547 ////////////////////////////////////////////////////////////////////////////////
6548 /// Function called when loading a new class library.
6549 
6552  TIter next(GetListOfLeaves());
6553  TLeaf* leaf = 0;
6554  while ((leaf = (TLeaf*) next())) {
6555  leaf->Notify();
6556  leaf->GetBranch()->Notify();
6557  }
6558  return kTRUE;
6559 }
6560 
6561 ////////////////////////////////////////////////////////////////////////////////
6562 /// This function may be called after having filled some entries in a Tree
6563 /// Using the information in the existing branch buffers, it will reassign
6564 /// new branch buffer sizes to optimize time and memory.
6565 ///
6566 /// The function computes the best values for branch buffer sizes such that
6567 /// the total buffer sizes is less than maxMemory and nearby entries written
6568 /// at the same time.
6569 /// In case the branch compression factor for the data written so far is less
6570 /// than compMin, the compression is disabled.
6571 ///
6572 /// if option ="d" an analysis report is printed.
6573 
6574 void TTree::OptimizeBaskets(ULong64_t maxMemory, Float_t minComp, Option_t *option)
6576  //Flush existing baskets if the file is writable
6577  if (this->GetDirectory()->IsWritable()) this->FlushBaskets();
6578 
6579  TString opt( option );
6580  opt.ToLower();
6581  Bool_t pDebug = opt.Contains("d");
6582  TObjArray *leaves = this->GetListOfLeaves();
6583  Int_t nleaves = leaves->GetEntries();
6584  Double_t treeSize = (Double_t)this->GetTotBytes();
6585 
6586  if (nleaves == 0 || treeSize == 0) {
6587  // We're being called too early, we really have nothing to do ...
6588  return;
6589  }
6590  Double_t aveSize = treeSize/nleaves;
6591  UInt_t bmin = 512;
6592  UInt_t bmax = 256000;
6593  Double_t memFactor = 1;
6594  Int_t i, oldMemsize,newMemsize,oldBaskets,newBaskets;
6595  i = oldMemsize = newMemsize = oldBaskets = newBaskets = 0;
6596 
6597  //we make two passes
6598  //one pass to compute the relative branch buffer sizes
6599  //a second pass to compute the absolute values
6600  for (Int_t pass =0;pass<2;pass++) {
6601  oldMemsize = 0; //to count size of baskets in memory with old buffer size
6602  newMemsize = 0; //to count size of baskets in memory with new buffer size
6603  oldBaskets = 0; //to count number of baskets with old buffer size
6604  newBaskets = 0; //to count number of baskets with new buffer size
6605  for (i=0;i<nleaves;i++) {
6606  TLeaf *leaf = (TLeaf*)leaves->At(i);
6607  TBranch *branch = leaf->GetBranch();
6608  Double_t totBytes = (Double_t)branch->GetTotBytes();
6609  Double_t idealFactor = totBytes/aveSize;
6610  UInt_t sizeOfOneEntry;
6611  if (branch->GetEntries() == 0) {
6612  // There is no data, so let's make a guess ...
6613  sizeOfOneEntry = aveSize;
6614  } else {
6615  sizeOfOneEntry = 1+(UInt_t)(totBytes / (Double_t)branch->GetEntries());
6616  }
6617  Int_t oldBsize = branch->GetBasketSize();
6618  oldMemsize += oldBsize;
6619  oldBaskets += 1+Int_t(totBytes/oldBsize);
6620  Int_t nb = branch->GetListOfBranches()->GetEntries();
6621  if (nb > 0) {
6622  newBaskets += 1+Int_t(totBytes/oldBsize);
6623  continue;
6624  }
6625  Double_t bsize = oldBsize*idealFactor*memFactor; //bsize can be very large !
6626  if (bsize < 0) bsize = bmax;
6627  if (bsize > bmax) bsize = bmax;
6628  UInt_t newBsize = UInt_t(bsize);
6629  if (pass) { // only on the second pass so that it doesn't interfere with scaling
6630  newBsize = newBsize + (branch->GetEntries() * sizeof(Int_t) * 2); // make room for meta data
6631  // We used ATLAS fully-split xAOD for testing, which is a rather unbalanced TTree, 10K branches,
6632  // with 8K having baskets smaller than 512 bytes. To achieve good I/O performance ATLAS uses auto-flush 100,
6633  // resulting in the smallest baskets being ~300-400 bytes, so this change increases their memory by about 8k*150B =~ 1MB,
6634  // at the same time it significantly reduces the number of total baskets because it ensures that all 100 entries can be
6635  // stored in a single basket (the old optimization tended to make baskets too small). In a toy example with fixed sized
6636  // structures we found a factor of 2 fewer baskets needed in the new scheme.
6637  // rounds up, increases basket size to ensure all entries fit into single basket as intended
6638  newBsize = newBsize - newBsize%512 + 512;
6639  }
6640  if (newBsize < sizeOfOneEntry) newBsize = sizeOfOneEntry;
6641  if (newBsize < bmin) newBsize = bmin;
6642  if (newBsize > 10000000) newBsize = bmax;
6643  if (pass) {
6644  if (pDebug) printf("Changing buffer size from %6d to %6d bytes for %s\n",oldBsize,newBsize,branch->GetName());
6645  branch->SetBasketSize(newBsize);
6646  }
6647  newMemsize += newBsize;
6648  // For this number to be somewhat accurate when newBsize is 'low'
6649  // we do not include any space for meta data in the requested size (newBsize) even-though SetBasketSize will
6650  // not let it be lower than 100+TBranch::fEntryOffsetLen.
6651  newBaskets += 1+Int_t(totBytes/newBsize);
6652  if (pass == 0) continue;
6653  //Reset the compression level in case the compression factor is small
6654  Double_t comp = 1;
6655  if (branch->GetZipBytes() > 0) comp = totBytes/Double_t(branch->GetZipBytes());
6656  if (comp > 1 && comp < minComp) {
6657  if (pDebug) printf("Disabling compression for branch : %s\n",branch->GetName());
6658  branch->SetCompressionSettings(0);
6659  }
6660  }
6661  // coverity[divide_by_zero] newMemsize can not be zero as there is at least one leaf
6662  memFactor = Double_t(maxMemory)/Double_t(newMemsize);
6663  if (memFactor > 100) memFactor = 100;
6664  Double_t bmin_new = bmin*memFactor;
6665  Double_t bmax_new = bmax*memFactor;
6666  static const UInt_t hardmax = 1*1024*1024*1024; // Really, really never give more than 1Gb to a single buffer.
6667 
6668  // Really, really never go lower than 8 bytes (we use this number
6669  // so that the calculation of the number of basket is consistent
6670  // but in fact SetBasketSize will not let the size go below
6671  // TBranch::fEntryOffsetLen + (100 + strlen(branch->GetName())
6672  // (The 2nd part being a slight over estimate of the key length.
6673  static const UInt_t hardmin = 8;
6674  bmin = (bmin_new > hardmax) ? hardmax : ( bmin_new < hardmin ? hardmin : (UInt_t)bmin_new );
6675  bmax = (bmax_new > hardmax) ? bmin : (UInt_t)bmax_new;
6676  }
6677  if (pDebug) {
6678  printf("oldMemsize = %d, newMemsize = %d\n",oldMemsize, newMemsize);
6679  printf("oldBaskets = %d, newBaskets = %d\n",oldBaskets, newBaskets);
6680  }
6681 }
6682 
6683 ////////////////////////////////////////////////////////////////////////////////
6684 /// Interface to the Principal Components Analysis class.
6685 ///
6686 /// Create an instance of TPrincipal
6687 ///
6688 /// Fill it with the selected variables
6689 ///
6690 /// - if option "n" is specified, the TPrincipal object is filled with
6691 /// normalized variables.
6692 /// - If option "p" is specified, compute the principal components
6693 /// - If option "p" and "d" print results of analysis
6694 /// - If option "p" and "h" generate standard histograms
6695 /// - If option "p" and "c" generate code of conversion functions
6696 /// - return a pointer to the TPrincipal object. It is the user responsibility
6697 /// - to delete this object.
6698 /// - The option default value is "np"
6699 ///
6700 /// see TTree::Draw for explanation of the other parameters.
6701 ///
6702 /// The created object is named "principal" and a reference to it
6703 /// is added to the list of specials Root objects.
6704 /// you can retrieve a pointer to the created object via:
6705 /// ~~~ {.cpp}
6706 /// TPrincipal *principal =
6707 /// (TPrincipal*)gROOT->GetListOfSpecials()->FindObject("principal");
6708 /// ~~~
6709 
6710 TPrincipal* TTree::Principal(const char* varexp, const char* selection, Option_t* option, Long64_t nentries, Long64_t firstentry)
6712  GetPlayer();
6713  if (fPlayer) {
6714  return fPlayer->Principal(varexp, selection, option, nentries, firstentry);
6715  }
6716  return 0;
6717 }
6718 
6719 ////////////////////////////////////////////////////////////////////////////////
6720 /// Print a summary of the tree contents.
6721 ///
6722 /// - If option contains "all" friend trees are also printed.
6723 /// - If option contains "toponly" only the top level branches are printed.
6724 /// - If option contains "clusters" information about the cluster of baskets is printed.
6725 ///
6726 /// Wildcarding can be used to print only a subset of the branches, e.g.,
6727 /// `T.Print("Elec*")` will print all branches with name starting with "Elec".
6728 
6729 void TTree::Print(Option_t* option) const
6731  // We already have been visited while recursively looking
6732  // through the friends tree, let's return.
6733  if (kPrint & fFriendLockStatus) {
6734  return;
6735  }
6736  Int_t s = 0;
6737  Int_t skey = 0;
6738  if (fDirectory) {
6739  TKey* key = fDirectory->GetKey(GetName());
6740  if (key) {
6741  skey = key->GetKeylen();
6742  s = key->GetNbytes();
6743  }
6744  }
6745  Long64_t total = skey;
6746  if (fZipBytes > 0) {
6747  total += fTotBytes;
6748  }
6749  TBufferFile b(TBuffer::kWrite, 10000);
6750  TTree::Class()->WriteBuffer(b, (TTree*) this);
6751  total += b.Length();
6752  Long64_t file = fZipBytes + s;
6753  Float_t cx = 1;
6754  if (fZipBytes) {
6755  cx = (fTotBytes + 0.00001) / fZipBytes;
6756  }
6757  Printf("******************************************************************************");
6758  Printf("*Tree :%-10s: %-54s *", GetName(), GetTitle());
6759  Printf("*Entries : %8lld : Total = %15lld bytes File Size = %10lld *", fEntries, total, file);
6760  Printf("* : : Tree compression factor = %6.2f *", cx);
6761  Printf("******************************************************************************");
6762 
6763  if (strncmp(option,"clusters",strlen("clusters"))==0) {
6764  Printf("%-16s %-16s %-16s %5s",
6765  "Cluster Range #", "Entry Start", "Last Entry", "Size");
6766  Int_t index= 0;
6767  Long64_t clusterRangeStart = 0;
6768  if (fNClusterRange) {
6769  for( ; index < fNClusterRange; ++index) {
6770  Printf("%-16d %-16lld %-16lld %5lld",
6771  index, clusterRangeStart, fClusterRangeEnd[index], fClusterSize[index]);
6772  clusterRangeStart = fClusterRangeEnd[index] + 1;
6773  }
6774  }
6775  Printf("%-16d %-16lld %-16lld %5lld",
6776  index, clusterRangeStart, fEntries - 1, fAutoFlush);
6777  return;
6778  }
6779 
6780  Int_t nl = const_cast<TTree*>(this)->GetListOfLeaves()->GetEntries();
6781  Int_t l;
6782  TBranch* br = 0;
6783  TLeaf* leaf = 0;
6784  if (strstr(option, "toponly")) {
6785  Long64_t *count = new Long64_t[nl];
6786  Int_t keep =0;
6787  for (l=0;l<nl;l++) {
6788  leaf = (TLeaf *)const_cast<TTree*>(this)->GetListOfLeaves()->At(l);
6789  br = leaf->GetBranch();
6790  if (strchr(br->GetName(),'.')) {
6791  count[l] = -1;
6792  count[keep] += br->GetZipBytes();
6793  } else {
6794  keep = l;
6795  count[keep] = br->GetZipBytes();
6796  }
6797  }
6798  for (l=0;l<nl;l++) {
6799  if (count[l] < 0) continue;
6800  leaf = (TLeaf *)const_cast<TTree*>(this)->GetListOfLeaves()->At(l);
6801  br = leaf->GetBranch();
6802  printf("branch: %-20s %9lld\n",br->GetName(),count[l]);
6803  }
6804  delete [] count;
6805  } else {
6806  TString reg = "*";
6807  if (strlen(option) && strchr(option,'*')) reg = option;
6808  TRegexp re(reg,kTRUE);
6809  TIter next(const_cast<TTree*>(this)->GetListOfBranches());
6811  while ((br= (TBranch*)next())) {
6812  TString st = br->GetName();
6813  st.ReplaceAll("/","_");
6814  if (st.Index(re) == kNPOS) continue;
6815  br->Print(option);
6816  }
6817  }
6818 
6819  //print TRefTable (if one)
6820  if (fBranchRef) fBranchRef->Print(option);
6821 
6822  //print friends if option "all"
6823  if (!fFriends || !strstr(option,"all")) return;
6824  TIter nextf(fFriends);
6825  TFriendLock lock(const_cast<TTree*>(this),kPrint);
6826  TFriendElement *fr;
6827  while ((fr = (TFriendElement*)nextf())) {
6828  TTree * t = fr->GetTree();
6829  if (t) t->Print(option);
6830  }
6831 }
6832 
6833 ////////////////////////////////////////////////////////////////////////////////
6834 /// print statistics about the TreeCache for this tree, like
6835 /// ~~~ {.cpp}
6836 /// ******TreeCache statistics for file: cms2.root ******
6837 /// Reading 73921562 bytes in 716 transactions
6838 /// Average transaction = 103.242405 Kbytes
6839 /// Number of blocks in current cache: 202, total size : 6001193
6840 /// ~~~
6841 /// if option = "a" the list of blocks in the cache is printed
6842 
6843 void TTree::PrintCacheStats(Option_t* option) const
6845  TFile *f = GetCurrentFile();
6846  if (!f) return;
6847  TTreeCache *tc = (TTreeCache*)f->GetCacheRead(const_cast<TTree*>(this));
6848  if (tc) tc->Print(option);
6849 }
6850 
6851 ////////////////////////////////////////////////////////////////////////////////
6852 /// Process this tree executing the TSelector code in the specified filename.
6853 /// The return value is -1 in case of error and TSelector::GetStatus() in
6854 /// in case of success.
6855 ///
6856 /// The code in filename is loaded (interpreted or compiled, see below),
6857 /// filename must contain a valid class implementation derived from TSelector,
6858 /// where TSelector has the following member functions:
6859 ///
6860 /// - `Begin()`: called every time a loop on the tree starts,
6861 /// a convenient place to create your histograms.
6862 /// - `SlaveBegin()`: called after Begin(), when on PROOF called only on the
6863 /// slave servers.
6864 /// - `Process()`: called for each event, in this function you decide what
6865 /// to read and fill your histograms.
6866 /// - `SlaveTerminate`: called at the end of the loop on the tree, when on PROOF
6867 /// called only on the slave servers.
6868 /// - `Terminate()`: called at the end of the loop on the tree,
6869 /// a convenient place to draw/fit your histograms.
6870 ///
6871 /// If filename is of the form file.C, the file will be interpreted.
6872 ///
6873 /// If filename is of the form file.C++, the file file.C will be compiled
6874 /// and dynamically loaded.
6875 ///
6876 /// If filename is of the form file.C+, the file file.C will be compiled
6877 /// and dynamically loaded. At next call, if file.C is older than file.o
6878 /// and file.so, the file.C is not compiled, only file.so is loaded.
6879 ///
6880 /// ## NOTE1
6881 ///
6882 /// It may be more interesting to invoke directly the other Process function
6883 /// accepting a TSelector* as argument.eg
6884 /// ~~~ {.cpp}
6885 /// MySelector *selector = (MySelector*)TSelector::GetSelector(filename);
6886 /// selector->CallSomeFunction(..);
6887 /// mytree.Process(selector,..);
6888 /// ~~~
6889 /// ## NOTE2
6890 //
6891 /// One should not call this function twice with the same selector file
6892 /// in the same script. If this is required, proceed as indicated in NOTE1,
6893 /// by getting a pointer to the corresponding TSelector,eg
6894 ///
6895 /// ### workaround 1
6896 /// ~~~ {.cpp}
6897 /// void stubs1() {
6898 /// TSelector *selector = TSelector::GetSelector("h1test.C");
6899 /// TFile *f1 = new TFile("stubs_nood_le1.root");
6900 /// TTree *h1 = (TTree*)f1->Get("h1");
6901 /// h1->Process(selector);
6902 /// TFile *f2 = new TFile("stubs_nood_le1_coarse.root");
6903 /// TTree *h2 = (TTree*)f2->Get("h1");
6904 /// h2->Process(selector);
6905 /// }
6906 /// ~~~
6907 /// or use ACLIC to compile the selector
6908 ///
6909 /// ### workaround 2
6910 /// ~~~ {.cpp}
6911 /// void stubs2() {
6912 /// TFile *f1 = new TFile("stubs_nood_le1.root");
6913 /// TTree *h1 = (TTree*)f1->Get("h1");
6914 /// h1->Process("h1test.C+");
6915 /// TFile *f2 = new TFile("stubs_nood_le1_coarse.root");
6916 /// TTree *h2 = (TTree*)f2->Get("h1");
6917 /// h2->Process("h1test.C+");
6918 /// }
6919 /// ~~~
6920 
6921 Long64_t TTree::Process(const char* filename, Option_t* option, Long64_t nentries, Long64_t firstentry)
6923  GetPlayer();
6924  if (fPlayer) {
6925  return fPlayer->Process(filename, option, nentries, firstentry);
6926  }
6927  return -1;
6928 }
6929 
6930 ////////////////////////////////////////////////////////////////////////////////
6931 /// Process this tree executing the code in the specified selector.
6932 /// The return value is -1 in case of error and TSelector::GetStatus() in
6933 /// in case of success.
6934 ///
6935 /// The TSelector class has the following member functions:
6936 ///
6937 /// - `Begin()`: called every time a loop on the tree starts,
6938 /// a convenient place to create your histograms.
6939 /// - `SlaveBegin()`: called after Begin(), when on PROOF called only on the
6940 /// slave servers.
6941 /// - `Process()`: called for each event, in this function you decide what
6942 /// to read and fill your histograms.
6943 /// - `SlaveTerminate`: called at the end of the loop on the tree, when on PROOF
6944 /// called only on the slave servers.
6945 /// - `Terminate()`: called at the end of the loop on the tree,
6946 /// a convenient place to draw/fit your histograms.
6947 ///
6948 /// If the Tree (Chain) has an associated EventList, the loop is on the nentries
6949 /// of the EventList, starting at firstentry, otherwise the loop is on the
6950 /// specified Tree entries.
6951 
6952 Long64_t TTree::Process(TSelector* selector, Option_t* option, Long64_t nentries, Long64_t firstentry)
6954  GetPlayer();
6955  if (fPlayer) {
6956  return fPlayer->Process(selector, option, nentries, firstentry);
6957  }
6958  return -1;
6959 }
6960 
6961 ////////////////////////////////////////////////////////////////////////////////
6962 /// Make a projection of a tree using selections.
6963 ///
6964 /// Depending on the value of varexp (described in Draw) a 1-D, 2-D, etc.,
6965 /// projection of the tree will be filled in histogram hname.
6966 /// Note that the dimension of hname must match with the dimension of varexp.
6967 ///
6968 
6969 Long64_t TTree::Project(const char* hname, const char* varexp, const char* selection, Option_t* option, Long64_t nentries, Long64_t firstentry)
6971  TString var;
6972  var.Form("%s>>%s", varexp, hname);
6973  TString opt("goff");
6974  if (option) {
6975  opt.Form("%sgoff", option);
6976  }
6977  Long64_t nsel = Draw(var, selection, opt, nentries, firstentry);
6978  return nsel;
6979 }
6980 
6981 ////////////////////////////////////////////////////////////////////////////////
6982 /// Loop over entries and return a TSQLResult object containing entries following selection.
6983 
6984 TSQLResult* TTree::Query(const char* varexp, const char* selection, Option_t* option, Long64_t nentries, Long64_t firstentry)
6986  GetPlayer();
6987  if (fPlayer) {
6988  return fPlayer->Query(varexp, selection, option, nentries, firstentry);
6989  }
6990  return 0;
6991 }
6992 
6993 ////////////////////////////////////////////////////////////////////////////////
6994 /// Create or simply read branches from filename.
6995 ///
6996 /// if branchDescriptor = "" (default), it is assumed that the Tree descriptor
6997 /// is given in the first line of the file with a syntax like
6998 /// ~~~ {.cpp}
6999 /// A/D:Table[2]/F:Ntracks/I:astring/C
7000 /// ~~~
7001 /// otherwise branchDescriptor must be specified with the above syntax.
7002 ///
7003 /// - If the type of the first variable is not specified, it is assumed to be "/F"
7004 /// - If the type of any other variable is not specified, the type of the previous
7005 /// variable is assumed. eg
7006 /// - `x:y:z` (all variables are assumed of type "F"
7007 /// - `x/D:y:z` (all variables are of type "D"
7008 /// - `x:y/D:z` (x is type "F", y and z of type "D"
7009 ///
7010 /// delimiter allows for the use of another delimiter besides whitespace.
7011 /// This provides support for direct import of common data file formats
7012 /// like csv. If delimiter != ' ' and branchDescriptor == "", then the
7013 /// branch description is taken from the first line in the file, but
7014 /// delimiter is used for the branch names tokenization rather than ':'.
7015 /// Note however that if the values in the first line do not use the
7016 /// /[type] syntax, all variables are assumed to be of type "F".
7017 /// If the filename ends with extensions .csv or .CSV and a delimiter is
7018 /// not specified (besides ' '), the delimiter is automatically set to ','.
7019 ///
7020 /// Lines in the input file starting with "#" are ignored. Leading whitespace
7021 /// for each column data is skipped. Empty lines are skipped.
7022 ///
7023 /// A TBranch object is created for each variable in the expression.
7024 /// The total number of rows read from the file is returned.
7025 ///
7026 /// ## FILLING a TTree WITH MULTIPLE INPUT TEXT FILES
7027 ///
7028 /// To fill a TTree with multiple input text files, proceed as indicated above
7029 /// for the first input file and omit the second argument for subsequent calls
7030 /// ~~~ {.cpp}
7031 /// T.ReadFile("file1.dat","branch descriptor");
7032 /// T.ReadFile("file2.dat");
7033 /// ~~~
7034 
7035 Long64_t TTree::ReadFile(const char* filename, const char* branchDescriptor, char delimiter)
7037  std::ifstream in;
7038  in.open(filename);
7039  if (!in.good()) {
7040  Error("ReadFile","Cannot open file: %s",filename);
7041  return 0;
7042  }
7043  const char* ext = strrchr(filename, '.');
7044  if(ext != NULL && ((strcmp(ext, ".csv") == 0) || (strcmp(ext, ".CSV") == 0)) && delimiter == ' ') {
7045  delimiter = ',';
7046  }
7047  return ReadStream(in, branchDescriptor, delimiter);
7048 }
7049 
7050 ////////////////////////////////////////////////////////////////////////////////
7051 /// Determine which newline this file is using.
7052 /// Return '\\r' for Windows '\\r\\n' as that already terminates.
7053 
7054 char TTree::GetNewlineValue(std::istream &inputStream)
7056  Long_t inPos = inputStream.tellg();
7057  char newline = '\n';
7058  while(1) {
7059  char c = 0;
7060  inputStream.get(c);
7061  if(!inputStream.good()) {
7062  Error("ReadStream","Error reading stream: no newline found.");
7063  return 0;
7064  }
7065  if(c == newline) break;
7066  if(c == '\r') {
7067  newline = '\r';
7068  break;
7069  }
7070  }
7071  inputStream.clear();
7072  inputStream.seekg(inPos);
7073  return newline;
7074 }
7075 
7076 ////////////////////////////////////////////////////////////////////////////////
7077 /// Create or simply read branches from an input stream.
7078 ///
7079 /// See reference information for TTree::ReadFile
7080 
7081 Long64_t TTree::ReadStream(std::istream& inputStream, const char *branchDescriptor, char delimiter)
7083  char newline = 0;
7084  std::stringstream ss;
7085  std::istream *inTemp;
7086  Long_t inPos = inputStream.tellg();
7087  if (!inputStream.good()) {
7088  Error("ReadStream","Error reading stream");
7089  return 0;
7090  }
7091  if (inPos == -1) {
7092  ss << std::cin.rdbuf();
7093  newline = GetNewlineValue(ss);
7094  inTemp = &ss;
7095  } else {
7096  newline = GetNewlineValue(inputStream);
7097  inTemp = &inputStream;
7098  }
7099  std::istream& in = *inTemp;
7100  Long64_t nlines = 0;
7101 
7102  TBranch *branch = 0;
7103  Int_t nbranches = fBranches.GetEntries();
7104  if (nbranches == 0) {
7105  char *bdname = new char[4000];
7106  char *bd = new char[100000];
7107  Int_t nch = 0;
7108  if (branchDescriptor) nch = strlen(branchDescriptor);
7109  // branch Descriptor is null, read its definition from the first line in the file
7110  if (!nch) {
7111  do {
7112  in.getline(bd, 100000, newline);
7113  if (!in.good()) {
7114  delete [] bdname;
7115  delete [] bd;
7116  Error("ReadStream","Error reading stream");
7117  return 0;
7118  }
7119  char *cursor = bd;
7120  while( isspace(*cursor) && *cursor != '\n' && *cursor != '\0') {
7121  ++cursor;
7122  }
7123  if (*cursor != '#' && *cursor != '\n' && *cursor != '\0') {
7124  break;
7125  }
7126  } while (true);
7127  ++nlines;
7128  nch = strlen(bd);
7129  } else {
7130  strlcpy(bd,branchDescriptor,100000);
7131  }
7132 
7133  //parse the branch descriptor and create a branch for each element
7134  //separated by ":"
7135  void *address = &bd[90000];
7136  char *bdcur = bd;
7137  TString desc="", olddesc="F";
7138  char bdelim = ':';
7139  if(delimiter != ' ') {
7140  bdelim = delimiter;
7141  if (strchr(bdcur,bdelim)==0 && strchr(bdcur,':') != 0) {
7142  // revert to the default
7143  bdelim = ':';
7144  }
7145  }
7146  while (bdcur) {
7147  char *colon = strchr(bdcur,bdelim);
7148  if (colon) *colon = 0;
7149  strlcpy(bdname,bdcur,4000);
7150  char *slash = strchr(bdname,'/');
7151  if (slash) {
7152  *slash = 0;
7153  desc = bdcur;
7154  olddesc = slash+1;
7155  } else {
7156  desc.Form("%s/%s",bdname,olddesc.Data());
7157  }
7158  char *bracket = strchr(bdname,'[');
7159  if (bracket) {
7160  *bracket = 0;
7161  }
7162  branch = new TBranch(this,bdname,address,desc.Data(),32000);
7163  if (branch->IsZombie()) {
7164  delete branch;
7165  Warning("ReadStream","Illegal branch definition: %s",bdcur);
7166  } else {
7167  fBranches.Add(branch);
7168  branch->SetAddress(0);
7169  }
7170  if (!colon)break;
7171  bdcur = colon+1;
7172  }
7173  delete [] bdname;
7174  delete [] bd;
7175  }
7176 
7177  nbranches = fBranches.GetEntries();
7178 
7179  if (gDebug > 1) {
7180  Info("ReadStream", "Will use branches:");
7181  for (int i = 0 ; i < nbranches; ++i) {
7182  TBranch* br = (TBranch*) fBranches.At(i);
7183  Info("ReadStream", " %s: %s [%s]", br->GetName(),
7184  br->GetTitle(), br->GetListOfLeaves()->At(0)->IsA()->GetName());
7185  }
7186  if (gDebug > 3) {
7187  Info("ReadStream", "Dumping read tokens, format:");
7188  Info("ReadStream", "LLLLL:BBB:gfbe:GFBE:T");
7189  Info("ReadStream", " L: line number");
7190  Info("ReadStream", " B: branch number");
7191  Info("ReadStream", " gfbe: good / fail / bad / eof of token");
7192  Info("ReadStream", " GFBE: good / fail / bad / eof of file");
7193  Info("ReadStream", " T: Token being read");
7194  }
7195  }
7196 
7197  //loop on all lines in the file
7198  Long64_t nGoodLines = 0;
7199  std::string line;
7200  const char sDelimBuf[2] = { delimiter, 0 };
7201  const char* sDelim = sDelimBuf;
7202  if (delimiter == ' ') {
7203  // ' ' really means whitespace
7204  sDelim = "[ \t]";
7205  }
7206  while(in.good()) {
7207  if (newline == '\r' && in.peek() == '\n') {
7208  // Windows, skip '\n':
7209  in.get();
7210  }
7211  std::getline(in, line, newline);
7212  ++nlines;
7213 
7214  TString sLine(line);
7215  sLine = sLine.Strip(TString::kLeading); // skip leading whitespace
7216  if (sLine.IsNull()) {
7217  if (gDebug > 2) {
7218  Info("ReadStream", "Skipping empty line number %lld", nlines);
7219  }
7220  continue; // silently skip empty lines
7221  }
7222  if (sLine[0] == '#') {
7223  if (gDebug > 2) {
7224  Info("ReadStream", "Skipping comment line number %lld: '%s'",
7225  nlines, line.c_str());
7226  }
7227  continue;
7228  }
7229  if (gDebug > 2) {
7230  Info("ReadStream", "Parsing line number %lld: '%s'",
7231  nlines, line.c_str());
7232  }
7233 
7234  // Loop on branches and read the branch values into their buffer
7235  branch = 0;
7236  TString tok; // one column's data
7237  TString leafData; // leaf data, possibly multiple tokens for e.g. /I[2]
7238  std::stringstream sToken; // string stream feeding leafData into leaves
7239  Ssiz_t pos = 0;
7240  Int_t iBranch = 0;
7241  Bool_t goodLine = kTRUE; // whether the row can be filled into the tree
7242  Int_t remainingLeafLen = 0; // remaining columns for the current leaf
7243  while (goodLine && iBranch < nbranches
7244  && sLine.Tokenize(tok, pos, sDelim)) {
7245  tok = tok.Strip(TString::kLeading); // skip leading whitespace
7246  if (tok.IsNull() && delimiter == ' ') {
7247  // 1 2 should not be interpreted as 1,,,2 but 1, 2.
7248  // Thus continue until we have a non-empty token.
7249  continue;
7250  }
7251 
7252  if (!remainingLeafLen) {
7253  // next branch!
7254  branch = (TBranch*)fBranches.At(iBranch);
7255  }
7256  TLeaf *leaf = (TLeaf*)branch->GetListOfLeaves()->At(0);
7257  if (!remainingLeafLen) {
7258  remainingLeafLen = leaf->GetLen();
7259  if (leaf->GetMaximum() > 0) {
7260  // This is a dynamic leaf length, i.e. most likely a TLeafC's
7261  // string size. This still translates into one token:
7262  remainingLeafLen = 1;
7263  }
7264 
7265  leafData = tok;
7266  } else {
7267  // append token to laf data:
7268  leafData += " ";
7269  leafData += tok;
7270  }
7271  --remainingLeafLen;
7272  if (remainingLeafLen) {
7273  // need more columns for this branch:
7274  continue;
7275  }
7276  ++iBranch;
7277 
7278  // initialize stringstream with token
7279  sToken.clear();
7280  sToken.seekp(0, std::ios_base::beg);
7281  sToken.str(leafData.Data());
7282  sToken.seekg(0, std::ios_base::beg);
7283  leaf->ReadValue(sToken, 0 /* 0 = "all" */);
7284  if (gDebug > 3) {
7285  Info("ReadStream", "%5lld:%3d:%d%d%d%d:%d%d%d%d:%s",
7286  nlines, iBranch,
7287  (int)sToken.good(), (int)sToken.fail(),
7288  (int)sToken.bad(), (int)sToken.eof(),
7289  (int)in.good(), (int)in.fail(),
7290  (int)in.bad(), (int)in.eof(),
7291  sToken.str().c_str());
7292  }
7293 
7294  // Error handling
7295  if (sToken.bad()) {
7296  // How could that happen for a stringstream?
7297  Warning("ReadStream",
7298  "Buffer error while reading data for branch %s on line %lld",
7299  branch->GetName(), nlines);
7300  } else if (!sToken.eof()) {
7301  if (sToken.fail()) {
7302  Warning("ReadStream",
7303  "Couldn't read formatted data in \"%s\" for branch %s on line %lld; ignoring line",
7304  tok.Data(), branch->GetName(), nlines);
7305  goodLine = kFALSE;
7306  } else {
7307  std::string remainder;
7308  std::getline(sToken, remainder, newline);
7309  if (!remainder.empty()) {
7310  Warning("ReadStream",
7311  "Ignoring trailing \"%s\" while reading data for branch %s on line %lld",
7312  remainder.c_str(), branch->GetName(), nlines);
7313  }
7314  }
7315  }
7316  } // tokenizer loop
7317 
7318  if (iBranch < nbranches) {
7319  Warning("ReadStream",
7320  "Read too few columns (%d < %d) in line %lld; ignoring line",
7321  iBranch, nbranches, nlines);
7322  goodLine = kFALSE;
7323  } else if (pos != kNPOS) {
7324  sLine = sLine.Strip(TString::kTrailing);
7325  if (pos < sLine.Length()) {
7326  Warning("ReadStream",
7327  "Ignoring trailing \"%s\" while reading line %lld",
7328  sLine.Data() + pos - 1 /* also print delimiter */,
7329  nlines);
7330  }
7331  }
7332 
7333  //we are now ready to fill the tree
7334  if (goodLine) {
7335  Fill();
7336  ++nGoodLines;
7337  }
7338  }
7339 
7340  return nGoodLines;
7341 }
7342 
7343 ////////////////////////////////////////////////////////////////////////////////
7344 /// Make sure that obj (which is being deleted or will soon be) is no
7345 /// longer referenced by this TTree.
7346 
7349  if (obj == fEventList) {
7350  fEventList = 0;
7351  }
7352  if (obj == fEntryList) {
7353  fEntryList = 0;
7354  }
7355  if (fUserInfo) {
7356  fUserInfo->RecursiveRemove(obj);
7357  }
7358  if (fPlayer == obj) {
7359  fPlayer = 0;
7360  }
7361  if (fTreeIndex == obj) {
7362  fTreeIndex = 0;
7363  }
7364  if (fAliases) {
7365  fAliases->RecursiveRemove(obj);
7366  }
7367  if (fFriends) {
7368  fFriends->RecursiveRemove(obj);
7369  }
7370 }
7371 
7372 ////////////////////////////////////////////////////////////////////////////////
7373 /// Refresh contents of this tree and its branches from the current status on disk.
7374 ///
7375 /// One can call this function in case the tree file is being
7376 /// updated by another process.
7377 
7378 void TTree::Refresh()
7380  if (!fDirectory->GetFile()) {
7381  return;
7382  }
7383  fDirectory->ReadKeys();
7384  fDirectory->Remove(this);
7385  TTree* tree; fDirectory->GetObject(GetName(),tree);
7386  if (!tree) {
7387  return;
7388  }
7389  //copy info from tree header into this Tree
7390  fEntries = 0;
7391  fNClusterRange = 0;
7392  ImportClusterRanges(tree);
7393 
7394  fAutoSave = tree->fAutoSave;
7395  fEntries = tree->fEntries;
7396  fTotBytes = tree->fTotBytes;
7397  fZipBytes = tree->fZipBytes;
7398  fSavedBytes = tree->fSavedBytes;
7399  fTotalBuffers = tree->fTotalBuffers.load();
7400 
7401  //loop on all branches and update them
7402  Int_t nleaves = fLeaves.GetEntriesFast();
7403  for (Int_t i = 0; i < nleaves; i++) {
7404  TLeaf* leaf = (TLeaf*) fLeaves.UncheckedAt(i);
7405  TBranch* branch = (TBranch*) leaf->GetBranch();
7406  branch->Refresh(tree->GetBranch(branch->GetName()));
7407  }
7408  fDirectory->Remove(tree);
7409  fDirectory->Append(this);
7410  delete tree;
7411  tree = 0;
7412 }
7413 
7414 ////////////////////////////////////////////////////////////////////////////////
7415 /// Remove a friend from the list of friends.
7416 
7417 void TTree::RemoveFriend(TTree* oldFriend)
7419  // We already have been visited while recursively looking
7420  // through the friends tree, let return
7422  return;
7423  }
7424  if (!fFriends) {
7425  return;
7426  }
7427  TFriendLock lock(this, kRemoveFriend);
7428  TIter nextf(fFriends);
7429  TFriendElement* fe = 0;
7430  while ((fe = (TFriendElement*) nextf())) {
7431  TTree* friend_t = fe->GetTree();
7432  if (friend_t == oldFriend) {
7433  fFriends->Remove(fe);
7434  delete fe;
7435  fe = 0;
7436  }
7437  }
7438 }
7439 
7440 ////////////////////////////////////////////////////////////////////////////////
7441 /// Reset baskets, buffers and entries count in all branches and leaves.
7442 
7443 void TTree::Reset(Option_t* option)
7445  fNotify = 0;
7446  fEntries = 0;
7447  fNClusterRange = 0;
7448  fTotBytes = 0;
7449  fZipBytes = 0;
7450  fFlushedBytes = 0;
7451  fSavedBytes = 0;
7452  fTotalBuffers = 0;
7453  fChainOffset = 0;
7454  fReadEntry = -1;
7455 
7456  delete fTreeIndex;
7457  fTreeIndex = 0;
7458 
7460  for (Int_t i = 0; i < nb; ++i) {
7461  TBranch* branch = (TBranch*) fBranches.UncheckedAt(i);
7462  branch->Reset(option);
7463  }
7464 
7465  if (fBranchRef) {
7466  fBranchRef->Reset();
7467  }
7468 }
7469 
7470 ////////////////////////////////////////////////////////////////////////////////
7471 /// Resets the state of this TTree after a merge (keep the customization but
7472 /// forget the data).
7473 
7476  fEntries = 0;
7477  fNClusterRange = 0;
7478  fTotBytes = 0;
7479  fZipBytes = 0;
7480  fSavedBytes = 0;
7481  fFlushedBytes = 0;
7482  fTotalBuffers = 0;
7483  fChainOffset = 0;
7484  fReadEntry = -1;
7485 
7486  delete fTreeIndex;
7487  fTreeIndex = 0;
7488 
7490  for (Int_t i = 0; i < nb; ++i) {
7491  TBranch* branch = (TBranch*) fBranches.UncheckedAt(i);
7492  branch->ResetAfterMerge(info);
7493  }
7494 
7495  if (fBranchRef) {
7496  fBranchRef->ResetAfterMerge(info);
7497  }
7498 }
7499 
7500 ////////////////////////////////////////////////////////////////////////////////
7501 /// Tell all of our branches to set their addresses to zero.
7502 ///
7503 /// Note: If any of our branches own any objects, they are deleted.
7504 
7507  if (br && br->GetTree()) {
7508  br->ResetAddress();
7509  }
7510 }
7511 
7512 ////////////////////////////////////////////////////////////////////////////////
7513 /// Tell all of our branches to drop their current objects and allocate new ones.
7514 
7518  Int_t nbranches = branches->GetEntriesFast();
7519  for (Int_t i = 0; i < nbranches; ++i) {
7520  TBranch* branch = (TBranch*) branches->UncheckedAt(i);
7521  branch->ResetAddress();
7522  }
7523 }
7524 
7525 ////////////////////////////////////////////////////////////////////////////////
7526 /// Loop over tree entries and print entries passing selection.
7527 ///
7528 /// - If varexp is 0 (or "") then print only first 8 columns.
7529 /// - If varexp = "*" print all columns.
7530 ///
7531 /// Otherwise a columns selection can be made using "var1:var2:var3".
7532 /// See TTreePlayer::Scan for more information
7533 
7534 Long64_t TTree::Scan(const char* varexp, const char* selection, Option_t* option, Long64_t nentries, Long64_t firstentry)
7536  GetPlayer();
7537  if (fPlayer) {
7538  return fPlayer->Scan(varexp, selection, option, nentries, firstentry);
7539  }
7540  return -1;
7541 }
7542 
7543 ////////////////////////////////////////////////////////////////////////////////
7544 /// Set a tree variable alias.
7545 ///
7546 /// Set an alias for an expression/formula based on the tree 'variables'.
7547 ///
7548 /// The content of 'aliasName' can be used in TTreeFormula (i.e. TTree::Draw,
7549 /// TTree::Scan, TTreeViewer) and will be evaluated as the content of
7550 /// 'aliasFormula'.
7551 ///
7552 /// If the content of 'aliasFormula' only contains symbol names, periods and
7553 /// array index specification (for example event.fTracks[3]), then
7554 /// the content of 'aliasName' can be used as the start of symbol.
7555 ///
7556 /// If the alias 'aliasName' already existed, it is replaced by the new
7557 /// value.
7558 ///
7559 /// When being used, the alias can be preceded by an eventual 'Friend Alias'
7560 /// (see TTree::GetFriendAlias)
7561 ///
7562 /// Return true if it was added properly.
7563 ///
7564 /// For example:
7565 /// ~~~ {.cpp}
7566 /// tree->SetAlias("x1","(tdc1[1]-tdc1[0])/49");
7567 /// tree->SetAlias("y1","(tdc1[3]-tdc1[2])/47");
7568 /// tree->SetAlias("x2","(tdc2[1]-tdc2[0])/49");
7569 /// tree->SetAlias("y2","(tdc2[3]-tdc2[2])/47");
7570 /// tree->Draw("y2-y1:x2-x1");
7571 ///
7572 /// tree->SetAlias("theGoodTrack","event.fTracks[3]");
7573 /// tree->Draw("theGoodTrack.fPx"); // same as "event.fTracks[3].fPx"
7574 /// ~~~
7575 
7576 Bool_t TTree::SetAlias(const char* aliasName, const char* aliasFormula)
7578  if (!aliasName || !aliasFormula) {
7579  return kFALSE;
7580  }
7581  if (!aliasName[0] || !aliasFormula[0]) {
7582  return kFALSE;
7583  }
7584  if (!fAliases) {
7585  fAliases = new TList;
7586  } else {
7587  TNamed* oldHolder = (TNamed*) fAliases->FindObject(aliasName);
7588  if (oldHolder) {
7589  oldHolder->SetTitle(aliasFormula);
7590  return kTRUE;
7591  }
7592  }
7593  TNamed* holder = new TNamed(aliasName, aliasFormula);
7594  fAliases->Add(holder);
7595  return kTRUE;
7596 }
7597 
7598 ////////////////////////////////////////////////////////////////////////////////
7599 /// This function may be called at the start of a program to change
7600 /// the default value for fAutoFlush.
7601 ///
7602 /// ### CASE 1 : autof > 0
7603 ///
7604 /// autof is the number of consecutive entries after which TTree::Fill will
7605 /// flush all branch buffers to disk.
7606 ///
7607 /// ### CASE 2 : autof < 0
7608 ///
7609 /// When filling the Tree the branch buffers will be flushed to disk when
7610 /// more than autof bytes have been written to the file. At the first FlushBaskets
7611 /// TTree::Fill will replace fAutoFlush by the current value of fEntries.
7612 ///
7613 /// Calling this function with autof<0 is interesting when it is hard to estimate
7614 /// the size of one entry. This value is also independent of the Tree.
7615 ///
7616 /// The Tree is initialized with fAutoFlush=-30000000, ie that, by default,
7617 /// the first AutoFlush will be done when 30 MBytes of data are written to the file.
7618 ///
7619 /// ### CASE 3 : autof = 0
7620 ///
7621 /// The AutoFlush mechanism is disabled.
7622 ///
7623 /// Flushing the buffers at regular intervals optimize the location of
7624 /// consecutive entries on the disk by creating clusters of baskets.
7625 ///
7626 /// A cluster of baskets is a set of baskets that contains all
7627 /// the data for a (consecutive) set of entries and that is stored
7628 /// consecutively on the disk. When reading all the branches, this
7629 /// is the minimum set of baskets that the TTreeCache will read.
7630 
7631 void TTree::SetAutoFlush(Long64_t autof /* = -30000000 */ )
7633  // Implementation note:
7634  //
7635  // A positive value of autoflush determines the size (in number of entries) of
7636  // a cluster of baskets.
7637  //
7638  // If the value of autoflush is changed over time (this happens in
7639  // particular when the TTree results from fast merging many trees),
7640  // we record the values of fAutoFlush in the data members:
7641  // fClusterRangeEnd and fClusterSize.
7642  // In the code we refer to a range of entries where the size of the
7643  // cluster of baskets is the same (i.e the value of AutoFlush was
7644  // constant) is called a ClusterRange.
7645  //
7646  // The 2 arrays (fClusterRangeEnd and fClusterSize) have fNClusterRange
7647  // active (used) values and have fMaxClusterRange allocated entries.
7648  //
7649  // fClusterRangeEnd contains the last entries number of a cluster range.
7650  // In particular this means that the 'next' cluster starts at fClusterRangeEnd[]+1
7651  // fClusterSize contains the size in number of entries of all the cluster
7652  // within the given range.
7653  // The last range (and the only one if fNClusterRange is zero) start at
7654  // fNClusterRange[fNClusterRange-1]+1 and ends at the end of the TTree. The
7655  // size of the cluster in this range is given by the value of fAutoFlush.
7656  //
7657  // For example printing the beginning and end of each the ranges can be done by:
7658  //
7659  // Printf("%-16s %-16s %-16s %5s",
7660  // "Cluster Range #", "Entry Start", "Last Entry", "Size");
7661  // Int_t index= 0;
7662  // Long64_t clusterRangeStart = 0;
7663  // if (fNClusterRange) {
7664  // for( ; index < fNClusterRange; ++index) {
7665  // Printf("%-16d %-16lld %-16lld %5lld",
7666  // index, clusterRangeStart, fClusterRangeEnd[index], fClusterSize[index]);
7667  // clusterRangeStart = fClusterRangeEnd[index] + 1;
7668  // }
7669  // }
7670  // Printf("%-16d %-16lld %-16lld %5lld",
7671  // index, prevEntry, fEntries - 1, fAutoFlush);
7672  //
7673 
7674  // Note: We store the entry number corresponding to the end of the cluster
7675  // rather than its start in order to avoid using the array if the cluster
7676  // size never varies (If there is only one value of AutoFlush for the whole TTree).
7677 
7678  if (fAutoFlush > 0 || autof > 0) {
7679  // The mechanism was already enabled, let's record the previous
7680  // cluster if needed.
7681  if (fFlushedBytes) {
7682  if ( (fNClusterRange+1) > fMaxClusterRange ) {
7683  if (fMaxClusterRange) {
7684  Int_t newsize = TMath::Max(10,Int_t(2*fMaxClusterRange));
7686  newsize*sizeof(Long64_t),fMaxClusterRange*sizeof(Long64_t));
7688  newsize*sizeof(Long64_t),fMaxClusterRange*sizeof(Long64_t));
7689  fMaxClusterRange = newsize;
7690  } else {
7691  fMaxClusterRange = 2;
7694  }
7695  }
7698  ++fNClusterRange;
7699  }
7700  }
7701  fAutoFlush = autof;
7702 }
7703 
7704 ////////////////////////////////////////////////////////////////////////////////
7705 /// This function may be called at the start of a program to change
7706 /// the default value for fAutoSave (and for SetAutoSave) is -300000000, ie 300 MBytes
7707 /// When filling the Tree the branch buffers as well as the Tree header
7708 /// will be flushed to disk when the watermark is reached.
7709 /// If fAutoSave is positive the watermark is reached when a multiple of fAutoSave
7710 /// entries have been written.
7711 /// If fAutoSave is negative the watermark is reached when -fAutoSave bytes
7712 /// have been written to the file.
7713 /// In case of a program crash, it will be possible to recover the data in the Tree
7714 /// up to the last AutoSave point.
7715 
7716 void TTree::SetAutoSave(Long64_t autos)
7718  fAutoSave = autos;
7719 }
7720 
7721 ////////////////////////////////////////////////////////////////////////////////
7722 /// Set a branch's basket size.
7723 ///
7724 /// bname is the name of a branch.
7725 ///
7726 /// - if bname="*", apply to all branches.
7727 /// - if bname="xxx*", apply to all branches with name starting with xxx
7728 ///
7729 /// see TRegexp for wildcarding options
7730 /// buffsize = branc basket size
7731 
7732 void TTree::SetBasketSize(const char* bname, Int_t buffsize)
7734  Int_t nleaves = fLeaves.GetEntriesFast();
7735  TRegexp re(bname, kTRUE);
7736  Int_t nb = 0;
7737  for (Int_t i = 0; i < nleaves; i++) {
7738  TLeaf* leaf = (TLeaf*) fLeaves.UncheckedAt(i);
7739  TBranch* branch = (TBranch*) leaf->GetBranch();
7740  TString s = branch->GetName();
7741  if (strcmp(bname, branch->GetName()) && (s.Index(re) == kNPOS)) {
7742  continue;
7743  }
7744  nb++;
7745  branch->SetBasketSize(buffsize);
7746  }
7747  if (!nb) {
7748  Error("SetBasketSize", "unknown branch -> '%s'", bname);
7749  }
7750 }
7751 
7752 ////////////////////////////////////////////////////////////////////////////////
7753 /// Change branch address, dealing with clone trees properly.
7754 /// See TTree::CheckBranchAddressType for the semantic of the return value.
7755 ///
7756 /// Note: See the comments in TBranchElement::SetAddress() for the
7757 /// meaning of the addr parameter and the object ownership policy.
7758 
7759 Int_t TTree::SetBranchAddress(const char* bname, void* addr, TBranch** ptr)
7761  TBranch* branch = GetBranch(bname);
7762  if (!branch) {
7763  if (ptr) *ptr = 0;
7764  Error("SetBranchAddress", "unknown branch -> %s", bname);
7765  return kMissingBranch;
7766  }
7767  return SetBranchAddressImp(branch,addr,ptr);
7768 }
7769 
7770 ////////////////////////////////////////////////////////////////////////////////
7771 /// Verify the validity of the type of addr before calling SetBranchAddress.
7772 /// See TTree::CheckBranchAddressType for the semantic of the return value.
7773 ///
7774 /// Note: See the comments in TBranchElement::SetAddress() for the
7775 /// meaning of the addr parameter and the object ownership policy.
7776 
7777 Int_t TTree::SetBranchAddress(const char* bname, void* addr, TClass* ptrClass, EDataType datatype, Bool_t isptr)
7779  return SetBranchAddress(bname, addr, 0, ptrClass, datatype, isptr);
7780 }
7781 
7782 ////////////////////////////////////////////////////////////////////////////////
7783 /// Verify the validity of the type of addr before calling SetBranchAddress.
7784 /// See TTree::CheckBranchAddressType for the semantic of the return value.
7785 ///
7786 /// Note: See the comments in TBranchElement::SetAddress() for the
7787 /// meaning of the addr parameter and the object ownership policy.
7788 
7789 Int_t TTree::SetBranchAddress(const char* bname, void* addr, TBranch** ptr, TClass* ptrClass, EDataType datatype, Bool_t isptr)
7791  TBranch* branch = GetBranch(bname);
7792  if (!branch) {
7793  if (ptr) *ptr = 0;
7794  Error("SetBranchAddress", "unknown branch -> %s", bname);
7795  return kMissingBranch;
7796  }
7797 
7798  Int_t res = CheckBranchAddressType(branch, ptrClass, datatype, isptr);
7799  // This will set the value of *ptr to branch.
7800  if (res >= 0) {
7801  // The check succeeded.
7802  SetBranchAddressImp(branch,addr,ptr);
7803  } else {
7804  if (ptr) *ptr = 0;
7805  }
7806  return res;
7807 }
7808 
7809 ////////////////////////////////////////////////////////////////////////////////
7810 /// Change branch address, dealing with clone trees properly.
7811 /// See TTree::CheckBranchAddressType for the semantic of the return value.
7812 ///
7813 /// Note: See the comments in TBranchElement::SetAddress() for the
7814 /// meaning of the addr parameter and the object ownership policy.
7815 
7816 Int_t TTree::SetBranchAddressImp(TBranch *branch, void* addr, TBranch** ptr)
7818  if (ptr) {
7819  *ptr = branch;
7820  }
7821  if (fClones) {
7822  void* oldAddr = branch->GetAddress();
7823  TIter next(fClones);
7824  TTree* clone = 0;
7825  const char *bname = branch->GetName();
7826  while ((clone = (TTree*) next())) {
7827  TBranch* cloneBr = clone->GetBranch(bname);
7828  if (cloneBr && (cloneBr->GetAddress() == oldAddr)) {
7829  cloneBr->SetAddress(addr);
7830  }
7831  }
7832  }
7833  branch->SetAddress(addr);
7834  return kVoidPtr;
7835 }
7836 
7837 ////////////////////////////////////////////////////////////////////////////////
7838 /// Set branch status to Process or DoNotProcess.
7839 ///
7840 /// When reading a Tree, by default, all branches are read.
7841 /// One can speed up considerably the analysis phase by activating
7842 /// only the branches that hold variables involved in a query.
7843 ///
7844 /// bname is the name of a branch.
7845 ///
7846 /// - if bname="*", apply to all branches.
7847 /// - if bname="xxx*", apply to all branches with name starting with xxx
7848 ///
7849 /// see TRegexp for wildcarding options
7850 ///
7851 /// - status = 1 branch will be processed
7852 /// - = 0 branch will not be processed
7853 ///
7854 /// Example:
7855 ///
7856 /// Assume a tree T with sub-branches a,b,c,d,e,f,g,etc..
7857 /// when doing T.GetEntry(i) all branches are read for entry i.
7858 /// to read only the branches c and e, one can do
7859 /// ~~~ {.cpp}
7860 /// T.SetBranchStatus("*",0); //disable all branches
7861 /// T.SetBranchStatus("c",1);
7862 /// T.setBranchStatus("e",1);
7863 /// T.GetEntry(i);
7864 /// ~~~
7865 /// bname is interpreted as a wildcarded TRegexp (see TRegexp::MakeWildcard).
7866 /// Thus, "a*b" or "a.*b" matches branches starting with "a" and ending with
7867 /// "b", but not any other branch with an "a" followed at some point by a
7868 /// "b". For this second behavior, use "*a*b*". Note that TRegExp does not
7869 /// support '|', and so you cannot select, e.g. track and shower branches
7870 /// with "track|shower".
7871 ///
7872 /// __WARNING! WARNING! WARNING!__
7873 ///
7874 /// SetBranchStatus is matching the branch based on match of the branch
7875 /// 'name' and not on the branch hierarchy! In order to be able to
7876 /// selectively enable a top level object that is 'split' you need to make
7877 /// sure the name of the top level branch is prefixed to the sub-branches'
7878 /// name (by adding a dot ('.') at the end of the Branch creation and use the
7879 /// corresponding bname.
7880 ///
7881 /// I.e If your Tree has been created in split mode with a parent branch "parent."
7882 /// (note the trailing dot).
7883 /// ~~~ {.cpp}
7884 /// T.SetBranchStatus("parent",1);
7885 /// ~~~
7886 /// will not activate the sub-branches of "parent". You should do:
7887 /// ~~~ {.cpp}
7888 /// T.SetBranchStatus("parent*",1);
7889 /// ~~~
7890 /// Without the trailing dot in the branch creation you have no choice but to
7891 /// call SetBranchStatus explicitly for each of the sub branches.
7892 ///
7893 /// An alternative to this function is to read directly and only
7894 /// the interesting branches. Example:
7895 /// ~~~ {.cpp}
7896 /// TBranch *brc = T.GetBranch("c");
7897 /// TBranch *bre = T.GetBranch("e");
7898 /// brc->GetEntry(i);
7899 /// bre->GetEntry(i);
7900 /// ~~~
7901 /// If found is not 0, the number of branch(es) found matching the regular
7902 /// expression is returned in *found AND the error message 'unknown branch'
7903 /// is suppressed.
7904 
7905 void TTree::SetBranchStatus(const char* bname, Bool_t status, UInt_t* found)
7907  // We already have been visited while recursively looking
7908  // through the friends tree, let return
7910  return;
7911  }
7912 
7913  TBranch *branch, *bcount, *bson;
7914  TLeaf *leaf, *leafcount;
7915 
7916  Int_t i,j;
7917  Int_t nleaves = fLeaves.GetEntriesFast();
7918  TRegexp re(bname,kTRUE);
7919  Int_t nb = 0;
7920 
7921  // first pass, loop on all branches
7922  // for leafcount branches activate/deactivate in function of status
7923  for (i=0;i<nleaves;i++) {
7924  leaf = (TLeaf*)fLeaves.UncheckedAt(i);
7925  branch = (TBranch*)leaf->GetBranch();
7926  TString s = branch->GetName();
7927  if (strcmp(bname,"*")) { //Regexp gives wrong result for [] in name
7928  TString longname;
7929  longname.Form("%s.%s",GetName(),branch->GetName());
7930  if (strcmp(bname,branch->GetName())
7931  && longname != bname
7932  && s.Index(re) == kNPOS) continue;
7933  }
7934  nb++;
7935  if (status) branch->ResetBit(kDoNotProcess);
7936  else branch->SetBit(kDoNotProcess);
7937  leafcount = leaf->GetLeafCount();
7938  if (leafcount) {
7939  bcount = leafcount->GetBranch();
7940  if (status) bcount->ResetBit(kDoNotProcess);
7941  else bcount->SetBit(kDoNotProcess);
7942  }
7943  }
7944  if (nb==0 && strchr(bname,'*')==0) {
7945  branch = GetBranch(bname);
7946  if (branch) {
7947  if (status) branch->ResetBit(kDoNotProcess);
7948  else branch->SetBit(kDoNotProcess);
7949  ++nb;
7950  }
7951  }
7952 
7953  //search in list of friends
7954  UInt_t foundInFriend = 0;
7955  if (fFriends) {
7956  TFriendLock lock(this,kSetBranchStatus);
7957  TIter nextf(fFriends);
7958  TFriendElement *fe;
7959  TString name;
7960  while ((fe = (TFriendElement*)nextf())) {
7961  TTree *t = fe->GetTree();
7962  if (t==0) continue;
7963 
7964  // If the alias is present replace it with the real name.
7965  char *subbranch = (char*)strstr(bname,fe->GetName());
7966  if (subbranch!=bname) subbranch = 0;
7967  if (subbranch) {
7968  subbranch += strlen(fe->GetName());
7969  if ( *subbranch != '.' ) subbranch = 0;
7970  else subbranch ++;
7971  }
7972  if (subbranch) {
7973  name.Form("%s.%s",t->GetName(),subbranch);
7974  } else {
7975  name = bname;
7976  }
7977  t->SetBranchStatus(name,status, &foundInFriend);
7978  }
7979  }
7980  if (!nb && !foundInFriend) {
7981  if (found==0) {
7982  if (status) {
7983  if (strchr(bname,'*') != 0)
7984  Error("SetBranchStatus", "No branch name is matching wildcard -> %s", bname);
7985  else
7986  Error("SetBranchStatus", "unknown branch -> %s", bname);
7987  } else {
7988  if (strchr(bname,'*') != 0)
7989  Warning("SetBranchStatus", "No branch name is matching wildcard -> %s", bname);
7990  else
7991  Warning("SetBranchStatus", "unknown branch -> %s", bname);
7992  }
7993  }
7994  return;
7995  }
7996  if (found) *found = nb + foundInFriend;
7997 
7998  // second pass, loop again on all branches
7999  // activate leafcount branches for active branches only
8000  for (i = 0; i < nleaves; i++) {
8001  leaf = (TLeaf*)fLeaves.UncheckedAt(i);
8002  branch = (TBranch*)leaf->GetBranch();
8003  if (!branch->TestBit(kDoNotProcess)) {
8004  leafcount = leaf->GetLeafCount();
8005  if (leafcount) {
8006  bcount = leafcount->GetBranch();
8007  bcount->ResetBit(kDoNotProcess);
8008  }
8009  } else {
8010  //Int_t nbranches = branch->GetListOfBranches()->GetEntriesFast();
8011  Int_t nbranches = branch->GetListOfBranches()->GetEntries();
8012  for (j=0;j<nbranches;j++) {
8013  bson = (TBranch*)branch->GetListOfBranches()->UncheckedAt(j);
8014  if (!bson) continue;
8015  if (!bson->TestBit(kDoNotProcess)) {
8016  if (bson->GetNleaves() <= 0) continue;
8017  branch->ResetBit(kDoNotProcess);
8018  break;
8019  }
8020  }
8021  }
8022  }
8023 }
8024 
8025 ////////////////////////////////////////////////////////////////////////////////
8026 /// Set the current branch style. (static function)
8027 ///
8028 /// - style = 0 old Branch
8029 /// - style = 1 new Bronch
8030 
8033  fgBranchStyle = style;
8034 }
8035 
8036 ////////////////////////////////////////////////////////////////////////////////
8037 /// Set maximum size of the file cache .
8038 //
8039 /// - if cachesize = 0 the existing cache (if any) is deleted.
8040 /// - if cachesize = -1 (default) it is set to the AutoFlush value when writing
8041 /// the Tree (default is 30 MBytes).
8042 ///
8043 /// Returns:
8044 /// - 0 size set, cache was created if possible
8045 /// - -1 on error
8046 
8049  // remember that the user has requested an explicit cache setup
8050  fCacheUserSet = kTRUE;
8051 
8052  return SetCacheSizeAux(kFALSE, cacheSize);
8053 }
8054 
8055 ////////////////////////////////////////////////////////////////////////////////
8056 /// Set the size of the file cache and create it if possible.
8057 ///
8058 /// If autocache is true:
8059 /// this may be an autocreated cache, possibly enlarging an existing
8060 /// autocreated cache. The size is calculated. The value passed in cacheSize:
8061 /// - cacheSize = 0 make cache if default cache creation is enabled
8062 /// - cacheSize = -1 make a default sized cache in any case
8063 ///
8064 /// If autocache is false:
8065 /// this is a user requested cache. cacheSize is used to size the cache.
8066 /// This cache should never be automatically adjusted.
8067 ///
8068 /// Returns:
8069 /// - 0 size set, or existing autosized cache almost large enough.
8070 /// (cache was created if possible)
8071 /// - -1 on error
8072 
8073 Int_t TTree::SetCacheSizeAux(Bool_t autocache /* = kTRUE */, Long64_t cacheSize /* = 0 */ )
8075  if (autocache) {
8076  // used as a once only control for automatic cache setup
8078  }
8079 
8080  if (!autocache) {
8081  // negative size means the user requests the default
8082  if (cacheSize < 0) {
8083  cacheSize = GetCacheAutoSize(kTRUE);
8084  }
8085  } else {
8086  if (cacheSize == 0) {
8087  cacheSize = GetCacheAutoSize();
8088  } else if (cacheSize < 0) {
8089  cacheSize = GetCacheAutoSize(kTRUE);
8090  }
8091  }
8092 
8093  TFile* file = GetCurrentFile();
8094  if (!file || GetTree() != this) {
8095  // if there's no file or we are not a plain tree (e.g. if we're a TChain)
8096  // do not create a cache, only record the size if one was given
8097  if (!autocache) {
8098  fCacheSize = cacheSize;
8099  }
8100  if (GetTree() != this) {
8101  return 0;
8102  }
8103  if (!autocache && cacheSize>0) {
8104  Warning("SetCacheSizeAux", "A TTreeCache could not be created because the TTree has no file");
8105  }
8106  return 0;
8107  }
8108 
8109  // Check for an existing cache
8110  TTreeCache* pf = GetReadCache(file);
8111  if (pf) {
8112  if (autocache) {
8113  // reset our cache status tracking in case existing cache was added
8114  // by the user without using one of the TTree methods
8115  fCacheSize = pf->GetBufferSize();
8116  fCacheUserSet = !pf->IsAutoCreated();
8117 
8118  if (fCacheUserSet) {
8119  // existing cache was created by the user, don't change it
8120  return 0;
8121  }
8122  } else {
8123  // update the cache to ensure it records the user has explicitly
8124  // requested it
8125  pf->SetAutoCreated(kFALSE);
8126  }
8127 
8128  // if we're using an automatically calculated size and the existing
8129  // cache is already almost large enough don't resize
8130  if (autocache && Long64_t(0.80*cacheSize) < fCacheSize) {
8131  // already large enough
8132  return 0;
8133  }
8134 
8135  if (cacheSize == fCacheSize) {
8136  return 0;
8137  }
8138 
8139  if (cacheSize == 0) {
8140  // delete existing cache
8141  pf->WaitFinishPrefetch();
8142  file->SetCacheRead(0,this);
8143  delete pf;
8144  pf = 0;
8145  } else {
8146  // resize
8147  Int_t res = pf->SetBufferSize(cacheSize);
8148  if (res < 0) {
8149  return -1;
8150  }
8151  }
8152  } else {
8153  // no existing cache
8154  if (autocache) {
8155  if (fCacheUserSet) {
8156  // value was already set manually.
8157  if (fCacheSize == 0) return 0;
8158  // Expected a cache should exist; perhaps the user moved it
8159  // Do nothing more here.
8160  if (cacheSize) {
8161  Error("SetCacheSizeAux", "Not setting up an automatically sized TTreeCache because of missing cache previously set");
8162  }
8163  return -1;
8164  }
8165  }
8166  }
8167 
8168  fCacheSize = cacheSize;
8169  if (cacheSize == 0 || pf) {
8170  return 0;
8171  }
8172 
8174  pf = new TTreeCacheUnzip(this, cacheSize);
8175  else
8176  pf = new TTreeCache(this, cacheSize);
8177 
8178  pf->SetAutoCreated(autocache);
8179 
8180  return 0;
8181 }
8182 
8183 ////////////////////////////////////////////////////////////////////////////////
8184 ///interface to TTreeCache to set the cache entry range
8185 ///
8186 /// Returns:
8187 /// - 0 entry range set
8188 /// - -1 on error
8189 
8192  if (!GetTree()) {
8193  if (LoadTree(0)<0) {
8194  Error("SetCacheEntryRange","Could not load a tree");
8195  return -1;
8196  }
8197  }
8198  if (GetTree()) {
8199  if (GetTree() != this) {
8200  return GetTree()->SetCacheEntryRange(first, last);
8201  }
8202  } else {
8203  Error("SetCacheEntryRange", "No tree is available. Could not set cache entry range");
8204  return -1;
8205  }
8206 
8207  TFile *f = GetCurrentFile();
8208  if (!f) {
8209  Error("SetCacheEntryRange", "No file is available. Could not set cache entry range");
8210  return -1;
8211  }
8212  TTreeCache *tc = GetReadCache(f,kTRUE);
8213  if (!tc) {
8214  Error("SetCacheEntryRange", "No cache is available. Could not set entry range");
8215  return -1;
8216  }
8217  tc->SetEntryRange(first,last);
8218  return 0;
8219 }
8220 
8221 ////////////////////////////////////////////////////////////////////////////////
8222 /// Interface to TTreeCache to set the number of entries for the learning phase
8223 
8227 }
8228 
8229 ////////////////////////////////////////////////////////////////////////////////
8230 /// Enable/Disable circularity for this tree.
8231 ///
8232 /// if maxEntries > 0 a maximum of maxEntries is kept in one buffer/basket
8233 /// per branch in memory.
8234 /// Note that when this function is called (maxEntries>0) the Tree
8235 /// must be empty or having only one basket per branch.
8236 /// if maxEntries <= 0 the tree circularity is disabled.
8237 ///
8238 /// #### NOTE 1:
8239 /// Circular Trees are interesting in online real time environments
8240 /// to store the results of the last maxEntries events.
8241 /// #### NOTE 2:
8242 /// Calling SetCircular with maxEntries <= 0 is necessary before
8243 /// merging circular Trees that have been saved on files.
8244 /// #### NOTE 3:
8245 /// SetCircular with maxEntries <= 0 is automatically called
8246 /// by TChain::Merge
8247 /// #### NOTE 4:
8248 /// A circular Tree can still be saved in a file. When read back,
8249 /// it is still a circular Tree and can be filled again.
8250 
8251 void TTree::SetCircular(Long64_t maxEntries)
8253  if (maxEntries <= 0) {
8254  // Disable circularity.
8255  fMaxEntries = 1000000000;
8256  fMaxEntries *= 1000;
8258  //in case the Tree was originally created in gROOT, the branch
8259  //compression level was set to -1. If the Tree is now associated to
8260  //a file, reset the compression level to the file compression level
8261  if (fDirectory) {
8262  TFile* bfile = fDirectory->GetFile();
8263  Int_t compress = 1;
8264  if (bfile) {
8265  compress = bfile->GetCompressionSettings();
8266  }
8268  for (Int_t i = 0; i < nb; i++) {
8269  TBranch* branch = (TBranch*) fBranches.UncheckedAt(i);
8270  branch->SetCompressionSettings(compress);
8271  }
8272  }
8273  } else {
8274  // Enable circularity.
8275  fMaxEntries = maxEntries;
8276  SetBit(kCircular);
8277  }
8278 }
8279 
8280 ////////////////////////////////////////////////////////////////////////////////
8281 /// Set the debug level and the debug range.
8282 ///
8283 /// For entries in the debug range, the functions TBranchElement::Fill
8284 /// and TBranchElement::GetEntry will print the number of bytes filled
8285 /// or read for each branch.
8286 
8287 void TTree::SetDebug(Int_t level, Long64_t min, Long64_t max)
8289  fDebug = level;
8290  fDebugMin = min;
8291  fDebugMax = max;
8292 }
8293 
8294 ////////////////////////////////////////////////////////////////////////////////
8295 /// Update the default value for the branch's fEntryOffsetLen.
8296 /// If updateExisting is true, also update all the existing branches.
8297 /// If newdefault is less than 10, the new default value will be 10.
8298 
8299 void TTree::SetDefaultEntryOffsetLen(Int_t newdefault, Bool_t updateExisting)
8301  if (newdefault < 10) {
8302  newdefault = 10;
8303  }
8304  fDefaultEntryOffsetLen = newdefault;
8305  if (updateExisting) {
8306  TIter next( GetListOfBranches() );
8307  TBranch *b;
8308  while ( ( b = (TBranch*)next() ) ) {
8309  b->SetEntryOffsetLen( newdefault, kTRUE );
8310  }
8311  if (fBranchRef) {
8312  fBranchRef->SetEntryOffsetLen( newdefault, kTRUE );
8313  }
8314  }
8315 }
8316 
8317 ////////////////////////////////////////////////////////////////////////////////
8318 /// Change the tree's directory.
8319 ///
8320 /// Remove reference to this tree from current directory and
8321 /// add reference to new directory dir. The dir parameter can
8322 /// be 0 in which case the tree does not belong to any directory.
8323 ///
8324 
8327  if (fDirectory == dir) {
8328  return;
8329  }
8330  if (fDirectory) {
8331  fDirectory->Remove(this);
8332 
8333  // Delete or move the file cache if it points to this Tree
8334  TFile *file = fDirectory->GetFile();
8335  MoveReadCache(file,dir);
8336  }
8337  fDirectory = dir;
8338  if (fDirectory) {
8339  fDirectory->Append(this);
8340  }
8341  TFile* file = 0;
8342  if (fDirectory) {
8343  file = fDirectory->GetFile();
8344  }
8345  if (fBranchRef) {
8346  fBranchRef->SetFile(file);
8347  }
8348  TBranch* b = 0;
8349  TIter next(GetListOfBranches());
8350  while((b = (TBranch*) next())) {
8351  b->SetFile(file);
8352  }
8353 }
8354 
8355 ////////////////////////////////////////////////////////////////////////////////
8356 /// Change number of entries in the tree.
8357 ///
8358 /// If n >= 0, set number of entries in the tree = n.
8359 ///
8360 /// If n < 0, set number of entries in the tree to match the
8361 /// number of entries in each branch. (default for n is -1)
8362 ///
8363 /// This function should be called only when one fills each branch
8364 /// independently via TBranch::Fill without calling TTree::Fill.
8365 /// Calling TTree::SetEntries() make sense only if the number of entries
8366 /// in each branch is identical, a warning is issued otherwise.
8367 /// The function returns the number of entries.
8368 ///
8369 
8372  // case 1 : force number of entries to n
8373  if (n >= 0) {
8374  fEntries = n;
8375  return n;
8376  }
8377 
8378  // case 2; compute the number of entries from the number of entries in the branches
8379  TBranch* b = 0;
8380  Long64_t nMin = 99999999;
8381  Long64_t nMax = 0;
8382  TIter next(GetListOfBranches());
8383  while((b = (TBranch*) next())){
8384  Long64_t n2 = b->GetEntries();
8385  if (n2 < nMin) {
8386  nMin = n2;
8387  }
8388  if (n2 > nMax) {
8389  nMax = n2;
8390  }
8391  }
8392  if (nMin != nMax) {
8393  Warning("SetEntries", "Tree branches have different numbers of entries, with %lld maximum.", nMax);
8394  }
8395  fEntries = nMax;
8396  return fEntries;
8397 }
8398 
8399 ////////////////////////////////////////////////////////////////////////////////
8400 /// Set an EntryList
8401 
8402 void TTree::SetEntryList(TEntryList *enlist, Option_t * /*opt*/)
8404  if (fEntryList) {
8405  //check if the previous entry list is owned by the tree
8406  if (fEntryList->TestBit(kCanDelete)){
8407  delete fEntryList;
8408  }
8409  }
8410  fEventList = 0;
8411  if (!enlist) {
8412  fEntryList = 0;
8413  return;
8414  }
8415  fEntryList = enlist;
8416  fEntryList->SetTree(this);
8417 
8418 }
8419 
8420 ////////////////////////////////////////////////////////////////////////////////
8421 /// This function transfroms the given TEventList into a TEntryList
8422 /// The new TEntryList is owned by the TTree and gets deleted when the tree
8423 /// is deleted. This TEntryList can be returned by GetEntryList() function.
8424 
8425 void TTree::SetEventList(TEventList *evlist)
8427  fEventList = evlist;
8428  if (fEntryList){
8429  if (fEntryList->TestBit(kCanDelete)) {
8430  TEntryList *tmp = fEntryList;
8431  fEntryList = 0; // Avoid problem with RecursiveRemove.
8432  delete tmp;
8433  } else {
8434  fEntryList = 0;
8435  }
8436  }
8437 
8438  if (!evlist) {
8439  fEntryList = 0;
8440  fEventList = 0;
8441  return;
8442  }
8443 
8444  fEventList = evlist;
8445  char enlistname[100];
8446  snprintf(enlistname,100, "%s_%s", evlist->GetName(), "entrylist");
8447  fEntryList = new TEntryList(enlistname, evlist->GetTitle());
8448  fEntryList->SetDirectory(0); // We own this.
8449  Int_t nsel = evlist->GetN();
8450  fEntryList->SetTree(this);
8451  Long64_t entry;
8452  for (Int_t i=0; i<nsel; i++){
8453  entry = evlist->GetEntry(i);
8454  fEntryList->Enter(entry);
8455  }
8456  fEntryList->SetReapplyCut(evlist->GetReapplyCut());
8457  fEntryList->SetBit(kCanDelete, kTRUE);
8458 }
8459 
8460 ////////////////////////////////////////////////////////////////////////////////
8461 /// Set number of entries to estimate variable limits.
8462 /// If n is -1, the estimate is set to be the current maximum
8463 /// for the tree (i.e. GetEntries() + 1)
8464 /// If n is less than -1, the behavior is undefined.
8465 
8466 void TTree::SetEstimate(Long64_t n /* = 1000000 */)
8468  if (n == 0) {
8469  n = 10000;
8470  } else if (n < 0) {
8471  n = fEntries - n;
8472  }
8473  fEstimate = n;
8474  GetPlayer();
8475  if (fPlayer) {
8476  fPlayer->SetEstimate(n);
8477  }
8478 }
8479 
8480 ////////////////////////////////////////////////////////////////////////////////
8481 /// Set fFileNumber to number.
8482 /// fFileNumber is used by TTree::Fill to set the file name
8483 /// for a new file to be created when the current file exceeds fgTreeMaxSize.
8484 /// (see TTree::ChangeFile)
8485 /// if fFileNumber=10, the new file name will have a suffix "_11",
8486 /// ie, fFileNumber is incremented before setting the file name
8487 
8488 void TTree::SetFileNumber(Int_t number)
8490  if (fFileNumber < 0) {
8491  Warning("SetFileNumber", "file number must be positive. Set to 0");
8492  fFileNumber = 0;
8493  return;
8494  }
8495  fFileNumber = number;
8496 }
8497 
8498 ////////////////////////////////////////////////////////////////////////////////
8499 /// Set all the branches in this TTree to be in decomposed object mode
8500 /// (also known as MakeClass mode).
8501 
8504  fMakeClass = make;
8505 
8507  for (Int_t i = 0; i < nb; ++i) {
8508  TBranch* branch = (TBranch*) fBranches.UncheckedAt(i);
8509  branch->SetMakeClass(make);
8510  }
8511 }
8512 
8513 ////////////////////////////////////////////////////////////////////////////////
8514 /// Set the maximum size in bytes of a Tree file (static function).
8515 /// The default size is 100000000000LL, ie 100 Gigabytes.
8516 ///
8517 /// In TTree::Fill, when the file has a size > fgMaxTreeSize,
8518 /// the function closes the current file and starts writing into
8519 /// a new file with a name of the style "file_1.root" if the original
8520 /// requested file name was "file.root".
8521 
8525 }
8526 
8527 ////////////////////////////////////////////////////////////////////////////////
8528 /// Change the name of this tree.
8529 
8530 void TTree::SetName(const char* name)
8532  if (gPad) {
8533  gPad->Modified();
8534  }
8535  // Trees are named objects in a THashList.
8536  // We must update hashlists if we change the name.
8537  TFile *file = 0;
8538  TTreeCache *pf = 0;
8539  if (fDirectory) {
8540  fDirectory->Remove(this);
8541  if ((file = GetCurrentFile())) {
8542  pf = GetReadCache(file);
8543  file->SetCacheRead(0,this,TFile::kDoNotDisconnect);
8544  }
8545  }
8546  // This changes our hash value.
8547  fName = name;
8548  if (fDirectory) {
8549  fDirectory->Append(this);
8550  if (pf) {
8551  file->SetCacheRead(pf,this,TFile::kDoNotDisconnect);
8552  }
8553  }
8554 }
8555 
8556 ////////////////////////////////////////////////////////////////////////////////
8557 /// Change the name and title of this tree.
8558 
8559 void TTree::SetObject(const char* name, const char* title)
8561  if (gPad) {
8562  gPad->Modified();
8563  }
8564 
8565  // Trees are named objects in a THashList.
8566  // We must update hashlists if we change the name
8567  TFile *file = 0;
8568  TTreeCache *pf = 0;
8569  if (fDirectory) {
8570  fDirectory->Remove(this);
8571  if ((file = GetCurrentFile())) {
8572  pf = GetReadCache(file);
8573  file->SetCacheRead(0,this,TFile::kDoNotDisconnect);
8574  }
8575  }
8576  // This changes our hash value.
8577  fName = name;
8578  fTitle = title;
8579  if (fDirectory) {
8580  fDirectory->Append(this);
8581  if (pf) {
8582  file->SetCacheRead(pf,this,TFile::kDoNotDisconnect);
8583  }
8584  }
8585 }
8586 
8587 ////////////////////////////////////////////////////////////////////////////////
8588 /// Enable or disable parallel unzipping of Tree buffers.
8589 
8590 void TTree::SetParallelUnzip(Bool_t opt, Float_t RelSize)
8594 
8595  if (RelSize > 0) {
8597  }
8598 
8599 }
8600 
8601 ////////////////////////////////////////////////////////////////////////////////
8602 /// Set perf stats
8603 
8606  fPerfStats = perf;
8607 }
8608 
8609 ////////////////////////////////////////////////////////////////////////////////
8610 /// The current TreeIndex is replaced by the new index.
8611 /// Note that this function does not delete the previous index.
8612 /// This gives the possibility to play with more than one index, e.g.,
8613 /// ~~~ {.cpp}
8614 /// TVirtualIndex* oldIndex = tree.GetTreeIndex();
8615 /// tree.SetTreeIndex(newIndex);
8616 /// tree.Draw();
8617 /// tree.SetTreeIndex(oldIndex);
8618 /// tree.Draw(); etc
8619 /// ~~~
8620 
8623  if (fTreeIndex) {
8624  fTreeIndex->SetTree(0);
8625  }
8626  fTreeIndex = index;
8627 }
8628 
8629 ////////////////////////////////////////////////////////////////////////////////
8630 /// Set tree weight.
8631 ///
8632 /// The weight is used by TTree::Draw to automatically weight each
8633 /// selected entry in the resulting histogram.
8634 ///
8635 /// For example the equivalent of:
8636 /// ~~~ {.cpp}
8637 /// T.Draw("x", "w")
8638 /// ~~~
8639 /// is:
8640 /// ~~~ {.cpp}
8641 /// T.SetWeight(w);
8642 /// T.Draw("x");
8643 /// ~~~
8644 /// This function is redefined by TChain::SetWeight. In case of a
8645 /// TChain, an option "global" may be specified to set the same weight
8646 /// for all trees in the TChain instead of the default behaviour
8647 /// using the weights of each tree in the chain (see TChain::SetWeight).
8648 
8651  fWeight = w;
8652 }
8653 
8654 ////////////////////////////////////////////////////////////////////////////////
8655 /// Print values of all active leaves for entry.
8656 ///
8657 /// - if entry==-1, print current entry (default)
8658 /// - if a leaf is an array, a maximum of lenmax elements is printed.
8659 
8660 void TTree::Show(Long64_t entry, Int_t lenmax)
8662  if (entry != -1) {
8663  Int_t ret = LoadTree(entry);
8664  if (ret == -2) {
8665  Error("Show()", "Cannot read entry %lld (entry does not exist)", entry);
8666  return;
8667  } else if (ret == -1) {
8668  Error("Show()", "Cannot read entry %lld (I/O error)", entry);
8669  return;
8670  }
8671  ret = GetEntry(entry);
8672  if (ret == -1) {
8673  Error("Show()", "Cannot read entry %lld (I/O error)", entry);
8674  return;
8675  } else if (ret == 0) {
8676  Error("Show()", "Cannot read entry %lld (no data read)", entry);
8677  return;
8678  }
8679  }
8680  printf("======> EVENT:%lld\n", fReadEntry);
8681  TObjArray* leaves = GetListOfLeaves();
8682  Int_t nleaves = leaves->GetEntriesFast();
8683  Int_t ltype;
8684  for (Int_t i = 0; i < nleaves; i++) {
8685  TLeaf* leaf = (TLeaf*) leaves->UncheckedAt(i);
8686  TBranch* branch = leaf->GetBranch();
8687  if (branch->TestBit(kDoNotProcess)) {
8688  continue;
8689  }
8690  Int_t len = leaf->GetLen();
8691  if (len <= 0) {
8692  continue;
8693  }
8694  len = TMath::Min(len, lenmax);
8695  if (leaf->IsA() == TLeafElement::Class()) {
8696  leaf->PrintValue(lenmax);
8697  continue;
8698  }
8699  if (branch->GetListOfBranches()->GetEntriesFast() > 0) {
8700  continue;
8701  }
8702  ltype = 10;
8703  if (leaf->IsA() == TLeafF::Class()) {
8704  ltype = 5;
8705  }
8706  if (leaf->IsA() == TLeafD::Class()) {
8707  ltype = 5;
8708  }
8709  if (leaf->IsA() == TLeafC::Class()) {
8710  len = 1;
8711  ltype = 5;
8712  };
8713  printf(" %-15s = ", leaf->GetName());
8714  for (Int_t l = 0; l < len; l++) {
8715  leaf->PrintValue(l);
8716  if (l == (len - 1)) {
8717  printf("\n");
8718  continue;
8719  }
8720  printf(", ");
8721  if ((l % ltype) == 0) {
8722  printf("\n ");
8723  }
8724  }
8725  }
8726 }
8727 
8728 ////////////////////////////////////////////////////////////////////////////////
8729 /// Start the TTreeViewer on this tree.
8730 ///
8731 /// - ww is the width of the canvas in pixels
8732 /// - wh is the height of the canvas in pixels
8733 
8734 void TTree::StartViewer()
8736  GetPlayer();
8737  if (fPlayer) {
8738  fPlayer->StartViewer(600, 400);
8739  }
8740 }
8741 
8742 ////////////////////////////////////////////////////////////////////////////////
8743 /// Stop the cache learning phase
8744 ///
8745 /// Returns:
8746 /// - 0 learning phase stopped or not active
8747 /// - -1 on error
8748 
8751  if (!GetTree()) {
8752  if (LoadTree(0)<0) {
8753  Error("StopCacheLearningPhase","Could not load a tree");
8754  return -1;
8755  }
8756  }
8757  if (GetTree()) {
8758  if (GetTree() != this) {
8759  return GetTree()->StopCacheLearningPhase();
8760  }
8761  } else {
8762  Error("StopCacheLearningPhase", "No tree is available. Could not stop cache learning phase");
8763  return -1;
8764  }
8765 
8766  TFile *f = GetCurrentFile();
8767  if (!f) {
8768  Error("StopCacheLearningPhase", "No file is available. Could not stop cache learning phase");
8769  return -1;
8770  }
8771  TTreeCache *tc = GetReadCache(f,kTRUE);
8772  if (!tc) {
8773  Error("StopCacheLearningPhase", "No cache is available. Could not stop learning phase");
8774  return -1;
8775  }
8776  tc->StopLearningPhase();
8777  return 0;
8778 }
8779 
8780 ////////////////////////////////////////////////////////////////////////////////
8781 /// Set the fTree member for all branches and sub branches.
8782 
8783 static void TBranch__SetTree(TTree *tree, TObjArray &branches)
8785  Int_t nb = branches.GetEntriesFast();
8786  for (Int_t i = 0; i < nb; ++i) {
8787  TBranch* br = (TBranch*) branches.UncheckedAt(i);
8788  br->SetTree(tree);
8789 
8790  Int_t nBaskets = br->GetListOfBaskets()->GetEntries();
8791  Int_t writeBasket = br->GetWriteBasket();
8792  for (Int_t j=writeBasket,n=0;j>=0 && n<nBaskets;--j) {
8793  TBasket *bk = (TBasket*)br->GetListOfBaskets()->UncheckedAt(j);
8794  if (bk) {
8795  tree->IncrementTotalBuffers(bk->GetBufferSize());
8796  ++n;
8797  }
8798  }
8799 
8800  TBranch__SetTree(tree,*br->GetListOfBranches());
8801  }
8802 }
8803 
8804 ////////////////////////////////////////////////////////////////////////////////
8805 /// Set the fTree member for all friend elements.
8806 
8807 void TFriendElement__SetTree(TTree *tree, TList *frlist)
8809  if (frlist) {
8810  TObjLink *lnk = frlist->FirstLink();
8811  while (lnk) {
8812  TFriendElement *elem = (TFriendElement*)lnk->GetObject();
8813  elem->fParentTree = tree;
8814  lnk = lnk->Next();
8815  }
8816  }
8817 }
8818 
8819 ////////////////////////////////////////////////////////////////////////////////
8820 /// Stream a class object.
8821 
8822 void TTree::Streamer(TBuffer& b)
8823 {
8824  if (b.IsReading()) {
8825  UInt_t R__s, R__c;
8826  if (fDirectory) {
8827  fDirectory->Remove(this);
8828  //delete the file cache if it points to this Tree
8829  TFile *file = fDirectory->GetFile();
8830  MoveReadCache(file,0);
8831  }
8832  fDirectory = 0;
8835  Version_t R__v = b.ReadVersion(&R__s, &R__c);
8836  if (R__v > 4) {
8837  b.ReadClassBuffer(TTree::Class(), this, R__v, R__s, R__c);
8838 
8839  fBranches.SetOwner(kTRUE); // True needed only for R__v < 19 and most R__v == 19
8840 
8841  if (fBranchRef) fBranchRef->SetTree(this);
8844 
8845  if (fTreeIndex) {
8846  fTreeIndex->SetTree(this);
8847  }
8848  if (fIndex.fN) {
8849  Warning("Streamer", "Old style index in this tree is deleted. Rebuild the index via TTree::BuildIndex");
8850  fIndex.Set(0);
8851  fIndexValues.Set(0);
8852  }
8853  if (fEstimate <= 10000) {
8854  fEstimate = 1000000;
8855  }
8856  if (GetCacheAutoSize() != 0) {
8857  // a cache will be automatically created.
8858  // No need for TTreePlayer::Process to enable the cache
8859  fCacheSize = 0;
8860  } else if (fAutoFlush < 0) {
8861  // If there is no autoflush set, let's keep the cache completely
8862  // disable by default for now.
8864  } else if (fAutoFlush != 0) {
8865  // Estimate the cluster size.
8866  // This will allow TTree::Process to enable the cache.
8867  if (fZipBytes != 0) {
8869  } else if (fTotBytes != 0) {
8871  } else {
8872  fCacheSize = 30000000;
8873  }
8874  if (fCacheSize >= (INT_MAX / 4)) {
8875  fCacheSize = INT_MAX / 4;
8876  } else if (fCacheSize == 0) {
8877  fCacheSize = 30000000;
8878  }
8879  } else {
8880  fCacheSize = 0;
8881  }
8883  return;
8884  }
8885  //====process old versions before automatic schema evolution
8886  Stat_t djunk;
8887  Int_t ijunk;
8888  TNamed::Streamer(b);
8889  TAttLine::Streamer(b);
8890  TAttFill::Streamer(b);
8891  TAttMarker::Streamer(b);
8892  b >> fScanField;
8893  b >> ijunk; fMaxEntryLoop = (Long64_t)ijunk;
8894  b >> ijunk; fMaxVirtualSize = (Long64_t)ijunk;
8895  b >> djunk; fEntries = (Long64_t)djunk;
8896  b >> djunk; fTotBytes = (Long64_t)djunk;
8897  b >> djunk; fZipBytes = (Long64_t)djunk;
8898  b >> ijunk; fAutoSave = (Long64_t)ijunk;
8899  b >> ijunk; fEstimate = (Long64_t)ijunk;
8900  if (fEstimate <= 10000) fEstimate = 1000000;
8901  fBranches.Streamer(b);
8902  if (fBranchRef) fBranchRef->SetTree(this);
8904  fLeaves.Streamer(b);
8906  if (R__v > 1) fIndexValues.Streamer(b);
8907  if (R__v > 2) fIndex.Streamer(b);
8908  if (R__v > 3) {
8909  TList OldInfoList;
8910  OldInfoList.Streamer(b);
8911  OldInfoList.Delete();
8912  }
8913  fNClusterRange = 0;
8914  fDefaultEntryOffsetLen = 1000;
8916  b.CheckByteCount(R__s, R__c, TTree::IsA());
8917  //====end of old versions
8918  } else {
8919  if (fBranchRef) {
8920  fBranchRef->Clear();
8921  }
8922  TRefTable *table = TRefTable::GetRefTable();
8923  if (table) TRefTable::SetRefTable(0);
8924 
8925  b.WriteClassBuffer(TTree::Class(), this);
8926 
8927  if (table) TRefTable::SetRefTable(table);
8928  }
8929 }
8930 
8931 ////////////////////////////////////////////////////////////////////////////////
8932 /// Unbinned fit of one or more variable(s) from a tree.
8933 ///
8934 /// funcname is a TF1 function.
8935 ///
8936 /// See TTree::Draw for explanations of the other parameters.
8937 ///
8938 /// Fit the variable varexp using the function funcname using the
8939 /// selection cuts given by selection.
8940 ///
8941 /// The list of fit options is given in parameter option.
8942 ///
8943 /// - option = "Q" Quiet mode (minimum printing)
8944 /// - option = "V" Verbose mode (default is between Q and V)
8945 /// - option = "E" Perform better Errors estimation using Minos technique
8946 /// - option = "M" More. Improve fit results
8947 ///
8948 /// You can specify boundary limits for some or all parameters via
8949 /// ~~~ {.cpp}
8950 /// func->SetParLimits(p_number, parmin, parmax);
8951 /// ~~~
8952 /// if parmin>=parmax, the parameter is fixed
8953 ///
8954 /// Note that you are not forced to fix the limits for all parameters.
8955 /// For example, if you fit a function with 6 parameters, you can do:
8956 /// ~~~ {.cpp}
8957 /// func->SetParameters(0,3.1,1.e-6,0.1,-8,100);
8958 /// func->SetParLimits(4,-10,-4);
8959 /// func->SetParLimits(5, 1,1);
8960 /// ~~~
8961 /// With this setup:
8962 ///
8963 /// - Parameters 0->3 can vary freely
8964 /// - Parameter 4 has boundaries [-10,-4] with initial value -8
8965 /// - Parameter 5 is fixed to 100.
8966 ///
8967 /// For the fit to be meaningful, the function must be self-normalized.
8968 ///
8969 /// i.e. It must have the same integral regardless of the parameter
8970 /// settings. Otherwise the fit will effectively just maximize the
8971 /// area.
8972 ///
8973 /// It is mandatory to have a normalization variable
8974 /// which is fixed for the fit. e.g.
8975 /// ~~~ {.cpp}
8976 /// TF1* f1 = new TF1("f1", "gaus(0)/sqrt(2*3.14159)/[2]", 0, 5);
8977 /// f1->SetParameters(1, 3.1, 0.01);
8978 /// f1->SetParLimits(0, 1, 1); // fix the normalization parameter to 1
8979 /// data->UnbinnedFit("f1", "jpsimass", "jpsipt>3.0");
8980 /// ~~~
8981 /// 1, 2 and 3 Dimensional fits are supported. See also TTree::Fit
8982 ///
8983 /// Return status:
8984 ///
8985 /// - The function return the status of the fit in the following form
8986 /// fitResult = migradResult + 10*minosResult + 100*hesseResult + 1000*improveResult
8987 /// - The fitResult is 0 is the fit is OK.
8988 /// - The fitResult is negative in case of an error not connected with the fit.
8989 /// - The number of entries used in the fit can be obtained via mytree.GetSelectedRows();
8990 /// - If the number of selected entries is null the function returns -1
8991 
8992 Int_t TTree::UnbinnedFit(const char* funcname, const char* varexp, const char* selection, Option_t* option, Long64_t nentries, Long64_t firstentry)
8994  GetPlayer();
8995  if (fPlayer) {
8996  return fPlayer->UnbinnedFit(funcname, varexp, selection, option, nentries, firstentry);
8997  }
8998  return -1;
8999 }
9000 
9001 ////////////////////////////////////////////////////////////////////////////////
9002 /// Replace current attributes by current style.
9003 
9006  if (gStyle->IsReading()) {
9015  } else {
9024  }
9025 }
9026 
9027 ////////////////////////////////////////////////////////////////////////////////
9028 /// Write this object to the current directory. For more see TObject::Write
9029 /// Write calls TTree::FlushBaskets before writing the tree.
9030 
9031 Int_t TTree::Write(const char *name, Int_t option, Int_t bufsize) const
9033  FlushBaskets();
9034  return TObject::Write(name, option, bufsize);
9035 }
9036 
9037 ////////////////////////////////////////////////////////////////////////////////
9038 /// Write this object to the current directory. For more see TObject::Write
9039 /// If option & kFlushBasket, call FlushBasket before writing the tree.
9040 
9041 Int_t TTree::Write(const char *name, Int_t option, Int_t bufsize)
9043  return ((const TTree*)this)->Write(name, option, bufsize);
9044 }
9045 
9046 ////////////////////////////////////////////////////////////////////////////////
9047 /// \class TTreeFriendLeafIter
9048 ///
9049 /// Iterator on all the leaves in a TTree and its friend
9050 
9052 
9053 ////////////////////////////////////////////////////////////////////////////////
9054 /// Create a new iterator. By default the iteration direction
9055 /// is kIterForward. To go backward use kIterBackward.
9056 
9058 : fTree(const_cast<TTree*>(tree))
9059 , fLeafIter(0)
9060 , fTreeIter(0)
9061 , fDirection(dir)
9062 {
9063 }
9064 
9065 ////////////////////////////////////////////////////////////////////////////////
9066 /// Copy constructor. Does NOT copy the 'cursor' location!
9067 
9069 : TIterator(iter)
9070 , fTree(iter.fTree)
9071 , fLeafIter(0)
9072 , fTreeIter(0)
9073 , fDirection(iter.fDirection)
9074 {
9075 }
9076 
9077 ////////////////////////////////////////////////////////////////////////////////
9078 /// Overridden assignment operator. Does NOT copy the 'cursor' location!
9079 
9082  if (this != &rhs && rhs.IsA() == TTreeFriendLeafIter::Class()) {
9083  const TTreeFriendLeafIter &rhs1 = (const TTreeFriendLeafIter &)rhs;
9084  fDirection = rhs1.fDirection;
9085  }
9086  return *this;
9087 }
9088 
9089 ////////////////////////////////////////////////////////////////////////////////
9090 /// Overridden assignment operator. Does NOT copy the 'cursor' location!
9091 
9094  if (this != &rhs) {
9095  fDirection = rhs.fDirection;
9096  }
9097  return *this;
9098 }
9099 
9100 ////////////////////////////////////////////////////////////////////////////////
9101 /// Go the next friend element
9102 
9105  if (!fTree) return 0;
9106 
9107  TObject * next;
9108  TTree * nextTree;
9109 
9110  if (!fLeafIter) {
9111  TObjArray *list = fTree->GetListOfLeaves();
9112  if (!list) return 0; // Can happen with an empty chain.
9113  fLeafIter = list->MakeIterator(fDirection);
9114  if (!fLeafIter) return 0;
9115  }
9116 
9117  next = fLeafIter->Next();
9118  if (!next) {
9119  if (!fTreeIter) {
9120  TCollection * list = fTree->GetListOfFriends();
9121  if (!list) return next;
9122  fTreeIter = list->MakeIterator(fDirection);
9123  if (!fTreeIter) return 0;
9124  }
9125  TFriendElement * nextFriend = (TFriendElement*) fTreeIter->Next();
9126  ///nextTree = (TTree*)fTreeIter->Next();
9127  if (nextFriend) {
9128  nextTree = const_cast<TTree*>(nextFriend->GetTree());
9129  if (!nextTree) return Next();
9130  SafeDelete(fLeafIter);
9131  fLeafIter = nextTree->GetListOfLeaves()->MakeIterator(fDirection);
9132  if (!fLeafIter) return 0;
9133  next = fLeafIter->Next();
9134  }
9135  }
9136  return next;
9137 }
9138 
9139 ////////////////////////////////////////////////////////////////////////////////
9140 /// Returns the object option stored in the list.
9141 
9144  if (fLeafIter) return fLeafIter->GetOption();
9145  return "";
9146 }
A zero length substring is legal.
Definition: TString.h:83
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:37
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:47
virtual Bool_t GetReapplyCut() const
Definition: TEventList.h:59
virtual void UpdateAddress()
Definition: TBranch.h:219
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:4558
virtual const char * GetName() const
Returns name of object.
Definition: TNamed.h:51
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:830
Double_t fWeight
Tree weight (see TTree::SetWeight)
Definition: TTree.h:106
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:1266
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:37
virtual void SetLineWidth(Width_t lwidth)
Set the line width.
Definition: TAttLine.h:49
Bool_t IsReading() const
Definition: TBuffer.h:83
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:5873
A TFolder object is a collection of objects and folders.
Definition: TFolder.h:32
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:416
Bool_t CanSplit() const
Return true if the data member of this TClass can be saved separately.
Definition: TClass.cxx:2240
TList * GetListOfBases()
Return list containing the TBaseClass(es) of a class.
Definition: TClass.cxx:3460
virtual TTree * CopyTree(const char *selection, Option_t *option="", Long64_t nentries=kMaxEntries, Long64_t firstentry=0)=0
ESTLType
Definition: ESTLType.h:28
TStreamerInfo * BuildStreamerInfo(TClass *cl, void *pointer=0, Bool_t canOptimize=kTRUE)
Build StreamerInfo for class cl.
Definition: TTree.cxx:2552
An array of TObjects.
Definition: TObjArray.h:39
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:128
Principal Components Analysis (PCA)
Definition: TPrincipal.h:28
virtual TDirectory * GetDirectory() const
Definition: TEntryList.h:76
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:192
virtual TList * GetListOfKeys() const
Definition: TDirectory.h:158
virtual void Delete(Option_t *option="")
Remove all objects from the list AND delete all heap based objects.
Definition: TList.cxx:405
virtual void UpdateFile()
Refresh the value of fDirectory (i.e.
Definition: TBranch.cxx:2664
virtual void Info(const char *method, const char *msgfmt,...) const
Issue info message.
Definition: TObject.cxx:899
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:51
virtual void SetAddress(void *add)
Set address of this branch.
Definition: TBranch.cxx:2061
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 Using the information in the e...
Definition: TTree.cxx:6575
Bool_t MemoryFull(Int_t nbytes)
Check if adding nbytes to memory we are still below MaxVirtualsize.
Definition: TTree.cxx:6382
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:1472
virtual Int_t MakeCode(const char *filename=0)
Generate a skeleton function for this tree.
Definition: TTree.cxx:6185
long long Long64_t
Definition: RtypesCore.h:69
Abstract interface for Tree Index.
Definition: TVirtualIndex.h:31
virtual Int_t GetBasketSize() const
Definition: TBranch.h:152
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:7082
This namespace contains pre-defined functions to be used in conjuction with TExecutor::Map and TExecu...
Definition: StringConv.hxx:21
virtual Int_t StopCacheLearningPhase()
Stop the cache learning phase.
Definition: TTree.cxx:8750
virtual void SetBranchStatus(const char *bname, Bool_t status=1, UInt_t *found=0)
Set branch status to Process or DoNotProcess.
Definition: TTree.cxx:7906
virtual void IncrementTotalBuffers(Int_t nbytes)
Definition: TTree.h:472
short Version_t
Definition: RtypesCore.h:61
virtual void Delete(Option_t *option="")
Delete this tree from memory or/and disk.
Definition: TTree.cxx:3563
Bool_t EqualTo(const char *cs, ECaseCompare cmp=kExact) const
Definition: TString.h:576
A Branch for the case of an object.
Definition: TBranchObject.h:28
const char * GetFullTypeName() const
Get full type description of data member, e,g.: "class TDirectory*".
TObjArray * GetListOfBaskets()
Definition: TBranch.h:177
TLine * line
static Int_t fgBranchStyle
Old/New branch style.
Definition: TTree.h:157
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:5989
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:1381
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:6742
static Long64_t GetMaxTreeSize()
Static function which returns the tree file size limit in bytes.
Definition: TTree.cxx:5820
virtual void SetParallelUnzip(Bool_t opt=kTRUE, Float_t RelSize=-1)
Enable or disable parallel unzipping of Tree buffers.
Definition: TTree.cxx:8591
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:6645
virtual Int_t MakeCode(const char *filename)=0
Provides the interface for the PROOF internal performance measurement and event tracing.
return c
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:6551
TTree()
Default constructor and I/O constructor.
Definition: TTree.cxx:650
virtual TTree * GetFriend(const char *) const
Return a pointer to the TTree friend whose name or alias is &#39;friendname.
Definition: TTree.cxx:5539
void GetObject(const char *namecycle, T *&ptr)
Definition: TDirectory.h:147
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:33
virtual Long64_t GetEntriesFast() const
Definition: TTree.h:395
const char * Size
Definition: TXMLSetup.cxx:56
TBuffer * fTransientBuffer
! Pointer to the current transient buffer.
Definition: TTree.h:149
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:6730
virtual void SetCacheRead(TFileCacheRead *cache, TObject *tree=0, ECacheAction action=kDisconnect)
Set a pointer to the read cache.
Definition: TFile.cxx:2197
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:1647
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:4786
TString & ReplaceAll(const TString &s1, const TString &s2)
Definition: TString.h:635
R__EXTERN TStyle * gStyle
Definition: TStyle.h:418
TList * fFriends
pointer to list of friend elements
Definition: TTree.h:142
void SetHistLineWidth(Width_t width=1)
Definition: TStyle.h:373
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:6711
Bool_t TestBit(UInt_t f) const
Definition: TObject.h:157
virtual Int_t Fill()
Fill all branches.
Definition: TTree.cxx:4375
Int_t GetMakeClass() const
Definition: TTree.h:424
virtual TEntryList * GetEntryList()
Returns the entry list, set to this tree.
Definition: TTree.cxx:5419
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:641
static void SetBranchStyle(Int_t style=1)
Set the current branch style.
Definition: TTree.cxx:8032
A specialized TFileCacheRead object for a TTree.
Definition: TTreeCache.h:34
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:5745
TTree * fTree
Definition: TTree.h:190
const std::type_info * GetTypeInfo() const
Definition: TClass.h:451
static Int_t SetParallelUnzip(TTreeCacheUnzip::EParUnzipMode option=TTreeCacheUnzip::kEnable)
Static function that (de)activates multithreading unzipping.
static char DataTypeToChar(EDataType datatype)
Definition: TTree.cxx:427
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:4368
virtual void PrintValue(Int_t i=0) const
Definition: TLeaf.h:123
A ROOT file is a suite of consecutive data records (TKey instances) with a well defined format...
Definition: TFile.h:50
const char * GetTypeName() const
Get type of data member, e,g.: "class TDirectory*" -> "TDirectory".
virtual Int_t GetEntries() const
Definition: TCollection.h:92
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:5655
virtual TList * GetListOfFriends() const
Definition: TTree.h:419
virtual Long64_t GetAutoFlush() const
Definition: TTree.h:378
Buffer base class used for serializing objects.
Definition: TBuffer.h:42
Regular expression class.
Definition: TRegexp.h:35
TDirectory * fDirectory
! Pointer to directory holding this tree
Definition: TTree.h:133
constexpr Float_t kNEntriesResortInv
Definition: TTree.cxx:416
Int_t fMakeClass
! not zero when processing code generated by MakeClass
Definition: TTree.h:130
#define R__ASSERT(e)
Definition: TError.h:98
virtual TBasket * CreateBasket(TBranch *)
Create a basket for this tree and given branch.
Definition: TTree.cxx:3547
virtual Int_t CheckByteCount(UInt_t startpos, UInt_t bcnt, const TClass *clss)=0
#define gROOT
Definition: TROOT.h:364
TList * GetListOfDataMembers(Bool_t load=kTRUE)
Return list containing the TDataMembers of a class.
Definition: TClass.cxx:3570
Ssiz_t Index(const char *pat, Ssiz_t i=0, ECaseCompare cmp=kExact) const
Definition: TString.h:582
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:7717
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:5211
virtual Int_t ReadKeys(Bool_t=kTRUE)
Definition: TDirectory.h:182
virtual Int_t GetOffset() const
Definition: TLeaf.h:79
Basic string class.
Definition: TString.h:137
TVirtualCollectionProxy * GetCollectionProxy() const
Return the proxy describing the collection (if any).
Definition: TClass.cxx:2822
virtual void SetAddress(void *addobj)
Point this branch at an object.
virtual Int_t MakeProxy(const char *classname, const char *macrofilename=0, const char *cutfilename=0, const char *option=0, Int_t maxUnrolling=3)
Generate a skeleton analysis class for this Tree using TBranchProxy.
Definition: TTree.cxx:6313
virtual Long64_t GetEntryNumberWithBestIndex(Long64_t major, Long64_t minor) const =0
Short_t Min(Short_t a, Short_t b)
Definition: TMathBase.h:170
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:1089
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:4510
int Int_t
Definition: RtypesCore.h:41
bool Bool_t
Definition: RtypesCore.h:59
TArc * a
Definition: textangle.C:12
const Bool_t kFALSE
Definition: Rtypes.h:92
virtual void Browse(TBrowser *)
Browse content of the TTree.
Definition: TTree.cxx:2512
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:44
virtual void StopLearningPhase()
This is the counterpart of StartLearningPhase() and can be used to stop the learning phase...
Int_t fScanField
Number of runs before prompting in Scan.
Definition: TTree.h:108
virtual TTree * CloneTree(Long64_t nentries=-1, Option_t *option="")
Create a clone of this tree and copy nentries.
Definition: TTree.cxx:3004
TObject * At(Int_t idx) const
Definition: TObjArray.h:167
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:3535
const char * Class
Definition: TXMLSetup.cxx:64
virtual void KeepCircular()
Keep a maximum of fMaxEntries in memory.
Definition: TTree.cxx:5953
TArrayD fIndexValues
Sorted index values.
Definition: TTree.h:139
void SetAutoCreated(Bool_t val)
Definition: TTreeCache.h:101
virtual EDataType GetType() const =0
constexpr Int_t kNEntriesResort
Definition: TTree.cxx:415
virtual Long64_t GetEntries(const char *)=0
Long64_t fMaxEntryLoop
Maximum number of entries to process.
Definition: TTree.h:114
TVirtualTreePlayer * GetPlayer()
Load the TTreePlayer (if not already done).
Definition: TTree.cxx:5859
virtual void SetMaxVirtualSize(Long64_t size=0)
Definition: TTree.h:554
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:6985
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:2654
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:32
virtual Width_t GetLineWidth() const
Return the line width.
Definition: TAttLine.h:41
void Reset()
Definition: TCollection.h:161
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:739
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:497
virtual void Refresh()
Refresh contents of this tree and its branches from the current status on disk.
Definition: TTree.cxx:7379
Width_t GetHistLineWidth() const
Definition: TStyle.h:237
if object in a list can be deleted
Definition: TObject.h:56
virtual void SetFileNumber(Int_t number=0)
Set fFileNumber to number.
Definition: TTree.cxx:8489
virtual Double_t GetMinimum(const char *columname)
Return minimum of column with name columname.
Definition: TTree.cxx:5830
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:3635
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:3907
Int_t Length() const
Definition: TBuffer.h:96
virtual void SetTree(TTree *tree)
Definition: TBranch.h:217
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
virtual Style_t GetMarkerStyle() const
Return the marker style.
Definition: TAttMarker.h:37
virtual void StartViewer()
Start the TTreeViewer on this tree.
Definition: TTree.cxx:8735
virtual Long64_t Merge(TCollection *list, Option_t *option="")
Merge the trees in the TList into this tree.
Definition: TTree.cxx:6439
Marker Attributes class.
Definition: TAttMarker.h:24
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:40
virtual Int_t GetEntryWithIndex(Int_t major, Int_t minor=0)
Read entry corresponding to major and minor number.
Definition: TTree.cxx:5492
TList * fAliases
List of aliases for expressions based on the tree branches.
Definition: TTree.h:136
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:1629
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:4800
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:507
virtual Long64_t GetCacheSize() const
Definition: TTree.h:384
Bool_t IsBasic() const
Return true if data member is a basic type, e.g. char, int, long...
virtual TObjArray * GetListOfBranches()
Definition: TTree.h:417
Helper class to iterate over cluster of baskets.
Definition: TTree.h:256
TVirtualTreePlayer * fPlayer
! Pointer to current Tree player
Definition: TTree.h:145
virtual const char * ClassName() const
Returns name of class to which the object belongs.
Definition: TObject.cxx:188
Fill Area Attributes class.
Definition: TAttFill.h:24
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:5914
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:7632
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:2335
Bool_t IsAutoCreated() const
Definition: TTreeCache.h:89
virtual Long64_t CopyEntries(TTree *tree, Long64_t nentries=-1, Option_t *option="")
Copy nentries from given tree to this tree.
Definition: TTree.cxx:3366
virtual Int_t SetBranchAddress(const char *bname, void *add, TBranch **ptr=0)
Change branch address, dealing with clone trees properly.
Definition: TTree.cxx:7760
void SetHistFillColor(Color_t color=1)
Definition: TStyle.h:369
Int_t fNfill
! Local for EntryLoop
Definition: TTree.h:126
virtual Double_t GetValue(Int_t i=0) const
Definition: TLeaf.h:122
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:8560
virtual Bool_t IsWritable() const
Definition: TDirectory.h:171
The TNamed class is the base class for all named ROOT classes.
Definition: TNamed.h:33
virtual Long64_t GetEntryNumberWithBestIndex(Long64_t major, Long64_t minor=0) const
Return entry number corresponding to major and minor number.
Definition: TTree.cxx:5455
virtual Bool_t Notify()
This method must be overridden to handle object notification.
Definition: TObject.cxx:551
virtual Long64_t GetReadEntry() const
Definition: TTree.h:436
virtual const char * GetAlias(const char *aliasName) const
Returns the expanded value of the alias. Search in the friends if any.
Definition: TTree.cxx:4828
virtual TLeaf * GetLeaf(const char *name) const
Return pointer to the 1st Leaf named name in thisBranch.
Definition: TBranch.cxx:1478
virtual Long64_t LoadTree(Long64_t entry)
Set current entry.
Definition: TTree.cxx:6010
Bool_t fCacheUserSet
! true if the cache setting was explicitly given by user
Definition: TTree.h:151
virtual void SetTreeIndex(TVirtualIndex *index)
The current TreeIndex is replaced by the new index.
Definition: TTree.cxx:8622
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:112
static Int_t GetBranchStyle()
Static function returning the current branch style.
Definition: TTree.cxx:4980
virtual Int_t BuildIndex(const char *majorname, const char *minorname="0")
Build a Tree Index (default is TTreeIndex).
Definition: TTree.cxx:2537
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:8993
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:2306
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:1885
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:5557
virtual void Show(Long64_t entry=-1, Int_t lenmax=20)
Print values of all active leaves for entry.
Definition: TTree.cxx:8661
virtual TBranch * FindBranch(const char *name)
Find the immediate sub-branch with passed name.
Definition: TBranch.cxx:907
TBranchRef * fBranchRef
Branch supporting the TRefTable (if any)
Definition: TTree.h:147
virtual Int_t MakeClass(const char *classname=0, Option_t *option="")
Generate a skeleton analysis class for this tree.
Definition: TTree.cxx:6152
virtual const char * Getenv(const char *env)
Get environment variable.
Definition: TSystem.cxx:1628
virtual TClusterIterator GetClusterIterator(Long64_t firstentry)
Return an iterator over the cluster of baskets starting at firstentry.
Definition: TTree.cxx:5042
virtual Int_t GetN() const
Definition: TEventList.h:58
virtual void SetMarkerColor(Color_t mcolor=1)
Set the marker color.
Definition: TAttMarker.h:43
Style_t GetHistFillStyle() const
Definition: TStyle.h:235
const Int_t kDoNotProcess
Definition: TBranch.h:52
UInt_t fFriendLockStatus
! Record which method is locking the friend recursion
Definition: TTree.h:148
virtual void Append(TObject *obj, Bool_t replace=kFALSE)
Append object to this directory.
Long_t GetThisOffset() const
Definition: TRealData.h:59
const int maxsize
virtual Int_t MakeClass(const char *classname, const char *option)=0
Int_t fTimerInterval
Timer interval in milliseconds.
Definition: TTree.h:107
virtual Size_t GetMarkerSize() const
Return the marker size.
Definition: TAttMarker.h:38
virtual TFriendElement * AddFriend(const char *treename, const char *filename="")
Add a TFriendElement to the list of friends.
Definition: TTree.cxx:1185
TDataType * GetDataType() const
Definition: TDataMember.h:74
virtual Long64_t Scan(const char *varexp="", const char *selection="", Option_t *option="", Long64_t nentries=kMaxEntries, Long64_t firstentry=0)
Loop over tree entries and print entries passing selection.
Definition: TTree.cxx:7535
Long64_t fFlushedBytes
Number of auto-flushed bytes.
Definition: TTree.h:105
virtual Int_t GetLenType() const
Definition: TLeaf.h:75
TObjArray * GetListOfBranches()
Definition: TBranch.h:178
UInt_t fNEntriesSinceSorting
! Number of entries processed since the last re-sorting of branches
Definition: TTree.h:153
Ssiz_t First(char c) const
Find first occurrence of a character c.
Definition: TString.cxx:467
Specialization of TTreeCache for parallel Unzipping.
virtual TList * GetList() const
Definition: TDirectory.h:157
Book space in a file, create I/O buffers, to fill them, (un)compress them.
Definition: TKey.h:30
XFontStruct * id
Definition: TGX11.cxx:108
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:5791
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:7418
virtual void SetAddress(void *add=0)
Definition: TLeaf.h:124
TCollection * GetListOfFolders() const
Definition: TFolder.h:57
virtual TList * GetUserInfo()
Return a pointer to the list containing user objects associated to this tree.
Definition: TTree.cxx:5898
virtual void SetCacheLearnEntries(Int_t n=10)
Interface to TTreeCache to set the number of entries for the learning phase.
Definition: TTree.cxx:8225
A branch containing and managing a TRefTable for TRef autoloading.
Definition: TBranchRef.h:33
Long64_t fZipBytes
Total number of bytes in all branches after compression.
Definition: TTree.h:103
virtual TFile * GetFile() const
Definition: TDirectory.h:155
Long64_t fDebugMax
! Last entry number to debug
Definition: TTree.h:129
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:1391
virtual TTree * GetTree() const
Definition: TTree.h:444
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:8426
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:446
void UseCurrentStyle()
Replace current attributes by current style.
Definition: TTree.cxx:9005
A specialized string object used for TTree selections.
Definition: TCut.h:27
A doubly linked list.
Definition: TList.h:47
virtual void ResetAfterMerge(TFileMergeInfo *)
Reset a Branch.
Definition: TBranch.cxx:1977
virtual TBranch * GetBranch(const char *name)
Return pointer to the branch with the given name in this tree or its friends.
Definition: TTree.cxx:4869
Bool_t fCacheDoAutoInit
! true if cache auto creation or resize check is needed
Definition: TTree.h:150
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:70
virtual Int_t Fill()
Loop on all leaves of this branch to fill Basket buffer.
Definition: TBranch.cxx:737
TObjArray fLeaves
Direct pointers to individual branch leaves.
Definition: TTree.h:135
Long64_t * fClusterRangeEnd
[fNClusterRange] Last entry of a cluster range.
Definition: TTree.h:119
virtual void SetLineColor(Color_t lcolor)
Set the line color.
Definition: TAttLine.h:46
void BuildRealData(void *pointer=0, Bool_t isTransient=kFALSE)
Build a full list of persistent data members.
Definition: TClass.cxx:1951
Using a TBrowser one can browse all ROOT objects.
Definition: TBrowser.h:41
Int_t fNClusterRange
Number of Cluster range in addition to the one defined by &#39;AutoFlush&#39;.
Definition: TTree.h:111
virtual Long64_t GetEntryNumber(Long64_t entry) const
Return entry number corresponding to entry.
Definition: TTree.cxx:5430
Int_t fN
Definition: TArray.h:40
TEntryList * fEntryList
! Pointer to event selection list (if one)
Definition: TTree.h:138
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:379
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:169
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:9042
virtual void SetEstimate(Long64_t nentries=1000000)
Set number of entries to estimate variable limits.
Definition: TTree.cxx:8467
virtual void SetOffset(Int_t offset=0)
Definition: TBranch.h:215
virtual TObject * First() const
Return the first object in the list. Returns 0 when list is empty.
Definition: TList.cxx:557
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:371
void SetCompressionSettings(Int_t settings=1)
Set compression settings.
Definition: TBranch.cxx:2184
R__EXTERN TSystem * gSystem
Definition: TSystem.h:549
Long64_t fChainOffset
! Offset of 1st entry of this Tree in a TChain
Definition: TTree.h:122
~TFriendLock()
Restore the state of tree the same as before we set the lock.
Definition: TTree.cxx:508
Long64_t * fClusterSize
[fNClusterRange] Number of entries in each cluster for a given range.
Definition: TTree.h:120
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:42
Basic data type descriptor (datatype information is obtained from CINT).
Definition: TDataType.h:46
void TFriendElement__SetTree(TTree *tree, TList *frlist)
Set the fTree member for all friend elements.
Definition: TTree.cxx:8808
virtual Long64_t GetEntryNumberWithIndex(Long64_t major, Long64_t minor=0) const
Return entry number corresponding to major and minor number.
Definition: TTree.cxx:5475
TVirtualPerfStats * fPerfStats
! pointer to the current perf stats object
Definition: TTree.h:143
TClass * GetActualClass(const void *object) const
Return a pointer the the real class of the object.
Definition: TClass.cxx:2536
virtual TIterator * MakeIterator(Bool_t dir=kIterForward) const =0
TTree * GetTree() const
Definition: TTreeCache.h:88
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:496
virtual Int_t ReadTObject(TObject *, const char *)
Definition: TDirectory.h:183
virtual TObject * Remove(TObject *obj)
Remove object from the list.
Definition: TList.cxx:675
Long64_t fReadEntry
! Number of the entry being processed
Definition: TTree.h:123
virtual TVirtualIndex * GetTreeIndex() const
Definition: TTree.h:445
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:488
Int_t GetWriteBasket() const
Definition: TBranch.h:171
virtual ~TTree()
Destructor.
Definition: TTree.cxx:829
TDataMember * GetDataMember() const
Definition: TRealData.h:57
Collection abstract base class.
Definition: TCollection.h:48
void Destructor(void *obj, Bool_t dtorOnly=kFALSE)
Explicitly call destructor for object.
Definition: TClass.cxx:5071
TList * fUserInfo
pointer to a list of user objects associated to this Tree
Definition: TTree.h:144
TObjArray fBranches
List of Branches.
Definition: TTree.h:134
void Form(const char *fmt,...)
Formats a string using a printf style format descriptor.
Definition: TString.cxx:2322
unsigned int UInt_t
Definition: RtypesCore.h:42
TMarker * m
Definition: textangle.C:8
Int_t GetEntriesFast() const
Definition: TObjArray.h:66
virtual void Error(const char *method, const char *msgfmt,...) const
Issue error message.
Definition: TObject.cxx:925
TFile * GetCurrentFile() const
Return pointer to the current file.
Definition: TTree.cxx:5053
virtual Long64_t GetN() const =0
static void SetMaxTreeSize(Long64_t maxsize=1900000000)
Set the maximum size in bytes of a Tree file (static function).
Definition: TTree.cxx:8523
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:655
Ssiz_t Length() const
Definition: TString.h:390
virtual void MakeFree(Long64_t first, Long64_t last)
Mark unused bytes on the file.
Definition: TFile.cxx:1394
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:71
Manages buffers for branches of a Tree.
Definition: TBasket.h:38
virtual void * GetValuePointer() const
Definition: TLeaf.h:80
TSubString Strip(EStripType s=kTrailing, char c=' ') const
Return a substring of self stripped at beginning and/or end.
Definition: TString.cxx:1070
Int_t GetMaxBaskets() const
Definition: TBranch.h:180
A TEventList object is a list of selected events (entries) in a TTree.
Definition: TEventList.h:33
TLine * l
Definition: textangle.C:4
virtual TLeaf * FindLeaf(const char *name)
Find leaf..
Definition: TTree.cxx:4630
The TRealData class manages the effective list of all data members for a given class.
Definition: TRealData.h:34
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:1217
Bool_t CanIgnoreTObjectStreamer()
Definition: TClass.h:358
TArrayI fIndex
Index of sorted values.
Definition: TTree.h:140
The ROOT global object gROOT contains a list of all defined classes.
Definition: TClass.h:81
virtual void SetMarkerStyle(Style_t mstyle=1)
Set the marker style.
Definition: TAttMarker.h:45
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:2811
virtual TObject * At(Int_t idx) const
Returns the object at position idx. Returns 0 if idx is out of range.
Definition: TList.cxx:311
Bool_t fIMTEnabled
! true if implicit multi-threading is enabled for this tree
Definition: TTree.h:152
Option_t * GetOption() const
Returns the object option stored in the list.
Definition: TTree.cxx:9143
virtual TBranchRef * GetBranchRef() const
Definition: TTree.h:381
Bool_t InheritsFrom(const char *cl) const
Return kTRUE if this class inherits from a class with name "classname".
Definition: TClass.cxx:4610
void SetName(const char *name)
Definition: TCollection.h:116
virtual void ResetBranchAddress(TBranch *)
Tell all of our branches to set their addresses to zero.
Definition: TTree.cxx:7506
Bool_t fDirection
iteration direction
Definition: TTree.h:591
TEventList * fEventList
! Pointer to event selection list (if one)
Definition: TTree.h:137
TString fName
Definition: TNamed.h:36
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:2215
virtual const char * GetTreeName() const
virtual Bool_t GetBranchStatus(const char *branchname) const
Return status of branch with name branchname.
Definition: TTree.cxx:4965
if object destructor must call RecursiveRemove()
Definition: TObject.h:57
virtual void SetMarkerSize(Size_t msize=1)
Set the marker size.
Definition: TAttMarker.h:46
Long64_t fMaxEntries
Maximum number of entries in case of circular buffers.
Definition: TTree.h:113
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:1100
virtual void KeepCircular(Long64_t maxEntries)
keep a maximum of fMaxEntries in memory
Definition: TBranch.cxx:1684
Each class (see TClass) has a linked list of its base class(es).
Definition: TBaseClass.h:35
char GetNewlineValue(std::istream &inputStream)
Determine which newline this file is using.
Definition: TTree.cxx:7055
virtual TObjLink * FirstLink() const
Definition: TList.h:101
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:1160
#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:1023
void InitializeBranchLists(bool checkLeafCount)
Divides the top-level branches into two vectors: (i) branches to be processed sequentially and (ii) b...
Definition: TTree.cxx:5351
Long64_t fAutoSave
Autosave tree when fAutoSave entries written or -fAutoSave (compressed) bytes produced.
Definition: TTree.h:116
virtual void SaveSelf(Bool_t=kFALSE)
Definition: TDirectory.h:189
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:2108
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:2740
virtual Color_t GetLineColor() const
Return the line color.
Definition: TAttLine.h:39
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:8288
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:6922
Data member is a pointer to an array of basic types.
Definition: TLeaf.h:59
static unsigned int total
static const Ssiz_t kNPOS
Definition: TString.h:258
TString & Remove(Ssiz_t pos)
Definition: TString.h:616
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:4307
virtual Int_t Fill()
Fill the branch basket with the referenced objects parent numbers.
Definition: TBranchRef.cxx:103
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:8503
virtual void SetWeight(Double_t w=1, Option_t *option="")
Set tree weight.
Definition: TTree.cxx:8650
Color_t GetHistFillColor() const
Definition: TStyle.h:233
Version_t GetClassVersion() const
Definition: TClass.h:382
TObjArray * Tokenize(const TString &delim) const
This function is used to isolate sequential tokens in a TString.
Definition: TString.cxx:2241
Long64_t Next()
Move on to the next cluster and return the starting entry of this next cluster.
Definition: TTree.cxx:599
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:8326
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:6102
virtual void SetEstimate(Long64_t n)=0
TObject * UncheckedAt(Int_t i) const
Definition: TObjArray.h:91
virtual void Print(Option_t *option="") const
Print cache statistics.
Long64_t fMaxVirtualSize
Maximum total size of buffers kept in memory.
Definition: TTree.h:115
virtual TObject * Remove(TObject *)
Remove an object from the in-memory list.
virtual Int_t GetMaximum() const
Definition: TLeaf.h:76
#define ClassImp(name)
Definition: Rtypes.h:279
double f(double x)
Bool_t IsZombie() const
Definition: TObject.h:120
virtual void StartViewer(Int_t ww, Int_t wh)=0
virtual void SetEntryList(TEntryList *list, Option_t *opt="")
Set an EntryList.
Definition: TTree.cxx:8403
TIterator & operator=(const TIterator &rhs)
Overridden assignment operator. Does NOT copy the &#39;cursor&#39; location!
Definition: TTree.cxx:9081
virtual void ResetAddress()
Reset the address of the branch.
Definition: TBranch.cxx:2030
virtual TKey * GetKey(const char *, Short_t=9999) const
Definition: TDirectory.h:156
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:865
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:4992
void SetHistLineStyle(Style_t styl=0)
Definition: TStyle.h:372
Long64_t fTotBytes
Total number of bytes in all branches before compression.
Definition: TTree.h:102
virtual void WaitFinishPrefetch()
Color_t GetHistLineColor() const
Definition: TStyle.h:234
std::vector< TBranch * > fSeqBranches
! Branches to be processed sequentially when IMT is on
Definition: TTree.h:155
Describe directory structure in memory.
Definition: TDirectory.h:44
virtual void SetPerfStats(TVirtualPerfStats *perf)
Set perf stats.
Definition: TTree.cxx:8605
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:154
TDirectory * GetDirectory() const
Definition: TTree.h:392
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:8784
void SortBranchesByTime()
Sorts top-level branches by the last average task time recorded per branch.
Definition: TTree.cxx:5399
R__EXTERN TEnv * gEnv
Definition: TEnv.h:174
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:7036
TList * GetListOfRealData() const
Definition: TClass.h:405
Bool_t HasDataMemberInfo() const
Definition: TClass.h:371
TNamed()
Definition: TNamed.h:40
Long64_t fAutoFlush
Auto-flush tree when fAutoFlush entries written or -fAutoFlush (compressed) bytes produced...
Definition: TTree.h:117
Int_t GetNbytes() const
Definition: TKey.h:88
virtual void ResetBranchAddresses()
Tell all of our branches to drop their current objects and allocate new ones.
Definition: TTree.cxx:7516
virtual void Draw(Option_t *opt)
Default Draw method for all objects.
Definition: TTree.h:367
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:37
EDataType
Definition: TDataType.h:30
virtual Color_t GetFillColor() const
Return the fill area color.
Definition: TAttFill.h:35
Int_t fDefaultEntryOffsetLen
Initial Length of fEntryOffset table in the basket buffers.
Definition: TTree.h:110
Bool_t Contains(const char *pat, ECaseCompare cmp=kExact) const
Definition: TString.h:567
void Browse(TBrowser *b)
Browse this collection (called by TBrowser).
TObjArray * GetListOfLeaves()
Definition: TBranch.h:179
Long64_t fEstimate
Number of entries to estimate histogram limits.
Definition: TTree.h:118
Int_t BufferSize() const
Definition: TBuffer.h:94
static void SetUnzipRelBufferSize(Float_t relbufferSize)
static function: Sets the unzip relatibe buffer size
UInt_t fMethodBit
Definition: TTree.h:191
Helper class to prevent infinite recursion in the usage of TTree Friends.
Definition: TTree.h:187
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:2893
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:8048
Int_t fDebug
! Debug level
Definition: TTree.h:127
EOnIndexError
Definition: TTree.cxx:3263
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:8074
double Stat_t
Definition: RtypesCore.h:73
virtual void SetLineStyle(Style_t lstyle)
Set the line style.
Definition: TAttLine.h:48
virtual Long64_t GetEntries() const
Definition: TTree.h:393
Int_t GetKeylen() const
Definition: TKey.h:86
Bool_t IsPersistent() const
Definition: TDataMember.h:89
Bool_t IsNull() const
Definition: TString.h:387
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:7733
virtual TFile * GetFile()
Return pointer to TFile containing this friend TTree.
virtual TBranch * BranchRef()
Build the optional branch supporting the TRefTable.
Definition: TTree.cxx:2139
virtual void ResetAfterMerge(TFileMergeInfo *)
Resets the state of this TTree after a merge (keep the customization but forget the data)...
Definition: TTree.cxx:7475
virtual Bool_t SetAlias(const char *aliasName, const char *aliasFormula)
Set a tree variable alias.
Definition: TTree.cxx:7577
Int_t fFileNumber
! current file number (if file extensions)
Definition: TTree.h:131
Mother of all ROOT objects.
Definition: TObject.h:37
TObjArray * GetElements() const
Int_t fUpdate
Update frequency for EntryLoop.
Definition: TTree.h:109
virtual void ReadValue(std::istream &, Char_t=' ')
Definition: TLeaf.h:95
Bool_t IsReading() const
Definition: TStyle.h:290
virtual Long64_t GetEND() const
Definition: TFile.h:200
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:178
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:1652
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:2200
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:460
virtual void SetFile(TFile *file=0)
Set file where this branch writes/reads its buffers.
Definition: TBranch.cxx:2242
Long64_t fEntries
Number of entries.
Definition: TTree.h:101
Bool_t IsTObject() const
Return kTRUE is the class inherits from TObject.
Definition: TClass.cxx:5583
TList * fClones
! List of cloned trees which share our addresses
Definition: TTree.h:146
virtual void Refresh(TBranch *b)
Refresh this branch using new information in b This function is called by TTree::Refresh.
Definition: TBranch.cxx:1887
Long64_t GetEntries() const
Definition: TBranch.h:183
Style_t GetHistLineStyle() const
Definition: TStyle.h:236
virtual Int_t MakeSelector(const char *selector=0, Option_t *option="")
Generate skeleton selector class for this tree.
Definition: TTree.cxx:6367
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:918
virtual Long64_t GetTotBytes() const
Definition: TTree.h:443
Class implementing or helping the various TTree cloning method.
Definition: TTreeCloner.h:40
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:31
virtual void Add(TObject *obj)
Definition: TList.h:81
const Ssiz_t kNPOS
Definition: Rtypes.h:115
Bool_t IsImplicitMTEnabled()
Returns true if the implicit multi-threading in ROOT is enabled.
Definition: TROOT.cxx:545
TClusterIterator(TTree *tree, Long64_t firstEntry)
Regular constructor.
Definition: TTree.cxx:525
virtual void RecursiveRemove(TObject *obj)
Remove object from this collection and recursively remove the object from all other objects (and coll...
Definition: TList.cxx:635
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:202
virtual void Reset(Option_t *option="")
Reset a Branch.
Definition: TBranch.cxx:1936
A TFriendElement TF describes a TTree object TF in a file.
virtual Long64_t GetZipBytes() const
Definition: TTree.h:471
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:2223
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:7348
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:1710
#define NULL
Definition: Rtypes.h:82
#define snprintf
Definition: civetweb.c:822
TTree * GetTree() const
Definition: TBranch.h:184
#define gPad
Definition: TVirtualPad.h:289
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:8252
R__EXTERN Int_t gDebug
Definition: Rtypes.h:128
Int_t GetBufferSize() const
Definition: TBasket.h:75
virtual void Reset(Option_t *option="")
Reset baskets, buffers and entries count in all branches and leaves.
Definition: TTree.cxx:7444
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:124
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:147
TObject * fNotify
! Object to be notified when loading a Tree
Definition: TTree.h:132
virtual Int_t SetCacheEntryRange(Long64_t first, Long64_t last)
interface to TTreeCache to set the cache entry range
Definition: TTree.cxx:8191
void Add(TObject *obj)
Definition: TObjArray.h:75
Double_t Atof() const
Return floating-point value contained in string.
Definition: TString.cxx:2031
A TTree object has a header with a name and a title.
Definition: TTree.h:98
#define gDirectory
Definition: TDirectory.h:221
TVirtualIndex * fTreeIndex
Pointer to the tree Index (if any)
Definition: TTree.h:141
TFriendLock & operator=(const TFriendLock &)
Assignment operator.
Definition: TTree.cxx:495
Int_t SetBranchAddressImp(TBranch *branch, void *addr, TBranch **ptr)
Change branch address, dealing with clone trees properly.
Definition: TTree.cxx:7817
virtual TVirtualIndex * BuildIndex(const TTree *T, const char *majorname, const char *minorname)=0
void ResetBit(UInt_t f)
Definition: TObject.h:156
virtual void SetDefaultEntryOffsetLen(Int_t newdefault, Bool_t updateExisting=kFALSE)
Update the default value for the branch&#39;s fEntryOffsetLen.
Definition: TTree.cxx:8300
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:1852
TObject * Next()
Go the next friend element.
Definition: TTree.cxx:9104
Definition: first.py:1
virtual Color_t GetMarkerColor() const
Return the marker color.
Definition: TAttMarker.h:36
virtual void DropBaskets()
Remove some baskets from memory.
Definition: TTree.cxx:4294
Int_t FlushBaskets()
Flush to disk all the baskets of this branch and any of subbranches.
Definition: TBranch.cxx:1008
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:5639
static Long64_t fgMaxTreeSize
Maximum size of a file containing a Tree.
Definition: TTree.h:158
virtual Style_t GetFillStyle() const
Return the fill area style.
Definition: TAttFill.h:36
virtual void Fatal(const char *method, const char *msgfmt,...) const
Issue fatal error message.
Definition: TObject.cxx:953
virtual void WriteHeader()
Write File Header.
Definition: TFile.cxx:2447
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:1400
virtual Long64_t SetEntries(Long64_t n=-1)
Change number of entries in the tree.
Definition: TTree.cxx:8371
R__EXTERN TInterpreter * gCling
Definition: TInterpreter.h:519
TBranch * GetBranch() const
Definition: TLeaf.h:70
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:2627
virtual const char * GetName() const
Returns name of object.
Definition: TObject.cxx:416
static TTree * MergeTrees(TList *list, Option_t *option="")
Static function merging the trees in the TList into a new tree.
Definition: TTree.cxx:6396
virtual Int_t GetSize() const
Definition: TCollection.h:95
A TTree is a list of TBranches.
Definition: TBranch.h:58
virtual const char * GetName() const
Returns name of object.
Definition: TRealData.h:56
A TSelector object is used by the TTree::Draw, TTree::Scan, TTree::Process to navigate in a TTree and...
Definition: TSelector.h:39
const Bool_t kTRUE
Definition: Rtypes.h:91
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:370
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:1739
A List of entry numbers in a TTree or TChain.
Definition: TEntryList.h:27
virtual Int_t AddBranchToCache(const char *bname, Bool_t subbranches=kFALSE)
Add branch with name bname to the Tree cache.
Definition: TTree.cxx:940
Int_t fPacketSize
! Number of entries in one packet for parallel root
Definition: TTree.h:125
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:122
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:6970
Line Attributes class.
Definition: TAttLine.h:24
virtual Long64_t GetEntryNumberWithIndex(Long64_t major, Long64_t minor) const =0
Int_t GetCompressionLevel() const
Definition: TFile.h:366
Bool_t IsObject() const
Definition: TRealData.h:60
Long64_t BinarySearch(Long64_t n, const T *array, T value)
Definition: TMath.h:931
TBranch * GetMother() const
Get our top-level parent branch in the tree.
Definition: TBranch.cxx:1551
char name[80]
Definition: TGX11.cxx:109
TFriendLock(const TFriendLock &)
Copy constructor.
Definition: TTree.cxx:485
virtual void Warning(const char *method, const char *msgfmt,...) const
Issue warning message.
Definition: TObject.cxx:911
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:5086
virtual void SetName(const char *name)
Change the name of this tree.
Definition: TTree.cxx:8531
Int_t GetCompressionSettings() const
Definition: TFile.h:372
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:568
virtual const char * GetTitle() const
Returns title of object.
Definition: TNamed.h:52
virtual void PrintCacheStats(Option_t *option="") const
print statistics about the TreeCache for this tree, like ******TreeCache statistics for file: cms2...
Definition: TTree.cxx:6844
void MoveReadCache(TFile *src, TDirectory *dir)
Move a cache from a file to the current file in dir.
Definition: TTree.cxx:6529
virtual void CopyAddresses(TTree *, Bool_t undo=kFALSE)
Set branch addresses of passed tree equal to ours.
Definition: TTree.cxx:3159
virtual TObjArray * GetListOfLeaves()
Definition: TTree.h:418
static void ResetCount()
Static function resetting fgCount.
Definition: TBranch.cxx:2053
Long64_t fSavedBytes
Number of autosaved bytes.
Definition: TTree.h:104
Long64_t fCacheSize
! Maximum size of file buffers
Definition: TTree.h:121
virtual const char * GetFriendAlias(TTree *) const
If the &#39;tree&#39; is a friend, this method returns its alias name.
Definition: TTree.cxx:5596
void * New(ENewType defConstructor=kClassNew, Bool_t quiet=kFALSE) const
Return a pointer to a newly allocated object of this class.
Definition: TClass.cxx:4714
Int_t GetNleaves() const
Definition: TBranch.h:181
virtual Long64_t AutoSave(Option_t *option="")
AutoSave tree header every fAutoSave bytes.
Definition: TTree.cxx:1337
const char * Data() const
Definition: TString.h:349